Merge remote-tracking branch 'upstream/trunk'
28
.distignore
|
@ -1,28 +0,0 @@
|
||||||
.*
|
|
||||||
.*/
|
|
||||||
*.lock
|
|
||||||
*.md
|
|
||||||
*.zip
|
|
||||||
/bin/
|
|
||||||
/build/
|
|
||||||
/node_modules/
|
|
||||||
/tests/
|
|
||||||
babel.config.js
|
|
||||||
changelog.txt
|
|
||||||
composer.*
|
|
||||||
tsconfig.*
|
|
||||||
contributors.html
|
|
||||||
docker-compose.yaml
|
|
||||||
Dockerfile
|
|
||||||
Gruntfile.js
|
|
||||||
lerna.json
|
|
||||||
none
|
|
||||||
package-lock.json
|
|
||||||
package.json
|
|
||||||
packages/woocommerce-admin/docs
|
|
||||||
phpcs.xml
|
|
||||||
phpunit.xml
|
|
||||||
phpunit.xml.dist
|
|
||||||
README.md
|
|
||||||
renovate.json
|
|
||||||
webpack.config.js
|
|
|
@ -22,3 +22,6 @@ trim_trailing_whitespace = false
|
||||||
trim_trailing_whitespace = false
|
trim_trailing_whitespace = false
|
||||||
indent_style = space
|
indent_style = space
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
|
|
||||||
|
[*.json]
|
||||||
|
indent_style = tab
|
||||||
|
|
|
@ -1,21 +1 @@
|
||||||
*.min.js
|
node_modules
|
||||||
|
|
||||||
/assets/js/accounting/**
|
|
||||||
/assets/js/flexslider/**
|
|
||||||
/assets/js/jquery-blockui/**
|
|
||||||
/assets/js/jquery-cookie/**
|
|
||||||
/assets/js/jquery-flot/**
|
|
||||||
/assets/js/jquery-payment/**
|
|
||||||
/assets/js/jquery-qrcode/**
|
|
||||||
/assets/js/jquery-serializejson/**
|
|
||||||
/assets/js/jquery-tiptip/**
|
|
||||||
/assets/js/jquery-ui-touch-punch/**
|
|
||||||
/assets/js/js-cookie/**
|
|
||||||
/assets/js/photoswipe/**
|
|
||||||
/assets/js/prettyPhoto/**
|
|
||||||
/assets/js/round/**
|
|
||||||
/assets/js/select2/**
|
|
||||||
/assets/js/selectWoo/**
|
|
||||||
/assets/js/stupidtable/**
|
|
||||||
/assets/js/zeroclipboard/**
|
|
||||||
/assets/js/zoom/**
|
|
35
.eslintrc.js
|
@ -1,33 +1,4 @@
|
||||||
/** @format */
|
module.exports = {
|
||||||
|
|
||||||
const { useE2EEsLintConfig } = require( './tests/e2e/env/config/use-config' );
|
|
||||||
|
|
||||||
module.exports = useE2EEsLintConfig( {
|
|
||||||
root: true,
|
root: true,
|
||||||
env: {
|
extends: [ 'plugin:@woocommerce/eslint-plugin/recommended' ],
|
||||||
browser: true,
|
};
|
||||||
es6: true,
|
|
||||||
node: true
|
|
||||||
},
|
|
||||||
globals: {
|
|
||||||
wp: true,
|
|
||||||
wpApiSettings: true,
|
|
||||||
wcSettings: true,
|
|
||||||
es6: true
|
|
||||||
},
|
|
||||||
rules: {
|
|
||||||
camelcase: 0,
|
|
||||||
indent: 0,
|
|
||||||
'max-len': [ 2, { 'code': 140 } ],
|
|
||||||
'no-console': 1
|
|
||||||
},
|
|
||||||
parser: 'babel-eslint',
|
|
||||||
parserOptions: {
|
|
||||||
ecmaVersion: 8,
|
|
||||||
ecmaFeatures: {
|
|
||||||
modules: true,
|
|
||||||
experimentalObjectRestSpread: true,
|
|
||||||
jsx: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
} );
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ There are many ways to contribute to the project!
|
||||||
|
|
||||||
If you wish to contribute code, please read the information in the sections below. Then [fork](https://help.github.com/articles/fork-a-repo/) WooCommerce, commit your changes, and [submit a pull request](https://help.github.com/articles/using-pull-requests/) 🎉
|
If you wish to contribute code, please read the information in the sections below. Then [fork](https://help.github.com/articles/fork-a-repo/) WooCommerce, commit your changes, and [submit a pull request](https://help.github.com/articles/using-pull-requests/) 🎉
|
||||||
|
|
||||||
We use the `good first issue` label to mark issues that are suitable for new contributors. You can find all the issues with this label [here](https://github.com/woocommerce/woocommerce/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22).
|
We use the `good first issue` label to mark issues that are suitable for new contributors. You can find all the issues with this label [here](https://github.com/woocommerce/woocommerce/issues?q=is%3Aopen+is%3Aissue+label%3A%22type%3A+good+first+issue%22).
|
||||||
|
|
||||||
WooCommerce is licensed under the GPLv3+, and all contributions to the project will be released under the same license. You maintain copyright over any contribution you make, and by submitting a pull request, you are agreeing to release that contribution under the GPLv3+ license.
|
WooCommerce is licensed under the GPLv3+, and all contributions to the project will be released under the same license. You maintain copyright over any contribution you make, and by submitting a pull request, you are agreeing to release that contribution under the GPLv3+ license.
|
||||||
|
|
||||||
|
@ -26,8 +26,8 @@ If you have questions about the process to contribute code or want to discuss de
|
||||||
- [Minification of SCSS and JS](https://github.com/woocommerce/woocommerce/wiki/Minification-of-SCSS-and-JS)
|
- [Minification of SCSS and JS](https://github.com/woocommerce/woocommerce/wiki/Minification-of-SCSS-and-JS)
|
||||||
- [Naming conventions](https://github.com/woocommerce/woocommerce/wiki/Naming-conventions)
|
- [Naming conventions](https://github.com/woocommerce/woocommerce/wiki/Naming-conventions)
|
||||||
- [String localisation guidelines](https://github.com/woocommerce/woocommerce/wiki/String-localisation-guidelines)
|
- [String localisation guidelines](https://github.com/woocommerce/woocommerce/wiki/String-localisation-guidelines)
|
||||||
- [Running unit tests](https://github.com/woocommerce/woocommerce/blob/master/tests/README.md)
|
- [Running unit tests](https://github.com/woocommerce/woocommerce/blob/trunk/plugins/woocommerce/tests/README.md)
|
||||||
- [Running e2e tests](https://github.com/woocommerce/woocommerce/wiki/End-to-end-Testing)
|
- [Running e2e tests](https://github.com/woocommerce/woocommerce/blob/trunk/plugins/woocommerce/tests/e2e/README.md)
|
||||||
|
|
||||||
## Coding Guidelines and Development 🛠
|
## Coding Guidelines and Development 🛠
|
||||||
|
|
||||||
|
@ -37,19 +37,18 @@ If you have questions about the process to contribute code or want to discuss de
|
||||||
- Ensure you use LF line endings in your code editor. Use [EditorConfig](http://editorconfig.org/) if your editor supports it so that indentation, line endings and other settings are auto configured.
|
- Ensure you use LF line endings in your code editor. Use [EditorConfig](http://editorconfig.org/) if your editor supports it so that indentation, line endings and other settings are auto configured.
|
||||||
- When committing, reference your issue number (#1234) and include a note about the fix.
|
- When committing, reference your issue number (#1234) and include a note about the fix.
|
||||||
- Ensure that your code supports the minimum supported versions of PHP and WordPress; this is shown at the top of the `readme.txt` file.
|
- Ensure that your code supports the minimum supported versions of PHP and WordPress; this is shown at the top of the `readme.txt` file.
|
||||||
- Push the changes to your fork and submit a pull request on the master branch of the WooCommerce repository.
|
- Push the changes to your fork and submit a pull request on the trunk branch of the WooCommerce repository.
|
||||||
- Make sure to write good and detailed commit messages (see [this post](https://chris.beams.io/posts/git-commit/) for more on this) and follow all the applicable sections of the pull request template.
|
- Make sure to write good and detailed commit messages (see [this post](https://chris.beams.io/posts/git-commit/) for more on this) and follow all the applicable sections of the pull request template.
|
||||||
- Please avoid modifying the changelog directly or updating the .pot files. These will be updated by the WooCommerce team.
|
- Please avoid modifying the changelog directly or updating the .pot files. These will be updated by the WooCommerce team.
|
||||||
|
|
||||||
If you are contributing code to the (Javascript-driven) WooCommerce Admin project or to Gutenberg blocks, note that these are developed in external packages.
|
If you are contributing code to the (Javascript-driven) Gutenberg blocks, note that it's developed in an external package.
|
||||||
|
|
||||||
- [WooCommerce Admin](https://github.com/woocommerce/woocommerce-admin)
|
|
||||||
- [Blocks](https://github.com/woocommerce/woocommerce-gutenberg-products-block)
|
- [Blocks](https://github.com/woocommerce/woocommerce-gutenberg-products-block)
|
||||||
|
|
||||||
## Feature Requests 🚀
|
## Feature Requests 🚀
|
||||||
|
|
||||||
Feature requests can be [submitted to our issue tracker](https://github.com/woocommerce/woocommerce/issues/new?template=6-Feature-request.md). Be sure to include a description of the expected behavior and use case, and before submitting a request, please search for similar ones in the closed issues.
|
Feature requests can be [submitted to our issue tracker](https://github.com/woocommerce/woocommerce/issues/new?assignees=&labels=type%3A+enhancement%2Cstatus%3A+awaiting+triage&template=2-enhancement.yml&title=%5BEnhancement%5D%3A+). Be sure to include a description of the expected behavior and use case, and before submitting a request, please search for similar ones in the closed issues.
|
||||||
|
|
||||||
Feature request issues will remain closed until we see sufficient interest via comments and [👍 reactions](https://help.github.com/articles/about-discussions-in-issues-and-pull-requests/) from the community.
|
Feature request issues will remain closed until we see sufficient interest via comments and [👍 reactions](https://help.github.com/articles/about-discussions-in-issues-and-pull-requests/) from the community.
|
||||||
|
|
||||||
You can see a [list of current feature requests which require votes here](https://github.com/woocommerce/woocommerce/issues?q=is%3Aclosed+label%3A%22type%3A+enhancement%22+label%3A%22votes+needed%22+sort%3Areactions-%2B1-desc).
|
You can see a [list of current feature requests which require votes here](https://github.com/woocommerce/woocommerce/issues?q=is%3Aissue+sort%3Areactions-%2B1-desc+label%3A%22needs%3A+votes%22+).
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
---
|
|
||||||
name: "\U0001F512 Security issue"
|
|
||||||
about: Please report security issues *only* via https://www.hackerone.com
|
|
||||||
title: ''
|
|
||||||
labels: ''
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
For security reasons, please report all security issues via https://hackerone.com/automattic/. Also, if the issue is valid, a bug bounty will be paid out to you.
|
|
||||||
|
|
||||||
Please disclose responsibly and not via GitHub (which allows for exploiting issues in the wild before the patch is released).
|
|
|
@ -0,0 +1,95 @@
|
||||||
|
name: 🐞 Bug Report
|
||||||
|
description: Report a bug if something isn't working as expected in WooCommerce Core.
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
### Thanks for contributing!
|
||||||
|
|
||||||
|
Please provide us with the information requested in this bug report.
|
||||||
|
Without these details, we won't be able to fully evaluate this issue.
|
||||||
|
Bug reports lacking detail, or for any other reason than to report a bug, may be closed without action.
|
||||||
|
|
||||||
|
While our goal is to address all the issues reported in this repository, GitHub should be treated as a place to report confirmed bugs only.
|
||||||
|
- If you have a support request or custom code related question please follow one of the steps below:
|
||||||
|
- Review [WooCommerce Self-Service Guide](https://woocommerce.com/document/woocommerce-self-service-guide/) to see if the solutions listed there apply to your case;
|
||||||
|
- If you are a paying customer of WooCommerce, contact WooCommerce support by [opening a ticket or starting a live chat](https://woocommerce.com/contact-us/);
|
||||||
|
- Make a post on [WooCommerce community forum](https://wordpress.org/support/plugin/woocommerce/)
|
||||||
|
- To get help on custom code questions go to the [WooCommerce Community Slack](https://woocommerce.com/community-slack/) and visit the `#developers` channel.
|
||||||
|
|
||||||
|
Make sure to look through the [existing `type: bug` issues](https://github.com/woocommerce/woocommerce/issues?q=is%3Aopen+is%3Aissue+label%3A%22type%3A+bug%22) to see whether your bug has already been submitted.
|
||||||
|
Feel free to contribute to any existing issues.
|
||||||
|
Search tip: You can filter our issues using [our labels](https://github.com/woocommerce/woocommerce/labels).
|
||||||
|
Search tip: Make use of [GitHub's search syntax to refine your search](https://help.github.com/en/github/searching-for-information-on-github/searching-issues-and-pull-requests).
|
||||||
|
- type: checkboxes
|
||||||
|
id: prerequisites
|
||||||
|
attributes:
|
||||||
|
label: Prerequisites
|
||||||
|
description: Please confirm these before submitting the issue.
|
||||||
|
options:
|
||||||
|
- label: I have carried out troubleshooting steps and I believe I have found a bug.
|
||||||
|
- label: I have searched for similar bugs in both open and closed issues and cannot find a duplicate.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: summary
|
||||||
|
attributes:
|
||||||
|
label: Describe the bug
|
||||||
|
description: A clear and concise description of what the bug is.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: expected
|
||||||
|
attributes:
|
||||||
|
label: Expected behavior
|
||||||
|
placeholder: |
|
||||||
|
A clear and concise description of what you expected to happen.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: actual
|
||||||
|
attributes:
|
||||||
|
label: Actual behavior
|
||||||
|
placeholder: |
|
||||||
|
A clear and concise description of what actually happens. Please be as descriptive as possible;
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: steps
|
||||||
|
attributes:
|
||||||
|
label: Steps to reproduce
|
||||||
|
description: Attach screenshot(s) or recording(s) directly by dragging & dropping.
|
||||||
|
placeholder: |
|
||||||
|
1. Go to
|
||||||
|
2. Click on
|
||||||
|
3. Scroll down to
|
||||||
|
4. See error
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: environment
|
||||||
|
attributes:
|
||||||
|
label: WordPress Environment
|
||||||
|
description: |
|
||||||
|
We use the [WooCommerce System Status Report](https://woocommerce.com/document/understanding-the-woocommerce-system-status-report/) to help us evaluate the issue.
|
||||||
|
Without this report we won't be able to fully evaluate this issue.
|
||||||
|
placeholder: |
|
||||||
|
The System Status Report is found in your WordPress admin under **WooCommerce > Status**.
|
||||||
|
Please select “Get system report”, then “Copy for support”, and then paste it here.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: checkboxes
|
||||||
|
id: isolating
|
||||||
|
attributes:
|
||||||
|
label: Isolating the problem
|
||||||
|
description: |
|
||||||
|
Please try testing your site for theme and plugins conflict.
|
||||||
|
To do that deactivate all plugins except for WooCommerce and switch to a default WordPress theme or [Storefront](https://en-gb.wordpress.org/themes/storefront/). Then test again.
|
||||||
|
If the issue is resolved with the default theme and all plugins deactivated, it means that one of your plugins or a theme is causing the issue.
|
||||||
|
You will then need to enable it one by one and test every time you do that in order to figure out which plugin is causing the issue.
|
||||||
|
options:
|
||||||
|
- label: I have deactivated other plugins and confirmed this bug occurs when only WooCommerce plugin is active.
|
||||||
|
- label: This bug happens with a default WordPress theme active, or [Storefront](https://woocommerce.com/storefront/).
|
||||||
|
- label: I can reproduce this bug consistently using the steps above.
|
||||||
|
validations:
|
||||||
|
required: true
|
|
@ -1,20 +0,0 @@
|
||||||
---
|
|
||||||
name: "\U0001F47D External issues"
|
|
||||||
about: Please report WooCommerce Admin, WooCommerce Gutenberg Products Blocks or Action Scheduler issues directly to their respective repositories.
|
|
||||||
title: ''
|
|
||||||
labels: ''
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
Please report issues for the following features directly to their respective repositories.
|
|
||||||
|
|
||||||
WooCommerce Admin: https://github.com/woocommerce/woocommerce-admin
|
|
||||||
|
|
||||||
WooCommerce Gutenberg Products Blocks: https://github.com/woocommerce/woocommerce-gutenberg-products-block
|
|
||||||
|
|
||||||
Action Scheduler: https://github.com/woocommerce/action-scheduler
|
|
||||||
|
|
||||||
WooCommerce REST API Docs: https://github.com/woocommerce/woocommerce-rest-api-docs
|
|
||||||
|
|
||||||
WooCommerce Code Reference: https://github.com/woocommerce/code-reference
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
name: ✨ Enhancement Request
|
||||||
|
description: If you have an idea to improve an existing feature in core or need something for development (such as a new hook) please let us know or submit a Pull Request!
|
||||||
|
title: "[Enhancement]: "
|
||||||
|
labels: ["type: enhancement", "status: awaiting triage"]
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
### Thanks for contributing!
|
||||||
|
|
||||||
|
Please provide us with the information requested in this form.
|
||||||
|
|
||||||
|
Make sure to look through [existing `type: enhancement` issues](https://github.com/woocommerce/woocommerce/issues?q=is%3Aopen+is%3Aissue+label%3A%22type%3A+enhancement%22) and [existing `votes needed` issues](https://github.com/woocommerce/woocommerce/issues?q=is%3Aissue+sort%3Areactions-%2B1-desc+label%3A%22needs%3A+votes%22+) to see whether your idea is already being discussed.
|
||||||
|
Feel free to contribute to any existing issues.
|
||||||
|
Search tip: You can filter our issues using [our enhancement label](https://github.com/woocommerce/woocommerce/issues?q=is%3Aissue+label%3A%22type%3A+enhancement%22+).
|
||||||
|
Search tip: Make use of [GitHub's search syntax to refine your search](https://help.github.com/en/github/searching-for-information-on-github/searching-issues-and-pull-requests).
|
||||||
|
- type: textarea
|
||||||
|
id: summary
|
||||||
|
attributes:
|
||||||
|
label: Describe the solution you'd like
|
||||||
|
description: A clear and concise description of what you want to happen.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: alternative
|
||||||
|
attributes:
|
||||||
|
label: Describe alternatives you've considered
|
||||||
|
description: A clear and concise description of any alternative solutions or features you've considered.
|
||||||
|
- type: textarea
|
||||||
|
id: context
|
||||||
|
attributes:
|
||||||
|
label: Additional context
|
||||||
|
description: Add any other context or screenshots about the feature request here.
|
|
@ -1,28 +0,0 @@
|
||||||
---
|
|
||||||
name: "❓ Support Question"
|
|
||||||
about: "If you have a question \U0001F4AC please see our docs or use our forums, helpdesk,
|
|
||||||
or Slack Community!"
|
|
||||||
title: ''
|
|
||||||
labels: ''
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
We don't offer technical support on GitHub so we recommend using the following:
|
|
||||||
|
|
||||||
**Reading our documentation**
|
|
||||||
Usage docs can be found here: https://docs.woocommerce.com/
|
|
||||||
|
|
||||||
If you have a problem, you may want to start with the self help guide here: https://docs.woocommerce.com/document/woocommerce-self-service-guide/
|
|
||||||
|
|
||||||
**Technical support for premium extensions or if you're a WooCommerce.com customer**
|
|
||||||
Contact WooCommerce support by opening a ticket.
|
|
||||||
https://woocommerce.com/contact-us/
|
|
||||||
|
|
||||||
**For help with custom code**
|
|
||||||
WooCommerce Slack Community: https://woocommerce.com/community-slack/ in the `#developers` channel.
|
|
||||||
|
|
||||||
**General usage and development questions**
|
|
||||||
- WooCommerce Slack Community: https://woocommerce.com/community-slack/
|
|
||||||
- WordPress.org Forums: https://wordpress.org/support/plugin/woocommerce
|
|
||||||
- The Official WooCommerce Facebook Group https://www.facebook.com/groups/advanced.woocommerce/
|
|
|
@ -1,58 +0,0 @@
|
||||||
---
|
|
||||||
name: "\U0001F41E Bug report"
|
|
||||||
about: Report a bug if something isn't working as expected in the core WooCommerce
|
|
||||||
plugin.
|
|
||||||
title: ''
|
|
||||||
labels: ''
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
Please provide us with the information requested in this bug report. Without these details, we won't be able to fully evaluate this issue.
|
|
||||||
Bug reports lacking detail, or for any other reason than to report a bug, may be closed without action.
|
|
||||||
|
|
||||||
<!-- This template is for confirmed bugs only. If you have a support request or custom code related question please see our docs or use our forums, helpdesk, or Slack Community! https://github.com/woocommerce/woocommerce/issues/new?assignees=&labels=&template=3-Support.md&title= -->
|
|
||||||
|
|
||||||
<!-- Make sure to look through the existing issues to see whether your bug has already been submitted. Feel free to contribute to any existing issues. -->
|
|
||||||
<!-- Search tip: You can filter our issues using our component labels https://github.com/woocommerce/woocommerce/labels?q=component -->
|
|
||||||
<!-- Search tip: Make use of GitHub's search syntax to refine your search https://help.github.com/en/github/searching-for-information-on-github/searching-issues-and-pull-requests -->
|
|
||||||
|
|
||||||
**Prerequisites (mark completed items with an [x]):**
|
|
||||||
- [ ] I have have carried out troubleshooting steps and I believe I have found a bug.
|
|
||||||
- [ ] I have searched for similar bugs in both open and closed issues and cannot find a duplicate.
|
|
||||||
|
|
||||||
**Describe the bug**
|
|
||||||
A clear and concise description of what the bug is.
|
|
||||||
|
|
||||||
**Expected behavior**
|
|
||||||
A clear and concise description of what you expected to happen.
|
|
||||||
|
|
||||||
**Actual behavior**
|
|
||||||
A clear and concise description of what actually happens. Please be as descriptive as possible;
|
|
||||||
|
|
||||||
**Steps to reproduce the bug (We need to be able to reproduce the bug in order to fix it.)**
|
|
||||||
Steps to reproduce the bug:
|
|
||||||
1. Go to '...'
|
|
||||||
2. Click on '....'
|
|
||||||
3. Scroll down to '....'
|
|
||||||
4. See error
|
|
||||||
|
|
||||||
**Screenshots**
|
|
||||||
If applicable, add screenshots to help explain your problem.
|
|
||||||
|
|
||||||
<!-- Please try testing your site for theme and plugins conflict. To do that deactivate all plugins except for WooCommerce and switch to a default WordPress theme or [Storefront](https://en-gb.wordpress.org/themes/storefront/). Then test again. If the issue is resolved with the default theme and all plugins deactivated, it means that one of your plugins or a theme is causing the issue. You will then need to enable it one by one and test every time you do that in order to figure out which plugin is causing the issue. -->
|
|
||||||
|
|
||||||
**Isolating the problem (mark completed items with an [x]):**
|
|
||||||
- [ ] I have deactivated other plugins and confirmed this bug occurs when only WooCommerce plugin is active.
|
|
||||||
- [ ] This bug happens with a default WordPress theme active, or [Storefront](https://woocommerce.com/storefront/).
|
|
||||||
- [ ] I can reproduce this bug consistently using the steps above.
|
|
||||||
|
|
||||||
**WordPress Environment**
|
|
||||||
We use the [WooCommerce System Status Report](https://docs.woocommerce.com/document/understanding-the-woocommerce-system-status-report/) to help us evaluate the issue.
|
|
||||||
Without this report we won't be able to fully evaluate this issue.
|
|
||||||
<details>
|
|
||||||
```
|
|
||||||
The System Status Report is found in your WordPress admin under **WooCommerce > Status**.
|
|
||||||
Please select “Get system report”, then “Copy for support”, and then paste it here.
|
|
||||||
```
|
|
||||||
</details>
|
|
|
@ -1,25 +0,0 @@
|
||||||
---
|
|
||||||
name: "✨ New Enhancement"
|
|
||||||
about: If you have an idea to improve an existing feature in core or need something
|
|
||||||
for development (such as a new hook) please let us know or submit a Pull Request!
|
|
||||||
title: ''
|
|
||||||
labels: ''
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
<!-- Make sure to look through existing issues to see whether your idea is already being discussed. Feel free to contribute to any existing issues. -->
|
|
||||||
|
|
||||||
<!-- Search tip: You can filter issues using our enhancement label https://github.com/woocommerce/woocommerce/issues?q=is%3Aissue+label%3Aenhancement -->
|
|
||||||
|
|
||||||
**Is your feature request related to a problem? Please describe.**
|
|
||||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
|
||||||
|
|
||||||
**Describe the solution you'd like**
|
|
||||||
A clear and concise description of what you want to happen.
|
|
||||||
|
|
||||||
**Describe alternatives you've considered**
|
|
||||||
A clear and concise description of any alternative solutions or features you've considered.
|
|
||||||
|
|
||||||
**Additional context**
|
|
||||||
Add any other context or screenshots about the feature request here.
|
|
|
@ -1,25 +0,0 @@
|
||||||
---
|
|
||||||
name: "\U0001F680 Feature request"
|
|
||||||
about: "Suggest a new feature \U0001F389 We'll consider building it if it receives
|
|
||||||
sufficient interest! \U0001F44D"
|
|
||||||
title: ''
|
|
||||||
labels: ''
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
<!-- Make sure to look through existing issues to see whether your idea is already being discussed. Feel free to contribute to any existing issues. -->
|
|
||||||
|
|
||||||
<!-- Search tip: You can filter issues using our enhancement label https://github.com/woocommerce/woocommerce/issues?q=is%3Aissue+label%3Aenhancement -->
|
|
||||||
|
|
||||||
**Is your feature request related to a problem? Please describe.**
|
|
||||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
|
||||||
|
|
||||||
**Describe the solution you'd like**
|
|
||||||
A clear and concise description of what you want to happen.
|
|
||||||
|
|
||||||
**Describe alternatives you've considered**
|
|
||||||
A clear and concise description of any alternative solutions or features you've considered.
|
|
||||||
|
|
||||||
**Additional context**
|
|
||||||
Add any other context or screenshots about the feature request here.
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
blank_issues_enabled: true
|
||||||
|
contact_links:
|
||||||
|
- name: 🔒 Security issue
|
||||||
|
url: https://hackerone.com/automattic/
|
||||||
|
about: For security reasons, please report all security issues via HackerOne. If the issue is valid, a bug bounty will be paid out to you. Please disclose responsibly and not via GitHub (which allows for exploiting issues in the wild before the patch is released).
|
||||||
|
- name: ❓ Support Question
|
||||||
|
url: https://woocommerce.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.
|
|
@ -1,6 +1,6 @@
|
||||||
### All Submissions:
|
### All Submissions:
|
||||||
|
|
||||||
* [ ] Have you followed the [WooCommerce Contributing guideline](https://github.com/woocommerce/woocommerce/blob/master/.github/CONTRIBUTING.md)?
|
* [ ] Have you followed the [WooCommerce Contributing guideline](https://github.com/woocommerce/woocommerce/blob/trunk/.github/CONTRIBUTING.md)?
|
||||||
* [ ] Does your code follow the [WordPress' coding standards](https://make.wordpress.org/core/handbook/best-practices/coding-standards/)?
|
* [ ] Does your code follow the [WordPress' coding standards](https://make.wordpress.org/core/handbook/best-practices/coding-standards/)?
|
||||||
* [ ] Have you checked to ensure there aren't other open [Pull Requests](../../pulls) for the same update/change?
|
* [ ] Have you checked to ensure there aren't other open [Pull Requests](../../pulls) for the same update/change?
|
||||||
|
|
||||||
|
@ -25,9 +25,10 @@ Closes # .
|
||||||
* [ ] Have you added an explanation of what your changes do and why you'd like us to include them?
|
* [ ] 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 written new tests for your changes, as applicable?
|
||||||
* [ ] Have you successfully run tests with your changes locally?
|
* [ ] 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] -->
|
<!-- Mark completed items with an [x] -->
|
||||||
|
|
||||||
### Changelog entry
|
### FOR PR REVIEWER ONLY:
|
||||||
|
|
||||||
> Enter a summary of all changes on this Pull Request. This will appear in the changelog if accepted.
|
* [ ] 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.
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
'package: @woocommerce/api':
|
||||||
|
- packages/js/api/**/*
|
||||||
|
|
||||||
|
'package: @woocommerce/e2e-utils':
|
||||||
|
- packages/js/e2e-utils/**/*
|
||||||
|
|
||||||
|
'package: @woocommerce/e2e-environment':
|
||||||
|
- packages/js/e2e-environment/**/*
|
||||||
|
|
||||||
|
'package: @woocommerce/api-core-tests':
|
||||||
|
- packages/js/api-core-tests/**/*
|
||||||
|
|
||||||
|
'package: @woocommerce/e2e-core-tests':
|
||||||
|
- packages/js/e2e-core-tests/**/*
|
||||||
|
|
||||||
|
'package: @woocommerce/admin-e2e-tests':
|
||||||
|
- packages/js/admin-e2e-tests/**/*
|
||||||
|
|
||||||
|
'package: @woocommerce/components':
|
||||||
|
- packages/js/components/**/*
|
||||||
|
|
||||||
|
'package: @woocommerce/csv-export':
|
||||||
|
- packages/js/csv-export/**/*
|
||||||
|
|
||||||
|
'package: @woocommerce/currency':
|
||||||
|
- packages/js/currency/**/*
|
||||||
|
|
||||||
|
'package: @woocommerce/customer-effort-score':
|
||||||
|
- packages/js/customer-effort-score/**/*
|
||||||
|
|
||||||
|
'package: @woocommerce/data':
|
||||||
|
- packages/js/data/**/*
|
||||||
|
|
||||||
|
'package: @woocommerce/date':
|
||||||
|
- packages/js/date/**/*
|
||||||
|
|
||||||
|
'package: dependency-extraction-webpack-plugin':
|
||||||
|
- packages/js/dependency-extraction-webpack-plugin/**/*
|
||||||
|
|
||||||
|
'package: @woocommerce/eslint-plugin':
|
||||||
|
- packages/js/eslint-plugin/**/*
|
||||||
|
|
||||||
|
'package: @woocommerce/experimental':
|
||||||
|
- packages/js/experimental/**/*
|
||||||
|
|
||||||
|
'package: @woocommerce/explat':
|
||||||
|
- packages/js/explat/**/*
|
||||||
|
|
||||||
|
'package: @woocommerce/js-tests':
|
||||||
|
- packages/js/js-tests/**/*
|
||||||
|
|
||||||
|
'package: @woocommerce/navigation':
|
||||||
|
- packages/js/navigation/**/*
|
||||||
|
|
||||||
|
'package: @woocommerce/notices':
|
||||||
|
- packages/js/notices/**/*
|
||||||
|
|
||||||
|
'package: @woocommerce/number':
|
||||||
|
- packages/js/number/**/*
|
||||||
|
|
||||||
|
'package: @woocommerce/onboarding':
|
||||||
|
- packages/js/onboarding/**/*
|
||||||
|
|
||||||
|
'package: @woocommerce/style-build':
|
||||||
|
- packages/js/style-build/**/*
|
||||||
|
|
||||||
|
'package: @woocommerce/tracks':
|
||||||
|
- packages/js/tracks/**/*
|
||||||
|
|
||||||
|
'plugin: woocommerce':
|
||||||
|
- plugins/woocommerce/**/*
|
||||||
|
|
||||||
|
'focus: react admin':
|
||||||
|
- plugins/woocommerce/src/Admin/**/*
|
||||||
|
- plugins/woocommerce/src/Internal/Admin/**/*
|
||||||
|
- plugins/woocommerce-admin/**/*
|
|
@ -0,0 +1,30 @@
|
||||||
|
name: Build release zip file
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
ref:
|
||||||
|
description: 'By default the zip file is generated from the branch the workflow runs from, but you can specify an explicit reference to use instead here (e.g. refs/tags/tag_name or refs/heads/release/x.x). The resulting file will be available as an artifact on the workflow run.'
|
||||||
|
required: false
|
||||||
|
default: ''
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Build release zip file
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
ref: ${{ github.event.inputs.ref || github.ref }}
|
||||||
|
- name: Build the zip file
|
||||||
|
id: build
|
||||||
|
uses: woocommerce/action-build@trunk
|
||||||
|
- name: Unzip the file (prevents double zip problem)
|
||||||
|
run: unzip ${{ steps.build.outputs.zip_path }} -d zipfile
|
||||||
|
- name: Upload the zip file as an artifact
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
name: woocommerce
|
||||||
|
path: zipfile
|
||||||
|
retention-days: 7
|
|
@ -8,10 +8,10 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
- name: Build
|
- name: Build
|
||||||
id: build
|
id: build
|
||||||
uses: woocommerce/action-build@v2
|
uses: woocommerce/action-build@trunk
|
||||||
- name: Upload release asset
|
- name: Upload release asset
|
||||||
uses: actions/upload-release-asset@v1
|
uses: actions/upload-release-asset@v1
|
||||||
env:
|
env:
|
||||||
|
@ -21,3 +21,30 @@ jobs:
|
||||||
asset_path: ${{ steps.build.outputs.zip_path }}
|
asset_path: ${{ steps.build.outputs.zip_path }}
|
||||||
asset_name: woocommerce.zip
|
asset_name: woocommerce.zip
|
||||||
asset_content_type: application/zip
|
asset_content_type: application/zip
|
||||||
|
update-code-reference:
|
||||||
|
if: github.event.release.prerelease == false && github.event.release.draft == false && github.repository_owner == 'woocommerce'
|
||||||
|
name: Update Code Reference
|
||||||
|
needs: build
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Invoke Code Reference build and deploy workflow
|
||||||
|
uses: aurelien-baudet/workflow-dispatch@v2
|
||||||
|
with:
|
||||||
|
workflow: GitHub Pages deploy
|
||||||
|
repo: woocommerce/code-reference
|
||||||
|
token: ${{ secrets.CUSTOM_GH_TOKEN }}
|
||||||
|
ref: refs/heads/trunk
|
||||||
|
inputs: '{ "version": "${{ github.event.release.tag_name }}" }'
|
||||||
|
run-release-smoke-tests:
|
||||||
|
name: Execute Smoke test release
|
||||||
|
needs: build
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Invoke release smoke testing workflow
|
||||||
|
uses: aurelien-baudet/workflow-dispatch@v2
|
||||||
|
with:
|
||||||
|
workflow: Smoke test release
|
||||||
|
repo: ${{ github.repository }}
|
||||||
|
token: ${{ secrets.E2E_WORKFLOW_GH_TOKEN }}
|
||||||
|
ref: refs/heads/trunk
|
||||||
|
inputs: '{ "release_id": "${{ github.event.release.id }}" }'
|
||||||
|
|
|
@ -0,0 +1,97 @@
|
||||||
|
name: Run CI
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- trunk
|
||||||
|
- 'release/**'
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: bash
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
name: PHP ${{ matrix.php }} WP ${{ matrix.wp }}
|
||||||
|
timeout-minutes: 20
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
continue-on-error: ${{ matrix.wp == 'nightly' }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
php: [ '7.2', '7.3', '7.4', '8.0' ]
|
||||||
|
wp: [ 'latest' ]
|
||||||
|
include:
|
||||||
|
- wp: nightly
|
||||||
|
php: '7.4'
|
||||||
|
- wp: '5.8'
|
||||||
|
php: 7.2
|
||||||
|
- wp: '5.7'
|
||||||
|
php: 7.2
|
||||||
|
services:
|
||||||
|
database:
|
||||||
|
image: mysql:5.6
|
||||||
|
env:
|
||||||
|
MYSQL_ROOT_PASSWORD: root
|
||||||
|
ports:
|
||||||
|
- 3306:3306
|
||||||
|
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=5
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Setup PHP
|
||||||
|
uses: shivammathur/setup-php@v2
|
||||||
|
with:
|
||||||
|
php-version: ${{ matrix.php }}
|
||||||
|
tools: composer
|
||||||
|
extensions: mysql
|
||||||
|
coverage: none
|
||||||
|
|
||||||
|
- name: Tool versions
|
||||||
|
run: |
|
||||||
|
php --version
|
||||||
|
composer --version
|
||||||
|
|
||||||
|
- name: Get cached composer and pnpm directories
|
||||||
|
uses: actions/cache@v3
|
||||||
|
id: cache-deps
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.pnpm-store
|
||||||
|
plugins/woocommerce/packages
|
||||||
|
plugins/woocommerce/vendor
|
||||||
|
key: ${{ runner.os }}-npm-composer-${{ hashFiles('plugins/woocommerce/composer.lock', '**/pnpm-lock.yaml') }}
|
||||||
|
|
||||||
|
- name: Install PNPM
|
||||||
|
run: npm install -g pnpm
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install
|
||||||
|
|
||||||
|
- name: Install Composer dependencies
|
||||||
|
if: steps.cache-deps.outputs.cache-hit != 'true'
|
||||||
|
run: pnpm nx composer-install woocommerce
|
||||||
|
|
||||||
|
- name: Build Admin feature config
|
||||||
|
run: pnpm nx build:feature-config woocommerce
|
||||||
|
|
||||||
|
- name: Add PHP8 Compatibility.
|
||||||
|
run: |
|
||||||
|
if [ "$(php -r "echo version_compare(PHP_VERSION,'8.0','>=');")" ]; then
|
||||||
|
curl -L https://github.com/woocommerce/phpunit/archive/add-compatibility-with-php8-to-phpunit-7.zip -o /tmp/phpunit-7.5-fork.zip
|
||||||
|
unzip -d /tmp/phpunit-7.5-fork /tmp/phpunit-7.5-fork.zip
|
||||||
|
cd plugins/woocommerce
|
||||||
|
composer bin phpunit config --unset platform
|
||||||
|
composer bin phpunit config repositories.0 '{"type": "path", "url": "/tmp/phpunit-7.5-fork/phpunit-add-compatibility-with-php8-to-phpunit-7", "options": {"symlink": false}}'
|
||||||
|
composer bin phpunit require --dev -W phpunit/phpunit:@dev --ignore-platform-reqs
|
||||||
|
rm -rf ./vendor/phpunit/
|
||||||
|
pnpm nx composer-dump-autoload woocommerce
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Init DB and WP
|
||||||
|
working-directory: plugins/woocommerce
|
||||||
|
run: ./tests/bin/install.sh woo_test root root 127.0.0.1 ${{ matrix.wp }}
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: pnpm nx test-unit woocommerce
|
|
@ -0,0 +1,64 @@
|
||||||
|
name: Mirrors
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: ["trunk", "release/**"]
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
if: github.repository == 'woocommerce/woocommerce'
|
||||||
|
name: Build WooCommerce zip
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Build
|
||||||
|
id: build
|
||||||
|
uses: woocommerce/action-build@trunk
|
||||||
|
env:
|
||||||
|
BUILD_ENV: mirrors
|
||||||
|
- name: Upload PR zip
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
name: woocommerce
|
||||||
|
path: ${{ steps.build.outputs.zip_path }}
|
||||||
|
retention-days: 7
|
||||||
|
mirror:
|
||||||
|
if: github.repository == 'woocommerce/woocommerce'
|
||||||
|
name: Push to Mirror
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [build]
|
||||||
|
steps:
|
||||||
|
- name: Create directories
|
||||||
|
run: |
|
||||||
|
mkdir -p tmp/woocommerce-build
|
||||||
|
mkdir -p monorepo
|
||||||
|
- name: Checkout monorepo
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
path: monorepo
|
||||||
|
- name: Download WooCommerce ZIP
|
||||||
|
uses: actions/download-artifact@v2
|
||||||
|
with:
|
||||||
|
name: woocommerce
|
||||||
|
path: tmp/woocommerce-build
|
||||||
|
- name: Extract and replace WooCommerce zip.
|
||||||
|
working-directory: tmp/woocommerce-build
|
||||||
|
run: |
|
||||||
|
mkdir -p woocommerce/woocommerce-production
|
||||||
|
unzip woocommerce.zip -d woocommerce/woocommerce-production
|
||||||
|
mv woocommerce/woocommerce-production/woocommerce/* woocommerce/woocommerce-production
|
||||||
|
rm -rf woocommerce/woocommerce-production/woocommerce
|
||||||
|
- name: Set up mirror
|
||||||
|
working-directory: tmp/woocommerce-build
|
||||||
|
run: |
|
||||||
|
touch mirrors.txt
|
||||||
|
echo "woocommerce/woocommerce-production" >> mirrors.txt
|
||||||
|
- name: Push to mirror
|
||||||
|
uses: Automattic/action-push-to-mirrors@v1
|
||||||
|
with:
|
||||||
|
source-directory: ${{ github.workspace }}/monorepo
|
||||||
|
token: ${{ secrets.API_TOKEN_GITHUB }}
|
||||||
|
username: matticbot
|
||||||
|
working-directory: ${{ github.workspace }}/tmp/woocommerce-build
|
||||||
|
timeout-minutes: 5 # 2021-01-18: Successful runs seem to take about half a minute.
|
|
@ -4,20 +4,21 @@ on:
|
||||||
- cron: '0 0 * * *' # Run at 12 AM UTC.
|
- cron: '0 0 * * *' # Run at 12 AM UTC.
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
|
if: github.repository_owner == 'woocommerce'
|
||||||
name: Nightly builds
|
name: Nightly builds
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
build: [master]
|
build: [trunk]
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
ref: ${{ matrix.build }}
|
ref: ${{ matrix.build }}
|
||||||
- name: Build
|
- name: Build
|
||||||
id: build
|
id: build
|
||||||
uses: woocommerce/action-build@v2
|
uses: woocommerce/action-build@trunk
|
||||||
- name: Deploy nightly build
|
- name: Deploy nightly build
|
||||||
uses: WebFreak001/deploy-nightly@v1.1.0
|
uses: WebFreak001/deploy-nightly@v1.1.0
|
||||||
env:
|
env:
|
||||||
|
|
|
@ -1,122 +1,222 @@
|
||||||
name: Build zip for PR
|
name: Build zip for PR
|
||||||
on:
|
on: pull_request
|
||||||
pull_request
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
name: Build zip for PR
|
name: Build zip for PR
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
id: build
|
id: build
|
||||||
uses: woocommerce/action-build@v2
|
uses: woocommerce/action-build@trunk
|
||||||
|
env:
|
||||||
|
BUILD_ENV: e2e
|
||||||
|
|
||||||
- name: Upload PR zip
|
- name: Upload PR zip
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v3
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
name: woocommerce
|
name: woocommerce
|
||||||
path: ${{ steps.build.outputs.zip_path }}
|
path: ${{ steps.build.outputs.zip_path }}
|
||||||
retention-days: 7
|
retention-days: 7
|
||||||
|
|
||||||
- name: Add comment
|
e2e-tests-run:
|
||||||
uses: actions/github-script@v3
|
name: Runs E2E tests.
|
||||||
if: github.repository_owner == 'woocommerce'
|
runs-on: ubuntu-18.04
|
||||||
with:
|
needs: [build]
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
steps:
|
||||||
script: |
|
- name: Create dirs.
|
||||||
github.issues.createComment({
|
run: |
|
||||||
issue_number: context.issue.number,
|
mkdir -p code/woocommerce
|
||||||
owner: context.repo.owner,
|
mkdir -p package/woocommerce
|
||||||
repo: context.repo.repo,
|
mkdir -p tmp/woocommerce
|
||||||
body: ':package: Artifacts ready for [download](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})!'
|
|
||||||
})
|
|
||||||
|
|
||||||
e2e-tests-cache:
|
- name: Checkout code.
|
||||||
name: Set e2e caches for running tests
|
uses: actions/checkout@v3
|
||||||
runs-on: ubuntu-latest
|
with:
|
||||||
steps:
|
path: package/woocommerce
|
||||||
- name: Checkout code.
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
|
|
||||||
- name: Load Node.js.
|
- name: Move current directory to code. We will install zip file in this dir later.
|
||||||
uses: actions/setup-node@v2
|
run: mv ./package/woocommerce/plugins/woocommerce/* ./code/woocommerce
|
||||||
with:
|
|
||||||
node-version: '12'
|
|
||||||
|
|
||||||
# From https://docs.github.com/en/actions/guides/caching-dependencies-to-speed-up-workflows#using-the-cache-action
|
- name: Download WooCommerce ZIP.
|
||||||
- name: Cache node modules
|
uses: actions/download-artifact@v3
|
||||||
uses: actions/cache@v2
|
with:
|
||||||
id: cache_node_modules
|
name: woocommerce
|
||||||
env:
|
path: tmp
|
||||||
cache-name: cache-node-modules
|
|
||||||
with:
|
|
||||||
path: ./node_modules
|
|
||||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('package-lock.json') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-build-${{ env.cache-name }}-
|
|
||||||
|
|
||||||
- name: Run npm install, and cache if they aren't.
|
- name: Extract and replace WooCommerce zip.
|
||||||
run: npm install
|
working-directory: tmp
|
||||||
|
run: |
|
||||||
|
unzip woocommerce.zip -d woocommerce
|
||||||
|
mv woocommerce/woocommerce/* ../package/woocommerce/plugins/woocommerce/
|
||||||
|
|
||||||
e2e-tests-run:
|
- name: Cache modules
|
||||||
name: Runs E2E tests.
|
uses: actions/cache@v3
|
||||||
runs-on: ubuntu-latest
|
with:
|
||||||
needs: [ build, e2e-tests-cache ]
|
path: |
|
||||||
steps:
|
~/.pnpm-store
|
||||||
|
key: ${{ runner.os }}-npm-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||||
|
|
||||||
- name: Create dirs.
|
- name: Install PNPM
|
||||||
run: |
|
run: npm install -g pnpm
|
||||||
mkdir -p code/woocommerce
|
|
||||||
mkdir -p package/woocommerce
|
|
||||||
mkdir -p tmp/woocommerce
|
|
||||||
mkdir -p node_modules
|
|
||||||
|
|
||||||
- name: Checkout code.
|
- name: Install dependencies
|
||||||
uses: actions/checkout@v2
|
working-directory: package/woocommerce
|
||||||
with:
|
run: pnpm install
|
||||||
path: package/woocommerce
|
|
||||||
|
|
||||||
# From https://docs.github.com/en/actions/guides/caching-dependencies-to-speed-up-workflows#using-the-cache-action
|
- name: Load docker images and start containers.
|
||||||
- name: Cache node modules
|
working-directory: package/woocommerce/plugins/woocommerce
|
||||||
uses: actions/cache@v2
|
run: pnpm exec wc-e2e docker:up
|
||||||
id: cache_node_modules
|
|
||||||
env:
|
|
||||||
cache-name: cache-node-modules
|
|
||||||
with:
|
|
||||||
path: ./node_modules
|
|
||||||
key: ${{ runner.os }}-build-${{ hashFiles('package-lock.json') }}
|
|
||||||
restore-keys: ${{ runner.os }}-build-${{ env.cache-name }}-
|
|
||||||
|
|
||||||
- name: Restore node modules from cache, if available.
|
- name: Run tests command.
|
||||||
run: mv ./node_modules package/woocommerce/node_modules
|
working-directory: package/woocommerce/plugins/woocommerce
|
||||||
|
env:
|
||||||
|
WC_E2E_SCREENSHOTS: 1
|
||||||
|
E2E_SLACK_TOKEN: ${{ secrets.E2E_SLACK_TOKEN }}
|
||||||
|
E2E_SLACK_CHANNEL: ${{ secrets.E2E_SLACK_CHANNEL }}
|
||||||
|
run: pnpm exec wc-e2e test:e2e
|
||||||
|
|
||||||
- name: Run npm install.
|
- name: Archive E2E test screenshots
|
||||||
working-directory: package/woocommerce
|
uses: actions/upload-artifact@v3
|
||||||
run: npm install
|
if: always()
|
||||||
|
with:
|
||||||
|
name: E2E Screenshots
|
||||||
|
path: package/woocommerce/plugins/woocommerce/tests/e2e/screenshots
|
||||||
|
if-no-files-found: ignore
|
||||||
|
retention-days: 5
|
||||||
|
|
||||||
- name: Load docker images and start containers.
|
api-tests-run:
|
||||||
working-directory: package/woocommerce
|
name: Runs API tests.
|
||||||
run: npx wc-e2e docker:up
|
runs-on: ubuntu-18.04
|
||||||
|
needs: [build]
|
||||||
|
steps:
|
||||||
|
- name: Create dirs.
|
||||||
|
run: |
|
||||||
|
mkdir -p code/woocommerce
|
||||||
|
mkdir -p package/woocommerce
|
||||||
|
mkdir -p tmp/woocommerce
|
||||||
|
|
||||||
- name: Move current directory to code. We will install zip file in this dir later.
|
- name: Checkout code.
|
||||||
run: mv ./package/woocommerce/* ./code/woocommerce
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
path: package/woocommerce
|
||||||
|
|
||||||
- name: Download WooCommerce ZIP.
|
- name: Move current directory to code. We will install zip file in this dir later.
|
||||||
uses: actions/download-artifact@v2
|
run: mv ./package/woocommerce/plugins/woocommerce/* ./code/woocommerce
|
||||||
with:
|
|
||||||
name: woocommerce
|
|
||||||
path: tmp
|
|
||||||
|
|
||||||
- name: Extract and replace WooCommerce zip.
|
- name: Download WooCommerce ZIP.
|
||||||
working-directory: tmp
|
uses: actions/download-artifact@v3
|
||||||
run: |
|
with:
|
||||||
unzip woocommerce.zip -d woocommerce
|
name: woocommerce
|
||||||
mv woocommerce/woocommerce/* ../package/woocommerce/
|
path: tmp
|
||||||
|
|
||||||
- name: Run tests command.
|
- name: Extract and replace WooCommerce zip.
|
||||||
working-directory: code/woocommerce
|
working-directory: tmp
|
||||||
run: npx wc-e2e test:e2e
|
run: |
|
||||||
|
unzip woocommerce.zip -d woocommerce
|
||||||
|
mv woocommerce/woocommerce/* ../package/woocommerce/plugins/woocommerce/
|
||||||
|
|
||||||
|
- name: Cache modules
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.pnpm-store
|
||||||
|
key: ${{ runner.os }}-npm-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||||
|
|
||||||
|
- name: Install PNPM
|
||||||
|
run: npm install -g pnpm
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
working-directory: package/woocommerce
|
||||||
|
run: pnpm install
|
||||||
|
|
||||||
|
- name: Load docker images and start containers.
|
||||||
|
working-directory: package/woocommerce/plugins/woocommerce
|
||||||
|
run: pnpm exec wc-e2e docker:up
|
||||||
|
|
||||||
|
- name: Run tests command.
|
||||||
|
working-directory: package/woocommerce/plugins/woocommerce
|
||||||
|
env:
|
||||||
|
BASE_URL: http://localhost:8084
|
||||||
|
USER_KEY: admin
|
||||||
|
USER_SECRET: password
|
||||||
|
run: pnpm exec wc-api-tests test api
|
||||||
|
|
||||||
|
- name: Upload API test report
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: api-test-report---pr-${{ github.event.number }}
|
||||||
|
path: |
|
||||||
|
package/woocommerce/packages/js/api-core-tests/allure-results
|
||||||
|
package/woocommerce/packages/js/api-core-tests/allure-report
|
||||||
|
retention-days: 7
|
||||||
|
|
||||||
|
k6-tests-run:
|
||||||
|
name: Runs k6 Performance tests
|
||||||
|
runs-on: ubuntu-18.04
|
||||||
|
needs: [build]
|
||||||
|
steps:
|
||||||
|
- name: Create dirs.
|
||||||
|
run: |
|
||||||
|
mkdir -p code/woocommerce
|
||||||
|
mkdir -p package/woocommerce
|
||||||
|
mkdir -p tmp/woocommerce
|
||||||
|
|
||||||
|
- name: Checkout code.
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
path: package/woocommerce
|
||||||
|
|
||||||
|
- name: Move current directory to code. We will install zip file in this dir later.
|
||||||
|
run: mv ./package/woocommerce/plugins/woocommerce/* ./code/woocommerce
|
||||||
|
|
||||||
|
- name: Download WooCommerce ZIP.
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: woocommerce
|
||||||
|
path: tmp
|
||||||
|
|
||||||
|
- name: Extract and replace WooCommerce zip.
|
||||||
|
working-directory: tmp
|
||||||
|
run: |
|
||||||
|
unzip woocommerce.zip -d woocommerce
|
||||||
|
mv woocommerce/woocommerce/* ../package/woocommerce/plugins/woocommerce/
|
||||||
|
|
||||||
|
- name: Cache modules
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.pnpm-store
|
||||||
|
key: ${{ runner.os }}-npm-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||||
|
|
||||||
|
- name: Install PNPM
|
||||||
|
run: npm install -g pnpm
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
working-directory: package/woocommerce
|
||||||
|
run: pnpm install
|
||||||
|
|
||||||
|
- name: Workaround to use initialization file with prepopulated data.
|
||||||
|
working-directory: package/woocommerce/plugins/woocommerce/tests/e2e/docker
|
||||||
|
run: |
|
||||||
|
cp init-sample-products.sh initialize.sh
|
||||||
|
|
||||||
|
- name: Load docker images and start containers.
|
||||||
|
working-directory: package/woocommerce/plugins/woocommerce
|
||||||
|
run: pnpm exec wc-e2e docker:up
|
||||||
|
|
||||||
|
- name: Install k6
|
||||||
|
run: |
|
||||||
|
curl https://github.com/grafana/k6/releases/download/v0.33.0/k6-v0.33.0-linux-amd64.tar.gz -L | tar xvz --strip-components 1
|
||||||
|
|
||||||
|
- name: Run k6 tests
|
||||||
|
run: |
|
||||||
|
./k6 run package/woocommerce/plugins/woocommerce/tests/performance/tests/gh-action-pr-requests.js
|
||||||
|
|
|
@ -1,10 +1,16 @@
|
||||||
name: Run code coverage on PR
|
name: Run code coverage on PR
|
||||||
on:
|
on:
|
||||||
pull_request
|
pull_request
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: bash
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
name: Code coverage (PHP 7.4, WP Latest)
|
name: Code coverage (PHP 7.4, WP Latest)
|
||||||
timeout-minutes: 15
|
timeout-minutes: 20
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
services:
|
services:
|
||||||
database:
|
database:
|
||||||
|
@ -16,7 +22,9 @@ jobs:
|
||||||
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=5
|
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=5
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
fetch-depth: 100
|
||||||
|
|
||||||
- name: Setup PHP
|
- name: Setup PHP
|
||||||
uses: shivammathur/setup-php@v2
|
uses: shivammathur/setup-php@v2
|
||||||
|
@ -31,21 +39,38 @@ jobs:
|
||||||
php --version
|
php --version
|
||||||
composer --version
|
composer --version
|
||||||
|
|
||||||
- name: Get cached composer directories
|
- name: Get cached composer and pnpm directories
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
|
id: cache-deps
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
./packages
|
~/.pnpm-store
|
||||||
./vendor
|
plugins/woocommerce/packages
|
||||||
key: ${{ runner.os }}-${{ hashFiles('./composer.lock') }}
|
plugins/woocommerce/vendor
|
||||||
|
key: ${{ runner.os }}-npm-composer-${{ hashFiles('plugins/woocommerce/composer.lock', '**/pnpm-lock.yaml') }}
|
||||||
|
|
||||||
- name: Setup and install composer
|
- name: Install PNPM
|
||||||
run: composer install
|
run: npm install -g pnpm
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install
|
||||||
|
|
||||||
|
- name: Install Composer dependencies
|
||||||
|
if: steps.cache-deps.outputs.cache-hit != 'true'
|
||||||
|
run: pnpm nx composer-install woocommerce
|
||||||
|
|
||||||
|
- name: Build Admin feature config
|
||||||
|
run: |
|
||||||
|
pnpm nx build:feature-config woocommerce
|
||||||
|
|
||||||
- name: Init DB and WP
|
- name: Init DB and WP
|
||||||
run: ./tests/bin/install.sh woo_test root root 127.0.0.1 latest
|
run: pnpm nx install-unit-test-db woocommerce
|
||||||
|
|
||||||
- name: Run unit tests with code coverage. Allow to fail.
|
- name: Run unit tests with code coverage. Allow to fail.
|
||||||
run: |
|
run: |
|
||||||
RUN_CODE_COVERAGE=1 bash ./tests/bin/phpunit.sh
|
pnpm nx test-code-coverage woocommerce
|
||||||
exit 0
|
exit 0
|
||||||
|
|
||||||
|
- name: Send code coverage to Codecov.
|
||||||
|
run: |
|
||||||
|
bash <(curl -s https://codecov.io/bash)
|
||||||
|
|
|
@ -1,49 +1,59 @@
|
||||||
name: Run code sniff on PR
|
name: Run code sniff on PR
|
||||||
on:
|
on:
|
||||||
pull_request
|
pull_request
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: bash
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
name: Code sniff (PHP 7.4, WP Latest)
|
name: Code sniff (PHP 7.4, WP Latest)
|
||||||
timeout-minutes: 15
|
timeout-minutes: 15
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
services:
|
|
||||||
database:
|
|
||||||
image: mysql:5.6
|
|
||||||
env:
|
|
||||||
MYSQL_ROOT_PASSWORD: root
|
|
||||||
ports:
|
|
||||||
- 3306:3306
|
|
||||||
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=5
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
fetch-depth: 100
|
||||||
|
|
||||||
- name: Setup PHP
|
- name: Setup PHP
|
||||||
uses: shivammathur/setup-php@v2
|
uses: shivammathur/setup-php@v2
|
||||||
with:
|
with:
|
||||||
php-version: 7.4
|
php-version: 7.4
|
||||||
tools: composer
|
tools: composer, cs2pr
|
||||||
extensions: mysql
|
|
||||||
coverage: none
|
|
||||||
|
|
||||||
- name: Tool versions
|
- name: Tool versions
|
||||||
run: |
|
run: |
|
||||||
php --version
|
php --version
|
||||||
composer --version
|
composer --version
|
||||||
|
|
||||||
- name: Get cached composer directories
|
- name: Get cached composer and pnpm directories
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
|
id: cache-deps
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
./packages
|
~/.pnpm-store
|
||||||
./vendor
|
plugins/woocommerce/packages
|
||||||
key: ${{ runner.os }}-${{ hashFiles('./composer.lock') }}
|
plugins/woocommerce/vendor
|
||||||
|
key: ${{ runner.os }}-npm-composer-${{ hashFiles('plugins/woocommerce/composer.lock', '**/pnpm-lock.yaml') }}
|
||||||
|
|
||||||
- name: Setup and install composer
|
- name: Install PNPM
|
||||||
run: composer install
|
run: npm install -g pnpm
|
||||||
|
|
||||||
- name: Init DB and WP
|
- name: Install dependencies
|
||||||
run: ./tests/bin/install.sh woo_test root root 127.0.0.1 latest
|
run: pnpm install
|
||||||
|
|
||||||
|
- name: Install Composer dependencies
|
||||||
|
if: steps.cache-deps.outputs.cache-hit != 'true'
|
||||||
|
run: pnpm nx composer-install woocommerce
|
||||||
|
|
||||||
- name: Run code sniff
|
- name: Run code sniff
|
||||||
run: RUN_PHPCS=1 bash ./tests/bin/phpcs.sh
|
continue-on-error: true
|
||||||
|
working-directory: plugins/woocommerce
|
||||||
|
run: ./tests/bin/phpcs.sh "${{ github.event.pull_request.base.sha }}" "${{ github.event.after }}"
|
||||||
|
|
||||||
|
- name: Show PHPCS results in PR
|
||||||
|
working-directory: plugins/woocommerce
|
||||||
|
run: cs2pr ./phpcs-report.xml
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
name: Run lint checks potentially affecting projects across the monorepo
|
||||||
|
on: pull_request
|
||||||
|
concurrency:
|
||||||
|
group: changelogger-${{ github.event_name }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
jobs:
|
||||||
|
changelogger_used:
|
||||||
|
name: Changelogger use
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 5
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
ref: ${{ github.event.pull_request.head.sha }}
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Setup PHP
|
||||||
|
uses: shivammathur/setup-php@v2
|
||||||
|
with:
|
||||||
|
php-version: '7.4'
|
||||||
|
|
||||||
|
- name: Check change files are touched for touched projects
|
||||||
|
env:
|
||||||
|
BASE: ${{ github.event.pull_request.base.sha }}
|
||||||
|
HEAD: ${{ github.event.pull_request.head.sha }}
|
||||||
|
run: php tools/monorepo/check-changelogger-use.php --debug "$BASE" "$HEAD"
|
|
@ -0,0 +1,47 @@
|
||||||
|
name: Lint and tests for JS packages and woocommerce-admin/client
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- 'packages/js/**/**'
|
||||||
|
- 'plugins/woocommerce-admin/client/**'
|
||||||
|
- '!**.md'
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
lint-test-js:
|
||||||
|
name: Lint and Test JS
|
||||||
|
runs-on: ubuntu-18.04
|
||||||
|
steps:
|
||||||
|
- name: Check out repository code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- uses: actions/setup-node@v2
|
||||||
|
with:
|
||||||
|
node-version: '16'
|
||||||
|
|
||||||
|
- name: Cache modules
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.pnpm-store
|
||||||
|
key: ${{ runner.os }}-npm-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||||
|
|
||||||
|
- name: Install PNPM
|
||||||
|
run: npm install -g pnpm
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install
|
||||||
|
|
||||||
|
- name: Lint
|
||||||
|
run: |
|
||||||
|
pnpm nx lint woocommerce-admin
|
||||||
|
pnpm nx lint:js-packages woocommerce-admin
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
run: |
|
||||||
|
pnpm nx build woocommerce-admin
|
||||||
|
pnpm nx test woocommerce-admin
|
||||||
|
pnpm nx test:packages woocommerce-admin
|
|
@ -0,0 +1,18 @@
|
||||||
|
name: 'Label Pull Request Project'
|
||||||
|
on:
|
||||||
|
pull_request_target:
|
||||||
|
types:
|
||||||
|
- opened
|
||||||
|
- synchronize
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
label_project:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/labeler@v3
|
||||||
|
with:
|
||||||
|
repo-token: "${{ secrets.GITHUB_TOKEN }}"
|
||||||
|
configuration-path: .github/project-pr-labeler.yml
|
|
@ -0,0 +1,125 @@
|
||||||
|
name: Run smoke tests against pull request.
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- trunk
|
||||||
|
types:
|
||||||
|
- labeled
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
prcheck:
|
||||||
|
name: Smoke test a pull request.
|
||||||
|
if: "${{ contains(github.event.label.name, 'run: smoke tests') }}"
|
||||||
|
runs-on: ubuntu-18.04
|
||||||
|
steps:
|
||||||
|
- name: Create dirs.
|
||||||
|
run: |
|
||||||
|
mkdir -p code/woocommerce
|
||||||
|
mkdir -p package/woocommerce
|
||||||
|
mkdir -p tmp/woocommerce
|
||||||
|
|
||||||
|
- name: Checkout code.
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
path: package/woocommerce
|
||||||
|
|
||||||
|
- name: Get cached composer and pnpm directories
|
||||||
|
uses: actions/cache@v3
|
||||||
|
id: cache-deps
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.pnpm-store
|
||||||
|
package/woocommerce/plugins/woocommerce/packages
|
||||||
|
package/woocommerce/plugins/woocommerce/vendor
|
||||||
|
key: ${{ runner.os }}-smoke-test-npm-composer-${{ hashFiles('plugins/woocommerce/composer.lock', '**/pnpm-lock.yaml') }}
|
||||||
|
|
||||||
|
- name: Install PNPM
|
||||||
|
run: npm install -g pnpm
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install
|
||||||
|
|
||||||
|
- name: Install Composer dependencies
|
||||||
|
if: steps.cache-deps.outputs.cache-hit != 'true'
|
||||||
|
run: pnpm nx composer-install-no-dev woocommerce
|
||||||
|
|
||||||
|
- name: Install prerequisites.
|
||||||
|
working-directory: package/woocommerce/plugins/woocommerce
|
||||||
|
id: installation
|
||||||
|
run: |
|
||||||
|
pnpm nx build-assets woocommerce
|
||||||
|
pnpm install jest
|
||||||
|
|
||||||
|
- name: Run smoke test.
|
||||||
|
working-directory: package/woocommerce/plugins/woocommerce
|
||||||
|
if: always()
|
||||||
|
env:
|
||||||
|
SMOKE_TEST_URL: ${{ secrets.SMOKE_TEST_URL }}
|
||||||
|
SMOKE_TEST_ADMIN_USER: ${{ secrets.SMOKE_TEST_ADMIN_USER }}
|
||||||
|
SMOKE_TEST_ADMIN_PASSWORD: ${{ secrets.SMOKE_TEST_ADMIN_PASSWORD }}
|
||||||
|
SMOKE_TEST_ADMIN_USER_EMAIL: ${{ secrets.SMOKE_TEST_ADMIN_USER_EMAIL }}
|
||||||
|
SMOKE_TEST_CUSTOMER_USER: ${{ secrets.SMOKE_TEST_CUSTOMER_USER }}
|
||||||
|
SMOKE_TEST_CUSTOMER_PASSWORD: ${{ secrets.SMOKE_TEST_CUSTOMER_PASSWORD }}
|
||||||
|
WC_E2E_SCREENSHOTS: 1
|
||||||
|
E2E_RETEST: 1
|
||||||
|
E2E_SLACK_TOKEN: ${{ secrets.SMOKE_TEST_SLACK_TOKEN }}
|
||||||
|
E2E_SLACK_CHANNEL: ${{ secrets.SMOKE_TEST_SLACK_CHANNEL }}
|
||||||
|
UPDATE_WC: 1
|
||||||
|
DEFAULT_TIMEOUT_OVERRIDE: 120000
|
||||||
|
run: |
|
||||||
|
pnpm exec wc-e2e test:e2e tests/e2e/specs/smoke-tests/update-woocommerce.js
|
||||||
|
|
||||||
|
- name: Post Smoke tests results comment on PR
|
||||||
|
if: always()
|
||||||
|
uses: actions/github-script@v5
|
||||||
|
env:
|
||||||
|
TITLE: 'Smoke Test Results'
|
||||||
|
SMOKE_TEST_URL: ${{ secrets.SMOKE_TEST_URL }}
|
||||||
|
with:
|
||||||
|
github-token: ${{secrets.GITHUB_TOKEN}}
|
||||||
|
script: |
|
||||||
|
const script = require( './package/woocommerce/packages/js/e2e-environment/bin/post-results-to-github-pr.js' )
|
||||||
|
await script({github, context})
|
||||||
|
|
||||||
|
- name: Run E2E tests.
|
||||||
|
working-directory: package/woocommerce/plugins/woocommerce
|
||||||
|
if: always()
|
||||||
|
env:
|
||||||
|
SMOKE_TEST_URL: ${{ secrets.SMOKE_TEST_URL }}
|
||||||
|
SMOKE_TEST_ADMIN_USER: ${{ secrets.SMOKE_TEST_ADMIN_USER }}
|
||||||
|
SMOKE_TEST_ADMIN_PASSWORD: ${{ secrets.SMOKE_TEST_ADMIN_PASSWORD }}
|
||||||
|
SMOKE_TEST_ADMIN_USER_EMAIL: ${{ secrets.SMOKE_TEST_ADMIN_USER_EMAIL }}
|
||||||
|
SMOKE_TEST_CUSTOMER_USER: ${{ secrets.SMOKE_TEST_CUSTOMER_USER }}
|
||||||
|
SMOKE_TEST_CUSTOMER_PASSWORD: ${{ secrets.SMOKE_TEST_CUSTOMER_PASSWORD }}
|
||||||
|
WC_E2E_SCREENSHOTS: 1
|
||||||
|
E2E_RETEST: 1
|
||||||
|
E2E_SLACK_TOKEN: ${{ secrets.SMOKE_TEST_SLACK_TOKEN }}
|
||||||
|
E2E_SLACK_CHANNEL: ${{ secrets.SMOKE_TEST_SLACK_CHANNEL }}
|
||||||
|
UPDATE_WC: 1
|
||||||
|
DEFAULT_TIMEOUT_OVERRIDE: 120000
|
||||||
|
run: |
|
||||||
|
pnpm exec wc-e2e test:e2e
|
||||||
|
|
||||||
|
- name: Post E2E tests results comment on PR
|
||||||
|
if: always()
|
||||||
|
uses: actions/github-script@v5
|
||||||
|
env:
|
||||||
|
TITLE: 'E2E Test Results'
|
||||||
|
SMOKE_TEST_URL: ${{ secrets.SMOKE_TEST_URL }}
|
||||||
|
with:
|
||||||
|
github-token: ${{secrets.GITHUB_TOKEN}}
|
||||||
|
script: |
|
||||||
|
const script = require( './package/woocommerce/packages/js/e2e-environment/bin/post-results-to-github-pr.js' )
|
||||||
|
await script({github, context})
|
||||||
|
|
||||||
|
- name: Remove label from pull request.
|
||||||
|
if: |
|
||||||
|
always()
|
||||||
|
&& contains( github.event.pull_request.labels.*.name, format('run{0} smoke tests', ':'))
|
||||||
|
uses: actions-ecosystem/action-remove-labels@v1
|
||||||
|
with:
|
||||||
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
labels: 'run: smoke tests'
|
|
@ -1,22 +1,30 @@
|
||||||
name: Run unit tests on PR
|
name: Run unit tests on PR
|
||||||
on:
|
on:
|
||||||
pull_request
|
pull_request
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: bash
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
name: PHP ${{ matrix.php }} WP ${{ matrix.wp }}
|
name: PHP ${{ matrix.php }} WP ${{ matrix.wp }}
|
||||||
timeout-minutes: 15
|
timeout-minutes: 20
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
continue-on-error: ${{ matrix.wp == 'nightly' }}
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
php: [ '7.0', '7.1', '7.2', '7.3', '7.4', '8.0' ]
|
php: [ '7.2', '7.3', '7.4', '8.0' ]
|
||||||
wp: [ "latest" ]
|
wp: [ "latest" ]
|
||||||
include:
|
include:
|
||||||
- wp: nightly
|
- wp: nightly
|
||||||
php: '7.4'
|
php: '7.4'
|
||||||
- wp: '5.5'
|
- wp: '5.8'
|
||||||
php: 7.2
|
php: 7.2
|
||||||
- wp: '5.4'
|
- wp: '5.7'
|
||||||
php: 7.2
|
php: 7.2
|
||||||
services:
|
services:
|
||||||
database:
|
database:
|
||||||
|
@ -43,29 +51,46 @@ jobs:
|
||||||
php --version
|
php --version
|
||||||
composer --version
|
composer --version
|
||||||
|
|
||||||
- name: Get cached composer directories
|
- name: Get cached composer and pnpm directories
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
|
id: cache-deps
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
./packages
|
~/.pnpm-store
|
||||||
./vendor
|
plugins/woocommerce/packages
|
||||||
key: ${{ runner.os }}-${{ hashFiles('./composer.lock') }}
|
plugins/woocommerce/vendor
|
||||||
|
key: ${{ runner.os }}-npm-composer-${{ hashFiles('plugins/woocommerce/composer.lock', '**/pnpm-lock.yaml') }}
|
||||||
|
|
||||||
- name: Setup and install composer
|
- name: Install PNPM
|
||||||
run: composer install
|
run: npm install -g pnpm
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install
|
||||||
|
|
||||||
|
- name: Install Composer dependencies
|
||||||
|
if: steps.cache-deps.outputs.cache-hit != 'true'
|
||||||
|
run: pnpm nx composer-install woocommerce
|
||||||
|
|
||||||
|
- name: Build Admin feature config
|
||||||
|
run: |
|
||||||
|
pnpm nx build:feature-config woocommerce
|
||||||
|
|
||||||
- name: Add PHP8 Compatibility.
|
- name: Add PHP8 Compatibility.
|
||||||
run: |
|
run: |
|
||||||
if [ "$(php -r "echo version_compare(PHP_VERSION,'8.0','>=');")" ]; then
|
if [ "$(php -r "echo version_compare(PHP_VERSION,'8.0','>=');")" ]; then
|
||||||
curl -L https://github.com/woocommerce/phpunit/archive/add-compatibility-with-php8-to-phpunit-7.zip -o /tmp/phpunit-7.5-fork.zip
|
curl -L https://github.com/woocommerce/phpunit/archive/add-compatibility-with-php8-to-phpunit-7.zip -o /tmp/phpunit-7.5-fork.zip
|
||||||
unzip -d /tmp/phpunit-7.5-fork /tmp/phpunit-7.5-fork.zip
|
unzip -d /tmp/phpunit-7.5-fork /tmp/phpunit-7.5-fork.zip
|
||||||
|
cd plugins/woocommerce
|
||||||
composer bin phpunit config --unset platform
|
composer bin phpunit config --unset platform
|
||||||
composer bin phpunit config repositories.0 '{"type": "path", "url": "/tmp/phpunit-7.5-fork/phpunit-add-compatibility-with-php8-to-phpunit-7", "options": {"symlink": false}}'
|
composer bin phpunit config repositories.0 '{"type": "path", "url": "/tmp/phpunit-7.5-fork/phpunit-add-compatibility-with-php8-to-phpunit-7", "options": {"symlink": false}}'
|
||||||
composer bin phpunit require --dev -W phpunit/phpunit:@dev --ignore-platform-reqs
|
composer bin phpunit require --dev -W phpunit/phpunit:@dev --ignore-platform-reqs
|
||||||
|
rm -rf ./vendor/phpunit/
|
||||||
|
pnpm nx composer-dump-autoload woocommerce
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Init DB and WP
|
- name: Init DB and WP
|
||||||
|
working-directory: plugins/woocommerce
|
||||||
run: ./tests/bin/install.sh woo_test root root 127.0.0.1 ${{ matrix.wp }}
|
run: ./tests/bin/install.sh woo_test root root 127.0.0.1 ${{ matrix.wp }}
|
||||||
|
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: ./vendor/bin/phpunit -c ./phpunit.xml
|
run: pnpm nx test-unit woocommerce
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
name: "Pull request post-merge processing"
|
||||||
|
on:
|
||||||
|
pull_request_target:
|
||||||
|
types: [closed]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
process-pull-request-after-merge:
|
||||||
|
name: "Process a pull request after it's merged"
|
||||||
|
if: github.event.pull_request.merged == true
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: "Get the action scripts"
|
||||||
|
run: |
|
||||||
|
scripts="assign-milestone-to-merged-pr.php add-post-merge-comment.php post-request-shared.php"
|
||||||
|
for script in $scripts
|
||||||
|
do
|
||||||
|
curl \
|
||||||
|
--silent \
|
||||||
|
--fail \
|
||||||
|
--header 'Authorization: bearer ${{ secrets.GITHUB_TOKEN }}' \
|
||||||
|
--header 'User-Agent: GitHub action to set the milestone for a pull request' \
|
||||||
|
--header 'Accept: application/vnd.github.v3.raw' \
|
||||||
|
--output $script \
|
||||||
|
--location "$GITHUB_API_URL/repos/${{ github.repository }}/contents/.github/workflows/scripts/$script?ref=${{ github.event.pull_request.base.ref }}"
|
||||||
|
done
|
||||||
|
env:
|
||||||
|
GITHUB_API_URL: ${{ env.GITHUB_API_URL }}
|
||||||
|
- name: "Install PHP"
|
||||||
|
uses: shivammathur/setup-php@v2
|
||||||
|
with:
|
||||||
|
php-version: '7.4'
|
||||||
|
- name: "Run the script to assign a milestone"
|
||||||
|
if: |
|
||||||
|
contains(github.event.pull_request.labels.*.name, 'plugin: woocommerce') &&
|
||||||
|
!github.event.pull_request.milestone &&
|
||||||
|
github.event.pull_request.base.ref == 'trunk'
|
||||||
|
run: php assign-milestone-to-merged-pr.php
|
||||||
|
env:
|
||||||
|
PULL_REQUEST_ID: ${{ github.event.pull_request.node_id }}
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
- name: "Run the script to post a comment with next steps hint"
|
||||||
|
if: "contains(github.event.pull_request.labels.*.name, 'plugin: woocommerce')"
|
||||||
|
run: php add-post-merge-comment.php
|
||||||
|
env:
|
||||||
|
PULL_REQUEST_ID: ${{ github.event.pull_request.node_id }}
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
@ -0,0 +1,35 @@
|
||||||
|
name: "Enforce release code freeze"
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 16 * * 4' # Run at 1600 UTC on Thursdays.
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
maybe-create-next-milestone-and-release-branch:
|
||||||
|
name: "Maybe create next milestone and release branch"
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: "Get the action script"
|
||||||
|
run: |
|
||||||
|
scripts="post-request-shared.php release-code-freeze.php"
|
||||||
|
for script in $scripts
|
||||||
|
do
|
||||||
|
curl \
|
||||||
|
--silent \
|
||||||
|
--fail \
|
||||||
|
--header 'Authorization: bearer ${{ secrets.GITHUB_TOKEN }}' \
|
||||||
|
--header 'User-Agent: GitHub action to enforce release code freeze' \
|
||||||
|
--header 'Accept: application/vnd.github.v3.raw' \
|
||||||
|
--output $script \
|
||||||
|
--location "$GITHUB_API_URL/repos/${{ github.repository }}/contents/.github/workflows/scripts/$script?ref=$GITHUB_REF"
|
||||||
|
done
|
||||||
|
env:
|
||||||
|
GITHUB_API_URL: ${{ env.GITHUB_API_URL }}
|
||||||
|
GITHUB_REF: ${{ env.GITHUB_REF }}
|
||||||
|
- name: "Install PHP"
|
||||||
|
uses: shivammathur/setup-php@v2
|
||||||
|
with:
|
||||||
|
php-version: '7.4'
|
||||||
|
- name: "Run the script to enforce the code freeze"
|
||||||
|
run: php release-code-freeze.php
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
@ -0,0 +1,94 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Script to automatically add a comment to a pull request when it's merged.
|
||||||
|
*
|
||||||
|
* @package WooCommerce/GithubActions
|
||||||
|
*/
|
||||||
|
|
||||||
|
// phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped, WordPress.WP.AlternativeFunctions
|
||||||
|
|
||||||
|
require_once __DIR__ . '/post-request-shared.php';
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the merger login name.
|
||||||
|
*/
|
||||||
|
|
||||||
|
echo 'Retrieving the merger user name... ';
|
||||||
|
|
||||||
|
$get_pr_merged_username_query = "
|
||||||
|
node(id: \"$pr_id\") {
|
||||||
|
... on PullRequest {
|
||||||
|
timelineItems(first: 1, itemTypes: MERGED_EVENT) {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
... on MergedEvent {
|
||||||
|
actor {
|
||||||
|
login
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}";
|
||||||
|
|
||||||
|
$result = do_graphql_api_request( $get_pr_merged_username_query );
|
||||||
|
|
||||||
|
if ( is_array( $result ) ) {
|
||||||
|
if ( empty( $result['errors'] ) ) {
|
||||||
|
echo "Ok!\n";
|
||||||
|
} else {
|
||||||
|
echo "\n*** Errors found while retrieving the merger user name:\n";
|
||||||
|
echo var_dump( $result['errors'] );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
echo "\n*** Error found while retrieving the merger user name: file_get_contents returned the following:\n";
|
||||||
|
echo var_dump( $result );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$merger_user_name = $result['data']['node']['timelineItems']['edges'][0]['node']['actor']['login'];
|
||||||
|
echo "The pull request was merged by: $merger_user_name\n";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Post the comment.
|
||||||
|
*/
|
||||||
|
|
||||||
|
$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 testing instructions` label";
|
||||||
|
|
||||||
|
$add_comment_mutation = "
|
||||||
|
addComment(input: {subjectId: \"$pr_id\", body: \"$comment_body\", clientMutationId: \"$github_token\"}) {
|
||||||
|
commentEdge {
|
||||||
|
node {
|
||||||
|
id
|
||||||
|
databaseId
|
||||||
|
url
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}";
|
||||||
|
|
||||||
|
echo 'Publishing the comment... ';
|
||||||
|
|
||||||
|
$result = do_graphql_api_request( $add_comment_mutation, true );
|
||||||
|
|
||||||
|
if ( is_array( $result ) ) {
|
||||||
|
if ( empty( $result['errors'] ) ) {
|
||||||
|
echo "Ok!\n";
|
||||||
|
} else {
|
||||||
|
echo "\n*** Errors found while publishing the comment:\n";
|
||||||
|
echo var_dump( $result['errors'] );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
echo "\n*** Error found while publishing the comment: file_get_contents returned the following:\n";
|
||||||
|
echo var_dump( $result );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$comment_url = $result['data']['addComment']['commentEdge']['node']['url'];
|
||||||
|
echo "Comment URL: $comment_url\n";
|
||||||
|
|
||||||
|
// phpcs:enable WordPress.Security.EscapeOutput.OutputNotEscaped, WordPress.WP.AlternativeFunctions
|
|
@ -0,0 +1,47 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Script to automatically assign a milestone to a pull request when it's merged.
|
||||||
|
*
|
||||||
|
* @package WooCommerce/GithubActions
|
||||||
|
*/
|
||||||
|
|
||||||
|
// phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped, WordPress.WP.AlternativeFunctions
|
||||||
|
|
||||||
|
require_once __DIR__ . '/post-request-shared.php';
|
||||||
|
|
||||||
|
$chosen_milestone = get_latest_milestone_from_api( true );
|
||||||
|
|
||||||
|
echo 'Milestone that will be assigned: ' . $chosen_milestone['title'] . "\n";
|
||||||
|
|
||||||
|
if ( getenv( 'DRY_RUN' ) ) {
|
||||||
|
echo "Dry run, skipping the actual milestone assignment\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Assign the milestone to the pull request.
|
||||||
|
*/
|
||||||
|
|
||||||
|
echo 'Assigning the milestone to the pull request... ';
|
||||||
|
|
||||||
|
$milestone_id = $chosen_milestone['id'];
|
||||||
|
$mutation = "
|
||||||
|
updatePullRequest(input: {pullRequestId: \"$pr_id\", milestoneId: \"$milestone_id\"}) {
|
||||||
|
clientMutationId
|
||||||
|
}
|
||||||
|
";
|
||||||
|
|
||||||
|
$result = do_graphql_api_request( $mutation, true );
|
||||||
|
if ( is_array( $result ) ) {
|
||||||
|
if ( empty( $result['errors'] ) ) {
|
||||||
|
echo "Ok!\n";
|
||||||
|
} else {
|
||||||
|
echo "\n*** Errors found while assigning the milestone:\n";
|
||||||
|
echo var_dump( $result['errors'] );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
echo "\n*** Error found while assigning the milestone: file_get_contents returned the following:\n";
|
||||||
|
echo var_dump( $result );
|
||||||
|
}
|
||||||
|
|
||||||
|
// phpcs:enable WordPress.Security.EscapeOutput.OutputNotEscaped, WordPress.WP.AlternativeFunctions
|
|
@ -0,0 +1,54 @@
|
||||||
|
/**
|
||||||
|
* A script that fetches the asset id of a given release and sets it as the output for the step that calls it
|
||||||
|
*/
|
||||||
|
const https = require('https');
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
hostname: 'api.github.com',
|
||||||
|
port: 443,
|
||||||
|
path: `/repos/${process.env.REPO}/releases/${process.env.RELEASE_ID}/assets`,
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Authorization': `Bearer ${ process.env.GITHUB_TOKEN }`,
|
||||||
|
'User-Agent': 'WooCommerce Smoke Build'
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
const fetchAssetId = () => {
|
||||||
|
return new Promise( ( resolve, reject ) => {
|
||||||
|
const request = https.get( options, ( response ) => {
|
||||||
|
response.setEncoding('utf8');
|
||||||
|
|
||||||
|
let responseBody = '';
|
||||||
|
|
||||||
|
response.on( 'data', ( chunk ) => {
|
||||||
|
responseBody += chunk;
|
||||||
|
} );
|
||||||
|
|
||||||
|
response.on( 'end', () => {
|
||||||
|
const assets = JSON.parse( responseBody );
|
||||||
|
// use the most recently uploaded asset
|
||||||
|
resolve( assets[ assets.length - 1 ].id );
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
request.on('error', ( error ) => {
|
||||||
|
reject( error );
|
||||||
|
} );
|
||||||
|
|
||||||
|
request.end();
|
||||||
|
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = async ( { github, context, core } ) => {
|
||||||
|
const id = await fetchAssetId();
|
||||||
|
|
||||||
|
// set asset_id as the output
|
||||||
|
core.setOutput( 'asset_id', id );
|
||||||
|
}
|
|
@ -0,0 +1,284 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Common code for the post-merge GitHub action scripts.
|
||||||
|
*
|
||||||
|
* @package WooCommerce/GithubActions
|
||||||
|
*/
|
||||||
|
|
||||||
|
// phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped, WordPress.WP.AlternativeFunctions
|
||||||
|
|
||||||
|
global $repo_owner, $repo_name, $github_token, $graphql_api_url;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Grab/process input.
|
||||||
|
*/
|
||||||
|
|
||||||
|
$repo_parts = explode( '/', getenv( 'GITHUB_REPOSITORY' ) );
|
||||||
|
$repo_owner = $repo_parts[0];
|
||||||
|
$repo_name = $repo_parts[1];
|
||||||
|
|
||||||
|
$pr_id = getenv( 'PULL_REQUEST_ID' );
|
||||||
|
$github_token = getenv( 'GITHUB_TOKEN' );
|
||||||
|
$github_api_url = getenv( 'GITHUB_API_URL' );
|
||||||
|
$graphql_api_url = getenv( 'GITHUB_GRAPHQL_URL' );
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to get the latest milestone.
|
||||||
|
*
|
||||||
|
* @param bool $use_latest_when_null When true, the function returns the latest milestone regardless of release branch status.
|
||||||
|
* @return string The title of the latest milestone.
|
||||||
|
*/
|
||||||
|
function get_latest_milestone_from_api( $use_latest_when_null = false ) {
|
||||||
|
global $repo_owner, $repo_name;
|
||||||
|
|
||||||
|
echo 'Getting the list of milestones...' . PHP_EOL;
|
||||||
|
|
||||||
|
$query = "
|
||||||
|
repository(owner:\"$repo_owner\", name:\"$repo_name\") {
|
||||||
|
milestones(first: 10, states: [OPEN], orderBy: {field: CREATED_AT, direction: DESC}) {
|
||||||
|
nodes {
|
||||||
|
id
|
||||||
|
title
|
||||||
|
state
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
";
|
||||||
|
$json = do_graphql_api_request( $query );
|
||||||
|
$milestones = $json['data']['repository']['milestones']['nodes'];
|
||||||
|
$milestones = array_map(
|
||||||
|
function( $x ) {
|
||||||
|
return 1 === preg_match( '/^\d+\.\d+\.\d+$/D', $x['title'] ) ? $x : null;
|
||||||
|
},
|
||||||
|
$milestones
|
||||||
|
);
|
||||||
|
$milestones = array_filter( $milestones );
|
||||||
|
usort(
|
||||||
|
$milestones,
|
||||||
|
function( $a, $b ) {
|
||||||
|
return version_compare( $b['title'], $a['title'] );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
echo 'Latest open milestone: ' . $milestones[0]['title'] . PHP_EOL;
|
||||||
|
|
||||||
|
$chosen_milestone = null;
|
||||||
|
foreach ( $milestones as $milestone ) {
|
||||||
|
$milestone_title_parts = explode( '.', $milestone['title'] );
|
||||||
|
$milestone_release_branch = 'release/' . $milestone_title_parts[0] . '.' . $milestone_title_parts[1];
|
||||||
|
|
||||||
|
$query = "
|
||||||
|
repository(owner:\"$repo_owner\", name:\"$repo_name\") {
|
||||||
|
ref(qualifiedName: \"refs/heads/$milestone_release_branch\") {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
";
|
||||||
|
$result = do_graphql_api_request( $query );
|
||||||
|
|
||||||
|
if ( is_null( $result['data']['repository']['ref'] ) ) {
|
||||||
|
$chosen_milestone = $milestone;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If all the milestones have a release branch, just take the newest one.
|
||||||
|
if ( $use_latest_when_null && is_null( $chosen_milestone ) ) {
|
||||||
|
echo 'WARNING: No milestone without release branch found, the newest one will be assigned.' . PHP_EOL;
|
||||||
|
$chosen_milestone = $milestones[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $chosen_milestone;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to get the last major.minor version with a release from the API.
|
||||||
|
*
|
||||||
|
* @return string Returns the latest version with a release formatted as "major.minor".
|
||||||
|
*/
|
||||||
|
function get_latest_version_with_release() {
|
||||||
|
global $repo_owner, $repo_name;
|
||||||
|
|
||||||
|
echo 'Getting the list of releases...' . PHP_EOL;
|
||||||
|
|
||||||
|
$query = "
|
||||||
|
repository(owner:\"$repo_owner\", name:\"$repo_name\") {
|
||||||
|
releases(first: 25, orderBy: { field: CREATED_AT, direction: DESC}) {
|
||||||
|
nodes {
|
||||||
|
tagName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
";
|
||||||
|
$json = do_graphql_api_request( $query );
|
||||||
|
$releases = $json['data']['repository']['releases']['nodes'];
|
||||||
|
$releases = array_map(
|
||||||
|
function( $x ) {
|
||||||
|
return 1 === preg_match( '/^\d+\.\d+\.\d+/D', $x['tagName'] ) ? $x : null;
|
||||||
|
},
|
||||||
|
$releases
|
||||||
|
);
|
||||||
|
$releases = array_filter( $releases );
|
||||||
|
usort(
|
||||||
|
$releases,
|
||||||
|
function( $a, $b ) {
|
||||||
|
return version_compare( $b['tagName'], $a['tagName'] );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
$major_minor = preg_replace( '/(^\d+\.\d+).*?$/', '\1', $releases[0]['tagName'] );
|
||||||
|
echo 'Most recent version with a release: ' . $major_minor . PHP_EOL;
|
||||||
|
|
||||||
|
return $major_minor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to retreive the sha1 reference for a given branch name.
|
||||||
|
*
|
||||||
|
* @param string $branch The name of the branch.
|
||||||
|
* @return string Returns the name of the branch, or a falsey value on error.
|
||||||
|
*/
|
||||||
|
function get_ref_from_branch( $branch ) {
|
||||||
|
global $repo_owner, $repo_name;
|
||||||
|
$query = "
|
||||||
|
repository(owner:\"$repo_owner\", name:\"$repo_name\") {
|
||||||
|
ref(qualifiedName: \"refs/heads/{$branch}\") {
|
||||||
|
target {
|
||||||
|
... on Commit {
|
||||||
|
history(first: 1) {
|
||||||
|
edges{ node{ oid } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
";
|
||||||
|
$result = do_graphql_api_request( $query );
|
||||||
|
|
||||||
|
// Warnings suppressed here because traversing this level of arrays with isset / is_array checks would be messy.
|
||||||
|
return @$result['data']['repository']['ref']['target']['history']['edges'][0]['node']['oid'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to create milestone using the GitHub REST API.
|
||||||
|
*
|
||||||
|
* @param string $title The title of the milestone to be created.
|
||||||
|
* @return bool True on success, False otherwise.
|
||||||
|
*/
|
||||||
|
function create_github_milestone( $title ) {
|
||||||
|
global $repo_owner, $repo_name;
|
||||||
|
|
||||||
|
$result = do_github_api_post_request( "/repos/{$repo_owner}/{$repo_name}/milestones", array(
|
||||||
|
'title' => $title,
|
||||||
|
) );
|
||||||
|
|
||||||
|
return is_array( $result ) && $result['title'] === $title;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to create branch using the GitHub REST API.
|
||||||
|
*
|
||||||
|
* @param string $branch The branch to be created.
|
||||||
|
* @param string $sha The sha1 reference for the branch.
|
||||||
|
* @return bool True on success, False otherwise.
|
||||||
|
*/
|
||||||
|
function create_github_branch( $branch, $sha ) {
|
||||||
|
global $repo_owner, $repo_name;
|
||||||
|
|
||||||
|
$ref = "refs/heads/{$branch}";
|
||||||
|
$result = do_github_api_post_request( "/repos/{$repo_owner}/{$repo_name}/git/refs", array(
|
||||||
|
'ref' => $ref,
|
||||||
|
'sha' => $sha,
|
||||||
|
) );
|
||||||
|
|
||||||
|
return is_array( $result ) && $result['ref'] === $ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to create branch using the GitHub REST API from an existing branch.
|
||||||
|
*
|
||||||
|
* @param string $source The branch from which to create.
|
||||||
|
* @param string $target The branch to be created.
|
||||||
|
* @return bool True on success, False otherwise.
|
||||||
|
*/
|
||||||
|
function create_github_branch_from_branch( $source, $target ) {
|
||||||
|
$ref = get_ref_from_branch( $source );
|
||||||
|
if ( ! $ref ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return create_github_branch( $target, $ref );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to do a GitHub API POST Request.
|
||||||
|
*
|
||||||
|
* @param array $request_url
|
||||||
|
* @param array $body The body of the request to be json encoded.
|
||||||
|
* @return mixed The json-decoded response if a response is received, 'false' (or whatever file_get_contents returns) otherwise.
|
||||||
|
*/
|
||||||
|
function do_github_api_post_request( $request_path, $body ) {
|
||||||
|
global $github_token, $github_api_url, $github_api_response_code;
|
||||||
|
|
||||||
|
$context = stream_context_create(
|
||||||
|
array(
|
||||||
|
'http' => array(
|
||||||
|
'method' => 'POST',
|
||||||
|
'header' => array(
|
||||||
|
'Accept: application/vnd.github.v3+json',
|
||||||
|
'Content-Type: application/json',
|
||||||
|
'User-Agent: GitHub Actions for creation of milestones',
|
||||||
|
'Authorization: bearer ' . $github_token,
|
||||||
|
),
|
||||||
|
'content' => json_encode( $body ),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$full_request_url = rtrim( $github_api_url, '/' ) . '/' . ltrim( $request_path, '/' );
|
||||||
|
$result = @file_get_contents( $full_request_url, false, $context );
|
||||||
|
|
||||||
|
// Verify that the post request was sucessful.
|
||||||
|
$status_line = $http_response_header[0];
|
||||||
|
preg_match( "/^HTTPS?\/\d\.\d\s+(\d{3})\s+/i", $status_line, $matches );
|
||||||
|
$github_api_response_code = $matches[1];
|
||||||
|
if ( '2' !== substr( $github_api_response_code, 0, 1 ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return is_string( $result ) ? json_decode( $result, true ) : $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to query the GitHub GraphQL API.
|
||||||
|
*
|
||||||
|
* @param string $body The GraphQL-formatted request body, without "query" or "mutation" wrapper.
|
||||||
|
* @param bool $is_mutation True if the request is a mutation, false if it's a query.
|
||||||
|
* @return mixed The json-decoded response if a response is received, 'false' (or whatever file_get_contents returns) otherwise.
|
||||||
|
*/
|
||||||
|
function do_graphql_api_request( $body, $is_mutation = false ) {
|
||||||
|
global $github_token, $graphql_api_url;
|
||||||
|
|
||||||
|
$keyword = $is_mutation ? 'mutation' : 'query';
|
||||||
|
$data = array( 'query' => "$keyword { $body }" );
|
||||||
|
$context = stream_context_create(
|
||||||
|
array(
|
||||||
|
'http' => array(
|
||||||
|
'method' => 'POST',
|
||||||
|
'header' => array(
|
||||||
|
'Accept: application/json',
|
||||||
|
'Content-Type: application/json',
|
||||||
|
'User-Agent: GitHub action to set the milestone for a pull request',
|
||||||
|
'Authorization: bearer ' . $github_token,
|
||||||
|
),
|
||||||
|
'content' => json_encode( $data ),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$result = file_get_contents( $graphql_api_url, false, $context );
|
||||||
|
return is_string( $result ) ? json_decode( $result, true ) : $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// phpcs:enable WordPress.Security.EscapeOutput.OutputNotEscaped, WordPress.WP.AlternativeFunctions
|
|
@ -0,0 +1,65 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Script to automatically enforce the release code freeze.
|
||||||
|
*
|
||||||
|
* @package WooCommerce/GithubActions
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once __DIR__ . '/post-request-shared.php';
|
||||||
|
|
||||||
|
$now = time();
|
||||||
|
if ( getenv( 'TIME_OVERRIDE' ) ) {
|
||||||
|
$now = strtotime( getenv( 'TIME_OVERRIDE' ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Code freeze comes 26 days prior to release day.
|
||||||
|
$release_time = strtotime( '+26 days', $now );
|
||||||
|
$release_day_of_week = date( 'l', $release_time );
|
||||||
|
$release_day_of_month = (int) date( 'j', $release_time );
|
||||||
|
|
||||||
|
// If 26 days from now isn't the second Tuesday, then it's not code freeze day.
|
||||||
|
if ( 'Tuesday' !== $release_day_of_week || $release_day_of_month < 8 || $release_day_of_month > 14 ) {
|
||||||
|
echo 'Info: Today is not the Thursday of the code freeze.' . PHP_EOL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$latest_version_with_release = get_latest_version_with_release();
|
||||||
|
|
||||||
|
if ( empty( $latest_version_with_release ) ) {
|
||||||
|
echo '*** Error: Unable to get latest version with release' . PHP_EOL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Because we go from 5.9 to 6.0, we can get the next major_minor by adding 0.1 and formatting appropriately.
|
||||||
|
$latest_float = (float) $latest_version_with_release;
|
||||||
|
$branch_major_minor = number_format( $latest_float + 0.1, 1 );
|
||||||
|
$milestone_major_minor = number_format( $latest_float + 0.2, 1 );
|
||||||
|
|
||||||
|
// We use those values to get the release branch and next milestones that we need to create.
|
||||||
|
$release_branch_to_create = "release/{$branch_major_minor}";
|
||||||
|
$milestone_to_create = "{$milestone_major_minor}.0";
|
||||||
|
|
||||||
|
if ( getenv( 'DRY_RUN' ) ) {
|
||||||
|
echo 'DRY RUN: Skipping actual creation of release branch and milestone...' . PHP_EOL;
|
||||||
|
echo "Release Branch: {$release_branch_to_create}" . PHP_EOL;
|
||||||
|
echo "Milestone: {$milestone_to_create}" . PHP_EOL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( create_github_milestone( $milestone_to_create ) ) {
|
||||||
|
echo "Created milestone {$milestone_to_create}" . PHP_EOL;
|
||||||
|
} else if ( '422' === $github_api_response_code ) {
|
||||||
|
// The milestone already existed when GitHub returns a 422 status.
|
||||||
|
echo "Notice: Unable to create {$milestone_to_create} milestone. Maybe it already exists? Skipping..." . PHP_EOL;
|
||||||
|
} else {
|
||||||
|
echo "*** Error: Unable to create {$milestone_to_create} milestone" . PHP_EOL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( create_github_branch_from_branch( 'trunk', $release_branch_to_create ) ) {
|
||||||
|
echo "Created branch {$release_branch_to_create}" . PHP_EOL;
|
||||||
|
} else if ( '422' === $github_api_response_code ) {
|
||||||
|
// The release branch already existed when GitHub returns a 422 status.
|
||||||
|
echo "Notice: Unable to create {$release_branch_to_create} branch. Maybe it already exists? Skipping..." . PHP_EOL;
|
||||||
|
} else {
|
||||||
|
echo "*** Error: Unable to create {$release_branch_to_create}" . PHP_EOL;
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
name: Check daily smoke test site status.
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '25 7 * * *'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
ping_site:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
name: Check site and notify if not found
|
||||||
|
steps:
|
||||||
|
- name: Check site status
|
||||||
|
id: sitecheck
|
||||||
|
uses: srt32/uptime@958231f4d95c117f08eb0fc70907e80d0dfedf2b
|
||||||
|
with:
|
||||||
|
url-to-hit: "${{ secrets.SMOKE_TEST_URL }}ready/"
|
||||||
|
expected-statuses: "200,301"
|
||||||
|
- name: Send message to Slack API
|
||||||
|
if: failure()
|
||||||
|
uses: archive/github-actions-slack@deecc2edc496dc642d643de1d7cf3a47f51fb27a
|
||||||
|
id: notify
|
||||||
|
with:
|
||||||
|
slack-bot-user-oauth-access-token: ${{ secrets.SMOKE_TEST_SLACK_TOKEN }}
|
||||||
|
slack-channel: ${{ secrets.SMOKE_TEST_SLACK_CHANNEL }}
|
||||||
|
slack-text: ':warning: <!subteam^${{ secrets.SMOKE_TEST_SLACK_GROUP }}> FYI the URL ${{ secrets.SMOKE_TEST_URL }}ready/ appears to be returning `404 not found` :x:'
|
|
@ -0,0 +1,153 @@
|
||||||
|
name: Smoke test daily
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '25 3 * * *'
|
||||||
|
jobs:
|
||||||
|
login-run:
|
||||||
|
name: Daily smoke test on trunk.
|
||||||
|
runs-on: ubuntu-18.04
|
||||||
|
steps:
|
||||||
|
- name: Create dirs.
|
||||||
|
run: |
|
||||||
|
mkdir -p code/woocommerce
|
||||||
|
mkdir -p package/woocommerce
|
||||||
|
mkdir -p tmp/woocommerce
|
||||||
|
mkdir -p node_modules
|
||||||
|
|
||||||
|
- name: Checkout code.
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
path: package/woocommerce
|
||||||
|
ref: trunk
|
||||||
|
|
||||||
|
- name: Install prerequisites.
|
||||||
|
working-directory: package/woocommerce/plugins/woocommerce
|
||||||
|
run: |
|
||||||
|
npm install -g pnpm
|
||||||
|
pnpm install
|
||||||
|
pnpm nx composer-install-no-dev woocommerce
|
||||||
|
pnpm nx build-assets woocommerce
|
||||||
|
pnpm install jest
|
||||||
|
|
||||||
|
- name: Run smoke test.
|
||||||
|
working-directory: package/woocommerce/plugins/woocommerce
|
||||||
|
env:
|
||||||
|
SMOKE_TEST_URL: ${{ secrets.SMOKE_TEST_URL }}
|
||||||
|
SMOKE_TEST_ADMIN_USER: ${{ secrets.SMOKE_TEST_ADMIN_USER }}
|
||||||
|
SMOKE_TEST_ADMIN_PASSWORD: ${{ secrets.SMOKE_TEST_ADMIN_PASSWORD }}
|
||||||
|
SMOKE_TEST_ADMIN_USER_EMAIL: ${{ secrets.SMOKE_TEST_ADMIN_USER_EMAIL }}
|
||||||
|
SMOKE_TEST_CUSTOMER_USER: ${{ secrets.SMOKE_TEST_CUSTOMER_USER }}
|
||||||
|
SMOKE_TEST_CUSTOMER_PASSWORD: ${{ secrets.SMOKE_TEST_CUSTOMER_PASSWORD }}
|
||||||
|
WC_E2E_SCREENSHOTS: 1
|
||||||
|
E2E_RETEST: 1
|
||||||
|
E2E_SLACK_TOKEN: ${{ secrets.SMOKE_TEST_SLACK_TOKEN }}
|
||||||
|
E2E_SLACK_CHANNEL: 'C01U0H617MY'
|
||||||
|
UPDATE_WC: 1
|
||||||
|
DEFAULT_TIMEOUT_OVERRIDE: 120000
|
||||||
|
BASE_URL: ${{ secrets.SMOKE_TEST_URL }}
|
||||||
|
USER_KEY: ${{ secrets.SMOKE_TEST_ADMIN_USER }}
|
||||||
|
USER_SECRET: ${{ secrets.SMOKE_TEST_ADMIN_PASSWORD }}
|
||||||
|
run: |
|
||||||
|
pnpm exec wc-e2e test:e2e tests/e2e/specs/smoke-tests/update-woocommerce.js
|
||||||
|
pnpm exec wc-e2e test:e2e
|
||||||
|
pnpm exec wc-api-tests test api
|
||||||
|
|
||||||
|
build:
|
||||||
|
name: Build zip for PR
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
id: build
|
||||||
|
uses: woocommerce/action-build@trunk
|
||||||
|
env:
|
||||||
|
BUILD_ENV: e2e
|
||||||
|
|
||||||
|
- name: Upload PR zip
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
name: woocommerce
|
||||||
|
path: ${{ steps.build.outputs.zip_path }}
|
||||||
|
retention-days: 7
|
||||||
|
|
||||||
|
test-plugins:
|
||||||
|
name: Smoke tests with ${{ matrix.plugin }} plugin installed
|
||||||
|
runs-on: ubuntu-18.04
|
||||||
|
needs: [build]
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- plugin: 'WooCommerce Payments'
|
||||||
|
repo: 'automattic/woocommerce-payments'
|
||||||
|
- plugin: 'WooCommerce PayPal Payments'
|
||||||
|
repo: 'woocommerce/woocommerce-paypal-payments'
|
||||||
|
- plugin: 'WooCommerce Shipping & Tax'
|
||||||
|
repo: 'automattic/woocommerce-services'
|
||||||
|
- plugin: 'WooCommerce Subscriptions'
|
||||||
|
repo: WC_SUBSCRIPTIONS_REPO
|
||||||
|
private: true
|
||||||
|
- plugin: 'WordPress SEO' # Yoast SEO in the UI, but the slug is wordpress-seo
|
||||||
|
repo: 'Yoast/wordpress-seo'
|
||||||
|
- plugin: 'Contact Form 7'
|
||||||
|
repo: 'takayukister/contact-form-7'
|
||||||
|
steps:
|
||||||
|
- name: Create dirs.
|
||||||
|
run: |
|
||||||
|
mkdir -p code/woocommerce
|
||||||
|
mkdir -p package/woocommerce
|
||||||
|
mkdir -p tmp/woocommerce
|
||||||
|
mkdir -p node_modules
|
||||||
|
|
||||||
|
- name: Checkout code.
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
path: package/woocommerce
|
||||||
|
|
||||||
|
- name: Install PNPM and install dependencies
|
||||||
|
working-directory: package/woocommerce
|
||||||
|
run: |
|
||||||
|
npm install -g pnpm
|
||||||
|
pnpm install
|
||||||
|
|
||||||
|
- name: Load docker images and start containers.
|
||||||
|
working-directory: package/woocommerce/plugins/woocommerce
|
||||||
|
run: pnpm exec wc-e2e docker:up
|
||||||
|
|
||||||
|
- name: Move current directory to code. We will install zip file in this dir later.
|
||||||
|
run: mv ./package/woocommerce/plugins/woocommerce/* ./code/woocommerce
|
||||||
|
|
||||||
|
- name: Download WooCommerce ZIP.
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: woocommerce
|
||||||
|
path: tmp
|
||||||
|
|
||||||
|
- name: Extract and replace WooCommerce zip.
|
||||||
|
working-directory: tmp
|
||||||
|
run: |
|
||||||
|
unzip woocommerce.zip -d woocommerce
|
||||||
|
mv woocommerce/woocommerce/* ../package/woocommerce/plugins/woocommerce/
|
||||||
|
|
||||||
|
- name: Install dependencies again
|
||||||
|
working-directory: package/woocommerce
|
||||||
|
run: |
|
||||||
|
npm install -g pnpm
|
||||||
|
pnpm install
|
||||||
|
|
||||||
|
- name: Run tests command.
|
||||||
|
working-directory: package/woocommerce/plugins/woocommerce
|
||||||
|
env:
|
||||||
|
WC_E2E_SCREENSHOTS: 1
|
||||||
|
E2E_SLACK_TOKEN: ${{ secrets.SMOKE_TEST_SLACK_TOKEN }}
|
||||||
|
E2E_SLACK_CHANNEL: ${{ secrets.RELEASE_TEST_SLACK_CHANNEL }}
|
||||||
|
PLUGIN_REPOSITORY: ${{ matrix.private && secrets[matrix.repo] || matrix.repo }}
|
||||||
|
PLUGIN_NAME: ${{ matrix.plugin }}
|
||||||
|
GITHUB_TOKEN: ${{ secrets.E2E_GH_TOKEN }}
|
||||||
|
run: |
|
||||||
|
pnpm exec wc-e2e test:e2e tests/e2e/specs/smoke-tests/upload-plugin.js
|
||||||
|
pnpm exec wc-e2e test:e2e
|
|
@ -0,0 +1,197 @@
|
||||||
|
name: Smoke test release
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
release_id:
|
||||||
|
description: 'WooCommerce Release Id'
|
||||||
|
required: true
|
||||||
|
jobs:
|
||||||
|
login-run:
|
||||||
|
name: Daily smoke test on release.
|
||||||
|
runs-on: ubuntu-18.04
|
||||||
|
steps:
|
||||||
|
- name: Create dirs.
|
||||||
|
run: |
|
||||||
|
mkdir -p code/woocommerce
|
||||||
|
mkdir -p package/woocommerce
|
||||||
|
mkdir -p tmp/woocommerce
|
||||||
|
mkdir -p node_modules
|
||||||
|
|
||||||
|
- name: Checkout code.
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
path: package/woocommerce
|
||||||
|
ref: trunk
|
||||||
|
|
||||||
|
- name: Install prerequisites.
|
||||||
|
working-directory: package/woocommerce/plugins/woocommerce
|
||||||
|
run: |
|
||||||
|
npm install -g pnpm
|
||||||
|
pnpm install
|
||||||
|
pnpm nx composer-install-no-dev woocommerce
|
||||||
|
pnpm nx build-assets woocommerce
|
||||||
|
pnpm install jest
|
||||||
|
|
||||||
|
- name: Run smoke test.
|
||||||
|
working-directory: package/woocommerce/plugins/woocommerce
|
||||||
|
env:
|
||||||
|
SMOKE_TEST_URL: ${{ secrets.RELEASE_TEST_URL }}
|
||||||
|
SMOKE_TEST_ADMIN_USER: ${{ secrets.RELEASE_TEST_ADMIN_USER }}
|
||||||
|
SMOKE_TEST_ADMIN_PASSWORD: ${{ secrets.RELEASE_TEST_ADMIN_PASSWORD }}
|
||||||
|
SMOKE_TEST_ADMIN_USER_EMAIL: ${{ secrets.RELEASE_TEST_ADMIN_USER_EMAIL }}
|
||||||
|
SMOKE_TEST_CUSTOMER_USER: ${{ secrets.RELEASE_TEST_CUSTOMER_USER }}
|
||||||
|
SMOKE_TEST_CUSTOMER_PASSWORD: ${{ secrets.RELEASE_TEST_CUSTOMER_PASSWORD }}
|
||||||
|
WC_E2E_SCREENSHOTS: 1
|
||||||
|
E2E_RETEST: 1
|
||||||
|
E2E_SLACK_TOKEN: ${{ secrets.SMOKE_TEST_SLACK_TOKEN }}
|
||||||
|
E2E_SLACK_CHANNEL: 'C02DS4NE72S'
|
||||||
|
TEST_RELEASE: 1
|
||||||
|
UPDATE_WC: 1
|
||||||
|
DEFAULT_TIMEOUT_OVERRIDE: 120000
|
||||||
|
BASE_URL: ${{ secrets.RELEASE_TEST_URL }}
|
||||||
|
USER_KEY: ${{ secrets.RELEASE_TEST_ADMIN_USER }}
|
||||||
|
USER_SECRET: ${{ secrets.RELEASE_TEST_ADMIN_PASSWORD }}
|
||||||
|
run: |
|
||||||
|
pnpm exec wc-e2e test:e2e tests/e2e/specs/smoke-tests/update-woocommerce.js
|
||||||
|
pnpm exec wc-e2e test:e2e
|
||||||
|
pnpm exec wc-api-tests test api
|
||||||
|
test-wp-version:
|
||||||
|
name: Smoke test on L-${{ matrix.wp }} WordPress version
|
||||||
|
runs-on: ubuntu-18.04
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
wp: ['1', '2']
|
||||||
|
steps:
|
||||||
|
- name: Create dirs.
|
||||||
|
run: |
|
||||||
|
mkdir -p code/woocommerce
|
||||||
|
mkdir -p package/woocommerce
|
||||||
|
mkdir -p tmp/woocommerce
|
||||||
|
mkdir -p node_modules
|
||||||
|
|
||||||
|
- name: Checkout code.
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
path: package/woocommerce
|
||||||
|
- name: Fetch Asset ID
|
||||||
|
id: fetch_asset_id
|
||||||
|
uses: actions/github-script@v5
|
||||||
|
env:
|
||||||
|
RELEASE_ID: ${{ github.event.inputs.release_id }}
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
REPO: ${{ github.repository }}
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
const script = require( './package/woocommerce/.github/workflows/scripts/fetch-asset-id.js' )
|
||||||
|
await script({github, context, core})
|
||||||
|
|
||||||
|
- name: Install PNPM and install dependencies
|
||||||
|
working-directory: package/woocommerce
|
||||||
|
run: |
|
||||||
|
npm install -g pnpm
|
||||||
|
pnpm install
|
||||||
|
|
||||||
|
- name: Load docker images and start containers.
|
||||||
|
working-directory: package/woocommerce/plugins/woocommerce
|
||||||
|
env:
|
||||||
|
LATEST_WP_VERSION_MINUS: ${{ matrix.wp }}
|
||||||
|
run: pnpm nx docker-up woocommerce
|
||||||
|
|
||||||
|
- name: Move current directory to code. We will install zip file in this dir later.
|
||||||
|
run: mv ./package/woocommerce/plugins/woocommerce/* ./code/woocommerce
|
||||||
|
|
||||||
|
- name: Download WooCommerce release zip
|
||||||
|
working-directory: tmp
|
||||||
|
run: |
|
||||||
|
curl https://api.github.com/repos/${{ github.repository }}/releases/assets/${{ steps.fetch_asset_id.outputs.asset_id }} -LJOH 'Accept: application/octet-stream'
|
||||||
|
|
||||||
|
unzip woocommerce.zip -d woocommerce
|
||||||
|
mv woocommerce/woocommerce/* ../package/woocommerce/plugins/woocommerce/
|
||||||
|
|
||||||
|
- name: Run tests command.
|
||||||
|
working-directory: package/woocommerce/plugins/woocommerce
|
||||||
|
env:
|
||||||
|
WC_E2E_SCREENSHOTS: 1
|
||||||
|
E2E_SLACK_TOKEN: ${{ secrets.SMOKE_TEST_SLACK_TOKEN }}
|
||||||
|
E2E_SLACK_CHANNEL: ${{ secrets.RELEASE_TEST_SLACK_CHANNEL }}
|
||||||
|
run: pnpm nx test-e2e woocommerce
|
||||||
|
|
||||||
|
test-plugins:
|
||||||
|
name: Smoke tests with ${{ matrix.plugin }} plugin installed
|
||||||
|
runs-on: ubuntu-18.04
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- plugin: 'WooCommerce Payments'
|
||||||
|
repo: 'automattic/woocommerce-payments'
|
||||||
|
- plugin: 'WooCommerce PayPal Payments'
|
||||||
|
repo: 'woocommerce/woocommerce-paypal-payments'
|
||||||
|
- plugin: 'WooCommerce Shipping & Tax'
|
||||||
|
repo: 'automattic/woocommerce-services'
|
||||||
|
- plugin: 'WooCommerce Subscriptions'
|
||||||
|
repo: WC_SUBSCRIPTIONS_REPO
|
||||||
|
private: true
|
||||||
|
- plugin: 'WordPress SEO' # Yoast SEO in the UI, but the slug is wordpress-seo
|
||||||
|
repo: 'Yoast/wordpress-seo'
|
||||||
|
- plugin: 'Contact Form 7'
|
||||||
|
repo: 'takayukister/contact-form-7'
|
||||||
|
steps:
|
||||||
|
- name: Create dirs.
|
||||||
|
run: |
|
||||||
|
mkdir -p code/woocommerce
|
||||||
|
mkdir -p package/woocommerce
|
||||||
|
mkdir -p tmp/woocommerce
|
||||||
|
mkdir -p node_modules
|
||||||
|
|
||||||
|
- name: Checkout code.
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
path: package/woocommerce
|
||||||
|
- name: Fetch Asset ID
|
||||||
|
id: fetch_asset_id
|
||||||
|
uses: actions/github-script@v5
|
||||||
|
env:
|
||||||
|
RELEASE_ID: ${{ github.event.inputs.release_id }}
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
REPO: ${{ github.repository }}
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
const script = require( './package/woocommerce/.github/workflows/scripts/fetch-asset-id.js' )
|
||||||
|
await script({github, context, core})
|
||||||
|
|
||||||
|
- name: Install PNPM and install dependencies
|
||||||
|
working-directory: package/woocommerce
|
||||||
|
run: |
|
||||||
|
npm install -g pnpm
|
||||||
|
pnpm install
|
||||||
|
|
||||||
|
- name: Load docker images and start containers.
|
||||||
|
working-directory: package/woocommerce/plugins/woocommerce
|
||||||
|
env:
|
||||||
|
LATEST_WP_VERSION_MINUS: ${{ matrix.wp }}
|
||||||
|
run: pnpm nx docker-up woocommerce
|
||||||
|
|
||||||
|
- name: Move current directory to code. We will install zip file in this dir later.
|
||||||
|
run: mv ./package/woocommerce/plugins/woocommerce/* ./code/woocommerce
|
||||||
|
|
||||||
|
- name: Download WooCommerce release zip
|
||||||
|
working-directory: tmp
|
||||||
|
run: |
|
||||||
|
curl https://api.github.com/repos/${{ github.repository }}/releases/assets/${{ steps.fetch_asset_id.outputs.asset_id }} -LJOH 'Accept: application/octet-stream'
|
||||||
|
|
||||||
|
unzip woocommerce.zip -d woocommerce
|
||||||
|
mv woocommerce/woocommerce/* ../package/woocommerce/plugins/woocommerce/
|
||||||
|
|
||||||
|
- name: Run tests command.
|
||||||
|
working-directory: package/woocommerce/plugins/woocommerce
|
||||||
|
env:
|
||||||
|
WC_E2E_SCREENSHOTS: 1
|
||||||
|
E2E_SLACK_TOKEN: ${{ secrets.SMOKE_TEST_SLACK_TOKEN }}
|
||||||
|
E2E_SLACK_CHANNEL: ${{ secrets.RELEASE_TEST_SLACK_CHANNEL }}
|
||||||
|
PLUGIN_REPOSITORY: ${{ matrix.private && secrets[matrix.repo] || matrix.repo }}
|
||||||
|
PLUGIN_NAME: ${{ matrix.plugin }}
|
||||||
|
GITHUB_TOKEN: ${{ secrets.E2E_GH_TOKEN }}
|
||||||
|
run: |
|
||||||
|
pnpm exec wc-e2e test:e2e tests/e2e/specs/smoke-tests/upload-plugin.js
|
||||||
|
pnpm exec wc-e2e test:e2e
|
|
@ -0,0 +1,24 @@
|
||||||
|
name: 'Close stale needs-feedback issues'
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '21 0 * * *'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
stale:
|
||||||
|
if: |
|
||||||
|
! contains(github.event.issue.labels.*.name, 'type: enhancement')
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/stale@v3
|
||||||
|
with:
|
||||||
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
stale-issue-message: "As a part of this repository's maintenance, this issue is being marked as stale due to inactivity. Please feel free to comment on it in case we missed something.\n\n###### After 7 days with no activity this issue will be automatically be closed."
|
||||||
|
close-issue-message: 'This issue was closed because it has been 14 days with no activity.'
|
||||||
|
days-before-issue-stale: 7
|
||||||
|
days-before-issue-close: 7
|
||||||
|
days-before-pr-close: -1
|
||||||
|
stale-issue-label: 'status: stale'
|
||||||
|
stale-pr-label: 'status: stale'
|
||||||
|
only-issue-labels: 'needs: author feedback'
|
||||||
|
close-issue-label: "status: can't reproduce"
|
||||||
|
ascending: true
|
|
@ -0,0 +1,15 @@
|
||||||
|
name: Add Triage Label
|
||||||
|
|
||||||
|
on:
|
||||||
|
issues:
|
||||||
|
types: opened
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
add_label:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- uses: actions-ecosystem/action-add-labels@v1
|
||||||
|
if: github.event.issue.labels[0] == null
|
||||||
|
with:
|
||||||
|
labels: 'status: awaiting triage'
|
|
@ -0,0 +1,166 @@
|
||||||
|
name: Add issue triage comments.
|
||||||
|
on:
|
||||||
|
issues:
|
||||||
|
types:
|
||||||
|
- labeled
|
||||||
|
jobs:
|
||||||
|
add-dev-comment:
|
||||||
|
if: "github.event.label.name == 'needs: developer feedback'"
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
issues: write
|
||||||
|
steps:
|
||||||
|
- name: Add developer feedback comment
|
||||||
|
uses: actions/github-script@v5
|
||||||
|
with:
|
||||||
|
github-token: ${{ secrets.WC_BOT_TRIAGE_TOKEN }}
|
||||||
|
script: |
|
||||||
|
github.rest.issues.createComment({
|
||||||
|
issue_number: context.issue.number,
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
body: 'Hi @${{ github.event.issue.user.login }},\n\n\
|
||||||
|
Thank you for opening the issue! It requires further feedback from the WooCommerce Core team.\n\n\
|
||||||
|
We are adding the `needs developer feedback` label to this issue so that the Core team could take a look.\n\n\
|
||||||
|
Please note it may take a few days for them to get to this issue. Thank you for your patience.'
|
||||||
|
})
|
||||||
|
add-reproduction-comment:
|
||||||
|
if: "github.event.label.name == 'status: reproduction'"
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
issues: write
|
||||||
|
steps:
|
||||||
|
- name: Add needs reproduction comment
|
||||||
|
uses: actions/github-script@v5
|
||||||
|
with:
|
||||||
|
github-token: ${{ secrets.WC_BOT_TRIAGE_TOKEN }}
|
||||||
|
script: |
|
||||||
|
github.rest.issues.createComment({
|
||||||
|
issue_number: context.issue.number,
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
body: 'We are adding the `status: needs reproduction` label to this issue to try reproduce it on the \
|
||||||
|
current released version of WooCommerce.\n\n\
|
||||||
|
Thank you for your patience.'
|
||||||
|
})
|
||||||
|
add-support-comment:
|
||||||
|
if: "github.event.label.name == 'type: support request'"
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
issues: write
|
||||||
|
steps:
|
||||||
|
- name: Add support request comment
|
||||||
|
uses: actions/github-script@v5
|
||||||
|
with:
|
||||||
|
github-token: ${{ secrets.WC_BOT_TRIAGE_TOKEN }}
|
||||||
|
script: |
|
||||||
|
github.rest.issues.createComment({
|
||||||
|
issue_number: context.issue.number,
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
body: 'Hi @${{ github.event.issue.user.login }},\n\n\
|
||||||
|
While our goal is to address all the issues reported in this repository, \
|
||||||
|
GitHub should be treated as a place to report confirmed bugs only.\n\n\
|
||||||
|
The type of issue you submitted looks like a support request which may or may not reveal a bug once proper \
|
||||||
|
troubleshooting is done. In order to confirm the bug, please follow one of the steps below:\n\n\
|
||||||
|
- Review [WooCommerce Self-Service Guide](https://docs.woocommerce.com/document/woocommerce-self-service-guide/) \
|
||||||
|
to see if the solutions listed there apply to your case;\n\
|
||||||
|
- If you are a paying customer of WooCommerce, contact WooCommerce support by \
|
||||||
|
[opening a ticket or starting a live chat](https://woocommerce.com/contact-us/);\n\
|
||||||
|
- Make a post on [WooCommerce community forum](https://wordpress.org/support/plugin/woocommerce/)\n\n\
|
||||||
|
If you confirm the bug, please provide us with clear steps to reproduce it.\n\n\
|
||||||
|
We are closing this issue for now as it seems to be a support request and not a bug. \
|
||||||
|
If we missed something, please leave a comment and we will take a second look.'
|
||||||
|
})
|
||||||
|
- name: Close support request issue
|
||||||
|
uses: actions/github-script@v5
|
||||||
|
with:
|
||||||
|
github-token: ${{ secrets.WC_BOT_TRIAGE_TOKEN }}
|
||||||
|
script: |
|
||||||
|
github.rest.issues.update({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
issue_number: context.issue.number,
|
||||||
|
state: 'closed'
|
||||||
|
})
|
||||||
|
add-votes-comment:
|
||||||
|
if: "github.event.label.name == 'needs: votes'"
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
issues: write
|
||||||
|
steps:
|
||||||
|
- name: Add votes needed comment
|
||||||
|
uses: actions/github-script@v5
|
||||||
|
with:
|
||||||
|
github-token: ${{ secrets.WC_BOT_TRIAGE_TOKEN }}
|
||||||
|
script: |
|
||||||
|
github.rest.issues.createComment({
|
||||||
|
issue_number: context.issue.number,
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
body: "Thanks for the suggestion @${{ github.event.issue.user.login }},\n\n\
|
||||||
|
While we appreciate you sharing your ideas with us, it doesn't fit in with our current priorities for the project.\n\
|
||||||
|
At some point, we may revisit our priorities and look through the list of suggestions like this one to see if it \
|
||||||
|
warrants a second look.\n\n\
|
||||||
|
In the meantime, we are going to close this issue with the `votes needed` label and evaluate over time if this \
|
||||||
|
issue collects more feedback.\n\n\
|
||||||
|
Don't be alarmed if you don't see any activity on this issue for a while. \
|
||||||
|
We'll keep an eye on the popularity of this request."
|
||||||
|
})
|
||||||
|
- name: Close votes needed issue
|
||||||
|
uses: actions/github-script@v5
|
||||||
|
with:
|
||||||
|
github-token: ${{ secrets.WC_BOT_TRIAGE_TOKEN }}
|
||||||
|
script: |
|
||||||
|
github.rest.issues.update({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
issue_number: context.issue.number,
|
||||||
|
state: 'closed'
|
||||||
|
})
|
||||||
|
fill-template-comment:
|
||||||
|
if: "github.event.label.name == 'needs: template'"
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
issues: write
|
||||||
|
steps:
|
||||||
|
- name: Add reply to fill template
|
||||||
|
uses: actions/github-script@v5
|
||||||
|
with:
|
||||||
|
github-token: ${{ secrets.WC_BOT_TRIAGE_TOKEN }}
|
||||||
|
script: |
|
||||||
|
github.rest.issues.createComment({
|
||||||
|
issue_number: context.issue.number,
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
body: "Hi @${{ github.event.issue.user.login }},\n\n\
|
||||||
|
Thank you for submitting the issue. However, you didn't fill out the details of the bug report template that we ask for. Without these details, we can't fully evaluate this issue. Please provide us with the information requested so we could take a look further.\n\n\
|
||||||
|
**Describe the bug**\n\n\
|
||||||
|
A clear and concise description of what the bug is. Please be as descriptive as possible; issues lacking detail, or for any other reason than to report a bug, may be closed without action.\n\n\
|
||||||
|
**To Reproduce**\n\n\
|
||||||
|
Steps to reproduce the behavior:\n\n\
|
||||||
|
1. Go to '...'\n\
|
||||||
|
2. Click on '....'\n\
|
||||||
|
3. Scroll down to '....'\n\
|
||||||
|
4. See error\n\n\
|
||||||
|
**Screenshots**\n\n\
|
||||||
|
If applicable, add screenshots to help explain your problem.\n\n\
|
||||||
|
**Expected behavior**\n\n\
|
||||||
|
A clear and concise description of what you expected to happen.\n\n\
|
||||||
|
**Isolating the problem (mark completed items with an [x]):**\n\n\
|
||||||
|
- [ ] I have deactivated other plugins and confirmed this bug occurs when only WooCommerce plugin is active.\n\
|
||||||
|
- [ ] This bug happens with a default WordPress theme active, or [Storefront](https://woocommerce.com/storefront/).\n\
|
||||||
|
- [ ] I can reproduce this bug consistently using the steps above.\n\n\
|
||||||
|
**WordPress Environment**\n\n\
|
||||||
|
Copy and paste the system status report from **WooCommerce > System Status** in WordPress admin."
|
||||||
|
})
|
||||||
|
- name: remove-needs-template-label
|
||||||
|
uses: actions-ecosystem/action-remove-labels@v1
|
||||||
|
with:
|
||||||
|
github-token: ${{ secrets.WC_BOT_TRIAGE_TOKEN }}
|
||||||
|
labels: 'needs: template'
|
||||||
|
- name: add-needs-author-feedback-label
|
||||||
|
uses: actions-ecosystem/action-add-labels@v1
|
||||||
|
with:
|
||||||
|
github-token: ${{ secrets.WC_BOT_TRIAGE_TOKEN }}
|
||||||
|
labels: 'needs: author feedback'
|
|
@ -0,0 +1,28 @@
|
||||||
|
name: 'Update contributor feedback labels on comment'
|
||||||
|
on: 'issue_comment'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
feedback:
|
||||||
|
if: |
|
||||||
|
github.actor != 'github-actions' &&
|
||||||
|
github.actor == github.event.issue.user.login &&
|
||||||
|
github.event.issue &&
|
||||||
|
github.event.issue.state == 'open' &&
|
||||||
|
contains(github.event.issue.labels.*.name, 'needs: author feedback')
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Add has feedback
|
||||||
|
uses: actions-ecosystem/action-add-labels@v1
|
||||||
|
with:
|
||||||
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
labels: 'needs: triage feedback'
|
||||||
|
- name: remove needs feedback
|
||||||
|
uses: actions-ecosystem/action-remove-labels@v1
|
||||||
|
with:
|
||||||
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
labels: 'needs: author feedback'
|
||||||
|
- name: remove stale
|
||||||
|
uses: actions-ecosystem/action-remove-labels@v1
|
||||||
|
with:
|
||||||
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
labels: 'status: stale'
|
|
@ -1,78 +1,85 @@
|
||||||
# Editors
|
# Operating System files
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# IDE files
|
||||||
|
.idea
|
||||||
|
.vscode/*
|
||||||
project.xml
|
project.xml
|
||||||
project.properties
|
project.properties
|
||||||
/nbproject/private/
|
|
||||||
.buildpath
|
|
||||||
.project
|
.project
|
||||||
.settings*
|
.settings*
|
||||||
.idea
|
|
||||||
.vscode
|
|
||||||
*.sublime-project
|
*.sublime-project
|
||||||
*.sublime-workspace
|
*.sublime-workspace
|
||||||
.sublimelinterrc
|
.sublimelinterrc
|
||||||
*.swp
|
|
||||||
|
# Excluded IDE Files for developer experience tooling within workspace
|
||||||
|
!.vscode/tasks.json
|
||||||
|
|
||||||
# Grunt
|
# Grunt
|
||||||
node_modules/
|
|
||||||
none
|
none
|
||||||
|
|
||||||
# Sass
|
# Sass
|
||||||
.sass-cache/
|
.sass-cache/
|
||||||
|
|
||||||
# Compiled CSS
|
# Logs
|
||||||
/assets/css/*.css
|
logs/
|
||||||
/assets/css/photoswipe/**/*.min.css
|
|
||||||
|
|
||||||
# Minified JS
|
# Eslint Cache
|
||||||
/assets/js/**/*.min.js
|
.eslintcache
|
||||||
|
|
||||||
# OS X metadata
|
# Environment files
|
||||||
.DS_Store
|
wp-cli.local.yml
|
||||||
|
yarn-error.log
|
||||||
|
npm-debug.log
|
||||||
|
.pnpm-debug.log
|
||||||
|
|
||||||
# Windows junk
|
# Build files
|
||||||
Thumbs.db
|
*.sql
|
||||||
|
*.swp
|
||||||
|
*.zip
|
||||||
|
|
||||||
# Behat/CLI Tests
|
# Built packages
|
||||||
tests/cli/installer
|
build/
|
||||||
tests/cli/composer.phar
|
build-module/
|
||||||
tests/cli/composer.lock
|
build-style/
|
||||||
tests/cli/composer.json
|
build-types/
|
||||||
tests/cli/vendor
|
dist/
|
||||||
|
|
||||||
|
# Project files
|
||||||
|
node_modules/
|
||||||
|
vendor/
|
||||||
|
|
||||||
|
# TypeScript files
|
||||||
|
tsconfig.tsbuildinfo
|
||||||
|
|
||||||
|
# Node Package Dependencies
|
||||||
|
package-lock.json
|
||||||
|
|
||||||
|
# wp-env config
|
||||||
|
.wp-env.override.json
|
||||||
|
|
||||||
# Unit tests
|
# Unit tests
|
||||||
/tmp
|
tmp/
|
||||||
/tests/bin/tmp
|
|
||||||
/tests/e2e/config/local-*.json
|
|
||||||
/tests/e2e/config/local.json
|
|
||||||
/tests/e2e/config/default.json
|
|
||||||
/tests/e2e/env/config/default.json
|
|
||||||
/tests/e2e/docker
|
|
||||||
/tests/e2e/env/docker/wp-cli/initialize.sh
|
|
||||||
/tests/e2e/env/build/
|
|
||||||
/tests/e2e/env/build-module/
|
|
||||||
/tests/e2e/utils/build/
|
|
||||||
/tests/e2e/utils/build-module/
|
|
||||||
|
|
||||||
# Logs
|
|
||||||
/logs
|
|
||||||
|
|
||||||
# Composer
|
# Composer
|
||||||
/vendor/
|
vendor/
|
||||||
/bin/composer/**/vendor/
|
bin/composer/**/vendor/
|
||||||
/lib/vendor/
|
lib/vendor/
|
||||||
contributors.md
|
contributors.md
|
||||||
contributors.html
|
contributors.html
|
||||||
|
|
||||||
# Packages
|
# Yarn
|
||||||
/packages/*
|
yarn.lock
|
||||||
!/packages/README.md
|
|
||||||
|
|
||||||
# Screenshots for e2e tests failures
|
# Editors
|
||||||
/screenshots/
|
nbproject/private/
|
||||||
|
|
||||||
# Language files
|
# Test Results
|
||||||
i18n/languages/woocommerce.pot
|
test-results.json
|
||||||
|
|
||||||
# Build
|
# Admin Feature config
|
||||||
build/
|
plugins/woocommerce/includes/react-admin/feature-config.php
|
||||||
woocommerce.zip
|
|
||||||
|
# PHP lint
|
||||||
|
phpcs-report.xml
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
#!/bin/sh
|
||||||
|
. "$(dirname "$0")/_/husky.sh"
|
||||||
|
|
||||||
|
pnpm install
|
||||||
|
pnpm nx affected --target="composer-install" --base=ORIG_HEAD --head=HEAD
|
|
@ -0,0 +1,4 @@
|
||||||
|
#!/bin/sh
|
||||||
|
. "$(dirname "$0")/_/husky.sh"
|
||||||
|
|
||||||
|
pnpm exec lint-staged
|
|
@ -0,0 +1,4 @@
|
||||||
|
#!/bin/sh
|
||||||
|
. "$(dirname "$0")/_/husky.sh"
|
||||||
|
|
||||||
|
./bin/pre-push.sh
|
|
@ -0,0 +1,3 @@
|
||||||
|
// Import the default config file and expose it in the project root.
|
||||||
|
// Useful for editor integrations.
|
||||||
|
module.exports = require( '@wordpress/prettier-config' );
|
|
@ -1,3 +1,3 @@
|
||||||
{
|
{
|
||||||
"extends": "stylelint-config-wordpress",
|
"extends": "@wordpress/stylelint-config",
|
||||||
}
|
}
|
||||||
|
|
110
.travis.yml
|
@ -1,110 +0,0 @@
|
||||||
version: ~> 1.0
|
|
||||||
|
|
||||||
# Specifies that Travis should create builds for master and release branches and also tags.
|
|
||||||
branches:
|
|
||||||
only:
|
|
||||||
- master
|
|
||||||
- /^\d+\.\d+(\.\d+)?(-\S*)?$/
|
|
||||||
- /^release\//
|
|
||||||
|
|
||||||
language: php
|
|
||||||
os:
|
|
||||||
- linux
|
|
||||||
dist: xenial
|
|
||||||
|
|
||||||
# Test main supported versions of PHP against latest WP.
|
|
||||||
php:
|
|
||||||
- "7.0"
|
|
||||||
- "7.1"
|
|
||||||
- "7.2"
|
|
||||||
- "7.3"
|
|
||||||
- "7.4"
|
|
||||||
- "8.0"
|
|
||||||
|
|
||||||
env:
|
|
||||||
- WP_VERSION=latest WP_MULTISITE=0
|
|
||||||
|
|
||||||
# Additional tests against stable PHP (min version is 7.0)
|
|
||||||
# and code coverage report.
|
|
||||||
jobs:
|
|
||||||
fast_finish: true
|
|
||||||
include:
|
|
||||||
- name: "Core E2E Tests"
|
|
||||||
env: WP_VERSION=latest WP_MULTISITE=0 RUN_E2E=1
|
|
||||||
install:
|
|
||||||
- nvm install
|
|
||||||
- npm install
|
|
||||||
- composer install --no-dev
|
|
||||||
script:
|
|
||||||
- npm run build:assets
|
|
||||||
- npm run docker:up
|
|
||||||
- npm run test:e2e
|
|
||||||
after_script:
|
|
||||||
- npm run docker:down
|
|
||||||
- name: "WP Nightly"
|
|
||||||
php: "7.4"
|
|
||||||
env: WP_VERSION=nightly WP_MULTISITE=0
|
|
||||||
- name: "WP Latest - 1"
|
|
||||||
php: "7.2"
|
|
||||||
env: WP_VERSION=5.5 WP_MULTISITE=0
|
|
||||||
- name: "WP Latest - 2"
|
|
||||||
php: "7.2"
|
|
||||||
env: WP_VERSION=5.4 WP_MULTISITE=0
|
|
||||||
- name: "Code Standards"
|
|
||||||
php: "7.4"
|
|
||||||
env: WP_VERSION=latest WP_MULTISITE=0 RUN_PHPCS=1
|
|
||||||
- name: "Code Coverage"
|
|
||||||
php: "7.4"
|
|
||||||
env: WP_VERSION=latest WP_MULTISITE=0 RUN_CODE_COVERAGE=1
|
|
||||||
allow_failures:
|
|
||||||
- php: "7.4"
|
|
||||||
env: WP_VERSION=latest WP_MULTISITE=0 RUN_CODE_COVERAGE=1
|
|
||||||
|
|
||||||
# Git clone depth
|
|
||||||
# By default Travis CI clones repositories to a depth of 50 commits. Using a depth of 1 makes this step a bit faster.
|
|
||||||
git:
|
|
||||||
depth: 1
|
|
||||||
|
|
||||||
# Since Xenial services are not started by default, we need to instruct it below to start.
|
|
||||||
services:
|
|
||||||
- mysql
|
|
||||||
- docker
|
|
||||||
|
|
||||||
cache:
|
|
||||||
directories:
|
|
||||||
- $HOME/.composer/cache
|
|
||||||
|
|
||||||
# Composer 2.0.7 introduced a change that broke the jetpack autoloader in PHP 7.0 - 7.3.
|
|
||||||
before_install:
|
|
||||||
- composer self-update 2.0.6
|
|
||||||
|
|
||||||
install:
|
|
||||||
- export PATH="$HOME/.composer/vendor/bin:$PATH"
|
|
||||||
- |
|
|
||||||
# Remove Xdebug for a huge performance increase:
|
|
||||||
if [ -f ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/xdebug.ini ]; then
|
|
||||||
phpenv config-rm xdebug.ini
|
|
||||||
else
|
|
||||||
echo "xdebug.ini does not exist"
|
|
||||||
fi
|
|
||||||
- composer install
|
|
||||||
- |
|
|
||||||
if [ "$(php -r "echo version_compare(PHP_VERSION,'8.0','>=');")" ]; then
|
|
||||||
curl -L https://github.com/woocommerce/phpunit/archive/add-compatibility-with-php8-to-phpunit-7.zip -o /tmp/phpunit-7.5-fork.zip
|
|
||||||
unzip -d /tmp/phpunit-7.5-fork /tmp/phpunit-7.5-fork.zip
|
|
||||||
composer bin phpunit config --unset platform
|
|
||||||
composer bin phpunit config repositories.0 '{"type": "path", "url": "/tmp/phpunit-7.5-fork/phpunit-add-compatibility-with-php8-to-phpunit-7", "options": {"symlink": false}}'
|
|
||||||
composer bin phpunit require --dev -W phpunit/phpunit:@dev --ignore-platform-reqs
|
|
||||||
fi
|
|
||||||
- |
|
|
||||||
# Install WP Test suite:
|
|
||||||
if [[ ! -z "$WP_VERSION" ]]; then
|
|
||||||
bash tests/bin/install.sh woocommerce_test root '' localhost $WP_VERSION
|
|
||||||
fi
|
|
||||||
|
|
||||||
script:
|
|
||||||
- bash tests/bin/phpunit.sh
|
|
||||||
- bash tests/bin/phpcs.sh
|
|
||||||
|
|
||||||
after_script:
|
|
||||||
- bash tests/bin/travis.sh after
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
{
|
||||||
|
"version": "2.0.0",
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"command": "pnpm tsc -b tsconfig.base.json",
|
||||||
|
"type": "shell",
|
||||||
|
"problemMatcher": [ "$tsc" ],
|
||||||
|
"label": "Typescript compile",
|
||||||
|
"detail": "Run tsc against tsconfig.base.json",
|
||||||
|
"runOptions": {
|
||||||
|
"runOn": "default"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "pnpm tsc -b tsconfig.base.json --watch",
|
||||||
|
"type": "shell",
|
||||||
|
"problemMatcher": {
|
||||||
|
"base": "$tsc-watch",
|
||||||
|
"applyTo": "allDocuments"
|
||||||
|
},
|
||||||
|
"isBackground": true,
|
||||||
|
"label": "Incremental Typescript compile",
|
||||||
|
"detail": "Incremental background type checks",
|
||||||
|
"runOptions": {
|
||||||
|
"runOn": "folderOpen"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,138 @@
|
||||||
|
# WooCommerce Development Setup with WP-ENV
|
||||||
|
|
||||||
|
Docker development setup for WooCommerce with WP-ENV.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
Please install WP-ENV before getting started. You can find more about WP-ENV on [here](https://github.com/WordPress/gutenberg/tree/master/packages/env).
|
||||||
|
|
||||||
|
The following command installs WP-ENV globally.
|
||||||
|
|
||||||
|
`npm -g i @wordpress/env`
|
||||||
|
|
||||||
|
If you don't already have [pnpm](https://pnpm.io/installation) installed, you can quickly add it using NPM.
|
||||||
|
|
||||||
|
`npm install -g pnpm`
|
||||||
|
|
||||||
|
## Starting WP-ENV
|
||||||
|
|
||||||
|
1. Navigate to the root of WooCommerce source code.
|
||||||
|
2. Start the docker container by running `wp-env start`
|
||||||
|
|
||||||
|
You should see the following output
|
||||||
|
|
||||||
|
```
|
||||||
|
WordPress development site started at http://localhost:8888/
|
||||||
|
WordPress test site started at http://localhost:8889/
|
||||||
|
MySQL is listening on port 55003
|
||||||
|
```
|
||||||
|
|
||||||
|
The port # might be different depending on your `.wp-env.override.json` configuration.
|
||||||
|
|
||||||
|
## Getting Started with Developing
|
||||||
|
|
||||||
|
Once you have WP-ENV container up, we need to run a few commands to start developing.
|
||||||
|
|
||||||
|
1. Run `pnpm install` to install npm modules.
|
||||||
|
2. Run `pnpm nx build woocommerce` to build core.
|
||||||
|
3. Run `pnpm nx composer-install woocommerce` to install PHP dependencies.
|
||||||
|
|
||||||
|
If you don't have Composer available locally, run the following command. It runs the command in WP-ENV container.
|
||||||
|
|
||||||
|
`wp-env run composer composer install`
|
||||||
|
|
||||||
|
You might also want to run `pnpm start` to watch your CSS and JS changes if you are working on the frontend.
|
||||||
|
|
||||||
|
You're now ready to develop!
|
||||||
|
|
||||||
|
### Typescript Checking
|
||||||
|
|
||||||
|
Typescript is progressively being implemented in this repository, and you might come across some files that are `.ts` or `.tsx`. By default, a VSCode environment will run type checking on such files that are currently open.
|
||||||
|
|
||||||
|
As of now, some parts of the codebase that were imported from the Woocommerce-Admin repository, into the `plugins/woocommerce-admin/client` directory, still fail Typescript checking. This has been scheduled on the team's backlog to be fixed.
|
||||||
|
|
||||||
|
In order to run type checking across the entire repository, you can run this command in your shell, from the root of this repository:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
pnpm tsc -b tsconfig.base.json
|
||||||
|
```
|
||||||
|
|
||||||
|
For better developer experience, the folder `.vscode/tasks.json` has two VSCode tasks to run these commands automatically as well as to parse the output and highlight the errors in the `Problems` tab and in the file explorer pane. The first task runs it once, the second one runs it in the background upon saving of any modified files. This task is also automatically prompted by VSCode to be run upon opening the folder.
|
||||||
|
|
||||||
|
|
||||||
|
## Using Xdebug
|
||||||
|
|
||||||
|
Please refer to [WP-ENV official README](https://github.com/WordPress/gutenberg/tree/master/packages/env#using-xdebug) section for setting up Xdebug.
|
||||||
|
|
||||||
|
## Overriding the Default Configuration
|
||||||
|
|
||||||
|
The default configuration comes with PHP 7.4, WooCommerce 5.0, and a few WordPress config values.
|
||||||
|
|
||||||
|
You can create `.wp-env.override.json` file and override the default configuration values.
|
||||||
|
|
||||||
|
You can find more about `.wp-env.override.json` configuration [here](https://github.com/WordPress/gutenberg/tree/master/packages/env#wp-envoverridejson).
|
||||||
|
|
||||||
|
**Example: Overriding PHP version to 8.0**
|
||||||
|
|
||||||
|
Create `.wp-env.override.json` in the root directory with the following content.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"phpVersion": "8.0"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Exampe: Adding a locally installed plugin**
|
||||||
|
|
||||||
|
Method 1 - Adding to the `plugins` array
|
||||||
|
|
||||||
|
Open the default `.wp-env.json` and copy `plugins` array and paste it into the `.wp-env.override.json` and add your locally installed plugin. Copying the default `plugins` is needed as WP-ENV does not merge the values of the `plugins`.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"plugins": [
|
||||||
|
"./plugins/woocommerce",
|
||||||
|
"https://downloads.wordpress.org/plugin/wp-crontrol.1.10.0.zip"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Method 2 - Adding to the `mappings`
|
||||||
|
|
||||||
|
This method is simpler, but the plugin does not get activated on startup. You need to manually activate it yourself on the first startup.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mappings": {
|
||||||
|
"wp-content/plugins/wp-crontrol": "../woocommerce"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Accessing MySQL
|
||||||
|
|
||||||
|
The MySQL port can change when you restart your container.
|
||||||
|
|
||||||
|
You can get the current MySQL port from the output of `wp-env start` command.
|
||||||
|
|
||||||
|
1. Open your choice of MySQL tool.
|
||||||
|
2. Use the following values to access the MySQL container.
|
||||||
|
|
||||||
|
| Name | Value |
|
||||||
|
| -------- | --------------------- |
|
||||||
|
| Host | 127.0.0.1 |
|
||||||
|
| Username | root |
|
||||||
|
| Password | password |
|
||||||
|
| Port | Port from the command |
|
||||||
|
|
||||||
|
## HOWTOs
|
||||||
|
|
||||||
|
##### How do I ssh into the container?
|
||||||
|
|
||||||
|
Run the following command to ssh into the container
|
||||||
|
`wp-env run wordpress /bin/bash`
|
||||||
|
|
||||||
|
You can run a command in the container with the following syntax. You can find more about on the `run` command [here](https://github.com/WordPress/gutenberg/tree/master/packages/env#wp-env-run-container-command)
|
||||||
|
|
||||||
|
Syntax:
|
||||||
|
`wp-env run :container-type :linux-command`
|
231
Gruntfile.js
|
@ -1,231 +0,0 @@
|
||||||
module.exports = function( grunt ) {
|
|
||||||
'use strict';
|
|
||||||
var sass = require( 'node-sass' );
|
|
||||||
|
|
||||||
grunt.initConfig({
|
|
||||||
|
|
||||||
// Setting folder templates.
|
|
||||||
dirs: {
|
|
||||||
css: 'assets/css',
|
|
||||||
fonts: 'assets/fonts',
|
|
||||||
images: 'assets/images',
|
|
||||||
js: 'assets/js',
|
|
||||||
php: 'includes'
|
|
||||||
},
|
|
||||||
|
|
||||||
// JavaScript linting with ESLint.
|
|
||||||
eslint: {
|
|
||||||
src: [
|
|
||||||
'<%= dirs.js %>/admin/*.js',
|
|
||||||
'!<%= dirs.js %>/admin/*.min.js',
|
|
||||||
'<%= dirs.js %>/frontend/*.js',
|
|
||||||
'!<%= dirs.js %>/frontend/*.min.js'
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
// Sass linting with Stylelint.
|
|
||||||
stylelint: {
|
|
||||||
options: {
|
|
||||||
configFile: '.stylelintrc'
|
|
||||||
},
|
|
||||||
all: [
|
|
||||||
'<%= dirs.css %>/*.scss',
|
|
||||||
'!<%= dirs.css %>/select2.scss'
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
// Minify .js files.
|
|
||||||
uglify: {
|
|
||||||
options: {
|
|
||||||
ie8: true,
|
|
||||||
parse: {
|
|
||||||
strict: false
|
|
||||||
},
|
|
||||||
output: {
|
|
||||||
comments : /@license|@preserve|^!/
|
|
||||||
}
|
|
||||||
},
|
|
||||||
js_assets: {
|
|
||||||
files: [{
|
|
||||||
expand: true,
|
|
||||||
cwd: '<%= dirs.js %>/',
|
|
||||||
src: [
|
|
||||||
'**/*.js',
|
|
||||||
'!**/*.min.js'
|
|
||||||
],
|
|
||||||
extDot: 'last',
|
|
||||||
dest: '<%= dirs.js %>',
|
|
||||||
ext: '.min.js'
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// Compile all .scss files.
|
|
||||||
sass: {
|
|
||||||
compile: {
|
|
||||||
options: {
|
|
||||||
implementation: sass,
|
|
||||||
sourceMap: 'none'
|
|
||||||
},
|
|
||||||
files: [{
|
|
||||||
expand: true,
|
|
||||||
cwd: '<%= dirs.css %>/',
|
|
||||||
src: ['*.scss'],
|
|
||||||
dest: '<%= dirs.css %>/',
|
|
||||||
ext: '.css'
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// Generate RTL .css files.
|
|
||||||
rtlcss: {
|
|
||||||
woocommerce: {
|
|
||||||
expand: true,
|
|
||||||
cwd: '<%= dirs.css %>',
|
|
||||||
src: [
|
|
||||||
'*.css',
|
|
||||||
'!select2.css',
|
|
||||||
'!*-rtl.css'
|
|
||||||
],
|
|
||||||
dest: '<%= dirs.css %>/',
|
|
||||||
ext: '-rtl.css'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// Minify all .css files.
|
|
||||||
cssmin: {
|
|
||||||
minify: {
|
|
||||||
files: [
|
|
||||||
{
|
|
||||||
expand: true,
|
|
||||||
cwd: '<%= dirs.css %>/',
|
|
||||||
src: ['*.css'],
|
|
||||||
dest: '<%= dirs.css %>/',
|
|
||||||
ext: '.css'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
expand: true,
|
|
||||||
cwd: '<%= dirs.css %>/photoswipe/',
|
|
||||||
src: ['*.css', '!*.min.css'],
|
|
||||||
dest: '<%= dirs.css %>/photoswipe/',
|
|
||||||
ext: '.min.css'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
expand: true,
|
|
||||||
cwd: '<%= dirs.css %>/photoswipe/default-skin/',
|
|
||||||
src: ['*.css', '!*.min.css'],
|
|
||||||
dest: '<%= dirs.css %>/photoswipe/default-skin/',
|
|
||||||
ext: '.min.css'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// Concatenate select2.css onto the admin.css files.
|
|
||||||
concat: {
|
|
||||||
admin: {
|
|
||||||
files: {
|
|
||||||
'<%= dirs.css %>/admin.css' : ['<%= dirs.css %>/select2.css', '<%= dirs.css %>/admin.css'],
|
|
||||||
'<%= dirs.css %>/admin-rtl.css' : ['<%= dirs.css %>/select2.css', '<%= dirs.css %>/admin-rtl.css']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// Watch changes for assets.
|
|
||||||
watch: {
|
|
||||||
css: {
|
|
||||||
files: ['<%= dirs.css %>/*.scss'],
|
|
||||||
tasks: ['sass', 'rtlcss', 'postcss', 'cssmin', 'concat']
|
|
||||||
},
|
|
||||||
js: {
|
|
||||||
files: [
|
|
||||||
'GruntFile.js',
|
|
||||||
'<%= dirs.js %>/**/*.js',
|
|
||||||
'!<%= dirs.js %>/**/*.min.js'
|
|
||||||
],
|
|
||||||
tasks: ['eslint','newer:uglify']
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// PHP Code Sniffer.
|
|
||||||
phpcs: {
|
|
||||||
options: {
|
|
||||||
bin: 'vendor/bin/phpcs'
|
|
||||||
},
|
|
||||||
dist: {
|
|
||||||
src: [
|
|
||||||
'**/*.php', // Include all php files.
|
|
||||||
'!includes/api/legacy/**',
|
|
||||||
'!includes/libraries/**',
|
|
||||||
'!node_modules/**',
|
|
||||||
'!tests/cli/**',
|
|
||||||
'!tmp/**',
|
|
||||||
'!vendor/**'
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// Autoprefixer.
|
|
||||||
postcss: {
|
|
||||||
options: {
|
|
||||||
processors: [
|
|
||||||
require( 'autoprefixer' )
|
|
||||||
]
|
|
||||||
},
|
|
||||||
dist: {
|
|
||||||
src: [
|
|
||||||
'<%= dirs.css %>/*.css'
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Load NPM tasks to be used here.
|
|
||||||
grunt.loadNpmTasks( 'grunt-sass' );
|
|
||||||
grunt.loadNpmTasks( 'grunt-phpcs' );
|
|
||||||
grunt.loadNpmTasks( 'grunt-rtlcss' );
|
|
||||||
grunt.loadNpmTasks( 'grunt-postcss' );
|
|
||||||
grunt.loadNpmTasks( 'grunt-stylelint' );
|
|
||||||
grunt.loadNpmTasks( 'gruntify-eslint' );
|
|
||||||
grunt.loadNpmTasks( 'grunt-contrib-uglify' );
|
|
||||||
grunt.loadNpmTasks( 'grunt-contrib-cssmin' );
|
|
||||||
grunt.loadNpmTasks( 'grunt-contrib-concat' );
|
|
||||||
grunt.loadNpmTasks( 'grunt-contrib-copy' );
|
|
||||||
grunt.loadNpmTasks( 'grunt-contrib-watch' );
|
|
||||||
grunt.loadNpmTasks( 'grunt-contrib-clean' );
|
|
||||||
grunt.loadNpmTasks( 'grunt-newer' );
|
|
||||||
|
|
||||||
// Register tasks.
|
|
||||||
grunt.registerTask( 'default', [
|
|
||||||
'js',
|
|
||||||
'css'
|
|
||||||
]);
|
|
||||||
|
|
||||||
grunt.registerTask( 'js', [
|
|
||||||
'eslint',
|
|
||||||
'uglify:js_assets'
|
|
||||||
]);
|
|
||||||
|
|
||||||
grunt.registerTask( 'css', [
|
|
||||||
'sass',
|
|
||||||
'rtlcss',
|
|
||||||
'postcss',
|
|
||||||
'cssmin',
|
|
||||||
'concat'
|
|
||||||
]);
|
|
||||||
|
|
||||||
grunt.registerTask( 'assets', [
|
|
||||||
'js',
|
|
||||||
'css'
|
|
||||||
]);
|
|
||||||
|
|
||||||
grunt.registerTask( 'e2e-build', [
|
|
||||||
'uglify:js_assets',
|
|
||||||
'css'
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Only an alias to 'default' task.
|
|
||||||
grunt.registerTask( 'dev', [
|
|
||||||
'default'
|
|
||||||
]);
|
|
||||||
};
|
|
13
README.md
|
@ -5,8 +5,8 @@
|
||||||
<a href="https://packagist.org/packages/woocommerce/woocommerce"><img src="https://poser.pugx.org/woocommerce/woocommerce/v/stable" alt="Latest Stable Version"></a>
|
<a href="https://packagist.org/packages/woocommerce/woocommerce"><img src="https://poser.pugx.org/woocommerce/woocommerce/v/stable" alt="Latest Stable Version"></a>
|
||||||
<img src="https://img.shields.io/wordpress/plugin/dt/woocommerce.svg" alt="WordPress.org downloads">
|
<img src="https://img.shields.io/wordpress/plugin/dt/woocommerce.svg" alt="WordPress.org downloads">
|
||||||
<img src="https://img.shields.io/wordpress/plugin/r/woocommerce.svg" alt="WordPress.org rating">
|
<img src="https://img.shields.io/wordpress/plugin/r/woocommerce.svg" alt="WordPress.org rating">
|
||||||
<a href="https://travis-ci.com/woocommerce/woocommerce"><img src="https://travis-ci.com/woocommerce/woocommerce.svg?branch=master" alt="Build Status"></a>
|
<a href="https://github.com/woocommerce/woocommerce/actions/workflows/ci.yml"><img src="https://github.com/woocommerce/woocommerce/actions/workflows/ci.yml/badge.svg?branch=trunk" alt="Build Status"></a>
|
||||||
<a href="https://codecov.io/gh/woocommerce/woocommerce"><img src="https://codecov.io/gh/woocommerce/woocommerce/branch/master/graph/badge.svg" alt="codecov"></a>
|
<a href="https://codecov.io/gh/woocommerce/woocommerce"><img src="https://codecov.io/gh/woocommerce/woocommerce/branch/trunk/graph/badge.svg" alt="codecov"></a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
Welcome to the WooCommerce repository on GitHub. Here you can browse the source, look at open issues and keep track of development. We recommend all developers to follow the [WooCommerce development blog](https://woocommerce.wordpress.com/) to stay up to date about everything happening in the project. You can also [follow @DevelopWC](https://twitter.com/DevelopWC) on Twitter for the latest development updates.
|
Welcome to the WooCommerce repository on GitHub. Here you can browse the source, look at open issues and keep track of development. We recommend all developers to follow the [WooCommerce development blog](https://woocommerce.wordpress.com/) to stay up to date about everything happening in the project. You can also [follow @DevelopWC](https://twitter.com/DevelopWC) on Twitter for the latest development updates.
|
||||||
|
@ -18,6 +18,7 @@ If you are not a developer, please use the [WooCommerce plugin page](https://wor
|
||||||
* [WooCommerce Developer Documentation](https://github.com/woocommerce/woocommerce/wiki)
|
* [WooCommerce Developer Documentation](https://github.com/woocommerce/woocommerce/wiki)
|
||||||
* [WooCommerce Code Reference](https://docs.woocommerce.com/wc-apidocs/)
|
* [WooCommerce Code Reference](https://docs.woocommerce.com/wc-apidocs/)
|
||||||
* [WooCommerce REST API Docs](https://woocommerce.github.io/woocommerce-rest-api-docs/)
|
* [WooCommerce REST API Docs](https://woocommerce.github.io/woocommerce-rest-api-docs/)
|
||||||
|
* [Setting up a development environment](https://github.com/woocommerce/woocommerce/wiki/How-to-set-up-WooCommerce-development-environment)
|
||||||
|
|
||||||
## Reporting Security Issues
|
## Reporting Security Issues
|
||||||
To disclose a security issue to our team, [please submit a report via HackerOne here](https://hackerone.com/automattic/).
|
To disclose a security issue to our team, [please submit a report via HackerOne here](https://hackerone.com/automattic/).
|
||||||
|
@ -34,4 +35,10 @@ This repository is not suitable for support. Please don't use our issue tracker
|
||||||
Support requests in issues on this repository will be closed on sight.
|
Support requests in issues on this repository will be closed on sight.
|
||||||
|
|
||||||
## Contributing to WooCommerce
|
## Contributing to WooCommerce
|
||||||
If you have a patch or have stumbled upon an issue with WooCommerce core, you can contribute this back to the code. Please read our [contributor guidelines](https://github.com/woocommerce/woocommerce/blob/master/.github/CONTRIBUTING.md) for more information how you can do this.
|
If you have a patch or have stumbled upon an issue with WooCommerce core, you can contribute this back to the code. Please read our [contributor guidelines](https://github.com/woocommerce/woocommerce/blob/trunk/.github/CONTRIBUTING.md) for more information how you can do this.
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<br/><br/>
|
||||||
|
Made with 💜 by <a href="https://woocommerce.com/">WooCommerce</a>.<br/>
|
||||||
|
<a href="https://woocommerce.com/careers/">We're hiring</a>! Come work with us!
|
||||||
|
</p>
|
||||||
|
|
|
@ -1,288 +0,0 @@
|
||||||
/**
|
|
||||||
* Deprecated
|
|
||||||
* Fallback for bourbon equivalent
|
|
||||||
*/
|
|
||||||
@mixin clearfix() {
|
|
||||||
*zoom: 1;
|
|
||||||
|
|
||||||
&::before,
|
|
||||||
&::after {
|
|
||||||
content: " ";
|
|
||||||
display: table;
|
|
||||||
}
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
clear: both;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deprecated
|
|
||||||
* Vendor prefix no longer required.
|
|
||||||
*/
|
|
||||||
@mixin border_radius($radius: 4px) {
|
|
||||||
border-radius: $radius;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deprecated
|
|
||||||
* Vendor prefix no longer required.
|
|
||||||
*/
|
|
||||||
@mixin border_radius_right($radius: 4px) {
|
|
||||||
border-top-right-radius: $radius;
|
|
||||||
border-bottom-right-radius: $radius;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deprecated
|
|
||||||
* Vendor prefix no longer required.
|
|
||||||
*/
|
|
||||||
@mixin border_radius_left($radius: 4px) {
|
|
||||||
border-top-left-radius: $radius;
|
|
||||||
border-bottom-left-radius: $radius;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deprecated
|
|
||||||
* Vendor prefix no longer required.
|
|
||||||
*/
|
|
||||||
@mixin border_radius_bottom($radius: 4px) {
|
|
||||||
border-bottom-left-radius: $radius;
|
|
||||||
border-bottom-right-radius: $radius;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deprecated
|
|
||||||
* Vendor prefix no longer required.
|
|
||||||
*/
|
|
||||||
@mixin border_radius_top($radius: 4px) {
|
|
||||||
border-top-left-radius: $radius;
|
|
||||||
border-top-right-radius: $radius;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deprecated
|
|
||||||
* Vendor prefix no longer required.
|
|
||||||
*/
|
|
||||||
@mixin opacity( $opacity: 0.75 ) {
|
|
||||||
opacity: $opacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deprecated
|
|
||||||
* Vendor prefix no longer required.
|
|
||||||
*/
|
|
||||||
@mixin box_shadow($shadow_x: 3px, $shadow_y: 3px, $shadow_rad: 3px, $shadow_in: 3px, $shadow_color: #888) {
|
|
||||||
box-shadow: $shadow_x $shadow_y $shadow_rad $shadow_in $shadow_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deprecated
|
|
||||||
* Vendor prefix no longer required.
|
|
||||||
*/
|
|
||||||
@mixin inset_box_shadow($shadow_x: 3px, $shadow_y: 3px, $shadow_rad: 3px, $shadow_in: 3px, $shadow_color: #888) {
|
|
||||||
box-shadow: inset $shadow_x $shadow_y $shadow_rad $shadow_in $shadow_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deprecated
|
|
||||||
* Vendor prefix no longer required.
|
|
||||||
*/
|
|
||||||
@mixin text_shadow($shadow_x: 3px, $shadow_y: 3px, $shadow_rad: 3px, $shadow_color: #fff) {
|
|
||||||
text-shadow: $shadow_x $shadow_y $shadow_rad $shadow_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deprecated
|
|
||||||
* Vendor prefix no longer required.
|
|
||||||
*/
|
|
||||||
@mixin vertical_gradient($from: #000, $to: #fff) {
|
|
||||||
background-color: $from;
|
|
||||||
background: -webkit-linear-gradient($from, $to);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deprecated
|
|
||||||
* Vendor prefix no longer required.
|
|
||||||
*/
|
|
||||||
@mixin transition($selector: all, $animation: ease-in-out, $duration: 0.2s) {
|
|
||||||
transition: $selector $animation $duration;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deprecated
|
|
||||||
* Use bourbon mixin instead `@include transform(scale(1.5));`
|
|
||||||
*/
|
|
||||||
@mixin scale($ratio: 1.5) {
|
|
||||||
-webkit-transform: scale($ratio);
|
|
||||||
transform: scale($ratio);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deprecated
|
|
||||||
* Use bourbon mixin instead `@include box-sizing(border-box);`
|
|
||||||
*/
|
|
||||||
@mixin borderbox() {
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
@mixin darkorlighttextshadow($a, $opacity: 0.8) {
|
|
||||||
|
|
||||||
@if lightness($a) >= 65% {
|
|
||||||
|
|
||||||
@include text_shadow(0, -1px, 0, rgba(0, 0, 0, $opacity));
|
|
||||||
}
|
|
||||||
|
|
||||||
@else {
|
|
||||||
|
|
||||||
@include text_shadow(0, 1px, 0, rgba(255, 255, 255, $opacity));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Objects
|
|
||||||
*/
|
|
||||||
@mixin menu() {
|
|
||||||
|
|
||||||
@include clearfix();
|
|
||||||
|
|
||||||
li {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@mixin mediaright() {
|
|
||||||
|
|
||||||
@include clearfix();
|
|
||||||
|
|
||||||
img {
|
|
||||||
float: right;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@mixin medialeft() {
|
|
||||||
|
|
||||||
@include clearfix();
|
|
||||||
|
|
||||||
img {
|
|
||||||
float: right;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@mixin ir() {
|
|
||||||
display: block;
|
|
||||||
text-indent: -9999px;
|
|
||||||
position: relative;
|
|
||||||
height: 1em;
|
|
||||||
width: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
@mixin icon( $glyph: "\e001" ) {
|
|
||||||
font-family: "WooCommerce";
|
|
||||||
speak: never;
|
|
||||||
font-weight: normal;
|
|
||||||
font-variant: normal;
|
|
||||||
text-transform: none;
|
|
||||||
line-height: 1;
|
|
||||||
margin: 0;
|
|
||||||
text-indent: 0;
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
text-align: center;
|
|
||||||
content: $glyph;
|
|
||||||
}
|
|
||||||
|
|
||||||
@mixin icon_dashicons( $glyph: "\f333" ) {
|
|
||||||
font-family: "Dashicons";
|
|
||||||
speak: never;
|
|
||||||
font-weight: normal;
|
|
||||||
font-variant: normal;
|
|
||||||
text-transform: none;
|
|
||||||
line-height: 1;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
margin: 0;
|
|
||||||
text-indent: 0;
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
text-align: center;
|
|
||||||
content: $glyph;
|
|
||||||
}
|
|
||||||
|
|
||||||
@mixin iconbefore( $glyph: "\e001" ) {
|
|
||||||
font-family: "WooCommerce";
|
|
||||||
speak: never;
|
|
||||||
font-weight: normal;
|
|
||||||
font-variant: normal;
|
|
||||||
text-transform: none;
|
|
||||||
line-height: 1;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
margin-right: 0.618em;
|
|
||||||
content: $glyph;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
@mixin iconbeforedashicons( $glyph: "\f333" ) {
|
|
||||||
font-family: "Dashicons";
|
|
||||||
speak: never;
|
|
||||||
font-weight: normal;
|
|
||||||
font-variant: normal;
|
|
||||||
text-transform: none;
|
|
||||||
line-height: 1;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
content: $glyph;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
@mixin iconafter( $glyph: "\e001" ) {
|
|
||||||
font-family: "WooCommerce";
|
|
||||||
speak: never;
|
|
||||||
font-weight: normal;
|
|
||||||
font-variant: normal;
|
|
||||||
text-transform: none;
|
|
||||||
line-height: 1;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
margin-left: 0.618em;
|
|
||||||
content: $glyph;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
@mixin loader() {
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
height: 1em;
|
|
||||||
width: 1em;
|
|
||||||
display: block;
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
margin-left: -0.5em;
|
|
||||||
margin-top: -0.5em;
|
|
||||||
content: "";
|
|
||||||
animation: spin 1s ease-in-out infinite;
|
|
||||||
background: url("../images/icons/loader.svg") center center;
|
|
||||||
background-size: cover;
|
|
||||||
line-height: 1;
|
|
||||||
text-align: center;
|
|
||||||
font-size: 2em;
|
|
||||||
color: rgba(#000, 0.75);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@mixin inversebuttoncolors {
|
|
||||||
background-color: transparent !important;
|
|
||||||
color: var(--button--color-text-hover) !important;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: var(--button--color-background) !important;
|
|
||||||
color: var(--button--color-text) !important;
|
|
||||||
text-decoration: none !important;
|
|
||||||
}
|
|
||||||
}
|
|
Before Width: | Height: | Size: 4.9 KiB |
Before Width: | Height: | Size: 4.8 KiB |
|
@ -1 +0,0 @@
|
||||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><defs><style>.cls-1{fill:#4267b2;}.cls-2{fill:#fff;}</style></defs><title>flogo_RGB_HEX-512</title><path class="cls-1" d="M483.74,0H28.26A28.26,28.26,0,0,0,0,28.26V483.74A28.26,28.26,0,0,0,28.26,512H273.5V314H207V236.5h66.5v-57c0-66.13,40.39-102.14,99.38-102.14,28.25,0,52.54,2.1,59.62,3v69.11l-40.68,0c-32.1,0-38.32,15.25-38.32,37.64V236.5h76.74l-10,77.5H353.5V512H483.74A28.26,28.26,0,0,0,512,483.74V28.26A28.26,28.26,0,0,0,483.74,0Z"/><path id="f" class="cls-2" d="M353.5,512V314h66.75l10-77.5H353.5V187.14c0-22.39,6.22-37.64,38.32-37.64l40.68,0V80.37c-7.08-.94-31.37-3-59.62-3-59,0-99.38,36-99.38,102.14v57H207V314h66.5V512Z"/></svg>
|
|
Before Width: | Height: | Size: 732 B |
Before Width: | Height: | Size: 5.4 KiB |
Before Width: | Height: | Size: 3.7 KiB |
|
@ -1 +0,0 @@
|
||||||
<svg viewBox="0 0 367 300" xmlns="http://www.w3.org/2000/svg"><path d="M251 135.1c-6.4 4.9-14.4 7.8-23 7.8-8.9 0-17-3.1-23.5-8.1-6.5 5.1-14.6 8.1-23.5 8.1s-17.1-3.1-23.6-8.2c-6.5 5.1-14.7 8.2-23.6 8.2s-17-3.1-23.5-8.1c-6.5 5.1-14.6 8.1-23.5 8.1-2 0-4-.2-6-.5v73.4c0 6.3 5.7 12 12 12h54.8c6.3 0 10.9-5.7 10.9-12v-30.7c6.9 2.2 14.1 3.5 22.8 3.5s17.1-1.3 22.8-3.5v30.7c0 6.3 5.7 12 12 12h54.8c6.3 0 10.9-5.7 10.9-12V142c-2.6.6-5.3.9-8 .9-8.4-.1-16.4-3-22.8-7.8zm-115.5 49.8c0 5-4.1 9.1-9.1 9.1h-14.1c-5 0-9.1-4.1-9.1-9.1v-14.1c0-5 4.1-9.1 9.1-9.1h14.1c5 0 9.1 4.1 9.1 9.1zm123.3 0c0 5-4.1 9.1-9.1 9.1h-14.1c-5 0-9.1-4.1-9.1-9.1v-14.1c0-5 4.1-9.1 9.1-9.1h14.1c5 0 9.1 4.1 9.1 9.1zm36.1-85l-30.1-30.1c-3.9-3.9-11.6-7.1-17.1-7.1H113.3c-5.5 0-13.2 3.2-17.1 7.1L66.1 99.9l-7 7c.9 12.5 10 22.7 21.9 25.3h.1c.4.1.9.2 1.3.3h.1c.4.1.8.1 1.3.2h.2c.4 0 .8.1 1.2.1H87c.7 0 1.4 0 2-.1.2 0 .4 0 .6-.1.5 0 .9-.1 1.4-.2.2 0 .5-.1.7-.1.4-.1.8-.1 1.2-.2.2-.1.5-.1.7-.2l1.2-.3c.2-.1.4-.1.6-.2.5-.2 1-.3 1.5-.5.1 0 .2-.1.4-.1.6-.2 1.2-.5 1.7-.8.2-.1.4-.2.5-.3.4-.2.8-.4 1.1-.6.2-.1.4-.3.7-.4l.9-.6c.1-.1.2-.1.3-.2 3.1-2.1 5.7-4.8 7.7-7.9 5 7.7 13.6 12.7 23.5 12.7s18.6-5.1 23.6-12.9c2 3.2 4.7 5.9 7.8 8.1.5.4 1.1.7 1.6 1 .1.1.2.1.3.2 1.1.6 2.2 1.2 3.4 1.6.1 0 .2.1.3.1l1.8.6c.6.2 1.2.3 1.8.5.1 0 .3.1.4.1.6.1 1.2.3 1.8.4s1.3.2 1.9.2h.5c.6 0 1.3.1 1.9.1s1.3 0 1.9-.1h.5c.6-.1 1.3-.1 1.9-.2s1.2-.2 1.8-.4c.1 0 .3-.1.4-.1.6-.1 1.2-.3 1.8-.5l1.8-.6c.1 0 .2-.1.3-.1 1.2-.5 2.3-1 3.4-1.6.1-.1.2-.1.3-.2.5-.3 1.1-.7 1.6-1 3.1-2.1 5.7-4.8 7.7-7.9 5 7.7 13.6 12.7 23.5 12.7 9.5 0 18-4.8 23-12.1 2 2.8 4.4 5.3 7.3 7.2.5.4 1.1.7 1.6 1 .1.1.2.1.3.2 1.1.6 2.2 1.2 3.4 1.6.1 0 .2.1.3.1l1.8.6c.6.2 1.2.3 1.8.5.1 0 .3.1.4.1.6.1 1.2.3 1.8.4s1.3.2 1.9.2h.5c.6 0 1.3.1 1.9.1s1.2 0 1.9-.1h.4c.6 0 1.2-.1 1.7-.2h.1c.6-.1 1.3-.2 1.9-.4h.1c11.9-2.7 20.9-12.8 21.8-25.3zM150 107c-.1 8.8-7.3 15.9-16.1 15.9s-16-7.1-16.1-15.9l15-37h25zm77.8 15.9c-8.8 0-16-7.1-16.1-15.9l-7.8-37h25l15 37c-.1 8.8-7.3 15.9-16.1 15.9z" fill="#fff"/></svg>
|
|
Before Width: | Height: | Size: 1.9 KiB |
|
@ -1 +0,0 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="266 396.7 25.5 23.6"><path fill="#FFF" d="M266 402.5c0-3.5 2.2-5.8 5.5-5.8s5.5 2.3 5.5 5.8-2.2 5.8-5.5 5.8-5.5-2.3-5.5-5.8zm2.9 17.3l8.5-11.8 6.2-10.7h5.2l-8.6 11.9-6 10.7h-5.3zm4.1-17.3c0-1.6-.5-2.5-1.5-2.5s-1.5.9-1.5 2.5c0 1.5.6 2.5 1.5 2.5.9-.1 1.5-1 1.5-2.5zm7.5 12c0-3.5 2.2-5.8 5.5-5.8s5.5 2.3 5.5 5.8-2.2 5.8-5.5 5.8-5.5-2.3-5.5-5.8zm7 0c0-1.6-.6-2.5-1.5-2.5s-1.5.9-1.5 2.5c0 1.5.6 2.5 1.5 2.5.9-.1 1.5-1 1.5-2.5z"/></svg>
|
|
Before Width: | Height: | Size: 478 B |
|
@ -1 +0,0 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 31.5 27.78"><defs><style>.cls-1,.cls-2{fill:#fff;}.cls-2{stroke:#fff;stroke-linecap:round;stroke-miterlimit:10;stroke-width:1.5px;}</style></defs><title>Asset 5</title><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path class="cls-1" d="M4.8,16.57H6.61a2,2,0,0,1,2,2v8.55a0,0,0,0,1,0,0H2.8a0,0,0,0,1,0,0V18.57A2,2,0,0,1,4.8,16.57Z"/><path class="cls-1" d="M14.85,7.53h1.81a2,2,0,0,1,2,2V27.12a0,0,0,0,1,0,0H12.85a0,0,0,0,1,0,0V9.53A2,2,0,0,1,14.85,7.53Z"/><path class="cls-1" d="M24.89,0H26.7a2,2,0,0,1,2,2V27.12a0,0,0,0,1,0,0H22.89a0,0,0,0,1,0,0V2A2,2,0,0,1,24.89,0Z"/><line class="cls-2" x1="0.75" y1="27.03" x2="30.75" y2="27.03"/></g></g></svg>
|
|
Before Width: | Height: | Size: 729 B |
Before Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 346 KiB |
Before Width: | Height: | Size: 7.8 KiB |
Before Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 13 KiB |
|
@ -1,158 +0,0 @@
|
||||||
/*global jQuery, Backbone, _, woocommerce_admin_api_keys, wcSetClipboard, wcClearClipboard */
|
|
||||||
(function( $ ) {
|
|
||||||
|
|
||||||
var APIView = Backbone.View.extend({
|
|
||||||
/**
|
|
||||||
* Element
|
|
||||||
*
|
|
||||||
* @param {Object} '#key-fields'
|
|
||||||
*/
|
|
||||||
el: $( '#key-fields' ),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Events
|
|
||||||
*
|
|
||||||
* @type {Object}
|
|
||||||
*/
|
|
||||||
events: {
|
|
||||||
'click input#update_api_key': 'saveKey'
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize actions
|
|
||||||
*/
|
|
||||||
initialize: function(){
|
|
||||||
_.bindAll( this, 'saveKey' );
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Init jQuery.BlockUI
|
|
||||||
*/
|
|
||||||
block: function() {
|
|
||||||
$( this.el ).block({
|
|
||||||
message: null,
|
|
||||||
overlayCSS: {
|
|
||||||
background: '#fff',
|
|
||||||
opacity: 0.6
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove jQuery.BlockUI
|
|
||||||
*/
|
|
||||||
unblock: function() {
|
|
||||||
$( this.el ).unblock();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Init TipTip
|
|
||||||
*/
|
|
||||||
initTipTip: function( css_class ) {
|
|
||||||
$( document.body )
|
|
||||||
.on( 'click', css_class, function( evt ) {
|
|
||||||
evt.preventDefault();
|
|
||||||
if ( ! document.queryCommandSupported( 'copy' ) ) {
|
|
||||||
$( css_class ).parent().find( 'input' ).focus().select();
|
|
||||||
$( '#copy-error' ).text( woocommerce_admin_api_keys.clipboard_failed );
|
|
||||||
} else {
|
|
||||||
$( '#copy-error' ).text( '' );
|
|
||||||
wcClearClipboard();
|
|
||||||
wcSetClipboard( $( this ).prev( 'input' ).val().trim(), $( css_class ) );
|
|
||||||
}
|
|
||||||
} )
|
|
||||||
.on( 'aftercopy', css_class, function() {
|
|
||||||
$( '#copy-error' ).text( '' );
|
|
||||||
$( css_class ).tipTip( {
|
|
||||||
'attribute': 'data-tip',
|
|
||||||
'activation': 'focus',
|
|
||||||
'fadeIn': 50,
|
|
||||||
'fadeOut': 50,
|
|
||||||
'delay': 0
|
|
||||||
} ).focus();
|
|
||||||
} )
|
|
||||||
.on( 'aftercopyerror', css_class, function() {
|
|
||||||
$( css_class ).parent().find( 'input' ).focus().select();
|
|
||||||
$( '#copy-error' ).text( woocommerce_admin_api_keys.clipboard_failed );
|
|
||||||
} );
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create qrcode
|
|
||||||
*
|
|
||||||
* @param {string} consumer_key
|
|
||||||
* @param {string} consumer_secret
|
|
||||||
*/
|
|
||||||
createQRCode: function( consumer_key, consumer_secret ) {
|
|
||||||
$( '#keys-qrcode' ).qrcode({
|
|
||||||
text: consumer_key + '|' + consumer_secret,
|
|
||||||
width: 120,
|
|
||||||
height: 120
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Save API Key using ajax
|
|
||||||
*
|
|
||||||
* @param {Object} e
|
|
||||||
*/
|
|
||||||
saveKey: function( e ) {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
self.block();
|
|
||||||
|
|
||||||
Backbone.ajax({
|
|
||||||
method: 'POST',
|
|
||||||
dataType: 'json',
|
|
||||||
url: woocommerce_admin_api_keys.ajax_url,
|
|
||||||
data: {
|
|
||||||
action: 'woocommerce_update_api_key',
|
|
||||||
security: woocommerce_admin_api_keys.update_api_nonce,
|
|
||||||
key_id: $( '#key_id', self.el ).val(),
|
|
||||||
description: $( '#key_description', self.el ).val(),
|
|
||||||
user: $( '#key_user', self.el ).val(),
|
|
||||||
permissions: $( '#key_permissions', self.el ).val()
|
|
||||||
},
|
|
||||||
success: function( response ) {
|
|
||||||
$( '.wc-api-message', self.el ).remove();
|
|
||||||
|
|
||||||
if ( response.success ) {
|
|
||||||
var data = response.data;
|
|
||||||
|
|
||||||
$( 'h2, h3', self.el ).first().append( '<div class="wc-api-message updated"><p>' + data.message + '</p></div>' );
|
|
||||||
|
|
||||||
if ( 0 < data.consumer_key.length && 0 < data.consumer_secret.length ) {
|
|
||||||
$( '#api-keys-options', self.el ).remove();
|
|
||||||
$( 'p.submit', self.el ).empty().append( data.revoke_url );
|
|
||||||
|
|
||||||
var template = wp.template( 'api-keys-template' );
|
|
||||||
|
|
||||||
$( 'p.submit', self.el ).before( template({
|
|
||||||
consumer_key: data.consumer_key,
|
|
||||||
consumer_secret: data.consumer_secret
|
|
||||||
}) );
|
|
||||||
self.createQRCode( data.consumer_key, data.consumer_secret );
|
|
||||||
self.initTipTip( '.copy-key' );
|
|
||||||
self.initTipTip( '.copy-secret' );
|
|
||||||
} else {
|
|
||||||
$( '#key_description', self.el ).val( data.description );
|
|
||||||
$( '#key_user', self.el ).val( data.user_id );
|
|
||||||
$( '#key_permissions', self.el ).val( data.permissions );
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$( 'h2, h3', self.el )
|
|
||||||
.first()
|
|
||||||
.append( '<div class="wc-api-message error"><p>' + response.data.message + '</p></div>' );
|
|
||||||
}
|
|
||||||
|
|
||||||
self.unblock();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
new APIView();
|
|
||||||
|
|
||||||
})( jQuery );
|
|
|
@ -1,147 +0,0 @@
|
||||||
/*global jQuery, Backbone, _ */
|
|
||||||
( function( $, Backbone, _ ) {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* WooCommerce Backbone Modal plugin
|
|
||||||
*
|
|
||||||
* @param {object} options
|
|
||||||
*/
|
|
||||||
$.fn.WCBackboneModal = function( options ) {
|
|
||||||
return this.each( function() {
|
|
||||||
( new $.WCBackboneModal( $( this ), options ) );
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize the Backbone Modal
|
|
||||||
*
|
|
||||||
* @param {object} element [description]
|
|
||||||
* @param {object} options [description]
|
|
||||||
*/
|
|
||||||
$.WCBackboneModal = function( element, options ) {
|
|
||||||
// Set settings
|
|
||||||
var settings = $.extend( {}, $.WCBackboneModal.defaultOptions, options );
|
|
||||||
|
|
||||||
if ( settings.template ) {
|
|
||||||
new $.WCBackboneModal.View({
|
|
||||||
target: settings.template,
|
|
||||||
string: settings.variable
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set default options
|
|
||||||
*
|
|
||||||
* @type {object}
|
|
||||||
*/
|
|
||||||
$.WCBackboneModal.defaultOptions = {
|
|
||||||
template: '',
|
|
||||||
variable: {}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create the Backbone Modal
|
|
||||||
*
|
|
||||||
* @return {null}
|
|
||||||
*/
|
|
||||||
$.WCBackboneModal.View = Backbone.View.extend({
|
|
||||||
tagName: 'div',
|
|
||||||
id: 'wc-backbone-modal-dialog',
|
|
||||||
_target: undefined,
|
|
||||||
_string: undefined,
|
|
||||||
events: {
|
|
||||||
'click .modal-close': 'closeButton',
|
|
||||||
'click #btn-ok' : 'addButton',
|
|
||||||
'touchstart #btn-ok': 'addButton',
|
|
||||||
'keydown' : 'keyboardActions'
|
|
||||||
},
|
|
||||||
resizeContent: function() {
|
|
||||||
var $content = $( '.wc-backbone-modal-content' ).find( 'article' );
|
|
||||||
var max_h = $( window ).height() * 0.75;
|
|
||||||
|
|
||||||
$content.css({
|
|
||||||
'max-height': max_h + 'px'
|
|
||||||
});
|
|
||||||
},
|
|
||||||
initialize: function( data ) {
|
|
||||||
var view = this;
|
|
||||||
this._target = data.target;
|
|
||||||
this._string = data.string;
|
|
||||||
_.bindAll( this, 'render' );
|
|
||||||
this.render();
|
|
||||||
|
|
||||||
$( window ).resize(function() {
|
|
||||||
view.resizeContent();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
render: function() {
|
|
||||||
var template = wp.template( this._target );
|
|
||||||
|
|
||||||
this.$el.append(
|
|
||||||
template( this._string )
|
|
||||||
);
|
|
||||||
|
|
||||||
$( document.body ).css({
|
|
||||||
'overflow': 'hidden'
|
|
||||||
}).append( this.$el );
|
|
||||||
|
|
||||||
this.resizeContent();
|
|
||||||
this.$( '.wc-backbone-modal-content' ).attr( 'tabindex' , '0' ).focus();
|
|
||||||
|
|
||||||
$( document.body ).trigger( 'init_tooltips' );
|
|
||||||
|
|
||||||
$( document.body ).trigger( 'wc_backbone_modal_loaded', this._target );
|
|
||||||
},
|
|
||||||
closeButton: function( e ) {
|
|
||||||
e.preventDefault();
|
|
||||||
$( document.body ).trigger( 'wc_backbone_modal_before_remove', this._target );
|
|
||||||
this.undelegateEvents();
|
|
||||||
$( document ).off( 'focusin' );
|
|
||||||
$( document.body ).css({
|
|
||||||
'overflow': 'auto'
|
|
||||||
});
|
|
||||||
this.remove();
|
|
||||||
$( document.body ).trigger( 'wc_backbone_modal_removed', this._target );
|
|
||||||
},
|
|
||||||
addButton: function( e ) {
|
|
||||||
$( document.body ).trigger( 'wc_backbone_modal_response', [ this._target, this.getFormData() ] );
|
|
||||||
this.closeButton( e );
|
|
||||||
},
|
|
||||||
getFormData: function() {
|
|
||||||
var data = {};
|
|
||||||
|
|
||||||
$( document.body ).trigger( 'wc_backbone_modal_before_update', this._target );
|
|
||||||
|
|
||||||
$.each( $( 'form', this.$el ).serializeArray(), function( index, item ) {
|
|
||||||
if ( item.name.indexOf( '[]' ) !== -1 ) {
|
|
||||||
item.name = item.name.replace( '[]', '' );
|
|
||||||
data[ item.name ] = $.makeArray( data[ item.name ] );
|
|
||||||
data[ item.name ].push( item.value );
|
|
||||||
} else {
|
|
||||||
data[ item.name ] = item.value;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return data;
|
|
||||||
},
|
|
||||||
keyboardActions: function( e ) {
|
|
||||||
var button = e.keyCode || e.which;
|
|
||||||
|
|
||||||
// Enter key
|
|
||||||
if (
|
|
||||||
13 === button &&
|
|
||||||
! ( e.target.tagName && ( e.target.tagName.toLowerCase() === 'input' || e.target.tagName.toLowerCase() === 'textarea' ) )
|
|
||||||
) {
|
|
||||||
this.addButton( e );
|
|
||||||
}
|
|
||||||
|
|
||||||
// ESC key
|
|
||||||
if ( 27 === button ) {
|
|
||||||
this.closeButton( e );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
}( jQuery, Backbone, _ ));
|
|
|
@ -1,449 +0,0 @@
|
||||||
/* global marketplace_suggestions, ajaxurl, Cookies */
|
|
||||||
( function( $, marketplace_suggestions, ajaxurl ) {
|
|
||||||
$( function() {
|
|
||||||
if ( 'undefined' === typeof marketplace_suggestions ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stand-in wcTracks.recordEvent in case tracks is not available (for any reason).
|
|
||||||
window.wcTracks = window.wcTracks || {};
|
|
||||||
window.wcTracks.recordEvent = window.wcTracks.recordEvent || function() { };
|
|
||||||
|
|
||||||
// Tracks events sent in this file:
|
|
||||||
// - marketplace_suggestion_displayed
|
|
||||||
// - marketplace_suggestion_clicked
|
|
||||||
// - marketplace_suggestion_dismissed
|
|
||||||
// All are prefixed by {WC_Tracks::PREFIX}.
|
|
||||||
// All have one property for `suggestionSlug`, to identify the specific suggestion message.
|
|
||||||
|
|
||||||
// Dismiss the specified suggestion from the UI, and save the dismissal in settings.
|
|
||||||
function dismissSuggestion( context, product, promoted, url, suggestionSlug ) {
|
|
||||||
// hide the suggestion in the UI
|
|
||||||
var selector = '[data-suggestion-slug=' + suggestionSlug + ']';
|
|
||||||
$( selector ).fadeOut( function() {
|
|
||||||
$( this ).remove();
|
|
||||||
tidyProductEditMetabox();
|
|
||||||
} );
|
|
||||||
|
|
||||||
// save dismissal in user settings
|
|
||||||
jQuery.post(
|
|
||||||
ajaxurl,
|
|
||||||
{
|
|
||||||
'action': 'woocommerce_add_dismissed_marketplace_suggestion',
|
|
||||||
'_wpnonce': marketplace_suggestions.dismiss_suggestion_nonce,
|
|
||||||
'slug': suggestionSlug
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// if this is a high-use area, delay new suggestion that area for a short while
|
|
||||||
var highUseSuggestionContexts = [ 'products-list-inline' ];
|
|
||||||
if ( _.contains( highUseSuggestionContexts, context ) ) {
|
|
||||||
// snooze suggestions in that area for 2 days
|
|
||||||
var contextSnoozeCookie = 'woocommerce_snooze_suggestions__' + context;
|
|
||||||
Cookies.set( contextSnoozeCookie, 'true', { expires: 2 } );
|
|
||||||
|
|
||||||
// keep track of how often this area gets dismissed in a cookie
|
|
||||||
var contextDismissalCountCookie = 'woocommerce_dismissed_suggestions__' + context;
|
|
||||||
var previousDismissalsInThisContext = parseInt( Cookies.get( contextDismissalCountCookie ), 10 ) || 0;
|
|
||||||
Cookies.set( contextDismissalCountCookie, previousDismissalsInThisContext + 1, { expires: 31 } );
|
|
||||||
}
|
|
||||||
|
|
||||||
window.wcTracks.recordEvent( 'marketplace_suggestion_dismissed', {
|
|
||||||
suggestion_slug: suggestionSlug,
|
|
||||||
context: context,
|
|
||||||
product: product || '',
|
|
||||||
promoted: promoted || '',
|
|
||||||
target: url || ''
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Render DOM element for suggestion dismiss button.
|
|
||||||
function renderDismissButton( context, product, promoted, url, suggestionSlug ) {
|
|
||||||
var dismissButton = document.createElement( 'a' );
|
|
||||||
|
|
||||||
dismissButton.classList.add( 'suggestion-dismiss' );
|
|
||||||
dismissButton.setAttribute( 'title', marketplace_suggestions.i18n_marketplace_suggestions_dismiss_tooltip );
|
|
||||||
dismissButton.setAttribute( 'href', '#' );
|
|
||||||
dismissButton.onclick = function( event ) {
|
|
||||||
event.preventDefault();
|
|
||||||
dismissSuggestion( context, product, promoted, url, suggestionSlug );
|
|
||||||
};
|
|
||||||
|
|
||||||
return dismissButton;
|
|
||||||
}
|
|
||||||
|
|
||||||
function addURLParameters( context, url ) {
|
|
||||||
var urlParams = marketplace_suggestions.in_app_purchase_params;
|
|
||||||
urlParams.utm_source = 'unknown';
|
|
||||||
urlParams.utm_campaign = 'marketplacesuggestions';
|
|
||||||
urlParams.utm_medium = 'product';
|
|
||||||
|
|
||||||
var sourceContextMap = {
|
|
||||||
'productstable': [
|
|
||||||
'products-list-inline'
|
|
||||||
],
|
|
||||||
'productsempty': [
|
|
||||||
'products-list-empty-header',
|
|
||||||
'products-list-empty-footer',
|
|
||||||
'products-list-empty-body'
|
|
||||||
],
|
|
||||||
'ordersempty': [
|
|
||||||
'orders-list-empty-header',
|
|
||||||
'orders-list-empty-footer',
|
|
||||||
'orders-list-empty-body'
|
|
||||||
],
|
|
||||||
'editproduct': [
|
|
||||||
'product-edit-meta-tab-header',
|
|
||||||
'product-edit-meta-tab-footer',
|
|
||||||
'product-edit-meta-tab-body'
|
|
||||||
]
|
|
||||||
};
|
|
||||||
var utmSource = _.findKey( sourceContextMap, function( sourceInfo ) {
|
|
||||||
return _.contains( sourceInfo, context );
|
|
||||||
} );
|
|
||||||
if ( utmSource ) {
|
|
||||||
urlParams.utm_source = utmSource;
|
|
||||||
}
|
|
||||||
|
|
||||||
return url + '?' + jQuery.param( urlParams );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Render DOM element for suggestion linkout, optionally with button style.
|
|
||||||
function renderLinkout( context, product, promoted, slug, url, text, isButton ) {
|
|
||||||
var linkoutButton = document.createElement( 'a' );
|
|
||||||
|
|
||||||
var utmUrl = addURLParameters( context, url );
|
|
||||||
linkoutButton.setAttribute( 'href', utmUrl );
|
|
||||||
|
|
||||||
// By default, CTA links should open in same tab (and feel integrated with Woo).
|
|
||||||
// Exception: when editing products, use new tab. User may have product edits
|
|
||||||
// that need to be saved.
|
|
||||||
var newTabContexts = [
|
|
||||||
'product-edit-meta-tab-header',
|
|
||||||
'product-edit-meta-tab-footer',
|
|
||||||
'product-edit-meta-tab-body'
|
|
||||||
];
|
|
||||||
if ( _.includes( newTabContexts, context ) ) {
|
|
||||||
linkoutButton.setAttribute( 'target', 'blank' );
|
|
||||||
}
|
|
||||||
|
|
||||||
linkoutButton.textContent = text;
|
|
||||||
|
|
||||||
linkoutButton.onclick = function() {
|
|
||||||
window.wcTracks.recordEvent( 'marketplace_suggestion_clicked', {
|
|
||||||
suggestion_slug: slug,
|
|
||||||
context: context,
|
|
||||||
product: product || '',
|
|
||||||
promoted: promoted || '',
|
|
||||||
target: url || ''
|
|
||||||
} );
|
|
||||||
};
|
|
||||||
|
|
||||||
if ( isButton ) {
|
|
||||||
linkoutButton.classList.add( 'button' );
|
|
||||||
} else {
|
|
||||||
linkoutButton.classList.add( 'linkout' );
|
|
||||||
var linkoutIcon = document.createElement( 'span' );
|
|
||||||
linkoutIcon.classList.add( 'dashicons', 'dashicons-external' );
|
|
||||||
linkoutButton.appendChild( linkoutIcon );
|
|
||||||
}
|
|
||||||
|
|
||||||
return linkoutButton;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Render DOM element for suggestion icon image.
|
|
||||||
function renderSuggestionIcon( iconUrl ) {
|
|
||||||
if ( ! iconUrl ) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var image = document.createElement( 'img' );
|
|
||||||
image.src = iconUrl;
|
|
||||||
image.classList.add( 'marketplace-suggestion-icon' );
|
|
||||||
|
|
||||||
return image;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Render DOM elements for suggestion content.
|
|
||||||
function renderSuggestionContent( slug, title, copy ) {
|
|
||||||
var container = document.createElement( 'div' );
|
|
||||||
|
|
||||||
container.classList.add( 'marketplace-suggestion-container-content' );
|
|
||||||
|
|
||||||
if ( title ) {
|
|
||||||
var titleHeading = document.createElement( 'h4' );
|
|
||||||
titleHeading.textContent = title;
|
|
||||||
container.appendChild( titleHeading );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( copy ) {
|
|
||||||
var body = document.createElement( 'p' );
|
|
||||||
body.textContent = copy;
|
|
||||||
container.appendChild( body );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Conditionally add in a Manage suggestions link to product edit
|
|
||||||
// metabox footer (based on suggestion slug).
|
|
||||||
var slugsWithManage = [
|
|
||||||
'product-edit-empty-footer-browse-all',
|
|
||||||
'product-edit-meta-tab-footer-browse-all'
|
|
||||||
];
|
|
||||||
if ( -1 !== slugsWithManage.indexOf( slug ) ) {
|
|
||||||
container.classList.add( 'has-manage-link' );
|
|
||||||
|
|
||||||
var manageSuggestionsLink = document.createElement( 'a' );
|
|
||||||
manageSuggestionsLink.classList.add( 'marketplace-suggestion-manage-link', 'linkout' );
|
|
||||||
manageSuggestionsLink.setAttribute(
|
|
||||||
'href',
|
|
||||||
marketplace_suggestions.manage_suggestions_url
|
|
||||||
);
|
|
||||||
manageSuggestionsLink.textContent = marketplace_suggestions.i18n_marketplace_suggestions_manage_suggestions;
|
|
||||||
|
|
||||||
container.appendChild( manageSuggestionsLink );
|
|
||||||
}
|
|
||||||
|
|
||||||
return container;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Render DOM elements for suggestion call-to-action – button or link with dismiss 'x'.
|
|
||||||
function renderSuggestionCTA( context, product, promoted, slug, url, linkText, linkIsButton, allowDismiss ) {
|
|
||||||
var container = document.createElement( 'div' );
|
|
||||||
|
|
||||||
if ( ! linkText ) {
|
|
||||||
linkText = marketplace_suggestions.i18n_marketplace_suggestions_default_cta;
|
|
||||||
}
|
|
||||||
|
|
||||||
container.classList.add( 'marketplace-suggestion-container-cta' );
|
|
||||||
if ( url && linkText ) {
|
|
||||||
var linkoutElement = renderLinkout( context, product, promoted, slug, url, linkText, linkIsButton );
|
|
||||||
container.appendChild( linkoutElement );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( allowDismiss ) {
|
|
||||||
container.appendChild( renderDismissButton( context, product, promoted, url, slug ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
return container;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Render a "list item" style suggestion.
|
|
||||||
// These are used in onboarding style contexts, e.g. products list empty state.
|
|
||||||
function renderListItem( context, product, promoted, slug, iconUrl, title, copy, url, linkText, linkIsButton, allowDismiss ) {
|
|
||||||
var container = document.createElement( 'div' );
|
|
||||||
container.classList.add( 'marketplace-suggestion-container' );
|
|
||||||
container.dataset.suggestionSlug = slug;
|
|
||||||
|
|
||||||
var icon = renderSuggestionIcon( iconUrl );
|
|
||||||
if ( icon ) {
|
|
||||||
container.appendChild( icon );
|
|
||||||
}
|
|
||||||
container.appendChild(
|
|
||||||
renderSuggestionContent( slug, title, copy )
|
|
||||||
);
|
|
||||||
container.appendChild(
|
|
||||||
renderSuggestionCTA( context, product, promoted, slug, url, linkText, linkIsButton, allowDismiss )
|
|
||||||
);
|
|
||||||
|
|
||||||
return container;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filter suggestion data to remove less-relevant suggestions.
|
|
||||||
function getRelevantPromotions( marketplaceSuggestionsApiData, displayContext ) {
|
|
||||||
// select based on display context
|
|
||||||
var promos = _.filter( marketplaceSuggestionsApiData, function( promo ) {
|
|
||||||
if ( _.isArray( promo.context ) ) {
|
|
||||||
return _.contains( promo.context, displayContext );
|
|
||||||
}
|
|
||||||
return ( displayContext === promo.context );
|
|
||||||
} );
|
|
||||||
|
|
||||||
// hide promos the user has dismissed
|
|
||||||
promos = _.filter( promos, function( promo ) {
|
|
||||||
return ! _.contains( marketplace_suggestions.dismissed_suggestions, promo.slug );
|
|
||||||
} );
|
|
||||||
|
|
||||||
// hide promos for things the user already has installed
|
|
||||||
promos = _.filter( promos, function( promo ) {
|
|
||||||
return ! _.contains( marketplace_suggestions.active_plugins, promo.product );
|
|
||||||
} );
|
|
||||||
|
|
||||||
// hide promos that are not applicable based on user's installed extensions
|
|
||||||
promos = _.filter( promos, function( promo ) {
|
|
||||||
if ( ! promo['show-if-active'] ) {
|
|
||||||
// this promotion is relevant to all
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the user has any of the prerequisites, show the promo
|
|
||||||
return ( _.intersection( marketplace_suggestions.active_plugins, promo['show-if-active'] ).length > 0 );
|
|
||||||
} );
|
|
||||||
|
|
||||||
return promos;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Show and hide page elements dependent on suggestion state.
|
|
||||||
function hidePageElementsForSuggestionState( usedSuggestionsContexts ) {
|
|
||||||
var showingEmptyStateSuggestions = _.intersection(
|
|
||||||
usedSuggestionsContexts,
|
|
||||||
[ 'products-list-empty-body', 'orders-list-empty-body' ]
|
|
||||||
).length > 0;
|
|
||||||
|
|
||||||
// Streamline onboarding UI if we're in 'empty state' welcome mode.
|
|
||||||
if ( showingEmptyStateSuggestions ) {
|
|
||||||
$( '#screen-meta-links' ).hide();
|
|
||||||
$( '#wpfooter' ).hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hide the header & footer, they don't make sense without specific promotion content
|
|
||||||
if ( ! showingEmptyStateSuggestions ) {
|
|
||||||
$( '.marketplace-suggestions-container[data-marketplace-suggestions-context="products-list-empty-header"]' ).hide();
|
|
||||||
$( '.marketplace-suggestions-container[data-marketplace-suggestions-context="products-list-empty-footer"]' ).hide();
|
|
||||||
$( '.marketplace-suggestions-container[data-marketplace-suggestions-context="orders-list-empty-header"]' ).hide();
|
|
||||||
$( '.marketplace-suggestions-container[data-marketplace-suggestions-context="orders-list-empty-footer"]' ).hide();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Streamline the product edit suggestions tab dependent on what's visible.
|
|
||||||
function tidyProductEditMetabox() {
|
|
||||||
var productMetaboxSuggestions = $(
|
|
||||||
'.marketplace-suggestions-container[data-marketplace-suggestions-context="product-edit-meta-tab-body"]'
|
|
||||||
).children();
|
|
||||||
if ( 0 >= productMetaboxSuggestions.length ) {
|
|
||||||
var metaboxSuggestionsUISelector =
|
|
||||||
'.marketplace-suggestions-container[data-marketplace-suggestions-context="product-edit-meta-tab-body"]';
|
|
||||||
metaboxSuggestionsUISelector +=
|
|
||||||
', .marketplace-suggestions-container[data-marketplace-suggestions-context="product-edit-meta-tab-header"]';
|
|
||||||
metaboxSuggestionsUISelector +=
|
|
||||||
', .marketplace-suggestions-container[data-marketplace-suggestions-context="product-edit-meta-tab-footer"]';
|
|
||||||
$( metaboxSuggestionsUISelector ).fadeOut( {
|
|
||||||
complete: function() {
|
|
||||||
$( '.marketplace-suggestions-metabox-nosuggestions-placeholder' ).fadeIn();
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function addManageSuggestionsTracksHandler() {
|
|
||||||
$( 'a.marketplace-suggestion-manage-link' ).on( 'click', function() {
|
|
||||||
window.wcTracks.recordEvent( 'marketplace_suggestions_manage_clicked' );
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
|
|
||||||
function isContextHiddenOnPageLoad( context ) {
|
|
||||||
// Some suggestions are not visible on page load;
|
|
||||||
// e.g. the user reveals them by selecting a tab.
|
|
||||||
var revealableSuggestionsContexts = [
|
|
||||||
'product-edit-meta-tab-header',
|
|
||||||
'product-edit-meta-tab-body',
|
|
||||||
'product-edit-meta-tab-footer'
|
|
||||||
];
|
|
||||||
return _.includes( revealableSuggestionsContexts, context );
|
|
||||||
}
|
|
||||||
|
|
||||||
// track the current product data tab to avoid over-tracking suggestions
|
|
||||||
var currentTab = false;
|
|
||||||
|
|
||||||
// Render suggestion data in appropriate places in UI.
|
|
||||||
function displaySuggestions( marketplaceSuggestionsApiData ) {
|
|
||||||
var usedSuggestionsContexts = [];
|
|
||||||
|
|
||||||
// iterate over all suggestions containers, rendering promos
|
|
||||||
$( '.marketplace-suggestions-container' ).each( function() {
|
|
||||||
// determine the context / placement we're populating
|
|
||||||
var context = this.dataset.marketplaceSuggestionsContext;
|
|
||||||
|
|
||||||
// find promotions that target this context
|
|
||||||
var promos = getRelevantPromotions( marketplaceSuggestionsApiData, context );
|
|
||||||
|
|
||||||
// shuffle/randomly select five suggestions to display
|
|
||||||
var suggestionsToDisplay = _.sample( promos, 5 );
|
|
||||||
|
|
||||||
// render the promo content
|
|
||||||
for ( var i in suggestionsToDisplay ) {
|
|
||||||
|
|
||||||
var linkText = suggestionsToDisplay[ i ]['link-text'];
|
|
||||||
var linkoutIsButton = true;
|
|
||||||
if ( suggestionsToDisplay[ i ]['link-text'] ) {
|
|
||||||
linkText = suggestionsToDisplay[ i ]['link-text'];
|
|
||||||
linkoutIsButton = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// dismiss is allowed by default
|
|
||||||
var allowDismiss = true;
|
|
||||||
if ( suggestionsToDisplay[ i ]['allow-dismiss'] === false ) {
|
|
||||||
allowDismiss = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var content = renderListItem(
|
|
||||||
context,
|
|
||||||
suggestionsToDisplay[ i ].product,
|
|
||||||
suggestionsToDisplay[ i ].promoted,
|
|
||||||
suggestionsToDisplay[ i ].slug,
|
|
||||||
suggestionsToDisplay[ i ].icon,
|
|
||||||
suggestionsToDisplay[ i ].title,
|
|
||||||
suggestionsToDisplay[ i ].copy,
|
|
||||||
suggestionsToDisplay[ i ].url,
|
|
||||||
linkText,
|
|
||||||
linkoutIsButton,
|
|
||||||
allowDismiss
|
|
||||||
);
|
|
||||||
$( this ).append( content );
|
|
||||||
$( this ).addClass( 'showing-suggestion' );
|
|
||||||
usedSuggestionsContexts.push( context );
|
|
||||||
|
|
||||||
if ( ! isContextHiddenOnPageLoad( context ) ) {
|
|
||||||
// Fire 'displayed' tracks events for immediately visible suggestions.
|
|
||||||
window.wcTracks.recordEvent( 'marketplace_suggestion_displayed', {
|
|
||||||
suggestion_slug: suggestionsToDisplay[ i ].slug,
|
|
||||||
context: context,
|
|
||||||
product: suggestionsToDisplay[ i ].product || '',
|
|
||||||
promoted: suggestionsToDisplay[ i ].promoted || '',
|
|
||||||
target: suggestionsToDisplay[ i ].url || ''
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Track when suggestions are displayed (and not already visible).
|
|
||||||
$( 'ul.product_data_tabs li.marketplace-suggestions_options a' ).on( 'click', function( e ) {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
if ( '#marketplace_suggestions' === currentTab ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ! isContextHiddenOnPageLoad( context ) ) {
|
|
||||||
// We've already fired 'displayed' event above.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for ( var i in suggestionsToDisplay ) {
|
|
||||||
window.wcTracks.recordEvent( 'marketplace_suggestion_displayed', {
|
|
||||||
suggestion_slug: suggestionsToDisplay[ i ].slug,
|
|
||||||
context: context,
|
|
||||||
product: suggestionsToDisplay[ i ].product || '',
|
|
||||||
promoted: suggestionsToDisplay[ i ].promoted || '',
|
|
||||||
target: suggestionsToDisplay[ i ].url || ''
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
} );
|
|
||||||
|
|
||||||
hidePageElementsForSuggestionState( usedSuggestionsContexts );
|
|
||||||
tidyProductEditMetabox();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( marketplace_suggestions.suggestions_data ) {
|
|
||||||
displaySuggestions( marketplace_suggestions.suggestions_data );
|
|
||||||
|
|
||||||
// track the current product data tab to avoid over-reporting suggestion views
|
|
||||||
$( 'ul.product_data_tabs' ).on( 'click', 'li a', function( e ) {
|
|
||||||
e.preventDefault();
|
|
||||||
currentTab = $( this ).attr( 'href' );
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
|
|
||||||
addManageSuggestionsTracksHandler();
|
|
||||||
});
|
|
||||||
|
|
||||||
})( jQuery, marketplace_suggestions, ajaxurl );
|
|
|
@ -1,70 +0,0 @@
|
||||||
/* global woocommerce_admin_meta_boxes_coupon */
|
|
||||||
jQuery(function( $ ) {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Coupon actions
|
|
||||||
*/
|
|
||||||
var wc_meta_boxes_coupon_actions = {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize variations actions
|
|
||||||
*/
|
|
||||||
init: function() {
|
|
||||||
$( 'select#discount_type' )
|
|
||||||
.on( 'change', this.type_options )
|
|
||||||
.trigger( 'change' );
|
|
||||||
|
|
||||||
this.insert_generate_coupon_code_button();
|
|
||||||
$( '.button.generate-coupon-code' ).on( 'click', this.generate_coupon_code );
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show/hide fields by coupon type options
|
|
||||||
*/
|
|
||||||
type_options: function() {
|
|
||||||
// Get value
|
|
||||||
var select_val = $( this ).val();
|
|
||||||
|
|
||||||
if ( 'percent' === select_val ) {
|
|
||||||
$( '#coupon_amount' ).removeClass( 'wc_input_price' ).addClass( 'wc_input_decimal' );
|
|
||||||
} else {
|
|
||||||
$( '#coupon_amount' ).removeClass( 'wc_input_decimal' ).addClass( 'wc_input_price' );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( select_val !== 'fixed_cart' ) {
|
|
||||||
$( '.limit_usage_to_x_items_field' ).show();
|
|
||||||
} else {
|
|
||||||
$( '.limit_usage_to_x_items_field' ).hide();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Insert generate coupon code buttom HTML.
|
|
||||||
*/
|
|
||||||
insert_generate_coupon_code_button: function() {
|
|
||||||
$( '.post-type-shop_coupon' ).find( '#title' ).after(
|
|
||||||
'<a href="#" class="button generate-coupon-code">' + woocommerce_admin_meta_boxes_coupon.generate_button_text + '</a>'
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate a random coupon code
|
|
||||||
*/
|
|
||||||
generate_coupon_code: function( e ) {
|
|
||||||
e.preventDefault();
|
|
||||||
var $coupon_code_field = $( '#title' ),
|
|
||||||
$coupon_code_label = $( '#title-prompt-text' ),
|
|
||||||
$result = '';
|
|
||||||
for ( var i = 0; i < woocommerce_admin_meta_boxes_coupon.char_length; i++ ) {
|
|
||||||
$result += woocommerce_admin_meta_boxes_coupon.characters.charAt(
|
|
||||||
Math.floor( Math.random() * woocommerce_admin_meta_boxes_coupon.characters.length )
|
|
||||||
);
|
|
||||||
}
|
|
||||||
$result = woocommerce_admin_meta_boxes_coupon.prefix + $result + woocommerce_admin_meta_boxes_coupon.suffix;
|
|
||||||
$coupon_code_field.focus().val( $result );
|
|
||||||
$coupon_code_label.addClass( 'screen-reader-text' );
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
wc_meta_boxes_coupon_actions.init();
|
|
||||||
});
|
|
|
@ -1,691 +0,0 @@
|
||||||
/*global woocommerce_admin_meta_boxes */
|
|
||||||
jQuery( function( $ ) {
|
|
||||||
|
|
||||||
// Scroll to first checked category
|
|
||||||
// https://github.com/scribu/wp-category-checklist-tree/blob/d1c3c1f449e1144542efa17dde84a9f52ade1739/category-checklist-tree.php
|
|
||||||
$( function() {
|
|
||||||
$( '[id$="-all"] > ul.categorychecklist' ).each( function() {
|
|
||||||
var $list = $( this );
|
|
||||||
var $firstChecked = $list.find( ':checked' ).first();
|
|
||||||
|
|
||||||
if ( ! $firstChecked.length ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var pos_first = $list.find( 'input' ).position().top;
|
|
||||||
var pos_checked = $firstChecked.position().top;
|
|
||||||
|
|
||||||
$list.closest( '.tabs-panel' ).scrollTop( pos_checked - pos_first + 5 );
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Prevent enter submitting post form.
|
|
||||||
$( '#upsell_product_data' ).on( 'keypress', function( e ) {
|
|
||||||
if ( e.keyCode === 13 ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Type box.
|
|
||||||
if ( $( 'body' ).hasClass( 'wc-wp-version-gte-55' ) ) {
|
|
||||||
$( '.type_box' ).appendTo( '#woocommerce-product-data .hndle' );
|
|
||||||
} else {
|
|
||||||
$( '.type_box' ).appendTo( '#woocommerce-product-data .hndle span' );
|
|
||||||
}
|
|
||||||
|
|
||||||
$( function() {
|
|
||||||
// Prevent inputs in meta box headings opening/closing contents.
|
|
||||||
$( '#woocommerce-product-data' ).find( '.hndle' ).unbind( 'click.postboxes' );
|
|
||||||
|
|
||||||
$( '#woocommerce-product-data' ).on( 'click', '.hndle', function( event ) {
|
|
||||||
|
|
||||||
// If the user clicks on some form input inside the h3 the box should not be toggled.
|
|
||||||
if ( $( event.target ).filter( 'input, option, label, select' ).length ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$( '#woocommerce-product-data' ).toggleClass( 'closed' );
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Catalog Visibility.
|
|
||||||
$( '#catalog-visibility' ).find( '.edit-catalog-visibility' ).on( 'click', function() {
|
|
||||||
if ( $( '#catalog-visibility-select' ).is( ':hidden' ) ) {
|
|
||||||
$( '#catalog-visibility-select' ).slideDown( 'fast' );
|
|
||||||
$( this ).hide();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
$( '#catalog-visibility' ).find( '.save-post-visibility' ).on( 'click', function() {
|
|
||||||
$( '#catalog-visibility-select' ).slideUp( 'fast' );
|
|
||||||
$( '#catalog-visibility' ).find( '.edit-catalog-visibility' ).show();
|
|
||||||
|
|
||||||
var label = $( 'input[name=_visibility]:checked' ).attr( 'data-label' );
|
|
||||||
|
|
||||||
if ( $( 'input[name=_featured]' ).is( ':checked' ) ) {
|
|
||||||
label = label + ', ' + woocommerce_admin_meta_boxes.featured_label;
|
|
||||||
$( 'input[name=_featured]' ).attr( 'checked', 'checked' );
|
|
||||||
}
|
|
||||||
|
|
||||||
$( '#catalog-visibility-display' ).text( label );
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
$( '#catalog-visibility' ).find( '.cancel-post-visibility' ).on( 'click', function() {
|
|
||||||
$( '#catalog-visibility-select' ).slideUp( 'fast' );
|
|
||||||
$( '#catalog-visibility' ).find( '.edit-catalog-visibility' ).show();
|
|
||||||
|
|
||||||
var current_visibility = $( '#current_visibility' ).val();
|
|
||||||
var current_featured = $( '#current_featured' ).val();
|
|
||||||
|
|
||||||
$( 'input[name=_visibility]' ).removeAttr( 'checked' );
|
|
||||||
$( 'input[name=_visibility][value=' + current_visibility + ']' ).attr( 'checked', 'checked' );
|
|
||||||
|
|
||||||
var label = $( 'input[name=_visibility]:checked' ).attr( 'data-label' );
|
|
||||||
|
|
||||||
if ( 'yes' === current_featured ) {
|
|
||||||
label = label + ', ' + woocommerce_admin_meta_boxes.featured_label;
|
|
||||||
$( 'input[name=_featured]' ).attr( 'checked', 'checked' );
|
|
||||||
} else {
|
|
||||||
$( 'input[name=_featured]' ).removeAttr( 'checked' );
|
|
||||||
}
|
|
||||||
|
|
||||||
$( '#catalog-visibility-display' ).text( label );
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Product type specific options.
|
|
||||||
$( 'select#product-type' ).change( function() {
|
|
||||||
|
|
||||||
// Get value.
|
|
||||||
var select_val = $( this ).val();
|
|
||||||
|
|
||||||
if ( 'variable' === select_val ) {
|
|
||||||
$( 'input#_manage_stock' ).trigger( 'change' );
|
|
||||||
$( 'input#_downloadable' ).prop( 'checked', false );
|
|
||||||
$( 'input#_virtual' ).removeAttr( 'checked' );
|
|
||||||
} else if ( 'grouped' === select_val ) {
|
|
||||||
$( 'input#_downloadable' ).prop( 'checked', false );
|
|
||||||
$( 'input#_virtual' ).removeAttr( 'checked' );
|
|
||||||
} else if ( 'external' === select_val ) {
|
|
||||||
$( 'input#_downloadable' ).prop( 'checked', false );
|
|
||||||
$( 'input#_virtual' ).removeAttr( 'checked' );
|
|
||||||
}
|
|
||||||
|
|
||||||
show_and_hide_panels();
|
|
||||||
|
|
||||||
$( 'ul.wc-tabs li:visible' ).eq( 0 ).find( 'a' ).trigger( 'click' );
|
|
||||||
|
|
||||||
$( document.body ).trigger( 'woocommerce-product-type-change', select_val, $( this ) );
|
|
||||||
|
|
||||||
}).trigger( 'change' );
|
|
||||||
|
|
||||||
$( 'input#_downloadable, input#_virtual' ).change( function() {
|
|
||||||
show_and_hide_panels();
|
|
||||||
});
|
|
||||||
|
|
||||||
function show_and_hide_panels() {
|
|
||||||
var product_type = $( 'select#product-type' ).val();
|
|
||||||
var is_virtual = $( 'input#_virtual:checked' ).length;
|
|
||||||
var is_downloadable = $( 'input#_downloadable:checked' ).length;
|
|
||||||
|
|
||||||
// Hide/Show all with rules.
|
|
||||||
var hide_classes = '.hide_if_downloadable, .hide_if_virtual';
|
|
||||||
var show_classes = '.show_if_downloadable, .show_if_virtual';
|
|
||||||
|
|
||||||
$.each( woocommerce_admin_meta_boxes.product_types, function( index, value ) {
|
|
||||||
hide_classes = hide_classes + ', .hide_if_' + value;
|
|
||||||
show_classes = show_classes + ', .show_if_' + value;
|
|
||||||
});
|
|
||||||
|
|
||||||
$( hide_classes ).show();
|
|
||||||
$( show_classes ).hide();
|
|
||||||
|
|
||||||
// Shows rules.
|
|
||||||
if ( is_downloadable ) {
|
|
||||||
$( '.show_if_downloadable' ).show();
|
|
||||||
}
|
|
||||||
if ( is_virtual ) {
|
|
||||||
$( '.show_if_virtual' ).show();
|
|
||||||
|
|
||||||
// If user enables virtual while on shipping tab, switch to general tab.
|
|
||||||
if ( $( '.shipping_options.shipping_tab' ).hasClass( 'active' ) ) {
|
|
||||||
$( '.general_options.general_tab > a' ).trigger( 'click' );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$( '.show_if_' + product_type ).show();
|
|
||||||
|
|
||||||
// Hide rules.
|
|
||||||
if ( is_downloadable ) {
|
|
||||||
$( '.hide_if_downloadable' ).hide();
|
|
||||||
}
|
|
||||||
if ( is_virtual ) {
|
|
||||||
$( '.hide_if_virtual' ).hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
$( '.hide_if_' + product_type ).hide();
|
|
||||||
|
|
||||||
$( 'input#_manage_stock' ).trigger( 'change' );
|
|
||||||
|
|
||||||
// Hide empty panels/tabs after display.
|
|
||||||
$( '.woocommerce_options_panel' ).each( function() {
|
|
||||||
var $children = $( this ).children( '.options_group' );
|
|
||||||
|
|
||||||
if ( 0 === $children.length ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var $invisble = $children.filter( function() {
|
|
||||||
return 'none' === $( this ).css( 'display' );
|
|
||||||
});
|
|
||||||
|
|
||||||
// Hide panel.
|
|
||||||
if ( $invisble.length === $children.length ) {
|
|
||||||
var $id = $( this ).prop( 'id' );
|
|
||||||
$( '.product_data_tabs' ).find( 'li a[href="#' + $id + '"]' ).parent().hide();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sale price schedule.
|
|
||||||
$( '.sale_price_dates_fields' ).each( function() {
|
|
||||||
var $these_sale_dates = $( this );
|
|
||||||
var sale_schedule_set = false;
|
|
||||||
var $wrap = $these_sale_dates.closest( 'div, table' );
|
|
||||||
|
|
||||||
$these_sale_dates.find( 'input' ).each( function() {
|
|
||||||
if ( '' !== $( this ).val() ) {
|
|
||||||
sale_schedule_set = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if ( sale_schedule_set ) {
|
|
||||||
$wrap.find( '.sale_schedule' ).hide();
|
|
||||||
$wrap.find( '.sale_price_dates_fields' ).show();
|
|
||||||
} else {
|
|
||||||
$wrap.find( '.sale_schedule' ).show();
|
|
||||||
$wrap.find( '.sale_price_dates_fields' ).hide();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$( '#woocommerce-product-data' ).on( 'click', '.sale_schedule', function() {
|
|
||||||
var $wrap = $( this ).closest( 'div, table' );
|
|
||||||
|
|
||||||
$( this ).hide();
|
|
||||||
$wrap.find( '.cancel_sale_schedule' ).show();
|
|
||||||
$wrap.find( '.sale_price_dates_fields' ).show();
|
|
||||||
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
$( '#woocommerce-product-data' ).on( 'click', '.cancel_sale_schedule', function() {
|
|
||||||
var $wrap = $( this ).closest( 'div, table' );
|
|
||||||
|
|
||||||
$( this ).hide();
|
|
||||||
$wrap.find( '.sale_schedule' ).show();
|
|
||||||
$wrap.find( '.sale_price_dates_fields' ).hide();
|
|
||||||
$wrap.find( '.sale_price_dates_fields' ).find( 'input' ).val('');
|
|
||||||
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
// File inputs.
|
|
||||||
$( '#woocommerce-product-data' ).on( 'click','.downloadable_files a.insert', function() {
|
|
||||||
$( this ).closest( '.downloadable_files' ).find( 'tbody' ).append( $( this ).data( 'row' ) );
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
$( '#woocommerce-product-data' ).on( 'click','.downloadable_files a.delete',function() {
|
|
||||||
$( this ).closest( 'tr' ).remove();
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Stock options.
|
|
||||||
$( 'input#_manage_stock' ).change( function() {
|
|
||||||
if ( $( this ).is( ':checked' ) ) {
|
|
||||||
$( 'div.stock_fields' ).show();
|
|
||||||
$( 'p.stock_status_field' ).hide();
|
|
||||||
} else {
|
|
||||||
var product_type = $( 'select#product-type' ).val();
|
|
||||||
|
|
||||||
$( 'div.stock_fields' ).hide();
|
|
||||||
$( 'p.stock_status_field:not( .hide_if_' + product_type + ' )' ).show();
|
|
||||||
}
|
|
||||||
|
|
||||||
$( 'input.variable_manage_stock' ).trigger( 'change' );
|
|
||||||
}).trigger( 'change' );
|
|
||||||
|
|
||||||
// Date picker fields.
|
|
||||||
function date_picker_select( datepicker ) {
|
|
||||||
var option = $( datepicker ).next().is( '.hasDatepicker' ) ? 'minDate' : 'maxDate',
|
|
||||||
otherDateField = 'minDate' === option ? $( datepicker ).next() : $( datepicker ).prev(),
|
|
||||||
date = $( datepicker ).datepicker( 'getDate' );
|
|
||||||
|
|
||||||
$( otherDateField ).datepicker( 'option', option, date );
|
|
||||||
$( datepicker ).trigger( 'change' );
|
|
||||||
}
|
|
||||||
|
|
||||||
$( '.sale_price_dates_fields' ).each( function() {
|
|
||||||
$( this ).find( 'input' ).datepicker({
|
|
||||||
defaultDate: '',
|
|
||||||
dateFormat: 'yy-mm-dd',
|
|
||||||
numberOfMonths: 1,
|
|
||||||
showButtonPanel: true,
|
|
||||||
onSelect: function() {
|
|
||||||
date_picker_select( $( this ) );
|
|
||||||
}
|
|
||||||
});
|
|
||||||
$( this ).find( 'input' ).each( function() { date_picker_select( $( this ) ); } );
|
|
||||||
});
|
|
||||||
|
|
||||||
// Attribute Tables.
|
|
||||||
|
|
||||||
// Initial order.
|
|
||||||
var woocommerce_attribute_items = $( '.product_attributes' ).find( '.woocommerce_attribute' ).get();
|
|
||||||
|
|
||||||
woocommerce_attribute_items.sort( function( a, b ) {
|
|
||||||
var compA = parseInt( $( a ).attr( 'rel' ), 10 );
|
|
||||||
var compB = parseInt( $( b ).attr( 'rel' ), 10 );
|
|
||||||
return ( compA < compB ) ? -1 : ( compA > compB ) ? 1 : 0;
|
|
||||||
});
|
|
||||||
$( woocommerce_attribute_items ).each( function( index, el ) {
|
|
||||||
$( '.product_attributes' ).append( el );
|
|
||||||
});
|
|
||||||
|
|
||||||
function attribute_row_indexes() {
|
|
||||||
$( '.product_attributes .woocommerce_attribute' ).each( function( index, el ) {
|
|
||||||
$( '.attribute_position', el ).val( parseInt( $( el ).index( '.product_attributes .woocommerce_attribute' ), 10 ) );
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
$( '.product_attributes .woocommerce_attribute' ).each( function( index, el ) {
|
|
||||||
if ( $( el ).css( 'display' ) !== 'none' && $( el ).is( '.taxonomy' ) ) {
|
|
||||||
$( 'select.attribute_taxonomy' ).find( 'option[value="' + $( el ).data( 'taxonomy' ) + '"]' ).attr( 'disabled', 'disabled' );
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Add rows.
|
|
||||||
$( 'button.add_attribute' ).on( 'click', function() {
|
|
||||||
var size = $( '.product_attributes .woocommerce_attribute' ).length;
|
|
||||||
var attribute = $( 'select.attribute_taxonomy' ).val();
|
|
||||||
var $wrapper = $( this ).closest( '#product_attributes' );
|
|
||||||
var $attributes = $wrapper.find( '.product_attributes' );
|
|
||||||
var product_type = $( 'select#product-type' ).val();
|
|
||||||
var data = {
|
|
||||||
action: 'woocommerce_add_attribute',
|
|
||||||
taxonomy: attribute,
|
|
||||||
i: size,
|
|
||||||
security: woocommerce_admin_meta_boxes.add_attribute_nonce
|
|
||||||
};
|
|
||||||
|
|
||||||
$wrapper.block({
|
|
||||||
message: null,
|
|
||||||
overlayCSS: {
|
|
||||||
background: '#fff',
|
|
||||||
opacity: 0.6
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$.post( woocommerce_admin_meta_boxes.ajax_url, data, function( response ) {
|
|
||||||
$attributes.append( response );
|
|
||||||
|
|
||||||
if ( 'variable' !== product_type ) {
|
|
||||||
$attributes.find( '.enable_variation' ).hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
$( document.body ).trigger( 'wc-enhanced-select-init' );
|
|
||||||
|
|
||||||
attribute_row_indexes();
|
|
||||||
|
|
||||||
$attributes.find( '.woocommerce_attribute' ).last().find( 'h3' ).trigger( 'click' );
|
|
||||||
|
|
||||||
$wrapper.unblock();
|
|
||||||
|
|
||||||
$( document.body ).trigger( 'woocommerce_added_attribute' );
|
|
||||||
});
|
|
||||||
|
|
||||||
if ( attribute ) {
|
|
||||||
$( 'select.attribute_taxonomy' ).find( 'option[value="' + attribute + '"]' ).attr( 'disabled','disabled' );
|
|
||||||
$( 'select.attribute_taxonomy' ).val( '' );
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
$( '.product_attributes' ).on( 'blur', 'input.attribute_name', function() {
|
|
||||||
$( this ).closest( '.woocommerce_attribute' ).find( 'strong.attribute_name' ).text( $( this ).val() );
|
|
||||||
});
|
|
||||||
|
|
||||||
$( '.product_attributes' ).on( 'click', 'button.select_all_attributes', function() {
|
|
||||||
$( this ).closest( 'td' ).find( 'select option' ).prop( 'selected', 'selected' );
|
|
||||||
$( this ).closest( 'td' ).find( 'select' ).trigger( 'change' );
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
$( '.product_attributes' ).on( 'click', 'button.select_no_attributes', function() {
|
|
||||||
$( this ).closest( 'td' ).find( 'select option' ).removeAttr( 'selected' );
|
|
||||||
$( this ).closest( 'td' ).find( 'select' ).trigger( 'change' );
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
$( '.product_attributes' ).on( 'click', '.remove_row', function() {
|
|
||||||
if ( window.confirm( woocommerce_admin_meta_boxes.remove_attribute ) ) {
|
|
||||||
var $parent = $( this ).parent().parent();
|
|
||||||
|
|
||||||
if ( $parent.is( '.taxonomy' ) ) {
|
|
||||||
$parent.find( 'select, input[type=text]' ).val( '' );
|
|
||||||
$parent.hide();
|
|
||||||
$( 'select.attribute_taxonomy' ).find( 'option[value="' + $parent.data( 'taxonomy' ) + '"]' ).removeAttr( 'disabled' );
|
|
||||||
} else {
|
|
||||||
$parent.find( 'select, input[type=text]' ).val( '' );
|
|
||||||
$parent.hide();
|
|
||||||
attribute_row_indexes();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Attribute ordering.
|
|
||||||
$( '.product_attributes' ).sortable({
|
|
||||||
items: '.woocommerce_attribute',
|
|
||||||
cursor: 'move',
|
|
||||||
axis: 'y',
|
|
||||||
handle: 'h3',
|
|
||||||
scrollSensitivity: 40,
|
|
||||||
forcePlaceholderSize: true,
|
|
||||||
helper: 'clone',
|
|
||||||
opacity: 0.65,
|
|
||||||
placeholder: 'wc-metabox-sortable-placeholder',
|
|
||||||
start: function( event, ui ) {
|
|
||||||
ui.item.css( 'background-color', '#f6f6f6' );
|
|
||||||
},
|
|
||||||
stop: function( event, ui ) {
|
|
||||||
ui.item.removeAttr( 'style' );
|
|
||||||
attribute_row_indexes();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Add a new attribute (via ajax).
|
|
||||||
$( '.product_attributes' ).on( 'click', 'button.add_new_attribute', function() {
|
|
||||||
|
|
||||||
$( '.product_attributes' ).block({
|
|
||||||
message: null,
|
|
||||||
overlayCSS: {
|
|
||||||
background: '#fff',
|
|
||||||
opacity: 0.6
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var $wrapper = $( this ).closest( '.woocommerce_attribute' );
|
|
||||||
var attribute = $wrapper.data( 'taxonomy' );
|
|
||||||
var new_attribute_name = window.prompt( woocommerce_admin_meta_boxes.new_attribute_prompt );
|
|
||||||
|
|
||||||
if ( new_attribute_name ) {
|
|
||||||
|
|
||||||
var data = {
|
|
||||||
action: 'woocommerce_add_new_attribute',
|
|
||||||
taxonomy: attribute,
|
|
||||||
term: new_attribute_name,
|
|
||||||
security: woocommerce_admin_meta_boxes.add_attribute_nonce
|
|
||||||
};
|
|
||||||
|
|
||||||
$.post( woocommerce_admin_meta_boxes.ajax_url, data, function( response ) {
|
|
||||||
|
|
||||||
if ( response.error ) {
|
|
||||||
// Error.
|
|
||||||
window.alert( response.error );
|
|
||||||
} else if ( response.slug ) {
|
|
||||||
// Success.
|
|
||||||
$wrapper.find( 'select.attribute_values' )
|
|
||||||
.append( '<option value="' + response.term_id + '" selected="selected">' + response.name + '</option>' );
|
|
||||||
$wrapper.find( 'select.attribute_values' ).trigger( 'change' );
|
|
||||||
}
|
|
||||||
|
|
||||||
$( '.product_attributes' ).unblock();
|
|
||||||
});
|
|
||||||
|
|
||||||
} else {
|
|
||||||
$( '.product_attributes' ).unblock();
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Save attributes and update variations.
|
|
||||||
$( '.save_attributes' ).on( 'click', function() {
|
|
||||||
|
|
||||||
$( '.product_attributes' ).block({
|
|
||||||
message: null,
|
|
||||||
overlayCSS: {
|
|
||||||
background: '#fff',
|
|
||||||
opacity: 0.6
|
|
||||||
}
|
|
||||||
});
|
|
||||||
var original_data = $( '.product_attributes' ).find( 'input, select, textarea' );
|
|
||||||
var data = {
|
|
||||||
post_id : woocommerce_admin_meta_boxes.post_id,
|
|
||||||
product_type: $( '#product-type' ).val(),
|
|
||||||
data : original_data.serialize(),
|
|
||||||
action : 'woocommerce_save_attributes',
|
|
||||||
security : woocommerce_admin_meta_boxes.save_attributes_nonce
|
|
||||||
};
|
|
||||||
|
|
||||||
$.post( woocommerce_admin_meta_boxes.ajax_url, data, function( response ) {
|
|
||||||
if ( response.error ) {
|
|
||||||
// Error.
|
|
||||||
window.alert( response.error );
|
|
||||||
} else if ( response.data ) {
|
|
||||||
// Success.
|
|
||||||
$( '.product_attributes' ).html( response.data.html );
|
|
||||||
$( '.product_attributes' ).unblock();
|
|
||||||
|
|
||||||
// Hide the 'Used for variations' checkbox if not viewing a variable product
|
|
||||||
show_and_hide_panels();
|
|
||||||
|
|
||||||
// Make sure the dropdown is not disabled for empty value attributes.
|
|
||||||
$( 'select.attribute_taxonomy' ).find( 'option' ).prop( 'disabled', false );
|
|
||||||
|
|
||||||
$( '.product_attributes .woocommerce_attribute' ).each( function( index, el ) {
|
|
||||||
if ( $( el ).css( 'display' ) !== 'none' && $( el ).is( '.taxonomy' ) ) {
|
|
||||||
$( 'select.attribute_taxonomy' )
|
|
||||||
.find( 'option[value="' + $( el ).data( 'taxonomy' ) + '"]' )
|
|
||||||
.prop( 'disabled', true );
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Reload variations panel.
|
|
||||||
var this_page = window.location.toString();
|
|
||||||
this_page = this_page.replace( 'post-new.php?', 'post.php?post=' + woocommerce_admin_meta_boxes.post_id + '&action=edit&' );
|
|
||||||
|
|
||||||
$( '#variable_product_options' ).load( this_page + ' #variable_product_options_inner', function() {
|
|
||||||
$( '#variable_product_options' ).trigger( 'reload' );
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Uploading files.
|
|
||||||
var downloadable_file_frame;
|
|
||||||
var file_path_field;
|
|
||||||
|
|
||||||
$( document.body ).on( 'click', '.upload_file_button', function( event ) {
|
|
||||||
var $el = $( this );
|
|
||||||
|
|
||||||
file_path_field = $el.closest( 'tr' ).find( 'td.file_url input' );
|
|
||||||
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
// If the media frame already exists, reopen it.
|
|
||||||
if ( downloadable_file_frame ) {
|
|
||||||
downloadable_file_frame.open();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var downloadable_file_states = [
|
|
||||||
// Main states.
|
|
||||||
new wp.media.controller.Library({
|
|
||||||
library: wp.media.query(),
|
|
||||||
multiple: true,
|
|
||||||
title: $el.data('choose'),
|
|
||||||
priority: 20,
|
|
||||||
filterable: 'uploaded'
|
|
||||||
})
|
|
||||||
];
|
|
||||||
|
|
||||||
// Create the media frame.
|
|
||||||
downloadable_file_frame = wp.media.frames.downloadable_file = wp.media({
|
|
||||||
// Set the title of the modal.
|
|
||||||
title: $el.data('choose'),
|
|
||||||
library: {
|
|
||||||
type: ''
|
|
||||||
},
|
|
||||||
button: {
|
|
||||||
text: $el.data('update')
|
|
||||||
},
|
|
||||||
multiple: true,
|
|
||||||
states: downloadable_file_states
|
|
||||||
});
|
|
||||||
|
|
||||||
// When an image is selected, run a callback.
|
|
||||||
downloadable_file_frame.on( 'select', function() {
|
|
||||||
var file_path = '';
|
|
||||||
var selection = downloadable_file_frame.state().get( 'selection' );
|
|
||||||
|
|
||||||
selection.map( function( attachment ) {
|
|
||||||
attachment = attachment.toJSON();
|
|
||||||
if ( attachment.url ) {
|
|
||||||
file_path = attachment.url;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
file_path_field.val( file_path ).trigger( 'change' );
|
|
||||||
});
|
|
||||||
|
|
||||||
// Set post to 0 and set our custom type.
|
|
||||||
downloadable_file_frame.on( 'ready', function() {
|
|
||||||
downloadable_file_frame.uploader.options.uploader.params = {
|
|
||||||
type: 'downloadable_product'
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
// Finally, open the modal.
|
|
||||||
downloadable_file_frame.open();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Download ordering.
|
|
||||||
$( '.downloadable_files tbody' ).sortable({
|
|
||||||
items: 'tr',
|
|
||||||
cursor: 'move',
|
|
||||||
axis: 'y',
|
|
||||||
handle: 'td.sort',
|
|
||||||
scrollSensitivity: 40,
|
|
||||||
forcePlaceholderSize: true,
|
|
||||||
helper: 'clone',
|
|
||||||
opacity: 0.65
|
|
||||||
});
|
|
||||||
|
|
||||||
// Product gallery file uploads.
|
|
||||||
var product_gallery_frame;
|
|
||||||
var $image_gallery_ids = $( '#product_image_gallery' );
|
|
||||||
var $product_images = $( '#product_images_container' ).find( 'ul.product_images' );
|
|
||||||
|
|
||||||
$( '.add_product_images' ).on( 'click', 'a', function( event ) {
|
|
||||||
var $el = $( this );
|
|
||||||
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
// If the media frame already exists, reopen it.
|
|
||||||
if ( product_gallery_frame ) {
|
|
||||||
product_gallery_frame.open();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the media frame.
|
|
||||||
product_gallery_frame = wp.media.frames.product_gallery = wp.media({
|
|
||||||
// Set the title of the modal.
|
|
||||||
title: $el.data( 'choose' ),
|
|
||||||
button: {
|
|
||||||
text: $el.data( 'update' )
|
|
||||||
},
|
|
||||||
states: [
|
|
||||||
new wp.media.controller.Library({
|
|
||||||
title: $el.data( 'choose' ),
|
|
||||||
filterable: 'all',
|
|
||||||
multiple: true
|
|
||||||
})
|
|
||||||
]
|
|
||||||
});
|
|
||||||
|
|
||||||
// When an image is selected, run a callback.
|
|
||||||
product_gallery_frame.on( 'select', function() {
|
|
||||||
var selection = product_gallery_frame.state().get( 'selection' );
|
|
||||||
var attachment_ids = $image_gallery_ids.val();
|
|
||||||
|
|
||||||
selection.map( function( attachment ) {
|
|
||||||
attachment = attachment.toJSON();
|
|
||||||
|
|
||||||
if ( attachment.id ) {
|
|
||||||
attachment_ids = attachment_ids ? attachment_ids + ',' + attachment.id : attachment.id;
|
|
||||||
var attachment_image = attachment.sizes && attachment.sizes.thumbnail ? attachment.sizes.thumbnail.url : attachment.url;
|
|
||||||
|
|
||||||
$product_images.append(
|
|
||||||
'<li class="image" data-attachment_id="' + attachment.id + '"><img src="' + attachment_image +
|
|
||||||
'" /><ul class="actions"><li><a href="#" class="delete" title="' + $el.data('delete') + '">' +
|
|
||||||
$el.data('text') + '</a></li></ul></li>'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$image_gallery_ids.val( attachment_ids );
|
|
||||||
});
|
|
||||||
|
|
||||||
// Finally, open the modal.
|
|
||||||
product_gallery_frame.open();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Image ordering.
|
|
||||||
$product_images.sortable({
|
|
||||||
items: 'li.image',
|
|
||||||
cursor: 'move',
|
|
||||||
scrollSensitivity: 40,
|
|
||||||
forcePlaceholderSize: true,
|
|
||||||
forceHelperSize: false,
|
|
||||||
helper: 'clone',
|
|
||||||
opacity: 0.65,
|
|
||||||
placeholder: 'wc-metabox-sortable-placeholder',
|
|
||||||
start: function( event, ui ) {
|
|
||||||
ui.item.css( 'background-color', '#f6f6f6' );
|
|
||||||
},
|
|
||||||
stop: function( event, ui ) {
|
|
||||||
ui.item.removeAttr( 'style' );
|
|
||||||
},
|
|
||||||
update: function() {
|
|
||||||
var attachment_ids = '';
|
|
||||||
|
|
||||||
$( '#product_images_container' ).find( 'ul li.image' ).css( 'cursor', 'default' ).each( function() {
|
|
||||||
var attachment_id = $( this ).attr( 'data-attachment_id' );
|
|
||||||
attachment_ids = attachment_ids + attachment_id + ',';
|
|
||||||
});
|
|
||||||
|
|
||||||
$image_gallery_ids.val( attachment_ids );
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Remove images.
|
|
||||||
$( '#product_images_container' ).on( 'click', 'a.delete', function() {
|
|
||||||
$( this ).closest( 'li.image' ).remove();
|
|
||||||
|
|
||||||
var attachment_ids = '';
|
|
||||||
|
|
||||||
$( '#product_images_container' ).find( 'ul li.image' ).css( 'cursor', 'default' ).each( function() {
|
|
||||||
var attachment_id = $( this ).attr( 'data-attachment_id' );
|
|
||||||
attachment_ids = attachment_ids + attachment_id + ',';
|
|
||||||
});
|
|
||||||
|
|
||||||
$image_gallery_ids.val( attachment_ids );
|
|
||||||
|
|
||||||
// Remove any lingering tooltips.
|
|
||||||
$( '#tiptip_holder' ).removeAttr( 'style' );
|
|
||||||
$( '#tiptip_arrow' ).removeAttr( 'style' );
|
|
||||||
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,68 +0,0 @@
|
||||||
jQuery( function ( $ ) {
|
|
||||||
|
|
||||||
// Run tipTip
|
|
||||||
function runTipTip() {
|
|
||||||
// Remove any lingering tooltips
|
|
||||||
$( '#tiptip_holder' ).removeAttr( 'style' );
|
|
||||||
$( '#tiptip_arrow' ).removeAttr( 'style' );
|
|
||||||
$( '.tips' ).tipTip({
|
|
||||||
'attribute': 'data-tip',
|
|
||||||
'fadeIn': 50,
|
|
||||||
'fadeOut': 50,
|
|
||||||
'delay': 200,
|
|
||||||
'keepAlive': true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
runTipTip();
|
|
||||||
|
|
||||||
$( '.wc-metaboxes-wrapper' ).on( 'click', '.wc-metabox > h3', function() {
|
|
||||||
$( this ).parent( '.wc-metabox' ).toggleClass( 'closed' ).toggleClass( 'open' );
|
|
||||||
});
|
|
||||||
|
|
||||||
// Tabbed Panels
|
|
||||||
$( document.body ).on( 'wc-init-tabbed-panels', function() {
|
|
||||||
$( 'ul.wc-tabs' ).show();
|
|
||||||
$( 'ul.wc-tabs a' ).on( 'click', function( e ) {
|
|
||||||
e.preventDefault();
|
|
||||||
var panel_wrap = $( this ).closest( 'div.panel-wrap' );
|
|
||||||
$( 'ul.wc-tabs li', panel_wrap ).removeClass( 'active' );
|
|
||||||
$( this ).parent().addClass( 'active' );
|
|
||||||
$( 'div.panel', panel_wrap ).hide();
|
|
||||||
$( $( this ).attr( 'href' ) ).show();
|
|
||||||
});
|
|
||||||
$( 'div.panel-wrap' ).each( function() {
|
|
||||||
$( this ).find( 'ul.wc-tabs li' ).eq( 0 ).find( 'a' ).trigger( 'click' );
|
|
||||||
});
|
|
||||||
}).trigger( 'wc-init-tabbed-panels' );
|
|
||||||
|
|
||||||
// Date Picker
|
|
||||||
$( document.body ).on( 'wc-init-datepickers', function() {
|
|
||||||
$( '.date-picker-field, .date-picker' ).datepicker({
|
|
||||||
dateFormat: 'yy-mm-dd',
|
|
||||||
numberOfMonths: 1,
|
|
||||||
showButtonPanel: true
|
|
||||||
});
|
|
||||||
}).trigger( 'wc-init-datepickers' );
|
|
||||||
|
|
||||||
// Meta-Boxes - Open/close
|
|
||||||
$( '.wc-metaboxes-wrapper' ).on( 'click', '.wc-metabox h3', function( event ) {
|
|
||||||
// If the user clicks on some form input inside the h3, like a select list (for variations), the box should not be toggled
|
|
||||||
if ( $( event.target ).filter( ':input, option, .sort' ).length ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$( this ).next( '.wc-metabox-content' ).stop().slideToggle();
|
|
||||||
})
|
|
||||||
.on( 'click', '.expand_all', function() {
|
|
||||||
$( this ).closest( '.wc-metaboxes-wrapper' ).find( '.wc-metabox > .wc-metabox-content' ).show();
|
|
||||||
return false;
|
|
||||||
})
|
|
||||||
.on( 'click', '.close_all', function() {
|
|
||||||
$( this ).closest( '.wc-metaboxes-wrapper' ).find( '.wc-metabox > .wc-metabox-content' ).hide();
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
$( '.wc-metabox.closed' ).each( function() {
|
|
||||||
$( this ).find( '.wc-metabox-content' ).hide();
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,167 +0,0 @@
|
||||||
/*global inlineEditPost, woocommerce_admin, woocommerce_quick_edit */
|
|
||||||
jQuery(
|
|
||||||
function( $ ) {
|
|
||||||
$( '#the-list' ).on(
|
|
||||||
'click',
|
|
||||||
'.editinline',
|
|
||||||
function() {
|
|
||||||
|
|
||||||
inlineEditPost.revert();
|
|
||||||
|
|
||||||
var post_id = $( this ).closest( 'tr' ).attr( 'id' );
|
|
||||||
|
|
||||||
post_id = post_id.replace( 'post-', '' );
|
|
||||||
|
|
||||||
var $wc_inline_data = $( '#woocommerce_inline_' + post_id );
|
|
||||||
|
|
||||||
var sku = $wc_inline_data.find( '.sku' ).text(),
|
|
||||||
regular_price = $wc_inline_data.find( '.regular_price' ).text(),
|
|
||||||
sale_price = $wc_inline_data.find( '.sale_price ' ).text(),
|
|
||||||
weight = $wc_inline_data.find( '.weight' ).text(),
|
|
||||||
length = $wc_inline_data.find( '.length' ).text(),
|
|
||||||
width = $wc_inline_data.find( '.width' ).text(),
|
|
||||||
height = $wc_inline_data.find( '.height' ).text(),
|
|
||||||
shipping_class = $wc_inline_data.find( '.shipping_class' ).text(),
|
|
||||||
visibility = $wc_inline_data.find( '.visibility' ).text(),
|
|
||||||
stock_status = $wc_inline_data.find( '.stock_status' ).text(),
|
|
||||||
stock = $wc_inline_data.find( '.stock' ).text(),
|
|
||||||
featured = $wc_inline_data.find( '.featured' ).text(),
|
|
||||||
manage_stock = $wc_inline_data.find( '.manage_stock' ).text(),
|
|
||||||
menu_order = $wc_inline_data.find( '.menu_order' ).text(),
|
|
||||||
tax_status = $wc_inline_data.find( '.tax_status' ).text(),
|
|
||||||
tax_class = $wc_inline_data.find( '.tax_class' ).text(),
|
|
||||||
backorders = $wc_inline_data.find( '.backorders' ).text(),
|
|
||||||
product_type = $wc_inline_data.find( '.product_type' ).text();
|
|
||||||
|
|
||||||
var formatted_regular_price = regular_price.replace( '.', woocommerce_admin.mon_decimal_point ),
|
|
||||||
formatted_sale_price = sale_price.replace( '.', woocommerce_admin.mon_decimal_point );
|
|
||||||
|
|
||||||
$( 'input[name="_sku"]', '.inline-edit-row' ).val( sku );
|
|
||||||
$( 'input[name="_regular_price"]', '.inline-edit-row' ).val( formatted_regular_price );
|
|
||||||
$( 'input[name="_sale_price"]', '.inline-edit-row' ).val( formatted_sale_price );
|
|
||||||
$( 'input[name="_weight"]', '.inline-edit-row' ).val( weight );
|
|
||||||
$( 'input[name="_length"]', '.inline-edit-row' ).val( length );
|
|
||||||
$( 'input[name="_width"]', '.inline-edit-row' ).val( width );
|
|
||||||
$( 'input[name="_height"]', '.inline-edit-row' ).val( height );
|
|
||||||
|
|
||||||
$( 'select[name="_shipping_class"] option:selected', '.inline-edit-row' ).attr( 'selected', false ).trigger( 'change' );
|
|
||||||
$( 'select[name="_shipping_class"] option[value="' + shipping_class + '"]' ).attr( 'selected', 'selected' )
|
|
||||||
.trigger( 'change' );
|
|
||||||
|
|
||||||
$( 'input[name="_stock"]', '.inline-edit-row' ).val( stock );
|
|
||||||
$( 'input[name="menu_order"]', '.inline-edit-row' ).val( menu_order );
|
|
||||||
|
|
||||||
$(
|
|
||||||
'select[name="_tax_status"] option, ' +
|
|
||||||
'select[name="_tax_class"] option, ' +
|
|
||||||
'select[name="_visibility"] option, ' +
|
|
||||||
'select[name="_stock_status"] option, ' +
|
|
||||||
'select[name="_backorders"] option'
|
|
||||||
).removeAttr( 'selected' );
|
|
||||||
|
|
||||||
var is_variable_product = 'variable' === product_type;
|
|
||||||
$( 'select[name="_stock_status"] ~ .wc-quick-edit-warning', '.inline-edit-row' ).toggle( is_variable_product );
|
|
||||||
$( 'select[name="_stock_status"] option[value="' + (is_variable_product ? '' : stock_status) + '"]', '.inline-edit-row' )
|
|
||||||
.attr( 'selected', 'selected' );
|
|
||||||
|
|
||||||
$( 'select[name="_tax_status"] option[value="' + tax_status + '"]', '.inline-edit-row' ).attr( 'selected', 'selected' );
|
|
||||||
$( 'select[name="_tax_class"] option[value="' + tax_class + '"]', '.inline-edit-row' ).attr( 'selected', 'selected' );
|
|
||||||
$( 'select[name="_visibility"] option[value="' + visibility + '"]', '.inline-edit-row' ).attr( 'selected', 'selected' );
|
|
||||||
$( 'select[name="_backorders"] option[value="' + backorders + '"]', '.inline-edit-row' ).attr( 'selected', 'selected' );
|
|
||||||
|
|
||||||
if ( 'yes' === featured ) {
|
|
||||||
$( 'input[name="_featured"]', '.inline-edit-row' ).attr( 'checked', 'checked' );
|
|
||||||
} else {
|
|
||||||
$( 'input[name="_featured"]', '.inline-edit-row' ).removeAttr( 'checked' );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Conditional display.
|
|
||||||
var product_is_virtual = $wc_inline_data.find( '.product_is_virtual' ).text();
|
|
||||||
|
|
||||||
var product_supports_stock_status = 'external' !== product_type;
|
|
||||||
var product_supports_stock_fields = 'external' !== product_type && 'grouped' !== product_type;
|
|
||||||
|
|
||||||
$( '.stock_fields, .manage_stock_field, .stock_status_field, .backorder_field' ).show();
|
|
||||||
|
|
||||||
if ( product_supports_stock_fields ) {
|
|
||||||
if ( 'yes' === manage_stock ) {
|
|
||||||
$( '.stock_qty_field, .backorder_field', '.inline-edit-row' ).show().removeAttr( 'style' );
|
|
||||||
$( '.stock_status_field' ).hide();
|
|
||||||
$( '.manage_stock_field input' ).prop( 'checked', true );
|
|
||||||
} else {
|
|
||||||
$( '.stock_qty_field, .backorder_field', '.inline-edit-row' ).hide();
|
|
||||||
$( '.stock_status_field' ).show().removeAttr( 'style' );
|
|
||||||
$( '.manage_stock_field input' ).prop( 'checked', false );
|
|
||||||
}
|
|
||||||
} else if ( product_supports_stock_status ) {
|
|
||||||
$( '.stock_fields, .manage_stock_field, .backorder_field' ).hide();
|
|
||||||
} else {
|
|
||||||
$( '.stock_fields, .manage_stock_field, .stock_status_field, .backorder_field' ).hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( 'simple' === product_type || 'external' === product_type ) {
|
|
||||||
$( '.price_fields', '.inline-edit-row' ).show().removeAttr( 'style' );
|
|
||||||
} else {
|
|
||||||
$( '.price_fields', '.inline-edit-row' ).hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( 'yes' === product_is_virtual ) {
|
|
||||||
$( '.dimension_fields', '.inline-edit-row' ).hide();
|
|
||||||
} else {
|
|
||||||
$( '.dimension_fields', '.inline-edit-row' ).show().removeAttr( 'style' );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rename core strings.
|
|
||||||
$( 'input[name="comment_status"]' ).parent().find( '.checkbox-title' ).text( woocommerce_quick_edit.strings.allow_reviews );
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
$( '#the-list' ).on(
|
|
||||||
'change',
|
|
||||||
'.inline-edit-row input[name="_manage_stock"]',
|
|
||||||
function() {
|
|
||||||
|
|
||||||
if ( $( this ).is( ':checked' ) ) {
|
|
||||||
$( '.stock_qty_field, .backorder_field', '.inline-edit-row' ).show().removeAttr( 'style' );
|
|
||||||
$( '.stock_status_field' ).hide();
|
|
||||||
} else {
|
|
||||||
$( '.stock_qty_field, .backorder_field', '.inline-edit-row' ).hide();
|
|
||||||
$( '.stock_status_field' ).show().removeAttr( 'style' );
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
$( '#wpbody' ).on(
|
|
||||||
'click',
|
|
||||||
'#doaction, #doaction2',
|
|
||||||
function() {
|
|
||||||
$( 'input.text', '.inline-edit-row' ).val( '' );
|
|
||||||
$( '#woocommerce-fields' ).find( 'select' ).prop( 'selectedIndex', 0 );
|
|
||||||
$( '#woocommerce-fields-bulk' ).find( '.inline-edit-group .change-input' ).hide();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
$( '#wpbody' ).on(
|
|
||||||
'change',
|
|
||||||
'#woocommerce-fields-bulk .inline-edit-group .change_to',
|
|
||||||
function() {
|
|
||||||
|
|
||||||
if ( 0 < $( this ).val() ) {
|
|
||||||
$( this ).closest( 'div' ).find( '.change-input' ).show();
|
|
||||||
} else {
|
|
||||||
$( this ).closest( 'div' ).find( '.change-input' ).hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
$( '#wpbody' ).on(
|
|
||||||
'click',
|
|
||||||
'.trash-product',
|
|
||||||
function() {
|
|
||||||
return window.confirm( woocommerce_admin.i18n_delete_product_notice );
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
|
@ -1,383 +0,0 @@
|
||||||
/* global htmlSettingsTaxLocalizeScript, ajaxurl */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used by woocommerce/includes/admin/settings/views/html-settings-tax.php
|
|
||||||
*/
|
|
||||||
( function( $, data, wp, ajaxurl ) {
|
|
||||||
$( function() {
|
|
||||||
|
|
||||||
if ( ! String.prototype.trim ) {
|
|
||||||
String.prototype.trim = function () {
|
|
||||||
return this.replace( /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '' );
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
var rowTemplate = wp.template( 'wc-tax-table-row' ),
|
|
||||||
rowTemplateEmpty = wp.template( 'wc-tax-table-row-empty' ),
|
|
||||||
paginationTemplate = wp.template( 'wc-tax-table-pagination' ),
|
|
||||||
$table = $( '.wc_tax_rates' ),
|
|
||||||
$tbody = $( '#rates' ),
|
|
||||||
$save_button = $( ':input[name="save"]' ),
|
|
||||||
$pagination = $( '#rates-pagination' ),
|
|
||||||
$search_field = $( '#rates-search .wc-tax-rates-search-field' ),
|
|
||||||
$submit = $( '.submit .button-primary[type=submit]' ),
|
|
||||||
WCTaxTableModelConstructor = Backbone.Model.extend({
|
|
||||||
changes: {},
|
|
||||||
setRateAttribute: function( rateID, attribute, value ) {
|
|
||||||
var rates = _.indexBy( this.get( 'rates' ), 'tax_rate_id' ),
|
|
||||||
changes = {};
|
|
||||||
|
|
||||||
if ( rates[ rateID ][ attribute ] !== value ) {
|
|
||||||
changes[ rateID ] = {};
|
|
||||||
changes[ rateID ][ attribute ] = value;
|
|
||||||
rates[ rateID ][ attribute ] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.logChanges( changes );
|
|
||||||
},
|
|
||||||
logChanges: function( changedRows ) {
|
|
||||||
var changes = this.changes || {};
|
|
||||||
|
|
||||||
_.each( changedRows, function( row, id ) {
|
|
||||||
changes[ id ] = _.extend( changes[ id ] || {
|
|
||||||
tax_rate_id : id
|
|
||||||
}, row );
|
|
||||||
} );
|
|
||||||
|
|
||||||
this.changes = changes;
|
|
||||||
this.trigger( 'change:rates' );
|
|
||||||
},
|
|
||||||
getFilteredRates: function() {
|
|
||||||
var rates = this.get( 'rates' ),
|
|
||||||
search = $search_field.val().toLowerCase();
|
|
||||||
|
|
||||||
if ( search.length ) {
|
|
||||||
rates = _.filter( rates, function( rate ) {
|
|
||||||
var search_text = _.toArray( rate ).join( ' ' ).toLowerCase();
|
|
||||||
return ( -1 !== search_text.indexOf( search ) );
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
|
|
||||||
rates = _.sortBy( rates, function( rate ) {
|
|
||||||
return parseInt( rate.tax_rate_order, 10 );
|
|
||||||
} );
|
|
||||||
|
|
||||||
return rates;
|
|
||||||
},
|
|
||||||
block: function() {
|
|
||||||
$( '.wc_tax_rates' ).block({
|
|
||||||
message: null,
|
|
||||||
overlayCSS: {
|
|
||||||
background: '#fff',
|
|
||||||
opacity: 0.6
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
unblock: function() {
|
|
||||||
$( '.wc_tax_rates' ).unblock();
|
|
||||||
},
|
|
||||||
save: function() {
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
self.block();
|
|
||||||
|
|
||||||
Backbone.ajax({
|
|
||||||
method: 'POST',
|
|
||||||
dataType: 'json',
|
|
||||||
url: ajaxurl + ( ajaxurl.indexOf( '?' ) > 0 ? '&' : '?' ) + 'action=woocommerce_tax_rates_save_changes',
|
|
||||||
data: {
|
|
||||||
current_class: data.current_class,
|
|
||||||
wc_tax_nonce: data.wc_tax_nonce,
|
|
||||||
changes: self.changes
|
|
||||||
},
|
|
||||||
success: function( response, textStatus ) {
|
|
||||||
if ( 'success' === textStatus && response.success ) {
|
|
||||||
WCTaxTableModelInstance.set( 'rates', response.data.rates );
|
|
||||||
WCTaxTableModelInstance.trigger( 'change:rates' );
|
|
||||||
|
|
||||||
WCTaxTableModelInstance.changes = {};
|
|
||||||
WCTaxTableModelInstance.trigger( 'saved:rates' );
|
|
||||||
|
|
||||||
// Reload view.
|
|
||||||
WCTaxTableInstance.render();
|
|
||||||
}
|
|
||||||
|
|
||||||
self.unblock();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} ),
|
|
||||||
WCTaxTableViewConstructor = Backbone.View.extend({
|
|
||||||
rowTemplate: rowTemplate,
|
|
||||||
per_page: data.limit,
|
|
||||||
page: data.page,
|
|
||||||
initialize: function() {
|
|
||||||
var qty_pages = Math.ceil( _.toArray( this.model.get( 'rates' ) ).length / this.per_page );
|
|
||||||
|
|
||||||
this.qty_pages = 0 === qty_pages ? 1 : qty_pages;
|
|
||||||
this.page = this.sanitizePage( data.page );
|
|
||||||
|
|
||||||
this.listenTo( this.model, 'change:rates', this.setUnloadConfirmation );
|
|
||||||
this.listenTo( this.model, 'saved:rates', this.clearUnloadConfirmation );
|
|
||||||
$tbody.on( 'change autocompletechange', ':input', { view: this }, this.updateModelOnChange );
|
|
||||||
$search_field.on( 'keyup search', { view: this }, this.onSearchField );
|
|
||||||
$pagination.on( 'click', 'a', { view: this }, this.onPageChange );
|
|
||||||
$pagination.on( 'change', 'input', { view: this }, this.onPageChange );
|
|
||||||
$( window ).on( 'beforeunload', { view: this }, this.unloadConfirmation );
|
|
||||||
$submit.on( 'click', { view: this }, this.onSubmit );
|
|
||||||
$save_button.prop( 'disabled', true );
|
|
||||||
|
|
||||||
// Can bind these directly to the buttons, as they won't get overwritten.
|
|
||||||
$table.find( '.insert' ).on( 'click', { view: this }, this.onAddNewRow );
|
|
||||||
$table.find( '.remove_tax_rates' ).on( 'click', { view: this }, this.onDeleteRow );
|
|
||||||
$table.find( '.export' ).on( 'click', { view: this }, this.onExport );
|
|
||||||
},
|
|
||||||
render: function() {
|
|
||||||
var rates = this.model.getFilteredRates(),
|
|
||||||
qty_rates = _.size( rates ),
|
|
||||||
qty_pages = Math.ceil( qty_rates / this.per_page ),
|
|
||||||
first_index = 0 === qty_rates ? 0 : this.per_page * ( this.page - 1 ),
|
|
||||||
last_index = this.per_page * this.page,
|
|
||||||
paged_rates = _.toArray( rates ).slice( first_index, last_index ),
|
|
||||||
view = this;
|
|
||||||
|
|
||||||
// Blank out the contents.
|
|
||||||
this.$el.empty();
|
|
||||||
|
|
||||||
if ( paged_rates.length ) {
|
|
||||||
// Populate $tbody with the current page of results.
|
|
||||||
$.each( paged_rates, function( id, rowData ) {
|
|
||||||
view.$el.append( view.rowTemplate( rowData ) );
|
|
||||||
} );
|
|
||||||
} else {
|
|
||||||
view.$el.append( rowTemplateEmpty() );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize autocomplete for countries.
|
|
||||||
this.$el.find( 'td.country input' ).autocomplete({
|
|
||||||
source: data.countries,
|
|
||||||
minLength: 2
|
|
||||||
});
|
|
||||||
|
|
||||||
// Initialize autocomplete for states.
|
|
||||||
this.$el.find( 'td.state input' ).autocomplete({
|
|
||||||
source: data.states,
|
|
||||||
minLength: 3
|
|
||||||
});
|
|
||||||
|
|
||||||
// Postcode and city don't have `name` values by default.
|
|
||||||
// They're only created if the contents changes, to save on database queries (I think)
|
|
||||||
this.$el.find( 'td.postcode input, td.city input' ).change( function() {
|
|
||||||
$( this ).attr( 'name', $( this ).data( 'name' ) );
|
|
||||||
});
|
|
||||||
|
|
||||||
if ( qty_pages > 1 ) {
|
|
||||||
// We've now displayed our initial page, time to render the pagination box.
|
|
||||||
$pagination.html( paginationTemplate( {
|
|
||||||
qty_rates: qty_rates,
|
|
||||||
current_page: this.page,
|
|
||||||
qty_pages: qty_pages
|
|
||||||
} ) );
|
|
||||||
} else {
|
|
||||||
$pagination.empty();
|
|
||||||
view.page = 1;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
updateUrl: function() {
|
|
||||||
if ( ! window.history.replaceState ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var url = data.base_url,
|
|
||||||
search = $search_field.val();
|
|
||||||
|
|
||||||
if ( 1 < this.page ) {
|
|
||||||
url += '&p=' + encodeURIComponent( this.page );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( search.length ) {
|
|
||||||
url += '&s=' + encodeURIComponent( search );
|
|
||||||
}
|
|
||||||
|
|
||||||
window.history.replaceState( {}, '', url );
|
|
||||||
},
|
|
||||||
onSubmit: function( event ) {
|
|
||||||
event.data.view.model.save();
|
|
||||||
event.preventDefault();
|
|
||||||
},
|
|
||||||
onAddNewRow: function( event ) {
|
|
||||||
var view = event.data.view,
|
|
||||||
model = view.model,
|
|
||||||
rates = _.indexBy( model.get( 'rates' ), 'tax_rate_id' ),
|
|
||||||
changes = {},
|
|
||||||
size = _.size( rates ),
|
|
||||||
newRow = _.extend( {}, data.default_rate, {
|
|
||||||
tax_rate_id: 'new-' + size + '-' + Date.now(),
|
|
||||||
newRow: true
|
|
||||||
} ),
|
|
||||||
$current, current_id, current_order, rates_to_reorder, reordered_rates;
|
|
||||||
|
|
||||||
$current = $tbody.children( '.current' );
|
|
||||||
|
|
||||||
if ( $current.length ) {
|
|
||||||
current_id = $current.last().data( 'id' );
|
|
||||||
current_order = parseInt( rates[ current_id ].tax_rate_order, 10 );
|
|
||||||
newRow.tax_rate_order = 1 + current_order;
|
|
||||||
|
|
||||||
rates_to_reorder = _.filter( rates, function( rate ) {
|
|
||||||
if ( parseInt( rate.tax_rate_order, 10 ) > current_order ) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
} );
|
|
||||||
|
|
||||||
reordered_rates = _.map( rates_to_reorder, function( rate ) {
|
|
||||||
rate.tax_rate_order++;
|
|
||||||
changes[ rate.tax_rate_id ] = _.extend(
|
|
||||||
changes[ rate.tax_rate_id ] || {}, { tax_rate_order : rate.tax_rate_order }
|
|
||||||
);
|
|
||||||
return rate;
|
|
||||||
} );
|
|
||||||
} else {
|
|
||||||
newRow.tax_rate_order = 1 + _.max(
|
|
||||||
_.pluck( rates, 'tax_rate_order' ),
|
|
||||||
function ( val ) {
|
|
||||||
// Cast them all to integers, because strings compare funky. Sighhh.
|
|
||||||
return parseInt( val, 10 );
|
|
||||||
}
|
|
||||||
);
|
|
||||||
// Move the last page
|
|
||||||
view.page = view.qty_pages;
|
|
||||||
}
|
|
||||||
|
|
||||||
rates[ newRow.tax_rate_id ] = newRow;
|
|
||||||
changes[ newRow.tax_rate_id ] = newRow;
|
|
||||||
|
|
||||||
model.set( 'rates', rates );
|
|
||||||
model.logChanges( changes );
|
|
||||||
|
|
||||||
view.render();
|
|
||||||
},
|
|
||||||
onDeleteRow: function( event ) {
|
|
||||||
var view = event.data.view,
|
|
||||||
model = view.model,
|
|
||||||
rates = _.indexBy( model.get( 'rates' ), 'tax_rate_id' ),
|
|
||||||
changes = {},
|
|
||||||
$current, current_id;
|
|
||||||
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
if ( $current = $tbody.children( '.current' ) ) {
|
|
||||||
$current.each(function(){
|
|
||||||
current_id = $( this ).data('id');
|
|
||||||
|
|
||||||
delete rates[ current_id ];
|
|
||||||
|
|
||||||
changes[ current_id ] = _.extend( changes[ current_id ] || {}, { deleted : 'deleted' } );
|
|
||||||
});
|
|
||||||
|
|
||||||
model.set( 'rates', rates );
|
|
||||||
model.logChanges( changes );
|
|
||||||
|
|
||||||
view.render();
|
|
||||||
} else {
|
|
||||||
window.alert( data.strings.no_rows_selected );
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onSearchField: function( event ){
|
|
||||||
event.data.view.updateUrl();
|
|
||||||
event.data.view.render();
|
|
||||||
},
|
|
||||||
onPageChange: function( event ) {
|
|
||||||
var $target = $( event.currentTarget );
|
|
||||||
|
|
||||||
event.preventDefault();
|
|
||||||
event.data.view.page = $target.data( 'goto' ) ? $target.data( 'goto' ) : $target.val();
|
|
||||||
event.data.view.render();
|
|
||||||
event.data.view.updateUrl();
|
|
||||||
},
|
|
||||||
onExport: function( event ) {
|
|
||||||
var csv_data = 'data:application/csv;charset=utf-8,' + data.strings.csv_data_cols.join(',') + '\n';
|
|
||||||
|
|
||||||
$.each( event.data.view.model.getFilteredRates(), function( id, rowData ) {
|
|
||||||
var row = '';
|
|
||||||
|
|
||||||
row += rowData.tax_rate_country + ',';
|
|
||||||
row += rowData.tax_rate_state + ',';
|
|
||||||
row += ( rowData.postcode ? rowData.postcode.join( '; ' ) : '' ) + ',';
|
|
||||||
row += ( rowData.city ? rowData.city.join( '; ' ) : '' ) + ',';
|
|
||||||
row += rowData.tax_rate + ',';
|
|
||||||
row += rowData.tax_rate_name + ',';
|
|
||||||
row += rowData.tax_rate_priority + ',';
|
|
||||||
row += rowData.tax_rate_compound + ',';
|
|
||||||
row += rowData.tax_rate_shipping + ',';
|
|
||||||
row += data.current_class;
|
|
||||||
|
|
||||||
csv_data += row + '\n';
|
|
||||||
});
|
|
||||||
|
|
||||||
$( this ).attr( 'href', encodeURI( csv_data ) );
|
|
||||||
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
setUnloadConfirmation: function() {
|
|
||||||
this.needsUnloadConfirm = true;
|
|
||||||
$save_button.prop( 'disabled', false );
|
|
||||||
},
|
|
||||||
clearUnloadConfirmation: function() {
|
|
||||||
this.needsUnloadConfirm = false;
|
|
||||||
$save_button.prop( 'disabled', true );
|
|
||||||
},
|
|
||||||
unloadConfirmation: function( event ) {
|
|
||||||
if ( event.data.view.needsUnloadConfirm ) {
|
|
||||||
event.returnValue = data.strings.unload_confirmation_msg;
|
|
||||||
window.event.returnValue = data.strings.unload_confirmation_msg;
|
|
||||||
return data.strings.unload_confirmation_msg;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
updateModelOnChange: function( event ) {
|
|
||||||
var model = event.data.view.model,
|
|
||||||
$target = $( event.target ),
|
|
||||||
id = $target.closest( 'tr' ).data( 'id' ),
|
|
||||||
attribute = $target.data( 'attribute' ),
|
|
||||||
val = $target.val();
|
|
||||||
|
|
||||||
if ( 'city' === attribute || 'postcode' === attribute ) {
|
|
||||||
val = val.split( ';' );
|
|
||||||
val = $.map( val, function( thing ) {
|
|
||||||
return thing.trim();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( 'tax_rate_compound' === attribute || 'tax_rate_shipping' === attribute ) {
|
|
||||||
if ( $target.is( ':checked' ) ) {
|
|
||||||
val = 1;
|
|
||||||
} else {
|
|
||||||
val = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
model.setRateAttribute( id, attribute, val );
|
|
||||||
},
|
|
||||||
sanitizePage: function( page_num ) {
|
|
||||||
page_num = parseInt( page_num, 10 );
|
|
||||||
if ( page_num < 1 ) {
|
|
||||||
page_num = 1;
|
|
||||||
} else if ( page_num > this.qty_pages ) {
|
|
||||||
page_num = this.qty_pages;
|
|
||||||
}
|
|
||||||
return page_num;
|
|
||||||
}
|
|
||||||
} ),
|
|
||||||
WCTaxTableModelInstance = new WCTaxTableModelConstructor({
|
|
||||||
rates: data.rates
|
|
||||||
} ),
|
|
||||||
WCTaxTableInstance = new WCTaxTableViewConstructor({
|
|
||||||
model: WCTaxTableModelInstance,
|
|
||||||
el: '#rates'
|
|
||||||
} );
|
|
||||||
|
|
||||||
WCTaxTableInstance.render();
|
|
||||||
|
|
||||||
});
|
|
||||||
})( jQuery, htmlSettingsTaxLocalizeScript, wp, ajaxurl );
|
|
|
@ -1,183 +0,0 @@
|
||||||
/* global woocommerce_settings_params, wp */
|
|
||||||
( function( $, params, wp ) {
|
|
||||||
$( function() {
|
|
||||||
// Sell Countries
|
|
||||||
$( 'select#woocommerce_allowed_countries' ).change( function() {
|
|
||||||
if ( 'specific' === $( this ).val() ) {
|
|
||||||
$( this ).closest('tr').next( 'tr' ).hide();
|
|
||||||
$( this ).closest('tr').next().next( 'tr' ).show();
|
|
||||||
} else if ( 'all_except' === $( this ).val() ) {
|
|
||||||
$( this ).closest('tr').next( 'tr' ).show();
|
|
||||||
$( this ).closest('tr').next().next( 'tr' ).hide();
|
|
||||||
} else {
|
|
||||||
$( this ).closest('tr').next( 'tr' ).hide();
|
|
||||||
$( this ).closest('tr').next().next( 'tr' ).hide();
|
|
||||||
}
|
|
||||||
}).trigger( 'change' );
|
|
||||||
|
|
||||||
// Ship Countries
|
|
||||||
$( 'select#woocommerce_ship_to_countries' ).change( function() {
|
|
||||||
if ( 'specific' === $( this ).val() ) {
|
|
||||||
$( this ).closest('tr').next( 'tr' ).show();
|
|
||||||
} else {
|
|
||||||
$( this ).closest('tr').next( 'tr' ).hide();
|
|
||||||
}
|
|
||||||
}).trigger( 'change' );
|
|
||||||
|
|
||||||
// Stock management
|
|
||||||
$( 'input#woocommerce_manage_stock' ).change( function() {
|
|
||||||
if ( $( this ).is(':checked') ) {
|
|
||||||
$( this ).closest('tbody').find( '.manage_stock_field' ).closest( 'tr' ).show();
|
|
||||||
} else {
|
|
||||||
$( this ).closest('tbody').find( '.manage_stock_field' ).closest( 'tr' ).hide();
|
|
||||||
}
|
|
||||||
}).trigger( 'change' );
|
|
||||||
|
|
||||||
// Color picker
|
|
||||||
$( '.colorpick' )
|
|
||||||
|
|
||||||
.iris({
|
|
||||||
change: function( event, ui ) {
|
|
||||||
$( this ).parent().find( '.colorpickpreview' ).css({ backgroundColor: ui.color.toString() });
|
|
||||||
},
|
|
||||||
hide: true,
|
|
||||||
border: true
|
|
||||||
})
|
|
||||||
|
|
||||||
.on( 'click focus', function( event ) {
|
|
||||||
event.stopPropagation();
|
|
||||||
$( '.iris-picker' ).hide();
|
|
||||||
$( this ).closest( 'td' ).find( '.iris-picker' ).show();
|
|
||||||
$( this ).data( 'original-value', $( this ).val() );
|
|
||||||
})
|
|
||||||
|
|
||||||
.on( 'change', function() {
|
|
||||||
if ( $( this ).is( '.iris-error' ) ) {
|
|
||||||
var original_value = $( this ).data( 'original-value' );
|
|
||||||
|
|
||||||
if ( original_value.match( /^\#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/ ) ) {
|
|
||||||
$( this ).val( $( this ).data( 'original-value' ) ).trigger( 'change' );
|
|
||||||
} else {
|
|
||||||
$( this ).val( '' ).trigger( 'change' );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$( 'body' ).on( 'click', function() {
|
|
||||||
$( '.iris-picker' ).hide();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Edit prompt
|
|
||||||
$( function() {
|
|
||||||
var changed = false;
|
|
||||||
|
|
||||||
$( 'input, textarea, select, checkbox' ).change( function() {
|
|
||||||
if ( ! changed ) {
|
|
||||||
window.onbeforeunload = function() {
|
|
||||||
return params.i18n_nav_warning;
|
|
||||||
};
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$( '.submit :input' ).on( 'click', function() {
|
|
||||||
window.onbeforeunload = '';
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Sorting
|
|
||||||
$( 'table.wc_gateways tbody, table.wc_shipping tbody' ).sortable({
|
|
||||||
items: 'tr',
|
|
||||||
cursor: 'move',
|
|
||||||
axis: 'y',
|
|
||||||
handle: 'td.sort',
|
|
||||||
scrollSensitivity: 40,
|
|
||||||
helper: function( event, ui ) {
|
|
||||||
ui.children().each( function() {
|
|
||||||
$( this ).width( $( this ).width() );
|
|
||||||
});
|
|
||||||
ui.css( 'left', '0' );
|
|
||||||
return ui;
|
|
||||||
},
|
|
||||||
start: function( event, ui ) {
|
|
||||||
ui.item.css( 'background-color', '#f6f6f6' );
|
|
||||||
},
|
|
||||||
stop: function( event, ui ) {
|
|
||||||
ui.item.removeAttr( 'style' );
|
|
||||||
ui.item.trigger( 'updateMoveButtons' );
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Select all/none
|
|
||||||
$( '.woocommerce' ).on( 'click', '.select_all', function() {
|
|
||||||
$( this ).closest( 'td' ).find( 'select option' ).attr( 'selected', 'selected' );
|
|
||||||
$( this ).closest( 'td' ).find( 'select' ).trigger( 'change' );
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
$( '.woocommerce' ).on( 'click', '.select_none', function() {
|
|
||||||
$( this ).closest( 'td' ).find( 'select option' ).removeAttr( 'selected' );
|
|
||||||
$( this ).closest( 'td' ).find( 'select' ).trigger( 'change' );
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Re-order buttons.
|
|
||||||
$( '.wc-item-reorder-nav').find( '.wc-move-up, .wc-move-down' ).on( 'click', function() {
|
|
||||||
var moveBtn = $( this ),
|
|
||||||
$row = moveBtn.closest( 'tr' );
|
|
||||||
|
|
||||||
moveBtn.focus();
|
|
||||||
|
|
||||||
var isMoveUp = moveBtn.is( '.wc-move-up' ),
|
|
||||||
isMoveDown = moveBtn.is( '.wc-move-down' );
|
|
||||||
|
|
||||||
if ( isMoveUp ) {
|
|
||||||
var $previewRow = $row.prev( 'tr' );
|
|
||||||
|
|
||||||
if ( $previewRow && $previewRow.length ) {
|
|
||||||
$previewRow.before( $row );
|
|
||||||
wp.a11y.speak( params.i18n_moved_up );
|
|
||||||
}
|
|
||||||
} else if ( isMoveDown ) {
|
|
||||||
var $nextRow = $row.next( 'tr' );
|
|
||||||
|
|
||||||
if ( $nextRow && $nextRow.length ) {
|
|
||||||
$nextRow.after( $row );
|
|
||||||
wp.a11y.speak( params.i18n_moved_down );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
moveBtn.focus(); // Re-focus after the container was moved.
|
|
||||||
moveBtn.closest( 'table' ).trigger( 'updateMoveButtons' );
|
|
||||||
} );
|
|
||||||
|
|
||||||
$( '.wc-item-reorder-nav').closest( 'table' ).on( 'updateMoveButtons', function() {
|
|
||||||
var table = $( this ),
|
|
||||||
lastRow = $( this ).find( 'tbody tr:last' ),
|
|
||||||
firstRow = $( this ).find( 'tbody tr:first' );
|
|
||||||
|
|
||||||
table.find( '.wc-item-reorder-nav .wc-move-disabled' ).removeClass( 'wc-move-disabled' )
|
|
||||||
.attr( { 'tabindex': '0', 'aria-hidden': 'false' } );
|
|
||||||
firstRow.find( '.wc-item-reorder-nav .wc-move-up' ).addClass( 'wc-move-disabled' )
|
|
||||||
.attr( { 'tabindex': '-1', 'aria-hidden': 'true' } );
|
|
||||||
lastRow.find( '.wc-item-reorder-nav .wc-move-down' ).addClass( 'wc-move-disabled' )
|
|
||||||
.attr( { 'tabindex': '-1', 'aria-hidden': 'true' } );
|
|
||||||
} );
|
|
||||||
|
|
||||||
$( '.wc-item-reorder-nav').closest( 'table' ).trigger( 'updateMoveButtons' );
|
|
||||||
|
|
||||||
|
|
||||||
$( '.submit button' ).on( 'click', function() {
|
|
||||||
if (
|
|
||||||
$( 'select#woocommerce_allowed_countries' ).val() === 'specific' &&
|
|
||||||
! $( '[name="woocommerce_specific_allowed_countries[]"]' ).val()
|
|
||||||
) {
|
|
||||||
if ( window.confirm( woocommerce_settings_params.i18n_no_specific_countries_selected ) ) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
|
|
||||||
});
|
|
||||||
})( jQuery, woocommerce_settings_params, wp );
|
|
|
@ -1,126 +0,0 @@
|
||||||
/* global jQuery, woocommerce_admin_system_status, wcSetClipboard, wcClearClipboard */
|
|
||||||
jQuery( function ( $ ) {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Users country and state fields
|
|
||||||
*/
|
|
||||||
var wcSystemStatus = {
|
|
||||||
init: function() {
|
|
||||||
$( document.body )
|
|
||||||
.on( 'click', 'a.help_tip, a.woocommerce-help-tip', this.preventTipTipClick )
|
|
||||||
.on( 'click', 'a.debug-report', this.generateReport )
|
|
||||||
.on( 'click', '#copy-for-support', this.copyReport )
|
|
||||||
.on( 'aftercopy', '#copy-for-support', this.copySuccess )
|
|
||||||
.on( 'aftercopyfailure', '#copy-for-support', this.copyFail );
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prevent anchor behavior when click on TipTip.
|
|
||||||
*
|
|
||||||
* @return {Bool}
|
|
||||||
*/
|
|
||||||
preventTipTipClick: function() {
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate system status report.
|
|
||||||
*
|
|
||||||
* @return {Bool}
|
|
||||||
*/
|
|
||||||
generateReport: function() {
|
|
||||||
var report = '';
|
|
||||||
|
|
||||||
$( '.wc_status_table thead, .wc_status_table tbody' ).each( function() {
|
|
||||||
if ( $( this ).is( 'thead' ) ) {
|
|
||||||
var label = $( this ).find( 'th:eq(0)' ).data( 'export-label' ) || $( this ).text();
|
|
||||||
report = report + '\n### ' + label.trim() + ' ###\n\n';
|
|
||||||
} else {
|
|
||||||
$( 'tr', $( this ) ).each( function() {
|
|
||||||
var label = $( this ).find( 'td:eq(0)' ).data( 'export-label' ) || $( this ).find( 'td:eq(0)' ).text();
|
|
||||||
var the_name = label.trim().replace( /(<([^>]+)>)/ig, '' ); // Remove HTML.
|
|
||||||
|
|
||||||
// Find value
|
|
||||||
var $value_html = $( this ).find( 'td:eq(2)' ).clone();
|
|
||||||
$value_html.find( '.private' ).remove();
|
|
||||||
$value_html.find( '.dashicons-yes' ).replaceWith( '✔' );
|
|
||||||
$value_html.find( '.dashicons-no-alt, .dashicons-warning' ).replaceWith( '❌' );
|
|
||||||
|
|
||||||
// Format value
|
|
||||||
var the_value = $value_html.text().trim();
|
|
||||||
var value_array = the_value.split( ', ' );
|
|
||||||
|
|
||||||
if ( value_array.length > 1 ) {
|
|
||||||
// If value have a list of plugins ','.
|
|
||||||
// Split to add new line.
|
|
||||||
var temp_line ='';
|
|
||||||
$.each( value_array, function( key, line ) {
|
|
||||||
temp_line = temp_line + line + '\n';
|
|
||||||
});
|
|
||||||
|
|
||||||
the_value = temp_line;
|
|
||||||
}
|
|
||||||
|
|
||||||
report = report + '' + the_name + ': ' + the_value + '\n';
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
|
||||||
$( '#debug-report' ).slideDown();
|
|
||||||
$( '#debug-report' ).find( 'textarea' ).val( '`' + report + '`' ).focus().select();
|
|
||||||
$( this ).fadeOut();
|
|
||||||
return false;
|
|
||||||
} catch ( e ) {
|
|
||||||
/* jshint devel: true */
|
|
||||||
console.log( e );
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copy for report.
|
|
||||||
*
|
|
||||||
* @param {Object} evt Copy event.
|
|
||||||
*/
|
|
||||||
copyReport: function( evt ) {
|
|
||||||
wcClearClipboard();
|
|
||||||
wcSetClipboard( $( '#debug-report' ).find( 'textarea' ).val(), $( this ) );
|
|
||||||
evt.preventDefault();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Display a "Copied!" tip when success copying
|
|
||||||
*/
|
|
||||||
copySuccess: function() {
|
|
||||||
$( '#copy-for-support' ).tipTip({
|
|
||||||
'attribute': 'data-tip',
|
|
||||||
'activation': 'focus',
|
|
||||||
'fadeIn': 50,
|
|
||||||
'fadeOut': 50,
|
|
||||||
'delay': 0
|
|
||||||
}).focus();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Displays the copy error message when failure copying.
|
|
||||||
*/
|
|
||||||
copyFail: function() {
|
|
||||||
$( '.copy-error' ).removeClass( 'hidden' );
|
|
||||||
$( '#debug-report' ).find( 'textarea' ).focus().select();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
wcSystemStatus.init();
|
|
||||||
|
|
||||||
$( '.wc_status_table' ).on( 'click', '.run-tool .button', function( evt ) {
|
|
||||||
evt.stopImmediatePropagation();
|
|
||||||
return window.confirm( woocommerce_admin_system_status.run_tool_confirmation );
|
|
||||||
});
|
|
||||||
|
|
||||||
$( '#log-viewer-select' ).on( 'click', 'h2 a.page-title-action', function( evt ) {
|
|
||||||
evt.stopImmediatePropagation();
|
|
||||||
return window.confirm( woocommerce_admin_system_status.delete_log_confirmation );
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,120 +0,0 @@
|
||||||
/*global wc_users_params */
|
|
||||||
jQuery( function ( $ ) {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Users country and state fields
|
|
||||||
*/
|
|
||||||
var wc_users_fields = {
|
|
||||||
states: null,
|
|
||||||
init: function() {
|
|
||||||
if ( typeof wc_users_params.countries !== 'undefined' ) {
|
|
||||||
/* State/Country select boxes */
|
|
||||||
this.states = JSON.parse( wc_users_params.countries.replace( /"/g, '"' ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
$( '.js_field-country' ).selectWoo().change( this.change_country );
|
|
||||||
$( '.js_field-country' ).trigger( 'change', [ true ] );
|
|
||||||
$( document.body ).on( 'change', 'select.js_field-state', this.change_state );
|
|
||||||
|
|
||||||
$( document.body ).on( 'click', 'button.js_copy-billing', this.copy_billing );
|
|
||||||
},
|
|
||||||
|
|
||||||
change_country: function( e, stickValue ) {
|
|
||||||
// Check for stickValue before using it
|
|
||||||
if ( typeof stickValue === 'undefined' ) {
|
|
||||||
stickValue = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prevent if we don't have the metabox data
|
|
||||||
if ( wc_users_fields.states === null ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var $this = $( this ),
|
|
||||||
country = $this.val(),
|
|
||||||
$state = $this.parents( '.form-table' ).find( ':input.js_field-state' ),
|
|
||||||
$parent = $state.parent(),
|
|
||||||
input_name = $state.attr( 'name' ),
|
|
||||||
input_id = $state.attr( 'id' ),
|
|
||||||
stickstatefield = 'woocommerce.stickState-' + country,
|
|
||||||
value = $this.data( stickstatefield ) ? $this.data( stickstatefield ) : $state.val(),
|
|
||||||
placeholder = $state.attr( 'placeholder' ),
|
|
||||||
$newstate;
|
|
||||||
|
|
||||||
if ( stickValue ){
|
|
||||||
$this.data( 'woocommerce.stickState-' + country, value );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove the previous DOM element
|
|
||||||
$parent.show().find( '.select2-container' ).remove();
|
|
||||||
|
|
||||||
if ( ! $.isEmptyObject( wc_users_fields.states[ country ] ) ) {
|
|
||||||
var state = wc_users_fields.states[ country ],
|
|
||||||
$defaultOption = $( '<option value=""></option>' )
|
|
||||||
.text( wc_users_fields.i18n_select_state_text );
|
|
||||||
|
|
||||||
$newstate = $( '<select style="width: 25em;"></select>' )
|
|
||||||
.prop( 'id', input_id )
|
|
||||||
.prop( 'name', input_name )
|
|
||||||
.prop( 'placeholder', placeholder )
|
|
||||||
.addClass( 'js_field-state' )
|
|
||||||
.append( $defaultOption );
|
|
||||||
|
|
||||||
$.each( state, function( index ) {
|
|
||||||
var $option = $( '<option></option>' )
|
|
||||||
.prop( 'value', index )
|
|
||||||
.text( state[ index ] );
|
|
||||||
$newstate.append( $option );
|
|
||||||
} );
|
|
||||||
|
|
||||||
$newstate.val( value );
|
|
||||||
|
|
||||||
$state.replaceWith( $newstate );
|
|
||||||
|
|
||||||
$newstate.show().selectWoo().hide().trigger( 'change' );
|
|
||||||
} else {
|
|
||||||
$newstate = $( '<input type="text" />' )
|
|
||||||
.prop( 'id', input_id )
|
|
||||||
.prop( 'name', input_name )
|
|
||||||
.prop( 'placeholder', placeholder )
|
|
||||||
.addClass( 'js_field-state regular-text' )
|
|
||||||
.val( value );
|
|
||||||
$state.replaceWith( $newstate );
|
|
||||||
}
|
|
||||||
|
|
||||||
// This event has a typo - deprecated in 2.5.0
|
|
||||||
$( document.body ).trigger( 'contry-change.woocommerce', [country, $( this ).closest( 'div' )] );
|
|
||||||
$( document.body ).trigger( 'country-change.woocommerce', [country, $( this ).closest( 'div' )] );
|
|
||||||
},
|
|
||||||
|
|
||||||
change_state: function() {
|
|
||||||
// Here we will find if state value on a select has changed and stick it to the country data
|
|
||||||
var $this = $( this ),
|
|
||||||
state = $this.val(),
|
|
||||||
$country = $this.parents( '.form-table' ).find( ':input.js_field-country' ),
|
|
||||||
country = $country.val();
|
|
||||||
|
|
||||||
$country.data( 'woocommerce.stickState-' + country, state );
|
|
||||||
},
|
|
||||||
|
|
||||||
copy_billing: function( event ) {
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
$( '#fieldset-billing' ).find( 'input, select' ).each( function( i, el ) {
|
|
||||||
// The address keys match up, except for the prefix
|
|
||||||
var shipName = el.name.replace( /^billing_/, 'shipping_' );
|
|
||||||
// Swap prefix, then check if there are any elements
|
|
||||||
var shipEl = $( '[name="' + shipName + '"]' );
|
|
||||||
// No corresponding shipping field, skip this item
|
|
||||||
if ( ! shipEl.length ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Found a matching shipping element, update the value
|
|
||||||
shipEl.val( el.value ).trigger( 'change' );
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
wc_users_fields.init();
|
|
||||||
|
|
||||||
});
|
|
|
@ -1,38 +0,0 @@
|
||||||
/* exported wcSetClipboard, wcClearClipboard */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple text copy functions using native browser clipboard capabilities.
|
|
||||||
* @since 3.2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the user's clipboard contents.
|
|
||||||
*
|
|
||||||
* @param string data: Text to copy to clipboard.
|
|
||||||
* @param object $el: jQuery element to trigger copy events on. (Default: document)
|
|
||||||
*/
|
|
||||||
function wcSetClipboard( data, $el ) {
|
|
||||||
if ( 'undefined' === typeof $el ) {
|
|
||||||
$el = jQuery( document );
|
|
||||||
}
|
|
||||||
var $temp_input = jQuery( '<textarea style="opacity:0">' );
|
|
||||||
jQuery( 'body' ).append( $temp_input );
|
|
||||||
$temp_input.val( data ).select();
|
|
||||||
|
|
||||||
$el.trigger( 'beforecopy' );
|
|
||||||
try {
|
|
||||||
document.execCommand( 'copy' );
|
|
||||||
$el.trigger( 'aftercopy' );
|
|
||||||
} catch ( err ) {
|
|
||||||
$el.trigger( 'aftercopyfailure' );
|
|
||||||
}
|
|
||||||
|
|
||||||
$temp_input.remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clear the user's clipboard.
|
|
||||||
*/
|
|
||||||
function wcClearClipboard() {
|
|
||||||
wcSetClipboard( '' );
|
|
||||||
}
|
|
|
@ -1,280 +0,0 @@
|
||||||
/*global wc_enhanced_select_params */
|
|
||||||
jQuery( function( $ ) {
|
|
||||||
|
|
||||||
function getEnhancedSelectFormatString() {
|
|
||||||
return {
|
|
||||||
'language': {
|
|
||||||
errorLoading: function() {
|
|
||||||
// Workaround for https://github.com/select2/select2/issues/4355 instead of i18n_ajax_error.
|
|
||||||
return wc_enhanced_select_params.i18n_searching;
|
|
||||||
},
|
|
||||||
inputTooLong: function( args ) {
|
|
||||||
var overChars = args.input.length - args.maximum;
|
|
||||||
|
|
||||||
if ( 1 === overChars ) {
|
|
||||||
return wc_enhanced_select_params.i18n_input_too_long_1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return wc_enhanced_select_params.i18n_input_too_long_n.replace( '%qty%', overChars );
|
|
||||||
},
|
|
||||||
inputTooShort: function( args ) {
|
|
||||||
var remainingChars = args.minimum - args.input.length;
|
|
||||||
|
|
||||||
if ( 1 === remainingChars ) {
|
|
||||||
return wc_enhanced_select_params.i18n_input_too_short_1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return wc_enhanced_select_params.i18n_input_too_short_n.replace( '%qty%', remainingChars );
|
|
||||||
},
|
|
||||||
loadingMore: function() {
|
|
||||||
return wc_enhanced_select_params.i18n_load_more;
|
|
||||||
},
|
|
||||||
maximumSelected: function( args ) {
|
|
||||||
if ( args.maximum === 1 ) {
|
|
||||||
return wc_enhanced_select_params.i18n_selection_too_long_1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return wc_enhanced_select_params.i18n_selection_too_long_n.replace( '%qty%', args.maximum );
|
|
||||||
},
|
|
||||||
noResults: function() {
|
|
||||||
return wc_enhanced_select_params.i18n_no_matches;
|
|
||||||
},
|
|
||||||
searching: function() {
|
|
||||||
return wc_enhanced_select_params.i18n_searching;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
$( document.body )
|
|
||||||
|
|
||||||
.on( 'wc-enhanced-select-init', function() {
|
|
||||||
|
|
||||||
// Regular select boxes
|
|
||||||
$( ':input.wc-enhanced-select, :input.chosen_select' ).filter( ':not(.enhanced)' ).each( function() {
|
|
||||||
var select2_args = $.extend({
|
|
||||||
minimumResultsForSearch: 10,
|
|
||||||
allowClear: $( this ).data( 'allow_clear' ) ? true : false,
|
|
||||||
placeholder: $( this ).data( 'placeholder' )
|
|
||||||
}, getEnhancedSelectFormatString() );
|
|
||||||
|
|
||||||
$( this ).selectWoo( select2_args ).addClass( 'enhanced' );
|
|
||||||
});
|
|
||||||
|
|
||||||
$( ':input.wc-enhanced-select-nostd, :input.chosen_select_nostd' ).filter( ':not(.enhanced)' ).each( function() {
|
|
||||||
var select2_args = $.extend({
|
|
||||||
minimumResultsForSearch: 10,
|
|
||||||
allowClear: true,
|
|
||||||
placeholder: $( this ).data( 'placeholder' )
|
|
||||||
}, getEnhancedSelectFormatString() );
|
|
||||||
|
|
||||||
$( this ).selectWoo( select2_args ).addClass( 'enhanced' );
|
|
||||||
});
|
|
||||||
|
|
||||||
// Ajax product search box
|
|
||||||
$( ':input.wc-product-search' ).filter( ':not(.enhanced)' ).each( function() {
|
|
||||||
var select2_args = {
|
|
||||||
allowClear: $( this ).data( 'allow_clear' ) ? true : false,
|
|
||||||
placeholder: $( this ).data( 'placeholder' ),
|
|
||||||
minimumInputLength: $( this ).data( 'minimum_input_length' ) ? $( this ).data( 'minimum_input_length' ) : '3',
|
|
||||||
escapeMarkup: function( m ) {
|
|
||||||
return m;
|
|
||||||
},
|
|
||||||
ajax: {
|
|
||||||
url: wc_enhanced_select_params.ajax_url,
|
|
||||||
dataType: 'json',
|
|
||||||
delay: 250,
|
|
||||||
data: function( params ) {
|
|
||||||
return {
|
|
||||||
term : params.term,
|
|
||||||
action : $( this ).data( 'action' ) || 'woocommerce_json_search_products_and_variations',
|
|
||||||
security : wc_enhanced_select_params.search_products_nonce,
|
|
||||||
exclude : $( this ).data( 'exclude' ),
|
|
||||||
exclude_type : $( this ).data( 'exclude_type' ),
|
|
||||||
include : $( this ).data( 'include' ),
|
|
||||||
limit : $( this ).data( 'limit' ),
|
|
||||||
display_stock: $( this ).data( 'display_stock' )
|
|
||||||
};
|
|
||||||
},
|
|
||||||
processResults: function( data ) {
|
|
||||||
var terms = [];
|
|
||||||
if ( data ) {
|
|
||||||
$.each( data, function( id, text ) {
|
|
||||||
terms.push( { id: id, text: text } );
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
results: terms
|
|
||||||
};
|
|
||||||
},
|
|
||||||
cache: true
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
select2_args = $.extend( select2_args, getEnhancedSelectFormatString() );
|
|
||||||
|
|
||||||
$( this ).selectWoo( select2_args ).addClass( 'enhanced' );
|
|
||||||
|
|
||||||
if ( $( this ).data( 'sortable' ) ) {
|
|
||||||
var $select = $(this);
|
|
||||||
var $list = $( this ).next( '.select2-container' ).find( 'ul.select2-selection__rendered' );
|
|
||||||
|
|
||||||
$list.sortable({
|
|
||||||
placeholder : 'ui-state-highlight select2-selection__choice',
|
|
||||||
forcePlaceholderSize: true,
|
|
||||||
items : 'li:not(.select2-search__field)',
|
|
||||||
tolerance : 'pointer',
|
|
||||||
stop: function() {
|
|
||||||
$( $list.find( '.select2-selection__choice' ).get().reverse() ).each( function() {
|
|
||||||
var id = $( this ).data( 'data' ).id;
|
|
||||||
var option = $select.find( 'option[value="' + id + '"]' )[0];
|
|
||||||
$select.prepend( option );
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// Keep multiselects ordered alphabetically if they are not sortable.
|
|
||||||
} else if ( $( this ).prop( 'multiple' ) ) {
|
|
||||||
$( this ).on( 'change', function(){
|
|
||||||
var $children = $( this ).children();
|
|
||||||
$children.sort(function(a, b){
|
|
||||||
var atext = a.text.toLowerCase();
|
|
||||||
var btext = b.text.toLowerCase();
|
|
||||||
|
|
||||||
if ( atext > btext ) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if ( atext < btext ) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
});
|
|
||||||
$( this ).html( $children );
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Ajax customer search boxes
|
|
||||||
$( ':input.wc-customer-search' ).filter( ':not(.enhanced)' ).each( function() {
|
|
||||||
var select2_args = {
|
|
||||||
allowClear: $( this ).data( 'allow_clear' ) ? true : false,
|
|
||||||
placeholder: $( this ).data( 'placeholder' ),
|
|
||||||
minimumInputLength: $( this ).data( 'minimum_input_length' ) ? $( this ).data( 'minimum_input_length' ) : '1',
|
|
||||||
escapeMarkup: function( m ) {
|
|
||||||
return m;
|
|
||||||
},
|
|
||||||
ajax: {
|
|
||||||
url: wc_enhanced_select_params.ajax_url,
|
|
||||||
dataType: 'json',
|
|
||||||
delay: 1000,
|
|
||||||
data: function( params ) {
|
|
||||||
return {
|
|
||||||
term: params.term,
|
|
||||||
action: 'woocommerce_json_search_customers',
|
|
||||||
security: wc_enhanced_select_params.search_customers_nonce,
|
|
||||||
exclude: $( this ).data( 'exclude' )
|
|
||||||
};
|
|
||||||
},
|
|
||||||
processResults: function( data ) {
|
|
||||||
var terms = [];
|
|
||||||
if ( data ) {
|
|
||||||
$.each( data, function( id, text ) {
|
|
||||||
terms.push({
|
|
||||||
id: id,
|
|
||||||
text: text
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
results: terms
|
|
||||||
};
|
|
||||||
},
|
|
||||||
cache: true
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
select2_args = $.extend( select2_args, getEnhancedSelectFormatString() );
|
|
||||||
|
|
||||||
$( this ).selectWoo( select2_args ).addClass( 'enhanced' );
|
|
||||||
|
|
||||||
if ( $( this ).data( 'sortable' ) ) {
|
|
||||||
var $select = $(this);
|
|
||||||
var $list = $( this ).next( '.select2-container' ).find( 'ul.select2-selection__rendered' );
|
|
||||||
|
|
||||||
$list.sortable({
|
|
||||||
placeholder : 'ui-state-highlight select2-selection__choice',
|
|
||||||
forcePlaceholderSize: true,
|
|
||||||
items : 'li:not(.select2-search__field)',
|
|
||||||
tolerance : 'pointer',
|
|
||||||
stop: function() {
|
|
||||||
$( $list.find( '.select2-selection__choice' ).get().reverse() ).each( function() {
|
|
||||||
var id = $( this ).data( 'data' ).id;
|
|
||||||
var option = $select.find( 'option[value="' + id + '"]' )[0];
|
|
||||||
$select.prepend( option );
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Ajax category search boxes
|
|
||||||
$( ':input.wc-category-search' ).filter( ':not(.enhanced)' ).each( function() {
|
|
||||||
var select2_args = $.extend( {
|
|
||||||
allowClear : $( this ).data( 'allow_clear' ) ? true : false,
|
|
||||||
placeholder : $( this ).data( 'placeholder' ),
|
|
||||||
minimumInputLength: $( this ).data( 'minimum_input_length' ) ? $( this ).data( 'minimum_input_length' ) : 3,
|
|
||||||
escapeMarkup : function( m ) {
|
|
||||||
return m;
|
|
||||||
},
|
|
||||||
ajax: {
|
|
||||||
url: wc_enhanced_select_params.ajax_url,
|
|
||||||
dataType: 'json',
|
|
||||||
delay: 250,
|
|
||||||
data: function( params ) {
|
|
||||||
return {
|
|
||||||
term: params.term,
|
|
||||||
action: 'woocommerce_json_search_categories',
|
|
||||||
security: wc_enhanced_select_params.search_categories_nonce
|
|
||||||
};
|
|
||||||
},
|
|
||||||
processResults: function( data ) {
|
|
||||||
var terms = [];
|
|
||||||
if ( data ) {
|
|
||||||
$.each( data, function( id, term ) {
|
|
||||||
terms.push({
|
|
||||||
id: term.slug,
|
|
||||||
text: term.formatted_name
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
results: terms
|
|
||||||
};
|
|
||||||
},
|
|
||||||
cache: true
|
|
||||||
}
|
|
||||||
}, getEnhancedSelectFormatString() );
|
|
||||||
|
|
||||||
$( this ).selectWoo( select2_args ).addClass( 'enhanced' );
|
|
||||||
});
|
|
||||||
})
|
|
||||||
|
|
||||||
// WooCommerce Backbone Modal
|
|
||||||
.on( 'wc_backbone_modal_before_remove', function() {
|
|
||||||
$( '.wc-enhanced-select, :input.wc-product-search, :input.wc-customer-search' ).filter( '.select2-hidden-accessible' )
|
|
||||||
.selectWoo( 'close' );
|
|
||||||
})
|
|
||||||
|
|
||||||
.trigger( 'wc-enhanced-select-init' );
|
|
||||||
|
|
||||||
$( 'html' ).on( 'click', function( event ) {
|
|
||||||
if ( this === event.target ) {
|
|
||||||
$( '.wc-enhanced-select, :input.wc-product-search, :input.wc-customer-search' ).filter( '.select2-hidden-accessible' )
|
|
||||||
.selectWoo( 'close' );
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
} catch( err ) {
|
|
||||||
// If select2 failed (conflict?) log the error but don't stop other scripts breaking.
|
|
||||||
window.console.log( err );
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,88 +0,0 @@
|
||||||
/* global wc_orders_params */
|
|
||||||
jQuery( function( $ ) {
|
|
||||||
|
|
||||||
if ( typeof wc_orders_params === 'undefined' ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* WCOrdersTable class.
|
|
||||||
*/
|
|
||||||
var WCOrdersTable = function() {
|
|
||||||
$( document )
|
|
||||||
.on( 'click', '.post-type-shop_order .wp-list-table tbody td', this.onRowClick )
|
|
||||||
.on( 'click', '.order-preview:not(.disabled)', this.onPreview );
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Click a row.
|
|
||||||
*/
|
|
||||||
WCOrdersTable.prototype.onRowClick = function( e ) {
|
|
||||||
if ( $( e.target ).filter( 'a, a *, .no-link, .no-link *, button, button *' ).length ) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( window.getSelection && window.getSelection().toString().length ) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var $row = $( this ).closest( 'tr' ),
|
|
||||||
href = $row.find( 'a.order-view' ).attr( 'href' );
|
|
||||||
|
|
||||||
if ( href && href.length ) {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
if ( e.metaKey || e.ctrlKey ) {
|
|
||||||
window.open( href, '_blank' );
|
|
||||||
} else {
|
|
||||||
window.location = href;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Preview an order.
|
|
||||||
*/
|
|
||||||
WCOrdersTable.prototype.onPreview = function() {
|
|
||||||
var $previewButton = $( this ),
|
|
||||||
$order_id = $previewButton.data( 'order-id' );
|
|
||||||
|
|
||||||
if ( $previewButton.data( 'order-data' ) ) {
|
|
||||||
$( this ).WCBackboneModal({
|
|
||||||
template: 'wc-modal-view-order',
|
|
||||||
variable : $previewButton.data( 'order-data' )
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
$previewButton.addClass( 'disabled' );
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
url: wc_orders_params.ajax_url,
|
|
||||||
data: {
|
|
||||||
order_id: $order_id,
|
|
||||||
action : 'woocommerce_get_order_details',
|
|
||||||
security: wc_orders_params.preview_nonce
|
|
||||||
},
|
|
||||||
type: 'GET',
|
|
||||||
success: function( response ) {
|
|
||||||
$( '.order-preview' ).removeClass( 'disabled' );
|
|
||||||
|
|
||||||
if ( response.success ) {
|
|
||||||
$previewButton.data( 'order-data', response.data );
|
|
||||||
|
|
||||||
$( this ).WCBackboneModal({
|
|
||||||
template: 'wc-modal-view-order',
|
|
||||||
variable : response.data
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Init WCOrdersTable.
|
|
||||||
*/
|
|
||||||
new WCOrdersTable();
|
|
||||||
} );
|
|
|
@ -1,315 +0,0 @@
|
||||||
/*global wc_setup_params */
|
|
||||||
/*global wc_setup_currencies */
|
|
||||||
/*global wc_base_state */
|
|
||||||
/* @deprecated 4.6.0 */
|
|
||||||
jQuery( function( $ ) {
|
|
||||||
function blockWizardUI() {
|
|
||||||
$('.wc-setup-content').block({
|
|
||||||
message: null,
|
|
||||||
overlayCSS: {
|
|
||||||
background: '#fff',
|
|
||||||
opacity: 0.6
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
$( '.button-next' ).on( 'click', function() {
|
|
||||||
var form = $( this ).parents( 'form' ).get( 0 );
|
|
||||||
|
|
||||||
if ( ( 'function' !== typeof form.checkValidity ) || form.checkValidity() ) {
|
|
||||||
blockWizardUI();
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
} );
|
|
||||||
|
|
||||||
$( 'form.address-step' ).on( 'submit', function( e ) {
|
|
||||||
var form = $( this );
|
|
||||||
if ( ( 'function' !== typeof form.checkValidity ) || form.checkValidity() ) {
|
|
||||||
blockWizardUI();
|
|
||||||
}
|
|
||||||
|
|
||||||
e.preventDefault();
|
|
||||||
$('.wc-setup-content').unblock();
|
|
||||||
|
|
||||||
$( this ).WCBackboneModal( {
|
|
||||||
template: 'wc-modal-tracking-setup'
|
|
||||||
} );
|
|
||||||
|
|
||||||
$( document.body ).on( 'wc_backbone_modal_response', function() {
|
|
||||||
form.unbind( 'submit' ).trigger( 'submit' );
|
|
||||||
} );
|
|
||||||
|
|
||||||
$( '#wc_tracker_checkbox_dialog' ).on( 'change', function( e ) {
|
|
||||||
var eventTarget = $( e.target );
|
|
||||||
$( '#wc_tracker_checkbox' ).prop( 'checked', eventTarget.prop( 'checked' ) );
|
|
||||||
} );
|
|
||||||
|
|
||||||
$( '#wc_tracker_submit' ).on( 'click', function () {
|
|
||||||
form.unbind( 'submit' ).trigger( 'submit' );
|
|
||||||
} );
|
|
||||||
|
|
||||||
return true;
|
|
||||||
} );
|
|
||||||
|
|
||||||
$( '#store_country' ).on( 'change', function() {
|
|
||||||
// Prevent if we don't have the metabox data
|
|
||||||
if ( wc_setup_params.states === null ){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var $this = $( this ),
|
|
||||||
country = $this.val(),
|
|
||||||
$state_select = $( '#store_state' );
|
|
||||||
|
|
||||||
if ( ! $.isEmptyObject( wc_setup_params.states[ country ] ) ) {
|
|
||||||
var states = wc_setup_params.states[ country ];
|
|
||||||
|
|
||||||
$state_select.empty();
|
|
||||||
|
|
||||||
$.each( states, function( index ) {
|
|
||||||
$state_select.append( $( '<option value="' + index + '">' + states[ index ] + '</option>' ) );
|
|
||||||
} );
|
|
||||||
|
|
||||||
$( '.store-state-container' ).show();
|
|
||||||
$state_select.selectWoo().val( wc_base_state ).trigger( 'change' ).prop( 'required', true );
|
|
||||||
} else {
|
|
||||||
$( '.store-state-container' ).hide();
|
|
||||||
$state_select.empty().val( '' ).trigger( 'change' ).prop( 'required', false );
|
|
||||||
}
|
|
||||||
|
|
||||||
$( '#currency_code' ).val( wc_setup_currencies[ country ] ).trigger( 'change' );
|
|
||||||
} );
|
|
||||||
|
|
||||||
/* Setup postcode field and validations */
|
|
||||||
$( '#store_country' ).on( 'change', function() {
|
|
||||||
if ( ! wc_setup_params.postcodes ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var $this = $( this ),
|
|
||||||
country = $this.val(),
|
|
||||||
$store_postcode_input = $( '#store_postcode' ),
|
|
||||||
country_postcode_obj = wc_setup_params.postcodes[ country ];
|
|
||||||
|
|
||||||
// Default to required, if its unknown whether postcode is required or not.
|
|
||||||
if ( $.isEmptyObject( country_postcode_obj ) || country_postcode_obj.required ) {
|
|
||||||
$store_postcode_input.attr( 'required', 'true' );
|
|
||||||
} else {
|
|
||||||
$store_postcode_input.removeAttr( 'required' );
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
|
|
||||||
$( '#store_country' ).trigger( 'change' );
|
|
||||||
|
|
||||||
$( '.wc-wizard-services' ).on( 'change', '.wc-wizard-service-enable input', function() {
|
|
||||||
if ( $( this ).is( ':checked' ) ) {
|
|
||||||
$( this ).closest( '.wc-wizard-service-toggle' ).removeClass( 'disabled' );
|
|
||||||
$( this ).closest( '.wc-wizard-service-item' ).addClass( 'checked' );
|
|
||||||
$( this ).closest( '.wc-wizard-service-item' )
|
|
||||||
.find( '.wc-wizard-service-settings' ).removeClass( 'hide' );
|
|
||||||
} else {
|
|
||||||
$( this ).closest( '.wc-wizard-service-toggle' ).addClass( 'disabled' );
|
|
||||||
$( this ).closest( '.wc-wizard-service-item' ).removeClass( 'checked' );
|
|
||||||
$( this ).closest( '.wc-wizard-service-item' )
|
|
||||||
.find( '.wc-wizard-service-settings' ).addClass( 'hide' );
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
|
|
||||||
$( '.wc-wizard-services' ).on( 'keyup', function( e ) {
|
|
||||||
var code = e.keyCode || e.which,
|
|
||||||
$focused = $( document.activeElement );
|
|
||||||
|
|
||||||
if ( $focused.is( '.wc-wizard-service-toggle, .wc-wizard-service-enable' ) && ( 13 === code || 32 === code ) ) {
|
|
||||||
$focused.find( ':input' ).trigger( 'click' );
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
|
|
||||||
$( '.wc-wizard-services' ).on( 'click', '.wc-wizard-service-enable', function( e ) {
|
|
||||||
var eventTarget = $( e.target );
|
|
||||||
|
|
||||||
if ( eventTarget.is( 'input' ) ) {
|
|
||||||
e.stopPropagation();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var $checkbox = $( this ).find( 'input[type="checkbox"]' );
|
|
||||||
|
|
||||||
$checkbox.prop( 'checked', ! $checkbox.prop( 'checked' ) ).trigger( 'change' );
|
|
||||||
} );
|
|
||||||
|
|
||||||
$( '.wc-wizard-services-list-toggle' ).on( 'click', function() {
|
|
||||||
$( this ).closest( '.wc-wizard-services-list-toggle' ).toggleClass( 'closed' );
|
|
||||||
$( this ).closest( '.wc-wizard-services' ).find( '.wc-wizard-service-item' )
|
|
||||||
.slideToggle()
|
|
||||||
.css( 'display', 'flex' );
|
|
||||||
} );
|
|
||||||
|
|
||||||
$( '.wc-wizard-services' ).on( 'change', '.wc-wizard-shipping-method-select .method', function( e ) {
|
|
||||||
var zone = $( this ).closest( '.wc-wizard-service-description' );
|
|
||||||
var selectedMethod = e.target.value;
|
|
||||||
|
|
||||||
var description = zone.find( '.shipping-method-descriptions' );
|
|
||||||
description.find( '.shipping-method-description' ).addClass( 'hide' );
|
|
||||||
description.find( '.' + selectedMethod ).removeClass( 'hide' );
|
|
||||||
|
|
||||||
var $checkbox = zone.parent().find( 'input[type="checkbox"]' );
|
|
||||||
var settings = zone.find( '.shipping-method-settings' );
|
|
||||||
settings
|
|
||||||
.find( '.shipping-method-setting' )
|
|
||||||
.addClass( 'hide' )
|
|
||||||
.find( '.shipping-method-required-field' )
|
|
||||||
.prop( 'required', false );
|
|
||||||
settings
|
|
||||||
.find( '.' + selectedMethod )
|
|
||||||
.removeClass( 'hide' )
|
|
||||||
.find( '.shipping-method-required-field' )
|
|
||||||
.prop( 'required', $checkbox.prop( 'checked' ) );
|
|
||||||
} ).find( '.wc-wizard-shipping-method-select .method' ).trigger( 'change' );
|
|
||||||
|
|
||||||
$( '.wc-wizard-services' ).on( 'change', '.wc-wizard-shipping-method-enable', function() {
|
|
||||||
var checked = $( this ).is( ':checked' );
|
|
||||||
var selectedMethod = $( this )
|
|
||||||
.closest( '.wc-wizard-service-item' )
|
|
||||||
.find( '.wc-wizard-shipping-method-select .method' )
|
|
||||||
.val();
|
|
||||||
|
|
||||||
$( this )
|
|
||||||
.closest( '.wc-wizard-service-item' )
|
|
||||||
.find( '.' + selectedMethod )
|
|
||||||
.find( '.shipping-method-required-field' )
|
|
||||||
.prop( 'required', checked );
|
|
||||||
} );
|
|
||||||
|
|
||||||
function submitActivateForm() {
|
|
||||||
$( 'form.activate-jetpack' ).trigger( 'submit' );
|
|
||||||
}
|
|
||||||
|
|
||||||
function waitForJetpackInstall() {
|
|
||||||
wp.ajax.post( 'setup_wizard_check_jetpack' )
|
|
||||||
.then( function( result ) {
|
|
||||||
// If we receive success, or an unexpected result
|
|
||||||
// let the form submit.
|
|
||||||
if (
|
|
||||||
! result ||
|
|
||||||
! result.is_active ||
|
|
||||||
'yes' === result.is_active
|
|
||||||
) {
|
|
||||||
return submitActivateForm();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait until checking the status again
|
|
||||||
setTimeout( waitForJetpackInstall, 3000 );
|
|
||||||
} )
|
|
||||||
.fail( function() {
|
|
||||||
// Submit the form as normal if the request fails
|
|
||||||
submitActivateForm();
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for a pending Jetpack install to finish before triggering a "save"
|
|
||||||
// on the activate step, which launches the Jetpack connection flow.
|
|
||||||
$( '.activate-jetpack' ).on( 'click', '.button-primary', function( e ) {
|
|
||||||
blockWizardUI();
|
|
||||||
|
|
||||||
if ( 'no' === wc_setup_params.pending_jetpack_install ) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
e.preventDefault();
|
|
||||||
waitForJetpackInstall();
|
|
||||||
} );
|
|
||||||
|
|
||||||
$( '.activate-new-onboarding' ).on( 'click', '.button-primary', function() {
|
|
||||||
// Show pending spinner while activate happens.
|
|
||||||
blockWizardUI();
|
|
||||||
} );
|
|
||||||
|
|
||||||
$( '.wc-wizard-services' ).on( 'change', 'input#stripe_create_account, input#ppec_paypal_reroute_requests', function() {
|
|
||||||
if ( $( this ).is( ':checked' ) ) {
|
|
||||||
$( this ).closest( '.wc-wizard-service-settings' )
|
|
||||||
.find( 'input.payment-email-input' )
|
|
||||||
.attr( 'type', 'email' )
|
|
||||||
.prop( 'disabled', false )
|
|
||||||
.prop( 'required', true );
|
|
||||||
} else {
|
|
||||||
$( this ).closest( '.wc-wizard-service-settings' )
|
|
||||||
.find( 'input.payment-email-input' )
|
|
||||||
.attr( 'type', null )
|
|
||||||
.prop( 'disabled', true )
|
|
||||||
.prop( 'required', false );
|
|
||||||
}
|
|
||||||
} ).find( 'input#stripe_create_account, input#ppec_paypal_reroute_requests' ).trigger( 'change' );
|
|
||||||
|
|
||||||
function addPlugins( bySlug, $el, hover ) {
|
|
||||||
var plugins = $el.data( 'plugins' );
|
|
||||||
for ( var i in Array.isArray( plugins ) ? plugins : [] ) {
|
|
||||||
var slug = plugins[ i ].slug;
|
|
||||||
bySlug[ slug ] = bySlug[ slug ] ||
|
|
||||||
$( '<span class="plugin-install-info-list-item">' )
|
|
||||||
.append( '<a href="https://wordpress.org/plugins/' + slug + '/" target="_blank">' + plugins[ i ].name + '</a>' );
|
|
||||||
|
|
||||||
bySlug[ slug ].find( 'a' )
|
|
||||||
.on( 'mouseenter mouseleave', ( function( $hover, event ) {
|
|
||||||
$hover.toggleClass( 'plugin-install-source', 'mouseenter' === event.type );
|
|
||||||
} ).bind( null, hover ? $el.closest( hover ) : $el ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function updatePluginInfo() {
|
|
||||||
var pluginLinkBySlug = {};
|
|
||||||
var extraPlugins = [];
|
|
||||||
|
|
||||||
$( '.wc-wizard-service-enable input:checked' ).each( function() {
|
|
||||||
addPlugins( pluginLinkBySlug, $( this ), '.wc-wizard-service-item' );
|
|
||||||
|
|
||||||
var $container = $( this ).closest( '.wc-wizard-service-item' );
|
|
||||||
$container.find( 'input.payment-checkbox-input:checked' ).each( function() {
|
|
||||||
extraPlugins.push( $( this ).attr( 'id' ) );
|
|
||||||
addPlugins( pluginLinkBySlug, $( this ), '.wc-wizard-service-settings' );
|
|
||||||
} );
|
|
||||||
$container.find( '.wc-wizard-shipping-method-select .method' ).each( function() {
|
|
||||||
var $this = $( this );
|
|
||||||
if ( 'live_rates' === $this.val() ) {
|
|
||||||
addPlugins( pluginLinkBySlug, $this, '.wc-wizard-service-item' );
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
} );
|
|
||||||
|
|
||||||
$( '.recommended-item input:checked' ).each( function() {
|
|
||||||
addPlugins( pluginLinkBySlug, $( this ), '.recommended-item' );
|
|
||||||
} );
|
|
||||||
|
|
||||||
var $list = $( 'span.plugin-install-info-list' ).empty();
|
|
||||||
|
|
||||||
for ( var slug in pluginLinkBySlug ) {
|
|
||||||
$list.append( pluginLinkBySlug[ slug ] );
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
extraPlugins &&
|
|
||||||
wc_setup_params.current_step &&
|
|
||||||
wc_setup_params.i18n.extra_plugins[ wc_setup_params.current_step ] &&
|
|
||||||
wc_setup_params.i18n.extra_plugins[ wc_setup_params.current_step ][ extraPlugins.join( ',' ) ]
|
|
||||||
) {
|
|
||||||
$list.append(
|
|
||||||
wc_setup_params.i18n.extra_plugins[ wc_setup_params.current_step ][ extraPlugins.join( ',' ) ]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
$( 'span.plugin-install-info' ).toggle( $list.children().length > 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
updatePluginInfo();
|
|
||||||
$( '.wc-setup-content' ).on( 'change', '[data-plugins]', updatePluginInfo );
|
|
||||||
|
|
||||||
$( document.body ).on( 'init_tooltips', function() {
|
|
||||||
$( '.help_tip' ).tipTip( {
|
|
||||||
'attribute': 'data-tip',
|
|
||||||
'fadeIn': 50,
|
|
||||||
'fadeOut': 50,
|
|
||||||
'delay': 200,
|
|
||||||
'defaultPosition': 'top'
|
|
||||||
} );
|
|
||||||
} ).trigger( 'init_tooltips' );
|
|
||||||
} );
|
|
|
@ -1,245 +0,0 @@
|
||||||
/* global shippingClassesLocalizeScript, ajaxurl */
|
|
||||||
( function( $, data, wp, ajaxurl ) {
|
|
||||||
$( function() {
|
|
||||||
var $tbody = $( '.wc-shipping-class-rows' ),
|
|
||||||
$save_button = $( '.wc-shipping-class-save' ),
|
|
||||||
$row_template = wp.template( 'wc-shipping-class-row' ),
|
|
||||||
$blank_template = wp.template( 'wc-shipping-class-row-blank' ),
|
|
||||||
|
|
||||||
// Backbone model
|
|
||||||
ShippingClass = Backbone.Model.extend({
|
|
||||||
changes: {},
|
|
||||||
logChanges: function( changedRows ) {
|
|
||||||
var changes = this.changes || {};
|
|
||||||
|
|
||||||
_.each( changedRows, function( row, id ) {
|
|
||||||
changes[ id ] = _.extend( changes[ id ] || { term_id : id }, row );
|
|
||||||
} );
|
|
||||||
|
|
||||||
this.changes = changes;
|
|
||||||
this.trigger( 'change:classes' );
|
|
||||||
},
|
|
||||||
save: function() {
|
|
||||||
if ( _.size( this.changes ) ) {
|
|
||||||
$.post( ajaxurl + ( ajaxurl.indexOf( '?' ) > 0 ? '&' : '?' ) + 'action=woocommerce_shipping_classes_save_changes', {
|
|
||||||
wc_shipping_classes_nonce : data.wc_shipping_classes_nonce,
|
|
||||||
changes : this.changes
|
|
||||||
}, this.onSaveResponse, 'json' );
|
|
||||||
} else {
|
|
||||||
shippingClass.trigger( 'saved:classes' );
|
|
||||||
}
|
|
||||||
},
|
|
||||||
discardChanges: function( id ) {
|
|
||||||
var changes = this.changes || {};
|
|
||||||
|
|
||||||
// Delete all changes
|
|
||||||
delete changes[ id ];
|
|
||||||
|
|
||||||
// No changes? Disable save button.
|
|
||||||
if ( 0 === _.size( this.changes ) ) {
|
|
||||||
shippingClassView.clearUnloadConfirmation();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onSaveResponse: function( response, textStatus ) {
|
|
||||||
if ( 'success' === textStatus ) {
|
|
||||||
if ( response.success ) {
|
|
||||||
shippingClass.set( 'classes', response.data.shipping_classes );
|
|
||||||
shippingClass.trigger( 'change:classes' );
|
|
||||||
shippingClass.changes = {};
|
|
||||||
shippingClass.trigger( 'saved:classes' );
|
|
||||||
} else if ( response.data ) {
|
|
||||||
window.alert( response.data );
|
|
||||||
} else {
|
|
||||||
window.alert( data.strings.save_failed );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
shippingClassView.unblock();
|
|
||||||
}
|
|
||||||
} ),
|
|
||||||
|
|
||||||
// Backbone view
|
|
||||||
ShippingClassView = Backbone.View.extend({
|
|
||||||
rowTemplate: $row_template,
|
|
||||||
initialize: function() {
|
|
||||||
this.listenTo( this.model, 'change:classes', this.setUnloadConfirmation );
|
|
||||||
this.listenTo( this.model, 'saved:classes', this.clearUnloadConfirmation );
|
|
||||||
this.listenTo( this.model, 'saved:classes', this.render );
|
|
||||||
$tbody.on( 'change', { view: this }, this.updateModelOnChange );
|
|
||||||
$( window ).on( 'beforeunload', { view: this }, this.unloadConfirmation );
|
|
||||||
$save_button.on( 'click', { view: this }, this.onSubmit );
|
|
||||||
$( document.body ).on( 'click', '.wc-shipping-class-add', { view: this }, this.onAddNewRow );
|
|
||||||
$( document.body ).on( 'click', '.wc-shipping-class-save-changes', { view: this }, this.onSubmit );
|
|
||||||
},
|
|
||||||
block: function() {
|
|
||||||
$( this.el ).block({
|
|
||||||
message: null,
|
|
||||||
overlayCSS: {
|
|
||||||
background: '#fff',
|
|
||||||
opacity: 0.6
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
unblock: function() {
|
|
||||||
$( this.el ).unblock();
|
|
||||||
},
|
|
||||||
render: function() {
|
|
||||||
var classes = _.indexBy( this.model.get( 'classes' ), 'term_id' ),
|
|
||||||
view = this;
|
|
||||||
|
|
||||||
this.$el.empty();
|
|
||||||
this.unblock();
|
|
||||||
|
|
||||||
if ( _.size( classes ) ) {
|
|
||||||
// Sort classes
|
|
||||||
classes = _.sortBy( classes, function( shipping_class ) {
|
|
||||||
return shipping_class.name;
|
|
||||||
} );
|
|
||||||
|
|
||||||
// Populate $tbody with the current classes
|
|
||||||
$.each( classes, function( id, rowData ) {
|
|
||||||
view.renderRow( rowData );
|
|
||||||
} );
|
|
||||||
} else {
|
|
||||||
view.$el.append( $blank_template );
|
|
||||||
}
|
|
||||||
},
|
|
||||||
renderRow: function( rowData ) {
|
|
||||||
var view = this;
|
|
||||||
view.$el.append( view.rowTemplate( rowData ) );
|
|
||||||
view.initRow( rowData );
|
|
||||||
},
|
|
||||||
initRow: function( rowData ) {
|
|
||||||
var view = this;
|
|
||||||
var $tr = view.$el.find( 'tr[data-id="' + rowData.term_id + '"]');
|
|
||||||
|
|
||||||
// Support select boxes
|
|
||||||
$tr.find( 'select' ).each( function() {
|
|
||||||
var attribute = $( this ).data( 'attribute' );
|
|
||||||
$( this ).find( 'option[value="' + rowData[ attribute ] + '"]' ).prop( 'selected', true );
|
|
||||||
} );
|
|
||||||
|
|
||||||
// Make the rows function
|
|
||||||
$tr.find( '.view' ).show();
|
|
||||||
$tr.find( '.edit' ).hide();
|
|
||||||
$tr.find( '.wc-shipping-class-edit' ).on( 'click', { view: this }, this.onEditRow );
|
|
||||||
$tr.find( '.wc-shipping-class-delete' ).on( 'click', { view: this }, this.onDeleteRow );
|
|
||||||
$tr.find( '.editing .wc-shipping-class-edit' ).trigger('click');
|
|
||||||
$tr.find( '.wc-shipping-class-cancel-edit' ).on( 'click', { view: this }, this.onCancelEditRow );
|
|
||||||
|
|
||||||
// Editing?
|
|
||||||
if ( true === rowData.editing ) {
|
|
||||||
$tr.addClass( 'editing' );
|
|
||||||
$tr.find( '.wc-shipping-class-edit' ).trigger( 'click' );
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onSubmit: function( event ) {
|
|
||||||
event.data.view.block();
|
|
||||||
event.data.view.model.save();
|
|
||||||
event.preventDefault();
|
|
||||||
},
|
|
||||||
onAddNewRow: function( event ) {
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
var view = event.data.view,
|
|
||||||
model = view.model,
|
|
||||||
classes = _.indexBy( model.get( 'classes' ), 'term_id' ),
|
|
||||||
changes = {},
|
|
||||||
size = _.size( classes ),
|
|
||||||
newRow = _.extend( {}, data.default_shipping_class, {
|
|
||||||
term_id: 'new-' + size + '-' + Date.now(),
|
|
||||||
editing: true,
|
|
||||||
newRow : true
|
|
||||||
} );
|
|
||||||
|
|
||||||
changes[ newRow.term_id ] = newRow;
|
|
||||||
|
|
||||||
model.logChanges( changes );
|
|
||||||
view.renderRow( newRow );
|
|
||||||
$( '.wc-shipping-classes-blank-state' ).remove();
|
|
||||||
},
|
|
||||||
onEditRow: function( event ) {
|
|
||||||
event.preventDefault();
|
|
||||||
$( this ).closest('tr').addClass('editing');
|
|
||||||
$( this ).closest('tr').find('.view').hide();
|
|
||||||
$( this ).closest('tr').find('.edit').show();
|
|
||||||
event.data.view.model.trigger( 'change:classes' );
|
|
||||||
},
|
|
||||||
onDeleteRow: function( event ) {
|
|
||||||
var view = event.data.view,
|
|
||||||
model = view.model,
|
|
||||||
classes = _.indexBy( model.get( 'classes' ), 'term_id' ),
|
|
||||||
changes = {},
|
|
||||||
term_id = $( this ).closest('tr').data('id');
|
|
||||||
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
if ( classes[ term_id ] ) {
|
|
||||||
delete classes[ term_id ];
|
|
||||||
changes[ term_id ] = _.extend( changes[ term_id ] || {}, { deleted : 'deleted' } );
|
|
||||||
model.set( 'classes', classes );
|
|
||||||
model.logChanges( changes );
|
|
||||||
}
|
|
||||||
|
|
||||||
view.render();
|
|
||||||
},
|
|
||||||
onCancelEditRow: function( event ) {
|
|
||||||
var view = event.data.view,
|
|
||||||
model = view.model,
|
|
||||||
row = $( this ).closest('tr'),
|
|
||||||
term_id = $( this ).closest('tr').data('id'),
|
|
||||||
classes = _.indexBy( model.get( 'classes' ), 'term_id' );
|
|
||||||
|
|
||||||
event.preventDefault();
|
|
||||||
model.discardChanges( term_id );
|
|
||||||
|
|
||||||
if ( classes[ term_id ] ) {
|
|
||||||
classes[ term_id ].editing = false;
|
|
||||||
row.after( view.rowTemplate( classes[ term_id ] ) );
|
|
||||||
view.initRow( classes[ term_id ] );
|
|
||||||
}
|
|
||||||
|
|
||||||
row.remove();
|
|
||||||
},
|
|
||||||
setUnloadConfirmation: function() {
|
|
||||||
this.needsUnloadConfirm = true;
|
|
||||||
$save_button.removeAttr( 'disabled' );
|
|
||||||
},
|
|
||||||
clearUnloadConfirmation: function() {
|
|
||||||
this.needsUnloadConfirm = false;
|
|
||||||
$save_button.attr( 'disabled', 'disabled' );
|
|
||||||
},
|
|
||||||
unloadConfirmation: function( event ) {
|
|
||||||
if ( event.data.view.needsUnloadConfirm ) {
|
|
||||||
event.returnValue = data.strings.unload_confirmation_msg;
|
|
||||||
window.event.returnValue = data.strings.unload_confirmation_msg;
|
|
||||||
return data.strings.unload_confirmation_msg;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
updateModelOnChange: function( event ) {
|
|
||||||
var model = event.data.view.model,
|
|
||||||
$target = $( event.target ),
|
|
||||||
term_id = $target.closest( 'tr' ).data( 'id' ),
|
|
||||||
attribute = $target.data( 'attribute' ),
|
|
||||||
value = $target.val(),
|
|
||||||
classes = _.indexBy( model.get( 'classes' ), 'term_id' ),
|
|
||||||
changes = {};
|
|
||||||
|
|
||||||
if ( ! classes[ term_id ] || classes[ term_id ][ attribute ] !== value ) {
|
|
||||||
changes[ term_id ] = {};
|
|
||||||
changes[ term_id ][ attribute ] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
model.logChanges( changes );
|
|
||||||
}
|
|
||||||
} ),
|
|
||||||
shippingClass = new ShippingClass({
|
|
||||||
classes: data.classes
|
|
||||||
} ),
|
|
||||||
shippingClassView = new ShippingClassView({
|
|
||||||
model: shippingClass,
|
|
||||||
el: $tbody
|
|
||||||
} );
|
|
||||||
|
|
||||||
shippingClassView.render();
|
|
||||||
});
|
|
||||||
})( jQuery, shippingClassesLocalizeScript, wp, ajaxurl );
|
|
|
@ -1,426 +0,0 @@
|
||||||
/* global shippingZoneMethodsLocalizeScript, ajaxurl */
|
|
||||||
( function( $, data, wp, ajaxurl ) {
|
|
||||||
$( function() {
|
|
||||||
var $table = $( '.wc-shipping-zone-methods' ),
|
|
||||||
$tbody = $( '.wc-shipping-zone-method-rows' ),
|
|
||||||
$save_button = $( '.wc-shipping-zone-method-save' ),
|
|
||||||
$row_template = wp.template( 'wc-shipping-zone-method-row' ),
|
|
||||||
$blank_template = wp.template( 'wc-shipping-zone-method-row-blank' ),
|
|
||||||
|
|
||||||
// Backbone model
|
|
||||||
ShippingMethod = Backbone.Model.extend({
|
|
||||||
changes: {},
|
|
||||||
logChanges: function( changedRows ) {
|
|
||||||
var changes = this.changes || {};
|
|
||||||
|
|
||||||
_.each( changedRows.methods, function( row, id ) {
|
|
||||||
changes.methods = changes.methods || { methods : {} };
|
|
||||||
changes.methods[ id ] = _.extend( changes.methods[ id ] || { instance_id : id }, row );
|
|
||||||
} );
|
|
||||||
|
|
||||||
if ( typeof changedRows.zone_name !== 'undefined' ) {
|
|
||||||
changes.zone_name = changedRows.zone_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( typeof changedRows.zone_locations !== 'undefined' ) {
|
|
||||||
changes.zone_locations = changedRows.zone_locations;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( typeof changedRows.zone_postcodes !== 'undefined' ) {
|
|
||||||
changes.zone_postcodes = changedRows.zone_postcodes;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.changes = changes;
|
|
||||||
this.trigger( 'change:methods' );
|
|
||||||
},
|
|
||||||
save: function() {
|
|
||||||
$.post(
|
|
||||||
ajaxurl + ( ajaxurl.indexOf( '?' ) > 0 ? '&' : '?' ) + 'action=woocommerce_shipping_zone_methods_save_changes',
|
|
||||||
{
|
|
||||||
wc_shipping_zones_nonce : data.wc_shipping_zones_nonce,
|
|
||||||
changes : this.changes,
|
|
||||||
zone_id : data.zone_id
|
|
||||||
},
|
|
||||||
this.onSaveResponse,
|
|
||||||
'json'
|
|
||||||
);
|
|
||||||
},
|
|
||||||
onSaveResponse: function( response, textStatus ) {
|
|
||||||
if ( 'success' === textStatus ) {
|
|
||||||
if ( response.success ) {
|
|
||||||
if ( response.data.zone_id !== data.zone_id ) {
|
|
||||||
data.zone_id = response.data.zone_id;
|
|
||||||
if ( window.history.pushState ) {
|
|
||||||
window.history.pushState(
|
|
||||||
{},
|
|
||||||
'',
|
|
||||||
'admin.php?page=wc-settings&tab=shipping&zone_id=' + response.data.zone_id
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
shippingMethod.set( 'methods', response.data.methods );
|
|
||||||
shippingMethod.trigger( 'change:methods' );
|
|
||||||
shippingMethod.changes = {};
|
|
||||||
shippingMethod.trigger( 'saved:methods' );
|
|
||||||
} else {
|
|
||||||
window.alert( data.strings.save_failed );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} ),
|
|
||||||
|
|
||||||
// Backbone view
|
|
||||||
ShippingMethodView = Backbone.View.extend({
|
|
||||||
rowTemplate: $row_template,
|
|
||||||
initialize: function() {
|
|
||||||
this.listenTo( this.model, 'change:methods', this.setUnloadConfirmation );
|
|
||||||
this.listenTo( this.model, 'saved:methods', this.clearUnloadConfirmation );
|
|
||||||
this.listenTo( this.model, 'saved:methods', this.render );
|
|
||||||
$tbody.on( 'change', { view: this }, this.updateModelOnChange );
|
|
||||||
$tbody.on( 'sortupdate', { view: this }, this.updateModelOnSort );
|
|
||||||
$( window ).on( 'beforeunload', { view: this }, this.unloadConfirmation );
|
|
||||||
$save_button.on( 'click', { view: this }, this.onSubmit );
|
|
||||||
|
|
||||||
$( document.body ).on(
|
|
||||||
'input change',
|
|
||||||
'#zone_name, #zone_locations, #zone_postcodes',
|
|
||||||
{ view: this },
|
|
||||||
this.onUpdateZone
|
|
||||||
);
|
|
||||||
$( document.body ).on( 'click', '.wc-shipping-zone-method-settings', { view: this }, this.onConfigureShippingMethod );
|
|
||||||
$( document.body ).on( 'click', '.wc-shipping-zone-add-method', { view: this }, this.onAddShippingMethod );
|
|
||||||
$( document.body ).on( 'wc_backbone_modal_response', this.onConfigureShippingMethodSubmitted );
|
|
||||||
$( document.body ).on( 'wc_backbone_modal_response', this.onAddShippingMethodSubmitted );
|
|
||||||
$( document.body ).on( 'change', '.wc-shipping-zone-method-selector select', this.onChangeShippingMethodSelector );
|
|
||||||
$( document.body ).on( 'click', '.wc-shipping-zone-postcodes-toggle', this.onTogglePostcodes );
|
|
||||||
},
|
|
||||||
onUpdateZone: function( event ) {
|
|
||||||
var view = event.data.view,
|
|
||||||
model = view.model,
|
|
||||||
value = $( this ).val(),
|
|
||||||
$target = $( event.target ),
|
|
||||||
attribute = $target.data( 'attribute' ),
|
|
||||||
changes = {};
|
|
||||||
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
changes[ attribute ] = value;
|
|
||||||
model.set( attribute, value );
|
|
||||||
model.logChanges( changes );
|
|
||||||
view.render();
|
|
||||||
},
|
|
||||||
block: function() {
|
|
||||||
$( this.el ).block({
|
|
||||||
message: null,
|
|
||||||
overlayCSS: {
|
|
||||||
background: '#fff',
|
|
||||||
opacity: 0.6
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
unblock: function() {
|
|
||||||
$( this.el ).unblock();
|
|
||||||
},
|
|
||||||
render: function() {
|
|
||||||
var methods = _.indexBy( this.model.get( 'methods' ), 'instance_id' ),
|
|
||||||
zone_name = this.model.get( 'zone_name' ),
|
|
||||||
view = this;
|
|
||||||
|
|
||||||
// Set name.
|
|
||||||
$('.wc-shipping-zone-name').text( zone_name ? zone_name : data.strings.default_zone_name );
|
|
||||||
|
|
||||||
// Blank out the contents.
|
|
||||||
this.$el.empty();
|
|
||||||
this.unblock();
|
|
||||||
|
|
||||||
if ( _.size( methods ) ) {
|
|
||||||
// Sort methods
|
|
||||||
methods = _.sortBy( methods, function( method ) {
|
|
||||||
return parseInt( method.method_order, 10 );
|
|
||||||
} );
|
|
||||||
|
|
||||||
// Populate $tbody with the current methods
|
|
||||||
$.each( methods, function( id, rowData ) {
|
|
||||||
if ( 'yes' === rowData.enabled ) {
|
|
||||||
rowData.enabled_icon = '<span class="woocommerce-input-toggle woocommerce-input-toggle--enabled">' +
|
|
||||||
data.strings.yes +
|
|
||||||
'</span>';
|
|
||||||
} else {
|
|
||||||
rowData.enabled_icon = '<span class="woocommerce-input-toggle woocommerce-input-toggle--disabled">' +
|
|
||||||
data.strings.no +
|
|
||||||
'</span>';
|
|
||||||
}
|
|
||||||
|
|
||||||
view.$el.append( view.rowTemplate( rowData ) );
|
|
||||||
|
|
||||||
var $tr = view.$el.find( 'tr[data-id="' + rowData.instance_id + '"]');
|
|
||||||
|
|
||||||
if ( ! rowData.has_settings ) {
|
|
||||||
$tr
|
|
||||||
.find( '.wc-shipping-zone-method-title > a' )
|
|
||||||
.replaceWith('<span>' + $tr.find( '.wc-shipping-zone-method-title > a' ).text() + '</span>' );
|
|
||||||
var $del = $tr.find( '.wc-shipping-zone-method-delete' );
|
|
||||||
$tr.find( '.wc-shipping-zone-method-title .row-actions' ).empty().html($del);
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
|
|
||||||
// Make the rows function
|
|
||||||
this.$el.find( '.wc-shipping-zone-method-delete' ).on( 'click', { view: this }, this.onDeleteRow );
|
|
||||||
this.$el.find( '.wc-shipping-zone-method-enabled a').on( 'click', { view: this }, this.onToggleEnabled );
|
|
||||||
} else {
|
|
||||||
view.$el.append( $blank_template );
|
|
||||||
}
|
|
||||||
|
|
||||||
this.initTooltips();
|
|
||||||
},
|
|
||||||
initTooltips: function() {
|
|
||||||
$( '#tiptip_holder' ).removeAttr( 'style' );
|
|
||||||
$( '#tiptip_arrow' ).removeAttr( 'style' );
|
|
||||||
$( '.tips' ).tipTip({ 'attribute': 'data-tip', 'fadeIn': 50, 'fadeOut': 50, 'delay': 50 });
|
|
||||||
},
|
|
||||||
onSubmit: function( event ) {
|
|
||||||
event.data.view.block();
|
|
||||||
event.data.view.model.save();
|
|
||||||
event.preventDefault();
|
|
||||||
},
|
|
||||||
onDeleteRow: function( event ) {
|
|
||||||
var view = event.data.view,
|
|
||||||
model = view.model,
|
|
||||||
methods = _.indexBy( model.get( 'methods' ), 'instance_id' ),
|
|
||||||
changes = {},
|
|
||||||
instance_id = $( this ).closest('tr').data('id');
|
|
||||||
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
delete methods[ instance_id ];
|
|
||||||
changes.methods = changes.methods || { methods : {} };
|
|
||||||
changes.methods[ instance_id ] = _.extend( changes.methods[ instance_id ] || {}, { deleted : 'deleted' } );
|
|
||||||
model.set( 'methods', methods );
|
|
||||||
model.logChanges( changes );
|
|
||||||
view.render();
|
|
||||||
},
|
|
||||||
onToggleEnabled: function( event ) {
|
|
||||||
var view = event.data.view,
|
|
||||||
$target = $( event.target ),
|
|
||||||
model = view.model,
|
|
||||||
methods = _.indexBy( model.get( 'methods' ), 'instance_id' ),
|
|
||||||
instance_id = $target.closest( 'tr' ).data( 'id' ),
|
|
||||||
enabled = $target.closest( 'tr' ).data( 'enabled' ) === 'yes' ? 'no' : 'yes',
|
|
||||||
changes = {};
|
|
||||||
|
|
||||||
event.preventDefault();
|
|
||||||
methods[ instance_id ].enabled = enabled;
|
|
||||||
changes.methods = changes.methods || { methods : {} };
|
|
||||||
changes.methods[ instance_id ] = _.extend( changes.methods[ instance_id ] || {}, { enabled : enabled } );
|
|
||||||
model.set( 'methods', methods );
|
|
||||||
model.logChanges( changes );
|
|
||||||
view.render();
|
|
||||||
},
|
|
||||||
setUnloadConfirmation: function() {
|
|
||||||
this.needsUnloadConfirm = true;
|
|
||||||
$save_button.removeAttr( 'disabled' );
|
|
||||||
},
|
|
||||||
clearUnloadConfirmation: function() {
|
|
||||||
this.needsUnloadConfirm = false;
|
|
||||||
$save_button.attr( 'disabled', 'disabled' );
|
|
||||||
},
|
|
||||||
unloadConfirmation: function( event ) {
|
|
||||||
if ( event.data.view.needsUnloadConfirm ) {
|
|
||||||
event.returnValue = data.strings.unload_confirmation_msg;
|
|
||||||
window.event.returnValue = data.strings.unload_confirmation_msg;
|
|
||||||
return data.strings.unload_confirmation_msg;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
updateModelOnChange: function( event ) {
|
|
||||||
var model = event.data.view.model,
|
|
||||||
$target = $( event.target ),
|
|
||||||
instance_id = $target.closest( 'tr' ).data( 'id' ),
|
|
||||||
attribute = $target.data( 'attribute' ),
|
|
||||||
value = $target.val(),
|
|
||||||
methods = _.indexBy( model.get( 'methods' ), 'instance_id' ),
|
|
||||||
changes = {};
|
|
||||||
|
|
||||||
if ( methods[ instance_id ][ attribute ] !== value ) {
|
|
||||||
changes.methods[ instance_id ] = {};
|
|
||||||
changes.methods[ instance_id ][ attribute ] = value;
|
|
||||||
methods[ instance_id ][ attribute ] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
model.logChanges( changes );
|
|
||||||
},
|
|
||||||
updateModelOnSort: function( event ) {
|
|
||||||
var view = event.data.view,
|
|
||||||
model = view.model,
|
|
||||||
methods = _.indexBy( model.get( 'methods' ), 'instance_id' ),
|
|
||||||
changes = {};
|
|
||||||
|
|
||||||
_.each( methods, function( method ) {
|
|
||||||
var old_position = parseInt( method.method_order, 10 );
|
|
||||||
var new_position = parseInt( $table.find( 'tr[data-id="' + method.instance_id + '"]').index() + 1, 10 );
|
|
||||||
|
|
||||||
if ( old_position !== new_position ) {
|
|
||||||
methods[ method.instance_id ].method_order = new_position;
|
|
||||||
changes.methods = changes.methods || { methods : {} };
|
|
||||||
changes.methods[ method.instance_id ] = _.extend(
|
|
||||||
changes.methods[ method.instance_id ] || {}, { method_order : new_position }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
|
|
||||||
if ( _.size( changes ) ) {
|
|
||||||
model.logChanges( changes );
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onConfigureShippingMethod: function( event ) {
|
|
||||||
var instance_id = $( this ).closest( 'tr' ).data( 'id' ),
|
|
||||||
model = event.data.view.model,
|
|
||||||
methods = _.indexBy( model.get( 'methods' ), 'instance_id' ),
|
|
||||||
method = methods[ instance_id ];
|
|
||||||
|
|
||||||
// Only load modal if supported
|
|
||||||
if ( ! method.settings_html ) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
$( this ).WCBackboneModal({
|
|
||||||
template : 'wc-modal-shipping-method-settings',
|
|
||||||
variable : {
|
|
||||||
instance_id : instance_id,
|
|
||||||
method : method
|
|
||||||
},
|
|
||||||
data : {
|
|
||||||
instance_id : instance_id,
|
|
||||||
method : method
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$( document.body ).trigger( 'init_tooltips' );
|
|
||||||
},
|
|
||||||
onConfigureShippingMethodSubmitted: function( event, target, posted_data ) {
|
|
||||||
if ( 'wc-modal-shipping-method-settings' === target ) {
|
|
||||||
shippingMethodView.block();
|
|
||||||
|
|
||||||
// Save method settings via ajax call
|
|
||||||
$.post(
|
|
||||||
ajaxurl + ( ajaxurl.indexOf( '?' ) > 0 ? '&' : '?' ) + 'action=woocommerce_shipping_zone_methods_save_settings',
|
|
||||||
{
|
|
||||||
wc_shipping_zones_nonce : data.wc_shipping_zones_nonce,
|
|
||||||
instance_id : posted_data.instance_id,
|
|
||||||
data : posted_data
|
|
||||||
},
|
|
||||||
function( response, textStatus ) {
|
|
||||||
if ( 'success' === textStatus && response.success ) {
|
|
||||||
$( 'table.wc-shipping-zone-methods' ).parent().find( '#woocommerce_errors' ).remove();
|
|
||||||
|
|
||||||
// If there were errors, prepend the form.
|
|
||||||
if ( response.data.errors.length > 0 ) {
|
|
||||||
shippingMethodView.showErrors( response.data.errors );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Method was saved. Re-render.
|
|
||||||
if ( _.size( shippingMethodView.model.changes ) ) {
|
|
||||||
shippingMethodView.model.save();
|
|
||||||
} else {
|
|
||||||
shippingMethodView.model.onSaveResponse( response, textStatus );
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
window.alert( data.strings.save_failed );
|
|
||||||
shippingMethodView.unblock();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'json'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
showErrors: function( errors ) {
|
|
||||||
var error_html = '<div id="woocommerce_errors" class="error notice is-dismissible">';
|
|
||||||
|
|
||||||
$( errors ).each( function( index, value ) {
|
|
||||||
error_html = error_html + '<p>' + value + '</p>';
|
|
||||||
} );
|
|
||||||
error_html = error_html + '</div>';
|
|
||||||
|
|
||||||
$( 'table.wc-shipping-zone-methods' ).before( error_html );
|
|
||||||
},
|
|
||||||
onAddShippingMethod: function( event ) {
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
$( this ).WCBackboneModal({
|
|
||||||
template : 'wc-modal-add-shipping-method',
|
|
||||||
variable : {
|
|
||||||
zone_id : data.zone_id
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$( '.wc-shipping-zone-method-selector select' ).trigger( 'change' );
|
|
||||||
},
|
|
||||||
onAddShippingMethodSubmitted: function( event, target, posted_data ) {
|
|
||||||
if ( 'wc-modal-add-shipping-method' === target ) {
|
|
||||||
shippingMethodView.block();
|
|
||||||
|
|
||||||
// Add method to zone via ajax call
|
|
||||||
$.post( ajaxurl + ( ajaxurl.indexOf( '?' ) > 0 ? '&' : '?' ) + 'action=woocommerce_shipping_zone_add_method', {
|
|
||||||
wc_shipping_zones_nonce : data.wc_shipping_zones_nonce,
|
|
||||||
method_id : posted_data.add_method_id,
|
|
||||||
zone_id : data.zone_id
|
|
||||||
}, function( response, textStatus ) {
|
|
||||||
if ( 'success' === textStatus && response.success ) {
|
|
||||||
if ( response.data.zone_id !== data.zone_id ) {
|
|
||||||
data.zone_id = response.data.zone_id;
|
|
||||||
if ( window.history.pushState ) {
|
|
||||||
window.history.pushState(
|
|
||||||
{},
|
|
||||||
'',
|
|
||||||
'admin.php?page=wc-settings&tab=shipping&zone_id=' + response.data.zone_id
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Trigger save if there are changes, or just re-render
|
|
||||||
if ( _.size( shippingMethodView.model.changes ) ) {
|
|
||||||
shippingMethodView.model.save();
|
|
||||||
} else {
|
|
||||||
shippingMethodView.model.set( 'methods', response.data.methods );
|
|
||||||
shippingMethodView.model.trigger( 'change:methods' );
|
|
||||||
shippingMethodView.model.changes = {};
|
|
||||||
shippingMethodView.model.trigger( 'saved:methods' );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
shippingMethodView.unblock();
|
|
||||||
}, 'json' );
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onChangeShippingMethodSelector: function() {
|
|
||||||
var description = $( this ).find( 'option:selected' ).data( 'description' );
|
|
||||||
$( this ).parent().find( '.wc-shipping-zone-method-description' ).remove();
|
|
||||||
$( this ).after( '<div class="wc-shipping-zone-method-description">' + description + '</div>' );
|
|
||||||
$( this ).closest( 'article' ).height( $( this ).parent().height() );
|
|
||||||
},
|
|
||||||
onTogglePostcodes: function( event ) {
|
|
||||||
event.preventDefault();
|
|
||||||
var $tr = $( this ).closest( 'tr');
|
|
||||||
$tr.find( '.wc-shipping-zone-postcodes' ).show();
|
|
||||||
$tr.find( '.wc-shipping-zone-postcodes-toggle' ).hide();
|
|
||||||
}
|
|
||||||
} ),
|
|
||||||
shippingMethod = new ShippingMethod({
|
|
||||||
methods: data.methods,
|
|
||||||
zone_name: data.zone_name
|
|
||||||
} ),
|
|
||||||
shippingMethodView = new ShippingMethodView({
|
|
||||||
model: shippingMethod,
|
|
||||||
el: $tbody
|
|
||||||
} );
|
|
||||||
|
|
||||||
shippingMethodView.render();
|
|
||||||
|
|
||||||
$tbody.sortable({
|
|
||||||
items: 'tr',
|
|
||||||
cursor: 'move',
|
|
||||||
axis: 'y',
|
|
||||||
handle: 'td.wc-shipping-zone-method-sort',
|
|
||||||
scrollSensitivity: 40
|
|
||||||
});
|
|
||||||
});
|
|
||||||
})( jQuery, shippingZoneMethodsLocalizeScript, wp, ajaxurl );
|
|
|
@ -1,271 +0,0 @@
|
||||||
/* global shippingZonesLocalizeScript, ajaxurl */
|
|
||||||
( function( $, data, wp, ajaxurl ) {
|
|
||||||
$( function() {
|
|
||||||
var $table = $( '.wc-shipping-zones' ),
|
|
||||||
$tbody = $( '.wc-shipping-zone-rows' ),
|
|
||||||
$save_button = $( '.wc-shipping-zone-save' ),
|
|
||||||
$row_template = wp.template( 'wc-shipping-zone-row' ),
|
|
||||||
$blank_template = wp.template( 'wc-shipping-zone-row-blank' ),
|
|
||||||
|
|
||||||
// Backbone model
|
|
||||||
ShippingZone = Backbone.Model.extend({
|
|
||||||
changes: {},
|
|
||||||
logChanges: function( changedRows ) {
|
|
||||||
var changes = this.changes || {};
|
|
||||||
|
|
||||||
_.each( changedRows, function( row, id ) {
|
|
||||||
changes[ id ] = _.extend( changes[ id ] || { zone_id : id }, row );
|
|
||||||
} );
|
|
||||||
|
|
||||||
this.changes = changes;
|
|
||||||
this.trigger( 'change:zones' );
|
|
||||||
},
|
|
||||||
discardChanges: function( id ) {
|
|
||||||
var changes = this.changes || {},
|
|
||||||
set_position = null,
|
|
||||||
zones = _.indexBy( this.get( 'zones' ), 'zone_id' );
|
|
||||||
|
|
||||||
// Find current set position if it has moved since last save
|
|
||||||
if ( changes[ id ] && changes[ id ].zone_order !== undefined ) {
|
|
||||||
set_position = changes[ id ].zone_order;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete all changes
|
|
||||||
delete changes[ id ];
|
|
||||||
|
|
||||||
// If the position was set, and this zone does exist in DB, set the position again so the changes are not lost.
|
|
||||||
if ( set_position !== null && zones[ id ] && zones[ id ].zone_order !== set_position ) {
|
|
||||||
changes[ id ] = _.extend( changes[ id ] || {}, { zone_id : id, zone_order : set_position } );
|
|
||||||
}
|
|
||||||
|
|
||||||
this.changes = changes;
|
|
||||||
|
|
||||||
// No changes? Disable save button.
|
|
||||||
if ( 0 === _.size( this.changes ) ) {
|
|
||||||
shippingZoneView.clearUnloadConfirmation();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
save: function() {
|
|
||||||
if ( _.size( this.changes ) ) {
|
|
||||||
$.post( ajaxurl + ( ajaxurl.indexOf( '?' ) > 0 ? '&' : '?' ) + 'action=woocommerce_shipping_zones_save_changes', {
|
|
||||||
wc_shipping_zones_nonce : data.wc_shipping_zones_nonce,
|
|
||||||
changes : this.changes
|
|
||||||
}, this.onSaveResponse, 'json' );
|
|
||||||
} else {
|
|
||||||
shippingZone.trigger( 'saved:zones' );
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onSaveResponse: function( response, textStatus ) {
|
|
||||||
if ( 'success' === textStatus ) {
|
|
||||||
if ( response.success ) {
|
|
||||||
shippingZone.set( 'zones', response.data.zones );
|
|
||||||
shippingZone.trigger( 'change:zones' );
|
|
||||||
shippingZone.changes = {};
|
|
||||||
shippingZone.trigger( 'saved:zones' );
|
|
||||||
} else {
|
|
||||||
window.alert( data.strings.save_failed );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} ),
|
|
||||||
|
|
||||||
// Backbone view
|
|
||||||
ShippingZoneView = Backbone.View.extend({
|
|
||||||
rowTemplate: $row_template,
|
|
||||||
initialize: function() {
|
|
||||||
this.listenTo( this.model, 'change:zones', this.setUnloadConfirmation );
|
|
||||||
this.listenTo( this.model, 'saved:zones', this.clearUnloadConfirmation );
|
|
||||||
this.listenTo( this.model, 'saved:zones', this.render );
|
|
||||||
$tbody.on( 'change', { view: this }, this.updateModelOnChange );
|
|
||||||
$tbody.on( 'sortupdate', { view: this }, this.updateModelOnSort );
|
|
||||||
$( window ).on( 'beforeunload', { view: this }, this.unloadConfirmation );
|
|
||||||
$( document.body ).on( 'click', '.wc-shipping-zone-add', { view: this }, this.onAddNewRow );
|
|
||||||
},
|
|
||||||
block: function() {
|
|
||||||
$( this.el ).block({
|
|
||||||
message: null,
|
|
||||||
overlayCSS: {
|
|
||||||
background: '#fff',
|
|
||||||
opacity: 0.6
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
unblock: function() {
|
|
||||||
$( this.el ).unblock();
|
|
||||||
},
|
|
||||||
render: function() {
|
|
||||||
var zones = _.indexBy( this.model.get( 'zones' ), 'zone_id' ),
|
|
||||||
view = this;
|
|
||||||
|
|
||||||
view.$el.empty();
|
|
||||||
view.unblock();
|
|
||||||
|
|
||||||
if ( _.size( zones ) ) {
|
|
||||||
// Sort zones
|
|
||||||
zones = _( zones )
|
|
||||||
.chain()
|
|
||||||
.sortBy( function ( zone ) { return parseInt( zone.zone_id, 10 ); } )
|
|
||||||
.sortBy( function ( zone ) { return parseInt( zone.zone_order, 10 ); } )
|
|
||||||
.value();
|
|
||||||
|
|
||||||
// Populate $tbody with the current zones
|
|
||||||
$.each( zones, function( id, rowData ) {
|
|
||||||
view.renderRow( rowData );
|
|
||||||
} );
|
|
||||||
} else {
|
|
||||||
view.$el.append( $blank_template );
|
|
||||||
}
|
|
||||||
|
|
||||||
view.initRows();
|
|
||||||
},
|
|
||||||
renderRow: function( rowData ) {
|
|
||||||
var view = this;
|
|
||||||
view.$el.append( view.rowTemplate( rowData ) );
|
|
||||||
view.initRow( rowData );
|
|
||||||
},
|
|
||||||
initRow: function( rowData ) {
|
|
||||||
var view = this;
|
|
||||||
var $tr = view.$el.find( 'tr[data-id="' + rowData.zone_id + '"]');
|
|
||||||
|
|
||||||
// List shipping methods
|
|
||||||
view.renderShippingMethods( rowData.zone_id, rowData.shipping_methods );
|
|
||||||
$tr.find( '.wc-shipping-zone-delete' ).on( 'click', { view: this }, this.onDeleteRow );
|
|
||||||
},
|
|
||||||
initRows: function() {
|
|
||||||
// Stripe
|
|
||||||
if ( 0 === ( $( 'tbody.wc-shipping-zone-rows tr' ).length % 2 ) ) {
|
|
||||||
$table.find( 'tbody.wc-shipping-zone-rows' ).next( 'tbody' ).find( 'tr' ).addClass( 'odd' );
|
|
||||||
} else {
|
|
||||||
$table.find( 'tbody.wc-shipping-zone-rows' ).next( 'tbody' ).find( 'tr' ).removeClass( 'odd' );
|
|
||||||
}
|
|
||||||
// Tooltips
|
|
||||||
$( '#tiptip_holder' ).removeAttr( 'style' );
|
|
||||||
$( '#tiptip_arrow' ).removeAttr( 'style' );
|
|
||||||
$( '.tips' ).tipTip({ 'attribute': 'data-tip', 'fadeIn': 50, 'fadeOut': 50, 'delay': 50 });
|
|
||||||
},
|
|
||||||
renderShippingMethods: function( zone_id, shipping_methods ) {
|
|
||||||
var $tr = $( '.wc-shipping-zones tr[data-id="' + zone_id + '"]');
|
|
||||||
var $method_list = $tr.find('.wc-shipping-zone-methods ul');
|
|
||||||
|
|
||||||
$method_list.find( '.wc-shipping-zone-method' ).remove();
|
|
||||||
|
|
||||||
if ( _.size( shipping_methods ) ) {
|
|
||||||
shipping_methods = _.sortBy( shipping_methods, function( method ) {
|
|
||||||
return parseInt( method.method_order, 10 );
|
|
||||||
} );
|
|
||||||
|
|
||||||
_.each( shipping_methods, function( shipping_method ) {
|
|
||||||
var class_name = 'method_disabled';
|
|
||||||
|
|
||||||
if ( 'yes' === shipping_method.enabled ) {
|
|
||||||
class_name = 'method_enabled';
|
|
||||||
}
|
|
||||||
|
|
||||||
$method_list.append(
|
|
||||||
'<li class="wc-shipping-zone-method ' + class_name + '">' + shipping_method.title + '</li>'
|
|
||||||
);
|
|
||||||
} );
|
|
||||||
} else {
|
|
||||||
$method_list.append( '<li class="wc-shipping-zone-method">' + data.strings.no_shipping_methods_offered + '</li>' );
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onDeleteRow: function( event ) {
|
|
||||||
var view = event.data.view,
|
|
||||||
model = view.model,
|
|
||||||
zones = _.indexBy( model.get( 'zones' ), 'zone_id' ),
|
|
||||||
changes = {},
|
|
||||||
row = $( this ).closest('tr'),
|
|
||||||
zone_id = row.data('id');
|
|
||||||
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
if ( window.confirm( data.strings.delete_confirmation_msg ) ) {
|
|
||||||
if ( zones[ zone_id ] ) {
|
|
||||||
delete zones[ zone_id ];
|
|
||||||
changes[ zone_id ] = _.extend( changes[ zone_id ] || {}, { deleted : 'deleted' } );
|
|
||||||
model.set( 'zones', zones );
|
|
||||||
model.logChanges( changes );
|
|
||||||
event.data.view.block();
|
|
||||||
event.data.view.model.save();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
setUnloadConfirmation: function() {
|
|
||||||
this.needsUnloadConfirm = true;
|
|
||||||
$save_button.prop( 'disabled', false );
|
|
||||||
},
|
|
||||||
clearUnloadConfirmation: function() {
|
|
||||||
this.needsUnloadConfirm = false;
|
|
||||||
$save_button.prop( 'disabled', true );
|
|
||||||
},
|
|
||||||
unloadConfirmation: function( event ) {
|
|
||||||
if ( event.data.view.needsUnloadConfirm ) {
|
|
||||||
event.returnValue = data.strings.unload_confirmation_msg;
|
|
||||||
window.event.returnValue = data.strings.unload_confirmation_msg;
|
|
||||||
return data.strings.unload_confirmation_msg;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
updateModelOnChange: function( event ) {
|
|
||||||
var model = event.data.view.model,
|
|
||||||
$target = $( event.target ),
|
|
||||||
zone_id = $target.closest( 'tr' ).data( 'id' ),
|
|
||||||
attribute = $target.data( 'attribute' ),
|
|
||||||
value = $target.val(),
|
|
||||||
zones = _.indexBy( model.get( 'zones' ), 'zone_id' ),
|
|
||||||
changes = {};
|
|
||||||
|
|
||||||
if ( ! zones[ zone_id ] || zones[ zone_id ][ attribute ] !== value ) {
|
|
||||||
changes[ zone_id ] = {};
|
|
||||||
changes[ zone_id ][ attribute ] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
model.logChanges( changes );
|
|
||||||
},
|
|
||||||
updateModelOnSort: function( event ) {
|
|
||||||
var view = event.data.view,
|
|
||||||
model = view.model,
|
|
||||||
zones = _.indexBy( model.get( 'zones' ), 'zone_id' ),
|
|
||||||
rows = $( 'tbody.wc-shipping-zone-rows tr' ),
|
|
||||||
changes = {};
|
|
||||||
|
|
||||||
// Update sorted row position
|
|
||||||
_.each( rows, function( row ) {
|
|
||||||
var zone_id = $( row ).data( 'id' ),
|
|
||||||
old_position = null,
|
|
||||||
new_position = parseInt( $( row ).index(), 10 );
|
|
||||||
|
|
||||||
if ( zones[ zone_id ] ) {
|
|
||||||
old_position = parseInt( zones[ zone_id ].zone_order, 10 );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( old_position !== new_position ) {
|
|
||||||
changes[ zone_id ] = _.extend( changes[ zone_id ] || {}, { zone_order : new_position } );
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
|
|
||||||
if ( _.size( changes ) ) {
|
|
||||||
model.logChanges( changes );
|
|
||||||
event.data.view.block();
|
|
||||||
event.data.view.model.save();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} ),
|
|
||||||
shippingZone = new ShippingZone({
|
|
||||||
zones: data.zones
|
|
||||||
} ),
|
|
||||||
shippingZoneView = new ShippingZoneView({
|
|
||||||
model: shippingZone,
|
|
||||||
el: $tbody
|
|
||||||
} );
|
|
||||||
|
|
||||||
shippingZoneView.render();
|
|
||||||
|
|
||||||
$tbody.sortable({
|
|
||||||
items: 'tr',
|
|
||||||
cursor: 'move',
|
|
||||||
axis: 'y',
|
|
||||||
handle: 'td.wc-shipping-zone-sort',
|
|
||||||
scrollSensitivity: 40
|
|
||||||
});
|
|
||||||
});
|
|
||||||
})( jQuery, shippingZonesLocalizeScript, wp, ajaxurl );
|
|
|
@ -1,32 +0,0 @@
|
||||||
/*global jQuery */
|
|
||||||
(function( $ ) {
|
|
||||||
var recordEvent = function( link ) {
|
|
||||||
window.wcTracks.recordEvent( 'status_widget_click', {
|
|
||||||
link: link
|
|
||||||
} );
|
|
||||||
};
|
|
||||||
|
|
||||||
$( '.sales-this-month a' ).on( 'click', function() {
|
|
||||||
recordEvent( 'net-sales' );
|
|
||||||
});
|
|
||||||
|
|
||||||
$( '.best-seller-this-month a' ).on( 'click', function() {
|
|
||||||
recordEvent( 'best-seller-this-month' );
|
|
||||||
});
|
|
||||||
|
|
||||||
$( '.processing-orders a' ).on( 'click', function() {
|
|
||||||
recordEvent( 'orders-processing' );
|
|
||||||
});
|
|
||||||
|
|
||||||
$( '.on-hold-orders a' ).on( 'click', function() {
|
|
||||||
recordEvent( 'orders-on-hold' );
|
|
||||||
});
|
|
||||||
|
|
||||||
$( '.low-in-stock a' ).on( 'click', function() {
|
|
||||||
recordEvent( 'low-stock' );
|
|
||||||
});
|
|
||||||
|
|
||||||
$( '.out-of-stock a' ).on( 'click', function() {
|
|
||||||
recordEvent( 'out-of-stock' );
|
|
||||||
});
|
|
||||||
})( jQuery );
|
|
|
@ -1,411 +0,0 @@
|
||||||
/* global woocommerce_admin */
|
|
||||||
( function( $, woocommerce_admin ) {
|
|
||||||
$( function() {
|
|
||||||
if ( 'undefined' === typeof woocommerce_admin ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add buttons to product screen.
|
|
||||||
var $product_screen = $( '.edit-php.post-type-product' ),
|
|
||||||
$title_action = $product_screen.find( '.page-title-action:first' ),
|
|
||||||
$blankslate = $product_screen.find( '.woocommerce-BlankState' );
|
|
||||||
|
|
||||||
if ( 0 === $blankslate.length ) {
|
|
||||||
if ( woocommerce_admin.urls.export_products ) {
|
|
||||||
$title_action.after(
|
|
||||||
'<a href="' +
|
|
||||||
woocommerce_admin.urls.export_products +
|
|
||||||
'" class="page-title-action">' +
|
|
||||||
woocommerce_admin.strings.export_products +
|
|
||||||
'</a>'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if ( woocommerce_admin.urls.import_products ) {
|
|
||||||
$title_action.after(
|
|
||||||
'<a href="' +
|
|
||||||
woocommerce_admin.urls.import_products +
|
|
||||||
'" class="page-title-action">' +
|
|
||||||
woocommerce_admin.strings.import_products +
|
|
||||||
'</a>'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$title_action.hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Progress indicators when showing steps.
|
|
||||||
$( '.woocommerce-progress-form-wrapper .button-next' ).on( 'click', function() {
|
|
||||||
$('.wc-progress-form-content').block({
|
|
||||||
message: null,
|
|
||||||
overlayCSS: {
|
|
||||||
background: '#fff',
|
|
||||||
opacity: 0.6
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return true;
|
|
||||||
} );
|
|
||||||
|
|
||||||
// Field validation error tips
|
|
||||||
$( document.body )
|
|
||||||
|
|
||||||
.on( 'wc_add_error_tip', function( e, element, error_type ) {
|
|
||||||
var offset = element.position();
|
|
||||||
|
|
||||||
if ( element.parent().find( '.wc_error_tip' ).length === 0 ) {
|
|
||||||
element.after( '<div class="wc_error_tip ' + error_type + '">' + woocommerce_admin[error_type] + '</div>' );
|
|
||||||
element.parent().find( '.wc_error_tip' )
|
|
||||||
.css( 'left', offset.left + element.width() - ( element.width() / 2 ) - ( $( '.wc_error_tip' ).width() / 2 ) )
|
|
||||||
.css( 'top', offset.top + element.height() )
|
|
||||||
.fadeIn( '100' );
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
.on( 'wc_remove_error_tip', function( e, element, error_type ) {
|
|
||||||
element.parent().find( '.wc_error_tip.' + error_type ).fadeOut( '100', function() { $( this ).remove(); } );
|
|
||||||
})
|
|
||||||
|
|
||||||
.on( 'click', function() {
|
|
||||||
$( '.wc_error_tip' ).fadeOut( '100', function() { $( this ).remove(); } );
|
|
||||||
})
|
|
||||||
|
|
||||||
.on( 'blur', '.wc_input_decimal[type=text], .wc_input_price[type=text], .wc_input_country_iso[type=text]', function() {
|
|
||||||
$( '.wc_error_tip' ).fadeOut( '100', function() { $( this ).remove(); } );
|
|
||||||
})
|
|
||||||
|
|
||||||
.on(
|
|
||||||
'change',
|
|
||||||
'.wc_input_price[type=text], .wc_input_decimal[type=text], .wc-order-totals #refund_amount[type=text]',
|
|
||||||
function() {
|
|
||||||
var regex, decimalRegex,
|
|
||||||
decimailPoint = woocommerce_admin.decimal_point;
|
|
||||||
|
|
||||||
if ( $( this ).is( '.wc_input_price' ) || $( this ).is( '#refund_amount' ) ) {
|
|
||||||
decimailPoint = woocommerce_admin.mon_decimal_point;
|
|
||||||
}
|
|
||||||
|
|
||||||
regex = new RegExp( '[^\-0-9\%\\' + decimailPoint + ']+', 'gi' );
|
|
||||||
decimalRegex = new RegExp( '\\' + decimailPoint + '+', 'gi' );
|
|
||||||
|
|
||||||
var value = $( this ).val();
|
|
||||||
var newvalue = value.replace( regex, '' ).replace( decimalRegex, decimailPoint );
|
|
||||||
|
|
||||||
if ( value !== newvalue ) {
|
|
||||||
$( this ).val( newvalue );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
.on(
|
|
||||||
'keyup',
|
|
||||||
// eslint-disable-next-line max-len
|
|
||||||
'.wc_input_price[type=text], .wc_input_decimal[type=text], .wc_input_country_iso[type=text], .wc-order-totals #refund_amount[type=text]',
|
|
||||||
function() {
|
|
||||||
var regex, error, decimalRegex;
|
|
||||||
var checkDecimalNumbers = false;
|
|
||||||
|
|
||||||
if ( $( this ).is( '.wc_input_price' ) || $( this ).is( '#refund_amount' ) ) {
|
|
||||||
checkDecimalNumbers = true;
|
|
||||||
regex = new RegExp( '[^\-0-9\%\\' + woocommerce_admin.mon_decimal_point + ']+', 'gi' );
|
|
||||||
decimalRegex = new RegExp( '[^\\' + woocommerce_admin.mon_decimal_point + ']', 'gi' );
|
|
||||||
error = 'i18n_mon_decimal_error';
|
|
||||||
} else if ( $( this ).is( '.wc_input_country_iso' ) ) {
|
|
||||||
regex = new RegExp( '([^A-Z])+|(.){3,}', 'im' );
|
|
||||||
error = 'i18n_country_iso_error';
|
|
||||||
} else {
|
|
||||||
checkDecimalNumbers = true;
|
|
||||||
regex = new RegExp( '[^\-0-9\%\\' + woocommerce_admin.decimal_point + ']+', 'gi' );
|
|
||||||
decimalRegex = new RegExp( '[^\\' + woocommerce_admin.decimal_point + ']', 'gi' );
|
|
||||||
error = 'i18n_decimal_error';
|
|
||||||
}
|
|
||||||
|
|
||||||
var value = $( this ).val();
|
|
||||||
var newvalue = value.replace( regex, '' );
|
|
||||||
|
|
||||||
// Check if newvalue have more than one decimal point.
|
|
||||||
if ( checkDecimalNumbers && 1 < newvalue.replace( decimalRegex, '' ).length ) {
|
|
||||||
newvalue = newvalue.replace( decimalRegex, '' );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( value !== newvalue ) {
|
|
||||||
$( document.body ).triggerHandler( 'wc_add_error_tip', [ $( this ), error ] );
|
|
||||||
} else {
|
|
||||||
$( document.body ).triggerHandler( 'wc_remove_error_tip', [ $( this ), error ] );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
.on( 'change', '#_sale_price.wc_input_price[type=text], .wc_input_price[name^=variable_sale_price]', function() {
|
|
||||||
var sale_price_field = $( this ), regular_price_field;
|
|
||||||
|
|
||||||
if ( sale_price_field.attr( 'name' ).indexOf( 'variable' ) !== -1 ) {
|
|
||||||
regular_price_field = sale_price_field
|
|
||||||
.parents( '.variable_pricing' )
|
|
||||||
.find( '.wc_input_price[name^=variable_regular_price]' );
|
|
||||||
} else {
|
|
||||||
regular_price_field = $( '#_regular_price' );
|
|
||||||
}
|
|
||||||
|
|
||||||
var sale_price = parseFloat(
|
|
||||||
window.accounting.unformat( sale_price_field.val(), woocommerce_admin.mon_decimal_point )
|
|
||||||
);
|
|
||||||
var regular_price = parseFloat(
|
|
||||||
window.accounting.unformat( regular_price_field.val(), woocommerce_admin.mon_decimal_point )
|
|
||||||
);
|
|
||||||
|
|
||||||
if ( sale_price >= regular_price ) {
|
|
||||||
$( this ).val( '' );
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
.on( 'keyup', '#_sale_price.wc_input_price[type=text], .wc_input_price[name^=variable_sale_price]', function() {
|
|
||||||
var sale_price_field = $( this ), regular_price_field;
|
|
||||||
|
|
||||||
if ( sale_price_field.attr( 'name' ).indexOf( 'variable' ) !== -1 ) {
|
|
||||||
regular_price_field = sale_price_field
|
|
||||||
.parents( '.variable_pricing' )
|
|
||||||
.find( '.wc_input_price[name^=variable_regular_price]' );
|
|
||||||
} else {
|
|
||||||
regular_price_field = $( '#_regular_price' );
|
|
||||||
}
|
|
||||||
|
|
||||||
var sale_price = parseFloat(
|
|
||||||
window.accounting.unformat( sale_price_field.val(), woocommerce_admin.mon_decimal_point )
|
|
||||||
);
|
|
||||||
var regular_price = parseFloat(
|
|
||||||
window.accounting.unformat( regular_price_field.val(), woocommerce_admin.mon_decimal_point )
|
|
||||||
);
|
|
||||||
|
|
||||||
if ( sale_price >= regular_price ) {
|
|
||||||
$( document.body ).triggerHandler( 'wc_add_error_tip', [ $(this), 'i18n_sale_less_than_regular_error' ] );
|
|
||||||
} else {
|
|
||||||
$( document.body ).triggerHandler( 'wc_remove_error_tip', [ $(this), 'i18n_sale_less_than_regular_error' ] );
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
.on( 'init_tooltips', function() {
|
|
||||||
|
|
||||||
$( '.tips, .help_tip, .woocommerce-help-tip' ).tipTip( {
|
|
||||||
'attribute': 'data-tip',
|
|
||||||
'fadeIn': 50,
|
|
||||||
'fadeOut': 50,
|
|
||||||
'delay': 200,
|
|
||||||
'keepAlive': true
|
|
||||||
} );
|
|
||||||
|
|
||||||
$( '.column-wc_actions .wc-action-button' ).tipTip( {
|
|
||||||
'fadeIn': 50,
|
|
||||||
'fadeOut': 50,
|
|
||||||
'delay': 200
|
|
||||||
} );
|
|
||||||
|
|
||||||
// Add tiptip to parent element for widefat tables
|
|
||||||
$( '.parent-tips' ).each( function() {
|
|
||||||
$( this ).closest( 'a, th' ).attr( 'data-tip', $( this ).data( 'tip' ) ).tipTip( {
|
|
||||||
'attribute': 'data-tip',
|
|
||||||
'fadeIn': 50,
|
|
||||||
'fadeOut': 50,
|
|
||||||
'delay': 200,
|
|
||||||
'keepAlive': true
|
|
||||||
} ).css( 'cursor', 'help' );
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Tooltips
|
|
||||||
$( document.body ).trigger( 'init_tooltips' );
|
|
||||||
|
|
||||||
// wc_input_table tables
|
|
||||||
$( '.wc_input_table.sortable tbody' ).sortable({
|
|
||||||
items: 'tr',
|
|
||||||
cursor: 'move',
|
|
||||||
axis: 'y',
|
|
||||||
scrollSensitivity: 40,
|
|
||||||
forcePlaceholderSize: true,
|
|
||||||
helper: 'clone',
|
|
||||||
opacity: 0.65,
|
|
||||||
placeholder: 'wc-metabox-sortable-placeholder',
|
|
||||||
start: function( event, ui ) {
|
|
||||||
ui.item.css( 'background-color', '#f6f6f6' );
|
|
||||||
},
|
|
||||||
stop: function( event, ui ) {
|
|
||||||
ui.item.removeAttr( 'style' );
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// Focus on inputs within the table if clicked instead of trying to sort.
|
|
||||||
$( '.wc_input_table.sortable tbody input' ).on( 'click', function() {
|
|
||||||
$( this ).focus();
|
|
||||||
} );
|
|
||||||
|
|
||||||
$( '.wc_input_table .remove_rows' ).on( 'click', function() {
|
|
||||||
var $tbody = $( this ).closest( '.wc_input_table' ).find( 'tbody' );
|
|
||||||
if ( $tbody.find( 'tr.current' ).length > 0 ) {
|
|
||||||
var $current = $tbody.find( 'tr.current' );
|
|
||||||
$current.each( function() {
|
|
||||||
$( this ).remove();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
var controlled = false;
|
|
||||||
var shifted = false;
|
|
||||||
var hasFocus = false;
|
|
||||||
|
|
||||||
$( document.body ).on( 'keyup keydown', function( e ) {
|
|
||||||
shifted = e.shiftKey;
|
|
||||||
controlled = e.ctrlKey || e.metaKey;
|
|
||||||
});
|
|
||||||
|
|
||||||
$( '.wc_input_table' ).on( 'focus click', 'input', function( e ) {
|
|
||||||
var $this_table = $( this ).closest( 'table, tbody' );
|
|
||||||
var $this_row = $( this ).closest( 'tr' );
|
|
||||||
|
|
||||||
if ( ( e.type === 'focus' && hasFocus !== $this_row.index() ) || ( e.type === 'click' && $( this ).is( ':focus' ) ) ) {
|
|
||||||
hasFocus = $this_row.index();
|
|
||||||
|
|
||||||
if ( ! shifted && ! controlled ) {
|
|
||||||
$( 'tr', $this_table ).removeClass( 'current' ).removeClass( 'last_selected' );
|
|
||||||
$this_row.addClass( 'current' ).addClass( 'last_selected' );
|
|
||||||
} else if ( shifted ) {
|
|
||||||
$( 'tr', $this_table ).removeClass( 'current' );
|
|
||||||
$this_row.addClass( 'selected_now' ).addClass( 'current' );
|
|
||||||
|
|
||||||
if ( $( 'tr.last_selected', $this_table ).length > 0 ) {
|
|
||||||
if ( $this_row.index() > $( 'tr.last_selected', $this_table ).index() ) {
|
|
||||||
$( 'tr', $this_table )
|
|
||||||
.slice( $( 'tr.last_selected', $this_table ).index(), $this_row.index() )
|
|
||||||
.addClass( 'current' );
|
|
||||||
} else {
|
|
||||||
$( 'tr', $this_table )
|
|
||||||
.slice( $this_row.index(), $( 'tr.last_selected', $this_table ).index() + 1 )
|
|
||||||
.addClass( 'current' );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$( 'tr', $this_table ).removeClass( 'last_selected' );
|
|
||||||
$this_row.addClass( 'last_selected' );
|
|
||||||
} else {
|
|
||||||
$( 'tr', $this_table ).removeClass( 'last_selected' );
|
|
||||||
if ( controlled && $( this ).closest( 'tr' ).is( '.current' ) ) {
|
|
||||||
$this_row.removeClass( 'current' );
|
|
||||||
} else {
|
|
||||||
$this_row.addClass( 'current' ).addClass( 'last_selected' );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$( 'tr', $this_table ).removeClass( 'selected_now' );
|
|
||||||
}
|
|
||||||
}).on( 'blur', 'input', function() {
|
|
||||||
hasFocus = false;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Additional cost and Attribute term tables
|
|
||||||
$( '.woocommerce_page_wc-settings .shippingrows tbody tr:even, table.attributes-table tbody tr:nth-child(odd)' )
|
|
||||||
.addClass( 'alternate' );
|
|
||||||
|
|
||||||
// Show order items on orders page
|
|
||||||
$( document.body ).on( 'click', '.show_order_items', function() {
|
|
||||||
$( this ).closest( 'td' ).find( 'table' ).toggle();
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Select availability
|
|
||||||
$( 'select.availability' ).change( function() {
|
|
||||||
if ( $( this ).val() === 'all' ) {
|
|
||||||
$( this ).closest( 'tr' ).next( 'tr' ).hide();
|
|
||||||
} else {
|
|
||||||
$( this ).closest( 'tr' ).next( 'tr' ).show();
|
|
||||||
}
|
|
||||||
}).trigger( 'change' );
|
|
||||||
|
|
||||||
// Hidden options
|
|
||||||
$( '.hide_options_if_checked' ).each( function() {
|
|
||||||
$( this ).find( 'input:eq(0)' ).change( function() {
|
|
||||||
if ( $( this ).is( ':checked' ) ) {
|
|
||||||
$( this )
|
|
||||||
.closest( 'fieldset, tr' )
|
|
||||||
.nextUntil( '.hide_options_if_checked, .show_options_if_checked', '.hidden_option' )
|
|
||||||
.hide();
|
|
||||||
} else {
|
|
||||||
$( this )
|
|
||||||
.closest( 'fieldset, tr' )
|
|
||||||
.nextUntil( '.hide_options_if_checked, .show_options_if_checked', '.hidden_option' )
|
|
||||||
.show();
|
|
||||||
}
|
|
||||||
}).trigger( 'change' );
|
|
||||||
});
|
|
||||||
|
|
||||||
$( '.show_options_if_checked' ).each( function() {
|
|
||||||
$( this ).find( 'input:eq(0)' ).change( function() {
|
|
||||||
if ( $( this ).is( ':checked' ) ) {
|
|
||||||
$( this )
|
|
||||||
.closest( 'fieldset, tr' )
|
|
||||||
.nextUntil( '.hide_options_if_checked, .show_options_if_checked', '.hidden_option' )
|
|
||||||
.show();
|
|
||||||
} else {
|
|
||||||
$( this )
|
|
||||||
.closest( 'fieldset, tr' )
|
|
||||||
.nextUntil( '.hide_options_if_checked, .show_options_if_checked', '.hidden_option' )
|
|
||||||
.hide();
|
|
||||||
}
|
|
||||||
}).trigger( 'change' );
|
|
||||||
});
|
|
||||||
|
|
||||||
// Reviews.
|
|
||||||
$( 'input#woocommerce_enable_reviews' ).change(function() {
|
|
||||||
if ( $( this ).is( ':checked' ) ) {
|
|
||||||
$( '#woocommerce_enable_review_rating' ).closest( 'tr' ).show();
|
|
||||||
} else {
|
|
||||||
$( '#woocommerce_enable_review_rating' ).closest( 'tr' ).hide();
|
|
||||||
}
|
|
||||||
}).trigger( 'change' );
|
|
||||||
|
|
||||||
// Attribute term table
|
|
||||||
$( 'table.attributes-table tbody tr:nth-child(odd)' ).addClass( 'alternate' );
|
|
||||||
|
|
||||||
// Toggle gateway on/off.
|
|
||||||
$( '.wc_gateways' ).on( 'click', '.wc-payment-gateway-method-toggle-enabled', function() {
|
|
||||||
var $link = $( this ),
|
|
||||||
$row = $link.closest( 'tr' ),
|
|
||||||
$toggle = $link.find( '.woocommerce-input-toggle' );
|
|
||||||
|
|
||||||
var data = {
|
|
||||||
action: 'woocommerce_toggle_gateway_enabled',
|
|
||||||
security: woocommerce_admin.nonces.gateway_toggle,
|
|
||||||
gateway_id: $row.data( 'gateway_id' )
|
|
||||||
};
|
|
||||||
|
|
||||||
$toggle.addClass( 'woocommerce-input-toggle--loading' );
|
|
||||||
|
|
||||||
$.ajax( {
|
|
||||||
url: woocommerce_admin.ajax_url,
|
|
||||||
data: data,
|
|
||||||
dataType : 'json',
|
|
||||||
type : 'POST',
|
|
||||||
success: function( response ) {
|
|
||||||
if ( true === response.data ) {
|
|
||||||
$toggle.removeClass( 'woocommerce-input-toggle--enabled, woocommerce-input-toggle--disabled' );
|
|
||||||
$toggle.addClass( 'woocommerce-input-toggle--enabled' );
|
|
||||||
$toggle.removeClass( 'woocommerce-input-toggle--loading' );
|
|
||||||
} else if ( false === response.data ) {
|
|
||||||
$toggle.removeClass( 'woocommerce-input-toggle--enabled, woocommerce-input-toggle--disabled' );
|
|
||||||
$toggle.addClass( 'woocommerce-input-toggle--disabled' );
|
|
||||||
$toggle.removeClass( 'woocommerce-input-toggle--loading' );
|
|
||||||
} else if ( 'needs_setup' === response.data ) {
|
|
||||||
window.location.href = $link.attr( 'href' );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
$( '#wpbody' ).on( 'click', '#doaction, #doaction2', function() {
|
|
||||||
var action = $( this ).is( '#doaction' ) ? $( '#bulk-action-selector-top' ).val() : $( '#bulk-action-selector-bottom' ).val();
|
|
||||||
|
|
||||||
if ( 'remove_personal_data' === action ) {
|
|
||||||
return window.confirm( woocommerce_admin.i18n_remove_personal_data_notice );
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
})( jQuery, woocommerce_admin );
|
|