Merge branch 'trunk' into add/blocks-injection-rule

This commit is contained in:
Ron Rennick 2023-12-14 10:11:16 -04:00
commit 5ca5d9bdab
153 changed files with 10348 additions and 1831 deletions

View File

@ -9,6 +9,3 @@ contact_links:
- name: ❓ Support Question
url: https://woo.com/document/woocommerce-self-service-guide/
about: If you have a question please see our docs or use our forums, helpdesk, or Slack community!
- name: WooCommerce Blocks
url: https://github.com/woocommerce/woocommerce-gutenberg-products-block
about: Please report issues for WooCommerce Blocks directly to it's repository.

105
.github/workflows/blocks-e2e.yml vendored Normal file
View File

@ -0,0 +1,105 @@
name: Run Blocks E2E Tests
on:
pull_request:
paths:
- 'plugins/woocommerce-blocks/**'
- 'plugins/woocommerce/src/Blocks/**'
- 'plugins/woocommerce/templates/**'
- 'plugins/woocommerce/patterns/**'
jobs:
JSE2EWithGutenberg:
if: ${{ false }} # disable until we've fixed failing tests.
strategy:
fail-fast: false
matrix:
part: [1, 2, 3, 4, 5]
name: JavaScript E2E Tests (WP latest with Gutenberg plugin)
runs-on: ubuntu-latest
defaults:
run:
working-directory: plugins/woocommerce-blocks
steps:
- uses: actions/checkout@v3
- name: Setup WooCommerce Monorepo
uses: ./.github/actions/setup-woocommerce-monorepo
with:
install: '@woocommerce/plugin-woocommerce...'
build: '@woocommerce/plugin-woocommerce'
- name: Install Jest
run: pnpm install -g jest
- name: E2E Tests (WP latest with Gutenberg plugin)
env:
WOOCOMMERCE_BLOCKS_PHASE: 3
run: |
node ./bin/wp-env-with-gutenberg.js
npm run wp-env start
npm run wp-env:config && npx cross-env NODE_CONFIG_DIR=tests/e2e-jest/config wp-scripts test-e2e --config tests/e2e-jest/config/jest.config.js --listTests > ~/.jest-e2e-tests
npx cross-env JEST_PUPPETEER_CONFIG=tests/e2e-jest/config/jest-puppeteer.config.js cross-env NODE_CONFIG_DIR=tests/e2e-jest/config wp-scripts test-e2e --config tests/e2e-jest/config/jest.config.js --runInBand --runTestsByPath $( awk 'NR % 5 == ${{ matrix.part }} - 1' < ~/.jest-e2e-tests )
- name: Upload artifacts on failure
if: ${{ failure() }}
uses: actions/upload-artifact@v3.1.2
with:
name: e2e-with-gutenberg-test-report-${{matrix.part}}
path: reports/e2e
- name: Archive flaky tests report
uses: actions/upload-artifact@v3.1.2
if: always()
with:
name: flaky-tests-report-${{ matrix.part }}
path: flaky-tests
if-no-files-found: ignore
JSE2ETests:
name: JavaScript E2E Tests (latest)
strategy:
fail-fast: false
matrix:
part: [1, 2, 3, 4, 5]
runs-on: ubuntu-latest
defaults:
run:
working-directory: plugins/woocommerce-blocks
steps:
- uses: actions/checkout@v3
- name: Setup WooCommerce Monorepo
uses: ./.github/actions/setup-woocommerce-monorepo
with:
install: '@woocommerce/plugin-woocommerce...'
build: '@woocommerce/plugin-woocommerce'
- name: Install Jest
run: pnpm install -g jest
- name: E2E Tests (WP latest)
env:
WOOCOMMERCE_BLOCKS_PHASE: 3
run: |
node ./bin/wp-env-with-wp-641.js
pnpm --filter='@woocommerce/block-library' wp-env start
pnpm wp-env:config
pnpm --filter='@woocommerce/block-library' exec cross-env NODE_CONFIG_DIR=tests/e2e-jest/config wp-scripts test-e2e --config tests/e2e-jest/config/jest.config.js --listTests > ~/.jest-e2e-tests
pnpm --filter='@woocommerce/block-library' exec cross-env JEST_PUPPETEER_CONFIG=tests/e2e-jest/config/jest-puppeteer.config.js cross-env NODE_CONFIG_DIR=tests/e2e-jest/config wp-scripts test-e2e --config tests/e2e-jest/config/jest.config.js --runInBand --runTestsByPath $( awk 'NR % 5 == ${{ matrix.part }} - 1' < ~/.jest-e2e-tests ) --listTests
pnpm --filter='@woocommerce/block-library' exec cross-env JEST_PUPPETEER_CONFIG=tests/e2e-jest/config/jest-puppeteer.config.js cross-env NODE_CONFIG_DIR=tests/e2e-jest/config wp-scripts test-e2e --config tests/e2e-jest/config/jest.config.js --runInBand --runTestsByPath $( awk 'NR % 5 == ${{ matrix.part }} - 1' < ~/.jest-e2e-tests )
- name: Upload artifacts on failure
if: ${{ failure() }}
uses: actions/upload-artifact@v3.1.2
with:
name: e2e-test-report-${{matrix.part}}
path: reports/e2e
- name: Archive flaky tests report
uses: actions/upload-artifact@v3.1.2 # v2.2.2
if: always()
with:
name: flaky-tests-report-${{ matrix.part }}
path: flaky-tests
if-no-files-found: ignore

