Merge branch 'trunk' into update/32508_pnpx_deprecated

This commit is contained in:
Joel Thiessen 2022-04-13 12:35:29 -07:00 committed by GitHub
commit 0a0c6b45cf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
213 changed files with 5269 additions and 1852 deletions

View File

@ -25,13 +25,10 @@ Closes # .
* [ ] Have you added an explanation of what your changes do and why you'd like us to include them?
* [ ] Have you written new tests for your changes, as applicable?
* [ ] Have you successfully run tests with your changes locally?
* [ ] Have you created a changelog file by running `pnpm nx affected --target=changelog`?
<!-- Mark completed items with an [x] -->
### Changelog entry
> Enter a summary of all changes on this Pull Request. This will appear in the changelog if accepted.
### FOR PR REVIEWER ONLY:
* [ ] I have reviewed that everything is sanitized/escaped appropriately for any SQL or XSS injection possibilities. I made sure Linting is not ignored or disabled.

View File

@ -1,4 +1,4 @@
name: Run lint checks potentially affected projects across the monorepo
name: Run lint checks potentially affecting projects across the monorepo
on: pull_request
concurrency:
group: changelogger-${{ github.event_name }}-${{ github.ref }}
@ -9,10 +9,10 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 10
fetch-depth: 0
- name: Setup PHP
uses: shivammathur/setup-php@v2

View File

@ -57,7 +57,6 @@ echo "The pull request was merged by: $merger_user_name\n";
$comment_body = "Hi @$merger_user_name, thanks for merging this pull request. Please take a look at these follow-up tasks you may need to perform:
- [ ] Add the `release: add changelog` label
- [ ] Add the `release: add testing instructions` label";
$add_comment_mutation = "

5
.husky/post-merge Executable file
View File

@ -0,0 +1,5 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
pnpm install
pnpm nx affected --target="composer-install" --base=ORIG_HEAD --head=HEAD

View File

@ -1,4 +1,4 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
node bin/pre-push-hook.js
./bin/pre-push.sh

24
bin/pre-push.sh Executable file
View File

@ -0,0 +1,24 @@
#!/bin/sh
PROTECTED_BRANCH="trunk"
CURRENT_BRANCH=$(git branch --show-current)
if [ $PROTECTED_BRANCH = $CURRENT_BRANCH ]; then
if [ "$TERM" = "dumb" ]; then
>&2 echo "Sorry, you are unable to push to $PROTECTED_BRANCH using a GUI client! Please use git CLI."
exit 1
fi
printf "%sYou're about to push to $PROTECTED_BRANCH, is that what you intended? [y/N]: %s" "$(tput setaf 3)" "$(tput sgr0)"
read -r PROCEED < /dev/tty
echo
if [ "$(echo "${PROCEED:-n}" | tr "[:upper:]" "[:lower:]")" = "y" ]; then
echo "$(tput setaf 2)Brace yourself! Pushing to the $PROTECTED_BRANCH branch...$(tput sgr0)"
echo
exit 0
fi
echo "$(tput setaf 2)Push to $PROTECTED_BRANCH cancelled!$(tput sgr0)"
echo
exit 1
fi

View File

