Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Data: Add persistence via data plugin interface #8341

Merged
merged 15 commits into from
Aug 3, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 1 addition & 8 deletions edit-post/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*/
import { registerCoreBlocks } from '@wordpress/core-blocks';
import { render, unmountComponentAtNode } from '@wordpress/element';
import { dispatch, setupPersistence } from '@wordpress/data';
import { dispatch } from '@wordpress/data';
import deprecated from '@wordpress/deprecated';

/**
Expand All @@ -15,11 +15,6 @@ import store from './store';
import { initializeMetaBoxState } from './store/actions';
import Editor from './editor';

/**
* Module Constants
*/
const STORAGE_KEY = `WP_EDIT_POST_DATA_${ window.userSettings.uid }`;

/**
* Reinitializes the editor after the user chooses to reboot the editor after
* an unhandled error occurs, replacing previously mounted editor element using
Expand Down Expand Up @@ -93,5 +88,3 @@ export { default as PluginPostStatusInfo } from './components/sidebar/plugin-pos
export { default as PluginPrePublishPanel } from './components/sidebar/plugin-pre-publish-panel';
export { default as PluginSidebar } from './components/sidebar/plugin-sidebar';
export { default as PluginSidebarMoreMenuItem } from './components/header/plugin-sidebar-more-menu-item';

setupPersistence( STORAGE_KEY );
10 changes: 4 additions & 6 deletions edit-post/store/index.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
/**
* WordPress Dependencies
*/
import {
registerStore,
restrictPersistence,
} from '@wordpress/data';
import { registerStore } from '@wordpress/data';

/**
* Internal dependencies
Expand All @@ -13,11 +10,12 @@ import reducer from './reducer';
import applyMiddlewares from './middlewares';
import * as actions from './actions';
import * as selectors from './selectors';

const store = registerStore( 'core/edit-post', {
reducer: restrictPersistence( reducer, 'preferences' ),
reducer,
actions,
selectors,
persist: true,
persist: [ 'preferences' ],
} );

applyMiddlewares( store );
Expand Down
16 changes: 16 additions & 0 deletions lib/client-assets.php
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,22 @@ function gutenberg_register_scripts_and_styles() {
filemtime( gutenberg_dir_path() . 'build/data/index.js' ),
true
);
wp_add_inline_script(
'wp-data',
implode( "\n", array(
// TODO: Transferring old storage should be removed at v3.7.
'( function() {',
' var userId = window.userSettings.uid;',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This simplifies a lot in terms of passing user id to the client 👍

' var oldStorageKey = "WP_EDIT_POST_DATA_" + userId;',
' var storageKey = "WP_DATA_USER_" + userId;',
' if ( localStorage[ oldStorageKey ] ) {',
' localStorage[ storageKey ] = localStorage[ oldStorageKey ];',
' delete localStorage[ oldStorageKey ];',
' }',
' wp.data.use( wp.data.plugins.persistence, { storageKey: storageKey } );',
'} )()',
) )
);
wp_register_script(
'wp-core-data',
gutenberg_url( 'build/core-data/index.js' ),
Expand Down
55 changes: 50 additions & 5 deletions packages/data/src/deprecated.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import deprecated from '@wordpress/deprecated';
/**
* Internal dependencies
*/
import { getPersistenceStorage } from './persist';
import * as persistence from './plugins/persistence';

