From 9fb29cfc01926a608a9699893e1ba655627aef6e Mon Sep 17 00:00:00 2001 From: Adam Zielinski Date: Fri, 4 Feb 2022 17:10:09 +0100 Subject: [PATCH] Create your First App with Gutenberg Data tutorial (#191) * Add My first Gutenberg app example * Add 09-code-data-basics-esnext to lerna.json --- 09-code-data-basics-esnext/.eslintrc | 3 + .../build/index.asset.php | 1 + 09-code-data-basics-esnext/build/index.js | 188 ++++++++++++++++++ 09-code-data-basics-esnext/index.php | 60 ++++++ 09-code-data-basics-esnext/package.json | 28 +++ 09-code-data-basics-esnext/src/index.js | 71 +++++++ 09-code-data-basics-esnext/style.css | 17 ++ index.php | 1 + lerna.json | 1 + 9 files changed, 370 insertions(+) create mode 100644 09-code-data-basics-esnext/.eslintrc create mode 100644 09-code-data-basics-esnext/build/index.asset.php create mode 100644 09-code-data-basics-esnext/build/index.js create mode 100644 09-code-data-basics-esnext/index.php create mode 100644 09-code-data-basics-esnext/package.json create mode 100644 09-code-data-basics-esnext/src/index.js create mode 100644 09-code-data-basics-esnext/style.css diff --git a/09-code-data-basics-esnext/.eslintrc b/09-code-data-basics-esnext/.eslintrc new file mode 100644 index 00000000..371f02e3 --- /dev/null +++ b/09-code-data-basics-esnext/.eslintrc @@ -0,0 +1,3 @@ +{ + "extends": [ "plugin:@wordpress/eslint-plugin/recommended" ] +} diff --git a/09-code-data-basics-esnext/build/index.asset.php b/09-code-data-basics-esnext/build/index.asset.php new file mode 100644 index 00000000..a80163d1 --- /dev/null +++ b/09-code-data-basics-esnext/build/index.asset.php @@ -0,0 +1 @@ + array('wp-components', 'wp-core-data', 'wp-data', 'wp-element', 'wp-polyfill'), 'version' => '93651ae1be8cf64079654a48191d7fdb'); \ No newline at end of file diff --git a/09-code-data-basics-esnext/build/index.js b/09-code-data-basics-esnext/build/index.js new file mode 100644 index 00000000..b52f9dcc --- /dev/null +++ b/09-code-data-basics-esnext/build/index.js @@ -0,0 +1,188 @@ +/******/ (function() { // webpackBootstrap +/******/ "use strict"; +/******/ var __webpack_modules__ = ({ + +/***/ "@wordpress/components": +/*!************************************!*\ + !*** external ["wp","components"] ***! + \************************************/ +/***/ (function(module) { + +module.exports = window["wp"]["components"]; + +/***/ }), + +/***/ "@wordpress/core-data": +/*!**********************************!*\ + !*** external ["wp","coreData"] ***! + \**********************************/ +/***/ (function(module) { + +module.exports = window["wp"]["coreData"]; + +/***/ }), + +/***/ "@wordpress/data": +/*!******************************!*\ + !*** external ["wp","data"] ***! + \******************************/ +/***/ (function(module) { + +module.exports = window["wp"]["data"]; + +/***/ }), + +/***/ "@wordpress/element": +/*!*********************************!*\ + !*** external ["wp","element"] ***! + \*********************************/ +/***/ (function(module) { + +module.exports = window["wp"]["element"]; + +/***/ }) + +/******/ }); +/************************************************************************/ +/******/ // The module cache +/******/ var __webpack_module_cache__ = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ // Check if module is in cache +/******/ var cachedModule = __webpack_module_cache__[moduleId]; +/******/ if (cachedModule !== undefined) { +/******/ return cachedModule.exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = __webpack_module_cache__[moduleId] = { +/******/ // no module.id needed +/******/ // no module.loaded needed +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/compat get default export */ +/******/ !function() { +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function() { return module['default']; } : +/******/ function() { return module; }; +/******/ __webpack_require__.d(getter, { a: getter }); +/******/ return getter; +/******/ }; +/******/ }(); +/******/ +/******/ /* webpack/runtime/define property getters */ +/******/ !function() { +/******/ // define getter functions for harmony exports +/******/ __webpack_require__.d = function(exports, definition) { +/******/ for(var key in definition) { +/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { +/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); +/******/ } +/******/ } +/******/ }; +/******/ }(); +/******/ +/******/ /* webpack/runtime/hasOwnProperty shorthand */ +/******/ !function() { +/******/ __webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); } +/******/ }(); +/******/ +/******/ /* webpack/runtime/make namespace object */ +/******/ !function() { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = function(exports) { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ }(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; +// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. +!function() { +/*!**********************!*\ + !*** ./src/index.js ***! + \**********************/ +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _wordpress_element__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @wordpress/element */ "@wordpress/element"); +/* harmony import */ var _wordpress_element__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var _wordpress_components__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @wordpress/components */ "@wordpress/components"); +/* harmony import */ var _wordpress_components__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__); +/* harmony import */ var _wordpress_data__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @wordpress/data */ "@wordpress/data"); +/* harmony import */ var _wordpress_data__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_wordpress_data__WEBPACK_IMPORTED_MODULE_2__); +/* harmony import */ var _wordpress_core_data__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @wordpress/core-data */ "@wordpress/core-data"); +/* harmony import */ var _wordpress_core_data__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_wordpress_core_data__WEBPACK_IMPORTED_MODULE_3__); + + + + + + +function MyFirstApp() { + const [searchTerm, setSearchTerm] = (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_0__.useState)(''); + const { + pages, + hasResolved + } = (0,_wordpress_data__WEBPACK_IMPORTED_MODULE_2__.useSelect)(select => { + const query = {}; + + if (searchTerm) { + query.search = searchTerm; + } + + const selectorArgs = ['postType', 'page', query]; + return { + pages: select(_wordpress_core_data__WEBPACK_IMPORTED_MODULE_3__.store).getEntityRecords(...selectorArgs), + hasResolved: select(_wordpress_core_data__WEBPACK_IMPORTED_MODULE_3__.store).hasFinishedResolution('getEntityRecords', selectorArgs) + }; + }, [searchTerm]); + return (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_0__.createElement)("div", null, (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_0__.createElement)(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__.SearchControl, { + onChange: setSearchTerm, + value: searchTerm + }), (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_0__.createElement)(PagesList, { + hasResolved: hasResolved, + pages: pages + })); +} + +function PagesList(_ref) { + let { + hasResolved, + pages + } = _ref; + + if (!hasResolved) { + return (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_0__.createElement)(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__.Spinner, null); + } + + if (!pages?.length) { + return (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_0__.createElement)("div", null, "No results"); + } + + return (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_0__.createElement)("table", { + className: "wp-list-table widefat fixed striped table-view-list" + }, (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_0__.createElement)("thead", null, (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_0__.createElement)("tr", null, (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_0__.createElement)("td", null, "Title"))), (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_0__.createElement)("tbody", null, pages?.map(page => (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_0__.createElement)("tr", { + key: page.id + }, (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_0__.createElement)("td", null, page.title.rendered))))); +} + +window.addEventListener('load', function () { + (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_0__.render)((0,_wordpress_element__WEBPACK_IMPORTED_MODULE_0__.createElement)(MyFirstApp, null), document.querySelector('#my-first-gutenberg-app')); +}, false); +}(); +/******/ })() +; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/09-code-data-basics-esnext/index.php b/09-code-data-basics-esnext/index.php new file mode 100644 index 00000000..c6e9422d --- /dev/null +++ b/09-code-data-basics-esnext/index.php @@ -0,0 +1,60 @@ +Pages +
+ '; + }, + 'dashicons-schedule', + 3 + ); +} + +add_action( 'admin_menu', 'my_admin_menu' ); + +function load_custom_wp_admin_scripts( $hook ) { + // Load only on ?page=my-first-gutenberg-app. + if ( 'toplevel_page_my-first-gutenberg-app' !== $hook ) { + return; + } + + // Load the required WordPress packages. + + // Automatically load dependencies and version. + $asset_file = include plugin_dir_path( __FILE__ ) . 'build/index.asset.php'; + + // Enqueue CSS dependencies. + foreach ( $asset_file['dependencies'] as $style ) { + wp_enqueue_style( $style ); + } + + // Load our app.js. + wp_register_script( + '09-code-data-basics-esnext', + plugins_url( 'build/index.js', __FILE__ ), + $asset_file['dependencies'], + $asset_file['version'] + ); + wp_enqueue_script( '09-code-data-basics-esnext' ); + + // Load our style.css. + wp_register_style( + '09-code-data-basics-esnext', + plugins_url( 'style.css', __FILE__ ) + ); + wp_enqueue_style( '09-code-data-basics-esnext' ); +} + +add_action( 'admin_enqueue_scripts', 'load_custom_wp_admin_scripts' ); diff --git a/09-code-data-basics-esnext/package.json b/09-code-data-basics-esnext/package.json new file mode 100644 index 00000000..bdba0889 --- /dev/null +++ b/09-code-data-basics-esnext/package.json @@ -0,0 +1,28 @@ +{ + "name": "05-recipe-card-esnext", + "version": "1.1.0", + "private": true, + "description": "Example: Recipe Card (ESNext).", + "author": "The WordPress Contributors", + "license": "GPL-2.0-or-later", + "keywords": [ + "WordPress", + "block" + ], + "homepage": "https://github.com/WordPress/gutenberg-examples/", + "repository": "git+https://github.com/WordPress/gutenberg-examples.git", + "bugs": { + "url": "https://github.com/WordPress/gutenberg-examples/issues" + }, + "main": "build/index.js", + "devDependencies": { + "@wordpress/scripts": "^18.0.1" + }, + "scripts": { + "build": "wp-scripts build", + "format:js": "wp-scripts format-js", + "lint:js": "wp-scripts lint-js", + "packages-update": "wp-scripts packages-update", + "start": "wp-scripts start" + } +} diff --git a/09-code-data-basics-esnext/src/index.js b/09-code-data-basics-esnext/src/index.js new file mode 100644 index 00000000..9f76ab34 --- /dev/null +++ b/09-code-data-basics-esnext/src/index.js @@ -0,0 +1,71 @@ +import { SearchControl, Spinner } from '@wordpress/components'; +import { useState, render } from '@wordpress/element'; +import { useSelect } from '@wordpress/data'; +import { store as coreDataStore } from '@wordpress/core-data'; + +function MyFirstApp() { + const [ searchTerm, setSearchTerm ] = useState( '' ); + const { pages, hasResolved } = useSelect( + ( select ) => { + const query = {}; + if ( searchTerm ) { + query.search = searchTerm; + } + const selectorArgs = [ 'postType', 'page', query ]; + return { + pages: select( coreDataStore ).getEntityRecords( + ...selectorArgs + ), + hasResolved: select( coreDataStore ).hasFinishedResolution( + 'getEntityRecords', + selectorArgs + ), + }; + }, + [ searchTerm ] + ); + + return ( +
+ + +
+ ); +} + +function PagesList( { hasResolved, pages } ) { + if ( ! hasResolved ) { + return ; + } + if ( ! pages?.length ) { + return
No results
; + } + + return ( + + + + + + + + { pages?.map( ( page ) => ( + + + + ) ) } + +
Title
{ page.title.rendered }
+ ); +} + +window.addEventListener( + 'load', + function () { + render( + , + document.querySelector( '#my-first-gutenberg-app' ) + ); + }, + false +); diff --git a/09-code-data-basics-esnext/style.css b/09-code-data-basics-esnext/style.css new file mode 100644 index 00000000..25e32e0f --- /dev/null +++ b/09-code-data-basics-esnext/style.css @@ -0,0 +1,17 @@ +.toplevel_page_my-first-gutenberg-app #wpcontent { + background: #FFF; +} +#my-first-gutenberg-app { + max-width: 500px; +} +#my-first-gutenberg-app ul, +#my-first-gutenberg-app ul li { + list-style-type: disc; +} +#my-first-gutenberg-app ul { + padding-left: 20px; +} +#my-first-gutenberg-app .components-search-control__input { + height: 36px; + margin-left: 0; +} diff --git a/index.php b/index.php index 12d59fe3..0aa31c75 100644 --- a/index.php +++ b/index.php @@ -25,6 +25,7 @@ include '06-inner-blocks-esnext/index.php'; include '07-slotfills-esnext/index.php'; include '08-block-supports-esnext/index.php'; +include '09-code-data-basics-esnext/index.php'; include 'format-api/index.php'; include 'plugin-sidebar/plugin-sidebar.php'; include 'meta-block/meta-block.php'; diff --git a/lerna.json b/lerna.json index 7850611a..ce56a018 100644 --- a/lerna.json +++ b/lerna.json @@ -6,6 +6,7 @@ "05-recipe-card-esnext", "06-inner-blocks-esnext", "08-block-supports-esnext", + "09-code-data-basics-esnext", "format-api" ], "version": "independent"