53
.github/workflows/metrics.yml vendored Normal file
View File

@ -0,0 +1,53 @@
name: Metrics Tracking
on:
pull_request:
push:
branches: [trunk]
concurrency:
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.head_ref || github.sha }}
cancel-in-progress: true
permissions: {}
jobs:
metrics:
name: Run metrics tests
runs-on: ubuntu-20.04
permissions:
contents: read
env:
WP_ARTIFACTS_PATH: ${{ github.workspace }}/artifacts
steps:
- uses: actions/checkout@v3
- name: Setup WooCommerce Monorepo
uses: ./.github/actions/setup-woocommerce-monorepo
with:
install: '@woocommerce/plugin-woocommerce...'
build: '@woocommerce/plugin-woocommerce'
- name: Compare performance with trunk
if: github.event_name == 'pull_request'
run: cd tools/compare-perf && pnpm run compare perf $GITHUB_SHA trunk --tests-branch $GITHUB_SHA
- name: Compare performance with base branch
if: github.event_name == 'push'
# The base hash used here need to be a commit that is compatible with the current WP version
# The current one is 19f3d0884617d7ecdcf37664f648a51e2987cada
# it needs to be updated every time it becomes unsupported by the current wp-env (WP version).
# It is used as a base comparison point to avoid fluctuation in the performance metrics.
run: |
WP_VERSION=$(awk -F ': ' '/^Tested up to/{print $2}' plugins/woocommerce/readme.txt)
IFS=. read -ra WP_VERSION_ARRAY <<< "$WP_VERSION"
WP_MAJOR="${WP_VERSION_ARRAY[0]}.${WP_VERSION_ARRAY[1]}"
cd tools/compare-perf && pnpm run compare perf $GITHUB_SHA 19f3d0884617d7ecdcf37664f648a51e2987cada --tests-branch $GITHUB_SHA --wp-version "$WP_MAJOR"
- name: Archive performance results
if: success()
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
with:
name: performance-results
path: ${{ env.WP_ARTIFACTS_PATH }}/*.performance-results*.json

5
.gitignore vendored
View File

@ -104,3 +104,8 @@ changes.json
# default docs manifest
/manifest.json
# Metrics tests
/artifacts
/plugins/*/artifacts
/tools/*/artifacts

View File

@ -171,6 +171,15 @@
],
"pinVersion": "^8.13.0"
},
{
"dependencies": [
"@wordpress/e2e-test-utils-playwright"
],
"packages": [
"**"
],
"pinVersion": "wp-6.4"
},
{
"dependencies": [
"@wordpress/**"

19
bin/wp-env-with-wp-641.js Normal file
View File

@ -0,0 +1,19 @@
const fs = require( 'fs' );
const path = require( 'path' );
const wpEnvRaw = fs.readFileSync(
path.join( __dirname, '../plugins/woocommerce-blocks/.wp-env.json' )
);
const wpEnv = JSON.parse( wpEnvRaw );
// Pin the core version to 6.2.2 for Jest E2E test so we can keep the test
// passing when new WordPress versions are released. We do this because we're
// moving to Playwright and will abandon the Jest E2E tests once the migration
// is complete.
wpEnv.core = 'WordPress/WordPress#6.4.1';
// We write the new file to .wp-env.override.json (https://developer.wordpress.org/block-editor/reference-guides/packages/packages-env/#wp-env-override-json)
fs.writeFileSync(
path.join( __dirname, '..', '.wp-env.override.json' ),
JSON.stringify( wpEnv )
);

View File

@ -0,0 +1,4 @@
Significance: patch
Type: dev
Comment: Only a change to development tooling.

View File

@ -176,6 +176,7 @@
"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",

View File

@ -0,0 +1,4 @@
Significance: patch
Type: dev
Comment: Only a change to development tooling.

View File

@ -166,6 +166,7 @@
"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",

View File

@ -0,0 +1,4 @@
Significance: patch
Type: dev
Comment: Only a change to development tooling.

View File

@ -250,6 +250,7 @@
"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",

View File

@ -0,0 +1,4 @@
Significance: patch
Type: dev
Comment: Only a change to development tooling.

View File

@ -126,6 +126,7 @@
"files": [
"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",

View File

@ -0,0 +1,4 @@
Significance: patch
Type: dev
Comment: Only a change to development tooling.

View File

@ -129,6 +129,7 @@
"files": [
"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",

View File

@ -0,0 +1,4 @@
Significance: patch
Type: dev
Comment: Only a change to development tooling.

View File

@ -181,6 +181,7 @@
"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",

View File

@ -0,0 +1,4 @@
Significance: patch
Type: dev
Comment: Only a change to development tooling.

View File

@ -158,6 +158,7 @@
"files": [
"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",

View File

@ -0,0 +1,4 @@
Significance: patch
Type: dev
Comment: Only a change to development tooling.

View File

@ -136,6 +136,7 @@
"files": [
"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",

View File

@ -0,0 +1,4 @@
Significance: patch
Type: dev
Comment: Only a change to development tooling.

View File

@ -185,6 +185,7 @@
"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",

View File

@ -0,0 +1,4 @@
Significance: patch
Type: dev
Comment: Only a change to development tooling.

View File

@ -133,6 +133,7 @@
"files": [
"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",

View File

@ -0,0 +1,4 @@
Significance: patch
Type: dev
Comment: Only a change to development tooling.

View File

@ -119,6 +119,7 @@
"files": [
"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",

View File

@ -0,0 +1,4 @@
Significance: patch
Type: dev
Comment: Only a change to development tooling.

View File

@ -130,6 +130,7 @@
"files": [
"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",

View File

@ -0,0 +1,4 @@
Significance: patch
Type: dev
Comment: Only a change to development tooling.

View File

@ -139,6 +139,7 @@
"files": [
"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",

View File

@ -0,0 +1,4 @@
Significance: patch
Type: dev
Comment: Only a change to development tooling.

View File

@ -125,6 +125,7 @@
"files": [
"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",

View File

@ -0,0 +1,4 @@
Significance: patch
Type: dev
Comment: Only a change to development tooling.

View File

@ -171,6 +171,7 @@
"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",

View File

@ -0,0 +1,4 @@
Significance: patch
Type: dev
Comment: Only a change to development tooling.

View File

@ -223,6 +223,7 @@
"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",

View File

@ -0,0 +1,4 @@
Significance: minor
Type: tweak
CYS: Update copy

View File

@ -0,0 +1,5 @@
Significance: patch
Type: dev
Comment: Only a change to development tooling.

View File

@ -52,9 +52,15 @@ export const OnboardingTour = ( {
onRequestClose={ skipTour }
shouldCloseOnClickOutside={ false }
>
<span className="woocommerce-customize-store__title">
{ __(
'Our AI tool had a few issues generating your content.',
'woocommerce'
) }
</span>
<p>
{ __(
"We encountered some issues while generating content with AI. But don't worry — you can still customize the look and feel of your store, including adding your logo, and changing colors and layouts. Take a quick tour to discover what's possible.",
"But don't let that stop you! Start customizing the look and feel of your store by adding your logo and selecting your colors and layout. Take a quick tour to discover what's possible.",
'woocommerce'
) }
</p>

View File

@ -65,7 +65,7 @@ export const BusinessInfoDescription = ( {
<div className="woocommerce-cys-design-with-ai-guide">
<p>
{ __(
'The more detail you provide, the better our AI tool can do at creating your content.',
'The more detail you provide, the better job our AI can do! Try to include:',
'woocommerce'
) }
</p>

View File

@ -34,7 +34,7 @@ export const LookAndFeel = ( {
title: __( 'Contemporary', 'woocommerce' ),
key: 'Contemporary' as const,
subtitle: __(
'Clean lines, neutral colors, sleek and modern.',
'Clean lines, neutral colors, sleek and modern look.',
'woocommerce'
),
},

View File

@ -42,7 +42,7 @@ export const ToneOfVoice = ( {
title: __( 'Neutral', 'woocommerce' ),
key: 'Neutral' as const,
subtitle: __(
'Impartial tone with casual expressions and no slang.',
'Impartial tone with casual expressions without slang.',
'woocommerce'
),
},

View File

@ -210,6 +210,11 @@ body.woocommerce-customize-store.js.is-fullscreen-mode {
color: #1e1e1e;
}
span {
color: #1e1e1e;
font-weight: 700;
}
.woocommerce-customize-store__design-change-warning-modal-footer {
display: flex;
gap: 12px;

View File

@ -1,3 +1,8 @@
/**
* Internal dependencies
*/
import { ADMIN_URL } from '../../utils/admin-settings';
export const DEFAULT_TAB_KEY = 'discover';
export const MARKETPLACE_HOST = 'https://woo.com';
export const MARKETPLACE_PATH = '/extensions';
@ -11,3 +16,4 @@ export const MARKETPLACE_CART_PATH = MARKETPLACE_HOST + '/cart/';
export const MARKETPLACE_COLLABORATION_PATH =
MARKETPLACE_HOST +
'/document/managing-woocommerce-com-subscriptions/#transfer-a-woocommerce-com-subscription';
export const WP_ADMIN_PLUGIN_LIST_URL = ADMIN_URL + '/plugins.php';

