Move item in checklist

This commit is contained in:
Magnus Åhall 2024-01-13 10:01:10 +01:00
parent d0f410323e
commit 44f5d92815
3 changed files with 125 additions and 16 deletions

24
main.go
View File

@ -111,6 +111,7 @@ func main() { // {{{
service.Register("/node/checklist_item/state", true, true, nodeChecklistItemState) service.Register("/node/checklist_item/state", true, true, nodeChecklistItemState)
service.Register("/node/checklist_item/label", true, true, nodeChecklistItemLabel) service.Register("/node/checklist_item/label", true, true, nodeChecklistItemLabel)
service.Register("/node/checklist_item/delete", true, true, nodeChecklistItemDelete) 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/retrieve", true, true, keyRetrieve)
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)
@ -645,6 +646,29 @@ func nodeChecklistItemDelete(w http.ResponseWriter, r *http.Request, sess *sessi
"OK": true, "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) { // {{{ func keyRetrieve(w http.ResponseWriter, r *http.Request, sess *session.T) { // {{{
logger.Info("webserver", "request", "/key/retrieve") logger.Info("webserver", "request", "/key/retrieve")

44
node.go
View File

@ -600,6 +600,50 @@ func ChecklistItemDelete(userID, checklistItemID int) (err error) { // {{{
) )
return 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) { // {{{ func (node *Node) retrieveChecklist() (err error) { // {{{
var rows *sqlx.Rows var rows *sqlx.Rows

View File

@ -16,8 +16,7 @@ export class ChecklistGroup {
let item = new ChecklistItem(itemData) let item = new ChecklistItem(itemData)
item.checklistGroup = this item.checklistGroup = this
return item return item
} })
).sort(ChecklistItem.sort)
else else
this[key] = data[key] this[key] = data[key]
}) })
@ -92,6 +91,14 @@ export class ChecklistItem {
}) })
.catch(errCallback) .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 { export class Checklist extends Component {
@ -100,11 +107,14 @@ export class Checklist extends Component {
this.edit = signal(true) this.edit = signal(true)
this.dragItemSource = null this.dragItemSource = null
this.dragItemTarget = null this.dragItemTarget = null
this.groupElements = {}
this.state = { this.state = {
confirmDeletion: true, confirmDeletion: true,
} }
window._checklist = this
}//}}} }//}}}
render({ groups }, { confirmDeletion }) {//{{{ render({ groups }, { confirmDeletion }) {//{{{
this.groupElements = {}
if (groups.length == 0) if (groups.length == 0)
return return
@ -112,7 +122,10 @@ export class Checklist extends Component {
groups = [] groups = []
groups.sort(ChecklistGroup.sort) 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 edit = 'edit-list-gray.svg'
let confirmDeletionEl = '' let confirmDeletionEl = ''
@ -126,9 +139,9 @@ export class Checklist extends Component {
` `
} }
let addGroup = ()=>{ let addGroup = () => {
if (this.edit.value) if (this.edit.value)
return html`<img src="/images/${_VERSION}/add-gray.svg" onclick=${()=>this.addGroup()} />` return html`<img src="/images/${_VERSION}/add-gray.svg" onclick=${() => this.addGroup()} />`
} }
return html` return html`
@ -188,9 +201,11 @@ class ChecklistGroupElement extends Component {
}//}}} }//}}}
render({ ui, group }) {//{{{ render({ ui, group }) {//{{{
let items = ({ ui, group }) => let items = ({ ui, group }) =>
group.items.map(item => html`<${ChecklistItemElement} key="item-${item.ID}" ui=${ui} group=${this} item=${item} />`) group.items
.sort(ChecklistItem.sort)
.map(item => html`<${ChecklistItemElement} key="item-${item.ID}" ui=${ui} group=${this} item=${item} />`)
let label = ()=>html`<div class="label" style="cursor: pointer" ref=${this.label} onclick=${()=>this.editLabel()}>${group.Label}</div>` let label = () => html`<div class="label" style="cursor: pointer" ref=${this.label} onclick=${() => this.editLabel()}>${group.Label}</div>`
return html` return html`
<div class="checklist-group-container"> <div class="checklist-group-container">
@ -266,7 +281,7 @@ class ChecklistItemElement extends Component {
this.label = createRef() this.label = createRef()
}//}}} }//}}}
render({ ui, item }, { checked, dragTarget }) {//{{{ render({ ui, item }, { checked, dragTarget }) {//{{{
let checkbox = ()=>{ let checkbox = () => {
if (ui.edit.value) if (ui.edit.value)
return html`<label ref=${this.label} onclick=${() => this.editLabel()} style="cursor: pointer">${item.Label}</label>` return html`<label ref=${this.label} onclick=${() => this.editLabel()} style="cursor: pointer">${item.Label}</label>`
else else
@ -284,9 +299,9 @@ class ChecklistItemElement extends Component {
` `
}//}}} }//}}}
componentDidMount() {//{{{ componentDidMount() {//{{{
this.base.addEventListener('dragstart', ()=>this.dragStart()) this.base.addEventListener('dragstart', () => this.dragStart())
this.base.addEventListener('dragend', ()=>this.dragEnd()) this.base.addEventListener('dragend', () => this.dragEnd())
this.base.addEventListener('dragenter', evt=>this.dragEnter(evt)) this.base.addEventListener('dragenter', evt => this.dragEnter(evt))
}//}}} }//}}}
update(checked) {//{{{ update(checked) {//{{{
@ -348,11 +363,37 @@ class ChecklistItemElement extends Component {
this.props.ui.dragTarget(this) this.props.ui.dragTarget(this)
}//}}} }//}}}
dragEnd() {//{{{ dragEnd() {//{{{
console.log( let groups = this.props.ui.props.groups
this.props.ui.dragItemSource.props.item.Label, let from = this.props.ui.dragItemSource.props.item
this.props.ui.dragItemTarget.props.item.Label, let to = this.props.ui.dragItemTarget.props.item
)
this.props.ui.dragReset() 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'))
}//}}} }//}}}
} }