From 180e3c56e617881be630328192a5020603f8e614 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20=C5=BBuraw?= <9116238+krzysztofzuraw@users.noreply.github.com> Date: Thu, 4 May 2023 10:57:18 +0200 Subject: [PATCH] Migrate product create page to new MacawUI (#3372) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Michał Droń Co-authored-by: timur Co-authored-by: wojteknowacki --- cypress/e2e/configuration/customer.js | 6 +- .../e2e/configuration/warehouses/warehouse.js | 4 +- cypress/e2e/pages/pages.js | 4 +- .../updatingProductsWithoutSku.js | 1 - .../channels/available-channels-form.js | 2 +- cypress/elements/pages/page-details.js | 2 +- .../customCommands/basicOperations/index.js | 2 +- cypress/support/pages/attributesPage.js | 14 +- .../support/pages/catalog/collectionsPage.js | 1 + .../pages/catalog/products/VariantsPage.js | 5 +- .../catalog/products/productDetailsPage.js | 1 + .../catalog/products/productsListPage.js | 6 +- cypress/support/pages/shippingMethodPage.js | 6 +- cypress/support/pages/translationsPage.js | 11 +- locale/defaultMessages.json | 11 +- package-lock.json | 61 +- package.json | 2 +- .../AttributePage/AttributePage.tsx | 2 +- .../CategoryCreatePage/CategoryCreatePage.tsx | 4 +- .../CategoryUpdatePage/CategoryUpdatePage.tsx | 4 +- .../CollectionCreatePage.tsx | 4 +- .../CollectionDetailsPage.tsx | 4 +- .../TopNav/Menu.tsx} | 5 +- .../AppLayout/TopNav/{TopNav.tsx => Root.tsx} | 2 +- src/components/AppLayout/TopNav/index.ts | 7 +- .../Attributes/AttributeListItem.tsx | 33 + src/components/Attributes/AttributeRow.tsx | 129 ++-- src/components/Attributes/Attributes.tsx | 166 ++---- .../Attributes/BasicAttributeRow.tsx | 96 +-- .../Attributes/ExtendedAttributeRow.tsx | 44 +- src/components/Attributes/SwatchRow.tsx | 8 +- src/components/Attributes/index.ts | 1 - src/components/Attributes/styles.ts | 66 -- src/components/Attributes/types.ts | 2 +- src/components/Card/Content.tsx | 8 + src/components/Card/Root.tsx | 8 + src/components/Card/Title.tsx | 8 + src/components/Card/index.ts | 5 + .../ChannelAvailabilityItemContent.tsx | 238 ++++---- .../ChannelAvailabilityItemWrapper.tsx | 98 +-- .../ChannelsAvailabilityCard/Channel/index.ts | 2 + .../ChannelsAvailabilityCard.tsx | 28 +- .../ChannelsAvailabilityCardWrapper.tsx | 89 ++- .../ChannelsAvailabilityCard/styles.ts | 86 --- .../DateTimeField/DateTimeField.tsx | 18 +- src/components/DateTimeField/styles.ts | 28 - .../FileUploadField/FileUploadField.tsx | 84 +-- src/components/Hr.tsx | 39 +- src/components/Metadata/Metadata.test.tsx | 2 +- src/components/Metadata/Metadata.tsx | 14 +- src/components/Metadata/MetadataCard.tsx | 218 ++++--- src/components/Metadata/index.ts | 2 - src/components/Metadata/styles.ts | 79 --- src/components/Metadata/utils.ts | 5 +- .../RichTextEditor/RichTextEditor.tsx | 25 +- src/components/RichTextEditor/styles.ts | 78 ++- src/components/SeoForm/SeoForm.tsx | 217 +++---- src/components/SeoForm/index.ts | 1 - .../SingleAutocompleteSelectField.tsx | 20 +- src/components/TopNavMenu/index.ts | 1 - .../CustomerDetailsPage.tsx | 2 +- .../SaleCreatePage/SaleCreatePage.tsx | 2 +- .../SaleDetailsPage/SaleDetailsPage.tsx | 2 +- .../VoucherCreatePage/VoucherCreatePage.tsx | 2 +- .../VoucherDetailsPage/VoucherDetailsPage.tsx | 2 +- .../GiftCardUpdate/GiftCardUpdatePage.tsx | 2 +- .../OrderDetailsPage/OrderDetailsPage.tsx | 2 +- .../components/OrderPayment/OrderPayment.tsx | 4 +- .../OrderPaymentOrTransaction.test.tsx | 1 + .../OrderPaymentSummaryCard.tsx | 4 +- .../PageTypeCreatePage/PageTypeCreatePage.tsx | 2 +- .../PageTypeDetailsPage.tsx | 2 +- .../PageDetailsPage/PageDetailsPage.tsx | 6 +- .../ProductTypeCreatePage.tsx | 2 +- .../ProductTypeDetailsPage.tsx | 2 +- .../ProductCreatePage/ProductCreatePage.tsx | 21 +- .../ProductDetailsForm/ProductDetailsForm.tsx | 64 +- .../components/ProductDetailsForm/index.ts | 1 - .../ProductExternalMediaDialog.tsx | 24 +- .../ProductListPage/ProductListPage.tsx | 3 +- .../components/ProductMedia/ProductMedia.tsx | 293 ++++----- .../components/ProductMedia/messages.ts | 24 + .../ProductMediaPopper/ProductMediaPopper.tsx | 78 --- .../ProductOrganization.tsx | 104 ++-- .../components/ProductOrganization/index.ts | 1 - .../ProductShipping/ProductShipping.tsx | 75 +-- .../components/ProductShipping/index.ts | 1 + .../ProductStocks/ProductStocks.tsx | 564 +++++++++--------- .../components/ProductStocks/index.ts | 1 - .../components/ProductStocks/styles.ts | 107 ---- .../ProductUpdatePage.stories.tsx | 1 - .../ProductUpdatePage.test.tsx | 1 - .../ProductUpdatePage/ProductUpdatePage.tsx | 20 +- .../ProductVariantCreatePage.tsx | 11 +- .../ProductVariantPage/ProductVariantPage.tsx | 11 +- .../ProductVariantPrice.tsx | 149 ++--- .../components/ProductVariantPrice/index.ts | 1 - src/products/utils/data.ts | 2 +- .../views/ProductUpdate/ProductUpdate.tsx | 87 ++- .../ShippingZoneDetailsPage.tsx | 2 +- .../ShippingZoneRatesPage.tsx | 2 +- .../pages/TaxClassesPage/TaxClassesPage.tsx | 2 +- 102 files changed, 1589 insertions(+), 2215 deletions(-) rename src/components/{TopNavMenu/TopNavMenu.tsx => AppLayout/TopNav/Menu.tsx} (93%) rename src/components/AppLayout/TopNav/{TopNav.tsx => Root.tsx} (94%) create mode 100644 src/components/Attributes/AttributeListItem.tsx create mode 100644 src/components/Card/Content.tsx create mode 100644 src/components/Card/Root.tsx create mode 100644 src/components/Card/Title.tsx create mode 100644 src/components/Card/index.ts create mode 100644 src/components/ChannelsAvailabilityCard/Channel/index.ts delete mode 100644 src/components/ChannelsAvailabilityCard/styles.ts delete mode 100644 src/components/DateTimeField/styles.ts delete mode 100644 src/components/Metadata/styles.ts delete mode 100644 src/components/TopNavMenu/index.ts create mode 100644 src/products/components/ProductMedia/messages.ts delete mode 100644 src/products/components/ProductMediaPopper/ProductMediaPopper.tsx delete mode 100644 src/products/components/ProductStocks/styles.ts diff --git a/cypress/e2e/configuration/customer.js b/cypress/e2e/configuration/customer.js index bd7189655..d93bf7993 100644 --- a/cypress/e2e/configuration/customer.js +++ b/cypress/e2e/configuration/customer.js @@ -263,13 +263,15 @@ describe("Tests for customer", () => { createCustomer(email, randomName, address, true).then(({ user }) => { cy.visit(customerDetailsUrl(user.id)) .get(CUSTOMER_DETAILS_SELECTORS.nameInput) - .clearAndType(updatedName) + .clear() + .type(updatedName) .get(CUSTOMER_DETAILS_SELECTORS.lastNameInput) .clearAndType(updatedName) .get(CUSTOMER_DETAILS_SELECTORS.noteInput) .clearAndType(updatedName) .get(CUSTOMER_DETAILS_SELECTORS.emailInput) - .clearAndType(`${updatedName}@example.com`) + .clear() + .type(`${updatedName}@example.com`) .addAliasToGraphRequest("UpdateCustomer") .get(BUTTON_SELECTORS.confirm) .click() diff --git a/cypress/e2e/configuration/warehouses/warehouse.js b/cypress/e2e/configuration/warehouses/warehouse.js index 62b877cc3..c0d54443a 100644 --- a/cypress/e2e/configuration/warehouses/warehouse.js +++ b/cypress/e2e/configuration/warehouses/warehouse.js @@ -193,7 +193,9 @@ describe("As an admin I want to manage warehouses", () => { warehouse = warehouseResp; cy.visit(warehouseDetailsUrl(warehouse.id)) .get(WAREHOUSES_DETAILS.nameInput) - .clearAndType(updatedName) + .clear() + .type(updatedName) + // .clearAndType(updatedName) .fillUpBasicAddress(secondUsAddress) .addAliasToGraphRequest("WarehouseUpdate") .get(BUTTON_SELECTORS.confirm) diff --git a/cypress/e2e/pages/pages.js b/cypress/e2e/pages/pages.js index e33992de1..5e3447edb 100644 --- a/cypress/e2e/pages/pages.js +++ b/cypress/e2e/pages/pages.js @@ -162,7 +162,9 @@ describe("Tests for pages", () => { .then(({ page }) => { cy.visit(pageDetailsUrl(page.id)) .get(PAGE_DETAILS_SELECTORS.nameInput) - .clearAndType(updatedName) + .clear() + .type(updatedName) + // .clearAndType(updatedName) .get(PAGE_DETAILS_SELECTORS.isNotPublishedCheckbox) .click() .addAliasToGraphRequest("PageUpdate") diff --git a/cypress/e2e/products/productsWithoutSku/updatingProductsWithoutSku.js b/cypress/e2e/products/productsWithoutSku/updatingProductsWithoutSku.js index 11b55da65..a8368626c 100644 --- a/cypress/e2e/products/productsWithoutSku/updatingProductsWithoutSku.js +++ b/cypress/e2e/products/productsWithoutSku/updatingProductsWithoutSku.js @@ -192,7 +192,6 @@ describe("Updating products without sku", () => { .get(SHARED_ELEMENTS.skeleton) .should("not.exist") .get(VARIANTS_SELECTORS.skuTextField) - .find("input") .clear() .addAliasToGraphRequest("VariantUpdate") .get(VARIANTS_SELECTORS.variantNameInput) diff --git a/cypress/elements/channels/available-channels-form.js b/cypress/elements/channels/available-channels-form.js index 075a086e0..bb91586a7 100644 --- a/cypress/elements/channels/available-channels-form.js +++ b/cypress/elements/channels/available-channels-form.js @@ -1,7 +1,7 @@ export const AVAILABLE_CHANNELS_FORM = { manageChannelsButton: "[data-test-id='channels-availability-manage-button']", assignedChannels: "[data-test-id='expand-icon']", - publishedRadioButtons: "[name*='isPublished']", + publishedRadioButtons: "[name*='isPublished'] > ", availableForPurchaseRadioButtons: "[name*='isAvailableForPurchase']", radioButtonsValueTrue: "[value='true']", radioButtonsValueFalse: "[value='false']", diff --git a/cypress/elements/pages/page-details.js b/cypress/elements/pages/page-details.js index c2085b0a0..5e23207c4 100644 --- a/cypress/elements/pages/page-details.js +++ b/cypress/elements/pages/page-details.js @@ -6,6 +6,6 @@ export const PAGE_DETAILS_SELECTORS = { isNotPublishedCheckbox: '[name="isPublished"][value=false]', uploadFileButton: '[data-test-id="button-upload-file"]', richTextEditorAttributeValue: '[class*="ce-paragraph"]', - booleanAttributeValueCheckbox: '[name*="attribute:"][type="checkbox"]', + booleanAttributeValueCheckbox: '[role="checkbox"]', numericAttributeValueInput: '[name*="attribute:"]', }; diff --git a/cypress/support/customCommands/basicOperations/index.js b/cypress/support/customCommands/basicOperations/index.js index 857521095..90707baa1 100644 --- a/cypress/support/customCommands/basicOperations/index.js +++ b/cypress/support/customCommands/basicOperations/index.js @@ -10,7 +10,7 @@ Cypress.Commands.add("clearAndType", { prevSubject: true }, (subject, text) => { if (subject.find("[contenteditable]").length > 0) { cy.wrap(subject).find("[contenteditable]").clear().type(text); } else { - cy.wrap(subject).clear().type(text); + cy.wrap(subject).clear({ force: true }).type(text); } }); }); diff --git a/cypress/support/pages/attributesPage.js b/cypress/support/pages/attributesPage.js index fa87615c2..ddbf4a19b 100644 --- a/cypress/support/pages/attributesPage.js +++ b/cypress/support/pages/attributesPage.js @@ -9,7 +9,7 @@ export function createAttributeWithInputType({ entityType, numericSystemType, swatchImage, - valueRequired = true + valueRequired = true, }) { fillUpAttributeCreateFields({ name, attributeType, valueRequired }); if ( @@ -34,7 +34,7 @@ export function createAttributeWithInputType({ export function fillUpAttributeCreateFields({ name, attributeType, - valueRequired + valueRequired, }) { fillUpAttributeNameAndCode(name); cy.get(ATTRIBUTES_DETAILS.inputTypeSelect) @@ -49,9 +49,11 @@ export function fillUpAttributeCreateFields({ export function fillUpAttributeNameAndCode(name, code = name) { return cy .get(ATTRIBUTES_DETAILS.nameInput) - .clearAndType(name) + .clear() + .type(name) .get(ATTRIBUTES_DETAILS.codeInput) - .clearAndType(code); + .clear() + .type(code); } export function saveAttribute() { @@ -63,9 +65,7 @@ export function saveAttribute() { } export function submitAttribute() { - cy.get(BUTTON_SELECTORS.confirm) - .click() - .confirmationMessageShouldDisappear(); + cy.get(BUTTON_SELECTORS.confirm).click().confirmationMessageShouldDisappear(); } export function addSingleValue(valueName) { diff --git a/cypress/support/pages/catalog/collectionsPage.js b/cypress/support/pages/catalog/collectionsPage.js index 3b7f6150b..01267fc7d 100644 --- a/cypress/support/pages/catalog/collectionsPage.js +++ b/cypress/support/pages/catalog/collectionsPage.js @@ -25,6 +25,7 @@ export function createCollection(collectionName, isPublished, channel) { .get(AVAILABLE_CHANNELS_FORM.availableChannel) .click() .get(`${AVAILABLE_CHANNELS_FORM.publishedRadioButtons}${publishedSelector}`) + .first() .click(); return saveCollection().its("response.body.data.collectionCreate.collection"); } diff --git a/cypress/support/pages/catalog/products/VariantsPage.js b/cypress/support/pages/catalog/products/VariantsPage.js index 2db5c7db6..db2d1ca31 100644 --- a/cypress/support/pages/catalog/products/VariantsPage.js +++ b/cypress/support/pages/catalog/products/VariantsPage.js @@ -35,7 +35,6 @@ export function createVariant({ cy.get(VARIANTS_SELECTORS.saveButton) .click() .get(VARIANTS_SELECTORS.skuTextField) - .find("input") .should("be.enabled") .get(BUTTON_SELECTORS.back) .click() @@ -86,7 +85,7 @@ export function fillUpVariantDetails({ cy.get(VARIANTS_SELECTORS.variantNameInput).type(variantName); } if (sku) { - cy.get(VARIANTS_SELECTORS.skuTextField).type(sku); + cy.get(VARIANTS_SELECTORS.skuTextField).click({ force: true }).type(sku); } if (warehouseName) { cy.get(VARIANTS_SELECTORS.addWarehouseButton).click(); @@ -114,7 +113,7 @@ export function fillUpVariantAttributeAndSku({ attributeName, sku }) { .contains(attributeName) .click(); if (sku) { - cy.get(VARIANTS_SELECTORS.skuTextField).type(sku); + cy.get(VARIANTS_SELECTORS.skuTextField).click({ force: true }).type(sku); } } diff --git a/cypress/support/pages/catalog/products/productDetailsPage.js b/cypress/support/pages/catalog/products/productDetailsPage.js index 933a460fc..8bbc1c2ea 100644 --- a/cypress/support/pages/catalog/products/productDetailsPage.js +++ b/cypress/support/pages/catalog/products/productDetailsPage.js @@ -37,6 +37,7 @@ function updateProductManageInChannel(productUrl, manageSelector) { .get(AVAILABLE_CHANNELS_FORM.assignedChannels) .click() .get(manageSelector) + .first() .click() .waitForProgressBarToNotBeVisible() .addAliasToGraphRequest("ProductChannelListingUpdate") diff --git a/cypress/support/pages/catalog/products/productsListPage.js b/cypress/support/pages/catalog/products/productsListPage.js index 3b8119643..50a256a9f 100644 --- a/cypress/support/pages/catalog/products/productsListPage.js +++ b/cypress/support/pages/catalog/products/productsListPage.js @@ -80,7 +80,9 @@ export function selectProductsOutOfStock() { } export function selectFilterBy(filter) { - return showFilters().get(PRODUCTS_LIST.filters.filterBy[filter]).click(); + return showFilters() + .get(PRODUCTS_LIST.filters.filterBy[filter]) + .click({ timeout: 1000, force: true }); } export function selectFilterByAttribute(attributeSlug) { @@ -106,6 +108,8 @@ export function selectChannel(channelSlug) { export function submitFilters() { cy.addAliasToGraphRequest("ProductList") .get(BUTTON_SELECTORS.submit) + .scrollIntoView() + .should("be.visible") .click() .waitForRequestAndCheckIfNoErrors("@ProductList") .get(PRODUCTS_LIST.emptyProductRow) diff --git a/cypress/support/pages/shippingMethodPage.js b/cypress/support/pages/shippingMethodPage.js index a7fdf7669..c618cf161 100644 --- a/cypress/support/pages/shippingMethodPage.js +++ b/cypress/support/pages/shippingMethodPage.js @@ -26,9 +26,11 @@ export function fillUpShippingZoneData({ channelName, }) { cy.get(SHIPPING_ZONE_DETAILS.nameInput) - .clearAndType(shippingName) + .clear() + .type(shippingName) .get(SHIPPING_ZONE_DETAILS.descriptionInput) - .clearAndType(shippingName) + .clear() + .type(shippingName) .get(BUTTON_SELECTORS.confirm) .click() .confirmationMessageShouldAppear() diff --git a/cypress/support/pages/translationsPage.js b/cypress/support/pages/translationsPage.js index a5fea7d6d..7e7894e31 100644 --- a/cypress/support/pages/translationsPage.js +++ b/cypress/support/pages/translationsPage.js @@ -21,7 +21,9 @@ export function updateTranslationToCategory({ .get(SHARED_ELEMENTS.skeleton) .should("not.exist") .get(ELEMENT_TRANSLATION.translationInputField) - .clearAndType(translatedName) + .clear() + .type(translatedName) + // .clearAndType(translatedName) .get(BUTTON_SELECTORS.confirm) .click() .confirmationMessageShouldDisappear() @@ -37,14 +39,17 @@ export function updateTranslationToCategory({ .get(ELEMENT_TRANSLATION.editSeoTitleButton) .click() .get(ELEMENT_TRANSLATION.translationInputField) - .clearAndType(translatedSeoTitle) + .clear() + .type(translatedSeoTitle) .get(BUTTON_SELECTORS.confirm) .click() .confirmationMessageShouldDisappear() .get(ELEMENT_TRANSLATION.editSeoDescriptionButton) .click() .get(ELEMENT_TRANSLATION.translationInputField) - .clearAndType(translatedSeoDescription) + .clear() + .type(translatedSeoDescription) + // .clearAndType(translatedSeoDescription) .get(BUTTON_SELECTORS.confirm) .click() .confirmationMessageShouldDisappear(); diff --git a/locale/defaultMessages.json b/locale/defaultMessages.json index 972bcf116..7fef4cc59 100644 --- a/locale/defaultMessages.json +++ b/locale/defaultMessages.json @@ -1614,6 +1614,10 @@ "context": "area units type", "string": "Area" }, + "AD1PlC": { + "context": "channels availability text", + "string": "In {selectedChannelsCount} out of {allChannelsCount, plural, one {# channel} other {# channels}}" + }, "ADTNND": { "context": "product type", "string": "Physical" @@ -8100,10 +8104,6 @@ "context": "voucher discount type", "string": "Fixed Amount" }, - "vY2lpx": { - "context": "channels availability text", - "string": "Available at {selectedChannelsCount} out of {allChannelsCount, plural, one {# channel} other {# channels}}" - }, "vZMs8f": { "context": "default product variant indicator", "string": "Default" @@ -8497,6 +8497,9 @@ "context": "voucher requirements, header", "string": "Minimum Requirements" }, + "yi1HSj": { + "string": "({numberOfCharacters} of {maxCharacters} characters)" + }, "ymo+cm": { "context": "voucher discount", "string": "All products" diff --git a/package-lock.json b/package-lock.json index 6b9db5268..db8c2a0f1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,7 +27,7 @@ "@material-ui/lab": "^4.0.0-alpha.61", "@material-ui/styles": "^4.11.4", "@reach/auto-id": "^0.16.0", - "@saleor/macaw-ui": "0.8.0-pre.68", + "@saleor/macaw-ui": "0.8.0-pre.73", "@saleor/sdk": "^0.5.0", "@sentry/react": "^6.0.0", "@types/faker": "^5.1.6", @@ -7976,9 +7976,9 @@ } }, "node_modules/@saleor/macaw-ui": { - "version": "0.8.0-pre.68", - "resolved": "https://registry.npmjs.org/@saleor/macaw-ui/-/macaw-ui-0.8.0-pre.68.tgz", - "integrity": "sha512-4P1Ec4dpNk0MyejtosBZLd0EHl3pOBY1aFt09/R0Qpdiyu2+O7Jh/O1pwG+cpaG7J6hcrtMGsfYfLl24PwIAAA==", + "version": "0.8.0-pre.73", + "resolved": "https://registry.npmjs.org/@saleor/macaw-ui/-/macaw-ui-0.8.0-pre.73.tgz", + "integrity": "sha512-7+bFDATTV8ZjX3dpU20z5QMUMSZHoNgidLWEzUBkHWk6EgiDf+V5Mn2t8Eexd34uLOIKCQ0j4f/mVG+slRsj/w==", "dependencies": { "@dessert-box/react": "^0.4.0", "@floating-ui/react-dom-interactions": "^0.5.0", @@ -7992,14 +7992,17 @@ "@radix-ui/react-select": "^1.2.0", "@radix-ui/react-toggle": "^1.0.2", "@radix-ui/react-tooltip": "^1.0.5", + "@vanilla-extract/css-utils": "^0.1.3", "clsx": "^1.1.1", "downshift": "^6.1.7", + "downshift7": "npm:downshift@7.6.0", "lodash": "^4.17.21", "lodash-es": "^4.17.21", "react-inlinesvg": "^3.0.1" }, "engines": { - "node": ">=16 <19" + "node": ">=16 <19", + "pnpm": ">=8" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0", @@ -16986,6 +16989,27 @@ "react": ">=16.12.0" } }, + "node_modules/downshift7": { + "name": "downshift", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/downshift/-/downshift-7.6.0.tgz", + "integrity": "sha512-VSoTVynTAsabou/hbZ6HJHUVhtBiVOjQoBsCPcQq5eAROIGP+9XKMp9asAKQ3cEcUP4oe0fFdD2pziUjhFY33Q==", + "dependencies": { + "@babel/runtime": "^7.14.8", + "compute-scroll-into-view": "^2.0.4", + "prop-types": "^15.7.2", + "react-is": "^17.0.2", + "tslib": "^2.3.0" + }, + "peerDependencies": { + "react": ">=16.12.0" + } + }, + "node_modules/downshift7/node_modules/compute-scroll-into-view": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-2.0.4.tgz", + "integrity": "sha512-y/ZA3BGnxoM/QHHQ2Uy49CLtnWPbt4tTPpEEZiEmmiWBFKjej7nEyH8Ryz54jH0MLXflUYA3Er2zUxPSJu5R+g==" + }, "node_modules/duplexer": { "version": "0.1.2", "devOptional": true, @@ -43347,9 +43371,9 @@ } }, "@saleor/macaw-ui": { - "version": "0.8.0-pre.68", - "resolved": "https://registry.npmjs.org/@saleor/macaw-ui/-/macaw-ui-0.8.0-pre.68.tgz", - "integrity": "sha512-4P1Ec4dpNk0MyejtosBZLd0EHl3pOBY1aFt09/R0Qpdiyu2+O7Jh/O1pwG+cpaG7J6hcrtMGsfYfLl24PwIAAA==", + "version": "0.8.0-pre.73", + "resolved": "https://registry.npmjs.org/@saleor/macaw-ui/-/macaw-ui-0.8.0-pre.73.tgz", + "integrity": "sha512-7+bFDATTV8ZjX3dpU20z5QMUMSZHoNgidLWEzUBkHWk6EgiDf+V5Mn2t8Eexd34uLOIKCQ0j4f/mVG+slRsj/w==", "requires": { "@dessert-box/react": "^0.4.0", "@floating-ui/react-dom-interactions": "^0.5.0", @@ -43363,8 +43387,10 @@ "@radix-ui/react-select": "^1.2.0", "@radix-ui/react-toggle": "^1.0.2", "@radix-ui/react-tooltip": "^1.0.5", + "@vanilla-extract/css-utils": "^0.1.3", "clsx": "^1.1.1", "downshift": "^6.1.7", + "downshift7": "npm:downshift@7.6.0", "lodash": "^4.17.21", "lodash-es": "^4.17.21", "react-inlinesvg": "^3.0.1" @@ -49697,6 +49723,25 @@ "tslib": "^2.3.0" } }, + "downshift7": { + "version": "npm:downshift@7.6.0", + "resolved": "https://registry.npmjs.org/downshift/-/downshift-7.6.0.tgz", + "integrity": "sha512-VSoTVynTAsabou/hbZ6HJHUVhtBiVOjQoBsCPcQq5eAROIGP+9XKMp9asAKQ3cEcUP4oe0fFdD2pziUjhFY33Q==", + "requires": { + "@babel/runtime": "^7.14.8", + "compute-scroll-into-view": "^2.0.4", + "prop-types": "^15.7.2", + "react-is": "^17.0.2", + "tslib": "^2.3.0" + }, + "dependencies": { + "compute-scroll-into-view": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-2.0.4.tgz", + "integrity": "sha512-y/ZA3BGnxoM/QHHQ2Uy49CLtnWPbt4tTPpEEZiEmmiWBFKjej7nEyH8Ryz54jH0MLXflUYA3Er2zUxPSJu5R+g==" + } + } + }, "duplexer": { "version": "0.1.2", "devOptional": true diff --git a/package.json b/package.json index 2cc9e7f39..c29ab1f54 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "@material-ui/lab": "^4.0.0-alpha.61", "@material-ui/styles": "^4.11.4", "@reach/auto-id": "^0.16.0", - "@saleor/macaw-ui": "0.8.0-pre.68", + "@saleor/macaw-ui": "0.8.0-pre.73", "@saleor/sdk": "^0.5.0", "@sentry/react": "^6.0.0", "@types/faker": "^5.1.6", diff --git a/src/attributes/components/AttributePage/AttributePage.tsx b/src/attributes/components/AttributePage/AttributePage.tsx index 442c25d31..80fc12344 100644 --- a/src/attributes/components/AttributePage/AttributePage.tsx +++ b/src/attributes/components/AttributePage/AttributePage.tsx @@ -4,7 +4,7 @@ import { TopNav } from "@dashboard/components/AppLayout/TopNav"; import CardSpacer from "@dashboard/components/CardSpacer"; import Form from "@dashboard/components/Form"; import { DetailPageLayout } from "@dashboard/components/Layouts"; -import Metadata from "@dashboard/components/Metadata/Metadata"; +import { Metadata } from "@dashboard/components/Metadata/Metadata"; import { MetadataFormData } from "@dashboard/components/Metadata/types"; import Savebar from "@dashboard/components/Savebar"; import { ListSettingsUpdate } from "@dashboard/components/TablePagination"; diff --git a/src/categories/components/CategoryCreatePage/CategoryCreatePage.tsx b/src/categories/components/CategoryCreatePage/CategoryCreatePage.tsx index c69c453be..5bb25083d 100644 --- a/src/categories/components/CategoryCreatePage/CategoryCreatePage.tsx +++ b/src/categories/components/CategoryCreatePage/CategoryCreatePage.tsx @@ -1,9 +1,9 @@ import { TopNav } from "@dashboard/components/AppLayout/TopNav"; import { CardSpacer } from "@dashboard/components/CardSpacer"; import { DetailPageLayout } from "@dashboard/components/Layouts"; -import Metadata from "@dashboard/components/Metadata"; +import { Metadata } from "@dashboard/components/Metadata"; import Savebar from "@dashboard/components/Savebar"; -import SeoForm from "@dashboard/components/SeoForm"; +import { SeoForm } from "@dashboard/components/SeoForm"; import { ProductErrorFragment } from "@dashboard/graphql"; import useNavigator from "@dashboard/hooks/useNavigator"; import { ConfirmButtonTransitionState } from "@saleor/macaw-ui"; diff --git a/src/categories/components/CategoryUpdatePage/CategoryUpdatePage.tsx b/src/categories/components/CategoryUpdatePage/CategoryUpdatePage.tsx index 9a78243ee..85b6487bf 100644 --- a/src/categories/components/CategoryUpdatePage/CategoryUpdatePage.tsx +++ b/src/categories/components/CategoryUpdatePage/CategoryUpdatePage.tsx @@ -8,9 +8,9 @@ import { Button } from "@dashboard/components/Button"; import { CardSpacer } from "@dashboard/components/CardSpacer"; import CardTitle from "@dashboard/components/CardTitle"; import { DetailPageLayout } from "@dashboard/components/Layouts"; -import Metadata from "@dashboard/components/Metadata/Metadata"; +import { Metadata } from "@dashboard/components/Metadata/Metadata"; import Savebar from "@dashboard/components/Savebar"; -import SeoForm from "@dashboard/components/SeoForm"; +import { SeoForm } from "@dashboard/components/SeoForm"; import { Tab, TabContainer } from "@dashboard/components/Tab"; import { CategoryDetailsQuery, ProductErrorFragment } from "@dashboard/graphql"; import { SubmitPromise } from "@dashboard/hooks/useForm"; diff --git a/src/collections/components/CollectionCreatePage/CollectionCreatePage.tsx b/src/collections/components/CollectionCreatePage/CollectionCreatePage.tsx index d85ff5fc9..2310da075 100644 --- a/src/collections/components/CollectionCreatePage/CollectionCreatePage.tsx +++ b/src/collections/components/CollectionCreatePage/CollectionCreatePage.tsx @@ -4,9 +4,9 @@ import { TopNav } from "@dashboard/components/AppLayout/TopNav"; import { CardSpacer } from "@dashboard/components/CardSpacer"; import ChannelsAvailabilityCard from "@dashboard/components/ChannelsAvailabilityCard"; import { DetailPageLayout } from "@dashboard/components/Layouts"; -import Metadata from "@dashboard/components/Metadata"; +import { Metadata } from "@dashboard/components/Metadata"; import Savebar from "@dashboard/components/Savebar"; -import SeoForm from "@dashboard/components/SeoForm"; +import { SeoForm } from "@dashboard/components/SeoForm"; import { CollectionChannelListingErrorFragment, CollectionErrorFragment, diff --git a/src/collections/components/CollectionDetailsPage/CollectionDetailsPage.tsx b/src/collections/components/CollectionDetailsPage/CollectionDetailsPage.tsx index 9ee705a5a..b7ce7a7be 100644 --- a/src/collections/components/CollectionDetailsPage/CollectionDetailsPage.tsx +++ b/src/collections/components/CollectionDetailsPage/CollectionDetailsPage.tsx @@ -4,9 +4,9 @@ import { TopNav } from "@dashboard/components/AppLayout/TopNav"; import { CardSpacer } from "@dashboard/components/CardSpacer"; import ChannelsAvailabilityCard from "@dashboard/components/ChannelsAvailabilityCard"; import { DetailPageLayout } from "@dashboard/components/Layouts"; -import Metadata from "@dashboard/components/Metadata/Metadata"; +import { Metadata } from "@dashboard/components/Metadata/Metadata"; import Savebar from "@dashboard/components/Savebar"; -import SeoForm from "@dashboard/components/SeoForm"; +import { SeoForm } from "@dashboard/components/SeoForm"; import { CollectionChannelListingErrorFragment, CollectionDetailsQuery, diff --git a/src/components/TopNavMenu/TopNavMenu.tsx b/src/components/AppLayout/TopNav/Menu.tsx similarity index 93% rename from src/components/TopNavMenu/TopNavMenu.tsx rename to src/components/AppLayout/TopNav/Menu.tsx index 5052e8c3a..0ef66ffc2 100644 --- a/src/components/TopNavMenu/TopNavMenu.tsx +++ b/src/components/AppLayout/TopNav/Menu.tsx @@ -19,10 +19,7 @@ interface TopNavMenuProps { dataTestId?: string; } -export const TopNavMenu: React.FC = ({ - items, - dataTestId, -}) => ( +export const Menu: React.FC = ({ items, dataTestId }) => ( - - -
{children}
+ {selectLabel} + + + {children} ); }; diff --git a/src/components/Attributes/SwatchRow.tsx b/src/components/Attributes/SwatchRow.tsx index 74da0d4ea..47b39be81 100644 --- a/src/components/Attributes/SwatchRow.tsx +++ b/src/components/Attributes/SwatchRow.tsx @@ -1,4 +1,4 @@ -import BasicAttributeRow from "@dashboard/components/Attributes/BasicAttributeRow"; +import { BasicAttributeRow } from "@dashboard/components/Attributes/BasicAttributeRow"; import { getErrorMessage, getSingleDisplayValue, @@ -38,7 +38,10 @@ export const SwatchRow: React.FC = ({ const value = attribute.data.values.find(getBySlug(attribute.value[0])); return ( - + = ({ error={!!error} helperText={getErrorMessage(error, intl)} name={`attribute:${attribute.label}`} + id={`attribute:${attribute.label}`} value={attribute.value[0]} onChange={event => onChange(attribute.id, event.target.value)} fetchChoices={value => fetchAttributeValues(value, attribute.id)} diff --git a/src/components/Attributes/index.ts b/src/components/Attributes/index.ts index baed03372..44c1a977e 100644 --- a/src/components/Attributes/index.ts +++ b/src/components/Attributes/index.ts @@ -1,3 +1,2 @@ -export { default } from "./Attributes"; export * from "./Attributes"; export * from "./types"; diff --git a/src/components/Attributes/styles.ts b/src/components/Attributes/styles.ts index f3d4ff2a6..b878af983 100644 --- a/src/components/Attributes/styles.ts +++ b/src/components/Attributes/styles.ts @@ -2,13 +2,6 @@ import { makeStyles } from "@saleor/macaw-ui"; export const useStyles = makeStyles( () => ({ - fileField: { - float: "right", - }, - pullRight: { - display: "flex", - justifyContent: "flex-end", - }, swatchInput: { paddingTop: 16.5, paddingBottom: 16.5, @@ -23,62 +16,3 @@ export const useStyles = makeStyles( }), { name: "AttributeRow" }, ); - -export const useBasicAttributeStyles = makeStyles( - theme => ({ - attributeSection: { - "&:last-of-type": { - paddingBottom: 0, - }, - padding: theme.spacing(2, 0), - wordBreak: "break-word", - }, - attributeSectionLabel: { - alignItems: "center", - display: "flex", - }, - flex: { - columnGap: theme.spacing(2) + "px", - display: "flex", - flexDirection: "row", - [theme.breakpoints.down("md")]: { - flexDirection: "column", - rowGap: theme.spacing(2) + "px", - }, - }, - value: { - "&&": { - overflow: "visible", - }, - }, - tooltipIcon: { - fill: theme.palette.type === "dark" ? "#FAFAFA" : "#28234A", - fillOpacity: 0.6, - "&:hover": { - fillOpacity: 1, - }, - padding: theme.spacing(0.25), - marginLeft: theme.spacing(0.75), - }, - }), - { name: "BasicAttributeRow" }, -); - -export const useExtendedAttributeStyles = makeStyles( - theme => ({ - attributeSection: { - "&:last-of-type": { - paddingBottom: 0, - }, - padding: theme.spacing(2, 0), - }, - attributeSectionButton: { - float: "right", - }, - attributeSectionLabel: { - alignItems: "center", - display: "flex", - }, - }), - { name: "ExtendedAttributeRow" }, -); diff --git a/src/components/Attributes/types.ts b/src/components/Attributes/types.ts index 958230871..5706a76ab 100644 --- a/src/components/Attributes/types.ts +++ b/src/components/Attributes/types.ts @@ -16,7 +16,7 @@ export enum VariantAttributeScope { } export interface AttributeRowHandlers { - onChange: FormsetChange; + onChange: FormsetChange; onFileChange: FormsetChange; onMultiChange: FormsetChange; onReferencesAddClick: (attribute: AttributeInput) => void; diff --git a/src/components/Card/Content.tsx b/src/components/Card/Content.tsx new file mode 100644 index 000000000..023d7fc34 --- /dev/null +++ b/src/components/Card/Content.tsx @@ -0,0 +1,8 @@ +import { Box, Sprinkles } from "@saleor/macaw-ui/next"; +import React from "react"; + +export const Content: React.FC = ({ children, ...rest }) => ( + + {children} + +); diff --git a/src/components/Card/Root.tsx b/src/components/Card/Root.tsx new file mode 100644 index 000000000..550666418 --- /dev/null +++ b/src/components/Card/Root.tsx @@ -0,0 +1,8 @@ +import { Box, Sprinkles } from "@saleor/macaw-ui/next"; +import React from "react"; + +export const Root: React.FC = ({ children, ...rest }) => ( + + {children} + +); diff --git a/src/components/Card/Title.tsx b/src/components/Card/Title.tsx new file mode 100644 index 000000000..13d4eebe8 --- /dev/null +++ b/src/components/Card/Title.tsx @@ -0,0 +1,8 @@ +import { Box, Text } from "@saleor/macaw-ui/next"; +import React from "react"; + +export const Title: React.FC = ({ children }) => ( + + {children} + +); diff --git a/src/components/Card/index.ts b/src/components/Card/index.ts new file mode 100644 index 000000000..bf4f342a9 --- /dev/null +++ b/src/components/Card/index.ts @@ -0,0 +1,5 @@ +import { Content } from "./Content"; +import { Root } from "./Root"; +import { Title } from "./Title"; + +export const DashboardCard = Object.assign(Root, { Title, Content }); diff --git a/src/components/ChannelsAvailabilityCard/Channel/ChannelAvailabilityItemContent.tsx b/src/components/ChannelsAvailabilityCard/Channel/ChannelAvailabilityItemContent.tsx index eab2d3364..871f8f8ab 100644 --- a/src/components/ChannelsAvailabilityCard/Channel/ChannelAvailabilityItemContent.tsx +++ b/src/components/ChannelsAvailabilityCard/Channel/ChannelAvailabilityItemContent.tsx @@ -1,16 +1,18 @@ import { ChannelData } from "@dashboard/channels/utils"; -import ControlledCheckbox from "@dashboard/components/ControlledCheckbox"; -import Hr from "@dashboard/components/Hr"; -import RadioSwitchField from "@dashboard/components/RadioSwitchField"; import useCurrentDate from "@dashboard/hooks/useCurrentDate"; import useDateLocalize from "@dashboard/hooks/useDateLocalize"; import { getFormErrors, getProductErrorMessage } from "@dashboard/utils/errors"; -import { TextField, Typography } from "@material-ui/core"; -import clsx from "clsx"; +import { TextField } from "@material-ui/core"; +import { + Box, + Checkbox, + Divider, + RadioGroup, + Text, +} from "@saleor/macaw-ui/next"; import React, { useState } from "react"; import { useIntl } from "react-intl"; -import { useStyles } from "../styles"; import { ChannelOpts, ChannelsAvailabilityError, Messages } from "../types"; import { availabilityItemMessages } from "./messages"; @@ -22,7 +24,7 @@ export interface ChannelContentProps { onChange: (id: string, data: ChannelOpts) => void; } -const ChannelContent: React.FC = ({ +export const ChannelAvailabilityItemContent: React.FC = ({ data, disabled, errors, @@ -55,7 +57,6 @@ const ChannelContent: React.FC = ({ ); const [isAvailableDate, setAvailableDate] = useState(false); const intl = useIntl(); - const classes = useStyles({}); const parsedDate = new Date(dateNow); const todayDateUTC = parsedDate.toISOString().slice(0, 10); @@ -70,57 +71,64 @@ const ChannelContent: React.FC = ({ ); return ( -
- -

{messages.visibleLabel}

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

{messages.hiddenLabel}

- {publicationDate && - !isPublished && - Date.parse(publicationDate) >= dateNow && ( - - {messages.hiddenSecondLabel} - - )} - - } - value={isPublished} - onChange={() => { + + { onChange(id, { ...formData, - isPublished: !isPublished, + isPublished: value === "true", publicationDate: !isPublished && !publicationDate ? todayDateUTC : publicationDate, }); }} - /> + disabled={disabled} + display="flex" + flexDirection="column" + gap={6} + > + + + {messages.visibleLabel} + {isPublished && + publicationDate && + Date.parse(publicationDate) < dateNow && ( + + {messages.visibleSecondLabel || + visibleMessage(publicationDate)} + + )} + + + + + {messages.hiddenLabel} + {publicationDate && + !isPublished && + Date.parse(publicationDate) >= dateNow && ( + + {messages.hiddenSecondLabel} + + )} + + + {!isPublished && ( - <> - setPublicationDate(!isPublicationDate)} + + setPublicationDate(checked)} + checked={isPublicationDate} > {intl.formatMessage(availabilityItemMessages.setPublicationDate)} - + {isPublicationDate && ( = ({ publicationDate: e.target.value || null, }) } - className={classes.date} InputLabelProps={{ shrink: true, }} /> )} - + )} {hasAvailableProps && ( <> -
- + -

{messages.availableLabel}

+ name={`channel:isAvailableForPurchase:${id}`} + value={String(isAvailable)} + onValueChange={value => + onChange(id, { + ...formData, + availableForPurchase: !value ? null : availableForPurchase, + isAvailableForPurchase: value === "true", + }) + } + display="flex" + flexDirection="column" + gap={6} + > + + + {messages.availableLabel} {isAvailable && availableForPurchase && Date.parse(availableForPurchase) < dateNow && ( - + {visibleMessage(availableForPurchase)} - + )} - - } - name={`channel:isAvailableForPurchase:${id}`} - secondOptionLabel={ - <> -

{messages.unavailableLabel}

+
+
+ + + {messages.unavailableLabel} {availableForPurchase && !isAvailable && ( - + {messages.availableSecondLabel} - + )} - - } - value={isAvailable} - onChange={e => { - const { value } = e.target; - return onChange(id, { - ...formData, - availableForPurchase: !value ? null : availableForPurchase, - isAvailableForPurchase: value, - }); - }} - /> + + +
{!isAvailable && ( - <> - setAvailableDate(!isAvailableDate)} + + + setAvailableDate(checked) + } + checked={isAvailableDate} > {messages.setAvailabilityDateLabel} - + {isAvailableDate && ( = ({ availableForPurchase: e.target.value, }) } - className={classes.date} InputLabelProps={{ shrink: true, }} /> )} - + )} )} {visibleInListings !== undefined && ( <> -
- + -

- {intl.formatMessage(availabilityItemMessages.hideInListings)} -

- - {intl.formatMessage( - availabilityItemMessages.hideInListingsDescription, - )} - - - } - onChange={e => + onCheckedChange={checked => { onChange(id, { ...formData, - visibleInListings: !e.target.value, - }) - } - /> + visibleInListings: !checked, + }); + }} + > + + {intl.formatMessage(availabilityItemMessages.hideInListings)} + +
+ + {intl.formatMessage( + availabilityItemMessages.hideInListingsDescription, + )} + )} -
+ ); }; -export default ChannelContent; diff --git a/src/components/ChannelsAvailabilityCard/Channel/ChannelAvailabilityItemWrapper.tsx b/src/components/ChannelsAvailabilityCard/Channel/ChannelAvailabilityItemWrapper.tsx index 65f5ec8a6..fa8b27526 100644 --- a/src/components/ChannelsAvailabilityCard/Channel/ChannelAvailabilityItemWrapper.tsx +++ b/src/components/ChannelsAvailabilityCard/Channel/ChannelAvailabilityItemWrapper.tsx @@ -1,94 +1,28 @@ import { ChannelData } from "@dashboard/channels/utils"; import Label from "@dashboard/orders/components/OrderHistory/Label"; -import { Typography } from "@material-ui/core"; -import { Accordion, AccordionSummary, makeStyles } from "@saleor/macaw-ui"; +import { Accordion, Text } from "@saleor/macaw-ui/next"; import React from "react"; import { Messages } from "../types"; -const useExpanderStyles = makeStyles( - theme => ({ - expanded: {}, - root: { - boxShadow: "none", - margin: 0, - padding: 0, - paddingBottom: theme.spacing(2), - - "&:before": { - content: "none", - }, - - "&$expanded": { - margin: 0, - border: "none", - }, - }, - }), - { name: "ChannelContentWrapperExpander" }, -); - -const useSummaryStyles = makeStyles( - theme => ({ - expanded: {}, - root: { - width: "100%", - border: "none", - margin: 0, - padding: 0, - minHeight: 0, - paddingTop: theme.spacing(2), - - "&$expanded": { - minHeight: 0, - padding: theme.spacing(2, 0), - }, - }, - }), - { name: "ChannelContentWrapperExpanderSummary" }, -); - -const useStyles = makeStyles( - () => ({ - container: { - display: "flex", - flexDirection: "column", - }, - }), - { name: "ChannelWithVariantAvailabilityItemWrapper" }, -); - export interface ChannelContentWrapperProps { data: ChannelData; children: React.ReactNode; messages: Messages; } -const ChannelContentWrapper: React.FC = ({ - data, - messages, - children, -}) => { - const expanderClasses = useExpanderStyles(); - const summaryClasses = useSummaryStyles(); - const classes = useStyles(); - - const { name } = data; - - return ( - - -
- {name} -
-
- {children} -
- ); -}; - -export default ChannelContentWrapper; +export const ChannelAvailabilityItemWrapper: React.FC< + ChannelContentWrapperProps +> = ({ data: { name }, messages, children }) => ( + + + + {name} + + + {children} + + + +); diff --git a/src/components/ChannelsAvailabilityCard/Channel/index.ts b/src/components/ChannelsAvailabilityCard/Channel/index.ts new file mode 100644 index 000000000..ccc098a20 --- /dev/null +++ b/src/components/ChannelsAvailabilityCard/Channel/index.ts @@ -0,0 +1,2 @@ +export * from "./ChannelAvailabilityItemContent"; +export * from "./ChannelAvailabilityItemWrapper"; diff --git a/src/components/ChannelsAvailabilityCard/ChannelsAvailabilityCard.tsx b/src/components/ChannelsAvailabilityCard/ChannelsAvailabilityCard.tsx index 36bf9a4de..44f53b5f8 100644 --- a/src/components/ChannelsAvailabilityCard/ChannelsAvailabilityCard.tsx +++ b/src/components/ChannelsAvailabilityCard/ChannelsAvailabilityCard.tsx @@ -1,18 +1,19 @@ import { Channel as ChannelList, ChannelData } from "@dashboard/channels/utils"; -import Hr from "@dashboard/components/Hr"; import { PermissionEnum } from "@dashboard/graphql"; import useDateLocalize from "@dashboard/hooks/useDateLocalize"; import { RequireOnlyOne } from "@dashboard/misc"; -import { Typography } from "@material-ui/core"; +import { Box, Divider, Text } from "@saleor/macaw-ui/next"; import React from "react"; import { useIntl } from "react-intl"; -import ChannelAvailabilityItemContent from "./Channel/ChannelAvailabilityItemContent"; -import ChannelAvailabilityItemWrapper from "./Channel/ChannelAvailabilityItemWrapper"; -import ChannelsAvailabilityCardWrapper, { +import { + ChannelAvailabilityItemContent, + ChannelAvailabilityItemWrapper, +} from "./Channel"; +import { + ChannelsAvailabilityCardWrapper, ChannelsAvailabilityWrapperProps, } from "./ChannelsAvailabilityCardWrapper"; -import { useStyles } from "./styles"; import { ChannelOpts, ChannelsAvailabilityError, Messages } from "./types"; import { getChannelsAvailabilityMessages } from "./utils"; @@ -36,7 +37,9 @@ export type ChannelsAvailabilityCardProps = RequireOnlyOne< "channels" | "channelsList" >; -export const ChannelsAvailability: React.FC = props => { +export const ChannelsAvailability: React.FC< + ChannelsAvailabilityCardProps +> = props => { const { channelsList, errors = [], @@ -49,7 +52,6 @@ export const ChannelsAvailability: React.FC = pro } = props; const intl = useIntl(); const localizeDate = useDateLocalize(); - const classes = useStyles({}); const channelsMessages = getChannelsAvailabilityMessages({ messages, @@ -88,12 +90,10 @@ export const ChannelsAvailability: React.FC = pro : channelsList ? channelsList.map(data => ( -
-
- {data.name} -
-
-
+ + {data.name} + +
)) : null} diff --git a/src/components/ChannelsAvailabilityCard/ChannelsAvailabilityCardWrapper.tsx b/src/components/ChannelsAvailabilityCard/ChannelsAvailabilityCardWrapper.tsx index e2592547a..4cb29ed92 100644 --- a/src/components/ChannelsAvailabilityCard/ChannelsAvailabilityCardWrapper.tsx +++ b/src/components/ChannelsAvailabilityCard/ChannelsAvailabilityCardWrapper.tsx @@ -1,13 +1,10 @@ -import { Button } from "@dashboard/components/Button"; -import CardTitle from "@dashboard/components/CardTitle"; -import Hr from "@dashboard/components/Hr"; import RequirePermissions from "@dashboard/components/RequirePermissions"; import { PermissionEnum } from "@dashboard/graphql"; -import { Card, CardContent, Typography } from "@material-ui/core"; +import { Box, Button, Text } from "@saleor/macaw-ui/next"; import React from "react"; import { useIntl } from "react-intl"; -import { useStyles } from "./styles"; +import { DashboardCard } from "../Card"; export interface ChannelsAvailabilityWrapperProps { selectedChannelsCount: number; @@ -17,7 +14,9 @@ export interface ChannelsAvailabilityWrapperProps { openModal: () => void; } -export const ChannelsAvailabilityWrapper: React.FC = props => { +export const ChannelsAvailabilityCardWrapper: React.FC< + ChannelsAvailabilityWrapperProps +> = props => { const { selectedChannelsCount, allChannelsCount, @@ -26,12 +25,11 @@ export const ChannelsAvailabilityWrapper: React.FC - - - - - } - /> - - {!!channelsAvailabilityText && ( - <> - - {channelsAvailabilityText} - -
- - )} + + + + +
+ {intl.formatMessage({ + id: "5A6/2C", + defaultMessage: "Availability", + description: "section header", + })} +
+ {!!channelsAvailabilityText && ( + {channelsAvailabilityText} + )} +
+ + + +
+
+ + {children} -
-
- + + + ); }; - -export default ChannelsAvailabilityWrapper; diff --git a/src/components/ChannelsAvailabilityCard/styles.ts b/src/components/ChannelsAvailabilityCard/styles.ts deleted file mode 100644 index 7e93387fe..000000000 --- a/src/components/ChannelsAvailabilityCard/styles.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { makeStyles } from "@material-ui/core/styles"; - -export const useStyles = makeStyles( - theme => ({ - container: { - marginTop: theme.spacing(1), - marginBottom: theme.spacing(1), - }, - radioField: { - paddingLeft: theme.spacing(1), - }, - arrow: { - transition: theme.transitions.duration.short + "ms", - }, - card: { - "&:last-child": { - paddingBottom: 0, - }, - paddingTop: 0, - }, - channelBtn: { - "&:focus": { - outline: "none", - }, - background: "transparent", - border: "none", - cursor: "pointer", - textAlign: "left", - }, - channelInfo: { - fontSize: 14, - padding: theme.spacing(2, 0), - }, - channelItem: { - "&:last-child hr": { - display: "none", - }, - padding: theme.spacing(2, 0), - }, - channelName: { - alignItems: "center", - display: "flex", - justifyContent: "space-between", - marginBottom: theme.spacing(0.5), - }, - checkbox: { - alignItems: "flex-start", - marginTop: 10, - }, - date: { - "& svg": { - fill: theme.palette.primary.main, - }, - marginTop: theme.spacing(1), - }, - hr: { - position: "relative", - }, - label: { - lineHeight: 1.2, - }, - listingLabel: { - marginTop: 9, - }, - radioLabel: { - "& > span": { - padding: theme.spacing(0, 0.5), - }, - }, - rotate: { - transform: "rotate(180deg)", - }, - secondLabel: { - color: theme.palette.text.hint, - fontSize: 12, - }, - setPublicationDate: { - color: theme.palette.primary.main, - cursor: "pointer", - fontSize: 14, - paddingBottom: 10, - paddingTop: 0, - }, - }), - { name: "ChannelsAvailabilityCard" }, -); diff --git a/src/components/DateTimeField/DateTimeField.tsx b/src/components/DateTimeField/DateTimeField.tsx index 8c5d2d466..2ca2072e3 100644 --- a/src/components/DateTimeField/DateTimeField.tsx +++ b/src/components/DateTimeField/DateTimeField.tsx @@ -7,11 +7,10 @@ import { commonMessages } from "@dashboard/intl"; import { joinDateTime, splitDateTime } from "@dashboard/misc"; import { TextField } from "@material-ui/core"; import { TextFieldProps } from "@material-ui/core/TextField"; +import { Box } from "@saleor/macaw-ui/next"; import React from "react"; import { useIntl } from "react-intl"; -import { useStyles } from "./styles"; - type DateTimeFieldProps = Omit & { onChange: (value: string) => void; error: ProductErrorWithAttributesFragment | PageErrorWithAttributesFragment; @@ -26,12 +25,11 @@ export const DateTimeField: React.FC = ({ value, }) => { const intl = useIntl(); - const classes = useStyles(); const parsedValue = value ? splitDateTime(value) : { date: "", time: "" }; return ( - <> + = ({ type="date" value={parsedValue.date} InputLabelProps={{ shrink: true }} - InputProps={{ - classes: { - root: classes.dateField, - }, - }} /> = ({ type="time" value={parsedValue.time} InputLabelProps={{ shrink: true }} - InputProps={{ - classes: { - root: classes.timeField, - }, - }} /> - + ); }; diff --git a/src/components/DateTimeField/styles.ts b/src/components/DateTimeField/styles.ts deleted file mode 100644 index 16271ce47..000000000 --- a/src/components/DateTimeField/styles.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { makeStyles } from "@saleor/macaw-ui"; - -export const useStyles = makeStyles( - theme => ({ - dateField: { - borderRadius: "4px 0 0 4px", - }, - timeField: { - borderRadius: "0 4px 4px 0", - "& > fieldset": { - borderLeftWidth: "0 !important", - }, - }, - [theme.breakpoints.down("md")]: { - dateField: { - borderRadius: "4px 4px 0 0", - }, - timeField: { - borderRadius: "0 0 4px 4px", - "& > fieldset": { - borderTopWidth: "0 !important", - borderLeftWidth: "1px !important", - }, - }, - }, - }), - { name: "DateTimeField" }, -); diff --git a/src/components/FileUploadField/FileUploadField.tsx b/src/components/FileUploadField/FileUploadField.tsx index e0c1eed2b..cb455df7e 100644 --- a/src/components/FileUploadField/FileUploadField.tsx +++ b/src/components/FileUploadField/FileUploadField.tsx @@ -1,8 +1,6 @@ -import { Button } from "@dashboard/components/Button"; import { FileFragment } from "@dashboard/graphql"; import { commonMessages } from "@dashboard/intl"; -import { Typography } from "@material-ui/core"; -import { DeleteIcon, IconButton, makeStyles } from "@saleor/macaw-ui"; +import { Box, Button, Text, TrashBinIcon } from "@saleor/macaw-ui/next"; import React from "react"; import { useIntl } from "react-intl"; @@ -19,7 +17,6 @@ export interface FileUploadFieldProps { React.InputHTMLAttributes, HTMLInputElement >; - className?: string; disabled: boolean; loading: boolean; file: FileChoiceType; @@ -29,44 +26,17 @@ export interface FileUploadFieldProps { onFileDelete: () => void; } -const useStyles = makeStyles( - theme => ({ - errorText: { - color: theme.palette.error.light, - }, - fileField: { - display: "none", - }, - fileUrl: { - color: theme.palette.primary.main, - textDecoration: "none", - }, - uploadFileContent: { - alignItems: "center", - color: theme.palette.primary.main, - display: "flex", - fontSize: theme.typography.body1.fontSize, - }, - uploadFileName: { - minWidth: "6rem", - }, - }), - { name: "FileUploadField" }, -); - const FileUploadField: React.FC = props => { const { loading, disabled, file, - className, error, helperText, onFileUpload, onFileDelete, inputProps, } = props; - const classes = useStyles({}); const intl = useIntl(); const fileInputAnchor = React.createRef(); @@ -85,52 +55,46 @@ const FileUploadField: React.FC = props => { return ( <> -
+ {file.label ? ( -
-
+ + {loading ? ( ) : ( - + {file.label} )} -
- +
+ type="button" + /> +
) : ( -
- -
+ )} {error && ( - + {helperText} - + )} -
+ onFileUpload(event.target.files[0])} type="file" diff --git a/src/components/Hr.tsx b/src/components/Hr.tsx index c17533df0..8d7fd671d 100644 --- a/src/components/Hr.tsx +++ b/src/components/Hr.tsx @@ -1,32 +1,21 @@ -import { makeStyles } from "@saleor/macaw-ui"; -import { vars } from "@saleor/macaw-ui/next"; -import clsx from "clsx"; +import { Box } from "@saleor/macaw-ui/next"; import React from "react"; -interface HrProps { +/** + * @deprecated use `Divider` component from `@saleor/macaw-ui/next` + */ +export const Hr: React.FC<{ className?: string; -} - -const useStyles = makeStyles( - { - root: { - backgroundColor: vars.colors.border.neutralPlain, - border: "none", - display: "block", - height: 1, - margin: 0, - width: "100%", - }, - }, - { name: "Hr" }, +}> = ({ className }) => ( + ); -export const Hr: React.FC = props => { - const { className } = props; - - const classes = useStyles(props); - - return
; -}; Hr.displayName = "Hr"; export default Hr; diff --git a/src/components/Metadata/Metadata.test.tsx b/src/components/Metadata/Metadata.test.tsx index 0ca3e0fa0..f520196b3 100644 --- a/src/components/Metadata/Metadata.test.tsx +++ b/src/components/Metadata/Metadata.test.tsx @@ -5,7 +5,7 @@ import userEvent from "@testing-library/user-event"; import React from "react"; import { props } from "./fixtures"; -import Metadata from "./Metadata"; +import { Metadata } from "./Metadata"; const Component = () => { const { change, data } = useForm(props.data, jest.fn()); diff --git a/src/components/Metadata/Metadata.tsx b/src/components/Metadata/Metadata.tsx index f6f8b3235..4ffbba992 100644 --- a/src/components/Metadata/Metadata.tsx +++ b/src/components/Metadata/Metadata.tsx @@ -1,10 +1,10 @@ import { MetadataInput } from "@dashboard/graphql"; import { ChangeEvent } from "@dashboard/hooks/useForm"; import { removeAtIndex, updateAtIndex } from "@dashboard/utils/lists"; +import { Box } from "@saleor/macaw-ui/next"; import React from "react"; -import CardSpacer from "../CardSpacer"; -import MetadataCard, { MetadataCardProps } from "./MetadataCard"; +import { MetadataCard, MetadataCardProps } from "./MetadataCard"; import { EventDataAction, EventDataField } from "./types"; import { getDataKey, parseEventData } from "./utils"; @@ -13,7 +13,7 @@ export interface MetadataProps data: Record<"metadata" | "privateMetadata", MetadataInput[]>; } -const Metadata: React.FC = ({ data, onChange }) => { +export const Metadata: React.FC = ({ data, onChange }) => { const change = (event: ChangeEvent, isPrivate: boolean) => { const { action, field, fieldIndex, value } = parseEventData(event); const key = getDataKey(isPrivate); @@ -53,21 +53,17 @@ const Metadata: React.FC = ({ data, onChange }) => { }; 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 index 06231ba29..47255c649 100644 --- a/src/components/Metadata/MetadataCard.tsx +++ b/src/components/Metadata/MetadataCard.tsx @@ -1,27 +1,44 @@ -import { Button } from "@dashboard/components/Button"; import TableRowLink from "@dashboard/components/TableRowLink"; import { MetadataInput } from "@dashboard/graphql"; import { FormChange } from "@dashboard/hooks/useForm"; import { - Card, - CardActions, - CardContent, Table, TableBody, TableCell, TableHead, TextField, - Typography, } from "@material-ui/core"; -import { DeleteIcon, ExpandIcon, IconButton } from "@saleor/macaw-ui"; -import clsx from "clsx"; +import { makeStyles } from "@saleor/macaw-ui"; +import { + Box, + Button, + ChervonDownIcon, + ChervonUpIcon, + Text, + TrashBinIcon, + vars, +} from "@saleor/macaw-ui/next"; import React from "react"; import { FormattedMessage, useIntl } from "react-intl"; -import CardTitle from "../CardTitle"; +import { DashboardCard } from "../Card"; import Skeleton from "../Skeleton"; -import useStyles from "./styles"; -import { EventDataAction, EventDataField } from "./types"; +import { EventDataAction } from "./types"; +import { nameInputPrefix, nameSeparator, valueInputPrefix } from "./utils"; + +const useStyles = makeStyles( + theme => ({ + input: { + padding: theme.spacing(0.5, 2), + }, + nameInput: { + padding: "13px 16px", + }, + }), + { + name: "Metadata", + }, +); export interface MetadataCardProps { data: MetadataInput[]; @@ -29,11 +46,7 @@ export interface MetadataCardProps { onChange: FormChange; } -export const nameSeparator = ":"; -export const nameInputPrefix = EventDataField.name; -export const valueInputPrefix = EventDataField.value; - -const MetadataCard: React.FC = ({ +export const MetadataCard: React.FC = ({ data, isPrivate, onChange, @@ -43,49 +56,47 @@ const MetadataCard: React.FC = ({ const classes = useStyles(); return ( - - - {isPrivate - ? intl.formatMessage({ - id: "ETHnjq", - defaultMessage: "Private Metadata", - description: "header", - }) - : intl.formatMessage({ - id: "VcI+Zh", - defaultMessage: "Metadata", - description: "header", - })} - + setExpanded(!expanded)} + cursor="pointer" + > + {isPrivate + ? intl.formatMessage({ + id: "ETHnjq", + defaultMessage: "Private Metadata", + description: "header", + }) + : intl.formatMessage({ + id: "VcI+Zh", + defaultMessage: "Metadata", + description: "header", })} - hoverOutline={false} - variant="secondary" - data-test-id="expand" - onClick={() => setExpanded(!expanded)} - > - - - - } - /> + - + )} )} - + ); }; - -MetadataCard.displayName = "MetadataCard"; -export default MetadataCard; diff --git a/src/components/Metadata/index.ts b/src/components/Metadata/index.ts index 4ded27123..7fffd650b 100644 --- a/src/components/Metadata/index.ts +++ b/src/components/Metadata/index.ts @@ -1,5 +1,3 @@ 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 deleted file mode 100644 index 7d5d3dab7..000000000 --- a/src/components/Metadata/styles.ts +++ /dev/null @@ -1,79 +0,0 @@ -import { makeStyles } from "@saleor/macaw-ui"; - -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(4), - }, - }, - colActionHeader: { - ...colAction, - }, - colName: { - ...colName, - }, - colNameHeader: { - ...colName, - }, - colValue: {}, - actions: { - "&&": { - paddingBottom: theme.spacing(2), - paddingTop: theme.spacing(2), - paddingLeft: theme.spacing(4), - }, - }, - content: { - paddingBottom: 0, - paddingTop: theme.spacing(), - }, - emptyContainer: { - paddingBottom: 0, - paddingTop: 0, - }, - expandBtn: { - position: "relative", - left: theme.spacing(1), - top: -2, - transition: theme.transitions.create("transform", { - duration: theme.transitions.duration.shorter, - }), - border: 0, - }, - header: { - "&&": { - paddingBottom: theme.spacing(1), - }, - }, - input: { - padding: theme.spacing(0.5, 2), - }, - nameInput: { - padding: `13px 16px`, - }, - table: { - marginTop: theme.spacing(2), - tableLayout: "fixed", - }, - rotate: { - transform: "rotate(-180deg)", - }, - }; - }, - { - name: "Metadata", - }, -); - -export default useStyles; diff --git a/src/components/Metadata/utils.ts b/src/components/Metadata/utils.ts index ff8955303..9ad3c6423 100644 --- a/src/components/Metadata/utils.ts +++ b/src/components/Metadata/utils.ts @@ -1,8 +1,11 @@ import { ChangeEvent } from "@dashboard/hooks/useForm"; -import { nameSeparator } from "./MetadataCard"; import { EventData, EventDataAction, EventDataField } from "./types"; +export const nameSeparator = ":"; +export const nameInputPrefix = EventDataField.name; +export const valueInputPrefix = EventDataField.value; + export function parseEventData(event: ChangeEvent): EventData { let action: EventDataAction; let field: EventDataField = null; diff --git a/src/components/RichTextEditor/RichTextEditor.tsx b/src/components/RichTextEditor/RichTextEditor.tsx index f1815ce0d..b551fd079 100644 --- a/src/components/RichTextEditor/RichTextEditor.tsx +++ b/src/components/RichTextEditor/RichTextEditor.tsx @@ -38,11 +38,14 @@ const RichTextEditor: React.FC = ({ helperText, editorRef, onInitialize, + onChange, ...props }) => { const classes = useStyles({}); const id = useId(defaultId); const [isFocused, setIsFocused] = React.useState(false); + const [hasValue, setHasValue] = React.useState(false); + const isTyped = Boolean(hasValue || isFocused); const handleInitialize = React.useCallback((editor: EditorCore) => { if (onInitialize) { @@ -68,7 +71,17 @@ const RichTextEditor: React.FC = ({ fullWidth variant="outlined" > - + {label} {hasRendered && ( @@ -76,17 +89,25 @@ const RichTextEditor: React.FC = ({ // match with the id of holder div holder={id} tools={tools} - // LogLeves is undefined at runtime + // Log level is undefined at runtime logLevel={"ERROR" as LogLevels.ERROR} onInitialize={handleInitialize} + onChange={async event => { + const editorJsValue = await event.saver.save(); + setHasValue(editorJsValue.blocks.length > 0); + return onChange?.(); + }} {...props} >
0, })} onFocus={() => setIsFocused(true)} onBlur={() => setIsFocused(false)} diff --git a/src/components/RichTextEditor/styles.ts b/src/components/RichTextEditor/styles.ts index 174af4596..759d53d4f 100644 --- a/src/components/RichTextEditor/styles.ts +++ b/src/components/RichTextEditor/styles.ts @@ -1,16 +1,14 @@ -import { alpha } from "@material-ui/core/styles"; import { makeStyles } from "@saleor/macaw-ui"; +import { vars } from "@saleor/macaw-ui/next"; const useStyles = makeStyles( theme => { const hover = { "&:hover": { - background: alpha(theme.palette.primary.main, 0.1), + background: vars.colors.background.interactiveNeutralHighlightHovering, }, }; - const isDarkMode = theme.palette.type === "dark"; - return { editor: { "& .codex-editor": { @@ -20,17 +18,18 @@ const useStyles = makeStyles( minHeight: 24, }, "& .ce-block--selected .ce-block__content": { - background: `${alpha(theme.palette.primary.main, 0.2)} !important`, + background: `${vars.colors.background.interactiveNeutralHighlightPressing} !important`, }, "& .ce-block__content": { margin: 0, maxWidth: "unset", + paddingRight: "54px", }, "& .ce-conversion-tool": { ...hover, }, "& .ce-conversion-tool--focused": { - background: `${alpha(theme.palette.primary.main, 0.1)} !important`, + background: `${vars.colors.background.interactiveNeutralHighlightHovering} !important`, }, "& .ce-conversion-tool__icon": { background: "none", @@ -77,13 +76,21 @@ const useStyles = makeStyles( ...hover, }, "& .ce-popover": { - backgroundColor: theme.palette.background.paper, + backgroundColor: vars.colors.background.surfaceNeutralPlain, + position: "absolute", + top: 0, + left: "-186px", + }, + "& .ce-settings": { + position: "absolute", + left: "-56px", }, "& .ce-popover__item": { ...hover, }, "& .ce-popover__item-icon": { - color: theme.palette.saleor.generic.verydark, + color: vars.colors.foreground.iconNeutralDefault, + backgroundColor: vars.colors.background.surfaceNeutralPlain, }, "& .codex-editor__loader": { @@ -97,39 +104,62 @@ const useStyles = makeStyles( paddingBottom: "0 !important", }, "& a": { - color: theme.palette.primary.light, + color: vars.colors.foreground.textBrandDefault, }, - "&:not($rootDisabled):hover": { - borderColor: isDarkMode - ? theme.palette.saleor.main[2] - : theme.palette.saleor.main[4], + "& .ce-popover__item--focused": { + background: `${vars.colors.background.interactiveNeutralHighlightHovering} !important`, + }, + "& .cdx-search-field": { + backgroundColor: vars.colors.background.surfaceNeutralPlain, }, }, root: { - border: `1px solid ${theme.palette.saleor.main[4]}`, - borderRadius: 4, - fontSize: theme.typography.body1.fontSize, + border: "1px solid transparent", + borderRadius: vars.borderRadius[3], + fontSize: vars.fontSize.bodyMedium, + backgroundColor: vars.colors.background.surfaceNeutralHighlight, minHeight: 56, - padding: theme.spacing(3, 2), - paddingBottom: theme.spacing(), - paddingLeft: 10, position: "relative", transition: theme.transitions.duration.short + "ms", + padding: theme.spacing(3, 2), + paddingBottom: theme.spacing(), + paddingLeft: vars.space[4], + "&:hover": { + border: `1px solid ${vars.colors.border.neutralHighlight}`, + }, }, rootActive: { - borderColor: theme.palette.saleor.main[1], + border: `1px solid ${vars.colors.border.brandSubdued} !important`, + backgroundColor: `${vars.colors.background.interactiveNeutralHighlightDefault} !important`, }, rootDisabled: { - ...theme.overrides.MuiOutlinedInput.root["&$disabled"]["& fieldset"], - background: theme.palette.background.default, - color: theme.palette.saleor.main[4], + pointerEvents: "none", + backgroundColor: vars.colors.background.surfaceNeutralPlain, + border: `1px solid ${vars.colors.border.neutralHighlight}`, + color: vars.colors.foreground.textNeutralDisabled, }, rootError: { - borderColor: theme.palette.error.main, + backgroundColor: vars.colors.background.surfaceCriticalSubdued, }, rootStatic: { fontSize: theme.typography.body1.fontSize, }, + labelRoot: { + marginLeft: "-6px", + color: `${vars.colors.foreground.textNeutralSubdued} !important`, + }, + labelError: { + color: `${vars.colors.foreground.textCriticalSubdued} !important`, + }, + rootErrorFocus: { + border: "1px solid transparent !important", + }, + labelDisabled: { + color: `${vars.colors.foreground.textNeutralDisabled} !important`, + }, + rootTyped: { + backgroundColor: vars.colors.background.surfaceNeutralPlain, + }, }; }, { name: "RichTextEditor" }, diff --git a/src/components/SeoForm/SeoForm.tsx b/src/components/SeoForm/SeoForm.tsx index 9649ad99b..314d0a3a7 100644 --- a/src/components/SeoForm/SeoForm.tsx +++ b/src/components/SeoForm/SeoForm.tsx @@ -1,4 +1,3 @@ -import { Button } from "@dashboard/components/Button"; import { CollectionErrorFragment, PageErrorFragment, @@ -6,15 +5,13 @@ import { } from "@dashboard/graphql"; import { getFieldError, getProductErrorMessage } from "@dashboard/utils/errors"; import getPageErrorMessage from "@dashboard/utils/errors/page"; -import { Card, CardContent, TextField, Typography } from "@material-ui/core"; +import { TextField } from "@material-ui/core"; import { makeStyles } from "@saleor/macaw-ui"; -import clsx from "clsx"; +import { Box, Button, Input, Text } from "@saleor/macaw-ui/next"; import React from "react"; import { defineMessages, FormattedMessage, useIntl } from "react-intl"; -import slugify from "slugify"; -import CardTitle from "../CardTitle"; -import FormSpacer from "../FormSpacer"; +import { DashboardCard } from "../Card"; enum SeoField { slug = "slug", @@ -28,28 +25,7 @@ const maxTitleLength = 70; const maxDescriptionLength = 300; const useStyles = makeStyles( - theme => ({ - addressBar: { - color: "#006621", - fontSize: "13px", - lineHeight: "16px", - marginBottom: "2px", - overflow: "hidden", - textOverflow: "ellipsis", - whiteSpace: "nowrap", - }, - container: { - width: "100%", - }, - descriptionBar: { - color: "#545454", - fontSize: "13px", - lineHeight: "18px", - overflowWrap: "break-word", - }, - helperText: { - marginBottom: theme.spacing(3), - }, + { label: { flex: 1, }, @@ -59,21 +35,7 @@ const useStyles = makeStyles( }, display: "flex", }, - preview: { - minHeight: theme.spacing(10), - }, - title: { - padding: 0, - }, - titleBar: { - color: "#1a0dab", - fontSize: "18px", - lineHeight: "21px", - overflowWrap: "break-word", - textDecoration: "none", - wordWrap: "break-word", - }, - }), + }, { name: "SeoForm" }, ); @@ -95,7 +57,7 @@ interface SeoFormProps { onClick?(); } -const SeoForm: React.FC = props => { +export const SeoForm: React.FC = props => { const { description, descriptionPlaceholder, @@ -157,17 +119,18 @@ const SeoForm: React.FC = props => { const getError = (fieldName: SeoField) => getFieldError(errors, fieldName); return ( - - + + + - } - /> - - {shouldDisplayHelperText && ( - - {helperText} - - )} + + + + {shouldDisplayHelperText && {helperText}} {expanded && ( -
- maxSlugLength} - name={SeoField.slug} - label={ -
-
- -
- {slug?.length > 0 && ( - - - - )} -
- } - InputProps={{ - inputProps: { - maxLength: maxSlugLength, - }, - }} - helperText={getSlugHelperMessage()} - value={slug} - disabled={loading || disabled} - placeholder={slug || slugify(slugPlaceholder, { lower: true })} - onChange={handleSlugChange} - fullWidth - /> - - + + maxSlugLength} + name={SeoField.slug} + label={ + + + + + {slug?.length > 0 && ( + + + + )} + + } + helperText={getSlugHelperMessage()} + size="small" + value={slug} + onChange={handleSlugChange} + disabled={loading || disabled} + maxLength={maxSlugLength} + placeholder={slugPlaceholder} + /> + + maxTitleLength} name={SeoField.title} - label={ -
-
- -
- {title?.length > 0 && ( - - - - )} -
- } - InputProps={{ - inputProps: { - maxLength: maxTitleLength, - }, - }} - helperText={intl.formatMessage(seoFieldMessage)} value={title ?? ""} disabled={loading || disabled} - placeholder={titlePlaceholder} onChange={onChange} - fullWidth + maxLength={maxTitleLength} + placeholder={titlePlaceholder} + helperText={intl.formatMessage(seoFieldMessage)} + label={ + + + + + {title?.length > 0 && ( + + + + )} + + } /> - maxDescriptionLength} name={SeoField.description} @@ -300,11 +249,9 @@ const SeoForm: React.FC = props => { placeholder={descriptionPlaceholder} rows={10} /> -
+ )} - -
+ + ); }; -SeoForm.displayName = "SeoForm"; -export default SeoForm; diff --git a/src/components/SeoForm/index.ts b/src/components/SeoForm/index.ts index 1f1393243..dc370d80f 100644 --- a/src/components/SeoForm/index.ts +++ b/src/components/SeoForm/index.ts @@ -1,2 +1 @@ -export { default } from "./SeoForm"; export * from "./SeoForm"; diff --git a/src/components/SingleAutocompleteSelectField/SingleAutocompleteSelectField.tsx b/src/components/SingleAutocompleteSelectField/SingleAutocompleteSelectField.tsx index 381379ef4..c694675cf 100644 --- a/src/components/SingleAutocompleteSelectField/SingleAutocompleteSelectField.tsx +++ b/src/components/SingleAutocompleteSelectField/SingleAutocompleteSelectField.tsx @@ -45,13 +45,15 @@ export interface SingleAutocompleteSelectFieldProps nakedInput?: boolean; onBlur?: () => void; popperPlacement?: PopperPlacementType; + id?: string; } -const DebounceAutocomplete: React.ComponentType> = Debounce; +const DebounceAutocomplete: React.ComponentType> = + Debounce; -const SingleAutocompleteSelectFieldComponent: React.FC = props => { +const SingleAutocompleteSelectFieldComponent: React.FC< + SingleAutocompleteSelectFieldProps +> = props => { const { add, allowCustomValues, @@ -78,6 +80,7 @@ const SingleAutocompleteSelectFieldComponent: React.FC {isOpen && (!!inputValue || !!choices.length) && ( = ({ - choices, - fetchChoices, - ...rest -}) => { +const SingleAutocompleteSelectField: React.FC< + SingleAutocompleteSelectFieldProps +> = ({ choices, fetchChoices, ...rest }) => { const [query, setQuery] = React.useState(""); if (fetchChoices) { diff --git a/src/components/TopNavMenu/index.ts b/src/components/TopNavMenu/index.ts deleted file mode 100644 index d1125fc56..000000000 --- a/src/components/TopNavMenu/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./TopNavMenu"; diff --git a/src/customers/components/CustomerDetailsPage/CustomerDetailsPage.tsx b/src/customers/components/CustomerDetailsPage/CustomerDetailsPage.tsx index b18b62904..0eb752109 100644 --- a/src/customers/components/CustomerDetailsPage/CustomerDetailsPage.tsx +++ b/src/customers/components/CustomerDetailsPage/CustomerDetailsPage.tsx @@ -9,7 +9,7 @@ import CardMenu from "@dashboard/components/CardMenu/CardMenu"; import { CardSpacer } from "@dashboard/components/CardSpacer"; import Form from "@dashboard/components/Form"; import { DetailPageLayout } from "@dashboard/components/Layouts"; -import Metadata from "@dashboard/components/Metadata/Metadata"; +import { Metadata } from "@dashboard/components/Metadata/Metadata"; import { MetadataFormData } from "@dashboard/components/Metadata/types"; import RequirePermissions from "@dashboard/components/RequirePermissions"; import Savebar from "@dashboard/components/Savebar"; diff --git a/src/discounts/components/SaleCreatePage/SaleCreatePage.tsx b/src/discounts/components/SaleCreatePage/SaleCreatePage.tsx index 8413672bb..81827b99a 100644 --- a/src/discounts/components/SaleCreatePage/SaleCreatePage.tsx +++ b/src/discounts/components/SaleCreatePage/SaleCreatePage.tsx @@ -3,7 +3,7 @@ import { TopNav } from "@dashboard/components/AppLayout/TopNav"; import ChannelsAvailabilityCard from "@dashboard/components/ChannelsAvailabilityCard"; import Form from "@dashboard/components/Form"; import { DetailPageLayout } from "@dashboard/components/Layouts"; -import Metadata, { MetadataFormData } from "@dashboard/components/Metadata"; +import { Metadata, MetadataFormData } from "@dashboard/components/Metadata"; import Savebar from "@dashboard/components/Savebar"; import { createSaleChannelsChangeHandler } from "@dashboard/discounts/handlers"; import { saleListUrl } from "@dashboard/discounts/urls"; diff --git a/src/discounts/components/SaleDetailsPage/SaleDetailsPage.tsx b/src/discounts/components/SaleDetailsPage/SaleDetailsPage.tsx index 731fac9c4..689b5cf4e 100644 --- a/src/discounts/components/SaleDetailsPage/SaleDetailsPage.tsx +++ b/src/discounts/components/SaleDetailsPage/SaleDetailsPage.tsx @@ -4,7 +4,7 @@ import CardSpacer from "@dashboard/components/CardSpacer"; import ChannelsAvailabilityCard from "@dashboard/components/ChannelsAvailabilityCard"; import Form from "@dashboard/components/Form"; import { DetailPageLayout } from "@dashboard/components/Layouts"; -import Metadata, { MetadataFormData } from "@dashboard/components/Metadata"; +import { Metadata, MetadataFormData } from "@dashboard/components/Metadata"; import Savebar from "@dashboard/components/Savebar"; import { Tab, TabContainer } from "@dashboard/components/Tab"; import { diff --git a/src/discounts/components/VoucherCreatePage/VoucherCreatePage.tsx b/src/discounts/components/VoucherCreatePage/VoucherCreatePage.tsx index 74bca65ed..ee48c1a48 100644 --- a/src/discounts/components/VoucherCreatePage/VoucherCreatePage.tsx +++ b/src/discounts/components/VoucherCreatePage/VoucherCreatePage.tsx @@ -3,7 +3,7 @@ import { TopNav } from "@dashboard/components/AppLayout/TopNav"; import ChannelsAvailabilityCard from "@dashboard/components/ChannelsAvailabilityCard"; import Form from "@dashboard/components/Form"; import { DetailPageLayout } from "@dashboard/components/Layouts"; -import Metadata from "@dashboard/components/Metadata"; +import { Metadata } from "@dashboard/components/Metadata"; import Savebar from "@dashboard/components/Savebar"; import { createChannelsChangeHandler, diff --git a/src/discounts/components/VoucherDetailsPage/VoucherDetailsPage.tsx b/src/discounts/components/VoucherDetailsPage/VoucherDetailsPage.tsx index 7ec5d3e96..5760ccee7 100644 --- a/src/discounts/components/VoucherDetailsPage/VoucherDetailsPage.tsx +++ b/src/discounts/components/VoucherDetailsPage/VoucherDetailsPage.tsx @@ -5,7 +5,7 @@ import ChannelsAvailabilityCard from "@dashboard/components/ChannelsAvailability import CountryList from "@dashboard/components/CountryList"; import Form from "@dashboard/components/Form"; import { DetailPageLayout } from "@dashboard/components/Layouts"; -import Metadata, { MetadataFormData } from "@dashboard/components/Metadata"; +import { Metadata, MetadataFormData } from "@dashboard/components/Metadata"; import Savebar from "@dashboard/components/Savebar"; import { Tab, TabContainer } from "@dashboard/components/Tab"; import { diff --git a/src/giftCards/GiftCardUpdate/GiftCardUpdatePage.tsx b/src/giftCards/GiftCardUpdate/GiftCardUpdatePage.tsx index affde193f..96d0699cf 100644 --- a/src/giftCards/GiftCardUpdate/GiftCardUpdatePage.tsx +++ b/src/giftCards/GiftCardUpdate/GiftCardUpdatePage.tsx @@ -1,6 +1,6 @@ import CardSpacer from "@dashboard/components/CardSpacer"; import { DetailPageLayout } from "@dashboard/components/Layouts"; -import Metadata from "@dashboard/components/Metadata"; +import { Metadata } from "@dashboard/components/Metadata"; import Savebar from "@dashboard/components/Savebar"; import useNavigator from "@dashboard/hooks/useNavigator"; import React from "react"; diff --git a/src/orders/components/OrderDetailsPage/OrderDetailsPage.tsx b/src/orders/components/OrderDetailsPage/OrderDetailsPage.tsx index 19a7bbd5d..91163e436 100644 --- a/src/orders/components/OrderDetailsPage/OrderDetailsPage.tsx +++ b/src/orders/components/OrderDetailsPage/OrderDetailsPage.tsx @@ -9,7 +9,7 @@ import { CardSpacer } from "@dashboard/components/CardSpacer"; import { useDevModeContext } from "@dashboard/components/DevModePanel/hooks"; import Form from "@dashboard/components/Form"; import { DetailPageLayout } from "@dashboard/components/Layouts"; -import Metadata, { MetadataFormData } from "@dashboard/components/Metadata"; +import { Metadata, MetadataFormData } from "@dashboard/components/Metadata"; import Savebar from "@dashboard/components/Savebar"; import { OrderDetailsFragment, diff --git a/src/orders/components/OrderPayment/OrderPayment.tsx b/src/orders/components/OrderPayment/OrderPayment.tsx index eb9333a83..03201bec2 100644 --- a/src/orders/components/OrderPayment/OrderPayment.tsx +++ b/src/orders/components/OrderPayment/OrderPayment.tsx @@ -1,7 +1,6 @@ import { Button } from "@dashboard/components/Button"; import CardTitle from "@dashboard/components/CardTitle"; import HorizontalSpacer from "@dashboard/components/HorizontalSpacer"; -import { Hr } from "@dashboard/components/Hr"; import Money from "@dashboard/components/Money"; import { Pill } from "@dashboard/components/Pill"; import Skeleton from "@dashboard/components/Skeleton"; @@ -12,6 +11,7 @@ import { OrderStatus, } from "@dashboard/graphql"; import { Card, CardContent } from "@material-ui/core"; +import { Divider } from "@saleor/macaw-ui/next"; import clsx from "clsx"; import React from "react"; import { FormattedMessage, useIntl } from "react-intl"; @@ -201,7 +201,7 @@ const OrderPayment: React.FC = props => {
-
+
{!!usedGiftCardAmount && ( diff --git a/src/orders/components/OrderPaymentOrTransaction/OrderPaymentOrTransaction.test.tsx b/src/orders/components/OrderPaymentOrTransaction/OrderPaymentOrTransaction.test.tsx index 20a73b7f4..9318ff0dd 100644 --- a/src/orders/components/OrderPaymentOrTransaction/OrderPaymentOrTransaction.test.tsx +++ b/src/orders/components/OrderPaymentOrTransaction/OrderPaymentOrTransaction.test.tsx @@ -31,6 +31,7 @@ jest.mock("@saleor/macaw-ui", () => ({ jest.mock("@saleor/macaw-ui/next", () => ({ useTheme: jest.fn(() => () => ({})), + Divider: jest.fn(() => <>), vars: { colors: { border: { diff --git a/src/orders/components/OrderPaymentSummaryCard/OrderPaymentSummaryCard.tsx b/src/orders/components/OrderPaymentSummaryCard/OrderPaymentSummaryCard.tsx index 95b3dc17d..eeab3d71b 100644 --- a/src/orders/components/OrderPaymentSummaryCard/OrderPaymentSummaryCard.tsx +++ b/src/orders/components/OrderPaymentSummaryCard/OrderPaymentSummaryCard.tsx @@ -1,6 +1,5 @@ import { Button } from "@dashboard/components/Button"; import CardTitle from "@dashboard/components/CardTitle"; -import { Hr } from "@dashboard/components/Hr"; import { Pill } from "@dashboard/components/Pill"; import Skeleton from "@dashboard/components/Skeleton"; import { OrderAction, OrderDetailsFragment } from "@dashboard/graphql"; @@ -10,6 +9,7 @@ import { orderSendRefundUrl, } from "@dashboard/orders/urls"; import { Card, CardContent, Typography } from "@material-ui/core"; +import { Divider } from "@saleor/macaw-ui/next"; import React from "react"; import { FormattedMessage, useIntl } from "react-intl"; @@ -94,7 +94,7 @@ const OrderPaymentSummaryCard: React.FC = ({ {canAnyRefund && ( <> -
+ diff --git a/src/pageTypes/components/PageTypeCreatePage/PageTypeCreatePage.tsx b/src/pageTypes/components/PageTypeCreatePage/PageTypeCreatePage.tsx index 281fddcbd..3879df8c9 100644 --- a/src/pageTypes/components/PageTypeCreatePage/PageTypeCreatePage.tsx +++ b/src/pageTypes/components/PageTypeCreatePage/PageTypeCreatePage.tsx @@ -3,7 +3,7 @@ import Form from "@dashboard/components/Form"; import Grid from "@dashboard/components/Grid"; import Hr from "@dashboard/components/Hr"; import { DetailPageLayout } from "@dashboard/components/Layouts"; -import Metadata, { MetadataFormData } from "@dashboard/components/Metadata"; +import { Metadata, MetadataFormData } from "@dashboard/components/Metadata"; import Savebar from "@dashboard/components/Savebar"; import { PageErrorFragment } from "@dashboard/graphql"; import useNavigator from "@dashboard/hooks/useNavigator"; diff --git a/src/pageTypes/components/PageTypeDetailsPage/PageTypeDetailsPage.tsx b/src/pageTypes/components/PageTypeDetailsPage/PageTypeDetailsPage.tsx index b5de5f726..2c0f1e594 100644 --- a/src/pageTypes/components/PageTypeDetailsPage/PageTypeDetailsPage.tsx +++ b/src/pageTypes/components/PageTypeDetailsPage/PageTypeDetailsPage.tsx @@ -3,7 +3,7 @@ import Form from "@dashboard/components/Form"; import Grid from "@dashboard/components/Grid"; import Hr from "@dashboard/components/Hr"; import { DetailPageLayout } from "@dashboard/components/Layouts"; -import Metadata from "@dashboard/components/Metadata/Metadata"; +import { Metadata } from "@dashboard/components/Metadata"; import { MetadataFormData } from "@dashboard/components/Metadata/types"; import Savebar from "@dashboard/components/Savebar"; import { SingleAutocompleteChoiceType } from "@dashboard/components/SingleAutocompleteSelectField"; diff --git a/src/pages/components/PageDetailsPage/PageDetailsPage.tsx b/src/pages/components/PageDetailsPage/PageDetailsPage.tsx index 51c9c99d8..b8f11541f 100644 --- a/src/pages/components/PageDetailsPage/PageDetailsPage.tsx +++ b/src/pages/components/PageDetailsPage/PageDetailsPage.tsx @@ -4,12 +4,12 @@ import { } from "@dashboard/attributes/utils/data"; import { TopNav } from "@dashboard/components/AppLayout/TopNav"; import AssignAttributeValueDialog from "@dashboard/components/AssignAttributeValueDialog"; -import Attributes, { AttributeInput } from "@dashboard/components/Attributes"; +import { AttributeInput, Attributes } from "@dashboard/components/Attributes"; import CardSpacer from "@dashboard/components/CardSpacer"; import { DetailPageLayout } from "@dashboard/components/Layouts"; -import Metadata from "@dashboard/components/Metadata"; +import { Metadata } from "@dashboard/components/Metadata"; import Savebar from "@dashboard/components/Savebar"; -import SeoForm from "@dashboard/components/SeoForm"; +import { SeoForm } from "@dashboard/components/SeoForm"; import VisibilityCard from "@dashboard/components/VisibilityCard"; import { PageDetailsFragment, diff --git a/src/productTypes/components/ProductTypeCreatePage/ProductTypeCreatePage.tsx b/src/productTypes/components/ProductTypeCreatePage/ProductTypeCreatePage.tsx index 4386d6c90..6aa1ae7bd 100644 --- a/src/productTypes/components/ProductTypeCreatePage/ProductTypeCreatePage.tsx +++ b/src/productTypes/components/ProductTypeCreatePage/ProductTypeCreatePage.tsx @@ -2,7 +2,7 @@ import { TopNav } from "@dashboard/components/AppLayout/TopNav"; import CardSpacer from "@dashboard/components/CardSpacer"; import Form from "@dashboard/components/Form"; import { DetailPageLayout } from "@dashboard/components/Layouts"; -import Metadata, { MetadataFormData } from "@dashboard/components/Metadata"; +import { Metadata, MetadataFormData } from "@dashboard/components/Metadata"; import Savebar from "@dashboard/components/Savebar"; import { ProductTypeKindEnum, diff --git a/src/productTypes/components/ProductTypeDetailsPage/ProductTypeDetailsPage.tsx b/src/productTypes/components/ProductTypeDetailsPage/ProductTypeDetailsPage.tsx index a722e8658..e52e4df9d 100644 --- a/src/productTypes/components/ProductTypeDetailsPage/ProductTypeDetailsPage.tsx +++ b/src/productTypes/components/ProductTypeDetailsPage/ProductTypeDetailsPage.tsx @@ -3,7 +3,7 @@ import CardSpacer from "@dashboard/components/CardSpacer"; import ControlledSwitch from "@dashboard/components/ControlledSwitch"; import Form from "@dashboard/components/Form"; import { DetailPageLayout } from "@dashboard/components/Layouts"; -import Metadata from "@dashboard/components/Metadata/Metadata"; +import { Metadata } from "@dashboard/components/Metadata/Metadata"; import { MetadataFormData } from "@dashboard/components/Metadata/types"; import Savebar from "@dashboard/components/Savebar"; import { diff --git a/src/products/components/ProductCreatePage/ProductCreatePage.tsx b/src/products/components/ProductCreatePage/ProductCreatePage.tsx index 88d1c1a04..056aa2eae 100644 --- a/src/products/components/ProductCreatePage/ProductCreatePage.tsx +++ b/src/products/components/ProductCreatePage/ProductCreatePage.tsx @@ -6,14 +6,14 @@ import CannotDefineChannelsAvailabilityCard from "@dashboard/channels/components import { ChannelData } from "@dashboard/channels/utils"; import { TopNav } from "@dashboard/components/AppLayout/TopNav"; import AssignAttributeValueDialog from "@dashboard/components/AssignAttributeValueDialog"; -import Attributes, { AttributeInput } from "@dashboard/components/Attributes"; +import { AttributeInput, Attributes } from "@dashboard/components/Attributes"; import CardSpacer from "@dashboard/components/CardSpacer"; import ChannelsAvailabilityCard from "@dashboard/components/ChannelsAvailabilityCard"; import { DetailPageLayout } from "@dashboard/components/Layouts"; -import Metadata from "@dashboard/components/Metadata"; +import { Metadata } from "@dashboard/components/Metadata"; import { MultiAutocompleteChoiceType } from "@dashboard/components/MultiAutocompleteSelectField"; import Savebar from "@dashboard/components/Savebar"; -import SeoForm from "@dashboard/components/SeoForm"; +import { SeoForm } from "@dashboard/components/SeoForm"; import { PermissionEnum, ProductChannelListingErrorFragment, @@ -30,7 +30,7 @@ import { } from "@dashboard/graphql"; import useNavigator from "@dashboard/hooks/useNavigator"; import useStateFromProps from "@dashboard/hooks/useStateFromProps"; -import ProductVariantPrice from "@dashboard/products/components/ProductVariantPrice"; +import { ProductVariantPrice } from "@dashboard/products/components/ProductVariantPrice"; import { ProductCreateUrlQueryParams, productListUrl, @@ -41,10 +41,10 @@ import React from "react"; import { useIntl } from "react-intl"; import { FetchMoreProps, RelayToFlat } from "../../../types"; -import ProductDetailsForm from "../ProductDetailsForm"; -import ProductOrganization from "../ProductOrganization"; -import ProductShipping from "../ProductShipping/ProductShipping"; -import ProductStocks from "../ProductStocks"; +import { ProductDetailsForm } from "../ProductDetailsForm"; +import { ProductOrganization } from "../ProductOrganization"; +import { ProductShipping } from "../ProductShipping"; +import { ProductStocks } from "../ProductStocks"; import ProductTaxes from "../ProductTaxes"; import ProductCreateForm, { ProductCreateData, @@ -263,7 +263,6 @@ export const ProductCreatePage: React.FC = ({ richTextGetters={attributeRichTextGetters} /> )} - {isSimpleProduct && ( <> = ({ weightUnit={weightUnit} onChange={change} /> - - = ({ loading={loading} onChange={change} /> - @@ -341,7 +337,6 @@ export const ProductCreatePage: React.FC = ({ onProductTypeChange={handlers.selectProductType} collectionsInputDisplayValue={selectedCollections} /> - {isSimpleProduct ? ( = ({ data, - disabled, - errors, onChange, + errors, + disabled, }) => { const intl = useIntl(); + const formErrors = getFormErrors(["name", "description", "rating"], errors); const { editorRef, defaultValue, isReadyForMount, handleChange } = useRichTextContext(); - const formErrors = getFormErrors(["name", "description", "rating"], errors); - return ( - - - - + + {intl.formatMessage(commonMessages.generalInformations)} + + + - + {isReadyForMount ? ( = ({ name="description" /> )} - -
- - - + - -
-
+ + + ); }; -export default ProductDetailsForm; diff --git a/src/products/components/ProductDetailsForm/index.ts b/src/products/components/ProductDetailsForm/index.ts index a8c915932..01fce927b 100644 --- a/src/products/components/ProductDetailsForm/index.ts +++ b/src/products/components/ProductDetailsForm/index.ts @@ -1,2 +1 @@ -export { default } from "./ProductDetailsForm"; export * from "./ProductDetailsForm"; diff --git a/src/products/components/ProductExternalMediaDialog/ProductExternalMediaDialog.tsx b/src/products/components/ProductExternalMediaDialog/ProductExternalMediaDialog.tsx index ddd914422..6fd07488f 100644 --- a/src/products/components/ProductExternalMediaDialog/ProductExternalMediaDialog.tsx +++ b/src/products/components/ProductExternalMediaDialog/ProductExternalMediaDialog.tsx @@ -1,17 +1,15 @@ -import BackButton from "@dashboard/components/BackButton"; -import { Button } from "@dashboard/components/Button"; import Form from "@dashboard/components/Form"; import FormSpacer from "@dashboard/components/FormSpacer"; import { ProductFragment } from "@dashboard/graphql"; import { SubmitPromise } from "@dashboard/hooks/useForm"; +import { buttonMessages } from "@dashboard/intl"; import { Dialog, DialogActions, DialogContent, DialogTitle, - TextField, - Typography, } from "@material-ui/core"; +import { Button, Input, Text } from "@saleor/macaw-ui/next"; import React from "react"; import { defineMessages, FormattedMessage, useIntl } from "react-intl"; @@ -52,33 +50,37 @@ const ProductExternalMediaDialog: React.FC = ({ return ( - {intl.formatMessage(messages.buttonMessage)} + + {intl.formatMessage(messages.buttonMessage)} +
{({ change, data, submit }) => ( <> - + - + - - + diff --git a/src/products/components/ProductListPage/ProductListPage.tsx b/src/products/components/ProductListPage/ProductListPage.tsx index fd027a213..5a5de48f6 100644 --- a/src/products/components/ProductListPage/ProductListPage.tsx +++ b/src/products/components/ProductListPage/ProductListPage.tsx @@ -11,7 +11,6 @@ import { getByName } from "@dashboard/components/Filter/utils"; import { FilterPresetsSelect } from "@dashboard/components/FilterPresetsSelect"; import { ListPageLayout } from "@dashboard/components/Layouts"; import LimitReachedAlert from "@dashboard/components/LimitReachedAlert"; -import { TopNavMenu } from "@dashboard/components/TopNavMenu"; import { ProductListColumns } from "@dashboard/config"; import { GridAttributesQuery, @@ -188,7 +187,7 @@ export const ProductListPage: React.FC = props => { )} )} - ({ - card: { - marginTop: theme.spacing(2), - [theme.breakpoints.down("sm")]: { - marginTop: 0, - }, - }, - fileField: { - display: "none", - }, - icon: { - color: "rgba(255, 255, 255, 0.54)", - }, - image: { - height: "100%", - objectFit: "contain", - userSelect: "none", - width: "100%", - }, - imageContainer: { - "&:hover, &.dragged": { - "& $imageOverlay": { - display: "block", - }, - }, - background: "#ffffff", - border: `1px solid ${vars.colors.border.neutralPlain}`, - borderRadius: theme.spacing(), - height: 140, - margin: "auto", - overflow: "hidden", - padding: theme.spacing(2), - position: "relative", - width: 140, - }, - imageGridContainer: { - position: "relative", - }, - imageOverlay: { - background: "rgba(0, 0, 0, 0.6)", - cursor: "move", - display: "none", - height: 140, - left: 0, - padding: theme.spacing(2), - position: "absolute", - top: 0, - width: 140, - }, - imageOverlayToolbar: { - alignContent: "flex-end", - display: "flex", - position: "relative", - right: theme.spacing(-3), - top: theme.spacing(-2), - }, - imageUpload: { - height: "100%", - left: 0, - outline: 0, - position: "absolute", - top: 0, - width: "100%", - }, - imageUploadActive: { - zIndex: 1, - }, - imageUploadIconActive: { - display: "block", - }, - root: { - display: "grid", - gridColumnGap: theme.spacing(2), - gridRowGap: theme.spacing(2), - gridTemplateColumns: "repeat(4, 1fr)", - [theme.breakpoints.down("sm")]: { - gridTemplateColumns: "repeat(3, 1fr)", - }, - [theme.breakpoints.down("xs")]: { - gridTemplateColumns: "repeat(2, 1fr)", - }, - }, - rootDragActive: { - opacity: 0.2, - }, - }), - { name: "ProductMedia" }, -); +import { messages } from "./messages"; interface SortableMediaProps { media: { @@ -163,7 +65,6 @@ const MediaListContainer = SortableContainer( ); interface ProductMediaProps { - placeholderImage?: string; media: ProductMediaFragment[]; loading?: boolean; getImageEditUrl: (id: string) => string; @@ -176,7 +77,6 @@ interface ProductMediaProps { const ProductMedia: React.FC = props => { const { media, - placeholderImage, getImageEditUrl, onImageDelete, onImageReorder, @@ -184,14 +84,12 @@ const ProductMedia: React.FC = props => { openMediaUrlModal, } = props; - const classes = useStyles(props); const intl = useIntl(); const imagesUpload = React.useRef(null); const anchor = React.useRef(); const [imagesToUpload, setImagesToUpload] = React.useState< ProductMediaFragment[] >([]); - const [popperOpenStatus, setPopperOpenStatus] = React.useState(false); const handleImageUpload = createMultiFileUploadHandler(onImageUpload, { onAfterUpload: () => @@ -219,61 +117,92 @@ const ProductMedia: React.FC = props => { }); return ( - - - - - - - handleImageUpload(event.target.files)} - multiple - type="file" - ref={imagesUpload} - accept="image/*" - /> - - } - /> -
- {media === undefined ? ( - -
-
- -
-
-
- ) : media.length > 0 ? ( - <> - - {({ isDragActive }) => ( - + + + + + + + + + + + + imagesUpload.current.click()} + data-test-id="upload-images" + > + {intl.formatMessage(messages.uploadImages)} + + + + + {intl.formatMessage(messages.uploadUrl)} + + + + + + + + + + ) => + handleImageUpload(event.target.files) + } + multiple + type="file" + ref={imagesUpload} + accept="image/*" + /> + + + {media === undefined ? ( + + + + ) : media.length > 0 ? ( + <> + + {({ isDragActive }) => ( = props => { media={media} preview={imagesToUpload} onSortEnd={onImageReorder} - className={clsx({ - [classes.root]: true, - [classes.rootDragActive]: isDragActive, + className={sprinkles({ + display: "grid", + gap: 8, + gridTemplateColumns: { mobile: 2, tablet: 3, desktop: 4 }, + opacity: isDragActive ? "0.2" : "1", })} onDelete={onImageDelete} getEditHref={getImageEditUrl} /> - - )} - - - ) : ( - - )} -
-
+ )} + + + ) : ( + + )} + + + ); }; ProductMedia.displayName = "ProductMedia"; diff --git a/src/products/components/ProductMedia/messages.ts b/src/products/components/ProductMedia/messages.ts new file mode 100644 index 000000000..499b184e2 --- /dev/null +++ b/src/products/components/ProductMedia/messages.ts @@ -0,0 +1,24 @@ +import { defineMessages } from "react-intl"; + +export const messages = defineMessages({ + media: { + id: "/Mcvt4", + defaultMessage: "Media", + description: "section header", + }, + upload: { + id: "mGiA6q", + defaultMessage: "Upload", + description: "modal button upload", + }, + uploadImages: { + id: "9CEu8k", + defaultMessage: "Upload Images", + description: "modal button images upload", + }, + uploadUrl: { + id: "Q2UXlW", + defaultMessage: "Upload URL", + description: "modal button url upload", + }, +}); diff --git a/src/products/components/ProductMediaPopper/ProductMediaPopper.tsx b/src/products/components/ProductMediaPopper/ProductMediaPopper.tsx deleted file mode 100644 index 3df9500cc..000000000 --- a/src/products/components/ProductMediaPopper/ProductMediaPopper.tsx +++ /dev/null @@ -1,78 +0,0 @@ -import { - ClickAwayListener, - Grow, - MenuItem, - MenuList as Menu, - Paper, - Popper, -} from "@material-ui/core"; -import React from "react"; -import { defineMessages, useIntl } from "react-intl"; - -interface ProductMediaPopperProps { - anchorRef: HTMLButtonElement; - imagesUploadRef: HTMLInputElement; - openMediaUrlModal: () => void; - popperStatus: boolean; - setPopperStatus: (popperStatus: boolean) => void; -} - -const messages = defineMessages({ - uploadImages: { - id: "9CEu8k", - defaultMessage: "Upload Images", - description: "modal button images upload", - }, - uploadUrl: { - id: "Q2UXlW", - defaultMessage: "Upload URL", - description: "modal button url upload", - }, -}); - -export const ProductMediaPopper = ({ - anchorRef, - imagesUploadRef, - setPopperStatus, - openMediaUrlModal, - popperStatus, -}: ProductMediaPopperProps) => { - const intl = useIntl(); - - return ( - - {({ TransitionProps }) => ( - - - setPopperStatus(false)} - mouseEvent="onClick" - > - - imagesUploadRef.click()} - data-test-id="upload-images" - key="upload-images" - > - {intl.formatMessage(messages.uploadImages)} - - - {intl.formatMessage(messages.uploadUrl)} - - - - - - )} - - ); -}; diff --git a/src/products/components/ProductOrganization/ProductOrganization.tsx b/src/products/components/ProductOrganization/ProductOrganization.tsx index dbbb9e2cf..e21a2733d 100644 --- a/src/products/components/ProductOrganization/ProductOrganization.tsx +++ b/src/products/components/ProductOrganization/ProductOrganization.tsx @@ -1,7 +1,4 @@ -import CardSpacer from "@dashboard/components/CardSpacer"; -import CardTitle from "@dashboard/components/CardTitle"; -import { FormSpacer } from "@dashboard/components/FormSpacer"; -import Hr from "@dashboard/components/Hr"; +import { DashboardCard } from "@dashboard/components/Card"; import Link from "@dashboard/components/Link"; import MultiAutocompleteSelectField, { MultiAutocompleteChoiceType, @@ -16,12 +13,10 @@ import { } from "@dashboard/graphql"; import { ChangeEvent } from "@dashboard/hooks/useForm"; import { commonMessages } from "@dashboard/intl"; -import { maybe } from "@dashboard/misc"; import { productTypeUrl } from "@dashboard/productTypes/urls"; import { FetchMoreProps } from "@dashboard/types"; import { getFormErrors, getProductErrorMessage } from "@dashboard/utils/errors"; -import { Card, CardContent, Typography } from "@material-ui/core"; -import { makeStyles } from "@saleor/macaw-ui"; +import { Box, Text } from "@saleor/macaw-ui/next"; import React from "react"; import { FormattedMessage, useIntl } from "react-intl"; @@ -31,22 +26,6 @@ interface ProductType { name: string; } -const useStyles = makeStyles( - theme => ({ - card: { - overflow: "visible", - }, - cardSubtitle: { - fontSize: theme.typography.body1.fontSize, - marginBottom: theme.spacing(0.5), - }, - label: { - marginBottom: theme.spacing(0.5), - }, - }), - { name: "ProductOrganization" }, -); - interface ProductOrganizationProps { canChangeType: boolean; categories?: SingleAutocompleteChoiceType[]; @@ -74,7 +53,9 @@ interface ProductOrganizationProps { onProductTypeChange?: (event: ChangeEvent) => void; } -const ProductOrganization: React.FC = props => { +export const ProductOrganization: React.FC< + ProductOrganizationProps +> = props => { const { canChangeType, categories, @@ -98,7 +79,6 @@ const ProductOrganization: React.FC = props => { onProductTypeChange, } = props; - const classes = useStyles(props); const intl = useIntl(); const formErrors = getFormErrors( @@ -111,15 +91,15 @@ const ProductOrganization: React.FC = props => { : null; return ( - - + + {intl.formatMessage({ id: "JjeZEG", defaultMessage: "Organize Product", description: "section header", })} - /> - + + {canChangeType ? ( = props => { {...fetchMoreProductTypes} /> ) : ( - <> - - - - - - {productType?.name ?? "..."} - - - - - - - - {maybe( - () => - productType.hasVariants - ? intl.formatMessage(commonMessages.yes) - : intl.formatMessage(commonMessages.no), - "...", - )} - - + + + + + + + + {productType?.name ?? "..."} + + + + + + + + + + {productType?.hasVariants + ? intl.formatMessage(commonMessages.yes) + : intl.formatMessage(commonMessages.no)} + + + )} - -
- = props => { data-test-id="category" {...fetchMoreCategories} /> - -
- = props => { testId="collection" {...fetchMoreCollections} /> - -
+ + ); }; -ProductOrganization.displayName = "ProductOrganization"; -export default ProductOrganization; diff --git a/src/products/components/ProductOrganization/index.ts b/src/products/components/ProductOrganization/index.ts index 5ef78dde8..b7c870e6a 100644 --- a/src/products/components/ProductOrganization/index.ts +++ b/src/products/components/ProductOrganization/index.ts @@ -1,2 +1 @@ -export { default } from "./ProductOrganization"; export * from "./ProductOrganization"; diff --git a/src/products/components/ProductShipping/ProductShipping.tsx b/src/products/components/ProductShipping/ProductShipping.tsx index abc09329b..35355efbe 100644 --- a/src/products/components/ProductShipping/ProductShipping.tsx +++ b/src/products/components/ProductShipping/ProductShipping.tsx @@ -1,14 +1,8 @@ -import CardTitle from "@dashboard/components/CardTitle"; -import Grid from "@dashboard/components/Grid"; +import { DashboardCard } from "@dashboard/components/Card"; import { ProductErrorFragment } from "@dashboard/graphql"; import { getFormErrors, getProductErrorMessage } from "@dashboard/utils/errors"; import createNonNegativeValueChangeHandler from "@dashboard/utils/handlers/nonNegativeValueChangeHandler"; -import { - Card, - CardContent, - InputAdornment, - TextField, -} from "@material-ui/core"; +import { InputAdornment, TextField } from "@material-ui/core"; import React from "react"; import { useIntl } from "react-intl"; @@ -22,7 +16,7 @@ interface ProductShippingProps { onChange: (event: React.ChangeEvent) => void; } -const ProductShipping: React.FC = props => { +export const ProductShipping: React.FC = props => { const { data, disabled, errors, weightUnit, onChange } = props; const intl = useIntl(); @@ -31,43 +25,38 @@ const ProductShipping: React.FC = props => { const handleChange = createNonNegativeValueChangeHandler(onChange); return ( - - + + {intl.formatMessage({ id: "3rIMq/", defaultMessage: "Shipping", description: "product shipping", })} - /> - - - - {weightUnit || ""} - - ), - inputProps: { - min: 0, - }, - }} - /> - - - + + + {weightUnit || ""} + ), + inputProps: { + min: 0, + }, + }} + /> + + ); }; -ProductShipping.displayName = "ProductShipping"; -export default ProductShipping; diff --git a/src/products/components/ProductShipping/index.ts b/src/products/components/ProductShipping/index.ts index e69de29bb..9f62e5e7e 100644 --- a/src/products/components/ProductShipping/index.ts +++ b/src/products/components/ProductShipping/index.ts @@ -0,0 +1 @@ +export * from "./ProductShipping"; diff --git a/src/products/components/ProductStocks/ProductStocks.tsx b/src/products/components/ProductStocks/ProductStocks.tsx index 13c3db949..cd91273e9 100644 --- a/src/products/components/ProductStocks/ProductStocks.tsx +++ b/src/products/components/ProductStocks/ProductStocks.tsx @@ -2,11 +2,8 @@ import { ChannelData, ChannelPriceAndPreorderArgs, } from "@dashboard/channels/utils"; -import CardTitle from "@dashboard/components/CardTitle"; -import ControlledCheckbox from "@dashboard/components/ControlledCheckbox"; +import { DashboardCard } from "@dashboard/components/Card"; import { DateTimeTimezoneField } from "@dashboard/components/DateTimeTimezoneField"; -import FormSpacer from "@dashboard/components/FormSpacer"; -import Hr from "@dashboard/components/Hr"; import Link from "@dashboard/components/Link"; import PreviewPill from "@dashboard/components/PreviewPill"; import TableRowLink from "@dashboard/components/TableRowLink"; @@ -17,22 +14,20 @@ import { sectionNames } from "@dashboard/intl"; import { renderCollection } from "@dashboard/misc"; import { getFormErrors, getProductErrorMessage } from "@dashboard/utils/errors"; import createNonNegativeValueChangeHandler from "@dashboard/utils/handlers/nonNegativeValueChangeHandler"; +import { Table, TableBody, TableCell, TableHead } from "@material-ui/core"; import { - Card, - CardContent, - ClickAwayListener, - Grow, - MenuItem, - Paper, - Popper, - Table, - TableBody, - TableCell, - TableHead, - TextField, - Typography, -} from "@material-ui/core"; -import { Button, DeleteIcon, IconButton, PlusIcon } from "@saleor/macaw-ui"; + Box, + Button, + Checkbox, + Dropdown, + Input, + List, + PlusIcon, + sprinkles, + Text, + TrashBinIcon, + vars, +} from "@saleor/macaw-ui/next"; import React from "react"; import { FormattedMessage, useIntl } from "react-intl"; @@ -40,7 +35,6 @@ import { ProductCreateData } from "../ProductCreatePage"; import { ProductVariantCreateData } from "../ProductVariantCreatePage/form"; import { ProductVariantUpdateData } from "../ProductVariantPage/form"; import { messages } from "./messages"; -import { useStyles } from "./styles"; export interface ProductStockFormsetData { quantityAllocated: number; @@ -84,7 +78,7 @@ export interface ProductStocksProps { onWarehouseConfigure: () => void; } -const ProductStocks: React.FC = ({ +export const ProductStocks: React.FC = ({ data, disabled, hasVariants, @@ -102,11 +96,8 @@ const ProductStocks: React.FC = ({ onWarehouseStockDelete, onWarehouseConfigure, }) => { - const classes = useStyles(); const intl = useIntl(); - const anchor = React.useRef(); const [lastStockRowFocus, setLastStockRowFocus] = React.useState(false); - const [isExpanded, setExpansionState] = React.useState(false); const unitsLeft = parseInt(data.globalThreshold, 10) - data.globalSoldUnits; const warehousesToAssign = @@ -141,131 +132,129 @@ const ProductStocks: React.FC = ({ }; return ( - - - -
- + + {intl.formatMessage(messages.title)} + + + + -
- - - - - } - /> + - {!data.isPreorder && ( - <> - - + { + if (onEndPreorderTrigger && data.isPreorder) { + onEndPreorderTrigger(); + } else { + onFormDataChange({ target: { name: "isPreorder", value } }); + } + }} + disabled={disabled} + > + + + + + + + + + {!data.isPreorder && ( + - - - - - + onCheckedChange={value => + onFormDataChange({ target: { name: "trackInventory", value } }) } - /> - - )} -
-
- {!data.isPreorder && ( - - -
- - - -
-
- {!productVariantChannelListings?.length && ( - <> - - - - - + > + + + + + + + + + )} - {!warehouses?.length && ( - - {hasVariants ? ( - <> - ( - {chunks} - ), - }} - /> - - ) : ( - <> - ( - {chunks} - ), - }} - /> - + {!data.isPreorder && ( + + + + + + {!productVariantChannelListings?.length && ( + + + + )} + + {!warehouses?.length && ( + + {hasVariants ? ( + ( + {chunks} + ), + }} + /> + ) : ( + ( + {chunks} + ), + }} + /> + )} + )} - + )} -
- )} + + {productVariantChannelListings?.length > 0 && warehouses?.length > 0 && !data.isPreorder && ( - - - - - - - + + + + - - + + + + - - + + + + - + @@ -277,195 +266,192 @@ const ProductStocks: React.FC = ({ return ( - - {stock.label} + + {stock.label} - - {stock.data?.quantityAllocated || 0} + + {stock.data?.quantityAllocated || 0} - - + + size="small" + type="number" + min={0} + ref={input => stocks.length === index + 1 && handleStockInputFocus(input) } /> - - +
)} {data.isPreorder && ( - - - - - - {data.hasPreorderEndDate && ( -
- + + + + + {data.hasPreorderEndDate && ( + + + onChangePreorderEndDate({ + target: { + name: "preorderEndDateTime", + value: event, + }, + }) + } + /> + + )} + {/* @ts-ignore */} + +
- )} - - - - -
- - {productVariantChannelListings?.length > 0 && ( - - {data.globalThreshold - ? intl.formatMessage(messages.preorderTresholdUnitsLeft, { - unitsLeft, - }) - : intl.formatMessage(messages.preorderTresholdUnlimited)} - - )} -
-
+ {data.hasPreorderEndDate + ? intl.formatMessage(messages.endDateCancel) + : intl.formatMessage(messages.endDateSetup)} + + + + + + + + + + + + + + {productVariantChannelListings?.length > 0 && ( + + {data.globalThreshold + ? intl.formatMessage(messages.preorderTresholdUnitsLeft, { + unitsLeft, + }) + : intl.formatMessage(messages.preorderTresholdUnlimited)} + + )} + + + )} {productVariantChannelListings?.length > 0 && data.isPreorder && ( - - - - - - - + + + + - - + + + + - - + + + + @@ -477,25 +463,18 @@ const ProductStocks: React.FC = ({ return ( - - {listing.name} + + {listing.name} - - {listing?.unitsSold || 0} + + {listing?.unitsSold || 0} - - + { onVariantChannelListingChange(listing.id, { costPrice: listing.costPrice, @@ -507,6 +486,10 @@ const ProductStocks: React.FC = ({ }); }} value={listing?.preorderThreshold ?? ""} + size="small" + placeholder={intl.formatMessage( + messages.preorderTresholdUnlimited, + )} /> @@ -515,9 +498,6 @@ const ProductStocks: React.FC = ({
)} -
+ ); }; - -ProductStocks.displayName = "ProductStocks"; -export default ProductStocks; diff --git a/src/products/components/ProductStocks/index.ts b/src/products/components/ProductStocks/index.ts index ef1830648..3478b12c9 100644 --- a/src/products/components/ProductStocks/index.ts +++ b/src/products/components/ProductStocks/index.ts @@ -1,2 +1 @@ export * from "./ProductStocks"; -export { default } from "./ProductStocks"; diff --git a/src/products/components/ProductStocks/styles.ts b/src/products/components/ProductStocks/styles.ts deleted file mode 100644 index 09c874455..000000000 --- a/src/products/components/ProductStocks/styles.ts +++ /dev/null @@ -1,107 +0,0 @@ -import { ICONBUTTON_SIZE, makeStyles } from "@saleor/macaw-ui"; -import { vars } from "@saleor/macaw-ui/next"; - -export const useStyles = makeStyles( - theme => ({ - colAction: { - padding: 0, - width: `calc(${ICONBUTTON_SIZE}px + ${theme.spacing(1)})`, - }, - colName: {}, - colQuantity: { - textAlign: "right", - width: 150, - }, - colSoldUnits: { - textAlign: "right", - width: 150, - }, - colThreshold: { - textAlign: "right", - width: 180, - }, - editWarehouses: { - marginRight: theme.spacing(-1), - }, - input: { - padding: theme.spacing(1.5), - textAlign: "right", - }, - menuItem: { - "&:not(:last-of-type)": { - marginBottom: theme.spacing(2), - }, - }, - noWarehouseInfo: { - marginTop: theme.spacing(), - }, - paper: { - padding: theme.spacing(2), - maxHeight: 400, - overflow: "scroll", - border: `1px solid ${vars.colors.border.neutralDefault}`, - borderRadius: vars.borderRadius[3], - }, - popper: { - marginTop: theme.spacing(1), - zIndex: 2, - }, - quantityContainer: { - paddingTop: theme.spacing(), - }, - quantityHeader: { - alignItems: "center", - display: "flex", - justifyContent: "space-between", - }, - skuInputContainer: { - display: "grid", - gridColumnGap: theme.spacing(3), - gridTemplateColumns: "repeat(2, 1fr)", - }, - dateTimeInputs: { - marginTop: theme.spacing(2), - marginBottom: theme.spacing(2), - }, - preorderInfo: { - marginBottom: theme.spacing(2), - marginTop: theme.spacing(2), - display: "block", - }, - caption: { - fontSize: 14, - }, - thresholdRow: { - display: "grid", - gridColumnGap: theme.spacing(3), - gridTemplateColumns: "3fr 1fr", - marginTop: theme.spacing(1), - }, - thresholdInput: { - maxWidth: 400, - }, - addRow: { - "&:hover": { - cursor: "pointer", - "& $actionableText": { - color: theme.palette.primary.main, - }, - }, - }, - actionableText: {}, - preorderItemsLeftCount: { - fontSize: 14, - paddingTop: theme.spacing(2), - textAlign: "center", - }, - preorderLimitInfo: { - marginTop: theme.spacing(3), - }, - preview: { - marginLeft: theme.spacing(1), - }, - }), - { - name: "ProductStocks", - }, -); diff --git a/src/products/components/ProductUpdatePage/ProductUpdatePage.stories.tsx b/src/products/components/ProductUpdatePage/ProductUpdatePage.stories.tsx index 0289fd625..107737190 100644 --- a/src/products/components/ProductUpdatePage/ProductUpdatePage.stories.tsx +++ b/src/products/components/ProductUpdatePage/ProductUpdatePage.stories.tsx @@ -56,7 +56,6 @@ const props: ProductUpdatePageProps = { onSubmit: () => undefined, onVariantShow: () => undefined, refetch: () => undefined, - placeholderImage, product, referencePages: [], referenceProducts: [], diff --git a/src/products/components/ProductUpdatePage/ProductUpdatePage.test.tsx b/src/products/components/ProductUpdatePage/ProductUpdatePage.test.tsx index ea1e6da21..570855406 100644 --- a/src/products/components/ProductUpdatePage/ProductUpdatePage.test.tsx +++ b/src/products/components/ProductUpdatePage/ProductUpdatePage.test.tsx @@ -66,7 +66,6 @@ const props: ProductUpdatePageProps = { onMediaUrlUpload: () => undefined, onSubmit, onVariantShow: () => undefined, - placeholderImage, product, referencePages: [], referenceProducts: [], diff --git a/src/products/components/ProductUpdatePage/ProductUpdatePage.tsx b/src/products/components/ProductUpdatePage/ProductUpdatePage.tsx index 5f5a7d9b2..53f060f0f 100644 --- a/src/products/components/ProductUpdatePage/ProductUpdatePage.tsx +++ b/src/products/components/ProductUpdatePage/ProductUpdatePage.tsx @@ -10,15 +10,14 @@ import { import { ChannelData } from "@dashboard/channels/utils"; import { TopNav } from "@dashboard/components/AppLayout/TopNav"; import AssignAttributeValueDialog from "@dashboard/components/AssignAttributeValueDialog"; -import Attributes, { AttributeInput } from "@dashboard/components/Attributes"; -import CardMenu from "@dashboard/components/CardMenu"; +import { AttributeInput, Attributes } from "@dashboard/components/Attributes"; import CardSpacer from "@dashboard/components/CardSpacer"; import ChannelsAvailabilityCard from "@dashboard/components/ChannelsAvailabilityCard"; import { useDevModeContext } from "@dashboard/components/DevModePanel/hooks"; import { DetailPageLayout } from "@dashboard/components/Layouts"; -import Metadata from "@dashboard/components/Metadata/Metadata"; +import { Metadata } from "@dashboard/components/Metadata/Metadata"; import Savebar from "@dashboard/components/Savebar"; -import SeoForm from "@dashboard/components/SeoForm"; +import { SeoForm } from "@dashboard/components/SeoForm"; import { Choice } from "@dashboard/components/SingleSelectField"; import { ChannelFragment, @@ -52,9 +51,9 @@ import React from "react"; import { useIntl } from "react-intl"; import { getChoices } from "../../utils/data"; -import ProductDetailsForm from "../ProductDetailsForm"; +import { ProductDetailsForm } from "../ProductDetailsForm"; import ProductMedia from "../ProductMedia"; -import ProductOrganization from "../ProductOrganization"; +import { ProductOrganization } from "../ProductOrganization"; import ProductTaxes from "../ProductTaxes"; import ProductVariants from "../ProductVariants"; import ProductUpdateForm from "./form"; @@ -72,7 +71,6 @@ export interface ProductUpdatePageProps { channelsErrors: ProductChannelListingErrorFragment[]; variantListErrors: ProductVariantListError[]; errors: UseProductUpdateHandlerError[]; - placeholderImage: string; collections: RelayToFlat; categories: RelayToFlat; attributeValues: RelayToFlat< @@ -139,7 +137,6 @@ export const ProductUpdatePage: React.FC = ({ media, header, limits, - placeholderImage, product, saveButtonBarState, variants, @@ -326,8 +323,8 @@ export const ProductUpdatePage: React.FC = ({ return ( - = ({ testId: "graphiql-redirect", }, ]} - data-test-id="menu" + dataTestId="menu" /> @@ -349,7 +346,6 @@ export const ProductUpdatePage: React.FC = ({ ({ - colPrice: { - textAlign: "right", - verticalAlign: "middle", - width: 200, - }, - colType: { - fontSize: 14, - textAlign: "right", - width: 200, - }, - input: { - textAlign: "left", - }, - pricingContent: { - "&:last-child": { - paddingBottom: 0, - }, - paddingLeft: 0, - paddingRight: 0, - }, - table: { - tableLayout: "fixed", - }, - }), - { name: "ProductVariantPrice" }, -); - interface ProductVariantPriceProps { ProductVariantChannelListings?: ChannelData[]; errors?: ProductChannelListingErrorFragment[]; @@ -70,7 +34,9 @@ interface ProductVariantPriceProps { const numberOfColumns = 2; -const ProductVariantPrice: React.FC = props => { +export const ProductVariantPrice: React.FC< + ProductVariantPriceProps +> = props => { const { disabled = false, errors = [], @@ -79,22 +45,21 @@ const ProductVariantPrice: React.FC = props => { onChange, disabledMessage, } = props; - const classes = useStyles(props); const intl = useIntl(); const formErrors = getFormChannelErrors(["price", "costPrice"], errors); if (disabled || !ProductVariantChannelListings.length) { return ( - - + + {intl.formatMessage({ id: "Xm9qOu", defaultMessage: "Pricing", description: "product pricing, section header", })} - /> - - + + + {intl.formatMessage( disabledMessage || { id: "e48Igh", @@ -103,54 +68,60 @@ const ProductVariantPrice: React.FC = props => { description: "variant pricing section subtitle", }, )} - - - + + + ); } return ( - - + + {intl.formatMessage({ id: "Xm9qOu", defaultMessage: "Pricing", description: "product pricing, section header", })} - /> - - + + + {intl.formatMessage({ id: "VvA7ai", defaultMessage: "Channels that don’t have assigned prices will use their parent channel to define the price. Price will be converted to channel’s currency", description: "info text", })} - - - + + + - - + + + + - - + + + + - - + + + + @@ -169,11 +140,12 @@ const ProductVariantPrice: React.FC = props => { return ( - {listing?.name || } - + + {listing?.name || } + + {listing ? ( = props => { )} - + {listing ? ( = props => { () => ( - + + + ), )} - + ); }; -ProductVariantPrice.displayName = "ProductVariantPrice"; -export default ProductVariantPrice; diff --git a/src/products/components/ProductVariantPrice/index.ts b/src/products/components/ProductVariantPrice/index.ts index 104957ff1..1a561d004 100644 --- a/src/products/components/ProductVariantPrice/index.ts +++ b/src/products/components/ProductVariantPrice/index.ts @@ -1,2 +1 @@ -export { default } from "./ProductVariantPrice"; export * from "./ProductVariantPrice"; diff --git a/src/products/utils/data.ts b/src/products/utils/data.ts index 5f9db0059..dd66fc722 100644 --- a/src/products/utils/data.ts +++ b/src/products/utils/data.ts @@ -250,7 +250,7 @@ export const getPreorderEndHourFormData = (endDate?: string) => endDate ? moment(endDate).format("HH:mm") : ""; export const getSelectedMedia = < - T extends Pick + T extends Pick, >( media: T[] = [], selectedMediaIds: string[], diff --git a/src/products/views/ProductUpdate/ProductUpdate.tsx b/src/products/views/ProductUpdate/ProductUpdate.tsx index b163d6885..0e77274e4 100644 --- a/src/products/views/ProductUpdate/ProductUpdate.tsx +++ b/src/products/views/ProductUpdate/ProductUpdate.tsx @@ -1,4 +1,3 @@ -import placeholderImg from "@assets/images/placeholder255x255.png"; import ActionDialog from "@dashboard/components/ActionDialog"; import useAppChannel from "@dashboard/components/AppLayout/AppChannelContext"; import { AttributeInput } from "@dashboard/components/Attributes"; @@ -114,10 +113,8 @@ export const ProductUpdate: React.FC = ({ id, params }) => { }, }); - const [ - reorderProductImages, - reorderProductImagesOpts, - ] = useProductMediaReorderMutation({}); + const [reorderProductImages, reorderProductImagesOpts] = + useProductMediaReorderMutation({}); const [deleteProduct, deleteProductOpts] = useProductDeleteMutation({ onCompleted: () => { @@ -132,25 +129,23 @@ export const ProductUpdate: React.FC = ({ id, params }) => { }, }); - const [ - createProductImage, - createProductImageOpts, - ] = useProductMediaCreateMutation({ - onCompleted: data => { - const imageError = data.productMediaCreate.errors.find( - error => - error.field === - ("image" as keyof ProductMediaCreateMutationVariables), - ); - if (imageError) { - notify({ - status: "error", - title: intl.formatMessage(errorMessages.imgageUploadErrorTitle), - text: intl.formatMessage(errorMessages.imageUploadErrorText), - }); - } - }, - }); + const [createProductImage, createProductImageOpts] = + useProductMediaCreateMutation({ + onCompleted: data => { + const imageError = data.productMediaCreate.errors.find( + error => + error.field === + ("image" as keyof ProductMediaCreateMutationVariables), + ); + if (imageError) { + notify({ + status: "error", + title: intl.formatMessage(errorMessages.imgageUploadErrorTitle), + text: intl.formatMessage(errorMessages.imageUploadErrorText), + }); + } + }, + }); const [deleteProductImage] = useProductMediaDeleteMutation({ onCompleted: () => @@ -175,28 +170,26 @@ export const ProductUpdate: React.FC = ({ id, params }) => { }, }); - const [ - createProductMedia, - createProductMediaOpts, - ] = useProductMediaCreateMutation({ - onCompleted: data => { - const errors = data.productMediaCreate.errors; + const [createProductMedia, createProductMediaOpts] = + useProductMediaCreateMutation({ + onCompleted: data => { + const errors = data.productMediaCreate.errors; - if (errors.length) { - errors.map(error => + if (errors.length) { + errors.map(error => + notify({ + status: "error", + text: getProductErrorMessage(error, intl), + }), + ); + } else { notify({ - status: "error", - text: getProductErrorMessage(error, intl), - }), - ); - } else { - notify({ - status: "success", - text: intl.formatMessage(commonMessages.savedChanges), - }); - } - }, - }); + status: "success", + text: intl.formatMessage(commonMessages.savedChanges), + }); + } + }, + }); const handleMediaUrlUpload = (mediaUrl: string) => { const variables = { @@ -282,8 +275,9 @@ export const ProductUpdate: React.FC = ({ id, params }) => { ); const fetchMoreAttributeValues = { - hasMore: !!searchAttributeValuesOpts.data?.attribute?.choices?.pageInfo - ?.hasNextPage, + hasMore: + !!searchAttributeValuesOpts.data?.attribute?.choices?.pageInfo + ?.hasNextPage, loading: !!searchAttributeValuesOpts.loading, onFetchMore: loadMoreAttributeValues, }; @@ -316,7 +310,6 @@ export const ProductUpdate: React.FC = ({ id, params }) => { saveButtonBarState={formTransitionState} media={data?.product?.media} header={product?.name} - placeholderImage={placeholderImg} product={product} warehouses={warehouses} taxClasses={taxClasses ?? []} diff --git a/src/shipping/components/ShippingZoneDetailsPage/ShippingZoneDetailsPage.tsx b/src/shipping/components/ShippingZoneDetailsPage/ShippingZoneDetailsPage.tsx index 0ec066328..71f089bf6 100644 --- a/src/shipping/components/ShippingZoneDetailsPage/ShippingZoneDetailsPage.tsx +++ b/src/shipping/components/ShippingZoneDetailsPage/ShippingZoneDetailsPage.tsx @@ -3,7 +3,7 @@ import CardSpacer from "@dashboard/components/CardSpacer"; import CountryList from "@dashboard/components/CountryList"; import Form from "@dashboard/components/Form"; import { DetailPageLayout } from "@dashboard/components/Layouts"; -import Metadata from "@dashboard/components/Metadata/Metadata"; +import { Metadata } from "@dashboard/components/Metadata/Metadata"; import { MultiAutocompleteChoiceType } from "@dashboard/components/MultiAutocompleteSelectField"; import Savebar from "@dashboard/components/Savebar"; import { SingleAutocompleteChoiceType } from "@dashboard/components/SingleAutocompleteSelectField"; diff --git a/src/shipping/components/ShippingZoneRatesPage/ShippingZoneRatesPage.tsx b/src/shipping/components/ShippingZoneRatesPage/ShippingZoneRatesPage.tsx index 7f6a90446..246ff075d 100644 --- a/src/shipping/components/ShippingZoneRatesPage/ShippingZoneRatesPage.tsx +++ b/src/shipping/components/ShippingZoneRatesPage/ShippingZoneRatesPage.tsx @@ -4,7 +4,7 @@ import CardSpacer from "@dashboard/components/CardSpacer"; import ChannelsAvailabilityCard from "@dashboard/components/ChannelsAvailabilityCard"; import { WithFormId } from "@dashboard/components/Form"; import { DetailPageLayout } from "@dashboard/components/Layouts"; -import Metadata from "@dashboard/components/Metadata/Metadata"; +import { Metadata } from "@dashboard/components/Metadata/Metadata"; import Savebar from "@dashboard/components/Savebar"; import { PermissionEnum, diff --git a/src/taxes/pages/TaxClassesPage/TaxClassesPage.tsx b/src/taxes/pages/TaxClassesPage/TaxClassesPage.tsx index 20c53062b..75ae70944 100644 --- a/src/taxes/pages/TaxClassesPage/TaxClassesPage.tsx +++ b/src/taxes/pages/TaxClassesPage/TaxClassesPage.tsx @@ -2,7 +2,7 @@ import { TopNav } from "@dashboard/components/AppLayout/TopNav"; import CardTitle from "@dashboard/components/CardTitle"; import Grid from "@dashboard/components/Grid"; import { DetailPageLayout } from "@dashboard/components/Layouts"; -import Metadata from "@dashboard/components/Metadata"; +import { Metadata } from "@dashboard/components/Metadata"; import Savebar from "@dashboard/components/Savebar"; import Skeleton from "@dashboard/components/Skeleton"; import VerticalSpacer from "@dashboard/components/VerticalSpacer";