diff --git a/src/dom_components/index.js b/src/dom_components/index.js index c4a66558a..9fda0b1c5 100644 --- a/src/dom_components/index.js +++ b/src/dom_components/index.js @@ -290,10 +290,13 @@ export default () => { load(data) { return this.loadProjectData(data, { onResult: result => { + const wrapper = this.getWrapper(); if (isArray(result)) { - result.length && this.getComponents().reset(result); + result.length && wrapper.components(result); } else { - this.getWrapper().set(result); + const { components = [], ...rest } = result; + wrapper.set(rest); + wrapper.components(components); } }, }); diff --git a/src/editor/index.js b/src/editor/index.js index 8653d843b..fbf4184f9 100644 --- a/src/editor/index.js +++ b/src/editor/index.js @@ -430,22 +430,28 @@ export default (config = {}, opts = {}) => { }, /** - * Store data to the current storage - * @param {Function} clb Callback function - * @return {Object} Stored data + * Store data to the current storage. + * @param {Function} [resolve] Resolve callback function. + * @param {Function} [reject] Reject callback function. The error is passed as an argument. + * @param {Object} [options] Storage options. + * @example + * editor.store( + * () => console.log('Project stored'), + * (err) => console.error('Store error', err), + * ); */ - store(clb) { - return em.store(clb); + store(resolve, reject, options) { + return em.store(resolve, reject, options); }, /** - * Get the JSON project data, which could be stored and loaded back with `editor.loadProject(json)` + * Get the JSON project data, which could be stored and loaded back with `editor.loadProjectData(json)` * @returns {Object} * @example - * console.log(editor.getProject()); + * console.log(editor.getProjectData()); * // { pages: [...], styles: [...], ... } */ - getProject() { + getProjectData() { return em.storeData(); }, @@ -454,21 +460,27 @@ export default (config = {}, opts = {}) => { }, /** - * Load data from the current storage - * @param {Function} clb Callback function - * @return {Object} Stored data + * Load data from the current storage. + * @param {Function} [resolve] Resolve callback function. + * @param {Function} [reject] Reject callback function. The error is passed as an argument. + * @param {Object} [options] Storage options. + * @example + * editor.load( + * () => console.log('Project loaded'), + * (err) => console.error('Load error', err), + * ); */ - load(clb) { - return em.load(clb); + load(resolve, reject, options) { + return em.load(resolve, reject, options); }, /** * Load data from the JSON project * @param {Object} data Project to load * @example - * editor.loadProject({ pages: [...], styles: [...], ... }) + * editor.loadProjectData({ pages: [...], styles: [...], ... }) */ - loadProject(data) { + loadProjectData(data) { return em.loadData(data); }, diff --git a/src/editor/model/Editor.js b/src/editor/model/Editor.js index 2a565fb58..7c760fe99 100644 --- a/src/editor/model/Editor.js +++ b/src/editor/model/Editor.js @@ -133,10 +133,9 @@ export default class EditorModel extends Model { /** * Should be called once all modules and plugins are loaded - * @param {Function} clb * @private */ - loadOnStart(clb = null) { + loadOnStart() { const sm = this.get('StorageManager'); // In `onLoad`, the module will try to load the data from its configurations. @@ -147,14 +146,16 @@ export default class EditorModel extends Model { const modules = this.get('modules'); modules.forEach(mdl => mdl.postLoad && mdl.postLoad(this)); this.set('readyLoad', 1); - clb && clb(); }; - if (sm && sm.canAutoload()) { - this.load(postLoad); - } else { - setTimeout(postLoad); - } + // Defer for storage load events. + setTimeout(() => { + if (sm && sm.canAutoload()) { + this.load(postLoad, error => this.logError(error)); + } else { + postLoad(); + } + }); // Create shallow editor. // Here we can create components/styles without altering/triggering the main EditorModel @@ -607,23 +608,24 @@ export default class EditorModel extends Model { /** * Store data to the current storage - * @param {Function} clb Callback function - * @return {Object} Stored data + * @param {Function} [resolve] Resolve callback function. The result is passed as an argument. + * @param {Function} [reject] Reject callback function. The error is passed as an argument. + * @param {Object} [options] Storage options. * @private */ - store(opts) { + store(resolve, reject, options) { const sm = this.get('StorageManager'); if (!sm) return; - const isCallback = isFunction(opts); - const toStore = this.storeData(); - sm.store(toStore, res => { - isCallback && opts(res, toStore); - this.set('changesCount', 0); - this.trigger('storage:store', toStore); - }); - - return toStore; + return sm.store( + this.storeData(), + res => { + resolve?.(res); + this.set('changesCount', 0); + }, + reject, + options + ); } storeData() { @@ -640,54 +642,28 @@ export default class EditorModel extends Model { /** * Load data from the current storage - * @param {Function} clb Callback function + * @param {Function} [resolve] Resolve callback function. The result is passed as an argument. + * @param {Function} [reject] Reject callback function. The error is passed as an argument. + * @param {Object} [options] Storage options. * @private */ - load(clb = null) { - this.getCacheLoad(1, res => { - this.loadData(res); - clb && clb(res); - }); - } - - loadData(data = {}) { + load(resolve, reject, options) { const sm = this.get('StorageManager'); - const result = sm.__clearKeys(data); - - this.get('storables').forEach(module => { - module.load(result); - module.postLoad && module.postLoad(this); - }); + if (!sm) return; - return result; + return sm.load( + res => { + this.loadData(res); + resolve?.(res); + }, + reject, + options + ); } - /** - * Returns cached load - * @param {Boolean} force Force to reload - * @param {Function} clb Callback function - * @return {Object} - * @private - */ - getCacheLoad(force, clb) { - if (this.cacheLoad && !force) return this.cacheLoad; - const sm = this.get('StorageManager'); - const load = []; - - if (!sm) return {}; - - this.get('storables').forEach(m => { - let key = m.storageKey; - key = isFunction(key) ? key() : key; - const keys = isArray(key) ? key : [key]; - keys.forEach(k => load.push(k)); - }); - - sm.load(res => { - this.cacheLoad = res; - clb && clb(res); - setTimeout(() => this.trigger('storage:load', res)); - }); + loadData(data = {}) { + this.get('storables').forEach(module => module.load(data)); + return data; } /** diff --git a/src/storage_manager/index.js b/src/storage_manager/index.js index 884dcca77..401fef12e 100644 --- a/src/storage_manager/index.js +++ b/src/storage_manager/index.js @@ -215,8 +215,9 @@ export default () => { /** * Store data in the current storage. * @param {Object} data Data in key-value format, eg. `{ item1: value1, item2: value2 }` - * @param {Function} resolve Resolve callback function. The result is passed as an argument. - * @param {Function} reject Reject callback function. The error is passed as an argument. + * @param {Function} [resolve] Resolve callback function. + * @param {Function} [reject] Reject callback function. The error is passed as an argument. + * @param {Object} [options] Storage options. * @example * storageManager.store({item1: value1, item2: value2}); * */ @@ -226,6 +227,8 @@ export default () => { const opts = { ...this.getCurrentOptons(), ...options }; this.onStart(ev, data); + if (!st) return null; + const onResult = res => { this.onAfter(ev, res); resolve?.(res); @@ -237,13 +240,14 @@ export default () => { this.onError(ev, err); }; - return st ? st.store(data, onResult, onError, opts) : null; + return await st.store(data, onResult, onError, opts); }, /** * Load resource from the current storage by keys - * @param {Function} resolve Resolve callback function. The result is passed as an argument. - * @param {Function} reject Reject callback function. The error is passed as an argument. + * @param {Function} [resolve] Resolve callback function. The result is passed as an argument. + * @param {Function} [reject] Reject callback function. The error is passed as an argument. + * @param {Object} [options] Storage options. * @example * storageManager.load(res => { * // res -> {item1: value1, item2: value2} @@ -256,6 +260,8 @@ export default () => { let result = {}; this.onStart(ev); + if (!st) return resolve(result); + const onResult = res => { result = this.__clearKeys(res); this.onAfter(ev, result); @@ -268,7 +274,7 @@ export default () => { this.onError(ev, err); }; - return st ? st.load(onResult, onError, opts) : resolve(result); + return await st.load(onResult, onError, opts); }, /** @@ -331,7 +337,8 @@ export default () => { onAfter(ctx, data) { if (em) { em.trigger(eventAfter); - ctx && em.trigger(`${eventAfter}:${ctx}`, data); + em.trigger(`${eventAfter}:${ctx}`, data); + em.trigger(`storage:${ctx}`, data); } }, diff --git a/src/storage_manager/model/LocalStorage.js b/src/storage_manager/model/LocalStorage.js index 51f8ffbf9..e629617b9 100644 --- a/src/storage_manager/model/LocalStorage.js +++ b/src/storage_manager/model/LocalStorage.js @@ -15,7 +15,7 @@ export default Model.extend({ try { if (this.hasLocal()) { localStorage.setItem(opts.key, JSON.stringify(data)); - return resolve(); + return resolve(data); } else { reject(noLocalStorage); }