mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-11-28 05:37:34 +03:00
🐛 Fixed existing snippets not being available in beta editor
closes https://github.com/TryGhost/Team/issues/3387 - adds syncing of mobiledoc->lexical formats for snippets when opening the beta editor - this is a one-way sync - new snippets or changes made to snippets inside the beta will not be available in the old editor - creating or changing snippets in the old editor will sync to (and potentially overwrite snippets) in the beta editor - fixed incorrect saving of doubly-escaped JSON when creating snippets in the beta editor
This commit is contained in:
parent
7170b2489e
commit
ed24899fa5
@ -15,6 +15,10 @@ export default class UpdateSnippetModal extends Component {
|
||||
}
|
||||
if (lexical) {
|
||||
snippet.lexical = lexical;
|
||||
|
||||
if (!snippet.mobiledoc) {
|
||||
snippet.mobiledoc = {};
|
||||
}
|
||||
}
|
||||
|
||||
yield snippet.save();
|
||||
|
@ -173,8 +173,8 @@ export default class EditorController extends Controller {
|
||||
get snippets() {
|
||||
return this._snippets
|
||||
.reject(snippet => snippet.get('isNew'))
|
||||
.sort((a, b) => a.name.localeCompare(b.name))
|
||||
.filterBy('lexical', null);
|
||||
.reject(snippet => JSON.stringify(snippet.mobiledoc) === '{}')
|
||||
.sort((a, b) => a.name.localeCompare(b.name));
|
||||
}
|
||||
|
||||
@computed('session.user.{isAdmin,isEditor}')
|
||||
|
@ -22,6 +22,7 @@ import {isBlank} from '@ember/utils';
|
||||
import {isArray as isEmberArray} from '@ember/array';
|
||||
import {isHostLimitError, isServerUnreachableError, isVersionMismatchError} from 'ghost-admin/services/ajax';
|
||||
import {isInvalidError} from 'ember-ajax/errors';
|
||||
import {mobiledocToLexical} from '@tryghost/kg-converters';
|
||||
import {inject as service} from '@ember/service';
|
||||
|
||||
const DEFAULT_TITLE = '(Untitled)';
|
||||
@ -171,14 +172,15 @@ export default class LexicalEditorController extends Controller {
|
||||
return this.store.peekAll('snippet');
|
||||
}
|
||||
|
||||
@computed('_snippets.@each.{name,isNew}')
|
||||
@computed('_snippets.@each.{name,isNew,mobiledoc,lexical}')
|
||||
get snippets() {
|
||||
const snippets = this._snippets
|
||||
.reject(snippet => snippet.get('isNew'))
|
||||
.sort((a, b) => a.name.localeCompare(b.name))
|
||||
.filter(item => item.lexical !== null);
|
||||
|
||||
return snippets.map((item) => {
|
||||
item.value = item.lexical;
|
||||
item.value = JSON.stringify(item.lexical);
|
||||
|
||||
return item;
|
||||
});
|
||||
@ -360,9 +362,10 @@ export default class LexicalEditorController extends Controller {
|
||||
}
|
||||
|
||||
@action
|
||||
saveSnippet(snippet) {
|
||||
const snippetData = {name: snippet.name, lexical: snippet.value, mobiledoc: '{}'};
|
||||
let snippetRecord = this.store.createRecord('snippet', snippetData);
|
||||
saveNewSnippet(snippet) {
|
||||
const snippetData = {name: snippet.name, lexical: JSON.parse(snippet.value), mobiledoc: {}};
|
||||
const snippetRecord = this.store.createRecord('snippet', snippetData);
|
||||
|
||||
return snippetRecord.save().then(() => {
|
||||
this.notifications.closeAlerts('snippet.save');
|
||||
this.notifications.showNotification(
|
||||
@ -388,9 +391,9 @@ export default class LexicalEditorController extends Controller {
|
||||
const existingSnippet = this.snippets.find(snippet => snippet.name.toLowerCase() === snippetNameLC);
|
||||
|
||||
if (existingSnippet) {
|
||||
await this.confirmUpdateSnippet(existingSnippet, {lexical: data.value, mobiledoc: '{}'});
|
||||
await this.confirmUpdateSnippet(existingSnippet, {lexical: data.value});
|
||||
} else {
|
||||
await this.saveSnippet(data);
|
||||
await this.saveNewSnippet(data);
|
||||
}
|
||||
}
|
||||
|
||||
@ -771,10 +774,46 @@ export default class LexicalEditorController extends Controller {
|
||||
}
|
||||
}
|
||||
|
||||
// load supplementel data such as the members count in the background
|
||||
// load supplemental data such as snippets and members count in the background
|
||||
@restartableTask
|
||||
*backgroundLoaderTask() {
|
||||
yield this.store.query('snippet', {limit: 'all'});
|
||||
this.syncMobiledocSnippets();
|
||||
}
|
||||
|
||||
@action
|
||||
syncMobiledocSnippets() {
|
||||
const snippets = this.store.peekAll('snippet');
|
||||
|
||||
snippets.forEach((snippet) => {
|
||||
if (!snippet.lexical || snippet.lexical.syncedAt && moment.utc(snippet.lexical.syncedAt).isBefore(snippet.updatedAtUTC)) {
|
||||
const serializedLexical = mobiledocToLexical(JSON.stringify(snippet.mobiledoc));
|
||||
|
||||
// we get a full Lexical doc from the converter but Lexical only
|
||||
// stores an array of nodes in it's copy/paste dataset that we use for snippets
|
||||
const lexical = JSON.parse(serializedLexical);
|
||||
let nodes = lexical.root.children;
|
||||
|
||||
// for a single-paragraph text selection Lexical only stores the
|
||||
// text children in the nodes array
|
||||
if (nodes.length === 1 && nodes[0].type === 'paragraph') {
|
||||
nodes = nodes[0].children;
|
||||
}
|
||||
|
||||
const lexicalData = {
|
||||
namespace: 'KoenigEditor',
|
||||
nodes
|
||||
};
|
||||
|
||||
// set syncedAt so we can check if mobiledoc has been updated in next sync
|
||||
lexicalData.syncedAt = moment.utc().toISOString();
|
||||
|
||||
snippet.lexical = lexicalData;
|
||||
|
||||
// kick off a background save, we already have .lexical updated which is what we need
|
||||
snippet.save();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* Public methods --------------------------------------------------------*/
|
||||
|
8
ghost/admin/app/serializers/snippet.js
Normal file
8
ghost/admin/app/serializers/snippet.js
Normal file
@ -0,0 +1,8 @@
|
||||
import ApplicationSerializer from 'ghost-admin/serializers/application';
|
||||
|
||||
export default class PostSerializer extends ApplicationSerializer {
|
||||
attrs = {
|
||||
createdAtUTC: {key: 'created_at'},
|
||||
updatedAtUTC: {key: 'updated_at'}
|
||||
};
|
||||
}
|
Loading…
Reference in New Issue
Block a user