@ -1,5 +1,103 @@
== Changelog ==
= 6.4.0 2022-04-12 =
**WooCommerce**
- Add - Scaffolding for the custom orders table feature. ([#31692](https://github.com/woocommerce/woocommerce/pull/31692))
- Add - Add DB table structure for custom order tables. ([#31811](https://github.com/woocommerce/woocommerce/pull/31811))
- Add - Primary key for the product attributes lookup table. ([#32067](https://github.com/woocommerce/woocommerce/pull/32067))
- Add - Tracks to the dashboard status widget and setup widget. ([#31857](https://github.com/woocommerce/woocommerce/pull/31857))
- Add - Check around setup widget display when features are disabled. ([#31884](https://github.com/woocommerce/woocommerce/pull/31884))
- Add - 'woocommerce_get_formatted_meta_data_include_all_meta_lines' filter hook. This can be used to control whether metadata lines are shown in the order meta box. ([#30948](https://github.com/woocommerce/woocommerce/pull/30948))
- Enhancement - Introduce rate_limit_remaining column in the wc_rate_limits table. ([#32041](https://github.com/woocommerce/woocommerce/pull/32041))
- Tweak - Update PayPal Standard JS used in the admin environment to avoid deprecated functionality. ([#32076](https://github.com/woocommerce/woocommerce/pull/32076))
- Tweak - Change level of escaping used to render the CSV import error log. ([#32000](https://github.com/woocommerce/woocommerce/pull/32000))
- Tweak - Make the payment_url field available via the REST API's orders endpoint. ([#31826](https://github.com/woocommerce/woocommerce/pull/31826))
- Tweak - Rename WC_API_Exception code woocommerce_api_cannot_edit_product_catgory into woocommerce_api_cannot_edit_product_category ([#31785](https://github.com/woocommerce/woocommerce/pull/31785))
- Tweak - Updated default email color to new Woo purple ([#30586](https://github.com/woocommerce/woocommerce/pull/30586))
- Fix - Avoid depending on the presence of a theme header template to clear the cart after payment is made. ([#31877](https://github.com/woocommerce/woocommerce/pull/31877))
- Fix - Payments tab tracking. ([#31844](https://github.com/woocommerce/woocommerce/pull/31844))
- Fix - Remove unnecessary duplicate style in email-styles template. ([#31860](https://github.com/woocommerce/woocommerce/pull/31860))
- Fix - incorrect position value for registering menu pages. ([#31779](https://github.com/woocommerce/woocommerce/pull/31779))
- Fix - SZL currency symbol. Updated from 'L' to 'E'. ([#30602](https://github.com/woocommerce/woocommerce/pull/30602))
- Fix - Removed execution of at least one hook ignoring the `woocommerce_load_webhooks_limit` filter value. ([#29002](https://github.com/woocommerce/woocommerce/pull/29002))
- Dev - Added has_options() to REST API v3 product endpoint response. ([#32031](https://github.com/woocommerce/woocommerce/pull/32031))
- Dev - Added woocommerce_admin_order_should_render_refunds hook to allow control over the refunds UI within the order editor. ([#31414](https://github.com/woocommerce/woocommerce/pull/31414))
**WooCommerce Admin - 3.3.0 & 3.3.1 & 3.3.2**
- Add - Add asynchronous plugin install and activation endpoints ([#8079](https://github.com/woocommerce/woocommerce-admin/pull/8079))
- Performance - Avoid expensive get_notes() queries in CouponPageMoved admin_init actions by using new Notes::get_note_by_name() helper method. ([#8202](https://github.com/woocommerce/woocommerce-admin/pull/8202))
- Enhancement - Add chart color filter for overriding default chart colors. ([#8258](https://github.com/woocommerce/woocommerce-admin/pull/8258))
- Enhancement - Added Typescript type declarations to build for @woocommerce/components ([#8282](https://github.com/woocommerce/woocommerce-admin/pull/8282))
- Enhancement - Increase color selection limit to ten and add additional colors. ([#8258](https://github.com/woocommerce/woocommerce-admin/pull/8258))
- Enhancement - Made @woocommerce/components/Stepper a Typescript file ([#8286](https://github.com/woocommerce/woocommerce-admin/pull/8286))
- Enhancement - Prompts a modal to save any unsaved changes when the users try to move to a different step ([#8278](https://github.com/woocommerce/woocommerce-admin/pull/8278))
- Tweak - OBW: Override Country/Region label line-height style to avoid truncated descenders. ([#8186](https://github.com/woocommerce/woocommerce-admin/pull/8186))
- Tweak - Show single success message for theme install and activation ([#8236](https://github.com/woocommerce/woocommerce-admin/pull/8236))
- Tweak - Use WC_VERSION as cache buster for assets ([#8308](https://github.com/woocommerce/woocommerce-admin/pull/8308))
- Update - Adjust time range and add an image for the Jetpack Backup note. ([#8293](https://github.com/woocommerce/woocommerce-admin/pull/8293))
- Update - Implement MailChimp API request threshold for MailchimpScheduler. ([#8342](https://github.com/woocommerce/woocommerce-admin/pull/8342))
- Update - Reintroduce CES on product add, product update, and order update. ([#8238](https://github.com/woocommerce/woocommerce-admin/pull/8238))
- Update - Replace mysql image with mariadb ([#8220](https://github.com/woocommerce/woocommerce-admin/pull/8220))
- Update - Update country support list for WooCommerce Payments Task. ([#8517](https://github.com/woocommerce/woocommerce-admin/pull/8517))
- Fix - Fix handling of paid themes in purchase task. ([#8493](https://github.com/woocommerce/woocommerce-admin/pull/8493))
- Fix - Make sure the paid extension task is also shown for themes. ([#8412](https://github.com/woocommerce/woocommerce-admin/pull/8412))
- Fix - Reintroduce emphasis on inbox note action button. ([#8411](https://github.com/woocommerce/woocommerce-admin/pull/8411))
- Fix - Remove class ExtendedPayments. ([#8461](https://github.com/woocommerce/woocommerce-admin/pull/8461))
- Fix - Added random IDs to SVG checkmarks in stepper component ([#8222](https://github.com/woocommerce/woocommerce-admin/pull/8222))
- Fix - Fix Google Listings plugin is always shown in free features despite already activated. ([#8330](https://github.com/woocommerce/woocommerce-admin/pull/8330))
- Fix - Fix hidden notes in `admin/notes` endpoint when the user is not in the tasklist experiment. ([#8328](https://github.com/woocommerce/woocommerce-admin/pull/8328))
- Fix - Fix missing product name in variation analytic page for the deleted products. ([#8255](https://github.com/woocommerce/woocommerce-admin/pull/8255))
- Fix - Fix payments extensions displayed below the offline payments options. ([#8232](https://github.com/woocommerce/woocommerce-admin/pull/8232))
- Fix - Fix setup wizard title and flash of content ([#8201](https://github.com/woocommerce/woocommerce-admin/pull/8201))
- Fix - Fix too many pending run_remote_notifications actions. ([#8285](https://github.com/woocommerce/woocommerce-admin/pull/8285))
- Fix - Fix view logic for Setup additional payment providers task. ([#8391](https://github.com/woocommerce/woocommerce-admin/pull/8391))
- Fix - OBW: fix copy on Business Details when "WooCommerce Shipping" is not listed ([#8324](https://github.com/woocommerce/woocommerce-admin/pull/8324))
- Fix - Only add product data on REST requests and task list ([#8235](https://github.com/woocommerce/woocommerce-admin/pull/8235))
- Fix - Stop showing actioned inbox items ([#8394](https://github.com/woocommerce/woocommerce-admin/pull/8394))
- Fix - WC Payments task is not visible after installing the plugin ([#8514](https://github.com/woocommerce/woocommerce-admin/pull/8514))
- Fix - PHP warning when default param is missing in payments spec. ([#8519](https://github.com/woocommerce/woocommerce-admin/pull/8519))
- Dev - Added a test for tracks event recording for PaymentGatewaySuggestions ([#8306](https://github.com/woocommerce/woocommerce-admin/pull/8306))
- Dev - Add README to hook reference generation script ([#8004](https://github.com/woocommerce/woocommerce-admin/pull/8004))
- Dev - Add reset WooCommerce functionality to E2E tests, so tests have a fresh state. ([#8219](https://github.com/woocommerce/woocommerce-admin/pull/8219))
- Dev - Enabled optional typescript checking on ./client subfolder ([#8372](https://github.com/woocommerce/woocommerce-admin/pull/8372))
- Dev - Fix formatting and add filter param for changelog types for the testing instructions script. ([#8256](https://github.com/woocommerce/woocommerce-admin/pull/8256))
- Dev - Refactor MerchantEmailNotifications ([#8304](https://github.com/woocommerce/woocommerce-admin/pull/8304))
- Dev - Remove preloaded countries from data endpoints and use data store instead. ([#8380](https://github.com/woocommerce/woocommerce-admin/pull/8380))
- Dev - Remove unused pre loaded setting data displaying all the routes. ([#8379](https://github.com/woocommerce/woocommerce-admin/pull/8379))
- Dev - Remove unused task styling classes ([#8234](https://github.com/woocommerce/woocommerce-admin/pull/8234))
- Dev - Update dependencies to support react 17 and drop support for IE11. ([#8305](https://github.com/woocommerce/woocommerce-admin/pull/8305))
- Dev - Update task list data structure to better handle new designs. ([#8332](https://github.com/woocommerce/woocommerce-admin/pull/8332))
**WooCommerce Blocks - 7.2.0 & 7.2.1**
- Enhancement - Add Global Styles support to the Product Price block. ([5950](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5950))
- Enhancement - Add Global Styles support to the Add To Cart Button block. ([5816](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5816))
- Enhancement - Store API - Introduced `wc/store/v1` namespace. ([5911](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5911))
- Enhancement - Renamed WooCommerce block templates to more e-commerce related names. ([5935](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5935))
- Enhancement - Featured Product block: Add the ability to reset to a previously set custom background image. ([5886](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5886))
- Enhancement - Add a remove image button to the WooCommerce Feature Category block. ([5719](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5719))
- Enhancement - Add support for the global style for the On-Sale Badge block. ([5565](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5565))
- Enhancement - Add support for the global style for the Attribute Filter block. ([5557](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5557))
- Enhancement - Category List block: Add support for global style. ([5516](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5516))
- Fix - Fixed typo in `wooocommerce_store_api_validate_add_to_cart` and `wooocommerce_store_api_validate_cart_item` hook names. ([5926](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5926))
- Fix - Fix loading WC core translations in locales where WC Blocks is not localized for some strings. ([5910](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5910))
- Fix - Fixed an issue where clear customizations functionality was not working for WooCommerce templates. ([5746](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5746))
- Fix - Fixed hover and focus states for button components. ([5712](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5712))
- Fix - Add to Cart button on Products listing blocks will respect the "Redirect to the cart page after successful addition" setting. ([5708](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5708))
- Fix - Fixes Twenty Twenty Two issues with sales price and added to cart "View Cart" call out styling in the "Products by Category" block. ([5684](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5684))
- Fix - StoreAPI: Clear all wc notice types in the cart validation context [#5983](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5983)
- Fix - Don't trigger class deprecations notices if headers are already sent [#6074](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/6074)
- Various - Remove v1 string from Store Keys. ([5987](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5987))
- Various - Introduce the `InvalidCartException` for handling cart validation. ([5904](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5904))
- Various - Renamed Store API custom headers to remove `X-WC-Store-API` prefixes. [#5983](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5983)
- Various - Normalised Store API error codes [#5992](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5992)
- Various - Deprecated `woocommerce_blocks_checkout_order_processed` in favour of `woocommerce_store_api_checkout_order_processed`
- Various - Deprecated `woocommerce_blocks_checkout_update_order_meta` in favour of `woocommerce_store_api_checkout_update_order_meta`
- Various - Deprecated `woocommerce_blocks_checkout_update_order_from_request` in favour of `woocommerce_store_api_checkout_update_order_from_request`
= 6.3.1 2022-03-10 =
**WooCommerce**

View File

@ -14,7 +14,9 @@
"url": "https://github.com/woocommerce/woocommerce/issues"
},
"scripts": {
"preinstall": "npx only-allow pnpm"
"preinstall": "npx only-allow pnpm",
"postinstall": "pnpm git:update-hooks",
"git:update-hooks": "rm -r .git/hooks && mkdir -p .git/hooks && husky install"
},
"devDependencies": {
"@automattic/nx-composer": "^0.1.0",
@ -30,7 +32,9 @@
"@wordpress/prettier-config": "^1.1.1",
"chalk": "^4.1.2",
"glob": "^7.2.0",
"husky": "^7.0.4",
"jest": "^27.3.1",
"lint-staged": "^12.3.7",
"mkdirp": "^1.0.4",
"node-stream-zip": "^1.15.0",
"prettier": "npm:wp-prettier@^2.2.1-beta-1",

View File

@ -1,5 +1,9 @@
# Unreleased
- Add E2E tests to disabled welcome modal #32505
- Update test for payment task. #32467
# 1.0.0
- Add returned type annotations and remove unused vars. #8020

View File

@ -56,5 +56,10 @@
"clean": "pnpm exec rimraf tsconfig.tsbuildinfo build build-*",
"lint": "eslint src",
"prepack": "pnpm run clean && pnpm run build"
},
"lint-staged": {
"*.(t|j)s?(x)": [
"eslint --fix"
]
}
}

View File

@ -25,6 +25,15 @@ export class PaymentsSetup extends BasePage {
await this.clickButtonWithText( 'Got it' );
}
async showOtherPaymentMethods(): Promise< void > {
const selector = '.woocommerce-task-payments button.toggle-button';
await this.page.waitForSelector( selector );
const toggleButton = await this.page.$(
`${ selector }[aria-expanded=false]`
);
await toggleButton?.click();
}
async goToPaymentMethodSetup(
method: PaymentMethodWithSetupButton
): Promise< void > {
@ -41,14 +50,6 @@ export class PaymentsSetup extends BasePage {
}
}
async methodHasBeenSetup( method: PaymentMethod ): Promise< void > {
const selector = `.woocommerce-task-payment-${ method }`;
await this.page.waitForSelector( selector );
expect(
await getElementByText( '*', 'Manage', selector )
).toBeDefined();
}
async enableCashOnDelivery(): Promise< void > {
await this.page.waitForSelector( '.woocommerce-task-payment-cod' );
await this.clickButtonWithText( 'Enable' );

View File

@ -24,12 +24,7 @@ export class WcHomescreen extends BasePage {
}
async possiblyDismissWelcomeModal(): Promise< void > {
const modalText = 'Welcome to your WooCommerce stores online HQ!';
const modal = await waitForElementByTextWithoutThrow(
'h2',
modalText,
10
);
const modal = await this.isWelcomeModalVisible();
if ( modal ) {
await this.clickButtonWithText( 'Next' );
@ -41,6 +36,16 @@ export class WcHomescreen extends BasePage {
}
}
async isWelcomeModalVisible(): Promise< boolean > {
const modalText = 'Welcome to your WooCommerce stores online HQ!';
const modal = await waitForElementByTextWithoutThrow(
'h2',
modalText,
10
);
return modal;
}
async getTaskList(): Promise< Array< string | null > > {
await page.waitForSelector(
'.woocommerce-task-card .woocommerce-task-list__item-title'

View File

@ -42,8 +42,22 @@ export class WcSettings extends BasePage {
);
}
async paymentMethodIsEnabled( method = '' ): Promise< boolean > {
await this.navigate( 'checkout' );
await waitForElementByText( 'h2', 'Payment methods' );
const className = await getAttribute(
`tr[data-gateway_id=${ method }] .woocommerce-input-toggle`,
'className'
);
return (
( className as string ).indexOf(
'woocommerce-input-toggle--disabled'
) === -1
);
}
async cleanPaymentMethods(): Promise< void > {
this.navigate( 'checkout' );
await this.navigate( 'checkout' );
await waitForElementByText( 'h2', 'Payment methods' );
const paymentMethods = await page.$$( 'span.woocommerce-input-toggle' );
for ( const method of paymentMethods ) {

View File

@ -597,10 +597,37 @@ const testBusinessDetailsForm = () => {
} );
};
const testAdminHomescreen = () => {
describe( 'Homescreen', () => {
const profileWizard = new OnboardingWizard( page );
const homeScreen = new WcHomescreen( page );
const login = new Login( page );
beforeAll( async () => {
await login.login();
await resetWooCommerceState();
await profileWizard.navigate();
await profileWizard.skipStoreSetup();
} );
afterAll( async () => {
await login.logout();
} );
it( 'should not show welcome modal', async () => {
await homeScreen.isDisplayed();
await expect( homeScreen.isWelcomeModalVisible() ).resolves.toBe(
false
);
} );
} );
};
module.exports = {
testAdminOnboardingWizard,
testSelectiveBundleWCPay,
testDifferentStoreCurrenciesWCPay,
testSubscriptionsInclusion,
testBusinessDetailsForm,
testAdminHomescreen,
};

View File

@ -53,6 +53,7 @@ const testAdminPaymentSetupTask = () => {
} );
it( 'Saving valid bank account transfer details enables the payment method', async () => {
await paymentsSetup.showOtherPaymentMethods();
await paymentsSetup.goToPaymentMethodSetup( 'bacs' );
await bankTransferSetup.saveAccountDetails( {
accountNumber: '1234',
@ -62,12 +63,11 @@ const testAdminPaymentSetupTask = () => {
iban: '12 3456 7890',
swiftCode: 'ABBA',
} );
await homeScreen.isDisplayed();
await waitForTimeout( 1000 );
await homeScreen.clickOnTaskList( 'Set up payments' );
await paymentsSetup.isDisplayed();
await paymentsSetup.methodHasBeenSetup( 'bacs' );
expect( await settings.paymentMethodIsEnabled( 'bacs' ) ).toBe(
true
);
await homeScreen.navigate();
} );
it( 'Enabling cash on delivery enables the payment method', async () => {
@ -76,13 +76,13 @@ const testAdminPaymentSetupTask = () => {
await homeScreen.isDisplayed();
await waitForTimeout( 1000 );
await homeScreen.clickOnTaskList( 'Set up payments' );
await paymentsSetup.enableCashOnDelivery();
await homeScreen.navigate();
await homeScreen.isDisplayed();
await waitForTimeout( 1000 );
await homeScreen.clickOnTaskList( 'Set up payments' );
await paymentsSetup.isDisplayed();
await paymentsSetup.methodHasBeenSetup( 'cod' );
await paymentsSetup.showOtherPaymentMethods();
await paymentsSetup.enableCashOnDelivery();
await waitForTimeout( 1000 );
expect( await settings.paymentMethodIsEnabled( 'cod' ) ).toBe(
true
);
} );
} );
};

View File

@ -33,5 +33,10 @@
},
"bin": {
"wc-api-tests": "bin/wc-api-tests.sh"
},
"lint-staged": {
"*.(t|j)s?(x)": [
"eslint --fix"
]
}
}

View File

@ -52,5 +52,10 @@
},
"publishConfig": {
"access": "public"
},
"lint-staged": {
"*.(t|j)s?(x)": [
"eslint --fix"
]
}
}

View File

@ -1,5 +1,9 @@
# Unreleased
- Fix documentation for `TableCard` component
- Update dependency `@wordpress/hooks` to ^3.5.0
- Update dependency `@wordpress/icons` to ^8.1.0
# 10.0.0
- Replace deprecated wp.compose.withState with wp.element.useState. #8338
- Add missing dependencies. #8349

View File

@ -39,10 +39,10 @@
"@wordpress/deprecated": "^3.3.1",
"@wordpress/dom": "^3.3.2",
"@wordpress/element": "^4.1.1",
"@wordpress/hooks": "^2.12.3",
"@wordpress/hooks": "^3.5.0",
"@wordpress/html-entities": "^3.3.1",
"@wordpress/i18n": "^4.3.1",
"@wordpress/icons": "^6.3.0",
"@wordpress/icons": "^8.1.0",
"@wordpress/keycodes": "^3.3.1",
"@wordpress/url": "^3.4.1",
"@wordpress/viewport": "^4.1.2",
@ -123,5 +123,11 @@
"test:nobuild": "jest --config ./jest.config.json",
"test:update-snapshots": "pnpm run test:nobuild -- --updateSnapshot",
"test-staged": "jest --bail --config ./jest.config.json --findRelatedTests"
},
"lint-staged": {
"*.(t|j)s?(x)": [
"eslint --fix",
"pnpm test-staged"
]
}
}

View File

@ -67,8 +67,8 @@ Name | Type | Default | Description
`downloadable` | Boolean | `false` | Whether the table must be downloadable. If true, the download button will appear
`onClickDownload` | Function | `null` | A callback function called when the "download" button is pressed. Optional, if used, the download button will appear
`query` | Object | `{}` | An object of the query parameters passed to the page, ex `{ page: 2, per_page: 5 }`
`rowHeader` | One of type: number, bool | `0` | An array of arrays of display/value object pairs (see `Table` props)
`rows` | Array | `[]` | Which column should be the row header, defaults to the first item (`0`) (see `Table` props)
`rowHeader` | One of type: number, bool | `0` | Which column should be the row header, defaults to the first item (`0`) (see `Table` props)
`rows` | Array | `[]` | (required) An array of arrays of display/value object pairs (see `Table` props)
`rowsPerPage` | Number | `null` | (required) The total number of rows to display per page
`searchBy` | String | `null` | The string to use as a query parameter when searching row items
`showMenu` | Boolean | `true` | Boolean to determine whether or not ellipsis menu is shown

View File

@ -308,11 +308,12 @@ TableCard.propTypes = {
*/
query: PropTypes.object,
/**
* An array of arrays of display/value object pairs (see `Table` props).
* Which column should be the row header, defaults to the first item (`0`) (but could be set to `1`, if the first col
* is checkboxes, for example). Set to false to disable row headers.
*/
rowHeader: PropTypes.oneOfType( [ PropTypes.number, PropTypes.bool ] ),
/**
* Which column should be the row header, defaults to the first item (`0`) (see `Table` props).
* An array of arrays of display/value object pairs (see `Table` props).
*/
rows: PropTypes.arrayOf(
PropTypes.arrayOf(

View File

@ -46,5 +46,11 @@
"rimraf": "^3.0.2",
"ts-jest": "^27.1.3",
"typescript": "^4.6.2"
},
"lint-staged": {
"*.(t|j)s?(x)": [
"eslint --fix",
"pnpm test-staged"
]
}
}

View File

@ -49,5 +49,11 @@
"rimraf": "^3.0.2",
"ts-jest": "^27.1.3",
"typescript": "^4.6.2"
},
"lint-staged": {
"*.(t|j)s?(x)": [
"eslint --fix",
"pnpm test-staged"
]
}
}

View File

@ -70,5 +70,11 @@
"test": "pnpm run build && pnpm run test:nobuild",
"test:nobuild": "jest --config ./jest.config.json",
"test-staged": "jest --bail --config ./jest.config.json --findRelatedTests"
},
"lint-staged": {
"*.(t|j)s?(x)": [
"eslint --fix",
"pnpm test-staged"
]
}
}

View File

@ -1,5 +1,8 @@
# Unreleased
- Update dependency `@wordpress/hooks` to ^3.5.0
- Add `is_offline` attribute for `Plugin` type. #32467
# 3.1.0
- Add "moment" to peerDependencies. #8349

View File

@ -30,7 +30,7 @@
"@wordpress/data-controls": "^2.3.2",
"@wordpress/deprecated": "^3.3.1",
"@wordpress/element": "^4.1.1",
"@wordpress/hooks": "^2.12.3",
"@wordpress/hooks": "^3.5.0",
"@wordpress/i18n": "^4.3.1",
"@wordpress/url": "^3.4.1",
"dompurify": "^2.3.6",
@ -70,5 +70,11 @@
"test": "pnpm run build && pnpm run test:nobuild",
"test:nobuild": "jest --config ./jest.config.json",
"test-staged": "jest --bail --config ./jest.config.json --findRelatedTests"
},
"lint-staged": {
"*.(t|j)s?(x)": [
"eslint --fix",
"pnpm test-staged"
]
}
}

View File

@ -34,6 +34,7 @@ export { withPluginsHydration } from './plugins/with-plugins-hydration';
export { ONBOARDING_STORE_NAME } from './onboarding';
export { withOnboardingHydration } from './onboarding/with-onboarding-hydration';
export { getVisibleTasks } from './onboarding/utils';
export type { TaskType, TaskListType } from './onboarding/types';
export { USER_STORE_NAME } from './user';

View File

@ -9,12 +9,22 @@ export type TaskType = {
isSnoozed: boolean;
isVisible: boolean;
isSnoozable: boolean;
isDisabled: boolean;
snoozedUntil: number;
time: string;
title: string;
isVisited: boolean;
};
export type TaskListSection = {
id: string;
title: string;
description: string;
image: string;
tasks: string[];
isComplete: boolean;
};
export type TaskListType = {
id: string;
isCollapsible?: boolean;
@ -25,4 +35,5 @@ export type TaskListType = {
title: string;
eventPrefix: string;
displayProgressHeader: boolean;
sections?: TaskListSection[];
};

View File

@ -0,0 +1,16 @@
/**
* Internal dependencies
*/
import { TaskType } from './types';
/**
* Filters tasks to only visible tasks, taking in account snoozed tasks.
*/
export function getVisibleTasks( tasks: TaskType[] ) {
const nowTimestamp = Date.now();
return tasks.filter(
( task ) =>
! task.isDismissed &&
( ! task.isSnoozed || task.snoozedUntil < nowTimestamp )
);
}

View File

@ -55,4 +55,8 @@ export const pluginNames = {
'google-listings-and-ads': __( 'Google Listings and Ads', 'woocommerce' ),
'woo-razorpay': __( 'Razorpay', 'woocommerce' ),
mailpoet: __( 'MailPoet', 'woocommerce' ),
'pinterest-for-woocommerce': __(
'Pinterest for WooCommerce',
'woocommerce'
),
};

View File

@ -39,6 +39,7 @@ export type Plugin = {
recommendation_priority?: number;
is_visible?: boolean;
is_local_partner?: boolean;
is_offline?: boolean;
};
type PaypalOnboardingState = 'unknown' | 'start' | 'progressive' | 'onboarded';

View File

@ -52,5 +52,11 @@
"test": "pnpm run build && pnpm run test:nobuild",
"test:nobuild": "jest --config ./jest.config.json",
"test-staged": "jest --bail --config ./jest.config.json --findRelatedTests"
},
"lint-staged": {
"*.(t|j)s?(x)": [
"eslint --fix",
"pnpm test-staged"
]
}
}

View File

@ -34,5 +34,10 @@
"typescript": "^4.6.2",
"webpack": "^5.70.0",
"webpack-cli": "^3.3.12"
},
"lint-staged": {
"*.(t|j)s?(x)": [
"eslint --fix"
]
}
}

View File

@ -48,5 +48,10 @@
"clean": "rm -rf ./build ./build-module",
"compile": "node ./../bin/build.js",
"build": "./bin/build.sh && pnpm run clean && pnpm run compile"
},
"lint-staged": {
"*.(t|j)s?(x)": [
"eslint --fix"
]
}
}

View File

@ -77,5 +77,10 @@
},
"bin": {
"wc-e2e": "bin/wc-e2e.sh"
},
"lint-staged": {
"*.(t|j)s?(x)": [
"eslint --fix"
]
}
}

View File

@ -45,5 +45,10 @@
"build": "pnpm run clean && pnpm run compile",
"prepare": "pnpm run build",
"lint": "eslint src"
},
"lint-staged": {
"*.(t|j)s?(x)": [
"eslint --fix"
]
}
}

View File

@ -1,5 +1,7 @@
# Unreleased
- Update dependency `@wordpress/icons` to ^8.1.0
# 3.0.1
- Update all js packages with minor/patch version changes. #8392

View File

@ -29,7 +29,7 @@
"@wordpress/components": "^19.5.0",
"@wordpress/element": "^4.1.1",
"@wordpress/i18n": "^4.3.1",
"@wordpress/icons": "^6.3.0",
"@wordpress/icons": "^8.1.0",
"@wordpress/keycodes": "^3.3.1",
"classnames": "^2.3.1",
"dompurify": "^2.3.6",
@ -83,5 +83,11 @@
"test": "pnpm run build && pnpm run test:nobuild",
"test:nobuild": "jest --config ./jest.config.json",
"test-staged": "jest --bail --config ./jest.config.json --findRelatedTests"
},
"lint-staged": {
"*.(t|j)s?(x)": [
"eslint --fix",
"pnpm test-staged"
]
}
}

View File

@ -130,7 +130,7 @@ export const TaskItem: React.FC< TaskItemProps > = ( {
}, [ expanded ] );
const className = classnames( 'woocommerce-task-list__item', {
complete: completed,
'is-complete': completed,
expanded: isTaskExpanded,
'level-2': level === 2 && ! completed,
'level-1': level === 1 && ! completed,

View File

@ -121,7 +121,7 @@ $task-alert-yellow: #f0b849;
left: 5px;
}
&.complete {
&.is-complete {
.woocommerce-task__icon {
background-color: var(--wp-admin-theme-color);
}
@ -136,7 +136,7 @@ $task-alert-yellow: #f0b849;
}
}
&:not(.complete) {
&:not(.is-complete) {
.woocommerce-task__icon {
border: 1px solid $gray-100;
background: $white;

View File

@ -1,5 +1,7 @@
# Unreleased
- Update dependency `@wordpress/hooks` to ^3.5.0
# 2.1.0
- Add missing dependencies. #8349

View File

@ -28,7 +28,7 @@
"@automattic/explat-client": "^0.0.3",
"@automattic/explat-client-react-helpers": "^0.0.4",
"@wordpress/api-fetch": "^6.0.1",
"@wordpress/hooks": "^2.12.3",
"@wordpress/hooks": "^3.5.0",
"cookie": "^0.4.2",
"qs": "^6.10.3"
},
@ -54,5 +54,11 @@
"test": "pnpm run build && pnpm run test:nobuild",
"test:nobuild": "jest --config ./jest.config.json",
"test-staged": "jest --bail --config ./jest.config.json --findRelatedTests"
},
"lint-staged": {
"*.(t|j)s?(x)": [
"eslint --fix",
"pnpm test-staged"
]
}
}

View File

@ -40,5 +40,10 @@
"rimraf": "^3.0.2",
"ts-jest": "^27.1.3",
"typescript": "^4.6.2"
},
"lint-staged": {
"*.(t|j)s?(x)": [
"eslint --fix"
]
}
}

View File

@ -107,7 +107,7 @@ wooCommercePackages.forEach( ( lib ) => {
} );
} );
const config = require( '../../../../plugins/woocommerce-admin/config/development.json' );
const config = require( '../../../../plugins/woocommerce/client/admin/config/development.json' );
// Check if test is jsdom or node
if ( global.window ) {

View File

@ -1,5 +1,7 @@
# Unreleased
- Update dependency `@wordpress/hooks` to ^3.5.0
# 7.0.1
- Add missing dependencies. #8349

View File

@ -25,7 +25,7 @@
"@wordpress/components": "^19.5.0",
"@wordpress/compose": "^5.1.2",
"@wordpress/element": "^4.1.1",
"@wordpress/hooks": "^2.12.3",
"@wordpress/hooks": "^3.5.0",
"@wordpress/notices": "^3.3.2",
"@wordpress/url": "^3.4.1",
"history": "^4.10.1",
@ -57,5 +57,11 @@
"rimraf": "^3.0.2",
"ts-jest": "^27.1.3",
"typescript": "^4.6.2"
},
"lint-staged": {
"*.(t|j)s?(x)": [
"eslint --fix",
"pnpm test-staged"
]
}
}

View File

@ -2,6 +2,8 @@
# Unreleased
- Update dependency `@wordpress/a11y` to ^3.5.0
# 4.0.1
- Update all js packages with minor/patch version changes. #8392

View File

@ -22,7 +22,7 @@
"module": "build-module/index.js",
"react-native": "src/index",
"dependencies": {
"@wordpress/a11y": "^2.15.3",
"@wordpress/a11y": "^3.5.0",
"@wordpress/data": "^6.3.0",
"@wordpress/notices": "^3.3.2"
},
@ -51,5 +51,10 @@
"rimraf": "^3.0.2",
"ts-jest": "^27.1.3",
"typescript": "^4.6.2"
},
"lint-staged": {
"*.(t|j)s?(x)": [
"eslint --fix"
]
}
}

View File

@ -45,5 +45,11 @@
"rimraf": "^3.0.2",
"ts-jest": "^27.1.3",
"typescript": "^4.6.2"
},
"lint-staged": {
"*.(t|j)s?(x)": [
"eslint --fix",
"pnpm test-staged"
]
}
}

View File

@ -1,5 +1,7 @@
# Unreleased
- Update TaskList types.
# 3.0.1
- Add missing dependency.

View File

@ -59,5 +59,10 @@
"start": "concurrently \"tsc --build --watch\" \"webpack --watch\"",
"prepack": "pnpm run clean && pnpm run build",
"lint": "eslint src"
},
"lint-staged": {
"*.(t|j)s?(x)": [
"eslint --fix"
]
}
}

View File

@ -19,7 +19,7 @@
"main": "index.js",
"dependencies": {
"@automattic/color-studio": "^2.5.0",
"@wordpress/base-styles": "^3.6.0",
"@wordpress/base-styles": "^4.3.0",
"@wordpress/postcss-plugins-preset": "^1.6.0",
"css-loader": "^3.6.0",
"mini-css-extract-plugin": "^2.6.0",
@ -42,5 +42,10 @@
"ts-jest": "^27.1.3",
"typescript": "^4.6.2",
"webpack": "^5.70.0"
},
"lint-staged": {
"*.(t|j)s?(x)": [
"eslint --fix"
]
}
}

View File

@ -42,5 +42,10 @@
"rimraf": "^3.0.2",
"ts-jest": "^27.1.3",
"typescript": "^4.6.2"
},
"lint-staged": {
"*.(t|j)s?(x)": [
"eslint --fix"
]
}
}

View File

@ -27,7 +27,7 @@
<!-- Configs -->
<config name="minimum_supported_wp_version" value="5.2" />
<config name="testVersion" value="7.0-" />
<config name="testVersion" value="7.2-" />
<!-- Rules -->
<rule ref="WooCommerce-Core" />

View File

@ -1,62 +0,0 @@
/* eslint-disable */
module.exports = function ( grunt ) {
'use strict';
// Project configuration
grunt.initConfig( {
makepot: {
target: {
options: {
domainPath: '/languages',
exclude: [ '.git/*', 'bin/*', 'node_modules/*', 'tests/*' ],
mainFile: '../woocommerce/woocommerce.php',
potFilename: 'woocommerce-admin.pot',
potHeaders: {
poedit: true,
'x-poedit-keywordslist': true,
},
type: 'wp-plugin',
updateTimestamp: true,
},
},
},
checktextdomain: {
options: {
text_domain: 'woocommerce',
keywords: [
'__:1,2d',
'_e:1,2d',
'_x:1,2c,3d',
'esc_html__:1,2d',
'esc_html_e:1,2d',
'esc_html_x:1,2c,3d',
'esc_attr__:1,2d',
'esc_attr_e:1,2d',
'esc_attr_x:1,2c,3d',
'_ex:1,2c,3d',
'_n:1,2,4d',
'_nx:1,2,4c,5d',
'_n_noop:1,2,3d',
'_nx_noop:1,2,3c,4d',
],
},
files: {
src: [
'**/*.php', // Include all files/
'!node_modules/**', // Exclude node_modules/
'!tests/**', // Exclude tests/
'!vendor/**', // Exclude vendor/
'!tmp/**', // Exclude tmp/
],
expand: true,
},
},
} );
// Load NPM tasks to be used here.
grunt.loadNpmTasks( 'grunt-wp-i18n' );
grunt.loadNpmTasks( 'grunt-checktextdomain' );
grunt.util.linefeed = '\n';
};

View File

@ -22,16 +22,7 @@ module.exports = function ( api ) {
],
ignore: [ 'packages/**/node_modules' ],
env: {
production: {
plugins: [
[
'@wordpress/babel-plugin-makepot',
{
output: 'languages/woocommerce-admin.po',
},
],
],
},
production: {},
storybook: {
plugins: [

View File

@ -1,104 +0,0 @@
<?php
/**
* Command line script for merging two .pot files.
*
* @package WooCommerce\Admin
*/
/**
* Get the two file names from the command line.
*/
if ( $argc < 2 ) {
echo "Usage: php -f {$argv[0]} source-file.pot destination-file.pot\n";
exit;
}
for ( $index = 1; $index <= 2; $index++ ) {
if ( ! is_file( $argv[ $index ] ) ) {
echo "File not found: {$argv[ $index ]}\n";
exit;
}
}
/**
* Check whether an output locale has been requested.
*/
if ( isset( $argv[3] ) && 0 === stripos( $argv[3], 'lang=' ) ) {
$locale = substr( $argv[3], 5 );
$target_file = preg_replace( '|\.pot?|', "-{$locale}.po", $argv[2] );
} else {
$target_file = $argv[2];
}
/**
* Parse a .pot file into an array.
*
* @param string $file_name Pot file name.
* @return array
*/
function woocommerce_admin_parse_pot( $file_name ) {
$fh = fopen( $file_name, 'r' );
$originals = array();
$references = array();
$messages = array();
$have_msgid = false;
while ( ! feof( $fh ) ) {
$line = trim( fgets( $fh ) );
if ( ! $line ) {
$message = implode( "\n", $messages );
$originals[ $message ] = $references;
$references = array();
$messages = array();
$have_msgid = false;
$message = '';
continue;
}
if ( 'msgid' == substr( $line, 0, 5 ) ) {
$have_msgid = true;
}
if ( $have_msgid ) {
$messages[] = $line;
} else {
$references[] = $line;
}
}
fclose( $fh );
$message = implode( "\n", $messages );
$originals[ $message ] = $references;
return $originals;
}
// Read the translation files.
$originals_1 = woocommerce_admin_parse_pot( $argv[1] );
$originals_2 = woocommerce_admin_parse_pot( $argv[2] );
// Delete the original sources.
unlink( $argv[1] );
unlink( $argv[2] );
// We don't want two .pot headers in the output.
array_shift( $originals_1 );
$fh = fopen( $target_file, 'w' );
foreach ( $originals_2 as $message => $original ) {
// Use the complete message section to match strings to be translated.
if ( isset( $originals_1[ $message ] ) ) {
$original = array_merge( $original, $originals_1[ $message ] );
unset( $originals_1[ $message ] );
}
fwrite( $fh, implode( "\n", $original ) );
fwrite( $fh, "\n" . $message ."\n\n" );
}
foreach ( $originals_1 as $message => $original ) {
fwrite( $fh, implode( "\n", $original ) );
fwrite( $fh, "\n" . $message ."\n\n" );
}
fclose( $fh );
echo "Created {$target_file}\n";

View File

@ -1,23 +0,0 @@
#!/usr/bin/env bash
# Check for required version
WPCLI_VERSION=`wp cli version | cut -f2 -d' '`
if [ ${WPCLI_VERSION:0:1} -lt "2" -o ${WPCLI_VERSION:0:1} -eq "2" -a ${WPCLI_VERSION:2:1} -lt "1" ]; then
echo WP-CLI version 2.1.0 or greater is required to make JSON translation files
exit
fi
# Substitute JS source references with build references
for T in `find languages -name "*.po"`
do
sed \
-e 's/ client\/[^:]*:/ dist\/app\/index.js:/gp' \
-e 's/ packages\/components[^:]*:/ dist\/components\/index.js:/gp' \
-e 's/ packages\/date[^:]*:/ dist\/date\/index.js:/gp' \
$T | uniq > $T-build
rm $T
mv $T-build $T
done
# Make the JSON files
wp i18n make-json languages --no-purge

View File

@ -0,0 +1,4 @@
Significance: minor
Type: Add
Add support for sections in our TaskList class and create a new sectional task list component. #32302

View File

@ -100,6 +100,10 @@ function getMarketingItems( props ) {
link:
'https://woocommerce.com/document/google-listings-and-ads/?utm_medium=product#get-started',
},
activePlugins.includes( 'pinterest-for-woocommerce' ) && {
title: __( 'Set up Pinterest for WooCommerce', 'woocommerce' ),
link: 'https://woocommerce.com/products/pinterest-for-woocommerce/',
},
activePlugins.includes( 'mailchimp-for-woocommerce' ) && {
title: __( 'Connect Mailchimp for WooCommerce', 'woocommerce' ),
link:

View File

@ -121,7 +121,7 @@ Leaderboard.propTypes = {
*/
query: PropTypes.object,
/**
* Which column should be the row header, defaults to the first item (`0`) (see `Table` props).
* An array of arrays of display/value object pairs (see `Table` props).
*/
rows: PropTypes.arrayOf(
PropTypes.arrayOf(

View File

@ -42,6 +42,7 @@ import { WelcomeModal } from './welcome-modal';
import { useHeadercardExperimentHook } from './hooks/use-headercard-experiment-hook';
import './style.scss';
import '../dashboard/style.scss';
import { getAdminSetting } from '~/utils/admin-settings';
const Tasks = lazy( () =>
import( /* webpackChunkName: "tasks" */ '../tasks' )
@ -63,6 +64,8 @@ export const Layout = ( {
query,
taskListComplete,
hasTaskList,
showingProgressHeader,
isLoadingTaskLists,
shouldShowWelcomeModal,
shouldShowWelcomeFromCalypsoModal,
isTaskListHidden,
@ -140,7 +143,9 @@ export const Layout = ( {
<Column shouldStick={ shouldStickColumns }>
{ ! isLoadingExperimentAssignment &&
! isLoadingTwoColExperimentAssignment &&
! isRunningTaskListExperiment && (
! isRunningTaskListExperiment &&
! isLoadingTaskLists &&
! showingProgressHeader && (
<ActivityHeader
className="your-store-today"
title={ __(
@ -285,8 +290,13 @@ export default compose(
const { getOption, hasFinishedResolution } = select(
OPTIONS_STORE_NAME
);
const { getTaskList, getTaskLists } = select( ONBOARDING_STORE_NAME );
const {
getTaskList,
getTaskLists,
hasFinishedResolution: taskListFinishResolution,
} = select( ONBOARDING_STORE_NAME );
const taskLists = getTaskLists();
const isLoadingTaskLists = ! taskListFinishResolution( 'getTaskLists' );
const welcomeFromCalypsoModalDismissed =
getOption( WELCOME_FROM_CALYPSO_MODAL_DISMISSED_OPTION_NAME ) !==
@ -336,8 +346,12 @@ export default compose(
isBatchUpdating: isNotesRequesting( 'batchUpdateNotes' ),
shouldShowWelcomeModal,
shouldShowWelcomeFromCalypsoModal,
isLoadingTaskLists,
isTaskListHidden: getTaskList( 'setup' )?.isHidden,
hasTaskList: !! taskLists.find( ( list ) => list.isVisible ),
hasTaskList: getAdminSetting( 'visibleTaskListIds', [] ).length > 0,
showingProgressHeader: !! taskLists.find(
( list ) => list.isVisible && list.displayProgressHeader
),
taskListComplete: getTaskList( 'setup' )?.isComplete,
installTimestamp,
installTimestampHasResolved,

View File

@ -79,10 +79,21 @@ const PaymentRecommendations: React.FC = () => {
[ isInstalled ]
);
const supportsWCPayments =
paymentGatewaySuggestions &&
paymentGatewaySuggestions.filter( ( paymentGatewaySuggestion ) => {
return (
paymentGatewaySuggestion.id.indexOf(
'woocommerce_payments'
) === 0
);
} ).length === 1;
const triggeredPageViewRef = useRef( false );
const shouldShowRecommendations =
paymentGatewaySuggestions &&
paymentGatewaySuggestions.length > 0 &&
! supportsWCPayments &&
! isDismissed;
useEffect( () => {

View File

@ -201,7 +201,10 @@ class BusinessDetails extends Component {
const promises = [
this.persistProfileItems( {
business_extensions: businessExtensions,
business_extensions: [
...businessExtensions,
...alreadyActivatedExtensions,
],
} ),
];

View File

@ -1,3 +1,4 @@
@import 'node_modules/@wordpress/base-styles/colors.native';
// By using CSS variables, we can switch the spacing rhythm using a single media query.
:root {
--large-gap: 40px;
@ -37,6 +38,14 @@
max-width: 100%;
line-height: 1;
}
.components-panel__body > .components-panel__body-title,
.woocommerce-experimental-list__item,
.woocommerce-inbox-message {
&:hover {
background: $gray-0;
}
}
}
body.woocommerce-page {

View File

@ -19,9 +19,9 @@ $progress-complete-color: #007cba;
appearance: none;
border: 1px solid #ddd;
border-radius: 16px;
height: 10px;
height: 12px;
width: 100%;
margin-bottom: 20px;
margin-bottom: 0;
// Firefox
& {

View File

@ -4,7 +4,11 @@
import { __, sprintf } from '@wordpress/i18n';
import { useMemo } from '@wordpress/element';
import { useSelect } from '@wordpress/data';
import { ONBOARDING_STORE_NAME, TaskListType } from '@woocommerce/data';
import {
getVisibleTasks,
ONBOARDING_STORE_NAME,
TaskListType,
} from '@woocommerce/data';
import { getSetting } from '@woocommerce/settings';
/**
@ -20,37 +24,38 @@ type ProgressHeaderProps = {
export const ProgressHeader: React.FC< ProgressHeaderProps > = ( {
taskListId,
} ) => {
const { loading, tasksCount, completedCount, hasVisitedTasks } = useSelect(
( select ) => {
const {
loading,
tasksCount,
completedCount,
hasVisitedTasks,
disabledCompletedCount,
} = useSelect( ( select ) => {
const taskList: TaskListType = select(
ONBOARDING_STORE_NAME
).getTaskList( taskListId );
const finishedResolution = select(
ONBOARDING_STORE_NAME
).hasFinishedResolution( 'getTaskList', [ taskListId ] );
const nowTimestamp = Date.now();
const visibleTasks = taskList?.tasks.filter(
( task ) =>
! task.isDismissed &&
( ! task.isSnoozed || task.snoozedUntil < nowTimestamp )
);
const visibleTasks = getVisibleTasks( taskList?.tasks );
return {
loading: ! finishedResolution,
tasksCount: visibleTasks?.length,
completedCount: visibleTasks?.filter(
( task ) => task.isComplete
completedCount: visibleTasks?.filter( ( task ) => task.isComplete )
.length,
disabledCompletedCount: visibleTasks?.filter(
( task ) => task.isComplete && task.isDisabled
).length,
hasVisitedTasks:
visibleTasks?.filter( ( task ) => task.isVisited ).length >
0,
visibleTasks?.filter( ( task ) => task.isVisited ).length > 0,
};
}
);
} );
const progressTitle = useMemo( () => {
if (
( ! hasVisitedTasks && completedCount < 2 ) ||
( ! hasVisitedTasks &&
completedCount < 2 + disabledCompletedCount ) ||
completedCount === tasksCount
) {
const siteTitle = getSetting( 'siteTitle' );

View File

@ -24,7 +24,7 @@ export const Action = ( {
markConfigured,
onSetUp = () => {},
onSetupCallback,
setupButtonText = __( 'Set up', 'woocommerce' ),
setupButtonText = __( 'Get started', 'woocommerce' ),
} ) => {
const [ isBusy, setIsBusy ] = useState( false );

View File

@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { Card, CardHeader } from '@wordpress/components';
import { Card, CardHeader, CardFooter } from '@wordpress/components';
/**
* Internal dependencies
@ -15,10 +15,11 @@ export const List = ( {
markConfigured,
recommendation,
paymentGateways,
footerLink,
} ) => {
return (
<Card>
<CardHeader as="h2">{ heading }</CardHeader>
{ heading && <CardHeader as="h2">{ heading }</CardHeader> }
{ paymentGateways.map( ( paymentGateway ) => {
const { id } = paymentGateway;
return (
@ -30,6 +31,9 @@ export const List = ( {
/>
);
} ) }
{ footerLink && (
<CardFooter isBorderless>{ footerLink }</CardFooter>
) }
</Card>
);
};

View File

@ -6,14 +6,15 @@
overflow: hidden;
.components-card__media {
width: 170px;
width: 85px;
flex-shrink: 0;
align-self: flex-start;
img,
svg,
.is-placeholder {
margin: auto;
max-width: 100px;
max-width: 36px;
display: block;
}

View File

@ -49,7 +49,7 @@ describe( 'PaymentGatewaySuggestions > List', () => {
expect( queryByRole( 'button' ) ).toHaveTextContent( 'Enable' );
} );
it( 'should display the "Set up" button when setup is required', () => {
it( 'should display the "Get started" button when setup is required', () => {
const props = {
...defaultProps,
paymentGateways: [
@ -63,7 +63,7 @@ describe( 'PaymentGatewaySuggestions > List', () => {
const { queryByRole } = render( <List { ...props } /> );
expect( queryByRole( 'button' ) ).toHaveTextContent( 'Set up' );
expect( queryByRole( 'button' ) ).toHaveTextContent( 'Get started' );
} );
it( 'should display the SetupRequired component when appropriate', () => {

View File

@ -156,7 +156,7 @@ export const Configure = ( { markConfigured, paymentGateway } ) => {
</p>
) }
<Button isPrimary href={ settingsUrl }>
{ __( 'Set up', 'woocommerce' ) }
{ __( 'Get started', 'woocommerce' ) }
</Button>
</>
);

View File

@ -81,7 +81,7 @@ describe( 'Configure', () => {
const { container } = render( <Configure { ...props } /> );
const button = container.querySelector( 'a' );
expect( button.textContent ).toBe( 'Set up' );
expect( button.textContent ).toBe( 'Get started' );
expect( button.href ).toBe( mockGateway.settingsUrl );
} );
} );

View File

@ -0,0 +1,40 @@
/**
* External dependencies
*/
import { Button } from '@wordpress/components';
import ChevronUpIcon from 'gridicons/dist/chevron-up';
import ChevronDownIcon from 'gridicons/dist/chevron-down';
import { useState } from '@wordpress/element';
/**
* Internal dependencies
*/
import './Toggle.scss';
export const Toggle = ( { children, heading, onToggle } ) => {
const [ isShow, setIsShow ] = useState( false );
const onClick = () => {
onToggle( isShow );
setIsShow( ! isShow );
};
return (
<div className="toggle">
<Button
isTertiary
onClick={ onClick }
aria-expanded={ isShow }
frameBorder={ 0 }
className="toggle-button"
>
{ heading }
{ isShow ? (
<ChevronUpIcon size={ 18 } />
) : (
<ChevronDownIcon size={ 18 } />
) }
</Button>
{ isShow ? children : null }
</div>
);
};

View File

@ -0,0 +1,9 @@
.woocommerce-task-payments {
.toggle-button {
margin: $gap-small 0;
.gridicon {
margin-left: 4px;
}
}
}

View File

@ -0,0 +1 @@
export { Toggle } from './Toggle';

View File

@ -13,17 +13,23 @@ import { useMemo, useCallback, useEffect } from '@wordpress/element';
import { registerPlugin } from '@wordpress/plugins';
import { WooOnboardingTask } from '@woocommerce/onboarding';
import { getNewPath } from '@woocommerce/navigation';
import { Button } from '@wordpress/components';
import ExternalIcon from 'gridicons/dist/external';
/**
* Internal dependencies
*/
import { List, Placeholder as ListPlaceholder } from './components/List';
import { Setup, Placeholder as SetupPlaceholder } from './components/Setup';
import { Toggle } from './components/Toggle/Toggle';
import { WCPaySuggestion } from './components/WCPay';
import { getPluginSlug } from '~/utils';
import './plugins/Bacs';
import './payment-gateway-suggestions.scss';
const SEE_MORE_LINK =
'https://woocommerce.com/product-category/woocommerce-extensions/payment-gateways/?utm_source=payments_recommendations';
const comparePaymentGatewaysByPriority = ( a, b ) =>
a.recommendation_priority - b.recommendation_priority;
@ -179,7 +185,7 @@ export const PaymentGatewaySuggestions = ( { onComplete, query } ) => {
return gateway;
}, [ isResolving, query, paymentGateways ] );
const [ wcPayGateway, enabledGateways, additionalGateways ] = useMemo(
const [ wcPayGateway, offlineGateways, additionalGateways ] = useMemo(
() =>
Array.from( paymentGateways.values() )
.sort( ( a, b ) => {
@ -196,7 +202,7 @@ export const PaymentGatewaySuggestions = ( { onComplete, query } ) => {
} )
.reduce(
( all, gateway ) => {
const [ wcPay, enabled, additional ] = all;
const [ wcPay, offline, additional ] = all;
// WCPay is handled separately when not installed and configured
if (
@ -205,8 +211,8 @@ export const PaymentGatewaySuggestions = ( { onComplete, query } ) => {
! ( gateway.installed && ! gateway.needsSetup )
) {
wcPay.push( gateway );
} else if ( gateway.enabled ) {
enabled.push( gateway );
} else if ( gateway.is_offline ) {
offline.push( gateway );
} else {
additional.push( gateway );
}
@ -218,6 +224,20 @@ export const PaymentGatewaySuggestions = ( { onComplete, query } ) => {
[ paymentGateways ]
);
const isEligibleWCPay = !! wcPayGateway.length;
const trackSeeMore = () => {
recordEvent( 'tasklist_payment_see_more', {} );
};
const trackToggle = ( isShow ) => {
recordEvent( 'tasklist_payment_show_toggle', {
toggle: isShow ? 'hide' : 'show',
payment_method_count:
offlineGateways.length + additionalGateways.length,
} );
};
if ( query.id && ! currentGateway ) {
return <SetupPlaceholder />;
}
@ -231,32 +251,59 @@ export const PaymentGatewaySuggestions = ( { onComplete, query } ) => {
);
}
const additionalSection = !! additionalGateways.length && (
<List
heading={
isEligibleWCPay
? null
: __( 'Choose a payment provider', 'woocommerce' )
}
recommendation={ recommendation }
paymentGateways={ additionalGateways }
markConfigured={ markConfigured }
footerLink={
<Button
href={ SEE_MORE_LINK }
target="_blank"
onClick={ trackSeeMore }
isTertiary
>
{ __( 'See more', 'woocommerce' ) }
<ExternalIcon size={ 18 } />
</Button>
}
></List>
);
const offlineSection = !! offlineGateways.length && (
<List
heading={ __( 'Offline payment methods', 'woocommerce' ) }
recommendation={ recommendation }
paymentGateways={ offlineGateways }
markConfigured={ markConfigured }
/>
);
return (
<div className="woocommerce-task-payments">
{ ! paymentGateways.size && <ListPlaceholder /> }
{ !! wcPayGateway.length && (
{ isEligibleWCPay ? (
<>
<WCPaySuggestion paymentGateway={ wcPayGateway[ 0 ] } />
) }
{ !! enabledGateways.length && (
<List
heading={ __( 'Enabled payment gateways', 'woocommerce' ) }
recommendation={ recommendation }
paymentGateways={ enabledGateways }
/>
) }
{ !! additionalGateways.length && (
<List
heading={ __(
'Additional payment gateways',
'woocommerce'
) }
recommendation={ recommendation }
paymentGateways={ additionalGateways }
markConfigured={ markConfigured }
/>
<Toggle
heading={ __( 'Other payment methods', 'woocommerce' ) }
onToggle={ trackToggle }
>
{ additionalSection }
{ offlineSection }
</Toggle>
</>
) : (
<>
{ additionalSection }
{ offlineSection }
</>
) }
</div>
);

View File

@ -22,6 +22,14 @@
margin: 0;
}
.components-card__footer {
a.components-button {
.gridicon {
margin-left: 4px;
}
}
}
.woocommerce-task-payment__recommended-pill {
border: 1px solid $studio-gray-5;
border-radius: 28px;

View File

@ -49,6 +49,7 @@ const paymentGatewaySuggestions = [
image:
'http://localhost:8888/wp-content/plugins/woocommerce-admin/images/onboarding/cod.svg',
is_visible: true,
is_offline: true,
},
{
id: 'bacs',
@ -57,6 +58,7 @@ const paymentGatewaySuggestions = [
image:
'http://localhost:8888/wp-content/plugins/woocommerce-admin/images/onboarding/bacs.svg',
is_visible: true,
is_offline: true,
},
{
id: 'woocommerce_payments:non-us',
@ -83,8 +85,12 @@ const paymentGatewaySuggestions = [
},
];
const paymentGatewaySuggestionsWithoutWCPay = paymentGatewaySuggestions.filter(
( p ) => p.title !== 'WooCommerce Payments'
);
describe( 'PaymentGatewaySuggestions', () => {
test( 'should render payment gateway lists', () => {
test( 'should render only WCPay if its suggested', () => {
const onComplete = jest.fn();
const query = {};
useSelect.mockImplementation( () => ( {
@ -109,6 +115,38 @@ describe( 'PaymentGatewaySuggestions', () => {
( e ) => e.textContent
);
expect( paymentTitles ).toEqual( [] );
expect(
container.getElementsByTagName( 'title' )[ 0 ].textContent
).toBe( 'WooCommerce Payments' );
} );
test( 'should render all payment gateways if no WCPay', () => {
const onComplete = jest.fn();
const query = {};
useSelect.mockImplementation( () => ( {
isResolving: false,
getPaymentGateway: jest.fn(),
paymentGatewaySuggestions: paymentGatewaySuggestionsWithoutWCPay,
installedPaymentGateways: [],
} ) );
const { container } = render(
<PaymentGatewaySuggestions
onComplete={ onComplete }
query={ query }
/>
);
const paymentTitleElements = container.querySelectorAll(
'.woocommerce-task-payment__title'
);
const paymentTitles = Array.from( paymentTitleElements ).map(
( e ) => e.textContent
);
expect( paymentTitles ).toEqual( [
'Stripe',
'PayPal Payments',
@ -116,10 +154,6 @@ describe( 'PaymentGatewaySuggestions', () => {
'Cash on delivery',
'Direct bank transfer',
] );
expect(
container.getElementsByTagName( 'title' )[ 0 ].textContent
).toBe( 'WooCommerce Payments' );
} );
test( 'should the payment gateway offline options at the bottom', () => {
@ -128,7 +162,7 @@ describe( 'PaymentGatewaySuggestions', () => {
useSelect.mockImplementation( () => ( {
isResolving: false,
getPaymentGateway: jest.fn(),
paymentGatewaySuggestions,
paymentGatewaySuggestions: paymentGatewaySuggestionsWithoutWCPay,
installedPaymentGateways: [],
} ) );
@ -154,7 +188,7 @@ describe( 'PaymentGatewaySuggestions', () => {
useSelect.mockImplementation( () => ( {
isResolving: false,
getPaymentGateway: jest.fn(),
paymentGatewaySuggestions,
paymentGatewaySuggestions: paymentGatewaySuggestionsWithoutWCPay,
installedPaymentGateways: [
{
id: 'ppcp-gateway',
@ -184,7 +218,7 @@ describe( 'PaymentGatewaySuggestions', () => {
useSelect.mockImplementation( () => ( {
isResolving: false,
getPaymentGateway: jest.fn(),
paymentGatewaySuggestions,
paymentGatewaySuggestions: paymentGatewaySuggestionsWithoutWCPay,
installedPaymentGateways: [
{
id: 'ppcp-gateway',
@ -211,4 +245,59 @@ describe( 'PaymentGatewaySuggestions', () => {
selected: 'ppcp_gateway',
} );
} );
test( 'should record event correctly when other payment methods is clicked', () => {
const onComplete = jest.fn();
const query = {};
useSelect.mockImplementation( () => ( {
isResolving: false,
getPaymentGateway: jest.fn(),
paymentGatewaySuggestions,
installedPaymentGateways: [],
} ) );
render(
<PaymentGatewaySuggestions
onComplete={ onComplete }
query={ query }
/>
);
fireEvent.click( screen.getByText( 'Other payment methods' ) );
// By default it's hidden, so when toggle it shows.
expect( recordEvent ).toHaveBeenCalledWith(
'tasklist_payment_show_toggle',
{
toggle: 'show',
payment_method_count: paymentGatewaySuggestions.length - 1, // Minus one for WCPay since it's not counted in "other payment methods".
}
);
} );
test( 'should record event correctly when see more is clicked', () => {
const onComplete = jest.fn();
const query = {};
useSelect.mockImplementation( () => ( {
isResolving: false,
getPaymentGateway: jest.fn(),
paymentGatewaySuggestions,
installedPaymentGateways: [],
} ) );
render(
<PaymentGatewaySuggestions
onComplete={ onComplete }
query={ query }
/>
);
fireEvent.click( screen.getByText( 'Other payment methods' ) );
fireEvent.click( screen.getByText( 'See more' ) );
expect( recordEvent ).toHaveBeenCalledWith(
'tasklist_payment_see_more',
{}
);
} );
} );

View File

@ -15,7 +15,7 @@ import { ONBOARDING_STORE_NAME, PLUGINS_STORE_NAME } from '@woocommerce/data';
import CartModal from '../../dashboard/components/cart-modal';
import { getCategorizedOnboardingProducts } from '../../dashboard/utils';
const PurchaseTaskItem = () => {
const PurchaseTaskItem = ( { defaultTaskItem } ) => {
const [ cartModalOpen, setCartModalOpen ] = useState( false );
const { installedPlugins, productTypes, profileItems } = useSelect(
@ -47,10 +47,9 @@ const PurchaseTaskItem = () => {
installedPlugins
);
const { remainingProducts } = groupedProducts;
const DefaultTaskItem = defaultTaskItem;
return (
<WooOnboardingTaskListItem id="purchase">
{ ( { defaultTaskItem: DefaultTaskItem } ) => (
<>
<DefaultTaskItem
onClick={ () => {
@ -66,6 +65,14 @@ const PurchaseTaskItem = () => {
/>
) }
</>
);
};
const PurchaseTaskItemFill = () => {
return (
<WooOnboardingTaskListItem id="purchase">
{ ( { defaultTaskItem } ) => (
<PurchaseTaskItem defaultTaskItem={ defaultTaskItem } />
) }
</WooOnboardingTaskListItem>
);
@ -73,5 +80,5 @@ const PurchaseTaskItem = () => {
registerPlugin( 'woocommerce-admin-task-purchase', {
scope: 'woocommerce-tasks',
render: PurchaseTaskItem,
render: PurchaseTaskItemFill,
} );

View File

@ -6,7 +6,11 @@ import { useEffect, useRef, useState } from '@wordpress/element';
import { Card, CardHeader } from '@wordpress/components';
import { useSelect } from '@wordpress/data';
import { Badge } from '@woocommerce/components';
import { ONBOARDING_STORE_NAME, TaskListType } from '@woocommerce/data';
import {
getVisibleTasks,
ONBOARDING_STORE_NAME,
TaskListType,
} from '@woocommerce/data';
import { recordEvent } from '@woocommerce/tracks';
import { Text, List, CollapsibleList } from '@woocommerce/experimental';
@ -45,12 +49,7 @@ export const TaskList: React.FC< TaskListProps > = ( {
};
} );
const prevQueryRef = useRef( query );
const nowTimestamp = Date.now();
const visibleTasks = tasks.filter(
( task ) =>
! task.isDismissed &&
( ! task.isSnoozed || task.snoozedUntil < nowTimestamp )
);
const visibleTasks = getVisibleTasks( tasks );
const incompleteTasks = tasks.filter(
( task ) => ! task.isComplete && ! task.isDismissed

View File

@ -236,7 +236,7 @@
}
.woocommerce-task-list__setup_experiment_1 {
.woocommerce-experimental-list .woocommerce-experimental-list__item.complete {
.woocommerce-experimental-list .woocommerce-experimental-list__item.is-complete {
text-decoration: line-through;
.woocommerce-task-list__item-title {

View File

@ -4,7 +4,7 @@
import { __ } from '@wordpress/i18n';
import { MenuGroup, MenuItem } from '@wordpress/components';
import { check } from '@wordpress/icons';
import { Fragment, useEffect, lazy, Suspense } from '@wordpress/element';
import { Fragment, useEffect } from '@wordpress/element';
import { useDispatch, useSelect } from '@wordpress/data';
import { ONBOARDING_STORE_NAME, OPTIONS_STORE_NAME } from '@woocommerce/data';
import { useExperiment } from '@woocommerce/explat';
@ -15,37 +15,41 @@ import { recordEvent } from '@woocommerce/tracks';
*/
import { DisplayOption } from '~/activity-panel/display-options';
import { Task } from './task';
import { TasksPlaceholder } from './placeholder';
import { TasksPlaceholder, TasksPlaceholderProps } from './placeholder';
import './tasks.scss';
import { TaskListProps } from './task-list';
import { TaskListProps, TaskList } from './task-list';
import { TaskList as TwoColumnTaskList } from '../two-column-tasks/task-list';
import { SectionedTaskList } from '../two-column-tasks/sectioned-task-list';
import TwoColumnTaskListPlaceholder from '../two-column-tasks/placeholder';
import '../two-column-tasks/style.scss';
import { getAdminSetting } from '~/utils/admin-settings';
export type TasksProps = {
query: { task?: string };
};
const TaskList = lazy(
() => import( /* webpackChunkName: "task-list" */ './task-list' )
);
const TwoColumnTaskList = lazy(
() =>
import(
/* webpackChunkName: "two-column-task-list" */ '../two-column-tasks/task-list'
)
);
function getTaskListComponent(
taskListId: string
): React.LazyExoticComponent< React.FC< TaskListProps > > {
function getTaskListComponent( taskListId: string ): React.FC< TaskListProps > {
switch ( taskListId ) {
case 'setup_experiment_1':
return TwoColumnTaskList;
case 'setup_experiment_2':
return SectionedTaskList;
default:
return TaskList;
}
}
function getTaskListPlaceholderComponent(
taskListId: string
): React.FC< TasksPlaceholderProps > {
switch ( taskListId ) {
case 'setup_experiment_1':
return TwoColumnTaskListPlaceholder;
default:
return TasksPlaceholder;
}
}
export const Tasks: React.FC< TasksProps > = ( { query } ) => {
const { task } = query;
const { hideTaskList } = useDispatch( ONBOARDING_STORE_NAME );
@ -56,9 +60,9 @@ export const Tasks: React.FC< TasksProps > = ( { query } ) => {
const { isResolving, taskLists } = useSelect( ( select ) => {
return {
isResolving: select( ONBOARDING_STORE_NAME ).isResolving(
'getTaskLists'
),
isResolving: ! select(
ONBOARDING_STORE_NAME
).hasFinishedResolution( 'getTaskLists' ),
taskLists: select( ONBOARDING_STORE_NAME ).getTaskLists(),
};
} );
@ -108,8 +112,13 @@ export const Tasks: React.FC< TasksProps > = ( { query } ) => {
return null;
}
const taskListIds = getAdminSetting( 'visibleTaskListIds', [] );
const TaskListPlaceholderComponent = getTaskListPlaceholderComponent(
taskListIds[ 0 ]
);
if ( isResolving ) {
return <TasksPlaceholder query={ query } />;
return <TaskListPlaceholderComponent query={ query } />;
}
if ( currentTask ) {
@ -121,7 +130,7 @@ export const Tasks: React.FC< TasksProps > = ( { query } ) => {
}
if ( isLoadingExperiment ) {
return <TasksPlaceholder query={ query } />;
return <TaskListPlaceholderComponent query={ query } />;
}
return taskLists
@ -131,17 +140,7 @@ export const Tasks: React.FC< TasksProps > = ( { query } ) => {
: ! id.endsWith( 'two_column' )
)
.map( ( taskList ) => {
const {
id,
eventPrefix,
isComplete,
isHidden,
isVisible,
isToggleable,
title,
tasks,
displayProgressHeader,
} = taskList;
const { id, isHidden, isVisible, isToggleable } = taskList;
if ( ! isVisible ) {
return null;
@ -151,22 +150,14 @@ export const Tasks: React.FC< TasksProps > = ( { query } ) => {
return (
<Fragment key={ id }>
<Suspense fallback={ null }>
<TaskListComponent
id={ id }
eventPrefix={ eventPrefix }
isComplete={ isComplete }
isExpandable={
experimentAssignment?.variationName ===
'treatment'
experimentAssignment?.variationName === 'treatment'
}
query={ query }
tasks={ tasks }
title={ title }
twoColumns={ false }
displayProgressHeader={ displayProgressHeader }
{ ...taskList }
/>
</Suspense>
{ isToggleable && (
<DisplayOption>
<MenuGroup

View File

@ -27,10 +27,13 @@ jest.mock( '@wordpress/data', () => {
jest.mock( '@woocommerce/explat' );
jest.mock( '@woocommerce/tracks' );
jest.mock( '../task-list', () => ( { id } ) => <div>task-list:{ id }</div> );
jest.mock( '../../two-column-tasks/task-list', () => ( { id } ) => (
<div>two-column-list:{ id }</div>
) );
jest.mock( '../task-list', () => ( {
TaskList: ( { id } ) => <div>task-list:{ id }</div>,
} ) );
jest.mock( '../../two-column-tasks/task-list', () => ( {
TaskList: ( { id } ) => <div>two-column-list:{ id }</div>,
} ) );
jest.mock( '../task', () => ( {
Task: ( { query } ) => <div>task:{ query.task }</div>,

View File

@ -0,0 +1,26 @@
.woocommerce-task-section-header__container {
display: flex;
.woocommerce-task-header__illustration {
max-width: 150px;
width: 34%;
margin-left: auto;
margin-right: 7%;
display: flex;
align-items: center;
.illustration-background {
max-width: 100%;
}
}
.woocommerce-task-header__contents p {
font-size: 16px;
}
.woocommerce-task-header__contents h1 {
font-size: 20px;
line-height: 28px;
padding: 0;
}
}

View File

@ -0,0 +1,30 @@
/**
* Internal dependencies
*/
import './section-header.scss';
type Props = {
title: string;
description: string;
image: string;
};
const SectionHeader: React.FC< Props > = ( { title, description, image } ) => {
return (
<div className="woocommerce-task-header__contents-container woocommerce-task-section-header__container">
<div className="woocommerce-task-header__contents">
<h1>{ title }</h1>
<p>{ description }</p>
</div>
<div className="woocommerce-task-header__illustration">
<img
src={ image }
alt={ title }
className="illustration-background"
/>
</div>
</div>
);
};
export default SectionHeader;

View File

@ -3,7 +3,7 @@
*/
import { __ } from '@wordpress/i18n';
import { useSelect } from '@wordpress/data';
import { ONBOARDING_STORE_NAME, OPTIONS_STORE_NAME } from '@woocommerce/data';
import { ONBOARDING_STORE_NAME } from '@woocommerce/data';
/**
* Internal dependencies
@ -14,25 +14,7 @@ import TaskList from './task-list';
import TaskListPlaceholder from './placeholder';
import { Task } from '../tasks/task';
const taskDashboardSelect = ( select ) => {
const { getOption, hasFinishedResolution } = select( OPTIONS_STORE_NAME );
return {
keepCompletedTaskList: getOption(
'woocommerce_task_list_keep_completed'
),
isResolving: ! hasFinishedResolution( 'getOption', [
'woocommerce_task_list_keep_completed',
] ),
};
};
const TaskDashboard = ( { query, twoColumns } ) => {
const {
keepCompletedTaskList,
isResolving: isResolvingOptions,
} = useSelect( taskDashboardSelect );
const { task } = query;
const { isResolving, taskLists } = useSelect( ( select ) => {
@ -72,7 +54,7 @@ const TaskDashboard = ( { query, twoColumns } ) => {
return null;
}
if ( isResolving || isResolvingOptions || ! taskLists[ 0 ] ) {
if ( isResolving || ! taskLists[ 0 ] ) {
return <TaskListPlaceholder twoColumns={ twoColumns } />;
}
@ -104,7 +86,7 @@ const TaskDashboard = ( { query, twoColumns } ) => {
id={ taskList.id }
eventName="tasklist"
twoColumns={ twoColumns }
keepCompletedTaskList={ keepCompletedTaskList }
keepCompletedTaskList={ taskList.keepCompletedTaskList }
dismissedTasks={ dismissedTasks || [] }
isComplete={ isTaskListComplete }
query={ query }

View File

@ -8,7 +8,15 @@ import classnames from 'classnames';
*/
import './style.scss';
const TaskListPlaceholder = ( props ) => {
type TasksPlaceholderProps = {
numTasks?: number;
twoColumns?: boolean;
query: {
task?: string;
};
};
const TaskListPlaceholder: React.FC< TasksPlaceholderProps > = ( props ) => {
const { numTasks = 5, twoColumns = false } = props;
return (

View File

@ -0,0 +1,53 @@
/**
* External dependencies
*/
import { Badge } from '@woocommerce/components';
import { TaskListSection, TaskType } from '@woocommerce/data';
import { Icon, check } from '@wordpress/icons';
import { Text } from '@woocommerce/experimental';
/**
* Internal dependencies
*/
import SectionHeader from './headers/section-header';
type SectionPanelTitleProps = {
section: TaskListSection;
active: boolean;
tasks: TaskType[];
};
export const SectionPanelTitle: React.FC< SectionPanelTitleProps > = ( {
section,
active,
tasks,
} ) => {
if ( active ) {
return (
<div className="wooocommerce-task-card__header-container">
<div className="wooocommerce-task-card__header">
<SectionHeader { ...section } />
</div>
</div>
);
}
const uncompletedTasksCount = tasks.filter(
( task ) => ! task.isComplete && section.tasks.includes( task.id )
).length;
const isComplete = section.isComplete || uncompletedTasksCount === 0;
return (
<>
<Text variant="title.small" size="20" lineHeight="28px">
{ section.title }
</Text>
{ ! isComplete && <Badge count={ uncompletedTasksCount } /> }
{ isComplete && (
<div className="woocommerce-task__icon">
<Icon icon={ check } />
</div>
) }
</>
);
};

View File

@ -0,0 +1,92 @@
.woocommerce-sectioned-task-list {
.components-panel {
width: 100%;
background: transparent;
border: 0;
}
.components-panel__body {
padding-bottom: 0;
margin-bottom: $gap-smaller;
background: #fff;
border: 1px solid $gray-200;
&.is-opened {
padding-bottom: 0;
}
.components-panel__body-title {
margin-bottom: 0;
border-bottom: 1px solid #e0e0e0;
&:hover {
border-bottom: 1px solid #e0e0e0;
}
> .components-button {
font-size: 20px;
font-weight: 400;
padding-top: 20px;
padding-bottom: 20px;
}
.components-panel__arrow {
right: $gap-large;
}
}
.wooocommerce-task-card__header-container {
width: 100%;
border-bottom: none;
}
.components-panel__body-toggle {
box-shadow: none;
padding-left: $gap-large;
}
&.is-opened .components-panel__body-toggle {
width: 100%;
padding: 0;
.components-panel__arrow {
top: 32px;
}
}
.woocommerce-experimental-list {
width: calc(100% + 32px);
margin: 0 -16px;
}
}
ul li.woocommerce-task-list__item {
padding-top: $gap;
padding-bottom: $gap;
&.is-disabled {
pointer-events: none;
}
&:not(.is-complete) .woocommerce-task-list__item-before .woocommerce-task__icon {
border-color: $gray-300;
}
}
.woocommerce-task-list__item.is-complete .woocommerce-task__icon {
background-color: $alert-green;
}
.components-panel__body-title {
.woocommerce-badge {
width: 28px;
height: 28px;
}
.woocommerce-task__icon {
margin-left: $gap;
background-color: $alert-green;
border-radius: 50%;
width: 24px;
height: 24px;
svg {
fill: #fff;
position: relative;
}
}
}
}

View File

@ -0,0 +1,252 @@
/**
* External dependencies
*/
import { __ } from '@wordpress/i18n';
import { useEffect, useRef, useState } from '@wordpress/element';
import { Panel, PanelBody, PanelRow } from '@wordpress/components';
import { useSelect, useDispatch } from '@wordpress/data';
import { updateQueryString } from '@woocommerce/navigation';
import {
OPTIONS_STORE_NAME,
ONBOARDING_STORE_NAME,
TaskType,
getVisibleTasks,
} from '@woocommerce/data';
import { recordEvent } from '@woocommerce/tracks';
import { List, TaskItem } from '@woocommerce/experimental';
import classnames from 'classnames';
/**
* Internal dependencies
*/
import '../tasks/task-list.scss';
import './sectioned-task-list.scss';
import TaskListCompleted from './completed';
import { TaskListProps } from '~/tasks/task-list';
import { ProgressHeader } from '~/task-lists/progress-header';
import { SectionPanelTitle } from './section-panel-title';
type PanelBodyProps = Omit< PanelBody.Props, 'title' | 'onToggle' > & {
title: string | React.ReactNode | undefined;
onToggle?: ( isOpen: boolean ) => void;
};
const PanelBodyWithUpdatedType = PanelBody as React.ComponentType< PanelBodyProps >;
export const SectionedTaskList: React.FC< TaskListProps > = ( {
query,
id,
eventName,
tasks,
keepCompletedTaskList,
isComplete,
sections,
displayProgressHeader,
} ) => {
const { createNotice } = useDispatch( 'core/notices' );
const { updateOptions, dismissTask, undoDismissTask } = useDispatch(
OPTIONS_STORE_NAME
);
const { profileItems } = useSelect( ( select ) => {
const { getProfileItems } = select( ONBOARDING_STORE_NAME );
return {
profileItems: getProfileItems(),
};
} );
const { hideTaskList } = useDispatch( ONBOARDING_STORE_NAME );
const [ openPanel, setOpenPanel ] = useState< string | null >(
sections?.find( ( section ) => ! section.isComplete )?.id || null
);
const prevQueryRef = useRef( query );
const visibleTasks = getVisibleTasks( tasks );
const recordTaskListView = () => {
if ( query.task ) {
return;
}
recordEvent( `${ eventName }_view`, {
number_tasks: visibleTasks.length,
store_connected: profileItems.wccom_connected,
} );
};
useEffect( () => {
recordTaskListView();
}, [] );
useEffect( () => {
const { task: prevTask } = prevQueryRef.current;
const { task } = query;
if ( prevTask !== task ) {
window.document.documentElement.scrollTop = 0;
prevQueryRef.current = query;
}
}, [ query ] );
const onDismissTask = ( taskId: string ) => {
dismissTask( taskId );
createNotice( 'success', __( 'Task dismissed' ), {
actions: [
{
label: __( 'Undo', 'woocommerce-admin' ),
onClick: () => undoDismissTask( taskId ),
},
],
} );
};
const hideTasks = () => {
hideTaskList( id );
};
const keepTasks = () => {
const updateOptionsParams = {
woocommerce_task_list_keep_completed: 'yes',
};
updateOptions( {
...updateOptionsParams,
} );
};
let selectedHeaderCard = visibleTasks.find(
( listTask ) => listTask.isComplete === false
);
// If nothing is selected, default to the last task since everything is completed.
if ( ! selectedHeaderCard ) {
selectedHeaderCard = visibleTasks[ visibleTasks.length - 1 ];
}
const trackClick = ( task: TaskType ) => {
recordEvent( `${ eventName }_click`, {
task_name: task.id,
} );
};
const goToTask = ( task: TaskType ) => {
trackClick( task );
updateQueryString( { task: task.id } );
};
const onTaskSelected = ( task: TaskType ) => {
goToTask( task );
};
const getSectionTasks = ( sectionTaskIds: string[] ) => {
return visibleTasks.filter( ( task ) =>
sectionTaskIds.includes( task.id )
);
};
if ( ! visibleTasks.length ) {
return <div className="woocommerce-task-dashboard__container"></div>;
}
if ( isComplete && ! keepCompletedTaskList ) {
return (
<>
<TaskListCompleted
hideTasks={ hideTasks }
keepTasks={ keepTasks }
twoColumns={ false }
/>
</>
);
}
return (
<>
{ displayProgressHeader ? (
<ProgressHeader taskListId={ id } />
) : null }
<div
className={ classnames(
`woocommerce-task-dashboard__container woocommerce-sectioned-task-list two-column-experiment woocommerce-task-list__${ id }`
) }
>
<Panel>
{ ( sections || [] ).map( ( section ) => (
<PanelBodyWithUpdatedType
key={ section.id }
title={
<SectionPanelTitle
section={ section }
tasks={ tasks }
active={ openPanel === section.id }
/>
}
opened={ openPanel === section.id }
onToggle={ ( isOpen: boolean ) => {
if ( ! isOpen && openPanel === section.id ) {
setOpenPanel( null );
} else {
setOpenPanel( section.id );
}
} }
initialOpen={ false }
>
<PanelRow>
<List animation="custom">
{ getSectionTasks( section.tasks ).map(
( task ) => {
const className = classnames(
'woocommerce-task-list__item',
{
'is-complete':
task.isComplete,
'is-disabled':
task.isDisabled,
}
);
return (
<TaskItem
key={ task.id }
className={ className }
title={ task.title }
completed={
task.isComplete
}
expanded={
! task.isComplete
}
content={ task.content }
onClick={ () => {
if (
! task.isDisabled
) {
onTaskSelected(
task
);
}
} }
onDismiss={
task.isDismissable
? () =>
onDismissTask(
task.id
)
: undefined
}
action={ () => {} }
actionLabel={
task.actionLabel
}
/>
);
}
) }
</List>
</PanelRow>
</PanelBodyWithUpdatedType>
) ) }
</Panel>
</div>
</>
);
};
export default SectionedTaskList;

View File

@ -19,10 +19,10 @@
flex: 1;
}
.woocommerce-ellipsis-menu.setup {
.woocommerce-ellipsis-menu {
position: absolute;
top: 20px;
right: 16px;
top: $gap;
right: $gap-large;
}
.woocommerce-task-card.is-loading {
@ -103,7 +103,7 @@
margin: 0 auto;
justify-content: space-between;
ul li.complete .woocommerce-task-list__item-title {
ul li.is-complete .woocommerce-task-list__item-title {
font-weight: 600;
color: $gray-600;
}
@ -130,11 +130,11 @@
}
.woocommerce-task-header__contents {
max-width: 380px;
max-width: calc(60% - 2%);
}
.svg-background {
right: 0.5%;
right: 2%;
width: 40%;
}
}
@ -143,6 +143,13 @@
@include single-column;
}
&.two-columns .svg-background {
top: 50%;
bottom: 50%;
margin-top: auto;
margin-bottom: auto;
}
ul {
display: flex;
li {
@ -171,10 +178,13 @@
height: 100%;
}
}
.woocommerce-task-list__item:not(.complete) .woocommerce-task__icon {
.woocommerce-task-list__item:not(.is-complete) .woocommerce-task__icon {
border: 1px solid var(--wp-admin-theme-color);
background: transparent;
}
.woocommerce-task-list__item.is-complete:not(.complete) .woocommerce-task__icon {
border: none;
}
.woocommerce-task-list__item-before {
display: block;
@ -196,7 +206,7 @@
}
@for $i from 1 through 10 {
.woocommerce-task-list__item:not(.complete).index-#{$i} .woocommerce-task__icon::after {
.woocommerce-task-list__item:not(.is-complete).index-#{$i} .woocommerce-task__icon::after {
content: '#{$i}';
@extend .numbered-circle;
color: var(--wp-admin-theme-color);
@ -229,10 +239,6 @@
position: absolute;
z-index: 0;
right: 6%;
top: 50%;
bottom: 50%;
margin-top: auto;
margin-bottom: auto;
.admin-theme-color {
fill: var(--wp-admin-theme-color);

View File

@ -16,6 +16,7 @@ import {
ONBOARDING_STORE_NAME,
TaskType,
useUserPreferences,
getVisibleTasks,
} from '@woocommerce/data';
import { recordEvent } from '@woocommerce/tracks';
import { List, TaskItem } from '@woocommerce/experimental';
@ -63,12 +64,7 @@ export const TaskList: React.FC< TaskListProps > = ( {
const prevQueryRef = useRef( query );
const nowTimestamp = Date.now();
const visibleTasks = tasks.filter(
( task ) =>
! task.isDismissed &&
( ! task.isSnoozed || task.snoozedUntil < nowTimestamp )
);
const visibleTasks = getVisibleTasks( tasks );
const recordTaskListView = () => {
if ( query.task ) {
@ -295,7 +291,7 @@ export const TaskList: React.FC< TaskListProps > = ( {
const className = classnames(
'woocommerce-task-list__item index-' + index,
{
complete: task.isComplete,
'is-complete': task.isComplete,
'is-active': task.id === activeTaskId,
}
);

View File

@ -1,22 +0,0 @@
# Languages
## Contributing a Translation
If you'd like to contribute a translation, please follow the Localizing section in [CONTRIBUTING.md](https://github.com/woocommerce/woocommerce-admin/blob/main/CONTRIBUTING.md).
## Generating POT
The generated POT template file is not included in this repository. To create this file locally, follow instructions from [README.md](https://github.com/woocommerce/woocommerce-admin/blob/main/README.md) to install the project, then run the following command:
```
pnpm run i18n lang=xx_YY
```
After the build completes, you'll find a `woocommerce-admin-xx_YY.po` (eg. `woocommerce-admin-fr_FR.po`) strings file in this directory.
## Generating JSON
To generate JSON from your translations, save your translation file in this directory then run the following command:
```
pnpm run i18n:json
```

View File

@ -1,47 +0,0 @@
module.exports = {
'*.scss': [ 'pnpm run lint:css-fix' ],
'client/**/*.(t|j)s?(x)': [
'wp-scripts format-js',
'wp-scripts lint-js',
'pnpm run test-staged',
],
'packages/**/*.(t|j)s?(x)': ( packageFiles ) => {
const globalScripts = [
`wp-scripts format-js ${ packageFiles.join( ' ' ) }`,
`wp-scripts lint-js ${ packageFiles.join( ' ' ) }`,
];
const filesByPackage = packageFiles.reduce(
( packages, packageFile ) => {
const packageNameMatch = packageFile.match(
/\/packages\/([a-z0-9\-]+)\//
);
if ( ! packageNameMatch ) {
return packages;
}
const packageName = packageNameMatch[ 1 ];
if ( Array.isArray( packages[ packageName ] ) ) {
packages[ packageName ].push( packageFile );
} else {
packages[ packageName ] = [ packageFile ];
}
return packages;
},
{}
);
const workspaceScripts = Object.keys( filesByPackage ).map(
( packageName ) =>
`pnpm --filter @woocommerce/${ packageName } run test-staged -- ${ filesByPackage[
packageName
].join( ' ' ) }`
);
return globalScripts.concat( workspaceScripts );
},
'*.php': [ 'php -d display_errors=1 -l', 'composer run-script phpcs' ],
};

View File

@ -1,92 +1,63 @@
{
"name": "@woocommerce/admin-library",
"version": "3.3.0",
"homepage": "https://woocommerce.github.io/woocommerce-admin/",
"repository": {
"type": "git",
"url": "https://github.com:woocommerce/woocommerce-admin.git"
},
"license": "GPL-3.0-or-later",
"author": "Automattic",
"files": [
"dist/**/*.css",
"dist/**/*.js",
"dist/feature-config-core.php",
"includes/class-wc-admin-loader.php",
"includes/features/**/*.php",
"languages/**/*.json",
"license.txt"
],
"homepage": "https://github.com/woocommerce/woocommerce/tree/trunk/plugins/woocommerce-admin/README.md",
"repository": {
"type": "git",
"url": "https://github.com:woocommerce/woocommerce.git"
},
"scripts": {
"preinstall": "npx only-allow pnpm",
"prebuild": "pnpm run install-if-deps-outdated",
"run:packages": "pnpm run --filter ../../packages/js/",
"packages:fix:textdomain": "node ./bin/package-update-textdomain.js",
"build": "pnpm run build:feature-config && cross-env NODE_ENV=production webpack",
"analyze": "cross-env NODE_ENV=production ANALYZE=true webpack",
"postbuild": "pnpm run -s i18n:pot && pnpm run -s i18n:build",
"prebuild": "pnpm run install-if-deps-outdated",
"build": "pnpm run build:feature-config && cross-env NODE_ENV=production webpack",
"build-storybook": "build-storybook -c ./storybook/.storybook",
"build:feature-config": "php ../woocommerce/bin/generate-feature-config.php",
"build:packages": "cross-env NODE_ENV=production pnpm run:packages -- build",
"build:release": "./bin/build-plugin-zip.sh",
"clean": "rimraf ./dist && pnpm run:packages -- clean --parallel",
"clean": "rimraf ../woocommerce/assets/client/admin/* && pnpm run:packages -- clean --parallel",
"client:watch": "cross-env WC_ADMIN_PHASE=development pnpm run build:feature-config && cross-env WC_ADMIN_PHASE=development webpack --watch",
"create-hook-reference": "node ./bin/hook-reference/index.js",
"create-wc-extension": "node ./bin/starter-pack/starter-pack.js",
"predev": "pnpm run -s install-if-deps-outdated",
"dev": "cross-env WC_ADMIN_PHASE=development pnpm run build:feature-config && cross-env WC_ADMIN_PHASE=development pnpm run build:packages && cross-env WC_ADMIN_PHASE=development webpack",
"client:watch": "cross-env WC_ADMIN_PHASE=development pnpm run build:feature-config && cross-env WC_ADMIN_PHASE=development webpack --watch",
"packages:watch": "cross-env WC_ADMIN_PHASE=development pnpm run:packages -- start --parallel",
"docs": "./bin/import-wp-css-storybook.sh && BABEL_ENV=storybook STORYBOOK=true pnpm exec build-storybook -c storybook/.storybook -o ./docs/components/storybook",
"i18n": "pnpm run -s i18n:js && pnpm run -s i18n:check && pnpm run -s i18n:pot && pnpm run -s i18n:build",
"i18n:build": "php bin/combine-pot-files.php languages/woocommerce-admin.po languages/woocommerce-admin.pot",
"i18n:check": "grunt checktextdomain",
"i18n:js": "pnpm run clean && cross-env NODE_ENV=production babel client packages -o /dev/null",
"i18n:json": "./bin/make-i18n-json.sh",
"i18n:pot": "grunt makepot",
"example": "webpack --config docs/examples/extensions/examples.config.js --watch",
"preinstall": "npx only-allow pnpm",
"install-if-deps-outdated": "node bin/install-if-deps-outdated.js",
"install-if-no-packages": "node bin/install-if-no-packages.js",
"labels:dry": "github-label-sync --labels ./.github/label-sync-config.json --allow-added-labels --dry-run woocommerce/woocommerce-admin",
"labels:sync": "github-label-sync --labels ./.github/label-sync-config.json --allow-added-labels woocommerce/woocommerce-admin",
"lint": "pnpm run lint:js && pnpm run lint:css",
"lint:css": "stylelint '**/*.scss'",
"lint:css-fix": "stylelint '**/*.scss' --fix --ip 'storybook/wordpress'",
"lint:js": "wp-scripts lint-js ./client --ext=js,ts,tsx",
"lint:js-packages": "wp-scripts lint-js ../../packages/js --ext=js,ts,tsx",
"lint:js-fix": "pnpm run lint:js -- --fix --ext=js,ts,tsx",
"lint:php": "./vendor/bin/phpcs --standard=phpcs.xml.dist $(git ls-files | grep .php$)",
"lint:php-fix": "./vendor/bin/phpcbf --standard=phpcs.xml.dist $(git ls-files | grep .php$)",
"ts:check": "tsc --build ./tsconfig.json --pretty",
"ts:check:watch": "npm run ts:check -- --watch",
"reformat-files": "wp-scripts format-js -- --ignore-path .eslintignore",
"lint:js-packages": "wp-scripts lint-js ../../packages/js --ext=js,ts,tsx",
"lint:js-pre-commit": "wp-scripts lint-js --ext=js,ts,tsx",
"prepack": "pnpm install && pnpm run lint && pnpm run test && cross-env WC_ADMIN_PHASE=core pnpm run build",
"packages:fix:textdomain": "node ./bin/package-update-textdomain.js",
"packages:watch": "cross-env WC_ADMIN_PHASE=development pnpm run:packages -- start --parallel",
"pre-release": "./bin/pre-release.sh",
"publish-packages:check": "pnpm run build:packages && pnpm publish --dry-run --filter ../../packages/js/ --publish-branch main --report-summary && cat ../../pnpm-publish-summary.json && rimraf ../../pnpm-publish-summary.json",
"publish-packages:dev": "pnpm run build:packages && pnpm publish --filter ../../packages/js/ --publish-branch main --tag next",
"publish-packages:prod": "pnpm run build:packages && pnpm publish --filter ../../packages/js/ --publish-branch main",
"reformat-files": "wp-scripts format-js -- --ignore-path .eslintignore",
"run:packages": "pnpm run --filter ../../packages/js/",
"prestart": "pnpm run install-if-deps-outdated",
"start": "cross-env WC_ADMIN_PHASE=development pnpm run build:packages && cross-env WC_ADMIN_PHASE=development pnpm run build:feature-config && concurrently \"cross-env WC_ADMIN_PHASE=development webpack --watch\" \"cross-env WC_ADMIN_PHASE=development pnpm run:packages -- start --parallel\"",
"start:package": "pnpm run:packages -- start --parallel",
"pretest": "pnpm run -s install-if-no-packages",
"test:debug": "node --inspect-brk ./node_modules/.bin/jest --config client/jest.config.js --watch --runInBand --no-cache",
"test:client": "jest --config client/jest.config.js",
"test:packages": "pnpm run --filter ../../packages/js/ --filter !api-core-tests test",
"test": "pnpm nx build @woocommerce/js-tests && pnpm run test:client",
"test:e2e": "pnpm run build && test -z \"$(docker ps | grep woocommerce-admin-e2e)\" || pnpm exec wc-e2e docker:down && pnpm run e2e:docker-up && pnpm exec wc-e2e test:e2e",
"e2e:docker-up": "WC_E2E_FOLDER=../../../ pnpm exec wc-e2e docker:up ./tests/e2e/docker/initialize.sh",
"test-staged": "pnpm run test:client -- --bail --findRelatedTests",
"test:help": "wp-scripts test-unit-js --help",
"test:php": "docker-compose -f docker/wc-admin-php-test-suite/docker-compose.yml run --rm phpunit",
"posttest:php": "docker-compose -f docker/wc-admin-php-test-suite/docker-compose.yml down",
"test:update-snapshots": "pnpm run test:client -- --updateSnapshot && pnpm run --filter @woocommerce/components test:update-snapshots",
"test:watch": "tsc --build || concurrently \"pnpm run test:client -- --watch\" \"pnpm run:packages -- test:nobuild --parallel -- --watch\"",
"test:zip": "pnpm run clean && composer i && ./bin/build-test-zip.sh",
"example": "webpack --config docs/examples/extensions/examples.config.js --watch",
"pre-release": "./bin/pre-release.sh",
"create-wc-extension": "node ./bin/starter-pack/starter-pack.js",
"storybook": "./bin/import-wp-css-storybook.sh && BABEL_ENV=storybook STORYBOOK=true start-storybook -c ./storybook/.storybook -p 6007 --ci",
"storybook-rtl": "USE_RTL_STYLE=true pnpm run storybook",
"build-storybook": "build-storybook -c ./storybook/.storybook",
"changelog": "node ./bin/changelog --changelogSrcType='ZENHUB_RELEASE'",
"wp-env-mysql-port": "node ./docker/wc-admin-wp-env/mysql-port.js",
"create-hook-reference": "node ./bin/hook-reference/index.js",
"changelogger": "./vendor/bin/changelogger",
"test-instruction-logger": "./bin/test-instruction-logger/bin/test-instruction-logger"
"pretest": "pnpm run -s install-if-no-packages",
"test": "pnpm nx build @woocommerce/js-tests && pnpm run test:client",
"test-staged": "pnpm run test:client -- --bail --findRelatedTests",
"test:client": "jest --config client/jest.config.js",
"test:debug": "node --inspect-brk ./node_modules/.bin/jest --config client/jest.config.js --watch --runInBand --no-cache",
"test:help": "wp-scripts test-unit-js --help",
"test:packages": "pnpm run --filter ../../packages/js/ --filter !api-core-tests test",
"test:update-snapshots": "pnpm run test:client -- --updateSnapshot && pnpm run --filter @woocommerce/components test:update-snapshots",
"test:watch": "tsc --build || concurrently \"pnpm run test:client -- --watch\" \"pnpm run:packages -- test:nobuild --parallel -- --watch\"",
"ts:check": "tsc --build ./tsconfig.json --pretty",
"ts:check:watch": "npm run ts:check -- --watch"
},
"dependencies": {
"@automattic/explat-client": "^0.0.3",
@ -96,9 +67,9 @@
"@woocommerce/api": "^0.2.0",
"@woocommerce/e2e-environment": "^0.3.0",
"@woocommerce/e2e-utils": "^0.2.0",
"@wordpress/a11y": "^2.15.3",
"@wordpress/a11y": "^3.5.0",
"@wordpress/api-fetch": "^6.0.1",
"@wordpress/base-styles": "^3.6.0",
"@wordpress/base-styles": "^4.3.0",
"@wordpress/components": "^19.5.0",
"@wordpress/compose": "^5.1.2",
"@wordpress/core-data": "^4.1.2",
@ -107,10 +78,10 @@
"@wordpress/dom": "^3.3.2",
"@wordpress/dom-ready": "^3.3.1",
"@wordpress/element": "^4.1.1",
"@wordpress/hooks": "^2.12.3",
"@wordpress/hooks": "^3.5.0",
"@wordpress/html-entities": "^3.3.1",
"@wordpress/i18n": "^4.3.1",
"@wordpress/icons": "^6.3.0",
"@wordpress/icons": "^8.1.0",
"@wordpress/keycodes": "^3.3.1",
"@wordpress/notices": "^3.3.2",
"@wordpress/plugins": "^4.1.3",
@ -205,7 +176,6 @@
"@woocommerce/onboarding": "workspace:*",
"@woocommerce/style-build": "workspace:*",
"@woocommerce/tracks": "workspace:*",
"@wordpress/babel-plugin-makepot": "^2.1.3",
"@wordpress/babel-preset-default": "^6.5.1",
"@wordpress/browserslist-config": "^4.1.1",
"@wordpress/custom-templated-path-webpack-plugin": "^2.1.2",
@ -238,14 +208,9 @@
"expose-loader": "^3.1.0",
"fork-ts-checker-webpack-plugin": "^6.5.0",
"fs-extra": "^8.1.0",
"grunt": "^1.4.1",
"grunt-checktextdomain": "^1.0.1",
"grunt-wp-i18n": "^1.0.3",
"husky": "^7.0.0",
"jest": "^27.5.1",
"jest-environment-jsdom": "~27.5.0",
"jest-environment-node": "^27.5.1",
"lint-staged": "^12.3.5",
"md5": "^2.3.0",
"merge-config": "^2.0.0",
"mini-css-extract-plugin": "^2.6.0",
@ -282,6 +247,14 @@
"peerDependencies": {
"@wordpress/data": "^6.3.0"
},
"lint-staged": {
"*.scss": [ "pnpm lint:css-fix" ],
"client/**/*.(t|j)s?(x)": [
"pnpm reformat-files",
"pnpm wp-scripts lint-js",
"pnpm test-staged"
]
},
"engines": {
"node": "^16.13.1",
"pnpm": "^6.24.2"

View File

@ -47,7 +47,7 @@ class UnminifyWebpackPlugin {
compilation.hooks.processAssets.tap(
{
name: 'UnminifyWebpackPlugin',
stage: webpack.Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_INLINE,
stage: webpack.Compilation.PROCESS_ASSETS_STAGE_DERIVED,
},
( assets ) => {
Object.entries( assets ).forEach(

View File

@ -11,8 +11,6 @@
"homepage": "http://github.com/woocommerce/woocommerce-beta-tester",
"devDependencies": {
"eslint": "5.16.0",
"husky": "1.3.1",
"lint-staged": "8.1.5",
"uglify-js": "^3.5.3"
},
"assets": {
@ -32,28 +30,17 @@
"node": ">=10.15.0",
"npm": ">=6.4.1"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"linters": {
"*.php": [
"php -d display_errors=1 -l",
"composer run-script phpcs-pre-commit"
],
"*.js": [
"eslint --fix",
"git add"
]
},
"ignore": [
"*.min.js"
]
},
"woorelease": {
"svn_reauth": "true",
"wp_org_slug": "woocommerce-beta-tester"
},
"lint-staged": {
"*.php": [
"php -d display_errors=1 -l",
"composer --working-dir=./plugins/woocommerce-beta-tester run-script phpcs-pre-commit"
],
"!(*min).js": [
"eslint --fix"
]
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

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