project and cleanup of old tasks
This commit is contained in:
parent
fef1d4a799
commit
6701b64863
|
@ -36,4 +36,7 @@ func main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if err := taskRepo.CleanUp(); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,3 +59,51 @@ func (tr *TaskRepo) Update(t *Task) error {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cleanup removes older versions of tasks
|
||||||
|
func (tr *TaskRepo) CleanUp() error {
|
||||||
|
// loop through folders, get all tasks
|
||||||
|
taskSet := make(map[string][]*Task)
|
||||||
|
|
||||||
|
for _, folder := range knownFolders {
|
||||||
|
tasks, err := tr.FindAll(folder)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, t := range tasks {
|
||||||
|
if _, ok := taskSet[t.Id]; !ok {
|
||||||
|
taskSet[t.Id] = []*Task{}
|
||||||
|
}
|
||||||
|
taskSet[t.Id] = append(taskSet[t.Id], t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// determine which ones need to be gone
|
||||||
|
var tobeRemoved []*Task
|
||||||
|
for _, tasks := range taskSet {
|
||||||
|
maxUid := uint32(0)
|
||||||
|
for _, t := range tasks {
|
||||||
|
if t.Message.Uid > maxUid {
|
||||||
|
maxUid = t.Message.Uid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, t := range tasks {
|
||||||
|
if t.Message.Uid < maxUid {
|
||||||
|
tobeRemoved = append(tobeRemoved, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//fmt.Printf("removing: %+v\n", tobeRemoved)
|
||||||
|
|
||||||
|
// remove them
|
||||||
|
for _, t := range tobeRemoved {
|
||||||
|
if err := tr.mstore.Remove(t.Message); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -19,9 +19,18 @@ const (
|
||||||
|
|
||||||
QUOTE_PREFIX = ">"
|
QUOTE_PREFIX = ">"
|
||||||
PREVIOUS_SEPARATOR = "Previous version:"
|
PREVIOUS_SEPARATOR = "Previous version:"
|
||||||
FIELD_SEPARATOR = ":"
|
|
||||||
FIELD_ID = "id"
|
FIELD_SEPARATOR = ":"
|
||||||
FIELD_ACTION = "action"
|
SUBJECT_SEPARATOR = " - "
|
||||||
|
|
||||||
|
FIELD_ID = "id"
|
||||||
|
FIELD_ACTION = "action"
|
||||||
|
FIELD_PROJECT = "project"
|
||||||
|
FIELD_DUE = "date"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
knownFolders = []string{FOLDER_INBOX, FOLDER_NEW}
|
||||||
)
|
)
|
||||||
|
|
||||||
// Task reperesents a task based on the data stored in a message
|
// Task reperesents a task based on the data stored in a message
|
||||||
|
@ -33,8 +42,11 @@ type Task struct {
|
||||||
// Folder is the same name as the mstore folder
|
// Folder is the same name as the mstore folder
|
||||||
Folder string
|
Folder string
|
||||||
|
|
||||||
|
// Ordinary task attributes
|
||||||
Action string
|
Action string
|
||||||
|
Project string
|
||||||
Due Date
|
Due Date
|
||||||
|
|
||||||
Message *mstore.Message
|
Message *mstore.Message
|
||||||
|
|
||||||
// Current indicates whether the task represents an existing message in the mstore
|
// Current indicates whether the task represents an existing message in the mstore
|
||||||
|
@ -51,6 +63,7 @@ type Task struct {
|
||||||
// Keys that exist more than once are merged. The one that appears first in the body takes precedence. A value present in the Body takes precedence over one in the subject.
|
// Keys that exist more than once are merged. The one that appears first in the body takes precedence. A value present in the Body takes precedence over one in the subject.
|
||||||
// This enables updating a task by forwarding a topposted message whith new values for fields that the user wants to update.
|
// This enables updating a task by forwarding a topposted message whith new values for fields that the user wants to update.
|
||||||
func New(msg *mstore.Message) *Task {
|
func New(msg *mstore.Message) *Task {
|
||||||
|
// Id
|
||||||
dirty := false
|
dirty := false
|
||||||
id, d := FieldFromBody(FIELD_ID, msg.Body)
|
id, d := FieldFromBody(FIELD_ID, msg.Body)
|
||||||
if id == "" {
|
if id == "" {
|
||||||
|
@ -61,6 +74,7 @@ func New(msg *mstore.Message) *Task {
|
||||||
dirty = true
|
dirty = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Action
|
||||||
action, d := FieldFromBody(FIELD_ACTION, msg.Body)
|
action, d := FieldFromBody(FIELD_ACTION, msg.Body)
|
||||||
if action == "" {
|
if action == "" {
|
||||||
action = FieldFromSubject(FIELD_ACTION, msg.Subject)
|
action = FieldFromSubject(FIELD_ACTION, msg.Subject)
|
||||||
|
@ -72,16 +86,24 @@ func New(msg *mstore.Message) *Task {
|
||||||
dirty = true
|
dirty = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Folder
|
||||||
folder := msg.Folder
|
folder := msg.Folder
|
||||||
if folder == FOLDER_INBOX {
|
if folder == FOLDER_INBOX {
|
||||||
folder = FOLDER_NEW
|
folder = FOLDER_NEW
|
||||||
dirty = true
|
dirty = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Project
|
||||||
|
project, d := FieldFromBody(FIELD_PROJECT, msg.Body)
|
||||||
|
if d {
|
||||||
|
dirty = true
|
||||||
|
}
|
||||||
|
|
||||||
return &Task{
|
return &Task{
|
||||||
Id: id,
|
Id: id,
|
||||||
Action: action,
|
|
||||||
Folder: folder,
|
Folder: folder,
|
||||||
|
Action: action,
|
||||||
|
Project: project,
|
||||||
Message: msg,
|
Message: msg,
|
||||||
Current: true,
|
Current: true,
|
||||||
Dirty: dirty,
|
Dirty: dirty,
|
||||||
|
@ -89,15 +111,29 @@ func New(msg *mstore.Message) *Task {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Task) FormatSubject() string {
|
func (t *Task) FormatSubject() string {
|
||||||
return t.Action
|
order := []string{FIELD_PROJECT, FIELD_ACTION}
|
||||||
|
fields := map[string]string{
|
||||||
|
FIELD_PROJECT: t.Project,
|
||||||
|
FIELD_ACTION: t.Action,
|
||||||
|
}
|
||||||
|
|
||||||
|
parts := []string{}
|
||||||
|
for _, f := range order {
|
||||||
|
if fields[f] != "" {
|
||||||
|
parts = append(parts, fields[f])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.Join(parts, SUBJECT_SEPARATOR)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Task) FormatBody() string {
|
func (t *Task) FormatBody() string {
|
||||||
body := fmt.Sprintf("\n")
|
body := fmt.Sprintf("\n")
|
||||||
order := []string{FIELD_ID, FIELD_ACTION}
|
order := []string{FIELD_ID, FIELD_PROJECT, FIELD_ACTION}
|
||||||
fields := map[string]string{
|
fields := map[string]string{
|
||||||
FIELD_ID: t.Id,
|
FIELD_ID: t.Id,
|
||||||
FIELD_ACTION: t.Action,
|
FIELD_PROJECT: t.Project,
|
||||||
|
FIELD_ACTION: t.Action,
|
||||||
}
|
}
|
||||||
|
|
||||||
keyLen := 0
|
keyLen := 0
|
||||||
|
|
|
@ -12,7 +12,9 @@ import (
|
||||||
func TestNewFromMessage(t *testing.T) {
|
func TestNewFromMessage(t *testing.T) {
|
||||||
id := "an id"
|
id := "an id"
|
||||||
action := "some action"
|
action := "some action"
|
||||||
|
project := "project"
|
||||||
folder := task.FOLDER_NEW
|
folder := task.FOLDER_NEW
|
||||||
|
|
||||||
for _, tc := range []struct {
|
for _, tc := range []struct {
|
||||||
name string
|
name string
|
||||||
message *mstore.Message
|
message *mstore.Message
|
||||||
|
@ -27,19 +29,21 @@ func TestNewFromMessage(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "with id, action and folder",
|
name: "id, action, project and folder",
|
||||||
message: &mstore.Message{
|
message: &mstore.Message{
|
||||||
Folder: folder,
|
Folder: folder,
|
||||||
Body: fmt.Sprintf(`
|
Body: fmt.Sprintf(`
|
||||||
id: %s
|
id: %s
|
||||||
action: %s
|
action: %s
|
||||||
`, id, action),
|
project: %s
|
||||||
|
`, id, action, project),
|
||||||
},
|
},
|
||||||
hasId: true,
|
hasId: true,
|
||||||
exp: &task.Task{
|
exp: &task.Task{
|
||||||
Id: id,
|
Id: id,
|
||||||
Folder: folder,
|
Folder: folder,
|
||||||
Action: action,
|
Action: action,
|
||||||
|
Project: project,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -127,6 +131,8 @@ Forwarded message:
|
||||||
|
|
||||||
func TestFormatSubject(t *testing.T) {
|
func TestFormatSubject(t *testing.T) {
|
||||||
action := "an action"
|
action := "an action"
|
||||||
|
project := " a project"
|
||||||
|
|
||||||
for _, tc := range []struct {
|
for _, tc := range []struct {
|
||||||
name string
|
name string
|
||||||
task *task.Task
|
task *task.Task
|
||||||
|
@ -137,10 +143,20 @@ func TestFormatSubject(t *testing.T) {
|
||||||
task: &task.Task{},
|
task: &task.Task{},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "with action",
|
name: "action",
|
||||||
task: &task.Task{Action: action},
|
task: &task.Task{Action: action},
|
||||||
exp: action,
|
exp: action,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "project",
|
||||||
|
task: &task.Task{Project: project},
|
||||||
|
exp: project,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "action and project",
|
||||||
|
task: &task.Task{Action: action, Project: project},
|
||||||
|
exp: fmt.Sprintf("%s - %s", project, action),
|
||||||
|
},
|
||||||
} {
|
} {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
test.Equals(t, tc.exp, tc.task.FormatSubject())
|
test.Equals(t, tc.exp, tc.task.FormatSubject())
|
||||||
|
@ -151,6 +167,8 @@ func TestFormatSubject(t *testing.T) {
|
||||||
func TestFormatBody(t *testing.T) {
|
func TestFormatBody(t *testing.T) {
|
||||||
id := "an id"
|
id := "an id"
|
||||||
action := "an action"
|
action := "an action"
|
||||||
|
project := "project"
|
||||||
|
|
||||||
for _, tc := range []struct {
|
for _, tc := range []struct {
|
||||||
name string
|
name string
|
||||||
task *task.Task
|
task *task.Task
|
||||||
|
@ -161,21 +179,24 @@ func TestFormatBody(t *testing.T) {
|
||||||
task: &task.Task{},
|
task: &task.Task{},
|
||||||
exp: `
|
exp: `
|
||||||
id:
|
id:
|
||||||
|
project:
|
||||||
action:
|
action:
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "filled",
|
name: "filled",
|
||||||
task: &task.Task{
|
task: &task.Task{
|
||||||
Id: id,
|
Id: id,
|
||||||
Action: action,
|
Action: action,
|
||||||
|
Project: project,
|
||||||
Message: &mstore.Message{
|
Message: &mstore.Message{
|
||||||
Body: "previous body",
|
Body: "previous body",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
exp: `
|
exp: `
|
||||||
id: an id
|
id: an id
|
||||||
action: an action
|
project: project
|
||||||
|
action: an action
|
||||||
|
|
||||||
Previous version:
|
Previous version:
|
||||||
|
|
||||||
|
@ -233,7 +254,7 @@ field: valueb
|
||||||
expDirty: true,
|
expDirty: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "with colons",
|
name: "colons",
|
||||||
field: "field",
|
field: "field",
|
||||||
body: "field:: val:ue",
|
body: "field:: val:ue",
|
||||||
expValue: ": val:ue",
|
expValue: ": val:ue",
|
||||||
|
|
Loading…
Reference in New Issue