package ajax import ( "encoding/json" "errors" "fmt" "local/todo-server/server/ajax/form" "local/todo-server/server/ajax/task" "net/http" "sort" "strconv" "strings" ) type taskWithDelta struct { task *task.Task delta int } func (a *Ajax) loadTasks(w http.ResponseWriter, r *http.Request) error { listID, _, _ := a.Cur(r) filterComplete := filterComplete(form.Get(r, "compl")) filterLooping := filterLooping(form.Get(r, "looping")) filterTags := filterTags(form.ToStrArr(form.Get(r, "t"))) filterSubstr := filterSubstr(form.Get(r, "s")) tasks, err := a.storageListTasks(listID, filterComplete, filterTags, filterSubstr, filterLooping) if err != nil { return err } return json.NewEncoder(w).Encode(map[string]interface{}{"list": tasks}) } func filterLooping(looping string) func(t *task.Task) bool { return func(t *task.Task) bool { hasLoop := t.Loop > 0 || t.Cron != "" onlyLooping := looping == "1" return !onlyLooping || hasLoop } } func filterComplete(compl string) func(t *task.Task) bool { return func(t *task.Task) bool { return compl == "" || !t.Complete || (compl == "1" && t.Complete) } } func filterTags(tags []string) func(t *task.Task) bool { return func(t *task.Task) bool { for _, whitelisted := range tags { found := false for _, tag := range t.Tags { if whitelisted == tag { found = true } } if !found { return false } } return true } } func filterSubstr(substr string) func(t *task.Task) bool { return func(t *task.Task) bool { found := substr == "" || strings.Contains(strings.ToLower(fmt.Sprintf("%+v %+v", t.Title, t.Tags)), strings.ToLower(substr)) return found } } func (a *Ajax) newTask(w http.ResponseWriter, r *http.Request) error { listID, newTask, err := a.makeTask(r) if err != nil { return err } if err := a.storageSetTask(listID, newTask); err != nil { return err } return json.NewEncoder(w).Encode(map[string]interface{}{ "total": 1, "list": []*task.Task{newTask}, }) } func (a *Ajax) makeTask(r *http.Request) (string, *task.Task, error) { listID, _, tags := a.Cur(r) task, err := task.New(r) if err != nil { return "", nil, err } list, err := a.storageGetList(listID) if err != nil { return "", nil, err } task.Index = list.NextIndex() if err := a.storageSetList(list); err != nil { return "", nil, err } task.AppendTags(tags) return listID, task, nil } func (a *Ajax) deleteTask(w http.ResponseWriter, r *http.Request) error { _, taskID, _ := a.Cur(r) if err := a.storageDelTask(taskID); err != nil { return err } return json.NewEncoder(w).Encode(map[string]interface{}{"total": 0}) } func (a *Ajax) completeTask(w http.ResponseWriter, r *http.Request) error { listID, taskID, _ := a.Cur(r) completedTask, err := a.storageGetTask(taskID) if err != nil { return err } if err := a.storageDelTask(completedTask.UUID); err != nil { return err } completedTask.SetComplete(form.Get(r, "compl") == "1") if err := a.storageSetTask(listID, completedTask); err != nil { return err } return json.NewEncoder(w).Encode(map[string]interface{}{ "total": 1, "list": []*task.Task{completedTask}, }) } func (a *Ajax) editNote(w http.ResponseWriter, r *http.Request) error { listID, taskID, _ := a.Cur(r) editedTask, err := a.storageGetTask(taskID) if err != nil { return err } editedTask.SetNote(form.Get(r, "note")) if err := a.storageSetTask(listID, editedTask); err != nil { return err } return json.NewEncoder(w).Encode(map[string]interface{}{"total": 1, "list": []*task.Task{editedTask}}) } func (a *Ajax) editTask(w http.ResponseWriter, r *http.Request) error { listID, editedTask, err := a.makeTask(r) if err != nil { return err } _, taskID, _ := a.Cur(r) editedTask.UUID = taskID if err := a.storageSetTask(listID, editedTask); err != nil { return err } return json.NewEncoder(w).Encode(map[string]interface{}{"total": 1, "list": []*task.Task{editedTask}}) } func (a *Ajax) setPrio(w http.ResponseWriter, r *http.Request) error { listID, taskID, _ := a.Cur(r) editedTask, err := a.storageGetTask(taskID) if err != nil { return err } editedTask.SetPrio(form.ToInt(form.Get(r, "prio"))) if err := a.storageSetTask(listID, editedTask); err != nil { return err } return json.NewEncoder(w).Encode(map[string]interface{}{"total": 1, "list": []*task.Task{editedTask}}) } func (a *Ajax) moveTask(w http.ResponseWriter, r *http.Request) error { _, taskID, _ := a.Cur(r) toList := form.Get(r, "to") list, err := a.storageGetList(toList) if err != nil { return err } movedTask, err := a.storageGetTask(taskID) if err != nil { return err } if err := a.storageDelTask(taskID); err != nil { return err } movedTask.Index = list.NextIndex() if err := a.storageSetTask(toList, movedTask); err != nil { return err } if err := a.storageSetList(list); err != nil { return err } return json.NewEncoder(w).Encode(map[string]interface{}{"total": 1, "list": []*task.Task{movedTask}}) } func (a *Ajax) parseTaskStr(w http.ResponseWriter, r *http.Request) error { return errors.New("not impl") } func (a *Ajax) changeOrder(w http.ResponseWriter, r *http.Request) error { order := form.Get(r, "order") orders := strings.Split(order, "&") modified := make([]taskWithDelta, 0) indices := make([]int, 0) for _, order := range orders { taskIDDelta := strings.Split(order, "=") if len(taskIDDelta) < 2 { continue } taskID := taskIDDelta[0] delta, _ := strconv.Atoi(taskIDDelta[1]) task, err := a.storageGetTask(taskID) if err != nil { return err } modified = append(modified, taskWithDelta{task: task, delta: delta}) indices = append(indices, task.Index) } sort.Slice(modified, func(i, j int) bool { if modified[i].delta < modified[j].delta { return true } else if modified[i].delta > modified[j].delta { return false } return modified[i].task.Index < modified[j].task.Index }) sort.Ints(indices) for i := 0; i < len(modified); i++ { task := *modified[i].task task.Index = indices[i] listID, err := a.taskIDToListID(task.UUID) if err != nil { return err } if err := a.storageSetTask(listID, &task); err != nil { return err } } fmt.Fprintf(w, `{"total":1}`) return nil }