diff --git a/src/assets/images/integration-types/abb.png b/src/assets/images/integration-types/abb.png new file mode 100644 index 00000000..7f548016 Binary files /dev/null and b/src/assets/images/integration-types/abb.png differ diff --git a/src/assets/images/integration-types/icons/abb.svg b/src/assets/images/integration-types/icons/abb.svg new file mode 100644 index 00000000..4158d89f --- /dev/null +++ b/src/assets/images/integration-types/icons/abb.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/src/assets/images/integration-types/icons/mirakl.svg b/src/assets/images/integration-types/icons/mirakl.svg new file mode 100644 index 00000000..f84a0f67 --- /dev/null +++ b/src/assets/images/integration-types/icons/mirakl.svg @@ -0,0 +1,193 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/images/integration-types/icons/no_image.svg b/src/assets/images/integration-types/icons/no_image.svg new file mode 100644 index 00000000..442ef378 --- /dev/null +++ b/src/assets/images/integration-types/icons/no_image.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/assets/images/integration-types/icons/openai.png b/src/assets/images/integration-types/icons/openai.png new file mode 100644 index 00000000..23c2564c Binary files /dev/null and b/src/assets/images/integration-types/icons/openai.png differ diff --git a/src/assets/images/integration-types/mirakl.png b/src/assets/images/integration-types/mirakl.png new file mode 100644 index 00000000..996a3e2d Binary files /dev/null and b/src/assets/images/integration-types/mirakl.png differ diff --git a/src/assets/images/integration-types/no_image.jpg b/src/assets/images/integration-types/no_image.jpg new file mode 100644 index 00000000..58df114b Binary files /dev/null and b/src/assets/images/integration-types/no_image.jpg differ diff --git a/src/assets/images/integrations/mirakl/representation-types/allow_backorder.png b/src/assets/images/integrations/mirakl/representation-types/allow_backorder.png new file mode 100644 index 00000000..4f735ed9 Binary files /dev/null and b/src/assets/images/integrations/mirakl/representation-types/allow_backorder.png differ diff --git a/src/assets/images/integrations/mirakl/representation-types/condition.png b/src/assets/images/integrations/mirakl/representation-types/condition.png new file mode 100644 index 00000000..f8d7ace9 Binary files /dev/null and b/src/assets/images/integrations/mirakl/representation-types/condition.png differ diff --git a/src/assets/images/integrations/mirakl/representation-types/default_value.png b/src/assets/images/integrations/mirakl/representation-types/default_value.png new file mode 100644 index 00000000..012d49a6 Binary files /dev/null and b/src/assets/images/integrations/mirakl/representation-types/default_value.png differ diff --git a/src/assets/images/integrations/mirakl/representation-types/discounted_price.png b/src/assets/images/integrations/mirakl/representation-types/discounted_price.png new file mode 100644 index 00000000..4ead88d5 Binary files /dev/null and b/src/assets/images/integrations/mirakl/representation-types/discounted_price.png differ diff --git a/src/assets/images/integrations/mirakl/representation-types/document.png b/src/assets/images/integrations/mirakl/representation-types/document.png new file mode 100644 index 00000000..b8727f59 Binary files /dev/null and b/src/assets/images/integrations/mirakl/representation-types/document.png differ diff --git a/src/assets/images/integrations/mirakl/representation-types/image.png b/src/assets/images/integrations/mirakl/representation-types/image.png new file mode 100644 index 00000000..d1d34653 Binary files /dev/null and b/src/assets/images/integrations/mirakl/representation-types/image.png differ diff --git a/src/assets/images/integrations/mirakl/representation-types/price.png b/src/assets/images/integrations/mirakl/representation-types/price.png new file mode 100644 index 00000000..8635c90b Binary files /dev/null and b/src/assets/images/integrations/mirakl/representation-types/price.png differ diff --git a/src/assets/images/integrations/mirakl/representation-types/product_active.png b/src/assets/images/integrations/mirakl/representation-types/product_active.png new file mode 100644 index 00000000..c5deaba8 Binary files /dev/null and b/src/assets/images/integrations/mirakl/representation-types/product_active.png differ diff --git a/src/assets/images/integrations/mirakl/representation-types/product_bullet_point.png b/src/assets/images/integrations/mirakl/representation-types/product_bullet_point.png new file mode 100644 index 00000000..88ab763b Binary files /dev/null and b/src/assets/images/integrations/mirakl/representation-types/product_bullet_point.png differ diff --git a/src/assets/images/integrations/mirakl/representation-types/product_category.png b/src/assets/images/integrations/mirakl/representation-types/product_category.png new file mode 100644 index 00000000..84a1c575 Binary files /dev/null and b/src/assets/images/integrations/mirakl/representation-types/product_category.png differ diff --git a/src/assets/images/integrations/mirakl/representation-types/product_configurable_sku.png b/src/assets/images/integrations/mirakl/representation-types/product_configurable_sku.png new file mode 100644 index 00000000..92f4c410 Binary files /dev/null and b/src/assets/images/integrations/mirakl/representation-types/product_configurable_sku.png differ diff --git a/src/assets/images/integrations/mirakl/representation-types/product_description.png b/src/assets/images/integrations/mirakl/representation-types/product_description.png new file mode 100644 index 00000000..77d5f2d0 Binary files /dev/null and b/src/assets/images/integrations/mirakl/representation-types/product_description.png differ diff --git a/src/assets/images/integrations/mirakl/representation-types/product_ean.png b/src/assets/images/integrations/mirakl/representation-types/product_ean.png new file mode 100644 index 00000000..566e740e Binary files /dev/null and b/src/assets/images/integrations/mirakl/representation-types/product_ean.png differ diff --git a/src/assets/images/integrations/mirakl/representation-types/product_short_description.png b/src/assets/images/integrations/mirakl/representation-types/product_short_description.png new file mode 100644 index 00000000..186ff368 Binary files /dev/null and b/src/assets/images/integrations/mirakl/representation-types/product_short_description.png differ diff --git a/src/assets/images/integrations/mirakl/representation-types/product_sku.png b/src/assets/images/integrations/mirakl/representation-types/product_sku.png new file mode 100644 index 00000000..e1300960 Binary files /dev/null and b/src/assets/images/integrations/mirakl/representation-types/product_sku.png differ diff --git a/src/assets/images/integrations/mirakl/representation-types/product_subtitle.png b/src/assets/images/integrations/mirakl/representation-types/product_subtitle.png new file mode 100644 index 00000000..855e9d99 Binary files /dev/null and b/src/assets/images/integrations/mirakl/representation-types/product_subtitle.png differ diff --git a/src/assets/images/integrations/mirakl/representation-types/product_title.png b/src/assets/images/integrations/mirakl/representation-types/product_title.png new file mode 100644 index 00000000..6ebe0429 Binary files /dev/null and b/src/assets/images/integrations/mirakl/representation-types/product_title.png differ diff --git a/src/assets/images/integrations/mirakl/representation-types/product_url_key.png b/src/assets/images/integrations/mirakl/representation-types/product_url_key.png new file mode 100644 index 00000000..79d71bff Binary files /dev/null and b/src/assets/images/integrations/mirakl/representation-types/product_url_key.png differ diff --git a/src/assets/images/integrations/mirakl/representation-types/property.png b/src/assets/images/integrations/mirakl/representation-types/property.png new file mode 100644 index 00000000..32c8a9b7 Binary files /dev/null and b/src/assets/images/integrations/mirakl/representation-types/property.png differ diff --git a/src/assets/images/integrations/mirakl/representation-types/stock.png b/src/assets/images/integrations/mirakl/representation-types/stock.png new file mode 100644 index 00000000..1efc8763 Binary files /dev/null and b/src/assets/images/integrations/mirakl/representation-types/stock.png differ diff --git a/src/assets/images/integrations/mirakl/representation-types/swatch_image.png b/src/assets/images/integrations/mirakl/representation-types/swatch_image.png new file mode 100644 index 00000000..a76060f1 Binary files /dev/null and b/src/assets/images/integrations/mirakl/representation-types/swatch_image.png differ diff --git a/src/assets/images/integrations/mirakl/representation-types/thumbnail_image.png b/src/assets/images/integrations/mirakl/representation-types/thumbnail_image.png new file mode 100644 index 00000000..04de63a3 Binary files /dev/null and b/src/assets/images/integrations/mirakl/representation-types/thumbnail_image.png differ diff --git a/src/assets/images/integrations/mirakl/representation-types/unit.png b/src/assets/images/integrations/mirakl/representation-types/unit.png new file mode 100644 index 00000000..6d707ab1 Binary files /dev/null and b/src/assets/images/integrations/mirakl/representation-types/unit.png differ diff --git a/src/assets/images/integrations/mirakl/representation-types/vat_rate.png b/src/assets/images/integrations/mirakl/representation-types/vat_rate.png new file mode 100644 index 00000000..1b812034 Binary files /dev/null and b/src/assets/images/integrations/mirakl/representation-types/vat_rate.png differ diff --git a/src/assets/images/integrations/mirakl/representation-types/video.png b/src/assets/images/integrations/mirakl/representation-types/video.png new file mode 100644 index 00000000..d86a705e Binary files /dev/null and b/src/assets/images/integrations/mirakl/representation-types/video.png differ diff --git a/src/assets/images/integrations/mirakl/template-download-placeholder.png b/src/assets/images/integrations/mirakl/template-download-placeholder.png new file mode 100644 index 00000000..79e88c4c Binary files /dev/null and b/src/assets/images/integrations/mirakl/template-download-placeholder.png differ diff --git a/src/core/dashboard/dashboard/containers/dashboard-cards/DashboardCards.vue b/src/core/dashboard/dashboard/containers/dashboard-cards/DashboardCards.vue index 072b1160..74abc631 100644 --- a/src/core/dashboard/dashboard/containers/dashboard-cards/DashboardCards.vue +++ b/src/core/dashboard/dashboard/containers/dashboard-cards/DashboardCards.vue @@ -3,6 +3,7 @@ import { computed } from 'vue'; import { DashboardUserSections } from "./containers/dashboard-user-sections"; import { DashboardSectionAmazon } from "./containers/dashboard-section-amazon"; import { DashboardSectionEbay } from "./containers/dashboard-section-ebay"; +import { DashboardSectionMirakl } from "./containers/dashboard-section-mirakl"; import { DashboardSectionShein } from "./containers/dashboard-section-shein"; import { injectAuth } from "../../../../../shared/modules/auth"; @@ -10,6 +11,7 @@ const auth = injectAuth(); const hasAmazonIntegration = computed(() => Boolean(auth.user.company?.hasAmazonIntegration)); const hasEbayIntegration = computed(() => Boolean(auth.user.company?.hasEbayIntegration)); +const hasMiraklIntegration = computed(() => Boolean(auth.user.company?.hasMiraklIntegration)); const hasSheinIntegration = computed(() => Boolean(auth.user.company?.hasSheinIntegration)); @@ -19,6 +21,7 @@ const hasSheinIntegration = computed(() => Boolean(auth.user.company?.hasSheinIn + diff --git a/src/core/dashboard/dashboard/containers/dashboard-cards/containers/dashboard-section-mirakl/DashboardSectionMirakl.vue b/src/core/dashboard/dashboard/containers/dashboard-cards/containers/dashboard-section-mirakl/DashboardSectionMirakl.vue new file mode 100644 index 00000000..2e7837e7 --- /dev/null +++ b/src/core/dashboard/dashboard/containers/dashboard-cards/containers/dashboard-section-mirakl/DashboardSectionMirakl.vue @@ -0,0 +1,336 @@ + + + diff --git a/src/core/dashboard/dashboard/containers/dashboard-cards/containers/dashboard-section-mirakl/index.ts b/src/core/dashboard/dashboard/containers/dashboard-cards/containers/dashboard-section-mirakl/index.ts new file mode 100644 index 00000000..a9fa44d5 --- /dev/null +++ b/src/core/dashboard/dashboard/containers/dashboard-cards/containers/dashboard-section-mirakl/index.ts @@ -0,0 +1 @@ +export { default as DashboardSectionMirakl } from './DashboardSectionMirakl.vue'; diff --git a/src/core/integrations/integrations/configs.ts b/src/core/integrations/integrations/configs.ts index 8b8045bb..147c87aa 100644 --- a/src/core/integrations/integrations/configs.ts +++ b/src/core/integrations/integrations/configs.ts @@ -4,6 +4,7 @@ import {integrationsQuery} from "../../../shared/api/queries/integrations.js"; import {SearchConfig} from "../../../shared/components/organisms/general-search/searchConfig"; import {IntegrationTypes} from "./integrations"; import {deleteIntegrationMutation} from "../../../shared/api/mutations/salesChannels"; +import { getMiraklSubtypeBadge, isKnownMiraklSubType } from "./miraklSubtypes"; export const searchConfigConstructor = (t: Function): SearchConfig => ({ search: true, @@ -34,9 +35,33 @@ export const listingIntegrationTypeBadgeMap = (t: Function) => ({ [IntegrationTypes.Amazon]: { text: 'Amazon', color: 'yellow' }, [IntegrationTypes.Webhook]: { text: t('integrations.integrationTypes.webhook'), color: 'indigo' }, [IntegrationTypes.Ebay]: { text: 'Ebay', color: 'purple' }, - [IntegrationTypes.Shein]: { text: 'Shein', color: 'pink' } + [IntegrationTypes.Shein]: { text: 'Shein', color: 'pink' }, + [IntegrationTypes.Mirakl]: { text: 'Mirakl', color: 'indigo' } }); +const getIntegrationListingBadge = (item: any, t: Function) => { + const miraklSubtypeBadge = getMiraklSubtypeBadge(item?.type); + if (miraklSubtypeBadge) { + return miraklSubtypeBadge; + } + return listingIntegrationTypeBadgeMap(t)[item?.type] || { text: item?.type || '-', color: 'gray' }; +}; + +const getIntegrationShowRoute = (item: any) => { + const integrationType = item?.node?.type; + const isMiraklLike = + integrationType === IntegrationTypes.Mirakl || + isKnownMiraklSubType(integrationType); + + return { + name: 'integrations.integrations.show', + params: { + id: item.node.proxyId, + type: isMiraklLike ? IntegrationTypes.Mirakl : integrationType + } + }; +}; + export const listingConfigConstructor = (t: Function): ListingConfig => ({ headers: [ t('integrations.labels.hostname'), @@ -48,13 +73,19 @@ export const listingConfigConstructor = (t: Function): ListingConfig => ({ ], fields: [ { name: 'hostname', type: FieldType.Text }, - { name: 'type', type: FieldType.Badge, badgeMap: listingIntegrationTypeBadgeMap(t) }, + { + name: 'type', + type: FieldType.Badge, + badgeMap: listingIntegrationTypeBadgeMap(t), + accessor: (item: any) => getIntegrationListingBadge(item, t) + }, { name: 'active', type: FieldType.Boolean }, { name: 'verifySsl', type: FieldType.Boolean }, { name: 'connected', type: FieldType.Boolean }, { name: 'requestsPerMinute', type: FieldType.Text }, ], showUrlName: 'integrations.integrations.show', + showRouteResolver: getIntegrationShowRoute, deleteMutation: deleteIntegrationMutation, identifierKey: 'proxyId', deleteIdentifierKey: 'id', @@ -71,4 +102,4 @@ export function cleanShopHostname(input: string): string { return url.hostname; } export const listingQueryKey = 'integrations'; -export const listingQuery = integrationsQuery; \ No newline at end of file +export const listingQuery = integrationsQuery; diff --git a/src/core/integrations/integrations/integrations-create/IntegrationCreateController.vue b/src/core/integrations/integrations/integrations-create/IntegrationCreateController.vue index ed3a9dfa..4f8f2385 100644 --- a/src/core/integrations/integrations/integrations-create/IntegrationCreateController.vue +++ b/src/core/integrations/integrations/integrations-create/IntegrationCreateController.vue @@ -1,71 +1,118 @@ + + diff --git a/src/core/integrations/integrations/integrations-create/containers/integration-specific-step/mirakl/index.ts b/src/core/integrations/integrations/integrations-create/containers/integration-specific-step/mirakl/index.ts new file mode 100644 index 00000000..23466ee3 --- /dev/null +++ b/src/core/integrations/integrations/integrations-create/containers/integration-specific-step/mirakl/index.ts @@ -0,0 +1 @@ +export { default as MiraklChannelInfoStep } from './MiraklChannelInfoStep.vue'; diff --git a/src/core/integrations/integrations/integrations-create/containers/type-step/TypeStep.vue b/src/core/integrations/integrations/integrations-create/containers/type-step/TypeStep.vue index 9ec207ff..f0ba6bab 100644 --- a/src/core/integrations/integrations/integrations-create/containers/type-step/TypeStep.vue +++ b/src/core/integrations/integrations/integrations-create/containers/type-step/TypeStep.vue @@ -1,177 +1,769 @@ diff --git a/src/core/integrations/integrations/integrations-create/containers/type-step/info-cards/MagentoInfoCard.vue b/src/core/integrations/integrations/integrations-create/containers/type-step/info-cards/MagentoInfoCard.vue index f49487e0..f221a379 100644 --- a/src/core/integrations/integrations/integrations-create/containers/type-step/info-cards/MagentoInfoCard.vue +++ b/src/core/integrations/integrations/integrations-create/containers/type-step/info-cards/MagentoInfoCard.vue @@ -1,85 +1,128 @@ diff --git a/src/core/integrations/integrations/integrations-create/containers/type-step/info-cards/MiraklInfoCard.vue b/src/core/integrations/integrations/integrations-create/containers/type-step/info-cards/MiraklInfoCard.vue new file mode 100644 index 00000000..78d0a2f3 --- /dev/null +++ b/src/core/integrations/integrations/integrations-create/containers/type-step/info-cards/MiraklInfoCard.vue @@ -0,0 +1,178 @@ + + + diff --git a/src/core/integrations/integrations/integrations-create/containers/type-step/info-cards/ShopifyInfoCard.vue b/src/core/integrations/integrations/integrations-create/containers/type-step/info-cards/ShopifyInfoCard.vue index f2193f56..a022208f 100644 --- a/src/core/integrations/integrations/integrations-create/containers/type-step/info-cards/ShopifyInfoCard.vue +++ b/src/core/integrations/integrations/integrations-create/containers/type-step/info-cards/ShopifyInfoCard.vue @@ -1,125 +1,103 @@ diff --git a/src/core/integrations/integrations/integrations-create/containers/type-step/info-cards/WoocommerceInfoCard.vue b/src/core/integrations/integrations/integrations-create/containers/type-step/info-cards/WoocommerceInfoCard.vue index 54faefa3..acb6757b 100644 --- a/src/core/integrations/integrations/integrations-create/containers/type-step/info-cards/WoocommerceInfoCard.vue +++ b/src/core/integrations/integrations/integrations-create/containers/type-step/info-cards/WoocommerceInfoCard.vue @@ -1,41 +1,121 @@ diff --git a/src/core/integrations/integrations/integrations-create/containers/type-step/info-cards/index.ts b/src/core/integrations/integrations/integrations-create/containers/type-step/info-cards/index.ts index ea416212..e480a8c6 100644 --- a/src/core/integrations/integrations/integrations-create/containers/type-step/info-cards/index.ts +++ b/src/core/integrations/integrations/integrations-create/containers/type-step/info-cards/index.ts @@ -1,4 +1,5 @@ export { default as MagentoInfoCard } from './MagentoInfoCard.vue'; +export { default as MiraklInfoCard } from './MiraklInfoCard.vue'; export { default as WoocommerceInfoCard } from './WoocommerceInfoCard.vue'; export { default as ShopifyInfoCard } from './ShopifyInfoCard.vue'; export { default as WebhookInfoCard } from './WebhookInfoCard.vue'; diff --git a/src/core/integrations/integrations/integrations-show/IntegrationsShowController.vue b/src/core/integrations/integrations/integrations-show/IntegrationsShowController.vue index 6ec53252..b32a0f6e 100644 --- a/src/core/integrations/integrations/integrations-show/IntegrationsShowController.vue +++ b/src/core/integrations/integrations/integrations-show/IntegrationsShowController.vue @@ -14,7 +14,8 @@ import { getWoocommerceChannelQuery, getAmazonChannelQuery, getEbayChannelQuery, - getSheinChannelQuery + getSheinChannelQuery, + getMiraklChannelQuery } from "../../../../shared/api/queries/salesChannels.js"; import { getWebhookIntegrationQuery } from "../../../../shared/api/queries/webhookIntegrations.js"; import { AmazonGeneralInfoTab } from "./containers/general/amazon-general-tab"; @@ -24,6 +25,7 @@ import { WoocommerceGeneralInfoTab } from "./containers/general/woocommerce-gene import { WebhookGeneralInfoTab } from "./containers/general/webhook-general-tab"; import { EbayGeneralInfoTab } from "./containers/general/ebay-general-tab"; import { SheinGeneralInfoTab } from "./containers/general/shein-general-tab"; +import { MiraklGeneralInfoTab } from "./containers/general/mirakl-general-tab"; import apolloClient from "../../../../../apollo-client"; import { Loader } from "../../../../shared/components/atoms/loader"; import { Products } from "./containers/products"; @@ -39,7 +41,7 @@ import { DocumentTypes } from "./containers/document-types"; import { DefaultUnitConfigurators } from "./containers/default-unit-configurators"; import { Imports } from "./containers/imports"; import { Templates } from "./containers/templates"; -import { AmazonProductIssues } from "./containers/issues"; +import { AmazonProductIssues, MiraklProductIssues } from "./containers/issues"; import { refreshSalesChannelWebsitesMutation } from "../../../../shared/api/mutations/salesChannels"; import {Toast} from "../../../../shared/modules/toast"; @@ -61,8 +63,15 @@ const integrationData = ref(null); const gptFeed = ref(null); const initialGptEnabled = ref(false); +type IntegrationTabItem = { + name: string; + label: string; + icon: string; + group?: string; + hidden?: boolean; +}; -const tabItems = ref([ +const tabItems = ref([ { name: 'general', label: t('shared.tabs.general'), icon: 'circle-info' } ]); @@ -78,8 +87,8 @@ if (type.value !== IntegrationTypes.Webhook) { if (type.value === IntegrationTypes.Amazon) { tabItems.value.push( - { name: 'productRules', label: t('properties.rule.title'), icon: 'cog' }, { name: 'documentTypes', label: t('integrations.show.documentTypes.title'), icon: 'file-text' }, + { name: 'productRules', label: t('properties.rule.title'), icon: 'cog' }, { name: 'properties', label: t('properties.title'), icon: 'screwdriver-wrench' }, { name: 'propertySelectValues', label: t('properties.values.title'), icon: 'sitemap' }, { name: 'defaultUnits', label: t('integrations.show.sections.defaultUnits'), icon: 'weight-hanging' }, @@ -87,9 +96,9 @@ if (type.value !== IntegrationTypes.Webhook) { ); } else if (type.value === IntegrationTypes.Ebay) { tabItems.value.push( + { name: 'documentTypes', label: t('integrations.show.documentTypes.title'), icon: 'file-text' }, { name: 'inventoryFields', label: t('integrations.show.ebay.internalProperties.title'), icon: 'boxes-stacked' }, { name: 'productRules', label: t('properties.rule.title'), icon: 'cog' }, - { name: 'documentTypes', label: t('integrations.show.documentTypes.title'), icon: 'file-text' }, { name: 'properties', label: t('properties.title'), icon: 'screwdriver-wrench' }, { name: 'propertySelectValues', label: t('properties.values.title'), icon: 'sitemap' } ); @@ -101,9 +110,25 @@ if (type.value !== IntegrationTypes.Webhook) { { name: 'properties', label: t('properties.title'), icon: 'screwdriver-wrench' }, { name: 'propertySelectValues', label: t('properties.values.title'), icon: 'sitemap' } ); + } else if (type.value === IntegrationTypes.Mirakl) { + tabItems.value.push( + { name: 'documentTypes', label: t('integrations.show.documentTypes.title'), icon: 'file-text' }, + { name: 'defaultUnits', label: t('integrations.show.sections.defaultUnits'), icon: 'weight-hanging' }, + { name: 'productRules', label: t('properties.rule.title'), icon: 'cog' }, + { name: 'properties', label: t('properties.title'), icon: 'screwdriver-wrench' }, + { name: 'propertySelectValues', label: t('properties.values.title'), icon: 'sitemap' }, + { name: 'issues', label: t('integrations.show.tabs.issues'), icon: 'triangle-exclamation' } + ); } - tabItems.value.push({ name: 'imports', label: t('shared.tabs.imports'), icon: 'file-import' }); + if (type.value === IntegrationTypes.Mirakl) { + tabItems.value.push( + { name: 'imports', label: t('shared.tabs.imports'), icon: 'file-import', group: 'imports' }, + { name: 'miraklImports', label: t('shared.tabs.imports'), icon: 'file-import', group: 'imports', hidden: true }, + ); + } else { + tabItems.value.push({ name: 'imports', label: t('shared.tabs.imports'), icon: 'file-import' }); + } } else { tabItems.value.push( { name: 'monitor', label: t('webhooks.monitor.title'), icon: 'wave-square' }, @@ -126,6 +151,8 @@ const getIntegrationQuery = () => { return getEbayChannelQuery; case IntegrationTypes.Shein: return getSheinChannelQuery; + case IntegrationTypes.Mirakl: + return getMiraklChannelQuery; case IntegrationTypes.Webhook: return getWebhookIntegrationQuery; default: @@ -149,6 +176,8 @@ const getIntegrationQueryKey = () => { return "ebayChannel"; case IntegrationTypes.Shein: return "sheinChannel"; + case IntegrationTypes.Mirakl: + return "miraklChannel"; default: return "salesChannel"; } @@ -170,6 +199,8 @@ const getGeneralComponent = () => { return EbayGeneralInfoTab; case IntegrationTypes.Shein: return SheinGeneralInfoTab; + case IntegrationTypes.Mirakl: + return MiraklGeneralInfoTab; default: return null; } @@ -352,6 +383,10 @@ const pullData = async () => { + + diff --git a/src/core/integrations/integrations/integrations-show/containers/currencies/Currencies.vue b/src/core/integrations/integrations/integrations-show/containers/currencies/Currencies.vue index 89337951..c2ebd862 100644 --- a/src/core/integrations/integrations/integrations-show/containers/currencies/Currencies.vue +++ b/src/core/integrations/integrations/integrations-show/containers/currencies/Currencies.vue @@ -5,18 +5,21 @@ import { GeneralListing } from "../../../../../../shared/components/organisms/ge import { currenciesSearchConfigConstructor, currenciesListingConfigConstructor, - listingQuery, - listingQueryKey + listingQueryConstructor, + listingQueryKeyConstructor } from "./configs"; import { Button } from "../../../../../../shared/components/atoms/button"; +import { useRoute } from 'vue-router'; const props = defineProps<{ id: string; salesChannelId: string }>(); const emit = defineEmits(['pull-data']); +const route = useRoute(); const { t } = useI18n(); +const integrationType = String(route.params.type); const searchConfig = currenciesSearchConfigConstructor(t); -const listingConfig = currenciesListingConfigConstructor(t, props.id); +const listingConfig = currenciesListingConfigConstructor(t, props.id, integrationType); diff --git a/src/core/integrations/integrations/integrations-show/containers/currencies/configs.ts b/src/core/integrations/integrations/integrations-show/containers/currencies/configs.ts index 0978ee90..79b1363b 100644 --- a/src/core/integrations/integrations/integrations-show/containers/currencies/configs.ts +++ b/src/core/integrations/integrations/integrations-show/containers/currencies/configs.ts @@ -1,11 +1,17 @@ import { FieldType } from "../../../../../../shared/utils/constants"; -import {getRemoteCurrencyQuery, remoteCurrenciesQuery} from "../../../../../../shared/api/queries/salesChannels.js"; +import { + getRemoteCurrencyQuery, + remoteCurrenciesQuery, + miraklRemoteCurrenciesQuery, + getMiraklRemoteCurrencyQuery, +} from "../../../../../../shared/api/queries/salesChannels.js"; import { ListingConfig } from "../../../../../../shared/components/organisms/general-listing/listingConfig"; import {FormConfig, FormType} from '../../../../../../shared/components/organisms/general-form/formConfig'; import {currenciesQuerySelector} from "../../../../../../shared/api/queries/currencies.js"; import {currencyOnTheFlyConfig} from "../../../../../settings/currencies/configs"; -import {updateRemoteCurrencyMutation} from "../../../../../../shared/api/mutations/salesChannels.js"; +import {updateRemoteCurrencyMutation, updateMiraklRemoteCurrencyMutation} from "../../../../../../shared/api/mutations/salesChannels.js"; import {SearchConfig} from "../../../../../../shared/components/organisms/general-search/searchConfig"; +import { IntegrationTypes } from "../../../integrations"; export const currencyEditFormConfigConstructor = ( t: Function, @@ -15,11 +21,11 @@ export const currencyEditFormConfigConstructor = ( ): FormConfig => ({ cols: 1, type: FormType.EDIT, - mutation: updateRemoteCurrencyMutation, - mutationKey: "updateRemoteCurrency", - query: getRemoteCurrencyQuery, + mutation: type === IntegrationTypes.Mirakl ? updateMiraklRemoteCurrencyMutation : updateRemoteCurrencyMutation, + mutationKey: type === IntegrationTypes.Mirakl ? "updateMiraklRemoteCurrency" : "updateRemoteCurrency", + query: type === IntegrationTypes.Mirakl ? getMiraklRemoteCurrencyQuery : getRemoteCurrencyQuery, queryVariables: { id: currencyId }, - queryDataKey: "remoteCurrency", + queryDataKey: type === IntegrationTypes.Mirakl ? "miraklRemoteCurrency" : "remoteCurrency", submitUrl: { name: 'integrations.integrations.show', params: { type: type, id: integrationId }, query: { tab: 'currencies' } }, fields: [ { @@ -65,10 +71,11 @@ export const currenciesSearchConfigConstructor = (t: Function): SearchConfig => orders: [] }); -export const currenciesListingConfigConstructor = (t: Function, specificIntegrationId): ListingConfig => ({ +export const currenciesListingConfigConstructor = (t: Function, specificIntegrationId: string, type: string): ListingConfig => ({ headers: [ - t('integrations.show.currencies.labels.remoteCode'), + t(type === IntegrationTypes.Mirakl ? 'integrations.show.currencies.labels.label' : 'integrations.show.currencies.labels.remoteCode'), t('shared.labels.currency'), + ...(type === IntegrationTypes.Mirakl ? [t('shared.labels.default')] : []), ], fields: [ { name: 'name', type: FieldType.Text }, @@ -78,19 +85,23 @@ export const currenciesListingConfigConstructor = (t: Function, specificIntegrat label: t('currencies.labels.localCurrency'), keys: ['name'], showLabel: true - } + }, + ...(type === IntegrationTypes.Mirakl ? [{ name: 'isDefault', type: FieldType.Boolean as const }] : []), ], identifierKey: 'id', addActions: true, - addEdit: true, + addEdit: type !== IntegrationTypes.Mirakl, urlQueryParams: {integrationId: specificIntegrationId }, editUrlName: 'integrations.currencies.edit', showUrlName: 'integrations.currencies.edit', - addShow: true, + addShow: type !== IntegrationTypes.Mirakl, addDelete: false, addPagination: true, }); -export const listingQueryKey = 'remoteCurrencies'; -export const listingQuery = remoteCurrenciesQuery; +export const listingQueryKeyConstructor = (type: string) => + type === IntegrationTypes.Mirakl ? 'miraklRemoteCurrencies' : 'remoteCurrencies'; + +export const listingQueryConstructor = (type: string) => + type === IntegrationTypes.Mirakl ? miraklRemoteCurrenciesQuery : remoteCurrenciesQuery; diff --git a/src/core/integrations/integrations/integrations-show/containers/default-unit-configurators/DefaultUnitConfigurators.vue b/src/core/integrations/integrations/integrations-show/containers/default-unit-configurators/DefaultUnitConfigurators.vue index 60ef6a52..9fda5f84 100644 --- a/src/core/integrations/integrations/integrations-show/containers/default-unit-configurators/DefaultUnitConfigurators.vue +++ b/src/core/integrations/integrations/integrations-show/containers/default-unit-configurators/DefaultUnitConfigurators.vue @@ -2,6 +2,7 @@ import { computed } from 'vue'; import { IntegrationTypes } from '../../../integrations'; import { AmazonDefaultUnitConfigurators } from './containers/amazon-unit-configurators'; +import { MiraklDefaultUnitConfigurators } from './containers/mirakl-unit-configurators'; const props = defineProps<{ id: string; salesChannelId: string; type: string }>(); const emit = defineEmits(['pull-data']); @@ -10,6 +11,8 @@ const currentComponent = computed(() => { switch (props.type) { case IntegrationTypes.Amazon: return AmazonDefaultUnitConfigurators; + case IntegrationTypes.Mirakl: + return MiraklDefaultUnitConfigurators; default: return null; } diff --git a/src/core/integrations/integrations/integrations-show/containers/default-unit-configurators/containers/mirakl-unit-configurators/MiraklDefaultUnitConfigurators.vue b/src/core/integrations/integrations/integrations-show/containers/default-unit-configurators/containers/mirakl-unit-configurators/MiraklDefaultUnitConfigurators.vue new file mode 100644 index 00000000..4589393e --- /dev/null +++ b/src/core/integrations/integrations/integrations-show/containers/default-unit-configurators/containers/mirakl-unit-configurators/MiraklDefaultUnitConfigurators.vue @@ -0,0 +1,83 @@ + + + diff --git a/src/core/integrations/integrations/integrations-show/containers/default-unit-configurators/containers/mirakl-unit-configurators/configs.ts b/src/core/integrations/integrations/integrations-show/containers/default-unit-configurators/containers/mirakl-unit-configurators/configs.ts new file mode 100644 index 00000000..306885dc --- /dev/null +++ b/src/core/integrations/integrations/integrations-show/containers/default-unit-configurators/containers/mirakl-unit-configurators/configs.ts @@ -0,0 +1,39 @@ +import { FieldType } from "../../../../../../../../shared/utils/constants"; +import { miraklPropertiesQuery } from "../../../../../../../../shared/api/queries/salesChannels.js"; +import type { ListingConfig } from "../../../../../../../../shared/components/organisms/general-listing/listingConfig"; +import type { SearchConfig } from "../../../../../../../../shared/components/organisms/general-search/searchConfig"; + +export const miraklDefaultUnitConfiguratorsSearchConfigConstructor = (): SearchConfig => ({ + search: true, + orderKey: "sort", + filters: [], + orders: [], +}); + +export const miraklDefaultUnitConfiguratorsListingConfigConstructor = ( + t: Function, + specificIntegrationId: string, +): ListingConfig => ({ + headers: [ + t('shared.labels.name'), + t('integrations.show.properties.labels.code'), + t('integrations.show.mirakl.defaultUnits.labels.selectedUnit'), + ], + fields: [ + { name: 'name', type: FieldType.Text }, + { name: 'code', type: FieldType.Text }, + { name: 'defaultValue', type: FieldType.Text }, + ], + identifierKey: 'id', + urlQueryParams: { integrationId: specificIntegrationId }, + addActions: true, + addEdit: true, + addShow: true, + editUrlName: 'integrations.miraklDefaultUnitConfigurators.edit', + showUrlName: 'integrations.miraklDefaultUnitConfigurators.edit', + addDelete: false, + addPagination: true, +}); + +export const listingQueryKey = 'miraklProperties'; +export const listingQuery = miraklPropertiesQuery; diff --git a/src/core/integrations/integrations/integrations-show/containers/default-unit-configurators/containers/mirakl-unit-configurators/containers/IntegrationsMiraklDefaultUnitConfiguratorEditController.vue b/src/core/integrations/integrations/integrations-show/containers/default-unit-configurators/containers/mirakl-unit-configurators/containers/IntegrationsMiraklDefaultUnitConfiguratorEditController.vue new file mode 100644 index 00000000..f7f5df1d --- /dev/null +++ b/src/core/integrations/integrations/integrations-show/containers/default-unit-configurators/containers/mirakl-unit-configurators/containers/IntegrationsMiraklDefaultUnitConfiguratorEditController.vue @@ -0,0 +1,300 @@ + + + diff --git a/src/core/integrations/integrations/integrations-show/containers/default-unit-configurators/containers/mirakl-unit-configurators/index.ts b/src/core/integrations/integrations/integrations-show/containers/default-unit-configurators/containers/mirakl-unit-configurators/index.ts new file mode 100644 index 00000000..32719e10 --- /dev/null +++ b/src/core/integrations/integrations/integrations-show/containers/default-unit-configurators/containers/mirakl-unit-configurators/index.ts @@ -0,0 +1 @@ +export { default as MiraklDefaultUnitConfigurators } from './MiraklDefaultUnitConfigurators.vue'; diff --git a/src/core/integrations/integrations/integrations-show/containers/general/mirakl-general-tab/MiraklGeneralInfoTab.vue b/src/core/integrations/integrations/integrations-show/containers/general/mirakl-general-tab/MiraklGeneralInfoTab.vue new file mode 100644 index 00000000..07d72d96 --- /dev/null +++ b/src/core/integrations/integrations/integrations-show/containers/general/mirakl-general-tab/MiraklGeneralInfoTab.vue @@ -0,0 +1,304 @@ + + + diff --git a/src/core/integrations/integrations/integrations-show/containers/general/mirakl-general-tab/index.ts b/src/core/integrations/integrations/integrations-show/containers/general/mirakl-general-tab/index.ts new file mode 100644 index 00000000..6dfbc06c --- /dev/null +++ b/src/core/integrations/integrations/integrations-show/containers/general/mirakl-general-tab/index.ts @@ -0,0 +1 @@ +export { default as MiraklGeneralInfoTab } from './MiraklGeneralInfoTab.vue'; diff --git a/src/core/integrations/integrations/integrations-show/containers/imports/Imports.vue b/src/core/integrations/integrations/integrations-show/containers/imports/Imports.vue index d4e4ae19..5b633631 100644 --- a/src/core/integrations/integrations/integrations-show/containers/imports/Imports.vue +++ b/src/core/integrations/integrations/integrations-show/containers/imports/Imports.vue @@ -2,7 +2,7 @@ import { ref, computed } from 'vue'; import { useRoute } from 'vue-router'; import { IntegrationTypes } from "../../../integrations"; -import { AmazonImportsListing, EbayImportsListing, SheinImportsListing, GeneralImportsListing } from './components'; +import { AmazonImportsListing, EbayImportsListing, SheinImportsListing, MiraklImportsListing, GeneralImportsListing } from './components'; const route = useRoute(); const props = defineProps<{ id: string; salesChannelId: string }>(); @@ -10,11 +10,13 @@ const type = ref(String(route.params.type)); const isAmazon = computed(() => type.value === IntegrationTypes.Amazon); const isEbay = computed(() => type.value === IntegrationTypes.Ebay); const isShein = computed(() => type.value === IntegrationTypes.Shein); +const isMirakl = computed(() => type.value === IntegrationTypes.Mirakl); diff --git a/src/core/integrations/integrations/integrations-show/containers/imports/components/MiraklImportsListing.vue b/src/core/integrations/integrations/integrations-show/containers/imports/components/MiraklImportsListing.vue new file mode 100644 index 00000000..d410b582 --- /dev/null +++ b/src/core/integrations/integrations/integrations-show/containers/imports/components/MiraklImportsListing.vue @@ -0,0 +1,492 @@ + + + diff --git a/src/core/integrations/integrations/integrations-show/containers/imports/components/index.ts b/src/core/integrations/integrations/integrations-show/containers/imports/components/index.ts index e269bbe4..d2082842 100644 --- a/src/core/integrations/integrations/integrations-show/containers/imports/components/index.ts +++ b/src/core/integrations/integrations/integrations-show/containers/imports/components/index.ts @@ -1,4 +1,5 @@ export { default as AmazonImportsListing } from './AmazonImportsListing.vue'; export { default as EbayImportsListing } from './EbayImportsListing.vue'; export { default as SheinImportsListing } from './SheinImportsListing.vue'; +export { default as MiraklImportsListing } from './MiraklImportsListing.vue'; export { default as GeneralImportsListing } from './GeneralImportsListing.vue'; diff --git a/src/core/integrations/integrations/integrations-show/containers/imports/configs.ts b/src/core/integrations/integrations/integrations-show/containers/imports/configs.ts index 667f25b9..e2807312 100644 --- a/src/core/integrations/integrations/integrations-show/containers/imports/configs.ts +++ b/src/core/integrations/integrations/integrations-show/containers/imports/configs.ts @@ -14,6 +14,7 @@ export const getStatusBadgeMap = (t: Function) => ({ export interface SalesChannelImportItem { id: string; + name: string; status: 'new' | 'pending' | 'failed' | 'success' | 'processing'; percentage: number; createdAt: string; @@ -44,6 +45,15 @@ export interface SheinSalesChannelImportItem { createdAt: string; } +export interface MiraklImportProcessItem { + id: string; + proxyId: string; + type: string; + status: 'new' | 'pending' | 'failed' | 'success' | 'processing'; + percentage: number; + createdAt: string; +} + export interface SalesChannelSubscriptionResult { salesChannel: { id: string; @@ -53,6 +63,7 @@ export interface SalesChannelSubscriptionResult { amazonImports: AmazonSalesChannelImportItem[]; ebayImports: EbaySalesChannelImportItem[]; sheinImports: SheinSalesChannelImportItem[]; + miraklImports: MiraklImportProcessItem[]; }; } @@ -96,3 +107,72 @@ export interface EanCodeAttribute { attributeCode: string; isNew: boolean; } + +export interface MiraklFeedListItem { + id: string; + type?: string | null; + stage?: string | null; + status?: string | null; + remoteId?: string | null; + errorMessage?: string | null; + itemsCount?: number | null; + rowsCount?: number | null; + lastSyncedAt?: string | null; + lastSubmittedAt?: string | null; + lastPolledAt?: string | null; + createdAt?: string | null; + importStatus?: string | null; + reasonStatus?: string | null; + remoteDateCreated?: string | null; + hasErrorReport?: boolean | null; + hasNewProductReport?: boolean | null; + hasTransformationErrorReport?: boolean | null; + hasTransformedFile?: boolean | null; + errorReportFileUrl?: string | null; + newProductReportFileUrl?: string | null; + transformedFileUrl?: string | null; + transformationErrorReportFileUrl?: string | null; + productType?: { + id?: string | null; + name?: string | null; + remoteId?: string | null; + templateUrl?: string | null; + } | null; + salesChannelView?: { + id?: string | null; + name?: string | null; + remoteId?: string | null; + } | null; +} + +export const concludedMiraklFeedStatuses = ['success', 'partial', 'failed', 'cancelled']; + +export const getMiraklFeedStatusBadgeMap = (t: Function) => ({ + new: { text: t('integrations.imports.miraklFeeds.status.new'), color: 'gray' }, + pending: { text: t('integrations.imports.miraklFeeds.status.pending'), color: 'blue' }, + gathering_products: { text: t('integrations.imports.miraklFeeds.status.gathering_products'), color: 'indigo' }, + gathering_offers: { text: t('integrations.imports.miraklFeeds.status.gathering_offers'), color: 'indigo' }, + ready_to_render: { text: t('integrations.imports.miraklFeeds.status.ready_to_render'), color: 'sky' }, + submitted: { text: t('integrations.imports.miraklFeeds.status.submitted'), color: 'indigo' }, + processing: { text: t('integrations.imports.miraklFeeds.status.processing'), color: 'yellow' }, + success: { text: t('integrations.imports.miraklFeeds.status.success'), color: 'green' }, + partial: { text: t('integrations.imports.miraklFeeds.status.partial'), color: 'orange' }, + failed: { text: t('integrations.imports.miraklFeeds.status.failed'), color: 'red' }, + cancelled: { text: t('integrations.imports.miraklFeeds.status.cancelled'), color: 'gray' }, +}); + +export const getMiraklFeedImportStatusLabel = (t: Function, value?: string | null) => { + if (!value) { + return '-'; + } + const key = `integrations.imports.miraklFeeds.importStatus.${value}`; + const translated = t(key); + return translated === key ? value : translated; +}; + +export const getMiraklFeedFileBadges = (t: Function, feed: MiraklFeedListItem) => ([ + { text: t('integrations.imports.miraklFeeds.files.errorReport'), color: feed.hasErrorReport ? 'red' : 'gray' }, + { text: t('integrations.imports.miraklFeeds.files.newProductReport'), color: feed.hasNewProductReport ? 'blue' : 'gray' }, + { text: t('integrations.imports.miraklFeeds.files.transformedFile'), color: feed.hasTransformedFile ? 'green' : 'gray' }, + { text: t('integrations.imports.miraklFeeds.files.transformationErrorReport'), color: feed.hasTransformationErrorReport ? 'orange' : 'gray' }, +]); diff --git a/src/core/integrations/integrations/integrations-show/containers/imports/containers/create-import/ImportCreateController.vue b/src/core/integrations/integrations/integrations-show/containers/imports/containers/create-import/ImportCreateController.vue index c9cd3325..efebcd91 100644 --- a/src/core/integrations/integrations/integrations-show/containers/imports/containers/create-import/ImportCreateController.vue +++ b/src/core/integrations/integrations/integrations-show/containers/imports/containers/create-import/ImportCreateController.vue @@ -10,6 +10,7 @@ import { WoocommerceImporter } from "./containers/woocommerce/woocommerce-import import { AmazonImporter } from "./containers/amazon/amazon-importer"; import { EbayImporter } from "./containers/ebay/ebay-importer"; import { SheinImporter } from "./containers/shein/shein-importer"; +import { MiraklImporter } from "./containers/mirakl/mirakl-importer"; import {IntegrationTypes} from "../../../../../integrations"; @@ -39,6 +40,7 @@ const type = ref(String(route.params.type)); + diff --git a/src/core/integrations/integrations/integrations-show/containers/imports/containers/create-import/containers/mirakl/mirakl-importer/MiraklImporter.vue b/src/core/integrations/integrations/integrations-show/containers/imports/containers/create-import/containers/mirakl/mirakl-importer/MiraklImporter.vue new file mode 100644 index 00000000..e45cd042 --- /dev/null +++ b/src/core/integrations/integrations/integrations-show/containers/imports/containers/create-import/containers/mirakl/mirakl-importer/MiraklImporter.vue @@ -0,0 +1,147 @@ + + + diff --git a/src/core/integrations/integrations/integrations-show/containers/imports/containers/create-import/containers/mirakl/mirakl-importer/index.ts b/src/core/integrations/integrations/integrations-show/containers/imports/containers/create-import/containers/mirakl/mirakl-importer/index.ts new file mode 100644 index 00000000..7ccd9aa8 --- /dev/null +++ b/src/core/integrations/integrations/integrations-show/containers/imports/containers/create-import/containers/mirakl/mirakl-importer/index.ts @@ -0,0 +1 @@ +export { default as MiraklImporter } from './MiraklImporter.vue'; diff --git a/src/core/integrations/integrations/integrations-show/containers/imports/containers/import-show/ImportShowController.vue b/src/core/integrations/integrations/integrations-show/containers/imports/containers/import-show/ImportShowController.vue index 3c5814ee..60f2e0fb 100644 --- a/src/core/integrations/integrations/integrations-show/containers/imports/containers/import-show/ImportShowController.vue +++ b/src/core/integrations/integrations/integrations-show/containers/imports/containers/import-show/ImportShowController.vue @@ -1,5 +1,5 @@