From 9cb3803eb3c9f44b54e6ff60c1d95eb66454202f Mon Sep 17 00:00:00 2001 From: taco Date: Tue, 27 Feb 2024 00:07:05 +0900 Subject: [PATCH 1/3] =?UTF-8?q?practice=5Fmemo.vue=E3=82=92html=E3=81=A8js?= =?UTF-8?q?=E3=81=A7=E3=81=AE=E5=AE=9F=E8=A3=85=E3=81=AB=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/javascript/practice_memo.js | 140 +++++++++++++++-- app/javascript/practice_memo.vue | 163 -------------------- app/views/products/_practice_memo.html.slim | 43 ++++++ app/views/products/show.html.slim | 2 +- 4 files changed, 171 insertions(+), 177 deletions(-) delete mode 100644 app/javascript/practice_memo.vue create mode 100644 app/views/products/_practice_memo.html.slim diff --git a/app/javascript/practice_memo.js b/app/javascript/practice_memo.js index 184fb067d2c..e09e1de720e 100644 --- a/app/javascript/practice_memo.js +++ b/app/javascript/practice_memo.js @@ -1,18 +1,132 @@ -import Vue from 'vue' -import PracticeMemo from 'practice_memo.vue' +import CSRF from 'csrf' +import TextareaInitializer from 'textarea-initializer' +import MarkdownInitializer from 'markdown-initializer' +import { toast } from 'toast_react' document.addEventListener('DOMContentLoaded', () => { - const selector = '#js-practice-memo' - const practiceMemo = document.querySelector(selector) + const practiceMemo = document.querySelector('.practice-memo') if (practiceMemo) { - const practiceId = practiceMemo.getAttribute('data-practice-id') - new Vue({ - render: (h) => - h(PracticeMemo, { - props: { - practiceId: practiceId - } - }) - }).$mount(selector) + TextareaInitializer.initialize('.a-markdown-input__textarea') + const markdownInitializer = new MarkdownInitializer() + const practiceId = practiceMemo.dataset.practice_id + let savedMemo = '' + + const memoDisplay = practiceMemo.querySelector('.memo-display') + const memoEditor = practiceMemo.querySelector('.memo-editor') + const memoDisplayContent = memoDisplay.querySelector('.a-long-text') + const memoEditorPreview = memoEditor.querySelector( + '.a-markdown-input__preview' + ) + const editorTextarea = memoEditor.querySelector( + '.a-markdown-input__textarea' + ) + + fetch(`/api/practices/${practiceId}.json`, { + method: 'GET', + headers: { + 'X-Requested-With': 'XMLHttpRequest' + }, + credentials: 'same-origin', + redirect: 'manual' + }) + .then((response) => { + return response.json() + }) + .then((json) => { + if (json.memo) { + savedMemo = json.memo + editorTextarea.value = savedMemo + switchMemoDisplay(memoDisplay, savedMemo) + memoDisplayContent.innerHTML = markdownInitializer.render(savedMemo) + memoEditorPreview.innerHTML = markdownInitializer.render(savedMemo) + } + }) + .catch((error) => { + console.warn(error) + }) + + const editButton = memoDisplay.querySelector('.card-main-actions__action') + const modalElements = [memoDisplay, memoEditor] + editButton.addEventListener('click', () => + toggleClass(modalElements, 'is-hidden') + ) + + const saveButton = memoEditor.querySelector('.is-primary') + saveButton.addEventListener('click', () => { + toggleClass(modalElements, 'is-hidden') + savedMemo = editorTextarea.value + updateMemo(savedMemo, practiceId) + memoDisplayContent.innerHTML = markdownInitializer.render(savedMemo) + switchMemoDisplay(memoDisplay, savedMemo) + }) + + const cancelButton = memoEditor.querySelector('.is-secondary') + cancelButton.addEventListener('click', () => { + toggleClass(modalElements, 'is-hidden') + editorTextarea.value = savedMemo + memoEditorPreview.innerHTML = markdownInitializer.render(savedMemo) + }) + + editorTextarea.addEventListener('change', () => { + memoEditorPreview.innerHTML = markdownInitializer.render( + editorTextarea.value + ) + }) + + const editorTab = memoEditor.querySelector('.editor-tab') + const editorTabContent = memoEditor.querySelector('.is-editor') + const previewTab = memoEditor.querySelector('.preview-tab') + const previewTabContent = memoEditor.querySelector('.is-preview') + + const tabElements = [ + editorTab, + editorTabContent, + previewTab, + previewTabContent + ] + editorTab.addEventListener('click', () => + toggleClass(tabElements, 'is-active') + ) + previewTab.addEventListener('click', () => + toggleClass(tabElements, 'is-active') + ) } }) + +function updateMemo(memo, practiceId) { + const params = { + practice: { + memo: memo + } + } + fetch(`/api/practices/${practiceId}`, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json; charset=utf-8', + 'X-Requested-With': 'XMLHttpRequest', + 'X-CSRF-Token': CSRF.getToken() + }, + credentials: 'same-origin', + redirect: 'manual', + body: JSON.stringify(params) + }) + .then(() => { + toast('保存しました!') + }) + .catch((error) => { + console.warn(error) + }) +} + +function switchMemoDisplay(memoDisplay, memo) { + const memoContent = memoDisplay.querySelector('.any-memo') + const noMemoMessage = memoDisplay.querySelector('.no-memo') + memoContent.classList.toggle('is-hidden', memo === '') + noMemoMessage.classList.toggle('is-hidden', memo !== '') +} + +function toggleClass(elements, className) { + elements.forEach((element) => { + element.classList.toggle(className) + }) +} diff --git a/app/javascript/practice_memo.vue b/app/javascript/practice_memo.vue deleted file mode 100644 index d0bb9d33b7e..00000000000 --- a/app/javascript/practice_memo.vue +++ /dev/null @@ -1,163 +0,0 @@ - - diff --git a/app/views/products/_practice_memo.html.slim b/app/views/products/_practice_memo.html.slim new file mode 100644 index 00000000000..cd4fe12dddb --- /dev/null +++ b/app/views/products/_practice_memo.html.slim @@ -0,0 +1,43 @@ +.a-card.practice-memo data-practice_id=practice_id + .memo-display + .card-body + .card__description.any-memo.is-hidden + .a-long-text.is-md + .card-list.no-memo + .card-list__message + .container + .o-empty-message + .o-empty-message__icon + i.fa-regular.fa-sad-tear + .o-empty-message__text + | プラクティスメモはまだありません。 + hr.a-border-tint + footer.card-footer + .card-main-actions + ul.card-main-actions__items + li.card-main-actions__item + button.card-main-actions__action.a-button.is-sm.is-secondary.is-block + i.fa-solid.fa-pen + | 編集 + .memo-editor.is-hidden + .card-body + .form-tabs.js-tabs + .form-tabs__tab.js-tabs__tab.editor-tab.is-active + | メモ + .form-tabs__tab.js-tabs__tab.preview-tab + | プレビュー + .a-markdown-input.js-markdown-parent + .a-markdown-input__inner.is-editor.js-tabs__content.is-active + textarea.a-text-input.a-markdown-input__textarea + .a-markdown-input__inner.is-preview.js-tabs__content + .a-long-text.a-markdown-input__preview + hr.a-border-tint + .card-footer + .card-main-actions + .card-main-actions__items + .card-main-actions__item + button.a-button.is-sm.is-primary.is-block + | 保存する + .card-main-actions__item + button.a-button.is-sm.is-secondary.is-block + | キャンセル diff --git a/app/views/products/show.html.slim b/app/views/products/show.html.slim index b2e3859a8d4..8e6297f56b9 100644 --- a/app/views/products/show.html.slim +++ b/app/views/products/show.html.slim @@ -74,7 +74,7 @@ header.page-header .side-tabs-contents__item#side-tabs-content-1 div(data-vue="UserRecentReports" data-vue-user-id:number="#{@product.user.id}") .side-tabs-contents__item#side-tabs-content-2 - #js-practice-memo(data-practice-id="#{@product.practice_id}") + = render 'practice_memo', practice_id: @product.practice_id .side-tabs-contents__item#side-tabs-content-3 .user-info = render 'users/user_secret_attributes', user: @product.user From 5fc87824a193a24bcd11ebab5421789376162557 Mon Sep 17 00:00:00 2001 From: taco Date: Tue, 27 Feb 2024 20:03:52 +0900 Subject: [PATCH 2/3] =?UTF-8?q?=E6=AC=A0=E3=81=91=E3=81=A6=E3=81=84?= =?UTF-8?q?=E3=81=9F=E5=B1=9E=E6=80=A7=E3=82=92=E8=BF=BD=E5=8A=A0=E3=81=97?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/views/products/_practice_memo.html.slim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/products/_practice_memo.html.slim b/app/views/products/_practice_memo.html.slim index cd4fe12dddb..0a6b444cf80 100644 --- a/app/views/products/_practice_memo.html.slim +++ b/app/views/products/_practice_memo.html.slim @@ -28,7 +28,7 @@ | プレビュー .a-markdown-input.js-markdown-parent .a-markdown-input__inner.is-editor.js-tabs__content.is-active - textarea.a-text-input.a-markdown-input__textarea + textarea.a-text-input.a-markdown-input__textarea id='js-practice-memo' data-preview='#practice-memo-preview' name='practice[memo]' .a-markdown-input__inner.is-preview.js-tabs__content .a-long-text.a-markdown-input__preview hr.a-border-tint From fb2a2e5df17808e0491f458d2e2d59455141a839 Mon Sep 17 00:00:00 2001 From: machida Date: Tue, 12 Mar 2024 14:47:14 +0900 Subject: [PATCH 3/3] =?UTF-8?q?=E3=83=97=E3=83=A9=E3=82=AF=E3=83=86?= =?UTF-8?q?=E3=82=A3=E3=82=B9=E3=83=A1=E3=83=A2=E3=81=AE=E4=BD=99=E7=99=BD?= =?UTF-8?q?=E3=82=92=E4=BB=98=E3=81=91=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/blocks/form/_form-tabs.sass | 3 ++- app/views/products/_practice_memo.html.slim | 21 ++++++++++--------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/app/javascript/stylesheets/application/blocks/form/_form-tabs.sass b/app/javascript/stylesheets/application/blocks/form/_form-tabs.sass index cb0af6257fb..adebc05222c 100644 --- a/app/javascript/stylesheets/application/blocks/form/_form-tabs.sass +++ b/app/javascript/stylesheets/application/blocks/form/_form-tabs.sass @@ -3,7 +3,8 @@ margin-bottom: 1rem border-bottom: solid 1px var(--border) .a-card > &:first-child, - .a-card__inner > &:first-child + .a-card__inner > &:first-child, + .memo-editor > &:first-child padding-top: 1rem .form-tabs__tab diff --git a/app/views/products/_practice_memo.html.slim b/app/views/products/_practice_memo.html.slim index 0a6b444cf80..4b94e40b30d 100644 --- a/app/views/products/_practice_memo.html.slim +++ b/app/views/products/_practice_memo.html.slim @@ -20,17 +20,18 @@ i.fa-solid.fa-pen | 編集 .memo-editor.is-hidden + .form-tabs.js-tabs + .form-tabs__tab.js-tabs__tab.editor-tab.is-active + | メモ + .form-tabs__tab.js-tabs__tab.preview-tab + | プレビュー .card-body - .form-tabs.js-tabs - .form-tabs__tab.js-tabs__tab.editor-tab.is-active - | メモ - .form-tabs__tab.js-tabs__tab.preview-tab - | プレビュー - .a-markdown-input.js-markdown-parent - .a-markdown-input__inner.is-editor.js-tabs__content.is-active - textarea.a-text-input.a-markdown-input__textarea id='js-practice-memo' data-preview='#practice-memo-preview' name='practice[memo]' - .a-markdown-input__inner.is-preview.js-tabs__content - .a-long-text.a-markdown-input__preview + .card__description + .a-markdown-input.js-markdown-parent + .a-markdown-input__inner.is-editor.js-tabs__content.is-active + textarea.a-text-input.a-markdown-input__textarea id='js-practice-memo' data-preview='#practice-memo-preview' name='practice[memo]' + .a-markdown-input__inner.is-preview.js-tabs__content + .a-long-text.a-markdown-input__preview hr.a-border-tint .card-footer .card-main-actions