From 44f5d92815001af95d231c137f00f86a800efffc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20=C3=85hall?= Date: Sat, 13 Jan 2024 10:01:10 +0100 Subject: [PATCH] Move item in checklist --- main.go | 24 ++++++++++++++ node.go | 44 +++++++++++++++++++++++++ static/js/checklist.mjs | 73 ++++++++++++++++++++++++++++++++--------- 3 files changed, 125 insertions(+), 16 deletions(-) diff --git a/main.go b/main.go index 6981700..eebe749 100644 --- a/main.go +++ b/main.go @@ -111,6 +111,7 @@ func main() { // {{{ service.Register("/node/checklist_item/state", true, true, nodeChecklistItemState) service.Register("/node/checklist_item/label", true, true, nodeChecklistItemLabel) service.Register("/node/checklist_item/delete", true, true, nodeChecklistItemDelete) + service.Register("/node/checklist_item/move", true, true, nodeChecklistItemMove) service.Register("/key/retrieve", true, true, keyRetrieve) service.Register("/key/create", true, true, keyCreate) service.Register("/key/counter", true, true, keyCounter) @@ -645,6 +646,29 @@ func nodeChecklistItemDelete(w http.ResponseWriter, r *http.Request, sess *sessi "OK": true, }) } // }}} +func nodeChecklistItemMove(w http.ResponseWriter, r *http.Request, sess *session.T) { // {{{ + var err error + + req := struct { + ChecklistItemID int + AfterItemID int + }{} + if err = parseRequest(r, &req); err != nil { + responseError(w, err) + return + } + + err = ChecklistItemMove(sess.UserID, req.ChecklistItemID, req.AfterItemID) + if err != nil { + logger.Error("checklist", "error", err) + responseError(w, err) + return + } + + responseData(w, map[string]interface{}{ + "OK": true, + }) +} // }}} func keyRetrieve(w http.ResponseWriter, r *http.Request, sess *session.T) { // {{{ logger.Info("webserver", "request", "/key/retrieve") diff --git a/node.go b/node.go index f11c351..c65b4b4 100644 --- a/node.go +++ b/node.go @@ -600,6 +600,50 @@ func ChecklistItemDelete(userID, checklistItemID int) (err error) { // {{{ ) return } // }}} +func ChecklistItemMove(userID, checklistItemID, afterItemID int) (err error) { // {{{ + _, err = service.Db.Conn.Exec( + ` + WITH + "to" AS ( + SELECT + i.checklist_group_id AS group_id, + i."order" + FROM checklist_item i + INNER JOIN checklist_group g ON i.checklist_group_id = g.id + INNER JOIN node n ON g.node_id = n.id + WHERE + n.user_id = $1 AND + i.id = $3 + ), + + update_order AS ( + UPDATE checklist_item + SET + "order" = + CASE + WHEN checklist_item."order" <= "to"."order" THEN checklist_item."order" - 1 + WHEN checklist_item."order" > "to"."order" THEN checklist_item."order" + 1 + END + FROM "to" + WHERE + checklist_item.id != $2 AND + checklist_item.checklist_group_id = "to".group_id + ) + + UPDATE checklist_item + SET + checklist_group_id = "to".group_id, + "order" = "to"."order" + FROM "to" + WHERE + checklist_item.id = $2 + `, + userID, + checklistItemID, + afterItemID, + ) + return +} // }}} func (node *Node) retrieveChecklist() (err error) { // {{{ var rows *sqlx.Rows diff --git a/static/js/checklist.mjs b/static/js/checklist.mjs index 6abfbdc..498e08f 100644 --- a/static/js/checklist.mjs +++ b/static/js/checklist.mjs @@ -16,8 +16,7 @@ export class ChecklistGroup { let item = new ChecklistItem(itemData) item.checklistGroup = this return item - } - ).sort(ChecklistItem.sort) + }) else this[key] = data[key] }) @@ -92,6 +91,14 @@ export class ChecklistItem { }) .catch(errCallback) }//}}} + move(to, okCallback) {//{{{ + window._app.current.request('/node/checklist_item/move', { + ChecklistItemID: this.ID, + AfterItemID: to.ID, + }) + .then(okCallback) + .catch(_app.current.responseError) + }//}}} } export class Checklist extends Component { @@ -100,11 +107,14 @@ export class Checklist extends Component { this.edit = signal(true) this.dragItemSource = null this.dragItemTarget = null + this.groupElements = {} this.state = { confirmDeletion: true, } + window._checklist = this }//}}} render({ groups }, { confirmDeletion }) {//{{{ + this.groupElements = {} if (groups.length == 0) return @@ -112,7 +122,10 @@ export class Checklist extends Component { groups = [] groups.sort(ChecklistGroup.sort) - let groupElements = groups.map(group => html`<${ChecklistGroupElement} key="group-${group.ID}" ui=${this} group=${group} />`) + let groupElements = groups.map(group => { + this.groupElements[group.ID] = createRef() + return html`<${ChecklistGroupElement} ref=${this.groupElements[group.ID]} key="group-${group.ID}" ui=${this} group=${group} />` + }) let edit = 'edit-list-gray.svg' let confirmDeletionEl = '' @@ -126,9 +139,9 @@ export class Checklist extends Component { ` } - let addGroup = ()=>{ + let addGroup = () => { if (this.edit.value) - return html`this.addGroup()} />` + return html` this.addGroup()} />` } return html` @@ -187,10 +200,12 @@ class ChecklistGroupElement extends Component { this.label = createRef() }//}}} render({ ui, group }) {//{{{ - let items = ({ ui, group }) => - group.items.map(item => html`<${ChecklistItemElement} key="item-${item.ID}" ui=${ui} group=${this} item=${item} />`) + let items = ({ ui, group }) => + group.items + .sort(ChecklistItem.sort) + .map(item => html`<${ChecklistItemElement} key="item-${item.ID}" ui=${ui} group=${this} item=${item} />`) - let label = ()=>html`
this.editLabel()}>${group.Label}
` + let label = () => html`
this.editLabel()}>${group.Label}
` return html`
@@ -266,7 +281,7 @@ class ChecklistItemElement extends Component { this.label = createRef() }//}}} render({ ui, item }, { checked, dragTarget }) {//{{{ - let checkbox = ()=>{ + let checkbox = () => { if (ui.edit.value) return html`` else @@ -284,9 +299,9 @@ class ChecklistItemElement extends Component { ` }//}}} componentDidMount() {//{{{ - this.base.addEventListener('dragstart', ()=>this.dragStart()) - this.base.addEventListener('dragend', ()=>this.dragEnd()) - this.base.addEventListener('dragenter', evt=>this.dragEnter(evt)) + this.base.addEventListener('dragstart', () => this.dragStart()) + this.base.addEventListener('dragend', () => this.dragEnd()) + this.base.addEventListener('dragenter', evt => this.dragEnter(evt)) }//}}} update(checked) {//{{{ @@ -348,11 +363,37 @@ class ChecklistItemElement extends Component { this.props.ui.dragTarget(this) }//}}} dragEnd() {//{{{ - console.log( - this.props.ui.dragItemSource.props.item.Label, - this.props.ui.dragItemTarget.props.item.Label, - ) + let groups = this.props.ui.props.groups + let from = this.props.ui.dragItemSource.props.item + let to = this.props.ui.dragItemTarget.props.item + this.props.ui.dragReset() + + if (from.ID == to.ID) + return + + let fromGroup = groups.find(g => g.ID == from.GroupID) + let toGroup = groups.find(g => g.ID == to.GroupID) + + + from.Order = to.Order + from.GroupID = toGroup.ID + toGroup.items.forEach(i => { + if (i.ID == from.ID) + return + if (i.Order <= to.Order) + i.Order-- + }) + + if (fromGroup.ID != toGroup.ID) { + fromGroup.items = fromGroup.items.filter(i => i.ID != from.ID) + toGroup.items.push(from) + } + + this.props.ui.groupElements[fromGroup.ID].current.forceUpdate() + this.props.ui.groupElements[toGroup.ID].current.forceUpdate() + + from.move(to, ()=>console.log('ok')) }//}}} }