From a0ffbc807fc669f1d6b588ef28e60f1a6c7536e4 Mon Sep 17 00:00:00 2001 From: Jason Zimdars Date: Wed, 26 Feb 2025 17:37:49 -0600 Subject: [PATCH 1/6] Auto save comments to local storage to prevent losing work --- .../controllers/autosave_controller.js | 50 +++++++++++++++++++ app/views/comments/_new.html.erb | 8 +-- 2 files changed, 55 insertions(+), 3 deletions(-) create mode 100644 app/javascript/controllers/autosave_controller.js diff --git a/app/javascript/controllers/autosave_controller.js b/app/javascript/controllers/autosave_controller.js new file mode 100644 index 000000000..b863b648b --- /dev/null +++ b/app/javascript/controllers/autosave_controller.js @@ -0,0 +1,50 @@ +import { Controller } from "@hotwired/stimulus" +import { debounce } from "helpers/timing_helpers" + +export default class extends Controller { + static targets = ["input"] + static values = { key: String } + + initialize() { + this.debouncedSave = debounce(() => { + const content = this.inputTarget.value + if (content) { + localStorage.setItem(this.keyValue, content) + } else { + this.clear() + } + }, 300) + } + + connect() { + this.restoreContent() + } + + submit({ detail: { success } }) { + if (success) { + this.clear() + } + } + + save() { + this.debouncedSave() + } + + clear() { + localStorage.removeItem(this.keyValue) + } + + restoreContent() { + const savedContent = localStorage.getItem(this.keyValue) + if (savedContent) { + this.inputTarget.value = savedContent + this.inputTarget.dispatchEvent(new CustomEvent('house-md:change', { + bubbles: true, + detail: { + previousContent: '', + newContent: savedContent + } + })) + } + } +} \ No newline at end of file diff --git a/app/views/comments/_new.html.erb b/app/views/comments/_new.html.erb index 136db289e..b8feca412 100644 --- a/app/views/comments/_new.html.erb +++ b/app/views/comments/_new.html.erb @@ -2,9 +2,11 @@
<%= form_with model: Comment.new, url: bucket_bubble_comments_path(bubble.bucket, bubble), class: "flex flex-column gap full-width", - data: { controller: "form paste", - action: "keydown.ctrl+enter->form#submit:prevent keydown.meta+enter->form#submit:prevent keydown.esc->form#cancel:stop paste->paste#pasteFiles" } do |form| %> - <%= form.markdown_area :body, class: "input comment__input", required: true, placeholder: new_comment_placeholder(bubble) %> + data: { controller: "form paste autosave", + autosave_key_value: "comment-#{bubble.id}", + action: "turbo:submit-end->autosave#submit keydown.ctrl+enter->form#submit:prevent keydown.meta+enter->form#submit:prevent keydown.esc->form#cancel:stop paste->paste#pasteFiles" } do |form| %> + <%= form.markdown_area :body, class: "input comment__input", required: true, placeholder: new_comment_placeholder(bubble), + data: { autosave_target: "input", action: "house-md:change->autosave#save" } %> <%= form.button class: "comment__submit btn btn--reversed flex-item-justify-end txt-small" do %> <%= image_tag "check.svg", aria: { hidden: "true" }, size: 24 %> Save From ed08b85c2540d317b9de5b52da28c7eea0e3a030 Mon Sep 17 00:00:00 2001 From: Jason Zimdars Date: Wed, 26 Feb 2025 17:48:02 -0600 Subject: [PATCH 2/6] Fix that `remote-auto-save` loses markdown formatting by using local `autosave` --- app/views/bubbles/show.html.erb | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/app/views/bubbles/show.html.erb b/app/views/bubbles/show.html.erb index 6f6bb4e5b..79a0e9172 100644 --- a/app/views/bubbles/show.html.erb +++ b/app/views/bubbles/show.html.erb @@ -103,9 +103,21 @@ <% else %>
-
- <%= tag.house_md @bubble.draft_comment, name: "bubble[draft_comment]", class: "input comment__input", form: "bubble_form", placeholder: new_comment_placeholder(@bubble), - data: { action: "house-md:change->remote-auto-save#change focusout->remote-auto-save#submit", uploads_url: uploads_url(format: "json") } %> + + <%= tag.house_md @bubble.draft_comment, + name: "bubble[draft_comment]", + class: "input comment__input", + form: "bubble_form", + placeholder: new_comment_placeholder(@bubble), + data: { + autosave_target: "input", + action: "house-md:change->remote-auto-save#change house-md:change->autosave#save focusout->remote-auto-save#submit", + uploads_url: uploads_url(format: "json") + } %>
From a7cde91a1088bec8bfabac7b941405063907eba1 Mon Sep 17 00:00:00 2001 From: Kevin McConnell Date: Fri, 28 Feb 2025 14:50:26 +0000 Subject: [PATCH 3/6] Don't save draft comment to local storage Since we already save this to the database, along with the title. --- app/views/bubbles/show.html.erb | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/app/views/bubbles/show.html.erb b/app/views/bubbles/show.html.erb index 79a0e9172..6f6bb4e5b 100644 --- a/app/views/bubbles/show.html.erb +++ b/app/views/bubbles/show.html.erb @@ -103,21 +103,9 @@ <% else %>
-
- <%= tag.house_md @bubble.draft_comment, - name: "bubble[draft_comment]", - class: "input comment__input", - form: "bubble_form", - placeholder: new_comment_placeholder(@bubble), - data: { - autosave_target: "input", - action: "house-md:change->remote-auto-save#change house-md:change->autosave#save focusout->remote-auto-save#submit", - uploads_url: uploads_url(format: "json") - } %> + + <%= tag.house_md @bubble.draft_comment, name: "bubble[draft_comment]", class: "input comment__input", form: "bubble_form", placeholder: new_comment_placeholder(@bubble), + data: { action: "house-md:change->remote-auto-save#change focusout->remote-auto-save#submit", uploads_url: uploads_url(format: "json") } %>
From 06dcb11e4b14191b94db589147d7ab587e8eec7a Mon Sep 17 00:00:00 2001 From: Kevin McConnell Date: Fri, 28 Feb 2025 15:12:10 +0000 Subject: [PATCH 4/6] Refactor the controller a little bit --- .../controllers/autosave_controller.js | 48 +++++++++++-------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/app/javascript/controllers/autosave_controller.js b/app/javascript/controllers/autosave_controller.js index b863b648b..aaea8fa87 100644 --- a/app/javascript/controllers/autosave_controller.js +++ b/app/javascript/controllers/autosave_controller.js @@ -4,47 +4,53 @@ import { debounce } from "helpers/timing_helpers" export default class extends Controller { static targets = ["input"] static values = { key: String } - + initialize() { - this.debouncedSave = debounce(() => { - const content = this.inputTarget.value - if (content) { - localStorage.setItem(this.keyValue, content) - } else { - this.clear() - } - }, 300) + this.save = debounce(this.save.bind(this), 300) } - + connect() { - this.restoreContent() + this.#restoreContent() } - + submit({ detail: { success } }) { if (success) { - this.clear() + this.#clear() } } save() { - this.debouncedSave() + const content = this.inputTarget.value + if (content) { + localStorage.setItem(this.keyValue, content) + } else { + this.#clear() + } } - - clear() { + + // Private + + #clear() { localStorage.removeItem(this.keyValue) } - - restoreContent() { + + #restoreContent() { const savedContent = localStorage.getItem(this.keyValue) if (savedContent) { this.inputTarget.value = savedContent + this.#triggerChangeEvent(savedContent) + } + } + + #triggerChangeEvent(newValue) { + if (this.inputTarget.tagName === "HOUSE-MD") { this.inputTarget.dispatchEvent(new CustomEvent('house-md:change', { bubbles: true, - detail: { + detail: { previousContent: '', - newContent: savedContent + newContent: newValue } })) } } -} \ No newline at end of file +} From 4d13db0f8b110ce85b70d4ad84b9713a843b60b0 Mon Sep 17 00:00:00 2001 From: Kevin McConnell Date: Fri, 28 Feb 2025 15:13:23 +0000 Subject: [PATCH 5/6] Rename to `local-save-controller` --- ...autosave_controller.js => local_save_controller.js} | 0 app/views/comments/_new.html.erb | 10 +++++----- 2 files changed, 5 insertions(+), 5 deletions(-) rename app/javascript/controllers/{autosave_controller.js => local_save_controller.js} (100%) diff --git a/app/javascript/controllers/autosave_controller.js b/app/javascript/controllers/local_save_controller.js similarity index 100% rename from app/javascript/controllers/autosave_controller.js rename to app/javascript/controllers/local_save_controller.js diff --git a/app/views/comments/_new.html.erb b/app/views/comments/_new.html.erb index b8feca412..98b8a4968 100644 --- a/app/views/comments/_new.html.erb +++ b/app/views/comments/_new.html.erb @@ -1,12 +1,12 @@
- <%= form_with model: Comment.new, url: bucket_bubble_comments_path(bubble.bucket, bubble), class: "flex flex-column gap full-width", - data: { controller: "form paste autosave", - autosave_key_value: "comment-#{bubble.id}", - action: "turbo:submit-end->autosave#submit keydown.ctrl+enter->form#submit:prevent keydown.meta+enter->form#submit:prevent keydown.esc->form#cancel:stop paste->paste#pasteFiles" } do |form| %> + <%= form_with model: Comment.new, url: bucket_bubble_comments_path(bubble.bucket, bubble), class: "flex flex-column gap full-width", + data: { controller: "form paste local-save", + local_save_key_value: "comment-#{bubble.id}", + action: "turbo:submit-end->local-save#submit keydown.ctrl+enter->form#submit:prevent keydown.meta+enter->form#submit:prevent keydown.esc->form#cancel:stop paste->paste#pasteFiles" } do |form| %> <%= form.markdown_area :body, class: "input comment__input", required: true, placeholder: new_comment_placeholder(bubble), - data: { autosave_target: "input", action: "house-md:change->autosave#save" } %> + data: { local_save_target: "input", action: "house-md:change->local-save#save" } %> <%= form.button class: "comment__submit btn btn--reversed flex-item-justify-end txt-small" do %> <%= image_tag "check.svg", aria: { hidden: "true" }, size: 24 %> Save From 5d1206e067e9f11ec5e717f56139c1ae7eea119e Mon Sep 17 00:00:00 2001 From: Kevin McConnell Date: Fri, 28 Feb 2025 15:15:09 +0000 Subject: [PATCH 6/6] `remote-auto-save` -> `outlet-auto-save` --- ...auto_save_controller.js => outlet_auto_save_controller.js} | 0 app/views/bubbles/show.html.erb | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) rename app/javascript/controllers/{remote_auto_save_controller.js => outlet_auto_save_controller.js} (100%) diff --git a/app/javascript/controllers/remote_auto_save_controller.js b/app/javascript/controllers/outlet_auto_save_controller.js similarity index 100% rename from app/javascript/controllers/remote_auto_save_controller.js rename to app/javascript/controllers/outlet_auto_save_controller.js diff --git a/app/views/bubbles/show.html.erb b/app/views/bubbles/show.html.erb index 6f6bb4e5b..ae6f770a4 100644 --- a/app/views/bubbles/show.html.erb +++ b/app/views/bubbles/show.html.erb @@ -103,9 +103,9 @@ <% else %>
-
+ <%= tag.house_md @bubble.draft_comment, name: "bubble[draft_comment]", class: "input comment__input", form: "bubble_form", placeholder: new_comment_placeholder(@bubble), - data: { action: "house-md:change->remote-auto-save#change focusout->remote-auto-save#submit", uploads_url: uploads_url(format: "json") } %> + data: { action: "house-md:change->outlet-auto-save#change focusout->outlet-auto-save#submit", uploads_url: uploads_url(format: "json") } %>