From f44a4c3067f3ef68e0f52263c6bf83bf21fe1638 Mon Sep 17 00:00:00 2001 From: Raphael Beer Date: Mon, 13 Apr 2020 18:06:09 +0200 Subject: [PATCH] Add: different behavior when editing a post --- webapp/components/Editor/Editor.spec.js | 64 ++++++++++++++++++-- webapp/components/Editor/Editor.vue | 2 +- webapp/components/Editor/plugins/autoSave.js | 35 +++++++---- webapp/storybook/helpers.js | 2 +- 4 files changed, 84 insertions(+), 19 deletions(-) diff --git a/webapp/components/Editor/Editor.spec.js b/webapp/components/Editor/Editor.spec.js index 149124d44..f23796622 100644 --- a/webapp/components/Editor/Editor.spec.js +++ b/webapp/components/Editor/Editor.spec.js @@ -1,6 +1,7 @@ import Vue from 'vue' import VueRouter from 'vue-router' import { mount } from '@vue/test-utils' +import { h32 as hash } from 'xxhashjs' import MutationObserver from 'mutation-observer' import Editor from './Editor' @@ -166,7 +167,7 @@ describe('Editor.vue', () => { beforeEach(async () => { propsData = { - // + // // plugin ignores all changes (transactions) on this instance // autosave: false (default) } @@ -187,7 +188,7 @@ describe('Editor.vue', () => { }) }) - describe('when editing a post', () => { + describe('when creating a post', () => { const content = '

Post WIP

' beforeEach(async () => { @@ -219,21 +220,72 @@ describe('Editor.vue', () => { it('generates a temporary id for the post', () => { const { storageKey } = getFirstInStorage() - expect(storageKey).toMatch(/^autosave:post:[a-f\d]{8}$/) + expect(storageKey).toMatch(/^autosave:post:[a-f\d]{7,8}$/) }) it('stores temporary id of last edit', () => { const lastEditedId = localStorage.getItem('autosave:post:last') - expect(lastEditedId).toMatch(/^[a-f\d]{8}$/) + expect(lastEditedId).toMatch(/^[a-f\d]{7,8}$/) }) it('loads last edited autosave', () => { const wrapper = Wrapper() - const { value: autosaveHTML } = getFirstInStorage() + const lastId = localStorage.getItem('autosave:post:last') + const autosaveHTML = localStorage.getItem(`autosave:post:${lastId}`) expect(wrapper.vm.editor.getHTML()).toBe(autosaveHTML) }) }) + describe('when editing a post', () => { + const contentValue = '

Post WIP

' + const content = '

Post WIP autosaved

' + const postId = '4b3de466-ddab-487f-bd82-2839280bb56c' + const hashedPostId = hash(postId, 0xb0b).toString(16) + + beforeEach(async () => { + propsData = { + autosave: true, + value: contentValue, + } + mocks = { + $t: (t) => t, + } + + // plugin creates storage ids from $route.path + router = new VueRouter({ + routes: [{ path: `/post/edit/${postId}}` }], + }) + router.push(`/post/edit/${postId}`) + + Wrapper().vm.editor.setContent(content, true) + await jest.runAllTimers() + }) + + afterAll(() => { + localStorage.clear() + }) + + it('saves editor content to localStorage on input', async () => { + const { value } = getFirstInStorage() + expect(value).toBe(content) + }) + + it("uses post's id for storageKey", () => { + const { storageKey } = getFirstInStorage() + expect(storageKey).toBe(`autosave:post:${hashedPostId}`) + }) + + it('does not mark itself as last edit', () => { + const lastEditedId = localStorage.getItem('autosave:post:last') + expect(lastEditedId).not.toBe(hashedPostId) + }) + + it('does not load the autosave', () => { + const wrapper = Wrapper() + expect(wrapper.vm.editor.getHTML()).toBe(contentValue) + }) + }) + describe('when editing a comment', () => { const postId = '33739246-fa27-42ae-94de-2f590a2d92c4' const content = '

Comment WIP

' @@ -259,7 +311,7 @@ describe('Editor.vue', () => { it('saves editor content to localStorage on input', async () => { const { storageKey, value } = getFirstInStorage() - expect(storageKey).toMatch(/autosave:comment:[a-f\d]{8}/) + expect(storageKey).toMatch(/autosave:comment:[a-f\d]{7,8}/) expect(value).toBe(content) }) diff --git a/webapp/components/Editor/Editor.vue b/webapp/components/Editor/Editor.vue index 137ab669c..2e33b5400 100644 --- a/webapp/components/Editor/Editor.vue +++ b/webapp/components/Editor/Editor.vue @@ -113,7 +113,7 @@ export default { return extensions }, autosaveContent() { - return this.autosave && this.$route ? AutoSave.load(this.$route.path) : '' + return this.autosave && this.$route ? AutoSave.lastSave(this.$route.path) : '' }, }, watch: { diff --git a/webapp/components/Editor/plugins/autoSave.js b/webapp/components/Editor/plugins/autoSave.js index a839b6a95..be3a5f337 100644 --- a/webapp/components/Editor/plugins/autoSave.js +++ b/webapp/components/Editor/plugins/autoSave.js @@ -10,19 +10,26 @@ export default class AutoSave extends Extension { const { id = hash(Date.now().toString(), 0xb0b).toString(16), editorType = this.route.path, + mode = null, } = AutoSave.fromPath(this.route.path) this.id = id this.editorType = editorType + this.mode = mode } static fromPath(path) { - if (path === '/post/create') { - return { editorType: 'post' } + let [, editorType, mode, postId] = + path.match(/^\/?(post)\/(?:(create|edit)\/?)([a-f\d-]*)?$/) || [] + + if (editorType) { + postId = postId || Date.now().toString() + return { editorType, mode, id: hash(postId, 0xb0b).toString(16) } } - const commentMatch = path.match(/^\/post\/([0-9a-f-]*)\/[\w-]*$/) - if (commentMatch) { - return { editorType: 'comment', id: hash(commentMatch[1], 0xb0b).toString(16) } + const [, commentPostId] = path.match(/^\/post\/([a-f\d-]*)\/[\w-]*$/) || [] + + if (commentPostId) { + return { editorType: 'comment', id: hash(commentPostId, 0xb0b).toString(16) } } return {} @@ -35,13 +42,16 @@ export default class AutoSave extends Extension { return container.innerHTML } - static load(path) { - const { id, editorType = path } = AutoSave.fromPath(path) - const _id = localStorage.getItem(`autosave:${editorType}:last`) - if (!_id) { + static lastSave(path) { + let { mode, editorType = path } = AutoSave.fromPath(path) + + const id = localStorage.getItem(`autosave:${editorType}:last`) + + if (mode === 'edit' || !id) { return null } - const key = AutoSave.getStorageKey(_id, editorType) + + const key = AutoSave.getStorageKey(id, editorType) return localStorage[key] } @@ -67,7 +77,10 @@ export default class AutoSave extends Extension { this.storageKey, AutoSave.toHTML(tr.doc.content, editorState.config.schema), ) - localStorage.setItem(`autosave:${this.editorType}:last`, this.id) + + if (this.mode !== 'edit') { + localStorage.setItem(`autosave:${this.editorType}:last`, this.id) + } } return tr }, diff --git a/webapp/storybook/helpers.js b/webapp/storybook/helpers.js index aa51e162f..b5fef91f5 100644 --- a/webapp/storybook/helpers.js +++ b/webapp/storybook/helpers.js @@ -67,7 +67,7 @@ const helpers = { `, } - } + }, } export default helpers