Add: different behavior when editing a post

This commit is contained in:
Raphael Beer 2020-04-13 18:06:09 +02:00
parent 82b9f5cf0e
commit f44a4c3067
No known key found for this signature in database
GPG Key ID: C1AC5E018B25EF11
4 changed files with 84 additions and 19 deletions

View File

@ -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 = {
// <hc-editor :autosave="false" />
// <hc-editor :autosave="false|true" />
// 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 = '<p>Post WIP</p>'
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 = '<p>Post WIP</p>'
const content = '<p>Post WIP autosaved</p>'
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 = '<p>Comment WIP</p>'
@ -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)
})

View File

@ -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: {

View File

@ -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
},

View File

@ -67,7 +67,7 @@ const helpers = {
</base-card>
`,
}
}
},
}
export default helpers