package ajax import ( "bytes" "encoding/gob" "local/storage" "local/todo-server/server/ajax/form" "local/todo-server/server/ajax/list" "local/todo-server/server/ajax/task" "net/http" "path" "sort" "strings" ) func (a *Ajax) Cur(r *http.Request) (string, string, []string) { listID := form.Get(r, "list") taskID := form.Get(r, "id") if listID == "" { listID, _ = a.taskIDToListID(taskID) } tags, _ := r.URL.Query()["t"] return listID, taskID, tags } func (a *Ajax) taskIDToListID(taskID string) (string, error) { var listID string err := a.storageGet(path.Join("task", taskID, "map"), &listID) return listID, err } func (a *Ajax) storageListLists(filters ...func(t *list.List) bool) ([]*list.List, error) { results, err := a.DB.List(nil, path.Join("list"), path.Join("list", "}")) if err != nil { return nil, err } lists := []*list.List{} for _, result := range results { if d := path.Dir(result); d != "list" { continue } list, err := a.storageGetList(path.Base(result)) if err != nil { return nil, err } filtered := true for _, f := range filters { if !f(list) { filtered = false break } } if filtered { lists = append(lists, list) } } return lists, nil } func (a *Ajax) storageListTasks(listID string, filters ...func(t *task.Task) bool) ([]*task.Task, error) { results, err := a.DB.List(nil, path.Join("list", listID, "incomplete", "task"), path.Join("list", listID, "incomplete", "task", "}")) if err != nil { return nil, err } includeComplete := true for _, f := range filters { t := &task.Task{Complete: true} if !f(t) { includeComplete = false } } if includeComplete { completeResults, err := a.DB.List(nil, path.Join("list", listID, "complete", "task"), path.Join("list", listID, "complete", "task", "}")) if err != nil { return nil, err } results = append(results, completeResults...) } tasks := []*task.Task{} for _, result := range results { taskID := path.Base(result) if taskID == "" { continue } task, err := a.storageGetTask(taskID) if err != nil { return nil, err } filtered := true for _, f := range filters { if !f(task) { filtered = false break } } if filtered { //task.Title = fmt.Sprintf("[%d] %s", task.Index, task.Title) tasks = append(tasks, task) } } sort.SliceStable(tasks, func(i, j int) bool { if tasks[i].Complete != tasks[j].Complete { return tasks[j].Complete } if tasks[i].Index == tasks[j].Index { return tasks[i].Created.Before(tasks[j].Created) } return tasks[i].Index < tasks[j].Index }) return tasks, nil } func (a *Ajax) storageGetTask(taskID string) (*task.Task, error) { var listID string if err := a.storageGet(path.Join("task", taskID, "map"), &listID); err != nil { return nil, err } var task task.Task err := a.storageGet(path.Join("list", listID, "incomplete", "task", taskID), &task) if err == storage.ErrNotFound { err = a.storageGet(path.Join("list", listID, "complete", "task", taskID), &task) } return &task, err } func (a *Ajax) storageSetTask(listID string, newTask *task.Task) error { if newTask == nil { newTask = &task.Task{ UUID: "nil", } } if err := a.storageSet(path.Join("task", newTask.UUID, "map"), listID); err != nil { return err } scope := "incomplete" if newTask.Complete { scope = "complete" } return a.storageSet(path.Join("list", listID, scope, "task", newTask.UUID), *newTask) } func (a *Ajax) storageDelTask(taskID string) error { var listID string if err := a.storageGet(path.Join("task", taskID, "map"), &listID); err != nil { return err } if err := a.storageDel(path.Join("task", taskID, "map")); err != nil { return err } err := a.storageDel(path.Join("list", listID, "incomplete", "task", taskID)) if err == nil { err = a.storageDel(path.Join("list", listID, "complete", "task", taskID)) } return err } func (a *Ajax) storageGetList(listID string) (*list.List, error) { listID = strings.TrimSuffix(listID, "/") + "/" var list list.List err := a.storageGet(path.Join("list", listID), &list) return &list, err } func (a *Ajax) storageSetList(list *list.List) error { return a.storageSet(path.Join("list", list.UUID), *list) } func (a *Ajax) storageDelList(listID string) error { listID = strings.TrimSuffix(listID, "/") + "/" return a.storageDel(path.Join("list", listID)) } func (a *Ajax) storageSet(key string, value interface{}) error { buff := bytes.NewBuffer(nil) encoder := gob.NewEncoder(buff) if err := encoder.Encode(value); err != nil { return err } return a.DB.Set(key, buff.Bytes()) } func (a *Ajax) storageGet(key string, value interface{}) error { b, err := a.DB.Get(key) if err != nil { return err } buff := bytes.NewBuffer(b) decoder := gob.NewDecoder(buff) return decoder.Decode(value) } func (a *Ajax) storageDel(key string) error { return a.DB.Set(key, nil) }