diff --git a/bin/update-readmes.js b/bin/update-readmes.js
index 63d041e7ab509..7d96e68adce03 100755
--- a/bin/update-readmes.js
+++ b/bin/update-readmes.js
@@ -17,6 +17,7 @@ const packages = [
'Autogenerated selectors': 'src/selectors.js',
} ],
'data',
+ 'data-controls',
'date',
'deprecated',
'dom',
diff --git a/docs/manifest-devhub.json b/docs/manifest-devhub.json
index 09544a23854c3..2095e773664bb 100644
--- a/docs/manifest-devhub.json
+++ b/docs/manifest-devhub.json
@@ -1079,6 +1079,12 @@
"markdown_source": "../packages/custom-templated-path-webpack-plugin/README.md",
"parent": "packages"
},
+ {
+ "title": "@wordpress/data-controls",
+ "slug": "packages-data-controls",
+ "markdown_source": "../packages/data-controls/README.md",
+ "parent": "packages"
+ },
{
"title": "@wordpress/data",
"slug": "packages-data",
diff --git a/docs/manifest.json b/docs/manifest.json
index 594d3504a50dc..429fd5bc835ae 100644
--- a/docs/manifest.json
+++ b/docs/manifest.json
@@ -287,6 +287,12 @@
"markdown_source": "https://raw.githubusercontent.com/WordPress/gutenberg/master/packages/custom-templated-path-webpack-plugin/README.md",
"parent": "packages"
},
+ {
+ "title": "@wordpress/data-controls",
+ "slug": "packages-data-controls",
+ "markdown_source": "https://raw.githubusercontent.com/WordPress/gutenberg/master/packages/data-controls/README.md",
+ "parent": "packages"
+ },
{
"title": "@wordpress/data",
"slug": "packages-data",
diff --git a/package-lock.json b/package-lock.json
index 787fab54e81be..2b1826f94d929 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -3107,6 +3107,13 @@
"turbo-combine-reducers": "^1.0.2"
}
},
+ "@wordpress/data-controls": {
+ "version": "file:packages/data-controls",
+ "requires": {
+ "@wordpress/api-fetch": "file:packages/api-fetch",
+ "@wordpress/data": "file:packages/data"
+ }
+ },
"@wordpress/date": {
"version": "file:packages/date",
"requires": {
@@ -3245,6 +3252,7 @@
"@wordpress/compose": "file:packages/compose",
"@wordpress/core-data": "file:packages/core-data",
"@wordpress/data": "file:packages/data",
+ "@wordpress/data-controls": "file:packages/data-controls",
"@wordpress/date": "file:packages/date",
"@wordpress/deprecated": "file:packages/deprecated",
"@wordpress/element": "file:packages/element",
diff --git a/package.json b/package.json
index c9474bcfdc3e5..f43c1e4cf0864 100644
--- a/package.json
+++ b/package.json
@@ -28,6 +28,7 @@
"@wordpress/compose": "file:packages/compose",
"@wordpress/core-data": "file:packages/core-data",
"@wordpress/data": "file:packages/data",
+ "@wordpress/data-controls": "file:packages/data-controls",
"@wordpress/date": "file:packages/date",
"@wordpress/deprecated": "file:packages/deprecated",
"@wordpress/dom": "file:packages/dom",
diff --git a/packages/data-controls/CHANGELOG.md b/packages/data-controls/CHANGELOG.md
new file mode 100644
index 0000000000000..dff204f06c92d
--- /dev/null
+++ b/packages/data-controls/CHANGELOG.md
@@ -0,0 +1,3 @@
+# Master
+
+Initial release of the @wordpress/data-controls package.
diff --git a/packages/data-controls/README.md b/packages/data-controls/README.md
new file mode 100644
index 0000000000000..08b822fe67967
--- /dev/null
+++ b/packages/data-controls/README.md
@@ -0,0 +1,136 @@
+# Data Controls
+
+The data controls module is a module intended to simplify implementation of common controls used with the [`@wordpress/data`](/packages/data/README.md) package.
+
+**Note:** It is assumed that the registry being used has the controls plugin enabled on it (see [more details on controls here](https://github.com/WordPress/gutenberg/tree/master/packages/data#controls))
+
+## Installation
+
+Install the module
+
+```bash
+npm install @wordpress/data-controls --save
+```
+
+ _This package assumes that your code will run in an **ES2015+** environment. If you're using an environment that has limited or no support for ES2015+ such as lower versions of IE then using [core-js](https://github.com/zloirock/core-js) or [@babel/polyfill](https://babeljs.io/docs/en/next/babel-polyfill) will add support for these methods. Learn more about it in [Babel docs](https://babeljs.io/docs/en/next/caveats)._
+
+The following controls are available on the object returned by the module:
+
+## API
+
+
+
+# **apiFetch**
+
+Dispatches a control action for triggering an api fetch call.
+
+_Usage_
+
+```js
+import { apiFetch } from '@wordpress/data-controls';
+
+// Action generator using apiFetch
+export function* myAction {
+ const path = '/v2/my-api/items';
+ const items = yield apiFetch( { path } );
+ // do something with the items.
+}
+```
+
+_Parameters_
+
+- _request_ `Object`: Arguments for the fetch request.
+
+_Returns_
+
+- `Object`: The control descriptor.
+
+# **controls**
+
+The default export is what you use to register the controls with your custom
+store.
+
+_Usage_
+
+```js
+// WordPress dependencies
+import { controls } from '@wordpress/data-controls';
+import { registerStore } from '@wordpress/data';
+
+// Internal dependencies
+import reducer from './reducer';
+import * as selectors from './selectors';
+import * as actions from './actions';
+import * as resolvers from './resolvers';
+
+registerStore ( 'my-custom-store', {
+ reducer,
+ controls,
+ actions,
+ selectors,
+ resolvers,
+} );
+```
+
+_Returns_
+
+- `Object`: An object for registering the default controls with the store.
+
+# **dispatch**
+
+Dispatches a control action for triggering a registry dispatch.
+
+_Usage_
+
+```js
+import { dispatch } from '@wordpress/data-controls';
+
+// Action generator using dispatch
+export function* myAction {
+ yield dispatch( 'core/edit-post' ).togglePublishSidebar();
+ // do some other things.
+}
+```
+
+_Parameters_
+
+- _storeKey_ `string`: The key for the store the action belongs to
+- _actionName_ `string`: The name of the action to dispatch
+- _args_ `Array`: Arguments for the dispatch action.
+
+_Returns_
+
+- `Object`: The control descriptor.
+
+# **select**
+
+Dispatches a control action for triggering a registry select.
+
+Note: when this control action is handled, it automatically considers
+selectors that may have a resolver. It will await and return the resolved
+value when the selector has not been resolved yet.
+
+_Usage_
+
+```js
+import { select } from '@wordpress/data-controls';
+
+// Action generator using select
+export function* myAction {
+ const isSidebarOpened = yield select( 'core/edit-post', 'isEditorSideBarOpened' );
+ // do stuff with the result from the select.
+}
+```
+
+_Parameters_
+
+- _storeKey_ `string`: The key for the store the selector belongs to
+- _selectorName_ `string`: The name of the selector
+- _args_ `Array`: Arguments for the select.
+
+_Returns_
+
+- `Object`: The control descriptor.
+
+
+
diff --git a/packages/data-controls/package.json b/packages/data-controls/package.json
new file mode 100644
index 0000000000000..9ffbf80cd5165
--- /dev/null
+++ b/packages/data-controls/package.json
@@ -0,0 +1,31 @@
+{
+ "name": "@wordpress/data-controls",
+ "version": "1.0.0-beta.1",
+ "description": "A set of common controls for the @wordpress/data api.",
+ "author": "The WordPress Contributors",
+ "license": "GPL-2.0-or-later",
+ "keywords": [
+ "wordpress",
+ "data",
+ "controls"
+ ],
+ "homepage": "https://github.com/WordPress/gutenberg/tree/master/packages/data-controls/README.md",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/WordPress/gutenberg.git",
+ "directory": "packages/data-controls"
+ },
+ "bugs": {
+ "url": "https://github.com/WordPress/gutenberg/issues"
+ },
+ "main": "build/index.js",
+ "module": "build-module/index.js",
+ "react-native": "src/index",
+ "dependencies": {
+ "@wordpress/api-fetch": "file:../api-fetch",
+ "@wordpress/data": "file:../data"
+ },
+ "publishConfig": {
+ "access": "public"
+ }
+}
diff --git a/packages/data-controls/src/index.js b/packages/data-controls/src/index.js
new file mode 100644
index 0000000000000..c209b3397b4fa
--- /dev/null
+++ b/packages/data-controls/src/index.js
@@ -0,0 +1,171 @@
+/**
+ * WordPress dependencies
+ */
+import triggerFetch from '@wordpress/api-fetch';
+import { createRegistryControl } from '@wordpress/data';
+
+/**
+ * Dispatches a control action for triggering an api fetch call.
+ *
+ * @param {Object} request Arguments for the fetch request.
+ *
+ * @example
+ * ```js
+ * import { apiFetch } from '@wordpress/data-controls';
+ *
+ * // Action generator using apiFetch
+ * export function* myAction {
+ * const path = '/v2/my-api/items';
+ * const items = yield apiFetch( { path } );
+ * // do something with the items.
+ * }
+ * ```
+ *
+ * @return {Object} The control descriptor.
+ */
+export const apiFetch = ( request ) => {
+ return {
+ type: 'API_FETCH',
+ request,
+ };
+};
+
+/**
+ * Dispatches a control action for triggering a registry select.
+ *
+ * Note: when this control action is handled, it automatically considers
+ * selectors that may have a resolver. It will await and return the resolved
+ * value when the selector has not been resolved yet.
+ *
+ * @param {string} storeKey The key for the store the selector belongs to
+ * @param {string} selectorName The name of the selector
+ * @param {Array} args Arguments for the select.
+ *
+ * @example
+ * ```js
+ * import { select } from '@wordpress/data-controls';
+ *
+ * // Action generator using select
+ * export function* myAction {
+ * const isSidebarOpened = yield select( 'core/edit-post', 'isEditorSideBarOpened' );
+ * // do stuff with the result from the select.
+ * }
+ * ```
+ *
+ * @return {Object} The control descriptor.
+ */
+export function select( storeKey, selectorName, ...args ) {
+ return {
+ type: 'SELECT',
+ storeKey,
+ selectorName,
+ args,
+ };
+}
+
+/**
+ * Dispatches a control action for triggering a registry dispatch.
+ *
+ * @param {string} storeKey The key for the store the action belongs to
+ * @param {string} actionName The name of the action to dispatch
+ * @param {Array} args Arguments for the dispatch action.
+ *
+ * @example
+ * ```js
+ * import { dispatch } from '@wordpress/data-controls';
+ *
+ * // Action generator using dispatch
+ * export function* myAction {
+ * yield dispatch( 'core/edit-post' ).togglePublishSidebar();
+ * // do some other things.
+ * }
+ * ```
+ *
+ * @return {Object} The control descriptor.
+ */
+export function dispatch( storeKey, actionName, ...args ) {
+ return {
+ type: 'DISPATCH',
+ storeKey,
+ actionName,
+ args,
+ };
+}
+
+/**
+ * Utility for returning a promise that handles a selector with a resolver.
+ *
+ * @param {Object} registry The data registry.
+ * @param {string} storeKey The store the selector belongs to
+ * @param {string} selectorName The selector name
+ * @param {Array} args The arguments fed to the selector
+ *
+ * @return {Promise} A promise for resolving the given selector.
+ */
+const resolveSelect = ( registry, { storeKey, selectorName, args } ) => {
+ return new Promise( ( resolve ) => {
+ const hasFinished = () => registry.select( 'core/data' )
+ .hasFinishedResolution( storeKey, selectorName, args );
+ const getResult = () => registry.select( storeKey )[ selectorName ]
+ .apply( null, args );
+
+ // trigger the selector (to trigger the resolver)
+ const result = getResult();
+ if ( hasFinished() ) {
+ return resolve( result );
+ }
+
+ const unsubscribe = registry.subscribe( () => {
+ if ( hasFinished() ) {
+ unsubscribe();
+ resolve( getResult() );
+ }
+ } );
+ } );
+};
+
+/**
+ * The default export is what you use to register the controls with your custom
+ * store.
+ *
+ * @example
+ * ```js
+ * // WordPress dependencies
+ * import { controls } from '@wordpress/data-controls';
+ * import { registerStore } from '@wordpress/data';
+ *
+ * // Internal dependencies
+ * import reducer from './reducer';
+ * import * as selectors from './selectors';
+ * import * as actions from './actions';
+ * import * as resolvers from './resolvers';
+ *
+ * registerStore ( 'my-custom-store', {
+ * reducer,
+ * controls,
+ * actions,
+ * selectors,
+ * resolvers,
+ * } );
+ * ```
+ *
+ * @return {Object} An object for registering the default controls with the
+ * store.
+ */
+export const controls = {
+ API_FETCH( { request } ) {
+ return triggerFetch( request );
+ },
+ SELECT: createRegistryControl(
+ ( registry ) => ( { storeKey, selectorName, args } ) => {
+ return registry.select( storeKey )[ selectorName ].hasResolver ?
+ resolveSelect( registry, { storeKey, selectorName, args } ) :
+ registry.select( storeKey )[ selectorName ]( ...args );
+ }
+ ),
+ DISPATCH: createRegistryControl(
+ ( registry ) => ( { storeKey, actionName, args } ) => {
+ return registry.dispatch( storeKey )[ actionName ]( ...args );
+ }
+ ),
+};
diff --git a/packages/data-controls/src/test/index.js b/packages/data-controls/src/test/index.js
new file mode 100644
index 0000000000000..fcd6650352af1
--- /dev/null
+++ b/packages/data-controls/src/test/index.js
@@ -0,0 +1,146 @@
+/**
+ * WordPress dependencies
+ */
+import triggerFetch from '@wordpress/api-fetch';
+
+jest.mock( '@wordpress/api-fetch' );
+
+/**
+ * Internal dependencies
+ */
+import { controls } from '../index';
+
+describe( 'controls', () => {
+ describe( 'API_FETCH', () => {
+ afterEach( () => {
+ triggerFetch.mockClear();
+ } );
+ it( 'invokes the triggerFetch function', () => {
+ controls.API_FETCH( { request: '' } );
+ expect( triggerFetch ).toHaveBeenCalledTimes( 1 );
+ } );
+ it( 'invokes the triggerFetch funcion with the passed in request', () => {
+ controls.API_FETCH( { request: 'foo' } );
+ expect( triggerFetch ).toHaveBeenCalledWith( 'foo' );
+ } );
+ } );
+ describe( 'SELECT', () => {
+ const selectorWithUndefinedResolver = jest.fn();
+ const selectorWithResolver = jest.fn();
+ selectorWithResolver.hasResolver = true;
+ const selectorWithFalseResolver = jest.fn();
+ selectorWithFalseResolver.hasResolver = false;
+ const hasFinishedResolution = jest.fn();
+ const unsubscribe = jest.fn();
+ let subscribedCallback;
+ const registryMock = {
+ select: ( storeKey ) => {
+ const stores = {
+ mockStore: {
+ selectorWithResolver,
+ selectorWithUndefinedResolver,
+ selectorWithFalseResolver,
+ },
+ 'core/data': {
+ hasFinishedResolution,
+ },
+ };
+ return stores[ storeKey ];
+ },
+ subscribe: jest.fn(
+ ( subscribeCallback ) => {
+ subscribedCallback = subscribeCallback;
+ return unsubscribe;
+ }
+ ),
+ };
+ const getSelectorArgs = ( storeKey, selectorName, ...args ) => (
+ { storeKey, selectorName, args }
+ );
+ beforeEach( () => {
+ selectorWithUndefinedResolver.mockReturnValue( 'foo' );
+ selectorWithFalseResolver.mockReturnValue( 'bar' );
+ selectorWithResolver.mockReturnValue( 'resolved' );
+ hasFinishedResolution.mockReturnValue( false );
+ } );
+ afterEach( () => {
+ selectorWithUndefinedResolver.mockClear();
+ selectorWithResolver.mockClear();
+ selectorWithFalseResolver.mockClear();
+ hasFinishedResolution.mockClear();
+ unsubscribe.mockClear();
+ } );
+ it( 'invokes selector with undefined resolver', () => {
+ const testControl = controls.SELECT( registryMock );
+ const value = testControl( getSelectorArgs(
+ 'mockStore',
+ 'selectorWithUndefinedResolver'
+ ) );
+ expect( value ).toBe( 'foo' );
+ expect( selectorWithUndefinedResolver ).toHaveBeenCalled();
+ expect( hasFinishedResolution ).not.toHaveBeenCalled();
+ } );
+ it( 'invokes selector with resolver set to false', () => {
+ const testControl = controls.SELECT( registryMock );
+ const value = testControl( getSelectorArgs(
+ 'mockStore',
+ 'selectorWithFalseResolver'
+ ) );
+ expect( value ).toBe( 'bar' );
+ expect( selectorWithFalseResolver ).toHaveBeenCalled();
+ expect( hasFinishedResolution ).not.toHaveBeenCalled();
+ } );
+ describe( 'invokes selector with resolver set to true', () => {
+ const testControl = controls.SELECT( registryMock );
+ it( 'returns a promise', () => {
+ const value = testControl( getSelectorArgs(
+ 'mockStore',
+ 'selectorWithResolver'
+ ) );
+ expect( value ).toBeInstanceOf( Promise );
+ expect( hasFinishedResolution ).toHaveBeenCalled();
+ expect( registryMock.subscribe ).toHaveBeenCalled();
+ } );
+ it( 'selector with resolver resolves to expected result when ' +
+ 'finished', async () => {
+ const value = testControl( getSelectorArgs(
+ 'mockStore',
+ 'selectorWithResolver'
+ ) );
+ hasFinishedResolution.mockReturnValue( true );
+ subscribedCallback();
+ await expect( value ).resolves.toBe( 'resolved' );
+ expect( unsubscribe ).toHaveBeenCalled();
+ } );
+ } );
+ } );
+ describe( 'DISPATCH', () => {
+ const mockDispatch = jest.fn();
+ const registryMock = {
+ dispatch: ( storeKey ) => {
+ const stores = {
+ mockStore: {
+ mockDispatch,
+ },
+ };
+ return stores[ storeKey ];
+ },
+ };
+ beforeEach( () => {
+ mockDispatch.mockReturnValue( 'foo' );
+ } );
+ afterEach( () => {
+ mockDispatch.mockClear();
+ } );
+ it( 'invokes dispatch action', () => {
+ const testControl = controls.DISPATCH( registryMock );
+ const value = testControl( {
+ storeKey: 'mockStore',
+ actionName: 'mockDispatch',
+ args: [],
+ } );
+ expect( value ).toBe( 'foo' );
+ expect( mockDispatch ).toHaveBeenCalled();
+ } );
+ } );
+} );
diff --git a/packages/editor/CHANGELOG.md b/packages/editor/CHANGELOG.md
index da86f36a1209a..d37f22323ec95 100644
--- a/packages/editor/CHANGELOG.md
+++ b/packages/editor/CHANGELOG.md
@@ -8,6 +8,7 @@
- Refactor setupEditor effects to action-generator using controls ([#14513](https://github.com/WordPress/gutenberg/pull/14513))
- Remove redux-multi dependency (no longer needed/used with above refactor)
+- Replace internal controls definitions with usage of new @wordpress/data-controls package (see [#15435](https://github.com/WordPress/gutenberg/pull/15435)
## 9.1.0 (2019-03-06)
diff --git a/packages/editor/package.json b/packages/editor/package.json
index af327112ade9e..74384ff0ce390 100644
--- a/packages/editor/package.json
+++ b/packages/editor/package.json
@@ -30,6 +30,7 @@
"@wordpress/compose": "file:../compose",
"@wordpress/core-data": "file:../core-data",
"@wordpress/data": "file:../data",
+ "@wordpress/data-controls": "file:../data-controls",
"@wordpress/date": "file:../date",
"@wordpress/deprecated": "file:../deprecated",
"@wordpress/element": "file:../element",
diff --git a/packages/editor/src/store/actions.js b/packages/editor/src/store/actions.js
index 52f021d1a2f83..4c340057c6471 100644
--- a/packages/editor/src/store/actions.js
+++ b/packages/editor/src/store/actions.js
@@ -8,16 +8,15 @@ import { BEGIN, COMMIT, REVERT } from 'redux-optimist';
* WordPress dependencies
*/
import deprecated from '@wordpress/deprecated';
+import { dispatch, select, apiFetch } from '@wordpress/data-controls';
+import {
+ parse,
+ synchronizeBlocksWithTemplate,
+} from '@wordpress/blocks';
/**
* Internal dependencies
*/
-import {
- dispatch,
- select,
- resolveSelect,
- apiFetch,
-} from './controls';
import {
getPostRawValue,
} from './reducer';
@@ -34,14 +33,6 @@ import {
getNotificationArgumentsForTrashFail,
} from './utils/notice-builder';
-/**
- * WordPress dependencies
- */
-import {
- parse,
- synchronizeBlocksWithTemplate,
-} from '@wordpress/blocks';
-
/**
* Returns an action generator used in signalling that editor has initialized with
* the specified post object and editor settings.
@@ -323,7 +314,7 @@ export function* savePost( options = {} ) {
'getCurrentPostType'
);
- const postType = yield resolveSelect(
+ const postType = yield select(
'core',
'getPostType',
currentPostType
@@ -347,9 +338,9 @@ export function* savePost( options = {} ) {
let path = `/wp/v2/${ postType.rest_base }/${ post.id }`;
let method = 'PUT';
if ( isAutosave ) {
- const currentUser = yield resolveSelect( 'core', 'getCurrentUser' );
+ const currentUser = yield select( 'core', 'getCurrentUser' );
const currentUserId = currentUser ? currentUser.id : undefined;
- const autosavePost = yield resolveSelect( 'core', 'getAutosave', post.type, post.id, currentUserId );
+ const autosavePost = yield select( 'core', 'getAutosave', post.type, post.id, currentUserId );
const mappedAutosavePost = mapValues( pick( autosavePost, AUTOSAVE_PROPERTIES ), getPostRawValue );
// Ensure autosaves contain all expected fields, using autosave or
@@ -448,7 +439,7 @@ export function* refreshPost() {
STORE_KEY,
'getCurrentPostType'
);
- const postType = yield resolveSelect(
+ const postType = yield select(
'core',
'getPostType',
postTypeSlug
@@ -476,7 +467,7 @@ export function* trashPost() {
STORE_KEY,
'getCurrentPostType'
);
- const postType = yield resolveSelect(
+ const postType = yield select(
'core',
'getPostType',
postTypeSlug
diff --git a/packages/editor/src/store/controls.js b/packages/editor/src/store/controls.js
deleted file mode 100644
index 597a5f726145b..0000000000000
--- a/packages/editor/src/store/controls.js
+++ /dev/null
@@ -1,113 +0,0 @@
-/**
- * WordPress dependencies
- */
-import triggerFetch from '@wordpress/api-fetch';
-import { createRegistryControl } from '@wordpress/data';
-
-/**
- * Dispatches a control action for triggering an api fetch call.
- *
- * @param {Object} request Arguments for the fetch request.
- *
- * @return {Object} control descriptor.
- */
-export function apiFetch( request ) {
- return {
- type: 'API_FETCH',
- request,
- };
-}
-
-/**
- * Dispatches a control action for triggering a registry select.
- *
- * @param {string} storeKey
- * @param {string} selectorName
- * @param {Array} args Arguments for the select.
- *
- * @return {Object} control descriptor.
- */
-export function select( storeKey, selectorName, ...args ) {
- return {
- type: 'SELECT',
- storeKey,
- selectorName,
- args,
- };
-}
-
-/**
- * Dispatches a control action for triggering a registry select that has a
- * resolver.
- *
- * @param {string} storeKey
- * @param {string} selectorName
- * @param {Array} args Arguments for the select.
- *
- * @return {Object} control descriptor.
- */
-export function resolveSelect( storeKey, selectorName, ...args ) {
- return {
- type: 'RESOLVE_SELECT',
- storeKey,
- selectorName,
- args,
- };
-}
-
-/**
- * Dispatches a control action for triggering a registry dispatch.
- *
- * @param {string} storeKey
- * @param {string} actionName
- * @param {Array} args Arguments for the dispatch action.
- *
- * @return {Object} control descriptor.
- */
-export function dispatch( storeKey, actionName, ...args ) {
- return {
- type: 'DISPATCH',
- storeKey,
- actionName,
- args,
- };
-}
-
-export default {
- API_FETCH( { request } ) {
- return triggerFetch( request );
- },
- SELECT: createRegistryControl(
- ( registry ) => ( { storeKey, selectorName, args } ) => {
- return registry.select( storeKey )[ selectorName ]( ...args );
- }
- ),
- DISPATCH: createRegistryControl(
- ( registry ) => ( { storeKey, actionName, args } ) => {
- return registry.dispatch( storeKey )[ actionName ]( ...args );
- }
- ),
- RESOLVE_SELECT: createRegistryControl(
- ( registry ) => ( { storeKey, selectorName, args } ) => {
- return new Promise( ( resolve ) => {
- const hasFinished = () => registry.select( 'core/data' )
- .hasFinishedResolution( storeKey, selectorName, args );
- const getResult = () => registry.select( storeKey )[ selectorName ]
- .apply( null, args );
-
- // trigger the selector (to trigger the resolver)
- const result = getResult();
- if ( hasFinished() ) {
- return resolve( result );
- }
-
- const unsubscribe = registry.subscribe( () => {
- if ( hasFinished() ) {
- unsubscribe();
- resolve( getResult() );
- }
- } );
- } );
- }
- ),
-};
diff --git a/packages/editor/src/store/index.js b/packages/editor/src/store/index.js
index 42af629bcce0d..1ba136aaab722 100644
--- a/packages/editor/src/store/index.js
+++ b/packages/editor/src/store/index.js
@@ -2,6 +2,7 @@
* WordPress dependencies
*/
import { registerStore } from '@wordpress/data';
+import { controls } from '@wordpress/data-controls';
/**
* Internal dependencies
@@ -10,7 +11,6 @@ import reducer from './reducer';
import applyMiddlewares from './middlewares';
import * as selectors from './selectors';
import * as actions from './actions';
-import controls from './controls';
import { STORE_KEY } from './constants';
const store = registerStore( STORE_KEY, {
diff --git a/packages/editor/src/store/test/actions.js b/packages/editor/src/store/test/actions.js
index af7e7f60a2210..f0ec7c84dab15 100644
--- a/packages/editor/src/store/test/actions.js
+++ b/packages/editor/src/store/test/actions.js
@@ -3,11 +3,15 @@
*/
import { BEGIN, COMMIT, REVERT } from 'redux-optimist';
+/**
+ * WordPress dependencies
+ */
+import { select, dispatch, apiFetch } from '@wordpress/data-controls';
+
/**
* Internal dependencies
*/
import * as actions from '../actions';
-import { select, dispatch, apiFetch, resolveSelect } from '../controls';
import {
STORE_KEY,
SAVE_POST_NOTICE_ID,
@@ -15,24 +19,20 @@ import {
POST_UPDATE_TRANSACTION_ID,
} from '../constants';
-jest.mock( '../controls' );
+jest.mock( '@wordpress/data-controls' );
select.mockImplementation( ( ...args ) => {
- const { select: actualSelect } = jest.requireActual( '../controls' );
+ const { select: actualSelect } = jest
+ .requireActual( '@wordpress/data-controls' );
return actualSelect( ...args );
} );
dispatch.mockImplementation( ( ...args ) => {
- const { dispatch: actualDispatch } = jest.requireActual( '../controls' );
+ const { dispatch: actualDispatch } = jest
+ .requireActual( '@wordpress/data-controls' );
return actualDispatch( ...args );
} );
-resolveSelect.mockImplementation( ( ...args ) => {
- const { resolveSelect: selectResolver } = jest
- .requireActual( '../controls' );
- return selectResolver( ...args );
-} );
-
const apiFetchThrowError = ( error ) => {
apiFetch.mockClear();
apiFetch.mockImplementation( () => {
@@ -43,7 +43,8 @@ const apiFetchThrowError = ( error ) => {
const apiFetchDoActual = () => {
apiFetch.mockClear();
apiFetch.mockImplementation( ( ...args ) => {
- const { apiFetch: fetch } = jest.requireActual( '../controls' );
+ const { apiFetch: fetch } = jest
+ .requireActual( '@wordpress/data-controls' );
return fetch( ...args );
} );
};
@@ -212,7 +213,7 @@ describe( 'Post generator actions', () => {
() => {
const { value } = fulfillment.next( postTypeSlug );
expect( value ).toEqual(
- resolveSelect( 'core', 'getPostType', postTypeSlug )
+ select( 'core', 'getPostType', postTypeSlug )
);
},
],
@@ -278,7 +279,7 @@ describe( 'Post generator actions', () => {
() => {
const { value } = fulfillment.next();
expect( value ).toEqual(
- resolveSelect( 'core', 'getCurrentUser' )
+ select( 'core', 'getCurrentUser' )
);
},
],
@@ -288,7 +289,7 @@ describe( 'Post generator actions', () => {
() => {
const { value } = fulfillment.next( currentUser );
expect( value ).toEqual(
- resolveSelect(
+ select(
'core',
'getAutosave',
postTypeSlug,
@@ -533,7 +534,7 @@ describe( 'Post generator actions', () => {
);
it( 'yields expected action for selecting the post type object', () => {
const { value } = fulfillment.next( postTypeSlug );
- expect( value ).toEqual( resolveSelect(
+ expect( value ).toEqual( select(
'core',
'getPostType',
postTypeSlug
@@ -611,7 +612,7 @@ describe( 'Post generator actions', () => {
} );
it( 'yields expected action for selecting the post type object', () => {
const { value } = fulfillment.next( postTypeSlug );
- expect( value ).toEqual( resolveSelect(
+ expect( value ).toEqual( select(
'core',
'getPostType',
postTypeSlug