Add: load autosaved comments

This commit is contained in:
Raphael Beer 2020-04-10 17:06:03 +02:00
parent 828f79b6f3
commit 455771264e
No known key found for this signature in database
GPG Key ID: C1AC5E018B25EF11
3 changed files with 65 additions and 22 deletions

View File

@ -31,15 +31,15 @@ describe('Editor.vue', () => {
}))
}
beforeEach(() => {
propsData = {}
mocks = {
$t: () => 'some cool placeholder',
}
wrapper = Wrapper()
})
describe('mount', () => {
beforeEach(() => {
propsData = {}
mocks = {
$t: () => 'some cool placeholder',
}
wrapper = Wrapper()
})
it('renders', () => {
expect(Wrapper().is('div')).toBe(true)
})
@ -149,7 +149,7 @@ describe('Editor.vue', () => {
})
describe(':autosave', () => {
const getFirst = () => {
const getFirstInStorage = () => {
const storageKey = Object.keys(localStorage)[0]
const value = localStorage[storageKey]
return {
@ -165,9 +165,16 @@ describe('Editor.vue', () => {
let routerWrapper
beforeEach(() => {
propsData = {}
mocks = {
$t: (key) => key,
}
router = new VueRouter({
routes: [{ path: 'post/create' }],
})
mocks = {
$t: (key) => key,
}
router.push('/post/create')
propsData.autosave = false
routerWrapper = Wrapper()
@ -187,6 +194,10 @@ describe('Editor.vue', () => {
const content = '<p>Post WIP</p>'
beforeEach(async () => {
propsData = {}
mocks = {
$t: (key) => key,
}
router = new VueRouter({
routes: [{ path: 'post/create' }],
})
@ -201,7 +212,7 @@ describe('Editor.vue', () => {
})
it('saves editor content to localStorage on input', async () => {
const { storageKey, value } = getFirst()
const { storageKey, value } = getFirstInStorage()
expect(storageKey.startsWith('draft:post:')).toBe(true)
expect(value).toBe(content)
})
@ -212,6 +223,10 @@ describe('Editor.vue', () => {
const content = '<p>Comment WIP</p>'
beforeEach(async () => {
propsData = {}
mocks = {
$t: (key) => key,
}
router = new VueRouter({
routes: [{ path: `/post/${postId}/foo-title-slug` }],
})
@ -221,15 +236,21 @@ describe('Editor.vue', () => {
await jest.runAllTimers()
})
afterEach(() => {
afterAll(() => {
localStorage.clear()
})
it('saves editor content to localStorage on input', async () => {
const { storageKey, value } = getFirst()
const { storageKey, value } = getFirstInStorage()
expect(storageKey).toBe(`draft:${postId}`)
expect(value).toBe(content)
})
it('loads an existing autosave', () => {
const { value: autoSaveHTML } = getFirstInStorage()
const _wrapper = Wrapper()
expect(_wrapper.vm.editor.getHTML()).toBe(autoSaveHTML)
})
})
})
})

View File

@ -29,6 +29,9 @@ import { replace, build } from 'xregexp/xregexp-all.js'
import * as key from '../../constants/keycodes'
import { HASHTAG, MENTION } from '../../constants/editor'
import defaultExtensions from './defaultExtensions.js'
import AutoSave from './plugins/autoSave.js'
import EventHandler from './plugins/eventHandler.js'
import Hashtag from './nodes/Hashtag.js'
import Mention from './nodes/Mention.js'
@ -50,9 +53,12 @@ export default {
props: {
users: { type: Array, default: () => null }, // If 'null', than the Mention extention is not assigned.
hashtags: { type: Array, default: () => null }, // If 'null', than the Hashtag extention is not assigned.
value: { type: String, default: '' },
doc: { type: Object, default: () => {} },
autosave: { type: Boolean, default: true },
value: {
type: String,
default: '',
},
},
data() {
return {
@ -106,6 +112,9 @@ export default {
}
return extensions
},
autosaveContent() {
return this.autosave && this.$route ? AutoSave.load(this.$route.path) : ''
},
},
watch: {
placeholder: {
@ -120,7 +129,7 @@ export default {
},
mounted() {
this.editor = new Editor({
content: this.value || '',
content: this.value || this.autosaveContent || '',
doc: this.doc,
extensions: [
// Hashtags must come first, see

View File

@ -5,7 +5,6 @@ export default class AutoSave extends Extension {
constructor({ $route }) {
super()
this.route = $route
this._postId = 'randomIdForPosts'
}
static toHTML(content, schema) {
@ -15,16 +14,22 @@ export default class AutoSave extends Extension {
return container.innerHTML
}
get name() {
return 'auto_save'
static load(path) {
const key = AutoSave.getStorageKey(path)
return key ? localStorage[key] : null
}
get storageKey() {
if (this.route.path === '/post/create') {
return `draft:post:${this._postId}`
static getStorageKey(path) {
if (path === '/post/create') {
// find a way to keep invisible random ids
// for posts.
// Once a draft is sent, the storage item
// is deleted.
const _postId = 'randomPostId'
return `draft:post:${_postId}`
}
const commentMatch = this.route.path.match(/^\/post\/([0-9a-f-]*)\/[\w-]*$/)
const commentMatch = path.match(/^\/post\/([0-9a-f-]*)\/[\w-]*$/)
if (commentMatch) {
const key = `draft:${commentMatch[1]}`
return key
@ -33,12 +38,20 @@ export default class AutoSave extends Extension {
return null
}
get name() {
return 'auto_save'
}
get storageKey() {
return AutoSave.getStorageKey(this.route.path)
}
get plugins() {
return [
new Plugin({
key: new PluginKey('auto_save'),
filterTransaction: (tr, editorState) => {
if (tr.docChanged) {
if (tr.docChanged && this.storageKey) {
localStorage.setItem(
this.storageKey,
AutoSave.toHTML(tr.doc.content, editorState.config.schema),