Add initial product data views screen (#50981)
* Add product data views feature flag * Add basic products app file * Add lazy render for product app * Only render if GB is enabled * Add translation * Add changelogs * Address lint issues * Address final lint error
This commit is contained in:
parent
cf042dfb0a
commit
f2941d76e5
|
@ -199,7 +199,8 @@
|
|||
"@wordpress/viewport",
|
||||
"@wordpress/interface",
|
||||
"@wordpress/router",
|
||||
"@wordpress/edit-site"
|
||||
"@wordpress/edit-site",
|
||||
"@wordpress/private-apis"
|
||||
],
|
||||
"packages": [
|
||||
"@woocommerce/block-templates",
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Significance: minor
|
||||
Type: add
|
||||
|
||||
Add new product data views component for use on new product data views page.
|
|
@ -71,6 +71,7 @@
|
|||
"@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",
|
||||
|
|
|
@ -35,6 +35,11 @@ export * from './contexts/validation-context/types';
|
|||
export { EditorLoadingContext as __experimentalEditorLoadingContext } from './contexts/editor-loading-context';
|
||||
export { PostTypeContext } from './contexts/post-type-context';
|
||||
|
||||
/**
|
||||
* Product data views page.
|
||||
*/
|
||||
export * from './products';
|
||||
|
||||
// Init the store
|
||||
registerProductEditorUiStore();
|
||||
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/private-apis';
|
||||
|
||||
export const { lock, unlock } =
|
||||
__dangerousOptInToUnstableAPIsOnlyForCoreModules(
|
||||
'I acknowledge private features are not for use in themes or plugins and doing so will break in the next version of WordPress.',
|
||||
'@wordpress/edit-site'
|
||||
);
|
|
@ -0,0 +1,33 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { createElement } from '@wordpress/element';
|
||||
import { privateApis as routerPrivateApis } from '@wordpress/router';
|
||||
import {
|
||||
UnsavedChangesWarning,
|
||||
// @ts-expect-error No types for this exist yet.
|
||||
privateApis as editorPrivateApis,
|
||||
} from '@wordpress/editor';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { unlock } from '../lock-unlock';
|
||||
|
||||
const { RouterProvider } = unlock( routerPrivateApis );
|
||||
const { GlobalStylesProvider } = unlock( editorPrivateApis );
|
||||
|
||||
function ProductsLayout() {
|
||||
return <div>Initial Products Layout</div>;
|
||||
}
|
||||
|
||||
export function ProductsApp() {
|
||||
return (
|
||||
<GlobalStylesProvider>
|
||||
<UnsavedChangesWarning />
|
||||
<RouterProvider>
|
||||
<ProductsLayout />
|
||||
</RouterProvider>
|
||||
</GlobalStylesProvider>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
@include wordpress-admin-schemes();
|
||||
|
||||
.woocommerce_page_woocommerce-products-dashboard #wpadminbar,
|
||||
.woocommerce_page_woocommerce-products-dashboard #adminmenumain {
|
||||
display: none;
|
||||
}
|
||||
.woocommerce_page_woocommerce-products-dashboard #wpcontent {
|
||||
margin-left: 0;
|
||||
}
|
||||
body.woocommerce_page_woocommerce-products-dashboard
|
||||
#woocommerce-products-dashboard {
|
||||
@include wp-admin-reset("#woocommerce-products-dashboard");
|
||||
@include reset;
|
||||
display: block !important;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
body.js.is-fullscreen-mode {
|
||||
@include break-medium {
|
||||
// Reset the html.wp-topbar padding.
|
||||
// Because this uses negative margins, we have to compensate for the height.
|
||||
margin-top: -$admin-bar-height;
|
||||
height: calc(100% + #{$admin-bar-height});
|
||||
|
||||
#adminmenumain,
|
||||
#wpadminbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#wpcontent,
|
||||
#wpfooter {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import {
|
||||
StrictMode,
|
||||
Suspense,
|
||||
createElement,
|
||||
// @ts-expect-error createRoot is available.
|
||||
createRoot,
|
||||
lazy,
|
||||
} from '@wordpress/element';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { getGutenbergVersion } from './utils/get-gutenberg-version';
|
||||
|
||||
const ProductsApp = lazy( () =>
|
||||
import( './products-app' ).then( ( module ) => ( {
|
||||
default: module.ProductsApp,
|
||||
} ) )
|
||||
);
|
||||
|
||||
/**
|
||||
* Initializes the "Products Dashboard".
|
||||
*
|
||||
* @param {string} id DOM element id.
|
||||
*/
|
||||
export function initializeProductsDashboard( id: string ) {
|
||||
const target = document.getElementById( id );
|
||||
const root = createRoot( target );
|
||||
const isGutenbergEnabled = getGutenbergVersion() > 0;
|
||||
|
||||
root.render(
|
||||
<StrictMode>
|
||||
{ isGutenbergEnabled ? (
|
||||
<Suspense fallback={ null }>
|
||||
<ProductsApp />
|
||||
</Suspense>
|
||||
) : (
|
||||
<div>
|
||||
{ __(
|
||||
'Please enabled Gutenberg for this feature',
|
||||
'woocommerce'
|
||||
) }
|
||||
</div>
|
||||
) }
|
||||
</StrictMode>
|
||||
);
|
||||
|
||||
return root;
|
||||
}
|
|
@ -60,3 +60,5 @@
|
|||
|
||||
/* Hooks */
|
||||
@import "hooks/use-draggable/styles.scss";
|
||||
|
||||
@import "products.scss";
|
||||
|
|
|
@ -25,9 +25,21 @@ declare module '@wordpress/core-data' {
|
|||
name: string,
|
||||
id: number | string,
|
||||
options?: { enabled: boolean }
|
||||
): { record: T, editedRecord: T, isResolving: boolean, hasResolved: boolean };
|
||||
): {
|
||||
record: T;
|
||||
editedRecord: T;
|
||||
isResolving: boolean;
|
||||
hasResolved: boolean;
|
||||
};
|
||||
}
|
||||
declare module '@wordpress/keyboard-shortcuts' {
|
||||
function useShortcut(name: string, callback: (event: KeyboardEvent) => void): void;
|
||||
function useShortcut(
|
||||
name: string,
|
||||
callback: ( event: KeyboardEvent ) => void
|
||||
): void;
|
||||
const store;
|
||||
}
|
||||
|
||||
declare module '@wordpress/router' {
|
||||
const privateApis;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Significance: minor
|
||||
Type: add
|
||||
|
||||
Add new feature for a product data views page.
|
|
@ -3,6 +3,7 @@
|
|||
"activity-panels": true,
|
||||
"analytics": true,
|
||||
"product-block-editor": true,
|
||||
"product-data-views": false,
|
||||
"experimental-blocks": false,
|
||||
"coupons": true,
|
||||
"core-profiler": true,
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
"activity-panels": true,
|
||||
"analytics": true,
|
||||
"product-block-editor": true,
|
||||
"product-data-views": false,
|
||||
"experimental-blocks": true,
|
||||
"coupons": true,
|
||||
"core-profiler": true,
|
||||
|
|
|
@ -0,0 +1,145 @@
|
|||
<?php
|
||||
/**
|
||||
* WooCommerce Product Data Views
|
||||
*/
|
||||
|
||||
declare( strict_types = 1 );
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\Features\ProductDataViews;
|
||||
|
||||
use Automattic\Jetpack\Constants;
|
||||
use Automattic\WooCommerce\Blocks\Utils\Utils;
|
||||
use Automattic\WooCommerce\Internal\Admin\WCAdminAssets;
|
||||
|
||||
/**
|
||||
* Loads assets related to the product block editor.
|
||||
*/
|
||||
class Init {
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct() {
|
||||
if ( $this->has_data_views_support() ) {
|
||||
add_action( 'admin_menu', array( $this, 'woocommerce_add_new_products_dashboard' ) );
|
||||
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_styles' ) );
|
||||
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
|
||||
|
||||
if ( $this->is_product_data_view_page() ) {
|
||||
add_filter(
|
||||
'admin_body_class',
|
||||
static function ( $classes ) {
|
||||
return "$classes is-fullscreen-mode";
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if we are on a JS powered admin page.
|
||||
*/
|
||||
private static function is_product_data_view_page() {
|
||||
// phpcs:disable WordPress.Security.NonceVerification
|
||||
return isset( $_GET['page'] ) && 'woocommerce-products-dashboard' === $_GET['page'];
|
||||
// phpcs:enable WordPress.Security.NonceVerification
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks for data views support.
|
||||
*/
|
||||
private function has_data_views_support() {
|
||||
if ( Utils::wp_version_compare( '6.6', '>=' ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( is_plugin_active( 'gutenberg/gutenberg.php' ) ) {
|
||||
$gutenberg_version = '';
|
||||
|
||||
if ( defined( 'GUTENBERG_VERSION' ) ) {
|
||||
$gutenberg_version = GUTENBERG_VERSION;
|
||||
}
|
||||
|
||||
if ( ! $gutenberg_version ) {
|
||||
$gutenberg_data = get_file_data(
|
||||
WP_PLUGIN_DIR . '/gutenberg/gutenberg.php',
|
||||
array( 'Version' => 'Version' )
|
||||
);
|
||||
$gutenberg_version = $gutenberg_data['Version'];
|
||||
}
|
||||
return version_compare( $gutenberg_version, '19.0', '>=' );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue styles needed for the rich text editor.
|
||||
*/
|
||||
public function enqueue_styles() {
|
||||
if ( ! $this->is_product_data_view_page() ) {
|
||||
return;
|
||||
}
|
||||
wp_enqueue_style( 'wc-product-editor' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue scripts needed for the product form block editor.
|
||||
*/
|
||||
public function enqueue_scripts() {
|
||||
if ( ! $this->is_product_data_view_page() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$script_handle = 'wc-admin-edit-product';
|
||||
wp_register_script( $script_handle, '', array( 'wp-blocks' ), '0.1.0', true );
|
||||
wp_enqueue_script( $script_handle );
|
||||
wp_enqueue_media();
|
||||
wp_register_style( 'wc-global-presets', false ); // phpcs:ignore
|
||||
wp_add_inline_style( 'wc-global-presets', wp_get_global_stylesheet( array( 'presets' ) ) );
|
||||
wp_enqueue_style( 'wc-global-presets' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the default posts menu item with the new posts dashboard.
|
||||
*/
|
||||
public function woocommerce_add_new_products_dashboard() {
|
||||
$gutenberg_experiments = get_option( 'gutenberg-experiments' );
|
||||
if ( ! $gutenberg_experiments ) {
|
||||
return;
|
||||
}
|
||||
$ptype_obj = get_post_type_object( 'product' );
|
||||
add_submenu_page(
|
||||
'woocommerce',
|
||||
$ptype_obj->labels->name,
|
||||
esc_html__( 'All Products', 'woocommerce' ),
|
||||
'manage_woocommerce',
|
||||
'woocommerce-products-dashboard',
|
||||
array( $this, 'woocommerce_products_dashboard' ),
|
||||
1
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the new posts dashboard page.
|
||||
*/
|
||||
public function woocommerce_products_dashboard() {
|
||||
$suffix = Constants::is_true( 'SCRIPT_DEBUG' ) ? '' : '.min';
|
||||
$version = Constants::get_constant( 'WC_VERSION' );
|
||||
if ( function_exists( 'gutenberg_url' ) ) {
|
||||
// phpcs:disable WordPress.WP.EnqueuedResourceParameters.MissingVersion
|
||||
wp_register_style(
|
||||
'wp-gutenberg-posts-dashboard',
|
||||
gutenberg_url( 'build/edit-site/posts.css', __FILE__ ),
|
||||
array( 'wp-components' ),
|
||||
);
|
||||
// phpcs:enable WordPress.WP.EnqueuedResourceParameters.MissingVersion
|
||||
wp_enqueue_style( 'wp-gutenberg-posts-dashboard' );
|
||||
}
|
||||
WCAdminAssets::get_instance();
|
||||
wp_enqueue_script( 'wc-admin-product-editor', WC()->plugin_url() . '/assets/js/admin/product-editor' . $suffix . '.js', array( 'wc-product-editor' ), $version, false );
|
||||
wp_add_inline_script( 'wp-edit-site', 'window.wc.productEditor.initializeProductsDashboard( "woocommerce-products-dashboard" );', 'after' );
|
||||
wp_enqueue_script( 'wp-edit-site' );
|
||||
|
||||
echo '<div id="woocommerce-products-dashboard"></div>';
|
||||
}
|
||||
}
|
1167
pnpm-lock.yaml
1167
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue