Compare commits
No commits in common. "49fd943110c8a967ef3563049d154078e3e305b4" and "eea0b1c0f605fac368a190ef216ad87956041be5" have entirely different histories.
49fd943110
...
eea0b1c0f6
18
main.go
18
main.go
@ -147,7 +147,6 @@ func main() { // {{{
|
|||||||
service.Register("/key/create", true, true, keyCreate)
|
service.Register("/key/create", true, true, keyCreate)
|
||||||
service.Register("/key/counter", true, true, keyCounter)
|
service.Register("/key/counter", true, true, keyCounter)
|
||||||
service.Register("/notification/ack", false, false, notificationAcknowledge)
|
service.Register("/notification/ack", false, false, notificationAcknowledge)
|
||||||
service.Register("/schedule/list", true, true, scheduleList)
|
|
||||||
service.Register("/", false, false, service.StaticHandler)
|
service.Register("/", false, false, service.StaticHandler)
|
||||||
|
|
||||||
if flagCreateUser {
|
if flagCreateUser {
|
||||||
@ -778,22 +777,5 @@ func notificationAcknowledge(w http.ResponseWriter, r *http.Request, sess *sessi
|
|||||||
"OK": true,
|
"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
|
// vim: foldmethod=marker
|
||||||
|
11
node.go
11
node.go
@ -3,7 +3,6 @@ package main
|
|||||||
import (
|
import (
|
||||||
// External
|
// External
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
werr "git.gibonuddevalla.se/go/wrappederror"
|
|
||||||
|
|
||||||
// Standard
|
// Standard
|
||||||
"time"
|
"time"
|
||||||
@ -325,16 +324,8 @@ func CreateNode(userID, parentID int, name string) (node Node, err error) { // {
|
|||||||
return
|
return
|
||||||
} // }}}
|
} // }}}
|
||||||
func UpdateNode(userID, nodeID, timeOffset int, content string, cryptoKeyID int, markdown bool) (err error) { // {{{
|
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
|
var scannedSchedules, dbSchedules, add, remove []Schedule
|
||||||
scannedSchedules = ScanForSchedules(timezone, content)
|
scannedSchedules = ScanForSchedules(timeOffset, content)
|
||||||
for i := range scannedSchedules {
|
for i := range scannedSchedules {
|
||||||
scannedSchedules[i].Node.ID = nodeID
|
scannedSchedules[i].Node.ID = nodeID
|
||||||
scannedSchedules[i].UserID = userID
|
scannedSchedules[i].UserID = userID
|
||||||
|
@ -37,7 +37,7 @@ func InitNotificationManager() (err error) {// {{{
|
|||||||
user_id ASC,
|
user_id ASC,
|
||||||
prio ASC
|
prio ASC
|
||||||
)
|
)
|
||||||
SELECT COALESCE(jsonb_agg(s.*), '[]')
|
SELECT jsonb_agg(s.*)
|
||||||
FROM services s
|
FROM services s
|
||||||
`,
|
`,
|
||||||
)
|
)
|
||||||
|
97
schedule.go
97
schedule.go
@ -28,7 +28,7 @@ type Schedule struct {
|
|||||||
Acknowledged bool
|
Acknowledged bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func ScanForSchedules(timezone string, content string) (schedules []Schedule) { // {{{
|
func ScanForSchedules(timeOffset int, content string) (schedules []Schedule) { // {{{
|
||||||
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*\}`)
|
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,14 +40,19 @@ func ScanForSchedules(timezone string, content string) (schedules []Schedule) {
|
|||||||
data[1] = data[1] + ":00"
|
data[1] = data[1] + ":00"
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Info("time", "parse", data[1])
|
// Timezone calculations
|
||||||
location, err := time.LoadLocation(timezone)
|
var timeTZ string
|
||||||
if err != nil {
|
if timeOffset < 0 {
|
||||||
err = werr.Wrap(err).WithCode("002-00010")
|
hours := (-timeOffset) / 60
|
||||||
return
|
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
timestamp, err := time.ParseInLocation("2006-01-02 15:04:05", data[1], location)
|
timestamp, err := time.Parse("2006-01-02 15:04:05 -0700", timeTZ)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -81,15 +86,14 @@ func RetrieveSchedules(userID int, nodeID int) (schedules []Schedule, err error)
|
|||||||
res := service.Db.Conn.QueryRow(`
|
res := service.Db.Conn.QueryRow(`
|
||||||
WITH schedule_events AS (
|
WITH schedule_events AS (
|
||||||
SELECT
|
SELECT
|
||||||
s.id,
|
id,
|
||||||
s.user_id,
|
user_id,
|
||||||
json_build_object('id', s.node_id) AS node,
|
json_build_object('id', node_id) AS node,
|
||||||
s.schedule_uuid,
|
schedule_uuid,
|
||||||
(time - MAKE_INTERVAL(mins => s.remind_minutes)) AT TIME ZONE u.timezone AS time,
|
time - MAKE_INTERVAL(mins => remind_minutes) AS time,
|
||||||
s.description,
|
description,
|
||||||
s.acknowledged
|
acknowledged
|
||||||
FROM schedule s
|
FROM schedule
|
||||||
INNER JOIN public.user u ON s.user_id = u.id
|
|
||||||
WHERE
|
WHERE
|
||||||
user_id=$1 AND
|
user_id=$1 AND
|
||||||
CASE
|
CASE
|
||||||
@ -108,7 +112,6 @@ func RetrieveSchedules(userID int, nodeID int) (schedules []Schedule, err error)
|
|||||||
var data []byte
|
var data []byte
|
||||||
err = res.Scan(&data)
|
err = res.Scan(&data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = werr.Wrap(err).WithCode("002-000E")
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,16 +133,12 @@ func (s *Schedule) Insert(queryable Queryable) error { // {{{
|
|||||||
`,
|
`,
|
||||||
s.UserID,
|
s.UserID,
|
||||||
s.Node.ID,
|
s.Node.ID,
|
||||||
s.Time.Format("2006-01-02 15:04:05"),
|
s.Time,
|
||||||
s.RemindMinutes,
|
s.RemindMinutes,
|
||||||
s.Description,
|
s.Description,
|
||||||
)
|
)
|
||||||
|
|
||||||
err := res.Scan(&s.ID)
|
return res.Scan(&s.ID)
|
||||||
if err != nil {
|
|
||||||
err = werr.Wrap(err).WithCode("002-000D")
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
} // }}}
|
} // }}}
|
||||||
func (s *Schedule) Delete(queryable Queryable) error { // {{{
|
func (s *Schedule) Delete(queryable Queryable) error { // {{{
|
||||||
_, err := queryable.Exec(`
|
_, err := queryable.Exec(`
|
||||||
@ -159,14 +158,13 @@ func ExpiredSchedules() (schedules []Schedule) { // {{{
|
|||||||
|
|
||||||
res, err := service.Db.Conn.Queryx(`
|
res, err := service.Db.Conn.Queryx(`
|
||||||
SELECT
|
SELECT
|
||||||
s.id,
|
id,
|
||||||
s.user_id,
|
user_id,
|
||||||
s.node_id,
|
node_id,
|
||||||
s.schedule_uuid,
|
schedule_uuid,
|
||||||
(s.time - MAKE_INTERVAL(mins => s.remind_minutes)) AT TIME ZONE u.timezone AS time,
|
time - MAKE_INTERVAL(mins => remind_minutes) AS time,
|
||||||
s.description
|
description
|
||||||
FROM schedule s
|
FROM schedule
|
||||||
INNER JOIN public.user u ON s.user_id = u.id
|
|
||||||
WHERE
|
WHERE
|
||||||
(time - MAKE_INTERVAL(mins => remind_minutes)) < NOW() AND
|
(time - MAKE_INTERVAL(mins => remind_minutes)) < NOW() AND
|
||||||
NOT acknowledged
|
NOT acknowledged
|
||||||
@ -189,40 +187,3 @@ func ExpiredSchedules() (schedules []Schedule) { // {{{
|
|||||||
}
|
}
|
||||||
return
|
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
|
|
||||||
}// }}}
|
|
||||||
|
@ -59,7 +59,6 @@ export class NodeUI extends Component {
|
|||||||
case 'node':
|
case 'node':
|
||||||
if (node.ID == 0) {
|
if (node.ID == 0) {
|
||||||
page = html`
|
page = html`
|
||||||
<div style="cursor: pointer; color: #000; text-align: center;" onclick=${()=>this.page.value = 'schedule-events'}>Schedule events</div>
|
|
||||||
${children.length > 0 ? html`<div class="child-nodes">${children}</div><div id="notes-version">Notes version ${window._VERSION}</div>` : html``}
|
${children.length > 0 ? html`<div class="child-nodes">${children}</div><div id="notes-version">Notes version ${window._VERSION}</div>` : html``}
|
||||||
`
|
`
|
||||||
} else {
|
} else {
|
||||||
@ -98,14 +97,10 @@ export class NodeUI extends Component {
|
|||||||
case 'search':
|
case 'search':
|
||||||
page = html`<${Search} nodeui=${this} />`
|
page = html`<${Search} nodeui=${this} />`
|
||||||
break
|
break
|
||||||
|
|
||||||
case 'schedule-events':
|
|
||||||
page = html`<${ScheduleEventList} nodeui=${this} />`
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let menu = () => (this.menu.value ? html`<${Menu} nodeui=${this} />` : null)
|
let menu = ()=> (this.menu.value ? html`<${Menu} nodeui=${this} />` : null)
|
||||||
let checklist = () =>
|
let checklist = ()=>
|
||||||
html`
|
html`
|
||||||
<div class="checklist" onclick=${evt => { evt.stopPropagation(); this.toggleChecklist() }}>
|
<div class="checklist" onclick=${evt => { evt.stopPropagation(); this.toggleChecklist() }}>
|
||||||
<img src="/images/${window._VERSION}/${this.showChecklist() ? 'checklist-on.svg' : 'checklist-off.svg'}" />
|
<img src="/images/${window._VERSION}/${this.showChecklist() ? 'checklist-on.svg' : 'checklist-off.svg'}" />
|
||||||
@ -312,7 +307,7 @@ export class NodeUI extends Component {
|
|||||||
this.node.value.ShowChecklist.value = !this.node.value.ShowChecklist.value
|
this.node.value.ShowChecklist.value = !this.node.value.ShowChecklist.value
|
||||||
}//}}}
|
}//}}}
|
||||||
toggleMarkdown() {//{{{
|
toggleMarkdown() {//{{{
|
||||||
this.node.value.RenderMarkdown.value = !this.node.value.RenderMarkdown.value
|
this.node.value.RenderMarkdown.value = !this.node.value.RenderMarkdown.value
|
||||||
}//}}}
|
}//}}}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -623,7 +618,7 @@ export class Node {
|
|||||||
initChecklist(checklistData) {//{{{
|
initChecklist(checklistData) {//{{{
|
||||||
if (checklistData === undefined || checklistData === null)
|
if (checklistData === undefined || checklistData === null)
|
||||||
return
|
return
|
||||||
this.ChecklistGroups = checklistData.map(groupData => {
|
this.ChecklistGroups = checklistData.map(groupData=>{
|
||||||
return new ChecklistGroup(groupData)
|
return new ChecklistGroup(groupData)
|
||||||
})
|
})
|
||||||
}//}}}
|
}//}}}
|
||||||
@ -783,7 +778,7 @@ class NodeProperties extends Component {
|
|||||||
<div style="margin-bottom: 16px">These properties are only for this note.</div>
|
<div style="margin-bottom: 16px">These properties are only for this note.</div>
|
||||||
|
|
||||||
<div class="checks">
|
<div class="checks">
|
||||||
<input type="checkbox" id="render-markdown" checked=${nodeui.node.value.Markdown} onchange=${evt => nodeui.node.value.Markdown = evt.target.checked} />
|
<input type="checkbox" id="render-markdown" checked=${nodeui.node.value.Markdown} onchange=${evt=>nodeui.node.value.Markdown = evt.target.checked} />
|
||||||
<label for="render-markdown">Markdown view</label>
|
<label for="render-markdown">Markdown view</label>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -964,20 +959,4 @@ class ProfileSettings extends Component {
|
|||||||
}//}}}
|
}//}}}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ScheduleEventList extends Component {
|
|
||||||
constructor() {
|
|
||||||
super()
|
|
||||||
this.retrieveFutureEvents()
|
|
||||||
}
|
|
||||||
render() {
|
|
||||||
}
|
|
||||||
retrieveFutureEvents() {
|
|
||||||
_app.current.request('/schedule/list')
|
|
||||||
.then(foo=>{
|
|
||||||
console.log(foo)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// vim: foldmethod=marker
|
// vim: foldmethod=marker
|
||||||
|
Loading…
Reference in New Issue
Block a user