[Settings] Add fresh page, script, and package (#52391)

This commit is contained in:
Paul Sealock 2024-10-30 14:05:13 +13:00 committed by GitHub
parent 8fd310c133
commit 5d1a7499ce
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
27 changed files with 2225 additions and 1274 deletions

View File

@ -105,7 +105,7 @@
"react",
"react-dom",
"@types/react-dom",
"@types/react",
"@types/react"
],
"pinVersion": "18.3.x",
"packages": [
@ -119,7 +119,7 @@
"react",
"react-dom",
"@types/react-dom",
"@types/react",
"@types/react"
],
"pinVersion": "17.0.x",
"packages": [
@ -213,6 +213,7 @@
"packages": [
"@woocommerce/block-templates",
"@woocommerce/product-editor",
"@woocommerce/settings-editor",
"@woocommerce/admin-library",
"@woocommerce/components"
],
@ -448,7 +449,7 @@
"node",
"pnpm",
"postcss",
"postcss-loader",
"postcss-loader"
],
"packages": [
"**"

View File

@ -17,6 +17,7 @@ module.exports = [
'@woocommerce/notices',
'@woocommerce/number',
'@woocommerce/product-editor',
'@woocommerce/settings-editor',
'@woocommerce/tracks',
'@woocommerce/remote-logging',
// wc-blocks packages

View File

@ -0,0 +1,4 @@
Significance: minor
Type: add
Add Settings package, feature flag, and initial page.

View File

@ -0,0 +1,44 @@
module.exports = {
extends: [ 'plugin:@woocommerce/eslint-plugin/recommended' ],
root: true,
overrides: [
{
files: [ '**/*.js', '**/*.jsx', '**/*.tsx' ],
rules: {
'react/react-in-jsx-scope': 'off',
},
},
],
settings: {
'import/core-modules': [
'@woocommerce/admin-layout',
'@woocommerce/block-templates',
'@woocommerce/components',
'@woocommerce/customer-effort-score',
'@woocommerce/currency',
'@woocommerce/data',
'@woocommerce/experimental',
'@woocommerce/expression-evaluation',
'@woocommerce/navigation',
'@woocommerce/number',
'@woocommerce/settings',
'@woocommerce/tracks',
'@wordpress/blocks',
'@wordpress/block-editor',
'@wordpress/components',
'@wordpress/core-data',
'@wordpress/date',
'@wordpress/element',
'@wordpress/keycodes',
'@wordpress/media-utils',
'@testing-library/react',
'dompurify',
'react-router-dom',
],
'import/resolver': {
node: {},
webpack: {},
typescript: {},
},
},
};

View File

@ -0,0 +1 @@
package-lock=false

View File

@ -0,0 +1,11 @@
# Product Editor
A collection of WooCommerce Admin settings editor components and utilities.
## Installation
Install the module
```bash
pnpm install @woocommerce/settings-editor --save
```

View File

@ -0,0 +1,3 @@
module.exports = {
extends: '../internal-js-tests/babel.config.js',
};

View File

@ -0,0 +1,3 @@
# Changelog
This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

View File

@ -0,0 +1,4 @@
Significance: minor
Type: add
Add Settings package, feature flag, and initial page.

View File

@ -0,0 +1,32 @@
{
"name": "woocommerce/settings-editor",
"description": "WooCommerce Admin settings page",
"type": "library",
"license": "GPL-3.0-or-later",
"minimum-stability": "dev",
"require-dev": {
"automattic/jetpack-changelogger": "3.3.0"
},
"config": {
"platform": {
"php": "7.4"
}
},
"extra": {
"changelogger": {
"formatter": {
"filename": "../../../tools/changelogger/class-package-formatter.php"
},
"types": {
"fix": "Fixes an existing bug",
"add": "Adds functionality",
"update": "Update existing functionality",
"dev": "Development related task",
"tweak": "A minor adjustment to the codebase",
"performance": "Address performance issues",
"enhancement": "Improve existing functionality"
},
"changelog": "CHANGELOG.md"
}
}
}

View File

@ -0,0 +1,7 @@
{
"rootDir": "./",
"roots": [
"<rootDir>/src"
],
"preset": "./node_modules/@woocommerce/internal-js-tests/jest-preset.js"
}

View File

@ -0,0 +1,254 @@
{
"name": "@woocommerce/settings-editor",
"version": "0.1.0",
"description": "React components for the WooCommerce admin settings editor.",
"author": "Automattic",
"license": "GPL-2.0-or-later",
"keywords": [
"wordpress",
"woocommerce"
],
"homepage": "https://github.com/woocommerce/woocommerce/tree/trunk/packages/js/settings-editor/README.md",
"repository": {
"type": "git",
"url": "https://github.com/woocommerce/woocommerce.git"
},
"bugs": {
"url": "https://github.com/woocommerce/woocommerce/issues"
},
"main": "build/index.js",
"module": "build-module/index.js",
"types": "build-types",
"react-native": "src/index",
"files": [
"build",
"build-module",
"build-style",
"build-types"
],
"sideEffects": [
"build-style/**",
"src/**/*.scss"
],
"publishConfig": {
"access": "public"
},
"dependencies": {
"@types/lodash": "^4.14.202",
"@types/prop-types": "^15.7.11",
"@types/wordpress__blocks": "11.0.7",
"@woocommerce/settings": "^1.0.0",
"@woocommerce/tracks": "workspace:^",
"@wordpress/api-fetch": "wp-6.0",
"@wordpress/components": "wp-6.0",
"@wordpress/compose": "wp-6.0",
"@wordpress/core-data": "wp-6.0",
"@wordpress/data": "wp-6.0",
"@wordpress/dataviews": "^4.4.1",
"@wordpress/date": "wp-6.0",
"@wordpress/deprecated": "wp-6.0",
"@wordpress/edit-post": "wp-6.0",
"@wordpress/editor": "wp-6.0",
"@wordpress/element": "wp-6.0",
"@wordpress/hooks": "wp-6.0",
"@wordpress/html-entities": "wp-6.0",
"@wordpress/i18n": "wp-6.0",
"@wordpress/icons": "wp-6.0",
"@wordpress/interface": "wp-6.0",
"@wordpress/keyboard-shortcuts": "wp-6.0",
"@wordpress/keycodes": "wp-6.0",
"@wordpress/media-utils": "wp-6.0",
"@wordpress/plugins": "wp-6.0",
"@wordpress/preferences": "wp-6.0",
"@wordpress/private-apis": "^1.6.0",
"@wordpress/url": "wp-6.0",
"classnames": "^2.3.2",
"dompurify": "^2.4.7",
"prop-types": "^15.8.1",
"react-router-dom": "~6.3.0"
},
"devDependencies": {
"@babel/core": "^7.23.5",
"@babel/runtime": "^7.23.5",
"@testing-library/jest-dom": "5.16.2",
"@testing-library/react": "12.1.3",
"@testing-library/react-hooks": "8.0.1",
"@testing-library/user-event": "13.5.0",
"@types/dompurify": "^2.4.0",
"@types/jest": "27.5.x",
"@types/react": "17.0.x",
"@types/testing-library__jest-dom": "^5.14.9",
"@types/wordpress__block-editor": "7.0.0",
"@types/wordpress__block-library": "2.6.1",
"@types/wordpress__blocks": "11.0.7",
"@types/wordpress__components": "^19.10.5",
"@types/wordpress__core-data": "2.4.5",
"@types/wordpress__data": "6.0.2",
"@types/wordpress__date": "3.3.2",
"@types/wordpress__edit-post": "7.5.4",
"@types/wordpress__editor": "13.0.0",
"@types/wordpress__keycodes": "2.3.1",
"@types/wordpress__media-utils": "3.0.0",
"@types/wordpress__plugins": "3.0.0",
"@types/wordpress__rich-text": "3.4.6",
"@woocommerce/eslint-plugin": "workspace:*",
"@woocommerce/internal-js-tests": "workspace:*",
"@woocommerce/internal-style-build": "workspace:*",
"@wordpress/block-editor": "wp-6.0",
"@wordpress/browserslist-config": "wp-6.0",
"concurrently": "^7.6.0",
"copy-webpack-plugin": "^9.1.0",
"css-loader": "^3.6.0",
"eslint": "^8.55.0",
"jest": "27.5.x",
"jest-cli": "27.5.x",
"mini-css-extract-plugin": "^2.7.6",
"postcss": "^8.4.32",
"postcss-loader": "^4.3.0",
"react": "17.0.x",
"react-dom": "17.0.x",
"rimraf": "5.0.5",
"sass-loader": "^10.5.0",
"ts-jest": "29.1.x",
"typescript": "5.3.x",
"webpack": "^5.89.0",
"webpack-cli": "^3.3.12",
"webpack-remove-empty-scripts": "^0.7.3",
"webpack-rtl-plugin": "^2.0.0",
"wireit": "0.14.3"
},
"scripts": {
"build": "pnpm --if-present --workspace-concurrency=Infinity --stream --filter=\"$npm_package_name...\" '/^build:project:.*$/'",
"build:project": "pnpm --if-present '/^build:project:.*$/'",
"build:project:bundle": "wireit",
"build:project:cjs": "wireit",
"build:project:esm": "wireit",
"changelog": "XDEBUG_MODE=off composer install --quiet && composer exec -- changelogger",
"lint": "pnpm --if-present '/^lint:lang:.*$/'",
"lint:fix": "pnpm --if-present '/^lint:fix:lang:.*$/'",
"lint:fix:lang:js": "eslint src --fix",
"lint:lang:js": "eslint src",
"prepack": "pnpm build",
"test:js": "jest --config ./jest.config.json --passWithNoTests",
"watch:build": "pnpm --if-present --workspace-concurrency=Infinity --filter=\"$npm_package_name...\" --parallel '/^watch:build:project:.*$/'",
"watch:build:project": "pnpm --if-present run '/^watch:build:project:.*$/'",
"watch:build:project:bundle": "wireit",
"watch:build:project:cjs": "wireit",
"watch:build:project:esm": "wireit"
},
"peerDependencies": {
"@types/react": "17.0.x",
"@wordpress/data": "wp-6.0",
"react": "17.0.x",
"react-dom": "17.0.x"
},
"config": {
"ci": {
"lint": {
"command": "lint",
"changes": "src/**/*.{js,jsx,ts,tsx}"
},
"tests": [
{
"name": "JavaScript",
"command": "test:js",
"changes": [
"webpack.config.js",
"jest.config.js",
"babel.config.js",
"tsconfig.json",
"src/**/*.{js,jsx,ts,tsx}",
"typings/**/*.ts"
],
"cascade": "test:js",
"events": [
"pull_request",
"push"
]
}
]
}
},
"wireit": {
"build:project:bundle": {
"command": "webpack",
"clean": "if-file-deleted",
"env": {
"NODE_ENV": {
"external": true,
"default": "production"
}
},
"files": [
"webpack.config.js",
"src/**/*.scss"
],
"output": [
"build-style"
],
"dependencies": [
"dependencyOutputs"
]
},
"watch:build:project:bundle": {
"command": "webpack --watch",
"service": true
},
"build:project:cjs": {
"command": "tsc --project tsconfig-cjs.json",
"clean": "if-file-deleted",
"files": [
"tsconfig-cjs.json",
"src/**/*.{js,jsx,ts,tsx}",
"typings/**/*.ts"
],
"output": [
"build"
],
"dependencies": [
"dependencyOutputs"
]
},
"watch:build:project:cjs": {
"command": "tsc --project tsconfig-cjs.json --watch",
"service": true
},
"build:project:esm": {
"command": "tsc --project tsconfig.json",
"clean": "if-file-deleted",
"files": [
"tsconfig.json",
"src/**/*.{js,jsx,ts,tsx}",
"typings/**/*.ts"
],
"output": [
"build-module",
"build-types"
],
"dependencies": [
"dependencyOutputs"
]
},
"watch:build:project:esm": {
"command": "tsc --project tsconfig.json --watch",
"service": true
},
"dependencyOutputs": {
"allowUsuallyExcludedPaths": true,
"files": [
"node_modules/@woocommerce/internal-style-build/index.js",
"node_modules/@woocommerce/internal-style-build/abstracts",
"node_modules/@woocommerce/internal-js-tests/build",
"node_modules/@woocommerce/internal-js-tests/build-module",
"node_modules/@woocommerce/internal-js-tests/jest-preset.js",
"node_modules/@woocommerce/eslint-plugin/configs",
"node_modules/@woocommerce/eslint-plugin/rules",
"node_modules/@woocommerce/eslint-plugin/index.js",
"node_modules/@woocommerce/tracks/build",
"node_modules/@woocommerce/tracks/build-module",
"node_modules/@woocommerce/tracks/build-types",
"package.json"
]
}
}
}

View File

@ -0,0 +1,8 @@
/**
* External dependencies
*/
import { createElement } from '@wordpress/element';
export const SettingsEditor = () => {
return <div style={ { padding: '20px' } }>Settings Editor</div>;
};

View File

@ -0,0 +1,15 @@
{
"extends": "../tsconfig-cjs",
"compilerOptions": {
"outDir": "build",
"resolveJsonModule": true,
"typeRoots": [
"./typings",
"./node_modules/@types"
]
},
"include": [
"typings/**/*",
"src/**/*",
]
}

View File

@ -0,0 +1,19 @@
{
"extends": "../tsconfig",
"compilerOptions": {
"rootDir": "src",
"outDir": "build-module",
"declaration": true,
"declarationMap": true,
"declarationDir": "./build-types",
"resolveJsonModule": true,
"typeRoots": [
"./typings",
"./node_modules/@types"
]
},
"include": [
"typings/**/*",
"src/**/*",
],
}

View File

@ -0,0 +1,52 @@
/**
* External dependencies
*/
const RemoveEmptyScriptsPlugin = require( 'webpack-remove-empty-scripts' );
const WebpackRTLPlugin = require( 'webpack-rtl-plugin' );
/**
* Internal dependencies
*/
const {
webpackConfig,
plugin,
StyleAssetPlugin,
} = require( '@woocommerce/internal-style-build' );
const NODE_ENV = process.env.NODE_ENV || 'development';
module.exports = {
mode: process.env.NODE_ENV || 'development',
entry: {
'build-style': __dirname + '/src/style.scss',
},
output: {
path: __dirname,
},
module: {
parser: webpackConfig.parser,
rules: webpackConfig.rules,
},
plugins: [
new RemoveEmptyScriptsPlugin(),
new plugin( {
filename: ( data ) => {
return data.chunk.name.startsWith( '/build/blocks' )
? `[name].css`
: `[name]/style.css`;
},
chunkFilename: 'chunks/[id].style.css',
} ),
new WebpackRTLPlugin( {
test: /(?<!style)\.css$/,
filename: '[name]-rtl.css',
minify: NODE_ENV === 'development' ? false : { safe: true },
} ),
new WebpackRTLPlugin( {
test: /style\.css$/,
filename: '[name]/style-rtl.css',
minify: NODE_ENV === 'development' ? false : { safe: true },
} ),
new StyleAssetPlugin(),
],
};

View File

@ -0,0 +1,4 @@
Significance: minor
Type: add
Add Settings package, feature flag, and initial page.

View File

@ -65,9 +65,6 @@ const CoreProfiler = lazy( () =>
import( /* webpackChunkName: "core-profiler" */ '../core-profiler' )
);
const SettingsGroup = lazy( () =>
import( /* webpackChunkName: "settings" */ '../settings' )
);
const WCPaymentsWelcomePage = lazy( () =>
import(
/* webpackChunkName: "wcpay-payment-welcome-page" */ '../payments-welcome'
@ -321,35 +318,6 @@ export const getPages = () => {
} );
}
if ( window.wcAdminFeatures.settings ) {
pages.push( {
container: SettingsGroup,
path: '/settings/:page',
breadcrumbs: ( { match } ) => {
// @todo This might need to be refactored to retrieve groups via data store.
const settingsPages = getAdminSetting( 'settingsPages' );
const page = settingsPages[ match.params.page ];
if ( ! page ) {
return [];
}
return [
...initialBreadcrumbs,
[
settingsPages.general
? '/settings/general'
: `/settings/${
Object.keys( settingsPages )[ 0 ]
}`,
__( 'Settings', 'woocommerce' ),
],
page,
];
},
wpOpenMenu: 'toplevel_page_woocommerce',
capability: 'manage_woocommerce',
} );
}
if ( window.wcAdminFeatures[ 'wc-pay-welcome-page' ] ) {
pages.push( {
container: WCPaymentsWelcomePage,

View File

@ -1,3 +1,11 @@
export default ( {} ) => {
return <div>Settings page</div>;
};
/**
* External dependencies
*/
import { createRoot } from '@wordpress/element';
import { SettingsEditor } from '@woocommerce/settings-editor';
const node = document.getElementById( 'wc-settings-page' );
if ( node ) {
createRoot( node ).render( <SettingsEditor /> );
}

View File

@ -163,6 +163,7 @@
"@woocommerce/number": "workspace:*",
"@woocommerce/onboarding": "workspace:*",
"@woocommerce/product-editor": "workspace:*",
"@woocommerce/settings-editor": "workspace:*",
"@woocommerce/remote-logging": "workspace:*",
"@woocommerce/tracks": "workspace:*",
"@wordpress/babel-preset-default": "^6.17.0",
@ -308,6 +309,10 @@
"node_modules/@woocommerce/remote-logging/build",
"node_modules/@woocommerce/remote-logging/build-module",
"node_modules/@woocommerce/remote-logging/build-types",
"node_modules/@woocommerce/settings-editor/build",
"node_modules/@woocommerce/settings-editor/build-module",
"node_modules/@woocommerce/settings-editor/build-style",
"node_modules/@woocommerce/settings-editor/build-types",
"node_modules/@woocommerce/product-editor/build",
"node_modules/@woocommerce/product-editor/build-module",
"node_modules/@woocommerce/product-editor/build-style",

View File

@ -59,12 +59,14 @@ const wcAdminPackages = [
'onboarding',
'block-templates',
'product-editor',
'settings-editor',
'remote-logging',
];
const getEntryPoints = () => {
const entryPoints = {
app: './client/index.js',
settings: './client/settings/index.js',
};
wcAdminPackages.forEach( ( name ) => {
entryPoints[ name ] = `${ WC_ADMIN_PACKAGES_DIR }/${ name }`;
@ -92,7 +94,8 @@ const webpackConfig = {
filename: ( data ) => {
// Output wpAdminScripts to wp-admin-scripts folder
// See https://github.com/woocommerce/woocommerce-admin/pull/3061
return wpAdminScripts.includes( data.chunk.name )
return wpAdminScripts.includes( data.chunk.name ) ||
data.chunk.name === 'settings'
? `wp-admin-scripts/[name]${ outputSuffix }.js`
: `[name]/index${ outputSuffix }.js`;
},

View File

@ -120,7 +120,14 @@ class WC_Admin_Menus {
* Add menu item.
*/
public function settings_menu() {
$settings_page = add_submenu_page( 'woocommerce', __( 'WooCommerce settings', 'woocommerce' ), __( 'Settings', 'woocommerce' ), 'manage_woocommerce', 'wc-settings', array( $this, 'settings_page' ) );
$settings_page = add_submenu_page(
'woocommerce',
__( 'WooCommerce settings', 'woocommerce' ),
__( 'Settings', 'woocommerce' ),
'manage_woocommerce',
'wc-settings',
array( $this, 'settings_page' )
);
add_action( 'load-' . $settings_page, array( $this, 'settings_page_init' ) );
}
@ -347,7 +354,12 @@ class WC_Admin_Menus {
* Init the settings page.
*/
public function settings_page() {
WC_Admin_Settings::output();
if ( Features::is_enabled( 'settings' ) ) {
echo '<div style="padding: 20px;">The current screen is: ' . esc_html( get_current_screen()->id ) . '</div>';
echo '<div id="wc-settings-page"/>';
} else {
WC_Admin_Settings::output();
}
}
/**

View File

@ -5,7 +5,7 @@
namespace Automattic\WooCommerce\Admin\Features;
use Automattic\WooCommerce\Admin\PageController;
use Automattic\WooCommerce\Internal\Admin\WCAdminAssets;
/**
* Contains backend logic for the Settings feature.
@ -37,9 +37,37 @@ class Settings {
}
add_filter( 'woocommerce_admin_shared_settings', array( __CLASS__, 'add_component_settings' ) );
// Run this after the original WooCommerce settings have been added.
add_action( 'admin_menu', array( $this, 'register_pages' ), 60 );
add_action( 'init', array( $this, 'redirect_core_settings_pages' ) );
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_settings_editor_scripts' ) );
}
/**
* Enqueue scripts for the settings editor.
*/
public function enqueue_settings_editor_scripts() {
$screen = get_current_screen();
if ( ! $screen || 'woocommerce_page_wc-settings' !== $screen->id ) {
return;
}
// Make sure the Settings Editor package is loaded.
wp_enqueue_script( 'wc-settings-editor' );
$script_handle = 'wc-admin-edit-settings';
$script_path_name = 'wp-admin-scripts/settings';
$script_assets_filename = WCAdminAssets::get_script_asset_filename( 'wp-admin-scripts', 'settings' );
$script_assets = require WC_ADMIN_ABSPATH . WC_ADMIN_DIST_JS_FOLDER . 'wp-admin-scripts/' . $script_assets_filename;
$script_version = WCAdminAssets::get_file_version( 'js', $script_assets['version'] );
wp_register_script(
$script_handle,
WCAdminAssets::get_url( $script_path_name, 'js' ),
$script_assets['dependencies'],
$script_version,
true
);
// Load the main Settings script.
wp_enqueue_script( $script_handle );
}
/**
@ -63,78 +91,4 @@ class Settings {
return $settings;
}
/**
* Registers settings pages.
*/
public function register_pages() {
$controller = PageController::get_instance();
$setting_pages = \WC_Admin_Settings::get_settings_pages();
$settings = array();
foreach ( $setting_pages as $setting_page ) {
$settings = $setting_page->add_settings_page( $settings );
}
$order = 0;
foreach ( $settings as $key => $setting ) {
$order += 10;
$settings_page = array(
'parent' => 'woocommerce-settings',
'title' => $setting,
'id' => 'settings-' . $key,
'path' => "/settings/$key",
);
// Replace the old menu with the first settings item.
if ( 10 === $order ) {
$this->replace_settings_page( $settings_page );
}
$controller->register_page( $settings_page );
}
}
/**
* Replace the Settings page in the original WooCommerce menu.
*
* @param array $page Page used to replace the original.
*/
protected function replace_settings_page( $page ) {
global $submenu;
// Check if WooCommerce parent menu has been registered.
if ( ! isset( $submenu['woocommerce'] ) ) {
return;
}
foreach ( $submenu['woocommerce'] as &$item ) {
// The "slug" (aka the path) is the third item in the array.
if ( 0 === strpos( $item[2], 'wc-settings' ) ) {
$item[2] = wc_admin_url( "&path={$page['path']}" );
}
}
}
/**
* Redirect the old settings page URLs to the new ones.
*/
public function redirect_core_settings_pages() {
/* phpcs:disable WordPress.Security.NonceVerification */
if ( ! isset( $_GET['page'] ) || 'wc-settings' !== $_GET['page'] ) {
return;
}
if ( ! current_user_can( 'manage_woocommerce' ) ) {
return;
}
$setting_pages = \WC_Admin_Settings::get_settings_pages();
$default_setting = isset( $setting_pages[0] ) ? $setting_pages[0]->get_id() : '';
$setting = isset( $_GET['tab'] ) ? sanitize_text_field( wp_unslash( $_GET['tab'] ) ) : $default_setting;
/* phpcs:enable */
wp_safe_redirect( wc_admin_url( "&path=/settings/$setting" ) );
exit;
}
}

View File

@ -279,6 +279,7 @@ class WCAdminAssets {
'wc-navigation',
'wc-block-templates',
'wc-product-editor',
'wc-settings-editor',
'wc-remote-logging',
);

File diff suppressed because it is too large Load Diff