View File

@ -56,7 +56,12 @@
@media screen and (min-width: $break-small) {
.woocommerce-marketplace {
&__header-account-modal {
max-width: 350px;
max-width: $modal-min-width;
&.has-size-medium {
max-width: $modal-width-medium;
width: 100%;
}
}
}
}

View File

@ -233,9 +233,11 @@
}
}
.woocommerce-marketplace__my-subscriptions .components-button.is-link {
text-decoration: none;
padding: 6px 12px;
.woocommerce-marketplace__my-subscriptions .components-button {
&.is-link {
text-decoration: none;
padding: 6px 12px;
}
}
.woocommerce-marketplace__my-subscriptions
@ -300,6 +302,7 @@
box-shadow: 0 2px 6px 0 rgba($gray-100, 0.05);
border: 1px solid var(--gutenberg-gray-100, #f0f0f0);
padding-right: $grid-unit-15;
position: relative;
&::before {
content: '';
@ -338,3 +341,52 @@
padding: 0;
}
}
.woocommerce-marketplace__header-account-modal-overlay {
.components-modal__header {
padding-bottom: $grid-unit-20;
.components-modal__header-heading {
font-weight: 400;
font-size: 20px;
line-height: 28px;
}
}
.components-notice {
padding: $grid-unit-15 $grid-unit-20;
border-left: none;
margin: $grid-unit-20 0;
&.is-warning {
background-color: var(--wp-yellow-yellow-0, #fcf9e8);
align-items: start;
&::before {
content: '';
/* stylelint-disable-next-line function-url-quotes */
background-image: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 20C16.4183 20 20 16.4183 20 12C20 7.58172 16.4183 4 12 4C7.58172 4 4 7.58172 4 12C4 16.4183 7.58172 20 12 20Z' stroke='%23614200' stroke-width='1.5'/%3E%3Cpath d='M13 7H11V13H13V7Z' fill='%23614200'/%3E%3Cpath d='M13 15H11V17H13V15Z' fill='%23614200'/%3E%3C/svg%3E");
margin-right: $grid-unit-15;
width: 24px;
height: 24px;
}
.components-notice__content {
margin: 0;
}
}
}
.components-button-group .components-button {
&.is-primary {
box-shadow: none;
}
&.is-secondary {
box-shadow: inset 0 0 0 1px var(--wp-components-color-accent, var(--wp-admin-theme-color, #3858e9));
}
}
.woocommerce-marketplace__product-card {
margin: $grid-unit-20 0;
}
}

View File

@ -23,6 +23,7 @@ import {
import { Subscription } from './types';
import { RefreshButton } from './table/actions/refresh-button';
import Notices from './notices';
import InstallModal from './table/actions/install-modal';
export default function MySubscriptions(): JSX.Element {
const { subscriptions, isLoading } = useContext( SubscriptionsContext );
@ -58,6 +59,7 @@ export default function MySubscriptions(): JSX.Element {
if ( ! wccomSettings?.isConnected ) {
return (
<div className="woocommerce-marketplace__my-subscriptions--connect">
<InstallModal />
<div className="woocommerce-marketplace__my-subscriptions__icon" />
<h2 className="woocommerce-marketplace__my-subscriptions__header">
{ __( 'Manage your subscriptions', 'woocommerce' ) }
@ -77,6 +79,7 @@ export default function MySubscriptions(): JSX.Element {
return (
<div className="woocommerce-marketplace__my-subscriptions">
<InstallModal />
<section className="woocommerce-marketplace__my-subscriptions__notices">
<Notices />
</section>

View File

@ -0,0 +1,29 @@
/**
* External dependencies
*/
import { Button } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
/**
* Internal dependencies
*/
import { getAdminSetting } from '../../../../../utils/admin-settings';
interface RenewProps {
variant?: Button.ButtonVariant;
install?: string;
}
export default function ConnectAccountButton( props: RenewProps ) {
const wccomSettings = getAdminSetting( 'wccomHelper', {} );
const url = new URL( wccomSettings?.connectURL ?? '' );
if ( props.install ) {
url.searchParams.set( 'install', props.install );
}
return (
<Button href={ url.href } variant={ props.variant ?? 'secondary' }>
{ __( 'Connect Account', 'woocommerce' ) }
</Button>
);
}

View File

@ -0,0 +1,228 @@
/**
* External dependencies
*/
import { Button, ButtonGroup, Modal, Notice } from '@wordpress/components';
import { __, sprintf } from '@wordpress/i18n';
import { getNewPath, navigateTo, useQuery } from '@woocommerce/navigation';
import {
useCallback,
useContext,
useEffect,
useState,
} from '@wordpress/element';
/**
* Internal dependencies
*/
import { Subscription } from '../../types';
import { getAdminSetting } from '../../../../../utils/admin-settings';
import Install from './install';
import { SubscriptionsContext } from '../../../../contexts/subscriptions-context';
import { MARKETPLACE_PATH, WP_ADMIN_PLUGIN_LIST_URL } from '../../../constants';
import ConnectAccountButton from './connect-account-button';
import ProductCard from '../../../product-card/product-card';
import { addNotice, subscriptionToProduct } from '../../../../utils/functions';
import { NoticeStatus } from '../../../../contexts/types';
export default function InstallModal() {
const query = useQuery();
const installingProductKey = query?.install;
const wccomSettings = getAdminSetting( 'wccomHelper', {} );
const isConnected = !! wccomSettings?.isConnected;
const [ showModal, setShowModal ] = useState< boolean >( false );
const [ isInstalled, setIsInstalled ] = useState< boolean >( false );
const { subscriptions, isLoading } = useContext( SubscriptionsContext );
const subscription: Subscription | undefined = subscriptions.find(
( s: Subscription ) => s.product_key === installingProductKey
);
const removeInstallQuery = useCallback( () => {
navigateTo( {
url: getNewPath(
{
...query,
install: undefined,
},
MARKETPLACE_PATH,
{}
),
} );
}, [ query ] );
useEffect( () => {
if ( isLoading ) {
return;
}
// If subscriptions loaded, but we don't have a subscription for the product key, show an error.
if (
installingProductKey &&
isConnected &&
! isLoading &&
! subscription
) {
addNotice(
installingProductKey,
sprintf(
/* translators: %s is the product key */
__(
'Could not find subscription with product key %s.',
'woocommerce'
),
installingProductKey
),
NoticeStatus.Error
);
removeInstallQuery();
} else {
setShowModal( !! installingProductKey );
}
}, [
isConnected,
isLoading,
installingProductKey,
removeInstallQuery,
subscription,
] );
useEffect( () => {
if ( subscription && subscription.local.installed ) {
setIsInstalled( true );
}
}, [ subscription ] );
const onClose = () => {
removeInstallQuery();
setShowModal( false );
};
const modalTitle = () => {
if ( isInstalled ) {
return __( 'You are ready to go!', 'woocommerce' );
}
return __( 'Add to store', 'woocommerce' );
};
const modalContent = () => {
if ( ! isConnected ) {
return (
<Notice status="warning" isDismissible={ false }>
{ __(
'In order to install a product, you need to first connect your account.',
'woocommerce'
) }
</Notice>
);
} else if ( subscription ) {
const installContent = isInstalled
? __(
'Keep the momentum going and start setting up your extension.',
'woocommerce'
)
: __(
'Would you like to install this extension?',
'woocommerce'
);
return (
<>
<p className="woocommerce-marketplace__header-account-modal-text">
{ installContent }
</p>
<ProductCard
product={ subscriptionToProduct( subscription ) }
small={ true }
tracksData={ {
position: 1,
group: 'subscriptions',
label: 'install',
} }
/>
</>
);
}
};
const modalButtons = () => {
const buttons = [];
if ( isInstalled ) {
buttons.push(
<Button
variant="secondary"
href={ subscription?.documentation_url }
target="_blank"
className="woocommerce-marketplace__header-account-modal-button"
key={ 'docs' }
>
{ __( 'View docs', 'woocommerce' ) }
</Button>
);
buttons.push(
<Button
variant="primary"
href={ WP_ADMIN_PLUGIN_LIST_URL }
className="woocommerce-marketplace__header-account-modal-button"
key={ 'plugin-list' }
>
{ __( 'View in Plugins', 'woocommerce' ) }
</Button>
);
} else {
buttons.push(
<Button
variant="tertiary"
onClick={ onClose }
className="woocommerce-marketplace__header-account-modal-button"
key={ 'cancel' }
>
{ __( 'Cancel', 'woocommerce' ) }
</Button>
);
if ( ! isConnected ) {
buttons.push(
<ConnectAccountButton
variant="primary"
install={ installingProductKey }
key={ 'connect' }
/>
);
} else if ( subscription ) {
buttons.push(
<Install
subscription={ subscription }
variant="primary"
onError={ onClose }
key={ 'install' }
/>
);
}
}
return (
<ButtonGroup className="woocommerce-marketplace__header-account-modal-button-group">
{ buttons }
</ButtonGroup>
);
};
if ( ! showModal ) {
return null;
}
return (
<Modal
title={ modalTitle() }
onRequestClose={ onClose }
focusOnMount={ true }
className="woocommerce-marketplace__header-account-modal has-size-medium"
style={ { borderRadius: 4 } }
overlayClassName="woocommerce-marketplace__header-account-modal-overlay"
>
{ modalContent() }
{ modalButtons() }
</Modal>
);
}

View File

@ -22,6 +22,9 @@ import { NoticeStatus } from '../../../../contexts/types';
interface InstallProps {
subscription: Subscription;
variant?: Button.ButtonVariant;
onSuccess?: () => void;
onError?: () => void;
}
export default function Install( props: InstallProps ) {
@ -76,6 +79,10 @@ export default function Install( props: InstallProps ) {
product_id: props.subscription.product_id,
product_current_version: props.subscription.version,
} );
if ( props.onSuccess ) {
props.onSuccess();
}
} )
.catch( ( error ) => {
loadSubscriptions( false ).then( () => {
@ -101,19 +108,24 @@ export default function Install( props: InstallProps ) {
}
);
stopInstall();
if ( props.onError ) {
props.onError();
}
} );
recordEvent( 'marketplace_product_install_failed', {
product_zip_slug: props.subscription.zip_slug,
product_id: props.subscription.product_id,
product_current_version: props.subscription.version,
error_message: error?.data?.message,
} );
} );
};
return (
<Button
variant="link"
variant={ props.variant ?? 'link' }
isBusy={ loading }
disabled={ loading }
onClick={ install }

View File

@ -59,6 +59,28 @@
}
}
&.is-small {
padding: $medium-gap;
.woocommerce-marketplace__product-card__description,
.woocommerce-marketplace__product-card__price {
display: none;
}
.woocommerce-marketplace__product-card__content {
display: block;
}
.woocommerce-marketplace__product-card__details {
align-items: center;
}
.woocommerce-marketplace__product-card__title {
font-size: 14px;
line-height: 20px;
}
}
&:hover {
outline: 1.5px solid var(--wp-admin-theme-color);
}

View File

@ -19,6 +19,7 @@ export interface ProductCardProps {
product?: Product;
isLoading?: boolean;
tracksData: ProductTracksData;
small?: boolean;
}
function ProductCard( props: ProductCardProps ): JSX.Element {
@ -102,6 +103,7 @@ function ProductCard( props: ProductCardProps ): JSX.Element {
`woocommerce-marketplace__product-card--${ type }`,
{
'is-loading': isLoading,
'is-small': props.small,
}
);

View File

@ -33,3 +33,8 @@ $wp-gray-0: $gray-0;
$wp-gray-50: $gray-50;
$wp-gray-60: $gray-60;
$skeleton-loader-color: #f0f0f0;
// Modal
$modal-min-width: 350px;
$modal-width-small: 384px;
$modal-width-medium: 512px;

View File

@ -364,6 +364,23 @@ const removeNotice = ( productKey: string ) => {
dispatch( noticeStore ).removeNotice( productKey );
};
const subscriptionToProduct = ( subscription: Subscription ): Product => {
return {
id: subscription.product_id,
title: subscription.product_name,
image: '',
type: subscription.product_type as ProductType,
description: '',
vendorName: '',
vendorUrl: '',
icon: subscription.product_icon,
url: subscription.product_url,
price: -1,
averageRating: 0,
reviewsCount: 0,
};
};
// Append UTM parameters to a URL, being aware of existing query parameters
const appendURLParams = (
url: string,
@ -412,4 +429,5 @@ export {
removeNotice,
renewUrl,
subscribeUrl,
subscriptionToProduct,
};

View File

@ -33,7 +33,7 @@ const CustomizeStoreHeader = ( {
<h1>{ __( 'Start customizing your store', 'woocommerce' ) }</h1>
<p>
{ __(
'Quickly create a beautiful looking store using our built-in store designer, or select a pre-built theme and customize it to fit your brand.',
'Use our built-in AI tools to design your store and populate it with content, or select a pre-built theme and customize it to fit your brand.',
'woocommerce'
) }
</p>

View File

@ -17,6 +17,7 @@
},
"extra": {
"changelogger": {
"changes-dir": "../woocommerce/changelog",
"formatter": {
"filename": "../../tools/changelogger/class-package-formatter.php"
},

1071
plugins/woocommerce-admin/composer.lock generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -294,6 +294,7 @@
"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/explat/build",
"node_modules/@woocommerce/explat/build-module",
"node_modules/@woocommerce/explat/build-types",

View File

@ -1,21 +1,19 @@
{
"core": null,
"plugins": [
"https://downloads.wordpress.org/plugin/woocommerce.latest-stable.zip",
"https://github.com/WP-API/Basic-Auth/archive/master.zip",
"https://downloads.wordpress.org/plugin/wordpress-importer.0.8.zip",
"./tests/mocks/woo-test-helper",
"."
"../woocommerce"
],
"env": {
"tests": {
"mappings": {
"wp-content/mu-plugins": "./node_modules/@wordpress/e2e-tests/mu-plugins",
"wp-content/plugins/gutenberg-test-plugins": "./node_modules/@wordpress/e2e-tests/plugins",
"wp-content/plugins/woocommerce-blocks": ".",
"wp-content/plugins/woocommerce-gutenberg-products-block": ".",
"wp-cli.yml": "./wp-cli.yml",
"custom-plugins" : "./tests/e2e/mocks/custom-plugins"
"custom-plugins": "./tests/e2e/mocks/custom-plugins",
"wp-content/plugins/woocommerce/blocks-bin": "./bin"
}
}
},

View File

@ -3,6 +3,8 @@
*/
import { gallery as icon } from '@wordpress/icons';
import { registerBlockSingleProductTemplate } from '@woocommerce/atomic-utils';
import { createBlock } from '@wordpress/blocks';
import { isExperimentalBuild } from '@woocommerce/block-settings';
/**
* Internal dependencies
@ -11,6 +13,8 @@ import edit from './edit';
import metadata from './block.json';
import './style.scss';
const galleryBlock = isExperimentalBuild() ? 'woocommerce/product-gallery' : '';
registerBlockSingleProductTemplate( {
blockName: metadata.name,
// @ts-expect-error: `metadata` currently does not have a type definition in WordPress core
@ -19,6 +23,17 @@ registerBlockSingleProductTemplate( {
icon,
// @ts-expect-error `edit` can be extended to include other attributes
edit,
transforms: {
to: [
{
type: 'block',
blocks: [ galleryBlock ],
transform: () => {
return createBlock( galleryBlock );
},
},
],
},
},
isAvailableOnPostEditor: false,
} );

View File

@ -6,12 +6,17 @@ import { isWpVersion } from '@woocommerce/settings';
import { BlockInstance, createBlock } from '@wordpress/blocks';
import { VARIATION_NAME as PRODUCT_TITLE_VARIATION_NAME } from '@woocommerce/blocks/product-query/variations/elements/product-title';
import { VARIATION_NAME as PRODUCT_SUMMARY_VARIATION_NAME } from '@woocommerce/blocks/product-query/variations/elements/product-summary';
import { isExperimentalBuild } from '@woocommerce/block-settings';
/**
* Internal dependencies
*/
import { OnClickCallbackParameter } from './types';
const galleryBlock = isExperimentalBuild()
? 'woocommerce/product-gallery'
: 'woocommerce/product-image-gallery';
const getBlockifiedTemplate = () =>
[
createBlock( 'woocommerce/breadcrumbs' ),
@ -29,7 +34,7 @@ const getBlockifiedTemplate = () =>
justifyContent: 'right',
width: '512px',
},
[ createBlock( 'woocommerce/product-image-gallery' ) ]
[ createBlock( galleryBlock ) ]
),
createBlock( 'core/column', {}, [
createBlock( 'core/post-title', {

View File

@ -5,6 +5,8 @@ import { registerPaymentMethod } from '@woocommerce/blocks-registry';
import { __ } from '@wordpress/i18n';
import { getPaymentMethodData } from '@woocommerce/settings';
import { decodeEntities } from '@wordpress/html-entities';
import { sanitizeHTML } from '@woocommerce/utils';
import { RawHTML } from '@wordpress/element';
/**
* Internal dependencies
@ -19,7 +21,7 @@ const label = decodeEntities( settings?.title || '' ) || defaultLabel;
* Content component
*/
const Content = () => {
return decodeEntities( settings.description || '' );
return <RawHTML>{ sanitizeHTML( settings.description || '' ) }</RawHTML>;
};
/**

View File

@ -5,6 +5,8 @@ import { registerPaymentMethod } from '@woocommerce/blocks-registry';
import { __ } from '@wordpress/i18n';
import { getPaymentMethodData } from '@woocommerce/settings';
import { decodeEntities } from '@wordpress/html-entities';
import { sanitizeHTML } from '@woocommerce/utils';
import { RawHTML } from '@wordpress/element';
/**
* Internal dependencies
@ -19,7 +21,7 @@ const label = decodeEntities( settings?.title || '' ) || defaultLabel;
* Content component
*/
const Content = () => {
return decodeEntities( settings.description || '' );
return <RawHTML>{ sanitizeHTML( settings.description || '' ) }</RawHTML>;
};
/**

View File

@ -5,6 +5,8 @@ import { registerPaymentMethod } from '@woocommerce/blocks-registry';
import { __ } from '@wordpress/i18n';
import { getPaymentMethodData } from '@woocommerce/settings';
import { decodeEntities } from '@wordpress/html-entities';
import { sanitizeHTML } from '@woocommerce/utils';
import { RawHTML } from '@wordpress/element';
/**
* Internal dependencies
@ -19,7 +21,7 @@ const label = decodeEntities( settings?.title || '' ) || defaultLabel;
* Content component
*/
const Content = () => {
return decodeEntities( settings.description || '' );
return <RawHTML>{ sanitizeHTML( settings.description || '' ) }</RawHTML>;
};
/**

View File

@ -5,6 +5,8 @@ import { registerPaymentMethod } from '@woocommerce/blocks-registry';
import { __ } from '@wordpress/i18n';
import { getPaymentMethodData, WC_ASSET_URL } from '@woocommerce/settings';
import { decodeEntities } from '@wordpress/html-entities';
import { sanitizeHTML } from '@woocommerce/utils';
import { RawHTML } from '@wordpress/element';
/**
* Internal dependencies
@ -17,7 +19,7 @@ const settings = getPaymentMethodData( 'paypal', {} );
* Content component
*/
const Content = () => {
return decodeEntities( settings.description || '' );
return <RawHTML>{ sanitizeHTML( settings.description || '' ) }</RawHTML>;
};
const paypalPaymentMethod = {

View File

@ -21,7 +21,8 @@ wp wc customer update 1 --user=1 --billing='{"first_name":"John","last_name":"Do
## Prepare translation for the test suite
wp language core install nl_NL
wp language plugin install woocommerce nl_NL
wp plugin activate woocommerce-blocks
## No need to install the plugin anymore
# wp plugin activate woocommerce-blocks
## We download a full version of .po (that has translation for js files as well).
curl https://translate.wordpress.org/projects/wp-plugins/woo-gutenberg-products-block/stable/nl/default/export-translations/ --output ./wp-content/languages/plugins/woo-gutenberg-products-block-nl_NL.po
sleep 5

View File

@ -1,4 +1,4 @@
#!/bin/sh
BASENAME=$(basename "`pwd`")
# We need to pass the blocks plugin folder name to the script, the name can change depending on your local env and we can't hardcode it.
npm run wp-env run tests-cli './wp-content/plugins/'$BASENAME'/bin/wp-env-config.sh' $BASENAME
npm run wp-env run tests-cli './wp-content/plugins/woocommerce/blocks-bin/wp-env-config.sh' woocommerce

View File

@ -0,0 +1,3 @@
Significance: patch
Type: tweak
Comment: Product Gallery: Add transforms for better discovery.

View File

@ -0,0 +1,4 @@
Significance: patch
Type: dev
Comment: Just a change to the `.wp-env` config.

View File

@ -0,0 +1,4 @@
Significance: patch
Type: update
Allow built in payment method descriptions to contain HTML when rendered on the block checkout.

View File

@ -15,13 +15,12 @@
"php": "7.4"
},
"allow-plugins": {
"composer/installers": true,
"dealerdirect/phpcodesniffer-composer-installer": true,
"automattic/jetpack-autoloader": true
}
},
"extra": {
"changelogger": {
"changes-dir": "../woocommerce/changelog",
"formatter": {
"filename": "../../tools/changelogger/class-package-formatter.php"
},

View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "7ce541cc88ff7d19723d117c1ac3a59b",
"content-hash": "40f1e35cfc32070fda05769f2f481d39",
"packages": [],
"packages-dev": [
{

View File

@ -37,7 +37,7 @@ module.exports = {
],
transformIgnorePatterns: [
'node_modules/?!(simple-html-tokenizer|is-plain-obj|is-plain-object|memize)',
'node_modules/@woocommerce/e2e-utils/node_modules/config',
'node_modules/config',
],
testMatch: [ '**/?(*.)+(spec|test).[jt]s?(x)' ],
};

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 17 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 7.4 KiB

View File

@ -2,11 +2,11 @@
"minimum-stability": "dev",
"prefer-stable": true,
"require-dev": {
"phpunit/phpunit": "6.5.14"
"phpunit/phpunit": "^9.6"
},
"config": {
"platform": {
"php": "7.0"
"php": "7.4"
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,4 @@
Significance: patch
Type: fix
Fix Shipping Settings add method modal description to allow for large text and links in the text

View File

@ -0,0 +1,4 @@
Significance: minor
Type: add
Add subscription install modal.

View File

@ -0,0 +1,4 @@
Significance: patch
Type: update
Update Shipping Settings zone method modal spinner on modal primary button.

View File

@ -0,0 +1,4 @@
Significance: minor
Type: tweak
CYS: Update copy.

View File

@ -0,0 +1,4 @@
Significance: minor
Type: fix
Fix: CYS - fix path images patterns.

View File

@ -0,0 +1,4 @@
Significance: patch
Type: dev
Comment: Just a fix to a test file.

View File

@ -0,0 +1,4 @@
Significance: minor
Type: enhancement
Update the pattern imageSizing to single.

View File

@ -0,0 +1,4 @@
Significance: minor
Type: fix
Revert Shipping Settings change of replacing tables, replace only for use in JS powered modals.

View File

@ -0,0 +1,4 @@
Significance: patch
Type: dev
Comment: Only a change to development tooling.

View File

@ -0,0 +1,5 @@
Significance: patch
Type: dev
Comment: It's a build process E2E change.

View File

@ -0,0 +1,4 @@
Significance: minor
Type: add
Added Easyship promotion to shipping task for AU, NZ, SG, HK. Removed SkydropX.

View File

@ -0,0 +1,5 @@
Significance: patch
Type: dev
Comment: This is only a change to the way changelogs are generated.

View File

@ -0,0 +1,4 @@
Significance: patch
Type: update
Allow built in payment method descriptions to contain HTML when rendered on the block checkout.

View File

@ -4223,17 +4223,14 @@ table.wc_shipping {
margin: 12px 0;
border-radius: 4px;
}
}
.wc-shipping-zone-method-input-help-text {
position: absolute;
bottom: -30px;
height: 30px;
display: none;
}
.wc-shipping-zone-method-input-help-text-container {
min-height: 40px;
}
input:checked ~ .wc-shipping-zone-method-input-help-text {
display: block;
}
.wc-shipping-zone-method-input-help-text {
display: none;
}
.wc-shipping-zone-method-selector {
@ -4358,6 +4355,21 @@ table.wc_shipping {
.wc-backbone-modal-back-inactive {
display: none;
}
#btn-next.is-busy {
background-image: linear-gradient(-45deg, #fafafa 33%, #e0e0e0 33%, #e0e0e0 70%, #fafafa 70%);
animation-duration: 2.5s;
animation-timing-function: linear;
animation-delay: 0s;
animation-iteration-count: infinite;
animation-direction: normal;
animation-fill-mode: none;
animation-play-state: running;
animation-name: components-button__busy-animation;
animation-timeline: auto;
animation-range-start: normal;
color: #757575;
}
}
.wc-backbone-modal-add-shipping-method .wc-backbone-modal-main article {

View File

@ -409,6 +409,15 @@
});
$( '.wc-shipping-zone-method-selector select' ).trigger( 'change' );
$('.wc-shipping-zone-method-input input').change( function() {
const selected = $('.wc-shipping-zone-method-input input:checked');
const id = selected.attr( 'id' );
const description = $( `#${ id }-description` );
const descriptions = $( '.wc-shipping-zone-method-input-help-text' );
descriptions.css( 'display', 'none' );
description.css( 'display', 'block' );
});
},
/**
* The settings HTML is controlled and built by the settings api, so in order to refactor the
@ -510,11 +519,13 @@
// `<table class="form-table" />` elements added by the Settings API need to be removed.
// Modern browsers won't interpret other table elements like `td` not in a `table`, so
// Removing the `table` is sufficient.
const htmlContent = $( html );
const tables = htmlContent.find( 'table.form-table' );
const originalTable = $( html );
const htmlContent = $( '<div class="wc-shipping-zone-method-fields" />' );
htmlContent.html( originalTable.html() );
tables.each( ( i ) => {
const table = $( tables[ i ] );
const innerTables = htmlContent.find( 'table.form-table' );
innerTables.each( ( i ) => {
const table = $( innerTables[ i ] );
const div = $( '<div class="wc-shipping-zone-method-fields" />' );
div.html( table.html() );
table.replaceWith( div );
@ -526,7 +537,7 @@
if ( 'wc-modal-add-shipping-method' === target ) {
shippingMethodView.block();
$('#btn-next').html('<img alt="processing" src="images/wpspin_light.gif" class="waiting" />');
$('#btn-next').addClass( 'is-busy' );
// Add method to zone via ajax call
$.post( ajaxurl + ( ajaxurl.indexOf( '?' ) > 0 ? '&' : '?' ) + 'action=woocommerce_shipping_zone_add_method', {

View File

@ -38,7 +38,6 @@
"grunt-sass": "3.1.0",
"grunt-stylelint": "0.16.0",
"gruntify-eslint": "5.0.0",
"nodemon": "^2.0.22",
"sass": "^1.69.5",
"stylelint": "13.8.0",
"wireit": "0.14.1"

View File

@ -33,11 +33,10 @@
"bamarni/composer-bin-plugin": "^1.4",
"dms/phpunit-arraysubset-asserts": "^0.4.0",
"mockery/mockery": "1.6.6",
"phpunit/phpunit": "^9.0",
"phpunit/phpunit": "^9.6",
"sebastian/comparator": "^4.0",
"yoast/phpunit-polyfills": "^2.0",
"woocommerce/monorepo-plugin": "*",
"wp-hooks/generator": "0.9.0"
"woocommerce/monorepo-plugin": "*"
},
"config": {
"optimize-autoloader": true,

File diff suppressed because it is too large Load Diff

View File

@ -460,7 +460,7 @@ abstract class WC_Shipping_Method extends WC_Settings_API {
$settings_html = $this->generate_settings_html( $this->get_form_fields(), false );
}
return '<div class="wc-shipping-zone-method-fields">' . $settings_html . '</div>';
return '<table class="form-table">' . $settings_html . '</table>';
}
/**

Some files were not shown because too many files have changed in this diff Show More