diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 000000000..0e1d28804 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,73 @@ +version: 2 +jobs: + build-lint-benchmark: + docker: + - image: circleci/node:14.4.0-browsers + steps: + - checkout + - restore_cache: + keys: + - cache-{{ .Branch }}-{{ checksum "package.json" }} + - run: + name: Install system dependencies + command: sudo apt-get install -y libpng-dev + - run: + name: Install dependencies + command: npm install + - save_cache: + key: cache-{{ .Branch }}-{{ checksum "package.json" }} + paths: + - ~/.npm + - ~/.cache + - run: + name: Build application + command: npm run build + - run: + name: Install Lighthouse tools + command: sudo npm install -g @lhci/cli + - run: + name: Lighthouse audit + command: npx lhci autorun --upload.target=temporary-public-storage + + cypress: + docker: + - image: cypress/base:10 + environment: + TERM: xterm + parallelism: 1 + steps: + - checkout + - restore_cache: + keys: + - cache-{{ .Branch }}-{{ checksum "package.json" }} + - run: + name: Npm CI + command: npm ci + - run: + command: npx cypress verify + - save_cache: + key: cache-{{ .Branch }}-{{ checksum "package.json" }} + paths: + - ~/.npm + - ~/.cache + - persist_to_workspace: + root: ~/ + paths: + - project + - .cache/Cypress + - attach_workspace: + at: ~/ + - run: + name: Running E2E tests + command: npm run test:e2e:run + - store_artifacts: + path: cypress/videos + - store_artifacts: + path: cypress/screenshots + +workflows: + version: 2 + qa: + jobs: + - build-lint-benchmark: + context: Lighthouse diff --git a/.eslintrc.json b/.eslintrc.json index 98db3877e..2e6c63326 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -7,7 +7,12 @@ "parserOptions": { "sourceType": "module" }, - "plugins": ["@typescript-eslint", "import", "local-rules"], + "plugins": [ + "@typescript-eslint", + "import", + "local-rules", + "simple-import-sort" + ], "rules": { "@typescript-eslint/adjacent-overload-signatures": "error", "@typescript-eslint/array-type": [ @@ -69,9 +74,9 @@ "eqeqeq": ["error", "smart"], "guard-for-in": "error", "id-blacklist": "off", - "import/no-extraneous-dependencies": "off", - "import/no-internal-modules": "off", - "import/order": "error", + "import/no-extraneous-dependencies": "off", // imports are handled by simple-import-sort/sort + "import/no-internal-modules": "off", // imports are handled by simple-import-sort/sort + "import/order": "off", // imports are handled by simple-import-sort/sort "linebreak-style": "off", "local-rules/named-styles": "error", "max-classes-per-file": "off", @@ -113,7 +118,6 @@ ], "no-debugger": "error", "no-duplicate-case": "error", - "no-duplicate-imports": "error", "no-empty": "error", "no-eval": "error", "no-extra-bind": "error", @@ -149,22 +153,13 @@ "prefer-object-spread": "error", "quote-props": "off", "radix": "error", + "simple-import-sort/sort": ["error"], + "sort-imports": "off", // imports are handled by simple-import-sort/sort "sort-keys": "warn", "space-before-function-paren": "off", "spaced-comment": "error", "use-isnan": "error", "valid-typeof": "off" - // "@typescript-eslint/tslint/config": [ - // "error", - // { - // "rules": { - // "jsdoc-format": [true, "check-multiline-start"], - // "no-reference-import": true, - // "object-literal-sort-keys": true, - // "prefer-conditional-expression": true - // } - // } - // ] }, "ignorePatterns": ["node_modules/", "**/types/**/*"] } diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 000000000..b9efc0d80 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,2 @@ +# Restrict Test Environment Deployment Workflows to be Approved by Cloud Team +.github/workflows/test-env* @mirumee/saleor-cloud \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 536ecfbc8..72b819862 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -17,6 +17,30 @@ about: Create a report to help us improve ### Screenshots +### Http request and response from inspector + + +``` +// insert request and response here +``` + +### Console output + + +``` +// insert console output here +``` + **System information** + Operating system: +- [ ] Windows +- [ ] Linux +- [ ] MacOS +- [ ] Other + Browser: +- [ ] Safari +- [ ] Chrome +- [ ] Edge +- [ ] Other diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 7135688da..9a5806962 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -18,5 +18,13 @@ greatly reduce the amount of work needed to review your work. --> 1. [ ] Translated strings are extracted. 1. [ ] Number of API calls is optimized. 1. [ ] The changes are tested. +1. [ ] Data-test are added for new elements. 1. [ ] Type definitions are up to date. 1. [ ] Changes are mentioned in the changelog. + +### Test environment config + + + +API_URI=https://master.staging.saleor.rocks/graphql/ diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml new file mode 100644 index 000000000..604b8ce84 --- /dev/null +++ b/.github/workflows/codeql-analysis.yml @@ -0,0 +1,54 @@ +name: "CodeQL" + +on: + push: + branches: [master, ] + pull_request: + # The branches below must be a subset of the branches above + branches: [master] + schedule: + - cron: '0 10 * * 5' + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + with: + # We must fetch at least the immediate parents so that if this is + # a pull request then we can checkout the head. + fetch-depth: 2 + + # If this run was triggered by a pull request event, then checkout + # the head of the pull request instead of the merge commit. + - run: git checkout HEAD^2 + if: ${{ github.event_name == 'pull_request' }} + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v1 + # Override language selection by uncommenting this and choosing your languages + # with: + # languages: go, javascript, csharp, python, cpp, java + + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v1 + + # â„šī¸ Command-line programs to run using the OS shell. + # 📚 https://git.io/JvXDl + + # âœī¸ If the Autobuild fails above, remove it and uncomment the following three lines + # and modify them (or add more) to build your code if your project + # uses a compiled language + + #- run: | + # make bootstrap + # make release + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v1 diff --git a/.github/workflows/test-env-cleanup.yml b/.github/workflows/test-env-cleanup.yml new file mode 100644 index 000000000..b4832c83b --- /dev/null +++ b/.github/workflows/test-env-cleanup.yml @@ -0,0 +1,37 @@ +name: TEST-ENV-CLEANUP +# Remove test instance for closed pull requests + +on: + pull_request: + types: [closed] + branches: ["*"] + +jobs: + cleanup: + runs-on: ubuntu-latest + steps: + - uses: rlespinasse/github-slug-action@2.0.0 + - name: Set domain + # Set test instance domain based on branch name slug + run: | + echo "::set-env name=domain::${{ env.GITHUB_HEAD_REF_SLUG_URL }}.dashboard.saleor.rocks" + + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v1 + with: + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + aws-region: ${{ secrets.AWS_DEFAULT_REGION }} + + - name: Remove S3 directory + run: aws s3 rm --recursive s3://${{ secrets.AWS_TEST_DEPLOYMENT_BUCKET }}/${{ env.domain }}/ + + - name: Invalidate cache + run: aws cloudfront create-invalidation --distribution-id ${{ secrets.AWS_TEST_CF_DIST_ID }} --paths "/${{ env.domain }}/*" + + - name: Mark deployment as deactivated + uses: bobheadxi/deployments@v0.4.2 + with: + step: deactivate-env + token: ${{ secrets.GITHUB_TOKEN }} + env: ${{ env.GITHUB_HEAD_REF_SLUG_URL }} diff --git a/.github/workflows/test-env-deploy.yml b/.github/workflows/test-env-deploy.yml new file mode 100644 index 000000000..8e095ff5e --- /dev/null +++ b/.github/workflows/test-env-deploy.yml @@ -0,0 +1,114 @@ +name: TEST-ENV-DEPLOYMENT +# Build and deploy test instance for every pull request + +on: + pull_request: + # trigger on "edited" to update instance when configuration changes in PR description + types: [opened, reopened, synchronize] + branches: ["*"] + +jobs: + deploy: + if: github.event.pull_request.head.repo.full_name == 'mirumee/saleor-dashboard' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - uses: rlespinasse/github-slug-action@2.0.0 + + - name: Start deployment + uses: bobheadxi/deployments@v0.4.2 + id: deployment + with: + step: start + token: ${{ secrets.GITHUB_TOKEN }} + env: ${{ env.GITHUB_HEAD_REF_SLUG_URL }} + ref: ${{ github.head_ref }} + + - name: Start storybook deployment + uses: bobheadxi/deployments@v0.4.2 + id: storybook-deployment + with: + step: start + token: ${{ secrets.GITHUB_TOKEN }} + env: storybook ${{ env.GITHUB_HEAD_REF_SLUG_URL }} + ref: ${{ github.head_ref }} + + - name: Cache node modules + uses: actions/cache@v2 + env: + cache-name: cache-node-modules + with: + path: ~/.npm + key: ${{ runner.os }}-qa-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-qa-${{ env.cache-name }}- + ${{ runner.os }}-qa- + ${{ runner.os }}- + + - name: Install deps + run: | + npm ci + + - name: Get custom API_URI + id: api_uri + # Search for API_URI in PR description + env: + pull_request_body: ${{ github.event.pull_request.body }} + prefix: API_URI= + pattern: (http|https)://[a-zA-Z0-9.-]+/graphql/? + run: | + echo "::set-output name=custom_api_uri::$(echo $pull_request_body | grep -Eo "$prefix$pattern" | sed s/$prefix// | head -n 1)" + + - name: Run build + env: + # Use custom API_URI or the default one + API_URI: ${{ steps.api_uri.outputs.custom_api_uri || 'https://master.staging.saleor.rocks/graphql/' }} + APP_MOUNT_URI: / + STATIC_URL: / + run: | + npm run build + + - name: Run build storybook + run: | + npm run build-storybook + + - name: Set domain + # Set test instance domain based on branch name slug + run: | + echo "::set-env name=domain::${{ env.GITHUB_HEAD_REF_SLUG_URL }}.dashboard.saleor.rocks" + + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v1 + with: + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + aws-region: ${{ secrets.AWS_DEFAULT_REGION }} + + - name: Deploy to S3 + run: | + aws s3 sync ./build/dashboard s3://${{ secrets.AWS_TEST_DEPLOYMENT_BUCKET }}/${{ env.domain }} + aws s3 sync ./build/storybook s3://${{ secrets.AWS_TEST_DEPLOYMENT_BUCKET }}/${{ env.domain }}/storybook + + - name: Invalidate cache + run: aws cloudfront create-invalidation --distribution-id ${{ secrets.AWS_TEST_CF_DIST_ID }} --paths "/${{ env.domain }}/*" + + - name: Update deployment status + uses: bobheadxi/deployments@v0.4.2 + if: always() + with: + step: finish + token: ${{ secrets.GITHUB_TOKEN }} + status: ${{ job.status }} + env_url: https://${{ env.domain }}/ + deployment_id: ${{ steps.deployment.outputs.deployment_id }} + + - name: Update storybook deployment status + uses: bobheadxi/deployments@v0.4.2 + if: always() + with: + step: finish + token: ${{ secrets.GITHUB_TOKEN }} + status: ${{ job.status }} + env_url: https://${{ env.domain }}/storybook/index.html + deployment_id: ${{ steps.storybook-deployment.outputs.deployment_id }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 000000000..e01508e62 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,122 @@ +name: QA + +on: + pull_request: + branches: ["*"] + +jobs: + check-lock: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Validate lock file + run: | + npx lockfile-lint --path package-lock.json --allowed-hosts npm yarn + + tsc-and-linters: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Cache node modules + uses: actions/cache@v2 + env: + cache-name: cache-node-modules + with: + # npm cache files are stored in `~/.npm` on Linux/macOS + path: ~/.npm + key: ${{ runner.os }}-qa-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-qa-${{ env.cache-name }}- + ${{ runner.os }}-qa- + ${{ runner.os }}- + + - name: Install deps + run: | + npm ci + + - name: Run tsc + run: | + npm run check-types + + - name: Run lint + run: | + npm run lint + git diff --exit-code ./src + + jest-tests: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Cache node modules + uses: actions/cache@v2 + env: + cache-name: cache-node-modules + with: + # npm cache files are stored in `~/.npm` on Linux/macOS + path: ~/.npm + key: ${{ runner.os }}-qa-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-qa-${{ env.cache-name }}- + ${{ runner.os }}-qa- + ${{ runner.os }}- + + - name: Install deps + run: | + npm ci + + - name: Run jest + run: | + npm run test + + cypress-run: + runs-on: ubuntu-16.04 + steps: + - name: Checkout + uses: actions/checkout@v1 + - name: Cypress run + uses: cypress-io/github-action@v2 + env: + API_URI: ${{ secrets.API_URI }} + APP_MOUNT_URI: ${{ secrets.APP_MOUNT_URI }} + CYPRESS_USER_NAME: ${{ secrets.CYPRESS_USER_NAME }} + CYPRESS_USER_PASSWORD: ${{ secrets.CYPRESS_USER_PASSWORD }} + with: + build: npm run build + start: npx http-server -a localhost -p 9000 build/dashboard + wait-on: http://localhost:9000/ + wait-on-timeout: 120 + - uses: actions/upload-artifact@v1 + if: always() + with: + name: cypress-videos + path: cypress/videos + + translation-messages: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Cache node modules + uses: actions/cache@v2 + env: + cache-name: cache-node-modules + with: + # npm cache files are stored in `~/.npm` on Linux/macOS + path: ~/.npm + key: ${{ runner.os }}-qa-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-qa-${{ env.cache-name }}- + ${{ runner.os }}-qa- + ${{ runner.os }}- + + - name: Install deps + run: | + npm ci + + - name: Check message extraction + run: | + npm run extract-messages + git diff --exit-code ./locale diff --git a/.gitignore b/.gitignore index f5c4f1375..bc66b4afe 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ !.npmrc !.plop !.prettierignore +!.prettierrc !.pylintrc !.travis* !.testcafe diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 000000000..1f5e5d140 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,4 @@ +{ + "arrowParens": "avoid", + "trailingComma": "none" +} diff --git a/.testcafe/Data/systemData.js b/.testcafe/Data/systemData.js deleted file mode 100644 index 3d5df45dd..000000000 --- a/.testcafe/Data/systemData.js +++ /dev/null @@ -1 +0,0 @@ -export const MAIN_PAGE_URL = "http://localhost:9000/"; diff --git a/.testcafe/Data/userData.js b/.testcafe/Data/userData.js deleted file mode 100644 index a3d54f7d0..000000000 --- a/.testcafe/Data/userData.js +++ /dev/null @@ -1,2 +0,0 @@ -export const DEFAULT_USER_EMAIL = "admin@example.com"; -export const DEFAULT_USER_PASSWORD = "admin"; diff --git a/.testcafe/Models/homePageModel.js b/.testcafe/Models/homePageModel.js deleted file mode 100644 index 8e400c7e6..000000000 --- a/.testcafe/Models/homePageModel.js +++ /dev/null @@ -1,11 +0,0 @@ -import { Selector, t } from "testcafe"; - -export default class HomePage { - constructor() { - this.header = Selector('[data-tc="home-header"]'); - this.catalogMenu = Selector('[data-tc="Catalog"]'); - this.productsSubMenu = Selector( - '[data-tc="catalogue"]>[aria-label="products"]' - ); - } -} diff --git a/.testcafe/Models/loginPageModel.js b/.testcafe/Models/loginPageModel.js deleted file mode 100644 index 5447a6fdb..000000000 --- a/.testcafe/Models/loginPageModel.js +++ /dev/null @@ -1,16 +0,0 @@ -import { Selector, t } from "testcafe"; - -export default class LoginPage { - constructor() { - this.email = Selector('[data-tc="email"]'); - this.password = Selector('[data-tc="password"]'); - this.submitButton = Selector('[data-tc="submit"]'); - } - - async performLogin(putEmail, putPassword) { - await t - .typeText(this.email, putEmail) - .typeText(this.password, putPassword) - .click(this.submitButton); - } -} diff --git a/.testcafe/Tests/loginPageTests.js b/.testcafe/Tests/loginPageTests.js deleted file mode 100644 index 9f612dd4f..000000000 --- a/.testcafe/Tests/loginPageTests.js +++ /dev/null @@ -1,7 +0,0 @@ -import * as verifier from "../Verifications/loginPageVerifications"; -import { MAIN_PAGE_URL } from "../Data/systemData"; - -fixture`Login Tests`.page(MAIN_PAGE_URL); - -verifier.verifyEmailAndPasswordDisplayed(); -verifier.verifyIfUserCanLogin(); diff --git a/.testcafe/Verifications/loginPageVerifications.js b/.testcafe/Verifications/loginPageVerifications.js deleted file mode 100644 index 73c32c821..000000000 --- a/.testcafe/Verifications/loginPageVerifications.js +++ /dev/null @@ -1,20 +0,0 @@ -import LoginPage from "../Models/loginPageModel"; -import HomePage from "../Models/homePageModel"; -import { DEFAULT_USER_EMAIL, DEFAULT_USER_PASSWORD } from "../Data/userData"; - -const loginPage = new LoginPage(); -const homePage = new HomePage(); - -export function verifyEmailAndPasswordDisplayed() { - test("Verify that Email and Password are displayed", async t => { - await t.expect(loginPage.email.exists).ok(); - await t.expect(loginPage.password.exists).ok(); - }); -} - -export function verifyIfUserCanLogin() { - test("PerformLogin", async t => { - await loginPage.performLogin(DEFAULT_USER_EMAIL, DEFAULT_USER_PASSWORD); - await t.expect(homePage.header.exists).ok(); - }); -} diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index a80a62b15..000000000 --- a/.travis.yml +++ /dev/null @@ -1,23 +0,0 @@ -dist: xenial -language: node_js -sudo: false - -node_js: - - "12.12" - -branches: - only: - - master - - /next\/.*/ - -script: - - npm run build - - npm test -- --ci --coverage - -env: - global: - - APP_MOUNT_URI="/" - - API_URI="/graphql/" - -after_success: - - codecov diff --git a/.travis/check-strict-null-errors.snapshot b/.travis/check-strict-null-errors.snapshot deleted file mode 100644 index c35b716c6..000000000 --- a/.travis/check-strict-null-errors.snapshot +++ /dev/null @@ -1,2836 +0,0 @@ -src/attributes/components/AttributeList/AttributeList.tsx(102,35): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/attributes/components/AttributeList/AttributeList.tsx(114,35): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/attributes/components/AttributeList/AttributeList.tsx(128,35): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/attributes/components/AttributeList/AttributeList.tsx(143,35): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/attributes/components/AttributeList/AttributeList.tsx(158,35): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/attributes/components/AttributeList/AttributeList.tsx(197,41): error TS2532: Object is possibly 'undefined'. -src/attributes/components/AttributeList/AttributeList.tsx(199,31): error TS2532: Object is possibly 'undefined'. -src/attributes/components/AttributeList/AttributeList.tsx(207,44): error TS2532: Object is possibly 'undefined'. -src/attributes/components/AttributeList/AttributeList.tsx(219,48): error TS2532: Object is possibly 'undefined'. -src/attributes/components/AttributeList/AttributeList.tsx(231,27): error TS2532: Object is possibly 'undefined'. -src/attributes/components/AttributeList/AttributeList.tsx(244,27): error TS2532: Object is possibly 'undefined'. -src/attributes/components/AttributePage/AttributePage.tsx(67,9): error TS2322: Type '{ availableInGrid: boolean; filterableInDashboard: boolean; filterableInStorefront: boolean; inputType: AttributeInputTypeEnum | null; name: string | null; slug: string | null; storefrontSearchPosition: string; valueRequired: boolean; visibleInStorefront: boolean; }' is not assignable to type 'AttributePageFormData'. -src/attributes/components/AttributePage/AttributePage.tsx(118,13): error TS2322: Type 'string | null | undefined' is not assignable to type 'string | undefined'. -src/attributes/components/AttributeValueEditDialog/AttributeValueEditDialog.tsx(45,5): error TS2322: Type 'string | null' is not assignable to type 'string'. -src/attributes/components/AttributeValueEditDialog/AttributeValueEditDialog.tsx(45,23): error TS2531: Object is possibly 'null'. -src/attributes/components/AttributeValues/AttributeValues.tsx(113,34): error TS2532: Object is possibly 'undefined'. -src/attributes/components/AttributeValues/AttributeValues.tsx(117,32): error TS2532: Object is possibly 'undefined'. -src/attributes/components/AttributeValues/AttributeValues.tsx(117,46): error TS2532: Object is possibly 'undefined'. -src/attributes/components/AttributeValues/AttributeValues.tsx(120,32): error TS2532: Object is possibly 'undefined'. -src/attributes/components/AttributeValues/AttributeValues.tsx(120,46): error TS2532: Object is possibly 'undefined'. -src/attributes/components/AttributeValues/AttributeValues.tsx(125,66): error TS2532: Object is possibly 'undefined'. -src/attributes/views/AttributeCreate/AttributeCreate.tsx(61,29): error TS2538: Type 'undefined' cannot be used as an index type. -src/attributes/views/AttributeCreate/AttributeCreate.tsx(65,9): error TS2531: Object is possibly 'null'. -src/attributes/views/AttributeCreate/AttributeCreate.tsx(65,9): error TS2531: Object is possibly 'null'. -src/attributes/views/AttributeCreate/AttributeCreate.tsx(71,29): error TS2531: Object is possibly 'null'. -src/attributes/views/AttributeCreate/AttributeCreate.tsx(71,29): error TS2531: Object is possibly 'null'. -src/attributes/views/AttributeCreate/AttributeCreate.tsx(91,46): error TS2345: Argument of type 'number | undefined' is not assignable to parameter of type 'number'. -src/attributes/views/AttributeCreate/AttributeCreate.tsx(126,13): error TS2322: Type 'AttributeCreate_attributeCreate_errors[] | null' is not assignable to type 'UserError[]'. -src/attributes/views/AttributeCreate/AttributeCreate.tsx(127,21): error TS2532: Object is possibly 'undefined'. -src/attributes/views/AttributeCreate/AttributeCreate.tsx(127,21): error TS2531: Object is possibly 'null'. -src/attributes/views/AttributeCreate/AttributeCreate.tsx(131,13): error TS2322: Type 'undefined' is not assignable to type '() => void'. -src/attributes/views/AttributeCreate/AttributeCreate.tsx(183,17): error TS2322: Type 'undefined' is not assignable to type 'string'. -src/attributes/views/AttributeCreate/AttributeCreate.tsx(185,42): error TS2538: Type 'undefined' cannot be used as an index type. -src/attributes/views/AttributeCreate/AttributeCreate.tsx(191,52): error TS2538: Type 'undefined' cannot be used as an index type. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(53,9): error TS2531: Object is possibly 'null'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(53,9): error TS2531: Object is possibly 'null'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(63,9): error TS2531: Object is possibly 'null'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(63,9): error TS2531: Object is possibly 'null'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(74,9): error TS2531: Object is possibly 'null'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(74,9): error TS2531: Object is possibly 'null'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(79,9): error TS2531: Object is possibly 'null'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(79,9): error TS2531: Object is possibly 'null'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(85,9): error TS2531: Object is possibly 'null'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(85,9): error TS2531: Object is possibly 'null'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(96,9): error TS2531: Object is possibly 'null'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(96,9): error TS2531: Object is possibly 'null'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(98,9): error TS2322: Type 'string | null' is not assignable to type 'string'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(98,15): error TS2531: Object is possibly 'null'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(98,15): error TS2531: Object is possibly 'null'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(128,57): error TS2345: Argument of type '{ optimisticResponse: { attributeReorderValues: { __typename: "AttributeReorderValues"; attribute: { values: any; } | { values: any; __typename: "Attribute"; id: string; name: string | null; ... 7 more ...; valueRequired: boolean; }; errors: never[]; }; }; variables: { ...; }; }' is not assignable to parameter of type 'MutationFunctionOptions'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(133,46): error TS2532: Object is possibly 'undefined'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(135,45): error TS2532: Object is possibly 'undefined'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(135,45): error TS2531: Object is possibly 'null'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(135,45): error TS2531: Object is possibly 'null'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(136,45): error TS2532: Object is possibly 'undefined'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(136,45): error TS2531: Object is possibly 'null'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(136,45): error TS2345: Argument of type '(AttributeDetails_attribute_values | null)[] | null' is not assignable to parameter of type 'List'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(147,45): error TS2532: Object is possibly 'undefined'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(147,45): error TS2531: Object is possibly 'null'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(147,45): error TS2531: Object is possibly 'null'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(147,45): error TS2531: Object is possibly 'null'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(156,39): error TS2322: Type 'AttributeDetails_attribute | null | undefined' is not assignable to type 'AttributeDetailsFragment | null'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(156,62): error TS2532: Object is possibly 'undefined'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(158,39): error TS2322: Type 'AttributeUpdate_attributeUpdate_errors[] | null' is not assignable to type 'UserError[]'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(160,43): error TS2532: Object is possibly 'undefined'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(160,43): error TS2531: Object is possibly 'null'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(202,39): error TS2322: Type '(AttributeDetails_attribute_values | null)[] | null | undefined' is not assignable to type 'AttributeDetailsFragment_values[]'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(203,47): error TS2532: Object is possibly 'undefined'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(203,47): error TS2531: Object is possibly 'null'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(208,39): error TS2322: Type 'string | null' is not assignable to type 'string'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(209,47): error TS2532: Object is possibly 'undefined'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(209,47): error TS2531: Object is possibly 'null'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(225,39): error TS2322: Type 'string | null' is not assignable to type 'string'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(226,47): error TS2532: Object is possibly 'undefined'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(226,47): error TS2531: Object is possibly 'null'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(230,39): error TS2322: Type 'string | null' is not assignable to type 'string'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(232,43): error TS2532: Object is possibly 'undefined'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(232,43): error TS2531: Object is possibly 'null'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(232,43): error TS2531: Object is possibly 'null'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(232,43): error TS2533: Object is possibly 'null' or 'undefined'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(233,68): error TS2531: Object is possibly 'null'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(243,62): error TS2345: Argument of type '{ variables: { id: string | undefined; }; }' is not assignable to parameter of type 'MutationFunctionOptions'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(256,39): error TS2322: Type 'AttributeValueCreate_attributeValueCreate_errors[] | null' is not assignable to type 'UserError[]'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(258,43): error TS2532: Object is possibly 'undefined'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(258,43): error TS2531: Object is possibly 'null'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(274,39): error TS2322: Type 'AttributeDetails_attribute_values | null | undefined' is not assignable to type 'AttributeDetails_attribute_values | null'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(275,41): error TS2532: Object is possibly 'undefined'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(275,41): error TS2531: Object is possibly 'null'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(275,41): error TS2531: Object is possibly 'null'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(276,66): error TS2531: Object is possibly 'null'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(283,39): error TS2322: Type 'AttributeValueUpdate_attributeValueUpdate_errors[] | null' is not assignable to type 'UserError[]'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(285,43): error TS2532: Object is possibly 'undefined'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(285,43): error TS2531: Object is possibly 'null'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(294,49): error TS2532: Object is possibly 'undefined'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(294,49): error TS2531: Object is possibly 'null'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(294,49): error TS2531: Object is possibly 'null'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(294,49): error TS2533: Object is possibly 'null' or 'undefined'. -src/attributes/views/AttributeDetails/AttributeDetails.tsx(295,70): error TS2531: Object is possibly 'null'. -src/attributes/views/AttributeList/AttributeList.tsx(95,5): error TS2322: Type '(params?: AttributeListUrlQueryParams | undefined) => string' is not assignable to type 'CreateUrl'. -src/attributes/views/AttributeList/AttributeList.tsx(123,5): error TS2345: Argument of type 'AttributeList_attributes_pageInfo | undefined' is not assignable to parameter of type 'PageInfo'. -src/attributes/views/AttributeList/AttributeList.tsx(123,17): error TS2532: Object is possibly 'undefined'. -src/attributes/views/AttributeList/AttributeList.tsx(123,17): error TS2531: Object is possibly 'null'. -src/attributes/views/AttributeList/AttributeList.tsx(129,9): error TS2531: Object is possibly 'null'. -src/attributes/views/AttributeList/AttributeList.tsx(129,9): error TS2531: Object is possibly 'null'. -src/attributes/views/AttributeList/AttributeList.tsx(143,38): error TS2571: Object is of type 'unknown'. -src/attributes/views/AttributeList/AttributeList.tsx(150,13): error TS2322: Type 'AttributeList_attributes_edges_node[] | undefined' is not assignable to type 'AttributeList_attributes_edges_node[]'. -src/attributes/views/AttributeList/AttributeList.tsx(151,15): error TS2532: Object is possibly 'undefined'. -src/attributes/views/AttributeList/AttributeList.tsx(151,15): error TS2531: Object is possibly 'null'. -src/attributes/views/AttributeList/AttributeList.tsx(192,13): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. -src/attributes/views/AttributeList/AttributeList.tsx(193,57): error TS2532: Object is possibly 'undefined'. -src/attributes/views/AttributeList/AttributeList.tsx(196,35): error TS2345: Argument of type '{ variables: { ids: string[] | undefined; }; }' is not assignable to parameter of type 'MutationFunctionOptions'. -src/attributes/views/AttributeList/AttributeList.tsx(199,13): error TS2322: Type 'number | undefined' is not assignable to type 'number'. -src/attributes/views/AttributeList/AttributeList.tsx(199,35): error TS2532: Object is possibly 'undefined'. -src/attributes/views/AttributeList/filters.ts(27,39): error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'. -src/attributes/views/AttributeList/filters.ts(31,39): error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'. -src/attributes/views/AttributeList/filters.ts(35,39): error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'. -src/attributes/views/AttributeList/filters.ts(39,39): error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'. -src/attributes/views/AttributeList/filters.ts(43,39): error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'. -src/attributes/views/AttributeList/filters.ts(47,39): error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'. -src/attributes/views/AttributeList/sort.ts(20,7): error TS2322: Type 'undefined' is not assignable to type 'AttributeSortField'. -src/auth/AuthProvider.tsx(71,41): error TS2322: Type 'undefined' is not assignable to type 'User'. -src/auth/AuthProvider.tsx(83,20): error TS2531: Object is possibly 'null'. -src/auth/AuthProvider.tsx(86,21): error TS2345: Argument of type '{ user: TokenAuth_tokenCreate_user | null; }' is not assignable to parameter of type 'AuthProviderState | ((prevState: Readonly, props: Readonly) => AuthProviderState | ... 1 more ... | null) | Pick<...> | null'. -src/auth/AuthProvider.tsx(89,11): error TS2531: Object is possibly 'null'. -src/auth/AuthProvider.tsx(89,11): error TS2345: Argument of type 'string | null' is not assignable to parameter of type 'string'. -src/auth/AuthProvider.tsx(94,23): error TS2532: Object is possibly 'undefined'. -src/auth/AuthProvider.tsx(97,34): error TS2532: Object is possibly 'undefined'. -src/auth/AuthProvider.tsx(97,34): error TS2531: Object is possibly 'null'. -src/auth/AuthProvider.tsx(120,22): error TS2532: Object is possibly 'undefined'. -src/auth/AuthProvider.tsx(120,22): error TS2531: Object is possibly 'null'. -src/auth/AuthProvider.tsx(121,25): error TS2532: Object is possibly 'undefined'. -src/auth/AuthProvider.tsx(121,25): error TS2531: Object is possibly 'null'. -src/auth/AuthProvider.tsx(121,25): error TS2345: Argument of type 'TokenAuth_tokenCreate_user | null' is not assignable to parameter of type 'User'. -src/auth/AuthProvider.tsx(132,19): error TS2345: Argument of type '{ user: undefined; }' is not assignable to parameter of type 'AuthProviderState | ((prevState: Readonly, props: Readonly) => AuthProviderState | ... 1 more ... | null) | Pick<...> | null'. -src/auth/AuthProvider.tsx(133,9): error TS2774: This condition will always return true since the function is always defined. Did you mean to call it instead? -src/auth/components/ResetPasswordPage/ResetPasswordPage.stories.tsx(11,3): error TS2322: Type 'undefined' is not assignable to type 'string'. -src/auth/components/SectionRoute.tsx(17,11): error TS2339: Property 'user' does not exist on type 'unknown'. -src/auth/index.tsx(27,3): error TS2322: Type 'undefined' is not assignable to type '(username: string, password: string) => void'. -src/auth/index.tsx(28,3): error TS2322: Type 'undefined' is not assignable to type '(token: string, user: User) => void'. -src/auth/index.tsx(29,3): error TS2322: Type 'undefined' is not assignable to type '() => void'. -src/auth/misc.ts(5,3): error TS2531: Object is possibly 'null'. -src/auth/misc.ts(5,32): error TS2531: Object is possibly 'null'. -src/auth/views/Login.tsx(10,11): error TS2339: Property 'login' does not exist on type 'unknown'. -src/auth/views/Login.tsx(10,18): error TS2339: Property 'user' does not exist on type 'unknown'. -src/auth/views/Login.tsx(10,24): error TS2339: Property 'tokenAuthLoading' does not exist on type 'unknown'. -src/auth/views/NewPassword.tsx(16,11): error TS2339: Property 'loginByToken' does not exist on type 'unknown'. -src/auth/views/NewPassword.tsx(21,9): error TS2531: Object is possibly 'null'. -src/auth/views/NewPassword.tsx(22,20): error TS2531: Object is possibly 'null'. -src/auth/views/NewPassword.tsx(22,44): error TS2531: Object is possibly 'null'. -src/auth/views/ResetPassword.tsx(21,9): error TS2531: Object is possibly 'null'. -src/auth/views/ResetPassword.tsx(21,9): error TS2531: Object is possibly 'null'. -src/auth/views/ResetPassword.tsx(24,11): error TS2531: Object is possibly 'null'. -src/auth/views/ResetPassword.tsx(24,11): error TS2531: Object is possibly 'null'. -src/auth/views/ResetPassword.tsx(55,13): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/categories/components/CategoryBackground/CategoryBackground.tsx(59,46): error TS2532: Object is possibly 'undefined'. -src/categories/components/CategoryBackground/CategoryBackground.tsx(80,48): error TS2531: Object is possibly 'null'. -src/categories/components/CategoryBackground/CategoryBackground.tsx(82,15): error TS2322: Type 'MutableRefObject' is not assignable to type 'string | ((instance: HTMLInputElement | null) => void) | RefObject | null | undefined'. -src/categories/components/CategoryBackground/CategoryBackground.tsx(100,22): error TS2322: Type 'CategoryDetails_category_backgroundImage' is not assignable to type '{ alt?: string | undefined; url: string; }'. -src/categories/components/CategoryDetailsForm/CategoryDetailsForm.tsx(65,43): error TS2532: Object is possibly 'undefined'. -src/categories/components/CategoryList/CategoryList.tsx(89,9): error TS2322: Type 'CategoryFragment[] | undefined' is not assignable to type 'Node[]'. -src/categories/components/CategoryList/CategoryList.tsx(96,35): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/categories/components/CategoryList/CategoryList.tsx(109,35): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/categories/components/CategoryList/CategoryList.tsx(126,35): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/categories/components/CategoryList/CategoryList.tsx(158,11): error TS2345: Argument of type 'CategoryFragment[] | undefined' is not assignable to parameter of type 'CategoryFragment[]'. -src/categories/components/CategoryProductList/CategoryProductList.tsx(173,46): error TS2532: Object is possibly 'undefined'. -src/categories/components/CategoryProductList/CategoryProductList.tsx(178,44): error TS2532: Object is possibly 'undefined'. -src/categories/components/CategoryProductList/CategoryProductList.tsx(178,44): error TS2531: Object is possibly 'null'. -src/categories/components/CategoryProductList/CategoryProductList.tsx(212,34): error TS2532: Object is possibly 'undefined'. -src/categories/components/CategoryProductList/CategoryProductList.tsx(213,33): error TS2532: Object is possibly 'undefined'. -src/categories/components/CategoryProductList/CategoryProductList.tsx(213,33): error TS2531: Object is possibly 'null'. -src/categories/components/CategoryProductList/CategoryProductList.tsx(214,33): error TS2532: Object is possibly 'undefined'. -src/categories/components/CategoryProductList/CategoryProductList.tsx(214,33): error TS2531: Object is possibly 'null'. -src/categories/components/CategoryProductList/CategoryProductList.tsx(215,30): error TS2322: Type 'CategoryDetails_category_products_edges_node_basePrice | null' is not assignable to type 'IMoney'. -src/categories/components/CategoryProductList/CategoryProductList.tsx(215,37): error TS2532: Object is possibly 'undefined'. -src/categories/components/CategoryUpdatePage/CategoryUpdatePage.tsx(102,9): error TS2322: Type '{ backgroundImageAlt: string | null; description: any; name: string; seoDescription: string; seoTitle: string; }' is not assignable to type 'FormData'. -src/categories/components/CategoryUpdatePage/CategoryUpdatePage.tsx(104,41): error TS2531: Object is possibly 'null'. -src/categories/components/CategoryUpdatePage/CategoryUpdatePage.tsx(137,13): error TS2322: Type 'CategoryDetails_category_backgroundImage | null | undefined' is not assignable to type 'CategoryDetails_category_backgroundImage'. -src/categories/components/CategoryUpdatePage/CategoryUpdatePage.tsx(203,17): error TS2322: Type 'undefined' is not assignable to type 'Partial<{ asc: boolean; sort: CategoryListUrlSortField; }>'. -src/categories/components/CategoryUpdatePage/CategoryUpdatePage.tsx(216,15): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/categories/index.tsx(48,5): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/categories/views/CategoryCreate.tsx(25,9): error TS2531: Object is possibly 'null'. -src/categories/views/CategoryCreate.tsx(25,9): error TS2531: Object is possibly 'null'. -src/categories/views/CategoryCreate.tsx(31,28): error TS2531: Object is possibly 'null'. -src/categories/views/CategoryCreate.tsx(31,28): error TS2531: Object is possibly 'null'. -src/categories/views/CategoryCreate.tsx(40,11): error TS2532: Object is possibly 'undefined'. -src/categories/views/CategoryCreate.tsx(40,11): error TS2531: Object is possibly 'null'. -src/categories/views/CategoryCreate.tsx(54,9): error TS2322: Type 'CategoryCreate_categoryCreate_errors[] | null' is not assignable to type 'UserError[]'. -src/categories/views/CategoryDetails.tsx(81,9): error TS2531: Object is possibly 'null'. -src/categories/views/CategoryDetails.tsx(81,9): error TS2531: Object is possibly 'null'. -src/categories/views/CategoryDetails.tsx(96,9): error TS2531: Object is possibly 'null'. -src/categories/views/CategoryDetails.tsx(96,9): error TS2531: Object is possibly 'null'. -src/categories/views/CategoryDetails.tsx(97,36): error TS2531: Object is possibly 'null'. -src/categories/views/CategoryDetails.tsx(97,36): error TS2531: Object is possibly 'null'. -src/categories/views/CategoryDetails.tsx(102,11): error TS2322: Type 'string | null' is not assignable to type 'string'. -src/categories/views/CategoryDetails.tsx(113,9): error TS2531: Object is possibly 'null'. -src/categories/views/CategoryDetails.tsx(113,9): error TS2531: Object is possibly 'null'. -src/categories/views/CategoryDetails.tsx(144,9): error TS2531: Object is possibly 'null'. -src/categories/views/CategoryDetails.tsx(144,9): error TS2531: Object is possibly 'null'. -src/categories/views/CategoryDetails.tsx(155,5): error TS2345: Argument of type 'CategoryDetails_category_children_pageInfo | undefined' is not assignable to parameter of type 'PageInfo'. -src/categories/views/CategoryDetails.tsx(156,21): error TS2532: Object is possibly 'undefined'. -src/categories/views/CategoryDetails.tsx(156,21): error TS2531: Object is possibly 'null'. -src/categories/views/CategoryDetails.tsx(156,21): error TS2531: Object is possibly 'null'. -src/categories/views/CategoryDetails.tsx(157,21): error TS2532: Object is possibly 'undefined'. -src/categories/views/CategoryDetails.tsx(157,21): error TS2531: Object is possibly 'null'. -src/categories/views/CategoryDetails.tsx(157,21): error TS2531: Object is possibly 'null'. -src/categories/views/CategoryDetails.tsx(164,20): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/categories/views/CategoryDetails.tsx(164,39): error TS2532: Object is possibly 'undefined'. -src/categories/views/CategoryDetails.tsx(164,39): error TS2531: Object is possibly 'null'. -src/categories/views/CategoryDetails.tsx(170,15): error TS2322: Type 'CategoryPageTab | undefined' is not assignable to type 'CategoryPageTab'. -src/categories/views/CategoryDetails.tsx(171,15): error TS2322: Type 'CategoryDetails_category | null | undefined' is not assignable to type 'CategoryDetails_category'. -src/categories/views/CategoryDetails.tsx(171,37): error TS2532: Object is possibly 'undefined'. -src/categories/views/CategoryDetails.tsx(173,15): error TS2322: Type 'CategoryUpdate_categoryUpdate_errors[] | null | undefined' is not assignable to type 'UserError[]'. -src/categories/views/CategoryDetails.tsx(173,35): error TS2532: Object is possibly 'undefined'. -src/categories/views/CategoryDetails.tsx(173,35): error TS2531: Object is possibly 'null'. -src/categories/views/CategoryDetails.tsx(179,39): error TS2532: Object is possibly 'undefined'. -src/categories/views/CategoryDetails.tsx(179,39): error TS2531: Object is possibly 'null'. -src/categories/views/CategoryDetails.tsx(179,39): error TS2531: Object is possibly 'null'. -src/categories/views/CategoryDetails.tsx(208,15): error TS2322: Type '{ hasNextPage: boolean; hasPreviousPage: boolean; endCursor: string; startCursor: string; } | undefined' is not assignable to type '{ hasNextPage: boolean; hasPreviousPage: boolean; }'. -src/categories/views/CategoryDetails.tsx(226,15): error TS2322: Type 'CategoryDetails_category_products_edges_node[] | undefined' is not assignable to type 'CategoryDetails_category_products_edges_node[]'. -src/categories/views/CategoryDetails.tsx(227,17): error TS2532: Object is possibly 'undefined'. -src/categories/views/CategoryDetails.tsx(227,17): error TS2531: Object is possibly 'null'. -src/categories/views/CategoryDetails.tsx(227,17): error TS2531: Object is possibly 'null'. -src/categories/views/CategoryDetails.tsx(230,15): error TS2322: Type 'CategoryDetails_category_children_edges_node[] | undefined' is not assignable to type 'CategoryDetails_category_children_edges_node[]'. -src/categories/views/CategoryDetails.tsx(231,17): error TS2532: Object is possibly 'undefined'. -src/categories/views/CategoryDetails.tsx(231,17): error TS2531: Object is possibly 'null'. -src/categories/views/CategoryDetails.tsx(231,17): error TS2531: Object is possibly 'null'. -src/categories/views/CategoryDetails.tsx(278,44): error TS2532: Object is possibly 'undefined'. -src/categories/views/CategoryDetails.tsx(278,44): error TS2531: Object is possibly 'null'. -src/categories/views/CategoryDetails.tsx(288,15): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. -src/categories/views/CategoryDetails.tsx(290,29): error TS2532: Object is possibly 'undefined'. -src/categories/views/CategoryDetails.tsx(295,36): error TS2345: Argument of type '{ variables: { ids: string[] | undefined; }; }' is not assignable to parameter of type 'MutationFunctionOptions'. -src/categories/views/CategoryDetails.tsx(309,42): error TS2532: Object is possibly 'undefined'. -src/categories/views/CategoryDetails.tsx(311,44): error TS2532: Object is possibly 'undefined'. -src/categories/views/CategoryDetails.tsx(325,35): error TS2345: Argument of type '{ variables: { ids: string[] | undefined; }; }' is not assignable to parameter of type 'MutationFunctionOptions'. -src/categories/views/CategoryDetails.tsx(339,42): error TS2532: Object is possibly 'undefined'. -src/categories/views/CategoryDetails.tsx(341,44): error TS2532: Object is possibly 'undefined'. -src/categories/views/CategoryList/CategoryList.tsx(121,5): error TS2345: Argument of type 'RootCategories_categories_pageInfo | undefined' is not assignable to parameter of type 'PageInfo'. -src/categories/views/CategoryList/CategoryList.tsx(121,17): error TS2532: Object is possibly 'undefined'. -src/categories/views/CategoryList/CategoryList.tsx(121,17): error TS2531: Object is possibly 'null'. -src/categories/views/CategoryList/CategoryList.tsx(127,9): error TS2531: Object is possibly 'null'. -src/categories/views/CategoryList/CategoryList.tsx(127,9): error TS2531: Object is possibly 'null'. -src/categories/views/CategoryList/CategoryList.tsx(147,17): error TS2532: Object is possibly 'undefined'. -src/categories/views/CategoryList/CategoryList.tsx(147,17): error TS2531: Object is possibly 'null'. -src/categories/views/CategoryList/CategoryList.tsx(197,30): error TS2345: Argument of type '{ variables: { ids: string[] | undefined; }; }' is not assignable to parameter of type 'MutationFunctionOptions'. -src/categories/views/CategoryList/CategoryList.tsx(214,36): error TS2532: Object is possibly 'undefined'. -src/categories/views/CategoryList/CategoryList.tsx(215,53): error TS2532: Object is possibly 'undefined'. -src/categories/views/CategoryList/sort.ts(16,7): error TS2322: Type 'undefined' is not assignable to type 'CategorySortField'. -src/collections/components/CollectionCreatePage/CollectionCreatePage.tsx(48,5): error TS2322: Type 'null' is not assignable to type 'string'. -src/collections/components/CollectionCreatePage/CollectionCreatePage.tsx(49,5): error TS2322: Type 'null' is not assignable to type 'string'. -src/collections/components/CollectionCreatePage/CollectionCreatePage.tsx(93,17): error TS2322: Type '{ __typename: string; alt: string; url: string; } | null' is not assignable to type 'CollectionDetails_collection_backgroundImage'. -src/collections/components/CollectionDetails/CollectionDetails.tsx(60,43): error TS2532: Object is possibly 'undefined'. -src/collections/components/CollectionDetailsPage/CollectionDetailsPage.tsx(70,41): error TS2531: Object is possibly 'null'. -src/collections/components/CollectionDetailsPage/CollectionDetailsPage.tsx(99,17): error TS2322: Type '{ backgroundImageAlt: string | null; description: any; isFeatured: boolean; isPublished: boolean; name: string; publicationDate: any; seoDescription: string | null; seoTitle: string | null; }' is not assignable to type '{ backgroundImageAlt: string; }'. -src/collections/components/CollectionDetailsPage/CollectionDetailsPage.tsx(100,17): error TS2322: Type 'CollectionDetails_collection_backgroundImage | null | undefined' is not assignable to type 'CollectionDetails_collection_backgroundImage'. -src/collections/components/CollectionDetailsPage/CollectionDetailsPage.tsx(113,17): error TS2322: Type 'string | null' is not assignable to type 'string | undefined'. -src/collections/components/CollectionDetailsPage/CollectionDetailsPage.tsx(120,17): error TS2322: Type 'string | null' is not assignable to type 'string'. -src/collections/components/CollectionDetailsPage/CollectionDetailsPage.tsx(121,17): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/collections/components/CollectionImage/CollectionImage.tsx(71,46): error TS2532: Object is possibly 'undefined'. -src/collections/components/CollectionImage/CollectionImage.tsx(92,48): error TS2531: Object is possibly 'null'. -src/collections/components/CollectionImage/CollectionImage.tsx(94,15): error TS2322: Type 'MutableRefObject' is not assignable to type 'string | ((instance: HTMLInputElement | null) => void) | RefObject | null | undefined'. -src/collections/components/CollectionImage/CollectionImage.tsx(112,22): error TS2322: Type 'CollectionDetails_collection_backgroundImage' is not assignable to type '{ alt?: string | undefined; url: string; }'. -src/collections/components/CollectionList/CollectionList.tsx(91,35): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/collections/components/CollectionList/CollectionList.tsx(103,35): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/collections/components/CollectionList/CollectionList.tsx(114,35): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/collections/components/CollectionList/CollectionList.tsx(154,41): error TS2532: Object is possibly 'undefined'. -src/collections/components/CollectionList/CollectionList.tsx(161,44): error TS2532: Object is possibly 'undefined'. -src/collections/components/CollectionList/CollectionList.tsx(165,49): error TS2532: Object is possibly 'undefined'. -src/collections/components/CollectionList/CollectionList.tsx(169,27): error TS2532: Object is possibly 'undefined'. -src/collections/components/CollectionList/CollectionList.tsx(169,27): error TS2531: Object is possibly 'null'. -src/collections/components/CollectionList/CollectionList.tsx(176,50): error TS2532: Object is possibly 'undefined'. -src/collections/components/CollectionList/CollectionList.tsx(181,33): error TS2532: Object is possibly 'undefined'. -src/collections/components/CollectionList/CollectionList.tsx(183,27): error TS2532: Object is possibly 'undefined'. -src/collections/components/CollectionProducts/CollectionProducts.tsx(122,11): error TS2322: Type 'CollectionDetails_collection_products_edges_node[] | undefined' is not assignable to type 'Node[]'. -src/collections/components/CollectionProducts/CollectionProducts.tsx(122,30): error TS2531: Object is possibly 'null'. -src/collections/components/CollectionProducts/CollectionProducts.tsx(152,15): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. -src/collections/components/CollectionProducts/CollectionProducts.tsx(152,40): error TS2532: Object is possibly 'undefined'. -src/collections/components/CollectionProducts/CollectionProducts.tsx(154,15): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. -src/collections/components/CollectionProducts/CollectionProducts.tsx(154,44): error TS2532: Object is possibly 'undefined'. -src/collections/components/CollectionProducts/CollectionProducts.tsx(161,13): error TS2345: Argument of type 'CollectionDetails_collection_products_edges_node[] | undefined' is not assignable to parameter of type 'CollectionDetails_collection_products_edges_node[]'. -src/collections/components/CollectionProducts/CollectionProducts.tsx(161,25): error TS2531: Object is possibly 'null'. -src/collections/views/CollectionCreate.tsx(20,9): error TS2531: Object is possibly 'null'. -src/collections/views/CollectionCreate.tsx(20,9): error TS2531: Object is possibly 'null'. -src/collections/views/CollectionCreate.tsx(26,30): error TS2531: Object is possibly 'null'. -src/collections/views/CollectionCreate.tsx(26,30): error TS2531: Object is possibly 'null'. -src/collections/views/CollectionCreate.tsx(28,36): error TS2531: Object is possibly 'null'. -src/collections/views/CollectionCreate.tsx(28,36): error TS2531: Object is possibly 'null'. -src/collections/views/CollectionCreate.tsx(34,11): error TS2322: Type 'string | null' is not assignable to type 'string'. -src/collections/views/CollectionCreate.tsx(50,13): error TS2322: Type 'CreateCollection_collectionCreate_errors[] | null' is not assignable to type 'UserError[]'. -src/collections/views/CollectionCreate.tsx(51,21): error TS2532: Object is possibly 'undefined'. -src/collections/views/CollectionCreate.tsx(51,21): error TS2531: Object is possibly 'null'. -src/collections/views/CollectionDetails.tsx(79,15): error TS2531: Object is possibly 'null'. -src/collections/views/CollectionDetails.tsx(79,15): error TS2531: Object is possibly 'null'. -src/collections/views/CollectionDetails.tsx(85,42): error TS2531: Object is possibly 'null'. -src/collections/views/CollectionDetails.tsx(85,42): error TS2531: Object is possibly 'null'. -src/collections/views/CollectionDetails.tsx(91,17): error TS2322: Type 'string | null' is not assignable to type 'string'. -src/collections/views/CollectionDetails.tsx(98,15): error TS2531: Object is possibly 'null'. -src/collections/views/CollectionDetails.tsx(98,15): error TS2531: Object is possibly 'null'. -src/collections/views/CollectionDetails.tsx(109,15): error TS2531: Object is possibly 'null'. -src/collections/views/CollectionDetails.tsx(109,15): error TS2531: Object is possibly 'null'. -src/collections/views/CollectionDetails.tsx(121,15): error TS2531: Object is possibly 'null'. -src/collections/views/CollectionDetails.tsx(121,15): error TS2531: Object is possibly 'null'. -src/collections/views/CollectionDetails.tsx(158,36): error TS2532: Object is possibly 'undefined'. -src/collections/views/CollectionDetails.tsx(158,36): error TS2531: Object is possibly 'null'. -src/collections/views/CollectionDetails.tsx(159,21): error TS2532: Object is possibly 'undefined'. -src/collections/views/CollectionDetails.tsx(159,21): error TS2531: Object is possibly 'null'. -src/collections/views/CollectionDetails.tsx(159,57): error TS2532: Object is possibly 'undefined'. -src/collections/views/CollectionDetails.tsx(159,57): error TS2531: Object is possibly 'null'. -src/collections/views/CollectionDetails.tsx(181,17): error TS2345: Argument of type 'CollectionUpdate_collectionUpdate_errors[] | null | undefined' is not assignable to parameter of type 'UserError[]'. -src/collections/views/CollectionDetails.tsx(181,29): error TS2532: Object is possibly 'undefined'. -src/collections/views/CollectionDetails.tsx(181,29): error TS2531: Object is possibly 'null'. -src/collections/views/CollectionDetails.tsx(184,21): error TS2532: Object is possibly 'undefined'. -src/collections/views/CollectionDetails.tsx(184,21): error TS2531: Object is possibly 'null'. -src/collections/views/CollectionDetails.tsx(189,21): error TS2532: Object is possibly 'undefined'. -src/collections/views/CollectionDetails.tsx(189,21): error TS2531: Object is possibly 'null'. -src/collections/views/CollectionDetails.tsx(195,17): error TS2345: Argument of type 'CollectionDetails_collection_products_pageInfo | undefined' is not assignable to parameter of type 'PageInfo'. -src/collections/views/CollectionDetails.tsx(195,29): error TS2532: Object is possibly 'undefined'. -src/collections/views/CollectionDetails.tsx(195,29): error TS2531: Object is possibly 'null'. -src/collections/views/CollectionDetails.tsx(195,29): error TS2531: Object is possibly 'null'. -src/collections/views/CollectionDetails.tsx(202,32): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/collections/views/CollectionDetails.tsx(202,51): error TS2532: Object is possibly 'undefined'. -src/collections/views/CollectionDetails.tsx(202,51): error TS2531: Object is possibly 'null'. -src/collections/views/CollectionDetails.tsx(207,21): error TS2322: Type 'CollectionDetails_collection | null | undefined' is not assignable to type 'CollectionDetails_collection'. -src/collections/views/CollectionDetails.tsx(207,45): error TS2532: Object is possibly 'undefined'. -src/collections/views/CollectionDetails.tsx(208,21): error TS2322: Type 'CollectionUpdate_collectionUpdate_errors[]' is not assignable to type 'UserError[]'. -src/collections/views/CollectionDetails.tsx(209,23): error TS2531: Object is possibly 'null'. -src/collections/views/CollectionDetails.tsx(213,25): error TS2532: Object is possibly 'undefined'. -src/collections/views/CollectionDetails.tsx(213,25): error TS2531: Object is possibly 'null'. -src/collections/views/CollectionDetails.tsx(213,25): error TS2531: Object is possibly 'null'. -src/collections/views/CollectionDetails.tsx(213,61): error TS2532: Object is possibly 'undefined'. -src/collections/views/CollectionDetails.tsx(213,61): error TS2531: Object is possibly 'null'. -src/collections/views/CollectionDetails.tsx(296,44): error TS2532: Object is possibly 'undefined'. -src/collections/views/CollectionDetails.tsx(296,44): error TS2531: Object is possibly 'null'. -src/collections/views/CollectionDetails.tsx(310,25): error TS2322: Type 'string[] | undefined' is not assignable to type '(string | null)[]'. -src/collections/views/CollectionDetails.tsx(323,48): error TS2532: Object is possibly 'undefined'. -src/collections/views/CollectionDetails.tsx(325,50): error TS2532: Object is possibly 'undefined'. -src/collections/views/CollectionList/CollectionList.tsx(101,5): error TS2322: Type '(params?: CollectionListUrlQueryParams | undefined) => string' is not assignable to type 'CreateUrl'. -src/collections/views/CollectionList/CollectionList.tsx(134,5): error TS2345: Argument of type 'CollectionList_collections_pageInfo | undefined' is not assignable to parameter of type 'PageInfo'. -src/collections/views/CollectionList/CollectionList.tsx(134,17): error TS2532: Object is possibly 'undefined'. -src/collections/views/CollectionList/CollectionList.tsx(134,17): error TS2531: Object is possibly 'null'. -src/collections/views/CollectionList/CollectionList.tsx(140,9): error TS2531: Object is possibly 'null'. -src/collections/views/CollectionList/CollectionList.tsx(140,9): error TS2531: Object is possibly 'null'. -src/collections/views/CollectionList/CollectionList.tsx(151,9): error TS2531: Object is possibly 'null'. -src/collections/views/CollectionList/CollectionList.tsx(151,9): error TS2531: Object is possibly 'null'. -src/collections/views/CollectionList/CollectionList.tsx(162,38): error TS2571: Object is of type 'unknown'. -src/collections/views/CollectionList/CollectionList.tsx(184,17): error TS2322: Type 'CollectionList_collections_edges_node[] | undefined' is not assignable to type 'CollectionList_collections_edges_node[]'. -src/collections/views/CollectionList/CollectionList.tsx(185,19): error TS2532: Object is possibly 'undefined'. -src/collections/views/CollectionList/CollectionList.tsx(185,19): error TS2531: Object is possibly 'null'. -src/collections/views/CollectionList/CollectionList.tsx(241,17): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. -src/collections/views/CollectionList/CollectionList.tsx(243,31): error TS2532: Object is possibly 'undefined'. -src/collections/views/CollectionList/CollectionList.tsx(248,41): error TS2345: Argument of type '{ variables: { ids: string[] | undefined; isPublished: true; }; }' is not assignable to parameter of type 'MutationFunctionOptions'. -src/collections/views/CollectionList/CollectionList.tsx(265,44): error TS2532: Object is possibly 'undefined'. -src/collections/views/CollectionList/CollectionList.tsx(267,46): error TS2532: Object is possibly 'undefined'. -src/collections/views/CollectionList/CollectionList.tsx(274,17): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. -src/collections/views/CollectionList/CollectionList.tsx(276,31): error TS2532: Object is possibly 'undefined'. -src/collections/views/CollectionList/CollectionList.tsx(281,41): error TS2345: Argument of type '{ variables: { ids: string[] | undefined; isPublished: false; }; }' is not assignable to parameter of type 'MutationFunctionOptions'. -src/collections/views/CollectionList/CollectionList.tsx(298,44): error TS2532: Object is possibly 'undefined'. -src/collections/views/CollectionList/CollectionList.tsx(300,46): error TS2532: Object is possibly 'undefined'. -src/collections/views/CollectionList/CollectionList.tsx(307,17): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. -src/collections/views/CollectionList/CollectionList.tsx(309,31): error TS2532: Object is possibly 'undefined'. -src/collections/views/CollectionList/CollectionList.tsx(314,40): error TS2345: Argument of type '{ variables: { ids: string[] | undefined; }; }' is not assignable to parameter of type 'MutationFunctionOptions'. -src/collections/views/CollectionList/CollectionList.tsx(330,44): error TS2532: Object is possibly 'undefined'. -src/collections/views/CollectionList/CollectionList.tsx(332,46): error TS2532: Object is possibly 'undefined'. -src/collections/views/CollectionList/filters.ts(30,7): error TS2322: Type 'CollectionPublished | undefined' is not assignable to type 'CollectionPublished'. -src/collections/views/CollectionList/sort.ts(16,7): error TS2322: Type 'undefined' is not assignable to type 'CollectionSortField'. -src/components/AppLayout/AppActionContext.tsx(4,3): error TS2345: Argument of type 'undefined' is not assignable to parameter of type 'RefObject'. -src/components/AppLayout/AppHeaderContext.tsx(4,3): error TS2345: Argument of type 'undefined' is not assignable to parameter of type 'RefObject'. -src/components/AppLayout/AppLayout.tsx(309,11): error TS2339: Property 'logout' does not exist on type 'unknown'. -src/components/AppLayout/AppLayout.tsx(309,19): error TS2339: Property 'user' does not exist on type 'unknown'. -src/components/AppLayout/AppLayout.tsx(353,9): error TS2322: Type 'null' is not assignable to type '"unhandled" | undefined'. -src/components/AppLayout/AppLayout.tsx(425,26): error TS2322: Type 'MutableRefObject' is not assignable to type 'string | ((instance: HTMLDivElement | null) => void) | RefObject | null | undefined'. -src/components/AppLayout/AppLayout.tsx(433,66): error TS2322: Type 'MutableRefObject' is not assignable to type 'string | ((instance: HTMLDivElement | null) => void) | RefObject | null | undefined'. -src/components/AppLayout/AppLayout.tsx(516,48): error TS2322: Type 'MutableRefObject' is not assignable to type 'string | ((instance: HTMLDivElement | null) => void) | RefObject | null | undefined'. -src/components/AppLayout/MenuList.tsx(198,7): error TS2531: Object is possibly 'null'. -src/components/AppLayout/MenuList.tsx(198,36): error TS2531: Object is possibly 'null'. -src/components/AppLayout/MenuList.tsx(232,11): error TS2532: Object is possibly 'undefined'. -src/components/AppLayout/MenuList.tsx(235,24): error TS2532: Object is possibly 'undefined'. -src/components/AppLayout/MenuList.tsx(236,23): error TS2532: Object is possibly 'undefined'. -src/components/AppLayout/MenuList.tsx(241,12): error TS2531: Object is possibly 'null'. -src/components/AppLayout/MenuList.tsx(241,41): error TS2531: Object is possibly 'null'. -src/components/AppLayout/MenuList.tsx(247,36): error TS2532: Object is possibly 'undefined'. -src/components/AppLayout/MenuNested.tsx(177,10): error TS2532: Object is possibly 'undefined'. -src/components/AppLayout/MenuNested.tsx(180,30): error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'. -src/components/AssignProductDialog/AssignProductDialog.tsx(149,48): error TS2531: Object is possibly 'null'. -src/components/AutocompleteSelectMenu/AutocompleteSelectMenu.tsx(104,27): error TS2322: Type '((value: string) => void) | undefined' is not assignable to type '(...args: string[]) => void'. -src/components/CardMenu/CardMenu.tsx(57,7): error TS2769: No overload matches this call. -src/components/CardTitle/CardTitle.tsx(63,11): error TS2464: A computed property name must be of type 'string', 'number', 'symbol', or 'any'. -src/components/Checkbox/Checkbox.tsx(106,11): error TS2531: Object is possibly 'null'. -src/components/Checkbox/Checkbox.tsx(108,15): error TS2531: Object is possibly 'null'. -src/components/Checkbox/Checkbox.tsx(129,9): error TS2322: Type 'string | false' is not assignable to type 'string | number | string[] | undefined'. -src/components/ColumnPicker/ColumnPicker.tsx(81,12): error TS2322: Type 'MutableRefObject' is not assignable to type 'string | ((instance: HTMLDivElement | null) => void) | RefObject | null | undefined'. -src/components/ColumnPicker/ColumnPickerContent.tsx(96,43): error TS2345: Argument of type 'MutableRefObject' is not assignable to parameter of type 'MutableRefObject'. -src/components/ColumnPicker/ColumnPickerContent.tsx(129,46): error TS2322: Type 'MutableRefObject' is not assignable to type 'string | ((instance: HTMLDivElement | null) => void) | RefObject | null | undefined'. -src/components/ColumnPicker/ColumnPickerContent.tsx(153,44): error TS2322: Type 'MutableRefObject' is not assignable to type 'string | ((instance: HTMLDivElement | null) => void) | RefObject | null | undefined'. -src/components/ConfirmButton/ConfirmButton.tsx(103,11): error TS2322: Type 'Timeout' is not assignable to type 'null'. -src/components/ConfirmButton/ConfirmButton.tsx(111,24): error TS2769: No overload matches this call. -src/components/ConfirmButton/ConfirmButton.tsx(117,20): error TS2769: No overload matches this call. -src/components/ConfirmButton/ConfirmButton.tsx(142,13): error TS2464: A computed property name must be of type 'string', 'number', 'symbol', or 'any'. -src/components/ControlledSwitch.tsx(46,13): error TS2722: Cannot invoke an object which is possibly 'undefined'. -src/components/CountryList/CountryList.tsx(146,41): error TS2538: Type 'undefined' cannot be used as an index type. -src/components/CountryList/CountryList.tsx(147,43): error TS2532: Object is possibly 'undefined'. -src/components/CountryList/CountryList.tsx(149,34): error TS2532: Object is possibly 'undefined'. -src/components/CountryList/CountryList.tsx(152,30): error TS2532: Object is possibly 'undefined'. -src/components/CountryList/CountryList.tsx(167,58): error TS2532: Object is possibly 'undefined'. -src/components/Date/Date.test.tsx(34,10): error TS2531: Object is possibly 'null'. -src/components/Date/Date.test.tsx(43,10): error TS2531: Object is possibly 'null'. -src/components/Date/DateContext.tsx(3,56): error TS2345: Argument of type 'undefined' is not assignable to parameter of type 'number'. -src/components/Date/DateTime.tsx(17,37): error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'LocaleSpecifier'. -src/components/Debounce.tsx(15,20): error TS2769: No overload matches this call. -src/components/Debounce.tsx(17,5): error TS2322: Type 'Timeout' is not assignable to type 'null'. -src/components/Debounce.tsx(21,18): error TS2769: No overload matches this call. -src/components/Filter/Filter.tsx(107,12): error TS2322: Type 'MutableRefObject' is not assignable to type 'string | ((instance: HTMLDivElement | null) => void) | RefObject | null | undefined'. -src/components/Filter/FilterAutocompleteField.tsx(58,28): error TS2532: Object is possibly 'undefined'. -src/components/Filter/FilterAutocompleteField.tsx(103,28): error TS2722: Cannot invoke an object which is possibly 'undefined'. -src/components/Filter/FilterAutocompleteField.tsx(141,11): error TS2322: Type '(() => void) | undefined' is not assignable to type '() => void'. -src/components/Filter/FilterContent.tsx(347,21): error TS2532: Object is possibly 'undefined'. -src/components/Filter/FilterOptionField.tsx(45,8): error TS2532: Object is possibly 'undefined'. -src/components/Filter/reducer.ts(49,3): error TS2322: Type '({ active?: boolean | undefined; multiple?: boolean | undefined; options?: MultiAutocompleteChoiceType[] | undefined; value?: string[] | undefined; } | { ...; })[]' is not assignable to type 'IFilter'. -src/components/Filter/reducer.ts(49,54): error TS2339: Property 'name' does not exist on type '{ active?: boolean | undefined; multiple?: boolean | undefined; options?: MultiAutocompleteChoiceType[] | undefined; value?: string[] | undefined; } | { ...; }'. -src/components/Filter/reducer.ts(49,65): error TS2339: Property 'name' does not exist on type '{ active?: boolean | undefined; multiple?: boolean | undefined; options?: MultiAutocompleteChoiceType[] | undefined; value?: string[] | undefined; } | { ...; }'. -src/components/Filter/reducer.ts(58,37): error TS2345: Argument of type 'T | undefined' is not assignable to parameter of type 'string'. -src/components/Filter/reducer.ts(60,31): error TS2345: Argument of type 'IFilter | undefined' is not assignable to parameter of type 'IFilter'. -src/components/Filter/reducer.ts(62,7): error TS2322: Type 'IFilter | undefined' is not assignable to type 'IFilter'. -src/components/Form/Form.tsx(15,31): error TS2345: Argument of type 'T | undefined' is not assignable to parameter of type 'Record'. -src/components/ImageUpload/ImageUpload.tsx(81,15): error TS2464: A computed property name must be of type 'string', 'number', 'symbol', or 'any'. -src/components/ImageUpload/ImageUpload.tsx(86,17): error TS2464: A computed property name must be of type 'string', 'number', 'symbol', or 'any'. -src/components/LanguageSwitch/LanguageSwitch.tsx(65,40): error TS2322: Type 'MutableRefObject' is not assignable to type 'string | ((instance: HTMLDivElement | null) => void) | RefObject | null | undefined'. -src/components/ListField/ListField.tsx(66,9): error TS2722: Cannot invoke an object which is possibly 'undefined'. -src/components/ListField/ListField.tsx(86,7): error TS2722: Cannot invoke an object which is possibly 'undefined'. -src/components/Locale/Locale.tsx(108,3): error TS2418: Type of computed property's value is 'undefined', which is not assignable to type 'Record'. -src/components/Locale/Locale.tsx(191,53): error TS2366: Function lacks ending return statement and return type does not include 'undefined'. -src/components/Locale/Locale.tsx(212,3): error TS2322: Type 'undefined' is not assignable to type 'Locale'. -src/components/messages/index.ts(10,62): error TS2345: Argument of type 'undefined' is not assignable to parameter of type 'IMessageContext'. -src/components/messages/MessageManager.tsx(38,7): error TS2322: Type 'number' is not assignable to type 'never'. -src/components/messages/MessageManager.tsx(51,21): error TS2345: Argument of type '{ message: undefined; opened: true; }' is not assignable to parameter of type 'MessageManagerState | ((prevState: Readonly, props: Readonly<{}>) => MessageManagerState | Pick<...> | null) | Pick<...> | null'. -src/components/MultiAutocompleteSelectField/MultiAutocompleteSelectField.stories.tsx(19,3): error TS2322: Type 'undefined' is not assignable to type 'MultiAutocompleteChoiceType[]'. -src/components/MultiAutocompleteSelectField/MultiAutocompleteSelectField.stories.tsx(26,3): error TS2322: Type 'undefined' is not assignable to type 'string[]'. -src/components/MultiAutocompleteSelectField/MultiAutocompleteSelectField.tsx(159,19): error TS2322: Type 'boolean | "" | null | undefined' is not assignable to type 'boolean'. -src/components/MultiAutocompleteSelectField/MultiAutocompleteSelectField.tsx(163,19): error TS2322: Type 'number | null' is not assignable to type 'number'. -src/components/MultiAutocompleteSelectField/MultiAutocompleteSelectField.tsx(165,19): error TS2322: Type 'string | null' is not assignable to type 'string'. -src/components/MultiAutocompleteSelectField/MultiAutocompleteSelectFieldContent.tsx(161,43): error TS2345: Argument of type 'MutableRefObject' is not assignable to parameter of type 'MutableRefObject'. -src/components/MultiAutocompleteSelectField/MultiAutocompleteSelectFieldContent.tsx(164,47): error TS2345: Argument of type 'MutableRefObject' is not assignable to parameter of type 'MutableRefObject'. -src/components/MultiAutocompleteSelectField/MultiAutocompleteSelectFieldContent.tsx(181,40): error TS2322: Type 'MutableRefObject' is not assignable to type 'string | ((instance: HTMLDivElement | null) => void) | RefObject | null | undefined'. -src/components/MultiSelectField/MultiSelectField.tsx(90,34): error TS2532: Object is possibly 'undefined'. -src/components/Navigator/modes/catalog.ts(23,11): error TS2531: Object is possibly 'null'. -src/components/Navigator/modes/catalog.ts(40,11): error TS2531: Object is possibly 'null'. -src/components/Navigator/modes/catalog.ts(62,11): error TS2531: Object is possibly 'null'. -src/components/Navigator/modes/catalog.ts(67,18): error TS2531: Object is possibly 'null'. -src/components/Navigator/modes/utils.ts(58,7): error TS2322: Type 'null' is not assignable to type 'QuickSearchMode'. -src/components/Navigator/Navigator.tsx(84,9): error TS2322: Type 'null' is not assignable to type 'number | undefined'. -src/components/Navigator/Navigator.tsx(155,23): error TS2322: Type 'number | null' is not assignable to type 'number'. -src/components/Navigator/Navigator.tsx(167,23): error TS2322: Type 'number | null' is not assignable to type 'number'. -src/components/Navigator/Navigator.tsx(179,23): error TS2322: Type 'number | null' is not assignable to type 'number'. -src/components/Navigator/Navigator.tsx(191,23): error TS2322: Type 'number | null' is not assignable to type 'number'. -src/components/Navigator/NavigatorInput.tsx(70,11): error TS2322: Type 'string | null' is not assignable to type 'string | undefined'. -src/components/Navigator/useQuickSearch.ts(43,11): error TS2531: Object is possibly 'null'. -src/components/Navigator/useQuickSearch.ts(43,11): error TS2531: Object is possibly 'null'. -src/components/Navigator/useQuickSearch.ts(44,27): error TS2531: Object is possibly 'null'. -src/components/Navigator/useQuickSearch.ts(44,27): error TS2531: Object is possibly 'null'. -src/components/Navigator/useQuickSearch.ts(109,9): error TS2322: Type 'SearchCatalog | undefined' is not assignable to type 'SearchCatalog'. -src/components/Navigator/useQuickSearch.ts(114,9): error TS2322: Type 'CheckIfOrderExists_order | null | undefined' is not assignable to type 'CheckIfOrderExists_order'. -src/components/Navigator/useQuickSearch.ts(114,28): error TS2532: Object is possibly 'undefined'. -src/components/RichTextEditor/ImageEntity.tsx(56,39): error TS2322: Type 'MutableRefObject' is not assignable to type 'string | ((instance: HTMLDivElement | null) => void) | RefObject | null | undefined'. -src/components/RichTextEditor/ImageSource.tsx(41,53): error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'. -src/components/RichTextEditor/LinkEntity.tsx(70,39): error TS2322: Type 'MutableRefObject' is not assignable to type 'string | ((instance: HTMLDivElement | null) => void) | RefObject | null | undefined'. -src/components/SaveButtonBar/SaveButtonBar.tsx(122,27): error TS2532: Object is possibly 'undefined'. -src/components/SaveButtonBar/SaveButtonBar.tsx(133,27): error TS2532: Object is possibly 'undefined'. -src/components/SeoForm/SeoForm.tsx(157,20): error TS2532: Object is possibly 'undefined'. -src/components/SeoForm/SeoForm.tsx(164,47): error TS2532: Object is possibly 'undefined'. -src/components/Shop/index.tsx(13,61): error TS2345: Argument of type 'undefined' is not assignable to parameter of type 'ShopInfo_shop'. -src/components/SingleAutocompleteSelectField/SingleAutocompleteSelectField.stories.tsx(20,3): error TS2322: Type 'undefined' is not assignable to type 'SingleAutocompleteChoiceType[]'. -src/components/SingleAutocompleteSelectField/SingleAutocompleteSelectField.stories.tsx(21,3): error TS2322: Type 'undefined' is not assignable to type 'string'. -src/components/SingleAutocompleteSelectField/SingleAutocompleteSelectField.tsx(82,27): error TS2322: Type '((value: string) => void) | undefined' is not assignable to type '(...args: string[]) => void'. -src/components/SingleAutocompleteSelectField/SingleAutocompleteSelectField.tsx(148,21): error TS2322: Type 'boolean | "" | null | undefined' is not assignable to type 'boolean'. -src/components/SingleAutocompleteSelectField/SingleAutocompleteSelectField.tsx(149,21): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. -src/components/SingleAutocompleteSelectField/SingleAutocompleteSelectField.tsx(152,21): error TS2322: Type 'number | null' is not assignable to type 'number'. -src/components/SingleAutocompleteSelectField/SingleAutocompleteSelectField.tsx(154,21): error TS2322: Type 'string | null' is not assignable to type 'string'. -src/components/SingleAutocompleteSelectField/SingleAutocompleteSelectFieldContent.tsx(130,43): error TS2345: Argument of type 'MutableRefObject' is not assignable to parameter of type 'MutableRefObject'. -src/components/SingleAutocompleteSelectField/SingleAutocompleteSelectFieldContent.tsx(133,47): error TS2345: Argument of type 'MutableRefObject' is not assignable to parameter of type 'MutableRefObject'. -src/components/SingleAutocompleteSelectField/SingleAutocompleteSelectFieldContent.tsx(150,40): error TS2322: Type 'MutableRefObject' is not assignable to type 'string | ((instance: HTMLDivElement | null) => void) | RefObject | null | undefined'. -src/components/SingleSelectField/SingleSelectField.tsx(82,38): error TS2571: Object is of type 'unknown'. -src/components/StatusLabel/StatusLabel.tsx(59,9): error TS2464: A computed property name must be of type 'string', 'number', 'symbol', or 'any'. -src/components/TableHead/TableHead.tsx(119,43): error TS2532: Object is possibly 'undefined'. -src/components/TableHead/TableHead.tsx(119,55): error TS2532: Object is possibly 'undefined'. -src/components/TableHead/TableHead.tsx(123,31): error TS2722: Cannot invoke an object which is possibly 'undefined'. -src/components/TableHead/TableHead.tsx(123,48): error TS2345: Argument of type 'number | undefined' is not assignable to parameter of type 'number'. -src/components/TablePagination/TablePagination.tsx(92,6): error TS2604: JSX element type 'Component' does not have any construct or call signatures. -src/components/TablePagination/TablePagination.tsx(95,24): error TS2532: Object is possibly 'undefined'. -src/components/TablePagination/TablePagination.tsx(98,15): error TS2322: Type 'ListSettings | undefined' is not assignable to type 'ListSettings'. -src/components/TablePagination/TablePagination.tsx(99,15): error TS2322: Type '((key: "columns" | "rowNumber", value: any) => void) | undefined' is not assignable to type '(key: "columns" | "rowNumber", value: any) => any'. -src/components/TextFieldWithChoice/TextFieldWithChoice.tsx(59,17): error TS2722: Cannot invoke an object which is possibly 'undefined'. -src/components/TextFieldWithChoice/TextFieldWithChoice.tsx(72,21): error TS2322: Type 'MutableRefObject' is not assignable to type 'string | ((instance: HTMLDivElement | null) => void) | RefObject | null | undefined'. -src/components/Theme/ThemeProvider.tsx(36,9): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. -src/components/Timeline/TimelineNote.tsx(98,23): error TS2531: Object is possibly 'null'. -src/components/Timezone/Timezone.tsx(3,60): error TS2345: Argument of type 'undefined' is not assignable to parameter of type 'string'. -src/components/VisibilityCard/VisibilityCard.tsx(88,39): error TS2571: Object is of type 'unknown'. -src/components/WindowTitle/index.tsx(14,34): error TS2571: Object is of type 'unknown'. -src/config.ts(9,3): error TS2322: Type 'null' is not assignable to type 'string | undefined'. -src/configuration/ConfigurationPage.tsx(125,51): error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'. -src/configuration/index.tsx(193,27): error TS2571: Object is of type 'unknown'. -src/containers/AppState/reducer.ts(34,38): error TS2345: Argument of type '"unhandled" | undefined' is not assignable to parameter of type '"unhandled"'. -src/containers/AppState/reducer.ts(36,39): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/customers/components/CustomerAddress/CustomerAddress.tsx(108,27): error TS2322: Type 'CustomerAddresses_user_addresses' is not assignable to type 'AddressType'. -src/customers/components/CustomerAddressDialog/CustomerAddressDialog.tsx(81,7): error TS2322: Type 'string | null' is not assignable to type 'string'. -src/customers/components/CustomerAddresses/CustomerAddresses.tsx(56,20): error TS2531: Object is possibly 'null'. -src/customers/components/CustomerAddresses/CustomerAddresses.tsx(57,19): error TS2531: Object is possibly 'null'. -src/customers/components/CustomerAddresses/CustomerAddresses.tsx(68,17): error TS2322: Type 'CustomerDetails_user_defaultBillingAddress | null | undefined' is not assignable to type 'AddressType | undefined'. -src/customers/components/CustomerAddresses/CustomerAddresses.tsx(85,17): error TS2322: Type 'CustomerDetails_user_defaultShippingAddress | null | undefined' is not assignable to type 'AddressType | undefined'. -src/customers/components/CustomerAddresses/CustomerAddresses.tsx(106,13): error TS2322: Type 'CustomerDetails_user_defaultBillingAddress | null | undefined' is not assignable to type 'AddressType | undefined'. -src/customers/components/CustomerAddressListPage/CustomerAddressListPage.tsx(65,31): error TS2531: Object is possibly 'null'. -src/customers/components/CustomerAddressListPage/CustomerAddressListPage.tsx(125,13): error TS2345: Argument of type '(CustomerAddresses_user_addresses | null)[] | null | undefined' is not assignable to parameter of type '(CustomerAddresses_user_addresses | null)[]'. -src/customers/components/CustomerAddressListPage/CustomerAddressListPage.tsx(132,31): error TS2531: Object is possibly 'null'. -src/customers/components/CustomerAddressListPage/CustomerAddressListPage.tsx(136,31): error TS2531: Object is possibly 'null'. -src/customers/components/CustomerCreatePage/CustomerCreatePage.tsx(125,9): error TS2322: Type 'null' is not assignable to type 'AddressInput'. -src/customers/components/CustomerDetailsPage/CustomerDetailsPage.tsx(79,17): error TS2322: Type '{ email: string; firstName: string; isActive: boolean; lastName: string; note: string | null; }' is not assignable to type '{ isActive: boolean; note: string; }'. -src/customers/components/CustomerDetailsPage/CustomerDetailsPage.tsx(93,17): error TS2322: Type 'CustomerDetails_user_orders_edges_node[] | undefined' is not assignable to type 'CustomerDetails_user_orders_edges_node[]'. -src/customers/components/CustomerDetailsPage/CustomerDetailsPage.tsx(94,19): error TS2531: Object is possibly 'null'. -src/customers/components/CustomerList/CustomerList.tsx(87,35): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/customers/components/CustomerList/CustomerList.tsx(99,35): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/customers/components/CustomerList/CustomerList.tsx(110,35): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/customers/components/CustomerList/CustomerList.tsx(154,44): error TS2532: Object is possibly 'undefined'. -src/customers/components/CustomerList/CustomerList.tsx(161,49): error TS2532: Object is possibly 'undefined'. -src/customers/components/CustomerList/CustomerList.tsx(165,27): error TS2532: Object is possibly 'undefined'. -src/customers/components/CustomerList/CustomerList.tsx(165,27): error TS2531: Object is possibly 'null'. -src/customers/components/CustomerOrders/CustomerOrders.tsx(47,47): error TS2345: Argument of type 'PaymentChargeStatusEnum | null' is not assignable to parameter of type 'string'. -src/customers/components/CustomerOrders/CustomerOrders.tsx(97,13): error TS2345: Argument of type '{ paymentStatus: any; __typename: "Order"; id: string; created: any; number: string | null; total: CustomerDetails_user_orders_edges_node_total | null; }[] | undefined' is not assignable to parameter of type '{ paymentStatus: any; __typename: "Order"; id: string; created: any; number: string | null; total: CustomerDetails_user_orders_edges_node_total | null; }[]'. -src/customers/components/CustomerStats/CustomerStats.tsx(70,16): error TS2531: Object is possibly 'null'. -src/customers/components/CustomerStats/CustomerStats.tsx(74,25): error TS2531: Object is possibly 'null'. -src/customers/fixtures.ts(949,3): error TS2322: Type '({ __typename: "Address"; city: string; cityArea: string; companyName: string; country: { __typename: "CountryDisplay"; code: string; country: string; }; countryArea: string; firstName: string; ... 5 more ...; streetAddress2: string; } | { ...; })[]' is not assignable to type '(CustomerAddresses_user_addresses | null)[]'. -src/customers/views/CustomerAddresses.tsx(53,9): error TS2531: Object is possibly 'null'. -src/customers/views/CustomerAddresses.tsx(53,9): error TS2531: Object is possibly 'null'. -src/customers/views/CustomerAddresses.tsx(62,9): error TS2531: Object is possibly 'null'. -src/customers/views/CustomerAddresses.tsx(62,9): error TS2531: Object is possibly 'null'. -src/customers/views/CustomerAddresses.tsx(68,9): error TS2531: Object is possibly 'null'. -src/customers/views/CustomerAddresses.tsx(68,9): error TS2531: Object is possibly 'null'. -src/customers/views/CustomerAddresses.tsx(77,9): error TS2531: Object is possibly 'null'. -src/customers/views/CustomerAddresses.tsx(77,9): error TS2531: Object is possibly 'null'. -src/customers/views/CustomerAddresses.tsx(104,29): error TS2571: Object is of type 'unknown'. -src/customers/views/CustomerAddresses.tsx(114,31): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/customers/views/CustomerAddresses.tsx(114,50): error TS2532: Object is possibly 'undefined'. -src/customers/views/CustomerAddresses.tsx(114,50): error TS2531: Object is possibly 'null'. -src/customers/views/CustomerAddresses.tsx(117,31): error TS2322: Type 'CustomerAddresses_user | null | undefined' is not assignable to type 'CustomerAddresses_user'. -src/customers/views/CustomerAddresses.tsx(117,53): error TS2532: Object is possibly 'undefined'. -src/customers/views/CustomerAddresses.tsx(138,31): error TS2322: Type 'undefined' is not assignable to type 'CustomerAddresses_user_addresses'. -src/customers/views/CustomerAddresses.tsx(143,31): error TS2322: Type 'CreateCustomerAddress_addressCreate_errors[] | null' is not assignable to type 'UserError[]'. -src/customers/views/CustomerAddresses.tsx(145,35): error TS2532: Object is possibly 'undefined'. -src/customers/views/CustomerAddresses.tsx(145,35): error TS2531: Object is possibly 'null'. -src/customers/views/CustomerAddresses.tsx(162,31): error TS2322: Type 'CustomerAddresses_user_addresses | null | undefined' is not assignable to type 'CustomerAddresses_user_addresses'. -src/customers/views/CustomerAddresses.tsx(163,33): error TS2532: Object is possibly 'undefined'. -src/customers/views/CustomerAddresses.tsx(163,33): error TS2531: Object is possibly 'null'. -src/customers/views/CustomerAddresses.tsx(163,33): error TS2531: Object is possibly 'null'. -src/customers/views/CustomerAddresses.tsx(164,43): error TS2531: Object is possibly 'null'. -src/customers/views/CustomerAddresses.tsx(171,31): error TS2322: Type 'UpdateCustomerAddress_addressUpdate_errors[] | null' is not assignable to type 'UserError[]'. -src/customers/views/CustomerAddresses.tsx(173,35): error TS2532: Object is possibly 'undefined'. -src/customers/views/CustomerAddresses.tsx(173,35): error TS2531: Object is possibly 'null'. -src/customers/views/CustomerAddresses.tsx(181,55): error TS2345: Argument of type '{ variables: { id: string | undefined; input: AddressInput; }; }' is not assignable to parameter of type 'MutationFunctionOptions'. -src/customers/views/CustomerAddresses.tsx(201,55): error TS2345: Argument of type '{ variables: { id: string | undefined; }; }' is not assignable to parameter of type 'MutationFunctionOptions'. -src/customers/views/CustomerCreate.tsx(20,9): error TS2531: Object is possibly 'null'. -src/customers/views/CustomerCreate.tsx(20,9): error TS2531: Object is possibly 'null'. -src/customers/views/CustomerCreate.tsx(26,28): error TS2531: Object is possibly 'null'. -src/customers/views/CustomerCreate.tsx(26,28): error TS2531: Object is possibly 'null'. -src/customers/views/CustomerCreate.tsx(42,17): error TS2322: Type '(CustomerCreateData_shop_countries | null)[]' is not assignable to type 'CustomerCreateData_shop_countries[]'. -src/customers/views/CustomerCreate.tsx(42,40): error TS2532: Object is possibly 'undefined'. -src/customers/views/CustomerCreate.tsx(42,40): error TS2531: Object is possibly 'null'. -src/customers/views/CustomerCreate.tsx(44,17): error TS2322: Type 'CreateCustomer_customerCreate_errors[]' is not assignable to type 'UserError[]'. -src/customers/views/CustomerCreate.tsx(45,32): error TS2532: Object is possibly 'undefined'. -src/customers/views/CustomerCreate.tsx(45,32): error TS2531: Object is possibly 'null'. -src/customers/views/CustomerCreate.tsx(46,26): error TS2531: Object is possibly 'null'. -src/customers/views/CustomerCreate.tsx(47,21): error TS2531: Object is possibly 'null'. -src/customers/views/CustomerCreate.tsx(50,34): error TS2531: Object is possibly 'null'. -src/customers/views/CustomerDetails.tsx(42,9): error TS2531: Object is possibly 'null'. -src/customers/views/CustomerDetails.tsx(42,9): error TS2531: Object is possibly 'null'. -src/customers/views/CustomerDetails.tsx(49,9): error TS2531: Object is possibly 'null'. -src/customers/views/CustomerDetails.tsx(49,9): error TS2531: Object is possibly 'null'. -src/customers/views/CustomerDetails.tsx(80,23): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/customers/views/CustomerDetails.tsx(80,42): error TS2532: Object is possibly 'undefined'. -src/customers/views/CustomerDetails.tsx(80,42): error TS2531: Object is possibly 'null'. -src/customers/views/CustomerDetails.tsx(83,23): error TS2322: Type 'CustomerDetails_user | null | undefined' is not assignable to type 'CustomerDetails_user'. -src/customers/views/CustomerDetails.tsx(83,45): error TS2532: Object is possibly 'undefined'. -src/customers/views/CustomerDetails.tsx(89,23): error TS2322: Type 'UpdateCustomer_customerUpdate_errors[] | null | undefined' is not assignable to type 'UserError[]'. -src/customers/views/CustomerDetails.tsx(90,31): error TS2532: Object is possibly 'undefined'. -src/customers/views/CustomerDetails.tsx(90,31): error TS2531: Object is possibly 'null'. -src/customers/views/CustomerDetails.tsx(123,37): error TS2532: Object is possibly 'undefined'. -src/customers/views/CustomerDetails.tsx(123,37): error TS2531: Object is possibly 'null'. -src/customers/views/CustomerDetails.tsx(148,41): error TS2532: Object is possibly 'undefined'. -src/customers/views/CustomerDetails.tsx(148,41): error TS2531: Object is possibly 'null'. -src/customers/views/CustomerList/CustomerList.tsx(96,5): error TS2322: Type '(params?: CustomerListUrlQueryParams | undefined) => string' is not assignable to type 'CreateUrl'. -src/customers/views/CustomerList/CustomerList.tsx(129,5): error TS2345: Argument of type 'ListCustomers_customers_pageInfo | undefined' is not assignable to parameter of type 'PageInfo'. -src/customers/views/CustomerList/CustomerList.tsx(129,17): error TS2532: Object is possibly 'undefined'. -src/customers/views/CustomerList/CustomerList.tsx(129,17): error TS2531: Object is possibly 'null'. -src/customers/views/CustomerList/CustomerList.tsx(135,9): error TS2531: Object is possibly 'null'. -src/customers/views/CustomerList/CustomerList.tsx(135,9): error TS2531: Object is possibly 'null'. -src/customers/views/CustomerList/CustomerList.tsx(146,38): error TS2571: Object is of type 'unknown'. -src/customers/views/CustomerList/CustomerList.tsx(164,13): error TS2322: Type 'ListCustomers_customers_edges_node[] | undefined' is not assignable to type 'ListCustomers_customers_edges_node[]'. -src/customers/views/CustomerList/CustomerList.tsx(164,36): error TS2532: Object is possibly 'undefined'. -src/customers/views/CustomerList/CustomerList.tsx(164,36): error TS2531: Object is possibly 'null'. -src/customers/views/CustomerList/CustomerList.tsx(193,13): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. -src/customers/views/CustomerList/CustomerList.tsx(194,57): error TS2532: Object is possibly 'undefined'. -src/customers/views/CustomerList/CustomerList.tsx(199,35): error TS2345: Argument of type '{ variables: { ids: string[] | undefined; }; }' is not assignable to parameter of type 'MutationFunctionOptions'. -src/customers/views/CustomerList/CustomerList.tsx(215,40): error TS2532: Object is possibly 'undefined'. -src/customers/views/CustomerList/CustomerList.tsx(217,42): error TS2532: Object is possibly 'undefined'. -src/customers/views/CustomerList/filters.ts(35,9): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/customers/views/CustomerList/filters.ts(36,9): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/customers/views/CustomerList/filters.ts(48,9): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/customers/views/CustomerList/filters.ts(49,9): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/customers/views/CustomerList/filters.ts(61,9): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/customers/views/CustomerList/filters.ts(62,9): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/customers/views/CustomerList/filters.ts(77,21): error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'. -src/customers/views/CustomerList/filters.ts(78,21): error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'. -src/customers/views/CustomerList/filters.ts(81,21): error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'. -src/customers/views/CustomerList/filters.ts(82,21): error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'. -src/customers/views/CustomerList/sort.ts(16,7): error TS2322: Type 'undefined' is not assignable to type 'UserSortField'. -src/discounts/components/DiscountCategories/DiscountCategories.tsx(95,11): error TS2322: Type 'SaleDetails_sale_categories_edges_node[] | undefined' is not assignable to type 'Node[]'. -src/discounts/components/DiscountCategories/DiscountCategories.tsx(95,30): error TS2531: Object is possibly 'null'. -src/discounts/components/DiscountCategories/DiscountCategories.tsx(127,13): error TS2345: Argument of type 'SaleDetails_sale_categories_edges_node[] | undefined' is not assignable to parameter of type 'SaleDetails_sale_categories_edges_node[]'. -src/discounts/components/DiscountCategories/DiscountCategories.tsx(127,25): error TS2531: Object is possibly 'null'. -src/discounts/components/DiscountCollections/DiscountCollections.tsx(95,11): error TS2322: Type 'SaleDetails_sale_collections_edges_node[] | undefined' is not assignable to type 'Node[]'. -src/discounts/components/DiscountCollections/DiscountCollections.tsx(95,30): error TS2531: Object is possibly 'null'. -src/discounts/components/DiscountCollections/DiscountCollections.tsx(125,13): error TS2345: Argument of type 'SaleDetails_sale_collections_edges_node[] | undefined' is not assignable to parameter of type 'SaleDetails_sale_collections_edges_node[]'. -src/discounts/components/DiscountCollections/DiscountCollections.tsx(125,25): error TS2531: Object is possibly 'null'. -src/discounts/components/DiscountProducts/DiscountProducts.tsx(109,11): error TS2322: Type 'SaleDetails_sale_products_edges_node[] | undefined' is not assignable to type 'Node[]'. -src/discounts/components/DiscountProducts/DiscountProducts.tsx(109,30): error TS2531: Object is possibly 'null'. -src/discounts/components/DiscountProducts/DiscountProducts.tsx(144,13): error TS2345: Argument of type 'SaleDetails_sale_products_edges_node[] | undefined' is not assignable to parameter of type 'SaleDetails_sale_products_edges_node[]'. -src/discounts/components/DiscountProducts/DiscountProducts.tsx(144,25): error TS2531: Object is possibly 'null'. -src/discounts/components/SaleDetailsPage/SaleDetailsPage.tsx(116,5): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. -src/discounts/components/SaleDetailsPage/SaleDetailsPage.tsx(163,31): error TS2531: Object is possibly 'null'. -src/discounts/components/SaleDetailsPage/SaleDetailsPage.tsx(163,31): error TS2531: Object is possibly 'null'. -src/discounts/components/SaleDetailsPage/SaleDetailsPage.tsx(181,31): error TS2531: Object is possibly 'null'. -src/discounts/components/SaleDetailsPage/SaleDetailsPage.tsx(181,31): error TS2531: Object is possibly 'null'. -src/discounts/components/SaleDetailsPage/SaleDetailsPage.tsx(199,31): error TS2531: Object is possibly 'null'. -src/discounts/components/SaleDetailsPage/SaleDetailsPage.tsx(199,31): error TS2531: Object is possibly 'null'. -src/discounts/components/SaleList/SaleList.tsx(103,35): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/discounts/components/SaleList/SaleList.tsx(115,35): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/discounts/components/SaleList/SaleList.tsx(130,35): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/discounts/components/SaleList/SaleList.tsx(142,35): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/discounts/components/SaleList/SaleList.tsx(186,44): error TS2532: Object is possibly 'undefined'. -src/discounts/components/SaleList/SaleList.tsx(190,49): error TS2532: Object is possibly 'undefined'. -src/discounts/components/VoucherDetailsPage/VoucherDetailsPage.tsx(135,7): error TS2532: Object is possibly 'undefined'. -src/discounts/components/VoucherDetailsPage/VoucherDetailsPage.tsx(135,19): error TS2531: Object is possibly 'null'. -src/discounts/components/VoucherDetailsPage/VoucherDetailsPage.tsx(137,14): error TS2533: Object is possibly 'null' or 'undefined'. -src/discounts/components/VoucherDetailsPage/VoucherDetailsPage.tsx(153,5): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. -src/discounts/components/VoucherDetailsPage/VoucherDetailsPage.tsx(154,5): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. -src/discounts/components/VoucherDetailsPage/VoucherDetailsPage.tsx(156,13): error TS2531: Object is possibly 'null'. -src/discounts/components/VoucherDetailsPage/VoucherDetailsPage.tsx(159,27): error TS2531: Object is possibly 'null'. -src/discounts/components/VoucherDetailsPage/VoucherDetailsPage.tsx(164,29): error TS2531: Object is possibly 'null'. -src/discounts/components/VoucherDetailsPage/VoucherDetailsPage.tsx(219,35): error TS2531: Object is possibly 'null'. -src/discounts/components/VoucherDetailsPage/VoucherDetailsPage.tsx(219,35): error TS2531: Object is possibly 'null'. -src/discounts/components/VoucherDetailsPage/VoucherDetailsPage.tsx(236,35): error TS2531: Object is possibly 'null'. -src/discounts/components/VoucherDetailsPage/VoucherDetailsPage.tsx(236,35): error TS2531: Object is possibly 'null'. -src/discounts/components/VoucherDetailsPage/VoucherDetailsPage.tsx(253,35): error TS2531: Object is possibly 'null'. -src/discounts/components/VoucherDetailsPage/VoucherDetailsPage.tsx(253,35): error TS2531: Object is possibly 'null'. -src/discounts/components/VoucherDetailsPage/VoucherDetailsPage.tsx(315,19): error TS2322: Type '(VoucherDetails_voucher_countries | null)[] | null | undefined' is not assignable to type 'CountryFragment[]'. -src/discounts/components/VoucherList/VoucherList.tsx(118,35): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/discounts/components/VoucherList/VoucherList.tsx(130,35): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/discounts/components/VoucherList/VoucherList.tsx(144,35): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/discounts/components/VoucherList/VoucherList.tsx(158,35): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/discounts/components/VoucherList/VoucherList.tsx(172,35): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/discounts/components/VoucherList/VoucherList.tsx(186,35): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/discounts/components/VoucherList/VoucherList.tsx(229,44): error TS2532: Object is possibly 'undefined'. -src/discounts/components/VoucherList/VoucherList.tsx(233,49): error TS2532: Object is possibly 'undefined'. -src/discounts/components/VoucherList/VoucherList.tsx(285,23): error TS2532: Object is possibly 'undefined'. -src/discounts/components/VoucherList/VoucherList.tsx(285,59): error TS2532: Object is possibly 'undefined'. -src/discounts/components/VoucherValue/VoucherValue.tsx(75,13): error TS2322: Type 'null' is not assignable to type '{ label: ReactNode; value: string; }[]'. -src/discounts/views/SaleCreate.tsx(29,9): error TS2531: Object is possibly 'null'. -src/discounts/views/SaleCreate.tsx(29,9): error TS2531: Object is possibly 'null'. -src/discounts/views/SaleCreate.tsx(35,24): error TS2531: Object is possibly 'null'. -src/discounts/views/SaleCreate.tsx(35,24): error TS2531: Object is possibly 'null'. -src/discounts/views/SaleCreate.tsx(45,42): error TS2571: Object is of type 'unknown'. -src/discounts/views/SaleCreate.tsx(47,13): error TS2322: Type 'SaleCreate_saleCreate_errors[] | null | undefined' is not assignable to type 'UserError[]'. -src/discounts/views/SaleCreate.tsx(47,33): error TS2532: Object is possibly 'undefined'. -src/discounts/views/SaleCreate.tsx(47,33): error TS2531: Object is possibly 'null'. -src/discounts/views/SaleDetails.tsx(100,9): error TS2531: Object is possibly 'null'. -src/discounts/views/SaleDetails.tsx(100,9): error TS2531: Object is possibly 'null'. -src/discounts/views/SaleDetails.tsx(111,9): error TS2531: Object is possibly 'null'. -src/discounts/views/SaleDetails.tsx(111,9): error TS2531: Object is possibly 'null'. -src/discounts/views/SaleDetails.tsx(124,9): error TS2531: Object is possibly 'null'. -src/discounts/views/SaleDetails.tsx(124,9): error TS2531: Object is possibly 'null'. -src/discounts/views/SaleDetails.tsx(130,9): error TS2531: Object is possibly 'null'. -src/discounts/views/SaleDetails.tsx(130,9): error TS2531: Object is possibly 'null'. -src/discounts/views/SaleDetails.tsx(136,47): error TS2532: Object is possibly 'undefined'. -src/discounts/views/SaleDetails.tsx(154,43): error TS2532: Object is possibly 'undefined'. -src/discounts/views/SaleDetails.tsx(154,43): error TS2531: Object is possibly 'null'. -src/discounts/views/SaleDetails.tsx(154,43): error TS2531: Object is possibly 'null'. -src/discounts/views/SaleDetails.tsx(157,43): error TS2532: Object is possibly 'undefined'. -src/discounts/views/SaleDetails.tsx(157,43): error TS2531: Object is possibly 'null'. -src/discounts/views/SaleDetails.tsx(157,43): error TS2531: Object is possibly 'null'. -src/discounts/views/SaleDetails.tsx(158,43): error TS2532: Object is possibly 'undefined'. -src/discounts/views/SaleDetails.tsx(158,43): error TS2531: Object is possibly 'null'. -src/discounts/views/SaleDetails.tsx(158,43): error TS2531: Object is possibly 'null'. -src/discounts/views/SaleDetails.tsx(197,38): error TS2345: Argument of type 'SaleDetails_sale_products_pageInfo | undefined' is not assignable to parameter of type 'PageInfo'. -src/discounts/views/SaleDetails.tsx(206,39): error TS2571: Object is of type 'unknown'. -src/discounts/views/SaleDetails.tsx(208,31): error TS2322: Type 'SaleDetails_sale | null | undefined' is not assignable to type 'SaleDetails_sale'. -src/discounts/views/SaleDetails.tsx(208,49): error TS2532: Object is possibly 'undefined'. -src/discounts/views/SaleDetails.tsx(212,31): error TS2322: Type 'SaleUpdate_saleUpdate_errors[] | null | undefined' is not assignable to type 'UserError[]'. -src/discounts/views/SaleDetails.tsx(213,39): error TS2532: Object is possibly 'undefined'. -src/discounts/views/SaleDetails.tsx(213,39): error TS2531: Object is possibly 'null'. -src/discounts/views/SaleDetails.tsx(242,31): error TS2322: Type 'SaleDetailsPageTab | undefined' is not assignable to type 'SaleDetailsPageTab'. -src/discounts/views/SaleDetails.tsx(406,31): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. -src/discounts/views/SaleDetails.tsx(419,58): error TS2345: Argument of type 'string[] | undefined' is not assignable to parameter of type 'string[]'. -src/discounts/views/SaleDetails.tsx(428,48): error TS2532: Object is possibly 'undefined'. -src/discounts/views/SaleDetails.tsx(430,50): error TS2532: Object is possibly 'undefined'. -src/discounts/views/SaleDetails.tsx(438,31): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. -src/discounts/views/SaleDetails.tsx(452,59): error TS2345: Argument of type 'string[] | undefined' is not assignable to parameter of type 'string[]'. -src/discounts/views/SaleDetails.tsx(461,48): error TS2532: Object is possibly 'undefined'. -src/discounts/views/SaleDetails.tsx(463,50): error TS2532: Object is possibly 'undefined'. -src/discounts/views/SaleDetails.tsx(471,31): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. -src/discounts/views/SaleDetails.tsx(484,56): error TS2345: Argument of type 'string[] | undefined' is not assignable to parameter of type 'string[]'. -src/discounts/views/SaleDetails.tsx(493,48): error TS2532: Object is possibly 'undefined'. -src/discounts/views/SaleDetails.tsx(495,50): error TS2532: Object is possibly 'undefined'. -src/discounts/views/SaleDetails.tsx(524,54): error TS2532: Object is possibly 'undefined'. -src/discounts/views/SaleDetails.tsx(524,54): error TS2531: Object is possibly 'null'. -src/discounts/views/SaleList/filters.ts(34,42): error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'. -src/discounts/views/SaleList/filters.ts(45,9): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/discounts/views/SaleList/filters.ts(46,9): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/discounts/views/SaleList/filters.ts(54,13): error TS2532: Object is possibly 'undefined'. -src/discounts/views/SaleList/filters.ts(68,5): error TS2322: Type '"" | DiscountValueTypeEnum | undefined' is not assignable to type 'DiscountValueTypeEnum | null | undefined'. -src/discounts/views/SaleList/filters.ts(72,25): error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'. -src/discounts/views/SaleList/filters.ts(73,25): error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'. -src/discounts/views/SaleList/SaleList.tsx(97,5): error TS2322: Type '(params?: SaleListUrlQueryParams | undefined) => string' is not assignable to type 'CreateUrl'. -src/discounts/views/SaleList/SaleList.tsx(129,47): error TS2532: Object is possibly 'undefined'. -src/discounts/views/SaleList/SaleList.tsx(132,5): error TS2345: Argument of type 'SaleList_sales_pageInfo | undefined' is not assignable to parameter of type 'PageInfo'. -src/discounts/views/SaleList/SaleList.tsx(132,17): error TS2532: Object is possibly 'undefined'. -src/discounts/views/SaleList/SaleList.tsx(132,17): error TS2531: Object is possibly 'null'. -src/discounts/views/SaleList/SaleList.tsx(138,9): error TS2531: Object is possibly 'null'. -src/discounts/views/SaleList/SaleList.tsx(138,9): error TS2531: Object is possibly 'null'. -src/discounts/views/SaleList/SaleList.tsx(149,38): error TS2571: Object is of type 'unknown'. -src/discounts/views/SaleList/SaleList.tsx(155,26): error TS2345: Argument of type '{ variables: { ids: string[] | undefined; }; }' is not assignable to parameter of type 'MutationFunctionOptions'. -src/discounts/views/SaleList/SaleList.tsx(176,44): error TS2571: Object is of type 'unknown'. -src/discounts/views/SaleList/SaleList.tsx(177,15): error TS2322: Type 'SaleList_sales_edges_node[] | undefined' is not assignable to type 'SaleList_sales_edges_node[]'. -src/discounts/views/SaleList/SaleList.tsx(177,34): error TS2532: Object is possibly 'undefined'. -src/discounts/views/SaleList/SaleList.tsx(177,34): error TS2531: Object is possibly 'null'. -src/discounts/views/SaleList/SaleList.tsx(209,15): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. -src/discounts/views/SaleList/SaleList.tsx(222,32): error TS2532: Object is possibly 'undefined'. -src/discounts/views/SaleList/SaleList.tsx(223,49): error TS2532: Object is possibly 'undefined'. -src/discounts/views/SaleList/sort.ts(18,7): error TS2322: Type 'undefined' is not assignable to type 'SaleSortField'. -src/discounts/views/VoucherCreate.tsx(27,9): error TS2531: Object is possibly 'null'. -src/discounts/views/VoucherCreate.tsx(27,9): error TS2531: Object is possibly 'null'. -src/discounts/views/VoucherCreate.tsx(33,27): error TS2531: Object is possibly 'null'. -src/discounts/views/VoucherCreate.tsx(33,27): error TS2531: Object is possibly 'null'. -src/discounts/views/VoucherCreate.tsx(43,42): error TS2571: Object is of type 'unknown'. -src/discounts/views/VoucherCreate.tsx(45,13): error TS2322: Type 'VoucherCreate_voucherCreate_errors[] | null | undefined' is not assignable to type 'UserError[]'. -src/discounts/views/VoucherCreate.tsx(45,33): error TS2532: Object is possibly 'undefined'. -src/discounts/views/VoucherCreate.tsx(45,33): error TS2531: Object is possibly 'null'. -src/discounts/views/VoucherDetails.tsx(102,9): error TS2531: Object is possibly 'null'. -src/discounts/views/VoucherDetails.tsx(102,9): error TS2531: Object is possibly 'null'. -src/discounts/views/VoucherDetails.tsx(113,9): error TS2531: Object is possibly 'null'. -src/discounts/views/VoucherDetails.tsx(113,9): error TS2531: Object is possibly 'null'. -src/discounts/views/VoucherDetails.tsx(127,9): error TS2531: Object is possibly 'null'. -src/discounts/views/VoucherDetails.tsx(127,9): error TS2531: Object is possibly 'null'. -src/discounts/views/VoucherDetails.tsx(133,9): error TS2531: Object is possibly 'null'. -src/discounts/views/VoucherDetails.tsx(133,9): error TS2531: Object is possibly 'null'. -src/discounts/views/VoucherDetails.tsx(139,47): error TS2532: Object is possibly 'undefined'. -src/discounts/views/VoucherDetails.tsx(157,43): error TS2532: Object is possibly 'undefined'. -src/discounts/views/VoucherDetails.tsx(157,43): error TS2531: Object is possibly 'null'. -src/discounts/views/VoucherDetails.tsx(157,43): error TS2531: Object is possibly 'null'. -src/discounts/views/VoucherDetails.tsx(160,43): error TS2532: Object is possibly 'undefined'. -src/discounts/views/VoucherDetails.tsx(160,43): error TS2531: Object is possibly 'null'. -src/discounts/views/VoucherDetails.tsx(160,43): error TS2531: Object is possibly 'null'. -src/discounts/views/VoucherDetails.tsx(161,43): error TS2532: Object is possibly 'undefined'. -src/discounts/views/VoucherDetails.tsx(161,43): error TS2531: Object is possibly 'null'. -src/discounts/views/VoucherDetails.tsx(161,43): error TS2531: Object is possibly 'null'. -src/discounts/views/VoucherDetails.tsx(200,38): error TS2345: Argument of type 'VoucherDetails_voucher_products_pageInfo | undefined' is not assignable to parameter of type 'PageInfo'. -src/discounts/views/VoucherDetails.tsx(209,39): error TS2571: Object is of type 'unknown'. -src/discounts/views/VoucherDetails.tsx(211,31): error TS2322: Type 'VoucherDetails_voucher | null | undefined' is not assignable to type 'VoucherDetails_voucher'. -src/discounts/views/VoucherDetails.tsx(211,52): error TS2532: Object is possibly 'undefined'. -src/discounts/views/VoucherDetails.tsx(215,31): error TS2322: Type 'VoucherUpdate_voucherUpdate_errors[] | null | undefined' is not assignable to type 'UserError[]'. -src/discounts/views/VoucherDetails.tsx(217,35): error TS2532: Object is possibly 'undefined'. -src/discounts/views/VoucherDetails.tsx(217,35): error TS2531: Object is possibly 'null'. -src/discounts/views/VoucherDetails.tsx(250,50): error TS2532: Object is possibly 'undefined'. -src/discounts/views/VoucherDetails.tsx(250,50): error TS2531: Object is possibly 'null'. -src/discounts/views/VoucherDetails.tsx(250,50): error TS2531: Object is possibly 'null'. -src/discounts/views/VoucherDetails.tsx(253,45): error TS2531: Object is possibly 'null'. -src/discounts/views/VoucherDetails.tsx(255,57): error TS2531: Object is possibly 'null'. -src/discounts/views/VoucherDetails.tsx(289,31): error TS2322: Type 'VoucherDetailsPageTab | undefined' is not assignable to type 'VoucherDetailsPageTab'. -src/discounts/views/VoucherDetails.tsx(460,54): error TS2571: Object is of type 'unknown'. -src/discounts/views/VoucherDetails.tsx(475,35): error TS2532: Object is possibly 'undefined'. -src/discounts/views/VoucherDetails.tsx(475,35): error TS2531: Object is possibly 'null'. -src/discounts/views/VoucherDetails.tsx(475,35): error TS2531: Object is possibly 'null'. -src/discounts/views/VoucherDetails.tsx(476,48): error TS2531: Object is possibly 'null'. -src/discounts/views/VoucherDetails.tsx(511,31): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. -src/discounts/views/VoucherDetails.tsx(525,58): error TS2345: Argument of type 'string[] | undefined' is not assignable to parameter of type 'string[]'. -src/discounts/views/VoucherDetails.tsx(534,48): error TS2532: Object is possibly 'undefined'. -src/discounts/views/VoucherDetails.tsx(536,50): error TS2532: Object is possibly 'undefined'. -src/discounts/views/VoucherDetails.tsx(544,31): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. -src/discounts/views/VoucherDetails.tsx(558,59): error TS2345: Argument of type 'string[] | undefined' is not assignable to parameter of type 'string[]'. -src/discounts/views/VoucherDetails.tsx(567,48): error TS2532: Object is possibly 'undefined'. -src/discounts/views/VoucherDetails.tsx(569,50): error TS2532: Object is possibly 'undefined'. -src/discounts/views/VoucherDetails.tsx(577,31): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. -src/discounts/views/VoucherDetails.tsx(591,56): error TS2345: Argument of type 'string[] | undefined' is not assignable to parameter of type 'string[]'. -src/discounts/views/VoucherDetails.tsx(600,48): error TS2532: Object is possibly 'undefined'. -src/discounts/views/VoucherDetails.tsx(602,50): error TS2532: Object is possibly 'undefined'. -src/discounts/views/VoucherDetails.tsx(631,54): error TS2532: Object is possibly 'undefined'. -src/discounts/views/VoucherDetails.tsx(631,54): error TS2531: Object is possibly 'null'. -src/discounts/views/VoucherList/filters.ts(38,13): error TS2532: Object is possibly 'undefined'. -src/discounts/views/VoucherList/filters.ts(52,9): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/discounts/views/VoucherList/filters.ts(53,9): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/discounts/views/VoucherList/filters.ts(61,13): error TS2532: Object is possibly 'undefined'. -src/discounts/views/VoucherList/filters.ts(77,9): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/discounts/views/VoucherList/filters.ts(78,9): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/discounts/views/VoucherList/filters.ts(93,25): error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'. -src/discounts/views/VoucherList/filters.ts(94,25): error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'. -src/discounts/views/VoucherList/filters.ts(100,21): error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'. -src/discounts/views/VoucherList/filters.ts(101,21): error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'. -src/discounts/views/VoucherList/sort.ts(24,7): error TS2322: Type 'undefined' is not assignable to type 'VoucherSortField'. -src/discounts/views/VoucherList/VoucherList.tsx(97,5): error TS2322: Type '(params?: VoucherListUrlQueryParams | undefined) => string' is not assignable to type 'CreateUrl'. -src/discounts/views/VoucherList/VoucherList.tsx(129,47): error TS2532: Object is possibly 'undefined'. -src/discounts/views/VoucherList/VoucherList.tsx(132,5): error TS2345: Argument of type 'VoucherList_vouchers_pageInfo | undefined' is not assignable to parameter of type 'PageInfo'. -src/discounts/views/VoucherList/VoucherList.tsx(132,17): error TS2532: Object is possibly 'undefined'. -src/discounts/views/VoucherList/VoucherList.tsx(132,17): error TS2531: Object is possibly 'null'. -src/discounts/views/VoucherList/VoucherList.tsx(138,9): error TS2531: Object is possibly 'null'. -src/discounts/views/VoucherList/VoucherList.tsx(138,9): error TS2531: Object is possibly 'null'. -src/discounts/views/VoucherList/VoucherList.tsx(149,38): error TS2571: Object is of type 'unknown'. -src/discounts/views/VoucherList/VoucherList.tsx(155,29): error TS2345: Argument of type '{ variables: { ids: string[] | undefined; }; }' is not assignable to parameter of type 'MutationFunctionOptions'. -src/discounts/views/VoucherList/VoucherList.tsx(176,44): error TS2571: Object is of type 'unknown'. -src/discounts/views/VoucherList/VoucherList.tsx(178,15): error TS2322: Type 'VoucherList_vouchers_edges_node[] | undefined' is not assignable to type 'VoucherList_vouchers_edges_node[]'. -src/discounts/views/VoucherList/VoucherList.tsx(178,37): error TS2532: Object is possibly 'undefined'. -src/discounts/views/VoucherList/VoucherList.tsx(178,37): error TS2531: Object is possibly 'null'. -src/discounts/views/VoucherList/VoucherList.tsx(209,15): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. -src/discounts/views/VoucherList/VoucherList.tsx(222,32): error TS2532: Object is possibly 'undefined'. -src/discounts/views/VoucherList/VoucherList.tsx(223,49): error TS2532: Object is possibly 'undefined'. -src/fixtures.ts(20,5): error TS2322: Type 'undefined' is not assignable to type '() => void'. -src/fixtures.ts(21,5): error TS2322: Type 'undefined' is not assignable to type '() => void'. -src/fixtures.ts(22,5): error TS2322: Type 'undefined' is not assignable to type '() => void'. -src/fixtures.ts(23,23): error TS2322: Type 'undefined' is not assignable to type '() => void'. -src/fixtures.ts(29,5): error TS2322: Type 'undefined' is not assignable to type '() => void'. -src/fixtures.ts(30,5): error TS2322: Type 'undefined' is not assignable to type '() => void'. -src/fixtures.ts(31,5): error TS2322: Type 'undefined' is not assignable to type '() => void'. -src/fixtures.ts(32,23): error TS2322: Type 'undefined' is not assignable to type '() => void'. -src/fixtures.ts(38,20): error TS2322: Type 'undefined' is not assignable to type 'boolean'. -src/home/components/HomeActivityCard/activityMessages.ts(34,20): error TS2531: Object is possibly 'null'. -src/home/components/HomeProductListCard/HomeProductListCard.tsx(83,42): error TS2532: Object is possibly 'undefined'. -src/home/components/HomeProductListCard/HomeProductListCard.tsx(83,42): error TS2531: Object is possibly 'null'. -src/home/components/HomeProductListCard/HomeProductListCard.tsx(96,47): error TS2531: Object is possibly 'null'. -src/home/components/HomeProductListCard/HomeProductListCard.tsx(120,39): error TS2532: Object is possibly 'undefined'. -src/home/components/HomeProductListCard/HomeProductListCard.tsx(120,39): error TS2531: Object is possibly 'null'. -src/home/views/index.tsx(14,11): error TS2339: Property 'user' does not exist on type 'unknown'. -src/home/views/index.tsx(20,11): error TS2322: Type 'Home_activities_edges_node[] | undefined' is not assignable to type 'Home_activities_edges_node[]'. -src/home/views/index.tsx(21,13): error TS2532: Object is possibly 'undefined'. -src/home/views/index.tsx(21,13): error TS2531: Object is possibly 'null'. -src/home/views/index.tsx(23,11): error TS2322: Type 'number | null | undefined' is not assignable to type 'number'. -src/home/views/index.tsx(23,31): error TS2532: Object is possibly 'undefined'. -src/home/views/index.tsx(23,31): error TS2531: Object is possibly 'null'. -src/home/views/index.tsx(24,11): error TS2322: Type 'Home_salesToday_gross | undefined' is not assignable to type 'Home_salesToday_gross'. -src/home/views/index.tsx(24,30): error TS2532: Object is possibly 'undefined'. -src/home/views/index.tsx(24,30): error TS2531: Object is possibly 'null'. -src/home/views/index.tsx(25,11): error TS2322: Type 'Home_productTopToday_edges_node[] | undefined' is not assignable to type 'Home_productTopToday_edges_node[]'. -src/home/views/index.tsx(26,13): error TS2532: Object is possibly 'undefined'. -src/home/views/index.tsx(26,13): error TS2531: Object is possibly 'null'. -src/home/views/index.tsx(55,11): error TS2322: Type 'number | null | undefined' is not assignable to type 'number'. -src/home/views/index.tsx(55,40): error TS2532: Object is possibly 'undefined'. -src/home/views/index.tsx(55,40): error TS2531: Object is possibly 'null'. -src/home/views/index.tsx(56,11): error TS2322: Type 'number | null | undefined' is not assignable to type 'number'. -src/home/views/index.tsx(56,40): error TS2532: Object is possibly 'undefined'. -src/home/views/index.tsx(56,40): error TS2531: Object is possibly 'null'. -src/home/views/index.tsx(57,11): error TS2322: Type 'number | null | undefined' is not assignable to type 'number'. -src/home/views/index.tsx(57,43): error TS2532: Object is possibly 'undefined'. -src/home/views/index.tsx(57,43): error TS2531: Object is possibly 'null'. -src/home/views/index.tsx(58,11): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/hooks/makeMutation.ts(42,15): error TS2532: Object is possibly 'undefined'. -src/hooks/makeQuery.ts(66,25): error TS2532: Object is possibly 'undefined'. -src/hooks/makeSearch.ts(41,7): error TS2322: Type '(TVariables & { query: string; }) | { query: string; }' is not assignable to type 'TVariables | undefined'. -src/hooks/makeTopLevelSearch.ts(20,9): error TS2532: Object is possibly 'undefined'. -src/hooks/makeTopLevelSearch.ts(40,18): error TS2532: Object is possibly 'undefined'. -src/hooks/useClipboard.ts(9,20): error TS2769: No overload matches this call. -src/hooks/useClipboard.ts(17,7): error TS2322: Type 'Timeout' is not assignable to type 'null'. -src/hooks/useDebounce.ts(9,38): error TS2769: No overload matches this call. -src/hooks/useDebounce.ts(13,20): error TS2769: No overload matches this call. -src/hooks/useDebounce.ts(16,5): error TS2322: Type 'Timeout' is not assignable to type 'null'. -src/hooks/useElementScroll.ts(13,3): error TS2322: Type 'undefined' is not assignable to type 'Record<"x" | "y", number>'. -src/hooks/useFormset.ts(28,5): error TS2322: Type 'FormsetAtomicData | undefined' is not assignable to type 'FormsetAtomicData'. -src/hooks/useMultiAutocomplete.ts(17,26): error TS2532: Object is possibly 'undefined'. -src/hooks/useNotifier.ts(8,3): error TS2322: Type 'unknown' is not assignable to type 'IMessageContext'. -src/mutations.tsx(40,17): error TS2532: Object is possibly 'undefined'. -src/navigation/components/MenuDetailsPage/MenuDetailsPage.tsx(107,31): error TS2345: Argument of type '(MenuDetails_menu_items | null)[] | null' is not assignable to parameter of type 'MenuDetails_menu_items[]'. -src/navigation/components/MenuDetailsPage/tree.test.ts(15,5): error TS2531: Object is possibly 'null'. -src/navigation/components/MenuDetailsPage/tree.test.ts(16,46): error TS2345: Argument of type 'MenuDetails_menu_items_children | null' is not assignable to parameter of type 'MenuDetails_menu_items'. -src/navigation/components/MenuDetailsPage/tree.test.ts(181,40): error TS2345: Argument of type '(MenuDetails_menu_items | null)[] | null' is not assignable to parameter of type 'MenuDetails_menu_items[]'. -src/navigation/components/MenuDetailsPage/tree.ts(7,13): error TS2322: Type 'null' is not assignable to type 'number'. -src/navigation/components/MenuDetailsPage/tree.ts(14,17): error TS2345: Argument of type '(MenuDetails_menu_items_children | null)[] | null' is not assignable to parameter of type 'MenuDetails_menu_items[]'. -src/navigation/components/MenuDetailsPage/tree.ts(26,22): error TS2569: Type '(MenuDetails_menu_items_children | null)[] | null' is not an array type or a string type. Use compiler option '--downlevelIteration' to allow iterating of iterators. -src/navigation/components/MenuDetailsPage/tree.ts(42,26): error TS2345: Argument of type '(MenuDetails_menu_items_children | null)[] | null' is not assignable to parameter of type 'MenuDetails_menu_items[]'. -src/navigation/components/MenuDetailsPage/tree.ts(60,7): error TS2345: Argument of type '(MenuDetails_menu_items_children | null)[] | null' is not assignable to parameter of type 'MenuDetails_menu_items[]'. -src/navigation/components/MenuDetailsPage/tree.ts(80,15): error TS2531: Object is possibly 'null'. -src/navigation/components/MenuDetailsPage/tree.ts(109,5): error TS2345: Argument of type 'number | undefined' is not assignable to parameter of type 'number'. -src/navigation/components/MenuItemDialog/MenuItemDialog.tsx(73,10): error TS2533: Object is possibly 'null' or 'undefined'. -src/navigation/components/MenuItemDialog/MenuItemDialog.tsx(99,48): error TS2345: Argument of type 'undefined' is not assignable to parameter of type 'string | (() => string)'. -src/navigation/components/MenuItemDialog/MenuItemDialog.tsx(105,23): error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'SetStateAction'. -src/navigation/components/MenuItemDialog/MenuItemDialog.tsx(111,41): error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'SetStateAction'. -src/navigation/components/MenuItems/MenuItems.tsx(234,9): error TS2322: Type '{ minHeight: number; padding: boolean; paddingTop: boolean; }' is not assignable to type 'CSSProperties'. -src/navigation/components/MenuItems/tree.test.ts(42,28): error TS2531: Object is possibly 'null'. -src/navigation/components/MenuItems/tree.ts(71,9): error TS2322: Type '({ id: string; parentId: string | undefined; sortOrder: number; type: TreeOperationType; } | undefined)[]' is not assignable to type 'TreeOperation[]'. -src/navigation/components/MenuItems/tree.ts(90,3): error TS2322: Type 'TreeOperation | undefined' is not assignable to type 'TreeOperation'. -src/navigation/components/MenuItems/tree.ts(100,15): error TS2531: Object is possibly 'null'. -src/navigation/components/MenuItems/tree.ts(101,19): error TS2345: Argument of type 'MenuDetails_menu_items_children | null' is not assignable to parameter of type 'MenuDetails_menu_items'. -src/navigation/components/MenuItems/tree.ts(114,42): error TS2345: Argument of type '(MenuDetails_menu_items_children | null)[] | null' is not assignable to parameter of type 'MenuDetails_menu_items[]'. -src/navigation/components/MenuList/MenuList.tsx(91,37): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/navigation/components/MenuList/MenuList.tsx(106,37): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/navigation/components/MenuList/MenuList.tsx(155,46): error TS2532: Object is possibly 'undefined'. -src/navigation/components/MenuList/MenuList.tsx(159,51): error TS2532: Object is possibly 'undefined'. -src/navigation/components/MenuList/MenuList.tsx(163,29): error TS2532: Object is possibly 'undefined'. -src/navigation/components/MenuList/MenuList.tsx(163,29): error TS2531: Object is possibly 'null'. -src/navigation/components/MenuList/MenuList.tsx(169,45): error TS2532: Object is possibly 'undefined'. -src/navigation/views/MenuDetails/index.tsx(155,27): error TS2532: Object is possibly 'undefined'. -src/navigation/views/MenuDetails/index.tsx(155,27): error TS2531: Object is possibly 'null'. -src/navigation/views/MenuDetails/index.tsx(155,27): error TS2531: Object is possibly 'null'. -src/navigation/views/MenuDetails/index.tsx(156,27): error TS2532: Object is possibly 'undefined'. -src/navigation/views/MenuDetails/index.tsx(156,27): error TS2531: Object is possibly 'null'. -src/navigation/views/MenuDetails/index.tsx(156,27): error TS2531: Object is possibly 'null'. -src/navigation/views/MenuDetails/index.tsx(157,27): error TS2532: Object is possibly 'undefined'. -src/navigation/views/MenuDetails/index.tsx(157,27): error TS2531: Object is possibly 'null'. -src/navigation/views/MenuDetails/index.tsx(157,27): error TS2531: Object is possibly 'null'. -src/navigation/views/MenuDetails/index.tsx(172,25): error TS2322: Type 'MenuDetails_menu | null | undefined' is not assignable to type 'MenuDetails_menu'. -src/navigation/views/MenuDetails/index.tsx(172,43): error TS2532: Object is possibly 'undefined'. -src/navigation/views/MenuDetails/index.tsx(219,48): error TS2532: Object is possibly 'undefined'. -src/navigation/views/MenuDetails/index.tsx(219,48): error TS2531: Object is possibly 'null'. -src/navigation/views/MenuDetails/index.tsx(248,31): error TS2322: Type 'MenuItemCreate_menuItemCreate_errors[] | null' is not assignable to type 'UserError[]'. -src/navigation/views/MenuDetails/index.tsx(250,35): error TS2532: Object is possibly 'undefined'. -src/navigation/views/MenuDetails/index.tsx(250,35): error TS2531: Object is possibly 'null'. -src/navigation/views/MenuDetails/index.tsx(277,31): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/navigation/views/MenuDetails/index.tsx(286,31): error TS2532: Object is possibly 'undefined'. -src/navigation/views/MenuDetails/index.tsx(286,31): error TS2531: Object is possibly 'null'. -src/navigation/views/MenuDetails/index.tsx(286,31): error TS2345: Argument of type '(MenuDetails_menu_items | null)[] | null' is not assignable to parameter of type 'MenuDetails_menu_items[]'. -src/navigation/views/MenuDetails/index.tsx(287,40): error TS2532: Object is possibly 'undefined'. -src/navigation/views/MenuDetails/index.tsx(287,40): error TS2531: Object is possibly 'null'. -src/navigation/views/MenuDetails/index.tsx(287,40): error TS2345: Argument of type '(MenuDetails_menu_items | null)[] | null' is not assignable to parameter of type 'MenuDetails_menu_items[]'. -src/navigation/views/MenuDetails/index.tsx(292,29): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/navigation/views/MenuDetails/index.tsx(305,31): error TS2322: Type 'MenuItemUpdate_menuItemUpdate_errors[] | null' is not assignable to type 'UserError[]'. -src/navigation/views/MenuDetails/index.tsx(307,35): error TS2532: Object is possibly 'undefined'. -src/navigation/views/MenuDetails/index.tsx(307,35): error TS2531: Object is possibly 'null'. -src/navigation/views/MenuDetails/successHandlers.ts(18,7): error TS2531: Object is possibly 'null'. -src/navigation/views/MenuDetails/successHandlers.ts(18,7): error TS2531: Object is possibly 'null'. -src/navigation/views/MenuDetails/successHandlers.ts(33,7): error TS2531: Object is possibly 'null'. -src/navigation/views/MenuDetails/successHandlers.ts(33,7): error TS2531: Object is possibly 'null'. -src/navigation/views/MenuDetails/successHandlers.ts(52,7): error TS2531: Object is possibly 'null'. -src/navigation/views/MenuDetails/successHandlers.ts(52,7): error TS2531: Object is possibly 'null'. -src/navigation/views/MenuDetails/successHandlers.ts(67,5): error TS2531: Object is possibly 'null'. -src/navigation/views/MenuDetails/successHandlers.ts(67,5): error TS2531: Object is possibly 'null'. -src/navigation/views/MenuDetails/successHandlers.ts(68,5): error TS2531: Object is possibly 'null'. -src/navigation/views/MenuDetails/successHandlers.ts(68,5): error TS2531: Object is possibly 'null'. -src/navigation/views/MenuDetails/successHandlers.ts(69,5): error TS2531: Object is possibly 'null'. -src/navigation/views/MenuDetails/successHandlers.ts(69,5): error TS2531: Object is possibly 'null'. -src/navigation/views/MenuList/MenuList.tsx(74,5): error TS2345: Argument of type 'MenuList_menus_pageInfo | undefined' is not assignable to parameter of type 'PageInfo'. -src/navigation/views/MenuList/MenuList.tsx(74,17): error TS2532: Object is possibly 'undefined'. -src/navigation/views/MenuList/MenuList.tsx(74,17): error TS2531: Object is possibly 'null'. -src/navigation/views/MenuList/MenuList.tsx(80,9): error TS2531: Object is possibly 'null'. -src/navigation/views/MenuList/MenuList.tsx(80,9): error TS2531: Object is possibly 'null'. -src/navigation/views/MenuList/MenuList.tsx(87,24): error TS2531: Object is possibly 'null'. -src/navigation/views/MenuList/MenuList.tsx(87,24): error TS2531: Object is possibly 'null'. -src/navigation/views/MenuList/MenuList.tsx(92,9): error TS2531: Object is possibly 'null'. -src/navigation/views/MenuList/MenuList.tsx(92,9): error TS2531: Object is possibly 'null'. -src/navigation/views/MenuList/MenuList.tsx(103,9): error TS2531: Object is possibly 'null'. -src/navigation/views/MenuList/MenuList.tsx(103,9): error TS2531: Object is possibly 'null'. -src/navigation/views/MenuList/MenuList.tsx(127,21): error TS2322: Type 'MenuList_menus_edges_node[] | undefined' is not assignable to type 'MenuList_menus_edges_node[]'. -src/navigation/views/MenuList/MenuList.tsx(127,40): error TS2532: Object is possibly 'undefined'. -src/navigation/views/MenuList/MenuList.tsx(127,40): error TS2531: Object is possibly 'null'. -src/navigation/views/MenuList/MenuList.tsx(177,21): error TS2322: Type 'MenuCreate_menuCreate_errors[]' is not assignable to type 'UserError[]'. -src/navigation/views/MenuList/MenuList.tsx(177,29): error TS2531: Object is possibly 'null'. -src/navigation/views/MenuList/MenuList.tsx(190,34): error TS2345: Argument of type '{ variables: { id: string | undefined; }; }' is not assignable to parameter of type 'MutationFunctionOptions'. -src/navigation/views/MenuList/MenuList.tsx(210,31): error TS2532: Object is possibly 'undefined'. -src/navigation/views/MenuList/MenuList.tsx(210,31): error TS2531: Object is possibly 'null'. -src/navigation/views/MenuList/MenuList.tsx(210,31): error TS2532: Object is possibly 'undefined'. -src/navigation/views/MenuList/MenuList.tsx(220,21): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. -src/navigation/views/MenuList/MenuList.tsx(222,35): error TS2532: Object is possibly 'undefined'. -src/navigation/views/MenuList/MenuList.tsx(227,38): error TS2345: Argument of type '{ variables: { ids: string[] | undefined; }; }' is not assignable to parameter of type 'MutationFunctionOptions'. -src/navigation/views/MenuList/MenuList.tsx(246,35): error TS2532: Object is possibly 'undefined'. -src/navigation/views/MenuList/MenuList.tsx(251,44): error TS2532: Object is possibly 'undefined'. -src/navigation/views/MenuList/sort.ts(12,7): error TS2322: Type 'undefined' is not assignable to type 'MenuSortField'. -src/orders/components/OrderAddressEditDialog/OrderAddressEditDialog.tsx(64,13): error TS2532: Object is possibly 'undefined'. -src/orders/components/OrderAddressEditDialog/OrderAddressEditDialog.tsx(64,13): error TS2532: Object is possibly 'undefined'. -src/orders/components/OrderAddressEditDialog/OrderAddressEditDialog.tsx(76,26): error TS2532: Object is possibly 'undefined'. -src/orders/components/OrderAddressEditDialog/OrderAddressEditDialog.tsx(107,19): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/orders/components/OrderCustomer/OrderCustomer.tsx(90,17): error TS2533: Object is possibly 'null' or 'undefined'. -src/orders/components/OrderCustomer/OrderCustomer.tsx(133,17): error TS2722: Cannot invoke an object which is possibly 'undefined'. -src/orders/components/OrderCustomer/OrderCustomer.tsx(138,35): error TS2532: Object is possibly 'undefined'. -src/orders/components/OrderCustomer/OrderCustomer.tsx(326,25): error TS2533: Object is possibly 'null' or 'undefined'. -src/orders/components/OrderDetailsPage/OrderDetailsPage.tsx(93,13): error TS2531: Object is possibly 'null'. -src/orders/components/OrderDetailsPage/OrderDetailsPage.tsx(93,38): error TS2531: Object is possibly 'null'. -src/orders/components/OrderDetailsPage/OrderDetailsPage.tsx(134,15): error TS2322: Type '(OrderDetails_order_lines | null)[]' is not assignable to type 'OrderDetails_order_lines[]'. -src/orders/components/OrderDetailsPage/OrderDetailsPage.tsx(139,13): error TS2345: Argument of type '(OrderDetails_order_fulfillments | null)[] | undefined' is not assignable to parameter of type '(OrderDetails_order_fulfillments | null)[]'. -src/orders/components/OrderDetailsPage/OrderDetailsPage.tsx(147,19): error TS2322: Type 'string | null | undefined' is not assignable to type 'string'. -src/orders/components/OrderDetailsPage/OrderDetailsPage.tsx(167,13): error TS2322: Type '(OrderDetails_order_events | null)[] | null | undefined' is not assignable to type 'OrderDetails_order_events[]'. -src/orders/components/OrderDetailsPage/OrderDetailsPage.tsx(182,30): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/orders/components/OrderDraftDetails/OrderDraftDetails.tsx(52,9): error TS2322: Type '(OrderDetails_order_lines | null)[] | undefined' is not assignable to type 'OrderDetails_order_lines[]'. -src/orders/components/OrderDraftDetailsProducts/OrderDraftDetailsProducts.tsx(125,40): error TS2532: Object is possibly 'undefined'. -src/orders/components/OrderDraftDetailsProducts/OrderDraftDetailsProducts.tsx(125,40): error TS2531: Object is possibly 'null'. -src/orders/components/OrderDraftDetailsProducts/OrderDraftDetailsProducts.tsx(127,30): error TS2532: Object is possibly 'undefined'. -src/orders/components/OrderDraftDetailsProducts/OrderDraftDetailsProducts.tsx(127,50): error TS2532: Object is possibly 'undefined'. -src/orders/components/OrderDraftDetailsProducts/OrderDraftDetailsProducts.tsx(129,50): error TS2532: Object is possibly 'undefined'. -src/orders/components/OrderDraftDetailsProducts/OrderDraftDetailsProducts.tsx(130,52): error TS2532: Object is possibly 'undefined'. -src/orders/components/OrderDraftDetailsProducts/OrderDraftDetailsProducts.tsx(137,30): error TS2532: Object is possibly 'undefined'. -src/orders/components/OrderDraftDetailsProducts/OrderDraftDetailsProducts.tsx(139,42): error TS2532: Object is possibly 'undefined'. -src/orders/components/OrderDraftDetailsProducts/OrderDraftDetailsProducts.tsx(140,57): error TS2532: Object is possibly 'undefined'. -src/orders/components/OrderDraftDetailsProducts/OrderDraftDetailsProducts.tsx(145,25): error TS2322: Type '(() => void) | undefined' is not assignable to type '(event: FormEvent) => void'. -src/orders/components/OrderDraftDetailsProducts/OrderDraftDetailsProducts.tsx(166,30): error TS2532: Object is possibly 'undefined'. -src/orders/components/OrderDraftDetailsProducts/OrderDraftDetailsProducts.tsx(166,30): error TS2531: Object is possibly 'null'. -src/orders/components/OrderDraftDetailsProducts/OrderDraftDetailsProducts.tsx(167,33): error TS2532: Object is possibly 'undefined'. -src/orders/components/OrderDraftDetailsProducts/OrderDraftDetailsProducts.tsx(167,33): error TS2531: Object is possibly 'null'. -src/orders/components/OrderDraftDetailsProducts/OrderDraftDetailsProducts.tsx(173,30): error TS2532: Object is possibly 'undefined'. -src/orders/components/OrderDraftDetailsProducts/OrderDraftDetailsProducts.tsx(173,30): error TS2531: Object is possibly 'null'. -src/orders/components/OrderDraftDetailsProducts/OrderDraftDetailsProducts.tsx(173,52): error TS2532: Object is possibly 'undefined'. -src/orders/components/OrderDraftDetailsProducts/OrderDraftDetailsProducts.tsx(176,31): error TS2532: Object is possibly 'undefined'. -src/orders/components/OrderDraftDetailsProducts/OrderDraftDetailsProducts.tsx(176,31): error TS2531: Object is possibly 'null'. -src/orders/components/OrderDraftDetailsProducts/OrderDraftDetailsProducts.tsx(176,59): error TS2532: Object is possibly 'undefined'. -src/orders/components/OrderDraftDetailsProducts/OrderDraftDetailsProducts.tsx(177,33): error TS2532: Object is possibly 'undefined'. -src/orders/components/OrderDraftDetailsProducts/OrderDraftDetailsProducts.tsx(177,33): error TS2531: Object is possibly 'null'. -src/orders/components/OrderDraftDetailsProducts/OrderDraftDetailsProducts.tsx(185,62): error TS2532: Object is possibly 'undefined'. -src/orders/components/OrderDraftDetailsSummary/OrderDraftDetailsSummary.tsx(50,31): error TS2531: Object is possibly 'null'. -src/orders/components/OrderDraftDetailsSummary/OrderDraftDetailsSummary.tsx(88,35): error TS2531: Object is possibly 'null'. -src/orders/components/OrderDraftDetailsSummary/OrderDraftDetailsSummary.tsx(102,24): error TS2531: Object is possibly 'null'. -src/orders/components/OrderDraftDetailsSummary/OrderDraftDetailsSummary.tsx(108,31): error TS2531: Object is possibly 'null'. -src/orders/components/OrderDraftDetailsSummary/OrderDraftDetailsSummary.tsx(118,24): error TS2531: Object is possibly 'null'. -src/orders/components/OrderDraftDetailsSummary/OrderDraftDetailsSummary.tsx(127,31): error TS2531: Object is possibly 'null'. -src/orders/components/OrderDraftList/OrderDraftList.tsx(91,47): error TS2345: Argument of type 'PaymentChargeStatusEnum | null' is not assignable to parameter of type 'string'. -src/orders/components/OrderDraftList/OrderDraftList.tsx(109,35): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/orders/components/OrderDraftList/OrderDraftList.tsx(121,35): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/orders/components/OrderDraftList/OrderDraftList.tsx(135,35): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/orders/components/OrderDraftList/OrderDraftList.tsx(146,35): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/orders/components/OrderDraftList/OrderDraftList.tsx(176,11): error TS2345: Argument of type '{ paymentStatus: any; status: { localized: string; status: string; }; __typename: "Order"; billingAddress: OrderDraftList_draftOrders_edges_node_billingAddress | null; ... 4 more ...; userEmail: string | null; }[] | undefined' is not assignable to parameter of type '{ paymentStatus: any; status: { localized: string; status: string; }; __typename: "Order"; billingAddress: OrderDraftList_draftOrders_edges_node_billingAddress | null; ... 4 more ...; userEmail: string | null; }[]'. -src/orders/components/OrderDraftPage/OrderDraftPage.tsx(139,13): error TS2322: Type '(OrderDetails_order_events | null)[] | null | undefined' is not assignable to type 'OrderDetails_order_events[]'. -src/orders/components/OrderFulfillment/OrderFulfillment.tsx(87,25): error TS2531: Object is possibly 'null'. -src/orders/components/OrderFulfillment/OrderFulfillment.tsx(180,29): error TS2345: Argument of type '(OrderDetails_order_fulfillments_lines | null)[] | null | undefined' is not assignable to parameter of type '(OrderDetails_order_fulfillments_lines | null)[]'. -src/orders/components/OrderFulfillmentDialog/OrderFulfillmentDialog.tsx(147,50): error TS2531: Object is possibly 'null'. -src/orders/components/OrderHistory/OrderHistory.tsx(226,21): error TS2322: Type 'OrderDetails_order_events_user | null' is not assignable to type '{ email: string; }'. -src/orders/components/OrderHistory/OrderHistory.tsx(235,19): error TS2322: Type 'string | null | undefined' is not assignable to type 'string'. -src/orders/components/OrderList/OrderList.tsx(96,47): error TS2345: Argument of type 'PaymentChargeStatusEnum | null' is not assignable to parameter of type 'string'. -src/orders/components/OrderList/OrderList.tsx(113,35): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/orders/components/OrderList/OrderList.tsx(125,35): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/orders/components/OrderList/OrderList.tsx(139,35): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/orders/components/OrderList/OrderList.tsx(153,35): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/orders/components/OrderList/OrderList.tsx(167,35): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/orders/components/OrderList/OrderList.tsx(178,35): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/orders/components/OrderList/OrderList.tsx(208,11): error TS2345: Argument of type '{ paymentStatus: any; status: { localized: string; status: string; }; __typename: "Order"; billingAddress: OrderList_orders_edges_node_billingAddress | null; ... 4 more ...; userEmail: string | null; }[] | undefined' is not assignable to parameter of type '{ paymentStatus: any; status: { localized: string; status: string; }; __typename: "Order"; billingAddress: OrderList_orders_edges_node_billingAddress | null; ... 4 more ...; userEmail: string | null; }[]'. -src/orders/components/OrderPayment/OrderPayment.tsx(58,5): error TS2345: Argument of type 'PaymentChargeStatusEnum | null | undefined' is not assignable to parameter of type 'string'. -src/orders/components/OrderPayment/OrderPayment.tsx(91,38): error TS2531: Object is possibly 'null'. -src/orders/components/OrderPayment/OrderPayment.tsx(98,30): error TS2531: Object is possibly 'null'. -src/orders/components/OrderPayment/OrderPayment.tsx(101,33): error TS2531: Object is possibly 'null'. -src/orders/components/OrderPayment/OrderPayment.tsx(110,30): error TS2531: Object is possibly 'null'. -src/orders/components/OrderPayment/OrderPayment.tsx(112,21): error TS2531: Object is possibly 'null'. -src/orders/components/OrderPayment/OrderPayment.tsx(126,30): error TS2531: Object is possibly 'null'. -src/orders/components/OrderPayment/OrderPayment.tsx(129,33): error TS2531: Object is possibly 'null'. -src/orders/components/OrderPayment/OrderPayment.tsx(155,30): error TS2531: Object is possibly 'null'. -src/orders/components/OrderPayment/OrderPayment.tsx(158,33): error TS2531: Object is possibly 'null'. -src/orders/components/OrderPayment/OrderPayment.tsx(171,30): error TS2531: Object is possibly 'null'. -src/orders/components/OrderPayment/OrderPayment.tsx(174,33): error TS2531: Object is possibly 'null'. -src/orders/components/OrderPayment/OrderPayment.tsx(193,30): error TS2531: Object is possibly 'null'. -src/orders/components/OrderPayment/OrderPayment.tsx(196,26): error TS2322: Type 'OrderDetails_order_totalAuthorized | null' is not assignable to type 'IMoney'. -src/orders/components/OrderPayment/OrderPayment.tsx(208,30): error TS2531: Object is possibly 'null'. -src/orders/components/OrderPayment/OrderPayment.tsx(211,26): error TS2322: Type 'OrderDetails_order_totalCaptured | null' is not assignable to type 'IMoney'. -src/orders/components/OrderPayment/OrderPayment.tsx(224,25): error TS2531: Object is possibly 'null'. -src/orders/components/OrderPayment/OrderPayment.tsx(224,53): error TS2531: Object is possibly 'null'. -src/orders/components/OrderPayment/OrderPayment.tsx(230,23): error TS2345: Argument of type 'OrderDetails_order_totalCaptured | null' is not assignable to parameter of type 'IMoney'. -src/orders/components/OrderPayment/OrderPayment.tsx(231,23): error TS2531: Object is possibly 'null'. -src/orders/components/OrderProductAddDialog/OrderProductAddDialog.tsx(125,14): error TS2531: Object is possibly 'null'. -src/orders/components/OrderProductAddDialog/OrderProductAddDialog.tsx(126,33): error TS2531: Object is possibly 'null'. -src/orders/components/OrderProductAddDialog/OrderProductAddDialog.tsx(130,19): error TS2345: Argument of type '(SearchOrderVariant_search_edges_node_variants | null)[]' is not assignable to parameter of type 'SearchOrderVariant_search_edges_node_variants[]'. -src/orders/components/OrderProductAddDialog/OrderProductAddDialog.tsx(132,12): error TS2531: Object is possibly 'null'. -src/orders/components/OrderProductAddDialog/OrderProductAddDialog.tsx(135,57): error TS2531: Object is possibly 'null'. -src/orders/components/OrderProductAddDialog/OrderProductAddDialog.tsx(176,9): error TS2531: Object is possibly 'null'. -src/orders/components/OrderProductAddDialog/OrderProductAddDialog.tsx(176,59): error TS2345: Argument of type 'SearchOrderVariant_search_edges_node_variants | null' is not assignable to parameter of type 'SearchOrderVariant_search_edges_node_variants'. -src/orders/components/OrderProductAddDialog/OrderProductAddDialog.tsx(181,32): error TS2345: Argument of type '(SearchOrderVariant_search_edges_node_variants | null)[] | null' is not assignable to parameter of type 'SearchOrderVariant_search_edges_node_variants[]'. -src/orders/components/OrderProductAddDialog/OrderProductAddDialog.tsx(246,61): error TS2538: Type 'undefined' cannot be used as an index type. -src/orders/components/OrderProductAddDialog/OrderProductAddDialog.tsx(251,31): error TS2345: Argument of type 'SearchOrderVariant_search_edges_node | undefined' is not assignable to parameter of type 'SearchOrderVariant_search_edges_node'. -src/orders/components/OrderProductAddDialog/OrderProductAddDialog.tsx(262,48): error TS2532: Object is possibly 'undefined'. -src/orders/components/OrderProductAddDialog/OrderProductAddDialog.tsx(262,48): error TS2531: Object is possibly 'null'. -src/orders/components/OrderProductAddDialog/OrderProductAddDialog.tsx(265,38): error TS2532: Object is possibly 'undefined'. -src/orders/components/OrderProductAddDialog/OrderProductAddDialog.tsx(268,22): error TS2531: Object is possibly 'null'. -src/orders/components/OrderProductAddDialog/OrderProductAddDialog.tsx(268,34): error TS2532: Object is possibly 'undefined'. -src/orders/components/OrderProductAddDialog/OrderProductAddDialog.tsx(270,40): error TS2531: Object is possibly 'null'. -src/orders/components/OrderProductAddDialog/OrderProductAddDialog.tsx(276,63): error TS2538: Type 'undefined' cannot be used as an index type. -src/orders/components/OrderProductAddDialog/OrderProductAddDialog.tsx(283,35): error TS2345: Argument of type 'SearchOrderVariant_search_edges_node_variants | null' is not assignable to parameter of type 'SearchOrderVariant_search_edges_node_variants'. -src/orders/components/OrderProductAddDialog/OrderProductAddDialog.tsx(294,35): error TS2531: Object is possibly 'null'. -src/orders/components/OrderProductAddDialog/OrderProductAddDialog.tsx(300,40): error TS2531: Object is possibly 'null'. -src/orders/components/OrderProductAddDialog/OrderProductAddDialog.tsx(307,38): error TS2531: Object is possibly 'null'. -src/orders/components/OrderProductAddDialog/OrderProductAddDialog.tsx(307,38): error TS2531: Object is possibly 'null'. -src/orders/components/OrderProductAddDialog/OrderProductAddDialog.tsx(307,38): error TS2531: Object is possibly 'null'. -src/orders/components/OrderShippingMethodEditDialog/OrderShippingMethodEditDialog.tsx(77,22): error TS2322: Type 'OrderDetails_order_availableShippingMethods_price | null' is not assignable to type 'IMoney'. -src/orders/components/OrderUnfulfilledItems/OrderUnfulfilledItems.tsx(129,40): error TS2531: Object is possibly 'null'. -src/orders/components/OrderUnfulfilledItems/OrderUnfulfilledItems.tsx(139,30): error TS2531: Object is possibly 'null'. -src/orders/components/OrderUnfulfilledItems/OrderUnfulfilledItems.tsx(140,33): error TS2531: Object is possibly 'null'. -src/orders/components/OrderUnfulfilledItems/OrderUnfulfilledItems.tsx(149,21): error TS2531: Object is possibly 'null'. -src/orders/components/OrderUnfulfilledItems/OrderUnfulfilledItems.tsx(155,25): error TS2531: Object is possibly 'null'. -src/orders/components/OrderUnfulfilledItems/OrderUnfulfilledItems.tsx(156,33): error TS2531: Object is possibly 'null'. -src/orders/fixtures.ts(1142,41): error TS2345: Argument of type 'PaymentChargeStatusEnum | null' is not assignable to parameter of type 'string'. -src/orders/queries.ts(327,3): error TS2344: Type 'SearchOrderVariant' does not satisfy the constraint 'SearchData'. -src/orders/views/OrderDetails/index.tsx(55,32): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/index.tsx(63,32): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/index.tsx(78,11): error TS2339: Property 'user' does not exist on type 'unknown'. -src/orders/views/OrderDetails/index.tsx(161,34): error TS2532: Object is possibly 'undefined'. -src/orders/views/OrderDetails/index.tsx(164,27): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/orders/views/OrderDetails/index.tsx(164,58): error TS2532: Object is possibly 'undefined'. -src/orders/views/OrderDetails/index.tsx(164,58): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/index.tsx(174,27): error TS2322: Type 'OrderDetails_order | undefined' is not assignable to type 'OrderDetails_order'. -src/orders/views/OrderDetails/index.tsx(175,27): error TS2322: Type '(OrderDetails_order_availableShippingMethods | null)[] | null' is not assignable to type '{ id: string; name: string; }[] | undefined'. -src/orders/views/OrderDetails/index.tsx(176,35): error TS2532: Object is possibly 'undefined'. -src/orders/views/OrderDetails/index.tsx(176,35): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/index.tsx(210,50): error TS2532: Object is possibly 'undefined'. -src/orders/views/OrderDetails/index.tsx(210,50): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/index.tsx(217,29): error TS2345: Argument of type 'OrderCancel_orderCancel_errors[] | null | undefined' is not assignable to parameter of type 'UserError[]'. -src/orders/views/OrderDetails/index.tsx(218,37): error TS2532: Object is possibly 'undefined'. -src/orders/views/OrderDetails/index.tsx(218,37): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/index.tsx(221,27): error TS2322: Type 'string | null | undefined' is not assignable to type 'string'. -src/orders/views/OrderDetails/index.tsx(221,47): error TS2532: Object is possibly 'undefined'. -src/orders/views/OrderDetails/index.tsx(235,29): error TS2345: Argument of type 'OrderMarkAsPaid_orderMarkAsPaid_errors[] | null | undefined' is not assignable to parameter of type 'UserError[]'. -src/orders/views/OrderDetails/index.tsx(237,33): error TS2532: Object is possibly 'undefined'. -src/orders/views/OrderDetails/index.tsx(237,33): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/index.tsx(253,29): error TS2345: Argument of type 'OrderVoid_orderVoid_errors[] | null | undefined' is not assignable to parameter of type 'UserError[]'. -src/orders/views/OrderDetails/index.tsx(253,41): error TS2532: Object is possibly 'undefined'. -src/orders/views/OrderDetails/index.tsx(253,41): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/index.tsx(263,29): error TS2345: Argument of type 'OrderCapture_orderCapture_errors[] | null | undefined' is not assignable to parameter of type 'UserError[]'. -src/orders/views/OrderDetails/index.tsx(265,33): error TS2532: Object is possibly 'undefined'. -src/orders/views/OrderDetails/index.tsx(265,33): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/index.tsx(269,27): error TS2322: Type 'number | undefined' is not assignable to type 'number'. -src/orders/views/OrderDetails/index.tsx(269,48): error TS2532: Object is possibly 'undefined'. -src/orders/views/OrderDetails/index.tsx(269,48): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/index.tsx(284,29): error TS2345: Argument of type 'OrderRefund_orderRefund_errors[] | null | undefined' is not assignable to parameter of type 'UserError[]'. -src/orders/views/OrderDetails/index.tsx(286,33): error TS2532: Object is possibly 'undefined'. -src/orders/views/OrderDetails/index.tsx(286,33): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/index.tsx(289,27): error TS2322: Type 'number | undefined' is not assignable to type 'number'. -src/orders/views/OrderDetails/index.tsx(289,48): error TS2532: Object is possibly 'undefined'. -src/orders/views/OrderDetails/index.tsx(289,48): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/index.tsx(304,29): error TS2345: Argument of type 'OrderCreateFulfillment_orderFulfillmentCreate_errors[] | null | undefined' is not assignable to parameter of type 'UserError[]'. -src/orders/views/OrderDetails/index.tsx(306,33): error TS2532: Object is possibly 'undefined'. -src/orders/views/OrderDetails/index.tsx(306,33): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/index.tsx(311,27): error TS2322: Type '(OrderDetails_order_lines | null)[]' is not assignable to type 'OrderDetails_order_lines[]'. -src/orders/views/OrderDetails/index.tsx(311,46): error TS2532: Object is possibly 'undefined'. -src/orders/views/OrderDetails/index.tsx(312,37): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/index.tsx(312,62): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/index.tsx(319,52): error TS2532: Object is possibly 'undefined'. -src/orders/views/OrderDetails/index.tsx(322,39): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/index.tsx(322,64): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/index.tsx(325,50): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/index.tsx(330,38): error TS2532: Object is possibly 'undefined'. -src/orders/views/OrderDetails/index.tsx(338,29): error TS2345: Argument of type 'OrderFulfillmentCancel_orderFulfillmentCancel_errors[] | null | undefined' is not assignable to parameter of type 'UserError[]'. -src/orders/views/OrderDetails/index.tsx(340,33): error TS2532: Object is possibly 'undefined'. -src/orders/views/OrderDetails/index.tsx(340,33): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/index.tsx(347,31): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/orders/views/OrderDetails/index.tsx(357,29): error TS2345: Argument of type 'OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_errors[] | null | undefined' is not assignable to parameter of type 'UserError[]'. -src/orders/views/OrderDetails/index.tsx(359,33): error TS2532: Object is possibly 'undefined'. -src/orders/views/OrderDetails/index.tsx(359,33): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/index.tsx(364,27): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/orders/views/OrderDetails/index.tsx(366,31): error TS2532: Object is possibly 'undefined'. -src/orders/views/OrderDetails/index.tsx(366,31): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/index.tsx(366,31): error TS2533: Object is possibly 'null' or 'undefined'. -src/orders/views/OrderDetails/index.tsx(367,48): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/index.tsx(372,31): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/orders/views/OrderDetails/index.tsx(385,27): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/orders/views/OrderDetails/index.tsx(386,53): error TS2532: Object is possibly 'undefined'. -src/orders/views/OrderDetails/index.tsx(386,53): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/index.tsx(420,27): error TS2322: Type 'OrderDetails_order | undefined' is not assignable to type 'OrderDetails_order'. -src/orders/views/OrderDetails/index.tsx(421,50): error TS2532: Object is possibly 'undefined'. -src/orders/views/OrderDetails/index.tsx(421,50): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/index.tsx(423,37): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/index.tsx(424,38): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/index.tsx(449,50): error TS2532: Object is possibly 'undefined'. -src/orders/views/OrderDetails/index.tsx(449,50): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/index.tsx(457,29): error TS2345: Argument of type 'OrderDraftCancel_draftOrderDelete_errors[] | null | undefined' is not assignable to parameter of type 'UserError[]'. -src/orders/views/OrderDetails/index.tsx(459,33): error TS2532: Object is possibly 'undefined'. -src/orders/views/OrderDetails/index.tsx(459,33): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/index.tsx(466,27): error TS2322: Type 'string | null | undefined' is not assignable to type 'string'. -src/orders/views/OrderDetails/index.tsx(466,52): error TS2532: Object is possibly 'undefined'. -src/orders/views/OrderDetails/index.tsx(473,27): error TS2322: Type 'string | null | undefined' is not assignable to type 'string'. -src/orders/views/OrderDetails/index.tsx(473,52): error TS2532: Object is possibly 'undefined'. -src/orders/views/OrderDetails/index.tsx(474,64): error TS2345: Argument of type 'OrderDetails_order | undefined' is not assignable to parameter of type 'OrderDetails_order'. -src/orders/views/OrderDetails/index.tsx(480,29): error TS2345: Argument of type 'OrderShippingMethodUpdate_orderUpdateShipping_errors[] | null | undefined' is not assignable to parameter of type 'UserError[]'. -src/orders/views/OrderDetails/index.tsx(482,33): error TS2532: Object is possibly 'undefined'. -src/orders/views/OrderDetails/index.tsx(482,33): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/index.tsx(488,35): error TS2532: Object is possibly 'undefined'. -src/orders/views/OrderDetails/index.tsx(488,35): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/index.tsx(491,27): error TS2322: Type '(OrderDetails_order_availableShippingMethods | null)[] | null | undefined' is not assignable to type 'OrderDetails_order_availableShippingMethods[] | undefined'. -src/orders/views/OrderDetails/index.tsx(492,35): error TS2532: Object is possibly 'undefined'. -src/orders/views/OrderDetails/index.tsx(508,29): error TS2345: Argument of type 'OrderLinesAdd_draftOrderLinesCreate_errors[] | null | undefined' is not assignable to parameter of type 'UserError[]'. -src/orders/views/OrderDetails/index.tsx(510,33): error TS2532: Object is possibly 'undefined'. -src/orders/views/OrderDetails/index.tsx(510,33): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/index.tsx(544,25): error TS2345: Argument of type 'OrderUpdate_orderUpdate_errors[] | null | undefined' is not assignable to parameter of type 'UserError[]'. -src/orders/views/OrderDetails/index.tsx(544,37): error TS2532: Object is possibly 'undefined'. -src/orders/views/OrderDetails/index.tsx(544,37): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/index.tsx(547,25): error TS2345: Argument of type 'OrderDetails_order_shippingAddress | null | undefined' is not assignable to parameter of type 'AddressType'. -src/orders/views/OrderDetails/index.tsx(547,37): error TS2532: Object is possibly 'undefined'. -src/orders/views/OrderDetails/index.tsx(549,46): error TS2532: Object is possibly 'undefined'. -src/orders/views/OrderDetails/index.tsx(549,46): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/index.tsx(551,33): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/index.tsx(552,34): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/index.tsx(555,23): error TS2322: Type 'OrderUpdate_orderUpdate_errors[] | null' is not assignable to type 'UserError[]'. -src/orders/views/OrderDetails/index.tsx(556,31): error TS2532: Object is possibly 'undefined'. -src/orders/views/OrderDetails/index.tsx(556,31): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/index.tsx(575,25): error TS2345: Argument of type 'OrderUpdate_orderUpdate_errors[] | null | undefined' is not assignable to parameter of type 'UserError[]'. -src/orders/views/OrderDetails/index.tsx(575,37): error TS2532: Object is possibly 'undefined'. -src/orders/views/OrderDetails/index.tsx(575,37): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/index.tsx(578,25): error TS2345: Argument of type 'OrderDetails_order_billingAddress | null | undefined' is not assignable to parameter of type 'AddressType'. -src/orders/views/OrderDetails/index.tsx(578,37): error TS2532: Object is possibly 'undefined'. -src/orders/views/OrderDetails/index.tsx(580,46): error TS2532: Object is possibly 'undefined'. -src/orders/views/OrderDetails/index.tsx(580,46): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/index.tsx(582,33): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/index.tsx(583,34): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/index.tsx(586,23): error TS2322: Type 'OrderUpdate_orderUpdate_errors[] | null' is not assignable to type 'UserError[]'. -src/orders/views/OrderDetails/index.tsx(587,31): error TS2532: Object is possibly 'undefined'. -src/orders/views/OrderDetails/index.tsx(587,31): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(58,22): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(58,22): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(71,27): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(71,27): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(71,27): error TS2532: Object is possibly 'undefined'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(80,22): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(80,22): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(94,27): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(94,27): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(94,27): error TS2532: Object is possibly 'undefined'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(103,22): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(103,22): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(109,25): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(109,25): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(119,22): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(119,22): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(125,25): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(125,25): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(140,23): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(140,23): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(158,22): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(158,22): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(173,22): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(173,22): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(179,25): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(179,25): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(183,22): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(183,22): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(189,25): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(189,25): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(193,22): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(193,22): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(206,23): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(206,23): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(209,22): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(209,22): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(224,22): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(224,22): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(230,25): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(230,25): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(240,22): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(240,22): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(255,22): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(255,22): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(261,25): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(261,25): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(273,22): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(273,22): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(279,25): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(279,25): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(289,22): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(289,22): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(295,25): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDetails/OrderDetailsMessages.tsx(295,25): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDraftList/filters.ts(36,9): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/orders/views/OrderDraftList/filters.ts(37,9): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/orders/views/OrderDraftList/filters.ts(42,7): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/orders/views/OrderDraftList/OrderDraftList.tsx(75,23): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDraftList/OrderDraftList.tsx(75,23): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDraftList/OrderDraftList.tsx(97,5): error TS2322: Type '(params?: OrderDraftListUrlQueryParams | undefined) => string' is not assignable to type 'CreateUrl'. -src/orders/views/OrderDraftList/OrderDraftList.tsx(144,5): error TS2345: Argument of type 'OrderDraftList_draftOrders_pageInfo | undefined' is not assignable to parameter of type 'PageInfo'. -src/orders/views/OrderDraftList/OrderDraftList.tsx(144,17): error TS2532: Object is possibly 'undefined'. -src/orders/views/OrderDraftList/OrderDraftList.tsx(144,17): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDraftList/OrderDraftList.tsx(150,9): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDraftList/OrderDraftList.tsx(150,9): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDraftList/OrderDraftList.tsx(163,38): error TS2571: Object is of type 'unknown'. -src/orders/views/OrderDraftList/OrderDraftList.tsx(169,32): error TS2345: Argument of type '{ variables: { ids: string[] | undefined; }; }' is not assignable to parameter of type 'MutationFunctionOptions'. -src/orders/views/OrderDraftList/OrderDraftList.tsx(191,15): error TS2322: Type 'OrderDraftList_draftOrders_edges_node[] | undefined' is not assignable to type 'OrderDraftList_draftOrders_edges_node[]'. -src/orders/views/OrderDraftList/OrderDraftList.tsx(192,17): error TS2532: Object is possibly 'undefined'. -src/orders/views/OrderDraftList/OrderDraftList.tsx(192,17): error TS2531: Object is possibly 'null'. -src/orders/views/OrderDraftList/OrderDraftList.tsx(235,42): error TS2532: Object is possibly 'undefined'. -src/orders/views/OrderDraftList/OrderDraftList.tsx(237,44): error TS2532: Object is possibly 'undefined'. -src/orders/views/OrderDraftList/sort.ts(18,7): error TS2322: Type 'undefined' is not assignable to type 'OrderSortField'. -src/orders/views/OrderList/filters.ts(43,9): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/orders/views/OrderList/filters.ts(44,9): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/orders/views/OrderList/filters.ts(49,7): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/orders/views/OrderList/filters.ts(56,13): error TS2532: Object is possibly 'undefined'. -src/orders/views/OrderList/filters.ts(77,7): error TS2532: Object is possibly 'undefined'. -src/orders/views/OrderList/OrderList.tsx(73,23): error TS2531: Object is possibly 'null'. -src/orders/views/OrderList/OrderList.tsx(73,23): error TS2531: Object is possibly 'null'. -src/orders/views/OrderList/OrderList.tsx(95,5): error TS2322: Type '(params?: OrderListUrlQueryParams | undefined) => string' is not assignable to type 'CreateUrl'. -src/orders/views/OrderList/OrderList.tsx(128,38): error TS2571: Object is of type 'unknown'. -src/orders/views/OrderList/OrderList.tsx(144,5): error TS2345: Argument of type 'OrderList_orders_pageInfo | undefined' is not assignable to parameter of type 'PageInfo'. -src/orders/views/OrderList/OrderList.tsx(144,17): error TS2532: Object is possibly 'undefined'. -src/orders/views/OrderList/OrderList.tsx(144,17): error TS2531: Object is possibly 'null'. -src/orders/views/OrderList/OrderList.tsx(150,9): error TS2531: Object is possibly 'null'. -src/orders/views/OrderList/OrderList.tsx(150,9): error TS2531: Object is possibly 'null'. -src/orders/views/OrderList/OrderList.tsx(168,27): error TS2345: Argument of type '{ variables: { ids: string[] | undefined; restock: boolean; }; }' is not assignable to parameter of type 'MutationFunctionOptions'. -src/orders/views/OrderList/OrderList.tsx(183,15): error TS2322: Type 'OrderList_orders_edges_node[] | undefined' is not assignable to type 'OrderList_orders_edges_node[]'. -src/orders/views/OrderList/OrderList.tsx(183,35): error TS2532: Object is possibly 'undefined'. -src/orders/views/OrderList/OrderList.tsx(183,35): error TS2531: Object is possibly 'null'. -src/orders/views/OrderList/OrderList.tsx(222,43): error TS2532: Object is possibly 'undefined'. -src/orders/views/OrderList/sort.ts(20,7): error TS2322: Type 'undefined' is not assignable to type 'OrderSortField'. -src/pages/components/PageList/PageList.tsx(91,37): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/pages/components/PageList/PageList.tsx(106,37): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/pages/components/PageList/PageList.tsx(121,37): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/pages/components/PageList/PageList.tsx(168,46): error TS2532: Object is possibly 'undefined'. -src/pages/components/PageList/PageList.tsx(172,51): error TS2532: Object is possibly 'undefined'. -src/pages/components/PageList/PageList.tsx(175,51): error TS2532: Object is possibly 'undefined'. -src/pages/components/PageList/PageList.tsx(182,29): error TS2532: Object is possibly 'undefined'. -src/pages/components/PageList/PageList.tsx(192,35): error TS2532: Object is possibly 'undefined'. -src/pages/views/PageCreate.tsx(23,9): error TS2531: Object is possibly 'null'. -src/pages/views/PageCreate.tsx(23,9): error TS2531: Object is possibly 'null'. -src/pages/views/PageCreate.tsx(29,24): error TS2531: Object is possibly 'null'. -src/pages/views/PageCreate.tsx(29,24): error TS2531: Object is possibly 'null'. -src/pages/views/PageCreate.tsx(45,13): error TS2322: Type 'PageCreate_pageCreate_errors[] | null' is not assignable to type 'UserError[]'. -src/pages/views/PageCreate.tsx(45,33): error TS2532: Object is possibly 'undefined'. -src/pages/views/PageCreate.tsx(45,33): error TS2531: Object is possibly 'null'. -src/pages/views/PageCreate.tsx(47,13): error TS2322: Type 'null' is not assignable to type 'PageDetails_page'. -src/pages/views/PageDetails.tsx(44,9): error TS2531: Object is possibly 'null'. -src/pages/views/PageDetails.tsx(44,9): error TS2531: Object is possibly 'null'. -src/pages/views/PageDetails.tsx(62,21): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/pages/views/PageDetails.tsx(62,40): error TS2532: Object is possibly 'undefined'. -src/pages/views/PageDetails.tsx(62,40): error TS2531: Object is possibly 'null'. -src/pages/views/PageDetails.tsx(66,21): error TS2322: Type 'PageUpdate_pageUpdate_errors[] | null' is not assignable to type 'UserError[]'. -src/pages/views/PageDetails.tsx(67,29): error TS2532: Object is possibly 'undefined'. -src/pages/views/PageDetails.tsx(67,29): error TS2531: Object is possibly 'null'. -src/pages/views/PageDetails.tsx(71,21): error TS2322: Type 'PageDetails_page | null | undefined' is not assignable to type 'PageDetails_page'. -src/pages/views/PageDetails.tsx(71,39): error TS2532: Object is possibly 'undefined'. -src/pages/views/PageDetails.tsx(107,44): error TS2532: Object is possibly 'undefined'. -src/pages/views/PageDetails.tsx(107,44): error TS2531: Object is possibly 'null'. -src/pages/views/PageList/PageList.tsx(66,5): error TS2345: Argument of type 'PageList_pages_pageInfo | undefined' is not assignable to parameter of type 'PageInfo'. -src/pages/views/PageList/PageList.tsx(66,17): error TS2532: Object is possibly 'undefined'. -src/pages/views/PageList/PageList.tsx(66,17): error TS2531: Object is possibly 'null'. -src/pages/views/PageList/PageList.tsx(77,9): error TS2531: Object is possibly 'null'. -src/pages/views/PageList/PageList.tsx(77,9): error TS2531: Object is possibly 'null'. -src/pages/views/PageList/PageList.tsx(91,9): error TS2531: Object is possibly 'null'. -src/pages/views/PageList/PageList.tsx(91,9): error TS2531: Object is possibly 'null'. -src/pages/views/PageList/PageList.tsx(115,17): error TS2322: Type 'PageList_pages_edges_node[] | undefined' is not assignable to type 'PageList_pages_edges_node[]'. -src/pages/views/PageList/PageList.tsx(115,36): error TS2532: Object is possibly 'undefined'. -src/pages/views/PageList/PageList.tsx(115,36): error TS2531: Object is possibly 'null'. -src/pages/views/PageList/PageList.tsx(175,35): error TS2345: Argument of type '{ variables: { ids: string[] | undefined; isPublished: true; }; }' is not assignable to parameter of type 'MutationFunctionOptions'. -src/pages/views/PageList/PageList.tsx(192,44): error TS2532: Object is possibly 'undefined'. -src/pages/views/PageList/PageList.tsx(194,46): error TS2532: Object is possibly 'undefined'. -src/pages/views/PageList/PageList.tsx(205,35): error TS2345: Argument of type '{ variables: { ids: string[] | undefined; isPublished: false; }; }' is not assignable to parameter of type 'MutationFunctionOptions'. -src/pages/views/PageList/PageList.tsx(221,42): error TS2532: Object is possibly 'undefined'. -src/pages/views/PageList/PageList.tsx(223,44): error TS2532: Object is possibly 'undefined'. -src/pages/views/PageList/PageList.tsx(233,34): error TS2345: Argument of type '{ variables: { ids: string[] | undefined; }; }' is not assignable to parameter of type 'MutationFunctionOptions'. -src/pages/views/PageList/PageList.tsx(249,42): error TS2532: Object is possibly 'undefined'. -src/pages/views/PageList/PageList.tsx(251,44): error TS2532: Object is possibly 'undefined'. -src/pages/views/PageList/sort.ts(14,7): error TS2322: Type 'undefined' is not assignable to type 'PageSortField'. -src/plugins/components/PluginsDetailsPage/PluginsDetailsPage.tsx(69,5): error TS2322: Type '({ value: string; } | { value: string; __typename: "ConfigurationItem"; name: string; type: ConfigurationTypeFieldEnum | null; helpText: string | null; label: string | null; })[] | undefined' is not assignable to type 'ConfigurationItemInput[]'. -src/plugins/components/PluginsDetailsPage/PluginsDetailsPage.tsx(70,7): error TS2531: Object is possibly 'null'. -src/plugins/components/PluginsDetailsPage/PluginsDetailsPage.tsx(71,41): error TS2345: Argument of type '(Plugin_plugin_configuration | null)[] | null' is not assignable to parameter of type 'Plugin_plugin_configuration[]'. -src/plugins/components/PluginsDetailsPage/PluginsDetailsPage.tsx(71,63): error TS2531: Object is possibly 'null'. -src/plugins/components/PluginsDetailsPage/PluginsDetailsPage.tsx(74,18): error TS2531: Object is possibly 'null'. -src/plugins/components/PluginsDetailsPage/PluginsDetailsPage.tsx(156,23): error TS2322: Type '(Plugin_plugin_configuration | null)[] | null' is not assignable to type 'Plugin_plugin_configuration[]'. -src/plugins/components/PluginsDetailsPage/PluginsDetailsPage.tsx(162,23): error TS2531: Object is possibly 'null'. -src/plugins/components/PluginsDetailsPage/PluginsDetailsPage.tsx(163,39): error TS2345: Argument of type '(Plugin_plugin_configuration | null)[] | null' is not assignable to parameter of type 'Plugin_plugin_configuration[]'. -src/plugins/components/PluginsDetailsPage/PluginsDetailsPage.tsx(163,61): error TS2531: Object is possibly 'null'. -src/plugins/components/PluginsDetailsPage/PluginsDetailsPage.tsx(169,27): error TS2322: Type '(Plugin_plugin_configuration | null)[] | null' is not assignable to type 'Plugin_plugin_configuration[]'. -src/plugins/components/PluginSecretFieldDialog/PluginSecretFieldDialog.tsx(70,17): error TS2769: No overload matches this call. -src/plugins/components/PluginSettings/PluginSettings.tsx(73,16): error TS2532: Object is possibly 'undefined'. -src/plugins/components/PluginSettings/PluginSettings.tsx(76,26): error TS2532: Object is possibly 'undefined'. -src/plugins/components/PluginSettings/PluginSettings.tsx(89,31): error TS2532: Object is possibly 'undefined'. -src/plugins/components/PluginSettings/PluginSettings.tsx(90,26): error TS2532: Object is possibly 'undefined'. -src/plugins/components/PluginsList/PluginsList.tsx(75,35): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/plugins/components/PluginsList/PluginsList.tsx(90,35): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/plugins/components/PluginsList/PluginsList.tsx(134,47): error TS2532: Object is possibly 'undefined'. -src/plugins/components/PluginsList/PluginsList.tsx(140,47): error TS2532: Object is possibly 'undefined'. -src/plugins/components/PluginsList/PluginsList.tsx(141,31): error TS2532: Object is possibly 'undefined'. -src/plugins/utils.ts(11,14): error TS2532: Object is possibly 'undefined'. -src/plugins/utils.ts(11,14): error TS2345: Argument of type 'ConfigurationTypeFieldEnum | null' is not assignable to parameter of type 'ConfigurationTypeFieldEnum'. -src/plugins/views/PluginDetails.test.ts(64,9): error TS2322: Type 'ConfigurationItemInput[] | null' is not assignable to type 'ConfigurationItemInput[]'. -src/plugins/views/PluginDetails.test.ts(70,9): error TS2532: Object is possibly 'undefined'. -src/plugins/views/PluginDetails.test.ts(77,9): error TS2532: Object is possibly 'undefined'. -src/plugins/views/PluginList/PluginList.tsx(80,5): error TS2322: Type '(params?: PluginListUrlQueryParams | undefined) => string' is not assignable to type 'CreateUrl'. -src/plugins/views/PluginList/PluginList.tsx(111,5): error TS2345: Argument of type 'Plugins_plugins_pageInfo | undefined' is not assignable to parameter of type 'PageInfo'. -src/plugins/views/PluginList/PluginList.tsx(111,17): error TS2532: Object is possibly 'undefined'. -src/plugins/views/PluginList/PluginList.tsx(111,17): error TS2531: Object is possibly 'null'. -src/plugins/views/PluginList/PluginList.tsx(117,38): error TS2571: Object is of type 'unknown'. -src/plugins/views/PluginList/PluginList.tsx(128,9): error TS2322: Type 'Plugins_plugins_edges_node[] | undefined' is not assignable to type 'Plugins_plugins_edges_node[]'. -src/plugins/views/PluginList/PluginList.tsx(128,30): error TS2532: Object is possibly 'undefined'. -src/plugins/views/PluginList/PluginList.tsx(128,30): error TS2531: Object is possibly 'null'. -src/plugins/views/PluginList/sort.ts(14,7): error TS2322: Type 'undefined' is not assignable to type 'PluginSortField'. -src/plugins/views/PluginsDetails.tsx(44,14): error TS2533: Object is possibly 'null' or 'undefined'. -src/plugins/views/PluginsDetails.tsx(62,9): error TS2531: Object is possibly 'null'. -src/plugins/views/PluginsDetails.tsx(62,9): error TS2531: Object is possibly 'null'. -src/plugins/views/PluginsDetails.tsx(76,21): error TS2532: Object is possibly 'undefined'. -src/plugins/views/PluginsDetails.tsx(76,21): error TS2531: Object is possibly 'null'. -src/plugins/views/PluginsDetails.tsx(81,28): error TS2345: Argument of type '{ variables: { id: string; input: { configuration: { name: string | undefined; value: string; }[]; }; }; }' is not assignable to parameter of type 'MutationFunctionOptions'. -src/plugins/views/PluginsDetails.tsx(98,19): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/plugins/views/PluginsDetails.tsx(98,38): error TS2532: Object is possibly 'undefined'. -src/plugins/views/PluginsDetails.tsx(98,38): error TS2531: Object is possibly 'null'. -src/plugins/views/PluginsDetails.tsx(102,19): error TS2322: Type 'PluginUpdate_pluginUpdate_errors[] | null' is not assignable to type 'UserError[]'. -src/plugins/views/PluginsDetails.tsx(106,19): error TS2322: Type 'Plugin_plugin | null | undefined' is not assignable to type 'Plugin_plugin'. -src/plugins/views/PluginsDetails.tsx(106,39): error TS2532: Object is possibly 'undefined'. -src/plugins/views/PluginsDetails.tsx(125,29): error TS2532: Object is possibly 'undefined'. -src/plugins/views/PluginsDetails.tsx(125,29): error TS2531: Object is possibly 'null'. -src/plugins/views/PluginsDetails.tsx(125,29): error TS2345: Argument of type '(Plugin_plugin_configuration | null)[] | null' is not assignable to parameter of type 'Plugin_plugin_configuration[] | null'. -src/plugins/views/PluginsDetails.tsx(133,30): error TS2532: Object is possibly 'undefined'. -src/plugins/views/PluginsDetails.tsx(133,30): error TS2531: Object is possibly 'null'. -src/plugins/views/PluginsDetails.tsx(145,58): error TS2345: Argument of type 'null' is not assignable to parameter of type 'string'. -src/plugins/views/PluginsDetails.tsx(155,23): error TS2322: Type 'Plugin_plugin_configuration | null | undefined' is not assignable to type 'Plugin_plugin_configuration'. -src/plugins/views/PluginsDetails.tsx(156,25): error TS2532: Object is possibly 'undefined'. -src/plugins/views/PluginsDetails.tsx(156,25): error TS2531: Object is possibly 'null'. -src/plugins/views/PluginsDetails.tsx(156,25): error TS2531: Object is possibly 'null'. -src/plugins/views/PluginsDetails.tsx(157,36): error TS2531: Object is possibly 'null'. -src/products/components/ProductAttributes/ProductAttributes.tsx(90,3): error TS2322: Type '{ label: string | null; value: string | null; }[]' is not assignable to type 'MultiAutocompleteChoiceType[]'. -src/products/components/ProductAttributes/ProductAttributes.tsx(99,3): error TS2322: Type '{ label: string | null; value: string | null; }[]' is not assignable to type 'MultiAutocompleteChoiceType[]'. -src/products/components/ProductAttributes/ProductAttributes.tsx(120,3): error TS2322: Type '{ label: string | null; value: string | null; }[]' is not assignable to type 'SingleAutocompleteChoiceType[]'. -src/products/components/ProductAttributes/ProductAttributes.tsx(189,25): error TS2322: Type 'string | null' is not assignable to type 'string'. -src/products/components/ProductAttributes/ProductAttributes.tsx(191,29): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductCategoryAndCollectionsForm/ProductCategoryAndCollectionsForm.tsx(48,11): error TS2322: Type '{ value: string; label: string; }[] | undefined' is not assignable to type '{ value: string; label: ReactNode; }[]'. -src/products/components/ProductCategoryAndCollectionsForm/ProductCategoryAndCollectionsForm.tsx(61,11): error TS2322: Type '{ value: string; label: string; }[] | undefined' is not assignable to type '{ value: string; label: string; }[]'. -src/products/components/ProductCreatePage/ProductCreatePage.tsx(132,5): error TS2322: Type 'null' is not assignable to type 'string'. -src/products/components/ProductCreatePage/ProductCreatePage.tsx(133,5): error TS2322: Type 'null' is not assignable to type 'number'. -src/products/components/ProductCreatePage/ProductCreatePage.tsx(156,35): error TS2345: Argument of type '{ id: string; name: string; hasVariants: boolean; productAttributes: SearchProductTypes_search_edges_node_productAttributes[]; }[] | undefined' is not assignable to parameter of type 'Node[]'. -src/products/components/ProductCreatePage/ProductCreatePage.tsx(159,5): error TS2722: Cannot invoke an object which is possibly 'undefined'. -src/products/components/ProductCreatePage/ProductCreatePage.tsx(198,11): error TS2345: Argument of type '{ id: string; name: string; hasVariants: boolean; productAttributes: SearchProductTypes_search_edges_node_productAttributes[]; }[] | undefined' is not assignable to parameter of type 'ProductType[]'. -src/products/components/ProductCreatePage/ProductCreatePage.tsx(203,24): error TS2322: Type '(() => any) | undefined' is not assignable to type '() => any'. -src/products/components/ProductCreatePage/ProductCreatePage.tsx(238,23): error TS2322: Type 'undefined' is not assignable to type 'ProductDetails_product'. -src/products/components/ProductCreatePage/ProductCreatePage.tsx(309,15): error TS2322: Type '(() => any) | undefined' is not assignable to type '() => void'. -src/products/components/ProductDetailsForm/ProductDetailsForm.tsx(59,11): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. -src/products/components/ProductImages/ProductImages.tsx(201,20): error TS2531: Object is possibly 'null'. -src/products/components/ProductImages/ProductImages.tsx(220,30): error TS2531: Object is possibly 'null'. -src/products/components/ProductImages/ProductImages.tsx(231,52): error TS2345: Argument of type 'FileList | null' is not assignable to parameter of type 'FileList'. -src/products/components/ProductList/ProductList.tsx(130,38): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductList/ProductList.tsx(130,38): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductList/ProductList.tsx(133,31): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductList/ProductList.tsx(133,31): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductList/ProductList.tsx(141,47): error TS2322: Type 'ProductListColumns[] | undefined' is not assignable to type 'ProductListColumns[]'. -src/products/components/ProductList/ProductList.tsx(141,63): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductList/ProductList.tsx(144,47): error TS2322: Type 'ProductListColumns[] | undefined' is not assignable to type 'ProductListColumns[]'. -src/products/components/ProductList/ProductList.tsx(144,63): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductList/ProductList.tsx(150,41): error TS2322: Type 'ProductListColumns[] | undefined' is not assignable to type 'ProductListColumns[]'. -src/products/components/ProductList/ProductList.tsx(150,57): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductList/ProductList.tsx(165,39): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductList/ProductList.tsx(165,39): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductList/ProductList.tsx(169,37): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/products/components/ProductList/ProductList.tsx(178,47): error TS2322: Type 'ProductListColumns[] | undefined' is not assignable to type 'ProductListColumns[]'. -src/products/components/ProductList/ProductList.tsx(178,63): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductList/ProductList.tsx(183,39): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/products/components/ProductList/ProductList.tsx(194,47): error TS2322: Type 'ProductListColumns[] | undefined' is not assignable to type 'ProductListColumns[]'. -src/products/components/ProductList/ProductList.tsx(194,63): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductList/ProductList.tsx(199,39): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/products/components/ProductList/ProductList.tsx(221,41): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/products/components/ProductList/ProductList.tsx(231,21): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductList/ProductList.tsx(239,41): error TS2322: Type 'ProductListColumns[] | undefined' is not assignable to type 'ProductListColumns[]'. -src/products/components/ProductList/ProductList.tsx(239,57): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductList/ProductList.tsx(244,39): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/products/components/ProductList/ProductList.tsx(286,43): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductList/ProductList.tsx(293,46): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductList/ProductList.tsx(298,44): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductList/ProductList.tsx(298,44): error TS2531: Object is possibly 'null'. -src/products/components/ProductList/ProductList.tsx(301,51): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductList/ProductList.tsx(305,21): error TS2322: Type 'ProductListColumns[] | undefined' is not assignable to type 'ProductListColumns[]'. -src/products/components/ProductList/ProductList.tsx(305,37): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductList/ProductList.tsx(320,21): error TS2322: Type 'ProductListColumns[] | undefined' is not assignable to type 'ProductListColumns[]'. -src/products/components/ProductList/ProductList.tsx(320,37): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductList/ProductList.tsx(325,57): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductList/ProductList.tsx(358,43): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductList/ProductList.tsx(365,43): error TS2531: Object is possibly 'null'. -src/products/components/ProductList/ProductList.tsx(374,21): error TS2322: Type 'ProductListColumns[] | undefined' is not assignable to type 'ProductListColumns[]'. -src/products/components/ProductList/ProductList.tsx(374,37): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductList/ProductList.tsx(377,36): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductList/ProductList.tsx(378,35): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductList/ProductList.tsx(378,35): error TS2531: Object is possibly 'null'. -src/products/components/ProductList/ProductList.tsx(379,35): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductList/ProductList.tsx(379,35): error TS2531: Object is possibly 'null'. -src/products/components/ProductList/ProductList.tsx(380,32): error TS2322: Type 'ProductList_products_edges_node_basePrice | null' is not assignable to type 'IMoney'. -src/products/components/ProductList/ProductList.tsx(380,39): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductListPage/ProductListPage.tsx(87,5): error TS2722: Cannot invoke an object which is possibly 'undefined'. -src/products/components/ProductListPage/ProductListPage.tsx(113,5): error TS2322: Type '{ label: string | null; value: string; }' is not assignable to type 'ColumnPickerChoice'. -src/products/components/ProductListPage/ProductListPage.tsx(125,11): error TS2322: Type 'ProductListColumns[] | undefined' is not assignable to type 'string[]'. -src/products/components/ProductListPage/ProductListPage.tsx(125,27): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductListPage/ProductListPage.tsx(128,11): error TS2322: Type 'ProductListColumns[] | undefined' is not assignable to type 'string[]'. -src/products/components/ProductListPage/ProductListPage.tsx(128,27): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductOrganization/ProductOrganization.tsx(110,13): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/products/components/ProductOrganization/ProductOrganization.tsx(118,13): error TS2322: Type 'SingleAutocompleteChoiceType[] | undefined' is not assignable to type 'SingleAutocompleteChoiceType[]'. -src/products/components/ProductOrganization/ProductOrganization.tsx(119,13): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/products/components/ProductOrganization/ProductOrganization.tsx(120,13): error TS2322: Type '((event: ChangeEvent) => void) | undefined' is not assignable to type '(event: ChangeEvent) => void'. -src/products/components/ProductOrganization/ProductOrganization.tsx(130,38): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductOrganization/ProductOrganization.tsx(138,19): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductOrganization/ProductOrganization.tsx(163,11): error TS2322: Type 'SingleAutocompleteChoiceType[] | undefined' is not assignable to type 'SingleAutocompleteChoiceType[]'. -src/products/components/ProductOrganization/ProductOrganization.tsx(179,11): error TS2322: Type 'MultiAutocompleteChoiceType[] | undefined' is not assignable to type 'MultiAutocompleteChoiceType[]'. -src/products/components/ProductStock/ProductStock.tsx(84,31): error TS2531: Object is possibly 'null'. -src/products/components/ProductStock/ProductStock.tsx(84,31): error TS2531: Object is possibly 'null'. -src/products/components/ProductUpdatePage/ProductUpdatePage.tsx(131,17): error TS2531: Object is possibly 'null'. -src/products/components/ProductUpdatePage/ProductUpdatePage.tsx(135,16): error TS2345: Argument of type '(ProductDetails_product_collections | null)[] | null' is not assignable to parameter of type 'Node[]'. -src/products/components/ProductUpdatePage/ProductUpdatePage.tsx(145,32): error TS2531: Object is possibly 'null'. -src/products/components/ProductUpdatePage/ProductUpdatePage.tsx(149,5): error TS2722: Cannot invoke an object which is possibly 'undefined'. -src/products/components/ProductUpdatePage/ProductUpdatePage.tsx(186,26): error TS2322: Type '(() => any) | undefined' is not assignable to type '() => any'. -src/products/components/ProductUpdatePage/ProductUpdatePage.tsx(196,21): error TS2322: Type 'RawDraftContentState | undefined' is not assignable to type 'RawDraftContentState'. -src/products/components/ProductUpdatePage/ProductUpdatePage.tsx(205,21): error TS2322: Type '((id: string) => any) | undefined' is not assignable to type '(id: string) => () => void'. -src/products/components/ProductUpdatePage/ProductUpdatePage.tsx(229,23): error TS2322: Type 'ProductDetails_product_basePrice | null | undefined' is not assignable to type 'ProductVariant_costPrice | undefined'. -src/products/components/ProductUpdatePage/ProductUpdatePage.tsx(253,21): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/products/components/ProductUpdatePage/ProductUpdatePage.tsx(274,21): error TS2322: Type 'ProductUpdatePageFormData' is not assignable to type '{ category: string; collections: string[]; productType?: string | undefined; }'. -src/products/components/ProductUpdatePage/ProductUpdatePage.tsx(313,17): error TS2322: Type '(() => any) | undefined' is not assignable to type '() => void'. -src/products/components/ProductVariantAttributes/ProductVariantAttributes.tsx(41,26): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductVariantAttributes/ProductVariantAttributes.tsx(45,5): error TS2322: Type 'string | null' is not assignable to type 'string'. -src/products/components/ProductVariantAttributes/ProductVariantAttributes.tsx(56,10): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductVariantAttributes/ProductVariantAttributes.tsx(64,3): error TS2322: Type '{ label: string | null; value: string | null; }[]' is not assignable to type 'SingleAutocompleteChoiceType[]'. -src/products/components/ProductVariantAttributes/ProductVariantAttributes.tsx(64,10): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductVariantAttributes/ProductVariantAttributes.tsx(129,43): error TS2769: No overload matches this call. -src/products/components/ProductVariantAttributes/ProductVariantAttributes.tsx(130,37): error TS2538: Type 'null' cannot be used as an index type. -src/products/components/ProductVariantCreateDialog/createVariants.test.ts(63,20): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductVariantCreateDialog/createVariants.test.ts(64,17): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductVariantCreateDialog/createVariants.test.ts(88,5): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductVariantCreateDialog/createVariants.test.ts(92,13): error TS2533: Object is possibly 'null' or 'undefined'. -src/products/components/ProductVariantCreateDialog/createVariants.test.ts(93,35): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantCreateDialog/createVariants.test.ts(93,59): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductVariantCreateDialog/createVariants.test.ts(121,20): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductVariantCreateDialog/createVariants.test.ts(122,17): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductVariantCreateDialog/createVariants.test.ts(141,5): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductVariantCreateDialog/createVariants.test.ts(145,13): error TS2533: Object is possibly 'null' or 'undefined'. -src/products/components/ProductVariantCreateDialog/createVariants.test.ts(146,35): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantCreateDialog/createVariants.test.ts(146,59): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductVariantCreateDialog/createVariants.test.ts(167,20): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductVariantCreateDialog/createVariants.test.ts(168,17): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductVariantCreateDialog/createVariants.test.ts(176,20): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductVariantCreateDialog/createVariants.test.ts(177,17): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductVariantCreateDialog/createVariants.test.ts(192,5): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductVariantCreateDialog/createVariants.test.ts(196,13): error TS2533: Object is possibly 'null' or 'undefined'. -src/products/components/ProductVariantCreateDialog/createVariants.test.ts(197,35): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantCreateDialog/createVariants.test.ts(197,59): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductVariantCreateDialog/createVariants.test.ts(207,5): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductVariantCreateDialog/createVariants.test.ts(211,13): error TS2533: Object is possibly 'null' or 'undefined'. -src/products/components/ProductVariantCreateDialog/createVariants.test.ts(212,35): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantCreateDialog/createVariants.test.ts(212,59): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductVariantCreateDialog/createVariants.ts(23,23): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductVariantCreateDialog/createVariants.ts(26,10): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductVariantCreateDialog/form.ts(35,5): error TS2322: Type 'undefined' is not assignable to type 'string'. -src/products/components/ProductVariantCreateDialog/form.ts(41,5): error TS2322: Type 'undefined' is not assignable to type 'string'. -src/products/components/ProductVariantCreateDialog/ProductVariantCreate.stories.tsx(23,3): error TS2322: Type '{ slug: string | null; value: string; }[]' is not assignable to type 'AttributeValue[]'. -src/products/components/ProductVariantCreateDialog/ProductVariantCreate.stories.tsx(23,11): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantCreateDialog/ProductVariantCreate.stories.tsx(24,11): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantCreateDialog/ProductVariantCreate.stories.tsx(33,3): error TS2322: Type '{ slug: string | null; value: string; }[]' is not assignable to type 'AttributeValue[]'. -src/products/components/ProductVariantCreateDialog/ProductVariantCreate.stories.tsx(33,11): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantCreateDialog/ProductVariantCreate.stories.tsx(34,11): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantCreateDialog/ProductVariantCreate.stories.tsx(41,11): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantCreateDialog/ProductVariantCreate.stories.tsx(42,19): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantCreateDialog/ProductVariantCreate.stories.tsx(60,5): error TS2322: Type '{ id: string; values: (string | null)[]; }[]' is not assignable to type 'Attribute[]'. -src/products/components/ProductVariantCreateDialog/ProductVariantCreate.stories.tsx(64,7): error TS2322: Type '{ id: string; values: (string | null)[]; }[]' is not assignable to type 'Attribute[]'. -src/products/components/ProductVariantCreateDialog/ProductVariantCreatePrices.tsx(73,7): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductVariantCreateDialog/ProductVariantCreatePrices.tsx(73,7): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantCreateDialog/ProductVariantCreatePrices.tsx(76,11): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductVariantCreateDialog/ProductVariantCreatePrices.tsx(78,30): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantCreateDialog/ProductVariantCreatePrices.tsx(78,30): error TS2345: Argument of type 'string | null' is not assignable to parameter of type 'string'. -src/products/components/ProductVariantCreateDialog/ProductVariantCreatePrices.tsx(84,7): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductVariantCreateDialog/ProductVariantCreatePrices.tsx(84,7): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantCreateDialog/ProductVariantCreatePrices.tsx(87,11): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductVariantCreateDialog/ProductVariantCreatePrices.tsx(89,30): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantCreateDialog/ProductVariantCreatePrices.tsx(89,30): error TS2345: Argument of type 'string | null' is not assignable to parameter of type 'string'. -src/products/components/ProductVariantCreateDialog/ProductVariantCreatePrices.tsx(167,36): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantCreateDialog/ProductVariantCreatePrices.tsx(171,34): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantCreateDialog/ProductVariantCreatePrices.tsx(189,25): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductVariantCreateDialog/ProductVariantCreatePrices.tsx(190,51): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantCreateDialog/ProductVariantCreatePrices.tsx(195,27): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantCreateDialog/ProductVariantCreatePrices.tsx(195,27): error TS2345: Argument of type 'string | null' is not assignable to parameter of type 'string'. -src/products/components/ProductVariantCreateDialog/ProductVariantCreatePrices.tsx(277,36): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantCreateDialog/ProductVariantCreatePrices.tsx(281,34): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantCreateDialog/ProductVariantCreatePrices.tsx(292,25): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductVariantCreateDialog/ProductVariantCreatePrices.tsx(293,51): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantCreateDialog/ProductVariantCreatePrices.tsx(298,27): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantCreateDialog/ProductVariantCreatePrices.tsx(298,27): error TS2345: Argument of type 'string | null' is not assignable to parameter of type 'string'. -src/products/components/ProductVariantCreateDialog/ProductVariantCreateSummary.tsx(95,3): error TS2322: Type '(string | null)[]' is not assignable to type 'string[]'. -src/products/components/ProductVariantCreateDialog/ProductVariantCreateSummary.tsx(98,7): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantCreateDialog/ProductVariantCreateSummary.tsx(98,7): error TS2533: Object is possibly 'null' or 'undefined'. -src/products/components/ProductVariantCreateDialog/ProductVariantCreateSummary.tsx(100,11): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantCreateDialog/ProductVariantCreateSummary.tsx(101,11): error TS2533: Object is possibly 'null' or 'undefined'. -src/products/components/ProductVariantCreateDialog/ProductVariantCreateSummary.tsx(102,33): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantCreateDialog/ProductVariantCreateSummary.tsx(191,35): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantCreateDialog/ProductVariantCreateSummary.tsx(222,23): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductVariantCreateDialog/ProductVariantCreateSummary.tsx(249,23): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductVariantCreateDialog/ProductVariantCreateSummary.tsx(273,23): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductVariantCreateDialog/ProductVariantCreateValues.tsx(51,14): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantCreateDialog/ProductVariantCreateValues.tsx(53,62): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantCreateDialog/ProductVariantCreateValues.tsx(53,62): error TS2345: Argument of type 'string | null' is not assignable to parameter of type 'string'. -src/products/components/ProductVariantCreateDialog/ProductVariantCreateValues.tsx(55,17): error TS2769: No overload matches this call. -src/products/components/ProductVariantCreateDialog/ProductVariantCreateValues.tsx(55,22): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantCreateDialog/ProductVariantCreateValues.tsx(60,23): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantCreateDialog/ProductVariantCreateValues.tsx(61,23): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductVariantCreateDialog/ProductVariantCreateValues.tsx(66,36): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantCreateDialog/ProductVariantCreateValues.tsx(67,28): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantCreateDialog/reducer.ts(47,36): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductVariantCreateDialog/reducer.ts(53,55): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductVariantCreateDialog/reducer.ts(53,64): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductVariantCreateDialog/reducer.ts(82,5): error TS2322: Type '(Attribute | undefined)[]' is not assignable to type 'Attribute[]'. -src/products/components/ProductVariantCreateDialog/reducer.ts(209,18): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductVariantCreateDialog/reducer.ts(235,18): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductVariantCreateDialog/reducer.ts(328,37): error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'. -src/products/components/ProductVariantCreateDialog/reducer.ts(331,41): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/products/components/ProductVariantCreateDialog/reducer.ts(333,41): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/products/components/ProductVariantCreateDialog/reducer.ts(335,51): error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'. -src/products/components/ProductVariantCreateDialog/reducer.ts(337,51): error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'. -src/products/components/ProductVariantCreateDialog/reducer.ts(339,55): error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'. -src/products/components/ProductVariantCreateDialog/reducer.ts(341,55): error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'. -src/products/components/ProductVariantCreateDialog/reducer.ts(343,52): error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'. -src/products/components/ProductVariantCreateDialog/reducer.ts(345,52): error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'. -src/products/components/ProductVariantCreateDialog/reducer.ts(349,9): error TS2345: Argument of type '"price" | "sku" | "stock" | undefined' is not assignable to parameter of type 'VariantField'. -src/products/components/ProductVariantCreateDialog/reducer.ts(354,39): error TS2345: Argument of type 'number | undefined' is not assignable to parameter of type 'number'. -src/products/components/ProductVariantCreatePage/ProductVariantCreatePage.tsx(75,9): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantCreatePage/ProductVariantCreatePage.tsx(76,17): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantCreatePage/ProductVariantCreatePage.tsx(77,17): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantCreatePage/ProductVariantCreatePage.tsx(83,25): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantCreatePage/ProductVariantCreatePage.tsx(83,53): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantCreatePage/ProductVariantCreatePage.tsx(96,33): error TS2322: Type '(data: ProductVariantCreatePageFormData) => void' is not assignable to type '(data: { attributes: { name: string | null; slug: string | null; values: string[]; }[]; costPrice: string; images: string[] | undefined; priceOverride: string; quantity: string; sku: string; }) => void'. -src/products/components/ProductVariantCreatePage/ProductVariantCreatePage.tsx(110,19): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/products/components/ProductVariantCreatePage/ProductVariantCreatePage.tsx(110,50): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantCreatePage/ProductVariantCreatePage.tsx(111,19): error TS2322: Type '(ProductVariantCreateData_product_variants | null)[] | null | undefined' is not assignable to type 'ProductVariantDetails_productVariant[] | ProductVariantCreateData_product_variants[]'. -src/products/components/ProductVariantCreatePage/ProductVariantCreatePage.tsx(128,19): error TS2322: Type 'VariantCreate_productVariantCreate_productErrors[]' is not assignable to type 'UserError[]'. -src/products/components/ProductVariantCreatePage/ProductVariantCreatePage.tsx(137,19): error TS2322: Type 'VariantCreate_productVariantCreate_productErrors[]' is not assignable to type 'UserError[]'. -src/products/components/ProductVariantImageSelectDialog/ProductVariantImageSelectDialog.tsx(76,12): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductVariantImageSelectDialog/ProductVariantImageSelectDialog.tsx(84,23): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductVariantNavigation/ProductVariantNavigation.tsx(84,25): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductVariantNavigation/ProductVariantNavigation.tsx(84,25): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantNavigation/ProductVariantNavigation.tsx(84,25): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantNavigation/ProductVariantNavigation.tsx(106,62): error TS2322: Type 'null' is not assignable to type 'string | undefined'. -src/products/components/ProductVariantPage/ProductVariantPage.tsx(70,40): error TS2345: Argument of type 'ProductVariant | undefined' is not assignable to parameter of type 'ProductVariant'. -src/products/components/ProductVariantPage/ProductVariantPage.tsx(80,37): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductVariantPage/ProductVariantPage.tsx(80,37): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantPage/ProductVariantPage.tsx(80,65): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantPage/ProductVariantPage.tsx(82,5): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductVariantPage/ProductVariantPage.tsx(82,5): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantPage/ProductVariantPage.tsx(83,7): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantPage/ProductVariantPage.tsx(83,7): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantPage/ProductVariantPage.tsx(83,24): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantPage/ProductVariantPage.tsx(83,24): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantPage/ProductVariantPage.tsx(87,5): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductVariantPage/ProductVariantPage.tsx(88,46): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantPage/ProductVariantPage.tsx(89,30): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantPage/ProductVariantPage.tsx(89,30): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantPage/ProductVariantPage.tsx(89,47): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantPage/ProductVariantPage.tsx(89,47): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantPage/ProductVariantPage.tsx(93,28): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductVariantPage/ProductVariantPage.tsx(93,28): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantPage/ProductVariantPage.tsx(94,32): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductVariantPage/ProductVariantPage.tsx(94,32): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantPage/ProductVariantPage.tsx(95,27): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductVariantPage/ProductVariantPage.tsx(96,22): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductVariantPage/ProductVariantPage.tsx(102,7): error TS2322: Type 'FormsetData' is not assignable to type 'FormsetData'. -src/products/components/ProductVariantPage/ProductVariantPage.tsx(109,24): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductVariantPage/ProductVariantPage.tsx(125,23): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/products/components/ProductVariantPage/ProductVariantPage.tsx(126,31): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductVariantPage/ProductVariantPage.tsx(126,31): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantPage/ProductVariantPage.tsx(128,23): error TS2322: Type '(ProductVariant_product_variants | null)[] | null | undefined' is not assignable to type 'ProductVariantDetails_productVariant[] | ProductVariantCreateData_product_variants[]'. -src/products/components/ProductVariantPage/ProductVariantPage.tsx(128,45): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductVariantPage/ProductVariantPage.tsx(139,23): error TS2322: Type 'FormsetData' is not assignable to type 'VariantAttributeInput[]'. -src/products/components/ProductVariantPage/ProductVariantPage.tsx(140,23): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. -src/products/components/ProductVariantPage/ProductVariantPage.tsx(146,23): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. -src/products/components/ProductVariantPage/ProductVariantPage.tsx(147,23): error TS2322: Type '(ProductVariant_product_images | null)[] | undefined' is not assignable to type 'ProductImage[] | undefined'. -src/products/components/ProductVariantPage/ProductVariantPage.tsx(153,23): error TS2322: Type 'VariantUpdate_productVariantUpdate_productErrors[]' is not assignable to type 'UserError[]'. -src/products/components/ProductVariantPage/ProductVariantPage.tsx(168,23): error TS2322: Type 'VariantUpdate_productVariantUpdate_productErrors[]' is not assignable to type 'UserError[]'. -src/products/components/ProductVariantPage/ProductVariantPage.tsx(171,23): error TS2322: Type 'number | null | undefined' is not assignable to type 'number | undefined'. -src/products/components/ProductVariantPage/ProductVariantPage.tsx(196,11): error TS2322: Type '(ProductVariant_product_images | null)[] | undefined' is not assignable to type 'ProductImage[] | undefined'. -src/products/components/ProductVariantPage/ProductVariantPage.tsx(197,39): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariantPage/ProductVariantPage.tsx(197,67): error TS2531: Object is possibly 'null'. -src/products/components/ProductVariants/ProductVariants.tsx(177,39): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductVariants/ProductVariants.tsx(186,46): error TS2532: Object is possibly 'undefined'. -src/products/components/ProductVariants/ProductVariants.tsx(196,29): error TS2532: Object is possibly 'undefined'. -src/products/containers/ProductImagesReorder.tsx(32,34): error TS2532: Object is possibly 'undefined'. -src/products/containers/ProductImagesReorder.tsx(32,34): error TS2532: Object is possibly 'undefined'. -src/products/containers/ProductImagesReorder.tsx(34,31): error TS2538: Type 'null' cannot be used as an index type. -src/products/containers/ProductUpdateOperations.tsx(105,11): error TS2322: Type '(ProductDetails_product_images | null)[] | null' is not assignable to type '{ id: string; url: string; }[]'. -src/products/urls.ts(66,39): error TS2345: Argument of type 'ProductListUrlQueryParams | undefined' is not assignable to parameter of type 'object'. -src/products/urls.ts(72,59): error TS2345: Argument of type 'ProductUrlQueryParams | undefined' is not assignable to parameter of type 'object'. -src/products/urls.ts(88,15): error TS2345: Argument of type 'Partial<{ action: "remove"; }> | undefined' is not assignable to parameter of type 'object'. -src/products/urls.ts(106,15): error TS2345: Argument of type 'Partial<{ action: "remove"; }> | undefined' is not assignable to parameter of type 'object'. -src/products/utils/data.ts(39,7): error TS2322: Type '{ data: { inputType: AttributeInputTypeEnum | null; isRequired: boolean; values: (ProductDetails_product_attributes_attribute_values | null)[] | null; }; id: string; label: string | null; value: (string | null)[]; }[]' is not assignable to type 'ProductAttributeInput[]'. -src/products/utils/data.ts(47,46): error TS2531: Object is possibly 'null'. -src/products/utils/data.ts(60,3): error TS2322: Type '{ id: string; values: { label: string | null; value: string | null; }[]; }[]' is not assignable to type 'ProductAttributeValueChoices[]'. -src/products/utils/data.ts(65,18): error TS2531: Object is possibly 'null'. -src/products/utils/data.ts(66,18): error TS2531: Object is possibly 'null'. -src/products/utils/data.ts(76,3): error TS2322: Type '{ data: { inputType: AttributeInputTypeEnum | null; isRequired: boolean; values: (SearchProductTypes_search_edges_node_productAttributes_values | null)[] | null; }; id: string; label: string | null; value: never[]; }[]' is not assignable to type 'ProductAttributeInput[]'. -src/products/utils/data.ts(93,7): error TS2322: Type '{ data: { values: (ProductVariant_attributes_attribute_values | null)[] | null; }; id: string; label: string | null; value: string | null; }[]' is not assignable to type 'VariantAttributeInput[]'. -src/products/utils/data.ts(99,28): error TS2531: Object is possibly 'null'. -src/products/utils/data.ts(108,3): error TS2322: Type '{ data: { values: (ProductVariantCreateData_product_productType_variantAttributes_values | null)[] | null; }; id: string; label: string | null; value: string; }[] | undefined' is not assignable to type 'VariantAttributeInput[]'. -src/products/utils/data.ts(109,5): error TS2531: Object is possibly 'null'. -src/products/utils/data.ts(111,17): error TS2531: Object is possibly 'null'. -src/products/utils/data.ts(113,11): error TS2531: Object is possibly 'null'. -src/products/utils/data.ts(114,14): error TS2531: Object is possibly 'null'. -src/products/utils/data.ts(164,28): error TS2531: Object is possibly 'null'. -src/products/utils/data.ts(165,27): error TS2531: Object is possibly 'null'. -src/products/utils/data.ts(168,13): error TS2531: Object is possibly 'null'. -src/products/utils/data.ts(168,51): error TS2531: Object is possibly 'null'. -src/products/utils/data.ts(175,5): error TS2322: Type 'string | null' is not assignable to type 'string'. -src/products/utils/data.ts(176,5): error TS2322: Type 'string | null' is not assignable to type 'string'. -src/products/utils/data.ts(177,5): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/products/utils/data.ts(186,5): error TS2322: Type 'number | undefined' is not assignable to type 'number'. -src/products/utils/handlers.ts(20,28): error TS2532: Object is possibly 'undefined'. -src/products/utils/handlers.ts(25,26): error TS2532: Object is possibly 'undefined'. -src/products/utils/handlers.ts(34,27): error TS2345: Argument of type '(ProductAttributeValueChoices | { values: { label: string | null; value: string; }[]; id: string; })[]' is not assignable to parameter of type 'ProductAttributeValueChoices[]'. -src/products/utils/handlers.ts(56,28): error TS2532: Object is possibly 'undefined'. -src/products/utils/handlers.ts(84,27): error TS2345: Argument of type '(ProductAttributeValueChoices | { values: { label: string | null; value: string; }[]; id: string; })[]' is not assignable to parameter of type 'ProductAttributeValueChoices[]'. -src/products/utils/handlers.ts(106,20): error TS2345: Argument of type 'ProductType | undefined' is not assignable to parameter of type 'ProductType'. -src/products/utils/handlers.ts(109,52): error TS2345: Argument of type 'ProductType | undefined' is not assignable to parameter of type 'ProductType'. -src/products/utils/handlers.ts(111,7): error TS2532: Object is possibly 'undefined'. -src/products/views/ProductCreate.tsx(54,9): error TS2531: Object is possibly 'null'. -src/products/views/ProductCreate.tsx(54,9): error TS2531: Object is possibly 'null'. -src/products/views/ProductCreate.tsx(60,27): error TS2531: Object is possibly 'null'. -src/products/views/ProductCreate.tsx(60,27): error TS2531: Object is possibly 'null'. -src/products/views/ProductCreate.tsx(62,30): error TS2531: Object is possibly 'null'. -src/products/views/ProductCreate.tsx(62,30): error TS2531: Object is possibly 'null'. -src/products/views/ProductCreate.tsx(66,18): error TS2322: Type 'string | null' is not assignable to type 'string'. -src/products/views/ProductCreate.tsx(113,37): error TS2571: Object is of type 'unknown'. -src/products/views/ProductCreate.tsx(123,15): error TS2322: Type 'ProductCreate_productCreate_errors[] | null' is not assignable to type 'UserError[]'. -src/products/views/ProductCreate.tsx(124,23): error TS2532: Object is possibly 'undefined'. -src/products/views/ProductCreate.tsx(124,23): error TS2531: Object is possibly 'null'. -src/products/views/ProductImage.tsx(41,9): error TS2531: Object is possibly 'null'. -src/products/views/ProductImage.tsx(41,9): error TS2531: Object is possibly 'null'. -src/products/views/ProductImage.tsx(83,25): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/products/views/ProductImage.tsx(83,46): error TS2532: Object is possibly 'undefined'. -src/products/views/ProductImage.tsx(83,46): error TS2531: Object is possibly 'null'. -src/products/views/ProductImage.tsx(84,25): error TS2322: Type 'ProductImageById_product_mainImage | null' is not assignable to type '{ id: string; alt: string; url: string; } | undefined'. -src/products/views/ProductImage.tsx(85,25): error TS2322: Type '(ProductImageById_product_images | null)[] | null | undefined' is not assignable to type '{ id: string; url: string; }[] | undefined'. -src/products/views/ProductImage.tsx(85,45): error TS2532: Object is possibly 'undefined'. -src/products/views/ProductImage.tsx(85,45): error TS2531: Object is possibly 'null'. -src/products/views/ProductList/filters.ts(56,47): error TS2344: Type 'SearchCategoriesVariables' does not satisfy the constraint 'SearchVariables'. -src/products/views/ProductList/filters.ts(60,48): error TS2344: Type 'SearchCollectionsVariables' does not satisfy the constraint 'SearchVariables'. -src/products/views/ProductList/filters.ts(64,49): error TS2344: Type 'SearchProductTypesVariables' does not satisfy the constraint 'SearchVariables'. -src/products/views/ProductList/filters.ts(68,5): error TS2322: Type '{ active: boolean; choices: { label: string | null; value: string | null; }[]; name: string | null; slug: string | null; value: any; }[]' is not assignable to type '(FilterOpts & { choices: MultiAutocompleteChoiceType[]; name: string; slug: string; })[]'. -src/products/views/ProductList/filters.ts(69,24): error TS2531: Object is possibly 'null'. -src/products/views/ProductList/filters.ts(69,33): error TS2531: Object is possibly 'null'. -src/products/views/ProductList/filters.ts(71,29): error TS2532: Object is possibly 'undefined'. -src/products/views/ProductList/filters.ts(71,47): error TS2538: Type 'null' cannot be used as an index type. -src/products/views/ProductList/filters.ts(72,18): error TS2531: Object is possibly 'null'. -src/products/views/ProductList/filters.ts(73,18): error TS2531: Object is possibly 'null'. -src/products/views/ProductList/filters.ts(74,18): error TS2531: Object is possibly 'null'. -src/products/views/ProductList/filters.ts(79,52): error TS2538: Type 'null' cannot be used as an index type. -src/products/views/ProductList/filters.ts(80,33): error TS2538: Type 'null' cannot be used as an index type. -src/products/views/ProductList/filters.ts(87,11): error TS2532: Object is possibly 'undefined'. -src/products/views/ProductList/filters.ts(87,11): error TS2531: Object is possibly 'null'. -src/products/views/ProductList/filters.ts(104,15): error TS2532: Object is possibly 'undefined'. -src/products/views/ProductList/filters.ts(104,15): error TS2531: Object is possibly 'null'. -src/products/views/ProductList/filters.ts(111,39): error TS2345: Argument of type 'string[] | undefined' is not assignable to parameter of type 'string[]'. -src/products/views/ProductList/filters.ts(117,11): error TS2532: Object is possibly 'undefined'. -src/products/views/ProductList/filters.ts(117,11): error TS2531: Object is possibly 'null'. -src/products/views/ProductList/filters.ts(134,15): error TS2532: Object is possibly 'undefined'. -src/products/views/ProductList/filters.ts(134,15): error TS2531: Object is possibly 'null'. -src/products/views/ProductList/filters.ts(141,39): error TS2345: Argument of type 'string[] | undefined' is not assignable to parameter of type 'string[]'. -src/products/views/ProductList/filters.ts(150,9): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/products/views/ProductList/filters.ts(151,9): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/products/views/ProductList/filters.ts(158,11): error TS2532: Object is possibly 'undefined'. -src/products/views/ProductList/filters.ts(158,11): error TS2531: Object is possibly 'null'. -src/products/views/ProductList/filters.ts(175,15): error TS2532: Object is possibly 'undefined'. -src/products/views/ProductList/filters.ts(175,15): error TS2531: Object is possibly 'null'. -src/products/views/ProductList/filters.ts(182,39): error TS2345: Argument of type 'string[] | undefined' is not assignable to parameter of type 'string[]'. -src/products/views/ProductList/filters.ts(186,42): error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'. -src/products/views/ProductList/filters.ts(190,42): error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'. -src/products/views/ProductList/filters.ts(203,27): error TS2532: Object is possibly 'undefined'. -src/products/views/ProductList/filters.ts(204,15): error TS2532: Object is possibly 'undefined'. -src/products/views/ProductList/filters.ts(205,18): error TS2532: Object is possibly 'undefined'. -src/products/views/ProductList/filters.ts(215,23): error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'. -src/products/views/ProductList/filters.ts(216,23): error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'. -src/products/views/ProductList/filters.ts(231,4): error TS2366: Function lacks ending return statement and return type does not include 'undefined'. -src/products/views/ProductList/fixtures.ts(13,3): error TS2322: Type '{ active: false; choices: { label: string | null; value: string | null; }[]; name: string | null; slug: string | null; value: (string | false | null)[]; }[]' is not assignable to type '(FilterOpts & { choices: MultiAutocompleteChoiceType[]; name: string; slug: string; })[]'. -src/products/views/ProductList/fixtures.ts(15,14): error TS2531: Object is possibly 'null'. -src/products/views/ProductList/fixtures.ts(16,14): error TS2531: Object is possibly 'null'. -src/products/views/ProductList/fixtures.ts(17,14): error TS2531: Object is possibly 'null'. -src/products/views/ProductList/fixtures.ts(21,13): error TS2531: Object is possibly 'null'. -src/products/views/ProductList/fixtures.ts(21,13): error TS2531: Object is possibly 'null'. -src/products/views/ProductList/fixtures.ts(21,34): error TS2531: Object is possibly 'null'. -src/products/views/ProductList/fixtures.ts(21,60): error TS2531: Object is possibly 'null'. -src/products/views/ProductList/fixtures.ts(21,60): error TS2531: Object is possibly 'null'. -src/products/views/ProductList/ProductList.tsx(180,38): error TS2571: Object is of type 'unknown'. -src/products/views/ProductList/ProductList.tsx(194,17): error TS2532: Object is possibly 'undefined'. -src/products/views/ProductList/ProductList.tsx(194,17): error TS2531: Object is possibly 'null'. -src/products/views/ProductList/ProductList.tsx(197,15): error TS2532: Object is possibly 'undefined'. -src/products/views/ProductList/ProductList.tsx(197,15): error TS2531: Object is possibly 'null'. -src/products/views/ProductList/ProductList.tsx(204,15): error TS2532: Object is possibly 'undefined'. -src/products/views/ProductList/ProductList.tsx(204,15): error TS2531: Object is possibly 'null'. -src/products/views/ProductList/ProductList.tsx(211,15): error TS2532: Object is possibly 'undefined'. -src/products/views/ProductList/ProductList.tsx(211,15): error TS2531: Object is possibly 'null'. -src/products/views/ProductList/ProductList.tsx(220,7): error TS2322: Type '{ first: number; ids: ProductListColumns[] | undefined; }' is not assignable to type 'AvailableInGridAttributesVariables'. -src/products/views/ProductList/ProductList.tsx(226,15): error TS2345: Argument of type 'ProductList_products_pageInfo | undefined' is not assignable to parameter of type 'PageInfo'. -src/products/views/ProductList/ProductList.tsx(226,27): error TS2532: Object is possibly 'undefined'. -src/products/views/ProductList/ProductList.tsx(226,27): error TS2531: Object is possibly 'null'. -src/products/views/ProductList/ProductList.tsx(232,19): error TS2531: Object is possibly 'null'. -src/products/views/ProductList/ProductList.tsx(232,19): error TS2531: Object is possibly 'null'. -src/products/views/ProductList/ProductList.tsx(243,19): error TS2531: Object is possibly 'null'. -src/products/views/ProductList/ProductList.tsx(243,19): error TS2531: Object is possibly 'null'. -src/products/views/ProductList/ProductList.tsx(262,27): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/products/views/ProductList/ProductList.tsx(270,31): error TS2532: Object is possibly 'undefined'. -src/products/views/ProductList/ProductList.tsx(270,31): error TS2531: Object is possibly 'null'. -src/products/views/ProductList/ProductList.tsx(283,31): error TS2532: Object is possibly 'undefined'. -src/products/views/ProductList/ProductList.tsx(283,31): error TS2531: Object is possibly 'null'. -src/products/views/ProductList/ProductList.tsx(286,27): error TS2322: Type 'number | null' is not assignable to type 'number'. -src/products/views/ProductList/ProductList.tsx(287,35): error TS2532: Object is possibly 'undefined'. -src/products/views/ProductList/ProductList.tsx(287,35): error TS2531: Object is possibly 'null'. -src/products/views/ProductList/ProductList.tsx(294,31): error TS2532: Object is possibly 'undefined'. -src/products/views/ProductList/ProductList.tsx(294,31): error TS2531: Object is possibly 'null'. -src/products/views/ProductList/ProductList.tsx(300,27): error TS2322: Type 'ProductList_products_edges_node[] | undefined' is not assignable to type 'ProductList_products_edges_node[]'. -src/products/views/ProductList/ProductList.tsx(301,29): error TS2532: Object is possibly 'undefined'. -src/products/views/ProductList/ProductList.tsx(301,29): error TS2531: Object is possibly 'null'. -src/products/views/ProductList/ProductList.tsx(305,31): error TS2345: Argument of type '(prev: AvailableInGridAttributes, next: AvailableInGridAttributes) => AvailableInGridAttributes | { ...; }' is not assignable to parameter of type '(prev: AvailableInGridAttributes, next: AvailableInGridAttributes) => AvailableInGridAttributes'. -src/products/views/ProductList/ProductList.tsx(307,35): error TS2531: Object is possibly 'null'. -src/products/views/ProductList/ProductList.tsx(308,35): error TS2531: Object is possibly 'null'. -src/products/views/ProductList/ProductList.tsx(317,42): error TS2531: Object is possibly 'null'. -src/products/views/ProductList/ProductList.tsx(318,42): error TS2531: Object is possibly 'null'. -src/products/views/ProductList/ProductList.tsx(320,47): error TS2531: Object is possibly 'null'. -src/products/views/ProductList/ProductList.tsx(326,35): error TS2532: Object is possibly 'undefined'. -src/products/views/ProductList/ProductList.tsx(326,35): error TS2531: Object is possibly 'null'. -src/products/views/ProductList/ProductList.tsx(394,47): error TS2345: Argument of type '{ variables: { ids: string[] | undefined; }; }' is not assignable to parameter of type 'MutationFunctionOptions'. -src/products/views/ProductList/ProductList.tsx(409,54): error TS2532: Object is possibly 'undefined'. -src/products/views/ProductList/ProductList.tsx(412,50): error TS2532: Object is possibly 'undefined'. -src/products/views/ProductList/ProductList.tsx(424,48): error TS2345: Argument of type '{ variables: { ids: string[] | undefined; isPublished: true; }; }' is not assignable to parameter of type 'MutationFunctionOptions'. -src/products/views/ProductList/ProductList.tsx(441,54): error TS2532: Object is possibly 'undefined'. -src/products/views/ProductList/ProductList.tsx(444,50): error TS2532: Object is possibly 'undefined'. -src/products/views/ProductList/ProductList.tsx(456,48): error TS2345: Argument of type '{ variables: { ids: string[] | undefined; isPublished: false; }; }' is not assignable to parameter of type 'MutationFunctionOptions'. -src/products/views/ProductList/ProductList.tsx(473,54): error TS2532: Object is possibly 'undefined'. -src/products/views/ProductList/ProductList.tsx(476,50): error TS2532: Object is possibly 'undefined'. -src/products/views/ProductList/sort.ts(21,7): error TS2322: Type 'undefined' is not assignable to type 'ProductOrderField'. -src/products/views/ProductList/sort.ts(31,36): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/products/views/ProductList/sort.ts(35,34): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/products/views/ProductList/sort.ts(36,30): error TS2345: Argument of type 'ProductListUrlSortField.name | ProductListUrlSortField.productType | ProductListUrlSortField.status | ProductListUrlSortField.price | undefined' is not assignable to parameter of type 'ProductListUrlSortField'. -src/products/views/ProductUpdate/handlers.ts(43,27): error TS2531: Object is possibly 'null'. -src/products/views/ProductUpdate/handlers.ts(43,27): error TS2531: Object is possibly 'null'. -src/products/views/ProductUpdate/handlers.ts(70,15): error TS2531: Object is possibly 'null'. -src/products/views/ProductUpdate/handlers.ts(70,43): error TS2531: Object is possibly 'null'. -src/products/views/ProductUpdate/ProductUpdate.tsx(100,15): error TS2531: Object is possibly 'null'. -src/products/views/ProductUpdate/ProductUpdate.tsx(100,15): error TS2531: Object is possibly 'null'. -src/products/views/ProductUpdate/ProductUpdate.tsx(105,36): error TS2531: Object is possibly 'null'. -src/products/views/ProductUpdate/ProductUpdate.tsx(105,36): error TS2531: Object is possibly 'null'. -src/products/views/ProductUpdate/ProductUpdate.tsx(109,24): error TS2322: Type 'string | null' is not assignable to type 'string'. -src/products/views/ProductUpdate/ProductUpdate.tsx(115,30): error TS2531: Object is possibly 'null'. -src/products/views/ProductUpdate/ProductUpdate.tsx(115,30): error TS2531: Object is possibly 'null'. -src/products/views/ProductUpdate/ProductUpdate.tsx(121,15): error TS2322: Type 'string | null' is not assignable to type 'string'. -src/products/views/ProductUpdate/ProductUpdate.tsx(134,15): error TS2531: Object is possibly 'null'. -src/products/views/ProductUpdate/ProductUpdate.tsx(134,15): error TS2531: Object is possibly 'null'. -src/products/views/ProductUpdate/ProductUpdate.tsx(143,15): error TS2531: Object is possibly 'null'. -src/products/views/ProductUpdate/ProductUpdate.tsx(143,15): error TS2531: Object is possibly 'null'. -src/products/views/ProductUpdate/ProductUpdate.tsx(152,13): error TS2322: Type 'ProductDetails_product | undefined' is not assignable to type 'ProductDetails_product'. -src/products/views/ProductUpdate/ProductUpdate.tsx(175,17): error TS2345: Argument of type 'ProductDetails_product | undefined' is not assignable to parameter of type 'ProductDetails_product'. -src/products/views/ProductUpdate/ProductUpdate.tsx(184,17): error TS2345: Argument of type 'ProductDetails_product | undefined' is not assignable to parameter of type 'ProductDetails_product'. -src/products/views/ProductUpdate/ProductUpdate.tsx(197,17): error TS2345: Argument of type 'ProductUpdate_productUpdate_errors[] | null | undefined' is not assignable to parameter of type 'UserError[]'. -src/products/views/ProductUpdate/ProductUpdate.tsx(197,29): error TS2532: Object is possibly 'undefined'. -src/products/views/ProductUpdate/ProductUpdate.tsx(197,29): error TS2531: Object is possibly 'null'. -src/products/views/ProductUpdate/ProductUpdate.tsx(198,29): error TS2532: Object is possibly 'undefined'. -src/products/views/ProductUpdate/ProductUpdate.tsx(198,29): error TS2531: Object is possibly 'null'. -src/products/views/ProductUpdate/ProductUpdate.tsx(201,21): error TS2532: Object is possibly 'undefined'. -src/products/views/ProductUpdate/ProductUpdate.tsx(201,21): error TS2531: Object is possibly 'null'. -src/products/views/ProductUpdate/ProductUpdate.tsx(214,20): error TS2569: Type 'ProductUpdate_productUpdate_errors[] | null' is not an array type or a string type. Use compiler option '--downlevelIteration' to allow iterating of iterators. -src/products/views/ProductUpdate/ProductUpdate.tsx(215,25): error TS2532: Object is possibly 'undefined'. -src/products/views/ProductUpdate/ProductUpdate.tsx(215,25): error TS2531: Object is possibly 'null'. -src/products/views/ProductUpdate/ProductUpdate.tsx(218,20): error TS2569: Type 'SimpleProductUpdate_productUpdate_errors[] | null' is not an array type or a string type. Use compiler option '--downlevelIteration' to allow iterating of iterators. -src/products/views/ProductUpdate/ProductUpdate.tsx(219,25): error TS2532: Object is possibly 'undefined'. -src/products/views/ProductUpdate/ProductUpdate.tsx(219,25): error TS2531: Object is possibly 'null'. -src/products/views/ProductUpdate/ProductUpdate.tsx(226,32): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/products/views/ProductUpdate/ProductUpdate.tsx(226,51): error TS2532: Object is possibly 'undefined'. -src/products/views/ProductUpdate/ProductUpdate.tsx(226,51): error TS2531: Object is possibly 'null'. -src/products/views/ProductUpdate/ProductUpdate.tsx(235,21): error TS2322: Type '(ProductDetails_product_images | null)[] | null | undefined' is not assignable to type 'ProductDetails_product_images[]'. -src/products/views/ProductUpdate/ProductUpdate.tsx(235,41): error TS2532: Object is possibly 'undefined'. -src/products/views/ProductUpdate/ProductUpdate.tsx(235,41): error TS2531: Object is possibly 'null'. -src/products/views/ProductUpdate/ProductUpdate.tsx(236,21): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/products/views/ProductUpdate/ProductUpdate.tsx(236,41): error TS2532: Object is possibly 'undefined'. -src/products/views/ProductUpdate/ProductUpdate.tsx(238,21): error TS2322: Type 'ProductDetails_product | undefined' is not assignable to type 'ProductDetails_product'. -src/products/views/ProductUpdate/ProductUpdate.tsx(239,21): error TS2322: Type '(ProductDetails_product_variants | null)[] | null | undefined' is not assignable to type 'ProductDetails_product_variants[]'. -src/products/views/ProductUpdate/ProductUpdate.tsx(239,43): error TS2532: Object is possibly 'undefined'. -src/products/views/ProductUpdate/ProductUpdate.tsx(252,54): error TS2532: Object is possibly 'undefined'. -src/products/views/ProductUpdate/ProductUpdate.tsx(316,25): error TS2322: Type 'string[] | undefined' is not assignable to type 'string[]'. -src/products/views/ProductUpdate/ProductUpdate.tsx(330,48): error TS2532: Object is possibly 'undefined'. -src/products/views/ProductUpdate/ProductUpdate.tsx(332,50): error TS2532: Object is possibly 'undefined'. -src/products/views/ProductUpdate/ProductUpdate.tsx(339,21): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/products/views/ProductUpdate/ProductUpdate.tsx(340,23): error TS2532: Object is possibly 'undefined'. -src/products/views/ProductUpdate/ProductUpdate.tsx(340,23): error TS2531: Object is possibly 'null'. -src/products/views/ProductUpdate/ProductUpdate.tsx(340,23): error TS2531: Object is possibly 'null'. -src/products/views/ProductUpdate/ProductUpdate.tsx(342,21): error TS2322: Type 'ProductVariantBulkCreate_productVariantBulkCreate_bulkProductErrors[] | null' is not assignable to type 'ProductVariantBulkCreate_productVariantBulkCreate_bulkProductErrors[]'. -src/products/views/ProductUpdate/ProductUpdate.tsx(344,25): error TS2532: Object is possibly 'undefined'. -src/products/views/ProductUpdate/ProductUpdate.tsx(344,25): error TS2531: Object is possibly 'null'. -src/products/views/ProductUpdate/ProductUpdate.tsx(349,21): error TS2322: Type '(ProductDetails_product_productType_variantAttributes | null)[] | null' is not assignable to type 'ProductDetails_product_productType_variantAttributes[]'. -src/products/views/ProductUpdate/ProductUpdate.tsx(350,29): error TS2532: Object is possibly 'undefined'. -src/products/views/ProductUpdate/ProductUpdate.tsx(350,29): error TS2531: Object is possibly 'null'. -src/products/views/ProductUpdate/ProductUpdate.tsx(353,49): error TS2571: Object is of type 'unknown'. -src/products/views/ProductVariant.tsx(69,16): error TS2531: Object is possibly 'null'. -src/products/views/ProductVariant.tsx(69,16): error TS2531: Object is possibly 'null'. -src/products/views/ProductVariant.tsx(72,23): error TS2531: Object is possibly 'null'. -src/products/views/ProductVariant.tsx(72,23): error TS2345: Argument of type 'VariantUpdate_productVariantUpdate_productErrors[] | null' is not assignable to parameter of type 'SetStateAction'. -src/products/views/ProductVariant.tsx(93,49): error TS2531: Object is possibly 'null'. -src/products/views/ProductVariant.tsx(110,32): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/products/views/ProductVariant.tsx(110,51): error TS2532: Object is possibly 'undefined'. -src/products/views/ProductVariant.tsx(110,51): error TS2531: Object is possibly 'null'. -src/products/views/ProductVariant.tsx(117,21): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/products/views/ProductVariant.tsx(159,21): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/products/views/ProductVariant.tsx(159,39): error TS2532: Object is possibly 'undefined'. -src/products/views/ProductVariant.tsx(159,39): error TS2531: Object is possibly 'null'. -src/products/views/ProductVariantCreate.tsx(38,15): error TS2531: Object is possibly 'null'. -src/products/views/ProductVariantCreate.tsx(38,15): error TS2531: Object is possibly 'null'. -src/products/views/ProductVariantCreate.tsx(47,17): error TS2531: Object is possibly 'null'. -src/products/views/ProductVariantCreate.tsx(47,17): error TS2531: Object is possibly 'null'. -src/products/views/ProductVariantCreate.tsx(92,49): error TS2571: Object is of type 'unknown'. -src/products/views/ProductVariantCreate.tsx(93,21): error TS2322: Type 'VariantCreate_productVariantCreate_productErrors[] | null' is not assignable to type 'VariantCreate_productVariantCreate_productErrors[]'. -src/products/views/ProductVariantCreate.tsx(95,25): error TS2532: Object is possibly 'undefined'. -src/products/views/ProductVariantCreate.tsx(95,25): error TS2531: Object is possibly 'null'. -src/products/views/ProductVariantCreate.tsx(104,21): error TS2322: Type 'ProductVariantCreateData_product | null | undefined' is not assignable to type 'ProductVariantCreateData_product'. -src/products/views/ProductVariantCreate.tsx(104,42): error TS2532: Object is possibly 'undefined'. -src/productTypes/components/AssignAttributeDialog/AssignAttributeDialog.tsx(95,37): error TS2345: Argument of type 'MutableRefObject' is not assignable to parameter of type 'MutableRefObject'. -src/productTypes/components/AssignAttributeDialog/AssignAttributeDialog.tsx(198,53): error TS2345: Argument of type 'MutableRefObject' is not assignable to parameter of type 'MutableRefObject'. -src/productTypes/components/ProductTypeAttributes/ProductTypeAttributes.tsx(154,36): error TS2532: Object is possibly 'undefined'. -src/productTypes/components/ProductTypeAttributes/ProductTypeAttributes.tsx(157,43): error TS2532: Object is possibly 'undefined'. -src/productTypes/components/ProductTypeAttributes/ProductTypeAttributes.tsx(164,46): error TS2532: Object is possibly 'undefined'. -src/productTypes/components/ProductTypeAttributes/ProductTypeAttributes.tsx(168,34): error TS2532: Object is possibly 'undefined'. -src/productTypes/components/ProductTypeAttributes/ProductTypeAttributes.tsx(169,23): error TS2532: Object is possibly 'undefined'. -src/productTypes/components/ProductTypeAttributes/ProductTypeAttributes.tsx(175,34): error TS2532: Object is possibly 'undefined'. -src/productTypes/components/ProductTypeAttributes/ProductTypeAttributes.tsx(176,23): error TS2532: Object is possibly 'undefined'. -src/productTypes/components/ProductTypeAttributes/ProductTypeAttributes.tsx(184,45): error TS2532: Object is possibly 'undefined'. -src/productTypes/components/ProductTypeCreatePage/ProductTypeCreatePage.tsx(55,5): error TS2532: Object is possibly 'undefined'. -src/productTypes/components/ProductTypeCreatePage/ProductTypeCreatePage.tsx(55,5): error TS2345: Argument of type 'string | null' is not assignable to parameter of type 'string'. -src/productTypes/components/ProductTypeDetails/ProductTypeDetails.tsx(53,18): error TS2532: Object is possibly 'undefined'. -src/productTypes/components/ProductTypeDetailsPage/ProductTypeDetailsPage.tsx(71,5): error TS2532: Object is possibly 'undefined'. -src/productTypes/components/ProductTypeDetailsPage/ProductTypeDetailsPage.tsx(71,5): error TS2345: Argument of type 'string | null' is not assignable to parameter of type 'string'. -src/productTypes/components/ProductTypeDetailsPage/ProductTypeDetailsPage.tsx(96,17): error TS2531: Object is possibly 'null'. -src/productTypes/components/ProductTypeDetailsPage/ProductTypeDetailsPage.tsx(108,5): error TS2322: Type '{ label: string | null; value: string; }[]' is not assignable to type 'ChoiceType[]'. -src/productTypes/components/ProductTypeDetailsPage/ProductTypeDetailsPage.tsx(110,11): error TS2531: Object is possibly 'null'. -src/productTypes/components/ProductTypeDetailsPage/ProductTypeDetailsPage.tsx(111,20): error TS2531: Object is possibly 'null'. -src/productTypes/components/ProductTypeDetailsPage/ProductTypeDetailsPage.tsx(112,20): error TS2531: Object is possibly 'null'. -src/productTypes/components/ProductTypeDetailsPage/ProductTypeDetailsPage.tsx(115,5): error TS2322: Type 'string | null' is not assignable to type 'string'. -src/productTypes/components/ProductTypeDetailsPage/ProductTypeDetailsPage.tsx(115,26): error TS2531: Object is possibly 'null'. -src/productTypes/components/ProductTypeDetailsPage/ProductTypeDetailsPage.tsx(116,5): error TS2322: Type '{ label: string | null; value: string; }[]' is not assignable to type 'ChoiceType[]'. -src/productTypes/components/ProductTypeDetailsPage/ProductTypeDetailsPage.tsx(118,11): error TS2531: Object is possibly 'null'. -src/productTypes/components/ProductTypeDetailsPage/ProductTypeDetailsPage.tsx(119,20): error TS2531: Object is possibly 'null'. -src/productTypes/components/ProductTypeDetailsPage/ProductTypeDetailsPage.tsx(120,20): error TS2531: Object is possibly 'null'. -src/productTypes/components/ProductTypeDetailsPage/ProductTypeDetailsPage.tsx(123,5): error TS2322: Type 'number | undefined' is not assignable to type 'number'. -src/productTypes/components/ProductTypeDetailsPage/ProductTypeDetailsPage.tsx(123,25): error TS2531: Object is possibly 'null'. -src/productTypes/components/ProductTypeDetailsPage/ProductTypeDetailsPage.tsx(146,17): error TS2322: Type 'string | null' is not assignable to type 'string'. -src/productTypes/components/ProductTypeDetailsPage/ProductTypeDetailsPage.tsx(158,17): error TS2322: Type '(ProductTypeDetails_productType_productAttributes | null)[] | null | undefined' is not assignable to type 'ProductTypeDetails_productType_productAttributes[] | ProductTypeDetails_productType_variantAttributes[]'. -src/productTypes/components/ProductTypeDetailsPage/ProductTypeDetailsPage.tsx(184,21): error TS2322: Type '(ProductTypeDetails_productType_variantAttributes | null)[] | null | undefined' is not assignable to type 'ProductTypeDetails_productType_productAttributes[] | ProductTypeDetails_productType_variantAttributes[]'. -src/productTypes/components/ProductTypeList/ProductTypeList.tsx(87,35): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/productTypes/components/ProductTypeList/ProductTypeList.tsx(102,35): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/productTypes/components/ProductTypeList/ProductTypeList.tsx(146,41): error TS2532: Object is possibly 'undefined'. -src/productTypes/components/ProductTypeList/ProductTypeList.tsx(153,44): error TS2532: Object is possibly 'undefined'. -src/productTypes/components/ProductTypeList/ProductTypeList.tsx(177,32): error TS2532: Object is possibly 'undefined'. -src/productTypes/components/ProductTypeList/ProductTypeList.tsx(178,21): error TS2532: Object is possibly 'undefined'. -src/productTypes/components/ProductTypeList/ProductTypeList.tsx(198,32): error TS2532: Object is possibly 'undefined'. -src/productTypes/components/ProductTypeList/ProductTypeList.tsx(199,21): error TS2532: Object is possibly 'undefined'. -src/productTypes/components/ProductTypeList/ProductTypeList.tsx(199,21): error TS2531: Object is possibly 'null'. -src/productTypes/components/ProductTypeTaxes/ProductTypeTaxes.tsx(58,11): error TS2322: Type '{ label: string | null; value: string | null; }[]' is not assignable to type 'SingleAutocompleteChoiceType[]'. -src/productTypes/containers/ProductTypeOperations.tsx(48,37): error TS2533: Object is possibly 'null' or 'undefined'. -src/productTypes/containers/ProductTypeOperations.tsx(128,33): error TS2532: Object is possibly 'undefined'. -src/productTypes/containers/ProductTypeOperations.tsx(128,33): error TS2532: Object is possibly 'undefined'. -src/productTypes/containers/ProductTypeOperations.tsx(131,39): error TS2345: Argument of type '(ProductTypeDetailsFragment_productAttributes | null)[] | null' is not assignable to parameter of type 'ProductTypeDetailsFragment_productAttributes[]'. -src/productTypes/containers/ProductTypeOperations.tsx(132,39): error TS2532: Object is possibly 'undefined'. -src/productTypes/containers/ProductTypeOperations.tsx(132,39): error TS2532: Object is possibly 'undefined'. -src/productTypes/containers/ProductTypeOperations.tsx(136,33): error TS2532: Object is possibly 'undefined'. -src/productTypes/containers/ProductTypeOperations.tsx(136,33): error TS2532: Object is possibly 'undefined'. -src/productTypes/containers/ProductTypeOperations.tsx(139,39): error TS2345: Argument of type '(ProductTypeDetailsFragment_variantAttributes | null)[] | null' is not assignable to parameter of type 'ProductTypeDetailsFragment_productAttributes[]'. -src/productTypes/containers/ProductTypeOperations.tsx(140,39): error TS2532: Object is possibly 'undefined'. -src/productTypes/containers/ProductTypeOperations.tsx(140,39): error TS2532: Object is possibly 'undefined'. -src/productTypes/hooks/useAvailableAttributeSearch/index.tsx(40,45): error TS2344: Type 'SearchAttributesVariables' does not satisfy the constraint 'SearchVariables'. -src/productTypes/views/ProductTypeCreate.tsx(22,9): error TS2531: Object is possibly 'null'. -src/productTypes/views/ProductTypeCreate.tsx(22,9): error TS2531: Object is possibly 'null'. -src/productTypes/views/ProductTypeCreate.tsx(28,31): error TS2531: Object is possibly 'null'. -src/productTypes/views/ProductTypeCreate.tsx(28,31): error TS2531: Object is possibly 'null'. -src/productTypes/views/ProductTypeCreate.tsx(58,19): error TS2322: Type 'WeightUnitsEnum | null | undefined' is not assignable to type 'WeightUnitsEnum'. -src/productTypes/views/ProductTypeCreate.tsx(58,50): error TS2532: Object is possibly 'undefined'. -src/productTypes/views/ProductTypeCreate.tsx(58,50): error TS2531: Object is possibly 'null'. -src/productTypes/views/ProductTypeCreate.tsx(60,19): error TS2322: Type 'ProductTypeCreate_productTypeCreate_errors[] | null' is not assignable to type 'UserError[]'. -src/productTypes/views/ProductTypeCreate.tsx(61,27): error TS2532: Object is possibly 'undefined'. -src/productTypes/views/ProductTypeCreate.tsx(61,27): error TS2531: Object is possibly 'null'. -src/productTypes/views/ProductTypeCreate.tsx(70,19): error TS2322: Type '(ProductTypeCreateData_taxTypes | null)[] | null' is not assignable to type 'ProductTypeDetails_taxTypes[]'. -src/productTypes/views/ProductTypeCreate.tsx(70,41): error TS2532: Object is possibly 'undefined'. -src/productTypes/views/ProductTypeList/filters.ts(32,25): error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'. -src/productTypes/views/ProductTypeList/filters.ts(37,42): error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'. -src/productTypes/views/ProductTypeList/ProductTypeList.tsx(95,5): error TS2322: Type '(params?: ProductTypeListUrlQueryParams | undefined) => string' is not assignable to type 'CreateUrl'. -src/productTypes/views/ProductTypeList/ProductTypeList.tsx(128,5): error TS2345: Argument of type 'ProductTypeList_productTypes_pageInfo | undefined' is not assignable to parameter of type 'PageInfo'. -src/productTypes/views/ProductTypeList/ProductTypeList.tsx(128,17): error TS2532: Object is possibly 'undefined'. -src/productTypes/views/ProductTypeList/ProductTypeList.tsx(128,17): error TS2531: Object is possibly 'null'. -src/productTypes/views/ProductTypeList/ProductTypeList.tsx(134,9): error TS2531: Object is possibly 'null'. -src/productTypes/views/ProductTypeList/ProductTypeList.tsx(134,9): error TS2531: Object is possibly 'null'. -src/productTypes/views/ProductTypeList/ProductTypeList.tsx(151,38): error TS2571: Object is of type 'unknown'. -src/productTypes/views/ProductTypeList/ProductTypeList.tsx(159,33): error TS2345: Argument of type '{ variables: { ids: string[] | undefined; }; }' is not assignable to parameter of type 'MutationFunctionOptions'. -src/productTypes/views/ProductTypeList/ProductTypeList.tsx(180,15): error TS2322: Type 'ProductTypeList_productTypes_edges_node[] | undefined' is not assignable to type 'ProductTypeList_productTypes_edges_node[]'. -src/productTypes/views/ProductTypeList/ProductTypeList.tsx(181,17): error TS2532: Object is possibly 'undefined'. -src/productTypes/views/ProductTypeList/ProductTypeList.tsx(181,17): error TS2531: Object is possibly 'null'. -src/productTypes/views/ProductTypeList/ProductTypeList.tsx(224,42): error TS2532: Object is possibly 'undefined'. -src/productTypes/views/ProductTypeList/ProductTypeList.tsx(226,44): error TS2532: Object is possibly 'undefined'. -src/productTypes/views/ProductTypeList/sort.ts(14,7): error TS2322: Type 'undefined' is not assignable to type 'ProductTypeSortField'. -src/productTypes/views/ProductTypeUpdate/index.tsx(74,19): error TS2531: Object is possibly 'null'. -src/productTypes/views/ProductTypeUpdate/index.tsx(74,19): error TS2531: Object is possibly 'null'. -src/productTypes/views/ProductTypeUpdate/index.tsx(80,17): error TS2531: Object is possibly 'null'. -src/productTypes/views/ProductTypeUpdate/index.tsx(81,17): error TS2531: Object is possibly 'null'. -src/productTypes/views/ProductTypeUpdate/index.tsx(83,46): error TS2531: Object is possibly 'null'. -src/productTypes/views/ProductTypeUpdate/index.tsx(83,46): error TS2345: Argument of type 'AssignAttribute_attributeAssign_errors[]' is not assignable to parameter of type 'UserError[]'. -src/productTypes/views/ProductTypeUpdate/index.tsx(89,19): error TS2531: Object is possibly 'null'. -src/productTypes/views/ProductTypeUpdate/index.tsx(89,19): error TS2531: Object is possibly 'null'. -src/productTypes/views/ProductTypeUpdate/index.tsx(101,19): error TS2531: Object is possibly 'null'. -src/productTypes/views/ProductTypeUpdate/index.tsx(101,19): error TS2531: Object is possibly 'null'. -src/productTypes/views/ProductTypeUpdate/index.tsx(114,18): error TS2531: Object is possibly 'null'. -src/productTypes/views/ProductTypeUpdate/index.tsx(115,17): error TS2531: Object is possibly 'null'. -src/productTypes/views/ProductTypeUpdate/index.tsx(121,17): error TS2531: Object is possibly 'null'. -src/productTypes/views/ProductTypeUpdate/index.tsx(122,17): error TS2531: Object is possibly 'null'. -src/productTypes/views/ProductTypeUpdate/index.tsx(124,38): error TS2531: Object is possibly 'null'. -src/productTypes/views/ProductTypeUpdate/index.tsx(124,38): error TS2345: Argument of type 'ProductTypeUpdate_productTypeUpdate_errors[]' is not assignable to parameter of type 'UserError[]'. -src/productTypes/views/ProductTypeUpdate/index.tsx(130,17): error TS2322: Type 'ProductTypeDetails_productType | null | undefined' is not assignable to type 'ProductTypeDetailsFragment'. -src/productTypes/views/ProductTypeUpdate/index.tsx(130,42): error TS2532: Object is possibly 'undefined'. -src/productTypes/views/ProductTypeUpdate/index.tsx(178,35): error TS2532: Object is possibly 'undefined'. -src/productTypes/views/ProductTypeUpdate/index.tsx(180,49): error TS2538: Type 'undefined' cannot be used as an index type. -src/productTypes/views/ProductTypeUpdate/index.tsx(187,29): error TS2322: Type 'string | undefined' is not assignable to type 'string | null'. -src/productTypes/views/ProductTypeUpdate/index.tsx(193,23): error TS2322: Type 'string[] | undefined' is not assignable to type '(string | null)[]'. -src/productTypes/views/ProductTypeUpdate/index.tsx(204,27): error TS2532: Object is possibly 'undefined'. -src/productTypes/views/ProductTypeUpdate/index.tsx(204,27): error TS2531: Object is possibly 'null'. -src/productTypes/views/ProductTypeUpdate/index.tsx(205,27): error TS2532: Object is possibly 'undefined'. -src/productTypes/views/ProductTypeUpdate/index.tsx(205,27): error TS2531: Object is possibly 'null'. -src/productTypes/views/ProductTypeUpdate/index.tsx(209,29): error TS2531: Object is possibly 'null'. -src/productTypes/views/ProductTypeUpdate/index.tsx(209,29): error TS2531: Object is possibly 'null'. -src/productTypes/views/ProductTypeUpdate/index.tsx(219,36): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/productTypes/views/ProductTypeUpdate/index.tsx(219,55): error TS2532: Object is possibly 'undefined'. -src/productTypes/views/ProductTypeUpdate/index.tsx(219,55): error TS2531: Object is possibly 'null'. -src/productTypes/views/ProductTypeUpdate/index.tsx(221,25): error TS2322: Type 'WeightUnitsEnum | null | undefined' is not assignable to type 'WeightUnitsEnum'. -src/productTypes/views/ProductTypeUpdate/index.tsx(222,33): error TS2532: Object is possibly 'undefined'. -src/productTypes/views/ProductTypeUpdate/index.tsx(222,33): error TS2531: Object is possibly 'null'. -src/productTypes/views/ProductTypeUpdate/index.tsx(226,25): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/productTypes/views/ProductTypeUpdate/index.tsx(226,48): error TS2532: Object is possibly 'undefined'. -src/productTypes/views/ProductTypeUpdate/index.tsx(226,48): error TS2531: Object is possibly 'null'. -src/productTypes/views/ProductTypeUpdate/index.tsx(227,25): error TS2322: Type 'ProductTypeDetails_productType | null | undefined' is not assignable to type 'ProductTypeDetails_productType'. -src/productTypes/views/ProductTypeUpdate/index.tsx(227,50): error TS2532: Object is possibly 'undefined'. -src/productTypes/views/ProductTypeUpdate/index.tsx(229,25): error TS2322: Type '(ProductTypeDetails_taxTypes | null)[] | null' is not assignable to type 'ProductTypeDetails_taxTypes[]'. -src/productTypes/views/ProductTypeUpdate/index.tsx(229,47): error TS2532: Object is possibly 'undefined'. -src/productTypes/views/ProductTypeUpdate/index.tsx(322,29): error TS2322: Type '(string | null)[]' is not assignable to type 'string[]'. -src/productTypes/views/ProductTypeUpdate/index.tsx(324,33): error TS2532: Object is possibly 'undefined'. -src/productTypes/views/ProductTypeUpdate/index.tsx(324,33): error TS2531: Object is possibly 'null'. -src/productTypes/views/ProductTypeUpdate/index.tsx(324,33): error TS2531: Object is possibly 'null'. -src/productTypes/views/ProductTypeUpdate/index.tsx(345,29): error TS2322: Type 'string[] | undefined' is not assignable to type 'string[]'. -src/productTypes/views/ProductTypeUpdate/index.tsx(351,40): error TS2532: Object is possibly 'undefined'. -src/productTypes/views/ProductTypeUpdate/index.tsx(352,39): error TS2532: Object is possibly 'undefined'. -src/productTypes/views/ProductTypeUpdate/index.tsx(355,43): error TS2569: Type 'string[] | undefined' is not an array type or a string type. Use compiler option '--downlevelIteration' to allow iterating of iterators. -src/productTypes/views/ProductTypeUpdate/index.tsx(364,43): error TS2532: Object is possibly 'undefined'. -src/productTypes/views/ProductTypeUpdate/index.tsx(364,43): error TS2531: Object is possibly 'null'. -src/productTypes/views/ProductTypeUpdate/index.tsx(370,25): error TS2322: Type 'number | undefined' is not assignable to type 'number'. -src/productTypes/views/ProductTypeUpdate/index.tsx(370,56): error TS2532: Object is possibly 'undefined'. -src/productTypes/views/ProductTypeUpdate/index.tsx(376,33): error TS2532: Object is possibly 'undefined'. -src/productTypes/views/ProductTypeUpdate/index.tsx(376,33): error TS2531: Object is possibly 'null'. -src/productTypes/views/ProductTypeUpdate/index.tsx(384,34): error TS2532: Object is possibly 'undefined'. -src/productTypes/views/ProductTypeUpdate/index.tsx(384,34): error TS2531: Object is possibly 'null'. -src/productTypes/views/ProductTypeUpdate/index.tsx(384,34): error TS2569: Type '(ProductTypeDetails_productType_productAttributes | null)[] | null' is not an array type or a string type. Use compiler option '--downlevelIteration' to allow iterating of iterators. -src/productTypes/views/ProductTypeUpdate/index.tsx(385,34): error TS2532: Object is possibly 'undefined'. -src/productTypes/views/ProductTypeUpdate/index.tsx(385,34): error TS2531: Object is possibly 'null'. -src/productTypes/views/ProductTypeUpdate/index.tsx(385,34): error TS2569: Type '(ProductTypeDetails_productType_variantAttributes | null)[] | null' is not an array type or a string type. Use compiler option '--downlevelIteration' to allow iterating of iterators. -src/productTypes/views/ProductTypeUpdate/index.tsx(395,33): error TS2532: Object is possibly 'undefined'. -src/productTypes/views/ProductTypeUpdate/index.tsx(395,33): error TS2531: Object is possibly 'null'. -src/queries.tsx(86,31): error TS2532: Object is possibly 'undefined'. -src/searches/useCategorySearch.ts(31,35): error TS2344: Type 'SearchCategories' does not satisfy the constraint 'SearchData'. -src/searches/useCollectionSearch.ts(32,3): error TS2344: Type 'SearchCollections' does not satisfy the constraint 'SearchData'. -src/searches/useCustomerSearch.ts(33,35): error TS2344: Type 'SearchCustomers' does not satisfy the constraint 'SearchData'. -src/searches/usePageSearch.ts(24,35): error TS2344: Type 'SearchPages' does not satisfy the constraint 'SearchData'. -src/searches/useProductSearch.ts(30,35): error TS2344: Type 'SearchProducts' does not satisfy the constraint 'SearchData'. -src/searches/useProductTypeSearch.ts(45,3): error TS2344: Type 'SearchProductTypes' does not satisfy the constraint 'SearchData'. -src/searches/useServiceAccountSearch.ts(32,3): error TS2344: Type 'SearchServiceAccount' does not satisfy the constraint 'SearchData'. -src/services/components/ServiceDetailsPage/ServiceDetailsPage.stories.tsx(26,3): error TS2322: Type 'null' is not assignable to type 'string'. -src/services/components/ServiceDetailsPage/ServiceDetailsPage.stories.tsx(32,36): error TS2322: Type 'undefined' is not assignable to type 'ServiceDetails_serviceAccount'. -src/services/components/ServiceDetailsPage/ServiceDetailsPage.tsx(71,13): error TS2531: Object is possibly 'null'. -src/services/components/ServiceDetailsPage/ServiceDetailsPage.tsx(72,27): error TS2531: Object is possibly 'null'. -src/services/components/ServiceDetailsPage/ServiceDetailsPage.tsx(77,5): error TS2322: Type 'boolean | null' is not assignable to type 'boolean'. -src/services/components/ServiceDetailsPage/ServiceDetailsPage.tsx(78,5): error TS2322: Type 'string | null' is not assignable to type 'string'. -src/services/components/ServiceDetailsPage/ServiceDetailsPage.tsx(79,18): error TS2531: Object is possibly 'null'. -src/services/components/ServiceDetailsPage/ServiceDetailsPage.tsx(79,67): error TS2531: Object is possibly 'null'. -src/services/components/ServiceDetailsPage/ServiceDetailsPage.tsx(88,23): error TS2322: Type 'string | null | undefined' is not assignable to type 'string | undefined'. -src/services/components/ServiceDetailsPage/ServiceDetailsPage.tsx(110,17): error TS2322: Type '(ServiceDetails_serviceAccount_tokens | null)[] | null | undefined' is not assignable to type 'ServiceDetailsFragment_tokens[]'. -src/services/components/ServiceList/ServiceList.tsx(87,37): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/services/components/ServiceList/ServiceList.tsx(129,49): error TS2532: Object is possibly 'undefined'. -src/services/components/ServiceList/ServiceList.tsx(133,21): error TS2532: Object is possibly 'undefined'. -src/services/components/ServiceListPage/ServiceListPage.stories.tsx(45,49): error TS2322: Type 'undefined' is not assignable to type 'ServiceList_serviceAccounts_edges_node[]'. -src/services/components/ServiceTokenCreateDialog/ServiceTokenCreateDialog.tsx(117,49): error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'. -src/services/components/ServiceTokens/ServiceTokens.tsx(96,49): error TS2532: Object is possibly 'undefined'. -src/services/components/ServiceTokens/ServiceTokens.tsx(100,35): error TS2532: Object is possibly 'undefined'. -src/services/components/ServiceTokens/ServiceTokens.tsx(107,45): error TS2532: Object is possibly 'undefined'. -src/services/index.tsx(55,52): error TS2345: Argument of type 'null' is not assignable to parameter of type 'string | (() => string)'. -src/services/views/ServiceCreate/ServiceCreate.tsx(27,9): error TS2531: Object is possibly 'null'. -src/services/views/ServiceCreate/ServiceCreate.tsx(27,9): error TS2531: Object is possibly 'null'. -src/services/views/ServiceCreate/ServiceCreate.tsx(31,27): error TS2531: Object is possibly 'null'. -src/services/views/ServiceCreate/ServiceCreate.tsx(31,27): error TS2531: Object is possibly 'null'. -src/services/views/ServiceCreate/ServiceCreate.tsx(32,16): error TS2531: Object is possibly 'null'. -src/services/views/ServiceCreate/ServiceCreate.tsx(32,16): error TS2345: Argument of type 'string | null' is not assignable to parameter of type 'string'. -src/services/views/ServiceCreate/ServiceCreate.tsx(48,21): error TS2571: Object is of type 'unknown'. -src/services/views/ServiceCreate/ServiceCreate.tsx(64,15): error TS2322: Type 'ServiceCreate_serviceAccountCreate_errors[] | null' is not assignable to type 'UserError[]'. -src/services/views/ServiceCreate/ServiceCreate.tsx(65,23): error TS2532: Object is possibly 'undefined'. -src/services/views/ServiceCreate/ServiceCreate.tsx(65,23): error TS2531: Object is possibly 'null'. -src/services/views/ServiceCreate/ServiceCreate.tsx(70,40): error TS2571: Object is of type 'unknown'. -src/services/views/ServiceDetails/ServiceDetails.tsx(63,21): error TS2531: Object is possibly 'null'. -src/services/views/ServiceDetails/ServiceDetails.tsx(63,21): error TS2531: Object is possibly 'null'. -src/services/views/ServiceDetails/ServiceDetails.tsx(70,9): error TS2531: Object is possibly 'null'. -src/services/views/ServiceDetails/ServiceDetails.tsx(70,9): error TS2531: Object is possibly 'null'. -src/services/views/ServiceDetails/ServiceDetails.tsx(90,27): error TS2531: Object is possibly 'null'. -src/services/views/ServiceDetails/ServiceDetails.tsx(90,27): error TS2531: Object is possibly 'null'. -src/services/views/ServiceDetails/ServiceDetails.tsx(95,27): error TS2531: Object is possibly 'null'. -src/services/views/ServiceDetails/ServiceDetails.tsx(95,27): error TS2531: Object is possibly 'null'. -src/services/views/ServiceDetails/ServiceDetails.tsx(123,39): error TS2571: Object is of type 'unknown'. -src/services/views/ServiceDetails/ServiceDetails.tsx(149,41): error TS2345: Argument of type '{ variables: { id: string | undefined; }; }' is not assignable to parameter of type 'MutationFunctionOptions'. -src/services/views/ServiceDetails/ServiceDetails.tsx(159,33): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/services/views/ServiceDetails/ServiceDetails.tsx(161,33): error TS2322: Type 'ServiceUpdate_serviceAccountUpdate_errors[] | null | undefined' is not assignable to type 'UserError[]'. -src/services/views/ServiceDetails/ServiceDetails.tsx(163,37): error TS2532: Object is possibly 'undefined'. -src/services/views/ServiceDetails/ServiceDetails.tsx(163,37): error TS2531: Object is possibly 'null'. -src/services/views/ServiceDetails/ServiceDetails.tsx(178,58): error TS2571: Object is of type 'unknown'. -src/services/views/ServiceDetails/ServiceDetails.tsx(179,33): error TS2322: Type 'ServiceDetails_serviceAccount | null | undefined' is not assignable to type 'ServiceDetails_serviceAccount'. -src/services/views/ServiceDetails/ServiceDetails.tsx(179,54): error TS2532: Object is possibly 'undefined'. -src/services/views/ServiceDetails/ServiceDetails.tsx(184,33): error TS2322: Type 'string | null' is not assignable to type 'string'. -src/services/views/ServiceDetails/ServiceDetails.tsx(185,41): error TS2532: Object is possibly 'undefined'. -src/services/views/ServiceDetails/ServiceDetails.tsx(185,41): error TS2531: Object is possibly 'null'. -src/services/views/ServiceDetails/ServiceDetails.tsx(197,33): error TS2322: Type 'string | null | undefined' is not assignable to type 'string | undefined'. -src/services/views/ServiceDetails/ServiceDetails.tsx(199,37): error TS2532: Object is possibly 'undefined'. -src/services/views/ServiceDetails/ServiceDetails.tsx(199,37): error TS2531: Object is possibly 'null'. -src/services/views/ServiceDetails/ServiceDetails.tsx(206,49): error TS2532: Object is possibly 'undefined'. -src/services/views/ServiceDetails/ServiceDetails.tsx(206,49): error TS2531: Object is possibly 'null'. -src/services/views/ServiceDetails/ServiceDetails.tsx(206,49): error TS2531: Object is possibly 'null'. -src/services/views/ServiceDetails/ServiceDetails.tsx(207,46): error TS2531: Object is possibly 'null'. -src/services/views/ServiceDetails/ServiceDetails.tsx(209,39): error TS2533: Object is possibly 'null' or 'undefined'. -src/services/views/ServiceDetails/ServiceDetails.tsx(210,44): error TS2533: Object is possibly 'null' or 'undefined'. -src/services/views/ServiceDetails/ServiceDetails.tsx(213,50): error TS2533: Object is possibly 'null' or 'undefined'. -src/services/views/ServiceList/ServiceList.tsx(89,5): error TS2322: Type '(params?: ServiceListUrlQueryParams | undefined) => string' is not assignable to type 'CreateUrl'. -src/services/views/ServiceList/ServiceList.tsx(120,5): error TS2345: Argument of type 'ServiceList_serviceAccounts_pageInfo | undefined' is not assignable to parameter of type 'PageInfo'. -src/services/views/ServiceList/ServiceList.tsx(120,17): error TS2532: Object is possibly 'undefined'. -src/services/views/ServiceList/ServiceList.tsx(120,17): error TS2531: Object is possibly 'null'. -src/services/views/ServiceList/ServiceList.tsx(128,9): error TS2531: Object is possibly 'null'. -src/services/views/ServiceList/ServiceList.tsx(128,9): error TS2531: Object is possibly 'null'. -src/services/views/ServiceList/ServiceList.tsx(138,38): error TS2571: Object is of type 'unknown'. -src/services/views/ServiceList/ServiceList.tsx(144,25): error TS2345: Argument of type '{ variables: { id: string | undefined; }; }' is not assignable to parameter of type 'MutationFunctionOptions'. -src/services/views/ServiceList/ServiceList.tsx(167,15): error TS2322: Type 'ServiceList_serviceAccounts_edges_node[] | undefined' is not assignable to type 'ServiceList_serviceAccounts_edges_node[]'. -src/services/views/ServiceList/ServiceList.tsx(168,17): error TS2532: Object is possibly 'undefined'. -src/services/views/ServiceList/ServiceList.tsx(168,17): error TS2531: Object is possibly 'null'. -src/services/views/ServiceList/ServiceList.tsx(186,15): error TS2322: Type 'string | null' is not assignable to type 'string'. -src/services/views/ServiceList/ServiceList.tsx(188,19): error TS2532: Object is possibly 'undefined'. -src/services/views/ServiceList/ServiceList.tsx(188,19): error TS2531: Object is possibly 'null'. -src/services/views/ServiceList/ServiceList.tsx(188,19): error TS2532: Object is possibly 'undefined'. -src/services/views/ServiceList/sort.ts(12,7): error TS2322: Type 'undefined' is not assignable to type 'ServiceAccountSortField'. -src/shipping/components/ShippingZoneCreatePage/ShippingZoneCreatePage.tsx(75,19): error TS2322: Type '(CountryFragment | undefined)[]' is not assignable to type 'CountryFragment[]'. -src/shipping/components/ShippingZoneDetailsPage/ShippingZoneDetailsPage.tsx(75,17): error TS2322: Type '(ShippingZoneDetailsFragment_countries | null)[] | null | undefined' is not assignable to type 'CountryFragment[]'. -src/shipping/components/ShippingZoneDetailsPage/ShippingZoneDetailsPage.tsx(102,17): error TS2322: Type '(ShippingZoneDetailsFragment_shippingMethods | null)[] | undefined' is not assignable to type 'ShippingZoneDetailsFragment_shippingMethods[]'. -src/shipping/components/ShippingZoneDetailsPage/ShippingZoneDetailsPage.tsx(103,19): error TS2531: Object is possibly 'null'. -src/shipping/components/ShippingZoneDetailsPage/ShippingZoneDetailsPage.tsx(104,31): error TS2531: Object is possibly 'null'. -src/shipping/components/ShippingZoneDetailsPage/ShippingZoneDetailsPage.tsx(115,17): error TS2322: Type '(ShippingZoneDetailsFragment_shippingMethods | null)[] | undefined' is not assignable to type 'ShippingZoneDetailsFragment_shippingMethods[]'. -src/shipping/components/ShippingZoneDetailsPage/ShippingZoneDetailsPage.tsx(116,19): error TS2531: Object is possibly 'null'. -src/shipping/components/ShippingZoneDetailsPage/ShippingZoneDetailsPage.tsx(117,31): error TS2531: Object is possibly 'null'. -src/shipping/components/ShippingZoneRateDialog/ShippingZoneRateDialog.tsx(94,31): error TS2531: Object is possibly 'null'. -src/shipping/components/ShippingZoneRateDialog/ShippingZoneRateDialog.tsx(97,29): error TS2531: Object is possibly 'null'. -src/shipping/components/ShippingZoneRateDialog/ShippingZoneRateDialog.tsx(98,29): error TS2531: Object is possibly 'null'. -src/shipping/components/ShippingZoneRateDialog/ShippingZoneRateDialog.tsx(101,29): error TS2531: Object is possibly 'null'. -src/shipping/components/ShippingZoneRateDialog/ShippingZoneRateDialog.tsx(102,29): error TS2531: Object is possibly 'null'. -src/shipping/components/ShippingZoneRateDialog/ShippingZoneRateDialog.tsx(105,30): error TS2531: Object is possibly 'null'. -src/shipping/components/ShippingZoneRates/ShippingZoneRates.tsx(128,49): error TS2532: Object is possibly 'undefined'. -src/shipping/components/ShippingZoneRates/ShippingZoneRates.tsx(135,27): error TS2322: Type 'ShippingZoneDetailsFragment_shippingMethods_minimumOrderPrice | null' is not assignable to type 'IMoney | undefined'. -src/shipping/components/ShippingZoneRates/ShippingZoneRates.tsx(135,33): error TS2532: Object is possibly 'undefined'. -src/shipping/components/ShippingZoneRates/ShippingZoneRates.tsx(136,27): error TS2322: Type 'ShippingZoneDetailsFragment_shippingMethods_maximumOrderPrice | null' is not assignable to type 'IMoney | undefined'. -src/shipping/components/ShippingZoneRates/ShippingZoneRates.tsx(136,31): error TS2532: Object is possibly 'undefined'. -src/shipping/components/ShippingZoneRates/ShippingZoneRates.tsx(140,27): error TS2322: Type 'ShippingZoneDetailsFragment_shippingMethods_minimumOrderWeight | null' is not assignable to type 'Weight | undefined'. -src/shipping/components/ShippingZoneRates/ShippingZoneRates.tsx(140,33): error TS2532: Object is possibly 'undefined'. -src/shipping/components/ShippingZoneRates/ShippingZoneRates.tsx(141,27): error TS2322: Type 'ShippingZoneDetailsFragment_shippingMethods_maximumOrderWeight | null' is not assignable to type 'Weight | undefined'. -src/shipping/components/ShippingZoneRates/ShippingZoneRates.tsx(141,31): error TS2532: Object is possibly 'undefined'. -src/shipping/components/ShippingZoneRates/ShippingZoneRates.tsx(150,30): error TS2322: Type 'ShippingZoneDetailsFragment_shippingMethods_price | null' is not assignable to type 'IMoney'. -src/shipping/components/ShippingZoneRates/ShippingZoneRates.tsx(150,37): error TS2532: Object is possibly 'undefined'. -src/shipping/components/ShippingZoneRates/ShippingZoneRates.tsx(157,45): error TS2532: Object is possibly 'undefined'. -src/shipping/components/ShippingZoneRates/ShippingZoneRates.tsx(163,47): error TS2532: Object is possibly 'undefined'. -src/shipping/components/ShippingZonesList/ShippingZonesList.tsx(150,46): error TS2532: Object is possibly 'undefined'. -src/shipping/components/ShippingZonesList/ShippingZonesList.tsx(155,29): error TS2532: Object is possibly 'undefined'. -src/shipping/components/ShippingZonesList/ShippingZonesList.tsx(161,29): error TS2532: Object is possibly 'undefined'. -src/shipping/components/ShippingZonesList/ShippingZonesList.tsx(161,29): error TS2531: Object is possibly 'null'. -src/shipping/components/ShippingZonesList/ShippingZonesList.tsx(171,34): error TS2532: Object is possibly 'undefined'. -src/shipping/views/ShippingZoneCreate.tsx(21,9): error TS2531: Object is possibly 'null'. -src/shipping/views/ShippingZoneCreate.tsx(21,9): error TS2531: Object is possibly 'null'. -src/shipping/views/ShippingZoneCreate.tsx(25,32): error TS2531: Object is possibly 'null'. -src/shipping/views/ShippingZoneCreate.tsx(25,32): error TS2531: Object is possibly 'null'. -src/shipping/views/ShippingZoneCreate.tsx(32,34): error TS2571: Object is of type 'unknown'. -src/shipping/views/ShippingZoneCreate.tsx(34,11): error TS2322: Type 'CreateShippingZone_shippingZoneCreate_errors[] | null | undefined' is not assignable to type 'UserError[]'. -src/shipping/views/ShippingZoneCreate.tsx(35,19): error TS2532: Object is possibly 'undefined'. -src/shipping/views/ShippingZoneCreate.tsx(35,19): error TS2531: Object is possibly 'null'. -src/shipping/views/ShippingZoneDetails/index.tsx(40,9): error TS2531: Object is possibly 'null'. -src/shipping/views/ShippingZoneDetails/index.tsx(40,9): error TS2531: Object is possibly 'null'. -src/shipping/views/ShippingZoneDetails/index.tsx(49,9): error TS2531: Object is possibly 'null'. -src/shipping/views/ShippingZoneDetails/index.tsx(49,9): error TS2531: Object is possibly 'null'. -src/shipping/views/ShippingZoneDetails/index.tsx(58,9): error TS2531: Object is possibly 'null'. -src/shipping/views/ShippingZoneDetails/index.tsx(58,9): error TS2531: Object is possibly 'null'. -src/shipping/views/ShippingZoneDetails/index.tsx(67,9): error TS2531: Object is possibly 'null'. -src/shipping/views/ShippingZoneDetails/index.tsx(67,9): error TS2531: Object is possibly 'null'. -src/shipping/views/ShippingZoneDetails/index.tsx(76,9): error TS2531: Object is possibly 'null'. -src/shipping/views/ShippingZoneDetails/index.tsx(76,9): error TS2531: Object is possibly 'null'. -src/shipping/views/ShippingZoneDetails/index.tsx(98,17): error TS2322: Type 'UpdateShippingZone_shippingZoneUpdate_errors[] | null | undefined' is not assignable to type 'UserError[]'. -src/shipping/views/ShippingZoneDetails/index.tsx(100,21): error TS2532: Object is possibly 'undefined'. -src/shipping/views/ShippingZoneDetails/index.tsx(100,21): error TS2531: Object is possibly 'null'. -src/shipping/views/ShippingZoneDetails/index.tsx(174,17): error TS2322: Type 'ShippingZone_shippingZone | null | undefined' is not assignable to type 'ShippingZoneDetailsFragment'. -src/shipping/views/ShippingZoneDetails/index.tsx(174,43): error TS2532: Object is possibly 'undefined'. -src/shipping/views/ShippingZoneDetails/index.tsx(186,17): error TS2322: Type 'ShippingZone_shippingZone | null | undefined' is not assignable to type 'ShippingZoneDetailsFragment'. -src/shipping/views/ShippingZoneDetails/index.tsx(186,43): error TS2532: Object is possibly 'undefined'. -src/shipping/views/ShippingZoneDetails/ShippingZoneDetailsDialogs.tsx(49,5): error TS2531: Object is possibly 'null'. -src/shipping/views/ShippingZoneDetails/ShippingZoneDetailsDialogs.tsx(49,47): error TS2531: Object is possibly 'null'. -src/shipping/views/ShippingZoneDetails/ShippingZoneDetailsDialogs.tsx(57,38): error TS2571: Object is of type 'unknown'. -src/shipping/views/ShippingZoneDetails/ShippingZoneDetailsDialogs.tsx(59,9): error TS2322: Type 'UpdateShippingRate_shippingPriceUpdate_errors[] | null' is not assignable to type 'UserError[]'. -src/shipping/views/ShippingZoneDetails/ShippingZoneDetailsDialogs.tsx(60,17): error TS2532: Object is possibly 'undefined'. -src/shipping/views/ShippingZoneDetails/ShippingZoneDetailsDialogs.tsx(60,17): error TS2531: Object is possibly 'null'. -src/shipping/views/ShippingZoneDetails/ShippingZoneDetailsDialogs.tsx(66,13): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/shipping/views/ShippingZoneDetails/ShippingZoneDetailsDialogs.tsx(77,33): error TS2533: Object is possibly 'null' or 'undefined'. -src/shipping/views/ShippingZoneDetails/ShippingZoneDetailsDialogs.tsx(82,9): error TS2322: Type 'ShippingZoneDetailsFragment_shippingMethods | null | undefined' is not assignable to type 'ShippingZoneDetailsFragment_shippingMethods'. -src/shipping/views/ShippingZoneDetails/ShippingZoneDetailsDialogs.tsx(83,9): error TS2322: Type 'ShippingMethodTypeEnum | null | undefined' is not assignable to type 'ShippingMethodTypeEnum'. -src/shipping/views/ShippingZoneDetails/ShippingZoneDetailsDialogs.tsx(83,30): error TS2533: Object is possibly 'null' or 'undefined'. -src/shipping/views/ShippingZoneDetails/ShippingZoneDetailsDialogs.tsx(90,13): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/shipping/views/ShippingZoneDetails/ShippingZoneDetailsDialogs.tsx(106,33): error TS2533: Object is possibly 'null' or 'undefined'. -src/shipping/views/ShippingZoneDetails/ShippingZoneDetailsDialogs.tsx(114,38): error TS2571: Object is of type 'unknown'. -src/shipping/views/ShippingZoneDetails/ShippingZoneDetailsDialogs.tsx(116,9): error TS2322: Type 'CreateShippingRate_shippingPriceCreate_errors[] | null' is not assignable to type 'UserError[]'. -src/shipping/views/ShippingZoneDetails/ShippingZoneDetailsDialogs.tsx(117,17): error TS2532: Object is possibly 'undefined'. -src/shipping/views/ShippingZoneDetails/ShippingZoneDetailsDialogs.tsx(117,17): error TS2531: Object is possibly 'null'. -src/shipping/views/ShippingZoneDetails/ShippingZoneDetailsDialogs.tsx(157,9): error TS2322: Type 'undefined' is not assignable to type 'ShippingZoneDetailsFragment_shippingMethods'. -src/shipping/views/ShippingZoneDetails/ShippingZoneDetailsDialogs.tsx(158,9): error TS2322: Type 'ShippingMethodTypeEnum | undefined' is not assignable to type 'ShippingMethodTypeEnum'. -src/shipping/views/ShippingZoneDetails/ShippingZoneDetailsDialogs.tsx(188,32): error TS2571: Object is of type 'unknown'. -src/shipping/views/ShippingZoneDetails/ShippingZoneDetailsDialogs.tsx(190,17): error TS2531: Object is possibly 'null'. -src/shipping/views/ShippingZoneDetails/ShippingZoneDetailsDialogs.tsx(190,55): error TS2531: Object is possibly 'null'. -src/shipping/views/ShippingZoneDetails/ShippingZoneDetailsDialogs.tsx(213,26): error TS2531: Object is possibly 'null'. -src/shipping/views/ShippingZoneDetails/ShippingZoneDetailsDialogs.tsx(214,36): error TS2531: Object is possibly 'null'. -src/shipping/views/ShippingZoneDetails/ShippingZoneDetailsDialogs.tsx(215,33): error TS2531: Object is possibly 'null'. -src/shipping/views/ShippingZoneDetails/ShippingZoneDetailsDialogs.tsx(235,23): error TS2531: Object is possibly 'null'. -src/shipping/views/ShippingZoneDetails/ShippingZoneDetailsDialogs.tsx(235,23): error TS2533: Object is possibly 'null' or 'undefined'. -src/shipping/views/ShippingZoneDetails/ShippingZoneDetailsDialogs.tsx(236,36): error TS2531: Object is possibly 'null'. -src/shipping/views/ShippingZonesList.tsx(49,11): error TS2339: Property 'user' does not exist on type 'unknown'. -src/shipping/views/ShippingZonesList.tsx(66,15): error TS2531: Object is possibly 'null'. -src/shipping/views/ShippingZonesList.tsx(66,15): error TS2531: Object is possibly 'null'. -src/shipping/views/ShippingZonesList.tsx(84,15): error TS2531: Object is possibly 'null'. -src/shipping/views/ShippingZonesList.tsx(84,15): error TS2531: Object is possibly 'null'. -src/shipping/views/ShippingZonesList.tsx(94,15): error TS2531: Object is possibly 'null'. -src/shipping/views/ShippingZonesList.tsx(94,15): error TS2531: Object is possibly 'null'. -src/shipping/views/ShippingZonesList.tsx(119,25): error TS2345: Argument of type 'ShippingZones_shippingZones_pageInfo | undefined' is not assignable to parameter of type 'PageInfo'. -src/shipping/views/ShippingZonesList.tsx(119,37): error TS2532: Object is possibly 'undefined'. -src/shipping/views/ShippingZonesList.tsx(119,37): error TS2531: Object is possibly 'null'. -src/shipping/views/ShippingZonesList.tsx(128,37): error TS2571: Object is of type 'unknown'. -src/shipping/views/ShippingZonesList.tsx(136,29): error TS2322: Type 'ShippingZones_shippingZones_edges_node[] | undefined' is not assignable to type 'ShippingZoneFragment[]'. -src/shipping/views/ShippingZonesList.tsx(137,31): error TS2532: Object is possibly 'undefined'. -src/shipping/views/ShippingZonesList.tsx(137,31): error TS2531: Object is possibly 'null'. -src/shipping/views/ShippingZonesList.tsx(193,50): error TS2345: Argument of type '{ variables: { id: string | undefined; }; }' is not assignable to parameter of type 'MutationFunctionOptions'. -src/shipping/views/ShippingZonesList.tsx(206,43): error TS2532: Object is possibly 'undefined'. -src/shipping/views/ShippingZonesList.tsx(206,43): error TS2531: Object is possibly 'null'. -src/shipping/views/ShippingZonesList.tsx(206,43): error TS2532: Object is possibly 'undefined'. -src/shipping/views/ShippingZonesList.tsx(229,54): error TS2345: Argument of type '{ variables: { ids: string[] | undefined; }; }' is not assignable to parameter of type 'MutationFunctionOptions'. -src/shipping/views/ShippingZonesList.tsx(239,56): error TS2532: Object is possibly 'undefined'. -src/shipping/views/ShippingZonesList.tsx(242,52): error TS2532: Object is possibly 'undefined'. -src/siteSettings/components/SiteSettingsKeys/SiteSettingsKeys.tsx(86,70): error TS2532: Object is possibly 'undefined'. -src/siteSettings/components/SiteSettingsKeys/SiteSettingsKeys.tsx(89,49): error TS2532: Object is possibly 'undefined'. -src/siteSettings/components/SiteSettingsKeys/SiteSettingsKeys.tsx(94,49): error TS2532: Object is possibly 'undefined'. -src/siteSettings/components/SiteSettingsKeys/SiteSettingsKeys.tsx(97,55): error TS2532: Object is possibly 'undefined'. -src/siteSettings/components/SiteSettingsPage/SiteSettingsPage.tsx(102,17): error TS2531: Object is possibly 'null'. -src/siteSettings/components/SiteSettingsPage/SiteSettingsPage.tsx(111,23): error TS2531: Object is possibly 'null'. -src/siteSettings/components/SiteSettingsPage/SiteSettingsPage.tsx(112,30): error TS2531: Object is possibly 'null'. -src/siteSettings/components/SiteSettingsPage/SiteSettingsPage.tsx(113,26): error TS2531: Object is possibly 'null'. -src/siteSettings/components/SiteSettingsPage/SiteSettingsPage.tsx(114,30): error TS2531: Object is possibly 'null'. -src/siteSettings/components/SiteSettingsPage/SiteSettingsPage.tsx(115,5): error TS2322: Type 'string | null' is not assignable to type 'string'. -src/siteSettings/components/SiteSettingsPage/SiteSettingsPage.tsx(115,24): error TS2531: Object is possibly 'null'. -src/siteSettings/components/SiteSettingsPage/SiteSettingsPage.tsx(116,29): error TS2531: Object is possibly 'null'. -src/siteSettings/components/SiteSettingsPage/SiteSettingsPage.tsx(117,33): error TS2531: Object is possibly 'null'. -src/siteSettings/components/SiteSettingsPage/SiteSettingsPage.tsx(118,33): error TS2531: Object is possibly 'null'. -src/siteSettings/components/SiteSettingsPage/SiteSettingsPage.tsx(122,5): error TS2322: Type 'string | null' is not assignable to type 'string'. -src/siteSettings/components/SiteSettingsPage/SiteSettingsPage.tsx(123,5): error TS2322: Type 'string | null' is not assignable to type 'string'. -src/siteSettings/components/SiteSettingsPage/SiteSettingsPage.tsx(124,5): error TS2322: Type 'string | null' is not assignable to type 'string'. -src/siteSettings/components/SiteSettingsPage/SiteSettingsPage.tsx(125,5): error TS2322: Type 'string | null' is not assignable to type 'string'. -src/siteSettings/components/SiteSettingsPage/SiteSettingsPage.tsx(145,11): error TS2345: Argument of type '(SiteSettings_shop_countries | null)[]' is not assignable to parameter of type 'ShopInfo_shop_countries[]'. -src/siteSettings/components/SiteSettingsPage/SiteSettingsPage.tsx(230,17): error TS2322: Type '(SiteSettings_shop_authorizationKeys | null)[] | undefined' is not assignable to type 'SiteSettings_shop_authorizationKeys[]'. -src/siteSettings/fixtures.ts(13,3): error TS2322: Type '{ __typename: "Address"; city: string; cityArea: string; companyName: string; country: { __typename: "CountryDisplay"; code: string; country: string; }; countryArea: null; firstName: null; id: string; ... 4 more ...; streetAddress2: null; }' is not assignable to type 'SiteSettings_shop_companyAddress'. -src/siteSettings/views/index.tsx(40,22): error TS2531: Object is possibly 'null'. -src/siteSettings/views/index.tsx(40,22): error TS2531: Object is possibly 'null'. -src/siteSettings/views/index.tsx(48,22): error TS2531: Object is possibly 'null'. -src/siteSettings/views/index.tsx(48,22): error TS2531: Object is possibly 'null'. -src/siteSettings/views/index.tsx(59,27): error TS2531: Object is possibly 'null'. -src/siteSettings/views/index.tsx(59,27): error TS2531: Object is possibly 'null'. -src/siteSettings/views/index.tsx(67,9): error TS2531: Object is possibly 'null'. -src/siteSettings/views/index.tsx(68,9): error TS2531: Object is possibly 'null'. -src/siteSettings/views/index.tsx(69,9): error TS2531: Object is possibly 'null'. -src/siteSettings/views/index.tsx(70,9): error TS2531: Object is possibly 'null'. -src/siteSettings/views/index.tsx(71,9): error TS2531: Object is possibly 'null'. -src/siteSettings/views/index.tsx(72,9): error TS2531: Object is possibly 'null'. -src/siteSettings/views/index.tsx(92,26): error TS2569: Type 'ShopSettingsUpdate_shopDomainUpdate_errors[] | null' is not an array type or a string type. Use compiler option '--downlevelIteration' to allow iterating of iterators. -src/siteSettings/views/index.tsx(94,27): error TS2532: Object is possibly 'undefined'. -src/siteSettings/views/index.tsx(94,27): error TS2531: Object is possibly 'null'. -src/siteSettings/views/index.tsx(97,26): error TS2569: Type 'ShopSettingsUpdate_shopSettingsUpdate_errors[] | null' is not an array type or a string type. Use compiler option '--downlevelIteration' to allow iterating of iterators. -src/siteSettings/views/index.tsx(99,27): error TS2532: Object is possibly 'undefined'. -src/siteSettings/views/index.tsx(99,27): error TS2531: Object is possibly 'null'. -src/siteSettings/views/index.tsx(102,26): error TS2569: Type 'ShopSettingsUpdate_shopAddressUpdate_errors[] | null' is not an array type or a string type. Use compiler option '--downlevelIteration' to allow iterating of iterators. -src/siteSettings/views/index.tsx(104,27): error TS2532: Object is possibly 'undefined'. -src/siteSettings/views/index.tsx(104,27): error TS2531: Object is possibly 'null'. -src/siteSettings/views/index.tsx(168,27): error TS2322: Type 'SiteSettings_shop | null | undefined' is not assignable to type 'SiteSettings_shop'. -src/siteSettings/views/index.tsx(168,45): error TS2532: Object is possibly 'undefined'. -src/siteSettings/views/index.tsx(186,27): error TS2322: Type 'AuthorizationKeyAdd_authorizationKeyAdd_errors[] | null' is not assignable to type 'UserError[]'. -src/siteSettings/views/index.tsx(188,31): error TS2532: Object is possibly 'undefined'. -src/siteSettings/views/index.tsx(188,31): error TS2531: Object is possibly 'null'. -src/staff/components/StaffDetailsPage/StaffDetailsPage.tsx(76,13): error TS2531: Object is possibly 'null'. -src/staff/components/StaffDetailsPage/StaffDetailsPage.tsx(77,27): error TS2531: Object is possibly 'null'. -src/staff/components/StaffDetailsPage/StaffDetailsPage.tsx(84,18): error TS2531: Object is possibly 'null'. -src/staff/components/StaffDetailsPage/StaffDetailsPage.tsx(84,71): error TS2531: Object is possibly 'null'. -src/staff/components/StaffList/StaffList.tsx(95,37): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/staff/components/StaffList/StaffList.tsx(110,37): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/staff/components/StaffList/StaffList.tsx(124,13): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. -src/staff/components/StaffList/StaffList.tsx(129,13): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. -src/staff/components/StaffList/StaffList.tsx(150,32): error TS2532: Object is possibly 'undefined'. -src/staff/components/StaffList/StaffList.tsx(150,32): error TS2531: Object is possibly 'null'. -src/staff/components/StaffList/StaffList.tsx(153,40): error TS2532: Object is possibly 'undefined'. -src/staff/components/StaffList/StaffList.tsx(153,40): error TS2531: Object is possibly 'null'. -src/staff/components/StaffList/StaffList.tsx(167,23): error TS2532: Object is possibly 'undefined'. -src/staff/components/StaffList/StaffList.tsx(181,47): error TS2532: Object is possibly 'undefined'. -src/staff/components/StaffProperties/StaffProperties.tsx(125,31): error TS2531: Object is possibly 'null'. -src/staff/components/StaffProperties/StaffProperties.tsx(139,28): error TS2531: Object is possibly 'null'. -src/staff/components/StaffProperties/StaffProperties.tsx(142,36): error TS2531: Object is possibly 'null'. -src/staff/components/StaffProperties/StaffProperties.tsx(167,54): error TS2531: Object is possibly 'null'. -src/staff/views/StaffDetails.tsx(56,9): error TS2531: Object is possibly 'null'. -src/staff/views/StaffDetails.tsx(56,9): error TS2531: Object is possibly 'null'. -src/staff/views/StaffDetails.tsx(79,28): error TS2531: Object is possibly 'null'. -src/staff/views/StaffDetails.tsx(79,28): error TS2531: Object is possibly 'null'. -src/staff/views/StaffDetails.tsx(86,28): error TS2531: Object is possibly 'null'. -src/staff/views/StaffDetails.tsx(86,28): error TS2531: Object is possibly 'null'. -src/staff/views/StaffDetails.tsx(94,28): error TS2531: Object is possibly 'null'. -src/staff/views/StaffDetails.tsx(94,28): error TS2531: Object is possibly 'null'. -src/staff/views/StaffDetails.tsx(101,28): error TS2531: Object is possibly 'null'. -src/staff/views/StaffDetails.tsx(101,28): error TS2531: Object is possibly 'null'. -src/staff/views/StaffDetails.tsx(126,35): error TS2571: Object is of type 'unknown'. -src/staff/views/StaffDetails.tsx(126,52): error TS2532: Object is possibly 'undefined'. -src/staff/views/StaffDetails.tsx(126,52): error TS2531: Object is possibly 'null'. -src/staff/views/StaffDetails.tsx(184,58): error TS2571: Object is of type 'unknown'. -src/staff/views/StaffDetails.tsx(185,33): error TS2322: Type 'StaffMemberDetails_user | undefined' is not assignable to type 'StaffMemberDetails_user'. -src/staff/views/StaffDetails.tsx(203,58): error TS2532: Object is possibly 'undefined'. -src/staff/views/StaffDetails.tsx(203,58): error TS2531: Object is possibly 'null'. -src/staff/views/StaffDetails.tsx(225,56): error TS2532: Object is possibly 'undefined'. -src/staff/views/StaffDetails.tsx(225,56): error TS2531: Object is possibly 'null'. -src/staff/views/StaffDetails.tsx(234,33): error TS2322: Type 'ChangeStaffPassword_passwordChange_errors[] | null' is not assignable to type 'UserError[]'. -src/staff/views/StaffDetails.tsx(236,37): error TS2532: Object is possibly 'undefined'. -src/staff/views/StaffDetails.tsx(236,37): error TS2531: Object is possibly 'null'. -src/staff/views/StaffList/filters.ts(27,42): error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'. -src/staff/views/StaffList/sort.ts(12,7): error TS2322: Type 'undefined' is not assignable to type 'UserSortField'. -src/staff/views/StaffList/StaffList.tsx(67,38): error TS2571: Object is of type 'unknown'. -src/staff/views/StaffList/StaffList.tsx(95,5): error TS2322: Type '(params?: StaffListUrlQueryParams | undefined) => string' is not assignable to type 'CreateUrl'. -src/staff/views/StaffList/StaffList.tsx(126,9): error TS2531: Object is possibly 'null'. -src/staff/views/StaffList/StaffList.tsx(126,9): error TS2531: Object is possibly 'null'. -src/staff/views/StaffList/StaffList.tsx(130,38): error TS2531: Object is possibly 'null'. -src/staff/views/StaffList/StaffList.tsx(130,38): error TS2531: Object is possibly 'null'. -src/staff/views/StaffList/StaffList.tsx(145,33): error TS2571: Object is of type 'unknown'. -src/staff/views/StaffList/StaffList.tsx(157,11): error TS2345: Argument of type 'StaffList_staffUsers_pageInfo | undefined' is not assignable to parameter of type 'PageInfo'. -src/staff/views/StaffList/StaffList.tsx(157,23): error TS2532: Object is possibly 'undefined'. -src/staff/views/StaffList/StaffList.tsx(157,23): error TS2531: Object is possibly 'null'. -src/staff/views/StaffList/StaffList.tsx(182,15): error TS2322: Type 'StaffList_staffUsers_edges_node[] | undefined' is not assignable to type 'StaffList_staffUsers_edges_node[]'. -src/staff/views/StaffList/StaffList.tsx(183,17): error TS2532: Object is possibly 'undefined'. -src/staff/views/StaffList/StaffList.tsx(183,17): error TS2531: Object is possibly 'null'. -src/staff/views/StaffList/StaffList.tsx(195,15): error TS2322: Type 'StaffMemberAdd_staffCreate_errors[] | null' is not assignable to type 'UserError[]'. -src/staff/views/StaffList/StaffList.tsx(196,23): error TS2532: Object is possibly 'undefined'. -src/staff/views/StaffList/StaffList.tsx(196,23): error TS2531: Object is possibly 'null'. -src/storybook/mock.tsx(39,22): error TS2769: No overload matches this call. -src/storybook/mock.tsx(47,20): error TS2769: No overload matches this call. -src/storybook/mock.tsx(49,5): error TS2322: Type 'Timeout' is not assignable to type 'null'. -src/storybook/mock.tsx(61,5): error TS2322: Type 'Timeout' is not assignable to type 'null'. -src/storybook/mock.tsx(71,5): error TS2322: Type 'Timeout' is not assignable to type 'null'. -src/storybook/stories/attributes/AttributeListPage.tsx(64,35): error TS2322: Type 'undefined' is not assignable to type 'AttributeList_attributes_edges_node[]'. -src/storybook/stories/attributes/AttributePage.tsx(24,3): error TS2322: Type '(AttributeDetailsFragment_values | null)[] | null' is not assignable to type 'AttributeDetailsFragment_values[]'. -src/storybook/stories/attributes/AttributePage.tsx(33,7): error TS2322: Type 'undefined' is not assignable to type 'AttributeDetailsFragment | null'. -src/storybook/stories/attributes/AttributePage.tsx(35,7): error TS2322: Type 'undefined' is not assignable to type 'AttributeDetailsFragment_values[]'. -src/storybook/stories/attributes/AttributePage.tsx(38,53): error TS2322: Type 'undefined' is not assignable to type 'AttributeDetailsFragment_values[]'. -src/storybook/stories/attributes/AttributeValueEditDialog.tsx(13,3): error TS2322: Type '{ type: AttributeValueType.STRING; } | { type: AttributeValueType.STRING; __typename: "AttributeValue"; id: string; name: string | null; slug: string | null; }' is not assignable to type 'AttributeDetails_attribute_values | null'. -src/storybook/stories/attributes/AttributeValueEditDialog.tsx(14,8): error TS2531: Object is possibly 'null'. -src/storybook/stories/auth/LoginPage.tsx(12,3): error TS2322: Type 'undefined' is not assignable to type '() => void'. -src/storybook/stories/categories/CategoryListPage.tsx(37,47): error TS2322: Type 'undefined' is not assignable to type 'CategoryFragment[]'. -src/storybook/stories/categories/CategoryUpdatePage.tsx(19,3): error TS2322: Type 'undefined' is not assignable to type '(index: CategoryPageTab) => void'. -src/storybook/stories/categories/CategoryUpdatePage.tsx(23,3): error TS2322: Type 'undefined' is not assignable to type '() => any'. -src/storybook/stories/categories/CategoryUpdatePage.tsx(24,3): error TS2322: Type 'undefined' is not assignable to type '() => any'. -src/storybook/stories/categories/CategoryUpdatePage.tsx(26,26): error TS2322: Type 'undefined' is not assignable to type '() => void'. -src/storybook/stories/categories/CategoryUpdatePage.tsx(30,3): error TS2322: Type 'undefined' is not assignable to type '() => any'. -src/storybook/stories/categories/CategoryUpdatePage.tsx(31,3): error TS2322: Type 'undefined' is not assignable to type '() => any'. -src/storybook/stories/categories/CategoryUpdatePage.tsx(32,25): error TS2322: Type 'undefined' is not assignable to type '() => void'. -src/storybook/stories/categories/CategoryUpdatePage.tsx(39,13): error TS2531: Object is possibly 'null'. -src/storybook/stories/categories/CategoryUpdatePage.tsx(41,18): error TS2531: Object is possibly 'null'. -src/storybook/stories/categories/CategoryUpdatePage.tsx(77,7): error TS2322: Type 'undefined' is not assignable to type 'CategoryDetails_category_children_edges_node[]'. -src/storybook/stories/categories/CategoryUpdatePage.tsx(79,7): error TS2322: Type 'undefined' is not assignable to type 'CategoryDetails_category_products_edges_node[]'. -src/storybook/stories/categories/CategoryUpdatePage.tsx(80,7): error TS2322: Type 'undefined' is not assignable to type 'CategoryDetails_category'. -src/storybook/stories/collections/CollectionDetailsPage.tsx(40,39): error TS2322: Type 'undefined' is not assignable to type 'CollectionDetails_collection'. -src/storybook/stories/collections/CollectionDetailsPage.tsx(55,9): error TS2322: Type '{ edges: never[]; } | { edges: never[]; __typename: "ProductCountableConnection"; pageInfo: CollectionDetails_collection_products_pageInfo; }' is not assignable to type 'CollectionDetails_collection_products | null'. -src/storybook/stories/collections/CollectionListPage.tsx(44,36): error TS2322: Type 'undefined' is not assignable to type 'CollectionList_collections_edges_node[]'. -src/storybook/stories/components/ActionDialog.tsx(13,7): error TS2322: Type 'undefined' is not assignable to type '() => void'. -src/storybook/stories/components/ActionDialog.tsx(14,7): error TS2322: Type 'undefined' is not assignable to type '() => any'. -src/storybook/stories/components/AddressEdit.tsx(24,40): error TS2345: Argument of type '(CustomerDetails_user_defaultBillingAddress & CustomerAddresses_user_defaultBillingAddress) | null' is not assignable to parameter of type 'AddressType'. -src/storybook/stories/components/AddressEdit.tsx(29,32): error TS2531: Object is possibly 'null'. -src/storybook/stories/components/AddressEdit.tsx(30,11): error TS2322: Type 'undefined' is not assignable to type '(event: ChangeEvent) => any'. -src/storybook/stories/components/AddressFormatter.tsx(13,23): error TS2322: Type '(CustomerDetails_user_defaultBillingAddress & CustomerAddresses_user_defaultBillingAddress) | null' is not assignable to type 'AddressType | undefined'. -src/storybook/stories/components/AssignAttributeDialog.tsx(30,39): error TS2322: Type 'undefined' is not assignable to type 'SearchAttributes_productType_availableAttributes_edges_node[]'. -src/storybook/stories/components/AutocompleteSelectMenu.tsx(72,17): error TS2533: Object is possibly 'null' or 'undefined'. -src/storybook/stories/components/AutocompleteSelectMenu.tsx(74,3): error TS2322: Type 'undefined' is not assignable to type 'string'. -src/storybook/stories/components/AutocompleteSelectMenu.tsx(110,25): error TS2533: Object is possibly 'null' or 'undefined'. -src/storybook/stories/components/MultiSelectField.tsx(20,41): error TS2322: Type 'undefined' is not assignable to type '(event: any) => any'. -src/storybook/stories/components/MultiSelectField.tsx(25,7): error TS2322: Type 'undefined' is not assignable to type '(event: any) => any'. -src/storybook/stories/components/MultiSelectField.tsx(32,7): error TS2322: Type 'undefined' is not assignable to type '(event: any) => any'. -src/storybook/stories/components/MultiSelectField.tsx(39,7): error TS2322: Type 'undefined' is not assignable to type '(event: any) => any'. -src/storybook/stories/components/MultiSelectField.tsx(46,7): error TS2322: Type 'undefined' is not assignable to type '(event: any) => any'. -src/storybook/stories/components/MultiSelectField.tsx(54,7): error TS2322: Type 'undefined' is not assignable to type '(event: any) => any'. -src/storybook/stories/components/MultiSelectField.tsx(63,7): error TS2322: Type 'undefined' is not assignable to type '(event: any) => any'. -src/storybook/stories/components/PhoneField.tsx(18,7): error TS2322: Type 'undefined' is not assignable to type '(event: ChangeEvent) => any'. -src/storybook/stories/components/PriceField.tsx(11,43): error TS2322: Type 'undefined' is not assignable to type '(event: any) => any'. -src/storybook/stories/components/PriceField.tsx(12,53): error TS2322: Type 'undefined' is not assignable to type '(event: any) => any'. -src/storybook/stories/components/PriceField.tsx(14,37): error TS2322: Type 'undefined' is not assignable to type '(event: any) => any'. -src/storybook/stories/components/PriceField.tsx(17,36): error TS2322: Type 'undefined' is not assignable to type '(event: any) => any'. -src/storybook/stories/components/PriceField.tsx(20,36): error TS2322: Type 'undefined' is not assignable to type '(event: any) => any'. -src/storybook/stories/components/PriceField.tsx(22,47): error TS2322: Type 'undefined' is not assignable to type '(event: any) => any'. -src/storybook/stories/components/PriceField.tsx(24,44): error TS2322: Type 'undefined' is not assignable to type '(event: any) => any'. -src/storybook/stories/components/PriceField.tsx(31,7): error TS2322: Type 'undefined' is not assignable to type '(event: any) => any'. -src/storybook/stories/components/PriceField.tsx(41,7): error TS2322: Type 'undefined' is not assignable to type '(event: any) => any'. -src/storybook/stories/components/SaveButtonBar.tsx(43,11): error TS2322: Type 'Timeout' is not assignable to type 'undefined'. -src/storybook/stories/components/SaveButtonBar.tsx(67,23): error TS2322: Type '{ state: "default"; disabled: boolean; onCancel: undefined; onDelete: undefined; onSave: undefined; }' is not assignable to type 'SaveButtonBarProps'. -src/storybook/stories/components/SaveButtonBar.tsx(68,26): error TS2322: Type '{ state: "loading"; disabled: boolean; onCancel: undefined; onDelete: undefined; onSave: undefined; }' is not assignable to type 'SaveButtonBarProps'. -src/storybook/stories/components/SaveButtonBar.tsx(69,26): error TS2322: Type '{ state: "success"; disabled: boolean; onCancel: undefined; onDelete: undefined; onSave: undefined; }' is not assignable to type 'SaveButtonBarProps'. -src/storybook/stories/components/SaveButtonBar.tsx(70,24): error TS2322: Type '{ state: "error"; disabled: boolean; onCancel: undefined; onDelete: undefined; onSave: undefined; }' is not assignable to type 'SaveButtonBarProps'. -src/storybook/stories/components/SaveButtonBar.tsx(71,27): error TS2322: Type '{ disabled: true; onCancel: undefined; onDelete: undefined; onSave: undefined; state: ConfirmButtonTransitionState; }' is not assignable to type 'SaveButtonBarProps'. -src/storybook/stories/components/SingleSelectField.tsx(19,42): error TS2322: Type 'undefined' is not assignable to type '(event: any) => any'. -src/storybook/stories/components/SingleSelectField.tsx(24,7): error TS2322: Type 'undefined' is not assignable to type '(event: any) => any'. -src/storybook/stories/components/SingleSelectField.tsx(31,7): error TS2322: Type 'undefined' is not assignable to type '(event: any) => any'. -src/storybook/stories/components/SingleSelectField.tsx(38,7): error TS2322: Type 'undefined' is not assignable to type '(event: any) => any'. -src/storybook/stories/components/SingleSelectField.tsx(45,7): error TS2322: Type 'undefined' is not assignable to type '(event: any) => any'. -src/storybook/stories/components/SingleSelectField.tsx(53,7): error TS2322: Type 'undefined' is not assignable to type '(event: any) => any'. -src/storybook/stories/components/SingleSelectField.tsx(62,7): error TS2322: Type 'undefined' is not assignable to type '(event: any) => any'. -src/storybook/stories/components/TablePagination.tsx(18,9): error TS2322: Type 'undefined' is not assignable to type '(event: any) => any'. -src/storybook/stories/components/TablePagination.tsx(19,9): error TS2322: Type 'undefined' is not assignable to type '(event: any) => any'. -src/storybook/stories/components/TablePagination.tsx(29,9): error TS2322: Type 'undefined' is not assignable to type '(event: any) => any'. -src/storybook/stories/components/TablePagination.tsx(30,9): error TS2322: Type 'undefined' is not assignable to type '(event: any) => any'. -src/storybook/stories/components/TablePagination.tsx(40,9): error TS2322: Type 'undefined' is not assignable to type '(event: any) => any'. -src/storybook/stories/components/TablePagination.tsx(41,9): error TS2322: Type 'undefined' is not assignable to type '(event: any) => any'. -src/storybook/stories/components/TablePagination.tsx(51,9): error TS2322: Type 'undefined' is not assignable to type '(event: any) => any'. -src/storybook/stories/components/TablePagination.tsx(52,9): error TS2322: Type 'undefined' is not assignable to type '(event: any) => any'. -src/storybook/stories/configuration/ConfigurationPage.tsx(14,17): error TS2531: Object is possibly 'null'. -src/storybook/stories/configuration/ConfigurationPage.tsx(15,10): error TS2531: Object is possibly 'null'. -src/storybook/stories/configuration/ConfigurationPage.tsx(45,22): error TS2531: Object is possibly 'null'. -src/storybook/stories/customers/CustomerAddressDialog.tsx(12,3): error TS2322: Type 'CustomerAddresses_user_addresses | null' is not assignable to type 'CustomerAddresses_user_addresses'. -src/storybook/stories/customers/CustomerAddressDialog.tsx(12,12): error TS2531: Object is possibly 'null'. -src/storybook/stories/customers/CustomerAddressListPage.tsx(24,41): error TS2322: Type 'undefined' is not assignable to type 'CustomerAddresses_user'. -src/storybook/stories/customers/CustomerDetailsPage.tsx(36,37): error TS2322: Type 'undefined' is not assignable to type 'CustomerDetails_user'. -src/storybook/stories/customers/CustomerDetailsPage.tsx(51,9): error TS2322: Type '{ id: string; } | { id: string; __typename: "Address"; city: string; cityArea: string; companyName: string; country: CustomerDetails_user_defaultBillingAddress_country; ... 6 more ...; streetAddress2: string; }' is not assignable to type 'CustomerDetails_user_defaultBillingAddress | null'. -src/storybook/stories/customers/CustomerDetailsPage.tsx(72,9): error TS2322: Type '{ edges: never[]; } | { edges: never[]; __typename: "OrderCountableConnection"; }' is not assignable to type 'CustomerDetails_user_lastPlacedOrder | null'. -src/storybook/stories/customers/CustomerListPage.tsx(31,9): error TS2322: Type 'undefined' is not assignable to type 'string'. -src/storybook/stories/customers/CustomerListPage.tsx(32,9): error TS2322: Type 'undefined' is not assignable to type 'string'. -src/storybook/stories/customers/CustomerListPage.tsx(38,9): error TS2322: Type 'undefined' is not assignable to type 'string'. -src/storybook/stories/customers/CustomerListPage.tsx(39,9): error TS2322: Type 'undefined' is not assignable to type 'string'. -src/storybook/stories/customers/CustomerListPage.tsx(45,9): error TS2322: Type 'undefined' is not assignable to type 'string'. -src/storybook/stories/customers/CustomerListPage.tsx(46,9): error TS2322: Type 'undefined' is not assignable to type 'string'. -src/storybook/stories/customers/CustomerListPage.tsx(60,50): error TS2322: Type 'undefined' is not assignable to type 'ListCustomers_customers_edges_node[]'. -src/storybook/stories/discounts/SaleDetailsPage.tsx(22,26): error TS2322: Type 'undefined' is not assignable to type '() => void'. -src/storybook/stories/discounts/SaleDetailsPage.tsx(25,28): error TS2322: Type 'undefined' is not assignable to type '() => void'. -src/storybook/stories/discounts/SaleDetailsPage.tsx(30,25): error TS2322: Type 'undefined' is not assignable to type '() => void'. -src/storybook/stories/discounts/SaleDetailsPage.tsx(49,33): error TS2322: Type 'undefined' is not assignable to type 'SaleDetails_sale'. -src/storybook/stories/discounts/SaleListPage.tsx(37,9): error TS2322: Type 'undefined' is not assignable to type 'string'. -src/storybook/stories/discounts/SaleListPage.tsx(38,9): error TS2322: Type 'undefined' is not assignable to type 'string'. -src/storybook/stories/discounts/SaleListPage.tsx(56,50): error TS2322: Type 'undefined' is not assignable to type 'SaleList_sales_edges_node[]'. -src/storybook/stories/discounts/VoucherDetailsPage.tsx(24,26): error TS2322: Type 'undefined' is not assignable to type '() => void'. -src/storybook/stories/discounts/VoucherDetailsPage.tsx(27,28): error TS2322: Type 'undefined' is not assignable to type '() => void'. -src/storybook/stories/discounts/VoucherDetailsPage.tsx(32,25): error TS2322: Type 'undefined' is not assignable to type '() => void'. -src/storybook/stories/discounts/VoucherDetailsPage.tsx(46,52): error TS2322: Type 'undefined' is not assignable to type 'VoucherDetails_voucher'. -src/storybook/stories/discounts/VoucherListPage.tsx(39,9): error TS2322: Type 'undefined' is not assignable to type 'string'. -src/storybook/stories/discounts/VoucherListPage.tsx(40,9): error TS2322: Type 'undefined' is not assignable to type 'string'. -src/storybook/stories/discounts/VoucherListPage.tsx(50,9): error TS2322: Type 'undefined' is not assignable to type 'string'. -src/storybook/stories/discounts/VoucherListPage.tsx(51,9): error TS2322: Type 'undefined' is not assignable to type 'string'. -src/storybook/stories/discounts/VoucherListPage.tsx(65,53): error TS2322: Type 'undefined' is not assignable to type 'VoucherList_vouchers_edges_node[]'. -src/storybook/stories/home/HomePage.tsx(15,15): error TS2531: Object is possibly 'null'. -src/storybook/stories/home/HomePage.tsx(20,3): error TS2322: Type 'number | null' is not assignable to type 'number'. -src/storybook/stories/home/HomePage.tsx(20,11): error TS2531: Object is possibly 'null'. -src/storybook/stories/home/HomePage.tsx(21,3): error TS2322: Type 'number | null' is not assignable to type 'number'. -src/storybook/stories/home/HomePage.tsx(21,20): error TS2531: Object is possibly 'null'. -src/storybook/stories/home/HomePage.tsx(22,3): error TS2322: Type 'number | null' is not assignable to type 'number'. -src/storybook/stories/home/HomePage.tsx(22,20): error TS2531: Object is possibly 'null'. -src/storybook/stories/home/HomePage.tsx(23,3): error TS2322: Type 'number | null' is not assignable to type 'number'. -src/storybook/stories/home/HomePage.tsx(23,23): error TS2531: Object is possibly 'null'. -src/storybook/stories/home/HomePage.tsx(24,10): error TS2531: Object is possibly 'null'. -src/storybook/stories/home/HomePage.tsx(25,16): error TS2531: Object is possibly 'null'. -src/storybook/stories/home/HomePage.tsx(36,7): error TS2322: Type 'undefined' is not assignable to type 'Home_activities_edges_node[]'. -src/storybook/stories/home/HomePage.tsx(37,7): error TS2322: Type 'undefined' is not assignable to type 'number'. -src/storybook/stories/home/HomePage.tsx(38,7): error TS2322: Type 'undefined' is not assignable to type 'number'. -src/storybook/stories/home/HomePage.tsx(39,7): error TS2322: Type 'undefined' is not assignable to type 'number'. -src/storybook/stories/home/HomePage.tsx(40,7): error TS2322: Type 'undefined' is not assignable to type 'number'. -src/storybook/stories/home/HomePage.tsx(41,7): error TS2322: Type 'undefined' is not assignable to type 'Home_salesToday_gross'. -src/storybook/stories/home/HomePage.tsx(42,7): error TS2322: Type 'undefined' is not assignable to type 'Home_productTopToday_edges_node[]'. -src/storybook/stories/home/HomePage.tsx(43,7): error TS2322: Type 'undefined' is not assignable to type 'string'. -src/storybook/stories/navigation/MenuDetailsPage.tsx(18,19): error TS2322: Type 'undefined' is not assignable to type 'Promise'. -src/storybook/stories/navigation/MenuDetailsPage.tsx(26,49): error TS2322: Type 'undefined' is not assignable to type 'MenuDetails_menu'. -src/storybook/stories/navigation/MenuListPage.tsx(33,46): error TS2322: Type 'undefined' is not assignable to type 'MenuList_menus_edges_node[]'. -src/storybook/stories/orders/OrderAddressEditDialog.tsx(16,39): error TS2345: Argument of type 'OrderDetails_order_shippingAddress | null' is not assignable to parameter of type 'AddressType'. -src/storybook/stories/orders/OrderAddressEditDialog.tsx(28,39): error TS2345: Argument of type 'OrderDetails_order_billingAddress | null' is not assignable to parameter of type 'AddressType'. -src/storybook/stories/orders/OrderCancelDialog.tsx(14,7): error TS2322: Type 'undefined' is not assignable to type '(data: FormData) => any'. -src/storybook/stories/orders/OrderCustomer.tsx(30,51): error TS2322: Type 'undefined' is not assignable to type 'OrderDetails_order'. -src/storybook/stories/orders/OrderCustomer.tsx(36,9): error TS2322: Type '{ id: string; } | { id: string; __typename: "Address"; city: string; cityArea: string; companyName: string; country: OrderDetails_order_shippingAddress_country; ... 6 more ...; streetAddress2: string; }' is not assignable to type 'OrderDetails_order_shippingAddress | null'. -src/storybook/stories/orders/OrderDetailsPage.tsx(23,3): error TS2322: Type 'undefined' is not assignable to type '() => any'. -src/storybook/stories/orders/OrderDetailsPage.tsx(26,3): error TS2322: Type 'undefined' is not assignable to type '(data: FormData) => any'. -src/storybook/stories/orders/OrderDetailsPage.tsx(27,3): error TS2322: Type 'undefined' is not assignable to type '() => any'. -src/storybook/stories/orders/OrderDetailsPage.tsx(28,3): error TS2322: Type 'undefined' is not assignable to type '() => any'. -src/storybook/stories/orders/OrderDetailsPage.tsx(29,3): error TS2322: Type 'undefined' is not assignable to type '() => any'. -src/storybook/stories/orders/OrderDetailsPage.tsx(30,3): error TS2322: Type 'undefined' is not assignable to type '() => any'. -src/storybook/stories/orders/OrderDetailsPage.tsx(31,3): error TS2322: Type 'undefined' is not assignable to type '() => any'. -src/storybook/stories/orders/OrderDetailsPage.tsx(32,3): error TS2322: Type 'undefined' is not assignable to type '() => any'. -src/storybook/stories/orders/OrderDetailsPage.tsx(35,3): error TS2322: Type 'undefined' is not assignable to type '() => any'. -src/storybook/stories/orders/OrderDetailsPage.tsx(43,54): error TS2322: Type 'undefined' is not assignable to type 'OrderDetails_order'. -src/storybook/stories/orders/OrderDetailsPage.tsx(103,9): error TS2322: Type '({ status: FulfillmentStatus.CANCELED; } | { status: FulfillmentStatus.CANCELED; __typename: "Fulfillment"; id: string; lines: (OrderDetails_order_fulfillments_lines | null)[] | null; fulfillmentOrder: number; trackingNumber: string; })[]' is not assignable to type '(OrderDetails_order_fulfillments | null)[]'. -src/storybook/stories/orders/OrderDraftListPage.tsx(30,9): error TS2322: Type 'undefined' is not assignable to type 'string'. -src/storybook/stories/orders/OrderDraftListPage.tsx(31,9): error TS2322: Type 'undefined' is not assignable to type 'string'. -src/storybook/stories/orders/OrderDraftListPage.tsx(36,7): error TS2322: Type 'undefined' is not assignable to type 'string'. -src/storybook/stories/orders/OrderDraftListPage.tsx(51,45): error TS2322: Type 'undefined' is not assignable to type 'OrderDraftList_draftOrders_edges_node[]'. -src/storybook/stories/orders/OrderDraftPage.tsx(21,3): error TS2322: Type 'undefined' is not assignable to type '() => void'. -src/storybook/stories/orders/OrderDraftPage.tsx(25,3): error TS2322: Type 'undefined' is not assignable to type '(data: FormData) => void'. -src/storybook/stories/orders/OrderDraftPage.tsx(29,3): error TS2322: Type 'undefined' is not assignable to type '(id: string) => void'. -src/storybook/stories/orders/OrderDraftPage.tsx(31,3): error TS2322: Type 'undefined' is not assignable to type '() => void'. -src/storybook/stories/orders/OrderDraftPage.tsx(32,3): error TS2322: Type 'undefined' is not assignable to type '() => void'. -src/storybook/stories/orders/OrderDraftPage.tsx(44,48): error TS2322: Type 'undefined' is not assignable to type 'OrderDetails_order'. -src/storybook/stories/orders/OrderFulfillmentCancelDialog.tsx(13,7): error TS2322: Type 'undefined' is not assignable to type '(data: FormData) => any'. -src/storybook/stories/orders/OrderFulfillmentCancelDialog.tsx(14,7): error TS2322: Type 'undefined' is not assignable to type '() => any'. -src/storybook/stories/orders/OrderFulfillmentDialog.tsx(16,3): error TS2322: Type '(OrderDetails_order_lines | null)[]' is not assignable to type 'OrderDetails_order_lines[]'. -src/storybook/stories/orders/OrderFulfillmentDialog.tsx(17,3): error TS2322: Type 'undefined' is not assignable to type '() => any'. -src/storybook/stories/orders/OrderFulfillmentDialog.tsx(18,3): error TS2322: Type 'undefined' is not assignable to type '(data: FormData) => any'. -src/storybook/stories/orders/OrderFulfillmentTrackingDialog.tsx(14,7): error TS2322: Type 'undefined' is not assignable to type '(data: FormData) => any'. -src/storybook/stories/orders/OrderFulfillmentTrackingDialog.tsx(15,7): error TS2322: Type 'undefined' is not assignable to type '() => any'. -src/storybook/stories/orders/OrderHistory.tsx(13,19): error TS2322: Type 'undefined' is not assignable to type '(data: FormData) => void'. -src/storybook/stories/orders/OrderHistory.tsx(13,41): error TS2322: Type '(OrderDetails_order_events | null)[] | null' is not assignable to type 'OrderDetails_order_events[]'. -src/storybook/stories/orders/OrderListPage.tsx(53,7): error TS2322: Type 'undefined' is not assignable to type 'OrderList_orders_edges_node[]'. -src/storybook/stories/orders/OrderListPage.tsx(54,7): error TS2322: Type 'undefined' is not assignable to type 'number'. -src/storybook/stories/orders/OrderPaymentDialog.tsx(15,7): error TS2322: Type 'undefined' is not assignable to type '() => void'. -src/storybook/stories/orders/OrderPaymentDialog.tsx(16,7): error TS2322: Type 'undefined' is not assignable to type '(data: FormData) => void'. -src/storybook/stories/orders/OrderPaymentDialog.tsx(25,7): error TS2322: Type 'undefined' is not assignable to type '() => void'. -src/storybook/stories/orders/OrderPaymentDialog.tsx(26,7): error TS2322: Type 'undefined' is not assignable to type '(data: FormData) => void'. -src/storybook/stories/orders/OrderProductAddDialog.tsx(16,7): error TS2322: Type 'undefined' is not assignable to type '() => void'. -src/storybook/stories/orders/OrderProductAddDialog.tsx(17,7): error TS2322: Type 'undefined' is not assignable to type '(data: SearchOrderVariant_search_edges_node_variants[]) => void'. -src/storybook/stories/orders/OrderShippingMethodEditDialog.tsx(15,7): error TS2322: Type 'undefined' is not assignable to type '() => any'. -src/storybook/stories/orders/OrderShippingMethodEditDialog.tsx(18,7): error TS2322: Type 'null' is not assignable to type 'string'. -src/storybook/stories/orders/OrderShippingMethodEditDialog.tsx(19,7): error TS2322: Type '(OrderDetails_order_availableShippingMethods | null)[] | null' is not assignable to type 'OrderDetails_order_availableShippingMethods[] | undefined'. -src/storybook/stories/pages/PageDetailsPage.tsx(26,49): error TS2322: Type 'undefined' is not assignable to type 'PageDetails_page'. -src/storybook/stories/pages/PageListPage.tsx(32,46): error TS2322: Type 'undefined' is not assignable to type 'PageList_pages_edges_node[]'. -src/storybook/stories/plugins/PluginDetailsPage.tsx(27,52): error TS2322: Type 'undefined' is not assignable to type 'Plugin_plugin'. -src/storybook/stories/plugins/PluginsListPage.tsx(38,49): error TS2322: Type 'undefined' is not assignable to type 'Plugins_plugins_edges_node[]'. -src/storybook/stories/products/ProductCreatePage.tsx(23,7): error TS2322: Type '(ProductDetails_product_collections | null)[] | null' is not assignable to type 'SearchCollections_search_edges_node[]'. -src/storybook/stories/products/ProductCreatePage.tsx(30,7): error TS2322: Type '(SearchProductTypes_search_edges_node & ProductTypeList_productTypes_edges_node)[]' is not assignable to type '{ id: string; name: string; hasVariants: boolean; productAttributes: SearchProductTypes_search_edges_node_productAttributes[]; }[]'. -src/storybook/stories/products/ProductCreatePage.tsx(31,20): error TS2322: Type 'ProductDetails_product_category | null' is not assignable to type 'SearchCategories_search_edges_node'. -src/storybook/stories/products/ProductCreatePage.tsx(43,7): error TS2322: Type '(ProductDetails_product_collections | null)[] | null' is not assignable to type 'SearchCollections_search_edges_node[]'. -src/storybook/stories/products/ProductCreatePage.tsx(50,7): error TS2322: Type '(SearchProductTypes_search_edges_node & ProductTypeList_productTypes_edges_node)[]' is not assignable to type '{ id: string; name: string; hasVariants: boolean; productAttributes: SearchProductTypes_search_edges_node_productAttributes[]; }[]'. -src/storybook/stories/products/ProductCreatePage.tsx(51,20): error TS2322: Type 'ProductDetails_product_category | null' is not assignable to type 'SearchCategories_search_edges_node'. -src/storybook/stories/products/ProductCreatePage.tsx(65,7): error TS2322: Type '(ProductDetails_product_collections | null)[] | null' is not assignable to type 'SearchCollections_search_edges_node[]'. -src/storybook/stories/products/ProductCreatePage.tsx(72,7): error TS2322: Type '(SearchProductTypes_search_edges_node & ProductTypeList_productTypes_edges_node)[]' is not assignable to type '{ id: string; name: string; hasVariants: boolean; productAttributes: SearchProductTypes_search_edges_node_productAttributes[]; }[]'. -src/storybook/stories/products/ProductCreatePage.tsx(73,20): error TS2322: Type 'ProductDetails_product_category | null' is not assignable to type 'SearchCategories_search_edges_node'. -src/storybook/stories/products/ProductImagePage.tsx(22,7): error TS2322: Type 'undefined' is not assignable to type '() => void'. -src/storybook/stories/products/ProductImagePage.tsx(23,25): error TS2322: Type 'undefined' is not assignable to type '() => void'. -src/storybook/stories/products/ProductImagePage.tsx(33,7): error TS2322: Type 'undefined' is not assignable to type '() => void'. -src/storybook/stories/products/ProductImagePage.tsx(34,25): error TS2322: Type 'undefined' is not assignable to type '() => void'. -src/storybook/stories/products/ProductListPage.tsx(37,3): error TS2322: Type 'undefined' is not assignable to type 'string'. -src/storybook/stories/products/ProductListPage.tsx(43,3): error TS2322: Type '{ columns: ("productType" | "isPublished" | "price")[]; } | { columns: ("productType" | "isPublished" | "price")[]; rowNumber: number; }' is not assignable to type 'ListSettings | undefined'. -src/storybook/stories/products/ProductListPage.tsx(56,7): error TS2322: Type 'undefined' is not assignable to type 'ProductList_products_edges_node[]'. -src/storybook/stories/products/ProductListPage.tsx(57,7): error TS2322: Type 'undefined' is not assignable to type 'number'. -src/storybook/stories/products/ProductUpdatePage.tsx(19,16): error TS2322: Type 'ProductDetails_product_category | null' is not assignable to type 'SearchCategories_search_edges_node'. -src/storybook/stories/products/ProductUpdatePage.tsx(28,3): error TS2322: Type '((ProductDetails_product_images | null)[] & (ProductVariantCreateData_product_images | null)[]) | null' is not assignable to type 'ProductDetails_product_images[]'. -src/storybook/stories/products/ProductUpdatePage.tsx(31,24): error TS2322: Type 'undefined' is not assignable to type '() => void'. -src/storybook/stories/products/ProductUpdatePage.tsx(36,24): error TS2322: Type 'undefined' is not assignable to type '() => void'. -src/storybook/stories/products/ProductUpdatePage.tsx(41,3): error TS2322: Type '((ProductDetails_product_variants | null)[] & (ProductVariantCreateData_product_variants | null)[]) | null' is not assignable to type 'ProductDetails_product_variants[]'. -src/storybook/stories/products/ProductUpdatePage.tsx(63,7): error TS2322: Type 'undefined' is not assignable to type 'string'. -src/storybook/stories/products/ProductUpdatePage.tsx(65,7): error TS2322: Type 'undefined' is not assignable to type 'ProductDetails_product_variants[]'. -src/storybook/stories/products/ProductUpdatePage.tsx(66,7): error TS2322: Type 'undefined' is not assignable to type 'ProductDetails_product'. -src/storybook/stories/products/ProductUpdatePage.tsx(67,7): error TS2322: Type 'undefined' is not assignable to type 'SearchCollections_search_edges_node[]'. -src/storybook/stories/products/ProductUpdatePage.tsx(68,7): error TS2322: Type 'undefined' is not assignable to type 'ProductDetails_product_images[]'. -src/storybook/stories/products/ProductVariantCreatePage.tsx(23,7): error TS2322: Type 'undefined' is not assignable to type '(variantId: string) => void'. -src/storybook/stories/products/ProductVariantCreatePage.tsx(53,7): error TS2322: Type 'undefined' is not assignable to type '(variantId: string) => void'. -src/storybook/stories/products/ProductVariantCreatePage.tsx(63,7): error TS2322: Type 'undefined' is not assignable to type 'ProductVariantCreateData_product'. -src/storybook/stories/products/ProductVariantCreatePage.tsx(66,7): error TS2322: Type 'undefined' is not assignable to type '(variantId: string) => void'. -src/storybook/stories/products/ProductVariantCreatePage.tsx(82,7): error TS2322: Type 'undefined' is not assignable to type '(variantId: string) => void'. -src/storybook/stories/products/ProductVariantImageSelectDialog.tsx(18,7): error TS2322: Type '(ProductVariant_product_images | null)[] | null' is not assignable to type 'ProductImage[] | undefined'. -src/storybook/stories/products/ProductVariantImageSelectDialog.tsx(19,23): error TS2531: Object is possibly 'null'. -src/storybook/stories/products/ProductVariantImageSelectDialog.tsx(19,50): error TS2531: Object is possibly 'null'. -src/storybook/stories/products/ProductVariantPage.tsx(21,7): error TS2322: Type 'undefined' is not assignable to type '() => any'. -src/storybook/stories/products/ProductVariantPage.tsx(30,7): error TS2322: Type 'undefined' is not assignable to type 'string'. -src/storybook/stories/products/ProductVariantPage.tsx(36,7): error TS2322: Type 'undefined' is not assignable to type '() => any'. -src/storybook/stories/products/ProductVariantPage.tsx(49,7): error TS2322: Type 'undefined' is not assignable to type '() => any'. -src/storybook/stories/productTypes/ProductTypeAttributeEditDialog.tsx(16,3): error TS2322: Type 'string | null' is not assignable to type 'string'. -src/storybook/stories/productTypes/ProductTypeAttributeEditDialog.tsx(21,3): error TS2322: Type '{ label: string | null; value: string; }[]' is not assignable to type '{ label: string; value: string; }[]'. -src/storybook/stories/productTypes/ProductTypeAttributeEditDialog.tsx(21,11): error TS2531: Object is possibly 'null'. -src/storybook/stories/productTypes/ProductTypeAttributeEditDialog.tsx(22,12): error TS2531: Object is possibly 'null'. -src/storybook/stories/productTypes/ProductTypeAttributeEditDialog.tsx(23,12): error TS2531: Object is possibly 'null'. -src/storybook/stories/productTypes/ProductTypeCreatePage.tsx(28,55): error TS2322: Type 'undefined' is not assignable to type 'string'. -src/storybook/stories/productTypes/ProductTypeDetailsPage.tsx(42,7): error TS2322: Type 'undefined' is not assignable to type 'string'. -src/storybook/stories/productTypes/ProductTypeDetailsPage.tsx(43,7): error TS2322: Type 'undefined' is not assignable to type 'ProductTypeDetails_productType'. -src/storybook/stories/productTypes/ProductTypeListPage.tsx(52,53): error TS2322: Type 'undefined' is not assignable to type 'ProductTypeList_productTypes_edges_node[]'. -src/storybook/stories/shipping/ShippingZoneDetailsPage.tsx(35,7): error TS2322: Type 'undefined' is not assignable to type 'ShippingZoneDetailsFragment'. -src/storybook/stories/shipping/ShippingZoneRateDialog.tsx(21,3): error TS2322: Type 'ShippingZoneDetailsFragment_shippingMethods | null' is not assignable to type 'ShippingZoneDetailsFragment_shippingMethods'. -src/storybook/stories/shipping/ShippingZoneRateDialog.tsx(21,9): error TS2531: Object is possibly 'null'. -src/storybook/stories/shipping/ShippingZoneRateDialog.tsx(29,56): error TS2322: Type 'undefined' is not assignable to type 'ShippingZoneDetailsFragment_shippingMethods'. -src/storybook/stories/shipping/ShippingZoneRateDialog.tsx(32,40): error TS2322: Type 'undefined' is not assignable to type 'ShippingZoneDetailsFragment_shippingMethods'. -src/storybook/stories/shipping/ShippingZonesListPage.tsx(35,7): error TS2322: Type 'undefined' is not assignable to type 'ShippingZoneFragment[]'. -src/storybook/stories/siteSettings/SiteSettingsPage.tsx(27,50): error TS2322: Type 'undefined' is not assignable to type 'SiteSettings_shop'. -src/storybook/stories/staff/StaffDetailsPage.tsx(33,50): error TS2322: Type 'undefined' is not assignable to type 'StaffMemberDetails_user'. -src/storybook/stories/staff/StaffDetailsPage.tsx(40,22): error TS2531: Object is possibly 'null'. -src/storybook/stories/staff/StaffListPage.tsx(31,3): error TS2322: Type 'undefined' is not assignable to type '() => void'. -src/storybook/stories/staff/StaffListPage.tsx(44,47): error TS2322: Type 'undefined' is not assignable to type 'StaffList_staffUsers_edges_node[]'. -src/storybook/stories/taxes/CountryListPage.tsx(30,33): error TS2322: Type 'undefined' is not assignable to type 'CountryList_shop'. -src/storybook/stories/taxes/CountryTaxesPage.tsx(13,3): error TS2322: Type '(CountryList_shop_countries_vat_reducedRates | null)[]' is not assignable to type 'CountryList_shop_countries_vat_reducedRates[]'. -src/storybook/stories/taxes/CountryTaxesPage.tsx(13,18): error TS2531: Object is possibly 'null'. -src/storybook/stories/taxes/CountryTaxesPage.tsx(22,7): error TS2322: Type 'undefined' is not assignable to type 'string'. -src/storybook/stories/taxes/CountryTaxesPage.tsx(23,7): error TS2322: Type 'undefined' is not assignable to type 'CountryList_shop_countries_vat_reducedRates[]'. -src/storybook/stories/translations/TranslationsLanguageListPage.tsx(19,46): error TS2322: Type 'undefined' is not assignable to type 'ShopInfo_shop_languages[]'. -src/taxes/components/CountryList/CountryList.tsx(67,49): error TS2532: Object is possibly 'undefined'. -src/taxes/components/CountryList/CountryList.tsx(70,49): error TS2532: Object is possibly 'undefined'. -src/taxes/components/CountryList/CountryList.tsx(74,27): error TS2532: Object is possibly 'undefined'. -src/taxes/components/CountryList/CountryList.tsx(74,27): error TS2531: Object is possibly 'null'. -src/taxes/components/CountryListPage/CountryListPage.tsx(73,19): error TS2322: Type '(CountryList_shop_countries | null)[] | undefined' is not assignable to type 'CountryList_shop_countries[]'. -src/taxes/components/CountryTaxesPage/CountryTaxesPage.tsx(191,52): error TS2532: Object is possibly 'undefined'. -src/taxes/components/CountryTaxesPage/CountryTaxesPage.tsx(197,33): error TS2532: Object is possibly 'undefined'. -src/taxes/views/CountryList.tsx(22,9): error TS2531: Object is possibly 'null'. -src/taxes/views/CountryList.tsx(22,9): error TS2531: Object is possibly 'null'. -src/taxes/views/CountryList.tsx(30,9): error TS2531: Object is possibly 'null'. -src/taxes/views/CountryList.tsx(30,9): error TS2531: Object is possibly 'null'. -src/taxes/views/CountryList.tsx(67,19): error TS2322: Type '{ countries: (CountryList_shop_countries | null)[]; } | { countries: (CountryList_shop_countries | null)[]; __typename: "Shop"; chargeTaxesOnShipping: boolean; includeTaxesInPrices: boolean; displayGrossPrices: boolean; } | undefined' is not assignable to type 'CountryList_shop'. -src/taxes/views/CountryList.tsx(68,24): error TS2532: Object is possibly 'undefined'. -src/taxes/views/CountryList.tsx(69,32): error TS2532: Object is possibly 'undefined'. -src/taxes/views/CountryList.tsx(69,32): error TS2531: Object is possibly 'null'. -src/taxes/views/CountryList.tsx(70,34): error TS2531: Object is possibly 'null'. -src/taxes/views/CountryTaxes.tsx(20,11): error TS2532: Object is possibly 'undefined'. -src/taxes/views/CountryTaxes.tsx(20,11): error TS2531: Object is possibly 'null'. -src/taxes/views/CountryTaxes.tsx(20,47): error TS2531: Object is possibly 'null'. -src/taxes/views/CountryTaxes.tsx(24,13): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/taxes/views/CountryTaxes.tsx(24,38): error TS2533: Object is possibly 'null' or 'undefined'. -src/taxes/views/CountryTaxes.tsx(25,13): error TS2322: Type '(CountryList_shop_countries_vat_reducedRates | null)[] | undefined' is not assignable to type 'CountryList_shop_countries_vat_reducedRates[]'. -src/taxes/views/CountryTaxes.tsx(25,40): error TS2533: Object is possibly 'null' or 'undefined'. -src/taxes/views/CountryTaxes.tsx(25,40): error TS2531: Object is possibly 'null'. -src/theme.ts(21,18): error TS2345: Argument of type '{ overrides: { MuiButton: { contained: { "&$disabled": { backgroundColor: string; }; "&:active": { boxShadow: null; }; "&:hover": { boxShadow: null; }; boxShadow: null; }; containedPrimary: { "&:active": { backgroundColor: string; }; "&:hover": { ...; }; }; label: { ...; }; root: { ...; }; text: { ...; }; textPrimar...' is not assignable to parameter of type 'ThemeOptions'. -src/translations/components/TranslationFields/TranslationFields.tsx(170,25): error TS2322: Type 'undefined' is not assignable to type '(data: string) => void'. -src/translations/components/TranslationFields/TranslationFields.tsx(179,25): error TS2322: Type 'undefined' is not assignable to type '(data: string) => void'. -src/translations/components/TranslationFields/TranslationFields.tsx(188,25): error TS2322: Type 'undefined' is not assignable to type '(data: string) => void'. -src/translations/components/TranslationFields/TranslationFieldsRich.tsx(39,13): error TS2322: Type 'undefined' is not assignable to type 'boolean'. -src/translations/components/TranslationFields/TranslationFieldsRich.tsx(40,13): error TS2322: Type 'undefined' is not assignable to type 'string'. -src/translations/components/TranslationsCategoriesPage/TranslationsCategoriesPage.tsx(77,13): error TS2322: Type 'string | null | undefined' is not assignable to type 'string'. -src/translations/components/TranslationsCategoriesPage/TranslationsCategoriesPage.tsx(81,13): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/translations/components/TranslationsCategoriesPage/TranslationsCategoriesPage.tsx(112,13): error TS2322: Type 'string | null | undefined' is not assignable to type 'string'. -src/translations/components/TranslationsCategoriesPage/TranslationsCategoriesPage.tsx(116,13): error TS2322: Type 'string | null | undefined' is not assignable to type 'string'. -src/translations/components/TranslationsCategoriesPage/TranslationsCategoriesPage.tsx(123,13): error TS2322: Type 'string | null | undefined' is not assignable to type 'string'. -src/translations/components/TranslationsCategoriesPage/TranslationsCategoriesPage.tsx(127,13): error TS2322: Type 'string | null | undefined' is not assignable to type 'string'. -src/translations/components/TranslationsCollectionsPage/TranslationsCollectionsPage.tsx(80,13): error TS2322: Type 'string | null | undefined' is not assignable to type 'string'. -src/translations/components/TranslationsCollectionsPage/TranslationsCollectionsPage.tsx(84,13): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/translations/components/TranslationsCollectionsPage/TranslationsCollectionsPage.tsx(117,13): error TS2322: Type 'string | null | undefined' is not assignable to type 'string'. -src/translations/components/TranslationsCollectionsPage/TranslationsCollectionsPage.tsx(121,13): error TS2322: Type 'string | null | undefined' is not assignable to type 'string'. -src/translations/components/TranslationsCollectionsPage/TranslationsCollectionsPage.tsx(128,13): error TS2322: Type 'string | null | undefined' is not assignable to type 'string'. -src/translations/components/TranslationsCollectionsPage/TranslationsCollectionsPage.tsx(134,13): error TS2322: Type 'string | null | undefined' is not assignable to type 'string'. -src/translations/components/TranslationsEntitiesList/TranslationsEntitiesList.tsx(81,13): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. -src/translations/components/TranslationsEntitiesList/TranslationsEntitiesList.tsx(85,13): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. -src/translations/components/TranslationsEntitiesList/TranslationsEntitiesList.tsx(105,47): error TS2532: Object is possibly 'undefined'. -src/translations/components/TranslationsEntitiesList/TranslationsEntitiesList.tsx(115,23): error TS2532: Object is possibly 'undefined'. -src/translations/components/TranslationsLanguageList/TranslationsLanguageList.tsx(57,43): error TS2532: Object is possibly 'undefined'. -src/translations/components/TranslationsLanguageList/TranslationsLanguageList.tsx(61,27): error TS2532: Object is possibly 'undefined'. -src/translations/components/TranslationsPagesPage/TranslationsPagesPage.tsx(77,13): error TS2322: Type 'string | null | undefined' is not assignable to type 'string'. -src/translations/components/TranslationsPagesPage/TranslationsPagesPage.tsx(81,13): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/translations/components/TranslationsPagesPage/TranslationsPagesPage.tsx(115,13): error TS2322: Type 'string | null | undefined' is not assignable to type 'string'. -src/translations/components/TranslationsPagesPage/TranslationsPagesPage.tsx(119,13): error TS2322: Type 'string | null | undefined' is not assignable to type 'string'. -src/translations/components/TranslationsPagesPage/TranslationsPagesPage.tsx(126,13): error TS2322: Type 'string | null | undefined' is not assignable to type 'string'. -src/translations/components/TranslationsPagesPage/TranslationsPagesPage.tsx(130,13): error TS2322: Type 'string | null | undefined' is not assignable to type 'string'. -src/translations/components/TranslationsProductsPage/TranslationsProductsPage.tsx(78,13): error TS2322: Type 'string | null | undefined' is not assignable to type 'string'. -src/translations/components/TranslationsProductsPage/TranslationsProductsPage.tsx(82,13): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/translations/components/TranslationsProductsPage/TranslationsProductsPage.tsx(115,13): error TS2322: Type 'string | null | undefined' is not assignable to type 'string'. -src/translations/components/TranslationsProductsPage/TranslationsProductsPage.tsx(119,13): error TS2322: Type 'string | null | undefined' is not assignable to type 'string'. -src/translations/components/TranslationsProductsPage/TranslationsProductsPage.tsx(126,13): error TS2322: Type 'string | null | undefined' is not assignable to type 'string'. -src/translations/components/TranslationsProductsPage/TranslationsProductsPage.tsx(130,13): error TS2322: Type 'string | null | undefined' is not assignable to type 'string'. -src/translations/components/TranslationsProductTypesPage/TranslationsProductTypesPage.tsx(67,8): error TS2531: Object is possibly 'null'. -src/translations/components/TranslationsProductTypesPage/TranslationsProductTypesPage.tsx(80,34): error TS2531: Object is possibly 'null'. -src/translations/components/TranslationsProductTypesPage/TranslationsProductTypesPage.tsx(88,54): error TS2531: Object is possibly 'null'. -src/translations/components/TranslationsProductTypesPage/TranslationsProductTypesPage.tsx(89,19): error TS2322: Type 'string | null | undefined' is not assignable to type 'string'. -src/translations/components/TranslationsProductTypesPage/TranslationsProductTypesPage.tsx(90,21): error TS2531: Object is possibly 'null'. -src/translations/components/TranslationsProductTypesPage/TranslationsProductTypesPage.tsx(90,45): error TS2531: Object is possibly 'null'. -src/translations/components/TranslationsProductTypesPage/TranslationsProductTypesPage.tsx(93,19): error TS2322: Type 'string | null | undefined' is not assignable to type 'string'. -src/translations/components/TranslationsProductTypesPage/TranslationsProductTypesPage.tsx(93,38): error TS2531: Object is possibly 'null'. -src/translations/components/TranslationsProductTypesPage/TranslationsProductTypesPage.tsx(95,17): error TS2322: Type '{ displayName: string; name: string; translation: string | null | undefined; type: "short"; value: string | null | undefined; }' is not assignable to type 'TranslationField'. -src/translations/components/TranslationsProductTypesPage/TranslationsProductTypesPage.tsx(95,20): error TS2531: Object is possibly 'null'. -src/translations/components/TranslationsProductTypesPage/TranslationsProductTypesPage.tsx(95,20): error TS2531: Object is possibly 'null'. -src/translations/components/TranslationsProductTypesPage/TranslationsProductTypesPage.tsx(106,52): error TS2531: Object is possibly 'null'. -src/translations/components/TranslationsProductTypesPage/TranslationsProductTypesPage.tsx(108,23): error TS2531: Object is possibly 'null'. -src/translations/components/TranslationsProductTypesPage/TranslationsProductTypesPage.tsx(109,27): error TS2531: Object is possibly 'null'. -src/translations/components/TranslationsProductTypesPage/TranslationsProductTypesPage.tsx(113,40): error TS2531: Object is possibly 'null'. -src/translations/components/TranslationsProductTypesPage/TranslationsProductTypesPage.tsx(122,31): error TS2531: Object is possibly 'null'. -src/translations/components/TranslationsProductTypesPage/TranslationsProductTypesPage.tsx(131,12): error TS2531: Object is possibly 'null'. -src/translations/components/TranslationsProductTypesPage/TranslationsProductTypesPage.tsx(144,38): error TS2531: Object is possibly 'null'. -src/translations/components/TranslationsProductTypesPage/TranslationsProductTypesPage.tsx(152,58): error TS2531: Object is possibly 'null'. -src/translations/components/TranslationsProductTypesPage/TranslationsProductTypesPage.tsx(153,23): error TS2322: Type 'string | null | undefined' is not assignable to type 'string'. -src/translations/components/TranslationsProductTypesPage/TranslationsProductTypesPage.tsx(154,25): error TS2531: Object is possibly 'null'. -src/translations/components/TranslationsProductTypesPage/TranslationsProductTypesPage.tsx(155,29): error TS2531: Object is possibly 'null'. -src/translations/components/TranslationsProductTypesPage/TranslationsProductTypesPage.tsx(159,23): error TS2322: Type 'string | null | undefined' is not assignable to type 'string'. -src/translations/components/TranslationsProductTypesPage/TranslationsProductTypesPage.tsx(159,42): error TS2531: Object is possibly 'null'. -src/translations/components/TranslationsProductTypesPage/TranslationsProductTypesPage.tsx(161,21): error TS2322: Type '{ displayName: string; name: string; translation: string | null | undefined; type: "short"; value: string | null | undefined; }' is not assignable to type 'TranslationField'. -src/translations/components/TranslationsProductTypesPage/TranslationsProductTypesPage.tsx(161,24): error TS2531: Object is possibly 'null'. -src/translations/components/TranslationsProductTypesPage/TranslationsProductTypesPage.tsx(161,24): error TS2531: Object is possibly 'null'. -src/translations/components/TranslationsProductTypesPage/TranslationsProductTypesPage.tsx(172,56): error TS2531: Object is possibly 'null'. -src/translations/components/TranslationsProductTypesPage/TranslationsProductTypesPage.tsx(174,27): error TS2531: Object is possibly 'null'. -src/translations/components/TranslationsProductTypesPage/TranslationsProductTypesPage.tsx(175,31): error TS2531: Object is possibly 'null'. -src/translations/components/TranslationsProductTypesPage/TranslationsProductTypesPage.tsx(179,44): error TS2531: Object is possibly 'null'. -src/translations/components/TranslationsProductTypesPage/TranslationsProductTypesPage.tsx(188,35): error TS2531: Object is possibly 'null'. -src/translations/components/TranslationsSalesPage/TranslationsSalesPage.tsx(73,13): error TS2322: Type 'string | null | undefined' is not assignable to type 'string'. -src/translations/components/TranslationsSalesPage/TranslationsSalesPage.tsx(77,13): error TS2322: Type 'string | undefined' is not assignable to type 'string'. -src/translations/components/TranslationsVouchersPage/TranslationsVouchersPage.tsx(74,13): error TS2322: Type 'string | null | undefined' is not assignable to type 'string'. -src/translations/components/TranslationsVouchersPage/TranslationsVouchersPage.tsx(78,13): error TS2322: Type 'string | null | undefined' is not assignable to type 'string'. -src/translations/views/TranslationsCategories.tsx(51,9): error TS2531: Object is possibly 'null'. -src/translations/views/TranslationsCategories.tsx(51,9): error TS2531: Object is possibly 'null'. -src/translations/views/TranslationsCategories.tsx(94,40): error TS2571: Object is of type 'unknown'. -src/translations/views/TranslationsCategories.tsx(111,17): error TS2322: Type 'CategoryTranslationDetails_category | null | undefined' is not assignable to type 'CategoryTranslationFragment'. -src/translations/views/TranslationsCategories.tsx(111,39): error TS2532: Object is possibly 'undefined'. -src/translations/views/TranslationsCollections.tsx(51,9): error TS2531: Object is possibly 'null'. -src/translations/views/TranslationsCollections.tsx(51,9): error TS2531: Object is possibly 'null'. -src/translations/views/TranslationsCollections.tsx(97,40): error TS2571: Object is of type 'unknown'. -src/translations/views/TranslationsCollections.tsx(118,17): error TS2322: Type 'CollectionTranslationDetails_collection | null | undefined' is not assignable to type 'CollectionTranslationFragment'. -src/translations/views/TranslationsCollections.tsx(118,41): error TS2532: Object is possibly 'undefined'. -src/translations/views/TranslationsEntities.tsx(44,5): error TS2531: Object is possibly 'null'. -src/translations/views/TranslationsEntities.tsx(47,10): error TS2531: Object is possibly 'null'. -src/translations/views/TranslationsEntities.tsx(47,35): error TS2531: Object is possibly 'null'. -src/translations/views/TranslationsEntities.tsx(61,49): error TS2345: Argument of type '"categories" | "collections" | "pages" | "productTypes" | "products" | "sales" | "vouchers" | undefined' is not assignable to parameter of type 'string'. -src/translations/views/TranslationsEntities.tsx(123,5): error TS2571: Object is of type 'unknown'. -src/translations/views/TranslationsEntities.tsx(150,9): error TS2322: Type '"categories" | "collections" | "pages" | "productTypes" | "products" | "sales" | "vouchers" | undefined' is not assignable to type '"categories" | "collections" | "pages" | "productTypes" | "products" | "sales" | "vouchers"'. -src/translations/views/TranslationsEntities.tsx(160,15): error TS2345: Argument of type 'CategoryTranslations_categories_pageInfo | undefined' is not assignable to parameter of type 'PageInfo'. -src/translations/views/TranslationsEntities.tsx(160,27): error TS2532: Object is possibly 'undefined'. -src/translations/views/TranslationsEntities.tsx(160,27): error TS2531: Object is possibly 'null'. -src/translations/views/TranslationsEntities.tsx(168,17): error TS2322: Type '{ completion: { current: any; max: number; }; id: string; name: string; }[] | undefined' is not assignable to type 'TranslatableEntity[]'. -src/translations/views/TranslationsEntities.tsx(169,19): error TS2532: Object is possibly 'undefined'. -src/translations/views/TranslationsEntities.tsx(169,19): error TS2531: Object is possibly 'null'. -src/translations/views/TranslationsEntities.tsx(210,15): error TS2345: Argument of type 'ProductTranslations_products_pageInfo | undefined' is not assignable to parameter of type 'PageInfo'. -src/translations/views/TranslationsEntities.tsx(210,27): error TS2532: Object is possibly 'undefined'. -src/translations/views/TranslationsEntities.tsx(210,27): error TS2531: Object is possibly 'null'. -src/translations/views/TranslationsEntities.tsx(218,17): error TS2322: Type '{ completion: { current: any; max: number; }; id: string; name: string; }[] | undefined' is not assignable to type 'TranslatableEntity[]'. -src/translations/views/TranslationsEntities.tsx(219,19): error TS2532: Object is possibly 'undefined'. -src/translations/views/TranslationsEntities.tsx(219,19): error TS2531: Object is possibly 'null'. -src/translations/views/TranslationsEntities.tsx(260,15): error TS2345: Argument of type 'CollectionTranslations_collections_pageInfo | undefined' is not assignable to parameter of type 'PageInfo'. -src/translations/views/TranslationsEntities.tsx(260,27): error TS2532: Object is possibly 'undefined'. -src/translations/views/TranslationsEntities.tsx(260,27): error TS2531: Object is possibly 'null'. -src/translations/views/TranslationsEntities.tsx(268,17): error TS2322: Type '{ completion: { current: any; max: number; }; id: string; name: string; }[] | undefined' is not assignable to type 'TranslatableEntity[]'. -src/translations/views/TranslationsEntities.tsx(269,19): error TS2532: Object is possibly 'undefined'. -src/translations/views/TranslationsEntities.tsx(269,19): error TS2531: Object is possibly 'null'. -src/translations/views/TranslationsEntities.tsx(310,15): error TS2345: Argument of type 'SaleTranslations_sales_pageInfo | undefined' is not assignable to parameter of type 'PageInfo'. -src/translations/views/TranslationsEntities.tsx(310,27): error TS2532: Object is possibly 'undefined'. -src/translations/views/TranslationsEntities.tsx(310,27): error TS2531: Object is possibly 'null'. -src/translations/views/TranslationsEntities.tsx(318,17): error TS2322: Type '{ completion: { current: number; max: number; }; id: string; name: string; }[] | undefined' is not assignable to type 'TranslatableEntity[]'. -src/translations/views/TranslationsEntities.tsx(319,19): error TS2532: Object is possibly 'undefined'. -src/translations/views/TranslationsEntities.tsx(319,19): error TS2531: Object is possibly 'null'. -src/translations/views/TranslationsEntities.tsx(348,15): error TS2345: Argument of type 'VoucherTranslations_vouchers_pageInfo | undefined' is not assignable to parameter of type 'PageInfo'. -src/translations/views/TranslationsEntities.tsx(348,27): error TS2532: Object is possibly 'undefined'. -src/translations/views/TranslationsEntities.tsx(348,27): error TS2531: Object is possibly 'null'. -src/translations/views/TranslationsEntities.tsx(356,17): error TS2322: Type '{ completion: { current: number; max: number; }; id: string; name: string | null; }[] | undefined' is not assignable to type 'TranslatableEntity[]'. -src/translations/views/TranslationsEntities.tsx(357,19): error TS2532: Object is possibly 'undefined'. -src/translations/views/TranslationsEntities.tsx(357,19): error TS2531: Object is possibly 'null'. -src/translations/views/TranslationsEntities.tsx(390,15): error TS2345: Argument of type 'PageTranslations_pages_pageInfo | undefined' is not assignable to parameter of type 'PageInfo'. -src/translations/views/TranslationsEntities.tsx(390,27): error TS2532: Object is possibly 'undefined'. -src/translations/views/TranslationsEntities.tsx(390,27): error TS2531: Object is possibly 'null'. -src/translations/views/TranslationsEntities.tsx(398,17): error TS2322: Type '{ completion: { current: any; max: number; }; id: string; name: string; }[] | undefined' is not assignable to type 'TranslatableEntity[]'. -src/translations/views/TranslationsEntities.tsx(399,19): error TS2532: Object is possibly 'undefined'. -src/translations/views/TranslationsEntities.tsx(399,19): error TS2531: Object is possibly 'null'. -src/translations/views/TranslationsEntities.tsx(436,15): error TS2345: Argument of type 'ProductTypeTranslations_productTypes_pageInfo | undefined' is not assignable to parameter of type 'PageInfo'. -src/translations/views/TranslationsEntities.tsx(436,27): error TS2532: Object is possibly 'undefined'. -src/translations/views/TranslationsEntities.tsx(436,27): error TS2531: Object is possibly 'null'. -src/translations/views/TranslationsEntities.tsx(444,17): error TS2322: Type '{ completion: { current: number; max: number; }; id: string; name: string; }[] | undefined' is not assignable to type 'TranslatableEntity[]'. -src/translations/views/TranslationsEntities.tsx(445,19): error TS2532: Object is possibly 'undefined'. -src/translations/views/TranslationsEntities.tsx(445,19): error TS2531: Object is possibly 'null'. -src/translations/views/TranslationsEntities.tsx(451,31): error TS2531: Object is possibly 'null'. -src/translations/views/TranslationsEntities.tsx(455,31): error TS2531: Object is possibly 'null'. -src/translations/views/TranslationsEntities.tsx(463,54): error TS2531: Object is possibly 'null'. -src/translations/views/TranslationsEntities.tsx(463,54): error TS2531: Object is possibly 'null'. -src/translations/views/TranslationsEntities.tsx(467,54): error TS2531: Object is possibly 'null'. -src/translations/views/TranslationsEntities.tsx(467,54): error TS2531: Object is possibly 'null'. -src/translations/views/TranslationsLanguageList.tsx(15,30): error TS2571: Object is of type 'unknown'. -src/translations/views/TranslationsPages.tsx(54,9): error TS2531: Object is possibly 'null'. -src/translations/views/TranslationsPages.tsx(54,9): error TS2531: Object is possibly 'null'. -src/translations/views/TranslationsPages.tsx(97,40): error TS2571: Object is of type 'unknown'. -src/translations/views/TranslationsPages.tsx(114,17): error TS2322: Type 'PageTranslationDetails_page | null | undefined' is not assignable to type 'PageTranslationFragment'. -src/translations/views/TranslationsPages.tsx(114,35): error TS2532: Object is possibly 'undefined'. -src/translations/views/TranslationsProducts.tsx(51,9): error TS2531: Object is possibly 'null'. -src/translations/views/TranslationsProducts.tsx(51,9): error TS2531: Object is possibly 'null'. -src/translations/views/TranslationsProducts.tsx(94,40): error TS2571: Object is of type 'unknown'. -src/translations/views/TranslationsProducts.tsx(111,17): error TS2322: Type 'ProductTranslationDetails_product | null | undefined' is not assignable to type 'ProductTranslationFragment'. -src/translations/views/TranslationsProducts.tsx(111,38): error TS2532: Object is possibly 'undefined'. -src/translations/views/TranslationsProductTypes.tsx(58,9): error TS2531: Object is possibly 'null'. -src/translations/views/TranslationsProductTypes.tsx(58,9): error TS2531: Object is possibly 'null'. -src/translations/views/TranslationsProductTypes.tsx(66,9): error TS2531: Object is possibly 'null'. -src/translations/views/TranslationsProductTypes.tsx(66,9): error TS2531: Object is possibly 'null'. -src/translations/views/TranslationsProductTypes.tsx(120,19): error TS2345: Argument of type 'UpdateAttributeTranslations_attributeTranslate_errors[] | null' is not assignable to parameter of type 'UserError[]'. -src/translations/views/TranslationsProductTypes.tsx(122,23): error TS2532: Object is possibly 'undefined'. -src/translations/views/TranslationsProductTypes.tsx(122,23): error TS2531: Object is possibly 'null'. -src/translations/views/TranslationsProductTypes.tsx(128,23): error TS2532: Object is possibly 'undefined'. -src/translations/views/TranslationsProductTypes.tsx(128,23): error TS2531: Object is possibly 'null'. -src/translations/views/TranslationsProductTypes.tsx(143,44): error TS2571: Object is of type 'unknown'. -src/translations/views/TranslationsProductTypes.tsx(164,21): error TS2322: Type 'ProductTypeTranslationDetails_productType | null | undefined' is not assignable to type 'ProductTypeTranslationFragment'. -src/translations/views/TranslationsProductTypes.tsx(165,29): error TS2532: Object is possibly 'undefined'. -src/translations/views/TranslationsSales.tsx(54,9): error TS2531: Object is possibly 'null'. -src/translations/views/TranslationsSales.tsx(54,9): error TS2531: Object is possibly 'null'. -src/translations/views/TranslationsSales.tsx(90,40): error TS2571: Object is of type 'unknown'. -src/translations/views/TranslationsSales.tsx(108,17): error TS2322: Type 'SaleTranslationDetails_sale | null | undefined' is not assignable to type 'SaleTranslationFragment'. -src/translations/views/TranslationsSales.tsx(108,35): error TS2532: Object is possibly 'undefined'. -src/translations/views/TranslationsVouchers.tsx(54,9): error TS2531: Object is possibly 'null'. -src/translations/views/TranslationsVouchers.tsx(54,9): error TS2531: Object is possibly 'null'. -src/translations/views/TranslationsVouchers.tsx(90,40): error TS2571: Object is of type 'unknown'. -src/translations/views/TranslationsVouchers.tsx(108,17): error TS2322: Type 'VoucherTranslationDetails_voucher | null | undefined' is not assignable to type 'VoucherTranslationFragment'. -src/translations/views/TranslationsVouchers.tsx(108,38): error TS2532: Object is possibly 'undefined'. -src/utils/credentialsManagement.ts(7,7): error TS2774: This condition will always return true since the function is always defined. Did you mean to call it instead? -src/utils/credentialsManagement.ts(10,32): error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'. -src/utils/credentialsManagement.ts(17,7): error TS2774: This condition will always return true since the function is always defined. Did you mean to call it instead? -src/utils/errors.ts(4,3): error TS2322: Type 'UserError | undefined' is not assignable to type 'UserError'. -src/utils/filters/storage.ts(11,21): error TS2345: Argument of type 'string | null' is not assignable to parameter of type 'string'. -src/utils/handlers/multiAutocompleteSelectChangeHandler.ts(17,17): error TS2345: Argument of type '(MultiAutocompleteChoiceType | undefined)[]' is not assignable to parameter of type 'MultiAutocompleteChoiceType[]'. -src/utils/handlers/multiAutocompleteSelectChangeHandler.ts(17,52): error TS2532: Object is possibly 'undefined'. -src/utils/handlers/multiAutocompleteSelectChangeHandler.ts(17,64): error TS2532: Object is possibly 'undefined'. -src/utils/menu/menu.ts(30,9): error TS2322: Type '(TValue | undefined)[]' is not assignable to type 'TValue[]'. -src/utils/menu/menu.ts(59,9): error TS2322: Type 'IFlatMenuItem | undefined' is not assignable to type 'IFlatMenuItem'. -src/utils/menu/menu.ts(97,7): error TS2532: Object is possibly 'undefined'. -src/utils/menu/menu.ts(98,13): error TS2322: Type 'IFlatMenuItem | undefined' is not assignable to type 'IFlatMenuItem'. -src/utils/menu/menu.ts(101,11): error TS2322: Type 'IFlatMenuItem | undefined' is not assignable to type 'IFlatMenuItem'. -src/utils/menu/menu.ts(101,46): error TS2532: Object is possibly 'undefined'. -src/utils/menu/menu.ts(110,11): error TS2532: Object is possibly 'undefined'. -src/utils/menu/menu.ts(112,43): error TS2532: Object is possibly 'undefined'. -src/utils/menu/menu.ts(113,45): error TS2345: Argument of type 'IFlatMenuItem | undefined' is not assignable to parameter of type 'IFlatMenuItem'. -src/utils/menu/menu.ts(144,72): error TS2345: Argument of type 'null' is not assignable to parameter of type 'string'. -src/utils/sort.ts(82,3): error TS2322: Type '(params: TParams) => { direction: OrderDirection; field: TSortField; } | undefined' is not assignable to type 'GetSortQueryVariables'. -src/utils/urls.ts(12,5): error TS2322: Type 'undefined' is not assignable to type 'string[]'. -src/webhooks/components/WebhookCreatePage/WebhookCreatePage.tsx(65,7): error TS2532: Object is possibly 'undefined'. -src/webhooks/components/WebhookCreatePage/WebhookCreatePage.tsx(78,11): error TS2345: Argument of type '{ label: string | null; value: string; }[]' is not assignable to parameter of type 'SingleAutocompleteChoiceType[]'. -src/webhooks/components/WebhookCreatePage/WebhookCreatePage.tsx(99,19): error TS2322: Type '{ label: string | null; value: string; }[]' is not assignable to type 'SingleAutocompleteChoiceType[]'. -src/webhooks/components/WebhookInfo/WebhookInfo.tsx(75,34): error TS2345: Argument of type 'WebhookCreate_webhookCreate_webhookErrors[]' is not assignable to parameter of type 'UserError[]'. -src/webhooks/components/WebhookInfo/WebhookInfo.tsx(76,37): error TS2345: Argument of type 'WebhookCreate_webhookCreate_webhookErrors[]' is not assignable to parameter of type 'UserError[]'. -src/webhooks/components/WebhookInfo/WebhookInfo.tsx(102,11): error TS2322: Type 'string | false' is not assignable to type 'string | undefined'. -src/webhooks/components/WebhookInfo/WebhookInfo.tsx(118,34): error TS2345: Argument of type 'WebhookCreate_webhookCreate_webhookErrors[]' is not assignable to parameter of type 'UserError[]'. -src/webhooks/components/WebhookInfo/WebhookInfo.tsx(120,27): error TS2345: Argument of type 'WebhookCreate_webhookCreate_webhookErrors[]' is not assignable to parameter of type 'UserError[]'. -src/webhooks/components/WebhookInfo/WebhookInfo.tsx(138,34): error TS2345: Argument of type 'WebhookCreate_webhookCreate_webhookErrors[]' is not assignable to parameter of type 'UserError[]'. -src/webhooks/components/WebhookInfo/WebhookInfo.tsx(140,27): error TS2345: Argument of type 'WebhookCreate_webhookCreate_webhookErrors[]' is not assignable to parameter of type 'UserError[]'. -src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.stories.tsx(28,7): error TS2322: Type 'undefined' is not assignable to type 'WebhookDetails_webhook'. -src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx(59,18): error TS2531: Object is possibly 'null'. -src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx(60,16): error TS2531: Object is possibly 'null'. -src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx(62,5): error TS2322: Type '(WebhookEventTypeEnum | null)[]' is not assignable to type 'WebhookEventTypeEnum[]'. -src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx(62,13): error TS2531: Object is possibly 'null'. -src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx(63,21): error TS2531: Object is possibly 'null'. -src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx(66,5): error TS2322: Type 'string | null' is not assignable to type 'string'. -src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx(77,7): error TS2532: Object is possibly 'undefined'. -src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx(89,11): error TS2345: Argument of type '{ label: string | null; value: string; }[]' is not assignable to parameter of type 'SingleAutocompleteChoiceType[]'. -src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx(112,19): error TS2322: Type 'string | null' is not assignable to type 'string'. -src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx(113,19): error TS2322: Type '{ label: string | null; value: string; }[]' is not assignable to type 'SingleAutocompleteChoiceType[]'. -src/webhooks/components/WebhooksList/WebhooksList.tsx(87,37): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/webhooks/components/WebhooksList/WebhooksList.tsx(102,37): error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'. -src/webhooks/components/WebhooksList/WebhooksList.tsx(147,47): error TS2532: Object is possibly 'undefined'. -src/webhooks/components/WebhooksList/WebhooksList.tsx(151,25): error TS2532: Object is possibly 'undefined'. -src/webhooks/components/WebhooksListPage/WebhookListPage.stories.tsx(43,50): error TS2322: Type 'undefined' is not assignable to type 'Webhooks_webhooks_edges_node[]'. -src/webhooks/views/WebhookList/filters.ts(38,37): error TS2345: Argument of type 'undefined' is not assignable to parameter of type 'boolean'. -src/webhooks/views/WebhookList/sort.ts(14,7): error TS2322: Type 'undefined' is not assignable to type 'WebhookSortField'. -src/webhooks/views/WebhookList/WebhookList.tsx(89,5): error TS2322: Type '(params?: WebhookListUrlQueryParams | undefined) => string' is not assignable to type 'CreateUrl'. -src/webhooks/views/WebhookList/WebhookList.tsx(120,9): error TS2531: Object is possibly 'null'. -src/webhooks/views/WebhookList/WebhookList.tsx(120,9): error TS2531: Object is possibly 'null'. -src/webhooks/views/WebhookList/WebhookList.tsx(130,38): error TS2571: Object is of type 'unknown'. -src/webhooks/views/WebhookList/WebhookList.tsx(136,11): error TS2345: Argument of type 'Webhooks_webhooks_pageInfo | undefined' is not assignable to parameter of type 'PageInfo'. -src/webhooks/views/WebhookList/WebhookList.tsx(136,23): error TS2532: Object is possibly 'undefined'. -src/webhooks/views/WebhookList/WebhookList.tsx(136,23): error TS2531: Object is possibly 'null'. -src/webhooks/views/WebhookList/WebhookList.tsx(150,25): error TS2345: Argument of type '{ variables: { id: string | undefined; }; }' is not assignable to parameter of type 'MutationFunctionOptions'. -src/webhooks/views/WebhookList/WebhookList.tsx(174,15): error TS2322: Type 'Webhooks_webhooks_edges_node[] | undefined' is not assignable to type 'Webhooks_webhooks_edges_node[]'. -src/webhooks/views/WebhookList/WebhookList.tsx(174,37): error TS2532: Object is possibly 'undefined'. -src/webhooks/views/WebhookList/WebhookList.tsx(174,37): error TS2531: Object is possibly 'null'. -src/webhooks/views/WebhookList/WebhookList.tsx(187,15): error TS2322: Type 'string | null' is not assignable to type 'string'. -src/webhooks/views/WebhookList/WebhookList.tsx(189,19): error TS2532: Object is possibly 'undefined'. -src/webhooks/views/WebhookList/WebhookList.tsx(189,19): error TS2531: Object is possibly 'null'. -src/webhooks/views/WebhookList/WebhookList.tsx(189,19): error TS2532: Object is possibly 'undefined'. -src/webhooks/views/WebhooksCreate.tsx(33,9): error TS2531: Object is possibly 'null'. -src/webhooks/views/WebhooksCreate.tsx(33,9): error TS2531: Object is possibly 'null'. -src/webhooks/views/WebhooksCreate.tsx(37,27): error TS2531: Object is possibly 'null'. -src/webhooks/views/WebhooksCreate.tsx(37,27): error TS2531: Object is possibly 'null'. -src/webhooks/views/WebhooksCreate.tsx(72,15): error TS2322: Type 'WebhookCreate_webhookCreate_webhookErrors[] | null' is not assignable to type 'WebhookCreate_webhookCreate_webhookErrors[]'. -src/webhooks/views/WebhooksCreate.tsx(73,23): error TS2532: Object is possibly 'undefined'. -src/webhooks/views/WebhooksCreate.tsx(73,23): error TS2531: Object is possibly 'null'. -src/webhooks/views/WebhooksDetails.tsx(52,9): error TS2531: Object is possibly 'null'. -src/webhooks/views/WebhooksDetails.tsx(64,9): error TS2533: Object is possibly 'null' or 'undefined'. -src/webhooks/views/WebhooksDetails.tsx(90,19): error TS2531: Object is possibly 'null'. -src/webhooks/views/WebhooksDetails.tsx(100,25): error TS2345: Argument of type 'string | null | undefined' is not assignable to parameter of type 'string | undefined'. -src/webhooks/views/WebhooksDetails.tsx(107,23): error TS2322: Type 'WebhookDetails_webhook | undefined' is not assignable to type 'WebhookDetails_webhook'. -src/webhooks/views/WebhooksDetails.tsx(136,52): error TS2345: Argument of type 'string | null | undefined' is not assignable to parameter of type 'string | undefined'. diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c61104ad..f4d457413 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,10 +4,48 @@ All notable, unreleased changes to this project will be documented in this file. ## [Unreleased] +- Add sku column to fulfillment cards - #538 by @dominik-zeglen +- Migrate product base price to variant prices - #555 by @orzechdev +- Migrate old notifications to the new ones - #587 by @AlicjaSzu +- Add background task manager - #574 by @dominik-zeglen +- Handle task failure and fix task duplication - #588 by @dominik-zeglen +- Move fragments to separate directory to avoid circular imports - #592 by @dominik-zeglen +- Add order invoices management - #570 by @orzechdev +- Add Cypress e2e runner - #584 by @krzysztofwolski +- create Apps - #599 by @AlicjaSzu +- Refactor authorization - #624 by @dominik-zeglen +- Fix minor bugs - #628 by @dominik-zeglen +- Add navigator button - #635 by @dominik-zeglen +- Update to newest schema - #638 by @dominik-zeglen +- Fix missing save button - #636 by @dominik-zeglen +- Fix user avatars - #639 by @dominik-zeglen +- Reset modal state after closing - #644 by @dominik-zeglen +- Fix incorrect messages - #643 by @dominik-zeglen +- Do not use devserver to run cypress tests - #650 by @dominik-zeglen +- Fix updating product that has no variants - #649 by @dominik-zeglen +- Update checkbox design - #651 by @dominik-zeglen +- Add warehouse choice - #646 by @dominik-zeglen +- Fix user management modal actions - #637 by @eaglesemanation +- Fix navigator button rendering on safari browser - #656 by @dominik-zeglen +- Use hooks instead of containers with render props in product mutations - #667 by @dominik-zeglen +- Add apps and permission groups to navigator - #678 by @dominik-zeglen +- Add metadata - #670 by @dominik-zeglen +- Update order history information - #680 by @dominik-zeglen +- Add metadata editor to creator views - #684 by @dominik-zeglen +- Update product visibility card component - #679 by @AlicjaSzu +- Update savebar design - #690 by @dominik-zeglen +- Add metadata to orders - #688 by @dominik-zeglen +- Add lazyload to locales - #692 by @eaglesemanation +- Fix not closed address update modal with two confirmations - #699 by @orzechdev +- Update schema with PositiveDecimal type - #695 by @AlicjaSzu +- Restyle side menu - #697 by @dominik-zeglen +- Add error info when fetching taxes - #701 by @dominik-zeglen + ## 2.10.1 - Add weight field and fix warehouse country selection - #597 by @dominik-zeglen - Fix weight based rate update - #604 by @dominik-zeglen +- Add product export - #620 by @dominik-zeglen ## 2.10.0 @@ -58,6 +96,7 @@ All notable, unreleased changes to this project will be documented in this file. - Update product stock management to newest design - #515 by @dominik-zeglen - Handle untracked products - #523 by @dominik-zeglen - Display correct error if there were no graphql errors - #525 by @dominik-zeglen +- Fix updating order details on address change #711 - by @orzechdev ## 2.0.0 diff --git a/README.md b/README.md index 62bc5ce01..e017afe64 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Saleor Dashboard -![1 copy 2x](https://user-images.githubusercontent.com/5421321/47799917-8afd7a00-dd2b-11e8-88c7-63588e25bcea.png) +![Saleor Dashboard](https://user-images.githubusercontent.com/249912/82305745-5c52fd00-99be-11ea-9ac6-cc04a6f28c91.png) A GraphQL-powered, single-page dashboard application for [Saleor](https://github.com/mirumee/saleor/). @@ -87,3 +87,5 @@ To build the application bundle run: ``` $ npm run build ``` + +#### Crafted with â¤ī¸ by [Mirumee Software](https://mirumee.com) diff --git a/assets/images/activate-icon.svg b/assets/images/activate-icon.svg new file mode 100644 index 000000000..8ac7d076a --- /dev/null +++ b/assets/images/activate-icon.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/images/app-install-error.svg b/assets/images/app-install-error.svg new file mode 100644 index 000000000..44d68cafe --- /dev/null +++ b/assets/images/app-install-error.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/empty-metadata.svg b/assets/images/empty-metadata.svg new file mode 100644 index 000000000..42ed7d5df --- /dev/null +++ b/assets/images/empty-metadata.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/assets/images/error-icon.svg b/assets/images/error-icon.svg new file mode 100644 index 000000000..5f42eef60 --- /dev/null +++ b/assets/images/error-icon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/images/info-icon.svg b/assets/images/info-icon.svg new file mode 100644 index 000000000..425fc218d --- /dev/null +++ b/assets/images/info-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/login-background.svg b/assets/images/login-background.svg index f3489b8b5..30389401f 100644 --- a/assets/images/login-background.svg +++ b/assets/images/login-background.svg @@ -95,7 +95,7 @@ - + @@ -115,7 +115,7 @@ - + diff --git a/assets/images/logo-sidebar-light.svg b/assets/images/logo-sidebar-light.svg new file mode 100644 index 000000000..6d186cce1 --- /dev/null +++ b/assets/images/logo-sidebar-light.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/images/logo-white.svg b/assets/images/logo-white.svg deleted file mode 100644 index d01d84844..000000000 --- a/assets/images/logo-white.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/assets/images/menu-apps-icon.svg b/assets/images/menu-apps-icon.svg new file mode 100644 index 000000000..85d36954a --- /dev/null +++ b/assets/images/menu-apps-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/menu-catalog-icon.svg b/assets/images/menu-catalog-icon.svg index 6b67b5aac..159804b6d 100644 --- a/assets/images/menu-catalog-icon.svg +++ b/assets/images/menu-catalog-icon.svg @@ -1,3 +1,3 @@ - - + + diff --git a/assets/images/menu-configure-icon.svg b/assets/images/menu-configure-icon.svg index c1defe727..7a435af97 100644 --- a/assets/images/menu-configure-icon.svg +++ b/assets/images/menu-configure-icon.svg @@ -1,3 +1,3 @@ - - + + diff --git a/assets/images/menu-customers-icon.svg b/assets/images/menu-customers-icon.svg index b46a2fc1e..989bc7b0d 100644 --- a/assets/images/menu-customers-icon.svg +++ b/assets/images/menu-customers-icon.svg @@ -1,3 +1,3 @@ - - + + diff --git a/assets/images/menu-discounts-icon.svg b/assets/images/menu-discounts-icon.svg index 6f15dce79..30ca87a8e 100644 --- a/assets/images/menu-discounts-icon.svg +++ b/assets/images/menu-discounts-icon.svg @@ -1,3 +1,3 @@ - - + + diff --git a/assets/images/menu-home-icon.svg b/assets/images/menu-home-icon.svg index f91bd00a1..2c90eedf3 100644 --- a/assets/images/menu-home-icon.svg +++ b/assets/images/menu-home-icon.svg @@ -1,3 +1,3 @@ - - + + diff --git a/assets/images/menu-orders-icon.svg b/assets/images/menu-orders-icon.svg index 1e97d098d..74603fe7a 100644 --- a/assets/images/menu-orders-icon.svg +++ b/assets/images/menu-orders-icon.svg @@ -1,3 +1,3 @@ - - + + diff --git a/assets/images/menu-translation-icon.svg b/assets/images/menu-translation-icon.svg index 7d034dd68..e869dedd1 100644 --- a/assets/images/menu-translation-icon.svg +++ b/assets/images/menu-translation-icon.svg @@ -1,3 +1,3 @@ - - + + diff --git a/assets/images/navigator.svg b/assets/images/navigator.svg new file mode 100644 index 000000000..dbbde3b2f --- /dev/null +++ b/assets/images/navigator.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/plus-icon.svg b/assets/images/plus-icon.svg new file mode 100644 index 000000000..8a0ed5ebd --- /dev/null +++ b/assets/images/plus-icon.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/images/settings-icon.svg b/assets/images/settings-icon.svg new file mode 100644 index 000000000..452240eb0 --- /dev/null +++ b/assets/images/settings-icon.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/images/success-icon.svg b/assets/images/success-icon.svg new file mode 100644 index 000000000..7f7965403 --- /dev/null +++ b/assets/images/success-icon.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/images/support-icon.svg b/assets/images/support-icon.svg new file mode 100644 index 000000000..71b29d507 --- /dev/null +++ b/assets/images/support-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/warning-icon.svg b/assets/images/warning-icon.svg new file mode 100644 index 000000000..f073d2756 --- /dev/null +++ b/assets/images/warning-icon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/cypress.json b/cypress.json new file mode 100644 index 000000000..68d5704a0 --- /dev/null +++ b/cypress.json @@ -0,0 +1,7 @@ +{ + "baseUrl": "http://localhost:9000", + "defaultCommandTimeout": 15000, + "requestTimeout": 15000, + "viewportWidth": 1400, + "viewportHeight": 660 +} diff --git a/cypress/elements/account/left-menu/left-menu-selectors.js b/cypress/elements/account/left-menu/left-menu-selectors.js new file mode 100644 index 000000000..fb525ee06 --- /dev/null +++ b/cypress/elements/account/left-menu/left-menu-selectors.js @@ -0,0 +1,4 @@ +/* eslint-disable sort-keys */ +export const LEFT_MENU_SELECTORS = { + catalog: "[data-test-id='catalogue']" +}; diff --git a/cypress/elements/account/login-selectors.js b/cypress/elements/account/login-selectors.js new file mode 100644 index 000000000..388f6b458 --- /dev/null +++ b/cypress/elements/account/login-selectors.js @@ -0,0 +1,9 @@ +export const LOGIN_SELECTORS = { + accountSettings: "[data-test=accountSettingsButton]", + emailAddressInput: "input[name='email']", + emailPasswordInput: "input[name='password']", + signInButton: "[data-test=submit]", + userMenu: "[data-test=userMenu]", + warningCredentialMessage: "[data-test=loginErrorMessage]", + welcomePage: "[data-test=welcomeHeader]" +}; diff --git a/cypress/elements/catalog/product-selectors.js b/cypress/elements/catalog/product-selectors.js new file mode 100644 index 000000000..6e9c992aa --- /dev/null +++ b/cypress/elements/catalog/product-selectors.js @@ -0,0 +1,13 @@ +/* eslint-disable sort-keys */ +export const PRODUCTS_SELECTORS = { + products: "[data-test='submenu-item-label'][data-test-id='products']", + createProductBtn: "[data-test='add-product']", + productNameInput: "[name='name']", + productTypeInput: "[data-test='product-type']", + categoryInput: "[data-test='category']", + categoryItem: "[data-test='singleautocomplete-select-option']", + firstCategoryItem: "#downshift-0-item-0", + visibleRadioBtn: "[name='isPublished']", + saveBtn: "[data-test='button-bar-confirm']", + confirmationMsg: "[data-test='notification']" +}; diff --git a/cypress/integration/login_form.js b/cypress/integration/login_form.js new file mode 100644 index 000000000..e4af3a27a --- /dev/null +++ b/cypress/integration/login_form.js @@ -0,0 +1,38 @@ +import { LOGIN_SELECTORS } from "../elements/account/login-selectors"; + +// +describe("User authorization", () => { + beforeEach(() => { + cy.clearSessionData(); + }); + + it("should successfully log in an user", () => { + cy.visit("/"); + cy.loginUser(); + cy.get(LOGIN_SELECTORS.welcomePage); + }); + + it("should fail for wrong password", () => { + cy.visit("/") + .get(LOGIN_SELECTORS.emailAddressInput) + .type("admin@example.com") + .get(LOGIN_SELECTORS.emailPasswordInput) + .type("wrong-password") + .get(LOGIN_SELECTORS.signInButton) + .click() + .get(LOGIN_SELECTORS.warningCredentialMessage); + }); + + it("should successfully log out an user", () => { + cy.window().then(win => { + win.sessionStorage.clear(); + }); + cy.visit("/"); + cy.loginUser(); + cy.get(LOGIN_SELECTORS.userMenu) + .click() + .get(LOGIN_SELECTORS.accountSettings) + .click(); + cy.location("pathname").should("contains", "/staff/"); + }); +}); diff --git a/cypress/integration/products.js b/cypress/integration/products.js new file mode 100644 index 000000000..b7a034c69 --- /dev/null +++ b/cypress/integration/products.js @@ -0,0 +1,43 @@ +import { LEFT_MENU_SELECTORS } from "../elements/account/left-menu/left-menu-selectors"; +import { PRODUCTS_SELECTORS } from "../elements/catalog/product-selectors"; + +// +describe("Products", () => { + beforeEach(() => { + cy.clearSessionData().loginUserViaRequest(); + }); + + it("should add new visible product", () => { + cy.visit("/") + .get(LEFT_MENU_SELECTORS.catalog) + .click() + .get(PRODUCTS_SELECTORS.products) + .click() + .get(PRODUCTS_SELECTORS.createProductBtn) + .click() + .get(PRODUCTS_SELECTORS.productNameInput) + .click() + .type("Visible test product") + .get(PRODUCTS_SELECTORS.productTypeInput) + .click() + .type("Cushion") + .get(PRODUCTS_SELECTORS.categoryItem) + .should("have.length", 1) + .get(PRODUCTS_SELECTORS.firstCategoryItem) + .click() + .get(PRODUCTS_SELECTORS.categoryInput) + .click() + .get(PRODUCTS_SELECTORS.categoryItem) + .first() + .click() + .get(PRODUCTS_SELECTORS.visibleRadioBtn) + .first() + .click() + .get(PRODUCTS_SELECTORS.saveBtn) + .click() + .get(PRODUCTS_SELECTORS.confirmationMsg, { + timeout: 1000 + }) + .contains("Product created"); + }); +}); diff --git a/cypress/integration/warehouse.js b/cypress/integration/warehouse.js new file mode 100644 index 000000000..208321164 --- /dev/null +++ b/cypress/integration/warehouse.js @@ -0,0 +1,23 @@ +// +describe("Warehouse settings", () => { + beforeEach(() => { + cy.clearSessionData(); + }); + + xit("Warehouse section visible in the configuration", () => { + cy.visit("/configuration/") + .loginUser() + .get("[data-test-id=warehouses][data-test=settingsSubsection]") + .click(); + cy.location("pathname").should("eq", "/warehouses/"); + }); + + xit("Editing warehouse is available", () => { + cy.visit(`/warehouses`) + .loginUser() + .get("[data-test=editButton]") + .first() + .click() + .get("[data-test=generalInformationSection]"); + }); +}); diff --git a/cypress/plugins/index.js b/cypress/plugins/index.js new file mode 100644 index 000000000..9c5d27c8c --- /dev/null +++ b/cypress/plugins/index.js @@ -0,0 +1,22 @@ +// / +// *********************************************************** +// This example plugins/index.js can be used to load plugins +// +// You can change the location of this file or turn off loading +// the plugins file with the 'pluginsFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/plugins-guide +// *********************************************************** + +// This function is called when a project is opened or re-opened (e.g. due to +// the project's config changing) + +/** + * @type {Cypress.PluginConfig} + */ +module.exports = (on, config) => { + config.env.API_URI = process.env.API_URI; + + return config; +}; diff --git a/cypress/support/index.js b/cypress/support/index.js new file mode 100644 index 000000000..531b8aab9 --- /dev/null +++ b/cypress/support/index.js @@ -0,0 +1,19 @@ +import "./user"; + +Cypress.Commands.add("clearSessionData", () => { + // Because of known cypress bug, not all local storage data are cleared. + // Here is workaround to ensure tests have no side effects. + // Suggested usage: + + // beforeEach(() => { + // cy.clearSessionData(); + // }); + + cy.clearCookies(); + cy.clearLocalStorage(); + cy.visit("/", { + onBeforeLoad: win => { + win.sessionStorage.clear(); + } + }); +}); diff --git a/cypress/support/user/index.js b/cypress/support/user/index.js new file mode 100644 index 000000000..9edf99e27 --- /dev/null +++ b/cypress/support/user/index.js @@ -0,0 +1,48 @@ +/* eslint-disable sort-keys */ +import { LOGIN_SELECTORS } from "../../elements/account/login-selectors"; + +Cypress.Commands.add("loginUser", () => + cy + .get(LOGIN_SELECTORS.emailAddressInput) + .type(Cypress.env("USER_NAME")) + .get(LOGIN_SELECTORS.emailPasswordInput) + .type(Cypress.env("USER_PASSWORD"), { log: false }) + .get(LOGIN_SELECTORS.signInButton) + .click() +); + +Cypress.Commands.add("loginUserViaRequest", () => { + const logInMutationQuery = `mutation TokenAuth($email: String!, $password: String!) { + tokenCreate(email: $email, password: $password) { + token + errors: accountErrors { + code + field + message + __typename + } + user { + id + __typename + } + __typename + } + }`; + + return cy + .request({ + method: "POST", + url: Cypress.env("API_URI"), + body: { + operationName: "TokenAuth", + variables: { + email: Cypress.env("USER_NAME"), + password: Cypress.env("USER_PASSWORD") + }, + query: logInMutationQuery + } + }) + .then(resp => { + window.sessionStorage.setItem("auth", resp.body.data.tokenCreate.token); + }); +}); diff --git a/lighthouserc.json b/lighthouserc.json new file mode 100644 index 000000000..ac231e81b --- /dev/null +++ b/lighthouserc.json @@ -0,0 +1,9 @@ +{ + "ci": { + "collect": { + "url": ["http://localhost:3000/"], + "numberOfRuns": 5, + "staticDistDir": "./build/dashboard" + } + } +} diff --git a/locale/ar.json b/locale/ar.json index 7e2c6a727..b24a869f0 100644 --- a/locale/ar.json +++ b/locale/ar.json @@ -250,7 +250,7 @@ "context": "optional field", "string": "Optional" }, - "productVariantPriceOptionalPriceOverrideField": { + "productVariantPriceOptionalPriceField": { "context": "optional field", "string": "Optional" }, @@ -560,7 +560,7 @@ }, "src_dot_back": { "context": "button", - "string": "Back" + "string": "ØšŲˆØ¯ØŠ" }, "src_dot_cancel": { "context": "button", @@ -738,11 +738,11 @@ }, "src_dot_collections_dot_components_dot_CollectionCreatePage_dot_1815688500": { "context": "collection", - "string": "since {date}" + "string": "Ų…Ų†Ø° {date}" }, "src_dot_collections_dot_components_dot_CollectionCreatePage_dot_2001551496": { "context": "collection", - "string": "will be visible from {date}" + "string": "ØŗØĒŲƒŲˆŲ† Ø¸Ø§Ų‡Øą Ų…Ų† {date}" }, "src_dot_collections_dot_components_dot_CollectionCreatePage_dot_946315389": { "string": "ØŖØļ؁ ØšŲ†ŲˆØ§Ų† Ų…Ø­ØąŲƒ Ø§Ų„Ø¨Ø­ØĢ ؈ ؈Øĩ؁؇ Ų„ØĒØŗŲ‡ŲŠŲ„ Ø§Ų„ØšØĢŲˆØą ØšŲ„Ų‰ Ų‡Ø°Ų‡ Ø§Ų„ŲØĻØŠ" @@ -753,11 +753,11 @@ }, "src_dot_collections_dot_components_dot_CollectionDetailsPage_dot_1815688500": { "context": "collection", - "string": "since {date}" + "string": "Ų…Ų†Ø° {date}" }, "src_dot_collections_dot_components_dot_CollectionDetailsPage_dot_2001551496": { "context": "collection", - "string": "will be visible from {date}" + "string": "ØŗØĒŲƒŲˆŲ† Ø¸Ø§Ų‡Øą Ų…Ų† {date}" }, "src_dot_collections_dot_components_dot_CollectionDetailsPage_dot_2906897537": { "context": "switch button", @@ -1076,7 +1076,7 @@ }, "src_dot_components_dot_ErrorPage_dot_1723676032": { "context": "button", - "string": "Back to home" + "string": "Ø§Ų„ØšŲˆØ¯ØŠ ØĨŲ„Ų‰ Ø§Ų„ØĩŲØ­ØŠ Ø§Ų„ØąØĻŲŠØŗŲŠØŠ" }, "src_dot_components_dot_ErrorPage_dot_2736139139": { "string": "Ooops!..." @@ -1114,7 +1114,7 @@ }, "src_dot_components_dot_Filter_dot_2683154806": { "context": "is filter range or value", - "string": "equal to" + "string": "ŲŠØŗØ§ŲˆŲŠ" }, "src_dot_components_dot_Filter_dot_2779594451": { "context": "filter range separator", @@ -1126,7 +1126,7 @@ }, "src_dot_components_dot_Filter_dot_773313536": { "context": "is filter range or value", - "string": "between" + "string": "Ų…Ø§ Ø¨ŲŠŲ†" }, "src_dot_components_dot_Filter_dot_996289613": { "string": "ŲŲ„Ø§ØĒØą" @@ -1145,7 +1145,7 @@ }, "src_dot_components_dot_MoneyRange_dot_12301532": { "context": "money", - "string": "to {money}" + "string": "ØĨŲ„Ų‰ {money}" }, "src_dot_components_dot_MoneyRange_dot_1316359951": { "context": "money", @@ -1153,7 +1153,7 @@ }, "src_dot_components_dot_MoneyRange_dot_3729849657": { "context": "money", - "string": "from {money}" + "string": "Ų…Ų† {money}" }, "src_dot_components_dot_MultiAutocompleteSelectField_dot_1477537381": { "context": "add custom select input option", @@ -1406,19 +1406,19 @@ }, "src_dot_components_dot_WeightRange_dot_264731940": { "context": "weight", - "string": "to {value} {unit}" + "string": "ØĨŲ„Ų‰ {unit} {value}" }, "src_dot_components_dot_WeightRange_dot_2892071052": { "context": "weight", - "string": "{fromValue} {fromUnit} - {toValue} {toUnit}" + "string": "{toValue} {toUnit} - {fromValue} {fromUnit}" }, "src_dot_components_dot_WeightRange_dot_4256193688": { "context": "weight", - "string": "from {value} {unit}" + "string": "Ų…Ų† {unit} {value}" }, "src_dot_components_dot_Weight_dot_2781622322": { "context": "weight", - "string": "{value} {ŲˆØ­Ø¯Ø§ØĒ}" + "string": "ØĨŲ„Ų‰ {unit} {value}" }, "src_dot_configuration": { "context": "configuration section name", @@ -1675,6 +1675,10 @@ "context": "button", "string": "Delete" }, + "src_dot_demo": { + "context": "notification message after log in", + "string": "Just to let you know... You're in demo mode. You can play around with the dashboard but can't save changes." + }, "src_dot_description": { "string": "Ø§Ų„ŲˆØĩ؁" }, @@ -2532,6 +2536,10 @@ "context": "cancelled fulfillment, section header", "string": "Cancelled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderFulfillment_dot_693960049": { + "context": "ordered product sku", + "string": "ŲˆØ­Ø¯ØŠ Ø­ŲØ¸ Ø§Ų„ØŖŲˆØąØ§Ų‚ Ø§Ų„Ų…Ø§Ų„ŲŠØŠ" + }, "src_dot_orders_dot_components_dot_OrderFulfillment_dot_732594284": { "context": "button", "string": "Cancel Fulfillment" @@ -2749,6 +2757,10 @@ "context": "order payment", "string": "Outstanding Balance" }, + "src_dot_orders_dot_components_dot_OrderPayment_dot_3720114122": { + "context": "order discount", + "string": "ØŽØĩŲ…" + }, "src_dot_orders_dot_components_dot_OrderPayment_dot_3768782744": { "context": "order payment", "string": "Preauthorized amount" @@ -2768,10 +2780,6 @@ "context": "order total price", "string": "Ø§Ų„Ų…ØŦŲ…ŲˆØš" }, - "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_1542417144": { - "context": "dialog header", - "string": "Create Product" - }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2272209368": { "context": "variant sku", "string": "SKU {sku}" @@ -2779,6 +2787,10 @@ "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2336947364": { "string": "Search by product name, attribute, product type etc..." }, + "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2775402904": { + "context": "dialog header", + "string": "Add Product" + }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2850255786": { "string": "Search Products" }, @@ -2809,6 +2821,10 @@ "context": "section header", "string": "Unfulfilled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_693960049": { + "context": "ordered product sku", + "string": "ŲˆØ­Ø¯ØŠ Ø­ŲØ¸ Ø§Ų„ØŖŲˆØąØ§Ų‚ Ø§Ų„Ų…Ø§Ų„ŲŠØŠ" + }, "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_878013594": { "context": "order line total price", "string": "Ø§Ų„Ų…ØŦŲ…ŲˆØš" @@ -2902,14 +2918,14 @@ }, "src_dot_pages_dot_components_dot_PageDetailsPage_dot_1815688500": { "context": "page", - "string": "since {date}" + "string": "Ų…Ų†Ø° {date}" }, "src_dot_pages_dot_components_dot_PageDetailsPage_dot_1996767833": { "string": "ØŖØļ؁ ØšŲ†ŲˆØ§Ų† Ų…Ø­ØąŲƒ Ø§Ų„Ø¨Ø­ØĢ ؈ ؈Øĩ؁؇ Ų„ØĒØŗŲ‡ŲŠŲ„ Ø§Ų„ØšØĢŲˆØą ØšŲ„Ų‰ Ų‡Ø°Ų‡ Ø§Ų„ØĩŲØ­ØŠ" }, "src_dot_pages_dot_components_dot_PageDetailsPage_dot_2001551496": { "context": "page", - "string": "will be visible from {date}" + "string": "ØŗØĒŲƒŲˆŲ† Ø¸Ø§Ų‡Øą Ų…Ų† {date}" }, "src_dot_pages_dot_components_dot_PageInfo_dot_1116746286": { "context": "page content", @@ -3460,11 +3476,11 @@ }, "src_dot_products_dot_components_dot_ProductCreatePage_dot_1815688500": { "context": "product", - "string": "since {date}" + "string": "Ų…Ų†Ø° {date}" }, "src_dot_products_dot_components_dot_ProductCreatePage_dot_2001551496": { "context": "product", - "string": "will be visible from {date}" + "string": "ØŗØĒŲƒŲˆŲ† Ø¸Ø§Ų‡Øą Ų…Ų† {date}" }, "src_dot_products_dot_components_dot_ProductCreatePage_dot_2706108815": { "string": "ØŖØļ؁ ØšŲ†ŲˆØ§Ų† Ų…Ø­ØąŲƒ Ø§Ų„Ø¨Ø­ØĢ ؈ ؈Øĩ؁؇ Ų„ØĒØŗŲ‡ŲŠŲ„ Ø§Ų„ØšØĢŲˆØą ØšŲ„Ų‰ Ų‡Ø°Ø§ Ø§Ų„Ų…Ų†ØĒØŦ" @@ -3522,7 +3538,7 @@ }, "src_dot_products_dot_components_dot_ProductListPage_dot_available": { "context": "product status", - "string": "Available" + "string": "Ų…ØĒŲˆŲØą" }, "src_dot_products_dot_components_dot_ProductListPage_dot_hidden": { "context": "product is hidden", @@ -3621,27 +3637,24 @@ "context": "header", "string": "ؚدد" }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3143542809": { - "string": "This product doesn't have any stock. You can add it here." - }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3482985373": { - "context": "button", - "string": "Edit Warehouses" - }, "src_dot_products_dot_components_dot_ProductStocks_dot_3633706025": { "context": "product inventory, checkbox", "string": "Track Inventory" }, + "src_dot_products_dot_components_dot_ProductStocks_dot_3857433664": { + "context": "button", + "string": "Assign Warehouse" + }, "src_dot_products_dot_components_dot_ProductStocks_dot_849869830": { "string": "Active inventory tracking will automatically calculate changes of stock" }, "src_dot_products_dot_components_dot_ProductUpdatePage_dot_1815688500": { "context": "product", - "string": "since {date}" + "string": "Ų…Ų†Ø° {date}" }, "src_dot_products_dot_components_dot_ProductUpdatePage_dot_2001551496": { "context": "product", - "string": "will be visible from {date}" + "string": "ØŗØĒŲƒŲˆŲ† Ø¸Ø§Ų‡Øą Ų…Ų† {date}" }, "src_dot_products_dot_components_dot_ProductUpdatePage_dot_2706108815": { "string": "ØŖØļ؁ ØšŲ†ŲˆØ§Ų† Ų…Ø­ØąŲƒ Ø§Ų„Ø¨Ø­ØĢ ؈ ؈Øĩ؁؇ Ų„ØĒØŗŲ‡ŲŠŲ„ Ø§Ų„ØšØĢŲˆØą ØšŲ„Ų‰ Ų‡Ø°Ø§ Ø§Ų„Ų…Ų†ØĒØŦ" @@ -3671,7 +3684,7 @@ }, "src_dot_products_dot_components_dot_ProductVariantCreatorPage_dot_168343345": { "context": "variant attribute", - "string": "Attribute" + "string": "Ų…ŲŠØ˛ØŠ" }, "src_dot_products_dot_components_dot_ProductVariantCreatorPage_dot_1808330403": { "context": "variant attribute", @@ -3859,13 +3872,6 @@ "context": "product variant name", "string": "Ų…ØĒØēŲŠØą" }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_3482985373": { - "context": "dialog header", - "string": "Edit Warehouses" - }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_4112406382": { - "string": "Select warehouses that stock selected product" - }, "src_dot_products_dot_views_dot_1542417144": { "context": "window title", "string": "Create Product" @@ -4083,7 +4089,7 @@ }, "src_dot_services_dot_components_dot_ServiceList_dot_3239722049": { "context": "account status", - "string": "inactive" + "string": "ØēŲŠØą ŲØšØ§Ų„" }, "src_dot_services_dot_components_dot_ServiceList_dot_636461959": { "context": "service name", @@ -4147,6 +4153,9 @@ "context": "window title", "string": "Create Service Account" }, + "src_dot_sessionExpired": { + "string": "Your session has expired. Please log in again to continue." + }, "src_dot_shipping": { "context": "shipping section name", "string": "Shipping Methods" diff --git a/locale/az.json b/locale/az.json index 16324901d..7e7f16b19 100644 --- a/locale/az.json +++ b/locale/az.json @@ -250,7 +250,7 @@ "context": "optional field", "string": "Optional" }, - "productVariantPriceOptionalPriceOverrideField": { + "productVariantPriceOptionalPriceField": { "context": "optional field", "string": "Optional" }, @@ -1675,6 +1675,10 @@ "context": "button", "string": "Delete" }, + "src_dot_demo": { + "context": "notification message after log in", + "string": "Just to let you know... You're in demo mode. You can play around with the dashboard but can't save changes." + }, "src_dot_description": { "string": "ƏtraflÄą məlumat" }, @@ -2532,6 +2536,10 @@ "context": "cancelled fulfillment, section header", "string": "Cancelled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderFulfillment_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderFulfillment_dot_732594284": { "context": "button", "string": "Cancel Fulfillment" @@ -2749,6 +2757,10 @@ "context": "order payment", "string": "Outstanding Balance" }, + "src_dot_orders_dot_components_dot_OrderPayment_dot_3720114122": { + "context": "order discount", + "string": "Discount" + }, "src_dot_orders_dot_components_dot_OrderPayment_dot_3768782744": { "context": "order payment", "string": "Preauthorized amount" @@ -2768,10 +2780,6 @@ "context": "order total price", "string": "Total" }, - "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_1542417144": { - "context": "dialog header", - "string": "Create Product" - }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2272209368": { "context": "variant sku", "string": "SKU {sku}" @@ -2779,6 +2787,10 @@ "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2336947364": { "string": "Search by product name, attribute, product type etc..." }, + "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2775402904": { + "context": "dialog header", + "string": "Add Product" + }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2850255786": { "string": "Search Products" }, @@ -2809,6 +2821,10 @@ "context": "section header", "string": "Unfulfilled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_878013594": { "context": "order line total price", "string": "Total" @@ -3621,17 +3637,14 @@ "context": "header", "string": "MiqdarÄą" }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3143542809": { - "string": "This product doesn't have any stock. You can add it here." - }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3482985373": { - "context": "button", - "string": "Edit Warehouses" - }, "src_dot_products_dot_components_dot_ProductStocks_dot_3633706025": { "context": "product inventory, checkbox", "string": "Track Inventory" }, + "src_dot_products_dot_components_dot_ProductStocks_dot_3857433664": { + "context": "button", + "string": "Assign Warehouse" + }, "src_dot_products_dot_components_dot_ProductStocks_dot_849869830": { "string": "Active inventory tracking will automatically calculate changes of stock" }, @@ -3859,13 +3872,6 @@ "context": "product variant name", "string": "Variant" }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_3482985373": { - "context": "dialog header", - "string": "Edit Warehouses" - }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_4112406382": { - "string": "Select warehouses that stock selected product" - }, "src_dot_products_dot_views_dot_1542417144": { "context": "window title", "string": "Create Product" @@ -4147,6 +4153,9 @@ "context": "window title", "string": "Create Service Account" }, + "src_dot_sessionExpired": { + "string": "Your session has expired. Please log in again to continue." + }, "src_dot_shipping": { "context": "shipping section name", "string": "Shipping Methods" diff --git a/locale/bg.json b/locale/bg.json index d7b5b95b4..f3fe78a64 100644 --- a/locale/bg.json +++ b/locale/bg.json @@ -250,7 +250,7 @@ "context": "optional field", "string": "Optional" }, - "productVariantPriceOptionalPriceOverrideField": { + "productVariantPriceOptionalPriceField": { "context": "optional field", "string": "Optional" }, @@ -1675,6 +1675,10 @@ "context": "button", "string": "Delete" }, + "src_dot_demo": { + "context": "notification message after log in", + "string": "Just to let you know... You're in demo mode. You can play around with the dashboard but can't save changes." + }, "src_dot_description": { "string": "ОĐŋĐ¸ŅĐ°ĐŊиĐĩ" }, @@ -2532,6 +2536,10 @@ "context": "cancelled fulfillment, section header", "string": "Cancelled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderFulfillment_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderFulfillment_dot_732594284": { "context": "button", "string": "Cancel Fulfillment" @@ -2749,6 +2757,10 @@ "context": "order payment", "string": "Outstanding Balance" }, + "src_dot_orders_dot_components_dot_OrderPayment_dot_3720114122": { + "context": "order discount", + "string": "ĐžŅ‚ŅŅ‚ŅŠĐŋĐēа" + }, "src_dot_orders_dot_components_dot_OrderPayment_dot_3768782744": { "context": "order payment", "string": "ĐĄŅƒĐąŅĐ¸Đ´Đ¸Ņ€Đ°ĐŊа ҁ҃Đŧа" @@ -2768,10 +2780,6 @@ "context": "order total price", "string": "ĐĸĐžŅ‚Đ°Đģ" }, - "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_1542417144": { - "context": "dialog header", - "string": "Create Product" - }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2272209368": { "context": "variant sku", "string": "SKU {sku}" @@ -2779,6 +2787,10 @@ "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2336947364": { "string": "Search by product name, attribute, product type etc..." }, + "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2775402904": { + "context": "dialog header", + "string": "Add Product" + }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2850255786": { "string": "Search Products" }, @@ -2809,6 +2821,10 @@ "context": "section header", "string": "Unfulfilled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_878013594": { "context": "order line total price", "string": "ĐĸĐžŅ‚Đ°Đģ" @@ -3621,17 +3637,14 @@ "context": "header", "string": "КоĐģĐ¸Ņ‡ĐĩŅŅ‚Đ˛Đž" }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3143542809": { - "string": "This product doesn't have any stock. You can add it here." - }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3482985373": { - "context": "button", - "string": "Edit Warehouses" - }, "src_dot_products_dot_components_dot_ProductStocks_dot_3633706025": { "context": "product inventory, checkbox", "string": "Track Inventory" }, + "src_dot_products_dot_components_dot_ProductStocks_dot_3857433664": { + "context": "button", + "string": "Assign Warehouse" + }, "src_dot_products_dot_components_dot_ProductStocks_dot_849869830": { "string": "Active inventory tracking will automatically calculate changes of stock" }, @@ -3859,13 +3872,6 @@ "context": "product variant name", "string": "Đ’Đ°Ņ€Đ¸Đ°ĐŊŅ‚" }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_3482985373": { - "context": "dialog header", - "string": "Edit Warehouses" - }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_4112406382": { - "string": "Select warehouses that stock selected product" - }, "src_dot_products_dot_views_dot_1542417144": { "context": "window title", "string": "Create Product" @@ -4147,6 +4153,9 @@ "context": "window title", "string": "Create Service Account" }, + "src_dot_sessionExpired": { + "string": "Your session has expired. Please log in again to continue." + }, "src_dot_shipping": { "context": "shipping section name", "string": "Shipping Methods" diff --git a/locale/bn.json b/locale/bn.json index bc6bd4948..8598dc63b 100644 --- a/locale/bn.json +++ b/locale/bn.json @@ -250,7 +250,7 @@ "context": "optional field", "string": "Optional" }, - "productVariantPriceOptionalPriceOverrideField": { + "productVariantPriceOptionalPriceField": { "context": "optional field", "string": "Optional" }, @@ -1675,6 +1675,10 @@ "context": "button", "string": "Delete" }, + "src_dot_demo": { + "context": "notification message after log in", + "string": "Just to let you know... You're in demo mode. You can play around with the dashboard but can't save changes." + }, "src_dot_description": { "string": "āĻŦāĻŋāĻŦāϰāĻŖ" }, @@ -2532,6 +2536,10 @@ "context": "cancelled fulfillment, section header", "string": "Cancelled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderFulfillment_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderFulfillment_dot_732594284": { "context": "button", "string": "Cancel Fulfillment" @@ -2749,6 +2757,10 @@ "context": "order payment", "string": "Outstanding Balance" }, + "src_dot_orders_dot_components_dot_OrderPayment_dot_3720114122": { + "context": "order discount", + "string": "Discount" + }, "src_dot_orders_dot_components_dot_OrderPayment_dot_3768782744": { "context": "order payment", "string": "Preauthorized amount" @@ -2768,10 +2780,6 @@ "context": "order total price", "string": "Total" }, - "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_1542417144": { - "context": "dialog header", - "string": "Create Product" - }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2272209368": { "context": "variant sku", "string": "SKU {sku}" @@ -2779,6 +2787,10 @@ "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2336947364": { "string": "Search by product name, attribute, product type etc..." }, + "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2775402904": { + "context": "dialog header", + "string": "Add Product" + }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2850255786": { "string": "Search Products" }, @@ -2809,6 +2821,10 @@ "context": "section header", "string": "Unfulfilled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_878013594": { "context": "order line total price", "string": "Total" @@ -3621,17 +3637,14 @@ "context": "header", "string": "āĻĒāϰāĻŋāĻŽāĻžāĻŖ" }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3143542809": { - "string": "This product doesn't have any stock. You can add it here." - }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3482985373": { - "context": "button", - "string": "Edit Warehouses" - }, "src_dot_products_dot_components_dot_ProductStocks_dot_3633706025": { "context": "product inventory, checkbox", "string": "Track Inventory" }, + "src_dot_products_dot_components_dot_ProductStocks_dot_3857433664": { + "context": "button", + "string": "Assign Warehouse" + }, "src_dot_products_dot_components_dot_ProductStocks_dot_849869830": { "string": "Active inventory tracking will automatically calculate changes of stock" }, @@ -3859,13 +3872,6 @@ "context": "product variant name", "string": "Variant" }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_3482985373": { - "context": "dialog header", - "string": "Edit Warehouses" - }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_4112406382": { - "string": "Select warehouses that stock selected product" - }, "src_dot_products_dot_views_dot_1542417144": { "context": "window title", "string": "Create Product" @@ -4147,6 +4153,9 @@ "context": "window title", "string": "Create Service Account" }, + "src_dot_sessionExpired": { + "string": "Your session has expired. Please log in again to continue." + }, "src_dot_shipping": { "context": "shipping section name", "string": "Shipping Methods" diff --git a/locale/ca.json b/locale/ca.json index f203728b1..26dcd7956 100644 --- a/locale/ca.json +++ b/locale/ca.json @@ -250,7 +250,7 @@ "context": "optional field", "string": "Optional" }, - "productVariantPriceOptionalPriceOverrideField": { + "productVariantPriceOptionalPriceField": { "context": "optional field", "string": "Optional" }, @@ -1675,6 +1675,10 @@ "context": "button", "string": "Delete" }, + "src_dot_demo": { + "context": "notification message after log in", + "string": "Just to let you know... You're in demo mode. You can play around with the dashboard but can't save changes." + }, "src_dot_description": { "string": "DescripciÃŗ" }, @@ -2532,6 +2536,10 @@ "context": "cancelled fulfillment, section header", "string": "Cancelled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderFulfillment_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderFulfillment_dot_732594284": { "context": "button", "string": "Cancel Fulfillment" @@ -2749,6 +2757,10 @@ "context": "order payment", "string": "Outstanding Balance" }, + "src_dot_orders_dot_components_dot_OrderPayment_dot_3720114122": { + "context": "order discount", + "string": "Descompte" + }, "src_dot_orders_dot_components_dot_OrderPayment_dot_3768782744": { "context": "order payment", "string": "Quantitat pre-autoritzada" @@ -2768,10 +2780,6 @@ "context": "order total price", "string": "Total" }, - "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_1542417144": { - "context": "dialog header", - "string": "Create Product" - }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2272209368": { "context": "variant sku", "string": "SKU {sku}" @@ -2779,6 +2787,10 @@ "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2336947364": { "string": "Search by product name, attribute, product type etc..." }, + "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2775402904": { + "context": "dialog header", + "string": "Add Product" + }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2850255786": { "string": "Search Products" }, @@ -2809,6 +2821,10 @@ "context": "section header", "string": "Unfulfilled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_878013594": { "context": "order line total price", "string": "Total" @@ -3621,17 +3637,14 @@ "context": "header", "string": "Quantitat" }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3143542809": { - "string": "This product doesn't have any stock. You can add it here." - }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3482985373": { - "context": "button", - "string": "Edit Warehouses" - }, "src_dot_products_dot_components_dot_ProductStocks_dot_3633706025": { "context": "product inventory, checkbox", "string": "Track Inventory" }, + "src_dot_products_dot_components_dot_ProductStocks_dot_3857433664": { + "context": "button", + "string": "Assign Warehouse" + }, "src_dot_products_dot_components_dot_ProductStocks_dot_849869830": { "string": "Active inventory tracking will automatically calculate changes of stock" }, @@ -3859,13 +3872,6 @@ "context": "product variant name", "string": "Variant" }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_3482985373": { - "context": "dialog header", - "string": "Edit Warehouses" - }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_4112406382": { - "string": "Select warehouses that stock selected product" - }, "src_dot_products_dot_views_dot_1542417144": { "context": "window title", "string": "Create Product" @@ -4147,6 +4153,9 @@ "context": "window title", "string": "Create Service Account" }, + "src_dot_sessionExpired": { + "string": "Your session has expired. Please log in again to continue." + }, "src_dot_shipping": { "context": "shipping section name", "string": "Shipping Methods" diff --git a/locale/cs.json b/locale/cs.json index 40d8ad92f..1a5e089f2 100644 --- a/locale/cs.json +++ b/locale/cs.json @@ -250,7 +250,7 @@ "context": "optional field", "string": "Optional" }, - "productVariantPriceOptionalPriceOverrideField": { + "productVariantPriceOptionalPriceField": { "context": "optional field", "string": "Optional" }, @@ -1675,6 +1675,10 @@ "context": "button", "string": "Delete" }, + "src_dot_demo": { + "context": "notification message after log in", + "string": "Just to let you know... You're in demo mode. You can play around with the dashboard but can't save changes." + }, "src_dot_description": { "string": "Popis" }, @@ -2532,6 +2536,10 @@ "context": "cancelled fulfillment, section header", "string": "Cancelled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderFulfillment_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderFulfillment_dot_732594284": { "context": "button", "string": "ZruÅĄit zpracovÃĄní" @@ -2749,6 +2757,10 @@ "context": "order payment", "string": "Outstanding Balance" }, + "src_dot_orders_dot_components_dot_OrderPayment_dot_3720114122": { + "context": "order discount", + "string": "Sleva" + }, "src_dot_orders_dot_components_dot_OrderPayment_dot_3768782744": { "context": "order payment", "string": "PauÅĄÃĄlní ÄÃĄstka" @@ -2768,10 +2780,6 @@ "context": "order total price", "string": "Celkem" }, - "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_1542417144": { - "context": "dialog header", - "string": "Create Product" - }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2272209368": { "context": "variant sku", "string": "SKU {sku}" @@ -2779,6 +2787,10 @@ "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2336947364": { "string": "Search by product name, attribute, product type etc..." }, + "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2775402904": { + "context": "dialog header", + "string": "Add Product" + }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2850255786": { "string": "Search Products" }, @@ -2809,6 +2821,10 @@ "context": "section header", "string": "Unfulfilled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_878013594": { "context": "order line total price", "string": "Celkem" @@ -3621,17 +3637,14 @@ "context": "header", "string": "MnoÅžství" }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3143542809": { - "string": "This product doesn't have any stock. You can add it here." - }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3482985373": { - "context": "button", - "string": "Edit Warehouses" - }, "src_dot_products_dot_components_dot_ProductStocks_dot_3633706025": { "context": "product inventory, checkbox", "string": "Track Inventory" }, + "src_dot_products_dot_components_dot_ProductStocks_dot_3857433664": { + "context": "button", + "string": "Assign Warehouse" + }, "src_dot_products_dot_components_dot_ProductStocks_dot_849869830": { "string": "Active inventory tracking will automatically calculate changes of stock" }, @@ -3859,13 +3872,6 @@ "context": "product variant name", "string": "Varianta" }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_3482985373": { - "context": "dialog header", - "string": "Edit Warehouses" - }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_4112406382": { - "string": "Select warehouses that stock selected product" - }, "src_dot_products_dot_views_dot_1542417144": { "context": "window title", "string": "Create Product" @@ -4147,6 +4153,9 @@ "context": "window title", "string": "Create Service Account" }, + "src_dot_sessionExpired": { + "string": "Your session has expired. Please log in again to continue." + }, "src_dot_shipping": { "context": "shipping section name", "string": "Shipping Methods" diff --git a/locale/da.json b/locale/da.json index f8501b365..81c0add82 100644 --- a/locale/da.json +++ b/locale/da.json @@ -250,7 +250,7 @@ "context": "optional field", "string": "Optional" }, - "productVariantPriceOptionalPriceOverrideField": { + "productVariantPriceOptionalPriceField": { "context": "optional field", "string": "Optional" }, @@ -1675,6 +1675,10 @@ "context": "button", "string": "Delete" }, + "src_dot_demo": { + "context": "notification message after log in", + "string": "Just to let you know... You're in demo mode. You can play around with the dashboard but can't save changes." + }, "src_dot_description": { "string": "Beskrivelse" }, @@ -2532,6 +2536,10 @@ "context": "cancelled fulfillment, section header", "string": "Cancelled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderFulfillment_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderFulfillment_dot_732594284": { "context": "button", "string": "Annuller pakning" @@ -2749,6 +2757,10 @@ "context": "order payment", "string": "Outstanding Balance" }, + "src_dot_orders_dot_components_dot_OrderPayment_dot_3720114122": { + "context": "order discount", + "string": "Rabat" + }, "src_dot_orders_dot_components_dot_OrderPayment_dot_3768782744": { "context": "order payment", "string": "Preautoriseret beløb" @@ -2768,10 +2780,6 @@ "context": "order total price", "string": "Total" }, - "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_1542417144": { - "context": "dialog header", - "string": "Create Product" - }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2272209368": { "context": "variant sku", "string": "SKU {sku}" @@ -2779,6 +2787,10 @@ "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2336947364": { "string": "Search by product name, attribute, product type etc..." }, + "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2775402904": { + "context": "dialog header", + "string": "Add Product" + }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2850255786": { "string": "Search Products" }, @@ -2809,6 +2821,10 @@ "context": "section header", "string": "Unfulfilled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_878013594": { "context": "order line total price", "string": "Total" @@ -3621,17 +3637,14 @@ "context": "header", "string": "Kvantitet" }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3143542809": { - "string": "This product doesn't have any stock. You can add it here." - }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3482985373": { - "context": "button", - "string": "Edit Warehouses" - }, "src_dot_products_dot_components_dot_ProductStocks_dot_3633706025": { "context": "product inventory, checkbox", "string": "Track Inventory" }, + "src_dot_products_dot_components_dot_ProductStocks_dot_3857433664": { + "context": "button", + "string": "Assign Warehouse" + }, "src_dot_products_dot_components_dot_ProductStocks_dot_849869830": { "string": "Active inventory tracking will automatically calculate changes of stock" }, @@ -3859,13 +3872,6 @@ "context": "product variant name", "string": "Variant" }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_3482985373": { - "context": "dialog header", - "string": "Edit Warehouses" - }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_4112406382": { - "string": "Select warehouses that stock selected product" - }, "src_dot_products_dot_views_dot_1542417144": { "context": "window title", "string": "Create Product" @@ -4147,6 +4153,9 @@ "context": "window title", "string": "Create Service Account" }, + "src_dot_sessionExpired": { + "string": "Your session has expired. Please log in again to continue." + }, "src_dot_shipping": { "context": "shipping section name", "string": "Shipping Methods" diff --git a/locale/de.json b/locale/de.json index 855fccecc..b74e76f13 100644 --- a/locale/de.json +++ b/locale/de.json @@ -250,7 +250,7 @@ "context": "optional field", "string": "Optional" }, - "productVariantPriceOptionalPriceOverrideField": { + "productVariantPriceOptionalPriceField": { "context": "optional field", "string": "Optional" }, @@ -1675,6 +1675,10 @@ "context": "button", "string": "LÃļschen" }, + "src_dot_demo": { + "context": "notification message after log in", + "string": "Just to let you know... You're in demo mode. You can play around with the dashboard but can't save changes." + }, "src_dot_description": { "string": "Beschreibung" }, @@ -2532,6 +2536,10 @@ "context": "cancelled fulfillment, section header", "string": "Cancelled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderFulfillment_dot_693960049": { + "context": "ordered product sku", + "string": "Artikelnummer" + }, "src_dot_orders_dot_components_dot_OrderFulfillment_dot_732594284": { "context": "button", "string": "Auftragsabwicklung abbrechen" @@ -2749,6 +2757,10 @@ "context": "order payment", "string": "Outstanding Balance" }, + "src_dot_orders_dot_components_dot_OrderPayment_dot_3720114122": { + "context": "order discount", + "string": "Rabatt" + }, "src_dot_orders_dot_components_dot_OrderPayment_dot_3768782744": { "context": "order payment", "string": "Autorisierter Betrag" @@ -2768,10 +2780,6 @@ "context": "order total price", "string": "Gesamtsumme" }, - "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_1542417144": { - "context": "dialog header", - "string": "Produkt erstellen" - }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2272209368": { "context": "variant sku", "string": "SKU {sku}" @@ -2779,6 +2787,10 @@ "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2336947364": { "string": "Search by product name, attribute, product type etc..." }, + "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2775402904": { + "context": "dialog header", + "string": "Add Product" + }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2850255786": { "string": "Search Products" }, @@ -2809,6 +2821,10 @@ "context": "section header", "string": "Unfulfilled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_693960049": { + "context": "ordered product sku", + "string": "Artikelnummer" + }, "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_878013594": { "context": "order line total price", "string": "Gesamtsumme" @@ -3621,17 +3637,14 @@ "context": "header", "string": "Menge" }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3143542809": { - "string": "This product doesn't have any stock. You can add it here." - }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3482985373": { - "context": "button", - "string": "Edit Warehouses" - }, "src_dot_products_dot_components_dot_ProductStocks_dot_3633706025": { "context": "product inventory, checkbox", "string": "Track Inventory" }, + "src_dot_products_dot_components_dot_ProductStocks_dot_3857433664": { + "context": "button", + "string": "Assign Warehouse" + }, "src_dot_products_dot_components_dot_ProductStocks_dot_849869830": { "string": "Active inventory tracking will automatically calculate changes of stock" }, @@ -3859,13 +3872,6 @@ "context": "product variant name", "string": "Variante" }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_3482985373": { - "context": "dialog header", - "string": "Edit Warehouses" - }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_4112406382": { - "string": "Select warehouses that stock selected product" - }, "src_dot_products_dot_views_dot_1542417144": { "context": "window title", "string": "Produkt erstellen" @@ -4147,6 +4153,9 @@ "context": "window title", "string": "Create Service Account" }, + "src_dot_sessionExpired": { + "string": "Your session has expired. Please log in again to continue." + }, "src_dot_shipping": { "context": "shipping section name", "string": "Shipping Methods" diff --git a/locale/defaultMessages.json b/locale/defaultMessages.json index c26dac2b1..105c9bf12 100644 --- a/locale/defaultMessages.json +++ b/locale/defaultMessages.json @@ -205,6 +205,66 @@ "context": "vat not included in order price", "string": "does not apply" }, + "productExportFieldAvailability": { + "context": "product field", + "string": "Available for purchase" + }, + "productExportFieldCategory": { + "context": "product field", + "string": "Category" + }, + "productExportFieldCollections": { + "context": "product field", + "string": "Collections" + }, + "productExportFieldDescription": { + "context": "product field", + "string": "Description" + }, + "productExportFieldName": { + "context": "product field", + "string": "Name" + }, + "productExportFieldPrice": { + "context": "product field", + "string": "Cost Price" + }, + "productExportFieldProductImages": { + "context": "product field", + "string": "Product Images" + }, + "productExportFieldProductWeight": { + "context": "product field", + "string": "Export Product Weight" + }, + "productExportFieldTaxes": { + "context": "product field", + "string": "Charge Taxes" + }, + "productExportFieldType": { + "context": "product field", + "string": "Type" + }, + "productExportFieldVariantImages": { + "context": "product field", + "string": "Variant Images" + }, + "productExportFieldVariantPrice": { + "context": "product field", + "string": "Variant Price" + }, + "productExportFieldVariantSku": { + "context": "product field", + "string": "Export Variant SKU" + }, + "productExportFieldVariantWeight": { + "context": "product field", + "string": "Export Variant Weight" + }, + "productExportFieldVisibility": { + "context": "product field", + "string": "Visibility" + }, "productStatusLabel": { "context": "product", "string": "Published" @@ -250,10 +310,6 @@ "context": "optional field", "string": "Optional" }, - "productVariantPriceOptionalPriceOverrideField": { - "context": "optional field", - "string": "Optional" - }, "saleDetailsPageCategoriesQuantity": { "context": "number of categories", "string": "Categories ({quantity})" @@ -298,6 +354,357 @@ "context": "button", "string": "Accept" }, + "src_dot_apps": { + "context": "apps section name", + "string": "Apps" + }, + "src_dot_apps_dot_components_dot_AppActivateDialog_dot_1499521723": { + "context": "dialog header", + "string": "Activate App" + }, + "src_dot_apps_dot_components_dot_AppActivateDialog_dot_3356885734": { + "context": "activate app", + "string": "Are you sure you want to activate {name}? Activating will start gathering events." + }, + "src_dot_apps_dot_components_dot_AppActivateDialog_dot_3761045983": { + "context": "activate app", + "string": "Are you sure you want to activate this app? Activating will start gathering events" + }, + "src_dot_apps_dot_components_dot_AppActivateDialog_dot_3865193889": { + "context": "button label", + "string": "Activate" + }, + "src_dot_apps_dot_components_dot_AppDeactivateDialog_dot_1782042241": { + "context": "button label", + "string": "Deactivate" + }, + "src_dot_apps_dot_components_dot_AppDeactivateDialog_dot_2031792590": { + "context": "dialog header", + "string": "Dectivate App" + }, + "src_dot_apps_dot_components_dot_AppDeactivateDialog_dot_2955925498": { + "context": "deactivate app", + "string": "Are you sure you want to disable this app? Your data will be kept until you reactivate the app. You will be still billed for the app." + }, + "src_dot_apps_dot_components_dot_AppDeactivateDialog_dot_329373780": { + "context": "deactivate app", + "string": "Are you sure you want to disable {name}? Your data will be kept until you reactivate the app. You will be still billed for the app." + }, + "src_dot_apps_dot_components_dot_AppDeleteDialog_dot_1347203024": { + "context": "delete custom app", + "string": "Deleting {name}, you will delete all the data and webhooks regarding this app. Are you sure you want to do that?" + }, + "src_dot_apps_dot_components_dot_AppDeleteDialog_dot_1462011531": { + "context": "dialog header", + "string": "Delete App" + }, + "src_dot_apps_dot_components_dot_AppDeleteDialog_dot_330001535": { + "context": "delete app", + "string": "Are you sure you want to delete this app?" + }, + "src_dot_apps_dot_components_dot_AppDeleteDialog_dot_3817179919": { + "context": "delete app", + "string": "Deleting {name}, you will remove installation of the app. If you are paying for app subscription, remember to unsubscribe from the app in Saleor Marketplace. Are you sure you want to delete the app?" + }, + "src_dot_apps_dot_components_dot_AppDetailsPage_dot_1782042241": { + "context": "link", + "string": "Deactivate" + }, + "src_dot_apps_dot_components_dot_AppDetailsPage_dot_2432433023": { + "context": "app privacy policy link", + "string": "View this app’s privacy policy" + }, + "src_dot_apps_dot_components_dot_AppDetailsPage_dot_2973480575": { + "context": "link", + "string": "Edit settings" + }, + "src_dot_apps_dot_components_dot_AppDetailsPage_dot_3744068622": { + "context": "section header", + "string": "Data privacy" + }, + "src_dot_apps_dot_components_dot_AppDetailsPage_dot_3768793197": { + "context": "link", + "string": "Get Support" + }, + "src_dot_apps_dot_components_dot_AppDetailsPage_dot_3817397882": { + "context": "button", + "string": "Open App" + }, + "src_dot_apps_dot_components_dot_AppDetailsPage_dot_3865193889": { + "context": "link", + "string": "Activate" + }, + "src_dot_apps_dot_components_dot_AppDetailsPage_dot_3916538164": { + "context": "section header", + "string": "App permissions" + }, + "src_dot_apps_dot_components_dot_AppDetailsPage_dot_846582072": { + "context": "apps about permissions", + "string": "This app has permissions to:" + }, + "src_dot_apps_dot_components_dot_AppDetailsPage_dot_85811128": { + "context": "section header", + "string": "About this app" + }, + "src_dot_apps_dot_components_dot_AppDetailsSettingsPage_dot_198187074": { + "context": "button", + "string": "Support/FAQ" + }, + "src_dot_apps_dot_components_dot_AppDetailsSettingsPage_dot_3302125406": { + "context": "button", + "string": "My App" + }, + "src_dot_apps_dot_components_dot_AppDetailsSettingsPage_dot_3662390044": { + "context": "button", + "string": "Dashboard" + }, + "src_dot_apps_dot_components_dot_AppInProgressDeleteDialog_dot_1462011531": { + "context": "dialog header", + "string": "Delete App" + }, + "src_dot_apps_dot_components_dot_AppInProgressDeleteDialog_dot_330001535": { + "context": "delete app", + "string": "Are you sure you want to delete this app?" + }, + "src_dot_apps_dot_components_dot_AppInProgressDeleteDialog_dot_3817179919": { + "context": "delete app", + "string": "Deleting {name}, you will remove installation of the app. If you are paying for app subscription, remember to unsubscribe from the app in Saleor Marketplace. Are you sure you want to delete the app?" + }, + "src_dot_apps_dot_components_dot_AppInstallErrorPage_dot_1152717819": { + "context": "title", + "string": "There’s a problem with app." + }, + "src_dot_apps_dot_components_dot_AppInstallErrorPage_dot_1261716527": { + "context": "content", + "string": "Saleor couldn’t fetch crucial information regarding installation. Without those System can’t install the app in your Saleor. Please use the button below to get back to system’s dashboard." + }, + "src_dot_apps_dot_components_dot_AppInstallErrorPage_dot_3375237564": { + "context": "button", + "string": "Back to homepage" + }, + "src_dot_apps_dot_components_dot_AppInstallPage_dot_127674832": { + "context": "app data privacy link", + "string": "Learn more about data privacy" + }, + "src_dot_apps_dot_components_dot_AppInstallPage_dot_2538706256": { + "context": "install button", + "string": "Install App" + }, + "src_dot_apps_dot_components_dot_AppInstallPage_dot_2936990163": { + "context": "install app permissions", + "string": "Installing this app will give it following permissions:" + }, + "src_dot_apps_dot_components_dot_AppInstallPage_dot_3436300370": { + "context": "install app privacy", + "string": "Uninstalling the app will remove all your customer’s personal data stored by {name}. " + }, + "src_dot_apps_dot_components_dot_AppInstallPage_dot_3688014441": { + "context": "section header", + "string": "You are about to install {name}" + }, + "src_dot_apps_dot_components_dot_AppInstallPage_dot_3916538164": { + "context": "section header", + "string": "App permissions" + }, + "src_dot_apps_dot_components_dot_AppsInProgress_dot_1675189051": { + "context": "section header", + "string": "Ongoing Installations" + }, + "src_dot_apps_dot_components_dot_AppsInProgress_dot_2398081356": { + "context": "retry installation", + "string": "Retry" + }, + "src_dot_apps_dot_components_dot_AppsInProgress_dot_2868351060": { + "context": "app installation error", + "string": "There was a problem during installation" + }, + "src_dot_apps_dot_components_dot_AppsInProgress_dot_3733091754": { + "context": "app installation", + "string": "Installing app..." + }, + "src_dot_apps_dot_components_dot_CustomAppCreatePage_dot_1414896555": { + "context": "checkbox label", + "string": "Grant this app full access to the store" + }, + "src_dot_apps_dot_components_dot_CustomAppCreatePage_dot_3076071936": { + "context": "card description", + "string": "Expand or restrict app permissions to access certain part of Saleor system." + }, + "src_dot_apps_dot_components_dot_CustomAppCreatePage_dot_3189779214": { + "context": "header", + "string": "Create New App" + }, + "src_dot_apps_dot_components_dot_CustomAppCreatePage_dot_570656367": { + "context": "checkbox label", + "string": "App is active" + }, + "src_dot_apps_dot_components_dot_CustomAppDefaultToken_dot_1336855942": { + "string": "Generated Token" + }, + "src_dot_apps_dot_components_dot_CustomAppDefaultToken_dot_2080322626": { + "string": "This token gives you access to your shop's API, which you'll find here: {url}" + }, + "src_dot_apps_dot_components_dot_CustomAppDefaultToken_dot_2864204643": { + "context": "button", + "string": "Copied" + }, + "src_dot_apps_dot_components_dot_CustomAppDefaultToken_dot_3406541221": { + "context": "button", + "string": "Copy token" + }, + "src_dot_apps_dot_components_dot_CustomAppDefaultToken_dot_4189999598": { + "string": "We’ve created your default token. Make sure to copy your new personal access token now. You won’t be able to see it again." + }, + "src_dot_apps_dot_components_dot_CustomAppDetailsPage_dot_1414896555": { + "context": "checkbox label", + "string": "Grant this app full access to the store" + }, + "src_dot_apps_dot_components_dot_CustomAppDetailsPage_dot_3076071936": { + "context": "card description", + "string": "Expand or restrict app permissions to access certain part of Saleor system." + }, + "src_dot_apps_dot_components_dot_CustomAppDetailsPage_dot_570656367": { + "context": "checkbox label", + "string": "App is active" + }, + "src_dot_apps_dot_components_dot_CustomAppInformation_dot_2860466085": { + "context": "header", + "string": "App Information" + }, + "src_dot_apps_dot_components_dot_CustomAppInformation_dot_3001692357": { + "context": "custom app name", + "string": "App Name" + }, + "src_dot_apps_dot_components_dot_CustomAppTokens_dot_2446088470": { + "context": "custom app token key", + "string": "Key" + }, + "src_dot_apps_dot_components_dot_CustomAppTokens_dot_2639089057": { + "string": "No tokens found" + }, + "src_dot_apps_dot_components_dot_CustomAppTokens_dot_3209034045": { + "context": "header", + "string": "Tokens" + }, + "src_dot_apps_dot_components_dot_CustomAppTokens_dot_3875340101": { + "context": "button", + "string": "Create Token" + }, + "src_dot_apps_dot_components_dot_CustomAppTokens_dot_4017491013": { + "string": "Token Note" + }, + "src_dot_apps_dot_components_dot_CustomAppTokens_dot_4190792473": { + "context": "table actions", + "string": "Actions" + }, + "src_dot_apps_dot_components_dot_CustomApps_dot_3152347892": { + "context": "custom apps content", + "string": "Your custom created apps will be shown here." + }, + "src_dot_apps_dot_components_dot_CustomApps_dot_3230241731": { + "context": "create app button", + "string": "Create App" + }, + "src_dot_apps_dot_components_dot_DeactivatedText_dot_3064552173": { + "context": "app deactivated", + "string": "Deactivated" + }, + "src_dot_apps_dot_components_dot_InstalledApps_dot_1636202177": { + "context": "about app", + "string": "About" + }, + "src_dot_apps_dot_components_dot_InstalledApps_dot_186286611": { + "context": "apps content", + "string": "You don’t have any installed apps in your dashboard" + }, + "src_dot_apps_dot_components_dot_InstalledApps_dot_3504763431": { + "context": "section header", + "string": "Third-party Apps" + }, + "src_dot_apps_dot_components_dot_Marketplace_dot_2932910073": { + "context": "section header", + "string": "Saleor Marketplace" + }, + "src_dot_apps_dot_components_dot_Marketplace_dot_3259214524": { + "context": "marketplace content", + "string": "Marketplace is coming soon" + }, + "src_dot_apps_dot_components_dot_Marketplace_dot_3910026447": { + "context": "marketplace button", + "string": "Visit Marketplace" + }, + "src_dot_apps_dot_components_dot_Marketplace_dot_52985091": { + "context": "marketplace content", + "string": "Discover great free and paid apps in our Saleor Marketplace." + }, + "src_dot_apps_dot_components_dot_TokenCreateDialog_dot_1336855942": { + "string": "Generated Token" + }, + "src_dot_apps_dot_components_dot_TokenCreateDialog_dot_2530792168": { + "string": "Access token is used to authenticate service accounts" + }, + "src_dot_apps_dot_components_dot_TokenCreateDialog_dot_3009959880": { + "string": "We’ve created your token. Make sure to copy your new personal access token now. You won’t be able to see it again." + }, + "src_dot_apps_dot_components_dot_TokenCreateDialog_dot_3406541221": { + "context": "button", + "string": "Copy token" + }, + "src_dot_apps_dot_components_dot_TokenCreateDialog_dot_3875340101": { + "context": "header", + "string": "Create Token" + }, + "src_dot_apps_dot_components_dot_TokenCreateDialog_dot_4017491013": { + "string": "Token Note" + }, + "src_dot_apps_dot_components_dot_TokenCreateDialog_dot_4120989039": { + "context": "create service token, button", + "string": "Create" + }, + "src_dot_apps_dot_components_dot_TokenDeleteDialog_dot_2164262076": { + "context": "dialog title", + "string": "Delete Token" + }, + "src_dot_apps_dot_components_dot_TokenDeleteDialog_dot_981802752": { + "context": "delete token", + "string": "Are you sure you want to delete token {token}?" + }, + "src_dot_apps_dot_views_dot_AppDetailsSettings_dot_2140018198": { + "context": "app settings error", + "string": "Failed to fetch app settings" + }, + "src_dot_apps_dot_views_dot_AppDetails_dot_2021043385": { + "context": "snackbar text", + "string": "App activated" + }, + "src_dot_apps_dot_views_dot_AppDetails_dot_3791371350": { + "context": "snackbar text", + "string": "App deactivated" + }, + "src_dot_apps_dot_views_dot_AppInstall_dot_2538706256": { + "context": "window title", + "string": "Install App" + }, + "src_dot_apps_dot_views_dot_AppsList_dot_1180774955": { + "context": "app has been installed", + "string": "{name} is ready to be used" + }, + "src_dot_apps_dot_views_dot_AppsList_dot_3076215778": { + "context": "app has been removed", + "string": "App successfully removed" + }, + "src_dot_apps_dot_views_dot_AppsList_dot_539268521": { + "context": "message title", + "string": "Couldn’t Install {name}" + }, + "src_dot_apps_dot_views_dot_AppsList_dot_966773578": { + "context": "message title", + "string": "App installed" + }, + "src_dot_apps_dot_views_dot_CustomAppCreate_dot_3230241731": { + "context": "window title", + "string": "Create App" + }, "src_dot_attributes": { "context": "attributes section name", "string": "Attributes" @@ -708,6 +1115,9 @@ "context": "dialog title", "string": "Delete products" }, + "src_dot_categories_dot_views_dot_3296953393": { + "string": "Remember this will also unpin all products assigned to this category, making them unavailable in storefront." + }, "src_dot_categories_dot_views_dot_3488150607": { "string": "Remember this will also delete all products assigned to this category." }, @@ -736,14 +1146,18 @@ "context": "collections section name", "string": "Collections" }, - "src_dot_collections_dot_components_dot_CollectionCreatePage_dot_1815688500": { - "context": "collection", - "string": "since {date}" - }, "src_dot_collections_dot_components_dot_CollectionCreatePage_dot_2001551496": { "context": "collection", "string": "will be visible from {date}" }, + "src_dot_collections_dot_components_dot_CollectionCreatePage_dot_643174786": { + "context": "collection label", + "string": "Visible" + }, + "src_dot_collections_dot_components_dot_CollectionCreatePage_dot_77815154": { + "context": "collection label", + "string": "Hidden" + }, "src_dot_collections_dot_components_dot_CollectionCreatePage_dot_946315389": { "string": "Add search engine title and description to make this collection easier to find" }, @@ -751,10 +1165,6 @@ "context": "page header", "string": "Add Collection" }, - "src_dot_collections_dot_components_dot_CollectionDetailsPage_dot_1815688500": { - "context": "collection", - "string": "since {date}" - }, "src_dot_collections_dot_components_dot_CollectionDetailsPage_dot_2001551496": { "context": "collection", "string": "will be visible from {date}" @@ -763,6 +1173,14 @@ "context": "switch button", "string": "Feature on Homepage" }, + "src_dot_collections_dot_components_dot_CollectionDetailsPage_dot_643174786": { + "context": "collection label", + "string": "Visible" + }, + "src_dot_collections_dot_components_dot_CollectionDetailsPage_dot_77815154": { + "context": "collection label", + "string": "Hidden" + }, "src_dot_collections_dot_components_dot_CollectionDetailsPage_dot_946315389": { "string": "Add search engine title and description to make this collection easier to find" }, @@ -931,13 +1349,6 @@ "context": "permission list item description", "string": "This group is last source of that permission" }, - "src_dot_components_dot_AccountStatus_dot_2183517419": { - "context": "section header", - "string": "Account Status" - }, - "src_dot_components_dot_AccountStatus_dot_2683780981": { - "string": "If you want to disable this account uncheck the box below" - }, "src_dot_components_dot_AddressEdit_dot_1139500589": { "string": "Country" }, @@ -962,13 +1373,12 @@ "src_dot_components_dot_AddressEdit_dot_944851093": { "string": "Country area" }, - "src_dot_components_dot_AppLayout_dot_21332146": { - "context": "button", - "string": "Log out" + "src_dot_components_dot_AppStatus_dot_1624959454": { + "string": "If you want to disable this App please uncheck the box below." }, - "src_dot_components_dot_AppLayout_dot_248888005": { - "context": "button", - "string": "Account Settings" + "src_dot_components_dot_AppStatus_dot_1750277107": { + "context": "section header", + "string": "App Status" }, "src_dot_components_dot_AssignCategoryDialog_dot_1305061437": { "string": "Search Categories" @@ -1015,6 +1425,22 @@ "src_dot_components_dot_AutocompleteSelectMenu_dot_2332404293": { "string": "No results" }, + "src_dot_components_dot_AvailabilityCard_dot_1306298759": { + "context": "product availability", + "string": "Available for purchase" + }, + "src_dot_components_dot_AvailabilityCard_dot_2938074852": { + "context": "product available for purchase date", + "string": "will become available on {date}" + }, + "src_dot_components_dot_AvailabilityCard_dot_570524410": { + "context": "product availability date label", + "string": "Set availability date" + }, + "src_dot_components_dot_AvailabilityCard_dot_825317195": { + "context": "product unavailability", + "string": "Unavailable for purchase" + }, "src_dot_components_dot_ColumnPicker_dot_1483881697": { "context": "button", "string": "Reset" @@ -1143,6 +1569,46 @@ "context": "button", "string": "Add" }, + "src_dot_components_dot_Metadata_dot_1148029984": { + "context": "metadata field value, header", + "string": "Value" + }, + "src_dot_components_dot_Metadata_dot_1509432322": { + "context": "header", + "string": "Metadata" + }, + "src_dot_components_dot_Metadata_dot_1535223586": { + "context": "header", + "string": "Private Metadata" + }, + "src_dot_components_dot_Metadata_dot_2024779015": { + "context": "empty metadata text", + "string": "There is no private metadata created for this element." + }, + "src_dot_components_dot_Metadata_dot_2087058956": { + "context": "empty metadata text", + "string": "There is no metadata created for this element." + }, + "src_dot_components_dot_Metadata_dot_2537046678": { + "context": "metadata field name, header", + "string": "Field" + }, + "src_dot_components_dot_Metadata_dot_3181473584": { + "context": "add metadata field,button", + "string": "Add Field" + }, + "src_dot_components_dot_Metadata_dot_4190792473": { + "context": "table action", + "string": "Actions" + }, + "src_dot_components_dot_Metadata_dot_549104951": { + "context": "number of metadata fields in model", + "string": "{number,plural,one{{number} Field} other{{number} Fields}}" + }, + "src_dot_components_dot_Metadata_dot_553451245": { + "context": "empty metadata text", + "string": "Use the button below to add new metadata field" + }, "src_dot_components_dot_MoneyRange_dot_12301532": { "context": "money", "string": "to {money}" @@ -1165,6 +1631,9 @@ "src_dot_components_dot_MultiSelectField_dot_4205644805": { "string": "No results found" }, + "src_dot_components_dot_NavigatorButton_dot_154826674": { + "string": "Navigator" + }, "src_dot_components_dot_Navigator_dot_1116468870": { "context": "navigator placeholder", "string": "Order Number" @@ -1387,23 +1856,39 @@ "src_dot_components_dot_Timeline_dot_3028189627": { "string": "Leave your note here..." }, + "src_dot_components_dot_UserChip_dot_21332146": { + "context": "button", + "string": "Log out" + }, + "src_dot_components_dot_UserChip_dot_248888005": { + "context": "button", + "string": "Account Settings" + }, + "src_dot_components_dot_VisibilityCard_dot_1311467573": { + "string": "Show in product listings" + }, "src_dot_components_dot_VisibilityCard_dot_1459686496": { "context": "section header", "string": "Visibility" }, + "src_dot_components_dot_VisibilityCard_dot_1815688500": { + "context": "date", + "string": "since {date}" + }, "src_dot_components_dot_VisibilityCard_dot_2060790769": { "context": "publish on date", "string": "Publish on" }, + "src_dot_components_dot_VisibilityCard_dot_2264302389": { + "string": "Disabling this checkbox will remove product from search and category pages. It will be available on collection pages." + }, + "src_dot_components_dot_VisibilityCard_dot_2699516026": { + "context": "available on date", + "string": "Set available on" + }, "src_dot_components_dot_VisibilityCard_dot_292404896": { "string": "Set publication date" }, - "src_dot_components_dot_VisibilityCard_dot_643174786": { - "string": "Visible" - }, - "src_dot_components_dot_VisibilityCard_dot_77815154": { - "string": "Hidden" - }, "src_dot_components_dot_WeightRange_dot_264731940": { "context": "weight", "string": "to {value} {unit}" @@ -1420,6 +1905,18 @@ "context": "weight", "string": "{value} {unit}" }, + "src_dot_components_dot_messages_dot_1219076963": { + "context": "snackbar expand", + "string": "Expand" + }, + "src_dot_components_dot_messages_dot_2473863536": { + "context": "snackbar button undo", + "string": "Undo" + }, + "src_dot_components_dot_messages_dot_3444275093": { + "context": "snackbar collapse", + "string": "Collapse" + }, "src_dot_configuration": { "context": "configuration section name", "string": "Configuration" @@ -1430,14 +1927,8 @@ "src_dot_configuration_dot_1440737903": { "string": "Shipping Settings" }, - "src_dot_configuration_dot_1639245766": { - "string": "View and update your webhook and their settings" - }, - "src_dot_configuration_dot_2326418019": { - "string": "Attributes and Product Typess" - }, - "src_dot_configuration_dot_2387898569": { - "string": "Manage external integrations accounts" + "src_dot_configuration_dot_1742602794": { + "string": "Attributes and Product Types" }, "src_dot_configuration_dot_3140151600": { "string": "Staff Settings" @@ -1449,10 +1940,34 @@ "context": "button", "string": "Confirm" }, + "src_dot_containers_dot_BackgroundTasks_dot_exportFailedTitle": { + "string": "Product Export Failed" + }, + "src_dot_containers_dot_BackgroundTasks_dot_exportFinishedText": { + "string": "Product export has finished and was sent to your email address." + }, + "src_dot_containers_dot_BackgroundTasks_dot_exportFinishedTitle": { + "context": "csv file exporting has finished, header", + "string": "Exporting CSV finished" + }, + "src_dot_containers_dot_BackgroundTasks_dot_invoiceGenerateFinishedText": { + "string": "Requested Invoice was generated. It was added to the top of the invoice list on this view. Enjoy!" + }, + "src_dot_containers_dot_BackgroundTasks_dot_invoiceGenerateFinishedTitle": { + "context": "invoice generating has finished, header", + "string": "Invoice Generated" + }, + "src_dot_containers_dot_BackgroundTasks_dot_invoiceGenerationFailedTitle": { + "context": "dialog header, title", + "string": "Invoice Generation" + }, "src_dot_create": { "context": "button", "string": "Create" }, + "src_dot_customApps": { + "string": "Local Apps" + }, "src_dot_customers": { "context": "customers section name", "string": "Customers" @@ -1675,6 +2190,10 @@ "context": "button", "string": "Delete" }, + "src_dot_demo": { + "context": "notification message after log in", + "string": "Just to let you know... You're in demo mode. You can play around with the dashboard but can't save changes." + }, "src_dot_description": { "string": "Description" }, @@ -2200,11 +2719,14 @@ }, "src_dot_home": { "context": "home section name", - "string": "Home" + "string": "Dashboard" }, "src_dot_home_dot_components_dot_HomeActivityCard_dot_draft": { "string": "Order #{orderId} was placed from draft by {userEmail}" }, + "src_dot_home_dot_components_dot_HomeActivityCard_dot_draft_no_email": { + "string": "Order #{orderId} was placed from draft" + }, "src_dot_home_dot_components_dot_HomeActivityCard_dot_paid": { "string": "Order #{orderId} was fully paid" }, @@ -2222,6 +2744,10 @@ "context": "navigation section name", "string": "Navigation" }, + "src_dot_nextStep": { + "context": "go to next step, button", + "string": "Next" + }, "src_dot_no": { "string": "No" }, @@ -2315,13 +2841,22 @@ "src_dot_orders_dot_components_dot_OrderDraftDetailsProducts_dot_1895667608": { "string": "Product" }, + "src_dot_orders_dot_components_dot_OrderDraftDetailsProducts_dot_270371448": { + "string": "Product is out of stock" + }, "src_dot_orders_dot_components_dot_OrderDraftDetailsProducts_dot_2796503714": { "context": "quantity of ordered products", "string": "Quantity" }, + "src_dot_orders_dot_components_dot_OrderDraftDetailsProducts_dot_2963336581": { + "string": "Product is unavailable to purchase" + }, "src_dot_orders_dot_components_dot_OrderDraftDetailsProducts_dot_546865199": { "string": "No Products added to Order" }, + "src_dot_orders_dot_components_dot_OrderDraftDetailsProducts_dot_59548500": { + "string": "Product is hidden" + }, "src_dot_orders_dot_components_dot_OrderDraftDetailsProducts_dot_878013594": { "context": "total price of ordered products", "string": "Total" @@ -2517,6 +3052,10 @@ "context": "product name", "string": "Product" }, + "src_dot_orders_dot_components_dot_OrderFulfillment_dot_2211099657": { + "context": "fulfillment group tracking number", + "string": "Edit tracking" + }, "src_dot_orders_dot_components_dot_OrderFulfillment_dot_2796503714": { "context": "ordered product quantity", "string": "Quantity" @@ -2532,6 +3071,10 @@ "context": "cancelled fulfillment, section header", "string": "Cancelled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderFulfillment_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderFulfillment_dot_732594284": { "context": "button", "string": "Cancel Fulfillment" @@ -2584,6 +3127,10 @@ "context": "order history message", "string": "Order confirmation was sent to customer" }, + "src_dot_orders_dot_components_dot_OrderHistory_dot_2421636085": { + "context": "order history message", + "string": "Invoice was requested by {requestedBy}" + }, "src_dot_orders_dot_components_dot_OrderHistory_dot_2566971846": { "context": "order history message", "string": "Payment was voided" @@ -2604,6 +3151,10 @@ "context": "order history message", "string": "Draft order was created" }, + "src_dot_orders_dot_components_dot_OrderHistory_dot_3237374063": { + "context": "order history message", + "string": "Payment was authorized" + }, "src_dot_orders_dot_components_dot_OrderHistory_dot_3328124376": { "context": "order history message", "string": "Marked order as paid" @@ -2620,6 +3171,10 @@ "context": "order history message", "string": "Products were added to draft order" }, + "src_dot_orders_dot_components_dot_OrderHistory_dot_393045022": { + "context": "order history message", + "string": "Invoice no. {invoiceNumber} was updated" + }, "src_dot_orders_dot_components_dot_OrderHistory_dot_3990160018": { "string": "Order History" }, @@ -2631,6 +3186,10 @@ "context": "order history message", "string": "Products were deleted from draft order" }, + "src_dot_orders_dot_components_dot_OrderHistory_dot_4121987561": { + "context": "order history message", + "string": "Order refund information was sent to customer" + }, "src_dot_orders_dot_components_dot_OrderHistory_dot_4265697648": { "context": "order history message", "string": "Updated fulfillment group's tracking number" @@ -2639,14 +3198,52 @@ "context": "order history message", "string": "Payment failed" }, + "src_dot_orders_dot_components_dot_OrderHistory_dot_493321552": { + "context": "order history message", + "string": "Order cancel information was sent to customer" + }, "src_dot_orders_dot_components_dot_OrderHistory_dot_651019008": { "context": "order history message", "string": "Shipping details was sent to customer" }, + "src_dot_orders_dot_components_dot_OrderHistory_dot_748112244": { + "context": "order history message", + "string": "Invoice no. {invoiceNumber} was generated by {generatedBy}" + }, + "src_dot_orders_dot_components_dot_OrderHistory_dot_88351908": { + "context": "order history message", + "string": "Invoice was sent to customer by {sentBy}" + }, "src_dot_orders_dot_components_dot_OrderHistory_dot_950782935": { "context": "order history message", "string": "Order was cancelled" }, + "src_dot_orders_dot_components_dot_OrderInvoiceEmailSendDialog_dot_1821123638": { + "string": "Are you sure you want to send this invoice: {invoiceNumber} to the customer?" + }, + "src_dot_orders_dot_components_dot_OrderInvoiceEmailSendDialog_dot_2166306944": { + "context": "dialog header", + "string": "Send Invoice" + }, + "src_dot_orders_dot_components_dot_OrderInvoiceList_dot_24460204": { + "context": "section header", + "string": "Invoices" + }, + "src_dot_orders_dot_components_dot_OrderInvoiceList_dot_2739475235": { + "context": "invoice create date prefix", + "string": "created" + }, + "src_dot_orders_dot_components_dot_OrderInvoiceList_dot_3340654960": { + "string": "No invoices to be shown" + }, + "src_dot_orders_dot_components_dot_OrderInvoiceList_dot_3589949197": { + "context": "invoice number prefix", + "string": "Invoice" + }, + "src_dot_orders_dot_components_dot_OrderInvoiceList_dot_949234851": { + "context": "generate invoice button", + "string": "Generate" + }, "src_dot_orders_dot_components_dot_OrderListPage_dot_2826235371": { "context": "button", "string": "Create order" @@ -2749,6 +3346,10 @@ "context": "order payment", "string": "Outstanding Balance" }, + "src_dot_orders_dot_components_dot_OrderPayment_dot_3720114122": { + "context": "order discount", + "string": "Discount" + }, "src_dot_orders_dot_components_dot_OrderPayment_dot_3768782744": { "context": "order payment", "string": "Preauthorized amount" @@ -2809,10 +3410,17 @@ "context": "section header", "string": "Unfulfilled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_878013594": { "context": "order line total price", "string": "Total" }, + "src_dot_orders_dot_views_dot_OrderDetails_dot_1039259580": { + "string": "We’re generating the invoice you requested. Please wait a couple of moments" + }, "src_dot_orders_dot_views_dot_OrderDetails_dot_1056718390": { "string": "Payment successfully captured" }, @@ -2846,6 +3454,12 @@ "src_dot_orders_dot_views_dot_OrderDetails_dot_3367579693": { "string": "Order successfully updated" }, + "src_dot_orders_dot_views_dot_OrderDetails_dot_4085755992": { + "string": "Invoice email sent" + }, + "src_dot_orders_dot_views_dot_OrderDetails_dot_55607988": { + "string": "Invoice is Generating" + }, "src_dot_orders_dot_views_dot_OrderDetails_dot_580490159": { "context": "window title", "string": "Order #{orderNumber}" @@ -2900,10 +3514,6 @@ "context": "page header", "string": "Create Page" }, - "src_dot_pages_dot_components_dot_PageDetailsPage_dot_1815688500": { - "context": "page", - "string": "since {date}" - }, "src_dot_pages_dot_components_dot_PageDetailsPage_dot_1996767833": { "string": "Add search engine title and description to make this page easier to find" }, @@ -2911,6 +3521,14 @@ "context": "page", "string": "will be visible from {date}" }, + "src_dot_pages_dot_components_dot_PageDetailsPage_dot_643174786": { + "context": "page label", + "string": "Visible" + }, + "src_dot_pages_dot_components_dot_PageDetailsPage_dot_77815154": { + "context": "page label", + "string": "Hidden" + }, "src_dot_pages_dot_components_dot_PageInfo_dot_1116746286": { "context": "page content", "string": "Content" @@ -3219,9 +3837,6 @@ "src_dot_plugins_dot_components_dot_PluginsDetailsPage_dot_3799756739": { "string": "These are general information about your store. They define what is the URL of your store and what is shown in browsers taskbar." }, - "src_dot_plugins_dot_components_dot_PluginsDetailsPage_dot_4241018152": { - "string": "This adress will be used to generate invoices and calculate shipping rates. Email adress you provide here will be used as a contact adress for your customers." - }, "src_dot_plugins_dot_components_dot_PluginsListPage_dot_3233248823": { "string": "Search Plugins..." }, @@ -3280,12 +3895,6 @@ "src_dot_productTypes_dot_components_dot_AssignAttributeDialog_dot_902296540": { "string": "Search Attributes" }, - "src_dot_productTypes_dot_components_dot_ProductTypeAttributeEditDialog_dot_1228425832": { - "string": "Attribute name" - }, - "src_dot_productTypes_dot_components_dot_ProductTypeAttributeEditDialog_dot_335542212": { - "string": "Attribute values" - }, "src_dot_productTypes_dot_components_dot_ProductTypeAttributeUnassignDialog_dot_404238501": { "context": "dialog header", "string": "Unassign Attribute From Product Type" @@ -3458,21 +4067,119 @@ "context": "product organization, header", "string": "Organization" }, - "src_dot_products_dot_components_dot_ProductCreatePage_dot_1815688500": { - "context": "product", - "string": "since {date}" + "src_dot_products_dot_components_dot_ProductCreatePage_dot_2232321263": { + "context": "product publication date label", + "string": "will become published on {date}" }, - "src_dot_products_dot_components_dot_ProductCreatePage_dot_2001551496": { - "context": "product", - "string": "will be visible from {date}" + "src_dot_products_dot_components_dot_ProductCreatePage_dot_2341910657": { + "context": "product label", + "string": "Not published" }, "src_dot_products_dot_components_dot_ProductCreatePage_dot_2706108815": { "string": "Add search engine title and description to make this product easier to find" }, + "src_dot_products_dot_components_dot_ProductCreatePage_dot_3640454975": { + "context": "product label", + "string": "Published" + }, "src_dot_products_dot_components_dot_ProductDetailsForm_dot_636461959": { "context": "product name", "string": "Name" }, + "src_dot_products_dot_components_dot_ProductExportDialog_dot_1004476569": { + "context": "option", + "string": "Export stock for all warehouses" + }, + "src_dot_products_dot_components_dot_ProductExportDialog_dot_108342258": { + "context": "button", + "string": "Load More" + }, + "src_dot_products_dot_components_dot_ProductExportDialog_dot_1547327218": { + "context": "there are more elements of list that are hidden", + "string": "and {number} more" + }, + "src_dot_products_dot_components_dot_ProductExportDialog_dot_1890035856": { + "context": "informations about product organization, header", + "string": "Product Organization" + }, + "src_dot_products_dot_components_dot_ProductExportDialog_dot_2119710854": { + "context": "informations about product seo, header", + "string": "SEO Information" + }, + "src_dot_products_dot_components_dot_ProductExportDialog_dot_2167661409": { + "context": "export selected products to csv file", + "string": "Selected products ({number})" + }, + "src_dot_products_dot_components_dot_ProductExportDialog_dot_2318723509": { + "context": "export products to csv file, choice field label", + "string": "Export information for:" + }, + "src_dot_products_dot_components_dot_ProductExportDialog_dot_2355065897": { + "context": "export all products to csv file", + "string": "All products ({number})" + }, + "src_dot_products_dot_components_dot_ProductExportDialog_dot_2474350154": { + "context": "list of warehouses", + "string": "Warehouses A to Z" + }, + "src_dot_products_dot_components_dot_ProductExportDialog_dot_2659464408": { + "context": "product export to csv file, header", + "string": "Information exported" + }, + "src_dot_products_dot_components_dot_ProductExportDialog_dot_2693217446": { + "context": "export products as csv or spreadsheet file", + "string": "Export as:" + }, + "src_dot_products_dot_components_dot_ProductExportDialog_dot_2883720012": { + "context": "export products to csv file, button", + "string": "export products" + }, + "src_dot_products_dot_components_dot_ProductExportDialog_dot_3012202273": { + "context": "export products to csv file, dialog header", + "string": "Export Information" + }, + "src_dot_products_dot_components_dot_ProductExportDialog_dot_3365843236": { + "context": "product export to csv file, header", + "string": "Export Settings" + }, + "src_dot_products_dot_components_dot_ProductExportDialog_dot_3443345452": { + "context": "selectt all options", + "string": "Select All" + }, + "src_dot_products_dot_components_dot_ProductExportDialog_dot_3518309850": { + "context": "export products as spreadsheet", + "string": "Spreadsheet for Excel, Numbers etc." + }, + "src_dot_products_dot_components_dot_ProductExportDialog_dot_3599582104": { + "string": "Search Atrtibuttes" + }, + "src_dot_products_dot_components_dot_ProductExportDialog_dot_3902059658": { + "string": "Export Product Stock Quantity to CSV" + }, + "src_dot_products_dot_components_dot_ProductExportDialog_dot_3919525499": { + "context": "informations about product stock, header", + "string": "Inventory Information" + }, + "src_dot_products_dot_components_dot_ProductExportDialog_dot_4118932547": { + "context": "export products as csv file", + "string": "Plain CSV file" + }, + "src_dot_products_dot_components_dot_ProductExportDialog_dot_472026385": { + "context": "select product informations to be exported", + "string": "Information exported:" + }, + "src_dot_products_dot_components_dot_ProductExportDialog_dot_524117994": { + "context": "input helper text, search attributes", + "string": "Search by attribute name" + }, + "src_dot_products_dot_components_dot_ProductExportDialog_dot_700651641": { + "context": "export filtered products to csv file", + "string": "Current search ({number})" + }, + "src_dot_products_dot_components_dot_ProductExportDialog_dot_734825715": { + "context": "informations about product prices etc, header", + "string": "Financial Information" + }, "src_dot_products_dot_components_dot_ProductImageNavigation_dot_3060635772": { "context": "section header", "string": "All Photos" @@ -3509,6 +4216,10 @@ "context": "product type", "string": "Type" }, + "src_dot_products_dot_components_dot_ProductListPage_dot_2059406063": { + "context": "export products to csv file, button", + "string": "Export Products" + }, "src_dot_products_dot_components_dot_ProductListPage_dot_3550330425": { "string": "Search Products..." }, @@ -3551,6 +4262,10 @@ "context": "product price", "string": "Price" }, + "src_dot_products_dot_components_dot_ProductList_dot_150865454": { + "context": "product type", + "string": "Simple" + }, "src_dot_products_dot_components_dot_ProductList_dot_1657559629": { "string": "No products found" }, @@ -3562,6 +4277,10 @@ "context": "product status", "string": "Not published" }, + "src_dot_products_dot_components_dot_ProductList_dot_2754779425": { + "context": "product type", + "string": "Configurable" + }, "src_dot_products_dot_components_dot_ProductList_dot_3640454975": { "context": "product status", "string": "Published" @@ -3640,17 +4359,21 @@ "src_dot_products_dot_components_dot_ProductStocks_dot_849869830": { "string": "Active inventory tracking will automatically calculate changes of stock" }, - "src_dot_products_dot_components_dot_ProductUpdatePage_dot_1815688500": { - "context": "product", - "string": "since {date}" + "src_dot_products_dot_components_dot_ProductUpdatePage_dot_2232321263": { + "context": "product publication date label", + "string": "will become published on {date}" }, - "src_dot_products_dot_components_dot_ProductUpdatePage_dot_2001551496": { - "context": "product", - "string": "will be visible from {date}" + "src_dot_products_dot_components_dot_ProductUpdatePage_dot_2341910657": { + "context": "product label", + "string": "Not published" }, "src_dot_products_dot_components_dot_ProductUpdatePage_dot_2706108815": { "string": "Add search engine title and description to make this product easier to find" }, + "src_dot_products_dot_components_dot_ProductUpdatePage_dot_3640454975": { + "context": "product label", + "string": "Published" + }, "src_dot_products_dot_components_dot_ProductVariantCreatePage_dot_2853608829": { "context": "button", "string": "Save variant" @@ -3792,11 +4515,11 @@ "context": "product pricing, section header", "string": "Pricing" }, - "src_dot_products_dot_components_dot_ProductVariantPrice_dot_1416480328": { - "string": "Cost price override" + "src_dot_products_dot_components_dot_ProductVariantPrice_dot_1134347598": { + "string": "Price" }, - "src_dot_products_dot_components_dot_ProductVariantPrice_dot_2238565650": { - "string": "Selling price override" + "src_dot_products_dot_components_dot_ProductVariantPrice_dot_819659341": { + "string": "Cost price" }, "src_dot_products_dot_components_dot_ProductVariants_dot_1001303107": { "context": "product variant inventory", @@ -3889,6 +4612,10 @@ "context": "dialog content", "string": "{counter,plural,one{Are you sure you want to delete this product?} other{Are you sure you want to delete {displayQuantity} products?}}" }, + "src_dot_products_dot_views_dot_ProductList_dot_1505423810": { + "context": "waiting for export to end, header", + "string": "Exporting CSV" + }, "src_dot_products_dot_views_dot_ProductList_dot_1547167026": { "context": "publish product, button", "string": "Publish" @@ -3917,6 +4644,9 @@ "context": "dialog header", "string": "Delete Products" }, + "src_dot_products_dot_views_dot_ProductList_dot_44832327": { + "string": "We are currently exporting your requested CSV. As soon as it is available it will be sent to your email address" + }, "src_dot_products_dot_views_dot_ProductUpdate_dot_1177237881": { "context": "dialog content", "string": "{counter,plural,one{Are you sure you want to delete this variant?} other{Are you sure you want to delete {displayQuantity} variants?}}" @@ -3932,6 +4662,10 @@ "src_dot_products_dot_views_dot_ProductUpdate_dot_4108890645": { "string": "Product removed" }, + "src_dot_products_dot_views_dot_ProductUpdate_dot_671489548": { + "context": "snackbar text", + "string": "Product availability updated" + }, "src_dot_products_dot_views_dot_ProductUpdate_dot_879305849": { "context": "dialog header", "string": "Delete Product" @@ -3980,163 +4714,18 @@ "src_dot_savedChanges": { "string": "Saved changes" }, + "src_dot_selectAll": { + "context": "select all options, button", + "string": "Select All" + }, + "src_dot_send": { + "context": "button", + "string": "Send" + }, "src_dot_serviceAccounts": { "context": "service accounts section name", "string": "Service Accounts" }, - "src_dot_services_dot_components_dot_ServiceCreatePage_dot_1848599267": { - "context": "checkbox label", - "string": "User has full access to the store" - }, - "src_dot_services_dot_components_dot_ServiceCreatePage_dot_248507553": { - "context": "header", - "string": "Create New Account" - }, - "src_dot_services_dot_components_dot_ServiceCreatePage_dot_27827485": { - "context": "checkbox label", - "string": "Service account is active" - }, - "src_dot_services_dot_components_dot_ServiceCreatePage_dot_3639008725": { - "context": "card description", - "string": "Expand or restrict user's permissions to access certain part of saleor system." - }, - "src_dot_services_dot_components_dot_ServiceDefaultToken_dot_1336855942": { - "string": "Generated Token" - }, - "src_dot_services_dot_components_dot_ServiceDefaultToken_dot_2080322626": { - "string": "This token gives you access to your shop's API, which you'll find here: {url}" - }, - "src_dot_services_dot_components_dot_ServiceDefaultToken_dot_2864204643": { - "context": "button", - "string": "Copied" - }, - "src_dot_services_dot_components_dot_ServiceDefaultToken_dot_3406541221": { - "context": "button", - "string": "Copy token" - }, - "src_dot_services_dot_components_dot_ServiceDefaultToken_dot_4189999598": { - "string": "We’ve created your default token. Make sure to copy your new personal access token now. You won’t be able to see it again." - }, - "src_dot_services_dot_components_dot_ServiceDeleteDialog_dot_1534767622": { - "context": "dialog header", - "string": "Delete Service Account" - }, - "src_dot_services_dot_components_dot_ServiceDeleteDialog_dot_2297471173": { - "context": "delete service account", - "string": "Are you sure you want to delete {name}?" - }, - "src_dot_services_dot_components_dot_ServiceDetailsPage_dot_1848599267": { - "context": "checkbox label", - "string": "User has full access to the store" - }, - "src_dot_services_dot_components_dot_ServiceDetailsPage_dot_27827485": { - "context": "checkbox label", - "string": "Service account is active" - }, - "src_dot_services_dot_components_dot_ServiceDetailsPage_dot_3639008725": { - "context": "card description", - "string": "Expand or restrict user's permissions to access certain part of saleor system." - }, - "src_dot_services_dot_components_dot_ServiceInfo_dot_3789449123": { - "context": "service account", - "string": "Account Name" - }, - "src_dot_services_dot_components_dot_ServiceInfo_dot_426959482": { - "context": "header", - "string": "Service Account Information" - }, - "src_dot_services_dot_components_dot_ServiceListPage_dot_1895355592": { - "string": "Search Service Accounts" - }, - "src_dot_services_dot_components_dot_ServiceListPage_dot_4040605455": { - "context": "tab name", - "string": "All Service Accounts" - }, - "src_dot_services_dot_components_dot_ServiceListPage_dot_624280156": { - "context": "button", - "string": "Create account" - }, - "src_dot_services_dot_components_dot_ServiceListPage_dot_active": { - "context": "service account", - "string": "Active" - }, - "src_dot_services_dot_components_dot_ServiceListPage_dot_deactivated": { - "context": "service account", - "string": "Inactive" - }, - "src_dot_services_dot_components_dot_ServiceList_dot_1342308051": { - "string": "No service accounts found" - }, - "src_dot_services_dot_components_dot_ServiceList_dot_31853942": { - "context": "account status", - "string": "active" - }, - "src_dot_services_dot_components_dot_ServiceList_dot_3239722049": { - "context": "account status", - "string": "inactive" - }, - "src_dot_services_dot_components_dot_ServiceList_dot_636461959": { - "context": "service name", - "string": "Name" - }, - "src_dot_services_dot_components_dot_ServiceTokenCreateDialog_dot_1336855942": { - "string": "Generated Token" - }, - "src_dot_services_dot_components_dot_ServiceTokenCreateDialog_dot_2530792168": { - "string": "Access token is used to authenticate service accounts" - }, - "src_dot_services_dot_components_dot_ServiceTokenCreateDialog_dot_3009959880": { - "string": "We’ve created your token. Make sure to copy your new personal access token now. You won’t be able to see it again." - }, - "src_dot_services_dot_components_dot_ServiceTokenCreateDialog_dot_3406541221": { - "context": "button", - "string": "Copy token" - }, - "src_dot_services_dot_components_dot_ServiceTokenCreateDialog_dot_3875340101": { - "context": "header", - "string": "Create Token" - }, - "src_dot_services_dot_components_dot_ServiceTokenCreateDialog_dot_4017491013": { - "string": "Token Note" - }, - "src_dot_services_dot_components_dot_ServiceTokenCreateDialog_dot_4120989039": { - "context": "create service token, button", - "string": "Create" - }, - "src_dot_services_dot_components_dot_ServiceTokenDeleteDialog_dot_1534767622": { - "context": "dialog title", - "string": "Delete Service Account" - }, - "src_dot_services_dot_components_dot_ServiceTokenDeleteDialog_dot_981802752": { - "context": "delete token", - "string": "Are you sure you want to delete token {token}?" - }, - "src_dot_services_dot_components_dot_ServiceTokens_dot_2446088470": { - "context": "service account key", - "string": "Key" - }, - "src_dot_services_dot_components_dot_ServiceTokens_dot_2639089057": { - "string": "No tokens found" - }, - "src_dot_services_dot_components_dot_ServiceTokens_dot_3875340101": { - "context": "button", - "string": "Create Token" - }, - "src_dot_services_dot_components_dot_ServiceTokens_dot_4017491013": { - "string": "Token Note" - }, - "src_dot_services_dot_components_dot_ServiceTokens_dot_4190792473": { - "context": "table actions", - "string": "Actions" - }, - "src_dot_services_dot_components_dot_ServiceTokens_dot_426959482": { - "context": "header", - "string": "Service Account Information" - }, - "src_dot_services_dot_views_dot_ServiceCreate_dot_3167211165": { - "context": "window title", - "string": "Create Service Account" - }, "src_dot_sessionExpired": { "string": "Your session has expired. Please log in again to continue." }, @@ -5073,15 +5662,35 @@ "src_dot_utils_dot_errors_dot_duplicatedInputItem": { "string": "Cannot add and remove group the same time" }, + "src_dot_utils_dot_errors_dot_emailNotSet": { + "context": "error message", + "string": "Email address is not set" + }, "src_dot_utils_dot_errors_dot_graphqlError": { "string": "API error" }, "src_dot_utils_dot_errors_dot_invalid": { "string": "Invalid value" }, + "src_dot_utils_dot_errors_dot_invalidManifestFormat": { + "string": "Invalid manifest format" + }, "src_dot_utils_dot_errors_dot_invalidPassword": { "string": "Invalid password" }, + "src_dot_utils_dot_errors_dot_invalidPermission": { + "string": "Permission is invalid" + }, + "src_dot_utils_dot_errors_dot_invalidStatus": { + "context": "error message", + "string": "Status is invalid" + }, + "src_dot_utils_dot_errors_dot_invalidUrlFormat": { + "string": "Url has invalid format" + }, + "src_dot_utils_dot_errors_dot_misconfigured": { + "string": "Plugin is misconfigured and cannot be activated" + }, "src_dot_utils_dot_errors_dot_noShippingAddress": { "context": "error message", "string": "Cannot choose a shipping method for an order without the shipping address" @@ -5090,9 +5699,27 @@ "context": "error message", "string": "Only draft orders can be edited" }, + "src_dot_utils_dot_errors_dot_notFound": { + "context": "error message", + "string": "Invoice not found" + }, + "src_dot_utils_dot_errors_dot_notReady": { + "context": "error message", + "string": "Billing address is not set or invoice is not ready to be send" + }, + "src_dot_utils_dot_errors_dot_numberNotSet": { + "context": "error message", + "string": "Number not set for an invoice" + }, + "src_dot_utils_dot_errors_dot_outOfScopeApp": { + "string": "App is out of your permissions scope" + }, "src_dot_utils_dot_errors_dot_outOfScopeGroup": { "string": "Group is out of your permission scope" }, + "src_dot_utils_dot_errors_dot_outOfScopePermission": { + "string": "Permission is out of your scope" + }, "src_dot_utils_dot_errors_dot_outOfScopeUser": { "string": "User is out of your permissions scope" }, @@ -5137,6 +5764,10 @@ "src_dot_utils_dot_errors_dot_unknownError": { "string": "Unknown error" }, + "src_dot_utils_dot_errors_dot_urlNotSet": { + "context": "error message", + "string": "URL not set for an invoice" + }, "src_dot_utils_dot_errors_dot_variantNoDigitalContent": { "string": "This variant does not have any digital content" }, @@ -5230,6 +5861,14 @@ "context": "dialog header", "string": "Delete Webhook" }, + "src_dot_webhooks_dot_components_dot_WebhookEvents_dot_1087314240": { + "context": "event", + "string": "Checkout updated" + }, + "src_dot_webhooks_dot_components_dot_WebhookEvents_dot_1368317066": { + "context": "event", + "string": "Invoice deleted" + }, "src_dot_webhooks_dot_components_dot_WebhookEvents_dot_1436364351": { "context": "section header", "string": "Events" @@ -5238,10 +5877,18 @@ "context": "event", "string": "Order updated" }, + "src_dot_webhooks_dot_components_dot_WebhookEvents_dot_2240725235": { + "context": "event", + "string": "Checkout created" + }, "src_dot_webhooks_dot_components_dot_WebhookEvents_dot_2454751033": { "context": "event", "string": "All events" }, + "src_dot_webhooks_dot_components_dot_WebhookEvents_dot_2862596150": { + "context": "event", + "string": "Invoice sent" + }, "src_dot_webhooks_dot_components_dot_WebhookEvents_dot_2899821092": { "context": "event", "string": "Product created" @@ -5274,6 +5921,10 @@ "context": "event", "string": "Changed quantity in checkout" }, + "src_dot_webhooks_dot_components_dot_WebhookEvents_dot_4186057882": { + "context": "event", + "string": "Invoice requested" + }, "src_dot_webhooks_dot_components_dot_WebhookEvents_dot_4281441551": { "context": "event", "string": "Fulfillment created" @@ -5306,9 +5957,6 @@ "context": "webhook specific information", "string": "Webhook specific information" }, - "src_dot_webhooks_dot_components_dot_WebhookInfo_dot_819389696": { - "string": "Assign to Service Account" - }, "src_dot_webhooks_dot_components_dot_WebhookStatus_dot_2772025990": { "context": "webhooks active", "string": "Webhook is active" @@ -5329,31 +5977,16 @@ "context": "header", "string": "{webhookName} Details" }, - "src_dot_webhooks_dot_components_dot_WebhooksListPage_dot_1432828311": { - "string": "Search Webhooks" - }, - "src_dot_webhooks_dot_components_dot_WebhooksListPage_dot_2295583901": { - "context": "button", - "string": "Create webhook" - }, - "src_dot_webhooks_dot_components_dot_WebhooksListPage_dot_3300314452": { - "context": "tab name", - "string": "All Webhooks" - }, - "src_dot_webhooks_dot_components_dot_WebhooksListPage_dot_active": { - "context": "webhook", - "string": "Active" - }, - "src_dot_webhooks_dot_components_dot_WebhooksListPage_dot_inactive": { - "context": "webhook", - "string": "Inactive" - }, "src_dot_webhooks_dot_components_dot_WebhooksList_dot_1153324159": { "string": "No webhooks found" }, - "src_dot_webhooks_dot_components_dot_WebhooksList_dot_2487865635": { - "context": "webhook service account", - "string": "Service Account" + "src_dot_webhooks_dot_components_dot_WebhooksList_dot_3493926696": { + "context": "button", + "string": "Create Webhook" + }, + "src_dot_webhooks_dot_components_dot_WebhooksList_dot_3861572549": { + "context": "header", + "string": "Webhooks" }, "src_dot_webhooks_dot_components_dot_WebhooksList_dot_4120604650": { "context": "user action bar", diff --git a/locale/el.json b/locale/el.json index 46d182355..172ea2bda 100644 --- a/locale/el.json +++ b/locale/el.json @@ -250,7 +250,7 @@ "context": "optional field", "string": "Optional" }, - "productVariantPriceOptionalPriceOverrideField": { + "productVariantPriceOptionalPriceField": { "context": "optional field", "string": "Optional" }, @@ -1675,6 +1675,10 @@ "context": "button", "string": "Delete" }, + "src_dot_demo": { + "context": "notification message after log in", + "string": "Just to let you know... You're in demo mode. You can play around with the dashboard but can't save changes." + }, "src_dot_description": { "string": "ΠÎĩĪÎšÎŗĪÎąĪ†ÎŽ" }, @@ -2532,6 +2536,10 @@ "context": "cancelled fulfillment, section header", "string": "Cancelled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderFulfillment_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderFulfillment_dot_732594284": { "context": "button", "string": "Cancel Fulfillment" @@ -2749,6 +2757,10 @@ "context": "order payment", "string": "Outstanding Balance" }, + "src_dot_orders_dot_components_dot_OrderPayment_dot_3720114122": { + "context": "order discount", + "string": "ΈÎēĪ€Ī„Ī‰ĪƒÎˇ" + }, "src_dot_orders_dot_components_dot_OrderPayment_dot_3768782744": { "context": "order payment", "string": "Î ĪÎŋÎĩÎŗÎēÎĩÎēĪÎšÎŧέÎŊÎŋ Ī€Îŋ΃Ό" @@ -2768,10 +2780,6 @@ "context": "order total price", "string": "ÎŖĪÎŊÎŋÎģÎŋ" }, - "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_1542417144": { - "context": "dialog header", - "string": "Create Product" - }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2272209368": { "context": "variant sku", "string": "SKU {sku}" @@ -2779,6 +2787,10 @@ "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2336947364": { "string": "Search by product name, attribute, product type etc..." }, + "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2775402904": { + "context": "dialog header", + "string": "Add Product" + }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2850255786": { "string": "Search Products" }, @@ -2809,6 +2821,10 @@ "context": "section header", "string": "Unfulfilled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_878013594": { "context": "order line total price", "string": "ÎŖĪÎŊÎŋÎģÎŋ" @@ -3621,17 +3637,14 @@ "context": "header", "string": "ΠÎŋĪƒĪŒĪ„ÎˇĪ„Îą" }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3143542809": { - "string": "This product doesn't have any stock. You can add it here." - }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3482985373": { - "context": "button", - "string": "Edit Warehouses" - }, "src_dot_products_dot_components_dot_ProductStocks_dot_3633706025": { "context": "product inventory, checkbox", "string": "Track Inventory" }, + "src_dot_products_dot_components_dot_ProductStocks_dot_3857433664": { + "context": "button", + "string": "Assign Warehouse" + }, "src_dot_products_dot_components_dot_ProductStocks_dot_849869830": { "string": "Active inventory tracking will automatically calculate changes of stock" }, @@ -3859,13 +3872,6 @@ "context": "product variant name", "string": "Î ÎąĪÎąÎģÎģÎąÎŗÎŽ" }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_3482985373": { - "context": "dialog header", - "string": "Edit Warehouses" - }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_4112406382": { - "string": "Select warehouses that stock selected product" - }, "src_dot_products_dot_views_dot_1542417144": { "context": "window title", "string": "Create Product" @@ -4147,6 +4153,9 @@ "context": "window title", "string": "Create Service Account" }, + "src_dot_sessionExpired": { + "string": "Your session has expired. Please log in again to continue." + }, "src_dot_shipping": { "context": "shipping section name", "string": "Shipping Methods" diff --git a/locale/es.json b/locale/es.json index 9a388d9eb..ad5bbd0d0 100644 --- a/locale/es.json +++ b/locale/es.json @@ -250,7 +250,7 @@ "context": "optional field", "string": "Opcional" }, - "productVariantPriceOptionalPriceOverrideField": { + "productVariantPriceOptionalPriceField": { "context": "optional field", "string": "Opcional" }, @@ -1675,6 +1675,10 @@ "context": "button", "string": "Borrar" }, + "src_dot_demo": { + "context": "notification message after log in", + "string": "Just to let you know... You're in demo mode. You can play around with the dashboard but can't save changes." + }, "src_dot_description": { "string": "DescripciÃŗn" }, @@ -2532,6 +2536,10 @@ "context": "cancelled fulfillment, section header", "string": "({quantity}) cancelados" }, + "src_dot_orders_dot_components_dot_OrderFulfillment_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderFulfillment_dot_732594284": { "context": "button", "string": "Cancelar envío" @@ -2749,6 +2757,10 @@ "context": "order payment", "string": "Saldo pendiente" }, + "src_dot_orders_dot_components_dot_OrderPayment_dot_3720114122": { + "context": "order discount", + "string": "Descuento" + }, "src_dot_orders_dot_components_dot_OrderPayment_dot_3768782744": { "context": "order payment", "string": "Monto preautorizado" @@ -2768,10 +2780,6 @@ "context": "order total price", "string": "Total" }, - "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_1542417144": { - "context": "dialog header", - "string": "Crear producto" - }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2272209368": { "context": "variant sku", "string": "SKU {sku}" @@ -2779,6 +2787,10 @@ "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2336947364": { "string": "Buscar por nombre de producto, atributo, tipo de producto, etc." }, + "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2775402904": { + "context": "dialog header", + "string": "Agregar Producto" + }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2850255786": { "string": "Buscar Productos" }, @@ -2809,6 +2821,10 @@ "context": "section header", "string": "No cumplido ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_878013594": { "context": "order line total price", "string": "Total" @@ -3621,17 +3637,14 @@ "context": "header", "string": "Cantidad" }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3143542809": { - "string": "Este producto no tiene stock. Puedes agregarlo aquí." - }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3482985373": { - "context": "button", - "string": "Editar almacenes" - }, "src_dot_products_dot_components_dot_ProductStocks_dot_3633706025": { "context": "product inventory, checkbox", "string": "Seguimiento de inventario" }, + "src_dot_products_dot_components_dot_ProductStocks_dot_3857433664": { + "context": "button", + "string": "Assign Warehouse" + }, "src_dot_products_dot_components_dot_ProductStocks_dot_849869830": { "string": "El seguimiento de inventario activo calcularÃĄ automÃĄticamente los cambios de stock" }, @@ -3859,13 +3872,6 @@ "context": "product variant name", "string": "Variante" }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_3482985373": { - "context": "dialog header", - "string": "Editar almacenes" - }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_4112406382": { - "string": "Seleccione los almacenes que tienen el producto seleccionado." - }, "src_dot_products_dot_views_dot_1542417144": { "context": "window title", "string": "Crear producto" @@ -4147,6 +4153,9 @@ "context": "window title", "string": "Crear cuenta de servicio" }, + "src_dot_sessionExpired": { + "string": "Your session has expired. Please log in again to continue." + }, "src_dot_shipping": { "context": "shipping section name", "string": "MÊtodos de envío" diff --git a/locale/es_CO.json b/locale/es_CO.json index ef4ada859..a2ec729f5 100644 --- a/locale/es_CO.json +++ b/locale/es_CO.json @@ -250,7 +250,7 @@ "context": "optional field", "string": "Optional" }, - "productVariantPriceOptionalPriceOverrideField": { + "productVariantPriceOptionalPriceField": { "context": "optional field", "string": "Optional" }, @@ -1675,6 +1675,10 @@ "context": "button", "string": "Delete" }, + "src_dot_demo": { + "context": "notification message after log in", + "string": "Just to let you know... You're in demo mode. You can play around with the dashboard but can't save changes." + }, "src_dot_description": { "string": "DescripciÃŗn" }, @@ -2532,6 +2536,10 @@ "context": "cancelled fulfillment, section header", "string": "Cancelled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderFulfillment_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderFulfillment_dot_732594284": { "context": "button", "string": "Cancel Fulfillment" @@ -2749,6 +2757,10 @@ "context": "order payment", "string": "Outstanding Balance" }, + "src_dot_orders_dot_components_dot_OrderPayment_dot_3720114122": { + "context": "order discount", + "string": "Discount" + }, "src_dot_orders_dot_components_dot_OrderPayment_dot_3768782744": { "context": "order payment", "string": "Preauthorized amount" @@ -2768,10 +2780,6 @@ "context": "order total price", "string": "Total" }, - "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_1542417144": { - "context": "dialog header", - "string": "Create Product" - }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2272209368": { "context": "variant sku", "string": "SKU {sku}" @@ -2779,6 +2787,10 @@ "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2336947364": { "string": "Search by product name, attribute, product type etc..." }, + "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2775402904": { + "context": "dialog header", + "string": "Add Product" + }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2850255786": { "string": "Search Products" }, @@ -2809,6 +2821,10 @@ "context": "section header", "string": "Unfulfilled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_878013594": { "context": "order line total price", "string": "Total" @@ -3621,17 +3637,14 @@ "context": "header", "string": "Cantidad" }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3143542809": { - "string": "This product doesn't have any stock. You can add it here." - }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3482985373": { - "context": "button", - "string": "Edit Warehouses" - }, "src_dot_products_dot_components_dot_ProductStocks_dot_3633706025": { "context": "product inventory, checkbox", "string": "Track Inventory" }, + "src_dot_products_dot_components_dot_ProductStocks_dot_3857433664": { + "context": "button", + "string": "Assign Warehouse" + }, "src_dot_products_dot_components_dot_ProductStocks_dot_849869830": { "string": "Active inventory tracking will automatically calculate changes of stock" }, @@ -3859,13 +3872,6 @@ "context": "product variant name", "string": "Variant" }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_3482985373": { - "context": "dialog header", - "string": "Edit Warehouses" - }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_4112406382": { - "string": "Select warehouses that stock selected product" - }, "src_dot_products_dot_views_dot_1542417144": { "context": "window title", "string": "Create Product" @@ -4147,6 +4153,9 @@ "context": "window title", "string": "Create Service Account" }, + "src_dot_sessionExpired": { + "string": "Your session has expired. Please log in again to continue." + }, "src_dot_shipping": { "context": "shipping section name", "string": "Shipping Methods" diff --git a/locale/et.json b/locale/et.json index ede6f6401..fadf1025d 100644 --- a/locale/et.json +++ b/locale/et.json @@ -250,7 +250,7 @@ "context": "optional field", "string": "Valikuline" }, - "productVariantPriceOptionalPriceOverrideField": { + "productVariantPriceOptionalPriceField": { "context": "optional field", "string": "Valikuline" }, @@ -1675,6 +1675,10 @@ "context": "button", "string": "Delete" }, + "src_dot_demo": { + "context": "notification message after log in", + "string": "Just to let you know... You're in demo mode. You can play around with the dashboard but can't save changes." + }, "src_dot_description": { "string": "Kirjeldus" }, @@ -2532,6 +2536,10 @@ "context": "cancelled fulfillment, section header", "string": "Cancelled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderFulfillment_dot_693960049": { + "context": "ordered product sku", + "string": "Tootekood" + }, "src_dot_orders_dot_components_dot_OrderFulfillment_dot_732594284": { "context": "button", "string": "TÃŧhista Saadetis" @@ -2749,6 +2757,10 @@ "context": "order payment", "string": "Outstanding Balance" }, + "src_dot_orders_dot_components_dot_OrderPayment_dot_3720114122": { + "context": "order discount", + "string": "Allahindlus" + }, "src_dot_orders_dot_components_dot_OrderPayment_dot_3768782744": { "context": "order payment", "string": "Eelnevalt kinnitatud summa" @@ -2768,10 +2780,6 @@ "context": "order total price", "string": "Kokku" }, - "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_1542417144": { - "context": "dialog header", - "string": "Create Product" - }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2272209368": { "context": "variant sku", "string": "SKU {sku}" @@ -2779,6 +2787,10 @@ "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2336947364": { "string": "Search by product name, attribute, product type etc..." }, + "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2775402904": { + "context": "dialog header", + "string": "Lisa Toode" + }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2850255786": { "string": "Otsi tooteid" }, @@ -2809,6 +2821,10 @@ "context": "section header", "string": "Täitmata ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_693960049": { + "context": "ordered product sku", + "string": "Tootekood" + }, "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_878013594": { "context": "order line total price", "string": "Kokku" @@ -3621,17 +3637,14 @@ "context": "header", "string": "Kogus" }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3143542809": { - "string": "This product doesn't have any stock. You can add it here." - }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3482985373": { - "context": "button", - "string": "Edit Warehouses" - }, "src_dot_products_dot_components_dot_ProductStocks_dot_3633706025": { "context": "product inventory, checkbox", "string": "Track Inventory" }, + "src_dot_products_dot_components_dot_ProductStocks_dot_3857433664": { + "context": "button", + "string": "Assign Warehouse" + }, "src_dot_products_dot_components_dot_ProductStocks_dot_849869830": { "string": "Active inventory tracking will automatically calculate changes of stock" }, @@ -3859,13 +3872,6 @@ "context": "product variant name", "string": "Variant" }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_3482985373": { - "context": "dialog header", - "string": "Edit Warehouses" - }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_4112406382": { - "string": "Select warehouses that stock selected product" - }, "src_dot_products_dot_views_dot_1542417144": { "context": "window title", "string": "Create Product" @@ -4147,6 +4153,9 @@ "context": "window title", "string": "Create Service Account" }, + "src_dot_sessionExpired": { + "string": "Your session has expired. Please log in again to continue." + }, "src_dot_shipping": { "context": "shipping section name", "string": "Shipping Methods" diff --git a/locale/fa.json b/locale/fa.json index 733529938..e99e528b1 100644 --- a/locale/fa.json +++ b/locale/fa.json @@ -250,7 +250,7 @@ "context": "optional field", "string": "Optional" }, - "productVariantPriceOptionalPriceOverrideField": { + "productVariantPriceOptionalPriceField": { "context": "optional field", "string": "Optional" }, @@ -1675,6 +1675,10 @@ "context": "button", "string": "Ø­Ø°Ų" }, + "src_dot_demo": { + "context": "notification message after log in", + "string": "Just to let you know... You're in demo mode. You can play around with the dashboard but can't save changes." + }, "src_dot_description": { "string": "ØĒ؈ØļیحاØĒ" }, @@ -2532,6 +2536,10 @@ "context": "cancelled fulfillment, section header", "string": "Cancelled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderFulfillment_dot_693960049": { + "context": "ordered product sku", + "string": "ŲˆØ§Ø­Ø¯ Ø§Ų†Ø¨Ø§Øą Ø¯Ø§ØąÛŒ" + }, "src_dot_orders_dot_components_dot_OrderFulfillment_dot_732594284": { "context": "button", "string": "Ų„Øē؈ ŲžØąØ¯Ø§Ø˛Ø´" @@ -2749,6 +2757,10 @@ "context": "order payment", "string": "ØĒØąØ§Ø˛" }, + "src_dot_orders_dot_components_dot_OrderPayment_dot_3720114122": { + "context": "order discount", + "string": "ØĒØŽŲÛŒŲ" + }, "src_dot_orders_dot_components_dot_OrderPayment_dot_3768782744": { "context": "order payment", "string": "Ų…Ų‚Ø¯Ø§Øą ŲžÛŒØ´ ŲžØąØ¯Ø§ØŽØĒ" @@ -2768,10 +2780,6 @@ "context": "order total price", "string": "Ų…ØŦŲ…ŲˆØš ÚŠŲ„" }, - "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_1542417144": { - "context": "dialog header", - "string": "ایØŦاد Ų…Ø­ØĩŲˆŲ„" - }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2272209368": { "context": "variant sku", "string": "SKU {sku}" @@ -2779,6 +2787,10 @@ "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2336947364": { "string": "Search by product name, attribute, product type etc..." }, + "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2775402904": { + "context": "dialog header", + "string": "Ø§ŲØ˛ŲˆØ¯Ų† Ų…Ø­ØĩŲˆŲ„" + }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2850255786": { "string": "Search Products" }, @@ -2809,6 +2821,10 @@ "context": "section header", "string": "Unfulfilled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_693960049": { + "context": "ordered product sku", + "string": "ŲˆØ§Ø­Ø¯ Ø§Ų†Ø¨Ø§Øą Ø¯Ø§ØąÛŒ" + }, "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_878013594": { "context": "order line total price", "string": "Ų…ØŦŲ…ŲˆØš ÚŠŲ„" @@ -3621,17 +3637,14 @@ "context": "header", "string": "ØĒؚداد" }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3143542809": { - "string": "This product doesn't have any stock. You can add it here." - }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3482985373": { - "context": "button", - "string": "Edit Warehouses" - }, "src_dot_products_dot_components_dot_ProductStocks_dot_3633706025": { "context": "product inventory, checkbox", "string": "Track Inventory" }, + "src_dot_products_dot_components_dot_ProductStocks_dot_3857433664": { + "context": "button", + "string": "Assign Warehouse" + }, "src_dot_products_dot_components_dot_ProductStocks_dot_849869830": { "string": "Active inventory tracking will automatically calculate changes of stock" }, @@ -3859,13 +3872,6 @@ "context": "product variant name", "string": "Ų†ŲˆØš" }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_3482985373": { - "context": "dialog header", - "string": "Edit Warehouses" - }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_4112406382": { - "string": "Select warehouses that stock selected product" - }, "src_dot_products_dot_views_dot_1542417144": { "context": "window title", "string": "ایØŦاد Ų…Ø­ØĩŲˆŲ„" @@ -4147,6 +4153,9 @@ "context": "window title", "string": "ØŗØ§ØŽØĒ Ø­ØŗØ§Ø¨ ØŽØ¯Ų…ØĒ" }, + "src_dot_sessionExpired": { + "string": "Your session has expired. Please log in again to continue." + }, "src_dot_shipping": { "context": "shipping section name", "string": "ØąŲˆØ´ Ø§ØąØŗØ§Ų„" diff --git a/locale/fr.json b/locale/fr.json index 1f3dd7122..af8f2168e 100644 --- a/locale/fr.json +++ b/locale/fr.json @@ -13,7 +13,7 @@ "string": "GÊrer et ajouter des pages" }, "configurationMenuPermissionGroups": { - "string": "Manage your permission groups and their permissions" + "string": "GÊrez vos groupes de permissions et leurs permissions" }, "configurationMenuProductTypes": { "string": "DÊfinir les types de produits vendu" @@ -31,7 +31,7 @@ "string": "GÊrer les taxes de votre magasin" }, "configurationMenuWarehouses": { - "string": "Manage and update your warehouse information" + "string": "GÊrez et mettez à jour les informations de votre entrepôt" }, "configurationPluginsPages": { "string": "Visualiser et mettre à jour vos plugins et leurs paramètres " @@ -244,13 +244,13 @@ }, "productVariantCreatorWarehouseSectionHeader": { "context": "header", - "string": "Warehouses" + "string": "Entrepôts" }, "productVariantPriceOptionalCostPriceField": { "context": "optional field", "string": "Optionnel" }, - "productVariantPriceOptionalPriceOverrideField": { + "productVariantPriceOptionalPriceField": { "context": "optional field", "string": "Optionnel" }, @@ -288,7 +288,7 @@ }, "shippingZoneWarehouses_dot_autocomplete_dot_label": { "context": "autocomplete select label", - "string": "Warehouse" + "string": "Entrepôt" }, "siteSettingsMailingHelperText": { "context": "helper text", @@ -296,17 +296,17 @@ }, "src_dot_accept": { "context": "button", - "string": "Accept" + "string": "J'accepte" }, "src_dot_attributes": { "context": "attributes section name", "string": "Attributs" }, "src_dot_attributes_dot_attributeSlugUnique": { - "string": "Attribute with this slug already exists" + "string": "L'attribut avec ce slug existe dÊjà" }, "src_dot_attributes_dot_attributeValueAlreadyExists": { - "string": "This value already exists within this attribute" + "string": "Cette valeur existe dÊjà dans cet attribut" }, "src_dot_attributes_dot_components_dot_AttributeBulkDeleteDialog_dot_1184518529": { "context": "dialog content", @@ -913,19 +913,19 @@ "string": "Effacer les collections" }, "src_dot_components_dot_AccountPermissionGroups_dot_2836633439": { - "string": "Permission groups" + "string": "Groupes de permissions" }, "src_dot_components_dot_AccountPermissions_dot_2690176844": { "context": "dialog header", - "string": "Droits" + "string": "Permissions" }, "src_dot_components_dot_AccountPermissions_dot_2731975416": { "context": "card section description", - "string": "Available permissions" + "string": "Permissions disponibles" }, "src_dot_components_dot_AccountPermissions_dot_2853621891": { "context": "exceeded permissions description", - "string": "This groups permissions exceeds your own. You are able only to manage permissions that you have." + "string": "Les permissions de ce groupe dÊpassent les vôtres. Vous ne pouvez gÊrer que les permissions dont vous disposez." }, "src_dot_components_dot_AccountPermissions_dot_3674526441": { "context": "permission list item description", @@ -1237,7 +1237,7 @@ }, "src_dot_components_dot_Navigator_dot_modes_dot_createPermissionGroup": { "context": "button", - "string": "Create Permission Group" + "string": "CrÊer un groupe de permissions" }, "src_dot_components_dot_Navigator_dot_modes_dot_createProduct": { "context": "button", @@ -1428,7 +1428,7 @@ "string": "Divers" }, "src_dot_configuration_dot_1440737903": { - "string": "Shipping Settings" + "string": "Paramètres de livraison" }, "src_dot_configuration_dot_1639245766": { "string": "Consultez et modifiez les Webhooks et leurs paramètres" @@ -1675,6 +1675,10 @@ "context": "button", "string": "Effacer" }, + "src_dot_demo": { + "context": "notification message after log in", + "string": "Just to let you know... You're in demo mode. You can play around with the dashboard but can't save changes." + }, "src_dot_description": { "string": "Description" }, @@ -2227,7 +2231,7 @@ }, "src_dot_ok": { "context": "button", - "string": "OK" + "string": "D'accord" }, "src_dot_optionalField": { "context": "field is optional", @@ -2257,7 +2261,7 @@ }, "src_dot_orders_dot_components_dot_OrderCannotCancelOrderDialog_dot_1561587911": { "context": "dialog header", - "string": "Saleor couldn’t cancel order" + "string": "Saleor n'a pas pu annuler la commande" }, "src_dot_orders_dot_components_dot_OrderCannotCancelOrderDialog_dot_775268031": { "string": "There are still fulfillments created for this order. Cancel the fulfillments first before you cancel the order." @@ -2443,11 +2447,11 @@ }, "src_dot_orders_dot_components_dot_OrderFulfillPage_dot_2588284040": { "context": "no variant stock in warehouse", - "string": "No Stock" + "string": "Pas de stock" }, "src_dot_orders_dot_components_dot_OrderFulfillPage_dot_3244948255": { "context": "header", - "string": "Items ready to ship" + "string": "Articles prÃĒts à ÃĒtre expÊdiÊs" }, "src_dot_orders_dot_components_dot_OrderFulfillPage_dot_3620521256": { "context": "page header", @@ -2462,7 +2466,7 @@ }, "src_dot_orders_dot_components_dot_OrderFulfillPage_dot_580490159": { "context": "page header with order number", - "string": "Order #{orderNumber}" + "string": "Commande #{orderNumber}" }, "src_dot_orders_dot_components_dot_OrderFulfillPage_dot_693960049": { "context": "product's sku", @@ -2473,7 +2477,7 @@ }, "src_dot_orders_dot_components_dot_OrderFulfillmentCancelDialog_dot_46197273": { "context": "select warehouse to restock items", - "string": "Select Warehouse" + "string": "SÊlectionner un entrepôt" }, "src_dot_orders_dot_components_dot_OrderFulfillmentCancelDialog_dot_732594284": { "context": "dialog header", @@ -2532,6 +2536,10 @@ "context": "cancelled fulfillment, section header", "string": "Cancelled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderFulfillment_dot_693960049": { + "context": "ordered product sku", + "string": "UGS (UnitÊ de Gestion de Stock)" + }, "src_dot_orders_dot_components_dot_OrderFulfillment_dot_732594284": { "context": "button", "string": "Annuler le traitement" @@ -2749,6 +2757,10 @@ "context": "order payment", "string": "Solde exceptionnel " }, + "src_dot_orders_dot_components_dot_OrderPayment_dot_3720114122": { + "context": "order discount", + "string": "Remise" + }, "src_dot_orders_dot_components_dot_OrderPayment_dot_3768782744": { "context": "order payment", "string": "Montant prÊ-autorisÊ" @@ -2768,10 +2780,6 @@ "context": "order total price", "string": "Total" }, - "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_1542417144": { - "context": "dialog header", - "string": "CrÊer produit" - }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2272209368": { "context": "variant sku", "string": "UGS {sku}" @@ -2779,6 +2787,10 @@ "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2336947364": { "string": "Recherche par nom de produit, attribut, type de produit, etc..." }, + "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2775402904": { + "context": "dialog header", + "string": "Ajouter un produit" + }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2850255786": { "string": "Rechercher dans les produits" }, @@ -2809,6 +2821,10 @@ "context": "section header", "string": "Non traitÊes ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_693960049": { + "context": "ordered product sku", + "string": "UGS (UnitÊ de Gestion de Stock)" + }, "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_878013594": { "context": "order line total price", "string": "Total" @@ -2848,7 +2864,7 @@ }, "src_dot_orders_dot_views_dot_OrderDetails_dot_580490159": { "context": "window title", - "string": "Order #{orderNumber}" + "string": "Commande #{orderNumber}" }, "src_dot_orders_dot_views_dot_OrderDetails_dot_617145655": { "string": "La mÊthode de livraison a ÊtÊ mise à jour avec succès" @@ -2858,7 +2874,7 @@ }, "src_dot_orders_dot_views_dot_OrderDetails_dot_694622335": { "context": "window title", - "string": "Draft Order #{orderNumber}" + "string": "Commande brouillonne #{orderNumber}" }, "src_dot_orders_dot_views_dot_OrderDetails_dot_927945225": { "string": "Le traitement a ÊtÊ annulÊ" @@ -3029,7 +3045,7 @@ }, "src_dot_permissionGroups": { "context": "permission groups section name", - "string": "Permission Groups" + "string": "Groupes de permissions" }, "src_dot_permissionGroups_dot_components_dot_AssignMembersDialog_dot_1004218338": { "context": "staff member status", @@ -3037,25 +3053,25 @@ }, "src_dot_permissionGroups_dot_components_dot_AssignMembersDialog_dot_1731102929": { "context": "button", - "string": "Assign" + "string": "Affecter" }, "src_dot_permissionGroups_dot_components_dot_AssignMembersDialog_dot_2986043376": { "context": "dialog header", - "string": "Assign Staff Members" + "string": "Affecter des membres du personnel" }, "src_dot_permissionGroups_dot_components_dot_AssignMembersDialog_dot_3111990517": { - "string": "Search by name, email, etc..." + "string": "Recherche par nom, email, etc ..." }, "src_dot_permissionGroups_dot_components_dot_AssignMembersDialog_dot_3247064221": { "context": "staff member status", "string": "ActivÊ" }, "src_dot_permissionGroups_dot_components_dot_AssignMembersDialog_dot_3532084010": { - "string": "Search Staff Members" + "string": "Rechercher des membres du personnel" }, "src_dot_permissionGroups_dot_components_dot_MembersErrorDialog_dot_3005518110": { "context": "dialog title", - "string": "Unassign users" + "string": "Annuler l'attribution des utilisateurs" }, "src_dot_permissionGroups_dot_components_dot_MembersErrorDialog_dot_334280454": { "context": "dialog content", @@ -3063,7 +3079,7 @@ }, "src_dot_permissionGroups_dot_components_dot_PermissionGroupCreatePage_dot_3765873075": { "context": "checkbox label", - "string": "Group has full access to the store" + "string": "Le groupe a un accès complet au magasin" }, "src_dot_permissionGroups_dot_components_dot_PermissionGroupCreatePage_dot_3920591233": { "context": "card description", @@ -3075,7 +3091,7 @@ }, "src_dot_permissionGroups_dot_components_dot_PermissionGroupDeleteDialog_dot_3528974446": { "context": "dialog title", - "string": "Delete permission group" + "string": "Supprimer le groupe de permissions" }, "src_dot_permissionGroups_dot_components_dot_PermissionGroupDeleteDialog_dot_956177443": { "context": "deletion error message", @@ -3083,7 +3099,7 @@ }, "src_dot_permissionGroups_dot_components_dot_PermissionGroupDetailsPage_dot_3765873075": { "context": "checkbox label", - "string": "Group has full access to the store" + "string": "Le groupe a un accès complet au magasin" }, "src_dot_permissionGroups_dot_components_dot_PermissionGroupDetailsPage_dot_3920591233": { "context": "card description", @@ -3091,24 +3107,24 @@ }, "src_dot_permissionGroups_dot_components_dot_PermissionGroupInfo_dot_2081191949": { "context": "text field label", - "string": "Group name" + "string": "Nom du groupe" }, "src_dot_permissionGroups_dot_components_dot_PermissionGroupListPage_dot_613749311": { "context": "button", - "string": "create permission group" + "string": "CrÊer un groupe de permissions" }, "src_dot_permissionGroups_dot_components_dot_PermissionGroupList_dot_2011544055": { "context": "permission group name", - "string": "Permission Group Name" + "string": "Nom du groupe de permission" }, "src_dot_permissionGroups_dot_components_dot_PermissionGroupList_dot_2734377620": { - "string": "Members" + "string": "Membres" }, "src_dot_permissionGroups_dot_components_dot_PermissionGroupList_dot_4190792473": { "string": "Actions" }, "src_dot_permissionGroups_dot_components_dot_PermissionGroupList_dot_425941108": { - "string": "No permission groups found" + "string": "Aucun groupe de permissions trouvÊ" }, "src_dot_permissionGroups_dot_components_dot_PermissionGroupMemberList_dot_1004218338": { "context": "staff member status", @@ -3119,14 +3135,14 @@ "string": "You haven’t assigned any member to this permission group yet." }, "src_dot_permissionGroups_dot_components_dot_PermissionGroupMemberList_dot_1512872240": { - "string": "No members found" + "string": "Aucun membre trouvÊ" }, "src_dot_permissionGroups_dot_components_dot_PermissionGroupMemberList_dot_1789607185": { "string": "Adresse e-mail" }, "src_dot_permissionGroups_dot_components_dot_PermissionGroupMemberList_dot_2457011428": { "context": "button", - "string": "Assign members" + "string": "Affecter des membres" }, "src_dot_permissionGroups_dot_components_dot_PermissionGroupMemberList_dot_2652621342": { "context": "empty list message", @@ -3138,7 +3154,7 @@ }, "src_dot_permissionGroups_dot_components_dot_PermissionGroupMemberList_dot_3397233744": { "context": "header", - "string": "Group members" + "string": "Les membres du groupe" }, "src_dot_permissionGroups_dot_components_dot_PermissionGroupMemberList_dot_4190792473": { "string": "Actions" @@ -3149,7 +3165,7 @@ }, "src_dot_permissionGroups_dot_components_dot_UnassignMembersDialog_dot_3005518110": { "context": "dialog title", - "string": "Unassign users" + "string": "Annuler l'attribution des utilisateurs" }, "src_dot_permissionGroups_dot_components_dot_UnassignMembersDialog_dot_778652830": { "context": "dialog content", @@ -3160,14 +3176,14 @@ "string": "CrÊer une catÊgorie" }, "src_dot_permissionGroups_dot_views_dot_PermissionGroupCreate_dot_3930588328": { - "string": "Permission group created" + "string": "Groupe de permissions crÊÊ" }, "src_dot_permissionGroups_dot_views_dot_PermissionGroupDetails_dot_870815507": { "context": "button title", "string": "DÊsassigner" }, "src_dot_permissionGroups_dot_views_dot_PermissionGroupList_dot_92979760": { - "string": "Permission Group Deleted" + "string": "Groupe de permission supprimÊ" }, "src_dot_plugins": { "context": "plugins section name", @@ -3611,27 +3627,24 @@ }, "src_dot_products_dot_components_dot_ProductStocks_dot_2622674857": { "context": "tabel column header", - "string": "Warehouse Name" + "string": "Nom de l'entrepôt" }, "src_dot_products_dot_components_dot_ProductStocks_dot_2729628316": { "context": "tabel column header", - "string": "Quantity Available" + "string": "QuantitÊ disponible" }, "src_dot_products_dot_components_dot_ProductStocks_dot_2796503714": { "context": "header", "string": "QuantitÊ" }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3143542809": { - "string": "This product doesn't have any stock. You can add it here." - }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3482985373": { - "context": "button", - "string": "Edit Warehouses" - }, "src_dot_products_dot_components_dot_ProductStocks_dot_3633706025": { "context": "product inventory, checkbox", "string": "Track Inventory" }, + "src_dot_products_dot_components_dot_ProductStocks_dot_3857433664": { + "context": "button", + "string": "Attribuer un entrepôt" + }, "src_dot_products_dot_components_dot_ProductStocks_dot_849869830": { "string": "Active inventory tracking will automatically calculate changes of stock" }, @@ -3675,19 +3688,19 @@ }, "src_dot_products_dot_components_dot_ProductVariantCreatorPage_dot_1808330403": { "context": "variant attribute", - "string": "Select Attribute" + "string": "SÊlectionnez un attribut" }, "src_dot_products_dot_components_dot_ProductVariantCreatorPage_dot_2002684673": { "context": "page title", - "string": "Price and SKUs" + "string": "Prix et UGS" }, "src_dot_products_dot_components_dot_ProductVariantCreatorPage_dot_2020618004": { "context": "variant stock, header", - "string": "Stock and Warehousing" + "string": "Stock et entreposage" }, "src_dot_products_dot_components_dot_ProductVariantCreatorPage_dot_2158649399": { "context": "product attribute values, page title", - "string": "Choose Values" + "string": "Choisissez des valeurs" }, "src_dot_products_dot_components_dot_ProductVariantCreatorPage_dot_2478977538": { "context": "attribute values, variant creation step", @@ -3721,7 +3734,7 @@ "string": "Here is the summary of variants that will be created. You can change prices, stocks an SKU for each one created." }, "src_dot_products_dot_components_dot_ProductVariantCreatorPage_dot_3896519183": { - "string": "Skip stock for now" + "string": "Ignorer le stock pour l'instant" }, "src_dot_products_dot_components_dot_ProductVariantCreatorPage_dot_4120989039": { "context": "create multiple variants, button", @@ -3729,7 +3742,7 @@ }, "src_dot_products_dot_components_dot_ProductVariantCreatorPage_dot_520980261": { "context": "variant creator summary card header", - "string": "Created Variants" + "string": "Variantes crÊÊes" }, "src_dot_products_dot_components_dot_ProductVariantCreatorPage_dot_551319747": { "string": "Based on your selections we will create {numberOfProducts} products. Use this step to customize price and stocks for your new products" @@ -3819,7 +3832,7 @@ }, "src_dot_products_dot_components_dot_ProductVariants_dot_1614793985": { "context": "variant stock status", - "string": "Available inventory at:" + "string": "Inventaire disponible à:" }, "src_dot_products_dot_components_dot_ProductVariants_dot_1721716102": { "context": "button", @@ -3838,7 +3851,7 @@ }, "src_dot_products_dot_components_dot_ProductVariants_dot_3203451491": { "context": "filtering option", - "string": "All Warehouses" + "string": "Tous les entrepôts" }, "src_dot_products_dot_components_dot_ProductVariants_dot_3490038570": { "context": "product variant inventory status", @@ -3850,7 +3863,7 @@ }, "src_dot_products_dot_components_dot_ProductVariants_dot_4017567521": { "context": "product variant inventory", - "string": "Not stocked" + "string": "non stockÊ" }, "src_dot_products_dot_components_dot_ProductVariants_dot_693960049": { "string": "UGS (UnitÊ de Gestion de Stock)" @@ -3859,13 +3872,6 @@ "context": "product variant name", "string": "Variation" }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_3482985373": { - "context": "dialog header", - "string": "Edit Warehouses" - }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_4112406382": { - "string": "Select warehouses that stock selected product" - }, "src_dot_products_dot_views_dot_1542417144": { "context": "window title", "string": "CrÊer produit" @@ -3952,7 +3958,7 @@ }, "src_dot_products_dot_views_dot_ProductVariantCreator_dot_830692292": { "context": "window title", - "string": "Create Variants" + "string": "CrÊer une variante" }, "src_dot_properties": { "string": "PropriÊtÊs" @@ -3962,11 +3968,11 @@ }, "src_dot_readyToCapture": { "context": "order status", - "string": "Ready to capture" + "string": "PrÃĒt à capturer" }, "src_dot_readyToFulfill": { "context": "order status", - "string": "Ready to fulfill" + "string": "PrÃĒt à traitÊe" }, "src_dot_refunded": { "context": "payment status", @@ -4147,6 +4153,9 @@ "context": "window title", "string": "CrÊer un compte service" }, + "src_dot_sessionExpired": { + "string": "Your session has expired. Please log in again to continue." + }, "src_dot_shipping": { "context": "shipping section name", "string": "MÊthodes de livraison" @@ -4158,11 +4167,11 @@ "string": "UnitÊ du poids de la livraison " }, "src_dot_shipping_dot_components_dot_ShippingZoneAddWarehouseDialog_dot_2622674857": { - "string": "Warehouse Name" + "string": "Nom de l'entrepôt" }, "src_dot_shipping_dot_components_dot_ShippingZoneAddWarehouseDialog_dot_3173942020": { "context": "header, dialog", - "string": "Create New Warehouse" + "string": "CrÊer un nouvel entrepôt" }, "src_dot_shipping_dot_components_dot_ShippingZoneCountriesAssignDialog_dot_1003092716": { "string": "Le reste du monde" @@ -4336,18 +4345,18 @@ }, "src_dot_shipping_dot_components_dot_ShippingZoneWarehouses_dot_1221560277": { "context": "section header", - "string": "Warehouse" + "string": "Entrepôt" }, "src_dot_shipping_dot_components_dot_ShippingZoneWarehouses_dot_2304484478": { "context": "button", - "string": "Add New Warehouse" + "string": "Ajouter un nouvel entrepôt" }, "src_dot_shipping_dot_components_dot_ShippingZoneWarehouses_dot_3852102652": { "string": "Select warehouse from which you will ship products for this shipping zone. This warehouse address will also be used to calculate taxes." }, "src_dot_shipping_dot_components_dot_ShippingZoneWarehouses_dot_46197273": { "context": "input placeholder", - "string": "Select Warehouse" + "string": "SÊlectionner un entrepôt" }, "src_dot_shipping_dot_components_dot_ShippingZonesListPage_dot_1325966144": { "context": "header", @@ -5031,7 +5040,7 @@ "string": "Authorization key with this type already exists" }, "src_dot_utils_dot_errors_dot_assignNonStaffMember": { - "string": "Only staff members can be assigned" + "string": "Seuls les membres du personnel peuvent ÃĒtre affectÊs" }, "src_dot_utils_dot_errors_dot_attributeAlreadyAssigned": { "string": "This attribute has already been assigned to this product type" @@ -5044,7 +5053,7 @@ }, "src_dot_utils_dot_errors_dot_billingNotSet": { "context": "error message", - "string": "Billing address is not set" + "string": "L'adresse de facturation n'est pas dÊfinie" }, "src_dot_utils_dot_errors_dot_cannotCancelFulfillment": { "context": "error message", @@ -5080,10 +5089,10 @@ "string": "API error" }, "src_dot_utils_dot_errors_dot_invalid": { - "string": "Invalid value" + "string": "Valeur invalide" }, "src_dot_utils_dot_errors_dot_invalidPassword": { - "string": "Invalid password" + "string": "Mot de passe incorrect" }, "src_dot_utils_dot_errors_dot_noShippingAddress": { "context": "error message", @@ -5119,29 +5128,29 @@ }, "src_dot_utils_dot_errors_dot_skuUnique": { "context": "bulk variant create error", - "string": "SKUs must be unique" + "string": "Les UGSs doivent ÃĒtre uniques" }, "src_dot_utils_dot_errors_dot_slugUnique": { "context": "error message", - "string": "Slug must be unique for each warehouse" + "string": "Le slug doit ÃĒtre unique pour chaque entrepôt" }, "src_dot_utils_dot_errors_dot_tooCommon": { - "string": "This password is too commonly used" + "string": "Ce mot de passe est trop couramment utilisÊ" }, "src_dot_utils_dot_errors_dot_tooShort": { - "string": "This password is too short" + "string": "Ce mot de passe est trop court" }, "src_dot_utils_dot_errors_dot_tooSimilar": { - "string": "These passwords are too similar" + "string": "Ces mots de passe sont trop similaires" }, "src_dot_utils_dot_errors_dot_unique": { - "string": "This needs to be unique" + "string": "Cela doit ÃĒtre unique" }, "src_dot_utils_dot_errors_dot_unknownError": { - "string": "Unknown error" + "string": "Erreur inconnue" }, "src_dot_utils_dot_errors_dot_variantNoDigitalContent": { - "string": "This variant does not have any digital content" + "string": "Cette variante n'a pas de contenu numÊrique" }, "src_dot_vouchers": { "context": "vouchers section name", @@ -5149,7 +5158,7 @@ }, "src_dot_warehouses": { "context": "warehouses section name", - "string": "Warehouses" + "string": "Entrepôts" }, "src_dot_warehouses_dot_components_dot_WarehouseCreatePage_dot_1967111456": { "context": "warehouse", @@ -5157,39 +5166,39 @@ }, "src_dot_warehouses_dot_components_dot_WarehouseCreatePage_dot_934572530": { "context": "header", - "string": "Create Warehouse" + "string": "CrÊer un entrepôt" }, "src_dot_warehouses_dot_components_dot_WarehouseDeleteDialog_dot_1355303260": { "context": "dialog content", - "string": "Are you sure you want to delete {warehouseName}?" + "string": "Etes-vous sÃģr que vous voulez supprimer {warehouseName}?" }, "src_dot_warehouses_dot_components_dot_WarehouseDeleteDialog_dot_3857661071": { "context": "dialog title", - "string": "Delete Warehouse" + "string": "Supprimer l'entrepôt" }, "src_dot_warehouses_dot_components_dot_WarehouseDetailsPage_dot_1967111456": { "context": "warehouse", "string": "Informations d'adresse" }, "src_dot_warehouses_dot_components_dot_WarehouseInfo_dot_2622674857": { - "string": "Warehouse Name" + "string": "Nom de l'entrepôt" }, "src_dot_warehouses_dot_components_dot_WarehouseListPage_dot_2304765290": { - "string": "Search Warehouse" + "string": "Rechercher entrepôt" }, "src_dot_warehouses_dot_components_dot_WarehouseListPage_dot_3203451491": { "context": "tab name", - "string": "All Warehouses" + "string": "Tous les entrepôts" }, "src_dot_warehouses_dot_components_dot_WarehouseListPage_dot_934572530": { "context": "button", - "string": "Create Warehouse" + "string": "CrÊer un entrepôt" }, "src_dot_warehouses_dot_components_dot_WarehouseList_dot_1225932315": { - "string": "Shipping Zones" + "string": "Zones d'expÊdition" }, "src_dot_warehouses_dot_components_dot_WarehouseList_dot_3787396469": { - "string": "No warehouses found" + "string": "Aucun entrepôt trouvÊ" }, "src_dot_warehouses_dot_components_dot_WarehouseList_dot_4190792473": { "string": "Actions" @@ -5200,14 +5209,14 @@ }, "src_dot_warehouses_dot_components_dot_WarehouseZones_dot_1225932315": { "context": "zones that warehouse sends to", - "string": "Shipping Zones" + "string": "Zones d'expÊdition" }, "src_dot_warehouses_dot_components_dot_WarehouseZones_dot_2423245141": { - "string": "This warehouse has no shipping zones assigned." + "string": "Cet entrepôt n'a aucune zone de livraison assignÊe." }, "src_dot_warehouses_dot_views_dot_WarehouseCreate_dot_934572530": { "context": "header", - "string": "Create Warehouse" + "string": "CrÊer un entrepôt" }, "src_dot_webhooks": { "context": "webhooks section name", @@ -5219,7 +5228,7 @@ }, "src_dot_webhooks_dot_components_dot_WebhookDeleteDialog_dot_216945727": { "context": "delete webhook", - "string": "Are you sure you want to delete this webhook?" + "string": "Voulez-vous vraiment supprimer ce webhook?" }, "src_dot_webhooks_dot_components_dot_WebhookDeleteDialog_dot_2297471173": { "context": "delete webhook", @@ -5322,7 +5331,7 @@ }, "src_dot_webhooks_dot_components_dot_WebhooksDetailsPage_dot_1595053355": { "context": "header", - "string": "Unnamed Webhook Details" + "string": "DÊtails du Webhook sans nom" }, "src_dot_webhooks_dot_components_dot_WebhooksDetailsPage_dot_408706360": { "context": "header", @@ -5359,7 +5368,7 @@ "string": "Action" }, "src_dot_webhooks_dot_components_dot_WebhooksList_dot_618422799": { - "string": "Unnamed webhook" + "string": "Webhook sans nom" }, "src_dot_webhooks_dot_components_dot_WebhooksList_dot_636461959": { "context": "webhook name", diff --git a/locale/hi.json b/locale/hi.json index a5e250f1a..f3f077b97 100644 --- a/locale/hi.json +++ b/locale/hi.json @@ -250,7 +250,7 @@ "context": "optional field", "string": "Optional" }, - "productVariantPriceOptionalPriceOverrideField": { + "productVariantPriceOptionalPriceField": { "context": "optional field", "string": "Optional" }, @@ -1675,6 +1675,10 @@ "context": "button", "string": "Delete" }, + "src_dot_demo": { + "context": "notification message after log in", + "string": "Just to let you know... You're in demo mode. You can play around with the dashboard but can't save changes." + }, "src_dot_description": { "string": "ā¤ĩ⤰āĨā¤Ŗā¤¨" }, @@ -2532,6 +2536,10 @@ "context": "cancelled fulfillment, section header", "string": "Cancelled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderFulfillment_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderFulfillment_dot_732594284": { "context": "button", "string": "Cancel Fulfillment" @@ -2749,6 +2757,10 @@ "context": "order payment", "string": "Outstanding Balance" }, + "src_dot_orders_dot_components_dot_OrderPayment_dot_3720114122": { + "context": "order discount", + "string": "Discount" + }, "src_dot_orders_dot_components_dot_OrderPayment_dot_3768782744": { "context": "order payment", "string": "Preauthorized amount" @@ -2768,10 +2780,6 @@ "context": "order total price", "string": "Total" }, - "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_1542417144": { - "context": "dialog header", - "string": "Create Product" - }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2272209368": { "context": "variant sku", "string": "SKU {sku}" @@ -2779,6 +2787,10 @@ "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2336947364": { "string": "Search by product name, attribute, product type etc..." }, + "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2775402904": { + "context": "dialog header", + "string": "Add Product" + }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2850255786": { "string": "Search Products" }, @@ -2809,6 +2821,10 @@ "context": "section header", "string": "Unfulfilled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_878013594": { "context": "order line total price", "string": "Total" @@ -3621,17 +3637,14 @@ "context": "header", "string": "ā¤Žā¤žā¤¤āĨā¤°ā¤ž" }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3143542809": { - "string": "This product doesn't have any stock. You can add it here." - }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3482985373": { - "context": "button", - "string": "Edit Warehouses" - }, "src_dot_products_dot_components_dot_ProductStocks_dot_3633706025": { "context": "product inventory, checkbox", "string": "Track Inventory" }, + "src_dot_products_dot_components_dot_ProductStocks_dot_3857433664": { + "context": "button", + "string": "Assign Warehouse" + }, "src_dot_products_dot_components_dot_ProductStocks_dot_849869830": { "string": "Active inventory tracking will automatically calculate changes of stock" }, @@ -3859,13 +3872,6 @@ "context": "product variant name", "string": "ā¤ĒāĨā¤°ā¤•ā¤žā¤°" }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_3482985373": { - "context": "dialog header", - "string": "Edit Warehouses" - }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_4112406382": { - "string": "Select warehouses that stock selected product" - }, "src_dot_products_dot_views_dot_1542417144": { "context": "window title", "string": "Create Product" @@ -4147,6 +4153,9 @@ "context": "window title", "string": "Create Service Account" }, + "src_dot_sessionExpired": { + "string": "Your session has expired. Please log in again to continue." + }, "src_dot_shipping": { "context": "shipping section name", "string": "Shipping Methods" diff --git a/locale/hu.json b/locale/hu.json index 3c290d844..10727d259 100644 --- a/locale/hu.json +++ b/locale/hu.json @@ -250,7 +250,7 @@ "context": "optional field", "string": "Optional" }, - "productVariantPriceOptionalPriceOverrideField": { + "productVariantPriceOptionalPriceField": { "context": "optional field", "string": "Optional" }, @@ -1675,6 +1675,10 @@ "context": "button", "string": "Delete" }, + "src_dot_demo": { + "context": "notification message after log in", + "string": "Just to let you know... You're in demo mode. You can play around with the dashboard but can't save changes." + }, "src_dot_description": { "string": "LeírÃĄs" }, @@ -2532,6 +2536,10 @@ "context": "cancelled fulfillment, section header", "string": "Cancelled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderFulfillment_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderFulfillment_dot_732594284": { "context": "button", "string": "TeljesítÊs elvetÊse" @@ -2749,6 +2757,10 @@ "context": "order payment", "string": "Outstanding Balance" }, + "src_dot_orders_dot_components_dot_OrderPayment_dot_3720114122": { + "context": "order discount", + "string": "KedvezmÊny" + }, "src_dot_orders_dot_components_dot_OrderPayment_dot_3768782744": { "context": "order payment", "string": "Előzetesen jÃŗvÃĄhagyott Ãļsszeg" @@ -2768,10 +2780,6 @@ "context": "order total price", "string": "Összesen" }, - "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_1542417144": { - "context": "dialog header", - "string": "Create Product" - }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2272209368": { "context": "variant sku", "string": "SKU {sku}" @@ -2779,6 +2787,10 @@ "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2336947364": { "string": "Search by product name, attribute, product type etc..." }, + "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2775402904": { + "context": "dialog header", + "string": "Add Product" + }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2850255786": { "string": "Search Products" }, @@ -2809,6 +2821,10 @@ "context": "section header", "string": "Unfulfilled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_878013594": { "context": "order line total price", "string": "Összesen" @@ -3621,17 +3637,14 @@ "context": "header", "string": "MennyisÊg" }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3143542809": { - "string": "This product doesn't have any stock. You can add it here." - }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3482985373": { - "context": "button", - "string": "Edit Warehouses" - }, "src_dot_products_dot_components_dot_ProductStocks_dot_3633706025": { "context": "product inventory, checkbox", "string": "Track Inventory" }, + "src_dot_products_dot_components_dot_ProductStocks_dot_3857433664": { + "context": "button", + "string": "Assign Warehouse" + }, "src_dot_products_dot_components_dot_ProductStocks_dot_849869830": { "string": "Active inventory tracking will automatically calculate changes of stock" }, @@ -3859,13 +3872,6 @@ "context": "product variant name", "string": "VÃĄltozat" }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_3482985373": { - "context": "dialog header", - "string": "Edit Warehouses" - }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_4112406382": { - "string": "Select warehouses that stock selected product" - }, "src_dot_products_dot_views_dot_1542417144": { "context": "window title", "string": "Create Product" @@ -4147,6 +4153,9 @@ "context": "window title", "string": "Create Service Account" }, + "src_dot_sessionExpired": { + "string": "Your session has expired. Please log in again to continue." + }, "src_dot_shipping": { "context": "shipping section name", "string": "Shipping Methods" diff --git a/locale/hy.json b/locale/hy.json index a29ff02d0..2e8dbb7d8 100644 --- a/locale/hy.json +++ b/locale/hy.json @@ -250,7 +250,7 @@ "context": "optional field", "string": "Optional" }, - "productVariantPriceOptionalPriceOverrideField": { + "productVariantPriceOptionalPriceField": { "context": "optional field", "string": "Optional" }, @@ -1675,6 +1675,10 @@ "context": "button", "string": "Delete" }, + "src_dot_demo": { + "context": "notification message after log in", + "string": "Just to let you know... You're in demo mode. You can play around with the dashboard but can't save changes." + }, "src_dot_description": { "string": "Õ†Õ¯ÕĄÖ€ÕĄÕŖÖ€Õ¸Ö‚ÕŠÕĩուÕļ" }, @@ -2532,6 +2536,10 @@ "context": "cancelled fulfillment, section header", "string": "Cancelled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderFulfillment_dot_693960049": { + "context": "ordered product sku", + "string": "ՊՊՄ" + }, "src_dot_orders_dot_components_dot_OrderFulfillment_dot_732594284": { "context": "button", "string": "Cancel Fulfillment" @@ -2749,6 +2757,10 @@ "context": "order payment", "string": "Outstanding Balance" }, + "src_dot_orders_dot_components_dot_OrderPayment_dot_3720114122": { + "context": "order discount", + "string": "Discount" + }, "src_dot_orders_dot_components_dot_OrderPayment_dot_3768782744": { "context": "order payment", "string": "Preauthorized amount" @@ -2768,10 +2780,6 @@ "context": "order total price", "string": "Ô¸ÕļÕ¤Õ°ÕĄÕļուր" }, - "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_1542417144": { - "context": "dialog header", - "string": "Create Product" - }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2272209368": { "context": "variant sku", "string": "SKU {sku}" @@ -2779,6 +2787,10 @@ "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2336947364": { "string": "Search by product name, attribute, product type etc..." }, + "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2775402904": { + "context": "dialog header", + "string": "Add Product" + }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2850255786": { "string": "Search Products" }, @@ -2809,6 +2821,10 @@ "context": "section header", "string": "Unfulfilled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_693960049": { + "context": "ordered product sku", + "string": "ՊՊՄ" + }, "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_878013594": { "context": "order line total price", "string": "Ô¸ÕļÕ¤Õ°ÕĄÕļուր" @@ -3621,17 +3637,14 @@ "context": "header", "string": "Õ”ÕĄÕļÕĄÕ¯" }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3143542809": { - "string": "This product doesn't have any stock. You can add it here." - }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3482985373": { - "context": "button", - "string": "Edit Warehouses" - }, "src_dot_products_dot_components_dot_ProductStocks_dot_3633706025": { "context": "product inventory, checkbox", "string": "Track Inventory" }, + "src_dot_products_dot_components_dot_ProductStocks_dot_3857433664": { + "context": "button", + "string": "Assign Warehouse" + }, "src_dot_products_dot_components_dot_ProductStocks_dot_849869830": { "string": "Active inventory tracking will automatically calculate changes of stock" }, @@ -3859,13 +3872,6 @@ "context": "product variant name", "string": "ÕÕĄÖ€ÕĸÕĨÖ€ÕĄÕ¯" }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_3482985373": { - "context": "dialog header", - "string": "Edit Warehouses" - }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_4112406382": { - "string": "Select warehouses that stock selected product" - }, "src_dot_products_dot_views_dot_1542417144": { "context": "window title", "string": "Create Product" @@ -4147,6 +4153,9 @@ "context": "window title", "string": "Create Service Account" }, + "src_dot_sessionExpired": { + "string": "Your session has expired. Please log in again to continue." + }, "src_dot_shipping": { "context": "shipping section name", "string": "Shipping Methods" diff --git a/locale/id.json b/locale/id.json index 5779b301b..754fcf819 100644 --- a/locale/id.json +++ b/locale/id.json @@ -250,7 +250,7 @@ "context": "optional field", "string": "Optional" }, - "productVariantPriceOptionalPriceOverrideField": { + "productVariantPriceOptionalPriceField": { "context": "optional field", "string": "Optional" }, @@ -1675,6 +1675,10 @@ "context": "button", "string": "Delete" }, + "src_dot_demo": { + "context": "notification message after log in", + "string": "Just to let you know... You're in demo mode. You can play around with the dashboard but can't save changes." + }, "src_dot_description": { "string": "Deskripsi" }, @@ -2532,6 +2536,10 @@ "context": "cancelled fulfillment, section header", "string": "Cancelled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderFulfillment_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderFulfillment_dot_732594284": { "context": "button", "string": "Batalkan Pemenuhan" @@ -2749,6 +2757,10 @@ "context": "order payment", "string": "Outstanding Balance" }, + "src_dot_orders_dot_components_dot_OrderPayment_dot_3720114122": { + "context": "order discount", + "string": "Diskon" + }, "src_dot_orders_dot_components_dot_OrderPayment_dot_3768782744": { "context": "order payment", "string": "Jumlah yang diotorisasi" @@ -2768,10 +2780,6 @@ "context": "order total price", "string": "Total" }, - "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_1542417144": { - "context": "dialog header", - "string": "Create Product" - }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2272209368": { "context": "variant sku", "string": "SKU {sku}" @@ -2779,6 +2787,10 @@ "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2336947364": { "string": "Search by product name, attribute, product type etc..." }, + "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2775402904": { + "context": "dialog header", + "string": "Add Product" + }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2850255786": { "string": "Search Products" }, @@ -2809,6 +2821,10 @@ "context": "section header", "string": "Unfulfilled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_878013594": { "context": "order line total price", "string": "Total" @@ -3621,17 +3637,14 @@ "context": "header", "string": "Jumlah" }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3143542809": { - "string": "This product doesn't have any stock. You can add it here." - }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3482985373": { - "context": "button", - "string": "Edit Warehouses" - }, "src_dot_products_dot_components_dot_ProductStocks_dot_3633706025": { "context": "product inventory, checkbox", "string": "Track Inventory" }, + "src_dot_products_dot_components_dot_ProductStocks_dot_3857433664": { + "context": "button", + "string": "Assign Warehouse" + }, "src_dot_products_dot_components_dot_ProductStocks_dot_849869830": { "string": "Active inventory tracking will automatically calculate changes of stock" }, @@ -3859,13 +3872,6 @@ "context": "product variant name", "string": "Variasi" }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_3482985373": { - "context": "dialog header", - "string": "Edit Warehouses" - }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_4112406382": { - "string": "Select warehouses that stock selected product" - }, "src_dot_products_dot_views_dot_1542417144": { "context": "window title", "string": "Create Product" @@ -4147,6 +4153,9 @@ "context": "window title", "string": "Create Service Account" }, + "src_dot_sessionExpired": { + "string": "Your session has expired. Please log in again to continue." + }, "src_dot_shipping": { "context": "shipping section name", "string": "Shipping Methods" diff --git a/locale/is.json b/locale/is.json index cd6e0a130..8b30ddafa 100644 --- a/locale/is.json +++ b/locale/is.json @@ -250,7 +250,7 @@ "context": "optional field", "string": "Optional" }, - "productVariantPriceOptionalPriceOverrideField": { + "productVariantPriceOptionalPriceField": { "context": "optional field", "string": "Optional" }, @@ -1675,6 +1675,10 @@ "context": "button", "string": "Delete" }, + "src_dot_demo": { + "context": "notification message after log in", + "string": "Just to let you know... You're in demo mode. You can play around with the dashboard but can't save changes." + }, "src_dot_description": { "string": "LÃŊsing" }, @@ -2532,6 +2536,10 @@ "context": "cancelled fulfillment, section header", "string": "Cancelled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderFulfillment_dot_693960049": { + "context": "ordered product sku", + "string": "VN" + }, "src_dot_orders_dot_components_dot_OrderFulfillment_dot_732594284": { "context": "button", "string": "Cancel Fulfillment" @@ -2749,6 +2757,10 @@ "context": "order payment", "string": "Outstanding Balance" }, + "src_dot_orders_dot_components_dot_OrderPayment_dot_3720114122": { + "context": "order discount", + "string": "AfslÃĄttur" + }, "src_dot_orders_dot_components_dot_OrderPayment_dot_3768782744": { "context": "order payment", "string": "Preauthorized amount" @@ -2768,10 +2780,6 @@ "context": "order total price", "string": "Samtals" }, - "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_1542417144": { - "context": "dialog header", - "string": "Create Product" - }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2272209368": { "context": "variant sku", "string": "SKU {sku}" @@ -2779,6 +2787,10 @@ "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2336947364": { "string": "Search by product name, attribute, product type etc..." }, + "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2775402904": { + "context": "dialog header", + "string": "Add Product" + }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2850255786": { "string": "Search Products" }, @@ -2809,6 +2821,10 @@ "context": "section header", "string": "Unfulfilled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_693960049": { + "context": "ordered product sku", + "string": "VN" + }, "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_878013594": { "context": "order line total price", "string": "Samtals" @@ -3621,17 +3637,14 @@ "context": "header", "string": "Magn" }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3143542809": { - "string": "This product doesn't have any stock. You can add it here." - }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3482985373": { - "context": "button", - "string": "Edit Warehouses" - }, "src_dot_products_dot_components_dot_ProductStocks_dot_3633706025": { "context": "product inventory, checkbox", "string": "Track Inventory" }, + "src_dot_products_dot_components_dot_ProductStocks_dot_3857433664": { + "context": "button", + "string": "Assign Warehouse" + }, "src_dot_products_dot_components_dot_ProductStocks_dot_849869830": { "string": "Active inventory tracking will automatically calculate changes of stock" }, @@ -3859,13 +3872,6 @@ "context": "product variant name", "string": "Afbrigði" }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_3482985373": { - "context": "dialog header", - "string": "Edit Warehouses" - }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_4112406382": { - "string": "Select warehouses that stock selected product" - }, "src_dot_products_dot_views_dot_1542417144": { "context": "window title", "string": "Create Product" @@ -4147,6 +4153,9 @@ "context": "window title", "string": "Create Service Account" }, + "src_dot_sessionExpired": { + "string": "Your session has expired. Please log in again to continue." + }, "src_dot_shipping": { "context": "shipping section name", "string": "Shipping Methods" diff --git a/locale/it.json b/locale/it.json index 57e9cd47d..26effc63a 100644 --- a/locale/it.json +++ b/locale/it.json @@ -250,7 +250,7 @@ "context": "optional field", "string": "Facoltativo" }, - "productVariantPriceOptionalPriceOverrideField": { + "productVariantPriceOptionalPriceField": { "context": "optional field", "string": "Facoltativo" }, @@ -1675,6 +1675,10 @@ "context": "button", "string": "Elimina" }, + "src_dot_demo": { + "context": "notification message after log in", + "string": "Just to let you know... You're in demo mode. You can play around with the dashboard but can't save changes." + }, "src_dot_description": { "string": "Descrizione" }, @@ -2532,6 +2536,10 @@ "context": "cancelled fulfillment, section header", "string": "Cancelled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderFulfillment_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderFulfillment_dot_732594284": { "context": "button", "string": "Annulla evasione " @@ -2749,6 +2757,10 @@ "context": "order payment", "string": "Saldo in sospeso" }, + "src_dot_orders_dot_components_dot_OrderPayment_dot_3720114122": { + "context": "order discount", + "string": "Sconto" + }, "src_dot_orders_dot_components_dot_OrderPayment_dot_3768782744": { "context": "order payment", "string": "Importo pre-autorizzato" @@ -2768,10 +2780,6 @@ "context": "order total price", "string": "Totale" }, - "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_1542417144": { - "context": "dialog header", - "string": "Crea Prodotto" - }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2272209368": { "context": "variant sku", "string": "SKU {sku}" @@ -2779,6 +2787,10 @@ "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2336947364": { "string": "Cerca per nome prodotto, attributo, tipologia di prodotto, etc..." }, + "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2775402904": { + "context": "dialog header", + "string": "Add Product" + }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2850255786": { "string": "Cerca Prodotti" }, @@ -2809,6 +2821,10 @@ "context": "section header", "string": "Non evasi ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_878013594": { "context": "order line total price", "string": "Totale" @@ -3621,17 +3637,14 @@ "context": "header", "string": "Quantità" }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3143542809": { - "string": "This product doesn't have any stock. You can add it here." - }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3482985373": { - "context": "button", - "string": "Edit Warehouses" - }, "src_dot_products_dot_components_dot_ProductStocks_dot_3633706025": { "context": "product inventory, checkbox", "string": "Track Inventory" }, + "src_dot_products_dot_components_dot_ProductStocks_dot_3857433664": { + "context": "button", + "string": "Assign Warehouse" + }, "src_dot_products_dot_components_dot_ProductStocks_dot_849869830": { "string": "Active inventory tracking will automatically calculate changes of stock" }, @@ -3859,13 +3872,6 @@ "context": "product variant name", "string": "Variante" }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_3482985373": { - "context": "dialog header", - "string": "Edit Warehouses" - }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_4112406382": { - "string": "Select warehouses that stock selected product" - }, "src_dot_products_dot_views_dot_1542417144": { "context": "window title", "string": "Crea Prodotto" @@ -4147,6 +4153,9 @@ "context": "window title", "string": "Crea Account Servizio" }, + "src_dot_sessionExpired": { + "string": "Your session has expired. Please log in again to continue." + }, "src_dot_shipping": { "context": "shipping section name", "string": "Metodi di Spedizione" diff --git a/locale/ja.json b/locale/ja.json index 90538e721..1d92e4889 100644 --- a/locale/ja.json +++ b/locale/ja.json @@ -250,7 +250,7 @@ "context": "optional field", "string": "Optional" }, - "productVariantPriceOptionalPriceOverrideField": { + "productVariantPriceOptionalPriceField": { "context": "optional field", "string": "Optional" }, @@ -1675,6 +1675,10 @@ "context": "button", "string": "Delete" }, + "src_dot_demo": { + "context": "notification message after log in", + "string": "Just to let you know... You're in demo mode. You can play around with the dashboard but can't save changes." + }, "src_dot_description": { "string": "čĒŦ明" }, @@ -2532,6 +2536,10 @@ "context": "cancelled fulfillment, section header", "string": "Cancelled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderFulfillment_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderFulfillment_dot_732594284": { "context": "button", "string": "Cancel Fulfillment" @@ -2749,6 +2757,10 @@ "context": "order payment", "string": "Outstanding Balance" }, + "src_dot_orders_dot_components_dot_OrderPayment_dot_3720114122": { + "context": "order discount", + "string": "剞åŧ•" + }, "src_dot_orders_dot_components_dot_OrderPayment_dot_3768782744": { "context": "order payment", "string": "Preauthorized amount" @@ -2768,10 +2780,6 @@ "context": "order total price", "string": "合荈" }, - "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_1542417144": { - "context": "dialog header", - "string": "Create Product" - }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2272209368": { "context": "variant sku", "string": "SKU {sku}" @@ -2779,6 +2787,10 @@ "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2336947364": { "string": "Search by product name, attribute, product type etc..." }, + "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2775402904": { + "context": "dialog header", + "string": "Add Product" + }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2850255786": { "string": "Search Products" }, @@ -2809,6 +2821,10 @@ "context": "section header", "string": "Unfulfilled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_878013594": { "context": "order line total price", "string": "合荈" @@ -3621,17 +3637,14 @@ "context": "header", "string": "数量" }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3143542809": { - "string": "This product doesn't have any stock. You can add it here." - }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3482985373": { - "context": "button", - "string": "Edit Warehouses" - }, "src_dot_products_dot_components_dot_ProductStocks_dot_3633706025": { "context": "product inventory, checkbox", "string": "Track Inventory" }, + "src_dot_products_dot_components_dot_ProductStocks_dot_3857433664": { + "context": "button", + "string": "Assign Warehouse" + }, "src_dot_products_dot_components_dot_ProductStocks_dot_849869830": { "string": "Active inventory tracking will automatically calculate changes of stock" }, @@ -3859,13 +3872,6 @@ "context": "product variant name", "string": "Variant" }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_3482985373": { - "context": "dialog header", - "string": "Edit Warehouses" - }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_4112406382": { - "string": "Select warehouses that stock selected product" - }, "src_dot_products_dot_views_dot_1542417144": { "context": "window title", "string": "Create Product" @@ -4147,6 +4153,9 @@ "context": "window title", "string": "Create Service Account" }, + "src_dot_sessionExpired": { + "string": "Your session has expired. Please log in again to continue." + }, "src_dot_shipping": { "context": "shipping section name", "string": "Shipping Methods" diff --git a/locale/ko.json b/locale/ko.json index 424004e93..bbe560655 100644 --- a/locale/ko.json +++ b/locale/ko.json @@ -250,7 +250,7 @@ "context": "optional field", "string": "Optional" }, - "productVariantPriceOptionalPriceOverrideField": { + "productVariantPriceOptionalPriceField": { "context": "optional field", "string": "Optional" }, @@ -1675,6 +1675,10 @@ "context": "button", "string": "ė‚­ė œ" }, + "src_dot_demo": { + "context": "notification message after log in", + "string": "Just to let you know... You're in demo mode. You can play around with the dashboard but can't save changes." + }, "src_dot_description": { "string": "네ëĒ…" }, @@ -2532,6 +2536,10 @@ "context": "cancelled fulfillment, section header", "string": "Cancelled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderFulfillment_dot_693960049": { + "context": "ordered product sku", + "string": "ėžŦęŗ  관ëĻŦ ėŊ”드" + }, "src_dot_orders_dot_components_dot_OrderFulfillment_dot_732594284": { "context": "button", "string": "Cancel Fulfillment" @@ -2749,6 +2757,10 @@ "context": "order payment", "string": "Outstanding Balance" }, + "src_dot_orders_dot_components_dot_OrderPayment_dot_3720114122": { + "context": "order discount", + "string": "í• ė¸" + }, "src_dot_orders_dot_components_dot_OrderPayment_dot_3768782744": { "context": "order payment", "string": "ė‚Ŧė „ėŠšė¸ëœ ę¸ˆė•Ą" @@ -2768,10 +2780,6 @@ "context": "order total price", "string": "í•Šęŗ„" }, - "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_1542417144": { - "context": "dialog header", - "string": "Create Product" - }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2272209368": { "context": "variant sku", "string": "SKU {sku}" @@ -2779,6 +2787,10 @@ "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2336947364": { "string": "Search by product name, attribute, product type etc..." }, + "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2775402904": { + "context": "dialog header", + "string": "Add Product" + }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2850255786": { "string": "Search Products" }, @@ -2809,6 +2821,10 @@ "context": "section header", "string": "Unfulfilled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_693960049": { + "context": "ordered product sku", + "string": "ėžŦęŗ  관ëĻŦ ėŊ”드" + }, "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_878013594": { "context": "order line total price", "string": "í•Šęŗ„" @@ -3621,17 +3637,14 @@ "context": "header", "string": "ėˆ˜ëŸ‰" }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3143542809": { - "string": "This product doesn't have any stock. You can add it here." - }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3482985373": { - "context": "button", - "string": "Edit Warehouses" - }, "src_dot_products_dot_components_dot_ProductStocks_dot_3633706025": { "context": "product inventory, checkbox", "string": "Track Inventory" }, + "src_dot_products_dot_components_dot_ProductStocks_dot_3857433664": { + "context": "button", + "string": "Assign Warehouse" + }, "src_dot_products_dot_components_dot_ProductStocks_dot_849869830": { "string": "Active inventory tracking will automatically calculate changes of stock" }, @@ -3859,13 +3872,6 @@ "context": "product variant name", "string": "ė˜ĩė…˜" }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_3482985373": { - "context": "dialog header", - "string": "Edit Warehouses" - }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_4112406382": { - "string": "Select warehouses that stock selected product" - }, "src_dot_products_dot_views_dot_1542417144": { "context": "window title", "string": "Create Product" @@ -4147,6 +4153,9 @@ "context": "window title", "string": "Create Service Account" }, + "src_dot_sessionExpired": { + "string": "Your session has expired. Please log in again to continue." + }, "src_dot_shipping": { "context": "shipping section name", "string": "Shipping Methods" diff --git a/locale/mn.json b/locale/mn.json index 974a80f3e..3c8a27d8e 100644 --- a/locale/mn.json +++ b/locale/mn.json @@ -250,7 +250,7 @@ "context": "optional field", "string": "ЗааваĐģ ĐąĐ¸Ņˆ" }, - "productVariantPriceOptionalPriceOverrideField": { + "productVariantPriceOptionalPriceField": { "context": "optional field", "string": "ЗааваĐģ ĐąĐ¸Ņˆ" }, @@ -292,7 +292,7 @@ }, "siteSettingsMailingHelperText": { "context": "helper text", - "string": "Mailing Configuration" + "string": "ИĐŧŅĐšĐģиКĐŊ Ņ‚ĐžŅ…Đ¸Ņ€ĐŗĐžĐž" }, "src_dot_accept": { "context": "button", @@ -369,11 +369,11 @@ }, "src_dot_attributes_dot_components_dot_AttributeListPage_dot_filterableInDashboard": { "context": "use attribute in filtering", - "string": "Filterable in Dashboard" + "string": "Dashboard Đ´ŅŅŅ€ŅŅŅ ŅˆŌ¯Ō¯Ņ… йОĐģĐžĐŧĐļŅ‚ĐžĐš" }, "src_dot_attributes_dot_components_dot_AttributeListPage_dot_filterableInStorefront": { "context": "use attribute in filtering", - "string": "Filterable in Storefront" + "string": "Storefront Đ´ŅŅŅ€ŅŅŅ ŅˆŌ¯Ō¯Ņ… йОĐģĐžĐŧĐļŅ‚ĐžĐš" }, "src_dot_attributes_dot_components_dot_AttributeListPage_dot_isVariantOnly": { "context": "attribute can be used only in variants", @@ -1106,7 +1106,7 @@ "string": "ĐĨаКĐģŅ‚Ņ‹Đŗ Ņ…Đ°Đ´ĐŗĐ°ĐģĐ°Ņ…" }, "src_dot_components_dot_FilterCard_dot_996289613": { - "string": "Filters" + "string": "Đ¨Ō¯Ō¯Đģ҂ԝԝҀ" }, "src_dot_components_dot_Filter_dot_2332404293": { "context": "search", @@ -1129,11 +1129,11 @@ "string": "Ņ…ĐžĐžŅ€ĐžĐŊĐ´" }, "src_dot_components_dot_Filter_dot_996289613": { - "string": "Filters" + "string": "Đ¨Ō¯Ō¯Đģ҂ԝԝҀ" }, "src_dot_components_dot_ImageUpload_dot_1731007575": { "context": "image upload", - "string": "Drop here to upload" + "string": "Đ­ĐŊĐ´ Ņ„Đ°ĐšĐģаа Ņ…ŅƒŅƒĐģĐŊа ҃҃" }, "src_dot_components_dot_LanguageSwitch_dot_4150219184": { "context": "button", @@ -1609,7 +1609,7 @@ }, "src_dot_customers_dot_components_dot_CustomerOrders_dot_2889196282": { "context": "number of order", - "string": "No. of Order" + "string": "Đ—Đ°Ņ…Đ¸Đ°ĐģĐŗŅ‹ĐŊ Đ´ŅƒĐŗĐ°Đ°Ņ€" }, "src_dot_customers_dot_components_dot_CustomerOrders_dot_3029139173": { "context": "button", @@ -1675,6 +1675,10 @@ "context": "button", "string": "ĐŖŅŅ‚ĐŗĐ°Ņ…" }, + "src_dot_demo": { + "context": "notification message after log in", + "string": "Just to let you know... You're in demo mode. You can play around with the dashboard but can't save changes." + }, "src_dot_description": { "string": "ĐĸаКĐģĐąĐ°Ņ€" }, @@ -1912,11 +1916,11 @@ "string": "Код Ō¯Ō¯ŅĐŗŅŅ…" }, "src_dot_discounts_dot_components_dot_VoucherLimits_dot_2215544659": { - "string": "Limit number of times this discount can be used in total" + "string": "ĐĐ¸ĐšŅ‚ Đ°ŅˆĐ¸ĐŗĐģĐ°Ņ… йОĐģĐžĐŧĐļŅ‚ĐžĐš Ņ‚ĐžĐž" }, "src_dot_discounts_dot_components_dot_VoucherLimits_dot_3459612469": { "context": "limit voucher", - "string": "Limit to one use per customer" + "string": "1 Ņ…ŅŅ€ŅĐŗĐģŅĐŗŅ‡Đ¸ĐšĐŊ Đ°ŅˆĐ¸ĐŗĐģĐ°Ņ… Ņ…ŅĐˇĐŗĐ°Đ°Ņ€" }, "src_dot_discounts_dot_components_dot_VoucherLimits_dot_3751756157": { "context": "voucher usage limit, header", @@ -1924,7 +1928,7 @@ }, "src_dot_discounts_dot_components_dot_VoucherLimits_dot_557552777": { "context": "voucher", - "string": "Limit of Uses" + "string": "ĐŅˆĐ¸ĐŗĐģĐ°Ņ… Ņ…ŅĐˇĐŗĐ°Đ°Ņ€" }, "src_dot_discounts_dot_components_dot_VoucherListPage_dot_1112241061": { "context": "tab name", @@ -2162,7 +2166,7 @@ }, "src_dot_done": { "context": "button", - "string": "Done" + "string": "Đ”ŅƒŅƒŅŅĐ°ĐŊ" }, "src_dot_draft": { "context": "order status", @@ -2170,10 +2174,10 @@ }, "src_dot_draftOrders": { "context": "draft orders section name", - "string": "Draft Orders" + "string": "ĐĐžĐžŅ€ĐžĐŗ ĐˇĐ°Ņ…Đ¸Đ°ĐģĐŗŅƒŅƒĐ´" }, "src_dot_drafts": { - "string": "Drafts" + "string": "ĐĐžĐžŅ€ĐŗŅƒŅƒĐ´" }, "src_dot_edit": { "context": "button", @@ -2193,7 +2197,7 @@ }, "src_dot_fulfilled": { "context": "order status", - "string": "Fulfilled" + "string": "БиĐĩĐģŌ¯Ō¯ĐģŅŅĐŊ" }, "src_dot_generalInformations": { "string": "Đ•Ņ€ĶŠĐŊŅ…Đ¸Đš ĐŧŅĐ´ŅŅĐģŅĐģ" @@ -2357,7 +2361,7 @@ }, "src_dot_orders_dot_components_dot_OrderDraftFinalizeDialog_dot_1161061962": { "context": "dialog header", - "string": "Finalize Draft Order" + "string": "ĐĐžĐžŅ€ĐžĐŗ ĐˇĐ°Ņ…Đ¸Đ°ĐģĐŗŅ‹Đŗ Đ´ŅƒŅƒŅĐŗĐ°Ņ…" }, "src_dot_orders_dot_components_dot_OrderDraftFinalizeDialog_dot_1297434244": { "string": "No user information" @@ -2370,7 +2374,7 @@ }, "src_dot_orders_dot_components_dot_OrderDraftFinalizeDialog_dot_2725265632": { "context": "button", - "string": "Finalize" + "string": "Đ”ŅƒŅƒŅĐŗĐ°Ņ…" }, "src_dot_orders_dot_components_dot_OrderDraftFinalizeDialog_dot_2824936338": { "string": "Shipping method provided, but no product requires it" @@ -2383,7 +2387,7 @@ }, "src_dot_orders_dot_components_dot_OrderDraftFinalizeDialog_dot_678764806": { "context": "button", - "string": "Finalize anyway" + "string": "Đ”ŅƒŅƒŅĐŗĐ°Ņ…" }, "src_dot_orders_dot_components_dot_OrderDraftListPage_dot_2826235371": { "context": "button", @@ -2408,7 +2412,7 @@ "string": "БиĐĩĐģŅĐŗĐ´ŅŅŅ…ĐŗŌ¯Đš ĐˇĐ°Ņ…Đ¸Đ°ĐģĐŗŅƒŅƒĐ´ ĐžĐģĐ´ŅĐžĐŊĐŗŌ¯Đš" }, "src_dot_orders_dot_components_dot_OrderDraftList_dot_2889196282": { - "string": "No. of Order" + "string": "Đ—Đ°Ņ…Đ¸Đ°ĐģĐŗŅ‹ĐŊ Đ´ŅƒĐŗĐ°Đ°Ņ€" }, "src_dot_orders_dot_components_dot_OrderDraftList_dot_3426593715": { "string": "ĐĨŅŅ€ŅĐŗĐģŅĐŗŅ‡" @@ -2427,7 +2431,7 @@ }, "src_dot_orders_dot_components_dot_OrderDraftPage_dot_2725265632": { "context": "button", - "string": "Finalize" + "string": "Đ”ŅƒŅƒŅĐŗĐ°Ņ…" }, "src_dot_orders_dot_components_dot_OrderFulfillPage_dot_1608534452": { "context": "page header", @@ -2439,7 +2443,7 @@ }, "src_dot_orders_dot_components_dot_OrderFulfillPage_dot_2095687440": { "context": "fulfill order, button", - "string": "Fulfill" + "string": "БиĐĩĐģŌ¯Ō¯ĐģŅŅ…" }, "src_dot_orders_dot_components_dot_OrderFulfillPage_dot_2588284040": { "context": "no variant stock in warehouse", @@ -2526,12 +2530,16 @@ }, "src_dot_orders_dot_components_dot_OrderFulfillment_dot_3494686506": { "context": "section header", - "string": "Fulfilled ({quantity})" + "string": "БиĐĩĐģŌ¯Ō¯ĐģŅŅĐŊ ({quantity})" }, "src_dot_orders_dot_components_dot_OrderFulfillment_dot_4039425374": { "context": "cancelled fulfillment, section header", "string": "Cancelled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderFulfillment_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderFulfillment_dot_732594284": { "context": "button", "string": "Cancel Fulfillment" @@ -2550,7 +2558,7 @@ }, "src_dot_orders_dot_components_dot_OrderHistory_dot_1521936480": { "context": "order history message", - "string": "Fulfilled {quantity} items" + "string": "БиĐĩĐģŌ¯Ō¯ĐģŅĐŗĐ´ŅŅĐŊ {quantity} ŅˆĐ¸Ņ€Ņ…ŅĐŗ ĐˇĐ°Ņ…Đ¸Đ°ĐģĐŗĐ° йаКĐŊа" }, "src_dot_orders_dot_components_dot_OrderHistory_dot_1527620381": { "context": "order history message", @@ -2562,7 +2570,7 @@ }, "src_dot_orders_dot_components_dot_OrderHistory_dot_1867847329": { "context": "order history message", - "string": "Links to the order's digital goods were sent" + "string": "ДиĐļĐ¸Ņ‚Đ°Đģ ĐąŌ¯Ņ‚ŅŅĐŗĐ´ŅŅ…Ō¯Ō¯ĐŊĐ¸ĐšĐŗ Đ°ŅˆĐ¸ĐŗĐģĐ°Ņ… ĐˇĐ°Đ°Đ˛Đ°Ņ€ Ņ…ŅŅ€ŅĐŗĐģŅĐŗŅ‡ Ņ€Ō¯Ō¯ иĐģĐŗŅŅĐŗĐ´ŅŅĐŊ" }, "src_dot_orders_dot_components_dot_OrderHistory_dot_1964864749": { "context": "order history message", @@ -2598,11 +2606,11 @@ }, "src_dot_orders_dot_components_dot_OrderHistory_dot_3081292385": { "context": "order history message", - "string": "Fulfillment confirmation was sent to customer" + "string": "Đ—Đ°Ņ…Đ¸Đ°ĐģĐŗĐ° ĐąĐ°Ņ‚Đ°ĐģĐŗĐ°Đ°ĐļŅĐ°ĐŊ Ņ‚ŅƒŅ…Đ°Đš Ņ…ŅŅ€ŅĐŗĐģŅĐŗŅ‡Đ¸Đ´ ĐŧŅĐ´ŅĐŗĐ´ŅŅĐŊ" }, "src_dot_orders_dot_components_dot_OrderHistory_dot_3095247195": { "context": "order history message", - "string": "Draft order was created" + "string": "ĐĐžĐžŅ€ĐžĐŗ ĐˇĐ°Ņ…Đ¸Đ°ĐģĐŗĐ° аĐŧĐļиĐģŅ‚Ņ‚Đ°Đš Ō¯Ō¯ŅĐŗŅĐŗĐ´ĐģŅŅ" }, "src_dot_orders_dot_components_dot_OrderHistory_dot_3328124376": { "context": "order history message", @@ -2667,14 +2675,14 @@ "string": "ŌŽŌ¯ŅĐŗŅĐŗĐ´ĐģŅŅ" }, "src_dot_orders_dot_components_dot_OrderList_dot_1198046928": { - "string": "Fulfillment status" + "string": "ĐĸĶŠĐģĶŠĐ˛" }, "src_dot_orders_dot_components_dot_OrderList_dot_2743232155": { "context": "payment status", "string": "ĐĸĶŠĐģĐąĶŠŅ€" }, "src_dot_orders_dot_components_dot_OrderList_dot_2889196282": { - "string": "No. of Order" + "string": "Đ—Đ°Ņ…Đ¸Đ°ĐģĐŗŅ‹ĐŊ Đ´ŅƒĐŗĐ°Đ°Ņ€" }, "src_dot_orders_dot_components_dot_OrderList_dot_3426593715": { "context": "e-mail or full name", @@ -2749,6 +2757,10 @@ "context": "order payment", "string": "ŌŽĐģĐ´ŅĐŗĐ´ŅĐģ" }, + "src_dot_orders_dot_components_dot_OrderPayment_dot_3720114122": { + "context": "order discount", + "string": "ĐĨŅĐŧĐ´Ņ€Đ°Đģ" + }, "src_dot_orders_dot_components_dot_OrderPayment_dot_3768782744": { "context": "order payment", "string": "Preauthorized amount" @@ -2768,10 +2780,6 @@ "context": "order total price", "string": "ĐĐ¸ĐšŅ‚" }, - "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_1542417144": { - "context": "dialog header", - "string": "Đ‘Ō¯Ņ‚ŅŅĐŗĐ´ŅŅ…Ō¯Ō¯ĐŊ Ō¯Ō¯ŅĐŗŅŅ…" - }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2272209368": { "context": "variant sku", "string": "SKU {sku}" @@ -2779,6 +2787,10 @@ "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2336947364": { "string": "Search by product name, attribute, product type etc..." }, + "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2775402904": { + "context": "dialog header", + "string": "Add Product" + }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2850255786": { "string": "Đ‘Ō¯Ņ‚ŅŅĐŗĐ´ŅŅ…Ō¯Ō¯ĐŊŌ¯Ō¯Đ´ŅŅŅ Ņ…Đ°ĐšŅ…" }, @@ -2799,7 +2811,7 @@ }, "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_2095687440": { "context": "button", - "string": "Fulfill" + "string": "БиĐĩĐģŌ¯Ō¯ĐģŅŅ…" }, "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_2796503714": { "context": "ordered products", @@ -2809,6 +2821,10 @@ "context": "section header", "string": "Unfulfilled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_878013594": { "context": "order line total price", "string": "ĐĐ¸ĐšŅ‚" @@ -2817,13 +2833,13 @@ "string": "Payment successfully captured" }, "src_dot_orders_dot_views_dot_OrderDetails_dot_1435191432": { - "string": "Draft order successfully finalized" + "string": "ĐĐžĐžŅ€ĐžĐŗ ĐˇĐ°Ņ…Đ¸Đ°ĐģĐŗŅ‹Đŗ аĐŧĐļиĐģŅ‚Ņ‚Đ°Đš Đ´ŅƒŅƒŅĐŗĐ°Đģаа" }, "src_dot_orders_dot_views_dot_OrderDetails_dot_1468420349": { "string": "Order line deleted" }, "src_dot_orders_dot_views_dot_OrderDetails_dot_1475565380": { - "string": "Fulfillment successfully updated" + "string": "АĐŧĐļиĐģŅ‚Ņ‚Đ°Đš ŅˆĐ¸ĐŊŅŅ‡ĐģŅĐŗĐ´ĐģŅŅ" }, "src_dot_orders_dot_views_dot_OrderDetails_dot_1632861387": { "string": "Order line updated" @@ -2838,7 +2854,7 @@ "string": "Đ—Đ°Ņ…Đ¸Đ°ĐģĐŗĐ° аĐŧĐļиĐģŅ‚Ņ‚Đ°Đš Ņ†ŅƒŅ†ĐģĐ°ĐŗĐ´Đģаа" }, "src_dot_orders_dot_views_dot_OrderDetails_dot_3178394068": { - "string": "Note successfully added" + "string": "АĐŧĐļиĐģŅ‚Ņ‚Đ°Đš ĐŊŅĐŧŅĐŗĐ´ĐģŅŅ" }, "src_dot_orders_dot_views_dot_OrderDetails_dot_3280942553": { "string": "Order payment successfully voided" @@ -2861,7 +2877,7 @@ "string": "Draft Order #{orderNumber}" }, "src_dot_orders_dot_views_dot_OrderDetails_dot_927945225": { - "string": "Fulfillment successfully cancelled" + "string": "АĐŧĐļиĐģŅ‚Ņ‚Đ°Đš Ņ†ŅƒŅ†ĐģĐ°ĐŗĐ´Đ°Đ°" }, "src_dot_orders_dot_views_dot_OrderDraftList_dot_1161115149": { "context": "dialog header", @@ -3621,17 +3637,14 @@ "context": "header", "string": "ĐĸОО Ņ…ŅĐŧĐļŅŅ" }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3143542809": { - "string": "This product doesn't have any stock. You can add it here." - }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3482985373": { - "context": "button", - "string": "Edit Warehouses" - }, "src_dot_products_dot_components_dot_ProductStocks_dot_3633706025": { "context": "product inventory, checkbox", "string": "Track Inventory" }, + "src_dot_products_dot_components_dot_ProductStocks_dot_3857433664": { + "context": "button", + "string": "Assign Warehouse" + }, "src_dot_products_dot_components_dot_ProductStocks_dot_849869830": { "string": "Active inventory tracking will automatically calculate changes of stock" }, @@ -3859,13 +3872,6 @@ "context": "product variant name", "string": "Variant" }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_3482985373": { - "context": "dialog header", - "string": "Edit Warehouses" - }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_4112406382": { - "string": "Select warehouses that stock selected product" - }, "src_dot_products_dot_views_dot_1542417144": { "context": "window title", "string": "Đ‘Ō¯Ņ‚ŅŅĐŗĐ´ŅŅ…Ō¯Ō¯ĐŊ Ō¯Ō¯ŅĐŗŅŅ…" @@ -4147,6 +4153,9 @@ "context": "window title", "string": "Create Service Account" }, + "src_dot_sessionExpired": { + "string": "Your session has expired. Please log in again to continue." + }, "src_dot_shipping": { "context": "shipping section name", "string": "Shipping Methods" @@ -4465,7 +4474,7 @@ "string": "No keys" }, "src_dot_siteSettings_dot_components_dot_SiteSettingsMailing_dot_1124962330": { - "string": "Mailing email address" + "string": "ИĐŧŅĐšĐģ Ņ…Đ°ŅĐŗ" }, "src_dot_siteSettings_dot_components_dot_SiteSettingsMailing_dot_1672275992": { "context": "email sender", @@ -4473,7 +4482,7 @@ }, "src_dot_siteSettings_dot_components_dot_SiteSettingsMailing_dot_280712237": { "context": "section header", - "string": "Mailing Configuration" + "string": "ИĐŧŅĐšĐģиКĐŊ Ņ‚ĐžŅ…Đ¸Ņ€ĐŗĐžĐž" }, "src_dot_siteSettings_dot_components_dot_SiteSettingsMailing_dot_297689661": { "string": "Configurate your email address from which all automatic emails will be sent to your customers." @@ -4488,7 +4497,7 @@ "string": "ВĐĩĐą ĐĨĐ°ŅĐŗ" }, "src_dot_siteSettings_dot_components_dot_SiteSettingsMailing_dot_70179174": { - "string": "Mailing email sender" + "string": "ИĐģĐŗŅŅĐŗŅ‡" }, "src_dot_siteSettings_dot_components_dot_SiteSettingsPage_dot_1004240342": { "string": "This adress will be used to generate invoices and calculate shipping rates." @@ -4506,7 +4515,7 @@ }, "src_dot_siteSettings_dot_components_dot_SiteSettingsPage_dot_280712237": { "context": "section header", - "string": "Mailing Configuration" + "string": "ИĐŧŅĐšĐģиКĐŊ Ņ‚ĐžŅ…Đ¸Ņ€ĐŗĐžĐž" }, "src_dot_siteSettings_dot_components_dot_SiteSettingsPage_dot_3657173399": { "string": "ĐĸаĐŊŅ‹ ŅĐŊĐ´ ĐžŅ€ŅƒŅƒĐģŅĐ°ĐŊ иĐŧŅĐšĐģ Ņ…Đ°ŅĐŗĐ¸ĐšĐŗ Ņ‚Đ°ĐŊŅ‹ Ņ…Đ°Ņ€Đ¸ĐģŅ†Đ°ĐŗŅ‡Đ´Ņ‹ĐŊ Ņ…ĐžĐģйОО ĐąĐ°Ņ€Đ¸Ņ… Ņ…Đ°ŅĐŗ йОĐģĐŗĐžĐŊ Đ°ŅˆĐ¸ĐŗĐģĐ°Ņ… йОĐģĐŊĐž." @@ -4830,7 +4839,7 @@ }, "src_dot_translations_dot_components_dot_TranslationFields_dot_363646127": { "context": "button", - "string": "Discard" + "string": "БоĐģĐ¸Ņ…" }, "src_dot_translations_dot_components_dot_TranslationFields_dot_3793796047": { "string": "No translation yet" diff --git a/locale/nb.json b/locale/nb.json index 86a1af60a..c996e9d99 100644 --- a/locale/nb.json +++ b/locale/nb.json @@ -250,7 +250,7 @@ "context": "optional field", "string": "Valgfritt" }, - "productVariantPriceOptionalPriceOverrideField": { + "productVariantPriceOptionalPriceField": { "context": "optional field", "string": "Valgfritt" }, @@ -1675,6 +1675,10 @@ "context": "button", "string": "Slett" }, + "src_dot_demo": { + "context": "notification message after log in", + "string": "Just to let you know... You're in demo mode. You can play around with the dashboard but can't save changes." + }, "src_dot_description": { "string": "Beskrivelse" }, @@ -2532,6 +2536,10 @@ "context": "cancelled fulfillment, section header", "string": "Cancelled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderFulfillment_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderFulfillment_dot_732594284": { "context": "button", "string": "Kanseller forsendelse" @@ -2749,6 +2757,10 @@ "context": "order payment", "string": "UtestÃĨende beløp" }, + "src_dot_orders_dot_components_dot_OrderPayment_dot_3720114122": { + "context": "order discount", + "string": "Rabatt" + }, "src_dot_orders_dot_components_dot_OrderPayment_dot_3768782744": { "context": "order payment", "string": "ForhÃĨndsautorisert beløp" @@ -2768,10 +2780,6 @@ "context": "order total price", "string": "Total" }, - "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_1542417144": { - "context": "dialog header", - "string": "Opprett Produkt" - }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2272209368": { "context": "variant sku", "string": "SKU {sku}" @@ -2779,6 +2787,10 @@ "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2336947364": { "string": "Søk etter produktnavn, attributt, produkttype, osv..." }, + "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2775402904": { + "context": "dialog header", + "string": "Add Product" + }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2850255786": { "string": "Søk i Produkter" }, @@ -2809,6 +2821,10 @@ "context": "section header", "string": "Ikke sendt ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_878013594": { "context": "order line total price", "string": "Total" @@ -3621,17 +3637,14 @@ "context": "header", "string": "Antall" }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3143542809": { - "string": "This product doesn't have any stock. You can add it here." - }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3482985373": { - "context": "button", - "string": "Edit Warehouses" - }, "src_dot_products_dot_components_dot_ProductStocks_dot_3633706025": { "context": "product inventory, checkbox", "string": "Track Inventory" }, + "src_dot_products_dot_components_dot_ProductStocks_dot_3857433664": { + "context": "button", + "string": "Assign Warehouse" + }, "src_dot_products_dot_components_dot_ProductStocks_dot_849869830": { "string": "Active inventory tracking will automatically calculate changes of stock" }, @@ -3859,13 +3872,6 @@ "context": "product variant name", "string": "Variant" }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_3482985373": { - "context": "dialog header", - "string": "Edit Warehouses" - }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_4112406382": { - "string": "Select warehouses that stock selected product" - }, "src_dot_products_dot_views_dot_1542417144": { "context": "window title", "string": "Opprett Produkt" @@ -4147,6 +4153,9 @@ "context": "window title", "string": "Opprett Servicekonto" }, + "src_dot_sessionExpired": { + "string": "Your session has expired. Please log in again to continue." + }, "src_dot_shipping": { "context": "shipping section name", "string": "Fraktmetoder" diff --git a/locale/nl.json b/locale/nl.json index 8fbe1e3c9..016ce9b57 100644 --- a/locale/nl.json +++ b/locale/nl.json @@ -250,7 +250,7 @@ "context": "optional field", "string": "Optional" }, - "productVariantPriceOptionalPriceOverrideField": { + "productVariantPriceOptionalPriceField": { "context": "optional field", "string": "Optional" }, @@ -1675,6 +1675,10 @@ "context": "button", "string": "Verwijder" }, + "src_dot_demo": { + "context": "notification message after log in", + "string": "Just to let you know... You're in demo mode. You can play around with the dashboard but can't save changes." + }, "src_dot_description": { "string": "Omschrijving" }, @@ -2532,6 +2536,10 @@ "context": "cancelled fulfillment, section header", "string": "Cancelled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderFulfillment_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderFulfillment_dot_732594284": { "context": "button", "string": "Cancel Fulfillment" @@ -2749,6 +2757,10 @@ "context": "order payment", "string": "Outstanding Balance" }, + "src_dot_orders_dot_components_dot_OrderPayment_dot_3720114122": { + "context": "order discount", + "string": "Korting" + }, "src_dot_orders_dot_components_dot_OrderPayment_dot_3768782744": { "context": "order payment", "string": "Vooraf goedgekeurd bedrag" @@ -2768,10 +2780,6 @@ "context": "order total price", "string": "Totaal" }, - "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_1542417144": { - "context": "dialog header", - "string": "Create Product" - }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2272209368": { "context": "variant sku", "string": "SKU {sku}" @@ -2779,6 +2787,10 @@ "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2336947364": { "string": "Search by product name, attribute, product type etc..." }, + "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2775402904": { + "context": "dialog header", + "string": "Add Product" + }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2850255786": { "string": "Search Products" }, @@ -2809,6 +2821,10 @@ "context": "section header", "string": "Unfulfilled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_878013594": { "context": "order line total price", "string": "Totaal" @@ -3621,17 +3637,14 @@ "context": "header", "string": "Hoeveelheid" }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3143542809": { - "string": "This product doesn't have any stock. You can add it here." - }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3482985373": { - "context": "button", - "string": "Edit Warehouses" - }, "src_dot_products_dot_components_dot_ProductStocks_dot_3633706025": { "context": "product inventory, checkbox", "string": "Track Inventory" }, + "src_dot_products_dot_components_dot_ProductStocks_dot_3857433664": { + "context": "button", + "string": "Assign Warehouse" + }, "src_dot_products_dot_components_dot_ProductStocks_dot_849869830": { "string": "Active inventory tracking will automatically calculate changes of stock" }, @@ -3859,13 +3872,6 @@ "context": "product variant name", "string": "Productversie" }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_3482985373": { - "context": "dialog header", - "string": "Edit Warehouses" - }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_4112406382": { - "string": "Select warehouses that stock selected product" - }, "src_dot_products_dot_views_dot_1542417144": { "context": "window title", "string": "Create Product" @@ -4147,6 +4153,9 @@ "context": "window title", "string": "Create Service Account" }, + "src_dot_sessionExpired": { + "string": "Your session has expired. Please log in again to continue." + }, "src_dot_shipping": { "context": "shipping section name", "string": "Shipping Methods" diff --git a/locale/pl.json b/locale/pl.json index 876068bb8..5742b9790 100644 --- a/locale/pl.json +++ b/locale/pl.json @@ -4,19 +4,19 @@ "string": "Anuluj zamÃŗwienie" }, "configurationMenuAttributes": { - "string": "Determine attributes used to create product types" + "string": "Określa atrybuty do stworzenia produktu" }, "configurationMenuNavigation": { - "string": "Define how users can navigate through your store" + "string": "Zdefiniuj jak uÅŧytkownicy mogą poruszać się po twoim sklepie" }, "configurationMenuPages": { - "string": "Manage and add additional pages" + "string": "Zarządzaj i dodaj nowe strony" }, "configurationMenuPermissionGroups": { - "string": "Manage your permission groups and their permissions" + "string": "Zarządzaj grupami uprawnień i ich uprawnieniami" }, "configurationMenuProductTypes": { - "string": "Define types of products you sell" + "string": "Definiuje typy produktÃŗw, ktÃŗre sprzedajesz" }, "configurationMenuShipping": { "string": "Manage how you ship out orders" @@ -250,7 +250,7 @@ "context": "optional field", "string": "Optional" }, - "productVariantPriceOptionalPriceOverrideField": { + "productVariantPriceOptionalPriceField": { "context": "optional field", "string": "Optional" }, @@ -1675,6 +1675,10 @@ "context": "button", "string": "Usuń" }, + "src_dot_demo": { + "context": "notification message after log in", + "string": "Just to let you know... You're in demo mode. You can play around with the dashboard but can't save changes." + }, "src_dot_description": { "string": "Opis" }, @@ -2532,6 +2536,10 @@ "context": "cancelled fulfillment, section header", "string": "Cancelled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderFulfillment_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderFulfillment_dot_732594284": { "context": "button", "string": "Anuluj realizację" @@ -2749,6 +2757,10 @@ "context": "order payment", "string": "Outstanding Balance" }, + "src_dot_orders_dot_components_dot_OrderPayment_dot_3720114122": { + "context": "order discount", + "string": "ZniÅŧka" + }, "src_dot_orders_dot_components_dot_OrderPayment_dot_3768782744": { "context": "order payment", "string": "Kwota zablokowana" @@ -2768,10 +2780,6 @@ "context": "order total price", "string": "Suma" }, - "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_1542417144": { - "context": "dialog header", - "string": "Create Product" - }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2272209368": { "context": "variant sku", "string": "SKU {sku}" @@ -2779,6 +2787,10 @@ "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2336947364": { "string": "Search by product name, attribute, product type etc..." }, + "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2775402904": { + "context": "dialog header", + "string": "Add Product" + }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2850255786": { "string": "Search Products" }, @@ -2809,6 +2821,10 @@ "context": "section header", "string": "Unfulfilled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_878013594": { "context": "order line total price", "string": "Suma" @@ -3621,17 +3637,14 @@ "context": "header", "string": "Ilość" }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3143542809": { - "string": "This product doesn't have any stock. You can add it here." - }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3482985373": { - "context": "button", - "string": "Edit Warehouses" - }, "src_dot_products_dot_components_dot_ProductStocks_dot_3633706025": { "context": "product inventory, checkbox", "string": "Track Inventory" }, + "src_dot_products_dot_components_dot_ProductStocks_dot_3857433664": { + "context": "button", + "string": "Assign Warehouse" + }, "src_dot_products_dot_components_dot_ProductStocks_dot_849869830": { "string": "Active inventory tracking will automatically calculate changes of stock" }, @@ -3859,13 +3872,6 @@ "context": "product variant name", "string": "Wariant" }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_3482985373": { - "context": "dialog header", - "string": "Edit Warehouses" - }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_4112406382": { - "string": "Select warehouses that stock selected product" - }, "src_dot_products_dot_views_dot_1542417144": { "context": "window title", "string": "Create Product" @@ -4147,6 +4153,9 @@ "context": "window title", "string": "Create Service Account" }, + "src_dot_sessionExpired": { + "string": "Your session has expired. Please log in again to continue." + }, "src_dot_shipping": { "context": "shipping section name", "string": "Shipping Methods" diff --git a/locale/pt.json b/locale/pt.json index 3ce20c904..e8f1f258c 100644 --- a/locale/pt.json +++ b/locale/pt.json @@ -4,88 +4,88 @@ "string": "Cancelar Pedido" }, "configurationMenuAttributes": { - "string": "Determine attributes used to create product types" + "string": "Identifique atributos usados para criar tipos de produtos" }, "configurationMenuNavigation": { - "string": "Define how users can navigate through your store" + "string": "Defina com os utilizadores navegam pela loja" }, "configurationMenuPages": { - "string": "Manage and add additional pages" + "string": "Modifique e adicione pÃĄginas adicionais" }, "configurationMenuPermissionGroups": { - "string": "Manage your permission groups and their permissions" + "string": "Modifique grupos e as suas permissÃĩes" }, "configurationMenuProductTypes": { - "string": "Define types of products you sell" + "string": "Defina os tipos de produtos que vende" }, "configurationMenuShipping": { - "string": "Manage how you ship out orders" + "string": "Defina como envia as encomendas" }, "configurationMenuSiteSettings": { - "string": "View and update your site settings" + "string": "Veja e edite as opçÃĩes do site" }, "configurationMenuStaff": { - "string": "Manage your employees and their permissions" + "string": "Defina empregados e as suas permissÃĩes" }, "configurationMenuTaxes": { - "string": "Manage how your store charges tax" + "string": "Defina como a loja gere os impostos" }, "configurationMenuWarehouses": { - "string": "Manage and update your warehouse information" + "string": "Defina a informaÃ§ÃŖo de armazÊm" }, "configurationPluginsPages": { - "string": "View and update your plugins and their settings." + "string": "Veja e edite os plugins e as suas opçÃĩes" }, "homeActivityCardHeader": { "context": "header", - "string": "Activity" + "string": "Actividade" }, "homeActivityCardNoActivities": { - "string": "No activities found" + "string": "Nenhuma actividade encontrada" }, "homeAnalyticsCardHeader": { "string": "Hoje" }, "homeHeaderText": { "context": "header", - "string": "Hello there, {userName}" + "string": "OlÃĄ, {userName}" }, "homeHeaderTextCaption": { "context": "subheader", - "string": "Here is some information we gathered about your store" + "string": "Aqui estÃĄ alguma informaÃ§ÃŖo que reunimos acerca da sua loja" }, "homeNotificationTableNoOrders": { - "string": "No orders ready to fulfill" + "string": "Nenhum pedido pronto a ser realizado" }, "homeNotificationTableOrders": { - "string": "{amount, plural,one {One order is ready to fulfill} other {{amount} Orders are ready to fulfill}}" + "string": "{amount, plural,one {Um pedido pronto a ser realizado} other {{amount} Pedidos prontos a serem realizados.}}" }, "homeNotificationTablePayments": { - "string": "{amount, plural,one {One payment to capture} other {{amount} Payments to capture}}" + "string": "{amount, plural,one {Um pagamento a capturar} other {{amount} Pagamentos a capturar}}" }, "homeNotificationTableProducts": { - "string": "{amount, plural,one {One product out of stock} other {{amount} Products out of stock}}" + "string": "{amount, plural,one {Um produto esgotado} other {{amount} Produtos esgotados}}" }, "homeNotificationsNoPayments": { - "string": "No payments waiting for capture" + "string": "Nenhum pagamento a capturar" }, "homeNotificationsTableNoProducts": { - "string": "No products out of stock" + "string": "Nenhum produto esgotado" }, "homeProductListCardOrders": { "context": "number of ordered products", - "string": "{amount, plural,one {One ordered} other {{amount} Ordered}}" + "string": "{amount, plural,one {Um pedido} other {{amount} Pedidos}}" }, "homeProductsListCardHeader": { "context": "header", - "string": "Top Products" + "string": "Top de produtos" }, "homeProductsListCardNoProducts": { - "string": "No products found" + "string": "Nenhum produto encontrado" }, "homeScreenDisclaimer": { "context": "header", - "string": "Disclaimer" + "string": "Aviso legal" }, "homeScreenDisclaimerText1": { "string": "The new dashboard and the GraphQL API are preview-quality software." @@ -95,21 +95,21 @@ }, "homeScreenHeader": { "context": "header", - "string": "Hello there, {userName}" + "string": "OlÃĄ, {userName}" }, "menuCreateDialogHeader": { "context": "dialog header", - "string": "Create Menu" + "string": "Criar Menu" }, "menuCreateDialogMenuTitleLabel": { - "string": "Menu Title" + "string": "Título do Menu" }, "menuDetailsDeleteMenuContent": { - "string": "Are you sure you want to delete menu {menuName}?" + "string": "Tem a certeza que pretende apagar o menu {menuName}?" }, "menuDetailsDeleteMenuHeader": { "context": "dialog header", - "string": "Delete Menu" + "string": "Apagar Menu" }, "menuDetailsPageHelperText": { "string": "Creating the navigation structure is done by dragging and dropping. Simply create a new menu item and then drag it into its destined place. You can move items inside one another to create a tree structure and drag items up and down to create a hierarchy" @@ -120,7 +120,7 @@ }, "menuItemDialogAddLink": { "context": "add link to navigation", - "string": "Link to: {url}" + "string": "Link para: {url}" }, "menuItemDialogEditItem": { "context": "edit menu item, header", @@ -131,7 +131,7 @@ "string": "Link" }, "menuItemDialogLinkPlaceholder": { - "string": "Start typing to begin search..." + "string": "Escreva para começar a procura..." }, "menuItemDialogNameLabel": { "context": "menu item name", @@ -156,7 +156,7 @@ }, "menuListDeleteMenuHeader": { "context": "dialog header", - "string": "Delete Menu" + "string": "Apagar Menu" }, "menuListDeleteMenusContent": { "string": "{counter,plural,one {Are you sure you want to delete this menu?} other {Are you sure you want to delete {displayQuantity} menus?}}" @@ -173,17 +173,17 @@ "string": "Items" }, "menuListMenutitle": { - "string": "Menu Title" + "string": "Título do Menu" }, "menuListNoMenus": { "string": "No menus found" }, "menuListPageAddMenu": { "context": "button", - "string": "Create Menu" + "string": "Criar Menu" }, "menuPropertiesMenuTitle": { - "string": "Menu Title" + "string": "Título do Menu" }, "orderCustomerBillingAddressNotSet": { "context": "no address is set in draft order", @@ -215,11 +215,11 @@ }, "productTypeCreateHeader": { "context": "window title", - "string": "Create Product Type" + "string": "Criar tipo de produto" }, "productTypeCreatePageHeader": { "context": "header", - "string": "Create Product Type" + "string": "Criar tipo de produto" }, "productTypeTaxesHeader": { "context": "section header", @@ -244,59 +244,59 @@ }, "productVariantCreatorWarehouseSectionHeader": { "context": "header", - "string": "Warehouses" + "string": "ArmazÊns" }, "productVariantPriceOptionalCostPriceField": { "context": "optional field", - "string": "Optional" + "string": "Opcional" }, - "productVariantPriceOptionalPriceOverrideField": { + "productVariantPriceOptionalPriceField": { "context": "optional field", - "string": "Optional" + "string": "Opcional" }, "saleDetailsPageCategoriesQuantity": { "context": "number of categories", - "string": "Categories ({quantity})" + "string": "Categorias ({quantity})" }, "saleDetailsPageCollectionsQuantity": { "context": "number of collections", - "string": "Collections ({quantity})" + "string": "ColecçÃĩes ({quantity})" }, "saleDetailsPageProductsQuantity": { "context": "number of products", - "string": "Products ({quantity})" + "string": "Produtos ({quantity})" }, "saleDetailsUnassignCategory": { "context": "unassign category from sale, button", - "string": "Unassign" + "string": "Desatribuir" }, "saleDetailsUnassignCollection": { "context": "unassign collection from sale, button", - "string": "Unassign" + "string": "Desatribuir" }, "saleDetailsUnassignProduct": { "context": "unassign product from sale, button", - "string": "Unassign" + "string": "Desatribuir" }, "shippingZoneDetailsDialogsDeleteShippingMethod": { "context": "delete shipping method", - "string": "Are you sure you want to delete {name}?" + "string": "Tem a certeza que pretende apagar {name}?" }, "shippingZoneDetailsDialogsDeleteShippingZone": { "context": "delete shipping zone", - "string": "Are you sure you want to delete {name}?" + "string": "Tem a certeza que pretende apagar {name}?" }, "shippingZoneWarehouses_dot_autocomplete_dot_label": { "context": "autocomplete select label", - "string": "Warehouse" + "string": "ArmazÊm" }, "siteSettingsMailingHelperText": { "context": "helper text", - "string": "Mailing Configuration" + "string": "ConfiguraÃ§ÃŖo de listas de e-mail" }, "src_dot_accept": { "context": "button", - "string": "Accept" + "string": "Aceitar" }, "src_dot_attributes": { "context": "attributes section name", @@ -334,46 +334,46 @@ }, "src_dot_attributes_dot_components_dot_AttributeDetails_dot_2592224946": { "context": "check to require attribute to have value", - "string": "Value Required" + "string": "É necessÃĄrio o valor" }, "src_dot_attributes_dot_components_dot_AttributeDetails_dot_3334509011": { "context": "product attribute type", - "string": "Multiple Select" + "string": "SelecÃ§ÃŖo mÃēltipla" }, "src_dot_attributes_dot_components_dot_AttributeDetails_dot_3605174225": { "context": "attribute's slug short code label", - "string": "Attribute Code" + "string": "CÃŗdigo de atributo" }, "src_dot_attributes_dot_components_dot_AttributeDetails_dot_4107478955": { "context": "attribute slug input field helper text", - "string": "This is used internally. Make sure you don’t use spaces" + "string": "Isto Ê utilizado internamente. NÃŖo utilizar espaços" }, "src_dot_attributes_dot_components_dot_AttributeDetails_dot_691600601": { "context": "attribute's label", - "string": "Default Label" + "string": "Etiqueta por omissÃŖo" }, "src_dot_attributes_dot_components_dot_AttributeListPage_dot_2417065806": { "context": "tab name", - "string": "All Attributes" + "string": "Todos os atributos" }, "src_dot_attributes_dot_components_dot_AttributeListPage_dot_3824684885": { "context": "button", - "string": "Create attribute" + "string": "Criar atributo" }, "src_dot_attributes_dot_components_dot_AttributeListPage_dot_3916653510": { - "string": "Search Attribute" + "string": "Procurar atributo" }, "src_dot_attributes_dot_components_dot_AttributeListPage_dot_availableInGrid": { "context": "attribute can be column in product list table", - "string": "Can be used as column" + "string": "Pode ser utilizado como coluna" }, "src_dot_attributes_dot_components_dot_AttributeListPage_dot_filterableInDashboard": { "context": "use attribute in filtering", - "string": "Filterable in Dashboard" + "string": "Pode ser filtrado no painel de controlo" }, "src_dot_attributes_dot_components_dot_AttributeListPage_dot_filterableInStorefront": { "context": "use attribute in filtering", - "string": "Filterable in Storefront" + "string": "Pode ser filtrado na loja" }, "src_dot_attributes_dot_components_dot_AttributeListPage_dot_isVariantOnly": { "context": "attribute can be used only in variants", @@ -381,14 +381,14 @@ }, "src_dot_attributes_dot_components_dot_AttributeListPage_dot_valueRequired": { "context": "attribute value is required", - "string": "Value Required" + "string": "É necessÃĄrio o valor" }, "src_dot_attributes_dot_components_dot_AttributeListPage_dot_visibleInStorefront": { "context": "attribute", - "string": "Visible on Product Page in Storefront" + "string": "Visível na pÃĄgina de produto na loja" }, "src_dot_attributes_dot_components_dot_AttributeList_dot_1192828581": { - "string": "No attributes found" + "string": "Nenhum atributo encontrado" }, "src_dot_attributes_dot_components_dot_AttributeList_dot_2186555805": { "context": "attribute can be searched in storefront", @@ -396,22 +396,22 @@ }, "src_dot_attributes_dot_components_dot_AttributeList_dot_2235596452": { "context": "attribute can be searched in dashboard", - "string": "Searchable" + "string": "Pode ser procurado" }, "src_dot_attributes_dot_components_dot_AttributeList_dot_3605174225": { - "string": "Attribute Code" + "string": "CÃŗdigo de atributo" }, "src_dot_attributes_dot_components_dot_AttributeList_dot_643174786": { "context": "attribute is visible", - "string": "Visible" + "string": "Visível" }, "src_dot_attributes_dot_components_dot_AttributeList_dot_691600601": { "context": "attribute's label'", - "string": "Default Label" + "string": "Etiqueta por omissÃŖo" }, "src_dot_attributes_dot_components_dot_AttributePage_dot_2855501559": { "context": "page title", - "string": "Create New Attribute" + "string": "Criar novo atributo" }, "src_dot_attributes_dot_components_dot_AttributeProperties_dot_1318123158": { "context": "attribute is filterable in storefront", @@ -419,11 +419,11 @@ }, "src_dot_attributes_dot_components_dot_AttributeProperties_dot_1877630205": { "context": "attribute properties regarding storefront", - "string": "Storefront Properties" + "string": "Propriedades da loja" }, "src_dot_attributes_dot_components_dot_AttributeProperties_dot_26409543": { "context": "attribute properties regarding dashboard", - "string": "Dashboard Properties" + "string": "Propriedades do painel de controlo" }, "src_dot_attributes_dot_components_dot_AttributeProperties_dot_3590282519": { "context": "attribute position in storefront filters", @@ -431,10 +431,10 @@ }, "src_dot_attributes_dot_components_dot_AttributeProperties_dot_3876764312": { "context": "attribute", - "string": "Visible on Product Page in Storefront" + "string": "Visível na pÃĄgina de produto na loja" }, "src_dot_attributes_dot_components_dot_AttributeProperties_dot_4048785456": { - "string": "If enabled this attribute can be used as a column in product table." + "string": "Se activo, este atributo pode ser usado como coluna na tabela de produto" }, "src_dot_attributes_dot_components_dot_AttributeProperties_dot_673770329": { "context": "add attribute as column in product list table", @@ -639,7 +639,7 @@ "string": "Preço" }, "src_dot_categories_dot_components_dot_CategoryProductList_dot_1657559629": { - "string": "No products found" + "string": "Nenhum produto encontrado" }, "src_dot_categories_dot_components_dot_CategoryProductList_dot_1952810469": { "context": "product type", @@ -819,7 +819,7 @@ "string": "Publicado " }, "src_dot_collections_dot_components_dot_CollectionProducts_dot_1657559629": { - "string": "No products found" + "string": "Nenhum produto encontrado" }, "src_dot_collections_dot_components_dot_CollectionProducts_dot_1952810469": { "context": "product type", @@ -877,7 +877,7 @@ }, "src_dot_collections_dot_views_dot_870815507": { "context": "unassign product from collection, button", - "string": "Unassign" + "string": "Desatribuir" }, "src_dot_collections_dot_views_dot_942133001": { "context": "dialog title", @@ -1399,7 +1399,7 @@ "string": "Set publication date" }, "src_dot_components_dot_VisibilityCard_dot_643174786": { - "string": "Visible" + "string": "Visível" }, "src_dot_components_dot_VisibilityCard_dot_77815154": { "string": "Oculto" @@ -1669,12 +1669,16 @@ "string": "Delete Customers" }, "src_dot_dashboard": { - "string": "Painel de controle" + "string": "Painel de controlo" }, "src_dot_delete": { "context": "button", "string": "Delete" }, + "src_dot_demo": { + "context": "notification message after log in", + "string": "Just to let you know... You're in demo mode. You can play around with the dashboard but can't save changes." + }, "src_dot_description": { "string": "DescriÃ§ÃŖo" }, @@ -1749,7 +1753,7 @@ "string": "Active Dates" }, "src_dot_discounts_dot_components_dot_DiscountProducts_dot_1657559629": { - "string": "No products found" + "string": "Nenhum produto encontrado" }, "src_dot_discounts_dot_components_dot_DiscountProducts_dot_2100305525": { "context": "button", @@ -1894,15 +1898,15 @@ }, "src_dot_discounts_dot_components_dot_VoucherDetailsPage_dot_346170541": { "context": "number of categories", - "string": "Categories ({quantity})" + "string": "Categorias ({quantity})" }, "src_dot_discounts_dot_components_dot_VoucherDetailsPage_dot_3673147015": { "context": "number of collections", - "string": "Collections ({quantity})" + "string": "ColecçÃĩes ({quantity})" }, "src_dot_discounts_dot_components_dot_VoucherDetailsPage_dot_846927739": { "context": "number of products", - "string": "Products ({quantity})" + "string": "Produtos ({quantity})" }, "src_dot_discounts_dot_components_dot_VoucherInfo_dot_1262795626": { "string": "Discount Code" @@ -2231,7 +2235,7 @@ }, "src_dot_optionalField": { "context": "field is optional", - "string": "Optional" + "string": "Opcional" }, "src_dot_orders": { "context": "orders section name", @@ -2532,6 +2536,10 @@ "context": "cancelled fulfillment, section header", "string": "Cancelled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderFulfillment_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderFulfillment_dot_732594284": { "context": "button", "string": "Cancelar processo" @@ -2749,6 +2757,10 @@ "context": "order payment", "string": "Outstanding Balance" }, + "src_dot_orders_dot_components_dot_OrderPayment_dot_3720114122": { + "context": "order discount", + "string": "Desconto" + }, "src_dot_orders_dot_components_dot_OrderPayment_dot_3768782744": { "context": "order payment", "string": "Quantidade prÊ-autorizada" @@ -2768,10 +2780,6 @@ "context": "order total price", "string": "Total" }, - "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_1542417144": { - "context": "dialog header", - "string": "Create Product" - }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2272209368": { "context": "variant sku", "string": "SKU {sku}" @@ -2779,6 +2787,10 @@ "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2336947364": { "string": "Search by product name, attribute, product type etc..." }, + "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2775402904": { + "context": "dialog header", + "string": "Add Product" + }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2850255786": { "string": "Search Products" }, @@ -2809,6 +2821,10 @@ "context": "section header", "string": "Unfulfilled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_878013594": { "context": "order line total price", "string": "Total" @@ -3071,7 +3087,7 @@ }, "src_dot_permissionGroups_dot_components_dot_PermissionGroupDeleteDialog_dot_2297471173": { "context": "dialog content", - "string": "Are you sure you want to delete {name}?" + "string": "Tem a certeza que pretende apagar {name}?" }, "src_dot_permissionGroups_dot_components_dot_PermissionGroupDeleteDialog_dot_3528974446": { "context": "dialog title", @@ -3164,7 +3180,7 @@ }, "src_dot_permissionGroups_dot_views_dot_PermissionGroupDetails_dot_870815507": { "context": "button title", - "string": "Unassign" + "string": "Desatribuir" }, "src_dot_permissionGroups_dot_views_dot_PermissionGroupList_dot_92979760": { "string": "Permission Group Deleted" @@ -3294,7 +3310,7 @@ "string": "Are you sure you want to unassign {attributeName} from {productTypeName}?" }, "src_dot_productTypes_dot_components_dot_ProductTypeAttributes_dot_1192828581": { - "string": "No attributes found" + "string": "Nenhum atributo encontrado" }, "src_dot_productTypes_dot_components_dot_ProductTypeAttributes_dot_1228425832": { "string": "Attribute name" @@ -3325,7 +3341,7 @@ }, "src_dot_productTypes_dot_components_dot_ProductTypeDeleteDialog_dot_2297471173": { "context": "delete product type", - "string": "Are you sure you want to delete {name}?" + "string": "Tem a certeza que pretende apagar {name}?" }, "src_dot_productTypes_dot_components_dot_ProductTypeDeleteDialog_dot_924066985": { "context": "dialog header", @@ -3426,7 +3442,7 @@ }, "src_dot_productTypes_dot_views_dot_ProductTypeUpdate_dot_870815507": { "context": "unassign attribute from product type, button", - "string": "Unassign" + "string": "Desatribuir" }, "src_dot_products": { "context": "products section name", @@ -3479,7 +3495,7 @@ }, "src_dot_products_dot_components_dot_ProductImagePage_dot_1905082483": { "context": "field is optional", - "string": "Optional" + "string": "Opcional" }, "src_dot_products_dot_components_dot_ProductImagePage_dot_2546267317": { "context": "header", @@ -3545,14 +3561,14 @@ }, "src_dot_products_dot_components_dot_ProductListPage_dot_visible": { "context": "product is visible", - "string": "Visible" + "string": "Visível" }, "src_dot_products_dot_components_dot_ProductList_dot_1134347598": { "context": "product price", "string": "Preço" }, "src_dot_products_dot_components_dot_ProductList_dot_1657559629": { - "string": "No products found" + "string": "Nenhum produto encontrado" }, "src_dot_products_dot_components_dot_ProductList_dot_1952810469": { "context": "product type", @@ -3621,17 +3637,14 @@ "context": "header", "string": "Quantidade" }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3143542809": { - "string": "This product doesn't have any stock. You can add it here." - }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3482985373": { - "context": "button", - "string": "Edit Warehouses" - }, "src_dot_products_dot_components_dot_ProductStocks_dot_3633706025": { "context": "product inventory, checkbox", "string": "Track Inventory" }, + "src_dot_products_dot_components_dot_ProductStocks_dot_3857433664": { + "context": "button", + "string": "Assign Warehouse" + }, "src_dot_products_dot_components_dot_ProductStocks_dot_849869830": { "string": "Active inventory tracking will automatically calculate changes of stock" }, @@ -3758,7 +3771,7 @@ }, "src_dot_products_dot_components_dot_ProductVariantDeleteDialog_dot_2297471173": { "context": "delete product variant", - "string": "Are you sure you want to delete {name}?" + "string": "Tem a certeza que pretende apagar {name}?" }, "src_dot_products_dot_components_dot_ProductVariantDeleteDialog_dot_3726089650": { "context": "dialog header", @@ -3859,13 +3872,6 @@ "context": "product variant name", "string": "Variante" }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_3482985373": { - "context": "dialog header", - "string": "Edit Warehouses" - }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_4112406382": { - "string": "Select warehouses that stock selected product" - }, "src_dot_products_dot_views_dot_1542417144": { "context": "window title", "string": "Create Product" @@ -3937,7 +3943,7 @@ }, "src_dot_products_dot_views_dot_ProductUpdate_dot_2297471173": { "context": "delete product", - "string": "Are you sure you want to delete {name}?" + "string": "Tem a certeza que pretende apagar {name}?" }, "src_dot_products_dot_views_dot_ProductUpdate_dot_4108890645": { "string": "Product removed" @@ -4033,7 +4039,7 @@ }, "src_dot_services_dot_components_dot_ServiceDeleteDialog_dot_2297471173": { "context": "delete service account", - "string": "Are you sure you want to delete {name}?" + "string": "Tem a certeza que pretende apagar {name}?" }, "src_dot_services_dot_components_dot_ServiceDetailsPage_dot_1848599267": { "context": "checkbox label", @@ -4147,6 +4153,9 @@ "context": "window title", "string": "Create Service Account" }, + "src_dot_sessionExpired": { + "string": "Your session has expired. Please log in again to continue." + }, "src_dot_shipping": { "context": "shipping section name", "string": "Shipping Methods" @@ -4336,7 +4345,7 @@ }, "src_dot_shipping_dot_components_dot_ShippingZoneWarehouses_dot_1221560277": { "context": "section header", - "string": "Warehouse" + "string": "ArmazÊm" }, "src_dot_shipping_dot_components_dot_ShippingZoneWarehouses_dot_2304484478": { "context": "button", @@ -4473,7 +4482,7 @@ }, "src_dot_siteSettings_dot_components_dot_SiteSettingsMailing_dot_280712237": { "context": "section header", - "string": "Mailing Configuration" + "string": "ConfiguraÃ§ÃŖo de listas de e-mail" }, "src_dot_siteSettings_dot_components_dot_SiteSettingsMailing_dot_297689661": { "string": "Configurate your email address from which all automatic emails will be sent to your customers." @@ -4506,7 +4515,7 @@ }, "src_dot_siteSettings_dot_components_dot_SiteSettingsPage_dot_280712237": { "context": "section header", - "string": "Mailing Configuration" + "string": "ConfiguraÃ§ÃŖo de listas de e-mail" }, "src_dot_siteSettings_dot_components_dot_SiteSettingsPage_dot_3657173399": { "string": "Email adress you provide here will be used as a contact adress for your customers." @@ -5149,7 +5158,7 @@ }, "src_dot_warehouses": { "context": "warehouses section name", - "string": "Warehouses" + "string": "ArmazÊns" }, "src_dot_warehouses_dot_components_dot_WarehouseCreatePage_dot_1967111456": { "context": "warehouse", @@ -5223,7 +5232,7 @@ }, "src_dot_webhooks_dot_components_dot_WebhookDeleteDialog_dot_2297471173": { "context": "delete webhook", - "string": "Are you sure you want to delete {name}?" + "string": "Tem a certeza que pretende apagar {name}?" }, "src_dot_webhooks_dot_components_dot_WebhookDeleteDialog_dot_3514087611": { "context": "dialog header", @@ -5374,14 +5383,14 @@ }, "voucherDetailsUnassignCategory": { "context": "unassign category from voucher, button", - "string": "Unassign" + "string": "Desatribuir" }, "voucherDetailsUnassignCollection": { "context": "unassign collection from voucher, button", - "string": "Unassign" + "string": "Desatribuir" }, "voucherDetailsUnassignProduct": { "context": "unassign product from voucher, button", - "string": "Unassign" + "string": "Desatribuir" } } \ No newline at end of file diff --git a/locale/pt_BR.json b/locale/pt_BR.json index a037d8263..22da06452 100644 --- a/locale/pt_BR.json +++ b/locale/pt_BR.json @@ -250,7 +250,7 @@ "context": "optional field", "string": "Optional" }, - "productVariantPriceOptionalPriceOverrideField": { + "productVariantPriceOptionalPriceField": { "context": "optional field", "string": "Optional" }, @@ -1675,6 +1675,10 @@ "context": "button", "string": "Excluir" }, + "src_dot_demo": { + "context": "notification message after log in", + "string": "Just to let you know... You're in demo mode. You can play around with the dashboard but can't save changes." + }, "src_dot_description": { "string": "DescriÃ§ÃŖo" }, @@ -2532,6 +2536,10 @@ "context": "cancelled fulfillment, section header", "string": "Cancelled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderFulfillment_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderFulfillment_dot_732594284": { "context": "button", "string": "Cancelar faturamento" @@ -2749,6 +2757,10 @@ "context": "order payment", "string": "Outstanding Balance" }, + "src_dot_orders_dot_components_dot_OrderPayment_dot_3720114122": { + "context": "order discount", + "string": "Desconto" + }, "src_dot_orders_dot_components_dot_OrderPayment_dot_3768782744": { "context": "order payment", "string": "Quantidade prÊ-autorizada" @@ -2768,10 +2780,6 @@ "context": "order total price", "string": "Total" }, - "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_1542417144": { - "context": "dialog header", - "string": "Criar Produto" - }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2272209368": { "context": "variant sku", "string": "SKU {sku}" @@ -2779,6 +2787,10 @@ "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2336947364": { "string": "Search by product name, attribute, product type etc..." }, + "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2775402904": { + "context": "dialog header", + "string": "Add Product" + }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2850255786": { "string": "Search Products" }, @@ -2809,6 +2821,10 @@ "context": "section header", "string": "Unfulfilled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_878013594": { "context": "order line total price", "string": "Total" @@ -3621,17 +3637,14 @@ "context": "header", "string": "Quantidade" }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3143542809": { - "string": "This product doesn't have any stock. You can add it here." - }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3482985373": { - "context": "button", - "string": "Edit Warehouses" - }, "src_dot_products_dot_components_dot_ProductStocks_dot_3633706025": { "context": "product inventory, checkbox", "string": "Track Inventory" }, + "src_dot_products_dot_components_dot_ProductStocks_dot_3857433664": { + "context": "button", + "string": "Assign Warehouse" + }, "src_dot_products_dot_components_dot_ProductStocks_dot_849869830": { "string": "Active inventory tracking will automatically calculate changes of stock" }, @@ -3859,13 +3872,6 @@ "context": "product variant name", "string": "Variante" }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_3482985373": { - "context": "dialog header", - "string": "Edit Warehouses" - }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_4112406382": { - "string": "Select warehouses that stock selected product" - }, "src_dot_products_dot_views_dot_1542417144": { "context": "window title", "string": "Criar Produto" @@ -4147,6 +4153,9 @@ "context": "window title", "string": "Create Service Account" }, + "src_dot_sessionExpired": { + "string": "Your session has expired. Please log in again to continue." + }, "src_dot_shipping": { "context": "shipping section name", "string": "MÊtodos de Envio" diff --git a/locale/ro.json b/locale/ro.json index 9c6511d60..062e9f960 100644 --- a/locale/ro.json +++ b/locale/ro.json @@ -250,7 +250,7 @@ "context": "optional field", "string": "Optional" }, - "productVariantPriceOptionalPriceOverrideField": { + "productVariantPriceOptionalPriceField": { "context": "optional field", "string": "Optional" }, @@ -1675,6 +1675,10 @@ "context": "button", "string": "Delete" }, + "src_dot_demo": { + "context": "notification message after log in", + "string": "Just to let you know... You're in demo mode. You can play around with the dashboard but can't save changes." + }, "src_dot_description": { "string": "Descriere" }, @@ -2532,6 +2536,10 @@ "context": "cancelled fulfillment, section header", "string": "Cancelled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderFulfillment_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderFulfillment_dot_732594284": { "context": "button", "string": "Anulează Livrarea" @@ -2749,6 +2757,10 @@ "context": "order payment", "string": "Outstanding Balance" }, + "src_dot_orders_dot_components_dot_OrderPayment_dot_3720114122": { + "context": "order discount", + "string": "Reducere" + }, "src_dot_orders_dot_components_dot_OrderPayment_dot_3768782744": { "context": "order payment", "string": "Sumă prea mare" @@ -2768,10 +2780,6 @@ "context": "order total price", "string": "Total" }, - "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_1542417144": { - "context": "dialog header", - "string": "Create Product" - }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2272209368": { "context": "variant sku", "string": "SKU {sku}" @@ -2779,6 +2787,10 @@ "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2336947364": { "string": "Search by product name, attribute, product type etc..." }, + "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2775402904": { + "context": "dialog header", + "string": "Add Product" + }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2850255786": { "string": "Search Products" }, @@ -2809,6 +2821,10 @@ "context": "section header", "string": "Unfulfilled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_878013594": { "context": "order line total price", "string": "Total" @@ -3621,17 +3637,14 @@ "context": "header", "string": "Cantitate" }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3143542809": { - "string": "This product doesn't have any stock. You can add it here." - }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3482985373": { - "context": "button", - "string": "Edit Warehouses" - }, "src_dot_products_dot_components_dot_ProductStocks_dot_3633706025": { "context": "product inventory, checkbox", "string": "Track Inventory" }, + "src_dot_products_dot_components_dot_ProductStocks_dot_3857433664": { + "context": "button", + "string": "Assign Warehouse" + }, "src_dot_products_dot_components_dot_ProductStocks_dot_849869830": { "string": "Active inventory tracking will automatically calculate changes of stock" }, @@ -3859,13 +3872,6 @@ "context": "product variant name", "string": "Variantă" }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_3482985373": { - "context": "dialog header", - "string": "Edit Warehouses" - }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_4112406382": { - "string": "Select warehouses that stock selected product" - }, "src_dot_products_dot_views_dot_1542417144": { "context": "window title", "string": "Create Product" @@ -4147,6 +4153,9 @@ "context": "window title", "string": "Create Service Account" }, + "src_dot_sessionExpired": { + "string": "Your session has expired. Please log in again to continue." + }, "src_dot_shipping": { "context": "shipping section name", "string": "Shipping Methods" diff --git a/locale/ru.json b/locale/ru.json index c60c4616a..0421d2424 100644 --- a/locale/ru.json +++ b/locale/ru.json @@ -4,28 +4,28 @@ "string": "ĐžŅ‚ĐŧĐĩĐŊĐ¸Ņ‚ŅŒ СаĐēаС" }, "configurationMenuAttributes": { - "string": "Determine attributes used to create product types" + "string": "ОĐŋŅ€ĐĩĐ´ĐĩĐģĐ¸Ņ‚ŅŒ Đ°Ņ‚Ņ€Đ¸ĐąŅƒŅ‚Ņ‹, Đ¸ŅĐŋĐžĐģŅŒĐˇŅƒĐĩĐŧŅ‹Đĩ Đ´ĐģŅ ŅĐžĐˇĐ´Đ°ĐŊĐ¸Ņ Ņ‚Đ¸ĐŋОв Ņ‚ĐžĐ˛Đ°Ņ€ĐžĐ˛" }, "configurationMenuNavigation": { - "string": "Define how users can navigate through your store" + "string": "Đ—Đ°Đ´Đ°Ņ‚ŅŒ ĐēаĐē ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģи ĐŧĐžĐŗŅƒŅ‚ ĐŋĐĩŅ€ĐĩĐŧĐĩŅ‰Đ°Ņ‚ŅŒŅŅ ĐŋĐž Đ˛Đ°ŅˆĐĩĐŧ҃ ĐŧĐ°ĐŗĐ°ĐˇĐ¸ĐŊ҃" }, "configurationMenuPages": { - "string": "Manage and add additional pages" + "string": "ĐŖĐŋŅ€Đ°Đ˛ĐģĐĩĐŊиĐĩ и дОйавĐģĐĩĐŊиĐĩ Đ´ĐžĐŋĐžĐģĐŊĐ¸Ņ‚ĐĩĐģҌĐŊҋ҅ ŅŅ‚Ņ€Đ°ĐŊĐ¸Ņ†" }, "configurationMenuPermissionGroups": { - "string": "Manage your permission groups and their permissions" + "string": "ĐŖĐŋŅ€Đ°Đ˛ĐģĐĩĐŊиĐĩ ĐŗŅ€ŅƒĐŋĐŋаĐŧи Ņ€Đ°ĐˇŅ€Đĩ҈ĐĩĐŊиК и Đ¸Ņ… Ņ€Đ°ĐˇŅ€Đĩ҈ĐĩĐŊĐ¸ŅĐŧи" }, "configurationMenuProductTypes": { - "string": "Define types of products you sell" + "string": "Đ—Đ°Đ´Đ°Ņ‚ŅŒ Ņ‚Đ¸ĐŋŅ‹ ĐŋŅ€ĐžĐ´Đ°Đ˛Đ°ĐĩĐŧҋ҅ Ņ‚ĐžĐ˛Đ°Ņ€ĐžĐ˛" }, "configurationMenuShipping": { - "string": "Manage how you ship out orders" + "string": "ĐŖĐŋŅ€Đ°Đ˛ĐģĐĩĐŊиĐĩ Đ´ĐžŅŅ‚Đ°Đ˛ĐēОК СаĐēаСОв" }, "configurationMenuSiteSettings": { - "string": "View and update your site settings" + "string": "ĐŸŅ€ĐžŅĐŧĐžŅ‚Ņ€ и ОйĐŊОвĐģĐĩĐŊиĐĩ ĐŊĐ°ŅŅ‚Ņ€ĐžĐĩĐē Đ˛Đ°ŅˆĐĩĐŗĐž ŅĐ°ĐšŅ‚Đ°" }, "configurationMenuStaff": { - "string": "Manage your employees and their permissions" + "string": "ĐŖĐŋŅ€Đ°Đ˛ĐģĐĩĐŊиĐĩ ŅĐžŅ‚Ņ€ŅƒĐ´ĐŊиĐēаĐŧи и Đ¸Ņ… ĐŋŅ€Đ°Đ˛Đ°Đŧи" }, "configurationMenuTaxes": { "string": "Manage how your store charges tax" @@ -41,24 +41,24 @@ "string": "АĐēŅ‚Đ¸Đ˛ĐŊĐžŅŅ‚ŅŒ" }, "homeActivityCardNoActivities": { - "string": "No activities found" + "string": "НиĐēаĐēĐ¸Ņ… Đ´ĐĩĐšŅŅ‚Đ˛Đ¸Đš ĐŊĐĩ ĐŊаКдĐĩĐŊĐž" }, "homeAnalyticsCardHeader": { "string": "ĐĄĐĩĐŗĐžĐ´ĐŊŅ" }, "homeHeaderText": { "context": "header", - "string": "Hello there, {userName}" + "string": "ĐŸŅ€Đ¸Đ˛ĐĩŅ‚, {userName}" }, "homeHeaderTextCaption": { "context": "subheader", - "string": "Here is some information we gathered about your store" + "string": "Đ’ĐžŅ‚ ĐŊĐĩĐēĐžŅ‚ĐžŅ€Ņ‹Đĩ ŅĐ˛ĐĩĐ´ĐĩĐŊĐ¸Ņ, ĐēĐžŅ‚ĐžŅ€Ņ‹Đĩ ĐŧŅ‹ ŅĐžĐąŅ€Đ°Đģи Đž Đ˛Đ°ŅˆĐĩĐŧ ĐŧĐ°ĐŗĐ°ĐˇĐ¸ĐŊĐĩ" }, "homeNotificationTableNoOrders": { "string": "No orders ready to fulfill" }, "homeNotificationTableOrders": { - "string": "{amount, plural,one {One order is ready to fulfill} other {{amount} Orders are ready to fulfill}}" + "string": "{amount, plural,one {ОдиĐŊ СаĐēаС ĐŗĐžŅ‚ĐžĐ˛ Đē Đ¸ŅĐŋĐžĐģĐŊĐĩĐŊĐ¸ŅŽ} few {{amount} СаĐēаСа ĐŗĐžŅ‚ĐžĐ˛Ņ‹ Đē Đ¸ŅĐŋĐžĐģĐŊĐĩĐŊĐ¸ŅŽ} many {{amount} СаĐēаСОв ĐŗĐžŅ‚ĐžĐ˛Ņ‹ Đē Đ¸ŅĐŋĐžĐģĐŊĐĩĐŊĐ¸ŅŽ} other {{amount} СаĐēаСОв ĐŗĐžŅ‚ĐžĐ˛Ņ‹ Đē Đ¸ŅĐŋĐžĐģĐŊĐĩĐŊĐ¸ŅŽ}}" }, "homeNotificationTablePayments": { "string": "{amount, plural,one {One payment to capture} other {{amount} Payments to capture}}" @@ -70,7 +70,7 @@ "string": "No payments waiting for capture" }, "homeNotificationsTableNoProducts": { - "string": "No products out of stock" + "string": "НĐĩŅ‚ ĐŋŅ€ĐžĐ´ŅƒĐēŅ‚ĐžĐ˛ ҁ ĐŧаĐģŅ‹Đŧ ĐžŅŅ‚Đ°Ņ‚ĐēĐžĐŧ ĐŊа ҁĐēĐģадĐĩ" }, "homeProductListCardOrders": { "context": "number of ordered products", @@ -78,14 +78,14 @@ }, "homeProductsListCardHeader": { "context": "header", - "string": "Top Products" + "string": "Đ›ŅƒŅ‡ŅˆĐ¸Đĩ Ņ‚ĐžĐ˛Đ°Ņ€Ņ‹" }, "homeProductsListCardNoProducts": { - "string": "No products found" + "string": "ĐĸĐžĐ˛Đ°Ņ€Ņ‹ ĐŊĐĩ ĐŊаКдĐĩĐŊŅ‹" }, "homeScreenDisclaimer": { "context": "header", - "string": "Disclaimer" + "string": "ĐŸŅ€ĐĩĐ´ŅƒĐŋŅ€ĐĩĐļĐ´ĐĩĐŊиĐĩ" }, "homeScreenDisclaimerText1": { "string": "The new dashboard and the GraphQL API are preview-quality software." @@ -95,24 +95,24 @@ }, "homeScreenHeader": { "context": "header", - "string": "Hello there, {userName}" + "string": "ĐŸŅ€Đ¸Đ˛ĐĩŅ‚, {userName}" }, "menuCreateDialogHeader": { "context": "dialog header", - "string": "Create Menu" + "string": "ĐĄĐžĐˇĐ´Đ°Ņ‚ŅŒ ĐŧĐĩĐŊŅŽ" }, "menuCreateDialogMenuTitleLabel": { - "string": "Menu Title" + "string": "Đ—Đ°ĐŗĐžĐģОвОĐē ĐŧĐĩĐŊŅŽ" }, "menuDetailsDeleteMenuContent": { "string": "Đ’Ņ‹ ŅƒĐ˛ĐĩŅ€ĐĩĐŊŅ‹, Ņ‡Ņ‚Đž Ņ…ĐžŅ‚Đ¸Ņ‚Đĩ ŅƒĐ´Đ°ĐģĐ¸Ņ‚ŅŒ menu {menuName}?" }, "menuDetailsDeleteMenuHeader": { "context": "dialog header", - "string": "Delete Menu" + "string": "ĐŖĐ´Đ°ĐģĐ¸Ņ‚ŅŒ ĐŧĐĩĐŊŅŽ" }, "menuDetailsPageHelperText": { - "string": "Creating the navigation structure is done by dragging and dropping. Simply create a new menu item and then drag it into its destined place. You can move items inside one another to create a tree structure and drag items up and down to create a hierarchy" + "string": "ХОСдаĐŊиĐĩ ŅŅ‚Ņ€ŅƒĐēŅ‚ŅƒŅ€Ņ‹ ĐŊĐ°Đ˛Đ¸ĐŗĐ°Ņ†Đ¸Đ¸ Đ˛Ņ‹ĐŋĐžĐģĐŊŅĐĩŅ‚ŅŅ ĐŋŅƒŅ‚ĐĩĐŧ ĐŋĐĩŅ€ĐĩŅ‚Đ°ŅĐēиваĐŊĐ¸Ņ. ĐŸŅ€ĐžŅŅ‚Đž ŅĐžĐˇĐ´Đ°ĐšŅ‚Đĩ ĐŊĐžĐ˛Ņ‹Đš Đŋ҃ĐŊĐēŅ‚ ĐŧĐĩĐŊŅŽ, а ĐˇĐ°Ņ‚ĐĩĐŧ ĐŋĐĩŅ€ĐĩŅ‚Đ°Ņ‰Đ¸Ņ‚Đĩ ĐĩĐŗĐž в ĐŋŅ€ĐĩĐ´ĐŊаСĐŊĐ°Ņ‡ĐĩĐŊĐŊĐžĐĩ ĐĩĐŧ҃ ĐŧĐĩŅŅ‚Đž. Đ’Ņ‹ ĐŧĐžĐļĐĩŅ‚Đĩ ĐŋĐĩŅ€ĐĩĐŧĐĩŅ‰Đ°Ņ‚ŅŒ ŅĐģĐĩĐŧĐĩĐŊ҂ҋ ĐŊа Đ´Ņ€ŅƒĐŗ Đ´Ņ€ŅƒĐŗĐ° Đ´ĐģŅ ŅĐžĐˇĐ´Đ°ĐŊĐ¸Ņ Đ´Ņ€ĐĩвОвидĐŊОК ŅŅ‚Ņ€ŅƒĐēŅ‚ŅƒŅ€Ņ‹ и ĐŋĐĩŅ€ĐĩŅ‚Đ°ŅĐēĐ¸Đ˛Đ°Ņ‚ŅŒ ŅĐģĐĩĐŧĐĩĐŊ҂ҋ ввĐĩҀ҅ и вĐŊиС Đ´ĐģŅ ŅĐžĐˇĐ´Đ°ĐŊĐ¸Ņ иĐĩŅ€Đ°Ņ€Ņ…Đ¸Đ¸" }, "menuItemDialogAddItem": { "context": "create new menu item, header", @@ -120,11 +120,11 @@ }, "menuItemDialogAddLink": { "context": "add link to navigation", - "string": "Link to: {url}" + "string": "ĐĄŅŅ‹ĐģĐēа ĐŊа: {url}" }, "menuItemDialogEditItem": { "context": "edit menu item, header", - "string": "Edit Item" + "string": "Đ ĐĩдаĐēŅ‚Đ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒ ŅĐģĐĩĐŧĐĩĐŊŅ‚" }, "menuItemDialogLinkLabel": { "context": "label", @@ -139,11 +139,11 @@ }, "menuItemsAddItem": { "context": "add new menu item", - "string": "Create new item" + "string": "ĐĄĐžĐˇĐ´Đ°Ņ‚ŅŒ ĐŊĐžĐ˛Ņ‹Đš ŅĐģĐĩĐŧĐĩĐŊŅ‚" }, "menuItemsHeader": { "context": "header", - "string": "Menu Items" + "string": "Đ­ĐģĐĩĐŧĐĩĐŊ҂ҋ ĐŧĐĩĐŊŅŽ" }, "menuItemsPlaceholder": { "string": "Đ”ĐžĐąĐ°Đ˛ŅŒŅ‚Đĩ ĐŊĐžĐ˛Ņ‹Đš Đŋ҃ĐŊĐēŅ‚, Ņ‡Ņ‚ĐžĐąŅ‹ ĐŊĐ°Ņ‡Đ°Ņ‚ŅŒ ŅĐžĐˇĐ´Đ°Đ˛Đ°Ņ‚ŅŒ ĐŧĐĩĐŊŅŽ." @@ -152,11 +152,11 @@ "string": "Created menu" }, "menuListDeleteMenuContent": { - "string": "Are you sure you want to delete {menuName}?" + "string": "Đ’Ņ‹ ŅƒĐ˛ĐĩŅ€ĐĩĐŊŅ‹, Ņ‡Ņ‚Đž Ņ…ĐžŅ‚Đ¸Ņ‚Đĩ ŅƒĐ´Đ°ĐģĐ¸Ņ‚ŅŒ {menuName}?" }, "menuListDeleteMenuHeader": { "context": "dialog header", - "string": "Delete Menu" + "string": "ĐŖĐ´Đ°ĐģĐ¸Ņ‚ŅŒ ĐŧĐĩĐŊŅŽ" }, "menuListDeleteMenusContent": { "string": "{counter,plural,one {Are you sure you want to delete this menu?} other {Are you sure you want to delete {displayQuantity} menus?}}" @@ -170,20 +170,20 @@ }, "menuListItems": { "context": "number of menu items", - "string": "Items" + "string": "Đ­ĐģĐĩĐŧĐĩĐŊ҂ҋ" }, "menuListMenutitle": { - "string": "Menu Title" + "string": "Đ—Đ°ĐŗĐžĐģОвОĐē ĐŧĐĩĐŊŅŽ" }, "menuListNoMenus": { "string": "No menus found" }, "menuListPageAddMenu": { "context": "button", - "string": "Create Menu" + "string": "ĐĄĐžĐˇĐ´Đ°Ņ‚ŅŒ ĐŧĐĩĐŊŅŽ" }, "menuPropertiesMenuTitle": { - "string": "Menu Title" + "string": "Đ—Đ°ĐŗĐžĐģОвОĐē ĐŧĐĩĐŊŅŽ" }, "orderCustomerBillingAddressNotSet": { "context": "no address is set in draft order", @@ -215,11 +215,11 @@ }, "productTypeCreateHeader": { "context": "window title", - "string": "Create Product Type" + "string": "ĐĄĐžĐˇĐ´Đ°Ņ‚ŅŒ Ņ‚Đ¸Đŋ ĐŋŅ€ĐžĐ´ŅƒĐēŅ‚Đ°" }, "productTypeCreatePageHeader": { "context": "header", - "string": "Create Product Type" + "string": "ĐĄĐžĐˇĐ´Đ°Ņ‚ŅŒ Ņ‚Đ¸Đŋ ĐŋŅ€ĐžĐ´ŅƒĐēŅ‚Đ°" }, "productTypeTaxesHeader": { "context": "section header", @@ -244,13 +244,13 @@ }, "productVariantCreatorWarehouseSectionHeader": { "context": "header", - "string": "Warehouses" + "string": "ĐĄĐēĐģĐ°Đ´Ņ‹" }, "productVariantPriceOptionalCostPriceField": { "context": "optional field", "string": "Optional" }, - "productVariantPriceOptionalPriceOverrideField": { + "productVariantPriceOptionalPriceField": { "context": "optional field", "string": "Optional" }, @@ -288,7 +288,7 @@ }, "shippingZoneWarehouses_dot_autocomplete_dot_label": { "context": "autocomplete select label", - "string": "Warehouse" + "string": "ĐĄĐēĐģад" }, "siteSettingsMailingHelperText": { "context": "helper text", @@ -314,7 +314,7 @@ }, "src_dot_attributes_dot_components_dot_AttributeBulkDeleteDialog_dot_1655187315": { "context": "dialog title", - "string": "Delete attributes" + "string": "ĐŖĐ´Đ°ĐģĐ¸Ņ‚ŅŒ Đ°Ņ‚Ņ€Đ¸ĐąŅƒŅ‚Ņ‹" }, "src_dot_attributes_dot_components_dot_AttributeDeleteDialog_dot_1889602489": { "context": "dialog title", @@ -322,7 +322,7 @@ }, "src_dot_attributes_dot_components_dot_AttributeDeleteDialog_dot_3738429348": { "context": "dialog content", - "string": "Are you sure you want to delete {attributeName}?" + "string": "Đ’Ņ‹ ŅƒĐ˛ĐĩŅ€ĐĩĐŊŅ‹, Ņ‡Ņ‚Đž Đ’Ņ‹ Ņ…ĐžŅ‚Đ¸Ņ‚Đĩ ŅƒĐ´Đ°ĐģĐ¸Ņ‚ŅŒ { attributeName }?" }, "src_dot_attributes_dot_components_dot_AttributeDetails_dot_1005562666": { "context": "attribute's editor component", @@ -403,7 +403,7 @@ }, "src_dot_attributes_dot_components_dot_AttributeList_dot_643174786": { "context": "attribute is visible", - "string": "Visible" + "string": "ВидиĐŧŅ‹Đš" }, "src_dot_attributes_dot_components_dot_AttributeList_dot_691600601": { "context": "attribute's label'", @@ -419,11 +419,11 @@ }, "src_dot_attributes_dot_components_dot_AttributeProperties_dot_1877630205": { "context": "attribute properties regarding storefront", - "string": "Storefront Properties" + "string": "ĐĄĐ˛ĐžĐšŅŅ‚Đ˛Đ° Đ˛Đ¸Ņ‚Ņ€Đ¸ĐŊŅ‹" }, "src_dot_attributes_dot_components_dot_AttributeProperties_dot_26409543": { "context": "attribute properties regarding dashboard", - "string": "Dashboard Properties" + "string": "ĐĄĐ˛ĐžĐšŅŅ‚Đ˛Đ° Đ´Đ°ŅˆĐąĐžŅ€Đ´Đ°" }, "src_dot_attributes_dot_components_dot_AttributeProperties_dot_3590282519": { "context": "attribute position in storefront filters", @@ -560,7 +560,7 @@ }, "src_dot_back": { "context": "button", - "string": "Back" + "string": "Назад" }, "src_dot_cancel": { "context": "button", @@ -639,11 +639,11 @@ "string": "ĐĻĐĩĐŊа" }, "src_dot_categories_dot_components_dot_CategoryProductList_dot_1657559629": { - "string": "No products found" + "string": "ĐĸĐžĐ˛Đ°Ņ€Ņ‹ ĐŊĐĩ ĐŊаКдĐĩĐŊŅ‹" }, "src_dot_categories_dot_components_dot_CategoryProductList_dot_1952810469": { "context": "product type", - "string": "Type" + "string": "ĐĸиĐŋ" }, "src_dot_categories_dot_components_dot_CategoryProductList_dot_2341910657": { "context": "product", @@ -663,7 +663,7 @@ }, "src_dot_categories_dot_components_dot_CategoryProducts_dot_4164156574": { "context": "header", - "string": "Products in {categoryName}" + "string": "ĐĸĐžĐ˛Đ°Ņ€ĐžĐ˛ в {categoryName}" }, "src_dot_categories_dot_components_dot_CategoryUpdatePage_dot_2159874182": { "context": "number of subcategories in category", @@ -682,7 +682,7 @@ }, "src_dot_categories_dot_components_dot_CategoryUpdatePage_dot_770296100": { "context": "button", - "string": "Create subcategory" + "string": "ĐĄĐžĐˇĐ´Đ°Ņ‚ŅŒ ĐŋОдĐēĐ°Ņ‚ĐĩĐŗĐžŅ€Đ¸ŅŽ" }, "src_dot_categories_dot_views_dot_1140231710": { "context": "window title", @@ -819,11 +819,11 @@ "string": "ОĐŋŅƒĐąĐģиĐēОваĐŊĐž" }, "src_dot_collections_dot_components_dot_CollectionProducts_dot_1657559629": { - "string": "No products found" + "string": "ĐĸĐžĐ˛Đ°Ņ€Ņ‹ ĐŊĐĩ ĐŊаКдĐĩĐŊŅ‹" }, "src_dot_collections_dot_components_dot_CollectionProducts_dot_1952810469": { "context": "product type", - "string": "Type" + "string": "ĐĸиĐŋ" }, "src_dot_collections_dot_components_dot_CollectionProducts_dot_2341910657": { "context": "product is not published", @@ -1399,7 +1399,7 @@ "string": "Set publication date" }, "src_dot_components_dot_VisibilityCard_dot_643174786": { - "string": "Visible" + "string": "ВидиĐŧŅ‹Đš" }, "src_dot_components_dot_VisibilityCard_dot_77815154": { "string": "ĐĄĐēŅ€Ņ‹Ņ‚Đž" @@ -1675,6 +1675,10 @@ "context": "button", "string": "ĐŖĐ´Đ°ĐģĐ¸Ņ‚ŅŒ" }, + "src_dot_demo": { + "context": "notification message after log in", + "string": "Just to let you know... You're in demo mode. You can play around with the dashboard but can't save changes." + }, "src_dot_description": { "string": "ОĐŋĐ¸ŅĐ°ĐŊиĐĩ" }, @@ -1749,7 +1753,7 @@ "string": "Đ’Ņ€ĐĩĐŧŅ аĐēŅ‚Đ¸Đ˛ĐŊĐžŅŅ‚Đ¸" }, "src_dot_discounts_dot_components_dot_DiscountProducts_dot_1657559629": { - "string": "No products found" + "string": "ĐĸĐžĐ˛Đ°Ņ€Ņ‹ ĐŊĐĩ ĐŊаКдĐĩĐŊŅ‹" }, "src_dot_discounts_dot_components_dot_DiscountProducts_dot_2100305525": { "context": "button", @@ -2532,6 +2536,10 @@ "context": "cancelled fulfillment, section header", "string": "Cancelled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderFulfillment_dot_693960049": { + "context": "ordered product sku", + "string": "ЕдиĐŊĐ¸Ņ†Đ° ҁĐēĐģĐ°Đ´ŅĐēĐžĐŗĐž ŅƒŅ‡Ņ‘Ņ‚Đ°" + }, "src_dot_orders_dot_components_dot_OrderFulfillment_dot_732594284": { "context": "button", "string": "ĐžŅ‚ĐŧĐĩĐŊĐ¸Ņ‚ŅŒ ĐŋĐžĐŋĐžĐģĐŊĐĩĐŊиĐĩ" @@ -2749,6 +2757,10 @@ "context": "order payment", "string": "Outstanding Balance" }, + "src_dot_orders_dot_components_dot_OrderPayment_dot_3720114122": { + "context": "order discount", + "string": "ĐĄĐēидĐēа" + }, "src_dot_orders_dot_components_dot_OrderPayment_dot_3768782744": { "context": "order payment", "string": "ĐĐ˛Ņ‚ĐžŅ€Đ¸ĐˇĐžĐ˛Đ°ĐŊĐŊĐžĐĩ Ņ‡Đ¸ŅĐģĐž" @@ -2768,10 +2780,6 @@ "context": "order total price", "string": "ĐĄŅƒĐŧĐŧа" }, - "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_1542417144": { - "context": "dialog header", - "string": "Create Product" - }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2272209368": { "context": "variant sku", "string": "SKU {sku}" @@ -2779,6 +2787,10 @@ "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2336947364": { "string": "Search by product name, attribute, product type etc..." }, + "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2775402904": { + "context": "dialog header", + "string": "Đ”ĐžĐąĐ°Đ˛Đ¸Ņ‚ŅŒ Ņ‚ĐžĐ˛Đ°Ņ€" + }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2850255786": { "string": "Search Products" }, @@ -2809,6 +2821,10 @@ "context": "section header", "string": "Unfulfilled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_693960049": { + "context": "ordered product sku", + "string": "ЕдиĐŊĐ¸Ņ†Đ° ҁĐēĐģĐ°Đ´ŅĐēĐžĐŗĐž ŅƒŅ‡Ņ‘Ņ‚Đ°" + }, "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_878013594": { "context": "order line total price", "string": "ĐĄŅƒĐŧĐŧа" @@ -3363,7 +3379,7 @@ }, "src_dot_productTypes_dot_components_dot_ProductTypeListPage_dot_type": { "context": "product type is digital or physical", - "string": "Type" + "string": "ĐĸиĐŋ" }, "src_dot_productTypes_dot_components_dot_ProductTypeList_dot_1126553969": { "string": "No product types found" @@ -3378,7 +3394,7 @@ }, "src_dot_productTypes_dot_components_dot_ProductTypeList_dot_1952810469": { "context": "product type is either simple or configurable", - "string": "Type" + "string": "ĐĸиĐŋ" }, "src_dot_productTypes_dot_components_dot_ProductTypeList_dot_2253986440": { "context": "product type name", @@ -3507,7 +3523,7 @@ }, "src_dot_products_dot_components_dot_ProductListPage_dot_1952810469": { "context": "product type", - "string": "Type" + "string": "ĐĸиĐŋ" }, "src_dot_products_dot_components_dot_ProductListPage_dot_3550330425": { "string": "Search Products..." @@ -3545,18 +3561,18 @@ }, "src_dot_products_dot_components_dot_ProductListPage_dot_visible": { "context": "product is visible", - "string": "Visible" + "string": "ВидиĐŧŅ‹Đš" }, "src_dot_products_dot_components_dot_ProductList_dot_1134347598": { "context": "product price", "string": "ĐĻĐĩĐŊа" }, "src_dot_products_dot_components_dot_ProductList_dot_1657559629": { - "string": "No products found" + "string": "ĐĸĐžĐ˛Đ°Ņ€Ņ‹ ĐŊĐĩ ĐŊаКдĐĩĐŊŅ‹" }, "src_dot_products_dot_components_dot_ProductList_dot_1952810469": { "context": "product type", - "string": "Type" + "string": "ĐĸиĐŋ" }, "src_dot_products_dot_components_dot_ProductList_dot_2341910657": { "context": "product status", @@ -3621,17 +3637,14 @@ "context": "header", "string": "КоĐģĐ¸Ņ‡ĐĩŅŅ‚Đ˛Đž" }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3143542809": { - "string": "This product doesn't have any stock. You can add it here." - }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3482985373": { - "context": "button", - "string": "Edit Warehouses" - }, "src_dot_products_dot_components_dot_ProductStocks_dot_3633706025": { "context": "product inventory, checkbox", "string": "Track Inventory" }, + "src_dot_products_dot_components_dot_ProductStocks_dot_3857433664": { + "context": "button", + "string": "Assign Warehouse" + }, "src_dot_products_dot_components_dot_ProductStocks_dot_849869830": { "string": "Active inventory tracking will automatically calculate changes of stock" }, @@ -3859,13 +3872,6 @@ "context": "product variant name", "string": "Đ’Đ°Ņ€Đ¸Đ°ĐŊ҂ҋ" }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_3482985373": { - "context": "dialog header", - "string": "Edit Warehouses" - }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_4112406382": { - "string": "Select warehouses that stock selected product" - }, "src_dot_products_dot_views_dot_1542417144": { "context": "window title", "string": "Create Product" @@ -4147,6 +4153,9 @@ "context": "window title", "string": "Create Service Account" }, + "src_dot_sessionExpired": { + "string": "Your session has expired. Please log in again to continue." + }, "src_dot_shipping": { "context": "shipping section name", "string": "Shipping Methods" @@ -4336,7 +4345,7 @@ }, "src_dot_shipping_dot_components_dot_ShippingZoneWarehouses_dot_1221560277": { "context": "section header", - "string": "Warehouse" + "string": "ĐĄĐēĐģад" }, "src_dot_shipping_dot_components_dot_ShippingZoneWarehouses_dot_2304484478": { "context": "button", @@ -5149,7 +5158,7 @@ }, "src_dot_warehouses": { "context": "warehouses section name", - "string": "Warehouses" + "string": "ĐĄĐēĐģĐ°Đ´Ņ‹" }, "src_dot_warehouses_dot_components_dot_WarehouseCreatePage_dot_1967111456": { "context": "warehouse", diff --git a/locale/sk.json b/locale/sk.json index d8f5d6299..bdfaa70cc 100644 --- a/locale/sk.json +++ b/locale/sk.json @@ -48,11 +48,11 @@ }, "homeHeaderText": { "context": "header", - "string": "Hello there, {userName}" + "string": "Ahoj {userName}" }, "homeHeaderTextCaption": { "context": "subheader", - "string": "Here is some information we gathered about your store" + "string": "Tu je zopÃĄr informÃĄcií, čo sme zozbierali o tvojom obchode" }, "homeNotificationTableNoOrders": { "string": "No orders ready to fulfill" @@ -78,7 +78,7 @@ }, "homeProductsListCardHeader": { "context": "header", - "string": "Top Products" + "string": "Top Produkty" }, "homeProductsListCardNoProducts": { "string": "No products found" @@ -95,11 +95,11 @@ }, "homeScreenHeader": { "context": "header", - "string": "Hello there, {userName}" + "string": "Ahoj {userName}" }, "menuCreateDialogHeader": { "context": "dialog header", - "string": "Create Menu" + "string": "VytvoriÅĨ menu" }, "menuCreateDialogMenuTitleLabel": { "string": "Menu Title" @@ -109,7 +109,7 @@ }, "menuDetailsDeleteMenuHeader": { "context": "dialog header", - "string": "Delete Menu" + "string": "VymazaÅĨ menu" }, "menuDetailsPageHelperText": { "string": "Creating the navigation structure is done by dragging and dropping. Simply create a new menu item and then drag it into its destined place. You can move items inside one another to create a tree structure and drag items up and down to create a hierarchy" @@ -156,7 +156,7 @@ }, "menuListDeleteMenuHeader": { "context": "dialog header", - "string": "Delete Menu" + "string": "VymazaÅĨ menu" }, "menuListDeleteMenusContent": { "string": "{counter,plural,one {Are you sure you want to delete this menu?} other {Are you sure you want to delete {displayQuantity} menus?}}" @@ -180,7 +180,7 @@ }, "menuListPageAddMenu": { "context": "button", - "string": "Create Menu" + "string": "VytvoriÅĨ menu" }, "menuPropertiesMenuTitle": { "string": "Menu Title" @@ -250,7 +250,7 @@ "context": "optional field", "string": "Optional" }, - "productVariantPriceOptionalPriceOverrideField": { + "productVariantPriceOptionalPriceField": { "context": "optional field", "string": "Optional" }, @@ -296,7 +296,7 @@ }, "src_dot_accept": { "context": "button", - "string": "Accept" + "string": "PotvrdiÅĨ" }, "src_dot_attributes": { "context": "attributes section name", @@ -1675,6 +1675,10 @@ "context": "button", "string": "VymazaÅĨ" }, + "src_dot_demo": { + "context": "notification message after log in", + "string": "Just to let you know... You're in demo mode. You can play around with the dashboard but can't save changes." + }, "src_dot_description": { "string": "Popis" }, @@ -2532,6 +2536,10 @@ "context": "cancelled fulfillment, section header", "string": "Cancelled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderFulfillment_dot_693960049": { + "context": "ordered product sku", + "string": "SkladovÃĄ jednotka " + }, "src_dot_orders_dot_components_dot_OrderFulfillment_dot_732594284": { "context": "button", "string": "ZruÅĄiÅĨ naplnenie" @@ -2749,6 +2757,10 @@ "context": "order payment", "string": "Outstanding Balance" }, + "src_dot_orders_dot_components_dot_OrderPayment_dot_3720114122": { + "context": "order discount", + "string": "ZÄžava" + }, "src_dot_orders_dot_components_dot_OrderPayment_dot_3768782744": { "context": "order payment", "string": "PovolenÃĄ čiastka" @@ -2768,10 +2780,6 @@ "context": "order total price", "string": "Celkom" }, - "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_1542417144": { - "context": "dialog header", - "string": "Create Product" - }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2272209368": { "context": "variant sku", "string": "SKU {sku}" @@ -2779,6 +2787,10 @@ "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2336947364": { "string": "Search by product name, attribute, product type etc..." }, + "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2775402904": { + "context": "dialog header", + "string": "Add Product" + }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2850255786": { "string": "Search Products" }, @@ -2809,6 +2821,10 @@ "context": "section header", "string": "Unfulfilled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_693960049": { + "context": "ordered product sku", + "string": "SkladovÃĄ jednotka " + }, "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_878013594": { "context": "order line total price", "string": "Celkom" @@ -3621,17 +3637,14 @@ "context": "header", "string": "Počet" }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3143542809": { - "string": "This product doesn't have any stock. You can add it here." - }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3482985373": { - "context": "button", - "string": "Edit Warehouses" - }, "src_dot_products_dot_components_dot_ProductStocks_dot_3633706025": { "context": "product inventory, checkbox", "string": "Track Inventory" }, + "src_dot_products_dot_components_dot_ProductStocks_dot_3857433664": { + "context": "button", + "string": "Assign Warehouse" + }, "src_dot_products_dot_components_dot_ProductStocks_dot_849869830": { "string": "Active inventory tracking will automatically calculate changes of stock" }, @@ -3859,13 +3872,6 @@ "context": "product variant name", "string": "Varianta" }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_3482985373": { - "context": "dialog header", - "string": "Edit Warehouses" - }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_4112406382": { - "string": "Select warehouses that stock selected product" - }, "src_dot_products_dot_views_dot_1542417144": { "context": "window title", "string": "Create Product" @@ -4147,6 +4153,9 @@ "context": "window title", "string": "Create Service Account" }, + "src_dot_sessionExpired": { + "string": "Your session has expired. Please log in again to continue." + }, "src_dot_shipping": { "context": "shipping section name", "string": "Shipping Methods" diff --git a/locale/sl.json b/locale/sl.json index 8e6827a3d..164343b39 100644 --- a/locale/sl.json +++ b/locale/sl.json @@ -250,7 +250,7 @@ "context": "optional field", "string": "Optional" }, - "productVariantPriceOptionalPriceOverrideField": { + "productVariantPriceOptionalPriceField": { "context": "optional field", "string": "Optional" }, @@ -1675,6 +1675,10 @@ "context": "button", "string": "Delete" }, + "src_dot_demo": { + "context": "notification message after log in", + "string": "Just to let you know... You're in demo mode. You can play around with the dashboard but can't save changes." + }, "src_dot_description": { "string": "Opis" }, @@ -2532,6 +2536,10 @@ "context": "cancelled fulfillment, section header", "string": "Cancelled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderFulfillment_dot_693960049": { + "context": "ordered product sku", + "string": "SKU - ÅĄtevilka izdelka" + }, "src_dot_orders_dot_components_dot_OrderFulfillment_dot_732594284": { "context": "button", "string": "Cancel Fulfillment" @@ -2749,6 +2757,10 @@ "context": "order payment", "string": "Outstanding Balance" }, + "src_dot_orders_dot_components_dot_OrderPayment_dot_3720114122": { + "context": "order discount", + "string": "Discount" + }, "src_dot_orders_dot_components_dot_OrderPayment_dot_3768782744": { "context": "order payment", "string": "Preauthorized amount" @@ -2768,10 +2780,6 @@ "context": "order total price", "string": "Skupna vsota" }, - "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_1542417144": { - "context": "dialog header", - "string": "Create Product" - }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2272209368": { "context": "variant sku", "string": "SKU {sku}" @@ -2779,6 +2787,10 @@ "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2336947364": { "string": "Search by product name, attribute, product type etc..." }, + "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2775402904": { + "context": "dialog header", + "string": "Add Product" + }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2850255786": { "string": "Search Products" }, @@ -2809,6 +2821,10 @@ "context": "section header", "string": "Unfulfilled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_693960049": { + "context": "ordered product sku", + "string": "SKU - ÅĄtevilka izdelka" + }, "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_878013594": { "context": "order line total price", "string": "Skupna vsota" @@ -3621,17 +3637,14 @@ "context": "header", "string": "Količina" }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3143542809": { - "string": "This product doesn't have any stock. You can add it here." - }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3482985373": { - "context": "button", - "string": "Edit Warehouses" - }, "src_dot_products_dot_components_dot_ProductStocks_dot_3633706025": { "context": "product inventory, checkbox", "string": "Track Inventory" }, + "src_dot_products_dot_components_dot_ProductStocks_dot_3857433664": { + "context": "button", + "string": "Assign Warehouse" + }, "src_dot_products_dot_components_dot_ProductStocks_dot_849869830": { "string": "Active inventory tracking will automatically calculate changes of stock" }, @@ -3859,13 +3872,6 @@ "context": "product variant name", "string": "Različica" }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_3482985373": { - "context": "dialog header", - "string": "Edit Warehouses" - }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_4112406382": { - "string": "Select warehouses that stock selected product" - }, "src_dot_products_dot_views_dot_1542417144": { "context": "window title", "string": "Create Product" @@ -4147,6 +4153,9 @@ "context": "window title", "string": "Create Service Account" }, + "src_dot_sessionExpired": { + "string": "Your session has expired. Please log in again to continue." + }, "src_dot_shipping": { "context": "shipping section name", "string": "Shipping Methods" diff --git a/locale/sq.json b/locale/sq.json index 63d90102d..0852476eb 100644 --- a/locale/sq.json +++ b/locale/sq.json @@ -250,7 +250,7 @@ "context": "optional field", "string": "Optional" }, - "productVariantPriceOptionalPriceOverrideField": { + "productVariantPriceOptionalPriceField": { "context": "optional field", "string": "Optional" }, @@ -1675,6 +1675,10 @@ "context": "button", "string": "Delete" }, + "src_dot_demo": { + "context": "notification message after log in", + "string": "Just to let you know... You're in demo mode. You can play around with the dashboard but can't save changes." + }, "src_dot_description": { "string": "Pershkrimi" }, @@ -2532,6 +2536,10 @@ "context": "cancelled fulfillment, section header", "string": "Cancelled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderFulfillment_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderFulfillment_dot_732594284": { "context": "button", "string": "Anullo perfundimin" @@ -2749,6 +2757,10 @@ "context": "order payment", "string": "Outstanding Balance" }, + "src_dot_orders_dot_components_dot_OrderPayment_dot_3720114122": { + "context": "order discount", + "string": "Zbritje" + }, "src_dot_orders_dot_components_dot_OrderPayment_dot_3768782744": { "context": "order payment", "string": "Shuma e autorizuar me pare" @@ -2768,10 +2780,6 @@ "context": "order total price", "string": "Totali" }, - "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_1542417144": { - "context": "dialog header", - "string": "Create Product" - }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2272209368": { "context": "variant sku", "string": "SKU {sku}" @@ -2779,6 +2787,10 @@ "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2336947364": { "string": "Search by product name, attribute, product type etc..." }, + "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2775402904": { + "context": "dialog header", + "string": "Add Product" + }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2850255786": { "string": "Search Products" }, @@ -2809,6 +2821,10 @@ "context": "section header", "string": "Unfulfilled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_878013594": { "context": "order line total price", "string": "Totali" @@ -3621,17 +3637,14 @@ "context": "header", "string": "Sasia" }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3143542809": { - "string": "This product doesn't have any stock. You can add it here." - }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3482985373": { - "context": "button", - "string": "Edit Warehouses" - }, "src_dot_products_dot_components_dot_ProductStocks_dot_3633706025": { "context": "product inventory, checkbox", "string": "Track Inventory" }, + "src_dot_products_dot_components_dot_ProductStocks_dot_3857433664": { + "context": "button", + "string": "Assign Warehouse" + }, "src_dot_products_dot_components_dot_ProductStocks_dot_849869830": { "string": "Active inventory tracking will automatically calculate changes of stock" }, @@ -3859,13 +3872,6 @@ "context": "product variant name", "string": "Variant" }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_3482985373": { - "context": "dialog header", - "string": "Edit Warehouses" - }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_4112406382": { - "string": "Select warehouses that stock selected product" - }, "src_dot_products_dot_views_dot_1542417144": { "context": "window title", "string": "Create Product" @@ -4147,6 +4153,9 @@ "context": "window title", "string": "Create Service Account" }, + "src_dot_sessionExpired": { + "string": "Your session has expired. Please log in again to continue." + }, "src_dot_shipping": { "context": "shipping section name", "string": "Shipping Methods" diff --git a/locale/sr.json b/locale/sr.json index 6886b2995..efe8c4ce7 100644 --- a/locale/sr.json +++ b/locale/sr.json @@ -250,7 +250,7 @@ "context": "optional field", "string": "Optional" }, - "productVariantPriceOptionalPriceOverrideField": { + "productVariantPriceOptionalPriceField": { "context": "optional field", "string": "Optional" }, @@ -1675,6 +1675,10 @@ "context": "button", "string": "Delete" }, + "src_dot_demo": { + "context": "notification message after log in", + "string": "Just to let you know... You're in demo mode. You can play around with the dashboard but can't save changes." + }, "src_dot_description": { "string": "Opis" }, @@ -2532,6 +2536,10 @@ "context": "cancelled fulfillment, section header", "string": "Cancelled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderFulfillment_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderFulfillment_dot_732594284": { "context": "button", "string": "Cancel Fulfillment" @@ -2749,6 +2757,10 @@ "context": "order payment", "string": "Outstanding Balance" }, + "src_dot_orders_dot_components_dot_OrderPayment_dot_3720114122": { + "context": "order discount", + "string": "Discount" + }, "src_dot_orders_dot_components_dot_OrderPayment_dot_3768782744": { "context": "order payment", "string": "Preauthorized amount" @@ -2768,10 +2780,6 @@ "context": "order total price", "string": "Total" }, - "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_1542417144": { - "context": "dialog header", - "string": "Create Product" - }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2272209368": { "context": "variant sku", "string": "SKU {sku}" @@ -2779,6 +2787,10 @@ "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2336947364": { "string": "Search by product name, attribute, product type etc..." }, + "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2775402904": { + "context": "dialog header", + "string": "Add Product" + }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2850255786": { "string": "Search Products" }, @@ -2809,6 +2821,10 @@ "context": "section header", "string": "Unfulfilled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_878013594": { "context": "order line total price", "string": "Total" @@ -3621,17 +3637,14 @@ "context": "header", "string": "Količina" }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3143542809": { - "string": "This product doesn't have any stock. You can add it here." - }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3482985373": { - "context": "button", - "string": "Edit Warehouses" - }, "src_dot_products_dot_components_dot_ProductStocks_dot_3633706025": { "context": "product inventory, checkbox", "string": "Track Inventory" }, + "src_dot_products_dot_components_dot_ProductStocks_dot_3857433664": { + "context": "button", + "string": "Assign Warehouse" + }, "src_dot_products_dot_components_dot_ProductStocks_dot_849869830": { "string": "Active inventory tracking will automatically calculate changes of stock" }, @@ -3859,13 +3872,6 @@ "context": "product variant name", "string": "Variant" }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_3482985373": { - "context": "dialog header", - "string": "Edit Warehouses" - }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_4112406382": { - "string": "Select warehouses that stock selected product" - }, "src_dot_products_dot_views_dot_1542417144": { "context": "window title", "string": "Create Product" @@ -4147,6 +4153,9 @@ "context": "window title", "string": "Create Service Account" }, + "src_dot_sessionExpired": { + "string": "Your session has expired. Please log in again to continue." + }, "src_dot_shipping": { "context": "shipping section name", "string": "Shipping Methods" diff --git a/locale/sv.json b/locale/sv.json index 105db22f6..50d98c31d 100644 --- a/locale/sv.json +++ b/locale/sv.json @@ -250,7 +250,7 @@ "context": "optional field", "string": "Optional" }, - "productVariantPriceOptionalPriceOverrideField": { + "productVariantPriceOptionalPriceField": { "context": "optional field", "string": "Optional" }, @@ -1675,6 +1675,10 @@ "context": "button", "string": "Delete" }, + "src_dot_demo": { + "context": "notification message after log in", + "string": "Just to let you know... You're in demo mode. You can play around with the dashboard but can't save changes." + }, "src_dot_description": { "string": "Beskrivning" }, @@ -2532,6 +2536,10 @@ "context": "cancelled fulfillment, section header", "string": "Cancelled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderFulfillment_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderFulfillment_dot_732594284": { "context": "button", "string": "Avbryt kÃļp" @@ -2749,6 +2757,10 @@ "context": "order payment", "string": "Outstanding Balance" }, + "src_dot_orders_dot_components_dot_OrderPayment_dot_3720114122": { + "context": "order discount", + "string": "Rabatt" + }, "src_dot_orders_dot_components_dot_OrderPayment_dot_3768782744": { "context": "order payment", "string": "Summa fÃļr automatisk betalning" @@ -2768,10 +2780,6 @@ "context": "order total price", "string": "Totalsumma" }, - "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_1542417144": { - "context": "dialog header", - "string": "Create Product" - }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2272209368": { "context": "variant sku", "string": "SKU {sku}" @@ -2779,6 +2787,10 @@ "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2336947364": { "string": "Search by product name, attribute, product type etc..." }, + "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2775402904": { + "context": "dialog header", + "string": "Add Product" + }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2850255786": { "string": "Search Products" }, @@ -2809,6 +2821,10 @@ "context": "section header", "string": "Unfulfilled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_878013594": { "context": "order line total price", "string": "Totalsumma" @@ -3621,17 +3637,14 @@ "context": "header", "string": "Antal" }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3143542809": { - "string": "This product doesn't have any stock. You can add it here." - }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3482985373": { - "context": "button", - "string": "Edit Warehouses" - }, "src_dot_products_dot_components_dot_ProductStocks_dot_3633706025": { "context": "product inventory, checkbox", "string": "Track Inventory" }, + "src_dot_products_dot_components_dot_ProductStocks_dot_3857433664": { + "context": "button", + "string": "Assign Warehouse" + }, "src_dot_products_dot_components_dot_ProductStocks_dot_849869830": { "string": "Active inventory tracking will automatically calculate changes of stock" }, @@ -3859,13 +3872,6 @@ "context": "product variant name", "string": "Variant" }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_3482985373": { - "context": "dialog header", - "string": "Edit Warehouses" - }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_4112406382": { - "string": "Select warehouses that stock selected product" - }, "src_dot_products_dot_views_dot_1542417144": { "context": "window title", "string": "Create Product" @@ -4147,6 +4153,9 @@ "context": "window title", "string": "Create Service Account" }, + "src_dot_sessionExpired": { + "string": "Your session has expired. Please log in again to continue." + }, "src_dot_shipping": { "context": "shipping section name", "string": "Shipping Methods" diff --git a/locale/th.json b/locale/th.json index 0090da814..8e0227856 100644 --- a/locale/th.json +++ b/locale/th.json @@ -250,7 +250,7 @@ "context": "optional field", "string": "Optional" }, - "productVariantPriceOptionalPriceOverrideField": { + "productVariantPriceOptionalPriceField": { "context": "optional field", "string": "Optional" }, @@ -1675,6 +1675,10 @@ "context": "button", "string": "Delete" }, + "src_dot_demo": { + "context": "notification message after log in", + "string": "Just to let you know... You're in demo mode. You can play around with the dashboard but can't save changes." + }, "src_dot_description": { "string": "ā¸„ā¸ŗā¸­ā¸˜ā¸´ā¸šā¸˛ā¸ĸ⏞" }, @@ -2532,6 +2536,10 @@ "context": "cancelled fulfillment, section header", "string": "Cancelled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderFulfillment_dot_693960049": { + "context": "ordered product sku", + "string": "⏪ā¸Ģā¸ąā¸Ēā¸Ēā¸´ā¸™ā¸„āš‰ā¸˛" + }, "src_dot_orders_dot_components_dot_OrderFulfillment_dot_732594284": { "context": "button", "string": "Cancel Fulfillment" @@ -2749,6 +2757,10 @@ "context": "order payment", "string": "Outstanding Balance" }, + "src_dot_orders_dot_components_dot_OrderPayment_dot_3720114122": { + "context": "order discount", + "string": "ā¸Ēāšˆā¸§ā¸™ā¸Ĩ⏔" + }, "src_dot_orders_dot_components_dot_OrderPayment_dot_3768782744": { "context": "order payment", "string": "Preauthorized amount" @@ -2768,10 +2780,6 @@ "context": "order total price", "string": "ā¸Ŗā¸§ā¸Ąā¸—ā¸ąāš‰ā¸‡ā¸Ģā¸Ąā¸”" }, - "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_1542417144": { - "context": "dialog header", - "string": "Create Product" - }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2272209368": { "context": "variant sku", "string": "SKU {sku}" @@ -2779,6 +2787,10 @@ "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2336947364": { "string": "Search by product name, attribute, product type etc..." }, + "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2775402904": { + "context": "dialog header", + "string": "Add Product" + }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2850255786": { "string": "Search Products" }, @@ -2809,6 +2821,10 @@ "context": "section header", "string": "Unfulfilled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_693960049": { + "context": "ordered product sku", + "string": "⏪ā¸Ģā¸ąā¸Ēā¸Ēā¸´ā¸™ā¸„āš‰ā¸˛" + }, "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_878013594": { "context": "order line total price", "string": "ā¸Ŗā¸§ā¸Ąā¸—ā¸ąāš‰ā¸‡ā¸Ģā¸Ąā¸”" @@ -3621,17 +3637,14 @@ "context": "header", "string": "ā¸ˆā¸ŗā¸™ā¸§ā¸™" }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3143542809": { - "string": "This product doesn't have any stock. You can add it here." - }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3482985373": { - "context": "button", - "string": "Edit Warehouses" - }, "src_dot_products_dot_components_dot_ProductStocks_dot_3633706025": { "context": "product inventory, checkbox", "string": "Track Inventory" }, + "src_dot_products_dot_components_dot_ProductStocks_dot_3857433664": { + "context": "button", + "string": "Assign Warehouse" + }, "src_dot_products_dot_components_dot_ProductStocks_dot_849869830": { "string": "Active inventory tracking will automatically calculate changes of stock" }, @@ -3859,13 +3872,6 @@ "context": "product variant name", "string": "Variant" }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_3482985373": { - "context": "dialog header", - "string": "Edit Warehouses" - }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_4112406382": { - "string": "Select warehouses that stock selected product" - }, "src_dot_products_dot_views_dot_1542417144": { "context": "window title", "string": "Create Product" @@ -4147,6 +4153,9 @@ "context": "window title", "string": "Create Service Account" }, + "src_dot_sessionExpired": { + "string": "Your session has expired. Please log in again to continue." + }, "src_dot_shipping": { "context": "shipping section name", "string": "Shipping Methods" diff --git a/locale/tr.json b/locale/tr.json index 810c07f18..6e48b201a 100644 --- a/locale/tr.json +++ b/locale/tr.json @@ -250,7 +250,7 @@ "context": "optional field", "string": "İsteğe bağlÄą" }, - "productVariantPriceOptionalPriceOverrideField": { + "productVariantPriceOptionalPriceField": { "context": "optional field", "string": "İsteğe bağlÄą" }, @@ -296,7 +296,7 @@ }, "src_dot_accept": { "context": "button", - "string": "Accept" + "string": "Kabul et" }, "src_dot_attributes": { "context": "attributes section name", @@ -338,7 +338,7 @@ }, "src_dot_attributes_dot_components_dot_AttributeDetails_dot_3334509011": { "context": "product attribute type", - "string": "Multiple Select" + "string": "Çoklu Seçim" }, "src_dot_attributes_dot_components_dot_AttributeDetails_dot_3605174225": { "context": "attribute's slug short code label", @@ -568,10 +568,10 @@ }, "src_dot_cancelled": { "context": "order status", - "string": "Cancelled" + "string": "İptal Edildi" }, "src_dot_catalog": { - "string": "Catalog" + "string": "Katalog" }, "src_dot_categories": { "context": "categories section name", @@ -587,7 +587,7 @@ }, "src_dot_categories_dot_components_dot_CategoryCreatePage_dot_236319840": { "context": "page header", - "string": "Create New Category" + "string": "Yeni Kategori Oluştur" }, "src_dot_categories_dot_components_dot_CategoryCreatePage_dot_2563994280": { "string": "Add search engine title and description to make this category easier to find" @@ -608,7 +608,7 @@ }, "src_dot_categories_dot_components_dot_CategoryListPage_dot_1140231710": { "context": "button", - "string": "Create category" + "string": "Kategori oluştur" }, "src_dot_categories_dot_components_dot_CategoryListPage_dot_3841025483": { "string": "Search Category" @@ -682,11 +682,11 @@ }, "src_dot_categories_dot_components_dot_CategoryUpdatePage_dot_770296100": { "context": "button", - "string": "Create subcategory" + "string": "Alt kategori oluştur" }, "src_dot_categories_dot_views_dot_1140231710": { "context": "window title", - "string": "Create category" + "string": "Kategori oluştur" }, "src_dot_categories_dot_views_dot_1204353135": { "string": "{counter,plural,one {Are you sure you want to delete this product?} other {Are you sure you want to delete {displayQuantity} products?}}" @@ -1187,7 +1187,7 @@ }, "src_dot_components_dot_Navigator_dot_2935523260": { "context": "navigator placeholder", - "string": "Search in Catalog" + "string": "Katalogta ara" }, "src_dot_components_dot_Navigator_dot_3060198201": { "context": "navigator section header", @@ -1256,7 +1256,7 @@ }, "src_dot_components_dot_Navigator_dot_modes_dot_helpCatalogMode": { "context": "navigator catalog mode description", - "string": "Search in Catalog" + "string": "Katalogta ara" }, "src_dot_components_dot_Navigator_dot_modes_dot_helpCommandsMode": { "context": "navigator command mode description", @@ -1675,6 +1675,10 @@ "context": "button", "string": "Delete" }, + "src_dot_demo": { + "context": "notification message after log in", + "string": "Just to let you know... You're in demo mode. You can play around with the dashboard but can't save changes." + }, "src_dot_description": { "string": "AÃ§Äąklama" }, @@ -2532,6 +2536,10 @@ "context": "cancelled fulfillment, section header", "string": "Cancelled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderFulfillment_dot_693960049": { + "context": "ordered product sku", + "string": "Barkod" + }, "src_dot_orders_dot_components_dot_OrderFulfillment_dot_732594284": { "context": "button", "string": "Cancel Fulfillment" @@ -2749,6 +2757,10 @@ "context": "order payment", "string": "Outstanding Balance" }, + "src_dot_orders_dot_components_dot_OrderPayment_dot_3720114122": { + "context": "order discount", + "string": "İndirim" + }, "src_dot_orders_dot_components_dot_OrderPayment_dot_3768782744": { "context": "order payment", "string": "Preauthorized amount" @@ -2768,10 +2780,6 @@ "context": "order total price", "string": "Toplam" }, - "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_1542417144": { - "context": "dialog header", - "string": "Create Product" - }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2272209368": { "context": "variant sku", "string": "SKU {sku}" @@ -2779,6 +2787,10 @@ "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2336947364": { "string": "Search by product name, attribute, product type etc..." }, + "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2775402904": { + "context": "dialog header", + "string": "Add Product" + }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2850255786": { "string": "Search Products" }, @@ -2809,6 +2821,10 @@ "context": "section header", "string": "Unfulfilled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_693960049": { + "context": "ordered product sku", + "string": "Barkod" + }, "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_878013594": { "context": "order line total price", "string": "Toplam" @@ -3157,7 +3173,7 @@ }, "src_dot_permissionGroups_dot_views_dot_PermissionGroupCreate_dot_1140231710": { "context": "window title", - "string": "Create category" + "string": "Kategori oluştur" }, "src_dot_permissionGroups_dot_views_dot_PermissionGroupCreate_dot_3930588328": { "string": "Permission group created" @@ -3621,17 +3637,14 @@ "context": "header", "string": "Adet" }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3143542809": { - "string": "This product doesn't have any stock. You can add it here." - }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3482985373": { - "context": "button", - "string": "Edit Warehouses" - }, "src_dot_products_dot_components_dot_ProductStocks_dot_3633706025": { "context": "product inventory, checkbox", "string": "Track Inventory" }, + "src_dot_products_dot_components_dot_ProductStocks_dot_3857433664": { + "context": "button", + "string": "Assign Warehouse" + }, "src_dot_products_dot_components_dot_ProductStocks_dot_849869830": { "string": "Active inventory tracking will automatically calculate changes of stock" }, @@ -3859,13 +3872,6 @@ "context": "product variant name", "string": "Varyant" }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_3482985373": { - "context": "dialog header", - "string": "Edit Warehouses" - }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_4112406382": { - "string": "Select warehouses that stock selected product" - }, "src_dot_products_dot_views_dot_1542417144": { "context": "window title", "string": "Create Product" @@ -4147,6 +4153,9 @@ "context": "window title", "string": "Create Service Account" }, + "src_dot_sessionExpired": { + "string": "Your session has expired. Please log in again to continue." + }, "src_dot_shipping": { "context": "shipping section name", "string": "Shipping Methods" @@ -4817,7 +4826,7 @@ }, "src_dot_translations": { "context": "translations section name", - "string": "Translations" + "string": "Çeviriler" }, "src_dot_translations_dot_components_dot_TranslationFields_dot_1308081812": { "string": "{numberOfFields} Translations, {numberOfTranslatedFields} Completed" @@ -4883,7 +4892,7 @@ }, "src_dot_translations_dot_components_dot_TranslationsEntitiesListPage_dot_2460580333": { "context": "header", - "string": "Translations to {language}" + "string": "{language} Çeviriler" }, "src_dot_translations_dot_components_dot_TranslationsEntitiesListPage_dot_2559018090": { "string": "Search Page" @@ -4923,7 +4932,7 @@ "string": "No translatable entities found" }, "src_dot_translations_dot_components_dot_TranslationsEntitiesList_dot_49462429": { - "string": "Completed Translations" + "string": "TamamlanmÄąÅŸ Çeviriler" }, "src_dot_translations_dot_components_dot_TranslationsEntitiesList_dot_636461959": { "context": "entity (product, collection, shipping method) name", diff --git a/locale/uk.json b/locale/uk.json index 01a1c5170..d8ef664df 100644 --- a/locale/uk.json +++ b/locale/uk.json @@ -1,47 +1,47 @@ { "OrderCancelDialogHeader": { "context": "dialog header", - "string": "Đ’Ņ–Đ´ĐŧŅ–ĐŊĐ¸Ņ‚Đ¸ СаĐŧОвĐģĐĩĐŊĐŊŅ" + "string": "ĐĄĐēĐ°ŅŅƒĐ˛Đ°Ņ‚Đ¸ СаĐŧОвĐģĐĩĐŊĐŊŅ" }, "configurationMenuAttributes": { - "string": "Determine attributes used to create product types" + "string": "ВизĐŊĐ°Ņ‡Ņ‚Đĩ Đ°Ņ‚Ņ€Đ¸ĐąŅƒŅ‚Đ¸, ŅĐēŅ– виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅŽŅ‚ŅŒŅŅ Đ´ĐģŅ ŅŅ‚Đ˛ĐžŅ€ĐĩĐŊĐŊŅ Ņ‚Đ¸ĐŋŅ–Đ˛ Ņ‚ĐžĐ˛Đ°Ņ€Ņ–Đ˛" }, "configurationMenuNavigation": { - "string": "Define how users can navigate through your store" + "string": "ВизĐŊĐ°Ņ‡Ņ‚Đĩ, ŅĐēŅ– ĐēĐžŅ€Đ¸ŅŅ‚ŅƒĐ˛Đ°Ņ‡Ņ– ĐŧĐžĐļŅƒŅ‚ŅŒ ĐŋĐĩŅ€ĐĩĐŧŅ–Ņ‰Đ°Ņ‚Đ¸ŅŅ ĐŋĐž Đ˛Đ°ŅˆĐžĐŧ҃ ĐŧĐ°ĐŗĐ°ĐˇĐ¸ĐŊ҃" }, "configurationMenuPages": { - "string": "Manage and add additional pages" + "string": "ĐŖĐŋŅ€Đ°Đ˛ĐģŅ–ĐŊĐŊŅ Ņ‚Đ° дОдаваĐŊĐŊŅ Đ´ĐžĐŋĐžĐŧŅ–ĐļĐŊĐ¸Ņ… ŅŅ‚ĐžŅ€Ņ–ĐŊĐžĐē" }, "configurationMenuPermissionGroups": { - "string": "Manage your permission groups and their permissions" + "string": "ĐŖĐŋŅ€Đ°Đ˛ĐģŅ–ĐŊĐŊŅ ĐŗŅ€ŅƒĐŋаĐŧи дОСвОĐģŅ–Đ˛ Ņ‚Đ° Ņ—Ņ… дОСвОĐģаĐŧи" }, "configurationMenuProductTypes": { - "string": "Define types of products you sell" + "string": "ВизĐŊĐ°Ņ‡Ņ‚Đĩ Ņ‚Đ¸Đŋи Ņ‚ĐžĐ˛Đ°Ņ€Ņ–Đ˛, ŅĐēŅ– ви ĐŋŅ€ĐžĐ´Đ°Ņ”Ņ‚Đĩ" }, "configurationMenuShipping": { - "string": "Manage how you ship out orders" + "string": "ĐŖĐŋŅ€Đ°Đ˛ĐģŅ–ĐŊĐŊŅ, ŅĐē ви Đ˛Ņ–Đ´ĐŋŅ€Đ°Đ˛ĐģŅŅ”Ņ‚Đĩ СаĐŧОвĐģĐĩĐŊĐŊŅ" }, "configurationMenuSiteSettings": { - "string": "View and update your site settings" + "string": "ПĐĩŅ€ĐĩĐŗĐģŅĐ´ Ņ‚Đ° ĐžĐŊОвĐģĐĩĐŊĐŊŅ ĐŊаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°ĐŊҌ Đ˛Đ°ŅˆĐžĐŗĐž ŅĐ°ĐšŅ‚Ņƒ" }, "configurationMenuStaff": { - "string": "Manage your employees and their permissions" + "string": "ĐŖĐŋŅ€Đ°Đ˛ĐģŅ–ĐŊĐŊŅ ҁĐŋŅ–Đ˛Ņ€ĐžĐąŅ–Ņ‚ĐŊиĐēаĐŧи Ņ‚Đ° Ņ—Ņ… дОСвОĐģаĐŧи" }, "configurationMenuTaxes": { - "string": "Manage how your store charges tax" + "string": "ĐŖĐŋŅ€Đ°Đ˛ĐģŅ–ĐŊĐŊŅ, ŅĐē Đ˛Đ°Ņˆ ĐŧĐ°ĐŗĐ°ĐˇĐ¸ĐŊ ŅŅ‚ŅĐŗŅƒŅ” ĐŋĐžĐ´Đ°Ņ‚ĐžĐē" }, "configurationMenuWarehouses": { - "string": "Manage and update your warehouse information" + "string": "ĐŖĐŋŅ€Đ°Đ˛ĐģŅ–ĐŊĐŊŅ Ņ‚Đ° ĐžĐŊОвĐģĐĩĐŊĐŊŅ Ņ–ĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ— ĐŋŅ€Đž Đ˛Đ°Ņˆ ҁĐēĐģад" }, "configurationPluginsPages": { - "string": "View and update your plugins and their settings." + "string": "ПĐĩŅ€ĐĩĐŗĐģŅĐ´ Ņ‚Đ° ĐžĐŊОвĐģĐĩĐŊĐŊŅ ĐŋĐģĐ°ĐŗŅ–ĐŊŅ–Đ˛ Ņ‚Đ° Ņ—Ņ… ĐŊаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°ĐŊҌ" }, "homeActivityCardHeader": { "context": "header", "string": "АĐēŅ‚Đ¸Đ˛ĐŊŅ–ŅŅ‚ŅŒ" }, "homeActivityCardNoActivities": { - "string": "No activities found" + "string": "НĐĩ СĐŊаКдĐĩĐŊĐž Đ´Ņ–ŅĐģҌĐŊĐžŅŅ‚Ņ–" }, "homeAnalyticsCardHeader": { "string": "ĐĄŅŒĐžĐŗĐžĐ´ĐŊŅ–" @@ -52,13 +52,13 @@ }, "homeHeaderTextCaption": { "context": "subheader", - "string": "Here is some information we gathered about your store" + "string": "ĐžŅŅŒ Đ´ĐĩŅĐēŅ– Đ˛Ņ–Đ´ĐžĐŧĐžŅŅ‚Ņ–, ŅĐēŅ– Đŧи ĐˇŅ–ĐąŅ€Đ°Đģи ĐŋŅ€Đž Đ˛Đ°Ņˆ ĐŧĐ°ĐŗĐ°ĐˇĐ¸ĐŊ" }, "homeNotificationTableNoOrders": { - "string": "No orders ready to fulfill" + "string": "ЗаĐŧОвĐģĐĩĐŊĐŊŅ ĐŊĐĩ ĐŗĐžŅ‚ĐžĐ˛Ņ– Đ´Đž виĐēĐžĐŊаĐŊĐŊŅ" }, "homeNotificationTableOrders": { - "string": "{amount, plural,one {One order is ready to fulfill} other {{amount} Orders are ready to fulfill}}" + "string": "{amount, plural,one {ЗаĐŧОвĐģĐĩĐŊĐŊŅ ĐŗĐžŅ‚ĐžĐ˛Đĩ Đ´Đž виĐēĐžĐŊаĐŊĐŊŅ} few {{amount} ЗаĐŧОвĐģĐĩĐŊĐŊŅ ĐŗĐžŅ‚ĐžĐ˛Ņ– Đ´Đž виĐēĐžĐŊаĐŊĐŊŅ} many {{amount} ЗаĐŧОвĐģĐĩĐŊҌ ĐŗĐžŅ‚ĐžĐ˛Ņ– Đ´Đž виĐēĐžĐŊаĐŊĐŊŅ} other {{amount} ЗаĐŧОвĐģĐĩĐŊĐŊŅ ĐŗĐžŅ‚ĐžĐ˛Ņ– Đ´Đž виĐēĐžĐŊаĐŊĐŊŅ}}" }, "homeNotificationTablePayments": { "string": "{amount, plural,one {One payment to capture} other {{amount} Payments to capture}}" @@ -70,7 +70,7 @@ "string": "No payments waiting for capture" }, "homeNotificationsTableNoProducts": { - "string": "No products out of stock" + "string": "НĐĩĐŧĐ°Ņ” Ņ‚ĐžĐ˛Đ°Ņ€Ņ–Đ˛ ĐŊа ҁĐēĐģĐ°Đ´Ņ–" }, "homeProductListCardOrders": { "context": "number of ordered products", @@ -78,10 +78,10 @@ }, "homeProductsListCardHeader": { "context": "header", - "string": "Top Products" + "string": "ПоĐŋ҃ĐģŅŅ€ĐŊŅ– Ņ‚ĐžĐ˛Đ°Ņ€Đ¸" }, "homeProductsListCardNoProducts": { - "string": "No products found" + "string": "НĐĩ СĐŊаКдĐĩĐŊĐž ĐļОдĐŊĐžĐŗĐž Ņ‚ĐžĐ˛Đ°Ņ€Ņƒ" }, "homeScreenDisclaimer": { "context": "header", @@ -99,17 +99,17 @@ }, "menuCreateDialogHeader": { "context": "dialog header", - "string": "Create Menu" + "string": "ĐĄŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ ĐŧĐĩĐŊŅŽ" }, "menuCreateDialogMenuTitleLabel": { "string": "Menu Title" }, "menuDetailsDeleteMenuContent": { - "string": "Are you sure you want to delete menu {menuName}?" + "string": "Ви вĐŋĐĩвĐŊĐĩĐŊŅ–, Ņ‰Đž Ņ…ĐžŅ‡ĐĩŅ‚Đĩ видаĐģĐ¸Ņ‚Đ¸ ĐŧĐĩĐŊŅŽ {menuName}?" }, "menuDetailsDeleteMenuHeader": { "context": "dialog header", - "string": "Delete Menu" + "string": "ВидаĐģĐ¸Ņ‚Đ¸ ĐŧĐĩĐŊŅŽ" }, "menuDetailsPageHelperText": { "string": "Creating the navigation structure is done by dragging and dropping. Simply create a new menu item and then drag it into its destined place. You can move items inside one another to create a tree structure and drag items up and down to create a hierarchy" @@ -120,18 +120,18 @@ }, "menuItemDialogAddLink": { "context": "add link to navigation", - "string": "Link to: {url}" + "string": "ĐŸĐžŅĐ¸ĐģаĐŊĐŊŅ Đ´Đž: {url}" }, "menuItemDialogEditItem": { "context": "edit menu item, header", - "string": "Edit Item" + "string": "Đ ĐĩĐ´Đ°ĐŗŅƒĐ˛Đ°Ņ‚Đ¸ ĐĩĐģĐĩĐŧĐĩĐŊŅ‚" }, "menuItemDialogLinkLabel": { "context": "label", "string": "ĐŸĐžŅĐ¸ĐģаĐŊĐŊŅ" }, "menuItemDialogLinkPlaceholder": { - "string": "Start typing to begin search..." + "string": "ĐŸĐžŅ‡ĐŊŅ–Ņ‚ŅŒ Đ˛Đ˛ĐžĐ´Đ¸Ņ‚Đ¸ Ņ‚ĐĩĐēҁ҂, Ņ‰ĐžĐą Ņ€ĐžĐˇĐŋĐžŅ‡Đ°Ņ‚Đ¸ ĐŋĐžŅˆŅƒĐē..." }, "menuItemDialogNameLabel": { "context": "menu item name", @@ -139,34 +139,34 @@ }, "menuItemsAddItem": { "context": "add new menu item", - "string": "Create new item" + "string": "ĐĄŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ ĐŊОвиК ĐĩĐģĐĩĐŧĐĩĐŊŅ‚" }, "menuItemsHeader": { "context": "header", - "string": "Menu Items" + "string": "ĐŸŅƒĐŊĐēŅ‚Đ¸ ĐŧĐĩĐŊŅŽ" }, "menuItemsPlaceholder": { "string": "Đ”ĐžĐ´Đ°Ņ‚Đ¸ ĐŊОвиК Đŋ҃ĐŊĐēŅ‚ ĐŧĐĩĐŊŅŽ, Ņ‰ĐžĐą Ņ€ĐžĐˇĐŋĐžŅ‡Đ°Ņ‚Đ¸ Ņ€ĐžĐąĐžŅ‚Ņƒ С ĐŧĐĩĐŊŅŽ" }, "menuListCreatedMenu": { - "string": "Created menu" + "string": "МĐĩĐŊŅŽ ŅŅ‚Đ˛ĐžŅ€ĐĩĐŊĐž" }, "menuListDeleteMenuContent": { - "string": "Are you sure you want to delete {menuName}?" + "string": "Ви вĐŋĐĩвĐŊĐĩĐŊŅ–, Ņ‰Đž Ņ…ĐžŅ‡ĐĩŅ‚Đĩ видаĐģĐ¸Ņ‚Đ¸ {menuName}?" }, "menuListDeleteMenuHeader": { "context": "dialog header", - "string": "Delete Menu" + "string": "ВидаĐģĐ¸Ņ‚Đ¸ ĐŧĐĩĐŊŅŽ" }, "menuListDeleteMenusContent": { "string": "{counter,plural,one {Are you sure you want to delete this menu?} other {Are you sure you want to delete {displayQuantity} menus?}}" }, "menuListDeleteMenusHeader": { "context": "dialog header", - "string": "Delete Menus" + "string": "ВидаĐģĐ¸Ņ‚Đ¸ ĐŧĐĩĐŊŅŽ" }, "menuListDeletedMenu": { - "string": "Deleted menu" + "string": "ВидаĐģĐ¸Ņ‚Đ¸ ĐŧĐĩĐŊŅŽ" }, "menuListItems": { "context": "number of menu items", @@ -180,7 +180,7 @@ }, "menuListPageAddMenu": { "context": "button", - "string": "Create Menu" + "string": "ĐĄŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ ĐŧĐĩĐŊŅŽ" }, "menuPropertiesMenuTitle": { "string": "Menu Title" @@ -199,11 +199,11 @@ }, "orderPaymentShippingDoesNotApply": { "context": "order does not require shipping", - "string": "does not apply" + "string": "ĐŊĐĩ ĐˇĐ°ŅŅ‚ĐžŅĐžĐ˛ŅƒŅ”Ņ‚ŅŒŅŅ" }, "orderPaymentVATDoesNotApply": { "context": "vat not included in order price", - "string": "does not apply" + "string": "ĐŊĐĩ ĐˇĐ°ŅŅ‚ĐžŅĐžĐ˛ŅƒŅ”Ņ‚ŅŒŅŅ" }, "productStatusLabel": { "context": "product", @@ -215,18 +215,18 @@ }, "productTypeCreateHeader": { "context": "window title", - "string": "Create Product Type" + "string": "ĐĄŅ‚Đ˛ĐžŅ€Ņ–Ņ‚ŅŒ Ņ‚Đ¸Đŋ Ņ‚ĐžĐ˛Đ°Ņ€Ņƒ" }, "productTypeCreatePageHeader": { "context": "header", - "string": "Create Product Type" + "string": "ĐĄŅ‚Đ˛ĐžŅ€Ņ–Ņ‚ŅŒ Ņ‚Đ¸Đŋ Ņ‚ĐžĐ˛Đ°Ņ€Ņƒ" }, "productTypeTaxesHeader": { "context": "section header", - "string": "Taxes" + "string": "ĐŸĐžĐ´Đ°Ņ‚Đēи" }, "productTypeTaxesInputLabel": { - "string": "Taxes" + "string": "ĐŸĐžĐ´Đ°Ņ‚Đēи" }, "productVariantCreatePricesPriceInputLabel": { "string": "ĐĻŅ–ĐŊа" @@ -244,23 +244,23 @@ }, "productVariantCreatorWarehouseSectionHeader": { "context": "header", - "string": "Warehouses" + "string": "ĐĄĐēĐģади" }, "productVariantPriceOptionalCostPriceField": { "context": "optional field", "string": "Optional" }, - "productVariantPriceOptionalPriceOverrideField": { + "productVariantPriceOptionalPriceField": { "context": "optional field", "string": "Optional" }, "saleDetailsPageCategoriesQuantity": { "context": "number of categories", - "string": "Categories ({quantity})" + "string": "ĐšĐ°Ņ‚ĐĩĐŗĐžŅ€Ņ–Ņ— ({quantity})" }, "saleDetailsPageCollectionsQuantity": { "context": "number of collections", - "string": "Collections ({quantity})" + "string": "КоĐģĐĩĐē҆Җҗ ({quantity})" }, "saleDetailsPageProductsQuantity": { "context": "number of products", @@ -268,15 +268,15 @@ }, "saleDetailsUnassignCategory": { "context": "unassign category from sale, button", - "string": "Unassign" + "string": "ĐĄĐēĐ°ŅŅƒĐ˛Đ°Ņ‚Đ¸" }, "saleDetailsUnassignCollection": { "context": "unassign collection from sale, button", - "string": "Unassign" + "string": "ĐĄĐēĐ°ŅŅƒĐ˛Đ°Ņ‚Đ¸" }, "saleDetailsUnassignProduct": { "context": "unassign product from sale, button", - "string": "Unassign" + "string": "ĐĄĐēĐ°ŅŅƒĐ˛Đ°Ņ‚Đ¸" }, "shippingZoneDetailsDialogsDeleteShippingMethod": { "context": "delete shipping method", @@ -314,7 +314,7 @@ }, "src_dot_attributes_dot_components_dot_AttributeBulkDeleteDialog_dot_1655187315": { "context": "dialog title", - "string": "Delete attributes" + "string": "ВидаĐģĐ¸Ņ‚Đ¸ Đ°Ņ‚Ņ€Đ¸ĐąŅƒŅ‚Đ¸" }, "src_dot_attributes_dot_components_dot_AttributeDeleteDialog_dot_1889602489": { "context": "dialog title", @@ -322,7 +322,7 @@ }, "src_dot_attributes_dot_components_dot_AttributeDeleteDialog_dot_3738429348": { "context": "dialog content", - "string": "Are you sure you want to delete {attributeName}?" + "string": "Ви вĐŋĐĩвĐŊĐĩĐŊŅ–, Ņ‰Đž Ņ…ĐžŅ‡ĐĩŅ‚Đĩ видаĐģĐ¸Ņ‚Đ¸ {attributeName}?" }, "src_dot_attributes_dot_components_dot_AttributeDetails_dot_1005562666": { "context": "attribute's editor component", @@ -334,7 +334,7 @@ }, "src_dot_attributes_dot_components_dot_AttributeDetails_dot_2592224946": { "context": "check to require attribute to have value", - "string": "Value Required" + "string": "НĐĩĐžĐąŅ…Ņ–Đ´ĐŊĐĩ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ" }, "src_dot_attributes_dot_components_dot_AttributeDetails_dot_3334509011": { "context": "product attribute type", @@ -342,7 +342,7 @@ }, "src_dot_attributes_dot_components_dot_AttributeDetails_dot_3605174225": { "context": "attribute's slug short code label", - "string": "Attribute Code" + "string": "Код Đ°Ņ‚Ņ€Đ¸ĐąŅƒŅ‚Ņƒ" }, "src_dot_attributes_dot_components_dot_AttributeDetails_dot_4107478955": { "context": "attribute slug input field helper text", @@ -350,7 +350,7 @@ }, "src_dot_attributes_dot_components_dot_AttributeDetails_dot_691600601": { "context": "attribute's label", - "string": "Default Label" + "string": "ĐœŅ–Ņ‚Đēа Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ" }, "src_dot_attributes_dot_components_dot_AttributeListPage_dot_2417065806": { "context": "tab name", @@ -358,7 +358,7 @@ }, "src_dot_attributes_dot_components_dot_AttributeListPage_dot_3824684885": { "context": "button", - "string": "Create attribute" + "string": "ĐĄŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ Đ°Ņ‚Ņ€Đ¸ĐąŅƒŅ‚" }, "src_dot_attributes_dot_components_dot_AttributeListPage_dot_3916653510": { "string": "Search Attribute" @@ -377,45 +377,45 @@ }, "src_dot_attributes_dot_components_dot_AttributeListPage_dot_isVariantOnly": { "context": "attribute can be used only in variants", - "string": "Variant Only" + "string": "ĐĸŅ–ĐģҌĐēи Đ˛Đ°Ņ€Ņ–Đ°ĐŊŅ‚" }, "src_dot_attributes_dot_components_dot_AttributeListPage_dot_valueRequired": { "context": "attribute value is required", - "string": "Value Required" + "string": "НĐĩĐžĐąŅ…Ņ–Đ´ĐŊĐĩ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ" }, "src_dot_attributes_dot_components_dot_AttributeListPage_dot_visibleInStorefront": { "context": "attribute", - "string": "Visible on Product Page in Storefront" + "string": "Đ’Ņ–Đ´ĐžĐŧиК ĐŊа ŅŅ‚ĐžŅ€Ņ–ĐŊ҆Җ ĐŋŅ€ĐžĐ´ŅƒĐēŅ‚Ņƒ ҃ Đ˛Ņ–Ņ‚Ņ€Đ¸ĐŊŅ–" }, "src_dot_attributes_dot_components_dot_AttributeList_dot_1192828581": { "string": "No attributes found" }, "src_dot_attributes_dot_components_dot_AttributeList_dot_2186555805": { "context": "attribute can be searched in storefront", - "string": "Use in faceted search" + "string": "ВиĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ ĐŋŅ€Đ¸ ĐąĐ°ĐŗĐ°Ņ‚ĐžŅ„ŅƒĐŊĐēŅ†Ņ–ĐžĐŊаĐģҌĐŊĐžĐŧ҃ ĐŋĐžŅˆŅƒĐē҃" }, "src_dot_attributes_dot_components_dot_AttributeList_dot_2235596452": { "context": "attribute can be searched in dashboard", "string": "Searchable" }, "src_dot_attributes_dot_components_dot_AttributeList_dot_3605174225": { - "string": "Attribute Code" + "string": "Код Đ°Ņ‚Ņ€Đ¸ĐąŅƒŅ‚Ņƒ" }, "src_dot_attributes_dot_components_dot_AttributeList_dot_643174786": { "context": "attribute is visible", - "string": "Visible" + "string": "ВидиĐŧиК" }, "src_dot_attributes_dot_components_dot_AttributeList_dot_691600601": { "context": "attribute's label'", - "string": "Default Label" + "string": "ĐœŅ–Ņ‚Đēа Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ" }, "src_dot_attributes_dot_components_dot_AttributePage_dot_2855501559": { "context": "page title", - "string": "Create New Attribute" + "string": "ĐĄŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ ĐŊОвиК Đ°Ņ‚Ņ€Đ¸ĐąŅƒŅ‚" }, "src_dot_attributes_dot_components_dot_AttributeProperties_dot_1318123158": { "context": "attribute is filterable in storefront", - "string": "Use in Faceted Navigation" + "string": "ВиĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ в ĐąĐ°ĐŗĐ°Ņ‚ĐžĐ°ŅĐŋĐĩĐēŅ‚ĐŊŅ–Đš ĐŊĐ°Đ˛Ņ–ĐŗĐ°Ņ†Ņ–Ņ—" }, "src_dot_attributes_dot_components_dot_AttributeProperties_dot_1877630205": { "context": "attribute properties regarding storefront", @@ -423,7 +423,7 @@ }, "src_dot_attributes_dot_components_dot_AttributeProperties_dot_26409543": { "context": "attribute properties regarding dashboard", - "string": "Dashboard Properties" + "string": "ВĐģĐ°ŅŅ‚Đ¸Đ˛ĐžŅŅ‚Ņ– Ņ–ĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–ĐšĐŊĐžŅ— ĐŋаĐŊĐĩĐģŅ–" }, "src_dot_attributes_dot_components_dot_AttributeProperties_dot_3590282519": { "context": "attribute position in storefront filters", @@ -431,7 +431,7 @@ }, "src_dot_attributes_dot_components_dot_AttributeProperties_dot_3876764312": { "context": "attribute", - "string": "Visible on Product Page in Storefront" + "string": "Đ’Ņ–Đ´ĐžĐŧиК ĐŊа ŅŅ‚ĐžŅ€Ņ–ĐŊ҆Җ ĐŋŅ€ĐžĐ´ŅƒĐēŅ‚Ņƒ ҃ Đ˛Ņ–Ņ‚Ņ€Đ¸ĐŊŅ–" }, "src_dot_attributes_dot_components_dot_AttributeProperties_dot_4048785456": { "string": "If enabled this attribute can be used as a column in product table." @@ -442,21 +442,21 @@ }, "src_dot_attributes_dot_components_dot_AttributeProperties_dot_714335445": { "context": "use attribute in filtering", - "string": "Use in Filtering" + "string": "ВиĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ ҃ ҄ҖĐģŅŒŅ‚Ņ€ŅƒĐ˛Đ°ĐŊĐŊŅ–" }, "src_dot_attributes_dot_components_dot_AttributeProperties_dot_787251583": { "string": "If enabled, you’ll be able to use this attribute to filter products in product list." }, "src_dot_attributes_dot_components_dot_AttributeValueDeleteDialog_dot_1326420604": { "context": "delete attribute value", - "string": "Are you sure you want to delete \"{name}\" value?" + "string": "Ви вĐŋĐĩвĐŊĐĩĐŊŅ–, Ņ‰Đž Ņ…ĐžŅ‡ĐĩŅ‚Đĩ видаĐģĐ¸Ņ‚Đ¸ \"{name}\" СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ?" }, "src_dot_attributes_dot_components_dot_AttributeValueDeleteDialog_dot_203246037": { "context": "dialog title", - "string": "Delete attribute value" + "string": "ВидаĐģĐ¸Ņ‚Đ¸ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Đ°Ņ‚Ņ€Đ¸ĐąŅƒŅ‚Đ°" }, "src_dot_attributes_dot_components_dot_AttributeValueDeleteDialog_dot_4031078167": { - "string": "Are you sure you want to delete \"{name}\" value? If you delete it you won’t be able to assign it to any of the products with \"{attributeName}\" attribute." + "string": "Ви вĐŋĐĩвĐŊĐĩĐŊŅ–, Ņ‰Đž Ņ…ĐžŅ‡ĐĩŅ‚Đĩ видаĐģĐ¸Ņ‚Đ¸ \"{name}\" СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ? Đ¯ĐēŅ‰Đž ви видаĐģĐ¸Ņ‚Đĩ ĐšĐžĐŗĐž, ви ĐŊĐĩ СĐŧĐžĐļĐĩŅ‚Đĩ ĐŋŅ€Đ¸ĐˇĐŊĐ°Ņ‡Đ¸Ņ‚Đ¸ ĐšĐžĐŗĐž ĐļОдĐŊĐžĐŧ҃ С ĐŋŅ€ĐžĐ´ŅƒĐēŅ‚Ņ–Đ˛ С \"{attributeName}\" вĐģĐ°ŅŅ‚Đ¸Đ˛Ņ–ŅŅ‚ŅŽ." }, "src_dot_attributes_dot_components_dot_AttributeValueEditDialog_dot_1395607402": { "context": "edit attribute value", @@ -472,11 +472,11 @@ }, "src_dot_attributes_dot_components_dot_AttributeValues_dot_1397696159": { "context": "attribute values list: name column header", - "string": "Default Store View" + "string": "ПĐĩŅ€ĐĩĐŗĐģŅĐ´ ĐŧĐ°ĐŗĐ°ĐˇĐ¸ĐŊ҃ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ" }, "src_dot_attributes_dot_components_dot_AttributeValues_dot_1565474525": { "context": "attribute values list: slug column header", - "string": "Admin" + "string": "АдĐŧŅ–ĐŊŅ–ŅŅ‚Ņ€Đ°Ņ‚ĐžŅ€" }, "src_dot_attributes_dot_components_dot_AttributeValues_dot_2054206599": { "context": "No attribute values found", @@ -484,21 +484,21 @@ }, "src_dot_attributes_dot_components_dot_AttributeValues_dot_224159874": { "context": "section header", - "string": "Attribute Values" + "string": "ЗĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Đ°Ņ‚Ņ€Đ¸ĐąŅƒŅ‚Ņƒ" }, "src_dot_attributes_dot_components_dot_AttributeValues_dot_351422234": { "context": "assign attribute value button", - "string": "Assign value" + "string": "ĐŸŅ€Đ¸ĐˇĐŊĐ°Ņ‡Đ¸Ņ‚Đ¸ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ" }, "src_dot_attributes_dot_views_dot_AttributeCreate_dot_11941964": { "string": "Successfully created attribute" }, "src_dot_attributes_dot_views_dot_AttributeDetails_dot_423042761": { "context": "attribute value deleted", - "string": "Value deleted" + "string": "ЗĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ видаĐģĐĩĐŊĐž" }, "src_dot_attributes_dot_views_dot_AttributeDetails_dot_499456739": { - "string": "Attribute deleted" + "string": "ĐŅ‚Ņ€Đ¸ĐąŅƒŅ‚ видаĐģĐĩĐŊĐž" }, "src_dot_attributes_dot_views_dot_AttributeDetails_dot_634268988": { "context": "added new attribute value", @@ -506,7 +506,7 @@ }, "src_dot_attributes_dot_views_dot_AttributeList_dot_3218248395": { "context": "deleted multiple attributes", - "string": "Attributes successfully delete" + "string": "ĐŅ‚Ņ€Đ¸ĐąŅƒŅ‚Đ¸ ҃ҁĐŋŅ–ŅˆĐŊĐž видаĐģŅŅŽŅ‚ŅŒŅŅ" }, "src_dot_auth_dot_components_dot_LoginPage_dot_109182747": { "context": "button", @@ -533,7 +533,7 @@ "string": "Set new password" }, "src_dot_auth_dot_components_dot_NewPasswordPage_dot_2799926859": { - "string": "Confirm Password" + "string": "ĐŸŅ–Đ´Ņ‚Đ˛ĐĩŅ€Đ´Ņ–Ņ‚ŅŒ ĐŋĐ°Ņ€ĐžĐģҌ" }, "src_dot_auth_dot_components_dot_NewPasswordPage_dot_4253911811": { "string": "Passwords do not match" @@ -547,7 +547,7 @@ }, "src_dot_auth_dot_components_dot_ResetPasswordSuccessPage_dot_2245157344": { "context": "button", - "string": "Back to login" + "string": "ПовĐĩŅ€ĐŊŅƒŅ‚Đ¸ŅŅ Đ´Đž Đ°Đ˛Ņ‚ĐžŅ€Đ¸ĐˇĐ°Ņ†Ņ–Ņ—" }, "src_dot_auth_dot_components_dot_ResetPasswordSuccessPage_dot_4066297200": { "string": "Success! In a few minutes you’ll receive a message with instructions on how to reset your password." @@ -556,11 +556,11 @@ "string": "Provided email address does not exist in our database." }, "src_dot_availability": { - "string": "Availability" + "string": "Đ”ĐžŅŅ‚ŅƒĐŋĐŊŅ–ŅŅ‚ŅŒ" }, "src_dot_back": { "context": "button", - "string": "Back" + "string": "Назад" }, "src_dot_cancel": { "context": "button", @@ -579,7 +579,7 @@ }, "src_dot_categories_dot_components_dot_CategoryBackground_dot_2224943474": { "context": "section header", - "string": "Background Image (optional)" + "string": "ФОĐŊОвĐĩ ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊĐŊŅ (ĐŊĐĩĐžĐąĐžĐ˛â€™ŅĐˇĐēОвО)" }, "src_dot_categories_dot_components_dot_CategoryBackground_dot_3289097895": { "context": "field is optional", @@ -587,7 +587,7 @@ }, "src_dot_categories_dot_components_dot_CategoryCreatePage_dot_236319840": { "context": "page header", - "string": "Create New Category" + "string": "ĐĄŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ ĐŊĐžĐ˛Ņƒ ĐēĐ°Ņ‚ĐĩĐŗĐžŅ€Ņ–ŅŽ" }, "src_dot_categories_dot_components_dot_CategoryCreatePage_dot_2563994280": { "string": "Đ”ĐžĐ´Đ°Ņ‚Đ¸ ĐˇĐ°ĐŗĐžĐģОвОĐē Ņ‚Đ° ĐžĐŋĐ¸Ņ Đ´ĐģŅ ĐŋĐžŅˆŅƒĐēĐžĐ˛ĐžŅ— ŅĐ¸ŅŅ‚ĐĩĐŧи, Ņ‰ĐžĐą ĐŋĐžĐģĐĩĐŗŅˆĐ¸Ņ‚Đ¸ ĐŋĐžŅˆŅƒĐē ҆ҖҔҗ ĐēĐ°Ņ‚ĐĩĐŗĐžŅ€Ņ–Ņ—" @@ -598,17 +598,17 @@ }, "src_dot_categories_dot_components_dot_CategoryDeleteDialog_dot_847492725": { "context": "delete category", - "string": "Are you sure you want to delete {categoryName}?" + "string": "Ви вĐŋĐĩвĐŊĐĩĐŊŅ–, Ņ‰Đž Ņ…ĐžŅ‡ĐĩŅ‚Đĩ видаĐģĐ¸Ņ‚Đ¸ {categoryName}?" }, "src_dot_categories_dot_components_dot_CategoryDetailsForm_dot_1214235329": { - "string": "Category Name" + "string": "Назва ĐēĐ°Ņ‚ĐĩĐŗĐžŅ€Ņ–Ņ—" }, "src_dot_categories_dot_components_dot_CategoryDetailsForm_dot_4037703468": { - "string": "Category Description" + "string": "ОĐŋĐ¸Ņ ĐēĐ°Ņ‚ĐĩĐŗĐžŅ€Ņ–Ņ—" }, "src_dot_categories_dot_components_dot_CategoryListPage_dot_1140231710": { "context": "button", - "string": "Create category" + "string": "ĐĄŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ ĐēĐ°Ņ‚ĐĩĐŗĐžŅ€Ņ–ŅŽ" }, "src_dot_categories_dot_components_dot_CategoryListPage_dot_3841025483": { "string": "Search Category" @@ -618,7 +618,7 @@ "string": "Đ’ŅŅ– ĐēĐ°Ņ‚ĐĩĐŗĐžŅ€Ņ–Ņ—" }, "src_dot_categories_dot_components_dot_CategoryList_dot_1214235329": { - "string": "Category Name" + "string": "Назва ĐēĐ°Ņ‚ĐĩĐŗĐžŅ€Ņ–Ņ—" }, "src_dot_categories_dot_components_dot_CategoryList_dot_2054128296": { "string": "No categories found" @@ -639,11 +639,11 @@ "string": "ĐĻŅ–ĐŊа" }, "src_dot_categories_dot_components_dot_CategoryProductList_dot_1657559629": { - "string": "No products found" + "string": "НĐĩ СĐŊаКдĐĩĐŊĐž ĐļОдĐŊĐžĐŗĐž Ņ‚ĐžĐ˛Đ°Ņ€Ņƒ" }, "src_dot_categories_dot_components_dot_CategoryProductList_dot_1952810469": { "context": "product type", - "string": "Type" + "string": "ĐĸиĐŋ" }, "src_dot_categories_dot_components_dot_CategoryProductList_dot_2341910657": { "context": "product", @@ -682,17 +682,17 @@ }, "src_dot_categories_dot_components_dot_CategoryUpdatePage_dot_770296100": { "context": "button", - "string": "Create subcategory" + "string": "ĐĄŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ ĐŋŅ–Đ´ĐēĐ°Ņ‚ĐĩĐŗĐžŅ€Ņ–ŅŽ" }, "src_dot_categories_dot_views_dot_1140231710": { "context": "window title", - "string": "Create category" + "string": "ĐĄŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ ĐēĐ°Ņ‚ĐĩĐŗĐžŅ€Ņ–ŅŽ" }, "src_dot_categories_dot_views_dot_1204353135": { "string": "{counter,plural,one {Are you sure you want to delete this product?} other {Are you sure you want to delete {displayQuantity} products?}}" }, "src_dot_categories_dot_views_dot_1754466114": { - "string": "Category created" + "string": "ĐšĐ°Ņ‚ĐĩĐŗĐžŅ€Ņ–Ņ ŅŅ‚Đ˛ĐžŅ€ĐĩĐŊа" }, "src_dot_categories_dot_views_dot_1823337870": { "string": "{counter,plural,one {Are you sure you want to delete this category?} other {Are you sure you want to delete {displayQuantity} categories?}}" @@ -702,21 +702,21 @@ "string": "ВидаĐģĐ¸Ņ‚Đ¸ ĐēĐ°Ņ‚ĐĩĐŗĐžŅ€Ņ–ŅŽ" }, "src_dot_categories_dot_views_dot_2189424032": { - "string": "Category deleted" + "string": "ĐšĐ°Ņ‚ĐĩĐŗĐžŅ€Ņ–Ņ видаĐģĐĩĐŊа" }, "src_dot_categories_dot_views_dot_2507763081": { "context": "dialog title", - "string": "Delete products" + "string": "ВидаĐģĐ¸Ņ‚Đ¸ Ņ‚ĐžĐ˛Đ°Ņ€Đ¸" }, "src_dot_categories_dot_views_dot_3488150607": { "string": "Remember this will also delete all products assigned to this category." }, "src_dot_categories_dot_views_dot_712767046": { "context": "dialog title", - "string": "Delete categories" + "string": "ВидаĐģĐ¸Ņ‚Đ¸ ĐēĐ°Ņ‚ĐĩĐŗĐžŅ€Ņ–Ņ—" }, "src_dot_categories_dot_views_dot_847492725": { - "string": "Are you sure you want to delete {categoryName}?" + "string": "Ви вĐŋĐĩвĐŊĐĩĐŊŅ–, Ņ‰Đž Ņ…ĐžŅ‡ĐĩŅ‚Đĩ видаĐģĐ¸Ņ‚Đ¸ {categoryName}?" }, "src_dot_categories_dot_views_dot_CategoryList_dot_1823337870": { "string": "{counter,plural,one {Are you sure you want to delete this category?} other {Are you sure you want to delete {displayQuantity} categories?}}" @@ -726,7 +726,7 @@ }, "src_dot_categories_dot_views_dot_CategoryList_dot_712767046": { "context": "dialog title", - "string": "Delete categories" + "string": "ВидаĐģĐ¸Ņ‚Đ¸ ĐēĐ°Ņ‚ĐĩĐŗĐžŅ€Ņ–Ņ—" }, "src_dot_clear": { "context": "button", @@ -738,11 +738,11 @@ }, "src_dot_collections_dot_components_dot_CollectionCreatePage_dot_1815688500": { "context": "collection", - "string": "since {date}" + "string": "Ņ€ĐžĐˇĐŧҖ҉ĐĩĐŊĐž С {date}" }, "src_dot_collections_dot_components_dot_CollectionCreatePage_dot_2001551496": { "context": "collection", - "string": "will be visible from {date}" + "string": "ĐąŅƒĐ´Đĩ видĐŊĐž С {date}" }, "src_dot_collections_dot_components_dot_CollectionCreatePage_dot_946315389": { "string": "Đ”ĐžĐ´Đ°Ņ‚Đ¸ ĐˇĐ°ĐŗĐžĐģОвОĐē Ņ‚Đ° ĐžĐŋĐ¸Ņ Đ´ĐģŅ ĐŋĐžŅˆŅƒĐēĐžĐ˛ĐžŅ— ŅĐ¸ŅŅ‚ĐĩĐŧи, Ņ‰ĐžĐą ĐŋĐžĐģĐĩĐŗŅˆĐ¸Ņ‚Đ¸ ĐŋĐžŅˆŅƒĐē ҆ҖҔҗ ĐēĐžĐģĐĩĐē҆Җҗ" @@ -753,15 +753,15 @@ }, "src_dot_collections_dot_components_dot_CollectionDetailsPage_dot_1815688500": { "context": "collection", - "string": "since {date}" + "string": "Ņ€ĐžĐˇĐŧҖ҉ĐĩĐŊĐž С {date}" }, "src_dot_collections_dot_components_dot_CollectionDetailsPage_dot_2001551496": { "context": "collection", - "string": "will be visible from {date}" + "string": "ĐąŅƒĐ´Đĩ видĐŊĐž С {date}" }, "src_dot_collections_dot_components_dot_CollectionDetailsPage_dot_2906897537": { "context": "switch button", - "string": "Feature on Homepage" + "string": "Đ¤ŅƒĐŊĐē҆Җҗ ĐŊа ĐŗĐžĐģОвĐŊŅ–Đš ŅŅ‚ĐžŅ€Ņ–ĐŊ҆Җ" }, "src_dot_collections_dot_components_dot_CollectionDetailsPage_dot_946315389": { "string": "Đ”ĐžĐ´Đ°Ņ‚Đ¸ ĐˇĐ°ĐŗĐžĐģОвОĐē Ņ‚Đ° ĐžĐŋĐ¸Ņ Đ´ĐģŅ ĐŋĐžŅˆŅƒĐēĐžĐ˛ĐžŅ— ŅĐ¸ŅŅ‚ĐĩĐŧи, Ņ‰ĐžĐą ĐŋĐžĐģĐĩĐŗŅˆĐ¸Ņ‚Đ¸ ĐŋĐžŅˆŅƒĐē ҆ҖҔҗ ĐēĐžĐģĐĩĐē҆Җҗ" @@ -772,7 +772,7 @@ }, "src_dot_collections_dot_components_dot_CollectionImage_dot_2224943474": { "context": "section header", - "string": "Background Image (optional)" + "string": "ФОĐŊОвĐĩ ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊĐŊŅ (ĐŊĐĩĐžĐąĐžĐ˛â€™ŅĐˇĐēОвО)" }, "src_dot_collections_dot_components_dot_CollectionImage_dot_3289097895": { "context": "field is optional", @@ -787,7 +787,7 @@ }, "src_dot_collections_dot_components_dot_CollectionListPage_dot_686910896": { "context": "button", - "string": "Create collection" + "string": "ĐĄŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ ĐēĐžĐģĐĩĐēŅ†Ņ–ŅŽ" }, "src_dot_collections_dot_components_dot_CollectionListPage_dot_hidden": { "context": "collection", @@ -808,22 +808,22 @@ "string": "No. of Products" }, "src_dot_collections_dot_components_dot_CollectionList_dot_2759199473": { - "string": "Collection Name" + "string": "Назва ĐēĐžĐģĐĩĐē҆Җҗ" }, "src_dot_collections_dot_components_dot_CollectionList_dot_3326160357": { "context": "collection availability", - "string": "Availability" + "string": "Đ”ĐžŅŅ‚ŅƒĐŋĐŊŅ–ŅŅ‚ŅŒ" }, "src_dot_collections_dot_components_dot_CollectionList_dot_3640454975": { "context": "collection is published", "string": "ОĐŋŅƒĐąĐģŅ–ĐēОваĐŊĐž" }, "src_dot_collections_dot_components_dot_CollectionProducts_dot_1657559629": { - "string": "No products found" + "string": "НĐĩ СĐŊаКдĐĩĐŊĐž ĐļОдĐŊĐžĐŗĐž Ņ‚ĐžĐ˛Đ°Ņ€Ņƒ" }, "src_dot_collections_dot_components_dot_CollectionProducts_dot_1952810469": { "context": "product type", - "string": "Type" + "string": "ĐĸиĐŋ" }, "src_dot_collections_dot_components_dot_CollectionProducts_dot_2341910657": { "context": "product is not published", @@ -839,7 +839,7 @@ }, "src_dot_collections_dot_components_dot_CollectionProducts_dot_460524544": { "context": "button", - "string": "Assign product" + "string": "ĐŸŅ€Đ¸ĐˇĐŊĐ°Ņ‡Đ¸Ņ‚Đ¸ Ņ‚ĐžĐ˛Đ°Ņ€" }, "src_dot_collections_dot_components_dot_CollectionProducts_dot_636461959": { "context": "product name", @@ -852,32 +852,32 @@ "string": "ĐĸĐžĐ˛Đ°Ņ€ дОдаĐŊиК Đ´Đž ĐēĐžĐģĐĩĐē҆Җҗ" }, "src_dot_collections_dot_views_dot_2402899582": { - "string": "Are you sure you want to delete collection's image?" + "string": "Ви вĐŋĐĩвĐŊĐĩĐŊŅ–, Ņ‰Đž Ņ…ĐžŅ‡ĐĩŅ‚Đĩ видаĐģĐ¸Ņ‚Đ¸ ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊĐŊŅ ĐēĐžĐģĐĩĐē҆Җҗ?" }, "src_dot_collections_dot_views_dot_3215481647": { "string": "{counter,plural,one {Are you sure you want to unassign this product?} other {Are you sure you want to unassign {displayQuantity} products?}}" }, "src_dot_collections_dot_views_dot_3482612628": { - "string": "Deleted product from collection" + "string": "ВидаĐģĐĩĐŊиК Ņ‚ĐžĐ˛Đ°Ņ€ Ņ–Đˇ ĐēĐžĐģĐĩĐē҆Җҗ" }, "src_dot_collections_dot_views_dot_3791354625": { "context": "dialog title", "string": "Unassign products from collection" }, "src_dot_collections_dot_views_dot_523939418": { - "string": "Are you sure you want to delete {collectionName}?" + "string": "Ви вĐŋĐĩвĐŊĐĩĐŊŅ–, Ņ‰Đž Ņ…ĐžŅ‡ĐĩŅ‚Đĩ видаĐģĐ¸Ņ‚Đ¸ {collectionName}?" }, "src_dot_collections_dot_views_dot_686910896": { "context": "window title", - "string": "Create collection" + "string": "ĐĄŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ ĐēĐžĐģĐĩĐēŅ†Ņ–ŅŽ" }, "src_dot_collections_dot_views_dot_699514132": { "context": "dialog title", - "string": "Delete Collection" + "string": "ВидаĐģĐ¸Ņ‚Đ¸ ĐēĐžĐģĐĩĐēŅ†Ņ–ŅŽ" }, "src_dot_collections_dot_views_dot_870815507": { "context": "unassign product from collection, button", - "string": "Unassign" + "string": "ĐĄĐēĐ°ŅŅƒĐ˛Đ°Ņ‚Đ¸" }, "src_dot_collections_dot_views_dot_942133001": { "context": "dialog title", @@ -899,7 +899,7 @@ }, "src_dot_collections_dot_views_dot_CollectionList_dot_2637364047": { "context": "dialog title", - "string": "Unpublish collections" + "string": "ĐĄĐēĐ°ŅŅƒĐ˛Đ°Ņ‚Đ¸ ĐŋŅƒĐąĐģŅ–ĐēĐ°Ņ†Ņ–ŅŽ ĐēĐžĐģĐĩĐēŅ†Ņ–Đš" }, "src_dot_collections_dot_views_dot_CollectionList_dot_2756013640": { "string": "{counter,plural,one {Are you sure you want to publish this collection?} other {Are you sure you want to publish {displayQuantity} collections?}}" @@ -910,7 +910,7 @@ }, "src_dot_collections_dot_views_dot_CollectionList_dot_3817188998": { "context": "dialog title", - "string": "Delete collections" + "string": "ВидаĐģĐ¸Ņ‚Đ¸ ĐēĐžĐģĐĩĐē҆Җҗ" }, "src_dot_components_dot_AccountPermissionGroups_dot_2836633439": { "string": "Permission groups" @@ -951,13 +951,13 @@ "string": "ĐŧŅ–ŅŅ‚Đž" }, "src_dot_components_dot_AddressEdit_dot_2965971965": { - "string": "ZIP / Postal code" + "string": "ĐŸĐžŅˆŅ‚ĐžĐ˛Đ¸Đš Ņ–ĐŊĐ´ĐĩĐēҁ" }, "src_dot_components_dot_AddressEdit_dot_3121963259": { "string": "ĐĐ´Ņ€ĐĩŅĐ° 2" }, "src_dot_components_dot_AddressEdit_dot_3570415321": { - "string": "Company" + "string": "КоĐŧĐŋаĐŊŅ–Ņ" }, "src_dot_components_dot_AddressEdit_dot_944851093": { "string": "Country area" @@ -975,32 +975,32 @@ }, "src_dot_components_dot_AssignCategoryDialog_dot_190977792": { "context": "dialog header", - "string": "Assign Categories" + "string": "ĐŸŅ€Đ¸ĐˇĐŊĐ°Ņ‡Đ¸Ņ‚Đ¸ ĐēĐ°Ņ‚ĐĩĐŗĐžŅ€Ņ–Ņ—" }, "src_dot_components_dot_AssignCategoryDialog_dot_3690273268": { "string": "Search by category name, etc..." }, "src_dot_components_dot_AssignCategoryDialog_dot_3973677075": { "context": "button", - "string": "Assign categories" + "string": "ĐŸŅ€Đ¸ĐˇĐŊĐ°Ņ‡Đ¸Ņ‚Đ¸ ĐēĐ°Ņ‚ĐĩĐŗĐžŅ€Ņ–Ņ—" }, "src_dot_components_dot_AssignCollectionDialog_dot_1035511604": { "context": "button", - "string": "Assign collections" + "string": "ĐŸŅ€Đ¸ĐˇĐŊĐ°Ņ‡Đ¸Ņ‚Đ¸ ĐēĐžĐģĐĩĐē҆Җҗ" }, "src_dot_components_dot_AssignCollectionDialog_dot_2605414502": { "string": "Search by collection name, etc..." }, "src_dot_components_dot_AssignCollectionDialog_dot_3992923611": { "context": "dialog header", - "string": "Assign Collection" + "string": "ĐŸŅ€Đ¸ĐˇĐŊĐ°Ņ‡Đ¸Ņ‚Đ¸ ĐēĐžĐģĐĩĐēŅ†ŅŽ" }, "src_dot_components_dot_AssignCollectionDialog_dot_4057224233": { "string": "Search Collection" }, "src_dot_components_dot_AssignProductDialog_dot_2100305525": { "context": "button", - "string": "Assign products" + "string": "ĐŸŅ€Đ¸ĐˇĐŊĐ°Ņ‡Đ¸Ņ‚Đ¸ Ņ‚ĐžĐ˛Đ°Ņ€Đ¸" }, "src_dot_components_dot_AssignProductDialog_dot_2336947364": { "string": "Search by product name, attribute, product type etc..." @@ -1010,7 +1010,7 @@ }, "src_dot_components_dot_AssignProductDialog_dot_649693468": { "context": "dialog header", - "string": "Assign Product" + "string": "ĐŸŅ€Đ¸ĐˇĐŊĐ°Ņ‡Đ¸Ņ‚Đ¸ Ņ‚ĐžĐ˛Đ°Ņ€" }, "src_dot_components_dot_AutocompleteSelectMenu_dot_2332404293": { "string": "No results" @@ -1025,7 +1025,7 @@ }, "src_dot_components_dot_ColumnPicker_dot_2715399461": { "context": "pick columns to display", - "string": "{numberOfSelected} columns selected out of {numberOfTotal}" + "string": "{numberOfSelected} ŅŅ‚ĐžĐ˛ĐŋŅ†Ņ–Đ˛ ĐžĐąŅ€Đ°ĐŊĐž С {numberOfTotal}" }, "src_dot_components_dot_CompanyAddressInput_dot_1139500589": { "string": "ĐšŅ€Đ°Ņ—ĐŊа" @@ -1040,13 +1040,13 @@ "string": "ĐŧŅ–ŅŅ‚Đž" }, "src_dot_components_dot_CompanyAddressInput_dot_2965971965": { - "string": "ZIP / Postal code" + "string": "ĐŸĐžŅˆŅ‚ĐžĐ˛Đ¸Đš Ņ–ĐŊĐ´ĐĩĐēҁ" }, "src_dot_components_dot_CompanyAddressInput_dot_3121963259": { "string": "ĐĐ´Ņ€ĐĩŅĐ° 2" }, "src_dot_components_dot_CompanyAddressInput_dot_3570415321": { - "string": "Company" + "string": "КоĐŧĐŋаĐŊŅ–Ņ" }, "src_dot_components_dot_CompanyAddressInput_dot_944851093": { "string": "Country area" @@ -1057,18 +1057,18 @@ }, "src_dot_components_dot_CountryList_dot_2460766407": { "context": "number of countries", - "string": "{number} Countries" + "string": "ĐšŅ€Đ°Ņ—ĐŊи {number}" }, "src_dot_components_dot_CountryList_dot_2747492886": { "context": "button", - "string": "Assign countries" + "string": "ĐŸŅ€Đ¸ĐˇĐŊĐ°Ņ‡Đ¸Ņ‚Đ¸ ĐēŅ€Đ°Ņ—ĐŊи" }, "src_dot_components_dot_DeleteFilterTabDialog_dot_2173195312": { "context": "custom search delete, dialog header", - "string": "Delete Search" + "string": "ВидаĐģĐ¸Ņ‚Đ¸ ĐŋĐžŅˆŅƒĐē" }, "src_dot_components_dot_DeleteFilterTabDialog_dot_71479100": { - "string": "Are you sure you want to delete {name} search tab?" + "string": "Ви вĐŋĐĩвĐŊĐĩĐŊŅ–, Ņ‰Đž Ņ…ĐžŅ‡ĐĩŅ‚Đĩ видаĐģĐ¸Ņ‚Đ¸ {name} вĐēĐģадĐē҃ ĐŋĐžŅˆŅƒĐē҃?" }, "src_dot_components_dot_ErrorMessageCard_dot_2845142593": { "context": "header", @@ -1076,7 +1076,7 @@ }, "src_dot_components_dot_ErrorPage_dot_1723676032": { "context": "button", - "string": "Back to home" + "string": "ПовĐĩŅ€ĐŊŅƒŅ‚Đ¸ŅŅ ĐŊа ĐŗĐžĐģОвĐŊ҃" }, "src_dot_components_dot_ErrorPage_dot_2736139139": { "string": "Ooops!..." @@ -1085,21 +1085,21 @@ "string": "ПоĐŧиĐģĐēа" }, "src_dot_components_dot_ErrorPage_dot_3090161573": { - "string": "Don't worry, everything is gonna be fine" + "string": "НĐĩ Ņ…Đ˛Đ¸ĐģŅŽĐšŅ‚ĐĩҁҌ, Đ˛ŅĐĩ ĐąŅƒĐ´Đĩ Đ´ĐžĐąŅ€Đĩ" }, "src_dot_components_dot_ErrorPage_dot_3182212440": { - "string": "We've encountered a problem..." + "string": "Ми ĐˇŅ–Ņ‚ĐēĐŊ҃ĐģĐ¸ŅŅ С ĐŋŅ€ĐžĐąĐģĐĩĐŧĐžŅŽ..." }, "src_dot_components_dot_FileUpload_dot_3050254265": { "context": "upload file, button", - "string": "Upload" + "string": "ЗаваĐŊŅ‚Đ°ĐļĐ¸Ņ‚Đ¸" }, "src_dot_components_dot_FilterBar_dot_2173195312": { "context": "button", - "string": "Delete Search" + "string": "ВидаĐģĐ¸Ņ‚Đ¸ ĐŋĐžŅˆŅƒĐē" }, "src_dot_components_dot_FilterBar_dot_2340527467": { - "string": "Custom Filter" + "string": "ĐĄĐŋĐĩŅ†Ņ–Đ°ĐģҌĐŊиК ҄ҖĐģŅŒŅ‚Ņ€" }, "src_dot_components_dot_FilterBar_dot_3268463180": { "context": "button", @@ -1114,11 +1114,11 @@ }, "src_dot_components_dot_Filter_dot_2683154806": { "context": "is filter range or value", - "string": "equal to" + "string": "Đ´ĐžŅ€Ņ–Đ˛ĐŊŅŽŅ”" }, "src_dot_components_dot_Filter_dot_2779594451": { "context": "filter range separator", - "string": "and" + "string": "Ņ‚Đ°" }, "src_dot_components_dot_Filter_dot_4190318230": { "context": "search results", @@ -1126,7 +1126,7 @@ }, "src_dot_components_dot_Filter_dot_773313536": { "context": "is filter range or value", - "string": "between" + "string": "ĐŧŅ–Đļ" }, "src_dot_components_dot_Filter_dot_996289613": { "string": "Đ¤Ņ–ĐģŅŒŅ‚Ņ€" @@ -1145,7 +1145,7 @@ }, "src_dot_components_dot_MoneyRange_dot_12301532": { "context": "money", - "string": "to {money}" + "string": "Đ´Đž {money}" }, "src_dot_components_dot_MoneyRange_dot_1316359951": { "context": "money", @@ -1153,7 +1153,7 @@ }, "src_dot_components_dot_MoneyRange_dot_3729849657": { "context": "money", - "string": "from {money}" + "string": "Đ˛Ņ–Đ´ {money}" }, "src_dot_components_dot_MultiAutocompleteSelectField_dot_1477537381": { "context": "add custom select input option", @@ -1171,7 +1171,7 @@ }, "src_dot_components_dot_Navigator_dot_1167695965": { "context": "navigator placeholder", - "string": "Type Command" + "string": "ВвĐĩĐ´Ņ–Ņ‚ŅŒ ĐēĐžĐŧаĐŊĐ´Ņƒ" }, "src_dot_components_dot_Navigator_dot_1643417013": { "context": "navigator placeholder", @@ -1183,7 +1183,7 @@ }, "src_dot_components_dot_Navigator_dot_2874620973": { "context": "navigator placeholder", - "string": "Type {key} to see available actions" + "string": "ВвĐĩĐ´Ņ–Ņ‚ŅŒ {key}, Ņ‰ĐžĐą ĐŋĐĩŅ€ĐĩĐŗĐģŅĐŊŅƒŅ‚Đ¸ Đ´ĐžŅŅ‚ŅƒĐŋĐŊŅ– Đ´Ņ–Ņ—" }, "src_dot_components_dot_Navigator_dot_2935523260": { "context": "navigator placeholder", @@ -1221,19 +1221,19 @@ }, "src_dot_components_dot_Navigator_dot_modes_dot_createCategory": { "context": "button", - "string": "Create Category" + "string": "ĐĄŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ ĐēĐ°Ņ‚ĐĩĐŗĐžŅ€Ņ–ŅŽ" }, "src_dot_components_dot_Navigator_dot_modes_dot_createCollection": { "context": "button", - "string": "Create Collection" + "string": "ĐĄŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ ĐēĐžĐģĐĩĐēŅ†Ņ–ŅŽ" }, "src_dot_components_dot_Navigator_dot_modes_dot_createCustomer": { "context": "button", - "string": "Create Customer" + "string": "ĐĄŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ ĐēĐģŅ–Ņ”ĐŊŅ‚Đ°" }, "src_dot_components_dot_Navigator_dot_modes_dot_createOrder": { "context": "button", - "string": "Create Order" + "string": "ĐĄŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ СаĐŧОвĐģĐĩĐŊĐŊŅ" }, "src_dot_components_dot_Navigator_dot_modes_dot_createPermissionGroup": { "context": "button", @@ -1241,11 +1241,11 @@ }, "src_dot_components_dot_Navigator_dot_modes_dot_createProduct": { "context": "button", - "string": "Create Product" + "string": "ĐĄŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ Ņ‚ĐžĐ˛Đ°Ņ€" }, "src_dot_components_dot_Navigator_dot_modes_dot_createVoucher": { "context": "button", - "string": "Create Voucher" + "string": "ĐĄŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ Đē҃ĐŋĐžĐŊ" }, "src_dot_components_dot_Navigator_dot_modes_dot_customerWithName": { "string": "{firstName} {lastName}" @@ -1272,7 +1272,7 @@ }, "src_dot_components_dot_Navigator_dot_modes_dot_helpMode": { "context": "navigator help mode description", - "string": "Display Help" + "string": "ПоĐēĐ°ĐˇĐ°Ņ‚Đ¸ Đ´ĐžĐ˛Ņ–Đ´Đē҃" }, "src_dot_components_dot_Navigator_dot_modes_dot_helpOrdersMode": { "context": "navigator order mode description", @@ -1317,7 +1317,7 @@ "string": "Invalid content" }, "src_dot_components_dot_RichTextEditor_dot_2925475978": { - "string": "URL Linked" + "string": "URL-Đ°Đ´Ņ€ĐĩŅĐ°" }, "src_dot_components_dot_RichTextEditor_dot_4035057905": { "string": "Image URL" @@ -1335,10 +1335,10 @@ }, "src_dot_components_dot_SearchBar_dot_2173195312": { "context": "button", - "string": "Delete Search" + "string": "ВидаĐģĐ¸Ņ‚Đ¸ ĐŋĐžŅˆŅƒĐē" }, "src_dot_components_dot_SearchBar_dot_2340527467": { - "string": "Custom Filter" + "string": "ĐĄĐŋĐĩŅ†Ņ–Đ°ĐģҌĐŊиК ҄ҖĐģŅŒŅ‚Ņ€" }, "src_dot_components_dot_SearchBar_dot_3268463180": { "context": "button", @@ -1351,7 +1351,7 @@ "string": "Search engine description" }, "src_dot_components_dot_SeoForm_dot_2378618579": { - "string": "If empty, the preview shows what will be autogenerated." + "string": "Đ¯ĐēŅ‰Đž ĐŋĐžŅ€ĐžĐļĐŊŅŒĐž, ĐŋĐžĐŋĐĩŅ€ĐĩĐ´ĐŊŅ–Đš ĐŋĐĩŅ€ĐĩĐŗĐģŅĐ´ ĐŋĐžĐēаĐļĐĩ, Ņ‰Đž ĐąŅƒĐ´Đĩ ŅŅ‚Đ˛ĐžŅ€ĐĩĐŊĐž Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐž" }, "src_dot_components_dot_SeoForm_dot_3198271020": { "context": "button", @@ -1362,7 +1362,7 @@ }, "src_dot_components_dot_SeoForm_dot_3877274856": { "context": "character limit", - "string": "{numberOfCharacters} of {maxCharacters} characters" + "string": "{numberOfCharacters} С {maxCharacters} ŅĐ¸ĐŧвОĐģŅ–Đ˛" }, "src_dot_components_dot_SingleAutocompleteSelectField_dot_1477537381": { "context": "add custom select input option", @@ -1389,7 +1389,7 @@ }, "src_dot_components_dot_VisibilityCard_dot_1459686496": { "context": "section header", - "string": "Visibility" + "string": "ВидиĐŧŅ–ŅŅ‚ŅŒ" }, "src_dot_components_dot_VisibilityCard_dot_2060790769": { "context": "publish on date", @@ -1399,14 +1399,14 @@ "string": "Set publication date" }, "src_dot_components_dot_VisibilityCard_dot_643174786": { - "string": "Visible" + "string": "ВидиĐŧиК" }, "src_dot_components_dot_VisibilityCard_dot_77815154": { "string": "Hidden" }, "src_dot_components_dot_WeightRange_dot_264731940": { "context": "weight", - "string": "to {value} {unit}" + "string": "Đ´Đž {value} {unit}" }, "src_dot_components_dot_WeightRange_dot_2892071052": { "context": "weight", @@ -1414,7 +1414,7 @@ }, "src_dot_components_dot_WeightRange_dot_4256193688": { "context": "weight", - "string": "from {value} {unit}" + "string": "Đ˛Ņ–Đ´ {value} {unit}" }, "src_dot_components_dot_Weight_dot_2781622322": { "context": "weight", @@ -1431,10 +1431,10 @@ "string": "Shipping Settings" }, "src_dot_configuration_dot_1639245766": { - "string": "View and update your webhook and their settings" + "string": "ПĐĩŅ€ĐĩĐŗĐģŅĐ´ Ņ‚Đ° ĐžĐŊОвĐģĐĩĐŊĐŊŅ вĐĩĐąŅ…ŅƒĐēŅ–Đ˛ Ņ‚Đ° Ņ—Ņ… ĐŊаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°ĐŊҌ" }, "src_dot_configuration_dot_2326418019": { - "string": "Attributes and Product Typess" + "string": "ĐŅ‚Ņ€Đ¸ĐąŅƒŅ‚Đ¸ Ņ‚Đ° Ņ‚Đ¸Đŋи ĐŋŅ€ĐžĐ´ŅƒĐēŅ‚Ņ–Đ˛" }, "src_dot_configuration_dot_2387898569": { "string": "Manage external integrations accounts" @@ -1447,7 +1447,7 @@ }, "src_dot_confirm": { "context": "button", - "string": "Confirm" + "string": "ĐŸŅ–Đ´Ņ‚Đ˛ĐĩŅ€Đ´Ņ–Ņ‚ŅŒ" }, "src_dot_create": { "context": "button", @@ -1467,7 +1467,7 @@ }, "src_dot_customers_dot_components_dot_CustomerAddressListPage_dot_1090326769": { "context": "customer's address book, header", - "string": "{fullName}'s Address Book" + "string": "{fullName} ĐĐ´Ņ€ĐĩҁĐŊа ĐēĐŊĐ¸ĐŗĐ°" }, "src_dot_customers_dot_components_dot_CustomerAddressListPage_dot_1428369222": { "string": "This customer doesn’t have any adresses added to his address book. You can add address using the button below." @@ -1481,13 +1481,13 @@ }, "src_dot_customers_dot_components_dot_CustomerAddressListPage_dot_489918044": { "context": "customer details, header", - "string": "{fullName} Details" + "string": "{fullName} ДĐĩŅ‚Đ°ĐģŅ–" }, "src_dot_customers_dot_components_dot_CustomerAddress_dot_1224809208": { - "string": "Default Address" + "string": "ĐĐ´Ņ€ĐĩŅĐ° Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ" }, "src_dot_customers_dot_components_dot_CustomerAddress_dot_1578192486": { - "string": "Default Billing Address" + "string": "ПĐģĐ°Ņ‚Ņ–ĐļĐŊа Đ°Đ´Ņ€ĐĩŅĐ° Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ" }, "src_dot_customers_dot_components_dot_CustomerAddress_dot_2131178753": { "context": "button", @@ -1498,7 +1498,7 @@ "string": "Set as default billing address" }, "src_dot_customers_dot_components_dot_CustomerAddress_dot_4109348993": { - "string": "Default Shipping Address" + "string": "ĐĐ´Ņ€ĐĩŅĐ° Đ´ĐžŅŅ‚Đ°Đ˛Đēи Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ" }, "src_dot_customers_dot_components_dot_CustomerAddresses_dot_1967111456": { "context": "header", @@ -1513,11 +1513,11 @@ "string": "ĐĐ´Ņ€ĐĩŅĐ°" }, "src_dot_customers_dot_components_dot_CustomerAddresses_dot_3870425261": { - "string": "This customer has no addresses yet" + "string": "ĐĻĐĩĐš ĐēĐģŅ–Ņ”ĐŊŅ‚ ҉Đĩ ĐŊĐĩ ĐŧĐ°Ņ” Đ°Đ´Ņ€ĐĩŅĐ¸" }, "src_dot_customers_dot_components_dot_CustomerAddresses_dot_4282475982": { "context": "subsection header", - "string": "Billing Address" + "string": "ĐĐ´Ņ€ĐĩŅĐ° Đ˛Đ¸ŅŅ‚Đ°Đ˛ĐģĐĩĐŊĐŊŅ Ņ€Đ°Ņ…ŅƒĐŊĐē҃" }, "src_dot_customers_dot_components_dot_CustomerCreateAddress_dot_1751533141": { "context": "page header", @@ -1528,7 +1528,7 @@ }, "src_dot_customers_dot_components_dot_CustomerCreateDetails_dot_3063084773": { "context": "header", - "string": "Customer Overview" + "string": "ĐžĐŗĐģŅĐ´ ĐēĐģŅ–Ņ”ĐŊŅ‚Đ°" }, "src_dot_customers_dot_components_dot_CustomerCreateNote_dot_1520756907": { "context": "notes about customer header", @@ -1543,15 +1543,15 @@ }, "src_dot_customers_dot_components_dot_CustomerCreatePage_dot_4025686004": { "context": "page header", - "string": "Create Customer" + "string": "ĐĄŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ ĐēĐģŅ–Ņ”ĐŊŅ‚Đ°" }, "src_dot_customers_dot_components_dot_CustomerDetails_dot_2968565128": { "context": "check to mark this account as active", - "string": "User account active" + "string": "ОбĐģŅ–ĐēОвиК СаĐŋĐ¸Ņ ĐēĐžŅ€Đ¸ŅŅ‚ŅƒĐ˛Đ°Ņ‡Đ° аĐēŅ‚Đ¸Đ˛ĐŊиК" }, "src_dot_customers_dot_components_dot_CustomerDetails_dot_3298169382": { "context": "section subheader", - "string": "Active member since {date}" + "string": "АĐēŅ‚Đ¸Đ˛ĐŊиК ŅƒŅ‡Đ°ŅĐŊиĐē С {date}" }, "src_dot_customers_dot_components_dot_CustomerDetails_dot_577013340": { "context": "note about customer", @@ -1563,14 +1563,14 @@ }, "src_dot_customers_dot_components_dot_CustomerInfo_dot_778526801": { "context": "customer contact section, header", - "string": "Contact Informations" + "string": "КоĐŊŅ‚Đ°ĐēŅ‚ĐŊа Ņ–ĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ" }, "src_dot_customers_dot_components_dot_CustomerListPage_dot_1643417013": { "string": "Search Customer" }, "src_dot_customers_dot_components_dot_CustomerListPage_dot_2859116187": { "context": "button", - "string": "Create customer" + "string": "ĐĄŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ ĐēĐģŅ–Ņ”ĐŊŅ‚Đ°" }, "src_dot_customers_dot_components_dot_CustomerListPage_dot_477293306": { "context": "tab name", @@ -1594,10 +1594,10 @@ "string": "No customers found" }, "src_dot_customers_dot_components_dot_CustomerList_dot_2339105195": { - "string": "Customer Email" + "string": "ЕĐģĐĩĐēŅ‚Ņ€ĐžĐŊĐŊа ĐŋĐžŅˆŅ‚Đ° ĐēĐģŅ–Ņ”ĐŊŅ‚Đ°" }, "src_dot_customers_dot_components_dot_CustomerList_dot_4154265139": { - "string": "Customer Name" + "string": "ІĐŧ'Ņ ĐēĐģŅ–Ņ”ĐŊŅ‚Đ°" }, "src_dot_customers_dot_components_dot_CustomerOrders_dot_1756106276": { "context": "order status", @@ -1613,7 +1613,7 @@ }, "src_dot_customers_dot_components_dot_CustomerOrders_dot_3029139173": { "context": "button", - "string": "View all orders" + "string": "ПĐĩŅ€ĐĩĐŗĐģŅĐŊŅƒŅ‚Đ¸ Đ˛ŅŅ– СаĐŧОвĐģĐĩĐŊĐŊŅ" }, "src_dot_customers_dot_components_dot_CustomerOrders_dot_4205493358": { "context": "order placement date", @@ -1634,15 +1634,15 @@ }, "src_dot_customers_dot_components_dot_CustomerStats_dot_2543847016": { "context": "section header", - "string": "Customer History" + "string": "Đ†ŅŅ‚ĐžŅ€Ņ–Ņ ĐēĐģŅ–Ņ”ĐŊŅ‚Đ°" }, "src_dot_customers_dot_views_dot_1927691511": { "context": "delete customer, dialog content", - "string": "Are you sure you want to delete {email}?" + "string": "Ви вĐŋĐĩвĐŊĐĩĐŊŅ–, Ņ‰Đž Ņ…ĐžŅ‡ĐĩŅ‚Đĩ видаĐģĐ¸Ņ‚Đ¸ {email}?" }, "src_dot_customers_dot_views_dot_1998583641": { "context": "dialog header", - "string": "Delete Customer" + "string": "ВидаĐģĐ¸Ņ‚Đ¸ ĐēĐģŅ–Ņ”ĐŊŅ‚Đ°" }, "src_dot_customers_dot_views_dot_2657976015": { "context": "dialog header", @@ -1650,23 +1650,23 @@ }, "src_dot_customers_dot_views_dot_2859116187": { "context": "window title", - "string": "Create customer" + "string": "ĐĄŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ ĐēĐģŅ–Ņ”ĐŊŅ‚Đ°" }, "src_dot_customers_dot_views_dot_3689332763": { - "string": "Are you sure you want to delete this address from users address book?" + "string": "Ви вĐŋĐĩвĐŊĐĩĐŊŅ–, Ņ‰Đž Ņ…ĐžŅ‡ĐĩŅ‚Đĩ видаĐģĐ¸Ņ‚Đ¸ Ņ†ŅŽ Đ°Đ´Ņ€Đĩҁ҃ С Đ°Đ´Ņ€ĐĩҁĐŊĐžŅ— ĐēĐŊĐ¸ĐŗĐ¸ ĐēĐžŅ€Đ¸ŅŅ‚ŅƒĐ˛Đ°Ņ‡Ņ–Đ˛?" }, "src_dot_customers_dot_views_dot_3901579344": { - "string": "Customer Removed" + "string": "КĐģŅ–Ņ”ĐŊŅ‚Đ° видаĐģĐĩĐŊĐž" }, "src_dot_customers_dot_views_dot_3970234993": { - "string": "Customer created" + "string": "КĐģŅ–Ņ”ĐŊŅ‚ ŅŅ‚Đ˛ĐžŅ€ĐĩĐŊиК" }, "src_dot_customers_dot_views_dot_CustomerList_dot_1932444813": { "string": "{counter,plural,one {Are you sure you want to delete this customer?} other {Are you sure you want to delete {displayQuantity} customers?}}" }, "src_dot_customers_dot_views_dot_CustomerList_dot_2136923553": { "context": "dialog header", - "string": "Delete Customers" + "string": "ВидаĐģĐ¸Ņ‚Đ¸ ĐēĐģŅ–Ņ”ĐŊŅ‚Ņ–Đ˛" }, "src_dot_dashboard": { "string": "ĐĻĐĩĐŊ҂Ҁ ĐēĐĩŅ€ŅƒĐ˛Đ°ĐŊĐŊŅ " @@ -1675,6 +1675,10 @@ "context": "button", "string": "ВидаĐģĐ¸Ņ‚Đ¸" }, + "src_dot_demo": { + "context": "notification message after log in", + "string": "Just to let you know... You're in demo mode. You can play around with the dashboard but can't save changes." + }, "src_dot_description": { "string": "ОĐŋĐ¸Ņ" }, @@ -1682,7 +1686,7 @@ "string": "ЗĐŊиĐļĐēи " }, "src_dot_discounts_dot_components_dot_DiscountCategories_dot_1567318211": { - "string": "Category name" + "string": "Назва ĐēĐ°Ņ‚ĐĩĐŗĐžŅ€Ņ–Ņ—" }, "src_dot_discounts_dot_components_dot_DiscountCategories_dot_1681512341": { "context": "section header", @@ -1697,11 +1701,11 @@ }, "src_dot_discounts_dot_components_dot_DiscountCategories_dot_3973677075": { "context": "button", - "string": "Assign categories" + "string": "ĐŸŅ€Đ¸ĐˇĐŊĐ°Ņ‡Đ¸Ņ‚Đ¸ ĐēĐ°Ņ‚ĐĩĐŗĐžŅ€Ņ–Ņ—" }, "src_dot_discounts_dot_components_dot_DiscountCollections_dot_1035511604": { "context": "button", - "string": "Assign collections" + "string": "ĐŸŅ€Đ¸ĐˇĐŊĐ°Ņ‡Đ¸Ņ‚Đ¸ ĐēĐžĐģĐĩĐē҆Җҗ" }, "src_dot_discounts_dot_components_dot_DiscountCollections_dot_2137803833": { "string": "No collections found" @@ -1711,7 +1715,7 @@ "string": "ĐŸŅ€ĐžĐ´ŅƒĐēŅ‚Đ¸" }, "src_dot_discounts_dot_components_dot_DiscountCollections_dot_3011396316": { - "string": "Collection name" + "string": "Назва ĐēĐžĐģĐĩĐē҆Җҗ" }, "src_dot_discounts_dot_components_dot_DiscountCollections_dot_452750900": { "context": "section header", @@ -1719,7 +1723,7 @@ }, "src_dot_discounts_dot_components_dot_DiscountCountrySelectDialog_dot_1585396479": { "context": "dialog header", - "string": "Assign Countries" + "string": "ĐŸŅ€Đ¸ĐˇĐŊĐ°Ņ‡Đ¸Ņ‚Đ¸ ĐēŅ€Đ°Ņ—ĐŊи" }, "src_dot_discounts_dot_components_dot_DiscountCountrySelectDialog_dot_2110418881": { "context": "search box placeholder", @@ -1734,11 +1738,11 @@ }, "src_dot_discounts_dot_components_dot_DiscountCountrySelectDialog_dot_2747492886": { "context": "button", - "string": "Assign countries" + "string": "ĐŸŅ€Đ¸ĐˇĐŊĐ°Ņ‡Đ¸Ņ‚Đ¸ ĐēŅ€Đ°Ņ—ĐŊи" }, "src_dot_discounts_dot_components_dot_DiscountCountrySelectDialog_dot_2777439857": { "context": "country selection", - "string": "Countries A to Z" + "string": "ĐšŅ€Đ°Ņ—ĐŊи Đ˛Ņ–Đ´ А Đ´Đž Đ¯" }, "src_dot_discounts_dot_components_dot_DiscountDates_dot_1596226028": { "context": "voucher end date, switch button", @@ -1749,11 +1753,11 @@ "string": "АĐēŅ‚Đ¸Đ˛ĐŊŅ– Đ´Đ°Ņ‚Đ¸" }, "src_dot_discounts_dot_components_dot_DiscountProducts_dot_1657559629": { - "string": "No products found" + "string": "НĐĩ СĐŊаКдĐĩĐŊĐž ĐļОдĐŊĐžĐŗĐž Ņ‚ĐžĐ˛Đ°Ņ€Ņƒ" }, "src_dot_discounts_dot_components_dot_DiscountProducts_dot_2100305525": { "context": "button", - "string": "Assign products" + "string": "ĐŸŅ€Đ¸ĐˇĐŊĐ°Ņ‡Đ¸Ņ‚Đ¸ Ņ‚ĐžĐ˛Đ°Ņ€Đ¸" }, "src_dot_discounts_dot_components_dot_DiscountProducts_dot_2341910657": { "context": "product is not published", @@ -1775,7 +1779,7 @@ }, "src_dot_discounts_dot_components_dot_SaleCreatePage_dot_3866518732": { "context": "page header", - "string": "Create Sale" + "string": "ĐĄŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ Ņ€ĐžĐˇĐŋŅ€ĐžĐ´Đ°Đļ" }, "src_dot_discounts_dot_components_dot_SaleInfo_dot_636461959": { "context": "sale name", @@ -1786,7 +1790,7 @@ }, "src_dot_discounts_dot_components_dot_SaleListPage_dot_3866518732": { "context": "button", - "string": "Create Sale" + "string": "ĐĄŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ Ņ€ĐžĐˇĐŋŅ€ĐžĐ´Đ°Đļ" }, "src_dot_discounts_dot_components_dot_SaleListPage_dot_3907768880": { "context": "tab name", @@ -1821,7 +1825,7 @@ "string": "ĐĄŅ‚Đ°Ņ‚ŅƒŅ" }, "src_dot_discounts_dot_components_dot_SaleListPage_dot_type": { - "string": "Discount Type" + "string": "ĐĸиĐŋ СĐŊиĐļĐēи" }, "src_dot_discounts_dot_components_dot_SaleList_dot_1148029984": { "context": "sale value", @@ -1852,7 +1856,7 @@ }, "src_dot_discounts_dot_components_dot_SaleType_dot_3216816841": { "context": "percentage or fixed, header", - "string": "Discount Type" + "string": "ĐĸиĐŋ СĐŊиĐļĐēи" }, "src_dot_discounts_dot_components_dot_SaleType_dot_3688224049": { "context": "discount type", @@ -1868,11 +1872,11 @@ }, "src_dot_discounts_dot_components_dot_SaleValue_dot_1205967018": { "context": "sale discount", - "string": "Discount Value" + "string": "ЗĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ СĐŊиĐļĐēи" }, "src_dot_discounts_dot_components_dot_VoucherCreatePage_dot_1357216572": { "context": "page header", - "string": "Create Voucher" + "string": "ĐĄŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ Đē҃ĐŋĐžĐŊ" }, "src_dot_discounts_dot_components_dot_VoucherDates_dot_1596226028": { "context": "voucher end date, switch button", @@ -1883,10 +1887,10 @@ "string": "АĐēŅ‚Đ¸Đ˛ĐŊŅ– Đ´Đ°Ņ‚Đ¸" }, "src_dot_discounts_dot_components_dot_VoucherDetailsPage_dot_2071139683": { - "string": "Voucher applies to all countries" + "string": "ĐšŅƒĐŋĐžĐŊи ĐŋĐžŅˆĐ¸Ņ€ŅŽŅŽŅ‚ŅŒŅŅ ĐŊа Đ˛ŅŅ– ĐēŅ€Đ°Ņ—ĐŊи" }, "src_dot_discounts_dot_components_dot_VoucherDetailsPage_dot_2102960822": { - "string": "Voucher is limited to these countries" + "string": "ĐšŅƒĐŋĐžĐŊи ОйĐŧĐĩĐļŅƒŅŽŅ‚ŅŒŅŅ Ņ†Đ¸Đŧи ĐēŅ€Đ°Ņ—ĐŊаĐŧи" }, "src_dot_discounts_dot_components_dot_VoucherDetailsPage_dot_3109712047": { "context": "voucher country range", @@ -1894,18 +1898,18 @@ }, "src_dot_discounts_dot_components_dot_VoucherDetailsPage_dot_346170541": { "context": "number of categories", - "string": "Categories ({quantity})" + "string": "ĐšĐ°Ņ‚ĐĩĐŗĐžŅ€Ņ–Ņ— ({quantity})" }, "src_dot_discounts_dot_components_dot_VoucherDetailsPage_dot_3673147015": { "context": "number of collections", - "string": "Collections ({quantity})" + "string": "КоĐģĐĩĐē҆Җҗ ({quantity})" }, "src_dot_discounts_dot_components_dot_VoucherDetailsPage_dot_846927739": { "context": "number of products", "string": "Products ({quantity})" }, "src_dot_discounts_dot_components_dot_VoucherInfo_dot_1262795626": { - "string": "Discount Code" + "string": "Код СĐŊиĐļĐēи" }, "src_dot_discounts_dot_components_dot_VoucherInfo_dot_1944363009": { "context": "voucher code, button", @@ -1920,7 +1924,7 @@ }, "src_dot_discounts_dot_components_dot_VoucherLimits_dot_3751756157": { "context": "voucher usage limit, header", - "string": "Usage Limit" + "string": "ОбĐŧĐĩĐļĐĩĐŊĐŊŅ виĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ" }, "src_dot_discounts_dot_components_dot_VoucherLimits_dot_557552777": { "context": "voucher", @@ -1935,7 +1939,7 @@ }, "src_dot_discounts_dot_components_dot_VoucherListPage_dot_614836274": { "context": "button", - "string": "Create voucher" + "string": "ĐĄŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ Đē҃ĐŋĐžĐŊ" }, "src_dot_discounts_dot_components_dot_VoucherListPage_dot_active": { "context": "voucher status", @@ -1967,10 +1971,10 @@ }, "src_dot_discounts_dot_components_dot_VoucherListPage_dot_timesUsed": { "context": "voucher", - "string": "Times used" + "string": "ВиĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°ĐŊŅ– Ņ‡Đ°ŅĐ¸" }, "src_dot_discounts_dot_components_dot_VoucherListPage_dot_type": { - "string": "Discount Type" + "string": "ĐĸиĐŋ СĐŊиĐļĐēи" }, "src_dot_discounts_dot_components_dot_VoucherList_dot_1148029984": { "context": "voucher value", @@ -1986,7 +1990,7 @@ }, "src_dot_discounts_dot_components_dot_VoucherList_dot_3917820600": { "context": "voucher uses", - "string": "Uses" + "string": "ВиĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚ŅŒŅŅ" }, "src_dot_discounts_dot_components_dot_VoucherList_dot_47059407": { "context": "voucher is active from date", @@ -2025,11 +2029,11 @@ }, "src_dot_discounts_dot_components_dot_VoucherSummary_dot_2735425668": { "context": "voucher", - "string": "Applies to" + "string": "Đ’Ņ–Đ´ĐŊĐžŅĐ¸Ņ‚ŅŒŅŅ Đ´Đž" }, "src_dot_discounts_dot_components_dot_VoucherSummary_dot_3751756157": { "context": "voucher value requirement", - "string": "Usage Limit" + "string": "ОбĐŧĐĩĐļĐĩĐŊĐŊŅ виĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ" }, "src_dot_discounts_dot_components_dot_VoucherSummary_dot_78726751": { "context": "voucher code", @@ -2037,7 +2041,7 @@ }, "src_dot_discounts_dot_components_dot_VoucherTypes_dot_3216816841": { "context": "header", - "string": "Discount Type" + "string": "ĐĸиĐŋ СĐŊиĐļĐēи" }, "src_dot_discounts_dot_components_dot_VoucherTypes_dot_3289659291": { "context": "voucher discount type", @@ -2056,14 +2060,14 @@ "string": "ЗĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ" }, "src_dot_discounts_dot_components_dot_VoucherValue_dot_1205967018": { - "string": "Discount Value" + "string": "ЗĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ СĐŊиĐļĐēи" }, "src_dot_discounts_dot_components_dot_VoucherValue_dot_1492866942": { "context": "voucher application, switch button", "string": "Only once per order" }, "src_dot_discounts_dot_components_dot_VoucherValue_dot_1960678372": { - "string": "Voucher Specific Information" + "string": "КоĐŊĐēŅ€ĐĩŅ‚ĐŊа Ņ–ĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ ĐŋĐž Đē҃ĐŋĐžĐŊ҃" }, "src_dot_discounts_dot_components_dot_VoucherValue_dot_4189095909": { "string": "If this option is disabled, discount will be counted for every eligible product" @@ -2081,7 +2085,7 @@ "string": "Đ’Ņ–Đ´ĐŋŅ€Đ°Đ˛ĐģĐĩĐŊĐŊŅ " }, "src_dot_discounts_dot_views_dot_1162257691": { - "string": "Deleted voucher" + "string": "ВидаĐģĐĩĐŊиК Đē҃ĐŋĐžĐŊ" }, "src_dot_discounts_dot_views_dot_1402402714": { "context": "dialog header", @@ -2089,7 +2093,7 @@ }, "src_dot_discounts_dot_views_dot_1457489953": { "context": "dialog content", - "string": "Are you sure you want to delete {saleName}?" + "string": "Ви вĐŋĐĩвĐŊĐĩĐŊŅ–, Ņ‰Đž Ņ…ĐžŅ‡ĐĩŅ‚Đĩ видаĐģĐ¸Ņ‚Đ¸ {saleName}?" }, "src_dot_discounts_dot_views_dot_1827854264": { "context": "dialog header", @@ -2120,7 +2124,7 @@ }, "src_dot_discounts_dot_views_dot_3261917848": { "context": "dialog content", - "string": "Are you sure you want to delete {voucherCode}?" + "string": "Ви вĐŋĐĩвĐŊĐĩĐŊŅ–, Ņ‰Đž Ņ…ĐžŅ‡ĐĩŅ‚Đĩ видаĐģĐ¸Ņ‚Đ¸ {voucherCode}?" }, "src_dot_discounts_dot_views_dot_3395246518": { "context": "dialog header", @@ -2131,7 +2135,7 @@ }, "src_dot_discounts_dot_views_dot_506030254": { "context": "dialog header", - "string": "Delete Sale" + "string": "ВидаĐģĐ¸Ņ‚Đ¸ Ņ€ĐžĐˇĐŋŅ€ĐžĐ´Đ°Đļ" }, "src_dot_discounts_dot_views_dot_655651329": { "string": "Successfully created voucher" @@ -2142,11 +2146,11 @@ }, "src_dot_discounts_dot_views_dot_895379508": { "context": "dialog header", - "string": "Delete Voucher" + "string": "ВидаĐģĐ¸Ņ‚Đ¸ Đē҃ĐŋĐžĐŊ" }, "src_dot_discounts_dot_views_dot_SaleList_dot_2809303671": { "context": "dialog header", - "string": "Delete Sales" + "string": "ВидаĐģĐ¸Ņ‚Đ¸ Ņ€ĐžĐˇĐŋŅ€ĐžĐ´Đ°ĐļŅ–" }, "src_dot_discounts_dot_views_dot_SaleList_dot_372098008": { "context": "dialog content", @@ -2158,7 +2162,7 @@ }, "src_dot_discounts_dot_views_dot_VoucherList_dot_367317371": { "context": "dialog header", - "string": "Delete Vouchers" + "string": "ВидаĐģĐ¸Ņ‚Đ¸ Đē҃ĐŋĐžĐŊи" }, "src_dot_done": { "context": "button", @@ -2170,17 +2174,17 @@ }, "src_dot_draftOrders": { "context": "draft orders section name", - "string": "Draft Orders" + "string": "ЧĐĩŅ€ĐŊĐĩŅ‚Đēа СаĐŧОвĐģĐĩĐŊҌ" }, "src_dot_drafts": { - "string": "Drafts" + "string": "ЧĐĩŅ€ĐŊĐĩŅ‚Đēи" }, "src_dot_edit": { "context": "button", "string": "Đ ĐĩĐ´Đ°ĐŗŅƒĐ˛Đ°Ņ‚Đ¸" }, "src_dot_email": { - "string": "E-mail Address" + "string": "ЕĐģĐĩĐēŅ‚Ņ€ĐžĐŊĐŊа Đ°Đ´Ņ€ĐĩŅĐ°" }, "src_dot_endDate": { "string": "End Date" @@ -2200,7 +2204,7 @@ }, "src_dot_home": { "context": "home section name", - "string": "Đ”Ņ–Đŧ " + "string": "ГоĐģОвĐŊа" }, "src_dot_home_dot_components_dot_HomeActivityCard_dot_draft": { "string": "Order #{orderId} was placed from draft by {userEmail}" @@ -2247,7 +2251,7 @@ }, "src_dot_orders_dot_components_dot_OrderBulkCancelDialog_dot_1528036340": { "context": "dialog header", - "string": "Cancel Orders" + "string": "ĐĄĐēĐ°ŅŅƒĐ˛Đ°Ņ‚Đ¸ СаĐŧОвĐģĐĩĐŊĐŊŅ" }, "src_dot_orders_dot_components_dot_OrderBulkCancelDialog_dot_4224885638": { "string": "{counter,plural,one {Are you sure you want to cancel this order?} other {Are you sure you want to cancel {displayQuantity} orders?}}" @@ -2271,14 +2275,14 @@ }, "src_dot_orders_dot_components_dot_OrderCustomer_dot_2312694610": { "context": "subheader", - "string": "Contact Information" + "string": "КоĐŊŅ‚Đ°ĐēŅ‚ĐŊа Ņ–ĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ" }, "src_dot_orders_dot_components_dot_OrderCustomer_dot_2433460203": { "string": "Search Customers" }, "src_dot_orders_dot_components_dot_OrderCustomer_dot_2672803871": { "context": "link", - "string": "View Profile" + "string": "ПĐĩŅ€ĐĩĐŗĐģŅĐŊŅƒŅ‚Đ¸ ĐŋŅ€ĐžŅ„Ņ–ĐģҌ" }, "src_dot_orders_dot_components_dot_OrderCustomer_dot_2758581442": { "string": "Shipping Address" @@ -2292,10 +2296,10 @@ "string": "Same as shipping address" }, "src_dot_orders_dot_components_dot_OrderCustomer_dot_4172383244": { - "string": "Anonymous user" + "string": "АĐŊĐžĐŊŅ–ĐŧĐŊиК ĐēĐžŅ€Đ¸ŅŅ‚ŅƒĐ˛Đ°Ņ‡" }, "src_dot_orders_dot_components_dot_OrderCustomer_dot_4282475982": { - "string": "Billing Address" + "string": "ĐĐ´Ņ€ĐĩŅĐ° Đ˛Đ¸ŅŅ‚Đ°Đ˛ĐģĐĩĐŊĐŊŅ Ņ€Đ°Ņ…ŅƒĐŊĐē҃" }, "src_dot_orders_dot_components_dot_OrderDetailsPage_dot_1854613983": { "context": "button", @@ -2303,10 +2307,10 @@ }, "src_dot_orders_dot_components_dot_OrderDraftCancelDialog_dot_1961675716": { "context": "dialog header", - "string": "Delete Daft Order" + "string": "ВидаĐģĐ¸Ņ‚Đ¸ ҇ĐĩŅ€ĐŊĐĩŅ‚Đē҃ СаĐŧОвĐģĐĩĐŊĐŊŅ" }, "src_dot_orders_dot_components_dot_OrderDraftCancelDialog_dot_66064347": { - "string": "Are you sure you want to delete draft #{orderNumber}?" + "string": "Ви вĐŋĐĩвĐŊĐĩĐŊŅ–, Ņ‰Đž Ņ…ĐžŅ‡ĐĩŅ‚Đĩ видаĐģĐ¸Ņ‚Đ¸ ҇ĐĩŅ€ĐŊĐĩŅ‚Đē҃ #{orderNumber}?" }, "src_dot_orders_dot_components_dot_OrderDraftDetailsProducts_dot_1134347598": { "context": "price or ordered products", @@ -2353,7 +2357,7 @@ "string": "Đ”ĐžĐ´Đ°Ņ‚Đ¸ Ņ‚ĐžĐ˛Đ°Ņ€Đ¸" }, "src_dot_orders_dot_components_dot_OrderDraftFinalizeDialog_dot_115822814": { - "string": "No billing address" + "string": "ПĐģĐ°Ņ‚Ņ–ĐļĐŊа Đ°Đ´Ņ€ĐĩŅĐ° Đ˛Ņ–Đ´ŅŅƒŅ‚ĐŊŅ" }, "src_dot_orders_dot_components_dot_OrderDraftFinalizeDialog_dot_1161061962": { "context": "dialog header", @@ -2379,7 +2383,7 @@ "string": "Some products require shipping, but no method provided" }, "src_dot_orders_dot_components_dot_OrderDraftFinalizeDialog_dot_3358029330": { - "string": "Are you sure you want to finalize draft #{orderNumber}?" + "string": "Ви вĐŋĐĩвĐŊĐĩĐŊŅ–, Ņ‰Đž Ņ…ĐžŅ‡ĐĩŅ‚Đĩ СавĐĩŅ€ŅˆĐ¸Ņ‚Đ¸ ҇ĐĩŅ€ĐŊĐĩŅ‚Đē҃ #{orderNumber}?" }, "src_dot_orders_dot_components_dot_OrderDraftFinalizeDialog_dot_678764806": { "context": "button", @@ -2387,7 +2391,7 @@ }, "src_dot_orders_dot_components_dot_OrderDraftListPage_dot_2826235371": { "context": "button", - "string": "Create order" + "string": "ĐĄŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ СаĐŧОвĐģĐĩĐŊĐŊŅ" }, "src_dot_orders_dot_components_dot_OrderDraftListPage_dot_551325728": { "context": "tab name", @@ -2398,7 +2402,7 @@ }, "src_dot_orders_dot_components_dot_OrderDraftListPage_dot_created": { "context": "draft order", - "string": "Created" + "string": "ĐĄŅ‚Đ˛ĐžŅ€ĐĩĐŊĐž" }, "src_dot_orders_dot_components_dot_OrderDraftListPage_dot_customer": { "context": "draft order", @@ -2477,7 +2481,7 @@ }, "src_dot_orders_dot_components_dot_OrderFulfillmentCancelDialog_dot_732594284": { "context": "dialog header", - "string": "Cancel Fulfillment" + "string": "ĐĄĐēĐ°ŅŅƒĐ˛Đ°Ņ‚Đ¸ виĐēĐžĐŊаĐŊĐŊŅ" }, "src_dot_orders_dot_components_dot_OrderFulfillmentDialog_dot_2796503714": { "context": "quantity of fulfilled products", @@ -2522,7 +2526,7 @@ "string": "ĐšŅ–ĐģҌĐēŅ–ŅŅ‚ŅŒ" }, "src_dot_orders_dot_components_dot_OrderFulfillment_dot_3254150098": { - "string": "Tracking Number: {trackingNumber}" + "string": "НоĐŧĐĩŅ€ Đ˛Ņ–Đ´ŅĐģŅ–Đ´ĐēĐžĐ˛ŅƒĐ˛Đ°ĐŊĐŊŅ: {trackingNumber}" }, "src_dot_orders_dot_components_dot_OrderFulfillment_dot_3494686506": { "context": "section header", @@ -2532,9 +2536,13 @@ "context": "cancelled fulfillment, section header", "string": "Cancelled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderFulfillment_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderFulfillment_dot_732594284": { "context": "button", - "string": "Cancel Fulfillment" + "string": "ĐĄĐēĐ°ŅŅƒĐ˛Đ°Ņ‚Đ¸ виĐēĐžĐŊаĐŊĐŊŅ" }, "src_dot_orders_dot_components_dot_OrderFulfillment_dot_77179533": { "context": "fulfillment group", @@ -2590,7 +2598,7 @@ }, "src_dot_orders_dot_components_dot_OrderHistory_dot_2655541129": { "context": "order history message", - "string": "Order was fully paid" + "string": "ЗаĐŧОвĐģĐĩĐŊĐŊŅ ĐąŅƒĐģĐž ĐŋОвĐŊŅ–ŅŅ‚ŅŽ ĐžĐŋĐģĐ°Ņ‡ĐĩĐŊĐž" }, "src_dot_orders_dot_components_dot_OrderHistory_dot_2770854455": { "context": "order history message", @@ -2602,7 +2610,7 @@ }, "src_dot_orders_dot_components_dot_OrderHistory_dot_3095247195": { "context": "order history message", - "string": "Draft order was created" + "string": "ЧĐĩŅ€ĐŊĐĩŅ‚Đē҃ СаĐŧОвĐģĐĩĐŊĐŊŅ ŅŅ‚Đ˛ĐžŅ€ĐĩĐŊĐž" }, "src_dot_orders_dot_components_dot_OrderHistory_dot_3328124376": { "context": "order history message", @@ -2649,7 +2657,7 @@ }, "src_dot_orders_dot_components_dot_OrderListPage_dot_2826235371": { "context": "button", - "string": "Create order" + "string": "ĐĄŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ СаĐŧОвĐģĐĩĐŊĐŊŅ" }, "src_dot_orders_dot_components_dot_OrderListPage_dot_355376157": { "string": "Search Orders..." @@ -2664,7 +2672,7 @@ }, "src_dot_orders_dot_components_dot_OrderListPage_dot_placed": { "context": "order", - "string": "Created" + "string": "ĐĄŅ‚Đ˛ĐžŅ€ĐĩĐŊĐž" }, "src_dot_orders_dot_components_dot_OrderList_dot_1198046928": { "string": "Fulfillment status" @@ -2692,7 +2700,7 @@ "string": "No orders found" }, "src_dot_orders_dot_components_dot_OrderMarkAsPaidDialog_dot_2823153104": { - "string": "Are you sure you want to mark this order as paid?" + "string": "Ви вĐŋĐĩвĐŊĐĩĐŊŅ–, Ņ‰Đž Ņ…ĐžŅ‡ĐĩŅ‚Đĩ ĐŋОСĐŊĐ°Ņ‡Đ¸Ņ‚Đ¸ ҆Đĩ СаĐŧОвĐģĐĩĐŊĐŊŅ ŅĐē ĐžĐŋĐģĐ°Ņ‡ĐĩĐŊĐĩ?" }, "src_dot_orders_dot_components_dot_OrderMarkAsPaidDialog_dot_4196844912": { "context": "dialog header", @@ -2700,7 +2708,7 @@ }, "src_dot_orders_dot_components_dot_OrderPaymentDialog_dot_1466130374": { "context": "dialog header", - "string": "Capture Payment" + "string": "Đ—Đ°Ņ€Đ°Ņ…ŅƒĐ˛Đ°Ņ‚Đ¸ ĐŋĐģĐ°Ņ‚Ņ–Đļ" }, "src_dot_orders_dot_components_dot_OrderPaymentDialog_dot_250371749": { "context": "dialog header", @@ -2711,11 +2719,11 @@ "string": "ĐžĐąŅŅĐŗ" }, "src_dot_orders_dot_components_dot_OrderPaymentVoidDialog_dot_2217048637": { - "string": "Are you sure you want to void this payment?" + "string": "Ви вĐŋĐĩвĐŊĐĩĐŊŅ–, Ņ‰Đž Ņ…ĐžŅ‡ĐĩŅ‚Đĩ Đ˛Ņ–Đ´ĐŧŅ–ĐŊĐ¸Ņ‚Đ¸ ҆ĐĩĐš ĐŋĐģĐ°Ņ‚Ņ–Đļ?" }, "src_dot_orders_dot_components_dot_OrderPaymentVoidDialog_dot_3089049828": { "context": "dialog header", - "string": "Void Payment" + "string": "Đ’Ņ–Đ´ĐŧŅ–ĐŊĐ¸Ņ‚Đ¸ ĐŋĐģĐ°Ņ‚Ņ–Đļ" }, "src_dot_orders_dot_components_dot_OrderPayment_dot_1325966144": { "context": "order shipping method name", @@ -2723,11 +2731,11 @@ }, "src_dot_orders_dot_components_dot_OrderPayment_dot_1817306106": { "context": "vat included in order price", - "string": "VAT included" + "string": "ПДВ вĐēĐģŅŽŅ‡ĐĩĐŊĐž" }, "src_dot_orders_dot_components_dot_OrderPayment_dot_2183023165": { "context": "ordered products", - "string": "{quantity} items" + "string": "{quantity} ĐŋŅ€ĐĩĐ´ĐŧĐĩŅ‚Ņ–Đ˛" }, "src_dot_orders_dot_components_dot_OrderPayment_dot_2320183694": { "context": "order payment", @@ -2735,7 +2743,7 @@ }, "src_dot_orders_dot_components_dot_OrderPayment_dot_2444197639": { "context": "void payment, button", - "string": "Void" + "string": "Đ’Ņ–Đ´ĐŧŅ–ĐŊĐ¸Ņ‚Đ¸" }, "src_dot_orders_dot_components_dot_OrderPayment_dot_2845258362": { "context": "button", @@ -2749,12 +2757,16 @@ "context": "order payment", "string": "Outstanding Balance" }, + "src_dot_orders_dot_components_dot_OrderPayment_dot_3720114122": { + "context": "order discount", + "string": "ЗĐŊиĐļĐēа " + }, "src_dot_orders_dot_components_dot_OrderPayment_dot_3768782744": { "context": "order payment", "string": "ПоĐŋĐĩŅ€ĐĩĐ´ĐŊŅŒĐž Đ°Đ˛Ņ‚ĐžŅ€Đ¸ĐˇĐžĐ˛Đ°ĐŊа ĐžĐŋĐģĐ°Ņ‚Đ°" }, "src_dot_orders_dot_components_dot_OrderPayment_dot_3955023266": { - "string": "Taxes" + "string": "ĐŸĐžĐ´Đ°Ņ‚Đēи" }, "src_dot_orders_dot_components_dot_OrderPayment_dot_4211710217": { "context": "capture payment, button", @@ -2768,10 +2780,6 @@ "context": "order total price", "string": "РаСОĐŧ" }, - "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_1542417144": { - "context": "dialog header", - "string": "Create Product" - }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2272209368": { "context": "variant sku", "string": "SKU {sku}" @@ -2779,6 +2787,10 @@ "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2336947364": { "string": "Search by product name, attribute, product type etc..." }, + "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2775402904": { + "context": "dialog header", + "string": "Đ”ĐžĐ´Đ°Ņ‚Đ¸ ĐŋŅ€ĐžĐ´ŅƒĐēŅ‚" + }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2850255786": { "string": "Search Products" }, @@ -2807,7 +2819,11 @@ }, "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_2886647373": { "context": "section header", - "string": "Unfulfilled ({quantity})" + "string": "НĐĩвиĐēĐžĐŊаĐŊĐž ({quantity})" + }, + "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" }, "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_878013594": { "context": "order line total price", @@ -2865,10 +2881,10 @@ }, "src_dot_orders_dot_views_dot_OrderDraftList_dot_1161115149": { "context": "dialog header", - "string": "Delete Order Drafts" + "string": "ВидаĐģĐ¸Ņ‚Đ¸ ҇ĐĩŅ€ĐŊĐĩŅ‚Đēи СаĐŧОвĐģĐĩĐŊҌ" }, "src_dot_orders_dot_views_dot_OrderDraftList_dot_1648805446": { - "string": "Deleted draft orders" + "string": "ВидаĐģĐ¸Ņ‚Đ¸ ҇ĐĩŅ€ĐŊŅƒŅ‚Đēи СаĐŧОвĐģĐĩĐŊҌ" }, "src_dot_orders_dot_views_dot_OrderDraftList_dot_1738939038": { "string": "Order draft successfully created" @@ -2898,18 +2914,18 @@ }, "src_dot_pages_dot_components_dot_PageDetailsPage_dot_1068617485": { "context": "page header", - "string": "Create Page" + "string": "ĐĄŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ ŅŅ‚ĐžŅ€Ņ–ĐŊĐē҃" }, "src_dot_pages_dot_components_dot_PageDetailsPage_dot_1815688500": { "context": "page", - "string": "since {date}" + "string": "Ņ€ĐžĐˇĐŧҖ҉ĐĩĐŊĐž С {date}" }, "src_dot_pages_dot_components_dot_PageDetailsPage_dot_1996767833": { "string": "Đ”ĐžĐ´Đ°Ņ‚Đ¸ ĐˇĐ°ĐŗĐžĐģОвОĐē Ņ‚Đ° ĐžĐŋĐ¸Ņ Đ´ĐģŅ ĐŋĐžŅˆŅƒĐēĐžĐ˛ĐžŅ— ŅĐ¸ŅŅ‚ĐĩĐŧи, Ņ‰ĐžĐą ĐŋĐžĐģĐĩĐŗŅˆĐ¸Ņ‚Đ¸ ĐŋĐžŅˆŅƒĐē ҆ҖҔҗ ŅŅ‚ĐžŅ€Ņ–ĐŊĐēи" }, "src_dot_pages_dot_components_dot_PageDetailsPage_dot_2001551496": { "context": "page", - "string": "will be visible from {date}" + "string": "ĐąŅƒĐ´Đĩ видĐŊĐž С {date}" }, "src_dot_pages_dot_components_dot_PageInfo_dot_1116746286": { "context": "page content", @@ -2921,7 +2937,7 @@ }, "src_dot_pages_dot_components_dot_PageListPage_dot_3785394515": { "context": "button", - "string": "Create page" + "string": "ĐĄŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ СаĐŧОвĐģĐĩĐŊĐŊŅ" }, "src_dot_pages_dot_components_dot_PageList_dot_1124600214": { "context": "dialog header", @@ -2929,14 +2945,14 @@ }, "src_dot_pages_dot_components_dot_PageList_dot_1459686496": { "context": "page status", - "string": "Visibility" + "string": "ВидиĐŧŅ–ŅŅ‚ŅŒ" }, "src_dot_pages_dot_components_dot_PageList_dot_2489163252": { "string": "No pages found" }, "src_dot_pages_dot_components_dot_PageList_dot_3478065224": { "context": "page internal name", - "string": "Slug" + "string": "ОĐŋĐ¸ŅĐžĐ˛Đ° Ņ‡Đ°ŅŅ‚Đ¸ĐŊа" }, "src_dot_pages_dot_components_dot_PageList_dot_3640454975": { "context": "page status", @@ -2951,25 +2967,25 @@ }, "src_dot_pages_dot_components_dot_PageSlug_dot_3478065224": { "context": "page internal name", - "string": "Slug" + "string": "ОĐŋĐ¸ŅĐžĐ˛Đ° Ņ‡Đ°ŅŅ‚Đ¸ĐŊа" }, "src_dot_pages_dot_components_dot_PageSlug_dot_4210828158": { "string": "If empty, URL will be autogenerated from Page Name" }, "src_dot_pages_dot_views_dot_1068617485": { "context": "header", - "string": "Create Page" + "string": "ĐĄŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ ŅŅ‚ĐžŅ€Ņ–ĐŊĐē҃" }, "src_dot_pages_dot_views_dot_2680158037": { "string": "Successfully created new page" }, "src_dot_pages_dot_views_dot_3246254285": { "context": "dialog header", - "string": "Delete Page" + "string": "ВидаĐģĐ¸Ņ‚Đ¸ СаĐŧОвĐģĐĩĐŊĐŊŅ" }, "src_dot_pages_dot_views_dot_754348000": { "context": "delete page", - "string": "Are you sure you want to delete {title}?" + "string": "Ви вĐŋĐĩвĐŊĐĩĐŊŅ–, Ņ‰Đž Ņ…ĐžŅ‡ĐĩŅ‚Đĩ видаĐģĐ¸Ņ‚Đ¸ {title}?" }, "src_dot_pages_dot_views_dot_PageList_dot_1080715663": { "context": "notification", @@ -2981,7 +2997,7 @@ }, "src_dot_pages_dot_views_dot_PageList_dot_158565417": { "context": "dialog header", - "string": "Unpublish Pages" + "string": "ĐĄĐēĐ°ŅŅƒĐ˛Đ°Ņ‚Đ¸ ĐŋŅƒĐąĐģŅ–ĐēĐ°Ņ†Ņ–ŅŽ Ņ‚ĐžŅ€Ņ–ĐŊĐēи" }, "src_dot_pages_dot_views_dot_PageList_dot_1640740095": { "context": "dialog content", @@ -3009,7 +3025,7 @@ }, "src_dot_pages_dot_views_dot_PageList_dot_2782958373": { "context": "dialog header", - "string": "Delete Pages" + "string": "ВидаĐģĐ¸Ņ‚Đ¸ ŅŅ‚ĐžŅ€Ņ–ĐŊĐēи" }, "src_dot_paid": { "context": "payment status", @@ -3033,7 +3049,7 @@ }, "src_dot_permissionGroups_dot_components_dot_AssignMembersDialog_dot_1004218338": { "context": "staff member status", - "string": "Inactive" + "string": "НĐĩаĐēŅ‚Đ¸Đ˛ĐŊиК" }, "src_dot_permissionGroups_dot_components_dot_AssignMembersDialog_dot_1731102929": { "context": "button", @@ -3112,7 +3128,7 @@ }, "src_dot_permissionGroups_dot_components_dot_PermissionGroupMemberList_dot_1004218338": { "context": "staff member status", - "string": "Inactive" + "string": "НĐĩаĐēŅ‚Đ¸Đ˛ĐŊиК" }, "src_dot_permissionGroups_dot_components_dot_PermissionGroupMemberList_dot_136112637": { "context": "empty list message", @@ -3157,14 +3173,14 @@ }, "src_dot_permissionGroups_dot_views_dot_PermissionGroupCreate_dot_1140231710": { "context": "window title", - "string": "Create category" + "string": "ĐĄŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ ĐēĐ°Ņ‚ĐĩĐŗĐžŅ€Ņ–ŅŽ" }, "src_dot_permissionGroups_dot_views_dot_PermissionGroupCreate_dot_3930588328": { "string": "Permission group created" }, "src_dot_permissionGroups_dot_views_dot_PermissionGroupDetails_dot_870815507": { "context": "button title", - "string": "Unassign" + "string": "ĐĄĐēĐ°ŅŅƒĐ˛Đ°Ņ‚Đ¸" }, "src_dot_permissionGroups_dot_views_dot_PermissionGroupList_dot_92979760": { "string": "Permission Group Deleted" @@ -3175,7 +3191,7 @@ }, "src_dot_plugins_dot_components_dot_PluginAuthorization_dot_768575093": { "context": "section header", - "string": "Authorization" + "string": "ĐĐ˛Ņ‚ĐžŅ€Đ¸ĐˇĐ°Ņ†Ņ–Ņ" }, "src_dot_plugins_dot_components_dot_PluginInfo_dot_1049131348": { "context": "plugin name", @@ -3194,7 +3210,7 @@ }, "src_dot_plugins_dot_components_dot_PluginSecretFieldDialog_dot_3032939398": { "context": "header", - "string": "Add Value to Authorization Field" + "string": "Đ”ĐžĐ´Đ°Ņ‚Đ¸ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ в ĐŋĐžĐģŅ– Đ°Đ˛Ņ‚ĐžŅ€Đ¸ĐˇĐ°Ņ†Ņ–Ņ—" }, "src_dot_plugins_dot_components_dot_PluginSecretFieldDialog_dot_4269236107": { "context": "header", @@ -3210,7 +3226,7 @@ }, "src_dot_plugins_dot_components_dot_PluginsDetailsPage_dot_3352026836": { "context": "header", - "string": "{pluginName} Details" + "string": "ДĐĩŅ‚Đ°ĐģŅ– {pluginName}" }, "src_dot_plugins_dot_components_dot_PluginsDetailsPage_dot_3425535100": { "context": "section header", @@ -3227,7 +3243,7 @@ }, "src_dot_plugins_dot_components_dot_PluginsListPage_dot_3523826683": { "context": "tab name", - "string": "All Plugins" + "string": "Đ’ŅŅ– ĐŋĐģĐ°ĐŗŅ–ĐŊи" }, "src_dot_plugins_dot_components_dot_PluginsListPage_dot_active": { "context": "plugin", @@ -3235,7 +3251,7 @@ }, "src_dot_plugins_dot_components_dot_PluginsListPage_dot_deactivated": { "context": "plugin", - "string": "Inactive" + "string": "НĐĩаĐēŅ‚Đ¸Đ˛ĐŊиК" }, "src_dot_plugins_dot_components_dot_PluginsList_dot_3247064221": { "context": "plugin status", @@ -3254,7 +3270,7 @@ }, "src_dot_plugins_dot_views_dot_1096544448": { "context": "header", - "string": "Authorization Field Delete" + "string": "ВидаĐģĐ¸Ņ‚Đ¸ ĐŋĐžĐģĐĩ Đ°Đ˛Ņ‚ĐžŅ€Đ¸ĐˇĐ°Ņ†Ņ–Ņ—" }, "src_dot_plugins_dot_views_dot_955370043": { "string": "The plugin may stop working after this field is cleared. Are you sure you want to proceed?" @@ -3265,11 +3281,11 @@ }, "src_dot_productTypes_dot_components_dot_AssignAttributeDialog_dot_2173976534": { "context": "button", - "string": "Assign attributes" + "string": "ĐŸŅ€Đ¸ĐˇĐŊĐ°Ņ‡Đ¸Ņ‚Đ¸ Đ°Ņ‚Ņ€Đ¸ĐąŅƒŅ‚Đ¸" }, "src_dot_productTypes_dot_components_dot_AssignAttributeDialog_dot_3922579741": { "context": "dialog header", - "string": "Assign Attribute" + "string": "ĐŸŅ€Đ¸ĐˇĐŊĐ°Ņ‡Đ¸Ņ‚Đ¸ Đ°Ņ‚Ņ€Đ¸ĐąŅƒŅ‚" }, "src_dot_productTypes_dot_components_dot_AssignAttributeDialog_dot_4205644805": { "string": "No results found" @@ -3281,7 +3297,7 @@ "string": "Search Attributes" }, "src_dot_productTypes_dot_components_dot_ProductTypeAttributeEditDialog_dot_1228425832": { - "string": "Attribute name" + "string": "Назва Đ°Ņ‚Ņ€Đ¸ĐąŅƒŅ‚Ņƒ" }, "src_dot_productTypes_dot_components_dot_ProductTypeAttributeEditDialog_dot_335542212": { "string": "ЗĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Đ°Ņ‚Ņ€Đ¸ĐąŅƒŅ‚Ņ–Đ˛" @@ -3291,21 +3307,21 @@ "string": "Unassign Attribute From Product Type" }, "src_dot_productTypes_dot_components_dot_ProductTypeAttributeUnassignDialog_dot_722498450": { - "string": "Are you sure you want to unassign {attributeName} from {productTypeName}?" + "string": "Ви вĐŋĐĩвĐŊĐĩĐŊŅ–, Ņ‰Đž Ņ…ĐžŅ‡ĐĩŅ‚Đĩ ҁĐēĐ°ŅŅƒĐ˛Đ°Ņ‚Đ¸ ĐŋŅ€Đ¸ĐˇĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ {attributeName} С {productTypeName}?" }, "src_dot_productTypes_dot_components_dot_ProductTypeAttributes_dot_1192828581": { "string": "No attributes found" }, "src_dot_productTypes_dot_components_dot_ProductTypeAttributes_dot_1228425832": { - "string": "Attribute name" + "string": "Назва Đ°Ņ‚Ņ€Đ¸ĐąŅƒŅ‚Ņƒ" }, "src_dot_productTypes_dot_components_dot_ProductTypeAttributes_dot_1656462109": { "context": "button", - "string": "Assign attribute" + "string": "ĐŸŅ€Đ¸ĐˇĐŊĐ°Ņ‡Đ¸Ņ‚Đ¸ Đ°Ņ‚Ņ€Đ¸ĐąŅƒŅ‚" }, "src_dot_productTypes_dot_components_dot_ProductTypeAttributes_dot_3478065224": { "context": "attribute internal name", - "string": "Slug" + "string": "ОĐŋĐ¸ŅĐžĐ˛Đ° Ņ‡Đ°ŅŅ‚Đ¸ĐŊа" }, "src_dot_productTypes_dot_components_dot_ProductTypeAttributes_dot_3559259966": { "context": "section header", @@ -3313,7 +3329,7 @@ }, "src_dot_productTypes_dot_components_dot_ProductTypeAttributes_dot_888493112": { "context": "section header", - "string": "Variant Attributes" + "string": "Đ’Đ°Ņ€Ņ–Đ°ĐŊŅ‚ĐŊŅ– Đ°Ņ‚Ņ€Đ¸ĐąŅƒŅ‚Ņ–Đ˛" }, "src_dot_productTypes_dot_components_dot_ProductTypeBulkAttributeUnassignDialog_dot_2646729060": { "context": "unassign multiple attributes from product type", @@ -3329,7 +3345,7 @@ }, "src_dot_productTypes_dot_components_dot_ProductTypeDeleteDialog_dot_924066985": { "context": "dialog header", - "string": "Delete Product Type" + "string": "ВидаĐģĐ¸Ņ‚Đ¸ Ņ‚Đ¸Đŋ Ņ‚ĐžĐ˛Đ°Ņ€Ņƒ" }, "src_dot_productTypes_dot_components_dot_ProductTypeDetailsPage_dot_1217376589": { "context": "switch button", @@ -3347,11 +3363,11 @@ }, "src_dot_productTypes_dot_components_dot_ProductTypeListPage_dot_3479705616": { "context": "button", - "string": "create product type" + "string": "ŅŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ Ņ‚Đ¸Đŋ Ņ‚ĐžĐ˛Đ°Ņ€Ņƒ" }, "src_dot_productTypes_dot_components_dot_ProductTypeListPage_dot_configurable": { "context": "product type", - "string": "Configurable" + "string": "НаĐģĐ°ŅˆŅ‚ĐžĐ˛ŅƒŅ”Ņ‚ŅŒŅŅ" }, "src_dot_productTypes_dot_components_dot_ProductTypeListPage_dot_digital": { "context": "product", @@ -3363,7 +3379,7 @@ }, "src_dot_productTypes_dot_components_dot_ProductTypeListPage_dot_type": { "context": "product type is digital or physical", - "string": "Type" + "string": "ĐĸиĐŋ" }, "src_dot_productTypes_dot_components_dot_ProductTypeList_dot_1126553969": { "string": "No product types found" @@ -3378,15 +3394,15 @@ }, "src_dot_productTypes_dot_components_dot_ProductTypeList_dot_1952810469": { "context": "product type is either simple or configurable", - "string": "Type" + "string": "ĐĸиĐŋ" }, "src_dot_productTypes_dot_components_dot_ProductTypeList_dot_2253986440": { "context": "product type name", - "string": "Type Name" + "string": "ВвĐĩĐ´Ņ–Ņ‚ŅŒ ĐŊĐ°ĐˇĐ˛Ņƒ" }, "src_dot_productTypes_dot_components_dot_ProductTypeList_dot_2754779425": { "context": "product type", - "string": "Configurable" + "string": "НаĐģĐ°ŅˆŅ‚ĐžĐ˛ŅƒŅ”Ņ‚ŅŒŅŅ" }, "src_dot_productTypes_dot_components_dot_ProductTypeList_dot_881286562": { "context": "product type", @@ -3405,17 +3421,17 @@ "string": "Is this product shippable?" }, "src_dot_productTypes_dot_components_dot_ProductTypeShipping_dot_2927891783": { - "string": "Used to calculate rates for shipping for products of this product type, when specific weight is not given" + "string": "ВиĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚ŅŒŅŅ Đ´ĐģŅ ĐžĐąŅ‡Đ¸ŅĐģĐĩĐŊĐŊŅ Ņ‚Đ°Ņ€Đ¸Ņ„Ņ–Đ˛ ĐŊа Đ´ĐžŅŅ‚Đ°Đ˛Đē҃ ĐŋŅ€ĐžĐ´ŅƒĐē҆Җҗ Ņ†ŅŒĐžĐŗĐž Ņ‚Đ¸Đŋ҃ Ņ‚ĐžĐ˛Đ°Ņ€Ņƒ, ĐēĐžĐģи ĐēĐžĐŊĐēŅ€ĐĩŅ‚ĐŊа Đ˛Đ°ĐŗĐ° ĐŊĐĩ ĐŊĐ°Đ˛ĐžĐ´Đ¸Ņ‚ŅŒŅŅ" }, "src_dot_productTypes_dot_components_dot_ProductTypeShipping_dot_746695941": { - "string": "Weight" + "string": "Đ’Đ°ĐŗĐ°" }, "src_dot_productTypes_dot_views_dot_3822478981": { "string": "Successfully created product type" }, "src_dot_productTypes_dot_views_dot_ProductTypeList_dot_4080551769": { "context": "dialog header", - "string": "Delete Product Types" + "string": "ВидаĐģĐ¸Ņ‚Đ¸ Ņ‚Đ¸Đŋи Ņ‚ĐžĐ˛Đ°Ņ€Ņ–Đ˛" }, "src_dot_productTypes_dot_views_dot_ProductTypeList_dot_4269954457": { "context": "dialog content", @@ -3426,7 +3442,7 @@ }, "src_dot_productTypes_dot_views_dot_ProductTypeUpdate_dot_870815507": { "context": "unassign attribute from product type, button", - "string": "Unassign" + "string": "ĐĄĐēĐ°ŅŅƒĐ˛Đ°Ņ‚Đ¸" }, "src_dot_products": { "context": "products section name", @@ -3434,7 +3450,7 @@ }, "src_dot_products_dot_components_dot_ProductAttributes_dot_1071548120": { "context": "number of product attributes", - "string": "{number} Attributes" + "string": "{number} ВĐģĐ°ŅŅ‚Đ¸Đ˛ĐžŅŅ‚Ņ–" }, "src_dot_products_dot_components_dot_ProductAttributes_dot_1148029984": { "context": "attribute value", @@ -3460,11 +3476,11 @@ }, "src_dot_products_dot_components_dot_ProductCreatePage_dot_1815688500": { "context": "product", - "string": "since {date}" + "string": "Ņ€ĐžĐˇĐŧҖ҉ĐĩĐŊĐž С {date}" }, "src_dot_products_dot_components_dot_ProductCreatePage_dot_2001551496": { "context": "product", - "string": "will be visible from {date}" + "string": "ĐąŅƒĐ´Đĩ видĐŊĐž С {date}" }, "src_dot_products_dot_components_dot_ProductCreatePage_dot_2706108815": { "string": "Đ”ĐžĐ´Đ°Ņ‚Đ¸ ĐˇĐ°ĐŗĐžĐģОвОĐē Ņ‚Đ° ĐžĐŋĐ¸Ņ Đ´ĐģŅ ĐŋĐžŅˆŅƒĐēĐžĐ˛ĐžŅ— ŅĐ¸ŅŅ‚ĐĩĐŧи, Ņ‰ĐžĐą ĐŋĐžĐģĐĩĐŗŅˆĐ¸Ņ‚Đ¸ ĐŋĐžŅˆŅƒĐē Ņ†ŅŒĐžĐŗĐž Ņ‚ĐžĐ˛Đ°Ņ€Ņƒ" @@ -3503,11 +3519,11 @@ }, "src_dot_products_dot_components_dot_ProductListPage_dot_1542417144": { "context": "button", - "string": "Create Product" + "string": "ĐĄŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ Ņ‚ĐžĐ˛Đ°Ņ€" }, "src_dot_products_dot_components_dot_ProductListPage_dot_1952810469": { "context": "product type", - "string": "Type" + "string": "ĐĸиĐŋ" }, "src_dot_products_dot_components_dot_ProductListPage_dot_3550330425": { "string": "Search Products..." @@ -3522,7 +3538,7 @@ }, "src_dot_products_dot_components_dot_ProductListPage_dot_available": { "context": "product status", - "string": "Available" + "string": "Đ”ĐžŅŅ‚ŅƒĐŋĐŊŅ–" }, "src_dot_products_dot_components_dot_ProductListPage_dot_hidden": { "context": "product is hidden", @@ -3541,22 +3557,22 @@ }, "src_dot_products_dot_components_dot_ProductListPage_dot_visibility": { "context": "product visibility", - "string": "Visibility" + "string": "ВидиĐŧŅ–ŅŅ‚ŅŒ" }, "src_dot_products_dot_components_dot_ProductListPage_dot_visible": { "context": "product is visible", - "string": "Visible" + "string": "ВидиĐŧиК" }, "src_dot_products_dot_components_dot_ProductList_dot_1134347598": { "context": "product price", "string": "ĐĻŅ–ĐŊа" }, "src_dot_products_dot_components_dot_ProductList_dot_1657559629": { - "string": "No products found" + "string": "НĐĩ СĐŊаКдĐĩĐŊĐž ĐļОдĐŊĐžĐŗĐž Ņ‚ĐžĐ˛Đ°Ņ€Ņƒ" }, "src_dot_products_dot_components_dot_ProductList_dot_1952810469": { "context": "product type", - "string": "Type" + "string": "ĐĸиĐŋ" }, "src_dot_products_dot_components_dot_ProductList_dot_2341910657": { "context": "product status", @@ -3586,7 +3602,7 @@ }, "src_dot_products_dot_components_dot_ProductOrganization_dot_2754779425": { "context": "product is configurable", - "string": "Configurable" + "string": "НаĐģĐ°ŅˆŅ‚ĐžĐ˛ŅƒŅ”Ņ‚ŅŒŅŅ" }, "src_dot_products_dot_components_dot_ProductOrganization_dot_2805838453": { "context": "field is optional", @@ -3611,7 +3627,7 @@ }, "src_dot_products_dot_components_dot_ProductStocks_dot_2622674857": { "context": "tabel column header", - "string": "Warehouse Name" + "string": "Назва ҁĐēĐģĐ°Đ´Ņƒ" }, "src_dot_products_dot_components_dot_ProductStocks_dot_2729628316": { "context": "tabel column header", @@ -3621,38 +3637,35 @@ "context": "header", "string": "ĐšŅ–ĐģҌĐēŅ–ŅŅ‚ŅŒ" }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3143542809": { - "string": "This product doesn't have any stock. You can add it here." - }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3482985373": { - "context": "button", - "string": "Edit Warehouses" - }, "src_dot_products_dot_components_dot_ProductStocks_dot_3633706025": { "context": "product inventory, checkbox", "string": "Track Inventory" }, + "src_dot_products_dot_components_dot_ProductStocks_dot_3857433664": { + "context": "button", + "string": "Assign Warehouse" + }, "src_dot_products_dot_components_dot_ProductStocks_dot_849869830": { "string": "Active inventory tracking will automatically calculate changes of stock" }, "src_dot_products_dot_components_dot_ProductUpdatePage_dot_1815688500": { "context": "product", - "string": "since {date}" + "string": "Ņ€ĐžĐˇĐŧҖ҉ĐĩĐŊĐž С {date}" }, "src_dot_products_dot_components_dot_ProductUpdatePage_dot_2001551496": { "context": "product", - "string": "will be visible from {date}" + "string": "ĐąŅƒĐ´Đĩ видĐŊĐž С {date}" }, "src_dot_products_dot_components_dot_ProductUpdatePage_dot_2706108815": { "string": "Đ”ĐžĐ´Đ°Ņ‚Đ¸ ĐˇĐ°ĐŗĐžĐģОвОĐē Ņ‚Đ° ĐžĐŋĐ¸Ņ Đ´ĐģŅ ĐŋĐžŅˆŅƒĐēĐžĐ˛ĐžŅ— ŅĐ¸ŅŅ‚ĐĩĐŧи, Ņ‰ĐžĐą ĐŋĐžĐģĐĩĐŗŅˆĐ¸Ņ‚Đ¸ ĐŋĐžŅˆŅƒĐē Ņ†ŅŒĐžĐŗĐž Ņ‚ĐžĐ˛Đ°Ņ€Ņƒ" }, "src_dot_products_dot_components_dot_ProductVariantAttributes_dot_1536841622": { "context": "product attribute error", - "string": "All attributes should have value" + "string": "Đ’ŅŅ– Đ°Ņ‚Ņ€Đ¸ĐąŅƒŅ‚Đ¸ ĐŋОвиĐŊĐŊŅ– ĐŧĐ°Ņ‚Đ¸ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ" }, "src_dot_products_dot_components_dot_ProductVariantAttributes_dot_258966189": { "context": "product attribute error", - "string": "This variant already exists" + "string": "ĐĻĐĩĐš Đ˛Đ°Ņ€Ņ–Đ°ĐŊŅ‚ вĐļĐĩ ҖҁĐŊŅƒŅ”" }, "src_dot_products_dot_components_dot_ProductVariantCreatePage_dot_2853608829": { "context": "button", @@ -3660,7 +3673,7 @@ }, "src_dot_products_dot_components_dot_ProductVariantCreatePage_dot_3726089650": { "context": "button", - "string": "Delete Variant" + "string": "ВидаĐģĐ¸Ņ‚Đ¸ Đ˛Đ°Ņ€Ņ–Đ°ĐŊŅ‚" }, "src_dot_products_dot_components_dot_ProductVariantCreatorPage_dot_1134347598": { "context": "variant price", @@ -3671,7 +3684,7 @@ }, "src_dot_products_dot_components_dot_ProductVariantCreatorPage_dot_168343345": { "context": "variant attribute", - "string": "Attribute" + "string": "ĐŅ‚Ņ€Đ¸ĐąŅƒŅ‚" }, "src_dot_products_dot_components_dot_ProductVariantCreatorPage_dot_1808330403": { "context": "variant attribute", @@ -3702,16 +3715,16 @@ "string": "ĐŸŅ–Đ´ŅŅƒĐŧĐžĐē" }, "src_dot_products_dot_components_dot_ProductVariantCreatorPage_dot_2783195765": { - "string": "Apply single price to all SKUs" + "string": "Đ—Đ°ŅŅ‚ĐžŅĐžĐ˛ŅƒĐšŅ‚Đĩ Ņ”Đ´Đ¸ĐŊ҃ ҆ҖĐŊ҃ Đ´Đž Đ˛ŅŅ–Ņ… SKU" }, "src_dot_products_dot_components_dot_ProductVariantCreatorPage_dot_3387090508": { - "string": "Apply unique stock by attribute to each SKU" + "string": "Đ—Đ°ŅŅ‚ĐžŅĐžĐ˛ŅƒĐšŅ‚Đĩ ҃ĐŊŅ–ĐēаĐģҌĐŊиК СаĐŋĐ°Ņ Са вĐģĐ°ŅŅ‚Đ¸Đ˛Ņ–ŅĐŊŅŽ Đ´Đž ĐēĐžĐļĐŊĐžĐŗĐž SKU" }, "src_dot_products_dot_components_dot_ProductVariantCreatorPage_dot_3570949907": { - "string": "Apply unique prices by attribute to each SKU" + "string": "Đ—Đ°ŅŅ‚ĐžŅĐžĐ˛ŅƒĐšŅ‚Đĩ ҃ĐŊŅ–ĐēаĐģҌĐŊŅ– ҆ҖĐŊи Са вĐģĐ°ŅŅ‚Đ¸Đ˛ĐžŅŅ‚ŅĐŧи Đ´Đž ĐēĐžĐļĐŊĐžĐŗĐž SKU" }, "src_dot_products_dot_components_dot_ProductVariantCreatorPage_dot_3601538615": { - "string": "Apply single stock to all SKUs" + "string": "Đ—Đ°ŅŅ‚ĐžŅĐžĐ˛ŅƒĐšŅ‚Đĩ ОдиĐŊĐžŅ‡ĐŊиК СаĐŋĐ°Ņ Đ´Đž Đ˛ŅŅ–Ņ… SKU" }, "src_dot_products_dot_components_dot_ProductVariantCreatorPage_dot_3673120330": { "context": "button", @@ -3762,7 +3775,7 @@ }, "src_dot_products_dot_components_dot_ProductVariantDeleteDialog_dot_3726089650": { "context": "dialog header", - "string": "Delete Variant" + "string": "ВидаĐģĐ¸Ņ‚Đ¸ Đ˛Đ°Ņ€Ņ–Đ°ĐŊŅ‚" }, "src_dot_products_dot_components_dot_ProductVariantImageSelectDialog_dot_3196043669": { "context": "dialog header", @@ -3799,7 +3812,7 @@ "string": "Cost price override" }, "src_dot_products_dot_components_dot_ProductVariantPrice_dot_2238565650": { - "string": "Selling price override" + "string": "ĐĻŅ–ĐŊа ĐŋŅ€ĐžĐ´Đ°Đļ҃ ĐŋĐĩŅ€ĐĩĐ˛Đ¸Ņ‰ĐĩĐŊа" }, "src_dot_products_dot_components_dot_ProductVariants_dot_1001303107": { "context": "product variant inventory", @@ -3807,7 +3820,7 @@ }, "src_dot_products_dot_components_dot_ProductVariants_dot_1033175132": { "context": "product variant inventory", - "string": "Unavailable" + "string": "НĐĩĐ´ĐžŅŅ‚ŅƒĐŋĐŊиК" }, "src_dot_products_dot_components_dot_ProductVariants_dot_1134347598": { "context": "product variant price", @@ -3823,7 +3836,7 @@ }, "src_dot_products_dot_components_dot_ProductVariants_dot_1721716102": { "context": "button", - "string": "Create variants" + "string": "ĐĄŅ‚Đ˛ĐžŅ€Ņ–Ņ‚ŅŒ Đ˛Đ°Ņ€Ņ–Đ°ĐŊŅ‚Đ¸" }, "src_dot_products_dot_components_dot_ProductVariants_dot_2153006789": { "context": "section header", @@ -3834,11 +3847,11 @@ "string": "{numLocations,plural,one {{numAvailable} available at {numLocations} location} other {{numAvailable} available at {numLocations} locations}}" }, "src_dot_products_dot_components_dot_ProductVariants_dot_277989856": { - "string": "Use variants for products that come in a variety of versions for example different sizes or colors" + "string": "ВиĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐšŅ‚Đĩ Đ˛Đ°Ņ€Ņ–Đ°ĐŊŅ‚Đ¸ Đ´ĐģŅ Ņ‚ĐžĐ˛Đ°Ņ€Ņ–Đ˛, ŅĐēŅ– виĐŋ҃ҁĐēĐ°ŅŽŅ‚ŅŒŅŅ в Ņ€Ņ–ĐˇĐŊĐ¸Ņ… вĐĩŅ€ŅŅ–ŅŅ…, ĐŊаĐŋŅ€Đ¸ĐēĐģад, Ņ€Ņ–ĐˇĐŊĐ¸Ņ… Ņ€ĐžĐˇĐŧŅ–Ņ€Ņ–Đ˛ айО ĐēĐžĐģŅŒĐžŅ€Ņ–Đ˛" }, "src_dot_products_dot_components_dot_ProductVariants_dot_3203451491": { "context": "filtering option", - "string": "All Warehouses" + "string": "Đ’ŅŅ– ҁĐēĐģади" }, "src_dot_products_dot_components_dot_ProductVariants_dot_3490038570": { "context": "product variant inventory status", @@ -3846,7 +3859,7 @@ }, "src_dot_products_dot_components_dot_ProductVariants_dot_3989383405": { "context": "button", - "string": "Create variant" + "string": "ĐĄŅ‚Đ˛ĐžŅ€Ņ–Ņ‚ŅŒ Đ˛Đ°Ņ€Ņ–Đ°ĐŊŅ‚" }, "src_dot_products_dot_components_dot_ProductVariants_dot_4017567521": { "context": "product variant inventory", @@ -3859,16 +3872,9 @@ "context": "product variant name", "string": "Đ’Đ°Ņ€Ņ–Đ°ĐŊŅ‚" }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_3482985373": { - "context": "dialog header", - "string": "Edit Warehouses" - }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_4112406382": { - "string": "Select warehouses that stock selected product" - }, "src_dot_products_dot_views_dot_1542417144": { "context": "window title", - "string": "Create Product" + "string": "ĐĄŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ Ņ‚ĐžĐ˛Đ°Ņ€" }, "src_dot_products_dot_views_dot_1591632382": { "context": "page header", @@ -3876,24 +3882,24 @@ }, "src_dot_products_dot_views_dot_1731766393": { "context": "dialog header", - "string": "Delete Image" + "string": "ВидаĐģĐ¸Ņ‚Đ¸ ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊĐŊŅ" }, "src_dot_products_dot_views_dot_2279302139": { - "string": "Variant removed" + "string": "Đ’Đ°Ņ€Ņ–Đ°ĐŊŅ‚ видаĐģĐĩĐŊĐž" }, "src_dot_products_dot_views_dot_2362587265": { "context": "header", - "string": "Create Variant" + "string": "ĐĄŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ Đē҃ĐŋĐžĐŊ" }, "src_dot_products_dot_views_dot_2880386427": { - "string": "Are you sure you want to delete this image?" + "string": "Ви вĐŋĐĩвĐŊĐĩĐŊŅ–, Ņ‰Đž Ņ…ĐžŅ‡ĐĩŅ‚Đĩ видаĐģĐ¸Ņ‚Đ¸ ҆Đĩ ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊĐŊŅ?" }, "src_dot_products_dot_views_dot_2899821092": { - "string": "Product created" + "string": "ĐĸĐžĐ˛Đ°Ņ€ ŅŅ‚Đ˛ĐžŅ€ĐĩĐŊĐž" }, "src_dot_products_dot_views_dot_3989383405": { "context": "window title", - "string": "Create variant" + "string": "ĐĄŅ‚Đ˛ĐžŅ€Ņ–Ņ‚ŅŒ Đ˛Đ°Ņ€Ņ–Đ°ĐŊŅ‚" }, "src_dot_products_dot_views_dot_ProductList_dot_1204353135": { "context": "dialog content", @@ -3917,7 +3923,7 @@ }, "src_dot_products_dot_views_dot_ProductList_dot_3362608461": { "context": "dialog header", - "string": "Unpublish Products" + "string": "ĐĄĐēĐ°ŅŅƒĐ˛Đ°Ņ‚Đ¸ ĐŋŅƒĐąĐģŅ–ĐēĐ°Ņ†Ņ–ŅŽ Ņ‚ĐžĐ˛Đ°Ņ€Ņƒ" }, "src_dot_products_dot_views_dot_ProductList_dot_3518737068": { "context": "dialog content", @@ -3925,7 +3931,7 @@ }, "src_dot_products_dot_views_dot_ProductList_dot_400629795": { "context": "dialog header", - "string": "Delete Products" + "string": "ВидаĐģĐ¸Ņ‚Đ¸ Ņ‚ĐžĐ˛Đ°Ņ€Đ¸" }, "src_dot_products_dot_views_dot_ProductUpdate_dot_1177237881": { "context": "dialog content", @@ -3933,7 +3939,7 @@ }, "src_dot_products_dot_views_dot_ProductUpdate_dot_1454532689": { "context": "dialog header", - "string": "Delete Product Variants" + "string": "ВидаĐģĐ¸Ņ‚Đ¸ Đ˛Đ°Ņ€Ņ–Đ°ĐŊŅ‚Đ¸ Ņ‚ĐžĐ˛Đ°Ņ€Ņ–Đ˛" }, "src_dot_products_dot_views_dot_ProductUpdate_dot_2297471173": { "context": "delete product", @@ -3944,7 +3950,7 @@ }, "src_dot_products_dot_views_dot_ProductUpdate_dot_879305849": { "context": "dialog header", - "string": "Delete Product" + "string": "ВидаĐģĐ¸Ņ‚Đ¸ Ņ‚ĐžĐ˛Đ°Ņ€" }, "src_dot_products_dot_views_dot_ProductVariantCreator_dot_2292700443": { "context": "success message", @@ -3977,7 +3983,7 @@ "string": "ВидаĐģĐ¸Ņ‚Đ¸" }, "src_dot_requiredField": { - "string": "This field is required" + "string": "ĐĻĐĩ ĐŋĐžĐģĐĩ Ņ” ОйОв'ŅĐˇĐēОвиĐŧ" }, "src_dot_sales": { "context": "sales section name", @@ -3996,11 +4002,11 @@ }, "src_dot_services_dot_components_dot_ServiceCreatePage_dot_1848599267": { "context": "checkbox label", - "string": "User has full access to the store" + "string": "ĐšĐžŅ€Đ¸ŅŅ‚ŅƒĐ˛Đ°Ņ‡ ĐŧĐ°Ņ” ĐŋОвĐŊиК Đ´ĐžŅŅ‚ŅƒĐŋ Đ´Đž ĐŧĐ°ĐŗĐ°ĐˇĐ¸ĐŊ҃" }, "src_dot_services_dot_components_dot_ServiceCreatePage_dot_248507553": { "context": "header", - "string": "Create New Account" + "string": "ĐĄŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ ĐŊĐžĐ˛Ņ–Đš ОйĐģŅ–ĐēОвиК СаĐŋĐ¸Ņ" }, "src_dot_services_dot_components_dot_ServiceCreatePage_dot_27827485": { "context": "checkbox label", @@ -4011,25 +4017,25 @@ "string": "Expand or restrict user's permissions to access certain part of saleor system." }, "src_dot_services_dot_components_dot_ServiceDefaultToken_dot_1336855942": { - "string": "Generated Token" + "string": "ĐĄŅ‚Đ˛ĐžŅ€ĐĩĐŊĐž Ņ–Đ´ĐĩĐŊŅ‚Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–ĐšĐŊиК СĐŊаĐē" }, "src_dot_services_dot_components_dot_ServiceDefaultToken_dot_2080322626": { - "string": "This token gives you access to your shop's API, which you'll find here: {url}" + "string": "ĐĻĐĩĐš Ņ–Đ´ĐĩĐŊŅ‚Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–ĐšĐŊиК СĐŊаĐē ĐŊĐ°Đ´Đ°Ņ” ваĐŧ Đ´ĐžŅŅ‚ŅƒĐŋ Đ´Đž API Đ˛Đ°ŅˆĐžĐŗĐž ĐŧĐ°ĐŗĐ°ĐˇĐ¸ĐŊ҃, ŅĐēиК ви СĐŊаКдĐĩŅ‚Đĩ Ņ‚ŅƒŅ‚: {url}" }, "src_dot_services_dot_components_dot_ServiceDefaultToken_dot_2864204643": { "context": "button", - "string": "Copied" + "string": "ĐĄĐēĐžĐŋŅ–ĐšĐžĐ˛Đ°ĐŊĐž" }, "src_dot_services_dot_components_dot_ServiceDefaultToken_dot_3406541221": { "context": "button", - "string": "Copy token" + "string": "ĐĄĐēĐžĐŋŅ–ŅŽĐ˛Đ°Ņ‚Đ¸ Ņ‚ĐžĐēĐĩĐŊ" }, "src_dot_services_dot_components_dot_ServiceDefaultToken_dot_4189999598": { - "string": "We’ve created your default token. Make sure to copy your new personal access token now. You won’t be able to see it again." + "string": "Ми ŅŅ‚Đ˛ĐžŅ€Đ¸Đģи Đ˛Đ°Ņˆ Ņ–Đ´ĐĩĐŊŅ‚Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–ĐšĐŊиК СĐŊаĐē Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ. НĐĩ ĐˇĐ°ĐąŅƒĐ´ŅŒŅ‚Đĩ ҁĐēĐžĐŋŅ–ŅŽĐ˛Đ°Ņ‚Đ¸ ŅĐ˛Ņ–Đš ĐŊОвиК ĐžŅĐžĐąĐ¸ŅŅ‚Đ¸Đš Ņ–Đ´ĐĩĐŊŅ‚Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–ĐšĐŊиК СĐŊаĐē Đ´ĐžŅŅ‚ŅƒĐŋ҃ ĐˇĐ°Ņ€Đ°Đˇ. Ви ĐąŅ–ĐģҌ҈Đĩ ĐŊĐĩ СĐŧĐžĐļĐĩŅ‚Đĩ ĐšĐžĐŗĐž ĐŋĐžĐąĐ°Ņ‡Đ¸Ņ‚Đ¸." }, "src_dot_services_dot_components_dot_ServiceDeleteDialog_dot_1534767622": { "context": "dialog header", - "string": "Delete Service Account" + "string": "ВидаĐģĐ¸Ņ‚Đ¸ ҁĐģ҃ĐļйОвиК ОйĐģŅ–ĐēОвиК СаĐŋĐ¸Ņ" }, "src_dot_services_dot_components_dot_ServiceDeleteDialog_dot_2297471173": { "context": "delete service account", @@ -4037,7 +4043,7 @@ }, "src_dot_services_dot_components_dot_ServiceDetailsPage_dot_1848599267": { "context": "checkbox label", - "string": "User has full access to the store" + "string": "ĐšĐžŅ€Đ¸ŅŅ‚ŅƒĐ˛Đ°Ņ‡ ĐŧĐ°Ņ” ĐŋОвĐŊиК Đ´ĐžŅŅ‚ŅƒĐŋ Đ´Đž ĐŧĐ°ĐŗĐ°ĐˇĐ¸ĐŊ҃" }, "src_dot_services_dot_components_dot_ServiceDetailsPage_dot_27827485": { "context": "checkbox label", @@ -4064,7 +4070,7 @@ }, "src_dot_services_dot_components_dot_ServiceListPage_dot_624280156": { "context": "button", - "string": "Create account" + "string": "ĐĄŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ ОйĐģŅ–ĐēОвиК СаĐŋĐ¸Ņ" }, "src_dot_services_dot_components_dot_ServiceListPage_dot_active": { "context": "service account", @@ -4072,7 +4078,7 @@ }, "src_dot_services_dot_components_dot_ServiceListPage_dot_deactivated": { "context": "service account", - "string": "Inactive" + "string": "НĐĩаĐēŅ‚Đ¸Đ˛ĐŊиК" }, "src_dot_services_dot_components_dot_ServiceList_dot_1342308051": { "string": "No service accounts found" @@ -4083,31 +4089,31 @@ }, "src_dot_services_dot_components_dot_ServiceList_dot_3239722049": { "context": "account status", - "string": "inactive" + "string": "ĐŊĐĩаĐēŅ‚Đ¸Đ˛ĐŊиК" }, "src_dot_services_dot_components_dot_ServiceList_dot_636461959": { "context": "service name", "string": "Назва" }, "src_dot_services_dot_components_dot_ServiceTokenCreateDialog_dot_1336855942": { - "string": "Generated Token" + "string": "ĐĄŅ‚Đ˛ĐžŅ€ĐĩĐŊĐž Ņ–Đ´ĐĩĐŊŅ‚Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–ĐšĐŊиК СĐŊаĐē" }, "src_dot_services_dot_components_dot_ServiceTokenCreateDialog_dot_2530792168": { "string": "ĐĸĐžĐēĐĩĐŊ Đ´ĐžŅŅ‚ŅƒĐŋ҃ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚ŅŒŅŅ Đ´ĐģŅ Đ°Đ˛Ņ‚ĐĩĐŊŅ‚Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–Ņ— в аĐēĐ°ŅƒĐŊŅ‚Đ°Ņ… ҁĐĩŅ€Đ˛Ņ–ŅŅ–Đ˛" }, "src_dot_services_dot_components_dot_ServiceTokenCreateDialog_dot_3009959880": { - "string": "We’ve created your token. Make sure to copy your new personal access token now. You won’t be able to see it again." + "string": "Ми ŅŅ‚Đ˛ĐžŅ€Đ¸Đģи Đ˛Đ°Ņˆ Ņ–Đ´ĐĩĐŊŅ‚Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–ĐšĐŊиК СĐŊаĐē. НĐĩ ĐˇĐ°ĐąŅƒĐ´ŅŒŅ‚Đĩ ҁĐēĐžĐŋŅ–ŅŽĐ˛Đ°Ņ‚Đ¸ ŅĐ˛Ņ–Đš ĐŊОвиК ĐžŅĐžĐąĐ¸ŅŅ‚Đ¸Đš Ņ–Đ´ĐĩĐŊŅ‚Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–ĐšĐŊиК СĐŊаĐē Đ´ĐžŅŅ‚ŅƒĐŋ҃ ĐˇĐ°Ņ€Đ°Đˇ. Ви ĐąŅ–ĐģҌ҈Đĩ ĐŊĐĩ СĐŧĐžĐļĐĩŅ‚Đĩ ĐšĐžĐŗĐž ĐŋĐžĐąĐ°Ņ‡Đ¸Ņ‚Đ¸." }, "src_dot_services_dot_components_dot_ServiceTokenCreateDialog_dot_3406541221": { "context": "button", - "string": "Copy token" + "string": "ĐĄĐēĐžĐŋŅ–ŅŽĐ˛Đ°Ņ‚Đ¸ Ņ‚ĐžĐēĐĩĐŊ" }, "src_dot_services_dot_components_dot_ServiceTokenCreateDialog_dot_3875340101": { "context": "header", - "string": "Create Token" + "string": "ĐĄŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ Ņ‚ĐžĐēĐĩĐŊ" }, "src_dot_services_dot_components_dot_ServiceTokenCreateDialog_dot_4017491013": { - "string": "Token Note" + "string": "ĐŸŅ€Đ¸ĐŧŅ–Ņ‚Đēа Ņ‚ĐžĐēĐĩĐŊ҃" }, "src_dot_services_dot_components_dot_ServiceTokenCreateDialog_dot_4120989039": { "context": "create service token, button", @@ -4115,25 +4121,25 @@ }, "src_dot_services_dot_components_dot_ServiceTokenDeleteDialog_dot_1534767622": { "context": "dialog title", - "string": "Delete Service Account" + "string": "ВидаĐģĐ¸Ņ‚Đ¸ ҁĐģ҃ĐļйОвиК ОйĐģŅ–ĐēОвиК СаĐŋĐ¸Ņ" }, "src_dot_services_dot_components_dot_ServiceTokenDeleteDialog_dot_981802752": { "context": "delete token", - "string": "Are you sure you want to delete token {token}?" + "string": "Ви вĐŋĐĩвĐŊĐĩĐŊŅ–, Ņ‰Đž Ņ…ĐžŅ‡ĐĩŅ‚Đĩ видаĐģĐ¸Ņ‚Đ¸ Ņ‚ĐžĐēĐĩĐŊ {token}?" }, "src_dot_services_dot_components_dot_ServiceTokens_dot_2446088470": { "context": "service account key", "string": "КĐģŅŽŅ‡" }, "src_dot_services_dot_components_dot_ServiceTokens_dot_2639089057": { - "string": "No tokens found" + "string": "НĐĩ СĐŊаКдĐĩĐŊĐž Ņ–Đ´ĐĩĐŊŅ‚Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–ĐšĐŊĐžĐŗĐž СĐŊаĐē҃" }, "src_dot_services_dot_components_dot_ServiceTokens_dot_3875340101": { "context": "button", - "string": "Create Token" + "string": "ĐĄŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ Ņ‚ĐžĐēĐĩĐŊ" }, "src_dot_services_dot_components_dot_ServiceTokens_dot_4017491013": { - "string": "Token Note" + "string": "ĐŸŅ€Đ¸ĐŧŅ–Ņ‚Đēа Ņ‚ĐžĐēĐĩĐŊ҃" }, "src_dot_services_dot_components_dot_ServiceTokens_dot_4190792473": { "context": "table actions", @@ -4145,20 +4151,23 @@ }, "src_dot_services_dot_views_dot_ServiceCreate_dot_3167211165": { "context": "window title", - "string": "Create Service Account" + "string": "ĐĄŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ ҁĐĩŅ€Đ˛Ņ–ŅĐŊиК ОйĐģŅ–ĐēОвиК СаĐŋĐ¸Ņ" + }, + "src_dot_sessionExpired": { + "string": "Your session has expired. Please log in again to continue." }, "src_dot_shipping": { "context": "shipping section name", "string": "Shipping Methods" }, "src_dot_shipping_dot_components_dot_ShippingWeightUnitForm_dot_2863708228": { - "string": "This unit will be used as default shipping weight" + "string": "ĐĻŅ ОдиĐŊĐ¸Ņ†Ņ ĐąŅƒĐ´Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ŅŅ ŅĐē Đ˛Đ°ĐŗĐ° Đ´ĐžŅŅ‚Đ°Đ˛Đēи Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ" }, "src_dot_shipping_dot_components_dot_ShippingWeightUnitForm_dot_549146363": { "string": "Shipping Weight Unit" }, "src_dot_shipping_dot_components_dot_ShippingZoneAddWarehouseDialog_dot_2622674857": { - "string": "Warehouse Name" + "string": "Назва ҁĐēĐģĐ°Đ´Ņƒ" }, "src_dot_shipping_dot_components_dot_ShippingZoneAddWarehouseDialog_dot_3173942020": { "context": "header, dialog", @@ -4172,7 +4181,7 @@ }, "src_dot_shipping_dot_components_dot_ShippingZoneCountriesAssignDialog_dot_1585396479": { "context": "dialog header", - "string": "Assign Countries" + "string": "ĐŸŅ€Đ¸ĐˇĐŊĐ°Ņ‡Đ¸Ņ‚Đ¸ ĐēŅ€Đ°Ņ—ĐŊи" }, "src_dot_shipping_dot_components_dot_ShippingZoneCountriesAssignDialog_dot_1818089229": { "string": "If selected, this will add all of the countries not selected to other shipping zones" @@ -4185,11 +4194,11 @@ }, "src_dot_shipping_dot_components_dot_ShippingZoneCountriesAssignDialog_dot_2747492886": { "context": "button", - "string": "Assign countries" + "string": "ĐŸŅ€Đ¸ĐˇĐŊĐ°Ņ‡Đ¸Ņ‚Đ¸ ĐēŅ€Đ°Ņ—ĐŊи" }, "src_dot_shipping_dot_components_dot_ShippingZoneCountriesAssignDialog_dot_2777439857": { "context": "country selection", - "string": "Countries A to Z" + "string": "ĐšŅ€Đ°Ņ—ĐŊи Đ˛Ņ–Đ´ А Đ´Đž Đ¯" }, "src_dot_shipping_dot_components_dot_ShippingZoneCountriesAssignDialog_dot_3510295703": { "string": "Search Countries" @@ -4202,7 +4211,7 @@ }, "src_dot_shipping_dot_components_dot_ShippingZoneCreatePage_dot_4049462680": { "context": "header", - "string": "Create New Shipping Zone" + "string": "ĐĄŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ ĐŊĐžĐ˛Ņƒ СОĐŊ҃ Đ´ĐžŅŅ‚Đ°Đ˛Đēи" }, "src_dot_shipping_dot_components_dot_ShippingZoneCreatePage_dot_4270729636": { "string": "This is default shipping zone, which means that it covers all of the countries which are not assigned to other shipping zones" @@ -4237,11 +4246,11 @@ "string": "Rate Price" }, "src_dot_shipping_dot_components_dot_ShippingZoneRateDialog_dot_1486599614": { - "string": "This will be shown to customers at checkout" + "string": "ĐĻĐĩ ĐąŅƒĐ´Đĩ ĐŋĐžĐēаСаĐŊĐž ĐēĐģŅ–Ņ”ĐŊŅ‚Đ°Đŧ ĐŋŅ€Đ¸ ĐžŅ„ĐžŅ€ĐŧĐģĐĩĐŊĐŊŅ– СаĐŧОвĐģĐĩĐŊĐŊŅ" }, "src_dot_shipping_dot_components_dot_ShippingZoneRateDialog_dot_1542600502": { "context": "button", - "string": "Update rate" + "string": "Đ§Đ°ŅŅ‚ĐžŅ‚Đ° ĐžĐŊОвĐģĐĩĐŊĐŊŅ" }, "src_dot_shipping_dot_components_dot_ShippingZoneRateDialog_dot_16061680": { "context": "button", @@ -4252,15 +4261,15 @@ }, "src_dot_shipping_dot_components_dot_ShippingZoneRateDialog_dot_2215090771": { "context": "shipping method, switch button", - "string": "This is free shipping" + "string": "ĐĻĐĩ ĐąĐĩСĐēĐžŅˆŅ‚ĐžĐ˛ĐŊа Đ´ĐžŅŅ‚Đ°Đ˛Đēа" }, "src_dot_shipping_dot_components_dot_ShippingZoneRateDialog_dot_2324036635": { "context": "order weight range", - "string": "Weight range" + "string": "Đ’Đ°ĐŗĐžĐ˛Đ¸Đš Đ´Ņ–Đ°ĐŋаСОĐŊ" }, "src_dot_shipping_dot_components_dot_ShippingZoneRateDialog_dot_2533614652": { "context": "order price range", - "string": "Value range" + "string": "Đ”Ņ–Đ°ĐŋаСОĐŊ СĐŊĐ°Ņ‡ĐĩĐŊҌ" }, "src_dot_shipping_dot_components_dot_ShippingZoneRateDialog_dot_2892088870": { "context": "dialog header", @@ -4313,7 +4322,7 @@ }, "src_dot_shipping_dot_components_dot_ShippingZoneRates_dot_1923873558": { "context": "shipping method price range", - "string": "Value Range" + "string": "Đ”Ņ–Đ°ĐŋаСОĐŊ СĐŊĐ°Ņ‡ĐĩĐŊҌ" }, "src_dot_shipping_dot_components_dot_ShippingZoneRates_dot_1961493435": { "string": "No shipping rates found" @@ -4324,11 +4333,11 @@ }, "src_dot_shipping_dot_components_dot_ShippingZoneRates_dot_2600677138": { "context": "shipping method weight range", - "string": "Weight Range" + "string": "Đ”Ņ–Đ°ĐŋаСОĐŊ Đ˛Đ°ĐŗĐ¸" }, "src_dot_shipping_dot_components_dot_ShippingZoneRates_dot_383202459": { "context": "weight based shipping methods, section header", - "string": "Weight Based Rates" + "string": "ĐĸĐ°Ņ€Đ¸Ņ„Đ¸ ĐŊа ĐžŅĐŊĐžĐ˛Ņ– Đ˛Đ°ĐŗĐ¸" }, "src_dot_shipping_dot_components_dot_ShippingZoneRates_dot_636461959": { "context": "shipping method name", @@ -4359,7 +4368,7 @@ }, "src_dot_shipping_dot_components_dot_ShippingZonesList_dot_2673544109": { "context": "button", - "string": "Create shipping zone" + "string": "ĐĄŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ СОĐŊ҃ Đ´ĐžŅŅ‚Đ°Đ˛Đēи" }, "src_dot_shipping_dot_components_dot_ShippingZonesList_dot_3109712047": { "string": "ĐšŅ€Đ°Ņ—ĐŊи" @@ -4372,15 +4381,15 @@ "string": "No shipping zones found" }, "src_dot_shipping_dot_views_dot_1005071028": { - "string": "Are you sure you want to delete {shippingZoneName} shipping zone?" + "string": "Ви вĐŋĐĩвĐŊĐĩĐŊŅ–, Ņ‰Đž Ņ…ĐžŅ‡ĐĩŅ‚Đĩ видаĐģĐ¸Ņ‚Đ¸ {shippingZoneName} СОĐŊ҃ Đ´ĐžŅŅ‚Đ°Đ˛Đēи?" }, "src_dot_shipping_dot_views_dot_1010705153": { "context": "dialog header", - "string": "Delete Shipping Zone" + "string": "ВидаĐģĐ¸Ņ‚Đ¸ СОĐŊ҃ Đ´ĐžŅŅ‚Đ°Đ˛Đēи" }, "src_dot_shipping_dot_views_dot_1711385401": { "context": "dialog header", - "string": "Delete Shipping Zones" + "string": "ВидаĐģĐ¸Ņ‚Đ¸ СОĐŊи Đ´ĐžŅŅ‚Đ°Đ˛Đēи" }, "src_dot_shipping_dot_views_dot_725201918": { "context": "dialog content", @@ -4388,19 +4397,19 @@ }, "src_dot_shipping_dot_views_dot_ShippingZoneDetails_dot_1010705153": { "context": "dialog header", - "string": "Delete Shipping Zone" + "string": "ВидаĐģĐ¸Ņ‚Đ¸ СОĐŊ҃ Đ´ĐžŅŅ‚Đ°Đ˛Đēи" }, "src_dot_shipping_dot_views_dot_ShippingZoneDetails_dot_131963671": { "context": "unassign country", - "string": "Are you sure you want to delete {countryName} from this shipping zone?" + "string": "Ви вĐŋĐĩвĐŊĐĩĐŊŅ–, Ņ‰Đž Ņ…ĐžŅ‡ĐĩŅ‚Đĩ видаĐģĐ¸Ņ‚Đ¸ {countryName} С ҆ҖҔҗ СОĐŊи Đ´ĐžŅŅ‚Đ°Đ˛Đēи?" }, "src_dot_shipping_dot_views_dot_ShippingZoneDetails_dot_1502359905": { "context": "dialog header", - "string": "Delete Shipping Method" + "string": "ВидаĐģĐ¸Ņ‚Đ¸ ҁĐŋĐžŅŅ–Đą Đ´ĐžŅŅ‚Đ°Đ˛Đēи" }, "src_dot_shipping_dot_views_dot_ShippingZoneDetails_dot_3133838427": { "context": "unassign country, dialog header", - "string": "Delete from Shipping Zone" + "string": "ВидаĐģĐ¸Ņ‚Đ¸ Ņ–Đˇ СОĐŊи Đ´ĐžŅŅ‚Đ°Đ˛Đēи" }, "src_dot_show": { "context": "button", @@ -4420,7 +4429,7 @@ "string": "Name of your store" }, "src_dot_siteSettings_dot_components_dot_SiteSettingsDetails_dot_3808773492": { - "string": "URL of your online store" + "string": "URL-Đ°Đ´Ņ€ĐĩŅĐ° Đ˛Đ°ŅˆĐžĐŗĐž Ņ–ĐŊŅ‚ĐĩŅ€ĐŊĐĩŅ‚-ĐŧĐ°ĐŗĐ°ĐˇĐ¸ĐŊ҃" }, "src_dot_siteSettings_dot_components_dot_SiteSettingsDetails_dot_529433178": { "string": "Store description is shown on taskbar after your store name" @@ -4438,7 +4447,7 @@ }, "src_dot_siteSettings_dot_components_dot_SiteSettingsKeyDialog_dot_3039841202": { "context": "authentication provider name", - "string": "Authentication type" + "string": "ĐĸиĐŋ Đ°ŅƒŅ‚ĐĩĐŊŅ‚Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–Ņ—" }, "src_dot_siteSettings_dot_components_dot_SiteSettingsKeyDialog_dot_50561933": { "context": "button", @@ -4450,11 +4459,11 @@ }, "src_dot_siteSettings_dot_components_dot_SiteSettingsKeys_dot_1270286507": { "context": "authentication provider name", - "string": "Authentication Type" + "string": "ĐĸиĐŋ Đ°ŅƒŅ‚ĐĩĐŊŅ‚Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–Ņ—" }, "src_dot_siteSettings_dot_components_dot_SiteSettingsKeys_dot_226491688": { "context": "section header", - "string": "Authentication Keys" + "string": "КĐģŅŽŅ‡Ņ– Đ°ŅƒŅ‚ĐĩĐŊŅ‚Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–Ņ—" }, "src_dot_siteSettings_dot_components_dot_SiteSettingsKeys_dot_2446088470": { "context": "authentication provider API key", @@ -4476,16 +4485,16 @@ "string": "Mailing Configuration" }, "src_dot_siteSettings_dot_components_dot_SiteSettingsMailing_dot_297689661": { - "string": "Configurate your email address from which all automatic emails will be sent to your customers." + "string": "НаĐģĐ°ŅˆŅ‚ŅƒĐšŅ‚Đĩ ŅĐ˛ĐžŅŽ ĐĩĐģĐĩĐēŅ‚Ņ€ĐžĐŊĐŊ҃ Đ°Đ´Ņ€Đĩҁ҃, С ŅĐēĐžŅ— Đ˛ŅŅ– Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊŅ– ĐĩĐģĐĩĐēŅ‚Ņ€ĐžĐŊĐŊŅ– ĐģĐ¸ŅŅ‚Đ¸ ĐąŅƒĐ´ŅƒŅ‚ŅŒ Đ˛Ņ–Đ´ĐŋŅ€Đ°Đ˛ĐģĐĩĐŊŅ– Đ˛Đ°ŅˆĐ¸Đŧ ĐēĐģŅ–Ņ”ĐŊŅ‚Đ°Đŧ." }, "src_dot_siteSettings_dot_components_dot_SiteSettingsMailing_dot_3211348653": { - "string": "Customer password reset URL" + "string": "URL-Đ°Đ´Ņ€ĐĩŅĐ° Đ˛Ņ–Đ´ĐŊОвĐģĐĩĐŊĐŊŅ ĐŋĐ°Ņ€ĐžĐģŅ ĐēĐģŅ–Ņ”ĐŊŅ‚Đ°" }, "src_dot_siteSettings_dot_components_dot_SiteSettingsMailing_dot_3447841451": { "string": "This URL will be used as a main URL for password resets. It will be sent via email." }, "src_dot_siteSettings_dot_components_dot_SiteSettingsMailing_dot_50742153": { - "string": "URL address" + "string": "URL-Đ°Đ´Ņ€ĐĩŅĐ°" }, "src_dot_siteSettings_dot_components_dot_SiteSettingsMailing_dot_70179174": { "string": "Mailing email sender" @@ -4494,7 +4503,7 @@ "string": "This adress will be used to generate invoices and calculate shipping rates." }, "src_dot_siteSettings_dot_components_dot_SiteSettingsPage_dot_1214877701": { - "string": "Authentication method defines additional ways that customers can log in to your ecommerce." + "string": "ĐĄĐŋĐžŅŅ–Đą Đ°ŅƒŅ‚ĐĩĐŊŅ‚Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–Ņ— виСĐŊĐ°Ņ‡Đ°Ņ” Đ´ĐžĐ´Đ°Ņ‚ĐēĐžĐ˛Ņ– ҁĐŋĐžŅĐžĐąĐ¸, Са ŅĐēиĐŧи ĐēĐģŅ–Ņ”ĐŊŅ‚Đ¸ ĐŧĐžĐļŅƒŅ‚ŅŒ ŅƒĐ˛Ņ–ĐšŅ‚Đ¸ ҃ Đ´Đž Đ˛Đ°Ņ‰ĐžŅ— ĐĩĐģĐĩĐēŅ‚Ņ€ĐžĐŊĐŊĐžŅ— ĐēĐžĐŧĐĩҀ҆Җҗ." }, "src_dot_siteSettings_dot_components_dot_SiteSettingsPage_dot_229184360": { "context": "section header", @@ -4502,7 +4511,7 @@ }, "src_dot_siteSettings_dot_components_dot_SiteSettingsPage_dot_2768400497": { "context": "section header", - "string": "Company Information" + "string": "ІĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ ĐŋŅ€Đž ĐēĐžĐŧĐŋаĐŊŅ–ŅŽ" }, "src_dot_siteSettings_dot_components_dot_SiteSettingsPage_dot_280712237": { "context": "section header", @@ -4516,7 +4525,7 @@ }, "src_dot_siteSettings_dot_components_dot_SiteSettingsPage_dot_4088830385": { "context": "section header", - "string": "Authentication Methods" + "string": "ĐĄĐŋĐžŅĐžĐąĐ¸ Đ°ŅƒŅ‚ĐĩĐŊŅ‚Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–Ņ—" }, "src_dot_siteSettings_dot_components_dot_SiteSettingsPage_dot_866304242": { "string": "This where you will find all of the settings determining your stores e-mails. You can determine main email address and some of the contents of your emails." @@ -4565,7 +4574,7 @@ }, "src_dot_staff_dot_components_dot_StaffListPage_dot_deactivated": { "context": "staff member's account", - "string": "Deactivated" + "string": "ДĐĩаĐēŅ‚Đ¸Đ˛ĐžĐ˛Đ°ĐŊĐž" }, "src_dot_staff_dot_components_dot_StaffListPage_dot_status": { "context": "staff member's account", @@ -4573,7 +4582,7 @@ }, "src_dot_staff_dot_components_dot_StaffList_dot_1004218338": { "context": "staff member status", - "string": "Inactive" + "string": "НĐĩаĐēŅ‚Đ¸Đ˛ĐŊиК" }, "src_dot_staff_dot_components_dot_StaffList_dot_1789607185": { "string": "Email Address" @@ -4605,11 +4614,11 @@ "string": "Previous Password" }, "src_dot_staff_dot_components_dot_StaffPassword_dot_1274006906": { - "string": "You should change your password every month to avoid security issues." + "string": "Ви ĐŋОвиĐŊĐŊŅ– СĐŧŅ–ĐŊŅŽĐ˛Đ°Ņ‚Đ¸ ŅĐ˛Ņ–Đš ĐŋĐ°Ņ€ĐžĐģҌ Ņ‰ĐžĐŧŅ–ŅŅŅ†Ņ, Ņ‰ĐžĐą ҃ĐŊиĐēĐŊŅƒŅ‚Đ¸ ĐŋŅ€ĐžĐąĐģĐĩĐŧ С ĐąĐĩСĐŋĐĩĐēĐžŅŽ." }, "src_dot_staff_dot_components_dot_StaffPassword_dot_1434811103": { "context": "button", - "string": "Change your password" + "string": "ЗĐŧŅ–ĐŊĐ¸Ņ‚Đ¸ ĐŋĐ°Ņ€ĐžĐģҌ" }, "src_dot_staff_dot_components_dot_StaffPassword_dot_2237029987": { "context": "header", @@ -4634,25 +4643,25 @@ }, "src_dot_staff_dot_components_dot_StaffProperties_dot_2771097267": { "context": "button", - "string": "Change photo" + "string": "ЗĐŧŅ–ĐŊĐ¸Ņ‚Đ¸ Ņ„ĐžŅ‚Đž" }, "src_dot_staff_dot_components_dot_StaffProperties_dot_457748370": { "context": "button", - "string": "Delete photo" + "string": "ВидаĐģĐ¸Ņ‚Đ¸ Ņ„ĐžŅ‚ĐžĐŗŅ€Đ°Ņ„Ņ–ŅŽ" }, "src_dot_staff_dot_views_dot_1308770978": { "context": "dialog header", - "string": "delete Staff User" + "string": "видаĐģĐ¸Ņ‚Đ¸ ĐšĐžŅ€Đ¸ŅŅ‚ŅƒĐ˛Đ°Ņ‡Đ° ĐŋĐĩŅ€ŅĐžĐŊаĐģ҃" }, "src_dot_staff_dot_views_dot_3945766678": { - "string": "Are you sure you want to remove {email} avatar?" + "string": "Ви вĐŋĐĩвĐŊĐĩĐŊŅ–, Ņ‰Đž Ņ…ĐžŅ‡ĐĩŅ‚Đĩ видаĐģĐ¸Ņ‚Đ¸ {email} Đ°Đ˛Đ°Ņ‚Đ°Ņ€?" }, "src_dot_staff_dot_views_dot_701332676": { "context": "dialog header", - "string": "Delete Staff User Avatar" + "string": "ВидаĐģĐ¸Ņ‚Đ¸ aĐ˛Đ°Ņ‚Đ°Ņ€ ĐēĐžŅ€Đ¸ŅŅ‚ŅƒĐ˛Đ°Ņ‡Đ° ĐŋĐĩŅ€ŅĐžĐŊаĐģ҃" }, "src_dot_staff_dot_views_dot_8878988": { - "string": "Are you sure you want to delete {email} from staff members?" + "string": "Ви вĐŋĐĩвĐŊĐĩĐŊŅ–, Ņ‰Đž Ņ…ĐžŅ‡ĐĩŅ‚Đĩ видаĐģĐ¸Ņ‚Đ¸ {email} ĐˇŅ– ҁĐŋŅ–Đ˛Ņ€ĐžĐąŅ–Ņ‚ĐŊиĐēŅ–Đ˛?" }, "src_dot_startDate": { "string": "Start Date" @@ -4668,11 +4677,11 @@ }, "src_dot_taxes": { "context": "taxes section name", - "string": "Taxes" + "string": "ĐŸĐžĐ´Đ°Ņ‚Đēи" }, "src_dot_taxes_dot_components_dot_CountryListPage_dot_3955023266": { "context": "header", - "string": "Taxes" + "string": "ĐŸĐžĐ´Đ°Ņ‚Đēи" }, "src_dot_taxes_dot_components_dot_CountryList_dot_110033143": { "string": "No countries found" @@ -4681,10 +4690,10 @@ "string": "Reduced Tax Rates" }, "src_dot_taxes_dot_components_dot_CountryList_dot_4039455144": { - "string": "Country Code" + "string": "Код ĐēŅ€Đ°Ņ—ĐŊи" }, "src_dot_taxes_dot_components_dot_CountryList_dot_577035076": { - "string": "Country Name" + "string": "Назва ĐēŅ€Đ°Ņ—ĐŊи" }, "src_dot_taxes_dot_components_dot_CountryTaxesPage_dot_1040021611": { "context": "tax rate", @@ -4696,7 +4705,7 @@ }, "src_dot_taxes_dot_components_dot_CountryTaxesPage_dot_1323923780": { "context": "tax rate", - "string": "Bikes" + "string": "ВĐĩĐģĐžŅĐ¸ĐŋĐĩди" }, "src_dot_taxes_dot_components_dot_CountryTaxesPage_dot_1451721797": { "context": "tax rate", @@ -4710,11 +4719,11 @@ }, "src_dot_taxes_dot_components_dot_CountryTaxesPage_dot_2185495435": { "context": "tax rate", - "string": "Admission to cultural events" + "string": "ĐŸŅ€Đ¸ĐšĐžĐŧ ĐŊа Đē҃ĐģŅŒŅ‚ŅƒŅ€ĐŊŅ– ĐˇĐ°Ņ…ĐžĐ´Đ¸" }, "src_dot_taxes_dot_components_dot_CountryTaxesPage_dot_2201910191": { "context": "tax rate", - "string": "Baby foodstuffs" + "string": "Đ”Đ¸Ņ‚ŅŅ‡Ņ– ĐŋŅ€ĐžĐ´ŅƒĐēŅ‚Đ¸ Ņ…Đ°Ņ€Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅ" }, "src_dot_taxes_dot_components_dot_CountryTaxesPage_dot_231341634": { "context": "tax rate", @@ -4726,11 +4735,11 @@ }, "src_dot_taxes_dot_components_dot_CountryTaxesPage_dot_2394675125": { "context": "tax rate", - "string": "Books" + "string": "КĐŊĐ¸ĐŗĐ¸" }, "src_dot_taxes_dot_components_dot_CountryTaxesPage_dot_2465450918": { "context": "tax rate", - "string": "Agricultural supplies" + "string": "ĐĄŅ–ĐģҌҁҌĐēĐžĐŗĐžŅĐŋĐžĐ´Đ°Ņ€ŅŅŒĐēŅ– ĐŋŅ€Đ¸ĐŊаĐģĐĩĐļĐŊĐžŅŅ‚Ņ–" }, "src_dot_taxes_dot_components_dot_CountryTaxesPage_dot_2482229874": { "context": "tax rate", @@ -4742,7 +4751,7 @@ }, "src_dot_taxes_dot_components_dot_CountryTaxesPage_dot_2557534380": { "context": "tax rate", - "string": "Admission to entertainment events" + "string": "ĐŸŅ€Đ¸ĐšĐžĐŧ ĐŊа Ņ€ĐžĐˇĐ˛Đ°ĐļаĐģҌĐŊŅ– ĐˇĐ°Ņ…ĐžĐ´Đ¸" }, "src_dot_taxes_dot_components_dot_CountryTaxesPage_dot_2584490289": { "context": "tax rate", @@ -4750,7 +4759,7 @@ }, "src_dot_taxes_dot_components_dot_CountryTaxesPage_dot_2616794607": { "context": "tax rate", - "string": "Admission to sporting events" + "string": "ĐŸŅ€Đ¸ĐšĐžĐŧ ĐŊа ҁĐŋĐžŅ€Ņ‚Đ¸Đ˛ĐŊŅ– ĐˇĐ°Ņ…ĐžĐ´Đ¸" }, "src_dot_taxes_dot_components_dot_CountryTaxesPage_dot_2737618795": { "context": "header", @@ -4777,11 +4786,11 @@ }, "src_dot_taxes_dot_components_dot_CountryTaxesPage_dot_3525010870": { "context": "tax rate", - "string": "Water" + "string": "Вода" }, "src_dot_taxes_dot_components_dot_CountryTaxesPage_dot_3911019760": { "context": "tax rate", - "string": "Advertising" + "string": "Đ ĐĩĐēĐģаĐŧа" }, "src_dot_taxes_dot_components_dot_CountryTaxesPage_dot_4199760668": { "context": "tax rate", @@ -4789,7 +4798,7 @@ }, "src_dot_taxes_dot_components_dot_CountryTaxesPage_dot_752780599": { "context": "tax rate", - "string": "Wine" + "string": "ВиĐŊĐž" }, "src_dot_taxes_dot_components_dot_CountryTaxesPage_dot_776474251": { "context": "tax rate", @@ -4800,13 +4809,13 @@ "string": "Pharmaceuticals" }, "src_dot_taxes_dot_components_dot_TaxConfiguration_dot_142803418": { - "string": "All products prices are entered with tax included" + "string": "Đ’ŅŅ– ҆ҖĐŊи ĐŊа Ņ‚ĐžĐ˛Đ°Ņ€Đ¸ Đ˛Đ˛ĐžĐ´ŅŅ‚ŅŒŅŅ С ŅƒŅ€Đ°Ņ…ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ ĐŋĐžĐ´Đ°Ņ‚Đē҃" }, "src_dot_taxes_dot_components_dot_TaxConfiguration_dot_2102582640": { "string": "ПоĐēĐ°ĐˇŅƒĐ˛Đ°Ņ‚Đ¸ ваĐģĐžĐ˛Ņ– ҆ҖĐŊи ĐēĐģŅ–Ņ”ĐŊŅ‚Đ°Đŧ ҃ ĐŧĐ°ĐŗĐ°ĐˇĐ¸ĐŊŅ–" }, "src_dot_taxes_dot_components_dot_TaxConfiguration_dot_2654711891": { - "string": "Charge taxes on shipping rates" + "string": "ĐĄŅ‚ŅĐŗĐŊĐĩĐŊĐŊŅ ĐŋĐžĐ´Đ°Ņ‚ĐēŅ–Đ˛ ĐŊа Ņ‚Đ°Ņ€Đ¸Ņ„Đ¸ ĐŊа Đ´ĐžŅŅ‚Đ°Đ˛Đē҃" }, "src_dot_taxes_dot_components_dot_TaxConfiguration_dot_3375540052": { "context": "button", @@ -4817,16 +4826,16 @@ }, "src_dot_translations": { "context": "translations section name", - "string": "Translations" + "string": "ПĐĩŅ€ĐĩĐēĐģади" }, "src_dot_translations_dot_components_dot_TranslationFields_dot_1308081812": { - "string": "{numberOfFields} Translations, {numberOfTranslatedFields} Completed" + "string": "{numberOfFields} ПĐĩŅ€ĐĩĐēĐģĐ°Đ´Ņ–Đ˛, {numberOfTranslatedFields} ЗавĐĩŅ€ŅˆĐĩĐŊĐž" }, "src_dot_translations_dot_components_dot_TranslationFields_dot_1348655672": { "string": "Original String" }, "src_dot_translations_dot_components_dot_TranslationFields_dot_2481190613": { - "string": "Translation" + "string": "ПĐĩŅ€ĐĩĐēĐģад" }, "src_dot_translations_dot_components_dot_TranslationFields_dot_363646127": { "context": "button", @@ -4836,13 +4845,13 @@ "string": "No translation yet" }, "src_dot_translations_dot_components_dot_TranslationsCategoriesPage_dot_1214235329": { - "string": "Category Name" + "string": "Назва ĐēĐ°Ņ‚ĐĩĐŗĐžŅ€Ņ–Ņ—" }, "src_dot_translations_dot_components_dot_TranslationsCategoriesPage_dot_1406947243": { "string": "Search Engine Description" }, "src_dot_translations_dot_components_dot_TranslationsCategoriesPage_dot_1611537010": { - "string": "Translation Category \"{categoryName}\" - {languageCode}" + "string": "ПĐĩŅ€ĐĩĐēĐģад ĐēĐ°Ņ‚ĐĩĐŗĐžŅ€Ņ–Ņ— \"{categoryName}\" - {languageCode}" }, "src_dot_translations_dot_components_dot_TranslationsCategoriesPage_dot_2496919463": { "string": "Search Engine Title" @@ -4857,11 +4866,11 @@ "string": "Search Engine Title" }, "src_dot_translations_dot_components_dot_TranslationsCollectionsPage_dot_2759199473": { - "string": "Collection Name" + "string": "Назва ĐēĐžĐģĐĩĐē҆Җҗ" }, "src_dot_translations_dot_components_dot_TranslationsCollectionsPage_dot_3055443821": { "context": "header", - "string": "Translation Collection \"{collectionName}\" - {languageCode}" + "string": "ПĐĩŅ€ĐĩĐēĐģад ĐēĐžĐģĐĩĐē҆Җҗ \"{collectionName}\" - {languageCode}" }, "src_dot_translations_dot_components_dot_TranslationsCollectionsPage_dot_3468022343": { "string": "Search Engine Preview" @@ -4883,7 +4892,7 @@ }, "src_dot_translations_dot_components_dot_TranslationsEntitiesListPage_dot_2460580333": { "context": "header", - "string": "Translations to {language}" + "string": "ПĐĩŅ€ĐĩĐēĐģади ĐŊа {language}" }, "src_dot_translations_dot_components_dot_TranslationsEntitiesListPage_dot_2559018090": { "string": "Search Page" @@ -4917,13 +4926,13 @@ }, "src_dot_translations_dot_components_dot_TranslationsEntitiesList_dot_1136143456": { "context": "translation progress", - "string": "{current} of {max}" + "string": "{current} Đ´Đž {max}" }, "src_dot_translations_dot_components_dot_TranslationsEntitiesList_dot_4176487406": { "string": "No translatable entities found" }, "src_dot_translations_dot_components_dot_TranslationsEntitiesList_dot_49462429": { - "string": "Completed Translations" + "string": "ЗавĐĩŅ€ŅˆĐĩĐŊŅ– ĐŋĐĩŅ€ĐĩĐēĐģади" }, "src_dot_translations_dot_components_dot_TranslationsEntitiesList_dot_636461959": { "context": "entity (product, collection, shipping method) name", @@ -4950,7 +4959,7 @@ }, "src_dot_translations_dot_components_dot_TranslationsPagesPage_dot_2806429775": { "context": "header", - "string": "Translation Page \"{pageName}\" - {languageCode}" + "string": "ПĐĩŅ€ĐĩĐēĐģад ŅŅ‚ĐžŅ€Ņ–ĐŊĐēи \"{pageName}\" - {languageCode}" }, "src_dot_translations_dot_components_dot_TranslationsPagesPage_dot_3468022343": { "string": "Search Engine Preview" @@ -4960,22 +4969,22 @@ }, "src_dot_translations_dot_components_dot_TranslationsProductTypesPage_dot_1281101905": { "context": "header", - "string": "Translation Product Type \"{productTypeName}\" - {languageCode}" + "string": "ПĐĩŅ€ĐĩĐēĐģад Ņ‚Đ¸Đŋ҃ Ņ‚ĐžĐ˛Đ°Ņ€Ņƒ \"{productTypeName}\" - {languageCode}" }, "src_dot_translations_dot_components_dot_TranslationsProductTypesPage_dot_1567737068": { "context": "attribute values", - "string": "Value {number}" + "string": "ЗĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ {number}" }, "src_dot_translations_dot_components_dot_TranslationsProductTypesPage_dot_2510190956": { "context": "header", "string": "Product Attribute ({attributeName})" }, "src_dot_translations_dot_components_dot_TranslationsProductTypesPage_dot_2642976392": { - "string": "Attribute Name" + "string": "Назва Đ°Ņ‚Ņ€Đ¸ĐąŅƒŅ‚Ņƒ" }, "src_dot_translations_dot_components_dot_TranslationsProductTypesPage_dot_3538502409": { "context": "header", - "string": "Variant Attribute ({attributeName})" + "string": "Đ’Đ°Ņ€Ņ–Đ°ĐŊŅ‚ Đ°Ņ‚Ņ€Đ¸ĐąŅƒŅ‚Ņ–Đ˛ ({attributeName})" }, "src_dot_translations_dot_components_dot_TranslationsProductsPage_dot_1406947243": { "string": "Search Engine Description" @@ -4988,7 +4997,7 @@ }, "src_dot_translations_dot_components_dot_TranslationsProductsPage_dot_2713974050": { "context": "header", - "string": "Translation Product \"{productName}\" - {languageCode}" + "string": "ПĐĩŅ€ĐĩĐēĐģад Ņ‚ĐžĐ˛Đ°Ņ€Ņƒ \"{productName}\" - {languageCode}" }, "src_dot_translations_dot_components_dot_TranslationsProductsPage_dot_3374163063": { "string": "ОĐŋĐ¸Ņ" @@ -4998,33 +5007,33 @@ }, "src_dot_translations_dot_components_dot_TranslationsSalesPage_dot_3731955064": { "context": "header", - "string": "Translation Sale \"{saleName}\" - {languageCode}" + "string": "ПĐĩŅ€ĐĩĐēĐģад Ņ€ĐžĐˇĐŋŅ€ĐžĐ´Đ°Đļ҃ \"{saleName}\" - {languageCode}" }, "src_dot_translations_dot_components_dot_TranslationsSalesPage_dot_898281424": { "string": "Sale Name" }, "src_dot_translations_dot_components_dot_TranslationsVouchersPage_dot_2447510181": { "context": "header", - "string": "Translation Voucher \"{voucherName}\" - {languageCode}" + "string": "ПĐĩŅ€ĐĩĐēĐģад Đē҃ĐŋĐžĐŊ҃ \"{voucherName}\" - {languageCode}" }, "src_dot_translations_dot_components_dot_TranslationsVouchersPage_dot_2599922713": { - "string": "Voucher Name" + "string": "Назва" }, "src_dot_undo": { "context": "button", - "string": "Undo" + "string": "ĐĄĐēĐ°ŅŅƒĐ˛Đ°Ņ‚Đ¸" }, "src_dot_unfulfilled": { "context": "order status", - "string": "Unfulfilled" + "string": "НĐĩвиĐēĐžĐŊаĐŊĐž" }, "src_dot_unpaid": { "context": "payment status", - "string": "Unpaid" + "string": "НĐĩĐžĐŋĐģĐ°Ņ‡ĐĩĐŊиК" }, "src_dot_uploadImage": { "context": "button", - "string": "Upload image" + "string": "ЗаваĐŊŅ‚Đ°ĐļĐ¸Ņ‚Đ¸ ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊĐŊŅ" }, "src_dot_utils_dot_errors_dot_alreadyExists": { "context": "add authorization key error", @@ -5060,54 +5069,54 @@ }, "src_dot_utils_dot_errors_dot_cannotRefund": { "context": "error message", - "string": "Manual payments can not be refunded" + "string": "ОĐŋĐģĐ°Ņ‚Đ° в Ņ€ŅƒŅ‡ĐŊĐžĐŧ҃ Ņ€ĐĩĐļиĐŧŅ– ĐŊĐĩ ĐŧĐžĐļĐĩ ĐąŅƒŅ‚Đ¸ ĐŋОвĐĩŅ€ĐŊĐĩĐŊа" }, "src_dot_utils_dot_errors_dot_cannotRemoveFromLastGroup": { - "string": "Cannot remove user from last group" + "string": "НĐĩĐŧĐžĐļĐģивО видаĐģĐ¸Ņ‚Đ¸ ĐēĐžŅ€Đ¸ŅŅ‚ŅƒĐ˛Đ°Ņ‡Đ° С ĐžŅŅ‚Đ°ĐŊĐŊŅŒĐžŅ— ĐŗŅ€ŅƒĐŋи" }, "src_dot_utils_dot_errors_dot_cannotVoid": { "context": "error message", - "string": "Only pre-authorized payments can be voided" + "string": "ĐĸŅ–ĐģҌĐēи ĐŋĐžĐŋĐĩŅ€ĐĩĐ´ĐŊŅŒĐž Đ°Đ˛Ņ‚ĐžŅ€Đ¸ĐˇĐžĐ˛Đ°ĐŊŅ– ĐŋĐģĐ°Ņ‚ĐĩĐļŅ– ĐŧĐžĐļŅƒŅ‚ŅŒ ĐąŅƒŅ‚Đ¸ аĐŊ҃ĐģŅŒĐžĐ˛Đ°ĐŊŅ–" }, "src_dot_utils_dot_errors_dot_captureInactive": { "context": "error message", "string": "Đ›Đ¸ŅˆĐĩ ĐŋĐžĐŋĐĩŅ€ĐĩĐ´ĐŊŅŒĐž Đ°Đ˛Ņ‚ĐžŅ€Đ¸ĐˇĐžĐ˛Đ°ĐŊŅ– ĐžĐŋĐģĐ°Ņ‚Đ¸ ĐŧĐžĐļŅƒŅ‚ŅŒ ĐąŅƒŅ‚Đ¸ ĐŋŅ€Đ¸ĐšĐŊŅŅ‚Ņ–" }, "src_dot_utils_dot_errors_dot_duplicatedInputItem": { - "string": "Cannot add and remove group the same time" + "string": "НĐĩĐŧĐžĐļĐģивО Đ´ĐžĐ´Đ°Ņ‚Đ¸ Ņ‚Đ° видаĐģĐ¸Ņ‚Đ¸ ĐŗŅ€ŅƒĐŋ҃ ОдĐŊĐžŅ‡Đ°ŅĐŊĐž" }, "src_dot_utils_dot_errors_dot_graphqlError": { - "string": "API error" + "string": "ПоĐŧиĐģĐēа API" }, "src_dot_utils_dot_errors_dot_invalid": { - "string": "Invalid value" + "string": "НĐĩĐŋŅ€Đ¸ĐŋŅƒŅŅ‚Đ¸ĐŧĐĩ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ" }, "src_dot_utils_dot_errors_dot_invalidPassword": { - "string": "Invalid password" + "string": "НĐĩĐŋŅ€Đ°Đ˛Đ¸ĐģҌĐŊиК ĐŋĐ°Ņ€ĐžĐģҌ" }, "src_dot_utils_dot_errors_dot_noShippingAddress": { "context": "error message", - "string": "Cannot choose a shipping method for an order without the shipping address" + "string": "НĐĩĐŧĐžĐļĐģивО Đ˛Đ¸ĐąŅ€Đ°Ņ‚Đ¸ ҁĐŋĐžŅŅ–Đą Đ´ĐžŅŅ‚Đ°Đ˛Đēи Đ´ĐģŅ СаĐŧОвĐģĐĩĐŊĐŊŅ ĐąĐĩС Đ°Đ´Ņ€ĐĩŅĐ¸ Đ´ĐžŅŅ‚Đ°Đ˛Đēи" }, "src_dot_utils_dot_errors_dot_notEditable": { "context": "error message", - "string": "Only draft orders can be edited" + "string": "Đ ĐĩĐ´Đ°ĐŗŅƒĐ˛Đ°Ņ‚Đ¸ ĐŧĐžĐļŅƒŅ‚ŅŒ ĐģĐ¸ŅˆĐĩ ҇ĐĩŅ€ĐŊĐĩŅ‚Đēи СаĐŧОвĐģĐĩĐŊҌ" }, "src_dot_utils_dot_errors_dot_outOfScopeGroup": { - "string": "Group is out of your permission scope" + "string": "Đ“Ņ€ŅƒĐŋа Đ˛Đ¸Ņ…ĐžĐ´Đ¸Ņ‚ŅŒ Са ĐŧĐĩĐļŅ– Đ˛Đ°ŅˆĐžĐŗĐž дОСвОĐģ҃" }, "src_dot_utils_dot_errors_dot_outOfScopeUser": { - "string": "User is out of your permissions scope" + "string": "ĐšĐžŅ€Đ¸ŅŅ‚ŅƒĐ˛Đ°Ņ‡ Đ˛Đ¸Ņ…ĐžĐ´Đ¸Ņ‚ŅŒ Са ĐŧĐĩĐļŅ– Đ˛Đ°ŅˆĐžĐŗĐž дОСвОĐģ҃" }, "src_dot_utils_dot_errors_dot_passwordNumeric": { - "string": "Password cannot be entirely numeric" + "string": "ĐŸĐ°Ņ€ĐžĐģҌ ĐŊĐĩ ĐŧĐžĐļĐĩ ĐąŅƒŅ‚Đ¸ ĐŋОвĐŊŅ–ŅŅ‚ŅŽ С Ņ†Đ¸Ņ„Ņ€" }, "src_dot_utils_dot_errors_dot_paymentMissing": { "context": "error message", - "string": "There's no payment associated with the order" + "string": "НĐĩĐŧĐ°Ņ” ĐžĐŋĐģĐ°Ņ‚Đ¸, ĐŋОв'ŅĐˇĐ°ĐŊĐžŅ— Ņ–Đˇ СаĐŧОвĐģĐĩĐŊĐŊŅĐŧ" }, "src_dot_utils_dot_errors_dot_permissionOutOfScope": { - "string": "Those permissions are out of your scope" + "string": "ĐĻŅ– дОСвОĐģи ĐŊĐĩ Đ˛Ņ…ĐžĐ´ŅŅ‚ŅŒ ҃ Đ˛Đ°Ņˆ ĐžĐąŅŅĐŗ" }, "src_dot_utils_dot_errors_dot_shippingNotApplicable": { "context": "error message", @@ -5115,33 +5124,33 @@ }, "src_dot_utils_dot_errors_dot_shippingRequired": { "context": "error message", - "string": "Shipping method is required for this order" + "string": "ДĐģŅ Ņ†ŅŒĐžĐŗĐž СаĐŧОвĐģĐĩĐŊĐŊŅ ĐŊĐĩĐžĐąŅ…Ņ–Đ´ĐŊиК ҁĐŋĐžŅŅ–Đą Đ´ĐžŅŅ‚Đ°Đ˛Đēи" }, "src_dot_utils_dot_errors_dot_skuUnique": { "context": "bulk variant create error", - "string": "SKUs must be unique" + "string": "Код Ņ‚ĐžĐ˛Đ°Ņ€Ņƒ ĐŋОвиĐŊĐĩĐŊ ĐąŅƒŅ‚Đ¸ ҃ĐŊŅ–ĐēаĐģҌĐŊиĐŧ" }, "src_dot_utils_dot_errors_dot_slugUnique": { "context": "error message", - "string": "Slug must be unique for each warehouse" + "string": "ĐĄĐģ҃ĐļйОвĐĩ ĐŋĐžĐģĐĩ ĐŋОвиĐŊĐŊĐž ĐąŅƒŅ‚Đ¸ ҃ĐŊŅ–ĐēаĐģҌĐŊиĐŧ Đ´ĐģŅ ĐēĐžĐļĐŊĐžĐŗĐž ҁĐēĐģĐ°Đ´Ņƒ" }, "src_dot_utils_dot_errors_dot_tooCommon": { - "string": "This password is too commonly used" + "string": "ĐĻĐĩĐš ĐŋĐ°Ņ€ĐžĐģҌ СаĐŊĐ°Đ´Ņ‚Đž Ņ‡Đ°ŅŅ‚Đž виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚ŅŒŅŅ" }, "src_dot_utils_dot_errors_dot_tooShort": { - "string": "This password is too short" + "string": "ĐĻĐĩĐš ĐŋĐ°Ņ€ĐžĐģҌ СаĐŊĐ°Đ´Ņ‚Đž ĐēĐžŅ€ĐžŅ‚ĐēиК" }, "src_dot_utils_dot_errors_dot_tooSimilar": { - "string": "These passwords are too similar" + "string": "ĐĻŅ– ĐŋĐ°Ņ€ĐžĐģŅ– СаĐŊĐ°Đ´Ņ‚Đž ŅŅ…ĐžĐļŅ–" }, "src_dot_utils_dot_errors_dot_unique": { - "string": "This needs to be unique" + "string": "ĐĻĐĩ ĐŋОвиĐŊĐŊĐž ĐąŅƒŅ‚Đ¸ ҃ĐŊŅ–ĐēаĐģҌĐŊиĐŧ" }, "src_dot_utils_dot_errors_dot_unknownError": { - "string": "Unknown error" + "string": "НĐĩĐ˛Ņ–Đ´ĐžĐŧа ĐŋĐžĐŧиĐģĐēа" }, "src_dot_utils_dot_errors_dot_variantNoDigitalContent": { - "string": "This variant does not have any digital content" + "string": "ĐĻĐĩĐš Đ˛Đ°Ņ€Ņ–Đ°ĐŊŅ‚ ĐŊĐĩ ĐŧĐ°Ņ” ĐļОдĐŊĐžĐŗĐž вĐŧŅ–ŅŅ‚Ņƒ" }, "src_dot_vouchers": { "context": "vouchers section name", @@ -5149,7 +5158,7 @@ }, "src_dot_warehouses": { "context": "warehouses section name", - "string": "Warehouses" + "string": "ĐĄĐēĐģади" }, "src_dot_warehouses_dot_components_dot_WarehouseCreatePage_dot_1967111456": { "context": "warehouse", @@ -5157,39 +5166,39 @@ }, "src_dot_warehouses_dot_components_dot_WarehouseCreatePage_dot_934572530": { "context": "header", - "string": "Create Warehouse" + "string": "ĐĄŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ ҁĐēĐģад" }, "src_dot_warehouses_dot_components_dot_WarehouseDeleteDialog_dot_1355303260": { "context": "dialog content", - "string": "Are you sure you want to delete {warehouseName}?" + "string": "Ви вĐŋĐĩвĐŊĐĩĐŊŅ–, Ņ‰Đž Ņ…ĐžŅ‡ĐĩŅ‚Đĩ видаĐģĐ¸Ņ‚Đ¸ {warehouseName}?" }, "src_dot_warehouses_dot_components_dot_WarehouseDeleteDialog_dot_3857661071": { "context": "dialog title", - "string": "Delete Warehouse" + "string": "ВидаĐģĐ¸Ņ‚Đ¸ ҁĐēĐģад" }, "src_dot_warehouses_dot_components_dot_WarehouseDetailsPage_dot_1967111456": { "context": "warehouse", "string": "ІĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ ĐŋŅ€Đž Đ°Đ´Ņ€Đĩҁ҃" }, "src_dot_warehouses_dot_components_dot_WarehouseInfo_dot_2622674857": { - "string": "Warehouse Name" + "string": "Назва ҁĐēĐģĐ°Đ´Ņƒ" }, "src_dot_warehouses_dot_components_dot_WarehouseListPage_dot_2304765290": { - "string": "Search Warehouse" + "string": "ĐŸĐžŅˆŅƒĐē ҁĐēĐģĐ°Đ´Ņƒ" }, "src_dot_warehouses_dot_components_dot_WarehouseListPage_dot_3203451491": { "context": "tab name", - "string": "All Warehouses" + "string": "Đ’ŅŅ– ҁĐēĐģади" }, "src_dot_warehouses_dot_components_dot_WarehouseListPage_dot_934572530": { "context": "button", - "string": "Create Warehouse" + "string": "ĐĄŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ ҁĐēĐģад" }, "src_dot_warehouses_dot_components_dot_WarehouseList_dot_1225932315": { - "string": "Shipping Zones" + "string": "ЗоĐŊи Đ´ĐžŅŅ‚Đ°Đ˛Đēи" }, "src_dot_warehouses_dot_components_dot_WarehouseList_dot_3787396469": { - "string": "No warehouses found" + "string": "ĐĄĐēĐģĐ°Đ´Ņ–Đ˛ ĐŊĐĩ СĐŊаКдĐĩĐŊĐž" }, "src_dot_warehouses_dot_components_dot_WarehouseList_dot_4190792473": { "string": "Đ”Ņ–Ņ—" @@ -5200,26 +5209,26 @@ }, "src_dot_warehouses_dot_components_dot_WarehouseZones_dot_1225932315": { "context": "zones that warehouse sends to", - "string": "Shipping Zones" + "string": "ЗоĐŊи Đ´ĐžŅŅ‚Đ°Đ˛Đēи" }, "src_dot_warehouses_dot_components_dot_WarehouseZones_dot_2423245141": { - "string": "This warehouse has no shipping zones assigned." + "string": "На Ņ†ŅŒĐžĐŧ҃ ҁĐēĐģĐ°Đ´Ņ– ĐŊĐĩ ĐŋŅ€Đ¸ĐˇĐŊĐ°Ņ‡ĐĩĐŊŅ– СОĐŊи Đ´ĐžŅŅ‚Đ°Đ˛Đēи." }, "src_dot_warehouses_dot_views_dot_WarehouseCreate_dot_934572530": { "context": "header", - "string": "Create Warehouse" + "string": "ĐĄŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ ҁĐēĐģад" }, "src_dot_webhooks": { "context": "webhooks section name", - "string": "Webhooks" + "string": "ĐĄĐ¸ŅŅ‚ĐĩĐŧа ҁĐŋĐžĐ˛Ņ–Ņ‰ĐĩĐŊĐŊŅ ĐŋĐžĐ´Ņ–Đš" }, "src_dot_webhooks_dot_components_dot_WebhookCreatePage_dot_3493926696": { "context": "header", - "string": "Create Webhook" + "string": "ĐĄŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ вĐĩĐąŅ…ŅƒĐē" }, "src_dot_webhooks_dot_components_dot_WebhookDeleteDialog_dot_216945727": { "context": "delete webhook", - "string": "Are you sure you want to delete this webhook?" + "string": "Ви вĐŋĐĩвĐŊĐĩĐŊŅ–, Ņ‰Đž Ņ…ĐžŅ‡ĐĩŅ‚Đĩ видаĐģĐ¸Ņ‚Đ¸ Ņ†ŅŽĐš вĐĩĐąŅ…ŅƒĐē?" }, "src_dot_webhooks_dot_components_dot_WebhookDeleteDialog_dot_2297471173": { "context": "delete webhook", @@ -5227,27 +5236,27 @@ }, "src_dot_webhooks_dot_components_dot_WebhookDeleteDialog_dot_3514087611": { "context": "dialog header", - "string": "Delete Webhook" + "string": "ВидаĐģĐ¸Ņ‚Đ¸ вĐĩĐąŅ…ŅƒĐē" }, "src_dot_webhooks_dot_components_dot_WebhookEvents_dot_1436364351": { "context": "section header", - "string": "Events" + "string": "ĐŸĐžĐ´Ņ–Ņ—" }, "src_dot_webhooks_dot_components_dot_WebhookEvents_dot_1606361075": { "context": "event", - "string": "Order updated" + "string": "ЗаĐŧОвĐģĐĩĐŊĐŊŅ ĐžĐŊОвĐģĐĩĐŊĐž" }, "src_dot_webhooks_dot_components_dot_WebhookEvents_dot_2454751033": { "context": "event", - "string": "All events" + "string": "Đ’ŅŅ– ĐŋĐžĐ´Ņ–Ņ—" }, "src_dot_webhooks_dot_components_dot_WebhookEvents_dot_2899821092": { "context": "event", - "string": "Product created" + "string": "ĐĸĐžĐ˛Đ°Ņ€ ŅŅ‚Đ˛ĐžŅ€ĐĩĐŊĐž" }, "src_dot_webhooks_dot_components_dot_WebhookEvents_dot_3051538277": { "context": "webhook events", - "string": "Expand or restrict webhooks permissions to register certain events in Saleor system." + "string": "Đ ĐžĐˇŅˆĐ¸Ņ€ŅŽĐšŅ‚Đĩ айО ОйĐŧĐĩĐļŅƒĐšŅ‚Đĩ дОСвОĐģи вĐĩĐąŅ…ŅƒĐēŅ–Đ˛ Đ´ĐģŅ Ņ€ĐĩŅ”ŅŅ‚Ņ€Đ°Ņ†Ņ–Ņ— ĐŋĐžĐ´Ņ–Đš ҃ ŅĐ¸ŅŅ‚ĐĩĐŧŅ– Saleor." }, "src_dot_webhooks_dot_components_dot_WebhookEvents_dot_3345061702": { "context": "event", @@ -5255,89 +5264,89 @@ }, "src_dot_webhooks_dot_components_dot_WebhookEvents_dot_3400883706": { "context": "event", - "string": "Order created" + "string": "ЗаĐŧОвĐģĐĩĐŊĐŊŅ ŅŅ‚Đ˛ĐžŅ€ĐĩĐŊĐž" }, "src_dot_webhooks_dot_components_dot_WebhookEvents_dot_3617444329": { "context": "event", - "string": "Order cancelled" + "string": "ЗаĐŧОвĐģĐĩĐŊĐŊŅ ҁĐēĐ°ŅĐžĐ˛Đ°ĐŊĐž" }, "src_dot_webhooks_dot_components_dot_WebhookEvents_dot_3907151399": { "context": "event", - "string": "Order fulfilled" + "string": "ЗаĐŧОвĐģĐĩĐŊĐŊŅ виĐēĐžĐŊаĐŊĐž" }, "src_dot_webhooks_dot_components_dot_WebhookEvents_dot_3970234993": { "context": "event", - "string": "Customer created" + "string": "КĐģŅ–Ņ”ĐŊŅ‚ ŅŅ‚Đ˛ĐžŅ€ĐĩĐŊиК" }, "src_dot_webhooks_dot_components_dot_WebhookEvents_dot_40035964": { "context": "event", - "string": "Changed quantity in checkout" + "string": "ЗĐŧŅ–ĐŊĐĩĐŊĐž ĐēŅ–ĐģҌĐēŅ–ŅŅ‚ŅŒ в СаĐŧОвĐģĐĩĐŊĐŊŅ–" }, "src_dot_webhooks_dot_components_dot_WebhookEvents_dot_4281441551": { "context": "event", - "string": "Fulfillment created" + "string": "ВиĐēĐžĐŊаĐŊĐŊŅ ŅŅ‚Đ˛ĐžŅ€ĐĩĐŊĐž" }, "src_dot_webhooks_dot_components_dot_WebhookInfo_dot_1690209105": { "context": "webhook", - "string": "Target URL" + "string": "ĐĻŅ–ĐģҌ URL-Đ°Đ´Ņ€ĐĩŅĐ¸" }, "src_dot_webhooks_dot_components_dot_WebhookInfo_dot_1826224431": { "context": "webhook", - "string": "Webhook Name" + "string": "Назва" }, "src_dot_webhooks_dot_components_dot_WebhookInfo_dot_330298209": { "context": "section header", - "string": "Webhook Information" + "string": "ІĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ" }, "src_dot_webhooks_dot_components_dot_WebhookInfo_dot_3763861707": { "context": "webhook target url help text", - "string": "This URL will receive webhook POST requests" + "string": "ĐĻŅ URL-Đ°Đ´Ņ€ĐĩŅĐ° ĐžŅ‚Ņ€Đ¸ĐŧŅƒĐ˛Đ°Ņ‚Đ¸ĐŧĐĩ вĐĩĐąŅ…ŅƒĐē POST СаĐŋĐ¸Ņ‚Đ¸" }, "src_dot_webhooks_dot_components_dot_WebhookInfo_dot_3809115222": { "context": "webhook secret key help text", - "string": "secret key is used to create a hash signature with each payload. *optional field" + "string": "ҁĐĩĐēŅ€ĐĩŅ‚ĐŊиК ĐēĐģŅŽŅ‡ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚ŅŒŅŅ Đ´ĐģŅ ŅŅ‚Đ˛ĐžŅ€ĐĩĐŊĐŊŅ Ņ…Đĩ҈-ĐŋŅ–Đ´ĐŋĐ¸ŅŅƒ С ĐēĐžĐļĐŊиĐŧ ĐēĐžŅ€Đ¸ŅĐŊиĐŧ ĐŊаваĐŊŅ‚Đ°ĐļĐĩĐŊĐŊŅĐŧ. *ĐŊĐĩĐžĐąĐžĐ˛â€™ŅĐˇĐēОвĐĩ ĐŋĐžĐģĐĩ" }, "src_dot_webhooks_dot_components_dot_WebhookInfo_dot_3995417850": { "context": "webhook", - "string": "Secrect Key" + "string": "ĐĄĐĩĐēŅ€ĐĩŅ‚ĐŊиК ĐēĐģŅŽŅ‡" }, "src_dot_webhooks_dot_components_dot_WebhookInfo_dot_4194304040": { "context": "webhook specific information", - "string": "Webhook specific information" + "string": "ĐĄĐŋĐĩŅ†Ņ–Đ°ĐģҌĐŊĐž Ņ–ĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ ŅĐ¸ŅŅ‚ĐĩĐŧи ҁĐŋĐžĐ˛Ņ–Ņ‰ĐĩĐŊĐŊŅ ĐŋĐžĐ´Ņ–Đš" }, "src_dot_webhooks_dot_components_dot_WebhookInfo_dot_819389696": { - "string": "Assign to Service Account" + "string": "ĐŸŅ€Đ¸ĐˇĐŊĐ°Ņ‡Đ¸Ņ‚Đ¸ ҁĐģ҃ĐļйОвиК ОйĐģŅ–ĐēОвиК СаĐŋĐ¸Ņ" }, "src_dot_webhooks_dot_components_dot_WebhookStatus_dot_2772025990": { "context": "webhooks active", - "string": "Webhook is active" + "string": "ĐĄĐ¸ŅŅ‚ĐĩĐŧа ҁĐŋĐžĐ˛Ņ–Ņ‰ĐĩĐŊĐŊŅ ĐŋĐžĐ´Ņ–Đš аĐēŅ‚Đ¸Đ˛ĐŊа" }, "src_dot_webhooks_dot_components_dot_WebhookStatus_dot_313090629": { "context": "webhook active", - "string": "If you want to disable this webhook please uncheck the box below." + "string": "Đ¯ĐēŅ‰Đž ви Ņ…ĐžŅ‡ĐĩŅ‚Đĩ Đ˛Ņ–Đ´ĐēĐģŅŽŅ‡Đ¸Ņ‚Đ¸ ҆ĐĩĐš вĐĩĐąŅ…ŅƒĐē, СĐŊŅ–ĐŧŅ–Ņ‚ŅŒ ĐŋŅ€Đ°ĐŋĐžŅ€ĐĩŅ†ŅŒ ĐŊиĐļ҇Đĩ." }, "src_dot_webhooks_dot_components_dot_WebhookStatus_dot_596557805": { "context": "section header", - "string": "Webhook Status" + "string": "ĐĄŅ‚Đ°Ņ‚ŅƒŅ ŅĐ¸ŅŅ‚ĐĩĐŧи ҁĐŋĐžĐ˛Ņ–Ņ‰ĐĩĐŊĐŊŅ ĐŋĐžĐ´Ņ–Đš" }, "src_dot_webhooks_dot_components_dot_WebhooksDetailsPage_dot_1595053355": { "context": "header", - "string": "Unnamed Webhook Details" + "string": "ДĐĩŅ‚Đ°ĐģŅ– вĐĩĐąŅ…ŅƒĐē҃ ĐąĐĩС ĐŊаСви" }, "src_dot_webhooks_dot_components_dot_WebhooksDetailsPage_dot_408706360": { "context": "header", - "string": "{webhookName} Details" + "string": "ДĐĩŅ‚Đ°ĐģŅ– {webhookName}" }, "src_dot_webhooks_dot_components_dot_WebhooksListPage_dot_1432828311": { - "string": "Search Webhooks" + "string": "ĐŸĐžŅˆŅƒĐē вĐĩĐąŅ…ŅƒĐē҃" }, "src_dot_webhooks_dot_components_dot_WebhooksListPage_dot_2295583901": { "context": "button", - "string": "Create webhook" + "string": "ĐĄŅ‚Đ˛ĐžŅ€Ņ–Ņ‚ŅŒ вĐĩĐąŅ…ŅƒĐē" }, "src_dot_webhooks_dot_components_dot_WebhooksListPage_dot_3300314452": { "context": "tab name", - "string": "All Webhooks" + "string": "Đ’ŅŅ– вĐĩĐąŅ…ŅƒĐēи" }, "src_dot_webhooks_dot_components_dot_WebhooksListPage_dot_active": { "context": "webhook", @@ -5345,21 +5354,21 @@ }, "src_dot_webhooks_dot_components_dot_WebhooksListPage_dot_inactive": { "context": "webhook", - "string": "Inactive" + "string": "НĐĩаĐēŅ‚Đ¸Đ˛ĐŊиК" }, "src_dot_webhooks_dot_components_dot_WebhooksList_dot_1153324159": { - "string": "No webhooks found" + "string": "ВĐĩĐąŅ…ŅƒĐē ĐŊĐĩ СĐŊаКдĐĩĐŊĐž" }, "src_dot_webhooks_dot_components_dot_WebhooksList_dot_2487865635": { "context": "webhook service account", - "string": "Service Account" + "string": "ОбĐģŅ–ĐēОвиК СаĐŋĐ¸Ņ ҁĐģ҃Đļйи" }, "src_dot_webhooks_dot_components_dot_WebhooksList_dot_4120604650": { "context": "user action bar", "string": "Đ”Ņ–Ņ" }, "src_dot_webhooks_dot_components_dot_WebhooksList_dot_618422799": { - "string": "Unnamed webhook" + "string": "ВĐĩĐąŅ…ŅƒĐē ĐąĐĩС ĐŊаСви" }, "src_dot_webhooks_dot_components_dot_WebhooksList_dot_636461959": { "context": "webhook name", @@ -5367,21 +5376,21 @@ }, "src_dot_webhooks_dot_views_dot_3493926696": { "context": "window title", - "string": "Create Webhook" + "string": "ĐĄŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ вĐĩĐąŅ…ŅƒĐē" }, "src_dot_yes": { "string": "ĐĸаĐē " }, "voucherDetailsUnassignCategory": { "context": "unassign category from voucher, button", - "string": "Unassign" + "string": "ĐĄĐēĐ°ŅŅƒĐ˛Đ°Ņ‚Đ¸" }, "voucherDetailsUnassignCollection": { "context": "unassign collection from voucher, button", - "string": "Unassign" + "string": "ĐĄĐēĐ°ŅŅƒĐ˛Đ°Ņ‚Đ¸" }, "voucherDetailsUnassignProduct": { "context": "unassign product from voucher, button", - "string": "Unassign" + "string": "ĐĄĐēĐ°ŅŅƒĐ˛Đ°Ņ‚Đ¸" } } \ No newline at end of file diff --git a/locale/vi.json b/locale/vi.json index 5432578b7..f3097b0ee 100644 --- a/locale/vi.json +++ b/locale/vi.json @@ -250,7 +250,7 @@ "context": "optional field", "string": "Không báē¯t buáģ™c" }, - "productVariantPriceOptionalPriceOverrideField": { + "productVariantPriceOptionalPriceField": { "context": "optional field", "string": "Không báē¯t buáģ™c" }, @@ -1675,6 +1675,10 @@ "context": "button", "string": "XoÃĄ" }, + "src_dot_demo": { + "context": "notification message after log in", + "string": "Just to let you know... You're in demo mode. You can play around with the dashboard but can't save changes." + }, "src_dot_description": { "string": "Mô táēŖ" }, @@ -2532,6 +2536,10 @@ "context": "cancelled fulfillment, section header", "string": "Cancelled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderFulfillment_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderFulfillment_dot_732594284": { "context": "button", "string": "Huáģˇ Giao Hàng" @@ -2749,6 +2757,10 @@ "context": "order payment", "string": "Sáģ‘ tiáģn cáē§n xáģ­ lÃŊ" }, + "src_dot_orders_dot_components_dot_OrderPayment_dot_3720114122": { + "context": "order discount", + "string": "Discount" + }, "src_dot_orders_dot_components_dot_OrderPayment_dot_3768782744": { "context": "order payment", "string": "Sáģ‘ tiáģn Ä‘ÃŖ đưáģŖc uáģˇ quyáģn" @@ -2768,10 +2780,6 @@ "context": "order total price", "string": "Táģ•ng" }, - "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_1542417144": { - "context": "dialog header", - "string": "TáēĄo SáēŖn PháēŠm" - }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2272209368": { "context": "variant sku", "string": "SKU {sku}" @@ -2779,6 +2787,10 @@ "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2336947364": { "string": "TÃŦm báēąng tÃĒn sáēŖn pháēŠm, thuáģ™c tính, cháģ§ng loáēĄi, ..." }, + "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2775402904": { + "context": "dialog header", + "string": "Add Product" + }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2850255786": { "string": "TÃŦm CÃĄc SáēŖn PháēŠm" }, @@ -2809,6 +2821,10 @@ "context": "section header", "string": "Chưa ÄÃĄp áģ¨ng ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_693960049": { + "context": "ordered product sku", + "string": "SKU" + }, "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_878013594": { "context": "order line total price", "string": "Táģ•ng" @@ -3621,17 +3637,14 @@ "context": "header", "string": "Sáģ‘ lưáģŖng" }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3143542809": { - "string": "This product doesn't have any stock. You can add it here." - }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3482985373": { - "context": "button", - "string": "Edit Warehouses" - }, "src_dot_products_dot_components_dot_ProductStocks_dot_3633706025": { "context": "product inventory, checkbox", "string": "Track Inventory" }, + "src_dot_products_dot_components_dot_ProductStocks_dot_3857433664": { + "context": "button", + "string": "Assign Warehouse" + }, "src_dot_products_dot_components_dot_ProductStocks_dot_849869830": { "string": "Active inventory tracking will automatically calculate changes of stock" }, @@ -3859,13 +3872,6 @@ "context": "product variant name", "string": "Biáēŋn Tháģƒ" }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_3482985373": { - "context": "dialog header", - "string": "Edit Warehouses" - }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_4112406382": { - "string": "Select warehouses that stock selected product" - }, "src_dot_products_dot_views_dot_1542417144": { "context": "window title", "string": "TáēĄo SáēŖn PháēŠm" @@ -4147,6 +4153,9 @@ "context": "window title", "string": "TáēĄo Tài KhoáēŖn Dáģ‹ch VáģĨ" }, + "src_dot_sessionExpired": { + "string": "Your session has expired. Please log in again to continue." + }, "src_dot_shipping": { "context": "shipping section name", "string": "CÃĄch TháģŠc Váē­n Chuyáģƒn" diff --git a/locale/zh-Hans.json b/locale/zh-Hans.json index 805e40347..9f4349055 100644 --- a/locale/zh-Hans.json +++ b/locale/zh-Hans.json @@ -4,134 +4,134 @@ "string": "取æļˆčŽĸ单" }, "configurationMenuAttributes": { - "string": "Determine attributes used to create product types" + "string": "įĄŽčŽ¤åˆ›åģēäē§å“įąģåž‹įš„åąžæ€§" }, "configurationMenuNavigation": { - "string": "Define how users can navigate through your store" + "string": "åŽšäš‰į”¨æˆˇåĻ‚äŊ•æĩč§ˆæ‚¨įš„商åē—" }, "configurationMenuPages": { - "string": "Manage and add additional pages" + "string": "įŽĄį†å’Œæˇģ加å…ļåŽƒįš„éĄĩéĸ" }, "configurationMenuPermissionGroups": { - "string": "Manage your permission groups and their permissions" + "string": "įŽĄį†æ‚¨įš„æƒé™åŠį섿ƒé™" }, "configurationMenuProductTypes": { - "string": "Define types of products you sell" + "string": "åŽšäš‰æ‚¨é”€å”Žįš„äē§å“įąģ型" }, "configurationMenuShipping": { - "string": "Manage how you ship out orders" + "string": "įŽĄį†æ‚¨įš„å‘č´§æ–šåŧ" }, "configurationMenuSiteSettings": { - "string": "View and update your site settings" + "string": "æŸĨįœ‹å’Œæ›´æ–°æ‚¨įš„įŊ‘įĢ™čŽžįŊŽ" }, "configurationMenuStaff": { - "string": "Manage your employees and their permissions" + "string": "įŽĄį†æ‚¨įš„å‘˜åˇĨ及å…ļ权限" }, "configurationMenuTaxes": { - "string": "Manage how your store charges tax" + "string": "įŽĄį†åē—é“ēåĻ‚äŊ•æ”ļį¨Ž" }, "configurationMenuWarehouses": { - "string": "Manage and update your warehouse information" + "string": "įŽĄį†å’Œæ›´æ–°æ‚¨įš„äģ“åē“äŋĄæ¯" }, "configurationPluginsPages": { - "string": "View and update your plugins and their settings." + "string": "æŸĨįœ‹å’Œæ›´æ–°æ‚¨įš„æ’äģļ及å…ļ莞įŊŽ" }, "homeActivityCardHeader": { "context": "header", - "string": "Activity" + "string": " æ´ģ动" }, "homeActivityCardNoActivities": { - "string": "No activities found" + "string": "æ˛Ąæœ‰äŋƒé”€æ´ģ动" }, "homeAnalyticsCardHeader": { "string": "äģŠå¤Š" }, "homeHeaderText": { "context": "header", - "string": "Hello there, {userName}" + "string": "您åĨŊīŧŒ {userName}" }, "homeHeaderTextCaption": { "context": "subheader", - "string": "Here is some information we gathered about your store" + "string": "čŋ™æ˜¯æˆ‘äģŦæ”ļé›†įš„æœ‰å…ŗæ‚¨å•†åē—įš„ä¸€äē›äŋĄæ¯" }, "homeNotificationTableNoOrders": { - "string": "No orders ready to fulfill" + "string": "æ˛Ąæœ‰čŋ›čĄŒä¸­įš„čŽĸ单" }, "homeNotificationTableOrders": { - "string": "{amount, plural,one {One order is ready to fulfill} other {{amount} Orders are ready to fulfill}}" + "string": "{amount, plural,other {{amount}ä¸ĒčŽĸ单čŋ›čĄŒä¸­}}" }, "homeNotificationTablePayments": { - "string": "{amount, plural,one {One payment to capture} other {{amount} Payments to capture}}" + "string": "{amount, plural,other {需ä옿Ŧž{amount} }}" }, "homeNotificationTableProducts": { - "string": "{amount, plural,one {One product out of stock} other {{amount} Products out of stock}}" + "string": "{amount, plural,other {{amount} äē§å“įŧēč´§}}" }, "homeNotificationsNoPayments": { - "string": "No payments waiting for capture" + "string": "æ˛Ąæœ‰æœĒä옿Ŧžįš„čŽĸ单" }, "homeNotificationsTableNoProducts": { - "string": "No products out of stock" + "string": "æ˛Ąæœ‰äē§å“įŧēč´§" }, "homeProductListCardOrders": { "context": "number of ordered products", - "string": "{amount, plural,one {One ordered} other {{amount} Ordered}}" + "string": "{amount, plural,other {{amount} 下čŽĸ单}}" }, "homeProductsListCardHeader": { "context": "header", - "string": "Top Products" + "string": "įƒ­é”€äē§å“" }, "homeProductsListCardNoProducts": { - "string": "No products found" + "string": "æ˛Ąæœ‰äē§å“" }, "homeScreenDisclaimer": { "context": "header", - "string": "Disclaimer" + "string": "åŖ°æ˜Ž" }, "homeScreenDisclaimerText1": { - "string": "The new dashboard and the GraphQL API are preview-quality software." + "string": "æ–°įš„äģĒ襨æŋ和GraphQL API是éĸ„č§ˆį‰ˆæœŦįš„čŊ¯äģļ。" }, "homeScreenDisclaimerText2": { - "string": "The GraphQL API is beta quality. It is not fully optimized and some mutations or queries may be missing." + "string": "GraphQL APIä¸ēbetač´¨é‡ã€‚ 尚æœĒ厌全äŧ˜åŒ–īŧŒå¯čƒŊäŧšįŧē少某äē›įĒå˜æˆ–æŸĨč¯ĸ。" }, "homeScreenHeader": { "context": "header", - "string": "Hello there, {userName}" + "string": "您åĨŊīŧŒ {userName}" }, "menuCreateDialogHeader": { "context": "dialog header", - "string": "Create Menu" + "string": "新åģēčœå•" }, "menuCreateDialogMenuTitleLabel": { - "string": "Menu Title" + "string": "čœå•æ ‡éĸ˜" }, "menuDetailsDeleteMenuContent": { - "string": "Are you sure you want to delete menu {menuName}?" + "string": "æ‚¨įĄŽčŽ¤čĻåˆ é™¤čœå• {menuName}īŧŸ" }, "menuDetailsDeleteMenuHeader": { "context": "dialog header", - "string": "Delete Menu" + "string": "åˆ é™¤čœå•" }, "menuDetailsPageHelperText": { - "string": "Creating the navigation structure is done by dragging and dropping. Simply create a new menu item and then drag it into its destined place. You can move items inside one another to create a tree structure and drag items up and down to create a hierarchy" + "string": "通čŋ‡æ‹–攞æĨ创åģēå¯ŧčˆĒį쓿ž„。 åĒ需创åģē一ä¸Ēæ–°čœå•éĄšīŧŒį„ļ后将å…ļ拖动到å…ļéĸ„åޚäŊįŊŽåŗå¯ã€‚ 您可äģĨᛏäē’į§ģåŠ¨éĄšį›ŽäģĨ创åģēæ ‘į쓿ž„īŧŒåšļä¸Šä¸‹æ‹–åŠ¨éĄšį›ŽäģĨ创åģēåą‚æŦĄį쓿ž„" }, "menuItemDialogAddItem": { "context": "create new menu item, header", - "string": "Add Item" + "string": "æˇģåŠ į‰Šå“" }, "menuItemDialogAddLink": { "context": "add link to navigation", - "string": "Link to: {url}" + "string": "链æŽĨīŧš{url}" }, "menuItemDialogEditItem": { "context": "edit menu item, header", - "string": "Edit Item" + "string": "įŧ–čž‘åŽč´" }, "menuItemDialogLinkLabel": { "context": "label", "string": "链æŽĨ" }, "menuItemDialogLinkPlaceholder": { - "string": "Start typing to begin search..." + "string": "输å…Ĩ内厚搜į´ĸ" }, "menuItemDialogNameLabel": { "context": "menu item name", @@ -139,71 +139,71 @@ }, "menuItemsAddItem": { "context": "add new menu item", - "string": "Create new item" + "string": "创åģēæ–°įš„åŽč´" }, "menuItemsHeader": { "context": "header", - "string": "Menu Items" + "string": "čœå•æĄį›Ž" }, "menuItemsPlaceholder": { - "string": "Add new menu item to begin creating menu" + "string": "æˇģåŠ æ–°įš„čœå•č‡ŗåŧ€å§‹čœå•" }, "menuListCreatedMenu": { - "string": "Created menu" + "string": "åˇ˛åˆ›åģēįš„čœå•" }, "menuListDeleteMenuContent": { - "string": "Are you sure you want to delete {menuName}?" + "string": "æ‚¨įĄŽčŽ¤čĻåˆ é™¤čœå• {menuName}īŧŸ" }, "menuListDeleteMenuHeader": { "context": "dialog header", - "string": "Delete Menu" + "string": "åˆ é™¤čœå•" }, "menuListDeleteMenusContent": { - "string": "{counter,plural,one {Are you sure you want to delete this menu?} other {Are you sure you want to delete {displayQuantity} menus?}}" + "string": "{counter,plural,other {įĄŽčŽ¤čĻåˆ é™¤{displayQuantity}čœå•īŧŸ}}" }, "menuListDeleteMenusHeader": { "context": "dialog header", - "string": "Delete Menus" + "string": "åˆ é™¤čœå•" }, "menuListDeletedMenu": { - "string": "Deleted menu" + "string": "åˇ˛åˆ é™¤čœå•" }, "menuListItems": { "context": "number of menu items", - "string": "Items" + "string": "åŽč´" }, "menuListMenutitle": { - "string": "Menu Title" + "string": "čœå•æ ‡éĸ˜" }, "menuListNoMenus": { - "string": "No menus found" + "string": "æ˛Ąæœ‰čœå•" }, "menuListPageAddMenu": { "context": "button", - "string": "Create Menu" + "string": "新åģēčœå•" }, "menuPropertiesMenuTitle": { - "string": "Menu Title" + "string": "čœå•æ ‡éĸ˜" }, "orderCustomerBillingAddressNotSet": { "context": "no address is set in draft order", - "string": "Not set" + "string": "æ˛Ąæœ‰čŽžįŊŽ" }, "orderCustomerCustomerNotSet": { "context": "customer is not set in draft order", - "string": "Not set" + "string": "æ˛Ąæœ‰čŽžįŊŽ" }, "orderCustomerShippingAddressNotSet": { "context": "shipping address is not set in draft order", - "string": "Not set" + "string": "æ˛Ąæœ‰čŽžįŊŽ" }, "orderPaymentShippingDoesNotApply": { "context": "order does not require shipping", - "string": "does not apply" + "string": "æ˛Ąæœ‰į”Ÿæ•ˆ" }, "orderPaymentVATDoesNotApply": { "context": "vat not included in order price", - "string": "does not apply" + "string": "æ˛Ąæœ‰į”Ÿæ•ˆ" }, "productStatusLabel": { "context": "product", @@ -211,15 +211,15 @@ }, "productStockHeader": { "context": "product stock, section header", - "string": "Inventory" + "string": "åē“å­˜" }, "productTypeCreateHeader": { "context": "window title", - "string": "Create Product Type" + "string": "新åģēäē§å“įąģ型" }, "productTypeCreatePageHeader": { "context": "header", - "string": "Create Product Type" + "string": "新åģēäē§å“įąģ型" }, "productTypeTaxesHeader": { "context": "section header", @@ -236,113 +236,113 @@ "string": "ä쎿 ŧ" }, "productVariantCreatePricesStockInputLabel": { - "string": "Stock" + "string": "åē“å­˜" }, "productVariantCreatorStockSectionHeader": { "context": "variant stock, header", - "string": "Stock" + "string": "存货" }, "productVariantCreatorWarehouseSectionHeader": { "context": "header", - "string": "Warehouses" + "string": "č´§äģ“" }, "productVariantPriceOptionalCostPriceField": { "context": "optional field", - "string": "Optional" + "string": "可选" }, - "productVariantPriceOptionalPriceOverrideField": { + "productVariantPriceOptionalPriceField": { "context": "optional field", - "string": "Optional" + "string": "可选" }, "saleDetailsPageCategoriesQuantity": { "context": "number of categories", - "string": "Categories ({quantity})" + "string": "分įąģīŧˆ{quantity}īŧ‰" }, "saleDetailsPageCollectionsQuantity": { "context": "number of collections", - "string": "Collections ({quantity})" + "string": "įŗģ列 ({quantity})" }, "saleDetailsPageProductsQuantity": { "context": "number of products", - "string": "Products ({quantity})" + "string": "äē§å“ ({quantity})" }, "saleDetailsUnassignCategory": { "context": "unassign category from sale, button", - "string": "Unassign" + "string": "取æļˆåˆ†é…" }, "saleDetailsUnassignCollection": { "context": "unassign collection from sale, button", - "string": "Unassign" + "string": "取æļˆåˆ†é…" }, "saleDetailsUnassignProduct": { "context": "unassign product from sale, button", - "string": "Unassign" + "string": "取æļˆåˆ†é…" }, "shippingZoneDetailsDialogsDeleteShippingMethod": { "context": "delete shipping method", - "string": "Are you sure you want to delete {name}?" + "string": "æ‚¨įĄŽčŽ¤æƒŗčĻåˆ é™¤ {name}?īŧŸ" }, "shippingZoneDetailsDialogsDeleteShippingZone": { "context": "delete shipping zone", - "string": "Are you sure you want to delete {name}?" + "string": "æ‚¨įĄŽčŽ¤æƒŗčĻåˆ é™¤ {name}?īŧŸ" }, "shippingZoneWarehouses_dot_autocomplete_dot_label": { "context": "autocomplete select label", - "string": "Warehouse" + "string": "č´§äģ“" }, "siteSettingsMailingHelperText": { "context": "helper text", - "string": "Mailing Configuration" + "string": "邮äģļ配įŊŽ" }, "src_dot_accept": { "context": "button", - "string": "Accept" + "string": "æŽĨ受" }, "src_dot_attributes": { "context": "attributes section name", "string": "åąžæ€§" }, "src_dot_attributes_dot_attributeSlugUnique": { - "string": "Attribute with this slug already exists" + "string": "æ­¤æĄåąžæ€§åˇ˛å­˜åœ¨" }, "src_dot_attributes_dot_attributeValueAlreadyExists": { - "string": "This value already exists within this attribute" + "string": "æ­¤å€ŧ厞存圍äēŽæ­¤åąžæ€§ä¸­" }, "src_dot_attributes_dot_components_dot_AttributeBulkDeleteDialog_dot_1184518529": { "context": "dialog content", - "string": "{counter,plural,one {Are you sure you want to delete this attribute?} other {Are you sure you want to delete {displayQuantity} attributes?}}" + "string": "{counter,plural,other {įĄŽčŽ¤čĻåˆ é™¤{displayQuantity}åąžæ€§īŧŸ}}" }, "src_dot_attributes_dot_components_dot_AttributeBulkDeleteDialog_dot_1655187315": { "context": "dialog title", - "string": "Delete attributes" + "string": "åˆ é™¤åąžæ€§" }, "src_dot_attributes_dot_components_dot_AttributeDeleteDialog_dot_1889602489": { "context": "dialog title", - "string": "Delete attribute" + "string": "åˆ é™¤åąžæ€§" }, "src_dot_attributes_dot_components_dot_AttributeDeleteDialog_dot_3738429348": { "context": "dialog content", - "string": "Are you sure you want to delete {attributeName}?" + "string": "įĄŽčŽ¤čĻåˆ é™¤{attributeName}åąžæ€§īŧŸ" }, "src_dot_attributes_dot_components_dot_AttributeDetails_dot_1005562666": { "context": "attribute's editor component", - "string": "Catalog Input type for Store Owner" + "string": "商åē—æ‰€æœ‰č€…įš„į›ŽåŊ•čž“å…Ĩįąģ型" }, "src_dot_attributes_dot_components_dot_AttributeDetails_dot_1336738461": { "context": "product attribute type", - "string": "Dropdown" + "string": "下拉" }, "src_dot_attributes_dot_components_dot_AttributeDetails_dot_2592224946": { "context": "check to require attribute to have value", - "string": "Value Required" + "string": "所需å€ŧ" }, "src_dot_attributes_dot_components_dot_AttributeDetails_dot_3334509011": { "context": "product attribute type", - "string": "Multiple Select" + "string": "多选" }, "src_dot_attributes_dot_components_dot_AttributeDetails_dot_3605174225": { "context": "attribute's slug short code label", - "string": "Attribute Code" + "string": "åąžæ€§į " }, "src_dot_attributes_dot_components_dot_AttributeDetails_dot_4107478955": { "context": "attribute slug input field helper text", @@ -354,7 +354,7 @@ }, "src_dot_attributes_dot_components_dot_AttributeListPage_dot_2417065806": { "context": "tab name", - "string": "All Attributes" + "string": "æ‰€æœ‰åąžæ€§" }, "src_dot_attributes_dot_components_dot_AttributeListPage_dot_3824684885": { "context": "button", @@ -381,7 +381,7 @@ }, "src_dot_attributes_dot_components_dot_AttributeListPage_dot_valueRequired": { "context": "attribute value is required", - "string": "Value Required" + "string": "所需å€ŧ" }, "src_dot_attributes_dot_components_dot_AttributeListPage_dot_visibleInStorefront": { "context": "attribute", @@ -399,7 +399,7 @@ "string": "Searchable" }, "src_dot_attributes_dot_components_dot_AttributeList_dot_3605174225": { - "string": "Attribute Code" + "string": "åąžæ€§į " }, "src_dot_attributes_dot_components_dot_AttributeList_dot_643174786": { "context": "attribute is visible", @@ -411,7 +411,7 @@ }, "src_dot_attributes_dot_components_dot_AttributePage_dot_2855501559": { "context": "page title", - "string": "Create New Attribute" + "string": "新åģēæ–°åąžæ€§" }, "src_dot_attributes_dot_components_dot_AttributeProperties_dot_1318123158": { "context": "attribute is filterable in storefront", @@ -438,7 +438,7 @@ }, "src_dot_attributes_dot_components_dot_AttributeProperties_dot_673770329": { "context": "add attribute as column in product list table", - "string": "Add to Column Options" + "string": "æˇģåŠ åˆ—é€‰éĄš" }, "src_dot_attributes_dot_components_dot_AttributeProperties_dot_714335445": { "context": "use attribute in filtering", @@ -464,7 +464,7 @@ }, "src_dot_attributes_dot_components_dot_AttributeValueEditDialog_dot_1841790893": { "context": "add attribute value", - "string": "Add Value" + "string": "æˇģ加å€ŧ" }, "src_dot_attributes_dot_components_dot_AttributeValueEditDialog_dot_636461959": { "context": "attribute name", @@ -502,7 +502,7 @@ }, "src_dot_attributes_dot_views_dot_AttributeDetails_dot_634268988": { "context": "added new attribute value", - "string": "Added new value" + "string": "æˇģåŠ æ–°įš„å€ŧ" }, "src_dot_attributes_dot_views_dot_AttributeList_dot_3218248395": { "context": "deleted multiple attributes", @@ -533,7 +533,7 @@ "string": "Set new password" }, "src_dot_auth_dot_components_dot_NewPasswordPage_dot_2799926859": { - "string": "Confirm Password" + "string": "å¯†į įĄŽčŽ¤" }, "src_dot_auth_dot_components_dot_NewPasswordPage_dot_4253911811": { "string": "Passwords do not match" @@ -547,7 +547,7 @@ }, "src_dot_auth_dot_components_dot_ResetPasswordSuccessPage_dot_2245157344": { "context": "button", - "string": "Back to login" + "string": "čŋ”回į™ģåŊ•" }, "src_dot_auth_dot_components_dot_ResetPasswordSuccessPage_dot_4066297200": { "string": "Success! In a few minutes you’ll receive a message with instructions on how to reset your password." @@ -560,7 +560,7 @@ }, "src_dot_back": { "context": "button", - "string": "Back" + "string": "čŋ”回" }, "src_dot_cancel": { "context": "button", @@ -568,10 +568,10 @@ }, "src_dot_cancelled": { "context": "order status", - "string": "Cancelled" + "string": "取æļˆ" }, "src_dot_catalog": { - "string": "Catalog" + "string": "分įąģ" }, "src_dot_categories": { "context": "categories section name", @@ -579,18 +579,18 @@ }, "src_dot_categories_dot_components_dot_CategoryBackground_dot_2224943474": { "context": "section header", - "string": "Background Image (optional)" + "string": "北äēŦ台īŧˆå¯é€‰īŧ‰" }, "src_dot_categories_dot_components_dot_CategoryBackground_dot_3289097895": { "context": "field is optional", - "string": "(Optional)" + "string": "īŧˆå¯é€‰īŧ‰" }, "src_dot_categories_dot_components_dot_CategoryCreatePage_dot_236319840": { "context": "page header", - "string": "Create New Category" + "string": "新åģēæ–°åˆ†įąģ" }, "src_dot_categories_dot_components_dot_CategoryCreatePage_dot_2563994280": { - "string": "Add search engine title and description to make this category easier to find" + "string": "æˇģåŠ å…ŗé”Žå­—äŊŋåž—čŋ™ä¸Ē分įąģ更厚易čĸĢæœį´ĸåŧ•擎扞到" }, "src_dot_categories_dot_components_dot_CategoryDeleteDialog_dot_2004894945": { "context": "dialog title", @@ -601,10 +601,10 @@ "string": "Are you sure you want to delete {categoryName}?" }, "src_dot_categories_dot_components_dot_CategoryDetailsForm_dot_1214235329": { - "string": "Category Name" + "string": "分įąģ名" }, "src_dot_categories_dot_components_dot_CategoryDetailsForm_dot_4037703468": { - "string": "Category Description" + "string": "分įąģ描čŋ°" }, "src_dot_categories_dot_components_dot_CategoryListPage_dot_1140231710": { "context": "button", @@ -615,10 +615,10 @@ }, "src_dot_categories_dot_components_dot_CategoryListPage_dot_4294878092": { "context": "tab name", - "string": "All Categories" + "string": "所有分įąģ" }, "src_dot_categories_dot_components_dot_CategoryList_dot_1214235329": { - "string": "Category Name" + "string": "分įąģ名" }, "src_dot_categories_dot_components_dot_CategoryList_dot_2054128296": { "string": "No categories found" @@ -639,7 +639,7 @@ "string": "ä쎿 ŧ" }, "src_dot_categories_dot_components_dot_CategoryProductList_dot_1657559629": { - "string": "No products found" + "string": "æ˛Ąæœ‰äē§å“" }, "src_dot_categories_dot_components_dot_CategoryProductList_dot_1952810469": { "context": "product type", @@ -670,7 +670,7 @@ "string": "Subcategories" }, "src_dot_categories_dot_components_dot_CategoryUpdatePage_dot_2563994280": { - "string": "Add search engine title and description to make this category easier to find" + "string": "æˇģåŠ å…ŗé”Žå­—äŊŋåž—čŋ™ä¸Ē分įąģ更厚易čĸĢæœį´ĸåŧ•擎扞到" }, "src_dot_categories_dot_components_dot_CategoryUpdatePage_dot_2968663655": { "context": "number of products in category", @@ -678,7 +678,7 @@ }, "src_dot_categories_dot_components_dot_CategoryUpdatePage_dot_3229914152": { "context": "section header", - "string": "All Subcategories" + "string": "全部子įąģ" }, "src_dot_categories_dot_components_dot_CategoryUpdatePage_dot_770296100": { "context": "button", @@ -692,7 +692,7 @@ "string": "{counter,plural,one {Are you sure you want to delete this product?} other {Are you sure you want to delete {displayQuantity} products?}}" }, "src_dot_categories_dot_views_dot_1754466114": { - "string": "Category created" + "string": "分įąģåˇ˛æ–°åģē" }, "src_dot_categories_dot_views_dot_1823337870": { "string": "{counter,plural,one {Are you sure you want to delete this category?} other {Are you sure you want to delete {displayQuantity} categories?}}" @@ -702,7 +702,7 @@ "string": "Delete category" }, "src_dot_categories_dot_views_dot_2189424032": { - "string": "Category deleted" + "string": "分įąģåˇ˛åˆ é™¤" }, "src_dot_categories_dot_views_dot_2507763081": { "context": "dialog title", @@ -745,11 +745,11 @@ "string": "will be visible from {date}" }, "src_dot_collections_dot_components_dot_CollectionCreatePage_dot_946315389": { - "string": "Add search engine title and description to make this collection easier to find" + "string": "æˇģåŠ å…ŗé”Žå­—äŊŋåž—čŋ™ä¸Ēįŗģ列更厚易čĸĢæœį´ĸåŧ•擎扞到" }, "src_dot_collections_dot_components_dot_CollectionCreatePage_dot_951411809": { "context": "page header", - "string": "Add Collection" + "string": "æˇģ加įŗģ列" }, "src_dot_collections_dot_components_dot_CollectionDetailsPage_dot_1815688500": { "context": "collection", @@ -764,7 +764,7 @@ "string": "Feature on Homepage" }, "src_dot_collections_dot_components_dot_CollectionDetailsPage_dot_946315389": { - "string": "Add search engine title and description to make this collection easier to find" + "string": "æˇģåŠ å…ŗé”Žå­—äŊŋåž—čŋ™ä¸Ēįŗģ列更厚易čĸĢæœį´ĸåŧ•擎扞到" }, "src_dot_collections_dot_components_dot_CollectionDetails_dot_636461959": { "context": "collection name", @@ -772,15 +772,15 @@ }, "src_dot_collections_dot_components_dot_CollectionImage_dot_2224943474": { "context": "section header", - "string": "Background Image (optional)" + "string": "北äēŦ台īŧˆå¯é€‰īŧ‰" }, "src_dot_collections_dot_components_dot_CollectionImage_dot_3289097895": { "context": "field is optional", - "string": "(Optional)" + "string": "īŧˆå¯é€‰īŧ‰" }, "src_dot_collections_dot_components_dot_CollectionListPage_dot_1631917001": { "context": "tab name", - "string": "All Collections" + "string": "所有įŗģ列" }, "src_dot_collections_dot_components_dot_CollectionListPage_dot_4057224233": { "string": "Search Collection" @@ -791,7 +791,7 @@ }, "src_dot_collections_dot_components_dot_CollectionListPage_dot_hidden": { "context": "collection", - "string": "Hidden" + "string": "隐藏" }, "src_dot_collections_dot_components_dot_CollectionListPage_dot_published": { "context": "collection", @@ -808,7 +808,7 @@ "string": "No. of Products" }, "src_dot_collections_dot_components_dot_CollectionList_dot_2759199473": { - "string": "Collection Name" + "string": "įŗģ列名" }, "src_dot_collections_dot_components_dot_CollectionList_dot_3326160357": { "context": "collection availability", @@ -819,7 +819,7 @@ "string": "åˇ˛å‘å¸ƒ" }, "src_dot_collections_dot_components_dot_CollectionProducts_dot_1657559629": { - "string": "No products found" + "string": "æ˛Ąæœ‰äē§å“" }, "src_dot_collections_dot_components_dot_CollectionProducts_dot_1952810469": { "context": "product type", @@ -849,7 +849,7 @@ "string": "删除åĨ—餐" }, "src_dot_collections_dot_views_dot_2001540731": { - "string": "Added product to collection" + "string": "将äē§å“æˇģ加到įŗģ列" }, "src_dot_collections_dot_views_dot_2402899582": { "string": "Are you sure you want to delete collection's image?" @@ -877,7 +877,7 @@ }, "src_dot_collections_dot_views_dot_870815507": { "context": "unassign product from collection, button", - "string": "Unassign" + "string": "取æļˆåˆ†é…" }, "src_dot_collections_dot_views_dot_942133001": { "context": "dialog title", @@ -933,7 +933,7 @@ }, "src_dot_components_dot_AccountStatus_dot_2183517419": { "context": "section header", - "string": "Account Status" + "string": "č´ĻæˆˇįŠļ态" }, "src_dot_components_dot_AccountStatus_dot_2683780981": { "string": "If you want to disable this account uncheck the box below" @@ -945,7 +945,7 @@ "string": "Phone" }, "src_dot_components_dot_AddressEdit_dot_1363074570": { - "string": "Address line 1" + "string": "åœ°å€čĄŒ1" }, "src_dot_components_dot_AddressEdit_dot_253031977": { "string": "城市" @@ -954,13 +954,13 @@ "string": "ZIP / Postal code" }, "src_dot_components_dot_AddressEdit_dot_3121963259": { - "string": "Address line 2" + "string": "åœ°å€čĄŒ2" }, "src_dot_components_dot_AddressEdit_dot_3570415321": { - "string": "Company" + "string": "å…Ŧ司" }, "src_dot_components_dot_AddressEdit_dot_944851093": { - "string": "Country area" + "string": "å›ŊåŽļ地åŒē" }, "src_dot_components_dot_AppLayout_dot_21332146": { "context": "button", @@ -968,7 +968,7 @@ }, "src_dot_components_dot_AppLayout_dot_248888005": { "context": "button", - "string": "Account Settings" + "string": "č´ĻæˆˇčŽžįŊŽ" }, "src_dot_components_dot_AssignCategoryDialog_dot_1305061437": { "string": "Search Categories" @@ -1034,7 +1034,7 @@ "string": "Phone" }, "src_dot_components_dot_CompanyAddressInput_dot_1363074570": { - "string": "Address line 1" + "string": "åœ°å€čĄŒ1" }, "src_dot_components_dot_CompanyAddressInput_dot_253031977": { "string": "城市" @@ -1043,17 +1043,17 @@ "string": "ZIP / Postal code" }, "src_dot_components_dot_CompanyAddressInput_dot_3121963259": { - "string": "Address line 2" + "string": "åœ°å€čĄŒ2" }, "src_dot_components_dot_CompanyAddressInput_dot_3570415321": { - "string": "Company" + "string": "å…Ŧ司" }, "src_dot_components_dot_CompanyAddressInput_dot_944851093": { - "string": "Country area" + "string": "å›ŊåŽļ地åŒē" }, "src_dot_components_dot_ConfirmButton_dot_2845142593": { "context": "button", - "string": "Error" + "string": "错蝝" }, "src_dot_components_dot_CountryList_dot_2460766407": { "context": "number of countries", @@ -1072,17 +1072,17 @@ }, "src_dot_components_dot_ErrorMessageCard_dot_2845142593": { "context": "header", - "string": "Error" + "string": "错蝝" }, "src_dot_components_dot_ErrorPage_dot_1723676032": { "context": "button", - "string": "Back to home" + "string": "čŋ”回éĻ–éĄĩ" }, "src_dot_components_dot_ErrorPage_dot_2736139139": { - "string": "Ooops!..." + "string": "å™ĸīŧ..." }, "src_dot_components_dot_ErrorPage_dot_2845142593": { - "string": "Error" + "string": "错蝝" }, "src_dot_components_dot_ErrorPage_dot_3090161573": { "string": "Don't worry, everything is gonna be fine" @@ -1157,7 +1157,7 @@ }, "src_dot_components_dot_MultiAutocompleteSelectField_dot_1477537381": { "context": "add custom select input option", - "string": "Add new value: {value}" + "string": "æˇģåŠ æ–°įš„å€ŧīŧš{value}" }, "src_dot_components_dot_MultiAutocompleteSelectField_dot_4205644805": { "string": "No results found" @@ -1221,19 +1221,19 @@ }, "src_dot_components_dot_Navigator_dot_modes_dot_createCategory": { "context": "button", - "string": "Create Category" + "string": "新åģē分įąģ" }, "src_dot_components_dot_Navigator_dot_modes_dot_createCollection": { "context": "button", - "string": "Create Collection" + "string": "新åģēįŗģ列" }, "src_dot_components_dot_Navigator_dot_modes_dot_createCustomer": { "context": "button", - "string": "Create Customer" + "string": "新åģēåŽĸæˆˇ" }, "src_dot_components_dot_Navigator_dot_modes_dot_createOrder": { "context": "button", - "string": "Create Order" + "string": "新åģēčŽĸ单" }, "src_dot_components_dot_Navigator_dot_modes_dot_createPermissionGroup": { "context": "button", @@ -1241,7 +1241,7 @@ }, "src_dot_components_dot_Navigator_dot_modes_dot_createProduct": { "context": "button", - "string": "Create Product" + "string": "新åģēäē§å“" }, "src_dot_components_dot_Navigator_dot_modes_dot_createVoucher": { "context": "button", @@ -1285,7 +1285,7 @@ "string": "äē§å“" }, "src_dot_components_dot_NotFoundPage_dot_2736139139": { - "string": "Ooops!..." + "string": "å™ĸīŧ..." }, "src_dot_components_dot_NotFoundPage_dot_4036415297": { "string": "Something's missing" @@ -1302,7 +1302,7 @@ }, "src_dot_components_dot_RichTextEditor_dot_1603794322": { "context": "dialog header", - "string": "Add Image Link" + "string": "æˇģåŠ å›žį‰‡é“žæŽĨ" }, "src_dot_components_dot_RichTextEditor_dot_2049070632": { "context": "replace image, button", @@ -1310,7 +1310,7 @@ }, "src_dot_components_dot_RichTextEditor_dot_2160163587": { "context": "button", - "string": "Add or Edit Link" + "string": "æˇģ加或įŧ–螑铞æŽĨ" }, "src_dot_components_dot_RichTextEditor_dot_286109898": { "context": "rich text error", @@ -1320,7 +1320,7 @@ "string": "URL Linked" }, "src_dot_components_dot_RichTextEditor_dot_4035057905": { - "string": "Image URL" + "string": "å›žį‰‡URL" }, "src_dot_components_dot_RowNumberSelect_dot_1154361791": { "string": "No of Rows:" @@ -1366,7 +1366,7 @@ }, "src_dot_components_dot_SingleAutocompleteSelectField_dot_1477537381": { "context": "add custom select input option", - "string": "Add new value: {value}" + "string": "æˇģåŠ æ–°įš„å€ŧīŧš{value}" }, "src_dot_components_dot_SingleAutocompleteSelectField_dot_3069107721": { "string": "None" @@ -1402,7 +1402,7 @@ "string": "Visible" }, "src_dot_components_dot_VisibilityCard_dot_77815154": { - "string": "Hidden" + "string": "隐藏" }, "src_dot_components_dot_WeightRange_dot_264731940": { "context": "weight", @@ -1447,7 +1447,7 @@ }, "src_dot_confirm": { "context": "button", - "string": "Confirm" + "string": "įĄŽčŽ¤" }, "src_dot_create": { "context": "button", @@ -1459,11 +1459,11 @@ }, "src_dot_customers_dot_components_dot_CustomerAddressDialog_dot_2364475135": { "context": "dialog title", - "string": "Edit Address" + "string": "įŧ–čž‘åœ°å€" }, "src_dot_customers_dot_components_dot_CustomerAddressDialog_dot_3769321414": { "context": "dialog title", - "string": "Add Address" + "string": "æˇģ加地址" }, "src_dot_customers_dot_components_dot_CustomerAddressListPage_dot_1090326769": { "context": "customer's address book, header", @@ -1477,36 +1477,36 @@ }, "src_dot_customers_dot_components_dot_CustomerAddressListPage_dot_3623935073": { "context": "button", - "string": "Add address" + "string": "æˇģ加地址" }, "src_dot_customers_dot_components_dot_CustomerAddressListPage_dot_489918044": { "context": "customer details, header", "string": "{fullName} Details" }, "src_dot_customers_dot_components_dot_CustomerAddress_dot_1224809208": { - "string": "Default Address" + "string": "éģ˜čŽ¤åœ°å€" }, "src_dot_customers_dot_components_dot_CustomerAddress_dot_1578192486": { - "string": "Default Billing Address" + "string": "éģ˜čޤč´Ļ单地址" }, "src_dot_customers_dot_components_dot_CustomerAddress_dot_2131178753": { "context": "button", - "string": "Set as default shipping address" + "string": "莞ä¸ēéģ˜čŽ¤é…é€åœ°å€" }, "src_dot_customers_dot_components_dot_CustomerAddress_dot_3096438859": { "context": "button", - "string": "Set as default billing address" + "string": "莞ä¸ēéģ˜čޤč´Ļ单地址" }, "src_dot_customers_dot_components_dot_CustomerAddress_dot_4109348993": { - "string": "Default Shipping Address" + "string": "éģ˜čŽ¤é…é€åœ°å€" }, "src_dot_customers_dot_components_dot_CustomerAddresses_dot_1967111456": { "context": "header", - "string": "Address Information" + "string": "地址äŋĄæ¯" }, "src_dot_customers_dot_components_dot_CustomerAddresses_dot_2758581442": { "context": "subsection header", - "string": "Shipping Address" + "string": "配送地址" }, "src_dot_customers_dot_components_dot_CustomerAddresses_dot_359810770": { "context": "subsection header", @@ -1517,14 +1517,14 @@ }, "src_dot_customers_dot_components_dot_CustomerAddresses_dot_4282475982": { "context": "subsection header", - "string": "Billing Address" + "string": "č´Ļ单地址" }, "src_dot_customers_dot_components_dot_CustomerCreateAddress_dot_1751533141": { "context": "page header", - "string": "Primary Address" + "string": "éĻ–čĻåœ°å€" }, "src_dot_customers_dot_components_dot_CustomerCreateAddress_dot_401345057": { - "string": "The primary address of this customer." + "string": "čŋ™ä¸ĒåŽĸæˆˇįš„ä¸ģčĻåœ°å€" }, "src_dot_customers_dot_components_dot_CustomerCreateDetails_dot_3063084773": { "context": "header", @@ -1543,7 +1543,7 @@ }, "src_dot_customers_dot_components_dot_CustomerCreatePage_dot_4025686004": { "context": "page header", - "string": "Create Customer" + "string": "新åģēåŽĸæˆˇ" }, "src_dot_customers_dot_components_dot_CustomerDetails_dot_2968565128": { "context": "check to mark this account as active", @@ -1551,7 +1551,7 @@ }, "src_dot_customers_dot_components_dot_CustomerDetails_dot_3298169382": { "context": "section subheader", - "string": "Active member since {date}" + "string": "äģŽ {date} čĩˇįš„æ´ģčˇƒį”¨æˆˇ" }, "src_dot_customers_dot_components_dot_CustomerDetails_dot_577013340": { "context": "note about customer", @@ -1563,7 +1563,7 @@ }, "src_dot_customers_dot_components_dot_CustomerInfo_dot_778526801": { "context": "customer contact section, header", - "string": "Contact Informations" + "string": "联įŗģäēēäŋĄæ¯" }, "src_dot_customers_dot_components_dot_CustomerListPage_dot_1643417013": { "string": "Search Customer" @@ -1574,7 +1574,7 @@ }, "src_dot_customers_dot_components_dot_CustomerListPage_dot_477293306": { "context": "tab name", - "string": "All Customers" + "string": "所有åŽĸæˆˇ" }, "src_dot_customers_dot_components_dot_CustomerListPage_dot_joinDate": { "context": "customer", @@ -1646,14 +1646,14 @@ }, "src_dot_customers_dot_views_dot_2657976015": { "context": "dialog header", - "string": "Delete Address" + "string": "删除地址" }, "src_dot_customers_dot_views_dot_2859116187": { "context": "window title", "string": "Create customer" }, "src_dot_customers_dot_views_dot_3689332763": { - "string": "Are you sure you want to delete this address from users address book?" + "string": "äŊ įĄŽåޚčĻæŠŠčŋ™ä¸Ē地址äģŽåœ°å€č–„中删除吗īŧŸ" }, "src_dot_customers_dot_views_dot_3901579344": { "string": "Customer Removed" @@ -1675,6 +1675,10 @@ "context": "button", "string": "Delete" }, + "src_dot_demo": { + "context": "notification message after log in", + "string": "Just to let you know... You're in demo mode. You can play around with the dashboard but can't save changes." + }, "src_dot_description": { "string": "描čŋ°" }, @@ -1682,7 +1686,7 @@ "string": "æŠ˜æ‰Ŗ" }, "src_dot_discounts_dot_components_dot_DiscountCategories_dot_1567318211": { - "string": "Category name" + "string": "分įąģ名" }, "src_dot_discounts_dot_components_dot_DiscountCategories_dot_1681512341": { "context": "section header", @@ -1711,7 +1715,7 @@ "string": "äē§å“" }, "src_dot_discounts_dot_components_dot_DiscountCollections_dot_3011396316": { - "string": "Collection name" + "string": "įŗģ列名" }, "src_dot_discounts_dot_components_dot_DiscountCollections_dot_452750900": { "context": "section header", @@ -1749,7 +1753,7 @@ "string": "Active Dates" }, "src_dot_discounts_dot_components_dot_DiscountProducts_dot_1657559629": { - "string": "No products found" + "string": "æ˛Ąæœ‰äē§å“" }, "src_dot_discounts_dot_components_dot_DiscountProducts_dot_2100305525": { "context": "button", @@ -1798,7 +1802,7 @@ }, "src_dot_discounts_dot_components_dot_SaleListPage_dot_expired": { "context": "sale status", - "string": "Expired" + "string": "厞čŋ‡æœŸ" }, "src_dot_discounts_dot_components_dot_SaleListPage_dot_fixed": { "context": "discount type", @@ -1894,15 +1898,15 @@ }, "src_dot_discounts_dot_components_dot_VoucherDetailsPage_dot_346170541": { "context": "number of categories", - "string": "Categories ({quantity})" + "string": "分įąģīŧˆ{quantity}īŧ‰" }, "src_dot_discounts_dot_components_dot_VoucherDetailsPage_dot_3673147015": { "context": "number of collections", - "string": "Collections ({quantity})" + "string": "įŗģ列 ({quantity})" }, "src_dot_discounts_dot_components_dot_VoucherDetailsPage_dot_846927739": { "context": "number of products", - "string": "Products ({quantity})" + "string": "äē§å“ ({quantity})" }, "src_dot_discounts_dot_components_dot_VoucherInfo_dot_1262795626": { "string": "Discount Code" @@ -1928,7 +1932,7 @@ }, "src_dot_discounts_dot_components_dot_VoucherListPage_dot_1112241061": { "context": "tab name", - "string": "All Vouchers" + "string": "所有äģŖå¸åˆ¸" }, "src_dot_discounts_dot_components_dot_VoucherListPage_dot_1930485532": { "string": "Search Voucher" @@ -1943,7 +1947,7 @@ }, "src_dot_discounts_dot_components_dot_VoucherListPage_dot_expired": { "context": "voucher status", - "string": "Expired" + "string": "厞čŋ‡æœŸ" }, "src_dot_discounts_dot_components_dot_VoucherListPage_dot_fixed": { "context": "discount type", @@ -2025,7 +2029,7 @@ }, "src_dot_discounts_dot_components_dot_VoucherSummary_dot_2735425668": { "context": "voucher", - "string": "Applies to" + "string": "åē”į”¨åˆ°" }, "src_dot_discounts_dot_components_dot_VoucherSummary_dot_3751756157": { "context": "voucher value requirement", @@ -2180,7 +2184,7 @@ "string": "įŧ–čž‘" }, "src_dot_email": { - "string": "E-mail Address" + "string": "į”ĩå­é‚ŽįŽą" }, "src_dot_endDate": { "string": "End Date" @@ -2231,7 +2235,7 @@ }, "src_dot_optionalField": { "context": "field is optional", - "string": "Optional" + "string": "可选" }, "src_dot_orders": { "context": "orders section name", @@ -2239,15 +2243,15 @@ }, "src_dot_orders_dot_components_dot_OrderAddressEditDialog_dot_3278396777": { "context": "dialog header", - "string": "Edit Shipping Address" + "string": "įŧ–čž‘é…é€åœ°å€" }, "src_dot_orders_dot_components_dot_OrderAddressEditDialog_dot_3982060155": { "context": "dialog header", - "string": "Edit Billing Address" + "string": "įŧ–čž‘č´Ļ单地址" }, "src_dot_orders_dot_components_dot_OrderBulkCancelDialog_dot_1528036340": { "context": "dialog header", - "string": "Cancel Orders" + "string": "取æļˆčŽĸ单" }, "src_dot_orders_dot_components_dot_OrderBulkCancelDialog_dot_4224885638": { "string": "{counter,plural,one {Are you sure you want to cancel this order?} other {Are you sure you want to cancel {displayQuantity} orders?}}" @@ -2271,7 +2275,7 @@ }, "src_dot_orders_dot_components_dot_OrderCustomer_dot_2312694610": { "context": "subheader", - "string": "Contact Information" + "string": "联įŗģäēēäŋĄæ¯" }, "src_dot_orders_dot_components_dot_OrderCustomer_dot_2433460203": { "string": "Search Customers" @@ -2281,7 +2285,7 @@ "string": "View Profile" }, "src_dot_orders_dot_components_dot_OrderCustomer_dot_2758581442": { - "string": "Shipping Address" + "string": "配送地址" }, "src_dot_orders_dot_components_dot_OrderCustomer_dot_3426593715": { "context": "section header", @@ -2289,13 +2293,13 @@ }, "src_dot_orders_dot_components_dot_OrderCustomer_dot_3912924864": { "context": "billing address", - "string": "Same as shipping address" + "string": "å’Œé…é€åœ°å€į›¸åŒ" }, "src_dot_orders_dot_components_dot_OrderCustomer_dot_4172383244": { - "string": "Anonymous user" + "string": "不įŸĨåį”¨æˆˇ" }, "src_dot_orders_dot_components_dot_OrderCustomer_dot_4282475982": { - "string": "Billing Address" + "string": "č´Ļ单地址" }, "src_dot_orders_dot_components_dot_OrderDetailsPage_dot_1854613983": { "context": "button", @@ -2320,7 +2324,7 @@ "string": "数量" }, "src_dot_orders_dot_components_dot_OrderDraftDetailsProducts_dot_546865199": { - "string": "No Products added to Order" + "string": "æ˛Ąæœ‰äē§å“æˇģ加到čŽĸ单" }, "src_dot_orders_dot_components_dot_OrderDraftDetailsProducts_dot_878013594": { "context": "total price of ordered products", @@ -2328,7 +2332,7 @@ }, "src_dot_orders_dot_components_dot_OrderDraftDetailsSummary_dot_2429341469": { "context": "button", - "string": "Add shipping carrier" + "string": "æˇģ加åŋĢ递å…Ŧ司" }, "src_dot_orders_dot_components_dot_OrderDraftDetailsSummary_dot_3202709354": { "string": "Taxes (VAT included)" @@ -2338,7 +2342,7 @@ }, "src_dot_orders_dot_components_dot_OrderDraftDetailsSummary_dot_781550514": { "context": "subtotal price or an order", - "string": "Subtotal" + "string": "å°čŽĄ" }, "src_dot_orders_dot_components_dot_OrderDraftDetailsSummary_dot_878013594": { "context": "total price of an order", @@ -2350,10 +2354,10 @@ }, "src_dot_orders_dot_components_dot_OrderDraftDetails_dot_2528459381": { "context": "button", - "string": "Add products" + "string": "æˇģ加多ä¸Ēäē§å“" }, "src_dot_orders_dot_components_dot_OrderDraftFinalizeDialog_dot_115822814": { - "string": "No billing address" + "string": "æ˛Ąæœ‰č´Ļ单地址" }, "src_dot_orders_dot_components_dot_OrderDraftFinalizeDialog_dot_1161061962": { "context": "dialog header", @@ -2366,7 +2370,7 @@ "string": "There are missing or incorrect informations about this order:" }, "src_dot_orders_dot_components_dot_OrderDraftFinalizeDialog_dot_2430492151": { - "string": "No shipping address" + "string": "无配送地址" }, "src_dot_orders_dot_components_dot_OrderDraftFinalizeDialog_dot_2725265632": { "context": "button", @@ -2391,7 +2395,7 @@ }, "src_dot_orders_dot_components_dot_OrderDraftListPage_dot_551325728": { "context": "tab name", - "string": "All Drafts" + "string": "草į¨ŋįŽą" }, "src_dot_orders_dot_components_dot_OrderDraftListPage_dot_77765281": { "string": "Search Draft" @@ -2405,7 +2409,7 @@ "string": "åŽĸæˆˇ" }, "src_dot_orders_dot_components_dot_OrderDraftList_dot_2177368638": { - "string": "No draft orders found" + "string": "æœĒä옿ŦžčŽĸ单" }, "src_dot_orders_dot_components_dot_OrderDraftList_dot_2889196282": { "string": "No. of Order" @@ -2507,7 +2511,7 @@ }, "src_dot_orders_dot_components_dot_OrderFulfillment_dot_1119771899": { "context": "fulfillment group tracking number", - "string": "Add tracking" + "string": "æˇģ加čŋŊč¸Ē" }, "src_dot_orders_dot_components_dot_OrderFulfillment_dot_1134347598": { "context": "product price", @@ -2532,6 +2536,10 @@ "context": "cancelled fulfillment, section header", "string": "Cancelled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderFulfillment_dot_693960049": { + "context": "ordered product sku", + "string": "åē“存单äŊ" + }, "src_dot_orders_dot_components_dot_OrderFulfillment_dot_732594284": { "context": "button", "string": "Cancel Fulfillment" @@ -2546,7 +2554,7 @@ }, "src_dot_orders_dot_components_dot_OrderHistory_dot_1230178536": { "context": "order history message", - "string": "Order address was updated" + "string": "čŽĸå•åœ°å€åˇ˛æ›´æ–°" }, "src_dot_orders_dot_components_dot_OrderHistory_dot_1521936480": { "context": "order history message", @@ -2578,7 +2586,7 @@ }, "src_dot_orders_dot_components_dot_OrderHistory_dot_2304318421": { "context": "order history message", - "string": "Note was added to the order" + "string": "å¤‡æŗ¨čĸĢæˇģ加到čŽĸ单" }, "src_dot_orders_dot_components_dot_OrderHistory_dot_2369495522": { "context": "order history message", @@ -2656,7 +2664,7 @@ }, "src_dot_orders_dot_components_dot_OrderListPage_dot_875489544": { "context": "tab name", - "string": "All Orders" + "string": "全部čŽĸ单" }, "src_dot_orders_dot_components_dot_OrderListPage_dot_customer": { "context": "order", @@ -2749,6 +2757,10 @@ "context": "order payment", "string": "Outstanding Balance" }, + "src_dot_orders_dot_components_dot_OrderPayment_dot_3720114122": { + "context": "order discount", + "string": "æŠ˜æ‰Ŗ" + }, "src_dot_orders_dot_components_dot_OrderPayment_dot_3768782744": { "context": "order payment", "string": "éĸ„授权金éĸ" @@ -2762,16 +2774,12 @@ }, "src_dot_orders_dot_components_dot_OrderPayment_dot_781550514": { "context": "order subtotal price", - "string": "Subtotal" + "string": "å°čŽĄ" }, "src_dot_orders_dot_components_dot_OrderPayment_dot_878013594": { "context": "order total price", "string": "æ€ģ数" }, - "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_1542417144": { - "context": "dialog header", - "string": "Create Product" - }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2272209368": { "context": "variant sku", "string": "SKU {sku}" @@ -2779,6 +2787,10 @@ "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2336947364": { "string": "Search by product name, attribute, product type etc..." }, + "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2775402904": { + "context": "dialog header", + "string": "Add Product" + }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2850255786": { "string": "Search Products" }, @@ -2809,6 +2821,10 @@ "context": "section header", "string": "Unfulfilled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_693960049": { + "context": "ordered product sku", + "string": "åē“存单äŊ" + }, "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_878013594": { "context": "order line total price", "string": "æ€ģ数" @@ -2838,7 +2854,7 @@ "string": "Order successfully cancelled" }, "src_dot_orders_dot_views_dot_OrderDetails_dot_3178394068": { - "string": "Note successfully added" + "string": "å¤‡æŗ¨æˆåŠŸæˇģ加" }, "src_dot_orders_dot_views_dot_OrderDetails_dot_3280942553": { "string": "Order payment successfully voided" @@ -2898,14 +2914,14 @@ }, "src_dot_pages_dot_components_dot_PageDetailsPage_dot_1068617485": { "context": "page header", - "string": "Create Page" + "string": "新åģēéĄĩéĸ" }, "src_dot_pages_dot_components_dot_PageDetailsPage_dot_1815688500": { "context": "page", "string": "since {date}" }, "src_dot_pages_dot_components_dot_PageDetailsPage_dot_1996767833": { - "string": "Add search engine title and description to make this page easier to find" + "string": "æˇģ加标éĸ˜å’Œæčŋ°äŊŋåž—čŋ™ä¸ĒéĄĩéĸ更厚易čĸĢæœį´ĸåŧ•擎扞到" }, "src_dot_pages_dot_components_dot_PageDetailsPage_dot_2001551496": { "context": "page", @@ -2958,7 +2974,7 @@ }, "src_dot_pages_dot_views_dot_1068617485": { "context": "header", - "string": "Create Page" + "string": "新åģēéĄĩéĸ" }, "src_dot_pages_dot_views_dot_2680158037": { "string": "Successfully created new page" @@ -3033,7 +3049,7 @@ }, "src_dot_permissionGroups_dot_components_dot_AssignMembersDialog_dot_1004218338": { "context": "staff member status", - "string": "Inactive" + "string": "不æ´ģ衃" }, "src_dot_permissionGroups_dot_components_dot_AssignMembersDialog_dot_1731102929": { "context": "button", @@ -3071,7 +3087,7 @@ }, "src_dot_permissionGroups_dot_components_dot_PermissionGroupDeleteDialog_dot_2297471173": { "context": "dialog content", - "string": "Are you sure you want to delete {name}?" + "string": "æ‚¨įĄŽčŽ¤æƒŗčĻåˆ é™¤ {name}?īŧŸ" }, "src_dot_permissionGroups_dot_components_dot_PermissionGroupDeleteDialog_dot_3528974446": { "context": "dialog title", @@ -3105,14 +3121,14 @@ "string": "Members" }, "src_dot_permissionGroups_dot_components_dot_PermissionGroupList_dot_4190792473": { - "string": "Actions" + "string": "动äŊœ" }, "src_dot_permissionGroups_dot_components_dot_PermissionGroupList_dot_425941108": { "string": "No permission groups found" }, "src_dot_permissionGroups_dot_components_dot_PermissionGroupMemberList_dot_1004218338": { "context": "staff member status", - "string": "Inactive" + "string": "不æ´ģ衃" }, "src_dot_permissionGroups_dot_components_dot_PermissionGroupMemberList_dot_136112637": { "context": "empty list message", @@ -3122,7 +3138,7 @@ "string": "No members found" }, "src_dot_permissionGroups_dot_components_dot_PermissionGroupMemberList_dot_1789607185": { - "string": "Email Address" + "string": " į”ĩå­é‚ŽįŽą" }, "src_dot_permissionGroups_dot_components_dot_PermissionGroupMemberList_dot_2457011428": { "context": "button", @@ -3141,7 +3157,7 @@ "string": "Group members" }, "src_dot_permissionGroups_dot_components_dot_PermissionGroupMemberList_dot_4190792473": { - "string": "Actions" + "string": "动äŊœ" }, "src_dot_permissionGroups_dot_components_dot_PermissionGroupMemberList_dot_636461959": { "context": "staff member full name", @@ -3164,7 +3180,7 @@ }, "src_dot_permissionGroups_dot_views_dot_PermissionGroupDetails_dot_870815507": { "context": "button title", - "string": "Unassign" + "string": "取æļˆåˆ†é…" }, "src_dot_permissionGroups_dot_views_dot_PermissionGroupList_dot_92979760": { "string": "Permission Group Deleted" @@ -3194,7 +3210,7 @@ }, "src_dot_plugins_dot_components_dot_PluginSecretFieldDialog_dot_3032939398": { "context": "header", - "string": "Add Value to Authorization Field" + "string": "æˇģ加å€ŧč‡ŗæŽˆæƒåŒē域" }, "src_dot_plugins_dot_components_dot_PluginSecretFieldDialog_dot_4269236107": { "context": "header", @@ -3227,7 +3243,7 @@ }, "src_dot_plugins_dot_components_dot_PluginsListPage_dot_3523826683": { "context": "tab name", - "string": "All Plugins" + "string": "所有插äģļ" }, "src_dot_plugins_dot_components_dot_PluginsListPage_dot_active": { "context": "plugin", @@ -3235,7 +3251,7 @@ }, "src_dot_plugins_dot_components_dot_PluginsListPage_dot_deactivated": { "context": "plugin", - "string": "Inactive" + "string": "不æ´ģ衃" }, "src_dot_plugins_dot_components_dot_PluginsList_dot_3247064221": { "context": "plugin status", @@ -3243,7 +3259,7 @@ }, "src_dot_plugins_dot_components_dot_PluginsList_dot_4120604650": { "context": "user action bar", - "string": "Action" + "string": "动äŊœ" }, "src_dot_plugins_dot_components_dot_PluginsList_dot_636461959": { "context": "plugin name", @@ -3325,7 +3341,7 @@ }, "src_dot_productTypes_dot_components_dot_ProductTypeDeleteDialog_dot_2297471173": { "context": "delete product type", - "string": "Are you sure you want to delete {name}?" + "string": "æ‚¨įĄŽčŽ¤æƒŗčĻåˆ é™¤ {name}?īŧŸ" }, "src_dot_productTypes_dot_components_dot_ProductTypeDeleteDialog_dot_924066985": { "context": "dialog header", @@ -3340,7 +3356,7 @@ }, "src_dot_productTypes_dot_components_dot_ProductTypeListPage_dot_1776073799": { "context": "tab name", - "string": "All Product Types" + "string": "全部äē§å“įąģ型" }, "src_dot_productTypes_dot_components_dot_ProductTypeListPage_dot_3420445375": { "string": "Search Product Type" @@ -3351,7 +3367,7 @@ }, "src_dot_productTypes_dot_components_dot_ProductTypeListPage_dot_configurable": { "context": "product type", - "string": "Configurable" + "string": "可配įŊŽ" }, "src_dot_productTypes_dot_components_dot_ProductTypeListPage_dot_digital": { "context": "product", @@ -3386,7 +3402,7 @@ }, "src_dot_productTypes_dot_components_dot_ProductTypeList_dot_2754779425": { "context": "product type", - "string": "Configurable" + "string": "可配įŊŽ" }, "src_dot_productTypes_dot_components_dot_ProductTypeList_dot_881286562": { "context": "product type", @@ -3426,7 +3442,7 @@ }, "src_dot_productTypes_dot_views_dot_ProductTypeUpdate_dot_870815507": { "context": "unassign attribute from product type, button", - "string": "Unassign" + "string": "取æļˆåˆ†é…" }, "src_dot_products": { "context": "products section name", @@ -3467,7 +3483,7 @@ "string": "will be visible from {date}" }, "src_dot_products_dot_components_dot_ProductCreatePage_dot_2706108815": { - "string": "Add search engine title and description to make this product easier to find" + "string": "æˇģ加标éĸ˜å’Œæčŋ°äŊŋåž—čŋ™ä¸Ēäē§å“æ›´åŽšæ˜“čĸĢæœį´ĸåŧ•擎扞到" }, "src_dot_products_dot_components_dot_ProductDetailsForm_dot_636461959": { "context": "product name", @@ -3475,11 +3491,11 @@ }, "src_dot_products_dot_components_dot_ProductImageNavigation_dot_3060635772": { "context": "section header", - "string": "All Photos" + "string": "æ‰€æœ‰į…§į‰‡" }, "src_dot_products_dot_components_dot_ProductImagePage_dot_1905082483": { "context": "field is optional", - "string": "Optional" + "string": "可选" }, "src_dot_products_dot_components_dot_ProductImagePage_dot_2546267317": { "context": "header", @@ -3503,7 +3519,7 @@ }, "src_dot_products_dot_components_dot_ProductListPage_dot_1542417144": { "context": "button", - "string": "Create Product" + "string": "新åģēäē§å“" }, "src_dot_products_dot_components_dot_ProductListPage_dot_1952810469": { "context": "product type", @@ -3518,15 +3534,15 @@ }, "src_dot_products_dot_components_dot_ProductListPage_dot_821159718": { "context": "tab name", - "string": "All Products" + "string": "全部äē§å“" }, "src_dot_products_dot_components_dot_ProductListPage_dot_available": { "context": "product status", - "string": "Available" + "string": "å¯į”¨" }, "src_dot_products_dot_components_dot_ProductListPage_dot_hidden": { "context": "product is hidden", - "string": "Hidden" + "string": "隐藏" }, "src_dot_products_dot_components_dot_ProductListPage_dot_outOfStock": { "context": "product status", @@ -3552,7 +3568,7 @@ "string": "ä쎿 ŧ" }, "src_dot_products_dot_components_dot_ProductList_dot_1657559629": { - "string": "No products found" + "string": "æ˛Ąæœ‰äē§å“" }, "src_dot_products_dot_components_dot_ProductList_dot_1952810469": { "context": "product type", @@ -3586,11 +3602,11 @@ }, "src_dot_products_dot_components_dot_ProductOrganization_dot_2754779425": { "context": "product is configurable", - "string": "Configurable" + "string": "可配įŊŽ" }, "src_dot_products_dot_components_dot_ProductOrganization_dot_2805838453": { "context": "field is optional", - "string": "*Optional. Adding product to collection helps users find it." + "string": "*可选.æˇģ加äē§å“č‡ŗįŗģåˆ—å¸ŽåŠŠį”¨æˆˇæ‰žåˆ°åŽƒ" }, "src_dot_products_dot_components_dot_ProductOrganization_dot_4257289053": { "string": "Product Type" @@ -3621,17 +3637,14 @@ "context": "header", "string": "数量" }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3143542809": { - "string": "This product doesn't have any stock. You can add it here." - }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3482985373": { - "context": "button", - "string": "Edit Warehouses" - }, "src_dot_products_dot_components_dot_ProductStocks_dot_3633706025": { "context": "product inventory, checkbox", "string": "Track Inventory" }, + "src_dot_products_dot_components_dot_ProductStocks_dot_3857433664": { + "context": "button", + "string": "Assign Warehouse" + }, "src_dot_products_dot_components_dot_ProductStocks_dot_849869830": { "string": "Active inventory tracking will automatically calculate changes of stock" }, @@ -3644,11 +3657,11 @@ "string": "will be visible from {date}" }, "src_dot_products_dot_components_dot_ProductUpdatePage_dot_2706108815": { - "string": "Add search engine title and description to make this product easier to find" + "string": "æˇģ加标éĸ˜å’Œæčŋ°äŊŋåž—čŋ™ä¸Ēäē§å“æ›´åŽšæ˜“čĸĢæœį´ĸåŧ•擎扞到" }, "src_dot_products_dot_components_dot_ProductVariantAttributes_dot_1536841622": { "context": "product attribute error", - "string": "All attributes should have value" + "string": "æ‰€æœ‰åąžæ€§ä¸čƒŊä¸ēįŠē" }, "src_dot_products_dot_components_dot_ProductVariantAttributes_dot_258966189": { "context": "product attribute error", @@ -3695,7 +3708,7 @@ }, "src_dot_products_dot_components_dot_ProductVariantCreatorPage_dot_2670525734": { "context": "variant attribute", - "string": "Choose attribute" + "string": "é€‰æ‹Šåąžæ€§" }, "src_dot_products_dot_components_dot_ProductVariantCreatorPage_dot_2745385064": { "context": "variant creation step", @@ -3758,7 +3771,7 @@ }, "src_dot_products_dot_components_dot_ProductVariantDeleteDialog_dot_2297471173": { "context": "delete product variant", - "string": "Are you sure you want to delete {name}?" + "string": "æ‚¨įĄŽčŽ¤æƒŗčĻåˆ é™¤ {name}?īŧŸ" }, "src_dot_products_dot_components_dot_ProductVariantDeleteDialog_dot_3726089650": { "context": "dialog header", @@ -3777,7 +3790,7 @@ }, "src_dot_products_dot_components_dot_ProductVariantImages_dot_989683980": { "context": "button", - "string": "Choose photos" + "string": "é€‰æ‹Šå›žį‰‡" }, "src_dot_products_dot_components_dot_ProductVariantNavigation_dot_2153006789": { "context": "section header", @@ -3842,7 +3855,7 @@ }, "src_dot_products_dot_components_dot_ProductVariants_dot_3490038570": { "context": "product variant inventory status", - "string": "Inventory" + "string": "åē“å­˜" }, "src_dot_products_dot_components_dot_ProductVariants_dot_3989383405": { "context": "button", @@ -3859,16 +3872,9 @@ "context": "product variant name", "string": "å˜į§" }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_3482985373": { - "context": "dialog header", - "string": "Edit Warehouses" - }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_4112406382": { - "string": "Select warehouses that stock selected product" - }, "src_dot_products_dot_views_dot_1542417144": { "context": "window title", - "string": "Create Product" + "string": "新åģēäē§å“" }, "src_dot_products_dot_views_dot_1591632382": { "context": "page header", @@ -3937,7 +3943,7 @@ }, "src_dot_products_dot_views_dot_ProductUpdate_dot_2297471173": { "context": "delete product", - "string": "Are you sure you want to delete {name}?" + "string": "æ‚¨įĄŽčŽ¤æƒŗčĻåˆ é™¤ {name}?īŧŸ" }, "src_dot_products_dot_views_dot_ProductUpdate_dot_4108890645": { "string": "Product removed" @@ -4000,7 +4006,7 @@ }, "src_dot_services_dot_components_dot_ServiceCreatePage_dot_248507553": { "context": "header", - "string": "Create New Account" + "string": "新åģēį”¨æˆˇ" }, "src_dot_services_dot_components_dot_ServiceCreatePage_dot_27827485": { "context": "checkbox label", @@ -4018,11 +4024,11 @@ }, "src_dot_services_dot_components_dot_ServiceDefaultToken_dot_2864204643": { "context": "button", - "string": "Copied" + "string": "åˇ˛å¤åˆļ" }, "src_dot_services_dot_components_dot_ServiceDefaultToken_dot_3406541221": { "context": "button", - "string": "Copy token" + "string": "复åˆļ" }, "src_dot_services_dot_components_dot_ServiceDefaultToken_dot_4189999598": { "string": "We’ve created your default token. Make sure to copy your new personal access token now. You won’t be able to see it again." @@ -4033,7 +4039,7 @@ }, "src_dot_services_dot_components_dot_ServiceDeleteDialog_dot_2297471173": { "context": "delete service account", - "string": "Are you sure you want to delete {name}?" + "string": "æ‚¨įĄŽčŽ¤æƒŗčĻåˆ é™¤ {name}?īŧŸ" }, "src_dot_services_dot_components_dot_ServiceDetailsPage_dot_1848599267": { "context": "checkbox label", @@ -4049,7 +4055,7 @@ }, "src_dot_services_dot_components_dot_ServiceInfo_dot_3789449123": { "context": "service account", - "string": "Account Name" + "string": "į”¨æˆˇå" }, "src_dot_services_dot_components_dot_ServiceInfo_dot_426959482": { "context": "header", @@ -4060,7 +4066,7 @@ }, "src_dot_services_dot_components_dot_ServiceListPage_dot_4040605455": { "context": "tab name", - "string": "All Service Accounts" + "string": "å…¨éƒ¨æœåŠĄč´Ļåˇ" }, "src_dot_services_dot_components_dot_ServiceListPage_dot_624280156": { "context": "button", @@ -4072,7 +4078,7 @@ }, "src_dot_services_dot_components_dot_ServiceListPage_dot_deactivated": { "context": "service account", - "string": "Inactive" + "string": "不æ´ģ衃" }, "src_dot_services_dot_components_dot_ServiceList_dot_1342308051": { "string": "No service accounts found" @@ -4100,7 +4106,7 @@ }, "src_dot_services_dot_components_dot_ServiceTokenCreateDialog_dot_3406541221": { "context": "button", - "string": "Copy token" + "string": "复åˆļ" }, "src_dot_services_dot_components_dot_ServiceTokenCreateDialog_dot_3875340101": { "context": "header", @@ -4137,7 +4143,7 @@ }, "src_dot_services_dot_components_dot_ServiceTokens_dot_4190792473": { "context": "table actions", - "string": "Actions" + "string": "动äŊœ" }, "src_dot_services_dot_components_dot_ServiceTokens_dot_426959482": { "context": "header", @@ -4147,6 +4153,9 @@ "context": "window title", "string": "Create Service Account" }, + "src_dot_sessionExpired": { + "string": "Your session has expired. Please log in again to continue." + }, "src_dot_shipping": { "context": "shipping section name", "string": "Shipping Methods" @@ -4202,7 +4211,7 @@ }, "src_dot_shipping_dot_components_dot_ShippingZoneCreatePage_dot_4049462680": { "context": "header", - "string": "Create New Shipping Zone" + "string": "新åģēæ–°įš„配送åŒē域" }, "src_dot_shipping_dot_components_dot_ShippingZoneCreatePage_dot_4270729636": { "string": "This is default shipping zone, which means that it covers all of the countries which are not assigned to other shipping zones" @@ -4230,7 +4239,7 @@ }, "src_dot_shipping_dot_components_dot_ShippingZoneRateDialog_dot_1397795758": { "context": "add weight based shipping method, dialog header", - "string": "Add Weight Rate" + "string": "æˇģ加每å…Ŧ斤æ”ļč´š" }, "src_dot_shipping_dot_components_dot_ShippingZoneRateDialog_dot_1403365734": { "context": "shipping method price", @@ -4264,7 +4273,7 @@ }, "src_dot_shipping_dot_components_dot_ShippingZoneRateDialog_dot_2892088870": { "context": "dialog header", - "string": "Add Price Rate" + "string": "æˇģ加äŧ˜æƒ åˆŠįއ" }, "src_dot_shipping_dot_components_dot_ShippingZoneRateDialog_dot_3213611593": { "context": "shipping method", @@ -4336,7 +4345,7 @@ }, "src_dot_shipping_dot_components_dot_ShippingZoneWarehouses_dot_1221560277": { "context": "section header", - "string": "Warehouse" + "string": "č´§äģ“" }, "src_dot_shipping_dot_components_dot_ShippingZoneWarehouses_dot_2304484478": { "context": "button", @@ -4427,7 +4436,7 @@ }, "src_dot_siteSettings_dot_components_dot_SiteSettingsKeyDialog_dot_1238948746": { "context": "dialog header", - "string": "Add New Authorization Key" + "string": "æˇģåŠ æ–°įš„æŽˆæƒå¯†é’Ĩ" }, "src_dot_siteSettings_dot_components_dot_SiteSettingsKeyDialog_dot_2237029987": { "string": "坆᠁" @@ -4442,11 +4451,11 @@ }, "src_dot_siteSettings_dot_components_dot_SiteSettingsKeyDialog_dot_50561933": { "context": "button", - "string": "Add authentication" + "string": "æˇģåŠ čŽ¤č¯" }, "src_dot_siteSettings_dot_components_dot_SiteSettingsKeys_dot_1114030884": { "context": "button", - "string": "Add key" + "string": "æˇģ加锎" }, "src_dot_siteSettings_dot_components_dot_SiteSettingsKeys_dot_1270286507": { "context": "authentication provider name", @@ -4473,7 +4482,7 @@ }, "src_dot_siteSettings_dot_components_dot_SiteSettingsMailing_dot_280712237": { "context": "section header", - "string": "Mailing Configuration" + "string": "邮äģļ配įŊŽ" }, "src_dot_siteSettings_dot_components_dot_SiteSettingsMailing_dot_297689661": { "string": "Configurate your email address from which all automatic emails will be sent to your customers." @@ -4502,11 +4511,11 @@ }, "src_dot_siteSettings_dot_components_dot_SiteSettingsPage_dot_2768400497": { "context": "section header", - "string": "Company Information" + "string": "å…Ŧ司äŋĄæ¯" }, "src_dot_siteSettings_dot_components_dot_SiteSettingsPage_dot_280712237": { "context": "section header", - "string": "Mailing Configuration" + "string": "邮äģļ配įŊŽ" }, "src_dot_siteSettings_dot_components_dot_SiteSettingsPage_dot_3657173399": { "string": "Email adress you provide here will be used as a contact adress for your customers." @@ -4550,7 +4559,7 @@ }, "src_dot_staff_dot_components_dot_StaffListPage_dot_2852350932": { "context": "tab name", - "string": "All Staff Members" + "string": "全部员åˇĨ" }, "src_dot_staff_dot_components_dot_StaffListPage_dot_61043583": { "string": "Search Staff Member" @@ -4573,10 +4582,10 @@ }, "src_dot_staff_dot_components_dot_StaffList_dot_1004218338": { "context": "staff member status", - "string": "Inactive" + "string": "不æ´ģ衃" }, "src_dot_staff_dot_components_dot_StaffList_dot_1789607185": { - "string": "Email Address" + "string": " į”ĩå­é‚ŽįŽą" }, "src_dot_staff_dot_components_dot_StaffList_dot_3247064221": { "context": "staff member status", @@ -4609,7 +4618,7 @@ }, "src_dot_staff_dot_components_dot_StaffPassword_dot_1434811103": { "context": "button", - "string": "Change your password" + "string": "äŋŽæ”šå¯†į " }, "src_dot_staff_dot_components_dot_StaffPassword_dot_2237029987": { "context": "header", @@ -4634,7 +4643,7 @@ }, "src_dot_staff_dot_components_dot_StaffProperties_dot_2771097267": { "context": "button", - "string": "Change photo" + "string": "更æĸå›žį‰‡" }, "src_dot_staff_dot_components_dot_StaffProperties_dot_457748370": { "context": "button", @@ -4681,14 +4690,14 @@ "string": "Reduced Tax Rates" }, "src_dot_taxes_dot_components_dot_CountryList_dot_4039455144": { - "string": "Country Code" + "string": "å›ŊåŽļäģŖį " }, "src_dot_taxes_dot_components_dot_CountryList_dot_577035076": { - "string": "Country Name" + "string": "å›ŊåŽļ名字" }, "src_dot_taxes_dot_components_dot_CountryTaxesPage_dot_1040021611": { "context": "tax rate", - "string": "Accommodation" + "string": "äŊå¤„" }, "src_dot_taxes_dot_components_dot_CountryTaxesPage_dot_1260218997": { "context": "tax rate", @@ -4696,7 +4705,7 @@ }, "src_dot_taxes_dot_components_dot_CountryTaxesPage_dot_1323923780": { "context": "tax rate", - "string": "Bikes" + "string": "单čŊĻ" }, "src_dot_taxes_dot_components_dot_CountryTaxesPage_dot_1451721797": { "context": "tax rate", @@ -4714,7 +4723,7 @@ }, "src_dot_taxes_dot_components_dot_CountryTaxesPage_dot_2201910191": { "context": "tax rate", - "string": "Baby foodstuffs" + "string": "労å„ŋéŖŸį‰Š" }, "src_dot_taxes_dot_components_dot_CountryTaxesPage_dot_231341634": { "context": "tax rate", @@ -4726,11 +4735,11 @@ }, "src_dot_taxes_dot_components_dot_CountryTaxesPage_dot_2394675125": { "context": "tax rate", - "string": "Books" + "string": "äšĻįą" }, "src_dot_taxes_dot_components_dot_CountryTaxesPage_dot_2465450918": { "context": "tax rate", - "string": "Agricultural supplies" + "string": "农业䞛įģ™" }, "src_dot_taxes_dot_components_dot_CountryTaxesPage_dot_2482229874": { "context": "tax rate", @@ -4746,7 +4755,7 @@ }, "src_dot_taxes_dot_components_dot_CountryTaxesPage_dot_2584490289": { "context": "tax rate", - "string": "Children's clothing" + "string": "įĢĨčĄĢ" }, "src_dot_taxes_dot_components_dot_CountryTaxesPage_dot_2616794607": { "context": "tax rate", @@ -4765,7 +4774,7 @@ }, "src_dot_taxes_dot_components_dot_CountryTaxesPage_dot_331632763": { "context": "tax rate", - "string": "Hotels" + "string": "酒åē—" }, "src_dot_taxes_dot_components_dot_CountryTaxesPage_dot_331757068": { "context": "tax rate", @@ -4781,7 +4790,7 @@ }, "src_dot_taxes_dot_components_dot_CountryTaxesPage_dot_3911019760": { "context": "tax rate", - "string": "Advertising" + "string": "åšŋ告" }, "src_dot_taxes_dot_components_dot_CountryTaxesPage_dot_4199760668": { "context": "tax rate", @@ -4800,7 +4809,7 @@ "string": "Pharmaceuticals" }, "src_dot_taxes_dot_components_dot_TaxConfiguration_dot_142803418": { - "string": "All products prices are entered with tax included" + "string": "æ‰€æœ‰å•†å“įš„ä쎿 ŧåˇ˛åŒ…åĢį¨Ž" }, "src_dot_taxes_dot_components_dot_TaxConfiguration_dot_2102582640": { "string": "Show gross prices to customers in the storefront" @@ -4836,7 +4845,7 @@ "string": "No translation yet" }, "src_dot_translations_dot_components_dot_TranslationsCategoriesPage_dot_1214235329": { - "string": "Category Name" + "string": "分įąģ名" }, "src_dot_translations_dot_components_dot_TranslationsCategoriesPage_dot_1406947243": { "string": "Search Engine Description" @@ -4857,7 +4866,7 @@ "string": "Search Engine Title" }, "src_dot_translations_dot_components_dot_TranslationsCollectionsPage_dot_2759199473": { - "string": "Collection Name" + "string": "įŗģ列名" }, "src_dot_translations_dot_components_dot_TranslationsCollectionsPage_dot_3055443821": { "context": "header", @@ -4867,7 +4876,7 @@ "string": "Search Engine Preview" }, "src_dot_translations_dot_components_dot_TranslationsEntitiesListPage_dot_1163855804": { - "string": "Languages" + "string": "蝭荀" }, "src_dot_translations_dot_components_dot_TranslationsEntitiesListPage_dot_1866913828": { "string": "Search Sale" @@ -4923,20 +4932,20 @@ "string": "No translatable entities found" }, "src_dot_translations_dot_components_dot_TranslationsEntitiesList_dot_49462429": { - "string": "Completed Translations" + "string": "厌整įŋģ蝑" }, "src_dot_translations_dot_components_dot_TranslationsEntitiesList_dot_636461959": { "context": "entity (product, collection, shipping method) name", "string": "名字" }, "src_dot_translations_dot_components_dot_TranslationsLanguageListPage_dot_1163855804": { - "string": "Languages" + "string": "蝭荀" }, "src_dot_translations_dot_components_dot_TranslationsLanguageList_dot_2966651157": { "string": "No languages found" }, "src_dot_translations_dot_components_dot_TranslationsLanguageList_dot_604081953": { - "string": "Language" + "string": "蝭荀" }, "src_dot_translations_dot_components_dot_TranslationsPagesPage_dot_1116746286": { "context": "page content", @@ -5149,11 +5158,11 @@ }, "src_dot_warehouses": { "context": "warehouses section name", - "string": "Warehouses" + "string": "č´§äģ“" }, "src_dot_warehouses_dot_components_dot_WarehouseCreatePage_dot_1967111456": { "context": "warehouse", - "string": "Address Information" + "string": "地址äŋĄæ¯" }, "src_dot_warehouses_dot_components_dot_WarehouseCreatePage_dot_934572530": { "context": "header", @@ -5169,7 +5178,7 @@ }, "src_dot_warehouses_dot_components_dot_WarehouseDetailsPage_dot_1967111456": { "context": "warehouse", - "string": "Address Information" + "string": "地址äŋĄæ¯" }, "src_dot_warehouses_dot_components_dot_WarehouseInfo_dot_2622674857": { "string": "Warehouse Name" @@ -5192,7 +5201,7 @@ "string": "No warehouses found" }, "src_dot_warehouses_dot_components_dot_WarehouseList_dot_4190792473": { - "string": "Actions" + "string": "动äŊœ" }, "src_dot_warehouses_dot_components_dot_WarehouseList_dot_636461959": { "context": "warehouse", @@ -5223,7 +5232,7 @@ }, "src_dot_webhooks_dot_components_dot_WebhookDeleteDialog_dot_2297471173": { "context": "delete webhook", - "string": "Are you sure you want to delete {name}?" + "string": "æ‚¨įĄŽčŽ¤æƒŗčĻåˆ é™¤ {name}?īŧŸ" }, "src_dot_webhooks_dot_components_dot_WebhookDeleteDialog_dot_3514087611": { "context": "dialog header", @@ -5239,7 +5248,7 @@ }, "src_dot_webhooks_dot_components_dot_WebhookEvents_dot_2454751033": { "context": "event", - "string": "All events" + "string": "全部äē‹äģļ" }, "src_dot_webhooks_dot_components_dot_WebhookEvents_dot_2899821092": { "context": "event", @@ -5337,7 +5346,7 @@ }, "src_dot_webhooks_dot_components_dot_WebhooksListPage_dot_3300314452": { "context": "tab name", - "string": "All Webhooks" + "string": "所有Webhooks" }, "src_dot_webhooks_dot_components_dot_WebhooksListPage_dot_active": { "context": "webhook", @@ -5345,7 +5354,7 @@ }, "src_dot_webhooks_dot_components_dot_WebhooksListPage_dot_inactive": { "context": "webhook", - "string": "Inactive" + "string": "不æ´ģ衃" }, "src_dot_webhooks_dot_components_dot_WebhooksList_dot_1153324159": { "string": "No webhooks found" @@ -5356,7 +5365,7 @@ }, "src_dot_webhooks_dot_components_dot_WebhooksList_dot_4120604650": { "context": "user action bar", - "string": "Action" + "string": "动äŊœ" }, "src_dot_webhooks_dot_components_dot_WebhooksList_dot_618422799": { "string": "Unnamed webhook" @@ -5374,14 +5383,14 @@ }, "voucherDetailsUnassignCategory": { "context": "unassign category from voucher, button", - "string": "Unassign" + "string": "取æļˆåˆ†é…" }, "voucherDetailsUnassignCollection": { "context": "unassign collection from voucher, button", - "string": "Unassign" + "string": "取æļˆåˆ†é…" }, "voucherDetailsUnassignProduct": { "context": "unassign product from voucher, button", - "string": "Unassign" + "string": "取æļˆåˆ†é…" } } \ No newline at end of file diff --git a/locale/zh-Hant.json b/locale/zh-Hant.json index 41b86f20c..1e229ddf4 100644 --- a/locale/zh-Hant.json +++ b/locale/zh-Hant.json @@ -250,7 +250,7 @@ "context": "optional field", "string": "Optional" }, - "productVariantPriceOptionalPriceOverrideField": { + "productVariantPriceOptionalPriceField": { "context": "optional field", "string": "Optional" }, @@ -1675,6 +1675,10 @@ "context": "button", "string": "Delete" }, + "src_dot_demo": { + "context": "notification message after log in", + "string": "Just to let you know... You're in demo mode. You can play around with the dashboard but can't save changes." + }, "src_dot_description": { "string": "描čŋ°" }, @@ -2532,6 +2536,10 @@ "context": "cancelled fulfillment, section header", "string": "Cancelled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderFulfillment_dot_693960049": { + "context": "ordered product sku", + "string": "åēĢ存喎äŊ" + }, "src_dot_orders_dot_components_dot_OrderFulfillment_dot_732594284": { "context": "button", "string": "Cancel Fulfillment" @@ -2749,6 +2757,10 @@ "context": "order payment", "string": "Outstanding Balance" }, + "src_dot_orders_dot_components_dot_OrderPayment_dot_3720114122": { + "context": "order discount", + "string": "Discount" + }, "src_dot_orders_dot_components_dot_OrderPayment_dot_3768782744": { "context": "order payment", "string": "預先授æŦŠé‡‘額" @@ -2768,10 +2780,6 @@ "context": "order total price", "string": "Total" }, - "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_1542417144": { - "context": "dialog header", - "string": "Create Product" - }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2272209368": { "context": "variant sku", "string": "SKU {sku}" @@ -2779,6 +2787,10 @@ "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2336947364": { "string": "Search by product name, attribute, product type etc..." }, + "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2775402904": { + "context": "dialog header", + "string": "Add Product" + }, "src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2850255786": { "string": "Search Products" }, @@ -2809,6 +2821,10 @@ "context": "section header", "string": "Unfulfilled ({quantity})" }, + "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_693960049": { + "context": "ordered product sku", + "string": "åēĢ存喎äŊ" + }, "src_dot_orders_dot_components_dot_OrderUnfulfilledItems_dot_878013594": { "context": "order line total price", "string": "Total" @@ -3621,17 +3637,14 @@ "context": "header", "string": "åēĢ存" }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3143542809": { - "string": "This product doesn't have any stock. You can add it here." - }, - "src_dot_products_dot_components_dot_ProductStocks_dot_3482985373": { - "context": "button", - "string": "Edit Warehouses" - }, "src_dot_products_dot_components_dot_ProductStocks_dot_3633706025": { "context": "product inventory, checkbox", "string": "Track Inventory" }, + "src_dot_products_dot_components_dot_ProductStocks_dot_3857433664": { + "context": "button", + "string": "Assign Warehouse" + }, "src_dot_products_dot_components_dot_ProductStocks_dot_849869830": { "string": "Active inventory tracking will automatically calculate changes of stock" }, @@ -3859,13 +3872,6 @@ "context": "product variant name", "string": "č¤‡åˆåŧ" }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_3482985373": { - "context": "dialog header", - "string": "Edit Warehouses" - }, - "src_dot_products_dot_components_dot_ProductWarehousesDialog_dot_4112406382": { - "string": "Select warehouses that stock selected product" - }, "src_dot_products_dot_views_dot_1542417144": { "context": "window title", "string": "Create Product" @@ -4147,6 +4153,9 @@ "context": "window title", "string": "Create Service Account" }, + "src_dot_sessionExpired": { + "string": "Your session has expired. Please log in again to continue." + }, "src_dot_shipping": { "context": "shipping section name", "string": "Shipping Methods" diff --git a/package-lock.json b/package-lock.json index c4de74a1b..2cfb06a3a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "saleor-dashboard", - "version": "2.10.1", + "version": "2.11.0-a.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -1813,6 +1813,142 @@ "minimist": "^1.2.0" } }, + "@cypress/listr-verbose-renderer": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@cypress/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz", + "integrity": "sha1-p3SS9LEdzHxEajSz4ochr9M8ZCo=", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "cli-cursor": "^1.0.2", + "date-fns": "^1.27.2", + "figures": "^1.7.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "cli-cursor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", + "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", + "dev": true, + "requires": { + "restore-cursor": "^1.0.1" + } + }, + "onetime": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", + "dev": true + }, + "restore-cursor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", + "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "dev": true, + "requires": { + "exit-hook": "^1.0.0", + "onetime": "^1.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "@cypress/request": { + "version": "2.88.5", + "resolved": "https://registry.npmjs.org/@cypress/request/-/request-2.88.5.tgz", + "integrity": "sha512-TzEC1XMi1hJkywWpRfD2clreTa/Z+lOrXDCxxBTBPEcY5azdPi56A6Xw+O4tWJnaJH3iIE7G5aDXZC6JgRZLcA==", + "dev": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "dependencies": { + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true + } + } + }, + "@cypress/xvfb": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@cypress/xvfb/-/xvfb-1.2.4.tgz", + "integrity": "sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q==", + "dev": true, + "requires": { + "debug": "^3.1.0", + "lodash.once": "^4.1.1" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, "@emotion/cache": { "version": "10.0.19", "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-10.0.19.tgz", @@ -1967,6 +2103,52 @@ "resolved": "https://registry.npmjs.org/@formatjs/intl-utils/-/intl-utils-1.4.0.tgz", "integrity": "sha512-z5HyJumGzORM+5SpvkAlp/hu0AHDeZcUNKSmj9NjS7kWxOGZMuAdS3X1K5XiE0j5I8r8s8SIaz0IQOdMA1WFeA==" }, + "@hapi/address": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@hapi/address/-/address-2.1.4.tgz", + "integrity": "sha512-QD1PhQk+s31P1ixsX0H0Suoupp3VMXzIVMSwobR3F3MSUO2YCV0B7xqLcUw/Bh8yuvd3LhpyqLQWTNcRmp6IdQ==", + "dev": true + }, + "@hapi/formula": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@hapi/formula/-/formula-1.2.0.tgz", + "integrity": "sha512-UFbtbGPjstz0eWHb+ga/GM3Z9EzqKXFWIbSOFURU0A/Gku0Bky4bCk9/h//K2Xr3IrCfjFNhMm4jyZ5dbCewGA==", + "dev": true + }, + "@hapi/hoek": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-8.5.1.tgz", + "integrity": "sha512-yN7kbciD87WzLGc5539Tn0sApjyiGHAJgKvG9W8C7O+6c7qmoQMfVs0W4bX17eqz6C78QJqqFrtgdK5EWf6Qow==", + "dev": true + }, + "@hapi/joi": { + "version": "16.1.8", + "resolved": "https://registry.npmjs.org/@hapi/joi/-/joi-16.1.8.tgz", + "integrity": "sha512-wAsVvTPe+FwSrsAurNt5vkg3zo+TblvC5Bb1zMVK6SJzZqw9UrJnexxR+76cpePmtUZKHAPxcQ2Bf7oVHyahhg==", + "dev": true, + "requires": { + "@hapi/address": "^2.1.2", + "@hapi/formula": "^1.2.0", + "@hapi/hoek": "^8.2.4", + "@hapi/pinpoint": "^1.0.2", + "@hapi/topo": "^3.1.3" + } + }, + "@hapi/pinpoint": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@hapi/pinpoint/-/pinpoint-1.0.2.tgz", + "integrity": "sha512-dtXC/WkZBfC5vxscazuiJ6iq4j9oNx1SHknmIr8hofarpKUZKmlUVYVIhNVzIEgK5Wrc4GMHL5lZtt1uS2flmQ==", + "dev": true + }, + "@hapi/topo": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-3.1.6.tgz", + "integrity": "sha512-tAag0jEcjwH+P2quUfipd7liWCNX2F8NvYjQp2wtInsZxnMlypdw0FtAOLxtvvkO+GSRRbmNi8m/5y42PQJYCQ==", + "dev": true, + "requires": { + "@hapi/hoek": "^8.3.0" + } + }, "@jest/console": { "version": "24.9.0", "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz", @@ -2540,6 +2722,106 @@ "resolved": "https://registry.npmjs.org/@oclif/screen/-/screen-1.0.4.tgz", "integrity": "sha512-60CHpq+eqnTxLZQ4PGHYNwUX572hgpMHGPtTWMjdTMsAvlm69lZV/4ly6O3sAYkomo4NggGcomrDpBe34rxUqw==" }, + "@pollyjs/adapter": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@pollyjs/adapter/-/adapter-4.3.0.tgz", + "integrity": "sha512-8/kELw/esDY+Mi6xiYRSX3EHKoVmPeqjRYk7DHFbHhXoMs6ENrPS0ay8Ajl0KHppAnutTk4YLqaI/3VqFCR5iw==", + "dev": true, + "requires": { + "@pollyjs/utils": "^4.3.0" + } + }, + "@pollyjs/adapter-node-http": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@pollyjs/adapter-node-http/-/adapter-node-http-4.3.0.tgz", + "integrity": "sha512-13LC4/9a6rv8Av0qMM2k+MhVm9Txxai8aLZQabX0XTbnY9e+4yxeIdBC96HAgzmHqWlq30r8Tkgypu3agiKA9w==", + "dev": true, + "requires": { + "@pollyjs/adapter": "^4.3.0", + "@pollyjs/utils": "^4.3.0", + "lodash-es": "^4.17.11", + "nock": "^12.0.3" + } + }, + "@pollyjs/core": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@pollyjs/core/-/core-4.3.0.tgz", + "integrity": "sha512-8Fs0Lg19P39oO/GvzWoC/fkckrCSx9rL5DPmU4Ez/Q+WXnDzmWtHI1x/jmD+jv5JLc2ig/ueWugIpE0f9eZbAQ==", + "dev": true, + "requires": { + "@pollyjs/utils": "^4.3.0", + "@sindresorhus/fnv1a": "^1.2.0", + "blueimp-md5": "^2.10.0", + "fast-json-stable-stringify": "^2.0.0", + "is-absolute-url": "^3.0.0", + "lodash-es": "^4.17.11", + "route-recognizer": "^0.3.4", + "slugify": "^1.3.4" + } + }, + "@pollyjs/node-server": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@pollyjs/node-server/-/node-server-4.3.0.tgz", + "integrity": "sha512-pGrX889RkJXleW7p1cMKJqEtuasABbosneU9VrHOUYOMlYnObIOTt5y/n3m0NMAh9SyyusgqC7yQ18/PnMCgfg==", + "dev": true, + "requires": { + "@pollyjs/utils": "^4.3.0", + "body-parser": "^1.19.0", + "cors": "^2.8.5", + "express": "^4.17.1", + "fs-extra": "^8.0.1", + "http-graceful-shutdown": "^2.3.1", + "morgan": "^1.9.1", + "nocache": "^2.1.0" + }, + "dependencies": { + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + } + } + }, + "@pollyjs/persister": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@pollyjs/persister/-/persister-4.3.0.tgz", + "integrity": "sha512-oKTl++rZdT/5tMoeHMsgUAHjnRf/4qLNv7kc7u8ddldjgZ4eDAIWlG6BwFkhDxjhV+ofVlnLxFnRjmK4qrrmqA==", + "dev": true, + "requires": { + "@pollyjs/utils": "^4.3.0", + "bowser": "^2.4.0", + "fast-json-stable-stringify": "^2.0.0", + "lodash-es": "^4.17.11", + "set-cookie-parser": "^2.3.5", + "utf8-byte-length": "^1.0.4" + } + }, + "@pollyjs/persister-fs": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@pollyjs/persister-fs/-/persister-fs-4.3.0.tgz", + "integrity": "sha512-2DUIyl/3mr5F1Orq6bnpW6Witz2I8ulMGsqCFrlh4LaA4DlSg2SwOv88bbjzMCfqGP1CN3U5Zu8o7tZlFxkd8w==", + "dev": true, + "requires": { + "@pollyjs/node-server": "^4.3.0", + "@pollyjs/persister": "^4.3.0" + } + }, + "@pollyjs/utils": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@pollyjs/utils/-/utils-4.3.0.tgz", + "integrity": "sha512-8BYWtP4nK6mAlDgZQ8j2+EZjQH2beoHaHnZDyG7GdspOLeILtXhHLeAxp371YSKN387t7OEBS0nIQSMppHuTQg==", + "dev": true, + "requires": { + "qs": "^6.7.0", + "url-parse": "^1.4.7" + } + }, "@reach/router": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@reach/router/-/router-1.2.1.tgz", @@ -2553,6 +2835,31 @@ "warning": "^3.0.0" } }, + "@saleor/macaw-ui": { + "version": "0.1.1-9", + "resolved": "https://registry.npmjs.org/@saleor/macaw-ui/-/macaw-ui-0.1.1-9.tgz", + "integrity": "sha512-ryftb0jBs1ghIm4ILwJZ7vfQt90Kab9XlNcEUh4JFDV4+HEABrGpwstLKyCtIjFDzxQf/z9L4vbW25o1m6klmg==", + "requires": { + "@types/react-inlinesvg": "^0.8.1", + "classnames": "^2.2.6", + "downshift": "^1.31.16", + "lodash-es": "^4.17.15", + "react-helmet": "^5.2.1", + "react-inlinesvg": "^1.1.2", + "string-similarity": "^1.2.2" + }, + "dependencies": { + "react-inlinesvg": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/react-inlinesvg/-/react-inlinesvg-1.2.0.tgz", + "integrity": "sha512-IsznU+UzpUwDGzBWbf0bfSRA5Jbqz87xeoqLM/nSIDPkoHksInF1wCGybTSn4sIui+30TqboRQP1wAelNTkdog==", + "requires": { + "exenv": "^1.2.2", + "react-from-dom": "^0.3.0" + } + } + } + }, "@samverschueren/stream-to-observable": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz", @@ -2561,6 +2868,12 @@ "any-observable": "^0.3.0" } }, + "@sindresorhus/fnv1a": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/fnv1a/-/fnv1a-1.2.0.tgz", + "integrity": "sha512-5ezb/dBSTWtKQ4sLQwMgOJyREXJcZZkTMbendMwKrXTghUhWjZhstzkkmt4/WkFy/GSTSGzfJOKU7dEXv3C/XQ==", + "dev": true + }, "@storybook/addon-storyshots": { "version": "5.2.8", "resolved": "https://registry.npmjs.org/@storybook/addon-storyshots/-/addon-storyshots-5.2.8.tgz", @@ -3301,9 +3614,9 @@ } }, "@tootallnate/once": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.0.0.tgz", - "integrity": "sha512-KYyTT/T6ALPkIRd2Ge080X/BsXvy9O0hcWTtMWkPvwAwF99+vn6Dv4GzrFT/Nn1LePr+FFDbRXXlqmsy9lw2zA==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", "dev": true }, "@types/asap": { @@ -3368,6 +3681,12 @@ "integrity": "sha512-MNl+rT5UmZeilaPxAVs6YaPC2m6aA8rofviZbhbxpPpl61uKodfdQVsBtgJGTqGizEf02oW3tsVe7FYB8kK14A==", "dev": true }, + "@types/color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", + "dev": true + }, "@types/draft-js": { "version": "0.10.37", "resolved": "https://registry.npmjs.org/@types/draft-js/-/draft-js-0.10.37.tgz", @@ -3536,12 +3855,78 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.6.tgz", "integrity": "sha512-FjsYUPzEJdGXjwKqSpE0/9QEh6kzhTAeObA54rn6j3rR4C/mzpI9L0KNfoeASSPMMdxIsoJuCLDWcM/rVjIsSA==" }, + "@types/node-fetch": { + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.7.tgz", + "integrity": "sha512-o2WVNf5UhWRkxlf6eq+jMZDu7kjgpgJfl4xVNlvryc95O/6F2ld8ztKX+qu+Rjyet93WAWm5LjeX9H5FGkODvw==", + "dev": true, + "requires": { + "@types/node": "*", + "form-data": "^3.0.0" + }, + "dependencies": { + "form-data": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz", + "integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + } + } + }, "@types/normalize-package-data": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz", "integrity": "sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==", "dev": true }, + "@types/pollyjs__adapter": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@types/pollyjs__adapter/-/pollyjs__adapter-4.3.0.tgz", + "integrity": "sha512-aJ4+ianTKgbdZRnBjcB9D1Kn4ALn3YatGlAzgEdGHyv63aV+gzukKH8xqdrRB76pwrXXCQwLosNBFNTSEmRA9A==", + "dev": true, + "requires": { + "@types/pollyjs__core": "*" + } + }, + "@types/pollyjs__adapter-node-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/pollyjs__adapter-node-http/-/pollyjs__adapter-node-http-2.0.0.tgz", + "integrity": "sha512-v8g65xEnADlb1UZe4fNPO9KpU04uY6HAPns307RWqePlVtftctD73FA++74PbO17PNgMbi/7IzrZatiEEn9CPQ==", + "dev": true, + "requires": { + "@types/pollyjs__adapter": "*" + } + }, + "@types/pollyjs__core": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@types/pollyjs__core/-/pollyjs__core-4.3.0.tgz", + "integrity": "sha512-gloFb5e36G8Tice0J2GhdzqAAongh2ALBel5QjvjmTk4Vv0+mD3xkE3O50XHdRfbJwCOo7A/rpH+6J+kuKXdZg==", + "dev": true, + "requires": { + "@types/pollyjs__adapter": "*", + "@types/pollyjs__persister": "*" + } + }, + "@types/pollyjs__persister": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@types/pollyjs__persister/-/pollyjs__persister-4.3.0.tgz", + "integrity": "sha512-gEwKh9XQSHo+1iBTHKqBIa/BHfG0cLidgryU6jEWzQ9NTtYOGb2V5tf3qb0ddihO7kJW/d0MCKTN28hDS+XCDg==", + "dev": true + }, + "@types/pollyjs__persister-fs": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/pollyjs__persister-fs/-/pollyjs__persister-fs-2.0.0.tgz", + "integrity": "sha512-m788FLVtzE+qqrNeotBel2S1EhNMkkNRVJa9XQqeNdwvaJvOp7h/EWacKCrdHLK406LBo7vhL8dpWldkRBm0lg==", + "dev": true, + "requires": { + "@types/pollyjs__persister": "*" + } + }, "@types/prop-types": { "version": "15.7.3", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz", @@ -3617,6 +4002,14 @@ "@types/react": "*" } }, + "@types/react-inlinesvg": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@types/react-inlinesvg/-/react-inlinesvg-0.8.1.tgz", + "integrity": "sha512-pONmeCNqot4diXLhxb+jajDWX57rH/JmMu9H4NQWNMl5WUHAHmcrOfDfB05IgYBfRUX1Cvyjl9EZzKHxSxZpAA==", + "requires": { + "@types/react": "*" + } + }, "@types/react-router": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.2.tgz", @@ -3743,12 +4136,33 @@ "integrity": "sha512-wx2LQVvKlEkhXp/HoKIZ/aSL+TvfJdKco8i0xJS3aR877mg4qBHzNT6+B5a61vewZHo79EdZavskGnRXEC2H6A==", "dev": true }, + "@types/setup-polly-jest": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@types/setup-polly-jest/-/setup-polly-jest-0.5.0.tgz", + "integrity": "sha512-adGkOa52Z/zU6gZ6oU7iUyS6BOmueFUjPIXrW0INNZPZqB5p68Q6dukWVk2bqVXwDUy3Cd6B/aADSouClwwmew==", + "dev": true, + "requires": { + "@types/pollyjs__core": "*" + } + }, "@types/shallowequal": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@types/shallowequal/-/shallowequal-1.1.1.tgz", "integrity": "sha512-Lhni3aX80zbpdxRuWhnuYPm8j8UQaa571lHP/xI4W+7BAFhSIhRReXnqjEgT/XzPoXZTJkCqstFMJ8CZTK6IlQ==", "dev": true }, + "@types/sinonjs__fake-timers": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-6.0.1.tgz", + "integrity": "sha512-yYezQwGWty8ziyYLdZjwxyMb0CZR49h8JALHGrxjQHWlqGgc8kLdHEgWrgL0uZ29DMvEVBDnHU2Wg36zKSIUtA==", + "dev": true + }, + "@types/sizzle": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.2.tgz", + "integrity": "sha512-7EJYyKTL7tFR8+gDbB6Wwz/arpGa0Mywk1TJbNzKzHtzbwVmY4HR9WqS5VV7dsBUKQmPNr192jHr/VpBluj/hg==", + "dev": true + }, "@types/stack-utils": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz", @@ -3972,6 +4386,181 @@ } } }, + "@webassemblyjs/ast": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", + "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", + "dev": true, + "requires": { + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz", + "integrity": "sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA==", + "dev": true + }, + "@webassemblyjs/helper-api-error": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", + "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==", + "dev": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz", + "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==", + "dev": true + }, + "@webassemblyjs/helper-code-frame": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz", + "integrity": "sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==", + "dev": true, + "requires": { + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "@webassemblyjs/helper-fsm": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz", + "integrity": "sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw==", + "dev": true + }, + "@webassemblyjs/helper-module-context": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz", + "integrity": "sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", + "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==", + "dev": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz", + "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz", + "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==", + "dev": true, + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz", + "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==", + "dev": true, + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz", + "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==", + "dev": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz", + "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/helper-wasm-section": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-opt": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz", + "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz", + "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz", + "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "@webassemblyjs/wast-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz", + "integrity": "sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/floating-point-hex-parser": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-code-frame": "1.9.0", + "@webassemblyjs/helper-fsm": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", + "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, "@wry/context": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/@wry/context/-/context-0.4.4.tgz", @@ -4043,9 +4632,9 @@ } }, "acorn-jsx": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.1.0.tgz", - "integrity": "sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.2.0.tgz", + "integrity": "sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ==", "dev": true }, "acorn-walk": { @@ -4061,9 +4650,9 @@ "dev": true }, "agent-base": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.0.tgz", - "integrity": "sha512-j1Q7cSCqN+AwrmDd+pzgqc0/NpC655x2bUf5ZjRIO77DcNBFmh+OgRNzF6OKdCC9RSCb19fGd99+bhXFdkRNqw==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.1.tgz", + "integrity": "sha512-01q25QQDwLSsyfhrKbn8yuur+JNw0H+0Y4JiGIKd3z9aYk/w/2kxD/Upc+t2ZBBSUNff50VjPsSW2YxM8QYKVg==", "dev": true, "requires": { "debug": "4" @@ -4725,6 +5314,12 @@ "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", "dev": true }, + "arch": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/arch/-/arch-2.1.2.tgz", + "integrity": "sha512-NTBIIbAfkJeIletyABbVtdPgeKfDafR+1mZV/AyyfC1UkVkp9iUjV+wwmqtUgphHYajbI86jejBJp5e+jkGTiQ==", + "dev": true + }, "are-we-there-yet": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", @@ -4871,11 +5466,12 @@ "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" }, "asar": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/asar/-/asar-2.0.1.tgz", - "integrity": "sha512-Vo9yTuUtyFahkVMFaI6uMuX6N7k5DWa6a/8+7ov0/f8Lq9TVR0tUjzSzxQSxT1Y+RJIZgnP7BVb6Uhi+9cjxqA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/asar/-/asar-2.1.0.tgz", + "integrity": "sha512-d2Ovma+bfqNpvBzY/KU8oPY67ZworixTpkjSx0PCXnQi67c2cXmssaTxpFDUM0ttopXoGx/KRxNg/GDThYbXQA==", "dev": true, "requires": { + "@types/glob": "^7.1.1", "chromium-pickle-js": "^0.2.0", "commander": "^2.20.0", "cuint": "^0.2.2", @@ -5157,6 +5753,17 @@ "babel-types": "^6.24.1" } }, + "babel-helper-builder-react-jsx": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz", + "integrity": "sha1-Of+DE7dci2Xc7/HzHTg+D/KkCKA=", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "esutils": "^2.0.2" + } + }, "babel-helper-call-delegate": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", @@ -6393,6 +7000,46 @@ "esutils": "^2.0.2" } }, + "babel-plugin-transform-react-display-name": { + "version": "6.25.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz", + "integrity": "sha1-Z+K/Hx6ck6sI25Z5LgU5K/LMKNE=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-react-jsx": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz", + "integrity": "sha1-hAoCjn30YN/DotKfDA2R9jduZqM=", + "dev": true, + "requires": { + "babel-helper-builder-react-jsx": "^6.24.1", + "babel-plugin-syntax-jsx": "^6.8.0", + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-react-jsx-self": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz", + "integrity": "sha1-322AqdomEqEh5t3XVYvL7PBuY24=", + "dev": true, + "requires": { + "babel-plugin-syntax-jsx": "^6.8.0", + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-react-jsx-source": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz", + "integrity": "sha1-ZqwSFT9c0tF7PBkmj0vwGX9E7NY=", + "dev": true, + "requires": { + "babel-plugin-syntax-jsx": "^6.8.0", + "babel-runtime": "^6.22.0" + } + }, "babel-plugin-transform-react-remove-prop-types": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz", @@ -6601,6 +7248,20 @@ "lodash": "^4.17.11" } }, + "babel-preset-react": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.24.1.tgz", + "integrity": "sha1-umnfrqRfw+xjm2pOzqbhdwLJE4A=", + "dev": true, + "requires": { + "babel-plugin-syntax-jsx": "^6.3.13", + "babel-plugin-transform-react-display-name": "^6.23.0", + "babel-plugin-transform-react-jsx": "^6.24.1", + "babel-plugin-transform-react-jsx-self": "^6.22.0", + "babel-plugin-transform-react-jsx-source": "^6.22.0", + "babel-preset-flow": "^6.23.0" + } + }, "babel-preset-react-app": { "version": "9.0.2", "resolved": "https://registry.npmjs.org/babel-preset-react-app/-/babel-preset-react-app-9.0.2.tgz", @@ -6854,9 +7515,9 @@ } }, "core-js": { - "version": "2.6.10", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.10.tgz", - "integrity": "sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA==", + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", + "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==", "dev": true }, "debug": { @@ -6992,6 +7653,11 @@ "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", "dev": true }, + "bail": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz", + "integrity": "sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ==" + }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -7058,6 +7724,23 @@ "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==", "dev": true }, + "basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, "batch": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", @@ -7103,6 +7786,12 @@ "integrity": "sha512-DdmyoGCleJnkbp3nkbxTLJ18rjDsE4yCggEwKNXkeV123sPNfOCYeDoeuOY+F2FrSjO1YXcTU+dsy96KMy+gcg==", "dev": true }, + "blueimp-md5": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/blueimp-md5/-/blueimp-md5-2.17.0.tgz", + "integrity": "sha512-x5PKJHY5rHQYaADj6NwPUR2QRCUVSggPzrUKkeENpj871o9l9IefJbO2jkT5UvYykeOK9dx0VmkIo6dZ+vThYw==", + "dev": true + }, "bn.js": { "version": "4.11.8", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", @@ -7179,9 +7868,9 @@ "dev": true }, "bowser": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/bowser/-/bowser-1.6.0.tgz", - "integrity": "sha1-N/w4e2Fstq7zcNq01r1AK3TFxU0=", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.10.0.tgz", + "integrity": "sha512-OCsqTQboTEWWsUjcp5jLSw2ZHsBiv2C105iFs61bOT0Hnwi9p7/uuXdd7mu8RYcarREfdjNN+8LitmEHATsLYg==", "dev": true }, "boxen": { @@ -7408,6 +8097,12 @@ } } }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", + "dev": true + }, "buffer-from": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", @@ -7493,6 +8188,12 @@ "unset-value": "^1.0.0" } }, + "cachedir": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.3.0.tgz", + "integrity": "sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw==", + "dev": true + }, "call-me-maybe": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", @@ -7564,9 +8265,9 @@ "dev": true }, "caniuse-lite": { - "version": "1.0.30001008", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001008.tgz", - "integrity": "sha512-b8DJyb+VVXZGRgJUa30cbk8gKHZ3LOZTBLaUEEVr2P4xpmFigOCc62CO4uzquW641Ouq1Rm9N+rWLWdSYDaDIw==", + "version": "1.0.30001100", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001100.tgz", + "integrity": "sha512-0eYdp1+wFCnMlCj2oudciuQn2B9xAFq3WpgpcBIZTxk/1HNA/O2YA7rpeYhnOqsqAJq1AHUgx6i1jtafg7m2zA==", "dev": true }, "capture-exit": { @@ -7651,20 +8352,17 @@ "character-entities": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.3.tgz", - "integrity": "sha512-yB4oYSAa9yLcGyTbB4ItFwHw43QHdH129IJ5R+WvxOkWlyFnR5FAaBNnUq4mcxsTVZGh28bHoeTHMKXH1wZf3w==", - "dev": true + "integrity": "sha512-yB4oYSAa9yLcGyTbB4ItFwHw43QHdH129IJ5R+WvxOkWlyFnR5FAaBNnUq4mcxsTVZGh28bHoeTHMKXH1wZf3w==" }, "character-entities-legacy": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.3.tgz", - "integrity": "sha512-YAxUpPoPwxYFsslbdKkhrGnXAtXoHNgYjlBM3WMXkWGTl5RsY3QmOyhwAgL8Nxm9l5LBThXGawxKPn68y6/fww==", - "dev": true + "integrity": "sha512-YAxUpPoPwxYFsslbdKkhrGnXAtXoHNgYjlBM3WMXkWGTl5RsY3QmOyhwAgL8Nxm9l5LBThXGawxKPn68y6/fww==" }, "character-reference-invalid": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.3.tgz", - "integrity": "sha512-VOq6PRzQBam/8Jm6XBGk2fNEnHXAdGd6go0rtd4weAGECBamHDwwCQSOT12TACIYUZegUXnV6xBXqUssijtxIg==", - "dev": true + "integrity": "sha512-VOq6PRzQBam/8Jm6XBGk2fNEnHXAdGd6go0rtd4weAGECBamHDwwCQSOT12TACIYUZegUXnV6xBXqUssijtxIg==" }, "chardet": { "version": "0.7.0", @@ -7678,6 +8376,12 @@ "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", "dev": true }, + "check-more-types": { + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz", + "integrity": "sha1-FCD/sQ/URNz8ebQ4kbv//TKoRgA=", + "dev": true + }, "cheerio": { "version": "1.0.0-rc.3", "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.3.tgz", @@ -7730,12 +8434,6 @@ "integrity": "sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw==", "dev": true }, - "chrome-emulated-devices-list": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/chrome-emulated-devices-list/-/chrome-emulated-devices-list-0.1.1.tgz", - "integrity": "sha512-wQu6YKNTNGaUXovpkvXLnfeumVK47r2TKpOuCTwOKv/5SmRzfHual+E+oDIwS3KFWAcJPAhoNRAOLvXwzC6/pw==", - "dev": true - }, "chrome-remote-interface": { "version": "0.25.7", "resolved": "https://registry.npmjs.org/chrome-remote-interface/-/chrome-remote-interface-0.25.7.tgz", @@ -8068,9 +8766,9 @@ "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" }, "codecov": { - "version": "3.6.5", - "resolved": "https://registry.npmjs.org/codecov/-/codecov-3.6.5.tgz", - "integrity": "sha512-v48WuDMUug6JXwmmfsMzhCHRnhUf8O3duqXvltaYJKrO1OekZWpB/eH6iIoaxMl8Qli0+u3OxptdsBOYiD7VAQ==", + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/codecov/-/codecov-3.7.1.tgz", + "integrity": "sha512-JHWxyPTkMLLJn9SmKJnwAnvY09kg2Os2+Ux+GG7LwZ9g8gzDDISpIN5wAsH1UBaafA/yGcd3KofMaorE8qd6Lw==", "dev": true, "requires": { "argv": "0.0.2", @@ -8081,11 +8779,16 @@ } }, "coffeescript": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/coffeescript/-/coffeescript-2.4.1.tgz", - "integrity": "sha512-34GV1aHrsMpTaO3KfMJL40ZNuvKDR/g98THHnE9bQj8HjMaZvSrLik99WWqyMhRtbe8V5hpx5iLgdcSvM/S2wg==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/coffeescript/-/coffeescript-2.5.1.tgz", + "integrity": "sha512-J2jRPX0eeFh5VKyVnoLrfVFgLZtnnmp96WQSLAS8OrLm2wtQLcnikYKe1gViJKDH7vucjuhHvBKKBP3rKcD1tQ==", "dev": true }, + "collapse-white-space": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.6.tgz", + "integrity": "sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ==" + }, "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", @@ -8153,12 +8856,20 @@ "dev": true }, "compressible": { - "version": "2.0.17", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.17.tgz", - "integrity": "sha512-BGHeLCK1GV7j1bSmQQAi26X+GgWcTjLr/0tzSvMCl3LH1w1IJ4PFSPoV5316b30cneTziC+B1a+3OjoSUcQYmw==", + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", "dev": true, "requires": { - "mime-db": ">= 1.40.0 < 2" + "mime-db": ">= 1.43.0 < 2" + }, + "dependencies": { + "mime-db": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", + "dev": true + } } }, "compression": { @@ -8410,6 +9121,16 @@ } } }, + "cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dev": true, + "requires": { + "object-assign": "^4", + "vary": "^1" + } + }, "cosmiconfig": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", @@ -8742,6 +9463,130 @@ "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=", "dev": true }, + "cypress": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-4.9.0.tgz", + "integrity": "sha512-qGxT5E0j21FPryzhb0OBjCdhoR/n1jXtumpFFSBPYWsaZZhNaBvc3XlBUDEZKkkXPsqUFYiyhWdHN/zo0t5FcA==", + "dev": true, + "requires": { + "@cypress/listr-verbose-renderer": "0.4.1", + "@cypress/request": "2.88.5", + "@cypress/xvfb": "1.2.4", + "@types/sinonjs__fake-timers": "6.0.1", + "@types/sizzle": "2.3.2", + "arch": "2.1.2", + "bluebird": "3.7.2", + "cachedir": "2.3.0", + "chalk": "2.4.2", + "check-more-types": "2.24.0", + "cli-table3": "0.5.1", + "commander": "4.1.1", + "common-tags": "1.8.0", + "debug": "4.1.1", + "eventemitter2": "6.4.2", + "execa": "1.0.0", + "executable": "4.1.1", + "extract-zip": "1.7.0", + "fs-extra": "8.1.0", + "getos": "3.2.1", + "is-ci": "2.0.0", + "is-installed-globally": "0.3.2", + "lazy-ass": "1.6.0", + "listr": "0.14.3", + "lodash": "4.17.15", + "log-symbols": "3.0.0", + "minimist": "1.2.5", + "moment": "2.26.0", + "ospath": "1.2.2", + "pretty-bytes": "5.3.0", + "ramda": "0.26.1", + "request-progress": "3.0.0", + "supports-color": "7.1.0", + "tmp": "0.1.0", + "untildify": "4.0.0", + "url": "0.11.0", + "yauzl": "2.10.0" + }, + "dependencies": { + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true + }, + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "log-symbols": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", + "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==", + "dev": true, + "requires": { + "chalk": "^2.4.2" + } + }, + "moment": { + "version": "2.26.0", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.26.0.tgz", + "integrity": "sha512-oIixUO+OamkUkwjhAVE18rAMfRJNsNe/Stid/gwHSOfHrOtw9EhAY2AHvdKZ/k/MggcYELFCJz/Sn2pL8b8JMw==", + "dev": true + }, + "ramda": { + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.26.1.tgz", + "integrity": "sha512-hLWjpy7EnsDBb0p+Z3B7rPi3GDeRG5ZtiI33kJhTt+ORCd38AbAIjB/9zRIUoeTbE/AVX5ZkU7m6bznsvrf8eQ==", + "dev": true + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "tmp": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.1.0.tgz", + "integrity": "sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw==", + "dev": true, + "requires": { + "rimraf": "^2.6.3" + } + } + } + }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", @@ -9156,6 +10001,12 @@ } } }, + "device-specs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/device-specs/-/device-specs-1.0.0.tgz", + "integrity": "sha512-fYXbFSeilT7bnKWFi4OERSPHdtaEoDGn4aUhV5Nly6/I+Tp6JZ/6Icmd7LVIF5euyodGpxz2e/bfUmDnIdSIDw==", + "dev": true + }, "diff": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.1.tgz", @@ -9260,7 +10111,6 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.1.tgz", "integrity": "sha512-sK3ujri04WyjwQXVoK4PU3y8ula1stq10GJZpqHIUgoGZdsGzAGu65BnU3d08aTVSvO7mGPZUc0wTEDL+qGE0Q==", - "dev": true, "requires": { "domelementtype": "^2.0.1", "entities": "^2.0.0" @@ -9269,14 +10119,12 @@ "domelementtype": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.1.tgz", - "integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ==", - "dev": true + "integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ==" }, "entities": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.0.tgz", - "integrity": "sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw==", - "dev": true + "integrity": "sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw==" } } }, @@ -9485,9 +10333,9 @@ } }, "elliptic": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.1.tgz", - "integrity": "sha512-xvJINNLbTeWQjrl6X+7eQCrIy/YPv5XCpKW6kB5mKvtnGILoLDcySuwomfdzt0BMdLNVnuRNTuzKNHj0bva1Cg==", + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", + "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==", "dev": true, "requires": { "bn.js": "^4.4.0", @@ -9798,9 +10646,9 @@ } }, "eslint": { - "version": "6.7.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.7.1.tgz", - "integrity": "sha512-UWzBS79pNcsDSxgxbdjkmzn/B6BhsXMfUaOHnNwyE8nD+Q6pyT96ow2MccVayUTV4yMid4qLhMiQaywctRkBLA==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.8.0.tgz", + "integrity": "sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", @@ -9843,12 +10691,20 @@ }, "dependencies": { "ansi-escapes": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.0.tgz", - "integrity": "sha512-EiYhwo0v255HUL6eDyuLrXEkTi7WwVCLAw+SeOQ7M7qdun1z1pum4DEm/nuqIVbPvi9RPPc9k9LbyBv6H0DwVg==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", + "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==", "dev": true, "requires": { - "type-fest": "^0.8.1" + "type-fest": "^0.11.0" + }, + "dependencies": { + "type-fest": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz", + "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==", + "dev": true + } } }, "ansi-regex": { @@ -9857,6 +10713,16 @@ "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", "dev": true }, + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, "cli-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", @@ -9866,6 +10732,21 @@ "restore-cursor": "^3.1.0" } }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -9883,32 +10764,38 @@ } }, "figures": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.1.0.tgz", - "integrity": "sha512-ravh8VRXqHuMvZt/d8GblBeqDMkdJMBdv/2KntFH+ra5MXkO7nxNKpzQ3n6QD/2da1kH0aWmNISdvhM7gl2gVg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", "dev": true, "requires": { "escape-string-regexp": "^1.0.5" } }, "glob-parent": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz", - "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", "dev": true, "requires": { "is-glob": "^4.0.1" } }, "globals": { - "version": "12.3.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-12.3.0.tgz", - "integrity": "sha512-wAfjdLgFsPZsklLJvOBUBmzYE8/CwhEqSBEMRXA3qxIiNtyqvjYurAtIfDh6chlEPUfmTY3MnZh5Hfh4q0UlIw==", + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", + "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", "dev": true, "requires": { "type-fest": "^0.8.1" } }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, "ignore": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", @@ -9926,24 +10813,45 @@ } }, "inquirer": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.0.0.tgz", - "integrity": "sha512-rSdC7zelHdRQFkWnhsMu2+2SO41mpv2oF2zy4tMhmiLWkcKbOAs87fWAJhVXttKVwhdZvymvnuM95EyEXg2/tQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.1.0.tgz", + "integrity": "sha512-5fJMWEmikSYu0nv/flMc475MhGbB7TSPd/2IpFV4I4rMklboCH2rQjYY5kKiYGHqUF9gvaambupcJFFG9dvReg==", "dev": true, "requires": { "ansi-escapes": "^4.2.1", - "chalk": "^2.4.2", + "chalk": "^3.0.0", "cli-cursor": "^3.1.0", "cli-width": "^2.0.0", "external-editor": "^3.0.3", "figures": "^3.0.0", "lodash": "^4.17.15", "mute-stream": "0.0.8", - "run-async": "^2.2.0", - "rxjs": "^6.4.0", + "run-async": "^2.4.0", + "rxjs": "^6.5.3", "string-width": "^4.1.0", - "strip-ansi": "^5.1.0", + "strip-ansi": "^6.0.0", "through": "^2.3.6" + }, + "dependencies": { + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + } } }, "is-fullwidth-code-point": { @@ -9989,6 +10897,12 @@ "signal-exit": "^3.0.2" } }, + "run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true + }, "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", @@ -10017,6 +10931,15 @@ } } }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, "type-fest": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", @@ -10332,6 +11255,12 @@ "integrity": "sha512-CT7a5pT6SG9hvhCjyHKFA1+lClB4WA+gvBt04E7/buUTELgatneCrublqTzi++tZuCefUhJXrTm3W1wpK14sqg==", "dev": true }, + "eslint-plugin-simple-import-sort": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-5.0.3.tgz", + "integrity": "sha512-1rf3AWiHeWNCQdAq0iXNnlccnH1UDnelGgrPbjBBHE8d2hXVtOudcmy0vTF4hri3iJ0MKz8jBhmH6lJ0ZWZLHQ==", + "dev": true + }, "eslint-scope": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", @@ -10358,29 +11287,29 @@ "dev": true }, "esotope-hammerhead": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/esotope-hammerhead/-/esotope-hammerhead-0.4.0.tgz", - "integrity": "sha512-TAmc7OhAiWeovbzE9GGenU2vwuB9tzKHlW0hTH4rZsLmCNEKo8wIZ9qbEnw8nyXeNTjCmBYOYXUyaN+eZht7Tg==", + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/esotope-hammerhead/-/esotope-hammerhead-0.5.5.tgz", + "integrity": "sha512-EuSYJDtF8gLMB24lzjHw2KotauPsVJybFrtGfQyMm48oC7sTkspA26DqcqcbnRl4GC6sPVKWEx+ex72eqopX9Q==", "dev": true, "requires": { "@types/estree": "^0.0.39" } }, "espree": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/espree/-/espree-6.1.2.tgz", - "integrity": "sha512-2iUPuuPP+yW1PZaMSDM9eyVf8D5P0Hi8h83YtZ5bPc/zHYjII5khoixIUTMO794NOY8F/ThF1Bo8ncZILarUTA==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz", + "integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==", "dev": true, "requires": { - "acorn": "^7.1.0", - "acorn-jsx": "^5.1.0", + "acorn": "^7.1.1", + "acorn-jsx": "^5.2.0", "eslint-visitor-keys": "^1.1.0" }, "dependencies": { "acorn": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.1.tgz", - "integrity": "sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.2.0.tgz", + "integrity": "sha512-apwXVmYVpQ34m/i71vrApRrRKCWQnZZF1+npOD0WV5xZFfwWOmKGQ2RWlfdy9vWITsenisM8M0Qeq8agcFHNiQ==", "dev": true } } @@ -10391,12 +11320,20 @@ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" }, "esquery": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", - "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", + "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", "dev": true, "requires": { - "estraverse": "^4.0.0" + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.1.0.tgz", + "integrity": "sha512-FyohXK+R0vE+y1nHLoBM7ZTyqRpqAlhdZHCWIWEviFLiGB8b04H6bQs8G+XTthacvT8VuwvteiP7RJSxMs8UEw==", + "dev": true + } } }, "esrecurse": { @@ -10425,6 +11362,27 @@ "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", "dev": true }, + "event-stream": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", + "dev": true, + "requires": { + "duplexer": "~0.1.1", + "from": "~0", + "map-stream": "~0.1.0", + "pause-stream": "0.0.11", + "split": "0.3", + "stream-combiner": "~0.0.4", + "through": "~2.3.1" + } + }, + "eventemitter2": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.2.tgz", + "integrity": "sha512-r/Pwupa5RIzxIHbEKCkNXqpEQIIT4uQDxmP4G/Lug/NokVUWj0joz/WzWl3OxRpC5kDrH/WdiUJoR+IrwvXJEw==", + "dev": true + }, "eventemitter3": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.0.tgz", @@ -10491,12 +11449,40 @@ } } }, + "executable": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/executable/-/executable-4.1.1.tgz", + "integrity": "sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==", + "dev": true, + "requires": { + "pify": "^2.2.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "exenv": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz", + "integrity": "sha1-KueOhdmJQVhnCwPUe+wfA72Ru50=" + }, "exit": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", "dev": true }, + "exit-hook": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", + "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", + "dev": true + }, "exit-on-epipe": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz", @@ -10708,8 +11694,7 @@ "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" }, "extend-shallow": { "version": "3.0.2", @@ -10818,6 +11803,44 @@ "resolved": "https://registry.npmjs.org/extract-stack/-/extract-stack-1.0.0.tgz", "integrity": "sha1-uXrK+UQe6iMyUpYktzL8WhyBZfo=" }, + "extract-zip": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz", + "integrity": "sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==", + "dev": true, + "requires": { + "concat-stream": "^1.6.2", + "debug": "^2.6.9", + "mkdirp": "^0.5.4", + "yauzl": "^2.10.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", @@ -10915,6 +11938,15 @@ } } }, + "fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", + "dev": true, + "requires": { + "pend": "~1.2.0" + } + }, "figgy-pudding": { "version": "3.5.1", "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz", @@ -11196,9 +12228,9 @@ } }, "flatted": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz", - "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", + "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", "dev": true }, "flush-write-stream": { @@ -11218,24 +12250,10 @@ "dev": true }, "follow-redirects": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.9.0.tgz", - "integrity": "sha512-CRcPzsSIbXyVDl0QI01muNDu69S8trU4jArW9LpOt2WtC6LyUJetcIrmfHsRBx7/Jb6GHJUiuqyYxPooFfNt6A==", - "dev": true, - "requires": { - "debug": "^3.0.0" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } - } + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.12.1.tgz", + "integrity": "sha512-tmRv0AVuR7ZyouUHLeNSiO6pqulF7dYa3s19c6t+wz9LD69/uSzdMxJ2S91nTI9U3rt/IldxpzMOFejp6f0hjg==", + "dev": true }, "for-in": { "version": "1.0.2", @@ -11413,6 +12431,12 @@ "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", "dev": true }, + "from": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", + "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=", + "dev": true + }, "from2": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", @@ -12090,6 +13114,23 @@ "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", "dev": true }, + "getos": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/getos/-/getos-3.2.1.tgz", + "integrity": "sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q==", + "dev": true, + "requires": { + "async": "^3.2.0" + }, + "dependencies": { + "async": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz", + "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==", + "dev": true + } + } + }, "getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", @@ -12212,6 +13253,15 @@ "process": "^0.11.10" } }, + "global-dirs": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-2.0.1.tgz", + "integrity": "sha512-5HqUqdhkEovj2Of/ms3IeS/EekcO54ytHRLV4PEY2rhRwrHXLQjeVEES0Lhka0xwNDtGYn58wyC4s5+MHsOO6A==", + "dev": true, + "requires": { + "ini": "^1.3.5" + } + }, "global-modules": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", @@ -12304,12 +13354,12 @@ "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==" }, "graphlib": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/graphlib/-/graphlib-2.1.7.tgz", - "integrity": "sha512-TyI9jIy2J4j0qgPmOOrHTCtpPqJGN/aurBwc6ZT+bRii+di1I+Wv3obRhVrmBEXet+qkMaEX67dXrwsd3QQM6w==", + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/graphlib/-/graphlib-2.1.8.tgz", + "integrity": "sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A==", "dev": true, "requires": { - "lodash": "^4.17.5" + "lodash": "^4.17.15" } }, "graphql": { @@ -12347,9 +13397,9 @@ } }, "handle-thing": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.0.tgz", - "integrity": "sha512-d4sze1JNC454Wdo2fkuyzCr6aHcbL6PGGuFAz0Li/NcOm1tCHGnWDRmJP85dh9IhQErTc2svWFEX5xHIOo//kQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", "dev": true }, "har-schema": { @@ -12636,6 +13686,63 @@ "uglify-js": "^3.5.1" } }, + "html-to-react": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/html-to-react/-/html-to-react-1.4.3.tgz", + "integrity": "sha512-txe09A3vxW8yEZGJXJ1is5gGDfBEVACmZDSgwDyH5EsfRdOubBwBCg63ZThZP0xBn0UE4FyvMXZXmohusCxDcg==", + "requires": { + "domhandler": "^3.0", + "htmlparser2": "^4.1.0", + "lodash.camelcase": "^4.3.0", + "ramda": "^0.27" + }, + "dependencies": { + "domelementtype": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.1.tgz", + "integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ==" + }, + "domhandler": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-3.0.0.tgz", + "integrity": "sha512-eKLdI5v9m67kbXQbJSNn1zjh0SDzvzWVWtX+qEI3eMjZw8daH9k8rlj1FZY9memPwjiskQFbe7vHVVJIAqoEhw==", + "requires": { + "domelementtype": "^2.0.1" + } + }, + "domutils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.1.0.tgz", + "integrity": "sha512-CD9M0Dm1iaHfQ1R/TI+z3/JWp/pgub0j4jIQKH89ARR4ATAV2nbaOQS5XxU9maJP5jHaPdDDQSEHuE2UmpUTKg==", + "requires": { + "dom-serializer": "^0.2.1", + "domelementtype": "^2.0.1", + "domhandler": "^3.0.0" + } + }, + "entities": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.2.tgz", + "integrity": "sha512-dmD3AvJQBUjKpcNkoqr+x+IF0SdRtPz9Vk0uTy4yWqga9ibB6s4v++QFWNohjiUGoMlF552ZvNyXDxz5iW0qmw==" + }, + "htmlparser2": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-4.1.0.tgz", + "integrity": "sha512-4zDq1a1zhE4gQso/c5LP1OtrhYTncXNSpvJYtWJBtXAETPlMfi3IFNjGuQbYLuVY4ZR0QMqRVvo4Pdy9KLyP8Q==", + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^3.0.0", + "domutils": "^2.0.0", + "entities": "^2.0.0" + } + }, + "ramda": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.27.0.tgz", + "integrity": "sha512-pVzZdDpWwWqEVVLshWUHjNwuVP7SfcmPraYuqocJp1yo2U1R7P+5QAfDhdItkuoGqIBnBYrtPp7rEPqDn9HlZA==" + } + } + }, "html-webpack-plugin": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-3.2.0.tgz", @@ -12789,6 +13896,15 @@ } } }, + "http-graceful-shutdown": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/http-graceful-shutdown/-/http-graceful-shutdown-2.3.2.tgz", + "integrity": "sha512-Dn7fJjHWboN7WjNDuo7d7ZISdUlbnyQEtOjBwMGJig45ZztHQxCsnW9N89Pr3gb6VzvZy1HySgAu2Q98j6S17w==", + "dev": true, + "requires": { + "debug": "^4.1.1" + } + }, "http-parser-js": { "version": "0.4.10", "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.10.tgz", @@ -12796,9 +13912,9 @@ "dev": true }, "http-proxy": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.0.tgz", - "integrity": "sha512-84I2iJM/n1d4Hdgc6y2+qY5mDaz2PUVjlg9znE9byl+q0uC3DeByqBGReQu5tpLK0TAqTIXScRUV+dg7+bUPpQ==", + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", "dev": true, "requires": { "eventemitter3": "^4.0.0", @@ -12874,6 +13990,12 @@ } } }, + "human-signals": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", + "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", + "dev": true + }, "husky": { "version": "3.0.9", "resolved": "https://registry.npmjs.org/husky/-/husky-3.0.9.tgz", @@ -13262,14 +14384,12 @@ "is-alphabetical": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.3.tgz", - "integrity": "sha512-eEMa6MKpHFzw38eKm56iNNi6GJ7lf6aLLio7Kr23sJPAECscgRtZvOBYybejWDQ2bM949Y++61PY+udzj5QMLA==", - "dev": true + "integrity": "sha512-eEMa6MKpHFzw38eKm56iNNi6GJ7lf6aLLio7Kr23sJPAECscgRtZvOBYybejWDQ2bM949Y++61PY+udzj5QMLA==" }, "is-alphanumerical": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.3.tgz", "integrity": "sha512-A1IGAPO5AW9vSh7omxIlOGwIqEvpW/TA+DksVOPM5ODuxKlZS09+TEM1E3275lJqO2oJ38vDpeAL3DCIiHE6eA==", - "dev": true, "requires": { "is-alphabetical": "^1.0.0", "is-decimal": "^1.0.0" @@ -13304,8 +14424,7 @@ "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" }, "is-callable": { "version": "1.1.4", @@ -13349,8 +14468,7 @@ "is-decimal": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.3.tgz", - "integrity": "sha512-bvLSwoDg2q6Gf+E2LEPiklHZxxiSi3XAh4Mav65mKqTfCO1HM3uBs24TjEH8iJX3bbDdLXKJXBTmGzuTUuAEjQ==", - "dev": true + "integrity": "sha512-bvLSwoDg2q6Gf+E2LEPiklHZxxiSi3XAh4Mav65mKqTfCO1HM3uBs24TjEH8iJX3bbDdLXKJXBTmGzuTUuAEjQ==" }, "is-descriptor": { "version": "0.1.6", @@ -13453,14 +14571,23 @@ "is-hexadecimal": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.3.tgz", - "integrity": "sha512-zxQ9//Q3D/34poZf8fiy3m3XVpbQc7ren15iKqrTtLPwkPD/t3Scy9Imp63FujULGxuK0ZlCwoo5xNpktFgbOA==", - "dev": true + "integrity": "sha512-zxQ9//Q3D/34poZf8fiy3m3XVpbQc7ren15iKqrTtLPwkPD/t3Scy9Imp63FujULGxuK0ZlCwoo5xNpktFgbOA==" }, "is-in-browser": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/is-in-browser/-/is-in-browser-1.1.3.tgz", "integrity": "sha1-Vv9NtoOgeMYILrldrX3GLh0E+DU=" }, + "is-installed-globally": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.3.2.tgz", + "integrity": "sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g==", + "dev": true, + "requires": { + "global-dirs": "^2.0.1", + "is-path-inside": "^3.0.1" + } + }, "is-jquery-obj": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-jquery-obj/-/is-jquery-obj-0.1.1.tgz", @@ -13550,8 +14677,7 @@ "is-plain-obj": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", - "dev": true + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=" }, "is-plain-object": { "version": "2.0.4", @@ -13654,12 +14780,22 @@ "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", "dev": true }, + "is-whitespace-character": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz", + "integrity": "sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w==" + }, "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", "dev": true }, + "is-word-character": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.4.tgz", + "integrity": "sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA==" + }, "is-wsl": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", @@ -14044,6 +15180,12 @@ "pretty-format": "^24.9.0" } }, + "jest-localstorage-mock": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/jest-localstorage-mock/-/jest-localstorage-mock-2.4.3.tgz", + "integrity": "sha512-UgifkHKoWVRUoSqO4Z4Z+Hl1NbiYBVDlmkmulFFeRRneGECWAlAdGWJdyz+2NisjOZnnQoxQl0s5dQ7ch62Jxw==", + "dev": true + }, "jest-matcher-utils": { "version": "24.9.0", "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-24.9.0.tgz", @@ -14807,6 +15949,12 @@ "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", "dev": true }, + "lazy-ass": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/lazy-ass/-/lazy-ass-1.6.0.tgz", + "integrity": "sha1-eZllXoZGwX8In90YfRUNMyTVRRM=", + "dev": true + }, "lazy-cache": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", @@ -15155,13 +16303,13 @@ } }, "loader-fs-cache": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/loader-fs-cache/-/loader-fs-cache-1.0.2.tgz", - "integrity": "sha512-70IzT/0/L+M20jUlEqZhZyArTU6VKLRTYRDAYN26g4jfzpJqjipLL3/hgYpySqI9PwsVRHHFja0LfEmsx9X2Cw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/loader-fs-cache/-/loader-fs-cache-1.0.3.tgz", + "integrity": "sha512-ldcgZpjNJj71n+2Mf6yetz+c9bM4xpKtNds4LbqXzU/PTdeAX0g3ytnU1AJMEcTk2Lex4Smpe3Q/eCTsvUBxbA==", "dev": true, "requires": { "find-cache-dir": "^0.1.1", - "mkdirp": "0.5.1" + "mkdirp": "^0.5.1" }, "dependencies": { "find-cache-dir": { @@ -15258,6 +16406,11 @@ "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=" }, + "lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=" + }, "lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", @@ -15269,11 +16422,20 @@ "integrity": "sha1-yQRGkMIeBClL6qUXcS/e0fqI3pg=", "dev": true }, + "lodash.every": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.every/-/lodash.every-4.6.0.tgz", + "integrity": "sha1-64mYS+vENkJ5uzrvu9HKGb+mxqc=" + }, "lodash.flattendeep": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", - "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", - "dev": true + "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=" + }, + "lodash.foreach": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz", + "integrity": "sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM=" }, "lodash.get": { "version": "4.4.2", @@ -15290,6 +16452,16 @@ "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" }, + "lodash.map": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz", + "integrity": "sha1-dx7Hg540c9nEzeKLGTlMNWL09tM=" + }, + "lodash.maxby": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.maxby/-/lodash.maxby-4.6.0.tgz", + "integrity": "sha1-CCJABo88eiJ6oAqDgOTzjPB4bj0=" + }, "lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -15301,6 +16473,12 @@ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" }, + "lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=", + "dev": true + }, "lodash.pickby": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/lodash.pickby/-/lodash.pickby-4.6.0.tgz", @@ -15488,12 +16666,6 @@ } } }, - "loglevel": { - "version": "1.6.6", - "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.6.tgz", - "integrity": "sha512-Sgr5lbboAUBo3eXCSPL4/KoVz3ROKquOjcctxmHIt+vol2DrqTQe3SwkKKuYhEiWB5kYa13YyopJ69deJ1irzQ==", - "dev": true - }, "loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -15584,6 +16756,12 @@ "integrity": "sha1-J06fUAphEVMYO1uNhJCpwcI+4xA=", "dev": true }, + "map-stream": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", + "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=", + "dev": true + }, "map-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", @@ -15593,10 +16771,15 @@ "object-visit": "^1.0.0" } }, + "markdown-escapes": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.4.tgz", + "integrity": "sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg==" + }, "markdown-to-jsx": { - "version": "6.10.3", - "resolved": "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-6.10.3.tgz", - "integrity": "sha512-PSoUyLnW/xoW6RsxZrquSSz5eGEOTwa15H5eqp3enmrp8esmgDJmhzd6zmQ9tgAA9TxJzx1Hmf3incYU/IamoQ==", + "version": "6.11.4", + "resolved": "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-6.11.4.tgz", + "integrity": "sha512-3lRCD5Sh+tfA52iGgfs/XZiw33f7fFX9Bn55aNnVNUd2GzLDkOWyKYYD8Yju2B1Vn+feiEdgJs8T6Tg0xNokPw==", "dev": true, "requires": { "prop-types": "^15.6.2", @@ -15629,6 +16812,14 @@ "safe-buffer": "^5.1.2" } }, + "mdast-add-list-metadata": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdast-add-list-metadata/-/mdast-add-list-metadata-1.0.1.tgz", + "integrity": "sha512-fB/VP4MJ0LaRsog7hGPxgOrSL3gE/2uEdZyDuSEnKCv/8IkYHiDkIQSbChiJoHyxZZXZ9bzckyRk+vNxFzh8rA==", + "requires": { + "unist-util-visit-parents": "1.1.2" + } + }, "mdn-data": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", @@ -15903,22 +17094,20 @@ } }, "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", "dev": true, "requires": { - "minimist": "0.0.8" - }, - "dependencies": { - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - } + "minimist": "^1.2.5" } }, + "mock-apollo-client": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/mock-apollo-client/-/mock-apollo-client-0.4.0.tgz", + "integrity": "sha512-cHznpkX8uUClkWWJMpgdDWzEgjacM85xt69S9gPLrssM8Vahas0QmEJkFUycrRQyBkaqxvRe58Bg3a5pOvj2zA==", + "dev": true + }, "moment": { "version": "2.24.0", "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz", @@ -15944,6 +17133,42 @@ "integrity": "sha512-gFD2xGCl8YFgGHsqJ9NKRVdwlioeW3mI1iqfLNYQOv0+6JRwG58Zk9DIGQgyIaffSYaO1xsKnMaYzzNr1KyIAw==", "dev": true }, + "morgan": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", + "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", + "dev": true, + "requires": { + "basic-auth": "~2.0.1", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-finished": "~2.3.0", + "on-headers": "~1.0.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, "move-concurrently": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", @@ -16088,6 +17313,24 @@ "lower-case": "^1.1.1" } }, + "nocache": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/nocache/-/nocache-2.1.0.tgz", + "integrity": "sha512-0L9FvHG3nfnnmaEQPjT9xhfN4ISk0A8/2j4M37Np4mcDesJjHgEUfgPhdCyZuFI954tjokaIj/A3NdpFNdEh4Q==", + "dev": true + }, + "nock": { + "version": "12.0.3", + "resolved": "https://registry.npmjs.org/nock/-/nock-12.0.3.tgz", + "integrity": "sha512-QNb/j8kbFnKCiyqi9C5DD0jH/FubFGj5rt9NQFONXwQm3IPB0CULECg/eS3AU1KgZb/6SwUa4/DTRKhVxkGABw==", + "dev": true, + "requires": { + "debug": "^4.1.0", + "json-stringify-safe": "^5.0.1", + "lodash": "^4.17.13", + "propagate": "^2.0.0" + } + }, "node-dir": { "version": "0.1.17", "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz", @@ -16098,9 +17341,9 @@ } }, "node-fetch": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", - "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==" + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" }, "node-forge": { "version": "0.9.0", @@ -16565,6 +17808,12 @@ "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true }, + "ospath": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/ospath/-/ospath-1.2.2.tgz", + "integrity": "sha1-EnZjl3Sj+O8lcvf+QoDg6kVQwHs=", + "dev": true + }, "p-defer": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", @@ -16695,7 +17944,6 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.2.2.tgz", "integrity": "sha512-NzfpbxW/NPrzZ/yYSoQxyqUZMZXIdCfE0OIN4ESsnptHJECoUk3FZktxNuzQf4tjt5UEopnxpYJbvYuxIFDdsg==", - "dev": true, "requires": { "character-entities": "^1.0.0", "character-entities-legacy": "^1.0.0", @@ -16866,6 +18114,15 @@ "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", "dev": true }, + "pause-stream": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", + "dev": true, + "requires": { + "through": "~2.3" + } + }, "pbkdf2": { "version": "3.0.17", "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", @@ -16879,6 +18136,12 @@ "sha.js": "^2.4.8" } }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", + "dev": true + }, "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", @@ -17027,9 +18290,9 @@ "integrity": "sha512-+G+EkOPoE5S/zChTpmBSSDYmhXJ5PsW8eMhH8cP/CQHMFPBG/kC9Y5IIw6qNYgdJ+/COf0ddY2li28iHaZRSjw==" }, "portfinder": { - "version": "1.0.25", - "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.25.tgz", - "integrity": "sha512-6ElJnHBbxVA1XSLgBp7G1FiCkQdlqGzuF7DswL5tcea+E8UpuvPU7beVAjjRwCioTS9ZluNbu+ZyRvgTsmqEBg==", + "version": "1.0.26", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.26.tgz", + "integrity": "sha512-Xi7mKxJHHMI3rIUrnm/jjUgwhbYMkp/XKEcZX3aG4BrumLpq3nmoQMX+ClYnDZnZ/New7IatC1no5RX0zo1vXQ==", "dev": true, "requires": { "async": "^2.6.2", @@ -17195,6 +18458,12 @@ "integrity": "sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==", "dev": true }, + "pretty-bytes": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.3.0.tgz", + "integrity": "sha512-hjGrh+P926p4R4WbaB6OckyRtO0F0/lQBiT+0gnxjV+5kjPBrfVBFCsCLbMqVQeydvIoouYTCmmEURiH3R1Bdg==", + "dev": true + }, "pretty-error": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-2.1.1.tgz", @@ -17345,6 +18614,12 @@ "warning": "^3.0.0" } }, + "propagate": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz", + "integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==", + "dev": true + }, "property-information": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/property-information/-/property-information-5.3.0.tgz", @@ -17378,6 +18653,15 @@ "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", "dev": true }, + "ps-tree": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.2.0.tgz", + "integrity": "sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==", + "dev": true, + "requires": { + "event-stream": "=3.3.4" + } + }, "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", @@ -17856,6 +19140,16 @@ "react-clientside-effect": "^1.2.0" } }, + "react-from-dom": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/react-from-dom/-/react-from-dom-0.3.1.tgz", + "integrity": "sha512-PeNBa8iuzoD7qHA9O7YpGnXFvC+XFFwStmFh2/r2zJAvEIaRg6EwOj+EPcDIFwyYBhqPIItxIx/dGdeWiFivjQ==" + }, + "react-gtm-module": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/react-gtm-module/-/react-gtm-module-2.0.8.tgz", + "integrity": "sha512-OU5FwAHC3gWnnxJ+MLwBMLZO1Pmn1DiVCGHqptwDnNojE3QRrNxjqozkW5cNS4Zp+C6HZ8a4ZIt0QPNlpzua4Q==" + }, "react-helmet": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/react-helmet/-/react-helmet-5.2.1.tgz", @@ -17990,6 +19284,28 @@ "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" }, + "react-markdown": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-4.3.1.tgz", + "integrity": "sha512-HQlWFTbDxTtNY6bjgp3C3uv1h2xcjCSi1zAEzfBW9OwJJvENSYiLXWNXN5hHLsoqai7RnZiiHzcnWdXk2Splzw==", + "requires": { + "html-to-react": "^1.3.4", + "mdast-add-list-metadata": "1.0.1", + "prop-types": "^15.7.2", + "react-is": "^16.8.6", + "remark-parse": "^5.0.0", + "unified": "^6.1.5", + "unist-util-visit": "^1.3.0", + "xtend": "^4.0.1" + }, + "dependencies": { + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + } + } + }, "react-moment": { "version": "0.9.7", "resolved": "https://registry.npmjs.org/react-moment/-/react-moment-0.9.7.tgz", @@ -18547,6 +19863,35 @@ "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", "dev": true }, + "remark-parse": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-5.0.0.tgz", + "integrity": "sha512-b3iXszZLH1TLoyUzrATcTQUZrwNl1rE70rVdSruJFlDaJ9z5aMkhrG43Pp68OgfHndL/ADz6V69Zow8cTQu+JA==", + "requires": { + "collapse-white-space": "^1.0.2", + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-whitespace-character": "^1.0.0", + "is-word-character": "^1.0.0", + "markdown-escapes": "^1.0.0", + "parse-entities": "^1.1.0", + "repeat-string": "^1.5.4", + "state-toggle": "^1.0.0", + "trim": "0.0.1", + "trim-trailing-lines": "^1.0.0", + "unherit": "^1.0.4", + "unist-util-remove-position": "^1.0.0", + "vfile-location": "^2.0.0", + "xtend": "^4.0.1" + }, + "dependencies": { + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + } + } + }, "remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", @@ -18592,8 +19937,7 @@ "repeat-string": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" }, "repeating": { "version": "2.0.1", @@ -18604,6 +19948,11 @@ "is-finite": "^1.0.0" } }, + "replace-ext": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=" + }, "replicator": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/replicator/-/replicator-1.0.3.tgz", @@ -18662,6 +20011,15 @@ } } }, + "request-progress": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz", + "integrity": "sha1-TKdUCBx/7GP1BeT6qCWqBs1mnb4=", + "dev": true, + "requires": { + "throttleit": "^1.0.0" + } + }, "request-promise-core": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.3.tgz", @@ -18830,6 +20188,12 @@ "inherits": "^2.0.1" } }, + "route-recognizer": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/route-recognizer/-/route-recognizer-0.3.4.tgz", + "integrity": "sha512-2+MhsfPhvauN1O8KaXpXAOfR/fwe8dnUXVM+xw7yt40lJRfPVQxV6yryZm0cgRvAj5fMF/mdRZbL2ptwbs5i2g==", + "dev": true + }, "rst-selector-parser": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/rst-selector-parser/-/rst-selector-parser-2.2.3.tgz", @@ -19143,6 +20507,12 @@ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, + "set-cookie-parser": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.4.6.tgz", + "integrity": "sha512-mNCnTUF0OYPwYzSHbdRdCfNNHqrne+HS5tS5xNb6yJbdP9wInV0q5xPLE0EyfV/Q3tImo3y/OXpD8Jn0Jtnjrg==", + "dev": true + }, "set-value": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", @@ -19177,6 +20547,12 @@ "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", "dev": true }, + "setup-polly-jest": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/setup-polly-jest/-/setup-polly-jest-0.8.0.tgz", + "integrity": "sha512-dY2vPM5c7mOoF7EbujEqapI6DgbG0x+yN/3cNW3coL7Kmypzu6Zwd978ssIzxAwjf9lXwhw8T9jMBjReDXf63A==", + "dev": true + }, "sha.js": { "version": "2.4.11", "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", @@ -19442,13 +20818,14 @@ } }, "sockjs": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.19.tgz", - "integrity": "sha512-V48klKZl8T6MzatbLlzzRNhMepEys9Y4oGFpypBFFn1gLI/QQ9HtLLyWJNbPlwGLelOVOEijUbTTJeLLI59jLw==", + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.20.tgz", + "integrity": "sha512-SpmVOVpdq0DJc0qArhF3E5xsxvaiqGNb73XfgBpK1y3UD5gs8DSo8aCTsuT5pX8rssdc2NDIzANwP9eCAiSdTA==", "dev": true, "requires": { "faye-websocket": "^0.10.0", - "uuid": "^3.0.1" + "uuid": "^3.4.0", + "websocket-driver": "0.6.5" }, "dependencies": { "faye-websocket": { @@ -19459,6 +20836,21 @@ "requires": { "websocket-driver": ">=0.5.1" } + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + }, + "websocket-driver": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.6.5.tgz", + "integrity": "sha1-XLJVbOuF9Dc8bYI4qmkchFThOjY=", + "dev": true, + "requires": { + "websocket-extensions": ">=0.1.1" + } } } }, @@ -19581,9 +20973,9 @@ "dev": true }, "spdy": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.1.tgz", - "integrity": "sha512-HeZS3PBdMA+sZSu0qwpCxl3DeALD5ASx8pAX0jZdKXSpPWbQ6SYGnlg3BBmYLx5LtiZrmkAZfErCm2oECBcioA==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", "dev": true, "requires": { "debug": "^4.1.0", @@ -19608,9 +21000,9 @@ }, "dependencies": { "readable-stream": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz", - "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", "dev": true, "requires": { "inherits": "^2.0.3", @@ -19620,6 +21012,15 @@ } } }, + "split": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", + "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", + "dev": true, + "requires": { + "through": "2" + } + }, "split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", @@ -19678,6 +21079,132 @@ "integrity": "sha1-M6qE8Rd6VUjIk1Uzy/6zQgl19aQ=", "dev": true }, + "start-server-and-test": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/start-server-and-test/-/start-server-and-test-1.11.0.tgz", + "integrity": "sha512-FhkJFYL/lvbd0tKWvbxWNWjtFtq3Zpa09QDjA8EUH88AsgNL4hkAAKYNmbac+fFM8/GIZoJ1Mj4mm3SMI0X1bA==", + "dev": true, + "requires": { + "bluebird": "3.7.2", + "check-more-types": "2.24.0", + "debug": "4.1.1", + "execa": "3.4.0", + "lazy-ass": "1.6.0", + "ps-tree": "1.2.0", + "wait-on": "4.0.0" + }, + "dependencies": { + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "execa": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-3.4.0.tgz", + "integrity": "sha512-r9vdGQk4bmCuK1yKQu1KTwcT2zwfWdbdaXfCtAh+5nU/4fSX+JAb7vZGvI5naJrQlvONrEB20jeruESI69530g==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "p-finally": "^2.0.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + } + }, + "get-stream": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz", + "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "requires": { + "path-key": "^3.0.0" + } + }, + "onetime": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz", + "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "p-finally": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-2.0.1.tgz", + "integrity": "sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw==", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "state-toggle": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.3.tgz", + "integrity": "sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ==" + }, "static-extend": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", @@ -19727,6 +21254,15 @@ "readable-stream": "^2.0.2" } }, + "stream-combiner": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", + "dev": true, + "requires": { + "duplexer": "~0.1.1" + } + }, "stream-each": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", @@ -19812,6 +21348,18 @@ } } }, + "string-similarity": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/string-similarity/-/string-similarity-1.2.2.tgz", + "integrity": "sha512-IoHUjcw3Srl8nsPlW04U3qwWPk3oG2ffLM0tN853d/E/JlIvcmZmDY2Kz5HzKp4lEi2T7QD7Zuvjq/1rDw+XcQ==", + "requires": { + "lodash.every": "^4.6.0", + "lodash.flattendeep": "^4.4.0", + "lodash.foreach": "^4.5.0", + "lodash.map": "^4.6.0", + "lodash.maxby": "^4.6.0" + } + }, "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", @@ -19953,9 +21501,9 @@ "dev": true }, "strip-json-comments": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", - "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.0.tgz", + "integrity": "sha512-e6/d0eBu7gHtdCqFt0xJr642LdToM5/cN4Qb9DbHjVx1CP5RyeM+zH7pbecEmDv/lBqb0QH+6Uqq75rxFPkM0w==", "dev": true }, "stubs": { @@ -20315,9 +21863,9 @@ } }, "testcafe": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/testcafe/-/testcafe-1.6.1.tgz", - "integrity": "sha512-ZVZPBUJUnNoGr+MrCMvY7nUAQU4vCmMfl7kZXpmnsqBSGeiwVGb7Sx4ebDFYMWgEAjtIOdDmw75BwKtHSboyIA==", + "version": "1.8.8", + "resolved": "https://registry.npmjs.org/testcafe/-/testcafe-1.8.8.tgz", + "integrity": "sha512-e8yLVU76fEWwh/UIkbTUSDa/e+J8BryErXqNf8itKHA/s9B6Mt9IfsVCCSYXUfx9DIruzcLNTsJ2q1xxc2KO+A==", "dev": true, "requires": { "@types/node": "^10.12.19", @@ -20328,20 +21876,22 @@ "babel-plugin-transform-runtime": "^6.22.0", "babel-preset-env": "^1.1.8", "babel-preset-flow": "^6.23.0", + "babel-preset-react": "^6.24.1", "babel-preset-stage-2": "^6.22.0", "babel-runtime": "^6.22.0", "bin-v8-flags-filter": "^1.1.2", + "bowser": "^2.8.1", "callsite": "^1.0.0", "callsite-record": "^4.0.0", "chai": "^4.1.2", "chalk": "^2.3.0", - "chrome-emulated-devices-list": "^0.1.0", "chrome-remote-interface": "^0.25.3", "coffeescript": "^2.3.1", "commander": "^2.8.1", "debug": "^2.2.0", "dedent": "^0.4.0", "del": "^3.0.0", + "device-specs": "^1.0.0", "elegant-spinner": "^1.0.1", "emittery": "^0.4.1", "endpoint-utils": "^1.0.2", @@ -20378,11 +21928,11 @@ "resolve-cwd": "^1.0.0", "resolve-from": "^4.0.0", "sanitize-filename": "^1.6.0", - "source-map-support": "^0.5.5", + "source-map-support": "^0.5.16", "strip-bom": "^2.0.0", - "testcafe-browser-tools": "1.7.1", - "testcafe-hammerhead": "14.10.2", - "testcafe-legacy-api": "3.1.11", + "testcafe-browser-tools": "2.0.12", + "testcafe-hammerhead": "17.1.9", + "testcafe-legacy-api": "4.0.0", "testcafe-reporter-json": "^2.1.0", "testcafe-reporter-list": "^2.1.0", "testcafe-reporter-minimal": "^2.1.0", @@ -20391,14 +21941,13 @@ "time-limit-promise": "^1.0.2", "tmp": "0.0.28", "tree-kill": "^1.1.0", - "typescript": "^3.3.3", - "useragent": "^2.1.7" + "typescript": "^3.3.3" }, "dependencies": { "@types/node": { - "version": "10.17.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.4.tgz", - "integrity": "sha512-F2pgg+LcIr/elguz+x+fdBX5KeZXGUOp7TV8M0TVIrDezYLFRNt8oMTyps0VQ1kj5WGGoR18RdxnRDHXrIFHMQ==", + "version": "10.17.28", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.28.tgz", + "integrity": "sha512-dzjES1Egb4c1a89C7lKwQh8pwjYmlOAG9dW1pBgxEk57tMrLnssOfEthz8kdkNaBd7lIqQx7APm5+mZ619IiCQ==", "dev": true }, "babel-core": { @@ -20497,15 +22046,6 @@ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", "dev": true - }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } } } }, @@ -20608,18 +22148,18 @@ "dev": true }, "make-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.0.0.tgz", - "integrity": "sha512-grNJDhb8b1Jm1qeqW5R/O63wUo4UXo2v2HMic6YT9i/HBlF93S8jkMgH7yugvY9ABDShH4VZMn8I+U8+fCNegw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", "dev": true, "requires": { "semver": "^6.0.0" } }, "mime-db": { - "version": "1.42.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.42.0.tgz", - "integrity": "sha512-UbfJCR4UAVRNgMpfImz05smAXK7+c+ZntjaA26ANtkXLlOe947Aag5zdIcKQULAiF9Cq4WxBi9jUs5zkA84bYQ==", + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", "dev": true }, "ms": { @@ -20678,6 +22218,15 @@ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", @@ -20711,16 +22260,18 @@ } }, "testcafe-browser-tools": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/testcafe-browser-tools/-/testcafe-browser-tools-1.7.1.tgz", - "integrity": "sha512-9Lf4MAmVrxbdP5PiwO2PpLGF3aOXWzlaxVDEDfO2p4orfJNiQ8eTZMMqWWPXDxE/5CqDq/h9xBXjvZo+1cW5ew==", + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/testcafe-browser-tools/-/testcafe-browser-tools-2.0.12.tgz", + "integrity": "sha512-5oNNYlcZiDspqJB6L8CfI4vxjzkvARSZv3pa+JrFAoqYmEA3VPiAvzrn+P0zi0D5jEPkKngW2KTpq6r3GfdDNw==", "dev": true, "requires": { "array-find": "^1.0.0", - "babel-runtime": "^5.6.15", + "dedent": "^0.7.0", "del": "^5.1.0", + "execa": "^3.3.0", "graceful-fs": "^4.1.11", "linux-platform-info": "^0.0.3", + "lodash": "^4.17.15", "mkdirp": "^0.5.1", "mustache": "^2.1.2", "nanoid": "^2.1.3", @@ -20731,25 +22282,84 @@ "which-promise": "^1.0.0" }, "dependencies": { - "babel-runtime": { - "version": "5.8.38", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-5.8.38.tgz", - "integrity": "sha1-HAsC62MxL18If/IEUIJ7QlydTBk=", + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, "requires": { - "core-js": "^1.0.0" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" } }, - "core-js": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", - "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=", + "execa": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-3.4.0.tgz", + "integrity": "sha512-r9vdGQk4bmCuK1yKQu1KTwcT2zwfWdbdaXfCtAh+5nU/4fSX+JAb7vZGvI5naJrQlvONrEB20jeruESI69530g==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "p-finally": "^2.0.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + } + }, + "get-stream": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz", + "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true }, "nanoid": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-2.1.6.tgz", - "integrity": "sha512-2NDzpiuEy3+H0AVtdt8LoFi7PnqkOnIzYmJQp7xsEU6VexLluHQwKREuiz57XaQC5006seIadPrIZJhyS2n7aw==", + "version": "2.1.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-2.1.11.tgz", + "integrity": "sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA==", + "dev": true + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "requires": { + "path-key": "^3.0.0" + } + }, + "onetime": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz", + "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "p-finally": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-2.0.1.tgz", + "integrity": "sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw==", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true }, "pify": { @@ -20757,13 +22367,37 @@ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } } } }, "testcafe-hammerhead": { - "version": "14.10.2", - "resolved": "https://registry.npmjs.org/testcafe-hammerhead/-/testcafe-hammerhead-14.10.2.tgz", - "integrity": "sha512-6xxaVU4vO9wHXFpDdyDWVnU1fuDMkvSjuYpKzjrsoA8kNc+zA9T35AMT7EI+pyh7amteJRtsD0jnRU+ASeAfdQ==", + "version": "17.1.9", + "resolved": "https://registry.npmjs.org/testcafe-hammerhead/-/testcafe-hammerhead-17.1.9.tgz", + "integrity": "sha512-RxlUsCkspdrWEWb9S2n9hwqX2RwRp5CFjRTN7Ijx+vnCcHKn5VPBhDlSrZHRiQT1yfa9+FudNsjmmrmlAGvCSg==", "dev": true, "requires": { "acorn-hammerhead": "^0.3.0", @@ -20772,8 +22406,9 @@ "brotli": "^1.3.1", "crypto-md5": "^1.0.0", "css": "2.2.3", - "esotope-hammerhead": "^0.4.0", - "iconv-lite": "0.4.11", + "debug": "4.1.1", + "esotope-hammerhead": "0.5.5", + "iconv-lite": "0.5.1", "lodash": "^4.17.13", "lru-cache": "2.6.3", "match-url-wildcard": "0.0.4", @@ -20791,12 +22426,21 @@ "webauth": "^1.1.0" }, "dependencies": { - "iconv-lite": { - "version": "0.4.11", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.11.tgz", - "integrity": "sha1-LstC/SlHRJIiCaLnxATayHk9it4=", + "bowser": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-1.6.0.tgz", + "integrity": "sha1-N/w4e2Fstq7zcNq01r1AK3TFxU0=", "dev": true }, + "iconv-lite": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.5.1.tgz", + "integrity": "sha512-ONHr16SQvKZNSqjQT9gy5z24Jw+uqfO02/ngBSBoqChZ+W8qXX7GPRa1RoUnzGADw8K63R1BXUMzarCVQBpY8Q==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, "lru-cache": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.6.3.tgz", @@ -20860,9 +22504,9 @@ } }, "testcafe-legacy-api": { - "version": "3.1.11", - "resolved": "https://registry.npmjs.org/testcafe-legacy-api/-/testcafe-legacy-api-3.1.11.tgz", - "integrity": "sha512-JWv8Exc9FAEBbKw+IP97Ebd+0FzA3nzgRv9iQCNh/+JlZyUox7NWiojs9BAXqgxIltl54rdo7TxPkNslxb+Ltw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/testcafe-legacy-api/-/testcafe-legacy-api-4.0.0.tgz", + "integrity": "sha512-Tn+YEH8hqDPQs/1/d+A9G+FdfejougtoWX0wRxrLq5ECYy2qxwH8p9EGDUNatLm0IFIumVpcz2tSZkvRpfKLSg==", "dev": true, "requires": { "async": "0.2.6", @@ -20989,6 +22633,12 @@ "integrity": "sha512-AOvyNahXQuU7NN+VVvOOX+uW6FPaWdAOdRP5HfwYxAfCzXTFKRMoIMk+n+po318+ktcChx+F1Dd91G3YHeMKyg==", "dev": true }, + "throttleit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", + "integrity": "sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw=", + "dev": true + }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -21079,6 +22729,15 @@ "tmp": "0.1.0" }, "dependencies": { + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, "tmp": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.1.0.tgz", @@ -21086,17 +22745,6 @@ "dev": true, "requires": { "rimraf": "^2.6.3" - }, - "dependencies": { - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } } } } @@ -21208,12 +22856,27 @@ "resolved": "https://registry.npmjs.org/treeify/-/treeify-1.1.0.tgz", "integrity": "sha512-1m4RA7xVAJrSGrrXGs0L3YTwyvBs2S8PbRHaLZAkFw7JR8oIFwYtysxlBZhYIa7xSyiYJKZ3iGrrk55cGA3i9A==" }, + "trim": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", + "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=" + }, "trim-right": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", "dev": true }, + "trim-trailing-lines": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.3.tgz", + "integrity": "sha512-4ku0mmjXifQcTVfYDfR5lpgV7zVqPg6zV9rdZmwOPqq0+Zq19xDqEgagqVbc4pOOShbncuAOIs59R3+3gcF3ZA==" + }, + "trough": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz", + "integrity": "sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==" + }, "truncate-utf8-bytes": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", @@ -21445,6 +23108,22 @@ "integrity": "sha512-crP/n3eAPUJxZXM9T80/yv0YhkTEx2K1D3h7D1AJM6fzsWZrxdyRuLN0JH/dkZh1LNH8LxCnBzoPFCPbb2iGpg==", "dev": true }, + "unherit": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.3.tgz", + "integrity": "sha512-Ft16BJcnapDKp0+J/rqFC3Rrk6Y/Ng4nzsC028k2jdDII/rdZ7Wd3pPT/6+vIIxRagwRc9K0IUX0Ra4fKvw+WQ==", + "requires": { + "inherits": "^2.0.0", + "xtend": "^4.0.0" + }, + "dependencies": { + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + } + } + }, "unicode-canonical-property-names-ecmascript": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", @@ -21473,6 +23152,19 @@ "integrity": "sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw==", "dev": true }, + "unified": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/unified/-/unified-6.2.0.tgz", + "integrity": "sha512-1k+KPhlVtqmG99RaTbAv/usu85fcSRu3wY8X+vnsEhIxNP5VbVIDiXnLqyKIG+UMdyTg0ZX9EI6k2AfjJkHPtA==", + "requires": { + "bail": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^1.1.0", + "trough": "^1.0.0", + "vfile": "^2.0.0", + "x-is-string": "^0.1.0" + } + }, "union-class-names": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/union-class-names/-/union-class-names-1.0.0.tgz", @@ -21514,6 +23206,47 @@ "imurmurhash": "^0.1.4" } }, + "unist-util-is": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-3.0.0.tgz", + "integrity": "sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A==" + }, + "unist-util-remove-position": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-1.1.4.tgz", + "integrity": "sha512-tLqd653ArxJIPnKII6LMZwH+mb5q+n/GtXQZo6S6csPRs5zB0u79Yw8ouR3wTw8wxvdJFhpP6Y7jorWdCgLO0A==", + "requires": { + "unist-util-visit": "^1.1.0" + } + }, + "unist-util-stringify-position": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-1.1.2.tgz", + "integrity": "sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ==" + }, + "unist-util-visit": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.4.1.tgz", + "integrity": "sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw==", + "requires": { + "unist-util-visit-parents": "^2.0.0" + }, + "dependencies": { + "unist-util-visit-parents": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz", + "integrity": "sha512-DyN5vD4NE3aSeB+PXYNKxzGsfocxp6asDc2XXE3b0ekO2BaRUpBicbbUygfSvYfUz1IkmjFR1YF7dPklraMZ2g==", + "requires": { + "unist-util-is": "^3.0.0" + } + } + } + }, + "unist-util-visit-parents": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-1.1.2.tgz", + "integrity": "sha512-yvo+MMLjEwdc3RhhPYSximset7rwjMrdt9E41Smmvg25UQIenzrN83cRnF1JMzoMi9zZOQeYXHSDf7p+IQkW3Q==" + }, "universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", @@ -21577,6 +23310,12 @@ } } }, + "untildify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "dev": true + }, "upath": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", @@ -21712,34 +23451,6 @@ "use-force-update": "^1.0.5" } }, - "useragent": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz", - "integrity": "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==", - "dev": true, - "requires": { - "lru-cache": "4.1.x", - "tmp": "0.0.x" - }, - "dependencies": { - "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - } - } - }, "utf8-byte-length": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz", @@ -21834,6 +23545,30 @@ "extsprintf": "^1.2.0" } }, + "vfile": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-2.3.0.tgz", + "integrity": "sha512-ASt4mBUHcTpMKD/l5Q+WJXNtshlWxOogYyGYYrg4lt/vuRjC1EFQtlAofL5VmtVNIZJzWYFJjzGWZ0Gw8pzW1w==", + "requires": { + "is-buffer": "^1.1.4", + "replace-ext": "1.0.0", + "unist-util-stringify-position": "^1.0.0", + "vfile-message": "^1.0.0" + } + }, + "vfile-location": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-2.0.6.tgz", + "integrity": "sha512-sSFdyCP3G6Ka0CEmN83A2YCMKIieHx0EDaj5IDP4g1pa5ZJ4FJDvpO0WODLxo4LUX4oe52gmSCK7Jw4SBghqxA==" + }, + "vfile-message": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-1.1.1.tgz", + "integrity": "sha512-1WmsopSGhWt5laNir+633LszXvZ+Z/lxveBf6yhGsqnQIhlhzooZae7zV6YVM1Sdkw68dtAW3ow0pOdPANugvA==", + "requires": { + "unist-util-stringify-position": "^1.1.1" + } + }, "vm-browserify": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", @@ -21882,6 +23617,31 @@ "browser-process-hrtime": "^0.1.2" } }, + "wait-on": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-4.0.0.tgz", + "integrity": "sha512-QrW3J8LzS5ADPfD9Rx5S6KJck66xkqyiFKQs9jmUTkIhiEOmkzU7WRZc+MjsnmkrgjitS2xQ4bb13hnlQnKBUQ==", + "dev": true, + "requires": { + "@hapi/joi": "^16.1.8", + "lodash": "^4.17.15", + "minimist": "^1.2.0", + "request": "^2.88.0", + "request-promise-native": "^1.0.8", + "rxjs": "^6.5.4" + }, + "dependencies": { + "rxjs": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.0.tgz", + "integrity": "sha512-3HMA8z/Oz61DUHe+SdOiQyzIf4tOx5oQHmMir7IZEu6TMqCLHT4LRcmNaUS0NwOz8VLvmmBduMsoaUvMaIiqzg==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + } + } + }, "walker": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz", @@ -21900,14 +23660,145 @@ } }, "watchpack": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", - "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.2.tgz", + "integrity": "sha512-ymVbbQP40MFTp+cNMvpyBpBtygHnPzPkHqoIwRRj/0B8KhqQwV8LaKjtbaxF2lK4vl8zN9wCxS46IFCU5K4W0g==", "dev": true, "requires": { - "chokidar": "^2.0.2", + "chokidar": "^3.4.0", "graceful-fs": "^4.1.2", - "neo-async": "^2.5.0" + "neo-async": "^2.5.0", + "watchpack-chokidar2": "^2.0.0" + }, + "dependencies": { + "anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "dev": true, + "optional": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "binary-extensions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", + "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", + "dev": true, + "optional": true + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "optional": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "chokidar": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.0.tgz", + "integrity": "sha512-aXAaho2VJtisB/1fg1+3nlLJqGOuewTzQpd/Tz0yTg2R0e4IGtshYvtjowyEumcBv2z+y4+kc75Mz7j5xJskcQ==", + "dev": true, + "optional": true, + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.1.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.4.0" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "optional": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "fsevents": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", + "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "dev": true, + "optional": true + }, + "glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "dev": true, + "optional": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "optional": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "optional": true + }, + "readdirp": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", + "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==", + "dev": true, + "optional": true, + "requires": { + "picomatch": "^2.2.1" + }, + "dependencies": { + "picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "dev": true, + "optional": true + } + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "optional": true, + "requires": { + "is-number": "^7.0.0" + } + } + } + }, + "watchpack-chokidar2": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.0.tgz", + "integrity": "sha512-9TyfOyN/zLUbA288wZ8IsMZ+6cbzvsNyEzSBp6e/zkifi6xxbl8SmQ/CxQq32k8NNqrdVEVUVSEf56L4rQ/ZxA==", + "dev": true, + "optional": true, + "requires": { + "chokidar": "^2.1.8" } }, "wbuf": { @@ -21932,16 +23823,16 @@ "dev": true }, "webpack": { - "version": "4.42.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.42.1.tgz", - "integrity": "sha512-SGfYMigqEfdGchGhFFJ9KyRpQKnipvEvjc1TwrXEPCM6H5Wywu10ka8o3KGrMzSMxMQKt8aCHUFh5DaQ9UmyRg==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.43.0.tgz", + "integrity": "sha512-GW1LjnPipFW2Y78OOab8NJlCflB7EFskMih2AHdvjbpKMeDJqEgSx24cXXXiPS65+WSwVyxtDsJH6jGX2czy+g==", "dev": true, "requires": { "@webassemblyjs/ast": "1.9.0", "@webassemblyjs/helper-module-context": "1.9.0", "@webassemblyjs/wasm-edit": "1.9.0", "@webassemblyjs/wasm-parser": "1.9.0", - "acorn": "^6.2.1", + "acorn": "^6.4.1", "ajv": "^6.10.2", "ajv-keywords": "^3.4.1", "chrome-trace-event": "^1.0.2", @@ -21958,194 +23849,8 @@ "schema-utils": "^1.0.0", "tapable": "^1.1.3", "terser-webpack-plugin": "^1.4.3", - "watchpack": "^1.6.0", + "watchpack": "^1.6.1", "webpack-sources": "^1.4.1" - }, - "dependencies": { - "@webassemblyjs/ast": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", - "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", - "dev": true, - "requires": { - "@webassemblyjs/helper-module-context": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/wast-parser": "1.9.0" - } - }, - "@webassemblyjs/floating-point-hex-parser": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz", - "integrity": "sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA==", - "dev": true - }, - "@webassemblyjs/helper-api-error": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", - "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==", - "dev": true - }, - "@webassemblyjs/helper-buffer": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz", - "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==", - "dev": true - }, - "@webassemblyjs/helper-code-frame": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz", - "integrity": "sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==", - "dev": true, - "requires": { - "@webassemblyjs/wast-printer": "1.9.0" - } - }, - "@webassemblyjs/helper-fsm": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz", - "integrity": "sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw==", - "dev": true - }, - "@webassemblyjs/helper-module-context": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz", - "integrity": "sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0" - } - }, - "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", - "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==", - "dev": true - }, - "@webassemblyjs/helper-wasm-section": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz", - "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-buffer": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/wasm-gen": "1.9.0" - } - }, - "@webassemblyjs/ieee754": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz", - "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==", - "dev": true, - "requires": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "@webassemblyjs/leb128": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz", - "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==", - "dev": true, - "requires": { - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/utf8": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz", - "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==", - "dev": true - }, - "@webassemblyjs/wasm-edit": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz", - "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-buffer": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/helper-wasm-section": "1.9.0", - "@webassemblyjs/wasm-gen": "1.9.0", - "@webassemblyjs/wasm-opt": "1.9.0", - "@webassemblyjs/wasm-parser": "1.9.0", - "@webassemblyjs/wast-printer": "1.9.0" - } - }, - "@webassemblyjs/wasm-gen": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz", - "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/ieee754": "1.9.0", - "@webassemblyjs/leb128": "1.9.0", - "@webassemblyjs/utf8": "1.9.0" - } - }, - "@webassemblyjs/wasm-opt": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz", - "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-buffer": "1.9.0", - "@webassemblyjs/wasm-gen": "1.9.0", - "@webassemblyjs/wasm-parser": "1.9.0" - } - }, - "@webassemblyjs/wasm-parser": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz", - "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-api-error": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/ieee754": "1.9.0", - "@webassemblyjs/leb128": "1.9.0", - "@webassemblyjs/utf8": "1.9.0" - } - }, - "@webassemblyjs/wast-parser": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz", - "integrity": "sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/floating-point-hex-parser": "1.9.0", - "@webassemblyjs/helper-api-error": "1.9.0", - "@webassemblyjs/helper-code-frame": "1.9.0", - "@webassemblyjs/helper-fsm": "1.9.0", - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/wast-printer": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", - "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/wast-parser": "1.9.0", - "@xtuc/long": "4.2.2" - } - }, - "mkdirp": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.4.tgz", - "integrity": "sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - } } }, "webpack-cli": { @@ -22253,9 +23958,9 @@ } }, "webpack-dev-server": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.10.1.tgz", - "integrity": "sha512-AGG4+XrrXn4rbZUueyNrQgO4KGnol+0wm3MPdqGLmmA+NofZl3blZQKxZ9BND6RDNuvAK9OMYClhjOSnxpWRoA==", + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.11.0.tgz", + "integrity": "sha512-PUxZ+oSTxogFQgkTtFndEtJIPNmml7ExwufBZ9L2/Xyyd5PnOL5UreWe5ZT7IU25DSdykL9p1MLQzmLh2ljSeg==", "dev": true, "requires": { "ansi-html": "0.0.7", @@ -22266,31 +23971,31 @@ "debug": "^4.1.1", "del": "^4.1.1", "express": "^4.17.1", - "html-entities": "^1.2.1", + "html-entities": "^1.3.1", "http-proxy-middleware": "0.19.1", "import-local": "^2.0.0", "internal-ip": "^4.3.0", "ip": "^1.1.5", "is-absolute-url": "^3.0.3", "killable": "^1.0.1", - "loglevel": "^1.6.6", + "loglevel": "^1.6.8", "opn": "^5.5.0", "p-retry": "^3.0.1", - "portfinder": "^1.0.25", + "portfinder": "^1.0.26", "schema-utils": "^1.0.0", "selfsigned": "^1.10.7", "semver": "^6.3.0", "serve-index": "^1.9.1", - "sockjs": "0.3.19", + "sockjs": "0.3.20", "sockjs-client": "1.4.0", - "spdy": "^4.0.1", + "spdy": "^4.0.2", "strip-ansi": "^3.0.1", "supports-color": "^6.1.0", "url": "^0.11.0", "webpack-dev-middleware": "^3.7.2", "webpack-log": "^2.0.0", "ws": "^6.2.1", - "yargs": "12.0.5" + "yargs": "^13.3.2" }, "dependencies": { "ansi-regex": { @@ -22299,34 +24004,6 @@ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "dev": true }, - "cliui": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", - "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", - "dev": true, - "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } - } - }, "del": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", @@ -22342,12 +24019,6 @@ "rimraf": "^2.6.3" } }, - "get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", - "dev": true - }, "globby": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", @@ -22369,14 +24040,11 @@ } } }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } + "html-entities": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.3.1.tgz", + "integrity": "sha512-rhE/4Z3hIhzHAUKbW8jVcCyuT5oJCXXqhN/6mXXVCpzTmvJnoH2HL/bt3EZ6p55jbFJBeAe1ZNpL5BugLujxNA==", + "dev": true }, "is-path-in-cwd": { "version": "2.1.0", @@ -22396,10 +24064,10 @@ "path-is-inside": "^1.0.2" } }, - "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "loglevel": { + "version": "1.6.8", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.8.tgz", + "integrity": "sha512-bsU7+gc9AJ2SqpzxwU3+1fedl8zAntbtC5XYlt3s2j1hJcn2PsXSmgN8TaLG/J1/2mod4+cE/3vNL70/c1RNCA==", "dev": true }, "rimraf": { @@ -22417,6 +24085,34 @@ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, "strip-ansi": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", @@ -22435,29 +24131,6 @@ "has-flag": "^3.0.0" } }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - }, - "dependencies": { - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - } - } - }, "ws": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", @@ -22468,33 +24141,21 @@ } }, "yargs": { - "version": "12.0.5", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", - "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", "dev": true, "requires": { - "cliui": "^4.0.0", - "decamelize": "^1.2.0", + "cliui": "^5.0.0", "find-up": "^3.0.0", - "get-caller-file": "^1.0.1", - "os-locale": "^3.0.0", + "get-caller-file": "^2.0.1", "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", + "require-main-filename": "^2.0.0", "set-blocking": "^2.0.0", - "string-width": "^2.0.0", + "string-width": "^3.0.0", "which-module": "^2.0.0", - "y18n": "^3.2.1 || ^4.0.0", - "yargs-parser": "^11.1.1" - } - }, - "yargs-parser": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", - "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" } } } @@ -22568,9 +24229,9 @@ } }, "websocket-extensions": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz", - "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==", + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", "dev": true }, "whatwg-encoding": { @@ -22752,6 +24413,11 @@ "async-limiter": "~1.0.0" } }, + "x-is-string": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/x-is-string/-/x-is-string-0.1.0.tgz", + "integrity": "sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI=" + }, "xml-name-validator": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", @@ -22811,9 +24477,9 @@ } }, "yargs-parser": { - "version": "13.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", - "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", "dev": true, "requires": { "camelcase": "^5.0.0", @@ -22825,6 +24491,16 @@ "resolved": "https://registry.npmjs.org/yarn/-/yarn-1.22.0.tgz", "integrity": "sha512-KMHP/Jq53jZKTY9iTUt3dIVl/be6UPs2INo96+BnZHLKxYNTfwMmlgHTaMWyGZoO74RI4AIFvnWhYrXq2USJkg==" }, + "yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", + "dev": true, + "requires": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, "yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", diff --git a/package.json b/package.json index 9a8351045..14d84ddec 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "saleor-dashboard", - "version": "2.10.1", + "version": "2.11.0-a.0", "main": "src/index.tsx", "repository": { "type": "git", @@ -20,6 +20,7 @@ "@material-ui/core": "^4.5.1", "@material-ui/icons": "^4.5.1", "@material-ui/styles": "^4.5.2", + "@saleor/macaw-ui": "^0.1.1-9", "apollo": "^2.21.2", "apollo-cache-inmemory": "^1.6.5", "apollo-client": "^2.6.8", @@ -52,11 +53,13 @@ "react-dom": "^16.9.0", "react-dropzone": "^8.2.0", "react-error-boundary": "^1.2.5", + "react-gtm-module": "^2.0.8", "react-helmet": "^5.2.1", "react-infinite-scroller": "^1.2.4", "react-inlinesvg": "^0.8.4", "react-intl": "^3.1.8", "react-jss": "^10.0.0", + "react-markdown": "^4.3.1", "react-moment": "^0.9.7", "react-router": "^5.0.1", "react-router-dom": "^5.0.1", @@ -80,6 +83,9 @@ "@babel/preset-react": "^7.7.4", "@babel/preset-typescript": "^7.7.4", "@babel/runtime": "^7.7.6", + "@pollyjs/adapter-node-http": "^4.3.0", + "@pollyjs/core": "^4.3.0", + "@pollyjs/persister-fs": "^4.3.0", "@storybook/addon-storyshots": "^5.2.8", "@storybook/react": "^5.1.9", "@testing-library/react-hooks": "^1.1.0", @@ -90,6 +96,9 @@ "@types/jest": "^24.0.24", "@types/lodash-es": "^4.17.3", "@types/moment-timezone": "^0.5.12", + "@types/node-fetch": "^2.5.7", + "@types/pollyjs__adapter-node-http": "^2.0.0", + "@types/pollyjs__persister-fs": "^2.0.0", "@types/react": "^16.9.16", "@types/react-dom": "^16.8.5", "@types/react-dropzone": "^4.2.2", @@ -100,6 +109,7 @@ "@types/react-sortable-tree": "^0.3.6", "@types/react-test-renderer": "^16.8.2", "@types/semver-compare": "^1.0.1", + "@types/setup-polly-jest": "^0.5.0", "@types/storybook__addon-storyshots": "^3.4.9", "@types/storybook__react": "^4.0.2", "@types/url-join": "^4.0.0", @@ -111,41 +121,51 @@ "babel-loader": "^8.0.6", "babel-plugin-react-intl": "^5.1.11", "babel-plugin-react-intl-auto": "^3.1.0", - "codecov": "^3.6.5", + "codecov": "^3.7.1", "core-js": "^3.5.0", "cross-env": "^6.0.3", + "cypress": "^4.9.0", "enzyme": "^3.10.0", "enzyme-adapter-react-16": "^1.14.0", "enzyme-to-json": "^3.3.5", - "eslint": "^6.7.1", + "eslint": "^6.8.0", "eslint-loader": "^3.0.2", "eslint-plugin-import": "^2.19.1", "eslint-plugin-local-rules": "^0.1.1", "eslint-plugin-prefer-arrow": "^1.1.6", + "eslint-plugin-simple-import-sort": "^5.0.3", "file-loader": "^5.0.2", "fork-ts-checker-webpack-plugin": "^3.1.1", "html-webpack-plugin": "^3.2.0", "husky": "^3.0.8", "jest": "^24.8.0", "jest-file": "^1.0.0", + "jest-localstorage-mock": "^2.4.3", "lint-staged": "^9.4.2", + "mock-apollo-client": "^0.4.0", + "node-fetch": "^2.6.1", "prettier": "^1.19.1", "react-intl-translations-manager": "^5.0.3", "react-test-renderer": "^16.12.0", "regenerator-runtime": "^0.11.1", "require-context.macro": "^1.1.1", "rimraf": "^3.0.0", + "start-server-and-test": "^1.11.0", + "setup-polly-jest": "^0.8.0", "testcafe": "^1.3.3", "ts-jest": "^24.2.0", "tsconfig-paths-webpack-plugin": "^3.2.0", "webpack": "^4.35.3", "webpack-cli": "^3.3.6", - "webpack-dev-server": "^3.10.1" + "webpack-dev-server": "^3.11.0" }, "optionalDependencies": { "fsevents": "^1.2.9" }, "jest": { + "setupFiles": [ + "jest-localstorage-mock" + ], "transform": { "^.+\\.(jsx?|tsx?)$": "babel-jest", "^.+\\.(png|svg|jpe?g)$": "jest-file" @@ -162,7 +182,7 @@ "moduleNameMapper": { "@assets(.*)$": "/assets/$1", "@locale(.*)$": "/locale/$1", - "@saleor(.*)$": "/src/$1", + "@saleor(?!.*macaw)(.*)$": "/src/$1", "@test/(.*)$": "/testUtils/$1", "^lodash-es(.*)$": "lodash/$1" } @@ -178,22 +198,33 @@ "eslint --fix", "prettier --write", "git add" + ], + "*.{js,jsx}": [ + "eslint --fix", + "prettier --write", + "git add" ] }, "scripts": { - "build": "webpack -p", - "extract-json-messages": "rimraf build/locale && cross-env NODE_ENV=extract babel src 'src/**/*.{ts,tsx}' -o build/dashboard.bundle.js", - "transpile-messages": "node scripts/transpile-tx.js", - "extract-messages": "npm run extract-json-messages && npm run transpile-messages", - "build-types": "apollo client:codegen --target=typescript types --globalTypesFile=src/types/globalTypes.ts", - "check-types": "tsc --noEmit", - "check-strict-null-errors": "tsc --noEmit --strictNullChecks | node scripts/count-strict-null-check-errors.js", - "generate-component": "plop --plopfile .plop/plopfile.js", - "start": "webpack-dev-server --open -d", - "storybook": "start-storybook -p 3000 -c src/storybook/", "build-storybook": "build-storybook -c src/storybook/ -o build/storybook", + "build-types": "apollo client:codegen --target=typescript types --globalTypesFile=src/types/globalTypes.ts", + "build": "webpack -p", + "check-strict-null-errors": "tsc --noEmit --strictNullChecks | node scripts/count-strict-null-check-errors.js", + "check-types": "tsc --noEmit", + "extract-json-messages": "rimraf build/locale && cross-env NODE_ENV=extract babel src 'src/**/*.{ts,tsx}' -o build/dashboard.bundle.js", + "extract-messages": "npm run extract-json-messages && npm run transpile-messages", + "heroku-postbuild": "npm run build", + "serve:lhci": "NODE_ENV=production npm run server", + "start": "webpack-dev-server -d", + "storybook": "start-storybook -p 3000 -c src/storybook/", + "cy:run": "cypress run", + "cy:run:record": "npm run cy:run -- --record", + "cy:open": "cypress open", + "test:e2e:run": "start-server-and-test start http://localhost:9000 cy:run", + "test:e2e:run:record": "start-server-and-test start http://localhost:9000 cy:run:record", + "test:e2e:dev": "start-server-and-test start http://localhost:9000 cy:open", "test": "jest src/", - "test-e2e": "testcafe 'chrome:headless' .testcafe", - "heroku-postbuild": "npm run build" + "transpile-messages": "node scripts/transpile-tx.js", + "lint": "npx eslint \"src/**/*.@(tsx|ts|jsx|js)\" --fix ; npx prettier --check \"src/**/*.@(tsx|ts|jsx|js)\" --write" } } diff --git a/recordings/User_3768991250/will-be-logged-if-has-valid-token_3465908808/recording.har b/recordings/User_3768991250/will-be-logged-if-has-valid-token_3465908808/recording.har new file mode 100644 index 000000000..8ad594963 --- /dev/null +++ b/recordings/User_3768991250/will-be-logged-if-has-valid-token_3465908808/recording.har @@ -0,0 +1,128 @@ +{ + "log": { + "_recordingName": "User/will be logged if has valid token", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "4.3.0" + }, + "entries": [ + { + "_id": "f515e15cbc83df73e5bd41437971c2e6", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 691, + "cookies": [], + "headers": [ + { + "_fromType": "array", + "name": "accept", + "value": "*/*" + }, + { + "_fromType": "array", + "name": "content-type", + "value": "application/json" + }, + { + "_fromType": "array", + "name": "content-length", + "value": "691" + }, + { + "_fromType": "array", + "name": "user-agent", + "value": "node-fetch/1.0 (+https://github.com/bitinn/node-fetch)" + }, + { + "_fromType": "array", + "name": "accept-encoding", + "value": "gzip,deflate" + }, + { + "_fromType": "array", + "name": "connection", + "value": "close" + }, + { + "name": "host", + "value": "localhost:8000" + } + ], + "headersSize": 254, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/json", + "params": [], + "text": "[{\"operationName\":\"VerifyToken\",\"variables\":{\"token\":\"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1OTYwMjgyMTgsImV4cCI6MTU5NjAyODUxOCwidG9rZW4iOiJDM1NrMmtMUlZ1UEEiLCJlbWFpbCI6ImFkbWluQGV4YW1wbGUuY29tIiwidHlwZSI6ImFjY2VzcyIsInVzZXJfaWQiOiJWWE5sY2pveU1RPT0iLCJpc19zdGFmZiI6dHJ1ZX0.eo8_Ew98HICB4cFQN2U7mCJ8ydGVOvQLGRT4CnkufMc\"},\"query\":\"fragment User on User {\\n id\\n email\\n firstName\\n lastName\\n userPermissions {\\n code\\n name\\n __typename\\n }\\n avatar {\\n url\\n __typename\\n }\\n __typename\\n}\\n\\nmutation VerifyToken($token: String!) {\\n tokenVerify(token: $token) {\\n payload\\n user {\\n ...User\\n __typename\\n }\\n __typename\\n }\\n}\\n\"}]" + }, + "queryString": [], + "url": "http://localhost:8000/graphql/" + }, + "response": { + "bodySize": 1619, + "content": { + "mimeType": "application/json", + "size": 1619, + "text": "[{\"data\": {\"tokenVerify\": {\"payload\": {\"iat\": 1596028218, \"exp\": 1596028518, \"token\": \"C3Sk2kLRVuPA\", \"email\": \"admin@example.com\", \"type\": \"access\", \"user_id\": \"VXNlcjoyMQ==\", \"is_staff\": true}, \"user\": {\"id\": \"VXNlcjoyMQ==\", \"email\": \"admin@example.com\", \"firstName\": \"\", \"lastName\": \"\", \"userPermissions\": [{\"code\": \"MANAGE_APPS\", \"name\": \"Manage apps\", \"__typename\": \"UserPermission\"}, {\"code\": \"MANAGE_CHECKOUTS\", \"name\": \"Manage checkouts\", \"__typename\": \"UserPermission\"}, {\"code\": \"MANAGE_DISCOUNTS\", \"name\": \"Manage sales and vouchers.\", \"__typename\": \"UserPermission\"}, {\"code\": \"MANAGE_GIFT_CARD\", \"name\": \"Manage gift cards.\", \"__typename\": \"UserPermission\"}, {\"code\": \"MANAGE_MENUS\", \"name\": \"Manage navigation.\", \"__typename\": \"UserPermission\"}, {\"code\": \"MANAGE_ORDERS\", \"name\": \"Manage orders.\", \"__typename\": \"UserPermission\"}, {\"code\": \"MANAGE_PAGES\", \"name\": \"Manage pages.\", \"__typename\": \"UserPermission\"}, {\"code\": \"MANAGE_PLUGINS\", \"name\": \"Manage plugins\", \"__typename\": \"UserPermission\"}, {\"code\": \"MANAGE_PRODUCTS\", \"name\": \"Manage products.\", \"__typename\": \"UserPermission\"}, {\"code\": \"MANAGE_SETTINGS\", \"name\": \"Manage settings.\", \"__typename\": \"UserPermission\"}, {\"code\": \"MANAGE_SHIPPING\", \"name\": \"Manage shipping.\", \"__typename\": \"UserPermission\"}, {\"code\": \"MANAGE_STAFF\", \"name\": \"Manage staff.\", \"__typename\": \"UserPermission\"}, {\"code\": \"MANAGE_TRANSLATIONS\", \"name\": \"Manage translations.\", \"__typename\": \"UserPermission\"}, {\"code\": \"MANAGE_USERS\", \"name\": \"Manage customers.\", \"__typename\": \"UserPermission\"}], \"avatar\": null, \"__typename\": \"User\"}, \"__typename\": \"VerifyToken\"}}}]" + }, + "cookies": [], + "headers": [ + { + "name": "date", + "value": "Wed, 29 Jul 2020 13:10:18 GMT" + }, + { + "name": "server", + "value": "WSGIServer/0.2 CPython/3.8.1" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "access-control-allow-origin", + "value": "http://localhost:9000" + }, + { + "name": "access-control-allow-methods", + "value": "POST, OPTIONS" + }, + { + "name": "access-control-allow-headers", + "value": "Origin, Content-Type, Accept, Authorization" + }, + { + "name": "content-length", + "value": "1619" + }, + { + "name": "x-content-type-options", + "value": "nosniff" + } + ], + "headersSize": 336, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2020-07-29T13:10:18.327Z", + "time": 23, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 23 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/recordings/User_3768991250/will-be-logged-in-if-has-valid-credentials_3587751314/recording.har b/recordings/User_3768991250/will-be-logged-in-if-has-valid-credentials_3587751314/recording.har new file mode 100644 index 000000000..be977fd9c --- /dev/null +++ b/recordings/User_3768991250/will-be-logged-in-if-has-valid-credentials_3587751314/recording.har @@ -0,0 +1,141 @@ +{ + "log": { + "_recordingName": "User/will be logged in if has valid credentials", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "4.3.0" + }, + "entries": [ + { + "_id": "7c460842cac4a92c188d5451dfc533a2", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 587, + "cookies": [], + "headers": [ + { + "_fromType": "array", + "name": "accept", + "value": "*/*" + }, + { + "_fromType": "array", + "name": "content-type", + "value": "application/json" + }, + { + "_fromType": "array", + "name": "content-length", + "value": "587" + }, + { + "_fromType": "array", + "name": "user-agent", + "value": "node-fetch/1.0 (+https://github.com/bitinn/node-fetch)" + }, + { + "_fromType": "array", + "name": "accept-encoding", + "value": "gzip,deflate" + }, + { + "_fromType": "array", + "name": "connection", + "value": "close" + }, + { + "name": "host", + "value": "localhost:8000" + } + ], + "headersSize": 254, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/json", + "params": [], + "text": "[{\"operationName\":\"TokenAuth\",\"variables\":{\"email\":\"admin@example.com\",\"password\":\"admin\"},\"query\":\"fragment User on User {\\n id\\n email\\n firstName\\n lastName\\n userPermissions {\\n code\\n name\\n __typename\\n }\\n avatar {\\n url\\n __typename\\n }\\n __typename\\n}\\n\\nmutation TokenAuth($email: String!, $password: String!) {\\n tokenCreate(email: $email, password: $password) {\\n errors: accountErrors {\\n field\\n message\\n __typename\\n }\\n csrfToken\\n token\\n user {\\n ...User\\n __typename\\n }\\n __typename\\n }\\n}\\n\"}]" + }, + "queryString": [], + "url": "http://localhost:8000/graphql/" + }, + "response": { + "bodySize": 1830, + "content": { + "mimeType": "application/json", + "size": 1830, + "text": "[{\"data\": {\"tokenCreate\": {\"errors\": [], \"csrfToken\": \"rLPNMGNYKXH8VY4UNEWl4nEOFMseocljioigPl36IM2CqbdmOTEpNwvdHBAJ1ZWQ\", \"token\": \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1OTYwMjgyMTgsImV4cCI6MTU5NjAyODUxOCwidG9rZW4iOiJDM1NrMmtMUlZ1UEEiLCJlbWFpbCI6ImFkbWluQGV4YW1wbGUuY29tIiwidHlwZSI6ImFjY2VzcyIsInVzZXJfaWQiOiJWWE5sY2pveU1RPT0iLCJpc19zdGFmZiI6dHJ1ZX0.eo8_Ew98HICB4cFQN2U7mCJ8ydGVOvQLGRT4CnkufMc\", \"user\": {\"id\": \"VXNlcjoyMQ==\", \"email\": \"admin@example.com\", \"firstName\": \"\", \"lastName\": \"\", \"userPermissions\": [{\"code\": \"MANAGE_APPS\", \"name\": \"Manage apps\", \"__typename\": \"UserPermission\"}, {\"code\": \"MANAGE_CHECKOUTS\", \"name\": \"Manage checkouts\", \"__typename\": \"UserPermission\"}, {\"code\": \"MANAGE_DISCOUNTS\", \"name\": \"Manage sales and vouchers.\", \"__typename\": \"UserPermission\"}, {\"code\": \"MANAGE_GIFT_CARD\", \"name\": \"Manage gift cards.\", \"__typename\": \"UserPermission\"}, {\"code\": \"MANAGE_MENUS\", \"name\": \"Manage navigation.\", \"__typename\": \"UserPermission\"}, {\"code\": \"MANAGE_ORDERS\", \"name\": \"Manage orders.\", \"__typename\": \"UserPermission\"}, {\"code\": \"MANAGE_PAGES\", \"name\": \"Manage pages.\", \"__typename\": \"UserPermission\"}, {\"code\": \"MANAGE_PLUGINS\", \"name\": \"Manage plugins\", \"__typename\": \"UserPermission\"}, {\"code\": \"MANAGE_PRODUCTS\", \"name\": \"Manage products.\", \"__typename\": \"UserPermission\"}, {\"code\": \"MANAGE_SETTINGS\", \"name\": \"Manage settings.\", \"__typename\": \"UserPermission\"}, {\"code\": \"MANAGE_SHIPPING\", \"name\": \"Manage shipping.\", \"__typename\": \"UserPermission\"}, {\"code\": \"MANAGE_STAFF\", \"name\": \"Manage staff.\", \"__typename\": \"UserPermission\"}, {\"code\": \"MANAGE_TRANSLATIONS\", \"name\": \"Manage translations.\", \"__typename\": \"UserPermission\"}, {\"code\": \"MANAGE_USERS\", \"name\": \"Manage customers.\", \"__typename\": \"UserPermission\"}], \"avatar\": null, \"__typename\": \"User\"}, \"__typename\": \"CreateToken\"}}}]" + }, + "cookies": [ + { + "httpOnly": true, + "name": "refreshToken", + "path": "/", + "secure": true, + "value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1OTYwMjgyMTgsImV4cCI6MTU5ODYyMDIxOCwidG9rZW4iOiJDM1NrMmtMUlZ1UEEiLCJlbWFpbCI6ImFkbWluQGV4YW1wbGUuY29tIiwidHlwZSI6InJlZnJlc2giLCJ1c2VyX2lkIjoiVlhObGNqb3lNUT09IiwiaXNfc3RhZmYiOnRydWUsImNzcmZUb2tlbiI6InJMUE5NR05ZS1hIOFZZNFVORVdsNG5FT0ZNc2VvY2xqaW9pZ1BsMzZJTTJDcWJkbU9URXBOd3ZkSEJBSjFaV1EifQ.boD8G4pkSnZF-PLl5oOg85Uj-mqTiAzOkua9aAG3Bz4" + } + ], + "headers": [ + { + "name": "date", + "value": "Wed, 29 Jul 2020 13:10:18 GMT" + }, + { + "name": "server", + "value": "WSGIServer/0.2 CPython/3.8.1" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "access-control-allow-origin", + "value": "http://localhost:9000" + }, + { + "name": "access-control-allow-methods", + "value": "POST, OPTIONS" + }, + { + "name": "access-control-allow-headers", + "value": "Origin, Content-Type, Accept, Authorization" + }, + { + "name": "content-length", + "value": "1830" + }, + { + "name": "x-content-type-options", + "value": "nosniff" + }, + { + "_fromType": "array", + "name": "set-cookie", + "value": "refreshToken=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1OTYwMjgyMTgsImV4cCI6MTU5ODYyMDIxOCwidG9rZW4iOiJDM1NrMmtMUlZ1UEEiLCJlbWFpbCI6ImFkbWluQGV4YW1wbGUuY29tIiwidHlwZSI6InJlZnJlc2giLCJ1c2VyX2lkIjoiVlhObGNqb3lNUT09IiwiaXNfc3RhZmYiOnRydWUsImNzcmZUb2tlbiI6InJMUE5NR05ZS1hIOFZZNFVORVdsNG5FT0ZNc2VvY2xqaW9pZ1BsMzZJTTJDcWJkbU9URXBOd3ZkSEJBSjFaV1EifQ.boD8G4pkSnZF-PLl5oOg85Uj-mqTiAzOkua9aAG3Bz4; HttpOnly; Path=/; Secure" + } + ], + "headersSize": 768, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2020-07-29T13:10:18.064Z", + "time": 118, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 118 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/recordings/User_3768991250/will-not-be-logged-if-has-expired-token_544348836/recording.har b/recordings/User_3768991250/will-not-be-logged-if-has-expired-token_544348836/recording.har new file mode 100644 index 000000000..775ee5be6 --- /dev/null +++ b/recordings/User_3768991250/will-not-be-logged-if-has-expired-token_544348836/recording.har @@ -0,0 +1,128 @@ +{ + "log": { + "_recordingName": "User/will not be logged if has expired token", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "4.3.0" + }, + "entries": [ + { + "_id": "414f6b24b58b132c92e9a6ea67613a15", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 691, + "cookies": [], + "headers": [ + { + "_fromType": "array", + "name": "accept", + "value": "*/*" + }, + { + "_fromType": "array", + "name": "content-type", + "value": "application/json" + }, + { + "_fromType": "array", + "name": "content-length", + "value": "691" + }, + { + "_fromType": "array", + "name": "user-agent", + "value": "node-fetch/1.0 (+https://github.com/bitinn/node-fetch)" + }, + { + "_fromType": "array", + "name": "accept-encoding", + "value": "gzip,deflate" + }, + { + "_fromType": "array", + "name": "connection", + "value": "close" + }, + { + "name": "host", + "value": "localhost:8000" + } + ], + "headersSize": 254, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/json", + "params": [], + "text": "[{\"operationName\":\"VerifyToken\",\"variables\":{\"token\":\"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1OTUyMzk4OTcsImV4cCI6MTU5NTI0MDE5NywidG9rZW4iOiJxQ1Jia0dOMnpOT28iLCJlbWFpbCI6ImFkbWluQGV4YW1wbGUuY29tIiwidHlwZSI6ImFjY2VzcyIsInVzZXJfaWQiOiJWWE5sY2pveU1RPT0iLCJpc19zdGFmZiI6dHJ1ZX0.l-FnFDVmi5fASo7Uae2Emewu2pKyO2qLz7ZQl1fSzo4\"},\"query\":\"fragment User on User {\\n id\\n email\\n firstName\\n lastName\\n userPermissions {\\n code\\n name\\n __typename\\n }\\n avatar {\\n url\\n __typename\\n }\\n __typename\\n}\\n\\nmutation VerifyToken($token: String!) {\\n tokenVerify(token: $token) {\\n payload\\n user {\\n ...User\\n __typename\\n }\\n __typename\\n }\\n}\\n\"}]" + }, + "queryString": [], + "url": "http://localhost:8000/graphql/" + }, + "response": { + "bodySize": 89, + "content": { + "mimeType": "application/json", + "size": 89, + "text": "[{\"data\": {\"tokenVerify\": {\"payload\": null, \"user\": null, \"__typename\": \"VerifyToken\"}}}]" + }, + "cookies": [], + "headers": [ + { + "name": "date", + "value": "Tue, 21 Jul 2020 13:43:50 GMT" + }, + { + "name": "server", + "value": "WSGIServer/0.2 CPython/3.8.1" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-allow-methods", + "value": "POST, OPTIONS" + }, + { + "name": "access-control-allow-headers", + "value": "Origin, Content-Type, Accept, Authorization" + }, + { + "name": "content-length", + "value": "89" + }, + { + "name": "x-content-type-options", + "value": "nosniff" + } + ], + "headersSize": 314, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2020-07-21T13:43:50.249Z", + "time": 17, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 17 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/recordings/User_3768991250/will-not-be-logged-if-has-invalid-token_1301762210/recording.har b/recordings/User_3768991250/will-not-be-logged-if-has-invalid-token_1301762210/recording.har new file mode 100644 index 000000000..8e4ea3f81 --- /dev/null +++ b/recordings/User_3768991250/will-not-be-logged-if-has-invalid-token_1301762210/recording.har @@ -0,0 +1,128 @@ +{ + "log": { + "_recordingName": "User/will not be logged if has invalid token", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "4.3.0" + }, + "entries": [ + { + "_id": "4836098613648775386c1e10728424dd", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 428, + "cookies": [], + "headers": [ + { + "_fromType": "array", + "name": "accept", + "value": "*/*" + }, + { + "_fromType": "array", + "name": "content-type", + "value": "application/json" + }, + { + "_fromType": "array", + "name": "content-length", + "value": "428" + }, + { + "_fromType": "array", + "name": "user-agent", + "value": "node-fetch/1.0 (+https://github.com/bitinn/node-fetch)" + }, + { + "_fromType": "array", + "name": "accept-encoding", + "value": "gzip,deflate" + }, + { + "_fromType": "array", + "name": "connection", + "value": "close" + }, + { + "name": "host", + "value": "localhost:8000" + } + ], + "headersSize": 254, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/json", + "params": [], + "text": "[{\"operationName\":\"VerifyToken\",\"variables\":{\"token\":\"NotAToken\"},\"query\":\"fragment User on User {\\n id\\n email\\n firstName\\n lastName\\n userPermissions {\\n code\\n name\\n __typename\\n }\\n avatar {\\n url\\n __typename\\n }\\n __typename\\n}\\n\\nmutation VerifyToken($token: String!) {\\n tokenVerify(token: $token) {\\n payload\\n user {\\n ...User\\n __typename\\n }\\n __typename\\n }\\n}\\n\"}]" + }, + "queryString": [], + "url": "http://localhost:8000/graphql/" + }, + "response": { + "bodySize": 89, + "content": { + "mimeType": "application/json", + "size": 89, + "text": "[{\"data\": {\"tokenVerify\": {\"payload\": null, \"user\": null, \"__typename\": \"VerifyToken\"}}}]" + }, + "cookies": [], + "headers": [ + { + "name": "date", + "value": "Wed, 29 Jul 2020 13:10:18 GMT" + }, + { + "name": "server", + "value": "WSGIServer/0.2 CPython/3.8.1" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "access-control-allow-origin", + "value": "http://localhost:9000" + }, + { + "name": "access-control-allow-methods", + "value": "POST, OPTIONS" + }, + { + "name": "access-control-allow-headers", + "value": "Origin, Content-Type, Accept, Authorization" + }, + { + "name": "content-length", + "value": "89" + }, + { + "name": "x-content-type-options", + "value": "nosniff" + } + ], + "headersSize": 334, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2020-07-29T13:10:18.368Z", + "time": 6, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 6 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/recordings/User_3768991250/will-not-be-logged-in-if-doesn-t-have-valid-credentials_3719199657/recording.har b/recordings/User_3768991250/will-not-be-logged-in-if-doesn-t-have-valid-credentials_3719199657/recording.har new file mode 100644 index 000000000..547653fee --- /dev/null +++ b/recordings/User_3768991250/will-not-be-logged-in-if-doesn-t-have-valid-credentials_3719199657/recording.har @@ -0,0 +1,128 @@ +{ + "log": { + "_recordingName": "User/will not be logged in if doesn't have valid credentials", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "4.3.0" + }, + "entries": [ + { + "_id": "86487093ff8b070d496fcdc566e01adf", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 603, + "cookies": [], + "headers": [ + { + "_fromType": "array", + "name": "accept", + "value": "*/*" + }, + { + "_fromType": "array", + "name": "content-type", + "value": "application/json" + }, + { + "_fromType": "array", + "name": "content-length", + "value": "603" + }, + { + "_fromType": "array", + "name": "user-agent", + "value": "node-fetch/1.0 (+https://github.com/bitinn/node-fetch)" + }, + { + "_fromType": "array", + "name": "accept-encoding", + "value": "gzip,deflate" + }, + { + "_fromType": "array", + "name": "connection", + "value": "close" + }, + { + "name": "host", + "value": "localhost:8000" + } + ], + "headersSize": 254, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/json", + "params": [], + "text": "[{\"operationName\":\"TokenAuth\",\"variables\":{\"email\":\"admin@example.com\",\"password\":\"NotAValidPassword123!\"},\"query\":\"fragment User on User {\\n id\\n email\\n firstName\\n lastName\\n userPermissions {\\n code\\n name\\n __typename\\n }\\n avatar {\\n url\\n __typename\\n }\\n __typename\\n}\\n\\nmutation TokenAuth($email: String!, $password: String!) {\\n tokenCreate(email: $email, password: $password) {\\n errors: accountErrors {\\n field\\n message\\n __typename\\n }\\n csrfToken\\n token\\n user {\\n ...User\\n __typename\\n }\\n __typename\\n }\\n}\\n\"}]" + }, + "queryString": [], + "url": "http://localhost:8000/graphql/" + }, + "response": { + "bodySize": 214, + "content": { + "mimeType": "application/json", + "size": 214, + "text": "[{\"data\": {\"tokenCreate\": {\"errors\": [{\"field\": \"email\", \"message\": \"Please, enter valid credentials\", \"__typename\": \"AccountError\"}], \"csrfToken\": null, \"token\": null, \"user\": null, \"__typename\": \"CreateToken\"}}}]" + }, + "cookies": [], + "headers": [ + { + "name": "date", + "value": "Wed, 29 Jul 2020 13:10:18 GMT" + }, + { + "name": "server", + "value": "WSGIServer/0.2 CPython/3.8.1" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "access-control-allow-origin", + "value": "http://localhost:9000" + }, + { + "name": "access-control-allow-methods", + "value": "POST, OPTIONS" + }, + { + "name": "access-control-allow-headers", + "value": "Origin, Content-Type, Accept, Authorization" + }, + { + "name": "content-length", + "value": "214" + }, + { + "name": "x-content-type-options", + "value": "nosniff" + } + ], + "headersSize": 335, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2020-07-29T13:10:18.208Z", + "time": 99, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 99 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/schema.graphql b/schema.graphql index 98993d3bb..e2953571b 100644 --- a/schema.graphql +++ b/schema.graphql @@ -62,6 +62,11 @@ enum AccountErrorCode { PASSWORD_TOO_SIMILAR REQUIRED UNIQUE + JWT_SIGNATURE_EXPIRED + JWT_INVALID_TOKEN + JWT_DECODE_ERROR + JWT_MISSING_TOKEN + JWT_INVALID_CSRF_TOKEN } input AccountInput { @@ -201,7 +206,23 @@ type App implements Node & ObjectWithMetadata { metadata: [MetadataItem]! privateMeta: [MetaStore]! @deprecated(reason: "Use the `privetaMetadata` field. This field will be removed after 2020-07-31.") meta: [MetaStore]! @deprecated(reason: "Use the `metadata` field. This field will be removed after 2020-07-31.") + type: AppTypeEnum webhooks: [Webhook] + aboutApp: String + dataPrivacy: String + dataPrivacyUrl: String + homepageUrl: String + supportUrl: String + configurationUrl: String + appUrl: String + version: String + accessToken: String +} + +type AppActivate { + errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + appErrors: [AppError!]! + app: App } type AppCountableConnection { @@ -222,12 +243,24 @@ type AppCreate { app: App } +type AppDeactivate { + errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + appErrors: [AppError!]! + app: App +} + type AppDelete { errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") appErrors: [AppError!]! app: App } +type AppDeleteFailedInstallation { + errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + appErrors: [AppError!]! + appInstallation: AppInstallation +} + type AppError { field: String message: String @@ -236,8 +269,14 @@ type AppError { } enum AppErrorCode { + FORBIDDEN GRAPHQL_ERROR INVALID + INVALID_STATUS + INVALID_PERMISSION + INVALID_URL_FORMAT + INVALID_MANIFEST_FORMAT + MANIFEST_URL_CANT_CONNECT NOT_FOUND REQUIRED UNIQUE @@ -245,9 +284,16 @@ enum AppErrorCode { OUT_OF_SCOPE_PERMISSION } +type AppFetchManifest { + errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + manifest: Manifest + appErrors: [AppError!]! +} + input AppFilterInput { search: String isActive: Boolean + type: AppTypeEnum } input AppInput { @@ -256,6 +302,35 @@ input AppInput { permissions: [PermissionEnum] } +type AppInstall { + errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + appErrors: [AppError!]! + appInstallation: AppInstallation +} + +input AppInstallInput { + appName: String + manifestUrl: String + activateAfterInstallation: Boolean = true + permissions: [PermissionEnum] +} + +type AppInstallation implements Node & Job { + appName: String! + manifestUrl: String! + id: ID! + status: JobStatusEnum! + createdAt: DateTime! + updatedAt: DateTime! + message: String +} + +type AppRetryInstall { + errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + appErrors: [AppError!]! + appInstallation: AppInstallation +} + enum AppSortField { NAME CREATION_DATE @@ -290,6 +365,17 @@ input AppTokenInput { app: ID! } +type AppTokenVerify { + errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + valid: Boolean! + appErrors: [AppError!]! +} + +enum AppTypeEnum { + LOCAL + THIRDPARTY +} + type AppUpdate { errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") appErrors: [AppError!]! @@ -502,7 +588,7 @@ type AttributeValue implements Node { id: ID! name: String slug: String - type: AttributeValueType + type: AttributeValueType @deprecated(reason: "Use the `inputType` field to determine the type of attribute's value. This field will be removed after 2020-07-31.") translation(languageCode: LanguageCodeEnum!): AttributeValueTranslation inputType: AttributeInputTypeEnum } @@ -757,7 +843,6 @@ type Checkout implements Node & ObjectWithMetadata { created: DateTime! lastChange: DateTime! user: User - token: UUID! quantity: Int! billingAddress: Address shippingAddress: Address @@ -774,12 +859,13 @@ type Checkout implements Node & ObjectWithMetadata { privateMeta: [MetaStore]! @deprecated(reason: "Use the `privetaMetadata` field. This field will be removed after 2020-07-31.") meta: [MetaStore]! @deprecated(reason: "Use the `metadata` field. This field will be removed after 2020-07-31.") availableShippingMethods: [ShippingMethod]! - availablePaymentGateways: [PaymentGateway]! + availablePaymentGateways: [PaymentGateway!]! email: String! isShippingRequired: Boolean! lines: [CheckoutLine] shippingPrice: TaxedMoney subtotalPrice: TaxedMoney + token: UUID! totalPrice: TaxedMoney } @@ -811,6 +897,7 @@ type CheckoutComplete { errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") order: Order confirmationNeeded: Boolean! + confirmationData: JSONString checkoutErrors: [CheckoutError!]! } @@ -861,12 +948,15 @@ type CheckoutError { field: String message: String code: CheckoutErrorCode! + variants: [ID!] } enum CheckoutErrorCode { BILLING_ADDRESS_NOT_SET CHECKOUT_NOT_FULLY_PAID GRAPHQL_ERROR + PRODUCT_NOT_PUBLISHED + PRODUCT_UNAVAILABLE_FOR_PURCHASE INSUFFICIENT_STOCK INVALID INVALID_SHIPPING_METHOD @@ -982,7 +1072,7 @@ type Collection implements Node & ObjectWithMetadata { metadata: [MetadataItem]! privateMeta: [MetaStore]! @deprecated(reason: "Use the `privetaMetadata` field. This field will be removed after 2020-07-31.") meta: [MetaStore]! @deprecated(reason: "Use the `metadata` field. This field will be removed after 2020-07-31.") - products(before: String, after: String, first: Int, last: Int): ProductCountableConnection + products(filter: ProductFilterInput, sortBy: ProductOrder, before: String, after: String, first: Int, last: Int): ProductCountableConnection backgroundImage(size: Int): Image translation(languageCode: LanguageCodeEnum!): CollectionTranslation } @@ -1436,18 +1526,20 @@ type CountryDisplay { } type CreateToken { - token: String errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") - accountErrors: [AccountError!]! + token: String + refreshToken: String + csrfToken: String user: User + accountErrors: [AccountError!]! } type CreditCard { brand: String! - firstDigits: String! + firstDigits: String lastDigits: String! - expMonth: Int! - expYear: Int! + expMonth: Int + expYear: Int } type CustomerBulkDelete { @@ -1533,7 +1625,10 @@ input DateTimeRangeInput { lte: DateTime } -scalar Decimal +type DeactivateAllUserTokens { + errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + accountErrors: [AccountError!]! +} type DeleteMetadata { errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") @@ -1609,12 +1704,12 @@ input DigitalContentUploadInput { } type DigitalContentUrl implements Node { - token: UUID! content: DigitalContent! created: DateTime! downloadNum: Int! id: ID! url: String + token: UUID! } type DigitalContentUrlCreate { @@ -1681,7 +1776,7 @@ input DraftOrderCreateInput { billingAddress: AddressInput user: ID userEmail: String - discount: Decimal + discount: PositiveDecimal shippingAddress: AddressInput shippingMethod: ID voucher: ID @@ -1699,7 +1794,7 @@ input DraftOrderInput { billingAddress: AddressInput user: ID userEmail: String - discount: Decimal + discount: PositiveDecimal shippingAddress: AddressInput shippingMethod: ID voucher: ID @@ -1744,6 +1839,109 @@ type Error { message: String } +type ExportError { + field: String + message: String + code: ExportErrorCode! +} + +enum ExportErrorCode { + INVALID + NOT_FOUND + REQUIRED +} + +type ExportEvent implements Node { + id: ID! + date: DateTime! + type: ExportEventsEnum! + user: User + app: App + message: String! +} + +enum ExportEventsEnum { + EXPORT_PENDING + EXPORT_SUCCESS + EXPORT_FAILED + EXPORT_DELETED + EXPORTED_FILE_SENT + EXPORT_FAILED_INFO_SENT +} + +type ExportFile implements Node & Job { + id: ID! + user: User + app: App + status: JobStatusEnum! + createdAt: DateTime! + updatedAt: DateTime! + message: String + url: String + events: [ExportEvent!] +} + +type ExportFileCountableConnection { + pageInfo: PageInfo! + edges: [ExportFileCountableEdge!]! + totalCount: Int +} + +type ExportFileCountableEdge { + node: ExportFile! + cursor: String! +} + +input ExportFileFilterInput { + createdAt: DateTimeRangeInput + updatedAt: DateTimeRangeInput + status: JobStatusEnum + user: String + app: String +} + +enum ExportFileSortField { + STATUS + CREATED_AT + UPDATED_AT +} + +input ExportFileSortingInput { + direction: OrderDirection! + field: ExportFileSortField! +} + +input ExportInfoInput { + attributes: [ID!] + warehouses: [ID!] + fields: [ProductFieldEnum!] +} + +type ExportProducts { + errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + exportFile: ExportFile + exportErrors: [ExportError!]! +} + +input ExportProductsInput { + scope: ExportScope! + filter: ProductFilterInput + ids: [ID!] + exportInfo: ExportInfoInput + fileType: FileTypesEnum! +} + +enum ExportScope { + ALL + IDS + FILTER +} + +enum FileTypesEnum { + CSV + XLSX +} + type Fulfillment implements Node & ObjectWithMetadata { id: ID! fulfillmentOrder: Int! @@ -1864,7 +2062,7 @@ type GiftCardCreate { input GiftCardCreateInput { startDate: Date endDate: Date - balance: Decimal + balance: PositiveDecimal userEmail: String code: String } @@ -1899,7 +2097,7 @@ type GiftCardUpdate { input GiftCardUpdateInput { startDate: Date endDate: Date - balance: Decimal + balance: PositiveDecimal userEmail: String } @@ -1938,8 +2136,95 @@ input IntRangeInput { lte: Int } +type Invoice implements ObjectWithMetadata & Job & Node { + id: ID! + metadata: [MetadataItem]! + status: JobStatusEnum! + number: String + externalUrl: String + privateMetadata: [MetadataItem]! + privateMeta: [MetaStore]! @deprecated(reason: "Use the `privetaMetadata` field. This field will be removed after 2020-07-31.") + meta: [MetaStore]! @deprecated(reason: "Use the `metadata` field. This field will be removed after 2020-07-31.") + createdAt: DateTime! + updatedAt: DateTime! + message: String + url: String +} + +type InvoiceCreate { + errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + invoiceErrors: [InvoiceError!]! + invoice: Invoice +} + +input InvoiceCreateInput { + number: String! + url: String! +} + +type InvoiceDelete { + errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + invoiceErrors: [InvoiceError!]! + invoice: Invoice +} + +type InvoiceError { + field: String + message: String + code: InvoiceErrorCode! +} + +enum InvoiceErrorCode { + REQUIRED + NOT_READY + URL_NOT_SET + EMAIL_NOT_SET + NUMBER_NOT_SET + NOT_FOUND + INVALID_STATUS +} + +type InvoiceRequest { + errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + order: Order + invoiceErrors: [InvoiceError!]! + invoice: Invoice +} + +type InvoiceRequestDelete { + errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + invoiceErrors: [InvoiceError!]! + invoice: Invoice +} + +type InvoiceSendEmail { + errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + invoiceErrors: [InvoiceError!]! + invoice: Invoice +} + +type InvoiceUpdate { + errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + invoiceErrors: [InvoiceError!]! + invoice: Invoice +} + scalar JSONString +interface Job { + status: JobStatusEnum! + createdAt: DateTime! + updatedAt: DateTime! + message: String +} + +enum JobStatusEnum { + PENDING + SUCCESS + FAILED + DELETED +} + enum LanguageCodeEnum { AR AZ @@ -1955,6 +2240,7 @@ enum LanguageCodeEnum { ES_CO ET FA + FI FR HI HU @@ -1963,9 +2249,11 @@ enum LanguageCodeEnum { IS IT JA + KM KO LT MN + MY NB NL PL @@ -1974,10 +2262,12 @@ enum LanguageCodeEnum { RO RU SK + SL SQ SR - SW SV + SW + TA TH TR UK @@ -1991,6 +2281,21 @@ type LanguageDisplay { language: String! } +type Manifest { + identifier: String! + version: String! + name: String! + about: String + permissions: [Permission] + appUrl: String + configurationUrl: String + tokenTargetUrl: String + dataPrivacy: String + dataPrivacyUrl: String + homepageUrl: String + supportUrl: String +} + type Margin { start: Int stop: Int @@ -2333,6 +2638,7 @@ type Mutation { productClearMetadata(id: ID!, input: MetaPath!): ProductClearMeta @deprecated(reason: "Use the `deleteMetadata` mutation instead. This field will be removed after 2020-07-31.") productUpdatePrivateMetadata(id: ID!, input: MetaInput!): ProductUpdatePrivateMeta @deprecated(reason: "Use the `updatePrivateMetadata` mutation instead. This field will be removed after 2020-07-31.") productClearPrivateMetadata(id: ID!, input: MetaPath!): ProductClearPrivateMeta @deprecated(reason: "Use the `deletePrivateMetadata` mutation instead. This field will be removed after 2020-07-31.") + productSetAvailabilityForPurchase(isAvailable: Boolean!, productId: ID!, startDate: Date): ProductSetAvailabilityForPurchase productImageCreate(input: ProductImageCreateInput!): ProductImageCreate productImageDelete(id: ID!): ProductImageDelete productImageBulkDelete(ids: [ID]!): ProductImageBulkDelete @@ -2366,10 +2672,9 @@ type Mutation { productVariantClearPrivateMetadata(id: ID!, input: MetaPath!): ProductVariantClearPrivateMeta @deprecated(reason: "Use the `deletePrivateMetadata` mutation instead. This field will be removed after 2020-07-31.") variantImageAssign(imageId: ID!, variantId: ID!): VariantImageAssign variantImageUnassign(imageId: ID!, variantId: ID!): VariantImageUnassign - paymentCapture(amount: Decimal, paymentId: ID!): PaymentCapture - paymentRefund(amount: Decimal, paymentId: ID!): PaymentRefund + paymentCapture(amount: PositiveDecimal, paymentId: ID!): PaymentCapture + paymentRefund(amount: PositiveDecimal, paymentId: ID!): PaymentRefund paymentVoid(paymentId: ID!): PaymentVoid - paymentSecureConfirm(paymentId: ID!): PaymentSecureConfirm pageCreate(input: PageInput!): PageCreate pageDelete(id: ID!): PageDelete pageBulkDelete(ids: [ID]!): PageBulkDelete @@ -2387,7 +2692,7 @@ type Mutation { draftOrderUpdate(id: ID!, input: DraftOrderInput!): DraftOrderUpdate orderAddNote(order: ID!, input: OrderAddNoteInput!): OrderAddNote orderCancel(id: ID!): OrderCancel - orderCapture(amount: Decimal!, id: ID!): OrderCapture + orderCapture(amount: PositiveDecimal!, id: ID!): OrderCapture orderClearPrivateMeta(id: ID!, input: MetaPath!): OrderClearPrivateMeta @deprecated(reason: "Use the `deletePrivateMetadata` mutation instead. This field will be removed after 2020-07-31.") orderClearMeta(input: MetaPath!, token: UUID!): OrderClearMeta @deprecated(reason: "Use the `deleteMetadata` mutation instead. This field will be removed after 2020-07-31.") orderFulfill(input: OrderFulfillInput!, order: ID): OrderFulfill @@ -2398,7 +2703,7 @@ type Mutation { orderFulfillmentUpdateMeta(id: ID!, input: MetaInput!): FulfillmentUpdateMeta @deprecated(reason: "Use the `updateMetadata` mutation instead. This field will be removed after 2020-07-31.") orderFulfillmentUpdatePrivateMeta(id: ID!, input: MetaInput!): FulfillmentUpdatePrivateMeta @deprecated(reason: "Use the `updatePrivateMetadata` mutation instead. This field will be removed after 2020-07-31.") orderMarkAsPaid(id: ID!): OrderMarkAsPaid - orderRefund(amount: Decimal!, id: ID!): OrderRefund + orderRefund(amount: PositiveDecimal!, id: ID!): OrderRefund orderUpdate(id: ID!, input: OrderUpdateInput!): OrderUpdate orderUpdateMeta(input: MetaInput!, token: UUID!): OrderUpdateMeta @deprecated(reason: "Use the `updateMetadata` mutation instead. This field will be removed after 2020-07-31.") orderUpdatePrivateMeta(id: ID!, input: MetaInput!): OrderUpdatePrivateMeta @deprecated(reason: "Use the `updatePrivateMetadata` mutation instead. This field will be removed after 2020-07-31.") @@ -2420,6 +2725,12 @@ type Mutation { menuItemUpdate(id: ID!, input: MenuItemInput!): MenuItemUpdate menuItemTranslate(id: ID!, input: NameTranslationInput!, languageCode: LanguageCodeEnum!): MenuItemTranslate menuItemMove(menu: ID!, moves: [MenuItemMoveInput]!): MenuItemMove + invoiceRequest(number: String, orderId: ID!): InvoiceRequest + invoiceRequestDelete(id: ID!): InvoiceRequestDelete + invoiceCreate(input: InvoiceCreateInput!, orderId: ID!): InvoiceCreate + invoiceDelete(id: ID!): InvoiceDelete + invoiceUpdate(id: ID!, input: UpdateInvoiceInput!): InvoiceUpdate + invoiceSendEmail(id: ID!): InvoiceSendEmail giftCardActivate(id: ID!): GiftCardActivate giftCardCreate(input: GiftCardCreateInput!): GiftCardCreate giftCardDeactivate(id: ID!): GiftCardDeactivate @@ -2439,12 +2750,10 @@ type Mutation { voucherCataloguesAdd(id: ID!, input: CatalogueInput!): VoucherAddCatalogues voucherCataloguesRemove(id: ID!, input: CatalogueInput!): VoucherRemoveCatalogues voucherTranslate(id: ID!, input: NameTranslationInput!, languageCode: LanguageCodeEnum!): VoucherTranslate - tokenCreate(email: String!, password: String!): CreateToken - tokenRefresh(token: String!): RefreshToken - tokenVerify(token: String!): VerifyToken + exportProducts(input: ExportProductsInput!): ExportProducts checkoutAddPromoCode(checkoutId: ID!, promoCode: String!): CheckoutAddPromoCode checkoutBillingAddressUpdate(billingAddress: AddressInput!, checkoutId: ID!): CheckoutBillingAddressUpdate - checkoutComplete(checkoutId: ID!, redirectUrl: String, storeSource: Boolean = false): CheckoutComplete + checkoutComplete(checkoutId: ID!, paymentData: JSONString, redirectUrl: String, storeSource: Boolean = false): CheckoutComplete checkoutCreate(input: CheckoutCreateInput!): CheckoutCreate checkoutCustomerAttach(checkoutId: ID!, customerId: ID): CheckoutCustomerAttach checkoutCustomerDetach(checkoutId: ID!): CheckoutCustomerDetach @@ -2465,9 +2774,20 @@ type Mutation { appDelete(id: ID!): AppDelete appTokenCreate(input: AppTokenInput!): AppTokenCreate appTokenDelete(id: ID!): AppTokenDelete + appTokenVerify(token: String!): AppTokenVerify + appInstall(input: AppInstallInput!): AppInstall + appRetryInstall(activateAfterInstallation: Boolean = true, id: ID!): AppRetryInstall + appDeleteFailedInstallation(id: ID!): AppDeleteFailedInstallation + appFetchManifest(manifestUrl: String!): AppFetchManifest + appActivate(id: ID!): AppActivate + appDeactivate(id: ID!): AppDeactivate + tokenCreate(email: String!, password: String!): CreateToken + tokenRefresh(csrfToken: String, refreshToken: String): RefreshToken + tokenVerify(token: String!): VerifyToken + tokensDeactivateAll: DeactivateAllUserTokens requestPasswordReset(email: String!, redirectUrl: String!): RequestPasswordReset confirmAccount(email: String!, token: String!): ConfirmAccount - setPassword(token: String!, email: String!, password: String!): SetPassword + setPassword(email: String!, password: String!, token: String!): SetPassword passwordChange(newPassword: String!, oldPassword: String!): PasswordChange requestEmailChange(newEmail: String!, password: String!, redirectUrl: String!): RequestEmailChange confirmEmailChange(token: String!): ConfirmEmailChange @@ -2565,6 +2885,7 @@ type Order implements Node & ObjectWithMetadata { lines: [OrderLine]! actions: [OrderAction]! availableShippingMethods: [ShippingMethod] + invoices: [Invoice] number: String isPaid: Boolean paymentStatus: PaymentChargeStatusEnum @@ -2669,6 +2990,8 @@ enum OrderErrorCode { FULFILL_ORDER_LINE GRAPHQL_ERROR INVALID + PRODUCT_NOT_PUBLISHED + PRODUCT_UNAVAILABLE_FOR_PURCHASE NOT_FOUND ORDER_NO_SHIPPING_ADDRESS PAYMENT_ERROR @@ -2697,6 +3020,7 @@ type OrderEvent implements Node { quantity: Int composedId: String orderNumber: String + invoiceNumber: String oversoldItems: [String] lines: [OrderEventOrderLineObject] fulfilledItems: [FulfillmentLine] @@ -2725,6 +3049,8 @@ enum OrderEventsEmailsEnum { SHIPPING_CONFIRMATION TRACKING_UPDATED ORDER_CONFIRMATION + ORDER_CANCEL + ORDER_REFUND FULFILLMENT_CONFIRMATION DIGITAL_LINKS } @@ -2741,10 +3067,16 @@ enum OrderEventsEnum { ORDER_FULLY_PAID UPDATED_ADDRESS EMAIL_SENT + PAYMENT_AUTHORIZED PAYMENT_CAPTURED + EXTERNAL_SERVICE_NOTIFICATION PAYMENT_REFUNDED PAYMENT_VOIDED PAYMENT_FAILED + INVOICE_REQUESTED + INVOICE_GENERATED + INVOICE_UPDATED + INVOICE_SENT FULFILLMENT_CANCELED FULFILLMENT_RESTOCKED_ITEMS FULFILLMENT_FULFILLED_ITEMS @@ -2795,6 +3127,7 @@ type OrderLine implements Node { digitalContentUrl: DigitalContentUrl thumbnail(size: Int): Image unitPrice: TaxedMoney + totalPrice: TaxedMoney variant: ProductVariant translatedProductName: String! translatedVariantName: String! @@ -3043,14 +3376,11 @@ type Payment implements Node { token: String! checkout: Checkout order: Order - billingEmail: String! customerIpAddress: String - extraData: String! chargeStatus: PaymentChargeStatusEnum! actions: [OrderAction]! total: Money capturedAmount: Money - billingAddress: Address transactions: [Transaction] availableCaptureAmount: Money availableRefundAmount: Money @@ -3065,10 +3395,13 @@ type PaymentCapture { enum PaymentChargeStatusEnum { NOT_CHARGED + PENDING PARTIALLY_CHARGED FULLY_CHARGED PARTIALLY_REFUNDED FULLY_REFUNDED + REFUSED + CANCELLED } type PaymentCountableConnection { @@ -3093,22 +3426,29 @@ enum PaymentErrorCode { GRAPHQL_ERROR INVALID NOT_FOUND - PARTIAL_PAYMENT_NOT_ALLOWED - PAYMENT_ERROR REQUIRED UNIQUE + PARTIAL_PAYMENT_NOT_ALLOWED + SHIPPING_ADDRESS_NOT_SET + INVALID_SHIPPING_METHOD + SHIPPING_METHOD_NOT_SET + PAYMENT_ERROR + NOT_SUPPORTED_GATEWAY } type PaymentGateway { name: String! + id: ID! config: [GatewayConfigLine!]! + currencies: [String]! } input PaymentInput { gateway: String! - token: String! - amount: Decimal + token: String + amount: PositiveDecimal billingAddress: AddressInput + returnUrl: String } type PaymentRefund { @@ -3117,12 +3457,6 @@ type PaymentRefund { paymentErrors: [PaymentError!]! } -type PaymentSecureConfirm { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") - payment: Payment - paymentErrors: [PaymentError!]! -} - type PaymentSource { gateway: String! creditCardInfo: CreditCard @@ -3154,14 +3488,13 @@ enum PermissionEnum { MANAGE_SHIPPING MANAGE_SETTINGS MANAGE_TRANSLATIONS - MANAGE_WEBHOOKS MANAGE_CHECKOUTS } type PermissionGroupCreate { errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") - group: Group permissionGroupErrors: [PermissionGroupError!]! + group: Group } input PermissionGroupCreateInput { @@ -3210,8 +3543,8 @@ input PermissionGroupSortingInput { type PermissionGroupUpdate { errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") - group: Group permissionGroupErrors: [PermissionGroupError!]! + group: Group } input PermissionGroupUpdateInput { @@ -3282,6 +3615,8 @@ input PluginUpdateInput { configuration: [ConfigurationItemInput] } +scalar PositiveDecimal + input PriceRangeInput { gte: Float lte: Float @@ -3302,6 +3637,8 @@ type Product implements Node & ObjectWithMetadata { updatedAt: DateTime chargeTaxes: Boolean! weight: Weight + availableForPurchase: Date + visibleInListings: Boolean! privateMetadata: [MetadataItem]! metadata: [MetadataItem]! privateMeta: [MetaStore]! @deprecated(reason: "Use the `privetaMetadata` field. This field will be removed after 2020-07-31.") @@ -3310,7 +3647,6 @@ type Product implements Node & ObjectWithMetadata { thumbnail(size: Int): Image pricing: ProductPricingInfo isAvailable: Boolean - basePrice: Money minimalVariantPrice: Money taxType: TaxType attributes: [SelectedAttribute!]! @@ -3321,6 +3657,7 @@ type Product implements Node & ObjectWithMetadata { images: [ProductImage] collections: [Collection] translation(languageCode: LanguageCodeEnum!): ProductTranslation + isAvailableForPurchase: Boolean } type ProductAttributeError { @@ -3382,12 +3719,13 @@ input ProductCreateInput { isPublished: Boolean name: String slug: String - basePrice: Decimal taxCode: String seo: SeoInput weight: WeightScalar sku: String trackInventory: Boolean + basePrice: PositiveDecimal + visibleInListings: Boolean productType: ID! stocks: [StockInput!] } @@ -3419,17 +3757,36 @@ enum ProductErrorCode { VARIANT_NO_DIGITAL_CONTENT } +enum ProductFieldEnum { + NAME + DESCRIPTION + PRODUCT_TYPE + CATEGORY + VISIBLE + AVAILABLE_FOR_PURCHASE + SEARCHABLE + PRODUCT_WEIGHT + COLLECTIONS + CHARGE_TAXES + PRODUCT_IMAGES + VARIANT_SKU + VARIANT_PRICE + COST_PRICE + VARIANT_WEIGHT + VARIANT_IMAGES +} + input ProductFilterInput { isPublished: Boolean collections: [ID] categories: [ID] hasCategory: Boolean - price: PriceRangeInput attributes: [AttributeInput] stockAvailability: StockAvailability productType: ID stocks: ProductStockFilterInput search: String + price: PriceRangeInput minimalPrice: PriceRangeInput productTypes: [ID] } @@ -3496,12 +3853,13 @@ input ProductInput { isPublished: Boolean name: String slug: String - basePrice: Decimal taxCode: String seo: SeoInput weight: WeightScalar sku: String trackInventory: Boolean + basePrice: PositiveDecimal + visibleInListings: Boolean } input ProductOrder { @@ -3528,6 +3886,12 @@ type ProductPricingInfo { priceRangeLocalCurrency: TaxedMoneyRange } +type ProductSetAvailabilityForPurchase { + errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + product: Product + productErrors: [ProductError!]! +} + input ProductStockFilterInput { warehouseIds: [ID!] quantity: IntRangeInput @@ -3716,8 +4080,8 @@ type ProductVariant implements Node & ObjectWithMetadata { meta: [MetaStore]! @deprecated(reason: "Use the `metadata` field. This field will be removed after 2020-07-31.") quantity: Int! @deprecated(reason: "Use the stock field instead. This field will be removed after 2020-07-31.") quantityAllocated: Int @deprecated(reason: "Use the stock field instead. This field will be removed after 2020-07-31.") - stockQuantity: Int! @deprecated(reason: "Use the stock field instead. This field will be removed after 2020-07-31.") - priceOverride: Money + stockQuantity: Int! @deprecated(reason: "Use the quantityAvailable field instead. This field will be removed after 2020-07-31.") + price: Money pricing: VariantPricingInfo isAvailable: Boolean @deprecated(reason: "Use the stock field instead. This field will be removed after 2020-07-31.") attributes: [SelectedAttribute!]! @@ -3729,6 +4093,7 @@ type ProductVariant implements Node & ObjectWithMetadata { translation(languageCode: LanguageCodeEnum!): ProductVariantTranslation digitalContent: DigitalContent stocks(countryCode: CountryCode): [Stock] + quantityAvailable(countryCode: CountryCode): Int! } type ProductVariantBulkCreate { @@ -3740,8 +4105,8 @@ type ProductVariantBulkCreate { input ProductVariantBulkCreateInput { attributes: [AttributeValueInput]! - costPrice: Decimal - priceOverride: Decimal + costPrice: PositiveDecimal + price: PositiveDecimal sku: String! trackInventory: Boolean weight: WeightScalar @@ -3785,8 +4150,8 @@ type ProductVariantCreate { input ProductVariantCreateInput { attributes: [AttributeValueInput]! - costPrice: Decimal - priceOverride: Decimal + costPrice: PositiveDecimal + price: PositiveDecimal sku: String trackInventory: Boolean weight: WeightScalar @@ -3802,8 +4167,8 @@ type ProductVariantDelete { input ProductVariantInput { attributes: [AttributeValueInput] - costPrice: Decimal - priceOverride: Decimal + costPrice: PositiveDecimal + price: PositiveDecimal sku: String trackInventory: Boolean weight: WeightScalar @@ -3883,10 +4248,10 @@ type Query { attributes(filter: AttributeFilterInput, sortBy: AttributeSortingInput, before: String, after: String, first: Int, last: Int): AttributeCountableConnection attribute(id: ID!): Attribute categories(filter: CategoryFilterInput, sortBy: CategorySortingInput, level: Int, before: String, after: String, first: Int, last: Int): CategoryCountableConnection - category(id: ID!): Category - collection(id: ID!): Collection + category(id: ID, slug: String): Category + collection(id: ID, slug: String): Collection collections(filter: CollectionFilterInput, sortBy: CollectionSortingInput, before: String, after: String, first: Int, last: Int): CollectionCountableConnection - product(id: ID!): Product + product(id: ID, slug: String): Product products(filter: ProductFilterInput, sortBy: ProductOrder, stockAvailability: StockAvailability, before: String, after: String, first: Int, last: Int): ProductCountableConnection productType(id: ID!): ProductType productTypes(filter: ProductTypeFilterInput, sortBy: ProductTypeSortingInput, before: String, after: String, first: Int, last: Int): ProductTypeCountableConnection @@ -3915,11 +4280,14 @@ type Query { sales(filter: SaleFilterInput, sortBy: SaleSortingInput, query: String, before: String, after: String, first: Int, last: Int): SaleCountableConnection voucher(id: ID!): Voucher vouchers(filter: VoucherFilterInput, sortBy: VoucherSortingInput, query: String, before: String, after: String, first: Int, last: Int): VoucherCountableConnection + exportFile(id: ID!): ExportFile + exportFiles(filter: ExportFileFilterInput, sortBy: ExportFileSortingInput, before: String, after: String, first: Int, last: Int): ExportFileCountableConnection taxTypes: [TaxType] checkout(token: UUID): Checkout checkouts(before: String, after: String, first: Int, last: Int): CheckoutCountableConnection checkoutLine(id: ID): CheckoutLine checkoutLines(before: String, after: String, first: Int, last: Int): CheckoutLineCountableConnection + appsInstallations: [AppInstallation!]! apps(filter: AppFilterInput, sortBy: AppSortingInput, before: String, after: String, first: Int, last: Int): AppCountableConnection app(id: ID!): App addressValidationRules(countryCode: CountryCode!, countryArea: String, city: String, cityArea: String): AddressValidationData @@ -3942,8 +4310,10 @@ type ReducedRate { } type RefreshToken { + errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") token: String - payload: GenericScalar + user: User + accountErrors: [AccountError!]! } input ReorderInput { @@ -4025,7 +4395,7 @@ input SaleFilterInput { input SaleInput { name: String type: DiscountValueTypeEnum - value: Decimal + value: PositiveDecimal products: [ID] categories: [ID] collections: [ID] @@ -4193,10 +4563,12 @@ type ServiceAccountUpdatePrivateMeta { } type SetPassword { - token: String errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") - accountErrors: [AccountError!]! + token: String + refreshToken: String + csrfToken: String user: User + accountErrors: [AccountError!]! } type ShippingError { @@ -4269,9 +4641,9 @@ type ShippingPriceDelete { input ShippingPriceInput { name: String - price: Decimal - minimumOrderPrice: Decimal - maximumOrderPrice: Decimal + price: PositiveDecimal + minimumOrderPrice: PositiveDecimal + maximumOrderPrice: PositiveDecimal minimumOrderWeight: WeightScalar maximumOrderWeight: WeightScalar type: ShippingMethodTypeEnum @@ -4320,8 +4692,8 @@ type ShippingZoneCountableEdge { type ShippingZoneCreate { errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") - shippingZone: ShippingZone shippingErrors: [ShippingError!]! + shippingZone: ShippingZone } input ShippingZoneCreateInput { @@ -4339,8 +4711,8 @@ type ShippingZoneDelete { type ShippingZoneUpdate { errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") - shippingZone: ShippingZone shippingErrors: [ShippingError!]! + shippingZone: ShippingZone } input ShippingZoneUpdateInput { @@ -4352,9 +4724,10 @@ input ShippingZoneUpdateInput { } type Shop { + availablePaymentGateways(currency: String): [PaymentGateway!]! geolocalization: Geolocalization authorizationKeys: [AuthorizationKey]! - countries(languageCode: LanguageCodeEnum): [CountryDisplay]! + countries(languageCode: LanguageCodeEnum): [CountryDisplay!]! currencies: [String]! defaultCurrency: String! defaultCountry: CountryDisplay @@ -4561,7 +4934,6 @@ type Stock implements Node { productVariant: ProductVariant! quantity: Int! id: ID! - stockQuantity: Int! quantityAllocated: Int! } @@ -4659,7 +5031,6 @@ type Transaction implements Node { kind: TransactionKind! isSuccess: Boolean! error: TransactionError - gatewayResponse: JSONString! amount: Money } @@ -4678,10 +5049,14 @@ enum TransactionError { enum TransactionKind { AUTH + PENDING + ACTION_TO_CONFIRM REFUND + REFUND_ONGOING CAPTURE VOID CONFIRM + CANCEL } union TranslatableItem = ProductTranslatableContent | CollectionTranslatableContent | CategoryTranslatableContent | AttributeTranslatableContent | AttributeValueTranslatableContent | ProductVariantTranslatableContent | PageTranslatableContent | ShippingMethodTranslatableContent | SaleTranslatableContent | VoucherTranslatableContent | MenuItemTranslatableContent @@ -4733,6 +5108,11 @@ input TranslationInput { scalar UUID +input UpdateInvoiceInput { + number: String + url: String +} + type UpdateMetadata { errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") metadataErrors: [MetadataError!]! @@ -4888,8 +5268,11 @@ type VariantPricingInfo { } type VerifyToken { - payload: GenericScalar + errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") user: User + isValid: Boolean! + payload: GenericScalar + accountErrors: [AccountError!]! } type Voucher implements Node { @@ -4970,11 +5353,11 @@ input VoucherInput { startDate: DateTime endDate: DateTime discountValueType: DiscountValueTypeEnum - discountValue: Decimal + discountValue: PositiveDecimal products: [ID] collections: [ID] categories: [ID] - minAmountSpent: Decimal + minAmountSpent: PositiveDecimal minCheckoutItemsQuantity: Int countries: [String] applyOncePerOrder: Boolean @@ -5109,14 +5492,14 @@ input WarehouseFilterInput { type WarehouseShippingZoneAssign { errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") - warehouse: Warehouse warehouseErrors: [WarehouseError!]! + warehouse: Warehouse } type WarehouseShippingZoneUnassign { errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") - warehouse: Warehouse warehouseErrors: [WarehouseError!]! + warehouse: Warehouse } enum WarehouseSortField { @@ -5182,8 +5565,8 @@ input WebhookCreateInput { type WebhookDelete { errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") - webhook: Webhook webhookErrors: [WebhookError!]! + webhook: Webhook } type WebhookError { @@ -5212,9 +5595,14 @@ enum WebhookEventTypeEnum { ORDER_UPDATED ORDER_CANCELLED ORDER_FULFILLED + INVOICE_REQUESTED + INVOICE_DELETED + INVOICE_SENT CUSTOMER_CREATED PRODUCT_CREATED CHECKOUT_QUANTITY_CHANGED + CHECKOUT_CREATED + CHECKOUT_UPDATED FULFILLMENT_CREATED } @@ -5229,9 +5617,14 @@ enum WebhookSampleEventTypeEnum { ORDER_UPDATED ORDER_CANCELLED ORDER_FULFILLED + INVOICE_REQUESTED + INVOICE_DELETED + INVOICE_SENT CUSTOMER_CREATED PRODUCT_CREATED CHECKOUT_QUANTITY_CHANGED + CHECKOUT_CREATED + CHECKOUT_UPDATED FULFILLMENT_CREATED } @@ -5249,8 +5642,8 @@ input WebhookSortingInput { type WebhookUpdate { errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") - webhook: Webhook webhookErrors: [WebhookError!]! + webhook: Webhook } input WebhookUpdateInput { @@ -5264,7 +5657,7 @@ input WebhookUpdateInput { } type Weight { - unit: String! + unit: WeightUnitsEnum! value: Float! } diff --git a/src/apps/components/AppActivateDialog/AppActivateDialog.stories.tsx b/src/apps/components/AppActivateDialog/AppActivateDialog.stories.tsx new file mode 100644 index 000000000..cd54d8776 --- /dev/null +++ b/src/apps/components/AppActivateDialog/AppActivateDialog.stories.tsx @@ -0,0 +1,18 @@ +import Decorator from "@saleor/storybook/Decorator"; +import { storiesOf } from "@storybook/react"; +import React from "react"; + +import AppActivateDialog, { AppActivateDialogProps } from "./AppActivateDialog"; + +const props: AppActivateDialogProps = { + confirmButtonState: "default", + name: "App", + onClose: () => undefined, + onConfirm: () => undefined, + open: true +}; + +storiesOf("Views / Apps / Activate app", module) + .addDecorator(Decorator) + .add("default", () => ) + .add("unnamed app", () => ); diff --git a/src/apps/components/AppActivateDialog/AppActivateDialog.tsx b/src/apps/components/AppActivateDialog/AppActivateDialog.tsx new file mode 100644 index 000000000..f447d2402 --- /dev/null +++ b/src/apps/components/AppActivateDialog/AppActivateDialog.tsx @@ -0,0 +1,61 @@ +import DialogContentText from "@material-ui/core/DialogContentText"; +import ActionDialog from "@saleor/components/ActionDialog"; +import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; +import { getStringOrPlaceholder } from "@saleor/misc"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + +export interface AppActivateDialogProps { + confirmButtonState: ConfirmButtonTransitionState; + open: boolean; + name: string; + onClose: () => void; + onConfirm: () => void; +} + +const AppActivateDialog: React.FC = ({ + confirmButtonState, + open, + name, + onClose, + onConfirm +}) => { + const intl = useIntl(); + + return ( + + + {["", null].includes(name) ? ( + + ) : ( + {getStringOrPlaceholder(name)} + }} + /> + )} + + + ); +}; +AppActivateDialog.displayName = "AppActivateDialog"; +export default AppActivateDialog; diff --git a/src/apps/components/AppActivateDialog/index.ts b/src/apps/components/AppActivateDialog/index.ts new file mode 100644 index 000000000..7b7d24553 --- /dev/null +++ b/src/apps/components/AppActivateDialog/index.ts @@ -0,0 +1,2 @@ +export * from "./AppActivateDialog"; +export { default } from "./AppActivateDialog"; diff --git a/src/apps/components/AppDeactivateDialog/AppDeactivateDialog.stories.tsx b/src/apps/components/AppDeactivateDialog/AppDeactivateDialog.stories.tsx new file mode 100644 index 000000000..00cb9a903 --- /dev/null +++ b/src/apps/components/AppDeactivateDialog/AppDeactivateDialog.stories.tsx @@ -0,0 +1,20 @@ +import Decorator from "@saleor/storybook/Decorator"; +import { storiesOf } from "@storybook/react"; +import React from "react"; + +import AppDeactivateDialog, { + AppDeactivateDialogProps +} from "./AppDeactivateDialog"; + +const props: AppDeactivateDialogProps = { + confirmButtonState: "default", + name: "App", + onClose: () => undefined, + onConfirm: () => undefined, + open: true +}; + +storiesOf("Views / Apps / Deactivate app", module) + .addDecorator(Decorator) + .add("default", () => ) + .add("unnamed app", () => ); diff --git a/src/apps/components/AppDeactivateDialog/AppDeactivateDialog.tsx b/src/apps/components/AppDeactivateDialog/AppDeactivateDialog.tsx new file mode 100644 index 000000000..9cc84e6cb --- /dev/null +++ b/src/apps/components/AppDeactivateDialog/AppDeactivateDialog.tsx @@ -0,0 +1,61 @@ +import DialogContentText from "@material-ui/core/DialogContentText"; +import ActionDialog from "@saleor/components/ActionDialog"; +import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; +import { getStringOrPlaceholder } from "@saleor/misc"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + +export interface AppDeactivateDialogProps { + confirmButtonState: ConfirmButtonTransitionState; + open: boolean; + name: string; + onClose: () => void; + onConfirm: () => void; +} + +const AppDeactivateDialog: React.FC = ({ + confirmButtonState, + open, + name, + onClose, + onConfirm +}) => { + const intl = useIntl(); + + return ( + + + {["", null].includes(name) ? ( + + ) : ( + {getStringOrPlaceholder(name)} + }} + /> + )} + + + ); +}; +AppDeactivateDialog.displayName = "AppDeactivateDialog"; +export default AppDeactivateDialog; diff --git a/src/apps/components/AppDeactivateDialog/index.ts b/src/apps/components/AppDeactivateDialog/index.ts new file mode 100644 index 000000000..d58865cf1 --- /dev/null +++ b/src/apps/components/AppDeactivateDialog/index.ts @@ -0,0 +1,2 @@ +export * from "./AppDeactivateDialog"; +export { default } from "./AppDeactivateDialog"; diff --git a/src/apps/components/AppDeleteDialog/AppDeleteDialog.stories.tsx b/src/apps/components/AppDeleteDialog/AppDeleteDialog.stories.tsx new file mode 100644 index 000000000..43f19486a --- /dev/null +++ b/src/apps/components/AppDeleteDialog/AppDeleteDialog.stories.tsx @@ -0,0 +1,19 @@ +import Decorator from "@saleor/storybook/Decorator"; +import { storiesOf } from "@storybook/react"; +import React from "react"; + +import AppDeleteDialog, { AppDeleteDialogProps } from "./AppDeleteDialog"; + +const props: AppDeleteDialogProps = { + confirmButtonState: "default", + name: "App", + onClose: () => undefined, + onConfirm: () => undefined, + open: true, + type: "EXTERNAL" +}; + +storiesOf("Views / Apps / Delete app", module) + .addDecorator(Decorator) + .add("default", () => ) + .add("unnamed app", () => ); diff --git a/src/apps/components/AppDeleteDialog/AppDeleteDialog.tsx b/src/apps/components/AppDeleteDialog/AppDeleteDialog.tsx new file mode 100644 index 000000000..fa5708368 --- /dev/null +++ b/src/apps/components/AppDeleteDialog/AppDeleteDialog.tsx @@ -0,0 +1,67 @@ +import DialogContentText from "@material-ui/core/DialogContentText"; +import ActionDialog from "@saleor/components/ActionDialog"; +import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; +import { getStringOrPlaceholder } from "@saleor/misc"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + +export interface AppDeleteDialogProps { + confirmButtonState: ConfirmButtonTransitionState; + open: boolean; + name: string; + onClose: () => void; + onConfirm: () => void; + type: "CUSTOM" | "EXTERNAL"; +} + +const AppDeleteDialog: React.FC = ({ + confirmButtonState, + open, + name, + onClose, + onConfirm, + type +}) => { + const intl = useIntl(); + + return ( + + + {["", null].includes(name) ? ( + + ) : type === "EXTERNAL" ? ( + {getStringOrPlaceholder(name)} + }} + /> + ) : ( + {getStringOrPlaceholder(name)} + }} + /> + )} + + + ); +}; +AppDeleteDialog.displayName = "AppDeleteDialog"; +export default AppDeleteDialog; diff --git a/src/apps/components/AppDeleteDialog/index.ts b/src/apps/components/AppDeleteDialog/index.ts new file mode 100644 index 000000000..06d0e0693 --- /dev/null +++ b/src/apps/components/AppDeleteDialog/index.ts @@ -0,0 +1,2 @@ +export * from "./AppDeleteDialog"; +export { default } from "./AppDeleteDialog"; diff --git a/src/apps/components/AppDetailsPage/AppDetailsPage.stories.tsx b/src/apps/components/AppDetailsPage/AppDetailsPage.stories.tsx new file mode 100644 index 000000000..20cf82e41 --- /dev/null +++ b/src/apps/components/AppDetailsPage/AppDetailsPage.stories.tsx @@ -0,0 +1,20 @@ +import Decorator from "@saleor/storybook/Decorator"; +import { storiesOf } from "@storybook/react"; +import React from "react"; + +import { appDetails } from "../../fixtures"; +import AppDetailsPage, { AppDetailsPageProps } from "./AppDetailsPage"; + +const props: AppDetailsPageProps = { + data: appDetails, + loading: false, + navigateToAppSettings: () => undefined, + onAppActivateOpen: () => undefined, + onAppDeactivateOpen: () => undefined, + onBack: () => undefined +}; + +storiesOf("Views / Apps / App details", module) + .addDecorator(Decorator) + .add("default", () => ) + .add("loading", () => ); diff --git a/src/apps/components/AppDetailsPage/AppDetailsPage.tsx b/src/apps/components/AppDetailsPage/AppDetailsPage.tsx new file mode 100644 index 000000000..a01299701 --- /dev/null +++ b/src/apps/components/AppDetailsPage/AppDetailsPage.tsx @@ -0,0 +1,195 @@ +import Button from "@material-ui/core/Button"; +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import Typography from "@material-ui/core/Typography"; +import AppHeader from "@saleor/components/AppHeader"; +import CardSpacer from "@saleor/components/CardSpacer"; +import CardTitle from "@saleor/components/CardTitle"; +import Container from "@saleor/components/Container"; +import ExternalLink from "@saleor/components/ExternalLink"; +import PageHeader from "@saleor/components/PageHeader"; +import Skeleton from "@saleor/components/Skeleton"; +import { sectionNames } from "@saleor/intl"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; +import ReactMarkdown from "react-markdown"; + +import activateIcon from "../../../../assets/images/activate-icon.svg"; +import settingsIcon from "../../../../assets/images/settings-icon.svg"; +import supportIcon from "../../../../assets/images/support-icon.svg"; +import { useStyles } from "../../styles"; +import { App_app } from "../../types/App"; +import DeactivatedText from "../DeactivatedText"; + +export interface AppDetailsPageProps { + loading: boolean; + data: App_app; + navigateToAppSettings: () => void; + onAppActivateOpen: () => void; + onAppDeactivateOpen: () => void; + onBack: () => void; +} + +export const AppDetailsPage: React.FC = ({ + data, + loading, + navigateToAppSettings, + onAppActivateOpen, + onAppDeactivateOpen, + onBack +}) => { + const intl = useIntl(); + const classes = useStyles({}); + + return ( + + + {intl.formatMessage(sectionNames.apps)} + + + {data?.name} {!data?.isActive && } + + } + > + + +
+ {data ? ( +
+ + + + + + +
+ ) : ( + + )} +
+
+ + + + + {!loading ? : } + + + + + + + {!loading ? ( + <> + + + + {!!data?.permissions?.length && ( +
    + {data?.permissions?.map(perm => ( +
  • {perm.name}
  • + ))} +
+ )} + + ) : ( + + )} +
+
+ + + + + + {!loading ? ( + <> + {data?.dataPrivacy} + + + + + ) : ( + + )} + + + + + ); +}; + +AppDetailsPage.displayName = "AppDetailsPage"; +export default AppDetailsPage; diff --git a/src/apps/components/AppDetailsPage/index.ts b/src/apps/components/AppDetailsPage/index.ts new file mode 100644 index 000000000..1e11990da --- /dev/null +++ b/src/apps/components/AppDetailsPage/index.ts @@ -0,0 +1,2 @@ +export * from "./AppDetailsPage"; +export { default } from "./AppDetailsPage"; diff --git a/src/apps/components/AppDetailsSettingsPage/AppDetailsSettingsPage.stories.tsx b/src/apps/components/AppDetailsSettingsPage/AppDetailsSettingsPage.stories.tsx new file mode 100644 index 000000000..8665d545e --- /dev/null +++ b/src/apps/components/AppDetailsSettingsPage/AppDetailsSettingsPage.stories.tsx @@ -0,0 +1,20 @@ +import Decorator from "@saleor/storybook/Decorator"; +import { storiesOf } from "@storybook/react"; +import React from "react"; + +import { appDetails } from "../../fixtures"; +import AppDetailsSettingsPage, { + AppDetailsSettingsPageProps +} from "./AppDetailsSettingsPage"; + +const props: AppDetailsSettingsPageProps = { + backendHost: "host", + data: appDetails, + navigateToDashboard: () => undefined, + onBack: () => undefined, + onError: () => undefined +}; + +storiesOf("Views / Apps / App details settings", module) + .addDecorator(Decorator) + .add("default", () => ); diff --git a/src/apps/components/AppDetailsSettingsPage/AppDetailsSettingsPage.tsx b/src/apps/components/AppDetailsSettingsPage/AppDetailsSettingsPage.tsx new file mode 100644 index 000000000..86672606e --- /dev/null +++ b/src/apps/components/AppDetailsSettingsPage/AppDetailsSettingsPage.tsx @@ -0,0 +1,146 @@ +import Button from "@material-ui/core/Button"; +import Typography from "@material-ui/core/Typography"; +import AppHeader from "@saleor/components/AppHeader"; +import CardSpacer from "@saleor/components/CardSpacer"; +import Container from "@saleor/components/Container"; +import Grid from "@saleor/components/Grid"; +import Hr from "@saleor/components/Hr"; +import useTheme from "@saleor/hooks/useTheme"; +import { sectionNames } from "@saleor/intl"; +import classNames from "classnames"; +import React, { useEffect, useRef } from "react"; +import { FormattedMessage, useIntl } from "react-intl"; +import urlJoin from "url-join"; + +import { App_app } from "../../types/App"; +import { useStyles } from "./styles"; +import useSettingsBreadcrumbs from "./useSettingsBreadcrumbs"; + +export interface AppDetailsSettingsPageProps { + backendHost: string; + data: App_app; + navigateToDashboard: () => void; + onBack: () => void; + onError: () => void; +} + +export const AppDetailsSettingsPage: React.FC = ({ + backendHost, + data, + navigateToDashboard, + onBack, + onError +}) => { + const iframeRef = useRef(null); + const intl = useIntl(); + const classes = useStyles({}); + const { sendThemeToExtension } = useTheme(); + const [breadcrumbs, onBreadcrumbClick] = useSettingsBreadcrumbs(); + + useEffect(() => { + if (!iframeRef.current?.innerHTML && data?.configurationUrl) { + fetch(data?.configurationUrl, { + headers: { + "x-saleor-domain": backendHost, + "x-saleor-token": data.accessToken + }, + method: "GET" + }) + .then(async response => { + const url = new URL(response.url); + const text = await response.text(); + const content = new DOMParser().parseFromString(text, "text/html"); + + const iFrame = document.createElement("iframe"); + iFrame.src = "about:blank"; + iFrame.id = "extension-app"; + iframeRef.current.innerHTML = ""; + iframeRef.current.appendChild(iFrame); + const iFrameDoc = + iFrame.contentWindow && iFrame.contentWindow.document; + + const documentElement = content.documentElement; + const formScript = documentElement.querySelector("script"); + const formURL = new URL(documentElement.querySelector("script").src); + formScript.src = `${urlJoin(url.origin, formURL.pathname)}`; + iFrameDoc.write(content.documentElement.innerHTML); + iFrameDoc.close(); + iFrame.contentWindow.onload = sendThemeToExtension; + }) + .catch(() => onError()); + } + }, [data]); + + return ( + + + {intl.formatMessage(sectionNames.apps)} + + +
+
+ + {data?.name} + + {breadcrumbs.map(b => ( + onBreadcrumbClick(b.value)} + key={b.label} + > + {b.label} + + ))} +
+
+
+ + + +
+
+ + +
+ + +
+ + + ); +}; + +AppDetailsSettingsPage.displayName = "AppDetailsSettingsPage"; +export default AppDetailsSettingsPage; diff --git a/src/apps/components/AppDetailsSettingsPage/index.ts b/src/apps/components/AppDetailsSettingsPage/index.ts new file mode 100644 index 000000000..b492e446b --- /dev/null +++ b/src/apps/components/AppDetailsSettingsPage/index.ts @@ -0,0 +1,2 @@ +export * from "./AppDetailsSettingsPage"; +export { default } from "./AppDetailsSettingsPage"; diff --git a/src/apps/components/AppDetailsSettingsPage/styles.ts b/src/apps/components/AppDetailsSettingsPage/styles.ts new file mode 100644 index 000000000..cf6f42e4d --- /dev/null +++ b/src/apps/components/AppDetailsSettingsPage/styles.ts @@ -0,0 +1,62 @@ +import { makeStyles } from "@material-ui/core/styles"; + +export const useStyles = makeStyles( + theme => ({ + appSettingsHeader: { + "& > button, & > a": { + "&:last-child": { + marginRight: 0 + }, + marginRight: theme.spacing(2) + }, + display: "flex", + justifyContent: "flex-end" + }, + breadcrumb: { + "&:not(:last-child)": { + "&:after": { + content: "'/'", + display: "block", + position: "absolute", + right: -theme.spacing(2), + top: 0 + }, + "&:not(:first-child):hover": { + cursor: "pointer", + textDecoration: "underline" + } + }, + marginRight: theme.spacing(3), + position: "relative" + }, + breadcrumbContainer: { + alignItems: "center", + display: "flex" + }, + breadcrumbDisabled: { + "&:hover": { + textDecoration: "none" + }, + color: theme.palette.text.disabled + }, + breadcrumbs: { + display: "flex" + }, + hr: { + border: "none", + borderTop: `1px solid ${theme.palette.divider}`, + height: 0, + marginBottom: 0, + marginTop: 0, + width: "100%" + }, + iframeContainer: { + "& > iframe": { + border: "none", + minHeight: "75vh", + width: "100%" + } + } + }), + { name: "AppDetailsSettingsPage" } +); diff --git a/src/apps/components/AppDetailsSettingsPage/useSettingsBreadcrumbs.ts b/src/apps/components/AppDetailsSettingsPage/useSettingsBreadcrumbs.ts new file mode 100644 index 000000000..3edcc45ec --- /dev/null +++ b/src/apps/components/AppDetailsSettingsPage/useSettingsBreadcrumbs.ts @@ -0,0 +1,38 @@ +import { + Breadcrumb, + BreadcrumbChangeMessage, + BreadcrumbClickMessage, + ExtensionMessageEvent, + ExtensionMessageType, + sendMessageToExtension, + useExtensionMessage +} from "@saleor/macaw-ui/extensions"; +import { useState } from "react"; + +type UseSettingsBreadcrumbs = [Breadcrumb[], (value: string) => void]; +function useSettingsBreadcrumbs(): UseSettingsBreadcrumbs { + const [breadcrumbs, setBreadcrumbs] = useState([]); + + const handleBreadcrumbSet = ( + event: ExtensionMessageEvent + ) => { + if (event.data.type === ExtensionMessageType.BREADCRUMB_SET) { + setBreadcrumbs(event.data.breadcrumbs); + } + }; + + useExtensionMessage(handleBreadcrumbSet); + + const handleBreadcrumbClick = (value: string) => + sendMessageToExtension( + { + breadcrumb: value, + type: ExtensionMessageType.BREADCRUMB_CLICK + }, + "*" + ); + + return [breadcrumbs, handleBreadcrumbClick]; +} + +export default useSettingsBreadcrumbs; diff --git a/src/apps/components/AppInProgressDeleteDialog/AppInProgressDeleteDialog.stories.tsx b/src/apps/components/AppInProgressDeleteDialog/AppInProgressDeleteDialog.stories.tsx new file mode 100644 index 000000000..fc8598add --- /dev/null +++ b/src/apps/components/AppInProgressDeleteDialog/AppInProgressDeleteDialog.stories.tsx @@ -0,0 +1,22 @@ +import Decorator from "@saleor/storybook/Decorator"; +import { storiesOf } from "@storybook/react"; +import React from "react"; + +import AppInProgressDeleteDialog, { + AppInProgressDeleteDialogProps +} from "./AppInProgressDeleteDialog"; + +const props: AppInProgressDeleteDialogProps = { + confirmButtonState: "default", + name: "App", + onClose: () => undefined, + onConfirm: () => undefined, + open: true +}; + +storiesOf("Views / Apps / Delete app failed installation", module) + .addDecorator(Decorator) + .add("default", () => ) + .add("unnamed app", () => ( + + )); diff --git a/src/apps/components/AppInProgressDeleteDialog/AppInProgressDeleteDialog.tsx b/src/apps/components/AppInProgressDeleteDialog/AppInProgressDeleteDialog.tsx new file mode 100644 index 000000000..272a4fac8 --- /dev/null +++ b/src/apps/components/AppInProgressDeleteDialog/AppInProgressDeleteDialog.tsx @@ -0,0 +1,57 @@ +import DialogContentText from "@material-ui/core/DialogContentText"; +import ActionDialog from "@saleor/components/ActionDialog"; +import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; +import { getStringOrPlaceholder } from "@saleor/misc"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + +export interface AppInProgressDeleteDialogProps { + confirmButtonState: ConfirmButtonTransitionState; + open: boolean; + name: string; + onClose: () => void; + onConfirm: () => void; +} + +const AppInProgressDeleteDialog: React.FC = ({ + confirmButtonState, + open, + name, + onClose, + onConfirm +}) => { + const intl = useIntl(); + + return ( + + + {["", null].includes(name) ? ( + + ) : ( + {getStringOrPlaceholder(name)} + }} + /> + )} + + + ); +}; +AppInProgressDeleteDialog.displayName = "AppInProgressDeleteDialog"; +export default AppInProgressDeleteDialog; diff --git a/src/apps/components/AppInProgressDeleteDialog/index.ts b/src/apps/components/AppInProgressDeleteDialog/index.ts new file mode 100644 index 000000000..64c241dd2 --- /dev/null +++ b/src/apps/components/AppInProgressDeleteDialog/index.ts @@ -0,0 +1,2 @@ +export * from "./AppInProgressDeleteDialog"; +export { default } from "./AppInProgressDeleteDialog"; diff --git a/src/apps/components/AppInstallErrorPage/AppInstallErrorPage.tsx b/src/apps/components/AppInstallErrorPage/AppInstallErrorPage.tsx new file mode 100644 index 000000000..ef26b4f0a --- /dev/null +++ b/src/apps/components/AppInstallErrorPage/AppInstallErrorPage.tsx @@ -0,0 +1,56 @@ +import errorImg from "@assets/images/app-install-error.svg"; +import Button from "@material-ui/core/Button"; +import Grid from "@material-ui/core/Grid"; +import Typography from "@material-ui/core/Typography"; +import Container from "@saleor/components/Container"; +import React from "react"; +import { FormattedMessage } from "react-intl"; + +import { useStyles } from "./styles"; + +interface AppInstallErrorPageProps { + onBack: () => void; +} + +export const AppInstallErrorPage: React.FC = ({ + onBack +}) => { + const classes = useStyles({}); + + return ( + + + + + + + + + + + + + + + + + ); +}; + +export default AppInstallErrorPage; diff --git a/src/apps/components/AppInstallErrorPage/index.ts b/src/apps/components/AppInstallErrorPage/index.ts new file mode 100644 index 000000000..c49180823 --- /dev/null +++ b/src/apps/components/AppInstallErrorPage/index.ts @@ -0,0 +1,2 @@ +export * from "./AppInstallErrorPage"; +export { default } from "./AppInstallErrorPage"; diff --git a/src/apps/components/AppInstallErrorPage/styles.ts b/src/apps/components/AppInstallErrorPage/styles.ts new file mode 100644 index 000000000..6232b920f --- /dev/null +++ b/src/apps/components/AppInstallErrorPage/styles.ts @@ -0,0 +1,26 @@ +import { makeStyles } from "@material-ui/core/styles"; + +export const useStyles = makeStyles( + theme => ({ + button: { + marginTop: theme.spacing(2), + padding: theme.spacing(1.5, 2) + }, + root: { + "& > div": { + minHeight: "80vh" + }, + "& h3": { + fontWeight: 600, + marginBottom: theme.spacing(3), + maxWidth: theme.spacing(60) + }, + "& img": { + maxWidth: "100%" + } + } + }), + { + name: "AppInstallErrorPage" + } +); diff --git a/src/apps/components/AppInstallPage/AppInstallPage.stories.tsx b/src/apps/components/AppInstallPage/AppInstallPage.stories.tsx new file mode 100644 index 000000000..4847c70b0 --- /dev/null +++ b/src/apps/components/AppInstallPage/AppInstallPage.stories.tsx @@ -0,0 +1,18 @@ +import Decorator from "@saleor/storybook/Decorator"; +import { storiesOf } from "@storybook/react"; +import React from "react"; + +import { installApp } from "../../fixtures"; +import AppInstallPage, { AppInstallPageProps } from "./AppInstallPage"; + +const props: AppInstallPageProps = { + data: installApp, + loading: false, + navigateToAppsList: () => undefined, + onSubmit: () => undefined +}; + +storiesOf("Views / Apps / Install App", module) + .addDecorator(Decorator) + .add("default", () => ) + .add("loading", () => ); diff --git a/src/apps/components/AppInstallPage/AppInstallPage.tsx b/src/apps/components/AppInstallPage/AppInstallPage.tsx new file mode 100644 index 000000000..b6ca74f80 --- /dev/null +++ b/src/apps/components/AppInstallPage/AppInstallPage.tsx @@ -0,0 +1,160 @@ +import saleorDarkLogoSmall from "@assets/images/logo-dark-small.svg"; +import plusIcon from "@assets/images/plus-icon.svg"; +import Button from "@material-ui/core/Button"; +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import Grid from "@material-ui/core/Grid"; +import Typography from "@material-ui/core/Typography"; +import CardSpacer from "@saleor/components/CardSpacer"; +import CardTitle from "@saleor/components/CardTitle"; +import Container from "@saleor/components/Container"; +import Hr from "@saleor/components/Hr"; +import Skeleton from "@saleor/components/Skeleton"; +import { buttonMessages } from "@saleor/intl"; +import classNames from "classnames"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + +import { useStyles } from "../../styles"; +import { AppFetch_appFetchManifest_manifest } from "../../types/AppFetch"; + +export interface AppInstallPageProps { + data: AppFetch_appFetchManifest_manifest; + loading: boolean; + navigateToAppsList: () => void; + onSubmit: () => void; +} + +export const AppInstallPage: React.FC = ({ + data, + loading, + navigateToAppsList, + onSubmit +}) => { + const intl = useIntl(); + const classes = useStyles({}); + + const name = data?.name || ""; + + return ( + + + + + ) : ( + intl.formatMessage( + { + defaultMessage: `You are about to install {name}`, + description: "section header" + }, + { name } + ) + ) + } + /> + + {loading ? ( + + ) : ( +
+
+ +
+ +
+

{name?.charAt(0).toUpperCase()}

+
+
+ )} +
+
+ + + + + {loading ? ( + + ) : ( + <> + + + + {!!data?.permissions?.length && ( +
    + {data?.permissions?.map(perm => ( +
  • {perm.name}
  • + ))} +
+ )} +
+ + + + + + + + + )} +
+
+ + + + + + + + + +
+ ); +}; + +AppInstallPage.displayName = "AppInstallPage"; +export default AppInstallPage; diff --git a/src/apps/components/AppInstallPage/index.ts b/src/apps/components/AppInstallPage/index.ts new file mode 100644 index 000000000..6cdc3393b --- /dev/null +++ b/src/apps/components/AppInstallPage/index.ts @@ -0,0 +1,2 @@ +export * from "./AppInstallPage"; +export { default } from "./AppInstallPage"; diff --git a/src/apps/components/AppsInProgress/AppsInProgress.tsx b/src/apps/components/AppsInProgress/AppsInProgress.tsx new file mode 100644 index 000000000..0d1ed27df --- /dev/null +++ b/src/apps/components/AppsInProgress/AppsInProgress.tsx @@ -0,0 +1,117 @@ +import Button from "@material-ui/core/Button"; +import Progress from "@material-ui/core/CircularProgress"; +import IconButton from "@material-ui/core/IconButton"; +import TableBody from "@material-ui/core/TableBody"; +import TableCell from "@material-ui/core/TableCell"; +import TableRow from "@material-ui/core/TableRow"; +import Tooltip from "@material-ui/core/Tooltip"; +import Typography from "@material-ui/core/Typography"; +import DeleteIcon from "@material-ui/icons/Delete"; +import ErrorIcon from "@material-ui/icons/Error"; +import CardTitle from "@saleor/components/CardTitle"; +import { renderCollection, stopPropagation } from "@saleor/misc"; +import classNames from "classnames"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + +import { JobStatusEnum } from "../../../types/globalTypes"; +import { useStyles } from "../../styles"; +import { AppsInstallations_appsInstallations } from "../../types/AppsInstallations"; +import CardContainer from "../CardContainer"; + +export interface AppsInProgressProps { + appsList: AppsInstallations_appsInstallations[]; + disabled: boolean; + onAppInstallRetry: (id: string) => void; + onRemove: (id: string) => void; +} + +const AppsInProgress: React.FC = ({ + appsList, + disabled, + onAppInstallRetry, + onRemove, + ...props +}) => { + const intl = useIntl(); + const classes = useStyles(props); + + return ( + + } + > + + {renderCollection(appsList, ({ status, appName, id, message }) => ( + + + {appName} + + {status === JobStatusEnum.PENDING && ( + + + + +
+ +
+
+ )} + {status === JobStatusEnum.FAILED && ( + + + + {message}} + classes={{ + tooltip: classes.customTooltip + }} + > + + + + + onRemove(id))} + > + + + + )} +
+ ))} +
+
+ ); +}; + +AppsInProgress.displayName = "AppsInProgress"; +export default AppsInProgress; diff --git a/src/apps/components/AppsInProgress/index.ts b/src/apps/components/AppsInProgress/index.ts new file mode 100644 index 000000000..a18fc1160 --- /dev/null +++ b/src/apps/components/AppsInProgress/index.ts @@ -0,0 +1,2 @@ +export * from "./AppsInProgress"; +export { default } from "./AppsInProgress"; diff --git a/src/apps/components/AppsListPage/AppListPage.stories.tsx b/src/apps/components/AppsListPage/AppListPage.stories.tsx new file mode 100644 index 000000000..dded8b172 --- /dev/null +++ b/src/apps/components/AppsListPage/AppListPage.stories.tsx @@ -0,0 +1,58 @@ +import { + listActionsProps, + pageListProps, + searchPageProps, + sortPageProps, + tabPageProps +} from "@saleor/fixtures"; +import Decorator from "@saleor/storybook/Decorator"; +import { storiesOf } from "@storybook/react"; +import React from "react"; + +import { appsInProgress, appsList, customAppsList } from "../../fixtures"; +import AppsListPage, { AppsListPageProps } from "./AppsListPage"; + +const props: AppsListPageProps = { + ...listActionsProps, + ...pageListProps.default, + ...searchPageProps, + ...sortPageProps, + ...tabPageProps, + appsInProgressList: { appsInstallations: appsInProgress }, + customAppsList, + disabled: false, + installedAppsList: appsList, + loadingAppsInProgress: false, + navigateToCustomApp: () => undefined, + navigateToCustomAppCreate: () => undefined, + onAppInProgressRemove: () => undefined, + onAppInstallRetry: () => undefined, + onCustomAppRemove: () => undefined, + onInstalledAppRemove: () => undefined, + onNextPage: () => undefined, + onPreviousPage: () => undefined, + onRowClick: () => undefined, + onSettingsRowClick: () => undefined +}; + +storiesOf("Views / Apps / Apps list", module) + .addDecorator(Decorator) + .add("default", () => ) + .add("loading", () => ( + + )) + .add("no data", () => ( + + )); diff --git a/src/apps/components/AppsListPage/AppsListPage.tsx b/src/apps/components/AppsListPage/AppsListPage.tsx new file mode 100644 index 000000000..6b17f4f01 --- /dev/null +++ b/src/apps/components/AppsListPage/AppsListPage.tsx @@ -0,0 +1,76 @@ +import Container from "@saleor/components/Container"; +import PageHeader from "@saleor/components/PageHeader"; +import { sectionNames } from "@saleor/intl"; +import { ListProps } from "@saleor/types"; +import React from "react"; +import { useIntl } from "react-intl"; + +import { AppsInstallations } from "../../types/AppsInstallations"; +import { AppsList_apps_edges } from "../../types/AppsList"; +import AppsInProgress from "../AppsInProgress/AppsInProgress"; +import CustomApps from "../CustomApps/CustomApps"; +import InstalledApps from "../InstalledApps/InstalledApps"; +import Marketplace from "../Marketplace"; + +export interface AppsListPageProps extends ListProps { + installedAppsList: AppsList_apps_edges[]; + customAppsList: AppsList_apps_edges[]; + appsInProgressList?: AppsInstallations; + loadingAppsInProgress: boolean; + navigateToCustomApp: (id: string) => () => void; + navigateToCustomAppCreate: () => void; + onInstalledAppRemove: (id: string) => void; + onCustomAppRemove: (id: string) => void; + onAppInProgressRemove: (id: string) => void; + onAppInstallRetry: (id: string) => void; + onSettingsRowClick: (id: string) => () => void; +} + +const AppsListPage: React.FC = ({ + appsInProgressList, + customAppsList, + installedAppsList, + loadingAppsInProgress, + navigateToCustomApp, + navigateToCustomAppCreate, + onInstalledAppRemove, + onCustomAppRemove, + onAppInProgressRemove, + onAppInstallRetry, + onSettingsRowClick, + ...listProps +}) => { + const intl = useIntl(); + + const appsInProgress = appsInProgressList?.appsInstallations; + + return ( + + + {!!appsInProgress?.length && ( + + )} + + + + + ); +}; + +AppsListPage.displayName = "AppsListPage"; +export default AppsListPage; diff --git a/src/apps/components/AppsListPage/index.ts b/src/apps/components/AppsListPage/index.ts new file mode 100644 index 000000000..4fb8fb6a4 --- /dev/null +++ b/src/apps/components/AppsListPage/index.ts @@ -0,0 +1,2 @@ +export * from "./AppsListPage"; +export { default } from "./AppsListPage"; diff --git a/src/apps/components/AppsSkeleton/AppsSkeleton.tsx b/src/apps/components/AppsSkeleton/AppsSkeleton.tsx new file mode 100644 index 000000000..21fdb5ba2 --- /dev/null +++ b/src/apps/components/AppsSkeleton/AppsSkeleton.tsx @@ -0,0 +1,21 @@ +import TableCell from "@material-ui/core/TableCell"; +import TableRow from "@material-ui/core/TableRow"; +import Skeleton from "@saleor/components/Skeleton"; +import React from "react"; + +import { useStyles } from "../../styles"; + +export const AppsSkeleton = () => { + const classes = useStyles({}); + + return ( + + + + + + ); +}; + +AppsSkeleton.displayName = "AppsSkeleton"; +export default AppsSkeleton; diff --git a/src/apps/components/AppsSkeleton/index.ts b/src/apps/components/AppsSkeleton/index.ts new file mode 100644 index 000000000..a91325e46 --- /dev/null +++ b/src/apps/components/AppsSkeleton/index.ts @@ -0,0 +1,2 @@ +export * from "./AppsSkeleton"; +export { default } from "./AppsSkeleton"; diff --git a/src/apps/components/CardContainer/CardContainer.tsx b/src/apps/components/CardContainer/CardContainer.tsx new file mode 100644 index 000000000..81444808e --- /dev/null +++ b/src/apps/components/CardContainer/CardContainer.tsx @@ -0,0 +1,29 @@ +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import ResponsiveTable from "@saleor/components/ResponsiveTable"; +import React from "react"; + +import { useStyles } from "../../styles"; + +export interface CardContainerProps { + children: React.ReactNode; + header: React.ReactNode; +} + +const CardContainer: React.FC = ({ children, header }) => { + const classes = useStyles({}); + + return ( +
+ + {header} + + {children} + + +
+ ); +}; + +CardContainer.displayName = "CardContainer"; +export default CardContainer; diff --git a/src/apps/components/CardContainer/index.ts b/src/apps/components/CardContainer/index.ts new file mode 100644 index 000000000..3cca607ae --- /dev/null +++ b/src/apps/components/CardContainer/index.ts @@ -0,0 +1,2 @@ +export * from "./CardContainer"; +export { default } from "./CardContainer"; diff --git a/src/services/components/ServiceCreatePage/ServiceCreatePage.tsx b/src/apps/components/CustomAppCreatePage/CustomAppCreatePage.tsx similarity index 72% rename from src/services/components/ServiceCreatePage/ServiceCreatePage.tsx rename to src/apps/components/CustomAppCreatePage/CustomAppCreatePage.tsx index 22edb1f59..1c948a2be 100644 --- a/src/services/components/ServiceCreatePage/ServiceCreatePage.tsx +++ b/src/apps/components/CustomAppCreatePage/CustomAppCreatePage.tsx @@ -1,9 +1,7 @@ -import React from "react"; -import { useIntl } from "react-intl"; - +import { AppErrorFragment } from "@saleor/apps/types/AppErrorFragment"; import AccountPermissions from "@saleor/components/AccountPermissions"; -import AccountStatus from "@saleor/components/AccountStatus"; import AppHeader from "@saleor/components/AppHeader"; +import AppStatus from "@saleor/components/AppStatus"; import CardSpacer from "@saleor/components/CardSpacer"; import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; import Container from "@saleor/components/Container"; @@ -14,27 +12,29 @@ import SaveButtonBar from "@saleor/components/SaveButtonBar"; import { ShopInfo_shop_permissions } from "@saleor/components/Shop/types/ShopInfo"; import { sectionNames } from "@saleor/intl"; import { PermissionEnum } from "@saleor/types/globalTypes"; -import { AccountErrorFragment } from "@saleor/customers/types/AccountErrorFragment"; import { getFormErrors } from "@saleor/utils/errors"; -import getAccountErrorMessage from "@saleor/utils/errors/account"; -import ServiceInfo from "../ServiceInfo"; +import getAppErrorMessage from "@saleor/utils/errors/app"; +import React from "react"; +import { useIntl } from "react-intl"; -export interface ServiceCreatePageFormData { +import CustomAppInformation from "../CustomAppInformation"; + +export interface CustomAppCreatePageFormData { hasFullAccess: boolean; isActive: boolean; name: string; permissions: PermissionEnum[]; } -export interface ServiceCreatePageProps { +export interface CustomAppCreatePageProps { disabled: boolean; - errors: AccountErrorFragment[]; + errors: AppErrorFragment[]; permissions: ShopInfo_shop_permissions[]; saveButtonBarState: ConfirmButtonTransitionState; onBack: () => void; - onSubmit: (data: ServiceCreatePageFormData) => void; + onSubmit: (data: CustomAppCreatePageFormData) => void; } -const ServiceCreatePage: React.FC = props => { +const CustomAppCreatePage: React.FC = props => { const { disabled, errors, @@ -45,7 +45,7 @@ const ServiceCreatePage: React.FC = props => { } = props; const intl = useIntl(); - const initialForm: ServiceCreatePageFormData = { + const initialForm: CustomAppCreatePageFormData = { hasFullAccess: false, isActive: false, name: "", @@ -53,24 +53,24 @@ const ServiceCreatePage: React.FC = props => { }; const formErrors = getFormErrors(["permissions"], errors || []); - const permissionsError = getAccountErrorMessage(formErrors.permissions, intl); + const permissionsError = getAppErrorMessage(formErrors.permissions, intl); return (
{({ data, change, hasChanged, submit }) => ( - {intl.formatMessage(sectionNames.serviceAccounts)} + {intl.formatMessage(sectionNames.apps)}
- = props => { permissionsExceeded={false} onChange={change} fullAccessLabel={intl.formatMessage({ - defaultMessage: "User has full access to the store", + defaultMessage: "Grant this app full access to the store", description: "checkbox label" })} description={intl.formatMessage({ defaultMessage: - "Expand or restrict user's permissions to access certain part of saleor system.", + "Expand or restrict app permissions to access certain part of Saleor system.", description: "card description" })} /> - = props => { ); }; -ServiceCreatePage.displayName = "ServiceCreatePage"; -export default ServiceCreatePage; +CustomAppCreatePage.displayName = "CustomAppCreatePage"; +export default CustomAppCreatePage; diff --git a/src/apps/components/CustomAppCreatePage/index.ts b/src/apps/components/CustomAppCreatePage/index.ts new file mode 100644 index 000000000..3f24a8549 --- /dev/null +++ b/src/apps/components/CustomAppCreatePage/index.ts @@ -0,0 +1,2 @@ +export * from "./CustomAppCreatePage"; +export { default } from "./CustomAppCreatePage"; diff --git a/src/services/components/ServiceDefaultToken/ServiceDefaultToken.tsx b/src/apps/components/CustomAppDefaultToken/CustomAppDefaultToken.tsx similarity index 68% rename from src/services/components/ServiceDefaultToken/ServiceDefaultToken.tsx rename to src/apps/components/CustomAppDefaultToken/CustomAppDefaultToken.tsx index bcbe7f1fb..38b7433fd 100644 --- a/src/services/components/ServiceDefaultToken/ServiceDefaultToken.tsx +++ b/src/apps/components/CustomAppDefaultToken/CustomAppDefaultToken.tsx @@ -3,8 +3,6 @@ import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; import IconButton from "@material-ui/core/IconButton"; import Paper from "@material-ui/core/Paper"; -import { makeStyles } from "@material-ui/core/styles"; -import { fade } from "@material-ui/core/styles/colorManipulator"; import Typography from "@material-ui/core/Typography"; import CloseIcon from "@material-ui/icons/Close"; import Link from "@saleor/components/Link"; @@ -12,50 +10,16 @@ import useClipboard from "@saleor/hooks/useClipboard"; import React from "react"; import { FormattedMessage } from "react-intl"; -export interface ServiceDefaultTokenProps { +import { useStyles } from "./styles"; + +export interface CustomAppDefaultTokenProps { apiUri: string; token: string; onApiUriClick: () => void; onTokenClose: () => void; } -const useStyles = makeStyles( - theme => ({ - cancel: { - marginRight: theme.spacing(1) - }, - closeContainer: { - display: "flex", - justifyContent: "flex-end", - position: "relative", - right: -theme.spacing(), - top: -theme.spacing(1) - }, - content: { - display: "grid", - gridColumnGap: theme.spacing(3), - gridTemplateColumns: "1fr 60px", - marginBottom: theme.spacing(3) - }, - copy: { - marginTop: theme.spacing(), - position: "relative", - right: theme.spacing(1) - }, - paper: { - background: fade(theme.palette.primary.main, 0.05), - padding: theme.spacing(2, 3) - }, - root: { - boxShadow: "0px 5px 10px rgba(0, 0, 0, 0.05)" - } - }), - { - name: "ServiceTokenCreateDialog" - } -); - -const ServiceDefaultToken: React.FC = props => { +const CustomAppDefaultToken: React.FC = props => { const { apiUri, token, onApiUriClick, onTokenClose } = props; const classes = useStyles(props); const [copied, copy] = useClipboard(); @@ -112,5 +76,5 @@ const ServiceDefaultToken: React.FC = props => { ); }; -ServiceDefaultToken.displayName = "ServiceDefaultToken"; -export default ServiceDefaultToken; +CustomAppDefaultToken.displayName = "CustomAppDefaultToken"; +export default CustomAppDefaultToken; diff --git a/src/apps/components/CustomAppDefaultToken/index.ts b/src/apps/components/CustomAppDefaultToken/index.ts new file mode 100644 index 000000000..2d086352c --- /dev/null +++ b/src/apps/components/CustomAppDefaultToken/index.ts @@ -0,0 +1,2 @@ +export * from "./CustomAppDefaultToken"; +export { default } from "./CustomAppDefaultToken"; diff --git a/src/apps/components/CustomAppDefaultToken/styles.ts b/src/apps/components/CustomAppDefaultToken/styles.ts new file mode 100644 index 000000000..1f63c79ef --- /dev/null +++ b/src/apps/components/CustomAppDefaultToken/styles.ts @@ -0,0 +1,38 @@ +import { makeStyles } from "@material-ui/core/styles"; +import { fade } from "@material-ui/core/styles/colorManipulator"; + +export const useStyles = makeStyles( + theme => ({ + cancel: { + marginRight: theme.spacing(1) + }, + closeContainer: { + display: "flex", + justifyContent: "flex-end", + position: "relative", + right: -theme.spacing(), + top: -theme.spacing(1) + }, + content: { + display: "grid", + gridColumnGap: theme.spacing(3), + gridTemplateColumns: "1fr 60px", + marginBottom: theme.spacing(3) + }, + copy: { + marginTop: theme.spacing(), + position: "relative", + right: theme.spacing(1) + }, + paper: { + background: fade(theme.palette.primary.main, 0.05), + padding: theme.spacing(2, 3) + }, + root: { + boxShadow: "0px 5px 10px rgba(0, 0, 0, 0.05)" + } + }), + { + name: "CustomAppTokenCreateDialog" + } +); diff --git a/src/services/components/ServiceDetailsPage/ServiceDetailsPage.tsx b/src/apps/components/CustomAppDetailsPage/CustomAppDetailsPage.tsx similarity index 59% rename from src/services/components/ServiceDetailsPage/ServiceDetailsPage.tsx rename to src/apps/components/CustomAppDetailsPage/CustomAppDetailsPage.tsx index ebd9296ae..f452257e2 100644 --- a/src/services/components/ServiceDetailsPage/ServiceDetailsPage.tsx +++ b/src/apps/components/CustomAppDetailsPage/CustomAppDetailsPage.tsx @@ -1,9 +1,7 @@ -import React from "react"; -import { useIntl } from "react-intl"; - +import { AppErrorFragment } from "@saleor/apps/types/AppErrorFragment"; import AccountPermissions from "@saleor/components/AccountPermissions"; -import AccountStatus from "@saleor/components/AccountStatus"; import AppHeader from "@saleor/components/AppHeader"; +import AppStatus from "@saleor/components/AppStatus"; import CardSpacer from "@saleor/components/CardSpacer"; import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; import Container from "@saleor/components/Container"; @@ -13,89 +11,94 @@ import PageHeader from "@saleor/components/PageHeader"; import SaveButtonBar from "@saleor/components/SaveButtonBar"; import { ShopInfo_shop_permissions } from "@saleor/components/Shop/types/ShopInfo"; import { sectionNames } from "@saleor/intl"; -import { maybe } from "@saleor/misc"; -import { ServiceDetails_serviceAccount } from "@saleor/services/types/ServiceDetails"; import { PermissionEnum } from "@saleor/types/globalTypes"; -import { AccountErrorFragment } from "@saleor/customers/types/AccountErrorFragment"; import { getFormErrors } from "@saleor/utils/errors"; -import getAccountErrorMessage from "@saleor/utils/errors/account"; -import ServiceDefaultToken from "../ServiceDefaultToken"; -import ServiceInfo from "../ServiceInfo"; -import ServiceTokens from "../ServiceTokens"; +import getAppErrorMessage from "@saleor/utils/errors/app"; +import WebhooksList from "@saleor/webhooks/components/WebhooksList"; +import React from "react"; +import { useIntl } from "react-intl"; -export interface ServiceDetailsPageFormData { +import { AppUpdate_appUpdate_app } from "../../types/AppUpdate"; +import CustomAppDefaultToken from "../CustomAppDefaultToken"; +import CustomAppInformation from "../CustomAppInformation"; +import CustomAppTokens from "../CustomAppTokens"; + +export interface CustomAppDetailsPageFormData { hasFullAccess: boolean; isActive: boolean; name: string; permissions: PermissionEnum[]; } -export interface ServiceDetailsPageProps { +export interface CustomAppDetailsPageProps { apiUri: string; disabled: boolean; - errors: AccountErrorFragment[]; + errors: AppErrorFragment[]; permissions: ShopInfo_shop_permissions[]; saveButtonBarState: ConfirmButtonTransitionState; - service: ServiceDetails_serviceAccount; + app: AppUpdate_appUpdate_app; token: string; onApiUriClick: () => void; onBack: () => void; onTokenDelete: (id: string) => void; - onDelete: () => void; onTokenClose: () => void; onTokenCreate: () => void; - onSubmit: (data: ServiceDetailsPageFormData) => void; + onSubmit: (data: CustomAppDetailsPageFormData) => void; + onWebhookCreate: () => void; + onWebhookRemove: (id: string) => void; + navigateToWebhookDetails: (id: string) => () => void; } -const ServiceDetailsPage: React.FC = props => { +const CustomAppDetailsPage: React.FC = props => { const { apiUri, disabled, errors, permissions, saveButtonBarState, - service, + app, + navigateToWebhookDetails, token, onApiUriClick, onBack, - onDelete, onTokenClose, onTokenCreate, onTokenDelete, - onSubmit + onSubmit, + onWebhookCreate, + onWebhookRemove } = props; const intl = useIntl(); - const formErrors = getFormErrors(["permissions"], errors || []); - const permissionsError = getAccountErrorMessage(formErrors.permissions, intl); + const webhooks = app?.webhooks; - const initialForm: ServiceDetailsPageFormData = { - hasFullAccess: maybe( - () => - permissions.filter( - perm => - maybe(() => service.permissions, []).filter( - userPerm => userPerm.code === perm.code - ).length === 0 - ).length === 0, - false - ), - isActive: maybe(() => service.isActive, false), - name: maybe(() => service.name, ""), - permissions: maybe(() => service.permissions, []).map(perm => perm.code) + const formErrors = getFormErrors(["permissions"], errors || []); + const permissionsError = getAppErrorMessage(formErrors.permissions, intl); + + const initialForm: CustomAppDetailsPageFormData = { + hasFullAccess: + permissions?.filter( + perm => + app?.permissions?.filter(userPerm => userPerm.code === perm.code) + .length === 0 + ).length === 0 || false, + isActive: !!app?.isActive, + name: app?.name || "", + permissions: app?.permissions?.map(perm => perm.code) || [] }; + return ( {({ data, change, hasChanged, submit }) => ( - {intl.formatMessage(sectionNames.serviceAccounts)} + {intl.formatMessage(sectionNames.apps)} - service.name)} /> +
{token && ( <> - = props => { )} - - + +
= props => { permissionsExceeded={false} onChange={change} fullAccessLabel={intl.formatMessage({ - defaultMessage: "User has full access to the store", + defaultMessage: "Grant this app full access to the store", description: "checkbox label" })} description={intl.formatMessage({ defaultMessage: - "Expand or restrict user's permissions to access certain part of saleor system.", + "Expand or restrict app permissions to access certain part of Saleor system.", description: "card description" })} /> - = props => { state={saveButtonBarState} onCancel={onBack} onSave={submit} - onDelete={onDelete} /> )} @@ -160,5 +169,5 @@ const ServiceDetailsPage: React.FC = props => { ); }; -ServiceDetailsPage.displayName = "ServiceDetailsPage"; -export default ServiceDetailsPage; +CustomAppDetailsPage.displayName = "CustomAppDetailsPage"; +export default CustomAppDetailsPage; diff --git a/src/apps/components/CustomAppDetailsPage/index.ts b/src/apps/components/CustomAppDetailsPage/index.ts new file mode 100644 index 000000000..fc3198f13 --- /dev/null +++ b/src/apps/components/CustomAppDetailsPage/index.ts @@ -0,0 +1,2 @@ +export * from "./CustomAppDetailsPage"; +export { default } from "./CustomAppDetailsPage"; diff --git a/src/services/components/ServiceInfo/ServiceInfo.tsx b/src/apps/components/CustomAppInformation/CustomAppInformation.tsx similarity index 64% rename from src/services/components/ServiceInfo/ServiceInfo.tsx rename to src/apps/components/CustomAppInformation/CustomAppInformation.tsx index 1dbdba2c3..207a0d3c4 100644 --- a/src/services/components/ServiceInfo/ServiceInfo.tsx +++ b/src/apps/components/CustomAppInformation/CustomAppInformation.tsx @@ -1,25 +1,24 @@ import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; import TextField from "@material-ui/core/TextField"; +import { AppErrorFragment } from "@saleor/apps/types/AppErrorFragment"; +import CardTitle from "@saleor/components/CardTitle"; +import { FormChange } from "@saleor/hooks/useForm"; +import { getFormErrors } from "@saleor/utils/errors"; +import getAppErrorMessage from "@saleor/utils/errors/app"; import React from "react"; import { useIntl } from "react-intl"; -import CardTitle from "@saleor/components/CardTitle"; -import { FormChange } from "@saleor/hooks/useForm"; -import { AccountErrorFragment } from "@saleor/customers/types/AccountErrorFragment"; -import { getFormErrors } from "@saleor/utils/errors"; -import getAccountErrorMessage from "@saleor/utils/errors/account"; - -export interface ServiceInfoProps { +export interface CustomAppInfoProps { data: { name: string; }; disabled: boolean; - errors: AccountErrorFragment[]; + errors: AppErrorFragment[]; onChange: FormChange; } -const ServiceInfo: React.FC = ({ +const CustomAppInformation: React.FC = ({ data, disabled, errors, @@ -33,7 +32,7 @@ const ServiceInfo: React.FC = ({ @@ -42,10 +41,10 @@ const ServiceInfo: React.FC = ({ disabled={disabled} error={!!formErrors.name} label={intl.formatMessage({ - defaultMessage: "Account Name", - description: "service account" + defaultMessage: "App Name", + description: "custom app name" })} - helperText={getAccountErrorMessage(formErrors.name, intl)} + helperText={getAppErrorMessage(formErrors.name, intl)} fullWidth name="name" value={data.name} @@ -56,5 +55,5 @@ const ServiceInfo: React.FC = ({ ); }; -ServiceInfo.displayName = "ServiceInfo"; -export default ServiceInfo; +CustomAppInformation.displayName = "CustomAppInformation"; +export default CustomAppInformation; diff --git a/src/apps/components/CustomAppInformation/index.ts b/src/apps/components/CustomAppInformation/index.ts new file mode 100644 index 000000000..2ecb5c14b --- /dev/null +++ b/src/apps/components/CustomAppInformation/index.ts @@ -0,0 +1,2 @@ +export * from "./CustomAppInformation"; +export { default } from "./CustomAppInformation"; diff --git a/src/services/components/ServiceTokens/ServiceTokens.tsx b/src/apps/components/CustomAppTokens/CustomAppTokens.tsx similarity index 71% rename from src/services/components/ServiceTokens/ServiceTokens.tsx rename to src/apps/components/CustomAppTokens/CustomAppTokens.tsx index e0c6e39a1..9f96dcfc0 100644 --- a/src/services/components/ServiceTokens/ServiceTokens.tsx +++ b/src/apps/components/CustomAppTokens/CustomAppTokens.tsx @@ -1,52 +1,30 @@ import Button from "@material-ui/core/Button"; import Card from "@material-ui/core/Card"; import IconButton from "@material-ui/core/IconButton"; -import makeStyles from "@material-ui/core/styles/makeStyles"; import TableBody from "@material-ui/core/TableBody"; import TableCell from "@material-ui/core/TableCell"; import TableHead from "@material-ui/core/TableHead"; import TableRow from "@material-ui/core/TableRow"; import DeleteIcon from "@material-ui/icons/Delete"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import CardTitle from "@saleor/components/CardTitle"; import ResponsiveTable from "@saleor/components/ResponsiveTable"; import Skeleton from "@saleor/components/Skeleton"; -import { maybe, renderCollection } from "@saleor/misc"; -import { ServiceDetailsFragment_tokens } from "@saleor/services/types/ServiceDetailsFragment"; +import { renderCollection } from "@saleor/misc"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; -export interface ServiceTokensProps { - tokens: ServiceDetailsFragment_tokens[]; +import { AppUpdate_appUpdate_app_tokens } from "../../types/AppUpdate"; +import { useStyles } from "./styles"; + +export interface CustomAppTokensProps { + tokens: Array | null; onCreate: () => void; onDelete: (id: string) => void; } -const useStyles = makeStyles( - theme => ({ - [theme.breakpoints.down("md")]: { - colNote: { - width: 200 - } - }, - colActions: { - textAlign: "right", - width: 100 - }, - colKey: { - width: 200 - }, - colNote: {}, - table: { - tableLayout: "fixed" - } - }), - { name: "ServiceTokens" } -); - const numberOfColumns = 3; -const ServiceTokens: React.FC = props => { +const CustomAppTokens: React.FC = props => { const { tokens, onCreate, onDelete } = props; const classes = useStyles(props); const intl = useIntl(); @@ -55,7 +33,7 @@ const ServiceTokens: React.FC = props => { = props => { @@ -93,13 +71,10 @@ const ServiceTokens: React.FC = props => { token => ( - {maybe(() => token.name, )} + {token?.name || } - {maybe( - () => `**** ${token.authToken}`, - - )} + {token?.authToken ? `**** ${token.authToken}` : } = props => { ); }; -ServiceTokens.displayName = "ServiceTokens"; -export default ServiceTokens; +CustomAppTokens.displayName = "CustomAppTokens"; +export default CustomAppTokens; diff --git a/src/apps/components/CustomAppTokens/index.ts b/src/apps/components/CustomAppTokens/index.ts new file mode 100644 index 000000000..c88f1f2cf --- /dev/null +++ b/src/apps/components/CustomAppTokens/index.ts @@ -0,0 +1,2 @@ +export * from "./CustomAppTokens"; +export { default } from "./CustomAppTokens"; diff --git a/src/apps/components/CustomAppTokens/styles.ts b/src/apps/components/CustomAppTokens/styles.ts new file mode 100644 index 000000000..42231fff0 --- /dev/null +++ b/src/apps/components/CustomAppTokens/styles.ts @@ -0,0 +1,23 @@ +import makeStyles from "@material-ui/core/styles/makeStyles"; + +export const useStyles = makeStyles( + theme => ({ + [theme.breakpoints.down("md")]: { + colNote: { + width: 200 + } + }, + colActions: { + textAlign: "right", + width: 100 + }, + colKey: { + width: 200 + }, + colNote: {}, + table: { + tableLayout: "fixed" + } + }), + { name: "CustomAppTokens" } +); diff --git a/src/apps/components/CustomApps/CustomApps.tsx b/src/apps/components/CustomApps/CustomApps.tsx new file mode 100644 index 000000000..cb564600f --- /dev/null +++ b/src/apps/components/CustomApps/CustomApps.tsx @@ -0,0 +1,116 @@ +import Button from "@material-ui/core/Button"; +import CardHeader from "@material-ui/core/CardHeader"; +import IconButton from "@material-ui/core/IconButton"; +import TableBody from "@material-ui/core/TableBody"; +import TableCell from "@material-ui/core/TableCell"; +import TableRow from "@material-ui/core/TableRow"; +import Typography from "@material-ui/core/Typography"; +import DeleteIcon from "@material-ui/icons/Delete"; +import { commonMessages } from "@saleor/intl"; +import { renderCollection, stopPropagation } from "@saleor/misc"; +import React from "react"; +import { FormattedMessage } from "react-intl"; + +import { useStyles } from "../../styles"; +import { AppsList_apps_edges } from "../../types/AppsList"; +import AppsSkeleton from "../AppsSkeleton"; +import CardContainer from "../CardContainer"; +import DeactivatedText from "../DeactivatedText"; + +export interface CustomAppsProps { + appsList: AppsList_apps_edges[]; + navigateToCustomApp: (id: string) => () => void; + navigateToCustomAppCreate?: () => void; + onRemove: (id: string) => void; +} + +const CustomApps: React.FC = ({ + appsList, + navigateToCustomAppCreate, + onRemove, + navigateToCustomApp +}) => { + const classes = useStyles({}); + + return ( + + + + + ) + } + title={ + + + + } + /> +
+ + } + > + + {renderCollection( + appsList, + (app, index) => + app ? ( + + + + {app.node.name} + + {!app.node.isActive && ( +
+ +
+ )} +
+ + onRemove(app.node.id))} + > + + + +
+ ) : ( + + ), + () => ( + + + + + + + + ) + )} +
+
+ ); +}; + +CustomApps.displayName = "CustomApps"; +export default CustomApps; diff --git a/src/apps/components/CustomApps/index.ts b/src/apps/components/CustomApps/index.ts new file mode 100644 index 000000000..4c43c395b --- /dev/null +++ b/src/apps/components/CustomApps/index.ts @@ -0,0 +1,2 @@ +export * from "./CustomApps"; +export { default } from "./CustomApps"; diff --git a/src/apps/components/DeactivatedText/DeactivatedText.tsx b/src/apps/components/DeactivatedText/DeactivatedText.tsx new file mode 100644 index 000000000..4327fb911 --- /dev/null +++ b/src/apps/components/DeactivatedText/DeactivatedText.tsx @@ -0,0 +1,19 @@ +import Typography from "@material-ui/core/Typography"; +import React from "react"; +import { FormattedMessage } from "react-intl"; + +import { useStyles } from "./styles"; + +export const DeactivatedText: React.FC<{}> = () => { + const classes = useStyles({}); + return ( + + + + ); +}; + +export default DeactivatedText; diff --git a/src/apps/components/DeactivatedText/index.ts b/src/apps/components/DeactivatedText/index.ts new file mode 100644 index 000000000..6eb43119d --- /dev/null +++ b/src/apps/components/DeactivatedText/index.ts @@ -0,0 +1,2 @@ +export * from "./DeactivatedText"; +export { default } from "./DeactivatedText"; diff --git a/src/apps/components/DeactivatedText/styles.ts b/src/apps/components/DeactivatedText/styles.ts new file mode 100644 index 000000000..0c1e03ef2 --- /dev/null +++ b/src/apps/components/DeactivatedText/styles.ts @@ -0,0 +1,26 @@ +import { makeStyles } from "@material-ui/core/styles"; + +export const useStyles = makeStyles( + theme => ({ + root: { + "&:before": { + backgroundColor: theme.palette.error.main, + borderRadius: "50%", + content: "''", + display: "block", + height: 8, + left: 0, + position: "absolute", + top: "50%", + transform: "translateY(-50%)", + width: 8 + }, + color: theme.palette.error.main, + display: "inline-block", + marginLeft: theme.spacing(1.5), + paddingLeft: theme.spacing(2), + position: "relative" + } + }), + { name: "DeactivatedText" } +); diff --git a/src/apps/components/InstalledApps/InstalledApps.tsx b/src/apps/components/InstalledApps/InstalledApps.tsx new file mode 100644 index 000000000..8c307cbf1 --- /dev/null +++ b/src/apps/components/InstalledApps/InstalledApps.tsx @@ -0,0 +1,133 @@ +import Button from "@material-ui/core/Button"; +import IconButton from "@material-ui/core/IconButton"; +import TableBody from "@material-ui/core/TableBody"; +import TableCell from "@material-ui/core/TableCell"; +import TableFooter from "@material-ui/core/TableFooter"; +import TableRow from "@material-ui/core/TableRow"; +import Typography from "@material-ui/core/Typography"; +import DeleteIcon from "@material-ui/icons/Delete"; +import CardTitle from "@saleor/components/CardTitle"; +import TablePagination from "@saleor/components/TablePagination"; +import { renderCollection, stopPropagation } from "@saleor/misc"; +import { ListProps } from "@saleor/types"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + +import { useStyles } from "../../styles"; +import { AppsList_apps_edges } from "../../types/AppsList"; +import AppsSkeleton from "../AppsSkeleton"; +import CardContainer from "../CardContainer"; +import DeactivatedText from "../DeactivatedText"; + +export interface InstalledAppsProps extends ListProps { + appsList: AppsList_apps_edges[]; + onRemove: (id: string) => void; + onSettingsRowClick: (id: string) => () => void; +} +const numberOfColumns = 2; + +const InstalledApps: React.FC = ({ + appsList, + onRemove, + settings, + disabled, + onNextPage, + onPreviousPage, + onRowClick, + onUpdateListSettings, + onSettingsRowClick, + pageInfo, + ...props +}) => { + const intl = useIntl(); + const classes = useStyles(props); + + return ( + + } + > + <> + + + + + + + {renderCollection( + appsList, + (app, index) => + app ? ( + + + + {app.node.name} + + {!app.node.isActive && ( +
+ +
+ )} +
+ + + onRemove(app.node.id))} + > + + + +
+ ) : ( + + ), + () => ( + + + + + + + + ) + )} +
+ +
+ ); +}; + +InstalledApps.displayName = "InstalledApps"; +export default InstalledApps; diff --git a/src/apps/components/InstalledApps/index.ts b/src/apps/components/InstalledApps/index.ts new file mode 100644 index 000000000..03a42dc2f --- /dev/null +++ b/src/apps/components/InstalledApps/index.ts @@ -0,0 +1,2 @@ +export * from "./InstalledApps"; +export { default } from "./InstalledApps"; diff --git a/src/apps/components/Marketplace/Marketplace.tsx b/src/apps/components/Marketplace/Marketplace.tsx new file mode 100644 index 000000000..7ad75851d --- /dev/null +++ b/src/apps/components/Marketplace/Marketplace.tsx @@ -0,0 +1,59 @@ +import Button from "@material-ui/core/Button"; +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import Typography from "@material-ui/core/Typography"; +import CardTitle from "@saleor/components/CardTitle"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + +import { useStyles } from "../../styles"; + +interface MarketplaceProps { + link?: () => void; +} + +const Marketplace: React.FC = ({ link }) => { + const intl = useIntl(); + const classes = useStyles({}); + + return ( +
+ + + + {!!link ? ( + <> + + + + + + ) : ( + + + + )} + + +
+ ); +}; + +Marketplace.displayName = "Marketplace"; +export default Marketplace; diff --git a/src/apps/components/Marketplace/index.ts b/src/apps/components/Marketplace/index.ts new file mode 100644 index 000000000..ce958567a --- /dev/null +++ b/src/apps/components/Marketplace/index.ts @@ -0,0 +1,2 @@ +export * from "./Marketplace"; +export { default } from "./Marketplace"; diff --git a/src/services/components/ServiceTokenCreateDialog/ServiceTokenCreateDialog.tsx b/src/apps/components/TokenCreateDialog/TokenCreateDialog.tsx similarity index 83% rename from src/services/components/ServiceTokenCreateDialog/ServiceTokenCreateDialog.tsx rename to src/apps/components/TokenCreateDialog/TokenCreateDialog.tsx index 782d1e500..f7a571eed 100644 --- a/src/services/components/ServiceTokenCreateDialog/ServiceTokenCreateDialog.tsx +++ b/src/apps/components/TokenCreateDialog/TokenCreateDialog.tsx @@ -4,13 +4,8 @@ import DialogActions from "@material-ui/core/DialogActions"; import DialogContent from "@material-ui/core/DialogContent"; import DialogTitle from "@material-ui/core/DialogTitle"; import Paper from "@material-ui/core/Paper"; -import { makeStyles } from "@material-ui/core/styles"; import TextField from "@material-ui/core/TextField"; import Typography from "@material-ui/core/Typography"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - -import { fade } from "@material-ui/core/styles/colorManipulator"; import CardSpacer from "@saleor/components/CardSpacer"; import ConfirmButton, { ConfirmButtonTransitionState @@ -19,8 +14,12 @@ import Form from "@saleor/components/Form"; import FormSpacer from "@saleor/components/FormSpacer"; import useModalDialogOpen from "@saleor/hooks/useModalDialogOpen"; import { buttonMessages } from "@saleor/intl"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; -export interface ServiceTokenCreateDialogProps { +import { useStyles } from "./styles"; + +export interface TokenCreateDialogProps { confirmButtonState: ConfirmButtonTransitionState; open: boolean; token: string | undefined; @@ -28,37 +27,15 @@ export interface ServiceTokenCreateDialogProps { onCreate: (name: string) => void; } -type ServiceTokenCreateStep = "form" | "summary"; - -const useStyles = makeStyles( - theme => ({ - cancel: { - marginRight: theme.spacing(1) - }, - copy: { - marginTop: theme.spacing(), - position: "relative", - right: theme.spacing(1) - }, - paper: { - background: fade(theme.palette.primary.main, 0.05), - padding: theme.spacing(2, 3) - } - }), - { - name: "ServiceTokenCreateDialog" - } -); +type TokenCreateStep = "form" | "summary"; function handleCopy(token: string) { navigator.clipboard.writeText(token); } -const ServiceTokenCreateDialog: React.FC< - ServiceTokenCreateDialogProps -> = props => { +const TokenCreateDialog: React.FC = props => { const { confirmButtonState, open, token, onClose, onCreate } = props; - const [step, setStep] = React.useState("form"); + const [step, setStep] = React.useState("form"); const intl = useIntl(); const classes = useStyles(props); @@ -158,5 +135,5 @@ const ServiceTokenCreateDialog: React.FC< ); }; -ServiceTokenCreateDialog.displayName = "ServiceTokenCreateDialog"; -export default ServiceTokenCreateDialog; +TokenCreateDialog.displayName = "TokenCreateDialog"; +export default TokenCreateDialog; diff --git a/src/apps/components/TokenCreateDialog/index.ts b/src/apps/components/TokenCreateDialog/index.ts new file mode 100644 index 000000000..0ad4789c2 --- /dev/null +++ b/src/apps/components/TokenCreateDialog/index.ts @@ -0,0 +1,2 @@ +export { default } from "./TokenCreateDialog"; +export * from "./TokenCreateDialog"; diff --git a/src/apps/components/TokenCreateDialog/styles.ts b/src/apps/components/TokenCreateDialog/styles.ts new file mode 100644 index 000000000..4ba0e9333 --- /dev/null +++ b/src/apps/components/TokenCreateDialog/styles.ts @@ -0,0 +1,22 @@ +import { makeStyles } from "@material-ui/core/styles"; +import { fade } from "@material-ui/core/styles/colorManipulator"; + +export const useStyles = makeStyles( + theme => ({ + cancel: { + marginRight: theme.spacing(1) + }, + copy: { + marginTop: theme.spacing(), + position: "relative", + right: theme.spacing(1) + }, + paper: { + background: fade(theme.palette.primary.main, 0.05), + padding: theme.spacing(2, 3) + } + }), + { + name: "TokenCreateDialog" + } +); diff --git a/src/services/components/ServiceTokenDeleteDialog/ServiceTokenDeleteDialog.stories.tsx b/src/apps/components/TokenDeleteDialog/TokenDeleteDialog.stories.tsx similarity index 50% rename from src/services/components/ServiceTokenDeleteDialog/ServiceTokenDeleteDialog.stories.tsx rename to src/apps/components/TokenDeleteDialog/TokenDeleteDialog.stories.tsx index d1fcc2641..b639c5f72 100644 --- a/src/services/components/ServiceTokenDeleteDialog/ServiceTokenDeleteDialog.stories.tsx +++ b/src/apps/components/TokenDeleteDialog/TokenDeleteDialog.stories.tsx @@ -1,12 +1,10 @@ +import Decorator from "@saleor/storybook/Decorator"; import { storiesOf } from "@storybook/react"; import React from "react"; -import Decorator from "@saleor/storybook/Decorator"; -import ServiceTokenDeleteDialog, { - ServiceTokenDeleteDialogProps -} from "./ServiceTokenDeleteDialog"; +import TokenDeleteDialog, { TokenDeleteDialogProps } from "./TokenDeleteDialog"; -const props: ServiceTokenDeleteDialogProps = { +const props: TokenDeleteDialogProps = { confirmButtonState: "default", name: "Slack", onClose: () => undefined, @@ -14,6 +12,6 @@ const props: ServiceTokenDeleteDialogProps = { open: true }; -storiesOf("Views / Services / Token delete", module) +storiesOf("Views / Apps / Custom app details / Token delete", module) .addDecorator(Decorator) - .add("default", () => ); + .add("default", () => ); diff --git a/src/services/components/ServiceTokenDeleteDialog/ServiceTokenDeleteDialog.tsx b/src/apps/components/TokenDeleteDialog/TokenDeleteDialog.tsx similarity index 79% rename from src/services/components/ServiceTokenDeleteDialog/ServiceTokenDeleteDialog.tsx rename to src/apps/components/TokenDeleteDialog/TokenDeleteDialog.tsx index a7dd61d86..422b2f759 100644 --- a/src/services/components/ServiceTokenDeleteDialog/ServiceTokenDeleteDialog.tsx +++ b/src/apps/components/TokenDeleteDialog/TokenDeleteDialog.tsx @@ -1,11 +1,10 @@ import DialogContentText from "@material-ui/core/DialogContentText"; +import ActionDialog from "@saleor/components/ActionDialog"; +import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; import React from "react"; import { FormattedMessage, useIntl } from "react-intl"; -import ActionDialog from "@saleor/components/ActionDialog"; -import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; - -export interface ServiceTokenDeleteDialogProps { +export interface TokenDeleteDialogProps { confirmButtonState: ConfirmButtonTransitionState; open: boolean; onConfirm: () => void; @@ -13,7 +12,7 @@ export interface ServiceTokenDeleteDialogProps { name: string; } -const ServiceTokenDeleteDialog: React.FC = ({ +const TokenDeleteDialog: React.FC = ({ name, confirmButtonState, onClose, @@ -30,7 +29,7 @@ const ServiceTokenDeleteDialog: React.FC = ({ onConfirm={onConfirm} variant="delete" title={intl.formatMessage({ - defaultMessage: "Delete Service Account", + defaultMessage: "Delete Token", description: "dialog title" })} > @@ -47,5 +46,5 @@ const ServiceTokenDeleteDialog: React.FC = ({ ); }; -ServiceTokenDeleteDialog.displayName = "ServiceTokenDeleteDialog"; -export default ServiceTokenDeleteDialog; +TokenDeleteDialog.displayName = "TokenDeleteDialog"; +export default TokenDeleteDialog; diff --git a/src/apps/components/TokenDeleteDialog/index.ts b/src/apps/components/TokenDeleteDialog/index.ts new file mode 100644 index 000000000..536bbc3a4 --- /dev/null +++ b/src/apps/components/TokenDeleteDialog/index.ts @@ -0,0 +1,2 @@ +export * from "./TokenDeleteDialog"; +export { default } from "./TokenDeleteDialog"; diff --git a/src/apps/fixtures.ts b/src/apps/fixtures.ts new file mode 100644 index 000000000..eee4f6c2b --- /dev/null +++ b/src/apps/fixtures.ts @@ -0,0 +1,134 @@ +import { + AppTypeEnum, + JobStatusEnum, + PermissionEnum +} from "../types/globalTypes"; +import { App_app } from "./types/App"; +import { AppFetch_appFetchManifest_manifest } from "./types/AppFetch"; +import { AppsInstallations_appsInstallations } from "./types/AppsInstallations"; +import { AppsList_apps_edges } from "./types/AppsList"; + +export const appsList: AppsList_apps_edges[] = [ + { + __typename: "AppCountableEdge", + node: { + __typename: "App", + id: "QXBwOjE3Ng==", + isActive: true, + name: "app", + type: AppTypeEnum.THIRDPARTY + } + }, + { + __typename: "AppCountableEdge", + node: { + __typename: "App", + id: "QXBwOjE3Ng==", + isActive: false, + name: "app1", + type: AppTypeEnum.THIRDPARTY + } + } +]; + +export const customAppsList: AppsList_apps_edges[] = [ + { + __typename: "AppCountableEdge", + node: { + __typename: "App", + id: "QXBwOjE3Ng==", + isActive: true, + name: "app custom", + type: AppTypeEnum.LOCAL + } + } +]; + +export const appsInProgress: AppsInstallations_appsInstallations[] = [ + { + __typename: "AppInstallation", + appName: "app", + id: "QXBwSW5zdGFsbGF0aW9uOjk2", + manifestUrl: "http://localhost:3000/manifest", + message: "Failed to connect to app. Try later or contact with app support.", + status: JobStatusEnum.FAILED + }, + { + __typename: "AppInstallation", + appName: "app pending", + id: "QXBwSW5zdGFsbGF0aW9uOjk2", + manifestUrl: "http://localhost:3000/manifest", + message: "Pending.", + status: JobStatusEnum.PENDING + }, + { + __typename: "AppInstallation", + appName: "app success", + id: "QXBwSW5zdGFsbGF0aW9uOjk2", + manifestUrl: "http://localhost:3000/manifest", + message: "Success.", + status: JobStatusEnum.SUCCESS + } +]; + +export const appDetails: App_app = { + __typename: "App", + aboutApp: "Lorem ipsum", + accessToken: "token", + appUrl: "http://localhost:8888/app", + configurationUrl: "htpp://localhost:8888/configuration", + created: "2020-06-02T12:24:26.818138+00:00", + dataPrivacy: "Lorem ipsum", + dataPrivacyUrl: "http://localhost:8888/app-data-privacy", + homepageUrl: "http://localhost:8888/homepage", + id: "QXBwOjE4MQ==", + isActive: true, + metadata: [], + name: "app1", + permissions: [ + { + __typename: "Permission", + code: PermissionEnum.MANAGE_ORDERS, + name: "Manage orders." + }, + { + __typename: "Permission", + code: PermissionEnum.MANAGE_USERS, + name: "Manage customers." + } + ], + privateMetadata: [], + supportUrl: "http://localhost:8888/support", + tokens: [], + type: AppTypeEnum.THIRDPARTY, + version: "1.0.0", + webhooks: [] +}; + +export const installApp: AppFetch_appFetchManifest_manifest = { + __typename: "Manifest", + + about: "Lorem ipsum", + appUrl: null, + configurationUrl: null, + dataPrivacy: null, + dataPrivacyUrl: null, + homepageUrl: null, + identifier: "app", + name: "app", + permissions: [ + { + __typename: "Permission", + code: PermissionEnum.MANAGE_USERS, + name: "Manage users" + }, + { + __typename: "Permission", + code: PermissionEnum.MANAGE_ORDERS, + name: "Manage orders" + } + ], + supportUrl: null, + tokenTargetUrl: null, + version: "1.0" +}; diff --git a/src/apps/index.tsx b/src/apps/index.tsx new file mode 100644 index 000000000..79156da07 --- /dev/null +++ b/src/apps/index.tsx @@ -0,0 +1,118 @@ +import { sectionNames } from "@saleor/intl"; +import WebhooksRoutes from "@saleor/webhooks"; +import { parse as parseQs } from "qs"; +import React from "react"; +import { useIntl } from "react-intl"; +import { Route, RouteComponentProps, Switch } from "react-router-dom"; + +import { WindowTitle } from "../components/WindowTitle"; +import { + AppDetailsUrlQueryParams, + appInstallPath, + AppInstallUrlQueryParams, + AppListUrlQueryParams, + appPath, + appSettingsPath, + appsListPath, + customAppAddPath, + customAppPath, + CustomAppUrlQueryParams +} from "./urls"; +import AppDetailsView from "./views/AppDetails"; +import AppDetailsSettingsView from "./views/AppDetailsSettings"; +import AppInstallView from "./views/AppInstall"; +import AppsListView from "./views/AppsList"; +import CustomAppCreateView from "./views/CustomAppCreate"; +import CustomAppDetailsView from "./views/CustomAppDetails"; + +const AppDetails: React.FC> = ({ + match +}) => { + const qs = parseQs(location.search.substr(1)); + const params: AppDetailsUrlQueryParams = qs; + + return ( + + ); +}; + +const AppDetailsSettings: React.FC> = ({ + match +}) => ; + +const AppInstall: React.FC = props => { + const qs = parseQs(location.search.substr(1)); + const params: AppInstallUrlQueryParams = qs; + + return ; +}; + +interface CustomAppDetailsProps extends RouteComponentProps<{ id: string }> { + token: string; + onTokenClose: () => void; +} + +const CustomAppDetails: React.FC = ({ + match, + token, + onTokenClose +}) => { + const qs = parseQs(location.search.substr(1)); + const params: CustomAppUrlQueryParams = qs; + + return ( + + ); +}; + +const AppsList: React.FC = () => { + const qs = parseQs(location.search.substr(1)); + const params: AppListUrlQueryParams = qs; + + return ; +}; +const Component = () => { + const intl = useIntl(); + const [token, setToken] = React.useState(null); + + return ( + <> + + + + } + /> + + + + ( + setToken(null)} + /> + )} + /> + + + + + ); +}; + +export default Component; diff --git a/src/apps/mutations.ts b/src/apps/mutations.ts new file mode 100644 index 000000000..cc2f79976 --- /dev/null +++ b/src/apps/mutations.ts @@ -0,0 +1,269 @@ +import { appFragment } from "@saleor/fragments/apps"; +import { appErrorFragment } from "@saleor/fragments/errors"; +import { webhooksFragment } from "@saleor/fragments/webhooks"; +import makeMutation from "@saleor/hooks/makeMutation"; +import gql from "graphql-tag"; + +import { AppActivate, AppActivateVariables } from "./types/AppActivate"; +import { AppCreate, AppCreateVariables } from "./types/AppCreate"; +import { AppDeactivate, AppDeactivateVariables } from "./types/AppDeactivate"; +import { AppDelete, AppDeleteVariables } from "./types/AppDelete"; +import { + AppDeleteFailedInstallation, + AppDeleteFailedInstallationVariables +} from "./types/AppDeleteFailedInstallation"; +import { AppFetch, AppFetchVariables } from "./types/AppFetch"; +import { AppInstall, AppInstallVariables } from "./types/AppInstall"; +import { + AppRetryInstall, + AppRetryInstallVariables +} from "./types/AppRetryInstall"; +import { + AppTokenCreate, + AppTokenCreateVariables +} from "./types/AppTokenCreate"; +import { + AppTokenDelete, + AppTokenDeleteVariables +} from "./types/AppTokenDelete"; +import { AppUpdate, AppUpdateVariables } from "./types/AppUpdate"; + +export const appCreateMutation = gql` + ${appFragment} + ${webhooksFragment} + ${appErrorFragment} + mutation AppCreate($input: AppInput!) { + appCreate(input: $input) { + authToken + app { + ...AppFragment + } + errors: appErrors { + ...AppErrorFragment + } + } + } +`; + +export const appDeleteMutation = gql` + ${appFragment} + ${webhooksFragment} + ${appErrorFragment} + mutation AppDelete($id: ID!) { + appDelete(id: $id) { + app { + ...AppFragment + } + errors: appErrors { + ...AppErrorFragment + } + } + } +`; + +export const appDeleteFailedInstallationMutation = gql` + ${appErrorFragment} + mutation AppDeleteFailedInstallation($id: ID!) { + appDeleteFailedInstallation(id: $id) { + appInstallation { + id + status + appName + message + } + errors: appErrors { + ...AppErrorFragment + } + } + } +`; + +export const appFetchMutation = gql` + mutation AppFetch($manifestUrl: String!) { + appFetchManifest(manifestUrl: $manifestUrl) { + manifest { + identifier + version + about + name + appUrl + configurationUrl + tokenTargetUrl + dataPrivacy + dataPrivacyUrl + homepageUrl + supportUrl + permissions { + code + name + } + } + errors: appErrors { + ...AppErrorFragment + } + } + } +`; + +export const appInstallMutation = gql` + ${appErrorFragment} + mutation AppInstall($input: AppInstallInput!) { + appInstall(input: $input) { + appInstallation { + id + status + appName + manifestUrl + } + errors: appErrors { + ...AppErrorFragment + } + } + } +`; + +export const appRetryInstallMutation = gql` + ${appErrorFragment} + mutation AppRetryInstall($id: ID!) { + appRetryInstall(id: $id) { + appInstallation { + id + status + appName + manifestUrl + } + errors: appErrors { + ...AppErrorFragment + } + } + } +`; + +export const appActivateMutation = gql` + ${appErrorFragment} + mutation AppActivate($id: ID!) { + appActivate(id: $id) { + errors: appErrors { + ...AppErrorFragment + } + } + } +`; + +export const appDeactivateMutation = gql` + ${appErrorFragment} + mutation AppDeactivate($id: ID!) { + appDeactivate(id: $id) { + errors: appErrors { + ...AppErrorFragment + } + } + } +`; + +export const appUpdateMutation = gql` + ${appErrorFragment} + ${appFragment} + ${webhooksFragment} + mutation AppUpdate($id: ID!, $input: AppInput!) { + appUpdate(id: $id, input: $input) { + app { + ...AppFragment + permissions { + code + name + } + } + errors: appErrors { + ...AppErrorFragment + message + permissions + } + } + } +`; + +export const appTokenCreateMutation = gql` + ${appErrorFragment} + mutation AppTokenCreate($input: AppTokenInput!) { + appTokenCreate(input: $input) { + appToken { + name + authToken + id + } + authToken + errors: appErrors { + ...AppErrorFragment + } + } + } +`; + +export const appTokenDeleteMutation = gql` + ${appErrorFragment} + mutation AppTokenDelete($id: ID!) { + appTokenDelete(id: $id) { + appToken { + name + authToken + id + } + errors: appErrors { + ...AppErrorFragment + } + } + } +`; + +export const useAppCreateMutation = makeMutation( + appCreateMutation +); + +export const useAppDeleteMutation = makeMutation( + appDeleteMutation +); + +export const useAppDeleteFailedInstallationMutation = makeMutation< + AppDeleteFailedInstallation, + AppDeleteFailedInstallationVariables +>(appDeleteFailedInstallationMutation); + +export const useAppInstallMutation = makeMutation< + AppInstall, + AppInstallVariables +>(appInstallMutation); + +export const useAppRetryInstallMutation = makeMutation< + AppRetryInstall, + AppRetryInstallVariables +>(appRetryInstallMutation); + +export const useAppManifestFetchMutation = makeMutation< + AppFetch, + AppFetchVariables +>(appFetchMutation); + +export const useAppActivateMutation = makeMutation< + AppActivate, + AppActivateVariables +>(appActivateMutation); + +export const useAppDeactivateMutation = makeMutation< + AppDeactivate, + AppDeactivateVariables +>(appDeactivateMutation); + +export const useAppUpdateMutation = makeMutation( + appUpdateMutation +); + +export const useAppTokenCreateMutation = makeMutation< + AppTokenCreate, + AppTokenCreateVariables +>(appTokenCreateMutation); + +export const useAppTokenDeleteMutation = makeMutation< + AppTokenDelete, + AppTokenDeleteVariables +>(appTokenDeleteMutation); diff --git a/src/apps/queries.ts b/src/apps/queries.ts new file mode 100644 index 000000000..38fde017e --- /dev/null +++ b/src/apps/queries.ts @@ -0,0 +1,83 @@ +import { appFragment } from "@saleor/fragments/apps"; +import { webhooksFragment } from "@saleor/fragments/webhooks"; +import makeQuery from "@saleor/hooks/makeQuery"; +import gql from "graphql-tag"; + +import { App, AppVariables } from "./types/App"; +import { AppsInstallations } from "./types/AppsInstallations"; +import { AppsList, AppsListVariables } from "./types/AppsList"; + +const appsList = gql` + query AppsList( + $before: String + $after: String + $first: Int + $last: Int + $sort: AppSortingInput + $filter: AppFilterInput + ) { + apps( + before: $before + after: $after + first: $first + last: $last + sortBy: $sort + filter: $filter + ) { + pageInfo { + hasNextPage + hasPreviousPage + startCursor + endCursor + } + totalCount + edges { + node { + id + name + isActive + type + } + } + } + } +`; + +const appsInProgressList = gql` + query AppsInstallations { + appsInstallations { + status + message + appName + manifestUrl + id + } + } +`; + +const appDetails = gql` + ${appFragment} + ${webhooksFragment} + query App($id: ID!) { + app(id: $id) { + ...AppFragment + aboutApp + permissions { + code + name + } + dataPrivacy + dataPrivacyUrl + } + } +`; + +export const useAppsListQuery = makeQuery( + appsList +); + +export const useAppsInProgressListQuery = makeQuery( + appsInProgressList +); + +export const useAppDetails = makeQuery(appDetails); diff --git a/src/apps/styles.ts b/src/apps/styles.ts new file mode 100644 index 000000000..9d6e83224 --- /dev/null +++ b/src/apps/styles.ts @@ -0,0 +1,204 @@ +import { makeStyles } from "@material-ui/core/styles"; + +export const useStyles = makeStyles( + theme => ({ + [theme.breakpoints.up("lg")]: { + colName: { + "&&": { + width: "auto" + } + } + }, + alignRight: { + textAlign: "right" + }, + appContainer: { + marginBottom: theme.spacing(3) + }, + appContent: { + "&:last-child": { + padding: "0!important" + }, + padding: 0 + }, + appHeader: { + marginBottom: theme.spacing(3) + }, + appHeaderLinks: { + "& img": { + marginRight: theme.spacing(1) + }, + alignItems: "center", + display: "flex", + padding: theme.spacing(2, 0) + }, + appName: { + color: theme.palette.primary.main + }, + colAction: { + "&&": { + paddingRight: theme.spacing(1), + textAlign: "right" + }, + textAlign: "right" + }, + colInstallAction: { + "& > *": { + display: "inline-flex" + } + }, + colName: { + paddingLeft: 0, + width: theme.spacing(30) + }, + colSpinner: { + "& svg": { + textAlign: "right" + }, + paddingLeft: theme.spacing(3), + paddingRight: theme.spacing(2) + }, + customTooltip: { + "& > div": { + backgroundColor: theme.palette.error.main, + borderRadius: theme.spacing(1), + color: theme.palette.primary.contrastText, + padding: theme.spacing(2) + }, + padding: "0!important" + }, + error: { + "& svg": { + bottom: theme.spacing(0.2), + marginLeft: theme.spacing(0.6), + position: "relative" + }, + color: theme.palette.error.main, + margin: theme.spacing(0, 1, 0.7, 0) + }, + headerLinkContainer: { + "& span": { + fontWeight: 500 + }, + alignItems: "center", + display: "flex", + fontSize: theme.spacing(2), + fontWeight: 500, + lineHeight: 1.2, + marginRight: theme.spacing(3), + padding: 0, + textTransform: "none" + }, + hr: { + border: "none", + borderTop: `1px solid ${theme.palette.divider}`, + height: 0, + marginBottom: 0, + marginTop: 0, + width: "100%" + }, + installAppContainer: { + "& > div": { + position: "relative" + }, + "& img": { + position: "relative" + }, + display: "flex", + justifyContent: "space-between", + padding: theme.spacing(2, 0), + position: "relative", + width: theme.spacing(35) + }, + installCard: { + "&:before": { + backgroundColor: theme.palette.divider, + content: "''", + height: 2, + position: "absolute", + top: "50%", + transform: "translateY(-50%)", + width: theme.spacing(30) + }, + display: "flex", + justifyContent: "center", + position: "relative" + }, + installIcon: { + alignItems: "center", + backgroundColor: theme.palette.divider, + border: `1px solid ${theme.palette.divider}`, + borderRadius: "50%", + display: "flex", + height: theme.spacing(9), + justifyContent: "center", + overflow: "hidden", + width: theme.spacing(9) + }, + installPermissionTitle: { + fontWeight: 500 + }, + installPrivacyText: { + "& a": { + color: theme.palette.primary.main, + textDecoration: "none" + }, + color: theme.palette.text.hint + }, + installSaleorIcon: { + backgroundColor: theme.palette.secondary.main, + border: "none" + }, + installSpacer: { + margin: theme.spacing(2, 0) + }, + installText: { + color: theme.palette.primary.contrastText + }, + linkContainer: { + fontWeight: 500, + marginTop: theme.spacing(1.5) + }, + marketplaceContent: { + "& button": { + marginTop: theme.spacing(1) + }, + "&:last-child": { + padding: theme.spacing(2, 3, 2, 3) + }, + padding: theme.spacing(1) + }, + permissionsContainer: { + "& li": { + "&:last-child": { + marginBottom: 0 + }, + marginBottom: theme.spacing(1) + }, + paddingLeft: theme.spacing(2) + }, + retryBtnCol: { + paddingRight: theme.spacing(1), + width: theme.spacing(14) + }, + statusWrapper: { + display: "inline-block", + marginLeft: theme.spacing(2.5) + }, + table: { + tableLayout: "fixed" + }, + tableRow: { + cursor: "pointer" + }, + text: { + color: theme.palette.text.secondary + }, + title: { + flex: 1, + fontWeight: 500, + lineHeight: 1 + } + }), + { name: "AppList" } +); diff --git a/src/apps/types/App.ts b/src/apps/types/App.ts new file mode 100644 index 000000000..833e8d218 --- /dev/null +++ b/src/apps/types/App.ts @@ -0,0 +1,79 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { AppTypeEnum, PermissionEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL query operation: App +// ==================================================== + +export interface App_app_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface App_app_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface App_app_tokens { + __typename: "AppToken"; + authToken: string | null; + id: string; + name: string | null; +} + +export interface App_app_webhooks_app { + __typename: "App"; + id: string; + name: string | null; +} + +export interface App_app_webhooks { + __typename: "Webhook"; + id: string; + name: string; + isActive: boolean; + app: App_app_webhooks_app; +} + +export interface App_app_permissions { + __typename: "Permission"; + code: PermissionEnum; + name: string; +} + +export interface App_app { + __typename: "App"; + id: string; + name: string | null; + created: any | null; + isActive: boolean | null; + type: AppTypeEnum | null; + homepageUrl: string | null; + appUrl: string | null; + configurationUrl: string | null; + supportUrl: string | null; + version: string | null; + accessToken: string | null; + privateMetadata: (App_app_privateMetadata | null)[]; + metadata: (App_app_metadata | null)[]; + tokens: (App_app_tokens | null)[] | null; + webhooks: (App_app_webhooks | null)[] | null; + aboutApp: string | null; + permissions: (App_app_permissions | null)[] | null; + dataPrivacy: string | null; + dataPrivacyUrl: string | null; +} + +export interface App { + app: App_app | null; +} + +export interface AppVariables { + id: string; +} diff --git a/src/apps/types/AppActivate.ts b/src/apps/types/AppActivate.ts new file mode 100644 index 000000000..d4bae0f7a --- /dev/null +++ b/src/apps/types/AppActivate.ts @@ -0,0 +1,30 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { AppErrorCode, PermissionEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: AppActivate +// ==================================================== + +export interface AppActivate_appActivate_errors { + __typename: "AppError"; + field: string | null; + message: string | null; + code: AppErrorCode; + permissions: PermissionEnum[] | null; +} + +export interface AppActivate_appActivate { + __typename: "AppActivate"; + errors: AppActivate_appActivate_errors[]; +} + +export interface AppActivate { + appActivate: AppActivate_appActivate | null; +} + +export interface AppActivateVariables { + id: string; +} diff --git a/src/apps/types/AppCreate.ts b/src/apps/types/AppCreate.ts new file mode 100644 index 000000000..a3cb7cb0f --- /dev/null +++ b/src/apps/types/AppCreate.ts @@ -0,0 +1,84 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { AppInput, AppTypeEnum, AppErrorCode, PermissionEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: AppCreate +// ==================================================== + +export interface AppCreate_appCreate_app_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface AppCreate_appCreate_app_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface AppCreate_appCreate_app_tokens { + __typename: "AppToken"; + authToken: string | null; + id: string; + name: string | null; +} + +export interface AppCreate_appCreate_app_webhooks_app { + __typename: "App"; + id: string; + name: string | null; +} + +export interface AppCreate_appCreate_app_webhooks { + __typename: "Webhook"; + id: string; + name: string; + isActive: boolean; + app: AppCreate_appCreate_app_webhooks_app; +} + +export interface AppCreate_appCreate_app { + __typename: "App"; + id: string; + name: string | null; + created: any | null; + isActive: boolean | null; + type: AppTypeEnum | null; + homepageUrl: string | null; + appUrl: string | null; + configurationUrl: string | null; + supportUrl: string | null; + version: string | null; + accessToken: string | null; + privateMetadata: (AppCreate_appCreate_app_privateMetadata | null)[]; + metadata: (AppCreate_appCreate_app_metadata | null)[]; + tokens: (AppCreate_appCreate_app_tokens | null)[] | null; + webhooks: (AppCreate_appCreate_app_webhooks | null)[] | null; +} + +export interface AppCreate_appCreate_errors { + __typename: "AppError"; + field: string | null; + message: string | null; + code: AppErrorCode; + permissions: PermissionEnum[] | null; +} + +export interface AppCreate_appCreate { + __typename: "AppCreate"; + authToken: string | null; + app: AppCreate_appCreate_app | null; + errors: AppCreate_appCreate_errors[]; +} + +export interface AppCreate { + appCreate: AppCreate_appCreate | null; +} + +export interface AppCreateVariables { + input: AppInput; +} diff --git a/src/apps/types/AppDeactivate.ts b/src/apps/types/AppDeactivate.ts new file mode 100644 index 000000000..f391ecb2a --- /dev/null +++ b/src/apps/types/AppDeactivate.ts @@ -0,0 +1,30 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { AppErrorCode, PermissionEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: AppDeactivate +// ==================================================== + +export interface AppDeactivate_appDeactivate_errors { + __typename: "AppError"; + field: string | null; + message: string | null; + code: AppErrorCode; + permissions: PermissionEnum[] | null; +} + +export interface AppDeactivate_appDeactivate { + __typename: "AppDeactivate"; + errors: AppDeactivate_appDeactivate_errors[]; +} + +export interface AppDeactivate { + appDeactivate: AppDeactivate_appDeactivate | null; +} + +export interface AppDeactivateVariables { + id: string; +} diff --git a/src/apps/types/AppDelete.ts b/src/apps/types/AppDelete.ts new file mode 100644 index 000000000..af2a28456 --- /dev/null +++ b/src/apps/types/AppDelete.ts @@ -0,0 +1,83 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { AppTypeEnum, AppErrorCode, PermissionEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: AppDelete +// ==================================================== + +export interface AppDelete_appDelete_app_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface AppDelete_appDelete_app_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface AppDelete_appDelete_app_tokens { + __typename: "AppToken"; + authToken: string | null; + id: string; + name: string | null; +} + +export interface AppDelete_appDelete_app_webhooks_app { + __typename: "App"; + id: string; + name: string | null; +} + +export interface AppDelete_appDelete_app_webhooks { + __typename: "Webhook"; + id: string; + name: string; + isActive: boolean; + app: AppDelete_appDelete_app_webhooks_app; +} + +export interface AppDelete_appDelete_app { + __typename: "App"; + id: string; + name: string | null; + created: any | null; + isActive: boolean | null; + type: AppTypeEnum | null; + homepageUrl: string | null; + appUrl: string | null; + configurationUrl: string | null; + supportUrl: string | null; + version: string | null; + accessToken: string | null; + privateMetadata: (AppDelete_appDelete_app_privateMetadata | null)[]; + metadata: (AppDelete_appDelete_app_metadata | null)[]; + tokens: (AppDelete_appDelete_app_tokens | null)[] | null; + webhooks: (AppDelete_appDelete_app_webhooks | null)[] | null; +} + +export interface AppDelete_appDelete_errors { + __typename: "AppError"; + field: string | null; + message: string | null; + code: AppErrorCode; + permissions: PermissionEnum[] | null; +} + +export interface AppDelete_appDelete { + __typename: "AppDelete"; + app: AppDelete_appDelete_app | null; + errors: AppDelete_appDelete_errors[]; +} + +export interface AppDelete { + appDelete: AppDelete_appDelete | null; +} + +export interface AppDeleteVariables { + id: string; +} diff --git a/src/apps/types/AppDeleteFailedInstallation.ts b/src/apps/types/AppDeleteFailedInstallation.ts new file mode 100644 index 000000000..70dd4860f --- /dev/null +++ b/src/apps/types/AppDeleteFailedInstallation.ts @@ -0,0 +1,39 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { JobStatusEnum, AppErrorCode, PermissionEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: AppDeleteFailedInstallation +// ==================================================== + +export interface AppDeleteFailedInstallation_appDeleteFailedInstallation_appInstallation { + __typename: "AppInstallation"; + id: string; + status: JobStatusEnum; + appName: string; + message: string | null; +} + +export interface AppDeleteFailedInstallation_appDeleteFailedInstallation_errors { + __typename: "AppError"; + field: string | null; + message: string | null; + code: AppErrorCode; + permissions: PermissionEnum[] | null; +} + +export interface AppDeleteFailedInstallation_appDeleteFailedInstallation { + __typename: "AppDeleteFailedInstallation"; + appInstallation: AppDeleteFailedInstallation_appDeleteFailedInstallation_appInstallation | null; + errors: AppDeleteFailedInstallation_appDeleteFailedInstallation_errors[]; +} + +export interface AppDeleteFailedInstallation { + appDeleteFailedInstallation: AppDeleteFailedInstallation_appDeleteFailedInstallation | null; +} + +export interface AppDeleteFailedInstallationVariables { + id: string; +} diff --git a/src/apps/types/AppErrorFragment.ts b/src/apps/types/AppErrorFragment.ts new file mode 100644 index 000000000..2dca654b1 --- /dev/null +++ b/src/apps/types/AppErrorFragment.ts @@ -0,0 +1,17 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { AppErrorCode, PermissionEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL fragment: AppErrorFragment +// ==================================================== + +export interface AppErrorFragment { + __typename: "AppError"; + field: string | null; + message: string | null; + code: AppErrorCode; + permissions: PermissionEnum[] | null; +} diff --git a/src/apps/types/AppFetch.ts b/src/apps/types/AppFetch.ts new file mode 100644 index 000000000..3b09b98c4 --- /dev/null +++ b/src/apps/types/AppFetch.ts @@ -0,0 +1,53 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { PermissionEnum, AppErrorCode } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: AppFetch +// ==================================================== + +export interface AppFetch_appFetchManifest_manifest_permissions { + __typename: "Permission"; + code: PermissionEnum; + name: string; +} + +export interface AppFetch_appFetchManifest_manifest { + __typename: "Manifest"; + identifier: string; + version: string; + about: string | null; + name: string; + appUrl: string | null; + configurationUrl: string | null; + tokenTargetUrl: string | null; + dataPrivacy: string | null; + dataPrivacyUrl: string | null; + homepageUrl: string | null; + supportUrl: string | null; + permissions: (AppFetch_appFetchManifest_manifest_permissions | null)[] | null; +} + +export interface AppFetch_appFetchManifest_errors { + __typename: "AppError"; + field: string | null; + message: string | null; + code: AppErrorCode; + permissions: PermissionEnum[] | null; +} + +export interface AppFetch_appFetchManifest { + __typename: "AppFetchManifest"; + manifest: AppFetch_appFetchManifest_manifest | null; + errors: AppFetch_appFetchManifest_errors[]; +} + +export interface AppFetch { + appFetchManifest: AppFetch_appFetchManifest | null; +} + +export interface AppFetchVariables { + manifestUrl: string; +} diff --git a/src/apps/types/AppFragment.ts b/src/apps/types/AppFragment.ts new file mode 100644 index 000000000..ef2f53128 --- /dev/null +++ b/src/apps/types/AppFragment.ts @@ -0,0 +1,61 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { AppTypeEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL fragment: AppFragment +// ==================================================== + +export interface AppFragment_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface AppFragment_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface AppFragment_tokens { + __typename: "AppToken"; + authToken: string | null; + id: string; + name: string | null; +} + +export interface AppFragment_webhooks_app { + __typename: "App"; + id: string; + name: string | null; +} + +export interface AppFragment_webhooks { + __typename: "Webhook"; + id: string; + name: string; + isActive: boolean; + app: AppFragment_webhooks_app; +} + +export interface AppFragment { + __typename: "App"; + id: string; + name: string | null; + created: any | null; + isActive: boolean | null; + type: AppTypeEnum | null; + homepageUrl: string | null; + appUrl: string | null; + configurationUrl: string | null; + supportUrl: string | null; + version: string | null; + accessToken: string | null; + privateMetadata: (AppFragment_privateMetadata | null)[]; + metadata: (AppFragment_metadata | null)[]; + tokens: (AppFragment_tokens | null)[] | null; + webhooks: (AppFragment_webhooks | null)[] | null; +} diff --git a/src/apps/types/AppInstall.ts b/src/apps/types/AppInstall.ts new file mode 100644 index 000000000..4952ab004 --- /dev/null +++ b/src/apps/types/AppInstall.ts @@ -0,0 +1,39 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { AppInstallInput, JobStatusEnum, AppErrorCode, PermissionEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: AppInstall +// ==================================================== + +export interface AppInstall_appInstall_appInstallation { + __typename: "AppInstallation"; + id: string; + status: JobStatusEnum; + appName: string; + manifestUrl: string; +} + +export interface AppInstall_appInstall_errors { + __typename: "AppError"; + field: string | null; + message: string | null; + code: AppErrorCode; + permissions: PermissionEnum[] | null; +} + +export interface AppInstall_appInstall { + __typename: "AppInstall"; + appInstallation: AppInstall_appInstall_appInstallation | null; + errors: AppInstall_appInstall_errors[]; +} + +export interface AppInstall { + appInstall: AppInstall_appInstall | null; +} + +export interface AppInstallVariables { + input: AppInstallInput; +} diff --git a/src/apps/types/AppRetryInstall.ts b/src/apps/types/AppRetryInstall.ts new file mode 100644 index 000000000..31b8dd049 --- /dev/null +++ b/src/apps/types/AppRetryInstall.ts @@ -0,0 +1,39 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { JobStatusEnum, AppErrorCode, PermissionEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: AppRetryInstall +// ==================================================== + +export interface AppRetryInstall_appRetryInstall_appInstallation { + __typename: "AppInstallation"; + id: string; + status: JobStatusEnum; + appName: string; + manifestUrl: string; +} + +export interface AppRetryInstall_appRetryInstall_errors { + __typename: "AppError"; + field: string | null; + message: string | null; + code: AppErrorCode; + permissions: PermissionEnum[] | null; +} + +export interface AppRetryInstall_appRetryInstall { + __typename: "AppRetryInstall"; + appInstallation: AppRetryInstall_appRetryInstall_appInstallation | null; + errors: AppRetryInstall_appRetryInstall_errors[]; +} + +export interface AppRetryInstall { + appRetryInstall: AppRetryInstall_appRetryInstall | null; +} + +export interface AppRetryInstallVariables { + id: string; +} diff --git a/src/apps/types/AppTokenCreate.ts b/src/apps/types/AppTokenCreate.ts new file mode 100644 index 000000000..008e74772 --- /dev/null +++ b/src/apps/types/AppTokenCreate.ts @@ -0,0 +1,39 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { AppTokenInput, AppErrorCode, PermissionEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: AppTokenCreate +// ==================================================== + +export interface AppTokenCreate_appTokenCreate_appToken { + __typename: "AppToken"; + name: string | null; + authToken: string | null; + id: string; +} + +export interface AppTokenCreate_appTokenCreate_errors { + __typename: "AppError"; + field: string | null; + message: string | null; + code: AppErrorCode; + permissions: PermissionEnum[] | null; +} + +export interface AppTokenCreate_appTokenCreate { + __typename: "AppTokenCreate"; + appToken: AppTokenCreate_appTokenCreate_appToken | null; + authToken: string | null; + errors: AppTokenCreate_appTokenCreate_errors[]; +} + +export interface AppTokenCreate { + appTokenCreate: AppTokenCreate_appTokenCreate | null; +} + +export interface AppTokenCreateVariables { + input: AppTokenInput; +} diff --git a/src/apps/types/AppTokenDelete.ts b/src/apps/types/AppTokenDelete.ts new file mode 100644 index 000000000..53bc8e02b --- /dev/null +++ b/src/apps/types/AppTokenDelete.ts @@ -0,0 +1,38 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { AppErrorCode, PermissionEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: AppTokenDelete +// ==================================================== + +export interface AppTokenDelete_appTokenDelete_appToken { + __typename: "AppToken"; + name: string | null; + authToken: string | null; + id: string; +} + +export interface AppTokenDelete_appTokenDelete_errors { + __typename: "AppError"; + field: string | null; + message: string | null; + code: AppErrorCode; + permissions: PermissionEnum[] | null; +} + +export interface AppTokenDelete_appTokenDelete { + __typename: "AppTokenDelete"; + appToken: AppTokenDelete_appTokenDelete_appToken | null; + errors: AppTokenDelete_appTokenDelete_errors[]; +} + +export interface AppTokenDelete { + appTokenDelete: AppTokenDelete_appTokenDelete | null; +} + +export interface AppTokenDeleteVariables { + id: string; +} diff --git a/src/apps/types/AppUpdate.ts b/src/apps/types/AppUpdate.ts new file mode 100644 index 000000000..a27a4f3c3 --- /dev/null +++ b/src/apps/types/AppUpdate.ts @@ -0,0 +1,91 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { AppInput, AppTypeEnum, PermissionEnum, AppErrorCode } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: AppUpdate +// ==================================================== + +export interface AppUpdate_appUpdate_app_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface AppUpdate_appUpdate_app_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface AppUpdate_appUpdate_app_tokens { + __typename: "AppToken"; + authToken: string | null; + id: string; + name: string | null; +} + +export interface AppUpdate_appUpdate_app_webhooks_app { + __typename: "App"; + id: string; + name: string | null; +} + +export interface AppUpdate_appUpdate_app_webhooks { + __typename: "Webhook"; + id: string; + name: string; + isActive: boolean; + app: AppUpdate_appUpdate_app_webhooks_app; +} + +export interface AppUpdate_appUpdate_app_permissions { + __typename: "Permission"; + code: PermissionEnum; + name: string; +} + +export interface AppUpdate_appUpdate_app { + __typename: "App"; + id: string; + name: string | null; + created: any | null; + isActive: boolean | null; + type: AppTypeEnum | null; + homepageUrl: string | null; + appUrl: string | null; + configurationUrl: string | null; + supportUrl: string | null; + version: string | null; + accessToken: string | null; + privateMetadata: (AppUpdate_appUpdate_app_privateMetadata | null)[]; + metadata: (AppUpdate_appUpdate_app_metadata | null)[]; + tokens: (AppUpdate_appUpdate_app_tokens | null)[] | null; + webhooks: (AppUpdate_appUpdate_app_webhooks | null)[] | null; + permissions: (AppUpdate_appUpdate_app_permissions | null)[] | null; +} + +export interface AppUpdate_appUpdate_errors { + __typename: "AppError"; + field: string | null; + message: string | null; + code: AppErrorCode; + permissions: PermissionEnum[] | null; +} + +export interface AppUpdate_appUpdate { + __typename: "AppUpdate"; + app: AppUpdate_appUpdate_app | null; + errors: AppUpdate_appUpdate_errors[]; +} + +export interface AppUpdate { + appUpdate: AppUpdate_appUpdate | null; +} + +export interface AppUpdateVariables { + id: string; + input: AppInput; +} diff --git a/src/apps/types/AppsInstallations.ts b/src/apps/types/AppsInstallations.ts new file mode 100644 index 000000000..93c0aff2d --- /dev/null +++ b/src/apps/types/AppsInstallations.ts @@ -0,0 +1,22 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { JobStatusEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL query operation: AppsInstallations +// ==================================================== + +export interface AppsInstallations_appsInstallations { + __typename: "AppInstallation"; + status: JobStatusEnum; + message: string | null; + appName: string; + manifestUrl: string; + id: string; +} + +export interface AppsInstallations { + appsInstallations: AppsInstallations_appsInstallations[]; +} diff --git a/src/apps/types/AppsList.ts b/src/apps/types/AppsList.ts new file mode 100644 index 000000000..00a127bae --- /dev/null +++ b/src/apps/types/AppsList.ts @@ -0,0 +1,50 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { AppSortingInput, AppFilterInput, AppTypeEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL query operation: AppsList +// ==================================================== + +export interface AppsList_apps_pageInfo { + __typename: "PageInfo"; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string | null; + endCursor: string | null; +} + +export interface AppsList_apps_edges_node { + __typename: "App"; + id: string; + name: string | null; + isActive: boolean | null; + type: AppTypeEnum | null; +} + +export interface AppsList_apps_edges { + __typename: "AppCountableEdge"; + node: AppsList_apps_edges_node; +} + +export interface AppsList_apps { + __typename: "AppCountableConnection"; + pageInfo: AppsList_apps_pageInfo; + totalCount: number | null; + edges: AppsList_apps_edges[]; +} + +export interface AppsList { + apps: AppsList_apps | null; +} + +export interface AppsListVariables { + before?: string | null; + after?: string | null; + first?: number | null; + last?: number | null; + sort?: AppSortingInput | null; + filter?: AppFilterInput | null; +} diff --git a/src/apps/urls.ts b/src/apps/urls.ts new file mode 100644 index 000000000..7e5613dbe --- /dev/null +++ b/src/apps/urls.ts @@ -0,0 +1,59 @@ +import { stringify as stringifyQs } from "qs"; +import urlJoin from "url-join"; + +import { ActiveTab, Dialog, Pagination, SingleAction } from "../types"; + +export const MANIFEST_ATTR = "manifestUrl"; + +export type AppListUrlDialog = "remove" | "remove-app" | "remove-custom-app"; + +export type AppDetailsUrlDialog = "app-activate" | "app-deactivate"; + +export type AppListUrlQueryParams = ActiveTab & + Dialog & + SingleAction & + Pagination; + +export type AppDetailsUrlQueryParams = Dialog & + SingleAction; + +export type AppInstallUrlQueryParams = Partial<{ [MANIFEST_ATTR]: string }>; + +export enum AppListUrlSortField { + name = "name", + active = "active" +} + +export type CustomAppUrlDialog = + | "create-token" + | "remove-webhook" + | "remove-token"; +export type CustomAppUrlQueryParams = Dialog & SingleAction; + +export const appsSection = "/apps/"; +export const appsListPath = appsSection; + +export const customAppListPath = "/apps/custom/"; + +export const appPath = (id: string) => urlJoin(appsSection, id); +export const appSettingsPath = (id: string) => + urlJoin(appsSection, id, "settings"); +export const customAppPath = (id: string) => urlJoin(customAppListPath, id); +export const appInstallPath = urlJoin(appsSection, "install"); +export const appInstallUrl = appInstallPath; + +export const appUrl = (id: string, params?: AppDetailsUrlQueryParams) => + appPath(encodeURIComponent(id)) + "?" + stringifyQs(params); + +export const appSettingsUrl = (id: string, params?: AppDetailsUrlQueryParams) => + urlJoin(appPath(encodeURIComponent(id)), "settings") + + "?" + + stringifyQs(params); + +export const customAppUrl = (id: string, params?: CustomAppUrlQueryParams) => + customAppPath(encodeURIComponent(id)) + "?" + stringifyQs(params); +export const customAppAddPath = urlJoin(customAppListPath, "add"); +export const customAppAddUrl = customAppAddPath; + +export const appsListUrl = (params?: AppListUrlQueryParams) => + appsListPath + "?" + stringifyQs(params); diff --git a/src/apps/views/AppDetails/AppDetails.tsx b/src/apps/views/AppDetails/AppDetails.tsx new file mode 100644 index 000000000..6ab1138ec --- /dev/null +++ b/src/apps/views/AppDetails/AppDetails.tsx @@ -0,0 +1,125 @@ +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import getAppErrorMessage from "@saleor/utils/errors/app"; +import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; +import React from "react"; +import { useIntl } from "react-intl"; + +import AppActivateDialog from "../../components/AppActivateDialog"; +import AppDeactivateDialog from "../../components/AppDeactivateDialog"; +import AppDetailsPage from "../../components/AppDetailsPage"; +import { + useAppActivateMutation, + useAppDeactivateMutation +} from "../../mutations"; +import { useAppDetails } from "../../queries"; +import { + AppDetailsUrlDialog, + AppDetailsUrlQueryParams, + appSettingsUrl, + appsListPath, + appUrl +} from "../../urls"; + +interface AppDetailsProps { + id: string; + params: AppDetailsUrlQueryParams; +} + +export const AppDetails: React.FC = ({ id, params }) => { + const { data, loading, refetch } = useAppDetails({ + displayLoader: true, + variables: { id } + }); + const navigate = useNavigator(); + const notify = useNotifier(); + const intl = useIntl(); + const mutationOpts = { variables: { id } }; + const [activateApp, activateAppResult] = useAppActivateMutation({ + onCompleted: data => { + const errors = data?.appActivate?.errors; + if (errors?.length === 0) { + notify({ + status: "success", + text: intl.formatMessage({ + defaultMessage: "App activated", + description: "snackbar text" + }) + }); + refetch(); + closeModal(); + } else { + errors.forEach(error => + notify({ + status: "error", + text: getAppErrorMessage(error, intl) + }) + ); + } + } + }); + const [deactivateApp, deactivateAppResult] = useAppDeactivateMutation({ + onCompleted: data => { + const errors = data?.appDeactivate?.errors; + if (errors.length === 0) { + notify({ + status: "success", + text: intl.formatMessage({ + defaultMessage: "App deactivated", + description: "snackbar text" + }) + }); + refetch(); + closeModal(); + } else { + errors.forEach(error => + notify({ + status: "error", + text: getAppErrorMessage(error, intl) + }) + ); + } + } + }); + + const [openModal, closeModal] = createDialogActionHandlers< + AppDetailsUrlDialog, + AppDetailsUrlQueryParams + >(navigate, params => appUrl(id, params), params); + + const handleActivateConfirm = () => { + activateApp(mutationOpts); + }; + const handleDeactivateConfirm = () => { + deactivateApp(mutationOpts); + }; + + return ( + <> + + + navigate(appSettingsUrl(id))} + onAppActivateOpen={() => openModal("app-activate")} + onAppDeactivateOpen={() => openModal("app-deactivate")} + onBack={() => navigate(appsListPath)} + /> + + ); +}; + +export default AppDetails; diff --git a/src/apps/views/AppDetails/index.ts b/src/apps/views/AppDetails/index.ts new file mode 100644 index 000000000..d320b2453 --- /dev/null +++ b/src/apps/views/AppDetails/index.ts @@ -0,0 +1,2 @@ +export * from "./AppDetails"; +export { default } from "./AppDetails"; diff --git a/src/apps/views/AppDetailsSettings/AppDetailsSettings.tsx b/src/apps/views/AppDetailsSettings/AppDetailsSettings.tsx new file mode 100644 index 000000000..4044821a3 --- /dev/null +++ b/src/apps/views/AppDetailsSettings/AppDetailsSettings.tsx @@ -0,0 +1,46 @@ +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import useShop from "@saleor/hooks/useShop"; +import React from "react"; +import { useIntl } from "react-intl"; + +import AppDetailsSettingsPage from "../../components/AppDetailsSettingsPage"; +import { useAppDetails } from "../../queries"; +import { appsListPath, appUrl } from "../../urls"; + +interface AppDetailsSetttingsProps { + id: string; +} + +export const AppDetailsSettings: React.FC = ({ + id +}) => { + const shop = useShop(); + const { data } = useAppDetails({ + displayLoader: true, + variables: { id } + }); + const navigate = useNavigator(); + const notify = useNotifier(); + const intl = useIntl(); + + return ( + navigate(appUrl(id))} + onBack={() => navigate(appsListPath)} + onError={() => + notify({ + status: "error", + text: intl.formatMessage({ + defaultMessage: "Failed to fetch app settings", + description: "app settings error" + }) + }) + } + /> + ); +}; + +export default AppDetailsSettings; diff --git a/src/apps/views/AppDetailsSettings/index.ts b/src/apps/views/AppDetailsSettings/index.ts new file mode 100644 index 000000000..69a4896c3 --- /dev/null +++ b/src/apps/views/AppDetailsSettings/index.ts @@ -0,0 +1,2 @@ +export * from "./AppDetailsSettings"; +export { default } from "./AppDetailsSettings"; diff --git a/src/apps/views/AppInstall/AppInstall.tsx b/src/apps/views/AppInstall/AppInstall.tsx new file mode 100644 index 000000000..7f2042fb4 --- /dev/null +++ b/src/apps/views/AppInstall/AppInstall.tsx @@ -0,0 +1,112 @@ +import { WindowTitle } from "@saleor/components/WindowTitle"; +import useLocalStorage from "@saleor/hooks/useLocalStorage"; +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import getAppErrorMessage from "@saleor/utils/errors/app"; +import React, { useEffect } from "react"; +import { useIntl } from "react-intl"; +import { RouteComponentProps } from "react-router-dom"; + +import AppInstallErrorPage from "../../components/AppInstallErrorPage"; +import AppInstallPage from "../../components/AppInstallPage"; +import { + useAppInstallMutation, + useAppManifestFetchMutation +} from "../../mutations"; +import { + AppInstallUrlQueryParams, + appsListUrl, + MANIFEST_ATTR +} from "../../urls"; + +interface InstallAppCreateProps extends RouteComponentProps { + params: AppInstallUrlQueryParams; +} +export const InstallAppCreate: React.FC = ({ + params +}) => { + const [, setActiveInstallations] = useLocalStorage("activeInstallations", []); + const navigate = useNavigator(); + const notify = useNotifier(); + const intl = useIntl(); + const manifestUrl = params[MANIFEST_ATTR]; + + const [fetchManifest, fetchManifestOpts] = useAppManifestFetchMutation({ + onCompleted: data => { + if (data.appFetchManifest.errors.length) { + data.appFetchManifest.errors.forEach(error => { + notify({ + status: "error", + text: getAppErrorMessage(error, intl) + }); + }); + } + } + }); + const [installApp] = useAppInstallMutation({ + onCompleted: data => { + const installationData = data.appInstall.appInstallation; + if (data.appInstall.errors.length === 0) { + setActiveInstallations(activeInstallations => [ + ...activeInstallations, + { id: installationData.id, name: installationData.appName } + ]); + navigateToAppsList(); + } else { + data.appInstall.errors.forEach(error => { + notify({ + status: "error", + text: getAppErrorMessage(error, intl) + }); + }); + } + } + }); + + const navigateToAppsList = () => navigate(appsListUrl()); + + const handleSubmit = () => { + const manifest = fetchManifestOpts?.data?.appFetchManifest?.manifest; + installApp({ + variables: { + input: { + appName: manifest?.name, + manifestUrl, + permissions: manifest?.permissions.map(permission => permission.code) + } + } + }); + }; + + useEffect(() => { + if (manifestUrl) { + fetchManifest({ variables: { manifestUrl } }); + } else { + navigate(appsListUrl()); + } + }, []); + + return ( + <> + + {!!fetchManifestOpts.data?.appFetchManifest?.errors?.length || + !!fetchManifestOpts.error ? ( + navigate("/")} /> + ) : ( + + )} + + ); +}; + +export default InstallAppCreate; diff --git a/src/apps/views/AppInstall/index.ts b/src/apps/views/AppInstall/index.ts new file mode 100644 index 000000000..bbf79f50b --- /dev/null +++ b/src/apps/views/AppInstall/index.ts @@ -0,0 +1,2 @@ +export * from "./AppInstall"; +export { default } from "./AppInstall"; diff --git a/src/apps/views/AppsList/AppsList.tsx b/src/apps/views/AppsList/AppsList.tsx new file mode 100644 index 000000000..40c91f855 --- /dev/null +++ b/src/apps/views/AppsList/AppsList.tsx @@ -0,0 +1,341 @@ +import useListSettings from "@saleor/hooks/useListSettings"; +import useLocalStorage from "@saleor/hooks/useLocalStorage"; +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import usePaginator, { + createPaginationState +} from "@saleor/hooks/usePaginator"; +import { ListViews } from "@saleor/types"; +import getAppErrorMessage from "@saleor/utils/errors/app"; +import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; +import React, { useEffect, useRef } from "react"; +import { useIntl } from "react-intl"; + +import { + AppSortField, + AppTypeEnum, + JobStatusEnum, + OrderDirection +} from "../../../types/globalTypes"; +import AppDeleteDialog from "../../components/AppDeleteDialog"; +import AppInProgressDeleteDialog from "../../components/AppInProgressDeleteDialog"; +import AppsListPage from "../../components/AppsListPage"; +import { + useAppDeleteFailedInstallationMutation, + useAppDeleteMutation, + useAppRetryInstallMutation +} from "../../mutations"; +import { useAppsInProgressListQuery, useAppsListQuery } from "../../queries"; +import { AppDelete } from "../../types/AppDelete"; +import { AppDeleteFailedInstallation } from "../../types/AppDeleteFailedInstallation"; +import { AppsInstallations_appsInstallations } from "../../types/AppsInstallations"; +import { AppsList_apps_edges } from "../../types/AppsList"; +import { + AppListUrlDialog, + AppListUrlQueryParams, + appSettingsUrl, + appsListUrl, + appUrl, + customAppAddUrl, + customAppUrl +} from "../../urls"; + +const getCurrentAppName = (id: string, collection?: AppsList_apps_edges[]) => + collection?.find(edge => edge.node.id === id)?.node?.name; + +const getAppInProgressName = ( + id: string, + collection?: AppsInstallations_appsInstallations[] +) => collection?.find(app => app.id === id)?.appName; +interface AppsListProps { + params: AppListUrlQueryParams; +} + +export const AppsList: React.FC = ({ params }) => { + const { action } = params; + const [activeInstallations, setActiveInstallations] = useLocalStorage( + "activeInstallations", + [] + ); + const notify = useNotifier(); + const intl = useIntl(); + const navigate = useNavigator(); + const { updateListSettings, settings } = useListSettings(ListViews.APPS_LIST); + const paginate = usePaginator(); + const paginationState = createPaginationState(settings.rowNumber, params); + const queryVariables = { + sort: { + direction: OrderDirection.DESC, + field: AppSortField.CREATION_DATE + } + }; + const intervalId = useRef(null); + + const removeInstallation = (id: string) => + setActiveInstallations(installations => + installations.filter(item => item.id !== id) + ); + + const { + data: appsInProgressData, + loading: loadingAppsInProgress, + refetch: appsInProgressRefetch + } = useAppsInProgressListQuery({ + displayLoader: false + }); + const { data, loading, refetch } = useAppsListQuery({ + displayLoader: true, + variables: { + ...paginationState, + ...queryVariables, + filter: { + type: AppTypeEnum.THIRDPARTY + } + } + }); + + const { loadNextPage, loadPreviousPage, pageInfo } = paginate( + data?.apps?.pageInfo, + paginationState, + params + ); + + const { + data: customAppsData, + loading: customAppsLoading, + refetch: customAppsRefetch + } = useAppsListQuery({ + displayLoader: true, + variables: { + first: 100, + ...queryVariables, + filter: { + type: AppTypeEnum.LOCAL + } + } + }); + + const installedAppNotify = (name: string) => { + notify({ + status: "success", + text: intl.formatMessage( + { + defaultMessage: "{name} is ready to be used", + description: "app has been installed" + }, + { name } + ), + title: intl.formatMessage({ + defaultMessage: "App installed", + description: "message title" + }) + }); + }; + const [retryInstallApp] = useAppRetryInstallMutation({ + onCompleted: data => { + const errors = data.appRetryInstall.errors; + if (!errors.length) { + const appInstallation = data.appRetryInstall.appInstallation; + setActiveInstallations(installations => [ + ...installations, + { id: appInstallation.id, name: appInstallation.appName } + ]); + } else { + errors.forEach(error => + notify({ status: "error", text: getAppErrorMessage(error, intl) }) + ); + } + } + }); + const [openModal, closeModal] = createDialogActionHandlers< + AppListUrlDialog, + AppListUrlQueryParams + >(navigate, appsListUrl, params); + + const onAppRemove = (data: AppDelete) => { + const errors = data.appDelete.errors; + if (errors.length === 0) { + if (data.appDelete.app.type === AppTypeEnum.LOCAL) { + customAppsRefetch(); + } else { + refetch(); + } + closeModal(); + removeAppNotify(); + } else { + errors.forEach(error => + notify({ + status: "error", + text: getAppErrorMessage(error, intl) + }) + ); + } + }; + + const [deleteApp, deleteAppOpts] = useAppDeleteMutation({ + onCompleted: data => { + onAppRemove(data); + } + }); + const [ + deleteInProgressApp, + deleteInProgressAppOpts + ] = useAppDeleteFailedInstallationMutation({ + onCompleted: data => { + onAppInProgressRemove(data); + } + }); + + useEffect(() => { + const appsInProgress = appsInProgressData?.appsInstallations || []; + if (activeInstallations.length && !!appsInProgressData) { + if (!intervalId.current) { + intervalId.current = window.setInterval( + () => appsInProgressRefetch(), + 2000 + ); + } + activeInstallations.forEach(installation => { + const item = appsInProgress?.find(app => app.id === installation.id); + if (!item) { + removeInstallation(installation.id); + installedAppNotify(installation.name); + appsInProgressRefetch(); + } else if (item.status === JobStatusEnum.SUCCESS) { + removeInstallation(installation.id); + installedAppNotify(item.appName); + refetch(); + } else if (item.status === JobStatusEnum.FAILED) { + removeInstallation(installation.id); + notify({ + status: "error", + text: item.message, + title: intl.formatMessage( + { + defaultMessage: "Couldn’t Install {name}", + description: "message title" + }, + { name: item.appName } + ) + }); + } + }); + } + if (!activeInstallations.length && intervalId.current) { + clearInterval(intervalId.current); + intervalId.current = null; + } + + return () => { + if (intervalId.current) { + clearInterval(intervalId.current); + intervalId.current = null; + } + }; + }, [activeInstallations.length, appsInProgressData]); + + const handleRemoveInProgressConfirm = () => + deleteInProgressApp({ + variables: { + id: params.id + } + }); + + const handleRemoveConfirm = () => + deleteApp({ + variables: { + id: params.id + } + }); + + const removeAppNotify = () => { + notify({ + status: "success", + text: intl.formatMessage({ + defaultMessage: "App successfully removed", + description: "app has been removed" + }) + }); + }; + + const onAppInProgressRemove = (data: AppDeleteFailedInstallation) => { + const errors = data.appDeleteFailedInstallation.errors; + if (errors.length === 0) { + removeAppNotify(); + appsInProgressRefetch(); + closeModal(); + } else { + errors.forEach(error => + notify({ + status: "error", + text: getAppErrorMessage(error, intl) + }) + ); + } + }; + const onAppInstallRetry = (id: string) => + retryInstallApp({ variables: { id } }); + + const installedApps = data?.apps?.edges; + const customApps = customAppsData?.apps?.edges; + + return ( + <> + + + () => navigate(appUrl(id))} + onSettingsRowClick={id => () => navigate(appSettingsUrl(id))} + onAppInstallRetry={onAppInstallRetry} + navigateToCustomApp={id => () => navigate(customAppUrl(id))} + navigateToCustomAppCreate={() => navigate(customAppAddUrl)} + onInstalledAppRemove={id => + openModal("remove-app", { + id + }) + } + onCustomAppRemove={id => + openModal("remove-custom-app", { + id + }) + } + onAppInProgressRemove={id => + openModal("remove", { + id + }) + } + /> + + ); +}; + +export default AppsList; diff --git a/src/apps/views/AppsList/index.ts b/src/apps/views/AppsList/index.ts new file mode 100644 index 000000000..571192ed9 --- /dev/null +++ b/src/apps/views/AppsList/index.ts @@ -0,0 +1,2 @@ +export * from "./AppsList"; +export { default } from "./AppsList"; diff --git a/src/apps/views/CustomAppCreate/CustomAppCreate.tsx b/src/apps/views/CustomAppCreate/CustomAppCreate.tsx new file mode 100644 index 000000000..8aacf4730 --- /dev/null +++ b/src/apps/views/CustomAppCreate/CustomAppCreate.tsx @@ -0,0 +1,77 @@ +import { WindowTitle } from "@saleor/components/WindowTitle"; +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import useShop from "@saleor/hooks/useShop"; +import { commonMessages } from "@saleor/intl"; +import React from "react"; +import { useIntl } from "react-intl"; + +import CustomAppCreatePage, { + CustomAppCreatePageFormData +} from "../../components/CustomAppCreatePage"; +import { useAppCreateMutation } from "../../mutations"; +import { AppCreate } from "../../types/AppCreate"; +import { appsListUrl, customAppUrl } from "../../urls"; + +interface CustomAppCreateProps { + setToken: (token: string) => void; +} +export const CustomAppCreate: React.FC = ({ + setToken +}) => { + const navigate = useNavigator(); + const notify = useNotifier(); + const intl = useIntl(); + const shop = useShop(); + + const onSubmit = (data: AppCreate) => { + if (data.appCreate.errors.length === 0) { + notify({ + status: "success", + text: intl.formatMessage(commonMessages.savedChanges) + }); + navigate(customAppUrl(data.appCreate.app.id)); + setToken(data.appCreate.authToken); + } + }; + + const handleBack = () => navigate(appsListUrl()); + + const [createApp, createAppOpts] = useAppCreateMutation({ + onCompleted: onSubmit + }); + + const handleSubmit = (data: CustomAppCreatePageFormData) => + createApp({ + variables: { + input: { + isActive: data.isActive, + name: data.name, + permissions: data.hasFullAccess + ? shop.permissions.map(permission => permission.code) + : data.permissions + } + } + }); + + return ( + <> + + + + ); +}; + +export default CustomAppCreate; diff --git a/src/apps/views/CustomAppCreate/index.ts b/src/apps/views/CustomAppCreate/index.ts new file mode 100644 index 000000000..0fc349041 --- /dev/null +++ b/src/apps/views/CustomAppCreate/index.ts @@ -0,0 +1,2 @@ +export * from "./CustomAppCreate"; +export { default } from "./CustomAppCreate"; diff --git a/src/apps/views/CustomAppDetails/CustomAppDetails.tsx b/src/apps/views/CustomAppDetails/CustomAppDetails.tsx new file mode 100644 index 000000000..da7111e6d --- /dev/null +++ b/src/apps/views/CustomAppDetails/CustomAppDetails.tsx @@ -0,0 +1,226 @@ +import TokenCreateDialog from "@saleor/apps/components/TokenCreateDialog"; +import TokenDeleteDialog from "@saleor/apps/components/TokenDeleteDialog"; +import NotFoundPage from "@saleor/components/NotFoundPage"; +import { WindowTitle } from "@saleor/components/WindowTitle"; +import { API_URI } from "@saleor/config"; +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import useShop from "@saleor/hooks/useShop"; +import { commonMessages } from "@saleor/intl"; +import { getStringOrPlaceholder } from "@saleor/misc"; +import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; +import WebhookDeleteDialog from "@saleor/webhooks/components/WebhookDeleteDialog"; +import { useWebhookDeleteMutation } from "@saleor/webhooks/mutations"; +import { WebhookDelete } from "@saleor/webhooks/types/WebhookDelete"; +import { webhookAddPath, webhookPath } from "@saleor/webhooks/urls"; +import React from "react"; +import { useIntl } from "react-intl"; + +import CustomAppDetailsPage, { + CustomAppDetailsPageFormData +} from "../../components/CustomAppDetailsPage"; +import { + useAppTokenCreateMutation, + useAppTokenDeleteMutation, + useAppUpdateMutation +} from "../../mutations"; +import { useAppDetails } from "../../queries"; +import { AppTokenCreate } from "../../types/AppTokenCreate"; +import { AppTokenDelete } from "../../types/AppTokenDelete"; +import { AppUpdate } from "../../types/AppUpdate"; +import { + appsListUrl, + customAppUrl, + CustomAppUrlDialog, + CustomAppUrlQueryParams +} from "../../urls"; + +interface OrderListProps { + id: string; + params: CustomAppUrlQueryParams; + token: string; + onTokenClose: () => void; +} + +export const CustomAppDetails: React.FC = ({ + id, + params, + token, + onTokenClose +}) => { + const navigate = useNavigator(); + const notify = useNotifier(); + const intl = useIntl(); + const shop = useShop(); + + React.useEffect(() => onTokenClose, []); + + const [openModal, closeModal] = createDialogActionHandlers< + CustomAppUrlDialog, + CustomAppUrlQueryParams + >(navigate, params => customAppUrl(id, params), params); + + const { data, loading, refetch } = useAppDetails({ + displayLoader: true, + variables: { id } + }); + + const onWebhookDelete = (data: WebhookDelete) => { + if (data.webhookDelete.errors.length === 0) { + notify({ + status: "success", + text: intl.formatMessage(commonMessages.savedChanges) + }); + navigate(customAppUrl(id)); + closeModal(); + refetch(); + } + }; + + const [webhookDelete, webhookDeleteOpts] = useWebhookDeleteMutation({ + onCompleted: onWebhookDelete + }); + + const handleRemoveWebhookConfirm = () => { + webhookDelete({ + variables: { + id: params.id + } + }); + }; + + const onAppUpdate = (data: AppUpdate) => { + if (data?.appUpdate?.errors?.length === 0) { + notify({ + status: "success", + text: intl.formatMessage(commonMessages.savedChanges) + }); + } + }; + const handleBack = () => navigate(appsListUrl()); + const customApp = data?.app; + + if (customApp === null) { + return ; + } + + const onTokenCreate = (data: AppTokenCreate) => { + if (data?.appTokenCreate?.errors.length === 0) { + refetch(); + } + }; + const onTokenDelete = (data: AppTokenDelete) => { + if (data?.appTokenDelete?.errors.length === 0) { + notify({ + status: "success", + text: intl.formatMessage(commonMessages.savedChanges) + }); + refetch(); + closeModal(); + } + }; + + const [updateApp, updateAppOpts] = useAppUpdateMutation({ + onCompleted: onAppUpdate + }); + const [createToken, createTokenOpts] = useAppTokenCreateMutation({ + onCompleted: onTokenCreate + }); + const [deleteToken, deleteTokenOpts] = useAppTokenDeleteMutation({ + onCompleted: onTokenDelete + }); + + const handleSubmit = (data: CustomAppDetailsPageFormData) => + updateApp({ + variables: { + id, + input: { + isActive: data.isActive, + name: data.name, + permissions: data.hasFullAccess + ? shop.permissions.map(permission => permission.code) + : data.permissions + } + } + }); + + const handleTokenCreate = (name: string) => + createToken({ + variables: { + input: { + app: id, + name + } + } + }); + + const handleTokenDelete = () => + deleteToken({ + variables: { + id: params.id + } + }); + + const currentToken = data?.app?.tokens?.find(token => token.id === params.id); + + return ( + <> + + () => navigate(webhookPath(id))} + onApiUriClick={() => open(API_URI, "blank")} + onBack={handleBack} + onSubmit={handleSubmit} + onTokenClose={onTokenClose} + onTokenCreate={() => openModal("create-token")} + onTokenDelete={id => + openModal("remove-token", { + id + }) + } + onWebhookCreate={() => navigate(webhookAddPath(id))} + onWebhookRemove={id => + openModal("remove-webhook", { + id + }) + } + permissions={shop?.permissions} + app={data?.app} + saveButtonBarState={updateAppOpts.status} + /> + + + webhook.id === params.id)?.name + } + onClose={closeModal} + onConfirm={handleRemoveWebhookConfirm} + open={params.action === "remove-webhook"} + /> + + ); +}; + +export default CustomAppDetails; diff --git a/src/apps/views/CustomAppDetails/index.ts b/src/apps/views/CustomAppDetails/index.ts new file mode 100644 index 000000000..2461dd3f6 --- /dev/null +++ b/src/apps/views/CustomAppDetails/index.ts @@ -0,0 +1,2 @@ +export * from "./CustomAppDetails"; +export { default } from "./CustomAppDetails"; diff --git a/src/attributes/components/AttributeBulkDeleteDialog/AttributeBulkDeleteDialog.tsx b/src/attributes/components/AttributeBulkDeleteDialog/AttributeBulkDeleteDialog.tsx index 220bd2b79..480dfeda4 100644 --- a/src/attributes/components/AttributeBulkDeleteDialog/AttributeBulkDeleteDialog.tsx +++ b/src/attributes/components/AttributeBulkDeleteDialog/AttributeBulkDeleteDialog.tsx @@ -1,9 +1,8 @@ import DialogContentText from "@material-ui/core/DialogContentText"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import ActionDialog from "@saleor/components/ActionDialog"; import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; export interface AttributeBulkDeleteDialogProps { confirmButtonState: ConfirmButtonTransitionState; diff --git a/src/attributes/components/AttributeDeleteDialog/AttributeDeleteDialog.tsx b/src/attributes/components/AttributeDeleteDialog/AttributeDeleteDialog.tsx index 90c3c09e3..4ab30c283 100644 --- a/src/attributes/components/AttributeDeleteDialog/AttributeDeleteDialog.tsx +++ b/src/attributes/components/AttributeDeleteDialog/AttributeDeleteDialog.tsx @@ -1,9 +1,8 @@ import DialogContentText from "@material-ui/core/DialogContentText"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import ActionDialog from "@saleor/components/ActionDialog"; import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; export interface AttributeDeleteDialogProps { confirmButtonState: ConfirmButtonTransitionState; diff --git a/src/attributes/components/AttributeDetails/AttributeDetails.tsx b/src/attributes/components/AttributeDetails/AttributeDetails.tsx index 26b3ea201..5bffdb265 100644 --- a/src/attributes/components/AttributeDetails/AttributeDetails.tsx +++ b/src/attributes/components/AttributeDetails/AttributeDetails.tsx @@ -1,20 +1,20 @@ import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; import TextField from "@material-ui/core/TextField"; -import React from "react"; -import { useIntl } from "react-intl"; -import slugify from "slugify"; - import CardTitle from "@saleor/components/CardTitle"; import ControlledCheckbox from "@saleor/components/ControlledCheckbox"; import FormSpacer from "@saleor/components/FormSpacer"; import SingleSelectField from "@saleor/components/SingleSelectField"; +import { ProductErrorFragment } from "@saleor/fragments/types/ProductErrorFragment"; import { commonMessages } from "@saleor/intl"; import { AttributeInputTypeEnum } from "@saleor/types/globalTypes"; -import { getProductErrorMessage, getFormErrors } from "@saleor/utils/errors"; -import { ProductErrorFragment } from "@saleor/attributes/types/ProductErrorFragment"; -import { AttributePageFormData } from "../AttributePage"; +import { getFormErrors, getProductErrorMessage } from "@saleor/utils/errors"; +import React from "react"; +import { useIntl } from "react-intl"; +import slugify from "slugify"; + import { getAttributeSlugErrorMessage } from "../../errors"; +import { AttributePageFormData } from "../AttributePage"; export interface AttributeDetailsProps { canChangeType: boolean; diff --git a/src/attributes/components/AttributeList/AttributeList.tsx b/src/attributes/components/AttributeList/AttributeList.tsx index b3844066f..211c374ce 100644 --- a/src/attributes/components/AttributeList/AttributeList.tsx +++ b/src/attributes/components/AttributeList/AttributeList.tsx @@ -3,20 +3,20 @@ import TableBody from "@material-ui/core/TableBody"; import TableCell from "@material-ui/core/TableCell"; import TableFooter from "@material-ui/core/TableFooter"; import TableRow from "@material-ui/core/TableRow"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - +import { AttributeListUrlSortField } from "@saleor/attributes/urls"; import Checkbox from "@saleor/components/Checkbox"; import ResponsiveTable from "@saleor/components/ResponsiveTable"; import Skeleton from "@saleor/components/Skeleton"; +import TableCellHeader from "@saleor/components/TableCellHeader"; import TableHead from "@saleor/components/TableHead"; import TablePagination from "@saleor/components/TablePagination"; import { translateBoolean } from "@saleor/intl"; import { maybe, renderCollection } from "@saleor/misc"; import { ListActions, ListProps, SortPage } from "@saleor/types"; -import TableCellHeader from "@saleor/components/TableCellHeader"; -import { AttributeListUrlSortField } from "@saleor/attributes/urls"; import { getArrowDirection } from "@saleor/utils/sort"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { AttributeList_attributes_edges_node } from "../../types/AttributeList"; export interface AttributeListProps @@ -193,9 +193,9 @@ const AttributeList: React.FC = ({ key={attribute ? attribute.id : "skeleton"} onClick={attribute && onRowClick(attribute.id)} className={classes.link} - data-tc="id" - data-tc-id={maybe(() => attribute.id)} - data-tc-values={JSON.stringify( + data-test="id" + data-test-id={maybe(() => attribute.id)} + data-test-values={JSON.stringify( maybe(() => attribute.values, []) )} > @@ -207,16 +207,16 @@ const AttributeList: React.FC = ({ onChange={() => toggle(attribute.id)} />
- + {attribute ? attribute.slug : } - + {attribute ? attribute.name : } attribute.visibleInStorefront)} + data-test="visible" + data-test-visible={maybe(() => attribute.visibleInStorefront)} > {attribute ? ( translateBoolean(attribute.visibleInStorefront, intl) @@ -226,8 +226,8 @@ const AttributeList: React.FC = ({ attribute.filterableInDashboard )} > @@ -239,8 +239,8 @@ const AttributeList: React.FC = ({ attribute.filterableInStorefront )} > diff --git a/src/attributes/components/AttributeListPage/AttributeListPage.tsx b/src/attributes/components/AttributeListPage/AttributeListPage.tsx index 70f8733c2..9de531647 100644 --- a/src/attributes/components/AttributeListPage/AttributeListPage.tsx +++ b/src/attributes/components/AttributeListPage/AttributeListPage.tsx @@ -1,27 +1,27 @@ import Button from "@material-ui/core/Button"; import Card from "@material-ui/core/Card"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - +import { AttributeListUrlSortField } from "@saleor/attributes/urls"; import AppHeader from "@saleor/components/AppHeader"; import FilterBar from "@saleor/components/FilterBar"; import { sectionNames } from "@saleor/intl"; -import { AttributeListUrlSortField } from "@saleor/attributes/urls"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import Container from "../../../components/Container"; import PageHeader from "../../../components/PageHeader"; import { + FilterPageProps, ListActions, PageListProps, - FilterPageProps, - TabPageProps, - SortPage + SortPage, + TabPageProps } from "../../../types"; import { AttributeList_attributes_edges_node } from "../../types/AttributeList"; import AttributeList from "../AttributeList/AttributeList"; import { - createFilterStructure, + AttributeFilterKeys, AttributeListFilterOpts, - AttributeFilterKeys + createFilterStructure } from "./filters"; export interface AttributeListPageProps diff --git a/src/attributes/components/AttributeListPage/filters.ts b/src/attributes/components/AttributeListPage/filters.ts index d3309a492..2eb5dd6fb 100644 --- a/src/attributes/components/AttributeListPage/filters.ts +++ b/src/attributes/components/AttributeListPage/filters.ts @@ -1,9 +1,8 @@ -import { defineMessages, IntlShape } from "react-intl"; - -import { FilterOpts } from "@saleor/types"; -import { commonMessages } from "@saleor/intl"; import { IFilter } from "@saleor/components/Filter"; +import { commonMessages } from "@saleor/intl"; +import { FilterOpts } from "@saleor/types"; import { createBooleanField } from "@saleor/utils/filters/fields"; +import { defineMessages, IntlShape } from "react-intl"; export enum AttributeFilterKeys { availableInGrid = "availableInGrid", diff --git a/src/attributes/components/AttributePage/AttributePage.tsx b/src/attributes/components/AttributePage/AttributePage.tsx index 69a0f3477..9fe12bdb0 100644 --- a/src/attributes/components/AttributePage/AttributePage.tsx +++ b/src/attributes/components/AttributePage/AttributePage.tsx @@ -1,24 +1,28 @@ -import React from "react"; -import { useIntl } from "react-intl"; -import slugify from "slugify"; - import AppHeader from "@saleor/components/AppHeader"; import CardSpacer from "@saleor/components/CardSpacer"; import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; import Container from "@saleor/components/Container"; import Form from "@saleor/components/Form"; import Grid from "@saleor/components/Grid"; +import Metadata from "@saleor/components/Metadata/Metadata"; +import { MetadataFormData } from "@saleor/components/Metadata/types"; import PageHeader from "@saleor/components/PageHeader"; import SaveButtonBar from "@saleor/components/SaveButtonBar"; +import { + AttributeDetailsFragment, + AttributeDetailsFragment_values +} from "@saleor/fragments/types/AttributeDetailsFragment"; +import { ProductErrorFragment } from "@saleor/fragments/types/ProductErrorFragment"; import { sectionNames } from "@saleor/intl"; import { maybe } from "@saleor/misc"; import { ReorderAction } from "@saleor/types"; import { AttributeInputTypeEnum } from "@saleor/types/globalTypes"; -import { ProductErrorFragment } from "@saleor/attributes/types/ProductErrorFragment"; -import { - AttributeDetailsFragment, - AttributeDetailsFragment_values -} from "../../types/AttributeDetailsFragment"; +import { mapMetadataItemToInput } from "@saleor/utils/maps"; +import useMetadataChangeTrigger from "@saleor/utils/metadata/useMetadataChangeTrigger"; +import React from "react"; +import { useIntl } from "react-intl"; +import slugify from "slugify"; + import AttributeDetails from "../AttributeDetails"; import AttributeProperties from "../AttributeProperties"; import AttributeValues from "../AttributeValues"; @@ -38,7 +42,7 @@ export interface AttributePageProps { onValueUpdate: (id: string) => void; } -export interface AttributePageFormData { +export interface AttributePageFormData extends MetadataFormData { availableInGrid: boolean; filterableInDashboard: boolean; inputType: AttributeInputTypeEnum; @@ -65,6 +69,12 @@ const AttributePage: React.FC = ({ onValueUpdate }) => { const intl = useIntl(); + const { + isMetadataModified, + isPrivateMetadataModified, + makeChangeHandler: makeMetadataChangeHandler + } = useMetadataChangeTrigger(); + const initialForm: AttributePageFormData = attribute === null ? { @@ -72,7 +82,9 @@ const AttributePage: React.FC = ({ filterableInDashboard: true, filterableInStorefront: true, inputType: AttributeInputTypeEnum.DROPDOWN, + metadata: [], name: "", + privateMetadata: [], slug: "", storefrontSearchPosition: "", valueRequired: true, @@ -92,7 +104,11 @@ const AttributePage: React.FC = ({ () => attribute.inputType, AttributeInputTypeEnum.DROPDOWN ), + metadata: attribute?.metadata?.map(mapMetadataItemToInput), name: maybe(() => attribute.name, ""), + privateMetadata: attribute?.privateMetadata?.map( + mapMetadataItemToInput + ), slug: maybe(() => attribute.slug, ""), storefrontSearchPosition: maybe( () => attribute.storefrontSearchPosition.toString(), @@ -102,66 +118,82 @@ const AttributePage: React.FC = ({ visibleInStorefront: maybe(() => attribute.visibleInStorefront, true) }; - const handleSubmit = (data: AttributePageFormData) => + const handleSubmit = (data: AttributePageFormData) => { + const metadata = + !attribute || isMetadataModified ? data.metadata : undefined; + const privateMetadata = + !attribute || isPrivateMetadataModified + ? data.privateMetadata + : undefined; + onSubmit({ ...data, + metadata, + privateMetadata, slug: data.slug || slugify(data.name).toLowerCase() }); + }; return ( - {({ change, data, submit }) => ( - - - {intl.formatMessage(sectionNames.attributes)} - - attribute.name) - } - /> - -
- - - -
-
- -
-
- -
- )} + {({ change, data, submit }) => { + const changeMetadata = makeMetadataChangeHandler(change); + + return ( + + + {intl.formatMessage(sectionNames.attributes)} + + attribute.name) + } + /> + +
+ + + + + +
+
+ +
+
+ +
+ ); + }} ); }; diff --git a/src/attributes/components/AttributeProperties/AttributeProperties.tsx b/src/attributes/components/AttributeProperties/AttributeProperties.tsx index 1ad3fcd36..4d5e56589 100644 --- a/src/attributes/components/AttributeProperties/AttributeProperties.tsx +++ b/src/attributes/components/AttributeProperties/AttributeProperties.tsx @@ -2,17 +2,17 @@ import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; import TextField from "@material-ui/core/TextField"; import Typography from "@material-ui/core/Typography"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import CardSpacer from "@saleor/components/CardSpacer"; import CardTitle from "@saleor/components/CardTitle"; import ControlledCheckbox from "@saleor/components/ControlledCheckbox"; import FormSpacer from "@saleor/components/FormSpacer"; import Hr from "@saleor/components/Hr"; +import { ProductErrorFragment } from "@saleor/fragments/types/ProductErrorFragment"; import { commonMessages } from "@saleor/intl"; import { getFormErrors, getProductErrorMessage } from "@saleor/utils/errors"; -import { ProductErrorFragment } from "@saleor/attributes/types/ProductErrorFragment"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { AttributePageFormData } from "../AttributePage"; export interface AttributePropertiesProps { diff --git a/src/attributes/components/AttributeValueDeleteDialog/AttributeValueDeleteDialog.tsx b/src/attributes/components/AttributeValueDeleteDialog/AttributeValueDeleteDialog.tsx index e8872a427..7554862d6 100644 --- a/src/attributes/components/AttributeValueDeleteDialog/AttributeValueDeleteDialog.tsx +++ b/src/attributes/components/AttributeValueDeleteDialog/AttributeValueDeleteDialog.tsx @@ -1,9 +1,8 @@ import DialogContentText from "@material-ui/core/DialogContentText"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import ActionDialog from "@saleor/components/ActionDialog"; import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; export interface AttributeValueDeleteDialogProps { attributeName: string; diff --git a/src/attributes/components/AttributeValueEditDialog/AttributeValueEditDialog.tsx b/src/attributes/components/AttributeValueEditDialog/AttributeValueEditDialog.tsx index 5dba17ab3..0eb163ce9 100644 --- a/src/attributes/components/AttributeValueEditDialog/AttributeValueEditDialog.tsx +++ b/src/attributes/components/AttributeValueEditDialog/AttributeValueEditDialog.tsx @@ -4,19 +4,19 @@ import DialogActions from "@material-ui/core/DialogActions"; import DialogContent from "@material-ui/core/DialogContent"; import DialogTitle from "@material-ui/core/DialogTitle"; import TextField from "@material-ui/core/TextField"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - +import { getAttributeValueErrorMessage } from "@saleor/attributes/errors"; import ConfirmButton, { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; import Form from "@saleor/components/Form"; +import { ProductErrorFragment } from "@saleor/fragments/types/ProductErrorFragment"; import useModalDialogErrors from "@saleor/hooks/useModalDialogErrors"; import { buttonMessages } from "@saleor/intl"; import { maybe } from "@saleor/misc"; import { getFormErrors } from "@saleor/utils/errors"; -import { ProductErrorFragment } from "@saleor/attributes/types/ProductErrorFragment"; -import { getAttributeValueErrorMessage } from "@saleor/attributes/errors"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { AttributeDetails_attribute_values } from "../../types/AttributeDetails"; export interface AttributeValueEditDialogFormData { diff --git a/src/attributes/components/AttributeValues/AttributeValues.tsx b/src/attributes/components/AttributeValues/AttributeValues.tsx index 2cdd5c229..71b9c81f0 100644 --- a/src/attributes/components/AttributeValues/AttributeValues.tsx +++ b/src/attributes/components/AttributeValues/AttributeValues.tsx @@ -6,9 +6,6 @@ import TableCell from "@material-ui/core/TableCell"; import TableHead from "@material-ui/core/TableHead"; import TableRow from "@material-ui/core/TableRow"; import DeleteIcon from "@material-ui/icons/Delete"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import CardTitle from "@saleor/components/CardTitle"; import ResponsiveTable from "@saleor/components/ResponsiveTable"; import Skeleton from "@saleor/components/Skeleton"; @@ -16,9 +13,11 @@ import { SortableTableBody, SortableTableRow } from "@saleor/components/SortableTable"; +import { AttributeDetailsFragment_values } from "@saleor/fragments/types/AttributeDetailsFragment"; import { maybe, renderCollection, stopPropagation } from "@saleor/misc"; import { ReorderAction } from "@saleor/types"; -import { AttributeDetailsFragment_values } from "../../types/AttributeDetailsFragment"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; export interface AttributeValuesProps { disabled: boolean; diff --git a/src/attributes/errors.ts b/src/attributes/errors.ts index 1b0ad377b..a245bf8c2 100644 --- a/src/attributes/errors.ts +++ b/src/attributes/errors.ts @@ -1,8 +1,7 @@ -import { IntlShape, defineMessages } from "react-intl"; - +import { ProductErrorFragment } from "@saleor/fragments/types/ProductErrorFragment"; import { ProductErrorCode } from "@saleor/types/globalTypes"; import { getProductErrorMessage } from "@saleor/utils/errors"; -import { ProductErrorFragment } from "./types/ProductErrorFragment"; +import { defineMessages, IntlShape } from "react-intl"; const messages = defineMessages({ attributeSlugUnique: { diff --git a/src/attributes/fixtures.ts b/src/attributes/fixtures.ts index 92ab3ef0d..67788a9fe 100644 --- a/src/attributes/fixtures.ts +++ b/src/attributes/fixtures.ts @@ -1,9 +1,10 @@ +import { AttributeDetailsFragment } from "@saleor/fragments/types/AttributeDetailsFragment"; import { ProductDetails_product_productType_variantAttributes } from "@saleor/products/types/ProductDetails"; import { AttributeInputTypeEnum, AttributeValueType } from "@saleor/types/globalTypes"; -import { AttributeDetailsFragment } from "./types/AttributeDetailsFragment"; + import { AttributeList_attributes_edges_node } from "./types/AttributeList"; export const attribute: AttributeDetailsFragment = { @@ -13,7 +14,15 @@ export const attribute: AttributeDetailsFragment = { filterableInStorefront: true, id: "UHJvZHVjdEF0dHJpYnV0ZTo5", inputType: AttributeInputTypeEnum.DROPDOWN, + metadata: [ + { + __typename: "MetadataItem", + key: "integration.id", + value: "100023123" + } + ], name: "Author", + privateMetadata: [], slug: "author", storefrontSearchPosition: 2, valueRequired: true, @@ -36,10 +45,8 @@ export const attribute: AttributeDetailsFragment = { visibleInStorefront: true }; -export const attributes: Array< - AttributeList_attributes_edges_node & - ProductDetails_product_productType_variantAttributes -> = [ +export const attributes: Array = [ { node: { __typename: "Attribute" as "Attribute", diff --git a/src/attributes/index.tsx b/src/attributes/index.tsx index a15e5fc40..3c01987bd 100644 --- a/src/attributes/index.tsx +++ b/src/attributes/index.tsx @@ -1,19 +1,19 @@ +import { sectionNames } from "@saleor/intl"; +import { asSortParams } from "@saleor/utils/sort"; import { parse as parseQs } from "qs"; import React from "react"; +import { useIntl } from "react-intl"; import { Route, RouteComponentProps, Switch } from "react-router-dom"; -import { sectionNames } from "@saleor/intl"; -import { useIntl } from "react-intl"; -import { asSortParams } from "@saleor/utils/sort"; import { WindowTitle } from "../components/WindowTitle"; import { attributeAddPath, AttributeAddUrlQueryParams, attributeListPath, AttributeListUrlQueryParams, + AttributeListUrlSortField, attributePath, - AttributeUrlQueryParams, - AttributeListUrlSortField + AttributeUrlQueryParams } from "./urls"; import AttributeCreateComponent from "./views/AttributeCreate"; import AttributeDetailsComponent from "./views/AttributeDetails"; diff --git a/src/attributes/mutations.ts b/src/attributes/mutations.ts index 5aebd35a2..222f8d7b4 100644 --- a/src/attributes/mutations.ts +++ b/src/attributes/mutations.ts @@ -1,7 +1,8 @@ +import { attributeDetailsFragment } from "@saleor/fragments/attributes"; +import { productErrorFragment } from "@saleor/fragments/errors"; +import makeMutation from "@saleor/hooks/makeMutation"; import gql from "graphql-tag"; -import { TypedMutation } from "@saleor/mutations"; -import { attributeDetailsFragment } from "./queries"; import { AttributeBulkDelete, AttributeBulkDeleteVariables @@ -35,13 +36,6 @@ import { AttributeValueUpdateVariables } from "./types/AttributeValueUpdate"; -export const productErrorFragment = gql` - fragment ProductErrorFragment on ProductError { - code - field - } -`; - const attributeBulkDelete = gql` ${productErrorFragment} mutation AttributeBulkDelete($ids: [ID!]!) { @@ -52,7 +46,7 @@ const attributeBulkDelete = gql` } } `; -export const AttributeBulkDeleteMutation = TypedMutation< +export const useAttributeBulkDeleteMutation = makeMutation< AttributeBulkDelete, AttributeBulkDeleteVariables >(attributeBulkDelete); @@ -67,7 +61,7 @@ const attributeDelete = gql` } } `; -export const AttributeDeleteMutation = TypedMutation< +export const useAttributeDeleteMutation = makeMutation< AttributeDelete, AttributeDeleteVariables >(attributeDelete); @@ -86,7 +80,7 @@ export const attributeUpdateMutation = gql` } } `; -export const AttributeUpdateMutation = TypedMutation< +export const useAttributeUpdateMutation = makeMutation< AttributeUpdate, AttributeUpdateVariables >(attributeUpdateMutation); @@ -105,7 +99,7 @@ const attributeValueDelete = gql` } } `; -export const AttributeValueDeleteMutation = TypedMutation< +export const useAttributeValueDeleteMutation = makeMutation< AttributeValueDelete, AttributeValueDeleteVariables >(attributeValueDelete); @@ -124,7 +118,7 @@ export const attributeValueUpdateMutation = gql` } } `; -export const AttributeValueUpdateMutation = TypedMutation< +export const useAttributeValueUpdateMutation = makeMutation< AttributeValueUpdate, AttributeValueUpdateVariables >(attributeValueUpdateMutation); @@ -143,7 +137,7 @@ export const attributeValueCreateMutation = gql` } } `; -export const AttributeValueCreateMutation = TypedMutation< +export const useAttributeValueCreateMutation = makeMutation< AttributeValueCreate, AttributeValueCreateVariables >(attributeValueCreateMutation); @@ -162,7 +156,7 @@ export const attributeCreateMutation = gql` } } `; -export const AttributeCreateMutation = TypedMutation< +export const useAttributeCreateMutation = makeMutation< AttributeCreate, AttributeCreateVariables >(attributeCreateMutation); @@ -183,7 +177,7 @@ const attributeValueReorderMutation = gql` } } `; -export const AttributeValueReorderMutation = TypedMutation< +export const useAttributeValueReorderMutation = makeMutation< AttributeValueReorder, AttributeValueReorderVariables >(attributeValueReorderMutation); diff --git a/src/attributes/queries.ts b/src/attributes/queries.ts index 20b4392c4..1880de540 100644 --- a/src/attributes/queries.ts +++ b/src/attributes/queries.ts @@ -1,41 +1,17 @@ +import { + attributeDetailsFragment, + attributeFragment +} from "@saleor/fragments/attributes"; +import { pageInfoFragment } from "@saleor/fragments/pageInfo"; +import makeQuery from "@saleor/hooks/makeQuery"; import gql from "graphql-tag"; -import makeQuery from "@saleor/hooks/makeQuery"; -import { pageInfoFragment, TypedQuery } from "../queries"; import { AttributeDetails, AttributeDetailsVariables } from "./types/AttributeDetails"; import { AttributeList, AttributeListVariables } from "./types/AttributeList"; -export const attributeFragment = gql` - fragment AttributeFragment on Attribute { - id - name - slug - visibleInStorefront - filterableInDashboard - filterableInStorefront - } -`; - -export const attributeDetailsFragment = gql` - ${attributeFragment} - fragment AttributeDetailsFragment on Attribute { - ...AttributeFragment - availableInGrid - inputType - storefrontSearchPosition - valueRequired - values { - id - name - slug - type - } - } -`; - const attributeDetails = gql` ${attributeDetailsFragment} query AttributeDetails($id: ID!) { @@ -44,7 +20,7 @@ const attributeDetails = gql` } } `; -export const AttributeDetailsQuery = TypedQuery< +export const useAttributeDetailsQuery = makeQuery< AttributeDetails, AttributeDetailsVariables >(attributeDetails); diff --git a/src/attributes/types/AttributeCreate.ts b/src/attributes/types/AttributeCreate.ts index 3c7db619b..96aa56175 100644 --- a/src/attributes/types/AttributeCreate.ts +++ b/src/attributes/types/AttributeCreate.ts @@ -8,6 +8,18 @@ import { AttributeCreateInput, AttributeInputTypeEnum, AttributeValueType, Produ // GraphQL mutation operation: AttributeCreate // ==================================================== +export interface AttributeCreate_attributeCreate_attribute_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface AttributeCreate_attributeCreate_attribute_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface AttributeCreate_attributeCreate_attribute_values { __typename: "AttributeValue"; id: string; @@ -24,6 +36,8 @@ export interface AttributeCreate_attributeCreate_attribute { visibleInStorefront: boolean; filterableInDashboard: boolean; filterableInStorefront: boolean; + metadata: (AttributeCreate_attributeCreate_attribute_metadata | null)[]; + privateMetadata: (AttributeCreate_attributeCreate_attribute_privateMetadata | null)[]; availableInGrid: boolean; inputType: AttributeInputTypeEnum | null; storefrontSearchPosition: number; diff --git a/src/attributes/types/AttributeDetails.ts b/src/attributes/types/AttributeDetails.ts index f2708bb8d..1392ba7b2 100644 --- a/src/attributes/types/AttributeDetails.ts +++ b/src/attributes/types/AttributeDetails.ts @@ -8,6 +8,18 @@ import { AttributeInputTypeEnum, AttributeValueType } from "./../../types/global // GraphQL query operation: AttributeDetails // ==================================================== +export interface AttributeDetails_attribute_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface AttributeDetails_attribute_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface AttributeDetails_attribute_values { __typename: "AttributeValue"; id: string; @@ -24,6 +36,8 @@ export interface AttributeDetails_attribute { visibleInStorefront: boolean; filterableInDashboard: boolean; filterableInStorefront: boolean; + metadata: (AttributeDetails_attribute_metadata | null)[]; + privateMetadata: (AttributeDetails_attribute_privateMetadata | null)[]; availableInGrid: boolean; inputType: AttributeInputTypeEnum | null; storefrontSearchPosition: number; diff --git a/src/attributes/types/AttributeUpdate.ts b/src/attributes/types/AttributeUpdate.ts index 51dedb082..e06c55a1f 100644 --- a/src/attributes/types/AttributeUpdate.ts +++ b/src/attributes/types/AttributeUpdate.ts @@ -8,6 +8,18 @@ import { AttributeUpdateInput, AttributeInputTypeEnum, AttributeValueType, Produ // GraphQL mutation operation: AttributeUpdate // ==================================================== +export interface AttributeUpdate_attributeUpdate_attribute_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface AttributeUpdate_attributeUpdate_attribute_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface AttributeUpdate_attributeUpdate_attribute_values { __typename: "AttributeValue"; id: string; @@ -24,6 +36,8 @@ export interface AttributeUpdate_attributeUpdate_attribute { visibleInStorefront: boolean; filterableInDashboard: boolean; filterableInStorefront: boolean; + metadata: (AttributeUpdate_attributeUpdate_attribute_metadata | null)[]; + privateMetadata: (AttributeUpdate_attributeUpdate_attribute_privateMetadata | null)[]; availableInGrid: boolean; inputType: AttributeInputTypeEnum | null; storefrontSearchPosition: number; diff --git a/src/attributes/types/AttributeValueCreate.ts b/src/attributes/types/AttributeValueCreate.ts index 9f02505d2..83861c906 100644 --- a/src/attributes/types/AttributeValueCreate.ts +++ b/src/attributes/types/AttributeValueCreate.ts @@ -8,6 +8,18 @@ import { AttributeValueCreateInput, AttributeInputTypeEnum, AttributeValueType, // GraphQL mutation operation: AttributeValueCreate // ==================================================== +export interface AttributeValueCreate_attributeValueCreate_attribute_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface AttributeValueCreate_attributeValueCreate_attribute_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface AttributeValueCreate_attributeValueCreate_attribute_values { __typename: "AttributeValue"; id: string; @@ -24,6 +36,8 @@ export interface AttributeValueCreate_attributeValueCreate_attribute { visibleInStorefront: boolean; filterableInDashboard: boolean; filterableInStorefront: boolean; + metadata: (AttributeValueCreate_attributeValueCreate_attribute_metadata | null)[]; + privateMetadata: (AttributeValueCreate_attributeValueCreate_attribute_privateMetadata | null)[]; availableInGrid: boolean; inputType: AttributeInputTypeEnum | null; storefrontSearchPosition: number; diff --git a/src/attributes/types/AttributeValueDelete.ts b/src/attributes/types/AttributeValueDelete.ts index 978e938b3..4f1c4c4f1 100644 --- a/src/attributes/types/AttributeValueDelete.ts +++ b/src/attributes/types/AttributeValueDelete.ts @@ -8,6 +8,18 @@ import { AttributeInputTypeEnum, AttributeValueType, ProductErrorCode } from "./ // GraphQL mutation operation: AttributeValueDelete // ==================================================== +export interface AttributeValueDelete_attributeValueDelete_attribute_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface AttributeValueDelete_attributeValueDelete_attribute_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface AttributeValueDelete_attributeValueDelete_attribute_values { __typename: "AttributeValue"; id: string; @@ -24,6 +36,8 @@ export interface AttributeValueDelete_attributeValueDelete_attribute { visibleInStorefront: boolean; filterableInDashboard: boolean; filterableInStorefront: boolean; + metadata: (AttributeValueDelete_attributeValueDelete_attribute_metadata | null)[]; + privateMetadata: (AttributeValueDelete_attributeValueDelete_attribute_privateMetadata | null)[]; availableInGrid: boolean; inputType: AttributeInputTypeEnum | null; storefrontSearchPosition: number; diff --git a/src/attributes/types/AttributeValueUpdate.ts b/src/attributes/types/AttributeValueUpdate.ts index 564f7a691..5d653bf99 100644 --- a/src/attributes/types/AttributeValueUpdate.ts +++ b/src/attributes/types/AttributeValueUpdate.ts @@ -8,6 +8,18 @@ import { AttributeValueCreateInput, AttributeInputTypeEnum, AttributeValueType, // GraphQL mutation operation: AttributeValueUpdate // ==================================================== +export interface AttributeValueUpdate_attributeValueUpdate_attribute_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface AttributeValueUpdate_attributeValueUpdate_attribute_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface AttributeValueUpdate_attributeValueUpdate_attribute_values { __typename: "AttributeValue"; id: string; @@ -24,6 +36,8 @@ export interface AttributeValueUpdate_attributeValueUpdate_attribute { visibleInStorefront: boolean; filterableInDashboard: boolean; filterableInStorefront: boolean; + metadata: (AttributeValueUpdate_attributeValueUpdate_attribute_metadata | null)[]; + privateMetadata: (AttributeValueUpdate_attributeValueUpdate_attribute_privateMetadata | null)[]; availableInGrid: boolean; inputType: AttributeInputTypeEnum | null; storefrontSearchPosition: number; diff --git a/src/attributes/views/AttributeCreate/AttributeCreate.tsx b/src/attributes/views/AttributeCreate/AttributeCreate.tsx index 7ece9730e..89a45a543 100644 --- a/src/attributes/views/AttributeCreate/AttributeCreate.tsx +++ b/src/attributes/views/AttributeCreate/AttributeCreate.tsx @@ -1,11 +1,11 @@ -import React from "react"; -import { useIntl } from "react-intl"; -import slugify from "slugify"; - +import { ProductErrorFragment } from "@saleor/fragments/types/ProductErrorFragment"; import useNavigator from "@saleor/hooks/useNavigator"; import useNotifier from "@saleor/hooks/useNotifier"; -import { maybe } from "@saleor/misc"; +import { getStringOrPlaceholder } from "@saleor/misc"; import { ReorderEvent } from "@saleor/types"; +import { ProductErrorCode } from "@saleor/types/globalTypes"; +import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; +import createMetadataCreateHandler from "@saleor/utils/handlers/metadataCreateHandler"; import { add, isSelected, @@ -13,22 +13,28 @@ import { remove, updateAtIndex } from "@saleor/utils/lists"; -import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; -import { ProductErrorFragment } from "@saleor/attributes/types/ProductErrorFragment"; -import { ProductErrorCode } from "@saleor/types/globalTypes"; -import AttributePage from "../../components/AttributePage"; +import { + useMetadataUpdate, + usePrivateMetadataUpdate +} from "@saleor/utils/metadata/updateMetadata"; +import React from "react"; +import { useIntl } from "react-intl"; +import slugify from "slugify"; + +import AttributePage, { + AttributePageFormData +} from "../../components/AttributePage"; import AttributeValueDeleteDialog from "../../components/AttributeValueDeleteDialog"; import AttributeValueEditDialog, { AttributeValueEditDialogFormData } from "../../components/AttributeValueEditDialog"; -import { AttributeCreateMutation } from "../../mutations"; -import { AttributeCreate } from "../../types/AttributeCreate"; +import { useAttributeCreateMutation } from "../../mutations"; import { attributeAddUrl, + AttributeAddUrlDialog, AttributeAddUrlQueryParams, attributeListUrl, - attributeUrl, - AttributeAddUrlDialog + attributeUrl } from "../../urls"; interface AttributeDetailsProps { @@ -60,6 +66,22 @@ const AttributeDetails: React.FC = ({ params }) => { [] ); + const [attributeCreate, attributeCreateOpts] = useAttributeCreateMutation({ + onCompleted: data => { + if (data.attributeCreate.errors.length === 0) { + notify({ + status: "success", + text: intl.formatMessage({ + defaultMessage: "Successfully created attribute" + }) + }); + navigate(attributeUrl(data.attributeCreate.attribute.id)); + } + } + }); + const [updateMetadata] = useMetadataUpdate({}); + const [updatePrivateMetadata] = usePrivateMetadataUpdate({}); + const id = params.id ? parseInt(params.id, 0) : undefined; const [openModal, closeModal] = createDialogActionHandlers< @@ -73,16 +95,6 @@ const AttributeDetails: React.FC = ({ params }) => { setValues(remove(values[params.id], values, areValuesEqual)); closeModal(); }; - const handleCreate = (data: AttributeCreate) => { - if (data.attributeCreate.errors.length === 0) { - notify({ - text: intl.formatMessage({ - defaultMessage: "Successfully created attribute" - }) - }); - navigate(attributeUrl(data.attributeCreate.attribute.id)); - } - }; const handleValueUpdate = (input: AttributeValueEditDialogFormData) => { if (isSelected(input, values, areValuesEqual)) { setValueErrors([attributeValueAlreadyExistsError]); @@ -102,88 +114,94 @@ const AttributeDetails: React.FC = ({ params }) => { const handleValueReorder = ({ newIndex, oldIndex }: ReorderEvent) => setValues(move(values[oldIndex], values, areValuesEqual, newIndex)); + const handleCreate = async (data: AttributePageFormData) => { + const input = { + ...data, + metadata: undefined, + privateMetadata: undefined, + storefrontSearchPosition: parseInt(data.storefrontSearchPosition, 0), + values: values.map(value => ({ + name: value.name + })) + }; + + const result = await attributeCreate({ + variables: { + input + } + }); + + return result.data.attributeCreate?.attribute?.id || null; + }; + const handleSubmit = createMetadataCreateHandler( + handleCreate, + updateMetadata, + updatePrivateMetadata + ); + return ( - - {(attributeCreate, attributeCreateOpts) => ( + <> + navigate(attributeListUrl())} + onDelete={undefined} + onSubmit={handleSubmit} + onValueAdd={() => openModal("add-value")} + onValueDelete={id => + openModal("remove-value", { + id + }) + } + onValueReorder={handleValueReorder} + onValueUpdate={id => + openModal("edit-value", { + id + }) + } + saveButtonBarState={attributeCreateOpts.status} + values={values.map((value, valueIndex) => ({ + __typename: "AttributeValue" as "AttributeValue", + id: valueIndex.toString(), + slug: slugify(value.name).toLowerCase(), + sortOrder: valueIndex, + type: null, + value: null, + ...value + }))} + /> + + {values.length > 0 && ( <> - navigate(attributeListUrl())} - onDelete={undefined} - onSubmit={input => - attributeCreate({ - variables: { - input: { - ...input, - storefrontSearchPosition: parseInt( - input.storefrontSearchPosition, - 0 - ), - values: values.map(value => ({ - name: value.name - })) - } - } - }) - } - onValueAdd={() => openModal("add-value")} - onValueDelete={id => - openModal("remove-value", { - id - }) - } - onValueReorder={handleValueReorder} - onValueUpdate={id => - openModal("edit-value", { - id - }) - } - saveButtonBarState={attributeCreateOpts.status} - values={values.map((value, valueIndex) => ({ - __typename: "AttributeValue" as "AttributeValue", - id: valueIndex.toString(), - slug: slugify(value.name).toLowerCase(), - sortOrder: valueIndex, - type: null, - value: null, - ...value - }))} + - {values.length > 0 && ( - <> - values[id].name, "...")} - confirmButtonState="default" - onClose={closeModal} - onConfirm={handleValueDelete} - /> - values[params.id])} - confirmButtonState="default" - disabled={false} - errors={valueErrors} - open={params.action === "edit-value"} - onClose={closeModal} - onSubmit={handleValueUpdate} - /> - - )} )} - + ); }; AttributeDetails.displayName = "AttributeDetails"; diff --git a/src/attributes/views/AttributeDetails/AttributeDetails.tsx b/src/attributes/views/AttributeDetails/AttributeDetails.tsx index 2c00bb10d..b6951a2ce 100644 --- a/src/attributes/views/AttributeDetails/AttributeDetails.tsx +++ b/src/attributes/views/AttributeDetails/AttributeDetails.tsx @@ -1,38 +1,39 @@ -import React from "react"; -import { useIntl } from "react-intl"; - import useNavigator from "@saleor/hooks/useNavigator"; import useNotifier from "@saleor/hooks/useNotifier"; import { commonMessages } from "@saleor/intl"; import { maybe } from "@saleor/misc"; import { ReorderEvent } from "@saleor/types"; -import { move } from "@saleor/utils/lists"; -import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; import { getProductErrorMessage } from "@saleor/utils/errors"; +import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; +import createMetadataUpdateHandler from "@saleor/utils/handlers/metadataUpdateHandler"; +import { move } from "@saleor/utils/lists"; +import { + useMetadataUpdate, + usePrivateMetadataUpdate +} from "@saleor/utils/metadata/updateMetadata"; +import React from "react"; +import { useIntl } from "react-intl"; + import AttributeDeleteDialog from "../../components/AttributeDeleteDialog"; -import AttributePage from "../../components/AttributePage"; +import AttributePage, { + AttributePageFormData +} from "../../components/AttributePage"; import AttributeValueDeleteDialog from "../../components/AttributeValueDeleteDialog"; import AttributeValueEditDialog from "../../components/AttributeValueEditDialog"; import { - AttributeDeleteMutation, - AttributeUpdateMutation, - AttributeValueCreateMutation, - AttributeValueDeleteMutation, - AttributeValueReorderMutation, - AttributeValueUpdateMutation + useAttributeDeleteMutation, + useAttributeUpdateMutation, + useAttributeValueCreateMutation, + useAttributeValueDeleteMutation, + useAttributeValueReorderMutation, + useAttributeValueUpdateMutation } from "../../mutations"; -import { AttributeDetailsQuery } from "../../queries"; -import { AttributeDelete } from "../../types/AttributeDelete"; -import { AttributeUpdate } from "../../types/AttributeUpdate"; -import { AttributeValueCreate } from "../../types/AttributeValueCreate"; -import { AttributeValueDelete } from "../../types/AttributeValueDelete"; -import { AttributeValueReorder } from "../../types/AttributeValueReorder"; -import { AttributeValueUpdate } from "../../types/AttributeValueUpdate"; +import { useAttributeDetailsQuery } from "../../queries"; import { attributeListUrl, attributeUrl, - AttributeUrlQueryParams, - AttributeUrlDialog + AttributeUrlDialog, + AttributeUrlQueryParams } from "../../urls"; interface AttributeDetailsProps { @@ -44,275 +45,258 @@ const AttributeDetails: React.FC = ({ id, params }) => { const navigate = useNavigator(); const notify = useNotifier(); const intl = useIntl(); + const [updateMetadata] = useMetadataUpdate({}); + const [updatePrivateMetadata] = usePrivateMetadataUpdate({}); const [openModal, closeModal] = createDialogActionHandlers< AttributeUrlDialog, AttributeUrlQueryParams >(navigate, params => attributeUrl(id, params), params); - const handleDelete = (data: AttributeDelete) => { - if (data.attributeDelete.errors.length === 0) { - notify({ - text: intl.formatMessage({ - defaultMessage: "Attribute deleted" - }) - }); - navigate(attributeListUrl()); + const { data, loading } = useAttributeDetailsQuery({ + variables: { + id } - }; - const handleValueDelete = (data: AttributeValueDelete) => { - if (data.attributeValueDelete.errors.length === 0) { - notify({ - text: intl.formatMessage({ - defaultMessage: "Value deleted", - description: "attribute value deleted" - }) - }); - closeModal(); + }); + + const [attributeDelete, attributeDeleteOpts] = useAttributeDeleteMutation({ + onCompleted: data => { + if (data.attributeDelete.errors.length === 0) { + notify({ + status: "success", + text: intl.formatMessage({ + defaultMessage: "Attribute deleted" + }) + }); + navigate(attributeListUrl()); + } } - }; - const handleUpdate = (data: AttributeUpdate) => { - if (data.attributeUpdate.errors.length === 0) { - notify({ text: intl.formatMessage(commonMessages.savedChanges) }); + }); + + const [ + attributeValueDelete, + attributeValueDeleteOpts + ] = useAttributeValueDeleteMutation({ + onCompleted: data => { + if (data.attributeValueDelete.errors.length === 0) { + notify({ + status: "success", + text: intl.formatMessage({ + defaultMessage: "Value deleted", + description: "attribute value deleted" + }) + }); + closeModal(); + } } - }; - const handleValueUpdate = (data: AttributeValueUpdate) => { - if (data.attributeValueUpdate.errors.length === 0) { - notify({ text: intl.formatMessage(commonMessages.savedChanges) }); - closeModal(); + }); + + const [ + attributeValueUpdate, + attributeValueUpdateOpts + ] = useAttributeValueUpdateMutation({ + onCompleted: data => { + if (data.attributeValueUpdate.errors.length === 0) { + notify({ + status: "success", + text: intl.formatMessage(commonMessages.savedChanges) + }); + closeModal(); + } } - }; - const handleValueCreate = (data: AttributeValueCreate) => { - if (data.attributeValueCreate.errors.length === 0) { - notify({ - text: intl.formatMessage({ - defaultMessage: "Added new value", - description: "added new attribute value" - }) - }); - closeModal(); + }); + + const [attributeUpdate, attributeUpdateOpts] = useAttributeUpdateMutation({ + onCompleted: data => { + if (data.attributeUpdate.errors.length === 0) { + notify({ + status: "success", + text: intl.formatMessage(commonMessages.savedChanges) + }); + } } - }; - const handleValueReorderMutation = (data: AttributeValueReorder) => { - if (data.attributeReorderValues.errors.length !== 0) { - notify({ - text: getProductErrorMessage( - data.attributeReorderValues.errors[0], - intl - ) - }); + }); + + const [ + attributeValueCreate, + attributeValueCreateOpts + ] = useAttributeValueCreateMutation({ + onCompleted: data => { + if (data.attributeValueCreate.errors.length === 0) { + notify({ + status: "success", + text: intl.formatMessage({ + defaultMessage: "Added new value", + description: "added new attribute value" + }) + }); + closeModal(); + } } + }); + + const [attributeValueReorder] = useAttributeValueReorderMutation({ + onCompleted: data => { + if (data.attributeReorderValues.errors.length !== 0) { + notify({ + status: "error", + text: getProductErrorMessage( + data.attributeReorderValues.errors[0], + intl + ) + }); + } + } + }); + + const handleValueReorder = ({ newIndex, oldIndex }: ReorderEvent) => + attributeValueReorder({ + optimisticResponse: { + attributeReorderValues: { + __typename: "AttributeReorderValues", + attribute: { + ...data.attribute, + values: move( + data.attribute.values[oldIndex], + data.attribute.values, + (a, b) => a.id === b.id, + newIndex + ) + }, + errors: [] + } + }, + variables: { + id, + move: { + id: data.attribute.values[oldIndex].id, + sortOrder: newIndex - oldIndex + } + } + }); + + const handleUpdate = async (data: AttributePageFormData) => { + const input = { + ...data, + inputType: undefined, + metadata: undefined, + privateMetadata: undefined, + storefrontSearchPosition: parseInt(data.storefrontSearchPosition, 0) + }; + + const result = await attributeUpdate({ + variables: { + id, + input + } + }); + + return result.data.attributeUpdate.errors; }; + const handleSubmit = createMetadataUpdateHandler( + data?.attribute, + handleUpdate, + variables => updateMetadata({ variables }), + variables => updatePrivateMetadata({ variables }) + ); + return ( - - {({ data, loading }) => ( - - {(attributeDelete, attributeDeleteOpts) => ( - - {(attributeValueDelete, attributeValueDeleteOpts) => ( - - {(attributeUpdate, attributeUpdateOpts) => ( - - {(attributeValueUpdate, attributeValueUpdateOpts) => ( - - {(attributeValueCreate, attributeValueCreateOpts) => ( - - {attributeValueReorder => { - const handleValueReorder = ({ - newIndex, - oldIndex - }: ReorderEvent) => - attributeValueReorder({ - optimisticResponse: { - attributeReorderValues: { - __typename: "AttributeReorderValues", - attribute: { - ...data.attribute, - values: move( - data.attribute.values[oldIndex], - data.attribute.values, - (a, b) => a.id === b.id, - newIndex - ) - }, - errors: [] - } - }, - variables: { - id, - move: { - id: data.attribute.values[oldIndex].id, - sortOrder: newIndex - oldIndex - } - } - }); - - return ( - <> - data.attribute)} - disabled={loading} - errors={ - attributeUpdateOpts.data - ?.attributeUpdate.errors || [] - } - onBack={() => - navigate(attributeListUrl()) - } - onDelete={() => openModal("remove")} - onSubmit={data => { - const input = { - ...data, - inputType: undefined - }; - - attributeUpdate({ - variables: { - id, - input: { - ...input, - storefrontSearchPosition: parseInt( - input.storefrontSearchPosition, - 0 - ) - } - } - }); - }} - onValueAdd={() => openModal("add-value")} - onValueDelete={id => - openModal("remove-value", { - id - }) - } - onValueReorder={handleValueReorder} - onValueUpdate={id => - openModal("edit-value", { - id - }) - } - saveButtonBarState={ - attributeUpdateOpts.status - } - values={maybe( - () => data.attribute.values - )} - /> - data.attribute.name, - "..." - )} - confirmButtonState={ - attributeDeleteOpts.status - } - onClose={closeModal} - onConfirm={() => - attributeDelete({ - variables: { - id - } - }) - } - /> - data.attribute.name, - "..." - )} - open={params.action === "remove-value"} - name={maybe( - () => - data.attribute.values.find( - value => params.id === value.id - ).name, - "..." - )} - useName={true} - confirmButtonState={ - attributeValueDeleteOpts.status - } - onClose={closeModal} - onConfirm={() => - attributeValueDelete({ - variables: { - id: params.id - } - }) - } - /> - - attributeValueCreate({ - variables: { - id, - input - } - }) - } - /> - - data.attribute.values.find( - value => params.id === value.id - ) - )} - confirmButtonState={ - attributeValueUpdateOpts.status - } - disabled={loading} - errors={ - attributeValueUpdateOpts.data - ?.attributeValueUpdate.errors || [] - } - open={params.action === "edit-value"} - onClose={closeModal} - onSubmit={input => - attributeValueUpdate({ - variables: { - id: data.attribute.values.find( - value => params.id === value.id - ).id, - input - } - }) - } - /> - - ); - }} - - )} - - )} - - )} - - )} - - )} - - )} - + <> + data.attribute)} + disabled={loading} + errors={attributeUpdateOpts.data?.attributeUpdate.errors || []} + onBack={() => navigate(attributeListUrl())} + onDelete={() => openModal("remove")} + onSubmit={handleSubmit} + onValueAdd={() => openModal("add-value")} + onValueDelete={id => + openModal("remove-value", { + id + }) + } + onValueReorder={handleValueReorder} + onValueUpdate={id => + openModal("edit-value", { + id + }) + } + saveButtonBarState={attributeUpdateOpts.status} + values={maybe(() => data.attribute.values)} + /> + data.attribute.name, "...")} + confirmButtonState={attributeDeleteOpts.status} + onClose={closeModal} + onConfirm={() => + attributeDelete({ + variables: { + id + } + }) + } + /> + data.attribute.name, "...")} + open={params.action === "remove-value"} + name={maybe( + () => + data.attribute.values.find(value => params.id === value.id).name, + "..." + )} + useName={true} + confirmButtonState={attributeValueDeleteOpts.status} + onClose={closeModal} + onConfirm={() => + attributeValueDelete({ + variables: { + id: params.id + } + }) + } + /> + + attributeValueCreate({ + variables: { + id, + input + } + }) + } + /> + + data.attribute.values.find(value => params.id === value.id) + )} + confirmButtonState={attributeValueUpdateOpts.status} + disabled={loading} + errors={ + attributeValueUpdateOpts.data?.attributeValueUpdate.errors || [] + } + open={params.action === "edit-value"} + onClose={closeModal} + onSubmit={input => + attributeValueUpdate({ + variables: { + id: data.attribute.values.find(value => params.id === value.id) + .id, + input + } + }) + } + /> + ); }; AttributeDetails.displayName = "AttributeDetails"; diff --git a/src/attributes/views/AttributeList/AttributeList.tsx b/src/attributes/views/AttributeList/AttributeList.tsx index 63defa847..d71bd2907 100644 --- a/src/attributes/views/AttributeList/AttributeList.tsx +++ b/src/attributes/views/AttributeList/AttributeList.tsx @@ -1,16 +1,13 @@ import IconButton from "@material-ui/core/IconButton"; import DeleteIcon from "@material-ui/icons/Delete"; -import React from "react"; -import { useIntl } from "react-intl"; - import { areFiltersApplied, deleteFilterTab, getActiveFilters, + getFilterOpts, getFilterTabs, getFilterVariables, - saveFilterTab, - getFilterOpts + saveFilterTab } from "@saleor/attributes/views/AttributeList/filters"; import DeleteFilterTabDialog from "@saleor/components/DeleteFilterTabDialog"; import SaveFilterTabDialog, { @@ -22,28 +19,30 @@ import useNotifier from "@saleor/hooks/useNotifier"; import usePaginator, { createPaginationState } from "@saleor/hooks/usePaginator"; -import { getSortParams } from "@saleor/utils/sort"; -import createSortHandler from "@saleor/utils/handlers/sortHandler"; +import useShop from "@saleor/hooks/useShop"; import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; import createFilterHandlers from "@saleor/utils/handlers/filterHandlers"; -import useShop from "@saleor/hooks/useShop"; +import createSortHandler from "@saleor/utils/handlers/sortHandler"; +import { getSortParams } from "@saleor/utils/sort"; +import React from "react"; +import { useIntl } from "react-intl"; + import { PAGINATE_BY } from "../../../config"; import useBulkActions from "../../../hooks/useBulkActions"; import { maybe } from "../../../misc"; import AttributeBulkDeleteDialog from "../../components/AttributeBulkDeleteDialog"; import AttributeListPage from "../../components/AttributeListPage"; -import { AttributeBulkDeleteMutation } from "../../mutations"; +import { useAttributeBulkDeleteMutation } from "../../mutations"; import { useAttributeListQuery } from "../../queries"; -import { AttributeBulkDelete } from "../../types/AttributeBulkDelete"; import { attributeAddUrl, attributeListUrl, + AttributeListUrlDialog, AttributeListUrlQueryParams, - attributeUrl, - AttributeListUrlDialog + attributeUrl } from "../../urls"; -import { getSortQueryVariables } from "./sort"; import { getFilterQueryParam } from "./filters"; +import { getSortQueryVariables } from "./sort"; interface AttributeListProps { params: AttributeListUrlQueryParams; @@ -72,6 +71,26 @@ const AttributeList: React.FC = ({ params }) => { variables: queryVariables }); + const [ + attributeBulkDelete, + attributeBulkDeleteOpts + ] = useAttributeBulkDeleteMutation({ + onCompleted: data => { + if (data.attributeBulkDelete.errors.length === 0) { + closeModal(); + notify({ + status: "success", + text: intl.formatMessage({ + defaultMessage: "Attributes successfully delete", + description: "deleted multiple attributes" + }) + }); + reset(); + refetch(); + } + } + }); + const tabs = getFilterTabs(); const currentTab = @@ -125,95 +144,73 @@ const AttributeList: React.FC = ({ params }) => { params ); - const handleBulkDelete = (data: AttributeBulkDelete) => { - if (data.attributeBulkDelete.errors.length === 0) { - closeModal(); - notify({ - text: intl.formatMessage({ - defaultMessage: "Attributes successfully delete", - description: "deleted multiple attributes" - }) - }); - reset(); - refetch(); - } - }; - const handleSort = createSortHandler(navigate, attributeListUrl, params); const currencySymbol = maybe(() => shop.defaultCurrency, "USD"); return ( - - {(attributeBulkDelete, attributeBulkDeleteOpts) => ( - <> - - data.attributes.edges.map(edge => edge.node) - )} - currencySymbol={currencySymbol} - currentTab={currentTab} - disabled={loading || attributeBulkDeleteOpts.loading} - filterOpts={getFilterOpts(params)} - initialSearch={params.query || ""} - isChecked={isSelected} - onAdd={() => navigate(attributeAddUrl())} - onAll={resetFilters} - onBack={() => navigate(configurationMenuUrl)} - onFilterChange={changeFilters} - onNextPage={loadNextPage} - onPreviousPage={loadPreviousPage} - onRowClick={id => () => navigate(attributeUrl(id))} - onSearchChange={handleSearchChange} - onSort={handleSort} - onTabChange={handleTabChange} - onTabDelete={() => openModal("delete-search")} - onTabSave={() => openModal("save-search")} - pageInfo={pageInfo} - selected={listElements.length} - sort={getSortParams(params)} - tabs={tabs.map(tab => tab.name)} - toggle={toggle} - toggleAll={toggleAll} - toolbar={ - - openModal("remove", { - ids: listElements - }) - } - > - - + <> + data.attributes.edges.map(edge => edge.node))} + currencySymbol={currencySymbol} + currentTab={currentTab} + disabled={loading || attributeBulkDeleteOpts.loading} + filterOpts={getFilterOpts(params)} + initialSearch={params.query || ""} + isChecked={isSelected} + onAdd={() => navigate(attributeAddUrl())} + onAll={resetFilters} + onBack={() => navigate(configurationMenuUrl)} + onFilterChange={changeFilters} + onNextPage={loadNextPage} + onPreviousPage={loadPreviousPage} + onRowClick={id => () => navigate(attributeUrl(id))} + onSearchChange={handleSearchChange} + onSort={handleSort} + onTabChange={handleTabChange} + onTabDelete={() => openModal("delete-search")} + onTabSave={() => openModal("save-search")} + pageInfo={pageInfo} + selected={listElements.length} + sort={getSortParams(params)} + tabs={tabs.map(tab => tab.name)} + toggle={toggle} + toggleAll={toggleAll} + toolbar={ + + openModal("remove", { + ids: listElements + }) } - /> - params.ids.length > 0) - } - onConfirm={() => - attributeBulkDelete({ variables: { ids: params.ids } }) - } - onClose={closeModal} - quantity={maybe(() => params.ids.length)} - /> - - tabs[currentTab - 1].name, "...")} - /> - - )} - + > + + + } + /> + params.ids.length > 0)} + onConfirm={() => + attributeBulkDelete({ variables: { ids: params.ids } }) + } + onClose={closeModal} + quantity={maybe(() => params.ids.length)} + /> + + tabs[currentTab - 1].name, "...")} + /> + ); }; AttributeList.displayName = "AttributeList"; diff --git a/src/attributes/views/AttributeList/filters.test.ts b/src/attributes/views/AttributeList/filters.test.ts index 5a50d1f1c..e939c4326 100644 --- a/src/attributes/views/AttributeList/filters.test.ts +++ b/src/attributes/views/AttributeList/filters.test.ts @@ -1,12 +1,12 @@ -import { createIntl } from "react-intl"; -import { stringify as stringifyQs } from "qs"; - -import { AttributeListUrlFilters } from "@saleor/attributes/urls"; import { createFilterStructure } from "@saleor/attributes/components/AttributeListPage"; +import { AttributeListUrlFilters } from "@saleor/attributes/urls"; import { getFilterQueryParams } from "@saleor/utils/filters"; -import { config } from "@test/intl"; import { getExistingKeys, setFilterOptsStatus } from "@test/filters"; -import { getFilterVariables, getFilterQueryParam } from "./filters"; +import { config } from "@test/intl"; +import { stringify as stringifyQs } from "qs"; +import { createIntl } from "react-intl"; + +import { getFilterQueryParam, getFilterVariables } from "./filters"; describe("Filtering query params", () => { it("should be empty object if no params given", () => { diff --git a/src/attributes/views/AttributeList/filters.ts b/src/attributes/views/AttributeList/filters.ts index 5c39a51ca..ac8a3a961 100644 --- a/src/attributes/views/AttributeList/filters.ts +++ b/src/attributes/views/AttributeList/filters.ts @@ -1,10 +1,11 @@ -import { AttributeFilterInput } from "@saleor/types/globalTypes"; -import { maybe, parseBoolean } from "@saleor/misc"; -import { IFilterElement } from "@saleor/components/Filter"; import { - AttributeListFilterOpts, - AttributeFilterKeys + AttributeFilterKeys, + AttributeListFilterOpts } from "@saleor/attributes/components/AttributeListPage"; +import { IFilterElement } from "@saleor/components/Filter"; +import { maybe, parseBoolean } from "@saleor/misc"; +import { AttributeFilterInput } from "@saleor/types/globalTypes"; + import { createFilterTabUtils, createFilterUtils, @@ -16,7 +17,7 @@ import { AttributeListUrlQueryParams } from "../../urls"; -export const PRODUCT_FILTERS_KEY = "productFilters"; +export const ATTRIBUTE_FILTERS_KEY = "attributeFilters"; export function getFilterOpts( params: AttributeListUrlFilters @@ -129,7 +130,7 @@ export const { deleteFilterTab, getFilterTabs, saveFilterTab -} = createFilterTabUtils(PRODUCT_FILTERS_KEY); +} = createFilterTabUtils(ATTRIBUTE_FILTERS_KEY); export const { areFiltersApplied, getActiveFilters } = createFilterUtils< AttributeListUrlQueryParams, diff --git a/src/auth/AuthProvider.test.ts b/src/auth/AuthProvider.test.ts new file mode 100644 index 000000000..c9d82f557 --- /dev/null +++ b/src/auth/AuthProvider.test.ts @@ -0,0 +1,77 @@ +import setupApi from "@test/api"; +import { act, renderHook } from "@testing-library/react-hooks"; +import ApolloClient from "apollo-client"; + +import { useAuthProvider } from "./AuthProvider"; +import { getTokens, setAuthToken } from "./utils"; + +const apolloClient = setupApi(); + +function renderAuthProvider(apolloClient: ApolloClient) { + const intl = { + formatMessage: ({ defaultMessage }) => defaultMessage + }; + const notify = jest.fn(); + + const { result } = renderHook(() => + useAuthProvider(intl as any, notify, apolloClient) + ); + + return result; +} + +const credentials = { + email: "admin@example.com", + password: "admin", + token: null +}; + +beforeEach(() => { + localStorage.clear(); + sessionStorage.clear(); +}); + +describe("User", () => { + it("will be logged in if has valid credentials", async done => { + const hook = renderAuthProvider(apolloClient); + + await act(() => + hook.current.login(credentials.email, credentials.password) + ); + expect(hook.current.userContext.email).toBe(credentials.email); + credentials.token = getTokens().auth; + + done(); + }); + + it("will not be logged in if doesn't have valid credentials", async done => { + const hook = renderAuthProvider(apolloClient); + + await act(() => + hook.current.login(credentials.email, "NotAValidPassword123!") + ); + expect(hook.current.userContext).toBe(null); + + done(); + }); + + it("will be logged if has valid token", async done => { + setAuthToken(credentials.token, false); + const hook = renderAuthProvider(apolloClient); + + await act(() => hook.current.autologinPromise.current); + expect(hook.current.userContext.email).toBe(credentials.email); + + done(); + }); + + it("will not be logged if has invalid token", async done => { + setAuthToken("NotAToken", false); + const hook = renderAuthProvider(apolloClient); + + await act(() => hook.current.autologinPromise.current); + expect(hook.current.userContext).toBe(undefined); + + done(); + }); +}); diff --git a/src/auth/AuthProvider.tsx b/src/auth/AuthProvider.tsx index a99fc03e1..ad83dcea8 100644 --- a/src/auth/AuthProvider.tsx +++ b/src/auth/AuthProvider.tsx @@ -1,204 +1,227 @@ -import React from "react"; - +import { IMessageContext } from "@saleor/components/messages"; +import { DEMO_MODE } from "@saleor/config"; +import { User } from "@saleor/fragments/types/User"; +import useNotifier from "@saleor/hooks/useNotifier"; +import { getMutationStatus } from "@saleor/misc"; import { isSupported as isCredentialsManagementAPISupported, login as loginWithCredentialsManagementAPI, saveCredentials } from "@saleor/utils/credentialsManagement"; -import { MutationFunction, MutationResult } from "react-apollo"; -import { maybe } from "@saleor/misc"; -import { - TypedTokenAuthMutation, - TypedVerifyTokenMutation, - TokenRefreshMutation -} from "./mutations"; -import { TokenAuth, TokenAuthVariables } from "./types/TokenAuth"; -import { User } from "./types/User"; -import { VerifyToken, VerifyTokenVariables } from "./types/VerifyToken"; -import { getAuthToken, removeAuthToken, setAuthToken } from "./utils"; -import { RefreshToken, RefreshTokenVariables } from "./types/RefreshToken"; +import ApolloClient from "apollo-client"; +import React, { useContext, useEffect, useRef, useState } from "react"; +import { useApolloClient, useMutation } from "react-apollo"; +import { IntlShape, useIntl } from "react-intl"; + import { UserContext } from "./"; +import { + tokenAuthMutation, + tokenRefreshMutation, + tokenVerifyMutation +} from "./mutations"; +import { RefreshToken, RefreshTokenVariables } from "./types/RefreshToken"; +import { TokenAuth, TokenAuthVariables } from "./types/TokenAuth"; +import { VerifyToken, VerifyTokenVariables } from "./types/VerifyToken"; +import { + displayDemoMessage, + getTokens, + removeTokens, + setAuthToken, + setTokens +} from "./utils"; -interface AuthProviderOperationsProps { - children: (props: { - hasToken: boolean; - isAuthenticated: boolean; - tokenAuthLoading: boolean; - tokenVerifyLoading: boolean; - user: User; - }) => React.ReactNode; -} -const AuthProviderOperations: React.FC = ({ - children -}) => ( - - {(...tokenAuth) => ( - - {(...tokenVerify) => ( - - {(...tokenRefresh) => ( - - {children} - - )} - - )} - - )} - -); +const persistToken = false; -interface AuthProviderProps { - children: (props: { - hasToken: boolean; - isAuthenticated: boolean; - tokenAuthLoading: boolean; - tokenVerifyLoading: boolean; - user: User; - }) => React.ReactNode; - tokenAuth: [ - MutationFunction, - MutationResult - ]; - tokenVerify: [ - MutationFunction, - MutationResult - ]; - tokenRefresh: [ - MutationFunction, - MutationResult - ]; -} +export function useAuthProvider( + intl: IntlShape, + notify: IMessageContext, + apolloClient: ApolloClient +) { + const [userContext, setUserContext] = useState(undefined); + const autologinPromise = useRef>(); + const refreshPromise = useRef>(); -interface AuthProviderState { - user: User; - persistToken: boolean; -} - -class AuthProvider extends React.Component< - AuthProviderProps, - AuthProviderState -> { - constructor(props) { - super(props); - this.state = { persistToken: false, user: undefined }; - } - - componentWillReceiveProps(props: AuthProviderProps) { - const { tokenAuth, tokenVerify } = props; - const tokenAuthOpts = tokenAuth[1]; - const tokenVerifyOpts = tokenVerify[1]; - - if (tokenAuthOpts.error || tokenVerifyOpts.error) { - this.logout(); - } - if (tokenAuthOpts.data) { - const user = tokenAuthOpts.data.tokenCreate.user; - // FIXME: Now we set state also when auth fails and returned user is - // `null`, because the LoginView uses this `null` to display error. - this.setState({ user }); - if (user) { - setAuthToken( - tokenAuthOpts.data.tokenCreate.token, - this.state.persistToken - ); - } - } else { - if (maybe(() => tokenVerifyOpts.data.tokenVerify === null)) { - this.logout(); - } else { - const user = maybe(() => tokenVerifyOpts.data.tokenVerify.user); - if (!!user) { - this.setState({ user }); - } - } - } - } - - componentDidMount() { - const { user } = this.state; - const token = getAuthToken(); - if (!!token && !user) { - this.verifyToken(token); - } else { - loginWithCredentialsManagementAPI(this.login); - } - } - - login = async (email: string, password: string) => { - const { tokenAuth } = this.props; - const [tokenAuthFn] = tokenAuth; - - tokenAuthFn({ variables: { email, password } }).then(result => { - if (result && !result.data.tokenCreate.errors.length) { - saveCredentials(result.data.tokenCreate.user, password); - } - }); - }; - - loginByToken = (token: string, user: User) => { - this.setState({ user }); - setAuthToken(token, this.state.persistToken); - }; - - logout = () => { - this.setState({ user: undefined }); + const logout = () => { + setUserContext(undefined); if (isCredentialsManagementAPISupported) { navigator.credentials.preventSilentAccess(); } - removeAuthToken(); + removeTokens(); }; - verifyToken = (token: string) => { - const { tokenVerify } = this.props; - const [tokenVerifyFn] = tokenVerify; + const [tokenAuth, tokenAuthResult] = useMutation< + TokenAuth, + TokenAuthVariables + >(tokenAuthMutation, { + client: apolloClient, + onCompleted: result => { + if (result.tokenCreate.errors.length > 0) { + logout(); + } - return tokenVerifyFn({ variables: { token } }); + const user = result.tokenCreate.user; + + // FIXME: Now we set state also when auth fails and returned user is + // `null`, because the LoginView uses this `null` to display error. + setUserContext(user); + if (user) { + setTokens( + result.tokenCreate.token, + result.tokenCreate.csrfToken, + persistToken + ); + } + }, + onError: logout + }); + const [tokenRefresh] = useMutation( + tokenRefreshMutation, + { + client: apolloClient, + onError: logout + } + ); + const [tokenVerify, tokenVerifyResult] = useMutation< + VerifyToken, + VerifyTokenVariables + >(tokenVerifyMutation, { + client: apolloClient, + onCompleted: result => { + if (result.tokenVerify === null) { + logout(); + } else { + const user = result.tokenVerify?.user; + + if (!!user) { + setUserContext(user); + } + } + }, + onError: logout + }); + + const tokenAuthOpts = { + ...tokenAuthResult, + status: getMutationStatus(tokenAuthResult) + }; + const tokenVerifyOpts = { + ...tokenVerifyResult, + status: getMutationStatus(tokenVerifyResult) }; - refreshToken = async () => { - const { tokenRefresh } = this.props; - const [tokenRefreshFn] = tokenRefresh; - const token = getAuthToken(); - - const refreshData = await tokenRefreshFn({ variables: { token } }); - - setAuthToken(refreshData.data.tokenRefresh.token, this.state.persistToken); + const onLogin = () => { + if (DEMO_MODE) { + displayDemoMessage(intl, notify); + } }; - render() { - const { children, tokenAuth, tokenVerify } = this.props; - const tokenAuthOpts = tokenAuth[1]; - const tokenVerifyOpts = tokenVerify[1]; - const { user } = this.state; - const isAuthenticated = !!user; + useEffect(() => { + const token = getTokens().auth; + if (!!token && !userContext) { + autologinPromise.current = tokenVerify({ variables: { token } }); + } else { + autologinPromise.current = loginWithCredentialsManagementAPI(login); + } + }, []); - return ( - - {children({ - hasToken: !!getAuthToken(), - isAuthenticated, - tokenAuthLoading: tokenAuthOpts.loading, - tokenVerifyLoading: tokenVerifyOpts.loading, - user - })} - - ); - } + const login = async (email: string, password: string) => { + const result = await tokenAuth({ variables: { email, password } }); + + if (result && !result.data.tokenCreate.errors.length) { + if (!!onLogin) { + onLogin(); + } + saveCredentials(result.data.tokenCreate.user, password); + + return result.data.tokenCreate.user; + } + + return null; + }; + + const loginByToken = (auth: string, refresh: string, user: User) => { + setUserContext(user); + setTokens(auth, refresh, persistToken); + }; + + const refreshToken = (): Promise => { + if (!!refreshPromise.current) { + return refreshPromise.current; + } + + return new Promise(resolve => { + const token = getTokens().refresh; + + return tokenRefresh({ variables: { token } }).then(refreshData => { + if (!!refreshData.data.tokenRefresh?.token) { + setAuthToken(refreshData.data.tokenRefresh.token, persistToken); + return resolve(true); + } + + return resolve(false); + }); + }); + }; + + return { + autologinPromise, + login, + loginByToken, + logout, + refreshToken, + tokenAuthOpts, + tokenVerifyOpts, + userContext + }; } -export default AuthProviderOperations; +interface AuthProviderProps { + children: React.ReactNode; +} + +const AuthProvider: React.FC = ({ children }) => { + const apolloClient = useApolloClient(); + const intl = useIntl(); + const notify = useNotifier(); + + const { + login, + loginByToken, + logout, + tokenAuthOpts, + refreshToken, + tokenVerifyOpts, + userContext + } = useAuthProvider(intl, notify, apolloClient); + + return ( + + {children} + + ); +}; + +export const useAuth = () => { + const user = useContext(UserContext); + const isAuthenticated = !!user.user; + + return { + hasToken: !!getTokens(), + isAuthenticated, + tokenAuthLoading: user.tokenAuthLoading, + tokenVerifyLoading: user.tokenVerifyLoading, + user: user.user + }; +}; + +export default AuthProvider; diff --git a/src/auth/components/Layout.tsx b/src/auth/components/Layout.tsx index 8a8d9edb7..2be8f3ea1 100644 --- a/src/auth/components/Layout.tsx +++ b/src/auth/components/Layout.tsx @@ -1,11 +1,10 @@ -import { makeStyles } from "@material-ui/core/styles"; -import React from "react"; -import SVG from "react-inlinesvg"; - import backgroundArt from "@assets/images/login-background.svg"; import saleorDarkLogo from "@assets/images/logo-dark.svg"; import saleorLightLogo from "@assets/images/logo-light.svg"; +import { makeStyles } from "@material-ui/core/styles"; import useTheme from "@saleor/hooks/useTheme"; +import React from "react"; +import SVG from "react-inlinesvg"; const useStyles = makeStyles( theme => ({ diff --git a/src/auth/components/LoginPage/LoginPage.tsx b/src/auth/components/LoginPage/LoginPage.tsx index fc68ed093..700a9d0f4 100644 --- a/src/auth/components/LoginPage/LoginPage.tsx +++ b/src/auth/components/LoginPage/LoginPage.tsx @@ -2,12 +2,12 @@ import Button from "@material-ui/core/Button"; import { makeStyles } from "@material-ui/core/styles"; import TextField from "@material-ui/core/TextField"; import Typography from "@material-ui/core/Typography"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import Form from "@saleor/components/Form"; import { FormSpacer } from "@saleor/components/FormSpacer"; +import { DEMO_MODE } from "@saleor/config"; import { commonMessages } from "@saleor/intl"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; export interface FormData { email: string; @@ -54,12 +54,20 @@ const LoginCard: React.FC = props => { const classes = useStyles(props); const intl = useIntl(); + let initialFormData = { email: "", password: "" }; + if (DEMO_MODE) { + initialFormData = { + email: "admin@example.com", + password: "admin" + }; + } + return ( -
+ {({ change: handleChange, data, submit: handleSubmit }) => ( <> {error && ( -
+
@@ -74,7 +82,7 @@ const LoginCard: React.FC = props => { onChange={handleChange} value={data.email} inputProps={{ - "data-tc": "email" + "data-test": "email" }} /> @@ -89,7 +97,7 @@ const LoginCard: React.FC = props => { type="password" value={data.password} inputProps={{ - "data-tc": "password" + "data-test": "password" }} /> @@ -101,7 +109,7 @@ const LoginCard: React.FC = props => { variant="contained" onClick={handleSubmit} type="submit" - data-tc="submit" + data-test="submit" > diff --git a/src/auth/components/NewPasswordPage/NewPasswordPage.stories.tsx b/src/auth/components/NewPasswordPage/NewPasswordPage.stories.tsx index 36e2e3cf4..293200bc1 100644 --- a/src/auth/components/NewPasswordPage/NewPasswordPage.stories.tsx +++ b/src/auth/components/NewPasswordPage/NewPasswordPage.stories.tsx @@ -1,9 +1,9 @@ -import { storiesOf } from "@storybook/react"; -import React from "react"; - import CardDecorator from "@saleor/storybook//CardDecorator"; import Decorator from "@saleor/storybook//Decorator"; import { AccountErrorCode } from "@saleor/types/globalTypes"; +import { storiesOf } from "@storybook/react"; +import React from "react"; + import NewPasswordPage from "./NewPasswordPage"; storiesOf("Views / Authentication / Set up a new password", module) diff --git a/src/auth/components/NewPasswordPage/NewPasswordPage.tsx b/src/auth/components/NewPasswordPage/NewPasswordPage.tsx index 2dfd65389..ba9966675 100644 --- a/src/auth/components/NewPasswordPage/NewPasswordPage.tsx +++ b/src/auth/components/NewPasswordPage/NewPasswordPage.tsx @@ -2,13 +2,12 @@ import Button from "@material-ui/core/Button"; import { makeStyles } from "@material-ui/core/styles"; import TextField from "@material-ui/core/TextField"; import Typography from "@material-ui/core/Typography"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - +import { SetPassword_setPassword_errors } from "@saleor/auth/types/SetPassword"; import Form from "@saleor/components/Form"; import FormSpacer from "@saleor/components/FormSpacer"; -import { SetPassword_setPassword_errors } from "@saleor/auth/types/SetPassword"; import getAccountErrorMessage from "@saleor/utils/errors/account"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; const useStyles = makeStyles( theme => ({ @@ -87,7 +86,7 @@ const NewPasswordPage: React.FC = props => { type="password" value={data.password} inputProps={{ - "data-tc": "password" + "data-test": "password" }} /> @@ -110,7 +109,7 @@ const NewPasswordPage: React.FC = props => { }) } inputProps={{ - "data-tc": "confirm-password" + "data-test": "confirm-password" }} /> diff --git a/src/auth/components/ResetPasswordPage/ResetPasswordPage.stories.tsx b/src/auth/components/ResetPasswordPage/ResetPasswordPage.stories.tsx index 4c4a495a8..ab28cbe46 100644 --- a/src/auth/components/ResetPasswordPage/ResetPasswordPage.stories.tsx +++ b/src/auth/components/ResetPasswordPage/ResetPasswordPage.stories.tsx @@ -1,9 +1,9 @@ -import { storiesOf } from "@storybook/react"; -import React from "react"; - import CardDecorator from "@saleor/storybook/CardDecorator"; import Decorator from "@saleor/storybook/Decorator"; import { formError } from "@saleor/storybook/misc"; +import { storiesOf } from "@storybook/react"; +import React from "react"; + import ResetPasswordPage, { ResetPasswordPageProps } from "./ResetPasswordPage"; const props: ResetPasswordPageProps = { diff --git a/src/auth/components/ResetPasswordPage/ResetPasswordPage.tsx b/src/auth/components/ResetPasswordPage/ResetPasswordPage.tsx index e5647a944..7502ec631 100644 --- a/src/auth/components/ResetPasswordPage/ResetPasswordPage.tsx +++ b/src/auth/components/ResetPasswordPage/ResetPasswordPage.tsx @@ -2,12 +2,11 @@ import Button from "@material-ui/core/Button"; import { makeStyles } from "@material-ui/core/styles"; import TextField from "@material-ui/core/TextField"; import Typography from "@material-ui/core/Typography"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import Form from "@saleor/components/Form"; import FormSpacer from "@saleor/components/FormSpacer"; import { commonMessages } from "@saleor/intl"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; const useStyles = makeStyles( theme => ({ @@ -69,7 +68,7 @@ const ResetPasswordPage: React.FC = props => { onChange={handleChange} value={data.email} inputProps={{ - "data-tc": "email" + "data-test": "email" }} /> diff --git a/src/auth/components/ResetPasswordSuccessPage/ResetPasswordSuccessPage.stories.tsx b/src/auth/components/ResetPasswordSuccessPage/ResetPasswordSuccessPage.stories.tsx index 3e263e929..a18ef5c0e 100644 --- a/src/auth/components/ResetPasswordSuccessPage/ResetPasswordSuccessPage.stories.tsx +++ b/src/auth/components/ResetPasswordSuccessPage/ResetPasswordSuccessPage.stories.tsx @@ -1,8 +1,8 @@ +import CardDecorator from "@saleor/storybook/CardDecorator"; +import Decorator from "@saleor/storybook/Decorator"; import { storiesOf } from "@storybook/react"; import React from "react"; -import CardDecorator from "@saleor/storybook/CardDecorator"; -import Decorator from "@saleor/storybook/Decorator"; import ResetPasswordSuccessPage from "./ResetPasswordSuccessPage"; storiesOf("Views / Authentication / Reset password success", module) diff --git a/src/auth/components/ResetPasswordSuccessPage/ResetPasswordSuccessPage.tsx b/src/auth/components/ResetPasswordSuccessPage/ResetPasswordSuccessPage.tsx index 52c7697ff..5cc95cb26 100644 --- a/src/auth/components/ResetPasswordSuccessPage/ResetPasswordSuccessPage.tsx +++ b/src/auth/components/ResetPasswordSuccessPage/ResetPasswordSuccessPage.tsx @@ -1,11 +1,10 @@ import Button from "@material-ui/core/Button"; import { makeStyles } from "@material-ui/core/styles"; import Typography from "@material-ui/core/Typography"; +import FormSpacer from "@saleor/components/FormSpacer"; import React from "react"; import { FormattedMessage } from "react-intl"; -import FormSpacer from "@saleor/components/FormSpacer"; - const useStyles = makeStyles( { submit: { @@ -24,9 +23,7 @@ export interface ResetPasswordSuccessPageProps { onBack: () => void; } -const ResetPasswordSuccessPage: React.FC< - ResetPasswordSuccessPageProps -> = props => { +const ResetPasswordSuccessPage: React.FC = props => { const { onBack } = props; const classes = useStyles(props); diff --git a/src/auth/components/SectionRoute.tsx b/src/auth/components/SectionRoute.tsx index f1b2d1546..332909a62 100644 --- a/src/auth/components/SectionRoute.tsx +++ b/src/auth/components/SectionRoute.tsx @@ -1,7 +1,7 @@ +import useUser from "@saleor/hooks/useUser"; import React from "react"; import { Route, RouteProps } from "react-router-dom"; -import useUser from "@saleor/hooks/useUser"; import NotFound from "../../NotFound"; import { PermissionEnum } from "../../types/globalTypes"; import { hasPermission } from "../misc"; diff --git a/src/auth/errors.ts b/src/auth/errors.ts index 61808e3b2..092f745d2 100644 --- a/src/auth/errors.ts +++ b/src/auth/errors.ts @@ -1,13 +1,21 @@ -import { GraphQLError } from "graphql"; import { findValueInEnum } from "@saleor/misc"; +import { GraphQLError } from "graphql"; export enum JWTError { - invalid = "JSONWebTokenError", - expired = "JSONWebTokenExpired" + invalid = "InvalidTokenError", + invalidSignature = "InvalidSignatureError", + expired = "ExpiredSignatureError" } export function isJwtError(error: GraphQLError): boolean { - return !!findValueInEnum(error.extensions.exception.code, JWTError); + let jwtError: boolean; + try { + jwtError = !!findValueInEnum(error.extensions.exception.code, JWTError); + } catch (e) { + jwtError = false; + } + + return jwtError; } export function isTokenExpired(error: GraphQLError): boolean { diff --git a/src/auth/index.tsx b/src/auth/index.tsx index 7eecf89d1..4865edc02 100644 --- a/src/auth/index.tsx +++ b/src/auth/index.tsx @@ -1,8 +1,8 @@ +import { User } from "@saleor/fragments/types/User"; import React from "react"; import { Route, Switch } from "react-router-dom"; import Layout from "./components/Layout"; -import { User } from "./types/User"; import { newPasswordPath, passwordResetPath, @@ -12,14 +12,13 @@ import LoginView from "./views/Login"; import NewPassword from "./views/NewPassword"; import ResetPassword from "./views/ResetPassword"; import ResetPasswordSuccess from "./views/ResetPasswordSuccess"; -import LoginLoading from "./components/LoginLoading"; interface UserContext { login: (username: string, password: string) => void; - loginByToken: (token: string, user: User) => void; + loginByToken: (auth: string, csrf: string, user: User) => void; logout: () => void; tokenAuthLoading: boolean; - tokenRefresh: () => Promise; + tokenRefresh: () => Promise; tokenVerifyLoading: boolean; user?: User; } @@ -33,20 +32,12 @@ export const UserContext = React.createContext({ tokenVerifyLoading: false }); -interface AuthRouterProps { - hasToken: boolean; -} - -const AuthRouter: React.FC = ({ hasToken }) => ( +const AuthRouter: React.FC = () => ( - {!hasToken ? ( - - ) : ( - - )} + diff --git a/src/auth/link.ts b/src/auth/link.ts new file mode 100644 index 000000000..306ef036f --- /dev/null +++ b/src/auth/link.ts @@ -0,0 +1,39 @@ +import { setContext } from "apollo-link-context"; +import { ErrorResponse, onError } from "apollo-link-error"; + +import { getTokens, removeTokens } from "./"; +import { isJwtError, JWTError } from "./errors"; + +interface ResponseError extends ErrorResponse { + networkError?: Error & { + statusCode?: number; + bodyText?: string; + }; +} + +export const invalidateTokenLink = onError((error: ResponseError) => { + if ( + (error.networkError && error.networkError.statusCode === 401) || + error.graphQLErrors?.some(isJwtError) + ) { + if (error.graphQLErrors[0].extensions.code !== JWTError.expired) { + removeTokens(); + } + } +}); + +export const tokenLink = setContext((_, context) => { + const authToken = getTokens().auth; + + return { + ...context, + headers: { + ...context.headers, + Authorization: authToken ? `JWT ${authToken}` : null + } + }; +}); + +const link = invalidateTokenLink.concat(tokenLink); + +export default link; diff --git a/src/auth/misc.ts b/src/auth/misc.ts index d886c35cb..a9e1392f6 100644 --- a/src/auth/misc.ts +++ b/src/auth/misc.ts @@ -1,5 +1,6 @@ +import { User } from "@saleor/fragments/types/User"; + import { PermissionEnum } from "../types/globalTypes"; -import { User } from "./types/User"; export const hasPermission = (permission: PermissionEnum, user: User) => user.userPermissions.map(perm => perm.code).includes(permission); diff --git a/src/auth/mutations.ts b/src/auth/mutations.ts index ef6152076..8c21ce32d 100644 --- a/src/auth/mutations.ts +++ b/src/auth/mutations.ts @@ -1,41 +1,24 @@ +import { fragmentUser } from "@saleor/fragments/auth"; +import { accountErrorFragment } from "@saleor/fragments/errors"; import gql from "graphql-tag"; -import { accountErrorFragment } from "@saleor/customers/mutations"; import { TypedMutation } from "../mutations"; import { RequestPasswordReset, RequestPasswordResetVariables } from "./types/RequestPasswordReset"; import { SetPassword, SetPasswordVariables } from "./types/SetPassword"; -import { TokenAuth, TokenAuthVariables } from "./types/TokenAuth"; -import { VerifyToken, VerifyTokenVariables } from "./types/VerifyToken"; -import { RefreshToken, RefreshTokenVariables } from "./types/RefreshToken"; - -export const fragmentUser = gql` - fragment User on User { - id - email - firstName - lastName - userPermissions { - code - name - } - avatar { - url - } - } -`; export const tokenAuthMutation = gql` ${fragmentUser} mutation TokenAuth($email: String!, $password: String!) { tokenCreate(email: $email, password: $password) { - token - errors { + errors: accountErrors { field message } + csrfToken + token user { ...User } @@ -43,11 +26,6 @@ export const tokenAuthMutation = gql` } `; -export const TypedTokenAuthMutation = TypedMutation< - TokenAuth, - TokenAuthVariables ->(tokenAuthMutation); - export const tokenVerifyMutation = gql` ${fragmentUser} mutation VerifyToken($token: String!) { @@ -60,10 +38,13 @@ export const tokenVerifyMutation = gql` } `; -export const TypedVerifyTokenMutation = TypedMutation< - VerifyToken, - VerifyTokenVariables ->(tokenVerifyMutation); +export const tokenRefreshMutation = gql` + mutation RefreshToken($token: String!) { + tokenRefresh(csrfToken: $token) { + token + } + } +`; export const requestPasswordReset = gql` ${accountErrorFragment} @@ -88,6 +69,8 @@ export const setPassword = gql` errors: accountErrors { ...AccountErrorFragment } + csrfToken + refreshToken token user { ...User @@ -99,16 +82,3 @@ export const SetPasswordMutation = TypedMutation< SetPassword, SetPasswordVariables >(setPassword); - -const refreshToken = gql` - mutation RefreshToken($token: String!) { - tokenRefresh(token: $token) { - token - payload - } - } -`; -export const TokenRefreshMutation = TypedMutation< - RefreshToken, - RefreshTokenVariables ->(refreshToken); diff --git a/src/auth/types/RefreshToken.ts b/src/auth/types/RefreshToken.ts index cbd3679b9..f4efc60fd 100644 --- a/src/auth/types/RefreshToken.ts +++ b/src/auth/types/RefreshToken.ts @@ -9,7 +9,6 @@ export interface RefreshToken_tokenRefresh { __typename: "RefreshToken"; token: string | null; - payload: any | null; } export interface RefreshToken { diff --git a/src/auth/types/SetPassword.ts b/src/auth/types/SetPassword.ts index 9a09baf70..0ede71f38 100644 --- a/src/auth/types/SetPassword.ts +++ b/src/auth/types/SetPassword.ts @@ -38,6 +38,8 @@ export interface SetPassword_setPassword_user { export interface SetPassword_setPassword { __typename: "SetPassword"; errors: SetPassword_setPassword_errors[]; + csrfToken: string | null; + refreshToken: string | null; token: string | null; user: SetPassword_setPassword_user | null; } diff --git a/src/auth/types/TokenAuth.ts b/src/auth/types/TokenAuth.ts index 8d72009a9..8da32e338 100644 --- a/src/auth/types/TokenAuth.ts +++ b/src/auth/types/TokenAuth.ts @@ -9,7 +9,7 @@ import { PermissionEnum } from "./../../types/globalTypes"; // ==================================================== export interface TokenAuth_tokenCreate_errors { - __typename: "Error"; + __typename: "AccountError"; field: string | null; message: string | null; } @@ -37,8 +37,9 @@ export interface TokenAuth_tokenCreate_user { export interface TokenAuth_tokenCreate { __typename: "CreateToken"; - token: string | null; errors: TokenAuth_tokenCreate_errors[]; + csrfToken: string | null; + token: string | null; user: TokenAuth_tokenCreate_user | null; } diff --git a/src/auth/utils.ts b/src/auth/utils.ts index f2ed57e85..4ea5c4afb 100644 --- a/src/auth/utils.ts +++ b/src/auth/utils.ts @@ -1,15 +1,90 @@ -const TOKEN_STORAGE_KEY = "dashboardAuth"; +import { IMessageContext } from "@saleor/components/messages"; +import { UseNotifierResult } from "@saleor/hooks/useNotifier"; +import { commonMessages } from "@saleor/intl"; +import { ApolloError } from "apollo-client"; +import { IntlShape } from "react-intl"; -export const getAuthToken = () => - localStorage.getItem(TOKEN_STORAGE_KEY) || - sessionStorage.getItem(TOKEN_STORAGE_KEY); +import { isJwtError, isTokenExpired } from "./errors"; -export const setAuthToken = (token: string, persist: boolean) => - persist - ? localStorage.setItem(TOKEN_STORAGE_KEY, token) - : sessionStorage.setItem(TOKEN_STORAGE_KEY, token); +export enum TOKEN_STORAGE_KEY { + AUTH = "auth", + CSRF = "csrf" +} -export const removeAuthToken = () => { - localStorage.removeItem(TOKEN_STORAGE_KEY); - sessionStorage.removeItem(TOKEN_STORAGE_KEY); +export const getTokens = () => ({ + auth: + localStorage.getItem(TOKEN_STORAGE_KEY.AUTH) || + sessionStorage.getItem(TOKEN_STORAGE_KEY.AUTH), + refresh: + localStorage.getItem(TOKEN_STORAGE_KEY.CSRF) || + sessionStorage.getItem(TOKEN_STORAGE_KEY.CSRF) +}); + +export const setTokens = (auth: string, csrf: string, persist: boolean) => { + if (persist) { + localStorage.setItem(TOKEN_STORAGE_KEY.AUTH, auth); + localStorage.setItem(TOKEN_STORAGE_KEY.CSRF, csrf); + } else { + sessionStorage.setItem(TOKEN_STORAGE_KEY.AUTH, auth); + sessionStorage.setItem(TOKEN_STORAGE_KEY.CSRF, csrf); + } }; + +export const setAuthToken = (auth: string, persist: boolean) => { + if (persist) { + localStorage.setItem(TOKEN_STORAGE_KEY.AUTH, auth); + } else { + sessionStorage.setItem(TOKEN_STORAGE_KEY.AUTH, auth); + } +}; + +export const removeTokens = () => { + localStorage.removeItem(TOKEN_STORAGE_KEY.AUTH); + sessionStorage.removeItem(TOKEN_STORAGE_KEY.AUTH); +}; + +export const displayDemoMessage = ( + intl: IntlShape, + notify: UseNotifierResult +) => { + notify({ + text: intl.formatMessage(commonMessages.demo) + }); +}; + +export async function handleQueryAuthError( + error: ApolloError, + notify: IMessageContext, + tokenRefresh: () => Promise, + logout: () => void, + intl: IntlShape +) { + if (error.graphQLErrors.some(isJwtError)) { + if (error.graphQLErrors.every(isTokenExpired)) { + const success = await tokenRefresh(); + + if (!success) { + logout(); + notify({ + status: "error", + text: intl.formatMessage(commonMessages.sessionExpired) + }); + } + } else { + logout(); + notify({ + status: "error", + text: intl.formatMessage(commonMessages.somethingWentWrong) + }); + } + } else if ( + !error.graphQLErrors.every( + err => err.extensions?.exception?.code === "PermissionDenied" + ) + ) { + notify({ + status: "error", + text: intl.formatMessage(commonMessages.somethingWentWrong) + }); + } +} diff --git a/src/auth/views/Login.tsx b/src/auth/views/Login.tsx index b901f4c86..70a7a8dda 100644 --- a/src/auth/views/Login.tsx +++ b/src/auth/views/Login.tsx @@ -1,7 +1,7 @@ -import React from "react"; - import useNavigator from "@saleor/hooks/useNavigator"; import useUser from "@saleor/hooks/useUser"; +import React from "react"; + import LoginPage, { FormData } from "../components/LoginPage"; import { passwordResetUrl } from "../urls"; diff --git a/src/auth/views/NewPassword.tsx b/src/auth/views/NewPassword.tsx index b2373720b..95fa9a4df 100644 --- a/src/auth/views/NewPassword.tsx +++ b/src/auth/views/NewPassword.tsx @@ -1,9 +1,9 @@ +import useNavigator from "@saleor/hooks/useNavigator"; +import useUser from "@saleor/hooks/useUser"; import { parse as parseQs } from "qs"; import React from "react"; import { RouteComponentProps } from "react-router"; -import useNavigator from "@saleor/hooks/useNavigator"; -import useUser from "@saleor/hooks/useUser"; import NewPasswordPage, { NewPasswordPageFormData } from "../components/NewPasswordPage"; @@ -19,7 +19,11 @@ const NewPassword: React.FC = ({ location }) => { const handleSetPassword = async (data: SetPassword) => { if (data.setPassword.errors.length === 0) { - loginByToken(data.setPassword.token, data.setPassword.user); + loginByToken( + data.setPassword.token, + data.setPassword.csrfToken, + data.setPassword.user + ); navigate("/", true); } }; diff --git a/src/auth/views/ResetPassword.tsx b/src/auth/views/ResetPassword.tsx index 69b130f92..fc189ad50 100644 --- a/src/auth/views/ResetPassword.tsx +++ b/src/auth/views/ResetPassword.tsx @@ -1,10 +1,10 @@ +import { APP_MOUNT_URI } from "@saleor/config"; +import useNavigator from "@saleor/hooks/useNavigator"; +import { commonMessages } from "@saleor/intl"; import React from "react"; import { useIntl } from "react-intl"; import urlJoin from "url-join"; -import { APP_MOUNT_URI } from "@saleor/config"; -import useNavigator from "@saleor/hooks/useNavigator"; -import { commonMessages } from "@saleor/intl"; import ResetPasswordPage, { ResetPasswordPageFormData } from "../components/ResetPasswordPage"; diff --git a/src/auth/views/ResetPasswordSuccess.tsx b/src/auth/views/ResetPasswordSuccess.tsx index 650a22cd4..d09e99ebd 100644 --- a/src/auth/views/ResetPasswordSuccess.tsx +++ b/src/auth/views/ResetPasswordSuccess.tsx @@ -1,6 +1,6 @@ +import useNavigator from "@saleor/hooks/useNavigator"; import React from "react"; -import useNavigator from "@saleor/hooks/useNavigator"; import ResetPasswordSuccessPage from "../components/ResetPasswordSuccessPage"; const ResetPasswordSuccessView: React.FC = () => { diff --git a/src/categories/components/CategoryBackground/CategoryBackground.tsx b/src/categories/components/CategoryBackground/CategoryBackground.tsx index 80cb662d1..b801afa95 100644 --- a/src/categories/components/CategoryBackground/CategoryBackground.tsx +++ b/src/categories/components/CategoryBackground/CategoryBackground.tsx @@ -1,17 +1,17 @@ -import makeStyles from "@material-ui/core/styles/makeStyles"; -import TextField from "@material-ui/core/TextField"; -import React from "react"; - import Button from "@material-ui/core/Button"; import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; +import makeStyles from "@material-ui/core/styles/makeStyles"; +import TextField from "@material-ui/core/TextField"; import CardTitle from "@saleor/components/CardTitle"; import Hr from "@saleor/components/Hr"; import ImageTile from "@saleor/components/ImageTile"; import ImageUpload from "@saleor/components/ImageUpload"; import Skeleton from "@saleor/components/Skeleton"; import { commonMessages } from "@saleor/intl"; +import React from "react"; import { FormattedMessage, useIntl } from "react-intl"; + import { CategoryDetails_category_backgroundImage } from "../../types/CategoryDetails"; import { FormData } from "../CategoryUpdatePage"; diff --git a/src/categories/components/CategoryCreatePage/CategoryCreatePage.tsx b/src/categories/components/CategoryCreatePage/CategoryCreatePage.tsx index a47266f62..202abe404 100644 --- a/src/categories/components/CategoryCreatePage/CategoryCreatePage.tsx +++ b/src/categories/components/CategoryCreatePage/CategoryCreatePage.tsx @@ -1,20 +1,22 @@ -import { ContentState, convertToRaw, RawDraftContentState } from "draft-js"; -import React from "react"; -import { useIntl } from "react-intl"; - import AppHeader from "@saleor/components/AppHeader"; import { CardSpacer } from "@saleor/components/CardSpacer"; import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; import Container from "@saleor/components/Container"; import Form from "@saleor/components/Form"; +import Metadata, { MetadataFormData } from "@saleor/components/Metadata"; import PageHeader from "@saleor/components/PageHeader"; import SaveButtonBar from "@saleor/components/SaveButtonBar"; import SeoForm from "@saleor/components/SeoForm"; +import { ProductErrorFragment } from "@saleor/fragments/types/ProductErrorFragment"; import { sectionNames } from "@saleor/intl"; -import { ProductErrorFragment } from "@saleor/attributes/types/ProductErrorFragment"; +import useMetadataChangeTrigger from "@saleor/utils/metadata/useMetadataChangeTrigger"; +import { ContentState, convertToRaw, RawDraftContentState } from "draft-js"; +import React from "react"; +import { useIntl } from "react-intl"; + import CategoryDetailsForm from "../../components/CategoryDetailsForm"; -interface FormData { +export interface FormData extends MetadataFormData { description: RawDraftContentState; name: string; seoTitle: string; @@ -23,7 +25,9 @@ interface FormData { const initialData: FormData = { description: convertToRaw(ContentState.createFromText("")), + metadata: [], name: "", + privateMetadata: [], seoDescription: "", seoTitle: "" }; @@ -44,49 +48,59 @@ export const CategoryCreatePage: React.FC = ({ saveButtonBarState }) => { const intl = useIntl(); + const { + makeChangeHandler: makeMetadataChangeHandler + } = useMetadataChangeTrigger(); + return ( - {({ data, change, submit, hasChanged }) => ( - - - {intl.formatMessage(sectionNames.categories)} - - -
- - - { + const changeMetadata = makeMetadataChangeHandler(change); + + return ( + + + {intl.formatMessage(sectionNames.categories)} + + - -
-
- )} +
+ + + + + + +
+ + ); + }} ); }; diff --git a/src/categories/components/CategoryDeleteDialog/CategoryDeleteDialog.tsx b/src/categories/components/CategoryDeleteDialog/CategoryDeleteDialog.tsx index aa1eb6a2b..9b1282d7e 100644 --- a/src/categories/components/CategoryDeleteDialog/CategoryDeleteDialog.tsx +++ b/src/categories/components/CategoryDeleteDialog/CategoryDeleteDialog.tsx @@ -5,11 +5,10 @@ import DialogContent from "@material-ui/core/DialogContent"; import DialogContentText from "@material-ui/core/DialogContentText"; import DialogTitle from "@material-ui/core/DialogTitle"; import { makeStyles } from "@material-ui/core/styles"; +import { buttonMessages } from "@saleor/intl"; import React from "react"; import { FormattedMessage } from "react-intl"; -import { buttonMessages } from "@saleor/intl"; - const useStyles = makeStyles( theme => ({ deleteButton: { diff --git a/src/categories/components/CategoryDetailsForm/CategoryDetailsForm.tsx b/src/categories/components/CategoryDetailsForm/CategoryDetailsForm.tsx index 615667541..4779571ba 100644 --- a/src/categories/components/CategoryDetailsForm/CategoryDetailsForm.tsx +++ b/src/categories/components/CategoryDetailsForm/CategoryDetailsForm.tsx @@ -1,16 +1,16 @@ import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; import TextField from "@material-ui/core/TextField"; +import CardTitle from "@saleor/components/CardTitle"; +import FormSpacer from "@saleor/components/FormSpacer"; +import RichTextEditor from "@saleor/components/RichTextEditor"; +import { ProductErrorFragment } from "@saleor/fragments/types/ProductErrorFragment"; +import { commonMessages } from "@saleor/intl"; +import { getFormErrors, getProductErrorMessage } from "@saleor/utils/errors"; import { RawDraftContentState } from "draft-js"; import React from "react"; import { useIntl } from "react-intl"; -import CardTitle from "@saleor/components/CardTitle"; -import FormSpacer from "@saleor/components/FormSpacer"; -import RichTextEditor from "@saleor/components/RichTextEditor"; -import { commonMessages } from "@saleor/intl"; -import { getFormErrors, getProductErrorMessage } from "@saleor/utils/errors"; -import { ProductErrorFragment } from "@saleor/attributes/types/ProductErrorFragment"; import { maybe } from "../../../misc"; import { CategoryDetails_category } from "../../types/CategoryDetails"; diff --git a/src/categories/components/CategoryList/CategoryList.tsx b/src/categories/components/CategoryList/CategoryList.tsx index 09ae331b4..6b4a55f2d 100644 --- a/src/categories/components/CategoryList/CategoryList.tsx +++ b/src/categories/components/CategoryList/CategoryList.tsx @@ -3,20 +3,19 @@ import TableBody from "@material-ui/core/TableBody"; import TableCell from "@material-ui/core/TableCell"; import TableFooter from "@material-ui/core/TableFooter"; import TableRow from "@material-ui/core/TableRow"; -import React from "react"; -import { FormattedMessage } from "react-intl"; - -import { CategoryFragment } from "@saleor/categories/types/CategoryFragment"; +import { CategoryListUrlSortField } from "@saleor/categories/urls"; import Checkbox from "@saleor/components/Checkbox"; import ResponsiveTable from "@saleor/components/ResponsiveTable"; import Skeleton from "@saleor/components/Skeleton"; +import TableCellHeader from "@saleor/components/TableCellHeader"; import TableHead from "@saleor/components/TableHead"; import TablePagination from "@saleor/components/TablePagination"; +import { CategoryFragment } from "@saleor/fragments/types/CategoryFragment"; import { maybe, renderCollection } from "@saleor/misc"; import { ListActions, ListProps, SortPage } from "@saleor/types"; -import { CategoryListUrlSortField } from "@saleor/categories/urls"; -import TableCellHeader from "@saleor/components/TableCellHeader"; import { getArrowDirection } from "@saleor/utils/sort"; +import React from "react"; +import { FormattedMessage } from "react-intl"; const useStyles = makeStyles( theme => ({ @@ -166,8 +165,8 @@ const CategoryList: React.FC = props => { onClick={category ? onRowClick(category.id) : undefined} key={category ? category.id : "skeleton"} selected={isSelected} - data-tc="id" - data-tc-id={maybe(() => category.id)} + data-test="id" + data-test-id={maybe(() => category.id)} > = props => { onChange={() => toggle(category.id)} /> - + {category && category.name ? category.name : } diff --git a/src/categories/components/CategoryListPage/CategoryListPage.tsx b/src/categories/components/CategoryListPage/CategoryListPage.tsx index 11c22bcde..877e57ce9 100644 --- a/src/categories/components/CategoryListPage/CategoryListPage.tsx +++ b/src/categories/components/CategoryListPage/CategoryListPage.tsx @@ -1,21 +1,21 @@ import Button from "@material-ui/core/Button"; import Card from "@material-ui/core/Card"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - -import { CategoryFragment } from "@saleor/categories/types/CategoryFragment"; +import { CategoryListUrlSortField } from "@saleor/categories/urls"; import Container from "@saleor/components/Container"; import PageHeader from "@saleor/components/PageHeader"; import SearchBar from "@saleor/components/SearchBar"; +import { CategoryFragment } from "@saleor/fragments/types/CategoryFragment"; import { sectionNames } from "@saleor/intl"; import { ListActions, PageListProps, SearchPageProps, - TabPageProps, - SortPage + SortPage, + TabPageProps } from "@saleor/types"; -import { CategoryListUrlSortField } from "@saleor/categories/urls"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import CategoryList from "../CategoryList"; export interface CategoryTableProps diff --git a/src/categories/components/CategoryProductList/CategoryProductList.tsx b/src/categories/components/CategoryProductList/CategoryProductList.tsx index 50fe397a4..3959c3bb6 100644 --- a/src/categories/components/CategoryProductList/CategoryProductList.tsx +++ b/src/categories/components/CategoryProductList/CategoryProductList.tsx @@ -8,8 +8,6 @@ import Money from "@saleor/components/Money"; import ResponsiveTable from "@saleor/components/ResponsiveTable"; import Skeleton from "@saleor/components/Skeleton"; import StatusLabel from "@saleor/components/StatusLabel"; -import { FormattedMessage, useIntl } from "react-intl"; - import TableCellAvatar, { AVATAR_MARGIN } from "@saleor/components/TableCellAvatar"; @@ -18,7 +16,12 @@ import TablePagination from "@saleor/components/TablePagination"; import { maybe, renderCollection } from "@saleor/misc"; import { ListActions, ListProps } from "@saleor/types"; import React from "react"; -import { CategoryDetails_category_products_edges_node } from "../../types/CategoryDetails"; +import { FormattedMessage, useIntl } from "react-intl"; + +import { + CategoryDetails_category_products_edges_node, + CategoryDetails_category_products_edges_node_pricing_priceRangeUndiscounted +} from "../../types/CategoryDetails"; const useStyles = makeStyles( theme => ({ @@ -27,7 +30,7 @@ const useStyles = makeStyles( width: "auto" }, colPrice: { - width: 200 + width: 300 }, colPublished: { width: 200 @@ -74,9 +77,7 @@ interface CategoryProductListProps extends ListProps, ListActions { products: CategoryDetails_category_products_edges_node[]; } -export const CategoryProductList: React.FC< - CategoryProductListProps -> = props => { +export const CategoryProductList: React.FC = props => { const { disabled, isChecked, @@ -96,6 +97,51 @@ export const CategoryProductList: React.FC< const numberOfColumns = 5; + const getProductPrice = ( + priceRangeUndiscounted: CategoryDetails_category_products_edges_node_pricing_priceRangeUndiscounted + ) => { + if (!priceRangeUndiscounted) { + return null; + } + + const { start, stop } = priceRangeUndiscounted; + const { + gross: { amount: startAmount } + } = start; + const { + gross: { amount: stopAmount } + } = stop; + + if (startAmount === stopAmount) { + return ( + + ); + } else { + return ( + <> + + {" - "} + + + ); + } + }; + return (
@@ -209,10 +255,8 @@ export const CategoryProductList: React.FC< )} - {maybe(() => product.basePrice) && - maybe(() => product.basePrice.amount) !== undefined && - maybe(() => product.basePrice.currency) !== undefined ? ( - + {product?.pricing?.priceRangeUndiscounted ? ( + getProductPrice(product?.pricing?.priceRangeUndiscounted) ) : ( )} diff --git a/src/categories/components/CategoryProducts/CategoryProducts.tsx b/src/categories/components/CategoryProducts/CategoryProducts.tsx index df517b4b3..06ace2040 100644 --- a/src/categories/components/CategoryProducts/CategoryProducts.tsx +++ b/src/categories/components/CategoryProducts/CategoryProducts.tsx @@ -1,9 +1,9 @@ import Button from "@material-ui/core/Button"; import Card from "@material-ui/core/Card"; +import CardTitle from "@saleor/components/CardTitle"; import React from "react"; import { FormattedMessage, useIntl } from "react-intl"; -import CardTitle from "@saleor/components/CardTitle"; import { ListActions, PageListProps } from "../../../types"; import { CategoryDetails_category_products_edges_node } from "../../types/CategoryDetails"; import CategoryProductList from "../CategoryProductList"; diff --git a/src/categories/components/CategoryUpdatePage/CategoryUpdatePage.tsx b/src/categories/components/CategoryUpdatePage/CategoryUpdatePage.tsx index 58260c5f7..7b64d842d 100644 --- a/src/categories/components/CategoryUpdatePage/CategoryUpdatePage.tsx +++ b/src/categories/components/CategoryUpdatePage/CategoryUpdatePage.tsx @@ -1,21 +1,25 @@ import Button from "@material-ui/core/Button"; import Card from "@material-ui/core/Card"; -import { RawDraftContentState } from "draft-js"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import AppHeader from "@saleor/components/AppHeader"; import { CardSpacer } from "@saleor/components/CardSpacer"; import CardTitle from "@saleor/components/CardTitle"; import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; import Container from "@saleor/components/Container"; import Form from "@saleor/components/Form"; +import Metadata from "@saleor/components/Metadata/Metadata"; +import { MetadataFormData } from "@saleor/components/Metadata/types"; import PageHeader from "@saleor/components/PageHeader"; import SaveButtonBar from "@saleor/components/SaveButtonBar"; import SeoForm from "@saleor/components/SeoForm"; import { Tab, TabContainer } from "@saleor/components/Tab"; +import { ProductErrorFragment } from "@saleor/fragments/types/ProductErrorFragment"; import { sectionNames } from "@saleor/intl"; -import { ProductErrorFragment } from "@saleor/attributes/types/ProductErrorFragment"; +import { mapMetadataItemToInput } from "@saleor/utils/maps"; +import useMetadataChangeTrigger from "@saleor/utils/metadata/useMetadataChangeTrigger"; +import { RawDraftContentState } from "draft-js"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { maybe } from "../../../misc"; import { TabListActions } from "../../../types"; import CategoryDetailsForm from "../../components/CategoryDetailsForm"; @@ -28,7 +32,7 @@ import { import CategoryBackground from "../CategoryBackground"; import CategoryProducts from "../CategoryProducts"; -export interface FormData { +export interface FormData extends MetadataFormData { backgroundImageAlt: string; description: RawDraftContentState; name: string; @@ -100,144 +104,174 @@ export const CategoryUpdatePage: React.FC = ({ toggleAll }: CategoryUpdatePageProps) => { const intl = useIntl(); + const { + isMetadataModified, + isPrivateMetadataModified, + makeChangeHandler: makeMetadataChangeHandler + } = useMetadataChangeTrigger(); + const initialData: FormData = category ? { backgroundImageAlt: maybe(() => category.backgroundImage.alt, ""), description: maybe(() => JSON.parse(category.descriptionJson)), + metadata: category?.metadata?.map(mapMetadataItemToInput), name: category.name || "", + privateMetadata: category?.privateMetadata?.map(mapMetadataItemToInput), seoDescription: category.seoDescription || "", seoTitle: category.seoTitle || "" } : { backgroundImageAlt: "", description: "", + metadata: undefined, name: "", + privateMetadata: undefined, seoDescription: "", seoTitle: "" }; + + const handleSubmit = (data: FormData) => { + const metadata = isMetadataModified ? data.metadata : undefined; + const privateMetadata = isPrivateMetadataModified + ? data.privateMetadata + : undefined; + + onSubmit({ + ...data, + metadata, + privateMetadata + }); + }; + return ( -
- {({ data, change, submit, hasChanged }) => ( - - - {intl.formatMessage(sectionNames.categories)} - - - - - category.backgroundImage)} - onChange={change} - /> - - - - - - - - - - - - - {currentTab === CategoryPageTab.categories && ( - - - - - } - /> - + {({ data, change, submit, hasChanged }) => { + const changeMetadata = makeMetadataChangeHandler(change); + + return ( + + + {intl.formatMessage(sectionNames.categories)} + + + + + category.backgroundImage)} + onChange={change} + /> + + + + + + + + + + + + + + + {currentTab === CategoryPageTab.categories && ( + + + + + } + /> + undefined} + /> + + )} + {currentTab === CategoryPageTab.products && ( + category.name)} + products={products} disabled={disabled} - isChecked={isChecked} - isRoot={false} pageInfo={pageInfo} - selected={selected} - sort={undefined} - toggle={toggle} - toggleAll={toggleAll} - toolbar={subcategoryListToolbar} onNextPage={onNextPage} onPreviousPage={onPreviousPage} - onRowClick={onCategoryClick} - onSort={() => undefined} + onRowClick={onProductClick} + onAdd={onAddProduct} + toggle={toggle} + toggleAll={toggleAll} + selected={selected} + isChecked={isChecked} + toolbar={productListToolbar} /> - - )} - {currentTab === CategoryPageTab.products && ( - category.name)} - products={products} - disabled={disabled} - pageInfo={pageInfo} - onNextPage={onNextPage} - onPreviousPage={onPreviousPage} - onRowClick={onProductClick} - onAdd={onAddProduct} - toggle={toggle} - toggleAll={toggleAll} - selected={selected} - isChecked={isChecked} - toolbar={productListToolbar} + )} + - )} - - - )} + + ); + }}
); }; diff --git a/src/categories/fixtures.ts b/src/categories/fixtures.ts index 89ab0441f..d51e93b93 100644 --- a/src/categories/fixtures.ts +++ b/src/categories/fixtures.ts @@ -1,6 +1,7 @@ +import { CategoryFragment } from "@saleor/fragments/types/CategoryFragment"; + import { content } from "../storybook/stories/components/RichTextEditor"; import { CategoryDetails_category } from "./types/CategoryDetails"; -import { CategoryFragment } from "./types/CategoryFragment"; export const categories: CategoryFragment[] = [ { @@ -104,11 +105,19 @@ export const category: ( }, descriptionJson: JSON.stringify(content), id: "Q2F0ZWdvcnk6NA==", + metadata: [ + { + __typename: "MetadataItem", + key: "integration.id", + value: "100023123" + } + ], name: "Coffees", parent: { __typename: "Category", id: "Q2F0ZWdvcnk6Mw==" }, + privateMetadata: [], products: { __typename: "ProductCountableConnection", edges: [ @@ -117,14 +126,31 @@ export const category: ( cursor: "YXJyYXljb25uZWN0aW9uOjA=", node: { __typename: "Product", - basePrice: { - __typename: "Money", - amount: 83.3, - currency: "USD" - }, id: "UHJvZHVjdDoyMQ==", isAvailable: true, name: "Gardner-Schultz", + pricing: { + __typename: "ProductPricingInfo", + priceRangeUndiscounted: { + __typename: "TaxedMoneyRange", + start: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 3, + currency: "USD" + } + }, + stop: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 8, + currency: "USD" + } + } + } + }, productType: { __typename: "ProductType", id: "UHJvZHVjdFR5cGU6Mw==", @@ -138,14 +164,31 @@ export const category: ( cursor: "YXJyYXljb25uZWN0aW9uOjE=", node: { __typename: "Product", - basePrice: { - __typename: "Money", - amount: 68.27, - currency: "USD" - }, id: "UHJvZHVjdDoyMg==", isAvailable: true, name: "James, Martinez and Murray", + pricing: { + __typename: "ProductPricingInfo", + priceRangeUndiscounted: { + __typename: "TaxedMoneyRange", + start: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 3, + currency: "USD" + } + }, + stop: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 8, + currency: "USD" + } + } + } + }, productType: { __typename: "ProductType", id: "UHJvZHVjdFR5cGU6Mw==", @@ -159,14 +202,31 @@ export const category: ( cursor: "YXJyYXljb25uZWN0aW9uOjI=", node: { __typename: "Product", - basePrice: { - __typename: "Money", - amount: 21.43, - currency: "USD" - }, id: "UHJvZHVjdDoyMw==", isAvailable: true, name: "Curtis, Joyce and Turner", + pricing: { + __typename: "ProductPricingInfo", + priceRangeUndiscounted: { + __typename: "TaxedMoneyRange", + start: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 3, + currency: "USD" + } + }, + stop: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 8, + currency: "USD" + } + } + } + }, productType: { __typename: "ProductType", id: "UHJvZHVjdFR5cGU6Mw==", @@ -180,14 +240,31 @@ export const category: ( cursor: "YXJyYXljb25uZWN0aW9uOjM=", node: { __typename: "Product", - basePrice: { - __typename: "Money", - amount: 62.76, - currency: "USD" - }, id: "UHJvZHVjdDoyNA==", isAvailable: true, name: "Davis, Brown and Ray", + pricing: { + __typename: "ProductPricingInfo", + priceRangeUndiscounted: { + __typename: "TaxedMoneyRange", + start: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 3, + currency: "USD" + } + }, + stop: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 8, + currency: "USD" + } + } + } + }, productType: { __typename: "ProductType", id: "UHJvZHVjdFR5cGU6Mw==", @@ -201,14 +278,31 @@ export const category: ( cursor: "YXJyYXljb25uZWN0aW9uOjQ=", node: { __typename: "Product", - basePrice: { - __typename: "Money", - amount: 7.13, - currency: "USD" - }, id: "UHJvZHVjdDoyNQ==", isAvailable: true, name: "Gallegos Ltd", + pricing: { + __typename: "ProductPricingInfo", + priceRangeUndiscounted: { + __typename: "TaxedMoneyRange", + start: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 3, + currency: "USD" + } + }, + stop: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 8, + currency: "USD" + } + } + } + }, productType: { __typename: "ProductType", id: "UHJvZHVjdFR5cGU6Mw==", @@ -222,14 +316,31 @@ export const category: ( cursor: "YXJyYXljb25uZWN0aW9uOjU=", node: { __typename: "Product", - basePrice: { - __typename: "Money", - amount: 48.82, - currency: "USD" - }, id: "UHJvZHVjdDoyNg==", isAvailable: true, name: "Franklin Inc", + pricing: { + __typename: "ProductPricingInfo", + priceRangeUndiscounted: { + __typename: "TaxedMoneyRange", + start: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 3, + currency: "USD" + } + }, + stop: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 8, + currency: "USD" + } + } + } + }, productType: { __typename: "ProductType", id: "UHJvZHVjdFR5cGU6Mw==", @@ -243,14 +354,31 @@ export const category: ( cursor: "YXJyYXljb25uZWN0aW9uOjY=", node: { __typename: "Product", - basePrice: { - __typename: "Money", - amount: 27.34, - currency: "USD" - }, id: "UHJvZHVjdDoyNw==", isAvailable: true, name: "Williams-Taylor", + pricing: { + __typename: "ProductPricingInfo", + priceRangeUndiscounted: { + __typename: "TaxedMoneyRange", + start: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 3, + currency: "USD" + } + }, + stop: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 8, + currency: "USD" + } + } + } + }, productType: { __typename: "ProductType", id: "UHJvZHVjdFR5cGU6Mw==", @@ -264,14 +392,31 @@ export const category: ( cursor: "YXJyYXljb25uZWN0aW9uOjc=", node: { __typename: "Product", - basePrice: { - __typename: "Money", - amount: 75.42, - currency: "USD" - }, id: "UHJvZHVjdDoyOA==", isAvailable: true, name: "Riddle, Evans and Hicks", + pricing: { + __typename: "ProductPricingInfo", + priceRangeUndiscounted: { + __typename: "TaxedMoneyRange", + start: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 3, + currency: "USD" + } + }, + stop: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 8, + currency: "USD" + } + } + } + }, productType: { __typename: "ProductType", id: "UHJvZHVjdFR5cGU6Mw==", @@ -285,14 +430,31 @@ export const category: ( cursor: "YXJyYXljb25uZWN0aW9uOjg=", node: { __typename: "Product", - basePrice: { - __typename: "Money", - amount: 86.62, - currency: "USD" - }, id: "UHJvZHVjdDoyOQ==", isAvailable: true, name: "Hebert-Sherman", + pricing: { + __typename: "ProductPricingInfo", + priceRangeUndiscounted: { + __typename: "TaxedMoneyRange", + start: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 3, + currency: "USD" + } + }, + stop: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 8, + currency: "USD" + } + } + } + }, productType: { __typename: "ProductType", id: "UHJvZHVjdFR5cGU6Mw==", @@ -306,14 +468,31 @@ export const category: ( cursor: "YXJyYXljb25uZWN0aW9uOjk=", node: { __typename: "Product", - basePrice: { - __typename: "Money", - amount: 48.66, - currency: "USD" - }, id: "UHJvZHVjdDozMA==", isAvailable: true, name: "Carter and Sons", + pricing: { + __typename: "ProductPricingInfo", + priceRangeUndiscounted: { + __typename: "TaxedMoneyRange", + start: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 3, + currency: "USD" + } + }, + stop: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 8, + currency: "USD" + } + } + } + }, productType: { __typename: "ProductType", id: "UHJvZHVjdFR5cGU6Mw==", diff --git a/src/categories/index.tsx b/src/categories/index.tsx index 2ae9db35f..3de1ea6fc 100644 --- a/src/categories/index.tsx +++ b/src/categories/index.tsx @@ -1,18 +1,18 @@ +import { sectionNames } from "@saleor/intl"; +import { asSortParams } from "@saleor/utils/sort"; import { parse as parseQs } from "qs"; import React from "react"; import { useIntl } from "react-intl"; import { Route, RouteComponentProps, Switch } from "react-router-dom"; -import { sectionNames } from "@saleor/intl"; -import { asSortParams } from "@saleor/utils/sort"; import { WindowTitle } from "../components/WindowTitle"; import { categoryAddPath, categoryListPath, CategoryListUrlQueryParams, + CategoryListUrlSortField, categoryPath, - CategoryUrlQueryParams, - CategoryListUrlSortField + CategoryUrlQueryParams } from "./urls"; import { CategoryCreateView } from "./views/CategoryCreate"; import CategoryDetailsView, { getActiveTab } from "./views/CategoryDetails"; diff --git a/src/categories/mutations.ts b/src/categories/mutations.ts index a228faa8c..cb61a5072 100644 --- a/src/categories/mutations.ts +++ b/src/categories/mutations.ts @@ -1,8 +1,8 @@ +import { categoryDetailsFragment } from "@saleor/fragments/categories"; +import { productErrorFragment } from "@saleor/fragments/errors"; +import makeMutation from "@saleor/hooks/makeMutation"; import gql from "graphql-tag"; -import makeMutation from "@saleor/hooks/makeMutation"; -import { productErrorFragment } from "@saleor/attributes/mutations"; -import { categoryDetailsFragment } from "./queries"; import { CategoryBulkDelete, CategoryBulkDeleteVariables diff --git a/src/categories/queries.ts b/src/categories/queries.ts index 15ddc9247..af7dd09ba 100644 --- a/src/categories/queries.ts +++ b/src/categories/queries.ts @@ -1,42 +1,18 @@ +import { + categoryDetailsFragment, + categoryFragment +} from "@saleor/fragments/categories"; +import { pageInfoFragment } from "@saleor/fragments/pageInfo"; +import { fragmentMoney } from "@saleor/fragments/products"; +import makeQuery from "@saleor/hooks/makeQuery"; import gql from "graphql-tag"; -import makeQuery from "@saleor/hooks/makeQuery"; -import { pageInfoFragment } from "../queries"; import { CategoryDetails, CategoryDetailsVariables } from "./types/CategoryDetails"; import { RootCategories } from "./types/RootCategories"; -export const categoryFragment = gql` - fragment CategoryFragment on Category { - id - name - children { - totalCount - } - products { - totalCount - } - } -`; -export const categoryDetailsFragment = gql` - fragment CategoryDetailsFragment on Category { - id - backgroundImage { - alt - url - } - name - descriptionJson - seoDescription - seoTitle - parent { - id - } - } -`; - export const rootCategories = gql` ${categoryFragment} ${pageInfoFragment} @@ -73,6 +49,7 @@ export const useRootCategoriesQuery = makeQuery( ); export const categoryDetails = gql` + ${fragmentMoney} ${categoryFragment} ${categoryDetailsFragment} ${pageInfoFragment} @@ -104,10 +81,6 @@ export const categoryDetails = gql` node { id name - basePrice { - amount - currency - } isAvailable thumbnail { url @@ -116,6 +89,20 @@ export const categoryDetails = gql` id name } + pricing { + priceRangeUndiscounted { + start { + gross { + ...Money + } + } + stop { + gross { + ...Money + } + } + } + } } } } diff --git a/src/categories/types/CategoryCreate.ts b/src/categories/types/CategoryCreate.ts index 0bcf34a74..21991ef8d 100644 --- a/src/categories/types/CategoryCreate.ts +++ b/src/categories/types/CategoryCreate.ts @@ -8,6 +8,18 @@ import { CategoryInput, ProductErrorCode } from "./../../types/globalTypes"; // GraphQL mutation operation: CategoryCreate // ==================================================== +export interface CategoryCreate_categoryCreate_category_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface CategoryCreate_categoryCreate_category_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface CategoryCreate_categoryCreate_category_backgroundImage { __typename: "Image"; alt: string | null; @@ -22,6 +34,8 @@ export interface CategoryCreate_categoryCreate_category_parent { export interface CategoryCreate_categoryCreate_category { __typename: "Category"; id: string; + metadata: (CategoryCreate_categoryCreate_category_metadata | null)[]; + privateMetadata: (CategoryCreate_categoryCreate_category_privateMetadata | null)[]; backgroundImage: CategoryCreate_categoryCreate_category_backgroundImage | null; name: string; descriptionJson: any; diff --git a/src/categories/types/CategoryDetails.ts b/src/categories/types/CategoryDetails.ts index bcdf4f7ce..5cf7baa08 100644 --- a/src/categories/types/CategoryDetails.ts +++ b/src/categories/types/CategoryDetails.ts @@ -6,6 +6,18 @@ // GraphQL query operation: CategoryDetails // ==================================================== +export interface CategoryDetails_category_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface CategoryDetails_category_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface CategoryDetails_category_backgroundImage { __typename: "Image"; alt: string | null; @@ -62,12 +74,6 @@ export interface CategoryDetails_category_products_pageInfo { startCursor: string | null; } -export interface CategoryDetails_category_products_edges_node_basePrice { - __typename: "Money"; - amount: number; - currency: string; -} - export interface CategoryDetails_category_products_edges_node_thumbnail { __typename: "Image"; url: string; @@ -79,14 +85,47 @@ export interface CategoryDetails_category_products_edges_node_productType { name: string; } +export interface CategoryDetails_category_products_edges_node_pricing_priceRangeUndiscounted_start_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface CategoryDetails_category_products_edges_node_pricing_priceRangeUndiscounted_start { + __typename: "TaxedMoney"; + gross: CategoryDetails_category_products_edges_node_pricing_priceRangeUndiscounted_start_gross; +} + +export interface CategoryDetails_category_products_edges_node_pricing_priceRangeUndiscounted_stop_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface CategoryDetails_category_products_edges_node_pricing_priceRangeUndiscounted_stop { + __typename: "TaxedMoney"; + gross: CategoryDetails_category_products_edges_node_pricing_priceRangeUndiscounted_stop_gross; +} + +export interface CategoryDetails_category_products_edges_node_pricing_priceRangeUndiscounted { + __typename: "TaxedMoneyRange"; + start: CategoryDetails_category_products_edges_node_pricing_priceRangeUndiscounted_start | null; + stop: CategoryDetails_category_products_edges_node_pricing_priceRangeUndiscounted_stop | null; +} + +export interface CategoryDetails_category_products_edges_node_pricing { + __typename: "ProductPricingInfo"; + priceRangeUndiscounted: CategoryDetails_category_products_edges_node_pricing_priceRangeUndiscounted | null; +} + export interface CategoryDetails_category_products_edges_node { __typename: "Product"; id: string; name: string; - basePrice: CategoryDetails_category_products_edges_node_basePrice | null; isAvailable: boolean | null; thumbnail: CategoryDetails_category_products_edges_node_thumbnail | null; productType: CategoryDetails_category_products_edges_node_productType; + pricing: CategoryDetails_category_products_edges_node_pricing | null; } export interface CategoryDetails_category_products_edges { @@ -104,6 +143,8 @@ export interface CategoryDetails_category_products { export interface CategoryDetails_category { __typename: "Category"; id: string; + metadata: (CategoryDetails_category_metadata | null)[]; + privateMetadata: (CategoryDetails_category_privateMetadata | null)[]; backgroundImage: CategoryDetails_category_backgroundImage | null; name: string; descriptionJson: any; diff --git a/src/categories/types/CategoryProperties.ts b/src/categories/types/CategoryProperties.ts deleted file mode 100644 index 3ff2be8c5..000000000 --- a/src/categories/types/CategoryProperties.ts +++ /dev/null @@ -1,95 +0,0 @@ -/* tslint:disable */ -// This file was automatically generated and should not be edited. - -// ==================================================== -// GraphQL query operation: CategoryProperties -// ==================================================== - -export interface CategoryProperties_category_parent { - __typename: "Category"; - id: string; -} - -export interface CategoryProperties_category_children_edges_node_children { - __typename: "CategoryCountableConnection"; - totalCount: number | null; -} - -export interface CategoryProperties_category_children_edges_node_products { - __typename: "ProductCountableConnection"; - totalCount: number | null; -} - -export interface CategoryProperties_category_children_edges_node { - __typename: "Category"; - id: string; - name: string; - children: CategoryProperties_category_children_edges_node_children | null; - products: CategoryProperties_category_children_edges_node_products | null; -} - -export interface CategoryProperties_category_children_edges { - __typename: "CategoryCountableEdge"; - node: CategoryProperties_category_children_edges_node; -} - -export interface CategoryProperties_category_children { - __typename: "CategoryCountableConnection"; - edges: CategoryProperties_category_children_edges[]; -} - -export interface CategoryProperties_category_products_pageInfo { - __typename: "PageInfo"; - endCursor: string | null; - hasNextPage: boolean; - hasPreviousPage: boolean; - startCursor: string | null; -} - -export interface CategoryProperties_category_products_edges_node_productType { - __typename: "ProductType"; - id: string; - name: string; -} - -export interface CategoryProperties_category_products_edges_node { - __typename: "Product"; - id: string; - name: string; - thumbnailUrl: string | null; - productType: CategoryProperties_category_products_edges_node_productType; -} - -export interface CategoryProperties_category_products_edges { - __typename: "ProductCountableEdge"; - cursor: string; - node: CategoryProperties_category_products_edges_node; -} - -export interface CategoryProperties_category_products { - __typename: "ProductCountableConnection"; - pageInfo: CategoryProperties_category_products_pageInfo; - edges: CategoryProperties_category_products_edges[]; -} - -export interface CategoryProperties_category { - __typename: "Category"; - id: string; - name: string; - description: string; - parent: CategoryProperties_category_parent | null; - children: CategoryProperties_category_children | null; - products: CategoryProperties_category_products | null; -} - -export interface CategoryProperties { - category: CategoryProperties_category | null; -} - -export interface CategoryPropertiesVariables { - id: string; - first?: number | null; - after?: string | null; - last?: number | null; - before?: string | null; -} diff --git a/src/categories/types/CategoryUpdate.ts b/src/categories/types/CategoryUpdate.ts index 8b04c1583..1be777c04 100644 --- a/src/categories/types/CategoryUpdate.ts +++ b/src/categories/types/CategoryUpdate.ts @@ -8,6 +8,18 @@ import { CategoryInput, ProductErrorCode } from "./../../types/globalTypes"; // GraphQL mutation operation: CategoryUpdate // ==================================================== +export interface CategoryUpdate_categoryUpdate_category_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface CategoryUpdate_categoryUpdate_category_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface CategoryUpdate_categoryUpdate_category_backgroundImage { __typename: "Image"; alt: string | null; @@ -22,6 +34,8 @@ export interface CategoryUpdate_categoryUpdate_category_parent { export interface CategoryUpdate_categoryUpdate_category { __typename: "Category"; id: string; + metadata: (CategoryUpdate_categoryUpdate_category_metadata | null)[]; + privateMetadata: (CategoryUpdate_categoryUpdate_category_privateMetadata | null)[]; backgroundImage: CategoryUpdate_categoryUpdate_category_backgroundImage | null; name: string; descriptionJson: any; diff --git a/src/categories/types/RootCategoryChildren.ts b/src/categories/types/RootCategoryChildren.ts deleted file mode 100644 index 71f75ba20..000000000 --- a/src/categories/types/RootCategoryChildren.ts +++ /dev/null @@ -1,39 +0,0 @@ -/* tslint:disable */ -// This file was automatically generated and should not be edited. - -// ==================================================== -// GraphQL query operation: RootCategoryChildren -// ==================================================== - -export interface RootCategoryChildren_categories_edges_node_children { - __typename: "CategoryCountableConnection"; - totalCount: number | null; -} - -export interface RootCategoryChildren_categories_edges_node_products { - __typename: "ProductCountableConnection"; - totalCount: number | null; -} - -export interface RootCategoryChildren_categories_edges_node { - __typename: "Category"; - id: string; - name: string; - children: RootCategoryChildren_categories_edges_node_children | null; - products: RootCategoryChildren_categories_edges_node_products | null; -} - -export interface RootCategoryChildren_categories_edges { - __typename: "CategoryCountableEdge"; - cursor: string; - node: RootCategoryChildren_categories_edges_node; -} - -export interface RootCategoryChildren_categories { - __typename: "CategoryCountableConnection"; - edges: RootCategoryChildren_categories_edges[]; -} - -export interface RootCategoryChildren { - categories: RootCategoryChildren_categories | null; -} diff --git a/src/categories/urls.ts b/src/categories/urls.ts index 13c88a5d5..88fa6d5a1 100644 --- a/src/categories/urls.ts +++ b/src/categories/urls.ts @@ -7,8 +7,8 @@ import { Dialog, Filters, Pagination, - TabActionDialog, - Sort + Sort, + TabActionDialog } from "../types"; import { CategoryPageTab } from "./components/CategoryUpdatePage"; diff --git a/src/categories/views/CategoryCreate.tsx b/src/categories/views/CategoryCreate.tsx index 1eb3c56f5..606fab85b 100644 --- a/src/categories/views/CategoryCreate.tsx +++ b/src/categories/views/CategoryCreate.tsx @@ -1,11 +1,15 @@ -import React from "react"; -import { useIntl } from "react-intl"; - import { WindowTitle } from "@saleor/components/WindowTitle"; import useNavigator from "@saleor/hooks/useNavigator"; import useNotifier from "@saleor/hooks/useNotifier"; -import { maybe } from "../../misc"; -import CategoryCreatePage from "../components/CategoryCreatePage"; +import createMetadataCreateHandler from "@saleor/utils/handlers/metadataCreateHandler"; +import { + useMetadataUpdate, + usePrivateMetadataUpdate +} from "@saleor/utils/metadata/updateMetadata"; +import React from "react"; +import { useIntl } from "react-intl"; + +import CategoryCreatePage, { FormData } from "../components/CategoryCreatePage"; import { useCategoryCreateMutation } from "../mutations"; import { CategoryCreate } from "../types/CategoryCreate"; import { categoryListUrl, categoryUrl } from "../urls"; @@ -20,10 +24,13 @@ export const CategoryCreateView: React.FC = ({ const navigate = useNavigator(); const notify = useNotifier(); const intl = useIntl(); + const [updateMetadata] = useMetadataUpdate({}); + const [updatePrivateMetadata] = usePrivateMetadataUpdate({}); const handleSuccess = (data: CategoryCreate) => { if (data.categoryCreate.errors.length === 0) { notify({ + status: "success", text: intl.formatMessage({ defaultMessage: "Category created" }) @@ -36,9 +43,27 @@ export const CategoryCreateView: React.FC = ({ onCompleted: handleSuccess }); - const errors = maybe( - () => createCategoryResult.data.categoryCreate.errors, - [] + const handleCreate = async (formData: FormData) => { + const result = await createCategory({ + variables: { + input: { + descriptionJson: JSON.stringify(formData.description), + name: formData.name, + seo: { + description: formData.seoDescription, + title: formData.seoTitle + } + }, + parent: parentId || null + } + }); + + return result.data?.categoryCreate.category?.id || null; + }; + const handleSubmit = createMetadataCreateHandler( + handleCreate, + updateMetadata, + updatePrivateMetadata ); return ( @@ -51,26 +76,12 @@ export const CategoryCreateView: React.FC = ({ /> navigate(parentId ? categoryUrl(parentId) : categoryListUrl()) } - onSubmit={formData => - createCategory({ - variables: { - input: { - descriptionJson: JSON.stringify(formData.description), - name: formData.name, - seo: { - description: formData.seoDescription, - title: formData.seoTitle - } - }, - parent: parentId || null - } - }) - } + onSubmit={handleSubmit} /> ); diff --git a/src/categories/views/CategoryDetails.tsx b/src/categories/views/CategoryDetails.tsx index e33d91b96..cb875d01d 100644 --- a/src/categories/views/CategoryDetails.tsx +++ b/src/categories/views/CategoryDetails.tsx @@ -1,10 +1,8 @@ import DialogContentText from "@material-ui/core/DialogContentText"; import IconButton from "@material-ui/core/IconButton"; import DeleteIcon from "@material-ui/icons/Delete"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import ActionDialog from "@saleor/components/ActionDialog"; +import NotFoundPage from "@saleor/components/NotFoundPage"; import { WindowTitle } from "@saleor/components/WindowTitle"; import useBulkActions from "@saleor/hooks/useBulkActions"; import useNavigator from "@saleor/hooks/useNavigator"; @@ -14,16 +12,23 @@ import usePaginator, { } from "@saleor/hooks/usePaginator"; import { commonMessages } from "@saleor/intl"; import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; -import NotFoundPage from "@saleor/components/NotFoundPage"; +import createMetadataUpdateHandler from "@saleor/utils/handlers/metadataUpdateHandler"; +import { + useMetadataUpdate, + usePrivateMetadataUpdate +} from "@saleor/utils/metadata/updateMetadata"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { PAGINATE_BY } from "../../config"; import { maybe } from "../../misc"; -import { TypedProductBulkDeleteMutation } from "../../products/mutations"; -import { productBulkDelete } from "../../products/types/productBulkDelete"; +import { useProductBulkDeleteMutation } from "../../products/mutations"; import { productAddUrl, productUrl } from "../../products/urls"; import { CategoryInput } from "../../types/globalTypes"; import { CategoryPageTab, - CategoryUpdatePage + CategoryUpdatePage, + FormData } from "../components/CategoryUpdatePage/CategoryUpdatePage"; import { useCategoryBulkDeleteMutation, @@ -38,8 +43,8 @@ import { categoryAddUrl, categoryListUrl, categoryUrl, - CategoryUrlQueryParams, - CategoryUrlDialog + CategoryUrlDialog, + CategoryUrlQueryParams } from "../urls"; export interface CategoryDetailsProps { @@ -64,6 +69,8 @@ export const CategoryDetails: React.FC = ({ params.ids ); const intl = useIntl(); + const [updateMetadata] = useMetadataUpdate({}); + const [updatePrivateMetadata] = usePrivateMetadataUpdate({}); const paginationState = createPaginationState(PAGINATE_BY, params); const { data, loading, refetch } = useCategoryDetailsQuery({ @@ -80,6 +87,7 @@ export const CategoryDetails: React.FC = ({ const handleCategoryDelete = (data: CategoryDelete) => { if (data.categoryDelete.errors.length === 0) { notify({ + status: "success", text: intl.formatMessage({ defaultMessage: "Category deleted" }) @@ -99,6 +107,7 @@ export const CategoryDetails: React.FC = ({ ); if (backgroundImageError) { notify({ + status: "error", text: intl.formatMessage(commonMessages.somethingWentWrong) }); } @@ -113,6 +122,7 @@ export const CategoryDetails: React.FC = ({ if (data.categoryBulkDelete.errors.length === 0) { closeModal(); notify({ + status: "success", text: intl.formatMessage(commonMessages.savedChanges) }); reset(); @@ -126,6 +136,23 @@ export const CategoryDetails: React.FC = ({ onCompleted: handleBulkCategoryDelete }); + const [ + productBulkDelete, + productBulkDeleteOpts + ] = useProductBulkDeleteMutation({ + onCompleted: data => { + if (data.productBulkDelete.errors.length === 0) { + closeModal(); + notify({ + status: "success", + text: intl.formatMessage(commonMessages.savedChanges) + }); + refetch(); + reset(); + } + } + }); + const changeTab = (tabName: CategoryPageTab) => { reset(); navigate( @@ -140,17 +167,6 @@ export const CategoryDetails: React.FC = ({ CategoryUrlQueryParams >(navigate, params => categoryUrl(id, params), params); - const handleBulkProductDelete = (data: productBulkDelete) => { - if (data.productBulkDelete.errors.length === 0) { - closeModal(); - notify({ - text: intl.formatMessage(commonMessages.savedChanges) - }); - refetch(); - reset(); - } - }; - const { loadNextPage, loadPreviousPage, pageInfo } = paginate( params.activeTab === CategoryPageTab.categories ? maybe(() => data.category.children.pageInfo) @@ -159,194 +175,191 @@ export const CategoryDetails: React.FC = ({ params ); + const handleUpdate = async (formData: FormData) => { + const result = await updateCategory({ + variables: { + id, + input: { + backgroundImageAlt: formData.backgroundImageAlt, + descriptionJson: JSON.stringify(formData.description), + name: formData.name, + seo: { + description: formData.seoDescription, + title: formData.seoTitle + } + } + } + }); + + return result.data.categoryUpdate.errors; + }; + const handleSubmit = createMetadataUpdateHandler( + data?.category, + handleUpdate, + variables => updateMetadata({ variables }), + variables => updatePrivateMetadata({ variables }) + ); + return ( <> data.category.name)} /> - - {(productBulkDelete, productBulkDeleteOpts) => ( - <> - data.category)} - disabled={loading} - errors={updateResult.data?.categoryUpdate.errors || []} - onAddCategory={() => navigate(categoryAddUrl(id))} - onAddProduct={() => navigate(productAddUrl)} - onBack={() => - navigate( - maybe( - () => categoryUrl(data.category.parent.id), - categoryListUrl() - ) - ) + data.category)} + disabled={loading} + errors={updateResult.data?.categoryUpdate.errors || []} + onAddCategory={() => navigate(categoryAddUrl(id))} + onAddProduct={() => navigate(productAddUrl)} + onBack={() => + navigate( + maybe(() => categoryUrl(data.category.parent.id), categoryListUrl()) + ) + } + onCategoryClick={id => () => navigate(categoryUrl(id))} + onDelete={() => openModal("delete")} + onImageDelete={() => + updateCategory({ + variables: { + id, + input: { + backgroundImage: null } - onCategoryClick={id => () => navigate(categoryUrl(id))} - onDelete={() => openModal("delete")} - onImageDelete={() => - updateCategory({ - variables: { - id, - input: { - backgroundImage: null - } - } - }) + } + }) + } + onImageUpload={file => + updateCategory({ + variables: { + id, + input: { + backgroundImage: file } - onImageUpload={file => - updateCategory({ - variables: { - id, - input: { - backgroundImage: file - } - } - }) - } - onNextPage={loadNextPage} - onPreviousPage={loadPreviousPage} - pageInfo={pageInfo} - onProductClick={id => () => navigate(productUrl(id))} - onSubmit={formData => - updateCategory({ - variables: { - id, - input: { - backgroundImageAlt: formData.backgroundImageAlt, - descriptionJson: JSON.stringify(formData.description), - name: formData.name, - seo: { - description: formData.seoDescription, - title: formData.seoTitle - } - } - } - }) - } - products={maybe(() => - data.category.products.edges.map(edge => edge.node) - )} - saveButtonBarState={updateResult.status} - subcategories={maybe(() => - data.category.children.edges.map(edge => edge.node) - )} - subcategoryListToolbar={ - - openModal("delete-categories", { - ids: listElements - }) - } - > - - - } - productListToolbar={ - - openModal("delete-products", { - ids: listElements - }) - } - > - - - } - isChecked={isSelected} - selected={listElements.length} - toggle={toggle} - toggleAll={toggleAll} - /> - deleteCategory({ variables: { id } })} - open={params.action === "delete"} - title={intl.formatMessage({ - defaultMessage: "Delete category", - description: "dialog title" - })} - variant="delete" - > - - {maybe(() => data.category.name, "...")} - ) - }} - /> - - - - - - params.ids.length > 0) - } - confirmButtonState={categoryBulkDeleteOpts.status} - onClose={closeModal} - onConfirm={() => - categoryBulkDelete({ - variables: { ids: params.ids } - }).then(() => refetch()) - } - title={intl.formatMessage({ - defaultMessage: "Delete categories", - description: "dialog title" - })} - variant="delete" - > - - params.ids.length), - displayQuantity: ( - {maybe(() => params.ids.length)} - ) - }} - /> - - - - - - - productBulkDelete({ - variables: { ids: params.ids } - }).then(() => refetch()) - } - title={intl.formatMessage({ - defaultMessage: "Delete products", - description: "dialog title" - })} - variant="delete" - > - - params.ids.length), - displayQuantity: ( - {maybe(() => params.ids.length)} - ) - }} - /> - - - + } + }) + } + onNextPage={loadNextPage} + onPreviousPage={loadPreviousPage} + pageInfo={pageInfo} + onProductClick={id => () => navigate(productUrl(id))} + onSubmit={handleSubmit} + products={maybe(() => + data.category.products.edges.map(edge => edge.node) )} - + saveButtonBarState={updateResult.status} + subcategories={maybe(() => + data.category.children.edges.map(edge => edge.node) + )} + subcategoryListToolbar={ + + openModal("delete-categories", { + ids: listElements + }) + } + > + + + } + productListToolbar={ + + openModal("delete-products", { + ids: listElements + }) + } + > + + + } + isChecked={isSelected} + selected={listElements.length} + toggle={toggle} + toggleAll={toggleAll} + /> + deleteCategory({ variables: { id } })} + open={params.action === "delete"} + title={intl.formatMessage({ + defaultMessage: "Delete category", + description: "dialog title" + })} + variant="delete" + > + + {maybe(() => data.category.name, "...")} + ) + }} + /> + + + + + + params.ids.length > 0) + } + confirmButtonState={categoryBulkDeleteOpts.status} + onClose={closeModal} + onConfirm={() => + categoryBulkDelete({ + variables: { ids: params.ids } + }).then(() => refetch()) + } + title={intl.formatMessage({ + defaultMessage: "Delete categories", + description: "dialog title" + })} + variant="delete" + > + + params.ids.length), + displayQuantity: {maybe(() => params.ids.length)} + }} + /> + + + + + + + productBulkDelete({ + variables: { ids: params.ids } + }).then(() => refetch()) + } + title={intl.formatMessage({ + defaultMessage: "Delete products", + description: "dialog title" + })} + variant="delete" + > + + params.ids.length), + displayQuantity: {maybe(() => params.ids.length)} + }} + /> + + ); }; diff --git a/src/categories/views/CategoryList/CategoryList.tsx b/src/categories/views/CategoryList/CategoryList.tsx index 5363e67a8..ca2587b8d 100644 --- a/src/categories/views/CategoryList/CategoryList.tsx +++ b/src/categories/views/CategoryList/CategoryList.tsx @@ -1,9 +1,6 @@ import DialogContentText from "@material-ui/core/DialogContentText"; import IconButton from "@material-ui/core/IconButton"; import DeleteIcon from "@material-ui/icons/Delete"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import ActionDialog from "@saleor/components/ActionDialog"; import DeleteFilterTabDialog from "@saleor/components/DeleteFilterTabDialog"; import SaveFilterTabDialog, { @@ -17,9 +14,12 @@ import usePaginator, { } from "@saleor/hooks/usePaginator"; import { maybe } from "@saleor/misc"; import { ListViews } from "@saleor/types"; -import { getSortParams } from "@saleor/utils/sort"; -import createSortHandler from "@saleor/utils/handlers/sortHandler"; import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; +import createSortHandler from "@saleor/utils/handlers/sortHandler"; +import { getSortParams } from "@saleor/utils/sort"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { CategoryListPage } from "../../components/CategoryListPage/CategoryListPage"; import { useCategoryBulkDeleteMutation } from "../../mutations"; import { useRootCategoriesQuery } from "../../queries"; @@ -27,10 +27,10 @@ import { CategoryBulkDelete } from "../../types/CategoryBulkDelete"; import { categoryAddUrl, categoryListUrl, + CategoryListUrlDialog, CategoryListUrlFilters, CategoryListUrlQueryParams, - categoryUrl, - CategoryListUrlDialog + categoryUrl } from "../../urls"; import { areFiltersApplied, diff --git a/src/categories/views/CategoryList/filter.ts b/src/categories/views/CategoryList/filter.ts index f61179a63..fc42e95b9 100644 --- a/src/categories/views/CategoryList/filter.ts +++ b/src/categories/views/CategoryList/filter.ts @@ -1,4 +1,5 @@ import { CategoryFilterInput } from "@saleor/types/globalTypes"; + import { createFilterTabUtils, createFilterUtils diff --git a/src/collections/components/CollectionCreatePage/CollectionCreatePage.tsx b/src/collections/components/CollectionCreatePage/CollectionCreatePage.tsx index c6a3acabb..f31998883 100644 --- a/src/collections/components/CollectionCreatePage/CollectionCreatePage.tsx +++ b/src/collections/components/CollectionCreatePage/CollectionCreatePage.tsx @@ -1,27 +1,26 @@ -import Card from "@material-ui/core/Card"; -import CardContent from "@material-ui/core/CardContent"; -import { ContentState, convertToRaw, RawDraftContentState } from "draft-js"; -import React from "react"; -import { useIntl } from "react-intl"; - import AppHeader from "@saleor/components/AppHeader"; import { CardSpacer } from "@saleor/components/CardSpacer"; -import CardTitle from "@saleor/components/CardTitle"; import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; import { Container } from "@saleor/components/Container"; import Form from "@saleor/components/Form"; import Grid from "@saleor/components/Grid"; +import Metadata, { MetadataFormData } from "@saleor/components/Metadata"; import PageHeader from "@saleor/components/PageHeader"; import SaveButtonBar from "@saleor/components/SaveButtonBar"; import SeoForm from "@saleor/components/SeoForm"; import VisibilityCard from "@saleor/components/VisibilityCard"; +import { ProductErrorFragment } from "@saleor/fragments/types/ProductErrorFragment"; import useDateLocalize from "@saleor/hooks/useDateLocalize"; -import { commonMessages, sectionNames } from "@saleor/intl"; -import { ProductErrorFragment } from "@saleor/attributes/types/ProductErrorFragment"; +import { sectionNames } from "@saleor/intl"; +import useMetadataChangeTrigger from "@saleor/utils/metadata/useMetadataChangeTrigger"; +import { ContentState, convertToRaw, RawDraftContentState } from "draft-js"; +import React from "react"; +import { useIntl } from "react-intl"; + import CollectionDetails from "../CollectionDetails/CollectionDetails"; import { CollectionImage } from "../CollectionImage/CollectionImage"; -export interface CollectionCreatePageFormData { +export interface CollectionCreatePageFormData extends MetadataFormData { backgroundImage: { url: string; value: string; @@ -51,7 +50,9 @@ const initialForm: CollectionCreatePageFormData = { backgroundImageAlt: "", description: convertToRaw(ContentState.createFromText("")), isPublished: false, + metadata: [], name: "", + privateMetadata: [], publicationDate: "", seoDescription: "", seoTitle: "" @@ -66,122 +67,123 @@ const CollectionCreatePage: React.FC = ({ }: CollectionCreatePageProps) => { const intl = useIntl(); const localizeDate = useDateLocalize(); + const { + makeChangeHandler: makeMetadataChangeHandler + } = useMetadataChangeTrigger(); return (
- {({ change, data, hasChanged, submit }) => ( - - - {intl.formatMessage(sectionNames.collections)} - - - -
- - - - change({ - target: { - name: "backgroundImage", - value: { - url: null, - value: null - } - } - } as any) - } - onImageUpload={file => - change({ - target: { - name: "backgroundImage", - value: { - url: URL.createObjectURL(file), - value: file - } - } - } as any) - } - onChange={change} - data={data} - /> - - -
-
+ {({ change, data, hasChanged, submit }) => { + const changeMetadata = makeMetadataChangeHandler(change); + + return ( + + + {intl.formatMessage(sectionNames.collections)} + + +
- - - - + + + change({ + target: { + name: "backgroundImage", + value: { + url: null, + value: null } - )} - /> - - + } + } as any) + } + onImageUpload={file => + change({ + target: { + name: "backgroundImage", + value: { + url: URL.createObjectURL(file), + value: file + } + } + } as any) + } + onChange={change} + data={data} + /> + + + +
-
-
- -
- )} +
+ +
+ + + + ); + }} ); }; diff --git a/src/collections/components/CollectionDetails/CollectionDetails.tsx b/src/collections/components/CollectionDetails/CollectionDetails.tsx index c63bc1dea..2de3ae015 100644 --- a/src/collections/components/CollectionDetails/CollectionDetails.tsx +++ b/src/collections/components/CollectionDetails/CollectionDetails.tsx @@ -1,17 +1,17 @@ import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; import TextField from "@material-ui/core/TextField"; +import CardTitle from "@saleor/components/CardTitle"; +import FormSpacer from "@saleor/components/FormSpacer"; +import RichTextEditor from "@saleor/components/RichTextEditor"; +import { ProductErrorFragment } from "@saleor/fragments/types/ProductErrorFragment"; +import { commonMessages } from "@saleor/intl"; +import { maybe } from "@saleor/misc"; +import { getFormErrors, getProductErrorMessage } from "@saleor/utils/errors"; import { RawDraftContentState } from "draft-js"; import React from "react"; import { useIntl } from "react-intl"; -import CardTitle from "@saleor/components/CardTitle"; -import FormSpacer from "@saleor/components/FormSpacer"; -import RichTextEditor from "@saleor/components/RichTextEditor"; -import { commonMessages } from "@saleor/intl"; -import { maybe } from "@saleor/misc"; -import { getProductErrorMessage, getFormErrors } from "@saleor/utils/errors"; -import { ProductErrorFragment } from "@saleor/attributes/types/ProductErrorFragment"; import { CollectionDetails_collection } from "../../types/CollectionDetails"; export interface CollectionDetailsProps { diff --git a/src/collections/components/CollectionDetailsPage/CollectionDetailsPage.tsx b/src/collections/components/CollectionDetailsPage/CollectionDetailsPage.tsx index 106ba3463..8fba3282d 100644 --- a/src/collections/components/CollectionDetailsPage/CollectionDetailsPage.tsx +++ b/src/collections/components/CollectionDetailsPage/CollectionDetailsPage.tsx @@ -1,7 +1,3 @@ -import { RawDraftContentState } from "draft-js"; -import React from "react"; -import { useIntl } from "react-intl"; - import AppHeader from "@saleor/components/AppHeader"; import { CardSpacer } from "@saleor/components/CardSpacer"; import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; @@ -11,13 +7,21 @@ import Form from "@saleor/components/Form"; import FormSpacer from "@saleor/components/FormSpacer"; import Grid from "@saleor/components/Grid"; import Hr from "@saleor/components/Hr"; +import Metadata from "@saleor/components/Metadata/Metadata"; +import { MetadataFormData } from "@saleor/components/Metadata/types"; import PageHeader from "@saleor/components/PageHeader"; import SaveButtonBar from "@saleor/components/SaveButtonBar"; import SeoForm from "@saleor/components/SeoForm"; import VisibilityCard from "@saleor/components/VisibilityCard"; +import { ProductErrorFragment } from "@saleor/fragments/types/ProductErrorFragment"; import useDateLocalize from "@saleor/hooks/useDateLocalize"; import { sectionNames } from "@saleor/intl"; -import { ProductErrorFragment } from "@saleor/attributes/types/ProductErrorFragment"; +import { mapMetadataItemToInput } from "@saleor/utils/maps"; +import useMetadataChangeTrigger from "@saleor/utils/metadata/useMetadataChangeTrigger"; +import { RawDraftContentState } from "draft-js"; +import React from "react"; +import { useIntl } from "react-intl"; + import { maybe } from "../../../misc"; import { ListActions, PageListProps } from "../../../types"; import { CollectionDetails_collection } from "../../types/CollectionDetails"; @@ -25,7 +29,7 @@ import CollectionDetails from "../CollectionDetails/CollectionDetails"; import { CollectionImage } from "../CollectionImage/CollectionImage"; import CollectionProducts from "../CollectionProducts/CollectionProducts"; -export interface CollectionDetailsPageFormData { +export interface CollectionDetailsPageFormData extends MetadataFormData { backgroundImageAlt: string; description: RawDraftContentState; name: string; @@ -64,6 +68,24 @@ const CollectionDetailsPage: React.FC = ({ }: CollectionDetailsPageProps) => { const intl = useIntl(); const localizeDate = useDateLocalize(); + const { + isMetadataModified, + isPrivateMetadataModified, + makeChangeHandler: makeMetadataChangeHandler + } = useMetadataChangeTrigger(); + + const handleSubmit = (data: CollectionDetailsPageFormData) => { + const metadata = isMetadataModified ? data.metadata : undefined; + const privateMetadata = isPrivateMetadataModified + ? data.privateMetadata + : undefined; + + onSubmit({ + ...data, + metadata, + privateMetadata + }); + }; return (
= ({ description: maybe(() => JSON.parse(collection.descriptionJson)), isFeatured, isPublished: maybe(() => collection.isPublished, false), + metadata: collection?.metadata?.map(mapMetadataItemToInput), name: maybe(() => collection.name, ""), + privateMetadata: collection?.privateMetadata?.map( + mapMetadataItemToInput + ), publicationDate: maybe(() => collection.publicationDate, ""), seoDescription: maybe(() => collection.seoDescription, ""), seoTitle: maybe(() => collection.seoTitle, "") }} - onSubmit={onSubmit} + onSubmit={handleSubmit} confirmLeave > - {({ change, data, hasChanged, submit }) => ( - - - {intl.formatMessage(sectionNames.collections)} - - collection.name)} /> - -
- - - collection.backgroundImage)} - onImageDelete={onImageDelete} - onImageUpload={onImageUpload} - onChange={change} - /> - - - - collection.name)} - onChange={change} - /> -
-
+ {({ change, data, hasChanged, submit }) => { + const changeMetadata = makeMetadataChangeHandler(change); + + return ( + + + {intl.formatMessage(sectionNames.collections)} + + collection.name)} /> +
- - -
- -
+ /> + + collection.backgroundImage)} + onImageDelete={onImageDelete} + onImageUpload={onImageUpload} + onChange={change} + /> + + + + + + collection.name)} + onChange={change} + />
-
-
- -
- )} +
+
+ + +
+ +
+
+
+ + + + ); + }} ); }; diff --git a/src/collections/components/CollectionImage/CollectionImage.tsx b/src/collections/components/CollectionImage/CollectionImage.tsx index 6e96904c6..f17fb376c 100644 --- a/src/collections/components/CollectionImage/CollectionImage.tsx +++ b/src/collections/components/CollectionImage/CollectionImage.tsx @@ -1,17 +1,17 @@ -import { makeStyles } from "@material-ui/core/styles"; -import TextField from "@material-ui/core/TextField"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import Button from "@material-ui/core/Button"; import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; +import { makeStyles } from "@material-ui/core/styles"; +import TextField from "@material-ui/core/TextField"; import CardTitle from "@saleor/components/CardTitle"; import Hr from "@saleor/components/Hr"; import ImageTile from "@saleor/components/ImageTile"; import ImageUpload from "@saleor/components/ImageUpload"; import Skeleton from "@saleor/components/Skeleton"; import { commonMessages } from "@saleor/intl"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { CollectionDetails_collection_backgroundImage } from "../../types/CollectionDetails"; const useStyles = makeStyles( diff --git a/src/collections/components/CollectionList/CollectionList.tsx b/src/collections/components/CollectionList/CollectionList.tsx index 8657460a6..d46c53de0 100644 --- a/src/collections/components/CollectionList/CollectionList.tsx +++ b/src/collections/components/CollectionList/CollectionList.tsx @@ -3,20 +3,20 @@ import TableBody from "@material-ui/core/TableBody"; import TableCell from "@material-ui/core/TableCell"; import TableFooter from "@material-ui/core/TableFooter"; import TableRow from "@material-ui/core/TableRow"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - +import { CollectionListUrlSortField } from "@saleor/collections/urls"; import Checkbox from "@saleor/components/Checkbox"; import ResponsiveTable from "@saleor/components/ResponsiveTable"; import Skeleton from "@saleor/components/Skeleton"; import StatusLabel from "@saleor/components/StatusLabel"; +import TableCellHeader from "@saleor/components/TableCellHeader"; import TableHead from "@saleor/components/TableHead"; import TablePagination from "@saleor/components/TablePagination"; import { maybe, renderCollection } from "@saleor/misc"; import { ListActions, ListProps, SortPage } from "@saleor/types"; -import { CollectionListUrlSortField } from "@saleor/collections/urls"; -import TableCellHeader from "@saleor/components/TableCellHeader"; import { getArrowDirection } from "@saleor/utils/sort"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { CollectionList_collections_edges_node } from "../../types/CollectionList"; const useStyles = makeStyles( @@ -150,8 +150,8 @@ const CollectionList: React.FC = props => { onClick={collection ? onRowClick(collection.id) : undefined} key={collection ? collection.id : "skeleton"} selected={isSelected} - data-tc="id" - data-tc-id={maybe(() => collection.id)} + data-test="id" + data-test-id={maybe(() => collection.id)} > = props => { onChange={() => toggle(collection.id)} /> - + {maybe(() => collection.name, )} @@ -172,8 +172,8 @@ const CollectionList: React.FC = props => { collection.isPublished)} + data-test="published" + data-test-published={maybe(() => collection.isPublished)} > {maybe( () => ( diff --git a/src/collections/components/CollectionListPage/CollectionListPage.tsx b/src/collections/components/CollectionListPage/CollectionListPage.tsx index dcf23c717..0a709ef05 100644 --- a/src/collections/components/CollectionListPage/CollectionListPage.tsx +++ b/src/collections/components/CollectionListPage/CollectionListPage.tsx @@ -1,20 +1,20 @@ import Button from "@material-ui/core/Button"; import Card from "@material-ui/core/Card"; +import { CollectionListUrlSortField } from "@saleor/collections/urls"; +import { Container } from "@saleor/components/Container"; +import FilterBar from "@saleor/components/FilterBar"; +import PageHeader from "@saleor/components/PageHeader"; +import { sectionNames } from "@saleor/intl"; +import { + FilterPageProps, + ListActions, + PageListProps, + SortPage, + TabPageProps +} from "@saleor/types"; import React from "react"; import { FormattedMessage, useIntl } from "react-intl"; -import { Container } from "@saleor/components/Container"; -import PageHeader from "@saleor/components/PageHeader"; -import FilterBar from "@saleor/components/FilterBar"; -import { sectionNames } from "@saleor/intl"; -import { - ListActions, - PageListProps, - FilterPageProps, - TabPageProps, - SortPage -} from "@saleor/types"; -import { CollectionListUrlSortField } from "@saleor/collections/urls"; import { CollectionList_collections_edges_node } from "../../types/CollectionList"; import CollectionList from "../CollectionList/CollectionList"; import { diff --git a/src/collections/components/CollectionListPage/filters.ts b/src/collections/components/CollectionListPage/filters.ts index fdcd1478e..09b0fdd6e 100644 --- a/src/collections/components/CollectionListPage/filters.ts +++ b/src/collections/components/CollectionListPage/filters.ts @@ -1,10 +1,9 @@ -import { defineMessages, IntlShape } from "react-intl"; - +import { IFilter } from "@saleor/components/Filter"; import { commonMessages } from "@saleor/intl"; import { FilterOpts } from "@saleor/types"; import { CollectionPublished } from "@saleor/types/globalTypes"; -import { IFilter } from "@saleor/components/Filter"; import { createOptionsField } from "@saleor/utils/filters/fields"; +import { defineMessages, IntlShape } from "react-intl"; export interface CollectionListFilterOpts { status: FilterOpts; diff --git a/src/collections/components/CollectionProducts/CollectionProducts.tsx b/src/collections/components/CollectionProducts/CollectionProducts.tsx index 6d007651b..d5dd384d9 100644 --- a/src/collections/components/CollectionProducts/CollectionProducts.tsx +++ b/src/collections/components/CollectionProducts/CollectionProducts.tsx @@ -7,9 +7,6 @@ import TableCell from "@material-ui/core/TableCell"; import TableFooter from "@material-ui/core/TableFooter"; import TableRow from "@material-ui/core/TableRow"; import DeleteIcon from "@material-ui/icons/Delete"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import CardTitle from "@saleor/components/CardTitle"; import Checkbox from "@saleor/components/Checkbox"; import ResponsiveTable from "@saleor/components/ResponsiveTable"; @@ -20,6 +17,9 @@ import TableCellAvatar, { } from "@saleor/components/TableCellAvatar"; import TableHead from "@saleor/components/TableHead"; import TablePagination from "@saleor/components/TablePagination"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { maybe, renderCollection } from "../../../misc"; import { ListActions, PageListProps } from "../../../types"; import { CollectionDetails_collection } from "../../types/CollectionDetails"; diff --git a/src/collections/containers/CollectionOperations.tsx b/src/collections/containers/CollectionOperations.tsx deleted file mode 100644 index 9a65c37f1..000000000 --- a/src/collections/containers/CollectionOperations.tsx +++ /dev/null @@ -1,113 +0,0 @@ -import React from "react"; - -import { getMutationProviderData } from "../../misc"; -import { PartialMutationProviderOutput } from "../../types"; -import { - TypedCollectionAssignProductMutation, - TypedCollectionRemoveMutation, - TypedCollectionUpdateMutation, - TypedCollectionUpdateWithHomepageMutation, - TypedUnassignCollectionProductMutation -} from "../mutations"; -import { - CollectionAssignProduct, - CollectionAssignProductVariables -} from "../types/CollectionAssignProduct"; -import { - CollectionUpdate, - CollectionUpdateVariables -} from "../types/CollectionUpdate"; -import { - CollectionUpdateWithHomepage, - CollectionUpdateWithHomepageVariables -} from "../types/CollectionUpdateWithHomepage"; -import { - RemoveCollection, - RemoveCollectionVariables -} from "../types/RemoveCollection"; -import { - UnassignCollectionProduct, - UnassignCollectionProductVariables -} from "../types/UnassignCollectionProduct"; - -interface CollectionUpdateOperationsProps { - children: (props: { - updateCollectionWithHomepage: PartialMutationProviderOutput< - CollectionUpdateWithHomepage, - CollectionUpdateWithHomepageVariables - >; - assignProduct: PartialMutationProviderOutput< - CollectionAssignProduct, - CollectionAssignProductVariables - >; - unassignProduct: PartialMutationProviderOutput< - UnassignCollectionProduct, - UnassignCollectionProductVariables - >; - updateCollection: PartialMutationProviderOutput< - CollectionUpdate, - CollectionUpdateVariables - >; - removeCollection: PartialMutationProviderOutput< - RemoveCollection, - RemoveCollectionVariables - >; - }) => React.ReactNode; - onUpdate: (data: CollectionUpdate) => void; - onUpdateWithCollection: (data: CollectionUpdateWithHomepage) => void; - onProductAssign: (data: CollectionAssignProduct) => void; - onProductUnassign: (data: UnassignCollectionProduct) => void; - onRemove: (data: RemoveCollection) => void; -} - -const CollectionOperations: React.FC = ({ - children, - onUpdate, - onUpdateWithCollection, - onProductAssign, - onProductUnassign, - onRemove -}) => ( - - {(...updateCollection) => ( - - {(...removeCollection) => ( - - {(...assignProduct) => ( - - {(...updateWithHomepage) => ( - - {(...unassignProduct) => - children({ - assignProduct: getMutationProviderData( - ...assignProduct - ), - removeCollection: getMutationProviderData( - ...removeCollection - ), - unassignProduct: getMutationProviderData( - ...unassignProduct - ), - updateCollection: getMutationProviderData( - ...updateCollection - ), - updateCollectionWithHomepage: getMutationProviderData( - ...updateWithHomepage - ) - }) - } - - )} - - )} - - )} - - )} - -); -export default CollectionOperations; diff --git a/src/collections/fixtures.ts b/src/collections/fixtures.ts index 8fc75b09b..0119379c8 100644 --- a/src/collections/fixtures.ts +++ b/src/collections/fixtures.ts @@ -80,7 +80,15 @@ export const collection: ( descriptionJson: JSON.stringify(content), id: "Q29sbGVjdGlvbjox", isPublished: true, + metadata: [ + { + __typename: "MetadataItem", + key: "integration.id", + value: "100023123" + } + ], name: "Summer collection", + privateMetadata: [], products: { __typename: "ProductCountableConnection", edges: [ diff --git a/src/collections/index.tsx b/src/collections/index.tsx index 4c76b7bd8..9f9e5bf2e 100644 --- a/src/collections/index.tsx +++ b/src/collections/index.tsx @@ -1,18 +1,18 @@ +import { sectionNames } from "@saleor/intl"; +import { asSortParams } from "@saleor/utils/sort"; import { parse as parseQs } from "qs"; import React from "react"; import { useIntl } from "react-intl"; import { Route, RouteComponentProps, Switch } from "react-router-dom"; -import { sectionNames } from "@saleor/intl"; -import { asSortParams } from "@saleor/utils/sort"; import { WindowTitle } from "../components/WindowTitle"; import { collectionAddPath, collectionListPath, CollectionListUrlQueryParams, + CollectionListUrlSortField, collectionPath, - CollectionUrlQueryParams, - CollectionListUrlSortField + CollectionUrlQueryParams } from "./urls"; import CollectionCreate from "./views/CollectionCreate"; import CollectionDetailsView from "./views/CollectionDetails"; diff --git a/src/collections/mutations.ts b/src/collections/mutations.ts index b339d1a04..bf5fafa7c 100644 --- a/src/collections/mutations.ts +++ b/src/collections/mutations.ts @@ -1,11 +1,14 @@ -import gql from "graphql-tag"; - -import { productErrorFragment } from "@saleor/attributes/mutations"; -import { TypedMutation } from "../mutations"; import { collectionDetailsFragment, collectionProductFragment -} from "./queries"; +} from "@saleor/fragments/collections"; +import { + productErrorFragment, + shopErrorFragment +} from "@saleor/fragments/errors"; +import makeMutation from "@saleor/hooks/makeMutation"; +import gql from "graphql-tag"; + import { CollectionAssignProduct, CollectionAssignProductVariables @@ -39,13 +42,6 @@ import { UnassignCollectionProductVariables } from "./types/UnassignCollectionProduct"; -export const ShopErrorFragment = gql` - fragment ShopErrorFragment on ShopError { - code - field - } -`; - const collectionUpdate = gql` ${collectionDetailsFragment} ${productErrorFragment} @@ -60,7 +56,7 @@ const collectionUpdate = gql` } } `; -export const TypedCollectionUpdateMutation = TypedMutation< +export const useCollectionUpdateMutation = makeMutation< CollectionUpdate, CollectionUpdateVariables >(collectionUpdate); @@ -68,7 +64,7 @@ export const TypedCollectionUpdateMutation = TypedMutation< const collectionUpdateWithHomepage = gql` ${collectionDetailsFragment} ${productErrorFragment} - ${ShopErrorFragment} + ${shopErrorFragment} mutation CollectionUpdateWithHomepage( $id: ID! $input: CollectionInput! @@ -94,7 +90,7 @@ const collectionUpdateWithHomepage = gql` } } `; -export const TypedCollectionUpdateWithHomepageMutation = TypedMutation< +export const useCollectionUpdateWithHomepageMutation = makeMutation< CollectionUpdateWithHomepage, CollectionUpdateWithHomepageVariables >(collectionUpdateWithHomepage); @@ -133,7 +129,7 @@ const assignCollectionProduct = gql` } } `; -export const TypedCollectionAssignProductMutation = TypedMutation< +export const useCollectionAssignProductMutation = makeMutation< CollectionAssignProduct, CollectionAssignProductVariables >(assignCollectionProduct); @@ -152,7 +148,7 @@ const createCollection = gql` } } `; -export const TypedCollectionCreateMutation = TypedMutation< +export const useCollectionCreateMutation = makeMutation< CreateCollection, CreateCollectionVariables >(createCollection); @@ -167,7 +163,7 @@ const removeCollection = gql` } } `; -export const TypedCollectionRemoveMutation = TypedMutation< +export const useCollectionRemoveMutation = makeMutation< RemoveCollection, RemoveCollectionVariables >(removeCollection); @@ -217,7 +213,7 @@ const unassignCollectionProduct = gql` } } `; -export const TypedUnassignCollectionProductMutation = TypedMutation< +export const useUnassignCollectionProductMutation = makeMutation< UnassignCollectionProduct, UnassignCollectionProductVariables >(unassignCollectionProduct); @@ -232,7 +228,7 @@ const collectionBulkDelete = gql` } } `; -export const TypedCollectionBulkDelete = TypedMutation< +export const useCollectionBulkDelete = makeMutation< CollectionBulkDelete, CollectionBulkDeleteVariables >(collectionBulkDelete); @@ -247,7 +243,7 @@ const collectionBulkPublish = gql` } } `; -export const TypedCollectionBulkPublish = TypedMutation< +export const useCollectionBulkPublish = makeMutation< CollectionBulkPublish, CollectionBulkPublishVariables >(collectionBulkPublish); diff --git a/src/collections/queries.ts b/src/collections/queries.ts index b8230d0f9..c14d5b0e3 100644 --- a/src/collections/queries.ts +++ b/src/collections/queries.ts @@ -1,6 +1,11 @@ +import { + collectionDetailsFragment, + collectionFragment, + collectionProductFragment +} from "@saleor/fragments/collections"; +import makeQuery from "@saleor/hooks/makeQuery"; import gql from "graphql-tag"; -import makeQuery from "@saleor/hooks/makeQuery"; import { TypedQuery } from "../queries"; import { CollectionDetails, @@ -11,49 +16,6 @@ import { CollectionListVariables } from "./types/CollectionList"; -export const collectionFragment = gql` - fragment CollectionFragment on Collection { - id - isPublished - name - } -`; - -export const collectionDetailsFragment = gql` - ${collectionFragment} - fragment CollectionDetailsFragment on Collection { - ...CollectionFragment - backgroundImage { - alt - url - } - descriptionJson - publicationDate - seoDescription - seoTitle - isPublished - } -`; - -// This fragment is used to make sure that product's fields that are returned -// are always the same - fixes apollo cache -// https://github.com/apollographql/apollo-client/issues/2496 -// https://github.com/apollographql/apollo-client/issues/3468 -export const collectionProductFragment = gql` - fragment CollectionProductFragment on Product { - id - isPublished - name - productType { - id - name - } - thumbnail { - url - } - } -`; - export const collectionList = gql` ${collectionFragment} query CollectionList( diff --git a/src/collections/types/AssignHomepageCollection.ts b/src/collections/types/AssignHomepageCollection.ts deleted file mode 100644 index 48c912009..000000000 --- a/src/collections/types/AssignHomepageCollection.ts +++ /dev/null @@ -1,36 +0,0 @@ -/* tslint:disable */ -// This file was automatically generated and should not be edited. - -// ==================================================== -// GraphQL mutation operation: AssignHomepageCollection -// ==================================================== - -export interface AssignHomepageCollection_homepageCollectionUpdate_errors { - __typename: "Error"; - field: string | null; - message: string | null; -} - -export interface AssignHomepageCollection_homepageCollectionUpdate_shop_homepageCollection { - __typename: "Collection"; - id: string; -} - -export interface AssignHomepageCollection_homepageCollectionUpdate_shop { - __typename: "Shop"; - homepageCollection: AssignHomepageCollection_homepageCollectionUpdate_shop_homepageCollection | null; -} - -export interface AssignHomepageCollection_homepageCollectionUpdate { - __typename: "HomepageCollectionUpdate"; - errors: AssignHomepageCollection_homepageCollectionUpdate_errors[] | null; - shop: AssignHomepageCollection_homepageCollectionUpdate_shop | null; -} - -export interface AssignHomepageCollection { - homepageCollectionUpdate: AssignHomepageCollection_homepageCollectionUpdate | null; -} - -export interface AssignHomepageCollectionVariables { - id?: string | null; -} diff --git a/src/collections/types/CollectionDetails.ts b/src/collections/types/CollectionDetails.ts index 4f24c83ce..f46367d6a 100644 --- a/src/collections/types/CollectionDetails.ts +++ b/src/collections/types/CollectionDetails.ts @@ -6,6 +6,18 @@ // GraphQL query operation: CollectionDetails // ==================================================== +export interface CollectionDetails_collection_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface CollectionDetails_collection_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface CollectionDetails_collection_backgroundImage { __typename: "Image"; alt: string | null; @@ -56,6 +68,8 @@ export interface CollectionDetails_collection { id: string; isPublished: boolean; name: string; + metadata: (CollectionDetails_collection_metadata | null)[]; + privateMetadata: (CollectionDetails_collection_privateMetadata | null)[]; backgroundImage: CollectionDetails_collection_backgroundImage | null; descriptionJson: any; publicationDate: any | null; diff --git a/src/collections/types/CollectionUpdate.ts b/src/collections/types/CollectionUpdate.ts index 42f43cfd5..a3b85081f 100644 --- a/src/collections/types/CollectionUpdate.ts +++ b/src/collections/types/CollectionUpdate.ts @@ -8,6 +8,18 @@ import { CollectionInput, ProductErrorCode } from "./../../types/globalTypes"; // GraphQL mutation operation: CollectionUpdate // ==================================================== +export interface CollectionUpdate_collectionUpdate_collection_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface CollectionUpdate_collectionUpdate_collection_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface CollectionUpdate_collectionUpdate_collection_backgroundImage { __typename: "Image"; alt: string | null; @@ -19,6 +31,8 @@ export interface CollectionUpdate_collectionUpdate_collection { id: string; isPublished: boolean; name: string; + metadata: (CollectionUpdate_collectionUpdate_collection_metadata | null)[]; + privateMetadata: (CollectionUpdate_collectionUpdate_collection_privateMetadata | null)[]; backgroundImage: CollectionUpdate_collectionUpdate_collection_backgroundImage | null; descriptionJson: any; publicationDate: any | null; diff --git a/src/collections/types/CollectionUpdateWithHomepage.ts b/src/collections/types/CollectionUpdateWithHomepage.ts index a51f43b1e..d034e7cfe 100644 --- a/src/collections/types/CollectionUpdateWithHomepage.ts +++ b/src/collections/types/CollectionUpdateWithHomepage.ts @@ -30,6 +30,18 @@ export interface CollectionUpdateWithHomepage_homepageCollectionUpdate { shop: CollectionUpdateWithHomepage_homepageCollectionUpdate_shop | null; } +export interface CollectionUpdateWithHomepage_collectionUpdate_collection_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface CollectionUpdateWithHomepage_collectionUpdate_collection_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface CollectionUpdateWithHomepage_collectionUpdate_collection_backgroundImage { __typename: "Image"; alt: string | null; @@ -41,6 +53,8 @@ export interface CollectionUpdateWithHomepage_collectionUpdate_collection { id: string; isPublished: boolean; name: string; + metadata: (CollectionUpdateWithHomepage_collectionUpdate_collection_metadata | null)[]; + privateMetadata: (CollectionUpdateWithHomepage_collectionUpdate_collection_privateMetadata | null)[]; backgroundImage: CollectionUpdateWithHomepage_collectionUpdate_collection_backgroundImage | null; descriptionJson: any; publicationDate: any | null; diff --git a/src/collections/types/CreateCollection.ts b/src/collections/types/CreateCollection.ts index 2a5ea5d9d..7f1646436 100644 --- a/src/collections/types/CreateCollection.ts +++ b/src/collections/types/CreateCollection.ts @@ -8,6 +8,18 @@ import { CollectionCreateInput, ProductErrorCode } from "./../../types/globalTyp // GraphQL mutation operation: CreateCollection // ==================================================== +export interface CreateCollection_collectionCreate_collection_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface CreateCollection_collectionCreate_collection_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface CreateCollection_collectionCreate_collection_backgroundImage { __typename: "Image"; alt: string | null; @@ -19,6 +31,8 @@ export interface CreateCollection_collectionCreate_collection { id: string; isPublished: boolean; name: string; + metadata: (CreateCollection_collectionCreate_collection_metadata | null)[]; + privateMetadata: (CreateCollection_collectionCreate_collection_privateMetadata | null)[]; backgroundImage: CreateCollection_collectionCreate_collection_backgroundImage | null; descriptionJson: any; publicationDate: any | null; diff --git a/src/collections/types/SearchProducts.ts b/src/collections/types/SearchProducts.ts deleted file mode 100644 index 495338a8e..000000000 --- a/src/collections/types/SearchProducts.ts +++ /dev/null @@ -1,44 +0,0 @@ -/* tslint:disable */ -// This file was automatically generated and should not be edited. - -// ==================================================== -// GraphQL query operation: SearchProducts -// ==================================================== - -export interface SearchProducts_products_edges_node_productType { - __typename: "ProductType"; - id: string; - name: string; -} - -export interface SearchProducts_products_edges_node_thumbnail { - __typename: "Image"; - url: string; -} - -export interface SearchProducts_products_edges_node { - __typename: "Product"; - id: string; - isPublished: boolean; - name: string; - productType: SearchProducts_products_edges_node_productType; - thumbnail: SearchProducts_products_edges_node_thumbnail | null; -} - -export interface SearchProducts_products_edges { - __typename: "ProductCountableEdge"; - node: SearchProducts_products_edges_node; -} - -export interface SearchProducts_products { - __typename: "ProductCountableConnection"; - edges: SearchProducts_products_edges[]; -} - -export interface SearchProducts { - products: SearchProducts_products | null; -} - -export interface SearchProductsVariables { - query: string; -} diff --git a/src/collections/urls.ts b/src/collections/urls.ts index d22345b8a..65abf5b16 100644 --- a/src/collections/urls.ts +++ b/src/collections/urls.ts @@ -7,8 +7,8 @@ import { Dialog, Filters, Pagination, - TabActionDialog, - Sort + Sort, + TabActionDialog } from "../types"; const collectionSectionUrl = "/collections/"; diff --git a/src/collections/views/CollectionCreate.tsx b/src/collections/views/CollectionCreate.tsx index 345243306..ab2c29615 100644 --- a/src/collections/views/CollectionCreate.tsx +++ b/src/collections/views/CollectionCreate.tsx @@ -1,75 +1,93 @@ -import React from "react"; -import { useIntl } from "react-intl"; - import { WindowTitle } from "@saleor/components/WindowTitle"; import useNavigator from "@saleor/hooks/useNavigator"; import useNotifier from "@saleor/hooks/useNotifier"; import { commonMessages } from "@saleor/intl"; +import createMetadataCreateHandler from "@saleor/utils/handlers/metadataCreateHandler"; +import { + useMetadataUpdate, + usePrivateMetadataUpdate +} from "@saleor/utils/metadata/updateMetadata"; +import React from "react"; +import { useIntl } from "react-intl"; + import { CollectionCreateInput } from "../../types/globalTypes"; -import CollectionCreatePage from "../components/CollectionCreatePage/CollectionCreatePage"; -import { TypedCollectionCreateMutation } from "../mutations"; -import { CreateCollection } from "../types/CreateCollection"; +import CollectionCreatePage, { + CollectionCreatePageFormData +} from "../components/CollectionCreatePage/CollectionCreatePage"; +import { useCollectionCreateMutation } from "../mutations"; import { collectionListUrl, collectionUrl } from "../urls"; export const CollectionCreate: React.FC = () => { const navigate = useNavigator(); const notify = useNotifier(); const intl = useIntl(); + const [updateMetadata] = useMetadataUpdate({}); + const [updatePrivateMetadata] = usePrivateMetadataUpdate({}); - const handleCollectionCreateSuccess = (data: CreateCollection) => { - if (data.collectionCreate.errors.length === 0) { - notify({ - text: intl.formatMessage(commonMessages.savedChanges) - }); - navigate(collectionUrl(data.collectionCreate.collection.id)); - } else { - const backgroundImageError = data.collectionCreate.errors.find( - error => - error.field === ("backgroundImage" as keyof CollectionCreateInput) - ); - if (backgroundImageError) { + const [createCollection, createCollectionOpts] = useCollectionCreateMutation({ + onCompleted: data => { + if (data.collectionCreate.errors.length === 0) { notify({ - text: intl.formatMessage(commonMessages.somethingWentWrong) + status: "success", + text: intl.formatMessage(commonMessages.savedChanges) }); + navigate(collectionUrl(data.collectionCreate.collection.id)); + } else { + const backgroundImageError = data.collectionCreate.errors.find( + error => + error.field === ("backgroundImage" as keyof CollectionCreateInput) + ); + if (backgroundImageError) { + notify({ + status: "error", + text: intl.formatMessage(commonMessages.somethingWentWrong) + }); + } } } + }); + + const handleCreate = async (formData: CollectionCreatePageFormData) => { + const result = await createCollection({ + variables: { + input: { + backgroundImage: formData.backgroundImage.value, + backgroundImageAlt: formData.backgroundImageAlt, + descriptionJson: JSON.stringify(formData.description), + isPublished: formData.isPublished, + name: formData.name, + seo: { + description: formData.seoDescription, + title: formData.seoTitle + } + } + } + }); + + return result.data?.collectionCreate.collection?.id || null; }; + const handleSubmit = createMetadataCreateHandler( + handleCreate, + updateMetadata, + updatePrivateMetadata + ); + return ( - - {(createCollection, createCollectionOpts) => ( - <> - - navigate(collectionListUrl())} - disabled={createCollectionOpts.loading} - onSubmit={formData => - createCollection({ - variables: { - input: { - backgroundImage: formData.backgroundImage.value, - backgroundImageAlt: formData.backgroundImageAlt, - descriptionJson: JSON.stringify(formData.description), - isPublished: formData.isPublished, - name: formData.name, - seo: { - description: formData.seoDescription, - title: formData.seoTitle - } - } - } - }) - } - saveButtonBarState={createCollectionOpts.status} - /> - - )} - + <> + + navigate(collectionListUrl())} + disabled={createCollectionOpts.loading} + onSubmit={handleSubmit} + saveButtonBarState={createCollectionOpts.status} + /> + ); }; export default CollectionCreate; diff --git a/src/collections/views/CollectionDetails.tsx b/src/collections/views/CollectionDetails.tsx index f5cbe6b93..968238155 100644 --- a/src/collections/views/CollectionDetails.tsx +++ b/src/collections/views/CollectionDetails.tsx @@ -1,10 +1,8 @@ import Button from "@material-ui/core/Button"; import DialogContentText from "@material-ui/core/DialogContentText"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import ActionDialog from "@saleor/components/ActionDialog"; import AssignProductDialog from "@saleor/components/AssignProductDialog"; +import NotFoundPage from "@saleor/components/NotFoundPage"; import { WindowTitle } from "@saleor/components/WindowTitle"; import { DEFAULT_INITIAL_SEARCH_DATA, PAGINATE_BY } from "@saleor/config"; import useBulkActions from "@saleor/hooks/useBulkActions"; @@ -16,26 +14,35 @@ import usePaginator, { import { commonMessages } from "@saleor/intl"; import useProductSearch from "@saleor/searches/useProductSearch"; import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; -import NotFoundPage from "@saleor/components/NotFoundPage"; +import createMetadataUpdateHandler from "@saleor/utils/handlers/metadataUpdateHandler"; +import { + useMetadataUpdate, + usePrivateMetadataUpdate +} from "@saleor/utils/metadata/updateMetadata"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { getMutationState, maybe } from "../../misc"; import { productUrl } from "../../products/urls"; import { CollectionInput } from "../../types/globalTypes"; import CollectionDetailsPage, { CollectionDetailsPageFormData } from "../components/CollectionDetailsPage/CollectionDetailsPage"; -import CollectionOperations from "../containers/CollectionOperations"; +import { + useCollectionAssignProductMutation, + useCollectionRemoveMutation, + useCollectionUpdateMutation, + useCollectionUpdateWithHomepageMutation, + useUnassignCollectionProductMutation +} from "../mutations"; import { TypedCollectionDetailsQuery } from "../queries"; -import { CollectionAssignProduct } from "../types/CollectionAssignProduct"; import { CollectionUpdate } from "../types/CollectionUpdate"; -import { RemoveCollection } from "../types/RemoveCollection"; -import { UnassignCollectionProduct } from "../types/UnassignCollectionProduct"; import { collectionListUrl, collectionUrl, - CollectionUrlQueryParams, - CollectionUrlDialog + CollectionUrlDialog, + CollectionUrlQueryParams } from "../urls"; -import { CollectionUpdateWithHomepage } from "../types/CollectionUpdateWithHomepage"; interface CollectionDetailsProps { id: string; @@ -56,6 +63,90 @@ export const CollectionDetails: React.FC = ({ const { search, result } = useProductSearch({ variables: DEFAULT_INITIAL_SEARCH_DATA }); + const [updateMetadata] = useMetadataUpdate({}); + const [updatePrivateMetadata] = usePrivateMetadataUpdate({}); + + const handleCollectionUpdate = (data: CollectionUpdate) => { + if (data.collectionUpdate.errors.length === 0) { + notify({ + status: "success", + text: intl.formatMessage(commonMessages.savedChanges) + }); + navigate(collectionUrl(id)); + } else { + const backgroundImageError = data.collectionUpdate.errors.find( + error => error.field === ("backgroundImage" as keyof CollectionInput) + ); + if (backgroundImageError) { + notify({ + status: "error", + text: intl.formatMessage(commonMessages.somethingWentWrong) + }); + } + } + }; + const [updateCollection, updateCollectionOpts] = useCollectionUpdateMutation({ + onCompleted: handleCollectionUpdate + }); + + const [ + updateCollectionWithHomepage, + updateCollectionWithHomepageOpts + ] = useCollectionUpdateWithHomepageMutation({ + onCompleted: data => { + if (data.homepageCollectionUpdate.errors.length === 0) { + handleCollectionUpdate(data); + } + } + }); + + const [assignProduct, assignProductOpts] = useCollectionAssignProductMutation( + { + onCompleted: data => { + if (data.collectionAddProducts.errors.length === 0) { + notify({ + status: "success", + text: intl.formatMessage({ + defaultMessage: "Added product to collection" + }) + }); + navigate(collectionUrl(id), true); + } + } + } + ); + + const [ + unassignProduct, + unassignProductOpts + ] = useUnassignCollectionProductMutation({ + onCompleted: data => { + if (data.collectionRemoveProducts.errors.length === 0) { + notify({ + status: "success", + text: intl.formatMessage({ + defaultMessage: "Deleted product from collection" + }) + }); + reset(); + closeModal(); + } + } + }); + + const [removeCollection, removeCollectionOpts] = useCollectionRemoveMutation({ + onCompleted: data => { + if (data.collectionDelete.errors.length === 0) { + notify({ + status: "success", + text: intl.formatMessage({ + defaultMessage: "Deleted collection" + }) + }); + navigate(collectionListUrl()); + } + } + }); const [openModal, closeModal] = createDialogActionHandlers< CollectionUrlDialog, @@ -76,293 +167,236 @@ export const CollectionDetails: React.FC = ({ if (collection === null) { return ; } - const handleCollectionUpdate = (data: CollectionUpdate) => { - if (data.collectionUpdate.errors.length === 0) { - notify({ - text: intl.formatMessage(commonMessages.savedChanges) - }); - navigate(collectionUrl(id)); - } else { - const backgroundImageError = data.collectionUpdate.errors.find( - error => - error.field === ("backgroundImage" as keyof CollectionInput) - ); - if (backgroundImageError) { - notify({ - text: intl.formatMessage(commonMessages.somethingWentWrong) - }); - } - } - }; - const handleCollectioUpdateWithHomepage = ( - data: CollectionUpdateWithHomepage + + const handleUpdate = async ( + formData: CollectionDetailsPageFormData ) => { - if (data.homepageCollectionUpdate.errors.length === 0) { - handleCollectionUpdate(data); - } - }; + const input: CollectionInput = { + backgroundImageAlt: formData.backgroundImageAlt, + descriptionJson: JSON.stringify(formData.description), + isPublished: formData.isPublished, + name: formData.name, + publicationDate: formData.publicationDate, + seo: { + description: formData.seoDescription, + title: formData.seoTitle + } + }; + const isFeatured = data.shop.homepageCollection + ? data.shop.homepageCollection.id === data.collection.id + : false; - const handleProductAssign = (data: CollectionAssignProduct) => { - if (data.collectionAddProducts.errors.length === 0) { - notify({ - text: intl.formatMessage({ - defaultMessage: "Added product to collection" - }) + if (formData.isFeatured !== isFeatured) { + const result = await updateCollectionWithHomepage({ + variables: { + homepageId: formData.isFeatured ? id : null, + id, + input + } + }); + return [ + ...result.data.collectionUpdate.errors, + ...result.data.homepageCollectionUpdate.errors + ]; + } else { + const result = await updateCollection({ + variables: { + id, + input + } }); - navigate(collectionUrl(id), true); - } - }; - const handleProductUnassign = (data: UnassignCollectionProduct) => { - if (data.collectionRemoveProducts.errors.length === 0) { - notify({ - text: intl.formatMessage({ - defaultMessage: "Deleted product from collection" - }) - }); - reset(); - closeModal(); + return result.data.collectionUpdate.errors; } }; + const handleSubmit = createMetadataUpdateHandler( + data?.collection, + handleUpdate, + variables => updateMetadata({ variables }), + variables => updatePrivateMetadata({ variables }) + ); + + const formTransitionState = getMutationState( + updateCollectionOpts.called || + updateCollectionWithHomepageOpts.called, + updateCollectionOpts.loading || + updateCollectionWithHomepageOpts.loading, + updateCollectionOpts.data?.collectionUpdate.errors, + updateCollectionWithHomepageOpts.data?.collectionUpdate.errors, + updateCollectionWithHomepageOpts.data?.homepageCollectionUpdate.errors + ); + + const { loadNextPage, loadPreviousPage, pageInfo } = paginate( + data?.collection?.products?.pageInfo, + paginationState, + params + ); - const handleCollectionRemove = (data: RemoveCollection) => { - if (data.collectionDelete.errors.length === 0) { - notify({ - text: intl.formatMessage({ - defaultMessage: "Deleted collection" - }) - }); - navigate(collectionListUrl()); - } - }; return ( - - {({ - updateCollection, - updateCollectionWithHomepage, - assignProduct, - unassignProduct, - removeCollection - }) => { - const handleSubmit = ( - formData: CollectionDetailsPageFormData - ) => { - const input: CollectionInput = { - backgroundImageAlt: formData.backgroundImageAlt, - descriptionJson: JSON.stringify(formData.description), - isPublished: formData.isPublished, - name: formData.name, - publicationDate: formData.publicationDate, - seo: { - description: formData.seoDescription, - title: formData.seoTitle + <> + data.collection.name)} /> + openModal("assign")} + onBack={handleBack} + disabled={loading} + collection={data?.collection} + errors={updateCollectionOpts?.data?.collectionUpdate.errors || []} + isFeatured={maybe( + () => data.shop.homepageCollection.id === data.collection.id, + false + )} + onCollectionRemove={() => openModal("remove")} + onImageDelete={() => openModal("removeImage")} + onImageUpload={file => + updateCollection({ + variables: { + id, + input: { + backgroundImage: file + } } - }; - const isFeatured = data.shop.homepageCollection - ? data.shop.homepageCollection.id === data.collection.id - : false; - - if (formData.isFeatured !== isFeatured) { - updateCollectionWithHomepage.mutate({ - homepageId: formData.isFeatured ? id : null, - id, - input - }); - } else { - updateCollection.mutate({ - id, - input - }); - } - }; - - const formTransitionState = getMutationState( - updateCollection.opts.called || - updateCollectionWithHomepage.opts.called, - updateCollection.opts.loading || - updateCollectionWithHomepage.opts.loading, - maybe(() => updateCollection.opts.data.collectionUpdate.errors), - maybe( - () => - updateCollectionWithHomepage.opts.data.collectionUpdate - .errors - ), - maybe( - () => - updateCollectionWithHomepage.opts.data - .homepageCollectionUpdate.errors - ) - ); - - const { loadNextPage, loadPreviousPage, pageInfo } = paginate( - maybe(() => data.collection.products.pageInfo), - paginationState, - params - ); - - return ( - <> - data.collection.name)} /> - openModal("assign")} - onBack={handleBack} - disabled={loading} - collection={data?.collection} - errors={ - updateCollection.opts?.data?.collectionUpdate.errors || [] - } - isFeatured={maybe( - () => - data.shop.homepageCollection.id === data.collection.id, - false - )} - onCollectionRemove={() => openModal("remove")} - onImageDelete={() => openModal("removeImage")} - onImageUpload={file => - updateCollection.mutate({ - id, - input: { - backgroundImage: file - } - }) - } - onSubmit={handleSubmit} - onNextPage={loadNextPage} - onPreviousPage={loadPreviousPage} - pageInfo={pageInfo} - onProductUnassign={(productId, event) => { - event.stopPropagation(); - unassignProduct.mutate({ - collectionId: id, - productIds: [productId], - ...paginationState - }); - }} - onRowClick={id => () => navigate(productUrl(id))} - saveButtonBarState={formTransitionState} - toolbar={ - - } - isChecked={isSelected} - selected={listElements.length} - toggle={toggle} - toggleAll={toggleAll} + }) + } + onSubmit={handleSubmit} + onNextPage={loadNextPage} + onPreviousPage={loadPreviousPage} + pageInfo={pageInfo} + onProductUnassign={(productId, event) => { + event.stopPropagation(); + unassignProduct({ + variables: { + collectionId: id, + productIds: [productId], + ...paginationState + } + }); + }} + onRowClick={id => () => navigate(productUrl(id))} + saveButtonBarState={formTransitionState} + toolbar={ + + } + isChecked={isSelected} + selected={listElements.length} + toggle={toggle} + toggleAll={toggleAll} + /> + + assignProduct({ + variables: { + ...paginationState, + collectionId: id, + productIds: products.map(product => product.id) + } + }) + } + products={maybe(() => + result.data.search.edges + .map(edge => edge.node) + .filter(suggestedProduct => suggestedProduct.id) + )} + /> + + removeCollection({ + variables: { id } + }) + } + open={params.action === "remove"} + title={intl.formatMessage({ + defaultMessage: "Delete Collection", + description: "dialog title" + })} + variant="delete" + > + + + {maybe(() => data.collection.name, "...")} + + ) + }} + /> + + + + unassignProduct({ + variables: { + ...paginationState, + collectionId: id, + productIds: params.ids + } + }) + } + open={params.action === "unassign"} + title={intl.formatMessage({ + defaultMessage: "Unassign products from collection", + description: "dialog title" + })} + > + + params.ids.length), + displayQuantity: ( + {maybe(() => params.ids.length)} + ) + }} + /> + + + + updateCollection({ + variables: { + id, + input: { + backgroundImage: null } - products={maybe(() => - result.data.search.edges - .map(edge => edge.node) - .filter(suggestedProduct => suggestedProduct.id) - )} - /> - removeCollection.mutate({ id })} - open={params.action === "remove"} - title={intl.formatMessage({ - defaultMessage: "Delete Collection", - description: "dialog title" - })} - variant="delete" - > - - - {maybe(() => data.collection.name, "...")} - - ) - }} - /> - - - - unassignProduct.mutate({ - ...paginationState, - collectionId: id, - productIds: params.ids - }) - } - open={params.action === "unassign"} - title={intl.formatMessage({ - defaultMessage: "Unassign products from collection", - description: "dialog title" - })} - > - - params.ids.length), - displayQuantity: ( - {maybe(() => params.ids.length)} - ) - }} - /> - - - - updateCollection.mutate({ - id, - input: { - backgroundImage: null - } - }) - } - open={params.action === "removeImage"} - title={intl.formatMessage({ - defaultMessage: "Delete image", - description: "dialog title" - })} - variant="delete" - > - - - - - - ); - }} - + } + }) + } + open={params.action === "removeImage"} + title={intl.formatMessage({ + defaultMessage: "Delete image", + description: "dialog title" + })} + variant="delete" + > + + + + + ); }} diff --git a/src/collections/views/CollectionList/CollectionList.tsx b/src/collections/views/CollectionList/CollectionList.tsx index b5579d6aa..37693e38c 100644 --- a/src/collections/views/CollectionList/CollectionList.tsx +++ b/src/collections/views/CollectionList/CollectionList.tsx @@ -2,9 +2,6 @@ import Button from "@material-ui/core/Button"; import DialogContentText from "@material-ui/core/DialogContentText"; import IconButton from "@material-ui/core/IconButton"; import DeleteIcon from "@material-ui/icons/Delete"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import ActionDialog from "@saleor/components/ActionDialog"; import DeleteFilterTabDialog from "@saleor/components/DeleteFilterTabDialog"; import SaveFilterTabDialog, { @@ -17,38 +14,39 @@ import useNotifier from "@saleor/hooks/useNotifier"; import usePaginator, { createPaginationState } from "@saleor/hooks/usePaginator"; +import useShop from "@saleor/hooks/useShop"; import { commonMessages } from "@saleor/intl"; import { maybe } from "@saleor/misc"; import { ListViews } from "@saleor/types"; -import { getSortParams } from "@saleor/utils/sort"; -import createSortHandler from "@saleor/utils/handlers/sortHandler"; import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; -import useShop from "@saleor/hooks/useShop"; import createFilterHandlers from "@saleor/utils/handlers/filterHandlers"; +import createSortHandler from "@saleor/utils/handlers/sortHandler"; +import { getSortParams } from "@saleor/utils/sort"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import CollectionListPage from "../../components/CollectionListPage/CollectionListPage"; import { - TypedCollectionBulkDelete, - TypedCollectionBulkPublish + useCollectionBulkDelete, + useCollectionBulkPublish } from "../../mutations"; import { useCollectionListQuery } from "../../queries"; -import { CollectionBulkDelete } from "../../types/CollectionBulkDelete"; -import { CollectionBulkPublish } from "../../types/CollectionBulkPublish"; import { collectionAddUrl, collectionListUrl, + CollectionListUrlDialog, CollectionListUrlQueryParams, - collectionUrl, - CollectionListUrlDialog + collectionUrl } from "../../urls"; import { areFiltersApplied, deleteFilterTab, getActiveFilters, + getFilterOpts, + getFilterQueryParam, getFilterTabs, getFilterVariables, - saveFilterTab, - getFilterQueryParam, - getFilterOpts + saveFilterTab } from "./filters"; import { getSortQueryVariables } from "./sort"; @@ -83,6 +81,40 @@ export const CollectionList: React.FC = ({ params }) => { variables: queryVariables }); + const [ + collectionBulkDelete, + collectionBulkDeleteOpts + ] = useCollectionBulkDelete({ + onCompleted: data => { + if (data.collectionBulkDelete.errors.length === 0) { + notify({ + status: "success", + text: intl.formatMessage(commonMessages.savedChanges) + }); + refetch(); + reset(); + closeModal(); + } + } + }); + + const [ + collectionBulkPublish, + collectionBulkPublishOpts + ] = useCollectionBulkPublish({ + onCompleted: data => { + if (data.collectionBulkPublish.errors.length === 0) { + notify({ + status: "success", + text: intl.formatMessage(commonMessages.savedChanges) + }); + refetch(); + reset(); + closeModal(); + } + } + }); + const tabs = getFilterTabs(); const currentTab = @@ -136,223 +168,178 @@ export const CollectionList: React.FC = ({ params }) => { params ); - const handleCollectionBulkDelete = (data: CollectionBulkDelete) => { - if (data.collectionBulkDelete.errors.length === 0) { - notify({ - text: intl.formatMessage(commonMessages.savedChanges) - }); - refetch(); - reset(); - closeModal(); - } - }; - - const handleCollectionBulkPublish = (data: CollectionBulkPublish) => { - if (data.collectionBulkPublish.errors.length === 0) { - notify({ - text: intl.formatMessage(commonMessages.savedChanges) - }); - refetch(); - reset(); - closeModal(); - } - }; - const handleSort = createSortHandler(navigate, collectionListUrl, params); const currencySymbol = maybe(() => shop.defaultCurrency, "USD"); return ( - - {(collectionBulkDelete, collectionBulkDeleteOpts) => ( - - {(collectionBulkPublish, collectionBulkPublishOpts) => ( - <> - navigate(collectionAddUrl)} - onAll={resetFilters} - onTabChange={handleTabChange} - onTabDelete={() => openModal("delete-search")} - onTabSave={() => openModal("save-search")} - tabs={tabs.map(tab => tab.name)} - disabled={loading} - collections={maybe(() => - data.collections.edges.map(edge => edge.node) - )} - settings={settings} - onNextPage={loadNextPage} - onPreviousPage={loadPreviousPage} - onSort={handleSort} - onUpdateListSettings={updateListSettings} - pageInfo={pageInfo} - sort={getSortParams(params)} - onRowClick={id => () => navigate(collectionUrl(id))} - toolbar={ - <> - - - - openModal("remove", { - ids: listElements - }) - } - > - - - - } - isChecked={isSelected} - selected={listElements.length} - toggle={toggle} - toggleAll={toggleAll} + <> + navigate(collectionAddUrl)} + onAll={resetFilters} + onTabChange={handleTabChange} + onTabDelete={() => openModal("delete-search")} + onTabSave={() => openModal("save-search")} + tabs={tabs.map(tab => tab.name)} + disabled={loading} + collections={maybe(() => data.collections.edges.map(edge => edge.node))} + settings={settings} + onNextPage={loadNextPage} + onPreviousPage={loadPreviousPage} + onSort={handleSort} + onUpdateListSettings={updateListSettings} + pageInfo={pageInfo} + sort={getSortParams(params)} + onRowClick={id => () => navigate(collectionUrl(id))} + toolbar={ + <> + + + openModal("remove", { + ids: listElements + }) + } + > + + + + } + isChecked={isSelected} + selected={listElements.length} + toggle={toggle} + toggleAll={toggleAll} + /> + params.ids.length > 0)} + onClose={closeModal} + confirmButtonState={collectionBulkPublishOpts.status} + onConfirm={() => + collectionBulkPublish({ + variables: { + ids: params.ids, + isPublished: true + } + }) + } + variant="default" + title={intl.formatMessage({ + defaultMessage: "Publish collections", + description: "dialog title" + })} + > + + params.ids.length), + displayQuantity: {maybe(() => params.ids.length)} + }} + /> + + + params.ids.length > 0) + } + onClose={closeModal} + confirmButtonState={collectionBulkPublishOpts.status} + onConfirm={() => + collectionBulkPublish({ + variables: { + ids: params.ids, + isPublished: false + } + }) + } + variant="default" + title={intl.formatMessage({ + defaultMessage: "Unpublish collections", + description: "dialog title" + })} + > + + params.ids.length), + displayQuantity: {maybe(() => params.ids.length)} + }} + /> + + + params.ids.length > 0)} + onClose={closeModal} + confirmButtonState={collectionBulkDeleteOpts.status} + onConfirm={() => + collectionBulkDelete({ + variables: { + ids: params.ids + } + }) + } + variant="delete" + title={intl.formatMessage({ + defaultMessage: "Delete collections", + description: "dialog title" + })} + > + + params.ids.length), + displayQuantity: {maybe(() => params.ids.length)} + }} + /> + + + + tabs[currentTab - 1].name, "...")} + /> + ); }; export default CollectionList; diff --git a/src/collections/views/CollectionList/filters.test.ts b/src/collections/views/CollectionList/filters.test.ts index 1dc360a69..7e0bd32fb 100644 --- a/src/collections/views/CollectionList/filters.test.ts +++ b/src/collections/views/CollectionList/filters.test.ts @@ -1,13 +1,13 @@ -import { createIntl } from "react-intl"; -import { stringify as stringifyQs } from "qs"; - -import { CollectionListUrlFilters } from "@saleor/collections/urls"; import { createFilterStructure } from "@saleor/collections/components/CollectionListPage"; -import { getFilterQueryParams } from "@saleor/utils/filters"; +import { CollectionListUrlFilters } from "@saleor/collections/urls"; import { CollectionPublished } from "@saleor/types/globalTypes"; -import { config } from "@test/intl"; +import { getFilterQueryParams } from "@saleor/utils/filters"; import { getExistingKeys, setFilterOptsStatus } from "@test/filters"; -import { getFilterVariables, getFilterQueryParam } from "./filters"; +import { config } from "@test/intl"; +import { stringify as stringifyQs } from "qs"; +import { createIntl } from "react-intl"; + +import { getFilterQueryParam, getFilterVariables } from "./filters"; describe("Filtering query params", () => { it("should be empty object if no params given", () => { diff --git a/src/collections/views/CollectionList/filters.ts b/src/collections/views/CollectionList/filters.ts index 9b42354a5..c5d9a4fa1 100644 --- a/src/collections/views/CollectionList/filters.ts +++ b/src/collections/views/CollectionList/filters.ts @@ -1,23 +1,24 @@ +import { + CollectionFilterKeys, + CollectionListFilterOpts +} from "@saleor/collections/components/CollectionListPage"; +import { IFilterElement } from "@saleor/components/Filter"; +import { findValueInEnum, maybe } from "@saleor/misc"; import { CollectionFilterInput, CollectionPublished } from "@saleor/types/globalTypes"; -import { IFilterElement } from "@saleor/components/Filter"; -import { maybe, findValueInEnum } from "@saleor/misc"; -import { - CollectionListFilterOpts, - CollectionFilterKeys -} from "@saleor/collections/components/CollectionListPage"; -import { - CollectionListUrlFilters, - CollectionListUrlFiltersEnum, - CollectionListUrlQueryParams -} from "../../urls"; + import { createFilterTabUtils, createFilterUtils, getSingleEnumValueQueryParam } from "../../../utils/filters"; +import { + CollectionListUrlFilters, + CollectionListUrlFiltersEnum, + CollectionListUrlQueryParams +} from "../../urls"; export const COLLECTION_FILTERS_KEY = "collectionFilters"; diff --git a/src/components/Accordion/Accordion.stories.tsx b/src/components/Accordion/Accordion.stories.tsx new file mode 100644 index 000000000..752a160de --- /dev/null +++ b/src/components/Accordion/Accordion.stories.tsx @@ -0,0 +1,21 @@ +import CardDecorator from "@saleor/storybook/CardDecorator"; +import Decorator from "@saleor/storybook/Decorator"; +import { storiesOf } from "@storybook/react"; +import React from "react"; + +import Accordion from "./Accordion"; + +storiesOf("Generics / Accordion", module) + .addDecorator(Decorator) + .addDecorator(CardDecorator) + .add("default", () => Content) + .add("opened", () => ( + + Content + + )) + .add("with quick peek", () => ( + + Content + + )); diff --git a/src/components/Accordion/Accordion.tsx b/src/components/Accordion/Accordion.tsx new file mode 100644 index 000000000..59843aeae --- /dev/null +++ b/src/components/Accordion/Accordion.tsx @@ -0,0 +1,80 @@ +import IconButton from "@material-ui/core/IconButton"; +import makeStyles from "@material-ui/core/styles/makeStyles"; +import Typography from "@material-ui/core/Typography"; +import AddIcon from "@material-ui/icons/Add"; +import RemoveIcon from "@material-ui/icons/Remove"; +import classNames from "classnames"; +import React from "react"; + +import Hr from "../Hr"; + +const useStyles = makeStyles( + theme => ({ + content: { + padding: theme.spacing(3, 0) + }, + expandButton: { + position: "relative", + right: theme.spacing(-2), + top: theme.spacing(0.5) + }, + root: { + border: `1px solid ${theme.palette.divider}`, + borderRadius: 12, + padding: theme.spacing(0, 3) + }, + title: { + display: "flex", + justifyContent: "space-between" + }, + titleText: { + padding: theme.spacing(2, 0) + } + }), + { + name: "Accordion" + } +); + +export interface AccordionProps { + className?: string; + initialExpand?: boolean; + quickPeek?: React.ReactNode; + title: string; +} + +const Accordion: React.FC = ({ + children, + className, + initialExpand, + quickPeek, + title, + ...props +}) => { + const classes = useStyles({}); + const [expanded, setExpanded] = React.useState(!!initialExpand); + + return ( +
+
+ {title} +
+ setExpanded(!expanded)}> + {expanded ? : } + +
+
+ {(expanded || !!quickPeek) && ( + <> +
+
+ {quickPeek ? (expanded ? children : quickPeek) : children} +
+ + )} +
+ ); +}; + +Accordion.displayName = "Accordion"; +export default Accordion; diff --git a/src/components/Accordion/index.ts b/src/components/Accordion/index.ts new file mode 100644 index 000000000..0f4e089a0 --- /dev/null +++ b/src/components/Accordion/index.ts @@ -0,0 +1,2 @@ +export { default } from "./Accordion"; +export * from "./Accordion"; diff --git a/src/components/AccountPermissionGroups/AccountPermissionGroups.stories.tsx b/src/components/AccountPermissionGroups/AccountPermissionGroups.stories.tsx index 65bb2ffe8..f4228b142 100644 --- a/src/components/AccountPermissionGroups/AccountPermissionGroups.stories.tsx +++ b/src/components/AccountPermissionGroups/AccountPermissionGroups.stories.tsx @@ -1,9 +1,10 @@ +import { StaffErrorFragment } from "@saleor/fragments/types/StaffErrorFragment"; +import { SearchPermissionGroups_search_edges_node } from "@saleor/searches/types/SearchPermissionGroups"; +import Decorator from "@saleor/storybook/Decorator"; +import { AccountErrorCode } from "@saleor/types/globalTypes"; import { storiesOf } from "@storybook/react"; import React from "react"; -import Decorator from "@saleor/storybook/Decorator"; -import { SearchPermissionGroups_search_edges_node } from "@saleor/searches/types/SearchPermissionGroups"; -import { AccountErrorCode } from "@saleor/types/globalTypes"; -import { StaffErrorFragment } from "@saleor/staff/types/StaffErrorFragment"; + import { MultiAutocompleteChoiceType } from "../MultiAutocompleteSelectField"; import AccountPermissionGroups, { AccountPermissionGroupsProps } from "."; diff --git a/src/components/AccountPermissionGroups/AccountPermissionGroups.tsx b/src/components/AccountPermissionGroups/AccountPermissionGroups.tsx index 2314165e5..c3aa9c813 100644 --- a/src/components/AccountPermissionGroups/AccountPermissionGroups.tsx +++ b/src/components/AccountPermissionGroups/AccountPermissionGroups.tsx @@ -1,13 +1,13 @@ -import React from "react"; -import { useIntl } from "react-intl"; - import Typography from "@material-ui/core/Typography"; +import { StaffErrorFragment } from "@saleor/fragments/types/StaffErrorFragment"; import { FormChange } from "@saleor/hooks/useForm"; import { SearchPermissionGroups_search_edges_node } from "@saleor/searches/types/SearchPermissionGroups"; import { FetchMoreProps, SearchPageProps } from "@saleor/types"; import { getFormErrors } from "@saleor/utils/errors"; -import { StaffErrorFragment } from "@saleor/staff/types/StaffErrorFragment"; import getStaffErrorMessage from "@saleor/utils/errors/staff"; +import React from "react"; +import { useIntl } from "react-intl"; + import MultiAutocompleteSelectField, { MultiAutocompleteChoiceType } from "../MultiAutocompleteSelectField"; @@ -59,7 +59,7 @@ const AccountPermissionGroups: React.FC = props => value={formData?.permissionGroups} onChange={onChange} fetchChoices={onSearchChange} - data-tc="permissionGroups" + data-test="permissionGroups" onFetchMore={onFetchMore} hasMore={hasMore} loading={loading} diff --git a/src/components/AccountPermissions/AccountPermissions.tsx b/src/components/AccountPermissions/AccountPermissions.tsx index 1bcc23822..6a2a18562 100644 --- a/src/components/AccountPermissions/AccountPermissions.tsx +++ b/src/components/AccountPermissions/AccountPermissions.tsx @@ -1,20 +1,20 @@ -import React from "react"; -import { useIntl } from "react-intl"; +import { + Checkbox, + List, + ListItem, + ListItemIcon, + ListItemText +} from "@material-ui/core"; import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; import { makeStyles } from "@material-ui/core/styles"; import Typography from "@material-ui/core/Typography"; import CardTitle from "@saleor/components/CardTitle"; import Skeleton from "@saleor/components/Skeleton"; -import { - List, - ListItem, - ListItemText, - ListItemIcon, - Checkbox -} from "@material-ui/core"; import useUser from "@saleor/hooks/useUser"; import { PermissionData } from "@saleor/permissionGroups/components/PermissionGroupDetailsPage/PermissionGroupDetailsPage"; +import React from "react"; +import { useIntl } from "react-intl"; const useStyles = makeStyles( theme => ({ @@ -98,7 +98,7 @@ const AccountPermissions: React.FC = props => { {permissionsExceeded && ( <> - + {intl.formatMessage({ defaultMessage: "This groups permissions exceeds your own. You are able only to manage permissions that you have.", @@ -108,7 +108,7 @@ const AccountPermissions: React.FC = props => {
- + {intl.formatMessage({ defaultMessage: "Available permissions", description: "card section description" @@ -127,7 +127,7 @@ const AccountPermissions: React.FC = props => { {!permissionsExceeded && ( <> - {description} + {description} = props => { > = props => { > = props => { <>
- {errorMessage} + + {errorMessage} + )} diff --git a/src/components/AccountPermissions/utils.ts b/src/components/AccountPermissions/utils.ts index 10f2f5a57..4a790da52 100644 --- a/src/components/AccountPermissions/utils.ts +++ b/src/components/AccountPermissions/utils.ts @@ -1,5 +1,5 @@ -import { User_userPermissions } from "@saleor/auth/types/User"; import { ShopInfo_shop_permissions } from "@saleor/components/Shop/types/ShopInfo"; +import { User_userPermissions } from "@saleor/fragments/types/User"; import { PermissionGroupDetails_user_userPermissions } from "@saleor/permissionGroups/types/PermissionGroupDetails"; export const getLastSourcesOfPermission = ( diff --git a/src/components/AccountStatus/index.ts b/src/components/AccountStatus/index.ts deleted file mode 100644 index eb103372d..000000000 --- a/src/components/AccountStatus/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from "./AccountStatus"; -export * from "./AccountStatus"; diff --git a/src/components/ActionDialog/ActionDialog.tsx b/src/components/ActionDialog/ActionDialog.tsx index 737ce0723..c4b41cfb2 100644 --- a/src/components/ActionDialog/ActionDialog.tsx +++ b/src/components/ActionDialog/ActionDialog.tsx @@ -4,12 +4,12 @@ import DialogActions from "@material-ui/core/DialogActions"; import DialogContent from "@material-ui/core/DialogContent"; import DialogTitle from "@material-ui/core/DialogTitle"; import { makeStyles } from "@material-ui/core/styles"; +import { buttonMessages } from "@saleor/intl"; +import { DialogProps } from "@saleor/types"; import classNames from "classnames"; import React from "react"; import { FormattedMessage, useIntl } from "react-intl"; -import { buttonMessages } from "@saleor/intl"; -import { DialogProps } from "@saleor/types"; import ConfirmButton, { ConfirmButtonTransitionState } from "../ConfirmButton/ConfirmButton"; @@ -33,7 +33,7 @@ interface ActionDialogProps extends DialogProps { confirmButtonState: ConfirmButtonTransitionState; maxWidth?: "xs" | "sm" | "md" | "lg" | "xl" | false; title: string; - variant?: "default" | "delete"; + variant?: "default" | "delete" | "info"; onConfirm(); } @@ -61,20 +61,22 @@ const ActionDialog: React.FC = props => { - - {confirmButtonLabel || - (variant === "delete" - ? intl.formatMessage(buttonMessages.delete) - : intl.formatMessage(buttonMessages.confirm))} - + {variant !== "info" && ( + + {confirmButtonLabel || + (variant === "delete" + ? intl.formatMessage(buttonMessages.delete) + : intl.formatMessage(buttonMessages.confirm))} + + )} ); diff --git a/src/components/AddressEdit/AddressEdit.tsx b/src/components/AddressEdit/AddressEdit.tsx index 041bbd99d..136f5dfef 100644 --- a/src/components/AddressEdit/AddressEdit.tsx +++ b/src/components/AddressEdit/AddressEdit.tsx @@ -1,15 +1,15 @@ import { makeStyles } from "@material-ui/core/styles"; import TextField from "@material-ui/core/TextField"; -import React from "react"; -import { useIntl, IntlShape } from "react-intl"; - import { AddressTypeInput } from "@saleor/customers/types"; +import { AccountErrorFragment } from "@saleor/fragments/types/AccountErrorFragment"; +import { OrderErrorFragment } from "@saleor/fragments/types/OrderErrorFragment"; import { commonMessages } from "@saleor/intl"; import { getFormErrors } from "@saleor/utils/errors"; -import { AccountErrorFragment } from "@saleor/customers/types/AccountErrorFragment"; import getAccountErrorMessage from "@saleor/utils/errors/account"; -import { OrderErrorFragment } from "@saleor/orders/types/OrderErrorFragment"; import getOrderErrorMessage from "@saleor/utils/errors/order"; +import React from "react"; +import { IntlShape, useIntl } from "react-intl"; + import FormSpacer from "../FormSpacer"; import SingleAutocompleteSelectField, { SingleAutocompleteChoiceType diff --git a/src/components/AppHeader/AppHeader.tsx b/src/components/AppHeader/AppHeader.tsx index 5e5e11138..7f85264dd 100644 --- a/src/components/AppHeader/AppHeader.tsx +++ b/src/components/AppHeader/AppHeader.tsx @@ -3,6 +3,7 @@ import { makeStyles } from "@material-ui/core/styles"; import Typography from "@material-ui/core/Typography"; import ArrowBackIcon from "@material-ui/icons/ArrowBack"; import React from "react"; + import AppHeaderContext from "../AppLayout/AppHeaderContext"; import Skeleton from "../Skeleton"; @@ -33,7 +34,7 @@ const useStyles = makeStyles( marginTop: theme.spacing(0.5), transition: theme.transitions.duration.standard + "ms", [theme.breakpoints.down("sm")]: { - display: "none" + margin: theme.spacing(4, 0, 3, 0) } }, skeleton: { @@ -44,10 +45,7 @@ const useStyles = makeStyles( color: "inherit", flex: 1, marginLeft: theme.spacing(), - textTransform: "uppercase", - [theme.breakpoints.down("sm")]: { - display: "none" - } + textTransform: "uppercase" } }), { name: "AppHeader" } diff --git a/src/components/AppLayout/AppLayout.tsx b/src/components/AppLayout/AppLayout.tsx index 0decf3a2b..891ef3f09 100644 --- a/src/components/AppLayout/AppLayout.tsx +++ b/src/components/AppLayout/AppLayout.tsx @@ -1,39 +1,27 @@ -import Avatar from "@material-ui/core/Avatar"; -import Chip from "@material-ui/core/Chip"; -import ClickAwayListener from "@material-ui/core/ClickAwayListener"; -import Grow from "@material-ui/core/Grow"; -import Hidden from "@material-ui/core/Hidden"; import LinearProgress from "@material-ui/core/LinearProgress"; -import MenuItem from "@material-ui/core/MenuItem"; -import Menu from "@material-ui/core/MenuList"; -import Paper from "@material-ui/core/Paper"; -import Popper from "@material-ui/core/Popper"; -import { makeStyles } from "@material-ui/core/styles"; -import classNames from "classnames"; -import React from "react"; -import SVG from "react-inlinesvg"; -import { FormattedMessage, useIntl } from "react-intl"; -import useRouter from "use-react-router"; - -import saleorDarkLogoSmall from "@assets/images/logo-dark-small.svg"; -import saleorDarkLogo from "@assets/images/logo-dark.svg"; -import menuArrowIcon from "@assets/images/menu-arrow-icon.svg"; +import { makeStyles, Theme } from "@material-ui/core/styles"; +import useMediaQuery from "@material-ui/core/useMediaQuery"; import { createConfigurationMenu } from "@saleor/configuration"; import useAppState from "@saleor/hooks/useAppState"; -import useLocalStorage from "@saleor/hooks/useLocalStorage"; import useNavigator from "@saleor/hooks/useNavigator"; import useTheme from "@saleor/hooks/useTheme"; import useUser from "@saleor/hooks/useUser"; -import ArrowDropdown from "@saleor/icons/ArrowDropdown"; import { staffMemberDetailsUrl } from "@saleor/staff/urls"; +import React from "react"; +import { useIntl } from "react-intl"; +import useRouter from "use-react-router"; + import Container from "../Container"; import ErrorPage from "../ErrorPage"; +import Navigator from "../Navigator"; +import NavigatorButton from "../NavigatorButton/NavigatorButton"; +import SideBar from "../SideBar"; +import SideBarDrawer from "../SideBarDrawer/SideBarDrawer"; +import UserChip from "../UserChip"; import AppActionContext from "./AppActionContext"; import AppHeaderContext from "./AppHeaderContext"; -import { appLoaderHeight, drawerWidth, drawerWidthExpanded } from "./consts"; -import MenuList from "./MenuList"; +import { appLoaderHeight } from "./consts"; import createMenuStructure from "./menuStructure"; -import ResponsiveDrawer from "./ResponsiveDrawer"; import ThemeSwitch from "./ThemeSwitch"; const useStyles = makeStyles( @@ -50,231 +38,45 @@ const useStyles = makeStyles( }, appLoader: { height: appLoaderHeight, - marginBottom: theme.spacing(2), + marginBottom: theme.spacing(4), zIndex: 1201 }, appLoaderPlaceholder: { height: appLoaderHeight, - marginBottom: theme.spacing(2) - }, - arrow: { - marginLeft: theme.spacing(2), - transition: theme.transitions.duration.standard + "ms" - }, - avatar: { - "&&": { - height: 32, - width: 32 - } + marginBottom: theme.spacing(4) }, + content: { - [theme.breakpoints.down("sm")]: { - paddingLeft: 0 - }, - paddingLeft: drawerWidthExpanded, - transition: "padding-left 0.5s ease", - width: "100%" - }, - contentToggle: { - [theme.breakpoints.down("sm")]: { - paddingLeft: 0 - }, - paddingLeft: drawerWidth + flex: 1 }, darkThemeSwitch: { [theme.breakpoints.down("sm")]: { - marginRight: -theme.spacing(1.5) + marginRight: theme.spacing(1) }, marginRight: theme.spacing(2) }, header: { [theme.breakpoints.down("sm")]: { - height: 88, - marginBottom: 0 + height: "auto" }, display: "flex", height: 40, marginBottom: theme.spacing(3) }, - isMenuSmall: { - "& path": { - fill: theme.palette.primary.main - }, - "& span": { - margin: "0 8px" - }, - "& svg": { - marginTop: 8, - transform: "rotate(180deg)" - }, - "&:hover": { - background: "#E6F3F3" - }, - background: theme.palette.background.paper, - border: `solid 1px #EAEAEA`, - borderRadius: "50%", - cursor: "pointer", - height: 32, - position: "absolute", - right: -16, - top: 65, - transition: `background ${theme.transitions.duration.shorter}ms`, - width: 32, - zIndex: 99 - }, - isMenuSmallDark: { - "&:hover": { - background: `linear-gradient(0deg, rgba(25, 195, 190, 0.1), rgba(25, 195, 190, 0.1)), ${theme.palette.background.paper}` - }, - border: `solid 1px #252728`, - transition: `background ${theme.transitions.duration.shorter}ms` - }, - isMenuSmallHide: { - "& svg": { - marginLeft: "3px", - transform: "rotate(0deg)" - } - }, - logo: { - "& svg": { - left: "50%", - position: "absolute", - top: "50%", - transform: "translate(-50%,-50%)" - }, - background: theme.palette.secondary.main, - display: "block", - height: 80, - position: "relative" - }, - logoDark: { - "& path": { - fill: theme.palette.common.white - }, - background: theme.palette.primary.main - }, - logoSmall: { - "& svg": { - margin: 0, - padding: 0, - width: "80px" - } - }, - menu: { - background: theme.palette.background.paper, - height: "100vh", - padding: "25px 20px" - }, - menuIcon: { - "& span": { - "&:nth-child(1)": { - top: 15 - }, - "&:nth-child(2), &:nth-child(3)": { - top: 20 - }, - "&:nth-child(4)": { - top: 25 - }, - background: theme.palette.secondary.light, - display: "block", - height: 1, - left: "20%", - opacity: 1, - position: "absolute", - transform: "rotate(0deg)", - transition: ".25s ease-in-out", - width: "60%" - }, - [theme.breakpoints.up("md")]: { - display: "none" - }, - [theme.breakpoints.down("sm")]: { - left: 0 - }, - background: theme.palette.background.paper, - borderRadius: "50%", - cursor: "pointer", - height: 42, - left: theme.spacing(), - marginRight: theme.spacing(2), - position: "relative", - transform: "rotate(0deg)", - transition: `${theme.transitions.duration.shorter}ms ease-in-out`, - width: 42 - }, - menuIconDark: { - "& span": { - background: theme.palette.common.white - } - }, - menuIconOpen: { - "& span": { - "&:nth-child(1), &:nth-child(4)": { - left: "50%", - top: 20, - width: 0 - }, - "&:nth-child(2)": { - transform: "rotate(45deg)" - }, - "&:nth-child(3)": { - transform: "rotate(-45deg)" - } - }, - left: 280, - position: "absolute", - zIndex: 1999 - }, - menuSmall: { - background: theme.palette.background.paper, - height: "100vh", - overflow: "hidden", - padding: 25 - }, - popover: { - zIndex: 1 - }, + root: { + display: "flex", width: `100%` }, - rotate: { - transform: "rotate(180deg)" - }, - sideBar: { - [theme.breakpoints.down("sm")]: { - padding: 0 - }, - background: theme.palette.background.paper, - padding: `0 ${theme.spacing(4)}px` - }, spacer: { flex: 1 }, userBar: { - [theme.breakpoints.down("sm")]: { - alignItems: "flex-end", - flexDirection: "column-reverse", - overflow: "hidden" - }, alignItems: "center", display: "flex" }, - userChip: { - backgroundColor: theme.palette.background.paper, - borderRadius: 24, - color: theme.palette.text.primary, - height: 40, - padding: theme.spacing(0.5) - }, - userMenuContainer: { - position: "relative" - }, - userMenuItem: { - textAlign: "right" - }, + view: { - backgroundColor: theme.palette.background.default, flex: 1, flexGrow: 1, marginLeft: 0, @@ -284,7 +86,7 @@ const useStyles = makeStyles( } }, viewContainer: { - minHeight: `calc(100vh - ${theme.spacing(2) + appLoaderHeight + 70}px)` + minHeight: `calc(100vh - ${theme.spacing(4) + appLoaderHeight + 120}px)` } }), { @@ -299,17 +101,15 @@ interface AppLayoutProps { const AppLayout: React.FC = ({ children }) => { const classes = useStyles({}); const { isDark, toggleTheme } = useTheme(); - const [isMenuSmall, setMenuSmall] = useLocalStorage("isMenuSmall", false); - const [isDrawerOpened, setDrawerState] = React.useState(false); - const [isMenuOpened, setMenuState] = React.useState(false); const appActionAnchor = React.useRef(); const appHeaderAnchor = React.useRef(); - const anchor = React.useRef(); const { logout, user } = useUser(); const navigate = useNavigator(); const intl = useIntl(); const [appState, dispatchAppState] = useAppState(); const { location } = useRouter(); + const [isNavigatorVisible, setNavigatorVisibility] = React.useState(false); + const isMdUp = useMediaQuery((theme: Theme) => theme.breakpoints.up("md")); const menuStructure = createMenuStructure(intl); const configurationMenu = createConfigurationMenu(intl); @@ -324,27 +124,6 @@ const AppLayout: React.FC = ({ children }) => { ) ); - const handleLogout = () => { - setMenuState(false); - logout(); - }; - - const handleViewerProfile = () => { - setMenuState(false); - navigate(staffMemberDetailsUrl(user.id)); - }; - - const handleMenuItemClick = (url: string, event: React.MouseEvent) => { - event.stopPropagation(); - event.preventDefault(); - setDrawerState(false); - navigate(url); - }; - - const handleIsMenuSmall = () => { - setMenuSmall(!isMenuSmall); - }; - const handleErrorBack = () => { navigate("/"); dispatchAppState({ @@ -356,167 +135,82 @@ const AppLayout: React.FC = ({ children }) => { }; return ( - - -
-
- setDrawerState(false)} - open={isDrawerOpened} - small={!isMenuSmall} - > -
- -
- -
- -
-
- + + + +
+ {isMdUp && ( + - -
-
- {appState.loading ? ( - - ) : ( -
)} -
-
- -
-
setDrawerState(!isDrawerOpened)} - > - - - - -
-
-
-
- -
- - ) - } - classes={{ - avatar: classes.avatar - }} - className={classes.userChip} - label={ - <> - {user.email} - - - } - onClick={() => setMenuState(!isMenuOpened)} +
+ {appState.loading ? ( + + ) : ( +
+ )} +
+
+ +
+ {isMdUp &&
} + {!isMdUp && ( + + )} +
+
+ + setNavigatorVisibility(true)} + /> + + navigate(staffMemberDetailsUrl(user.id)) + } + user={user} /> - - {({ TransitionProps, placement }) => ( - - - setMenuState(false)} - mouseEvent="onClick" - > - - - - - - - - - - - - )} -
-
- + {!isMdUp &&
} + +
+
+ {appState.error + ? appState.error === "unhandled" && ( + + ) + : children} +
-
- {appState.error - ? appState.error === "unhandled" && ( - - ) - : children} -
+
-
-
- - + + + ); }; diff --git a/src/components/AppLayout/MenuList.tsx b/src/components/AppLayout/MenuList.tsx deleted file mode 100644 index 2ca3d9171..000000000 --- a/src/components/AppLayout/MenuList.tsx +++ /dev/null @@ -1,365 +0,0 @@ -import { makeStyles } from "@material-ui/core/styles"; -import Typography from "@material-ui/core/Typography"; -import classNames from "classnames"; -import React from "react"; -import SVG from "react-inlinesvg"; -import { FormattedMessage, useIntl } from "react-intl"; -import { matchPath } from "react-router"; - -import configureIcon from "@assets/images/menu-configure-icon.svg"; -import useTheme from "@saleor/hooks/useTheme"; -import { sectionNames } from "@saleor/intl"; -import { User } from "../../auth/types/User"; -import { - configurationMenuUrl, - createConfigurationMenu -} from "../../configuration"; -import { createHref } from "../../misc"; -import { orderDraftListUrl, orderListUrl } from "../../orders/urls"; -import MenuNested from "./MenuNested"; -import { IMenuItem } from "./menuStructure"; - -const useStyles = makeStyles( - theme => ({ - menuIcon: { - "& svg": { - height: 32, - width: 32 - }, - display: "inline-block", - position: "relative", - top: 8 - }, - menuIconDark: { - "& path": { - fill: theme.palette.common.white - } - }, - menuIconSmall: { - left: -5 - }, - menuIsActive: { - boxShadow: "0px 0px 12px 1px rgba(0,0,0,0.2)" - }, - menuItemHover: { - "& p": { - fontSize: 14, - transition: "color 0.5s ease, opacity 0.3s ease-out" - }, - "& path": { - transition: "fill 0.5s ease" - }, - "&:hover": { - "& p": { - color: theme.palette.primary.main - }, - "& path": { - fill: theme.palette.primary.main - }, - "&:before": { - borderLeft: `solid 2px ${theme.palette.primary.main}`, - content: "''", - height: 33, - left: -20, - position: "absolute", - top: 8 - }, - color: theme.palette.primary.main - }, - cursor: "pointer", - position: "relative" - }, - menuList: { - display: "flex", - flexDirection: "column", - height: "100%", - marginLeft: theme.spacing(4), - marginTop: theme.spacing(2), - paddingBottom: theme.spacing(3) - }, - menuListItem: { - alignItems: "center", - display: "block", - marginBottom: theme.spacing(5), - paddingLeft: 0, - textDecoration: "none", - transition: theme.transitions.duration.standard + "ms" - }, - menuListItemActive: { - "& $menuListItemText": { - color: theme.palette.primary.main - }, - "& path": { - color: theme.palette.primary.main, - fill: theme.palette.primary.main - } - }, - menuListItemOpen: { - "&:after": { - borderBottom: `10px solid transparent`, - borderLeft: `10px solid ${theme.palette.background.paper}`, - borderTop: `10px solid transparent`, - content: "''", - height: 0, - position: "absolute", - right: -30, - top: 15, - width: 0 - }, - "&:before": { - borderLeft: `solid 2px ${theme.palette.primary.main}`, - content: "''", - height: 33, - left: -20, - position: "absolute", - top: 8 - }, - position: "relative" - }, - menuListItemText: { - "&:hover": { - color: theme.palette.primary.main - }, - bottom: 0, - cursor: "pointer", - fontSize: "1rem", - fontWeight: 500, - left: 30, - opacity: 1, - paddingLeft: 16, - position: "absolute", - textTransform: "uppercase", - transition: "opacity 0.5s ease" - }, - menuListItemTextHide: { - bottom: 0, - left: 30, - opacity: 0, - position: "absolute" - }, - subMenu: { - padding: "0 15px" - }, - subMenuDrawer: { - background: "#000", - cursor: "pointer", - height: "100vh", - left: 0, - opacity: 0.2, - position: "absolute", - top: 0, - width: 0, - zIndex: -2 - }, - subMenuDrawerOpen: { - width: `100vw` - } - }), - { name: "MenuList" } -); - -interface MenuListProps { - className?: string; - menuItems: IMenuItem[]; - isMenuSmall: boolean; - location: string; - user: User; - renderConfigure: boolean; - onMenuItemClick: (url: string, event: React.MouseEvent) => void; -} - -export interface IActiveSubMenu { - isActive: boolean; - label: string | null; -} - -const MenuList: React.FC = props => { - const { - className, - menuItems, - isMenuSmall, - location, - user, - renderConfigure, - onMenuItemClick - } = props; - - const classes = useStyles(props); - - const { isDark } = useTheme(); - const [activeSubMenu, setActiveSubMenu] = React.useState({ - isActive: false, - label: null - }); - const intl = useIntl(); - - const configutationMenu = createConfigurationMenu(intl).map(menu => { - menu.menuItems.map(item => - user.userPermissions.map(perm => perm.code).includes(item.permission) - ); - }); - - const handleSubMenu = itemLabel => { - setActiveSubMenu({ - isActive: - itemLabel === activeSubMenu.label ? !activeSubMenu.isActive : true, - label: itemLabel - }); - }; - - const closeSubMenu = (menuItemUrl, event) => { - setActiveSubMenu({ - isActive: false, - label: null - }); - if (menuItemUrl && event) { - onMenuItemClick(menuItemUrl, event); - event.stopPropagation(); - event.preventDefault(); - } - }; - - return ( -
- {/* FIXME: this .split("?")[0] looks gross */} - {menuItems.map(menuItem => { - const isActive = (menuItem: IMenuItem) => - location.split("?")[0] === orderDraftListUrl().split("?")[0] && - menuItem.url.split("?")[0] === orderListUrl().split("?")[0] - ? false - : !!matchPath(location.split("?")[0], { - exact: menuItem.url.split("?")[0] === "/", - path: menuItem.url.split("?")[0] - }); - - if ( - menuItem.permission && - !user.userPermissions - .map(perm => perm.code) - .includes(menuItem.permission) - ) { - return null; - } - - if (!menuItem.url) { - const isAnyChildActive = menuItem.children.reduce( - (acc, child) => acc || isActive(child), - false - ); - - return ( -
-
handleSubMenu(menuItem.ariaLabel)} - > - - - {menuItem.label} - -
- -
closeSubMenu(null, event)} - className={classNames(classes.subMenuDrawer, { - [classes.subMenuDrawerOpen]: activeSubMenu.isActive - })} - /> -
- ); - } - - return ( - closeSubMenu(menuItem.url, event)} - key={menuItem.label} - > -
- - - {menuItem.label} - -
-
- ); - })} - {renderConfigure && configutationMenu.length > 0 && ( - closeSubMenu(configurationMenuUrl, event)} - > -
- - - - -
-
- )} -
- ); -}; - -MenuList.displayName = "MenuList"; -export default MenuList; diff --git a/src/components/AppLayout/MenuNested.tsx b/src/components/AppLayout/MenuNested.tsx deleted file mode 100644 index 57e81dd7c..000000000 --- a/src/components/AppLayout/MenuNested.tsx +++ /dev/null @@ -1,194 +0,0 @@ -import Hidden from "@material-ui/core/Hidden"; -import { makeStyles } from "@material-ui/core/styles"; -import Typography from "@material-ui/core/Typography"; -import classNames from "classnames"; -import React from "react"; -import SVG from "react-inlinesvg"; - -import menuArrowIcon from "@assets/images/menu-arrow-icon.svg"; -import useTheme from "@saleor/hooks/useTheme"; -import { createHref } from "@saleor/misc"; -import { drawerNestedMenuWidth, drawerWidthExpandedMobile } from "./consts"; -import { IActiveSubMenu } from "./MenuList"; -import { IMenuItem } from "./menuStructure"; - -const useStyles = makeStyles( - theme => ({ - menuListNested: { - background: theme.palette.background.paper, - height: "100vh", - position: "absolute", - right: 0, - top: 0, - transition: `right ${theme.transitions.duration.shorter}ms ease`, - width: drawerNestedMenuWidth, - zIndex: -1 - }, - menuListNestedClose: { - "& svg": { - fill: theme.palette.primary.main, - left: 11, - position: "relative", - top: 1 - }, - border: `solid 1px #EAEAEA`, - borderRadius: "100%", - cursor: "pointer", - height: 32, - position: "absolute", - right: 32, - top: 35, - transform: "rotate(180deg)", - width: 32 - }, - menuListNestedCloseDark: { - border: `solid 1px #252728` - }, - menuListNestedHide: { - opacity: 0 - }, - menuListNestedIcon: { - "& path": { - fill: "initial" - }, - "& svg": { height: 32, position: "relative", top: 7, width: 32 } - }, - menuListNestedIconDark: { - "& path": { - fill: theme.palette.common.white - } - }, - menuListNestedItem: { - "&:hover": { - "& p": { - color: theme.palette.primary.main - } - }, - display: "block", - marginBottom: theme.spacing(2), - padding: "0px 30px", - textDecoration: "none" - }, - menuListNestedOpen: { - [theme.breakpoints.down("sm")]: { - right: 0, - width: drawerWidthExpandedMobile, - zIndex: 2 - }, - right: -drawerNestedMenuWidth, - width: drawerNestedMenuWidth, - zIndex: -1 - }, - subHeader: { - borderBottom: "solid 1px #EAEAEA", - margin: "30px", - marginBottom: 39, - paddingBottom: 22 - }, - subHeaderDark: { - borderBottom: "solid 1px #252728" - }, - subHeaderTitle: { - [theme.breakpoints.up("md")]: { - paddingLeft: 0 - }, - display: "inline", - paddingLeft: 10 - } - }), - { name: "MenuNested" } -); - -export interface MenuNestedProps { - activeItem: IActiveSubMenu; - ariaLabel: string; - closeSubMenu: ({ isActive, label }: IActiveSubMenu) => void; - icon: string; - menuItem: IMenuItem; - title: string; - handleSubMenu: (itemLabel: string) => void; - onMenuItemClick: (url: string, event: React.MouseEvent) => void; -} - -const MenuNested: React.FC = props => { - const { - activeItem, - ariaLabel, - - closeSubMenu, - icon, - menuItem, - onMenuItemClick, - title - } = props; - const classes = useStyles(props); - - const menuItems = menuItem.children; - const { isDark } = useTheme(); - const closeMenu = (menuItemUrl, event) => { - onMenuItemClick(menuItemUrl, event); - closeSubMenu({ - isActive: false, - label: null - }); - event.stopPropagation(); - event.preventDefault(); - }; - return ( - <> -
- - - - -
{title}
- -
- closeSubMenu({ - isActive: false, - label: null - }) - } - > - -
-
-
- {menuItems.map(item => ( - closeMenu(item.url, event)} - key={item.label} - > - {item.label} - - ))} -
- - ); -}; - -MenuNested.displayName = "MenuNested"; -export default MenuNested; diff --git a/src/components/AppLayout/ResponsiveDrawer.tsx b/src/components/AppLayout/ResponsiveDrawer.tsx deleted file mode 100644 index 86f1dbb83..000000000 --- a/src/components/AppLayout/ResponsiveDrawer.tsx +++ /dev/null @@ -1,73 +0,0 @@ -import Drawer from "@material-ui/core/Drawer"; -import Hidden from "@material-ui/core/Hidden"; -import { makeStyles } from "@material-ui/core/styles"; -import React from "react"; -import { - drawerWidth, - drawerWidthExpanded, - drawerWidthExpandedMobile -} from "./consts"; - -const useStyles = makeStyles( - theme => ({ - drawerDesktop: { - backgroundColor: theme.palette.background.paper, - border: "none", - height: "100vh", - overflow: "visible", - padding: 0, - position: "fixed" as "fixed", - transition: "width 0.3s ease", - width: drawerWidthExpanded - }, - drawerDesktopSmall: { - overflow: "visible", - transition: "width 0.2s ease", - width: drawerWidth - }, - drawerMobile: { - width: drawerWidthExpandedMobile - } - }), - { name: "ResponsiveDrawer" } -); - -interface ResponsiveDrawerProps { - children?: React.ReactNode; - open: boolean; - small: boolean; - onClose?(); -} - -const ResponsiveDrawer: React.FC = props => { - const { children, onClose, open, small } = props; - - const classes = useStyles(props); - - return ( - <> - - - {children} - - - - - {children} - - - - ); -}; -export default ResponsiveDrawer; diff --git a/src/components/AppLayout/menuStructure.ts b/src/components/AppLayout/menuStructure.ts index 2c6aaaac8..b39d99161 100644 --- a/src/components/AppLayout/menuStructure.ts +++ b/src/components/AppLayout/menuStructure.ts @@ -1,18 +1,20 @@ -import { commonMessages, sectionNames } from "@saleor/intl"; -import { IntlShape } from "react-intl"; - +import appsIcon from "@assets/images/menu-apps-icon.svg"; import catalogIcon from "@assets/images/menu-catalog-icon.svg"; import customerIcon from "@assets/images/menu-customers-icon.svg"; import discountsIcon from "@assets/images/menu-discounts-icon.svg"; import homeIcon from "@assets/images/menu-home-icon.svg"; import ordersIcon from "@assets/images/menu-orders-icon.svg"; import translationIcon from "@assets/images/menu-translation-icon.svg"; +import { commonMessages, sectionNames } from "@saleor/intl"; +import { IntlShape } from "react-intl"; + +import { appsListPath } from "../../apps/urls"; import { categoryListUrl } from "../../categories/urls"; import { collectionListUrl } from "../../collections/urls"; import { customerListUrl } from "../../customers/urls"; +import { saleListUrl, voucherListUrl } from "../../discounts/urls"; import { orderDraftListUrl, orderListUrl } from "../../orders/urls"; import { productListUrl } from "../../products/urls"; -import { saleListUrl, voucherListUrl } from "../../discounts/urls"; import { languageListUrl } from "../../translations/urls"; import { PermissionEnum } from "../../types/globalTypes"; @@ -22,6 +24,7 @@ export interface IMenuItem { icon?: any; label: string; permission?: PermissionEnum; + testingContextId: string; url?: string; } @@ -31,6 +34,7 @@ function createMenuStructure(intl: IntlShape): IMenuItem[] { ariaLabel: "home", icon: homeIcon, label: intl.formatMessage(sectionNames.home), + testingContextId: "home", url: "/" }, { @@ -39,22 +43,26 @@ function createMenuStructure(intl: IntlShape): IMenuItem[] { { ariaLabel: "products", label: intl.formatMessage(sectionNames.products), + testingContextId: "products", url: productListUrl() }, { ariaLabel: "categories", label: intl.formatMessage(sectionNames.categories), + testingContextId: "categories", url: categoryListUrl() }, { ariaLabel: "collections", label: intl.formatMessage(sectionNames.collections), + testingContextId: "collections", url: collectionListUrl() } ], icon: catalogIcon, label: intl.formatMessage(commonMessages.catalog), - permission: PermissionEnum.MANAGE_PRODUCTS + permission: PermissionEnum.MANAGE_PRODUCTS, + testingContextId: "catalogue" }, { ariaLabel: "orders", @@ -63,24 +71,28 @@ function createMenuStructure(intl: IntlShape): IMenuItem[] { ariaLabel: "orders", label: intl.formatMessage(sectionNames.orders), permission: PermissionEnum.MANAGE_ORDERS, + testingContextId: "orders", url: orderListUrl() }, { ariaLabel: "order drafts", label: intl.formatMessage(commonMessages.drafts), permission: PermissionEnum.MANAGE_ORDERS, + testingContextId: "order drafts", url: orderDraftListUrl() } ], icon: ordersIcon, label: intl.formatMessage(sectionNames.orders), - permission: PermissionEnum.MANAGE_ORDERS + permission: PermissionEnum.MANAGE_ORDERS, + testingContextId: "orders" }, { ariaLabel: "customers", icon: customerIcon, label: intl.formatMessage(sectionNames.customers), permission: PermissionEnum.MANAGE_USERS, + testingContextId: "customers", url: customerListUrl() }, @@ -90,23 +102,35 @@ function createMenuStructure(intl: IntlShape): IMenuItem[] { { ariaLabel: "sales", label: intl.formatMessage(sectionNames.sales), + testingContextId: "sales", url: saleListUrl() }, { ariaLabel: "vouchers", label: intl.formatMessage(sectionNames.vouchers), + testingContextId: "vouchers", url: voucherListUrl() } ], icon: discountsIcon, label: intl.formatMessage(commonMessages.discounts), - permission: PermissionEnum.MANAGE_DISCOUNTS + permission: PermissionEnum.MANAGE_DISCOUNTS, + testingContextId: "discounts" + }, + { + ariaLabel: "apps", + icon: appsIcon, + label: intl.formatMessage(sectionNames.apps), + permission: PermissionEnum.MANAGE_APPS, + testingContextId: "apps", + url: appsListPath }, { ariaLabel: "translations", icon: translationIcon, label: intl.formatMessage(sectionNames.translations), permission: PermissionEnum.MANAGE_TRANSLATIONS, + testingContextId: "translations", url: languageListUrl } ]; diff --git a/src/components/AccountStatus/AccountStatus.tsx b/src/components/AppStatus/AppStatus.tsx similarity index 80% rename from src/components/AccountStatus/AccountStatus.tsx rename to src/components/AppStatus/AppStatus.tsx index a6302888f..9e989a9a2 100644 --- a/src/components/AccountStatus/AccountStatus.tsx +++ b/src/components/AppStatus/AppStatus.tsx @@ -1,13 +1,12 @@ import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; import Typography from "@material-ui/core/Typography"; +import CardTitle from "@saleor/components/CardTitle"; +import { ControlledCheckbox } from "@saleor/components/ControlledCheckbox"; import React from "react"; import { FormattedMessage, useIntl } from "react-intl"; -import CardTitle from "@saleor/components/CardTitle"; -import { ControlledCheckbox } from "@saleor/components/ControlledCheckbox"; - -interface StaffStatusProps { +interface AppStatusProps { data: { isActive: boolean; }; @@ -16,7 +15,7 @@ interface StaffStatusProps { onChange: (event: React.ChangeEvent) => void; } -const StaffStatus: React.FC = ({ +const AppStatus: React.FC = ({ data, disabled, label, @@ -28,13 +27,13 @@ const StaffStatus: React.FC = ({ - - + + = ({ ); }; -StaffStatus.displayName = "StaffStatus"; -export default StaffStatus; +AppStatus.displayName = "AppStatus"; +export default AppStatus; diff --git a/src/components/AppStatus/index.ts b/src/components/AppStatus/index.ts new file mode 100644 index 000000000..567fca42a --- /dev/null +++ b/src/components/AppStatus/index.ts @@ -0,0 +1,2 @@ +export { default } from "./AppStatus"; +export * from "./AppStatus"; diff --git a/src/components/AssignCategoryDialog/AssignCategoryDialog.tsx b/src/components/AssignCategoryDialog/AssignCategoryDialog.tsx index 8d66db15b..7b3bc1ed5 100644 --- a/src/components/AssignCategoryDialog/AssignCategoryDialog.tsx +++ b/src/components/AssignCategoryDialog/AssignCategoryDialog.tsx @@ -9,9 +9,6 @@ import TableBody from "@material-ui/core/TableBody"; import TableCell from "@material-ui/core/TableCell"; import TableRow from "@material-ui/core/TableRow"; import TextField from "@material-ui/core/TextField"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import ConfirmButton, { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; @@ -20,6 +17,9 @@ import ResponsiveTable from "@saleor/components/ResponsiveTable"; import useSearchQuery from "@saleor/hooks/useSearchQuery"; import { buttonMessages } from "@saleor/intl"; import { SearchCategories_search_edges_node } from "@saleor/searches/types/SearchCategories"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import Checkbox from "../Checkbox"; export interface FormData { diff --git a/src/components/AssignCollectionDialog/AssignCollectionDialog.tsx b/src/components/AssignCollectionDialog/AssignCollectionDialog.tsx index 48a24afcd..bf46d3de3 100644 --- a/src/components/AssignCollectionDialog/AssignCollectionDialog.tsx +++ b/src/components/AssignCollectionDialog/AssignCollectionDialog.tsx @@ -9,13 +9,13 @@ import TableBody from "@material-ui/core/TableBody"; import TableCell from "@material-ui/core/TableCell"; import TableRow from "@material-ui/core/TableRow"; import TextField from "@material-ui/core/TextField"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import ResponsiveTable from "@saleor/components/ResponsiveTable"; import useSearchQuery from "@saleor/hooks/useSearchQuery"; import { buttonMessages } from "@saleor/intl"; import { SearchCollections_search_edges_node } from "@saleor/searches/types/SearchCollections"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import Checkbox from "../Checkbox"; import ConfirmButton, { ConfirmButtonTransitionState diff --git a/src/components/AssignProductDialog/AssignProductDialog.tsx b/src/components/AssignProductDialog/AssignProductDialog.tsx index 3d1eadfba..7c40a65ae 100644 --- a/src/components/AssignProductDialog/AssignProductDialog.tsx +++ b/src/components/AssignProductDialog/AssignProductDialog.tsx @@ -9,9 +9,6 @@ import TableBody from "@material-ui/core/TableBody"; import TableCell from "@material-ui/core/TableCell"; import TableRow from "@material-ui/core/TableRow"; import TextField from "@material-ui/core/TextField"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import ConfirmButton, { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; @@ -22,6 +19,9 @@ import useSearchQuery from "@saleor/hooks/useSearchQuery"; import { buttonMessages } from "@saleor/intl"; import { maybe } from "@saleor/misc"; import { SearchProducts_search_edges_node } from "@saleor/searches/types/SearchProducts"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import Checkbox from "../Checkbox"; export interface FormData { diff --git a/src/components/AutocompleteSelectMenu/AutocompleteSelectMenu.tsx b/src/components/AutocompleteSelectMenu/AutocompleteSelectMenu.tsx index a3c2aa496..f8f0b165c 100644 --- a/src/components/AutocompleteSelectMenu/AutocompleteSelectMenu.tsx +++ b/src/components/AutocompleteSelectMenu/AutocompleteSelectMenu.tsx @@ -4,11 +4,11 @@ import Paper from "@material-ui/core/Paper"; import { makeStyles } from "@material-ui/core/styles"; import TextField from "@material-ui/core/TextField"; import ArrowBack from "@material-ui/icons/ArrowBack"; +import { buttonMessages } from "@saleor/intl"; import Downshift from "downshift"; import React from "react"; import { FormattedMessage } from "react-intl"; -import { buttonMessages } from "@saleor/intl"; import { getMenuItemByPath, IMenu, @@ -34,9 +34,9 @@ const validationError: Error = new Error( "Values supplied to AutocompleteSelectMenu should be unique" ); -const DebounceAutocomplete: React.ComponentType< - DebounceProps -> = Debounce; +const DebounceAutocomplete: React.ComponentType> = Debounce; const useStyles = makeStyles( theme => ({ diff --git a/src/components/AvailabilityCard/AvailabilityCard.stories.tsx b/src/components/AvailabilityCard/AvailabilityCard.stories.tsx new file mode 100644 index 000000000..779afafb3 --- /dev/null +++ b/src/components/AvailabilityCard/AvailabilityCard.stories.tsx @@ -0,0 +1,25 @@ +import Decorator from "@saleor/storybook/Decorator"; +import { storiesOf } from "@storybook/react"; +import React from "react"; + +import AvailabilityCard from "./AvailabilityCard"; +const props = { + data: { + availableForPurchase: "", + isAvailableForPurchase: false, + isPublished: true, + publicationDate: "", + visibleInListings: true + }, + errors: [], + messages: { + hiddenLabel: "Not published", + hiddenSecondLabel: "hidden label", + visibleLabel: "Published" + }, + onChange: () => undefined +}; + +storiesOf("Generics / AvailabilityCard", module) + .addDecorator(Decorator) + .add("default", () => ); diff --git a/src/components/AvailabilityCard/AvailabilityCard.tsx b/src/components/AvailabilityCard/AvailabilityCard.tsx new file mode 100644 index 000000000..382c4ecea --- /dev/null +++ b/src/components/AvailabilityCard/AvailabilityCard.tsx @@ -0,0 +1,53 @@ +import VisibilityCard, { + VisibilityCardProps +} from "@saleor/components/VisibilityCard"; +import useDateLocalize from "@saleor/hooks/useDateLocalize"; +import React from "react"; +import { useIntl } from "react-intl"; + +interface AvailabilityCardProps extends VisibilityCardProps { + data: { + availableForPurchase: string; + isAvailableForPurchase: boolean; + isPublished: boolean; + publicationDate: string; + visibleInListings: boolean; + }; +} + +export const AvailabilityCard: React.FC = props => { + const intl = useIntl(); + const localizeDate = useDateLocalize(); + + return ( + + ); +}; + +export default AvailabilityCard; diff --git a/src/components/AvailabilityCard/index.ts b/src/components/AvailabilityCard/index.ts new file mode 100644 index 000000000..f50012021 --- /dev/null +++ b/src/components/AvailabilityCard/index.ts @@ -0,0 +1,2 @@ +export * from "./AvailabilityCard"; +export { default } from "./AvailabilityCard"; diff --git a/src/components/CardMenu/CardMenu.tsx b/src/components/CardMenu/CardMenu.tsx index aa88a61ac..a6e8d67a8 100644 --- a/src/components/CardMenu/CardMenu.tsx +++ b/src/components/CardMenu/CardMenu.tsx @@ -1,6 +1,10 @@ +import ClickAwayListener from "@material-ui/core/ClickAwayListener"; +import Grow from "@material-ui/core/Grow"; import IconButton from "@material-ui/core/IconButton"; -import Menu from "@material-ui/core/Menu"; import MenuItem from "@material-ui/core/MenuItem"; +import MenuList from "@material-ui/core/MenuList"; +import Paper from "@material-ui/core/Paper"; +import Popper from "@material-ui/core/Popper"; import { makeStyles } from "@material-ui/core/styles"; import MoreVertIcon from "@material-ui/icons/MoreVert"; import React from "react"; @@ -9,6 +13,7 @@ const ITEM_HEIGHT = 48; export interface CardMenuItem { label: string; + testId?: string; onSelect: () => void; } @@ -26,34 +31,58 @@ const useStyles = makeStyles( height: 32, padding: 0, width: 32 + }, + paper: { + marginTop: theme.spacing(2), + maxHeight: ITEM_HEIGHT * 4.5 } }), { name: "CardMenu" } ); const CardMenu: React.FC = props => { - const { className, disabled, menuItems } = props; + const { className, disabled, menuItems, ...rest } = props; const classes = useStyles(props); - const [anchorEl, setAnchor] = React.useState(null); + const anchorRef = React.useRef(null); + const [open, setOpen] = React.useState(false); - const handleClick = (event: React.MouseEvent) => { - setAnchor(event.currentTarget); + const handleToggle = () => setOpen(prevOpen => !prevOpen); + + const handleClose = (event: React.MouseEvent) => { + if ( + anchorRef.current && + anchorRef.current.contains(event.target as HTMLElement) + ) { + return; + } + + setOpen(false); }; - const handleClose = () => { - setAnchor(null); + const handleListKeyDown = (event: React.KeyboardEvent) => { + if (event.key === "Tab") { + event.preventDefault(); + setOpen(false); + } }; - const handleMenuClick = (menuItemIndex: number) => { - menuItems[menuItemIndex].onSelect(); - handleClose(); - }; + const prevOpen = React.useRef(open); + React.useEffect(() => { + if (prevOpen.current === true && open === false) { + anchorRef.current!.focus(); + } - const open = !!anchorEl; + prevOpen.current = open; + }, [open]); + + const handleMenuClick = (index: number) => { + menuItems[index].onSelect(); + setOpen(false); + }; return ( -
+
= props => { className={classes.iconButton} color="primary" disabled={disabled} - onClick={handleClick} + ref={anchorRef} + onClick={handleToggle} > - - {menuItems.map((menuItem, menuItemIndex) => ( - handleMenuClick(menuItemIndex)} - key={menuItem.label} + {({ TransitionProps, placement }) => ( + - {menuItem.label} - - ))} - + + + + {menuItems.map((menuItem, menuItemIndex) => ( + handleMenuClick(menuItemIndex)} + key={menuItem.label} + data-test={menuItem.testId} + > + {menuItem.label} + + ))} + + + + + )} +
); }; diff --git a/src/components/Checkbox/Checkbox.tsx b/src/components/Checkbox/Checkbox.tsx index 529aef513..772800f6b 100644 --- a/src/components/Checkbox/Checkbox.tsx +++ b/src/components/Checkbox/Checkbox.tsx @@ -1,136 +1,25 @@ -import ButtonBase from "@material-ui/core/ButtonBase"; -import { CheckboxProps as MuiCheckboxProps } from "@material-ui/core/Checkbox"; -import { makeStyles } from "@material-ui/core/styles"; -import { fade } from "@material-ui/core/styles/colorManipulator"; -import classNames from "classnames"; +import MuiCheckbox, { + CheckboxProps as MuiCheckboxProps +} from "@material-ui/core/Checkbox"; import React from "react"; export type CheckboxProps = Omit< MuiCheckboxProps, - | "checkedIcon" - | "color" - | "icon" - | "indeterminateIcon" - | "classes" - | "onChange" - | "onClick" + "checkedIcon" | "color" | "icon" | "indeterminateIcon" | "classes" | "onClick" > & { disableClickPropagation?: boolean; - onChange?: (event: React.ChangeEvent) => void; }; -const useStyles = makeStyles( - theme => ({ - box: { - "&$checked": { - "&:before": { - background: theme.palette.primary.main, - color: theme.palette.background.paper, - content: '"\\2713"', - fontWeight: "bold", - textAlign: "center" - }, - borderColor: theme.palette.primary.main - }, - "&$disabled": { - borderColor: theme.palette.grey[200] - }, - "&$indeterminate": { - "&:before": { - background: theme.palette.primary.main, - height: 2, - top: 5 - }, - borderColor: theme.palette.primary.main - }, - "&:before": { - background: "rgba(0, 0, 0, 0)", - content: '""', - height: 14, - left: -1, - position: "absolute", - top: -1, - transition: theme.transitions.duration.short + "ms", - width: 14 - }, - - WebkitAppearance: "none", - border: `1px solid ${theme.palette.action.active}`, - boxSizing: "border-box", - cursor: "pointer", - height: 14, - outline: "0", - position: "relative", - userSelect: "none", - width: 14 - }, - checked: {}, - disabled: {}, - indeterminate: {}, - root: { - "&:hover": { - background: fade(theme.palette.primary.main, 0.1) - }, - alignSelf: "start", - borderRadius: "100%", - cursor: "pointer", - display: "flex", - height: 30, - justifyContent: "center", - margin: "5px 9px", - width: 30 - } - }), - { name: "Checkbox" } -); const Checkbox: React.FC = props => { - const { - checked, - className, - - disabled, - disableClickPropagation, - indeterminate, - onChange, - value, - name, - ...rest - } = props; - const classes = useStyles(props); - - const inputRef = React.useRef(null); - const handleClick = React.useCallback( - disableClickPropagation - ? event => { - event.stopPropagation(); - inputRef.current.click(); - } - : () => inputRef.current.click(), - [] - ); + const { disableClickPropagation, ...rest } = props; return ( - - - + onClick={ + disableClickPropagation ? event => event.stopPropagation() : undefined + } + /> ); }; Checkbox.displayName = "Checkbox"; diff --git a/src/components/Chip/Chip.tsx b/src/components/Chip/Chip.tsx index 53a56bcdf..5198817da 100644 --- a/src/components/Chip/Chip.tsx +++ b/src/components/Chip/Chip.tsx @@ -23,8 +23,8 @@ const useStyles = makeStyles( color: theme.palette.common.white }, root: { - background: fade(theme.palette.secondary.main, 0.8), - borderRadius: 8, + background: fade(theme.palette.primary.main, 0.8), + borderRadius: 18, display: "inline-block", marginRight: theme.spacing(2), padding: "6px 12px" diff --git a/src/components/ColumnPicker/ColumnPicker.tsx b/src/components/ColumnPicker/ColumnPicker.tsx index 3dc2cf759..d49a7144b 100644 --- a/src/components/ColumnPicker/ColumnPicker.tsx +++ b/src/components/ColumnPicker/ColumnPicker.tsx @@ -3,10 +3,10 @@ import Grow from "@material-ui/core/Grow"; import Popper from "@material-ui/core/Popper"; import { fade } from "@material-ui/core/styles/colorManipulator"; import makeStyles from "@material-ui/core/styles/makeStyles"; -import React from "react"; - import useStateFromProps from "@saleor/hooks/useStateFromProps"; import { toggle } from "@saleor/utils/lists"; +import React from "react"; + import ColumnPickerButton from "./ColumnPickerButton"; import ColumnPickerContent, { ColumnPickerContentProps diff --git a/src/components/ColumnPicker/ColumnPickerContent.tsx b/src/components/ColumnPicker/ColumnPickerContent.tsx index 971a57d3d..d4f5b4929 100644 --- a/src/components/ColumnPicker/ColumnPickerContent.tsx +++ b/src/components/ColumnPicker/ColumnPickerContent.tsx @@ -4,15 +4,15 @@ import CardContent from "@material-ui/core/CardContent"; import CircularProgress from "@material-ui/core/CircularProgress"; import makeStyles from "@material-ui/core/styles/makeStyles"; import Typography from "@material-ui/core/Typography"; +import useElementScroll from "@saleor/hooks/useElementScroll"; +import { buttonMessages } from "@saleor/intl"; +import { FetchMoreProps } from "@saleor/types"; +import { isSelected } from "@saleor/utils/lists"; import classNames from "classnames"; import React from "react"; import InfiniteScroll from "react-infinite-scroller"; import { FormattedMessage } from "react-intl"; -import useElementScroll from "@saleor/hooks/useElementScroll"; -import { buttonMessages } from "@saleor/intl"; -import { FetchMoreProps } from "@saleor/types"; -import { isSelected } from "@saleor/utils/lists"; import ControlledCheckbox from "../ControlledCheckbox"; import Hr from "../Hr"; diff --git a/src/components/CompanyAddressInput/CompanyAddressForm.tsx b/src/components/CompanyAddressInput/CompanyAddressForm.tsx index 8526826d3..e43752424 100644 --- a/src/components/CompanyAddressInput/CompanyAddressForm.tsx +++ b/src/components/CompanyAddressInput/CompanyAddressForm.tsx @@ -1,22 +1,21 @@ import { makeStyles } from "@material-ui/core/styles"; import TextField from "@material-ui/core/TextField"; -import React from "react"; -import { useIntl, IntlShape } from "react-intl"; - import FormSpacer from "@saleor/components/FormSpacer"; import Grid from "@saleor/components/Grid"; import SingleAutocompleteSelectField, { SingleAutocompleteChoiceType } from "@saleor/components/SingleAutocompleteSelectField"; import { AddressTypeInput } from "@saleor/customers/types"; +import { AccountErrorFragment } from "@saleor/fragments/types/AccountErrorFragment"; +import { ShopErrorFragment } from "@saleor/fragments/types/ShopErrorFragment"; +import { WarehouseErrorFragment } from "@saleor/fragments/types/WarehouseErrorFragment"; import { ChangeEvent } from "@saleor/hooks/useForm"; -import getShopErrorMessage from "@saleor/utils/errors/shop"; import { getFormErrors } from "@saleor/utils/errors"; -import { ShopErrorFragment } from "@saleor/siteSettings/types/ShopErrorFragment"; -import { AccountErrorFragment } from "@saleor/customers/types/AccountErrorFragment"; import getAccountErrorMessage from "@saleor/utils/errors/account"; +import getShopErrorMessage from "@saleor/utils/errors/shop"; import getWarehouseErrorMessage from "@saleor/utils/errors/warehouse"; -import { WarehouseErrorFragment } from "@saleor/warehouses/types/WarehouseErrorFragment"; +import React from "react"; +import { IntlShape, useIntl } from "react-intl"; export interface CompanyAddressFormProps { countries: SingleAutocompleteChoiceType[]; @@ -161,7 +160,7 @@ const CompanyAddressForm: React.FC = props => { choices={countries} InputProps={{ inputProps: { - autocomplete: "plsdontautocomplete" // Somehow it shuts it down + autoComplete: "none" } }} /> diff --git a/src/components/CompanyAddressInput/CompanyAddressInput.tsx b/src/components/CompanyAddressInput/CompanyAddressInput.tsx index 87ecaf788..4df8709ca 100644 --- a/src/components/CompanyAddressInput/CompanyAddressInput.tsx +++ b/src/components/CompanyAddressInput/CompanyAddressInput.tsx @@ -1,8 +1,8 @@ import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; import { makeStyles } from "@material-ui/core/styles"; -import React from "react"; import classNames from "classnames"; +import React from "react"; import CardTitle from "../CardTitle"; import CompanyAddressForm, { diff --git a/src/components/ControlledCheckbox.tsx b/src/components/ControlledCheckbox.tsx index ebace41f9..fd4d57b45 100644 --- a/src/components/ControlledCheckbox.tsx +++ b/src/components/ControlledCheckbox.tsx @@ -1,8 +1,7 @@ +import Checkbox from "@material-ui/core/Checkbox"; import FormControlLabel from "@material-ui/core/FormControlLabel"; import React from "react"; -import Checkbox from "./Checkbox"; - interface ControlledCheckboxProps { className?: string; name: string; @@ -27,7 +26,6 @@ export const ControlledCheckbox: React.FC = ({ checked={checked} disabled={disabled} name={name} - disableClickPropagation onChange={() => onChange({ target: { name, value: !checked } })} /> } diff --git a/src/components/ControlledSwitch.tsx b/src/components/ControlledSwitch.tsx index e7dea9c2a..d38bcda2b 100644 --- a/src/components/ControlledSwitch.tsx +++ b/src/components/ControlledSwitch.tsx @@ -4,10 +4,7 @@ import Switch from "@material-ui/core/Switch"; import React from "react"; const useStyles = makeStyles( - theme => ({ - label: { - marginLeft: theme.spacing(3.5) - }, + () => ({ labelText: { fontSize: 14 } @@ -51,7 +48,7 @@ export const ControlledSwitch: React.FC = props => { /> } label={ -
+
{uncheckedLabel ? ( checked ? ( label diff --git a/src/components/CountryList/CountryList.tsx b/src/components/CountryList/CountryList.tsx index 91f14550e..b217dbe7f 100644 --- a/src/components/CountryList/CountryList.tsx +++ b/src/components/CountryList/CountryList.tsx @@ -8,15 +8,15 @@ import TableCell from "@material-ui/core/TableCell"; import TableRow from "@material-ui/core/TableRow"; import ArrowDropDownIcon from "@material-ui/icons/ArrowDropDown"; import DeleteIcon from "@material-ui/icons/Delete"; +import CardTitle from "@saleor/components/CardTitle"; +import ResponsiveTable from "@saleor/components/ResponsiveTable"; +import Skeleton from "@saleor/components/Skeleton"; +import { CountryFragment } from "@saleor/fragments/types/CountryFragment"; import classNames from "classnames"; import React from "react"; import { FormattedMessage } from "react-intl"; -import CardTitle from "@saleor/components/CardTitle"; -import ResponsiveTable from "@saleor/components/ResponsiveTable"; -import Skeleton from "@saleor/components/Skeleton"; -import { maybe, renderCollection, getStringOrPlaceholder } from "../../misc"; -import { CountryFragment } from "../../taxes/types/CountryFragment"; +import { getStringOrPlaceholder, maybe, renderCollection } from "../../misc"; export interface CountryListProps { countries: CountryFragment[]; diff --git a/src/components/CreatorSteps/CreatorSteps.tsx b/src/components/CreatorSteps/CreatorSteps.tsx new file mode 100644 index 000000000..d7be7c4a3 --- /dev/null +++ b/src/components/CreatorSteps/CreatorSteps.tsx @@ -0,0 +1,84 @@ +import { makeStyles } from "@material-ui/core/styles"; +import Typography from "@material-ui/core/Typography"; +import classNames from "classnames"; +import React from "react"; + +export interface Step { + label: string; + value: T; +} + +const useStyles = makeStyles( + theme => ({ + label: { + fontSize: 14, + textAlign: "center" + }, + root: { + borderBottom: `1px solid ${theme.palette.divider}`, + display: "flex", + justifyContent: "space-between", + marginBottom: theme.spacing(3) + }, + tab: { + flex: 1, + paddingBottom: theme.spacing(), + userSelect: "none" + }, + tabActive: { + fontWeight: 600 + }, + tabVisited: { + borderBottom: `3px solid ${theme.palette.primary.main}`, + cursor: "pointer" + } + }), + { + name: "CreatorSteps" + } +); + +export interface CreatorStepsProps { + currentStep: T; + steps: Array>; + onStepClick: (step: T) => void; +} + +function makeCreatorSteps() { + const CreatorSteps: React.FC> = ({ + currentStep, + steps, + onStepClick + }) => { + const classes = useStyles({}); + + return ( +
+ {steps.map((step, stepIndex) => { + const visitedStep = + steps.findIndex(step => step.value === currentStep) >= stepIndex; + + return ( +
onStepClick(step.value) : undefined} + key={step.value} + > + + {step.label} + +
+ ); + })} +
+ ); + }; + CreatorSteps.displayName = "CreatorSteps"; + + return CreatorSteps; +} + +export default makeCreatorSteps; diff --git a/src/components/CreatorSteps/index.ts b/src/components/CreatorSteps/index.ts new file mode 100644 index 000000000..5ab26400a --- /dev/null +++ b/src/components/CreatorSteps/index.ts @@ -0,0 +1,2 @@ +export * from "./CreatorSteps"; +export { default } from "./CreatorSteps"; diff --git a/src/components/Date/Date.tsx b/src/components/Date/Date.tsx index 8f745be5e..07e002f6b 100644 --- a/src/components/Date/Date.tsx +++ b/src/components/Date/Date.tsx @@ -1,8 +1,8 @@ import Tooltip from "@material-ui/core/Tooltip"; +import useDateLocalize from "@saleor/hooks/useDateLocalize"; import moment from "moment-timezone"; import React from "react"; -import useDateLocalize from "@saleor/hooks/useDateLocalize"; import { LocaleConsumer } from "../Locale"; import { Consumer } from "./DateContext"; diff --git a/src/components/DebounceForm.tsx b/src/components/DebounceForm.tsx index 0e17ca8d9..5e446afa9 100644 --- a/src/components/DebounceForm.tsx +++ b/src/components/DebounceForm.tsx @@ -1,4 +1,5 @@ import React from "react"; + import Debounce from "./Debounce"; export interface DebounceFormProps { diff --git a/src/components/EditableTableCell/EditableTableCell.tsx b/src/components/EditableTableCell/EditableTableCell.tsx index 20da0e949..516df9499 100644 --- a/src/components/EditableTableCell/EditableTableCell.tsx +++ b/src/components/EditableTableCell/EditableTableCell.tsx @@ -4,11 +4,10 @@ import { makeStyles } from "@material-ui/core/styles"; import TableCell from "@material-ui/core/TableCell"; import TextField, { TextFieldProps } from "@material-ui/core/TextField"; import Typography from "@material-ui/core/Typography"; +import useForm from "@saleor/hooks/useForm"; import classNames from "classnames"; import React from "react"; -import useForm from "@saleor/hooks/useForm"; - const useStyles = makeStyles( theme => ({ card: { diff --git a/src/components/ErrorPage/ErrorPage.tsx b/src/components/ErrorPage/ErrorPage.tsx index 5b2042567..856230375 100644 --- a/src/components/ErrorPage/ErrorPage.tsx +++ b/src/components/ErrorPage/ErrorPage.tsx @@ -1,3 +1,4 @@ +import notFoundImage from "@assets/images/what.svg"; import Button from "@material-ui/core/Button"; import { makeStyles } from "@material-ui/core/styles"; import Typography from "@material-ui/core/Typography"; @@ -5,8 +6,6 @@ import React from "react"; import SVG from "react-inlinesvg"; import { FormattedMessage } from "react-intl"; -import notFoundImage from "@assets/images/what.svg"; - export interface ErrorPageProps { onBack: () => void; } diff --git a/src/components/Filter/Filter.tsx b/src/components/Filter/Filter.tsx index bcaeefc26..098dc7837 100644 --- a/src/components/Filter/Filter.tsx +++ b/src/components/Filter/Filter.tsx @@ -9,9 +9,9 @@ import classNames from "classnames"; import React from "react"; import { FormattedMessage } from "react-intl"; +import { FilterContent } from "."; import { IFilter, IFilterElement } from "./types"; import useFilter from "./useFilter"; -import { FilterContent } from "."; export interface FilterProps { currencySymbol: string; diff --git a/src/components/Filter/FilterAutocompleteField.tsx b/src/components/Filter/FilterAutocompleteField.tsx index 7a909c899..914ca1264 100644 --- a/src/components/Filter/FilterAutocompleteField.tsx +++ b/src/components/Filter/FilterAutocompleteField.tsx @@ -1,15 +1,15 @@ -import React from "react"; import FormControlLabel from "@material-ui/core/FormControlLabel"; -import Typography from "@material-ui/core/Typography"; -import TextField from "@material-ui/core/TextField"; import makeStyles from "@material-ui/core/styles/makeStyles"; +import TextField from "@material-ui/core/TextField"; +import Typography from "@material-ui/core/Typography"; +import { toggle } from "@saleor/utils/lists"; +import React from "react"; import { FormattedMessage } from "react-intl"; -import { toggle } from "@saleor/utils/lists"; -import { MultiAutocompleteChoiceType } from "../MultiAutocompleteSelectField"; -import Link from "../Link"; import Checkbox from "../Checkbox"; import Hr from "../Hr"; +import Link from "../Link"; +import { MultiAutocompleteChoiceType } from "../MultiAutocompleteSelectField"; import { FilterBaseFieldProps } from "./types"; interface FilterAutocompleteFieldProps extends FilterBaseFieldProps { @@ -50,7 +50,8 @@ const FilterAutocompleteField: React.FC = ({ displayValues, filterField, setDisplayValues, - onFilterPropertyChange + onFilterPropertyChange, + ...rest }) => { const classes = useStyles({}); @@ -90,8 +91,9 @@ const FilterAutocompleteField: React.FC = ({ }; return ( -
+
= ({ } @@ -118,7 +122,11 @@ const FilterAutocompleteField: React.FC = ({ ))} {displayHr &&
} {displayNoResults && ( - + )} @@ -126,7 +134,11 @@ const FilterAutocompleteField: React.FC = ({
+ } label={option.label} name={filterField.name} @@ -136,6 +148,7 @@ const FilterAutocompleteField: React.FC = ({ ))} {filterField.hasMore && ( { currencySymbol: string; @@ -101,6 +101,8 @@ function getIsFilterMultipleChoices( ]; } +const filterFieldTestingContext = "filter-field"; + const FilterContent: React.FC = ({ currencySymbol, filters, @@ -136,10 +138,19 @@ const FilterContent: React.FC = ({
- -
@@ -151,7 +162,13 @@ const FilterContent: React.FC = ({
} + control={ + + } label={filterField.label} onChange={() => onFilterPropertyChange({ @@ -170,6 +187,8 @@ const FilterContent: React.FC = ({
{filterField.type === FieldType.text && ( = ({ ) && ( <> = ({ {filterField.multiple ? ( <> = ({ /> = ({ ) : ( = ({ )} {filterField.type === FieldType.options && ( @@ -355,6 +385,10 @@ const FilterContent: React.FC = ({ @@ -378,6 +412,8 @@ const FilterContent: React.FC = ({ {filterField.type === FieldType.autocomplete && filterField.multiple && ( = ({ filterField, - onFilterPropertyChange + onFilterPropertyChange, + ...rest }) => { const classes = useStyles({}); const handleSelect = (value: string) => @@ -41,7 +42,7 @@ const FilterOptionField: React.FC = ({ }); return ( -
+
{filterField.options.map(option => (
= ({ + ) : ( diff --git a/src/components/Filter/reducer.ts b/src/components/Filter/reducer.ts index e8d837c7c..7d54f8110 100644 --- a/src/components/Filter/reducer.ts +++ b/src/components/Filter/reducer.ts @@ -1,4 +1,5 @@ import { update } from "@saleor/utils/lists"; + import { IFilter, IFilterElementMutableData } from "./types"; export type FilterReducerActionType = diff --git a/src/components/Filter/types.ts b/src/components/Filter/types.ts index a7b2f28a4..f872a87f1 100644 --- a/src/components/Filter/types.ts +++ b/src/components/Filter/types.ts @@ -1,4 +1,5 @@ import { FetchMoreProps, SearchPageProps } from "@saleor/types"; + import { MultiAutocompleteChoiceType } from "../MultiAutocompleteSelectField"; import { FilterReducerAction } from "./reducer"; diff --git a/src/components/Filter/useFilter.ts b/src/components/Filter/useFilter.ts index e51bebe56..0816cab13 100644 --- a/src/components/Filter/useFilter.ts +++ b/src/components/Filter/useFilter.ts @@ -1,4 +1,4 @@ -import { useReducer, useEffect, Dispatch } from "react"; +import { Dispatch, useEffect, useReducer } from "react"; import reduceFilter, { FilterReducerAction } from "./reducer"; import { IFilter, IFilterElement } from "./types"; @@ -17,7 +17,11 @@ function useFilter(initialFilter: IFilter): UseFilter { const reset = () => dispatchFilterAction({ payload: { - new: initialFilter + new: initialFilter.map(each => ({ + ...each, + active: false, + value: [] + })) }, type: "reset" }); diff --git a/src/components/FilterBar/FilterBar.tsx b/src/components/FilterBar/FilterBar.tsx index db4f6445e..fd912aabf 100644 --- a/src/components/FilterBar/FilterBar.tsx +++ b/src/components/FilterBar/FilterBar.tsx @@ -1,14 +1,14 @@ +import Button from "@material-ui/core/Button"; +import makeStyles from "@material-ui/core/styles/makeStyles"; import React from "react"; import { FormattedMessage, useIntl } from "react-intl"; -import makeStyles from "@material-ui/core/styles/makeStyles"; -import Button from "@material-ui/core/Button"; import { FilterProps } from "../../types"; +import Filter from "../Filter"; import { IFilter } from "../Filter/types"; -import FilterTabs, { FilterTab } from "../TableFilter"; import { SearchBarProps } from "../SearchBar"; import SearchInput from "../SearchBar/SearchInput"; -import Filter from "../Filter"; +import FilterTabs, { FilterTab } from "../TableFilter"; export interface FilterBarProps extends FilterProps, diff --git a/src/components/Form/Form.tsx b/src/components/Form/Form.tsx index 43668380f..2721f678a 100644 --- a/src/components/Form/Form.tsx +++ b/src/components/Form/Form.tsx @@ -1,6 +1,5 @@ -import React from "react"; - import useForm, { UseFormResult } from "@saleor/hooks/useForm"; +import React from "react"; export interface FormProps { children: (props: UseFormResult) => React.ReactNode; diff --git a/src/components/IconButtonTableCell/IconButtonTableCell.tsx b/src/components/IconButtonTableCell/IconButtonTableCell.tsx index b5d427cb1..e135ee3e3 100644 --- a/src/components/IconButtonTableCell/IconButtonTableCell.tsx +++ b/src/components/IconButtonTableCell/IconButtonTableCell.tsx @@ -1,8 +1,8 @@ import IconButton from "@material-ui/core/IconButton"; import { makeStyles } from "@material-ui/core/styles"; import TableCell from "@material-ui/core/TableCell"; -import React from "react"; import classNames from "classnames"; +import React from "react"; import { stopPropagation } from "../../misc"; import { ICONBUTTON_SIZE } from "../../theme"; diff --git a/src/components/ImageTile/ImageTile.tsx b/src/components/ImageTile/ImageTile.tsx index dcd20a2f4..f6bb80d2b 100644 --- a/src/components/ImageTile/ImageTile.tsx +++ b/src/components/ImageTile/ImageTile.tsx @@ -70,7 +70,7 @@ const ImageTile: React.FC = props => { const classes = useStyles(props); return ( -
+
({ @@ -145,7 +145,7 @@ const LinkChoice: React.FC = ({ selected={choice.value === value} key={choice.value} onClick={() => handleChange(choice.value)} - data-tc="select-option" + data-test="select-option" > {choice.label} diff --git a/src/components/ListField/ListField.tsx b/src/components/ListField/ListField.tsx index efd6a3d1f..c0e89814c 100644 --- a/src/components/ListField/ListField.tsx +++ b/src/components/ListField/ListField.tsx @@ -2,8 +2,8 @@ import Button from "@material-ui/core/Button"; import { createStyles, Theme, - withStyles, - WithStyles + WithStyles, + withStyles } from "@material-ui/core/styles"; import TextField, { StandardTextFieldProps } from "@material-ui/core/TextField"; import React from "react"; diff --git a/src/components/Locale/Locale.tsx b/src/components/Locale/Locale.tsx index 03bb1b0c5..5535532e1 100644 --- a/src/components/Locale/Locale.tsx +++ b/src/components/Locale/Locale.tsx @@ -1,49 +1,7 @@ +import useLocalStorage from "@saleor/hooks/useLocalStorage"; import React from "react"; import { IntlProvider } from "react-intl"; -import locale_AR from "@locale/ar.json"; -import locale_AZ from "@locale/az.json"; -import locale_BG from "@locale/bg.json"; -import locale_BN from "@locale/bn.json"; -import locale_CA from "@locale/ca.json"; -import locale_CS from "@locale/cs.json"; -import locale_DA from "@locale/da.json"; -import locale_DE from "@locale/de.json"; -import locale_EL from "@locale/el.json"; -import locale_ES from "@locale/es.json"; -import locale_ES_CO from "@locale/es_CO.json"; -import locale_ET from "@locale/et.json"; -import locale_FA from "@locale/fa.json"; -import locale_FR from "@locale/fr.json"; -import locale_HI from "@locale/hi.json"; -import locale_HU from "@locale/hu.json"; -import locale_HY from "@locale/hy.json"; -import locale_ID from "@locale/id.json"; -import locale_IS from "@locale/is.json"; -import locale_IT from "@locale/it.json"; -import locale_JA from "@locale/ja.json"; -import locale_KO from "@locale/ko.json"; -import locale_MN from "@locale/mn.json"; -import locale_NB from "@locale/nb.json"; -import locale_NL from "@locale/nl.json"; -import locale_PL from "@locale/pl.json"; -import locale_PT from "@locale/pt.json"; -import locale_PT_BR from "@locale/pt_BR.json"; -import locale_RO from "@locale/ro.json"; -import locale_RU from "@locale/ru.json"; -import locale_SK from "@locale/sk.json"; -import locale_SL from "@locale/sl.json"; -import locale_SQ from "@locale/sq.json"; -import locale_SR from "@locale/sr.json"; -import locale_SV from "@locale/sv.json"; -import locale_TH from "@locale/th.json"; -import locale_TR from "@locale/tr.json"; -import locale_UK from "@locale/uk.json"; -import locale_VI from "@locale/vi.json"; -import locale_ZH_HANS from "@locale/zh-Hans.json"; -import locale_ZH_HANT from "@locale/zh-Hant.json"; -import useLocalStorage from "@saleor/hooks/useLocalStorage"; - export enum Locale { AR = "ar", AZ = "az", @@ -56,7 +14,7 @@ export enum Locale { EL = "el", EN = "en", ES = "es", - ES_CO = "es-co", + ES_CO = "es-CO", ET = "et", FA = "fa", FR = "fr", @@ -73,7 +31,7 @@ export enum Locale { NL = "nl", PL = "pl", PT = "pt", - PT_BR = "pt-br", + PT_BR = "pt-BR", RO = "ro", RU = "ru", SK = "sk", @@ -85,8 +43,8 @@ export enum Locale { TR = "tr", UK = "uk", VI = "vi", - ZH_HANS = "zh-hans", - ZH_HANT = "zh-hant" + ZH_HANS = "zh-Hans", + ZH_HANT = "zh-Hant" } interface StructuredMessage { @@ -94,51 +52,6 @@ interface StructuredMessage { string: string; } type LocaleMessages = Record; -const localeData: Record = { - [Locale.AR]: locale_AR, - [Locale.AZ]: locale_AZ, - [Locale.BG]: locale_BG, - [Locale.BN]: locale_BN, - [Locale.CA]: locale_CA, - [Locale.CS]: locale_CS, - [Locale.DA]: locale_DA, - [Locale.DE]: locale_DE, - [Locale.EL]: locale_EL, - // Default language - [Locale.EN]: undefined, - [Locale.ES]: locale_ES, - [Locale.ES_CO]: locale_ES_CO, - [Locale.ET]: locale_ET, - [Locale.FA]: locale_FA, - [Locale.FR]: locale_FR, - [Locale.HI]: locale_HI, - [Locale.HU]: locale_HU, - [Locale.HY]: locale_HY, - [Locale.ID]: locale_ID, - [Locale.IS]: locale_IS, - [Locale.IT]: locale_IT, - [Locale.JA]: locale_JA, - [Locale.KO]: locale_KO, - [Locale.MN]: locale_MN, - [Locale.NB]: locale_NB, - [Locale.NL]: locale_NL, - [Locale.PL]: locale_PL, - [Locale.PT]: locale_PT, - [Locale.PT_BR]: locale_PT_BR, - [Locale.RO]: locale_RO, - [Locale.RU]: locale_RU, - [Locale.SK]: locale_SK, - [Locale.SL]: locale_SL, - [Locale.SQ]: locale_SQ, - [Locale.SR]: locale_SR, - [Locale.SV]: locale_SV, - [Locale.TH]: locale_TH, - [Locale.TR]: locale_TR, - [Locale.UK]: locale_UK, - [Locale.VI]: locale_VI, - [Locale.ZH_HANS]: locale_ZH_HANS, - [Locale.ZH_HANT]: locale_ZH_HANT -}; export const localeNames: Record = { [Locale.AR]: "Ø§Ų„ØšØąØ¨ŲŠŲ‘ØŠ", @@ -230,12 +143,27 @@ const LocaleProvider: React.FC = ({ children }) => { "locale", getMatchingLocale(navigator.languages) || defaultLocale ); + const [messages, setMessages] = React.useState(undefined); + + React.useEffect(() => { + async function changeLocale() { + if (locale !== defaultLocale) { + // It seems like Webpack is unable to use aliases for lazy imports + const mod = await import(`../../../locale/${locale}.json`); + setMessages(mod.default); + } else { + setMessages(undefined); + } + } + + changeLocale(); + }, [locale]); return ( { if (!err.includes("[React Intl] Missing message: ")) { console.error(err); diff --git a/src/components/Metadata/Metadata.stories.tsx b/src/components/Metadata/Metadata.stories.tsx new file mode 100644 index 000000000..f60c6ac6c --- /dev/null +++ b/src/components/Metadata/Metadata.stories.tsx @@ -0,0 +1,19 @@ +import useForm from "@saleor/hooks/useForm"; +import Decorator from "@saleor/storybook/Decorator"; +import { storiesOf } from "@storybook/react"; +import React from "react"; + +import { props } from "./fixtures"; +import Metadata from "./Metadata"; + +const InteractiveStory: React.FC = () => { + const { change, data } = useForm(props.data, () => undefined); + + return ; +}; + +storiesOf("Generics / Metadata", module) + .addDecorator(Decorator) + .add("default", () => ) + .add("loading", () => ) + .add("interactive", () => ); diff --git a/src/components/Metadata/Metadata.test.tsx b/src/components/Metadata/Metadata.test.tsx new file mode 100644 index 000000000..8cb49c4eb --- /dev/null +++ b/src/components/Metadata/Metadata.test.tsx @@ -0,0 +1,162 @@ +import useForm from "@saleor/hooks/useForm"; +import Wrapper from "@test/wrapper"; +import { configure } from "enzyme"; +import { mount } from "enzyme"; +import Adapter from "enzyme-adapter-react-16"; +import React from "react"; + +import { props } from "./fixtures"; +import Metadata from "./Metadata"; + +configure({ adapter: new Adapter() }); + +const expandButton = 'data-test="expand"'; + +const Component: React.FC = () => { + const { change, data } = useForm(props.data, jest.fn()); + + return ( + + + + ); +}; + +describe("Metadata editor", () => { + it("can expand field", () => { + const wrapper = mount(); + + const expandDataEl = "data-test-expanded"; + + expect( + wrapper + .find(`[${expandDataEl}]`) + .first() + .prop(expandDataEl) + ).toEqual(false); + wrapper + .find(`[${expandButton}]`) + .first() + .simulate("click"); + expect( + wrapper + .find(`[${expandDataEl}]`) + .first() + .prop(expandDataEl) + ).toEqual(true); + }); + + it("can edit field name", () => { + const wrapper = mount(); + + const inputNameSelector = '[name="name:1"] input'; + + // Expand to reveal fields + wrapper + .find(`[${expandButton}]`) + .first() + .simulate("click"); + + expect( + wrapper + .find(inputNameSelector) + .first() + .prop("value") + ).toEqual(props.data.metadata[1].key); + + wrapper + .find(inputNameSelector) + .first() + .simulate("change", { target: { name: "name:1", value: "x" } }); + + expect( + wrapper + .find(inputNameSelector) + .first() + .prop("value") + ).toEqual("x"); + }); + + it("can edit field value", () => { + const wrapper = mount(); + + const inputNameSelector = '[name="value:1"] textarea'; + + // Expand to reveal fields + wrapper + .find(`[${expandButton}]`) + .first() + .simulate("click"); + + expect( + wrapper + .find(inputNameSelector) + .first() + .prop("value") + ).toEqual(props.data.metadata[1].value); + + wrapper + .find(inputNameSelector) + .first() + .simulate("change", { target: { name: "value:1", value: "x" } }); + + expect( + wrapper + .find(inputNameSelector) + .first() + .prop("value") + ).toEqual("x"); + }); + + it("can delete field", () => { + const wrapper = mount(); + + const fieldSelector = 'tr[data-test="field"]'; + const deleteButtonSelector = '[data-test="deleteField"]'; + + // Expand to reveal fields + wrapper + .find(`[${expandButton}]`) + .first() + .simulate("click"); + + expect(wrapper.find(fieldSelector).length).toEqual( + props.data.metadata.length + ); + + wrapper + .find(deleteButtonSelector) + .first() + .simulate("click"); + + expect(wrapper.find(fieldSelector).length).toEqual( + props.data.metadata.length - 1 + ); + }); + + it("can add field", () => { + const wrapper = mount(); + + const fieldSelector = 'tr[data-test="field"]'; + const addButtonSelector = '[data-test="addField"]'; + + // Expand to reveal fields + wrapper + .find(`[${expandButton}]`) + .first() + .simulate("click"); + + expect(wrapper.find(fieldSelector).length).toEqual( + props.data.metadata.length + ); + + wrapper + .find(addButtonSelector) + .first() + .simulate("click"); + + expect(wrapper.find(fieldSelector).length).toEqual( + props.data.metadata.length + 1 + ); + }); +}); diff --git a/src/components/Metadata/Metadata.tsx b/src/components/Metadata/Metadata.tsx new file mode 100644 index 000000000..67a496bf5 --- /dev/null +++ b/src/components/Metadata/Metadata.tsx @@ -0,0 +1,73 @@ +import { ChangeEvent } from "@saleor/hooks/useForm"; +import { MetadataInput } from "@saleor/types/globalTypes"; +import { removeAtIndex, updateAtIndex } from "@saleor/utils/lists"; +import React from "react"; + +import CardSpacer from "../CardSpacer"; +import MetadataCard, { MetadataCardProps } from "./MetadataCard"; +import { EventDataAction, EventDataField } from "./types"; +import { getDataKey, parseEventData } from "./utils"; + +export interface MetadataProps + extends Omit { + data: Record<"metadata" | "privateMetadata", MetadataInput[]>; +} + +const Metadata: React.FC = ({ data, onChange }) => { + const change = (event: ChangeEvent, isPrivate: boolean) => { + const { action, field, fieldIndex, value } = parseEventData(event); + const key = getDataKey(isPrivate); + const dataToUpdate = data[key]; + + onChange({ + target: { + name: key, + value: + action === EventDataAction.update + ? updateAtIndex( + { + ...dataToUpdate[fieldIndex], + key: + field === EventDataField.name + ? value + : dataToUpdate[fieldIndex].key, + value: + field === EventDataField.value + ? value + : dataToUpdate[fieldIndex].value + }, + dataToUpdate, + fieldIndex + ) + : action === EventDataAction.add + ? [ + ...dataToUpdate, + { + key: "", + value: "" + } + ] + : removeAtIndex(dataToUpdate, fieldIndex) + } + }); + }; + + return ( + <> + change(event, false)} + /> + + change(event, true)} + /> + + ); +}; + +Metadata.displayName = "Metadata"; +export default Metadata; diff --git a/src/components/Metadata/MetadataCard.tsx b/src/components/Metadata/MetadataCard.tsx new file mode 100644 index 000000000..63b520c77 --- /dev/null +++ b/src/components/Metadata/MetadataCard.tsx @@ -0,0 +1,232 @@ +import emptyMetadata from "@assets/images/empty-metadata.svg"; +import Button from "@material-ui/core/Button"; +import Card from "@material-ui/core/Card"; +import CardActions from "@material-ui/core/CardActions"; +import CardContent from "@material-ui/core/CardContent"; +import IconButton from "@material-ui/core/IconButton"; +import Table from "@material-ui/core/Table"; +import TableBody from "@material-ui/core/TableBody"; +import TableCell from "@material-ui/core/TableCell"; +import TableHead from "@material-ui/core/TableHead"; +import TableRow from "@material-ui/core/TableRow"; +import TextField from "@material-ui/core/TextField"; +import Typography from "@material-ui/core/Typography"; +import ToggleIcon from "@material-ui/icons/ArrowDropDown"; +import DeleteIcon from "@material-ui/icons/Delete"; +import { FormChange } from "@saleor/hooks/useForm"; +import { MetadataInput } from "@saleor/types/globalTypes"; +import React, { useEffect } from "react"; +import SVG from "react-inlinesvg"; +import { useIntl } from "react-intl"; +import { FormattedMessage } from "react-intl"; + +import CardTitle from "../CardTitle"; +import Skeleton from "../Skeleton"; +import useStyles from "./styles"; +import { EventDataAction, EventDataField } from "./types"; + +export interface MetadataCardProps { + data: MetadataInput[]; + isPrivate: boolean; + onChange: FormChange; +} + +export const nameSeparator = ":"; +export const nameInputPrefix = EventDataField.name; +export const valueInputPrefix = EventDataField.value; + +const MetadataCard: React.FC = ({ + data, + isPrivate, + onChange +}) => { + const intl = useIntl(); + const loaded = React.useRef(false); + const [expanded, setExpanded] = React.useState(true); + const classes = useStyles({}); + + useEffect(() => { + if (data !== undefined) { + loaded.current = true; + if (data.length > 0) { + setExpanded(false); + } + } + }, [data === undefined]); + + return ( + + + {data === undefined ? ( + + + + ) : ( + <> + + {data.length > 0 && ( +
+ + + + setExpanded(!expanded)} + > + + +
+ )} +
+ {expanded && ( + <> + {data.length === 0 ? ( +
+ + + {isPrivate ? ( + + ) : ( + + )} + + + + +
+ ) : ( + + + + + + + + + + + + + + + + {data.map((field, fieldIndex) => ( + + + + + + + + + + onChange({ + target: { + name: EventDataAction.delete, + value: fieldIndex + } + }) + } + > + + + + + ))} + +
+ )} + + + + + )} + + )} +
+ ); +}; + +MetadataCard.displayName = "MetadataCard"; +export default MetadataCard; diff --git a/src/components/Metadata/fixtures.ts b/src/components/Metadata/fixtures.ts new file mode 100644 index 000000000..970116c99 --- /dev/null +++ b/src/components/Metadata/fixtures.ts @@ -0,0 +1,22 @@ +import { MetadataProps } from "./Metadata"; + +export const props: MetadataProps = { + data: { + metadata: [ + { + key: "key", + value: "value" + }, + { + key: "key2", + value: '{\n "jsonValue": "some-value"\n}' + }, + { + key: "key3", + value: "some-value" + } + ], + privateMetadata: [] + }, + onChange: () => undefined +}; diff --git a/src/components/Metadata/index.ts b/src/components/Metadata/index.ts new file mode 100644 index 000000000..4ded27123 --- /dev/null +++ b/src/components/Metadata/index.ts @@ -0,0 +1,5 @@ +export * from "./Metadata"; +export * from "./MetadataCard"; +export * from "./types"; +export { default } from "./Metadata"; +export { default as MetadataCard } from "./MetadataCard"; diff --git a/src/components/Metadata/styles.ts b/src/components/Metadata/styles.ts new file mode 100644 index 000000000..3d7c506fd --- /dev/null +++ b/src/components/Metadata/styles.ts @@ -0,0 +1,66 @@ +import makeStyles from "@material-ui/core/styles/makeStyles"; + +const useStyles = makeStyles( + theme => { + const colAction: React.CSSProperties = { + textAlign: "right", + width: 130 + }; + const colName: React.CSSProperties = { + width: 220 + }; + + return { + colAction: { + "&:last-child": { + ...colAction, + paddingRight: theme.spacing() + } + }, + colActionHeader: { + ...colAction + }, + colName: { + ...colName, + verticalAlign: "top" + }, + colNameHeader: { + ...colName + }, + colValue: {}, + content: { + paddingBottom: 0, + paddingTop: theme.spacing() + }, + emptyContainer: { + borderBottom: `1px solid ${theme.palette.divider}`, + paddingBottom: theme.spacing(4), + paddingTop: theme.spacing(3), + textAlign: "center" + }, + emptyImage: { + display: "block", + marginBottom: theme.spacing(2) + }, + input: { + padding: theme.spacing(0.5, 2) + }, + nameInput: { + padding: `13px 16px` + }, + table: { + tableLayout: "fixed" + }, + togglable: { + alignItems: "center", + display: "flex", + justifyContent: "space-between" + } + }; + }, + { + name: "Metadata" + } +); + +export default useStyles; diff --git a/src/components/Metadata/types.ts b/src/components/Metadata/types.ts new file mode 100644 index 000000000..9572572b9 --- /dev/null +++ b/src/components/Metadata/types.ts @@ -0,0 +1,21 @@ +import { MetadataInput } from "@saleor/types/globalTypes"; + +export enum EventDataAction { + add = "add", + delete = "delete", + update = "update" +} +export enum EventDataField { + name = "name", + value = "value" +} +export interface EventData { + action: EventDataAction; + field: EventDataField | null; + fieldIndex: number | null; + value: string; +} +export interface MetadataFormData { + metadata: MetadataInput[]; + privateMetadata: MetadataInput[]; +} diff --git a/src/components/Metadata/utils.ts b/src/components/Metadata/utils.ts new file mode 100644 index 000000000..28517b900 --- /dev/null +++ b/src/components/Metadata/utils.ts @@ -0,0 +1,42 @@ +import { ChangeEvent } from "@saleor/hooks/useForm"; + +import { nameSeparator } from "./MetadataCard"; +import { EventData, EventDataAction, EventDataField } from "./types"; + +export function parseEventData(event: ChangeEvent): EventData { + let action: EventDataAction; + let field: EventDataField = null; + let fieldIndex: number = null; + let value: string = null; + + if (event.target.name.includes(EventDataField.name)) { + action = EventDataAction.update; + field = EventDataField.name; + fieldIndex = parseInt(event.target.name.split(nameSeparator)[1], 0); + value = event.target.value; + } + if (event.target.name.includes(EventDataField.value)) { + action = EventDataAction.update; + field = EventDataField.value; + fieldIndex = parseInt(event.target.name.split(nameSeparator)[1], 0); + value = event.target.value; + } + if (event.target.name === EventDataAction.add) { + action = EventDataAction.add; + } + if (event.target.name === EventDataAction.delete) { + action = EventDataAction.delete; + fieldIndex = event.target.value; + } + + return { + action, + field, + fieldIndex, + value + }; +} + +export function getDataKey(isPrivate: boolean) { + return isPrivate ? "privateMetadata" : "metadata"; +} diff --git a/src/components/MultiAutocompleteSelectField/MultiAutocompleteSelectField.stories.tsx b/src/components/MultiAutocompleteSelectField/MultiAutocompleteSelectField.stories.tsx index 7b6763e7e..98d665139 100644 --- a/src/components/MultiAutocompleteSelectField/MultiAutocompleteSelectField.stories.tsx +++ b/src/components/MultiAutocompleteSelectField/MultiAutocompleteSelectField.stories.tsx @@ -1,11 +1,11 @@ -import { storiesOf } from "@storybook/react"; -import React from "react"; - import { countries } from "@saleor/fixtures"; import useMultiAutocomplete from "@saleor/hooks/useMultiAutocomplete"; import CardDecorator from "@saleor/storybook/CardDecorator"; import Decorator from "@saleor/storybook/Decorator"; import { ChoiceProvider } from "@saleor/storybook/mock"; +import { storiesOf } from "@storybook/react"; +import React from "react"; + import MultiAutocompleteSelectField, { MultiAutocompleteSelectFieldProps } from "./MultiAutocompleteSelectField"; diff --git a/src/components/MultiAutocompleteSelectField/MultiAutocompleteSelectField.tsx b/src/components/MultiAutocompleteSelectField/MultiAutocompleteSelectField.tsx index d7aab9a97..cd88b6ec8 100644 --- a/src/components/MultiAutocompleteSelectField/MultiAutocompleteSelectField.tsx +++ b/src/components/MultiAutocompleteSelectField/MultiAutocompleteSelectField.tsx @@ -1,19 +1,19 @@ import IconButton from "@material-ui/core/IconButton"; import { makeStyles } from "@material-ui/core/styles"; +import { fade } from "@material-ui/core/styles/colorManipulator"; import TextField from "@material-ui/core/TextField"; import Typography from "@material-ui/core/Typography"; import CloseIcon from "@material-ui/icons/Close"; +import Debounce, { DebounceProps } from "@saleor/components/Debounce"; +import ArrowDropdownIcon from "@saleor/icons/ArrowDropdown"; +import { FetchMoreProps } from "@saleor/types"; import Downshift, { ControllerStateAndHelpers } from "downshift"; import { filter } from "fuzzaldrin"; import React from "react"; -import { fade } from "@material-ui/core/styles/colorManipulator"; -import Debounce, { DebounceProps } from "@saleor/components/Debounce"; -import ArrowDropdownIcon from "@saleor/icons/ArrowDropdown"; -import { FetchMoreProps } from "@saleor/types"; import MultiAutocompleteSelectFieldContent, { - MultiAutocompleteChoiceType, - MultiAutocompleteActionType + MultiAutocompleteActionType, + MultiAutocompleteChoiceType } from "./MultiAutocompleteSelectFieldContent"; const useStyles = makeStyles( diff --git a/src/components/MultiAutocompleteSelectField/MultiAutocompleteSelectFieldContent.tsx b/src/components/MultiAutocompleteSelectField/MultiAutocompleteSelectFieldContent.tsx index 9bc21a39a..a68f71221 100644 --- a/src/components/MultiAutocompleteSelectField/MultiAutocompleteSelectFieldContent.tsx +++ b/src/components/MultiAutocompleteSelectField/MultiAutocompleteSelectFieldContent.tsx @@ -1,21 +1,20 @@ -import classNames from "classnames"; -import { GetItemPropsOptions } from "downshift"; -import React from "react"; -import SVG from "react-inlinesvg"; -import { FormattedMessage } from "react-intl"; - import chevronDown from "@assets/images/ChevronDown.svg"; import CircularProgress from "@material-ui/core/CircularProgress"; import MenuItem from "@material-ui/core/MenuItem"; -import Typography from "@material-ui/core/Typography"; import Paper from "@material-ui/core/Paper"; import { makeStyles } from "@material-ui/core/styles"; +import Typography from "@material-ui/core/Typography"; import AddIcon from "@material-ui/icons/Add"; import Checkbox from "@saleor/components/Checkbox"; import useElementScroll, { isScrolledToBottom } from "@saleor/hooks/useElementScroll"; import { FetchMoreProps } from "@saleor/types"; +import classNames from "classnames"; +import { GetItemPropsOptions } from "downshift"; +import React from "react"; +import SVG from "react-inlinesvg"; +import { FormattedMessage } from "react-intl"; import Hr from "../Hr"; @@ -211,7 +210,7 @@ const MultiAutocompleteSelectFieldContent: React.FC @@ -226,7 +225,7 @@ const MultiAutocompleteSelectFieldContent: React.FC diff --git a/src/components/Navigator/Navigator.tsx b/src/components/Navigator/Navigator.tsx index 3a2752f60..203c39b5e 100644 --- a/src/components/Navigator/Navigator.tsx +++ b/src/components/Navigator/Navigator.tsx @@ -3,15 +3,15 @@ import Modal from "@material-ui/core/Modal"; import Paper from "@material-ui/core/Paper"; import makeStyles from "@material-ui/core/styles/makeStyles"; import useTheme from "@material-ui/core/styles/useTheme"; +import { APP_VERSION } from "@saleor/config"; +import useLocalStorage from "@saleor/hooks/useLocalStorage"; +import useNotifier from "@saleor/hooks/useNotifier"; import Downshift from "downshift"; import hotkeys from "hotkeys-js"; import React from "react"; import { useIntl } from "react-intl"; import cmp from "semver-compare"; -import { APP_VERSION } from "@saleor/config"; -import useLocalStorage from "@saleor/hooks/useLocalStorage"; -import useNotifier from "@saleor/hooks/useNotifier"; import { getActions, getCatalog, @@ -49,6 +49,9 @@ const useStyles = makeStyles( overflow: "hidden" }, root: { + [theme.breakpoints.down("sm")]: { + height: "auto" + }, height: 500, maxWidth: 600, outline: 0, @@ -60,8 +63,12 @@ const useStyles = makeStyles( } ); -const Navigator: React.FC = () => { - const [visible, setVisible] = React.useState(false); +export interface NavigatorProps { + visible: boolean; + setVisibility: (state: boolean) => void; +} + +const Navigator: React.FC = ({ visible, setVisibility }) => { const input = React.useRef(null); const [query, mode, change, actions] = useQuickSearch(visible, input); const intl = useIntl(); @@ -76,7 +83,7 @@ const Navigator: React.FC = () => { React.useEffect(() => { hotkeys(navigatorHotkey, event => { event.preventDefault(); - setVisible(!visible); + setVisibility(!visible); }); if (cmp(APP_VERSION, "2.1.0") !== 1 && !notifiedAboutNavigator) { @@ -110,7 +117,7 @@ const Navigator: React.FC = () => { setVisible(false)} + onClose={() => setVisibility(false)} >
@@ -122,7 +129,7 @@ const Navigator: React.FC = () => { onSelect={(item: QuickSearchAction) => { const shouldRemainVisible = item.onClick(); if (!shouldRemainVisible) { - setVisible(false); + setVisibility(false); } }} onInputValueChange={value => diff --git a/src/components/Navigator/NavigatorInput.tsx b/src/components/Navigator/NavigatorInput.tsx index b82235162..9dd9d57e3 100644 --- a/src/components/Navigator/NavigatorInput.tsx +++ b/src/components/Navigator/NavigatorInput.tsx @@ -1,6 +1,7 @@ import makeStyles from "@material-ui/core/styles/makeStyles"; import React from "react"; import { useIntl } from "react-intl"; + import { QuickSearchMode } from "./types"; const useStyles = makeStyles( diff --git a/src/components/Navigator/modes/catalog.ts b/src/components/Navigator/modes/catalog.ts index 08be62dee..dcb1e3142 100644 --- a/src/components/Navigator/modes/catalog.ts +++ b/src/components/Navigator/modes/catalog.ts @@ -1,11 +1,11 @@ -import { score } from "fuzzaldrin"; -import { IntlShape } from "react-intl"; - import { categoryUrl } from "@saleor/categories/urls"; import { collectionUrl } from "@saleor/collections/urls"; import { UseNavigatorResult } from "@saleor/hooks/useNavigator"; import { maybe } from "@saleor/misc"; import { productUrl } from "@saleor/products/urls"; +import { score } from "fuzzaldrin"; +import { IntlShape } from "react-intl"; + import { SearchCatalog } from "../queries/types/SearchCatalog"; import { QuickSearchAction, QuickSearchActionInput } from "../types"; import messages from "./messages"; diff --git a/src/components/Navigator/modes/commands/actions.ts b/src/components/Navigator/modes/commands/actions.ts index 6a85d568a..a10c60c5d 100644 --- a/src/components/Navigator/modes/commands/actions.ts +++ b/src/components/Navigator/modes/commands/actions.ts @@ -1,15 +1,15 @@ -import { score } from "fuzzaldrin"; -import { IntlShape } from "react-intl"; - import { categoryAddUrl } from "@saleor/categories/urls"; -import { permissionGroupAddUrl } from "@saleor/permissionGroups/urls"; import { collectionAddUrl } from "@saleor/collections/urls"; import { customerAddUrl } from "@saleor/customers/urls"; import { voucherAddUrl } from "@saleor/discounts/urls"; import { UseNavigatorResult } from "@saleor/hooks/useNavigator"; import { OrderDraftCreate } from "@saleor/orders/types/OrderDraftCreate"; +import { permissionGroupAddUrl } from "@saleor/permissionGroups/urls"; import { productAddUrl } from "@saleor/products/urls"; +import { score } from "fuzzaldrin"; import { MutationFunction } from "react-apollo"; +import { IntlShape } from "react-intl"; + import { QuickSearchActionInput, QuickSearchMode } from "../../types"; import messages from "../messages"; import { sortScores } from "../utils"; diff --git a/src/components/Navigator/modes/customers.ts b/src/components/Navigator/modes/customers.ts index 32c1fe187..86cf7006c 100644 --- a/src/components/Navigator/modes/customers.ts +++ b/src/components/Navigator/modes/customers.ts @@ -1,8 +1,8 @@ -import { IntlShape } from "react-intl"; - import { customerUrl } from "@saleor/customers/urls"; import { UseNavigatorResult } from "@saleor/hooks/useNavigator"; import { SearchCustomers_search_edges_node } from "@saleor/searches/types/SearchCustomers"; +import { IntlShape } from "react-intl"; + import { QuickSearchAction } from "../types"; import messages from "./messages"; diff --git a/src/components/Navigator/modes/default/default.ts b/src/components/Navigator/modes/default/default.ts index d25691fff..c8222ecb7 100644 --- a/src/components/Navigator/modes/default/default.ts +++ b/src/components/Navigator/modes/default/default.ts @@ -1,8 +1,8 @@ +import { UseNavigatorResult } from "@saleor/hooks/useNavigator"; +import { OrderDraftCreate } from "@saleor/orders/types/OrderDraftCreate"; import { MutationFunction } from "react-apollo"; import { IntlShape } from "react-intl"; -import { UseNavigatorResult } from "@saleor/hooks/useNavigator"; -import { OrderDraftCreate } from "@saleor/orders/types/OrderDraftCreate"; import { QuickSearchAction, QuickSearchMode } from "../../types"; import { searchInCommands } from "../commands"; import { sortScores } from "../utils"; diff --git a/src/components/Navigator/modes/default/views.ts b/src/components/Navigator/modes/default/views.ts index c489ce6fb..3e323d846 100644 --- a/src/components/Navigator/modes/default/views.ts +++ b/src/components/Navigator/modes/default/views.ts @@ -1,6 +1,4 @@ -import { score } from "fuzzaldrin"; -import { IntlShape } from "react-intl"; - +import { appsListUrl } from "@saleor/apps/urls"; import { attributeListUrl } from "@saleor/attributes/urls"; import { categoryListUrl } from "@saleor/categories/urls"; import { collectionListUrl } from "@saleor/collections/urls"; @@ -11,17 +9,19 @@ import { sectionNames } from "@saleor/intl"; import { menuListUrl } from "@saleor/navigation/urls"; import { orderDraftListUrl, orderListUrl } from "@saleor/orders/urls"; import { pageListUrl } from "@saleor/pages/urls"; +import { permissionGroupListUrl } from "@saleor/permissionGroups/urls"; import { pluginListUrl } from "@saleor/plugins/urls"; import { productListUrl } from "@saleor/products/urls"; import { productTypeListUrl } from "@saleor/productTypes/urls"; -import { serviceListUrl } from "@saleor/services/urls"; import { shippingZonesListUrl } from "@saleor/shipping/urls"; import { siteSettingsUrl } from "@saleor/siteSettings/urls"; import { staffListUrl } from "@saleor/staff/urls"; import { countryListUrl } from "@saleor/taxes/urls"; import { languageListUrl } from "@saleor/translations/urls"; -import { webhookListUrl } from "@saleor/webhooks/urls"; import { warehouseListUrl } from "@saleor/warehouses/urls"; +import { score } from "fuzzaldrin"; +import { IntlShape } from "react-intl"; + import { QuickSearchActionInput } from "../../types"; interface View { @@ -34,6 +34,10 @@ function searchInViews( navigate: UseNavigatorResult ): QuickSearchActionInput[] { const views: View[] = [ + { + label: intl.formatMessage(sectionNames.apps), + url: appsListUrl() + }, { label: intl.formatMessage(sectionNames.attributes), url: attributeListUrl() @@ -70,6 +74,10 @@ function searchInViews( label: intl.formatMessage(sectionNames.pages), url: pageListUrl() }, + { + label: intl.formatMessage(sectionNames.permissionGroups), + url: permissionGroupListUrl() + }, { label: intl.formatMessage(sectionNames.plugins), url: pluginListUrl() @@ -86,10 +94,6 @@ function searchInViews( label: intl.formatMessage(sectionNames.sales), url: saleListUrl() }, - { - label: intl.formatMessage(sectionNames.serviceAccounts), - url: serviceListUrl() - }, { label: intl.formatMessage(sectionNames.shipping), url: shippingZonesListUrl() @@ -114,10 +118,6 @@ function searchInViews( label: intl.formatMessage(sectionNames.vouchers), url: voucherListUrl() }, - { - label: intl.formatMessage(sectionNames.webhooks), - url: webhookListUrl() - }, { label: intl.formatMessage(sectionNames.warehouses), url: warehouseListUrl() diff --git a/src/components/Navigator/modes/index.ts b/src/components/Navigator/modes/index.ts index 4dd2d487f..e0f85ce51 100644 --- a/src/components/Navigator/modes/index.ts +++ b/src/components/Navigator/modes/index.ts @@ -1,8 +1,8 @@ -import { IntlShape } from "react-intl"; - import { UseNavigatorResult } from "@saleor/hooks/useNavigator"; import { OrderDraftCreate } from "@saleor/orders/types/OrderDraftCreate"; import { MutationFunction } from "react-apollo"; +import { IntlShape } from "react-intl"; + import { QuickSearchAction, QuickSearchMode } from "../types"; import getCatalogModeActions from "./catalog"; import getCommandModeActions from "./commands"; diff --git a/src/components/Navigator/modes/orders.ts b/src/components/Navigator/modes/orders.ts index d5d44b244..f9dfda64d 100644 --- a/src/components/Navigator/modes/orders.ts +++ b/src/components/Navigator/modes/orders.ts @@ -1,8 +1,8 @@ -import { IntlShape } from "react-intl"; - import { UseNavigatorResult } from "@saleor/hooks/useNavigator"; import { maybe, transformOrderStatus } from "@saleor/misc"; import { orderUrl } from "@saleor/orders/urls"; +import { IntlShape } from "react-intl"; + import { CheckIfOrderExists_order } from "../queries/types/CheckIfOrderExists"; import { QuickSearchAction } from "../types"; import messages from "./messages"; diff --git a/src/components/Navigator/modes/types.ts b/src/components/Navigator/modes/types.ts index 13bab413f..400e05aa1 100644 --- a/src/components/Navigator/modes/types.ts +++ b/src/components/Navigator/modes/types.ts @@ -1,4 +1,5 @@ import { SearchCustomers_search_edges_node } from "@saleor/searches/types/SearchCustomers"; + import { CheckIfOrderExists_order } from "../queries/types/CheckIfOrderExists"; import { SearchCatalog } from "../queries/types/SearchCatalog"; diff --git a/src/components/Navigator/queries/useCatalogSearch.ts b/src/components/Navigator/queries/useCatalogSearch.ts index acf80c47d..5b6c3a9fd 100644 --- a/src/components/Navigator/queries/useCatalogSearch.ts +++ b/src/components/Navigator/queries/useCatalogSearch.ts @@ -1,8 +1,8 @@ +import makeQuery, { UseQueryResult } from "@saleor/hooks/makeQuery"; +import useDebounce from "@saleor/hooks/useDebounce"; import gql from "graphql-tag"; import { useState } from "react"; -import makeQuery, { UseQueryResult } from "@saleor/hooks/makeQuery"; -import useDebounce from "@saleor/hooks/useDebounce"; import { SearchCatalog, SearchCatalogVariables } from "./types/SearchCatalog"; const searchCatalog = gql` diff --git a/src/components/Navigator/queries/useCheckIfOrderExists.ts b/src/components/Navigator/queries/useCheckIfOrderExists.ts index d08b65a1a..5ad53ffa4 100644 --- a/src/components/Navigator/queries/useCheckIfOrderExists.ts +++ b/src/components/Navigator/queries/useCheckIfOrderExists.ts @@ -1,8 +1,8 @@ +import makeQuery, { UseQueryResult } from "@saleor/hooks/makeQuery"; +import useDebounce from "@saleor/hooks/useDebounce"; import gql from "graphql-tag"; import { useState } from "react"; -import makeQuery, { UseQueryResult } from "@saleor/hooks/makeQuery"; -import useDebounce from "@saleor/hooks/useDebounce"; import { CheckIfOrderExists, CheckIfOrderExistsVariables diff --git a/src/components/Navigator/useQuickSearch.ts b/src/components/Navigator/useQuickSearch.ts index edf3ddde8..ca6e27efe 100644 --- a/src/components/Navigator/useQuickSearch.ts +++ b/src/components/Navigator/useQuickSearch.ts @@ -1,6 +1,3 @@ -import { RefObject, useEffect, useState } from "react"; -import { useIntl } from "react-intl"; - import { DEFAULT_INITIAL_SEARCH_DATA } from "@saleor/config"; import { ChangeEvent, FormChange } from "@saleor/hooks/useForm"; import useModalDialogOpen from "@saleor/hooks/useModalDialogOpen"; @@ -9,6 +6,9 @@ import { maybe } from "@saleor/misc"; import { useOrderDraftCreateMutation } from "@saleor/orders/mutations"; import { orderUrl } from "@saleor/orders/urls"; import useCustomerSearch from "@saleor/searches/useCustomerSearch"; +import { RefObject, useEffect, useState } from "react"; +import { useIntl } from "react-intl"; + import getModeActions from "./modes"; import { getGqlOrderId, isQueryValidOrderNumber } from "./modes/orders"; import { getMode } from "./modes/utils"; diff --git a/src/components/NavigatorButton/NavigatorButton.stories.tsx b/src/components/NavigatorButton/NavigatorButton.stories.tsx new file mode 100644 index 000000000..95e7f0881 --- /dev/null +++ b/src/components/NavigatorButton/NavigatorButton.stories.tsx @@ -0,0 +1,12 @@ +import CardDecorator from "@saleor/storybook/CardDecorator"; +import Decorator from "@saleor/storybook/Decorator"; +import { storiesOf } from "@storybook/react"; +import React from "react"; + +import NavigatorButton from "./NavigatorButton"; + +storiesOf("Generics / NavigatorButton", module) + .addDecorator(Decorator) + .addDecorator(CardDecorator) + .add("mac", () => ) + .add("other", () => ); diff --git a/src/components/NavigatorButton/NavigatorButton.tsx b/src/components/NavigatorButton/NavigatorButton.tsx new file mode 100644 index 000000000..5e3c07341 --- /dev/null +++ b/src/components/NavigatorButton/NavigatorButton.tsx @@ -0,0 +1,158 @@ +import navigatorIcon from "@assets/images/navigator.svg"; +import Grow from "@material-ui/core/Grow"; +import IconButton, { IconButtonProps } from "@material-ui/core/IconButton"; +import Paper from "@material-ui/core/Paper"; +import Popper from "@material-ui/core/Popper"; +import makeStyles from "@material-ui/core/styles/makeStyles"; +import classNames from "classnames"; +import React from "react"; +import ReactSVG from "react-inlinesvg"; +import { FormattedMessage } from "react-intl"; + +const useStyles = makeStyles( + theme => { + const triangle = (color: string, width: number) => ({ + borderBottom: `${width}px solid ${color}`, + borderLeft: `${width}px solid transparent`, + borderRight: `${width}px solid transparent`, + height: 0, + width: 0 + }); + + return { + keyTile: { + "&:first-child": { + marginLeft: theme.spacing() + }, + alignItems: "center", + background: theme.palette.background.default, + borderRadius: 8, + display: "inline-flex", + height: 32, + justifyContent: "center", + marginLeft: theme.spacing(0.5), + padding: theme.spacing(), + width: 32 + }, + keyTileLabel: { + verticalAlign: "middle" + }, + paper: { + "&:after": { + ...triangle(theme.palette.background.paper, 7), + content: "''", + left: theme.spacing(2) + 2, + position: "absolute", + top: -theme.spacing() + 1 + }, + "&:before": { + ...triangle(theme.palette.divider, 8), + content: "''", + left: theme.spacing(2) + 1, + position: "absolute", + top: -theme.spacing() + }, + border: `1px solid ${theme.palette.divider}`, + borderRadius: 6, + marginTop: theme.spacing(2), + padding: theme.spacing(2), + position: "relative" + }, + + root: { + "& path": { + color: theme.palette.primary.main + }, + "&:not(:hover)": { + backgroundColor: theme.palette.background.paper + }, + [theme.breakpoints.down("sm")]: { + border: "none", + borderRadius: 16 + }, + border: `1px solid ${theme.palette.divider}`, + height: 40, + marginRight: theme.spacing(2), + padding: 6, + width: 40 + } + }; + }, + { + name: "NavigatorButton" + } +); + +export interface NavigatorButtonProps extends IconButtonProps { + isMac: boolean; +} + +const NavigatorButton: React.FC = ({ + className, + isMac, + ...props +}) => { + const classes = useStyles({}); + const helperTimer = React.useRef(null); + const [helperVisibility, setHelperVisibility] = React.useState(false); + const anchor = React.useRef(); + + const setHelper = () => { + helperTimer.current = setTimeout(() => setHelperVisibility(true), 2 * 1000); + }; + + const clearHelper = () => { + if (helperTimer.current) { + clearTimeout(helperTimer.current); + helperTimer.current = null; + } + setHelperVisibility(false); + }; + + return ( + <> + + + + + {({ TransitionProps, placement }) => ( + + + +
+ + {isMac ? "⌘" : "Ctrl"} + +
+
+ K +
+
+
+ )} +
+ + ); +}; + +NavigatorButton.displayName = "NavigatorButton"; +export default NavigatorButton; diff --git a/src/components/NotFoundPage/NotFoundPage.tsx b/src/components/NotFoundPage/NotFoundPage.tsx index ad36ceaab..6de11eaa6 100644 --- a/src/components/NotFoundPage/NotFoundPage.tsx +++ b/src/components/NotFoundPage/NotFoundPage.tsx @@ -1,3 +1,4 @@ +import notFoundImage from "@assets/images/not-found-404.svg"; import Button from "@material-ui/core/Button"; import { makeStyles } from "@material-ui/core/styles"; import Typography from "@material-ui/core/Typography"; @@ -5,8 +6,6 @@ import React from "react"; import SVG from "react-inlinesvg"; import { FormattedMessage } from "react-intl"; -import notFoundImage from "@assets/images/not-found-404.svg"; - const useStyles = makeStyles( theme => ({ button: { diff --git a/src/components/PhoneField/PhoneField.tsx b/src/components/PhoneField/PhoneField.tsx index d6a1567c9..efa90e8d7 100644 --- a/src/components/PhoneField/PhoneField.tsx +++ b/src/components/PhoneField/PhoneField.tsx @@ -1,8 +1,7 @@ import { makeStyles } from "@material-ui/core/styles"; import TextField from "@material-ui/core/TextField"; -import React from "react"; - import SingleSelectField from "@saleor/components/SingleSelectField"; +import React from "react"; const useStyles = makeStyles( theme => ({ diff --git a/src/components/RadioGroupField/RadioGroupField.tsx b/src/components/RadioGroupField/RadioGroupField.tsx index e44c9352e..2ef01e5a7 100644 --- a/src/components/RadioGroupField/RadioGroupField.tsx +++ b/src/components/RadioGroupField/RadioGroupField.tsx @@ -36,8 +36,11 @@ const useStyles = makeStyles( } ); -export interface RadioGroupFieldChoice { - value: string; +export interface RadioGroupFieldChoice< + T extends string | number = string | number +> { + disabled?: boolean; + value: T; label: React.ReactNode; } @@ -49,7 +52,7 @@ interface RadioGroupFieldProps { hint?: string; label?: string; name?: string; - value: string; + value: string | number; onChange: (event: React.ChangeEvent) => void; } @@ -87,6 +90,7 @@ export const RadioGroupField: React.FC = props => { {choices.length > 0 ? ( choices.map(choice => ( } diff --git a/src/components/RequirePermissions.tsx b/src/components/RequirePermissions.tsx index db6043255..a5f413fdc 100644 --- a/src/components/RequirePermissions.tsx +++ b/src/components/RequirePermissions.tsx @@ -1,7 +1,6 @@ -import React from "react"; - -import { User_userPermissions } from "@saleor/auth/types/User"; +import { User_userPermissions } from "@saleor/fragments/types/User"; import { PermissionEnum } from "@saleor/types/globalTypes"; +import React from "react"; export function hasPermissions( userPermissions: User_userPermissions[], diff --git a/src/components/RichTextEditor/ImageSource.tsx b/src/components/RichTextEditor/ImageSource.tsx index 766681eb9..d3ae28ff9 100644 --- a/src/components/RichTextEditor/ImageSource.tsx +++ b/src/components/RichTextEditor/ImageSource.tsx @@ -4,11 +4,11 @@ import DialogActions from "@material-ui/core/DialogActions"; import DialogContent from "@material-ui/core/DialogContent"; import DialogTitle from "@material-ui/core/DialogTitle"; import TextField from "@material-ui/core/TextField"; +import { buttonMessages } from "@saleor/intl"; import { AtomicBlockUtils, EditorState, EntityInstance } from "draft-js"; import React from "react"; import { FormattedMessage, useIntl } from "react-intl"; -import { buttonMessages } from "@saleor/intl"; import Form from "../Form"; interface ImageSourceProps { diff --git a/src/components/RichTextEditor/LinkEntity.tsx b/src/components/RichTextEditor/LinkEntity.tsx index 5a12f0195..86166fe2e 100644 --- a/src/components/RichTextEditor/LinkEntity.tsx +++ b/src/components/RichTextEditor/LinkEntity.tsx @@ -7,11 +7,11 @@ import Popper from "@material-ui/core/Popper"; import { makeStyles } from "@material-ui/core/styles"; import Typography from "@material-ui/core/Typography"; import DeleteIcon from "@material-ui/icons/Delete"; +import { buttonMessages } from "@saleor/intl"; import { ContentState } from "draft-js"; import React from "react"; import { FormattedMessage } from "react-intl"; -import { buttonMessages } from "@saleor/intl"; import Link from "../Link"; interface LinkEntityProps { diff --git a/src/components/RichTextEditor/LinkSource.tsx b/src/components/RichTextEditor/LinkSource.tsx index 433e956c1..b6c55e7a5 100644 --- a/src/components/RichTextEditor/LinkSource.tsx +++ b/src/components/RichTextEditor/LinkSource.tsx @@ -4,11 +4,11 @@ import DialogActions from "@material-ui/core/DialogActions"; import DialogContent from "@material-ui/core/DialogContent"; import DialogTitle from "@material-ui/core/DialogTitle"; import TextField from "@material-ui/core/TextField"; +import { buttonMessages } from "@saleor/intl"; import { EditorState, EntityInstance, RichUtils } from "draft-js"; import React from "react"; import { FormattedMessage, useIntl } from "react-intl"; -import { buttonMessages } from "@saleor/intl"; import Form from "../Form"; interface LinkSourceProps { diff --git a/src/components/RichTextEditor/RichTextEditor.tsx b/src/components/RichTextEditor/RichTextEditor.tsx index 463a9ad40..461b15ccc 100644 --- a/src/components/RichTextEditor/RichTextEditor.tsx +++ b/src/components/RichTextEditor/RichTextEditor.tsx @@ -1,7 +1,8 @@ import { makeStyles } from "@material-ui/core/styles"; import { fade } from "@material-ui/core/styles/colorManipulator"; import Typography from "@material-ui/core/Typography"; -import { FormattedMessage } from "react-intl"; +import { CreateCSSProperties } from "@material-ui/styles/withStyles"; +import { ChangeEvent } from "@saleor/hooks/useForm"; import classNames from "classnames"; import { RawDraftContentState } from "draft-js"; import { @@ -12,17 +13,16 @@ import { } from "draftail"; import isEqual from "lodash-es/isEqual"; import React from "react"; - -import { ChangeEvent } from "@saleor/hooks/useForm"; import ErrorBoundary from "react-error-boundary"; -import { CreateCSSProperties } from "@material-ui/styles/withStyles"; +import { FormattedMessage } from "react-intl"; + import BoldIcon from "../../icons/BoldIcon"; -import HeaderTwo from "../../icons/HeaderTwo"; +import HeaderOne from "../../icons/HeaderOne"; import HeaderThree from "../../icons/HeaderThree"; +import HeaderTwo from "../../icons/HeaderTwo"; import ItalicIcon from "../../icons/ItalicIcon"; import LinkIcon from "../../icons/LinkIcon"; import OrderedListIcon from "../../icons/OrderedListIcon"; -import HeaderOne from "../../icons/HeaderOne"; import QuotationIcon from "../../icons/QuotationIcon"; import StrikethroughIcon from "../../icons/StrikethroughIcon"; import UnorderedListIcon from "../../icons/UnorderedListIcon"; diff --git a/src/components/SaveButtonBar/SaveButtonBar.tsx b/src/components/SaveButtonBar/SaveButtonBar.tsx index 83ab6548a..b7a5b6cf0 100644 --- a/src/components/SaveButtonBar/SaveButtonBar.tsx +++ b/src/components/SaveButtonBar/SaveButtonBar.tsx @@ -1,12 +1,14 @@ import Button from "@material-ui/core/Button"; +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; import Portal from "@material-ui/core/Portal"; import { makeStyles } from "@material-ui/core/styles"; +import useWindowScroll from "@saleor/hooks/useWindowScroll"; +import { buttonMessages } from "@saleor/intl"; import classNames from "classnames"; import React from "react"; import { useIntl } from "react-intl"; -import useWindowScroll from "@saleor/hooks/useWindowScroll"; -import { buttonMessages } from "@saleor/intl"; import { maybe } from "../../misc"; import AppActionContext from "../AppLayout/AppActionContext"; import ConfirmButton, { @@ -16,13 +18,25 @@ import Container from "../Container"; const useStyles = makeStyles( theme => ({ + applyShadow: { + "&$card": { + boxShadow: "0px 6px 30px rgba(0, 0, 0, 0.16)" + } + }, button: { marginRight: theme.spacing(1) }, cancelButton: { marginRight: theme.spacing(2) }, - container: { + card: { + boxShadow: "0px 0px 0px rgba(0, 0, 0, 0.16)", + transition: theme.transitions.duration.shortest + "ms" + }, + content: { + "&:last-child": { + paddingBottom: theme.spacing(2) + }, display: "flex", paddingBottom: theme.spacing(2), paddingTop: theme.spacing(2), @@ -38,20 +52,10 @@ const useStyles = makeStyles( color: theme.palette.error.contrastText }, root: { - background: theme.palette.background.default, - borderTop: "1px solid transparent", - boxShadow: `0 -5px 5px 0 ${theme.palette.divider}`, - height: 70, - transition: `box-shadow ${theme.transitions.duration.shortest}ms` + height: 120 }, spacer: { flex: "1" - }, - stop: { - "&$root": { - borderTopColor: theme.palette.divider, - boxShadow: `0 0 0 0 ${theme.palette.divider}` - } } }), { name: "SaveButtonBar" } @@ -85,55 +89,58 @@ export const SaveButtonBar: React.FC = props => { const intl = useIntl(); const scrollPosition = useWindowScroll(); const scrolledToBottom = - scrollPosition.y + window.innerHeight >= document.body.scrollHeight; + scrollPosition.y + window.innerHeight - document.body.scrollHeight >= -5; return ( {anchor => anchor ? ( -
- - {!!onDelete && ( - - )} -
- - - {maybe( - () => labels.save, - intl.formatMessage(buttonMessages.save) - )} - + + {!!onDelete && ( + + )} +
+ + + {maybe( + () => labels.save, + intl.formatMessage(buttonMessages.save) + )} + + +
diff --git a/src/components/SaveFilterTabDialog/SaveFilterTabDialog.tsx b/src/components/SaveFilterTabDialog/SaveFilterTabDialog.tsx index a75f282a7..5b116531b 100644 --- a/src/components/SaveFilterTabDialog/SaveFilterTabDialog.tsx +++ b/src/components/SaveFilterTabDialog/SaveFilterTabDialog.tsx @@ -4,10 +4,10 @@ import DialogActions from "@material-ui/core/DialogActions"; import DialogContent from "@material-ui/core/DialogContent"; import DialogTitle from "@material-ui/core/DialogTitle"; import TextField from "@material-ui/core/TextField"; +import { buttonMessages } from "@saleor/intl"; import React from "react"; import { FormattedMessage, useIntl } from "react-intl"; -import { buttonMessages } from "@saleor/intl"; import ConfirmButton, { ConfirmButtonTransitionState } from "../ConfirmButton"; import Form from "../Form"; diff --git a/src/components/SearchBar/SearchBar.tsx b/src/components/SearchBar/SearchBar.tsx index 17c66b4bb..4493b62c1 100644 --- a/src/components/SearchBar/SearchBar.tsx +++ b/src/components/SearchBar/SearchBar.tsx @@ -1,9 +1,9 @@ +import Button from "@material-ui/core/Button"; +import makeStyles from "@material-ui/core/styles/makeStyles"; +import { SearchPageProps, TabPageProps } from "@saleor/types"; import React from "react"; import { FormattedMessage, useIntl } from "react-intl"; -import makeStyles from "@material-ui/core/styles/makeStyles"; -import Button from "@material-ui/core/Button"; -import { SearchPageProps, TabPageProps } from "@saleor/types"; import FilterTabs, { FilterTab } from "../TableFilter"; import SearchInput from "./SearchInput"; diff --git a/src/components/SearchBar/SearchInput.tsx b/src/components/SearchBar/SearchInput.tsx index 5d8b38e3e..ead6b46eb 100644 --- a/src/components/SearchBar/SearchInput.tsx +++ b/src/components/SearchBar/SearchInput.tsx @@ -1,6 +1,6 @@ import { makeStyles } from "@material-ui/core/styles"; -import React from "react"; import TextField from "@material-ui/core/TextField"; +import React from "react"; import { SearchPageProps } from "../../types"; import Debounce from "../Debounce"; diff --git a/src/components/Shop/index.tsx b/src/components/Shop/index.tsx index bf536a492..a99c967d9 100644 --- a/src/components/Shop/index.tsx +++ b/src/components/Shop/index.tsx @@ -1,10 +1,10 @@ -import React from "react"; -import Helmet from "react-helmet"; - import appleTouchIcon from "@assets/favicons/apple-touch-icon.png"; import favicon16 from "@assets/favicons/favicon-16x16.png"; import favicon32 from "@assets/favicons/favicon-32x32.png"; import safariPinnedTab from "@assets/favicons/safari-pinned-tab.svg"; +import React from "react"; +import Helmet from "react-helmet"; + import { TypedShopInfoQuery } from "./query"; import { ShopInfo_shop } from "./types/ShopInfo"; diff --git a/src/components/Shop/types/ShopInfo.ts b/src/components/Shop/types/ShopInfo.ts index f0f99ecfc..685af9f96 100644 --- a/src/components/Shop/types/ShopInfo.ts +++ b/src/components/Shop/types/ShopInfo.ts @@ -40,7 +40,7 @@ export interface ShopInfo_shop_permissions { export interface ShopInfo_shop { __typename: "Shop"; - countries: (ShopInfo_shop_countries | null)[]; + countries: ShopInfo_shop_countries[]; defaultCountry: ShopInfo_shop_defaultCountry | null; defaultCurrency: string; defaultWeightUnit: WeightUnitsEnum | null; diff --git a/src/components/SideBar/ExpandButton.tsx b/src/components/SideBar/ExpandButton.tsx new file mode 100644 index 000000000..379d6be95 --- /dev/null +++ b/src/components/SideBar/ExpandButton.tsx @@ -0,0 +1,42 @@ +import { ButtonProps } from "@material-ui/core/Button"; +import makeStyles from "@material-ui/core/styles/makeStyles"; +import ArrowIcon from "@material-ui/icons/ArrowBack"; +import classNames from "classnames"; +import React from "react"; + +import SquareButton from "../SquareButton"; + +const useStyles = makeStyles( + theme => ({ + arrow: { + transition: theme.transitions.duration.shortest + "ms" + }, + shrunk: { + transform: "scaleX(-1)" + } + }), + { + name: "ExpandButton" + } +); + +export interface ExpandButtonProps extends ButtonProps { + isShrunk: boolean; +} + +const ExpandButton: React.FC = ({ isShrunk, ...rest }) => { + const classes = useStyles({}); + + return ( + + + + ); +}; + +ExpandButton.displayName = "ExpandButton"; +export default ExpandButton; diff --git a/src/components/SideBar/MenuItem.tsx b/src/components/SideBar/MenuItem.tsx new file mode 100644 index 000000000..77462c507 --- /dev/null +++ b/src/components/SideBar/MenuItem.tsx @@ -0,0 +1,199 @@ +import ClickAwayListener from "@material-ui/core/ClickAwayListener"; +import Paper from "@material-ui/core/Paper"; +import Popper from "@material-ui/core/Popper"; +import { fade } from "@material-ui/core/styles/colorManipulator"; +import makeStyles from "@material-ui/core/styles/makeStyles"; +import Typography from "@material-ui/core/Typography"; +import { UseNavigatorResult } from "@saleor/hooks/useNavigator"; +import classNames from "classnames"; +import React from "react"; +import SVG from "react-inlinesvg"; + +import { IMenuItem } from "../AppLayout/menuStructure"; + +export interface MenuItemProps { + active: boolean; + isMenuShrunk: boolean; + menuItem: IMenuItem; + onClick: UseNavigatorResult; +} + +export const menuWidth = 210; +export const shrunkMenuWidth = 72; + +const useStyles = makeStyles( + theme => ({ + hideLabel: { + "&$label": { + opacity: 0 + } + }, + icon: { + "& svg": { + height: 24, + width: 24 + }, + marginRight: theme.spacing(1.5), + transition: theme.transitions.duration.shortest + "ms" + }, + label: { + cursor: "pointer", + display: "block", + fontSize: 16, + fontWeight: "bold", + opacity: 1, + transition: theme.transitions.duration.shortest + "ms" + }, + menuItemBtn: { + "&:focus": { + color: theme.palette.primary.main, + outline: 0 + }, + background: "none", + border: "none", + color: "inherit", + cursor: "pointer", + display: "inline-flex", + margin: 0, + padding: 0 + }, + paper: { + borderRadius: 16, + boxShadow: "0px 6px 30px rgba(0, 0, 0, 0.16)", + cursor: "default", + padding: theme.spacing(3), + textAlign: "left" + }, + popper: { + marginLeft: theme.spacing(3), + zIndex: 2 + }, + root: { + "&:hover, &:focus": { + color: theme.palette.primary.main, + outline: 0 + }, + borderBottomRightRadius: 100, + borderTopRightRadius: 100, + color: fade(theme.palette.text.primary, 0.6), + cursor: "pointer", + display: "flex", + height: 56, + marginBottom: theme.spacing(), + overflow: "hidden", + padding: theme.spacing(2, 3, 2, 3.5), + transition: theme.transitions.duration.shortest + "ms", + width: shrunkMenuWidth + }, + rootActive: { + "&$root": { + background: theme.palette.background.paper, + boxShadow: "0px 6px 30px rgba(0, 0, 0, 0.16)", + color: theme.palette.primary.main + } + }, + rootExpanded: { + width: menuWidth + }, + subMenuLabel: { + "&$label": { + "&:not(:last-child)": { + marginBottom: theme.spacing(2) + } + }, + "&:hover, &:focus": { + color: theme.palette.primary.main, + outline: 0 + }, + background: "none", + border: "none", + color: fade(theme.palette.text.primary, 0.6), + textAlign: "left", + whiteSpace: "nowrap" + } + }), + { + name: "MenuItem" + } +); + +const MenuItem: React.FC = ({ + active, + menuItem, + isMenuShrunk, + onClick +}) => { + const classes = useStyles({}); + const [open, setOpen] = React.useState(false); + const anchor = React.useRef(null); + + const handleClick = (event: React.MouseEvent, menuItem: IMenuItem) => { + event.stopPropagation(); + if (menuItem.children) { + setOpen(true); + } else { + onClick(menuItem.url); + setOpen(false); + } + }; + + return ( +
handleClick(event, menuItem)} + > + + {menuItem.children && ( + + setOpen(false)}> + + {menuItem.children.map(subMenuItem => ( + handleClick(event, subMenuItem)} + data-test="submenu-item-label" + data-test-id={subMenuItem.testingContextId} + variant="body2" + > + {subMenuItem.label} + + ))} + + + + )} +
+ ); +}; + +MenuItem.displayName = "MenuItem"; +export default MenuItem; diff --git a/src/components/SideBar/SideBar.tsx b/src/components/SideBar/SideBar.tsx new file mode 100644 index 000000000..77b4f3ee4 --- /dev/null +++ b/src/components/SideBar/SideBar.tsx @@ -0,0 +1,134 @@ +import logoLight from "@assets/images/logo-sidebar-light.svg"; +import configurationIcon from "@assets/images/menu-configure-icon.svg"; +import makeStyles from "@material-ui/core/styles/makeStyles"; +import { configurationMenuUrl } from "@saleor/configuration"; +import { User } from "@saleor/fragments/types/User"; +import useLocalStorage from "@saleor/hooks/useLocalStorage"; +import { UseNavigatorResult } from "@saleor/hooks/useNavigator"; +import { sectionNames } from "@saleor/intl"; +import classNames from "classnames"; +import React from "react"; +import SVG from "react-inlinesvg"; +import { IntlShape, useIntl } from "react-intl"; + +import { IMenuItem } from "../AppLayout/menuStructure"; +import ExpandButton from "./ExpandButton"; +import MenuItem, { menuWidth, shrunkMenuWidth } from "./MenuItem"; +import { isMenuActive } from "./utils"; + +const useStyles = makeStyles( + theme => ({ + expandButton: { + marginLeft: theme.spacing(2) + }, + float: { + position: "fixed" + }, + logo: { + margin: `36px 0 ${theme.spacing(3)}px ${theme.spacing(3)}px` + }, + root: { + transition: "width 0.5s ease", + width: menuWidth, + zIndex: 100 + }, + rootShrink: { + width: shrunkMenuWidth + } + }), + { + name: "SideBar" + } +); + +export interface SideBarProps { + className?: string; + menuItems: IMenuItem[]; + location: string; + user: User; + renderConfigure: boolean; + onMenuItemClick: UseNavigatorResult; +} + +export interface IActiveSubMenu { + isActive: boolean; + label: string | null; +} + +export const getConfigureMenuItem = (intl: IntlShape): IMenuItem => ({ + ariaLabel: "configure", + icon: configurationIcon, + label: intl.formatMessage(sectionNames.configuration), + testingContextId: "configure", + url: configurationMenuUrl +}); + +const SideBar: React.FC = ({ + location, + menuItems, + renderConfigure, + user, + onMenuItemClick +}) => { + const classes = useStyles({}); + const [isShrunk, setShrink] = useLocalStorage("isMenuSmall", false); + const intl = useIntl(); + const configureMenuItem = getConfigureMenuItem(intl); + + return ( +
+
+
+ +
+ {menuItems.map(menuItem => { + const isActive = isMenuActive(location, menuItem); + + if ( + menuItem.permission && + !user.userPermissions + .map(perm => perm.code) + .includes(menuItem.permission) + ) { + return null; + } + + return ( + + ); + })} + {renderConfigure && ( + acc || isMenuActive(location, menuItem), + false + ) + } + isMenuShrunk={isShrunk} + menuItem={configureMenuItem} + onClick={onMenuItemClick} + /> + )} + setShrink(!isShrunk)} + /> +
+
+ ); +}; + +SideBar.displayName = "SideBar"; +export default SideBar; diff --git a/src/components/SideBar/SubMenu.tsx b/src/components/SideBar/SubMenu.tsx new file mode 100644 index 000000000..e69de29bb diff --git a/src/components/SideBar/index.ts b/src/components/SideBar/index.ts new file mode 100644 index 000000000..df08bddc7 --- /dev/null +++ b/src/components/SideBar/index.ts @@ -0,0 +1,2 @@ +export * from "./SideBar"; +export { default } from "./SideBar"; diff --git a/src/components/SideBar/utils.ts b/src/components/SideBar/utils.ts new file mode 100644 index 000000000..06827a7ac --- /dev/null +++ b/src/components/SideBar/utils.ts @@ -0,0 +1,24 @@ +import { orderDraftListUrl, orderListUrl } from "@saleor/orders/urls"; +import { matchPath } from "react-router"; + +import { IMenuItem } from "../AppLayout/menuStructure"; + +export function isMenuActive(location: string, menuItem: IMenuItem) { + if (menuItem.children) { + return menuItem.children.reduce( + (acc, subMenuItem) => acc || isMenuActive(location, subMenuItem), + false + ); + } + + const activeUrl = location.split("?")[0]; + const menuItemUrl = menuItem.url.split("?")[0]; + + return activeUrl === orderDraftListUrl().split("?")[0] && + menuItemUrl === orderListUrl().split("?")[0] + ? false + : !!matchPath(activeUrl, { + exact: menuItemUrl === "/", + path: menuItemUrl + }); +} diff --git a/src/components/SideBarDrawer/MenuItemBtn.tsx b/src/components/SideBarDrawer/MenuItemBtn.tsx new file mode 100644 index 000000000..9013d5f36 --- /dev/null +++ b/src/components/SideBarDrawer/MenuItemBtn.tsx @@ -0,0 +1,32 @@ +import Typography from "@material-ui/core/Typography"; +import { UseNavigatorResult } from "@saleor/hooks/useNavigator"; +import React from "react"; +import SVG from "react-inlinesvg"; + +import { IMenuItem } from "../AppLayout/menuStructure"; +import useStyles from "./styles"; + +export interface MenuItemBtnProps { + menuItem: IMenuItem; + onClick: UseNavigatorResult; +} +const MenuItemBtn: React.FC = ({ menuItem, onClick }) => { + const classes = useStyles({}); + + return ( + + ); +}; + +MenuItemBtn.displayName = "MenuItemBtn"; +export default MenuItemBtn; diff --git a/src/components/SideBarDrawer/SideBarDrawer.stories.tsx b/src/components/SideBarDrawer/SideBarDrawer.stories.tsx new file mode 100644 index 000000000..057ee7b90 --- /dev/null +++ b/src/components/SideBarDrawer/SideBarDrawer.stories.tsx @@ -0,0 +1,37 @@ +import { staffMember } from "@saleor/staff/fixtures"; +import Decorator from "@saleor/storybook/Decorator"; +import { storiesOf } from "@storybook/react"; +import { config } from "@test/intl"; +import React from "react"; +import { createIntl } from "react-intl"; + +import createMenuStructure from "../AppLayout/menuStructure"; +import SideBarDrawer from "./SideBarDrawer"; + +const intl = createIntl(config); +const user = { + __typename: staffMember.__typename, + avatar: { + __typename: staffMember.avatar.__typename, + url: staffMember.avatar.url + }, + email: staffMember.email, + firstName: "Adam Evan", + id: staffMember.id, + isStaff: true, + lastName: "Newton", + note: null, + userPermissions: staffMember.userPermissions +}; + +storiesOf("Generics / Mobile Side Menu", module) + .addDecorator(Decorator) + .add("default", () => ( + undefined} + renderConfigure={true} + user={user} + /> + )); diff --git a/src/components/SideBarDrawer/SideBarDrawer.tsx b/src/components/SideBarDrawer/SideBarDrawer.tsx new file mode 100644 index 000000000..e7963401c --- /dev/null +++ b/src/components/SideBarDrawer/SideBarDrawer.tsx @@ -0,0 +1,132 @@ +import logoLight from "@assets/images/logo-sidebar-light.svg"; +import { Typography } from "@material-ui/core"; +import Drawer from "@material-ui/core/Drawer"; +import ArrowLeftIcon from "@material-ui/icons/ArrowLeft"; +import MenuIcon from "@material-ui/icons/Menu"; +import classNames from "classnames"; +import React from "react"; +import SVG from "react-inlinesvg"; +import { useIntl } from "react-intl"; + +import { IMenuItem } from "../AppLayout/menuStructure"; +import { getConfigureMenuItem, SideBarProps } from "../SideBar/SideBar"; +import SquareButton from "../SquareButton"; +import MenuItemBtn from "./MenuItemBtn"; +import useStyles from "./styles"; + +export type SideBarDrawerProps = SideBarProps; + +const SideBarDrawer: React.FC = ({ + menuItems, + onMenuItemClick, + renderConfigure, + user +}) => { + const [isOpened, setOpened] = React.useState(false); + const classes = useStyles({}); + const intl = useIntl(); + const [activeMenu, setActiveMenu] = React.useState(null); + const [showSubmenu, setShowSubmenu] = React.useState(false); + const container = React.useRef(null); + + const configureMenuItem = getConfigureMenuItem(intl); + + const handleMenuItemClick = (url: string) => { + setOpened(false); + setShowSubmenu(false); + onMenuItemClick(url); + }; + + const handleMenuItemWithChildrenClick = (menuItem: IMenuItem) => { + setActiveMenu(menuItem); + setShowSubmenu(true); + container.current.scrollTo({ + top: 0 + }); + }; + + return ( + <> + setOpened(true)}> + + + setOpened(false)} + > +
+
+
+ + {menuItems.map(menuItem => { + if ( + menuItem.permission && + !user.userPermissions + .map(perm => perm.code) + .includes(menuItem.permission) + ) { + return null; + } + + return ( + handleMenuItemWithChildrenClick(menuItem) + : handleMenuItemClick + } + key={menuItem.ariaLabel} + /> + ); + })} + {renderConfigure && ( + + )} +
+ {activeMenu && ( +
+
+
+ + + {activeMenu.label} + +
+ setShowSubmenu(false)}> + + +
+ {activeMenu.children.map(subMenuItem => ( + + ))} +
+ )} +
+
+
+ + ); +}; + +SideBarDrawer.displayName = "SideBarDrawer"; +export default SideBarDrawer; diff --git a/src/components/SideBarDrawer/index.ts b/src/components/SideBarDrawer/index.ts new file mode 100644 index 000000000..e69de29bb diff --git a/src/components/SideBarDrawer/styles.ts b/src/components/SideBarDrawer/styles.ts new file mode 100644 index 000000000..92cda2a00 --- /dev/null +++ b/src/components/SideBarDrawer/styles.ts @@ -0,0 +1,68 @@ +import makeStyles from "@material-ui/core/styles/makeStyles"; + +const useStyles = makeStyles( + theme => ({ + activeMenuLabel: { + display: "flex" + }, + container: { + overflowX: "hidden", + width: "100%" + }, + containerSubMenu: { + "&$container": { + overflow: "hidden" + } + }, + content: { + width: "50%" + }, + icon: { + marginRight: theme.spacing(2) + }, + innerContainer: { + display: "flex", + position: "relative", + right: 0, + transition: theme.transitions.duration.short + "ms", + width: "200%" + }, + label: { + fontWeight: "bold" + }, + logo: { + display: "block", + marginBottom: theme.spacing(4) + }, + menuItemBtn: { + alignItems: "center", + background: "none", + border: "none", + color: theme.palette.text.secondary, + display: "flex", + marginBottom: theme.spacing(3), + padding: 0 + }, + root: { + background: theme.palette.background.default, + borderBottomRightRadius: 32, + borderTopRightRadius: 32, + padding: theme.spacing(3), + width: 260 + }, + secondaryContentActive: { + right: "100%" + }, + subMenuTopBar: { + alignItems: "center", + display: "flex", + justifyContent: "space-between", + marginBottom: theme.spacing(3) + } + }), + { + name: "SideBarDrawer" + } +); + +export default useStyles; diff --git a/src/components/SingleAutocompleteSelectField/SingleAutocompleteSelectField.stories.tsx b/src/components/SingleAutocompleteSelectField/SingleAutocompleteSelectField.stories.tsx index 303bf4fa2..791cf77e8 100644 --- a/src/components/SingleAutocompleteSelectField/SingleAutocompleteSelectField.stories.tsx +++ b/src/components/SingleAutocompleteSelectField/SingleAutocompleteSelectField.stories.tsx @@ -1,12 +1,12 @@ -import { storiesOf } from "@storybook/react"; -import React from "react"; - import Form from "@saleor/components/Form"; import { countries } from "@saleor/fixtures"; import CardDecorator from "@saleor/storybook/CardDecorator"; import Decorator from "@saleor/storybook/Decorator"; import { ChoiceProvider } from "@saleor/storybook/mock"; import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler"; +import { storiesOf } from "@storybook/react"; +import React from "react"; + import SingleAutocompleteSelectField, { SingleAutocompleteSelectFieldProps } from "./SingleAutocompleteSelectField"; diff --git a/src/components/SingleAutocompleteSelectField/SingleAutocompleteSelectField.tsx b/src/components/SingleAutocompleteSelectField/SingleAutocompleteSelectField.tsx index f140d4c05..bca5ac905 100644 --- a/src/components/SingleAutocompleteSelectField/SingleAutocompleteSelectField.tsx +++ b/src/components/SingleAutocompleteSelectField/SingleAutocompleteSelectField.tsx @@ -1,17 +1,17 @@ import { InputProps } from "@material-ui/core/Input"; import { makeStyles } from "@material-ui/core/styles"; import TextField from "@material-ui/core/TextField"; +import useStateFromProps from "@saleor/hooks/useStateFromProps"; +import { FetchMoreProps } from "@saleor/types"; import Downshift from "downshift"; import { filter } from "fuzzaldrin"; import React from "react"; -import useStateFromProps from "@saleor/hooks/useStateFromProps"; -import { FetchMoreProps } from "@saleor/types"; import ArrowDropdownIcon from "../../icons/ArrowDropdown"; import Debounce, { DebounceProps } from "../Debounce"; import SingleAutocompleteSelectFieldContent, { - SingleAutocompleteChoiceType, - SingleAutocompleteActionType + SingleAutocompleteActionType, + SingleAutocompleteChoiceType } from "./SingleAutocompleteSelectFieldContent"; const useStyles = makeStyles( diff --git a/src/components/SingleAutocompleteSelectField/SingleAutocompleteSelectFieldContent.tsx b/src/components/SingleAutocompleteSelectField/SingleAutocompleteSelectFieldContent.tsx index 1375deebf..9a6794d65 100644 --- a/src/components/SingleAutocompleteSelectField/SingleAutocompleteSelectFieldContent.tsx +++ b/src/components/SingleAutocompleteSelectField/SingleAutocompleteSelectFieldContent.tsx @@ -1,20 +1,20 @@ +import chevronDown from "@assets/images/ChevronDown.svg"; import CircularProgress from "@material-ui/core/CircularProgress"; import MenuItem from "@material-ui/core/MenuItem"; -import Add from "@material-ui/icons/Add"; import Paper from "@material-ui/core/Paper"; import { makeStyles } from "@material-ui/core/styles"; import Typography from "@material-ui/core/Typography"; +import Add from "@material-ui/icons/Add"; +import useElementScroll, { + isScrolledToBottom +} from "@saleor/hooks/useElementScroll"; +import { FetchMoreProps } from "@saleor/types"; import classNames from "classnames"; import { GetItemPropsOptions } from "downshift"; import React from "react"; import SVG from "react-inlinesvg"; import { FormattedMessage } from "react-intl"; -import chevronDown from "@assets/images/ChevronDown.svg"; -import useElementScroll, { - isScrolledToBottom -} from "@saleor/hooks/useElementScroll"; -import { FetchMoreProps } from "@saleor/types"; import Hr from "../Hr"; const menuItemHeight = 46; @@ -175,7 +175,7 @@ const SingleAutocompleteSelectFieldContent: React.FC @@ -189,7 +189,7 @@ const SingleAutocompleteSelectFieldContent: React.FC @@ -205,7 +205,7 @@ const SingleAutocompleteSelectFieldContent: React.FC {suggestion.label} @@ -256,7 +256,7 @@ const SingleAutocompleteSelectFieldContent: React.FC diff --git a/src/components/SingleSelectField/SingleSelectField.tsx b/src/components/SingleSelectField/SingleSelectField.tsx index 87bd69de3..6009b4c76 100644 --- a/src/components/SingleSelectField/SingleSelectField.tsx +++ b/src/components/SingleSelectField/SingleSelectField.tsx @@ -1,5 +1,6 @@ import FormControl from "@material-ui/core/FormControl"; import FormHelperText from "@material-ui/core/FormHelperText"; +import { InputProps } from "@material-ui/core/Input"; import InputLabel from "@material-ui/core/InputLabel"; import MenuItem from "@material-ui/core/MenuItem"; import OutlinedInput from "@material-ui/core/OutlinedInput"; @@ -8,7 +9,6 @@ import { makeStyles } from "@material-ui/core/styles"; import classNames from "classnames"; import React from "react"; import { FormattedMessage } from "react-intl"; -import { InputProps } from "@material-ui/core/Input"; const useStyles = makeStyles( theme => ({ @@ -99,12 +99,21 @@ export const SingleSelectField: React.FC = props => { > {choices.length > 0 ? ( choices.map(choice => ( - + {choice.label} )) ) : ( - + )} diff --git a/src/components/SortableTable/SortableHandle.tsx b/src/components/SortableTable/SortableHandle.tsx index d9369fcb1..40997efd8 100644 --- a/src/components/SortableTable/SortableHandle.tsx +++ b/src/components/SortableTable/SortableHandle.tsx @@ -1,10 +1,9 @@ import makeStyles from "@material-ui/core/styles/makeStyles"; import TableCell from "@material-ui/core/TableCell"; +import Draggable from "@saleor/icons/Draggable"; import React from "react"; import { SortableHandle as SortableHandleHoc } from "react-sortable-hoc"; -import Draggable from "@saleor/icons/Draggable"; - const useStyles = makeStyles( theme => ({ columnDrag: { diff --git a/src/components/SortableTable/SortableTableBody.tsx b/src/components/SortableTable/SortableTableBody.tsx index 79d8f74fb..4a8d715c8 100644 --- a/src/components/SortableTable/SortableTableBody.tsx +++ b/src/components/SortableTable/SortableTableBody.tsx @@ -1,10 +1,9 @@ import makeStyles from "@material-ui/core/styles/makeStyles"; import TableBody, { TableBodyProps } from "@material-ui/core/TableBody"; +import { ReorderAction } from "@saleor/types"; import React from "react"; import { SortableContainer } from "react-sortable-hoc"; -import { ReorderAction } from "@saleor/types"; - const InnerSortableTableBody = SortableContainer( ({ children, ...props }) => {children} ); @@ -29,9 +28,10 @@ const useStyles = makeStyles( { name: "SortableTableBody" } ); -const SortableTableBody: React.FC< - Omit -> = props => { +const SortableTableBody: React.FC> = props => { const classes = useStyles({}); return ( diff --git a/src/components/SortableTable/SortableTableRow.tsx b/src/components/SortableTable/SortableTableRow.tsx index f75299921..48a77dad1 100644 --- a/src/components/SortableTable/SortableTableRow.tsx +++ b/src/components/SortableTable/SortableTableRow.tsx @@ -1,6 +1,7 @@ import TableRow, { TableRowProps } from "@material-ui/core/TableRow"; import React from "react"; import { SortableElement } from "react-sortable-hoc"; + import SortableHandle from "./SortableHandle"; const SortableTableRow = SortableElement( diff --git a/src/components/SquareButton/SquareButton.stories.tsx b/src/components/SquareButton/SquareButton.stories.tsx new file mode 100644 index 000000000..2458c5d9f --- /dev/null +++ b/src/components/SquareButton/SquareButton.stories.tsx @@ -0,0 +1,14 @@ +import CloseIcon from "@material-ui/icons/Close"; +import Decorator from "@saleor/storybook/Decorator"; +import { storiesOf } from "@storybook/react"; +import React from "react"; + +import SquareButton from "./SquareButton"; + +storiesOf("Generics / Square Button", module) + .addDecorator(Decorator) + .add("default", () => ( + + + + )); diff --git a/src/components/SquareButton/SquareButton.tsx b/src/components/SquareButton/SquareButton.tsx new file mode 100644 index 000000000..5e69a2fd9 --- /dev/null +++ b/src/components/SquareButton/SquareButton.tsx @@ -0,0 +1,34 @@ +import ButtonBase, { ButtonBaseProps } from "@material-ui/core/ButtonBase"; +import makeStyles from "@material-ui/core/styles/makeStyles"; +import classNames from "classnames"; +import React from "react"; + +const useStyles = makeStyles( + theme => ({ + root: { + "&:hover, &:focus": { + background: "#daedeb" + }, + background: theme.palette.background.paper, + borderRadius: 16, + color: theme.palette.primary.main, + height: 48, + transition: theme.transitions.duration.shortest + "ms", + width: 48 + } + }), + { + name: "ExpandButton" + } +); + +const SquareButton: React.FC = ({ className, ...rest }) => { + const classes = useStyles({}); + + return ( + + ); +}; + +SquareButton.displayName = "SquareButton"; +export default SquareButton; diff --git a/src/components/SquareButton/index.ts b/src/components/SquareButton/index.ts new file mode 100644 index 000000000..7f406f96b --- /dev/null +++ b/src/components/SquareButton/index.ts @@ -0,0 +1,2 @@ +export * from "./SquareButton"; +export { default } from "./SquareButton"; diff --git a/src/components/TableCellHeader/TableCellHeader.stories.tsx b/src/components/TableCellHeader/TableCellHeader.stories.tsx index 25d2e24c6..bf6148f4f 100644 --- a/src/components/TableCellHeader/TableCellHeader.stories.tsx +++ b/src/components/TableCellHeader/TableCellHeader.stories.tsx @@ -3,10 +3,10 @@ import TableBody from "@material-ui/core/TableBody"; import TableCell from "@material-ui/core/TableCell"; import TableHead from "@material-ui/core/TableHead"; import TableRow from "@material-ui/core/TableRow"; +import ResponsiveTable from "@saleor/components/ResponsiveTable"; import { storiesOf } from "@storybook/react"; import React from "react"; -import ResponsiveTable from "@saleor/components/ResponsiveTable"; import Decorator from "../../storybook/Decorator"; import TableCellHeader, { TableCellHeaderArrowDirection diff --git a/src/components/TableHead/TableHead.tsx b/src/components/TableHead/TableHead.tsx index 113a7cd65..f382fa1c7 100644 --- a/src/components/TableHead/TableHead.tsx +++ b/src/components/TableHead/TableHead.tsx @@ -11,7 +11,6 @@ import React from "react"; import { FormattedMessage } from "react-intl"; import { Node } from "../../types"; - import Checkbox from "../Checkbox"; export interface TableHeadProps extends MuiTableHeadProps { @@ -29,23 +28,6 @@ const useStyles = makeStyles( cell: { padding: 0 }, - checkboxPartialSelect: { - "& input": { - "&:before": { - background: [theme.palette.background.paper, "!important"] as any, - border: `solid 1px ${theme.palette.primary.main}`, - content: "''" - }, - background: theme.palette.background.paper - }, - "&:after": { - background: theme.palette.primary.main, - content: "''", - height: 2, - position: "absolute", - width: 6 - } - }, checkboxSelected: { backgroundColor: fade(theme.palette.primary.main, 0.05) }, @@ -114,10 +96,7 @@ const TableHead: React.FC = props => { })} > selected && selected > 0 - })} + indeterminate={items && items.length > selected && selected > 0} checked={selected === 0 ? false : true} disabled={disabled} onChange={() => toggleAll(items, selected)} diff --git a/src/components/TablePagination/TablePagination.tsx b/src/components/TablePagination/TablePagination.tsx index 9a669bf0c..af5f09e5c 100644 --- a/src/components/TablePagination/TablePagination.tsx +++ b/src/components/TablePagination/TablePagination.tsx @@ -2,10 +2,10 @@ import { IconButtonProps } from "@material-ui/core/IconButton"; import { makeStyles } from "@material-ui/core/styles"; import TableCell from "@material-ui/core/TableCell"; import Toolbar from "@material-ui/core/Toolbar"; -import React from "react"; - import RowNumberSelect from "@saleor/components/RowNumberSelect"; import { maybe } from "@saleor/misc"; +import React from "react"; + import { ListSettings } from "../../types"; import TablePaginationActions from "./TablePaginationActions"; @@ -94,7 +94,7 @@ const TablePagination: React.FC = props => {
{maybe(() => settings.rowNumber) && ( diff --git a/src/components/TablePagination/TablePaginationActions.tsx b/src/components/TablePagination/TablePaginationActions.tsx index f847475d3..0fd037f77 100644 --- a/src/components/TablePagination/TablePaginationActions.tsx +++ b/src/components/TablePagination/TablePaginationActions.tsx @@ -62,9 +62,7 @@ export interface TablePaginationActionsProps { onPreviousPage(event); } -export const TablePaginationActions: React.FC< - TablePaginationActionsProps -> = props => { +export const TablePaginationActions: React.FC = props => { const { backIconButtonProps, className, @@ -89,7 +87,7 @@ export const TablePaginationActions: React.FC< })} onClick={onPreviousPage} disabled={!hasPreviousPage} - data-tc="button-pagination-back" + data-test="button-pagination-back" {...backIconButtonProps} > {direction === "rtl" ? : } @@ -101,7 +99,7 @@ export const TablePaginationActions: React.FC< })} onClick={onNextPage} disabled={!hasNextPage} - data-tc="button-pagination-next" + data-test="button-pagination-next" {...nextIconButtonProps} > {direction === "rtl" ? : } diff --git a/src/components/Theme/ThemeProvider.tsx b/src/components/Theme/ThemeProvider.tsx index 591358b2b..e4db1eb4e 100644 --- a/src/components/Theme/ThemeProvider.tsx +++ b/src/components/Theme/ThemeProvider.tsx @@ -1,5 +1,10 @@ import { MuiThemeProvider } from "@material-ui/core/styles"; -import React from "react"; +import { + ExtensionMessageType, + sendMessageToExtension, + ThemeChangeMessage +} from "@saleor/macaw-ui/extensions"; +import React, { useEffect } from "react"; import Helmet from "react-helmet"; import Baseline from "../../Baseline"; @@ -8,10 +13,12 @@ import { dark, light } from "./themes"; interface IThemeContext { isDark: boolean; + sendThemeToExtension: () => void; toggleTheme: () => void; } export const ThemeContext = React.createContext({ isDark: false, + sendThemeToExtension: () => undefined, toggleTheme: () => undefined }); @@ -23,17 +30,31 @@ const ThemeProvider: React.FC = ({ isDefaultDark }) => { const [isDark, setDark] = React.useState(isDefaultDark); + const sendThemeToExtension = () => + sendMessageToExtension( + { + theme: isDark ? "dark" : "light", + type: ExtensionMessageType.THEME + }, + "*" + ); + const toggleTheme = () => { setDark(!isDark); localStorage.setItem("theme", (!isDark).toString()); }; + useEffect(() => { + sendThemeToExtension(); + }, [isDark]); + const theme = createTheme(isDark ? dark : light); return ( diff --git a/src/components/Theme/themes.ts b/src/components/Theme/themes.ts index 7dffeed5c..8a17c1bbf 100644 --- a/src/components/Theme/themes.ts +++ b/src/components/Theme/themes.ts @@ -70,7 +70,7 @@ export const dark: IThemeColors = { export const light: IThemeColors = { autofill: "#f4f6c5", background: { - default: "#F1F6F6", + default: "#EFF5F8", paper: "#FFFFFF" }, checkbox: { diff --git a/src/components/UserChip/UserChip.tsx b/src/components/UserChip/UserChip.tsx new file mode 100644 index 000000000..165499ea7 --- /dev/null +++ b/src/components/UserChip/UserChip.tsx @@ -0,0 +1,183 @@ +import Avatar from "@material-ui/core/Avatar"; +import Chip from "@material-ui/core/Chip"; +import ClickAwayListener from "@material-ui/core/ClickAwayListener"; +import Grow from "@material-ui/core/Grow"; +import Hidden from "@material-ui/core/Hidden"; +import MenuItem from "@material-ui/core/MenuItem"; +import Menu from "@material-ui/core/MenuList"; +import Paper from "@material-ui/core/Paper"; +import Popper from "@material-ui/core/Popper"; +import makeStyles from "@material-ui/core/styles/makeStyles"; +import { User } from "@saleor/fragments/types/User"; +import ArrowDropdown from "@saleor/icons/ArrowDropdown"; +import { getUserInitials, getUserName } from "@saleor/misc"; +import classNames from "classnames"; +import React from "react"; +import { FormattedMessage } from "react-intl"; + +const useStyles = makeStyles( + theme => ({ + arrow: { + [theme.breakpoints.down("sm")]: { + marginLeft: 0 + }, + marginLeft: theme.spacing(2), + transition: theme.transitions.duration.standard + "ms" + }, + avatar: { + "&&": { + [theme.breakpoints.down("sm")]: { + height: 40, + width: 40 + }, + height: 32, + width: 32 + } + }, + avatarInitials: { + color: theme.palette.primary.contrastText + }, + avatarPlaceholder: { + alignItems: "center", + background: theme.palette.primary.main, + borderRadius: "100%", + display: "flex", + justifyContent: "center" + }, + popover: { + marginTop: theme.spacing(2), + zIndex: 1 + }, + rotate: { + transform: "rotate(180deg)" + }, + userChip: { + [theme.breakpoints.down("sm")]: { + height: 48 + }, + backgroundColor: theme.palette.background.paper, + borderRadius: 24, + color: theme.palette.text.primary, + height: 40, + padding: theme.spacing(0.5) + }, + userMenuContainer: { + position: "relative" + }, + userMenuItem: { + textAlign: "right" + } + }), + { + name: "UserChip" + } +); + +export interface UserChipProps { + user: User; + onLogout: () => void; + onProfileClick: () => void; +} + +const UserChip: React.FC = ({ + user, + onLogout, + onProfileClick +}) => { + const classes = useStyles({}); + const [isMenuOpened, setMenuState] = React.useState(false); + const anchor = React.useRef(); + + const handleLogout = () => { + setMenuState(false); + onLogout(); + }; + + const handleViewerProfile = () => { + setMenuState(false); + onProfileClick(); + }; + + return ( +
+ + ) : ( +
+
+ {getUserInitials(user)} +
+
+ ) + } + classes={{ + avatar: classes.avatar + }} + className={classes.userChip} + label={ + <> + {getUserName(user, true)} + + + } + onClick={() => setMenuState(!isMenuOpened)} + data-test="userMenu" + /> + + {({ TransitionProps, placement }) => ( + + + setMenuState(false)} + mouseEvent="onClick" + > + + + + + + + + + + + + )} + +
+ ); +}; +UserChip.displayName = "UserChip"; +export default UserChip; diff --git a/src/components/UserChip/index.ts b/src/components/UserChip/index.ts new file mode 100644 index 000000000..125a4544b --- /dev/null +++ b/src/components/UserChip/index.ts @@ -0,0 +1,2 @@ +export * from "./UserChip"; +export { default } from "./UserChip"; diff --git a/src/components/VisibilityCard/VisibilityCard.tsx b/src/components/VisibilityCard/VisibilityCard.tsx index d75166fc8..4207baff5 100644 --- a/src/components/VisibilityCard/VisibilityCard.tsx +++ b/src/components/VisibilityCard/VisibilityCard.tsx @@ -3,18 +3,27 @@ import CardContent from "@material-ui/core/CardContent"; import { makeStyles } from "@material-ui/core/styles"; import TextField from "@material-ui/core/TextField"; import Typography from "@material-ui/core/Typography"; -import React from "react"; -import { useIntl } from "react-intl"; - import CardTitle from "@saleor/components/CardTitle"; +import ControlledCheckbox from "@saleor/components/ControlledCheckbox"; +import Hr from "@saleor/components/Hr"; import RadioSwitchField from "@saleor/components/RadioSwitchField"; +import useDateLocalize from "@saleor/hooks/useDateLocalize"; +import { ChangeEvent } from "@saleor/hooks/useForm"; import { UserError } from "@saleor/types"; import { getFieldError } from "@saleor/utils/errors"; +import classNames from "classnames"; +import React, { useState } from "react"; +import { useIntl } from "react-intl"; + import { DateContext } from "../Date/DateContext"; import FormSpacer from "../FormSpacer"; const useStyles = makeStyles( theme => ({ + checkbox: { + alignItems: "flex-start", + marginTop: 10 + }, children: { "& button": { margin: "0 9px" @@ -30,65 +39,92 @@ const useStyles = makeStyles( marginTop: theme.spacing(3) }, label: { - lineHeight: 1, - margin: 0 + lineHeight: 1.2, + marginBottom: 5, + marginTop: 0 + }, + listingLabel: { + marginTop: 9 }, secondLabel: { + color: theme.palette.text.hint, fontSize: 12 }, setPublicationDate: { color: theme.palette.primary.main, cursor: "pointer", - fontSize: "14px", - paddingTop: "15px", - textDecoration: "underline" + fontSize: 14, + paddingBottom: 10, + paddingTop: 0 } }), { name: "VisibilityCard" } ); -interface VisibilityCardProps { +interface Message { + visibleLabel: string; + hiddenLabel: string; + visibleSecondLabel?: string; + hiddenSecondLabel: string; + availableLabel?: string; + unavailableLabel?: string; + availableSecondLabel?: string; + setAvailabilityDateLabel?: string; +} +export interface VisibilityCardProps { children?: React.ReactNode | React.ReactNodeArray; data: { + availableForPurchase?: string; + isAvailableForPurchase?: boolean; isPublished: boolean; publicationDate: string; + visibleInListings?: boolean; }; errors: UserError[]; disabled?: boolean; - hiddenMessage: string; - onChange: (event: React.ChangeEvent) => void; - visibleMessage: string; + messages: Message; + onChange: (event: ChangeEvent) => void; } export const VisibilityCard: React.FC = props => { const { children, - data: { isPublished, publicationDate }, + data: { + availableForPurchase, + isAvailableForPurchase: isAvailable, + isPublished, + publicationDate, + visibleInListings + }, errors, disabled, - hiddenMessage, - onChange, - visibleMessage + messages, + onChange } = props; const classes = useStyles(props); - const intl = useIntl(); - const [isPublicationDate, setPublicationDate] = React.useState( + const localizeDate = useDateLocalize(); + const dateNow = React.useContext(DateContext); + const hasAvailableProps = + isAvailable !== undefined && availableForPurchase !== undefined; + + const [isPublicationDate, setPublicationDate] = useState( publicationDate === null ? true : false ); - const dateNow = React.useContext(DateContext); - const visibleSecondLabel = publicationDate - ? isPublished - ? visibleMessage - : null - : null; - const hiddenSecondLabel = publicationDate - ? isPublished - ? null - : Date.parse(publicationDate) > dateNow - ? hiddenMessage - : null - : null; + const [isAvailableDate, setAvailableDate] = useState( + availableForPurchase === null ? true : false + ); + + const visibleMessage = (date: string) => + intl.formatMessage( + { + defaultMessage: "since {date}", + description: "date" + }, + { + date: localizeDate(date, "L") + } + ); return ( @@ -104,23 +140,28 @@ export const VisibilityCard: React.FC = props => { error={!!getFieldError(errors, "isPublished")} firstOptionLabel={ <> -

- {intl.formatMessage({ - defaultMessage: "Visible" - })} -

- {visibleSecondLabel} +

{messages.visibleLabel}

+ {isPublished && + publicationDate && + Date.parse(publicationDate) < dateNow && ( + + {messages.visibleSecondLabel || + visibleMessage(publicationDate)} + + )} } name={"isPublished" as keyof FormData} secondOptionLabel={ <> -

- {intl.formatMessage({ - defaultMessage: "Hidden" - })} -

- {hiddenSecondLabel} +

{messages.hiddenLabel}

+ {publicationDate && + !isPublished && + Date.parse(publicationDate) >= dateNow && ( + + {messages.hiddenSecondLabel} + + )} } value={isPublished} @@ -128,16 +169,14 @@ export const VisibilityCard: React.FC = props => { /> {!isPublished && ( <> - {!isPublished && ( - setPublicationDate(!isPublicationDate)} - > - {intl.formatMessage({ - defaultMessage: "Set publication date" - })} - - )} + setPublicationDate(!isPublicationDate)} + > + {intl.formatMessage({ + defaultMessage: "Set publication date" + })} + {isPublicationDate && ( = props => { )} + {hasAvailableProps && ( + <> +
+ +

{messages.availableLabel}

+ {isAvailable && + availableForPurchase && + Date.parse(availableForPurchase) < dateNow && ( + + {visibleMessage(availableForPurchase)} + + )} + + } + name={"isAvailableForPurchase" as keyof FormData} + secondOptionLabel={ + <> +

{messages.unavailableLabel}

+ {availableForPurchase && !isAvailable && ( + + {messages.availableSecondLabel} + + )} + + } + value={isAvailable} + onChange={e => { + const { value } = e.target; + if (!value) { + onChange({ + target: { name: "availableForPurchase", value: null } + }); + } + return onChange(e); + }} + /> + {!isAvailable && ( + <> + setAvailableDate(!isAvailable)} + > + {messages.setAvailabilityDateLabel} + + {isAvailableDate && ( + + )} + + )} + {getFieldError(errors, "isAvailableForPurchase") && ( + <> + + + {getFieldError(errors, "isAvailableForPurchase")?.message} + + + )} + + )} + {visibleInListings !== undefined && ( + <> +
+ +

+ {intl.formatMessage({ + defaultMessage: "Show in product listings" + })} +

+ + + {intl.formatMessage({ + defaultMessage: + "Disabling this checkbox will remove product from search and category pages. It will be available on collection pages." + })} + + + } + onChange={onChange} + /> + + )}
{children}
diff --git a/src/components/WindowTitle/index.tsx b/src/components/WindowTitle/index.tsx index e68c41ba0..12f3a1041 100644 --- a/src/components/WindowTitle/index.tsx +++ b/src/components/WindowTitle/index.tsx @@ -1,8 +1,7 @@ +import useShop from "@saleor/hooks/useShop"; import React from "react"; import { Helmet } from "react-helmet"; -import useShop from "@saleor/hooks/useShop"; - interface WindowTitleProps { title: string; } diff --git a/src/components/messages/Container.tsx b/src/components/messages/Container.tsx new file mode 100644 index 000000000..c45cece2c --- /dev/null +++ b/src/components/messages/Container.tsx @@ -0,0 +1,12 @@ +import React from "react"; + +import { useStyles } from "./styles"; + +const Container = ({ children }) => { + const classes = useStyles({}); + return ( + !!children.length &&
{children}
+ ); +}; + +export default Container; diff --git a/src/components/messages/MessageManager.tsx b/src/components/messages/MessageManager.tsx index cbc604c71..fd2953607 100644 --- a/src/components/messages/MessageManager.tsx +++ b/src/components/messages/MessageManager.tsx @@ -1,117 +1,155 @@ import Button from "@material-ui/core/Button"; import IconButton from "@material-ui/core/IconButton"; -import Snackbar from "@material-ui/core/Snackbar"; +import SnackbarContent from "@material-ui/core/SnackbarContent"; import Typography from "@material-ui/core/Typography"; import CloseIcon from "@material-ui/icons/Close"; -import React from "react"; +import classNames from "classnames"; +import React, { useState } from "react"; +import { FormattedMessage } from "react-intl"; -import { IMessage, MessageContext } from "./"; +import { INotification } from "./"; +import { useStyles } from "./styles"; -interface Message extends IMessage { - key: string; -} -interface MessageManagerState { - message: Message; - opened: boolean; +export interface IMessageManagerProps extends INotification { + onMouseEnter?: () => void; + onMouseLeave?: () => void; } -export class MessageManager extends React.Component<{}, MessageManagerState> { - state: MessageManagerState = { - message: { key: "0", onUndo: undefined, text: "" }, - opened: false - }; - queue = []; +export const MessageManagerTemplate: React.FC = props => { + const { + close, + onMouseEnter, + onMouseLeave, + message: { actionBtn, expandText, status = "info", title, text, onUndo }, + timeout + } = props; - handleClose = (_, reason) => { - if (reason === "clickaway") { - return; - } - this.setState({ opened: false }); - }; + const [expand, setExpand] = useState(false); - handleExited = () => { - this.processQueue(); - }; + const classes = useStyles({}); + const id = props.id.toString(); - pushMessage = (message: IMessage) => { - this.queue.push({ - key: new Date().getTime(), - ...message - }); - - if (this.state.opened) { - this.setState({ opened: false }); - } else { - this.processQueue(); - } - }; - - processQueue = () => { - if (this.queue.length > 0) { - this.setState({ - message: this.queue.shift(), - opened: true - }); - } - }; - - render() { - const { autohide = 3000, title, text, key, onUndo } = this.state.message; - return ( - <> - - {title && ( - - {title} - - )} + return ( +
+ + {title && ( + + {title} + + )} + {text} - - } - title={title} - action={[ - !!onUndo ? ( + + + } + action={[ + !!expandText ? ( +
+
+

{expandText}

+
+ +
+ ) : ( + undefined + ), +
+ {!!onUndo && ( - ) : ( - undefined - ), - - - - ]} - /> - - {this.props.children} - - - ); - } -} -export default MessageManager; + )} + {!!actionBtn && ( + + )} +
, + + + , +
+
+
+ ]} + /> +
+ ); +}; diff --git a/src/components/messages/MessageManagerProvider.tsx b/src/components/messages/MessageManagerProvider.tsx new file mode 100644 index 000000000..4f20b8af3 --- /dev/null +++ b/src/components/messages/MessageManagerProvider.tsx @@ -0,0 +1,130 @@ +import React, { useCallback, useEffect, useRef, useState } from "react"; +import { createPortal } from "react-dom"; +import { TransitionGroup } from "react-transition-group"; + +import { + INotification, + ITimer, + MessageContext, + MessageManagerTemplate +} from "."; +import Container from "./Container"; +import Transition from "./Transition"; + +const MessageManagerProvider = ({ children }) => { + const root = useRef(null); + const timersArr = useRef([]); + const [notifications, setNotifications] = useState([]); + + useEffect(() => { + root.current = document.createElement("div"); + root.current.id = "__message-manager__"; + document.body.appendChild(root.current); + const timersArrRef = timersArr.current; + + return () => { + timersArrRef.forEach(timer => clearTimeout(timer.timeoutId)); + if (root.current) { + document.body.removeChild(root.current); + } + }; + }, []); + + const timerCallback = (notification: INotification) => { + remove(notification.id); + timersArr.current = timersArr.current.filter( + timer => timer.id !== notification.id + ); + }; + + const remove = useCallback(notificationId => { + setNotifications(currentNotifications => + currentNotifications.filter(n => n.id !== notificationId) + ); + }, []); + + const show = useCallback((message = {}, timeout = 3000) => { + const id = Date.now(); + const notification = { + close: () => remove(id), + id, + message, + timeout + }; + if (timeout !== null) { + const timeoutId = window.setTimeout(() => { + timerCallback(notification); + }, timeout); + + timersArr.current.push({ + id: notification.id, + notification, + remaining: timeout, + start: new Date().getTime(), + timeoutId + }); + } + + setNotifications(state => [notification, ...state]); + + return notification; + }, []); + + const getCurrentTimer = (notification: INotification) => { + const currentTimerIndex = timersArr.current.findIndex( + timer => timer.id === notification.id + ); + return timersArr.current[currentTimerIndex]; + }; + + const pauseTimer = (notification: INotification) => { + const currentTimer = getCurrentTimer(notification); + if (currentTimer) { + currentTimer.remaining = + currentTimer.remaining - (new Date().getTime() - currentTimer.start); + window.clearTimeout(currentTimer.timeoutId); + } + }; + const resumeTimer = (notification: INotification) => { + const currentTimer = getCurrentTimer(notification); + if (currentTimer) { + currentTimer.start = new Date().getTime(); + currentTimer.timeoutId = window.setTimeout( + () => timerCallback(notification), + currentTimer.remaining + ); + } + }; + + return ( + + {children} + {root.current && + createPortal( + + {!!notifications.length && + notifications.map(notification => ( + + pauseTimer(notification), + onMouseLeave: () => resumeTimer(notification) + } + : {})} + /> + + ))} + , + root.current + )} + + ); +}; + +export default MessageManagerProvider; diff --git a/src/components/messages/Transition.tsx b/src/components/messages/Transition.tsx new file mode 100644 index 000000000..e14c12483 --- /dev/null +++ b/src/components/messages/Transition.tsx @@ -0,0 +1,31 @@ +import React from "react"; +import { Transition as MessageManagerTransition } from "react-transition-group"; + +const duration = 250; + +const defaultStyle = { + opacity: 0, + transition: `opacity ${duration}ms ease` +}; + +const transitionStyles = { + entered: { opacity: 1 }, + entering: { opacity: 0 } +}; + +const Transition = ({ children, ...props }) => ( + + {state => ( +
+ {children} +
+ )} +
+); + +export default Transition; diff --git a/src/components/messages/index.ts b/src/components/messages/index.ts index 95424f09f..f2e574ae3 100644 --- a/src/components/messages/index.ts +++ b/src/components/messages/index.ts @@ -1,13 +1,48 @@ import { createContext } from "react"; +export type Status = "success" | "error" | "info" | "warning"; export interface IMessage { + actionBtn?: { + label: string; + action: () => void; + }; autohide?: number; + expandText?: string; title?: string; - text: string; + text: React.ReactNode; onUndo?: () => void; + status?: Status; } + +export interface INotification { + id: number; + message: IMessage; + timeout: number; + close: () => void; +} + +export interface ITimer { + id: number; + notification: INotification; + remaining: number; + start: number; + timeoutId: number; +} + +export const types = { + ERROR: "error", + INFO: "info", + SUCCESS: "success", + WARNING: "warning" +}; +export interface INotificationContext { + show: (message: IMessage, timeout?: number | null) => void; + remove: (notification: INotification) => void; +} + export type IMessageContext = (message: IMessage) => void; -export const MessageContext = createContext(undefined); +export const MessageContext = createContext(null); export * from "./MessageManager"; -export default MessageContext.Consumer; +export * from "./MessageManagerProvider"; +export { default } from "./MessageManagerProvider"; diff --git a/src/components/messages/styles.ts b/src/components/messages/styles.ts new file mode 100644 index 000000000..d462a93b7 --- /dev/null +++ b/src/components/messages/styles.ts @@ -0,0 +1,213 @@ +import errorIcon from "@assets/images/error-icon.svg"; +import infoIcon from "@assets/images/info-icon.svg"; +import successIcon from "@assets/images/success-icon.svg"; +import warningIcon from "@assets/images/warning-icon.svg"; +import { makeStyles } from "@material-ui/core/styles"; +import { darken } from "@material-ui/core/styles/colorManipulator"; + +const successColor = "#60DAA0"; +const warningColor = "#FFB84E"; +const infoColor = "#CAD8DF"; +const errorColor = "#FE6E76"; + +export const useStyles = makeStyles( + theme => ({ + "@keyframes bar": { + from: { transform: "translateX(-100%)" }, + to: { transform: "translateX(0)" } + }, + actionContainer: { + marginLeft: -8 + }, + closeBtn: { + "& svg": { + maxHeight: 18, + maxWidth: 18 + }, + color: "#fff", + padding: 10, + position: "absolute", + right: 5, + top: 7 + }, + closeBtnInfo: { + color: theme.palette.text.primary + }, + container: { + display: "grid", + gridTemplateRows: "repeat(auto-fill, minmax(90px, 1fr))", + justifyContent: "end", + left: 0, + pointerEvents: "none", + position: "fixed", + top: 0, + width: "100%", + zIndex: 1200 + }, + error: { + "& > div": { + "& button span": { + color: "#fff" + } + }, + "& > div:first-child": { + "&:before": { + backgroundImage: `url(${errorIcon})` + } + }, + backgroundColor: errorColor, + color: "#fff" + }, + expandBtn: { + "&:before": { + borderLeft: "4px solid transparent", + borderRight: "4px solid transparent", + borderTop: "8px solid #fff", + content: "''", + display: "block", + height: 0, + position: "absolute", + right: 0, + top: "50%", + transform: "translateY(-50%)", + width: 0 + }, + background: "transparent", + border: "none", + color: "#fff", + cursor: "pointer", + fontSize: theme.spacing(2), + outline: "none", + padding: 0, + paddingRight: 15, + position: "relative" + }, + expandBtnInfo: { + "&:before": { + borderTop: `8px solid ${theme.palette.text.primary}` + }, + color: theme.palette.text.primary + }, + expandedContainer: { + "& p": { + margin: theme.spacing(1, 0) + }, + color: "#fff", + marginBottom: 5 + }, + expandedContainerContent: { + overflow: "hidden", + transition: "max-height .6s ease" + }, + expandedContainerInfo: { + color: theme.palette.text.secondary + }, + expandedText: { + maxHeight: 500 + }, + hiddenText: { + maxHeight: 0 + }, + info: { + "& > div:first-child": { + "&:before": { + backgroundImage: `url(${infoIcon})` + } + } + }, + progressBar: { + animation: `$bar var(--animationTime) ease both`, + backgroundColor: infoColor, + height: 8, + transform: "translateX(-100%)", + width: "100%" + }, + progressBarContainer: { + borderRadius: "0 0 4px 4px", + bottom: 0, + left: 0, + overflow: "hidden", + position: "absolute", + width: "calc(100%)" + }, + progressBarError: { + backgroundColor: darken(errorColor, 0.2) + }, + progressBarSuccess: { + backgroundColor: darken(successColor, 0.2) + }, + progressBarWarning: { + backgroundColor: darken(warningColor, 0.2) + }, + snackbar: { + "& > div": { + paddingLeft: 60 + }, + "& > div:first-child": { + "&:before": { + backgroundRepeat: "no-repeat", + backgroundSize: "contain", + content: "''", + display: "block", + height: 32, + left: 15, + position: "absolute", + top: 13, + width: 32 + }, + paddingTop: 16, + position: "relative" + }, + "&:hover": { + "& [class*='progressBar']": { + animationPlayState: "paused" + } + }, + borderRadius: 4, + paddingBottom: 15, + paddingLeft: 5, + paddingRight: 45, + position: "relative" + }, + snackbarContainer: { + borderRadius: 4, + display: "block", + margin: theme.spacing(2, 2, 0, 2), + maxWidth: 450, + pointerEvents: "all", + position: "relative" + }, + success: { + "& > div:first-child": { + "&:before": { + backgroundImage: `url(${successIcon})` + } + }, + "& button span": { + color: "#fff" + }, + backgroundColor: successColor, + color: "#fff" + }, + text: { + color: "#fff", + paddingTop: 5 + }, + textInfo: { + paddingTop: 5 + }, + warning: { + "& > div:first-child": { + "&:before": { + backgroundImage: `url(${warningIcon})` + } + }, + "& button span": { + color: "#fff" + }, + backgroundColor: warningColor, + color: "#fff" + } + }), + { name: "MessageManager" } +); diff --git a/src/config.ts b/src/config.ts index 90b81e7c8..7a9e4ef0c 100644 --- a/src/config.ts +++ b/src/config.ts @@ -2,7 +2,7 @@ import packageInfo from "../package.json"; import { SearchVariables } from "./hooks/makeSearch"; import { ListSettings, ListViews, Pagination } from "./types"; -export const APP_MOUNT_URI = process.env.APP_MOUNT_URI || "/"; +export const APP_MOUNT_URI = process.env.APP_MOUNT_URI; export const API_URI = process.env.API_URI; export const DEFAULT_INITIAL_SEARCH_DATA: SearchVariables = { @@ -20,6 +20,7 @@ export const PAGINATE_BY = 20; export type ProductListColumns = "productType" | "isPublished" | "price"; export interface AppListViewSettings { + [ListViews.APPS_LIST]: ListSettings; [ListViews.CATEGORY_LIST]: ListSettings; [ListViews.COLLECTION_LIST]: ListSettings; [ListViews.CUSTOMER_LIST]: ListSettings; @@ -38,6 +39,9 @@ export interface AppListViewSettings { [ListViews.WEBHOOK_LIST]: ListSettings; } export const defaultListSettings: AppListViewSettings = { + [ListViews.APPS_LIST]: { + rowNumber: 10 + }, [ListViews.CATEGORY_LIST]: { rowNumber: PAGINATE_BY }, @@ -90,3 +94,5 @@ export const defaultListSettings: AppListViewSettings = { }; export const APP_VERSION = packageInfo.version; +export const DEMO_MODE = process.env.DEMO_MODE === "true"; +export const GTM_ID = process.env.GTM_ID; diff --git a/src/configuration/ConfigurationPage.tsx b/src/configuration/ConfigurationPage.tsx index fcdc547c4..271a08eca 100644 --- a/src/configuration/ConfigurationPage.tsx +++ b/src/configuration/ConfigurationPage.tsx @@ -1,14 +1,14 @@ import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; +import { IconProps } from "@material-ui/core/Icon"; import { makeStyles } from "@material-ui/core/styles"; import Typography from "@material-ui/core/Typography"; +import { User } from "@saleor/fragments/types/User"; +import { sectionNames } from "@saleor/intl"; import React from "react"; import { useIntl } from "react-intl"; -import { IconProps } from "@material-ui/core/Icon"; -import { sectionNames } from "@saleor/intl"; import { hasPermission } from "../auth/misc"; -import { User } from "../auth/types/User"; import Container from "../components/Container"; import PageHeader from "../components/PageHeader"; import { PermissionEnum } from "../types/globalTypes"; @@ -126,6 +126,8 @@ export const ConfigurationPage: React.FC = props => { className={item.url ? classes.card : classes.cardDisabled} onClick={() => onSectionClick(item.url)} key={itemIndex} + data-test="settingsSubsection" + data-test-id={item.title.toLowerCase()} >
{item.icon}
diff --git a/src/configuration/index.tsx b/src/configuration/index.tsx index 82cc16c98..9b434deab 100644 --- a/src/configuration/index.tsx +++ b/src/configuration/index.tsx @@ -1,45 +1,41 @@ -import React from "react"; -import { IntlShape, useIntl } from "react-intl"; - import { attributeListUrl } from "@saleor/attributes/urls"; import { WindowTitle } from "@saleor/components/WindowTitle"; import useNavigator from "@saleor/hooks/useNavigator"; import useUser from "@saleor/hooks/useUser"; import Attributes from "@saleor/icons/Attributes"; -import Bot from "@saleor/icons/Bot"; import Navigation from "@saleor/icons/Navigation"; import Pages from "@saleor/icons/Pages"; +import PermissionGroups from "@saleor/icons/PermissionGroups"; import Plugins from "@saleor/icons/Plugins"; import ProductTypes from "@saleor/icons/ProductTypes"; import ShippingMethods from "@saleor/icons/ShippingMethods"; import SiteSettings from "@saleor/icons/SiteSettings"; import StaffMembers from "@saleor/icons/StaffMembers"; -import PermissionGroups from "@saleor/icons/PermissionGroups"; import Taxes from "@saleor/icons/Taxes"; -import Webhooks from "@saleor/icons/Webhooks"; +import Warehouses from "@saleor/icons/Warehouses"; import { sectionNames } from "@saleor/intl"; import { maybe } from "@saleor/misc"; import { menuListUrl } from "@saleor/navigation/urls"; import { pageListUrl } from "@saleor/pages/urls"; +import { permissionGroupListUrl } from "@saleor/permissionGroups/urls"; import { pluginListUrl } from "@saleor/plugins/urls"; import { productTypeListUrl } from "@saleor/productTypes/urls"; -import { serviceListUrl } from "@saleor/services/urls"; import { shippingZonesListUrl } from "@saleor/shipping/urls"; import { siteSettingsUrl } from "@saleor/siteSettings/urls"; import { staffListUrl } from "@saleor/staff/urls"; -import { permissionGroupListUrl } from "@saleor/permissionGroups/urls"; import { taxSection } from "@saleor/taxes/urls"; import { PermissionEnum } from "@saleor/types/globalTypes"; -import { webhookListUrl } from "@saleor/webhooks/urls"; -import Warehouses from "@saleor/icons/Warehouses"; import { warehouseSection } from "@saleor/warehouses/urls"; +import React from "react"; +import { IntlShape, useIntl } from "react-intl"; + import ConfigurationPage, { MenuSection } from "./ConfigurationPage"; export function createConfigurationMenu(intl: IntlShape): MenuSection[] { return [ { label: intl.formatMessage({ - defaultMessage: "Attributes and Product Typess" + defaultMessage: "Attributes and Product Types" }), menuItems: [ { @@ -186,24 +182,6 @@ export function createConfigurationMenu(intl: IntlShape): MenuSection[] { permission: PermissionEnum.MANAGE_PLUGINS, title: intl.formatMessage(sectionNames.plugins), url: pluginListUrl() - }, - { - description: intl.formatMessage({ - defaultMessage: "Manage external integrations accounts" - }), - icon: , - permission: PermissionEnum.MANAGE_APPS, - title: intl.formatMessage(sectionNames.serviceAccounts), - url: serviceListUrl() - }, - { - description: intl.formatMessage({ - defaultMessage: "View and update your webhook and their settings" - }), - icon: , - permission: PermissionEnum.MANAGE_WEBHOOKS, - title: intl.formatMessage(sectionNames.webhooks), - url: webhookListUrl() } ] } diff --git a/src/containers/BackgroundTasks/BackgroundTasksProvider.test.tsx b/src/containers/BackgroundTasks/BackgroundTasksProvider.test.tsx new file mode 100644 index 000000000..8c5e46fa3 --- /dev/null +++ b/src/containers/BackgroundTasks/BackgroundTasksProvider.test.tsx @@ -0,0 +1,179 @@ +import { JobStatusEnum } from "@saleor/types/globalTypes"; +import { renderHook } from "@testing-library/react-hooks"; +import { createMockClient, RequestHandlerResponse } from "mock-apollo-client"; + +import { + backgroundTasksRefreshTime, + useBackgroundTasks +} from "./BackgroundTasksProvider"; +import { checkExportFileStatus } from "./queries"; +import { Task, TaskData, TaskStatus } from "./types"; +import { CheckExportFileStatus } from "./types/CheckExportFileStatus"; + +jest.useFakeTimers(); + +function renderBackgroundTasks() { + const mockClient = createMockClient(); + mockClient.setRequestHandler(checkExportFileStatus, () => + Promise.resolve>({ + data: { + exportFile: { + __typename: "ExportFile", + id: "123", + status: JobStatusEnum.SUCCESS + } + } + }) + ); + const intl = { + formatMessage: ({ defaultMessage }) => defaultMessage + }; + + return renderHook(() => + useBackgroundTasks(mockClient, jest.fn(), intl as any) + ); +} + +describe("Background task provider", () => { + it("can queue a task", done => { + const handle = jest.fn, []>( + () => new Promise(resolve => resolve(TaskStatus.SUCCESS)) + ); + const onCompleted = jest.fn(); + const onError = jest.fn(); + + const { result } = renderBackgroundTasks(); + + const taskId = result.current.queue(Task.CUSTOM, { + handle, + onCompleted, + onError + }); + expect(taskId).toBe(1); + expect(handle).toHaveBeenCalledTimes(0); + expect(onCompleted).toHaveBeenCalledTimes(0); + expect(onError).toHaveBeenCalledTimes(0); + + jest.runOnlyPendingTimers(); + + setImmediate(() => { + expect(handle).toHaveBeenCalledTimes(1); + expect(onCompleted).toHaveBeenCalledTimes(1); + expect(onError).toHaveBeenCalledTimes(0); + + done(); + }); + }); + + it("can handle task error", done => { + const handle = jest.fn, []>( + () => + new Promise(() => { + throw new Error("dummy error"); + }) + ); + const onCompleted = jest.fn(); + const onError = jest.fn(); + + const { result } = renderBackgroundTasks(); + + result.current.queue(Task.CUSTOM, { + handle, + onCompleted, + onError + }); + + jest.runOnlyPendingTimers(); + + setImmediate(() => { + expect(handle).toHaveBeenCalledTimes(1); + expect(onCompleted).toHaveBeenCalledTimes(0); + expect(onError).toHaveBeenCalledTimes(1); + + done(); + }); + }); + + it("can cancel task", done => { + const onCompleted = jest.fn(); + + const { result } = renderBackgroundTasks(); + + const taskId = result.current.queue(Task.CUSTOM, { + handle: () => new Promise(resolve => resolve(TaskStatus.SUCCESS)), + onCompleted + }); + + // Cancel task before executing it + jest.advanceTimersByTime(backgroundTasksRefreshTime * 0.9); + result.current.cancel(taskId); + + jest.runOnlyPendingTimers(); + + setImmediate(() => { + expect(onCompleted).toHaveBeenCalledTimes(0); + + done(); + }); + }); + + it("can queue multiple tasks", done => { + let cycle = 0; + + // Completed in two cycles + const shortTask = { + handle: jest.fn(() => + Promise.resolve(cycle > 1 ? TaskStatus.SUCCESS : TaskStatus.PENDING) + ), + onCompleted: jest.fn() + }; + + // Completed in three cycles + const longTask = { + handle: jest.fn(() => + Promise.resolve(cycle > 2 ? TaskStatus.SUCCESS : TaskStatus.PENDING) + ), + onCompleted: jest.fn() + }; + const tasks: TaskData[] = [shortTask, longTask]; + + const { result } = renderBackgroundTasks(); + + tasks.forEach(task => result.current.queue(Task.CUSTOM, task)); + + // Set time to backgroundTasksRefreshTime + cycle += 1; + jest.advanceTimersByTime(backgroundTasksRefreshTime + 100); + + setImmediate(() => { + expect(shortTask.handle).toHaveBeenCalledTimes(1); + expect(longTask.handle).toHaveBeenCalledTimes(1); + expect(shortTask.onCompleted).toHaveBeenCalledTimes(0); + expect(longTask.onCompleted).toHaveBeenCalledTimes(0); + + // Set time to backgroundTasksRefreshTime * 2 + cycle += 1; + jest.advanceTimersByTime(backgroundTasksRefreshTime); + + setImmediate(() => { + expect(shortTask.handle).toHaveBeenCalledTimes(2); + expect(longTask.handle).toHaveBeenCalledTimes(2); + expect(shortTask.onCompleted).toHaveBeenCalledTimes(1); + expect(longTask.onCompleted).toHaveBeenCalledTimes(0); + + // Set time to backgroundTasksRefreshTime * 3 + cycle += 1; + jest.advanceTimersByTime(backgroundTasksRefreshTime); + + setImmediate(() => { + expect(shortTask.handle).toHaveBeenCalledTimes(2); + expect(longTask.handle).toHaveBeenCalledTimes(3); + expect(shortTask.onCompleted).toHaveBeenCalledTimes(1); + expect(longTask.onCompleted).toHaveBeenCalledTimes(1); + + done(); + }); + }); + }); + }); +}); diff --git a/src/containers/BackgroundTasks/BackgroundTasksProvider.tsx b/src/containers/BackgroundTasks/BackgroundTasksProvider.tsx new file mode 100644 index 000000000..b9ec40fe2 --- /dev/null +++ b/src/containers/BackgroundTasks/BackgroundTasksProvider.tsx @@ -0,0 +1,135 @@ +import { IMessageContext } from "@saleor/components/messages"; +import useNotifier from "@saleor/hooks/useNotifier"; +import ApolloClient from "apollo-client"; +import React from "react"; +import { useApolloClient } from "react-apollo"; +import { IntlShape, useIntl } from "react-intl"; + +import BackgroundTasksContext from "./context"; +import { checkExportFileStatus, checkOrderInvoicesStatus } from "./queries"; +import { + handleTask, + queueCustom, + queueExport, + queueInvoiceGenerate +} from "./tasks"; +import { QueuedTask, Task, TaskData, TaskStatus } from "./types"; + +export const backgroundTasksRefreshTime = 15 * 1000; + +export function useBackgroundTasks( + apolloClient: ApolloClient, + notify: IMessageContext, + intl: IntlShape +) { + const idCounter = React.useRef(0); + const tasks = React.useRef([]); + + React.useEffect(() => { + const intervalId = setInterval(() => { + const queue = async () => { + try { + await Promise.all( + tasks.current.map(async task => { + if (task.status === TaskStatus.PENDING) { + let status: TaskStatus; + + try { + status = await handleTask(task); + } catch (error) { + throw error; + } + if (status !== TaskStatus.PENDING) { + const taskIndex = tasks.current.findIndex( + t => t.id === task.id + ); + tasks.current[taskIndex].status = status; + } + } + }) + ); + } catch (error) { + throw error; + } + }; + + queue(); + }, backgroundTasksRefreshTime); + + return () => clearInterval(intervalId); + }); + + function cancel(id: number) { + tasks.current = tasks.current.filter(task => task.id !== id); + } + + function queue(type: Task, data?: TaskData) { + idCounter.current += 1; + switch (type) { + case Task.CUSTOM: + queueCustom(idCounter.current, tasks, data); + break; + case Task.INVOICE_GENERATE: + queueInvoiceGenerate( + idCounter.current, + data.generateInvoice, + tasks, + () => + apolloClient.query({ + fetchPolicy: "network-only", + query: checkOrderInvoicesStatus, + variables: { + id: data.generateInvoice.orderId + } + }), + notify, + intl + ); + break; + case Task.EXPORT: + queueExport( + idCounter.current, + tasks, + () => + apolloClient.query({ + fetchPolicy: "network-only", + query: checkExportFileStatus, + variables: { + id: data.id + } + }), + notify, + intl + ); + break; + } + + return idCounter.current; + } + + return { + cancel, + queue + }; +} + +const BackgroundTasksProvider: React.FC = ({ children }) => { + const apolloClient = useApolloClient(); + const notify = useNotifier(); + const intl = useIntl(); + const { cancel, queue } = useBackgroundTasks(apolloClient, notify, intl); + + return ( + + {children} + + ); +}; + +BackgroundTasksProvider.displayName = "BackgroundTasksProvider"; +export default BackgroundTasksProvider; diff --git a/src/containers/BackgroundTasks/context.ts b/src/containers/BackgroundTasks/context.ts new file mode 100644 index 000000000..13f49e3ba --- /dev/null +++ b/src/containers/BackgroundTasks/context.ts @@ -0,0 +1,7 @@ +import { createContext } from "react"; + +import { BackgroundTasksContextType } from "./types"; + +const BackgroundTasksContext = createContext(null); + +export default BackgroundTasksContext; diff --git a/src/containers/BackgroundTasks/index.ts b/src/containers/BackgroundTasks/index.ts new file mode 100644 index 000000000..3525dcf82 --- /dev/null +++ b/src/containers/BackgroundTasks/index.ts @@ -0,0 +1,2 @@ +export * from "./BackgroundTasksProvider"; +export { default } from "./BackgroundTasksProvider"; diff --git a/src/containers/BackgroundTasks/messages.ts b/src/containers/BackgroundTasks/messages.ts new file mode 100644 index 000000000..6b7ab069c --- /dev/null +++ b/src/containers/BackgroundTasks/messages.ts @@ -0,0 +1,27 @@ +import { defineMessages } from "react-intl"; + +export default defineMessages({ + exportFailedTitle: { + defaultMessage: "Product Export Failed" + }, + exportFinishedText: { + defaultMessage: + "Product export has finished and was sent to your email address." + }, + exportFinishedTitle: { + defaultMessage: "Exporting CSV finished", + description: "csv file exporting has finished, header" + }, + invoiceGenerateFinishedText: { + defaultMessage: + "Requested Invoice was generated. It was added to the top of the invoice list on this view. Enjoy!" + }, + invoiceGenerateFinishedTitle: { + defaultMessage: "Invoice Generated", + description: "invoice generating has finished, header" + }, + invoiceGenerationFailedTitle: { + defaultMessage: "Invoice Generation", + description: "dialog header, title" + } +}); diff --git a/src/containers/BackgroundTasks/queries.ts b/src/containers/BackgroundTasks/queries.ts new file mode 100644 index 000000000..c34f04d04 --- /dev/null +++ b/src/containers/BackgroundTasks/queries.ts @@ -0,0 +1,23 @@ +import { invoiceFragment } from "@saleor/fragments/orders"; +import gql from "graphql-tag"; + +export const checkExportFileStatus = gql` + query CheckExportFileStatus($id: ID!) { + exportFile(id: $id) { + id + status + } + } +`; + +export const checkOrderInvoicesStatus = gql` + ${invoiceFragment} + query CheckOrderInvoicesStatus($id: ID!) { + order(id: $id) { + id + invoices { + ...InvoiceFragment + } + } + } +`; diff --git a/src/containers/BackgroundTasks/tasks.ts b/src/containers/BackgroundTasks/tasks.ts new file mode 100644 index 000000000..fb506ffd7 --- /dev/null +++ b/src/containers/BackgroundTasks/tasks.ts @@ -0,0 +1,144 @@ +import { IMessageContext } from "@saleor/components/messages"; +import { commonMessages } from "@saleor/intl"; +import { JobStatusEnum } from "@saleor/types/globalTypes"; +import { ApolloQueryResult } from "apollo-client"; +import { IntlShape } from "react-intl"; + +import messages from "./messages"; +import { + InvoiceGenerateParams, + QueuedTask, + TaskData, + TaskStatus +} from "./types"; +import { CheckExportFileStatus } from "./types/CheckExportFileStatus"; +import { CheckOrderInvoicesStatus } from "./types/CheckOrderInvoicesStatus"; + +function getTaskStatus(jobStatus: JobStatusEnum): TaskStatus { + switch (jobStatus) { + case JobStatusEnum.SUCCESS: + return TaskStatus.SUCCESS; + case JobStatusEnum.PENDING: + return TaskStatus.PENDING; + default: + return TaskStatus.FAILURE; + } +} + +export async function handleTask(task: QueuedTask): Promise { + let status = TaskStatus.PENDING; + try { + status = await task.handle(); + if (status !== TaskStatus.PENDING) { + task.onCompleted({ + status + }); + } + } catch (error) { + task.onError(error); + } + + return status; +} + +export function handleError(error: Error) { + throw error; +} + +export function queueCustom( + id: number, + tasks: React.MutableRefObject, + data: TaskData +) { + (["handle", "onCompleted"] as Array) + .filter(field => !data[field]) + .forEach(field => { + throw new Error(`${field} is required when creating custom task`); + }); + tasks.current = [ + ...tasks.current, + { + handle: data.handle, + id, + onCompleted: data.onCompleted, + onError: data.onError || handleError, + status: TaskStatus.PENDING + } + ]; +} + +export function queueInvoiceGenerate( + id: number, + generateInvoice: InvoiceGenerateParams, + tasks: React.MutableRefObject, + fetch: () => Promise>, + notify: IMessageContext, + intl: IntlShape +) { + if (!generateInvoice) { + throw new Error("generateInvoice is required when creating custom task"); + } + tasks.current = [ + ...tasks.current, + { + handle: async () => { + const result = await fetch(); + const status = result.data.order.invoices.find( + invoice => invoice.id === generateInvoice.invoiceId + ).status; + + return getTaskStatus(status); + }, + id, + onCompleted: data => + data.status === TaskStatus.SUCCESS + ? notify({ + status: "success", + text: intl.formatMessage(messages.invoiceGenerateFinishedText), + title: intl.formatMessage(messages.invoiceGenerateFinishedTitle) + }) + : notify({ + status: "error", + text: intl.formatMessage(commonMessages.somethingWentWrong), + title: intl.formatMessage(messages.invoiceGenerationFailedTitle) + }), + onError: handleError, + status: TaskStatus.PENDING + } + ]; +} + +export function queueExport( + id: number, + tasks: React.MutableRefObject, + fetch: () => Promise>, + notify: IMessageContext, + intl: IntlShape +) { + tasks.current = [ + ...tasks.current, + { + handle: async () => { + const result = await fetch(); + const status = result.data.exportFile.status; + + return getTaskStatus(status); + }, + id, + onCompleted: data => + data.status === TaskStatus.SUCCESS + ? notify({ + status: "success", + text: intl.formatMessage(messages.exportFinishedText), + title: intl.formatMessage(messages.exportFinishedTitle) + }) + : notify({ + status: "error", + text: intl.formatMessage(commonMessages.somethingWentWrong), + title: intl.formatMessage(messages.exportFailedTitle) + }), + onError: handleError, + status: TaskStatus.PENDING + } + ]; +} diff --git a/src/containers/BackgroundTasks/types.ts b/src/containers/BackgroundTasks/types.ts new file mode 100644 index 000000000..269fd3791 --- /dev/null +++ b/src/containers/BackgroundTasks/types.ts @@ -0,0 +1,40 @@ +export enum Task { + CUSTOM, + EXPORT, + INVOICE_GENERATE +} +export enum TaskStatus { + FAILURE, + PENDING, + SUCCESS +} +export interface InvoiceGenerateParams { + orderId: string; + invoiceId: string; +} + +export interface OnCompletedTaskData { + status: TaskStatus; +} +export type OnCompletedTaskFn = (data: OnCompletedTaskData) => void; + +export interface QueuedTask { + id: number; + handle: () => Promise; + status: TaskStatus; + onCompleted: OnCompletedTaskFn; + onError: (error: Error) => void; +} + +export interface TaskData { + generateInvoice?: InvoiceGenerateParams; + id?: string; + handle?: () => Promise; + onCompleted?: OnCompletedTaskFn; + onError?: () => void; +} + +export interface BackgroundTasksContextType { + cancel: (id: number) => void; + queue: (type: Task, data?: TaskData) => void; +} diff --git a/src/containers/BackgroundTasks/types/CheckExportFileStatus.ts b/src/containers/BackgroundTasks/types/CheckExportFileStatus.ts new file mode 100644 index 000000000..210e7e474 --- /dev/null +++ b/src/containers/BackgroundTasks/types/CheckExportFileStatus.ts @@ -0,0 +1,23 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { JobStatusEnum } from "./../../../types/globalTypes"; + +// ==================================================== +// GraphQL query operation: CheckExportFileStatus +// ==================================================== + +export interface CheckExportFileStatus_exportFile { + __typename: "ExportFile"; + id: string; + status: JobStatusEnum; +} + +export interface CheckExportFileStatus { + exportFile: CheckExportFileStatus_exportFile | null; +} + +export interface CheckExportFileStatusVariables { + id: string; +} diff --git a/src/containers/BackgroundTasks/types/CheckOrderInvoicesStatus.ts b/src/containers/BackgroundTasks/types/CheckOrderInvoicesStatus.ts new file mode 100644 index 000000000..848f69b04 --- /dev/null +++ b/src/containers/BackgroundTasks/types/CheckOrderInvoicesStatus.ts @@ -0,0 +1,32 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { JobStatusEnum } from "./../../../types/globalTypes"; + +// ==================================================== +// GraphQL query operation: CheckOrderInvoicesStatus +// ==================================================== + +export interface CheckOrderInvoicesStatus_order_invoices { + __typename: "Invoice"; + id: string; + number: string | null; + createdAt: any; + url: string | null; + status: JobStatusEnum; +} + +export interface CheckOrderInvoicesStatus_order { + __typename: "Order"; + id: string; + invoices: (CheckOrderInvoicesStatus_order_invoices | null)[] | null; +} + +export interface CheckOrderInvoicesStatus { + order: CheckOrderInvoicesStatus_order | null; +} + +export interface CheckOrderInvoicesStatusVariables { + id: string; +} diff --git a/src/customers/components/CustomerAddress/CustomerAddress.tsx b/src/customers/components/CustomerAddress/CustomerAddress.tsx index 59dfbe2f7..7a40c0988 100644 --- a/src/customers/components/CustomerAddress/CustomerAddress.tsx +++ b/src/customers/components/CustomerAddress/CustomerAddress.tsx @@ -3,14 +3,14 @@ import Card from "@material-ui/core/Card"; import CardActions from "@material-ui/core/CardActions"; import CardContent from "@material-ui/core/CardContent"; import { makeStyles } from "@material-ui/core/styles"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import AddressFormatter from "@saleor/components/AddressFormatter"; import CardMenu from "@saleor/components/CardMenu"; import CardTitle from "@saleor/components/CardTitle"; import Skeleton from "@saleor/components/Skeleton"; import { buttonMessages } from "@saleor/intl"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { AddressTypeEnum } from "../../../types/globalTypes"; import { CustomerAddresses_user_addresses } from "../../types/CustomerAddresses"; diff --git a/src/customers/components/CustomerAddressDialog/CustomerAddressDialog.tsx b/src/customers/components/CustomerAddressDialog/CustomerAddressDialog.tsx index 9a77a8a5d..f60e53dfd 100644 --- a/src/customers/components/CustomerAddressDialog/CustomerAddressDialog.tsx +++ b/src/customers/components/CustomerAddressDialog/CustomerAddressDialog.tsx @@ -3,15 +3,13 @@ import Dialog from "@material-ui/core/Dialog"; import DialogActions from "@material-ui/core/DialogActions"; import DialogContent from "@material-ui/core/DialogContent"; import DialogTitle from "@material-ui/core/DialogTitle"; -import { createStyles, withStyles, WithStyles } from "@material-ui/core/styles"; -import React from "react"; -import { FormattedMessage } from "react-intl"; - +import { createStyles, WithStyles, withStyles } from "@material-ui/core/styles"; import AddressEdit from "@saleor/components/AddressEdit"; import ConfirmButton, { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; import Form from "@saleor/components/Form"; +import { AccountErrorFragment } from "@saleor/fragments/types/AccountErrorFragment"; import useAddressValidation from "@saleor/hooks/useAddressValidation"; import useModalDialogErrors from "@saleor/hooks/useModalDialogErrors"; import useStateFromProps from "@saleor/hooks/useStateFromProps"; @@ -19,7 +17,9 @@ import { buttonMessages } from "@saleor/intl"; import { maybe } from "@saleor/misc"; import { AddressInput } from "@saleor/types/globalTypes"; import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler"; -import { AccountErrorFragment } from "@saleor/customers/types/AccountErrorFragment"; +import React from "react"; +import { FormattedMessage } from "react-intl"; + import { AddressTypeInput } from "../../types"; import { CustomerAddresses_user_addresses } from "../../types/CustomerAddresses"; diff --git a/src/customers/components/CustomerAddressListPage/CustomerAddressListPage.tsx b/src/customers/components/CustomerAddressListPage/CustomerAddressListPage.tsx index d823a8d0b..e63c49739 100644 --- a/src/customers/components/CustomerAddressListPage/CustomerAddressListPage.tsx +++ b/src/customers/components/CustomerAddressListPage/CustomerAddressListPage.tsx @@ -1,13 +1,12 @@ import Button from "@material-ui/core/Button"; import { makeStyles } from "@material-ui/core/styles"; import Typography from "@material-ui/core/Typography"; - -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import AppHeader from "@saleor/components/AppHeader"; import Container from "@saleor/components/Container"; import PageHeader from "@saleor/components/PageHeader"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { maybe, renderCollection } from "../../../misc"; import { AddressTypeEnum } from "../../../types/globalTypes"; import { CustomerAddresses_user } from "../../types/CustomerAddresses"; @@ -46,9 +45,7 @@ const useStyles = makeStyles( { name: "CustomerAddressListPage" } ); -const CustomerAddressListPage: React.FC< - CustomerAddressListPageProps -> = props => { +const CustomerAddressListPage: React.FC = props => { const { customer, disabled, diff --git a/src/customers/components/CustomerAddresses/CustomerAddresses.tsx b/src/customers/components/CustomerAddresses/CustomerAddresses.tsx index 99241e255..a82fbc172 100644 --- a/src/customers/components/CustomerAddresses/CustomerAddresses.tsx +++ b/src/customers/components/CustomerAddresses/CustomerAddresses.tsx @@ -3,13 +3,13 @@ import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; import { makeStyles } from "@material-ui/core/styles"; import Typography from "@material-ui/core/Typography"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import AddressFormatter from "@saleor/components/AddressFormatter"; import CardTitle from "@saleor/components/CardTitle"; import { Hr } from "@saleor/components/Hr"; import { buttonMessages } from "@saleor/intl"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { maybe } from "../../../misc"; import { CustomerDetails_user } from "../../types/CustomerDetails"; diff --git a/src/customers/components/CustomerCreateAddress/CustomerCreateAddress.tsx b/src/customers/components/CustomerCreateAddress/CustomerCreateAddress.tsx index 5ef7e309b..710aa1d2c 100644 --- a/src/customers/components/CustomerCreateAddress/CustomerCreateAddress.tsx +++ b/src/customers/components/CustomerCreateAddress/CustomerCreateAddress.tsx @@ -2,14 +2,14 @@ import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; import { makeStyles } from "@material-ui/core/styles"; import Typography from "@material-ui/core/Typography"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import AddressEdit from "@saleor/components/AddressEdit"; import CardTitle from "@saleor/components/CardTitle"; import { FormSpacer } from "@saleor/components/FormSpacer"; import { SingleAutocompleteChoiceType } from "@saleor/components/SingleAutocompleteSelectField"; -import { AccountErrorFragment } from "@saleor/customers/types/AccountErrorFragment"; +import { AccountErrorFragment } from "@saleor/fragments/types/AccountErrorFragment"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { AddressTypeInput } from "../../types"; const useStyles = makeStyles( diff --git a/src/customers/components/CustomerCreateDetails/CustomerCreateDetails.tsx b/src/customers/components/CustomerCreateDetails/CustomerCreateDetails.tsx index 785f5ccef..06fd2da43 100644 --- a/src/customers/components/CustomerCreateDetails/CustomerCreateDetails.tsx +++ b/src/customers/components/CustomerCreateDetails/CustomerCreateDetails.tsx @@ -2,14 +2,14 @@ import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; import { makeStyles } from "@material-ui/core/styles"; import TextField from "@material-ui/core/TextField"; +import CardTitle from "@saleor/components/CardTitle"; +import { AccountErrorFragment } from "@saleor/fragments/types/AccountErrorFragment"; +import { commonMessages } from "@saleor/intl"; +import { getFormErrors } from "@saleor/utils/errors"; +import getAccountErrorMessage from "@saleor/utils/errors/account"; import React from "react"; import { useIntl } from "react-intl"; -import CardTitle from "@saleor/components/CardTitle"; -import { commonMessages } from "@saleor/intl"; -import { getFormErrors } from "@saleor/utils/errors"; -import { AccountErrorFragment } from "@saleor/customers/types/AccountErrorFragment"; -import getAccountErrorMessage from "@saleor/utils/errors/account"; import { CustomerCreatePageFormData } from "../CustomerCreatePage"; const useStyles = makeStyles( diff --git a/src/customers/components/CustomerCreateNote/CustomerCreateNote.tsx b/src/customers/components/CustomerCreateNote/CustomerCreateNote.tsx index 6765547d9..b04b0496c 100644 --- a/src/customers/components/CustomerCreateNote/CustomerCreateNote.tsx +++ b/src/customers/components/CustomerCreateNote/CustomerCreateNote.tsx @@ -2,14 +2,13 @@ import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; import TextField from "@material-ui/core/TextField"; import Typography from "@material-ui/core/Typography"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import CardTitle from "@saleor/components/CardTitle"; import { FormSpacer } from "@saleor/components/FormSpacer"; +import { AccountErrorFragment } from "@saleor/fragments/types/AccountErrorFragment"; import { getFormErrors } from "@saleor/utils/errors"; import getAccountErrorMessage from "@saleor/utils/errors/account"; -import { AccountErrorFragment } from "@saleor/customers/types/AccountErrorFragment"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; export interface CustomerCreateNoteProps { data: { diff --git a/src/customers/components/CustomerCreatePage/CustomerCreatePage.tsx b/src/customers/components/CustomerCreatePage/CustomerCreatePage.tsx index c122130fe..554e96456 100644 --- a/src/customers/components/CustomerCreatePage/CustomerCreatePage.tsx +++ b/src/customers/components/CustomerCreatePage/CustomerCreatePage.tsx @@ -1,6 +1,3 @@ -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import AppHeader from "@saleor/components/AppHeader"; import { CardSpacer } from "@saleor/components/CardSpacer"; import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; @@ -9,11 +6,14 @@ import Form from "@saleor/components/Form"; import Grid from "@saleor/components/Grid"; import PageHeader from "@saleor/components/PageHeader"; import SaveButtonBar from "@saleor/components/SaveButtonBar"; +import { AccountErrorFragment } from "@saleor/fragments/types/AccountErrorFragment"; import useAddressValidation from "@saleor/hooks/useAddressValidation"; import { sectionNames } from "@saleor/intl"; import { AddressInput } from "@saleor/types/globalTypes"; import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler"; -import { AccountErrorFragment } from "@saleor/customers/types/AccountErrorFragment"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { AddressTypeInput } from "../../types"; import { CustomerCreateData_shop_countries } from "../../types/CustomerCreateData"; import CustomerCreateAddress from "../CustomerCreateAddress/CustomerCreateAddress"; diff --git a/src/customers/components/CustomerDetails/CustomerDetails.tsx b/src/customers/components/CustomerDetails/CustomerDetails.tsx index 6007dfe3f..b916c6c19 100644 --- a/src/customers/components/CustomerDetails/CustomerDetails.tsx +++ b/src/customers/components/CustomerDetails/CustomerDetails.tsx @@ -3,17 +3,17 @@ import CardContent from "@material-ui/core/CardContent"; import { makeStyles } from "@material-ui/core/styles"; import TextField from "@material-ui/core/TextField"; import Typography from "@material-ui/core/Typography"; +import CardTitle from "@saleor/components/CardTitle"; +import { ControlledCheckbox } from "@saleor/components/ControlledCheckbox"; +import Skeleton from "@saleor/components/Skeleton"; +import { AccountErrorFragment } from "@saleor/fragments/types/AccountErrorFragment"; +import { maybe } from "@saleor/misc"; +import { getFormErrors } from "@saleor/utils/errors"; +import getAccountErrorMessage from "@saleor/utils/errors/account"; import moment from "moment-timezone"; import React from "react"; import { FormattedMessage, useIntl } from "react-intl"; -import CardTitle from "@saleor/components/CardTitle"; -import { ControlledCheckbox } from "@saleor/components/ControlledCheckbox"; -import Skeleton from "@saleor/components/Skeleton"; -import { maybe } from "@saleor/misc"; -import { getFormErrors } from "@saleor/utils/errors"; -import getAccountErrorMessage from "@saleor/utils/errors/account"; -import { AccountErrorFragment } from "@saleor/customers/types/AccountErrorFragment"; import { CustomerDetails_user } from "../../types/CustomerDetails"; const useStyles = makeStyles( diff --git a/src/customers/components/CustomerDetailsPage/CustomerDetailsPage.tsx b/src/customers/components/CustomerDetailsPage/CustomerDetailsPage.tsx index 308a7f115..44081fc76 100644 --- a/src/customers/components/CustomerDetailsPage/CustomerDetailsPage.tsx +++ b/src/customers/components/CustomerDetailsPage/CustomerDetailsPage.tsx @@ -1,6 +1,3 @@ -import React from "react"; -import { useIntl } from "react-intl"; - import AppHeader from "@saleor/components/AppHeader"; import { CardSpacer } from "@saleor/components/CardSpacer"; import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; @@ -9,8 +6,11 @@ import Form from "@saleor/components/Form"; import Grid from "@saleor/components/Grid"; import PageHeader from "@saleor/components/PageHeader"; import SaveButtonBar from "@saleor/components/SaveButtonBar"; +import { AccountErrorFragment } from "@saleor/fragments/types/AccountErrorFragment"; import { sectionNames } from "@saleor/intl"; -import { AccountErrorFragment } from "@saleor/customers/types/AccountErrorFragment"; +import React from "react"; +import { useIntl } from "react-intl"; + import { getUserName, maybe } from "../../../misc"; import { CustomerDetails_user } from "../../types/CustomerDetails"; import CustomerAddresses from "../CustomerAddresses"; diff --git a/src/customers/components/CustomerInfo/CustomerInfo.tsx b/src/customers/components/CustomerInfo/CustomerInfo.tsx index f0b985921..c722f49d1 100644 --- a/src/customers/components/CustomerInfo/CustomerInfo.tsx +++ b/src/customers/components/CustomerInfo/CustomerInfo.tsx @@ -3,16 +3,15 @@ import CardContent from "@material-ui/core/CardContent"; import { makeStyles } from "@material-ui/core/styles"; import TextField from "@material-ui/core/TextField"; import Typography from "@material-ui/core/Typography"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import CardTitle from "@saleor/components/CardTitle"; import Grid from "@saleor/components/Grid"; import Hr from "@saleor/components/Hr"; +import { AccountErrorFragment } from "@saleor/fragments/types/AccountErrorFragment"; import { commonMessages } from "@saleor/intl"; -import { AccountErrorFragment } from "@saleor/customers/types/AccountErrorFragment"; import { getFormErrors } from "@saleor/utils/errors"; import getAccountErrorMessage from "@saleor/utils/errors/account"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; const useStyles = makeStyles( theme => ({ diff --git a/src/customers/components/CustomerList/CustomerList.tsx b/src/customers/components/CustomerList/CustomerList.tsx index 0dd489df0..160bc7d7b 100644 --- a/src/customers/components/CustomerList/CustomerList.tsx +++ b/src/customers/components/CustomerList/CustomerList.tsx @@ -3,19 +3,19 @@ import TableBody from "@material-ui/core/TableBody"; import TableCell from "@material-ui/core/TableCell"; import TableFooter from "@material-ui/core/TableFooter"; import TableRow from "@material-ui/core/TableRow"; -import React from "react"; -import { FormattedMessage } from "react-intl"; - import Checkbox from "@saleor/components/Checkbox"; import ResponsiveTable from "@saleor/components/ResponsiveTable"; import Skeleton from "@saleor/components/Skeleton"; +import TableCellHeader from "@saleor/components/TableCellHeader"; import TableHead from "@saleor/components/TableHead"; import TablePagination from "@saleor/components/TablePagination"; +import { CustomerListUrlSortField } from "@saleor/customers/urls"; import { getUserName, maybe, renderCollection } from "@saleor/misc"; import { ListActions, ListProps, SortPage } from "@saleor/types"; -import { CustomerListUrlSortField } from "@saleor/customers/urls"; -import TableCellHeader from "@saleor/components/TableCellHeader"; import { getArrowDirection } from "@saleor/utils/sort"; +import React from "react"; +import { FormattedMessage } from "react-intl"; + import { ListCustomers_customers_edges_node } from "../../types/ListCustomers"; const useStyles = makeStyles( diff --git a/src/customers/components/CustomerListPage/CustomerListPage.tsx b/src/customers/components/CustomerListPage/CustomerListPage.tsx index 2c45b6f05..51f0c9464 100644 --- a/src/customers/components/CustomerListPage/CustomerListPage.tsx +++ b/src/customers/components/CustomerListPage/CustomerListPage.tsx @@ -1,26 +1,26 @@ import Button from "@material-ui/core/Button"; import Card from "@material-ui/core/Card"; +import Container from "@saleor/components/Container"; +import FilterBar from "@saleor/components/FilterBar"; +import PageHeader from "@saleor/components/PageHeader"; +import { CustomerListUrlSortField } from "@saleor/customers/urls"; +import { sectionNames } from "@saleor/intl"; +import { + FilterPageProps, + ListActions, + PageListProps, + SortPage, + TabPageProps +} from "@saleor/types"; import React from "react"; import { FormattedMessage, useIntl } from "react-intl"; -import Container from "@saleor/components/Container"; -import PageHeader from "@saleor/components/PageHeader"; -import { sectionNames } from "@saleor/intl"; -import { - ListActions, - PageListProps, - TabPageProps, - SortPage, - FilterPageProps -} from "@saleor/types"; -import { CustomerListUrlSortField } from "@saleor/customers/urls"; -import FilterBar from "@saleor/components/FilterBar"; -import CustomerList from "../CustomerList/CustomerList"; import { ListCustomers_customers_edges_node } from "../../types/ListCustomers"; +import CustomerList from "../CustomerList/CustomerList"; import { + createFilterStructure, CustomerFilterKeys, - CustomerListFilterOpts, - createFilterStructure + CustomerListFilterOpts } from "./filters"; export interface CustomerListPageProps diff --git a/src/customers/components/CustomerListPage/filters.ts b/src/customers/components/CustomerListPage/filters.ts index 71301bac9..eb4642493 100644 --- a/src/customers/components/CustomerListPage/filters.ts +++ b/src/customers/components/CustomerListPage/filters.ts @@ -1,11 +1,10 @@ -import { IntlShape, defineMessages } from "react-intl"; - -import { FilterOpts, MinMax } from "@saleor/types"; import { IFilter } from "@saleor/components/Filter"; +import { FilterOpts, MinMax } from "@saleor/types"; import { createDateField, createNumberField } from "@saleor/utils/filters/fields"; +import { defineMessages, IntlShape } from "react-intl"; export enum CustomerFilterKeys { joined = "joined", diff --git a/src/customers/components/CustomerOrders/CustomerOrders.tsx b/src/customers/components/CustomerOrders/CustomerOrders.tsx index 09800e4cd..cf9aac9c5 100644 --- a/src/customers/components/CustomerOrders/CustomerOrders.tsx +++ b/src/customers/components/CustomerOrders/CustomerOrders.tsx @@ -5,15 +5,15 @@ import TableBody from "@material-ui/core/TableBody"; import TableCell from "@material-ui/core/TableCell"; import TableHead from "@material-ui/core/TableHead"; import TableRow from "@material-ui/core/TableRow"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import CardTitle from "@saleor/components/CardTitle"; import { DateTime } from "@saleor/components/Date"; import Money from "@saleor/components/Money"; import ResponsiveTable from "@saleor/components/ResponsiveTable"; import Skeleton from "@saleor/components/Skeleton"; import StatusLabel from "@saleor/components/StatusLabel"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { maybe, renderCollection, transformPaymentStatus } from "../../../misc"; import { CustomerDetails_user_orders_edges_node } from "../../types/CustomerDetails"; diff --git a/src/customers/components/CustomerStats/CustomerStats.tsx b/src/customers/components/CustomerStats/CustomerStats.tsx index 1187c502a..2623a6c0f 100644 --- a/src/customers/components/CustomerStats/CustomerStats.tsx +++ b/src/customers/components/CustomerStats/CustomerStats.tsx @@ -2,13 +2,13 @@ import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; import { makeStyles } from "@material-ui/core/styles"; import Typography from "@material-ui/core/Typography"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import CardTitle from "@saleor/components/CardTitle"; import { DateTime } from "@saleor/components/Date"; import { Hr } from "@saleor/components/Hr"; import Skeleton from "@saleor/components/Skeleton"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { maybe } from "../../../misc"; import { CustomerDetails_user } from "../../types/CustomerDetails"; diff --git a/src/customers/index.tsx b/src/customers/index.tsx index 1314ebc9c..301ea12f4 100644 --- a/src/customers/index.tsx +++ b/src/customers/index.tsx @@ -1,10 +1,10 @@ +import { sectionNames } from "@saleor/intl"; +import { asSortParams } from "@saleor/utils/sort"; import { parse as parseQs } from "qs"; import React from "react"; import { useIntl } from "react-intl"; import { Route, RouteComponentProps, Switch } from "react-router-dom"; -import { sectionNames } from "@saleor/intl"; -import { asSortParams } from "@saleor/utils/sort"; import { WindowTitle } from "../components/WindowTitle"; import { customerAddPath, @@ -12,9 +12,9 @@ import { CustomerAddressesUrlQueryParams, customerListPath, CustomerListUrlQueryParams, + CustomerListUrlSortField, customerPath, - CustomerUrlQueryParams, - CustomerListUrlSortField + CustomerUrlQueryParams } from "./urls"; import CustomerAddressesViewComponent from "./views/CustomerAddresses"; import CustomerCreateView from "./views/CustomerCreate"; diff --git a/src/customers/mutations.ts b/src/customers/mutations.ts index 30729d183..4625a3c4d 100644 --- a/src/customers/mutations.ts +++ b/src/customers/mutations.ts @@ -1,8 +1,12 @@ +import { fragmentAddress } from "@saleor/fragments/address"; +import { + customerAddressesFragment, + customerDetailsFragment +} from "@saleor/fragments/customers"; +import { accountErrorFragment } from "@saleor/fragments/errors"; import gql from "graphql-tag"; import { TypedMutation } from "../mutations"; -import { fragmentAddress } from "../orders/queries"; -import { customerAddressesFragment, customerDetailsFragment } from "./queries"; import { BulkRemoveCustomers, BulkRemoveCustomersVariables @@ -36,13 +40,6 @@ import { UpdateCustomerAddressVariables } from "./types/UpdateCustomerAddress"; -export const accountErrorFragment = gql` - fragment AccountErrorFragment on AccountError { - code - field - } -`; - const updateCustomer = gql` ${accountErrorFragment} ${customerDetailsFragment} diff --git a/src/customers/queries.ts b/src/customers/queries.ts index 7bd2af3b9..3bc3058fa 100644 --- a/src/customers/queries.ts +++ b/src/customers/queries.ts @@ -1,7 +1,11 @@ +import { + customerAddressesFragment, + customerDetailsFragment, + customerFragment +} from "@saleor/fragments/customers"; +import makeQuery from "@saleor/hooks/makeQuery"; import gql from "graphql-tag"; -import makeQuery from "@saleor/hooks/makeQuery"; -import { fragmentAddress } from "../orders/queries"; import { TypedQuery } from "../queries"; import { CustomerAddresses, @@ -14,50 +18,6 @@ import { } from "./types/CustomerDetails"; import { ListCustomers, ListCustomersVariables } from "./types/ListCustomers"; -export const customerFragment = gql` - fragment CustomerFragment on User { - id - email - firstName - lastName - } -`; - -export const customerDetailsFragment = gql` - ${customerFragment} - ${fragmentAddress} - fragment CustomerDetailsFragment on User { - ...CustomerFragment - dateJoined - lastLogin - defaultShippingAddress { - ...AddressFragment - } - defaultBillingAddress { - ...AddressFragment - } - note - isActive - } -`; - -export const customerAddressesFragment = gql` - ${customerFragment} - ${fragmentAddress} - fragment CustomerAddressesFragment on User { - ...CustomerFragment - addresses { - ...AddressFragment - } - defaultBillingAddress { - id - } - defaultShippingAddress { - id - } - } -`; - const customerList = gql` ${customerFragment} query ListCustomers( diff --git a/src/customers/types/CustomerCreateData.ts b/src/customers/types/CustomerCreateData.ts index 7ca532d09..a6e641a56 100644 --- a/src/customers/types/CustomerCreateData.ts +++ b/src/customers/types/CustomerCreateData.ts @@ -14,7 +14,7 @@ export interface CustomerCreateData_shop_countries { export interface CustomerCreateData_shop { __typename: "Shop"; - countries: (CustomerCreateData_shop_countries | null)[]; + countries: CustomerCreateData_shop_countries[]; } export interface CustomerCreateData { diff --git a/src/customers/urls.ts b/src/customers/urls.ts index 819672388..f770d63c9 100644 --- a/src/customers/urls.ts +++ b/src/customers/urls.ts @@ -8,8 +8,8 @@ import { Filters, Pagination, SingleAction, - TabActionDialog, - Sort + Sort, + TabActionDialog } from "../types"; export const customerSection = "/customers/"; diff --git a/src/customers/views/CustomerAddresses.tsx b/src/customers/views/CustomerAddresses.tsx index f1e8fdc81..cf1a7975a 100644 --- a/src/customers/views/CustomerAddresses.tsx +++ b/src/customers/views/CustomerAddresses.tsx @@ -1,7 +1,4 @@ import DialogContentText from "@material-ui/core/DialogContentText"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import ActionDialog from "@saleor/components/ActionDialog"; import { WindowTitle } from "@saleor/components/WindowTitle"; import useNavigator from "@saleor/hooks/useNavigator"; @@ -9,6 +6,9 @@ import useNotifier from "@saleor/hooks/useNotifier"; import useShop from "@saleor/hooks/useShop"; import { commonMessages } from "@saleor/intl"; import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { maybe } from "../../misc"; import CustomerAddressDialog from "../components/CustomerAddressDialog"; import CustomerAddressListPage from "../components/CustomerAddressListPage"; @@ -25,9 +25,9 @@ import { SetCustomerDefaultAddress } from "../types/SetCustomerDefaultAddress"; import { UpdateCustomerAddress } from "../types/UpdateCustomerAddress"; import { customerAddressesUrl, + CustomerAddressesUrlDialog, CustomerAddressesUrlQueryParams, - customerUrl, - CustomerAddressesUrlDialog + customerUrl } from "../urls"; interface CustomerAddressesProps { @@ -53,6 +53,7 @@ const CustomerAddresses: React.FC = ({ if (data.addressSetDefault.errors.length === 0) { closeModal(); notify({ + status: "success", text: intl.formatMessage(commonMessages.savedChanges) }); } @@ -68,6 +69,7 @@ const CustomerAddresses: React.FC = ({ if (data.addressUpdate.errors.length === 0) { closeModal(); notify({ + status: "success", text: intl.formatMessage(commonMessages.savedChanges) }); } @@ -77,6 +79,7 @@ const CustomerAddresses: React.FC = ({ if (data.addressDelete.errors.length === 0) { closeModal(); notify({ + status: "success", text: intl.formatMessage(commonMessages.savedChanges) }); } diff --git a/src/customers/views/CustomerCreate.tsx b/src/customers/views/CustomerCreate.tsx index 97b91efde..0331f9416 100644 --- a/src/customers/views/CustomerCreate.tsx +++ b/src/customers/views/CustomerCreate.tsx @@ -1,9 +1,9 @@ -import React from "react"; -import { useIntl } from "react-intl"; - import { WindowTitle } from "@saleor/components/WindowTitle"; import useNavigator from "@saleor/hooks/useNavigator"; import useNotifier from "@saleor/hooks/useNotifier"; +import React from "react"; +import { useIntl } from "react-intl"; + import { maybe } from "../../misc"; import CustomerCreatePage from "../components/CustomerCreatePage"; import { TypedCreateCustomerMutation } from "../mutations"; @@ -19,6 +19,7 @@ export const CustomerCreate: React.FC<{}> = () => { const handleCreateCustomerSuccess = (data: CreateCustomer) => { if (data.customerCreate.errors.length === 0) { notify({ + status: "success", text: intl.formatMessage({ defaultMessage: "Customer created" }) diff --git a/src/customers/views/CustomerDetails.tsx b/src/customers/views/CustomerDetails.tsx index f5d446b88..c7227e803 100644 --- a/src/customers/views/CustomerDetails.tsx +++ b/src/customers/views/CustomerDetails.tsx @@ -1,13 +1,13 @@ import DialogContentText from "@material-ui/core/DialogContentText"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import ActionDialog from "@saleor/components/ActionDialog"; +import NotFoundPage from "@saleor/components/NotFoundPage"; import { WindowTitle } from "@saleor/components/WindowTitle"; import useNavigator from "@saleor/hooks/useNavigator"; import useNotifier from "@saleor/hooks/useNotifier"; import { commonMessages } from "@saleor/intl"; -import NotFoundPage from "@saleor/components/NotFoundPage"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { maybe } from "../../misc"; import { orderListUrl, orderUrl } from "../../orders/urls"; import CustomerDetailsPage from "../components/CustomerDetailsPage/CustomerDetailsPage"; @@ -41,6 +41,7 @@ export const CustomerDetailsView: React.FC = ({ const handleCustomerUpdateSuccess = (data: UpdateCustomer) => { if (data.customerUpdate.errors.length === 0) { notify({ + status: "success", text: intl.formatMessage(commonMessages.savedChanges) }); } @@ -48,6 +49,7 @@ export const CustomerDetailsView: React.FC = ({ const handleCustomerRemoveSuccess = (data: RemoveCustomer) => { if (data.customerDelete.errors.length === 0) { notify({ + status: "success", text: intl.formatMessage({ defaultMessage: "Customer Removed" }) diff --git a/src/customers/views/CustomerList/CustomerList.tsx b/src/customers/views/CustomerList/CustomerList.tsx index b9df0532c..63cda7d45 100644 --- a/src/customers/views/CustomerList/CustomerList.tsx +++ b/src/customers/views/CustomerList/CustomerList.tsx @@ -1,9 +1,6 @@ import DialogContentText from "@material-ui/core/DialogContentText"; import IconButton from "@material-ui/core/IconButton"; import DeleteIcon from "@material-ui/icons/Delete"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import ActionDialog from "@saleor/components/ActionDialog"; import DeleteFilterTabDialog from "@saleor/components/DeleteFilterTabDialog"; import SaveFilterTabDialog, { @@ -16,14 +13,17 @@ import useNotifier from "@saleor/hooks/useNotifier"; import usePaginator, { createPaginationState } from "@saleor/hooks/usePaginator"; +import useShop from "@saleor/hooks/useShop"; import { commonMessages } from "@saleor/intl"; import { maybe } from "@saleor/misc"; import { ListViews } from "@saleor/types"; -import { getSortParams } from "@saleor/utils/sort"; -import createSortHandler from "@saleor/utils/handlers/sortHandler"; import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; -import useShop from "@saleor/hooks/useShop"; import createFilterHandlers from "@saleor/utils/handlers/filterHandlers"; +import createSortHandler from "@saleor/utils/handlers/sortHandler"; +import { getSortParams } from "@saleor/utils/sort"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import CustomerListPage from "../../components/CustomerListPage"; import { TypedBulkRemoveCustomers } from "../../mutations"; import { useCustomerListQuery } from "../../queries"; @@ -31,19 +31,19 @@ import { BulkRemoveCustomers } from "../../types/BulkRemoveCustomers"; import { customerAddUrl, customerListUrl, + CustomerListUrlDialog, CustomerListUrlQueryParams, - customerUrl, - CustomerListUrlDialog + customerUrl } from "../../urls"; import { areFiltersApplied, deleteFilterTab, getActiveFilters, + getFilterOpts, + getFilterQueryParam, getFilterTabs, getFilterVariables, - saveFilterTab, - getFilterQueryParam, - getFilterOpts + saveFilterTab } from "./filters"; import { getSortQueryVariables } from "./sort"; @@ -134,6 +134,7 @@ export const CustomerList: React.FC = ({ params }) => { const handleBulkCustomerDelete = (data: BulkRemoveCustomers) => { if (data.customerBulkDelete.errors.length === 0) { notify({ + status: "success", text: intl.formatMessage(commonMessages.savedChanges) }); reset(); diff --git a/src/customers/views/CustomerList/filters.test.ts b/src/customers/views/CustomerList/filters.test.ts index 7f73e826a..e2dcdbf6d 100644 --- a/src/customers/views/CustomerList/filters.test.ts +++ b/src/customers/views/CustomerList/filters.test.ts @@ -1,13 +1,13 @@ -import { createIntl } from "react-intl"; -import { stringify as stringifyQs } from "qs"; - -import { CustomerListUrlFilters } from "@saleor/customers/urls"; import { createFilterStructure } from "@saleor/customers/components/CustomerListPage"; -import { getFilterQueryParams } from "@saleor/utils/filters"; +import { CustomerListUrlFilters } from "@saleor/customers/urls"; import { date } from "@saleor/fixtures"; +import { getFilterQueryParams } from "@saleor/utils/filters"; import { getExistingKeys, setFilterOptsStatus } from "@test/filters"; import { config } from "@test/intl"; -import { getFilterVariables, getFilterQueryParam } from "./filters"; +import { stringify as stringifyQs } from "qs"; +import { createIntl } from "react-intl"; + +import { getFilterQueryParam, getFilterVariables } from "./filters"; describe("Filtering query params", () => { it("should be empty object if no params given", () => { diff --git a/src/customers/views/CustomerList/filters.ts b/src/customers/views/CustomerList/filters.ts index fb72e2d0b..0068da444 100644 --- a/src/customers/views/CustomerList/filters.ts +++ b/src/customers/views/CustomerList/filters.ts @@ -1,10 +1,11 @@ -import { CustomerFilterInput } from "@saleor/types/globalTypes"; -import { maybe } from "@saleor/misc"; import { IFilterElement } from "@saleor/components/Filter"; import { CustomerFilterKeys, CustomerListFilterOpts } from "@saleor/customers/components/CustomerListPage"; +import { maybe } from "@saleor/misc"; +import { CustomerFilterInput } from "@saleor/types/globalTypes"; + import { createFilterTabUtils, createFilterUtils, diff --git a/src/discounts/components/DiscountCategories/DiscountCategories.tsx b/src/discounts/components/DiscountCategories/DiscountCategories.tsx index 1a805509b..419d68187 100644 --- a/src/discounts/components/DiscountCategories/DiscountCategories.tsx +++ b/src/discounts/components/DiscountCategories/DiscountCategories.tsx @@ -7,15 +7,15 @@ import TableCell from "@material-ui/core/TableCell"; import TableFooter from "@material-ui/core/TableFooter"; import TableRow from "@material-ui/core/TableRow"; import DeleteIcon from "@material-ui/icons/Delete"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import CardTitle from "@saleor/components/CardTitle"; import Checkbox from "@saleor/components/Checkbox"; import ResponsiveTable from "@saleor/components/ResponsiveTable"; import Skeleton from "@saleor/components/Skeleton"; import TableHead from "@saleor/components/TableHead"; import TablePagination from "@saleor/components/TablePagination"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { maybe, renderCollection } from "../../../misc"; import { ListActions, ListProps } from "../../../types"; import { SaleDetails_sale } from "../../types/SaleDetails"; diff --git a/src/discounts/components/DiscountCollections/DiscountCollections.tsx b/src/discounts/components/DiscountCollections/DiscountCollections.tsx index 3484bc853..1525ae8e8 100644 --- a/src/discounts/components/DiscountCollections/DiscountCollections.tsx +++ b/src/discounts/components/DiscountCollections/DiscountCollections.tsx @@ -7,15 +7,15 @@ import TableCell from "@material-ui/core/TableCell"; import TableFooter from "@material-ui/core/TableFooter"; import TableRow from "@material-ui/core/TableRow"; import DeleteIcon from "@material-ui/icons/Delete"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import CardTitle from "@saleor/components/CardTitle"; import Checkbox from "@saleor/components/Checkbox"; import ResponsiveTable from "@saleor/components/ResponsiveTable"; import Skeleton from "@saleor/components/Skeleton"; import TableHead from "@saleor/components/TableHead"; import TablePagination from "@saleor/components/TablePagination"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { maybe, renderCollection } from "../../../misc"; import { ListActions, ListProps } from "../../../types"; import { SaleDetails_sale } from "../../types/SaleDetails"; diff --git a/src/discounts/components/DiscountCountrySelectDialog/DiscountCountrySelectDialog.tsx b/src/discounts/components/DiscountCountrySelectDialog/DiscountCountrySelectDialog.tsx index 0b8991c76..9a12c61f3 100644 --- a/src/discounts/components/DiscountCountrySelectDialog/DiscountCountrySelectDialog.tsx +++ b/src/discounts/components/DiscountCountrySelectDialog/DiscountCountrySelectDialog.tsx @@ -9,10 +9,6 @@ import TableCell from "@material-ui/core/TableCell"; import TableRow from "@material-ui/core/TableRow"; import TextField from "@material-ui/core/TextField"; import Typography from "@material-ui/core/Typography"; -import { filter } from "fuzzaldrin"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import Checkbox from "@saleor/components/Checkbox"; import ConfirmButton, { ConfirmButtonTransitionState @@ -24,6 +20,9 @@ import ResponsiveTable from "@saleor/components/ResponsiveTable"; // tslint:disable no-submodule-imports import { ShopInfo_shop_countries } from "@saleor/components/Shop/types/ShopInfo"; import { buttonMessages } from "@saleor/intl"; +import { filter } from "fuzzaldrin"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; interface FormData { allCountries: boolean; @@ -58,9 +57,7 @@ const useStyles = makeStyles( }), { name: "DiscountCountrySelectDialog" } ); -const DiscountCountrySelectDialog: React.FC< - DiscountCountrySelectDialogProps -> = props => { +const DiscountCountrySelectDialog: React.FC = props => { const { confirmButtonState, onClose, diff --git a/src/discounts/components/DiscountDates/DiscountDates.tsx b/src/discounts/components/DiscountDates/DiscountDates.tsx index 734a24773..be0368439 100644 --- a/src/discounts/components/DiscountDates/DiscountDates.tsx +++ b/src/discounts/components/DiscountDates/DiscountDates.tsx @@ -1,16 +1,15 @@ import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; import TextField from "@material-ui/core/TextField"; -import React from "react"; -import { useIntl } from "react-intl"; - import CardTitle from "@saleor/components/CardTitle"; import { ControlledCheckbox } from "@saleor/components/ControlledCheckbox"; import Grid from "@saleor/components/Grid"; +import { DiscountErrorFragment } from "@saleor/fragments/types/DiscountErrorFragment"; import { commonMessages } from "@saleor/intl"; import { getFormErrors } from "@saleor/utils/errors"; import getDiscountErrorMessage from "@saleor/utils/errors/discounts"; -import { DiscountErrorFragment } from "@saleor/discounts/types/DiscountErrorFragment"; +import React from "react"; +import { useIntl } from "react-intl"; interface DiscountDatesProps { data: { diff --git a/src/discounts/components/DiscountProducts/DiscountProducts.tsx b/src/discounts/components/DiscountProducts/DiscountProducts.tsx index b9ee5828d..8f3d51b38 100644 --- a/src/discounts/components/DiscountProducts/DiscountProducts.tsx +++ b/src/discounts/components/DiscountProducts/DiscountProducts.tsx @@ -7,9 +7,6 @@ import TableCell from "@material-ui/core/TableCell"; import TableFooter from "@material-ui/core/TableFooter"; import TableRow from "@material-ui/core/TableRow"; import DeleteIcon from "@material-ui/icons/Delete"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import CardTitle from "@saleor/components/CardTitle"; import Checkbox from "@saleor/components/Checkbox"; import ResponsiveTable from "@saleor/components/ResponsiveTable"; @@ -20,6 +17,9 @@ import TableCellAvatar, { } from "@saleor/components/TableCellAvatar"; import TableHead from "@saleor/components/TableHead"; import TablePagination from "@saleor/components/TablePagination"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { maybe, renderCollection } from "../../../misc"; import { ListActions, ListProps } from "../../../types"; import { SaleDetails_sale } from "../../types/SaleDetails"; diff --git a/src/discounts/components/SaleCreatePage/SaleCreatePage.tsx b/src/discounts/components/SaleCreatePage/SaleCreatePage.tsx index c4fece3cd..42a005283 100644 --- a/src/discounts/components/SaleCreatePage/SaleCreatePage.tsx +++ b/src/discounts/components/SaleCreatePage/SaleCreatePage.tsx @@ -1,6 +1,3 @@ -import React from "react"; -import { useIntl } from "react-intl"; - import AppHeader from "@saleor/components/AppHeader"; import CardSpacer from "@saleor/components/CardSpacer"; import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; @@ -9,8 +6,11 @@ import Form from "@saleor/components/Form"; import Grid from "@saleor/components/Grid"; import PageHeader from "@saleor/components/PageHeader"; import SaveButtonBar from "@saleor/components/SaveButtonBar"; +import { DiscountErrorFragment } from "@saleor/fragments/types/DiscountErrorFragment"; import { sectionNames } from "@saleor/intl"; -import { DiscountErrorFragment } from "@saleor/discounts/types/DiscountErrorFragment"; +import React from "react"; +import { useIntl } from "react-intl"; + import { SaleType as SaleTypeEnum } from "../../../types/globalTypes"; import DiscountDates from "../DiscountDates"; import SaleInfo from "../SaleInfo"; diff --git a/src/discounts/components/SaleDetailsPage/SaleDetailsPage.tsx b/src/discounts/components/SaleDetailsPage/SaleDetailsPage.tsx index d615284bd..46df77189 100644 --- a/src/discounts/components/SaleDetailsPage/SaleDetailsPage.tsx +++ b/src/discounts/components/SaleDetailsPage/SaleDetailsPage.tsx @@ -1,6 +1,3 @@ -import React from "react"; -import { useIntl } from "react-intl"; - import AppHeader from "@saleor/components/AppHeader"; import CardSpacer from "@saleor/components/CardSpacer"; import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; @@ -10,8 +7,11 @@ import Grid from "@saleor/components/Grid"; import PageHeader from "@saleor/components/PageHeader"; import SaveButtonBar from "@saleor/components/SaveButtonBar"; import { Tab, TabContainer } from "@saleor/components/Tab"; +import { DiscountErrorFragment } from "@saleor/fragments/types/DiscountErrorFragment"; import { sectionNames } from "@saleor/intl"; -import { DiscountErrorFragment } from "@saleor/discounts/types/DiscountErrorFragment"; +import React from "react"; +import { useIntl } from "react-intl"; + import { maybe, splitDateTime } from "../../../misc"; import { ListProps, TabListActions } from "../../../types"; import { SaleType as SaleTypeEnum } from "../../../types/globalTypes"; diff --git a/src/discounts/components/SaleInfo/SaleInfo.tsx b/src/discounts/components/SaleInfo/SaleInfo.tsx index 90908fd10..94a1baa1e 100644 --- a/src/discounts/components/SaleInfo/SaleInfo.tsx +++ b/src/discounts/components/SaleInfo/SaleInfo.tsx @@ -1,14 +1,14 @@ import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; import TextField from "@material-ui/core/TextField"; +import CardTitle from "@saleor/components/CardTitle"; +import { DiscountErrorFragment } from "@saleor/fragments/types/DiscountErrorFragment"; +import { commonMessages } from "@saleor/intl"; +import { getFormErrors } from "@saleor/utils/errors"; +import getDiscountErrorMessage from "@saleor/utils/errors/discounts"; import React from "react"; import { useIntl } from "react-intl"; -import CardTitle from "@saleor/components/CardTitle"; -import { commonMessages } from "@saleor/intl"; -import { getFormErrors } from "@saleor/utils/errors"; -import { DiscountErrorFragment } from "@saleor/discounts/types/DiscountErrorFragment"; -import getDiscountErrorMessage from "@saleor/utils/errors/discounts"; import { FormData } from "../SaleDetailsPage"; export interface SaleInfoProps { diff --git a/src/discounts/components/SaleList/SaleList.tsx b/src/discounts/components/SaleList/SaleList.tsx index ce78fd11a..6f640d982 100644 --- a/src/discounts/components/SaleList/SaleList.tsx +++ b/src/discounts/components/SaleList/SaleList.tsx @@ -3,23 +3,23 @@ import TableBody from "@material-ui/core/TableBody"; import TableCell from "@material-ui/core/TableCell"; import TableFooter from "@material-ui/core/TableFooter"; import TableRow from "@material-ui/core/TableRow"; -import React from "react"; -import { FormattedMessage } from "react-intl"; - import Checkbox from "@saleor/components/Checkbox"; import Date from "@saleor/components/Date"; import Money from "@saleor/components/Money"; import Percent from "@saleor/components/Percent"; import ResponsiveTable from "@saleor/components/ResponsiveTable"; import Skeleton from "@saleor/components/Skeleton"; +import TableCellHeader from "@saleor/components/TableCellHeader"; import TableHead from "@saleor/components/TableHead"; import TablePagination from "@saleor/components/TablePagination"; +import { SaleListUrlSortField } from "@saleor/discounts/urls"; import { maybe, renderCollection } from "@saleor/misc"; import { ListActions, ListProps, SortPage } from "@saleor/types"; import { SaleType } from "@saleor/types/globalTypes"; -import { SaleListUrlSortField } from "@saleor/discounts/urls"; -import TableCellHeader from "@saleor/components/TableCellHeader"; import { getArrowDirection } from "@saleor/utils/sort"; +import React from "react"; +import { FormattedMessage } from "react-intl"; + import { SaleList_sales_edges_node } from "../../types/SaleList"; export interface SaleListProps diff --git a/src/discounts/components/SaleListPage/SaleListPage.tsx b/src/discounts/components/SaleListPage/SaleListPage.tsx index b6c5ef9bd..96f593619 100644 --- a/src/discounts/components/SaleListPage/SaleListPage.tsx +++ b/src/discounts/components/SaleListPage/SaleListPage.tsx @@ -1,26 +1,26 @@ import Button from "@material-ui/core/Button"; import Card from "@material-ui/core/Card"; +import Container from "@saleor/components/Container"; +import FilterBar from "@saleor/components/FilterBar"; +import PageHeader from "@saleor/components/PageHeader"; +import { SaleListUrlSortField } from "@saleor/discounts/urls"; +import { sectionNames } from "@saleor/intl"; +import { + FilterPageProps, + ListActions, + PageListProps, + SortPage, + TabPageProps +} from "@saleor/types"; import React from "react"; import { FormattedMessage, useIntl } from "react-intl"; -import Container from "@saleor/components/Container"; -import PageHeader from "@saleor/components/PageHeader"; -import FilterBar from "@saleor/components/FilterBar"; -import { sectionNames } from "@saleor/intl"; -import { - ListActions, - PageListProps, - TabPageProps, - SortPage, - FilterPageProps -} from "@saleor/types"; -import { SaleListUrlSortField } from "@saleor/discounts/urls"; import { SaleList_sales_edges_node } from "../../types/SaleList"; import SaleList from "../SaleList"; import { + createFilterStructure, SaleFilterKeys, - SaleListFilterOpts, - createFilterStructure + SaleListFilterOpts } from "./filters"; export interface SaleListPageProps diff --git a/src/discounts/components/SaleListPage/filters.ts b/src/discounts/components/SaleListPage/filters.ts index cd60e2cda..eff413b00 100644 --- a/src/discounts/components/SaleListPage/filters.ts +++ b/src/discounts/components/SaleListPage/filters.ts @@ -1,5 +1,4 @@ -import { defineMessages, IntlShape } from "react-intl"; - +import { IFilter } from "@saleor/components/Filter"; import { FilterOpts, MinMax } from "@saleor/types"; import { DiscountStatusEnum, @@ -9,7 +8,7 @@ import { createDateField, createOptionsField } from "@saleor/utils/filters/fields"; -import { IFilter } from "@saleor/components/Filter"; +import { defineMessages, IntlShape } from "react-intl"; export enum SaleFilterKeys { saleType = "saleType", diff --git a/src/discounts/components/SaleSummary/SaleSummary.tsx b/src/discounts/components/SaleSummary/SaleSummary.tsx index 9841f895e..8c5787386 100644 --- a/src/discounts/components/SaleSummary/SaleSummary.tsx +++ b/src/discounts/components/SaleSummary/SaleSummary.tsx @@ -1,9 +1,6 @@ import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; import Typography from "@material-ui/core/Typography"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import CardSpacer from "@saleor/components/CardSpacer"; import CardTitle from "@saleor/components/CardTitle"; import Date from "@saleor/components/Date"; @@ -13,6 +10,9 @@ import Money from "@saleor/components/Money"; import Percent from "@saleor/components/Percent"; import Skeleton from "@saleor/components/Skeleton"; import { commonMessages } from "@saleor/intl"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { maybe } from "../../../misc"; import { SaleType } from "../../../types/globalTypes"; import { SaleDetails_sale } from "../../types/SaleDetails"; diff --git a/src/discounts/components/SaleType/SaleType.tsx b/src/discounts/components/SaleType/SaleType.tsx index 333db8ef7..a5f782f37 100644 --- a/src/discounts/components/SaleType/SaleType.tsx +++ b/src/discounts/components/SaleType/SaleType.tsx @@ -1,15 +1,15 @@ import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; import { makeStyles } from "@material-ui/core/styles"; -import React from "react"; -import { IntlShape, useIntl } from "react-intl"; - import CardTitle from "@saleor/components/CardTitle"; import RadioGroupField, { RadioGroupFieldChoice } from "@saleor/components/RadioGroupField"; import { FormChange } from "@saleor/hooks/useForm"; import { SaleType as SaleTypeEnum } from "@saleor/types/globalTypes"; +import React from "react"; +import { IntlShape, useIntl } from "react-intl"; + import { FormData } from "../SaleDetailsPage"; export interface SaleTypeProps { diff --git a/src/discounts/components/SaleValue/SaleValue.tsx b/src/discounts/components/SaleValue/SaleValue.tsx index 708671e43..34312ac2c 100644 --- a/src/discounts/components/SaleValue/SaleValue.tsx +++ b/src/discounts/components/SaleValue/SaleValue.tsx @@ -1,15 +1,15 @@ import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; import TextField from "@material-ui/core/TextField"; -import React from "react"; -import { useIntl } from "react-intl"; - import CardTitle from "@saleor/components/CardTitle"; +import { DiscountErrorFragment } from "@saleor/fragments/types/DiscountErrorFragment"; import { FormChange } from "@saleor/hooks/useForm"; import { SaleType } from "@saleor/types/globalTypes"; import { getFormErrors } from "@saleor/utils/errors"; import getDiscountErrorMessage from "@saleor/utils/errors/discounts"; -import { DiscountErrorFragment } from "@saleor/discounts/types/DiscountErrorFragment"; +import React from "react"; +import { useIntl } from "react-intl"; + import { FormData } from "../SaleDetailsPage"; export interface SaleValueProps { diff --git a/src/discounts/components/VoucherCreatePage/VoucherCreatePage.tsx b/src/discounts/components/VoucherCreatePage/VoucherCreatePage.tsx index fb09430bf..65899494e 100644 --- a/src/discounts/components/VoucherCreatePage/VoucherCreatePage.tsx +++ b/src/discounts/components/VoucherCreatePage/VoucherCreatePage.tsx @@ -1,6 +1,3 @@ -import React from "react"; -import { useIntl } from "react-intl"; - import AppHeader from "@saleor/components/AppHeader"; import CardSpacer from "@saleor/components/CardSpacer"; import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; @@ -9,8 +6,11 @@ import Form from "@saleor/components/Form"; import Grid from "@saleor/components/Grid"; import PageHeader from "@saleor/components/PageHeader"; import SaveButtonBar from "@saleor/components/SaveButtonBar"; +import { DiscountErrorFragment } from "@saleor/fragments/types/DiscountErrorFragment"; import { sectionNames } from "@saleor/intl"; -import { DiscountErrorFragment } from "@saleor/discounts/types/DiscountErrorFragment"; +import React from "react"; +import { useIntl } from "react-intl"; + import { DiscountValueTypeEnum, VoucherTypeEnum diff --git a/src/discounts/components/VoucherDates/VoucherDates.tsx b/src/discounts/components/VoucherDates/VoucherDates.tsx index 3f94dfa76..be804c2e6 100644 --- a/src/discounts/components/VoucherDates/VoucherDates.tsx +++ b/src/discounts/components/VoucherDates/VoucherDates.tsx @@ -1,16 +1,16 @@ import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; import TextField from "@material-ui/core/TextField"; -import React from "react"; -import { useIntl } from "react-intl"; - import CardTitle from "@saleor/components/CardTitle"; import { ControlledCheckbox } from "@saleor/components/ControlledCheckbox"; import Grid from "@saleor/components/Grid"; +import { DiscountErrorFragment } from "@saleor/fragments/types/DiscountErrorFragment"; import { commonMessages } from "@saleor/intl"; import { getFormErrors } from "@saleor/utils/errors"; import getDiscountErrorMessage from "@saleor/utils/errors/discounts"; -import { DiscountErrorFragment } from "@saleor/discounts/types/DiscountErrorFragment"; +import React from "react"; +import { useIntl } from "react-intl"; + import { FormData } from "../VoucherDetailsPage"; interface VoucherDatesProps { diff --git a/src/discounts/components/VoucherDetailsPage/VoucherDetailsPage.tsx b/src/discounts/components/VoucherDetailsPage/VoucherDetailsPage.tsx index 11db32b9b..db418d3e6 100644 --- a/src/discounts/components/VoucherDetailsPage/VoucherDetailsPage.tsx +++ b/src/discounts/components/VoucherDetailsPage/VoucherDetailsPage.tsx @@ -1,7 +1,4 @@ import Typography from "@material-ui/core/Typography"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import AppHeader from "@saleor/components/AppHeader"; import CardSpacer from "@saleor/components/CardSpacer"; import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; @@ -13,8 +10,11 @@ import PageHeader from "@saleor/components/PageHeader"; import SaveButtonBar from "@saleor/components/SaveButtonBar"; import { Tab, TabContainer } from "@saleor/components/Tab"; import { RequirementsPicker } from "@saleor/discounts/types"; +import { DiscountErrorFragment } from "@saleor/fragments/types/DiscountErrorFragment"; import { sectionNames } from "@saleor/intl"; -import { DiscountErrorFragment } from "@saleor/discounts/types/DiscountErrorFragment"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { maybe, splitDateTime } from "../../../misc"; import { ListProps, TabListActions } from "../../../types"; import { diff --git a/src/discounts/components/VoucherInfo/VoucherInfo.tsx b/src/discounts/components/VoucherInfo/VoucherInfo.tsx index 0ca4160d3..3b227980f 100644 --- a/src/discounts/components/VoucherInfo/VoucherInfo.tsx +++ b/src/discounts/components/VoucherInfo/VoucherInfo.tsx @@ -1,17 +1,17 @@ +import Button from "@material-ui/core/Button"; import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; import TextField from "@material-ui/core/TextField"; +import CardTitle from "@saleor/components/CardTitle"; +import { DiscountErrorFragment } from "@saleor/fragments/types/DiscountErrorFragment"; +import { commonMessages } from "@saleor/intl"; +import { getFormErrors } from "@saleor/utils/errors"; +import getDiscountErrorMessage from "@saleor/utils/errors/discounts"; import React from "react"; import { FormattedMessage, useIntl } from "react-intl"; -import Button from "@material-ui/core/Button"; -import CardTitle from "@saleor/components/CardTitle"; -import { commonMessages } from "@saleor/intl"; -import { DiscountErrorFragment } from "@saleor/discounts/types/DiscountErrorFragment"; -import { getFormErrors } from "@saleor/utils/errors"; -import getDiscountErrorMessage from "@saleor/utils/errors/discounts"; -import { FormData } from "../VoucherDetailsPage"; import { generateCode } from "../../../misc"; +import { FormData } from "../VoucherDetailsPage"; interface VoucherInfoProps { data: FormData; diff --git a/src/discounts/components/VoucherLimits/VoucherLimits.tsx b/src/discounts/components/VoucherLimits/VoucherLimits.tsx index c2650d659..30a377641 100644 --- a/src/discounts/components/VoucherLimits/VoucherLimits.tsx +++ b/src/discounts/components/VoucherLimits/VoucherLimits.tsx @@ -1,14 +1,14 @@ import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; import TextField from "@material-ui/core/TextField"; +import CardTitle from "@saleor/components/CardTitle"; +import { ControlledCheckbox } from "@saleor/components/ControlledCheckbox"; +import { DiscountErrorFragment } from "@saleor/fragments/types/DiscountErrorFragment"; +import { getFormErrors } from "@saleor/utils/errors"; +import getDiscountErrorMessage from "@saleor/utils/errors/discounts"; import React from "react"; import { useIntl } from "react-intl"; -import CardTitle from "@saleor/components/CardTitle"; -import { ControlledCheckbox } from "@saleor/components/ControlledCheckbox"; -import { getFormErrors } from "@saleor/utils/errors"; -import { DiscountErrorFragment } from "@saleor/discounts/types/DiscountErrorFragment"; -import getDiscountErrorMessage from "@saleor/utils/errors/discounts"; import { FormData } from "../VoucherDetailsPage"; interface VoucherLimitsProps { diff --git a/src/discounts/components/VoucherList/VoucherList.tsx b/src/discounts/components/VoucherList/VoucherList.tsx index 34899a583..4733999a7 100644 --- a/src/discounts/components/VoucherList/VoucherList.tsx +++ b/src/discounts/components/VoucherList/VoucherList.tsx @@ -3,23 +3,23 @@ import TableBody from "@material-ui/core/TableBody"; import TableCell from "@material-ui/core/TableCell"; import TableFooter from "@material-ui/core/TableFooter"; import TableRow from "@material-ui/core/TableRow"; -import React from "react"; -import { FormattedMessage } from "react-intl"; - import Checkbox from "@saleor/components/Checkbox"; import Date from "@saleor/components/Date"; import Money from "@saleor/components/Money"; import Percent from "@saleor/components/Percent"; import ResponsiveTable from "@saleor/components/ResponsiveTable"; import Skeleton from "@saleor/components/Skeleton"; +import TableCellHeader from "@saleor/components/TableCellHeader"; import TableHead from "@saleor/components/TableHead"; import TablePagination from "@saleor/components/TablePagination"; +import { VoucherListUrlSortField } from "@saleor/discounts/urls"; import { maybe, renderCollection } from "@saleor/misc"; import { ListActions, ListProps, SortPage } from "@saleor/types"; import { DiscountValueTypeEnum } from "@saleor/types/globalTypes"; -import { VoucherListUrlSortField } from "@saleor/discounts/urls"; -import TableCellHeader from "@saleor/components/TableCellHeader"; import { getArrowDirection } from "@saleor/utils/sort"; +import React from "react"; +import { FormattedMessage } from "react-intl"; + import { VoucherList_vouchers_edges_node } from "../../types/VoucherList"; export interface VoucherListProps diff --git a/src/discounts/components/VoucherListPage/VoucherListPage.tsx b/src/discounts/components/VoucherListPage/VoucherListPage.tsx index 91dbf982d..11193de57 100644 --- a/src/discounts/components/VoucherListPage/VoucherListPage.tsx +++ b/src/discounts/components/VoucherListPage/VoucherListPage.tsx @@ -1,26 +1,26 @@ import Button from "@material-ui/core/Button"; import Card from "@material-ui/core/Card"; +import Container from "@saleor/components/Container"; +import FilterBar from "@saleor/components/FilterBar"; +import PageHeader from "@saleor/components/PageHeader"; +import { VoucherListUrlSortField } from "@saleor/discounts/urls"; +import { sectionNames } from "@saleor/intl"; +import { + FilterPageProps, + ListActions, + PageListProps, + SortPage, + TabPageProps +} from "@saleor/types"; import React from "react"; import { FormattedMessage, useIntl } from "react-intl"; -import Container from "@saleor/components/Container"; -import PageHeader from "@saleor/components/PageHeader"; -import FilterBar from "@saleor/components/FilterBar"; -import { sectionNames } from "@saleor/intl"; -import { - ListActions, - PageListProps, - TabPageProps, - SortPage, - FilterPageProps -} from "@saleor/types"; -import { VoucherListUrlSortField } from "@saleor/discounts/urls"; import { VoucherList_vouchers_edges_node } from "../../types/VoucherList"; import VoucherList from "../VoucherList"; import { + createFilterStructure, VoucherFilterKeys, - VoucherListFilterOpts, - createFilterStructure + VoucherListFilterOpts } from "./filters"; export interface VoucherListPageProps diff --git a/src/discounts/components/VoucherListPage/filters.ts b/src/discounts/components/VoucherListPage/filters.ts index e1c2c56a5..8fc0a88c2 100644 --- a/src/discounts/components/VoucherListPage/filters.ts +++ b/src/discounts/components/VoucherListPage/filters.ts @@ -1,16 +1,15 @@ -import { defineMessages, IntlShape } from "react-intl"; - -import { - createOptionsField, - createNumberField, - createDateField -} from "@saleor/utils/filters/fields"; -import { - VoucherDiscountType, - DiscountStatusEnum -} from "@saleor/types/globalTypes"; -import { MinMax, FilterOpts } from "@saleor/types"; import { IFilter } from "@saleor/components/Filter"; +import { FilterOpts, MinMax } from "@saleor/types"; +import { + DiscountStatusEnum, + VoucherDiscountType +} from "@saleor/types/globalTypes"; +import { + createDateField, + createNumberField, + createOptionsField +} from "@saleor/utils/filters/fields"; +import { defineMessages, IntlShape } from "react-intl"; export enum VoucherFilterKeys { saleType = "saleType", diff --git a/src/discounts/components/VoucherRequirements/VoucherRequirements.tsx b/src/discounts/components/VoucherRequirements/VoucherRequirements.tsx index afb105079..da7d8e563 100644 --- a/src/discounts/components/VoucherRequirements/VoucherRequirements.tsx +++ b/src/discounts/components/VoucherRequirements/VoucherRequirements.tsx @@ -1,16 +1,16 @@ import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; import TextField from "@material-ui/core/TextField"; -import React from "react"; -import { useIntl } from "react-intl"; - import CardTitle from "@saleor/components/CardTitle"; import { FormSpacer } from "@saleor/components/FormSpacer"; import RadioGroupField from "@saleor/components/RadioGroupField"; import { RequirementsPicker } from "@saleor/discounts/types"; -import { DiscountErrorFragment } from "@saleor/discounts/types/DiscountErrorFragment"; +import { DiscountErrorFragment } from "@saleor/fragments/types/DiscountErrorFragment"; import { getFormErrors } from "@saleor/utils/errors"; import getDiscountErrorMessage from "@saleor/utils/errors/discounts"; +import React from "react"; +import { useIntl } from "react-intl"; + import { FormData } from "../VoucherDetailsPage"; interface VoucherRequirementsProps { diff --git a/src/discounts/components/VoucherSummary/VoucherSummary.tsx b/src/discounts/components/VoucherSummary/VoucherSummary.tsx index df402a531..f476fbe3a 100644 --- a/src/discounts/components/VoucherSummary/VoucherSummary.tsx +++ b/src/discounts/components/VoucherSummary/VoucherSummary.tsx @@ -1,9 +1,6 @@ import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; import Typography from "@material-ui/core/Typography"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import CardSpacer from "@saleor/components/CardSpacer"; import CardTitle from "@saleor/components/CardTitle"; import Date from "@saleor/components/Date"; @@ -13,6 +10,9 @@ import Money from "@saleor/components/Money"; import Percent from "@saleor/components/Percent"; import Skeleton from "@saleor/components/Skeleton"; import { commonMessages } from "@saleor/intl"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { maybe } from "../../../misc"; import { DiscountValueTypeEnum } from "../../../types/globalTypes"; import { translateVoucherTypes } from "../../translations"; diff --git a/src/discounts/components/VoucherTypes/VoucherTypes.tsx b/src/discounts/components/VoucherTypes/VoucherTypes.tsx index 871acc1a4..f64e9b4a8 100644 --- a/src/discounts/components/VoucherTypes/VoucherTypes.tsx +++ b/src/discounts/components/VoucherTypes/VoucherTypes.tsx @@ -1,16 +1,16 @@ import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; -import React from "react"; -import { useIntl } from "react-intl"; - import CardTitle from "@saleor/components/CardTitle"; import Grid from "@saleor/components/Grid"; import RadioGroupField from "@saleor/components/RadioGroupField"; -import { DiscountErrorFragment } from "@saleor/discounts/types/DiscountErrorFragment"; +import { DiscountErrorFragment } from "@saleor/fragments/types/DiscountErrorFragment"; import { getFormErrors } from "@saleor/utils/errors"; import getDiscountErrorMessage from "@saleor/utils/errors/discounts"; -import { FormData } from "../VoucherDetailsPage"; +import React from "react"; +import { useIntl } from "react-intl"; + import { DiscountValueTypeEnum } from "../../../types/globalTypes"; +import { FormData } from "../VoucherDetailsPage"; interface VoucherTypesProps { data: FormData; diff --git a/src/discounts/components/VoucherValue/VoucherValue.tsx b/src/discounts/components/VoucherValue/VoucherValue.tsx index f34bfa0d3..6c3e1ecf8 100644 --- a/src/discounts/components/VoucherValue/VoucherValue.tsx +++ b/src/discounts/components/VoucherValue/VoucherValue.tsx @@ -2,18 +2,18 @@ import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; import { makeStyles } from "@material-ui/core/styles"; import Typography from "@material-ui/core/Typography"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import CardTitle from "@saleor/components/CardTitle"; import ControlledCheckbox from "@saleor/components/ControlledCheckbox"; import { FormSpacer } from "@saleor/components/FormSpacer"; import Hr from "@saleor/components/Hr"; import RadioGroupField from "@saleor/components/RadioGroupField"; import TextFieldWithChoice from "@saleor/components/TextFieldWithChoice"; -import { DiscountErrorFragment } from "@saleor/discounts/types/DiscountErrorFragment"; +import { DiscountErrorFragment } from "@saleor/fragments/types/DiscountErrorFragment"; import { getFormErrors } from "@saleor/utils/errors"; import getDiscountErrorMessage from "@saleor/utils/errors/discounts"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { DiscountValueTypeEnum } from "../../../types/globalTypes"; import { translateVoucherTypes } from "../../translations"; import { FormData } from "../VoucherDetailsPage"; diff --git a/src/discounts/fixtures.ts b/src/discounts/fixtures.ts index 5dac9a7d9..9c2f22bfb 100644 --- a/src/discounts/fixtures.ts +++ b/src/discounts/fixtures.ts @@ -1,4 +1,5 @@ import placeholderImage from "@assets/images/placeholder60x60.png"; + import { DiscountValueTypeEnum, SaleType, diff --git a/src/discounts/index.tsx b/src/discounts/index.tsx index 4b3e64591..e2a23db85 100644 --- a/src/discounts/index.tsx +++ b/src/discounts/index.tsx @@ -1,10 +1,10 @@ +import { sectionNames } from "@saleor/intl"; +import { asSortParams } from "@saleor/utils/sort"; import { parse as parseQs } from "qs"; import React from "react"; import { useIntl } from "react-intl"; import { Route, RouteComponentProps, Switch } from "react-router-dom"; -import { sectionNames } from "@saleor/intl"; -import { asSortParams } from "@saleor/utils/sort"; import { WindowTitle } from "../components/WindowTitle"; import { saleDetailsPageTab } from "./components/SaleDetailsPage"; import { voucherDetailsPageTab } from "./components/VoucherDetailsPage"; @@ -12,15 +12,15 @@ import { saleAddPath, saleListPath, SaleListUrlQueryParams, + SaleListUrlSortField, salePath, SaleUrlQueryParams, voucherAddPath, voucherListPath, VoucherListUrlQueryParams, + VoucherListUrlSortField, voucherPath, - VoucherUrlQueryParams, - SaleListUrlSortField, - VoucherListUrlSortField + VoucherUrlQueryParams } from "./urls"; import SaleCreateView from "./views/SaleCreate"; import SaleDetailsViewComponent from "./views/SaleDetails"; diff --git a/src/discounts/mutations.ts b/src/discounts/mutations.ts index aa5007519..d9cadff5d 100644 --- a/src/discounts/mutations.ts +++ b/src/discounts/mutations.ts @@ -1,12 +1,13 @@ -import gql from "graphql-tag"; - -import { TypedMutation } from "../mutations"; import { saleDetailsFragment, saleFragment, voucherDetailsFragment, voucherFragment -} from "./queries"; +} from "@saleor/fragments/discounts"; +import { discountErrorFragment } from "@saleor/fragments/errors"; +import gql from "graphql-tag"; + +import { TypedMutation } from "../mutations"; import { SaleBulkDelete, SaleBulkDeleteVariables @@ -38,13 +39,6 @@ import { VoucherCreate, VoucherCreateVariables } from "./types/VoucherCreate"; import { VoucherDelete, VoucherDeleteVariables } from "./types/VoucherDelete"; import { VoucherUpdate, VoucherUpdateVariables } from "./types/VoucherUpdate"; -const discountErrorFragment = gql` - fragment DiscountErrorFragment on DiscountError { - code - field - } -`; - const saleUpdate = gql` ${discountErrorFragment} ${saleFragment} diff --git a/src/discounts/queries.ts b/src/discounts/queries.ts index 0d7230c34..683154ac4 100644 --- a/src/discounts/queries.ts +++ b/src/discounts/queries.ts @@ -1,7 +1,14 @@ +import { + saleDetailsFragment, + saleFragment, + voucherDetailsFragment, + voucherFragment +} from "@saleor/fragments/discounts"; +import { pageInfoFragment } from "@saleor/fragments/pageInfo"; +import makeQuery from "@saleor/hooks/makeQuery"; import gql from "graphql-tag"; -import makeQuery from "@saleor/hooks/makeQuery"; -import { pageInfoFragment, TypedQuery } from "../queries"; +import { TypedQuery } from "../queries"; import { SaleDetails, SaleDetailsVariables } from "./types/SaleDetails"; import { SaleList, SaleListVariables } from "./types/SaleList"; import { @@ -10,160 +17,6 @@ import { } from "./types/VoucherDetails"; import { VoucherList, VoucherListVariables } from "./types/VoucherList"; -export const saleFragment = gql` - fragment SaleFragment on Sale { - id - name - type - startDate - endDate - value - } -`; - -export const saleDetailsFragment = gql` - ${pageInfoFragment} - ${saleFragment} - fragment SaleDetailsFragment on Sale { - ...SaleFragment - products(after: $after, before: $before, first: $first, last: $last) { - edges { - node { - id - name - isPublished - productType { - id - name - } - thumbnail { - url - } - } - } - pageInfo { - ...PageInfoFragment - } - totalCount - } - categories(after: $after, before: $before, first: $first, last: $last) { - edges { - node { - id - name - products { - totalCount - } - } - } - pageInfo { - ...PageInfoFragment - } - totalCount - } - collections(after: $after, before: $before, first: $first, last: $last) { - edges { - node { - id - name - products { - totalCount - } - } - } - pageInfo { - ...PageInfoFragment - } - totalCount - } - } -`; - -export const voucherFragment = gql` - fragment VoucherFragment on Voucher { - id - code - startDate - endDate - usageLimit - discountValueType - discountValue - countries { - code - country - } - minSpent { - currency - amount - } - minCheckoutItemsQuantity - } -`; - -export const voucherDetailsFragment = gql` - ${pageInfoFragment} - ${voucherFragment} - fragment VoucherDetailsFragment on Voucher { - ...VoucherFragment - type - code - usageLimit - used - applyOncePerOrder - applyOncePerCustomer - products(after: $after, before: $before, first: $first, last: $last) { - edges { - node { - id - name - productType { - id - name - } - isPublished - thumbnail { - url - } - } - } - totalCount - pageInfo { - ...PageInfoFragment - } - } - collections(after: $after, before: $before, first: $first, last: $last) { - edges { - node { - id - name - products { - totalCount - } - } - } - totalCount - pageInfo { - ...PageInfoFragment - } - } - categories(after: $after, before: $before, first: $first, last: $last) { - edges { - node { - id - name - products { - totalCount - } - } - } - totalCount - pageInfo { - ...PageInfoFragment - } - } - } -`; - export const saleList = gql` ${pageInfoFragment} ${saleFragment} diff --git a/src/discounts/urls.ts b/src/discounts/urls.ts index 186e9a722..c3a8f7f41 100644 --- a/src/discounts/urls.ts +++ b/src/discounts/urls.ts @@ -6,10 +6,10 @@ import { BulkAction, Dialog, Filters, + FiltersWithMultipleValues, Pagination, - TabActionDialog, Sort, - FiltersWithMultipleValues + TabActionDialog } from "../types"; import { SaleDetailsPageTab } from "./components/SaleDetailsPage"; import { VoucherDetailsPageTab } from "./components/VoucherDetailsPage"; diff --git a/src/discounts/views/SaleCreate.tsx b/src/discounts/views/SaleCreate.tsx index 3c237ea83..b44ee45cb 100644 --- a/src/discounts/views/SaleCreate.tsx +++ b/src/discounts/views/SaleCreate.tsx @@ -1,11 +1,11 @@ -import React from "react"; -import { useIntl } from "react-intl"; - import { WindowTitle } from "@saleor/components/WindowTitle"; import useNavigator from "@saleor/hooks/useNavigator"; import useNotifier from "@saleor/hooks/useNotifier"; import useShop from "@saleor/hooks/useShop"; import { sectionNames } from "@saleor/intl"; +import React from "react"; +import { useIntl } from "react-intl"; + import { decimal, joinDateTime, maybe } from "../../misc"; import { DiscountValueTypeEnum, SaleType } from "../../types/globalTypes"; import SaleCreatePage from "../components/SaleCreatePage"; diff --git a/src/discounts/views/SaleDetails.tsx b/src/discounts/views/SaleDetails.tsx index caa386836..b7b5bbde6 100644 --- a/src/discounts/views/SaleDetails.tsx +++ b/src/discounts/views/SaleDetails.tsx @@ -1,8 +1,5 @@ import Button from "@material-ui/core/Button"; import DialogContentText from "@material-ui/core/DialogContentText"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import ActionDialog from "@saleor/components/ActionDialog"; import AssignCategoriesDialog from "@saleor/components/AssignCategoryDialog"; import AssignCollectionDialog from "@saleor/components/AssignCollectionDialog"; @@ -21,6 +18,9 @@ import useCategorySearch from "@saleor/searches/useCategorySearch"; import useCollectionSearch from "@saleor/searches/useCollectionSearch"; import useProductSearch from "@saleor/searches/useProductSearch"; import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { categoryUrl } from "../../categories/urls"; import { collectionUrl } from "../../collections/urls"; import { decimal, joinDateTime, maybe } from "../../misc"; @@ -43,8 +43,8 @@ import { SaleUpdate } from "../types/SaleUpdate"; import { saleListUrl, saleUrl, - SaleUrlQueryParams, - SaleUrlDialog + SaleUrlDialog, + SaleUrlQueryParams } from "../urls"; interface SaleDetailsProps { @@ -99,6 +99,7 @@ export const SaleDetails: React.FC = ({ id, params }) => { const handleSaleDelete = (data: SaleDelete) => { if (data.saleDelete.errors.length === 0) { notify({ + status: "success", text: intl.formatMessage({ defaultMessage: "Removed sale" }) @@ -110,6 +111,7 @@ export const SaleDetails: React.FC = ({ id, params }) => { const handleSaleUpdate = (data: SaleUpdate) => { if (data.saleUpdate.errors.length === 0) { notify({ + status: "success", text: intl.formatMessage(commonMessages.savedChanges) }); } diff --git a/src/discounts/views/SaleList/SaleList.tsx b/src/discounts/views/SaleList/SaleList.tsx index 2cfb889b4..d10865328 100644 --- a/src/discounts/views/SaleList/SaleList.tsx +++ b/src/discounts/views/SaleList/SaleList.tsx @@ -1,9 +1,6 @@ import DialogContentText from "@material-ui/core/DialogContentText"; import IconButton from "@material-ui/core/IconButton"; import DeleteIcon from "@material-ui/icons/Delete"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import ActionDialog from "@saleor/components/ActionDialog"; import DeleteFilterTabDialog from "@saleor/components/DeleteFilterTabDialog"; import SaveFilterTabDialog, { @@ -21,30 +18,33 @@ import useShop from "@saleor/hooks/useShop"; import { commonMessages, sectionNames } from "@saleor/intl"; import { maybe } from "@saleor/misc"; import { ListViews } from "@saleor/types"; -import { getSortParams } from "@saleor/utils/sort"; -import createSortHandler from "@saleor/utils/handlers/sortHandler"; import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; import createFilterHandlers from "@saleor/utils/handlers/filterHandlers"; +import createSortHandler from "@saleor/utils/handlers/sortHandler"; +import { getSortParams } from "@saleor/utils/sort"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import SaleListPage from "../../components/SaleListPage"; import { TypedSaleBulkDelete } from "../../mutations"; import { useSaleListQuery } from "../../queries"; import { SaleBulkDelete } from "../../types/SaleBulkDelete"; import { saleAddUrl, - SaleListUrlQueryParams, - saleUrl, saleListUrl, - SaleListUrlDialog + SaleListUrlDialog, + SaleListUrlQueryParams, + saleUrl } from "../../urls"; import { areFiltersApplied, deleteFilterTab, getActiveFilters, + getFilterOpts, + getFilterQueryParam, getFilterTabs, getFilterVariables, - saveFilterTab, - getFilterQueryParam, - getFilterOpts + saveFilterTab } from "./filters"; import { getSortQueryVariables } from "./sort"; @@ -137,6 +137,7 @@ export const SaleList: React.FC = ({ params }) => { const handleSaleBulkDelete = (data: SaleBulkDelete) => { if (data.saleBulkDelete.errors.length === 0) { notify({ + status: "success", text: intl.formatMessage(commonMessages.savedChanges) }); reset(); diff --git a/src/discounts/views/SaleList/filters.test.ts b/src/discounts/views/SaleList/filters.test.ts index f6d7f7743..665ef9c20 100644 --- a/src/discounts/views/SaleList/filters.test.ts +++ b/src/discounts/views/SaleList/filters.test.ts @@ -1,17 +1,17 @@ -import { createIntl } from "react-intl"; -import { stringify as stringifyQs } from "qs"; - -import { SaleListUrlFilters } from "@saleor/discounts/urls"; import { createFilterStructure } from "@saleor/discounts/components/SaleListPage"; -import { getFilterQueryParams } from "@saleor/utils/filters"; +import { SaleListUrlFilters } from "@saleor/discounts/urls"; import { date } from "@saleor/fixtures"; +import { + DiscountStatusEnum, + DiscountValueTypeEnum +} from "@saleor/types/globalTypes"; +import { getFilterQueryParams } from "@saleor/utils/filters"; import { getExistingKeys, setFilterOptsStatus } from "@test/filters"; import { config } from "@test/intl"; -import { - DiscountValueTypeEnum, - DiscountStatusEnum -} from "@saleor/types/globalTypes"; -import { getFilterVariables, getFilterQueryParam } from "./filters"; +import { stringify as stringifyQs } from "qs"; +import { createIntl } from "react-intl"; + +import { getFilterQueryParam, getFilterVariables } from "./filters"; describe("Filtering query params", () => { it("should be empty object if no params given", () => { diff --git a/src/discounts/views/SaleList/filters.ts b/src/discounts/views/SaleList/filters.ts index d2683e58f..7e40dfba0 100644 --- a/src/discounts/views/SaleList/filters.ts +++ b/src/discounts/views/SaleList/filters.ts @@ -1,28 +1,29 @@ +import { IFilterElement } from "@saleor/components/Filter"; +import { + SaleFilterKeys, + SaleListFilterOpts +} from "@saleor/discounts/components/SaleListPage"; +import { findValueInEnum, joinDateTime, maybe } from "@saleor/misc"; import { DiscountStatusEnum, DiscountValueTypeEnum, SaleFilterInput } from "@saleor/types/globalTypes"; -import { maybe, findValueInEnum, joinDateTime } from "@saleor/misc"; -import { IFilterElement } from "@saleor/components/Filter"; -import { - SaleListFilterOpts, - SaleFilterKeys -} from "@saleor/discounts/components/SaleListPage"; + import { createFilterTabUtils, createFilterUtils, dedupeFilter, getGteLteVariables, - getSingleEnumValueQueryParam, getMinMaxQueryParam, - getMultipleEnumValueQueryParam + getMultipleEnumValueQueryParam, + getSingleEnumValueQueryParam } from "../../../utils/filters"; import { SaleListUrlFilters, SaleListUrlFiltersEnum, - SaleListUrlQueryParams, - SaleListUrlFiltersWithMultipleValues + SaleListUrlFiltersWithMultipleValues, + SaleListUrlQueryParams } from "../../urls"; export const SALE_FILTERS_KEY = "saleFilters"; @@ -116,4 +117,7 @@ export const { export const { areFiltersApplied, getActiveFilters } = createFilterUtils< SaleListUrlQueryParams, SaleListUrlFilters ->(SaleListUrlFiltersEnum); +>({ + ...SaleListUrlFiltersEnum, + ...SaleListUrlFiltersWithMultipleValues +}); diff --git a/src/discounts/views/VoucherCreate.tsx b/src/discounts/views/VoucherCreate.tsx index 4b5b4bb4e..29f6fabaf 100644 --- a/src/discounts/views/VoucherCreate.tsx +++ b/src/discounts/views/VoucherCreate.tsx @@ -1,11 +1,11 @@ -import React from "react"; -import { useIntl } from "react-intl"; - import { WindowTitle } from "@saleor/components/WindowTitle"; import useNavigator from "@saleor/hooks/useNavigator"; import useNotifier from "@saleor/hooks/useNotifier"; import useShop from "@saleor/hooks/useShop"; import { sectionNames } from "@saleor/intl"; +import React from "react"; +import { useIntl } from "react-intl"; + import { decimal, joinDateTime, maybe } from "../../misc"; import { DiscountValueTypeEnum, @@ -26,6 +26,7 @@ export const VoucherDetails: React.FC = () => { const handleVoucherCreate = (data: VoucherCreate) => { if (data.voucherCreate.errors.length === 0) { notify({ + status: "success", text: intl.formatMessage({ defaultMessage: "Successfully created voucher" }) diff --git a/src/discounts/views/VoucherDetails.tsx b/src/discounts/views/VoucherDetails.tsx index 61b63e6b5..866073fde 100644 --- a/src/discounts/views/VoucherDetails.tsx +++ b/src/discounts/views/VoucherDetails.tsx @@ -1,8 +1,5 @@ import Button from "@material-ui/core/Button"; import DialogContentText from "@material-ui/core/DialogContentText"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import ActionDialog from "@saleor/components/ActionDialog"; import AssignCategoriesDialog from "@saleor/components/AssignCategoryDialog"; import AssignCollectionDialog from "@saleor/components/AssignCollectionDialog"; @@ -21,6 +18,9 @@ import useCategorySearch from "@saleor/searches/useCategorySearch"; import useCollectionSearch from "@saleor/searches/useCollectionSearch"; import useProductSearch from "@saleor/searches/useProductSearch"; import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { categoryUrl } from "../../categories/urls"; import { collectionUrl } from "../../collections/urls"; import { decimal, joinDateTime, maybe } from "../../misc"; @@ -48,8 +48,8 @@ import { VoucherUpdate } from "../types/VoucherUpdate"; import { voucherListUrl, voucherUrl, - VoucherUrlQueryParams, - VoucherUrlDialog + VoucherUrlDialog, + VoucherUrlQueryParams } from "../urls"; interface VoucherDetailsProps { @@ -101,6 +101,7 @@ export const VoucherDetails: React.FC = ({ const handleVoucherDelete = (data: VoucherDelete) => { if (data.voucherDelete.errors.length === 0) { notify({ + status: "success", text: intl.formatMessage({ defaultMessage: "Deleted voucher" }) @@ -113,6 +114,7 @@ export const VoucherDetails: React.FC = ({ if (data.voucherUpdate.errors.length === 0) { closeModal(); notify({ + status: "success", text: intl.formatMessage(commonMessages.savedChanges) }); } diff --git a/src/discounts/views/VoucherList/VoucherList.tsx b/src/discounts/views/VoucherList/VoucherList.tsx index e17019d3e..2eb624f65 100644 --- a/src/discounts/views/VoucherList/VoucherList.tsx +++ b/src/discounts/views/VoucherList/VoucherList.tsx @@ -1,9 +1,6 @@ import DialogContentText from "@material-ui/core/DialogContentText"; import IconButton from "@material-ui/core/IconButton"; import DeleteIcon from "@material-ui/icons/Delete"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import ActionDialog from "@saleor/components/ActionDialog"; import DeleteFilterTabDialog from "@saleor/components/DeleteFilterTabDialog"; import SaveFilterTabDialog, { @@ -21,10 +18,13 @@ import useShop from "@saleor/hooks/useShop"; import { commonMessages, sectionNames } from "@saleor/intl"; import { maybe } from "@saleor/misc"; import { ListViews } from "@saleor/types"; -import { getSortParams } from "@saleor/utils/sort"; -import createSortHandler from "@saleor/utils/handlers/sortHandler"; import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; import createFilterHandlers from "@saleor/utils/handlers/filterHandlers"; +import createSortHandler from "@saleor/utils/handlers/sortHandler"; +import { getSortParams } from "@saleor/utils/sort"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import VoucherListPage from "../../components/VoucherListPage"; import { TypedVoucherBulkDelete } from "../../mutations"; import { useVoucherListQuery } from "../../queries"; @@ -32,19 +32,19 @@ import { VoucherBulkDelete } from "../../types/VoucherBulkDelete"; import { voucherAddUrl, voucherListUrl, + VoucherListUrlDialog, VoucherListUrlQueryParams, - voucherUrl, - VoucherListUrlDialog + voucherUrl } from "../../urls"; import { areFiltersApplied, deleteFilterTab, getActiveFilters, + getFilterOpts, + getFilterQueryParam, getFilterTabs, getFilterVariables, - saveFilterTab, - getFilterQueryParam, - getFilterOpts + saveFilterTab } from "./filters"; import { getSortQueryVariables } from "./sort"; @@ -137,6 +137,7 @@ export const VoucherList: React.FC = ({ params }) => { const handleVoucherBulkDelete = (data: VoucherBulkDelete) => { if (data.voucherBulkDelete.errors.length === 0) { notify({ + status: "success", text: intl.formatMessage(commonMessages.savedChanges) }); reset(); diff --git a/src/discounts/views/VoucherList/filters.test.ts b/src/discounts/views/VoucherList/filters.test.ts index 0000a4e6b..cf7abeaab 100644 --- a/src/discounts/views/VoucherList/filters.test.ts +++ b/src/discounts/views/VoucherList/filters.test.ts @@ -1,17 +1,17 @@ -import { createIntl } from "react-intl"; -import { stringify as stringifyQs } from "qs"; - -import { VoucherListUrlFilters } from "@saleor/discounts/urls"; import { createFilterStructure } from "@saleor/discounts/components/VoucherListPage"; -import { getFilterQueryParams } from "@saleor/utils/filters"; +import { VoucherListUrlFilters } from "@saleor/discounts/urls"; import { date } from "@saleor/fixtures"; -import { getExistingKeys, setFilterOptsStatus } from "@test/filters"; -import { config } from "@test/intl"; import { DiscountStatusEnum, VoucherDiscountType } from "@saleor/types/globalTypes"; -import { getFilterVariables, getFilterQueryParam } from "./filters"; +import { getFilterQueryParams } from "@saleor/utils/filters"; +import { getExistingKeys, setFilterOptsStatus } from "@test/filters"; +import { config } from "@test/intl"; +import { stringify as stringifyQs } from "qs"; +import { createIntl } from "react-intl"; + +import { getFilterQueryParam, getFilterVariables } from "./filters"; describe("Filtering query params", () => { it("should be empty object if no params given", () => { diff --git a/src/discounts/views/VoucherList/filters.ts b/src/discounts/views/VoucherList/filters.ts index 691ec9a1e..ff3623fe0 100644 --- a/src/discounts/views/VoucherList/filters.ts +++ b/src/discounts/views/VoucherList/filters.ts @@ -1,27 +1,28 @@ -import { - VoucherFilterInput, - DiscountStatusEnum, - VoucherDiscountType -} from "@saleor/types/globalTypes"; -import { maybe, findValueInEnum, joinDateTime } from "@saleor/misc"; import { IFilterElement } from "@saleor/components/Filter"; import { - VoucherListFilterOpts, - VoucherFilterKeys + VoucherFilterKeys, + VoucherListFilterOpts } from "@saleor/discounts/components/VoucherListPage"; +import { findValueInEnum, joinDateTime, maybe } from "@saleor/misc"; +import { + DiscountStatusEnum, + VoucherDiscountType, + VoucherFilterInput +} from "@saleor/types/globalTypes"; + import { createFilterTabUtils, createFilterUtils, dedupeFilter, getGteLteVariables, - getMultipleEnumValueQueryParam, - getMinMaxQueryParam + getMinMaxQueryParam, + getMultipleEnumValueQueryParam } from "../../../utils/filters"; import { VoucherListUrlFilters, VoucherListUrlFiltersEnum, - VoucherListUrlQueryParams, - VoucherListUrlFiltersWithMultipleValues + VoucherListUrlFiltersWithMultipleValues, + VoucherListUrlQueryParams } from "../../urls"; export const VOUCHER_FILTERS_KEY = "voucherFilters"; @@ -148,4 +149,7 @@ export const { export const { areFiltersApplied, getActiveFilters } = createFilterUtils< VoucherListUrlQueryParams, VoucherListUrlFilters ->(VoucherListUrlFiltersEnum); +>({ + ...VoucherListUrlFiltersEnum, + ...VoucherListUrlFiltersWithMultipleValues +}); diff --git a/src/fixtures.ts b/src/fixtures.ts index 037506378..df7afbf9b 100644 --- a/src/fixtures.ts +++ b/src/fixtures.ts @@ -1,4 +1,5 @@ import { ShopInfo_shop_permissions } from "./components/Shop/types/ShopInfo"; +import { User_userPermissions } from "./fragments/types/User"; import { FetchMoreProps, FilterPageProps, @@ -9,7 +10,6 @@ import { TabPageProps } from "./types"; import { PermissionEnum } from "./types/globalTypes"; -import { User_userPermissions } from "./auth/types/User"; const pageInfo = { hasNextPage: true, @@ -370,7 +370,7 @@ export const permissions: ShopInfo_shop_permissions[] = [ name: "Manage apps." }, { - code: PermissionEnum.MANAGE_WEBHOOKS, + code: PermissionEnum.MANAGE_APPS, name: "Manage webhooks." } ].map(perm => ({ diff --git a/src/fragments/address.ts b/src/fragments/address.ts new file mode 100644 index 000000000..33126134c --- /dev/null +++ b/src/fragments/address.ts @@ -0,0 +1,22 @@ +import gql from "graphql-tag"; + +export const fragmentAddress = gql` + fragment AddressFragment on Address { + city + cityArea + companyName + country { + __typename + code + country + } + countryArea + firstName + id + lastName + phone + postalCode + streetAddress1 + streetAddress2 + } +`; diff --git a/src/fragments/apps.ts b/src/fragments/apps.ts new file mode 100644 index 000000000..8795330a2 --- /dev/null +++ b/src/fragments/apps.ts @@ -0,0 +1,33 @@ +import gql from "graphql-tag"; + +export const appFragment = gql` + fragment AppFragment on App { + id + name + created + isActive + type + homepageUrl + appUrl + configurationUrl + supportUrl + version + accessToken + privateMetadata { + key + value + } + metadata { + key + value + } + tokens { + authToken + id + name + } + webhooks { + ...WebhookFragment + } + } +`; diff --git a/src/fragments/attributes.ts b/src/fragments/attributes.ts new file mode 100644 index 000000000..66332cc49 --- /dev/null +++ b/src/fragments/attributes.ts @@ -0,0 +1,33 @@ +import gql from "graphql-tag"; + +import { metadataFragment } from "./metadata"; + +export const attributeFragment = gql` + fragment AttributeFragment on Attribute { + id + name + slug + visibleInStorefront + filterableInDashboard + filterableInStorefront + } +`; + +export const attributeDetailsFragment = gql` + ${attributeFragment} + ${metadataFragment} + fragment AttributeDetailsFragment on Attribute { + ...AttributeFragment + ...MetadataFragment + availableInGrid + inputType + storefrontSearchPosition + valueRequired + values { + id + name + slug + type + } + } +`; diff --git a/src/fragments/auth.ts b/src/fragments/auth.ts new file mode 100644 index 000000000..2a897a523 --- /dev/null +++ b/src/fragments/auth.ts @@ -0,0 +1,17 @@ +import gql from "graphql-tag"; + +export const fragmentUser = gql` + fragment User on User { + id + email + firstName + lastName + userPermissions { + code + name + } + avatar { + url + } + } +`; diff --git a/src/fragments/categories.ts b/src/fragments/categories.ts new file mode 100644 index 000000000..3eebe58d9 --- /dev/null +++ b/src/fragments/categories.ts @@ -0,0 +1,34 @@ +import gql from "graphql-tag"; + +import { metadataFragment } from "./metadata"; + +export const categoryFragment = gql` + fragment CategoryFragment on Category { + id + name + children { + totalCount + } + products { + totalCount + } + } +`; +export const categoryDetailsFragment = gql` + ${metadataFragment} + fragment CategoryDetailsFragment on Category { + id + ...MetadataFragment + backgroundImage { + alt + url + } + name + descriptionJson + seoDescription + seoTitle + parent { + id + } + } +`; diff --git a/src/fragments/collections.ts b/src/fragments/collections.ts new file mode 100644 index 000000000..a27129ce3 --- /dev/null +++ b/src/fragments/collections.ts @@ -0,0 +1,48 @@ +import gql from "graphql-tag"; + +import { metadataFragment } from "./metadata"; + +export const collectionFragment = gql` + fragment CollectionFragment on Collection { + id + isPublished + name + } +`; + +export const collectionDetailsFragment = gql` + ${collectionFragment} + ${metadataFragment} + fragment CollectionDetailsFragment on Collection { + ...CollectionFragment + ...MetadataFragment + backgroundImage { + alt + url + } + descriptionJson + publicationDate + seoDescription + seoTitle + isPublished + } +`; + +// This fragment is used to make sure that product's fields that are returned +// are always the same - fixes apollo cache +// https://github.com/apollographql/apollo-client/issues/2496 +// https://github.com/apollographql/apollo-client/issues/3468 +export const collectionProductFragment = gql` + fragment CollectionProductFragment on Product { + id + isPublished + name + productType { + id + name + } + thumbnail { + url + } + } +`; diff --git a/src/fragments/customers.ts b/src/fragments/customers.ts new file mode 100644 index 000000000..2e4753345 --- /dev/null +++ b/src/fragments/customers.ts @@ -0,0 +1,47 @@ +import gql from "graphql-tag"; + +import { fragmentAddress } from "./address"; + +export const customerFragment = gql` + fragment CustomerFragment on User { + id + email + firstName + lastName + } +`; + +export const customerDetailsFragment = gql` + ${customerFragment} + ${fragmentAddress} + fragment CustomerDetailsFragment on User { + ...CustomerFragment + dateJoined + lastLogin + defaultShippingAddress { + ...AddressFragment + } + defaultBillingAddress { + ...AddressFragment + } + note + isActive + } +`; + +export const customerAddressesFragment = gql` + ${customerFragment} + ${fragmentAddress} + fragment CustomerAddressesFragment on User { + ...CustomerFragment + addresses { + ...AddressFragment + } + defaultBillingAddress { + id + } + defaultShippingAddress { + id + } + } +`; diff --git a/src/fragments/discounts.ts b/src/fragments/discounts.ts new file mode 100644 index 000000000..2e99da371 --- /dev/null +++ b/src/fragments/discounts.ts @@ -0,0 +1,157 @@ +import gql from "graphql-tag"; + +import { pageInfoFragment } from "./pageInfo"; + +export const saleFragment = gql` + fragment SaleFragment on Sale { + id + name + type + startDate + endDate + value + } +`; + +export const saleDetailsFragment = gql` + ${pageInfoFragment} + ${saleFragment} + fragment SaleDetailsFragment on Sale { + ...SaleFragment + products(after: $after, before: $before, first: $first, last: $last) { + edges { + node { + id + name + isPublished + productType { + id + name + } + thumbnail { + url + } + } + } + pageInfo { + ...PageInfoFragment + } + totalCount + } + categories(after: $after, before: $before, first: $first, last: $last) { + edges { + node { + id + name + products { + totalCount + } + } + } + pageInfo { + ...PageInfoFragment + } + totalCount + } + collections(after: $after, before: $before, first: $first, last: $last) { + edges { + node { + id + name + products { + totalCount + } + } + } + pageInfo { + ...PageInfoFragment + } + totalCount + } + } +`; + +export const voucherFragment = gql` + fragment VoucherFragment on Voucher { + id + code + startDate + endDate + usageLimit + discountValueType + discountValue + countries { + code + country + } + minSpent { + currency + amount + } + minCheckoutItemsQuantity + } +`; + +export const voucherDetailsFragment = gql` + ${pageInfoFragment} + ${voucherFragment} + fragment VoucherDetailsFragment on Voucher { + ...VoucherFragment + type + code + usageLimit + used + applyOncePerOrder + applyOncePerCustomer + products(after: $after, before: $before, first: $first, last: $last) { + edges { + node { + id + name + productType { + id + name + } + isPublished + thumbnail { + url + } + } + } + totalCount + pageInfo { + ...PageInfoFragment + } + } + collections(after: $after, before: $before, first: $first, last: $last) { + edges { + node { + id + name + products { + totalCount + } + } + } + totalCount + pageInfo { + ...PageInfoFragment + } + } + categories(after: $after, before: $before, first: $first, last: $last) { + edges { + node { + id + name + products { + totalCount + } + } + } + totalCount + pageInfo { + ...PageInfoFragment + } + } + } +`; diff --git a/src/fragments/errors.ts b/src/fragments/errors.ts new file mode 100644 index 000000000..f4bd5d788 --- /dev/null +++ b/src/fragments/errors.ts @@ -0,0 +1,143 @@ +import gql from "graphql-tag"; + +export const productErrorFragment = gql` + fragment ProductErrorFragment on ProductError { + code + field + } +`; + +export const accountErrorFragment = gql` + fragment AccountErrorFragment on AccountError { + code + field + } +`; + +export const discountErrorFragment = gql` + fragment DiscountErrorFragment on DiscountError { + code + field + } +`; + +export const menuErrorFragment = gql` + fragment MenuErrorFragment on MenuError { + code + field + } +`; + +export const orderErrorFragment = gql` + fragment OrderErrorFragment on OrderError { + code + field + } +`; + +export const pageErrorFragment = gql` + fragment PageErrorFragment on PageError { + code + field + } +`; + +export const permissionGroupErrorFragment = gql` + fragment PermissionGroupErrorFragment on PermissionGroupError { + code + field + } +`; + +export const bulkProductErrorFragment = gql` + fragment BulkProductErrorFragment on BulkProductError { + field + code + index + } +`; +export const bulkStockErrorFragment = gql` + fragment BulkStockErrorFragment on BulkStockError { + code + field + index + } +`; +export const stockErrorFragment = gql` + fragment StockErrorFragment on StockError { + code + field + } +`; + +export const shippingErrorFragment = gql` + fragment ShippingErrorFragment on ShippingError { + code + field + } +`; + +export const shopErrorFragment = gql` + fragment ShopErrorFragment on ShopError { + code + field + } +`; + +export const staffErrorFragment = gql` + fragment StaffErrorFragment on StaffError { + code + field + } +`; + +export const warehouseErrorFragment = gql` + fragment WarehouseErrorFragment on WarehouseError { + code + field + } +`; + +export const webhookErrorFragment = gql` + fragment WebhookErrorFragment on WebhookError { + code + field + } +`; + +export const invoiceErrorFragment = gql` + fragment InvoiceErrorFragment on InvoiceError { + code + field + } +`; + +export const appErrorFragment = gql` + fragment AppErrorFragment on AppError { + field + message + code + permissions + } +`; + +export const exportErrorFragment = gql` + fragment ExportErrorFragment on ExportError { + code + field + } +`; + +export const pluginErrorFragment = gql` + fragment PluginErrorFragment on PluginError { + code + field + } +`; + +export const metadataErrorFragment = gql` + fragment MetadataErrorFragment on MetadataError { + code + field + } +`; diff --git a/src/fragments/metadata.ts b/src/fragments/metadata.ts new file mode 100644 index 000000000..2378d8b9e --- /dev/null +++ b/src/fragments/metadata.ts @@ -0,0 +1,16 @@ +import gql from "graphql-tag"; + +export const metadataFragment = gql` + fragment MetadataItem on MetadataItem { + key + value + } + fragment MetadataFragment on ObjectWithMetadata { + metadata { + ...MetadataItem + } + privateMetadata { + ...MetadataItem + } + } +`; diff --git a/src/fragments/navigation.ts b/src/fragments/navigation.ts new file mode 100644 index 000000000..899a523cc --- /dev/null +++ b/src/fragments/navigation.ts @@ -0,0 +1,69 @@ +import gql from "graphql-tag"; + +export const menuFragment = gql` + fragment MenuFragment on Menu { + id + name + items { + id + } + } +`; + +export const menuItemFragment = gql` + fragment MenuItemFragment on MenuItem { + category { + id + name + } + collection { + id + name + } + id + level + name + page { + id + title + } + url + } +`; + +// GraphQL does not support recurive fragments +export const menuItemNestedFragment = gql` + ${menuItemFragment} + fragment MenuItemNestedFragment on MenuItem { + ...MenuItemFragment + children { + ...MenuItemFragment + children { + ...MenuItemFragment + children { + ...MenuItemFragment + children { + ...MenuItemFragment + children { + ...MenuItemFragment + children { + ...MenuItemFragment + } + } + } + } + } + } + } +`; + +export const menuDetailsFragment = gql` + ${menuItemNestedFragment} + fragment MenuDetailsFragment on Menu { + id + items { + ...MenuItemNestedFragment + } + name + } +`; diff --git a/src/fragments/orders.ts b/src/fragments/orders.ts new file mode 100644 index 000000000..9f2d2c1f9 --- /dev/null +++ b/src/fragments/orders.ts @@ -0,0 +1,172 @@ +import gql from "graphql-tag"; + +import { fragmentAddress } from "./address"; +import { metadataFragment } from "./metadata"; + +export const fragmentOrderEvent = gql` + fragment OrderEventFragment on OrderEvent { + id + amount + date + email + emailType + invoiceNumber + message + quantity + type + user { + id + email + } + } +`; + +export const fragmentOrderLine = gql` + fragment OrderLineFragment on OrderLine { + id + isShippingRequired + variant { + product { + isAvailableForPurchase + isPublished + } + quantityAvailable + } + productName + productSku + quantity + quantityFulfilled + unitPrice { + gross { + amount + currency + } + net { + amount + currency + } + } + thumbnail { + url + } + } +`; +export const fulfillmentFragment = gql` + ${fragmentOrderLine} + fragment FulfillmentFragment on Fulfillment { + id + lines { + id + quantity + orderLine { + ...OrderLineFragment + } + } + fulfillmentOrder + status + trackingNumber + warehouse { + id + name + } + } +`; + +export const invoiceFragment = gql` + fragment InvoiceFragment on Invoice { + id + number + createdAt + url + status + } +`; + +export const fragmentOrderDetails = gql` + ${fragmentAddress} + ${fragmentOrderEvent} + ${fragmentOrderLine} + ${fulfillmentFragment} + ${invoiceFragment} + ${metadataFragment} + fragment OrderDetailsFragment on Order { + id + ...MetadataFragment + billingAddress { + ...AddressFragment + } + canFinalize + created + customerNote + events { + ...OrderEventFragment + } + fulfillments { + ...FulfillmentFragment + } + lines { + ...OrderLineFragment + } + number + paymentStatus + shippingAddress { + ...AddressFragment + } + shippingMethod { + id + } + shippingMethodName + shippingPrice { + gross { + amount + currency + } + } + status + subtotal { + gross { + amount + currency + } + } + total { + gross { + amount + currency + } + tax { + amount + currency + } + } + actions + totalAuthorized { + amount + currency + } + totalCaptured { + amount + currency + } + user { + id + email + } + userEmail + availableShippingMethods { + id + name + price { + amount + currency + } + } + discount { + amount + currency + } + invoices { + ...InvoiceFragment + } + } +`; diff --git a/src/fragments/pageInfo.ts b/src/fragments/pageInfo.ts new file mode 100644 index 000000000..413c5ff25 --- /dev/null +++ b/src/fragments/pageInfo.ts @@ -0,0 +1,10 @@ +import gql from "graphql-tag"; + +export const pageInfoFragment = gql` + fragment PageInfoFragment on PageInfo { + endCursor + hasNextPage + hasPreviousPage + startCursor + } +`; diff --git a/src/fragments/pages.ts b/src/fragments/pages.ts new file mode 100644 index 000000000..ea2e13d60 --- /dev/null +++ b/src/fragments/pages.ts @@ -0,0 +1,21 @@ +import gql from "graphql-tag"; + +export const pageFragment = gql` + fragment PageFragment on Page { + id + title + slug + isPublished + } +`; + +export const pageDetailsFragment = gql` + ${pageFragment} + fragment PageDetailsFragment on Page { + ...PageFragment + contentJson + seoTitle + seoDescription + publicationDate + } +`; diff --git a/src/fragments/permissionGroups.ts b/src/fragments/permissionGroups.ts new file mode 100644 index 000000000..e2ea84ec2 --- /dev/null +++ b/src/fragments/permissionGroups.ts @@ -0,0 +1,41 @@ +import gql from "graphql-tag"; + +import { staffMemberFragment } from "./staff"; + +export const permissionGroupFragment = gql` + fragment PermissionGroupFragment on Group { + id + name + userCanManage + users { + id + firstName + lastName + } + } +`; + +export const permissionFragment = gql` + fragment PermissionFragment on Permission { + code + name + } +`; + +export const permissionGroupDetailsFragment = gql` + ${permissionGroupFragment} + ${permissionFragment} + ${staffMemberFragment} + fragment PermissionGroupDetailsFragment on Group { + ...PermissionGroupFragment + permissions { + ...PermissionFragment + } + users { + ...StaffMemberFragment + avatar(size: 48) { + url + } + } + } +`; diff --git a/src/fragments/plugins.ts b/src/fragments/plugins.ts new file mode 100644 index 000000000..3a128af56 --- /dev/null +++ b/src/fragments/plugins.ts @@ -0,0 +1,24 @@ +import gql from "graphql-tag"; + +export const pluginsFragment = gql` + fragment PluginFragment on Plugin { + id + name + description + active + } +`; + +export const pluginsDetailsFragment = gql` + ${pluginsFragment} + fragment PluginsDetailsFragment on Plugin { + ...PluginFragment + configuration { + name + type + value + helpText + label + } + } +`; diff --git a/src/fragments/productTypes.ts b/src/fragments/productTypes.ts new file mode 100644 index 000000000..981dbe571 --- /dev/null +++ b/src/fragments/productTypes.ts @@ -0,0 +1,37 @@ +import gql from "graphql-tag"; + +import { attributeFragment } from "./attributes"; +import { metadataFragment } from "./metadata"; + +export const productTypeFragment = gql` + fragment ProductTypeFragment on ProductType { + id + name + hasVariants + isShippingRequired + taxType { + description + taxCode + } + } +`; + +export const productTypeDetailsFragment = gql` + ${attributeFragment} + ${productTypeFragment} + ${metadataFragment} + fragment ProductTypeDetailsFragment on ProductType { + ...ProductTypeFragment + ...MetadataFragment + productAttributes { + ...AttributeFragment + } + variantAttributes { + ...AttributeFragment + } + weight { + unit + value + } + } +`; diff --git a/src/fragments/products.ts b/src/fragments/products.ts new file mode 100644 index 000000000..1b651dfdd --- /dev/null +++ b/src/fragments/products.ts @@ -0,0 +1,259 @@ +import gql from "graphql-tag"; + +import { metadataFragment } from "./metadata"; +import { weightFragment } from "./weight"; + +export const stockFragment = gql` + fragment StockFragment on Stock { + id + quantity + quantityAllocated + warehouse { + id + name + } + } +`; + +export const fragmentMoney = gql` + fragment Money on Money { + amount + currency + } +`; + +export const fragmentProductImage = gql` + fragment ProductImageFragment on ProductImage { + id + alt + sortOrder + url + } +`; + +export const productFragment = gql` + fragment ProductFragment on Product { + id + name + thumbnail { + url + } + isAvailable + isPublished + productType { + id + name + hasVariants + } + } +`; + +export const productVariantAttributesFragment = gql` + ${fragmentMoney} + fragment ProductVariantAttributesFragment on Product { + id + attributes { + attribute { + id + slug + name + inputType + valueRequired + values { + id + name + slug + } + } + values { + id + name + slug + } + } + productType { + id + variantAttributes { + id + name + values { + id + name + slug + } + } + } + pricing { + priceRangeUndiscounted { + start { + gross { + ...Money + } + } + stop { + gross { + ...Money + } + } + } + } + } +`; + +export const productFragmentDetails = gql` + ${fragmentProductImage} + ${fragmentMoney} + ${productVariantAttributesFragment} + ${stockFragment} + ${weightFragment} + ${metadataFragment} + fragment Product on Product { + ...ProductVariantAttributesFragment + ...MetadataFragment + name + descriptionJson + seoTitle + seoDescription + category { + id + name + } + collections { + id + name + } + margin { + start + stop + } + purchaseCost { + start { + ...Money + } + stop { + ...Money + } + } + isAvailableForPurchase + isAvailable + isPublished + chargeTaxes + publicationDate + pricing { + priceRangeUndiscounted { + start { + gross { + ...Money + } + } + stop { + gross { + ...Money + } + } + } + } + images { + ...ProductImageFragment + } + variants { + id + sku + name + price { + ...Money + } + margin + stocks { + ...StockFragment + } + trackInventory + } + productType { + id + name + hasVariants + } + weight { + ...WeightFragment + } + availableForPurchase + visibleInListings + } +`; + +export const fragmentVariant = gql` + ${fragmentMoney} + ${fragmentProductImage} + ${stockFragment} + ${weightFragment} + ${metadataFragment} + fragment ProductVariant on ProductVariant { + id + ...MetadataFragment + attributes { + attribute { + id + name + slug + valueRequired + values { + id + name + slug + } + } + values { + id + name + slug + } + } + costPrice { + ...Money + } + images { + id + url + } + name + price { + ...Money + } + product { + id + images { + ...ProductImageFragment + } + name + thumbnail { + url + } + variants { + id + name + sku + images { + id + url + } + } + } + sku + stocks { + ...StockFragment + } + trackInventory + weight { + ...WeightFragment + } + } +`; + +export const exportFileFragment = gql` + fragment ExportFileFragment on ExportFile { + id + status + url + } +`; diff --git a/src/fragments/shipping.ts b/src/fragments/shipping.ts new file mode 100644 index 000000000..b2845edc7 --- /dev/null +++ b/src/fragments/shipping.ts @@ -0,0 +1,54 @@ +import gql from "graphql-tag"; + +export const shippingZoneFragment = gql` + fragment ShippingZoneFragment on ShippingZone { + id + countries { + code + country + } + name + } +`; +export const shippingMethodFragment = gql` + fragment ShippingMethodFragment on ShippingMethod { + id + minimumOrderPrice { + amount + currency + } + minimumOrderWeight { + unit + value + } + maximumOrderPrice { + amount + currency + } + maximumOrderWeight { + unit + value + } + name + price { + amount + currency + } + type + } +`; +export const shippingZoneDetailsFragment = gql` + ${shippingZoneFragment} + ${shippingMethodFragment} + fragment ShippingZoneDetailsFragment on ShippingZone { + ...ShippingZoneFragment + default + shippingMethods { + ...ShippingMethodFragment + } + warehouses { + id + name + } + } +`; diff --git a/src/fragments/shop.ts b/src/fragments/shop.ts new file mode 100644 index 000000000..b7e05eebe --- /dev/null +++ b/src/fragments/shop.ts @@ -0,0 +1,28 @@ +import gql from "graphql-tag"; + +import { fragmentAddress } from "./address"; + +export const shopFragment = gql` + ${fragmentAddress} + fragment ShopFragment on Shop { + authorizationKeys { + key + name + } + companyAddress { + ...AddressFragment + } + countries { + code + country + } + customerSetPasswordUrl + defaultMailSenderAddress + defaultMailSenderName + description + domain { + host + } + name + } +`; diff --git a/src/fragments/staff.ts b/src/fragments/staff.ts new file mode 100644 index 000000000..edc469c7e --- /dev/null +++ b/src/fragments/staff.ts @@ -0,0 +1,29 @@ +import gql from "graphql-tag"; + +export const staffMemberFragment = gql` + fragment StaffMemberFragment on User { + id + email + firstName + isActive + lastName + } +`; +export const staffMemberDetailsFragment = gql` + ${staffMemberFragment} + fragment StaffMemberDetailsFragment on User { + ...StaffMemberFragment + permissionGroups { + id + name + userCanManage + } + userPermissions { + code + name + } + avatar(size: 120) { + url + } + } +`; diff --git a/src/fragments/taxes.ts b/src/fragments/taxes.ts new file mode 100644 index 000000000..026bc00f4 --- /dev/null +++ b/src/fragments/taxes.ts @@ -0,0 +1,28 @@ +import gql from "graphql-tag"; + +export const countryFragment = gql` + fragment CountryFragment on CountryDisplay { + country + code + } +`; +export const countryWithTaxesFragment = gql` + ${countryFragment} + fragment CountryWithTaxesFragment on CountryDisplay { + ...CountryFragment + vat { + standardRate + reducedRates { + rateType + rate + } + } + } +`; +export const shopTaxesFragment = gql` + fragment ShopTaxesFragment on Shop { + chargeTaxesOnShipping + includeTaxesInPrices + displayGrossPrices + } +`; diff --git a/src/fragments/translations.ts b/src/fragments/translations.ts new file mode 100644 index 000000000..2a05816f4 --- /dev/null +++ b/src/fragments/translations.ts @@ -0,0 +1,172 @@ +import gql from "graphql-tag"; + +export const categoryTranslationFragment = gql` + fragment CategoryTranslationFragment on Category { + id + name + descriptionJson + seoDescription + seoTitle + translation(languageCode: $language) { + id + descriptionJson + language { + language + } + name + seoDescription + seoTitle + } + } +`; +export const collectionTranslationFragment = gql` + fragment CollectionTranslationFragment on Collection { + id + name + descriptionJson + seoDescription + seoTitle + translation(languageCode: $language) { + id + descriptionJson + language { + language + } + name + seoDescription + seoTitle + } + } +`; +export const productTranslationFragment = gql` + fragment ProductTranslationFragment on Product { + id + name + descriptionJson + seoDescription + seoTitle + translation(languageCode: $language) { + id + descriptionJson + language { + code + language + } + name + seoDescription + seoTitle + } + } +`; +export const saleTranslationFragment = gql` + fragment SaleTranslationFragment on Sale { + id + name + translation(languageCode: $language) { + id + language { + code + language + } + name + } + } +`; +export const voucherTranslationFragment = gql` + fragment VoucherTranslationFragment on Voucher { + id + name + translation(languageCode: $language) { + id + language { + code + language + } + name + } + } +`; +export const shippingMethodTranslationFragment = gql` + fragment ShippingMethodTranslationFragment on ShippingMethod { + id + name + translation(languageCode: $language) { + id + language { + code + language + } + name + } + } +`; +export const pageTranslationFragment = gql` + fragment PageTranslationFragment on Page { + id + contentJson + seoDescription + seoTitle + title + + translation(languageCode: $language) { + id + contentJson + seoDescription + seoTitle + title + language { + code + language + } + } + } +`; +export const pageTranslatableFragment = gql` + fragment PageTranslatableFragment on PageTranslatableContent { + id + contentJson + seoDescription + seoTitle + title + + translation(languageCode: $language) { + id + contentJson + seoDescription + seoTitle + title + language { + code + language + } + } + } +`; +export const productTypeTranslationFragment = gql` + fragment AttributeTranslationFragment on Attribute { + id + name + translation(languageCode: $language) { + id + name + } + values { + id + name + translation(languageCode: $language) { + id + name + } + } + } + fragment ProductTypeTranslationFragment on ProductType { + id + name + productAttributes { + ...AttributeTranslationFragment + } + variantAttributes { + ...AttributeTranslationFragment + } + } +`; diff --git a/src/customers/types/AccountErrorFragment.ts b/src/fragments/types/AccountErrorFragment.ts similarity index 100% rename from src/customers/types/AccountErrorFragment.ts rename to src/fragments/types/AccountErrorFragment.ts diff --git a/src/orders/types/AddressFragment.ts b/src/fragments/types/AddressFragment.ts similarity index 100% rename from src/orders/types/AddressFragment.ts rename to src/fragments/types/AddressFragment.ts diff --git a/src/fragments/types/AppErrorFragment.ts b/src/fragments/types/AppErrorFragment.ts new file mode 100644 index 000000000..2dca654b1 --- /dev/null +++ b/src/fragments/types/AppErrorFragment.ts @@ -0,0 +1,17 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { AppErrorCode, PermissionEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL fragment: AppErrorFragment +// ==================================================== + +export interface AppErrorFragment { + __typename: "AppError"; + field: string | null; + message: string | null; + code: AppErrorCode; + permissions: PermissionEnum[] | null; +} diff --git a/src/fragments/types/AppFragment.ts b/src/fragments/types/AppFragment.ts new file mode 100644 index 000000000..ef2f53128 --- /dev/null +++ b/src/fragments/types/AppFragment.ts @@ -0,0 +1,61 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { AppTypeEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL fragment: AppFragment +// ==================================================== + +export interface AppFragment_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface AppFragment_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface AppFragment_tokens { + __typename: "AppToken"; + authToken: string | null; + id: string; + name: string | null; +} + +export interface AppFragment_webhooks_app { + __typename: "App"; + id: string; + name: string | null; +} + +export interface AppFragment_webhooks { + __typename: "Webhook"; + id: string; + name: string; + isActive: boolean; + app: AppFragment_webhooks_app; +} + +export interface AppFragment { + __typename: "App"; + id: string; + name: string | null; + created: any | null; + isActive: boolean | null; + type: AppTypeEnum | null; + homepageUrl: string | null; + appUrl: string | null; + configurationUrl: string | null; + supportUrl: string | null; + version: string | null; + accessToken: string | null; + privateMetadata: (AppFragment_privateMetadata | null)[]; + metadata: (AppFragment_metadata | null)[]; + tokens: (AppFragment_tokens | null)[] | null; + webhooks: (AppFragment_webhooks | null)[] | null; +} diff --git a/src/attributes/types/AttributeDetailsFragment.ts b/src/fragments/types/AttributeDetailsFragment.ts similarity index 72% rename from src/attributes/types/AttributeDetailsFragment.ts rename to src/fragments/types/AttributeDetailsFragment.ts index 11a22408b..6d9faedd0 100644 --- a/src/attributes/types/AttributeDetailsFragment.ts +++ b/src/fragments/types/AttributeDetailsFragment.ts @@ -8,6 +8,18 @@ import { AttributeInputTypeEnum, AttributeValueType } from "./../../types/global // GraphQL fragment: AttributeDetailsFragment // ==================================================== +export interface AttributeDetailsFragment_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface AttributeDetailsFragment_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface AttributeDetailsFragment_values { __typename: "AttributeValue"; id: string; @@ -24,6 +36,8 @@ export interface AttributeDetailsFragment { visibleInStorefront: boolean; filterableInDashboard: boolean; filterableInStorefront: boolean; + metadata: (AttributeDetailsFragment_metadata | null)[]; + privateMetadata: (AttributeDetailsFragment_privateMetadata | null)[]; availableInGrid: boolean; inputType: AttributeInputTypeEnum | null; storefrontSearchPosition: number; diff --git a/src/attributes/types/AttributeFragment.ts b/src/fragments/types/AttributeFragment.ts similarity index 100% rename from src/attributes/types/AttributeFragment.ts rename to src/fragments/types/AttributeFragment.ts diff --git a/src/translations/types/AttributeTranslationFragment.ts b/src/fragments/types/AttributeTranslationFragment.ts similarity index 100% rename from src/translations/types/AttributeTranslationFragment.ts rename to src/fragments/types/AttributeTranslationFragment.ts diff --git a/src/products/types/BulkProductErrorFragment.ts b/src/fragments/types/BulkProductErrorFragment.ts similarity index 100% rename from src/products/types/BulkProductErrorFragment.ts rename to src/fragments/types/BulkProductErrorFragment.ts diff --git a/src/products/types/BulkStockErrorFragment.ts b/src/fragments/types/BulkStockErrorFragment.ts similarity index 100% rename from src/products/types/BulkStockErrorFragment.ts rename to src/fragments/types/BulkStockErrorFragment.ts diff --git a/src/categories/types/CategoryDetailsFragment.ts b/src/fragments/types/CategoryDetailsFragment.ts similarity index 67% rename from src/categories/types/CategoryDetailsFragment.ts rename to src/fragments/types/CategoryDetailsFragment.ts index 111a0e6c2..49e5640ea 100644 --- a/src/categories/types/CategoryDetailsFragment.ts +++ b/src/fragments/types/CategoryDetailsFragment.ts @@ -6,6 +6,18 @@ // GraphQL fragment: CategoryDetailsFragment // ==================================================== +export interface CategoryDetailsFragment_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface CategoryDetailsFragment_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface CategoryDetailsFragment_backgroundImage { __typename: "Image"; alt: string | null; @@ -20,6 +32,8 @@ export interface CategoryDetailsFragment_parent { export interface CategoryDetailsFragment { __typename: "Category"; id: string; + metadata: (CategoryDetailsFragment_metadata | null)[]; + privateMetadata: (CategoryDetailsFragment_privateMetadata | null)[]; backgroundImage: CategoryDetailsFragment_backgroundImage | null; name: string; descriptionJson: any; diff --git a/src/categories/types/CategoryFragment.ts b/src/fragments/types/CategoryFragment.ts similarity index 100% rename from src/categories/types/CategoryFragment.ts rename to src/fragments/types/CategoryFragment.ts diff --git a/src/translations/types/CategoryTranslationFragment.ts b/src/fragments/types/CategoryTranslationFragment.ts similarity index 100% rename from src/translations/types/CategoryTranslationFragment.ts rename to src/fragments/types/CategoryTranslationFragment.ts diff --git a/src/collections/types/CollectionDetailsFragment.ts b/src/fragments/types/CollectionDetailsFragment.ts similarity index 65% rename from src/collections/types/CollectionDetailsFragment.ts rename to src/fragments/types/CollectionDetailsFragment.ts index 24ae24d14..d2dc154a8 100644 --- a/src/collections/types/CollectionDetailsFragment.ts +++ b/src/fragments/types/CollectionDetailsFragment.ts @@ -6,6 +6,18 @@ // GraphQL fragment: CollectionDetailsFragment // ==================================================== +export interface CollectionDetailsFragment_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface CollectionDetailsFragment_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface CollectionDetailsFragment_backgroundImage { __typename: "Image"; alt: string | null; @@ -17,6 +29,8 @@ export interface CollectionDetailsFragment { id: string; isPublished: boolean; name: string; + metadata: (CollectionDetailsFragment_metadata | null)[]; + privateMetadata: (CollectionDetailsFragment_privateMetadata | null)[]; backgroundImage: CollectionDetailsFragment_backgroundImage | null; descriptionJson: any; publicationDate: any | null; diff --git a/src/collections/types/CollectionFragment.ts b/src/fragments/types/CollectionFragment.ts similarity index 100% rename from src/collections/types/CollectionFragment.ts rename to src/fragments/types/CollectionFragment.ts diff --git a/src/collections/types/CollectionProductFragment.ts b/src/fragments/types/CollectionProductFragment.ts similarity index 100% rename from src/collections/types/CollectionProductFragment.ts rename to src/fragments/types/CollectionProductFragment.ts diff --git a/src/translations/types/CollectionTranslationFragment.ts b/src/fragments/types/CollectionTranslationFragment.ts similarity index 100% rename from src/translations/types/CollectionTranslationFragment.ts rename to src/fragments/types/CollectionTranslationFragment.ts diff --git a/src/taxes/types/CountryFragment.ts b/src/fragments/types/CountryFragment.ts similarity index 100% rename from src/taxes/types/CountryFragment.ts rename to src/fragments/types/CountryFragment.ts diff --git a/src/taxes/types/CountryWithTaxesFragment.ts b/src/fragments/types/CountryWithTaxesFragment.ts similarity index 100% rename from src/taxes/types/CountryWithTaxesFragment.ts rename to src/fragments/types/CountryWithTaxesFragment.ts diff --git a/src/customers/types/CustomerAddressesFragment.ts b/src/fragments/types/CustomerAddressesFragment.ts similarity index 100% rename from src/customers/types/CustomerAddressesFragment.ts rename to src/fragments/types/CustomerAddressesFragment.ts diff --git a/src/customers/types/CustomerDetailsFragment.ts b/src/fragments/types/CustomerDetailsFragment.ts similarity index 100% rename from src/customers/types/CustomerDetailsFragment.ts rename to src/fragments/types/CustomerDetailsFragment.ts diff --git a/src/customers/types/CustomerFragment.ts b/src/fragments/types/CustomerFragment.ts similarity index 100% rename from src/customers/types/CustomerFragment.ts rename to src/fragments/types/CustomerFragment.ts diff --git a/src/discounts/types/DiscountErrorFragment.ts b/src/fragments/types/DiscountErrorFragment.ts similarity index 100% rename from src/discounts/types/DiscountErrorFragment.ts rename to src/fragments/types/DiscountErrorFragment.ts diff --git a/src/siteSettings/types/ShopErrorFragment.ts b/src/fragments/types/ExportErrorFragment.ts similarity index 56% rename from src/siteSettings/types/ShopErrorFragment.ts rename to src/fragments/types/ExportErrorFragment.ts index ae705f05f..7b421283b 100644 --- a/src/siteSettings/types/ShopErrorFragment.ts +++ b/src/fragments/types/ExportErrorFragment.ts @@ -2,14 +2,14 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { ShopErrorCode } from "./../../types/globalTypes"; +import { ExportErrorCode } from "./../../types/globalTypes"; // ==================================================== -// GraphQL fragment: ShopErrorFragment +// GraphQL fragment: ExportErrorFragment // ==================================================== -export interface ShopErrorFragment { - __typename: "ShopError"; - code: ShopErrorCode; +export interface ExportErrorFragment { + __typename: "ExportError"; + code: ExportErrorCode; field: string | null; } diff --git a/src/fragments/types/ExportFileFragment.ts b/src/fragments/types/ExportFileFragment.ts new file mode 100644 index 000000000..ebc4ae1d6 --- /dev/null +++ b/src/fragments/types/ExportFileFragment.ts @@ -0,0 +1,16 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { JobStatusEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL fragment: ExportFileFragment +// ==================================================== + +export interface ExportFileFragment { + __typename: "ExportFile"; + id: string; + status: JobStatusEnum; + url: string | null; +} diff --git a/src/orders/types/FulfillmentFragment.ts b/src/fragments/types/FulfillmentFragment.ts similarity index 81% rename from src/orders/types/FulfillmentFragment.ts rename to src/fragments/types/FulfillmentFragment.ts index e8ac634b5..ad8146360 100644 --- a/src/orders/types/FulfillmentFragment.ts +++ b/src/fragments/types/FulfillmentFragment.ts @@ -8,6 +8,18 @@ import { FulfillmentStatus } from "./../../types/globalTypes"; // GraphQL fragment: FulfillmentFragment // ==================================================== +export interface FulfillmentFragment_lines_orderLine_variant_product { + __typename: "Product"; + isAvailableForPurchase: boolean | null; + isPublished: boolean; +} + +export interface FulfillmentFragment_lines_orderLine_variant { + __typename: "ProductVariant"; + product: FulfillmentFragment_lines_orderLine_variant_product; + quantityAvailable: number; +} + export interface FulfillmentFragment_lines_orderLine_unitPrice_gross { __typename: "Money"; amount: number; @@ -35,6 +47,7 @@ export interface FulfillmentFragment_lines_orderLine { __typename: "OrderLine"; id: string; isShippingRequired: boolean; + variant: FulfillmentFragment_lines_orderLine_variant | null; productName: string; productSku: string; quantity: number; diff --git a/src/fragments/types/InvoiceErrorFragment.ts b/src/fragments/types/InvoiceErrorFragment.ts new file mode 100644 index 000000000..6f7fdd502 --- /dev/null +++ b/src/fragments/types/InvoiceErrorFragment.ts @@ -0,0 +1,15 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { InvoiceErrorCode } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL fragment: InvoiceErrorFragment +// ==================================================== + +export interface InvoiceErrorFragment { + __typename: "InvoiceError"; + code: InvoiceErrorCode; + field: string | null; +} diff --git a/src/fragments/types/InvoiceFragment.ts b/src/fragments/types/InvoiceFragment.ts new file mode 100644 index 000000000..1959df4ab --- /dev/null +++ b/src/fragments/types/InvoiceFragment.ts @@ -0,0 +1,18 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { JobStatusEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL fragment: InvoiceFragment +// ==================================================== + +export interface InvoiceFragment { + __typename: "Invoice"; + id: string; + number: string | null; + createdAt: any; + url: string | null; + status: JobStatusEnum; +} diff --git a/src/navigation/types/MenuDetailsFragment.ts b/src/fragments/types/MenuDetailsFragment.ts similarity index 100% rename from src/navigation/types/MenuDetailsFragment.ts rename to src/fragments/types/MenuDetailsFragment.ts diff --git a/src/navigation/types/MenuErrorFragment.ts b/src/fragments/types/MenuErrorFragment.ts similarity index 100% rename from src/navigation/types/MenuErrorFragment.ts rename to src/fragments/types/MenuErrorFragment.ts diff --git a/src/navigation/types/MenuFragment.ts b/src/fragments/types/MenuFragment.ts similarity index 100% rename from src/navigation/types/MenuFragment.ts rename to src/fragments/types/MenuFragment.ts diff --git a/src/navigation/types/MenuItemFragment.ts b/src/fragments/types/MenuItemFragment.ts similarity index 100% rename from src/navigation/types/MenuItemFragment.ts rename to src/fragments/types/MenuItemFragment.ts diff --git a/src/navigation/types/MenuItemNestedFragment.ts b/src/fragments/types/MenuItemNestedFragment.ts similarity index 100% rename from src/navigation/types/MenuItemNestedFragment.ts rename to src/fragments/types/MenuItemNestedFragment.ts diff --git a/src/fragments/types/Metadata.ts b/src/fragments/types/Metadata.ts new file mode 100644 index 000000000..27a384243 --- /dev/null +++ b/src/fragments/types/Metadata.ts @@ -0,0 +1,25 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL fragment: Metadata +// ==================================================== + +export interface Metadata_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface Metadata_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface Metadata { + __typename: "ServiceAccount" | "App" | "Product" | "ProductType" | "Attribute" | "Category" | "ProductVariant" | "DigitalContent" | "Collection" | "User" | "Checkout" | "Order" | "Fulfillment" | "Invoice"; + metadata: (Metadata_metadata | null)[]; + privateMetadata: (Metadata_privateMetadata | null)[]; +} diff --git a/src/fragments/types/MetadataErrorFragment.ts b/src/fragments/types/MetadataErrorFragment.ts new file mode 100644 index 000000000..7c669c123 --- /dev/null +++ b/src/fragments/types/MetadataErrorFragment.ts @@ -0,0 +1,15 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { MetadataErrorCode } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL fragment: MetadataErrorFragment +// ==================================================== + +export interface MetadataErrorFragment { + __typename: "MetadataError"; + code: MetadataErrorCode; + field: string | null; +} diff --git a/src/fragments/types/MetadataFragment.ts b/src/fragments/types/MetadataFragment.ts new file mode 100644 index 000000000..4c1b70245 --- /dev/null +++ b/src/fragments/types/MetadataFragment.ts @@ -0,0 +1,25 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL fragment: MetadataFragment +// ==================================================== + +export interface MetadataFragment_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface MetadataFragment_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface MetadataFragment { + __typename: "ServiceAccount" | "App" | "Product" | "ProductType" | "Attribute" | "Category" | "ProductVariant" | "DigitalContent" | "Collection" | "User" | "Checkout" | "Order" | "Fulfillment" | "Invoice"; + metadata: (MetadataFragment_metadata | null)[]; + privateMetadata: (MetadataFragment_privateMetadata | null)[]; +} diff --git a/src/services/types/ServiceFragment.ts b/src/fragments/types/MetadataItem.ts similarity index 57% rename from src/services/types/ServiceFragment.ts rename to src/fragments/types/MetadataItem.ts index 5c0e96fec..484b4f9dc 100644 --- a/src/services/types/ServiceFragment.ts +++ b/src/fragments/types/MetadataItem.ts @@ -3,12 +3,11 @@ // This file was automatically generated and should not be edited. // ==================================================== -// GraphQL fragment: ServiceFragment +// GraphQL fragment: MetadataItem // ==================================================== -export interface ServiceFragment { - __typename: "ServiceAccount"; - id: string; - name: string | null; - isActive: boolean | null; +export interface MetadataItem { + __typename: "MetadataItem"; + key: string; + value: string; } diff --git a/src/products/types/Money.ts b/src/fragments/types/Money.ts similarity index 100% rename from src/products/types/Money.ts rename to src/fragments/types/Money.ts diff --git a/src/orders/types/OrderDetailsFragment.ts b/src/fragments/types/OrderDetailsFragment.ts similarity index 80% rename from src/orders/types/OrderDetailsFragment.ts rename to src/fragments/types/OrderDetailsFragment.ts index e01d64bbb..638225326 100644 --- a/src/orders/types/OrderDetailsFragment.ts +++ b/src/fragments/types/OrderDetailsFragment.ts @@ -2,12 +2,24 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus, OrderAction } from "./../../types/globalTypes"; +import { OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus, OrderAction, JobStatusEnum } from "./../../types/globalTypes"; // ==================================================== // GraphQL fragment: OrderDetailsFragment // ==================================================== +export interface OrderDetailsFragment_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface OrderDetailsFragment_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface OrderDetailsFragment_billingAddress_country { __typename: "CountryDisplay"; code: string; @@ -43,12 +55,25 @@ export interface OrderDetailsFragment_events { date: any | null; email: string | null; emailType: OrderEventsEmailsEnum | null; + invoiceNumber: string | null; message: string | null; quantity: number | null; type: OrderEventsEnum | null; user: OrderDetailsFragment_events_user | null; } +export interface OrderDetailsFragment_fulfillments_lines_orderLine_variant_product { + __typename: "Product"; + isAvailableForPurchase: boolean | null; + isPublished: boolean; +} + +export interface OrderDetailsFragment_fulfillments_lines_orderLine_variant { + __typename: "ProductVariant"; + product: OrderDetailsFragment_fulfillments_lines_orderLine_variant_product; + quantityAvailable: number; +} + export interface OrderDetailsFragment_fulfillments_lines_orderLine_unitPrice_gross { __typename: "Money"; amount: number; @@ -76,6 +101,7 @@ export interface OrderDetailsFragment_fulfillments_lines_orderLine { __typename: "OrderLine"; id: string; isShippingRequired: boolean; + variant: OrderDetailsFragment_fulfillments_lines_orderLine_variant | null; productName: string; productSku: string; quantity: number; @@ -107,6 +133,18 @@ export interface OrderDetailsFragment_fulfillments { warehouse: OrderDetailsFragment_fulfillments_warehouse | null; } +export interface OrderDetailsFragment_lines_variant_product { + __typename: "Product"; + isAvailableForPurchase: boolean | null; + isPublished: boolean; +} + +export interface OrderDetailsFragment_lines_variant { + __typename: "ProductVariant"; + product: OrderDetailsFragment_lines_variant_product; + quantityAvailable: number; +} + export interface OrderDetailsFragment_lines_unitPrice_gross { __typename: "Money"; amount: number; @@ -134,6 +172,7 @@ export interface OrderDetailsFragment_lines { __typename: "OrderLine"; id: string; isShippingRequired: boolean; + variant: OrderDetailsFragment_lines_variant | null; productName: string; productSku: string; quantity: number; @@ -240,9 +279,26 @@ export interface OrderDetailsFragment_availableShippingMethods { price: OrderDetailsFragment_availableShippingMethods_price | null; } +export interface OrderDetailsFragment_discount { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDetailsFragment_invoices { + __typename: "Invoice"; + id: string; + number: string | null; + createdAt: any; + url: string | null; + status: JobStatusEnum; +} + export interface OrderDetailsFragment { __typename: "Order"; id: string; + metadata: (OrderDetailsFragment_metadata | null)[]; + privateMetadata: (OrderDetailsFragment_privateMetadata | null)[]; billingAddress: OrderDetailsFragment_billingAddress | null; canFinalize: boolean; created: any; @@ -265,4 +321,6 @@ export interface OrderDetailsFragment { user: OrderDetailsFragment_user | null; userEmail: string | null; availableShippingMethods: (OrderDetailsFragment_availableShippingMethods | null)[] | null; + discount: OrderDetailsFragment_discount | null; + invoices: (OrderDetailsFragment_invoices | null)[] | null; } diff --git a/src/orders/types/OrderErrorFragment.ts b/src/fragments/types/OrderErrorFragment.ts similarity index 100% rename from src/orders/types/OrderErrorFragment.ts rename to src/fragments/types/OrderErrorFragment.ts diff --git a/src/orders/types/OrderEventFragment.ts b/src/fragments/types/OrderEventFragment.ts similarity index 95% rename from src/orders/types/OrderEventFragment.ts rename to src/fragments/types/OrderEventFragment.ts index 324d3d958..4331d9cd1 100644 --- a/src/orders/types/OrderEventFragment.ts +++ b/src/fragments/types/OrderEventFragment.ts @@ -21,6 +21,7 @@ export interface OrderEventFragment { date: any | null; email: string | null; emailType: OrderEventsEmailsEnum | null; + invoiceNumber: string | null; message: string | null; quantity: number | null; type: OrderEventsEnum | null; diff --git a/src/orders/types/OrderLineFragment.ts b/src/fragments/types/OrderLineFragment.ts similarity index 75% rename from src/orders/types/OrderLineFragment.ts rename to src/fragments/types/OrderLineFragment.ts index 725832671..8e67fce9f 100644 --- a/src/orders/types/OrderLineFragment.ts +++ b/src/fragments/types/OrderLineFragment.ts @@ -6,6 +6,18 @@ // GraphQL fragment: OrderLineFragment // ==================================================== +export interface OrderLineFragment_variant_product { + __typename: "Product"; + isAvailableForPurchase: boolean | null; + isPublished: boolean; +} + +export interface OrderLineFragment_variant { + __typename: "ProductVariant"; + product: OrderLineFragment_variant_product; + quantityAvailable: number; +} + export interface OrderLineFragment_unitPrice_gross { __typename: "Money"; amount: number; @@ -33,6 +45,7 @@ export interface OrderLineFragment { __typename: "OrderLine"; id: string; isShippingRequired: boolean; + variant: OrderLineFragment_variant | null; productName: string; productSku: string; quantity: number; diff --git a/src/pages/types/PageDetailsFragment.ts b/src/fragments/types/PageDetailsFragment.ts similarity index 100% rename from src/pages/types/PageDetailsFragment.ts rename to src/fragments/types/PageDetailsFragment.ts diff --git a/src/pages/types/PageErrorFragment.ts b/src/fragments/types/PageErrorFragment.ts similarity index 100% rename from src/pages/types/PageErrorFragment.ts rename to src/fragments/types/PageErrorFragment.ts diff --git a/src/pages/types/PageFragment.ts b/src/fragments/types/PageFragment.ts similarity index 100% rename from src/pages/types/PageFragment.ts rename to src/fragments/types/PageFragment.ts diff --git a/src/types/PageInfoFragment.ts b/src/fragments/types/PageInfoFragment.ts similarity index 100% rename from src/types/PageInfoFragment.ts rename to src/fragments/types/PageInfoFragment.ts diff --git a/src/translations/types/PageTranslatableFragment.ts b/src/fragments/types/PageTranslatableFragment.ts similarity index 100% rename from src/translations/types/PageTranslatableFragment.ts rename to src/fragments/types/PageTranslatableFragment.ts diff --git a/src/translations/types/PageTranslationFragment.ts b/src/fragments/types/PageTranslationFragment.ts similarity index 100% rename from src/translations/types/PageTranslationFragment.ts rename to src/fragments/types/PageTranslationFragment.ts diff --git a/src/permissionGroups/types/PermissionFragment.ts b/src/fragments/types/PermissionFragment.ts similarity index 100% rename from src/permissionGroups/types/PermissionFragment.ts rename to src/fragments/types/PermissionFragment.ts diff --git a/src/permissionGroups/types/PermissionGroupDetailsFragment.ts b/src/fragments/types/PermissionGroupDetailsFragment.ts similarity index 100% rename from src/permissionGroups/types/PermissionGroupDetailsFragment.ts rename to src/fragments/types/PermissionGroupDetailsFragment.ts diff --git a/src/permissionGroups/types/PermissionGroupErrorFragment.ts b/src/fragments/types/PermissionGroupErrorFragment.ts similarity index 100% rename from src/permissionGroups/types/PermissionGroupErrorFragment.ts rename to src/fragments/types/PermissionGroupErrorFragment.ts diff --git a/src/permissionGroups/types/PermissionGroupFragment.ts b/src/fragments/types/PermissionGroupFragment.ts similarity index 100% rename from src/permissionGroups/types/PermissionGroupFragment.ts rename to src/fragments/types/PermissionGroupFragment.ts diff --git a/src/fragments/types/PluginErrorFragment.ts b/src/fragments/types/PluginErrorFragment.ts new file mode 100644 index 000000000..ce557f60e --- /dev/null +++ b/src/fragments/types/PluginErrorFragment.ts @@ -0,0 +1,15 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { PluginErrorCode } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL fragment: PluginErrorFragment +// ==================================================== + +export interface PluginErrorFragment { + __typename: "PluginError"; + code: PluginErrorCode; + field: string | null; +} diff --git a/src/plugins/types/PluginFragment.ts b/src/fragments/types/PluginFragment.ts similarity index 100% rename from src/plugins/types/PluginFragment.ts rename to src/fragments/types/PluginFragment.ts diff --git a/src/plugins/types/PluginsDetailsFragment.ts b/src/fragments/types/PluginsDetailsFragment.ts similarity index 100% rename from src/plugins/types/PluginsDetailsFragment.ts rename to src/fragments/types/PluginsDetailsFragment.ts diff --git a/src/products/types/Product.ts b/src/fragments/types/Product.ts similarity index 76% rename from src/products/types/Product.ts rename to src/fragments/types/Product.ts index 370fdc3d0..6921ecc67 100644 --- a/src/products/types/Product.ts +++ b/src/fragments/types/Product.ts @@ -2,7 +2,7 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { AttributeInputTypeEnum } from "./../../types/globalTypes"; +import { AttributeInputTypeEnum, WeightUnitsEnum } from "./../../types/globalTypes"; // ==================================================== // GraphQL fragment: Product @@ -60,6 +60,51 @@ export interface Product_productType { hasVariants: boolean; } +export interface Product_pricing_priceRangeUndiscounted_start_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface Product_pricing_priceRangeUndiscounted_start { + __typename: "TaxedMoney"; + gross: Product_pricing_priceRangeUndiscounted_start_gross; +} + +export interface Product_pricing_priceRangeUndiscounted_stop_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface Product_pricing_priceRangeUndiscounted_stop { + __typename: "TaxedMoney"; + gross: Product_pricing_priceRangeUndiscounted_stop_gross; +} + +export interface Product_pricing_priceRangeUndiscounted { + __typename: "TaxedMoneyRange"; + start: Product_pricing_priceRangeUndiscounted_start | null; + stop: Product_pricing_priceRangeUndiscounted_stop | null; +} + +export interface Product_pricing { + __typename: "ProductPricingInfo"; + priceRangeUndiscounted: Product_pricing_priceRangeUndiscounted | null; +} + +export interface Product_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface Product_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface Product_category { __typename: "Category"; id: string; @@ -72,12 +117,6 @@ export interface Product_collections { name: string; } -export interface Product_basePrice { - __typename: "Money"; - amount: number; - currency: string; -} - export interface Product_margin { __typename: "Margin"; start: number | null; @@ -102,39 +141,6 @@ export interface Product_purchaseCost { stop: Product_purchaseCost_stop | null; } -export interface Product_pricing_priceRange_start_net { - __typename: "Money"; - amount: number; - currency: string; -} - -export interface Product_pricing_priceRange_start { - __typename: "TaxedMoney"; - net: Product_pricing_priceRange_start_net; -} - -export interface Product_pricing_priceRange_stop_net { - __typename: "Money"; - amount: number; - currency: string; -} - -export interface Product_pricing_priceRange_stop { - __typename: "TaxedMoney"; - net: Product_pricing_priceRange_stop_net; -} - -export interface Product_pricing_priceRange { - __typename: "TaxedMoneyRange"; - start: Product_pricing_priceRange_start | null; - stop: Product_pricing_priceRange_stop | null; -} - -export interface Product_pricing { - __typename: "ProductPricingInfo"; - priceRange: Product_pricing_priceRange | null; -} - export interface Product_images { __typename: "ProductImage"; id: string; @@ -143,7 +149,7 @@ export interface Product_images { url: string; } -export interface Product_variants_priceOverride { +export interface Product_variants_price { __typename: "Money"; amount: number; currency: string; @@ -163,27 +169,20 @@ export interface Product_variants_stocks { warehouse: Product_variants_stocks_warehouse; } -export interface Product_variants_weight { - __typename: "Weight"; - unit: string; - value: number; -} - export interface Product_variants { __typename: "ProductVariant"; id: string; sku: string; name: string; - priceOverride: Product_variants_priceOverride | null; + price: Product_variants_price | null; margin: number | null; stocks: (Product_variants_stocks | null)[] | null; trackInventory: boolean; - weight: Product_variants_weight | null; } export interface Product_weight { __typename: "Weight"; - unit: string; + unit: WeightUnitsEnum; value: number; } @@ -192,21 +191,25 @@ export interface Product { id: string; attributes: Product_attributes[]; productType: Product_productType; + pricing: Product_pricing | null; + metadata: (Product_metadata | null)[]; + privateMetadata: (Product_privateMetadata | null)[]; name: string; descriptionJson: any; seoTitle: string | null; seoDescription: string | null; category: Product_category | null; collections: (Product_collections | null)[] | null; - basePrice: Product_basePrice | null; margin: Product_margin | null; purchaseCost: Product_purchaseCost | null; + isAvailableForPurchase: boolean | null; isAvailable: boolean | null; isPublished: boolean; chargeTaxes: boolean; publicationDate: any | null; - pricing: Product_pricing | null; images: (Product_images | null)[] | null; variants: (Product_variants | null)[] | null; weight: Product_weight | null; + availableForPurchase: any | null; + visibleInListings: boolean; } diff --git a/src/attributes/types/ProductErrorFragment.ts b/src/fragments/types/ProductErrorFragment.ts similarity index 100% rename from src/attributes/types/ProductErrorFragment.ts rename to src/fragments/types/ProductErrorFragment.ts diff --git a/src/products/types/ProductFragment.ts b/src/fragments/types/ProductFragment.ts similarity index 81% rename from src/products/types/ProductFragment.ts rename to src/fragments/types/ProductFragment.ts index 61306e93d..c7ab4b127 100644 --- a/src/products/types/ProductFragment.ts +++ b/src/fragments/types/ProductFragment.ts @@ -11,16 +11,11 @@ export interface ProductFragment_thumbnail { url: string; } -export interface ProductFragment_basePrice { - __typename: "Money"; - amount: number; - currency: string; -} - export interface ProductFragment_productType { __typename: "ProductType"; id: string; name: string; + hasVariants: boolean; } export interface ProductFragment { @@ -30,6 +25,5 @@ export interface ProductFragment { thumbnail: ProductFragment_thumbnail | null; isAvailable: boolean | null; isPublished: boolean; - basePrice: ProductFragment_basePrice | null; productType: ProductFragment_productType; } diff --git a/src/products/types/ProductImageFragment.ts b/src/fragments/types/ProductImageFragment.ts similarity index 100% rename from src/products/types/ProductImageFragment.ts rename to src/fragments/types/ProductImageFragment.ts diff --git a/src/translations/types/ProductTranslationFragment.ts b/src/fragments/types/ProductTranslationFragment.ts similarity index 100% rename from src/translations/types/ProductTranslationFragment.ts rename to src/fragments/types/ProductTranslationFragment.ts diff --git a/src/productTypes/types/ProductTypeDetailsFragment.ts b/src/fragments/types/ProductTypeDetailsFragment.ts similarity index 75% rename from src/productTypes/types/ProductTypeDetailsFragment.ts rename to src/fragments/types/ProductTypeDetailsFragment.ts index 87cd9d547..3c9851cd3 100644 --- a/src/productTypes/types/ProductTypeDetailsFragment.ts +++ b/src/fragments/types/ProductTypeDetailsFragment.ts @@ -2,6 +2,8 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. +import { WeightUnitsEnum } from "./../../types/globalTypes"; + // ==================================================== // GraphQL fragment: ProductTypeDetailsFragment // ==================================================== @@ -12,6 +14,18 @@ export interface ProductTypeDetailsFragment_taxType { taxCode: string | null; } +export interface ProductTypeDetailsFragment_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface ProductTypeDetailsFragment_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface ProductTypeDetailsFragment_productAttributes { __typename: "Attribute"; id: string; @@ -34,7 +48,7 @@ export interface ProductTypeDetailsFragment_variantAttributes { export interface ProductTypeDetailsFragment_weight { __typename: "Weight"; - unit: string; + unit: WeightUnitsEnum; value: number; } @@ -45,6 +59,8 @@ export interface ProductTypeDetailsFragment { hasVariants: boolean; isShippingRequired: boolean; taxType: ProductTypeDetailsFragment_taxType | null; + metadata: (ProductTypeDetailsFragment_metadata | null)[]; + privateMetadata: (ProductTypeDetailsFragment_privateMetadata | null)[]; productAttributes: (ProductTypeDetailsFragment_productAttributes | null)[] | null; variantAttributes: (ProductTypeDetailsFragment_variantAttributes | null)[] | null; weight: ProductTypeDetailsFragment_weight | null; diff --git a/src/productTypes/types/ProductTypeFragment.ts b/src/fragments/types/ProductTypeFragment.ts similarity index 100% rename from src/productTypes/types/ProductTypeFragment.ts rename to src/fragments/types/ProductTypeFragment.ts diff --git a/src/translations/types/ProductTypeTranslationFragment.ts b/src/fragments/types/ProductTypeTranslationFragment.ts similarity index 100% rename from src/translations/types/ProductTypeTranslationFragment.ts rename to src/fragments/types/ProductTypeTranslationFragment.ts diff --git a/src/products/types/ProductVariant.ts b/src/fragments/types/ProductVariant.ts similarity index 85% rename from src/products/types/ProductVariant.ts rename to src/fragments/types/ProductVariant.ts index 78926e644..0f7fcf4fc 100644 --- a/src/products/types/ProductVariant.ts +++ b/src/fragments/types/ProductVariant.ts @@ -2,10 +2,24 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. +import { WeightUnitsEnum } from "./../../types/globalTypes"; + // ==================================================== // GraphQL fragment: ProductVariant // ==================================================== +export interface ProductVariant_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface ProductVariant_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface ProductVariant_attributes_attribute_values { __typename: "AttributeValue"; id: string; @@ -47,7 +61,7 @@ export interface ProductVariant_images { url: string; } -export interface ProductVariant_priceOverride { +export interface ProductVariant_price { __typename: "Money"; amount: number; currency: string; @@ -105,18 +119,20 @@ export interface ProductVariant_stocks { export interface ProductVariant_weight { __typename: "Weight"; - unit: string; + unit: WeightUnitsEnum; value: number; } export interface ProductVariant { __typename: "ProductVariant"; id: string; + metadata: (ProductVariant_metadata | null)[]; + privateMetadata: (ProductVariant_privateMetadata | null)[]; attributes: ProductVariant_attributes[]; costPrice: ProductVariant_costPrice | null; images: (ProductVariant_images | null)[] | null; name: string; - priceOverride: ProductVariant_priceOverride | null; + price: ProductVariant_price | null; product: ProductVariant_product; sku: string; stocks: (ProductVariant_stocks | null)[] | null; diff --git a/src/products/types/ProductVariantAttributesFragment.ts b/src/fragments/types/ProductVariantAttributesFragment.ts similarity index 62% rename from src/products/types/ProductVariantAttributesFragment.ts rename to src/fragments/types/ProductVariantAttributesFragment.ts index 02d1e7847..0349fd386 100644 --- a/src/products/types/ProductVariantAttributesFragment.ts +++ b/src/fragments/types/ProductVariantAttributesFragment.ts @@ -58,9 +58,43 @@ export interface ProductVariantAttributesFragment_productType { variantAttributes: (ProductVariantAttributesFragment_productType_variantAttributes | null)[] | null; } +export interface ProductVariantAttributesFragment_pricing_priceRangeUndiscounted_start_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ProductVariantAttributesFragment_pricing_priceRangeUndiscounted_start { + __typename: "TaxedMoney"; + gross: ProductVariantAttributesFragment_pricing_priceRangeUndiscounted_start_gross; +} + +export interface ProductVariantAttributesFragment_pricing_priceRangeUndiscounted_stop_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ProductVariantAttributesFragment_pricing_priceRangeUndiscounted_stop { + __typename: "TaxedMoney"; + gross: ProductVariantAttributesFragment_pricing_priceRangeUndiscounted_stop_gross; +} + +export interface ProductVariantAttributesFragment_pricing_priceRangeUndiscounted { + __typename: "TaxedMoneyRange"; + start: ProductVariantAttributesFragment_pricing_priceRangeUndiscounted_start | null; + stop: ProductVariantAttributesFragment_pricing_priceRangeUndiscounted_stop | null; +} + +export interface ProductVariantAttributesFragment_pricing { + __typename: "ProductPricingInfo"; + priceRangeUndiscounted: ProductVariantAttributesFragment_pricing_priceRangeUndiscounted | null; +} + export interface ProductVariantAttributesFragment { __typename: "Product"; id: string; attributes: ProductVariantAttributesFragment_attributes[]; productType: ProductVariantAttributesFragment_productType; + pricing: ProductVariantAttributesFragment_pricing | null; } diff --git a/src/discounts/types/SaleDetailsFragment.ts b/src/fragments/types/SaleDetailsFragment.ts similarity index 100% rename from src/discounts/types/SaleDetailsFragment.ts rename to src/fragments/types/SaleDetailsFragment.ts diff --git a/src/discounts/types/SaleFragment.ts b/src/fragments/types/SaleFragment.ts similarity index 100% rename from src/discounts/types/SaleFragment.ts rename to src/fragments/types/SaleFragment.ts diff --git a/src/translations/types/SaleTranslationFragment.ts b/src/fragments/types/SaleTranslationFragment.ts similarity index 100% rename from src/translations/types/SaleTranslationFragment.ts rename to src/fragments/types/SaleTranslationFragment.ts diff --git a/src/shipping/types/ShippingErrorFragment.ts b/src/fragments/types/ShippingErrorFragment.ts similarity index 100% rename from src/shipping/types/ShippingErrorFragment.ts rename to src/fragments/types/ShippingErrorFragment.ts diff --git a/src/shipping/types/ShippingMethodFragment.ts b/src/fragments/types/ShippingMethodFragment.ts similarity index 90% rename from src/shipping/types/ShippingMethodFragment.ts rename to src/fragments/types/ShippingMethodFragment.ts index 0c33ded59..fb3c79e9d 100644 --- a/src/shipping/types/ShippingMethodFragment.ts +++ b/src/fragments/types/ShippingMethodFragment.ts @@ -2,7 +2,7 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { ShippingMethodTypeEnum } from "./../../types/globalTypes"; +import { WeightUnitsEnum, ShippingMethodTypeEnum } from "./../../types/globalTypes"; // ==================================================== // GraphQL fragment: ShippingMethodFragment @@ -16,7 +16,7 @@ export interface ShippingMethodFragment_minimumOrderPrice { export interface ShippingMethodFragment_minimumOrderWeight { __typename: "Weight"; - unit: string; + unit: WeightUnitsEnum; value: number; } @@ -28,7 +28,7 @@ export interface ShippingMethodFragment_maximumOrderPrice { export interface ShippingMethodFragment_maximumOrderWeight { __typename: "Weight"; - unit: string; + unit: WeightUnitsEnum; value: number; } diff --git a/src/translations/types/ShippingMethodTranslationFragment.ts b/src/fragments/types/ShippingMethodTranslationFragment.ts similarity index 100% rename from src/translations/types/ShippingMethodTranslationFragment.ts rename to src/fragments/types/ShippingMethodTranslationFragment.ts diff --git a/src/shipping/types/ShippingZoneDetailsFragment.ts b/src/fragments/types/ShippingZoneDetailsFragment.ts similarity index 94% rename from src/shipping/types/ShippingZoneDetailsFragment.ts rename to src/fragments/types/ShippingZoneDetailsFragment.ts index 13bf1a398..c55177fa9 100644 --- a/src/shipping/types/ShippingZoneDetailsFragment.ts +++ b/src/fragments/types/ShippingZoneDetailsFragment.ts @@ -2,7 +2,7 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { ShippingMethodTypeEnum } from "./../../types/globalTypes"; +import { WeightUnitsEnum, ShippingMethodTypeEnum } from "./../../types/globalTypes"; // ==================================================== // GraphQL fragment: ShippingZoneDetailsFragment @@ -22,7 +22,7 @@ export interface ShippingZoneDetailsFragment_shippingMethods_minimumOrderPrice { export interface ShippingZoneDetailsFragment_shippingMethods_minimumOrderWeight { __typename: "Weight"; - unit: string; + unit: WeightUnitsEnum; value: number; } @@ -34,7 +34,7 @@ export interface ShippingZoneDetailsFragment_shippingMethods_maximumOrderPrice { export interface ShippingZoneDetailsFragment_shippingMethods_maximumOrderWeight { __typename: "Weight"; - unit: string; + unit: WeightUnitsEnum; value: number; } diff --git a/src/shipping/types/ShippingZoneFragment.ts b/src/fragments/types/ShippingZoneFragment.ts similarity index 100% rename from src/shipping/types/ShippingZoneFragment.ts rename to src/fragments/types/ShippingZoneFragment.ts diff --git a/src/collections/types/ShopErrorFragment.ts b/src/fragments/types/ShopErrorFragment.ts similarity index 100% rename from src/collections/types/ShopErrorFragment.ts rename to src/fragments/types/ShopErrorFragment.ts diff --git a/src/siteSettings/types/ShopFragment.ts b/src/fragments/types/ShopFragment.ts similarity index 96% rename from src/siteSettings/types/ShopFragment.ts rename to src/fragments/types/ShopFragment.ts index aaf4326c9..19e601c27 100644 --- a/src/siteSettings/types/ShopFragment.ts +++ b/src/fragments/types/ShopFragment.ts @@ -51,7 +51,7 @@ export interface ShopFragment { __typename: "Shop"; authorizationKeys: (ShopFragment_authorizationKeys | null)[]; companyAddress: ShopFragment_companyAddress | null; - countries: (ShopFragment_countries | null)[]; + countries: ShopFragment_countries[]; customerSetPasswordUrl: string | null; defaultMailSenderAddress: string | null; defaultMailSenderName: string | null; diff --git a/src/taxes/types/ShopTaxesFragment.ts b/src/fragments/types/ShopTaxesFragment.ts similarity index 100% rename from src/taxes/types/ShopTaxesFragment.ts rename to src/fragments/types/ShopTaxesFragment.ts diff --git a/src/staff/types/StaffErrorFragment.ts b/src/fragments/types/StaffErrorFragment.ts similarity index 100% rename from src/staff/types/StaffErrorFragment.ts rename to src/fragments/types/StaffErrorFragment.ts diff --git a/src/staff/types/StaffMemberDetailsFragment.ts b/src/fragments/types/StaffMemberDetailsFragment.ts similarity index 100% rename from src/staff/types/StaffMemberDetailsFragment.ts rename to src/fragments/types/StaffMemberDetailsFragment.ts index a52f00126..22f80c5d8 100644 --- a/src/staff/types/StaffMemberDetailsFragment.ts +++ b/src/fragments/types/StaffMemberDetailsFragment.ts @@ -8,11 +8,6 @@ import { PermissionEnum } from "./../../types/globalTypes"; // GraphQL fragment: StaffMemberDetailsFragment // ==================================================== -export interface StaffMemberDetailsFragment_avatar { - __typename: "Image"; - url: string; -} - export interface StaffMemberDetailsFragment_permissionGroups { __typename: "Group"; id: string; @@ -26,6 +21,11 @@ export interface StaffMemberDetailsFragment_userPermissions { name: string; } +export interface StaffMemberDetailsFragment_avatar { + __typename: "Image"; + url: string; +} + export interface StaffMemberDetailsFragment { __typename: "User"; id: string; @@ -33,7 +33,7 @@ export interface StaffMemberDetailsFragment { firstName: string; isActive: boolean; lastName: string; - avatar: StaffMemberDetailsFragment_avatar | null; permissionGroups: (StaffMemberDetailsFragment_permissionGroups | null)[] | null; userPermissions: (StaffMemberDetailsFragment_userPermissions | null)[] | null; + avatar: StaffMemberDetailsFragment_avatar | null; } diff --git a/src/staff/types/StaffMemberFragment.ts b/src/fragments/types/StaffMemberFragment.ts similarity index 76% rename from src/staff/types/StaffMemberFragment.ts rename to src/fragments/types/StaffMemberFragment.ts index f5098fcdf..118b747c1 100644 --- a/src/staff/types/StaffMemberFragment.ts +++ b/src/fragments/types/StaffMemberFragment.ts @@ -6,11 +6,6 @@ // GraphQL fragment: StaffMemberFragment // ==================================================== -export interface StaffMemberFragment_avatar { - __typename: "Image"; - url: string; -} - export interface StaffMemberFragment { __typename: "User"; id: string; @@ -18,5 +13,4 @@ export interface StaffMemberFragment { firstName: string; isActive: boolean; lastName: string; - avatar: StaffMemberFragment_avatar | null; } diff --git a/src/products/types/StockErrorFragment.ts b/src/fragments/types/StockErrorFragment.ts similarity index 100% rename from src/products/types/StockErrorFragment.ts rename to src/fragments/types/StockErrorFragment.ts diff --git a/src/products/types/StockFragment.ts b/src/fragments/types/StockFragment.ts similarity index 100% rename from src/products/types/StockFragment.ts rename to src/fragments/types/StockFragment.ts diff --git a/src/auth/types/User.ts b/src/fragments/types/User.ts similarity index 100% rename from src/auth/types/User.ts rename to src/fragments/types/User.ts diff --git a/src/discounts/types/VoucherDetailsFragment.ts b/src/fragments/types/VoucherDetailsFragment.ts similarity index 100% rename from src/discounts/types/VoucherDetailsFragment.ts rename to src/fragments/types/VoucherDetailsFragment.ts diff --git a/src/discounts/types/VoucherFragment.ts b/src/fragments/types/VoucherFragment.ts similarity index 100% rename from src/discounts/types/VoucherFragment.ts rename to src/fragments/types/VoucherFragment.ts diff --git a/src/translations/types/VoucherTranslationFragment.ts b/src/fragments/types/VoucherTranslationFragment.ts similarity index 100% rename from src/translations/types/VoucherTranslationFragment.ts rename to src/fragments/types/VoucherTranslationFragment.ts diff --git a/src/warehouses/types/WarehouseDetailsFragment.ts b/src/fragments/types/WarehouseDetailsFragment.ts similarity index 100% rename from src/warehouses/types/WarehouseDetailsFragment.ts rename to src/fragments/types/WarehouseDetailsFragment.ts diff --git a/src/warehouses/types/WarehouseErrorFragment.ts b/src/fragments/types/WarehouseErrorFragment.ts similarity index 100% rename from src/warehouses/types/WarehouseErrorFragment.ts rename to src/fragments/types/WarehouseErrorFragment.ts diff --git a/src/warehouses/types/WarehouseFragment.ts b/src/fragments/types/WarehouseFragment.ts similarity index 100% rename from src/warehouses/types/WarehouseFragment.ts rename to src/fragments/types/WarehouseFragment.ts diff --git a/src/warehouses/types/WarehouseWithShippingFragment.ts b/src/fragments/types/WarehouseWithShippingFragment.ts similarity index 100% rename from src/warehouses/types/WarehouseWithShippingFragment.ts rename to src/fragments/types/WarehouseWithShippingFragment.ts diff --git a/src/webhooks/types/WebhookErrorFragment.ts b/src/fragments/types/WebhookErrorFragment.ts similarity index 100% rename from src/webhooks/types/WebhookErrorFragment.ts rename to src/fragments/types/WebhookErrorFragment.ts diff --git a/src/webhooks/types/WebhookFragment.ts b/src/fragments/types/WebhookFragment.ts similarity index 75% rename from src/webhooks/types/WebhookFragment.ts rename to src/fragments/types/WebhookFragment.ts index 27bee647d..1c8dcc8f9 100644 --- a/src/webhooks/types/WebhookFragment.ts +++ b/src/fragments/types/WebhookFragment.ts @@ -6,8 +6,8 @@ // GraphQL fragment: WebhookFragment // ==================================================== -export interface WebhookFragment_serviceAccount { - __typename: "ServiceAccount"; +export interface WebhookFragment_app { + __typename: "App"; id: string; name: string | null; } @@ -17,5 +17,5 @@ export interface WebhookFragment { id: string; name: string; isActive: boolean; - serviceAccount: WebhookFragment_serviceAccount; + app: WebhookFragment_app; } diff --git a/src/webhooks/types/WebhooksDetailsFragment.ts b/src/fragments/types/WebhooksDetailsFragment.ts similarity index 74% rename from src/webhooks/types/WebhooksDetailsFragment.ts rename to src/fragments/types/WebhooksDetailsFragment.ts index 8efe55bba..8eaf7e94f 100644 --- a/src/webhooks/types/WebhooksDetailsFragment.ts +++ b/src/fragments/types/WebhooksDetailsFragment.ts @@ -6,8 +6,8 @@ // GraphQL fragment: WebhooksDetailsFragment // ==================================================== -export interface WebhooksDetailsFragment_serviceAccount { - __typename: "ServiceAccount"; +export interface WebhooksDetailsFragment_app { + __typename: "App"; id: string; name: string | null; } @@ -17,5 +17,5 @@ export interface WebhooksDetailsFragment { id: string; name: string; isActive: boolean; - serviceAccount: WebhooksDetailsFragment_serviceAccount; + app: WebhooksDetailsFragment_app; } diff --git a/src/fragments/types/WeightFragment.ts b/src/fragments/types/WeightFragment.ts new file mode 100644 index 000000000..2a9708b2b --- /dev/null +++ b/src/fragments/types/WeightFragment.ts @@ -0,0 +1,15 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { WeightUnitsEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL fragment: WeightFragment +// ==================================================== + +export interface WeightFragment { + __typename: "Weight"; + unit: WeightUnitsEnum; + value: number; +} diff --git a/src/fragments/warehouses.ts b/src/fragments/warehouses.ts new file mode 100644 index 000000000..49eb9d843 --- /dev/null +++ b/src/fragments/warehouses.ts @@ -0,0 +1,35 @@ +import gql from "graphql-tag"; + +import { fragmentAddress } from "./address"; + +export const warehouseFragment = gql` + fragment WarehouseFragment on Warehouse { + id + name + } +`; +export const warehouseWithShippingFragment = gql` + ${warehouseFragment} + fragment WarehouseWithShippingFragment on Warehouse { + ...WarehouseFragment + shippingZones(first: 100) { + edges { + node { + id + name + } + } + } + } +`; + +export const warehouseDetailsFragment = gql` + ${fragmentAddress} + ${warehouseWithShippingFragment} + fragment WarehouseDetailsFragment on Warehouse { + ...WarehouseWithShippingFragment + address { + ...AddressFragment + } + } +`; diff --git a/src/fragments/webhooks.ts b/src/fragments/webhooks.ts new file mode 100644 index 000000000..8d71f9d4f --- /dev/null +++ b/src/fragments/webhooks.ts @@ -0,0 +1,20 @@ +import gql from "graphql-tag"; + +export const webhooksFragment = gql` + fragment WebhookFragment on Webhook { + id + name + isActive + app { + id + name + } + } +`; + +export const webhooksDetailsFragment = gql` + ${webhooksFragment} + fragment WebhooksDetailsFragment on Webhook { + ...WebhookFragment + } +`; diff --git a/src/fragments/weight.ts b/src/fragments/weight.ts new file mode 100644 index 000000000..67fb2870f --- /dev/null +++ b/src/fragments/weight.ts @@ -0,0 +1,8 @@ +import gql from "graphql-tag"; + +export const weightFragment = gql` + fragment WeightFragment on Weight { + unit + value + } +`; diff --git a/src/home/components/HomeActivityCard/HomeActivityCard.tsx b/src/home/components/HomeActivityCard/HomeActivityCard.tsx index e8f3060a2..4094a8f35 100644 --- a/src/home/components/HomeActivityCard/HomeActivityCard.tsx +++ b/src/home/components/HomeActivityCard/HomeActivityCard.tsx @@ -4,12 +4,12 @@ import ListItem from "@material-ui/core/ListItem"; import ListItemText from "@material-ui/core/ListItemText"; import { makeStyles } from "@material-ui/core/styles"; import Typography from "@material-ui/core/Typography"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import CardTitle from "@saleor/components/CardTitle"; import { DateTime } from "@saleor/components/Date"; import Skeleton from "@saleor/components/Skeleton"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { renderCollection } from "../../../misc"; import { Home_activities_edges_node } from "../../types/Home"; import { getActivityMessage } from "./activityMessages"; diff --git a/src/home/components/HomeActivityCard/activityMessages.ts b/src/home/components/HomeActivityCard/activityMessages.ts index d89cb350c..045ceb413 100644 --- a/src/home/components/HomeActivityCard/activityMessages.ts +++ b/src/home/components/HomeActivityCard/activityMessages.ts @@ -7,6 +7,9 @@ const messages = defineMessages({ draft: { defaultMessage: "Order #{orderId} was placed from draft by {userEmail}" }, + draft_no_email: { + defaultMessage: "Order #{orderId} was placed from draft" + }, paid: { defaultMessage: "Order #{orderId} was fully paid" }, @@ -29,10 +32,17 @@ export const getActivityMessage = ( orderId: activity.orderNumber }); case OrderEventsEnum.PLACED_FROM_DRAFT: - return intl.formatMessage(messages.draft, { - orderId: activity.orderNumber, - userEmail: activity.user.email - }); + if (!!activity.user?.email) { + return intl.formatMessage(messages.draft, { + orderId: activity.orderNumber, + userEmail: activity.user?.email + }); + } else { + return intl.formatMessage(messages.draft_no_email, { + orderId: activity.orderNumber + }); + } + default: return activity.message; } diff --git a/src/home/components/HomeHeader/HomeHeader.tsx b/src/home/components/HomeHeader/HomeHeader.tsx index df541359b..4a1ef43f9 100644 --- a/src/home/components/HomeHeader/HomeHeader.tsx +++ b/src/home/components/HomeHeader/HomeHeader.tsx @@ -1,10 +1,9 @@ import { makeStyles } from "@material-ui/core/styles"; import Typography from "@material-ui/core/Typography"; +import Skeleton from "@saleor/components/Skeleton"; import React from "react"; import { FormattedMessage } from "react-intl"; -import Skeleton from "@saleor/components/Skeleton"; - const useStyles = makeStyles( theme => ({ headerContainer: { @@ -30,8 +29,12 @@ const HomeOrdersCard: React.FC = props => { const classes = useStyles(props); return ( -
- +
+ {userName ? ( ({ diff --git a/src/home/components/HomePage/HomePage.tsx b/src/home/components/HomePage/HomePage.tsx index f4015a240..072173bcd 100644 --- a/src/home/components/HomePage/HomePage.tsx +++ b/src/home/components/HomePage/HomePage.tsx @@ -1,6 +1,4 @@ import { makeStyles } from "@material-ui/core/styles"; -import React from "react"; - import CardSpacer from "@saleor/components/CardSpacer"; import Container from "@saleor/components/Container"; import Grid from "@saleor/components/Grid"; @@ -9,6 +7,8 @@ import RequirePermissions from "@saleor/components/RequirePermissions"; import Skeleton from "@saleor/components/Skeleton"; import { UserPermissionProps } from "@saleor/types"; import { PermissionEnum } from "@saleor/types/globalTypes"; +import React from "react"; + import Orders from "../../../icons/Orders"; import Sales from "../../../icons/Sales"; import { @@ -36,10 +36,10 @@ const useStyles = makeStyles( } }, icon: { - "& path":{ - fill:theme.palette.primary.main, + "& path": { + fill: theme.palette.primary.main } - }, + } }), { name: "HomePage" } ); @@ -91,7 +91,13 @@ const HomePage: React.FC = props => {
} + icon={ + + } > {sales ? ( @@ -101,7 +107,13 @@ const HomePage: React.FC = props => { } + icon={ + + } > {orders === undefined ? ( diff --git a/src/home/components/HomeProductListCard/HomeProductListCard.tsx b/src/home/components/HomeProductListCard/HomeProductListCard.tsx index 0df05d32e..4ebe0e70c 100644 --- a/src/home/components/HomeProductListCard/HomeProductListCard.tsx +++ b/src/home/components/HomeProductListCard/HomeProductListCard.tsx @@ -4,15 +4,15 @@ import TableBody from "@material-ui/core/TableBody"; import TableCell from "@material-ui/core/TableCell"; import TableRow from "@material-ui/core/TableRow"; import Typography from "@material-ui/core/Typography"; -import classNames from "classnames"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import CardTitle from "@saleor/components/CardTitle"; import Money from "@saleor/components/Money"; import ResponsiveTable from "@saleor/components/ResponsiveTable"; import Skeleton from "@saleor/components/Skeleton"; import TableCellAvatar from "@saleor/components/TableCellAvatar"; +import classNames from "classnames"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { maybe, renderCollection } from "../../../misc"; import { Home_productTopToday_edges_node } from "../../types/Home"; diff --git a/src/home/components/HomeScreen.tsx b/src/home/components/HomeScreen.tsx index aa9bcbf44..8035d9c14 100644 --- a/src/home/components/HomeScreen.tsx +++ b/src/home/components/HomeScreen.tsx @@ -1,12 +1,11 @@ import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; import Typography from "@material-ui/core/Typography"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import CardTitle from "@saleor/components/CardTitle"; import Container from "@saleor/components/Container"; import PageHeader from "@saleor/components/PageHeader"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; interface HomeScreenProps { user: { diff --git a/src/home/fixtures.ts b/src/home/fixtures.ts index 580590de0..321c06a00 100644 --- a/src/home/fixtures.ts +++ b/src/home/fixtures.ts @@ -193,6 +193,28 @@ export const shop: (placeholderImage: string) => Home = ( } } }, + { + __typename: "OrderEventCountableEdge", + node: { + __typename: "OrderEvent", + amount: null, + composedId: null, + date: "2018-10-12T15:51:11.665838+00:00", + email: null, + emailType: null, + id: "T3JkZXJFdmVudDo3Nw==", + message: null, + orderNumber: "15", + oversoldItems: null, + quantity: null, + type: OrderEventsEnum.PLACED_FROM_DRAFT, + user: { + __typename: "User", + email: null, + id: "VXNlcjoyMQ==" + } + } + }, { __typename: "OrderEventCountableEdge", node: { diff --git a/src/home/views/index.tsx b/src/home/views/index.tsx index 81af44182..2c1016991 100644 --- a/src/home/views/index.tsx +++ b/src/home/views/index.tsx @@ -1,7 +1,7 @@ -import React from "react"; - import useNavigator from "@saleor/hooks/useNavigator"; import useUser from "@saleor/hooks/useUser"; +import React from "react"; + import { getUserName, maybe } from "../../misc"; import { orderListUrl } from "../../orders/urls"; import { productListUrl, productVariantEditUrl } from "../../products/urls"; diff --git a/src/hooks/makeMutation.ts b/src/hooks/makeMutation.ts index 0bd2c2eb5..0f4867882 100644 --- a/src/hooks/makeMutation.ts +++ b/src/hooks/makeMutation.ts @@ -1,3 +1,7 @@ +import { isJwtError } from "@saleor/auth/errors"; +import { commonMessages } from "@saleor/intl"; +import { getMutationStatus, maybe } from "@saleor/misc"; +import { MutationResultAdditionalProps } from "@saleor/types"; import { ApolloError } from "apollo-client"; import { DocumentNode } from "graphql"; import { @@ -7,10 +11,6 @@ import { } from "react-apollo"; import { useIntl } from "react-intl"; -import { commonMessages } from "@saleor/intl"; -import { maybe, getMutationStatus } from "@saleor/misc"; -import { MutationResultAdditionalProps } from "@saleor/types"; -import { isJwtError } from "@saleor/auth/errors"; import useNotifier from "./useNotifier"; import useUser from "./useUser"; @@ -48,15 +48,18 @@ function makeMutation( ) ) { notify({ + status: "error", text: intl.formatMessage(commonMessages.readOnly) }); } else if (err.graphQLErrors.some(isJwtError)) { user.logout(); notify({ + status: "error", text: intl.formatMessage(commonMessages.sessionExpired) }); } else { notify({ + status: "error", text: intl.formatMessage(commonMessages.somethingWentWrong) }); } diff --git a/src/hooks/makeQuery.ts b/src/hooks/makeQuery.ts index beddd14df..e67bf93f7 100644 --- a/src/hooks/makeQuery.ts +++ b/src/hooks/makeQuery.ts @@ -1,12 +1,11 @@ +import { handleQueryAuthError } from "@saleor/auth"; +import { RequireAtLeastOne } from "@saleor/misc"; import { ApolloQueryResult } from "apollo-client"; import { DocumentNode } from "graphql"; import { useEffect } from "react"; import { QueryResult, useQuery as useBaseQuery } from "react-apollo"; import { useIntl } from "react-intl"; -import { commonMessages } from "@saleor/intl"; -import { maybe, RequireAtLeastOne } from "@saleor/misc"; -import { isJwtError } from "@saleor/auth/errors"; import useAppState from "./useAppState"; import useNotifier from "./useNotifier"; import useUser from "./useUser"; @@ -48,6 +47,14 @@ function makeQuery( }, errorPolicy: "all", fetchPolicy: "cache-and-network", + onError: error => + handleQueryAuthError( + error, + notify, + user.tokenRefresh, + user.logout, + intl + ), skip, variables }); @@ -63,24 +70,6 @@ function makeQuery( } }, [queryData.loading]); - if (queryData.error) { - if (queryData.error.graphQLErrors.some(isJwtError)) { - user.logout(); - notify({ - text: intl.formatMessage(commonMessages.sessionExpired) - }); - } else if ( - !queryData.error.graphQLErrors.every( - err => - maybe(() => err.extensions.exception.code) === "PermissionDenied" - ) - ) { - notify({ - text: intl.formatMessage(commonMessages.somethingWentWrong) - }); - } - } - const loadMore = ( mergeFunc: (previousResults: TData, fetchMoreResult: TData) => TData, extraVariables: RequireAtLeastOne diff --git a/src/hooks/makeTopLevelSearch.ts b/src/hooks/makeTopLevelSearch.ts index 1b163be8d..0e81770b7 100644 --- a/src/hooks/makeTopLevelSearch.ts +++ b/src/hooks/makeTopLevelSearch.ts @@ -1,6 +1,6 @@ +import { PageInfoFragment } from "@saleor/fragments/types/PageInfoFragment"; import { DocumentNode } from "graphql"; -import { PageInfoFragment } from "@saleor/types/PageInfoFragment"; import makeSearch, { SearchVariables, UseSearchHook } from "./makeSearch"; export interface SearchData { diff --git a/src/hooks/useAddressValidation.ts b/src/hooks/useAddressValidation.ts index 8db050f74..de9f81bad 100644 --- a/src/hooks/useAddressValidation.ts +++ b/src/hooks/useAddressValidation.ts @@ -1,10 +1,9 @@ -import { useState } from "react"; - import { AddressTypeInput } from "@saleor/customers/types"; +import { AccountErrorFragment } from "@saleor/fragments/types/AccountErrorFragment"; import { transformFormToAddress } from "@saleor/misc"; -import { AddressInput, AccountErrorCode } from "@saleor/types/globalTypes"; +import { AccountErrorCode, AddressInput } from "@saleor/types/globalTypes"; import { add, remove } from "@saleor/utils/lists"; -import { AccountErrorFragment } from "@saleor/customers/types/AccountErrorFragment"; +import { useState } from "react"; interface UseAddressValidation { errors: AccountErrorFragment[]; diff --git a/src/hooks/useBackgroundTask.ts b/src/hooks/useBackgroundTask.ts new file mode 100644 index 000000000..9ec45f163 --- /dev/null +++ b/src/hooks/useBackgroundTask.ts @@ -0,0 +1,8 @@ +import BackgroundTasksContext from "@saleor/containers/BackgroundTasks/context"; +import { useContext } from "react"; + +function useBackgroundTask() { + return useContext(BackgroundTasksContext); +} + +export default useBackgroundTask; diff --git a/src/hooks/useDateLocalize.ts b/src/hooks/useDateLocalize.ts index d183556c2..635e7b765 100644 --- a/src/hooks/useDateLocalize.ts +++ b/src/hooks/useDateLocalize.ts @@ -1,15 +1,14 @@ +import { LocaleContext } from "@saleor/components/Locale"; import moment from "moment-timezone"; import { useContext } from "react"; -import { LocaleContext } from "@saleor/components/Locale"; - -function useDateLocalize(): (date: string) => string { +function useDateLocalize(): (date: string, format?: string) => string { const { locale } = useContext(LocaleContext); - return (date: string) => + return (date: string, format?: string) => moment(date) .locale(locale) - .format("ll"); + .format(format || "ll"); } export default useDateLocalize; diff --git a/src/hooks/useForm.ts b/src/hooks/useForm.ts index 73034800b..752030949 100644 --- a/src/hooks/useForm.ts +++ b/src/hooks/useForm.ts @@ -1,7 +1,7 @@ +import { toggle } from "@saleor/utils/lists"; import isEqual from "lodash-es/isEqual"; import { useState } from "react"; -import { toggle } from "@saleor/utils/lists"; import useStateFromProps from "./useStateFromProps"; export interface ChangeEvent { diff --git a/src/hooks/useFormset.ts b/src/hooks/useFormset.ts index be1143ebe..373be104b 100644 --- a/src/hooks/useFormset.ts +++ b/src/hooks/useFormset.ts @@ -1,4 +1,5 @@ import { removeAtIndex } from "@saleor/utils/lists"; + import useStateFromProps from "./useStateFromProps"; export type FormsetChange = (id: string, value: TValue) => void; diff --git a/src/hooks/useListSettings.ts b/src/hooks/useListSettings.ts index cac29fca9..a8ead57e7 100644 --- a/src/hooks/useListSettings.ts +++ b/src/hooks/useListSettings.ts @@ -1,5 +1,6 @@ -import { useEffect } from "react"; import useLocalStorage from "@saleor/hooks/useLocalStorage"; +import { useEffect } from "react"; + import { AppListViewSettings, defaultListSettings } from "./../config"; import { ListSettings, ListViews } from "./../types"; diff --git a/src/hooks/useLocale.ts b/src/hooks/useLocale.ts index 9114c9d72..f35188b0c 100644 --- a/src/hooks/useLocale.ts +++ b/src/hooks/useLocale.ts @@ -1,6 +1,5 @@ -import { useContext } from "react"; - import { LocaleContext } from "@saleor/components/Locale"; +import { useContext } from "react"; function useLocale() { const localeInfo = useContext(LocaleContext); diff --git a/src/hooks/useMultiAutocomplete.ts b/src/hooks/useMultiAutocomplete.ts index af3a375a2..01ad18a1b 100644 --- a/src/hooks/useMultiAutocomplete.ts +++ b/src/hooks/useMultiAutocomplete.ts @@ -1,5 +1,6 @@ import { MultiAutocompleteChoiceType } from "@saleor/components/MultiAutocompleteSelectField"; import { maybe } from "@saleor/misc"; + import useListActions from "./useListActions"; function useMultiAutocomplete(initial: MultiAutocompleteChoiceType[] = []) { diff --git a/src/hooks/useNotifier.ts b/src/hooks/useNotifier.ts index 6f18707e9..b18186511 100644 --- a/src/hooks/useNotifier.ts +++ b/src/hooks/useNotifier.ts @@ -1,10 +1,16 @@ +import { IMessage } from "@saleor/components/messages"; +import { IMessageContext, MessageContext } from "@saleor/components/messages"; import { useContext } from "react"; -import { IMessageContext, MessageContext } from "@saleor/components/messages"; - export type UseNotifierResult = IMessageContext; + function useNotifier(): UseNotifierResult { - const notify = useContext(MessageContext); + const notificationContext = useContext(MessageContext); + + const notify = (options: IMessage) => { + const timeout = options.status === "error" ? null : options.autohide; + notificationContext.show(options, timeout); + }; return notify; } export default useNotifier; diff --git a/src/hooks/useSearchQuery.ts b/src/hooks/useSearchQuery.ts index eac204bfc..c12db30df 100644 --- a/src/hooks/useSearchQuery.ts +++ b/src/hooks/useSearchQuery.ts @@ -1,6 +1,5 @@ -import React from "react"; - import { ChangeEvent } from "@saleor/hooks/useForm"; +import React from "react"; export type UseSearchQuery = [string, (event: ChangeEvent) => void, () => void]; function useSearchQuery( diff --git a/src/hooks/useShop.ts b/src/hooks/useShop.ts index bf89283c8..c15c7bf0c 100644 --- a/src/hooks/useShop.ts +++ b/src/hooks/useShop.ts @@ -1,6 +1,5 @@ -import { useContext } from "react"; - import { ShopContext } from "@saleor/components/Shop"; +import { useContext } from "react"; function useShop() { return useContext(ShopContext); diff --git a/src/hooks/useTheme.ts b/src/hooks/useTheme.ts index 409b09f3d..e945a468a 100644 --- a/src/hooks/useTheme.ts +++ b/src/hooks/useTheme.ts @@ -1,6 +1,5 @@ -import { useContext } from "react"; - import { ThemeContext } from "@saleor/components/Theme"; +import { useContext } from "react"; function useTheme() { const themeInfo = useContext(ThemeContext); diff --git a/src/icons/ArrowSort.tsx b/src/icons/ArrowSort.tsx index 4455903c0..071b7ade9 100644 --- a/src/icons/ArrowSort.tsx +++ b/src/icons/ArrowSort.tsx @@ -10,7 +10,8 @@ const ArrowSort = createSvgIcon( d="M11.0328 17.1401V4H12.9672V17.1401L14.6322 15.4751L16 16.8429L12 20.8429L8 16.8429L9.36782 15.4751L11.0328 17.1401Z" fill="currentColor" /> - -, "ArrowSort") + , + "ArrowSort" +); export default ArrowSort; diff --git a/src/icons/Attributes.tsx b/src/icons/Attributes.tsx index bf3fb437b..c14386357 100644 --- a/src/icons/Attributes.tsx +++ b/src/icons/Attributes.tsx @@ -9,7 +9,8 @@ const Attributes = createSvgIcon( d="M37.9487 10.4808C37.9487 14.4459 34.7343 17.6603 30.7692 17.6603C26.8041 17.6603 23.5897 14.4459 23.5897 10.4808C23.5897 6.51565 26.8041 3.30128 30.7692 3.30128C34.7343 3.30128 37.9487 6.51565 37.9487 10.4808ZM40 10.4808C40 15.5788 35.8672 19.7115 30.7692 19.7115C25.6712 19.7115 21.5385 15.5788 21.5385 10.4808C21.5385 5.38275 25.6712 1.25 30.7692 1.25C35.8672 1.25 40 5.38275 40 10.4808ZM16.4103 9.45484H2.05128V23.8138H16.4103V9.45484ZM0 7.40356V25.8651H18.4615V7.40356H0ZM24.6154 20.7371L13.9566 39.1987H35.2741L24.6154 20.7371ZM24.6154 24.8397L17.5095 37.1474H31.7212L24.6154 24.8397Z" fill="#06847B" /> - -, "Attributes") + , + "Attributes" +); export default Attributes; diff --git a/src/icons/Ballot.tsx b/src/icons/Ballot.tsx index bb33bdb3c..1862e633b 100644 --- a/src/icons/Ballot.tsx +++ b/src/icons/Ballot.tsx @@ -11,7 +11,8 @@ const Ballot = createSvgIcon( - -, "Ballot") + , + "Ballot" +); export default Ballot; diff --git a/src/icons/BoldIcon.tsx b/src/icons/BoldIcon.tsx index bbc865c18..85724be5a 100644 --- a/src/icons/BoldIcon.tsx +++ b/src/icons/BoldIcon.tsx @@ -4,7 +4,8 @@ import React from "react"; const BoldIcon = createSvgIcon( <> - -, "BoldIcon") + , + "BoldIcon" +); export default BoldIcon; diff --git a/src/icons/Bot.tsx b/src/icons/Bot.tsx index 176688f6c..600357d5f 100644 --- a/src/icons/Bot.tsx +++ b/src/icons/Bot.tsx @@ -7,7 +7,8 @@ const Bot = createSvgIcon( clipRule="evenodd" d="M22.1012 3.96887C22.1012 5.12931 21.1604 6.07004 20 6.07004C18.8396 6.07004 17.8988 5.12931 17.8988 3.96887C17.8988 2.80843 18.8396 1.8677 20 1.8677C21.1604 1.8677 22.1012 2.80843 22.1012 3.96887ZM20.856 7.84519C22.6365 7.45378 23.9689 5.86692 23.9689 3.96887C23.9689 1.77692 22.1919 0 20 0C17.8081 0 16.0311 1.77692 16.0311 3.96887C16.0311 5.81119 17.2864 7.36033 18.9883 7.80765V10.1167H5.29183V16.3424H0V28.7938H5.29183V35.0195H34.7082V28.7938H40V16.3424H34.7082V10.1167H20.856V7.84519ZM34.7082 26.9261V18.2101H38.1323V26.9261H34.7082ZM5.29183 18.2101H1.8677V26.9261H5.29183V18.2101ZM12.2986 26.3603H27.7916V33.1517H32.8405V11.9844H7.15953V33.1517H12.2986V26.3603ZM14.1663 33.1517V28.228H25.9239V33.1517H14.1663ZM16.6537 19.6887C16.6537 20.8151 15.7125 21.7899 14.4747 21.7899C13.2369 21.7899 12.2957 20.8151 12.2957 19.6887C12.2957 18.5623 13.2369 17.5875 14.4747 17.5875C15.7125 17.5875 16.6537 18.5623 16.6537 19.6887ZM18.5214 19.6887C18.5214 21.8807 16.7096 23.6576 14.4747 23.6576C12.2398 23.6576 10.428 21.8807 10.428 19.6887C10.428 17.4968 12.2398 15.7198 14.4747 15.7198C16.7096 15.7198 18.5214 17.4968 18.5214 19.6887ZM25.4475 21.7899C26.6079 21.7899 27.5486 20.8492 27.5486 19.6887C27.5486 18.5283 26.6079 17.5875 25.4475 17.5875C24.287 17.5875 23.3463 18.5283 23.3463 19.6887C23.3463 20.8492 24.287 21.7899 25.4475 21.7899ZM25.4475 23.6576C27.6394 23.6576 29.4163 21.8807 29.4163 19.6887C29.4163 17.4968 27.6394 15.7198 25.4475 15.7198C23.2555 15.7198 21.4786 17.4968 21.4786 19.6887C21.4786 21.8807 23.2555 23.6576 25.4475 23.6576Z" fill="#06847B" - /> -, "Bot") + />, + "Bot" +); export default Bot; diff --git a/src/icons/Checkbox.tsx b/src/icons/Checkbox.tsx new file mode 100644 index 000000000..174c99378 --- /dev/null +++ b/src/icons/Checkbox.tsx @@ -0,0 +1,18 @@ +import createSvgIcon from "@material-ui/icons/utils/createSvgIcon"; +import React from "react"; + +const Checkbox = createSvgIcon( + <> + + , + "Checkbox" +); + +export default Checkbox; diff --git a/src/icons/CheckboxChecked.tsx b/src/icons/CheckboxChecked.tsx new file mode 100644 index 000000000..63170dac3 --- /dev/null +++ b/src/icons/CheckboxChecked.tsx @@ -0,0 +1,17 @@ +import createSvgIcon from "@material-ui/icons/utils/createSvgIcon"; +import React from "react"; + +const CheckboxChecked = createSvgIcon( + <> + + + , + "CheckboxChecked" +); + +export default CheckboxChecked; diff --git a/src/icons/CheckboxIndeterminate.tsx b/src/icons/CheckboxIndeterminate.tsx new file mode 100644 index 000000000..8079e9b24 --- /dev/null +++ b/src/icons/CheckboxIndeterminate.tsx @@ -0,0 +1,19 @@ +import createSvgIcon from "@material-ui/icons/utils/createSvgIcon"; +import React from "react"; + +const CheckboxIndeterminate = createSvgIcon( + <> + + + , + "CheckboxIndeterminate" +); + +export default CheckboxIndeterminate; diff --git a/src/icons/Draggable.tsx b/src/icons/Draggable.tsx index e263aa752..1c05d4ec1 100644 --- a/src/icons/Draggable.tsx +++ b/src/icons/Draggable.tsx @@ -25,7 +25,8 @@ const Draggable = createSvgIcon( - -, "Draggable") + , + "Draggable" +); export default Draggable; diff --git a/src/icons/Folder.tsx b/src/icons/Folder.tsx index 3267c949b..b3bc4e67a 100644 --- a/src/icons/Folder.tsx +++ b/src/icons/Folder.tsx @@ -6,7 +6,8 @@ const Folder = createSvgIcon( - -, "Folder") + , + "Folder" +); export default Folder; diff --git a/src/icons/HeaderOne.tsx b/src/icons/HeaderOne.tsx index 1926b1e22..ade1cc046 100644 --- a/src/icons/HeaderOne.tsx +++ b/src/icons/HeaderOne.tsx @@ -5,7 +5,8 @@ const HeaderOne = createSvgIcon( <> - -, "HeaderOne") + , + "HeaderOne" +); export default HeaderOne; diff --git a/src/icons/HeaderThree.tsx b/src/icons/HeaderThree.tsx index 145256b38..384da7c14 100644 --- a/src/icons/HeaderThree.tsx +++ b/src/icons/HeaderThree.tsx @@ -5,7 +5,8 @@ const HeaderThree = createSvgIcon( <> - -, "HeaderThree") + , + "HeaderThree" +); export default HeaderThree; diff --git a/src/icons/HeaderTwo.tsx b/src/icons/HeaderTwo.tsx index a73ee3ff4..e2bb6f5f4 100644 --- a/src/icons/HeaderTwo.tsx +++ b/src/icons/HeaderTwo.tsx @@ -5,7 +5,8 @@ const HeaderTwo = createSvgIcon( <> - -, "HeaderTwo") + , + "HeaderTwo" +); export default HeaderTwo; diff --git a/src/icons/Home.tsx b/src/icons/Home.tsx index 3a06e35c4..f29b58519 100644 --- a/src/icons/Home.tsx +++ b/src/icons/Home.tsx @@ -6,7 +6,8 @@ const Home = createSvgIcon( - -, "Home") + , + "Home" +); export default Home; diff --git a/src/icons/Image.tsx b/src/icons/Image.tsx index 85256850b..77589b375 100644 --- a/src/icons/Image.tsx +++ b/src/icons/Image.tsx @@ -20,7 +20,8 @@ const Image = createSvgIcon( - -, "Image") + , + "Image" +); export default Image; diff --git a/src/icons/ItalicIcon.tsx b/src/icons/ItalicIcon.tsx index eaf45abdd..a6824e219 100644 --- a/src/icons/ItalicIcon.tsx +++ b/src/icons/ItalicIcon.tsx @@ -4,7 +4,8 @@ import React from "react"; const ItalicIcon = createSvgIcon( <> - -, "ItalicIcon") + , + "ItalicIcon" +); export default ItalicIcon; diff --git a/src/icons/LinkIcon.tsx b/src/icons/LinkIcon.tsx index 280970b39..a45434eba 100644 --- a/src/icons/LinkIcon.tsx +++ b/src/icons/LinkIcon.tsx @@ -4,7 +4,8 @@ import React from "react"; const LinkIcon = createSvgIcon( <> - -, "LinkIcon") + , + "LinkIcon" +); export default LinkIcon; diff --git a/src/icons/LocalShipping.tsx b/src/icons/LocalShipping.tsx index c6e54804c..958c65c69 100644 --- a/src/icons/LocalShipping.tsx +++ b/src/icons/LocalShipping.tsx @@ -6,7 +6,8 @@ const LocalShipping = createSvgIcon( - -, "LocalShipping") + , + "LocalShipping" +); export default LocalShipping; diff --git a/src/icons/Monetization.tsx b/src/icons/Monetization.tsx index d8a737c43..5e3c48dd7 100644 --- a/src/icons/Monetization.tsx +++ b/src/icons/Monetization.tsx @@ -8,7 +8,8 @@ const Monetization = createSvgIcon( - -, "Monetization") + , + "Monetization" +); export default Monetization; diff --git a/src/icons/Moon.tsx b/src/icons/Moon.tsx index dbfddea6d..9d666f0ea 100644 --- a/src/icons/Moon.tsx +++ b/src/icons/Moon.tsx @@ -18,7 +18,8 @@ const Moon = createSvgIcon( clipRule="evenodd" d="M14.8213 10.155L15.1675 11.2692C15.2561 11.5543 15.3397 11.6951 15.4313 11.7839C15.5225 11.8722 15.6533 11.9399 15.9059 12.0123L16.9053 12.2987L15.9168 12.6207C15.6441 12.7096 15.5037 12.7913 15.4113 12.8848C15.3196 12.9776 15.2461 13.1115 15.1678 13.3662L14.8759 14.316L14.5618 13.3733C14.4791 13.1249 14.4002 12.9911 14.3039 12.8959C14.2052 12.7982 14.0616 12.7146 13.7979 12.6163L12.9004 12.2815L13.8199 12.0128C14.1052 11.9294 14.2479 11.8528 14.3373 11.7645C14.4227 11.6803 14.4923 11.5526 14.554 11.2907L14.8213 10.155ZM14.8759 12.1156C14.8477 12.151 14.8173 12.1849 14.7844 12.2174C14.7381 12.2631 14.6886 12.3042 14.636 12.3416C14.6762 12.3733 14.7147 12.4071 14.7514 12.4434C14.7883 12.4799 14.8224 12.5179 14.8542 12.5576C14.8862 12.5159 14.9208 12.4758 14.9586 12.4376C14.9986 12.3971 15.0409 12.3599 15.0855 12.3253C15.0521 12.2992 15.0197 12.2712 14.9885 12.2409C14.9479 12.2016 14.9106 12.1599 14.8759 12.1156Z" /> - -, "Moon") + , + "Moon" +); export default Moon; diff --git a/src/icons/Navigation.tsx b/src/icons/Navigation.tsx index c128e30d2..ccd745a76 100644 --- a/src/icons/Navigation.tsx +++ b/src/icons/Navigation.tsx @@ -9,7 +9,8 @@ const Navigation = createSvgIcon( d="M35.9075 11.3232C40.8772 19.931 37.928 30.9378 29.3202 35.9075C20.7123 40.8772 9.70553 37.928 4.7358 29.3201C-0.233933 20.7123 2.71533 9.70553 11.3232 4.7358C19.931 -0.233933 30.9378 2.71533 35.9075 11.3232ZM37.6393 10.3233C43.1612 19.8876 39.8842 32.1173 30.32 37.6393C20.7557 43.1612 8.52596 39.8842 3.00404 30.32C-2.51789 20.7557 0.759069 8.52596 10.3233 3.00404C19.8876 -2.51789 32.1173 0.759069 37.6393 10.3233ZM14.9402 14.5709L31.0335 9.60975L26.0724 25.7031L21.7789 21.4096C22.3117 20.6975 22.2544 19.6836 21.6072 19.0364C20.9599 18.3891 19.946 18.3319 19.2339 18.8647L14.9402 14.5709ZM19.0359 21.6077C18.3884 20.9602 18.3314 19.946 18.8646 19.2338L14.571 14.9402L9.6098 31.0335L25.7032 26.0723L21.4097 21.7789C20.6976 22.3122 19.6833 22.2551 19.0359 21.6077ZM18.7012 15.504L28.0085 12.6348L25.1393 21.9421L18.7012 15.504Z" fill="#06847B" /> - -, "Navigation") + , + "Navigation" +); export default Navigation; diff --git a/src/icons/NoPhoto.tsx b/src/icons/NoPhoto.tsx index 33dda5582..95b206819 100644 --- a/src/icons/NoPhoto.tsx +++ b/src/icons/NoPhoto.tsx @@ -4,7 +4,8 @@ import React from "react"; const NoPhoto = createSvgIcon( - -, "NoPhoto") + , + "NoPhoto" +); export default NoPhoto; diff --git a/src/icons/OrderedListIcon.tsx b/src/icons/OrderedListIcon.tsx index 76517b348..c43e0d490 100644 --- a/src/icons/OrderedListIcon.tsx +++ b/src/icons/OrderedListIcon.tsx @@ -4,7 +4,8 @@ import React from "react"; const OrderedListIcon = createSvgIcon( <> - -, "OrderedListIcon") + , + "OrderedListIcon" +); export default OrderedListIcon; diff --git a/src/icons/Orders.tsx b/src/icons/Orders.tsx index aca432220..25d00004d 100644 --- a/src/icons/Orders.tsx +++ b/src/icons/Orders.tsx @@ -9,7 +9,8 @@ const Orders = createSvgIcon( d="M43 13H16V51H43V45.5H41V49H18V15H41V33.5H43V13ZM40 43.9142L48.2071 35.7071L46.7928 34.2929L40 41.0858L36.7071 37.7929L35.2928 39.2071L40 43.9142ZM22 19H25V22H22V19ZM36 19H27V22H36V19ZM22 25H25V28H22V25ZM36 25H27V28H36V25ZM22 31H25V34H22V31ZM36 31H27V34H36V31Z" fill="#06847B" /> - -, "Orders") + , + "Orders" +); export default Orders; diff --git a/src/icons/Pages.tsx b/src/icons/Pages.tsx index c4b010527..6a96abd96 100644 --- a/src/icons/Pages.tsx +++ b/src/icons/Pages.tsx @@ -9,7 +9,8 @@ const Pages = createSvgIcon( d="M18.179 1.20349H32.8068L40 8.39671V34.0421H24.6825V32.0528H38.0107V9.2207L37.79 9H32V3.20999L31.9828 3.19278H20.1683V7.15606H18.179V1.20349ZM0 6.16142H14.6278L21.821 13.3546V39H20.8264H0V6.16142ZM14 8.34692V15H19.8317V37.0107H1.98929V8.15071H13.8038L14 8.34692ZM18 19H4V22H18V19ZM4 24H18V27H4V24ZM35 12H25V15H35V12ZM25 17H35V28H25V17ZM18 29H4V32H18V29Z" fill="#06847B" /> - -, "Pages") + , + "Pages" +); export default Pages; diff --git a/src/icons/Plugins.tsx b/src/icons/Plugins.tsx index ef23371dc..7f6b74439 100644 --- a/src/icons/Plugins.tsx +++ b/src/icons/Plugins.tsx @@ -11,7 +11,8 @@ const Plugins = createSvgIcon( fill="#06847B" /> - -, "Plugins") + , + "Plugins" +); export default Plugins; diff --git a/src/icons/ProductTypes.tsx b/src/icons/ProductTypes.tsx index bdeeea8a9..2c924859f 100644 --- a/src/icons/ProductTypes.tsx +++ b/src/icons/ProductTypes.tsx @@ -9,7 +9,8 @@ const ProductTypes = createSvgIcon( d="M0 6.5V33L20 40L40 33V6.5L20 0L0 6.5ZM2.5 8.69935V31.2263L18.75 36.9138V14.3869L2.5 8.69935ZM21.25 14.3869V36.9138L37.5 31.2263V8.69935L21.25 14.3869ZM34.1436 7.22539L20 2.62872L5.8564 7.22539L20 12.1756L34.1436 7.22539Z" fill="#06847B" /> - -, "ProductTypes") + , + "ProductTypes" +); export default ProductTypes; diff --git a/src/icons/QuotationIcon.tsx b/src/icons/QuotationIcon.tsx index b67a5246b..07849cd2f 100644 --- a/src/icons/QuotationIcon.tsx +++ b/src/icons/QuotationIcon.tsx @@ -4,7 +4,8 @@ import React from "react"; const QuotationIcon = createSvgIcon( <> - -, "QuotationIcon") + , + "QuotationIcon" +); export default QuotationIcon; diff --git a/src/icons/Sales.tsx b/src/icons/Sales.tsx index f621216c5..f78f0c361 100644 --- a/src/icons/Sales.tsx +++ b/src/icons/Sales.tsx @@ -9,7 +9,8 @@ const Sales = createSvgIcon( d="M40.1974 14H49.7682V22.7732L45.9287 19.2537L35.0969 30.0855L25.1555 28.0973L15.5364 39.6402L14 38.3598L24.3809 25.9027L34.4395 27.9145L44.453 17.901L40.1974 14ZM21.2682 44H17.2682V49H21.2682V44ZM15.2682 42V51H23.2682V42H15.2682ZM26.2682 34H30.2682V49H26.2682V34ZM24.2682 51V32H32.2682V51H24.2682ZM39.2682 37H35.2682V49H39.2682V37ZM33.2682 35V51H41.2682V35H33.2682ZM44.2682 28H48.2682V49H44.2682V28ZM42.2682 51V26H50.2682V51H42.2682Z" fill="#06847B" /> - -, "Sales") + , + "Sales" +); export default Sales; diff --git a/src/icons/ShippingMethods.tsx b/src/icons/ShippingMethods.tsx index e552267a0..62977adb3 100644 --- a/src/icons/ShippingMethods.tsx +++ b/src/icons/ShippingMethods.tsx @@ -9,7 +9,8 @@ const ShippingMethods = createSvgIcon( d="M0 0H29.3333V12.2666H40V32.9751L32.9752 40H7.4667V19.8248L9.15816 18.1333H0V0ZM27.2 3.35694V12.2666H15.0249L11.2915 16H2.13333V3.07966L14.9333 9.73563L27.2 3.35694ZM24.929 2.13333H4.93756L14.9333 7.33111L24.929 2.13333ZM12.2667 18.1333H12.1752L11.1085 19.2H31.5582L36.3582 14.4H15.9085L12.2667 18.0418V18.1333ZM32.5334 21.2418L37.8667 15.9085V32.0915L32.5334 37.4248V21.2418ZM9.60003 21.3333V37.8666H30.4V21.3333H9.60003ZM18.6667 30.9333H26.6667V28.8H18.6667V30.9333ZM18.6667 34.6666H25.0667V32.5333H18.6667V34.6666Z" fill="#06847B" /> - -, "ShippingMethods") + , + "ShippingMethods" +); export default ShippingMethods; diff --git a/src/icons/Shop.tsx b/src/icons/Shop.tsx index 215f80a0f..6429405c0 100644 --- a/src/icons/Shop.tsx +++ b/src/icons/Shop.tsx @@ -8,7 +8,8 @@ const Shop = createSvgIcon( - -, "Shop") + , + "Shop" +); export default Shop; diff --git a/src/icons/SiteSettings.tsx b/src/icons/SiteSettings.tsx index a161305eb..515109666 100644 --- a/src/icons/SiteSettings.tsx +++ b/src/icons/SiteSettings.tsx @@ -9,7 +9,8 @@ const SiteSettings = createSvgIcon( d="M31.8208 5.55248L30.7926 8.35093L31.545 9.18475C33.147 10.9601 34.3637 13.1054 35.0581 15.4817L35.3837 16.596L38.1395 17.0712V23.1349L35.3838 23.6101L35.0582 24.7244C34.4073 26.9518 33.2976 28.9763 31.8417 30.6834L31.1357 31.5111L32.2146 34.4475L26.7281 37.6084L24.9142 35.4411L23.7814 35.7276C22.572 36.0334 21.3058 36.1961 20 36.1961C18.6942 36.1961 17.428 36.0334 16.2186 35.7276L15.0858 35.4411L13.2719 37.6084L7.78535 34.4475L8.86424 31.5111L8.15831 30.6834C6.70243 28.9763 5.59267 26.9518 4.94182 24.7244L4.61622 23.6101L1.86047 23.1349L1.86047 17.0712L4.61625 16.596L4.94186 15.4817C5.63625 13.1054 6.85296 10.9601 8.45495 9.18475L9.20736 8.35093L8.17916 5.55248L13.6657 2.39164L15.5348 4.62486L16.6397 4.37851C17.7208 4.1375 18.8448 4.01018 20 4.01018C21.1552 4.01018 22.2792 4.1375 23.3603 4.37851L24.4652 4.62486L26.3343 2.39164L31.8208 5.55248ZM40 24.702V15.5042L36.8439 14.9599C36.0699 12.311 34.7134 9.91885 32.9263 7.93836L34.1077 4.72285L25.9098 0L23.7651 2.56262C22.5521 2.2922 21.2924 2.14972 20 2.14972C18.7076 2.14972 17.4479 2.2922 16.2349 2.56262L14.0902 0L5.89227 4.72285L7.07371 7.93836C5.28657 9.91885 3.93009 12.311 3.15607 14.9599L0 15.5042V24.702L3.15603 25.2462C3.88152 27.7291 5.11876 29.9864 6.74273 31.8906L5.49846 35.2772L13.6964 40L15.7625 37.5313C17.1197 37.8744 18.539 38.0565 20 38.0565C21.461 38.0565 22.8803 37.8744 24.2375 37.5313L26.3036 40L34.5015 35.2772L33.2573 31.8906C34.8812 29.9864 36.1185 27.7291 36.844 25.2462L40 24.702ZM28.4425 20C28.4425 24.6627 24.6627 28.4425 20 28.4425C15.3373 28.4425 11.5574 24.6627 11.5574 20C11.5574 15.3373 15.3373 11.5574 20 11.5574C24.6627 11.5574 28.4425 15.3373 28.4425 20ZM30.303 20C30.303 25.6902 25.6902 30.303 20 30.303C14.3097 30.303 9.69693 25.6902 9.69693 20C9.69693 14.3097 14.3097 9.69693 20 9.69693C25.6902 9.69693 30.303 14.3097 30.303 20Z" fill="#06847B" /> - -, "SiteSettings") + , + "SiteSettings" +); export default SiteSettings; diff --git a/src/icons/StaffMembers.tsx b/src/icons/StaffMembers.tsx index 6b1aa270e..fdffb5071 100644 --- a/src/icons/StaffMembers.tsx +++ b/src/icons/StaffMembers.tsx @@ -9,7 +9,8 @@ const StaffMembers = createSvgIcon( d="M20 8C20 11.3137 17.3137 14 14 14C10.6863 14 8 11.3137 8 8C8 4.68629 10.6863 2 14 2C17.3137 2 20 4.68629 20 8ZM22 8C22 12.4183 18.4183 16 14 16C9.58172 16 6 12.4183 6 8C6 3.58172 9.58172 0 14 0C18.4183 0 22 3.58172 22 8ZM2.31344 38L4.94331 20H22.0567L23.0395 26.7268L23 27H23.0794L24.6866 38H2.31344ZM25.1006 27L27 40H0L3.21429 18H23.7857L24.0447 19.7729L25.0238 13H31.5H37.9762L40 27H25.1006ZM31.5 13C28.4624 13 26 10.5376 26 7.5C26 4.46243 28.4624 2 31.5 2C34.5376 2 37 4.46243 37 7.5C37 10.5376 34.5376 13 31.5 13ZM31.5 11C33.433 11 35 9.433 35 7.5C35 5.567 33.433 4 31.5 4C29.567 4 28 5.567 28 7.5C28 9.433 29.567 11 31.5 11ZM25.3099 25L26.7555 15H36.2445L37.6901 25H25.3099Z" fill="#06847B" /> - -, "StaffMembers") + , + "StaffMembers" +); export default StaffMembers; diff --git a/src/icons/StoreMall.tsx b/src/icons/StoreMall.tsx index cacfd4df2..dfcc6ce7a 100644 --- a/src/icons/StoreMall.tsx +++ b/src/icons/StoreMall.tsx @@ -6,7 +6,8 @@ const StoreMall = createSvgIcon( - -, "StoreMall") + , + "StoreMall" +); export default StoreMall; diff --git a/src/icons/StrikethroughIcon.tsx b/src/icons/StrikethroughIcon.tsx index ef9a135b8..b409b4c00 100644 --- a/src/icons/StrikethroughIcon.tsx +++ b/src/icons/StrikethroughIcon.tsx @@ -4,7 +4,8 @@ import React from "react"; const HeaderOne = createSvgIcon( <> - -, "HeaderOne") + , + "HeaderOne" +); export default HeaderOne; diff --git a/src/icons/Sun.tsx b/src/icons/Sun.tsx index 2a8b15aa9..68f721cd9 100644 --- a/src/icons/Sun.tsx +++ b/src/icons/Sun.tsx @@ -8,7 +8,8 @@ const Sun = createSvgIcon( clipRule="evenodd" d="M12.6363 5V7.54545H11.3636V5H12.6363ZM11.9999 13.9091C13.0543 13.9091 13.909 13.0544 13.909 12C13.909 10.9456 13.0543 10.0909 11.9999 10.0909C10.9456 10.0909 10.0908 10.9456 10.0908 12C10.0908 13.0544 10.9456 13.9091 11.9999 13.9091ZM11.9999 15.1818C13.7572 15.1818 15.1817 13.7573 15.1817 12C15.1817 10.2427 13.7572 8.81818 11.9999 8.81818C10.2427 8.81818 8.8181 10.2427 8.8181 12C8.8181 13.7573 10.2427 15.1818 11.9999 15.1818ZM14.6998 8.40019L15.5997 9.30014L17.3996 7.50023L16.4997 6.60028L14.6998 8.40019ZM12.6363 16.4545V19H11.3636V16.4545H12.6363ZM6.60019 16.4998L7.50015 17.3997L9.30006 15.5998L8.4001 14.6999L6.60019 16.4998ZM14.6999 15.5998L15.5999 14.6998L17.3998 16.4997L16.4998 17.3997L14.6999 15.5998ZM6.60025 7.5002L8.40016 9.3001L9.30012 8.40015L7.50021 6.60024L6.60025 7.5002ZM19 12.6363H16.4545L16.4545 11.3636H19V12.6363ZM5 12.6364L7.54545 12.6364V11.3637H5V12.6364Z" /> - -, "Sun") + , + "Sun" +); export default Sun; diff --git a/src/icons/Taxes.tsx b/src/icons/Taxes.tsx index 08a77e56f..d2d8d69b1 100644 --- a/src/icons/Taxes.tsx +++ b/src/icons/Taxes.tsx @@ -9,7 +9,8 @@ const Taxes = createSvgIcon( d="M2 0H34.6316V21.0526H32.5263V2.10526H4.10526V37.8947H32.5263V35.2632H34.6316V40H2V0ZM8.31579 20H11.4737V23.1579H8.31579V20ZM16.7368 20H13.5789V23.1579H16.7368V20ZM18.8421 20H22V23.1579H18.8421V20ZM27.2632 20H24.1053V23.1579H27.2632V20ZM8.31579 25.2632H11.4737V28.4211H8.31579V25.2632ZM16.7368 25.2632H13.5789V28.4211H16.7368V25.2632ZM18.8421 25.2632H22V28.4211H18.8421V25.2632ZM11.4737 30.5263H8.31579V33.6842H11.4737V30.5263ZM13.5789 30.5263H16.7368V33.6842H13.5789V30.5263ZM22 30.5263H18.8421V33.6842H22V30.5263ZM26.2105 9.47368H10.4211V14.7368H26.2105V9.47368ZM8.31579 7.36842V16.8421H28.3158V7.36842H8.31579ZM37.7895 30.5263H34.6316V33.6842H37.7895V30.5263ZM28.3158 24.2105H31.4737V27.3684H28.3158V24.2105ZM29.0602 34.4285L38.5339 24.9548L37.0452 23.4662L27.5715 32.9398L29.0602 34.4285Z" fill="#06847B" /> - -, "Taxes") + , + "Taxes" +); export default Taxes; diff --git a/src/icons/Truck.tsx b/src/icons/Truck.tsx index fea266be7..5dadea379 100644 --- a/src/icons/Truck.tsx +++ b/src/icons/Truck.tsx @@ -7,7 +7,8 @@ const Truck = createSvgIcon( d="M20 8.1355H17V4.1355H3C1.9 4.1355 1 5.0355 1 6.1355V17.1355H3C3 18.7955 4.34 20.1355 6 20.1355C7.66 20.1355 9 18.7955 9 17.1355H15C15 18.7955 16.34 20.1355 18 20.1355C19.66 20.1355 21 18.7955 21 17.1355H23V12.1355L20 8.1355ZM19.5 9.6355L21.46 12.1355H17V9.6355H19.5ZM6 18.1355C5.45 18.1355 5 17.6855 5 17.1355C5 16.5855 5.45 16.1355 6 16.1355C6.55 16.1355 7 16.5855 7 17.1355C7 17.6855 6.55 18.1355 6 18.1355ZM8.22 15.1355C7.67 14.5255 6.89 14.1355 6 14.1355C5.11 14.1355 4.33 14.5255 3.78 15.1355H3V6.1355H15V15.1355H8.22ZM18 18.1355C17.45 18.1355 17 17.6855 17 17.1355C17 16.5855 17.45 16.1355 18 16.1355C18.55 16.1355 19 16.5855 19 17.1355C19 17.6855 18.55 18.1355 18 18.1355Z" fill="#616161" /> - -, "Truck") + , + "Truck" +); export default Truck; diff --git a/src/icons/UnorderedListIcon.tsx b/src/icons/UnorderedListIcon.tsx index 7d0242632..e53d421bc 100644 --- a/src/icons/UnorderedListIcon.tsx +++ b/src/icons/UnorderedListIcon.tsx @@ -4,7 +4,8 @@ import React from "react"; const UnorderedListIcon = createSvgIcon( <> - -, "UnorderedListIcon") + , + "UnorderedListIcon" +); export default UnorderedListIcon; diff --git a/src/icons/Unstyled.tsx b/src/icons/Unstyled.tsx index 1a8b9bd8d..3c50c4347 100644 --- a/src/icons/Unstyled.tsx +++ b/src/icons/Unstyled.tsx @@ -8,7 +8,8 @@ const Unstyled = createSvgIcon( clipRule="evenodd" d="M17.5028 0H17.5027H15.0886H11.4673V2.41416L15.0886 2.41416V9.65714H5.43187V7.72803L0 10.8641L5.43187 14.0002V12.0713L17.5025 12.0713V12.0708H17.5028V0Z" /> - -, "Unstyled") + , + "Unstyled" +); export default Unstyled; diff --git a/src/icons/Webhooks.tsx b/src/icons/Webhooks.tsx index 9b8387cbf..b8f44ef36 100644 --- a/src/icons/Webhooks.tsx +++ b/src/icons/Webhooks.tsx @@ -9,7 +9,8 @@ const Webhooks = createSvgIcon( d="M10.188 25.403L14.8603 17.9921C11.5958 15.3023 10.5525 10.9218 12.3952 7.03423C14.4554 2.68805 19.4727 0.911694 23.8632 2.67405C28.3581 4.47829 30.6541 10.5097 28.3722 15.6112L26.9311 14.9665C28.8961 10.5736 26.8313 5.56662 23.2751 4.13916C19.6146 2.66981 15.5043 4.16105 13.8218 7.71045C12.2078 11.1154 13.2502 14.9597 16.3677 17.1575L16.9804 17.5895L11.5587 26.1892C11.9146 26.496 12.2246 26.8684 12.469 27.301C13.6059 29.3129 12.8965 31.8654 10.8847 33.0023C8.87279 34.1392 6.32024 33.4298 5.18339 31.4179C4.04653 29.4061 4.75587 26.8535 6.76775 25.7167C7.85287 25.1035 9.09527 25.0274 10.188 25.403ZM23.2649 10.8173C23.2649 12.256 22.0986 13.4222 20.6599 13.4222C19.2213 13.4222 18.055 12.256 18.055 10.8173C18.055 9.37865 19.2213 8.21239 20.6599 8.21239C22.0986 8.21239 23.2649 9.37865 23.2649 10.8173ZM22.1884 14.713C21.7149 14.8989 21.1994 15.001 20.6599 15.001C18.3494 15.001 16.4763 13.1279 16.4763 10.8173C16.4763 8.50674 18.3494 6.63365 20.6599 6.63365C22.9705 6.63365 24.8436 8.50674 24.8436 10.8173C24.8436 12.0191 24.3368 13.1026 23.5253 13.8657L27.6887 21.6091C31.6202 20.096 35.9283 21.3402 38.3955 24.8467C41.154 28.7675 40.2364 33.995 36.5573 36.9426C32.7897 39.9611 26.4344 38.9945 23.1295 34.5103L24.4003 33.5736C27.2448 37.4331 32.5933 38.0955 35.5702 35.7105C38.6356 33.2546 39.3563 28.956 37.1043 25.7552C34.9442 22.6851 31.1037 21.7052 27.6738 23.3323L26.9957 23.6539L22.1884 14.713ZM28.4266 28.5411C27.7395 29.8054 28.2075 31.3873 29.4718 32.0744C30.7362 32.7614 32.3181 32.2935 33.0051 31.0291C33.6922 29.7648 33.2242 28.1829 31.9599 27.4958C30.6955 26.8088 29.1136 27.2768 28.4266 28.5411ZM26.6391 30.7276C26.8998 31.8533 27.6229 32.8664 28.718 33.4615C30.7485 34.5649 33.2889 33.8134 34.3923 31.7829C35.4956 29.7525 34.7441 27.2121 32.7137 26.1087C30.6832 25.0053 28.1428 25.7569 27.0394 27.7873C26.8022 28.2239 26.6507 28.6841 26.5792 29.1486L16.4131 29.1096L16.3716 29.8582C16.1604 33.6666 13.4532 36.5883 9.71044 37.0246C5.80888 37.4794 2.36564 34.7845 1.67123 30.9016C0.99662 27.1295 4.1478 22.7246 8.91444 22.0623L8.69716 20.4986C3.16177 21.2677 -0.735523 26.4118 0.117155 31.1796C0.950033 35.8367 5.11583 39.1496 9.89322 38.5927C14.1665 38.0946 17.3279 34.8879 17.8783 30.694L26.6391 30.7276ZM11.0946 28.0777C10.3866 26.8249 8.7972 26.3832 7.54443 27.0911C6.29165 27.799 5.84995 29.3885 6.55786 30.6413C7.26577 31.894 8.85522 32.3357 10.108 31.6278C11.3608 30.9199 11.8025 29.3305 11.0946 28.0777Z" fill="#06847B" /> - -, "Webhooks") + , + "Webhooks" +); export default Webhooks; diff --git a/src/index.tsx b/src/index.tsx index 2a60c75cb..9317abeea 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,39 +1,40 @@ +import useAppState from "@saleor/hooks/useAppState"; import { defaultDataIdFromObject, InMemoryCache } from "apollo-cache-inmemory"; import { ApolloClient } from "apollo-client"; import { ApolloLink } from "apollo-link"; import { BatchHttpLink } from "apollo-link-batch-http"; -import { setContext } from "apollo-link-context"; -import { ErrorResponse, onError } from "apollo-link-error"; import { createUploadLink } from "apollo-upload-client"; import React from "react"; import { ApolloProvider } from "react-apollo"; import { render } from "react-dom"; import ErrorBoundary from "react-error-boundary"; +import TagManager from "react-gtm-module"; import { useIntl } from "react-intl"; import { BrowserRouter, Route, Switch } from "react-router-dom"; -import Navigator from "@saleor/components/Navigator"; -import useAppState from "@saleor/hooks/useAppState"; +import AppsSection from "./apps"; +import { appsSection } from "./apps/urls"; import AttributeSection from "./attributes"; import { attributeSection } from "./attributes/urls"; -import Auth, { getAuthToken, removeAuthToken } from "./auth"; -import { isJwtError } from "./auth/errors"; -import AuthProvider from "./auth/AuthProvider"; +import Auth from "./auth"; +import AuthProvider, { useAuth } from "./auth/AuthProvider"; import LoginLoading from "./auth/components/LoginLoading/LoginLoading"; import SectionRoute from "./auth/components/SectionRoute"; +import authLink from "./auth/link"; import { hasPermission } from "./auth/misc"; import CategorySection from "./categories"; import CollectionSection from "./collections"; import AppLayout from "./components/AppLayout"; import { DateProvider } from "./components/Date"; import { LocaleProvider } from "./components/Locale"; -import { MessageManager } from "./components/messages"; +import MessageManagerProvider from "./components/messages"; import { ShopProvider } from "./components/Shop"; import ThemeProvider from "./components/Theme"; import { WindowTitle } from "./components/WindowTitle"; -import { API_URI, APP_MOUNT_URI } from "./config"; +import { API_URI, APP_MOUNT_URI, GTM_ID } from "./config"; import ConfigurationSection, { createConfigurationMenu } from "./configuration"; import AppStateProvider from "./containers/AppState"; +import BackgroundTasksProvider from "./containers/BackgroundTasks"; import { CustomerSection } from "./customers"; import DiscountSection from "./discounts"; import HomePage from "./home"; @@ -43,55 +44,28 @@ import { navigationSection } from "./navigation/urls"; import { NotFound } from "./NotFound"; import OrdersSection from "./orders"; import PageSection from "./pages"; +import PermissionGroupSection from "./permissionGroups"; import PluginsSection from "./plugins"; import ProductSection from "./products"; import ProductTypesSection from "./productTypes"; -import PermissionGroupSection from "./permissionGroups"; -import ServiceSection from "./services"; -import { serviceSection } from "./services/urls"; import ShippingSection from "./shipping"; import SiteSettingsSection from "./siteSettings"; import StaffSection from "./staff"; import TaxesSection from "./taxes"; import TranslationsSection from "./translations"; import { PermissionEnum } from "./types/globalTypes"; -import WebhooksSection from "./webhooks"; -import { warehouseSection } from "./warehouses/urls"; import WarehouseSection from "./warehouses"; +import { warehouseSection } from "./warehouses/urls"; -interface ResponseError extends ErrorResponse { - networkError?: Error & { - statusCode?: number; - bodyText?: string; - }; +if (process.env.GTM_ID !== undefined) { + TagManager.initialize({ gtmId: GTM_ID }); } -const invalidTokenLink = onError((error: ResponseError) => { - if ( - (error.networkError && error.networkError.statusCode === 401) || - error.graphQLErrors?.some(isJwtError) - ) { - removeAuthToken(); - } -}); - -const authLink = setContext((_, context) => { - const authToken = getAuthToken(); - - return { - ...context, - headers: { - ...context.headers, - Authorization: authToken ? `JWT ${authToken}` : null - } - }; -}); - // DON'T TOUCH THIS // These are separate clients and do not share configs between themselves // so we need to explicitly set them const linkOptions = { - credentials: "same-origin", + credentials: "include", uri: API_URI }; const uploadLink = createUploadLink(linkOptions); @@ -117,7 +91,7 @@ const apolloClient = new ApolloClient({ return defaultDataIdFromObject(obj); } }), - link: invalidTokenLink.concat(authLink.concat(link)) + link: authLink.concat(link) }); const App: React.FC = () => { @@ -129,13 +103,17 @@ const App: React.FC = () => { - - - - - - - + + + + + + + + + + + @@ -147,155 +125,144 @@ const App: React.FC = () => { const Routes: React.FC = () => { const intl = useIntl(); const [, dispatchAppState] = useAppState(); + const { + hasToken, + isAuthenticated, + tokenAuthLoading, + tokenVerifyLoading, + user + } = useAuth(); return ( <> - - {({ - hasToken, - isAuthenticated, - tokenAuthLoading, - tokenVerifyLoading, - user - }) => - isAuthenticated && !tokenAuthLoading && !tokenVerifyLoading ? ( - - - - dispatchAppState({ - payload: { - error: "unhandled" - }, - type: "displayError" - }) - } - > - - - - - - - - - - - - - - - - - - - - - - - {createConfigurationMenu(intl).filter(menu => - menu.menuItems.map(item => - hasPermission(item.permission, user) - ) - ).length > 0 && ( - - )} - - - - - ) : hasToken && tokenVerifyLoading ? ( - - ) : ( - - ) - } - + {isAuthenticated && !tokenAuthLoading && !tokenVerifyLoading ? ( + + + dispatchAppState({ + payload: { + error: "unhandled" + }, + type: "displayError" + }) + } + > + + + + + + + + + + + + + + + + + + + + + + {createConfigurationMenu(intl).filter(menu => + menu.menuItems.map(item => hasPermission(item.permission, user)) + ).length > 0 && ( + + )} + + + + + ) : hasToken && tokenVerifyLoading ? ( + + ) : ( + + )} ); }; diff --git a/src/intl.ts b/src/intl.ts index 479b630dc..fa27aa818 100644 --- a/src/intl.ts +++ b/src/intl.ts @@ -7,9 +7,17 @@ export const commonMessages = defineMessages({ catalog: { defaultMessage: "Catalog" }, + customApps: { + defaultMessage: "Local Apps" + }, dashboard: { defaultMessage: "Dashboard" }, + demo: { + defaultMessage: + "Just to let you know... You're in demo mode. You can play around with the dashboard but can't save changes.", + description: "notification message after log in" + }, description: { defaultMessage: "Description" }, @@ -124,6 +132,10 @@ export const buttonMessages = defineMessages({ defaultMessage: "Manage", description: "button" }, + nextStep: { + defaultMessage: "Next", + description: "go to next step, button" + }, ok: { defaultMessage: "OK", description: "button" @@ -136,6 +148,14 @@ export const buttonMessages = defineMessages({ defaultMessage: "Save", description: "button" }, + selectAll: { + defaultMessage: "Select All", + description: "select all options, button" + }, + send: { + defaultMessage: "Send", + description: "button" + }, show: { defaultMessage: "Show", description: "button" @@ -147,6 +167,10 @@ export const buttonMessages = defineMessages({ }); export const sectionNames = defineMessages({ + apps: { + defaultMessage: "Apps", + description: "apps section name" + }, attributes: { defaultMessage: "Attributes", description: "attributes section name" @@ -172,7 +196,7 @@ export const sectionNames = defineMessages({ description: "draft orders section name" }, home: { - defaultMessage: "Home", + defaultMessage: "Dashboard", description: "home section name" }, navigation: { diff --git a/src/misc.ts b/src/misc.ts index f4934f862..2e661000a 100644 --- a/src/misc.ts +++ b/src/misc.ts @@ -7,9 +7,9 @@ import { ConfirmButtonTransitionState } from "./components/ConfirmButton/Confirm import { APP_MOUNT_URI } from "./config"; import { AddressType, AddressTypeInput } from "./customers/types"; import { + MutationResultAdditionalProps, PartialMutationProviderOutput, - UserError, - MutationResultAdditionalProps + UserError } from "./types"; import { AddressInput, @@ -235,7 +235,7 @@ export function hasErrors(errorList: UserError[] | null): boolean { export function getMutationState( called: boolean, loading: boolean, - ...errorList: UserError[][] + ...errorList: any[][] ): ConfirmButtonTransitionState { if (loading) { return "loading"; @@ -306,10 +306,10 @@ export function createHref(url: string) { interface AnyEvent { stopPropagation: () => void; } -export function stopPropagation(cb: () => void) { +export function stopPropagation(cb: (event?: AnyEvent) => void) { return (event: AnyEvent) => { event.stopPropagation(); - cb(); + cb(event); }; } diff --git a/src/mutations.tsx b/src/mutations.tsx index f685c6cb8..329444b12 100644 --- a/src/mutations.tsx +++ b/src/mutations.tsx @@ -4,12 +4,12 @@ import React from "react"; import { Mutation, MutationFunction, MutationResult } from "react-apollo"; import { useIntl } from "react-intl"; +import { isJwtError } from "./auth/errors"; import useNotifier from "./hooks/useNotifier"; +import useUser from "./hooks/useUser"; import { commonMessages } from "./intl"; import { getMutationStatus } from "./misc"; import { MutationResultAdditionalProps } from "./types"; -import { isJwtError } from "./auth/errors"; -import useUser from "./hooks/useUser"; export interface TypedMutationInnerProps { children: ( @@ -39,6 +39,7 @@ export function TypedMutation( onError={(err: ApolloError) => { if (err.networkError) { notify({ + status: "error", text: intl.formatMessage(commonMessages.somethingWentWrong) }); } @@ -47,15 +48,18 @@ export function TypedMutation( "ReadOnlyException" ) { notify({ + status: "error", text: intl.formatMessage(commonMessages.readOnly) }); } else if (err.graphQLErrors.some(isJwtError)) { user.logout(); notify({ + status: "error", text: intl.formatMessage(commonMessages.sessionExpired) }); } else { notify({ + status: "error", text: intl.formatMessage(commonMessages.somethingWentWrong) }); } diff --git a/src/navigation/components/MenuCreateDialog/MenuCreateDialog.tsx b/src/navigation/components/MenuCreateDialog/MenuCreateDialog.tsx index 41c0f9f25..200a9ed0b 100644 --- a/src/navigation/components/MenuCreateDialog/MenuCreateDialog.tsx +++ b/src/navigation/components/MenuCreateDialog/MenuCreateDialog.tsx @@ -4,17 +4,16 @@ import DialogActions from "@material-ui/core/DialogActions"; import DialogContent from "@material-ui/core/DialogContent"; import DialogTitle from "@material-ui/core/DialogTitle"; import TextField from "@material-ui/core/TextField"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import ConfirmButton, { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; import Form from "@saleor/components/Form"; +import { MenuErrorFragment } from "@saleor/fragments/types/MenuErrorFragment"; import { buttonMessages } from "@saleor/intl"; -import { MenuErrorFragment } from "@saleor/navigation/types/MenuErrorFragment"; import { getFormErrors } from "@saleor/utils/errors"; import getMenuErrorMessage from "@saleor/utils/errors/menu"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; export interface MenuCreateDialogFormData { name: string; diff --git a/src/navigation/components/MenuDetailsPage/MenuDetailsPage.tsx b/src/navigation/components/MenuDetailsPage/MenuDetailsPage.tsx index 8979c0cd5..93c093ff8 100644 --- a/src/navigation/components/MenuDetailsPage/MenuDetailsPage.tsx +++ b/src/navigation/components/MenuDetailsPage/MenuDetailsPage.tsx @@ -1,7 +1,4 @@ import Typography from "@material-ui/core/Typography"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import AppHeader from "@saleor/components/AppHeader"; import CardSpacer from "@saleor/components/CardSpacer"; import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; @@ -9,8 +6,11 @@ import Container from "@saleor/components/Container"; import Form from "@saleor/components/Form"; import Grid from "@saleor/components/Grid"; import SaveButtonBar from "@saleor/components/SaveButtonBar"; +import { MenuErrorFragment } from "@saleor/fragments/types/MenuErrorFragment"; import { sectionNames } from "@saleor/intl"; -import { MenuErrorFragment } from "@saleor/navigation/types/MenuErrorFragment"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { maybe } from "../../../misc"; import { MenuDetails_menu } from "../../types/MenuDetails"; import { MenuItemType } from "../MenuItemDialog"; diff --git a/src/navigation/components/MenuItemDialog/MenuItemDialog.tsx b/src/navigation/components/MenuItemDialog/MenuItemDialog.tsx index 93f31776d..394c2ec46 100644 --- a/src/navigation/components/MenuItemDialog/MenuItemDialog.tsx +++ b/src/navigation/components/MenuItemDialog/MenuItemDialog.tsx @@ -5,15 +5,12 @@ import DialogContent from "@material-ui/core/DialogContent"; import DialogTitle from "@material-ui/core/DialogTitle"; import TextField from "@material-ui/core/TextField"; import Typography from "@material-ui/core/Typography"; -import isUrl from "is-url"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import AutocompleteSelectMenu from "@saleor/components/AutocompleteSelectMenu"; import ConfirmButton, { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; import FormSpacer from "@saleor/components/FormSpacer"; +import { MenuErrorFragment } from "@saleor/fragments/types/MenuErrorFragment"; import useModalDialogErrors from "@saleor/hooks/useModalDialogErrors"; import useModalDialogOpen from "@saleor/hooks/useModalDialogOpen"; import useStateFromProps from "@saleor/hooks/useStateFromProps"; @@ -21,10 +18,12 @@ import { buttonMessages, sectionNames } from "@saleor/intl"; import { SearchCategories_search_edges_node } from "@saleor/searches/types/SearchCategories"; import { SearchCollections_search_edges_node } from "@saleor/searches/types/SearchCollections"; import { SearchPages_search_edges_node } from "@saleor/searches/types/SearchPages"; -import { getMenuItemByValue, IMenu } from "@saleor/utils/menu"; -import { MenuErrorFragment } from "@saleor/navigation/types/MenuErrorFragment"; import { getFieldError, getFormErrors } from "@saleor/utils/errors"; import getMenuErrorMessage from "@saleor/utils/errors/menu"; +import { getMenuItemByValue, IMenu } from "@saleor/utils/menu"; +import isUrl from "is-url"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; export type MenuItemType = "category" | "collection" | "link" | "page"; export interface MenuItemData { diff --git a/src/navigation/components/MenuItems/MenuItems.tsx b/src/navigation/components/MenuItems/MenuItems.tsx index 554e71173..bbc5916ec 100644 --- a/src/navigation/components/MenuItems/MenuItems.tsx +++ b/src/navigation/components/MenuItems/MenuItems.tsx @@ -7,15 +7,15 @@ import { makeStyles } from "@material-ui/core/styles"; import Typography from "@material-ui/core/Typography"; import DeleteIcon from "@material-ui/icons/Delete"; import EditIcon from "@material-ui/icons/Edit"; +import CardTitle from "@saleor/components/CardTitle"; +import Skeleton from "@saleor/components/Skeleton"; +import useTheme from "@saleor/hooks/useTheme"; +import { buttonMessages } from "@saleor/intl"; import classNames from "classnames"; import React from "react"; import { FormattedMessage, useIntl } from "react-intl"; import SortableTree, { NodeRendererProps, TreeItem } from "react-sortable-tree"; -import CardTitle from "@saleor/components/CardTitle"; -import Skeleton from "@saleor/components/Skeleton"; -import useTheme from "@saleor/hooks/useTheme"; -import { buttonMessages } from "@saleor/intl"; import Draggable from "../../../icons/Draggable"; import { MenuDetails_menu_items } from "../../types/MenuDetails"; import { MenuItemType } from "../MenuItemDialog"; diff --git a/src/navigation/components/MenuList/MenuList.tsx b/src/navigation/components/MenuList/MenuList.tsx index 8223da51c..c2f161e66 100644 --- a/src/navigation/components/MenuList/MenuList.tsx +++ b/src/navigation/components/MenuList/MenuList.tsx @@ -5,20 +5,20 @@ import TableCell from "@material-ui/core/TableCell"; import TableFooter from "@material-ui/core/TableFooter"; import TableRow from "@material-ui/core/TableRow"; import DeleteIcon from "@material-ui/icons/Delete"; -import React from "react"; -import { FormattedMessage } from "react-intl"; - import Checkbox from "@saleor/components/Checkbox"; import IconButtonTableCell from "@saleor/components/IconButtonTableCell"; import ResponsiveTable from "@saleor/components/ResponsiveTable"; import Skeleton from "@saleor/components/Skeleton"; +import TableCellHeader from "@saleor/components/TableCellHeader"; import TableHead from "@saleor/components/TableHead"; import TablePagination from "@saleor/components/TablePagination"; import { maybe, renderCollection } from "@saleor/misc"; -import { ListActions, ListProps, SortPage } from "@saleor/types"; import { MenuListUrlSortField } from "@saleor/navigation/urls"; -import TableCellHeader from "@saleor/components/TableCellHeader"; +import { ListActions, ListProps, SortPage } from "@saleor/types"; import { getArrowDirection } from "@saleor/utils/sort"; +import React from "react"; +import { FormattedMessage } from "react-intl"; + import { MenuList_menus_edges_node } from "../../types/MenuList"; export interface MenuListProps diff --git a/src/navigation/components/MenuListPage/MenuListPage.tsx b/src/navigation/components/MenuListPage/MenuListPage.tsx index 429545c21..457424ca6 100644 --- a/src/navigation/components/MenuListPage/MenuListPage.tsx +++ b/src/navigation/components/MenuListPage/MenuListPage.tsx @@ -1,14 +1,13 @@ import Button from "@material-ui/core/Button"; - -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import AppHeader from "@saleor/components/AppHeader"; import Container from "@saleor/components/Container"; import PageHeader from "@saleor/components/PageHeader"; import { sectionNames } from "@saleor/intl"; -import { ListActions, PageListProps, SortPage } from "@saleor/types"; import { MenuListUrlSortField } from "@saleor/navigation/urls"; +import { ListActions, PageListProps, SortPage } from "@saleor/types"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { MenuList_menus_edges_node } from "../../types/MenuList"; import MenuList from "../MenuList"; diff --git a/src/navigation/components/MenuProperties/MenuProperties.tsx b/src/navigation/components/MenuProperties/MenuProperties.tsx index d798a4cad..8182a95b7 100644 --- a/src/navigation/components/MenuProperties/MenuProperties.tsx +++ b/src/navigation/components/MenuProperties/MenuProperties.tsx @@ -1,14 +1,14 @@ import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; import TextField from "@material-ui/core/TextField"; +import CardTitle from "@saleor/components/CardTitle"; +import { MenuErrorFragment } from "@saleor/fragments/types/MenuErrorFragment"; +import { commonMessages } from "@saleor/intl"; +import { getFormErrors } from "@saleor/utils/errors"; +import getMenuErrorMessage from "@saleor/utils/errors/menu"; import React from "react"; import { useIntl } from "react-intl"; -import CardTitle from "@saleor/components/CardTitle"; -import { commonMessages } from "@saleor/intl"; -import { MenuErrorFragment } from "@saleor/navigation/types/MenuErrorFragment"; -import { getFormErrors } from "@saleor/utils/errors"; -import getMenuErrorMessage from "@saleor/utils/errors/menu"; import { MenuDetailsFormData } from "../MenuDetailsPage"; export interface MenuPropertiesProps { diff --git a/src/navigation/index.tsx b/src/navigation/index.tsx index 39d1559bb..5e42c6dd3 100644 --- a/src/navigation/index.tsx +++ b/src/navigation/index.tsx @@ -1,13 +1,13 @@ +import { asSortParams } from "@saleor/utils/sort"; import { parse as parseQs } from "qs"; import React from "react"; import { Route, RouteComponentProps, Switch } from "react-router-dom"; -import { asSortParams } from "@saleor/utils/sort"; import { menuListPath, - menuPath, MenuListUrlQueryParams, - MenuListUrlSortField + MenuListUrlSortField, + menuPath } from "./urls"; import MenuDetailsComponent from "./views/MenuDetails"; import MenuListComponent from "./views/MenuList"; diff --git a/src/navigation/mutations.ts b/src/navigation/mutations.ts index 5a43533e2..3df68787b 100644 --- a/src/navigation/mutations.ts +++ b/src/navigation/mutations.ts @@ -1,6 +1,11 @@ +import { menuErrorFragment } from "@saleor/fragments/errors"; +import { + menuItemFragment, + menuItemNestedFragment +} from "@saleor/fragments/navigation"; import gql from "graphql-tag"; + import { TypedMutation } from "../mutations"; -import { menuItemFragment, menuItemNestedFragment } from "./queries"; import { MenuBulkDelete, MenuBulkDeleteVariables @@ -17,13 +22,6 @@ import { } from "./types/MenuItemUpdate"; import { MenuUpdate, MenuUpdateVariables } from "./types/MenuUpdate"; -const menuErrorFragment = gql` - fragment MenuErrorFragment on MenuError { - code - field - } -`; - const menuCreate = gql` ${menuErrorFragment} mutation MenuCreate($input: MenuCreateInput!) { diff --git a/src/navigation/queries.ts b/src/navigation/queries.ts index c03b4db48..4bb0316cc 100644 --- a/src/navigation/queries.ts +++ b/src/navigation/queries.ts @@ -1,77 +1,15 @@ -import gql from "graphql-tag"; +import { + menuDetailsFragment, + menuFragment +} from "@saleor/fragments/navigation"; +import { pageInfoFragment } from "@saleor/fragments/pageInfo"; import makeQuery from "@saleor/hooks/makeQuery"; -import { pageInfoFragment, TypedQuery } from "../queries"; +import gql from "graphql-tag"; + +import { TypedQuery } from "../queries"; import { MenuDetails, MenuDetailsVariables } from "./types/MenuDetails"; import { MenuList, MenuListVariables } from "./types/MenuList"; -export const menuFragment = gql` - fragment MenuFragment on Menu { - id - name - items { - id - } - } -`; - -export const menuItemFragment = gql` - fragment MenuItemFragment on MenuItem { - category { - id - name - } - collection { - id - name - } - id - level - name - page { - id - title - } - url - } -`; - -// GraphQL does not support recurive fragments -export const menuItemNestedFragment = gql` - ${menuItemFragment} - fragment MenuItemNestedFragment on MenuItem { - ...MenuItemFragment - children { - ...MenuItemFragment - children { - ...MenuItemFragment - children { - ...MenuItemFragment - children { - ...MenuItemFragment - children { - ...MenuItemFragment - children { - ...MenuItemFragment - } - } - } - } - } - } - } -`; - -export const menuDetailsFragment = gql` - ${menuItemNestedFragment} - fragment MenuDetailsFragment on Menu { - id - items { - ...MenuItemNestedFragment - } - name - } -`; - const menuList = gql` ${menuFragment} ${pageInfoFragment} diff --git a/src/navigation/views/MenuDetails/index.tsx b/src/navigation/views/MenuDetails/index.tsx index 52d3d7ddd..d33d5ddcc 100644 --- a/src/navigation/views/MenuDetails/index.tsx +++ b/src/navigation/views/MenuDetails/index.tsx @@ -1,7 +1,4 @@ import DialogContentText from "@material-ui/core/DialogContentText"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import ActionDialog from "@saleor/components/ActionDialog"; import { DEFAULT_INITIAL_SEARCH_DATA } from "@saleor/config"; import useNavigator from "@saleor/hooks/useNavigator"; @@ -9,6 +6,9 @@ import useNotifier from "@saleor/hooks/useNotifier"; import useCategorySearch from "@saleor/searches/useCategorySearch"; import useCollectionSearch from "@saleor/searches/useCollectionSearch"; import usePageSearch from "@saleor/searches/usePageSearch"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { categoryUrl } from "../../../categories/urls"; import { collectionUrl } from "../../../collections/urls"; import { maybe } from "../../../misc"; diff --git a/src/navigation/views/MenuDetails/successHandlers.ts b/src/navigation/views/MenuDetails/successHandlers.ts index 1dce13307..9c7204cba 100644 --- a/src/navigation/views/MenuDetails/successHandlers.ts +++ b/src/navigation/views/MenuDetails/successHandlers.ts @@ -1,6 +1,6 @@ +import { commonMessages } from "@saleor/intl"; import { IntlShape } from "react-intl"; -import { commonMessages } from "@saleor/intl"; import { UseNavigatorResult } from "../../../hooks/useNavigator"; import { UseNotifierResult } from "../../../hooks/useNotifier"; import { MenuDelete } from "../../types/MenuDelete"; @@ -18,6 +18,7 @@ export function handleItemCreate( if (data.menuItemCreate.errors.length === 0) { closeModal(); notify({ + status: "success", text: intl.formatMessage(commonMessages.savedChanges) }); } @@ -32,6 +33,7 @@ export function handleItemUpdate( ) { if (data.menuItemUpdate.errors.length === 0) { notify({ + status: "success", text: intl.formatMessage(commonMessages.savedChanges) }); navigate( @@ -51,6 +53,7 @@ export function handleDelete( ) { if (data.menuDelete.errors.length === 0) { notify({ + status: "success", text: intl.formatMessage(commonMessages.savedChanges) }); navigate(menuListUrl(), true); @@ -69,6 +72,7 @@ export function handleUpdate( data.menuUpdate.errors.length === 0 ) { notify({ + status: "success", text: intl.formatMessage(commonMessages.savedChanges) }); refetch(); diff --git a/src/navigation/views/MenuList/MenuList.tsx b/src/navigation/views/MenuList/MenuList.tsx index 0b303d83d..4d345424c 100644 --- a/src/navigation/views/MenuList/MenuList.tsx +++ b/src/navigation/views/MenuList/MenuList.tsx @@ -1,8 +1,5 @@ import Button from "@material-ui/core/Button"; import DialogContentText from "@material-ui/core/DialogContentText"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import ActionDialog from "@saleor/components/ActionDialog"; import { configurationMenuUrl } from "@saleor/configuration"; import useBulkActions from "@saleor/hooks/useBulkActions"; @@ -15,8 +12,11 @@ import usePaginator, { import { buttonMessages, commonMessages } from "@saleor/intl"; import { maybe } from "@saleor/misc"; import { ListViews } from "@saleor/types"; -import { getSortParams } from "@saleor/utils/sort"; import createSortHandler from "@saleor/utils/handlers/sortHandler"; +import { getSortParams } from "@saleor/utils/sort"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import MenuCreateDialog from "../../components/MenuCreateDialog"; import MenuListPage from "../../components/MenuListPage"; import { @@ -79,6 +79,7 @@ const MenuList: React.FC = ({ params }) => { const handleCreate = (data: MenuCreate) => { if (data.menuCreate.errors.length === 0) { notify({ + status: "success", text: intl.formatMessage({ defaultMessage: "Created menu", id: "menuListCreatedMenu" @@ -91,6 +92,7 @@ const MenuList: React.FC = ({ params }) => { const handleBulkDelete = (data: MenuBulkDelete) => { if (data.menuBulkDelete.errors.length === 0) { notify({ + status: "success", text: intl.formatMessage(commonMessages.savedChanges) }); closeModal(); @@ -102,6 +104,7 @@ const MenuList: React.FC = ({ params }) => { const handleDelete = (data: MenuDelete) => { if (data.menuDelete.errors.length === 0) { notify({ + status: "success", text: intl.formatMessage({ defaultMessage: "Deleted menu", id: "menuListDeletedMenu" diff --git a/src/orders/components/OrderAddressEditDialog/OrderAddressEditDialog.tsx b/src/orders/components/OrderAddressEditDialog/OrderAddressEditDialog.tsx index 22d7e4279..1df64b36b 100644 --- a/src/orders/components/OrderAddressEditDialog/OrderAddressEditDialog.tsx +++ b/src/orders/components/OrderAddressEditDialog/OrderAddressEditDialog.tsx @@ -4,15 +4,13 @@ import DialogActions from "@material-ui/core/DialogActions"; import DialogContent from "@material-ui/core/DialogContent"; import DialogTitle from "@material-ui/core/DialogTitle"; import { makeStyles } from "@material-ui/core/styles"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import AddressEdit from "@saleor/components/AddressEdit"; import ConfirmButton, { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; import Form from "@saleor/components/Form"; import { AddressTypeInput } from "@saleor/customers/types"; +import { OrderErrorFragment } from "@saleor/fragments/types/OrderErrorFragment"; import useAddressValidation from "@saleor/hooks/useAddressValidation"; import useModalDialogErrors from "@saleor/hooks/useModalDialogErrors"; import useStateFromProps from "@saleor/hooks/useStateFromProps"; @@ -20,7 +18,8 @@ import { buttonMessages } from "@saleor/intl"; import { maybe } from "@saleor/misc"; import { AddressInput } from "@saleor/types/globalTypes"; import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler"; -import { OrderErrorFragment } from "@saleor/orders/types/OrderErrorFragment"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; const useStyles = makeStyles( { @@ -81,7 +80,7 @@ const OrderAddressEditDialog: React.FC = props => { return (
- {({ change, data, submit }) => { + {({ change, data }) => { const handleCountrySelect = createSingleAutocompleteSelectHandler( change, setCountryDisplayName, @@ -119,7 +118,6 @@ const OrderAddressEditDialog: React.FC = props => { transitionState={confirmButtonState} color="primary" variant="contained" - onClick={submit} type="submit" > diff --git a/src/orders/components/OrderBulkCancelDialog/OrderBulkCancelDialog.tsx b/src/orders/components/OrderBulkCancelDialog/OrderBulkCancelDialog.tsx index d8d073963..dca9ac17a 100644 --- a/src/orders/components/OrderBulkCancelDialog/OrderBulkCancelDialog.tsx +++ b/src/orders/components/OrderBulkCancelDialog/OrderBulkCancelDialog.tsx @@ -1,9 +1,8 @@ import DialogContentText from "@material-ui/core/DialogContentText"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import ActionDialog from "@saleor/components/ActionDialog"; import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; export interface OrderBulkCancelDialogProps { confirmButtonState: ConfirmButtonTransitionState; diff --git a/src/orders/components/OrderCancelDialog/OrderCancelDialog.tsx b/src/orders/components/OrderCancelDialog/OrderCancelDialog.tsx index 34748e33b..393c78591 100644 --- a/src/orders/components/OrderCancelDialog/OrderCancelDialog.tsx +++ b/src/orders/components/OrderCancelDialog/OrderCancelDialog.tsx @@ -4,17 +4,16 @@ import DialogActions from "@material-ui/core/DialogActions"; import DialogContent from "@material-ui/core/DialogContent"; import DialogContentText from "@material-ui/core/DialogContentText"; import DialogTitle from "@material-ui/core/DialogTitle"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import ConfirmButton, { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; -import { buttonMessages } from "@saleor/intl"; -import { OrderErrorFragment } from "@saleor/orders/types/OrderErrorFragment"; import FormSpacer from "@saleor/components/FormSpacer"; -import getOrderErrorMessage from "@saleor/utils/errors/order"; +import { OrderErrorFragment } from "@saleor/fragments/types/OrderErrorFragment"; import useModalDialogErrors from "@saleor/hooks/useModalDialogErrors"; +import { buttonMessages } from "@saleor/intl"; +import getOrderErrorMessage from "@saleor/utils/errors/order"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; export interface OrderCancelDialogProps { confirmButtonState: ConfirmButtonTransitionState; @@ -48,7 +47,7 @@ const OrderCancelDialog: React.FC = props => { /> - + = props => { {errors.length > 0 && ( <> - {errors.map(err => ( - + {errors.map((err, index) => ( + {getOrderErrorMessage(err, intl)} ))} diff --git a/src/orders/components/OrderCannotCancelOrderDialog/OrderCannotCancelOrderDialog.tsx b/src/orders/components/OrderCannotCancelOrderDialog/OrderCannotCancelOrderDialog.tsx index b2a515ea2..17b0c3cd0 100644 --- a/src/orders/components/OrderCannotCancelOrderDialog/OrderCannotCancelOrderDialog.tsx +++ b/src/orders/components/OrderCannotCancelOrderDialog/OrderCannotCancelOrderDialog.tsx @@ -5,11 +5,10 @@ import DialogContent from "@material-ui/core/DialogContent"; import DialogContentText from "@material-ui/core/DialogContentText"; import DialogTitle from "@material-ui/core/DialogTitle"; import makeStyles from "@material-ui/core/styles/makeStyles"; -import React from "react"; -import { FormattedMessage } from "react-intl"; - import { buttonMessages } from "@saleor/intl"; import { DialogProps } from "@saleor/types"; +import React from "react"; +import { FormattedMessage } from "react-intl"; const useStyles = makeStyles( theme => ({ diff --git a/src/orders/components/OrderCustomer/OrderCustomer.tsx b/src/orders/components/OrderCustomer/OrderCustomer.tsx index 999170f0c..ddcfe94df 100644 --- a/src/orders/components/OrderCustomer/OrderCustomer.tsx +++ b/src/orders/components/OrderCustomer/OrderCustomer.tsx @@ -3,9 +3,6 @@ import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; import { makeStyles } from "@material-ui/core/styles"; import Typography from "@material-ui/core/Typography"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import CardTitle from "@saleor/components/CardTitle"; import ExternalLink from "@saleor/components/ExternalLink"; import Form from "@saleor/components/Form"; @@ -20,6 +17,9 @@ import { SearchCustomers_search_edges_node } from "@saleor/searches/types/Search import { FetchMoreProps, UserPermissionProps } from "@saleor/types"; import { PermissionEnum } from "@saleor/types/globalTypes"; import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { customerUrl } from "../../../customers/urls"; import { createHref, maybe } from "../../../misc"; import { OrderDetails_order } from "../../types/OrderDetails"; diff --git a/src/orders/components/OrderCustomerNote/OrderCustomerNote.tsx b/src/orders/components/OrderCustomerNote/OrderCustomerNote.tsx index 84e456ec0..f6a96cb52 100644 --- a/src/orders/components/OrderCustomerNote/OrderCustomerNote.tsx +++ b/src/orders/components/OrderCustomerNote/OrderCustomerNote.tsx @@ -1,11 +1,10 @@ import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; import Typography from "@material-ui/core/Typography"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import CardTitle from "@saleor/components/CardTitle"; import Skeleton from "@saleor/components/Skeleton"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; interface OrderCustomerNoteProps { note: string; diff --git a/src/orders/components/OrderDetailsPage/OrderDetailsPage.tsx b/src/orders/components/OrderDetailsPage/OrderDetailsPage.tsx index 18bc44472..eb5ad5d68 100644 --- a/src/orders/components/OrderDetailsPage/OrderDetailsPage.tsx +++ b/src/orders/components/OrderDetailsPage/OrderDetailsPage.tsx @@ -1,18 +1,24 @@ import { makeStyles } from "@material-ui/core/styles"; import Typography from "@material-ui/core/Typography"; -import React from "react"; -import { useIntl } from "react-intl"; - import AppHeader from "@saleor/components/AppHeader"; import CardMenu from "@saleor/components/CardMenu"; import { CardSpacer } from "@saleor/components/CardSpacer"; +import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; import { Container } from "@saleor/components/Container"; import { DateTime } from "@saleor/components/Date"; +import Form from "@saleor/components/Form"; import Grid from "@saleor/components/Grid"; +import Metadata, { MetadataFormData } from "@saleor/components/Metadata"; import PageHeader from "@saleor/components/PageHeader"; +import SaveButtonBar from "@saleor/components/SaveButtonBar"; import Skeleton from "@saleor/components/Skeleton"; import { sectionNames } from "@saleor/intl"; import { UserPermissionProps } from "@saleor/types"; +import { mapMetadataItemToInput } from "@saleor/utils/maps"; +import useMetadataChangeTrigger from "@saleor/utils/metadata/useMetadataChangeTrigger"; +import React from "react"; +import { useIntl } from "react-intl"; + import { maybe, renderCollection } from "../../../misc"; import { OrderStatus } from "../../../types/globalTypes"; import { OrderDetails_order } from "../../types/OrderDetails"; @@ -20,6 +26,7 @@ import OrderCustomer from "../OrderCustomer"; import OrderCustomerNote from "../OrderCustomerNote"; import OrderFulfillment from "../OrderFulfillment"; import OrderHistory, { FormData as HistoryFormData } from "../OrderHistory"; +import OrderInvoiceList from "../OrderInvoiceList"; import OrderPayment from "../OrderPayment/OrderPayment"; import OrderUnfulfilledItems from "../OrderUnfulfilledItems/OrderUnfulfilledItems"; @@ -48,6 +55,8 @@ export interface OrderDetailsPageProps extends UserPermissionProps { code: string; label: string; }>; + disabled: boolean; + saveButtonBarState: ConfirmButtonTransitionState; onBack(); onBillingAddressEdit(); onFulfillmentCancel(id: string); @@ -62,11 +71,17 @@ export interface OrderDetailsPageProps extends UserPermissionProps { onOrderCancel(); onNoteAdd(data: HistoryFormData); onProfileView(); + onInvoiceClick(invoiceId: string); + onInvoiceGenerate(); + onInvoiceSend(invoiceId: string); + onSubmit(data: MetadataFormData); } const OrderDetailsPage: React.FC = props => { const { + disabled, order, + saveButtonBarState, userPermissions, onBack, onBillingAddressEdit, @@ -80,11 +95,20 @@ const OrderDetailsPage: React.FC = props => { onPaymentRefund, onPaymentVoid, onShippingAddressEdit, - onProfileView + onProfileView, + onInvoiceClick, + onInvoiceGenerate, + onInvoiceSend, + onSubmit } = props; const classes = useStyles(props); const intl = useIntl(); + const { + isMetadataModified, + isPrivateMetadataModified, + makeChangeHandler: makeMetadataChangeHandler + } = useMetadataChangeTrigger(); const canCancel = maybe(() => order.status) !== OrderStatus.CANCELED; const canEditAddresses = maybe(() => order.status) !== OrderStatus.CANCELED; @@ -93,96 +117,138 @@ const OrderDetailsPage: React.FC = props => { line => line.quantityFulfilled < line.quantity ); + const handleSubmit = (data: MetadataFormData) => { + const metadata = isMetadataModified ? data.metadata : undefined; + const privateMetadata = isPrivateMetadataModified + ? data.privateMetadata + : undefined; + + onSubmit({ + metadata, + privateMetadata + }); + }; + + const initial: MetadataFormData = { + metadata: order?.metadata.map(mapMetadataItemToInput), + privateMetadata: order?.privateMetadata.map(mapMetadataItemToInput) + }; + return ( - - - {intl.formatMessage(sectionNames.orders)} - - order.number) ? "#" + order.number : undefined} - > - {canCancel && ( - - )} - -
- {order && order.created ? ( - - - - ) : ( - - )} -
- -
- {unfulfilled.length > 0 && ( - - )} - {renderCollection( - maybe(() => order.fulfillments), - (fulfillment, fulfillmentIndex) => ( - fulfillment.id, "loading")}> - {!(unfulfilled.length === 0 && fulfillmentIndex === 0) && ( - - )} - order.number)} - onOrderFulfillmentCancel={() => - onFulfillmentCancel(fulfillment.id) - } - onTrackingCodeAdd={() => - onFulfillmentTrackingNumberUpdate(fulfillment.id) - } + + {({ change, data, hasChanged, submit }) => { + const changeMetadata = makeMetadataChangeHandler(change); + + return ( + + + {intl.formatMessage(sectionNames.orders)} + + order.number) ? "#" + order.number : undefined} + > + {canCancel && ( + - - ) - )} - - - order.events)} - onNoteAdd={onNoteAdd} - /> -
-
- - - order.customerNote)} /> -
-
-
+ )} + +
+ {order && order.created ? ( + + + + ) : ( + + )} +
+ +
+ {unfulfilled.length > 0 && ( + + )} + {renderCollection( + maybe(() => order.fulfillments), + (fulfillment, fulfillmentIndex) => ( + fulfillment.id, "loading")} + > + {!( + unfulfilled.length === 0 && fulfillmentIndex === 0 + ) && } + order.number)} + onOrderFulfillmentCancel={() => + onFulfillmentCancel(fulfillment.id) + } + onTrackingCodeAdd={() => + onFulfillmentTrackingNumberUpdate(fulfillment.id) + } + /> + + ) + )} + + + + + order.events)} + onNoteAdd={onNoteAdd} + /> +
+
+ + + + + order.customerNote)} /> +
+
+ + + ); + }} + ); }; OrderDetailsPage.displayName = "OrderDetailsPage"; diff --git a/src/orders/components/OrderDraftCancelDialog/OrderDraftCancelDialog.tsx b/src/orders/components/OrderDraftCancelDialog/OrderDraftCancelDialog.tsx index 7e40705e1..403d07f32 100644 --- a/src/orders/components/OrderDraftCancelDialog/OrderDraftCancelDialog.tsx +++ b/src/orders/components/OrderDraftCancelDialog/OrderDraftCancelDialog.tsx @@ -1,13 +1,12 @@ import DialogContentText from "@material-ui/core/DialogContentText"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import ActionDialog from "@saleor/components/ActionDialog"; import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; -import { OrderErrorFragment } from "@saleor/orders/types/OrderErrorFragment"; -import useModalDialogErrors from "@saleor/hooks/useModalDialogErrors"; import FormSpacer from "@saleor/components/FormSpacer"; +import { OrderErrorFragment } from "@saleor/fragments/types/OrderErrorFragment"; +import useModalDialogErrors from "@saleor/hooks/useModalDialogErrors"; import getOrderErrorMessage from "@saleor/utils/errors/order"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; export interface OrderDraftCancelDialogProps { confirmButtonState: ConfirmButtonTransitionState; @@ -41,7 +40,7 @@ const OrderDraftCancelDialog: React.FC = ({ })} variant="delete" > - + = ({ {errors.length > 0 && ( <> - {errors.map(err => ( - + {errors.map((err, index) => ( + {getOrderErrorMessage(err, intl)} ))} diff --git a/src/orders/components/OrderDraftDetails/OrderDraftDetails.tsx b/src/orders/components/OrderDraftDetails/OrderDraftDetails.tsx index 729552ce9..f495c45b5 100644 --- a/src/orders/components/OrderDraftDetails/OrderDraftDetails.tsx +++ b/src/orders/components/OrderDraftDetails/OrderDraftDetails.tsx @@ -1,10 +1,10 @@ import Button from "@material-ui/core/Button"; import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; +import CardTitle from "@saleor/components/CardTitle"; import React from "react"; import { FormattedMessage, useIntl } from "react-intl"; -import CardTitle from "@saleor/components/CardTitle"; import { maybe } from "../../../misc"; import { OrderDetails_order } from "../../types/OrderDetails"; import OrderDraftDetailsProducts, { diff --git a/src/orders/components/OrderDraftDetailsProducts/OrderDraftDetailsProducts.tsx b/src/orders/components/OrderDraftDetailsProducts/OrderDraftDetailsProducts.tsx index c1e2af9de..c5fb64609 100644 --- a/src/orders/components/OrderDraftDetailsProducts/OrderDraftDetailsProducts.tsx +++ b/src/orders/components/OrderDraftDetailsProducts/OrderDraftDetailsProducts.tsx @@ -7,9 +7,6 @@ import TableRow from "@material-ui/core/TableRow"; import TextField from "@material-ui/core/TextField"; import Typography from "@material-ui/core/Typography"; import DeleteIcon from "@material-ui/icons/Delete"; -import React from "react"; -import { FormattedMessage } from "react-intl"; - import { DebounceForm } from "@saleor/components/DebounceForm"; import Form from "@saleor/components/Form"; import Money from "@saleor/components/Money"; @@ -18,6 +15,9 @@ import Skeleton from "@saleor/components/Skeleton"; import TableCellAvatar, { AVATAR_MARGIN } from "@saleor/components/TableCellAvatar"; +import React from "react"; +import { FormattedMessage } from "react-intl"; + import { maybe, renderCollection } from "../../../misc"; import { OrderDetails_order_lines } from "../../types/OrderDetails"; @@ -51,6 +51,9 @@ const useStyles = makeStyles( textAlign: "right", width: 150 }, + errorInfo: { + color: theme.palette.error.main + }, quantityField: { "& input": { padding: "12px 12px 10px", @@ -71,9 +74,7 @@ interface OrderDraftDetailsProductsProps { onOrderLineRemove: (id: string) => void; } -const OrderDraftDetailsProducts: React.FC< - OrderDraftDetailsProductsProps -> = props => { +const OrderDraftDetailsProducts: React.FC = props => { const { lines, onOrderLineChange, onOrderLineRemove } = props; const classes = useStyles(props); @@ -128,6 +129,30 @@ const OrderDraftDetailsProducts: React.FC< <> {line.productName} {line.productSku} + {!line.variant.quantityAvailable ? ( + + + + ) : !line.variant.product.isAvailableForPurchase ? ( + + + + ) : ( + !line.variant.product.isPublished && ( + + + + ) + )} ) : ( @@ -153,6 +178,7 @@ const OrderDraftDetailsProducts: React.FC< type="number" value={data.quantity} onChange={debounce} + onBlur={submit} /> )} diff --git a/src/orders/components/OrderDraftDetailsSummary/OrderDraftDetailsSummary.tsx b/src/orders/components/OrderDraftDetailsSummary/OrderDraftDetailsSummary.tsx index 93d463280..4bfe8e8c3 100644 --- a/src/orders/components/OrderDraftDetailsSummary/OrderDraftDetailsSummary.tsx +++ b/src/orders/components/OrderDraftDetailsSummary/OrderDraftDetailsSummary.tsx @@ -1,10 +1,10 @@ import { makeStyles } from "@material-ui/core/styles"; -import React from "react"; -import { FormattedMessage } from "react-intl"; - import Link from "@saleor/components/Link"; import Money from "@saleor/components/Money"; import Skeleton from "@saleor/components/Skeleton"; +import React from "react"; +import { FormattedMessage } from "react-intl"; + import { maybe } from "../../../misc"; import { OrderDetails_order } from "../../types/OrderDetails"; @@ -27,9 +27,7 @@ interface OrderDraftDetailsSummaryProps { onShippingMethodEdit: () => void; } -const OrderDraftDetailsSummary: React.FC< - OrderDraftDetailsSummaryProps -> = props => { +const OrderDraftDetailsSummary: React.FC = props => { const { order, onShippingMethodEdit } = props; const classes = useStyles(props); diff --git a/src/orders/components/OrderDraftFinalizeDialog/OrderDraftFinalizeDialog.tsx b/src/orders/components/OrderDraftFinalizeDialog/OrderDraftFinalizeDialog.tsx index a46816752..ba8ab3482 100644 --- a/src/orders/components/OrderDraftFinalizeDialog/OrderDraftFinalizeDialog.tsx +++ b/src/orders/components/OrderDraftFinalizeDialog/OrderDraftFinalizeDialog.tsx @@ -1,13 +1,12 @@ import DialogContentText from "@material-ui/core/DialogContentText"; -import React from "react"; -import { FormattedMessage, IntlShape, useIntl } from "react-intl"; - import ActionDialog from "@saleor/components/ActionDialog"; import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; -import { OrderErrorFragment } from "@saleor/orders/types/OrderErrorFragment"; -import useModalDialogErrors from "@saleor/hooks/useModalDialogErrors"; import FormSpacer from "@saleor/components/FormSpacer"; +import { OrderErrorFragment } from "@saleor/fragments/types/OrderErrorFragment"; +import useModalDialogErrors from "@saleor/hooks/useModalDialogErrors"; import getOrderErrorMessage from "@saleor/utils/errors/order"; +import React from "react"; +import { FormattedMessage, IntlShape, useIntl } from "react-intl"; export enum OrderDraftFinalizeWarning { NO_SHIPPING, @@ -110,8 +109,8 @@ const OrderDraftFinalizeDialog: React.FC = ({ {errors.length > 0 && ( <> - {errors.map(err => ( - + {errors.map((err, index) => ( + {getOrderErrorMessage(err, intl)} ))} diff --git a/src/orders/components/OrderDraftList/OrderDraftList.tsx b/src/orders/components/OrderDraftList/OrderDraftList.tsx index 1b572d3a6..207e9bb89 100644 --- a/src/orders/components/OrderDraftList/OrderDraftList.tsx +++ b/src/orders/components/OrderDraftList/OrderDraftList.tsx @@ -3,14 +3,12 @@ import TableBody from "@material-ui/core/TableBody"; import TableCell from "@material-ui/core/TableCell"; import TableFooter from "@material-ui/core/TableFooter"; import TableRow from "@material-ui/core/TableRow"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import Checkbox from "@saleor/components/Checkbox"; import { DateTime } from "@saleor/components/Date"; import Money from "@saleor/components/Money"; import ResponsiveTable from "@saleor/components/ResponsiveTable"; import Skeleton from "@saleor/components/Skeleton"; +import TableCellHeader from "@saleor/components/TableCellHeader"; import TableHead from "@saleor/components/TableHead"; import TablePagination from "@saleor/components/TablePagination"; import { @@ -19,10 +17,12 @@ import { transformOrderStatus, transformPaymentStatus } from "@saleor/misc"; -import { ListActions, ListProps, SortPage } from "@saleor/types"; import { OrderDraftListUrlSortField } from "@saleor/orders/urls"; -import TableCellHeader from "@saleor/components/TableCellHeader"; +import { ListActions, ListProps, SortPage } from "@saleor/types"; import { getArrowDirection } from "@saleor/utils/sort"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { OrderDraftList_draftOrders_edges_node } from "../../types/OrderDraftList"; const useStyles = makeStyles( diff --git a/src/orders/components/OrderDraftListPage/OrderDraftListPage.tsx b/src/orders/components/OrderDraftListPage/OrderDraftListPage.tsx index 83b6ec50d..a884c6830 100644 --- a/src/orders/components/OrderDraftListPage/OrderDraftListPage.tsx +++ b/src/orders/components/OrderDraftListPage/OrderDraftListPage.tsx @@ -1,27 +1,26 @@ import Button from "@material-ui/core/Button"; import Card from "@material-ui/core/Card"; - +import Container from "@saleor/components/Container"; +import FilterBar from "@saleor/components/FilterBar"; +import PageHeader from "@saleor/components/PageHeader"; +import { sectionNames } from "@saleor/intl"; +import { OrderDraftListUrlSortField } from "@saleor/orders/urls"; +import { + FilterPageProps, + ListActions, + PageListProps, + SortPage, + TabPageProps +} from "@saleor/types"; import React from "react"; import { FormattedMessage, useIntl } from "react-intl"; -import Container from "@saleor/components/Container"; -import PageHeader from "@saleor/components/PageHeader"; -import { sectionNames } from "@saleor/intl"; -import { - ListActions, - PageListProps, - TabPageProps, - SortPage, - FilterPageProps -} from "@saleor/types"; -import { OrderDraftListUrlSortField } from "@saleor/orders/urls"; -import FilterBar from "@saleor/components/FilterBar"; -import OrderDraftList from "../OrderDraftList"; import { OrderDraftList_draftOrders_edges_node } from "../../types/OrderDraftList"; +import OrderDraftList from "../OrderDraftList"; import { - OrderDraftListFilterOpts, + createFilterStructure, OrderDraftFilterKeys, - createFilterStructure + OrderDraftListFilterOpts } from "./filters"; export interface OrderDraftListPageProps diff --git a/src/orders/components/OrderDraftListPage/filters.ts b/src/orders/components/OrderDraftListPage/filters.ts index 9824461f8..6dcb557a9 100644 --- a/src/orders/components/OrderDraftListPage/filters.ts +++ b/src/orders/components/OrderDraftListPage/filters.ts @@ -1,8 +1,7 @@ -import { IntlShape, defineMessages } from "react-intl"; - +import { IFilter } from "@saleor/components/Filter"; import { FilterOpts, MinMax } from "@saleor/types"; import { createDateField, createTextField } from "@saleor/utils/filters/fields"; -import { IFilter } from "@saleor/components/Filter"; +import { defineMessages, IntlShape } from "react-intl"; export enum OrderDraftFilterKeys { created = "created", diff --git a/src/orders/components/OrderDraftPage/OrderDraftPage.tsx b/src/orders/components/OrderDraftPage/OrderDraftPage.tsx index 2a4de7342..7e1c1e058 100644 --- a/src/orders/components/OrderDraftPage/OrderDraftPage.tsx +++ b/src/orders/components/OrderDraftPage/OrderDraftPage.tsx @@ -1,8 +1,5 @@ import { makeStyles } from "@material-ui/core/styles"; import Typography from "@material-ui/core/Typography"; -import React from "react"; -import { useIntl } from "react-intl"; - import AppHeader from "@saleor/components/AppHeader"; import CardMenu from "@saleor/components/CardMenu"; import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; @@ -15,6 +12,9 @@ import Skeleton from "@saleor/components/Skeleton"; import { sectionNames } from "@saleor/intl"; import { SearchCustomers_search_edges_node } from "@saleor/searches/types/SearchCustomers"; import { FetchMoreProps, UserPermissionProps } from "@saleor/types"; +import React from "react"; +import { useIntl } from "react-intl"; + import { maybe } from "../../../misc"; import { DraftOrderInput } from "../../../types/globalTypes"; import { OrderDetails_order } from "../../types/OrderDetails"; diff --git a/src/orders/components/OrderFulfillPage/OrderFulfillPage.stories.tsx b/src/orders/components/OrderFulfillPage/OrderFulfillPage.stories.tsx index e348b0cdc..5fd129448 100644 --- a/src/orders/components/OrderFulfillPage/OrderFulfillPage.stories.tsx +++ b/src/orders/components/OrderFulfillPage/OrderFulfillPage.stories.tsx @@ -1,11 +1,11 @@ +import Decorator from "@saleor/storybook/Decorator"; +import { OrderErrorCode } from "@saleor/types/globalTypes"; +import { warehouseList } from "@saleor/warehouses/fixtures"; import { storiesOf } from "@storybook/react"; import React from "react"; -import Decorator from "@saleor/storybook/Decorator"; -import { warehouseList } from "@saleor/warehouses/fixtures"; -import { OrderErrorCode } from "@saleor/types/globalTypes"; -import OrderFulfillPage, { OrderFulfillPageProps } from "./OrderFulfillPage"; import { orderToFulfill } from "./fixtures"; +import OrderFulfillPage, { OrderFulfillPageProps } from "./OrderFulfillPage"; const props: OrderFulfillPageProps = { disabled: false, diff --git a/src/orders/components/OrderFulfillPage/OrderFulfillPage.tsx b/src/orders/components/OrderFulfillPage/OrderFulfillPage.tsx index 9ba8d9c15..e8e157f5b 100644 --- a/src/orders/components/OrderFulfillPage/OrderFulfillPage.tsx +++ b/src/orders/components/OrderFulfillPage/OrderFulfillPage.tsx @@ -1,41 +1,40 @@ -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; import Card from "@material-ui/core/Card"; import CardActions from "@material-ui/core/CardActions"; +import { makeStyles, Theme } from "@material-ui/core/styles"; import TableBody from "@material-ui/core/TableBody"; import TableCell from "@material-ui/core/TableCell"; import TableHead from "@material-ui/core/TableHead"; import TableRow from "@material-ui/core/TableRow"; import TextField from "@material-ui/core/TextField"; -import classNames from "classnames"; import Typography from "@material-ui/core/Typography"; - -import useFormset, { FormsetData } from "@saleor/hooks/useFormset"; -import { - OrderFulfillStockInput, - OrderErrorCode -} from "@saleor/types/globalTypes"; -import { WarehouseFragment } from "@saleor/warehouses/types/WarehouseFragment"; -import TableCellAvatar from "@saleor/components/TableCellAvatar"; -import Container from "@saleor/components/Container"; -import PageHeader from "@saleor/components/PageHeader"; -import SaveButtonBar from "@saleor/components/SaveButtonBar"; +import { CSSProperties } from "@material-ui/styles"; +import AppHeader from "@saleor/components/AppHeader"; +import CardTitle from "@saleor/components/CardTitle"; import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; +import Container from "@saleor/components/Container"; +import ControlledCheckbox from "@saleor/components/ControlledCheckbox"; import Form from "@saleor/components/Form"; +import PageHeader from "@saleor/components/PageHeader"; +import ResponsiveTable from "@saleor/components/ResponsiveTable"; +import SaveButtonBar from "@saleor/components/SaveButtonBar"; +import Skeleton from "@saleor/components/Skeleton"; +import TableCellAvatar from "@saleor/components/TableCellAvatar"; +import { WarehouseFragment } from "@saleor/fragments/types/WarehouseFragment"; +import useFormset, { FormsetData } from "@saleor/hooks/useFormset"; +import { renderCollection } from "@saleor/misc"; +import { FulfillOrder_orderFulfill_errors } from "@saleor/orders/types/FulfillOrder"; import { OrderFulfillData_order, OrderFulfillData_order_lines } from "@saleor/orders/types/OrderFulfillData"; -import CardTitle from "@saleor/components/CardTitle"; -import ResponsiveTable from "@saleor/components/ResponsiveTable"; -import { Theme, makeStyles } from "@material-ui/core/styles"; +import { + OrderErrorCode, + OrderFulfillStockInput +} from "@saleor/types/globalTypes"; import { update } from "@saleor/utils/lists"; -import ControlledCheckbox from "@saleor/components/ControlledCheckbox"; -import { renderCollection } from "@saleor/misc"; -import Skeleton from "@saleor/components/Skeleton"; -import AppHeader from "@saleor/components/AppHeader"; -import { FulfillOrder_orderFulfill_errors } from "@saleor/orders/types/FulfillOrder"; -import { CSSProperties } from "@material-ui/styles"; +import classNames from "classnames"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; type ClassKey = | "actionBar" @@ -261,7 +260,7 @@ const OrderFulfillPage: React.FC = props => { (line, lineIndex) => { if (!line) { return ( - + @@ -327,6 +326,7 @@ const OrderFulfillPage: React.FC = props => { if (!warehouseStock) { return ( = props => { .variant.trackInventory } ), - max: + max: ( line.variant.trackInventory && - warehouseStock.quantity, + warehouseStock.quantity + ).toString(), min: 0, style: { textAlign: "right" } }} @@ -410,7 +411,10 @@ const OrderFulfillPage: React.FC = props => { ); })} - + = props => { /> + + + = props => { > {maybe(() => line.orderLine.productName) || } + + {line?.orderLine.productSku || } + - {maybe(() => line.quantity) || } + {line?.quantity || } {maybe(() => line.orderLine.unitPrice.gross) ? ( @@ -278,6 +292,16 @@ const OrderFulfillment: React.FC = props => { )} + {status === FulfillmentStatus.FULFILLED && fulfillment.trackingNumber && ( + + + + )} ); }; diff --git a/src/orders/components/OrderFulfillmentCancelDialog/OrderFulfillmentCancelDialog.tsx b/src/orders/components/OrderFulfillmentCancelDialog/OrderFulfillmentCancelDialog.tsx index 653b865b1..256a40ae2 100644 --- a/src/orders/components/OrderFulfillmentCancelDialog/OrderFulfillmentCancelDialog.tsx +++ b/src/orders/components/OrderFulfillmentCancelDialog/OrderFulfillmentCancelDialog.tsx @@ -5,20 +5,19 @@ import DialogContent from "@material-ui/core/DialogContent"; import DialogContentText from "@material-ui/core/DialogContentText"; import DialogTitle from "@material-ui/core/DialogTitle"; import { makeStyles } from "@material-ui/core/styles"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import ConfirmButton, { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; import Form from "@saleor/components/Form"; -import { buttonMessages } from "@saleor/intl"; -import { OrderErrorFragment } from "@saleor/orders/types/OrderErrorFragment"; import FormSpacer from "@saleor/components/FormSpacer"; -import getOrderErrorMessage from "@saleor/utils/errors/order"; -import { WarehouseFragment } from "@saleor/warehouses/types/WarehouseFragment"; import SingleAutocompleteSelectField from "@saleor/components/SingleAutocompleteSelectField"; +import { OrderErrorFragment } from "@saleor/fragments/types/OrderErrorFragment"; +import { WarehouseFragment } from "@saleor/fragments/types/WarehouseFragment"; +import { buttonMessages } from "@saleor/intl"; +import getOrderErrorMessage from "@saleor/utils/errors/order"; import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; export interface OrderFulfillmentCancelDialogFormData { warehouseId: string; @@ -112,8 +111,8 @@ const OrderFulfillmentCancelDialog: React.FC {errors.length > 0 && ( <> - {errors.map(err => ( - + {errors.map((err, index) => ( + {getOrderErrorMessage(err, intl)} ))} diff --git a/src/orders/components/OrderFulfillmentDialog/OrderFulfillmentDialog.tsx b/src/orders/components/OrderFulfillmentDialog/OrderFulfillmentDialog.tsx index 54183723b..6ac29031a 100644 --- a/src/orders/components/OrderFulfillmentDialog/OrderFulfillmentDialog.tsx +++ b/src/orders/components/OrderFulfillmentDialog/OrderFulfillmentDialog.tsx @@ -10,9 +10,6 @@ import TableCell from "@material-ui/core/TableCell"; import TableHead from "@material-ui/core/TableHead"; import TableRow from "@material-ui/core/TableRow"; import TextField from "@material-ui/core/TextField"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import ConfirmButton, { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; @@ -22,12 +19,15 @@ import ResponsiveTable from "@saleor/components/ResponsiveTable"; import TableCellAvatar, { AVATAR_MARGIN } from "@saleor/components/TableCellAvatar"; +import { OrderErrorFragment } from "@saleor/fragments/types/OrderErrorFragment"; import { buttonMessages } from "@saleor/intl"; -import { OrderErrorFragment } from "@saleor/orders/types/OrderErrorFragment"; import { getFormErrors } from "@saleor/utils/errors"; import getOrderErrorMessage from "@saleor/utils/errors/order"; -import { OrderDetails_order_lines } from "../../types/OrderDetails"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { maybe } from "../../../misc"; +import { OrderDetails_order_lines } from "../../types/OrderDetails"; export interface FormData { lines: number[]; @@ -164,7 +164,7 @@ const OrderFulfillmentDialog: React.FC = props => { = props => { {errors .filter(err => !formFields.includes(err.field)) - .map(err => ( - + .map((err, index) => ( + {getOrderErrorMessage(err, intl)} ))} diff --git a/src/orders/components/OrderFulfillmentTrackingDialog/OrderFulfillmentTrackingDialog.tsx b/src/orders/components/OrderFulfillmentTrackingDialog/OrderFulfillmentTrackingDialog.tsx index 41fa5ac54..93a119b2f 100644 --- a/src/orders/components/OrderFulfillmentTrackingDialog/OrderFulfillmentTrackingDialog.tsx +++ b/src/orders/components/OrderFulfillmentTrackingDialog/OrderFulfillmentTrackingDialog.tsx @@ -5,19 +5,18 @@ import DialogContent from "@material-ui/core/DialogContent"; import DialogContentText from "@material-ui/core/DialogContentText"; import DialogTitle from "@material-ui/core/DialogTitle"; import TextField from "@material-ui/core/TextField"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import ConfirmButton, { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; import Form from "@saleor/components/Form"; -import { buttonMessages } from "@saleor/intl"; -import { OrderErrorFragment } from "@saleor/orders/types/OrderErrorFragment"; -import useModalDialogErrors from "@saleor/hooks/useModalDialogErrors"; -import getOrderErrorMessage from "@saleor/utils/errors/order"; -import { getFormErrors } from "@saleor/utils/errors"; import FormSpacer from "@saleor/components/FormSpacer"; +import { OrderErrorFragment } from "@saleor/fragments/types/OrderErrorFragment"; +import useModalDialogErrors from "@saleor/hooks/useModalDialogErrors"; +import { buttonMessages } from "@saleor/intl"; +import { getFormErrors } from "@saleor/utils/errors"; +import getOrderErrorMessage from "@saleor/utils/errors/order"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; export interface FormData { trackingNumber: string; @@ -77,8 +76,8 @@ const OrderFulfillmentTrackingDialog: React.FC {errors .filter(err => !formFields.includes(err.field)) - .map(err => ( - + .map((err, index) => ( + {getOrderErrorMessage(err, intl)} ))} diff --git a/src/orders/components/OrderHistory/OrderHistory.tsx b/src/orders/components/OrderHistory/OrderHistory.tsx index 8c1e84fcc..e2881ff00 100644 --- a/src/orders/components/OrderHistory/OrderHistory.tsx +++ b/src/orders/components/OrderHistory/OrderHistory.tsx @@ -1,8 +1,5 @@ import { makeStyles } from "@material-ui/core/styles"; import Typography from "@material-ui/core/Typography"; -import React from "react"; -import { FormattedMessage, IntlShape, useIntl } from "react-intl"; - import Form from "@saleor/components/Form"; import Hr from "@saleor/components/Hr"; import Skeleton from "@saleor/components/Skeleton"; @@ -12,6 +9,9 @@ import { TimelineEvent, TimelineNote } from "@saleor/components/Timeline"; +import React from "react"; +import { FormattedMessage, IntlShape, useIntl } from "react-intl"; + import { OrderEventsEmailsEnum, OrderEventsEnum @@ -76,12 +76,64 @@ const getEventMessage = (event: OrderDetails_order_events, intl: IntlShape) => { defaultMessage: "Shipping tracking number was sent to customer", description: "order history message" }); + case OrderEventsEmailsEnum.ORDER_CANCEL: + return intl.formatMessage({ + defaultMessage: "Order cancel information was sent to customer", + description: "order history message" + }); + case OrderEventsEmailsEnum.ORDER_REFUND: + return intl.formatMessage({ + defaultMessage: "Order refund information was sent to customer", + description: "order history message" + }); } case OrderEventsEnum.FULFILLMENT_CANCELED: return intl.formatMessage({ defaultMessage: "Fulfillment was cancelled", description: "order history message" }); + case OrderEventsEnum.INVOICE_REQUESTED: + return intl.formatMessage( + { + defaultMessage: "Invoice was requested by {requestedBy}", + description: "order history message" + }, + { + requestedBy: event.user ? event.user.email : null + } + ); + case OrderEventsEnum.INVOICE_GENERATED: + return intl.formatMessage( + { + defaultMessage: + "Invoice no. {invoiceNumber} was generated by {generatedBy}", + description: "order history message" + }, + { + generatedBy: event.user ? event.user.email : null, + invoiceNumber: event.invoiceNumber + } + ); + case OrderEventsEnum.INVOICE_UPDATED: + return intl.formatMessage( + { + defaultMessage: "Invoice no. {invoiceNumber} was updated", + description: "order history message" + }, + { + invoiceNumber: event.invoiceNumber + } + ); + case OrderEventsEnum.INVOICE_SENT: + return intl.formatMessage( + { + defaultMessage: "Invoice was sent to customer by {sentBy}", + description: "order history message" + }, + { + sentBy: event.user ? event.user.email : null + } + ); case OrderEventsEnum.FULFILLMENT_FULFILLED_ITEMS: return intl.formatMessage( { @@ -169,6 +221,13 @@ const getEventMessage = (event: OrderDetails_order_events, intl: IntlShape) => { defaultMessage: "Order address was updated", description: "order history message" }); + case OrderEventsEnum.PAYMENT_AUTHORIZED: + return intl.formatMessage({ + defaultMessage: "Payment was authorized", + description: "order history message" + }); + case OrderEventsEnum.EXTERNAL_SERVICE_NOTIFICATION: + return event.message; } }; diff --git a/src/orders/components/OrderInvoiceEmailSendDialog/OrderInvoiceEmailSendDialog.tsx b/src/orders/components/OrderInvoiceEmailSendDialog/OrderInvoiceEmailSendDialog.tsx new file mode 100644 index 000000000..639c79e94 --- /dev/null +++ b/src/orders/components/OrderInvoiceEmailSendDialog/OrderInvoiceEmailSendDialog.tsx @@ -0,0 +1,81 @@ +import Button from "@material-ui/core/Button"; +import Dialog from "@material-ui/core/Dialog"; +import DialogActions from "@material-ui/core/DialogActions"; +import DialogContent from "@material-ui/core/DialogContent"; +import DialogContentText from "@material-ui/core/DialogContentText"; +import DialogTitle from "@material-ui/core/DialogTitle"; +import ConfirmButton, { + ConfirmButtonTransitionState +} from "@saleor/components/ConfirmButton"; +import FormSpacer from "@saleor/components/FormSpacer"; +import { InvoiceErrorFragment } from "@saleor/fragments/types/InvoiceErrorFragment"; +import { InvoiceFragment } from "@saleor/fragments/types/InvoiceFragment"; +import { buttonMessages } from "@saleor/intl"; +import { DialogProps } from "@saleor/types"; +import getInvoiceErrorMessage from "@saleor/utils/errors/invoice"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + +export interface OrderInvoiceEmailSendDialogProps extends DialogProps { + confirmButtonState: ConfirmButtonTransitionState; + errors: InvoiceErrorFragment[]; + invoice: InvoiceFragment; + onSend: () => void; +} + +const OrderInvoiceEmailSendDialog: React.FC = ({ + confirmButtonState, + errors, + open, + invoice, + onClose, + onSend +}) => { + const intl = useIntl(); + + return ( + + + {intl.formatMessage({ + defaultMessage: "Send Invoice", + description: "dialog header" + })} + + + + {invoice?.number} + }} + /> + + {errors.length > 0 && ( + <> + + {errors.map((err, idx) => ( + + {getInvoiceErrorMessage(err, intl)} + + ))} + + )} + + + + + + + + + ); +}; +OrderInvoiceEmailSendDialog.displayName = "OrderInvoiceEmailSendDialog"; +export default OrderInvoiceEmailSendDialog; diff --git a/src/orders/components/OrderInvoiceEmailSendDialog/index.ts b/src/orders/components/OrderInvoiceEmailSendDialog/index.ts new file mode 100644 index 000000000..62455152a --- /dev/null +++ b/src/orders/components/OrderInvoiceEmailSendDialog/index.ts @@ -0,0 +1,2 @@ +export { default } from "./OrderInvoiceEmailSendDialog"; +export * from "./OrderInvoiceEmailSendDialog"; diff --git a/src/orders/components/OrderInvoiceList/OrderInvoiceList.tsx b/src/orders/components/OrderInvoiceList/OrderInvoiceList.tsx new file mode 100644 index 000000000..73d8d9e0a --- /dev/null +++ b/src/orders/components/OrderInvoiceList/OrderInvoiceList.tsx @@ -0,0 +1,128 @@ +import Button from "@material-ui/core/Button"; +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import { makeStyles } from "@material-ui/core/styles"; +import TableBody from "@material-ui/core/TableBody"; +import TableCell from "@material-ui/core/TableCell"; +import TableRow from "@material-ui/core/TableRow"; +import Typography from "@material-ui/core/Typography"; +import CardTitle from "@saleor/components/CardTitle"; +import Date from "@saleor/components/Date"; +import ResponsiveTable from "@saleor/components/ResponsiveTable"; +import Skeleton from "@saleor/components/Skeleton"; +import { InvoiceFragment } from "@saleor/fragments/types/InvoiceFragment"; +import { buttonMessages } from "@saleor/intl"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + +const useStyles = makeStyles( + () => ({ + cardContentTable: { + "&:last-child": { + padding: 0 + }, + padding: 0 + }, + colAction: { paddingRight: "0.5rem", width: "auto" }, + colNumber: { width: "100%" }, + colNumberClickable: { + cursor: "pointer", + width: "100%" + } + }), + { name: "OrderInvoiceList" } +); + +export interface OrderInvoiceListProps { + invoices: InvoiceFragment[]; + onInvoiceGenerate: () => void; + onInvoiceClick: (invoiceId: string) => void; + onInvoiceSend: (invoiceId: string) => void; +} + +const OrderInvoiceList: React.FC = props => { + const { invoices, onInvoiceGenerate, onInvoiceClick, onInvoiceSend } = props; + + const classes = useStyles(props); + + const intl = useIntl(); + + const generatedInvoices = invoices?.filter( + invoice => invoice.status === "SUCCESS" + ); + + return ( + + + + + ) + } + /> + + {!generatedInvoices ? ( + + ) : !generatedInvoices?.length ? ( + + + + ) : ( + + + {generatedInvoices.map(invoice => ( + + onInvoiceClick(invoice.id)} + > + {" "} + {invoice.number} + + {" "} + + + + {onInvoiceSend && ( + onInvoiceSend(invoice.id)} + > + + + )} + + ))} + + + )} + + + ); +}; + +OrderInvoiceList.displayName = "OrderInvoiceList"; +export default OrderInvoiceList; diff --git a/src/orders/components/OrderInvoiceList/index.ts b/src/orders/components/OrderInvoiceList/index.ts new file mode 100644 index 000000000..155c0f16e --- /dev/null +++ b/src/orders/components/OrderInvoiceList/index.ts @@ -0,0 +1,2 @@ +export { default } from "./OrderInvoiceList"; +export * from "./OrderInvoiceList"; diff --git a/src/orders/components/OrderList/OrderList.tsx b/src/orders/components/OrderList/OrderList.tsx index b119bf771..7a2dca9a6 100644 --- a/src/orders/components/OrderList/OrderList.tsx +++ b/src/orders/components/OrderList/OrderList.tsx @@ -2,16 +2,14 @@ import { makeStyles } from "@material-ui/core/styles"; import TableBody from "@material-ui/core/TableBody"; import TableCell from "@material-ui/core/TableCell"; import TableFooter from "@material-ui/core/TableFooter"; -import TableRow from "@material-ui/core/TableRow"; import TableHead from "@material-ui/core/TableHead"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - +import TableRow from "@material-ui/core/TableRow"; import { DateTime } from "@saleor/components/Date"; import Money from "@saleor/components/Money"; import ResponsiveTable from "@saleor/components/ResponsiveTable"; import Skeleton from "@saleor/components/Skeleton"; import StatusLabel from "@saleor/components/StatusLabel"; +import TableCellHeader from "@saleor/components/TableCellHeader"; import TablePagination from "@saleor/components/TablePagination"; import { maybe, @@ -19,10 +17,12 @@ import { transformOrderStatus, transformPaymentStatus } from "@saleor/misc"; -import { ListProps, SortPage } from "@saleor/types"; import { OrderListUrlSortField } from "@saleor/orders/urls"; -import TableCellHeader from "@saleor/components/TableCellHeader"; +import { ListProps, SortPage } from "@saleor/types"; import { getArrowDirection } from "@saleor/utils/sort"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { OrderList_orders_edges_node } from "../../types/OrderList"; const useStyles = makeStyles( diff --git a/src/orders/components/OrderListPage/OrderListPage.tsx b/src/orders/components/OrderListPage/OrderListPage.tsx index aaf2e7141..8eb78de0c 100644 --- a/src/orders/components/OrderListPage/OrderListPage.tsx +++ b/src/orders/components/OrderListPage/OrderListPage.tsx @@ -1,21 +1,20 @@ import Button from "@material-ui/core/Button"; import Card from "@material-ui/core/Card"; - +import Container from "@saleor/components/Container"; +import FilterBar from "@saleor/components/FilterBar"; +import PageHeader from "@saleor/components/PageHeader"; +import { sectionNames } from "@saleor/intl"; +import { OrderListUrlSortField } from "@saleor/orders/urls"; +import { FilterPageProps, PageListProps, SortPage } from "@saleor/types"; import React from "react"; import { FormattedMessage, useIntl } from "react-intl"; -import Container from "@saleor/components/Container"; -import PageHeader from "@saleor/components/PageHeader"; -import { sectionNames } from "@saleor/intl"; -import { FilterPageProps, PageListProps, SortPage } from "@saleor/types"; -import { OrderListUrlSortField } from "@saleor/orders/urls"; -import FilterBar from "@saleor/components/FilterBar"; import { OrderList_orders_edges_node } from "../../types/OrderList"; import OrderList from "../OrderList"; import { createFilterStructure, - OrderListFilterOpts, - OrderFilterKeys + OrderFilterKeys, + OrderListFilterOpts } from "./filters"; export interface OrderListPageProps diff --git a/src/orders/components/OrderListPage/filters.ts b/src/orders/components/OrderListPage/filters.ts index 4403b8ae5..98228311e 100644 --- a/src/orders/components/OrderListPage/filters.ts +++ b/src/orders/components/OrderListPage/filters.ts @@ -1,5 +1,6 @@ -import { defineMessages, IntlShape } from "react-intl"; - +import { IFilter } from "@saleor/components/Filter"; +import { commonMessages } from "@saleor/intl"; +import { orderStatusMessages } from "@saleor/misc"; import { FilterOpts, MinMax } from "@saleor/types"; import { OrderStatusFilter } from "@saleor/types/globalTypes"; import { @@ -7,9 +8,7 @@ import { createOptionsField, createTextField } from "@saleor/utils/filters/fields"; -import { IFilter } from "@saleor/components/Filter"; -import { orderStatusMessages } from "@saleor/misc"; -import { commonMessages } from "@saleor/intl"; +import { defineMessages, IntlShape } from "react-intl"; export enum OrderFilterKeys { created = "created", diff --git a/src/orders/components/OrderMarkAsPaidDialog/OrderMarkAsPaidDialog.tsx b/src/orders/components/OrderMarkAsPaidDialog/OrderMarkAsPaidDialog.tsx index 6843a58d3..9f00813c1 100644 --- a/src/orders/components/OrderMarkAsPaidDialog/OrderMarkAsPaidDialog.tsx +++ b/src/orders/components/OrderMarkAsPaidDialog/OrderMarkAsPaidDialog.tsx @@ -1,13 +1,12 @@ import DialogContentText from "@material-ui/core/DialogContentText"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import ActionDialog from "@saleor/components/ActionDialog"; import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; -import { OrderErrorFragment } from "@saleor/orders/types/OrderErrorFragment"; import FormSpacer from "@saleor/components/FormSpacer"; -import getOrderErrorMessage from "@saleor/utils/errors/order"; +import { OrderErrorFragment } from "@saleor/fragments/types/OrderErrorFragment"; import useModalDialogErrors from "@saleor/hooks/useModalDialogErrors"; +import getOrderErrorMessage from "@saleor/utils/errors/order"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; export interface OrderMarkAsPaidDialogProps { confirmButtonState: ConfirmButtonTransitionState; @@ -44,8 +43,8 @@ const OrderMarkAsPaidDialog: React.FC = ({ {errors.length > 0 && ( <> - {errors.map(err => ( - + {errors.map((err, index) => ( + {getOrderErrorMessage(err, intl)} ))} diff --git a/src/orders/components/OrderPayment/OrderPayment.tsx b/src/orders/components/OrderPayment/OrderPayment.tsx index 9f6fc639f..48a1c1992 100644 --- a/src/orders/components/OrderPayment/OrderPayment.tsx +++ b/src/orders/components/OrderPayment/OrderPayment.tsx @@ -3,14 +3,14 @@ import Card from "@material-ui/core/Card"; import CardActions from "@material-ui/core/CardActions"; import CardContent from "@material-ui/core/CardContent"; import { makeStyles } from "@material-ui/core/styles"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import CardTitle from "@saleor/components/CardTitle"; import { Hr } from "@saleor/components/Hr"; import Money, { subtractMoney } from "@saleor/components/Money"; import Skeleton from "@saleor/components/Skeleton"; import StatusLabel from "@saleor/components/StatusLabel"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { maybe, transformPaymentStatus } from "../../../misc"; import { OrderAction, OrderStatus } from "../../../types/globalTypes"; import { OrderDetails_order } from "../../types/OrderDetails"; @@ -159,6 +159,20 @@ const OrderPayment: React.FC = props => { )} + {order?.discount?.amount > 0 && ( + + + + + + + - + + + )} = ({ {errors .filter(err => !formFields.includes(err.field)) - .map(err => ( - + .map((err, index) => ( + {getOrderErrorMessage(err, intl)} ))} diff --git a/src/orders/components/OrderPaymentVoidDialog/OrderPaymentVoidDialog.tsx b/src/orders/components/OrderPaymentVoidDialog/OrderPaymentVoidDialog.tsx index 3bc64d55e..eed639a95 100644 --- a/src/orders/components/OrderPaymentVoidDialog/OrderPaymentVoidDialog.tsx +++ b/src/orders/components/OrderPaymentVoidDialog/OrderPaymentVoidDialog.tsx @@ -4,16 +4,15 @@ import DialogActions from "@material-ui/core/DialogActions"; import DialogContent from "@material-ui/core/DialogContent"; import DialogContentText from "@material-ui/core/DialogContentText"; import DialogTitle from "@material-ui/core/DialogTitle"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import ConfirmButton, { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; -import { buttonMessages } from "@saleor/intl"; -import { OrderErrorFragment } from "@saleor/orders/types/OrderErrorFragment"; import FormSpacer from "@saleor/components/FormSpacer"; +import { OrderErrorFragment } from "@saleor/fragments/types/OrderErrorFragment"; +import { buttonMessages } from "@saleor/intl"; import getOrderErrorMessage from "@saleor/utils/errors/order"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; export interface OrderPaymentVoidDialogProps { confirmButtonState: ConfirmButtonTransitionState; @@ -47,8 +46,8 @@ const OrderPaymentVoidDialog: React.FC = ({ {errors.length > 0 && ( <> - {errors.map(err => ( - + {errors.map((err, index) => ( + {getOrderErrorMessage(err, intl)} ))} diff --git a/src/orders/components/OrderProductAddDialog/OrderProductAddDialog.tsx b/src/orders/components/OrderProductAddDialog/OrderProductAddDialog.tsx index 004bd4b03..0330b72ee 100644 --- a/src/orders/components/OrderProductAddDialog/OrderProductAddDialog.tsx +++ b/src/orders/components/OrderProductAddDialog/OrderProductAddDialog.tsx @@ -10,26 +10,26 @@ import TableBody from "@material-ui/core/TableBody"; import TableCell from "@material-ui/core/TableCell"; import TableRow from "@material-ui/core/TableRow"; import TextField from "@material-ui/core/TextField"; -import React from "react"; -import InfiniteScroll from "react-infinite-scroller"; -import { FormattedMessage, useIntl } from "react-intl"; - import Checkbox from "@saleor/components/Checkbox"; import ConfirmButton, { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; +import FormSpacer from "@saleor/components/FormSpacer"; import Money from "@saleor/components/Money"; import ResponsiveTable from "@saleor/components/ResponsiveTable"; import TableCellAvatar from "@saleor/components/TableCellAvatar"; +import { OrderErrorFragment } from "@saleor/fragments/types/OrderErrorFragment"; +import useModalDialogErrors from "@saleor/hooks/useModalDialogErrors"; +import useModalDialogOpen from "@saleor/hooks/useModalDialogOpen"; import useSearchQuery from "@saleor/hooks/useSearchQuery"; import { buttonMessages } from "@saleor/intl"; import { maybe, renderCollection } from "@saleor/misc"; import { FetchMoreProps } from "@saleor/types"; -import { OrderErrorFragment } from "@saleor/orders/types/OrderErrorFragment"; import getOrderErrorMessage from "@saleor/utils/errors/order"; -import useModalDialogErrors from "@saleor/hooks/useModalDialogErrors"; -import FormSpacer from "@saleor/components/FormSpacer"; -import useModalDialogOpen from "@saleor/hooks/useModalDialogOpen"; +import React from "react"; +import InfiniteScroll from "react-infinite-scroller"; +import { FormattedMessage, useIntl } from "react-intl"; + import { SearchOrderVariant_search_edges_node, SearchOrderVariant_search_edges_node_variants @@ -340,8 +340,8 @@ const OrderProductAddDialog: React.FC = props => { {errors.length > 0 && ( <> - {errors.map(err => ( - + {errors.map((err, index) => ( + {getOrderErrorMessage(err, intl)} ))} diff --git a/src/orders/components/OrderShippingMethodEditDialog/OrderShippingMethodEditDialog.tsx b/src/orders/components/OrderShippingMethodEditDialog/OrderShippingMethodEditDialog.tsx index 7eb7c9ded..43419630b 100644 --- a/src/orders/components/OrderShippingMethodEditDialog/OrderShippingMethodEditDialog.tsx +++ b/src/orders/components/OrderShippingMethodEditDialog/OrderShippingMethodEditDialog.tsx @@ -5,21 +5,21 @@ import DialogContent from "@material-ui/core/DialogContent"; import DialogContentText from "@material-ui/core/DialogContentText"; import DialogTitle from "@material-ui/core/DialogTitle"; import { makeStyles } from "@material-ui/core/styles"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import ConfirmButton, { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; import Form from "@saleor/components/Form"; +import FormSpacer from "@saleor/components/FormSpacer"; import Money from "@saleor/components/Money"; import { SingleSelectField } from "@saleor/components/SingleSelectField"; -import { buttonMessages } from "@saleor/intl"; -import { OrderErrorFragment } from "@saleor/orders/types/OrderErrorFragment"; +import { OrderErrorFragment } from "@saleor/fragments/types/OrderErrorFragment"; import useModalDialogErrors from "@saleor/hooks/useModalDialogErrors"; +import { buttonMessages } from "@saleor/intl"; import { getFormErrors } from "@saleor/utils/errors"; import getOrderErrorMessage from "@saleor/utils/errors/order"; -import FormSpacer from "@saleor/components/FormSpacer"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { OrderDetails_order_availableShippingMethods } from "../../types/OrderDetails"; export interface FormData { @@ -120,8 +120,8 @@ const OrderShippingMethodEditDialog: React.FC 0 && ( <> - {nonFieldErrors.map(err => ( - + {nonFieldErrors.map((err, index) => ( + {getOrderErrorMessage(err, intl)} ))} diff --git a/src/orders/components/OrderUnfulfilledItems/OrderUnfulfilledItems.tsx b/src/orders/components/OrderUnfulfilledItems/OrderUnfulfilledItems.tsx index bd8b6ae5d..47634f897 100644 --- a/src/orders/components/OrderUnfulfilledItems/OrderUnfulfilledItems.tsx +++ b/src/orders/components/OrderUnfulfilledItems/OrderUnfulfilledItems.tsx @@ -6,9 +6,6 @@ import TableBody from "@material-ui/core/TableBody"; import TableCell from "@material-ui/core/TableCell"; import TableHead from "@material-ui/core/TableHead"; import TableRow from "@material-ui/core/TableRow"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import CardTitle from "@saleor/components/CardTitle"; import Money from "@saleor/components/Money"; import ResponsiveTable from "@saleor/components/ResponsiveTable"; @@ -17,6 +14,9 @@ import StatusLabel from "@saleor/components/StatusLabel"; import TableCellAvatar, { AVATAR_MARGIN } from "@saleor/components/TableCellAvatar"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { maybe } from "../../../misc"; import { OrderDetails_order_lines } from "../../types/OrderDetails"; @@ -40,6 +40,11 @@ const useStyles = makeStyles( textAlign: "center", width: 120 }, + colSku: { + textAlign: "right", + textOverflow: "ellipsis", + width: 120 + }, colTotal: { textAlign: "right", width: 120 @@ -97,6 +102,12 @@ const OrderUnfulfilledItems: React.FC = props => { /> + + + = props => { > {maybe(() => line.productName) || } + + {line?.productSku || } + {maybe(() => line.quantity - line.quantityFulfilled) || ( diff --git a/src/orders/containers/OrderOperations.tsx b/src/orders/containers/OrderOperations.tsx index c134b21aa..68832d315 100644 --- a/src/orders/containers/OrderOperations.tsx +++ b/src/orders/containers/OrderOperations.tsx @@ -3,6 +3,8 @@ import React from "react"; import { getMutationProviderData } from "../../misc"; import { PartialMutationProviderOutput } from "../../types"; import { + TypedInvoiceEmailSendMutation, + TypedInvoiceRequestMutation, TypedOrderAddNoteMutation, TypedOrderCancelMutation, TypedOrderCaptureMutation, @@ -20,6 +22,14 @@ import { TypedOrderUpdateMutation, TypedOrderVoidMutation } from "../mutations"; +import { + InvoiceEmailSend, + InvoiceEmailSendVariables +} from "../types/InvoiceEmailSend"; +import { + InvoiceRequest, + InvoiceRequestVariables +} from "../types/InvoiceRequest"; import { OrderAddNote, OrderAddNoteVariables } from "../types/OrderAddNote"; import { OrderCancel, OrderCancelVariables } from "../types/OrderCancel"; import { OrderCapture, OrderCaptureVariables } from "../types/OrderCapture"; @@ -128,6 +138,14 @@ interface OrderOperationsProps { OrderLineUpdate, OrderLineUpdateVariables >; + orderInvoiceRequest: PartialMutationProviderOutput< + InvoiceRequest, + InvoiceRequestVariables + >; + orderInvoiceSend: PartialMutationProviderOutput< + InvoiceEmailSend, + InvoiceEmailSendVariables + >; }) => React.ReactNode; onOrderFulfillmentCancel: (data: OrderFulfillmentCancel) => void; onOrderFulfillmentUpdate: (data: OrderFulfillmentUpdateTracking) => void; @@ -145,6 +163,8 @@ interface OrderOperationsProps { onOrderLineDelete: (data: OrderLineDelete) => void; onOrderLinesAdd: (data: OrderLinesAdd) => void; onOrderLineUpdate: (data: OrderLineUpdate) => void; + onInvoiceRequest: (data: InvoiceRequest) => void; + onInvoiceSend: (data: InvoiceEmailSend) => void; } const OrderOperations: React.FC = ({ @@ -164,7 +184,9 @@ const OrderOperations: React.FC = ({ onDraftFinalize, onOrderFulfillmentCancel, onOrderFulfillmentUpdate, - onOrderMarkAsPaid + onOrderMarkAsPaid, + onInvoiceRequest, + onInvoiceSend }) => ( {(...orderVoid) => ( @@ -233,58 +255,86 @@ const OrderOperations: React.FC = ({ > {( ...markAsPaid - ) => - children({ - orderAddNote: getMutationProviderData( - ...addNote - ), - orderCancel: getMutationProviderData( - ...orderCancel - ), - orderDraftCancel: getMutationProviderData( - ...cancelDraft - ), - orderDraftFinalize: getMutationProviderData( - ...finalizeDraft - ), - orderDraftUpdate: getMutationProviderData( - ...updateDraft - ), - orderFulfillmentCancel: getMutationProviderData( - ...cancelFulfillment - ), - orderFulfillmentUpdateTracking: getMutationProviderData( - ...updateTrackingNumber - ), - orderLineDelete: getMutationProviderData( - ...deleteOrderLine - ), - orderLineUpdate: getMutationProviderData( - ...updateOrderLine - ), - orderLinesAdd: getMutationProviderData( - ...addOrderLine - ), - orderPaymentCapture: getMutationProviderData( - ...paymentCapture - ), - orderPaymentMarkAsPaid: getMutationProviderData( - ...markAsPaid - ), - orderPaymentRefund: getMutationProviderData( - ...paymentRefund - ), - orderShippingMethodUpdate: getMutationProviderData( - ...updateShippingMethod - ), - orderUpdate: getMutationProviderData( - ...update - ), - orderVoid: getMutationProviderData( - ...orderVoid - ) - }) - } + ) => ( + + {( + ...invoiceRequest + ) => ( + + {( + ...invoiceEmailSend + ) => + children( + { + orderAddNote: getMutationProviderData( + ...addNote + ), + orderCancel: getMutationProviderData( + ...orderCancel + ), + orderDraftCancel: getMutationProviderData( + ...cancelDraft + ), + orderDraftFinalize: getMutationProviderData( + ...finalizeDraft + ), + orderDraftUpdate: getMutationProviderData( + ...updateDraft + ), + orderFulfillmentCancel: getMutationProviderData( + ...cancelFulfillment + ), + orderFulfillmentUpdateTracking: getMutationProviderData( + ...updateTrackingNumber + ), + orderInvoiceRequest: getMutationProviderData( + ...invoiceRequest + ), + orderInvoiceSend: getMutationProviderData( + ...invoiceEmailSend + ), + orderLineDelete: getMutationProviderData( + ...deleteOrderLine + ), + orderLineUpdate: getMutationProviderData( + ...updateOrderLine + ), + orderLinesAdd: getMutationProviderData( + ...addOrderLine + ), + orderPaymentCapture: getMutationProviderData( + ...paymentCapture + ), + orderPaymentMarkAsPaid: getMutationProviderData( + ...markAsPaid + ), + orderPaymentRefund: getMutationProviderData( + ...paymentRefund + ), + orderShippingMethodUpdate: getMutationProviderData( + ...updateShippingMethod + ), + orderUpdate: getMutationProviderData( + ...update + ), + orderVoid: getMutationProviderData( + ...orderVoid + ) + } + ) + } + + )} + + )} )} diff --git a/src/orders/fixtures.ts b/src/orders/fixtures.ts index fe69a4a58..187246728 100644 --- a/src/orders/fixtures.ts +++ b/src/orders/fixtures.ts @@ -1,10 +1,14 @@ +import { InvoiceFragment } from "@saleor/fragments/types/InvoiceFragment"; import { SearchCustomers_search_edges_node } from "@saleor/searches/types/SearchCustomers"; -import { MessageDescriptor } from "react-intl"; import { warehouseList } from "@saleor/warehouses/fixtures"; +import { MessageDescriptor } from "react-intl"; + import { transformOrderStatus, transformPaymentStatus } from "../misc"; import { FulfillmentStatus, + JobStatusEnum, OrderAction, + OrderEventsEmailsEnum, OrderEventsEnum, OrderStatus, PaymentChargeStatusEnum @@ -809,6 +813,7 @@ export const order = (placeholder: string): OrderDetails_order => ({ canFinalize: true, created: "2018-09-11T09:37:28.185874+00:00", customerNote: "Lorem ipsum dolor sit amet", + discount: null, events: [ { __typename: "OrderEvent", @@ -817,6 +822,7 @@ export const order = (placeholder: string): OrderDetails_order => ({ email: null, emailType: null, id: "T3JkZXJFdmVudDoyMQ==", + invoiceNumber: null, message: null, quantity: 1, type: OrderEventsEnum.FULFILLMENT_FULFILLED_ITEMS, @@ -833,6 +839,7 @@ export const order = (placeholder: string): OrderDetails_order => ({ email: null, emailType: null, id: "T3JkZXJFdmVudDo0", + invoiceNumber: null, message: "This is note", quantity: null, type: OrderEventsEnum.NOTE_ADDED, @@ -845,10 +852,63 @@ export const order = (placeholder: string): OrderDetails_order => ({ email: null, emailType: null, id: "T3JkZXJFdmVudDo1", + invoiceNumber: null, message: "This is note", quantity: null, type: OrderEventsEnum.NOTE_ADDED, user: null + }, + { + __typename: "OrderEvent", + amount: null, + date: "2019-09-17T13:22:24.376193+00:00", + email: null, + emailType: null, + id: "T3JkZXJFdmVudDo2", + invoiceNumber: null, + message: "Note from external service", + quantity: null, + type: OrderEventsEnum.EXTERNAL_SERVICE_NOTIFICATION, + user: null + }, + { + __typename: "OrderEvent", + amount: null, + date: "2019-09-17T13:22:24.376193+00:00", + email: null, + emailType: OrderEventsEmailsEnum.ORDER_CANCEL, + id: "T3JkZXJFdmVudDo3", + invoiceNumber: null, + message: null, + quantity: null, + type: OrderEventsEnum.EMAIL_SENT, + user: null + }, + { + __typename: "OrderEvent", + amount: null, + date: "2019-09-17T13:22:24.376193+00:00", + email: null, + emailType: OrderEventsEmailsEnum.ORDER_REFUND, + id: "T3JkZXJFdmVudDo4", + invoiceNumber: null, + message: null, + quantity: null, + type: OrderEventsEnum.EMAIL_SENT, + user: null + }, + { + __typename: "OrderEvent", + amount: null, + date: "2019-09-17T13:22:24.376193+00:00", + email: null, + emailType: null, + id: "T3JkZXJFdmVudDo5", + invoiceNumber: null, + message: null, + quantity: null, + type: OrderEventsEnum.PAYMENT_AUTHORIZED, + user: null } ], fulfillments: [ @@ -884,6 +944,15 @@ export const order = (placeholder: string): OrderDetails_order => ({ amount: 79.71, currency: "USD" } + }, + variant: { + __typename: "ProductVariant", + product: { + __typename: "Product", + isAvailableForPurchase: true, + isPublished: true + }, + quantityAvailable: 10 } }, quantity: 1 @@ -925,6 +994,15 @@ export const order = (placeholder: string): OrderDetails_order => ({ amount: 79.71, currency: "USD" } + }, + variant: { + __typename: "ProductVariant", + product: { + __typename: "Product", + isAvailableForPurchase: true, + isPublished: true + }, + quantityAvailable: 10 } }, quantity: 1 @@ -936,6 +1014,16 @@ export const order = (placeholder: string): OrderDetails_order => ({ } ], id: "T3JkZXI6OQ==", + invoices: [ + { + __typename: "Invoice", + createdAt: "2020-06-22T13:52:05.094636+00:00", + id: "SW52b2ljZTox", + number: "1", + status: JobStatusEnum.SUCCESS, + url: "invoice1" + } + ], lines: [ { __typename: "OrderLine", @@ -961,6 +1049,15 @@ export const order = (placeholder: string): OrderDetails_order => ({ amount: 18.51, currency: "USD" } + }, + variant: { + __typename: "ProductVariant", + product: { + __typename: "Product", + isAvailableForPurchase: true, + isPublished: true + }, + quantityAvailable: 10 } }, { @@ -987,11 +1084,28 @@ export const order = (placeholder: string): OrderDetails_order => ({ amount: 79.71, currency: "USD" } + }, + variant: { + __typename: "ProductVariant", + product: { + __typename: "Product", + isAvailableForPurchase: true, + isPublished: true + }, + quantityAvailable: 10 } } ], + metadata: [ + { + __typename: "MetadataItem", + key: "integration.key", + value: "some-value" + } + ], number: "9", paymentStatus: PaymentChargeStatusEnum.NOT_CHARGED, + privateMetadata: [], shippingAddress: { __typename: "Address", city: "West Patriciastad", @@ -1064,9 +1178,20 @@ export const draftOrder = (placeholder: string): OrderDetails_order => ({ canFinalize: true, created: "2018-09-20T23:23:39.811428+00:00", customerNote: "Lorem ipsum dolor sit", + discount: null, events: [], fulfillments: [], id: "T3JkZXI6MjQ=", + invoices: [ + { + __typename: "Invoice", + createdAt: "2020-06-22T13:52:05.094636+00:00", + id: "SW52b2ljZTox", + number: "1", + status: JobStatusEnum.SUCCESS, + url: "invoice1" + } + ], lines: [ { __typename: "OrderLine" as "OrderLine", @@ -1092,6 +1217,15 @@ export const draftOrder = (placeholder: string): OrderDetails_order => ({ amount: 65.95, currency: "USD" } + }, + variant: { + __typename: "ProductVariant", + product: { + __typename: "Product", + isAvailableForPurchase: true, + isPublished: true + }, + quantityAvailable: 10 } }, { @@ -1118,11 +1252,22 @@ export const draftOrder = (placeholder: string): OrderDetails_order => ({ amount: 68.2, currency: "USD" } + }, + variant: { + __typename: "ProductVariant", + product: { + __typename: "Product", + isAvailableForPurchase: true, + isPublished: true + }, + quantityAvailable: 10 } } ], + metadata: [], number: "24", paymentStatus: null, + privateMetadata: [], shippingAddress: null, shippingMethod: null, shippingMethodName: null, @@ -1319,3 +1464,42 @@ export const orderLineSearch = ( ] } ]; + +export const invoices: InvoiceFragment[] = [ + { + __typename: "Invoice", + createdAt: "2020-07-02T12:13:56.901097+00:00", + id: "SW52b2ljZTo0", + number: "1/07/2020", + status: JobStatusEnum.PENDING, + url: + "http://localhost:8000/media/invoices/invoice-1/07/2020-order-20-1fef611b-7514-4dc6-aee3-09a8232b1d6a.pdf" + }, + { + __typename: "Invoice", + createdAt: "2020-07-02T09:06:17.059412+00:00", + id: "SW52b2ljZToz", + number: "1/07/2020", + status: JobStatusEnum.SUCCESS, + url: + "http://localhost:8000/media/invoices/invoice-1/07/2020-order-20-8df26967-ad21-4075-a446-cef44ae05197.pdf" + }, + { + __typename: "Invoice", + createdAt: "2020-07-02T09:05:58.300952+00:00", + id: "SW52b2ljZToy", + number: "1/07/2020", + status: JobStatusEnum.SUCCESS, + url: + "http://localhost:8000/media/invoices/invoice-1/07/2020-order-20-5ebc85e0-e587-4386-8292-9b85839281e6.pdf" + }, + { + __typename: "Invoice", + createdAt: "2020-07-02T09:04:27.257562+00:00", + id: "SW52b2ljZTox", + number: "1/07/2020", + status: JobStatusEnum.SUCCESS, + url: + "http://localhost:8000/media/invoices/invoice-1/07/2020-order-20-0e449e10-ef4b-4066-bebe-361f670b6820.pdf" + } +]; diff --git a/src/orders/index.tsx b/src/orders/index.tsx index c8db1246e..410c0d17b 100644 --- a/src/orders/index.tsx +++ b/src/orders/index.tsx @@ -1,25 +1,25 @@ +import { sectionNames } from "@saleor/intl"; +import { asSortParams } from "@saleor/utils/sort"; import { parse as parseQs } from "qs"; import React from "react"; import { useIntl } from "react-intl"; import { Route, RouteComponentProps, Switch } from "react-router-dom"; -import { sectionNames } from "@saleor/intl"; -import { asSortParams } from "@saleor/utils/sort"; import { WindowTitle } from "../components/WindowTitle"; import { orderDraftListPath, OrderDraftListUrlQueryParams, + OrderDraftListUrlSortField, + orderFulfillPath, orderListPath, OrderListUrlQueryParams, - orderPath, - OrderUrlQueryParams, - OrderDraftListUrlSortField, OrderListUrlSortField, - orderFulfillPath + orderPath, + OrderUrlQueryParams } from "./urls"; import OrderDetailsComponent from "./views/OrderDetails"; -import OrderFulfillComponent from "./views/OrderFulfill"; import OrderDraftListComponent from "./views/OrderDraftList"; +import OrderFulfillComponent from "./views/OrderFulfill"; import OrderListComponent from "./views/OrderList"; const OrderList: React.FC> = ({ location }) => { diff --git a/src/orders/mutations.ts b/src/orders/mutations.ts index d94c3f8ff..0169ae2f5 100644 --- a/src/orders/mutations.ts +++ b/src/orders/mutations.ts @@ -1,12 +1,25 @@ +import { + invoiceErrorFragment, + orderErrorFragment +} from "@saleor/fragments/errors"; +import { + fragmentOrderDetails, + fragmentOrderEvent, + invoiceFragment +} from "@saleor/fragments/orders"; +import makeMutation from "@saleor/hooks/makeMutation"; import gql from "graphql-tag"; -import makeMutation from "@saleor/hooks/makeMutation"; import { TypedMutation } from "../mutations"; +import { FulfillOrder, FulfillOrderVariables } from "./types/FulfillOrder"; import { - fragmentAddress, - fragmentOrderDetails, - fragmentOrderEvent -} from "./queries"; + InvoiceEmailSend, + InvoiceEmailSendVariables +} from "./types/InvoiceEmailSend"; +import { + InvoiceRequest, + InvoiceRequestVariables +} from "./types/InvoiceRequest"; import { OrderAddNote, OrderAddNoteVariables } from "./types/OrderAddNote"; import { OrderCancel, OrderCancelVariables } from "./types/OrderCancel"; import { OrderCapture, OrderCaptureVariables } from "./types/OrderCapture"; @@ -14,7 +27,6 @@ import { OrderDraftBulkCancel, OrderDraftBulkCancelVariables } from "./types/OrderDraftBulkCancel"; -import { FulfillOrder, FulfillOrderVariables } from "./types/FulfillOrder"; import { OrderDraftCancel, OrderDraftCancelVariables @@ -57,13 +69,6 @@ import { import { OrderUpdate, OrderUpdateVariables } from "./types/OrderUpdate"; import { OrderVoid, OrderVoidVariables } from "./types/OrderVoid"; -export const orderErrorFragment = gql` - fragment OrderErrorFragment on OrderError { - code - field - } -`; - const orderCancelMutation = gql` ${fragmentOrderDetails} ${orderErrorFragment} @@ -139,7 +144,7 @@ export const TypedOrderDraftFinalizeMutation = TypedMutation< const orderRefundMutation = gql` ${fragmentOrderDetails} ${orderErrorFragment} - mutation OrderRefund($id: ID!, $amount: Decimal!) { + mutation OrderRefund($id: ID!, $amount: PositiveDecimal!) { orderRefund(id: $id, amount: $amount) { errors: orderErrors { ...OrderErrorFragment @@ -196,7 +201,7 @@ export const TypedOrderMarkAsPaidMutation = TypedMutation< const orderCaptureMutation = gql` ${fragmentOrderDetails} ${orderErrorFragment} - mutation OrderCapture($id: ID!, $amount: Decimal!) { + mutation OrderCapture($id: ID!, $amount: PositiveDecimal!) { orderCapture(id: $id, amount: $amount) { errors: orderErrors { ...OrderErrorFragment @@ -276,7 +281,7 @@ export const TypedOrderAddNoteMutation = TypedMutation< >(orderAddNoteMutation); const orderUpdateMutation = gql` - ${fragmentAddress} + ${fragmentOrderDetails} ${orderErrorFragment} mutation OrderUpdate($id: ID!, $input: OrderUpdateInput!) { orderUpdate(id: $id, input: $input) { @@ -284,14 +289,7 @@ const orderUpdateMutation = gql` ...OrderErrorFragment } order { - id - userEmail - billingAddress { - ...AddressFragment - } - shippingAddress { - ...AddressFragment - } + ...OrderDetailsFragment } } } @@ -454,3 +452,47 @@ export const useOrderFulfill = makeMutation< FulfillOrder, FulfillOrderVariables >(fulfillOrder); + +const invoiceRequestMutation = gql` + ${invoiceErrorFragment} + ${invoiceFragment} + mutation InvoiceRequest($orderId: ID!) { + invoiceRequest(orderId: $orderId) { + errors: invoiceErrors { + ...InvoiceErrorFragment + } + invoice { + ...InvoiceFragment + } + order { + id + invoices { + ...InvoiceFragment + } + } + } + } +`; +export const TypedInvoiceRequestMutation = TypedMutation< + InvoiceRequest, + InvoiceRequestVariables +>(invoiceRequestMutation); + +const invoiceEmailSendMutation = gql` + ${invoiceErrorFragment} + ${invoiceFragment} + mutation InvoiceEmailSend($id: ID!) { + invoiceSendEmail(id: $id) { + errors: invoiceErrors { + ...InvoiceErrorFragment + } + invoice { + ...InvoiceFragment + } + } + } +`; +export const TypedInvoiceEmailSendMutation = TypedMutation< + InvoiceEmailSend, + InvoiceEmailSendVariables +>(invoiceEmailSendMutation); diff --git a/src/orders/queries.ts b/src/orders/queries.ts index c633515e5..334c15538 100644 --- a/src/orders/queries.ts +++ b/src/orders/queries.ts @@ -1,181 +1,24 @@ +import { fragmentAddress } from "@saleor/fragments/address"; +import { fragmentOrderDetails } from "@saleor/fragments/orders"; +import makeQuery from "@saleor/hooks/makeQuery"; +import makeTopLevelSearch from "@saleor/hooks/makeTopLevelSearch"; import gql from "graphql-tag"; -import makeTopLevelSearch from "@saleor/hooks/makeTopLevelSearch"; -import makeQuery from "@saleor/hooks/makeQuery"; import { TypedQuery } from "../queries"; import { OrderDetails, OrderDetailsVariables } from "./types/OrderDetails"; import { OrderDraftList, OrderDraftListVariables } from "./types/OrderDraftList"; +import { + OrderFulfillData, + OrderFulfillDataVariables +} from "./types/OrderFulfillData"; import { OrderList, OrderListVariables } from "./types/OrderList"; import { SearchOrderVariant as SearchOrderVariantType, SearchOrderVariantVariables } from "./types/SearchOrderVariant"; -import { - OrderFulfillData, - OrderFulfillDataVariables -} from "./types/OrderFulfillData"; - -export const fragmentOrderEvent = gql` - fragment OrderEventFragment on OrderEvent { - id - amount - date - email - emailType - message - quantity - type - user { - id - email - } - } -`; -export const fragmentAddress = gql` - fragment AddressFragment on Address { - city - cityArea - companyName - country { - __typename - code - country - } - countryArea - firstName - id - lastName - phone - postalCode - streetAddress1 - streetAddress2 - } -`; -export const fragmentOrderLine = gql` - fragment OrderLineFragment on OrderLine { - id - isShippingRequired - productName - productSku - quantity - quantityFulfilled - unitPrice { - gross { - amount - currency - } - net { - amount - currency - } - } - thumbnail { - url - } - } -`; -export const fulfillmentFragment = gql` - ${fragmentOrderLine} - fragment FulfillmentFragment on Fulfillment { - id - lines { - id - quantity - orderLine { - ...OrderLineFragment - } - } - fulfillmentOrder - status - trackingNumber - warehouse { - id - name - } - } -`; - -export const fragmentOrderDetails = gql` - ${fragmentAddress} - ${fragmentOrderEvent} - ${fragmentOrderLine} - ${fulfillmentFragment} - fragment OrderDetailsFragment on Order { - id - billingAddress { - ...AddressFragment - } - canFinalize - created - customerNote - events { - ...OrderEventFragment - } - fulfillments { - ...FulfillmentFragment - } - lines { - ...OrderLineFragment - } - number - paymentStatus - shippingAddress { - ...AddressFragment - } - shippingMethod { - id - } - shippingMethodName - shippingPrice { - gross { - amount - currency - } - } - status - subtotal { - gross { - amount - currency - } - } - total { - gross { - amount - currency - } - tax { - amount - currency - } - } - actions - totalAuthorized { - amount - currency - } - totalCaptured { - amount - currency - } - user { - id - email - } - userEmail - availableShippingMethods { - id - name - price { - amount - currency - } - } - } -`; export const orderListQuery = gql` ${fragmentAddress} diff --git a/src/orders/types/FulfillOrder.ts b/src/orders/types/FulfillOrder.ts index 786ffb08c..fd6f27ebf 100644 --- a/src/orders/types/FulfillOrder.ts +++ b/src/orders/types/FulfillOrder.ts @@ -2,7 +2,7 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { OrderFulfillInput, OrderErrorCode, OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus, OrderAction } from "./../../types/globalTypes"; +import { OrderFulfillInput, OrderErrorCode, OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus, OrderAction, JobStatusEnum } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: FulfillOrder @@ -16,6 +16,18 @@ export interface FulfillOrder_orderFulfill_errors { orderLine: string | null; } +export interface FulfillOrder_orderFulfill_order_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface FulfillOrder_orderFulfill_order_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface FulfillOrder_orderFulfill_order_billingAddress_country { __typename: "CountryDisplay"; code: string; @@ -51,12 +63,25 @@ export interface FulfillOrder_orderFulfill_order_events { date: any | null; email: string | null; emailType: OrderEventsEmailsEnum | null; + invoiceNumber: string | null; message: string | null; quantity: number | null; type: OrderEventsEnum | null; user: FulfillOrder_orderFulfill_order_events_user | null; } +export interface FulfillOrder_orderFulfill_order_fulfillments_lines_orderLine_variant_product { + __typename: "Product"; + isAvailableForPurchase: boolean | null; + isPublished: boolean; +} + +export interface FulfillOrder_orderFulfill_order_fulfillments_lines_orderLine_variant { + __typename: "ProductVariant"; + product: FulfillOrder_orderFulfill_order_fulfillments_lines_orderLine_variant_product; + quantityAvailable: number; +} + export interface FulfillOrder_orderFulfill_order_fulfillments_lines_orderLine_unitPrice_gross { __typename: "Money"; amount: number; @@ -84,6 +109,7 @@ export interface FulfillOrder_orderFulfill_order_fulfillments_lines_orderLine { __typename: "OrderLine"; id: string; isShippingRequired: boolean; + variant: FulfillOrder_orderFulfill_order_fulfillments_lines_orderLine_variant | null; productName: string; productSku: string; quantity: number; @@ -115,6 +141,18 @@ export interface FulfillOrder_orderFulfill_order_fulfillments { warehouse: FulfillOrder_orderFulfill_order_fulfillments_warehouse | null; } +export interface FulfillOrder_orderFulfill_order_lines_variant_product { + __typename: "Product"; + isAvailableForPurchase: boolean | null; + isPublished: boolean; +} + +export interface FulfillOrder_orderFulfill_order_lines_variant { + __typename: "ProductVariant"; + product: FulfillOrder_orderFulfill_order_lines_variant_product; + quantityAvailable: number; +} + export interface FulfillOrder_orderFulfill_order_lines_unitPrice_gross { __typename: "Money"; amount: number; @@ -142,6 +180,7 @@ export interface FulfillOrder_orderFulfill_order_lines { __typename: "OrderLine"; id: string; isShippingRequired: boolean; + variant: FulfillOrder_orderFulfill_order_lines_variant | null; productName: string; productSku: string; quantity: number; @@ -248,9 +287,26 @@ export interface FulfillOrder_orderFulfill_order_availableShippingMethods { price: FulfillOrder_orderFulfill_order_availableShippingMethods_price | null; } +export interface FulfillOrder_orderFulfill_order_discount { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface FulfillOrder_orderFulfill_order_invoices { + __typename: "Invoice"; + id: string; + number: string | null; + createdAt: any; + url: string | null; + status: JobStatusEnum; +} + export interface FulfillOrder_orderFulfill_order { __typename: "Order"; id: string; + metadata: (FulfillOrder_orderFulfill_order_metadata | null)[]; + privateMetadata: (FulfillOrder_orderFulfill_order_privateMetadata | null)[]; billingAddress: FulfillOrder_orderFulfill_order_billingAddress | null; canFinalize: boolean; created: any; @@ -273,6 +329,8 @@ export interface FulfillOrder_orderFulfill_order { user: FulfillOrder_orderFulfill_order_user | null; userEmail: string | null; availableShippingMethods: (FulfillOrder_orderFulfill_order_availableShippingMethods | null)[] | null; + discount: FulfillOrder_orderFulfill_order_discount | null; + invoices: (FulfillOrder_orderFulfill_order_invoices | null)[] | null; } export interface FulfillOrder_orderFulfill { diff --git a/src/orders/types/InvoiceEmailSend.ts b/src/orders/types/InvoiceEmailSend.ts new file mode 100644 index 000000000..6406ed5c0 --- /dev/null +++ b/src/orders/types/InvoiceEmailSend.ts @@ -0,0 +1,38 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { InvoiceErrorCode, JobStatusEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: InvoiceEmailSend +// ==================================================== + +export interface InvoiceEmailSend_invoiceSendEmail_errors { + __typename: "InvoiceError"; + code: InvoiceErrorCode; + field: string | null; +} + +export interface InvoiceEmailSend_invoiceSendEmail_invoice { + __typename: "Invoice"; + id: string; + number: string | null; + createdAt: any; + url: string | null; + status: JobStatusEnum; +} + +export interface InvoiceEmailSend_invoiceSendEmail { + __typename: "InvoiceSendEmail"; + errors: InvoiceEmailSend_invoiceSendEmail_errors[]; + invoice: InvoiceEmailSend_invoiceSendEmail_invoice | null; +} + +export interface InvoiceEmailSend { + invoiceSendEmail: InvoiceEmailSend_invoiceSendEmail | null; +} + +export interface InvoiceEmailSendVariables { + id: string; +} diff --git a/src/orders/types/InvoiceRequest.ts b/src/orders/types/InvoiceRequest.ts new file mode 100644 index 000000000..973ff4bda --- /dev/null +++ b/src/orders/types/InvoiceRequest.ts @@ -0,0 +1,54 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { InvoiceErrorCode, JobStatusEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: InvoiceRequest +// ==================================================== + +export interface InvoiceRequest_invoiceRequest_errors { + __typename: "InvoiceError"; + code: InvoiceErrorCode; + field: string | null; +} + +export interface InvoiceRequest_invoiceRequest_invoice { + __typename: "Invoice"; + id: string; + number: string | null; + createdAt: any; + url: string | null; + status: JobStatusEnum; +} + +export interface InvoiceRequest_invoiceRequest_order_invoices { + __typename: "Invoice"; + id: string; + number: string | null; + createdAt: any; + url: string | null; + status: JobStatusEnum; +} + +export interface InvoiceRequest_invoiceRequest_order { + __typename: "Order"; + id: string; + invoices: (InvoiceRequest_invoiceRequest_order_invoices | null)[] | null; +} + +export interface InvoiceRequest_invoiceRequest { + __typename: "InvoiceRequest"; + errors: InvoiceRequest_invoiceRequest_errors[]; + invoice: InvoiceRequest_invoiceRequest_invoice | null; + order: InvoiceRequest_invoiceRequest_order | null; +} + +export interface InvoiceRequest { + invoiceRequest: InvoiceRequest_invoiceRequest | null; +} + +export interface InvoiceRequestVariables { + orderId: string; +} diff --git a/src/orders/types/OrderAddNote.ts b/src/orders/types/OrderAddNote.ts index 3d268218c..75cd83e43 100644 --- a/src/orders/types/OrderAddNote.ts +++ b/src/orders/types/OrderAddNote.ts @@ -27,6 +27,7 @@ export interface OrderAddNote_orderAddNote_order_events { date: any | null; email: string | null; emailType: OrderEventsEmailsEnum | null; + invoiceNumber: string | null; message: string | null; quantity: number | null; type: OrderEventsEnum | null; diff --git a/src/orders/types/OrderCancel.ts b/src/orders/types/OrderCancel.ts index 7258dbdb0..db42d0608 100644 --- a/src/orders/types/OrderCancel.ts +++ b/src/orders/types/OrderCancel.ts @@ -2,7 +2,7 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { OrderErrorCode, OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus, OrderAction } from "./../../types/globalTypes"; +import { OrderErrorCode, OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus, OrderAction, JobStatusEnum } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: OrderCancel @@ -14,6 +14,18 @@ export interface OrderCancel_orderCancel_errors { field: string | null; } +export interface OrderCancel_orderCancel_order_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface OrderCancel_orderCancel_order_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface OrderCancel_orderCancel_order_billingAddress_country { __typename: "CountryDisplay"; code: string; @@ -49,12 +61,25 @@ export interface OrderCancel_orderCancel_order_events { date: any | null; email: string | null; emailType: OrderEventsEmailsEnum | null; + invoiceNumber: string | null; message: string | null; quantity: number | null; type: OrderEventsEnum | null; user: OrderCancel_orderCancel_order_events_user | null; } +export interface OrderCancel_orderCancel_order_fulfillments_lines_orderLine_variant_product { + __typename: "Product"; + isAvailableForPurchase: boolean | null; + isPublished: boolean; +} + +export interface OrderCancel_orderCancel_order_fulfillments_lines_orderLine_variant { + __typename: "ProductVariant"; + product: OrderCancel_orderCancel_order_fulfillments_lines_orderLine_variant_product; + quantityAvailable: number; +} + export interface OrderCancel_orderCancel_order_fulfillments_lines_orderLine_unitPrice_gross { __typename: "Money"; amount: number; @@ -82,6 +107,7 @@ export interface OrderCancel_orderCancel_order_fulfillments_lines_orderLine { __typename: "OrderLine"; id: string; isShippingRequired: boolean; + variant: OrderCancel_orderCancel_order_fulfillments_lines_orderLine_variant | null; productName: string; productSku: string; quantity: number; @@ -113,6 +139,18 @@ export interface OrderCancel_orderCancel_order_fulfillments { warehouse: OrderCancel_orderCancel_order_fulfillments_warehouse | null; } +export interface OrderCancel_orderCancel_order_lines_variant_product { + __typename: "Product"; + isAvailableForPurchase: boolean | null; + isPublished: boolean; +} + +export interface OrderCancel_orderCancel_order_lines_variant { + __typename: "ProductVariant"; + product: OrderCancel_orderCancel_order_lines_variant_product; + quantityAvailable: number; +} + export interface OrderCancel_orderCancel_order_lines_unitPrice_gross { __typename: "Money"; amount: number; @@ -140,6 +178,7 @@ export interface OrderCancel_orderCancel_order_lines { __typename: "OrderLine"; id: string; isShippingRequired: boolean; + variant: OrderCancel_orderCancel_order_lines_variant | null; productName: string; productSku: string; quantity: number; @@ -246,9 +285,26 @@ export interface OrderCancel_orderCancel_order_availableShippingMethods { price: OrderCancel_orderCancel_order_availableShippingMethods_price | null; } +export interface OrderCancel_orderCancel_order_discount { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderCancel_orderCancel_order_invoices { + __typename: "Invoice"; + id: string; + number: string | null; + createdAt: any; + url: string | null; + status: JobStatusEnum; +} + export interface OrderCancel_orderCancel_order { __typename: "Order"; id: string; + metadata: (OrderCancel_orderCancel_order_metadata | null)[]; + privateMetadata: (OrderCancel_orderCancel_order_privateMetadata | null)[]; billingAddress: OrderCancel_orderCancel_order_billingAddress | null; canFinalize: boolean; created: any; @@ -271,6 +327,8 @@ export interface OrderCancel_orderCancel_order { user: OrderCancel_orderCancel_order_user | null; userEmail: string | null; availableShippingMethods: (OrderCancel_orderCancel_order_availableShippingMethods | null)[] | null; + discount: OrderCancel_orderCancel_order_discount | null; + invoices: (OrderCancel_orderCancel_order_invoices | null)[] | null; } export interface OrderCancel_orderCancel { diff --git a/src/orders/types/OrderCapture.ts b/src/orders/types/OrderCapture.ts index 5c3abf2ee..da37b506e 100644 --- a/src/orders/types/OrderCapture.ts +++ b/src/orders/types/OrderCapture.ts @@ -2,7 +2,7 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { OrderErrorCode, OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus, OrderAction } from "./../../types/globalTypes"; +import { OrderErrorCode, OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus, OrderAction, JobStatusEnum } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: OrderCapture @@ -14,6 +14,18 @@ export interface OrderCapture_orderCapture_errors { field: string | null; } +export interface OrderCapture_orderCapture_order_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface OrderCapture_orderCapture_order_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface OrderCapture_orderCapture_order_billingAddress_country { __typename: "CountryDisplay"; code: string; @@ -49,12 +61,25 @@ export interface OrderCapture_orderCapture_order_events { date: any | null; email: string | null; emailType: OrderEventsEmailsEnum | null; + invoiceNumber: string | null; message: string | null; quantity: number | null; type: OrderEventsEnum | null; user: OrderCapture_orderCapture_order_events_user | null; } +export interface OrderCapture_orderCapture_order_fulfillments_lines_orderLine_variant_product { + __typename: "Product"; + isAvailableForPurchase: boolean | null; + isPublished: boolean; +} + +export interface OrderCapture_orderCapture_order_fulfillments_lines_orderLine_variant { + __typename: "ProductVariant"; + product: OrderCapture_orderCapture_order_fulfillments_lines_orderLine_variant_product; + quantityAvailable: number; +} + export interface OrderCapture_orderCapture_order_fulfillments_lines_orderLine_unitPrice_gross { __typename: "Money"; amount: number; @@ -82,6 +107,7 @@ export interface OrderCapture_orderCapture_order_fulfillments_lines_orderLine { __typename: "OrderLine"; id: string; isShippingRequired: boolean; + variant: OrderCapture_orderCapture_order_fulfillments_lines_orderLine_variant | null; productName: string; productSku: string; quantity: number; @@ -113,6 +139,18 @@ export interface OrderCapture_orderCapture_order_fulfillments { warehouse: OrderCapture_orderCapture_order_fulfillments_warehouse | null; } +export interface OrderCapture_orderCapture_order_lines_variant_product { + __typename: "Product"; + isAvailableForPurchase: boolean | null; + isPublished: boolean; +} + +export interface OrderCapture_orderCapture_order_lines_variant { + __typename: "ProductVariant"; + product: OrderCapture_orderCapture_order_lines_variant_product; + quantityAvailable: number; +} + export interface OrderCapture_orderCapture_order_lines_unitPrice_gross { __typename: "Money"; amount: number; @@ -140,6 +178,7 @@ export interface OrderCapture_orderCapture_order_lines { __typename: "OrderLine"; id: string; isShippingRequired: boolean; + variant: OrderCapture_orderCapture_order_lines_variant | null; productName: string; productSku: string; quantity: number; @@ -246,9 +285,26 @@ export interface OrderCapture_orderCapture_order_availableShippingMethods { price: OrderCapture_orderCapture_order_availableShippingMethods_price | null; } +export interface OrderCapture_orderCapture_order_discount { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderCapture_orderCapture_order_invoices { + __typename: "Invoice"; + id: string; + number: string | null; + createdAt: any; + url: string | null; + status: JobStatusEnum; +} + export interface OrderCapture_orderCapture_order { __typename: "Order"; id: string; + metadata: (OrderCapture_orderCapture_order_metadata | null)[]; + privateMetadata: (OrderCapture_orderCapture_order_privateMetadata | null)[]; billingAddress: OrderCapture_orderCapture_order_billingAddress | null; canFinalize: boolean; created: any; @@ -271,6 +327,8 @@ export interface OrderCapture_orderCapture_order { user: OrderCapture_orderCapture_order_user | null; userEmail: string | null; availableShippingMethods: (OrderCapture_orderCapture_order_availableShippingMethods | null)[] | null; + discount: OrderCapture_orderCapture_order_discount | null; + invoices: (OrderCapture_orderCapture_order_invoices | null)[] | null; } export interface OrderCapture_orderCapture { diff --git a/src/orders/types/OrderDetails.ts b/src/orders/types/OrderDetails.ts index 4ec01cdca..cf6adac75 100644 --- a/src/orders/types/OrderDetails.ts +++ b/src/orders/types/OrderDetails.ts @@ -2,12 +2,24 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus, OrderAction, WeightUnitsEnum } from "./../../types/globalTypes"; +import { OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus, OrderAction, JobStatusEnum, WeightUnitsEnum } from "./../../types/globalTypes"; // ==================================================== // GraphQL query operation: OrderDetails // ==================================================== +export interface OrderDetails_order_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface OrderDetails_order_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface OrderDetails_order_billingAddress_country { __typename: "CountryDisplay"; code: string; @@ -43,12 +55,25 @@ export interface OrderDetails_order_events { date: any | null; email: string | null; emailType: OrderEventsEmailsEnum | null; + invoiceNumber: string | null; message: string | null; quantity: number | null; type: OrderEventsEnum | null; user: OrderDetails_order_events_user | null; } +export interface OrderDetails_order_fulfillments_lines_orderLine_variant_product { + __typename: "Product"; + isAvailableForPurchase: boolean | null; + isPublished: boolean; +} + +export interface OrderDetails_order_fulfillments_lines_orderLine_variant { + __typename: "ProductVariant"; + product: OrderDetails_order_fulfillments_lines_orderLine_variant_product; + quantityAvailable: number; +} + export interface OrderDetails_order_fulfillments_lines_orderLine_unitPrice_gross { __typename: "Money"; amount: number; @@ -76,6 +101,7 @@ export interface OrderDetails_order_fulfillments_lines_orderLine { __typename: "OrderLine"; id: string; isShippingRequired: boolean; + variant: OrderDetails_order_fulfillments_lines_orderLine_variant | null; productName: string; productSku: string; quantity: number; @@ -107,6 +133,18 @@ export interface OrderDetails_order_fulfillments { warehouse: OrderDetails_order_fulfillments_warehouse | null; } +export interface OrderDetails_order_lines_variant_product { + __typename: "Product"; + isAvailableForPurchase: boolean | null; + isPublished: boolean; +} + +export interface OrderDetails_order_lines_variant { + __typename: "ProductVariant"; + product: OrderDetails_order_lines_variant_product; + quantityAvailable: number; +} + export interface OrderDetails_order_lines_unitPrice_gross { __typename: "Money"; amount: number; @@ -134,6 +172,7 @@ export interface OrderDetails_order_lines { __typename: "OrderLine"; id: string; isShippingRequired: boolean; + variant: OrderDetails_order_lines_variant | null; productName: string; productSku: string; quantity: number; @@ -240,9 +279,26 @@ export interface OrderDetails_order_availableShippingMethods { price: OrderDetails_order_availableShippingMethods_price | null; } +export interface OrderDetails_order_discount { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDetails_order_invoices { + __typename: "Invoice"; + id: string; + number: string | null; + createdAt: any; + url: string | null; + status: JobStatusEnum; +} + export interface OrderDetails_order { __typename: "Order"; id: string; + metadata: (OrderDetails_order_metadata | null)[]; + privateMetadata: (OrderDetails_order_privateMetadata | null)[]; billingAddress: OrderDetails_order_billingAddress | null; canFinalize: boolean; created: any; @@ -265,6 +321,8 @@ export interface OrderDetails_order { user: OrderDetails_order_user | null; userEmail: string | null; availableShippingMethods: (OrderDetails_order_availableShippingMethods | null)[] | null; + discount: OrderDetails_order_discount | null; + invoices: (OrderDetails_order_invoices | null)[] | null; } export interface OrderDetails_shop_countries { @@ -275,7 +333,7 @@ export interface OrderDetails_shop_countries { export interface OrderDetails_shop { __typename: "Shop"; - countries: (OrderDetails_shop_countries | null)[]; + countries: OrderDetails_shop_countries[]; defaultWeightUnit: WeightUnitsEnum | null; } diff --git a/src/orders/types/OrderDraftCancel.ts b/src/orders/types/OrderDraftCancel.ts index 0d5f737d9..8199977a5 100644 --- a/src/orders/types/OrderDraftCancel.ts +++ b/src/orders/types/OrderDraftCancel.ts @@ -2,7 +2,7 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { OrderErrorCode, OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus, OrderAction } from "./../../types/globalTypes"; +import { OrderErrorCode, OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus, OrderAction, JobStatusEnum } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: OrderDraftCancel @@ -14,6 +14,18 @@ export interface OrderDraftCancel_draftOrderDelete_errors { field: string | null; } +export interface OrderDraftCancel_draftOrderDelete_order_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface OrderDraftCancel_draftOrderDelete_order_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface OrderDraftCancel_draftOrderDelete_order_billingAddress_country { __typename: "CountryDisplay"; code: string; @@ -49,12 +61,25 @@ export interface OrderDraftCancel_draftOrderDelete_order_events { date: any | null; email: string | null; emailType: OrderEventsEmailsEnum | null; + invoiceNumber: string | null; message: string | null; quantity: number | null; type: OrderEventsEnum | null; user: OrderDraftCancel_draftOrderDelete_order_events_user | null; } +export interface OrderDraftCancel_draftOrderDelete_order_fulfillments_lines_orderLine_variant_product { + __typename: "Product"; + isAvailableForPurchase: boolean | null; + isPublished: boolean; +} + +export interface OrderDraftCancel_draftOrderDelete_order_fulfillments_lines_orderLine_variant { + __typename: "ProductVariant"; + product: OrderDraftCancel_draftOrderDelete_order_fulfillments_lines_orderLine_variant_product; + quantityAvailable: number; +} + export interface OrderDraftCancel_draftOrderDelete_order_fulfillments_lines_orderLine_unitPrice_gross { __typename: "Money"; amount: number; @@ -82,6 +107,7 @@ export interface OrderDraftCancel_draftOrderDelete_order_fulfillments_lines_orde __typename: "OrderLine"; id: string; isShippingRequired: boolean; + variant: OrderDraftCancel_draftOrderDelete_order_fulfillments_lines_orderLine_variant | null; productName: string; productSku: string; quantity: number; @@ -113,6 +139,18 @@ export interface OrderDraftCancel_draftOrderDelete_order_fulfillments { warehouse: OrderDraftCancel_draftOrderDelete_order_fulfillments_warehouse | null; } +export interface OrderDraftCancel_draftOrderDelete_order_lines_variant_product { + __typename: "Product"; + isAvailableForPurchase: boolean | null; + isPublished: boolean; +} + +export interface OrderDraftCancel_draftOrderDelete_order_lines_variant { + __typename: "ProductVariant"; + product: OrderDraftCancel_draftOrderDelete_order_lines_variant_product; + quantityAvailable: number; +} + export interface OrderDraftCancel_draftOrderDelete_order_lines_unitPrice_gross { __typename: "Money"; amount: number; @@ -140,6 +178,7 @@ export interface OrderDraftCancel_draftOrderDelete_order_lines { __typename: "OrderLine"; id: string; isShippingRequired: boolean; + variant: OrderDraftCancel_draftOrderDelete_order_lines_variant | null; productName: string; productSku: string; quantity: number; @@ -246,9 +285,26 @@ export interface OrderDraftCancel_draftOrderDelete_order_availableShippingMethod price: OrderDraftCancel_draftOrderDelete_order_availableShippingMethods_price | null; } +export interface OrderDraftCancel_draftOrderDelete_order_discount { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDraftCancel_draftOrderDelete_order_invoices { + __typename: "Invoice"; + id: string; + number: string | null; + createdAt: any; + url: string | null; + status: JobStatusEnum; +} + export interface OrderDraftCancel_draftOrderDelete_order { __typename: "Order"; id: string; + metadata: (OrderDraftCancel_draftOrderDelete_order_metadata | null)[]; + privateMetadata: (OrderDraftCancel_draftOrderDelete_order_privateMetadata | null)[]; billingAddress: OrderDraftCancel_draftOrderDelete_order_billingAddress | null; canFinalize: boolean; created: any; @@ -271,6 +327,8 @@ export interface OrderDraftCancel_draftOrderDelete_order { user: OrderDraftCancel_draftOrderDelete_order_user | null; userEmail: string | null; availableShippingMethods: (OrderDraftCancel_draftOrderDelete_order_availableShippingMethods | null)[] | null; + discount: OrderDraftCancel_draftOrderDelete_order_discount | null; + invoices: (OrderDraftCancel_draftOrderDelete_order_invoices | null)[] | null; } export interface OrderDraftCancel_draftOrderDelete { diff --git a/src/orders/types/OrderDraftFinalize.ts b/src/orders/types/OrderDraftFinalize.ts index 8b1ea1068..3251c64fb 100644 --- a/src/orders/types/OrderDraftFinalize.ts +++ b/src/orders/types/OrderDraftFinalize.ts @@ -2,7 +2,7 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { OrderErrorCode, OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus, OrderAction } from "./../../types/globalTypes"; +import { OrderErrorCode, OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus, OrderAction, JobStatusEnum } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: OrderDraftFinalize @@ -14,6 +14,18 @@ export interface OrderDraftFinalize_draftOrderComplete_errors { field: string | null; } +export interface OrderDraftFinalize_draftOrderComplete_order_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface OrderDraftFinalize_draftOrderComplete_order_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface OrderDraftFinalize_draftOrderComplete_order_billingAddress_country { __typename: "CountryDisplay"; code: string; @@ -49,12 +61,25 @@ export interface OrderDraftFinalize_draftOrderComplete_order_events { date: any | null; email: string | null; emailType: OrderEventsEmailsEnum | null; + invoiceNumber: string | null; message: string | null; quantity: number | null; type: OrderEventsEnum | null; user: OrderDraftFinalize_draftOrderComplete_order_events_user | null; } +export interface OrderDraftFinalize_draftOrderComplete_order_fulfillments_lines_orderLine_variant_product { + __typename: "Product"; + isAvailableForPurchase: boolean | null; + isPublished: boolean; +} + +export interface OrderDraftFinalize_draftOrderComplete_order_fulfillments_lines_orderLine_variant { + __typename: "ProductVariant"; + product: OrderDraftFinalize_draftOrderComplete_order_fulfillments_lines_orderLine_variant_product; + quantityAvailable: number; +} + export interface OrderDraftFinalize_draftOrderComplete_order_fulfillments_lines_orderLine_unitPrice_gross { __typename: "Money"; amount: number; @@ -82,6 +107,7 @@ export interface OrderDraftFinalize_draftOrderComplete_order_fulfillments_lines_ __typename: "OrderLine"; id: string; isShippingRequired: boolean; + variant: OrderDraftFinalize_draftOrderComplete_order_fulfillments_lines_orderLine_variant | null; productName: string; productSku: string; quantity: number; @@ -113,6 +139,18 @@ export interface OrderDraftFinalize_draftOrderComplete_order_fulfillments { warehouse: OrderDraftFinalize_draftOrderComplete_order_fulfillments_warehouse | null; } +export interface OrderDraftFinalize_draftOrderComplete_order_lines_variant_product { + __typename: "Product"; + isAvailableForPurchase: boolean | null; + isPublished: boolean; +} + +export interface OrderDraftFinalize_draftOrderComplete_order_lines_variant { + __typename: "ProductVariant"; + product: OrderDraftFinalize_draftOrderComplete_order_lines_variant_product; + quantityAvailable: number; +} + export interface OrderDraftFinalize_draftOrderComplete_order_lines_unitPrice_gross { __typename: "Money"; amount: number; @@ -140,6 +178,7 @@ export interface OrderDraftFinalize_draftOrderComplete_order_lines { __typename: "OrderLine"; id: string; isShippingRequired: boolean; + variant: OrderDraftFinalize_draftOrderComplete_order_lines_variant | null; productName: string; productSku: string; quantity: number; @@ -246,9 +285,26 @@ export interface OrderDraftFinalize_draftOrderComplete_order_availableShippingMe price: OrderDraftFinalize_draftOrderComplete_order_availableShippingMethods_price | null; } +export interface OrderDraftFinalize_draftOrderComplete_order_discount { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDraftFinalize_draftOrderComplete_order_invoices { + __typename: "Invoice"; + id: string; + number: string | null; + createdAt: any; + url: string | null; + status: JobStatusEnum; +} + export interface OrderDraftFinalize_draftOrderComplete_order { __typename: "Order"; id: string; + metadata: (OrderDraftFinalize_draftOrderComplete_order_metadata | null)[]; + privateMetadata: (OrderDraftFinalize_draftOrderComplete_order_privateMetadata | null)[]; billingAddress: OrderDraftFinalize_draftOrderComplete_order_billingAddress | null; canFinalize: boolean; created: any; @@ -271,6 +327,8 @@ export interface OrderDraftFinalize_draftOrderComplete_order { user: OrderDraftFinalize_draftOrderComplete_order_user | null; userEmail: string | null; availableShippingMethods: (OrderDraftFinalize_draftOrderComplete_order_availableShippingMethods | null)[] | null; + discount: OrderDraftFinalize_draftOrderComplete_order_discount | null; + invoices: (OrderDraftFinalize_draftOrderComplete_order_invoices | null)[] | null; } export interface OrderDraftFinalize_draftOrderComplete { diff --git a/src/orders/types/OrderDraftUpdate.ts b/src/orders/types/OrderDraftUpdate.ts index 77f764948..95d5b5e60 100644 --- a/src/orders/types/OrderDraftUpdate.ts +++ b/src/orders/types/OrderDraftUpdate.ts @@ -2,7 +2,7 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { DraftOrderInput, OrderErrorCode, OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus, OrderAction } from "./../../types/globalTypes"; +import { DraftOrderInput, OrderErrorCode, OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus, OrderAction, JobStatusEnum } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: OrderDraftUpdate @@ -14,6 +14,18 @@ export interface OrderDraftUpdate_draftOrderUpdate_errors { field: string | null; } +export interface OrderDraftUpdate_draftOrderUpdate_order_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface OrderDraftUpdate_draftOrderUpdate_order_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface OrderDraftUpdate_draftOrderUpdate_order_billingAddress_country { __typename: "CountryDisplay"; code: string; @@ -49,12 +61,25 @@ export interface OrderDraftUpdate_draftOrderUpdate_order_events { date: any | null; email: string | null; emailType: OrderEventsEmailsEnum | null; + invoiceNumber: string | null; message: string | null; quantity: number | null; type: OrderEventsEnum | null; user: OrderDraftUpdate_draftOrderUpdate_order_events_user | null; } +export interface OrderDraftUpdate_draftOrderUpdate_order_fulfillments_lines_orderLine_variant_product { + __typename: "Product"; + isAvailableForPurchase: boolean | null; + isPublished: boolean; +} + +export interface OrderDraftUpdate_draftOrderUpdate_order_fulfillments_lines_orderLine_variant { + __typename: "ProductVariant"; + product: OrderDraftUpdate_draftOrderUpdate_order_fulfillments_lines_orderLine_variant_product; + quantityAvailable: number; +} + export interface OrderDraftUpdate_draftOrderUpdate_order_fulfillments_lines_orderLine_unitPrice_gross { __typename: "Money"; amount: number; @@ -82,6 +107,7 @@ export interface OrderDraftUpdate_draftOrderUpdate_order_fulfillments_lines_orde __typename: "OrderLine"; id: string; isShippingRequired: boolean; + variant: OrderDraftUpdate_draftOrderUpdate_order_fulfillments_lines_orderLine_variant | null; productName: string; productSku: string; quantity: number; @@ -113,6 +139,18 @@ export interface OrderDraftUpdate_draftOrderUpdate_order_fulfillments { warehouse: OrderDraftUpdate_draftOrderUpdate_order_fulfillments_warehouse | null; } +export interface OrderDraftUpdate_draftOrderUpdate_order_lines_variant_product { + __typename: "Product"; + isAvailableForPurchase: boolean | null; + isPublished: boolean; +} + +export interface OrderDraftUpdate_draftOrderUpdate_order_lines_variant { + __typename: "ProductVariant"; + product: OrderDraftUpdate_draftOrderUpdate_order_lines_variant_product; + quantityAvailable: number; +} + export interface OrderDraftUpdate_draftOrderUpdate_order_lines_unitPrice_gross { __typename: "Money"; amount: number; @@ -140,6 +178,7 @@ export interface OrderDraftUpdate_draftOrderUpdate_order_lines { __typename: "OrderLine"; id: string; isShippingRequired: boolean; + variant: OrderDraftUpdate_draftOrderUpdate_order_lines_variant | null; productName: string; productSku: string; quantity: number; @@ -246,9 +285,26 @@ export interface OrderDraftUpdate_draftOrderUpdate_order_availableShippingMethod price: OrderDraftUpdate_draftOrderUpdate_order_availableShippingMethods_price | null; } +export interface OrderDraftUpdate_draftOrderUpdate_order_discount { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDraftUpdate_draftOrderUpdate_order_invoices { + __typename: "Invoice"; + id: string; + number: string | null; + createdAt: any; + url: string | null; + status: JobStatusEnum; +} + export interface OrderDraftUpdate_draftOrderUpdate_order { __typename: "Order"; id: string; + metadata: (OrderDraftUpdate_draftOrderUpdate_order_metadata | null)[]; + privateMetadata: (OrderDraftUpdate_draftOrderUpdate_order_privateMetadata | null)[]; billingAddress: OrderDraftUpdate_draftOrderUpdate_order_billingAddress | null; canFinalize: boolean; created: any; @@ -271,6 +327,8 @@ export interface OrderDraftUpdate_draftOrderUpdate_order { user: OrderDraftUpdate_draftOrderUpdate_order_user | null; userEmail: string | null; availableShippingMethods: (OrderDraftUpdate_draftOrderUpdate_order_availableShippingMethods | null)[] | null; + discount: OrderDraftUpdate_draftOrderUpdate_order_discount | null; + invoices: (OrderDraftUpdate_draftOrderUpdate_order_invoices | null)[] | null; } export interface OrderDraftUpdate_draftOrderUpdate { diff --git a/src/orders/types/OrderFulfillmentCancel.ts b/src/orders/types/OrderFulfillmentCancel.ts index 014908b9e..4ae7b4eac 100644 --- a/src/orders/types/OrderFulfillmentCancel.ts +++ b/src/orders/types/OrderFulfillmentCancel.ts @@ -2,7 +2,7 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { FulfillmentCancelInput, OrderErrorCode, OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus, OrderAction } from "./../../types/globalTypes"; +import { FulfillmentCancelInput, OrderErrorCode, OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus, OrderAction, JobStatusEnum } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: OrderFulfillmentCancel @@ -14,6 +14,18 @@ export interface OrderFulfillmentCancel_orderFulfillmentCancel_errors { field: string | null; } +export interface OrderFulfillmentCancel_orderFulfillmentCancel_order_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface OrderFulfillmentCancel_orderFulfillmentCancel_order_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface OrderFulfillmentCancel_orderFulfillmentCancel_order_billingAddress_country { __typename: "CountryDisplay"; code: string; @@ -49,12 +61,25 @@ export interface OrderFulfillmentCancel_orderFulfillmentCancel_order_events { date: any | null; email: string | null; emailType: OrderEventsEmailsEnum | null; + invoiceNumber: string | null; message: string | null; quantity: number | null; type: OrderEventsEnum | null; user: OrderFulfillmentCancel_orderFulfillmentCancel_order_events_user | null; } +export interface OrderFulfillmentCancel_orderFulfillmentCancel_order_fulfillments_lines_orderLine_variant_product { + __typename: "Product"; + isAvailableForPurchase: boolean | null; + isPublished: boolean; +} + +export interface OrderFulfillmentCancel_orderFulfillmentCancel_order_fulfillments_lines_orderLine_variant { + __typename: "ProductVariant"; + product: OrderFulfillmentCancel_orderFulfillmentCancel_order_fulfillments_lines_orderLine_variant_product; + quantityAvailable: number; +} + export interface OrderFulfillmentCancel_orderFulfillmentCancel_order_fulfillments_lines_orderLine_unitPrice_gross { __typename: "Money"; amount: number; @@ -82,6 +107,7 @@ export interface OrderFulfillmentCancel_orderFulfillmentCancel_order_fulfillment __typename: "OrderLine"; id: string; isShippingRequired: boolean; + variant: OrderFulfillmentCancel_orderFulfillmentCancel_order_fulfillments_lines_orderLine_variant | null; productName: string; productSku: string; quantity: number; @@ -113,6 +139,18 @@ export interface OrderFulfillmentCancel_orderFulfillmentCancel_order_fulfillment warehouse: OrderFulfillmentCancel_orderFulfillmentCancel_order_fulfillments_warehouse | null; } +export interface OrderFulfillmentCancel_orderFulfillmentCancel_order_lines_variant_product { + __typename: "Product"; + isAvailableForPurchase: boolean | null; + isPublished: boolean; +} + +export interface OrderFulfillmentCancel_orderFulfillmentCancel_order_lines_variant { + __typename: "ProductVariant"; + product: OrderFulfillmentCancel_orderFulfillmentCancel_order_lines_variant_product; + quantityAvailable: number; +} + export interface OrderFulfillmentCancel_orderFulfillmentCancel_order_lines_unitPrice_gross { __typename: "Money"; amount: number; @@ -140,6 +178,7 @@ export interface OrderFulfillmentCancel_orderFulfillmentCancel_order_lines { __typename: "OrderLine"; id: string; isShippingRequired: boolean; + variant: OrderFulfillmentCancel_orderFulfillmentCancel_order_lines_variant | null; productName: string; productSku: string; quantity: number; @@ -246,9 +285,26 @@ export interface OrderFulfillmentCancel_orderFulfillmentCancel_order_availableSh price: OrderFulfillmentCancel_orderFulfillmentCancel_order_availableShippingMethods_price | null; } +export interface OrderFulfillmentCancel_orderFulfillmentCancel_order_discount { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderFulfillmentCancel_orderFulfillmentCancel_order_invoices { + __typename: "Invoice"; + id: string; + number: string | null; + createdAt: any; + url: string | null; + status: JobStatusEnum; +} + export interface OrderFulfillmentCancel_orderFulfillmentCancel_order { __typename: "Order"; id: string; + metadata: (OrderFulfillmentCancel_orderFulfillmentCancel_order_metadata | null)[]; + privateMetadata: (OrderFulfillmentCancel_orderFulfillmentCancel_order_privateMetadata | null)[]; billingAddress: OrderFulfillmentCancel_orderFulfillmentCancel_order_billingAddress | null; canFinalize: boolean; created: any; @@ -271,6 +327,8 @@ export interface OrderFulfillmentCancel_orderFulfillmentCancel_order { user: OrderFulfillmentCancel_orderFulfillmentCancel_order_user | null; userEmail: string | null; availableShippingMethods: (OrderFulfillmentCancel_orderFulfillmentCancel_order_availableShippingMethods | null)[] | null; + discount: OrderFulfillmentCancel_orderFulfillmentCancel_order_discount | null; + invoices: (OrderFulfillmentCancel_orderFulfillmentCancel_order_invoices | null)[] | null; } export interface OrderFulfillmentCancel_orderFulfillmentCancel { diff --git a/src/orders/types/OrderFulfillmentUpdateTracking.ts b/src/orders/types/OrderFulfillmentUpdateTracking.ts index 0a0e5cca1..13962b3e4 100644 --- a/src/orders/types/OrderFulfillmentUpdateTracking.ts +++ b/src/orders/types/OrderFulfillmentUpdateTracking.ts @@ -2,7 +2,7 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { FulfillmentUpdateTrackingInput, OrderErrorCode, OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus, OrderAction } from "./../../types/globalTypes"; +import { FulfillmentUpdateTrackingInput, OrderErrorCode, OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus, OrderAction, JobStatusEnum } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: OrderFulfillmentUpdateTracking @@ -14,6 +14,18 @@ export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_e field: string | null; } +export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_billingAddress_country { __typename: "CountryDisplay"; code: string; @@ -49,12 +61,25 @@ export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_o date: any | null; email: string | null; emailType: OrderEventsEmailsEnum | null; + invoiceNumber: string | null; message: string | null; quantity: number | null; type: OrderEventsEnum | null; user: OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_events_user | null; } +export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_fulfillments_lines_orderLine_variant_product { + __typename: "Product"; + isAvailableForPurchase: boolean | null; + isPublished: boolean; +} + +export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_fulfillments_lines_orderLine_variant { + __typename: "ProductVariant"; + product: OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_fulfillments_lines_orderLine_variant_product; + quantityAvailable: number; +} + export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_fulfillments_lines_orderLine_unitPrice_gross { __typename: "Money"; amount: number; @@ -82,6 +107,7 @@ export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_o __typename: "OrderLine"; id: string; isShippingRequired: boolean; + variant: OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_fulfillments_lines_orderLine_variant | null; productName: string; productSku: string; quantity: number; @@ -113,6 +139,18 @@ export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_o warehouse: OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_fulfillments_warehouse | null; } +export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_lines_variant_product { + __typename: "Product"; + isAvailableForPurchase: boolean | null; + isPublished: boolean; +} + +export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_lines_variant { + __typename: "ProductVariant"; + product: OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_lines_variant_product; + quantityAvailable: number; +} + export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_lines_unitPrice_gross { __typename: "Money"; amount: number; @@ -140,6 +178,7 @@ export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_o __typename: "OrderLine"; id: string; isShippingRequired: boolean; + variant: OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_lines_variant | null; productName: string; productSku: string; quantity: number; @@ -246,9 +285,26 @@ export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_o price: OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_availableShippingMethods_price | null; } +export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_discount { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_invoices { + __typename: "Invoice"; + id: string; + number: string | null; + createdAt: any; + url: string | null; + status: JobStatusEnum; +} + export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order { __typename: "Order"; id: string; + metadata: (OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_metadata | null)[]; + privateMetadata: (OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_privateMetadata | null)[]; billingAddress: OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_billingAddress | null; canFinalize: boolean; created: any; @@ -271,6 +327,8 @@ export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_o user: OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_user | null; userEmail: string | null; availableShippingMethods: (OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_availableShippingMethods | null)[] | null; + discount: OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_discount | null; + invoices: (OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_invoices | null)[] | null; } export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking { diff --git a/src/orders/types/OrderLineDelete.ts b/src/orders/types/OrderLineDelete.ts index 8205439ea..8ff4b5ea6 100644 --- a/src/orders/types/OrderLineDelete.ts +++ b/src/orders/types/OrderLineDelete.ts @@ -2,7 +2,7 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { OrderErrorCode, OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus, OrderAction } from "./../../types/globalTypes"; +import { OrderErrorCode, OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus, OrderAction, JobStatusEnum } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: OrderLineDelete @@ -14,6 +14,18 @@ export interface OrderLineDelete_draftOrderLineDelete_errors { field: string | null; } +export interface OrderLineDelete_draftOrderLineDelete_order_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface OrderLineDelete_draftOrderLineDelete_order_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface OrderLineDelete_draftOrderLineDelete_order_billingAddress_country { __typename: "CountryDisplay"; code: string; @@ -49,12 +61,25 @@ export interface OrderLineDelete_draftOrderLineDelete_order_events { date: any | null; email: string | null; emailType: OrderEventsEmailsEnum | null; + invoiceNumber: string | null; message: string | null; quantity: number | null; type: OrderEventsEnum | null; user: OrderLineDelete_draftOrderLineDelete_order_events_user | null; } +export interface OrderLineDelete_draftOrderLineDelete_order_fulfillments_lines_orderLine_variant_product { + __typename: "Product"; + isAvailableForPurchase: boolean | null; + isPublished: boolean; +} + +export interface OrderLineDelete_draftOrderLineDelete_order_fulfillments_lines_orderLine_variant { + __typename: "ProductVariant"; + product: OrderLineDelete_draftOrderLineDelete_order_fulfillments_lines_orderLine_variant_product; + quantityAvailable: number; +} + export interface OrderLineDelete_draftOrderLineDelete_order_fulfillments_lines_orderLine_unitPrice_gross { __typename: "Money"; amount: number; @@ -82,6 +107,7 @@ export interface OrderLineDelete_draftOrderLineDelete_order_fulfillments_lines_o __typename: "OrderLine"; id: string; isShippingRequired: boolean; + variant: OrderLineDelete_draftOrderLineDelete_order_fulfillments_lines_orderLine_variant | null; productName: string; productSku: string; quantity: number; @@ -113,6 +139,18 @@ export interface OrderLineDelete_draftOrderLineDelete_order_fulfillments { warehouse: OrderLineDelete_draftOrderLineDelete_order_fulfillments_warehouse | null; } +export interface OrderLineDelete_draftOrderLineDelete_order_lines_variant_product { + __typename: "Product"; + isAvailableForPurchase: boolean | null; + isPublished: boolean; +} + +export interface OrderLineDelete_draftOrderLineDelete_order_lines_variant { + __typename: "ProductVariant"; + product: OrderLineDelete_draftOrderLineDelete_order_lines_variant_product; + quantityAvailable: number; +} + export interface OrderLineDelete_draftOrderLineDelete_order_lines_unitPrice_gross { __typename: "Money"; amount: number; @@ -140,6 +178,7 @@ export interface OrderLineDelete_draftOrderLineDelete_order_lines { __typename: "OrderLine"; id: string; isShippingRequired: boolean; + variant: OrderLineDelete_draftOrderLineDelete_order_lines_variant | null; productName: string; productSku: string; quantity: number; @@ -246,9 +285,26 @@ export interface OrderLineDelete_draftOrderLineDelete_order_availableShippingMet price: OrderLineDelete_draftOrderLineDelete_order_availableShippingMethods_price | null; } +export interface OrderLineDelete_draftOrderLineDelete_order_discount { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderLineDelete_draftOrderLineDelete_order_invoices { + __typename: "Invoice"; + id: string; + number: string | null; + createdAt: any; + url: string | null; + status: JobStatusEnum; +} + export interface OrderLineDelete_draftOrderLineDelete_order { __typename: "Order"; id: string; + metadata: (OrderLineDelete_draftOrderLineDelete_order_metadata | null)[]; + privateMetadata: (OrderLineDelete_draftOrderLineDelete_order_privateMetadata | null)[]; billingAddress: OrderLineDelete_draftOrderLineDelete_order_billingAddress | null; canFinalize: boolean; created: any; @@ -271,6 +327,8 @@ export interface OrderLineDelete_draftOrderLineDelete_order { user: OrderLineDelete_draftOrderLineDelete_order_user | null; userEmail: string | null; availableShippingMethods: (OrderLineDelete_draftOrderLineDelete_order_availableShippingMethods | null)[] | null; + discount: OrderLineDelete_draftOrderLineDelete_order_discount | null; + invoices: (OrderLineDelete_draftOrderLineDelete_order_invoices | null)[] | null; } export interface OrderLineDelete_draftOrderLineDelete { diff --git a/src/orders/types/OrderLineUpdate.ts b/src/orders/types/OrderLineUpdate.ts index 948b0beac..b214b9e17 100644 --- a/src/orders/types/OrderLineUpdate.ts +++ b/src/orders/types/OrderLineUpdate.ts @@ -2,7 +2,7 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { OrderLineInput, OrderErrorCode, OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus, OrderAction } from "./../../types/globalTypes"; +import { OrderLineInput, OrderErrorCode, OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus, OrderAction, JobStatusEnum } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: OrderLineUpdate @@ -14,6 +14,18 @@ export interface OrderLineUpdate_draftOrderLineUpdate_errors { field: string | null; } +export interface OrderLineUpdate_draftOrderLineUpdate_order_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface OrderLineUpdate_draftOrderLineUpdate_order_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface OrderLineUpdate_draftOrderLineUpdate_order_billingAddress_country { __typename: "CountryDisplay"; code: string; @@ -49,12 +61,25 @@ export interface OrderLineUpdate_draftOrderLineUpdate_order_events { date: any | null; email: string | null; emailType: OrderEventsEmailsEnum | null; + invoiceNumber: string | null; message: string | null; quantity: number | null; type: OrderEventsEnum | null; user: OrderLineUpdate_draftOrderLineUpdate_order_events_user | null; } +export interface OrderLineUpdate_draftOrderLineUpdate_order_fulfillments_lines_orderLine_variant_product { + __typename: "Product"; + isAvailableForPurchase: boolean | null; + isPublished: boolean; +} + +export interface OrderLineUpdate_draftOrderLineUpdate_order_fulfillments_lines_orderLine_variant { + __typename: "ProductVariant"; + product: OrderLineUpdate_draftOrderLineUpdate_order_fulfillments_lines_orderLine_variant_product; + quantityAvailable: number; +} + export interface OrderLineUpdate_draftOrderLineUpdate_order_fulfillments_lines_orderLine_unitPrice_gross { __typename: "Money"; amount: number; @@ -82,6 +107,7 @@ export interface OrderLineUpdate_draftOrderLineUpdate_order_fulfillments_lines_o __typename: "OrderLine"; id: string; isShippingRequired: boolean; + variant: OrderLineUpdate_draftOrderLineUpdate_order_fulfillments_lines_orderLine_variant | null; productName: string; productSku: string; quantity: number; @@ -113,6 +139,18 @@ export interface OrderLineUpdate_draftOrderLineUpdate_order_fulfillments { warehouse: OrderLineUpdate_draftOrderLineUpdate_order_fulfillments_warehouse | null; } +export interface OrderLineUpdate_draftOrderLineUpdate_order_lines_variant_product { + __typename: "Product"; + isAvailableForPurchase: boolean | null; + isPublished: boolean; +} + +export interface OrderLineUpdate_draftOrderLineUpdate_order_lines_variant { + __typename: "ProductVariant"; + product: OrderLineUpdate_draftOrderLineUpdate_order_lines_variant_product; + quantityAvailable: number; +} + export interface OrderLineUpdate_draftOrderLineUpdate_order_lines_unitPrice_gross { __typename: "Money"; amount: number; @@ -140,6 +178,7 @@ export interface OrderLineUpdate_draftOrderLineUpdate_order_lines { __typename: "OrderLine"; id: string; isShippingRequired: boolean; + variant: OrderLineUpdate_draftOrderLineUpdate_order_lines_variant | null; productName: string; productSku: string; quantity: number; @@ -246,9 +285,26 @@ export interface OrderLineUpdate_draftOrderLineUpdate_order_availableShippingMet price: OrderLineUpdate_draftOrderLineUpdate_order_availableShippingMethods_price | null; } +export interface OrderLineUpdate_draftOrderLineUpdate_order_discount { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderLineUpdate_draftOrderLineUpdate_order_invoices { + __typename: "Invoice"; + id: string; + number: string | null; + createdAt: any; + url: string | null; + status: JobStatusEnum; +} + export interface OrderLineUpdate_draftOrderLineUpdate_order { __typename: "Order"; id: string; + metadata: (OrderLineUpdate_draftOrderLineUpdate_order_metadata | null)[]; + privateMetadata: (OrderLineUpdate_draftOrderLineUpdate_order_privateMetadata | null)[]; billingAddress: OrderLineUpdate_draftOrderLineUpdate_order_billingAddress | null; canFinalize: boolean; created: any; @@ -271,6 +327,8 @@ export interface OrderLineUpdate_draftOrderLineUpdate_order { user: OrderLineUpdate_draftOrderLineUpdate_order_user | null; userEmail: string | null; availableShippingMethods: (OrderLineUpdate_draftOrderLineUpdate_order_availableShippingMethods | null)[] | null; + discount: OrderLineUpdate_draftOrderLineUpdate_order_discount | null; + invoices: (OrderLineUpdate_draftOrderLineUpdate_order_invoices | null)[] | null; } export interface OrderLineUpdate_draftOrderLineUpdate { diff --git a/src/orders/types/OrderLinesAdd.ts b/src/orders/types/OrderLinesAdd.ts index b2cd429e8..d4edddb09 100644 --- a/src/orders/types/OrderLinesAdd.ts +++ b/src/orders/types/OrderLinesAdd.ts @@ -2,7 +2,7 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { OrderLineCreateInput, OrderErrorCode, OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus, OrderAction } from "./../../types/globalTypes"; +import { OrderLineCreateInput, OrderErrorCode, OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus, OrderAction, JobStatusEnum } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: OrderLinesAdd @@ -14,6 +14,18 @@ export interface OrderLinesAdd_draftOrderLinesCreate_errors { field: string | null; } +export interface OrderLinesAdd_draftOrderLinesCreate_order_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface OrderLinesAdd_draftOrderLinesCreate_order_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface OrderLinesAdd_draftOrderLinesCreate_order_billingAddress_country { __typename: "CountryDisplay"; code: string; @@ -49,12 +61,25 @@ export interface OrderLinesAdd_draftOrderLinesCreate_order_events { date: any | null; email: string | null; emailType: OrderEventsEmailsEnum | null; + invoiceNumber: string | null; message: string | null; quantity: number | null; type: OrderEventsEnum | null; user: OrderLinesAdd_draftOrderLinesCreate_order_events_user | null; } +export interface OrderLinesAdd_draftOrderLinesCreate_order_fulfillments_lines_orderLine_variant_product { + __typename: "Product"; + isAvailableForPurchase: boolean | null; + isPublished: boolean; +} + +export interface OrderLinesAdd_draftOrderLinesCreate_order_fulfillments_lines_orderLine_variant { + __typename: "ProductVariant"; + product: OrderLinesAdd_draftOrderLinesCreate_order_fulfillments_lines_orderLine_variant_product; + quantityAvailable: number; +} + export interface OrderLinesAdd_draftOrderLinesCreate_order_fulfillments_lines_orderLine_unitPrice_gross { __typename: "Money"; amount: number; @@ -82,6 +107,7 @@ export interface OrderLinesAdd_draftOrderLinesCreate_order_fulfillments_lines_or __typename: "OrderLine"; id: string; isShippingRequired: boolean; + variant: OrderLinesAdd_draftOrderLinesCreate_order_fulfillments_lines_orderLine_variant | null; productName: string; productSku: string; quantity: number; @@ -113,6 +139,18 @@ export interface OrderLinesAdd_draftOrderLinesCreate_order_fulfillments { warehouse: OrderLinesAdd_draftOrderLinesCreate_order_fulfillments_warehouse | null; } +export interface OrderLinesAdd_draftOrderLinesCreate_order_lines_variant_product { + __typename: "Product"; + isAvailableForPurchase: boolean | null; + isPublished: boolean; +} + +export interface OrderLinesAdd_draftOrderLinesCreate_order_lines_variant { + __typename: "ProductVariant"; + product: OrderLinesAdd_draftOrderLinesCreate_order_lines_variant_product; + quantityAvailable: number; +} + export interface OrderLinesAdd_draftOrderLinesCreate_order_lines_unitPrice_gross { __typename: "Money"; amount: number; @@ -140,6 +178,7 @@ export interface OrderLinesAdd_draftOrderLinesCreate_order_lines { __typename: "OrderLine"; id: string; isShippingRequired: boolean; + variant: OrderLinesAdd_draftOrderLinesCreate_order_lines_variant | null; productName: string; productSku: string; quantity: number; @@ -246,9 +285,26 @@ export interface OrderLinesAdd_draftOrderLinesCreate_order_availableShippingMeth price: OrderLinesAdd_draftOrderLinesCreate_order_availableShippingMethods_price | null; } +export interface OrderLinesAdd_draftOrderLinesCreate_order_discount { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderLinesAdd_draftOrderLinesCreate_order_invoices { + __typename: "Invoice"; + id: string; + number: string | null; + createdAt: any; + url: string | null; + status: JobStatusEnum; +} + export interface OrderLinesAdd_draftOrderLinesCreate_order { __typename: "Order"; id: string; + metadata: (OrderLinesAdd_draftOrderLinesCreate_order_metadata | null)[]; + privateMetadata: (OrderLinesAdd_draftOrderLinesCreate_order_privateMetadata | null)[]; billingAddress: OrderLinesAdd_draftOrderLinesCreate_order_billingAddress | null; canFinalize: boolean; created: any; @@ -271,6 +327,8 @@ export interface OrderLinesAdd_draftOrderLinesCreate_order { user: OrderLinesAdd_draftOrderLinesCreate_order_user | null; userEmail: string | null; availableShippingMethods: (OrderLinesAdd_draftOrderLinesCreate_order_availableShippingMethods | null)[] | null; + discount: OrderLinesAdd_draftOrderLinesCreate_order_discount | null; + invoices: (OrderLinesAdd_draftOrderLinesCreate_order_invoices | null)[] | null; } export interface OrderLinesAdd_draftOrderLinesCreate { diff --git a/src/orders/types/OrderMarkAsPaid.ts b/src/orders/types/OrderMarkAsPaid.ts index 898cf9a99..c7c5cc9b2 100644 --- a/src/orders/types/OrderMarkAsPaid.ts +++ b/src/orders/types/OrderMarkAsPaid.ts @@ -2,7 +2,7 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { OrderErrorCode, OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus, OrderAction } from "./../../types/globalTypes"; +import { OrderErrorCode, OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus, OrderAction, JobStatusEnum } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: OrderMarkAsPaid @@ -14,6 +14,18 @@ export interface OrderMarkAsPaid_orderMarkAsPaid_errors { field: string | null; } +export interface OrderMarkAsPaid_orderMarkAsPaid_order_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface OrderMarkAsPaid_orderMarkAsPaid_order_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface OrderMarkAsPaid_orderMarkAsPaid_order_billingAddress_country { __typename: "CountryDisplay"; code: string; @@ -49,12 +61,25 @@ export interface OrderMarkAsPaid_orderMarkAsPaid_order_events { date: any | null; email: string | null; emailType: OrderEventsEmailsEnum | null; + invoiceNumber: string | null; message: string | null; quantity: number | null; type: OrderEventsEnum | null; user: OrderMarkAsPaid_orderMarkAsPaid_order_events_user | null; } +export interface OrderMarkAsPaid_orderMarkAsPaid_order_fulfillments_lines_orderLine_variant_product { + __typename: "Product"; + isAvailableForPurchase: boolean | null; + isPublished: boolean; +} + +export interface OrderMarkAsPaid_orderMarkAsPaid_order_fulfillments_lines_orderLine_variant { + __typename: "ProductVariant"; + product: OrderMarkAsPaid_orderMarkAsPaid_order_fulfillments_lines_orderLine_variant_product; + quantityAvailable: number; +} + export interface OrderMarkAsPaid_orderMarkAsPaid_order_fulfillments_lines_orderLine_unitPrice_gross { __typename: "Money"; amount: number; @@ -82,6 +107,7 @@ export interface OrderMarkAsPaid_orderMarkAsPaid_order_fulfillments_lines_orderL __typename: "OrderLine"; id: string; isShippingRequired: boolean; + variant: OrderMarkAsPaid_orderMarkAsPaid_order_fulfillments_lines_orderLine_variant | null; productName: string; productSku: string; quantity: number; @@ -113,6 +139,18 @@ export interface OrderMarkAsPaid_orderMarkAsPaid_order_fulfillments { warehouse: OrderMarkAsPaid_orderMarkAsPaid_order_fulfillments_warehouse | null; } +export interface OrderMarkAsPaid_orderMarkAsPaid_order_lines_variant_product { + __typename: "Product"; + isAvailableForPurchase: boolean | null; + isPublished: boolean; +} + +export interface OrderMarkAsPaid_orderMarkAsPaid_order_lines_variant { + __typename: "ProductVariant"; + product: OrderMarkAsPaid_orderMarkAsPaid_order_lines_variant_product; + quantityAvailable: number; +} + export interface OrderMarkAsPaid_orderMarkAsPaid_order_lines_unitPrice_gross { __typename: "Money"; amount: number; @@ -140,6 +178,7 @@ export interface OrderMarkAsPaid_orderMarkAsPaid_order_lines { __typename: "OrderLine"; id: string; isShippingRequired: boolean; + variant: OrderMarkAsPaid_orderMarkAsPaid_order_lines_variant | null; productName: string; productSku: string; quantity: number; @@ -246,9 +285,26 @@ export interface OrderMarkAsPaid_orderMarkAsPaid_order_availableShippingMethods price: OrderMarkAsPaid_orderMarkAsPaid_order_availableShippingMethods_price | null; } +export interface OrderMarkAsPaid_orderMarkAsPaid_order_discount { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderMarkAsPaid_orderMarkAsPaid_order_invoices { + __typename: "Invoice"; + id: string; + number: string | null; + createdAt: any; + url: string | null; + status: JobStatusEnum; +} + export interface OrderMarkAsPaid_orderMarkAsPaid_order { __typename: "Order"; id: string; + metadata: (OrderMarkAsPaid_orderMarkAsPaid_order_metadata | null)[]; + privateMetadata: (OrderMarkAsPaid_orderMarkAsPaid_order_privateMetadata | null)[]; billingAddress: OrderMarkAsPaid_orderMarkAsPaid_order_billingAddress | null; canFinalize: boolean; created: any; @@ -271,6 +327,8 @@ export interface OrderMarkAsPaid_orderMarkAsPaid_order { user: OrderMarkAsPaid_orderMarkAsPaid_order_user | null; userEmail: string | null; availableShippingMethods: (OrderMarkAsPaid_orderMarkAsPaid_order_availableShippingMethods | null)[] | null; + discount: OrderMarkAsPaid_orderMarkAsPaid_order_discount | null; + invoices: (OrderMarkAsPaid_orderMarkAsPaid_order_invoices | null)[] | null; } export interface OrderMarkAsPaid_orderMarkAsPaid { diff --git a/src/orders/types/OrderRefund.ts b/src/orders/types/OrderRefund.ts index 6f764f9e6..8ba6a4c84 100644 --- a/src/orders/types/OrderRefund.ts +++ b/src/orders/types/OrderRefund.ts @@ -2,7 +2,7 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { OrderErrorCode, OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus, OrderAction } from "./../../types/globalTypes"; +import { OrderErrorCode, OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus, OrderAction, JobStatusEnum } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: OrderRefund @@ -14,6 +14,18 @@ export interface OrderRefund_orderRefund_errors { field: string | null; } +export interface OrderRefund_orderRefund_order_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface OrderRefund_orderRefund_order_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface OrderRefund_orderRefund_order_billingAddress_country { __typename: "CountryDisplay"; code: string; @@ -49,12 +61,25 @@ export interface OrderRefund_orderRefund_order_events { date: any | null; email: string | null; emailType: OrderEventsEmailsEnum | null; + invoiceNumber: string | null; message: string | null; quantity: number | null; type: OrderEventsEnum | null; user: OrderRefund_orderRefund_order_events_user | null; } +export interface OrderRefund_orderRefund_order_fulfillments_lines_orderLine_variant_product { + __typename: "Product"; + isAvailableForPurchase: boolean | null; + isPublished: boolean; +} + +export interface OrderRefund_orderRefund_order_fulfillments_lines_orderLine_variant { + __typename: "ProductVariant"; + product: OrderRefund_orderRefund_order_fulfillments_lines_orderLine_variant_product; + quantityAvailable: number; +} + export interface OrderRefund_orderRefund_order_fulfillments_lines_orderLine_unitPrice_gross { __typename: "Money"; amount: number; @@ -82,6 +107,7 @@ export interface OrderRefund_orderRefund_order_fulfillments_lines_orderLine { __typename: "OrderLine"; id: string; isShippingRequired: boolean; + variant: OrderRefund_orderRefund_order_fulfillments_lines_orderLine_variant | null; productName: string; productSku: string; quantity: number; @@ -113,6 +139,18 @@ export interface OrderRefund_orderRefund_order_fulfillments { warehouse: OrderRefund_orderRefund_order_fulfillments_warehouse | null; } +export interface OrderRefund_orderRefund_order_lines_variant_product { + __typename: "Product"; + isAvailableForPurchase: boolean | null; + isPublished: boolean; +} + +export interface OrderRefund_orderRefund_order_lines_variant { + __typename: "ProductVariant"; + product: OrderRefund_orderRefund_order_lines_variant_product; + quantityAvailable: number; +} + export interface OrderRefund_orderRefund_order_lines_unitPrice_gross { __typename: "Money"; amount: number; @@ -140,6 +178,7 @@ export interface OrderRefund_orderRefund_order_lines { __typename: "OrderLine"; id: string; isShippingRequired: boolean; + variant: OrderRefund_orderRefund_order_lines_variant | null; productName: string; productSku: string; quantity: number; @@ -246,9 +285,26 @@ export interface OrderRefund_orderRefund_order_availableShippingMethods { price: OrderRefund_orderRefund_order_availableShippingMethods_price | null; } +export interface OrderRefund_orderRefund_order_discount { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderRefund_orderRefund_order_invoices { + __typename: "Invoice"; + id: string; + number: string | null; + createdAt: any; + url: string | null; + status: JobStatusEnum; +} + export interface OrderRefund_orderRefund_order { __typename: "Order"; id: string; + metadata: (OrderRefund_orderRefund_order_metadata | null)[]; + privateMetadata: (OrderRefund_orderRefund_order_privateMetadata | null)[]; billingAddress: OrderRefund_orderRefund_order_billingAddress | null; canFinalize: boolean; created: any; @@ -271,6 +327,8 @@ export interface OrderRefund_orderRefund_order { user: OrderRefund_orderRefund_order_user | null; userEmail: string | null; availableShippingMethods: (OrderRefund_orderRefund_order_availableShippingMethods | null)[] | null; + discount: OrderRefund_orderRefund_order_discount | null; + invoices: (OrderRefund_orderRefund_order_invoices | null)[] | null; } export interface OrderRefund_orderRefund { diff --git a/src/orders/types/OrderRelease.ts b/src/orders/types/OrderRelease.ts deleted file mode 100644 index 0fb77a66f..000000000 --- a/src/orders/types/OrderRelease.ts +++ /dev/null @@ -1,267 +0,0 @@ -/* tslint:disable */ -// This file was automatically generated and should not be edited. - -import { OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus } from "./../../types/globalTypes"; - -// ==================================================== -// GraphQL mutation operation: OrderRelease -// ==================================================== - -export interface OrderRelease_orderRelease_order_billingAddress_country { - __typename: "CountryDisplay"; - code: string; - country: string; -} - -export interface OrderRelease_orderRelease_order_billingAddress { - __typename: "Address"; - city: string; - cityArea: string; - companyName: string; - country: OrderRelease_orderRelease_order_billingAddress_country; - countryArea: string; - firstName: string; - id: string; - lastName: string; - phone: string | null; - postalCode: string; - streetAddress1: string; - streetAddress2: string; -} - -export interface OrderRelease_orderRelease_order_events_user { - __typename: "User"; - email: string; -} - -export interface OrderRelease_orderRelease_order_events { - __typename: "OrderEvent"; - id: string; - amount: number | null; - date: any | null; - email: string | null; - emailType: OrderEventsEmailsEnum | null; - message: string | null; - quantity: number | null; - type: OrderEventsEnum | null; - user: OrderRelease_orderRelease_order_events_user | null; -} - -export interface OrderRelease_orderRelease_order_fulfillments_lines_edges_node_orderLine_unitPrice_gross { - __typename: "Money"; - amount: number; - currency: string; -} - -export interface OrderRelease_orderRelease_order_fulfillments_lines_edges_node_orderLine_unitPrice_net { - __typename: "Money"; - amount: number; - currency: string; -} - -export interface OrderRelease_orderRelease_order_fulfillments_lines_edges_node_orderLine_unitPrice { - __typename: "TaxedMoney"; - gross: OrderRelease_orderRelease_order_fulfillments_lines_edges_node_orderLine_unitPrice_gross; - net: OrderRelease_orderRelease_order_fulfillments_lines_edges_node_orderLine_unitPrice_net; -} - -export interface OrderRelease_orderRelease_order_fulfillments_lines_edges_node_orderLine { - __typename: "OrderLine"; - id: string; - productName: string; - productSku: string; - quantity: number; - quantityFulfilled: number; - unitPrice: OrderRelease_orderRelease_order_fulfillments_lines_edges_node_orderLine_unitPrice | null; - thumbnailUrl: string | null; -} - -export interface OrderRelease_orderRelease_order_fulfillments_lines_edges_node { - __typename: "FulfillmentLine"; - id: string; - quantity: number; - orderLine: OrderRelease_orderRelease_order_fulfillments_lines_edges_node_orderLine | null; -} - -export interface OrderRelease_orderRelease_order_fulfillments_lines_edges { - __typename: "FulfillmentLineCountableEdge"; - node: OrderRelease_orderRelease_order_fulfillments_lines_edges_node; -} - -export interface OrderRelease_orderRelease_order_fulfillments_lines { - __typename: "FulfillmentLineCountableConnection"; - edges: OrderRelease_orderRelease_order_fulfillments_lines_edges[]; -} - -export interface OrderRelease_orderRelease_order_fulfillments { - __typename: "Fulfillment"; - id: string; - lines: OrderRelease_orderRelease_order_fulfillments_lines | null; - fulfillmentOrder: number; - status: FulfillmentStatus; - trackingNumber: string; -} - -export interface OrderRelease_orderRelease_order_lines_unitPrice_gross { - __typename: "Money"; - amount: number; - currency: string; -} - -export interface OrderRelease_orderRelease_order_lines_unitPrice_net { - __typename: "Money"; - amount: number; - currency: string; -} - -export interface OrderRelease_orderRelease_order_lines_unitPrice { - __typename: "TaxedMoney"; - gross: OrderRelease_orderRelease_order_lines_unitPrice_gross; - net: OrderRelease_orderRelease_order_lines_unitPrice_net; -} - -export interface OrderRelease_orderRelease_order_lines { - __typename: "OrderLine"; - id: string; - productName: string; - productSku: string; - quantity: number; - quantityFulfilled: number; - unitPrice: OrderRelease_orderRelease_order_lines_unitPrice | null; - thumbnailUrl: string | null; -} - -export interface OrderRelease_orderRelease_order_shippingAddress_country { - __typename: "CountryDisplay"; - code: string; - country: string; -} - -export interface OrderRelease_orderRelease_order_shippingAddress { - __typename: "Address"; - city: string; - cityArea: string; - companyName: string; - country: OrderRelease_orderRelease_order_shippingAddress_country; - countryArea: string; - firstName: string; - id: string; - lastName: string; - phone: string | null; - postalCode: string; - streetAddress1: string; - streetAddress2: string; -} - -export interface OrderRelease_orderRelease_order_shippingMethod { - __typename: "ShippingMethod"; - id: string; -} - -export interface OrderRelease_orderRelease_order_shippingPrice_gross { - __typename: "Money"; - amount: number; - currency: string; -} - -export interface OrderRelease_orderRelease_order_shippingPrice { - __typename: "TaxedMoney"; - gross: OrderRelease_orderRelease_order_shippingPrice_gross; -} - -export interface OrderRelease_orderRelease_order_subtotal_gross { - __typename: "Money"; - amount: number; - currency: string; -} - -export interface OrderRelease_orderRelease_order_subtotal { - __typename: "TaxedMoney"; - gross: OrderRelease_orderRelease_order_subtotal_gross; -} - -export interface OrderRelease_orderRelease_order_total_gross { - __typename: "Money"; - amount: number; - currency: string; -} - -export interface OrderRelease_orderRelease_order_total_tax { - __typename: "Money"; - amount: number; - currency: string; -} - -export interface OrderRelease_orderRelease_order_total { - __typename: "TaxedMoney"; - gross: OrderRelease_orderRelease_order_total_gross; - tax: OrderRelease_orderRelease_order_total_tax; -} - -export interface OrderRelease_orderRelease_order_totalAuthorized { - __typename: "Money"; - amount: number; - currency: string; -} - -export interface OrderRelease_orderRelease_order_totalCaptured { - __typename: "Money"; - amount: number; - currency: string; -} - -export interface OrderRelease_orderRelease_order_user { - __typename: "User"; - id: string; - email: string; -} - -export interface OrderRelease_orderRelease_order_availableShippingMethods_price { - __typename: "Money"; - amount: number; - currency: string; -} - -export interface OrderRelease_orderRelease_order_availableShippingMethods { - __typename: "ShippingMethod"; - id: string; - name: string; - price: OrderRelease_orderRelease_order_availableShippingMethods_price | null; -} - -export interface OrderRelease_orderRelease_order { - __typename: "Order"; - id: string; - billingAddress: OrderRelease_orderRelease_order_billingAddress | null; - created: any; - events: (OrderRelease_orderRelease_order_events | null)[] | null; - fulfillments: (OrderRelease_orderRelease_order_fulfillments | null)[]; - lines: (OrderRelease_orderRelease_order_lines | null)[]; - number: string | null; - paymentStatus: PaymentChargeStatusEnum | null; - shippingAddress: OrderRelease_orderRelease_order_shippingAddress | null; - shippingMethod: OrderRelease_orderRelease_order_shippingMethod | null; - shippingMethodName: string | null; - shippingPrice: OrderRelease_orderRelease_order_shippingPrice | null; - status: OrderStatus; - subtotal: OrderRelease_orderRelease_order_subtotal | null; - total: OrderRelease_orderRelease_order_total | null; - totalAuthorized: OrderRelease_orderRelease_order_totalAuthorized | null; - totalCaptured: OrderRelease_orderRelease_order_totalCaptured | null; - user: OrderRelease_orderRelease_order_user | null; - userEmail: string | null; - availableShippingMethods: (OrderRelease_orderRelease_order_availableShippingMethods | null)[] | null; -} - -export interface OrderRelease_orderRelease { - __typename: "OrderRelease"; - order: OrderRelease_orderRelease_order | null; -} - -export interface OrderRelease { - orderRelease: OrderRelease_orderRelease | null; -} - -export interface OrderReleaseVariables { - id: string; -} diff --git a/src/orders/types/OrderShippingMethods.ts b/src/orders/types/OrderShippingMethods.ts deleted file mode 100644 index 818adf916..000000000 --- a/src/orders/types/OrderShippingMethods.ts +++ /dev/null @@ -1,31 +0,0 @@ -/* tslint:disable */ -// This file was automatically generated and should not be edited. - -// ==================================================== -// GraphQL query operation: OrderShippingMethods -// ==================================================== - -export interface OrderShippingMethods_shippingZones_edges_node_shippingMethods { - __typename: "ShippingMethod"; - id: string; - name: string; -} - -export interface OrderShippingMethods_shippingZones_edges_node { - __typename: "ShippingZone"; - shippingMethods: (OrderShippingMethods_shippingZones_edges_node_shippingMethods | null)[] | null; -} - -export interface OrderShippingMethods_shippingZones_edges { - __typename: "ShippingZoneCountableEdge"; - node: OrderShippingMethods_shippingZones_edges_node; -} - -export interface OrderShippingMethods_shippingZones { - __typename: "ShippingZoneCountableConnection"; - edges: OrderShippingMethods_shippingZones_edges[]; -} - -export interface OrderShippingMethods { - shippingZones: OrderShippingMethods_shippingZones | null; -} diff --git a/src/orders/types/OrderUpdate.ts b/src/orders/types/OrderUpdate.ts index b199f05e6..f86226252 100644 --- a/src/orders/types/OrderUpdate.ts +++ b/src/orders/types/OrderUpdate.ts @@ -2,7 +2,7 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { OrderUpdateInput, OrderErrorCode } from "./../../types/globalTypes"; +import { OrderUpdateInput, OrderErrorCode, OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus, OrderAction, JobStatusEnum } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: OrderUpdate @@ -14,6 +14,18 @@ export interface OrderUpdate_orderUpdate_errors { field: string | null; } +export interface OrderUpdate_orderUpdate_order_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface OrderUpdate_orderUpdate_order_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface OrderUpdate_orderUpdate_order_billingAddress_country { __typename: "CountryDisplay"; code: string; @@ -36,6 +48,145 @@ export interface OrderUpdate_orderUpdate_order_billingAddress { streetAddress2: string; } +export interface OrderUpdate_orderUpdate_order_events_user { + __typename: "User"; + id: string; + email: string; +} + +export interface OrderUpdate_orderUpdate_order_events { + __typename: "OrderEvent"; + id: string; + amount: number | null; + date: any | null; + email: string | null; + emailType: OrderEventsEmailsEnum | null; + invoiceNumber: string | null; + message: string | null; + quantity: number | null; + type: OrderEventsEnum | null; + user: OrderUpdate_orderUpdate_order_events_user | null; +} + +export interface OrderUpdate_orderUpdate_order_fulfillments_lines_orderLine_variant_product { + __typename: "Product"; + isAvailableForPurchase: boolean | null; + isPublished: boolean; +} + +export interface OrderUpdate_orderUpdate_order_fulfillments_lines_orderLine_variant { + __typename: "ProductVariant"; + product: OrderUpdate_orderUpdate_order_fulfillments_lines_orderLine_variant_product; + quantityAvailable: number; +} + +export interface OrderUpdate_orderUpdate_order_fulfillments_lines_orderLine_unitPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderUpdate_orderUpdate_order_fulfillments_lines_orderLine_unitPrice_net { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderUpdate_orderUpdate_order_fulfillments_lines_orderLine_unitPrice { + __typename: "TaxedMoney"; + gross: OrderUpdate_orderUpdate_order_fulfillments_lines_orderLine_unitPrice_gross; + net: OrderUpdate_orderUpdate_order_fulfillments_lines_orderLine_unitPrice_net; +} + +export interface OrderUpdate_orderUpdate_order_fulfillments_lines_orderLine_thumbnail { + __typename: "Image"; + url: string; +} + +export interface OrderUpdate_orderUpdate_order_fulfillments_lines_orderLine { + __typename: "OrderLine"; + id: string; + isShippingRequired: boolean; + variant: OrderUpdate_orderUpdate_order_fulfillments_lines_orderLine_variant | null; + productName: string; + productSku: string; + quantity: number; + quantityFulfilled: number; + unitPrice: OrderUpdate_orderUpdate_order_fulfillments_lines_orderLine_unitPrice | null; + thumbnail: OrderUpdate_orderUpdate_order_fulfillments_lines_orderLine_thumbnail | null; +} + +export interface OrderUpdate_orderUpdate_order_fulfillments_lines { + __typename: "FulfillmentLine"; + id: string; + quantity: number; + orderLine: OrderUpdate_orderUpdate_order_fulfillments_lines_orderLine | null; +} + +export interface OrderUpdate_orderUpdate_order_fulfillments_warehouse { + __typename: "Warehouse"; + id: string; + name: string; +} + +export interface OrderUpdate_orderUpdate_order_fulfillments { + __typename: "Fulfillment"; + id: string; + lines: (OrderUpdate_orderUpdate_order_fulfillments_lines | null)[] | null; + fulfillmentOrder: number; + status: FulfillmentStatus; + trackingNumber: string; + warehouse: OrderUpdate_orderUpdate_order_fulfillments_warehouse | null; +} + +export interface OrderUpdate_orderUpdate_order_lines_variant_product { + __typename: "Product"; + isAvailableForPurchase: boolean | null; + isPublished: boolean; +} + +export interface OrderUpdate_orderUpdate_order_lines_variant { + __typename: "ProductVariant"; + product: OrderUpdate_orderUpdate_order_lines_variant_product; + quantityAvailable: number; +} + +export interface OrderUpdate_orderUpdate_order_lines_unitPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderUpdate_orderUpdate_order_lines_unitPrice_net { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderUpdate_orderUpdate_order_lines_unitPrice { + __typename: "TaxedMoney"; + gross: OrderUpdate_orderUpdate_order_lines_unitPrice_gross; + net: OrderUpdate_orderUpdate_order_lines_unitPrice_net; +} + +export interface OrderUpdate_orderUpdate_order_lines_thumbnail { + __typename: "Image"; + url: string; +} + +export interface OrderUpdate_orderUpdate_order_lines { + __typename: "OrderLine"; + id: string; + isShippingRequired: boolean; + variant: OrderUpdate_orderUpdate_order_lines_variant | null; + productName: string; + productSku: string; + quantity: number; + quantityFulfilled: number; + unitPrice: OrderUpdate_orderUpdate_order_lines_unitPrice | null; + thumbnail: OrderUpdate_orderUpdate_order_lines_thumbnail | null; +} + export interface OrderUpdate_orderUpdate_order_shippingAddress_country { __typename: "CountryDisplay"; code: string; @@ -58,12 +209,126 @@ export interface OrderUpdate_orderUpdate_order_shippingAddress { streetAddress2: string; } +export interface OrderUpdate_orderUpdate_order_shippingMethod { + __typename: "ShippingMethod"; + id: string; +} + +export interface OrderUpdate_orderUpdate_order_shippingPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderUpdate_orderUpdate_order_shippingPrice { + __typename: "TaxedMoney"; + gross: OrderUpdate_orderUpdate_order_shippingPrice_gross; +} + +export interface OrderUpdate_orderUpdate_order_subtotal_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderUpdate_orderUpdate_order_subtotal { + __typename: "TaxedMoney"; + gross: OrderUpdate_orderUpdate_order_subtotal_gross; +} + +export interface OrderUpdate_orderUpdate_order_total_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderUpdate_orderUpdate_order_total_tax { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderUpdate_orderUpdate_order_total { + __typename: "TaxedMoney"; + gross: OrderUpdate_orderUpdate_order_total_gross; + tax: OrderUpdate_orderUpdate_order_total_tax; +} + +export interface OrderUpdate_orderUpdate_order_totalAuthorized { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderUpdate_orderUpdate_order_totalCaptured { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderUpdate_orderUpdate_order_user { + __typename: "User"; + id: string; + email: string; +} + +export interface OrderUpdate_orderUpdate_order_availableShippingMethods_price { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderUpdate_orderUpdate_order_availableShippingMethods { + __typename: "ShippingMethod"; + id: string; + name: string; + price: OrderUpdate_orderUpdate_order_availableShippingMethods_price | null; +} + +export interface OrderUpdate_orderUpdate_order_discount { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderUpdate_orderUpdate_order_invoices { + __typename: "Invoice"; + id: string; + number: string | null; + createdAt: any; + url: string | null; + status: JobStatusEnum; +} + export interface OrderUpdate_orderUpdate_order { __typename: "Order"; id: string; - userEmail: string | null; + metadata: (OrderUpdate_orderUpdate_order_metadata | null)[]; + privateMetadata: (OrderUpdate_orderUpdate_order_privateMetadata | null)[]; billingAddress: OrderUpdate_orderUpdate_order_billingAddress | null; + canFinalize: boolean; + created: any; + customerNote: string; + events: (OrderUpdate_orderUpdate_order_events | null)[] | null; + fulfillments: (OrderUpdate_orderUpdate_order_fulfillments | null)[]; + lines: (OrderUpdate_orderUpdate_order_lines | null)[]; + number: string | null; + paymentStatus: PaymentChargeStatusEnum | null; shippingAddress: OrderUpdate_orderUpdate_order_shippingAddress | null; + shippingMethod: OrderUpdate_orderUpdate_order_shippingMethod | null; + shippingMethodName: string | null; + shippingPrice: OrderUpdate_orderUpdate_order_shippingPrice | null; + status: OrderStatus; + subtotal: OrderUpdate_orderUpdate_order_subtotal | null; + total: OrderUpdate_orderUpdate_order_total | null; + actions: (OrderAction | null)[]; + totalAuthorized: OrderUpdate_orderUpdate_order_totalAuthorized | null; + totalCaptured: OrderUpdate_orderUpdate_order_totalCaptured | null; + user: OrderUpdate_orderUpdate_order_user | null; + userEmail: string | null; + availableShippingMethods: (OrderUpdate_orderUpdate_order_availableShippingMethods | null)[] | null; + discount: OrderUpdate_orderUpdate_order_discount | null; + invoices: (OrderUpdate_orderUpdate_order_invoices | null)[] | null; } export interface OrderUpdate_orderUpdate { diff --git a/src/orders/types/OrderVoid.ts b/src/orders/types/OrderVoid.ts index 880598c78..ce3feb82f 100644 --- a/src/orders/types/OrderVoid.ts +++ b/src/orders/types/OrderVoid.ts @@ -2,7 +2,7 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { OrderErrorCode, OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus, OrderAction } from "./../../types/globalTypes"; +import { OrderErrorCode, OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus, OrderAction, JobStatusEnum } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: OrderVoid @@ -14,6 +14,18 @@ export interface OrderVoid_orderVoid_errors { field: string | null; } +export interface OrderVoid_orderVoid_order_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface OrderVoid_orderVoid_order_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface OrderVoid_orderVoid_order_billingAddress_country { __typename: "CountryDisplay"; code: string; @@ -49,12 +61,25 @@ export interface OrderVoid_orderVoid_order_events { date: any | null; email: string | null; emailType: OrderEventsEmailsEnum | null; + invoiceNumber: string | null; message: string | null; quantity: number | null; type: OrderEventsEnum | null; user: OrderVoid_orderVoid_order_events_user | null; } +export interface OrderVoid_orderVoid_order_fulfillments_lines_orderLine_variant_product { + __typename: "Product"; + isAvailableForPurchase: boolean | null; + isPublished: boolean; +} + +export interface OrderVoid_orderVoid_order_fulfillments_lines_orderLine_variant { + __typename: "ProductVariant"; + product: OrderVoid_orderVoid_order_fulfillments_lines_orderLine_variant_product; + quantityAvailable: number; +} + export interface OrderVoid_orderVoid_order_fulfillments_lines_orderLine_unitPrice_gross { __typename: "Money"; amount: number; @@ -82,6 +107,7 @@ export interface OrderVoid_orderVoid_order_fulfillments_lines_orderLine { __typename: "OrderLine"; id: string; isShippingRequired: boolean; + variant: OrderVoid_orderVoid_order_fulfillments_lines_orderLine_variant | null; productName: string; productSku: string; quantity: number; @@ -113,6 +139,18 @@ export interface OrderVoid_orderVoid_order_fulfillments { warehouse: OrderVoid_orderVoid_order_fulfillments_warehouse | null; } +export interface OrderVoid_orderVoid_order_lines_variant_product { + __typename: "Product"; + isAvailableForPurchase: boolean | null; + isPublished: boolean; +} + +export interface OrderVoid_orderVoid_order_lines_variant { + __typename: "ProductVariant"; + product: OrderVoid_orderVoid_order_lines_variant_product; + quantityAvailable: number; +} + export interface OrderVoid_orderVoid_order_lines_unitPrice_gross { __typename: "Money"; amount: number; @@ -140,6 +178,7 @@ export interface OrderVoid_orderVoid_order_lines { __typename: "OrderLine"; id: string; isShippingRequired: boolean; + variant: OrderVoid_orderVoid_order_lines_variant | null; productName: string; productSku: string; quantity: number; @@ -246,9 +285,26 @@ export interface OrderVoid_orderVoid_order_availableShippingMethods { price: OrderVoid_orderVoid_order_availableShippingMethods_price | null; } +export interface OrderVoid_orderVoid_order_discount { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderVoid_orderVoid_order_invoices { + __typename: "Invoice"; + id: string; + number: string | null; + createdAt: any; + url: string | null; + status: JobStatusEnum; +} + export interface OrderVoid_orderVoid_order { __typename: "Order"; id: string; + metadata: (OrderVoid_orderVoid_order_metadata | null)[]; + privateMetadata: (OrderVoid_orderVoid_order_privateMetadata | null)[]; billingAddress: OrderVoid_orderVoid_order_billingAddress | null; canFinalize: boolean; created: any; @@ -271,6 +327,8 @@ export interface OrderVoid_orderVoid_order { user: OrderVoid_orderVoid_order_user | null; userEmail: string | null; availableShippingMethods: (OrderVoid_orderVoid_order_availableShippingMethods | null)[] | null; + discount: OrderVoid_orderVoid_order_discount | null; + invoices: (OrderVoid_orderVoid_order_invoices | null)[] | null; } export interface OrderVoid_orderVoid { diff --git a/src/orders/urls.ts b/src/orders/urls.ts index d500f7f12..0efa7ffde 100644 --- a/src/orders/urls.ts +++ b/src/orders/urls.ts @@ -9,8 +9,8 @@ import { FiltersWithMultipleValues, Pagination, SingleAction, - TabActionDialog, - Sort + Sort, + TabActionDialog } from "../types"; const orderSectionUrl = "/orders"; @@ -99,7 +99,8 @@ export type OrderUrlDialog = | "finalize" | "mark-paid" | "refund" - | "void"; + | "void" + | "invoice-send"; export type OrderUrlQueryParams = Dialog & SingleAction; export const orderUrl = (id: string, params?: OrderUrlQueryParams) => orderPath(encodeURIComponent(id)) + "?" + stringifyQs(params); diff --git a/src/orders/views/OrderDetails/OrderDetailsMessages.tsx b/src/orders/views/OrderDetails/OrderDetailsMessages.tsx index a2162928f..fad2cd6ef 100644 --- a/src/orders/views/OrderDetails/OrderDetailsMessages.tsx +++ b/src/orders/views/OrderDetails/OrderDetailsMessages.tsx @@ -1,9 +1,12 @@ -import React from "react"; -import { useIntl } from "react-intl"; - +import messages from "@saleor/containers/BackgroundTasks/messages"; import useNavigator from "@saleor/hooks/useNavigator"; import useNotifier from "@saleor/hooks/useNotifier"; import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; +import React from "react"; +import { useIntl } from "react-intl"; + +import { InvoiceEmailSend } from "../../types/InvoiceEmailSend"; +import { InvoiceRequest } from "../../types/InvoiceRequest"; import { OrderAddNote } from "../../types/OrderAddNote"; import { OrderCancel } from "../../types/OrderCancel"; import { OrderCapture } from "../../types/OrderCapture"; @@ -42,6 +45,9 @@ interface OrderDetailsMessages { handlePaymentRefund: (data: OrderRefund) => void; handleShippingMethodUpdate: (data: OrderShippingMethodUpdate) => void; handleUpdate: (data: OrderUpdate) => void; + handleInvoiceGeneratePending: (data: InvoiceRequest) => void; + handleInvoiceGenerateFinished: (data: InvoiceRequest) => void; + handleInvoiceSend: (data: InvoiceEmailSend) => void; }) => React.ReactElement; id: string; params: OrderUrlQueryParams; @@ -66,6 +72,7 @@ export const OrderDetailsMessages: React.FC = ({ const errs = data.orderCapture?.errors; if (errs.length === 0) { pushMessage({ + status: "success", text: intl.formatMessage({ defaultMessage: "Payment successfully captured" }) @@ -77,6 +84,7 @@ export const OrderDetailsMessages: React.FC = ({ const errs = data.orderRefund?.errors; if (errs.length === 0) { pushMessage({ + status: "success", text: intl.formatMessage({ defaultMessage: "Payment successfully refunded" }) @@ -88,6 +96,7 @@ export const OrderDetailsMessages: React.FC = ({ const errs = data.orderMarkAsPaid?.errors; if (errs.length === 0) { pushMessage({ + status: "success", text: intl.formatMessage({ defaultMessage: "Order marked as paid" }) @@ -99,6 +108,7 @@ export const OrderDetailsMessages: React.FC = ({ const errs = data.orderCancel?.errors; if (errs.length === 0) { pushMessage({ + status: "success", text: intl.formatMessage({ defaultMessage: "Order successfully cancelled" }) @@ -110,6 +120,7 @@ export const OrderDetailsMessages: React.FC = ({ const errs = data.draftOrderDelete?.errors; if (errs.length === 0) { pushMessage({ + status: "success", text: intl.formatMessage({ defaultMessage: "Order successfully cancelled" }) @@ -121,6 +132,7 @@ export const OrderDetailsMessages: React.FC = ({ const errs = data.orderVoid?.errors; if (errs.length === 0) { pushMessage({ + status: "success", text: intl.formatMessage({ defaultMessage: "Order payment successfully voided" }) @@ -132,6 +144,7 @@ export const OrderDetailsMessages: React.FC = ({ const errs = data.orderAddNote?.errors; if (errs.length === 0) { pushMessage({ + status: "success", text: intl.formatMessage({ defaultMessage: "Note successfully added" }) @@ -142,16 +155,19 @@ export const OrderDetailsMessages: React.FC = ({ const errs = data.orderUpdate?.errors; if (errs.length === 0) { pushMessage({ + status: "success", text: intl.formatMessage({ defaultMessage: "Order successfully updated" }) }); + closeModal(); } }; const handleDraftUpdate = (data: OrderDraftUpdate) => { const errs = data.draftOrderUpdate?.errors; if (errs.length === 0) { pushMessage({ + status: "success", text: intl.formatMessage({ defaultMessage: "Order successfully updated" }) @@ -162,6 +178,7 @@ export const OrderDetailsMessages: React.FC = ({ const errs = data.orderUpdateShipping?.errors; if (errs.length === 0) { pushMessage({ + status: "success", text: intl.formatMessage({ defaultMessage: "Shipping method successfully updated" }) @@ -173,6 +190,7 @@ export const OrderDetailsMessages: React.FC = ({ const errs = data.draftOrderLineDelete?.errors; if (errs.length === 0) { pushMessage({ + status: "success", text: intl.formatMessage({ defaultMessage: "Order line deleted" }) @@ -183,6 +201,7 @@ export const OrderDetailsMessages: React.FC = ({ const errs = data.draftOrderLinesCreate?.errors; if (errs.length === 0) { pushMessage({ + status: "success", text: intl.formatMessage({ defaultMessage: "Order line added" }) @@ -194,6 +213,7 @@ export const OrderDetailsMessages: React.FC = ({ const errs = data.draftOrderLineUpdate?.errors; if (errs.length === 0) { pushMessage({ + status: "success", text: intl.formatMessage({ defaultMessage: "Order line updated" }) @@ -204,6 +224,7 @@ export const OrderDetailsMessages: React.FC = ({ const errs = data.orderFulfillmentCancel?.errors; if (errs.length === 0) { pushMessage({ + status: "success", text: intl.formatMessage({ defaultMessage: "Fulfillment successfully cancelled" }) @@ -217,6 +238,7 @@ export const OrderDetailsMessages: React.FC = ({ const errs = data.orderFulfillmentUpdateTracking?.errors; if (errs.length === 0) { pushMessage({ + status: "success", text: intl.formatMessage({ defaultMessage: "Fulfillment successfully updated" }) @@ -228,6 +250,7 @@ export const OrderDetailsMessages: React.FC = ({ const errs = data.draftOrderComplete?.errors; if (errs.length === 0) { pushMessage({ + status: "success", text: intl.formatMessage({ defaultMessage: "Draft order successfully finalized" }) @@ -235,11 +258,51 @@ export const OrderDetailsMessages: React.FC = ({ closeModal(); } }; + const handleInvoiceGeneratePending = (data: InvoiceRequest) => { + const errs = data.invoiceRequest?.errors; + if (errs.length === 0) { + pushMessage({ + text: intl.formatMessage({ + defaultMessage: + "We’re generating the invoice you requested. Please wait a couple of moments" + }), + title: intl.formatMessage({ + defaultMessage: "Invoice is Generating" + }) + }); + closeModal(); + } + }; + const handleInvoiceGenerateFinished = (data: InvoiceRequest) => { + const errs = data.invoiceRequest?.errors; + if (errs.length === 0) { + pushMessage({ + status: "success", + text: intl.formatMessage(messages.invoiceGenerateFinishedText), + title: intl.formatMessage(messages.invoiceGenerateFinishedTitle) + }); + closeModal(); + } + }; + const handleInvoiceSend = (data: InvoiceEmailSend) => { + const errs = data.invoiceSendEmail?.errors; + if (errs.length === 0) { + pushMessage({ + text: intl.formatMessage({ + defaultMessage: "Invoice email sent" + }) + }); + closeModal(); + } + }; return children({ handleDraftCancel, handleDraftFinalize, handleDraftUpdate, + handleInvoiceGenerateFinished, + handleInvoiceGeneratePending, + handleInvoiceSend, handleNoteAdd, handleOrderCancel, handleOrderFulfillmentCancel, diff --git a/src/orders/views/OrderDetails/index.tsx b/src/orders/views/OrderDetails/index.tsx index 50c369b6c..bdc0e1363 100644 --- a/src/orders/views/OrderDetails/index.tsx +++ b/src/orders/views/OrderDetails/index.tsx @@ -1,23 +1,40 @@ -import { useIntl } from "react-intl"; -import React from "react"; - +import { MetadataFormData } from "@saleor/components/Metadata"; +import NotFoundPage from "@saleor/components/NotFoundPage"; import { WindowTitle } from "@saleor/components/WindowTitle"; import { DEFAULT_INITIAL_SEARCH_DATA } from "@saleor/config"; +import { Task } from "@saleor/containers/BackgroundTasks/types"; +import useBackgroundTask from "@saleor/hooks/useBackgroundTask"; import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; import useUser from "@saleor/hooks/useUser"; +import { commonMessages } from "@saleor/intl"; +import OrderCannotCancelOrderDialog from "@saleor/orders/components/OrderCannotCancelOrderDialog"; +import OrderInvoiceEmailSendDialog from "@saleor/orders/components/OrderInvoiceEmailSendDialog"; +import { InvoiceRequest } from "@saleor/orders/types/InvoiceRequest"; import useCustomerSearch from "@saleor/searches/useCustomerSearch"; import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; -import NotFoundPage from "@saleor/components/NotFoundPage"; +import createMetadataUpdateHandler from "@saleor/utils/handlers/metadataUpdateHandler"; +import { + useMetadataUpdate, + usePrivateMetadataUpdate +} from "@saleor/utils/metadata/updateMetadata"; import { useWarehouseList } from "@saleor/warehouses/queries"; -import OrderCannotCancelOrderDialog from "@saleor/orders/components/OrderCannotCancelOrderDialog"; +import React from "react"; +import { useIntl } from "react-intl"; + import { customerUrl } from "../../../customers/urls"; import { + getMutationState, + getStringOrPlaceholder, maybe, - transformAddressToForm, - getStringOrPlaceholder + transformAddressToForm } from "../../../misc"; import { productUrl } from "../../../products/urls"; -import { OrderStatus, FulfillmentStatus } from "../../../types/globalTypes"; +import { + FulfillmentStatus, + JobStatusEnum, + OrderStatus +} from "../../../types/globalTypes"; import OrderAddressEditDialog from "../../components/OrderAddressEditDialog"; import OrderCancelDialog from "../../components/OrderCancelDialog"; import OrderDetailsPage from "../../components/OrderDetailsPage"; @@ -37,11 +54,11 @@ import OrderOperations from "../../containers/OrderOperations"; import { TypedOrderDetailsQuery, useOrderVariantSearch } from "../../queries"; import { OrderDetails_order } from "../../types/OrderDetails"; import { + orderFulfillUrl, orderListUrl, orderUrl, - OrderUrlQueryParams, OrderUrlDialog, - orderFulfillUrl + OrderUrlQueryParams } from "../../urls"; import { OrderDetailsMessages } from "./OrderDetailsMessages"; @@ -103,7 +120,14 @@ export const OrderDetails: React.FC = ({ id, params }) => { first: 30 } }); + const { queue } = useBackgroundTask(); const intl = useIntl(); + const [updateMetadata, updateMetadataOpts] = useMetadataUpdate({}); + const [ + updatePrivateMetadata, + updatePrivateMetadataOpts + ] = usePrivateMetadataUpdate({}); + const notify = useNotifier(); const [openModal, closeModal] = createDialogActionHandlers< OrderUrlDialog, @@ -121,6 +145,23 @@ export const OrderDetails: React.FC = ({ id, params }) => { return ; } + const handleSubmit = async (data: MetadataFormData) => { + const update = createMetadataUpdateHandler( + order, + () => Promise.resolve([]), + variables => updateMetadata({ variables }), + variables => updatePrivateMetadata({ variables }) + ); + const result = await update(data); + + if (result.length === 0) { + notify({ + status: "success", + text: intl.formatMessage(commonMessages.savedChanges) + }); + } + }; + return ( {orderMessages => ( @@ -148,6 +189,22 @@ export const OrderDetails: React.FC = ({ id, params }) => { onDraftFinalize={orderMessages.handleDraftFinalize} onDraftCancel={orderMessages.handleDraftCancel} onOrderMarkAsPaid={orderMessages.handleOrderMarkAsPaid} + onInvoiceRequest={(data: InvoiceRequest) => { + if ( + data.invoiceRequest.invoice.status === JobStatusEnum.SUCCESS + ) { + orderMessages.handleInvoiceGenerateFinished(data); + } else { + orderMessages.handleInvoiceGeneratePending(data); + queue(Task.INVOICE_GENERATE, { + generateInvoice: { + invoiceId: data.invoiceRequest.invoice.id, + orderId: id + } + }); + } + }} + onInvoiceSend={orderMessages.handleInvoiceSend} > {({ orderAddNote, @@ -165,7 +222,9 @@ export const OrderDetails: React.FC = ({ id, params }) => { orderFulfillmentUpdateTracking, orderDraftCancel, orderDraftFinalize, - orderPaymentMarkAsPaid + orderPaymentMarkAsPaid, + orderInvoiceRequest, + orderInvoiceSend }) => ( <> {order?.status !== OrderStatus.DRAFT ? ( @@ -184,6 +243,10 @@ export const OrderDetails: React.FC = ({ id, params }) => { )} /> orderAddNote.mutate({ input: variables, @@ -192,6 +255,22 @@ export const OrderDetails: React.FC = ({ id, params }) => { } onBack={handleBack} order={order} + saveButtonBarState={getMutationState( + updateMetadataOpts.called || + updatePrivateMetadataOpts.called, + updateMetadataOpts.loading || + updatePrivateMetadataOpts.loading, + [ + ...(updateMetadataOpts.data?.deleteMetadata + .errors || []), + ...(updateMetadataOpts.data?.updateMetadata + .errors || []), + ...(updatePrivateMetadataOpts.data + ?.deletePrivateMetadata.errors || []), + ...(updatePrivateMetadataOpts.data + ?.updatePrivateMetadata.errors || []) + ] + )} shippingMethods={maybe( () => data.order.availableShippingMethods, [] @@ -229,6 +308,22 @@ export const OrderDetails: React.FC = ({ id, params }) => { onProfileView={() => navigate(customerUrl(order.user.id)) } + onInvoiceClick={id => + window.open( + order.invoices.find(invoice => invoice.id === id) + ?.url, + "_blank" + ) + } + onInvoiceGenerate={() => + orderInvoiceRequest.mutate({ + orderId: id + }) + } + onInvoiceSend={id => + openModal("invoice-send", { id }) + } + onSubmit={handleSubmit} /> = ({ id, params }) => { } onClose={closeModal} /> + invoice.id === params.id + )} + onClose={closeModal} + onSend={() => + orderInvoiceSend.mutate({ id: params.id }) + } + /> ) : ( <> diff --git a/src/orders/views/OrderDraftList/OrderDraftList.tsx b/src/orders/views/OrderDraftList/OrderDraftList.tsx index 1b184d5b8..a44b38f25 100644 --- a/src/orders/views/OrderDraftList/OrderDraftList.tsx +++ b/src/orders/views/OrderDraftList/OrderDraftList.tsx @@ -1,9 +1,6 @@ import DialogContentText from "@material-ui/core/DialogContentText"; import IconButton from "@material-ui/core/IconButton"; import DeleteIcon from "@material-ui/icons/Delete"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import ActionDialog from "@saleor/components/ActionDialog"; import DeleteFilterTabDialog from "@saleor/components/DeleteFilterTabDialog"; import SaveFilterTabDialog, { @@ -16,13 +13,16 @@ import useNotifier from "@saleor/hooks/useNotifier"; import usePaginator, { createPaginationState } from "@saleor/hooks/usePaginator"; +import useShop from "@saleor/hooks/useShop"; import { maybe } from "@saleor/misc"; import { ListViews } from "@saleor/types"; +import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; +import createFilterHandlers from "@saleor/utils/handlers/filterHandlers"; import createSortHandler from "@saleor/utils/handlers/sortHandler"; import { getSortParams } from "@saleor/utils/sort"; -import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; -import useShop from "@saleor/hooks/useShop"; -import createFilterHandlers from "@saleor/utils/handlers/filterHandlers"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import OrderDraftListPage from "../../components/OrderDraftListPage"; import { TypedOrderDraftBulkCancelMutation, @@ -33,19 +33,19 @@ import { OrderDraftBulkCancel } from "../../types/OrderDraftBulkCancel"; import { OrderDraftCreate } from "../../types/OrderDraftCreate"; import { orderDraftListUrl, + OrderDraftListUrlDialog, OrderDraftListUrlQueryParams, - orderUrl, - OrderDraftListUrlDialog + orderUrl } from "../../urls"; import { areFiltersApplied, deleteFilterTab, getActiveFilters, + getFilterOpts, + getFilterQueryParam, getFilterTabs, getFilterVariables, - saveFilterTab, - getFilterQueryParam, - getFilterOpts + saveFilterTab } from "./filters"; import { getSortQueryVariables } from "./sort"; @@ -68,6 +68,7 @@ export const OrderDraftList: React.FC = ({ params }) => { const handleCreateOrderCreateSuccess = (data: OrderDraftCreate) => { notify({ + status: "success", text: intl.formatMessage({ defaultMessage: "Order draft successfully created" }) @@ -149,6 +150,7 @@ export const OrderDraftList: React.FC = ({ params }) => { const handleOrderDraftBulkCancel = (data: OrderDraftBulkCancel) => { if (data.draftOrderBulkDelete.errors.length === 0) { notify({ + status: "success", text: intl.formatMessage({ defaultMessage: "Deleted draft orders" }) diff --git a/src/orders/views/OrderDraftList/filters.test.ts b/src/orders/views/OrderDraftList/filters.test.ts index bc0bd6e4c..3e84f3ab2 100644 --- a/src/orders/views/OrderDraftList/filters.test.ts +++ b/src/orders/views/OrderDraftList/filters.test.ts @@ -1,13 +1,13 @@ -import { createIntl } from "react-intl"; -import { stringify as stringifyQs } from "qs"; - -import { OrderDraftListUrlFilters } from "@saleor/orders/urls"; -import { createFilterStructure } from "@saleor/orders/components/OrderDraftListPage"; -import { getFilterQueryParams } from "@saleor/utils/filters"; import { date } from "@saleor/fixtures"; +import { createFilterStructure } from "@saleor/orders/components/OrderDraftListPage"; +import { OrderDraftListUrlFilters } from "@saleor/orders/urls"; +import { getFilterQueryParams } from "@saleor/utils/filters"; import { getExistingKeys, setFilterOptsStatus } from "@test/filters"; import { config } from "@test/intl"; -import { getFilterVariables, getFilterQueryParam } from "./filters"; +import { stringify as stringifyQs } from "qs"; +import { createIntl } from "react-intl"; + +import { getFilterQueryParam, getFilterVariables } from "./filters"; describe("Filtering query params", () => { it("should be empty object if no params given", () => { diff --git a/src/orders/views/OrderDraftList/filters.ts b/src/orders/views/OrderDraftList/filters.ts index a6814a4e0..6f82a85c3 100644 --- a/src/orders/views/OrderDraftList/filters.ts +++ b/src/orders/views/OrderDraftList/filters.ts @@ -1,15 +1,11 @@ -import { OrderDraftFilterInput } from "@saleor/types/globalTypes"; -import { maybe } from "@saleor/misc"; import { IFilterElement } from "@saleor/components/Filter"; +import { maybe } from "@saleor/misc"; import { OrderDraftFilterKeys, OrderDraftListFilterOpts } from "@saleor/orders/components/OrderDraftListPage"; -import { - OrderDraftListUrlFilters, - OrderDraftListUrlFiltersEnum, - OrderDraftListUrlQueryParams -} from "../../urls"; +import { OrderDraftFilterInput } from "@saleor/types/globalTypes"; + import { createFilterTabUtils, createFilterUtils, @@ -17,6 +13,11 @@ import { getMinMaxQueryParam, getSingleValueQueryParam } from "../../../utils/filters"; +import { + OrderDraftListUrlFilters, + OrderDraftListUrlFiltersEnum, + OrderDraftListUrlQueryParams +} from "../../urls"; export const ORDER_DRAFT_FILTERS_KEY = "orderDraftFilters"; diff --git a/src/orders/views/OrderFulfill/OrderFulfill.tsx b/src/orders/views/OrderFulfill/OrderFulfill.tsx index 39dd898d3..6306d048a 100644 --- a/src/orders/views/OrderFulfill/OrderFulfill.tsx +++ b/src/orders/views/OrderFulfill/OrderFulfill.tsx @@ -1,14 +1,13 @@ -import { useIntl } from "react-intl"; -import React from "react"; - -import { useOrderFulfillData } from "@saleor/orders/queries"; -import OrderFulfillPage from "@saleor/orders/components/OrderFulfillPage"; +import { WindowTitle } from "@saleor/components/WindowTitle"; import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import OrderFulfillPage from "@saleor/orders/components/OrderFulfillPage"; +import { useOrderFulfill } from "@saleor/orders/mutations"; +import { useOrderFulfillData } from "@saleor/orders/queries"; import { orderUrl } from "@saleor/orders/urls"; import { useWarehouseList } from "@saleor/warehouses/queries"; -import { WindowTitle } from "@saleor/components/WindowTitle"; -import { useOrderFulfill } from "@saleor/orders/mutations"; -import useNotifier from "@saleor/hooks/useNotifier"; +import React from "react"; +import { useIntl } from "react-intl"; export interface OrderFulfillProps { orderId: string; @@ -35,6 +34,7 @@ const OrderFulfill: React.FC = ({ orderId }) => { if (data.orderFulfill.errors.length === 0) { navigate(orderUrl(orderId), true); notify({ + status: "success", text: intl.formatMessage({ defaultMessage: "Fulfilled Items", description: "order fulfilled success message" diff --git a/src/orders/views/OrderList/OrderList.tsx b/src/orders/views/OrderList/OrderList.tsx index d08881d2b..04227b950 100644 --- a/src/orders/views/OrderList/OrderList.tsx +++ b/src/orders/views/OrderList/OrderList.tsx @@ -1,6 +1,3 @@ -import React from "react"; -import { useIntl } from "react-intl"; - import DeleteFilterTabDialog from "@saleor/components/DeleteFilterTabDialog"; import SaveFilterTabDialog, { SaveFilterTabDialogFormData @@ -12,31 +9,34 @@ import usePaginator, { createPaginationState } from "@saleor/hooks/usePaginator"; import useShop from "@saleor/hooks/useShop"; -import { maybe, getStringOrPlaceholder } from "@saleor/misc"; +import { getStringOrPlaceholder, maybe } from "@saleor/misc"; import { ListViews } from "@saleor/types"; -import createSortHandler from "@saleor/utils/handlers/sortHandler"; -import { getSortParams } from "@saleor/utils/sort"; import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; import createFilterHandlers from "@saleor/utils/handlers/filterHandlers"; +import createSortHandler from "@saleor/utils/handlers/sortHandler"; +import { getSortParams } from "@saleor/utils/sort"; +import React from "react"; +import { useIntl } from "react-intl"; + import OrderListPage from "../../components/OrderListPage/OrderListPage"; import { useOrderDraftCreateMutation } from "../../mutations"; import { useOrderListQuery } from "../../queries"; import { OrderDraftCreate } from "../../types/OrderDraftCreate"; import { orderListUrl, + OrderListUrlDialog, OrderListUrlQueryParams, - orderUrl, - OrderListUrlDialog + orderUrl } from "../../urls"; import { areFiltersApplied, deleteFilterTab, getActiveFilters, - getFilterTabs, getFilterOpts, + getFilterQueryParam, + getFilterTabs, getFilterVariables, - saveFilterTab, - getFilterQueryParam + saveFilterTab } from "./filters"; import { getSortQueryVariables } from "./sort"; @@ -56,6 +56,7 @@ export const OrderList: React.FC = ({ params }) => { const handleCreateOrderCreateSuccess = (data: OrderDraftCreate) => { notify({ + status: "success", text: intl.formatMessage({ defaultMessage: "Order draft successfully created" }) diff --git a/src/orders/views/OrderList/filters.test.ts b/src/orders/views/OrderList/filters.test.ts index b737c70b0..ac0d5f386 100644 --- a/src/orders/views/OrderList/filters.test.ts +++ b/src/orders/views/OrderList/filters.test.ts @@ -1,14 +1,14 @@ -import { createIntl } from "react-intl"; -import { stringify as stringifyQs } from "qs"; - -import { OrderListUrlFilters } from "@saleor/orders/urls"; -import { createFilterStructure } from "@saleor/orders/components/OrderListPage"; -import { getFilterQueryParams } from "@saleor/utils/filters"; import { date } from "@saleor/fixtures"; +import { createFilterStructure } from "@saleor/orders/components/OrderListPage"; +import { OrderListUrlFilters } from "@saleor/orders/urls"; +import { OrderStatusFilter } from "@saleor/types/globalTypes"; +import { getFilterQueryParams } from "@saleor/utils/filters"; import { getExistingKeys, setFilterOptsStatus } from "@test/filters"; import { config } from "@test/intl"; -import { OrderStatusFilter } from "@saleor/types/globalTypes"; -import { getFilterVariables, getFilterQueryParam } from "./filters"; +import { stringify as stringifyQs } from "qs"; +import { createIntl } from "react-intl"; + +import { getFilterQueryParam, getFilterVariables } from "./filters"; describe("Filtering query params", () => { it("should be empty object if no params given", () => { diff --git a/src/orders/views/OrderList/filters.ts b/src/orders/views/OrderList/filters.ts index e84423630..f24b39494 100644 --- a/src/orders/views/OrderList/filters.ts +++ b/src/orders/views/OrderList/filters.ts @@ -1,8 +1,9 @@ -import { findInEnum, maybe, findValueInEnum } from "@saleor/misc"; +import { findInEnum, findValueInEnum, maybe } from "@saleor/misc"; import { - OrderListFilterOpts, - OrderFilterKeys + OrderFilterKeys, + OrderListFilterOpts } from "@saleor/orders/components/OrderListPage/filters"; + import { IFilterElement } from "../../../components/Filter"; import { OrderFilterInput, diff --git a/src/pages/components/PageDetailsPage/PageDetailsPage.tsx b/src/pages/components/PageDetailsPage/PageDetailsPage.tsx index 251504816..6176562fa 100644 --- a/src/pages/components/PageDetailsPage/PageDetailsPage.tsx +++ b/src/pages/components/PageDetailsPage/PageDetailsPage.tsx @@ -1,12 +1,3 @@ -import { - ContentState, - convertFromRaw, - convertToRaw, - RawDraftContentState -} from "draft-js"; -import React from "react"; -import { useIntl } from "react-intl"; - import AppHeader from "@saleor/components/AppHeader"; import CardSpacer from "@saleor/components/CardSpacer"; import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; @@ -17,9 +8,18 @@ import PageHeader from "@saleor/components/PageHeader"; import SaveButtonBar from "@saleor/components/SaveButtonBar"; import SeoForm from "@saleor/components/SeoForm"; import VisibilityCard from "@saleor/components/VisibilityCard"; +import { PageErrorFragment } from "@saleor/fragments/types/PageErrorFragment"; import useDateLocalize from "@saleor/hooks/useDateLocalize"; import { sectionNames } from "@saleor/intl"; -import { PageErrorFragment } from "@saleor/pages/types/PageErrorFragment"; +import { + ContentState, + convertFromRaw, + convertToRaw, + RawDraftContentState +} from "draft-js"; +import React from "react"; +import { useIntl } from "react-intl"; + import { maybe } from "../../../misc"; import { PageDetails_page } from "../../types/PageDetails"; import PageInfo from "../PageInfo"; @@ -122,25 +122,26 @@ const PageDetailsPage: React.FC = ({ data={data} errors={errors} disabled={disabled} - hiddenMessage={intl.formatMessage( - { - defaultMessage: "will be visible from {date}", - description: "page" - }, - { - date: localizeDate(data.publicationDate) - } - )} + messages={{ + hiddenLabel: intl.formatMessage({ + defaultMessage: "Hidden", + description: "page label" + }), + hiddenSecondLabel: intl.formatMessage( + { + defaultMessage: "will be visible from {date}", + description: "page" + }, + { + date: localizeDate(data.publicationDate, "L") + } + ), + visibleLabel: intl.formatMessage({ + defaultMessage: "Visible", + description: "page label" + }) + }} onChange={change} - visibleMessage={intl.formatMessage( - { - defaultMessage: "since {date}", - description: "page" - }, - { - date: localizeDate(data.publicationDate) - } - )} />
diff --git a/src/pages/components/PageInfo/PageInfo.tsx b/src/pages/components/PageInfo/PageInfo.tsx index d6467cb4f..c89a2883f 100644 --- a/src/pages/components/PageInfo/PageInfo.tsx +++ b/src/pages/components/PageInfo/PageInfo.tsx @@ -2,16 +2,16 @@ import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; import { makeStyles } from "@material-ui/core/styles"; import TextField from "@material-ui/core/TextField"; -import React from "react"; -import { useIntl } from "react-intl"; - import CardTitle from "@saleor/components/CardTitle"; import FormSpacer from "@saleor/components/FormSpacer"; import RichTextEditor from "@saleor/components/RichTextEditor"; +import { PageErrorFragment } from "@saleor/fragments/types/PageErrorFragment"; import { commonMessages } from "@saleor/intl"; import { getFormErrors } from "@saleor/utils/errors"; -import { PageErrorFragment } from "@saleor/pages/types/PageErrorFragment"; import getPageErrorMessage from "@saleor/utils/errors/page"; +import React from "react"; +import { useIntl } from "react-intl"; + import { maybe } from "../../../misc"; import { PageDetails_page } from "../../types/PageDetails"; import { FormData } from "../PageDetailsPage"; diff --git a/src/pages/components/PageList/PageList.tsx b/src/pages/components/PageList/PageList.tsx index 2ab9e07da..06a43dae3 100644 --- a/src/pages/components/PageList/PageList.tsx +++ b/src/pages/components/PageList/PageList.tsx @@ -4,20 +4,20 @@ import TableBody from "@material-ui/core/TableBody"; import TableCell from "@material-ui/core/TableCell"; import TableFooter from "@material-ui/core/TableFooter"; import TableRow from "@material-ui/core/TableRow"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import Checkbox from "@saleor/components/Checkbox"; import ResponsiveTable from "@saleor/components/ResponsiveTable"; import Skeleton from "@saleor/components/Skeleton"; import StatusLabel from "@saleor/components/StatusLabel"; +import TableCellHeader from "@saleor/components/TableCellHeader"; import TableHead from "@saleor/components/TableHead"; import TablePagination from "@saleor/components/TablePagination"; import { maybe, renderCollection } from "@saleor/misc"; -import { ListActions, ListProps, SortPage } from "@saleor/types"; import { PageListUrlSortField } from "@saleor/pages/urls"; -import TableCellHeader from "@saleor/components/TableCellHeader"; +import { ListActions, ListProps, SortPage } from "@saleor/types"; import { getArrowDirection } from "@saleor/utils/sort"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { PageList_pages_edges_node } from "../../types/PageList"; export interface PageListProps diff --git a/src/pages/components/PageListPage/PageListPage.tsx b/src/pages/components/PageListPage/PageListPage.tsx index 1d7b49725..aaf488cc7 100644 --- a/src/pages/components/PageListPage/PageListPage.tsx +++ b/src/pages/components/PageListPage/PageListPage.tsx @@ -1,14 +1,13 @@ import Button from "@material-ui/core/Button"; - -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import AppHeader from "@saleor/components/AppHeader"; import Container from "@saleor/components/Container"; import PageHeader from "@saleor/components/PageHeader"; import { sectionNames } from "@saleor/intl"; -import { ListActions, PageListProps, SortPage } from "@saleor/types"; import { PageListUrlSortField } from "@saleor/pages/urls"; +import { ListActions, PageListProps, SortPage } from "@saleor/types"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { PageList_pages_edges_node } from "../../types/PageList"; import PageList from "../PageList"; diff --git a/src/pages/components/PageSlug/PageSlug.tsx b/src/pages/components/PageSlug/PageSlug.tsx index 9cd191c5b..256ddcfd4 100644 --- a/src/pages/components/PageSlug/PageSlug.tsx +++ b/src/pages/components/PageSlug/PageSlug.tsx @@ -1,14 +1,14 @@ import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; import TextField from "@material-ui/core/TextField"; +import CardTitle from "@saleor/components/CardTitle"; +import { PageErrorFragment } from "@saleor/fragments/types/PageErrorFragment"; +import { getFormErrors } from "@saleor/utils/errors"; +import getPageErrorMessage from "@saleor/utils/errors/page"; import React from "react"; import { useIntl } from "react-intl"; import slugify from "slugify"; -import CardTitle from "@saleor/components/CardTitle"; -import { getFormErrors } from "@saleor/utils/errors"; -import getPageErrorMessage from "@saleor/utils/errors/page"; -import { PageErrorFragment } from "@saleor/pages/types/PageErrorFragment"; import { FormData } from "../PageDetailsPage"; export interface PageSlugProps { diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 9929240cc..cf98c14ae 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -1,18 +1,18 @@ +import { sectionNames } from "@saleor/intl"; +import { asSortParams } from "@saleor/utils/sort"; import { parse as parseQs } from "qs"; import React from "react"; import { useIntl } from "react-intl"; import { Route, RouteComponentProps, Switch } from "react-router-dom"; -import { sectionNames } from "@saleor/intl"; -import { asSortParams } from "@saleor/utils/sort"; import { WindowTitle } from "../components/WindowTitle"; import { pageCreatePath, pageListPath, PageListUrlQueryParams, + PageListUrlSortField, pagePath, - PageUrlQueryParams, - PageListUrlSortField + PageUrlQueryParams } from "./urls"; import PageCreate from "./views/PageCreate"; import PageDetailsComponent from "./views/PageDetails"; diff --git a/src/pages/mutations.ts b/src/pages/mutations.ts index d5b55d325..9cc38a9c1 100644 --- a/src/pages/mutations.ts +++ b/src/pages/mutations.ts @@ -1,7 +1,8 @@ +import { pageErrorFragment } from "@saleor/fragments/errors"; +import { pageDetailsFragment } from "@saleor/fragments/pages"; import gql from "graphql-tag"; import { TypedMutation } from "../mutations"; -import { pageDetailsFragment } from "./queries"; import { PageBulkPublish, PageBulkPublishVariables @@ -14,13 +15,6 @@ import { PageCreate, PageCreateVariables } from "./types/PageCreate"; import { PageRemove, PageRemoveVariables } from "./types/PageRemove"; import { PageUpdate, PageUpdateVariables } from "./types/PageUpdate"; -const pageErrorFragment = gql` - fragment PageErrorFragment on PageError { - code - field - } -`; - const pageCreate = gql` ${pageDetailsFragment} ${pageErrorFragment} diff --git a/src/pages/queries.ts b/src/pages/queries.ts index 5623f1273..8dd8618c6 100644 --- a/src/pages/queries.ts +++ b/src/pages/queries.ts @@ -1,30 +1,11 @@ +import { pageDetailsFragment, pageFragment } from "@saleor/fragments/pages"; +import makeQuery from "@saleor/hooks/makeQuery"; import gql from "graphql-tag"; -import makeQuery from "@saleor/hooks/makeQuery"; import { TypedQuery } from "../queries"; import { PageDetails, PageDetailsVariables } from "./types/PageDetails"; import { PageList, PageListVariables } from "./types/PageList"; -export const pageFragment = gql` - fragment PageFragment on Page { - id - title - slug - isPublished - } -`; - -export const pageDetailsFragment = gql` - ${pageFragment} - fragment PageDetailsFragment on Page { - ...PageFragment - contentJson - seoTitle - seoDescription - publicationDate - } -`; - const pageList = gql` ${pageFragment} query PageList( diff --git a/src/pages/views/PageCreate.tsx b/src/pages/views/PageCreate.tsx index d9f95a34f..c9110aaa6 100644 --- a/src/pages/views/PageCreate.tsx +++ b/src/pages/views/PageCreate.tsx @@ -1,9 +1,9 @@ -import React from "react"; -import { useIntl } from "react-intl"; - import { WindowTitle } from "@saleor/components/WindowTitle"; import useNavigator from "@saleor/hooks/useNavigator"; import useNotifier from "@saleor/hooks/useNotifier"; +import React from "react"; +import { useIntl } from "react-intl"; + import PageDetailsPage from "../components/PageDetailsPage"; import { TypedPageCreate } from "../mutations"; import { PageCreate as PageCreateData } from "../types/PageCreate"; @@ -21,6 +21,7 @@ export const PageCreate: React.FC = () => { const handlePageCreate = (data: PageCreateData) => { if (data.pageCreate.errors.length === 0) { notify({ + status: "success", text: intl.formatMessage({ defaultMessage: "Successfully created new page" }) diff --git a/src/pages/views/PageDetails.tsx b/src/pages/views/PageDetails.tsx index 1d02ee9e0..fd9cc58fd 100644 --- a/src/pages/views/PageDetails.tsx +++ b/src/pages/views/PageDetails.tsx @@ -1,13 +1,13 @@ import DialogContentText from "@material-ui/core/DialogContentText"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import ActionDialog from "@saleor/components/ActionDialog"; import { WindowTitle } from "@saleor/components/WindowTitle"; import useNavigator from "@saleor/hooks/useNavigator"; import useNotifier from "@saleor/hooks/useNotifier"; import { commonMessages } from "@saleor/intl"; -import { maybe, getStringOrPlaceholder } from "../../misc"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + +import { getStringOrPlaceholder, maybe } from "../../misc"; import { PageInput } from "../../types/globalTypes"; import PageDetailsPage, { FormData } from "../components/PageDetailsPage"; import { TypedPageRemove, TypedPageUpdate } from "../mutations"; @@ -44,6 +44,7 @@ export const PageDetails: React.FC = ({ id, params }) => { const handlePageRemove = (data: PageRemove) => { if (data.pageDelete.errors.length === 0) { notify({ + status: "success", text: intl.formatMessage(commonMessages.savedChanges) }); navigate(pageListUrl()); diff --git a/src/pages/views/PageList/PageList.tsx b/src/pages/views/PageList/PageList.tsx index 9400ef410..47c9da1f6 100644 --- a/src/pages/views/PageList/PageList.tsx +++ b/src/pages/views/PageList/PageList.tsx @@ -2,9 +2,6 @@ import Button from "@material-ui/core/Button"; import DialogContentText from "@material-ui/core/DialogContentText"; import IconButton from "@material-ui/core/IconButton"; import DeleteIcon from "@material-ui/icons/Delete"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import ActionDialog from "@saleor/components/ActionDialog"; import { configurationMenuUrl } from "@saleor/configuration"; import useBulkActions from "@saleor/hooks/useBulkActions"; @@ -16,9 +13,12 @@ import usePaginator, { } from "@saleor/hooks/usePaginator"; import { maybe } from "@saleor/misc"; import { ListViews } from "@saleor/types"; -import { getSortParams } from "@saleor/utils/sort"; -import createSortHandler from "@saleor/utils/handlers/sortHandler"; import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; +import createSortHandler from "@saleor/utils/handlers/sortHandler"; +import { getSortParams } from "@saleor/utils/sort"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import PageListPage from "../../components/PageListPage/PageListPage"; import { TypedPageBulkPublish, TypedPageBulkRemove } from "../../mutations"; import { usePageListQuery } from "../../queries"; @@ -77,6 +77,7 @@ export const PageList: React.FC = ({ params }) => { if (data.pageBulkPublish.errors.length === 0) { closeModal(); notify({ + status: "success", text: intl.formatMessage({ defaultMessage: "Published pages", description: "notification" @@ -91,6 +92,7 @@ export const PageList: React.FC = ({ params }) => { if (data.pageBulkDelete.errors.length === 0) { closeModal(); notify({ + status: "success", text: intl.formatMessage({ defaultMessage: "Removed pages", description: "notification" diff --git a/src/permissionGroups/components/AssignMembersDialog/AssignMembersDialog.stories.tsx b/src/permissionGroups/components/AssignMembersDialog/AssignMembersDialog.stories.tsx index e4959d136..c2011240e 100644 --- a/src/permissionGroups/components/AssignMembersDialog/AssignMembersDialog.stories.tsx +++ b/src/permissionGroups/components/AssignMembersDialog/AssignMembersDialog.stories.tsx @@ -1,10 +1,10 @@ -import { storiesOf } from "@storybook/react"; -import React from "react"; - import AssignMembersDialog, { AssignMembersDialogProps } from "@saleor/permissionGroups/components/AssignMembersDialog"; import Decorator from "@saleor/storybook/Decorator"; +import { storiesOf } from "@storybook/react"; +import React from "react"; + import { users } from "../../fixtures"; const props: AssignMembersDialogProps = { diff --git a/src/permissionGroups/components/AssignMembersDialog/AssignMembersDialog.tsx b/src/permissionGroups/components/AssignMembersDialog/AssignMembersDialog.tsx index 834038fb5..61219ff6b 100644 --- a/src/permissionGroups/components/AssignMembersDialog/AssignMembersDialog.tsx +++ b/src/permissionGroups/components/AssignMembersDialog/AssignMembersDialog.tsx @@ -1,32 +1,31 @@ -import { FormattedMessage, useIntl } from "react-intl"; -import InfiniteScroll from "react-infinite-scroller"; -import classNames from "classnames"; - -import ConfirmButton, { - ConfirmButtonTransitionState -} from "@saleor/components/ConfirmButton"; -import { buttonMessages } from "@saleor/intl"; -import { makeStyles } from "@material-ui/core/styles"; -import { getUserName, getUserInitials } from "@saleor/misc"; -import { DialogProps, FetchMoreProps, SearchPageProps } from "@saleor/types"; -import useElementScroll from "@saleor/hooks/useElementScroll"; +import { Checkbox, Typography } from "@material-ui/core"; import Button from "@material-ui/core/Button"; import CircularProgress from "@material-ui/core/CircularProgress"; import Dialog from "@material-ui/core/Dialog"; import DialogActions from "@material-ui/core/DialogActions"; import DialogContent from "@material-ui/core/DialogContent"; import DialogTitle from "@material-ui/core/DialogTitle"; -import React from "react"; -import ResponsiveTable from "@saleor/components/ResponsiveTable"; +import { makeStyles } from "@material-ui/core/styles"; import TableBody from "@material-ui/core/TableBody"; import TableCell from "@material-ui/core/TableCell"; import TableRow from "@material-ui/core/TableRow"; import TextField from "@material-ui/core/TextField"; -import useSearchQuery from "@saleor/hooks/useSearchQuery"; -import { SearchStaffMembers_search_edges_node } from "@saleor/searches/types/SearchStaffMembers"; -import { Checkbox, Typography } from "@material-ui/core"; -import Skeleton from "@saleor/components/Skeleton"; import CardSpacer from "@saleor/components/CardSpacer"; +import ConfirmButton, { + ConfirmButtonTransitionState +} from "@saleor/components/ConfirmButton"; +import ResponsiveTable from "@saleor/components/ResponsiveTable"; +import Skeleton from "@saleor/components/Skeleton"; +import useElementScroll from "@saleor/hooks/useElementScroll"; +import useSearchQuery from "@saleor/hooks/useSearchQuery"; +import { buttonMessages } from "@saleor/intl"; +import { getUserInitials, getUserName } from "@saleor/misc"; +import { SearchStaffMembers_search_edges_node } from "@saleor/searches/types/SearchStaffMembers"; +import { DialogProps, FetchMoreProps, SearchPageProps } from "@saleor/types"; +import classNames from "classnames"; +import React from "react"; +import InfiniteScroll from "react-infinite-scroller"; +import { FormattedMessage, useIntl } from "react-intl"; const useStyles = makeStyles( theme => ({ diff --git a/src/permissionGroups/components/MembersErrorDialog/MembersErrorDialog.stories.tsx b/src/permissionGroups/components/MembersErrorDialog/MembersErrorDialog.stories.tsx index 0ae5c543b..b637cfbea 100644 --- a/src/permissionGroups/components/MembersErrorDialog/MembersErrorDialog.stories.tsx +++ b/src/permissionGroups/components/MembersErrorDialog/MembersErrorDialog.stories.tsx @@ -1,6 +1,7 @@ +import Decorator from "@saleor/storybook/Decorator"; import { storiesOf } from "@storybook/react"; import React from "react"; -import Decorator from "@saleor/storybook/Decorator"; + import MembersErrorDialog, { MembersErrorDialogProps } from "./MembersErrorDialog"; diff --git a/src/permissionGroups/components/MembersErrorDialog/MembersErrorDialog.tsx b/src/permissionGroups/components/MembersErrorDialog/MembersErrorDialog.tsx index cc685ec90..496f637ae 100644 --- a/src/permissionGroups/components/MembersErrorDialog/MembersErrorDialog.tsx +++ b/src/permissionGroups/components/MembersErrorDialog/MembersErrorDialog.tsx @@ -1,9 +1,8 @@ import DialogContentText from "@material-ui/core/DialogContentText"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import ActionDialog from "@saleor/components/ActionDialog"; import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; export interface MembersErrorDialogProps { confirmButtonState: ConfirmButtonTransitionState; @@ -30,7 +29,7 @@ const MembersErrorDialog: React.FC = ({ defaultMessage: "Unassign users", description: "dialog title" })} - variant="default" + variant="info" > ({ @@ -128,19 +125,21 @@ const PermissionGroupList: React.FC = props => { onClick={ permissionGroup ? onRowClick(permissionGroup.id) : undefined } - data-tc="id" - data-tc-id={maybe(() => permissionGroup.id)} + data-test="id" + data-test-id={maybe(() => permissionGroup.id)} > {permissionGroup ? ( - {permissionGroup.name} + {permissionGroup.name} ) : ( )} {permissionGroup ? ( - {permissionGroup.users.length} + + {permissionGroup.users.length} + ) : ( )} diff --git a/src/permissionGroups/components/PermissionGroupListPage/PermissionGroupListPage.stories.tsx b/src/permissionGroups/components/PermissionGroupListPage/PermissionGroupListPage.stories.tsx index ffbbd6738..473b38497 100644 --- a/src/permissionGroups/components/PermissionGroupListPage/PermissionGroupListPage.stories.tsx +++ b/src/permissionGroups/components/PermissionGroupListPage/PermissionGroupListPage.stories.tsx @@ -1,17 +1,16 @@ -import { storiesOf } from "@storybook/react"; -import React from "react"; import { listActionsProps, pageListProps, sortPageProps } from "@saleor/fixtures"; - import PermissionGroupListPage, { PermissionGroupListPageProps } from "@saleor/permissionGroups/components/PermissionGroupListPage"; -import Decorator from "@saleor/storybook/Decorator"; -import { PermissionGroupListUrlSortField } from "@saleor/permissionGroups/urls"; import { permissionGroups } from "@saleor/permissionGroups/fixtures"; +import { PermissionGroupListUrlSortField } from "@saleor/permissionGroups/urls"; +import Decorator from "@saleor/storybook/Decorator"; +import { storiesOf } from "@storybook/react"; +import React from "react"; const props: PermissionGroupListPageProps = { permissionGroups, diff --git a/src/permissionGroups/components/PermissionGroupListPage/PermissionGroupListPage.tsx b/src/permissionGroups/components/PermissionGroupListPage/PermissionGroupListPage.tsx index 1c646c0fa..e022a7e83 100644 --- a/src/permissionGroups/components/PermissionGroupListPage/PermissionGroupListPage.tsx +++ b/src/permissionGroups/components/PermissionGroupListPage/PermissionGroupListPage.tsx @@ -1,15 +1,15 @@ import Button from "@material-ui/core/Button"; import Card from "@material-ui/core/Card"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import AppHeader from "@saleor/components/AppHeader"; import Container from "@saleor/components/Container"; import PageHeader from "@saleor/components/PageHeader"; import { sectionNames } from "@saleor/intl"; -import { PermissionGroupListUrlSortField } from "../../urls"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { PageListProps, SortPage } from "../../../types"; import { PermissionGroupList_permissionGroups_edges_node } from "../../types/PermissionGroupList"; +import { PermissionGroupListUrlSortField } from "../../urls"; import PermissionGroupList from "../PermissionGroupList"; export interface PermissionGroupListPageProps diff --git a/src/permissionGroups/components/PermissionGroupMemberList/PermissionGroupMemberList.tsx b/src/permissionGroups/components/PermissionGroupMemberList/PermissionGroupMemberList.tsx index cc4dd3651..ec51ca259 100644 --- a/src/permissionGroups/components/PermissionGroupMemberList/PermissionGroupMemberList.tsx +++ b/src/permissionGroups/components/PermissionGroupMemberList/PermissionGroupMemberList.tsx @@ -1,32 +1,31 @@ +import { Button, IconButton } from "@material-ui/core"; import Card from "@material-ui/core/Card"; import { makeStyles } from "@material-ui/core/styles"; import TableBody from "@material-ui/core/TableBody"; import TableCell from "@material-ui/core/TableCell"; -import TableHead from "@saleor/components/TableHead"; import TableRow from "@material-ui/core/TableRow"; import Typography from "@material-ui/core/Typography"; -import classNames from "classnames"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; import DeleteIcon from "@material-ui/icons/Delete"; +import CardTitle from "@saleor/components/CardTitle"; +import Checkbox from "@saleor/components/Checkbox"; import ResponsiveTable from "@saleor/components/ResponsiveTable"; import Skeleton from "@saleor/components/Skeleton"; +import TableCellHeader from "@saleor/components/TableCellHeader"; +import TableHead from "@saleor/components/TableHead"; import { getUserInitials, getUserName, - stopPropagation, - renderCollection + renderCollection, + stopPropagation } from "@saleor/misc"; -import { ListActions, SortPage } from "@saleor/types"; -import TableCellHeader from "@saleor/components/TableCellHeader"; -import Checkbox from "@saleor/components/Checkbox"; - -import { Button, IconButton } from "@material-ui/core"; -import CardTitle from "@saleor/components/CardTitle"; +import { sortMembers } from "@saleor/permissionGroups/sort"; import { PermissionGroupDetails_permissionGroup_users } from "@saleor/permissionGroups/types/PermissionGroupDetails"; import { MembersListUrlSortField } from "@saleor/permissionGroups/urls"; +import { ListActions, SortPage } from "@saleor/types"; import { getArrowDirection } from "@saleor/utils/sort"; -import { sortMembers } from "@saleor/permissionGroups/sort"; +import classNames from "classnames"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; const useStyles = makeStyles( theme => ({ @@ -53,8 +52,8 @@ const useStyles = makeStyles( width: 47 }, avatarDefault: { - "& p": { - color: "#fff", + "& div": { + color: theme.palette.primary.contrastText, lineHeight: "47px" }, background: theme.palette.primary.main, diff --git a/src/permissionGroups/components/UnassignMembersDialog/UnassignMembersDialog.stories.tsx b/src/permissionGroups/components/UnassignMembersDialog/UnassignMembersDialog.stories.tsx index 145388d54..8be26fb0f 100644 --- a/src/permissionGroups/components/UnassignMembersDialog/UnassignMembersDialog.stories.tsx +++ b/src/permissionGroups/components/UnassignMembersDialog/UnassignMembersDialog.stories.tsx @@ -1,9 +1,9 @@ -import { storiesOf } from "@storybook/react"; -import React from "react"; import UnassignMembersDialog, { UnassignMembersDialogProps } from "@saleor/permissionGroups/components/UnassignMembersDialog"; import Decorator from "@saleor/storybook/Decorator"; +import { storiesOf } from "@storybook/react"; +import React from "react"; const props: UnassignMembersDialogProps = { confirmButtonState: "default", diff --git a/src/permissionGroups/components/UnassignMembersDialog/UnassignMembersDialog.tsx b/src/permissionGroups/components/UnassignMembersDialog/UnassignMembersDialog.tsx index d8e63072c..568c77bab 100644 --- a/src/permissionGroups/components/UnassignMembersDialog/UnassignMembersDialog.tsx +++ b/src/permissionGroups/components/UnassignMembersDialog/UnassignMembersDialog.tsx @@ -1,9 +1,8 @@ import DialogContentText from "@material-ui/core/DialogContentText"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import ActionDialog from "@saleor/components/ActionDialog"; import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; export interface UnassignMembersDialogProps { confirmButtonState: ConfirmButtonTransitionState; diff --git a/src/permissionGroups/fixtures.ts b/src/permissionGroups/fixtures.ts index 1fc235bfb..f0e1e3b5b 100644 --- a/src/permissionGroups/fixtures.ts +++ b/src/permissionGroups/fixtures.ts @@ -1,15 +1,15 @@ import * as avatarImg from "@assets/images/avatars/avatar1.png"; +import { PermissionGroupErrorFragment } from "@saleor/fragments/types/PermissionGroupErrorFragment"; import { SearchStaffMembers_search_edges_node } from "@saleor/searches/types/SearchStaffMembers"; +import { StaffMemberDetails_user_permissionGroups } from "@saleor/staff/types/StaffMemberDetails"; /* eslint-disable sort-keys */ import { PermissionEnum, PermissionGroupErrorCode } from "@saleor/types/globalTypes"; -import { StaffMemberDetails_user_permissionGroups } from "@saleor/staff/types/StaffMemberDetails"; import { PermissionGroupDetails_permissionGroup } from "./types/PermissionGroupDetails"; import { PermissionGroupList_permissionGroups_edges_node } from "./types/PermissionGroupList"; -import { PermissionGroupErrorFragment } from "./types/PermissionGroupErrorFragment"; export const permissionGroups: PermissionGroupList_permissionGroups_edges_node[] = [ { diff --git a/src/permissionGroups/index.tsx b/src/permissionGroups/index.tsx index da2282d04..04f59d772 100644 --- a/src/permissionGroups/index.tsx +++ b/src/permissionGroups/index.tsx @@ -1,23 +1,23 @@ +import { sectionNames } from "@saleor/intl"; +import { asSortParams } from "@saleor/utils/sort"; import { parse as parseQs } from "qs"; import React from "react"; import { useIntl } from "react-intl"; import { Route, RouteComponentProps, Switch } from "react-router-dom"; -import { sectionNames } from "@saleor/intl"; -import { asSortParams } from "@saleor/utils/sort"; import { WindowTitle } from "../components/WindowTitle"; import { - permissionGroupListPath, - permissionGroupDetailsPath, + MembersListUrlSortField, permissionGroupAddPath, - PermissionGroupListUrlQueryParams, - PermissionGroupListUrlSortField, + permissionGroupDetailsPath, PermissionGroupDetailsUrlQueryParams, - MembersListUrlSortField + permissionGroupListPath, + PermissionGroupListUrlQueryParams, + PermissionGroupListUrlSortField } from "./urls"; -import PermissionGroupListComponent from "./views/PermissionGroupList"; -import PermissionGroupDetailsComponent from "./views/PermissionGroupDetails"; import PermissionGroupCreate from "./views/PermissionGroupCreate"; +import PermissionGroupDetailsComponent from "./views/PermissionGroupDetails"; +import PermissionGroupListComponent from "./views/PermissionGroupList"; const permissionGroupList: React.FC> = ({ location diff --git a/src/permissionGroups/mutations.ts b/src/permissionGroups/mutations.ts index 2dca8eb89..4ec5356d1 100644 --- a/src/permissionGroups/mutations.ts +++ b/src/permissionGroups/mutations.ts @@ -1,8 +1,8 @@ +import { permissionGroupErrorFragment } from "@saleor/fragments/errors"; +import { permissionGroupDetailsFragment } from "@saleor/fragments/permissionGroups"; +import makeMutation from "@saleor/hooks/makeMutation"; import gql from "graphql-tag"; -import makeMutation from "@saleor/hooks/makeMutation"; - -import { permissionGroupDetailsFragment } from "./queries"; import { PermissionGroupCreate, PermissionGroupCreateVariables @@ -16,13 +16,6 @@ import { PermissionGroupUpdateVariables } from "./types/PermissionGroupUpdate"; -export const permissionGroupErrorFragment = gql` - fragment PermissionGroupErrorFragment on PermissionGroupError { - code - field - } -`; - export const permissionGroupDelete = gql` ${permissionGroupErrorFragment} mutation PermissionGroupDelete($id: ID!) { diff --git a/src/permissionGroups/queries.ts b/src/permissionGroups/queries.ts index 9050a502a..927032edf 100644 --- a/src/permissionGroups/queries.ts +++ b/src/permissionGroups/queries.ts @@ -1,51 +1,19 @@ +import { pageInfoFragment } from "@saleor/fragments/pageInfo"; +import { + permissionGroupDetailsFragment, + permissionGroupFragment +} from "@saleor/fragments/permissionGroups"; +import makeQuery from "@saleor/hooks/makeQuery"; import gql from "graphql-tag"; -import makeQuery from "@saleor/hooks/makeQuery"; -import { staffMemberFragment } from "@saleor/staff/queries"; - -import { pageInfoFragment } from "../queries"; -import { - PermissionGroupList, - PermissionGroupListVariables -} from "./types/PermissionGroupList"; import { PermissionGroupDetails, PermissionGroupDetailsVariables } from "./types/PermissionGroupDetails"; -export const permissionGroupFragment = gql` - fragment PermissionGroupFragment on Group { - id - name - userCanManage - users { - id - firstName - lastName - } - } -`; - -export const permissionFragment = gql` - fragment PermissionFragment on Permission { - code - name - } -`; - -export const permissionGroupDetailsFragment = gql` - ${permissionGroupFragment} - ${permissionFragment} - ${staffMemberFragment} - fragment PermissionGroupDetailsFragment on Group { - ...PermissionGroupFragment - permissions { - ...PermissionFragment - } - users { - ...StaffMemberFragment - } - } -`; +import { + PermissionGroupList, + PermissionGroupListVariables +} from "./types/PermissionGroupList"; export const permissionGroupListQuery = gql` ${pageInfoFragment} diff --git a/src/permissionGroups/sort.ts b/src/permissionGroups/sort.ts index 0eca72665..fa3bb3992 100644 --- a/src/permissionGroups/sort.ts +++ b/src/permissionGroups/sort.ts @@ -1,4 +1,5 @@ import { getUserName } from "@saleor/misc"; + import { PermissionGroupDetails_permissionGroup_users } from "./types/PermissionGroupDetails"; import { MembersListUrlSortField } from "./urls"; diff --git a/src/permissionGroups/urls.ts b/src/permissionGroups/urls.ts index 3cf733c96..3f47a04ff 100644 --- a/src/permissionGroups/urls.ts +++ b/src/permissionGroups/urls.ts @@ -1,14 +1,13 @@ -import { stringify as stringifyQs } from "qs"; -import urlJoin from "url-join"; - import { BulkAction, Dialog, Pagination, - TabActionDialog, + SingleAction, Sort, - SingleAction + TabActionDialog } from "@saleor/types"; +import { stringify as stringifyQs } from "qs"; +import urlJoin from "url-join"; const permissionGroupSection = "/permission-groups/"; diff --git a/src/permissionGroups/utils.ts b/src/permissionGroups/utils.ts index 87030b101..b924f1cd9 100644 --- a/src/permissionGroups/utils.ts +++ b/src/permissionGroups/utils.ts @@ -1,9 +1,9 @@ +import { ShopInfo_shop_permissions } from "@saleor/components/Shop/types/ShopInfo"; +import { User } from "@saleor/fragments/types/User"; import difference from "lodash-es/difference"; -import { ShopInfo_shop_permissions } from "@saleor/components/Shop/types/ShopInfo"; -import { User } from "@saleor/auth/types/User"; -import { PermissionGroupDetails_permissionGroup } from "./types/PermissionGroupDetails"; import { PermissionGroupDetailsPageFormData } from "./components/PermissionGroupDetailsPage"; +import { PermissionGroupDetails_permissionGroup } from "./types/PermissionGroupDetails"; /** * Will return true if group has all permissions available in shop assigned. diff --git a/src/permissionGroups/views/PermissionGroupCreate/PermissionGroupCreate.tsx b/src/permissionGroups/views/PermissionGroupCreate/PermissionGroupCreate.tsx index 0acda5ed8..5e18ed71e 100644 --- a/src/permissionGroups/views/PermissionGroupCreate/PermissionGroupCreate.tsx +++ b/src/permissionGroups/views/PermissionGroupCreate/PermissionGroupCreate.tsx @@ -1,15 +1,16 @@ -import React from "react"; -import { useIntl } from "react-intl"; import { WindowTitle } from "@saleor/components/WindowTitle"; import useNavigator from "@saleor/hooks/useNavigator"; import useNotifier from "@saleor/hooks/useNotifier"; import useShop from "@saleor/hooks/useShop"; import useUser from "@saleor/hooks/useUser"; import { PermissionData } from "@saleor/permissionGroups/components/PermissionGroupDetailsPage"; -import { PermissionGroupCreate } from "../../types/PermissionGroupCreate"; -import { permissionGroupListUrl, permissionGroupDetailsUrl } from "../../urls"; -import { usePermissionGroupCreate } from "../../mutations"; +import React from "react"; +import { useIntl } from "react-intl"; + import PermissionGroupCreatePage from "../../components/PermissionGroupCreatePage"; +import { usePermissionGroupCreate } from "../../mutations"; +import { PermissionGroupCreate } from "../../types/PermissionGroupCreate"; +import { permissionGroupDetailsUrl, permissionGroupListUrl } from "../../urls"; const PermissionGroupCreateView: React.FC = () => { const navigate = useNavigator(); @@ -21,6 +22,7 @@ const PermissionGroupCreateView: React.FC = () => { const handleSuccess = (data: PermissionGroupCreate) => { if (data?.permissionGroupCreate?.errors.length === 0) { notify({ + status: "success", text: intl.formatMessage({ defaultMessage: "Permission group created" }) diff --git a/src/permissionGroups/views/PermissionGroupDetails/PermissionGroupDetails.tsx b/src/permissionGroups/views/PermissionGroupDetails/PermissionGroupDetails.tsx index 71f12c489..6294c993b 100644 --- a/src/permissionGroups/views/PermissionGroupDetails/PermissionGroupDetails.tsx +++ b/src/permissionGroups/views/PermissionGroupDetails/PermissionGroupDetails.tsx @@ -1,37 +1,37 @@ -import React, { useState } from "react"; -import useNavigator from "@saleor/hooks/useNavigator"; -import useShop from "@saleor/hooks/useShop"; -import useBulkActions from "@saleor/hooks/useBulkActions"; -import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; -import { useIntl } from "react-intl"; -import useNotifier from "@saleor/hooks/useNotifier"; -import { DEFAULT_INITIAL_SEARCH_DATA } from "@saleor/config"; import { Button } from "@material-ui/core"; +import { DEFAULT_INITIAL_SEARCH_DATA } from "@saleor/config"; +import useBulkActions from "@saleor/hooks/useBulkActions"; +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import useShop from "@saleor/hooks/useShop"; +import useStateFromProps from "@saleor/hooks/useStateFromProps"; +import useUser from "@saleor/hooks/useUser"; import { commonMessages } from "@saleor/intl"; -import { getSortParams } from "@saleor/utils/sort"; -import createSortHandler from "@saleor/utils/handlers/sortHandler"; +import MembersErrorDialog from "@saleor/permissionGroups/components/MembersErrorDialog"; import { arePermissionsExceeded, permissionsDiff, usersDiff } from "@saleor/permissionGroups/utils"; -import useStateFromProps from "@saleor/hooks/useStateFromProps"; import useStaffMemberSearch from "@saleor/searches/useStaffMemberSearch"; -import useUser from "@saleor/hooks/useUser"; -import MembersErrorDialog from "@saleor/permissionGroups/components/MembersErrorDialog"; -import PermissionGroupDetailsPage from "../../components/PermissionGroupDetailsPage"; -import AssignMembersDialog from "../../components/AssignMembersDialog"; -import UnassignMembersDialog from "../../components/UnassignMembersDialog"; -import { usePermissionGroupDetailsQuery } from "../../queries"; -import { usePermissionGroupUpdate } from "../../mutations"; +import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; +import createSortHandler from "@saleor/utils/handlers/sortHandler"; +import { getSortParams } from "@saleor/utils/sort"; +import React, { useState } from "react"; +import { useIntl } from "react-intl"; +import AssignMembersDialog from "../../components/AssignMembersDialog"; +import PermissionGroupDetailsPage from "../../components/PermissionGroupDetailsPage"; +import UnassignMembersDialog from "../../components/UnassignMembersDialog"; +import { usePermissionGroupUpdate } from "../../mutations"; +import { usePermissionGroupDetailsQuery } from "../../queries"; +import { PermissionGroupUpdate } from "../../types/PermissionGroupUpdate"; import { permissionGroupDetailsUrl, - PermissionGroupDetailsUrlQueryParams, PermissionGroupDetailsUrlDialog, + PermissionGroupDetailsUrlQueryParams, permissionGroupListUrl } from "../../urls"; -import { PermissionGroupUpdate } from "../../types/PermissionGroupUpdate"; interface PermissionGroupDetailsProps { id: string; @@ -66,6 +66,7 @@ export const PermissionGroupDetails: React.FC = ({ const handleUpdateSuccess = (data: PermissionGroupUpdate) => { if (data.permissionGroupUpdate.errors.length === 0) { notify({ + status: "success", text: intl.formatMessage(commonMessages.savedChanges) }); refetch(); diff --git a/src/permissionGroups/views/PermissionGroupList/PermissionGroupList.tsx b/src/permissionGroups/views/PermissionGroupList/PermissionGroupList.tsx index b6f602f5d..b696f2557 100644 --- a/src/permissionGroups/views/PermissionGroupList/PermissionGroupList.tsx +++ b/src/permissionGroups/views/PermissionGroupList/PermissionGroupList.tsx @@ -1,31 +1,30 @@ -import React from "react"; -import { useIntl } from "react-intl"; - +import { configurationMenuUrl } from "@saleor/configuration"; +import { PermissionGroupErrorFragment } from "@saleor/fragments/types/PermissionGroupErrorFragment"; import useListSettings from "@saleor/hooks/useListSettings"; import useNavigator from "@saleor/hooks/useNavigator"; - +import useNotifier from "@saleor/hooks/useNotifier"; import usePaginator, { createPaginationState } from "@saleor/hooks/usePaginator"; -import { configurationMenuUrl } from "@saleor/configuration"; -import useNotifier from "@saleor/hooks/useNotifier"; -import { ListViews } from "@saleor/types"; -import { getSortParams } from "@saleor/utils/sort"; -import createSortHandler from "@saleor/utils/handlers/sortHandler"; +import { getStringOrPlaceholder } from "@saleor/misc"; import PermissionGroupDeleteDialog from "@saleor/permissionGroups/components/PermissionGroupDeleteDialog"; -import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; +import { usePermissionGroupDelete } from "@saleor/permissionGroups/mutations"; import { usePermissionGroupListQuery } from "@saleor/permissionGroups/queries"; import { PermissionGroupDelete } from "@saleor/permissionGroups/types/PermissionGroupDelete"; -import { usePermissionGroupDelete } from "@saleor/permissionGroups/mutations"; -import { getStringOrPlaceholder } from "@saleor/misc"; -import { PermissionGroupErrorFragment } from "@saleor/permissionGroups/types/PermissionGroupErrorFragment"; +import { ListViews } from "@saleor/types"; +import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; +import createSortHandler from "@saleor/utils/handlers/sortHandler"; +import { getSortParams } from "@saleor/utils/sort"; +import React from "react"; +import { useIntl } from "react-intl"; + import PermissionGroupListPage from "../../components/PermissionGroupListPage"; import { - permissionGroupListUrl, permissionGroupAddUrl, - PermissionGroupListUrlQueryParams, permissionGroupDetailsUrl, - PermissionGroupListUrlDialog + permissionGroupListUrl, + PermissionGroupListUrlDialog, + PermissionGroupListUrlQueryParams } from "../../urls"; import { getSortQueryVariables } from "./sort"; @@ -82,6 +81,7 @@ export const PermissionGroupList: React.FC = ({ const handleDeleteSuccess = (data: PermissionGroupDelete) => { if (data.permissionGroupDelete.errors.length === 0) { notify({ + status: "success", text: intl.formatMessage({ defaultMessage: "Permission Group Deleted" }) diff --git a/src/plugins/components/PluginAuthorization/PluginAuthorization.tsx b/src/plugins/components/PluginAuthorization/PluginAuthorization.tsx index 3cd38de73..a1b9cbdfb 100644 --- a/src/plugins/components/PluginAuthorization/PluginAuthorization.tsx +++ b/src/plugins/components/PluginAuthorization/PluginAuthorization.tsx @@ -3,15 +3,14 @@ import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; import makeStyles from "@material-ui/core/styles/makeStyles"; import Typography from "@material-ui/core/Typography"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import CardTitle from "@saleor/components/CardTitle"; import Hr from "@saleor/components/Hr"; import { buttonMessages } from "@saleor/intl"; import { Plugin_plugin_configuration } from "@saleor/plugins/types/Plugin"; import { isSecretField } from "@saleor/plugins/utils"; import { ConfigurationTypeFieldEnum } from "@saleor/types/globalTypes"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; interface PluginAuthorizationProps { fields: Plugin_plugin_configuration[]; diff --git a/src/plugins/components/PluginInfo/PluginInfo.tsx b/src/plugins/components/PluginInfo/PluginInfo.tsx index 8a579701b..861c6c8eb 100644 --- a/src/plugins/components/PluginInfo/PluginInfo.tsx +++ b/src/plugins/components/PluginInfo/PluginInfo.tsx @@ -2,19 +2,23 @@ import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; import makeStyles from "@material-ui/core/styles/makeStyles"; import Typography from "@material-ui/core/Typography"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import CardTitle from "@saleor/components/CardTitle"; import ControlledCheckbox from "@saleor/components/ControlledCheckbox"; import FormSpacer from "@saleor/components/FormSpacer"; import Hr from "@saleor/components/Hr"; +import { PluginErrorFragment } from "@saleor/fragments/types/PluginErrorFragment"; import { commonMessages } from "@saleor/intl"; +import { PluginErrorCode } from "@saleor/types/globalTypes"; +import getPluginErrorMessage from "@saleor/utils/errors/plugins"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { FormData } from "../PluginsDetailsPage"; interface PluginInfoProps { data: FormData; description: string; + errors: PluginErrorFragment[]; name: string; onChange: (event: React.ChangeEvent) => void; } @@ -35,11 +39,17 @@ const useStyles = makeStyles( const PluginInfo: React.FC = ({ data, description, + errors, name, onChange }) => { const classes = useStyles({}); const intl = useIntl(); + + const misconfiguredError = errors.find( + err => err.code === PluginErrorCode.PLUGIN_MISCONFIGURED + ); + return ( = ({ checked={data.active} onChange={onChange} /> + {misconfiguredError && ( + + {getPluginErrorMessage(misconfiguredError, intl)} + + )} ); diff --git a/src/plugins/components/PluginSecretFieldDialog/PluginSecretFieldDialog.stories.tsx b/src/plugins/components/PluginSecretFieldDialog/PluginSecretFieldDialog.stories.tsx index 16028559b..d1caef19c 100644 --- a/src/plugins/components/PluginSecretFieldDialog/PluginSecretFieldDialog.stories.tsx +++ b/src/plugins/components/PluginSecretFieldDialog/PluginSecretFieldDialog.stories.tsx @@ -1,7 +1,7 @@ +import { ConfigurationTypeFieldEnum } from "@saleor/types/globalTypes"; import { storiesOf } from "@storybook/react"; import React from "react"; -import { ConfigurationTypeFieldEnum } from "@saleor/types/globalTypes"; import Decorator from "../../../storybook/Decorator"; import PluginSecretFieldDialog, { PluginSecretFieldDialogProps diff --git a/src/plugins/components/PluginSecretFieldDialog/PluginSecretFieldDialog.tsx b/src/plugins/components/PluginSecretFieldDialog/PluginSecretFieldDialog.tsx index 82bea2488..0cfdda1b2 100644 --- a/src/plugins/components/PluginSecretFieldDialog/PluginSecretFieldDialog.tsx +++ b/src/plugins/components/PluginSecretFieldDialog/PluginSecretFieldDialog.tsx @@ -4,9 +4,6 @@ import DialogActions from "@material-ui/core/DialogActions"; import DialogContent from "@material-ui/core/DialogContent"; import DialogTitle from "@material-ui/core/DialogTitle"; import TextField from "@material-ui/core/TextField"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import ConfirmButton, { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; @@ -17,6 +14,8 @@ import { maybe } from "@saleor/misc"; import { Plugin_plugin_configuration } from "@saleor/plugins/types/Plugin"; import { DialogProps } from "@saleor/types"; import { ConfigurationTypeFieldEnum } from "@saleor/types/globalTypes"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; export interface PluginSecretFieldDialogFormData { value: string; diff --git a/src/plugins/components/PluginSettings/PluginSettings.tsx b/src/plugins/components/PluginSettings/PluginSettings.tsx index d14aa9f53..b470ca9c4 100644 --- a/src/plugins/components/PluginSettings/PluginSettings.tsx +++ b/src/plugins/components/PluginSettings/PluginSettings.tsx @@ -2,15 +2,18 @@ import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; import makeStyles from "@material-ui/core/styles/makeStyles"; import TextField from "@material-ui/core/TextField"; +import Tooltip from "@material-ui/core/Tooltip"; +import Typography from "@material-ui/core/Typography"; +import InfoIcon from "@material-ui/icons/Info"; import CardTitle from "@saleor/components/CardTitle"; -import ControlledCheckbox from "@saleor/components/ControlledCheckbox"; +import ControlledSwitch from "@saleor/components/ControlledSwitch"; +import { Plugin_plugin_configuration } from "@saleor/plugins/types/Plugin"; import { UserError } from "@saleor/types"; import { ConfigurationTypeFieldEnum } from "@saleor/types/globalTypes"; +import { getFieldError } from "@saleor/utils/errors"; import React from "react"; import { useIntl } from "react-intl"; -import { Plugin_plugin_configuration } from "@saleor/plugins/types/Plugin"; -import { getFieldError } from "@saleor/utils/errors"; import { FormData } from "../PluginsDetailsPage"; interface PluginSettingsProps { @@ -32,7 +35,9 @@ const useStyles = makeStyles( item: { "&:not(:last-child)": { marginBottom: theme.spacing(3) - } + }, + alignItems: "center", + display: "flex" }, itemLabel: { fontWeight: 500 @@ -71,17 +76,30 @@ const PluginSettings: React.FC = ({ return (
{fieldData.type === ConfigurationTypeFieldEnum.BOOLEAN ? ( - + <> + + {fieldData.helpText && ( + + {fieldData.helpText} + + } + > + + + )} + ) : ( void; @@ -65,15 +65,13 @@ const PluginsDetailsPage: React.FC = props => { const classes = useStyles(props); const intl = useIntl(); const initialForm: FormData = { - active: maybe(() => plugin.active, false), - configuration: maybe(() => - plugin.configuration - .filter(field => !isSecretField(plugin.configuration, field.name)) - .map(field => ({ - ...field, - value: field.value || "" - })) - ) + active: plugin?.active || false, + configuration: plugin?.configuration + ?.filter(field => !isSecretField(plugin?.configuration || [], field.name)) + .map(field => ({ + ...field, + value: field.value || "" + })) }; return ( @@ -108,7 +106,7 @@ const PluginsDetailsPage: React.FC = props => { description: "header" }, { - pluginName: maybe(() => plugin.name, "...") + pluginName: getStringOrPlaceholder(plugin?.name) } )} /> @@ -129,8 +127,9 @@ const PluginsDetailsPage: React.FC = props => {
plugin.description, "")} - name={maybe(() => plugin.name, "")} + description={plugin?.description || ""} + errors={errors} + name={plugin?.name || ""} onChange={onChange} /> {data.configuration && ( @@ -143,25 +142,17 @@ const PluginsDetailsPage: React.FC = props => { description: "section header" })}
- - {intl.formatMessage({ - defaultMessage: - "This adress will be used to generate invoices and calculate shipping rates. Email adress you provide here will be used as a contact adress for your customers." - })} -
plugin.configuration, [])} + fields={plugin?.configuration || []} errors={errors} disabled={disabled} onChange={onChange} /> - {maybe(() => - plugin.configuration.some(field => - isSecretField(plugin.configuration, field.name) - ) + {plugin?.configuration.some(field => + isSecretField(plugin.configuration, field.name) ) && ( <> diff --git a/src/plugins/components/PluginsList/PluginsList.tsx b/src/plugins/components/PluginsList/PluginsList.tsx index 568e88910..37528e7c2 100644 --- a/src/plugins/components/PluginsList/PluginsList.tsx +++ b/src/plugins/components/PluginsList/PluginsList.tsx @@ -5,19 +5,19 @@ import TableFooter from "@material-ui/core/TableFooter"; import TableHead from "@material-ui/core/TableHead"; import TableRow from "@material-ui/core/TableRow"; import EditIcon from "@material-ui/icons/Edit"; -import React from "react"; -import { useIntl } from "react-intl"; - import ResponsiveTable from "@saleor/components/ResponsiveTable"; import Skeleton from "@saleor/components/Skeleton"; import StatusLabel from "@saleor/components/StatusLabel"; +import TableCellHeader from "@saleor/components/TableCellHeader"; import TablePagination from "@saleor/components/TablePagination"; import { translateBoolean } from "@saleor/intl"; import { maybe, renderCollection } from "@saleor/misc"; -import { ListProps, SortPage } from "@saleor/types"; import { PluginListUrlSortField } from "@saleor/plugins/urls"; -import TableCellHeader from "@saleor/components/TableCellHeader"; +import { ListProps, SortPage } from "@saleor/types"; import { getArrowDirection } from "@saleor/utils/sort"; +import React from "react"; +import { useIntl } from "react-intl"; + import { Plugins_plugins_edges_node } from "../../types/Plugins"; export interface PluginListProps diff --git a/src/plugins/components/PluginsListPage/PluginsListPage.tsx b/src/plugins/components/PluginsListPage/PluginsListPage.tsx index da4ead724..5075cfc64 100644 --- a/src/plugins/components/PluginsListPage/PluginsListPage.tsx +++ b/src/plugins/components/PluginsListPage/PluginsListPage.tsx @@ -1,19 +1,19 @@ -import React from "react"; import Card from "@material-ui/core/Card"; -import { useIntl } from "react-intl"; - import AppHeader from "@saleor/components/AppHeader"; import Container from "@saleor/components/Container"; +import FilterBar from "@saleor/components/FilterBar"; import PageHeader from "@saleor/components/PageHeader"; import { sectionNames } from "@saleor/intl"; +import { PluginListUrlSortField } from "@saleor/plugins/urls"; import { + FilterPageProps, PageListProps, SortPage, - FilterPageProps, TabPageProps } from "@saleor/types"; -import { PluginListUrlSortField } from "@saleor/plugins/urls"; -import FilterBar from "@saleor/components/FilterBar"; +import React from "react"; +import { useIntl } from "react-intl"; + import { Plugins_plugins_edges_node } from "../../types/Plugins"; import PluginsList from "../PluginsList/PluginsList"; import { diff --git a/src/plugins/components/PluginsListPage/filters.ts b/src/plugins/components/PluginsListPage/filters.ts index d4d1a384b..0e1ef8ae6 100644 --- a/src/plugins/components/PluginsListPage/filters.ts +++ b/src/plugins/components/PluginsListPage/filters.ts @@ -1,9 +1,8 @@ -import { defineMessages, IntlShape } from "react-intl"; - -import { FilterOpts } from "@saleor/types"; import { IFilter } from "@saleor/components/Filter"; -import { createBooleanField } from "@saleor/utils/filters/fields"; import { commonMessages } from "@saleor/intl"; +import { FilterOpts } from "@saleor/types"; +import { createBooleanField } from "@saleor/utils/filters/fields"; +import { defineMessages, IntlShape } from "react-intl"; export enum PluginFilterKeys { active = "active" diff --git a/src/plugins/fixtures.ts b/src/plugins/fixtures.ts index 17fbf19ba..fd0133132 100644 --- a/src/plugins/fixtures.ts +++ b/src/plugins/fixtures.ts @@ -1,4 +1,5 @@ import { ConfigurationTypeFieldEnum } from "@saleor/types/globalTypes"; + import { Plugin_plugin } from "./types/Plugin"; import { Plugins_plugins_edges_node } from "./types/Plugins"; diff --git a/src/plugins/index.tsx b/src/plugins/index.tsx index f88721f37..844ec4f1c 100644 --- a/src/plugins/index.tsx +++ b/src/plugins/index.tsx @@ -1,20 +1,20 @@ +import { sectionNames } from "@saleor/intl"; +import { asSortParams } from "@saleor/utils/sort"; import { parse as parseQs } from "qs"; import React from "react"; import { useIntl } from "react-intl"; import { Route, RouteComponentProps, Switch } from "react-router-dom"; -import { sectionNames } from "@saleor/intl"; -import { asSortParams } from "@saleor/utils/sort"; import { WindowTitle } from "../components/WindowTitle"; import { pluginListPath, PluginListUrlQueryParams, + PluginListUrlSortField, pluginPath, - PluginUrlQueryParams, - PluginListUrlSortField + PluginUrlQueryParams } from "./urls"; -import PluginsDetailsComponent from "./views/PluginsDetails"; import PluginsListComponent from "./views/PluginList"; +import PluginsDetailsComponent from "./views/PluginsDetails"; const PluginList: React.FC> = ({ location }) => { const qs = parseQs(location.search.substr(1)); diff --git a/src/plugins/mutations.ts b/src/plugins/mutations.ts index 9a23fada4..ce6419de5 100644 --- a/src/plugins/mutations.ts +++ b/src/plugins/mutations.ts @@ -1,16 +1,17 @@ +import { pluginErrorFragment } from "@saleor/fragments/errors"; +import { pluginsDetailsFragment } from "@saleor/fragments/plugins"; import gql from "graphql-tag"; import { TypedMutation } from "../mutations"; -import { pluginsDetailsFragment } from "./queries"; import { PluginUpdate, PluginUpdateVariables } from "./types/PluginUpdate"; const pluginUpdate = gql` ${pluginsDetailsFragment} + ${pluginErrorFragment} mutation PluginUpdate($id: ID!, $input: PluginUpdateInput!) { pluginUpdate(id: $id, input: $input) { - errors { - field - message + errors: pluginsErrors { + ...PluginErrorFragment } plugin { ...PluginsDetailsFragment diff --git a/src/plugins/queries.ts b/src/plugins/queries.ts index c3003fa81..801d8436f 100644 --- a/src/plugins/queries.ts +++ b/src/plugins/queries.ts @@ -1,33 +1,14 @@ +import { + pluginsDetailsFragment, + pluginsFragment +} from "@saleor/fragments/plugins"; +import makeQuery from "@saleor/hooks/makeQuery"; import gql from "graphql-tag"; -import makeQuery from "@saleor/hooks/makeQuery"; import { TypedQuery } from "../queries"; import { Plugin, PluginVariables } from "./types/Plugin"; import { Plugins, PluginsVariables } from "./types/Plugins"; -export const pluginsFragment = gql` - fragment PluginFragment on Plugin { - id - name - description - active - } -`; - -export const pluginsDetailsFragment = gql` - ${pluginsFragment} - fragment PluginsDetailsFragment on Plugin { - ...PluginFragment - configuration { - name - type - value - helpText - label - } - } -`; - const pluginsList = gql` ${pluginsFragment} query Plugins( diff --git a/src/plugins/types/PluginUpdate.ts b/src/plugins/types/PluginUpdate.ts index c420bf0b0..6aa937c5a 100644 --- a/src/plugins/types/PluginUpdate.ts +++ b/src/plugins/types/PluginUpdate.ts @@ -2,16 +2,16 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { PluginUpdateInput, ConfigurationTypeFieldEnum } from "./../../types/globalTypes"; +import { PluginUpdateInput, PluginErrorCode, ConfigurationTypeFieldEnum } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: PluginUpdate // ==================================================== export interface PluginUpdate_pluginUpdate_errors { - __typename: "Error"; + __typename: "PluginError"; + code: PluginErrorCode; field: string | null; - message: string | null; } export interface PluginUpdate_pluginUpdate_plugin_configuration { diff --git a/src/plugins/urls.ts b/src/plugins/urls.ts index c6be657c5..b5bc8e040 100644 --- a/src/plugins/urls.ts +++ b/src/plugins/urls.ts @@ -2,12 +2,12 @@ import { stringify as stringifyQs } from "qs"; import urlJoin from "url-join"; import { + ActiveTab, Dialog, + Filters, Pagination, SingleAction, Sort, - Filters, - ActiveTab, TabActionDialog } from "../types"; diff --git a/src/plugins/utils.ts b/src/plugins/utils.ts index 5d10d2115..9f7a73eaa 100644 --- a/src/plugins/utils.ts +++ b/src/plugins/utils.ts @@ -1,4 +1,5 @@ import { ConfigurationTypeFieldEnum } from "@saleor/types/globalTypes"; + import { Plugin_plugin_configuration } from "./types/Plugin"; export function isSecretField( diff --git a/src/plugins/views/PluginList/PluginList.tsx b/src/plugins/views/PluginList/PluginList.tsx index e46efa943..5e824e97d 100644 --- a/src/plugins/views/PluginList/PluginList.tsx +++ b/src/plugins/views/PluginList/PluginList.tsx @@ -1,41 +1,41 @@ +import DeleteFilterTabDialog from "@saleor/components/DeleteFilterTabDialog"; +import SaveFilterTabDialog, { + SaveFilterTabDialogFormData +} from "@saleor/components/SaveFilterTabDialog"; import { configurationMenuUrl } from "@saleor/configuration"; import useListSettings from "@saleor/hooks/useListSettings"; import useNavigator from "@saleor/hooks/useNavigator"; import usePaginator, { createPaginationState } from "@saleor/hooks/usePaginator"; +import useShop from "@saleor/hooks/useShop"; import { maybe } from "@saleor/misc"; import { ListViews } from "@saleor/types"; +import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; +import createFilterHandlers from "@saleor/utils/handlers/filterHandlers"; +import createSortHandler from "@saleor/utils/handlers/sortHandler"; +import { getSortParams } from "@saleor/utils/sort"; import React from "react"; -import { getSortParams } from "@saleor/utils/sort"; -import createSortHandler from "@saleor/utils/handlers/sortHandler"; -import createFilterHandlers from "@saleor/utils/handlers/filterHandlers"; -import useShop from "@saleor/hooks/useShop"; -import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; -import SaveFilterTabDialog, { - SaveFilterTabDialogFormData -} from "@saleor/components/SaveFilterTabDialog"; -import DeleteFilterTabDialog from "@saleor/components/DeleteFilterTabDialog"; import PluginsListPage from "../../components/PluginsListPage/PluginsListPage"; import { usePluginsListQuery } from "../../queries"; import { - PluginListUrlQueryParams, pluginListUrl, - pluginUrl, - PluginListUrlDialog + PluginListUrlDialog, + PluginListUrlQueryParams, + pluginUrl } from "../../urls"; -import { getSortQueryVariables } from "./sort"; import { - getFilterQueryParam, - getFilterOpts, - getFilterTabs, areFiltersApplied, - saveFilterTab, - getActiveFilters, deleteFilterTab, - getFilterVariables + getActiveFilters, + getFilterOpts, + getFilterQueryParam, + getFilterTabs, + getFilterVariables, + saveFilterTab } from "./filters"; +import { getSortQueryVariables } from "./sort"; interface PluginsListProps { params: PluginListUrlQueryParams; diff --git a/src/plugins/views/PluginList/filters.test.ts b/src/plugins/views/PluginList/filters.test.ts index fe14aa8b5..f6ad46aac 100644 --- a/src/plugins/views/PluginList/filters.test.ts +++ b/src/plugins/views/PluginList/filters.test.ts @@ -1,12 +1,12 @@ -import { createIntl } from "react-intl"; -import { stringify as stringifyQs } from "qs"; - -import { PluginListUrlFilters } from "@saleor/plugins/urls"; import { createFilterStructure } from "@saleor/plugins/components/PluginsListPage"; +import { PluginListUrlFilters } from "@saleor/plugins/urls"; import { getFilterQueryParams } from "@saleor/utils/filters"; import { getExistingKeys, setFilterOptsStatus } from "@test/filters"; import { config } from "@test/intl"; -import { getFilterVariables, getFilterQueryParam } from "./filters"; +import { stringify as stringifyQs } from "qs"; +import { createIntl } from "react-intl"; + +import { getFilterQueryParam, getFilterVariables } from "./filters"; describe("Filtering query params", () => { it("should be empty object if no params given", () => { diff --git a/src/plugins/views/PluginList/filters.ts b/src/plugins/views/PluginList/filters.ts index ae33062e3..297652fdd 100644 --- a/src/plugins/views/PluginList/filters.ts +++ b/src/plugins/views/PluginList/filters.ts @@ -1,20 +1,21 @@ -import { PluginFilterInput } from "@saleor/types/globalTypes"; -import { - PluginListFilterOpts, - PluginFilterKeys -} from "@saleor/plugins/components/PluginsListPage"; -import { maybe, parseBoolean } from "@saleor/misc"; import { IFilterElement } from "@saleor/components/Filter"; +import { maybe, parseBoolean } from "@saleor/misc"; import { - PluginListUrlFilters, - PluginListUrlFiltersEnum, - PluginListUrlQueryParams -} from "../../urls"; + PluginFilterKeys, + PluginListFilterOpts +} from "@saleor/plugins/components/PluginsListPage"; +import { PluginFilterInput } from "@saleor/types/globalTypes"; + import { createFilterTabUtils, createFilterUtils, getSingleValueQueryParam } from "../../../utils/filters"; +import { + PluginListUrlFilters, + PluginListUrlFiltersEnum, + PluginListUrlQueryParams +} from "../../urls"; export const PLUGIN_FILTERS_KEY = "pluginFilters"; diff --git a/src/plugins/views/PluginsDetails.tsx b/src/plugins/views/PluginsDetails.tsx index 8dcf88b13..74b719024 100644 --- a/src/plugins/views/PluginsDetails.tsx +++ b/src/plugins/views/PluginsDetails.tsx @@ -1,7 +1,4 @@ import DialogContentText from "@material-ui/core/DialogContentText"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import ActionDialog from "@saleor/components/ActionDialog"; import { WindowTitle } from "@saleor/components/WindowTitle"; import useNavigator from "@saleor/hooks/useNavigator"; @@ -9,7 +6,9 @@ import useNotifier from "@saleor/hooks/useNotifier"; import { commonMessages } from "@saleor/intl"; import { ConfigurationItemInput } from "@saleor/types/globalTypes"; import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; -import { maybe } from "../../misc"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import PluginsDetailsPage from "../components/PluginsDetailsPage"; import PluginSecretFieldDialog from "../components/PluginSecretFieldDialog"; import { TypedPluginUpdate } from "../mutations"; @@ -19,8 +18,8 @@ import { PluginUpdate } from "../types/PluginUpdate"; import { pluginListUrl, pluginUrl, - PluginUrlQueryParams, - PluginUrlDialog + PluginUrlDialog, + PluginUrlQueryParams } from "../urls"; import { isSecretField } from "../utils"; @@ -61,6 +60,7 @@ export const PluginsDetails: React.FC = ({ const handleUpdate = (data: PluginUpdate) => { if (data.pluginUpdate.errors.length === 0) { notify({ + status: "success", text: intl.formatMessage(commonMessages.savedChanges) }); closeModal(); @@ -72,10 +72,7 @@ export const PluginsDetails: React.FC = ({ {pluginDetails => ( {(pluginUpdate, pluginUpdateOpts) => { - const formErrors = maybe( - () => pluginUpdateOpts.data.pluginUpdate.errors, - [] - ); + const formErrors = pluginUpdateOpts.data?.pluginUpdate.errors || []; const handleFieldUpdate = (value: string) => pluginUpdate({ @@ -94,16 +91,14 @@ export const PluginsDetails: React.FC = ({ return ( <> - pluginDetails.data.plugin.name)} - /> + pluginDetails.data.plugin)} + plugin={pluginDetails.data?.plugin} onBack={() => navigate(pluginListUrl())} onClear={id => openModal("clear", { @@ -130,7 +125,7 @@ export const PluginsDetails: React.FC = ({ }) } /> - {maybe(() => pluginDetails.data.plugin.configuration) && ( + {pluginDetails.data?.plugin?.configuration && ( <> = ({ confirmButtonState={ !!params.action ? pluginUpdateOpts.status : "default" } - field={maybe(() => - pluginDetails.data.plugin.configuration.find( - field => field.name === params.id - ) + field={pluginDetails.data?.plugin?.configuration.find( + field => field.name === params.id )} onClose={closeModal} onConfirm={formData => handleFieldUpdate(formData.value)} diff --git a/src/productTypes/components/AssignAttributeDialog/AssignAttributeDialog.tsx b/src/productTypes/components/AssignAttributeDialog/AssignAttributeDialog.tsx index 96f392455..32040d27b 100644 --- a/src/productTypes/components/AssignAttributeDialog/AssignAttributeDialog.tsx +++ b/src/productTypes/components/AssignAttributeDialog/AssignAttributeDialog.tsx @@ -11,11 +11,6 @@ import TableCell from "@material-ui/core/TableCell"; import TableRow from "@material-ui/core/TableRow"; import TextField from "@material-ui/core/TextField"; import Typography from "@material-ui/core/Typography"; -import classNames from "classnames"; -import React from "react"; -import InfiniteScroll from "react-infinite-scroller"; -import { FormattedMessage, useIntl } from "react-intl"; - import Checkbox from "@saleor/components/Checkbox"; import ConfirmButton, { ConfirmButtonTransitionState @@ -30,7 +25,12 @@ import useSearchQuery from "@saleor/hooks/useSearchQuery"; import { buttonMessages } from "@saleor/intl"; import { maybe, renderCollection } from "@saleor/misc"; import { FetchMoreProps } from "@saleor/types"; -import { SearchAttributes_productType_availableAttributes_edges_node } from "../../hooks/useAvailableAttributeSearch/types/SearchAttributes"; +import classNames from "classnames"; +import React from "react"; +import InfiniteScroll from "react-infinite-scroller"; +import { FormattedMessage, useIntl } from "react-intl"; + +import { SearchAvailableAttributes_productType_availableAttributes_edges_node } from "../../hooks/useAvailableAttributeSearch/types/SearchAvailableAttributes"; const useStyles = makeStyles( theme => ({ @@ -63,7 +63,7 @@ export interface AssignAttributeDialogProps extends FetchMoreProps { confirmButtonState: ConfirmButtonTransitionState; errors: string[]; open: boolean; - attributes: SearchAttributes_productType_availableAttributes_edges_node[]; + attributes: SearchAvailableAttributes_productType_availableAttributes_edges_node[]; selected: string[]; onClose: () => void; onFetch: (query: string) => void; diff --git a/src/productTypes/components/ProductTypeAttributeEditDialog/ProductTypeAttributeEditDialog.tsx b/src/productTypes/components/ProductTypeAttributeEditDialog/ProductTypeAttributeEditDialog.tsx deleted file mode 100644 index 6a444d2f8..000000000 --- a/src/productTypes/components/ProductTypeAttributeEditDialog/ProductTypeAttributeEditDialog.tsx +++ /dev/null @@ -1,112 +0,0 @@ -import Button from "@material-ui/core/Button"; -import Dialog from "@material-ui/core/Dialog"; -import DialogActions from "@material-ui/core/DialogActions"; -import DialogContent from "@material-ui/core/DialogContent"; -import DialogTitle from "@material-ui/core/DialogTitle"; -import TextField from "@material-ui/core/TextField"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - -import Form from "@saleor/components/Form"; -import { FormSpacer } from "@saleor/components/FormSpacer"; -import ListField from "@saleor/components/ListField"; -import { buttonMessages } from "@saleor/intl"; -import { UserError } from "@saleor/types"; -import { getFieldError } from "@saleor/utils/errors"; - -export interface FormData { - name: string; - values: Array<{ - label: string; - value: string; - }>; -} - -export interface ProductTypeAttributeEditDialogProps { - disabled: boolean; - errors: UserError[]; - name: string; - opened: boolean; - title: string; - values: Array<{ - label: string; - value: string; - }>; - onClose: () => void; - onConfirm: (data: FormData) => void; -} - -const ProductTypeAttributeEditDialog: React.FC = ({ - disabled, - errors, - name, - opened, - title, - values, - onClose, - onConfirm -}) => { - const intl = useIntl(); - - const initialForm: FormData = { - name: name || "", - values: values || [] - }; - return ( - -
- {({ change, data }) => ( - <> - {title} - - - - - - - - - - - )} -
-
- ); -}; -ProductTypeAttributeEditDialog.displayName = "ProductTypeAttributeEditDialog"; -export default ProductTypeAttributeEditDialog; diff --git a/src/productTypes/components/ProductTypeAttributeEditDialog/index.ts b/src/productTypes/components/ProductTypeAttributeEditDialog/index.ts deleted file mode 100644 index 6344b380f..000000000 --- a/src/productTypes/components/ProductTypeAttributeEditDialog/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from "./ProductTypeAttributeEditDialog"; -export * from "./ProductTypeAttributeEditDialog"; diff --git a/src/productTypes/components/ProductTypeAttributeUnassignDialog/ProductTypeAttributeUnassignDialog.tsx b/src/productTypes/components/ProductTypeAttributeUnassignDialog/ProductTypeAttributeUnassignDialog.tsx index 5a1f2e077..98306692a 100644 --- a/src/productTypes/components/ProductTypeAttributeUnassignDialog/ProductTypeAttributeUnassignDialog.tsx +++ b/src/productTypes/components/ProductTypeAttributeUnassignDialog/ProductTypeAttributeUnassignDialog.tsx @@ -1,9 +1,8 @@ import DialogContentText from "@material-ui/core/DialogContentText"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import ActionDialog from "@saleor/components/ActionDialog"; import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; export interface ProductTypeAttributeUnassignDialogProps { attributeName: string; @@ -14,9 +13,7 @@ export interface ProductTypeAttributeUnassignDialogProps { onConfirm: () => void; } -const ProductTypeAttributeUnassignDialog: React.FC< - ProductTypeAttributeUnassignDialogProps -> = ({ +const ProductTypeAttributeUnassignDialog: React.FC = ({ attributeName, confirmButtonState, open, diff --git a/src/productTypes/components/ProductTypeAttributes/ProductTypeAttributes.tsx b/src/productTypes/components/ProductTypeAttributes/ProductTypeAttributes.tsx index 4141ad5d9..0487366bc 100644 --- a/src/productTypes/components/ProductTypeAttributes/ProductTypeAttributes.tsx +++ b/src/productTypes/components/ProductTypeAttributes/ProductTypeAttributes.tsx @@ -5,9 +5,6 @@ import { makeStyles } from "@material-ui/core/styles"; import TableCell from "@material-ui/core/TableCell"; import TableRow from "@material-ui/core/TableRow"; import DeleteIcon from "@material-ui/icons/Delete"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import CardTitle from "@saleor/components/CardTitle"; import Checkbox from "@saleor/components/Checkbox"; import ResponsiveTable from "@saleor/components/ResponsiveTable"; @@ -20,6 +17,9 @@ import TableHead from "@saleor/components/TableHead"; import { maybe, renderCollection, stopPropagation } from "@saleor/misc"; import { ListActions, ReorderAction } from "@saleor/types"; import { AttributeTypeEnum } from "@saleor/types/globalTypes"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { ProductTypeDetails_productType_productAttributes, ProductTypeDetails_productType_variantAttributes @@ -83,7 +83,7 @@ const ProductTypeAttributes: React.FC = props => { return ( = props => { } key={maybe(() => attribute.id)} index={attributeIndex || 0} - data-tc="id" - data-tc-id={maybe(() => attribute.id)} + data-test="id" + data-test-id={maybe(() => attribute.id)} > = props => { onChange={() => toggle(attribute.id)} /> - + {maybe(() => attribute.name) ? ( attribute.name ) : ( )} - + {maybe(() => attribute.slug) ? ( attribute.slug ) : ( diff --git a/src/productTypes/components/ProductTypeBulkAttributeUnassignDialog/ProductTypeBulkAttributeUnassignDialog.tsx b/src/productTypes/components/ProductTypeBulkAttributeUnassignDialog/ProductTypeBulkAttributeUnassignDialog.tsx index 234ce3ddb..965901488 100644 --- a/src/productTypes/components/ProductTypeBulkAttributeUnassignDialog/ProductTypeBulkAttributeUnassignDialog.tsx +++ b/src/productTypes/components/ProductTypeBulkAttributeUnassignDialog/ProductTypeBulkAttributeUnassignDialog.tsx @@ -1,9 +1,8 @@ import DialogContentText from "@material-ui/core/DialogContentText"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import ActionDialog from "@saleor/components/ActionDialog"; import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; export interface ProductTypeBulkAttributeUnassignDialogProps { attributeQuantity: number; diff --git a/src/productTypes/components/ProductTypeCreatePage/ProductTypeCreatePage.tsx b/src/productTypes/components/ProductTypeCreatePage/ProductTypeCreatePage.tsx index 3a11f5705..79568ae1c 100644 --- a/src/productTypes/components/ProductTypeCreatePage/ProductTypeCreatePage.tsx +++ b/src/productTypes/components/ProductTypeCreatePage/ProductTypeCreatePage.tsx @@ -1,12 +1,10 @@ -import React from "react"; -import { useIntl } from "react-intl"; - import AppHeader from "@saleor/components/AppHeader"; import CardSpacer from "@saleor/components/CardSpacer"; import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; import Container from "@saleor/components/Container"; import Form from "@saleor/components/Form"; import Grid from "@saleor/components/Grid"; +import Metadata, { MetadataFormData } from "@saleor/components/Metadata"; import PageHeader from "@saleor/components/PageHeader"; import SaveButtonBar from "@saleor/components/SaveButtonBar"; import { ChangeEvent, FormChange } from "@saleor/hooks/useForm"; @@ -15,11 +13,15 @@ import { sectionNames } from "@saleor/intl"; import { ProductTypeDetails_taxTypes } from "@saleor/productTypes/types/ProductTypeDetails"; import { UserError } from "@saleor/types"; import { WeightUnitsEnum } from "@saleor/types/globalTypes"; +import useMetadataChangeTrigger from "@saleor/utils/metadata/useMetadataChangeTrigger"; +import React from "react"; +import { useIntl } from "react-intl"; + import ProductTypeDetails from "../ProductTypeDetails/ProductTypeDetails"; import ProductTypeShipping from "../ProductTypeShipping/ProductTypeShipping"; import ProductTypeTaxes from "../ProductTypeTaxes/ProductTypeTaxes"; -export interface ProductTypeForm { +export interface ProductTypeForm extends MetadataFormData { name: string; isShippingRequired: boolean; taxType: string; @@ -39,7 +41,9 @@ export interface ProductTypeCreatePageProps { const formInitialData: ProductTypeForm = { isShippingRequired: false, + metadata: [], name: "", + privateMetadata: [], taxType: "", weight: 0 }; @@ -68,56 +72,65 @@ const ProductTypeCreatePage: React.FC = ({ }: ProductTypeCreatePageProps) => { const intl = useIntl(); const [taxTypeDisplayName, setTaxTypeDisplayName] = useStateFromProps(""); + const { + makeChangeHandler: makeMetadataChangeHandler + } = useMetadataChangeTrigger(); return (
- {({ change, data, hasChanged, submit }) => ( - - - {intl.formatMessage(sectionNames.productTypes)} - - - -
- - - - handleTaxTypeChange( - event, - taxTypes, - change, - setTaxTypeDisplayName - ) - } - /> -
-
- -
-
- -
- )} + {({ change, data, hasChanged, submit }) => { + const changeMetadata = makeMetadataChangeHandler(change); + + return ( + + + {intl.formatMessage(sectionNames.productTypes)} + + + +
+ + + + handleTaxTypeChange( + event, + taxTypes, + change, + setTaxTypeDisplayName + ) + } + /> + + +
+
+ +
+
+ +
+ ); + }}
); }; diff --git a/src/productTypes/components/ProductTypeDeleteDialog/ProductTypeDeleteDialog.tsx b/src/productTypes/components/ProductTypeDeleteDialog/ProductTypeDeleteDialog.tsx index fa64b7e1f..482f3ba98 100644 --- a/src/productTypes/components/ProductTypeDeleteDialog/ProductTypeDeleteDialog.tsx +++ b/src/productTypes/components/ProductTypeDeleteDialog/ProductTypeDeleteDialog.tsx @@ -1,9 +1,8 @@ import DialogContentText from "@material-ui/core/DialogContentText"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import ActionDialog from "@saleor/components/ActionDialog"; import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; export interface ProductTypeDeleteDialogProps { confirmButtonState: ConfirmButtonTransitionState; diff --git a/src/productTypes/components/ProductTypeDetails/ProductTypeDetails.tsx b/src/productTypes/components/ProductTypeDetails/ProductTypeDetails.tsx index 758fd36e6..abfde6ba6 100644 --- a/src/productTypes/components/ProductTypeDetails/ProductTypeDetails.tsx +++ b/src/productTypes/components/ProductTypeDetails/ProductTypeDetails.tsx @@ -2,13 +2,12 @@ import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; import { makeStyles } from "@material-ui/core/styles"; import TextField from "@material-ui/core/TextField"; -import React from "react"; -import { useIntl } from "react-intl"; - import CardTitle from "@saleor/components/CardTitle"; import { commonMessages } from "@saleor/intl"; import { UserError } from "@saleor/types"; import { getFieldError } from "@saleor/utils/errors"; +import React from "react"; +import { useIntl } from "react-intl"; const useStyles = makeStyles( { diff --git a/src/productTypes/components/ProductTypeDetailsPage/ProductTypeDetailsPage.tsx b/src/productTypes/components/ProductTypeDetailsPage/ProductTypeDetailsPage.tsx index 1737361f9..a4a5391df 100644 --- a/src/productTypes/components/ProductTypeDetailsPage/ProductTypeDetailsPage.tsx +++ b/src/productTypes/components/ProductTypeDetailsPage/ProductTypeDetailsPage.tsx @@ -1,6 +1,3 @@ -import React from "react"; -import { useIntl } from "react-intl"; - import AppHeader from "@saleor/components/AppHeader"; import CardSpacer from "@saleor/components/CardSpacer"; import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; @@ -8,6 +5,8 @@ import Container from "@saleor/components/Container"; import ControlledSwitch from "@saleor/components/ControlledSwitch"; import Form from "@saleor/components/Form"; import Grid from "@saleor/components/Grid"; +import Metadata from "@saleor/components/Metadata/Metadata"; +import { MetadataFormData } from "@saleor/components/Metadata/types"; import PageHeader from "@saleor/components/PageHeader"; import SaveButtonBar from "@saleor/components/SaveButtonBar"; import { ChangeEvent, FormChange } from "@saleor/hooks/useForm"; @@ -16,6 +15,11 @@ import { sectionNames } from "@saleor/intl"; import { maybe } from "@saleor/misc"; import { ListActions, ReorderEvent, UserError } from "@saleor/types"; import { AttributeTypeEnum, WeightUnitsEnum } from "@saleor/types/globalTypes"; +import { mapMetadataItemToInput } from "@saleor/utils/maps"; +import useMetadataChangeTrigger from "@saleor/utils/metadata/useMetadataChangeTrigger"; +import React from "react"; +import { useIntl } from "react-intl"; + import { ProductTypeDetails_productType, ProductTypeDetails_taxTypes @@ -30,7 +34,7 @@ interface ChoiceType { value: string; } -export interface ProductTypeForm { +export interface ProductTypeForm extends MetadataFormData { name: string; hasVariants: boolean; isShippingRequired: boolean; @@ -92,6 +96,12 @@ const ProductTypeDetailsPage: React.FC = ({ onSubmit }) => { const intl = useIntl(); + const { + isMetadataModified, + isPrivateMetadataModified, + makeChangeHandler: makeMetadataChangeHandler + } = useMetadataChangeTrigger(); + const [taxTypeDisplayName, setTaxTypeDisplayName] = useStateFromProps( maybe(() => productType.taxType.description, "") ); @@ -104,7 +114,9 @@ const ProductTypeDetailsPage: React.FC = ({ maybe(() => productType.isShippingRequired) !== undefined ? productType.isShippingRequired : false, + metadata: productType?.metadata?.map(mapMetadataItemToInput), name: maybe(() => productType.name) !== undefined ? productType.name : "", + privateMetadata: productType?.privateMetadata?.map(mapMetadataItemToInput), productAttributes: maybe(() => productType.productAttributes) !== undefined ? productType.productAttributes.map(attribute => ({ @@ -122,97 +134,117 @@ const ProductTypeDetailsPage: React.FC = ({ : [], weight: maybe(() => productType.weight.value) }; + + const handleSubmit = (data: ProductTypeForm) => { + const metadata = isMetadataModified ? data.metadata : undefined; + const privateMetadata = isPrivateMetadataModified + ? data.privateMetadata + : undefined; + + onSubmit({ + ...data, + metadata, + privateMetadata + }); + }; + return ( -
- {({ change, data, hasChanged, submit }) => ( - - - {intl.formatMessage(sectionNames.productTypes)} - - - -
- - - - handleTaxTypeChange( - event, - taxTypes, - change, - setTaxTypeDisplayName - ) - } - /> - - productType.productAttributes)} - disabled={disabled} - type={AttributeTypeEnum.PRODUCT} - onAttributeAssign={onAttributeAdd} - onAttributeClick={onAttributeClick} - onAttributeReorder={(event: ReorderEvent) => - onAttributeReorder(event, AttributeTypeEnum.PRODUCT) - } - onAttributeUnassign={onAttributeUnassign} - {...productAttributeList} - /> - - onHasVariantsToggle(event.target.value)} - /> - {data.hasVariants && ( - <> - - productType.variantAttributes)} - disabled={disabled} - type={AttributeTypeEnum.VARIANT} - onAttributeAssign={onAttributeAdd} - onAttributeClick={onAttributeClick} - onAttributeReorder={(event: ReorderEvent) => - onAttributeReorder(event, AttributeTypeEnum.VARIANT) - } - onAttributeUnassign={onAttributeUnassign} - {...variantAttributeList} - /> - - )} -
-
- -
-
- -
- )} + + {({ change, data, hasChanged, submit }) => { + const changeMetadata = makeMetadataChangeHandler(change); + + return ( + + + {intl.formatMessage(sectionNames.productTypes)} + + + +
+ + + + handleTaxTypeChange( + event, + taxTypes, + change, + setTaxTypeDisplayName + ) + } + /> + + productType.productAttributes)} + disabled={disabled} + type={AttributeTypeEnum.PRODUCT} + onAttributeAssign={onAttributeAdd} + onAttributeClick={onAttributeClick} + onAttributeReorder={(event: ReorderEvent) => + onAttributeReorder(event, AttributeTypeEnum.PRODUCT) + } + onAttributeUnassign={onAttributeUnassign} + {...productAttributeList} + /> + + onHasVariantsToggle(event.target.value)} + /> + {data.hasVariants && ( + <> + + productType.variantAttributes)} + disabled={disabled} + type={AttributeTypeEnum.VARIANT} + onAttributeAssign={onAttributeAdd} + onAttributeClick={onAttributeClick} + onAttributeReorder={(event: ReorderEvent) => + onAttributeReorder(event, AttributeTypeEnum.VARIANT) + } + onAttributeUnassign={onAttributeUnassign} + {...variantAttributeList} + /> + + )} + + +
+
+ +
+
+ +
+ ); + }}
); }; diff --git a/src/productTypes/components/ProductTypeList/ProductTypeList.tsx b/src/productTypes/components/ProductTypeList/ProductTypeList.tsx index ef748da3f..14eefbdad 100644 --- a/src/productTypes/components/ProductTypeList/ProductTypeList.tsx +++ b/src/productTypes/components/ProductTypeList/ProductTypeList.tsx @@ -4,17 +4,17 @@ import TableCell from "@material-ui/core/TableCell"; import TableFooter from "@material-ui/core/TableFooter"; import TableRow from "@material-ui/core/TableRow"; import Typography from "@material-ui/core/Typography"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import Checkbox from "@saleor/components/Checkbox"; import ResponsiveTable from "@saleor/components/ResponsiveTable"; import Skeleton from "@saleor/components/Skeleton"; +import TableCellHeader from "@saleor/components/TableCellHeader"; import TableHead from "@saleor/components/TableHead"; import TablePagination from "@saleor/components/TablePagination"; import { ProductTypeListUrlSortField } from "@saleor/productTypes/urls"; import { getArrowDirection } from "@saleor/utils/sort"; -import TableCellHeader from "@saleor/components/TableCellHeader"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { maybe, renderCollection } from "../../../misc"; import { ListActions, ListProps, SortPage } from "../../../types"; import { ProductTypeList_productTypes_edges_node } from "../../types/ProductTypeList"; @@ -142,8 +142,8 @@ const ProductTypeList: React.FC = props => { key={productType ? productType.id : "skeleton"} onClick={productType ? onRowClick(productType.id) : undefined} selected={isSelected} - data-tc="id" - data-tc-id={maybe(() => productType.id)} + data-test="id" + data-test-id={maybe(() => productType.id)} > = props => { {productType ? ( <> - {productType.name} + {productType.name} {maybe(() => productType.hasVariants) ? intl.formatMessage({ diff --git a/src/productTypes/components/ProductTypeListPage/ProductTypeListPage.tsx b/src/productTypes/components/ProductTypeListPage/ProductTypeListPage.tsx index 647ae7ada..dc1e2482b 100644 --- a/src/productTypes/components/ProductTypeListPage/ProductTypeListPage.tsx +++ b/src/productTypes/components/ProductTypeListPage/ProductTypeListPage.tsx @@ -1,20 +1,20 @@ import Button from "@material-ui/core/Button"; import Card from "@material-ui/core/Card"; +import AppHeader from "@saleor/components/AppHeader"; +import Container from "@saleor/components/Container"; +import FilterBar from "@saleor/components/FilterBar"; +import PageHeader from "@saleor/components/PageHeader"; +import { sectionNames } from "@saleor/intl"; +import { ProductTypeListUrlSortField } from "@saleor/productTypes/urls"; import React from "react"; import { FormattedMessage, useIntl } from "react-intl"; -import AppHeader from "@saleor/components/AppHeader"; -import Container from "@saleor/components/Container"; -import PageHeader from "@saleor/components/PageHeader"; -import FilterBar from "@saleor/components/FilterBar"; -import { sectionNames } from "@saleor/intl"; -import { ProductTypeListUrlSortField } from "@saleor/productTypes/urls"; import { + FilterPageProps, ListActions, PageListProps, - FilterPageProps, - TabPageProps, - SortPage + SortPage, + TabPageProps } from "../../../types"; import { ProductTypeList_productTypes_edges_node } from "../../types/ProductTypeList"; import ProductTypeList from "../ProductTypeList"; diff --git a/src/productTypes/components/ProductTypeListPage/filters.ts b/src/productTypes/components/ProductTypeListPage/filters.ts index c6664e09c..0ec157d8b 100644 --- a/src/productTypes/components/ProductTypeListPage/filters.ts +++ b/src/productTypes/components/ProductTypeListPage/filters.ts @@ -1,13 +1,12 @@ -import { defineMessages, IntlShape } from "react-intl"; - +import { IFilter } from "@saleor/components/Filter"; +import { commonMessages } from "@saleor/intl"; import { FilterOpts } from "@saleor/types"; import { ProductTypeConfigurable, ProductTypeEnum } from "@saleor/types/globalTypes"; -import { IFilter } from "@saleor/components/Filter"; -import { commonMessages } from "@saleor/intl"; import { createOptionsField } from "@saleor/utils/filters/fields"; +import { defineMessages, IntlShape } from "react-intl"; export enum ProductTypeFilterKeys { configurable = "configurable", diff --git a/src/productTypes/components/ProductTypeShipping/ProductTypeShipping.tsx b/src/productTypes/components/ProductTypeShipping/ProductTypeShipping.tsx index cb8ca105f..4d054524b 100644 --- a/src/productTypes/components/ProductTypeShipping/ProductTypeShipping.tsx +++ b/src/productTypes/components/ProductTypeShipping/ProductTypeShipping.tsx @@ -1,11 +1,10 @@ import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; import TextField from "@material-ui/core/TextField"; -import React from "react"; -import { useIntl } from "react-intl"; - import CardTitle from "@saleor/components/CardTitle"; import { ControlledCheckbox } from "@saleor/components/ControlledCheckbox"; +import React from "react"; +import { useIntl } from "react-intl"; interface ProductTypeShippingProps { data: { diff --git a/src/productTypes/components/ProductTypeTaxes/ProductTypeTaxes.tsx b/src/productTypes/components/ProductTypeTaxes/ProductTypeTaxes.tsx index b1f972978..7a355520e 100644 --- a/src/productTypes/components/ProductTypeTaxes/ProductTypeTaxes.tsx +++ b/src/productTypes/components/ProductTypeTaxes/ProductTypeTaxes.tsx @@ -1,12 +1,12 @@ import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; import { makeStyles } from "@material-ui/core/styles"; -import React from "react"; -import { useIntl } from "react-intl"; - import CardTitle from "@saleor/components/CardTitle"; import SingleAutocompleteSelectField from "@saleor/components/SingleAutocompleteSelectField"; import { ProductTypeDetails_taxTypes } from "@saleor/productTypes/types/ProductTypeDetails"; +import React from "react"; +import { useIntl } from "react-intl"; + import { maybe } from "../../../misc"; import { ProductTypeForm } from "../ProductTypeDetailsPage/ProductTypeDetailsPage"; diff --git a/src/productTypes/containers/ProductTypeOperations.tsx b/src/productTypes/containers/ProductTypeOperations.tsx index 6fdc327d3..b50847d4f 100644 --- a/src/productTypes/containers/ProductTypeOperations.tsx +++ b/src/productTypes/containers/ProductTypeOperations.tsx @@ -1,14 +1,17 @@ +import { + ProductTypeDetailsFragment, + ProductTypeDetailsFragment_productAttributes +} from "@saleor/fragments/types/ProductTypeDetailsFragment"; +import { AttributeTypeEnum, ReorderInput } from "@saleor/types/globalTypes"; import React from "react"; import { MutationFunction } from "react-apollo"; -import { AttributeTypeEnum, ReorderInput } from "@saleor/types/globalTypes"; import { getMutationProviderData } from "../../misc"; import { PartialMutationProviderOutput } from "../../types"; import { ProductTypeAttributeReorderMutation, TypedAssignAttributeMutation, TypedProductTypeDeleteMutation, - TypedProductTypeUpdateMutation, TypedUnassignAttributeMutation } from "../mutations"; import { @@ -23,23 +26,13 @@ import { ProductTypeDelete, ProductTypeDeleteVariables } from "../types/ProductTypeDelete"; -import { - ProductTypeDetailsFragment, - ProductTypeDetailsFragment_productAttributes -} from "../types/ProductTypeDetailsFragment"; -import { - ProductTypeUpdate, - ProductTypeUpdateVariables -} from "../types/ProductTypeUpdate"; import { UnassignAttribute, UnassignAttributeVariables } from "../types/UnassignAttribute"; function moveAttribute( - attributes: - | ProductTypeDetailsFragment_productAttributes[] - | ProductTypeDetailsFragment_productAttributes[], + attributes: ProductTypeDetailsFragment_productAttributes[], move: ReorderInput ) { const attributeIndex = attributes.findIndex( @@ -77,17 +70,12 @@ interface ProductTypeOperationsProps { ProductTypeAttributeReorder, ProductTypeAttributeReorderVariables >; - updateProductType: PartialMutationProviderOutput< - ProductTypeUpdate, - ProductTypeUpdateVariables - >; }) => React.ReactNode; productType: ProductTypeDetailsFragment; onAssignAttribute: (data: AssignAttribute) => void; onUnassignAttribute: (data: UnassignAttribute) => void; onProductTypeAttributeReorder: (data: ProductTypeAttributeReorder) => void; onProductTypeDelete: (data: ProductTypeDelete) => void; - onProductTypeUpdate: (data: ProductTypeUpdate) => void; } const ProductTypeOperations: React.FC = ({ @@ -96,85 +84,72 @@ const ProductTypeOperations: React.FC = ({ onAssignAttribute, onUnassignAttribute, onProductTypeAttributeReorder, - onProductTypeDelete, - onProductTypeUpdate + onProductTypeDelete }) => ( {(...deleteProductType) => ( - - {(...updateProductType) => ( - - {(...assignAttribute) => ( - - {(...unassignAttribute) => ( - - {( - reorderAttributeMutation, - reorderAttributeMutationResult - ) => { - const reorderAttributeMutationFn: MutationFunction< - ProductTypeAttributeReorder, - ProductTypeAttributeReorderVariables - > = opts => { - const optimisticResponse: ProductTypeAttributeReorder = { - productTypeReorderAttributes: { - __typename: "ProductTypeReorderAttributes" as "ProductTypeReorderAttributes", - errors: [], - productType: { - ...productType, - productAttributes: - opts.variables.type === - AttributeTypeEnum.PRODUCT - ? moveAttribute( - productType.productAttributes, - opts.variables.move - ) - : productType.productAttributes, - variantAttributes: - opts.variables.type === - AttributeTypeEnum.VARIANT - ? moveAttribute( - productType.variantAttributes, - opts.variables.move - ) - : productType.variantAttributes - } - } - }; - return reorderAttributeMutation({ - ...opts, - optimisticResponse - }); - }; + + {(...assignAttribute) => ( + + {(...unassignAttribute) => ( + + {(reorderAttributeMutation, reorderAttributeMutationResult) => { + const reorderAttributeMutationFn: MutationFunction< + ProductTypeAttributeReorder, + ProductTypeAttributeReorderVariables + > = opts => { + const optimisticResponse: ProductTypeAttributeReorder = { + productTypeReorderAttributes: { + __typename: "ProductTypeReorderAttributes" as "ProductTypeReorderAttributes", + errors: [], + productType: { + ...productType, + productAttributes: + opts.variables.type === AttributeTypeEnum.PRODUCT + ? moveAttribute( + productType.productAttributes, + opts.variables.move + ) + : productType.productAttributes, + variantAttributes: + opts.variables.type === AttributeTypeEnum.VARIANT + ? moveAttribute( + productType.variantAttributes, + opts.variables.move + ) + : productType.variantAttributes + } + } + }; + return reorderAttributeMutation({ + ...opts, + optimisticResponse + }); + }; - return children({ - assignAttribute: getMutationProviderData( - ...assignAttribute - ), - deleteProductType: getMutationProviderData( - ...deleteProductType - ), - reorderAttribute: getMutationProviderData( - reorderAttributeMutationFn, - reorderAttributeMutationResult - ), - unassignAttribute: getMutationProviderData( - ...unassignAttribute - ), - updateProductType: getMutationProviderData( - ...updateProductType - ) - }); - }} - - )} - + return children({ + assignAttribute: getMutationProviderData( + ...assignAttribute + ), + deleteProductType: getMutationProviderData( + ...deleteProductType + ), + reorderAttribute: getMutationProviderData( + reorderAttributeMutationFn, + reorderAttributeMutationResult + ), + unassignAttribute: getMutationProviderData( + ...unassignAttribute + ) + }); + }} + )} - + )} - + )} ); diff --git a/src/productTypes/fixtures.ts b/src/productTypes/fixtures.ts index ffd35d801..f8400876c 100644 --- a/src/productTypes/fixtures.ts +++ b/src/productTypes/fixtures.ts @@ -2,7 +2,8 @@ import { SearchProductTypes_search_edges_node, SearchProductTypes_search_edges_node_productAttributes } from "@saleor/searches/types/SearchProductTypes"; -import { AttributeInputTypeEnum } from "../types/globalTypes"; + +import { AttributeInputTypeEnum, WeightUnitsEnum } from "../types/globalTypes"; import { ProductTypeDetails_productType } from "./types/ProductTypeDetails"; import { ProductTypeList_productTypes_edges_node } from "./types/ProductTypeList"; @@ -468,9 +469,8 @@ export const attributes: SearchProductTypes_search_edges_node_productAttributes[ } ].map(edge => edge.node); -export const productTypes: Array< - SearchProductTypes_search_edges_node & ProductTypeList_productTypes_edges_node -> = [ +export const productTypes: Array = [ { __typename: "ProductType" as "ProductType", hasVariants: true, @@ -550,7 +550,15 @@ export const productType: ProductTypeDetails_productType = { hasVariants: false, id: "UHJvZHVjdFR5cGU6NQ==", isShippingRequired: false, + metadata: [ + { + __typename: "MetadataItem", + key: "integration.id", + value: "100023123" + } + ], name: "E-books", + privateMetadata: [], productAttributes: [ { __typename: "Attribute" as "Attribute", @@ -601,7 +609,7 @@ export const productType: ProductTypeDetails_productType = { ], weight: { __typename: "Weight", - unit: "kg", + unit: WeightUnitsEnum.KG, value: 7.82 } }; diff --git a/src/productTypes/hooks/useAvailableAttributeSearch/index.tsx b/src/productTypes/hooks/useAvailableAttributeSearch/index.tsx index 6a3d7037d..bbc26d5e8 100644 --- a/src/productTypes/hooks/useAvailableAttributeSearch/index.tsx +++ b/src/productTypes/hooks/useAvailableAttributeSearch/index.tsx @@ -1,15 +1,15 @@ +import { pageInfoFragment } from "@saleor/fragments/pageInfo"; +import makeSearch from "@saleor/hooks/makeSearch"; import gql from "graphql-tag"; -import makeSearch from "@saleor/hooks/makeSearch"; -import { pageInfoFragment } from "@saleor/queries"; import { - SearchAttributes, - SearchAttributesVariables -} from "./types/SearchAttributes"; + SearchAvailableAttributes, + SearchAvailableAttributesVariables +} from "./types/SearchAvailableAttributes"; export const searchAttributes = gql` ${pageInfoFragment} - query SearchAttributes( + query SearchAvailableAttributes( $id: ID! $after: String $first: Int! @@ -37,35 +37,36 @@ export const searchAttributes = gql` } `; -export default makeSearch( - searchAttributes, - result => - result.loadMore( - (prev, next) => { - if ( - prev.productType.availableAttributes.pageInfo.endCursor === - next.productType.availableAttributes.pageInfo.endCursor - ) { - return prev; - } - - return { - ...prev, - productType: { - ...prev.productType, - availableAttributes: { - ...prev.productType.availableAttributes, - edges: [ - ...prev.productType.availableAttributes.edges, - ...next.productType.availableAttributes.edges - ], - pageInfo: next.productType.availableAttributes.pageInfo - } - } - }; - }, - { - after: result.data.productType.availableAttributes.pageInfo.endCursor +export default makeSearch< + SearchAvailableAttributes, + SearchAvailableAttributesVariables +>(searchAttributes, result => + result.loadMore( + (prev, next) => { + if ( + prev.productType.availableAttributes.pageInfo.endCursor === + next.productType.availableAttributes.pageInfo.endCursor + ) { + return prev; } - ) + + return { + ...prev, + productType: { + ...prev.productType, + availableAttributes: { + ...prev.productType.availableAttributes, + edges: [ + ...prev.productType.availableAttributes.edges, + ...next.productType.availableAttributes.edges + ], + pageInfo: next.productType.availableAttributes.pageInfo + } + } + }; + }, + { + after: result.data.productType.availableAttributes.pageInfo.endCursor + } + ) ); diff --git a/src/productTypes/hooks/useAvailableAttributeSearch/types/SearchAttributes.ts b/src/productTypes/hooks/useAvailableAttributeSearch/types/SearchAttributes.ts deleted file mode 100644 index b45411fa9..000000000 --- a/src/productTypes/hooks/useAvailableAttributeSearch/types/SearchAttributes.ts +++ /dev/null @@ -1,50 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -// This file was automatically generated and should not be edited. - -// ==================================================== -// GraphQL query operation: SearchAttributes -// ==================================================== - -export interface SearchAttributes_productType_availableAttributes_edges_node { - __typename: "Attribute"; - id: string; - name: string | null; - slug: string | null; -} - -export interface SearchAttributes_productType_availableAttributes_edges { - __typename: "AttributeCountableEdge"; - node: SearchAttributes_productType_availableAttributes_edges_node; -} - -export interface SearchAttributes_productType_availableAttributes_pageInfo { - __typename: "PageInfo"; - endCursor: string | null; - hasNextPage: boolean; - hasPreviousPage: boolean; - startCursor: string | null; -} - -export interface SearchAttributes_productType_availableAttributes { - __typename: "AttributeCountableConnection"; - edges: SearchAttributes_productType_availableAttributes_edges[]; - pageInfo: SearchAttributes_productType_availableAttributes_pageInfo; -} - -export interface SearchAttributes_productType { - __typename: "ProductType"; - id: string; - availableAttributes: SearchAttributes_productType_availableAttributes | null; -} - -export interface SearchAttributes { - productType: SearchAttributes_productType | null; -} - -export interface SearchAttributesVariables { - id: string; - after?: string | null; - first: number; - query: string; -} diff --git a/src/productTypes/hooks/useAvailableAttributeSearch/types/SearchAvailableAttributes.ts b/src/productTypes/hooks/useAvailableAttributeSearch/types/SearchAvailableAttributes.ts new file mode 100644 index 000000000..9956975e7 --- /dev/null +++ b/src/productTypes/hooks/useAvailableAttributeSearch/types/SearchAvailableAttributes.ts @@ -0,0 +1,50 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL query operation: SearchAvailableAttributes +// ==================================================== + +export interface SearchAvailableAttributes_productType_availableAttributes_edges_node { + __typename: "Attribute"; + id: string; + name: string | null; + slug: string | null; +} + +export interface SearchAvailableAttributes_productType_availableAttributes_edges { + __typename: "AttributeCountableEdge"; + node: SearchAvailableAttributes_productType_availableAttributes_edges_node; +} + +export interface SearchAvailableAttributes_productType_availableAttributes_pageInfo { + __typename: "PageInfo"; + endCursor: string | null; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string | null; +} + +export interface SearchAvailableAttributes_productType_availableAttributes { + __typename: "AttributeCountableConnection"; + edges: SearchAvailableAttributes_productType_availableAttributes_edges[]; + pageInfo: SearchAvailableAttributes_productType_availableAttributes_pageInfo; +} + +export interface SearchAvailableAttributes_productType { + __typename: "ProductType"; + id: string; + availableAttributes: SearchAvailableAttributes_productType_availableAttributes | null; +} + +export interface SearchAvailableAttributes { + productType: SearchAvailableAttributes_productType | null; +} + +export interface SearchAvailableAttributesVariables { + id: string; + after?: string | null; + first: number; + query: string; +} diff --git a/src/productTypes/index.tsx b/src/productTypes/index.tsx index d97a8be5c..7c3cc533d 100644 --- a/src/productTypes/index.tsx +++ b/src/productTypes/index.tsx @@ -1,18 +1,18 @@ +import { sectionNames } from "@saleor/intl"; +import { asSortParams } from "@saleor/utils/sort"; import { parse as parseQs } from "qs"; import React from "react"; import { useIntl } from "react-intl"; import { Route, RouteComponentProps, Switch } from "react-router-dom"; -import { sectionNames } from "@saleor/intl"; -import { asSortParams } from "@saleor/utils/sort"; import { WindowTitle } from "../components/WindowTitle"; import { productTypeAddPath, productTypeListPath, ProductTypeListUrlQueryParams, + ProductTypeListUrlSortField, productTypePath, - ProductTypeUrlQueryParams, - ProductTypeListUrlSortField + ProductTypeUrlQueryParams } from "./urls"; import ProductTypeCreate from "./views/ProductTypeCreate"; import ProductTypeListComponent from "./views/ProductTypeList"; diff --git a/src/productTypes/mutations.ts b/src/productTypes/mutations.ts index 7d103d756..bd73b86b3 100644 --- a/src/productTypes/mutations.ts +++ b/src/productTypes/mutations.ts @@ -1,7 +1,8 @@ +import { productTypeDetailsFragment } from "@saleor/fragments/productTypes"; +import makeMutation from "@saleor/hooks/makeMutation"; import gql from "graphql-tag"; import { TypedMutation } from "../mutations"; -import { productTypeDetailsFragment } from "./queries"; import { AssignAttribute, AssignAttributeVariables @@ -78,7 +79,7 @@ export const productTypeUpdateMutation = gql` } } `; -export const TypedProductTypeUpdateMutation = TypedMutation< +export const useProductTypeUpdateMutation = makeMutation< ProductTypeUpdate, ProductTypeUpdateVariables >(productTypeUpdateMutation); diff --git a/src/productTypes/queries.ts b/src/productTypes/queries.ts index f6bdc47de..d0d289d0e 100644 --- a/src/productTypes/queries.ts +++ b/src/productTypes/queries.ts @@ -1,8 +1,12 @@ +import { pageInfoFragment } from "@saleor/fragments/pageInfo"; +import { + productTypeDetailsFragment, + productTypeFragment +} from "@saleor/fragments/productTypes"; +import makeQuery from "@saleor/hooks/makeQuery"; import gql from "graphql-tag"; -import { attributeFragment } from "@saleor/attributes/queries"; -import makeQuery from "@saleor/hooks/makeQuery"; -import { pageInfoFragment, TypedQuery } from "../queries"; +import { TypedQuery } from "../queries"; import { ProductTypeCreateData } from "./types/ProductTypeCreateData"; import { ProductTypeDetails, @@ -13,37 +17,6 @@ import { ProductTypeListVariables } from "./types/ProductTypeList"; -export const productTypeFragment = gql` - fragment ProductTypeFragment on ProductType { - id - name - hasVariants - isShippingRequired - taxType { - description - taxCode - } - } -`; - -export const productTypeDetailsFragment = gql` - ${attributeFragment} - ${productTypeFragment} - fragment ProductTypeDetailsFragment on ProductType { - ...ProductTypeFragment - productAttributes { - ...AttributeFragment - } - variantAttributes { - ...AttributeFragment - } - weight { - unit - value - } - } -`; - export const productTypeListQuery = gql` ${pageInfoFragment} ${productTypeFragment} diff --git a/src/productTypes/types/AssignAttribute.ts b/src/productTypes/types/AssignAttribute.ts index 2e9d3fb4a..365276b7a 100644 --- a/src/productTypes/types/AssignAttribute.ts +++ b/src/productTypes/types/AssignAttribute.ts @@ -2,7 +2,7 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { AttributeAssignInput } from "./../../types/globalTypes"; +import { AttributeAssignInput, WeightUnitsEnum } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: AssignAttribute @@ -20,6 +20,18 @@ export interface AssignAttribute_attributeAssign_productType_taxType { taxCode: string | null; } +export interface AssignAttribute_attributeAssign_productType_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface AssignAttribute_attributeAssign_productType_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface AssignAttribute_attributeAssign_productType_productAttributes { __typename: "Attribute"; id: string; @@ -42,7 +54,7 @@ export interface AssignAttribute_attributeAssign_productType_variantAttributes { export interface AssignAttribute_attributeAssign_productType_weight { __typename: "Weight"; - unit: string; + unit: WeightUnitsEnum; value: number; } @@ -53,6 +65,8 @@ export interface AssignAttribute_attributeAssign_productType { hasVariants: boolean; isShippingRequired: boolean; taxType: AssignAttribute_attributeAssign_productType_taxType | null; + metadata: (AssignAttribute_attributeAssign_productType_metadata | null)[]; + privateMetadata: (AssignAttribute_attributeAssign_productType_privateMetadata | null)[]; productAttributes: (AssignAttribute_attributeAssign_productType_productAttributes | null)[] | null; variantAttributes: (AssignAttribute_attributeAssign_productType_variantAttributes | null)[] | null; weight: AssignAttribute_attributeAssign_productType_weight | null; diff --git a/src/productTypes/types/AttributeCreate.ts b/src/productTypes/types/AttributeCreate.ts deleted file mode 100644 index 63548a3bc..000000000 --- a/src/productTypes/types/AttributeCreate.ts +++ /dev/null @@ -1,79 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -// This file was automatically generated and should not be edited. - -import { AttributeCreateInput, AttributeTypeEnum, TaxRateType } from "./../../types/globalTypes"; - -// ==================================================== -// GraphQL mutation operation: AttributeCreate -// ==================================================== - -export interface AttributeCreate_attributeCreate_errors { - __typename: "Error"; - field: string | null; - message: string | null; -} - -export interface AttributeCreate_attributeCreate_productType_productAttributes_values { - __typename: "AttributeValue"; - id: string; - name: string | null; - slug: string | null; -} - -export interface AttributeCreate_attributeCreate_productType_productAttributes { - __typename: "Attribute"; - id: string; - name: string | null; - slug: string | null; - values: (AttributeCreate_attributeCreate_productType_productAttributes_values | null)[] | null; -} - -export interface AttributeCreate_attributeCreate_productType_variantAttributes_values { - __typename: "AttributeValue"; - id: string; - name: string | null; - slug: string | null; -} - -export interface AttributeCreate_attributeCreate_productType_variantAttributes { - __typename: "Attribute"; - id: string; - name: string | null; - slug: string | null; - values: (AttributeCreate_attributeCreate_productType_variantAttributes_values | null)[] | null; -} - -export interface AttributeCreate_attributeCreate_productType_weight { - __typename: "Weight"; - unit: string; - value: number; -} - -export interface AttributeCreate_attributeCreate_productType { - __typename: "ProductType"; - id: string; - name: string; - hasVariants: boolean; - isShippingRequired: boolean; - taxRate: TaxRateType | null; - productAttributes: (AttributeCreate_attributeCreate_productType_productAttributes | null)[] | null; - variantAttributes: (AttributeCreate_attributeCreate_productType_variantAttributes | null)[] | null; - weight: AttributeCreate_attributeCreate_productType_weight | null; -} - -export interface AttributeCreate_attributeCreate { - __typename: "AttributeCreate"; - errors: AttributeCreate_attributeCreate_errors[] | null; - productType: AttributeCreate_attributeCreate_productType | null; -} - -export interface AttributeCreate { - attributeCreate: AttributeCreate_attributeCreate | null; -} - -export interface AttributeCreateVariables { - id: string; - input: AttributeCreateInput; - type: AttributeTypeEnum; -} diff --git a/src/productTypes/types/AttributeDelete.ts b/src/productTypes/types/AttributeDelete.ts deleted file mode 100644 index f62cd728f..000000000 --- a/src/productTypes/types/AttributeDelete.ts +++ /dev/null @@ -1,77 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -// This file was automatically generated and should not be edited. - -import { TaxRateType } from "./../../types/globalTypes"; - -// ==================================================== -// GraphQL mutation operation: AttributeDelete -// ==================================================== - -export interface AttributeDelete_attributeDelete_errors { - __typename: "Error"; - field: string | null; - message: string | null; -} - -export interface AttributeDelete_attributeDelete_productType_productAttributes_values { - __typename: "AttributeValue"; - id: string; - name: string | null; - slug: string | null; -} - -export interface AttributeDelete_attributeDelete_productType_productAttributes { - __typename: "Attribute"; - id: string; - name: string | null; - slug: string | null; - values: (AttributeDelete_attributeDelete_productType_productAttributes_values | null)[] | null; -} - -export interface AttributeDelete_attributeDelete_productType_variantAttributes_values { - __typename: "AttributeValue"; - id: string; - name: string | null; - slug: string | null; -} - -export interface AttributeDelete_attributeDelete_productType_variantAttributes { - __typename: "Attribute"; - id: string; - name: string | null; - slug: string | null; - values: (AttributeDelete_attributeDelete_productType_variantAttributes_values | null)[] | null; -} - -export interface AttributeDelete_attributeDelete_productType_weight { - __typename: "Weight"; - unit: string; - value: number; -} - -export interface AttributeDelete_attributeDelete_productType { - __typename: "ProductType"; - id: string; - name: string; - hasVariants: boolean; - isShippingRequired: boolean; - taxRate: TaxRateType | null; - productAttributes: (AttributeDelete_attributeDelete_productType_productAttributes | null)[] | null; - variantAttributes: (AttributeDelete_attributeDelete_productType_variantAttributes | null)[] | null; - weight: AttributeDelete_attributeDelete_productType_weight | null; -} - -export interface AttributeDelete_attributeDelete { - __typename: "AttributeDelete"; - errors: AttributeDelete_attributeDelete_errors[] | null; - productType: AttributeDelete_attributeDelete_productType | null; -} - -export interface AttributeDelete { - attributeDelete: AttributeDelete_attributeDelete | null; -} - -export interface AttributeDeleteVariables { - id: string; -} diff --git a/src/productTypes/types/AttributeFragment.ts b/src/productTypes/types/AttributeFragment.ts deleted file mode 100644 index 35a35464f..000000000 --- a/src/productTypes/types/AttributeFragment.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -// This file was automatically generated and should not be edited. - -// ==================================================== -// GraphQL fragment: AttributeFragment -// ==================================================== - -export interface AttributeFragment_values { - __typename: "AttributeValue"; - id: string; - name: string | null; - slug: string | null; -} - -export interface AttributeFragment { - __typename: "Attribute"; - id: string; - name: string | null; - slug: string | null; - values: (AttributeFragment_values | null)[] | null; -} diff --git a/src/productTypes/types/AttributeUpdate.ts b/src/productTypes/types/AttributeUpdate.ts deleted file mode 100644 index 08245fd55..000000000 --- a/src/productTypes/types/AttributeUpdate.ts +++ /dev/null @@ -1,45 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -// This file was automatically generated and should not be edited. - -import { AttributeUpdateInput } from "./../../types/globalTypes"; - -// ==================================================== -// GraphQL mutation operation: AttributeUpdate -// ==================================================== - -export interface AttributeUpdate_attributeUpdate_errors { - __typename: "Error"; - field: string | null; - message: string | null; -} - -export interface AttributeUpdate_attributeUpdate_attribute_values { - __typename: "AttributeValue"; - id: string; - name: string | null; - slug: string | null; -} - -export interface AttributeUpdate_attributeUpdate_attribute { - __typename: "Attribute"; - id: string; - name: string | null; - slug: string | null; - values: (AttributeUpdate_attributeUpdate_attribute_values | null)[] | null; -} - -export interface AttributeUpdate_attributeUpdate { - __typename: "AttributeUpdate"; - errors: AttributeUpdate_attributeUpdate_errors[] | null; - attribute: AttributeUpdate_attributeUpdate_attribute | null; -} - -export interface AttributeUpdate { - attributeUpdate: AttributeUpdate_attributeUpdate | null; -} - -export interface AttributeUpdateVariables { - id: string; - input: AttributeUpdateInput; -} diff --git a/src/productTypes/types/ProductTypeAttributeReorder.ts b/src/productTypes/types/ProductTypeAttributeReorder.ts index 6d4ca443d..bafaa3ca6 100644 --- a/src/productTypes/types/ProductTypeAttributeReorder.ts +++ b/src/productTypes/types/ProductTypeAttributeReorder.ts @@ -2,7 +2,7 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { ReorderInput, AttributeTypeEnum } from "./../../types/globalTypes"; +import { ReorderInput, AttributeTypeEnum, WeightUnitsEnum } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: ProductTypeAttributeReorder @@ -20,6 +20,18 @@ export interface ProductTypeAttributeReorder_productTypeReorderAttributes_produc taxCode: string | null; } +export interface ProductTypeAttributeReorder_productTypeReorderAttributes_productType_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface ProductTypeAttributeReorder_productTypeReorderAttributes_productType_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface ProductTypeAttributeReorder_productTypeReorderAttributes_productType_productAttributes { __typename: "Attribute"; id: string; @@ -42,7 +54,7 @@ export interface ProductTypeAttributeReorder_productTypeReorderAttributes_produc export interface ProductTypeAttributeReorder_productTypeReorderAttributes_productType_weight { __typename: "Weight"; - unit: string; + unit: WeightUnitsEnum; value: number; } @@ -53,6 +65,8 @@ export interface ProductTypeAttributeReorder_productTypeReorderAttributes_produc hasVariants: boolean; isShippingRequired: boolean; taxType: ProductTypeAttributeReorder_productTypeReorderAttributes_productType_taxType | null; + metadata: (ProductTypeAttributeReorder_productTypeReorderAttributes_productType_metadata | null)[]; + privateMetadata: (ProductTypeAttributeReorder_productTypeReorderAttributes_productType_privateMetadata | null)[]; productAttributes: (ProductTypeAttributeReorder_productTypeReorderAttributes_productType_productAttributes | null)[] | null; variantAttributes: (ProductTypeAttributeReorder_productTypeReorderAttributes_productType_variantAttributes | null)[] | null; weight: ProductTypeAttributeReorder_productTypeReorderAttributes_productType_weight | null; diff --git a/src/productTypes/types/ProductTypeCreate.ts b/src/productTypes/types/ProductTypeCreate.ts index 5993bbb02..559209242 100644 --- a/src/productTypes/types/ProductTypeCreate.ts +++ b/src/productTypes/types/ProductTypeCreate.ts @@ -2,7 +2,7 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { ProductTypeInput } from "./../../types/globalTypes"; +import { ProductTypeInput, WeightUnitsEnum } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: ProductTypeCreate @@ -20,6 +20,18 @@ export interface ProductTypeCreate_productTypeCreate_productType_taxType { taxCode: string | null; } +export interface ProductTypeCreate_productTypeCreate_productType_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface ProductTypeCreate_productTypeCreate_productType_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface ProductTypeCreate_productTypeCreate_productType_productAttributes { __typename: "Attribute"; id: string; @@ -42,7 +54,7 @@ export interface ProductTypeCreate_productTypeCreate_productType_variantAttribut export interface ProductTypeCreate_productTypeCreate_productType_weight { __typename: "Weight"; - unit: string; + unit: WeightUnitsEnum; value: number; } @@ -53,6 +65,8 @@ export interface ProductTypeCreate_productTypeCreate_productType { hasVariants: boolean; isShippingRequired: boolean; taxType: ProductTypeCreate_productTypeCreate_productType_taxType | null; + metadata: (ProductTypeCreate_productTypeCreate_productType_metadata | null)[]; + privateMetadata: (ProductTypeCreate_productTypeCreate_productType_privateMetadata | null)[]; productAttributes: (ProductTypeCreate_productTypeCreate_productType_productAttributes | null)[] | null; variantAttributes: (ProductTypeCreate_productTypeCreate_productType_variantAttributes | null)[] | null; weight: ProductTypeCreate_productTypeCreate_productType_weight | null; diff --git a/src/productTypes/types/ProductTypeDetails.ts b/src/productTypes/types/ProductTypeDetails.ts index c403f627d..fcfb86707 100644 --- a/src/productTypes/types/ProductTypeDetails.ts +++ b/src/productTypes/types/ProductTypeDetails.ts @@ -14,6 +14,18 @@ export interface ProductTypeDetails_productType_taxType { taxCode: string | null; } +export interface ProductTypeDetails_productType_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface ProductTypeDetails_productType_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface ProductTypeDetails_productType_productAttributes { __typename: "Attribute"; id: string; @@ -36,7 +48,7 @@ export interface ProductTypeDetails_productType_variantAttributes { export interface ProductTypeDetails_productType_weight { __typename: "Weight"; - unit: string; + unit: WeightUnitsEnum; value: number; } @@ -47,6 +59,8 @@ export interface ProductTypeDetails_productType { hasVariants: boolean; isShippingRequired: boolean; taxType: ProductTypeDetails_productType_taxType | null; + metadata: (ProductTypeDetails_productType_metadata | null)[]; + privateMetadata: (ProductTypeDetails_productType_privateMetadata | null)[]; productAttributes: (ProductTypeDetails_productType_productAttributes | null)[] | null; variantAttributes: (ProductTypeDetails_productType_variantAttributes | null)[] | null; weight: ProductTypeDetails_productType_weight | null; diff --git a/src/productTypes/types/ProductTypeUpdate.ts b/src/productTypes/types/ProductTypeUpdate.ts index 58c66afe2..c2e43a3fd 100644 --- a/src/productTypes/types/ProductTypeUpdate.ts +++ b/src/productTypes/types/ProductTypeUpdate.ts @@ -2,7 +2,7 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { ProductTypeInput } from "./../../types/globalTypes"; +import { ProductTypeInput, WeightUnitsEnum } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: ProductTypeUpdate @@ -20,6 +20,18 @@ export interface ProductTypeUpdate_productTypeUpdate_productType_taxType { taxCode: string | null; } +export interface ProductTypeUpdate_productTypeUpdate_productType_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface ProductTypeUpdate_productTypeUpdate_productType_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface ProductTypeUpdate_productTypeUpdate_productType_productAttributes { __typename: "Attribute"; id: string; @@ -42,7 +54,7 @@ export interface ProductTypeUpdate_productTypeUpdate_productType_variantAttribut export interface ProductTypeUpdate_productTypeUpdate_productType_weight { __typename: "Weight"; - unit: string; + unit: WeightUnitsEnum; value: number; } @@ -53,6 +65,8 @@ export interface ProductTypeUpdate_productTypeUpdate_productType { hasVariants: boolean; isShippingRequired: boolean; taxType: ProductTypeUpdate_productTypeUpdate_productType_taxType | null; + metadata: (ProductTypeUpdate_productTypeUpdate_productType_metadata | null)[]; + privateMetadata: (ProductTypeUpdate_productTypeUpdate_productType_privateMetadata | null)[]; productAttributes: (ProductTypeUpdate_productTypeUpdate_productType_productAttributes | null)[] | null; variantAttributes: (ProductTypeUpdate_productTypeUpdate_productType_variantAttributes | null)[] | null; weight: ProductTypeUpdate_productTypeUpdate_productType_weight | null; diff --git a/src/productTypes/types/UnassignAttribute.ts b/src/productTypes/types/UnassignAttribute.ts index b042fc6e3..555b11ade 100644 --- a/src/productTypes/types/UnassignAttribute.ts +++ b/src/productTypes/types/UnassignAttribute.ts @@ -2,6 +2,8 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. +import { WeightUnitsEnum } from "./../../types/globalTypes"; + // ==================================================== // GraphQL mutation operation: UnassignAttribute // ==================================================== @@ -18,6 +20,18 @@ export interface UnassignAttribute_attributeUnassign_productType_taxType { taxCode: string | null; } +export interface UnassignAttribute_attributeUnassign_productType_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface UnassignAttribute_attributeUnassign_productType_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface UnassignAttribute_attributeUnassign_productType_productAttributes { __typename: "Attribute"; id: string; @@ -40,7 +54,7 @@ export interface UnassignAttribute_attributeUnassign_productType_variantAttribut export interface UnassignAttribute_attributeUnassign_productType_weight { __typename: "Weight"; - unit: string; + unit: WeightUnitsEnum; value: number; } @@ -51,6 +65,8 @@ export interface UnassignAttribute_attributeUnassign_productType { hasVariants: boolean; isShippingRequired: boolean; taxType: UnassignAttribute_attributeUnassign_productType_taxType | null; + metadata: (UnassignAttribute_attributeUnassign_productType_metadata | null)[]; + privateMetadata: (UnassignAttribute_attributeUnassign_productType_privateMetadata | null)[]; productAttributes: (UnassignAttribute_attributeUnassign_productType_productAttributes | null)[] | null; variantAttributes: (UnassignAttribute_attributeUnassign_productType_variantAttributes | null)[] | null; weight: UnassignAttribute_attributeUnassign_productType_weight | null; diff --git a/src/productTypes/urls.ts b/src/productTypes/urls.ts index 5905a7b04..716a4daa2 100644 --- a/src/productTypes/urls.ts +++ b/src/productTypes/urls.ts @@ -8,8 +8,8 @@ import { Filters, Pagination, SingleAction, - TabActionDialog, - Sort + Sort, + TabActionDialog } from "../types"; const productTypeSection = "/product-types/"; diff --git a/src/productTypes/views/ProductTypeCreate.tsx b/src/productTypes/views/ProductTypeCreate.tsx index f116699ca..80317b77a 100644 --- a/src/productTypes/views/ProductTypeCreate.tsx +++ b/src/productTypes/views/ProductTypeCreate.tsx @@ -1,9 +1,14 @@ -import React from "react"; -import { useIntl } from "react-intl"; - import { WindowTitle } from "@saleor/components/WindowTitle"; import useNavigator from "@saleor/hooks/useNavigator"; import useNotifier from "@saleor/hooks/useNotifier"; +import createMetadataCreateHandler from "@saleor/utils/handlers/metadataCreateHandler"; +import { + useMetadataUpdate, + usePrivateMetadataUpdate +} from "@saleor/utils/metadata/updateMetadata"; +import React from "react"; +import { useIntl } from "react-intl"; + import { maybe } from "../../misc"; import ProductTypeCreatePage, { ProductTypeForm @@ -17,10 +22,13 @@ export const ProductTypeCreate: React.FC = () => { const navigate = useNavigator(); const notify = useNotifier(); const intl = useIntl(); + const [updateMetadata] = useMetadataUpdate({}); + const [updatePrivateMetadata] = usePrivateMetadataUpdate({}); const handleCreateSuccess = (updateData: ProductTypeCreateMutation) => { if (updateData.productTypeCreate.errors.length === 0) { notify({ + status: "success", text: intl.formatMessage({ defaultMessage: "Successfully created product type" }) @@ -31,8 +39,8 @@ export const ProductTypeCreate: React.FC = () => { return ( {(createProductType, createProductTypeOpts) => { - const handleCreate = (formData: ProductTypeForm) => - createProductType({ + const handleCreate = async (formData: ProductTypeForm) => { + const result = await createProductType({ variables: { input: { hasVariants: false, @@ -43,6 +51,15 @@ export const ProductTypeCreate: React.FC = () => { } } }); + + return result.data?.productTypeCreate.productType?.id || null; + }; + const handleSubmit = createMetadataCreateHandler( + handleCreate, + updateMetadata, + updatePrivateMetadata + ); + return ( {({ data, loading }) => ( @@ -57,19 +74,18 @@ export const ProductTypeCreate: React.FC = () => { data.shop.defaultWeightUnit)} disabled={loading} - errors={maybe( - () => createProductTypeOpts.data.productTypeCreate.errors, - [] - )} + errors={ + createProductTypeOpts.data?.productTypeCreate.errors || [] + } pageTitle={intl.formatMessage({ defaultMessage: "Create Product Type", description: "header", id: "productTypeCreatePageHeader" })} saveButtonBarState={createProductTypeOpts.status} - taxTypes={maybe(() => data.taxTypes, [])} + taxTypes={data?.taxTypes || []} onBack={() => navigate(productTypeListUrl())} - onSubmit={handleCreate} + onSubmit={handleSubmit} /> )} diff --git a/src/productTypes/views/ProductTypeList/ProductTypeList.tsx b/src/productTypes/views/ProductTypeList/ProductTypeList.tsx index b69bc8662..359430b49 100644 --- a/src/productTypes/views/ProductTypeList/ProductTypeList.tsx +++ b/src/productTypes/views/ProductTypeList/ProductTypeList.tsx @@ -1,9 +1,6 @@ import DialogContentText from "@material-ui/core/DialogContentText"; import IconButton from "@material-ui/core/IconButton"; import DeleteIcon from "@material-ui/icons/Delete"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import ActionDialog from "@saleor/components/ActionDialog"; import DeleteFilterTabDialog from "@saleor/components/DeleteFilterTabDialog"; import SaveFilterTabDialog, { @@ -16,13 +13,16 @@ import useNotifier from "@saleor/hooks/useNotifier"; import usePaginator, { createPaginationState } from "@saleor/hooks/usePaginator"; +import useShop from "@saleor/hooks/useShop"; import { commonMessages } from "@saleor/intl"; import { ListViews } from "@saleor/types"; -import { getSortParams } from "@saleor/utils/sort"; -import createSortHandler from "@saleor/utils/handlers/sortHandler"; import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; -import useShop from "@saleor/hooks/useShop"; import createFilterHandlers from "@saleor/utils/handlers/filterHandlers"; +import createSortHandler from "@saleor/utils/handlers/sortHandler"; +import { getSortParams } from "@saleor/utils/sort"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { configurationMenuUrl } from "../../../configuration"; import { maybe } from "../../../misc"; import ProductTypeListPage from "../../components/ProductTypeListPage"; @@ -40,11 +40,11 @@ import { areFiltersApplied, deleteFilterTab, getActiveFilters, + getFilterOpts, + getFilterQueryParam, getFilterTabs, getFilterVariables, - saveFilterTab, - getFilterQueryParam, - getFilterOpts + saveFilterTab } from "./filters"; import { getSortQueryVariables } from "./sort"; @@ -133,6 +133,7 @@ export const ProductTypeList: React.FC = ({ params }) => { const handleProductTypeBulkDelete = (data: ProductTypeBulkDelete) => { if (data.productTypeBulkDelete.errors.length === 0) { notify({ + status: "success", text: intl.formatMessage(commonMessages.savedChanges) }); reset(); diff --git a/src/productTypes/views/ProductTypeList/filters.test.ts b/src/productTypes/views/ProductTypeList/filters.test.ts index 9911460a0..a8f46393b 100644 --- a/src/productTypes/views/ProductTypeList/filters.test.ts +++ b/src/productTypes/views/ProductTypeList/filters.test.ts @@ -1,16 +1,16 @@ -import { createIntl } from "react-intl"; -import { stringify as stringifyQs } from "qs"; - -import { ProductTypeListUrlFilters } from "@saleor/productTypes/urls"; import { createFilterStructure } from "@saleor/productTypes/components/ProductTypeListPage"; +import { ProductTypeListUrlFilters } from "@saleor/productTypes/urls"; +import { + ProductTypeConfigurable, + ProductTypeEnum +} from "@saleor/types/globalTypes"; import { getFilterQueryParams } from "@saleor/utils/filters"; import { getExistingKeys, setFilterOptsStatus } from "@test/filters"; import { config } from "@test/intl"; -import { - ProductTypeEnum, - ProductTypeConfigurable -} from "@saleor/types/globalTypes"; -import { getFilterVariables, getFilterQueryParam } from "./filters"; +import { stringify as stringifyQs } from "qs"; +import { createIntl } from "react-intl"; + +import { getFilterQueryParam, getFilterVariables } from "./filters"; describe("Filtering query params", () => { it("should be empty object if no params given", () => { diff --git a/src/productTypes/views/ProductTypeList/filters.ts b/src/productTypes/views/ProductTypeList/filters.ts index c21c4e426..cbc457b70 100644 --- a/src/productTypes/views/ProductTypeList/filters.ts +++ b/src/productTypes/views/ProductTypeList/filters.ts @@ -1,14 +1,15 @@ -import { - ProductTypeFilterInput, - ProductTypeConfigurable, - ProductTypeEnum -} from "@saleor/types/globalTypes"; import { IFilterElement } from "@saleor/components/Filter"; -import { maybe, findValueInEnum } from "@saleor/misc"; +import { findValueInEnum, maybe } from "@saleor/misc"; import { ProductTypeFilterKeys, ProductTypeListFilterOpts } from "@saleor/productTypes/components/ProductTypeListPage"; +import { + ProductTypeConfigurable, + ProductTypeEnum, + ProductTypeFilterInput +} from "@saleor/types/globalTypes"; + import { createFilterTabUtils, createFilterUtils, diff --git a/src/productTypes/views/ProductTypeUpdate/errors.tsx b/src/productTypes/views/ProductTypeUpdate/errors.tsx deleted file mode 100644 index 5e2c83535..000000000 --- a/src/productTypes/views/ProductTypeUpdate/errors.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import React from "react"; - -import { UserError } from "../../../types"; - -interface ProductTypeUpdateErrorsState { - addAttributeErrors: UserError[]; - editAttributeErrors: UserError[]; - formErrors: UserError[]; -} -interface ProductTypeUpdateErrorsProps { - children: (props: { - errors: ProductTypeUpdateErrorsState; - set: { - addAttributeErrors: (errors: UserError[]) => void; - editAttributeErrors: (errors: UserError[]) => void; - formErrors: (errors: UserError[]) => void; - }; - }) => React.ReactNode; -} - -export class ProductTypeUpdateErrors extends React.Component< - ProductTypeUpdateErrorsProps, - ProductTypeUpdateErrorsState -> { - state: ProductTypeUpdateErrorsState = { - addAttributeErrors: [], - editAttributeErrors: [], - formErrors: [] - }; - - render() { - return this.props.children({ - errors: this.state, - set: { - addAttributeErrors: (addAttributeErrors: UserError[]) => - this.setState({ addAttributeErrors }), - editAttributeErrors: (editAttributeErrors: UserError[]) => - this.setState({ editAttributeErrors }), - formErrors: (formErrors: UserError[]) => this.setState({ formErrors }) - } - }); - } -} -export default ProductTypeUpdateErrors; diff --git a/src/productTypes/views/ProductTypeUpdate/index.tsx b/src/productTypes/views/ProductTypeUpdate/index.tsx index 492320261..eb987853f 100644 --- a/src/productTypes/views/ProductTypeUpdate/index.tsx +++ b/src/productTypes/views/ProductTypeUpdate/index.tsx @@ -1,8 +1,6 @@ import Button from "@material-ui/core/Button"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import { attributeUrl } from "@saleor/attributes/urls"; +import NotFoundPage from "@saleor/components/NotFoundPage"; import { WindowTitle } from "@saleor/components/WindowTitle"; import { DEFAULT_INITIAL_SEARCH_DATA } from "@saleor/config"; import useBulkActions from "@saleor/hooks/useBulkActions"; @@ -11,9 +9,17 @@ import useNotifier from "@saleor/hooks/useNotifier"; import { commonMessages } from "@saleor/intl"; import { maybe } from "@saleor/misc"; import AssignAttributeDialog from "@saleor/productTypes/components/AssignAttributeDialog"; +import { useProductTypeUpdateMutation } from "@saleor/productTypes/mutations"; import { ReorderEvent } from "@saleor/types"; import { AttributeTypeEnum } from "@saleor/types/globalTypes"; -import NotFoundPage from "@saleor/components/NotFoundPage"; +import createMetadataUpdateHandler from "@saleor/utils/handlers/metadataUpdateHandler"; +import { + useMetadataUpdate, + usePrivateMetadataUpdate +} from "@saleor/utils/metadata/updateMetadata"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import ProductTypeAttributeUnassignDialog from "../../components/ProductTypeAttributeUnassignDialog"; import ProductTypeBulkAttributeUnassignDialog from "../../components/ProductTypeBulkAttributeUnassignDialog"; import ProductTypeDeleteDialog from "../../components/ProductTypeDeleteDialog"; @@ -25,14 +31,12 @@ import useAvailableAttributeSearch from "../../hooks/useAvailableAttributeSearch import { TypedProductTypeDetailsQuery } from "../../queries"; import { AssignAttribute } from "../../types/AssignAttribute"; import { ProductTypeDelete } from "../../types/ProductTypeDelete"; -import { ProductTypeUpdate as ProductTypeUpdateMutation } from "../../types/ProductTypeUpdate"; import { UnassignAttribute } from "../../types/UnassignAttribute"; import { productTypeListUrl, productTypeUrl, ProductTypeUrlQueryParams } from "../../urls"; -import { ProductTypeUpdateErrors } from "./errors"; interface ProductTypeUpdateProps { id: string; @@ -54,357 +58,367 @@ export const ProductTypeUpdate: React.FC = ({ id } }); + const [errors, setErrors] = React.useState({ + addAttributeErrors: [], + editAttributeErrors: [], + formErrors: [] + }); + + const [ + updateProductType, + updateProductTypeOpts + ] = useProductTypeUpdateMutation({ + onCompleted: updateData => { + if ( + !updateData.productTypeUpdate.errors || + updateData.productTypeUpdate.errors.length === 0 + ) { + notify({ + status: "success", + text: intl.formatMessage(commonMessages.savedChanges) + }); + } else if ( + updateData.productTypeUpdate.errors !== null && + updateData.productTypeUpdate.errors.length > 0 + ) { + setErrors(prevErrors => ({ + ...prevErrors, + formErrors: updateData.productTypeUpdate.errors + })); + } + } + }); + + const [updateMetadata] = useMetadataUpdate({}); + const [updatePrivateMetadata] = usePrivateMetadataUpdate({}); const handleBack = () => navigate(productTypeListUrl()); + const handleProductTypeUpdate = async (formData: ProductTypeForm) => { + const result = await updateProductType({ + variables: { + id, + input: { + hasVariants: formData.hasVariants, + isShippingRequired: formData.isShippingRequired, + name: formData.name, + productAttributes: formData.productAttributes.map( + choice => choice.value + ), + taxCode: formData.taxType, + variantAttributes: formData.variantAttributes.map( + choice => choice.value + ), + weight: formData.weight + } + } + }); + + return result.data.productTypeUpdate.errors; + }; + return ( - - {({ errors, set: setErrors }) => ( - - {({ data, loading: dataLoading }) => { - const productType = data?.productType; + + {({ data, loading: dataLoading }) => { + const productType = data?.productType; - if (productType === null) { - return ; - } + if (productType === null) { + return ; + } - const closeModal = () => navigate(productTypeUrl(id), true); + const closeModal = () => navigate(productTypeUrl(id), true); - const handleAttributeAssignSuccess = (data: AssignAttribute) => { - if (data.attributeAssign.errors.length === 0) { - notify({ - text: intl.formatMessage(commonMessages.savedChanges) + const handleAttributeAssignSuccess = (data: AssignAttribute) => { + if (data.attributeAssign.errors.length === 0) { + notify({ + status: "success", + text: intl.formatMessage(commonMessages.savedChanges) + }); + closeModal(); + } else if ( + data.attributeAssign.errors !== null && + data.attributeAssign.errors.length > 0 + ) { + setErrors(prevErrors => ({ + ...prevErrors, + addAttributeErrors: data.attributeAssign.errors + })); + } + }; + const handleAttributeUnassignSuccess = (data: UnassignAttribute) => { + if (data.attributeUnassign.errors.length === 0) { + notify({ + status: "success", + text: intl.formatMessage(commonMessages.savedChanges) + }); + closeModal(); + productAttributeListActions.reset(); + variantAttributeListActions.reset(); + } + }; + const handleProductTypeDeleteSuccess = ( + deleteData: ProductTypeDelete + ) => { + if (deleteData.productTypeDelete.errors.length === 0) { + notify({ + status: "success", + text: intl.formatMessage({ + defaultMessage: "Product type deleted" + }) + }); + navigate(productTypeListUrl(), true); + } + }; + const handleSubmit = createMetadataUpdateHandler( + data?.productType, + handleProductTypeUpdate, + variables => updateMetadata({ variables }), + variables => updatePrivateMetadata({ variables }) + ); + + return ( + data.productType)} + onAssignAttribute={handleAttributeAssignSuccess} + onUnassignAttribute={handleAttributeUnassignSuccess} + onProductTypeDelete={handleProductTypeDeleteSuccess} + onProductTypeAttributeReorder={() => undefined} + > + {({ + assignAttribute, + deleteProductType, + unassignAttribute, + reorderAttribute + }) => { + const handleProductTypeDelete = () => + deleteProductType.mutate({ id }); + const handleProductTypeVariantsToggle = (hasVariants: boolean) => + updateProductType({ + variables: { + id, + input: { + hasVariants + } + } }); - closeModal(); - } else if ( - data.attributeAssign.errors !== null && - data.attributeAssign.errors.length > 0 - ) { - setErrors.addAttributeErrors(data.attributeAssign.errors); - } - }; - const handleAttributeUnassignSuccess = ( - data: UnassignAttribute - ) => { - if (data.attributeUnassign.errors.length === 0) { - notify({ - text: intl.formatMessage(commonMessages.savedChanges) + const handleAssignAttribute = () => + assignAttribute.mutate({ + id, + operations: params.ids.map(id => ({ + id, + type: AttributeTypeEnum[params.type] + })) }); - closeModal(); - productAttributeListActions.reset(); - variantAttributeListActions.reset(); - } - }; - const handleProductTypeDeleteSuccess = ( - deleteData: ProductTypeDelete - ) => { - if (deleteData.productTypeDelete.errors.length === 0) { - notify({ - text: intl.formatMessage({ - defaultMessage: "Product type deleted" - }) + + const handleAttributeUnassign = () => + unassignAttribute.mutate({ + id, + ids: [params.id] }); - navigate(productTypeListUrl(), true); - } - }; - const handleProductTypeUpdateSuccess = ( - updateData: ProductTypeUpdateMutation - ) => { - if ( - !updateData.productTypeUpdate.errors || - updateData.productTypeUpdate.errors.length === 0 - ) { - notify({ - text: intl.formatMessage(commonMessages.savedChanges) + + const handleBulkAttributeUnassign = () => + unassignAttribute.mutate({ + id, + ids: params.ids }); - } else if ( - updateData.productTypeUpdate.errors !== null && - updateData.productTypeUpdate.errors.length > 0 - ) { - setErrors.formErrors(updateData.productTypeUpdate.errors); - } - }; - return ( - data.productType)} - onAssignAttribute={handleAttributeAssignSuccess} - onUnassignAttribute={handleAttributeUnassignSuccess} - onProductTypeDelete={handleProductTypeDeleteSuccess} - onProductTypeUpdate={handleProductTypeUpdateSuccess} - onProductTypeAttributeReorder={() => undefined} - > - {({ - assignAttribute, - deleteProductType, - unassignAttribute, - updateProductType, - reorderAttribute - }) => { - const handleProductTypeDelete = () => - deleteProductType.mutate({ id }); - const handleProductTypeUpdate = ( - formData: ProductTypeForm - ) => { - updateProductType.mutate({ - id, - input: { - hasVariants: formData.hasVariants, - isShippingRequired: formData.isShippingRequired, - name: formData.name, - productAttributes: formData.productAttributes.map( - choice => choice.value - ), - taxCode: formData.taxType, - variantAttributes: formData.variantAttributes.map( - choice => choice.value - ), - weight: formData.weight - } - }); - }; - const handleProductTypeVariantsToggle = ( - hasVariants: boolean - ) => - updateProductType.mutate({ - id, - input: { - hasVariants - } - }); - const handleAssignAttribute = () => - assignAttribute.mutate({ - id, - operations: params.ids.map(id => ({ - id, - type: AttributeTypeEnum[params.type] - })) - }); + const loading = updateProductTypeOpts.loading || dataLoading; - const handleAttributeUnassign = () => - unassignAttribute.mutate({ - id, - ids: [params.id] - }); + const handleAttributeReorder = ( + event: ReorderEvent, + type: AttributeTypeEnum + ) => { + const attributes = + type === AttributeTypeEnum.PRODUCT + ? data.productType.productAttributes + : data.productType.variantAttributes; - const handleBulkAttributeUnassign = () => - unassignAttribute.mutate({ - id, - ids: params.ids - }); + reorderAttribute.mutate({ + move: { + id: attributes[event.oldIndex].id, + sortOrder: event.newIndex - event.oldIndex + }, + productTypeId: id, + type + }); + }; - const loading = updateProductType.opts.loading || dataLoading; - - const handleAttributeReorder = ( - event: ReorderEvent, - type: AttributeTypeEnum - ) => { - const attributes = - type === AttributeTypeEnum.PRODUCT - ? data.productType.productAttributes - : data.productType.variantAttributes; - - reorderAttribute.mutate({ - move: { - id: attributes[event.oldIndex].id, - sortOrder: event.newIndex - event.oldIndex - }, - productTypeId: id, - type - }); - }; - - return ( - <> - data.productType.name)} /> - data.shop.defaultWeightUnit - )} - disabled={loading} - errors={errors.formErrors} - pageTitle={maybe(() => data.productType.name)} - productType={maybe(() => data.productType)} - saveButtonBarState={updateProductType.opts.status} - taxTypes={maybe(() => data.taxTypes, [])} - onAttributeAdd={type => - navigate( - productTypeUrl(id, { - action: "assign-attribute", - type - }) - ) - } - onAttributeClick={attributeId => - navigate(attributeUrl(attributeId)) - } - onAttributeReorder={handleAttributeReorder} - onAttributeUnassign={attributeId => - navigate( - productTypeUrl(id, { - action: "unassign-attribute", - id: attributeId - }) - ) - } - onBack={handleBack} - onDelete={() => - navigate( - productTypeUrl(id, { - action: "remove" - }) - ) - } - onHasVariantsToggle={handleProductTypeVariantsToggle} - onSubmit={handleProductTypeUpdate} - productAttributeList={{ - isChecked: productAttributeListActions.isSelected, - selected: - productAttributeListActions.listElements.length, - toggle: productAttributeListActions.toggle, - toggleAll: productAttributeListActions.toggleAll, - toolbar: ( - - ) - }} - variantAttributeList={{ - isChecked: variantAttributeListActions.isSelected, - selected: - variantAttributeListActions.listElements.length, - toggle: variantAttributeListActions.toggle, - toggleAll: variantAttributeListActions.toggleAll, - toolbar: ( - - ) - }} - /> - {!dataLoading && - Object.keys(AttributeTypeEnum).map(key => ( - - result.data.productType.availableAttributes.edges.map( - edge => edge.node - ) - )} - confirmButtonState={assignAttribute.opts.status} - errors={maybe( - () => - assignAttribute.opts.data.attributeAssign.errors.map( - err => err.message - ), - [] - )} - loading={result.loading} - onClose={closeModal} - onSubmit={handleAssignAttribute} - onFetch={search} - onFetchMore={loadMore} - onOpen={result.refetch} - hasMore={maybe( - () => - result.data.productType.availableAttributes - .pageInfo.hasNextPage, - false - )} - open={ - params.action === "assign-attribute" && - params.type === AttributeTypeEnum[key] - } - selected={maybe(() => params.ids, [])} - onToggle={attributeId => { - const ids = maybe(() => params.ids, []); - navigate( - productTypeUrl(id, { - ...params, - ids: ids.includes(attributeId) - ? params.ids.filter( - selectedId => selectedId !== attributeId - ) - : [...ids, attributeId] - }) - ); - }} - key={key} + return ( + <> + data.productType.name)} /> + data.shop.defaultWeightUnit)} + disabled={loading} + errors={errors.formErrors} + pageTitle={maybe(() => data.productType.name)} + productType={maybe(() => data.productType)} + saveButtonBarState={updateProductTypeOpts.status} + taxTypes={maybe(() => data.taxTypes, [])} + onAttributeAdd={type => + navigate( + productTypeUrl(id, { + action: "assign-attribute", + type + }) + ) + } + onAttributeClick={attributeId => + navigate(attributeUrl(attributeId)) + } + onAttributeReorder={handleAttributeReorder} + onAttributeUnassign={attributeId => + navigate( + productTypeUrl(id, { + action: "unassign-attribute", + id: attributeId + }) + ) + } + onBack={handleBack} + onDelete={() => + navigate( + productTypeUrl(id, { + action: "remove" + }) + ) + } + onHasVariantsToggle={handleProductTypeVariantsToggle} + onSubmit={handleSubmit} + productAttributeList={{ + isChecked: productAttributeListActions.isSelected, + selected: productAttributeListActions.listElements.length, + toggle: productAttributeListActions.toggle, + toggleAll: productAttributeListActions.toggleAll, + toolbar: ( + + ) + }} + variantAttributeList={{ + isChecked: variantAttributeListActions.isSelected, + selected: variantAttributeListActions.listElements.length, + toggle: variantAttributeListActions.toggle, + toggleAll: variantAttributeListActions.toggleAll, + toolbar: ( + + ) + }} + /> + {!dataLoading && + Object.keys(AttributeTypeEnum).map(key => ( + + result.data.productType.availableAttributes.edges.map( + edge => edge.node + ) )} - /> - - [ - ...data.productType.productAttributes, - ...data.productType.variantAttributes - ].find(attribute => attribute.id === params.id) - .name, - "..." + assignAttribute.opts.data.attributeAssign.errors.map( + err => err.message + ), + [] )} - confirmButtonState={unassignAttribute.opts.status} + loading={result.loading} onClose={closeModal} - onConfirm={handleAttributeUnassign} - open={params.action === "unassign-attribute"} - productTypeName={maybe( - () => data.productType.name, - "..." + onSubmit={handleAssignAttribute} + onFetch={search} + onFetchMore={loadMore} + onOpen={result.refetch} + hasMore={maybe( + () => + result.data.productType.availableAttributes.pageInfo + .hasNextPage, + false )} + open={ + params.action === "assign-attribute" && + params.type === AttributeTypeEnum[key] + } + selected={maybe(() => params.ids, [])} + onToggle={attributeId => { + const ids = maybe(() => params.ids, []); + navigate( + productTypeUrl(id, { + ...params, + ids: ids.includes(attributeId) + ? params.ids.filter( + selectedId => selectedId !== attributeId + ) + : [...ids, attributeId] + }) + ); + }} + key={key} /> - - ); - }} - - ); - }} - - )} - + ))} + data.productType.name, "...")} + open={params.action === "remove"} + onClose={() => navigate(productTypeUrl(id))} + onConfirm={handleProductTypeDelete} + /> + params.ids.length)} + confirmButtonState={unassignAttribute.opts.status} + onClose={closeModal} + onConfirm={handleBulkAttributeUnassign} + open={params.action === "unassign-attributes"} + productTypeName={maybe(() => data.productType.name, "...")} + /> + + [ + ...data.productType.productAttributes, + ...data.productType.variantAttributes + ].find(attribute => attribute.id === params.id).name, + "..." + )} + confirmButtonState={unassignAttribute.opts.status} + onClose={closeModal} + onConfirm={handleAttributeUnassign} + open={params.action === "unassign-attribute"} + productTypeName={maybe(() => data.productType.name, "...")} + /> + + ); + }} + + ); + }} + ); }; export default ProductTypeUpdate; diff --git a/src/products/components/ProductAttributes/ProductAttributes.tsx b/src/products/components/ProductAttributes/ProductAttributes.tsx index 24617faeb..c6018c2ef 100644 --- a/src/products/components/ProductAttributes/ProductAttributes.tsx +++ b/src/products/components/ProductAttributes/ProductAttributes.tsx @@ -4,10 +4,6 @@ import IconButton from "@material-ui/core/IconButton"; import makeStyles from "@material-ui/core/styles/makeStyles"; import Typography from "@material-ui/core/Typography"; import ArrowDropDownIcon from "@material-ui/icons/ArrowDropDown"; -import classNames from "classnames"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import CardTitle from "@saleor/components/CardTitle"; import Grid from "@saleor/components/Grid"; import Hr from "@saleor/components/Hr"; @@ -21,6 +17,9 @@ import { FormsetAtomicData, FormsetChange } from "@saleor/hooks/useFormset"; import { maybe } from "@saleor/misc"; import { ProductDetails_product_attributes_attribute_values } from "@saleor/products/types/ProductDetails"; import { AttributeInputTypeEnum } from "@saleor/types/globalTypes"; +import classNames from "classnames"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; export interface ProductAttributeInputData { inputType: AttributeInputTypeEnum; @@ -158,7 +157,7 @@ const ProductAttributes: React.FC = ({ = ({
{attribute.label}
-
+
{attribute.data.inputType === AttributeInputTypeEnum.DROPDOWN ? ( ; diff --git a/src/products/components/ProductCreatePage/ProductCreatePage.tsx b/src/products/components/ProductCreatePage/ProductCreatePage.tsx index 3d1ae00f1..d96f30343 100644 --- a/src/products/components/ProductCreatePage/ProductCreatePage.tsx +++ b/src/products/components/ProductCreatePage/ProductCreatePage.tsx @@ -1,18 +1,16 @@ -import { ContentState, convertToRaw, RawDraftContentState } from "draft-js"; -import React from "react"; -import { useIntl } from "react-intl"; - import AppHeader from "@saleor/components/AppHeader"; +import AvailabilityCard from "@saleor/components/AvailabilityCard"; import CardSpacer from "@saleor/components/CardSpacer"; import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; import Container from "@saleor/components/Container"; import Form from "@saleor/components/Form"; import Grid from "@saleor/components/Grid"; +import Metadata, { MetadataFormData } from "@saleor/components/Metadata"; import { MultiAutocompleteChoiceType } from "@saleor/components/MultiAutocompleteSelectField"; import PageHeader from "@saleor/components/PageHeader"; import SaveButtonBar from "@saleor/components/SaveButtonBar"; import SeoForm from "@saleor/components/SeoForm"; -import VisibilityCard from "@saleor/components/VisibilityCard"; +import { ProductErrorFragment } from "@saleor/fragments/types/ProductErrorFragment"; import useDateLocalize from "@saleor/hooks/useDateLocalize"; import useFormset from "@saleor/hooks/useFormset"; import useStateFromProps from "@saleor/hooks/useStateFromProps"; @@ -25,10 +23,14 @@ import { import { SearchCategories_search_edges_node } from "@saleor/searches/types/SearchCategories"; import { SearchCollections_search_edges_node } from "@saleor/searches/types/SearchCollections"; import { SearchProductTypes_search_edges_node_productAttributes } from "@saleor/searches/types/SearchProductTypes"; +import { SearchWarehouses_search_edges_node } from "@saleor/searches/types/SearchWarehouses"; import createMultiAutocompleteSelectHandler from "@saleor/utils/handlers/multiAutocompleteSelectChangeHandler"; import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler"; -import { ProductErrorFragment } from "@saleor/attributes/types/ProductErrorFragment"; -import { SearchWarehouses_search_edges_node } from "@saleor/searches/types/SearchWarehouses"; +import useMetadataChangeTrigger from "@saleor/utils/metadata/useMetadataChangeTrigger"; +import { ContentState, convertToRaw, RawDraftContentState } from "draft-js"; +import React from "react"; +import { useIntl } from "react-intl"; + import { FetchMoreProps } from "../../../types"; import { createAttributeChangeHandler, @@ -42,16 +44,19 @@ import ProductAttributes, { import ProductDetailsForm from "../ProductDetailsForm"; import ProductOrganization from "../ProductOrganization"; import ProductPricing from "../ProductPricing"; -import ProductStocks, { ProductStockInput } from "../ProductStocks"; import ProductShipping from "../ProductShipping/ProductShipping"; +import ProductStocks, { ProductStockInput } from "../ProductStocks"; -interface FormData { +interface FormData extends MetadataFormData { + availableForPurchase: string; basePrice: number; publicationDate: string; category: string; collections: string[]; chargeTaxes: boolean; description: RawDraftContentState; + isAvailable: boolean; + isAvailableForPurchase: boolean; isPublished: boolean; name: string; productType: string; @@ -60,6 +65,7 @@ interface FormData { sku: string; stockQuantity: number; trackInventory: boolean; + visibleInListings: boolean; weight: string; } export interface ProductCreatePageSubmitData extends FormData { @@ -133,14 +139,24 @@ export const ProductCreatePage: React.FC = ({ const initialDescription = React.useRef( convertToRaw(ContentState.createFromText("")) ); + + const { + makeChangeHandler: makeMetadataChangeHandler + } = useMetadataChangeTrigger(); + const initialData: FormData = { + availableForPurchase: "", basePrice: 0, category: "", chargeTaxes: false, collections: [], description: {} as any, + isAvailable: false, + isAvailableForPurchase: false, isPublished: false, + metadata: [], name: "", + privateMetadata: [], productType: "", publicationDate: "", seoDescription: "", @@ -148,6 +164,7 @@ export const ProductCreatePage: React.FC = ({ sku: null, stockQuantity: null, trackInventory: false, + visibleInListings: false, weight: "" }; @@ -170,9 +187,9 @@ export const ProductCreatePage: React.FC = ({ const handleSubmit = (data: FormData) => onSubmit({ + ...data, attributes, - stocks, - ...data + stocks }); return ( @@ -212,6 +229,8 @@ export const ProductCreatePage: React.FC = ({ productTypeChoiceList ); + const changeMetadata = makeMetadataChangeHandler(change); + return ( @@ -237,14 +256,6 @@ export const ProductCreatePage: React.FC = ({ /> )} - - {!!productType && !productType.hasVariants && ( <> = ({ weightUnit={weightUnit} onChange={change} /> + = ({ loading={disabled} onChange={change} /> + +
= ({ collectionsInputDisplayValue={selectedCollections} /> -
diff --git a/src/products/components/ProductDetailsForm/ProductDetailsForm.tsx b/src/products/components/ProductDetailsForm/ProductDetailsForm.tsx index 04d3321f4..aac585345 100644 --- a/src/products/components/ProductDetailsForm/ProductDetailsForm.tsx +++ b/src/products/components/ProductDetailsForm/ProductDetailsForm.tsx @@ -1,16 +1,15 @@ import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; import TextField from "@material-ui/core/TextField"; -import { RawDraftContentState } from "draft-js"; -import React from "react"; -import { useIntl } from "react-intl"; - import CardTitle from "@saleor/components/CardTitle"; import FormSpacer from "@saleor/components/FormSpacer"; import RichTextEditor from "@saleor/components/RichTextEditor"; +import { ProductErrorFragment } from "@saleor/fragments/types/ProductErrorFragment"; import { commonMessages } from "@saleor/intl"; import { getFormErrors, getProductErrorMessage } from "@saleor/utils/errors"; -import { ProductErrorFragment } from "@saleor/attributes/types/ProductErrorFragment"; +import { RawDraftContentState } from "draft-js"; +import React from "react"; +import { useIntl } from "react-intl"; interface ProductDetailsFormProps { data: { diff --git a/src/products/components/ProductExportDialog/ProductExportDialog.stories.tsx b/src/products/components/ProductExportDialog/ProductExportDialog.stories.tsx new file mode 100644 index 000000000..f81aead66 --- /dev/null +++ b/src/products/components/ProductExportDialog/ProductExportDialog.stories.tsx @@ -0,0 +1,55 @@ +import Decorator from "@saleor/storybook/Decorator"; +import { + ExportErrorCode, + ExportProductsInput +} from "@saleor/types/globalTypes"; +import { warehouseList } from "@saleor/warehouses/fixtures"; +import { storiesOf } from "@storybook/react"; +import React from "react"; + +import { attributes } from "../../../attributes/fixtures"; +import ProductExportDialog, { + ProductExportDialogProps +} from "./ProductExportDialog"; + +const props: ProductExportDialogProps = { + attributes: attributes.map(attr => ({ + __typename: "Attribute", + id: attr.id, + name: attr.name + })), + confirmButtonState: "default", + errors: [], + hasMore: true, + loading: true, + onClose: () => undefined, + onFetch: () => undefined, + onFetchMore: () => undefined, + onSubmit: () => undefined, + open: true, + productQuantity: { + all: 100, + filter: 32 + }, + selectedProducts: 18, + warehouses: warehouseList +}; + +storiesOf("Views / Products / Export / Export settings", module) + .addDecorator(Decorator) + .add("interactive", () => ) + .add("no products selected", () => ( + + )) + .add("errors", () => ( + ).map(field => ({ + __typename: "ExportError", + code: ExportErrorCode.INVALID, + field + }))} + /> + )); diff --git a/src/products/components/ProductExportDialog/ProductExportDialog.tsx b/src/products/components/ProductExportDialog/ProductExportDialog.tsx new file mode 100644 index 000000000..5f9581eeb --- /dev/null +++ b/src/products/components/ProductExportDialog/ProductExportDialog.tsx @@ -0,0 +1,264 @@ +import Button from "@material-ui/core/Button"; +import Dialog from "@material-ui/core/Dialog"; +import DialogActions from "@material-ui/core/DialogActions"; +import DialogContent from "@material-ui/core/DialogContent"; +import DialogTitle from "@material-ui/core/DialogTitle"; +import Typography from "@material-ui/core/Typography"; +import ConfirmButton, { + ConfirmButtonTransitionState +} from "@saleor/components/ConfirmButton"; +import makeCreatorSteps, { Step } from "@saleor/components/CreatorSteps"; +import { MultiAutocompleteChoiceType } from "@saleor/components/MultiAutocompleteSelectField"; +import { ExportErrorFragment } from "@saleor/fragments/types/ExportErrorFragment"; +import useForm, { FormChange } from "@saleor/hooks/useForm"; +import useModalDialogErrors from "@saleor/hooks/useModalDialogErrors"; +import useModalDialogOpen from "@saleor/hooks/useModalDialogOpen"; +import useWizard from "@saleor/hooks/useWizard"; +import { buttonMessages } from "@saleor/intl"; +import { SearchAttributes_search_edges_node } from "@saleor/searches/types/SearchAttributes"; +import { DialogProps, FetchMoreProps } from "@saleor/types"; +import { + ExportProductsInput, + ExportScope, + FileTypesEnum +} from "@saleor/types/globalTypes"; +import getExportErrorMessage from "@saleor/utils/errors/export"; +import { toggle } from "@saleor/utils/lists"; +import { mapNodeToChoice } from "@saleor/utils/maps"; +import { WarehouseList_warehouses_edges_node } from "@saleor/warehouses/types/WarehouseList"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + +import ProductExportDialogInfo, { + attributeNamePrefix, + warehouseNamePrefix +} from "./ProductExportDialogInfo"; +import ProductExportDialogSettings, { + ProductQuantity +} from "./ProductExportDialogSettings"; + +export enum ProductExportStep { + INFO, + SETTINGS +} + +function useSteps(): Array> { + const intl = useIntl(); + + return [ + { + label: intl.formatMessage({ + defaultMessage: "Information exported", + description: "product export to csv file, header" + }), + value: ProductExportStep.INFO + }, + { + label: intl.formatMessage({ + defaultMessage: "Export Settings", + description: "product export to csv file, header" + }), + value: ProductExportStep.SETTINGS + } + ]; +} + +const initialForm: ExportProductsInput = { + exportInfo: { + attributes: [], + fields: [], + warehouses: [] + }, + fileType: FileTypesEnum.CSV, + scope: ExportScope.ALL +}; + +const ProductExportSteps = makeCreatorSteps(); + +export interface ProductExportDialogProps extends DialogProps, FetchMoreProps { + attributes: SearchAttributes_search_edges_node[]; + confirmButtonState: ConfirmButtonTransitionState; + errors: ExportErrorFragment[]; + productQuantity: ProductQuantity; + selectedProducts: number; + warehouses: WarehouseList_warehouses_edges_node[]; + onFetch: (query: string) => void; + onSubmit: (data: ExportProductsInput) => void; +} + +const ProductExportDialog: React.FC = ({ + attributes, + confirmButtonState, + errors, + productQuantity, + onClose, + onSubmit, + open, + selectedProducts, + warehouses, + ...fetchMoreProps +}) => { + const [step, { next, prev, set: setStep }] = useWizard( + ProductExportStep.INFO, + [ProductExportStep.INFO, ProductExportStep.SETTINGS] + ); + const steps = useSteps(); + const dialogErrors = useModalDialogErrors(errors, open); + const notFormErrors = dialogErrors.filter(err => !err.field); + const intl = useIntl(); + const [selectedAttributes, setSelectedAttributes] = React.useState< + MultiAutocompleteChoiceType[] + >([]); + const { change, data, reset, submit } = useForm(initialForm, onSubmit); + + useModalDialogOpen(open, { + onClose: () => { + reset(); + setStep(ProductExportStep.INFO); + } + }); + + const attributeChoices = mapNodeToChoice(attributes); + const warehouseChoices = mapNodeToChoice(warehouses); + + const handleAttributeSelect: FormChange = event => { + const id = event.target.name.substr(attributeNamePrefix.length); + + change({ + target: { + name: "exportInfo", + value: { + ...data.exportInfo, + attributes: toggle(id, data.exportInfo.attributes, (a, b) => a === b) + } + } + }); + + const choice = attributeChoices.find(choice => choice.value === id); + + setSelectedAttributes( + toggle(choice, selectedAttributes, (a, b) => a.value === b.value) + ); + }; + + const handleWarehouseSelect: FormChange = event => + change({ + target: { + name: "exportInfo", + value: { + ...data.exportInfo, + warehouses: toggle( + event.target.name.substr(warehouseNamePrefix.length), + data.exportInfo.warehouses, + (a, b) => a === b + ) + } + } + }); + + const handleToggleAllWarehouses: FormChange = () => + change({ + target: { + name: "exportInfo", + value: { + ...data.exportInfo, + warehouses: + data.exportInfo.warehouses.length === warehouses.length + ? [] + : warehouses.map(warehouse => warehouse.id) + } + } + }); + + return ( + + <> + + + + + + {step === ProductExportStep.INFO && ( + + )} + {step === ProductExportStep.SETTINGS && ( + + )} + + + {notFormErrors.length > 0 && ( + + {notFormErrors.map(err => ( + + {getExportErrorMessage(err, intl)} + + ))} + + )} + + + {step === ProductExportStep.INFO && ( + + )} + {step === ProductExportStep.SETTINGS && ( + + )} + {step === ProductExportStep.INFO && ( + + )} + {step === ProductExportStep.SETTINGS && ( + + + + )} + + + + ); +}; + +ProductExportDialog.displayName = "ProductExportDialog"; +export default ProductExportDialog; diff --git a/src/products/components/ProductExportDialog/ProductExportDialogInfo.tsx b/src/products/components/ProductExportDialog/ProductExportDialogInfo.tsx new file mode 100644 index 000000000..14535ad01 --- /dev/null +++ b/src/products/components/ProductExportDialog/ProductExportDialogInfo.tsx @@ -0,0 +1,545 @@ +import Button from "@material-ui/core/Button"; +import CircularProgress from "@material-ui/core/CircularProgress"; +import FormControlLabel from "@material-ui/core/FormControlLabel"; +import makeStyles from "@material-ui/core/styles/makeStyles"; +import TextField from "@material-ui/core/TextField"; +import Typography from "@material-ui/core/Typography"; +import Accordion, { AccordionProps } from "@saleor/components/Accordion"; +import Checkbox from "@saleor/components/Checkbox"; +import Chip from "@saleor/components/Chip"; +import Hr from "@saleor/components/Hr"; +import { MultiAutocompleteChoiceType } from "@saleor/components/MultiAutocompleteSelectField"; +import { ChangeEvent, FormChange } from "@saleor/hooks/useForm"; +import useSearchQuery from "@saleor/hooks/useSearchQuery"; +import { sectionNames } from "@saleor/intl"; +import { FetchMoreProps } from "@saleor/types"; +import { + ExportProductsInput, + ProductFieldEnum +} from "@saleor/types/globalTypes"; +import { toggle } from "@saleor/utils/lists"; +import React from "react"; +import { useIntl } from "react-intl"; +import { FormattedMessage } from "react-intl"; + +import useProductExportFieldMessages from "./messages"; + +export const attributeNamePrefix = "attribute-"; +export const warehouseNamePrefix = "warehouse-"; +const maxChips = 4; + +const inventoryFields = [ + ProductFieldEnum.PRODUCT_WEIGHT, + ProductFieldEnum.VARIANT_SKU, + ProductFieldEnum.VARIANT_WEIGHT +]; + +const useStyles = makeStyles( + theme => ({ + accordion: { + marginBottom: theme.spacing(2) + }, + checkbox: { + position: "relative", + right: -theme.spacing(1.5) + }, + chip: { + marginBottom: theme.spacing(1), + marginRight: theme.spacing() + }, + dialogLabel: { + marginBottom: theme.spacing(2) + }, + hr: { + marginBottom: theme.spacing(3), + marginTop: theme.spacing(3) + }, + hrWarehouses: { + marginBottom: theme.spacing(3), + marginTop: theme.spacing(1) + }, + label: { + "&&": { + overflow: "visible" + }, + "&:first-of-type": { + paddingTop: 0 + }, + "&:not(:last-of-type)": { + borderBottom: `1px solid ${theme.palette.divider}` + }, + justifyContent: "space-between", + margin: theme.spacing(0), + padding: theme.spacing(1, 0), + width: "100%" + }, + loadMoreContainer: { + display: "flex", + justifyContent: "center", + marginTop: theme.spacing(2) + }, + moreLabel: { + display: "inline-block", + marginBottom: theme.spacing() + }, + optionLabel: { + marginLeft: 0 + }, + quickPeekContainer: { + marginBottom: theme.spacing(-1) + }, + warehousesLabel: { + marginBottom: theme.spacing(2) + } + }), + { + name: "ProductExportDialogInfo" + } +); + +const Option: React.FC<{ + checked: boolean; + name: string; + onChange: (event: ChangeEvent) => void; +}> = ({ checked, children, name, onChange }) => { + const classes = useStyles({}); + + return ( + + } + className={classes.label} + label={children} + labelPlacement="start" + > + ); +}; + +const FieldAccordion: React.FC void; + onToggleAll: (field: ProductFieldEnum[], setTo: boolean) => void; +}> = ({ data, fields, onChange, onToggleAll, ...props }) => { + const classes = useStyles({}); + const getFieldLabel = useProductExportFieldMessages(); + + const selectedAll = fields.every(field => + data.exportInfo.fields.includes(field) + ); + + const selectedFields = data.exportInfo.fields.filter(field => + fields.includes(field) + ); + + return ( + 0 && ( +
+ {selectedFields.slice(0, maxChips).map(field => ( + + onChange({ + target: { + name: field, + value: false + } + }) + } + key={field} + /> + ))} + {selectedFields.length > maxChips && ( + + + + )} +
+ ) + } + {...props} + > + + {fields.map(field => ( + + ))} +
+ ); +}; + +export interface ProductExportDialogInfoProps extends FetchMoreProps { + attributes: MultiAutocompleteChoiceType[]; + warehouses: MultiAutocompleteChoiceType[]; + data: ExportProductsInput; + selectedAttributes: MultiAutocompleteChoiceType[]; + onAttrtibuteSelect: FormChange; + onWarehouseSelect: FormChange; + onChange: FormChange; + onFetch: (query: string) => void; + onSelectAllWarehouses: FormChange; +} + +const ProductExportDialogInfo: React.FC = ({ + attributes, + data, + hasMore, + selectedAttributes, + loading, + warehouses, + onAttrtibuteSelect, + onWarehouseSelect, + onChange, + onFetch, + onFetchMore, + onSelectAllWarehouses +}) => { + const classes = useStyles({}); + const intl = useIntl(); + const [query, onQueryChange] = useSearchQuery(onFetch); + const getFieldLabel = useProductExportFieldMessages(); + + const handleFieldChange = (event: ChangeEvent) => + onChange({ + target: { + name: "exportInfo", + value: { + ...data.exportInfo, + fields: toggle( + event.target.name, + data.exportInfo.fields, + (a, b) => a === b + ) + } + } + }); + + const handleToggleAllFields = (fields: ProductFieldEnum[], setTo: boolean) => + onChange({ + target: { + name: "exportInfo", + value: { + ...data.exportInfo, + fields: setTo + ? [ + ...data.exportInfo.fields, + ...fields.filter( + field => !data.exportInfo.fields.includes(field) + ) + ] + : data.exportInfo.fields.filter(field => !fields.includes(field)) + } + } + }); + + const selectedInventoryFields = data.exportInfo.fields.filter(field => + inventoryFields.includes(field) + ); + const selectedAllInventoryFields = + selectedInventoryFields.length === inventoryFields.length; + + return ( + <> + + + + + 0 && ( +
+ {selectedAttributes.slice(0, maxChips).map(attribute => ( + + onAttrtibuteSelect({ + target: { + name: attributeNamePrefix + attribute.value, + value: undefined + } + }) + } + key={attribute.value} + /> + ))} + {selectedAttributes.length > maxChips && ( + + + + )} +
+ ) + } + data-test="attributes" + > + + }} + /> +
+ {attributes.map(attribute => ( + + ))} + {(hasMore || loading) && ( +
+ {hasMore && !loading && ( + + )} + {loading && } +
+ )} +
+ + 0 || + selectedInventoryFields.length > 0) && ( +
+ {selectedInventoryFields.slice(0, maxChips).map(field => ( + + onChange({ + target: { + name: field, + value: false + } + }) + } + /> + ))} + {data.exportInfo.warehouses + .slice(0, maxChips - selectedInventoryFields.length) + .map(warehouseId => ( + warehouse.value === warehouseId + ).label + } + onClose={() => + onWarehouseSelect({ + target: { + name: warehouseNamePrefix + warehouseId, + value: undefined + } + }) + } + /> + ))} + {data.exportInfo.warehouses.length + + selectedInventoryFields.length > + maxChips && ( + + + + )} +
+ ) + } + data-test="inventory" + > +
+ + {inventoryFields.map(field => ( + + ))} +
+
+ + + +
+ +
+
+ + + + {warehouses.map(warehouse => ( + + ))} +
+ + + ); +}; + +ProductExportDialogInfo.displayName = "ProductExportDialogInfo"; +export default ProductExportDialogInfo; diff --git a/src/products/components/ProductExportDialog/ProductExportDialogSettings.tsx b/src/products/components/ProductExportDialog/ProductExportDialogSettings.tsx new file mode 100644 index 000000000..040b0dbc3 --- /dev/null +++ b/src/products/components/ProductExportDialog/ProductExportDialogSettings.tsx @@ -0,0 +1,144 @@ +import makeStyles from "@material-ui/core/styles/makeStyles"; +import Hr from "@saleor/components/Hr"; +import RadioGroupField, { + RadioGroupFieldChoice +} from "@saleor/components/RadioGroupField"; +import { ExportErrorFragment } from "@saleor/fragments/types/ExportErrorFragment"; +import { ChangeEvent } from "@saleor/hooks/useForm"; +import { + ExportProductsInput, + ExportScope, + FileTypesEnum +} from "@saleor/types/globalTypes"; +import { getFormErrors } from "@saleor/utils/errors"; +import getExportErrorMessage from "@saleor/utils/errors/export"; +import React from "react"; +import { useIntl } from "react-intl"; + +const useStyles = makeStyles( + theme => ({ + hr: { + marginBottom: theme.spacing(3), + marginTop: theme.spacing(3) + } + }), + { + name: "ProductExportDialogSettings" + } +); + +export type ProductQuantity = Record<"all" | "filter", number>; +export interface ProductExportDialogSettingsProps { + data: ExportProductsInput; + errors: ExportErrorFragment[]; + productQuantity: ProductQuantity; + selectedProducts: number; + onChange: (event: ChangeEvent) => void; +} + +const formFields: Array = ["fileType", "scope"]; + +const ProductExportDialogSettings: React.FC = ({ + data, + errors, + onChange, + productQuantity, + selectedProducts +}) => { + const classes = useStyles({}); + const intl = useIntl(); + + const formErrors = getFormErrors(formFields, errors); + + const productsToExportChoices: Array> = [ + { + label: intl.formatMessage( + { + defaultMessage: "All products ({number})", + description: "export all products to csv file" + }, + { + number: productQuantity.all || "..." + } + ), + value: ExportScope.ALL + }, + { + disabled: selectedProducts === 0, + label: intl.formatMessage( + { + defaultMessage: "Selected products ({number})", + description: "export selected products to csv file" + }, + { + number: selectedProducts + } + ), + value: ExportScope.IDS + }, + { + label: intl.formatMessage( + { + defaultMessage: "Current search ({number})", + description: "export filtered products to csv file" + }, + { + number: productQuantity.filter || "..." + } + ), + value: ExportScope.FILTER + } + ]; + + const productExportTypeChoices: Array> = [ + { + label: intl.formatMessage({ + defaultMessage: "Spreadsheet for Excel, Numbers etc.", + description: "export products as spreadsheet" + }), + value: FileTypesEnum.XLSX + }, + { + label: intl.formatMessage({ + defaultMessage: "Plain CSV file", + description: "export products as csv file" + }), + value: FileTypesEnum.CSV + } + ]; + + return ( + <> + +
+ + + ); +}; + +ProductExportDialogSettings.displayName = "ProductExportDialogSettings"; +export default ProductExportDialogSettings; diff --git a/src/products/components/ProductExportDialog/index.ts b/src/products/components/ProductExportDialog/index.ts new file mode 100644 index 000000000..ea211ddcc --- /dev/null +++ b/src/products/components/ProductExportDialog/index.ts @@ -0,0 +1,2 @@ +export * from "./ProductExportDialog"; +export { default } from "./ProductExportDialog"; diff --git a/src/products/components/ProductExportDialog/messages.ts b/src/products/components/ProductExportDialog/messages.ts new file mode 100644 index 000000000..3ec171775 --- /dev/null +++ b/src/products/components/ProductExportDialog/messages.ts @@ -0,0 +1,88 @@ +import { ProductFieldEnum } from "@saleor/types/globalTypes"; +import { useIntl } from "react-intl"; + +function useProductExportFieldMessages() { + const intl = useIntl(); + + const messages = { + [ProductFieldEnum.CATEGORY]: intl.formatMessage({ + defaultMessage: "Category", + description: "product field", + id: "productExportFieldCategory" + }), + [ProductFieldEnum.CHARGE_TAXES]: intl.formatMessage({ + defaultMessage: "Charge Taxes", + description: "product field", + id: "productExportFieldTaxes" + }), + [ProductFieldEnum.COLLECTIONS]: intl.formatMessage({ + defaultMessage: "Collections", + description: "product field", + id: "productExportFieldCollections" + }), + [ProductFieldEnum.COST_PRICE]: intl.formatMessage({ + defaultMessage: "Cost Price", + description: "product field", + id: "productExportFieldPrice" + }), + [ProductFieldEnum.DESCRIPTION]: intl.formatMessage({ + defaultMessage: "Description", + description: "product field", + id: "productExportFieldDescription" + }), + [ProductFieldEnum.NAME]: intl.formatMessage({ + defaultMessage: "Name", + description: "product field", + id: "productExportFieldName" + }), + [ProductFieldEnum.PRODUCT_IMAGES]: intl.formatMessage({ + defaultMessage: "Product Images", + description: "product field", + id: "productExportFieldProductImages" + }), + [ProductFieldEnum.PRODUCT_TYPE]: intl.formatMessage({ + defaultMessage: "Type", + description: "product field", + id: "productExportFieldType" + }), + [ProductFieldEnum.PRODUCT_WEIGHT]: intl.formatMessage({ + defaultMessage: "Export Product Weight", + description: "product field", + id: "productExportFieldProductWeight" + }), + [ProductFieldEnum.VARIANT_IMAGES]: intl.formatMessage({ + defaultMessage: "Variant Images", + description: "product field", + id: "productExportFieldVariantImages" + }), + [ProductFieldEnum.VARIANT_PRICE]: intl.formatMessage({ + defaultMessage: "Variant Price", + description: "product field", + id: "productExportFieldVariantPrice" + }), + [ProductFieldEnum.VARIANT_SKU]: intl.formatMessage({ + defaultMessage: "Export Variant SKU", + description: "product field", + id: "productExportFieldVariantSku" + }), + [ProductFieldEnum.VARIANT_WEIGHT]: intl.formatMessage({ + defaultMessage: "Export Variant Weight", + description: "product field", + id: "productExportFieldVariantWeight" + }), + [ProductFieldEnum.VISIBLE]: intl.formatMessage({ + defaultMessage: "Visibility", + description: "product field", + id: "productExportFieldVisibility" + }), + [ProductFieldEnum.AVAILABLE_FOR_PURCHASE]: intl.formatMessage({ + defaultMessage: "Available for purchase", + description: "product field", + id: "productExportFieldAvailability" + }) + }; + + return (field: ProductFieldEnum) => messages[field]; +} + +export default useProductExportFieldMessages; diff --git a/src/products/components/ProductImageNavigation/ProductImageNavigation.tsx b/src/products/components/ProductImageNavigation/ProductImageNavigation.tsx index 6868013ff..26229bf43 100644 --- a/src/products/components/ProductImageNavigation/ProductImageNavigation.tsx +++ b/src/products/components/ProductImageNavigation/ProductImageNavigation.tsx @@ -1,13 +1,12 @@ import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; import { makeStyles } from "@material-ui/core/styles"; +import CardTitle from "@saleor/components/CardTitle"; +import Skeleton from "@saleor/components/Skeleton"; import classNames from "classnames"; import React from "react"; import { useIntl } from "react-intl"; -import CardTitle from "@saleor/components/CardTitle"; -import Skeleton from "@saleor/components/Skeleton"; - const useStyles = makeStyles( theme => ({ card: { diff --git a/src/products/components/ProductImagePage/ProductImagePage.tsx b/src/products/components/ProductImagePage/ProductImagePage.tsx index aa00dfb82..55b4b85e2 100644 --- a/src/products/components/ProductImagePage/ProductImagePage.tsx +++ b/src/products/components/ProductImagePage/ProductImagePage.tsx @@ -2,9 +2,6 @@ import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; import { makeStyles } from "@material-ui/core/styles"; import TextField from "@material-ui/core/TextField"; -import React from "react"; -import { useIntl } from "react-intl"; - import AppHeader from "@saleor/components/AppHeader"; import CardTitle from "@saleor/components/CardTitle"; import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; @@ -15,6 +12,9 @@ import PageHeader from "@saleor/components/PageHeader"; import SaveButtonBar from "@saleor/components/SaveButtonBar"; import Skeleton from "@saleor/components/Skeleton"; import { commonMessages } from "@saleor/intl"; +import React from "react"; +import { useIntl } from "react-intl"; + import ProductImageNavigation from "../ProductImageNavigation"; const useStyles = makeStyles( diff --git a/src/products/components/ProductImages/ProductImages.tsx b/src/products/components/ProductImages/ProductImages.tsx index 00e5157c4..bc3c750ca 100644 --- a/src/products/components/ProductImages/ProductImages.tsx +++ b/src/products/components/ProductImages/ProductImages.tsx @@ -12,6 +12,7 @@ import classNames from "classnames"; import React from "react"; import { useIntl } from "react-intl"; import { SortableContainer, SortableElement } from "react-sortable-hoc"; + import { ProductDetails_product_images } from "../../types/ProductDetails"; const useStyles = makeStyles( @@ -221,7 +222,7 @@ const ProductImages: React.FC = props => { disabled={loading} variant="text" color="primary" - data-tc="button-upload-image" + data-test="button-upload-image" > {intl.formatMessage(commonMessages.uploadImage)} diff --git a/src/products/components/ProductList/ProductList.tsx b/src/products/components/ProductList/ProductList.tsx index 895194939..0a163a684 100644 --- a/src/products/components/ProductList/ProductList.tsx +++ b/src/products/components/ProductList/ProductList.tsx @@ -3,10 +3,7 @@ import TableBody from "@material-ui/core/TableBody"; import TableCell from "@material-ui/core/TableCell"; import TableFooter from "@material-ui/core/TableFooter"; import TableRow from "@material-ui/core/TableRow"; -import classNames from "classnames"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - +import Typography from "@material-ui/core/Typography"; import Checkbox from "@saleor/components/Checkbox"; import Money from "@saleor/components/Money"; import ResponsiveTable from "@saleor/components/ResponsiveTable"; @@ -24,14 +21,20 @@ import { getAttributeIdFromColumnValue, isAttributeColumnValue } from "@saleor/products/components/ProductListPage/utils"; -import { AvailableInGridAttributes_grid_edges_node } from "@saleor/products/types/AvailableInGridAttributes"; -import { ProductList_products_edges_node } from "@saleor/products/types/ProductList"; +import { GridAttributes_grid_edges_node } from "@saleor/products/types/GridAttributes"; +import { + ProductList_products_edges_node, + ProductList_products_edges_node_pricing_priceRangeUndiscounted +} from "@saleor/products/types/ProductList"; import { ProductListUrlSortField } from "@saleor/products/urls"; import { ListActions, ListProps, SortPage } from "@saleor/types"; import TDisplayColumn, { DisplayColumnProps } from "@saleor/utils/columns/DisplayColumn"; import { getArrowDirection } from "@saleor/utils/sort"; +import classNames from "classnames"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; const useStyles = makeStyles( theme => ({ @@ -40,7 +43,7 @@ const useStyles = makeStyles( width: "auto" }, colPrice: { - width: 200 + width: 300 }, colPublished: { width: 200 @@ -65,6 +68,9 @@ const useStyles = makeStyles( colNameHeader: { marginLeft: AVATAR_MARGIN }, + colNameWrapper: { + display: "block" + }, colPrice: { textAlign: "right" }, @@ -98,7 +104,7 @@ interface ProductListProps ListActions, SortPage { activeAttributeSortId: string; - gridAttributes: AvailableInGridAttributes_grid_edges_node[]; + gridAttributes: GridAttributes_grid_edges_node[]; products: ProductList_products_edges_node[]; } @@ -131,6 +137,51 @@ export const ProductList: React.FC = props => { ); const numberOfColumns = 2 + settings.columns.length; + const getProductPrice = ( + priceRangeUndiscounted: ProductList_products_edges_node_pricing_priceRangeUndiscounted + ) => { + if (!priceRangeUndiscounted) { + return null; + } + + const { start, stop } = priceRangeUndiscounted; + const { + gross: { amount: startAmount } + } = start; + const { + gross: { amount: stopAmount } + } = stop; + + if (startAmount === stopAmount) { + return ( + + ); + } else { + return ( + <> + + {" - "} + + + ); + } + }; + return (
@@ -281,8 +332,8 @@ export const ProductList: React.FC = props => { key={product ? product.id : "skeleton"} onClick={product && onRowClick(product.id)} className={classes.link} - data-tc="id" - data-tc-id={maybe(() => product.id)} + data-test="id" + data-test-id={maybe(() => product.id)} > = props => { product.thumbnail.url)} - data-tc="name" + data-test="name" > - {maybe(() => product.name, )} + {product?.productType ? ( +
+ {product.name} + {product?.productType && ( + + {product.productType.hasVariants ? ( + + ) : ( + + )} + + )} +
+ ) : ( + + )}
= props => { > {product && product.productType ? ( product.productType.name @@ -320,8 +392,8 @@ export const ProductList: React.FC = props => { > product.isPublished)} + data-test="isPublished" + data-test-is-published={maybe(() => product.isPublished)} > {product && maybe(() => product.isPublished !== undefined) ? ( @@ -348,8 +420,8 @@ export const ProductList: React.FC = props => { @@ -373,10 +445,10 @@ export const ProductList: React.FC = props => { displayColumns={settings.columns} > - {maybe(() => product.basePrice) && - maybe(() => product.basePrice.amount) !== undefined && - maybe(() => product.basePrice.currency) !== undefined ? ( - + {product?.pricing?.priceRangeUndiscounted ? ( + getProductPrice( + product?.pricing?.priceRangeUndiscounted + ) ) : ( )} diff --git a/src/products/components/ProductListPage/ProductListPage.tsx b/src/products/components/ProductListPage/ProductListPage.tsx index d0bb14c1d..8bc6b452c 100644 --- a/src/products/components/ProductListPage/ProductListPage.tsx +++ b/src/products/components/ProductListPage/ProductListPage.tsx @@ -1,20 +1,19 @@ import Button from "@material-ui/core/Button"; import Card from "@material-ui/core/Card"; import makeStyles from "@material-ui/core/styles/makeStyles"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - +import CardMenu from "@saleor/components/CardMenu"; import ColumnPicker, { ColumnPickerChoice } from "@saleor/components/ColumnPicker"; import Container from "@saleor/components/Container"; +import FilterBar from "@saleor/components/FilterBar"; import PageHeader from "@saleor/components/PageHeader"; import { ProductListColumns } from "@saleor/config"; import { sectionNames } from "@saleor/intl"; import { - AvailableInGridAttributes_availableInGrid_edges_node, - AvailableInGridAttributes_grid_edges_node -} from "@saleor/products/types/AvailableInGridAttributes"; + GridAttributes_availableInGrid_edges_node, + GridAttributes_grid_edges_node +} from "@saleor/products/types/GridAttributes"; import { ProductList_products_edges_node } from "@saleor/products/types/ProductList"; import { FetchMoreProps, @@ -23,7 +22,9 @@ import { PageListProps, SortPage } from "@saleor/types"; -import FilterBar from "@saleor/components/FilterBar"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { ProductListUrlSortField } from "../../urls"; import ProductList from "../ProductList"; import { @@ -39,17 +40,18 @@ export interface ProductListPageProps FetchMoreProps, SortPage { activeAttributeSortId: string; - availableInGridAttributes: AvailableInGridAttributes_availableInGrid_edges_node[]; + availableInGridAttributes: GridAttributes_availableInGrid_edges_node[]; currencySymbol: string; - gridAttributes: AvailableInGridAttributes_grid_edges_node[]; + gridAttributes: GridAttributes_grid_edges_node[]; totalGridAttributes: number; products: ProductList_products_edges_node[]; + onExport: () => void; } const useStyles = makeStyles( theme => ({ columnPicker: { - marginRight: theme.spacing(3) + margin: theme.spacing(0, 3) } }), { name: "ProductListPage" } @@ -71,6 +73,7 @@ export const ProductListPage: React.FC = props => { totalGridAttributes, onAdd, onAll, + onExport, onFetchMore, onFilterChange, onSearchChange, @@ -119,6 +122,19 @@ export const ProductListPage: React.FC = props => { return ( + = props => { onClick={onAdd} color="primary" variant="contained" - data-tc="add-product" + data-test="add-product" > = props => { value={data.productType} onChange={onProductTypeChange} fetchChoices={fetchProductTypes} - data-tc="product-type" + data-test="product-type" {...fetchMoreProductTypes} /> ) : ( @@ -171,7 +170,7 @@ const ProductOrganization: React.FC = props => { value={data.category} onChange={onCategoryChange} fetchChoices={fetchCategories} - data-tc="category" + data-test="category" {...fetchMoreCategories} /> @@ -196,7 +195,7 @@ const ProductOrganization: React.FC = props => { } onChange={onCollectionChange} fetchChoices={fetchCollections} - data-tc="collections" + data-test="collections" {...fetchMoreCollections} /> diff --git a/src/products/components/ProductPricing/ProductPricing.tsx b/src/products/components/ProductPricing/ProductPricing.tsx index f39d406ed..c51119e69 100644 --- a/src/products/components/ProductPricing/ProductPricing.tsx +++ b/src/products/components/ProductPricing/ProductPricing.tsx @@ -1,14 +1,13 @@ import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; import { makeStyles } from "@material-ui/core/styles"; -import React from "react"; -import { useIntl } from "react-intl"; - import CardTitle from "@saleor/components/CardTitle"; import ControlledCheckbox from "@saleor/components/ControlledCheckbox"; import PriceField from "@saleor/components/PriceField"; -import { ProductErrorFragment } from "@saleor/attributes/types/ProductErrorFragment"; +import { ProductErrorFragment } from "@saleor/fragments/types/ProductErrorFragment"; import { getFormErrors, getProductErrorMessage } from "@saleor/utils/errors"; +import React from "react"; +import { useIntl } from "react-intl"; const useStyles = makeStyles( theme => ({ diff --git a/src/products/components/ProductShipping/ProductShipping.tsx b/src/products/components/ProductShipping/ProductShipping.tsx index ef5373ce4..a4ddcc43c 100644 --- a/src/products/components/ProductShipping/ProductShipping.tsx +++ b/src/products/components/ProductShipping/ProductShipping.tsx @@ -4,10 +4,10 @@ import InputAdornment from "@material-ui/core/InputAdornment"; import TextField from "@material-ui/core/TextField"; import CardTitle from "@saleor/components/CardTitle"; import Grid from "@saleor/components/Grid"; +import { ProductErrorFragment } from "@saleor/fragments/types/ProductErrorFragment"; import { getFormErrors, getProductErrorMessage } from "@saleor/utils/errors"; import React from "react"; import { useIntl } from "react-intl"; -import { ProductErrorFragment } from "@saleor/attributes/types/ProductErrorFragment"; interface ProductShippingProps { data: { diff --git a/src/products/components/ProductStocks/ProductStocks.tsx b/src/products/components/ProductStocks/ProductStocks.tsx index b4d2af73c..1ab107907 100644 --- a/src/products/components/ProductStocks/ProductStocks.tsx +++ b/src/products/components/ProductStocks/ProductStocks.tsx @@ -1,36 +1,35 @@ -import ClickAwayListener from "@material-ui/core/ClickAwayListener"; -import Grow from "@material-ui/core/Grow"; -import Popper from "@material-ui/core/Popper"; -import { fade } from "@material-ui/core/styles/colorManipulator"; -import IconButton from "@material-ui/core/IconButton"; import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; +import ClickAwayListener from "@material-ui/core/ClickAwayListener"; +import Grow from "@material-ui/core/Grow"; +import IconButton from "@material-ui/core/IconButton"; +import MenuItem from "@material-ui/core/MenuItem"; +import Paper from "@material-ui/core/Paper"; +import Popper from "@material-ui/core/Popper"; +import { fade } from "@material-ui/core/styles/colorManipulator"; +import makeStyles from "@material-ui/core/styles/makeStyles"; import Table from "@material-ui/core/Table"; -import TableHead from "@material-ui/core/TableHead"; import TableBody from "@material-ui/core/TableBody"; import TableCell from "@material-ui/core/TableCell"; +import TableHead from "@material-ui/core/TableHead"; import TableRow from "@material-ui/core/TableRow"; import TextField from "@material-ui/core/TextField"; import Typography from "@material-ui/core/Typography"; -import React from "react"; -import { useIntl, FormattedMessage } from "react-intl"; -import makeStyles from "@material-ui/core/styles/makeStyles"; import AddIcon from "@material-ui/icons/Add"; import DeleteIcon from "@material-ui/icons/Delete"; -import Paper from "@material-ui/core/Paper"; -import MenuItem from "@material-ui/core/MenuItem"; - -import { FormChange } from "@saleor/hooks/useForm"; -import { FormsetChange, FormsetAtomicData } from "@saleor/hooks/useFormset"; import CardTitle from "@saleor/components/CardTitle"; -import { getFieldError } from "@saleor/utils/errors"; -import { UserError } from "@saleor/types"; import ControlledCheckbox from "@saleor/components/ControlledCheckbox"; import FormSpacer from "@saleor/components/FormSpacer"; import Hr from "@saleor/components/Hr"; +import { WarehouseFragment } from "@saleor/fragments/types/WarehouseFragment"; +import { FormChange } from "@saleor/hooks/useForm"; +import { FormsetAtomicData, FormsetChange } from "@saleor/hooks/useFormset"; import { renderCollection } from "@saleor/misc"; import { ICONBUTTON_SIZE } from "@saleor/theme"; -import { WarehouseFragment } from "@saleor/warehouses/types/WarehouseFragment"; +import { UserError } from "@saleor/types"; +import { getFieldError } from "@saleor/utils/errors"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; export type ProductStockInput = FormsetAtomicData; export interface ProductStockFormData { diff --git a/src/products/components/ProductUpdatePage/ProductUpdatePage.tsx b/src/products/components/ProductUpdatePage/ProductUpdatePage.tsx index e6b8ade87..d3be9d79e 100644 --- a/src/products/components/ProductUpdatePage/ProductUpdatePage.tsx +++ b/src/products/components/ProductUpdatePage/ProductUpdatePage.tsx @@ -1,18 +1,16 @@ -import { convertFromRaw, RawDraftContentState } from "draft-js"; -import { diff } from "fast-array-diff"; -import React from "react"; -import { useIntl } from "react-intl"; - import AppHeader from "@saleor/components/AppHeader"; +import AvailabilityCard from "@saleor/components/AvailabilityCard"; import CardSpacer from "@saleor/components/CardSpacer"; import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; import Container from "@saleor/components/Container"; import Form from "@saleor/components/Form"; import Grid from "@saleor/components/Grid"; +import Metadata from "@saleor/components/Metadata/Metadata"; import PageHeader from "@saleor/components/PageHeader"; import SaveButtonBar from "@saleor/components/SaveButtonBar"; import SeoForm from "@saleor/components/SeoForm"; -import VisibilityCard from "@saleor/components/VisibilityCard"; +import { ProductErrorFragment } from "@saleor/fragments/types/ProductErrorFragment"; +import { WarehouseFragment } from "@saleor/fragments/types/WarehouseFragment"; import useDateLocalize from "@saleor/hooks/useDateLocalize"; import useFormset from "@saleor/hooks/useFormset"; import useStateFromProps from "@saleor/hooks/useStateFromProps"; @@ -23,8 +21,12 @@ import { SearchCollections_search_edges_node } from "@saleor/searches/types/Sear import { FetchMoreProps, ListActions } from "@saleor/types"; import createMultiAutocompleteSelectHandler from "@saleor/utils/handlers/multiAutocompleteSelectChangeHandler"; import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler"; -import { ProductErrorFragment } from "@saleor/attributes/types/ProductErrorFragment"; -import { WarehouseFragment } from "@saleor/warehouses/types/WarehouseFragment"; +import useMetadataChangeTrigger from "@saleor/utils/metadata/useMetadataChangeTrigger"; +import { convertFromRaw, RawDraftContentState } from "draft-js"; +import { diff } from "fast-array-diff"; +import React from "react"; +import { useIntl } from "react-intl"; + import { ProductDetails_product, ProductDetails_product_images, @@ -35,9 +37,9 @@ import { getChoices, getProductUpdatePageFormData, getSelectedAttributesFromProduct, + getStockInputFromProduct, ProductAttributeValueChoices, - ProductUpdatePageFormData, - getStockInputFromProduct + ProductUpdatePageFormData } from "../../utils/data"; import { createAttributeChangeHandler, @@ -48,9 +50,9 @@ import ProductDetailsForm from "../ProductDetailsForm"; import ProductImages from "../ProductImages"; import ProductOrganization from "../ProductOrganization"; import ProductPricing from "../ProductPricing"; -import ProductVariants from "../ProductVariants"; -import ProductStocks, { ProductStockInput } from "../ProductStocks"; import ProductShipping from "../ProductShipping/ProductShipping"; +import ProductStocks, { ProductStockInput } from "../ProductStocks"; +import ProductVariants from "../ProductVariants"; export interface ProductUpdatePageProps extends ListActions { defaultWeightUnit: string; @@ -155,6 +157,12 @@ export const ProductUpdatePage: React.FC = ({ getChoices(maybe(() => product.collections, [])) ); + const { + isMetadataModified, + isPrivateMetadataModified, + makeChangeHandler: makeMetadataChangeHandler + } = useMetadataChangeTrigger(); + const initialData = getProductUpdatePageFormData(product, variants); const initialDescription = maybe(() => JSON.parse(product.descriptionJson) @@ -162,27 +170,47 @@ export const ProductUpdatePage: React.FC = ({ const categories = getChoices(categoryChoiceList); const collections = getChoices(collectionChoiceList); - const currency = maybe(() => product.basePrice.currency); + const currency = + product?.variants?.length && product.variants[0].price.currency; const hasVariants = maybe(() => product.productType.hasVariants, false); const handleSubmit = (data: ProductUpdatePageFormData) => { - const dataStocks = stocks.map(stock => stock.id); - const variantStocks = product.variants[0].stocks.map( - stock => stock.warehouse.id - ); - const stockDiff = diff(variantStocks, dataStocks); + const metadata = isMetadataModified ? data.metadata : undefined; + const privateMetadata = isPrivateMetadataModified + ? data.privateMetadata + : undefined; - onSubmit({ - ...data, - addStocks: stocks.filter(stock => - stockDiff.added.some(addedStock => addedStock === stock.id) - ), - attributes, - removeStocks: stockDiff.removed, - updateStocks: stocks.filter( - stock => !stockDiff.added.some(addedStock => addedStock === stock.id) - ) - }); + if (product.productType.hasVariants) { + onSubmit({ + ...data, + addStocks: [], + attributes, + metadata, + privateMetadata, + removeStocks: [], + updateStocks: [] + }); + } else { + const dataStocks = stocks.map(stock => stock.id); + const variantStocks = product.variants[0]?.stocks.map( + stock => stock.warehouse.id + ); + const stockDiff = diff(variantStocks, dataStocks); + + onSubmit({ + ...data, + addStocks: stocks.filter(stock => + stockDiff.added.some(addedStock => addedStock === stock.id) + ), + attributes, + metadata, + privateMetadata, + removeStocks: stockDiff.removed, + updateStocks: stocks.filter( + stock => !stockDiff.added.some(addedStock => addedStock === stock.id) + ) + }); + } }; return ( @@ -213,6 +241,7 @@ export const ProductUpdatePage: React.FC = ({ attributes, triggerChange ); + const changeMetadata = makeMetadataChangeHandler(change); return ( <> @@ -249,19 +278,27 @@ export const ProductUpdatePage: React.FC = ({ /> )} - - + {!!product?.productType && !hasVariants && ( + <> + + + + )} {hasVariants ? ( = ({ "Add search engine title and description to make this product easier to find" })} /> + +
= ({ onCollectionChange={handleCollectionSelect} /> -
diff --git a/src/products/components/ProductVariantAttributes/ProductVariantAttributes.tsx b/src/products/components/ProductVariantAttributes/ProductVariantAttributes.tsx index bad74b2b5..9685f24a0 100644 --- a/src/products/components/ProductVariantAttributes/ProductVariantAttributes.tsx +++ b/src/products/components/ProductVariantAttributes/ProductVariantAttributes.tsx @@ -1,9 +1,6 @@ import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; import Typography from "@material-ui/core/Typography"; -import React from "react"; -import { useIntl } from "react-intl"; - import CardTitle from "@saleor/components/CardTitle"; import FormSpacer from "@saleor/components/FormSpacer"; import Grid from "@saleor/components/Grid"; @@ -11,11 +8,13 @@ import SingleAutocompleteSelectField, { SingleAutocompleteChoiceType } from "@saleor/components/SingleAutocompleteSelectField"; import Skeleton from "@saleor/components/Skeleton"; +import { ProductVariant_attributes_attribute_values } from "@saleor/fragments/types/ProductVariant"; import { FormsetAtomicData, FormsetChange } from "@saleor/hooks/useFormset"; import { commonMessages } from "@saleor/intl"; import { VariantCreate_productVariantCreate_errors } from "@saleor/products/types/VariantCreate"; import { getProductVariantAttributeErrorMessage } from "@saleor/utils/errors/product"; -import { ProductVariant_attributes_attribute_values } from "../../types/ProductVariant"; +import React from "react"; +import { useIntl } from "react-intl"; export interface VariantAttributeInputData { values: ProductVariant_attributes_attribute_values[]; @@ -100,7 +99,7 @@ const ProductVariantAttributes: React.FC = ({ value={getAttributeValue(attribute.id, attributes)} choices={getAttributeValueChoices(attribute.id, attributes)} allowCustomValues - data-tc="variant-attribute-input" + data-test="variant-attribute-input" /> )) )} diff --git a/src/products/components/ProductVariantCreatePage/ProductVariantCreatePage.tsx b/src/products/components/ProductVariantCreatePage/ProductVariantCreatePage.tsx index 2e59ea446..ac79fad42 100644 --- a/src/products/components/ProductVariantCreatePage/ProductVariantCreatePage.tsx +++ b/src/products/components/ProductVariantCreatePage/ProductVariantCreatePage.tsx @@ -1,35 +1,37 @@ -import React from "react"; -import { useIntl } from "react-intl"; - import AppHeader from "@saleor/components/AppHeader"; import CardSpacer from "@saleor/components/CardSpacer"; import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; import Container from "@saleor/components/Container"; import Form from "@saleor/components/Form"; import Grid from "@saleor/components/Grid"; +import Metadata, { MetadataFormData } from "@saleor/components/Metadata"; import PageHeader from "@saleor/components/PageHeader"; import SaveButtonBar from "@saleor/components/SaveButtonBar"; +import { ProductErrorFragment } from "@saleor/fragments/types/ProductErrorFragment"; import useFormset, { FormsetChange, FormsetData } from "@saleor/hooks/useFormset"; import { getVariantAttributeInputFromProduct } from "@saleor/products/utils/data"; -import { ProductErrorFragment } from "@saleor/attributes/types/ProductErrorFragment"; import { SearchWarehouses_search_edges_node } from "@saleor/searches/types/SearchWarehouses"; +import useMetadataChangeTrigger from "@saleor/utils/metadata/useMetadataChangeTrigger"; +import React from "react"; +import { useIntl } from "react-intl"; + import { maybe } from "../../../misc"; import { ProductVariantCreateData_product } from "../../types/ProductVariantCreateData"; import ProductShipping from "../ProductShipping/ProductShipping"; +import ProductStocks, { ProductStockInput } from "../ProductStocks"; import ProductVariantAttributes, { VariantAttributeInputData } from "../ProductVariantAttributes"; import ProductVariantNavigation from "../ProductVariantNavigation"; import ProductVariantPrice from "../ProductVariantPrice"; -import ProductStocks, { ProductStockInput } from "../ProductStocks"; -interface ProductVariantCreatePageFormData { +interface ProductVariantCreatePageFormData extends MetadataFormData { costPrice: string; images: string[]; - priceOverride: string; + price: string; quantity: string; sku: string; trackInventory: boolean; @@ -83,11 +85,16 @@ const ProductVariantCreatePage: React.FC = ({ data: stocks, remove: removeStock } = useFormset([]); + const { + makeChangeHandler: makeMetadataChangeHandler + } = useMetadataChangeTrigger(); const initialForm: ProductVariantCreatePageFormData = { costPrice: "", images: maybe(() => product.images.map(image => image.id)), - priceOverride: "", + metadata: [], + price: "", + privateMetadata: [], quantity: "0", sku: "", trackInventory: true, @@ -108,6 +115,7 @@ const ProductVariantCreatePage: React.FC = ({ changeAttributeData(id, value); triggerChange(); }; + const changeMetadata = makeMetadataChangeHandler(change); return ( @@ -135,7 +143,7 @@ const ProductVariantCreatePage: React.FC = ({ = ({ removeStock(id); }} /> + +
({ diff --git a/src/products/components/ProductVariantCreatorPage/ProductVariantCreatorPriceAndSku.tsx b/src/products/components/ProductVariantCreatorPage/ProductVariantCreatorPriceAndSku.tsx index 52ccf460c..79b0a7324 100644 --- a/src/products/components/ProductVariantCreatorPage/ProductVariantCreatorPriceAndSku.tsx +++ b/src/products/components/ProductVariantCreatorPage/ProductVariantCreatorPriceAndSku.tsx @@ -1,8 +1,8 @@ +import CardSpacer from "@saleor/components/CardSpacer"; +import { WarehouseFragment } from "@saleor/fragments/types/WarehouseFragment"; +import { ProductDetails_product_productType_variantAttributes } from "@saleor/products/types/ProductDetails"; import React from "react"; -import { ProductDetails_product_productType_variantAttributes } from "@saleor/products/types/ProductDetails"; -import CardSpacer from "@saleor/components/CardSpacer"; -import { WarehouseFragment } from "@saleor/warehouses/types/WarehouseFragment"; import { ProductVariantCreateFormData, VariantCreatorPricesAndSkuMode diff --git a/src/products/components/ProductVariantCreatorPage/ProductVariantCreatorPrices.tsx b/src/products/components/ProductVariantCreatorPage/ProductVariantCreatorPrices.tsx index 21ddd1938..31100a0cb 100644 --- a/src/products/components/ProductVariantCreatorPage/ProductVariantCreatorPrices.tsx +++ b/src/products/components/ProductVariantCreatorPage/ProductVariantCreatorPrices.tsx @@ -1,20 +1,20 @@ -import FormControlLabel from "@material-ui/core/FormControlLabel"; import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; +import FormControlLabel from "@material-ui/core/FormControlLabel"; import Radio from "@material-ui/core/Radio"; import RadioGroup from "@material-ui/core/RadioGroup"; import { makeStyles } from "@material-ui/core/styles"; import TextField from "@material-ui/core/TextField"; import Typography from "@material-ui/core/Typography"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - +import CardTitle from "@saleor/components/CardTitle"; import FormSpacer from "@saleor/components/FormSpacer"; import Grid from "@saleor/components/Grid"; import Hr from "@saleor/components/Hr"; import SingleSelectField from "@saleor/components/SingleSelectField"; import { ProductDetails_product_productType_variantAttributes } from "@saleor/products/types/ProductDetails"; -import CardTitle from "@saleor/components/CardTitle"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { ProductVariantCreateFormData, VariantCreatorPricesAndSkuMode diff --git a/src/products/components/ProductVariantCreatorPage/ProductVariantCreatorStock.tsx b/src/products/components/ProductVariantCreatorPage/ProductVariantCreatorStock.tsx index b087073a9..51770851a 100644 --- a/src/products/components/ProductVariantCreatorPage/ProductVariantCreatorStock.tsx +++ b/src/products/components/ProductVariantCreatorPage/ProductVariantCreatorStock.tsx @@ -1,23 +1,23 @@ -import FormControlLabel from "@material-ui/core/FormControlLabel"; import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; +import FormControlLabel from "@material-ui/core/FormControlLabel"; import Radio from "@material-ui/core/Radio"; import RadioGroup from "@material-ui/core/RadioGroup"; import { makeStyles } from "@material-ui/core/styles"; import TextField from "@material-ui/core/TextField"; import Typography from "@material-ui/core/Typography"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - +import CardSpacer from "@saleor/components/CardSpacer"; +import CardTitle from "@saleor/components/CardTitle"; +import ControlledCheckbox from "@saleor/components/ControlledCheckbox"; import FormSpacer from "@saleor/components/FormSpacer"; import Hr from "@saleor/components/Hr"; import SingleSelectField from "@saleor/components/SingleSelectField"; +import { WarehouseFragment } from "@saleor/fragments/types/WarehouseFragment"; import { ProductDetails_product_productType_variantAttributes } from "@saleor/products/types/ProductDetails"; -import CardTitle from "@saleor/components/CardTitle"; -import { WarehouseFragment } from "@saleor/warehouses/types/WarehouseFragment"; -import CardSpacer from "@saleor/components/CardSpacer"; -import ControlledCheckbox from "@saleor/components/ControlledCheckbox"; import { isSelected } from "@saleor/utils/lists"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { ProductVariantCreateFormData, VariantCreatorPricesAndSkuMode diff --git a/src/products/components/ProductVariantCreatorPage/ProductVariantCreatorSummary.tsx b/src/products/components/ProductVariantCreatorPage/ProductVariantCreatorSummary.tsx index 620c7ea31..904a2e181 100644 --- a/src/products/components/ProductVariantCreatorPage/ProductVariantCreatorSummary.tsx +++ b/src/products/components/ProductVariantCreatorPage/ProductVariantCreatorSummary.tsx @@ -1,24 +1,24 @@ +import Card from "@material-ui/core/Card"; import blue from "@material-ui/core/colors/blue"; import cyan from "@material-ui/core/colors/cyan"; import green from "@material-ui/core/colors/green"; import purple from "@material-ui/core/colors/purple"; import yellow from "@material-ui/core/colors/yellow"; -import Card from "@material-ui/core/Card"; import IconButton from "@material-ui/core/IconButton"; import { makeStyles, Theme } from "@material-ui/core/styles"; import TextField from "@material-ui/core/TextField"; import DeleteIcon from "@material-ui/icons/Delete"; -import classNames from "classnames"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - +import CardTitle from "@saleor/components/CardTitle"; +import Hr from "@saleor/components/Hr"; +import { WarehouseFragment } from "@saleor/fragments/types/WarehouseFragment"; import { ProductVariantBulkCreate_productVariantBulkCreate_errors } from "@saleor/products/types/ProductVariantBulkCreate"; import { ProductVariantBulkCreateInput } from "@saleor/types/globalTypes"; import { getFormErrors } from "@saleor/utils/errors"; import { getBulkProductErrorMessage } from "@saleor/utils/errors/product"; -import CardTitle from "@saleor/components/CardTitle"; -import { WarehouseFragment } from "@saleor/warehouses/types/WarehouseFragment"; -import Hr from "@saleor/components/Hr"; +import classNames from "classnames"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { ProductDetails_product_productType_variantAttributes } from "../../types/ProductDetails"; import { ProductVariantCreateFormData } from "./form"; import { VariantField } from "./reducer"; @@ -203,7 +203,7 @@ const ProductVariantCreatorSummary: React.FC error => error.index === variantIndex ); const variantFormErrors = getFormErrors( - ["priceOverride", "quantity", "sku"], + ["price", "quantity", "sku"], variantErrors ); @@ -234,9 +234,9 @@ const ProductVariantCreatorSummary: React.FC endAdornment: currencySymbol }} className={classes.input} - error={!!variantFormErrors.priceOverride} + error={!!variantFormErrors.price} helperText={getBulkProductErrorMessage( - variantFormErrors.priceOverride, + variantFormErrors.price, intl )} inputProps={{ @@ -244,7 +244,7 @@ const ProductVariantCreatorSummary: React.FC type: "number" }} fullWidth - value={variant.priceOverride} + value={variant.price} onChange={event => onVariantDataChange( variantIndex, diff --git a/src/products/components/ProductVariantCreatorPage/ProductVariantCreatorTabs.tsx b/src/products/components/ProductVariantCreatorPage/ProductVariantCreatorTabs.tsx index 49c4ab52a..2e93ebff7 100644 --- a/src/products/components/ProductVariantCreatorPage/ProductVariantCreatorTabs.tsx +++ b/src/products/components/ProductVariantCreatorPage/ProductVariantCreatorTabs.tsx @@ -1,16 +1,12 @@ -import { makeStyles } from "@material-ui/core/styles"; -import Typography from "@material-ui/core/Typography"; -import classNames from "classnames"; +import makeCreatorSteps, { Step } from "@saleor/components/CreatorSteps"; import React from "react"; -import { IntlShape, useIntl } from "react-intl"; +import { useIntl } from "react-intl"; import { ProductVariantCreatorStep } from "./types"; -interface Step { - label: string; - value: ProductVariantCreatorStep; -} -function getSteps(intl: IntlShape): Step[] { +function useSteps(): Array> { + const intl = useIntl(); + return [ { label: intl.formatMessage({ @@ -36,69 +32,27 @@ function getSteps(intl: IntlShape): Step[] { ]; } -const useStyles = makeStyles( - theme => ({ - label: { - fontSize: 14, - textAlign: "center" - }, - root: { - borderBottom: `1px solid ${theme.palette.divider}`, - display: "flex", - justifyContent: "space-between", - marginBottom: theme.spacing(3) - }, - tab: { - flex: 1, - paddingBottom: theme.spacing(), - userSelect: "none" - }, - tabActive: { - fontWeight: 600 - }, - tabVisited: { - borderBottom: `3px solid ${theme.palette.primary.main}`, - cursor: "pointer" - } - }), - { - name: "ProductVariantCreatorTabs" - } -); +const ProductVariantCreatorSteps = makeCreatorSteps< + ProductVariantCreatorStep +>(); export interface ProductVariantCreatorTabsProps { step: ProductVariantCreatorStep; onStepClick: (step: ProductVariantCreatorStep) => void; } -const ProductVariantCreatorTabs: React.FC = props => { - const { step: currentStep, onStepClick } = props; - const classes = useStyles(props); - const intl = useIntl(); - const steps = getSteps(intl); +const ProductVariantCreatorTabs: React.FC = ({ + step: currentStep, + onStepClick +}) => { + const steps = useSteps(); return ( -
- {steps.map((step, stepIndex) => { - const visitedStep = - steps.findIndex(step => step.value === currentStep) >= stepIndex; - - return ( -
onStepClick(step.value) : undefined} - key={step.value} - > - - {step.label} - -
- ); - })} -
+ ); }; diff --git a/src/products/components/ProductVariantCreatorPage/ProductVariantCreatorValues.tsx b/src/products/components/ProductVariantCreatorPage/ProductVariantCreatorValues.tsx index b482bbd30..3584aa14c 100644 --- a/src/products/components/ProductVariantCreatorPage/ProductVariantCreatorValues.tsx +++ b/src/products/components/ProductVariantCreatorPage/ProductVariantCreatorValues.tsx @@ -1,15 +1,15 @@ -import makeStyles from "@material-ui/core/styles/makeStyles"; import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; -import React from "react"; - +import makeStyles from "@material-ui/core/styles/makeStyles"; +import CardSpacer from "@saleor/components/CardSpacer"; +import CardTitle from "@saleor/components/CardTitle"; import ControlledCheckbox from "@saleor/components/ControlledCheckbox"; import Debounce from "@saleor/components/Debounce"; import Skeleton from "@saleor/components/Skeleton"; import { ProductDetails_product_productType_variantAttributes } from "@saleor/products/types/ProductDetails"; import { isSelected } from "@saleor/utils/lists"; -import CardTitle from "@saleor/components/CardTitle"; -import CardSpacer from "@saleor/components/CardSpacer"; +import React from "react"; + import { ProductVariantCreateFormData } from "./form"; export interface ProductVariantCreatorValuesProps { diff --git a/src/products/components/ProductVariantCreatorPage/__snapshots__/reducer.test.ts.snap b/src/products/components/ProductVariantCreatorPage/__snapshots__/reducer.test.ts.snap index 32a195361..23447aca2 100644 --- a/src/products/components/ProductVariantCreatorPage/__snapshots__/reducer.test.ts.snap +++ b/src/products/components/ProductVariantCreatorPage/__snapshots__/reducer.test.ts.snap @@ -87,7 +87,7 @@ Object { ], }, ], - "priceOverride": "24.99", + "price": "24.99", "sku": "", "stocks": Array [ Object { @@ -129,7 +129,7 @@ Object { ], }, ], - "priceOverride": "24.99", + "price": "24.99", "sku": "", "stocks": Array [ Object { @@ -171,7 +171,7 @@ Object { ], }, ], - "priceOverride": "26.99", + "price": "26.99", "sku": "", "stocks": Array [ Object { @@ -213,7 +213,7 @@ Object { ], }, ], - "priceOverride": "49.99", + "price": "49.99", "sku": "", "stocks": Array [ Object { @@ -255,7 +255,7 @@ Object { ], }, ], - "priceOverride": "24.99", + "price": "24.99", "sku": "", "stocks": Array [ Object { @@ -297,7 +297,7 @@ Object { ], }, ], - "priceOverride": "24.99", + "price": "24.99", "sku": "", "stocks": Array [ Object { @@ -339,7 +339,7 @@ Object { ], }, ], - "priceOverride": "26.99", + "price": "26.99", "sku": "", "stocks": Array [ Object { @@ -381,7 +381,7 @@ Object { ], }, ], - "priceOverride": "26.99", + "price": "26.99", "sku": "", "stocks": Array [ Object { @@ -499,7 +499,7 @@ Object { ], }, ], - "priceOverride": "24.99", + "price": "24.99", "sku": "", "stocks": Array [ Object { @@ -541,7 +541,7 @@ Object { ], }, ], - "priceOverride": "24.99", + "price": "24.99", "sku": "", "stocks": Array [ Object { @@ -583,7 +583,7 @@ Object { ], }, ], - "priceOverride": "26.99", + "price": "26.99", "sku": "", "stocks": Array [ Object { @@ -625,7 +625,7 @@ Object { ], }, ], - "priceOverride": "26.99", + "price": "26.99", "sku": "", "stocks": Array [ Object { @@ -667,7 +667,7 @@ Object { ], }, ], - "priceOverride": "24.99", + "price": "24.99", "sku": "", "stocks": Array [ Object { @@ -709,7 +709,7 @@ Object { ], }, ], - "priceOverride": "24.99", + "price": "24.99", "sku": "", "stocks": Array [ Object { @@ -751,7 +751,7 @@ Object { ], }, ], - "priceOverride": "26.99", + "price": "26.99", "sku": "", "stocks": Array [ Object { @@ -793,7 +793,7 @@ Object { ], }, ], - "priceOverride": "26.99", + "price": "26.99", "sku": "", "stocks": Array [ Object { @@ -930,7 +930,7 @@ Object { ], }, ], - "priceOverride": "45.99", + "price": "45.99", "sku": "", "stocks": Array [ Object { @@ -972,7 +972,7 @@ Object { ], }, ], - "priceOverride": "45.99", + "price": "45.99", "sku": "", "stocks": Array [ Object { @@ -1014,7 +1014,7 @@ Object { ], }, ], - "priceOverride": "45.99", + "price": "45.99", "sku": "", "stocks": Array [ Object { @@ -1056,7 +1056,7 @@ Object { ], }, ], - "priceOverride": "45.99", + "price": "45.99", "sku": "", "stocks": Array [ Object { @@ -1098,7 +1098,7 @@ Object { ], }, ], - "priceOverride": "45.99", + "price": "45.99", "sku": "", "stocks": Array [ Object { @@ -1140,7 +1140,7 @@ Object { ], }, ], - "priceOverride": "45.99", + "price": "45.99", "sku": "", "stocks": Array [ Object { @@ -1182,7 +1182,7 @@ Object { ], }, ], - "priceOverride": "45.99", + "price": "45.99", "sku": "", "stocks": Array [ Object { @@ -1224,7 +1224,7 @@ Object { ], }, ], - "priceOverride": "45.99", + "price": "45.99", "sku": "", "stocks": Array [ Object { @@ -1328,7 +1328,7 @@ Object { ], }, ], - "priceOverride": "45.99", + "price": "45.99", "sku": "", "stocks": Array [ Object { @@ -1370,7 +1370,7 @@ Object { ], }, ], - "priceOverride": "45.99", + "price": "45.99", "sku": "", "stocks": Array [ Object { @@ -1412,7 +1412,7 @@ Object { ], }, ], - "priceOverride": "45.99", + "price": "45.99", "sku": "", "stocks": Array [ Object { @@ -1454,7 +1454,7 @@ Object { ], }, ], - "priceOverride": "45.99", + "price": "45.99", "sku": "", "stocks": Array [ Object { @@ -1496,7 +1496,7 @@ Object { ], }, ], - "priceOverride": "51.99", + "price": "51.99", "sku": "", "stocks": Array [ Object { @@ -1538,7 +1538,7 @@ Object { ], }, ], - "priceOverride": "51.99", + "price": "51.99", "sku": "", "stocks": Array [ Object { @@ -1580,7 +1580,7 @@ Object { ], }, ], - "priceOverride": "51.99", + "price": "51.99", "sku": "", "stocks": Array [ Object { @@ -1622,7 +1622,7 @@ Object { ], }, ], - "priceOverride": "51.99", + "price": "51.99", "sku": "", "stocks": Array [ Object { @@ -1717,7 +1717,7 @@ Object { ], }, ], - "priceOverride": "10.99", + "price": "10.99", "sku": "", "stocks": Array [ Object { @@ -1759,7 +1759,7 @@ Object { ], }, ], - "priceOverride": "10.99", + "price": "10.99", "sku": "", "stocks": Array [ Object { @@ -1801,7 +1801,7 @@ Object { ], }, ], - "priceOverride": "10.99", + "price": "10.99", "sku": "", "stocks": Array [ Object { @@ -1843,7 +1843,7 @@ Object { ], }, ], - "priceOverride": "10.99", + "price": "10.99", "sku": "", "stocks": Array [ Object { @@ -1885,7 +1885,7 @@ Object { ], }, ], - "priceOverride": "10.99", + "price": "10.99", "sku": "", "stocks": Array [ Object { @@ -1927,7 +1927,7 @@ Object { ], }, ], - "priceOverride": "10.99", + "price": "10.99", "sku": "", "stocks": Array [ Object { @@ -1969,7 +1969,7 @@ Object { ], }, ], - "priceOverride": "10.99", + "price": "10.99", "sku": "", "stocks": Array [ Object { @@ -2011,7 +2011,7 @@ Object { ], }, ], - "priceOverride": "10.99", + "price": "10.99", "sku": "", "stocks": Array [ Object { @@ -2119,7 +2119,7 @@ Object { ], }, ], - "priceOverride": "10.99", + "price": "10.99", "sku": "", "stocks": Array [ Object { @@ -2149,7 +2149,7 @@ Object { ], }, ], - "priceOverride": "10.99", + "price": "10.99", "sku": "", "stocks": Array [ Object { @@ -2179,7 +2179,7 @@ Object { ], }, ], - "priceOverride": "10.99", + "price": "10.99", "sku": "", "stocks": Array [ Object { @@ -2209,7 +2209,7 @@ Object { ], }, ], - "priceOverride": "10.99", + "price": "10.99", "sku": "", "stocks": Array [ Object { @@ -2239,7 +2239,7 @@ Object { ], }, ], - "priceOverride": "10.99", + "price": "10.99", "sku": "", "stocks": Array [ Object { @@ -2269,7 +2269,7 @@ Object { ], }, ], - "priceOverride": "10.99", + "price": "10.99", "sku": "", "stocks": Array [ Object { @@ -2299,7 +2299,7 @@ Object { ], }, ], - "priceOverride": "10.99", + "price": "10.99", "sku": "", "stocks": Array [ Object { @@ -2329,7 +2329,7 @@ Object { ], }, ], - "priceOverride": "10.99", + "price": "10.99", "sku": "", "stocks": Array [ Object { diff --git a/src/products/components/ProductVariantCreatorPage/createVariants.test.ts b/src/products/components/ProductVariantCreatorPage/createVariants.test.ts index 9fbcd609d..e0319c1ab 100644 --- a/src/products/components/ProductVariantCreatorPage/createVariants.test.ts +++ b/src/products/components/ProductVariantCreatorPage/createVariants.test.ts @@ -43,7 +43,7 @@ describe("Creates variant matrix", () => { ); variants.forEach(variant => { - expect(variant.priceOverride).toBe(price); + expect(variant.price).toBe(price); variant.stocks.forEach((_, stockIndex) => { expect(variant.stocks[stockIndex].quantity).toBe(stock[stockIndex]); }); @@ -98,7 +98,7 @@ describe("Creates variant matrix", () => { ).values[0] === attributeValue ) .forEach(variant => { - expect(variant.priceOverride).toBe( + expect(variant.price).toBe( (price * (attributeValueIndex + 1)).toString() ); }); @@ -141,7 +141,7 @@ describe("Creates variant matrix", () => { ); variants.forEach(variant => { - expect(variant.priceOverride).toBe(price); + expect(variant.price).toBe(price); }); attribute.values.forEach((attributeValue, attributeValueIndex) => { @@ -210,7 +210,7 @@ describe("Creates variant matrix", () => { ).values[0] === attributeValue ) .forEach(variant => { - expect(variant.priceOverride).toBe( + expect(variant.price).toBe( (price * (attributeValueIndex + 1)).toString() ); }); diff --git a/src/products/components/ProductVariantCreatorPage/createVariants.ts b/src/products/components/ProductVariantCreatorPage/createVariants.ts index 231ad44a8..462be5760 100644 --- a/src/products/components/ProductVariantCreatorPage/createVariants.ts +++ b/src/products/components/ProductVariantCreatorPage/createVariants.ts @@ -1,4 +1,5 @@ import { ProductVariantBulkCreateInput } from "@saleor/types/globalTypes"; + import { AllOrAttribute, Attribute, @@ -45,7 +46,7 @@ function createVariant( data: ProductVariantCreateFormData, attributes: CreateVariantInput ): ProductVariantBulkCreateInput { - const priceOverride = getValueFromMode(attributes, data.price, "0"); + const price = getValueFromMode(attributes, data.price, "0"); const stocks = getValueFromMode( attributes, data.stock, @@ -57,7 +58,7 @@ function createVariant( id: attribute.attributeId, values: [attribute.attributeValueSlug] })), - priceOverride, + price, sku: "", stocks: stocks.map((quantity, stockIndex) => ({ quantity, diff --git a/src/products/components/ProductVariantCreatorPage/fixtures.ts b/src/products/components/ProductVariantCreatorPage/fixtures.ts index 41aacbd6b..c0878f527 100644 --- a/src/products/components/ProductVariantCreatorPage/fixtures.ts +++ b/src/products/components/ProductVariantCreatorPage/fixtures.ts @@ -1,4 +1,5 @@ -import { WarehouseFragment } from "@saleor/warehouses/types/WarehouseFragment"; +import { WarehouseFragment } from "@saleor/fragments/types/WarehouseFragment"; + import { createVariants } from "./createVariants"; import { AllOrAttribute, diff --git a/src/products/components/ProductVariantCreatorPage/form.ts b/src/products/components/ProductVariantCreatorPage/form.ts index db3f2c46d..1622dd86e 100644 --- a/src/products/components/ProductVariantCreatorPage/form.ts +++ b/src/products/components/ProductVariantCreatorPage/form.ts @@ -1,5 +1,6 @@ +import { WarehouseFragment } from "@saleor/fragments/types/WarehouseFragment"; import { ProductDetails_product_productType_variantAttributes } from "@saleor/products/types/ProductDetails"; -import { WarehouseFragment } from "@saleor/warehouses/types/WarehouseFragment"; + import { ProductVariantBulkCreateInput } from "../../../types/globalTypes"; export interface AttributeValue { diff --git a/src/products/components/ProductVariantCreatorPage/reducer.test.ts b/src/products/components/ProductVariantCreatorPage/reducer.test.ts index 7cab43af8..ce6f8debf 100644 --- a/src/products/components/ProductVariantCreatorPage/reducer.test.ts +++ b/src/products/components/ProductVariantCreatorPage/reducer.test.ts @@ -6,8 +6,8 @@ import { warehouses } from "./fixtures"; import reducer, { - VariantField, - ProductVariantCreateReducerActionType + ProductVariantCreateReducerActionType, + VariantField } from "./reducer"; function execActions( @@ -250,9 +250,9 @@ describe("Reducer is able to", () => { } ]); - expect(state.variants[variantIndex].priceOverride).toBe(value); - expect(state.variants[variantIndex - 1].priceOverride).toBe( - fourthStep.variants[variantIndex - 1].priceOverride + expect(state.variants[variantIndex].price).toBe(value); + expect(state.variants[variantIndex - 1].price).toBe( + fourthStep.variants[variantIndex - 1].price ); expect(state).toMatchSnapshot(); }); diff --git a/src/products/components/ProductVariantCreatorPage/reducer.ts b/src/products/components/ProductVariantCreatorPage/reducer.ts index 23b387af7..5f702218c 100644 --- a/src/products/components/ProductVariantCreatorPage/reducer.ts +++ b/src/products/components/ProductVariantCreatorPage/reducer.ts @@ -1,12 +1,13 @@ +import { StockInput } from "@saleor/types/globalTypes"; import { add, remove, removeAtIndex, toggle, - updateAtIndex, - update + update, + updateAtIndex } from "@saleor/utils/lists"; -import { StockInput } from "@saleor/types/globalTypes"; + import { createVariants } from "./createVariants"; import { ProductVariantCreateFormData, @@ -300,7 +301,7 @@ function changeVariantData( ...state.variants[variantIndex] }; if (field === "price") { - variant.priceOverride = value; + variant.price = value; } else if (field === "sku") { variant.sku = value; } diff --git a/src/products/components/ProductVariantCreatorPage/utils.ts b/src/products/components/ProductVariantCreatorPage/utils.ts index eae1a5714..d14daf64b 100644 --- a/src/products/components/ProductVariantCreatorPage/utils.ts +++ b/src/products/components/ProductVariantCreatorPage/utils.ts @@ -1,7 +1,8 @@ import { - ProductDetails_product_productType_variantAttributes_values, - ProductDetails_product_productType_variantAttributes + ProductDetails_product_productType_variantAttributes, + ProductDetails_product_productType_variantAttributes_values } from "@saleor/products/types/ProductDetails"; + import { ProductVariantCreateFormData } from "./form"; export function getPriceAttributeValues( diff --git a/src/products/components/ProductVariantDeleteDialog/ProductVariantDeleteDialog.tsx b/src/products/components/ProductVariantDeleteDialog/ProductVariantDeleteDialog.tsx index d3855fb8c..4ef3a39ee 100644 --- a/src/products/components/ProductVariantDeleteDialog/ProductVariantDeleteDialog.tsx +++ b/src/products/components/ProductVariantDeleteDialog/ProductVariantDeleteDialog.tsx @@ -5,13 +5,12 @@ import DialogContent from "@material-ui/core/DialogContent"; import DialogContentText from "@material-ui/core/DialogContentText"; import DialogTitle from "@material-ui/core/DialogTitle"; import { makeStyles } from "@material-ui/core/styles"; -import React from "react"; -import { FormattedMessage } from "react-intl"; - import ConfirmButton, { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; import { buttonMessages } from "@saleor/intl"; +import React from "react"; +import { FormattedMessage } from "react-intl"; const useStyles = makeStyles( theme => ({ @@ -34,9 +33,7 @@ export interface ProductVariantDeleteDialogProps { onConfirm?(); } -const ProductVariantDeleteDialog: React.FC< - ProductVariantDeleteDialogProps -> = props => { +const ProductVariantDeleteDialog: React.FC = props => { const { confirmButtonState, name, open, onConfirm, onClose } = props; const classes = useStyles(props); diff --git a/src/products/components/ProductVariantImageSelectDialog/ProductVariantImageSelectDialog.tsx b/src/products/components/ProductVariantImageSelectDialog/ProductVariantImageSelectDialog.tsx index ba861a096..97606ee2b 100644 --- a/src/products/components/ProductVariantImageSelectDialog/ProductVariantImageSelectDialog.tsx +++ b/src/products/components/ProductVariantImageSelectDialog/ProductVariantImageSelectDialog.tsx @@ -4,13 +4,12 @@ import DialogActions from "@material-ui/core/DialogActions"; import DialogContent from "@material-ui/core/DialogContent"; import DialogTitle from "@material-ui/core/DialogTitle"; import { makeStyles } from "@material-ui/core/styles"; +import { ProductImageFragment } from "@saleor/fragments/types/ProductImageFragment"; +import { buttonMessages } from "@saleor/intl"; import classNames from "classnames"; import React from "react"; import { FormattedMessage } from "react-intl"; -import { buttonMessages } from "@saleor/intl"; -import { ProductImage } from "../../types/ProductImage"; - const useStyles = makeStyles( theme => ({ image: { @@ -49,16 +48,14 @@ const useStyles = makeStyles( ); interface ProductVariantImageSelectDialogProps { - images?: ProductImage[]; + images?: ProductImageFragment[]; selectedImages?: string[]; open: boolean; onClose(); onImageSelect(id: string); } -const ProductVariantImageSelectDialog: React.FC< - ProductVariantImageSelectDialogProps -> = props => { +const ProductVariantImageSelectDialog: React.FC = props => { const { images, open, selectedImages, onClose, onImageSelect } = props; const classes = useStyles(props); diff --git a/src/products/components/ProductVariantImages/ProductVariantImages.tsx b/src/products/components/ProductVariantImages/ProductVariantImages.tsx index 18d8f48b5..2ac624c68 100644 --- a/src/products/components/ProductVariantImages/ProductVariantImages.tsx +++ b/src/products/components/ProductVariantImages/ProductVariantImages.tsx @@ -3,12 +3,11 @@ import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; import { makeStyles } from "@material-ui/core/styles"; import Typography from "@material-ui/core/Typography"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import CardTitle from "@saleor/components/CardTitle"; import Skeleton from "@saleor/components/Skeleton"; -import { ProductImage } from "../../types/ProductImage"; +import { ProductImageFragment } from "@saleor/fragments/types/ProductImageFragment"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; const useStyles = makeStyles( theme => ({ @@ -43,15 +42,13 @@ const useStyles = makeStyles( ); interface ProductVariantImagesProps { - images?: ProductImage[]; + images?: ProductImageFragment[]; placeholderImage?: string; disabled: boolean; onImageAdd(); } -export const ProductVariantImages: React.FC< - ProductVariantImagesProps -> = props => { +export const ProductVariantImages: React.FC = props => { const { disabled, images, onImageAdd } = props; const classes = useStyles(props); diff --git a/src/products/components/ProductVariantNavigation/ProductVariantNavigation.tsx b/src/products/components/ProductVariantNavigation/ProductVariantNavigation.tsx index 79a1ac224..89f0e7d55 100644 --- a/src/products/components/ProductVariantNavigation/ProductVariantNavigation.tsx +++ b/src/products/components/ProductVariantNavigation/ProductVariantNavigation.tsx @@ -4,14 +4,14 @@ import { makeStyles } from "@material-ui/core/styles"; import TableBody from "@material-ui/core/TableBody"; import TableCell from "@material-ui/core/TableCell"; import TableRow from "@material-ui/core/TableRow"; -import classNames from "classnames"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import CardTitle from "@saleor/components/CardTitle"; import ResponsiveTable from "@saleor/components/ResponsiveTable"; import Skeleton from "@saleor/components/Skeleton"; import TableCellAvatar from "@saleor/components/TableCellAvatar"; +import classNames from "classnames"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { maybe, renderCollection } from "../../../misc"; import { ProductVariantCreateData_product_variants } from "../../types/ProductVariantCreateData"; import { ProductVariantDetails_productVariant } from "../../types/ProductVariantDetails"; @@ -51,9 +51,7 @@ interface ProductVariantNavigationProps { onRowClick: (variantId: string) => void; } -const ProductVariantNavigation: React.FC< - ProductVariantNavigationProps -> = props => { +const ProductVariantNavigation: React.FC = props => { const { current, fallbackThumbnail, variants, onAdd, onRowClick } = props; const classes = useStyles(props); diff --git a/src/products/components/ProductVariantPage/ProductVariantPage.tsx b/src/products/components/ProductVariantPage/ProductVariantPage.tsx index ccd30d80e..74eb8097b 100644 --- a/src/products/components/ProductVariantPage/ProductVariantPage.tsx +++ b/src/products/components/ProductVariantPage/ProductVariantPage.tsx @@ -1,14 +1,15 @@ -import React from "react"; -import { diff } from "fast-array-diff"; - import AppHeader from "@saleor/components/AppHeader"; import CardSpacer from "@saleor/components/CardSpacer"; import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; import Container from "@saleor/components/Container"; import Form from "@saleor/components/Form"; import Grid from "@saleor/components/Grid"; +import { MetadataFormData } from "@saleor/components/Metadata"; +import Metadata from "@saleor/components/Metadata/Metadata"; import PageHeader from "@saleor/components/PageHeader"; import SaveButtonBar from "@saleor/components/SaveButtonBar"; +import { ProductVariant } from "@saleor/fragments/types/ProductVariant"; +import { WarehouseFragment } from "@saleor/fragments/types/WarehouseFragment"; import useFormset, { FormsetChange, FormsetData @@ -18,10 +19,14 @@ import { getAttributeInputFromVariant, getStockInputFromVariant } from "@saleor/products/utils/data"; -import { WarehouseFragment } from "@saleor/warehouses/types/WarehouseFragment"; +import { mapMetadataItemToInput } from "@saleor/utils/maps"; +import useMetadataChangeTrigger from "@saleor/utils/metadata/useMetadataChangeTrigger"; +import { diff } from "fast-array-diff"; +import React from "react"; + import { maybe } from "../../../misc"; -import { ProductVariant } from "../../types/ProductVariant"; import ProductShipping from "../ProductShipping/ProductShipping"; +import ProductStocks, { ProductStockInput } from "../ProductStocks"; import ProductVariantAttributes, { VariantAttributeInputData } from "../ProductVariantAttributes"; @@ -29,11 +34,10 @@ import ProductVariantImages from "../ProductVariantImages"; import ProductVariantImageSelectDialog from "../ProductVariantImageSelectDialog"; import ProductVariantNavigation from "../ProductVariantNavigation"; import ProductVariantPrice from "../ProductVariantPrice"; -import ProductStocks, { ProductStockInput } from "../ProductStocks"; -export interface ProductVariantPageFormData { +export interface ProductVariantPageFormData extends MetadataFormData { costPrice: string; - priceOverride: string; + price: string; sku: string; trackInventory: boolean; weight: string; @@ -100,6 +104,12 @@ const ProductVariantPage: React.FC = ({ const [isModalOpened, setModalStatus] = React.useState(false); const toggleModal = () => setModalStatus(!isModalOpened); + const { + isMetadataModified, + isPrivateMetadataModified, + makeChangeHandler: makeMetadataChangeHandler + } = useMetadataChangeTrigger(); + const variantImages = maybe(() => variant.images.map(image => image.id), []); const productImages = maybe(() => variant.product.images.sort((prev, next) => @@ -114,7 +124,9 @@ const ProductVariantPage: React.FC = ({ const initialForm: ProductVariantPageFormData = { costPrice: maybe(() => variant.costPrice.amount.toString(), ""), - priceOverride: maybe(() => variant.priceOverride.amount.toString(), ""), + metadata: variant?.metadata?.map(mapMetadataItemToInput), + price: maybe(() => variant.price.amount.toString(), ""), + privateMetadata: variant?.privateMetadata?.map(mapMetadataItemToInput), sku: maybe(() => variant.sku, ""), trackInventory: variant?.trackInventory, weight: variant?.weight?.value.toString() || "" @@ -124,6 +136,10 @@ const ProductVariantPage: React.FC = ({ const dataStocks = stocks.map(stock => stock.id); const variantStocks = variant.stocks.map(stock => stock.warehouse.id); const stockDiff = diff(variantStocks, dataStocks); + const metadata = isMetadataModified ? data.metadata : undefined; + const privateMetadata = isPrivateMetadataModified + ? data.privateMetadata + : undefined; onSubmit({ ...data, @@ -131,6 +147,8 @@ const ProductVariantPage: React.FC = ({ stockDiff.added.some(addedStock => addedStock === stock.id) ), attributes, + metadata, + privateMetadata, removeStocks: stockDiff.removed, updateStocks: stocks.filter( stock => !stockDiff.added.some(addedStock => addedStock === stock.id) @@ -152,6 +170,8 @@ const ProductVariantPage: React.FC = ({ triggerChange(); }; + const changeMetadata = makeMetadataChangeHandler(change); + return ( <> @@ -187,10 +207,10 @@ const ProductVariantPage: React.FC = ({ = ({ removeStock(id); }} /> + +
({ @@ -22,7 +21,7 @@ const useStyles = makeStyles( interface ProductVariantPriceProps { currencySymbol?: string; - priceOverride?: string; + price?: string; costPrice?: string; errors: ProductErrorFragment[]; loading?: boolean; @@ -30,19 +29,12 @@ interface ProductVariantPriceProps { } const ProductVariantPrice: React.FC = props => { - const { - currencySymbol, - costPrice, - errors, - priceOverride, - loading, - onChange - } = props; + const { currencySymbol, costPrice, errors, price, loading, onChange } = props; const classes = useStyles(props); const intl = useIntl(); - const formErrors = getFormErrors(["price_override", "cost_price"], errors); + const formErrors = getFormErrors(["price", "cost_price"], errors); return ( @@ -56,20 +48,12 @@ const ProductVariantPrice: React.FC = props => {
= props => { error={!!formErrors.cost_price} name="costPrice" label={intl.formatMessage({ - defaultMessage: "Cost price override" + defaultMessage: "Cost price" })} hint={ getProductErrorMessage(formErrors.cost_price, intl) || diff --git a/src/products/components/ProductVariants/ProductVariants.tsx b/src/products/components/ProductVariants/ProductVariants.tsx index 869a5facd..86ee81aa4 100644 --- a/src/products/components/ProductVariants/ProductVariants.tsx +++ b/src/products/components/ProductVariants/ProductVariants.tsx @@ -7,24 +7,24 @@ import TableBody from "@material-ui/core/TableBody"; import TableCell from "@material-ui/core/TableCell"; import TableRow from "@material-ui/core/TableRow"; import Typography from "@material-ui/core/Typography"; -import React from "react"; -import { FormattedMessage, useIntl, IntlShape } from "react-intl"; - import CardTitle from "@saleor/components/CardTitle"; import Checkbox from "@saleor/components/Checkbox"; +import LinkChoice from "@saleor/components/LinkChoice"; import Money from "@saleor/components/Money"; import ResponsiveTable from "@saleor/components/ResponsiveTable"; +import { SingleAutocompleteChoiceType } from "@saleor/components/SingleAutocompleteSelectField"; import Skeleton from "@saleor/components/Skeleton"; import TableHead from "@saleor/components/TableHead"; -import { SingleAutocompleteChoiceType } from "@saleor/components/SingleAutocompleteSelectField"; -import LinkChoice from "@saleor/components/LinkChoice"; +import { ProductVariant_costPrice } from "@saleor/fragments/types/ProductVariant"; +import React from "react"; +import { FormattedMessage, IntlShape, useIntl } from "react-intl"; + import { maybe, renderCollection } from "../../../misc"; import { ListActions } from "../../../types"; import { ProductDetails_product_variants, ProductDetails_product_variants_stocks_warehouse } from "../../types/ProductDetails"; -import { ProductVariant_costPrice } from "../../types/ProductVariant"; function getWarehouseChoices( variants: ProductDetails_product_variants[], @@ -211,7 +211,7 @@ export const ProductVariants: React.FC = props => { onClick={onVariantAdd} variant="text" color="primary" - data-tc="button-add-variant" + data-test="button-add-variant" > = props => { onClick={onVariantsAdd} variant="text" color="primary" - data-tc="button-add-variants" + data-test="button-add-variants" > = props => { onChange={() => toggle(variant.id)} /> - + {variant ? variant.name || variant.sku : } - + {variant ? variant.sku : } - + {variant ? ( - variant.priceOverride ? ( - + variant.price ? ( + ) : fallbackPrice ? ( ) : ( @@ -341,7 +341,7 @@ export const ProductVariants: React.FC = props => { {numAvailable === null ? ( diff --git a/src/products/containers/ProductImagesReorder.tsx b/src/products/containers/ProductImagesReorder.tsx index 8c56ae1d2..8fcbfd93a 100644 --- a/src/products/containers/ProductImagesReorder.tsx +++ b/src/products/containers/ProductImagesReorder.tsx @@ -1,7 +1,7 @@ import React from "react"; import { TypedMutationInnerProps } from "../../mutations"; -import { TypedProductImagesReorder } from "../mutations"; +import { useProductImagesReorder } from "../mutations"; import { ProductImageReorder, ProductImageReorderVariables @@ -19,12 +19,17 @@ interface ProductImagesReorderProviderProps }>; } -const ProductImagesReorderProvider: React.FC< - ProductImagesReorderProviderProps -> = ({ children, productId, productImages, ...mutationProps }) => ( - - {(mutate, mutationResult) => - children(opts => { +const ProductImagesReorderProvider: React.FC = ({ + children, + productId, + productImages, + ...mutationProps +}) => { + const [mutate, mutationResult] = useProductImagesReorder(mutationProps); + + return ( + <> + {children(opts => { const productImagesMap = productImages.reduce((prev, curr) => { prev[curr.id] = curr; return prev; @@ -49,9 +54,9 @@ const ProductImagesReorderProvider: React.FC< ...opts, optimisticResponse }); - }, mutationResult) - } - -); + }, mutationResult)} + + ); +}; export default ProductImagesReorderProvider; diff --git a/src/products/containers/ProductUpdateOperations.tsx b/src/products/containers/ProductUpdateOperations.tsx deleted file mode 100644 index a2e79a952..000000000 --- a/src/products/containers/ProductUpdateOperations.tsx +++ /dev/null @@ -1,153 +0,0 @@ -import React from "react"; - -import { getMutationProviderData, maybe } from "../../misc"; -import { PartialMutationProviderOutput } from "../../types"; -import { - TypedProductDeleteMutation, - TypedProductImageCreateMutation, - TypedProductImageDeleteMutation, - TypedProductUpdateMutation, - TypedProductVariantBulkDeleteMutation, - TypedSimpleProductUpdateMutation -} from "../mutations"; -import { ProductDelete, ProductDeleteVariables } from "../types/ProductDelete"; -import { ProductDetails_product } from "../types/ProductDetails"; -import { - ProductImageCreate, - ProductImageCreateVariables -} from "../types/ProductImageCreate"; -import { - ProductImageDelete, - ProductImageDeleteVariables -} from "../types/ProductImageDelete"; -import { - ProductImageReorder, - ProductImageReorderVariables -} from "../types/ProductImageReorder"; -import { ProductUpdate, ProductUpdateVariables } from "../types/ProductUpdate"; -import { - ProductVariantBulkDelete, - ProductVariantBulkDeleteVariables -} from "../types/ProductVariantBulkDelete"; -import { - SimpleProductUpdate, - SimpleProductUpdateVariables -} from "../types/SimpleProductUpdate"; -import ProductImagesReorderProvider from "./ProductImagesReorder"; - -interface ProductUpdateOperationsProps { - product: ProductDetails_product; - children: (props: { - bulkProductVariantDelete: PartialMutationProviderOutput< - ProductVariantBulkDelete, - ProductVariantBulkDeleteVariables - >; - createProductImage: PartialMutationProviderOutput< - ProductImageCreate, - ProductImageCreateVariables - >; - deleteProduct: PartialMutationProviderOutput< - ProductDelete, - ProductDeleteVariables - >; - deleteProductImage: PartialMutationProviderOutput< - ProductImageDelete, - ProductImageDeleteVariables - >; - reorderProductImages: PartialMutationProviderOutput< - ProductImageReorder, - ProductImageReorderVariables - >; - updateProduct: PartialMutationProviderOutput< - ProductUpdate, - ProductUpdateVariables - >; - updateSimpleProduct: PartialMutationProviderOutput< - SimpleProductUpdate, - SimpleProductUpdateVariables - >; - }) => React.ReactNode; - onBulkProductVariantDelete?: (data: ProductVariantBulkDelete) => void; - onDelete?: (data: ProductDelete) => void; - onImageCreate?: (data: ProductImageCreate) => void; - onImageDelete?: (data: ProductImageDelete) => void; - onImageReorder?: (data: ProductImageReorder) => void; - onUpdate?: (data: ProductUpdate) => void; -} - -const ProductUpdateOperations: React.FC = ({ - product, - children, - onBulkProductVariantDelete, - onDelete, - onImageDelete, - onImageCreate, - onImageReorder, - onUpdate -}) => { - const productId = product ? product.id : ""; - return ( - - {(...updateProduct) => ( - product.images, [])} - onCompleted={onImageReorder} - > - {(...reorderProductImages) => ( - - {(...createProductImage) => ( - - {(...deleteProduct) => ( - - {(...deleteProductImage) => ( - - {(...updateSimpleProduct) => ( - - {(...bulkProductVariantDelete) => - children({ - bulkProductVariantDelete: getMutationProviderData( - ...bulkProductVariantDelete - ), - createProductImage: getMutationProviderData( - ...createProductImage - ), - deleteProduct: getMutationProviderData( - ...deleteProduct - ), - deleteProductImage: getMutationProviderData( - ...deleteProductImage - ), - reorderProductImages: getMutationProviderData( - ...reorderProductImages - ), - updateProduct: getMutationProviderData( - ...updateProduct - ), - updateSimpleProduct: getMutationProviderData( - ...updateSimpleProduct - ) - }) - } - - )} - - )} - - )} - - )} - - )} - - )} - - ); -}; -export default ProductUpdateOperations; diff --git a/src/products/containers/ProductVariantOperations.tsx b/src/products/containers/ProductVariantOperations.tsx deleted file mode 100644 index fdb9a4a8b..000000000 --- a/src/products/containers/ProductVariantOperations.tsx +++ /dev/null @@ -1,77 +0,0 @@ -import React from "react"; - -import { getMutationProviderData } from "../../misc"; -import { PartialMutationProviderOutput } from "../../types"; -import { - TypedVariantDeleteMutation, - TypedVariantImageAssignMutation, - TypedVariantImageUnassignMutation, - TypedVariantUpdateMutation -} from "../mutations"; -import { VariantDelete, VariantDeleteVariables } from "../types/VariantDelete"; -import { - VariantImageAssign, - VariantImageAssignVariables -} from "../types/VariantImageAssign"; -import { - VariantImageUnassign, - VariantImageUnassignVariables -} from "../types/VariantImageUnassign"; -import { VariantUpdate, VariantUpdateVariables } from "../types/VariantUpdate"; - -interface VariantDeleteOperationsProps { - children: (props: { - deleteVariant: PartialMutationProviderOutput< - VariantDelete, - VariantDeleteVariables - >; - updateVariant: PartialMutationProviderOutput< - VariantUpdate, - VariantUpdateVariables - >; - assignImage: PartialMutationProviderOutput< - VariantImageAssign, - VariantImageAssignVariables - >; - unassignImage: PartialMutationProviderOutput< - VariantImageUnassign, - VariantImageUnassignVariables - >; - }) => React.ReactNode; - onDelete?: (data: VariantDelete) => void; - onImageAssign?: (data: VariantImageAssign) => void; - onImageUnassign?: (data: VariantImageUnassign) => void; - onUpdate?: (data: VariantUpdate) => void; -} - -const VariantUpdateOperations: React.FC = ({ - children, - onDelete, - onUpdate, - onImageAssign, - onImageUnassign -}) => ( - - {(...assignImage) => ( - - {(...unassignImage) => ( - - {(...updateVariant) => ( - - {(...deleteVariant) => - children({ - assignImage: getMutationProviderData(...assignImage), - deleteVariant: getMutationProviderData(...deleteVariant), - unassignImage: getMutationProviderData(...unassignImage), - updateVariant: getMutationProviderData(...updateVariant) - }) - } - - )} - - )} - - )} - -); -export default VariantUpdateOperations; diff --git a/src/products/fixtures.ts b/src/products/fixtures.ts index f3511910a..5432485a6 100644 --- a/src/products/fixtures.ts +++ b/src/products/fixtures.ts @@ -1,9 +1,13 @@ -import { AttributeInputTypeEnum } from "@saleor/types/globalTypes"; +import { ProductVariant } from "@saleor/fragments/types/ProductVariant"; +import { + AttributeInputTypeEnum, + WeightUnitsEnum +} from "@saleor/types/globalTypes"; import { warehouseList } from "@saleor/warehouses/fixtures"; + import { content } from "../storybook/stories/components/RichTextEditor"; import { ProductDetails_product } from "./types/ProductDetails"; import { ProductList_products_edges_node } from "./types/ProductList"; -import { ProductVariant } from "./types/ProductVariant"; import { ProductVariantCreateData_product } from "./types/ProductVariantCreateData"; export const product: ( @@ -91,13 +95,18 @@ export const product: ( ] } ], + availableForPurchase: null, basePrice: { __typename: "Money" as "Money", amount: 339.39, currency: "NZD", localized: "339.39 NZD" }, - category: { __typename: "Category", id: "Q2F0ZWdvcnk6MQ==", name: "Apparel" }, + category: { + __typename: "Category", + id: "Q2F0ZWdvcnk6MQ==", + name: "Apparel" + }, chargeTaxes: true, collections: [ { @@ -146,13 +155,21 @@ export const product: ( } ], isAvailable: false, + isAvailableForPurchase: false, isFeatured: false, isPublished: true, margin: { __typename: "Margin", start: 2, stop: 7 }, + metadata: [ + { + __typename: "MetadataItem", + key: "integration.id", + value: "100023123" + } + ], name: "Ergonomic Plastic Bacon", pricing: { __typename: "ProductPricingInfo", - priceRange: { + priceRangeUndiscounted: { __typename: "TaxedMoneyRange", start: { __typename: "TaxedMoney", @@ -182,6 +199,7 @@ export const product: ( } } }, + privateMetadata: [], productType: { __typename: "ProductType", hasVariants: true, @@ -255,7 +273,7 @@ export const product: ( ], margin: 2, name: "Cordoba Oro", - priceOverride: { + price: { __typename: "Money", amount: 678.78, currency: "USD" @@ -280,7 +298,7 @@ export const product: ( trackInventory: true, weight: { __typename: "Weight", - unit: "kg", + unit: WeightUnitsEnum.KG, value: 3 } }, @@ -301,7 +319,7 @@ export const product: ( ], margin: 7, name: "silver", - priceOverride: null, + price: null, sku: "69055-15190", stocks: [ { @@ -315,14 +333,15 @@ export const product: ( trackInventory: false, weight: { __typename: "Weight", - unit: "kg", + unit: WeightUnitsEnum.KG, value: 4 } } ], + visibleInListings: true, weight: { __typename: "Weight", - unit: "kg", + unit: WeightUnitsEnum.KG, value: 5 } }); @@ -332,17 +351,35 @@ export const products = ( { __typename: "Product", attributes: [], - basePrice: { - __typename: "Money", - amount: 15, - currency: "USD" - }, id: "UHJvZHVjdDo2MQ==", isAvailable: true, isPublished: true, name: "Nebula Night Sky Paint", + pricing: { + __typename: "ProductPricingInfo", + priceRangeUndiscounted: { + __typename: "TaxedMoneyRange", + start: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 3, + currency: "USD" + } + }, + stop: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 8, + currency: "USD" + } + } + } + }, productType: { __typename: "ProductType", + hasVariants: true, id: "UHJvZHVjdFR5cGU6Nw==", name: "Paint" }, @@ -354,17 +391,35 @@ export const products = ( { __typename: "Product", attributes: [], - basePrice: { - __typename: "Money", - amount: 15, - currency: "USD" - }, id: "UHJvZHVjdDo2NA==", isAvailable: true, isPublished: false, name: "Light Speed Yellow Paint", + pricing: { + __typename: "ProductPricingInfo", + priceRangeUndiscounted: { + __typename: "TaxedMoneyRange", + start: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 3, + currency: "USD" + } + }, + stop: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 8, + currency: "USD" + } + } + } + }, productType: { __typename: "ProductType", + hasVariants: true, id: "UHJvZHVjdFR5cGU6Nw==", name: "Paint" }, @@ -376,17 +431,36 @@ export const products = ( { __typename: "Product", attributes: [], - basePrice: { - __typename: "Money", - amount: 15, - currency: "USD" - }, id: "UHJvZHVjdDo2NQ==", isAvailable: true, isPublished: false, name: "Hyperspace Turquoise Paint", + + pricing: { + __typename: "ProductPricingInfo", + priceRangeUndiscounted: { + __typename: "TaxedMoneyRange", + start: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 3, + currency: "USD" + } + }, + stop: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 8, + currency: "USD" + } + } + } + }, productType: { __typename: "ProductType", + hasVariants: true, id: "UHJvZHVjdFR5cGU6Nw==", name: "Paint" }, @@ -413,17 +487,36 @@ export const products = ( ] } ], - basePrice: { - __typename: "Money", - amount: 3, - currency: "USD" - }, id: "UHJvZHVjdDo3NQ==", isAvailable: true, isPublished: true, name: "Pineapple Juice", + + pricing: { + __typename: "ProductPricingInfo", + priceRangeUndiscounted: { + __typename: "TaxedMoneyRange", + start: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 3, + currency: "USD" + } + }, + stop: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 8, + currency: "USD" + } + } + } + }, productType: { __typename: "ProductType", + hasVariants: true, id: "UHJvZHVjdFR5cGU6OQ==", name: "Juice" }, @@ -450,17 +543,36 @@ export const products = ( ] } ], - basePrice: { - __typename: "Money", - amount: 3, - currency: "USD" - }, id: "UHJvZHVjdDo3Ng==", isAvailable: true, isPublished: true, name: "Coconut Juice", + + pricing: { + __typename: "ProductPricingInfo", + priceRangeUndiscounted: { + __typename: "TaxedMoneyRange", + start: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 3, + currency: "USD" + } + }, + stop: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 8, + currency: "USD" + } + } + } + }, productType: { __typename: "ProductType", + hasVariants: true, id: "UHJvZHVjdFR5cGU6OQ==", name: "Juice" }, @@ -487,17 +599,36 @@ export const products = ( ] } ], - basePrice: { - __typename: "Money", - amount: 3, - currency: "USD" - }, id: "UHJvZHVjdDo3Mg==", isAvailable: true, isPublished: true, name: "Apple Juice", + + pricing: { + __typename: "ProductPricingInfo", + priceRangeUndiscounted: { + __typename: "TaxedMoneyRange", + start: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 3, + currency: "USD" + } + }, + stop: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 8, + currency: "USD" + } + } + } + }, productType: { __typename: "ProductType", + hasVariants: true, id: "UHJvZHVjdFR5cGU6OQ==", name: "Juice" }, @@ -524,17 +655,36 @@ export const products = ( ] } ], - basePrice: { - __typename: "Money", - amount: 3, - currency: "USD" - }, id: "UHJvZHVjdDo3MQ==", isAvailable: true, isPublished: true, name: "Orange Juice", + + pricing: { + __typename: "ProductPricingInfo", + priceRangeUndiscounted: { + __typename: "TaxedMoneyRange", + start: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 3, + currency: "USD" + } + }, + stop: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 8, + currency: "USD" + } + } + } + }, productType: { __typename: "ProductType", + hasVariants: true, id: "UHJvZHVjdFR5cGU6OQ==", name: "Juice" }, @@ -561,17 +711,36 @@ export const products = ( ] } ], - basePrice: { - __typename: "Money", - amount: 3, - currency: "USD" - }, id: "UHJvZHVjdDo3NA==", isAvailable: true, isPublished: true, name: "Banana Juice", + + pricing: { + __typename: "ProductPricingInfo", + priceRangeUndiscounted: { + __typename: "TaxedMoneyRange", + start: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 3, + currency: "USD" + } + }, + stop: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 8, + currency: "USD" + } + } + } + }, productType: { __typename: "ProductType", + hasVariants: true, id: "UHJvZHVjdFR5cGU6OQ==", name: "Juice" }, @@ -598,17 +767,36 @@ export const products = ( ] } ], - basePrice: { - __typename: "Money", - amount: 3, - currency: "USD" - }, id: "UHJvZHVjdDo3OQ==", isAvailable: true, isPublished: false, name: "Bean Juice", + + pricing: { + __typename: "ProductPricingInfo", + priceRangeUndiscounted: { + __typename: "TaxedMoneyRange", + start: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 3, + currency: "USD" + } + }, + stop: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 8, + currency: "USD" + } + } + } + }, productType: { __typename: "ProductType", + hasVariants: true, id: "UHJvZHVjdFR5cGU6OQ==", name: "Juice" }, @@ -635,17 +823,36 @@ export const products = ( ] } ], - basePrice: { - __typename: "Money", - amount: 3, - currency: "USD" - }, id: "UHJvZHVjdDo3Mw==", isAvailable: true, isPublished: true, name: "Carrot Juice", + + pricing: { + __typename: "ProductPricingInfo", + priceRangeUndiscounted: { + __typename: "TaxedMoneyRange", + start: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 3, + currency: "USD" + } + }, + stop: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 8, + currency: "USD" + } + } + } + }, productType: { __typename: "ProductType", + hasVariants: true, id: "UHJvZHVjdFR5cGU6OQ==", name: "Juice" }, @@ -672,17 +879,36 @@ export const products = ( ] } ], - basePrice: { - __typename: "Money", - amount: 3, - currency: "USD" - }, id: "UHJvZHVjdDo3OA==", isAvailable: true, isPublished: true, name: "Green Juice", + + pricing: { + __typename: "ProductPricingInfo", + priceRangeUndiscounted: { + __typename: "TaxedMoneyRange", + start: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 3, + currency: "USD" + } + }, + stop: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 8, + currency: "USD" + } + } + } + }, productType: { __typename: "ProductType", + hasVariants: true, id: "UHJvZHVjdFR5cGU6OQ==", name: "Juice" }, @@ -709,17 +935,36 @@ export const products = ( ] } ], - basePrice: { - __typename: "Money", - amount: 30, - currency: "USD" - }, id: "UHJvZHVjdDo4OQ==", isAvailable: true, isPublished: true, name: "Code Division T-shirt", + + pricing: { + __typename: "ProductPricingInfo", + priceRangeUndiscounted: { + __typename: "TaxedMoneyRange", + start: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 3, + currency: "USD" + } + }, + stop: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 8, + currency: "USD" + } + } + } + }, productType: { __typename: "ProductType", + hasVariants: true, id: "UHJvZHVjdFR5cGU6MTQ=", name: "Top (clothing)" }, @@ -746,17 +991,36 @@ export const products = ( ] } ], - basePrice: { - __typename: "Money", - amount: 30, - currency: "USD" - }, id: "UHJvZHVjdDoxMDc=", isAvailable: true, isPublished: true, name: "Polo Shirt", + + pricing: { + __typename: "ProductPricingInfo", + priceRangeUndiscounted: { + __typename: "TaxedMoneyRange", + start: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 3, + currency: "USD" + } + }, + stop: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 8, + currency: "USD" + } + } + } + }, productType: { __typename: "ProductType", + hasVariants: true, id: "UHJvZHVjdFR5cGU6MTQ=", name: "Top (clothing)" }, @@ -783,17 +1047,36 @@ export const products = ( ] } ], - basePrice: { - __typename: "Money", - amount: 30, - currency: "USD" - }, id: "UHJvZHVjdDoxMDg=", isAvailable: true, isPublished: true, name: "Polo Shirt", + + pricing: { + __typename: "ProductPricingInfo", + priceRangeUndiscounted: { + __typename: "TaxedMoneyRange", + start: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 3, + currency: "USD" + } + }, + stop: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 8, + currency: "USD" + } + } + } + }, productType: { __typename: "ProductType", + hasVariants: true, id: "UHJvZHVjdFR5cGU6MTQ=", name: "Top (clothing)" }, @@ -820,17 +1103,36 @@ export const products = ( ] } ], - basePrice: { - __typename: "Money", - amount: 30, - currency: "USD" - }, id: "UHJvZHVjdDoxMDk=", isAvailable: true, isPublished: true, name: "Polo Shirt", + + pricing: { + __typename: "ProductPricingInfo", + priceRangeUndiscounted: { + __typename: "TaxedMoneyRange", + start: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 3, + currency: "USD" + } + }, + stop: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 8, + currency: "USD" + } + } + } + }, productType: { __typename: "ProductType", + hasVariants: true, id: "UHJvZHVjdFR5cGU6MTQ=", name: "Top (clothing)" }, @@ -857,17 +1159,36 @@ export const products = ( ] } ], - basePrice: { - __typename: "Money", - amount: 30, - currency: "USD" - }, id: "UHJvZHVjdDoxMTA=", isAvailable: true, isPublished: true, name: "Polo Shirt", + + pricing: { + __typename: "ProductPricingInfo", + priceRangeUndiscounted: { + __typename: "TaxedMoneyRange", + start: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 3, + currency: "USD" + } + }, + stop: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 8, + currency: "USD" + } + } + } + }, productType: { __typename: "ProductType", + hasVariants: true, id: "UHJvZHVjdFR5cGU6MTQ=", name: "Top (clothing)" }, @@ -894,17 +1215,36 @@ export const products = ( ] } ], - basePrice: { - __typename: "Money", - amount: 30, - currency: "USD" - }, id: "UHJvZHVjdDoxMTU=", isAvailable: true, isPublished: false, name: "Black Hoodie", + + pricing: { + __typename: "ProductPricingInfo", + priceRangeUndiscounted: { + __typename: "TaxedMoneyRange", + start: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 3, + currency: "USD" + } + }, + stop: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 8, + currency: "USD" + } + } + } + }, productType: { __typename: "ProductType", + hasVariants: true, id: "UHJvZHVjdFR5cGU6MTQ=", name: "Top (clothing)" }, @@ -931,17 +1271,36 @@ export const products = ( ] } ], - basePrice: { - __typename: "Money", - amount: 30, - currency: "USD" - }, id: "UHJvZHVjdDoxMTY=", isAvailable: true, isPublished: true, name: "Blue Hoodie", + + pricing: { + __typename: "ProductPricingInfo", + priceRangeUndiscounted: { + __typename: "TaxedMoneyRange", + start: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 3, + currency: "USD" + } + }, + stop: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 8, + currency: "USD" + } + } + } + }, productType: { __typename: "ProductType", + hasVariants: true, id: "UHJvZHVjdFR5cGU6MTQ=", name: "Top (clothing)" }, @@ -968,17 +1327,36 @@ export const products = ( ] } ], - basePrice: { - __typename: "Money", - amount: 30, - currency: "USD" - }, id: "UHJvZHVjdDoxMTc=", isAvailable: true, isPublished: true, name: "Mustard Hoodie", + + pricing: { + __typename: "ProductPricingInfo", + priceRangeUndiscounted: { + __typename: "TaxedMoneyRange", + start: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 3, + currency: "USD" + } + }, + stop: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 8, + currency: "USD" + } + } + } + }, productType: { __typename: "ProductType", + hasVariants: true, id: "UHJvZHVjdFR5cGU6MTQ=", name: "Top (clothing)" }, @@ -1005,17 +1383,36 @@ export const products = ( ] } ], - basePrice: { - __typename: "Money", - amount: 20, - currency: "USD" - }, id: "UHJvZHVjdDo4NQ==", isAvailable: true, isPublished: false, name: "Colored Parrot Cushion", + + pricing: { + __typename: "ProductPricingInfo", + priceRangeUndiscounted: { + __typename: "TaxedMoneyRange", + start: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 3, + currency: "USD" + } + }, + stop: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 8, + currency: "USD" + } + } + } + }, productType: { __typename: "ProductType", + hasVariants: true, id: "UHJvZHVjdFR5cGU6MTI=", name: "Cushion" }, @@ -1134,12 +1531,20 @@ export const variant = (placeholderImage: string): ProductVariant => ({ url: placeholderImage } ], + metadata: [ + { + __typename: "MetadataItem", + key: "integration.id", + value: "100023123" + } + ], name: "Extended Hard", - priceOverride: { + price: { __typename: "Money", amount: 100, currency: "USD" }, + privateMetadata: [], product: { __typename: "Product" as "Product", id: "prod1", @@ -1293,7 +1698,7 @@ export const variant = (placeholderImage: string): ProductVariant => ({ trackInventory: true, weight: { __typename: "Weight", - unit: "kg", + unit: WeightUnitsEnum.KG, value: 6 } }); diff --git a/src/products/index.tsx b/src/products/index.tsx index b80a26e0c..46b4df70d 100644 --- a/src/products/index.tsx +++ b/src/products/index.tsx @@ -1,11 +1,11 @@ +import { sectionNames } from "@saleor/intl"; +import { asSortParams } from "@saleor/utils/sort"; +import { getArrayQueryParam } from "@saleor/utils/urls"; import { parse as parseQs } from "qs"; import React from "react"; import { useIntl } from "react-intl"; import { Route, RouteComponentProps, Switch } from "react-router-dom"; -import { sectionNames } from "@saleor/intl"; -import { asSortParams } from "@saleor/utils/sort"; -import { getArrayQueryParam } from "@saleor/utils/urls"; import { WindowTitle } from "../components/WindowTitle"; import { productAddPath, @@ -17,9 +17,9 @@ import { productPath, ProductUrlQueryParams, productVariantAddPath, + productVariantCreatorPath, productVariantEditPath, - ProductVariantEditUrlQueryParams, - productVariantCreatorPath + ProductVariantEditUrlQueryParams } from "./urls"; import ProductCreate from "./views/ProductCreate"; import ProductImageComponent from "./views/ProductImage"; @@ -52,7 +52,10 @@ const ProductUpdate: React.FC> = ({ match }) => { return ( ); }; diff --git a/src/products/mutations.ts b/src/products/mutations.ts index 18bcec297..12d6d4de3 100644 --- a/src/products/mutations.ts +++ b/src/products/mutations.ts @@ -1,10 +1,29 @@ +import { + bulkProductErrorFragment, + bulkStockErrorFragment, + exportErrorFragment, + productErrorFragment, + stockErrorFragment +} from "@saleor/fragments/errors"; +import { + exportFileFragment, + fragmentVariant, + productFragmentDetails +} from "@saleor/fragments/products"; +import makeMutation from "@saleor/hooks/makeMutation"; import gql from "graphql-tag"; -import { productErrorFragment } from "@saleor/attributes/mutations"; -import makeMutation from "@saleor/hooks/makeMutation"; -import { TypedMutation } from "../mutations"; +import { + productBulkDelete, + productBulkDeleteVariables +} from "./types/productBulkDelete"; +import { + productBulkPublish, + productBulkPublishVariables +} from "./types/productBulkPublish"; import { ProductCreate, ProductCreateVariables } from "./types/ProductCreate"; import { ProductDelete, ProductDeleteVariables } from "./types/ProductDelete"; +import { ProductExport, ProductExportVariables } from "./types/ProductExport"; import { ProductImageCreate, ProductImageCreateVariables @@ -21,7 +40,19 @@ import { ProductImageUpdate, ProductImageUpdateVariables } from "./types/ProductImageUpdate"; +import { + ProductSetAvailabilityForPurchase, + ProductSetAvailabilityForPurchaseVariables +} from "./types/ProductSetAvailabilityForPurchase"; import { ProductUpdate, ProductUpdateVariables } from "./types/ProductUpdate"; +import { + ProductVariantBulkCreate, + ProductVariantBulkCreateVariables +} from "./types/ProductVariantBulkCreate"; +import { + ProductVariantBulkDelete, + ProductVariantBulkDeleteVariables +} from "./types/ProductVariantBulkDelete"; import { SimpleProductUpdate, SimpleProductUpdateVariables @@ -38,45 +69,6 @@ import { } from "./types/VariantImageUnassign"; import { VariantUpdate, VariantUpdateVariables } from "./types/VariantUpdate"; -import { fragmentVariant, productFragmentDetails } from "./queries"; -import { - productBulkDelete, - productBulkDeleteVariables -} from "./types/productBulkDelete"; -import { - productBulkPublish, - productBulkPublishVariables -} from "./types/productBulkPublish"; -import { - ProductVariantBulkCreate, - ProductVariantBulkCreateVariables -} from "./types/ProductVariantBulkCreate"; -import { - ProductVariantBulkDelete, - ProductVariantBulkDeleteVariables -} from "./types/ProductVariantBulkDelete"; - -export const bulkProductErrorFragment = gql` - fragment BulkProductErrorFragment on BulkProductError { - field - code - index - } -`; -const bulkStockErrorFragment = gql` - fragment BulkStockErrorFragment on BulkStockError { - code - field - index - } -`; -const stockErrorFragment = gql` - fragment StockErrorFragment on StockError { - code - field - } -`; - export const productImageCreateMutation = gql` ${productErrorFragment} ${productFragmentDetails} @@ -91,7 +83,7 @@ export const productImageCreateMutation = gql` } } `; -export const TypedProductImageCreateMutation = TypedMutation< +export const useProductImageCreateMutation = makeMutation< ProductImageCreate, ProductImageCreateVariables >(productImageCreateMutation); @@ -109,7 +101,7 @@ export const productDeleteMutation = gql` } } `; -export const TypedProductDeleteMutation = TypedMutation< +export const useProductDeleteMutation = makeMutation< ProductDelete, ProductDeleteVariables >(productDeleteMutation); @@ -133,7 +125,7 @@ export const productImagesReorder = gql` } } `; -export const TypedProductImagesReorder = TypedMutation< +export const useProductImagesReorder = makeMutation< ProductImageReorder, ProductImageReorderVariables >(productImagesReorder); @@ -151,8 +143,9 @@ export const productUpdateMutation = gql` $descriptionJson: JSONString $isPublished: Boolean! $name: String - $basePrice: Decimal + $basePrice: PositiveDecimal $seo: SeoInput + $visibleInListings: Boolean ) { productUpdate( id: $id @@ -167,6 +160,7 @@ export const productUpdateMutation = gql` name: $name basePrice: $basePrice seo: $seo + visibleInListings: $visibleInListings } ) { errors: productErrors { @@ -178,7 +172,7 @@ export const productUpdateMutation = gql` } } `; -export const TypedProductUpdateMutation = TypedMutation< +export const useProductUpdateMutation = makeMutation< ProductUpdate, ProductUpdateVariables >(productUpdateMutation); @@ -199,7 +193,7 @@ export const simpleProductUpdateMutation = gql` $descriptionJson: JSONString $isPublished: Boolean! $name: String - $basePrice: Decimal + $basePrice: PositiveDecimal $productVariantId: ID! $productVariantInput: ProductVariantInput! $seo: SeoInput @@ -207,6 +201,7 @@ export const simpleProductUpdateMutation = gql` $deleteStocks: [ID!]! $updateStocks: [StockInput!]! $weight: WeightScalar + $visibleInListings: Boolean ) { productUpdate( id: $id @@ -222,6 +217,7 @@ export const simpleProductUpdateMutation = gql` basePrice: $basePrice seo: $seo weight: $weight + visibleInListings: $visibleInListings } ) { errors: productErrors { @@ -274,7 +270,7 @@ export const simpleProductUpdateMutation = gql` } } `; -export const TypedSimpleProductUpdateMutation = TypedMutation< +export const useSimpleProductUpdateMutation = makeMutation< SimpleProductUpdate, SimpleProductUpdateVariables >(simpleProductUpdateMutation); @@ -291,13 +287,14 @@ export const productCreateMutation = gql` $descriptionJson: JSONString $isPublished: Boolean! $name: String! - $basePrice: Decimal + $basePrice: PositiveDecimal $productType: ID! $sku: String $seo: SeoInput $stocks: [StockInput!]! $trackInventory: Boolean! $weight: WeightScalar + $visibleInListings: Boolean ) { productCreate( input: { @@ -316,6 +313,7 @@ export const productCreateMutation = gql` stocks: $stocks trackInventory: $trackInventory weight: $weight + visibleInListings: $visibleInListings } ) { errors: productErrors { @@ -327,7 +325,7 @@ export const productCreateMutation = gql` } } `; -export const TypedProductCreateMutation = TypedMutation< +export const useProductCreateMutation = makeMutation< ProductCreate, ProductCreateVariables >(productCreateMutation); @@ -345,7 +343,7 @@ export const variantDeleteMutation = gql` } } `; -export const TypedVariantDeleteMutation = TypedMutation< +export const useVariantDeleteMutation = makeMutation< VariantDelete, VariantDeleteVariables >(variantDeleteMutation); @@ -359,8 +357,8 @@ export const variantUpdateMutation = gql` $removeStocks: [ID!]! $id: ID! $attributes: [AttributeValueInput] - $costPrice: Decimal - $priceOverride: Decimal + $costPrice: PositiveDecimal + $price: PositiveDecimal $sku: String $trackInventory: Boolean! $stocks: [StockInput!]! @@ -371,7 +369,7 @@ export const variantUpdateMutation = gql` input: { attributes: $attributes costPrice: $costPrice - priceOverride: $priceOverride + price: $price sku: $sku trackInventory: $trackInventory weight: $weight @@ -417,7 +415,7 @@ export const variantUpdateMutation = gql` } } `; -export const TypedVariantUpdateMutation = TypedMutation< +export const useVariantUpdateMutation = makeMutation< VariantUpdate, VariantUpdateVariables >(variantUpdateMutation); @@ -436,7 +434,7 @@ export const variantCreateMutation = gql` } } `; -export const TypedVariantCreateMutation = TypedMutation< +export const useVariantCreateMutation = makeMutation< VariantCreate, VariantCreateVariables >(variantCreateMutation); @@ -457,7 +455,7 @@ export const productImageDeleteMutation = gql` } } `; -export const TypedProductImageDeleteMutation = TypedMutation< +export const useProductImageDeleteMutation = makeMutation< ProductImageDelete, ProductImageDeleteVariables >(productImageDeleteMutation); @@ -476,7 +474,7 @@ export const productImageUpdateMutation = gql` } } `; -export const TypedProductImageUpdateMutation = TypedMutation< +export const useProductImageUpdateMutation = makeMutation< ProductImageUpdate, ProductImageUpdateVariables >(productImageUpdateMutation); @@ -495,7 +493,7 @@ export const variantImageAssignMutation = gql` } } `; -export const TypedVariantImageAssignMutation = TypedMutation< +export const useVariantImageAssignMutation = makeMutation< VariantImageAssign, VariantImageAssignVariables >(variantImageAssignMutation); @@ -514,7 +512,7 @@ export const variantImageUnassignMutation = gql` } } `; -export const TypedVariantImageUnassignMutation = TypedMutation< +export const useVariantImageUnassignMutation = makeMutation< VariantImageUnassign, VariantImageUnassignVariables >(variantImageUnassignMutation); @@ -529,7 +527,7 @@ export const productBulkDeleteMutation = gql` } } `; -export const TypedProductBulkDeleteMutation = TypedMutation< +export const useProductBulkDeleteMutation = makeMutation< productBulkDelete, productBulkDeleteVariables >(productBulkDeleteMutation); @@ -544,7 +542,7 @@ export const productBulkPublishMutation = gql` } } `; -export const TypedProductBulkPublishMutation = TypedMutation< +export const useProductBulkPublishMutation = makeMutation< productBulkPublish, productBulkPublishVariables >(productBulkPublishMutation); @@ -577,7 +575,51 @@ export const ProductVariantBulkDeleteMutation = gql` } } `; -export const TypedProductVariantBulkDeleteMutation = TypedMutation< +export const useProductVariantBulkDeleteMutation = makeMutation< ProductVariantBulkDelete, ProductVariantBulkDeleteVariables >(ProductVariantBulkDeleteMutation); + +export const productExportMutation = gql` + ${exportFileFragment} + ${exportErrorFragment} + mutation ProductExport($input: ExportProductsInput!) { + exportProducts(input: $input) { + exportFile { + ...ExportFileFragment + } + errors: exportErrors { + ...ExportErrorFragment + } + } + } +`; +export const useProductExport = makeMutation< + ProductExport, + ProductExportVariables +>(productExportMutation); + +const productSetAvailabilityForPurchase = gql` + ${productErrorFragment} + mutation ProductSetAvailabilityForPurchase( + $isAvailable: Boolean! + $productId: ID! + $startDate: Date + ) { + productSetAvailabilityForPurchase( + isAvailable: $isAvailable + productId: $productId + startDate: $startDate + ) { + errors: productErrors { + ...ProductErrorFragment + message + } + } + } +`; + +export const useProductSetAvailabilityForPurchase = makeMutation< + ProductSetAvailabilityForPurchase, + ProductSetAvailabilityForPurchaseVariables +>(productSetAvailabilityForPurchase); diff --git a/src/products/queries.ts b/src/products/queries.ts index 5ae6e21d3..e94ea7379 100644 --- a/src/products/queries.ts +++ b/src/products/queries.ts @@ -1,12 +1,28 @@ +import { pageInfoFragment } from "@saleor/fragments/pageInfo"; +import { + fragmentMoney, + fragmentVariant, + productFragment, + productFragmentDetails, + productVariantAttributesFragment +} from "@saleor/fragments/products"; +import { warehouseFragment } from "@saleor/fragments/warehouses"; +import makeQuery from "@saleor/hooks/makeQuery"; import gql from "graphql-tag"; -import makeQuery from "@saleor/hooks/makeQuery"; -import { warehouseFragment } from "@saleor/warehouses/queries"; -import { pageInfoFragment, TypedQuery } from "../queries"; +import { CountAllProducts } from "./types/CountAllProducts"; import { - AvailableInGridAttributes, - AvailableInGridAttributesVariables -} from "./types/AvailableInGridAttributes"; + CreateMultipleVariantsData, + CreateMultipleVariantsDataVariables +} from "./types/CreateMultipleVariantsData"; +import { + GridAttributes, + GridAttributesVariables +} from "./types/GridAttributes"; +import { + InitialProductFilterData, + InitialProductFilterDataVariables +} from "./types/InitialProductFilterData"; import { ProductDetails, ProductDetailsVariables @@ -24,249 +40,6 @@ import { ProductVariantDetails, ProductVariantDetailsVariables } from "./types/ProductVariantDetails"; -import { - InitialProductFilterData, - InitialProductFilterDataVariables -} from "./types/InitialProductFilterData"; -import { - CreateMultipleVariantsData, - CreateMultipleVariantsDataVariables -} from "./types/CreateMultipleVariantsData"; - -export const stockFragment = gql` - fragment StockFragment on Stock { - id - quantity - quantityAllocated - warehouse { - id - name - } - } -`; - -export const fragmentMoney = gql` - fragment Money on Money { - amount - currency - } -`; - -export const fragmentProductImage = gql` - fragment ProductImageFragment on ProductImage { - id - alt - sortOrder - url - } -`; - -export const productFragment = gql` - ${fragmentMoney} - fragment ProductFragment on Product { - id - name - thumbnail { - url - } - isAvailable - isPublished - basePrice { - ...Money - } - productType { - id - name - } - } -`; - -const productVariantAttributesFragment = gql` - fragment ProductVariantAttributesFragment on Product { - id - attributes { - attribute { - id - slug - name - inputType - valueRequired - values { - id - name - slug - } - } - values { - id - name - slug - } - } - productType { - id - variantAttributes { - id - name - values { - id - name - slug - } - } - } - } -`; - -export const productFragmentDetails = gql` - ${fragmentProductImage} - ${fragmentMoney} - ${productVariantAttributesFragment} - ${stockFragment} - fragment Product on Product { - ...ProductVariantAttributesFragment - name - descriptionJson - seoTitle - seoDescription - category { - id - name - } - collections { - id - name - } - basePrice { - ...Money - } - margin { - start - stop - } - purchaseCost { - start { - ...Money - } - stop { - ...Money - } - } - isAvailable - isPublished - chargeTaxes - publicationDate - pricing { - priceRange { - start { - net { - ...Money - } - } - stop { - net { - ...Money - } - } - } - } - images { - ...ProductImageFragment - } - variants { - id - sku - name - priceOverride { - ...Money - } - margin - stocks { - ...StockFragment - } - trackInventory - weight { - unit - value - } - } - productType { - id - name - hasVariants - } - weight { - unit - value - } - } -`; - -export const fragmentVariant = gql` - ${fragmentMoney} - ${fragmentProductImage} - ${stockFragment} - fragment ProductVariant on ProductVariant { - id - attributes { - attribute { - id - name - slug - valueRequired - values { - id - name - slug - } - } - values { - id - name - slug - } - } - costPrice { - ...Money - } - images { - id - url - } - name - priceOverride { - ...Money - } - product { - id - images { - ...ProductImageFragment - } - name - thumbnail { - url - } - variants { - id - name - sku - images { - id - url - } - } - } - sku - stocks { - ...StockFragment - } - trackInventory - weight { - unit - value - } - } -`; const initialProductFilterDataQuery = gql` query InitialProductFilterData( @@ -320,6 +93,7 @@ export const useInitialProductFilterDataQuery = makeQuery< >(initialProductFilterDataQuery); const productListQuery = gql` + ${fragmentMoney} ${productFragment} query ProductList( $first: Int @@ -349,6 +123,20 @@ const productListQuery = gql` name } } + pricing { + priceRangeUndiscounted { + start { + gross { + ...Money + } + } + stop { + gross { + ...Money + } + } + } + } } } pageInfo { @@ -357,13 +145,24 @@ const productListQuery = gql` startCursor endCursor } + totalCount } } `; -export const TypedProductListQuery = TypedQuery< - ProductList, - ProductListVariables ->(productListQuery); +export const useProductListQuery = makeQuery( + productListQuery +); + +const countAllProductsQuery = gql` + query CountAllProducts { + products { + totalCount + } + } +`; +export const useCountAllProducts = makeQuery( + countAllProductsQuery +); const productDetailsQuery = gql` ${productFragmentDetails} @@ -373,7 +172,7 @@ const productDetailsQuery = gql` } } `; -export const TypedProductDetailsQuery = TypedQuery< +export const useProductDetails = makeQuery< ProductDetails, ProductDetailsVariables >(productDetailsQuery); @@ -386,7 +185,7 @@ const productVariantQuery = gql` } } `; -export const TypedProductVariantQuery = TypedQuery< +export const useProductVariantQuery = makeQuery< ProductVariantDetails, ProductVariantDetailsVariables >(productVariantQuery); @@ -430,7 +229,7 @@ const productVariantCreateQuery = gql` } } `; -export const TypedProductVariantCreateQuery = TypedQuery< +export const useProductVariantCreateQuery = makeQuery< ProductVariantCreateData, ProductVariantCreateDataVariables >(productVariantCreateQuery); @@ -452,7 +251,7 @@ const productImageQuery = gql` } } `; -export const TypedProductImageQuery = TypedQuery< +export const useProductImageQuery = makeQuery< ProductImageById, ProductImageByIdVariables >(productImageQuery); @@ -487,21 +286,17 @@ const availableInGridAttributes = gql` } } `; -export const AvailableInGridAttributesQuery = TypedQuery< - AvailableInGridAttributes, - AvailableInGridAttributesVariables +export const useAvailableInGridAttributesQuery = makeQuery< + GridAttributes, + GridAttributesVariables >(availableInGridAttributes); const createMultipleVariantsData = gql` - ${fragmentMoney} ${productVariantAttributesFragment} ${warehouseFragment} query CreateMultipleVariantsData($id: ID!) { product(id: $id) { ...ProductVariantAttributesFragment - basePrice { - ...Money - } } warehouses(first: 20) { edges { diff --git a/src/products/types/AvailableInGridAttributes.ts b/src/products/types/AvailableInGridAttributes.ts deleted file mode 100644 index e87d2abdf..000000000 --- a/src/products/types/AvailableInGridAttributes.ts +++ /dev/null @@ -1,60 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -// This file was automatically generated and should not be edited. - -// ==================================================== -// GraphQL query operation: AvailableInGridAttributes -// ==================================================== - -export interface AvailableInGridAttributes_availableInGrid_edges_node { - __typename: "Attribute"; - id: string; - name: string | null; -} - -export interface AvailableInGridAttributes_availableInGrid_edges { - __typename: "AttributeCountableEdge"; - node: AvailableInGridAttributes_availableInGrid_edges_node; -} - -export interface AvailableInGridAttributes_availableInGrid_pageInfo { - __typename: "PageInfo"; - endCursor: string | null; - hasNextPage: boolean; - hasPreviousPage: boolean; - startCursor: string | null; -} - -export interface AvailableInGridAttributes_availableInGrid { - __typename: "AttributeCountableConnection"; - edges: AvailableInGridAttributes_availableInGrid_edges[]; - pageInfo: AvailableInGridAttributes_availableInGrid_pageInfo; - totalCount: number | null; -} - -export interface AvailableInGridAttributes_grid_edges_node { - __typename: "Attribute"; - id: string; - name: string | null; -} - -export interface AvailableInGridAttributes_grid_edges { - __typename: "AttributeCountableEdge"; - node: AvailableInGridAttributes_grid_edges_node; -} - -export interface AvailableInGridAttributes_grid { - __typename: "AttributeCountableConnection"; - edges: AvailableInGridAttributes_grid_edges[]; -} - -export interface AvailableInGridAttributes { - availableInGrid: AvailableInGridAttributes_availableInGrid | null; - grid: AvailableInGridAttributes_grid | null; -} - -export interface AvailableInGridAttributesVariables { - first: number; - after?: string | null; - ids: string[]; -} diff --git a/src/products/types/CountAllProducts.ts b/src/products/types/CountAllProducts.ts new file mode 100644 index 000000000..1962d82e3 --- /dev/null +++ b/src/products/types/CountAllProducts.ts @@ -0,0 +1,16 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL query operation: CountAllProducts +// ==================================================== + +export interface CountAllProducts_products { + __typename: "ProductCountableConnection"; + totalCount: number | null; +} + +export interface CountAllProducts { + products: CountAllProducts_products | null; +} diff --git a/src/products/types/CreateMultipleVariantsData.ts b/src/products/types/CreateMultipleVariantsData.ts index 086d657b7..ea2d1909f 100644 --- a/src/products/types/CreateMultipleVariantsData.ts +++ b/src/products/types/CreateMultipleVariantsData.ts @@ -58,18 +58,45 @@ export interface CreateMultipleVariantsData_product_productType { variantAttributes: (CreateMultipleVariantsData_product_productType_variantAttributes | null)[] | null; } -export interface CreateMultipleVariantsData_product_basePrice { +export interface CreateMultipleVariantsData_product_pricing_priceRangeUndiscounted_start_gross { __typename: "Money"; amount: number; currency: string; } +export interface CreateMultipleVariantsData_product_pricing_priceRangeUndiscounted_start { + __typename: "TaxedMoney"; + gross: CreateMultipleVariantsData_product_pricing_priceRangeUndiscounted_start_gross; +} + +export interface CreateMultipleVariantsData_product_pricing_priceRangeUndiscounted_stop_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface CreateMultipleVariantsData_product_pricing_priceRangeUndiscounted_stop { + __typename: "TaxedMoney"; + gross: CreateMultipleVariantsData_product_pricing_priceRangeUndiscounted_stop_gross; +} + +export interface CreateMultipleVariantsData_product_pricing_priceRangeUndiscounted { + __typename: "TaxedMoneyRange"; + start: CreateMultipleVariantsData_product_pricing_priceRangeUndiscounted_start | null; + stop: CreateMultipleVariantsData_product_pricing_priceRangeUndiscounted_stop | null; +} + +export interface CreateMultipleVariantsData_product_pricing { + __typename: "ProductPricingInfo"; + priceRangeUndiscounted: CreateMultipleVariantsData_product_pricing_priceRangeUndiscounted | null; +} + export interface CreateMultipleVariantsData_product { __typename: "Product"; id: string; attributes: CreateMultipleVariantsData_product_attributes[]; productType: CreateMultipleVariantsData_product_productType; - basePrice: CreateMultipleVariantsData_product_basePrice | null; + pricing: CreateMultipleVariantsData_product_pricing | null; } export interface CreateMultipleVariantsData_warehouses_edges_node { diff --git a/src/products/types/ProductCreate.ts b/src/products/types/ProductCreate.ts index e1d020c3f..68c154d91 100644 --- a/src/products/types/ProductCreate.ts +++ b/src/products/types/ProductCreate.ts @@ -2,7 +2,7 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { AttributeValueInput, SeoInput, StockInput, ProductErrorCode, AttributeInputTypeEnum } from "./../../types/globalTypes"; +import { AttributeValueInput, SeoInput, StockInput, ProductErrorCode, AttributeInputTypeEnum, WeightUnitsEnum } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: ProductCreate @@ -66,6 +66,51 @@ export interface ProductCreate_productCreate_product_productType { hasVariants: boolean; } +export interface ProductCreate_productCreate_product_pricing_priceRangeUndiscounted_start_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ProductCreate_productCreate_product_pricing_priceRangeUndiscounted_start { + __typename: "TaxedMoney"; + gross: ProductCreate_productCreate_product_pricing_priceRangeUndiscounted_start_gross; +} + +export interface ProductCreate_productCreate_product_pricing_priceRangeUndiscounted_stop_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ProductCreate_productCreate_product_pricing_priceRangeUndiscounted_stop { + __typename: "TaxedMoney"; + gross: ProductCreate_productCreate_product_pricing_priceRangeUndiscounted_stop_gross; +} + +export interface ProductCreate_productCreate_product_pricing_priceRangeUndiscounted { + __typename: "TaxedMoneyRange"; + start: ProductCreate_productCreate_product_pricing_priceRangeUndiscounted_start | null; + stop: ProductCreate_productCreate_product_pricing_priceRangeUndiscounted_stop | null; +} + +export interface ProductCreate_productCreate_product_pricing { + __typename: "ProductPricingInfo"; + priceRangeUndiscounted: ProductCreate_productCreate_product_pricing_priceRangeUndiscounted | null; +} + +export interface ProductCreate_productCreate_product_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface ProductCreate_productCreate_product_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface ProductCreate_productCreate_product_category { __typename: "Category"; id: string; @@ -78,12 +123,6 @@ export interface ProductCreate_productCreate_product_collections { name: string; } -export interface ProductCreate_productCreate_product_basePrice { - __typename: "Money"; - amount: number; - currency: string; -} - export interface ProductCreate_productCreate_product_margin { __typename: "Margin"; start: number | null; @@ -108,39 +147,6 @@ export interface ProductCreate_productCreate_product_purchaseCost { stop: ProductCreate_productCreate_product_purchaseCost_stop | null; } -export interface ProductCreate_productCreate_product_pricing_priceRange_start_net { - __typename: "Money"; - amount: number; - currency: string; -} - -export interface ProductCreate_productCreate_product_pricing_priceRange_start { - __typename: "TaxedMoney"; - net: ProductCreate_productCreate_product_pricing_priceRange_start_net; -} - -export interface ProductCreate_productCreate_product_pricing_priceRange_stop_net { - __typename: "Money"; - amount: number; - currency: string; -} - -export interface ProductCreate_productCreate_product_pricing_priceRange_stop { - __typename: "TaxedMoney"; - net: ProductCreate_productCreate_product_pricing_priceRange_stop_net; -} - -export interface ProductCreate_productCreate_product_pricing_priceRange { - __typename: "TaxedMoneyRange"; - start: ProductCreate_productCreate_product_pricing_priceRange_start | null; - stop: ProductCreate_productCreate_product_pricing_priceRange_stop | null; -} - -export interface ProductCreate_productCreate_product_pricing { - __typename: "ProductPricingInfo"; - priceRange: ProductCreate_productCreate_product_pricing_priceRange | null; -} - export interface ProductCreate_productCreate_product_images { __typename: "ProductImage"; id: string; @@ -149,7 +155,7 @@ export interface ProductCreate_productCreate_product_images { url: string; } -export interface ProductCreate_productCreate_product_variants_priceOverride { +export interface ProductCreate_productCreate_product_variants_price { __typename: "Money"; amount: number; currency: string; @@ -169,27 +175,20 @@ export interface ProductCreate_productCreate_product_variants_stocks { warehouse: ProductCreate_productCreate_product_variants_stocks_warehouse; } -export interface ProductCreate_productCreate_product_variants_weight { - __typename: "Weight"; - unit: string; - value: number; -} - export interface ProductCreate_productCreate_product_variants { __typename: "ProductVariant"; id: string; sku: string; name: string; - priceOverride: ProductCreate_productCreate_product_variants_priceOverride | null; + price: ProductCreate_productCreate_product_variants_price | null; margin: number | null; stocks: (ProductCreate_productCreate_product_variants_stocks | null)[] | null; trackInventory: boolean; - weight: ProductCreate_productCreate_product_variants_weight | null; } export interface ProductCreate_productCreate_product_weight { __typename: "Weight"; - unit: string; + unit: WeightUnitsEnum; value: number; } @@ -198,23 +197,27 @@ export interface ProductCreate_productCreate_product { id: string; attributes: ProductCreate_productCreate_product_attributes[]; productType: ProductCreate_productCreate_product_productType; + pricing: ProductCreate_productCreate_product_pricing | null; + metadata: (ProductCreate_productCreate_product_metadata | null)[]; + privateMetadata: (ProductCreate_productCreate_product_privateMetadata | null)[]; name: string; descriptionJson: any; seoTitle: string | null; seoDescription: string | null; category: ProductCreate_productCreate_product_category | null; collections: (ProductCreate_productCreate_product_collections | null)[] | null; - basePrice: ProductCreate_productCreate_product_basePrice | null; margin: ProductCreate_productCreate_product_margin | null; purchaseCost: ProductCreate_productCreate_product_purchaseCost | null; + isAvailableForPurchase: boolean | null; isAvailable: boolean | null; isPublished: boolean; chargeTaxes: boolean; publicationDate: any | null; - pricing: ProductCreate_productCreate_product_pricing | null; images: (ProductCreate_productCreate_product_images | null)[] | null; variants: (ProductCreate_productCreate_product_variants | null)[] | null; weight: ProductCreate_productCreate_product_weight | null; + availableForPurchase: any | null; + visibleInListings: boolean; } export interface ProductCreate_productCreate { @@ -243,4 +246,5 @@ export interface ProductCreateVariables { stocks: StockInput[]; trackInventory: boolean; weight?: any | null; + visibleInListings?: boolean | null; } diff --git a/src/products/types/ProductDetails.ts b/src/products/types/ProductDetails.ts index 86d337d42..06e579bae 100644 --- a/src/products/types/ProductDetails.ts +++ b/src/products/types/ProductDetails.ts @@ -2,7 +2,7 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { AttributeInputTypeEnum } from "./../../types/globalTypes"; +import { AttributeInputTypeEnum, WeightUnitsEnum } from "./../../types/globalTypes"; // ==================================================== // GraphQL query operation: ProductDetails @@ -60,6 +60,51 @@ export interface ProductDetails_product_productType { hasVariants: boolean; } +export interface ProductDetails_product_pricing_priceRangeUndiscounted_start_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ProductDetails_product_pricing_priceRangeUndiscounted_start { + __typename: "TaxedMoney"; + gross: ProductDetails_product_pricing_priceRangeUndiscounted_start_gross; +} + +export interface ProductDetails_product_pricing_priceRangeUndiscounted_stop_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ProductDetails_product_pricing_priceRangeUndiscounted_stop { + __typename: "TaxedMoney"; + gross: ProductDetails_product_pricing_priceRangeUndiscounted_stop_gross; +} + +export interface ProductDetails_product_pricing_priceRangeUndiscounted { + __typename: "TaxedMoneyRange"; + start: ProductDetails_product_pricing_priceRangeUndiscounted_start | null; + stop: ProductDetails_product_pricing_priceRangeUndiscounted_stop | null; +} + +export interface ProductDetails_product_pricing { + __typename: "ProductPricingInfo"; + priceRangeUndiscounted: ProductDetails_product_pricing_priceRangeUndiscounted | null; +} + +export interface ProductDetails_product_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface ProductDetails_product_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface ProductDetails_product_category { __typename: "Category"; id: string; @@ -72,12 +117,6 @@ export interface ProductDetails_product_collections { name: string; } -export interface ProductDetails_product_basePrice { - __typename: "Money"; - amount: number; - currency: string; -} - export interface ProductDetails_product_margin { __typename: "Margin"; start: number | null; @@ -102,39 +141,6 @@ export interface ProductDetails_product_purchaseCost { stop: ProductDetails_product_purchaseCost_stop | null; } -export interface ProductDetails_product_pricing_priceRange_start_net { - __typename: "Money"; - amount: number; - currency: string; -} - -export interface ProductDetails_product_pricing_priceRange_start { - __typename: "TaxedMoney"; - net: ProductDetails_product_pricing_priceRange_start_net; -} - -export interface ProductDetails_product_pricing_priceRange_stop_net { - __typename: "Money"; - amount: number; - currency: string; -} - -export interface ProductDetails_product_pricing_priceRange_stop { - __typename: "TaxedMoney"; - net: ProductDetails_product_pricing_priceRange_stop_net; -} - -export interface ProductDetails_product_pricing_priceRange { - __typename: "TaxedMoneyRange"; - start: ProductDetails_product_pricing_priceRange_start | null; - stop: ProductDetails_product_pricing_priceRange_stop | null; -} - -export interface ProductDetails_product_pricing { - __typename: "ProductPricingInfo"; - priceRange: ProductDetails_product_pricing_priceRange | null; -} - export interface ProductDetails_product_images { __typename: "ProductImage"; id: string; @@ -143,7 +149,7 @@ export interface ProductDetails_product_images { url: string; } -export interface ProductDetails_product_variants_priceOverride { +export interface ProductDetails_product_variants_price { __typename: "Money"; amount: number; currency: string; @@ -163,27 +169,20 @@ export interface ProductDetails_product_variants_stocks { warehouse: ProductDetails_product_variants_stocks_warehouse; } -export interface ProductDetails_product_variants_weight { - __typename: "Weight"; - unit: string; - value: number; -} - export interface ProductDetails_product_variants { __typename: "ProductVariant"; id: string; sku: string; name: string; - priceOverride: ProductDetails_product_variants_priceOverride | null; + price: ProductDetails_product_variants_price | null; margin: number | null; stocks: (ProductDetails_product_variants_stocks | null)[] | null; trackInventory: boolean; - weight: ProductDetails_product_variants_weight | null; } export interface ProductDetails_product_weight { __typename: "Weight"; - unit: string; + unit: WeightUnitsEnum; value: number; } @@ -192,23 +191,27 @@ export interface ProductDetails_product { id: string; attributes: ProductDetails_product_attributes[]; productType: ProductDetails_product_productType; + pricing: ProductDetails_product_pricing | null; + metadata: (ProductDetails_product_metadata | null)[]; + privateMetadata: (ProductDetails_product_privateMetadata | null)[]; name: string; descriptionJson: any; seoTitle: string | null; seoDescription: string | null; category: ProductDetails_product_category | null; collections: (ProductDetails_product_collections | null)[] | null; - basePrice: ProductDetails_product_basePrice | null; margin: ProductDetails_product_margin | null; purchaseCost: ProductDetails_product_purchaseCost | null; + isAvailableForPurchase: boolean | null; isAvailable: boolean | null; isPublished: boolean; chargeTaxes: boolean; publicationDate: any | null; - pricing: ProductDetails_product_pricing | null; images: (ProductDetails_product_images | null)[] | null; variants: (ProductDetails_product_variants | null)[] | null; weight: ProductDetails_product_weight | null; + availableForPurchase: any | null; + visibleInListings: boolean; } export interface ProductDetails { diff --git a/src/products/types/ProductExport.ts b/src/products/types/ProductExport.ts new file mode 100644 index 000000000..fcc17aad1 --- /dev/null +++ b/src/products/types/ProductExport.ts @@ -0,0 +1,36 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { ExportProductsInput, JobStatusEnum, ExportErrorCode } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: ProductExport +// ==================================================== + +export interface ProductExport_exportProducts_exportFile { + __typename: "ExportFile"; + id: string; + status: JobStatusEnum; + url: string | null; +} + +export interface ProductExport_exportProducts_errors { + __typename: "ExportError"; + code: ExportErrorCode; + field: string | null; +} + +export interface ProductExport_exportProducts { + __typename: "ExportProducts"; + exportFile: ProductExport_exportProducts_exportFile | null; + errors: ProductExport_exportProducts_errors[]; +} + +export interface ProductExport { + exportProducts: ProductExport_exportProducts | null; +} + +export interface ProductExportVariables { + input: ExportProductsInput; +} diff --git a/src/products/types/ProductImage.ts b/src/products/types/ProductImage.ts deleted file mode 100644 index 8a5b981af..000000000 --- a/src/products/types/ProductImage.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* tslint:disable */ -// This file was automatically generated and should not be edited. - -// ==================================================== -// GraphQL fragment: ProductImage -// ==================================================== - -export interface ProductImage { - __typename: "ProductImage"; - id: string; - alt: string; - sortOrder: number; - url: string; -} diff --git a/src/products/types/ProductImageCreate.ts b/src/products/types/ProductImageCreate.ts index 6614ea716..9c472c556 100644 --- a/src/products/types/ProductImageCreate.ts +++ b/src/products/types/ProductImageCreate.ts @@ -2,7 +2,7 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { ProductErrorCode, AttributeInputTypeEnum } from "./../../types/globalTypes"; +import { ProductErrorCode, AttributeInputTypeEnum, WeightUnitsEnum } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: ProductImageCreate @@ -66,6 +66,51 @@ export interface ProductImageCreate_productImageCreate_product_productType { hasVariants: boolean; } +export interface ProductImageCreate_productImageCreate_product_pricing_priceRangeUndiscounted_start_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ProductImageCreate_productImageCreate_product_pricing_priceRangeUndiscounted_start { + __typename: "TaxedMoney"; + gross: ProductImageCreate_productImageCreate_product_pricing_priceRangeUndiscounted_start_gross; +} + +export interface ProductImageCreate_productImageCreate_product_pricing_priceRangeUndiscounted_stop_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ProductImageCreate_productImageCreate_product_pricing_priceRangeUndiscounted_stop { + __typename: "TaxedMoney"; + gross: ProductImageCreate_productImageCreate_product_pricing_priceRangeUndiscounted_stop_gross; +} + +export interface ProductImageCreate_productImageCreate_product_pricing_priceRangeUndiscounted { + __typename: "TaxedMoneyRange"; + start: ProductImageCreate_productImageCreate_product_pricing_priceRangeUndiscounted_start | null; + stop: ProductImageCreate_productImageCreate_product_pricing_priceRangeUndiscounted_stop | null; +} + +export interface ProductImageCreate_productImageCreate_product_pricing { + __typename: "ProductPricingInfo"; + priceRangeUndiscounted: ProductImageCreate_productImageCreate_product_pricing_priceRangeUndiscounted | null; +} + +export interface ProductImageCreate_productImageCreate_product_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface ProductImageCreate_productImageCreate_product_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface ProductImageCreate_productImageCreate_product_category { __typename: "Category"; id: string; @@ -78,12 +123,6 @@ export interface ProductImageCreate_productImageCreate_product_collections { name: string; } -export interface ProductImageCreate_productImageCreate_product_basePrice { - __typename: "Money"; - amount: number; - currency: string; -} - export interface ProductImageCreate_productImageCreate_product_margin { __typename: "Margin"; start: number | null; @@ -108,39 +147,6 @@ export interface ProductImageCreate_productImageCreate_product_purchaseCost { stop: ProductImageCreate_productImageCreate_product_purchaseCost_stop | null; } -export interface ProductImageCreate_productImageCreate_product_pricing_priceRange_start_net { - __typename: "Money"; - amount: number; - currency: string; -} - -export interface ProductImageCreate_productImageCreate_product_pricing_priceRange_start { - __typename: "TaxedMoney"; - net: ProductImageCreate_productImageCreate_product_pricing_priceRange_start_net; -} - -export interface ProductImageCreate_productImageCreate_product_pricing_priceRange_stop_net { - __typename: "Money"; - amount: number; - currency: string; -} - -export interface ProductImageCreate_productImageCreate_product_pricing_priceRange_stop { - __typename: "TaxedMoney"; - net: ProductImageCreate_productImageCreate_product_pricing_priceRange_stop_net; -} - -export interface ProductImageCreate_productImageCreate_product_pricing_priceRange { - __typename: "TaxedMoneyRange"; - start: ProductImageCreate_productImageCreate_product_pricing_priceRange_start | null; - stop: ProductImageCreate_productImageCreate_product_pricing_priceRange_stop | null; -} - -export interface ProductImageCreate_productImageCreate_product_pricing { - __typename: "ProductPricingInfo"; - priceRange: ProductImageCreate_productImageCreate_product_pricing_priceRange | null; -} - export interface ProductImageCreate_productImageCreate_product_images { __typename: "ProductImage"; id: string; @@ -149,7 +155,7 @@ export interface ProductImageCreate_productImageCreate_product_images { url: string; } -export interface ProductImageCreate_productImageCreate_product_variants_priceOverride { +export interface ProductImageCreate_productImageCreate_product_variants_price { __typename: "Money"; amount: number; currency: string; @@ -169,27 +175,20 @@ export interface ProductImageCreate_productImageCreate_product_variants_stocks { warehouse: ProductImageCreate_productImageCreate_product_variants_stocks_warehouse; } -export interface ProductImageCreate_productImageCreate_product_variants_weight { - __typename: "Weight"; - unit: string; - value: number; -} - export interface ProductImageCreate_productImageCreate_product_variants { __typename: "ProductVariant"; id: string; sku: string; name: string; - priceOverride: ProductImageCreate_productImageCreate_product_variants_priceOverride | null; + price: ProductImageCreate_productImageCreate_product_variants_price | null; margin: number | null; stocks: (ProductImageCreate_productImageCreate_product_variants_stocks | null)[] | null; trackInventory: boolean; - weight: ProductImageCreate_productImageCreate_product_variants_weight | null; } export interface ProductImageCreate_productImageCreate_product_weight { __typename: "Weight"; - unit: string; + unit: WeightUnitsEnum; value: number; } @@ -198,23 +197,27 @@ export interface ProductImageCreate_productImageCreate_product { id: string; attributes: ProductImageCreate_productImageCreate_product_attributes[]; productType: ProductImageCreate_productImageCreate_product_productType; + pricing: ProductImageCreate_productImageCreate_product_pricing | null; + metadata: (ProductImageCreate_productImageCreate_product_metadata | null)[]; + privateMetadata: (ProductImageCreate_productImageCreate_product_privateMetadata | null)[]; name: string; descriptionJson: any; seoTitle: string | null; seoDescription: string | null; category: ProductImageCreate_productImageCreate_product_category | null; collections: (ProductImageCreate_productImageCreate_product_collections | null)[] | null; - basePrice: ProductImageCreate_productImageCreate_product_basePrice | null; margin: ProductImageCreate_productImageCreate_product_margin | null; purchaseCost: ProductImageCreate_productImageCreate_product_purchaseCost | null; + isAvailableForPurchase: boolean | null; isAvailable: boolean | null; isPublished: boolean; chargeTaxes: boolean; publicationDate: any | null; - pricing: ProductImageCreate_productImageCreate_product_pricing | null; images: (ProductImageCreate_productImageCreate_product_images | null)[] | null; variants: (ProductImageCreate_productImageCreate_product_variants | null)[] | null; weight: ProductImageCreate_productImageCreate_product_weight | null; + availableForPurchase: any | null; + visibleInListings: boolean; } export interface ProductImageCreate_productImageCreate { diff --git a/src/products/types/ProductImageUpdate.ts b/src/products/types/ProductImageUpdate.ts index 26adab936..e85899725 100644 --- a/src/products/types/ProductImageUpdate.ts +++ b/src/products/types/ProductImageUpdate.ts @@ -2,7 +2,7 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { ProductErrorCode, AttributeInputTypeEnum } from "./../../types/globalTypes"; +import { ProductErrorCode, AttributeInputTypeEnum, WeightUnitsEnum } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: ProductImageUpdate @@ -66,6 +66,51 @@ export interface ProductImageUpdate_productImageUpdate_product_productType { hasVariants: boolean; } +export interface ProductImageUpdate_productImageUpdate_product_pricing_priceRangeUndiscounted_start_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ProductImageUpdate_productImageUpdate_product_pricing_priceRangeUndiscounted_start { + __typename: "TaxedMoney"; + gross: ProductImageUpdate_productImageUpdate_product_pricing_priceRangeUndiscounted_start_gross; +} + +export interface ProductImageUpdate_productImageUpdate_product_pricing_priceRangeUndiscounted_stop_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ProductImageUpdate_productImageUpdate_product_pricing_priceRangeUndiscounted_stop { + __typename: "TaxedMoney"; + gross: ProductImageUpdate_productImageUpdate_product_pricing_priceRangeUndiscounted_stop_gross; +} + +export interface ProductImageUpdate_productImageUpdate_product_pricing_priceRangeUndiscounted { + __typename: "TaxedMoneyRange"; + start: ProductImageUpdate_productImageUpdate_product_pricing_priceRangeUndiscounted_start | null; + stop: ProductImageUpdate_productImageUpdate_product_pricing_priceRangeUndiscounted_stop | null; +} + +export interface ProductImageUpdate_productImageUpdate_product_pricing { + __typename: "ProductPricingInfo"; + priceRangeUndiscounted: ProductImageUpdate_productImageUpdate_product_pricing_priceRangeUndiscounted | null; +} + +export interface ProductImageUpdate_productImageUpdate_product_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface ProductImageUpdate_productImageUpdate_product_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface ProductImageUpdate_productImageUpdate_product_category { __typename: "Category"; id: string; @@ -78,12 +123,6 @@ export interface ProductImageUpdate_productImageUpdate_product_collections { name: string; } -export interface ProductImageUpdate_productImageUpdate_product_basePrice { - __typename: "Money"; - amount: number; - currency: string; -} - export interface ProductImageUpdate_productImageUpdate_product_margin { __typename: "Margin"; start: number | null; @@ -108,39 +147,6 @@ export interface ProductImageUpdate_productImageUpdate_product_purchaseCost { stop: ProductImageUpdate_productImageUpdate_product_purchaseCost_stop | null; } -export interface ProductImageUpdate_productImageUpdate_product_pricing_priceRange_start_net { - __typename: "Money"; - amount: number; - currency: string; -} - -export interface ProductImageUpdate_productImageUpdate_product_pricing_priceRange_start { - __typename: "TaxedMoney"; - net: ProductImageUpdate_productImageUpdate_product_pricing_priceRange_start_net; -} - -export interface ProductImageUpdate_productImageUpdate_product_pricing_priceRange_stop_net { - __typename: "Money"; - amount: number; - currency: string; -} - -export interface ProductImageUpdate_productImageUpdate_product_pricing_priceRange_stop { - __typename: "TaxedMoney"; - net: ProductImageUpdate_productImageUpdate_product_pricing_priceRange_stop_net; -} - -export interface ProductImageUpdate_productImageUpdate_product_pricing_priceRange { - __typename: "TaxedMoneyRange"; - start: ProductImageUpdate_productImageUpdate_product_pricing_priceRange_start | null; - stop: ProductImageUpdate_productImageUpdate_product_pricing_priceRange_stop | null; -} - -export interface ProductImageUpdate_productImageUpdate_product_pricing { - __typename: "ProductPricingInfo"; - priceRange: ProductImageUpdate_productImageUpdate_product_pricing_priceRange | null; -} - export interface ProductImageUpdate_productImageUpdate_product_images { __typename: "ProductImage"; id: string; @@ -149,7 +155,7 @@ export interface ProductImageUpdate_productImageUpdate_product_images { url: string; } -export interface ProductImageUpdate_productImageUpdate_product_variants_priceOverride { +export interface ProductImageUpdate_productImageUpdate_product_variants_price { __typename: "Money"; amount: number; currency: string; @@ -169,27 +175,20 @@ export interface ProductImageUpdate_productImageUpdate_product_variants_stocks { warehouse: ProductImageUpdate_productImageUpdate_product_variants_stocks_warehouse; } -export interface ProductImageUpdate_productImageUpdate_product_variants_weight { - __typename: "Weight"; - unit: string; - value: number; -} - export interface ProductImageUpdate_productImageUpdate_product_variants { __typename: "ProductVariant"; id: string; sku: string; name: string; - priceOverride: ProductImageUpdate_productImageUpdate_product_variants_priceOverride | null; + price: ProductImageUpdate_productImageUpdate_product_variants_price | null; margin: number | null; stocks: (ProductImageUpdate_productImageUpdate_product_variants_stocks | null)[] | null; trackInventory: boolean; - weight: ProductImageUpdate_productImageUpdate_product_variants_weight | null; } export interface ProductImageUpdate_productImageUpdate_product_weight { __typename: "Weight"; - unit: string; + unit: WeightUnitsEnum; value: number; } @@ -198,23 +197,27 @@ export interface ProductImageUpdate_productImageUpdate_product { id: string; attributes: ProductImageUpdate_productImageUpdate_product_attributes[]; productType: ProductImageUpdate_productImageUpdate_product_productType; + pricing: ProductImageUpdate_productImageUpdate_product_pricing | null; + metadata: (ProductImageUpdate_productImageUpdate_product_metadata | null)[]; + privateMetadata: (ProductImageUpdate_productImageUpdate_product_privateMetadata | null)[]; name: string; descriptionJson: any; seoTitle: string | null; seoDescription: string | null; category: ProductImageUpdate_productImageUpdate_product_category | null; collections: (ProductImageUpdate_productImageUpdate_product_collections | null)[] | null; - basePrice: ProductImageUpdate_productImageUpdate_product_basePrice | null; margin: ProductImageUpdate_productImageUpdate_product_margin | null; purchaseCost: ProductImageUpdate_productImageUpdate_product_purchaseCost | null; + isAvailableForPurchase: boolean | null; isAvailable: boolean | null; isPublished: boolean; chargeTaxes: boolean; publicationDate: any | null; - pricing: ProductImageUpdate_productImageUpdate_product_pricing | null; images: (ProductImageUpdate_productImageUpdate_product_images | null)[] | null; variants: (ProductImageUpdate_productImageUpdate_product_variants | null)[] | null; weight: ProductImageUpdate_productImageUpdate_product_weight | null; + availableForPurchase: any | null; + visibleInListings: boolean; } export interface ProductImageUpdate_productImageUpdate { diff --git a/src/products/types/ProductList.ts b/src/products/types/ProductList.ts index 7931b98d2..c96e1001a 100644 --- a/src/products/types/ProductList.ts +++ b/src/products/types/ProductList.ts @@ -13,16 +13,11 @@ export interface ProductList_products_edges_node_thumbnail { url: string; } -export interface ProductList_products_edges_node_basePrice { - __typename: "Money"; - amount: number; - currency: string; -} - export interface ProductList_products_edges_node_productType { __typename: "ProductType"; id: string; name: string; + hasVariants: boolean; } export interface ProductList_products_edges_node_attributes_attribute { @@ -42,6 +37,39 @@ export interface ProductList_products_edges_node_attributes { values: (ProductList_products_edges_node_attributes_values | null)[]; } +export interface ProductList_products_edges_node_pricing_priceRangeUndiscounted_start_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ProductList_products_edges_node_pricing_priceRangeUndiscounted_start { + __typename: "TaxedMoney"; + gross: ProductList_products_edges_node_pricing_priceRangeUndiscounted_start_gross; +} + +export interface ProductList_products_edges_node_pricing_priceRangeUndiscounted_stop_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ProductList_products_edges_node_pricing_priceRangeUndiscounted_stop { + __typename: "TaxedMoney"; + gross: ProductList_products_edges_node_pricing_priceRangeUndiscounted_stop_gross; +} + +export interface ProductList_products_edges_node_pricing_priceRangeUndiscounted { + __typename: "TaxedMoneyRange"; + start: ProductList_products_edges_node_pricing_priceRangeUndiscounted_start | null; + stop: ProductList_products_edges_node_pricing_priceRangeUndiscounted_stop | null; +} + +export interface ProductList_products_edges_node_pricing { + __typename: "ProductPricingInfo"; + priceRangeUndiscounted: ProductList_products_edges_node_pricing_priceRangeUndiscounted | null; +} + export interface ProductList_products_edges_node { __typename: "Product"; id: string; @@ -49,9 +77,9 @@ export interface ProductList_products_edges_node { thumbnail: ProductList_products_edges_node_thumbnail | null; isAvailable: boolean | null; isPublished: boolean; - basePrice: ProductList_products_edges_node_basePrice | null; productType: ProductList_products_edges_node_productType; attributes: ProductList_products_edges_node_attributes[]; + pricing: ProductList_products_edges_node_pricing | null; } export interface ProductList_products_edges { @@ -71,6 +99,7 @@ export interface ProductList_products { __typename: "ProductCountableConnection"; edges: ProductList_products_edges[]; pageInfo: ProductList_products_pageInfo; + totalCount: number | null; } export interface ProductList { diff --git a/src/products/types/ProductSetAvailabilityForPurchase.ts b/src/products/types/ProductSetAvailabilityForPurchase.ts new file mode 100644 index 000000000..cc8cb6557 --- /dev/null +++ b/src/products/types/ProductSetAvailabilityForPurchase.ts @@ -0,0 +1,31 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { ProductErrorCode } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: ProductSetAvailabilityForPurchase +// ==================================================== + +export interface ProductSetAvailabilityForPurchase_productSetAvailabilityForPurchase_errors { + __typename: "ProductError"; + code: ProductErrorCode; + field: string | null; + message: string | null; +} + +export interface ProductSetAvailabilityForPurchase_productSetAvailabilityForPurchase { + __typename: "ProductSetAvailabilityForPurchase"; + errors: ProductSetAvailabilityForPurchase_productSetAvailabilityForPurchase_errors[]; +} + +export interface ProductSetAvailabilityForPurchase { + productSetAvailabilityForPurchase: ProductSetAvailabilityForPurchase_productSetAvailabilityForPurchase | null; +} + +export interface ProductSetAvailabilityForPurchaseVariables { + isAvailable: boolean; + productId: string; + startDate?: any | null; +} diff --git a/src/products/types/ProductUpdate.ts b/src/products/types/ProductUpdate.ts index 6a4e68411..f03604480 100644 --- a/src/products/types/ProductUpdate.ts +++ b/src/products/types/ProductUpdate.ts @@ -2,7 +2,7 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { AttributeValueInput, SeoInput, ProductErrorCode, AttributeInputTypeEnum } from "./../../types/globalTypes"; +import { AttributeValueInput, SeoInput, ProductErrorCode, AttributeInputTypeEnum, WeightUnitsEnum } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: ProductUpdate @@ -66,6 +66,51 @@ export interface ProductUpdate_productUpdate_product_productType { hasVariants: boolean; } +export interface ProductUpdate_productUpdate_product_pricing_priceRangeUndiscounted_start_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ProductUpdate_productUpdate_product_pricing_priceRangeUndiscounted_start { + __typename: "TaxedMoney"; + gross: ProductUpdate_productUpdate_product_pricing_priceRangeUndiscounted_start_gross; +} + +export interface ProductUpdate_productUpdate_product_pricing_priceRangeUndiscounted_stop_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ProductUpdate_productUpdate_product_pricing_priceRangeUndiscounted_stop { + __typename: "TaxedMoney"; + gross: ProductUpdate_productUpdate_product_pricing_priceRangeUndiscounted_stop_gross; +} + +export interface ProductUpdate_productUpdate_product_pricing_priceRangeUndiscounted { + __typename: "TaxedMoneyRange"; + start: ProductUpdate_productUpdate_product_pricing_priceRangeUndiscounted_start | null; + stop: ProductUpdate_productUpdate_product_pricing_priceRangeUndiscounted_stop | null; +} + +export interface ProductUpdate_productUpdate_product_pricing { + __typename: "ProductPricingInfo"; + priceRangeUndiscounted: ProductUpdate_productUpdate_product_pricing_priceRangeUndiscounted | null; +} + +export interface ProductUpdate_productUpdate_product_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface ProductUpdate_productUpdate_product_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface ProductUpdate_productUpdate_product_category { __typename: "Category"; id: string; @@ -78,12 +123,6 @@ export interface ProductUpdate_productUpdate_product_collections { name: string; } -export interface ProductUpdate_productUpdate_product_basePrice { - __typename: "Money"; - amount: number; - currency: string; -} - export interface ProductUpdate_productUpdate_product_margin { __typename: "Margin"; start: number | null; @@ -108,39 +147,6 @@ export interface ProductUpdate_productUpdate_product_purchaseCost { stop: ProductUpdate_productUpdate_product_purchaseCost_stop | null; } -export interface ProductUpdate_productUpdate_product_pricing_priceRange_start_net { - __typename: "Money"; - amount: number; - currency: string; -} - -export interface ProductUpdate_productUpdate_product_pricing_priceRange_start { - __typename: "TaxedMoney"; - net: ProductUpdate_productUpdate_product_pricing_priceRange_start_net; -} - -export interface ProductUpdate_productUpdate_product_pricing_priceRange_stop_net { - __typename: "Money"; - amount: number; - currency: string; -} - -export interface ProductUpdate_productUpdate_product_pricing_priceRange_stop { - __typename: "TaxedMoney"; - net: ProductUpdate_productUpdate_product_pricing_priceRange_stop_net; -} - -export interface ProductUpdate_productUpdate_product_pricing_priceRange { - __typename: "TaxedMoneyRange"; - start: ProductUpdate_productUpdate_product_pricing_priceRange_start | null; - stop: ProductUpdate_productUpdate_product_pricing_priceRange_stop | null; -} - -export interface ProductUpdate_productUpdate_product_pricing { - __typename: "ProductPricingInfo"; - priceRange: ProductUpdate_productUpdate_product_pricing_priceRange | null; -} - export interface ProductUpdate_productUpdate_product_images { __typename: "ProductImage"; id: string; @@ -149,7 +155,7 @@ export interface ProductUpdate_productUpdate_product_images { url: string; } -export interface ProductUpdate_productUpdate_product_variants_priceOverride { +export interface ProductUpdate_productUpdate_product_variants_price { __typename: "Money"; amount: number; currency: string; @@ -169,27 +175,20 @@ export interface ProductUpdate_productUpdate_product_variants_stocks { warehouse: ProductUpdate_productUpdate_product_variants_stocks_warehouse; } -export interface ProductUpdate_productUpdate_product_variants_weight { - __typename: "Weight"; - unit: string; - value: number; -} - export interface ProductUpdate_productUpdate_product_variants { __typename: "ProductVariant"; id: string; sku: string; name: string; - priceOverride: ProductUpdate_productUpdate_product_variants_priceOverride | null; + price: ProductUpdate_productUpdate_product_variants_price | null; margin: number | null; stocks: (ProductUpdate_productUpdate_product_variants_stocks | null)[] | null; trackInventory: boolean; - weight: ProductUpdate_productUpdate_product_variants_weight | null; } export interface ProductUpdate_productUpdate_product_weight { __typename: "Weight"; - unit: string; + unit: WeightUnitsEnum; value: number; } @@ -198,23 +197,27 @@ export interface ProductUpdate_productUpdate_product { id: string; attributes: ProductUpdate_productUpdate_product_attributes[]; productType: ProductUpdate_productUpdate_product_productType; + pricing: ProductUpdate_productUpdate_product_pricing | null; + metadata: (ProductUpdate_productUpdate_product_metadata | null)[]; + privateMetadata: (ProductUpdate_productUpdate_product_privateMetadata | null)[]; name: string; descriptionJson: any; seoTitle: string | null; seoDescription: string | null; category: ProductUpdate_productUpdate_product_category | null; collections: (ProductUpdate_productUpdate_product_collections | null)[] | null; - basePrice: ProductUpdate_productUpdate_product_basePrice | null; margin: ProductUpdate_productUpdate_product_margin | null; purchaseCost: ProductUpdate_productUpdate_product_purchaseCost | null; + isAvailableForPurchase: boolean | null; isAvailable: boolean | null; isPublished: boolean; chargeTaxes: boolean; publicationDate: any | null; - pricing: ProductUpdate_productUpdate_product_pricing | null; images: (ProductUpdate_productUpdate_product_images | null)[] | null; variants: (ProductUpdate_productUpdate_product_variants | null)[] | null; weight: ProductUpdate_productUpdate_product_weight | null; + availableForPurchase: any | null; + visibleInListings: boolean; } export interface ProductUpdate_productUpdate { @@ -239,4 +242,5 @@ export interface ProductUpdateVariables { name?: string | null; basePrice?: any | null; seo?: SeoInput | null; + visibleInListings?: boolean | null; } diff --git a/src/products/types/ProductVariantDetails.ts b/src/products/types/ProductVariantDetails.ts index 43a1871e7..425cbc21d 100644 --- a/src/products/types/ProductVariantDetails.ts +++ b/src/products/types/ProductVariantDetails.ts @@ -2,10 +2,24 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. +import { WeightUnitsEnum } from "./../../types/globalTypes"; + // ==================================================== // GraphQL query operation: ProductVariantDetails // ==================================================== +export interface ProductVariantDetails_productVariant_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface ProductVariantDetails_productVariant_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface ProductVariantDetails_productVariant_attributes_attribute_values { __typename: "AttributeValue"; id: string; @@ -47,7 +61,7 @@ export interface ProductVariantDetails_productVariant_images { url: string; } -export interface ProductVariantDetails_productVariant_priceOverride { +export interface ProductVariantDetails_productVariant_price { __typename: "Money"; amount: number; currency: string; @@ -105,18 +119,20 @@ export interface ProductVariantDetails_productVariant_stocks { export interface ProductVariantDetails_productVariant_weight { __typename: "Weight"; - unit: string; + unit: WeightUnitsEnum; value: number; } export interface ProductVariantDetails_productVariant { __typename: "ProductVariant"; id: string; + metadata: (ProductVariantDetails_productVariant_metadata | null)[]; + privateMetadata: (ProductVariantDetails_productVariant_privateMetadata | null)[]; attributes: ProductVariantDetails_productVariant_attributes[]; costPrice: ProductVariantDetails_productVariant_costPrice | null; images: (ProductVariantDetails_productVariant_images | null)[] | null; name: string; - priceOverride: ProductVariantDetails_productVariant_priceOverride | null; + price: ProductVariantDetails_productVariant_price | null; product: ProductVariantDetails_productVariant_product; sku: string; stocks: (ProductVariantDetails_productVariant_stocks | null)[] | null; diff --git a/src/products/types/SimpleProductUpdate.ts b/src/products/types/SimpleProductUpdate.ts index 4ebea508f..e023f09b1 100644 --- a/src/products/types/SimpleProductUpdate.ts +++ b/src/products/types/SimpleProductUpdate.ts @@ -2,7 +2,7 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { AttributeValueInput, ProductVariantInput, SeoInput, StockInput, ProductErrorCode, AttributeInputTypeEnum, StockErrorCode } from "./../../types/globalTypes"; +import { AttributeValueInput, ProductVariantInput, SeoInput, StockInput, ProductErrorCode, AttributeInputTypeEnum, WeightUnitsEnum, StockErrorCode } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: SimpleProductUpdate @@ -66,6 +66,51 @@ export interface SimpleProductUpdate_productUpdate_product_productType { hasVariants: boolean; } +export interface SimpleProductUpdate_productUpdate_product_pricing_priceRangeUndiscounted_start_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface SimpleProductUpdate_productUpdate_product_pricing_priceRangeUndiscounted_start { + __typename: "TaxedMoney"; + gross: SimpleProductUpdate_productUpdate_product_pricing_priceRangeUndiscounted_start_gross; +} + +export interface SimpleProductUpdate_productUpdate_product_pricing_priceRangeUndiscounted_stop_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface SimpleProductUpdate_productUpdate_product_pricing_priceRangeUndiscounted_stop { + __typename: "TaxedMoney"; + gross: SimpleProductUpdate_productUpdate_product_pricing_priceRangeUndiscounted_stop_gross; +} + +export interface SimpleProductUpdate_productUpdate_product_pricing_priceRangeUndiscounted { + __typename: "TaxedMoneyRange"; + start: SimpleProductUpdate_productUpdate_product_pricing_priceRangeUndiscounted_start | null; + stop: SimpleProductUpdate_productUpdate_product_pricing_priceRangeUndiscounted_stop | null; +} + +export interface SimpleProductUpdate_productUpdate_product_pricing { + __typename: "ProductPricingInfo"; + priceRangeUndiscounted: SimpleProductUpdate_productUpdate_product_pricing_priceRangeUndiscounted | null; +} + +export interface SimpleProductUpdate_productUpdate_product_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface SimpleProductUpdate_productUpdate_product_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface SimpleProductUpdate_productUpdate_product_category { __typename: "Category"; id: string; @@ -78,12 +123,6 @@ export interface SimpleProductUpdate_productUpdate_product_collections { name: string; } -export interface SimpleProductUpdate_productUpdate_product_basePrice { - __typename: "Money"; - amount: number; - currency: string; -} - export interface SimpleProductUpdate_productUpdate_product_margin { __typename: "Margin"; start: number | null; @@ -108,39 +147,6 @@ export interface SimpleProductUpdate_productUpdate_product_purchaseCost { stop: SimpleProductUpdate_productUpdate_product_purchaseCost_stop | null; } -export interface SimpleProductUpdate_productUpdate_product_pricing_priceRange_start_net { - __typename: "Money"; - amount: number; - currency: string; -} - -export interface SimpleProductUpdate_productUpdate_product_pricing_priceRange_start { - __typename: "TaxedMoney"; - net: SimpleProductUpdate_productUpdate_product_pricing_priceRange_start_net; -} - -export interface SimpleProductUpdate_productUpdate_product_pricing_priceRange_stop_net { - __typename: "Money"; - amount: number; - currency: string; -} - -export interface SimpleProductUpdate_productUpdate_product_pricing_priceRange_stop { - __typename: "TaxedMoney"; - net: SimpleProductUpdate_productUpdate_product_pricing_priceRange_stop_net; -} - -export interface SimpleProductUpdate_productUpdate_product_pricing_priceRange { - __typename: "TaxedMoneyRange"; - start: SimpleProductUpdate_productUpdate_product_pricing_priceRange_start | null; - stop: SimpleProductUpdate_productUpdate_product_pricing_priceRange_stop | null; -} - -export interface SimpleProductUpdate_productUpdate_product_pricing { - __typename: "ProductPricingInfo"; - priceRange: SimpleProductUpdate_productUpdate_product_pricing_priceRange | null; -} - export interface SimpleProductUpdate_productUpdate_product_images { __typename: "ProductImage"; id: string; @@ -149,7 +155,7 @@ export interface SimpleProductUpdate_productUpdate_product_images { url: string; } -export interface SimpleProductUpdate_productUpdate_product_variants_priceOverride { +export interface SimpleProductUpdate_productUpdate_product_variants_price { __typename: "Money"; amount: number; currency: string; @@ -169,27 +175,20 @@ export interface SimpleProductUpdate_productUpdate_product_variants_stocks { warehouse: SimpleProductUpdate_productUpdate_product_variants_stocks_warehouse; } -export interface SimpleProductUpdate_productUpdate_product_variants_weight { - __typename: "Weight"; - unit: string; - value: number; -} - export interface SimpleProductUpdate_productUpdate_product_variants { __typename: "ProductVariant"; id: string; sku: string; name: string; - priceOverride: SimpleProductUpdate_productUpdate_product_variants_priceOverride | null; + price: SimpleProductUpdate_productUpdate_product_variants_price | null; margin: number | null; stocks: (SimpleProductUpdate_productUpdate_product_variants_stocks | null)[] | null; trackInventory: boolean; - weight: SimpleProductUpdate_productUpdate_product_variants_weight | null; } export interface SimpleProductUpdate_productUpdate_product_weight { __typename: "Weight"; - unit: string; + unit: WeightUnitsEnum; value: number; } @@ -198,23 +197,27 @@ export interface SimpleProductUpdate_productUpdate_product { id: string; attributes: SimpleProductUpdate_productUpdate_product_attributes[]; productType: SimpleProductUpdate_productUpdate_product_productType; + pricing: SimpleProductUpdate_productUpdate_product_pricing | null; + metadata: (SimpleProductUpdate_productUpdate_product_metadata | null)[]; + privateMetadata: (SimpleProductUpdate_productUpdate_product_privateMetadata | null)[]; name: string; descriptionJson: any; seoTitle: string | null; seoDescription: string | null; category: SimpleProductUpdate_productUpdate_product_category | null; collections: (SimpleProductUpdate_productUpdate_product_collections | null)[] | null; - basePrice: SimpleProductUpdate_productUpdate_product_basePrice | null; margin: SimpleProductUpdate_productUpdate_product_margin | null; purchaseCost: SimpleProductUpdate_productUpdate_product_purchaseCost | null; + isAvailableForPurchase: boolean | null; isAvailable: boolean | null; isPublished: boolean; chargeTaxes: boolean; publicationDate: any | null; - pricing: SimpleProductUpdate_productUpdate_product_pricing | null; images: (SimpleProductUpdate_productUpdate_product_images | null)[] | null; variants: (SimpleProductUpdate_productUpdate_product_variants | null)[] | null; weight: SimpleProductUpdate_productUpdate_product_weight | null; + availableForPurchase: any | null; + visibleInListings: boolean; } export interface SimpleProductUpdate_productUpdate { @@ -229,6 +232,18 @@ export interface SimpleProductUpdate_productVariantUpdate_errors { field: string | null; } +export interface SimpleProductUpdate_productVariantUpdate_productVariant_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface SimpleProductUpdate_productVariantUpdate_productVariant_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface SimpleProductUpdate_productVariantUpdate_productVariant_attributes_attribute_values { __typename: "AttributeValue"; id: string; @@ -270,7 +285,7 @@ export interface SimpleProductUpdate_productVariantUpdate_productVariant_images url: string; } -export interface SimpleProductUpdate_productVariantUpdate_productVariant_priceOverride { +export interface SimpleProductUpdate_productVariantUpdate_productVariant_price { __typename: "Money"; amount: number; currency: string; @@ -328,18 +343,20 @@ export interface SimpleProductUpdate_productVariantUpdate_productVariant_stocks export interface SimpleProductUpdate_productVariantUpdate_productVariant_weight { __typename: "Weight"; - unit: string; + unit: WeightUnitsEnum; value: number; } export interface SimpleProductUpdate_productVariantUpdate_productVariant { __typename: "ProductVariant"; id: string; + metadata: (SimpleProductUpdate_productVariantUpdate_productVariant_metadata | null)[]; + privateMetadata: (SimpleProductUpdate_productVariantUpdate_productVariant_privateMetadata | null)[]; attributes: SimpleProductUpdate_productVariantUpdate_productVariant_attributes[]; costPrice: SimpleProductUpdate_productVariantUpdate_productVariant_costPrice | null; images: (SimpleProductUpdate_productVariantUpdate_productVariant_images | null)[] | null; name: string; - priceOverride: SimpleProductUpdate_productVariantUpdate_productVariant_priceOverride | null; + price: SimpleProductUpdate_productVariantUpdate_productVariant_price | null; product: SimpleProductUpdate_productVariantUpdate_productVariant_product; sku: string; stocks: (SimpleProductUpdate_productVariantUpdate_productVariant_stocks | null)[] | null; @@ -360,6 +377,18 @@ export interface SimpleProductUpdate_productVariantStocksCreate_errors { index: number | null; } +export interface SimpleProductUpdate_productVariantStocksCreate_productVariant_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface SimpleProductUpdate_productVariantStocksCreate_productVariant_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface SimpleProductUpdate_productVariantStocksCreate_productVariant_attributes_attribute_values { __typename: "AttributeValue"; id: string; @@ -401,7 +430,7 @@ export interface SimpleProductUpdate_productVariantStocksCreate_productVariant_i url: string; } -export interface SimpleProductUpdate_productVariantStocksCreate_productVariant_priceOverride { +export interface SimpleProductUpdate_productVariantStocksCreate_productVariant_price { __typename: "Money"; amount: number; currency: string; @@ -459,18 +488,20 @@ export interface SimpleProductUpdate_productVariantStocksCreate_productVariant_s export interface SimpleProductUpdate_productVariantStocksCreate_productVariant_weight { __typename: "Weight"; - unit: string; + unit: WeightUnitsEnum; value: number; } export interface SimpleProductUpdate_productVariantStocksCreate_productVariant { __typename: "ProductVariant"; id: string; + metadata: (SimpleProductUpdate_productVariantStocksCreate_productVariant_metadata | null)[]; + privateMetadata: (SimpleProductUpdate_productVariantStocksCreate_productVariant_privateMetadata | null)[]; attributes: SimpleProductUpdate_productVariantStocksCreate_productVariant_attributes[]; costPrice: SimpleProductUpdate_productVariantStocksCreate_productVariant_costPrice | null; images: (SimpleProductUpdate_productVariantStocksCreate_productVariant_images | null)[] | null; name: string; - priceOverride: SimpleProductUpdate_productVariantStocksCreate_productVariant_priceOverride | null; + price: SimpleProductUpdate_productVariantStocksCreate_productVariant_price | null; product: SimpleProductUpdate_productVariantStocksCreate_productVariant_product; sku: string; stocks: (SimpleProductUpdate_productVariantStocksCreate_productVariant_stocks | null)[] | null; @@ -490,6 +521,18 @@ export interface SimpleProductUpdate_productVariantStocksDelete_errors { field: string | null; } +export interface SimpleProductUpdate_productVariantStocksDelete_productVariant_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface SimpleProductUpdate_productVariantStocksDelete_productVariant_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface SimpleProductUpdate_productVariantStocksDelete_productVariant_attributes_attribute_values { __typename: "AttributeValue"; id: string; @@ -531,7 +574,7 @@ export interface SimpleProductUpdate_productVariantStocksDelete_productVariant_i url: string; } -export interface SimpleProductUpdate_productVariantStocksDelete_productVariant_priceOverride { +export interface SimpleProductUpdate_productVariantStocksDelete_productVariant_price { __typename: "Money"; amount: number; currency: string; @@ -589,18 +632,20 @@ export interface SimpleProductUpdate_productVariantStocksDelete_productVariant_s export interface SimpleProductUpdate_productVariantStocksDelete_productVariant_weight { __typename: "Weight"; - unit: string; + unit: WeightUnitsEnum; value: number; } export interface SimpleProductUpdate_productVariantStocksDelete_productVariant { __typename: "ProductVariant"; id: string; + metadata: (SimpleProductUpdate_productVariantStocksDelete_productVariant_metadata | null)[]; + privateMetadata: (SimpleProductUpdate_productVariantStocksDelete_productVariant_privateMetadata | null)[]; attributes: SimpleProductUpdate_productVariantStocksDelete_productVariant_attributes[]; costPrice: SimpleProductUpdate_productVariantStocksDelete_productVariant_costPrice | null; images: (SimpleProductUpdate_productVariantStocksDelete_productVariant_images | null)[] | null; name: string; - priceOverride: SimpleProductUpdate_productVariantStocksDelete_productVariant_priceOverride | null; + price: SimpleProductUpdate_productVariantStocksDelete_productVariant_price | null; product: SimpleProductUpdate_productVariantStocksDelete_productVariant_product; sku: string; stocks: (SimpleProductUpdate_productVariantStocksDelete_productVariant_stocks | null)[] | null; @@ -621,6 +666,18 @@ export interface SimpleProductUpdate_productVariantStocksUpdate_errors { index: number | null; } +export interface SimpleProductUpdate_productVariantStocksUpdate_productVariant_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface SimpleProductUpdate_productVariantStocksUpdate_productVariant_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface SimpleProductUpdate_productVariantStocksUpdate_productVariant_attributes_attribute_values { __typename: "AttributeValue"; id: string; @@ -662,7 +719,7 @@ export interface SimpleProductUpdate_productVariantStocksUpdate_productVariant_i url: string; } -export interface SimpleProductUpdate_productVariantStocksUpdate_productVariant_priceOverride { +export interface SimpleProductUpdate_productVariantStocksUpdate_productVariant_price { __typename: "Money"; amount: number; currency: string; @@ -720,18 +777,20 @@ export interface SimpleProductUpdate_productVariantStocksUpdate_productVariant_s export interface SimpleProductUpdate_productVariantStocksUpdate_productVariant_weight { __typename: "Weight"; - unit: string; + unit: WeightUnitsEnum; value: number; } export interface SimpleProductUpdate_productVariantStocksUpdate_productVariant { __typename: "ProductVariant"; id: string; + metadata: (SimpleProductUpdate_productVariantStocksUpdate_productVariant_metadata | null)[]; + privateMetadata: (SimpleProductUpdate_productVariantStocksUpdate_productVariant_privateMetadata | null)[]; attributes: SimpleProductUpdate_productVariantStocksUpdate_productVariant_attributes[]; costPrice: SimpleProductUpdate_productVariantStocksUpdate_productVariant_costPrice | null; images: (SimpleProductUpdate_productVariantStocksUpdate_productVariant_images | null)[] | null; name: string; - priceOverride: SimpleProductUpdate_productVariantStocksUpdate_productVariant_priceOverride | null; + price: SimpleProductUpdate_productVariantStocksUpdate_productVariant_price | null; product: SimpleProductUpdate_productVariantStocksUpdate_productVariant_product; sku: string; stocks: (SimpleProductUpdate_productVariantStocksUpdate_productVariant_stocks | null)[] | null; @@ -771,4 +830,5 @@ export interface SimpleProductUpdateVariables { deleteStocks: string[]; updateStocks: StockInput[]; weight?: any | null; + visibleInListings?: boolean | null; } diff --git a/src/products/types/VariantCreate.ts b/src/products/types/VariantCreate.ts index 004894e9b..888b46a09 100644 --- a/src/products/types/VariantCreate.ts +++ b/src/products/types/VariantCreate.ts @@ -2,7 +2,7 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { ProductVariantCreateInput, ProductErrorCode } from "./../../types/globalTypes"; +import { ProductVariantCreateInput, ProductErrorCode, WeightUnitsEnum } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: VariantCreate @@ -14,6 +14,18 @@ export interface VariantCreate_productVariantCreate_errors { field: string | null; } +export interface VariantCreate_productVariantCreate_productVariant_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface VariantCreate_productVariantCreate_productVariant_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface VariantCreate_productVariantCreate_productVariant_attributes_attribute_values { __typename: "AttributeValue"; id: string; @@ -55,7 +67,7 @@ export interface VariantCreate_productVariantCreate_productVariant_images { url: string; } -export interface VariantCreate_productVariantCreate_productVariant_priceOverride { +export interface VariantCreate_productVariantCreate_productVariant_price { __typename: "Money"; amount: number; currency: string; @@ -113,18 +125,20 @@ export interface VariantCreate_productVariantCreate_productVariant_stocks { export interface VariantCreate_productVariantCreate_productVariant_weight { __typename: "Weight"; - unit: string; + unit: WeightUnitsEnum; value: number; } export interface VariantCreate_productVariantCreate_productVariant { __typename: "ProductVariant"; id: string; + metadata: (VariantCreate_productVariantCreate_productVariant_metadata | null)[]; + privateMetadata: (VariantCreate_productVariantCreate_productVariant_privateMetadata | null)[]; attributes: VariantCreate_productVariantCreate_productVariant_attributes[]; costPrice: VariantCreate_productVariantCreate_productVariant_costPrice | null; images: (VariantCreate_productVariantCreate_productVariant_images | null)[] | null; name: string; - priceOverride: VariantCreate_productVariantCreate_productVariant_priceOverride | null; + price: VariantCreate_productVariantCreate_productVariant_price | null; product: VariantCreate_productVariantCreate_productVariant_product; sku: string; stocks: (VariantCreate_productVariantCreate_productVariant_stocks | null)[] | null; diff --git a/src/products/types/VariantImageAssign.ts b/src/products/types/VariantImageAssign.ts index ac72c1c4f..1980f0df5 100644 --- a/src/products/types/VariantImageAssign.ts +++ b/src/products/types/VariantImageAssign.ts @@ -2,7 +2,7 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { ProductErrorCode } from "./../../types/globalTypes"; +import { ProductErrorCode, WeightUnitsEnum } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: VariantImageAssign @@ -14,6 +14,18 @@ export interface VariantImageAssign_variantImageAssign_errors { field: string | null; } +export interface VariantImageAssign_variantImageAssign_productVariant_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface VariantImageAssign_variantImageAssign_productVariant_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface VariantImageAssign_variantImageAssign_productVariant_attributes_attribute_values { __typename: "AttributeValue"; id: string; @@ -55,7 +67,7 @@ export interface VariantImageAssign_variantImageAssign_productVariant_images { url: string; } -export interface VariantImageAssign_variantImageAssign_productVariant_priceOverride { +export interface VariantImageAssign_variantImageAssign_productVariant_price { __typename: "Money"; amount: number; currency: string; @@ -113,18 +125,20 @@ export interface VariantImageAssign_variantImageAssign_productVariant_stocks { export interface VariantImageAssign_variantImageAssign_productVariant_weight { __typename: "Weight"; - unit: string; + unit: WeightUnitsEnum; value: number; } export interface VariantImageAssign_variantImageAssign_productVariant { __typename: "ProductVariant"; id: string; + metadata: (VariantImageAssign_variantImageAssign_productVariant_metadata | null)[]; + privateMetadata: (VariantImageAssign_variantImageAssign_productVariant_privateMetadata | null)[]; attributes: VariantImageAssign_variantImageAssign_productVariant_attributes[]; costPrice: VariantImageAssign_variantImageAssign_productVariant_costPrice | null; images: (VariantImageAssign_variantImageAssign_productVariant_images | null)[] | null; name: string; - priceOverride: VariantImageAssign_variantImageAssign_productVariant_priceOverride | null; + price: VariantImageAssign_variantImageAssign_productVariant_price | null; product: VariantImageAssign_variantImageAssign_productVariant_product; sku: string; stocks: (VariantImageAssign_variantImageAssign_productVariant_stocks | null)[] | null; diff --git a/src/products/types/VariantImageUnassign.ts b/src/products/types/VariantImageUnassign.ts index 8d7d870ac..2b3b63ebb 100644 --- a/src/products/types/VariantImageUnassign.ts +++ b/src/products/types/VariantImageUnassign.ts @@ -2,7 +2,7 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { ProductErrorCode } from "./../../types/globalTypes"; +import { ProductErrorCode, WeightUnitsEnum } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: VariantImageUnassign @@ -14,6 +14,18 @@ export interface VariantImageUnassign_variantImageUnassign_errors { field: string | null; } +export interface VariantImageUnassign_variantImageUnassign_productVariant_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface VariantImageUnassign_variantImageUnassign_productVariant_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface VariantImageUnassign_variantImageUnassign_productVariant_attributes_attribute_values { __typename: "AttributeValue"; id: string; @@ -55,7 +67,7 @@ export interface VariantImageUnassign_variantImageUnassign_productVariant_images url: string; } -export interface VariantImageUnassign_variantImageUnassign_productVariant_priceOverride { +export interface VariantImageUnassign_variantImageUnassign_productVariant_price { __typename: "Money"; amount: number; currency: string; @@ -113,18 +125,20 @@ export interface VariantImageUnassign_variantImageUnassign_productVariant_stocks export interface VariantImageUnassign_variantImageUnassign_productVariant_weight { __typename: "Weight"; - unit: string; + unit: WeightUnitsEnum; value: number; } export interface VariantImageUnassign_variantImageUnassign_productVariant { __typename: "ProductVariant"; id: string; + metadata: (VariantImageUnassign_variantImageUnassign_productVariant_metadata | null)[]; + privateMetadata: (VariantImageUnassign_variantImageUnassign_productVariant_privateMetadata | null)[]; attributes: VariantImageUnassign_variantImageUnassign_productVariant_attributes[]; costPrice: VariantImageUnassign_variantImageUnassign_productVariant_costPrice | null; images: (VariantImageUnassign_variantImageUnassign_productVariant_images | null)[] | null; name: string; - priceOverride: VariantImageUnassign_variantImageUnassign_productVariant_priceOverride | null; + price: VariantImageUnassign_variantImageUnassign_productVariant_price | null; product: VariantImageUnassign_variantImageUnassign_productVariant_product; sku: string; stocks: (VariantImageUnassign_variantImageUnassign_productVariant_stocks | null)[] | null; diff --git a/src/products/types/VariantUpdate.ts b/src/products/types/VariantUpdate.ts index b898c17dc..9ebe6a027 100644 --- a/src/products/types/VariantUpdate.ts +++ b/src/products/types/VariantUpdate.ts @@ -2,7 +2,7 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { StockInput, AttributeValueInput, ProductErrorCode, StockErrorCode } from "./../../types/globalTypes"; +import { StockInput, AttributeValueInput, ProductErrorCode, WeightUnitsEnum, StockErrorCode } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: VariantUpdate @@ -14,6 +14,18 @@ export interface VariantUpdate_productVariantUpdate_errors { field: string | null; } +export interface VariantUpdate_productVariantUpdate_productVariant_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface VariantUpdate_productVariantUpdate_productVariant_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface VariantUpdate_productVariantUpdate_productVariant_attributes_attribute_values { __typename: "AttributeValue"; id: string; @@ -55,7 +67,7 @@ export interface VariantUpdate_productVariantUpdate_productVariant_images { url: string; } -export interface VariantUpdate_productVariantUpdate_productVariant_priceOverride { +export interface VariantUpdate_productVariantUpdate_productVariant_price { __typename: "Money"; amount: number; currency: string; @@ -113,18 +125,20 @@ export interface VariantUpdate_productVariantUpdate_productVariant_stocks { export interface VariantUpdate_productVariantUpdate_productVariant_weight { __typename: "Weight"; - unit: string; + unit: WeightUnitsEnum; value: number; } export interface VariantUpdate_productVariantUpdate_productVariant { __typename: "ProductVariant"; id: string; + metadata: (VariantUpdate_productVariantUpdate_productVariant_metadata | null)[]; + privateMetadata: (VariantUpdate_productVariantUpdate_productVariant_privateMetadata | null)[]; attributes: VariantUpdate_productVariantUpdate_productVariant_attributes[]; costPrice: VariantUpdate_productVariantUpdate_productVariant_costPrice | null; images: (VariantUpdate_productVariantUpdate_productVariant_images | null)[] | null; name: string; - priceOverride: VariantUpdate_productVariantUpdate_productVariant_priceOverride | null; + price: VariantUpdate_productVariantUpdate_productVariant_price | null; product: VariantUpdate_productVariantUpdate_productVariant_product; sku: string; stocks: (VariantUpdate_productVariantUpdate_productVariant_stocks | null)[] | null; @@ -145,6 +159,18 @@ export interface VariantUpdate_productVariantStocksUpdate_errors { index: number | null; } +export interface VariantUpdate_productVariantStocksUpdate_productVariant_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface VariantUpdate_productVariantStocksUpdate_productVariant_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface VariantUpdate_productVariantStocksUpdate_productVariant_attributes_attribute_values { __typename: "AttributeValue"; id: string; @@ -186,7 +212,7 @@ export interface VariantUpdate_productVariantStocksUpdate_productVariant_images url: string; } -export interface VariantUpdate_productVariantStocksUpdate_productVariant_priceOverride { +export interface VariantUpdate_productVariantStocksUpdate_productVariant_price { __typename: "Money"; amount: number; currency: string; @@ -244,18 +270,20 @@ export interface VariantUpdate_productVariantStocksUpdate_productVariant_stocks export interface VariantUpdate_productVariantStocksUpdate_productVariant_weight { __typename: "Weight"; - unit: string; + unit: WeightUnitsEnum; value: number; } export interface VariantUpdate_productVariantStocksUpdate_productVariant { __typename: "ProductVariant"; id: string; + metadata: (VariantUpdate_productVariantStocksUpdate_productVariant_metadata | null)[]; + privateMetadata: (VariantUpdate_productVariantStocksUpdate_productVariant_privateMetadata | null)[]; attributes: VariantUpdate_productVariantStocksUpdate_productVariant_attributes[]; costPrice: VariantUpdate_productVariantStocksUpdate_productVariant_costPrice | null; images: (VariantUpdate_productVariantStocksUpdate_productVariant_images | null)[] | null; name: string; - priceOverride: VariantUpdate_productVariantStocksUpdate_productVariant_priceOverride | null; + price: VariantUpdate_productVariantStocksUpdate_productVariant_price | null; product: VariantUpdate_productVariantStocksUpdate_productVariant_product; sku: string; stocks: (VariantUpdate_productVariantStocksUpdate_productVariant_stocks | null)[] | null; @@ -347,7 +375,7 @@ export interface VariantUpdateVariables { id: string; attributes?: (AttributeValueInput | null)[] | null; costPrice?: any | null; - priceOverride?: any | null; + price?: any | null; sku?: string | null; trackInventory: boolean; stocks: StockInput[]; diff --git a/src/products/urls.ts b/src/products/urls.ts index 327737745..859229d35 100644 --- a/src/products/urls.ts +++ b/src/products/urls.ts @@ -1,18 +1,17 @@ import urlJoin from "url-join"; -import { stringifyQs } from "../utils/urls"; - import { ActiveTab, BulkAction, Dialog, Filters, + FiltersAsDictWithMultipleValues, + FiltersWithMultipleValues, Pagination, Sort, - TabActionDialog, - FiltersWithMultipleValues, - FiltersAsDictWithMultipleValues + TabActionDialog } from "../types"; +import { stringifyQs } from "../utils/urls"; const productSection = "/products/"; @@ -24,6 +23,7 @@ export type ProductListUrlDialog = | "publish" | "unpublish" | "delete" + | "export" | TabActionDialog; export enum ProductListUrlFiltersEnum { priceFrom = "priceFrom", diff --git a/src/products/utils/data.ts b/src/products/utils/data.ts index d45704b44..28eab8a18 100644 --- a/src/products/utils/data.ts +++ b/src/products/utils/data.ts @@ -1,7 +1,8 @@ -import { RawDraftContentState } from "draft-js"; - +import { MetadataFormData } from "@saleor/components/Metadata/types"; import { MultiAutocompleteChoiceType } from "@saleor/components/MultiAutocompleteSelectField"; import { SingleAutocompleteChoiceType } from "@saleor/components/SingleAutocompleteSelectField"; +import { ProductVariant } from "@saleor/fragments/types/ProductVariant"; +import { FormsetAtomicData } from "@saleor/hooks/useFormset"; import { maybe } from "@saleor/misc"; import { ProductDetails_product, @@ -10,12 +11,13 @@ import { } from "@saleor/products/types/ProductDetails"; import { SearchProductTypes_search_edges_node_productAttributes } from "@saleor/searches/types/SearchProductTypes"; import { StockInput } from "@saleor/types/globalTypes"; -import { FormsetAtomicData } from "@saleor/hooks/useFormset"; +import { mapMetadataItemToInput } from "@saleor/utils/maps"; +import { RawDraftContentState } from "draft-js"; + import { ProductAttributeInput } from "../components/ProductAttributes"; -import { VariantAttributeInput } from "../components/ProductVariantAttributes"; -import { ProductVariant } from "../types/ProductVariant"; -import { ProductVariantCreateData_product } from "../types/ProductVariantCreateData"; import { ProductStockInput } from "../components/ProductStocks"; +import { VariantAttributeInput } from "../components/ProductVariantAttributes"; +import { ProductVariantCreateData_product } from "../types/ProductVariantCreateData"; export interface Collection { id: string; @@ -168,12 +170,15 @@ export function getChoices(nodes: Node[]): SingleAutocompleteChoiceType[] { ); } -export interface ProductUpdatePageFormData { +export interface ProductUpdatePageFormData extends MetadataFormData { + availableForPurchase: string; basePrice: number; category: string | null; collections: string[]; chargeTaxes: boolean; description: RawDraftContentState; + isAvailableForPurchase: boolean; + isAvailable: boolean; isPublished: boolean; name: string; publicationDate: string; @@ -182,6 +187,7 @@ export interface ProductUpdatePageFormData { sku: string; trackInventory: boolean; weight: string; + visibleInListings: boolean; } export function getProductUpdatePageFormData( @@ -189,7 +195,8 @@ export function getProductUpdatePageFormData( variants: ProductDetails_product_variants[] ): ProductUpdatePageFormData { return { - basePrice: maybe(() => product.basePrice.amount, 0), + availableForPurchase: product?.availableForPurchase, + basePrice: maybe(() => product.variants[0].price.amount, 0), category: maybe(() => product.category.id, ""), chargeTaxes: maybe(() => product.chargeTaxes, false), collections: maybe( @@ -197,8 +204,12 @@ export function getProductUpdatePageFormData( [] ), description: maybe(() => JSON.parse(product.descriptionJson)), + isAvailable: !!product?.isAvailable, + isAvailableForPurchase: !!product?.isAvailableForPurchase, isPublished: maybe(() => product.isPublished, false), + metadata: product?.metadata?.map(mapMetadataItemToInput), name: maybe(() => product.name, ""), + privateMetadata: product?.privateMetadata?.map(mapMetadataItemToInput), publicationDate: maybe(() => product.publicationDate, ""), seoDescription: maybe(() => product.seoDescription, ""), seoTitle: maybe(() => product.seoTitle, ""), @@ -212,6 +223,7 @@ export function getProductUpdatePageFormData( "" ), trackInventory: !!product?.variants[0]?.trackInventory, + visibleInListings: !!product?.visibleInListings, weight: product?.weight?.value.toString() || "" }; } diff --git a/src/products/utils/handlers.ts b/src/products/utils/handlers.ts index 7f0dc5071..cba4b3018 100644 --- a/src/products/utils/handlers.ts +++ b/src/products/utils/handlers.ts @@ -2,6 +2,7 @@ import { FormChange } from "@saleor/hooks/useForm"; import { FormsetChange, FormsetData } from "@saleor/hooks/useFormset"; import { maybe } from "@saleor/misc"; import { toggle } from "@saleor/utils/lists"; + import { ProductAttributeInputData } from "../components/ProductAttributes"; import { getAttributeInputFromProductType, diff --git a/src/products/views/ProductCreate.tsx b/src/products/views/ProductCreate.tsx index 5dfc64225..24d06a9da 100644 --- a/src/products/views/ProductCreate.tsx +++ b/src/products/views/ProductCreate.tsx @@ -1,6 +1,3 @@ -import React from "react"; -import { useIntl } from "react-intl"; - import { WindowTitle } from "@saleor/components/WindowTitle"; import { DEFAULT_INITIAL_SEARCH_DATA } from "@saleor/config"; import useNavigator from "@saleor/hooks/useNavigator"; @@ -9,13 +6,20 @@ import useShop from "@saleor/hooks/useShop"; import useCategorySearch from "@saleor/searches/useCategorySearch"; import useCollectionSearch from "@saleor/searches/useCollectionSearch"; import useProductTypeSearch from "@saleor/searches/useProductTypeSearch"; +import createMetadataCreateHandler from "@saleor/utils/handlers/metadataCreateHandler"; +import { + useMetadataUpdate, + usePrivateMetadataUpdate +} from "@saleor/utils/metadata/updateMetadata"; import { useWarehouseList } from "@saleor/warehouses/queries"; -import { decimal, maybe, weight } from "../../misc"; +import React from "react"; +import { useIntl } from "react-intl"; + +import { decimal, weight } from "../../misc"; import ProductCreatePage, { ProductCreatePageSubmitData } from "../components/ProductCreatePage"; -import { TypedProductCreateMutation } from "../mutations"; -import { ProductCreate } from "../types/ProductCreate"; +import { useProductCreateMutation } from "../mutations"; import { productListUrl, productUrl } from "../urls"; export const ProductCreateView: React.FC = () => { @@ -50,120 +54,116 @@ export const ProductCreateView: React.FC = () => { first: 50 } }); + const [updateMetadata] = useMetadataUpdate({}); + const [updatePrivateMetadata] = usePrivateMetadataUpdate({}); const handleBack = () => navigate(productListUrl()); - const handleSuccess = (data: ProductCreate) => { - if (data.productCreate.errors.length === 0) { - notify({ - text: intl.formatMessage({ - defaultMessage: "Product created" - }) - }); - navigate(productUrl(data.productCreate.product.id)); + const [productCreate, productCreateOpts] = useProductCreateMutation({ + onCompleted: data => { + if (data.productCreate.errors.length === 0) { + notify({ + status: "success", + text: intl.formatMessage({ + defaultMessage: "Product created" + }) + }); + navigate(productUrl(data.productCreate.product.id)); + } } + }); + + const handleCreate = async (formData: ProductCreatePageSubmitData) => { + const result = await productCreate({ + variables: { + attributes: formData.attributes.map(attribute => ({ + id: attribute.id, + values: attribute.value + })), + basePrice: decimal(formData.basePrice), + category: formData.category, + chargeTaxes: formData.chargeTaxes, + collections: formData.collections, + descriptionJson: JSON.stringify(formData.description), + isPublished: formData.isPublished, + name: formData.name, + productType: formData.productType, + publicationDate: + formData.publicationDate !== "" ? formData.publicationDate : null, + seo: { + description: formData.seoDescription, + title: formData.seoTitle + }, + sku: formData.sku, + stocks: formData.stocks.map(stock => ({ + quantity: parseInt(stock.value, 0), + warehouse: stock.id + })), + trackInventory: formData.trackInventory, + weight: weight(formData.weight) + } + }); + + return result.data.productCreate?.product?.id || null; }; + const handleSubmit = createMetadataCreateHandler( + handleCreate, + updateMetadata, + updatePrivateMetadata + ); return ( - - {(productCreate, productCreateOpts) => { - const handleSubmit = (formData: ProductCreatePageSubmitData) => { - productCreate({ - variables: { - attributes: formData.attributes.map(attribute => ({ - id: attribute.id, - values: attribute.value - })), - basePrice: decimal(formData.basePrice), - category: formData.category, - chargeTaxes: formData.chargeTaxes, - collections: formData.collections, - descriptionJson: JSON.stringify(formData.description), - isPublished: formData.isPublished, - name: formData.name, - productType: formData.productType, - publicationDate: - formData.publicationDate !== "" - ? formData.publicationDate - : null, - seo: { - description: formData.seoDescription, - title: formData.seoTitle - }, - sku: formData.sku, - stocks: formData.stocks.map(stock => ({ - quantity: parseInt(stock.value, 0), - warehouse: stock.id - })), - trackInventory: formData.trackInventory, - weight: weight(formData.weight) - } - }); - }; - - return ( - <> - - shop.defaultCurrency)} - categories={maybe( - () => searchCategoryOpts.data.search.edges, - [] - ).map(edge => edge.node)} - collections={maybe( - () => searchCollectionOpts.data.search.edges, - [] - ).map(edge => edge.node)} - disabled={productCreateOpts.loading} - errors={productCreateOpts.data?.productCreate.errors || []} - fetchCategories={searchCategory} - fetchCollections={searchCollection} - fetchProductTypes={searchProductTypes} - header={intl.formatMessage({ - defaultMessage: "New Product", - description: "page header" - })} - productTypes={maybe(() => - searchProductTypesOpts.data.search.edges.map(edge => edge.node) - )} - onBack={handleBack} - onSubmit={handleSubmit} - saveButtonBarState={productCreateOpts.status} - fetchMoreCategories={{ - hasMore: maybe( - () => searchCategoryOpts.data.search.pageInfo.hasNextPage - ), - loading: searchCategoryOpts.loading, - onFetchMore: loadMoreCategories - }} - fetchMoreCollections={{ - hasMore: maybe( - () => searchCollectionOpts.data.search.pageInfo.hasNextPage - ), - loading: searchCollectionOpts.loading, - onFetchMore: loadMoreCollections - }} - fetchMoreProductTypes={{ - hasMore: maybe( - () => searchProductTypesOpts.data.search.pageInfo.hasNextPage - ), - loading: searchProductTypesOpts.loading, - onFetchMore: loadMoreProductTypes - }} - warehouses={ - warehouses.data?.warehouses.edges.map(edge => edge.node) || [] - } - weightUnit={shop?.defaultWeightUnit} - /> - - ); - }} - + <> + + edge.node + )} + collections={(searchCollectionOpts.data?.search.edges || []).map( + edge => edge.node + )} + disabled={productCreateOpts.loading} + errors={productCreateOpts.data?.productCreate.errors || []} + fetchCategories={searchCategory} + fetchCollections={searchCollection} + fetchProductTypes={searchProductTypes} + header={intl.formatMessage({ + defaultMessage: "New Product", + description: "page header" + })} + productTypes={searchProductTypesOpts.data?.search.edges.map( + edge => edge.node + )} + onBack={handleBack} + onSubmit={handleSubmit} + saveButtonBarState={productCreateOpts.status} + fetchMoreCategories={{ + hasMore: searchCategoryOpts.data?.search.pageInfo.hasNextPage, + loading: searchCategoryOpts.loading, + onFetchMore: loadMoreCategories + }} + fetchMoreCollections={{ + hasMore: searchCollectionOpts.data?.search.pageInfo.hasNextPage, + loading: searchCollectionOpts.loading, + onFetchMore: loadMoreCollections + }} + fetchMoreProductTypes={{ + hasMore: searchProductTypesOpts.data?.search.pageInfo.hasNextPage, + loading: searchProductTypesOpts.loading, + onFetchMore: loadMoreProductTypes + }} + warehouses={ + warehouses.data?.warehouses.edges.map(edge => edge.node) || [] + } + weightUnit={shop?.defaultWeightUnit} + /> + ); }; export default ProductCreateView; diff --git a/src/products/views/ProductImage.tsx b/src/products/views/ProductImage.tsx index 48f49cfca..2efe9cbd5 100644 --- a/src/products/views/ProductImage.tsx +++ b/src/products/views/ProductImage.tsx @@ -1,24 +1,23 @@ import DialogContentText from "@material-ui/core/DialogContentText"; +import ActionDialog from "@saleor/components/ActionDialog"; +import NotFoundPage from "@saleor/components/NotFoundPage"; +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import { commonMessages } from "@saleor/intl"; import React from "react"; import { FormattedMessage, useIntl } from "react-intl"; -import ActionDialog from "@saleor/components/ActionDialog"; -import useNavigator from "@saleor/hooks/useNavigator"; -import useNotifier from "@saleor/hooks/useNotifier"; -import NotFoundPage from "@saleor/components/NotFoundPage"; -import { maybe } from "../../misc"; import ProductImagePage from "../components/ProductImagePage"; import { - TypedProductImageDeleteMutation, - TypedProductImageUpdateMutation + useProductImageDeleteMutation, + useProductImageUpdateMutation } from "../mutations"; -import { TypedProductImageQuery } from "../queries"; -import { ProductImageUpdate } from "../types/ProductImageUpdate"; +import { useProductImageQuery } from "../queries"; import { productImageUrl, ProductImageUrlQueryParams, - productUrl, - productListUrl + productListUrl, + productUrl } from "../urls"; interface ProductImageProps { @@ -37,90 +36,84 @@ export const ProductImage: React.FC = ({ const intl = useIntl(); const handleBack = () => navigate(productUrl(productId)); - const handleUpdateSuccess = (data: ProductImageUpdate) => { - if (data.productImageUpdate.errors.length === 0) { - notify({ text: "Saved changes" }); + + const { data, loading } = useProductImageQuery({ + displayLoader: true, + variables: { + imageId, + productId } + }); + + const [updateImage, updateResult] = useProductImageUpdateMutation({ + onCompleted: data => { + if (data.productImageUpdate.errors.length === 0) { + notify({ + status: "success", + text: intl.formatMessage(commonMessages.savedChanges) + }); + } + } + }); + + const [deleteImage, deleteResult] = useProductImageDeleteMutation({ + onCompleted: handleBack + }); + + const product = data?.product; + + if (product === null) { + return navigate(productListUrl())} />; + } + + const handleDelete = () => deleteImage({ variables: { id: imageId } }); + const handleImageClick = (id: string) => () => + navigate(productImageUrl(productId, id)); + const handleUpdate = (formData: { description: string }) => { + updateImage({ + variables: { + alt: formData.description, + id: imageId + } + }); }; + const image = data?.product?.mainImage; + return ( - - {({ data, loading }) => { - const product = data?.product; - - if (product === null) { - return navigate(productListUrl())} />; + <> + + navigate( + productImageUrl(productId, imageId, { + action: "remove" + }) + ) } - - return ( - - {(updateImage, updateResult) => ( - - {(deleteImage, deleteResult) => { - const handleDelete = () => - deleteImage({ variables: { id: imageId } }); - const handleImageClick = (id: string) => () => - navigate(productImageUrl(productId, id)); - const handleUpdate = (formData: { description: string }) => { - updateImage({ - variables: { - alt: formData.description, - id: imageId - } - }); - }; - const image = data && data.product && data.product.mainImage; - - return ( - <> - data.product.name)} - image={image || null} - images={maybe(() => data.product.images)} - onBack={handleBack} - onDelete={() => - navigate( - productImageUrl(productId, imageId, { - action: "remove" - }) - ) - } - onRowClick={handleImageClick} - onSubmit={handleUpdate} - saveButtonBarState={updateResult.status} - /> - - navigate(productImageUrl(productId, imageId), true) - } - onConfirm={handleDelete} - open={params.action === "remove"} - title={intl.formatMessage({ - defaultMessage: "Delete Image", - description: "dialog header" - })} - variant="delete" - confirmButtonState={deleteResult.status} - > - - - - - - ); - }} - - )} - - ); - }} - + onRowClick={handleImageClick} + onSubmit={handleUpdate} + saveButtonBarState={updateResult.status} + /> + navigate(productImageUrl(productId, imageId), true)} + onConfirm={handleDelete} + open={params.action === "remove"} + title={intl.formatMessage({ + defaultMessage: "Delete Image", + description: "dialog header" + })} + variant="delete" + confirmButtonState={deleteResult.status} + > + + + + + ); }; export default ProductImage; diff --git a/src/products/views/ProductList/ProductList.tsx b/src/products/views/ProductList/ProductList.tsx index de9ebe432..e25ca42eb 100644 --- a/src/products/views/ProductList/ProductList.tsx +++ b/src/products/views/ProductList/ProductList.tsx @@ -2,20 +2,19 @@ import Button from "@material-ui/core/Button"; import DialogContentText from "@material-ui/core/DialogContentText"; import IconButton from "@material-ui/core/IconButton"; import DeleteIcon from "@material-ui/icons/Delete"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import ActionDialog from "@saleor/components/ActionDialog"; import DeleteFilterTabDialog from "@saleor/components/DeleteFilterTabDialog"; import SaveFilterTabDialog, { SaveFilterTabDialogFormData } from "@saleor/components/SaveFilterTabDialog"; import { - defaultListSettings, - ProductListColumns, + DEFAULT_INITIAL_PAGINATION_DATA, DEFAULT_INITIAL_SEARCH_DATA, - DEFAULT_INITIAL_PAGINATION_DATA + defaultListSettings, + ProductListColumns } from "@saleor/config"; +import { Task } from "@saleor/containers/BackgroundTasks/types"; +import useBackgroundTask from "@saleor/hooks/useBackgroundTask"; import useBulkActions from "@saleor/hooks/useBulkActions"; import useListSettings from "@saleor/hooks/useListSettings"; import useNavigator from "@saleor/hooks/useNavigator"; @@ -26,47 +25,53 @@ import usePaginator, { import useShop from "@saleor/hooks/useShop"; import { commonMessages } from "@saleor/intl"; import { maybe } from "@saleor/misc"; -import { ProductListVariables } from "@saleor/products/types/ProductList"; -import { ListViews } from "@saleor/types"; -import { getSortUrlVariables } from "@saleor/utils/sort"; -import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; -import createFilterHandlers from "@saleor/utils/handlers/filterHandlers"; -import useCategorySearch from "@saleor/searches/useCategorySearch"; -import useCollectionSearch from "@saleor/searches/useCollectionSearch"; -import useProductTypeSearch from "@saleor/searches/useProductTypeSearch"; +import ProductExportDialog from "@saleor/products/components/ProductExportDialog"; import { getAttributeIdFromColumnValue, isAttributeColumnValue } from "@saleor/products/components/ProductListPage/utils"; +import { ProductListVariables } from "@saleor/products/types/ProductList"; +import useAttributeSearch from "@saleor/searches/useAttributeSearch"; +import useCategorySearch from "@saleor/searches/useCategorySearch"; +import useCollectionSearch from "@saleor/searches/useCollectionSearch"; +import useProductTypeSearch from "@saleor/searches/useProductTypeSearch"; +import { ListViews } from "@saleor/types"; +import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; +import createFilterHandlers from "@saleor/utils/handlers/filterHandlers"; +import { getSortUrlVariables } from "@saleor/utils/sort"; +import { useWarehouseList } from "@saleor/warehouses/queries"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import ProductListPage from "../../components/ProductListPage"; import { - TypedProductBulkDeleteMutation, - TypedProductBulkPublishMutation + useProductBulkDeleteMutation, + useProductBulkPublishMutation, + useProductExport } from "../../mutations"; import { - AvailableInGridAttributesQuery, - TypedProductListQuery, - useInitialProductFilterDataQuery + useAvailableInGridAttributesQuery, + useCountAllProducts, + useInitialProductFilterDataQuery, + useProductListQuery } from "../../queries"; -import { productBulkDelete } from "../../types/productBulkDelete"; -import { productBulkPublish } from "../../types/productBulkPublish"; import { productAddUrl, productListUrl, + ProductListUrlDialog, ProductListUrlQueryParams, ProductListUrlSortField, - productUrl, - ProductListUrlDialog + productUrl } from "../../urls"; import { areFiltersApplied, deleteFilterTab, getActiveFilters, + getFilterOpts, + getFilterQueryParam, getFilterTabs, getFilterVariables, - saveFilterTab, - getFilterOpts, - getFilterQueryParam + saveFilterTab } from "./filters"; import { getSortQueryVariables } from "./sort"; @@ -78,6 +83,7 @@ export const ProductList: React.FC = ({ params }) => { const navigate = useNavigator(); const notify = useNotifier(); const paginate = usePaginator(); + const { queue } = useBackgroundTask(); const shop = useShop(); const { isSelected, listElements, reset, toggle, toggleAll } = useBulkActions( params.ids @@ -111,6 +117,17 @@ export const ProductList: React.FC = ({ params }) => { first: 5 } }); + const searchAttributes = useAttributeSearch({ + variables: { + ...DEFAULT_INITIAL_SEARCH_DATA, + first: 10 + } + }); + const warehouses = useWarehouseList({ + variables: { + first: 100 + } + }); React.useEffect( () => @@ -137,6 +154,29 @@ export const ProductList: React.FC = ({ params }) => { ProductListUrlDialog, ProductListUrlQueryParams >(navigate, productListUrl, params); + const countAllProducts = useCountAllProducts({}); + + const [exportProducts, exportProductsOpts] = useProductExport({ + onCompleted: data => { + if (data.exportProducts.errors.length === 0) { + notify({ + text: intl.formatMessage({ + defaultMessage: + "We are currently exporting your requested CSV. As soon as it is available it will be sent to your email address" + }), + title: intl.formatMessage({ + defaultMessage: "Exporting CSV", + description: "waiting for export to end, header" + }) + }); + queue(Task.EXPORT, { + id: data.exportProducts.exportFile.id + }); + closeModal(); + reset(); + } + } + }); const [ changeFilters, @@ -193,6 +233,53 @@ export const ProductList: React.FC = ({ params }) => { }), [params, settings.rowNumber] ); + const { data, loading, refetch } = useProductListQuery({ + displayLoader: true, + variables: queryVariables + }); + + function filterColumnIds(columns: ProductListColumns[]) { + return columns + .filter(isAttributeColumnValue) + .map(getAttributeIdFromColumnValue); + } + const attributes = useAvailableInGridAttributesQuery({ + variables: { first: 6, ids: filterColumnIds(settings.columns) } + }); + + const [ + productBulkDelete, + productBulkDeleteOpts + ] = useProductBulkDeleteMutation({ + onCompleted: data => { + if (data.productBulkDelete.errors.length === 0) { + closeModal(); + notify({ + status: "success", + text: intl.formatMessage(commonMessages.savedChanges) + }); + reset(); + refetch(); + } + } + }); + + const [ + productBulkPublish, + productBulkPublishOpts + ] = useProductBulkPublishMutation({ + onCompleted: data => { + if (data.productBulkPublish.errors.length === 0) { + closeModal(); + notify({ + status: "success", + text: intl.formatMessage(commonMessages.savedChanges) + }); + reset(); + refetch(); + } + } + }); const filterOpts = getFilterOpts( params, @@ -220,303 +307,259 @@ export const ProductList: React.FC = ({ params }) => { } ); - function filterColumnIds(columns: ProductListColumns[]) { - return columns - .filter(isAttributeColumnValue) - .map(getAttributeIdFromColumnValue); - } + const { loadNextPage, loadPreviousPage, pageInfo } = paginate( + maybe(() => data.products.pageInfo), + paginationState, + params + ); return ( - - {attributes => ( - - {({ data, loading, refetch }) => { - const { loadNextPage, loadPreviousPage, pageInfo } = paginate( - maybe(() => data.products.pageInfo), - paginationState, - params - ); - - const handleBulkDelete = (data: productBulkDelete) => { - if (data.productBulkDelete.errors.length === 0) { - closeModal(); - notify({ - text: intl.formatMessage(commonMessages.savedChanges) - }); - reset(); - refetch(); + <> + attributes.data.availableInGrid.edges.map(edge => edge.node), + [] + )} + currencySymbol={currencySymbol} + currentTab={currentTab} + defaultSettings={defaultListSettings[ListViews.PRODUCT_LIST]} + filterOpts={filterOpts} + gridAttributes={maybe( + () => attributes.data.grid.edges.map(edge => edge.node), + [] + )} + totalGridAttributes={maybe( + () => attributes.data.availableInGrid.totalCount, + 0 + )} + settings={settings} + loading={attributes.loading} + hasMore={maybe( + () => attributes.data.availableInGrid.pageInfo.hasNextPage, + false + )} + onAdd={() => navigate(productAddUrl)} + disabled={loading} + products={maybe(() => data.products.edges.map(edge => edge.node))} + onFetchMore={() => + attributes.loadMore( + (prev, next) => { + if ( + prev.availableInGrid.pageInfo.endCursor === + next.availableInGrid.pageInfo.endCursor + ) { + return prev; } - }; - - const handleBulkPublish = (data: productBulkPublish) => { - if (data.productBulkPublish.errors.length === 0) { - closeModal(); - notify({ - text: intl.formatMessage(commonMessages.savedChanges) - }); - reset(); - refetch(); + return { + ...prev, + availableInGrid: { + ...prev.availableInGrid, + edges: [ + ...prev.availableInGrid.edges, + ...next.availableInGrid.edges + ], + pageInfo: next.availableInGrid.pageInfo + } + }; + }, + { + after: attributes.data.availableInGrid.pageInfo.endCursor + } + ) + } + onNextPage={loadNextPage} + onPreviousPage={loadPreviousPage} + onUpdateListSettings={updateListSettings} + pageInfo={pageInfo} + onRowClick={id => () => navigate(productUrl(id))} + onAll={resetFilters} + toolbar={ + <> + - - - openModal("delete", { - ids: listElements - }) - } - > - - - - } - isChecked={isSelected} - selected={listElements.length} - toggle={toggle} - toggleAll={toggleAll} - onSearchChange={handleSearchChange} - onFilterChange={changeFilters} - onTabSave={() => openModal("save-search")} - onTabDelete={() => openModal("delete-search")} - onTabChange={handleTabChange} - initialSearch={params.query || ""} - tabs={getFilterTabs().map(tab => tab.name)} - /> - - productBulkDelete({ - variables: { ids: params.ids } - }) - } - title={intl.formatMessage({ - defaultMessage: "Delete Products", - description: "dialog header" - })} - variant="delete" - > - - params.ids.length), - displayQuantity: ( - - {maybe(() => params.ids.length)} - - ) - }} - /> - - - - productBulkPublish({ - variables: { - ids: params.ids, - isPublished: true - } - }) - } - title={intl.formatMessage({ - defaultMessage: "Publish Products", - description: "dialog header" - })} - > - - params.ids.length), - displayQuantity: ( - - {maybe(() => params.ids.length)} - - ) - }} - /> - - - - productBulkPublish({ - variables: { - ids: params.ids, - isPublished: false - } - }) - } - title={intl.formatMessage({ - defaultMessage: "Unpublish Products", - description: "dialog header" - })} - > - - params.ids.length), - displayQuantity: ( - - {maybe(() => params.ids.length)} - - ) - }} - /> - - - - tabs[currentTab - 1].name, - "..." - )} - /> - - )} - - )} - - ); - }} - - )} - + > + + + + + openModal("delete", { + ids: listElements + }) + } + > + + + + } + isChecked={isSelected} + selected={listElements.length} + toggle={toggle} + toggleAll={toggleAll} + onSearchChange={handleSearchChange} + onFilterChange={changeFilters} + onTabSave={() => openModal("save-search")} + onTabDelete={() => openModal("delete-search")} + onTabChange={handleTabChange} + initialSearch={params.query || ""} + tabs={getFilterTabs().map(tab => tab.name)} + onExport={() => openModal("export")} + /> + + productBulkDelete({ + variables: { ids: params.ids } + }) + } + title={intl.formatMessage({ + defaultMessage: "Delete Products", + description: "dialog header" + })} + variant="delete" + > + + params.ids.length), + displayQuantity: {maybe(() => params.ids.length)} + }} + /> + + + + productBulkPublish({ + variables: { + ids: params.ids, + isPublished: true + } + }) + } + title={intl.formatMessage({ + defaultMessage: "Publish Products", + description: "dialog header" + })} + > + + params.ids.length), + displayQuantity: {maybe(() => params.ids.length)} + }} + /> + + + + productBulkPublish({ + variables: { + ids: params.ids, + isPublished: false + } + }) + } + title={intl.formatMessage({ + defaultMessage: "Unpublish Products", + description: "dialog header" + })} + > + + params.ids.length), + displayQuantity: {maybe(() => params.ids.length)} + }} + /> + + + edge.node + )} + hasMore={searchAttributes.result.data?.search.pageInfo.hasNextPage} + loading={searchAttributes.result.loading} + onFetch={searchAttributes.search} + onFetchMore={searchAttributes.loadMore} + open={params.action === "export"} + confirmButtonState={exportProductsOpts.status} + errors={exportProductsOpts.data?.exportProducts.errors || []} + productQuantity={{ + all: countAllProducts.data?.products.totalCount, + filter: data?.products.totalCount + }} + selectedProducts={listElements.length} + warehouses={ + warehouses.data?.warehouses.edges.map(edge => edge.node) || [] + } + onClose={closeModal} + onSubmit={data => + exportProducts({ + variables: { + input: { + ...data, + filter, + ids: listElements + } + } + }) + } + /> + + tabs[currentTab - 1].name, "...")} + /> + ); }; export default ProductList; diff --git a/src/products/views/ProductList/filters.test.ts b/src/products/views/ProductList/filters.test.ts index f5960b563..4a55b212a 100644 --- a/src/products/views/ProductList/filters.test.ts +++ b/src/products/views/ProductList/filters.test.ts @@ -1,13 +1,13 @@ -import { createIntl } from "react-intl"; -import { stringify as stringifyQs } from "qs"; - -import { ProductListUrlFilters } from "@saleor/products/urls"; import { createFilterStructure } from "@saleor/products/components/ProductListPage"; +import { ProductListUrlFilters } from "@saleor/products/urls"; +import { StockAvailability } from "@saleor/types/globalTypes"; import { getFilterQueryParams } from "@saleor/utils/filters"; import { getExistingKeys, setFilterOptsStatus } from "@test/filters"; import { config } from "@test/intl"; -import { StockAvailability } from "@saleor/types/globalTypes"; -import { getFilterVariables, getFilterQueryParam } from "./filters"; +import { stringify as stringifyQs } from "qs"; +import { createIntl } from "react-intl"; + +import { getFilterQueryParam, getFilterVariables } from "./filters"; import { productListFilterOpts } from "./fixtures"; describe("Filtering query params", () => { diff --git a/src/products/views/ProductList/filters.ts b/src/products/views/ProductList/filters.ts index 6ec02cd39..44f6701d6 100644 --- a/src/products/views/ProductList/filters.ts +++ b/src/products/views/ProductList/filters.ts @@ -1,22 +1,20 @@ -import isArray from "lodash-es/isArray"; - -import { maybe, findValueInEnum } from "@saleor/misc"; +import { UseSearchResult } from "@saleor/hooks/makeSearch"; +import { findValueInEnum, maybe } from "@saleor/misc"; import { ProductFilterKeys, ProductListFilterOpts, ProductStatus } from "@saleor/products/components/ProductListPage"; -import { UseSearchResult } from "@saleor/hooks/makeSearch"; +import { + InitialProductFilterData_attributes_edges_node, + InitialProductFilterData_categories_edges_node, + InitialProductFilterData_collections_edges_node, + InitialProductFilterData_productTypes_edges_node +} from "@saleor/products/types/InitialProductFilterData"; import { SearchCategories, SearchCategoriesVariables } from "@saleor/searches/types/SearchCategories"; -import { - InitialProductFilterData_categories_edges_node, - InitialProductFilterData_collections_edges_node, - InitialProductFilterData_productTypes_edges_node, - InitialProductFilterData_attributes_edges_node -} from "@saleor/products/types/InitialProductFilterData"; import { SearchCollections, SearchCollectionsVariables @@ -25,6 +23,8 @@ import { SearchProductTypes, SearchProductTypesVariables } from "@saleor/searches/types/SearchProductTypes"; +import isArray from "lodash-es/isArray"; + import { IFilterElement } from "../../../components/Filter"; import { ProductFilterInput, @@ -33,17 +33,18 @@ import { import { createFilterTabUtils, createFilterUtils, + dedupeFilter, getGteLteVariables, getMinMaxQueryParam, - getSingleEnumValueQueryParam, - dedupeFilter, - getMultipleValueQueryParam + getMultipleValueQueryParam, + getSingleEnumValueQueryParam } from "../../../utils/filters"; import { ProductListUrlFilters, + ProductListUrlFiltersAsDictWithMultipleValues, ProductListUrlFiltersEnum, - ProductListUrlQueryParams, - ProductListUrlFiltersWithMultipleValues + ProductListUrlFiltersWithMultipleValues, + ProductListUrlQueryParams } from "../../urls"; export const PRODUCT_FILTERS_KEY = "productFilters"; @@ -295,4 +296,8 @@ export const { export const { areFiltersApplied, getActiveFilters } = createFilterUtils< ProductListUrlQueryParams, ProductListUrlFilters ->(ProductListUrlFiltersEnum); +>({ + ...ProductListUrlFiltersEnum, + ...ProductListUrlFiltersWithMultipleValues, + ...ProductListUrlFiltersAsDictWithMultipleValues +}); diff --git a/src/products/views/ProductList/fixtures.ts b/src/products/views/ProductList/fixtures.ts index 82c5812f5..ad31a116c 100644 --- a/src/products/views/ProductList/fixtures.ts +++ b/src/products/views/ProductList/fixtures.ts @@ -1,11 +1,11 @@ +import { attributes } from "@saleor/attributes/fixtures"; +import { categories } from "@saleor/categories/fixtures"; +import { collections } from "@saleor/collections/fixtures"; +import { fetchMoreProps, searchPageProps } from "@saleor/fixtures"; import { ProductListFilterOpts, ProductStatus } from "@saleor/products/components/ProductListPage"; -import { attributes } from "@saleor/attributes/fixtures"; -import { fetchMoreProps, searchPageProps } from "@saleor/fixtures"; -import { categories } from "@saleor/categories/fixtures"; -import { collections } from "@saleor/collections/fixtures"; import { productTypes } from "@saleor/productTypes/fixtures"; import { StockAvailability } from "@saleor/types/globalTypes"; diff --git a/src/products/views/ProductUpdate/ProductUpdate.tsx b/src/products/views/ProductUpdate/ProductUpdate.tsx index 77423ea21..d3915ceab 100644 --- a/src/products/views/ProductUpdate/ProductUpdate.tsx +++ b/src/products/views/ProductUpdate/ProductUpdate.tsx @@ -1,42 +1,52 @@ +import placeholderImg from "@assets/images/placeholder255x255.png"; import DialogContentText from "@material-ui/core/DialogContentText"; import IconButton from "@material-ui/core/IconButton"; import DeleteIcon from "@material-ui/icons/Delete"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - -import placeholderImg from "@assets/images/placeholder255x255.png"; import ActionDialog from "@saleor/components/ActionDialog"; +import NotFoundPage from "@saleor/components/NotFoundPage"; import { WindowTitle } from "@saleor/components/WindowTitle"; import { DEFAULT_INITIAL_SEARCH_DATA } from "@saleor/config"; import useBulkActions from "@saleor/hooks/useBulkActions"; import useNavigator from "@saleor/hooks/useNavigator"; import useNotifier from "@saleor/hooks/useNotifier"; +import useShop from "@saleor/hooks/useShop"; import { commonMessages } from "@saleor/intl"; +import { + useProductDeleteMutation, + useProductImageCreateMutation, + useProductImageDeleteMutation, + useProductImagesReorder, + useProductSetAvailabilityForPurchase, + useProductUpdateMutation, + useProductVariantBulkDeleteMutation, + useSimpleProductUpdateMutation +} from "@saleor/products/mutations"; import useCategorySearch from "@saleor/searches/useCategorySearch"; import useCollectionSearch from "@saleor/searches/useCollectionSearch"; import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; -import NotFoundPage from "@saleor/components/NotFoundPage"; +import createMetadataUpdateHandler from "@saleor/utils/handlers/metadataUpdateHandler"; +import { + useMetadataUpdate, + usePrivateMetadataUpdate +} from "@saleor/utils/metadata/updateMetadata"; import { useWarehouseList } from "@saleor/warehouses/queries"; -import useShop from "@saleor/hooks/useShop"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { getMutationState, maybe } from "../../../misc"; import ProductUpdatePage from "../../components/ProductUpdatePage"; -import ProductUpdateOperations from "../../containers/ProductUpdateOperations"; -import { TypedProductDetailsQuery } from "../../queries"; -import { - ProductImageCreate, - ProductImageCreateVariables -} from "../../types/ProductImageCreate"; +import { useProductDetails } from "../../queries"; +import { ProductImageCreateVariables } from "../../types/ProductImageCreate"; import { ProductUpdate as ProductUpdateMutationResult } from "../../types/ProductUpdate"; -import { ProductVariantBulkDelete } from "../../types/ProductVariantBulkDelete"; import { productImageUrl, productListUrl, productUrl, + ProductUrlDialog, ProductUrlQueryParams, productVariantAddUrl, - productVariantEditUrl, - ProductUrlDialog, - productVariantCreatorUrl + productVariantCreatorUrl, + productVariantEditUrl } from "../../urls"; import { createImageReorderHandler, @@ -77,6 +87,106 @@ export const ProductUpdate: React.FC = ({ id, params }) => { } }); const shop = useShop(); + const [updateMetadata] = useMetadataUpdate({}); + const [updatePrivateMetadata] = usePrivateMetadataUpdate({}); + + const { data, loading, refetch } = useProductDetails({ + displayLoader: true, + variables: { + id + } + }); + + const handleUpdate = (data: ProductUpdateMutationResult) => { + if (data.productUpdate.errors.length === 0) { + notify({ + status: "success", + text: intl.formatMessage(commonMessages.savedChanges) + }); + } + }; + const [updateProduct, updateProductOpts] = useProductUpdateMutation({ + onCompleted: handleUpdate + }); + const [ + updateSimpleProduct, + updateSimpleProductOpts + ] = useSimpleProductUpdateMutation({ + onCompleted: handleUpdate + }); + + const [ + reorderProductImages, + reorderProductImagesOpts + ] = useProductImagesReorder({}); + + const [deleteProduct, deleteProductOpts] = useProductDeleteMutation({ + onCompleted: () => { + notify({ + status: "success", + text: intl.formatMessage({ + defaultMessage: "Product removed" + }) + }); + navigate(productListUrl()); + } + }); + + const [ + createProductImage, + createProductImageOpts + ] = useProductImageCreateMutation({ + onCompleted: data => { + const imageError = data.productImageCreate.errors.find( + error => error.field === ("image" as keyof ProductImageCreateVariables) + ); + if (imageError) { + notify({ + status: "error", + text: intl.formatMessage(commonMessages.somethingWentWrong) + }); + } + } + }); + + const [deleteProductImage] = useProductImageDeleteMutation({ + onCompleted: () => + notify({ + status: "success", + text: intl.formatMessage(commonMessages.savedChanges) + }) + }); + + const [ + bulkProductVariantDelete, + bulkProductVariantDeleteOpts + ] = useProductVariantBulkDeleteMutation({ + onCompleted: data => { + if (data.productVariantBulkDelete.errors.length === 0) { + closeModal(); + reset(); + refetch(); + } + } + }); + + const [ + setProductAvailability, + productAvailabilityOpts + ] = useProductSetAvailabilityForPurchase({ + onCompleted: data => { + const errors = data?.productSetAvailabilityForPurchase?.errors; + if (errors?.length === 0) { + notify({ + status: "success", + text: intl.formatMessage({ + defaultMessage: "Product availability updated", + description: "snackbar text" + }) + }); + } + } + }); const [openModal, closeModal] = createDialogActionHandlers< ProductUrlDialog, @@ -85,252 +195,177 @@ export const ProductUpdate: React.FC = ({ id, params }) => { const handleBack = () => navigate(productListUrl()); + const product = data?.product; + + if (product === null) { + return ; + } + + const handleVariantAdd = () => navigate(productVariantAddUrl(id)); + + const handleImageDelete = (id: string) => () => + deleteProductImage({ variables: { id } }); + const handleImageEdit = (imageId: string) => () => + navigate(productImageUrl(id, imageId)); + const handleSubmit = createMetadataUpdateHandler( + product, + createUpdateHandler( + product, + variables => updateProduct({ variables }), + variables => updateSimpleProduct({ variables }), + variables => setProductAvailability({ variables }) + ), + variables => updateMetadata({ variables }), + variables => updatePrivateMetadata({ variables }) + ); + const handleImageUpload = createImageUploadHandler(id, variables => + createProductImage({ variables }) + ); + const handleImageReorder = createImageReorderHandler(product, variables => + reorderProductImages({ variables }) + ); + + const disableFormSave = + createProductImageOpts.loading || + deleteProductOpts.loading || + reorderProductImagesOpts.loading || + updateProductOpts.loading || + productAvailabilityOpts.loading || + loading; + + const formTransitionState = getMutationState( + updateProductOpts.called || updateSimpleProductOpts.called, + updateProductOpts.loading || updateSimpleProductOpts.loading, + maybe(() => updateProductOpts.data.productUpdate.errors), + maybe(() => updateSimpleProductOpts.data.productUpdate.errors), + maybe(() => updateSimpleProductOpts.data.productVariantUpdate.errors) + ); + + const categories = maybe( + () => searchCategoriesOpts.data.search.edges, + [] + ).map(edge => edge.node); + const collections = maybe( + () => searchCollectionsOpts.data.search.edges, + [] + ).map(edge => edge.node); + const errors = [ + ...maybe(() => updateProductOpts.data.productUpdate.errors, []), + ...maybe(() => updateSimpleProductOpts.data.productUpdate.errors, []) + ]; + return ( - - {({ data, loading, refetch }) => { - const product = data?.product; - - if (product === null) { - return ; + <> + data.product.name)} /> + data.product.images)} + header={maybe(() => product.name)} + placeholderImage={placeholderImg} + product={product} + warehouses={ + warehouses.data?.warehouses.edges.map(edge => edge.node) || [] } - - const handleDelete = () => { - notify({ - text: intl.formatMessage({ - defaultMessage: "Product removed" - }) - }); - navigate(productListUrl()); - }; - const handleUpdate = (data: ProductUpdateMutationResult) => { - if (data.productUpdate.errors.length === 0) { - notify({ - text: intl.formatMessage(commonMessages.savedChanges) - }); - } - }; - - const handleImageCreate = (data: ProductImageCreate) => { - const imageError = data.productImageCreate.errors.find( - error => - error.field === ("image" as keyof ProductImageCreateVariables) - ); - if (imageError) { - notify({ - text: intl.formatMessage(commonMessages.somethingWentWrong) - }); - } - }; - const handleImageDeleteSuccess = () => - notify({ - text: intl.formatMessage(commonMessages.savedChanges) - }); - const handleVariantAdd = () => navigate(productVariantAddUrl(id)); - - const handleBulkProductVariantDelete = ( - data: ProductVariantBulkDelete - ) => { - if (data.productVariantBulkDelete.errors.length === 0) { - closeModal(); - reset(); - refetch(); - } - }; - - return ( - product.variants)} + onBack={handleBack} + onDelete={() => openModal("remove")} + onImageReorder={handleImageReorder} + onSubmit={handleSubmit} + onVariantAdd={handleVariantAdd} + onVariantsAdd={() => navigate(productVariantCreatorUrl(id))} + onVariantShow={variantId => () => + navigate(productVariantEditUrl(product.id, variantId))} + onImageUpload={handleImageUpload} + onImageEdit={handleImageEdit} + onImageDelete={handleImageDelete} + toolbar={ + + openModal("remove-variants", { + ids: listElements + }) + } > - {({ - bulkProductVariantDelete, - createProductImage, - deleteProduct, - deleteProductImage, - reorderProductImages, - updateProduct, - updateSimpleProduct - }) => { - const handleImageDelete = (id: string) => () => - deleteProductImage.mutate({ id }); - const handleImageEdit = (imageId: string) => () => - navigate(productImageUrl(id, imageId)); - const handleSubmit = createUpdateHandler( - product, - updateProduct.mutate, - updateSimpleProduct.mutate - ); - const handleImageUpload = createImageUploadHandler( - id, - createProductImage.mutate - ); - const handleImageReorder = createImageReorderHandler( - product, - reorderProductImages.mutate - ); - - const disableFormSave = - createProductImage.opts.loading || - deleteProduct.opts.loading || - reorderProductImages.opts.loading || - updateProduct.opts.loading || - loading; - const formTransitionState = getMutationState( - updateProduct.opts.called || updateSimpleProduct.opts.called, - updateProduct.opts.loading || updateSimpleProduct.opts.loading, - maybe(() => updateProduct.opts.data.productUpdate.errors), - maybe(() => updateSimpleProduct.opts.data.productUpdate.errors), - maybe( - () => - updateSimpleProduct.opts.data.productVariantUpdate.errors - ) - ); - - const categories = maybe( - () => searchCategoriesOpts.data.search.edges, - [] - ).map(edge => edge.node); - const collections = maybe( - () => searchCollectionsOpts.data.search.edges, - [] - ).map(edge => edge.node); - const errors = [ - ...maybe( - () => updateProduct.opts.data.productUpdate.errors, - [] - ), - ...maybe( - () => updateSimpleProduct.opts.data.productUpdate.errors, - [] - ) - ]; - - return ( - <> - data.product.name)} /> - data.product.images)} - header={maybe(() => product.name)} - placeholderImage={placeholderImg} - product={product} - warehouses={ - warehouses.data?.warehouses.edges.map( - edge => edge.node - ) || [] - } - variants={maybe(() => product.variants)} - onBack={handleBack} - onDelete={() => openModal("remove")} - onImageReorder={handleImageReorder} - onSubmit={handleSubmit} - onVariantAdd={handleVariantAdd} - onVariantsAdd={() => navigate(productVariantCreatorUrl(id))} - onVariantShow={variantId => () => - navigate(productVariantEditUrl(product.id, variantId))} - onImageUpload={handleImageUpload} - onImageEdit={handleImageEdit} - onImageDelete={handleImageDelete} - toolbar={ - - openModal("remove-variants", { - ids: listElements - }) - } - > - - - } - isChecked={isSelected} - selected={listElements.length} - toggle={toggle} - toggleAll={toggleAll} - fetchMoreCategories={{ - hasMore: maybe( - () => - searchCategoriesOpts.data.search.pageInfo.hasNextPage - ), - loading: searchCategoriesOpts.loading, - onFetchMore: loadMoreCategories - }} - fetchMoreCollections={{ - hasMore: maybe( - () => - searchCollectionsOpts.data.search.pageInfo.hasNextPage - ), - loading: searchCollectionsOpts.loading, - onFetchMore: loadMoreCollections - }} - /> - deleteProduct.mutate({ id })} - variant="delete" - title={intl.formatMessage({ - defaultMessage: "Delete Product", - description: "dialog header" - })} - > - - - - - - bulkProductVariantDelete.mutate({ - ids: params.ids - }) - } - variant="delete" - title={intl.formatMessage({ - defaultMessage: "Delete Product Variants", - description: "dialog header" - })} - > - - params.ids.length), - displayQuantity: ( - {maybe(() => params.ids.length)} - ) - }} - /> - - - - ); + + + } + isChecked={isSelected} + selected={listElements.length} + toggle={toggle} + toggleAll={toggleAll} + fetchMoreCategories={{ + hasMore: maybe( + () => searchCategoriesOpts.data.search.pageInfo.hasNextPage + ), + loading: searchCategoriesOpts.loading, + onFetchMore: loadMoreCategories + }} + fetchMoreCollections={{ + hasMore: maybe( + () => searchCollectionsOpts.data.search.pageInfo.hasNextPage + ), + loading: searchCollectionsOpts.loading, + onFetchMore: loadMoreCollections + }} + /> + deleteProduct({ variables: { id } })} + variant="delete" + title={intl.formatMessage({ + defaultMessage: "Delete Product", + description: "dialog header" + })} + > + + - ); - }} - + /> + + + + bulkProductVariantDelete({ + variables: { + ids: params.ids + } + }) + } + variant="delete" + title={intl.formatMessage({ + defaultMessage: "Delete Product Variants", + description: "dialog header" + })} + > + + params.ids.length), + displayQuantity: {maybe(() => params.ids.length)} + }} + /> + + + ); }; export default ProductUpdate; diff --git a/src/products/views/ProductUpdate/handlers.ts b/src/products/views/ProductUpdate/handlers.ts index 335bbe24b..f1ac03ad9 100644 --- a/src/products/views/ProductUpdate/handlers.ts +++ b/src/products/views/ProductUpdate/handlers.ts @@ -1,20 +1,41 @@ +import { BulkStockErrorFragment } from "@saleor/fragments/types/BulkStockErrorFragment"; +import { ProductErrorFragment } from "@saleor/fragments/types/ProductErrorFragment"; +import { StockErrorFragment } from "@saleor/fragments/types/StockErrorFragment"; import { decimal, weight } from "@saleor/misc"; import { ProductUpdatePageSubmitData } from "@saleor/products/components/ProductUpdatePage"; import { ProductDetails_product } from "@saleor/products/types/ProductDetails"; import { ProductImageCreateVariables } from "@saleor/products/types/ProductImageCreate"; import { ProductImageReorderVariables } from "@saleor/products/types/ProductImageReorder"; -import { ProductUpdateVariables } from "@saleor/products/types/ProductUpdate"; -import { SimpleProductUpdateVariables } from "@saleor/products/types/SimpleProductUpdate"; -import { ReorderEvent } from "@saleor/types"; -import { arrayMove } from "react-sortable-hoc"; +import { + ProductSetAvailabilityForPurchase, + ProductSetAvailabilityForPurchaseVariables +} from "@saleor/products/types/ProductSetAvailabilityForPurchase"; +import { + ProductUpdate, + ProductUpdateVariables +} from "@saleor/products/types/ProductUpdate"; +import { + SimpleProductUpdate, + SimpleProductUpdateVariables +} from "@saleor/products/types/SimpleProductUpdate"; import { mapFormsetStockToStockInput } from "@saleor/products/utils/data"; +import { ReorderEvent } from "@saleor/types"; +import { MutationFetchResult } from "react-apollo"; +import { arrayMove } from "react-sortable-hoc"; export function createUpdateHandler( product: ProductDetails_product, - updateProduct: (variables: ProductUpdateVariables) => void, - updateSimpleProduct: (variables: SimpleProductUpdateVariables) => void + updateProduct: ( + variables: ProductUpdateVariables + ) => Promise>, + updateSimpleProduct: ( + variables: SimpleProductUpdateVariables + ) => Promise>, + setProductAvailability: ( + variables: ProductSetAvailabilityForPurchaseVariables + ) => Promise> ) { - return (data: ProductUpdatePageSubmitData) => { + return async (data: ProductUpdatePageSubmitData) => { const productVariables: ProductUpdateVariables = { attributes: data.attributes.map(attribute => ({ id: attribute.id, @@ -33,13 +54,19 @@ export function createUpdateHandler( seo: { description: data.seoDescription, title: data.seoTitle - } + }, + visibleInListings: data.visibleInListings }; + let errors: Array< + ProductErrorFragment | StockErrorFragment | BulkStockErrorFragment + >; + if (product.productType.hasVariants) { - updateProduct(productVariables); + const result = await updateProduct(productVariables); + errors = result.data.productUpdate.errors; } else { - updateSimpleProduct({ + const result = await updateSimpleProduct({ ...productVariables, addStocks: data.addStocks.map(mapFormsetStockToStockInput), deleteStocks: data.removeStocks, @@ -51,7 +78,40 @@ export function createUpdateHandler( updateStocks: data.updateStocks.map(mapFormsetStockToStockInput), weight: weight(data.weight) }); + errors = [ + ...result.data.productUpdate.errors, + ...result.data.productVariantStocksCreate.errors, + ...result.data.productVariantStocksDelete.errors, + ...result.data.productVariantStocksUpdate.errors, + ...result.data.productVariantUpdate.errors + ]; } + const { isAvailableForPurchase, availableForPurchase } = data; + if ( + isAvailableForPurchase !== product.isAvailableForPurchase || + availableForPurchase !== product.availableForPurchase + ) { + const isAvailable = + availableForPurchase && !isAvailableForPurchase + ? true + : isAvailableForPurchase; + + const availabilityResult = await setProductAvailability({ + isAvailable, + productId: product.id, + startDate: isAvailableForPurchase + ? null + : availableForPurchase !== "" + ? availableForPurchase + : null + }); + errors = [ + ...errors, + ...availabilityResult.data.productSetAvailabilityForPurchase.errors + ]; + } + + return errors; }; } diff --git a/src/products/views/ProductVariant.tsx b/src/products/views/ProductVariant.tsx index bb7b10a22..bce7b327b 100644 --- a/src/products/views/ProductVariant.tsx +++ b/src/products/views/ProductVariant.tsx @@ -1,32 +1,39 @@ -import React, { useEffect, useState } from "react"; -import { useIntl } from "react-intl"; - import placeholderImg from "@assets/images/placeholder255x255.png"; +import NotFoundPage from "@saleor/components/NotFoundPage"; import { WindowTitle } from "@saleor/components/WindowTitle"; import useNavigator from "@saleor/hooks/useNavigator"; import useNotifier from "@saleor/hooks/useNotifier"; -import { commonMessages } from "@saleor/intl"; -import NotFoundPage from "@saleor/components/NotFoundPage"; -import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; -import { useWarehouseList } from "@saleor/warehouses/queries"; import useShop from "@saleor/hooks/useShop"; +import { commonMessages } from "@saleor/intl"; +import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; +import createMetadataUpdateHandler from "@saleor/utils/handlers/metadataUpdateHandler"; +import { + useMetadataUpdate, + usePrivateMetadataUpdate +} from "@saleor/utils/metadata/updateMetadata"; +import { useWarehouseList } from "@saleor/warehouses/queries"; +import React, { useEffect, useState } from "react"; +import { useIntl } from "react-intl"; + import { decimal, weight } from "../../misc"; import ProductVariantDeleteDialog from "../components/ProductVariantDeleteDialog"; import ProductVariantPage, { ProductVariantPageSubmitData } from "../components/ProductVariantPage"; -import ProductVariantOperations from "../containers/ProductVariantOperations"; -import { TypedProductVariantQuery } from "../queries"; import { - VariantUpdate, - VariantUpdate_productVariantUpdate_errors -} from "../types/VariantUpdate"; + useVariantDeleteMutation, + useVariantImageAssignMutation, + useVariantImageUnassignMutation, + useVariantUpdateMutation +} from "../mutations"; +import { useProductVariantQuery } from "../queries"; +import { VariantUpdate_productVariantUpdate_errors } from "../types/VariantUpdate"; import { productUrl, productVariantAddUrl, productVariantEditUrl, - ProductVariantEditUrlQueryParams, - ProductVariantEditUrlDialog + ProductVariantEditUrlDialog, + ProductVariantEditUrlQueryParams } from "../urls"; import { mapFormsetStockToStockInput } from "../utils/data"; @@ -59,6 +66,15 @@ export const ProductVariant: React.FC = ({ } }); + const { data, loading } = useProductVariantQuery({ + displayLoader: true, + variables: { + id: variantId + } + }); + const [updateMetadata] = useMetadataUpdate({}); + const [updatePrivateMetadata] = usePrivateMetadataUpdate({}); + const [openModal] = createDialogActionHandlers< ProductVariantEditUrlDialog, ProductVariantEditUrlQueryParams @@ -70,128 +86,137 @@ export const ProductVariant: React.FC = ({ const handleBack = () => navigate(productUrl(productId)); - return ( - - {({ data, loading }) => { - const variant = data?.productVariant; + const [assignImage, assignImageOpts] = useVariantImageAssignMutation({}); + const [unassignImage, unassignImageOpts] = useVariantImageUnassignMutation( + {} + ); + const [deleteVariant, deleteVariantOpts] = useVariantDeleteMutation({ + onCompleted: () => { + notify({ + status: "success", + text: intl.formatMessage({ + defaultMessage: "Variant removed" + }) + }); + navigate(productUrl(productId)); + } + }); + const [updateVariant, updateVariantOpts] = useVariantUpdateMutation({ + onCompleted: data => { + if (data.productVariantUpdate.errors.length === 0) { + notify({ + status: "success", + text: intl.formatMessage(commonMessages.savedChanges) + }); + } else { + setErrors(data.productVariantUpdate.errors); + } + } + }); - if (variant === null) { - return ; - } + const variant = data?.productVariant; - const handleDelete = () => { - notify({ - text: intl.formatMessage({ - defaultMessage: "Variant removed" - }) - }); - navigate(productUrl(productId)); - }; - const handleUpdate = (data: VariantUpdate) => { - if (data.productVariantUpdate.errors.length === 0) { - notify({ text: intl.formatMessage(commonMessages.savedChanges) }); - } else { - setErrors(data.productVariantUpdate.errors); + if (variant === null) { + return ; + } + + const disableFormSave = + loading || + deleteVariantOpts.loading || + updateVariantOpts.loading || + assignImageOpts.loading || + unassignImageOpts.loading; + + const handleImageSelect = (id: string) => () => { + if (variant) { + if (variant?.images?.map(image => image.id).indexOf(id) !== -1) { + unassignImage({ + variables: { + imageId: id, + variantId: variant.id } - }; + }); + } else { + assignImage({ + variables: { + imageId: id, + variantId: variant.id + } + }); + } + } + }; - return ( - - {({ assignImage, deleteVariant, updateVariant, unassignImage }) => { - const disableFormSave = - loading || - deleteVariant.opts.loading || - updateVariant.opts.loading || - assignImage.opts.loading || - unassignImage.opts.loading; + const handleUpdate = async (data: ProductVariantPageSubmitData) => { + const result = await updateVariant({ + variables: { + addStocks: data.addStocks.map(mapFormsetStockToStockInput), + attributes: data.attributes.map(attribute => ({ + id: attribute.id, + values: [attribute.value] + })), + costPrice: decimal(data.costPrice), + id: variantId, + price: decimal(data.price), + removeStocks: data.removeStocks, + sku: data.sku, + stocks: data.updateStocks.map(mapFormsetStockToStockInput), + trackInventory: data.trackInventory, + weight: weight(data.weight) + } + }); - const handleImageSelect = (id: string) => () => { - if (variant) { - if ( - variant.images && - variant.images.map(image => image.id).indexOf(id) !== -1 - ) { - unassignImage.mutate({ - imageId: id, - variantId: variant.id - }); - } else { - assignImage.mutate({ - imageId: id, - variantId: variant.id - }); - } - } - }; + return [ + ...result.data?.productVariantStocksCreate.errors, + ...result.data?.productVariantStocksDelete.errors, + ...result.data?.productVariantStocksUpdate.errors, + ...result.data?.productVariantUpdate.errors + ]; + }; + const handleSubmit = createMetadataUpdateHandler( + data?.productVariant, + handleUpdate, + variables => updateMetadata({ variables }), + variables => updatePrivateMetadata({ variables }) + ); - return ( - <> - - edge.node - ) || [] - } - onAdd={() => navigate(productVariantAddUrl(productId))} - onBack={handleBack} - onDelete={() => openModal("remove")} - onImageSelect={handleImageSelect} - onSubmit={(data: ProductVariantPageSubmitData) => - updateVariant.mutate({ - addStocks: data.addStocks.map( - mapFormsetStockToStockInput - ), - attributes: data.attributes.map(attribute => ({ - id: attribute.id, - values: [attribute.value] - })), - costPrice: decimal(data.costPrice), - id: variantId, - priceOverride: decimal(data.priceOverride), - removeStocks: data.removeStocks, - sku: data.sku, - stocks: data.updateStocks.map( - mapFormsetStockToStockInput - ), - trackInventory: data.trackInventory, - weight: weight(data.weight) - }) - } - onVariantClick={variantId => { - navigate(productVariantEditUrl(productId, variantId)); - }} - /> - - navigate(productVariantEditUrl(productId, variantId)) - } - onConfirm={() => - deleteVariant.mutate({ - id: variantId - }) - } - open={params.action === "remove"} - name={data?.productVariant?.name} - /> - - ); - }} - - ); - }} - + return ( + <> + + edge.node) || [] + } + onAdd={() => navigate(productVariantAddUrl(productId))} + onBack={handleBack} + onDelete={() => openModal("remove")} + onImageSelect={handleImageSelect} + onSubmit={handleSubmit} + onVariantClick={variantId => { + navigate(productVariantEditUrl(productId, variantId)); + }} + /> + navigate(productVariantEditUrl(productId, variantId))} + onConfirm={() => + deleteVariant({ + variables: { + id: variantId + } + }) + } + open={params.action === "remove"} + name={data?.productVariant?.name} + /> + ); }; export default ProductVariant; diff --git a/src/products/views/ProductVariantCreate.tsx b/src/products/views/ProductVariantCreate.tsx index b1545c2f2..bb52bf67d 100644 --- a/src/products/views/ProductVariantCreate.tsx +++ b/src/products/views/ProductVariantCreate.tsx @@ -1,21 +1,25 @@ -import React from "react"; -import { useIntl } from "react-intl"; - +import NotFoundPage from "@saleor/components/NotFoundPage"; import { WindowTitle } from "@saleor/components/WindowTitle"; import useNavigator from "@saleor/hooks/useNavigator"; import useNotifier from "@saleor/hooks/useNotifier"; import useShop from "@saleor/hooks/useShop"; -import NotFoundPage from "@saleor/components/NotFoundPage"; import { commonMessages } from "@saleor/intl"; +import createMetadataCreateHandler from "@saleor/utils/handlers/metadataCreateHandler"; +import { + useMetadataUpdate, + usePrivateMetadataUpdate +} from "@saleor/utils/metadata/updateMetadata"; import { useWarehouseList } from "@saleor/warehouses/queries"; +import React from "react"; +import { useIntl } from "react-intl"; + import { decimal, weight } from "../../misc"; import ProductVariantCreatePage, { ProductVariantCreatePageSubmitData } from "../components/ProductVariantCreatePage"; -import { TypedVariantCreateMutation } from "../mutations"; -import { TypedProductVariantCreateQuery } from "../queries"; -import { VariantCreate } from "../types/VariantCreate"; -import { productUrl, productVariantEditUrl, productListUrl } from "../urls"; +import { useVariantCreateMutation } from "../mutations"; +import { useProductVariantCreateQuery } from "../queries"; +import { productListUrl, productUrl, productVariantEditUrl } from "../urls"; interface ProductVariantCreateProps { productId: string; @@ -35,101 +39,100 @@ export const ProductVariant: React.FC = ({ } }); - return ( - - {({ data, loading: productLoading }) => { - const product = data?.product; + const { data, loading: productLoading } = useProductVariantCreateQuery({ + displayLoader: true, + variables: { id: productId } + }); - if (product === null) { - return navigate(productListUrl())} />; - } - - const handleCreateSuccess = (data: VariantCreate) => { - if (data.productVariantCreate.errors.length === 0) { - notify({ - text: intl.formatMessage(commonMessages.savedChanges) - }); - navigate( - productVariantEditUrl( - productId, - data.productVariantCreate.productVariant.id - ) - ); - } - }; - - return ( - - {(variantCreate, variantCreateResult) => { - const handleBack = () => navigate(productUrl(productId)); - const handleSubmit = ( - formData: ProductVariantCreatePageSubmitData - ) => - variantCreate({ - variables: { - input: { - attributes: formData.attributes - .filter(attribute => attribute.value !== "") - .map(attribute => ({ - id: attribute.id, - values: [attribute.value] - })), - costPrice: decimal(formData.costPrice), - priceOverride: decimal(formData.priceOverride), - product: productId, - sku: formData.sku, - stocks: formData.stocks.map(stock => ({ - quantity: parseInt(stock.value, 0), - warehouse: stock.id - })), - trackInventory: true, - weight: weight(formData.weight) - } - } - }); - const handleVariantClick = (id: string) => - navigate(productVariantEditUrl(productId, id)); - - const disableForm = productLoading || variantCreateResult.loading; - - return ( - <> - - edge.node - ) || [] - } - weightUnit={shop?.defaultWeightUnit} - /> - - ); - }} - + const [variantCreate, variantCreateResult] = useVariantCreateMutation({ + onCompleted: data => { + if (data.productVariantCreate.errors.length === 0) { + notify({ + status: "success", + text: intl.formatMessage(commonMessages.savedChanges) + }); + navigate( + productVariantEditUrl( + productId, + data.productVariantCreate.productVariant.id + ) ); - }} - + } + } + }); + const [updateMetadata] = useMetadataUpdate({}); + const [updatePrivateMetadata] = usePrivateMetadataUpdate({}); + + const product = data?.product; + + if (product === null) { + return navigate(productListUrl())} />; + } + + const handleBack = () => navigate(productUrl(productId)); + const handleCreate = async (formData: ProductVariantCreatePageSubmitData) => { + const result = await variantCreate({ + variables: { + input: { + attributes: formData.attributes + .filter(attribute => attribute.value !== "") + .map(attribute => ({ + id: attribute.id, + values: [attribute.value] + })), + costPrice: decimal(formData.costPrice), + price: decimal(formData.price), + product: productId, + sku: formData.sku, + stocks: formData.stocks.map(stock => ({ + quantity: parseInt(stock.value, 0), + warehouse: stock.id + })), + trackInventory: true, + weight: weight(formData.weight) + } + } + }); + + return result.data.productVariantCreate?.productVariant?.id || null; + }; + const handleSubmit = createMetadataCreateHandler( + handleCreate, + updateMetadata, + updatePrivateMetadata + ); + const handleVariantClick = (id: string) => + navigate(productVariantEditUrl(productId, id)); + + const disableForm = productLoading || variantCreateResult.loading; + + return ( + <> + + edge.node) || [] + } + weightUnit={shop?.defaultWeightUnit} + /> + ); }; export default ProductVariant; diff --git a/src/products/views/ProductVariantCreator/ProductVariantCreator.tsx b/src/products/views/ProductVariantCreator/ProductVariantCreator.tsx index b6854c310..8ba9a2ca0 100644 --- a/src/products/views/ProductVariantCreator/ProductVariantCreator.tsx +++ b/src/products/views/ProductVariantCreator/ProductVariantCreator.tsx @@ -1,13 +1,13 @@ +import { WindowTitle } from "@saleor/components/WindowTitle"; +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import useShop from "@saleor/hooks/useShop"; +import { useProductVariantBulkCreateMutation } from "@saleor/products/mutations"; +import { useCreateMultipleVariantsData } from "@saleor/products/queries"; +import { productUrl } from "@saleor/products/urls"; import React from "react"; import { useIntl } from "react-intl"; -import { WindowTitle } from "@saleor/components/WindowTitle"; -import { useCreateMultipleVariantsData } from "@saleor/products/queries"; -import { useProductVariantBulkCreateMutation } from "@saleor/products/mutations"; -import useNavigator from "@saleor/hooks/useNavigator"; -import useNotifier from "@saleor/hooks/useNotifier"; -import { productUrl } from "@saleor/products/urls"; -import useShop from "@saleor/hooks/useShop"; import ProductVariantCreatorPage from "../../components/ProductVariantCreatorPage"; interface ProductVariantCreatorProps { @@ -31,6 +31,7 @@ const ProductVariantCreator: React.FC = ({ onCompleted: data => { if (data.productVariantBulkCreate.errors.length === 0) { notify({ + status: "success", text: intl.formatMessage({ defaultMessage: "Successfully created variants", description: "success message" @@ -51,7 +52,7 @@ const ProductVariantCreator: React.FC = ({ })} /> { loadMore: ( @@ -80,27 +78,17 @@ export function TypedQuery( skip={skip} context={{ useBatching: true }} errorPolicy="all" + onError={error => + handleQueryAuthError( + error, + notify, + user.tokenRefresh, + user.logout, + intl + ) + } > {(queryData: QueryResult) => { - if (queryData.error) { - if (queryData.error.graphQLErrors.some(isJwtError)) { - user.logout(); - notify({ - text: intl.formatMessage(commonMessages.sessionExpired) - }); - } else if ( - !queryData.error.graphQLErrors.every( - err => - maybe(() => err.extensions.exception.code) === - "PermissionDenied" - ) - ) { - notify({ - text: intl.formatMessage(commonMessages.somethingWentWrong) - }); - } - } - const loadMore = ( mergeFunc: ( previousResults: TData, @@ -161,12 +149,3 @@ export function TypedQuery( ); }; } - -export const pageInfoFragment = gql` - fragment PageInfoFragment on PageInfo { - endCursor - hasNextPage - hasPreviousPage - startCursor - } -`; diff --git a/src/searches/types/SearchAttributes.ts b/src/searches/types/SearchAttributes.ts new file mode 100644 index 000000000..6446abe56 --- /dev/null +++ b/src/searches/types/SearchAttributes.ts @@ -0,0 +1,42 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL query operation: SearchAttributes +// ==================================================== + +export interface SearchAttributes_search_edges_node { + __typename: "Attribute"; + id: string; + name: string | null; +} + +export interface SearchAttributes_search_edges { + __typename: "AttributeCountableEdge"; + node: SearchAttributes_search_edges_node; +} + +export interface SearchAttributes_search_pageInfo { + __typename: "PageInfo"; + endCursor: string | null; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string | null; +} + +export interface SearchAttributes_search { + __typename: "AttributeCountableConnection"; + edges: SearchAttributes_search_edges[]; + pageInfo: SearchAttributes_search_pageInfo; +} + +export interface SearchAttributes { + search: SearchAttributes_search | null; +} + +export interface SearchAttributesVariables { + after?: string | null; + first: number; + query: string; +} diff --git a/src/searches/useAttributeSearch.ts b/src/searches/useAttributeSearch.ts new file mode 100644 index 000000000..7dc7affac --- /dev/null +++ b/src/searches/useAttributeSearch.ts @@ -0,0 +1,33 @@ +import { pageInfoFragment } from "@saleor/fragments/pageInfo"; +import makeTopLevelSearch from "@saleor/hooks/makeTopLevelSearch"; +import gql from "graphql-tag"; + +import { + SearchAttributes, + SearchAttributesVariables +} from "./types/SearchAttributes"; + +export const searchAttributes = gql` + ${pageInfoFragment} + query SearchAttributes($after: String, $first: Int!, $query: String!) { + search: attributes( + after: $after + first: $first + filter: { search: $query } + ) { + edges { + node { + id + name + } + } + pageInfo { + ...PageInfoFragment + } + } + } +`; + +export default makeTopLevelSearch( + searchAttributes +); diff --git a/src/searches/useCategorySearch.ts b/src/searches/useCategorySearch.ts index c8c9f5438..8c86ddbec 100644 --- a/src/searches/useCategorySearch.ts +++ b/src/searches/useCategorySearch.ts @@ -1,7 +1,7 @@ +import { pageInfoFragment } from "@saleor/fragments/pageInfo"; +import makeTopLevelSearch from "@saleor/hooks/makeTopLevelSearch"; import gql from "graphql-tag"; -import makeTopLevelSearch from "@saleor/hooks/makeTopLevelSearch"; -import { pageInfoFragment } from "@saleor/queries"; import { SearchCategories, SearchCategoriesVariables diff --git a/src/searches/useCollectionSearch.ts b/src/searches/useCollectionSearch.ts index cc58e751f..371033f06 100644 --- a/src/searches/useCollectionSearch.ts +++ b/src/searches/useCollectionSearch.ts @@ -1,7 +1,7 @@ +import { pageInfoFragment } from "@saleor/fragments/pageInfo"; +import makeTopLevelSearch from "@saleor/hooks/makeTopLevelSearch"; import gql from "graphql-tag"; -import makeTopLevelSearch from "@saleor/hooks/makeTopLevelSearch"; -import { pageInfoFragment } from "@saleor/queries"; import { SearchCollections, SearchCollectionsVariables diff --git a/src/searches/useCustomerSearch.ts b/src/searches/useCustomerSearch.ts index a6ac2f0eb..8cfd16229 100644 --- a/src/searches/useCustomerSearch.ts +++ b/src/searches/useCustomerSearch.ts @@ -1,7 +1,7 @@ +import { pageInfoFragment } from "@saleor/fragments/pageInfo"; +import makeTopLevelSearch from "@saleor/hooks/makeTopLevelSearch"; import gql from "graphql-tag"; -import makeTopLevelSearch from "@saleor/hooks/makeTopLevelSearch"; -import { pageInfoFragment } from "@saleor/queries"; import { SearchCustomers, SearchCustomersVariables diff --git a/src/searches/usePageSearch.ts b/src/searches/usePageSearch.ts index ec67fd33e..1027ec2f3 100644 --- a/src/searches/usePageSearch.ts +++ b/src/searches/usePageSearch.ts @@ -1,7 +1,7 @@ +import { pageInfoFragment } from "@saleor/fragments/pageInfo"; +import makeTopLevelSearch from "@saleor/hooks/makeTopLevelSearch"; import gql from "graphql-tag"; -import makeTopLevelSearch from "@saleor/hooks/makeTopLevelSearch"; -import { pageInfoFragment } from "@saleor/queries"; import { SearchPages, SearchPagesVariables } from "./types/SearchPages"; export const searchPages = gql` diff --git a/src/searches/usePermissionGroupSearch.ts b/src/searches/usePermissionGroupSearch.ts index edae98092..9445794a1 100644 --- a/src/searches/usePermissionGroupSearch.ts +++ b/src/searches/usePermissionGroupSearch.ts @@ -1,7 +1,7 @@ +import { pageInfoFragment } from "@saleor/fragments/pageInfo"; +import makeTopLevelSearch from "@saleor/hooks/makeTopLevelSearch"; import gql from "graphql-tag"; -import makeTopLevelSearch from "@saleor/hooks/makeTopLevelSearch"; -import { pageInfoFragment } from "@saleor/queries"; import { SearchPermissionGroups, SearchPermissionGroupsVariables diff --git a/src/searches/useProductSearch.ts b/src/searches/useProductSearch.ts index d98bad835..1da659a51 100644 --- a/src/searches/useProductSearch.ts +++ b/src/searches/useProductSearch.ts @@ -1,7 +1,7 @@ +import { pageInfoFragment } from "@saleor/fragments/pageInfo"; +import makeTopLevelSearch from "@saleor/hooks/makeTopLevelSearch"; import gql from "graphql-tag"; -import makeTopLevelSearch from "@saleor/hooks/makeTopLevelSearch"; -import { pageInfoFragment } from "@saleor/queries"; import { SearchProducts, SearchProductsVariables diff --git a/src/searches/useProductTypeSearch.ts b/src/searches/useProductTypeSearch.ts index 60517f670..e5cad1f89 100644 --- a/src/searches/useProductTypeSearch.ts +++ b/src/searches/useProductTypeSearch.ts @@ -1,7 +1,7 @@ +import { pageInfoFragment } from "@saleor/fragments/pageInfo"; +import makeTopLevelSearch from "@saleor/hooks/makeTopLevelSearch"; import gql from "graphql-tag"; -import makeTopLevelSearch from "@saleor/hooks/makeTopLevelSearch"; -import { pageInfoFragment } from "@saleor/queries"; import { SearchProductTypes, SearchProductTypesVariables diff --git a/src/searches/useServiceAccountSearch.ts b/src/searches/useServiceAccountSearch.ts index 542e550f3..92bd38659 100644 --- a/src/searches/useServiceAccountSearch.ts +++ b/src/searches/useServiceAccountSearch.ts @@ -1,7 +1,7 @@ +import { pageInfoFragment } from "@saleor/fragments/pageInfo"; +import makeTopLevelSearch from "@saleor/hooks/makeTopLevelSearch"; import gql from "graphql-tag"; -import makeTopLevelSearch from "@saleor/hooks/makeTopLevelSearch"; -import { pageInfoFragment } from "@saleor/queries"; import { SearchServiceAccount, SearchServiceAccountVariables diff --git a/src/searches/useStaffMemberSearch.ts b/src/searches/useStaffMemberSearch.ts index 87c007c33..6f0616912 100644 --- a/src/searches/useStaffMemberSearch.ts +++ b/src/searches/useStaffMemberSearch.ts @@ -1,7 +1,7 @@ +import { pageInfoFragment } from "@saleor/fragments/pageInfo"; +import makeTopLevelSearch from "@saleor/hooks/makeTopLevelSearch"; import gql from "graphql-tag"; -import makeTopLevelSearch from "@saleor/hooks/makeTopLevelSearch"; -import { pageInfoFragment } from "@saleor/queries"; import { SearchStaffMembers, SearchStaffMembersVariables diff --git a/src/searches/useWarehouseSearch.ts b/src/searches/useWarehouseSearch.ts index b5b0e6048..d37ab01a6 100644 --- a/src/searches/useWarehouseSearch.ts +++ b/src/searches/useWarehouseSearch.ts @@ -1,7 +1,7 @@ +import { pageInfoFragment } from "@saleor/fragments/pageInfo"; +import makeTopLevelSearch from "@saleor/hooks/makeTopLevelSearch"; import gql from "graphql-tag"; -import makeTopLevelSearch from "@saleor/hooks/makeTopLevelSearch"; -import { pageInfoFragment } from "@saleor/queries"; import { SearchWarehouses, SearchWarehousesVariables diff --git a/src/services/components/ServiceCreatePage/ServiceCreatePage.stories.tsx b/src/services/components/ServiceCreatePage/ServiceCreatePage.stories.tsx deleted file mode 100644 index 3f0dce218..000000000 --- a/src/services/components/ServiceCreatePage/ServiceCreatePage.stories.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import { storiesOf } from "@storybook/react"; -import React from "react"; - -import { permissions } from "@saleor/fixtures"; -import Decorator from "@saleor/storybook/Decorator"; -import { AccountErrorCode } from "@saleor/types/globalTypes"; -import ServiceCreatePage, { ServiceCreatePageProps } from "./ServiceCreatePage"; - -const props: ServiceCreatePageProps = { - disabled: false, - errors: [], - onBack: () => undefined, - onSubmit: () => undefined, - permissions, - saveButtonBarState: "default" -}; -storiesOf("Views / Services / Create service", module) - .addDecorator(Decorator) - .add("default", () => ) - .add("loading", () => ) - .add("form errors", () => ( - ({ - __typename: "AccountError", - code: AccountErrorCode.INVALID, - field - }))} - /> - )); diff --git a/src/services/components/ServiceCreatePage/index.ts b/src/services/components/ServiceCreatePage/index.ts deleted file mode 100644 index c02c29357..000000000 --- a/src/services/components/ServiceCreatePage/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from "./ServiceCreatePage"; -export * from "./ServiceCreatePage"; diff --git a/src/services/components/ServiceDefaultToken/index.ts b/src/services/components/ServiceDefaultToken/index.ts deleted file mode 100644 index 554fd2e80..000000000 --- a/src/services/components/ServiceDefaultToken/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from "./ServiceDefaultToken"; -export * from "./ServiceDefaultToken"; diff --git a/src/services/components/ServiceDeleteDialog/ServiceDeleteDialog.stories.tsx b/src/services/components/ServiceDeleteDialog/ServiceDeleteDialog.stories.tsx deleted file mode 100644 index c43118c72..000000000 --- a/src/services/components/ServiceDeleteDialog/ServiceDeleteDialog.stories.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import { storiesOf } from "@storybook/react"; -import React from "react"; - -import Decorator from "@saleor/storybook/Decorator"; -import ServiceDeleteDialog, { - ServiceDeleteDialogProps -} from "./ServiceDeleteDialog"; - -const props: ServiceDeleteDialogProps = { - confirmButtonState: "default", - name: "Magento Importer", - onClose: () => undefined, - onConfirm: () => undefined, - open: true -}; - -storiesOf("Views / Services / Delete service", module) - .addDecorator(Decorator) - .add("default", () => ); diff --git a/src/services/components/ServiceDeleteDialog/ServiceDeleteDialog.tsx b/src/services/components/ServiceDeleteDialog/ServiceDeleteDialog.tsx deleted file mode 100644 index ec83a9494..000000000 --- a/src/services/components/ServiceDeleteDialog/ServiceDeleteDialog.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import DialogContentText from "@material-ui/core/DialogContentText"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - -import ActionDialog from "@saleor/components/ActionDialog"; -import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; - -export interface ServiceDeleteDialogProps { - confirmButtonState: ConfirmButtonTransitionState; - open: boolean; - name: string; - onClose: () => void; - onConfirm: () => void; -} - -const ServiceDeleteDialog: React.FC = ({ - confirmButtonState, - open, - name, - onClose, - onConfirm -}) => { - const intl = useIntl(); - - return ( - - - {name} - }} - /> - - - ); -}; -ServiceDeleteDialog.displayName = "ServiceDeleteDialog"; -export default ServiceDeleteDialog; diff --git a/src/services/components/ServiceDeleteDialog/index.ts b/src/services/components/ServiceDeleteDialog/index.ts deleted file mode 100644 index b43358431..000000000 --- a/src/services/components/ServiceDeleteDialog/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from "./ServiceDeleteDialog"; -export * from "./ServiceDeleteDialog"; diff --git a/src/services/components/ServiceDetailsPage/ServiceDetailsPage.stories.tsx b/src/services/components/ServiceDetailsPage/ServiceDetailsPage.stories.tsx deleted file mode 100644 index f3f705011..000000000 --- a/src/services/components/ServiceDetailsPage/ServiceDetailsPage.stories.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import { storiesOf } from "@storybook/react"; -import React from "react"; - -import { permissions } from "@saleor/fixtures"; -import Decorator from "@saleor/storybook/Decorator"; -import { AccountErrorCode } from "@saleor/types/globalTypes"; -import { service } from "../../fixtures"; -import ServiceDetailsPage, { - ServiceDetailsPageProps -} from "./ServiceDetailsPage"; - -const props: ServiceDetailsPageProps = { - apiUri: "https://example.com/graphql/", - disabled: false, - errors: [], - onApiUriClick: () => undefined, - onBack: () => undefined, - onDelete: () => undefined, - onSubmit: () => undefined, - onTokenClose: () => undefined, - onTokenCreate: () => undefined, - onTokenDelete: () => undefined, - permissions, - saveButtonBarState: "default", - service, - token: null -}; -storiesOf("Views / Services / Service details", module) - .addDecorator(Decorator) - .add("default", () => ) - .add("loading", () => ( - - )) - .add("form errors", () => ( - ({ - __typename: "AccountError", - code: AccountErrorCode.INVALID, - field - }))} - /> - )) - .add("default token", () => ( - - )); diff --git a/src/services/components/ServiceDetailsPage/index.ts b/src/services/components/ServiceDetailsPage/index.ts deleted file mode 100644 index 9d3e06e0b..000000000 --- a/src/services/components/ServiceDetailsPage/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from "./ServiceDetailsPage"; -export * from "./ServiceDetailsPage"; diff --git a/src/services/components/ServiceInfo/index.ts b/src/services/components/ServiceInfo/index.ts deleted file mode 100644 index 2d3a86c07..000000000 --- a/src/services/components/ServiceInfo/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from "./ServiceInfo"; -export * from "./ServiceInfo"; diff --git a/src/services/components/ServiceList/ServiceList.tsx b/src/services/components/ServiceList/ServiceList.tsx deleted file mode 100644 index 0d1ec61ae..000000000 --- a/src/services/components/ServiceList/ServiceList.tsx +++ /dev/null @@ -1,180 +0,0 @@ -import IconButton from "@material-ui/core/IconButton"; -import { makeStyles } from "@material-ui/core/styles"; -import TableBody from "@material-ui/core/TableBody"; -import TableCell from "@material-ui/core/TableCell"; -import TableFooter from "@material-ui/core/TableFooter"; -import TableHead from "@material-ui/core/TableHead"; -import TableRow from "@material-ui/core/TableRow"; -import Typography from "@material-ui/core/Typography"; -import DeleteIcon from "@material-ui/icons/Delete"; -import EditIcon from "@material-ui/icons/Edit"; -import React from "react"; -import { FormattedMessage } from "react-intl"; - -import ResponsiveTable from "@saleor/components/ResponsiveTable"; -import Skeleton from "@saleor/components/Skeleton"; -import TablePagination from "@saleor/components/TablePagination"; -import { maybe, renderCollection, stopPropagation } from "@saleor/misc"; -import { ListProps, SortPage } from "@saleor/types"; -import { ServiceListUrlSortField } from "@saleor/services/urls"; -import TableCellHeader from "@saleor/components/TableCellHeader"; -import { getArrowDirection } from "@saleor/utils/sort"; -import { ServiceList_serviceAccounts_edges_node } from "../../types/ServiceList"; - -export interface ServiceListProps - extends ListProps, - SortPage { - services: ServiceList_serviceAccounts_edges_node[]; - onRemove: (id: string) => void; -} - -const useStyles = makeStyles( - theme => ({ - [theme.breakpoints.up("lg")]: { - colName: { - "&&": { - width: "auto" - } - } - }, - colAction: { - "&&": { - paddingRight: theme.spacing(1) - }, - textAlign: "right", - width: 140 - }, - colName: { - paddingLeft: 0, - width: 250 - }, - table: { - tableLayout: "fixed" - }, - tableRow: { - cursor: "pointer" - } - }), - { name: "ServiceList" } -); - -const numberOfColumns = 2; - -const ServiceList: React.FC = props => { - const { - settings, - disabled, - onNextPage, - onPreviousPage, - onUpdateListSettings, - onRemove, - onRowClick, - onSort, - pageInfo, - services, - sort - } = props; - - const classes = useStyles(props); - - return ( - - - - onSort(ServiceListUrlSortField.name)} - className={classes.colName} - > - - - - - - - - - - - - {renderCollection( - services, - service => ( - - - - {maybe(() => service.name, )} - - - {maybe(() => - service.isActive ? ( - - ) : ( - - ) - )} - - - - - - - onRemove(service.id)) - : undefined - } - > - - - - - ), - () => ( - - - - - - ) - )} - - - ); -}; -ServiceList.displayName = "ServiceList"; -export default ServiceList; diff --git a/src/services/components/ServiceList/index.ts b/src/services/components/ServiceList/index.ts deleted file mode 100644 index 3cfb6cc3d..000000000 --- a/src/services/components/ServiceList/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from "./ServiceList"; -export * from "./ServiceList"; diff --git a/src/services/components/ServiceListPage/ServiceListPage.stories.tsx b/src/services/components/ServiceListPage/ServiceListPage.stories.tsx deleted file mode 100644 index d3f5d74e1..000000000 --- a/src/services/components/ServiceListPage/ServiceListPage.stories.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import { storiesOf } from "@storybook/react"; -import React from "react"; - -import { - listActionsProps, - pageListProps, - searchPageProps, - tabPageProps, - sortPageProps, - filterPageProps -} from "@saleor/fixtures"; -import ServiceListPage, { - ServiceListPageProps -} from "@saleor/services/components/ServiceListPage"; -import Decorator from "@saleor/storybook/Decorator"; -import { ServiceListUrlSortField } from "@saleor/services/urls"; -import { serviceList } from "../../fixtures"; - -const props: ServiceListPageProps = { - ...listActionsProps, - ...pageListProps.default, - ...searchPageProps, - ...sortPageProps, - ...tabPageProps, - ...filterPageProps, - filterOpts: { - isActive: { - active: false, - value: true - } - }, - onBack: () => undefined, - onRemove: () => undefined, - services: serviceList, - sort: { - ...sortPageProps.sort, - sort: ServiceListUrlSortField.name - } -}; - -storiesOf("Views / Services / Service list", module) - .addDecorator(Decorator) - .add("default", () => ) - .add("loading", () => ( - - )) - .add("no data", () => ); diff --git a/src/services/components/ServiceListPage/ServiceListPage.tsx b/src/services/components/ServiceListPage/ServiceListPage.tsx deleted file mode 100644 index e3c6c2dc7..000000000 --- a/src/services/components/ServiceListPage/ServiceListPage.tsx +++ /dev/null @@ -1,96 +0,0 @@ -import Button from "@material-ui/core/Button"; -import Card from "@material-ui/core/Card"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - -import AppHeader from "@saleor/components/AppHeader"; -import Container from "@saleor/components/Container"; -import PageHeader from "@saleor/components/PageHeader"; -import FilterBar from "@saleor/components/FilterBar"; -import { sectionNames } from "@saleor/intl"; -import { - PageListProps, - TabPageProps, - SortPage, - FilterPageProps -} from "@saleor/types"; -import { ServiceListUrlSortField } from "@saleor/services/urls"; -import { ServiceList_serviceAccounts_edges_node } from "../../types/ServiceList"; -import ServiceList from "../ServiceList"; -import { - ServiceFilterKeys, - ServiceListFilterOpts, - createFilterStructure -} from "./filters"; - -export interface ServiceListPageProps - extends PageListProps, - FilterPageProps, - SortPage, - TabPageProps { - services: ServiceList_serviceAccounts_edges_node[]; - onBack: () => void; - onRemove: (id: string) => void; -} - -const ServiceListPage: React.FC = ({ - currencySymbol, - currentTab, - filterOpts, - initialSearch, - onAdd, - onAll, - onBack, - onFilterChange, - onSearchChange, - onTabChange, - onTabDelete, - onTabSave, - tabs, - ...listProps -}) => { - const intl = useIntl(); - - const structure = createFilterStructure(intl, filterOpts); - - return ( - - - {intl.formatMessage(sectionNames.configuration)} - - - - - - - - - - ); -}; -ServiceListPage.displayName = "ServiceListPage"; -export default ServiceListPage; diff --git a/src/services/components/ServiceListPage/filters.ts b/src/services/components/ServiceListPage/filters.ts deleted file mode 100644 index cf864cf54..000000000 --- a/src/services/components/ServiceListPage/filters.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { defineMessages, IntlShape } from "react-intl"; - -import { FilterOpts } from "@saleor/types"; -import { IFilter } from "@saleor/components/Filter"; -import { createBooleanField } from "@saleor/utils/filters/fields"; -import { commonMessages } from "@saleor/intl"; - -export enum ServiceFilterKeys { - active = "active" -} - -export interface ServiceListFilterOpts { - isActive: FilterOpts; -} - -const messages = defineMessages({ - active: { - defaultMessage: "Active", - description: "service account" - }, - deactivated: { - defaultMessage: "Inactive", - description: "service account" - } -}); - -export function createFilterStructure( - intl: IntlShape, - opts: ServiceListFilterOpts -): IFilter { - return [ - { - ...createBooleanField( - ServiceFilterKeys.active, - intl.formatMessage(commonMessages.status), - opts.isActive.value, - { - negative: intl.formatMessage(messages.deactivated), - positive: intl.formatMessage(messages.active) - } - ), - active: opts.isActive.active - } - ]; -} - -export default messages; diff --git a/src/services/components/ServiceListPage/index.ts b/src/services/components/ServiceListPage/index.ts deleted file mode 100644 index 44625afe2..000000000 --- a/src/services/components/ServiceListPage/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { default } from "./ServiceListPage"; -export * from "./ServiceListPage"; -export * from "./filters"; diff --git a/src/services/components/ServiceTokenCreateDialog/index.ts b/src/services/components/ServiceTokenCreateDialog/index.ts deleted file mode 100644 index f34be97d4..000000000 --- a/src/services/components/ServiceTokenCreateDialog/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from "./ServiceTokenCreateDialog"; -export * from "./ServiceTokenCreateDialog"; diff --git a/src/services/components/ServiceTokenDeleteDialog/index.ts b/src/services/components/ServiceTokenDeleteDialog/index.ts deleted file mode 100644 index 8b3a70a9b..000000000 --- a/src/services/components/ServiceTokenDeleteDialog/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from "./ServiceTokenDeleteDialog"; -export * from "./ServiceTokenDeleteDialog"; diff --git a/src/services/components/ServiceTokens/index.ts b/src/services/components/ServiceTokens/index.ts deleted file mode 100644 index 4ca5caf39..000000000 --- a/src/services/components/ServiceTokens/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from "./ServiceTokens"; -export * from "./ServiceTokens"; diff --git a/src/services/fixtures.ts b/src/services/fixtures.ts deleted file mode 100644 index 814c5d164..000000000 --- a/src/services/fixtures.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { PermissionEnum } from "@saleor/types/globalTypes"; - -import { ServiceDetails_serviceAccount } from "./types/ServiceDetails"; -import { ServiceList_serviceAccounts_edges_node } from "./types/ServiceList"; - -export const serviceList: ServiceList_serviceAccounts_edges_node[] = [ - { - __typename: "ServiceAccount" as "ServiceAccount", - id: "1", - isActive: true, - name: "Slack" - }, - { - __typename: "ServiceAccount" as "ServiceAccount", - id: "2", - isActive: true, - name: "Facebook Market" - }, - { - __typename: "ServiceAccount" as "ServiceAccount", - id: "3", - isActive: false, - name: "Magento Importer" - } -]; - -export const service: ServiceDetails_serviceAccount = { - __typename: "ServiceAccount" as "ServiceAccount", - id: "1", - isActive: true, - name: "Magento Importer", - permissions: [ - { - __typename: "Permission" as "Permission", - code: PermissionEnum.MANAGE_PRODUCTS, - name: "Manage products." - } - ], - tokens: [ - { - __typename: "ServiceAccountToken", - authToken: "AK05", - id: "t1", - name: "default" - } - ] -}; diff --git a/src/services/index.tsx b/src/services/index.tsx deleted file mode 100644 index 7c97a2577..000000000 --- a/src/services/index.tsx +++ /dev/null @@ -1,82 +0,0 @@ -import { parse as parseQs } from "qs"; -import React from "react"; -import { useIntl } from "react-intl"; -import { Route, RouteComponentProps, Switch } from "react-router-dom"; - -import { sectionNames } from "@saleor/intl"; -import { asSortParams } from "@saleor/utils/sort"; -import { WindowTitle } from "../components/WindowTitle"; -import { - serviceAddPath, - serviceListPath, - ServiceListUrlQueryParams, - servicePath, - ServiceUrlQueryParams, - ServiceListUrlSortField -} from "./urls"; -import ServiceCreate from "./views/ServiceCreate"; -import ServiceDetailsComponent from "./views/ServiceDetails"; -import ServiceListComponent from "./views/ServiceList"; - -const ServiceList: React.FC = ({ location }) => { - const qs = parseQs(location.search.substr(1)); - const params: ServiceListUrlQueryParams = asSortParams( - qs, - ServiceListUrlSortField - ); - - return ; -}; - -interface ServiceDetailsProps extends RouteComponentProps<{ id: string }> { - token: string; - onTokenClose: () => void; -} -const ServiceDetails: React.FC = ({ - match, - token, - onTokenClose -}) => { - const qs = parseQs(location.search.substr(1)); - const params: ServiceUrlQueryParams = qs; - - return ( - - ); -}; - -const ServiceSection = () => { - const intl = useIntl(); - const [token, setToken] = React.useState(null); - - return ( - <> - - - - } - /> - ( - setToken(null)} - /> - )} - /> - - - ); -}; - -export default ServiceSection; diff --git a/src/services/mutations.ts b/src/services/mutations.ts deleted file mode 100644 index af9d5db6a..000000000 --- a/src/services/mutations.ts +++ /dev/null @@ -1,103 +0,0 @@ -import gql from "graphql-tag"; - -import { accountErrorFragment } from "@saleor/customers/mutations"; -import { TypedMutation } from "../mutations"; -import { serviceDetailsFragment, serviceFragment } from "./queries"; -import { ServiceCreate, ServiceCreateVariables } from "./types/ServiceCreate"; -import { ServiceDelete, ServiceDeleteVariables } from "./types/ServiceDelete"; -import { - ServiceTokenCreate, - ServiceTokenCreateVariables -} from "./types/ServiceTokenCreate"; -import { - ServiceTokenDelete, - ServiceTokenDeleteVariables -} from "./types/ServiceTokenDelete"; -import { ServiceUpdate, ServiceUpdateVariables } from "./types/ServiceUpdate"; - -const serviceCreateMutation = gql` - ${accountErrorFragment} - ${serviceFragment} - mutation ServiceCreate($input: ServiceAccountInput!) { - serviceAccountCreate(input: $input) { - authToken - errors: accountErrors { - ...AccountErrorFragment - } - serviceAccount { - ...ServiceFragment - } - } - } -`; - -export const ServiceCreateMutation = TypedMutation< - ServiceCreate, - ServiceCreateVariables ->(serviceCreateMutation); - -const serviceDeleteMutation = gql` - ${accountErrorFragment} - mutation ServiceDelete($id: ID!) { - serviceAccountDelete(id: $id) { - errors: accountErrors { - ...AccountErrorFragment - } - } - } -`; -export const ServiceDeleteMutation = TypedMutation< - ServiceDelete, - ServiceDeleteVariables ->(serviceDeleteMutation); - -const serviceUpdateMutation = gql` - ${accountErrorFragment} - ${serviceDetailsFragment} - mutation ServiceUpdate($id: ID!, $input: ServiceAccountInput!) { - serviceAccountUpdate(id: $id, input: $input) { - errors: accountErrors { - ...AccountErrorFragment - } - serviceAccount { - ...ServiceDetailsFragment - } - } - } -`; - -export const ServiceUpdateMutation = TypedMutation< - ServiceUpdate, - ServiceUpdateVariables ->(serviceUpdateMutation); - -const serviceTokenCreate = gql` - ${accountErrorFragment} - mutation ServiceTokenCreate($input: ServiceAccountTokenInput!) { - serviceAccountTokenCreate(input: $input) { - authToken - errors: accountErrors { - ...AccountErrorFragment - } - } - } -`; -export const ServiceTokenCreateMutation = TypedMutation< - ServiceTokenCreate, - ServiceTokenCreateVariables ->(serviceTokenCreate); - -const serviceTokenDelete = gql` - ${accountErrorFragment} - mutation ServiceTokenDelete($id: ID!) { - serviceAccountTokenDelete(id: $id) { - errors: accountErrors { - ...AccountErrorFragment - } - } - } -`; -export const ServiceTokenDeleteMutation = TypedMutation< - ServiceTokenDelete, - ServiceTokenDeleteVariables ->(serviceTokenDelete); diff --git a/src/services/queries.ts b/src/services/queries.ts deleted file mode 100644 index c6e224820..000000000 --- a/src/services/queries.ts +++ /dev/null @@ -1,80 +0,0 @@ -import gql from "graphql-tag"; - -import makeQuery from "@saleor/hooks/makeQuery"; -import { pageInfoFragment, TypedQuery } from "../queries"; -import { - ServiceDetails, - ServiceDetailsVariables -} from "./types/ServiceDetails"; -import { ServiceList, ServiceListVariables } from "./types/ServiceList"; - -export const serviceFragment = gql` - fragment ServiceFragment on ServiceAccount { - id - name - isActive - } -`; - -const serviceList = gql` - ${pageInfoFragment} - ${serviceFragment} - query ServiceList( - $first: Int - $after: String - $last: Int - $before: String - $filter: ServiceAccountFilterInput - $sort: ServiceAccountSortingInput - ) { - serviceAccounts( - first: $first - after: $after - before: $before - last: $last - filter: $filter - sortBy: $sort - ) { - edges { - node { - ...ServiceFragment - } - } - pageInfo { - ...PageInfoFragment - } - } - } -`; -export const useServiceListQuery = makeQuery( - serviceList -); - -export const serviceDetailsFragment = gql` - ${serviceFragment} - fragment ServiceDetailsFragment on ServiceAccount { - ...ServiceFragment - permissions { - code - name - } - tokens { - id - name - authToken - } - } -`; - -const serviceDetails = gql` - ${serviceDetailsFragment} - query ServiceDetails($id: ID!) { - serviceAccount(id: $id) { - ...ServiceDetailsFragment - } - } -`; -export const ServiceDetailsQuery = TypedQuery< - ServiceDetails, - ServiceDetailsVariables ->(serviceDetails); diff --git a/src/services/types/ServiceCreate.ts b/src/services/types/ServiceCreate.ts deleted file mode 100644 index 74b3a0aea..000000000 --- a/src/services/types/ServiceCreate.ts +++ /dev/null @@ -1,37 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -// This file was automatically generated and should not be edited. - -import { ServiceAccountInput, AccountErrorCode } from "./../../types/globalTypes"; - -// ==================================================== -// GraphQL mutation operation: ServiceCreate -// ==================================================== - -export interface ServiceCreate_serviceAccountCreate_errors { - __typename: "AccountError"; - code: AccountErrorCode; - field: string | null; -} - -export interface ServiceCreate_serviceAccountCreate_serviceAccount { - __typename: "ServiceAccount"; - id: string; - name: string | null; - isActive: boolean | null; -} - -export interface ServiceCreate_serviceAccountCreate { - __typename: "ServiceAccountCreate"; - authToken: string | null; - errors: ServiceCreate_serviceAccountCreate_errors[]; - serviceAccount: ServiceCreate_serviceAccountCreate_serviceAccount | null; -} - -export interface ServiceCreate { - serviceAccountCreate: ServiceCreate_serviceAccountCreate | null; -} - -export interface ServiceCreateVariables { - input: ServiceAccountInput; -} diff --git a/src/services/types/ServiceDelete.ts b/src/services/types/ServiceDelete.ts deleted file mode 100644 index a23793c72..000000000 --- a/src/services/types/ServiceDelete.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -// This file was automatically generated and should not be edited. - -import { AccountErrorCode } from "./../../types/globalTypes"; - -// ==================================================== -// GraphQL mutation operation: ServiceDelete -// ==================================================== - -export interface ServiceDelete_serviceAccountDelete_errors { - __typename: "AccountError"; - code: AccountErrorCode; - field: string | null; -} - -export interface ServiceDelete_serviceAccountDelete { - __typename: "ServiceAccountDelete"; - errors: ServiceDelete_serviceAccountDelete_errors[]; -} - -export interface ServiceDelete { - serviceAccountDelete: ServiceDelete_serviceAccountDelete | null; -} - -export interface ServiceDeleteVariables { - id: string; -} diff --git a/src/services/types/ServiceDetails.ts b/src/services/types/ServiceDetails.ts deleted file mode 100644 index 2a0bb4187..000000000 --- a/src/services/types/ServiceDetails.ts +++ /dev/null @@ -1,39 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -// This file was automatically generated and should not be edited. - -import { PermissionEnum } from "./../../types/globalTypes"; - -// ==================================================== -// GraphQL query operation: ServiceDetails -// ==================================================== - -export interface ServiceDetails_serviceAccount_permissions { - __typename: "Permission"; - code: PermissionEnum; - name: string; -} - -export interface ServiceDetails_serviceAccount_tokens { - __typename: "ServiceAccountToken"; - id: string; - name: string | null; - authToken: string | null; -} - -export interface ServiceDetails_serviceAccount { - __typename: "ServiceAccount"; - id: string; - name: string | null; - isActive: boolean | null; - permissions: (ServiceDetails_serviceAccount_permissions | null)[] | null; - tokens: (ServiceDetails_serviceAccount_tokens | null)[] | null; -} - -export interface ServiceDetails { - serviceAccount: ServiceDetails_serviceAccount | null; -} - -export interface ServiceDetailsVariables { - id: string; -} diff --git a/src/services/types/ServiceDetailsFragment.ts b/src/services/types/ServiceDetailsFragment.ts deleted file mode 100644 index b62e25f3a..000000000 --- a/src/services/types/ServiceDetailsFragment.ts +++ /dev/null @@ -1,31 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -// This file was automatically generated and should not be edited. - -import { PermissionEnum } from "./../../types/globalTypes"; - -// ==================================================== -// GraphQL fragment: ServiceDetailsFragment -// ==================================================== - -export interface ServiceDetailsFragment_permissions { - __typename: "Permission"; - code: PermissionEnum; - name: string; -} - -export interface ServiceDetailsFragment_tokens { - __typename: "ServiceAccountToken"; - id: string; - name: string | null; - authToken: string | null; -} - -export interface ServiceDetailsFragment { - __typename: "ServiceAccount"; - id: string; - name: string | null; - isActive: boolean | null; - permissions: (ServiceDetailsFragment_permissions | null)[] | null; - tokens: (ServiceDetailsFragment_tokens | null)[] | null; -} diff --git a/src/services/types/ServiceList.ts b/src/services/types/ServiceList.ts deleted file mode 100644 index c03bf7bea..000000000 --- a/src/services/types/ServiceList.ts +++ /dev/null @@ -1,48 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -// This file was automatically generated and should not be edited. - -import { ServiceAccountFilterInput, ServiceAccountSortingInput } from "./../../types/globalTypes"; - -// ==================================================== -// GraphQL query operation: ServiceList -// ==================================================== - -export interface ServiceList_serviceAccounts_edges_node { - __typename: "ServiceAccount"; - id: string; - name: string | null; - isActive: boolean | null; -} - -export interface ServiceList_serviceAccounts_edges { - __typename: "ServiceAccountCountableEdge"; - node: ServiceList_serviceAccounts_edges_node; -} - -export interface ServiceList_serviceAccounts_pageInfo { - __typename: "PageInfo"; - endCursor: string | null; - hasNextPage: boolean; - hasPreviousPage: boolean; - startCursor: string | null; -} - -export interface ServiceList_serviceAccounts { - __typename: "ServiceAccountCountableConnection"; - edges: ServiceList_serviceAccounts_edges[]; - pageInfo: ServiceList_serviceAccounts_pageInfo; -} - -export interface ServiceList { - serviceAccounts: ServiceList_serviceAccounts | null; -} - -export interface ServiceListVariables { - first?: number | null; - after?: string | null; - last?: number | null; - before?: string | null; - filter?: ServiceAccountFilterInput | null; - sort?: ServiceAccountSortingInput | null; -} diff --git a/src/services/types/ServiceTokenCreate.ts b/src/services/types/ServiceTokenCreate.ts deleted file mode 100644 index 7529a10c4..000000000 --- a/src/services/types/ServiceTokenCreate.ts +++ /dev/null @@ -1,29 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -// This file was automatically generated and should not be edited. - -import { ServiceAccountTokenInput, AccountErrorCode } from "./../../types/globalTypes"; - -// ==================================================== -// GraphQL mutation operation: ServiceTokenCreate -// ==================================================== - -export interface ServiceTokenCreate_serviceAccountTokenCreate_errors { - __typename: "AccountError"; - code: AccountErrorCode; - field: string | null; -} - -export interface ServiceTokenCreate_serviceAccountTokenCreate { - __typename: "ServiceAccountTokenCreate"; - authToken: string | null; - errors: ServiceTokenCreate_serviceAccountTokenCreate_errors[]; -} - -export interface ServiceTokenCreate { - serviceAccountTokenCreate: ServiceTokenCreate_serviceAccountTokenCreate | null; -} - -export interface ServiceTokenCreateVariables { - input: ServiceAccountTokenInput; -} diff --git a/src/services/types/ServiceTokenDelete.ts b/src/services/types/ServiceTokenDelete.ts deleted file mode 100644 index 9cfad5249..000000000 --- a/src/services/types/ServiceTokenDelete.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -// This file was automatically generated and should not be edited. - -import { AccountErrorCode } from "./../../types/globalTypes"; - -// ==================================================== -// GraphQL mutation operation: ServiceTokenDelete -// ==================================================== - -export interface ServiceTokenDelete_serviceAccountTokenDelete_errors { - __typename: "AccountError"; - code: AccountErrorCode; - field: string | null; -} - -export interface ServiceTokenDelete_serviceAccountTokenDelete { - __typename: "ServiceAccountTokenDelete"; - errors: ServiceTokenDelete_serviceAccountTokenDelete_errors[]; -} - -export interface ServiceTokenDelete { - serviceAccountTokenDelete: ServiceTokenDelete_serviceAccountTokenDelete | null; -} - -export interface ServiceTokenDeleteVariables { - id: string; -} diff --git a/src/services/types/ServiceUpdate.ts b/src/services/types/ServiceUpdate.ts deleted file mode 100644 index 17feb8dc6..000000000 --- a/src/services/types/ServiceUpdate.ts +++ /dev/null @@ -1,52 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -// This file was automatically generated and should not be edited. - -import { ServiceAccountInput, AccountErrorCode, PermissionEnum } from "./../../types/globalTypes"; - -// ==================================================== -// GraphQL mutation operation: ServiceUpdate -// ==================================================== - -export interface ServiceUpdate_serviceAccountUpdate_errors { - __typename: "AccountError"; - code: AccountErrorCode; - field: string | null; -} - -export interface ServiceUpdate_serviceAccountUpdate_serviceAccount_permissions { - __typename: "Permission"; - code: PermissionEnum; - name: string; -} - -export interface ServiceUpdate_serviceAccountUpdate_serviceAccount_tokens { - __typename: "ServiceAccountToken"; - id: string; - name: string | null; - authToken: string | null; -} - -export interface ServiceUpdate_serviceAccountUpdate_serviceAccount { - __typename: "ServiceAccount"; - id: string; - name: string | null; - isActive: boolean | null; - permissions: (ServiceUpdate_serviceAccountUpdate_serviceAccount_permissions | null)[] | null; - tokens: (ServiceUpdate_serviceAccountUpdate_serviceAccount_tokens | null)[] | null; -} - -export interface ServiceUpdate_serviceAccountUpdate { - __typename: "ServiceAccountUpdate"; - errors: ServiceUpdate_serviceAccountUpdate_errors[]; - serviceAccount: ServiceUpdate_serviceAccountUpdate_serviceAccount | null; -} - -export interface ServiceUpdate { - serviceAccountUpdate: ServiceUpdate_serviceAccountUpdate | null; -} - -export interface ServiceUpdateVariables { - id: string; - input: ServiceAccountInput; -} diff --git a/src/services/urls.ts b/src/services/urls.ts deleted file mode 100644 index 4f5a29d1d..000000000 --- a/src/services/urls.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { stringify as stringifyQs } from "qs"; -import urlJoin from "url-join"; - -import { - ActiveTab, - Dialog, - Filters, - Pagination, - SingleAction, - TabActionDialog, - Sort -} from "../types"; - -export const serviceSection = "/services/"; - -export const serviceListPath = serviceSection; -export enum ServiceListUrlFiltersEnum { - active = "active", - query = "query" -} -export type ServiceListUrlFilters = Filters; -export type ServiceListUrlDialog = "remove" | TabActionDialog; -export enum ServiceListUrlSortField { - name = "name", - active = "active" -} -export type ServiceListUrlSort = Sort; -export type ServiceListUrlQueryParams = ActiveTab & - Dialog & - Pagination & - ServiceListUrlFilters & - ServiceListUrlSort & - SingleAction; -export const serviceListUrl = (params?: ServiceListUrlQueryParams) => - serviceListPath + "?" + stringifyQs(params); - -export const servicePath = (id: string) => urlJoin(serviceSection, id); -export type ServiceUrlDialog = "create-token" | "remove" | "remove-token"; -export type ServiceUrlQueryParams = Dialog & SingleAction; -export const serviceUrl = (id: string, params?: ServiceUrlQueryParams) => - servicePath(encodeURIComponent(id)) + "?" + stringifyQs(params); - -export const serviceAddPath = urlJoin(serviceSection, "add"); -export const serviceAddUrl = serviceAddPath; diff --git a/src/services/views/ServiceCreate/ServiceCreate.tsx b/src/services/views/ServiceCreate/ServiceCreate.tsx deleted file mode 100644 index efe6e8b7a..000000000 --- a/src/services/views/ServiceCreate/ServiceCreate.tsx +++ /dev/null @@ -1,76 +0,0 @@ -import React from "react"; -import { useIntl } from "react-intl"; - -import { WindowTitle } from "@saleor/components/WindowTitle"; -import useNavigator from "@saleor/hooks/useNavigator"; -import useNotifier from "@saleor/hooks/useNotifier"; -import useShop from "@saleor/hooks/useShop"; -import { commonMessages } from "@saleor/intl"; -import { ServiceCreateMutation } from "@saleor/services/mutations"; -import { ServiceCreate as ServiceCreateData } from "@saleor/services/types/ServiceCreate"; -import ServiceCreatePage, { - ServiceCreatePageFormData -} from "../../components/ServiceCreatePage"; -import { serviceListUrl, serviceUrl } from "../../urls"; - -interface ServiceCreateProps { - setToken: (token: string) => void; -} -export const ServiceCreate: React.FC = ({ setToken }) => { - const navigate = useNavigator(); - const notify = useNotifier(); - const intl = useIntl(); - const shop = useShop(); - - const onSubmit = (data: ServiceCreateData) => { - if (data.serviceAccountCreate.errors.length === 0) { - notify({ - text: intl.formatMessage(commonMessages.savedChanges) - }); - navigate(serviceUrl(data.serviceAccountCreate.serviceAccount.id)); - setToken(data.serviceAccountCreate.authToken); - } - }; - - const handleBack = () => navigate(serviceListUrl()); - - return ( - - {(serviceCreate, serviceCreateOpts) => { - const handleSubmit = (data: ServiceCreatePageFormData) => - serviceCreate({ - variables: { - input: { - isActive: data.isActive, - name: data.name, - permissions: data.hasFullAccess - ? shop.permissions.map(permission => permission.code) - : data.permissions - } - } - }); - - return ( - <> - - - - ); - }} - - ); -}; - -export default ServiceCreate; diff --git a/src/services/views/ServiceCreate/index.ts b/src/services/views/ServiceCreate/index.ts deleted file mode 100644 index a6de9b346..000000000 --- a/src/services/views/ServiceCreate/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from "./ServiceCreate"; -export * from "./ServiceCreate"; diff --git a/src/services/views/ServiceDetails/ServiceDetails.tsx b/src/services/views/ServiceDetails/ServiceDetails.tsx deleted file mode 100644 index 7cbf86008..000000000 --- a/src/services/views/ServiceDetails/ServiceDetails.tsx +++ /dev/null @@ -1,234 +0,0 @@ -import React from "react"; -import { useIntl } from "react-intl"; - -import { WindowTitle } from "@saleor/components/WindowTitle"; -import { API_URI } from "@saleor/config"; -import useNavigator from "@saleor/hooks/useNavigator"; -import useNotifier from "@saleor/hooks/useNotifier"; -import useShop from "@saleor/hooks/useShop"; -import { commonMessages } from "@saleor/intl"; -import { maybe, getStringOrPlaceholder } from "@saleor/misc"; -import ServiceDeleteDialog from "@saleor/services/components/ServiceDeleteDialog"; -import ServiceTokenCreateDialog from "@saleor/services/components/ServiceTokenCreateDialog"; -import ServiceTokenDeleteDialog from "@saleor/services/components/ServiceTokenDeleteDialog"; -import { - ServiceDeleteMutation, - ServiceTokenCreateMutation, - ServiceTokenDeleteMutation, - ServiceUpdateMutation -} from "@saleor/services/mutations"; -import { ServiceDelete } from "@saleor/services/types/ServiceDelete"; -import { ServiceTokenCreate } from "@saleor/services/types/ServiceTokenCreate"; -import { ServiceTokenDelete } from "@saleor/services/types/ServiceTokenDelete"; -import { ServiceUpdate } from "@saleor/services/types/ServiceUpdate"; -import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; -import NotFoundPage from "@saleor/components/NotFoundPage"; -import ServiceDetailsPage, { - ServiceDetailsPageFormData -} from "../../components/ServiceDetailsPage"; -import { ServiceDetailsQuery } from "../../queries"; -import { - serviceListUrl, - serviceUrl, - ServiceUrlDialog, - ServiceUrlQueryParams -} from "../../urls"; - -interface OrderListProps { - id: string; - params: ServiceUrlQueryParams; - token: string; - onTokenClose: () => void; -} - -export const ServiceDetails: React.FC = ({ - id, - params, - token, - onTokenClose -}) => { - const navigate = useNavigator(); - const notify = useNotifier(); - const intl = useIntl(); - const shop = useShop(); - - React.useEffect(() => onTokenClose, []); - - const [openModal, closeModal] = createDialogActionHandlers< - ServiceUrlDialog, - ServiceUrlQueryParams - >(navigate, params => serviceUrl(id, params), params); - - const onServiceUpdate = (data: ServiceUpdate) => { - if (maybe(() => data.serviceAccountUpdate.errors.length === 0)) { - notify({ - text: intl.formatMessage(commonMessages.savedChanges) - }); - } - }; - const onServiceDelete = (data: ServiceDelete) => { - if (data.serviceAccountDelete.errors.length === 0) { - notify({ - text: intl.formatMessage(commonMessages.savedChanges) - }); - navigate(serviceListUrl()); - } - }; - - const handleBack = () => navigate(serviceListUrl()); - - return ( - - {({ data, loading, refetch }) => { - const service = data?.serviceAccount; - - if (service === null) { - return ; - } - - const onTokenCreate = (data: ServiceTokenCreate) => { - if (maybe(() => data.serviceAccountTokenCreate.errors.length === 0)) { - refetch(); - } - }; - const onTokenDelete = (data: ServiceTokenDelete) => { - if (maybe(() => data.serviceAccountTokenDelete.errors.length === 0)) { - notify({ - text: intl.formatMessage(commonMessages.savedChanges) - }); - refetch(); - closeModal(); - } - }; - - return ( - - {(updateService, updateServiceOpts) => ( - - {(deleteService, deleteServiceOpts) => ( - - {(createToken, createTokenOpts) => ( - - {(deleteToken, deleteTokenOpts) => { - const handleSubmit = ( - data: ServiceDetailsPageFormData - ) => - updateService({ - variables: { - id, - input: { - isActive: data.isActive, - name: data.name, - permissions: data.hasFullAccess - ? shop.permissions.map( - permission => permission.code - ) - : data.permissions - } - } - }); - - const handleRemoveConfirm = () => - deleteService({ - variables: { - id - } - }); - - const handleTokenCreate = (name: string) => - createToken({ - variables: { - input: { - name, - serviceAccount: id - } - } - }); - - const handleTokenDelete = () => - deleteToken({ - variables: { - id: params.id - } - }); - - return ( - <> - - open(API_URI, "blank")} - onBack={handleBack} - onDelete={() => openModal("remove")} - onSubmit={handleSubmit} - onTokenClose={onTokenClose} - onTokenCreate={() => openModal("create-token")} - onTokenDelete={id => - openModal("remove-token", { - id - }) - } - permissions={shop?.permissions} - service={data?.serviceAccount} - saveButtonBarState={updateServiceOpts.status} - /> - - - { - const token = data.serviceAccount.tokens.find( - token => token.id === params.id - ); - if (token.name) { - return token.name; - } - - return `**** ${token.authToken}`; - }, "...")} - onClose={closeModal} - onConfirm={handleTokenDelete} - open={params.action === "remove-token"} - /> - - ); - }} - - )} - - )} - - )} - - ); - }} - - ); -}; - -export default ServiceDetails; diff --git a/src/services/views/ServiceDetails/index.ts b/src/services/views/ServiceDetails/index.ts deleted file mode 100644 index f7b2a2d0c..000000000 --- a/src/services/views/ServiceDetails/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from "./ServiceDetails"; -export * from "./ServiceDetails"; diff --git a/src/services/views/ServiceList/ServiceList.tsx b/src/services/views/ServiceList/ServiceList.tsx deleted file mode 100644 index 6c06fde1b..000000000 --- a/src/services/views/ServiceList/ServiceList.tsx +++ /dev/null @@ -1,217 +0,0 @@ -import React from "react"; -import useListSettings from "@saleor/hooks/useListSettings"; -import useNavigator from "@saleor/hooks/useNavigator"; -import useNotifier from "@saleor/hooks/useNotifier"; -import usePaginator, { - createPaginationState -} from "@saleor/hooks/usePaginator"; -import { useIntl } from "react-intl"; - -import DeleteFilterTabDialog from "@saleor/components/DeleteFilterTabDialog"; -import SaveFilterTabDialog, { - SaveFilterTabDialogFormData -} from "@saleor/components/SaveFilterTabDialog"; -import { configurationMenuUrl } from "@saleor/configuration"; -import { commonMessages } from "@saleor/intl"; -import { maybe } from "@saleor/misc"; -import { ServiceDeleteMutation } from "@saleor/services/mutations"; -import { ServiceDelete } from "@saleor/services/types/ServiceDelete"; -import { ListViews } from "@saleor/types"; -import { getSortParams } from "@saleor/utils/sort"; -import createSortHandler from "@saleor/utils/handlers/sortHandler"; -import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; -import useShop from "@saleor/hooks/useShop"; -import createFilterHandlers from "@saleor/utils/handlers/filterHandlers"; -import ServiceDeleteDialog from "../../components/ServiceDeleteDialog"; -import ServiceListPage from "../../components/ServiceListPage"; -import { useServiceListQuery } from "../../queries"; -import { - serviceAddUrl, - serviceListUrl, - ServiceListUrlDialog, - ServiceListUrlQueryParams, - serviceUrl -} from "../../urls"; -import { - areFiltersApplied, - deleteFilterTab, - getActiveFilters, - getFilterTabs, - getFilterQueryParam, - getFilterVariables, - saveFilterTab, - getFilterOpts -} from "./filters"; -import { getSortQueryVariables } from "./sort"; - -interface ServiceListProps { - params: ServiceListUrlQueryParams; -} - -export const ServiceList: React.FC = ({ params }) => { - const navigate = useNavigator(); - const notify = useNotifier(); - const paginate = usePaginator(); - const shop = useShop(); - const { updateListSettings, settings } = useListSettings( - ListViews.STAFF_MEMBERS_LIST - ); - const intl = useIntl(); - - const paginationState = createPaginationState(settings.rowNumber, params); - const queryVariables = React.useMemo( - () => ({ - ...paginationState, - filter: getFilterVariables(params), - sort: getSortQueryVariables(params) - }), - [params] - ); - const { data, loading, refetch } = useServiceListQuery({ - displayLoader: true, - variables: queryVariables - }); - - const tabs = getFilterTabs(); - - const currentTab = - params.activeTab === undefined - ? areFiltersApplied(params) - ? tabs.length + 1 - : 0 - : parseInt(params.activeTab, 0); - - const [ - changeFilters, - resetFilters, - handleSearchChange - ] = createFilterHandlers({ - createUrl: serviceListUrl, - getFilterQueryParam, - navigate, - params - }); - - const [openModal, closeModal] = createDialogActionHandlers< - ServiceListUrlDialog, - ServiceListUrlQueryParams - >(navigate, serviceListUrl, params); - - const handleTabChange = (tab: number) => { - navigate( - serviceListUrl({ - activeTab: tab.toString(), - ...getFilterTabs()[tab - 1].data - }) - ); - }; - - const handleTabDelete = () => { - deleteFilterTab(currentTab); - navigate(serviceListUrl()); - }; - - const handleTabSave = (data: SaveFilterTabDialogFormData) => { - saveFilterTab(data.name, getActiveFilters(params)); - handleTabChange(tabs.length + 1); - }; - - const { loadNextPage, loadPreviousPage, pageInfo } = paginate( - maybe(() => data.serviceAccounts.pageInfo), - paginationState, - params - ); - - const handleCreate = () => navigate(serviceAddUrl); - - const onRemove = (data: ServiceDelete) => { - if (data.serviceAccountDelete.errors.length === 0) { - notify({ - text: intl.formatMessage(commonMessages.savedChanges) - }); - closeModal(); - refetch(); - } - }; - - const handleSort = createSortHandler(navigate, serviceListUrl, params); - const currencySymbol = maybe(() => shop.defaultCurrency, "USD"); - - return ( - - {(deleteService, deleteServiceOpts) => { - const handleRemoveConfirm = () => - deleteService({ - variables: { - id: params.id - } - }); - - return ( - <> - openModal("delete-search")} - onTabSave={() => openModal("save-search")} - tabs={tabs.map(tab => tab.name)} - disabled={loading} - settings={settings} - pageInfo={pageInfo} - services={maybe(() => - data.serviceAccounts.edges.map(edge => edge.node) - )} - sort={getSortParams(params)} - onAdd={handleCreate} - onBack={() => navigate(configurationMenuUrl)} - onNextPage={loadNextPage} - onPreviousPage={loadPreviousPage} - onUpdateListSettings={updateListSettings} - onRowClick={id => () => navigate(serviceUrl(id))} - onRemove={id => - openModal("remove", { - id - }) - } - onSort={handleSort} - /> - - data.serviceAccounts.edges.find( - edge => edge.node.id === params.id - ).node.name, - "..." - )} - onClose={closeModal} - onConfirm={handleRemoveConfirm} - open={params.action === "remove"} - /> - - tabs[currentTab - 1].name, "...")} - /> - - ); - }} - - ); -}; - -export default ServiceList; diff --git a/src/services/views/ServiceList/__snapshots__/filters.test.ts.snap b/src/services/views/ServiceList/__snapshots__/filters.test.ts.snap deleted file mode 100644 index c63a81372..000000000 --- a/src/services/views/ServiceList/__snapshots__/filters.test.ts.snap +++ /dev/null @@ -1,9 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Filtering URL params should not be empty if active filters are present 1`] = ` -Object { - "active": "false", -} -`; - -exports[`Filtering URL params should not be empty if active filters are present 2`] = `"active=false"`; diff --git a/src/services/views/ServiceList/filters.test.ts b/src/services/views/ServiceList/filters.test.ts deleted file mode 100644 index e52fe2de1..000000000 --- a/src/services/views/ServiceList/filters.test.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { createIntl } from "react-intl"; -import { stringify as stringifyQs } from "qs"; - -import { ServiceListUrlFilters } from "@saleor/services/urls"; -import { createFilterStructure } from "@saleor/services/components/ServiceListPage"; -import { getFilterQueryParams } from "@saleor/utils/filters"; -import { getExistingKeys, setFilterOptsStatus } from "@test/filters"; -import { config } from "@test/intl"; -import { getFilterVariables, getFilterQueryParam } from "./filters"; - -describe("Filtering query params", () => { - it("should be empty object if no params given", () => { - const params: ServiceListUrlFilters = {}; - const filterVariables = getFilterVariables(params); - - expect(getExistingKeys(filterVariables)).toHaveLength(0); - }); - - it("should not be empty object if params given", () => { - const params: ServiceListUrlFilters = { - active: false.toString() - }; - const filterVariables = getFilterVariables(params); - - expect(getExistingKeys(filterVariables)).toHaveLength(1); - }); -}); - -describe("Filtering URL params", () => { - const intl = createIntl(config); - - const filters = createFilterStructure(intl, { - isActive: { - active: false, - value: false - } - }); - - it("should be empty if no active filters", () => { - const filterQueryParams = getFilterQueryParams( - filters, - getFilterQueryParam - ); - - expect(getExistingKeys(filterQueryParams)).toHaveLength(0); - }); - - it("should not be empty if active filters are present", () => { - const filterQueryParams = getFilterQueryParams( - setFilterOptsStatus(filters, true), - getFilterQueryParam - ); - - expect(filterQueryParams).toMatchSnapshot(); - expect(stringifyQs(filterQueryParams)).toMatchSnapshot(); - }); -}); diff --git a/src/services/views/ServiceList/filters.ts b/src/services/views/ServiceList/filters.ts deleted file mode 100644 index f8eaddd18..000000000 --- a/src/services/views/ServiceList/filters.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { ServiceAccountFilterInput } from "@saleor/types/globalTypes"; -import { - ServiceListFilterOpts, - ServiceFilterKeys -} from "@saleor/services/components/ServiceListPage/filters"; -import { maybe, parseBoolean } from "@saleor/misc"; -import { IFilterElement } from "@saleor/components/Filter"; -import { - ServiceListUrlFilters, - ServiceListUrlFiltersEnum, - ServiceListUrlQueryParams -} from "../../urls"; -import { - createFilterTabUtils, - createFilterUtils, - getSingleValueQueryParam -} from "../../../utils/filters"; - -export const STAFF_FILTERS_KEY = "staffFilters"; - -export function getFilterOpts( - params: ServiceListUrlFilters -): ServiceListFilterOpts { - return { - isActive: { - active: maybe(() => params.active !== undefined, false), - value: - params.active !== undefined ? parseBoolean(params.active, true) : true - } - }; -} - -export function getFilterVariables( - params: ServiceListUrlFilters -): ServiceAccountFilterInput { - return { - isActive: - params.active !== undefined - ? parseBoolean(params.active, true) - : undefined, - search: params.query - }; -} - -export function getFilterQueryParam( - filter: IFilterElement -): ServiceListUrlFilters { - const { name } = filter; - - switch (name) { - case ServiceFilterKeys.active: - return getSingleValueQueryParam(filter, ServiceListUrlFiltersEnum.active); - } -} - -export const { - deleteFilterTab, - getFilterTabs, - saveFilterTab -} = createFilterTabUtils(STAFF_FILTERS_KEY); - -export const { areFiltersApplied, getActiveFilters } = createFilterUtils< - ServiceListUrlQueryParams, - ServiceListUrlFilters ->(ServiceListUrlFiltersEnum); diff --git a/src/services/views/ServiceList/index.ts b/src/services/views/ServiceList/index.ts deleted file mode 100644 index 3cfb6cc3d..000000000 --- a/src/services/views/ServiceList/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from "./ServiceList"; -export * from "./ServiceList"; diff --git a/src/services/views/ServiceList/sort.ts b/src/services/views/ServiceList/sort.ts deleted file mode 100644 index a4fc01c77..000000000 --- a/src/services/views/ServiceList/sort.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { ServiceListUrlSortField } from "@saleor/services/urls"; -import { ServiceAccountSortField } from "@saleor/types/globalTypes"; -import { createGetSortQueryVariables } from "@saleor/utils/sort"; - -export function getSortQueryField( - sort: ServiceListUrlSortField -): ServiceAccountSortField { - switch (sort) { - case ServiceListUrlSortField.name: - return ServiceAccountSortField.NAME; - default: - return undefined; - } -} - -export const getSortQueryVariables = createGetSortQueryVariables( - getSortQueryField -); diff --git a/src/shipping/components/ShippingWeightUnitForm/ShippingWeightUnitForm.tsx b/src/shipping/components/ShippingWeightUnitForm/ShippingWeightUnitForm.tsx index 2b6e6d25f..4d7dec6c5 100644 --- a/src/shipping/components/ShippingWeightUnitForm/ShippingWeightUnitForm.tsx +++ b/src/shipping/components/ShippingWeightUnitForm/ShippingWeightUnitForm.tsx @@ -2,14 +2,14 @@ import Button from "@material-ui/core/Button"; import Card from "@material-ui/core/Card"; import CardActions from "@material-ui/core/CardActions"; import CardContent from "@material-ui/core/CardContent"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import CardTitle from "@saleor/components/CardTitle"; import Form from "@saleor/components/Form"; import Hr from "@saleor/components/Hr"; import SingleSelectField from "@saleor/components/SingleSelectField"; import { buttonMessages, sectionNames } from "@saleor/intl"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { WeightUnitsEnum } from "../../../types/globalTypes"; export interface FormData { diff --git a/src/shipping/components/ShippingZoneAddWarehouseDialog/ShippingZoneAddWarehouseDialog.tsx b/src/shipping/components/ShippingZoneAddWarehouseDialog/ShippingZoneAddWarehouseDialog.tsx index 4315c31c1..f0fc2b3f6 100644 --- a/src/shipping/components/ShippingZoneAddWarehouseDialog/ShippingZoneAddWarehouseDialog.tsx +++ b/src/shipping/components/ShippingZoneAddWarehouseDialog/ShippingZoneAddWarehouseDialog.tsx @@ -3,28 +3,27 @@ import Dialog from "@material-ui/core/Dialog"; import DialogActions from "@material-ui/core/DialogActions"; import DialogContent from "@material-ui/core/DialogContent"; import DialogTitle from "@material-ui/core/DialogTitle"; -import TextField from "@material-ui/core/TextField"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; import makeStyles from "@material-ui/core/styles/makeStyles"; - +import TextField from "@material-ui/core/TextField"; +import CompanyAddressForm from "@saleor/components/CompanyAddressInput/CompanyAddressForm"; import ConfirmButton, { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; -import { DialogProps } from "@saleor/types"; -import { AddressTypeInput } from "@saleor/customers/types"; -import useModalDialogOpen from "@saleor/hooks/useModalDialogOpen"; -import useModalDialogErrors from "@saleor/hooks/useModalDialogErrors"; -import CompanyAddressForm from "@saleor/components/CompanyAddressInput/CompanyAddressForm"; -import { buttonMessages } from "@saleor/intl"; -import Hr from "@saleor/components/Hr"; import Form from "@saleor/components/Form"; -import useAddressValidation from "@saleor/hooks/useAddressValidation"; -import useStateFromProps from "@saleor/hooks/useStateFromProps"; -import { ShopInfo_shop_countries } from "@saleor/components/Shop/types/ShopInfo"; -import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler"; import FormSpacer from "@saleor/components/FormSpacer"; -import { WarehouseErrorFragment } from "@saleor/warehouses/types/WarehouseErrorFragment"; +import Hr from "@saleor/components/Hr"; +import { ShopInfo_shop_countries } from "@saleor/components/Shop/types/ShopInfo"; +import { AddressTypeInput } from "@saleor/customers/types"; +import { WarehouseErrorFragment } from "@saleor/fragments/types/WarehouseErrorFragment"; +import useAddressValidation from "@saleor/hooks/useAddressValidation"; +import useModalDialogErrors from "@saleor/hooks/useModalDialogErrors"; +import useModalDialogOpen from "@saleor/hooks/useModalDialogOpen"; +import useStateFromProps from "@saleor/hooks/useStateFromProps"; +import { buttonMessages } from "@saleor/intl"; +import { DialogProps } from "@saleor/types"; +import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; export interface ShippingZoneAddWarehouseDialogSubmitData extends AddressTypeInput { diff --git a/src/shipping/components/ShippingZoneCountriesAssignDialog/ShippingZoneCountriesAssignDialog.tsx b/src/shipping/components/ShippingZoneCountriesAssignDialog/ShippingZoneCountriesAssignDialog.tsx index a54823b9b..a5b5f59e5 100644 --- a/src/shipping/components/ShippingZoneCountriesAssignDialog/ShippingZoneCountriesAssignDialog.tsx +++ b/src/shipping/components/ShippingZoneCountriesAssignDialog/ShippingZoneCountriesAssignDialog.tsx @@ -9,10 +9,6 @@ import TableCell from "@material-ui/core/TableCell"; import TableRow from "@material-ui/core/TableRow"; import TextField from "@material-ui/core/TextField"; import Typography from "@material-ui/core/Typography"; -import { filter } from "fuzzaldrin"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import Checkbox from "@saleor/components/Checkbox"; import ConfirmButton, { ConfirmButtonTransitionState @@ -23,6 +19,9 @@ import Hr from "@saleor/components/Hr"; import ResponsiveTable from "@saleor/components/ResponsiveTable"; import { ShopInfo_shop_countries } from "@saleor/components/Shop/types/ShopInfo"; import { buttonMessages } from "@saleor/intl"; +import { filter } from "fuzzaldrin"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; interface FormData { countries: string[]; @@ -61,9 +60,7 @@ const useStyles = makeStyles( }), { name: "ShippingZoneCountriesAssignDialog" } ); -const ShippingZoneCountriesAssignDialog: React.FC< - ShippingZoneCountriesAssignDialogProps -> = props => { +const ShippingZoneCountriesAssignDialog: React.FC = props => { const { confirmButtonState, isDefault, diff --git a/src/shipping/components/ShippingZoneCreatePage/ShippingZoneCreatePage.tsx b/src/shipping/components/ShippingZoneCreatePage/ShippingZoneCreatePage.tsx index 088f69aa1..a357ef81d 100644 --- a/src/shipping/components/ShippingZoneCreatePage/ShippingZoneCreatePage.tsx +++ b/src/shipping/components/ShippingZoneCreatePage/ShippingZoneCreatePage.tsx @@ -1,6 +1,3 @@ -import React from "react"; -import { useIntl } from "react-intl"; - import AppHeader from "@saleor/components/AppHeader"; import CardSpacer from "@saleor/components/CardSpacer"; import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; @@ -10,9 +7,12 @@ import Form from "@saleor/components/Form"; import Grid from "@saleor/components/Grid"; import PageHeader from "@saleor/components/PageHeader"; import SaveButtonBar from "@saleor/components/SaveButtonBar"; +import { CountryFragment } from "@saleor/fragments/types/CountryFragment"; +import { ShippingErrorFragment } from "@saleor/fragments/types/ShippingErrorFragment"; import { sectionNames } from "@saleor/intl"; -import { ShippingErrorFragment } from "@saleor/shipping/types/ShippingErrorFragment"; -import { CountryFragment } from "../../../taxes/types/CountryFragment"; +import React from "react"; +import { useIntl } from "react-intl"; + import ShippingZoneCountriesAssignDialog from "../ShippingZoneCountriesAssignDialog"; import ShippingZoneInfo from "../ShippingZoneInfo"; diff --git a/src/shipping/components/ShippingZoneDetailsPage/ShippingZoneDetailsPage.tsx b/src/shipping/components/ShippingZoneDetailsPage/ShippingZoneDetailsPage.tsx index 84167ace5..31c41233a 100644 --- a/src/shipping/components/ShippingZoneDetailsPage/ShippingZoneDetailsPage.tsx +++ b/src/shipping/components/ShippingZoneDetailsPage/ShippingZoneDetailsPage.tsx @@ -1,6 +1,3 @@ -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import AppHeader from "@saleor/components/AppHeader"; import CardSpacer from "@saleor/components/CardSpacer"; import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; @@ -8,20 +5,23 @@ import Container from "@saleor/components/Container"; import CountryList from "@saleor/components/CountryList"; import Form from "@saleor/components/Form"; import Grid from "@saleor/components/Grid"; +import { MultiAutocompleteChoiceType } from "@saleor/components/MultiAutocompleteSelectField"; import PageHeader from "@saleor/components/PageHeader"; import SaveButtonBar from "@saleor/components/SaveButtonBar"; -import { ShippingErrorFragment } from "@saleor/shipping/types/ShippingErrorFragment"; -import createMultiAutocompleteSelectHandler from "@saleor/utils/handlers/multiAutocompleteSelectChangeHandler"; import { SingleAutocompleteChoiceType } from "@saleor/components/SingleAutocompleteSelectField"; -import useStateFromProps from "@saleor/hooks/useStateFromProps"; -import { MultiAutocompleteChoiceType } from "@saleor/components/MultiAutocompleteSelectField"; -import { getStringOrPlaceholder } from "../../../misc"; -import { FetchMoreProps, SearchProps } from "../../../types"; -import { ShippingMethodTypeEnum } from "../../../types/globalTypes"; +import { ShippingErrorFragment } from "@saleor/fragments/types/ShippingErrorFragment"; import { ShippingZoneDetailsFragment, ShippingZoneDetailsFragment_warehouses -} from "../../types/ShippingZoneDetailsFragment"; +} from "@saleor/fragments/types/ShippingZoneDetailsFragment"; +import useStateFromProps from "@saleor/hooks/useStateFromProps"; +import createMultiAutocompleteSelectHandler from "@saleor/utils/handlers/multiAutocompleteSelectChangeHandler"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + +import { getStringOrPlaceholder } from "../../../misc"; +import { FetchMoreProps, SearchProps } from "../../../types"; +import { ShippingMethodTypeEnum } from "../../../types/globalTypes"; import ShippingZoneInfo from "../ShippingZoneInfo"; import ShippingZoneRates from "../ShippingZoneRates"; import ShippingZoneWarehouses from "../ShippingZoneWarehouses"; diff --git a/src/shipping/components/ShippingZoneInfo/ShippingZoneInfo.tsx b/src/shipping/components/ShippingZoneInfo/ShippingZoneInfo.tsx index 6aeacf402..ffca78e2a 100644 --- a/src/shipping/components/ShippingZoneInfo/ShippingZoneInfo.tsx +++ b/src/shipping/components/ShippingZoneInfo/ShippingZoneInfo.tsx @@ -1,14 +1,13 @@ import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; import TextField from "@material-ui/core/TextField"; -import React from "react"; -import { useIntl } from "react-intl"; - import CardTitle from "@saleor/components/CardTitle"; +import { ShippingErrorFragment } from "@saleor/fragments/types/ShippingErrorFragment"; import { commonMessages } from "@saleor/intl"; import { getFormErrors } from "@saleor/utils/errors"; import getShippingErrorMessage from "@saleor/utils/errors/shipping"; -import { ShippingErrorFragment } from "@saleor/shipping/types/ShippingErrorFragment"; +import React from "react"; +import { useIntl } from "react-intl"; export interface ShippingZoneInfoProps { data: Record<"name", string>; diff --git a/src/shipping/components/ShippingZoneRateDialog/ShippingZoneRateDialog.tsx b/src/shipping/components/ShippingZoneRateDialog/ShippingZoneRateDialog.tsx index 5db9aaed9..904cb2117 100644 --- a/src/shipping/components/ShippingZoneRateDialog/ShippingZoneRateDialog.tsx +++ b/src/shipping/components/ShippingZoneRateDialog/ShippingZoneRateDialog.tsx @@ -6,9 +6,6 @@ import DialogTitle from "@material-ui/core/DialogTitle"; import { makeStyles } from "@material-ui/core/styles"; import TextField from "@material-ui/core/TextField"; import Typography from "@material-ui/core/Typography"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import ConfirmButton, { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; @@ -17,14 +14,17 @@ import Form from "@saleor/components/Form"; import FormSpacer from "@saleor/components/FormSpacer"; import Hr from "@saleor/components/Hr"; import Skeleton from "@saleor/components/Skeleton"; +import { ShippingErrorFragment } from "@saleor/fragments/types/ShippingErrorFragment"; +import { ShippingZoneDetailsFragment_shippingMethods } from "@saleor/fragments/types/ShippingZoneDetailsFragment"; +import useModalDialogErrors from "@saleor/hooks/useModalDialogErrors"; import { buttonMessages } from "@saleor/intl"; import { getFormErrors } from "@saleor/utils/errors"; -import useModalDialogErrors from "@saleor/hooks/useModalDialogErrors"; import getShippingErrorMessage from "@saleor/utils/errors/shipping"; -import { ShippingErrorFragment } from "@saleor/shipping/types/ShippingErrorFragment"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { maybe } from "../../../misc"; import { ShippingMethodTypeEnum } from "../../../types/globalTypes"; -import { ShippingZoneDetailsFragment_shippingMethods } from "../../types/ShippingZoneDetailsFragment"; import { getShippingPriceRateErrorMessage, getShippingWeightRateErrorMessage @@ -37,6 +37,7 @@ export interface FormData { maxValue: string; isFree: boolean; price: string; + type: ShippingMethodTypeEnum; } export interface ShippingZoneRateDialogProps { @@ -104,7 +105,8 @@ const ShippingZoneRateDialog: React.FC = props => { minValue: "", name: "", noLimits: false, - price: "" + price: "", + type: null } : { isFree: maybe(() => rate.price.amount === 0, false), @@ -118,7 +120,8 @@ const ShippingZoneRateDialog: React.FC = props => { : maybe(() => rate.minimumOrderWeight.value.toString(), ""), name: maybe(() => rate.name, ""), noLimits: false, - price: maybe(() => rate.price.amount.toString(), "") + price: maybe(() => rate.price.amount.toString(), ""), + type: variant }; if (action === "edit") { initialForm.noLimits = !initialForm.maxValue && !initialForm.minValue; diff --git a/src/shipping/components/ShippingZoneRateDialog/errors.ts b/src/shipping/components/ShippingZoneRateDialog/errors.ts index a7dda3903..c8170e5b8 100644 --- a/src/shipping/components/ShippingZoneRateDialog/errors.ts +++ b/src/shipping/components/ShippingZoneRateDialog/errors.ts @@ -1,8 +1,7 @@ -import { IntlShape, defineMessages } from "react-intl"; - +import { ShippingErrorFragment } from "@saleor/fragments/types/ShippingErrorFragment"; import { ShippingErrorCode } from "@saleor/types/globalTypes"; import getShippingErrorMessage from "@saleor/utils/errors/shipping"; -import { ShippingErrorFragment } from "../../types/ShippingErrorFragment"; +import { defineMessages, IntlShape } from "react-intl"; const messages = defineMessages({ price: { diff --git a/src/shipping/components/ShippingZoneRates/ShippingZoneRates.tsx b/src/shipping/components/ShippingZoneRates/ShippingZoneRates.tsx index 7854d0a0c..40b4eb145 100644 --- a/src/shipping/components/ShippingZoneRates/ShippingZoneRates.tsx +++ b/src/shipping/components/ShippingZoneRates/ShippingZoneRates.tsx @@ -7,9 +7,6 @@ import TableHead from "@material-ui/core/TableHead"; import TableRow from "@material-ui/core/TableRow"; import DeleteIcon from "@material-ui/icons/Delete"; import EditIcon from "@material-ui/icons/Edit"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import CardTitle from "@saleor/components/CardTitle"; import IconButtonTableCell from "@saleor/components/IconButtonTableCell"; import Money from "@saleor/components/Money"; @@ -17,9 +14,12 @@ import MoneyRange from "@saleor/components/MoneyRange"; import ResponsiveTable from "@saleor/components/ResponsiveTable"; import Skeleton from "@saleor/components/Skeleton"; import WeightRange from "@saleor/components/WeightRange"; +import { ShippingZoneDetailsFragment_shippingMethods } from "@saleor/fragments/types/ShippingZoneDetailsFragment"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { maybe, renderCollection } from "../../../misc"; import { ICONBUTTON_SIZE } from "../../../theme"; -import { ShippingZoneDetailsFragment_shippingMethods } from "../../types/ShippingZoneDetailsFragment"; export interface ShippingZoneRatesProps { disabled: boolean; diff --git a/src/shipping/components/ShippingZoneWarehouses/ShippingZoneWarehouses.tsx b/src/shipping/components/ShippingZoneWarehouses/ShippingZoneWarehouses.tsx index e34264660..2db7806bb 100644 --- a/src/shipping/components/ShippingZoneWarehouses/ShippingZoneWarehouses.tsx +++ b/src/shipping/components/ShippingZoneWarehouses/ShippingZoneWarehouses.tsx @@ -1,14 +1,13 @@ import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; -import React from "react"; -import { useIntl } from "react-intl"; - import CardTitle from "@saleor/components/CardTitle"; -import { FetchMoreProps, SearchProps } from "@saleor/types"; -import { FormChange } from "@saleor/hooks/useForm"; import MultiAutocompleteSelectField, { MultiAutocompleteChoiceType } from "@saleor/components/MultiAutocompleteSelectField"; +import { FormChange } from "@saleor/hooks/useForm"; +import { FetchMoreProps, SearchProps } from "@saleor/types"; +import React from "react"; +import { useIntl } from "react-intl"; interface ShippingZoneWarehousesFormData { warehouses: string[]; diff --git a/src/shipping/components/ShippingZonesList/ShippingZonesList.tsx b/src/shipping/components/ShippingZonesList/ShippingZonesList.tsx index 10295a3fe..80a879229 100644 --- a/src/shipping/components/ShippingZonesList/ShippingZonesList.tsx +++ b/src/shipping/components/ShippingZonesList/ShippingZonesList.tsx @@ -7,19 +7,18 @@ import TableCell from "@material-ui/core/TableCell"; import TableFooter from "@material-ui/core/TableFooter"; import TableRow from "@material-ui/core/TableRow"; import DeleteIcon from "@material-ui/icons/Delete"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import CardTitle from "@saleor/components/CardTitle"; import Checkbox from "@saleor/components/Checkbox"; import ResponsiveTable from "@saleor/components/ResponsiveTable"; import Skeleton from "@saleor/components/Skeleton"; import TableHead from "@saleor/components/TableHead"; import TablePagination from "@saleor/components/TablePagination"; +import { ShippingZoneFragment } from "@saleor/fragments/types/ShippingZoneFragment"; import { maybe, renderCollection } from "@saleor/misc"; import { ICONBUTTON_SIZE } from "@saleor/theme"; import { ListActions, ListProps } from "@saleor/types"; -import { ShippingZoneFragment } from "../../types/ShippingZoneFragment"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; export interface ShippingZonesListProps extends ListProps, ListActions { shippingZones: ShippingZoneFragment[]; diff --git a/src/shipping/components/ShippingZonesListPage/ShippingZonesListPage.tsx b/src/shipping/components/ShippingZonesListPage/ShippingZonesListPage.tsx index 005dcbe34..39ecadbd5 100644 --- a/src/shipping/components/ShippingZonesListPage/ShippingZonesListPage.tsx +++ b/src/shipping/components/ShippingZonesListPage/ShippingZonesListPage.tsx @@ -1,15 +1,15 @@ -import React from "react"; -import { useIntl } from "react-intl"; - import AppHeader from "@saleor/components/AppHeader"; import Container from "@saleor/components/Container"; import Grid from "@saleor/components/Grid"; import PageHeader from "@saleor/components/PageHeader"; import RequirePermissions from "@saleor/components/RequirePermissions"; +import { ShippingZoneFragment } from "@saleor/fragments/types/ShippingZoneFragment"; import { sectionNames } from "@saleor/intl"; import { ListActions, PageListProps, UserPermissionProps } from "@saleor/types"; import { PermissionEnum, WeightUnitsEnum } from "@saleor/types/globalTypes"; -import { ShippingZoneFragment } from "../../types/ShippingZoneFragment"; +import React from "react"; +import { useIntl } from "react-intl"; + import ShippingWeightUnitForm from "../ShippingWeightUnitForm"; import ShippingZonesList from "../ShippingZonesList"; diff --git a/src/shipping/fixtures.ts b/src/shipping/fixtures.ts index 77eab37f9..209d6c32b 100644 --- a/src/shipping/fixtures.ts +++ b/src/shipping/fixtures.ts @@ -1,6 +1,7 @@ -import { ShippingMethodTypeEnum } from "../types/globalTypes"; -import { ShippingZoneDetailsFragment } from "./types/ShippingZoneDetailsFragment"; -import { ShippingZoneFragment } from "./types/ShippingZoneFragment"; +import { ShippingZoneDetailsFragment } from "@saleor/fragments/types/ShippingZoneDetailsFragment"; +import { ShippingZoneFragment } from "@saleor/fragments/types/ShippingZoneFragment"; + +import { ShippingMethodTypeEnum, WeightUnitsEnum } from "../types/globalTypes"; export const shippingZones: ShippingZoneFragment[] = [ { @@ -1553,7 +1554,7 @@ export const shippingZone: ShippingZoneDetailsFragment = { maximumOrderPrice: null, maximumOrderWeight: { __typename: "Weight", - unit: "kg", + unit: WeightUnitsEnum.KG, value: 80 }, minimumOrderPrice: { @@ -1563,7 +1564,7 @@ export const shippingZone: ShippingZoneDetailsFragment = { }, minimumOrderWeight: { __typename: "Weight", - unit: "kg", + unit: WeightUnitsEnum.KG, value: 0 }, name: "DB Schenker", @@ -1586,7 +1587,7 @@ export const shippingZone: ShippingZoneDetailsFragment = { }, minimumOrderWeight: { __typename: "Weight", - unit: "kg", + unit: WeightUnitsEnum.KG, value: 0 }, name: "Registred priority", @@ -1609,7 +1610,7 @@ export const shippingZone: ShippingZoneDetailsFragment = { }, minimumOrderWeight: { __typename: "Weight", - unit: "kg", + unit: WeightUnitsEnum.KG, value: 0 }, @@ -1633,7 +1634,7 @@ export const shippingZone: ShippingZoneDetailsFragment = { }, minimumOrderWeight: { __typename: "Weight", - unit: "kg", + unit: WeightUnitsEnum.KG, value: 0 }, name: "DHL", diff --git a/src/shipping/index.tsx b/src/shipping/index.tsx index b5f2738fc..32bdd7f7b 100644 --- a/src/shipping/index.tsx +++ b/src/shipping/index.tsx @@ -1,9 +1,9 @@ +import { sectionNames } from "@saleor/intl"; import { parse as parseQs } from "qs"; import React from "react"; import { useIntl } from "react-intl"; import { Route, RouteComponentProps, Switch } from "react-router-dom"; -import { sectionNames } from "@saleor/intl"; import { WindowTitle } from "../components/WindowTitle"; import { shippingZoneAddPath, @@ -25,9 +25,9 @@ const ShippingZonesList: React.FC> = ({ location }) => { interface ShippingZoneDetailsRouteProps { id: string; } -const ShippingZoneDetails: React.FC< - RouteComponentProps -> = ({ location, match }) => { +const ShippingZoneDetails: React.FC> = ({ location, match }) => { const qs = parseQs(location.search.substr(1)); const params: ShippingZoneUrlQueryParams = qs; return ( diff --git a/src/shipping/mutations.ts b/src/shipping/mutations.ts index 83ffa811a..e437bfa81 100644 --- a/src/shipping/mutations.ts +++ b/src/shipping/mutations.ts @@ -1,8 +1,12 @@ +import { shippingErrorFragment } from "@saleor/fragments/errors"; +import { + shippingMethodFragment, + shippingZoneDetailsFragment +} from "@saleor/fragments/shipping"; +import { countryFragment } from "@saleor/fragments/taxes"; +import makeMutation from "@saleor/hooks/makeMutation"; import gql from "graphql-tag"; -import makeMutation from "@saleor/hooks/makeMutation"; -import { countryFragment } from "../taxes/queries"; -import { shippingMethodFragment, shippingZoneDetailsFragment } from "./queries"; import { BulkDeleteShippingRate, BulkDeleteShippingRateVariables @@ -40,13 +44,6 @@ import { UpdateShippingZoneVariables } from "./types/UpdateShippingZone"; -export const shippingErrorFragment = gql` - fragment ShippingErrorFragment on ShippingError { - code - field - } -`; - const deleteShippingZone = gql` ${shippingErrorFragment} mutation DeleteShippingZone($id: ID!) { diff --git a/src/shipping/queries.ts b/src/shipping/queries.ts index 771a32b3f..6f4eb71b3 100644 --- a/src/shipping/queries.ts +++ b/src/shipping/queries.ts @@ -1,63 +1,14 @@ +import { pageInfoFragment } from "@saleor/fragments/pageInfo"; +import { + shippingZoneDetailsFragment, + shippingZoneFragment +} from "@saleor/fragments/shipping"; +import makeQuery from "@saleor/hooks/makeQuery"; import gql from "graphql-tag"; -import makeQuery from "@saleor/hooks/makeQuery"; -import { pageInfoFragment } from "../queries"; import { ShippingZone, ShippingZoneVariables } from "./types/ShippingZone"; import { ShippingZones, ShippingZonesVariables } from "./types/ShippingZones"; -export const shippingZoneFragment = gql` - fragment ShippingZoneFragment on ShippingZone { - id - countries { - code - country - } - name - } -`; -export const shippingMethodFragment = gql` - fragment ShippingMethodFragment on ShippingMethod { - id - minimumOrderPrice { - amount - currency - } - minimumOrderWeight { - unit - value - } - maximumOrderPrice { - amount - currency - } - maximumOrderWeight { - unit - value - } - name - price { - amount - currency - } - type - } -`; -export const shippingZoneDetailsFragment = gql` - ${shippingZoneFragment} - ${shippingMethodFragment} - fragment ShippingZoneDetailsFragment on ShippingZone { - ...ShippingZoneFragment - default - shippingMethods { - ...ShippingMethodFragment - } - warehouses { - id - name - } - } -`; - const shippingZones = gql` ${pageInfoFragment} ${shippingZoneFragment} diff --git a/src/shipping/types/CreateShippingRate.ts b/src/shipping/types/CreateShippingRate.ts index 7a29f3395..b1a8d9b95 100644 --- a/src/shipping/types/CreateShippingRate.ts +++ b/src/shipping/types/CreateShippingRate.ts @@ -2,7 +2,7 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { ShippingPriceInput, ShippingErrorCode, ShippingMethodTypeEnum } from "./../../types/globalTypes"; +import { ShippingPriceInput, ShippingErrorCode, WeightUnitsEnum, ShippingMethodTypeEnum } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: CreateShippingRate @@ -28,7 +28,7 @@ export interface CreateShippingRate_shippingPriceCreate_shippingZone_shippingMet export interface CreateShippingRate_shippingPriceCreate_shippingZone_shippingMethods_minimumOrderWeight { __typename: "Weight"; - unit: string; + unit: WeightUnitsEnum; value: number; } @@ -40,7 +40,7 @@ export interface CreateShippingRate_shippingPriceCreate_shippingZone_shippingMet export interface CreateShippingRate_shippingPriceCreate_shippingZone_shippingMethods_maximumOrderWeight { __typename: "Weight"; - unit: string; + unit: WeightUnitsEnum; value: number; } diff --git a/src/shipping/types/DeleteShippingRate.ts b/src/shipping/types/DeleteShippingRate.ts index d3fafa9b6..c5d02a026 100644 --- a/src/shipping/types/DeleteShippingRate.ts +++ b/src/shipping/types/DeleteShippingRate.ts @@ -2,7 +2,7 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { ShippingErrorCode, ShippingMethodTypeEnum } from "./../../types/globalTypes"; +import { ShippingErrorCode, WeightUnitsEnum, ShippingMethodTypeEnum } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: DeleteShippingRate @@ -28,7 +28,7 @@ export interface DeleteShippingRate_shippingPriceDelete_shippingZone_shippingMet export interface DeleteShippingRate_shippingPriceDelete_shippingZone_shippingMethods_minimumOrderWeight { __typename: "Weight"; - unit: string; + unit: WeightUnitsEnum; value: number; } @@ -40,7 +40,7 @@ export interface DeleteShippingRate_shippingPriceDelete_shippingZone_shippingMet export interface DeleteShippingRate_shippingPriceDelete_shippingZone_shippingMethods_maximumOrderWeight { __typename: "Weight"; - unit: string; + unit: WeightUnitsEnum; value: number; } diff --git a/src/shipping/types/ShippingZone.ts b/src/shipping/types/ShippingZone.ts index 091776cd3..bfde35cbb 100644 --- a/src/shipping/types/ShippingZone.ts +++ b/src/shipping/types/ShippingZone.ts @@ -2,7 +2,7 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { ShippingMethodTypeEnum } from "./../../types/globalTypes"; +import { WeightUnitsEnum, ShippingMethodTypeEnum } from "./../../types/globalTypes"; // ==================================================== // GraphQL query operation: ShippingZone @@ -22,7 +22,7 @@ export interface ShippingZone_shippingZone_shippingMethods_minimumOrderPrice { export interface ShippingZone_shippingZone_shippingMethods_minimumOrderWeight { __typename: "Weight"; - unit: string; + unit: WeightUnitsEnum; value: number; } @@ -34,7 +34,7 @@ export interface ShippingZone_shippingZone_shippingMethods_maximumOrderPrice { export interface ShippingZone_shippingZone_shippingMethods_maximumOrderWeight { __typename: "Weight"; - unit: string; + unit: WeightUnitsEnum; value: number; } diff --git a/src/shipping/types/UpdateShippingRate.ts b/src/shipping/types/UpdateShippingRate.ts index 88aa63cb4..880203eef 100644 --- a/src/shipping/types/UpdateShippingRate.ts +++ b/src/shipping/types/UpdateShippingRate.ts @@ -2,7 +2,7 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { ShippingPriceInput, ShippingErrorCode, ShippingMethodTypeEnum } from "./../../types/globalTypes"; +import { ShippingPriceInput, ShippingErrorCode, WeightUnitsEnum, ShippingMethodTypeEnum } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: UpdateShippingRate @@ -22,7 +22,7 @@ export interface UpdateShippingRate_shippingPriceUpdate_shippingMethod_minimumOr export interface UpdateShippingRate_shippingPriceUpdate_shippingMethod_minimumOrderWeight { __typename: "Weight"; - unit: string; + unit: WeightUnitsEnum; value: number; } @@ -34,7 +34,7 @@ export interface UpdateShippingRate_shippingPriceUpdate_shippingMethod_maximumOr export interface UpdateShippingRate_shippingPriceUpdate_shippingMethod_maximumOrderWeight { __typename: "Weight"; - unit: string; + unit: WeightUnitsEnum; value: number; } diff --git a/src/shipping/views/ShippingZoneCreate.tsx b/src/shipping/views/ShippingZoneCreate.tsx index 95928cc08..26082d261 100644 --- a/src/shipping/views/ShippingZoneCreate.tsx +++ b/src/shipping/views/ShippingZoneCreate.tsx @@ -1,10 +1,10 @@ -import React from "react"; -import { useIntl } from "react-intl"; - import useNavigator from "@saleor/hooks/useNavigator"; import useNotifier from "@saleor/hooks/useNotifier"; import useShop from "@saleor/hooks/useShop"; import { commonMessages } from "@saleor/intl"; +import React from "react"; +import { useIntl } from "react-intl"; + import ShippingZoneCreatePage from "../components/ShippingZoneCreatePage"; import { useShippingZoneCreate } from "../mutations"; import { shippingZonesListUrl, shippingZoneUrl } from "../urls"; @@ -19,6 +19,7 @@ const ShippingZoneCreate: React.FC<{}> = () => { onCompleted: data => { if (data.shippingZoneCreate.errors.length === 0) { notify({ + status: "success", text: intl.formatMessage(commonMessages.savedChanges) }); navigate(shippingZoneUrl(data.shippingZoneCreate.shippingZone.id)); diff --git a/src/shipping/views/ShippingZoneDetails/data.ts b/src/shipping/views/ShippingZoneDetails/data.ts index 48867c1a3..799e91600 100644 --- a/src/shipping/views/ShippingZoneDetails/data.ts +++ b/src/shipping/views/ShippingZoneDetails/data.ts @@ -1,8 +1,9 @@ -import { ShippingZoneUrlQueryParams } from "@saleor/shipping/urls"; -import { ShippingMethodTypeEnum } from "@saleor/types/globalTypes"; -import { UpdateShippingRateVariables } from "@saleor/shipping/types/UpdateShippingRate"; import { CreateShippingRateVariables } from "@saleor/shipping/types/CreateShippingRate"; import { ShippingZone_shippingZone_shippingMethods } from "@saleor/shipping/types/ShippingZone"; +import { UpdateShippingRateVariables } from "@saleor/shipping/types/UpdateShippingRate"; +import { ShippingZoneUrlQueryParams } from "@saleor/shipping/urls"; +import { ShippingMethodTypeEnum } from "@saleor/types/globalTypes"; + import { FormData as ShippingZoneRateDialogFormData } from "../../components/ShippingZoneRateDialog"; function getValue(value: string, hasLimits: boolean): number | null { @@ -27,7 +28,7 @@ export function getCreateShippingRateVariables( minimumOrderPrice: params.type === ShippingMethodTypeEnum.PRICE - ? getValue(data.maxValue, data.noLimits) + ? getValue(data.minValue, data.noLimits) : null, minimumOrderWeight: params.type === ShippingMethodTypeEnum.WEIGHT diff --git a/src/shipping/views/ShippingZoneDetails/index.tsx b/src/shipping/views/ShippingZoneDetails/index.tsx index b8be6523a..1ebaf32cc 100644 --- a/src/shipping/views/ShippingZoneDetails/index.tsx +++ b/src/shipping/views/ShippingZoneDetails/index.tsx @@ -1,32 +1,32 @@ -import { diff } from "fast-array-diff"; import DialogContentText from "@material-ui/core/DialogContentText"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import ActionDialog from "@saleor/components/ActionDialog"; +import NotFoundPage from "@saleor/components/NotFoundPage"; +import { DEFAULT_INITIAL_SEARCH_DATA } from "@saleor/config"; import useNavigator from "@saleor/hooks/useNavigator"; import useNotifier from "@saleor/hooks/useNotifier"; +import useShop from "@saleor/hooks/useShop"; import { commonMessages } from "@saleor/intl"; import useWarehouseSearch from "@saleor/searches/useWarehouseSearch"; -import { DEFAULT_INITIAL_SEARCH_DATA } from "@saleor/config"; +import ShippingZoneAddWarehouseDialog from "@saleor/shipping/components/ShippingZoneAddWarehouseDialog"; +import ShippingZoneCountriesAssignDialog from "@saleor/shipping/components/ShippingZoneCountriesAssignDialog"; +import ShippingZoneRateDialog from "@saleor/shipping/components/ShippingZoneRateDialog"; import { useShippingRateCreate, - useShippingRateUpdate, useShippingRateDelete, + useShippingRateUpdate, useShippingZoneDelete, useShippingZoneUpdate } from "@saleor/shipping/mutations"; import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; -import ShippingZoneRateDialog from "@saleor/shipping/components/ShippingZoneRateDialog"; -import useShop from "@saleor/hooks/useShop"; -import ShippingZoneCountriesAssignDialog from "@saleor/shipping/components/ShippingZoneCountriesAssignDialog"; -import NotFoundPage from "@saleor/components/NotFoundPage"; -import ShippingZoneAddWarehouseDialog from "@saleor/shipping/components/ShippingZoneAddWarehouseDialog"; import { useWarehouseCreate } from "@saleor/warehouses/mutations"; -import { getStringOrPlaceholder, findValueInEnum } from "../../../misc"; +import { diff } from "fast-array-diff"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + +import { findValueInEnum, getStringOrPlaceholder } from "../../../misc"; import { - ShippingMethodTypeEnum, - CountryCode + CountryCode, + ShippingMethodTypeEnum } from "../../../types/globalTypes"; import ShippingZoneDetailsPage, { FormData @@ -35,8 +35,8 @@ import { useShippingZone } from "../../queries"; import { shippingZonesListUrl, shippingZoneUrl, - ShippingZoneUrlQueryParams, - ShippingZoneUrlDialog + ShippingZoneUrlDialog, + ShippingZoneUrlQueryParams } from "../../urls"; import { getCreateShippingRateVariables, @@ -80,6 +80,7 @@ const ShippingZoneDetails: React.FC = ({ onCompleted: data => { if (data.shippingPriceCreate.errors.length === 0) { notify({ + status: "success", text: intl.formatMessage(commonMessages.savedChanges) }); closeModal(); @@ -91,6 +92,7 @@ const ShippingZoneDetails: React.FC = ({ onCompleted: data => { if (data.shippingPriceUpdate.errors.length === 0) { notify({ + status: "success", text: intl.formatMessage(commonMessages.savedChanges) }); closeModal(); @@ -102,6 +104,7 @@ const ShippingZoneDetails: React.FC = ({ onCompleted: data => { if (data.shippingPriceDelete.errors.length === 0) { notify({ + status: "success", text: intl.formatMessage(commonMessages.savedChanges) }); closeModal(); @@ -113,6 +116,7 @@ const ShippingZoneDetails: React.FC = ({ onCompleted: data => { if (data.shippingZoneDelete.errors.length === 0) { notify({ + status: "success", text: intl.formatMessage(commonMessages.savedChanges) }); navigate(shippingZonesListUrl(), true); @@ -124,6 +128,7 @@ const ShippingZoneDetails: React.FC = ({ onCompleted: data => { if (data.shippingZoneUpdate.errors.length === 0) { notify({ + status: "success", text: intl.formatMessage(commonMessages.savedChanges) }); closeModal(); @@ -135,6 +140,7 @@ const ShippingZoneDetails: React.FC = ({ onCompleted: data => { if (data.createWarehouse.errors.length === 0) { notify({ + status: "success", text: intl.formatMessage(commonMessages.savedChanges) }); closeModal(); diff --git a/src/shipping/views/ShippingZonesList.tsx b/src/shipping/views/ShippingZonesList.tsx index dd2ab2241..123789db9 100644 --- a/src/shipping/views/ShippingZonesList.tsx +++ b/src/shipping/views/ShippingZonesList.tsx @@ -1,9 +1,6 @@ import DialogContentText from "@material-ui/core/DialogContentText"; import IconButton from "@material-ui/core/IconButton"; import DeleteIcon from "@material-ui/icons/Delete"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import ActionDialog from "@saleor/components/ActionDialog"; import { configurationMenuUrl } from "@saleor/configuration"; import useBulkActions from "@saleor/hooks/useBulkActions"; @@ -16,22 +13,25 @@ import usePaginator, { import useShop from "@saleor/hooks/useShop"; import useUser from "@saleor/hooks/useUser"; import { commonMessages } from "@saleor/intl"; -import { maybe, getStringOrPlaceholder } from "@saleor/misc"; +import { getStringOrPlaceholder, maybe } from "@saleor/misc"; import { ListViews } from "@saleor/types"; import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import ShippingZonesListPage from "../components/ShippingZonesListPage"; import { + useDefaultWeightUnitUpdate, useShippingZoneBulkDelete, - useShippingZoneDelete, - useDefaultWeightUnitUpdate + useShippingZoneDelete } from "../mutations"; import { useShippingZoneList } from "../queries"; import { shippingZoneAddUrl, shippingZonesListUrl, + ShippingZonesListUrlDialog, ShippingZonesListUrlQueryParams, - shippingZoneUrl, - ShippingZonesListUrlDialog + shippingZoneUrl } from "../urls"; interface ShippingZonesListProps { @@ -70,6 +70,7 @@ export const ShippingZonesList: React.FC = ({ onCompleted: data => { if (data.shippingZoneDelete.errors.length === 0) { notify({ + status: "success", text: intl.formatMessage(commonMessages.savedChanges) }); closeModal(); @@ -85,6 +86,7 @@ export const ShippingZonesList: React.FC = ({ onCompleted: data => { if (data.shopSettingsUpdate.errors.length === 0) { notify({ + status: "success", text: intl.formatMessage(commonMessages.savedChanges) }); } @@ -98,6 +100,7 @@ export const ShippingZonesList: React.FC = ({ onCompleted: data => { if (data.shippingZoneBulkDelete.errors.length === 0) { notify({ + status: "success", text: intl.formatMessage(commonMessages.savedChanges) }); closeModal(); diff --git a/src/siteSettings/components/SiteSettingsDetails/SiteSettingsDetails.tsx b/src/siteSettings/components/SiteSettingsDetails/SiteSettingsDetails.tsx index 1ab493c03..111c3e71b 100644 --- a/src/siteSettings/components/SiteSettingsDetails/SiteSettingsDetails.tsx +++ b/src/siteSettings/components/SiteSettingsDetails/SiteSettingsDetails.tsx @@ -1,15 +1,15 @@ import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; import TextField from "@material-ui/core/TextField"; +import CardTitle from "@saleor/components/CardTitle"; +import FormSpacer from "@saleor/components/FormSpacer"; +import { ShopErrorFragment } from "@saleor/fragments/types/ShopErrorFragment"; +import { commonMessages } from "@saleor/intl"; +import { getFormErrors } from "@saleor/utils/errors"; +import getShopErrorMessage from "@saleor/utils/errors/shop"; import React from "react"; import { useIntl } from "react-intl"; -import CardTitle from "@saleor/components/CardTitle"; -import FormSpacer from "@saleor/components/FormSpacer"; -import { commonMessages } from "@saleor/intl"; -import { getFormErrors } from "@saleor/utils/errors"; -import { ShopErrorFragment } from "@saleor/siteSettings/types/ShopErrorFragment"; -import getShopErrorMessage from "@saleor/utils/errors/shop"; import { SiteSettingsPageFormData } from "../SiteSettingsPage"; interface SiteSettingsDetailsProps { diff --git a/src/siteSettings/components/SiteSettingsKeyDialog/SiteSettingsKeyDialog.tsx b/src/siteSettings/components/SiteSettingsKeyDialog/SiteSettingsKeyDialog.tsx index 11d394df0..9d5b2f135 100644 --- a/src/siteSettings/components/SiteSettingsKeyDialog/SiteSettingsKeyDialog.tsx +++ b/src/siteSettings/components/SiteSettingsKeyDialog/SiteSettingsKeyDialog.tsx @@ -4,17 +4,17 @@ import DialogActions from "@material-ui/core/DialogActions"; import DialogContent from "@material-ui/core/DialogContent"; import DialogTitle from "@material-ui/core/DialogTitle"; import TextField from "@material-ui/core/TextField"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import Form from "@saleor/components/Form"; import { FormSpacer } from "@saleor/components/FormSpacer"; import SingleSelectField from "@saleor/components/SingleSelectField"; +import { ShopErrorFragment } from "@saleor/fragments/types/ShopErrorFragment"; import { buttonMessages } from "@saleor/intl"; import { DialogProps } from "@saleor/types"; import { getFormErrors } from "@saleor/utils/errors"; -import { ShopErrorFragment } from "@saleor/siteSettings/types/ShopErrorFragment"; import getShopErrorMessage from "@saleor/utils/errors/shop"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { authorizationKeyTypes } from "../../../misc"; import { AuthorizationKeyType } from "../../../types/globalTypes"; diff --git a/src/siteSettings/components/SiteSettingsKeys/SiteSettingsKeys.tsx b/src/siteSettings/components/SiteSettingsKeys/SiteSettingsKeys.tsx index 5f67358a8..4933c7862 100644 --- a/src/siteSettings/components/SiteSettingsKeys/SiteSettingsKeys.tsx +++ b/src/siteSettings/components/SiteSettingsKeys/SiteSettingsKeys.tsx @@ -7,12 +7,12 @@ import TableCell from "@material-ui/core/TableCell"; import TableHead from "@material-ui/core/TableHead"; import TableRow from "@material-ui/core/TableRow"; import DeleteIcon from "@material-ui/icons/Delete"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import CardTitle from "@saleor/components/CardTitle"; import ResponsiveTable from "@saleor/components/ResponsiveTable"; import Skeleton from "@saleor/components/Skeleton"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { authorizationKeyTypes, maybe, renderCollection } from "../../../misc"; import { ICONBUTTON_SIZE } from "../../../theme"; import { AuthorizationKeyType } from "../../../types/globalTypes"; diff --git a/src/siteSettings/components/SiteSettingsMailing/SiteSettingsMailing.tsx b/src/siteSettings/components/SiteSettingsMailing/SiteSettingsMailing.tsx index 514e724a9..4c08cb3e8 100644 --- a/src/siteSettings/components/SiteSettingsMailing/SiteSettingsMailing.tsx +++ b/src/siteSettings/components/SiteSettingsMailing/SiteSettingsMailing.tsx @@ -3,15 +3,14 @@ import CardContent from "@material-ui/core/CardContent"; import { makeStyles } from "@material-ui/core/styles"; import TextField from "@material-ui/core/TextField"; import Typography from "@material-ui/core/Typography"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import CardTitle from "@saleor/components/CardTitle"; import FormSpacer from "@saleor/components/FormSpacer"; import Hr from "@saleor/components/Hr"; +import { ShopErrorFragment } from "@saleor/fragments/types/ShopErrorFragment"; import { getFormErrors } from "@saleor/utils/errors"; -import { ShopErrorFragment } from "@saleor/siteSettings/types/ShopErrorFragment"; import getShopErrorMessage from "@saleor/utils/errors/shop"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; export interface SiteSettingsMailingFormData { defaultMailSenderName: string; diff --git a/src/siteSettings/components/SiteSettingsPage/SiteSettingsPage.tsx b/src/siteSettings/components/SiteSettingsPage/SiteSettingsPage.tsx index 7fa681fa7..b05db7280 100644 --- a/src/siteSettings/components/SiteSettingsPage/SiteSettingsPage.tsx +++ b/src/siteSettings/components/SiteSettingsPage/SiteSettingsPage.tsx @@ -1,9 +1,7 @@ import { makeStyles } from "@material-ui/core/styles"; import Typography from "@material-ui/core/Typography"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import AppHeader from "@saleor/components/AppHeader"; +import CompanyAddressInput from "@saleor/components/CompanyAddressInput"; import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; import Container from "@saleor/components/Container"; import Form from "@saleor/components/Form"; @@ -11,13 +9,15 @@ import Grid from "@saleor/components/Grid"; import Hr from "@saleor/components/Hr"; import PageHeader from "@saleor/components/PageHeader"; import SaveButtonBar from "@saleor/components/SaveButtonBar"; +import { ShopErrorFragment } from "@saleor/fragments/types/ShopErrorFragment"; import useAddressValidation from "@saleor/hooks/useAddressValidation"; import useStateFromProps from "@saleor/hooks/useStateFromProps"; import { commonMessages, sectionNames } from "@saleor/intl"; import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler"; import { mapCountriesToChoices } from "@saleor/utils/maps"; -import { ShopErrorFragment } from "@saleor/siteSettings/types/ShopErrorFragment"; -import CompanyAddressInput from "@saleor/components/CompanyAddressInput"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { maybe } from "../../../misc"; import { AuthorizationKeyType } from "../../../types/globalTypes"; import { SiteSettings_shop } from "../../types/SiteSettings"; diff --git a/src/siteSettings/mutations.ts b/src/siteSettings/mutations.ts index c13b45f7f..50baaf211 100644 --- a/src/siteSettings/mutations.ts +++ b/src/siteSettings/mutations.ts @@ -1,8 +1,9 @@ +import { fragmentAddress } from "@saleor/fragments/address"; +import { shopErrorFragment } from "@saleor/fragments/errors"; +import { shopFragment } from "@saleor/fragments/shop"; import gql from "graphql-tag"; import { TypedMutation } from "../mutations"; -import { fragmentAddress } from "../orders/queries"; -import { shopFragment } from "./queries"; import { AuthorizationKeyAdd, AuthorizationKeyAddVariables @@ -16,12 +17,6 @@ import { ShopSettingsUpdateVariables } from "./types/ShopSettingsUpdate"; -const shopErrorFragment = gql` - fragment ShopErrorFragment on ShopError { - code - field - } -`; const authorizationKeyAdd = gql` ${shopErrorFragment} ${shopFragment} diff --git a/src/siteSettings/queries.ts b/src/siteSettings/queries.ts index d4e01c203..7432cd0e7 100644 --- a/src/siteSettings/queries.ts +++ b/src/siteSettings/queries.ts @@ -1,32 +1,9 @@ +import { shopFragment } from "@saleor/fragments/shop"; import gql from "graphql-tag"; -import { fragmentAddress } from "../orders/queries"; + import { TypedQuery } from "../queries"; import { SiteSettings } from "./types/SiteSettings"; -export const shopFragment = gql` - ${fragmentAddress} - fragment ShopFragment on Shop { - authorizationKeys { - key - name - } - companyAddress { - ...AddressFragment - } - countries { - code - country - } - customerSetPasswordUrl - defaultMailSenderAddress - defaultMailSenderName - description - domain { - host - } - name - } -`; const siteSettings = gql` ${shopFragment} query SiteSettings { diff --git a/src/siteSettings/types/AuthorizationKeyAdd.ts b/src/siteSettings/types/AuthorizationKeyAdd.ts index 258aabf71..33bf3f2d2 100644 --- a/src/siteSettings/types/AuthorizationKeyAdd.ts +++ b/src/siteSettings/types/AuthorizationKeyAdd.ts @@ -57,7 +57,7 @@ export interface AuthorizationKeyAdd_authorizationKeyAdd_shop { __typename: "Shop"; authorizationKeys: (AuthorizationKeyAdd_authorizationKeyAdd_shop_authorizationKeys | null)[]; companyAddress: AuthorizationKeyAdd_authorizationKeyAdd_shop_companyAddress | null; - countries: (AuthorizationKeyAdd_authorizationKeyAdd_shop_countries | null)[]; + countries: AuthorizationKeyAdd_authorizationKeyAdd_shop_countries[]; customerSetPasswordUrl: string | null; defaultMailSenderAddress: string | null; defaultMailSenderName: string | null; diff --git a/src/siteSettings/types/AuthorizationKeyDelete.ts b/src/siteSettings/types/AuthorizationKeyDelete.ts index ccf4f5ba8..ed491f0ea 100644 --- a/src/siteSettings/types/AuthorizationKeyDelete.ts +++ b/src/siteSettings/types/AuthorizationKeyDelete.ts @@ -57,7 +57,7 @@ export interface AuthorizationKeyDelete_authorizationKeyDelete_shop { __typename: "Shop"; authorizationKeys: (AuthorizationKeyDelete_authorizationKeyDelete_shop_authorizationKeys | null)[]; companyAddress: AuthorizationKeyDelete_authorizationKeyDelete_shop_companyAddress | null; - countries: (AuthorizationKeyDelete_authorizationKeyDelete_shop_countries | null)[]; + countries: AuthorizationKeyDelete_authorizationKeyDelete_shop_countries[]; customerSetPasswordUrl: string | null; defaultMailSenderAddress: string | null; defaultMailSenderName: string | null; diff --git a/src/siteSettings/types/ShopSettingsUpdate.ts b/src/siteSettings/types/ShopSettingsUpdate.ts index acc2e1bf1..b604b98f5 100644 --- a/src/siteSettings/types/ShopSettingsUpdate.ts +++ b/src/siteSettings/types/ShopSettingsUpdate.ts @@ -57,7 +57,7 @@ export interface ShopSettingsUpdate_shopSettingsUpdate_shop { __typename: "Shop"; authorizationKeys: (ShopSettingsUpdate_shopSettingsUpdate_shop_authorizationKeys | null)[]; companyAddress: ShopSettingsUpdate_shopSettingsUpdate_shop_companyAddress | null; - countries: (ShopSettingsUpdate_shopSettingsUpdate_shop_countries | null)[]; + countries: ShopSettingsUpdate_shopSettingsUpdate_shop_countries[]; customerSetPasswordUrl: string | null; defaultMailSenderAddress: string | null; defaultMailSenderName: string | null; diff --git a/src/siteSettings/types/SiteSettings.ts b/src/siteSettings/types/SiteSettings.ts index bc9abeea1..6b81087c2 100644 --- a/src/siteSettings/types/SiteSettings.ts +++ b/src/siteSettings/types/SiteSettings.ts @@ -51,7 +51,7 @@ export interface SiteSettings_shop { __typename: "Shop"; authorizationKeys: (SiteSettings_shop_authorizationKeys | null)[]; companyAddress: SiteSettings_shop_companyAddress | null; - countries: (SiteSettings_shop_countries | null)[]; + countries: SiteSettings_shop_countries[]; customerSetPasswordUrl: string | null; defaultMailSenderAddress: string | null; defaultMailSenderName: string | null; diff --git a/src/siteSettings/views/index.tsx b/src/siteSettings/views/index.tsx index 2d33440d7..b090eda9d 100644 --- a/src/siteSettings/views/index.tsx +++ b/src/siteSettings/views/index.tsx @@ -1,9 +1,8 @@ -import React from "react"; - import { WindowTitle } from "@saleor/components/WindowTitle"; import useNavigator from "@saleor/hooks/useNavigator"; import useNotifier from "@saleor/hooks/useNotifier"; import { commonMessages, sectionNames } from "@saleor/intl"; +import React from "react"; import { useIntl } from "react-intl"; import { configurationMenuUrl } from "../../configuration"; @@ -39,6 +38,7 @@ export const SiteSettings: React.FC = ({ params }) => { const handleAddKeySuccess = (data: AuthorizationKeyAdd) => { if (data.authorizationKeyAdd.errors.length === 0) { notify({ + status: "success", text: intl.formatMessage(commonMessages.savedChanges) }); navigate(siteSettingsUrl()); @@ -47,10 +47,12 @@ export const SiteSettings: React.FC = ({ params }) => { const handleDeleteKeySuccess = (data: AuthorizationKeyDelete) => { if (data.authorizationKeyDelete.errors.length === 0) { notify({ + status: "success", text: intl.formatMessage(commonMessages.savedChanges) }); } else { notify({ + status: "error", text: intl.formatMessage(commonMessages.somethingWentWrong) }); } @@ -62,6 +64,7 @@ export const SiteSettings: React.FC = ({ params }) => { data.shopAddressUpdate.errors.length === 0 ) { notify({ + status: "success", text: intl.formatMessage(commonMessages.savedChanges) }); } diff --git a/src/staff/components/StaffAddMemberDialog/StaffAddMemberDialog.tsx b/src/staff/components/StaffAddMemberDialog/StaffAddMemberDialog.tsx index 3d8760900..3b93382d1 100644 --- a/src/staff/components/StaffAddMemberDialog/StaffAddMemberDialog.tsx +++ b/src/staff/components/StaffAddMemberDialog/StaffAddMemberDialog.tsx @@ -1,6 +1,3 @@ -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import Button from "@material-ui/core/Button"; import Dialog from "@material-ui/core/Dialog"; import DialogActions from "@material-ui/core/DialogActions"; @@ -13,13 +10,15 @@ import ConfirmButton, { } from "@saleor/components/ConfirmButton"; import Form from "@saleor/components/Form"; import FormSpacer from "@saleor/components/FormSpacer"; -import { buttonMessages, commonMessages } from "@saleor/intl"; +import { StaffErrorFragment } from "@saleor/fragments/types/StaffErrorFragment"; import useModalDialogErrors from "@saleor/hooks/useModalDialogErrors"; -import { getFormErrors } from "@saleor/utils/errors"; -import { StaffErrorFragment } from "@saleor/staff/types/StaffErrorFragment"; +import { buttonMessages, commonMessages } from "@saleor/intl"; import { SearchPermissionGroups_search_edges_node } from "@saleor/searches/types/SearchPermissionGroups"; import { FetchMoreProps, SearchPageProps } from "@saleor/types"; +import { getFormErrors } from "@saleor/utils/errors"; import getStaffErrorMessage from "@saleor/utils/errors/staff"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; export interface AddMemberFormData { email: string; diff --git a/src/staff/components/StaffDetailsPage/StaffDetailsPage.stories.tsx b/src/staff/components/StaffDetailsPage/StaffDetailsPage.stories.tsx index 0712de9cb..734a55718 100644 --- a/src/staff/components/StaffDetailsPage/StaffDetailsPage.stories.tsx +++ b/src/staff/components/StaffDetailsPage/StaffDetailsPage.stories.tsx @@ -1,12 +1,12 @@ import { Omit } from "@material-ui/core"; -import { storiesOf } from "@storybook/react"; -import React from "react"; +import { userPermissionGroups } from "@saleor/permissionGroups/fixtures"; import StaffDetailsPage, { StaffDetailsPageProps } from "@saleor/staff/components/StaffDetailsPage"; import { staffMember } from "@saleor/staff/fixtures"; import Decorator from "@saleor/storybook/Decorator"; -import { userPermissionGroups } from "@saleor/permissionGroups/fixtures"; +import { storiesOf } from "@storybook/react"; +import React from "react"; const props: Omit = { availablePermissionGroups: [], diff --git a/src/staff/components/StaffDetailsPage/StaffDetailsPage.tsx b/src/staff/components/StaffDetailsPage/StaffDetailsPage.tsx index c90dab0a7..11ccc1439 100644 --- a/src/staff/components/StaffDetailsPage/StaffDetailsPage.tsx +++ b/src/staff/components/StaffDetailsPage/StaffDetailsPage.tsx @@ -1,10 +1,7 @@ -import React from "react"; -import { useIntl } from "react-intl"; - import { Card, CardContent, Typography } from "@material-ui/core"; import AccountPermissionGroups from "@saleor/components/AccountPermissionGroups"; -import AccountStatus from "@saleor/components/AccountStatus"; import AppHeader from "@saleor/components/AppHeader"; +import AccountStatus from "@saleor/components/AppStatus"; import CardSpacer from "@saleor/components/CardSpacer"; import CardTitle from "@saleor/components/CardTitle"; import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; @@ -14,6 +11,7 @@ import Grid from "@saleor/components/Grid"; import { MultiAutocompleteChoiceType } from "@saleor/components/MultiAutocompleteSelectField"; import PageHeader from "@saleor/components/PageHeader"; import SaveButtonBar from "@saleor/components/SaveButtonBar"; +import { StaffErrorFragment } from "@saleor/fragments/types/StaffErrorFragment"; import useLocale from "@saleor/hooks/useLocale"; import useStateFromProps from "@saleor/hooks/useStateFromProps"; import { sectionNames } from "@saleor/intl"; @@ -21,7 +19,9 @@ import { getUserName } from "@saleor/misc"; import { SearchPermissionGroups_search_edges_node } from "@saleor/searches/types/SearchPermissionGroups"; import { FetchMoreProps, SearchPageProps } from "@saleor/types"; import createMultiAutocompleteSelectHandler from "@saleor/utils/handlers/multiAutocompleteSelectChangeHandler"; -import { StaffErrorFragment } from "@saleor/staff/types/StaffErrorFragment"; +import React from "react"; +import { useIntl } from "react-intl"; + import { StaffMemberDetails_user } from "../../types/StaffMemberDetails"; import StaffPassword from "../StaffPassword/StaffPassword"; import StaffPreferences from "../StaffPreferences"; diff --git a/src/staff/components/StaffList/StaffList.tsx b/src/staff/components/StaffList/StaffList.tsx index de2232f7d..2f60804de 100644 --- a/src/staff/components/StaffList/StaffList.tsx +++ b/src/staff/components/StaffList/StaffList.tsx @@ -5,12 +5,9 @@ import TableFooter from "@material-ui/core/TableFooter"; import TableHead from "@material-ui/core/TableHead"; import TableRow from "@material-ui/core/TableRow"; import Typography from "@material-ui/core/Typography"; -import classNames from "classnames"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import ResponsiveTable from "@saleor/components/ResponsiveTable"; import Skeleton from "@saleor/components/Skeleton"; +import TableCellHeader from "@saleor/components/TableCellHeader"; import TablePagination from "@saleor/components/TablePagination"; import { getUserInitials, @@ -18,10 +15,13 @@ import { maybe, renderCollection } from "@saleor/misc"; -import { ListProps, SortPage } from "@saleor/types"; import { StaffListUrlSortField } from "@saleor/staff/urls"; -import TableCellHeader from "@saleor/components/TableCellHeader"; +import { ListProps, SortPage } from "@saleor/types"; import { getArrowDirection } from "@saleor/utils/sort"; +import classNames from "classnames"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + import { StaffList_staffUsers_edges_node } from "../../types/StaffList"; const useStyles = makeStyles( @@ -38,8 +38,8 @@ const useStyles = makeStyles( width: 47 }, avatarDefault: { - "& p": { - color: "#fff", + "& div": { + color: theme.palette.primary.contrastText, lineHeight: "47px" }, background: theme.palette.primary.main, diff --git a/src/staff/components/StaffListPage/StaffListPage.stories.tsx b/src/staff/components/StaffListPage/StaffListPage.stories.tsx index 3693ac7b6..ac214d9c7 100644 --- a/src/staff/components/StaffListPage/StaffListPage.stories.tsx +++ b/src/staff/components/StaffListPage/StaffListPage.stories.tsx @@ -1,17 +1,17 @@ +import { + filterPageProps, + pageListProps, + searchPageProps, + sortPageProps, + tabPageProps +} from "@saleor/fixtures"; +import { staffMembers } from "@saleor/staff/fixtures"; +import { StaffListUrlSortField } from "@saleor/staff/urls"; +import Decorator from "@saleor/storybook/Decorator"; +import { StaffMemberStatus } from "@saleor/types/globalTypes"; import { storiesOf } from "@storybook/react"; import React from "react"; -import { StaffListUrlSortField } from "@saleor/staff/urls"; -import { StaffMemberStatus } from "@saleor/types/globalTypes"; -import { - pageListProps, - searchPageProps, - tabPageProps, - sortPageProps, - filterPageProps -} from "@saleor/fixtures"; -import { staffMembers } from "@saleor/staff/fixtures"; -import Decorator from "@saleor/storybook/Decorator"; import StaffListPage, { StaffListPageProps } from "."; const props: StaffListPageProps = { diff --git a/src/staff/components/StaffListPage/StaffListPage.tsx b/src/staff/components/StaffListPage/StaffListPage.tsx index b4faf0728..e637936a6 100644 --- a/src/staff/components/StaffListPage/StaffListPage.tsx +++ b/src/staff/components/StaffListPage/StaffListPage.tsx @@ -1,20 +1,20 @@ import Button from "@material-ui/core/Button"; import Card from "@material-ui/core/Card"; +import AppHeader from "@saleor/components/AppHeader"; +import { Container } from "@saleor/components/Container"; +import FilterBar from "@saleor/components/FilterBar"; +import PageHeader from "@saleor/components/PageHeader"; +import { sectionNames } from "@saleor/intl"; +import { StaffListUrlSortField } from "@saleor/staff/urls"; +import { + FilterPageProps, + ListProps, + SortPage, + TabPageProps +} from "@saleor/types"; import React from "react"; import { FormattedMessage, useIntl } from "react-intl"; -import AppHeader from "@saleor/components/AppHeader"; -import { Container } from "@saleor/components/Container"; -import PageHeader from "@saleor/components/PageHeader"; -import FilterBar from "@saleor/components/FilterBar"; -import { sectionNames } from "@saleor/intl"; -import { - ListProps, - FilterPageProps, - TabPageProps, - SortPage -} from "@saleor/types"; -import { StaffListUrlSortField } from "@saleor/staff/urls"; import { StaffList_staffUsers_edges_node } from "../../types/StaffList"; import StaffList from "../StaffList/StaffList"; import { diff --git a/src/staff/components/StaffListPage/filters.ts b/src/staff/components/StaffListPage/filters.ts index 1831f09e2..19f3338f2 100644 --- a/src/staff/components/StaffListPage/filters.ts +++ b/src/staff/components/StaffListPage/filters.ts @@ -1,9 +1,8 @@ -import { IntlShape, defineMessages } from "react-intl"; - +import { IFilter } from "@saleor/components/Filter"; import { FilterOpts } from "@saleor/types"; import { StaffMemberStatus } from "@saleor/types/globalTypes"; -import { IFilter } from "@saleor/components/Filter"; import { createOptionsField } from "@saleor/utils/filters/fields"; +import { defineMessages, IntlShape } from "react-intl"; export enum StaffFilterKeys { status = "status" diff --git a/src/staff/components/StaffPassword/StaffPassword.tsx b/src/staff/components/StaffPassword/StaffPassword.tsx index 1d9582540..fe51fbc2b 100644 --- a/src/staff/components/StaffPassword/StaffPassword.tsx +++ b/src/staff/components/StaffPassword/StaffPassword.tsx @@ -1,11 +1,10 @@ -import React from "react"; import Button from "@material-ui/core/Button"; import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; import Typography from "@material-ui/core/Typography"; -import { FormattedMessage, useIntl } from "react-intl"; - import CardTitle from "@saleor/components/CardTitle"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; interface StaffPasswordProps { onChangePassword: () => void; diff --git a/src/staff/components/StaffPasswordResetDialog/StaffPasswordResetDialog.tsx b/src/staff/components/StaffPasswordResetDialog/StaffPasswordResetDialog.tsx index 8f6afbae8..429984bdf 100644 --- a/src/staff/components/StaffPasswordResetDialog/StaffPasswordResetDialog.tsx +++ b/src/staff/components/StaffPasswordResetDialog/StaffPasswordResetDialog.tsx @@ -1,23 +1,22 @@ -import React from "react"; import Button from "@material-ui/core/Button"; import Dialog from "@material-ui/core/Dialog"; import DialogActions from "@material-ui/core/DialogActions"; import DialogContent from "@material-ui/core/DialogContent"; -import TextField from "@material-ui/core/TextField"; import DialogTitle from "@material-ui/core/DialogTitle"; -import { FormattedMessage, useIntl } from "react-intl"; - -import { DialogProps } from "@saleor/types"; -import { buttonMessages } from "@saleor/intl"; -import Form from "@saleor/components/Form"; +import TextField from "@material-ui/core/TextField"; import ConfirmButton, { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; +import Form from "@saleor/components/Form"; import FormSpacer from "@saleor/components/FormSpacer"; +import { AccountErrorFragment } from "@saleor/fragments/types/AccountErrorFragment"; import useModalDialogErrors from "@saleor/hooks/useModalDialogErrors"; -import { AccountErrorFragment } from "@saleor/customers/types/AccountErrorFragment"; +import { buttonMessages } from "@saleor/intl"; +import { DialogProps } from "@saleor/types"; import { getFormErrors } from "@saleor/utils/errors"; import getAccountErrorMessage from "@saleor/utils/errors/account"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; interface StaffPasswordResetDialogFormData { newPassword: string; diff --git a/src/staff/components/StaffPreferences/StaffPreferences.tsx b/src/staff/components/StaffPreferences/StaffPreferences.tsx index 654140ca2..8191098ed 100644 --- a/src/staff/components/StaffPreferences/StaffPreferences.tsx +++ b/src/staff/components/StaffPreferences/StaffPreferences.tsx @@ -1,14 +1,13 @@ import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; import Typography from "@material-ui/core/Typography"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import CardTitle from "@saleor/components/CardTitle"; import FormSpacer from "@saleor/components/FormSpacer"; import { Locale, localeNames } from "@saleor/components/Locale"; import SingleAutocompleteSelectField from "@saleor/components/SingleAutocompleteSelectField"; import { capitalize } from "@saleor/misc"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; interface StaffPreferencesProps { locale: Locale; diff --git a/src/staff/components/StaffProperties/StaffProperties.tsx b/src/staff/components/StaffProperties/StaffProperties.tsx index 653790629..1a2b10f63 100644 --- a/src/staff/components/StaffProperties/StaffProperties.tsx +++ b/src/staff/components/StaffProperties/StaffProperties.tsx @@ -1,18 +1,18 @@ +import photoIcon from "@assets/images/photo-icon.svg"; import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; import { makeStyles } from "@material-ui/core/styles"; import TextField from "@material-ui/core/TextField"; import Typography from "@material-ui/core/Typography"; +import CardTitle from "@saleor/components/CardTitle"; +import { StaffErrorFragment } from "@saleor/fragments/types/StaffErrorFragment"; +import { commonMessages } from "@saleor/intl"; +import { getFormErrors } from "@saleor/utils/errors"; +import getStaffErrorMessage from "@saleor/utils/errors/staff"; import React from "react"; import SVG from "react-inlinesvg"; import { FormattedMessage, useIntl } from "react-intl"; -import photoIcon from "@assets/images/photo-icon.svg"; -import CardTitle from "@saleor/components/CardTitle"; -import { commonMessages } from "@saleor/intl"; -import { getFormErrors } from "@saleor/utils/errors"; -import { StaffErrorFragment } from "@saleor/staff/types/StaffErrorFragment"; -import getStaffErrorMessage from "@saleor/utils/errors/staff"; import { getUserInitials, maybe } from "../../../misc"; import { StaffMemberDetails_user } from "../../types/StaffMemberDetails"; @@ -35,7 +35,7 @@ const useStyles = makeStyles( width: 120 }, avatarDefault: { - "& p": { + "& div": { color: "#fff", fontSize: 35, fontWeight: "bold", diff --git a/src/staff/fixtures.ts b/src/staff/fixtures.ts index ce002d923..27ddc0081 100644 --- a/src/staff/fixtures.ts +++ b/src/staff/fixtures.ts @@ -1,5 +1,6 @@ import avatarImage from "@assets/images/avatars/avatar1.png"; import { permissions } from "@saleor/fixtures"; + import { StaffList_staffUsers_edges_node } from "./types/StaffList"; import { StaffMemberDetails_user } from "./types/StaffMemberDetails"; diff --git a/src/staff/index.tsx b/src/staff/index.tsx index 71541c889..c28900508 100644 --- a/src/staff/index.tsx +++ b/src/staff/index.tsx @@ -1,17 +1,17 @@ +import { sectionNames } from "@saleor/intl"; +import { asSortParams } from "@saleor/utils/sort"; import { parse as parseQs } from "qs"; import React from "react"; import { useIntl } from "react-intl"; import { Route, RouteComponentProps, Switch } from "react-router-dom"; -import { sectionNames } from "@saleor/intl"; -import { asSortParams } from "@saleor/utils/sort"; import { WindowTitle } from "../components/WindowTitle"; import { staffListPath, StaffListUrlQueryParams, + StaffListUrlSortField, staffMemberDetailsPath, - StaffMemberDetailsUrlQueryParams, - StaffListUrlSortField + StaffMemberDetailsUrlQueryParams } from "./urls"; import StaffDetailsComponent from "./views/StaffDetails"; import StaffListComponent from "./views/StaffList"; diff --git a/src/staff/mutations.ts b/src/staff/mutations.ts index 2987a1f9a..c51044584 100644 --- a/src/staff/mutations.ts +++ b/src/staff/mutations.ts @@ -1,8 +1,12 @@ -import gql from "graphql-tag"; +import { + accountErrorFragment, + staffErrorFragment +} from "@saleor/fragments/errors"; +import { staffMemberDetailsFragment } from "@saleor/fragments/staff"; import makeMutation from "@saleor/hooks/makeMutation"; -import { accountErrorFragment } from "@saleor/customers/mutations"; +import gql from "graphql-tag"; + import { TypedMutation } from "../mutations"; -import { staffMemberDetailsFragment } from "./queries"; import { ChangeStaffPassword, ChangeStaffPasswordVariables @@ -25,20 +29,6 @@ import { StaffMemberUpdateVariables } from "./types/StaffMemberUpdate"; -export const staffErrorFragment = gql` - fragment StaffErrorFragment on StaffError { - code - field - } -`; - -export const staffFragmentError = gql` - fragment StaffErrorFragment on StaffError { - code - field - } -`; - const staffMemberAddMutation = gql` ${staffErrorFragment} ${staffMemberDetailsFragment} diff --git a/src/staff/queries.ts b/src/staff/queries.ts index 8c0015064..4c2c6ef0e 100644 --- a/src/staff/queries.ts +++ b/src/staff/queries.ts @@ -1,5 +1,10 @@ -import gql from "graphql-tag"; +import { + staffMemberDetailsFragment, + staffMemberFragment +} from "@saleor/fragments/staff"; import makeQuery from "@saleor/hooks/makeQuery"; +import gql from "graphql-tag"; + import { TypedQuery } from "../queries"; import { StaffList, StaffListVariables } from "./types/StaffList"; import { @@ -7,33 +12,6 @@ import { StaffMemberDetailsVariables } from "./types/StaffMemberDetails"; -export const staffMemberFragment = gql` - fragment StaffMemberFragment on User { - id - email - firstName - isActive - lastName - avatar { - url - } - } -`; -export const staffMemberDetailsFragment = gql` - ${staffMemberFragment} - fragment StaffMemberDetailsFragment on User { - ...StaffMemberFragment - permissionGroups { - id - name - userCanManage - } - userPermissions { - code - name - } - } -`; const staffList = gql` ${staffMemberFragment} query StaffList( @@ -56,6 +34,9 @@ const staffList = gql` cursor node { ...StaffMemberFragment + avatar(size: 48) { + url + } } } pageInfo { diff --git a/src/staff/types/StaffMemberAdd.ts b/src/staff/types/StaffMemberAdd.ts index d42e80dcf..d5b176cff 100644 --- a/src/staff/types/StaffMemberAdd.ts +++ b/src/staff/types/StaffMemberAdd.ts @@ -14,11 +14,6 @@ export interface StaffMemberAdd_staffCreate_errors { field: string | null; } -export interface StaffMemberAdd_staffCreate_user_avatar { - __typename: "Image"; - url: string; -} - export interface StaffMemberAdd_staffCreate_user_permissionGroups { __typename: "Group"; id: string; @@ -32,6 +27,11 @@ export interface StaffMemberAdd_staffCreate_user_userPermissions { name: string; } +export interface StaffMemberAdd_staffCreate_user_avatar { + __typename: "Image"; + url: string; +} + export interface StaffMemberAdd_staffCreate_user { __typename: "User"; id: string; @@ -39,9 +39,9 @@ export interface StaffMemberAdd_staffCreate_user { firstName: string; isActive: boolean; lastName: string; - avatar: StaffMemberAdd_staffCreate_user_avatar | null; permissionGroups: (StaffMemberAdd_staffCreate_user_permissionGroups | null)[] | null; userPermissions: (StaffMemberAdd_staffCreate_user_userPermissions | null)[] | null; + avatar: StaffMemberAdd_staffCreate_user_avatar | null; } export interface StaffMemberAdd_staffCreate { diff --git a/src/staff/types/StaffMemberDetails.ts b/src/staff/types/StaffMemberDetails.ts index 1935e7461..2ec999c1a 100644 --- a/src/staff/types/StaffMemberDetails.ts +++ b/src/staff/types/StaffMemberDetails.ts @@ -8,11 +8,6 @@ import { PermissionEnum } from "./../../types/globalTypes"; // GraphQL query operation: StaffMemberDetails // ==================================================== -export interface StaffMemberDetails_user_avatar { - __typename: "Image"; - url: string; -} - export interface StaffMemberDetails_user_permissionGroups { __typename: "Group"; id: string; @@ -26,6 +21,11 @@ export interface StaffMemberDetails_user_userPermissions { name: string; } +export interface StaffMemberDetails_user_avatar { + __typename: "Image"; + url: string; +} + export interface StaffMemberDetails_user { __typename: "User"; id: string; @@ -33,9 +33,9 @@ export interface StaffMemberDetails_user { firstName: string; isActive: boolean; lastName: string; - avatar: StaffMemberDetails_user_avatar | null; permissionGroups: (StaffMemberDetails_user_permissionGroups | null)[] | null; userPermissions: (StaffMemberDetails_user_userPermissions | null)[] | null; + avatar: StaffMemberDetails_user_avatar | null; } export interface StaffMemberDetails { diff --git a/src/staff/types/StaffMemberUpdate.ts b/src/staff/types/StaffMemberUpdate.ts index b7ce4c317..abf093d50 100644 --- a/src/staff/types/StaffMemberUpdate.ts +++ b/src/staff/types/StaffMemberUpdate.ts @@ -14,11 +14,6 @@ export interface StaffMemberUpdate_staffUpdate_errors { field: string | null; } -export interface StaffMemberUpdate_staffUpdate_user_avatar { - __typename: "Image"; - url: string; -} - export interface StaffMemberUpdate_staffUpdate_user_permissionGroups { __typename: "Group"; id: string; @@ -32,6 +27,11 @@ export interface StaffMemberUpdate_staffUpdate_user_userPermissions { name: string; } +export interface StaffMemberUpdate_staffUpdate_user_avatar { + __typename: "Image"; + url: string; +} + export interface StaffMemberUpdate_staffUpdate_user { __typename: "User"; id: string; @@ -39,9 +39,9 @@ export interface StaffMemberUpdate_staffUpdate_user { firstName: string; isActive: boolean; lastName: string; - avatar: StaffMemberUpdate_staffUpdate_user_avatar | null; permissionGroups: (StaffMemberUpdate_staffUpdate_user_permissionGroups | null)[] | null; userPermissions: (StaffMemberUpdate_staffUpdate_user_userPermissions | null)[] | null; + avatar: StaffMemberUpdate_staffUpdate_user_avatar | null; } export interface StaffMemberUpdate_staffUpdate { diff --git a/src/staff/urls.ts b/src/staff/urls.ts index 35ce6c2a4..213d1dc51 100644 --- a/src/staff/urls.ts +++ b/src/staff/urls.ts @@ -7,8 +7,8 @@ import { Dialog, Filters, Pagination, - TabActionDialog, - Sort + Sort, + TabActionDialog } from "../types"; const staffSection = "/staff/"; diff --git a/src/staff/utils.ts b/src/staff/utils.ts index b2b870d3f..a2d427a48 100644 --- a/src/staff/utils.ts +++ b/src/staff/utils.ts @@ -1,7 +1,7 @@ import difference from "lodash-es/difference"; -import { StaffMemberDetails_user } from "./types/StaffMemberDetails"; import { StaffDetailsFormData } from "./components/StaffDetailsPage"; +import { StaffMemberDetails_user } from "./types/StaffMemberDetails"; /** * Return lists of groups which have to be added and removed from user. diff --git a/src/staff/views/StaffDetails.tsx b/src/staff/views/StaffDetails.tsx index 73a88b6f8..9c571fbe8 100644 --- a/src/staff/views/StaffDetails.tsx +++ b/src/staff/views/StaffDetails.tsx @@ -1,6 +1,3 @@ -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - import DialogContentText from "@material-ui/core/DialogContentText"; import ActionDialog from "@saleor/components/ActionDialog"; import NotFoundPage from "@saleor/components/NotFoundPage"; @@ -10,8 +7,10 @@ import useNavigator from "@saleor/hooks/useNavigator"; import useNotifier from "@saleor/hooks/useNotifier"; import useUser from "@saleor/hooks/useUser"; import { commonMessages } from "@saleor/intl"; -import { maybe, getStringOrPlaceholder } from "@saleor/misc"; +import { getStringOrPlaceholder, maybe } from "@saleor/misc"; import usePermissionGroupSearch from "@saleor/searches/usePermissionGroupSearch"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; import StaffDetailsPage from "../components/StaffDetailsPage/StaffDetailsPage"; import StaffPasswordResetDialog from "../components/StaffPasswordResetDialog"; @@ -57,6 +56,7 @@ export const StaffDetails: React.FC = ({ id, params }) => { const handleChangePassword = (data: ChangeStaffPassword) => { if (data.passwordChange.errors.length === 0) { notify({ + status: "success", text: intl.formatMessage(commonMessages.savedChanges) }); closeModal(); @@ -88,6 +88,7 @@ export const StaffDetails: React.FC = ({ id, params }) => { const handleStaffMemberUpdate = (data: StaffMemberUpdate) => { if (!maybe(() => data.staffUpdate.errors.length !== 0)) { notify({ + status: "success", text: intl.formatMessage(commonMessages.savedChanges) }); } @@ -95,6 +96,7 @@ export const StaffDetails: React.FC = ({ id, params }) => { const handleStaffMemberDelete = (data: StaffMemberDelete) => { if (!maybe(() => data.staffDelete.errors.length !== 0)) { notify({ + status: "success", text: intl.formatMessage(commonMessages.savedChanges) }); navigate(staffListUrl()); @@ -103,6 +105,7 @@ export const StaffDetails: React.FC = ({ id, params }) => { const handleStaffMemberAvatarUpdate = (data: StaffAvatarUpdate) => { if (!maybe(() => data.userAvatarUpdate.errors.length !== 0)) { notify({ + status: "success", text: intl.formatMessage(commonMessages.savedChanges) }); } @@ -110,6 +113,7 @@ export const StaffDetails: React.FC = ({ id, params }) => { const handleStaffMemberAvatarDelete = (data: StaffAvatarDelete) => { if (!maybe(() => data.userAvatarDelete.errors.length !== 0)) { notify({ + status: "success", text: intl.formatMessage(commonMessages.savedChanges) }); navigate(staffMemberDetailsUrl(id)); diff --git a/src/staff/views/StaffList/StaffList.tsx b/src/staff/views/StaffList/StaffList.tsx index 86a5c3c71..5b1c6ce45 100644 --- a/src/staff/views/StaffList/StaffList.tsx +++ b/src/staff/views/StaffList/StaffList.tsx @@ -1,7 +1,3 @@ -import React from "react"; -import { useIntl } from "react-intl"; -import urlJoin from "url-join"; - import { newPasswordUrl } from "@saleor/auth/urls"; import DeleteFilterTabDialog from "@saleor/components/DeleteFilterTabDialog"; import SaveFilterTabDialog, { @@ -17,13 +13,16 @@ import usePaginator, { } from "@saleor/hooks/usePaginator"; import useShop from "@saleor/hooks/useShop"; import { commonMessages } from "@saleor/intl"; +import { getStringOrPlaceholder } from "@saleor/misc"; import usePermissionGroupSearch from "@saleor/searches/usePermissionGroupSearch"; import { ListViews } from "@saleor/types"; import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; import createFilterHandlers from "@saleor/utils/handlers/filterHandlers"; import createSortHandler from "@saleor/utils/handlers/sortHandler"; import { getSortParams } from "@saleor/utils/sort"; -import { getStringOrPlaceholder } from "@saleor/misc"; +import React from "react"; +import { useIntl } from "react-intl"; +import urlJoin from "url-join"; import StaffAddMemberDialog, { AddMemberFormData @@ -134,6 +133,7 @@ export const StaffList: React.FC = ({ params }) => { const handleStaffMemberAddSuccess = (data: StaffMemberAdd) => { if (data.staffCreate.errors.length === 0) { notify({ + status: "success", text: intl.formatMessage(commonMessages.savedChanges) }); navigate(staffMemberDetailsUrl(data.staffCreate.user.id)); diff --git a/src/staff/views/StaffList/filters.test.ts b/src/staff/views/StaffList/filters.test.ts index 32a812b2d..40739ac1b 100644 --- a/src/staff/views/StaffList/filters.test.ts +++ b/src/staff/views/StaffList/filters.test.ts @@ -1,13 +1,13 @@ -import { createIntl } from "react-intl"; -import { stringify as stringifyQs } from "qs"; - -import { StaffListUrlFilters } from "@saleor/staff/urls"; import { createFilterStructure } from "@saleor/staff/components/StaffListPage"; +import { StaffListUrlFilters } from "@saleor/staff/urls"; +import { StaffMemberStatus } from "@saleor/types/globalTypes"; import { getFilterQueryParams } from "@saleor/utils/filters"; import { getExistingKeys, setFilterOptsStatus } from "@test/filters"; import { config } from "@test/intl"; -import { StaffMemberStatus } from "@saleor/types/globalTypes"; -import { getFilterVariables, getFilterQueryParam } from "./filters"; +import { stringify as stringifyQs } from "qs"; +import { createIntl } from "react-intl"; + +import { getFilterQueryParam, getFilterVariables } from "./filters"; describe("Filtering query params", () => { it("should be empty object if no params given", () => { diff --git a/src/staff/views/StaffList/filters.ts b/src/staff/views/StaffList/filters.ts index cfb46d078..d38f80090 100644 --- a/src/staff/views/StaffList/filters.ts +++ b/src/staff/views/StaffList/filters.ts @@ -1,10 +1,11 @@ -import { StaffUserInput, StaffMemberStatus } from "@saleor/types/globalTypes"; -import { maybe, findValueInEnum } from "@saleor/misc"; import { IFilterElement } from "@saleor/components/Filter"; +import { findValueInEnum, maybe } from "@saleor/misc"; import { - StaffListFilterOpts, - StaffFilterKeys + StaffFilterKeys, + StaffListFilterOpts } from "@saleor/staff/components/StaffListPage"; +import { StaffMemberStatus, StaffUserInput } from "@saleor/types/globalTypes"; + import { createFilterTabUtils, createFilterUtils, diff --git a/src/storybook/Decorator.tsx b/src/storybook/Decorator.tsx index c8f85751b..66e548747 100644 --- a/src/storybook/Decorator.tsx +++ b/src/storybook/Decorator.tsx @@ -1,9 +1,9 @@ +import { Locale, RawLocaleProvider } from "@saleor/components/Locale"; import React from "react"; import { IntlProvider } from "react-intl"; -import { Locale, RawLocaleProvider } from "@saleor/components/Locale"; import { Provider as DateProvider } from "../components/Date/DateContext"; -import { MessageManager } from "../components/messages"; +import MessageManagerProvider from "../components/messages"; import ThemeProvider from "../components/Theme"; import { TimezoneProvider } from "../components/Timezone"; @@ -18,7 +18,7 @@ export const Decorator = storyFn => ( - +
( > {storyFn()}
-
+
diff --git a/src/storybook/__snapshots__/Stories.test.ts.snap b/src/storybook/__snapshots__/Stories.test.ts.snap index b2c87ea14..7a91d3b8a 100644 --- a/src/storybook/__snapshots__/Stories.test.ts.snap +++ b/src/storybook/__snapshots__/Stories.test.ts.snap @@ -48,13 +48,191 @@ exports[`Storyshots Discounts / Select countries default 1`] = ` /> `; +exports[`Storyshots Generics / Accordion default 1`] = ` +
+
+
+
+
+
+ Title +
+
+ +
+
+
+
+
+
+`; + +exports[`Storyshots Generics / Accordion opened 1`] = ` +
+
+
+
+
+
+ Title +
+
+ +
+
+
+
+ Content +
+
+
+
+
+`; + +exports[`Storyshots Generics / Accordion with quick peek 1`] = ` +
+
+
+
+
+
+ Title +
+
+ +
+
+
+
+ Quick Peek +
+
+
+
+
+`; + exports[`Storyshots Generics / Account Permission Groups Widget default 1`] = `
`; +exports[`Storyshots Generics / AvailabilityCard default 1`] = ` +
+
+
+ + Visibility + +
+
+
+
+
+
+
+ + +
+
+
+
+
+ + +
+
+
+ Set availability date +
+
+ +
+
+
+
+`; + exports[`Storyshots Generics / Card menu default 1`] = `
- + + + + +
@@ -1179,20 +1722,39 @@ exports[`Storyshots Generics / Checkbox disabled 1`] = `
- + + + + +
@@ -1210,18 +1772,37 @@ exports[`Storyshots Generics / Checkbox interactive 1`] = ` class="MuiCardContent-root-id" >
- + + + + +
@@ -1239,18 +1820,37 @@ exports[`Storyshots Generics / Checkbox unchecked 1`] = `
- + + + + +
@@ -1267,18 +1867,44 @@ exports[`Storyshots Generics / Checkbox undeterminate 1`] = `
- + + + + +
@@ -1690,6 +2316,7 @@ exports[`Storyshots Generics / Filter default 1`] = `
+ + + + + @@ -1817,6 +2472,9 @@ exports[`Storyshots Generics / Filter default 1`] = `
- + + + + + @@ -1910,17 +2592,38 @@ exports[`Storyshots Generics / Filter default 1`] = ` @@ -1934,17 +2637,44 @@ exports[`Storyshots Generics / Filter default 1`] = ` @@ -1957,6 +2687,8 @@ exports[`Storyshots Generics / Filter default 1`] = ` >
+ + + + + @@ -2275,6 +3042,9 @@ exports[`Storyshots Generics / Filter interactive 1`] = `
- + + + + + @@ -2368,17 +3162,38 @@ exports[`Storyshots Generics / Filter interactive 1`] = ` @@ -2392,17 +3207,44 @@ exports[`Storyshots Generics / Filter interactive 1`] = ` @@ -2415,6 +3257,8 @@ exports[`Storyshots Generics / Filter interactive 1`] = ` >
`; +exports[`Storyshots Generics / Global messages with action 1`] = ` +
+
+
+ +
+
+
+`; + +exports[`Storyshots Generics / Global messages with error status 1`] = ` +
+
+
+ +
+
+
+`; + +exports[`Storyshots Generics / Global messages with expandText 1`] = ` +
+
+
+ +
+
+
+`; + +exports[`Storyshots Generics / Global messages with success status 1`] = ` +
+
+
+ +
+
+
+`; + exports[`Storyshots Generics / Global messages with undo action 1`] = `
`; +exports[`Storyshots Generics / Global messages with warning status 1`] = ` +
+
+
+ +
+
+
+`; + exports[`Storyshots Generics / Link with choices default 1`] = `
`; +exports[`Storyshots Generics / Metadata default 1`] = ` +
+
+
+ + Metadata + +
+
+
+
+ + + + + + + + + + + + +