From 4371eb8e50bd4fe2187d3a7713fbdcc46efa954e Mon Sep 17 00:00:00 2001 From: Serhii Horodilov Date: Tue, 30 Jan 2024 16:51:00 +0200 Subject: [PATCH 1/6] Implement task deletion behavior for the list view (fixes GH-11) --- src/views/partials/list_main.hbs | 6 +++--- src/views/partials/list_task.hbs | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/views/partials/list_main.hbs b/src/views/partials/list_main.hbs index ded18c1..620c3ec 100644 --- a/src/views/partials/list_main.hbs +++ b/src/views/partials/list_main.hbs @@ -16,7 +16,7 @@ {{! repeating tasks block }} {{>list_task - pk="a76e9fac-f8ca-45ca-ae57-063459443ff0" + pk="d5870f6d-8431-47ac-84e4-ef9de83ee622" summary="Shield at the holodeck was the energy of assimilation, lowered to a chemical c-beam." description="The creature is more transformator now than starship. solid and always quirky. energy at the wormhole was the life of ellipse, grabed to a mysterious proton. @@ -29,7 +29,7 @@ can_edit=false }} {{>list_task - pk="a76e9fac-f8ca-45ca-ae57-063459443ff0" + pk="1f380d72-ecf0-454a-99c8-7fde60c4d22f" summary="Sensor at the universe was the pattern of love, empowered to a futile alien." description="The nanomachine is more admiral now than processor. senior and patiently dead. pattern at the center was the death of attitude, loved to a biological ship. @@ -42,7 +42,7 @@ can_edit=true }} {{>list_task - pk="a76e9fac-f8ca-45ca-ae57-063459443ff0" + pk="d04c3467-65a4-436e-82dd-5b81c954eb0f" summary="Flight at the ready room was the vision of alignment, empowered to a quirky vogon." description="The particle is more creature now than transformator. virtual and rudely lunar. starlight travel at the ready room was the powerdrain of faith, evacuated to a most unusual moon. diff --git a/src/views/partials/list_task.hbs b/src/views/partials/list_task.hbs index db28f79..2e9f124 100644 --- a/src/views/partials/list_task.hbs +++ b/src/views/partials/list_task.hbs @@ -20,6 +20,7 @@ data-task-target="{{pk}}" aria-label="complete"> {{! TODO: patch-status? }} {{/if}} From d2ad9d51b64eb39b0cd76374a2515fc759e1d7ea Mon Sep 17 00:00:00 2001 From: Serhii Horodilov Date: Tue, 30 Jan 2024 17:37:48 +0200 Subject: [PATCH 2/6] Add htmx to patch tasks entries (GH-12) --- api/server.js | 6 ++++-- src/views/partials/list_task.hbs | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/api/server.js b/api/server.js index 3b7a796..1e3af12 100644 --- a/api/server.js +++ b/api/server.js @@ -4,6 +4,7 @@ const {host, port} = require("./settings") const app = express() app.use(express.json()) +app.use(express.urlencoded({ extended: true })) app.delete("/api/v1/tasks/:uuid", (req, res) => { const {uuid} = req.params @@ -13,8 +14,9 @@ app.delete("/api/v1/tasks/:uuid", (req, res) => { app.patch("/api/v1/tasks/:uuid", (req, res) => { const {uuid} = req.params - console.log(`PATCH Task('${uuid}')`) - res.status(200).end() + const {completed} = req.body + console.log(`PATCH Task('${uuid}') switch completed to ${completed}`) + res.status(200).json({completed:completed}) }) app.listen(port, host, () => { diff --git a/src/views/partials/list_task.hbs b/src/views/partials/list_task.hbs index 2e9f124..97fc243 100644 --- a/src/views/partials/list_task.hbs +++ b/src/views/partials/list_task.hbs @@ -14,10 +14,12 @@
{{#if completed}} {{! TODO: patch-status ? }} + hx-patch="/api/v1/tasks/{{pk}}" hx-vals="js:{completed:false}" hx-swap="none" + data-task-target="{{pk}}" aria-label="reopen"> {{else}} {{! TODO: patch-status? }} + hx-patch="/api/v1/tasks/{{pk}}" hx-vals="js:{completed:true}" hx-swap="none" + data-task-target="{{pk}}" aria-label="complete"> {{/if}} Date: Tue, 30 Jan 2024 19:16:43 +0200 Subject: [PATCH 3/6] Implement swap task completed behavior (fixes GH-12) --- api/server.js | 13 +++++-------- src/index.js | 2 ++ src/js/tasks.js | 28 ++++++++++++++++++++++++++++ src/views/partials/list_task.hbs | 6 +++--- 4 files changed, 38 insertions(+), 11 deletions(-) create mode 100644 src/js/tasks.js diff --git a/api/server.js b/api/server.js index 1e3af12..22d16f1 100644 --- a/api/server.js +++ b/api/server.js @@ -6,17 +6,14 @@ const app = express() app.use(express.json()) app.use(express.urlencoded({ extended: true })) -app.delete("/api/v1/tasks/:uuid", (req, res) => { - const {uuid} = req.params - console.log(`DELETE Task('${uuid}')`) +app.delete("/api/v1/tasks/:pk", (req, res) => { res.status(200).end() }) -app.patch("/api/v1/tasks/:uuid", (req, res) => { - const {uuid} = req.params - const {completed} = req.body - console.log(`PATCH Task('${uuid}') switch completed to ${completed}`) - res.status(200).json({completed:completed}) +app.patch("/api/v1/tasks/:pk", (req, res) => { + const {pk} = req.params + const completed = req.body.completed === "true" + res.status(200).json({pk, completed}) }) app.listen(port, host, () => { diff --git a/src/index.js b/src/index.js index 7e1ecf0..6c6ba56 100644 --- a/src/index.js +++ b/src/index.js @@ -18,3 +18,5 @@ import "./scss/list.scss" import "./scss/profile.scss" import "./scss/sign-in.scss" import "./scss/sign-up.scss" + +import "./js/tasks" diff --git a/src/js/tasks.js b/src/js/tasks.js new file mode 100644 index 0000000..14e3837 --- /dev/null +++ b/src/js/tasks.js @@ -0,0 +1,28 @@ +const swapTaskCompletedStatus = ({pk, completed}) => { + const element = document.getElementById(pk) + if (element) element.setAttribute("data-task-completed", completed) +} + + +const swapTaskPatchButton = ({element, completed}) => { + element.setAttribute("hx-vals", `js:{completed:${!completed}}`) + element.classList = ["bi"] // clean class list + if (completed) { + element.classList.add("bi-arrow-repeat") + } else { + element.classList.add("bi-check-lg") + } +} + + +document.body.addEventListener("htmx:afterOnLoad", (event) => { + const xhr = event.detail.xhr + const response = JSON.parse(xhr.response) + const triggeredElement = event.detail.elt + const action = triggeredElement.getAttribute("data-task-action") + + if (action === "patch" && xhr.responseURL.includes("tasks")) { + swapTaskPatchButton({...response, element: triggeredElement}) + swapTaskCompletedStatus(response) + } +}) diff --git a/src/views/partials/list_task.hbs b/src/views/partials/list_task.hbs index 97fc243..ca36177 100644 --- a/src/views/partials/list_task.hbs +++ b/src/views/partials/list_task.hbs @@ -15,15 +15,15 @@ {{#if completed}} + data-task-target="{{pk}}" data-task-action="patch"> {{else}} + data-task-target="{{pk}}" data-task-action="patch"> {{/if}} + data-task-target="{{pk}}" data-task-action="delete">
From f115565b4706c1c3acfb98500c186a3ed2869634 Mon Sep 17 00:00:00 2001 From: Serhii Horodilov Date: Tue, 30 Jan 2024 19:20:50 +0200 Subject: [PATCH 4/6] Fix task actions JS issues (fixes GH-11, fixes GH-12) --- src/js/tasks.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/js/tasks.js b/src/js/tasks.js index 14e3837..8c0c201 100644 --- a/src/js/tasks.js +++ b/src/js/tasks.js @@ -6,7 +6,7 @@ const swapTaskCompletedStatus = ({pk, completed}) => { const swapTaskPatchButton = ({element, completed}) => { element.setAttribute("hx-vals", `js:{completed:${!completed}}`) - element.classList = ["bi"] // clean class list + element.classList.remove("bi-arrow-repeat", "bi-check-lg") if (completed) { element.classList.add("bi-arrow-repeat") } else { @@ -17,11 +17,14 @@ const swapTaskPatchButton = ({element, completed}) => { document.body.addEventListener("htmx:afterOnLoad", (event) => { const xhr = event.detail.xhr - const response = JSON.parse(xhr.response) + if (xhr.status !== 200) return // do nothing if request wasn't successful + const triggeredElement = event.detail.elt const action = triggeredElement.getAttribute("data-task-action") + let response = xhr.response if (action === "patch" && xhr.responseURL.includes("tasks")) { + response = JSON.parse(response) swapTaskPatchButton({...response, element: triggeredElement}) swapTaskCompletedStatus(response) } From d65c2b52bd06e9f4568230573442a5aa4dc3a905 Mon Sep 17 00:00:00 2001 From: Serhii Horodilov Date: Tue, 30 Jan 2024 19:32:45 +0200 Subject: [PATCH 5/6] Fix action buttons styling --- src/scss/list.scss | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/scss/list.scss b/src/scss/list.scss index fade689..d13a469 100644 --- a/src/scss/list.scss +++ b/src/scss/list.scss @@ -25,15 +25,11 @@ $list-img-max-size: 5rem; } // action buttons - [aria-label=complete] { + [data-task-action=patch] { color: var(--bs-success); } - [aria-label=reopen] { - color: var(--bs-warning); - } - - [aria-label=delete] { + [data-task-action=delete] { color: var(--bs-danger); } } @@ -43,4 +39,8 @@ $list-img-max-size: 5rem; color: var(--bs-secondary-color) !important; text-decoration: line-through !important; } + + [data-task-action=patch] { + color: var(--bs-warning) + } } From e25bbaeebb8e0505f86dc59457ba0ee21e2b7892 Mon Sep 17 00:00:00 2001 From: Serhii Horodilov Date: Tue, 30 Jan 2024 20:29:58 +0200 Subject: [PATCH 6/6] Implement swap task completed for detail view (fixes GH-13) --- src/js/tasks.js | 42 +++++++++++++++++++++++++++--- src/views/partials/detail_main.hbs | 12 +++++---- 2 files changed, 45 insertions(+), 9 deletions(-) diff --git a/src/js/tasks.js b/src/js/tasks.js index 8c0c201..e090058 100644 --- a/src/js/tasks.js +++ b/src/js/tasks.js @@ -1,11 +1,25 @@ -const swapTaskCompletedStatus = ({pk, completed}) => { +const swapTaskListCompletedStatus = ({pk, completed}) => { const element = document.getElementById(pk) if (element) element.setAttribute("data-task-completed", completed) } -const swapTaskPatchButton = ({element, completed}) => { - element.setAttribute("hx-vals", `js:{completed:${!completed}}`) +const swapTaskDetailedCompletedStatus = ({completed}) => { + const element = document.querySelector("h1#summary") + if (!element) return + + if (completed) { + const icon = document.createElement("i") + icon.classList.add("bi", "bi-check-lg", "text-success") + element.prepend(icon) + } else { + const icon = element.querySelector("i.bi.bi-check-lg") + element.removeChild(icon) + } +} + + +const updateListActionButton = (element, completed) => { element.classList.remove("bi-arrow-repeat", "bi-check-lg") if (completed) { element.classList.add("bi-arrow-repeat") @@ -15,6 +29,25 @@ const swapTaskPatchButton = ({element, completed}) => { } +const updateDetailActionButton = (element, completed) => { + element.classList.remove("btn-outline-warning", "btn-outline-success") + if (completed) { + element.classList.add("btn-outline-warning") + element.textContent = "Reopen" + } else { + element.classList.add("btn-outline-success") + element.textContent = "Complete" + } +} + + +const swapTaskPatchButton = ({element, completed}) => { + element.setAttribute("hx-vals", `js:{completed:${!completed}}`) + if (element.matches("i[role=button]")) updateListActionButton(element, completed) + if (element.matches("button.btn")) updateDetailActionButton(element, completed) +} + + document.body.addEventListener("htmx:afterOnLoad", (event) => { const xhr = event.detail.xhr if (xhr.status !== 200) return // do nothing if request wasn't successful @@ -26,6 +59,7 @@ document.body.addEventListener("htmx:afterOnLoad", (event) => { if (action === "patch" && xhr.responseURL.includes("tasks")) { response = JSON.parse(response) swapTaskPatchButton({...response, element: triggeredElement}) - swapTaskCompletedStatus(response) + swapTaskDetailedCompletedStatus(response) + swapTaskListCompletedStatus(response) } }) diff --git a/src/views/partials/detail_main.hbs b/src/views/partials/detail_main.hbs index 7392a32..024df57 100644 --- a/src/views/partials/detail_main.hbs +++ b/src/views/partials/detail_main.hbs @@ -1,9 +1,9 @@
-

- {{#if completed}} {{/if}} - {{summary}} +

+ {{#if completed}}{{/if}} + {{summary}}


@@ -33,12 +33,14 @@
{{#if completed}} {{else}} {{/if}}