diff --git a/main.go b/main.go index fda0b26..041ace5 100644 --- a/main.go +++ b/main.go @@ -147,6 +147,7 @@ func main() { // {{{ service.Register("/key/create", true, true, keyCreate) service.Register("/key/counter", true, true, keyCounter) service.Register("/notification/ack", false, false, notificationAcknowledge) + service.Register("/schedule/list", true, true, scheduleList) service.Register("/", false, false, service.StaticHandler) if flagCreateUser { @@ -777,5 +778,22 @@ func notificationAcknowledge(w http.ResponseWriter, r *http.Request, sess *sessi "OK": true, }) } // }}} +func scheduleList(w http.ResponseWriter, r *http.Request, sess *session.T) { // {{{ + logger.Info("webserver", "request", "/schedule/list") + var err error + w.Header().Add("Access-Control-Allow-Origin", "*") + + var schedules []Schedule + schedules, err = FutureSchedules(sess.UserID) + if err != nil { + responseError(w, err) + return + } + + responseData(w, map[string]interface{}{ + "OK": true, + "ScheduleEvents": schedules, + }) +} // }}} // vim: foldmethod=marker diff --git a/node.go b/node.go index 38d2b0a..f453392 100644 --- a/node.go +++ b/node.go @@ -3,6 +3,7 @@ package main import ( // External "github.com/jmoiron/sqlx" + werr "git.gibonuddevalla.se/go/wrappederror" // Standard "time" @@ -324,8 +325,16 @@ func CreateNode(userID, parentID int, name string) (node Node, err error) { // { return } // }}} func UpdateNode(userID, nodeID, timeOffset int, content string, cryptoKeyID int, markdown bool) (err error) { // {{{ + var timezone string + row := service.Db.Conn.QueryRow(`SELECT timezone FROM public.user WHERE id=$1`, userID) + err = row.Scan(&timezone) + if err != nil { + err = werr.Wrap(err).WithCode("002-000F") + return + } + var scannedSchedules, dbSchedules, add, remove []Schedule - scannedSchedules = ScanForSchedules(timeOffset, content) + scannedSchedules = ScanForSchedules(timezone, content) for i := range scannedSchedules { scannedSchedules[i].Node.ID = nodeID scannedSchedules[i].UserID = userID diff --git a/notification_manager.go b/notification_manager.go index 7022af9..5d674da 100644 --- a/notification_manager.go +++ b/notification_manager.go @@ -37,7 +37,7 @@ func InitNotificationManager() (err error) {// {{{ user_id ASC, prio ASC ) - SELECT jsonb_agg(s.*) + SELECT COALESCE(jsonb_agg(s.*), '[]') FROM services s `, ) diff --git a/schedule.go b/schedule.go index 27c16db..2966917 100644 --- a/schedule.go +++ b/schedule.go @@ -28,7 +28,7 @@ type Schedule struct { Acknowledged bool } -func ScanForSchedules(timeOffset int, content string) (schedules []Schedule) { // {{{ +func ScanForSchedules(timezone string, content string) (schedules []Schedule) { // {{{ schedules = []Schedule{} rxp := regexp.MustCompile(`\{\s*([0-9]{4}-[0-9]{2}-[0-9]{2}\s+[0-9]{2}:[0-9]{2}(?::[0-9]{2})?)\s*\,\s*(?:(\d+)\s*(h|min)\s*,)?\s*([^\]]+?)\s*\}`) @@ -40,19 +40,14 @@ func ScanForSchedules(timeOffset int, content string) (schedules []Schedule) { / data[1] = data[1] + ":00" } - // Timezone calculations - var timeTZ string - if timeOffset < 0 { - hours := (-timeOffset) / 60 - mins := (-timeOffset) % 60 - timeTZ = fmt.Sprintf("%s -%02d%02d", data[1], hours, mins) - } else { - hours := timeOffset / 60 - mins := timeOffset % 60 - timeTZ = fmt.Sprintf("%s +%02d%02d", data[1], hours, mins) + logger.Info("time", "parse", data[1]) + location, err := time.LoadLocation(timezone) + if err != nil { + err = werr.Wrap(err).WithCode("002-00010") + return } - timestamp, err := time.Parse("2006-01-02 15:04:05 -0700", timeTZ) + timestamp, err := time.ParseInLocation("2006-01-02 15:04:05", data[1], location) if err != nil { continue } @@ -86,14 +81,15 @@ func RetrieveSchedules(userID int, nodeID int) (schedules []Schedule, err error) res := service.Db.Conn.QueryRow(` WITH schedule_events AS ( SELECT - id, - user_id, - json_build_object('id', node_id) AS node, - schedule_uuid, - time - MAKE_INTERVAL(mins => remind_minutes) AS time, - description, - acknowledged - FROM schedule + s.id, + s.user_id, + json_build_object('id', s.node_id) AS node, + s.schedule_uuid, + (time - MAKE_INTERVAL(mins => s.remind_minutes)) AT TIME ZONE u.timezone AS time, + s.description, + s.acknowledged + FROM schedule s + INNER JOIN public.user u ON s.user_id = u.id WHERE user_id=$1 AND CASE @@ -112,6 +108,7 @@ func RetrieveSchedules(userID int, nodeID int) (schedules []Schedule, err error) var data []byte err = res.Scan(&data) if err != nil { + err = werr.Wrap(err).WithCode("002-000E") return } @@ -133,12 +130,16 @@ func (s *Schedule) Insert(queryable Queryable) error { // {{{ `, s.UserID, s.Node.ID, - s.Time, + s.Time.Format("2006-01-02 15:04:05"), s.RemindMinutes, s.Description, ) - return res.Scan(&s.ID) + err := res.Scan(&s.ID) + if err != nil { + err = werr.Wrap(err).WithCode("002-000D") + } + return err } // }}} func (s *Schedule) Delete(queryable Queryable) error { // {{{ _, err := queryable.Exec(` @@ -158,13 +159,14 @@ func ExpiredSchedules() (schedules []Schedule) { // {{{ res, err := service.Db.Conn.Queryx(` SELECT - id, - user_id, - node_id, - schedule_uuid, - time - MAKE_INTERVAL(mins => remind_minutes) AS time, - description - FROM schedule + s.id, + s.user_id, + s.node_id, + s.schedule_uuid, + (s.time - MAKE_INTERVAL(mins => s.remind_minutes)) AT TIME ZONE u.timezone AS time, + s.description + FROM schedule s + INNER JOIN public.user u ON s.user_id = u.id WHERE (time - MAKE_INTERVAL(mins => remind_minutes)) < NOW() AND NOT acknowledged @@ -187,3 +189,40 @@ func ExpiredSchedules() (schedules []Schedule) { // {{{ } return } // }}} +func FutureSchedules(userID int) (schedules []Schedule, err error) {// {{{ + schedules = []Schedule{} + + res, err := service.Db.Conn.Queryx(` + SELECT + id, + user_id, + node_id, + schedule_uuid, + time, + description + FROM schedule + WHERE + user_id = $1 AND + time >= NOW() AND + NOT acknowledged + ORDER BY + time ASC + `, + userID, + ) + if err != nil { + err = werr.Wrap(err).WithCode("002-000B") + return + } + defer res.Close() + + for res.Next() { + s := Schedule{} + if err = res.Scan(&s.ID, &s.UserID, &s.Node.ID, &s.ScheduleUUID, &s.Time, &s.Description); err != nil { + err = werr.Wrap(err).WithCode("002-000C") + return + } + schedules = append(schedules, s) + } + return +}// }}} diff --git a/static/js/node.mjs b/static/js/node.mjs index 2f661ed..3608ab7 100644 --- a/static/js/node.mjs +++ b/static/js/node.mjs @@ -59,6 +59,7 @@ export class NodeUI extends Component { case 'node': if (node.ID == 0) { page = html` +