package ajax import ( "local/storage" "local/todo-server/config" "local/todo-server/server/ajax/task" "log" "net/http" "net/url" "time" ) type Ajax struct { DB storage.DB ListCnt int } func New() (*Ajax, error) { db, err := storage.New(storage.TypeFromString(config.StoreType), config.StoreAddr, config.StoreUser, config.StorePass) return &Ajax{ DB: db, }, err } func (a *Ajax) HandleAjax(w http.ResponseWriter, r *http.Request) { params := r.URL.Query() var foo func(http.ResponseWriter, *http.Request) error if has(params, "loadLists") { foo = a.loadLists } else if has(params, "loadTasks") { foo = a.loadTasks } else if has(params, "newTask") { foo = a.newTask } else if has(params, "fullNewTask") { foo = a.newTask } else if has(params, "deleteTask") { foo = a.deleteTask } else if has(params, "completeTask") { foo = a.completeTask } else if has(params, "editNote") { foo = a.editNote } else if has(params, "editTask") { foo = a.editTask } else if has(params, "changeOrder") { foo = a.changeOrder } else if has(params, "suggestTags") { foo = a.suggestTags } else if has(params, "setPrio") { foo = a.setPrio } else if has(params, "tagCloud") { foo = a.tagCloud } else if has(params, "addList") { foo = a.addList } else if has(params, "renameList") { foo = a.renameList } else if has(params, "deleteList") { foo = a.deleteList } else if has(params, "setSort") { foo = a.setSort } else if has(params, "publishList") { foo = a.publishList } else if has(params, "moveTask") { foo = a.moveTask } else if has(params, "changeListOrder") { foo = a.changeListOrder } else if has(params, "parseTaskStr") { foo = a.parseTaskStr } else if has(params, "clearCompletedInList") { foo = a.clearCompletedInList } else if has(params, "setShowNotesInList") { foo = a.setShowNotesInList } else if has(params, "setHideList") { foo = a.setHideList } if foo == nil { http.NotFound(w, r) } else if err := foo(w, r); err == storage.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) } else if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) } } func has(params url.Values, k string) bool { _, ok := params[k] return ok } func (a *Ajax) Async() { var err error nextDue := time.Now().Add(config.Loop) c := time.NewTicker(config.Loop) c2 := time.NewTicker(config.Loop) for { c.Stop() c.Reset(config.Loop) c2.Stop() c2.Reset(time.Until(nextDue)) log.Println("next loop at", time.Until(nextDue), "or", config.Loop) select { case <-c.C: case <-c2.C: } nextDue, err = a.loopTasks() if err != nil { log.Println("failed to loop tasks", err) } } } func (a *Ajax) loopTasks() (time.Time, error) { nextDue := time.Now().Add(time.Hour * 240) lists, err := a.storageListLists() if err != nil { return nextDue, err } for _, list := range lists { tasks, err := a.storageListTasks(list.UUID, func(t *task.Task) bool { return t.Complete }) if err != nil { return nextDue, err } for _, task := range tasks { if !task.Complete { continue } if task.Loop == 0 && task.Cron == "" { continue } nextLoopTrigger := task.Completed.Add(task.Loop) if task.Loop == 0 { nextLoopTrigger2 := task.Cron.Next(task.Completed) if nextLoopTrigger2.Before(nextLoopTrigger) { nextLoopTrigger = nextLoopTrigger2 } } if time.Now().Before(nextLoopTrigger) { if nextLoopTrigger.Before(nextDue) { nextDue = nextLoopTrigger } continue } task.Complete = false task.Completed = time.Time{} if err := a.storageSetTask(list.UUID, task); err != nil { return nextDue, err } } } return nextDue, nil }