/**
* Adds the rehydration behavior to redux reducers.
Expand Down Expand Up @@ -63,12 +63,14 @@ export function loadAndPersist( store, reducer, reducerKey, storageKey ) {
hint: 'See https://github.com/WordPress/gutenberg/pull/8146 for more details',
} );

const persist = persistence.createPersistenceInterface( { storageKey } );

// Load initially persisted value
const persistedString = getPersistenceStorage().getItem( storageKey );
if ( persistedString ) {
const persisted = persist.get();
if ( persisted ) {
const persistedState = {
...get( reducer( undefined, { type: '@@gutenberg/init' } ), reducerKey ),
...JSON.parse( persistedString ),
...JSON.parse( persisted ),
};

store.dispatch( {
Expand All @@ -85,7 +87,50 @@ export function loadAndPersist( store, reducer, reducerKey, storageKey ) {
if ( newStateValue !== currentStateValue ) {
currentStateValue = newStateValue;
const stateToSave = get( reducer( store.getState(), { type: 'SERIALIZE' } ), reducerKey );
getPersistenceStorage().setItem( storageKey, JSON.stringify( stateToSave ) );
persist.set( stateToSave );
}
} );
}

/**
* Higher-order reducer used to persist just one key from the reducer state.
*
* @param {function} reducer Reducer function.
* @param {string} keyToPersist The reducer key to persist.
*
* @return {function} Updated reducer.
*/
export function restrictPersistence( reducer, keyToPersist ) {
deprecated( 'wp.data.restrictPersistence', {
alternative: 'registerStore persist option with persistence plugin',
version: '3.7',
plugin: 'Gutenberg',
hint: 'See https://github.com/WordPress/gutenberg/pull/8341 for more details',
} );

reducer.__deprecatedKeyToPersist = keyToPersist;

return reducer;
}

/**
* Sets a different persistence storage.
*
* @param {Object} storage Persistence storage.
*/
export function setPersistenceStorage( storage ) {
deprecated( 'wp.data.setPersistenceStorage', {
alternative: 'persistence plugin with storage option',
version: '3.7',
plugin: 'Gutenberg',
hint: 'See https://github.com/WordPress/gutenberg/pull/8341 for more details',
} );

const originalCreatePersistenceInterface = persistence.createPersistenceInterface;
persistence.createPersistenceInterface = ( options ) => {
originalCreatePersistenceInterface( {
storage,
...options,
} );
};
}
12 changes: 10 additions & 2 deletions packages/data/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,19 @@ import { combineReducers } from 'redux';
* Internal dependencies
*/
import defaultRegistry from './default-registry';
export { restrictPersistence, setPersistenceStorage } from './persist';
import * as plugins from './plugins';

export { default as withSelect } from './components/with-select';
export { default as withDispatch } from './components/with-dispatch';
export { default as RegistryProvider } from './components/registry-provider';
export { createRegistry } from './registry';
export { withRehydration, loadAndPersist } from './deprecated';
export {
withRehydration,
loadAndPersist,
restrictPersistence,
setPersistenceStorage,
} from './deprecated';
export { plugins };

/**
* The combineReducers helper function turns an object whose values are different
Expand All @@ -35,3 +42,4 @@ export const registerActions = defaultRegistry.registerActions;
export const registerSelectors = defaultRegistry.registerSelectors;
export const registerResolvers = defaultRegistry.registerResolvers;
export const setupPersistence = defaultRegistry.setupPersistence;
export const use = defaultRegistry.use;
83 changes: 0 additions & 83 deletions packages/data/src/persist.js

This file was deleted.

17 changes: 17 additions & 0 deletions packages/data/src/plugins/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Data Plugins
============

Included here are a set of default plugin integrations for the WordPress data module.

## Usage

For any of the plugins included here as directories, call the `use` method to include its behaviors in the registry.

```js
// npm Usage
import { plugins, use } from '@wordpress/data';
use( plugins.persistence );

// WordPress Globals Usage
wp.data.use( wp.data.plugins.persistence );
```
1 change: 1 addition & 0 deletions packages/data/src/plugins/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as persistence } from './persistence';
36 changes: 36 additions & 0 deletions packages/data/src/plugins/persistence/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
Persistence Plugin
==================

The persistence plugin enhances a registry to enable registered stores to opt in to persistent storage.

By default, persistence occurs by [`localStorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage). This can be changed using the [`setStorage` function](#api) defined on the plugin. Unless set otherwise, state will be persisted on the `WP_DATA` key in storage.

## Usage

Call the `use` method on the default or your own registry to include the persistence plugin:

```js
wp.data.use( wp.data.plugins.persistence, { storageKey: 'example' } );
```

Then, when registering a store, set a `persist` property as `true` (persist all state) or an array of state keys to persist.

```js
wp.data.registerStore( 'my-plugin', {
// ...

persist: [ 'preferences' ],
} );
```

## Options

### `storage`

Persistent storage implementation. This must at least implement `getItem` and `setItem` of the Web Storage API.

See: https://developer.mozilla.org/en-US/docs/Web/API/Storage

### `storageKey`

The key on which to set in persistent storage.
Loading