@deenruv/admin-dashboard 1.0.17-dev.14 → 1.0.17-dev.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/storefrontAction/StorefrontAction.js +9 -0
- package/dist/components/storefrontAction/StorefrontAction.logic.js +27 -0
- package/dist/components/storefrontAction/index.js +2 -0
- package/dist/locales/en/collections.json +14 -0
- package/dist/locales/en/products.json +15 -0
- package/dist/locales/pl/collections.json +14 -0
- package/dist/locales/pl/products.json +15 -0
- package/dist/pages/collections/Detail.js +3 -0
- package/dist/pages/collections/_components/collectionStorefrontAction/CollectionStorefrontAction.js +41 -0
- package/dist/pages/collections/_components/collectionStorefrontAction/CollectionStorefrontAction.logic.js +44 -0
- package/dist/pages/collections/_components/collectionStorefrontAction/index.js +2 -0
- package/dist/pages/products/Detail.js +4 -1
- package/dist/pages/products/_components/productStorefrontAction/ProductStorefrontAction.js +42 -0
- package/dist/pages/products/_components/productStorefrontAction/ProductStorefrontAction.logic.js +39 -0
- package/dist/pages/products/_components/productStorefrontAction/index.js +2 -0
- package/dist/version.js +1 -1
- package/package.json +5 -5
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Button, SimpleTooltip } from '@deenruv/react-ui-devkit';
|
|
3
|
+
import { ExternalLink } from 'lucide-react';
|
|
4
|
+
export const StorefrontAction = ({ label, state }) => {
|
|
5
|
+
if (state.kind === 'ready') {
|
|
6
|
+
return (_jsx(Button, { asChild: true, variant: "secondary", size: "sm", children: _jsxs("a", { href: state.url, target: "_blank", rel: "noopener noreferrer", className: "gap-2", children: [_jsx(ExternalLink, { className: "size-4", "aria-hidden": "true" }), label] }) }));
|
|
7
|
+
}
|
|
8
|
+
return (_jsx(SimpleTooltip, { content: state.tooltip, children: _jsxs(Button, { type: "button", variant: "secondary", size: "sm", className: "gap-2", disabled: true, children: [_jsx(ExternalLink, { className: "size-4", "aria-hidden": "true" }), label] }) }));
|
|
9
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export const getStorefrontEntityUrlState = (context, resolver) => {
|
|
2
|
+
let resolvedUrl;
|
|
3
|
+
try {
|
|
4
|
+
resolvedUrl = resolver(context);
|
|
5
|
+
}
|
|
6
|
+
catch {
|
|
7
|
+
return { kind: 'disabled', reason: 'resolverFailed' };
|
|
8
|
+
}
|
|
9
|
+
if (resolvedUrl === undefined)
|
|
10
|
+
return { kind: 'hidden' };
|
|
11
|
+
if (resolvedUrl === null)
|
|
12
|
+
return { kind: 'disabled', reason: 'resolverEmpty' };
|
|
13
|
+
let urlString;
|
|
14
|
+
let protocol;
|
|
15
|
+
try {
|
|
16
|
+
const url = new globalThis.URL(resolvedUrl);
|
|
17
|
+
urlString = url.href;
|
|
18
|
+
protocol = url.protocol;
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return { kind: 'disabled', reason: 'urlNotAbsolute' };
|
|
22
|
+
}
|
|
23
|
+
if (protocol !== 'http:' && protocol !== 'https:') {
|
|
24
|
+
return { kind: 'disabled', reason: 'unsupportedProtocol' };
|
|
25
|
+
}
|
|
26
|
+
return { kind: 'ready', url: urlString };
|
|
27
|
+
};
|
|
@@ -7,6 +7,20 @@
|
|
|
7
7
|
"baseInfoUpdated": "Updated: {{value}}",
|
|
8
8
|
"buttonDisabledTooltip": "Fill in all required fields",
|
|
9
9
|
"noChangesTooltip": "No changes have been made",
|
|
10
|
+
"storefrontAction": {
|
|
11
|
+
"label": "Open in storefront",
|
|
12
|
+
"disabled": {
|
|
13
|
+
"collectionPrivate": "Make the collection public and save it before opening it in the storefront.",
|
|
14
|
+
"missingChannel": "Select a channel before opening the collection in the storefront.",
|
|
15
|
+
"missingSlug": "The saved collection has no slug for the selected language.",
|
|
16
|
+
"unsavedPrivate": "Save the current visibility before opening the collection in the storefront.",
|
|
17
|
+
"unsavedSlug": "Save the current slug before opening the collection in the storefront.",
|
|
18
|
+
"resolverFailed": "The storefront URL could not be resolved.",
|
|
19
|
+
"resolverEmpty": "The storefront URL resolver returned no URL.",
|
|
20
|
+
"urlNotAbsolute": "The storefront URL must be absolute.",
|
|
21
|
+
"unsupportedProtocol": "The storefront URL must use HTTP or HTTPS."
|
|
22
|
+
}
|
|
23
|
+
},
|
|
10
24
|
"table": {
|
|
11
25
|
"id": "Id",
|
|
12
26
|
"name": "Name",
|
|
@@ -42,6 +42,21 @@
|
|
|
42
42
|
"removeVariant": "Usuń wariant",
|
|
43
43
|
"removeVariantFromChannel": "Usuń wariant z kanału"
|
|
44
44
|
},
|
|
45
|
+
"storefrontAction": {
|
|
46
|
+
"label": "Open in storefront",
|
|
47
|
+
"disabled": {
|
|
48
|
+
"productDisabled": "Enable and save the product before opening it in the storefront.",
|
|
49
|
+
"missingChannel": "Select a channel before opening the product in the storefront.",
|
|
50
|
+
"channelNotAssigned": "The saved product is not assigned to the selected channel.",
|
|
51
|
+
"missingSlug": "The saved product has no slug for the selected language.",
|
|
52
|
+
"unsavedSlug": "Save the current slug before opening the product in the storefront.",
|
|
53
|
+
"unsavedEnabled": "Save the current availability status before opening the product in the storefront.",
|
|
54
|
+
"resolverFailed": "The storefront URL could not be resolved.",
|
|
55
|
+
"resolverEmpty": "The storefront URL resolver returned no URL.",
|
|
56
|
+
"urlNotAbsolute": "The storefront URL must be absolute.",
|
|
57
|
+
"unsupportedProtocol": "The storefront URL must use HTTP or HTTPS."
|
|
58
|
+
}
|
|
59
|
+
},
|
|
45
60
|
"initialVariant": {
|
|
46
61
|
"title": "Initial variant",
|
|
47
62
|
"description": "Create one default variant together with this product. If the variant name is empty, the product name will be used.",
|
|
@@ -7,6 +7,20 @@
|
|
|
7
7
|
"baseInfoUpdated": "Zaktualizowano: {{value}}",
|
|
8
8
|
"buttonDisabledTooltip": "Wypełnij wszystkie wymagane pola",
|
|
9
9
|
"noChangesTooltip": "Nie wprowadzono żadnych zmian",
|
|
10
|
+
"storefrontAction": {
|
|
11
|
+
"label": "Otwórz w sklepie",
|
|
12
|
+
"disabled": {
|
|
13
|
+
"collectionPrivate": "Ustaw kolekcję jako publiczną i zapisz ją, aby otworzyć ją w sklepie.",
|
|
14
|
+
"missingChannel": "Wybierz kanał, aby otworzyć kolekcję w sklepie.",
|
|
15
|
+
"missingSlug": "Zapisana kolekcja nie ma slugu dla wybranego języka.",
|
|
16
|
+
"unsavedPrivate": "Zapisz bieżącą widoczność, aby otworzyć kolekcję w sklepie.",
|
|
17
|
+
"unsavedSlug": "Zapisz bieżący slug, aby otworzyć kolekcję w sklepie.",
|
|
18
|
+
"resolverFailed": "Nie udało się wyznaczyć adresu URL sklepu.",
|
|
19
|
+
"resolverEmpty": "Konfiguracja sklepu nie zwróciła adresu URL.",
|
|
20
|
+
"urlNotAbsolute": "Adres URL sklepu musi być bezwzględny.",
|
|
21
|
+
"unsupportedProtocol": "Adres URL sklepu musi używać protokołu HTTP lub HTTPS."
|
|
22
|
+
}
|
|
23
|
+
},
|
|
10
24
|
"table": {
|
|
11
25
|
"id": "ID",
|
|
12
26
|
"name": "Nazwa",
|
|
@@ -42,6 +42,21 @@
|
|
|
42
42
|
"removeVariant": "Usuń wariant",
|
|
43
43
|
"removeVariantFromChannel": "Usuń wariant z kanału"
|
|
44
44
|
},
|
|
45
|
+
"storefrontAction": {
|
|
46
|
+
"label": "Otwórz w sklepie",
|
|
47
|
+
"disabled": {
|
|
48
|
+
"productDisabled": "Włącz i zapisz produkt, aby otworzyć go w sklepie.",
|
|
49
|
+
"missingChannel": "Wybierz kanał, aby otworzyć produkt w sklepie.",
|
|
50
|
+
"channelNotAssigned": "Zapisany produkt nie jest przypisany do wybranego kanału.",
|
|
51
|
+
"missingSlug": "Zapisany produkt nie ma slugu dla wybranego języka.",
|
|
52
|
+
"unsavedSlug": "Zapisz bieżący slug, aby otworzyć produkt w sklepie.",
|
|
53
|
+
"unsavedEnabled": "Zapisz bieżący status dostępności, aby otworzyć produkt w sklepie.",
|
|
54
|
+
"resolverFailed": "Nie udało się wyznaczyć adresu URL sklepu.",
|
|
55
|
+
"resolverEmpty": "Konfiguracja sklepu nie zwróciła adresu URL.",
|
|
56
|
+
"urlNotAbsolute": "Adres URL sklepu musi być bezwzględny.",
|
|
57
|
+
"unsupportedProtocol": "Adres URL sklepu musi używać protokołu HTTP lub HTTPS."
|
|
58
|
+
}
|
|
59
|
+
},
|
|
45
60
|
"initialVariant": {
|
|
46
61
|
"title": "Początkowy wariant",
|
|
47
62
|
"description": "Utwórz jeden domyślny wariant razem z tym produktem. Jeśli nazwa wariantu jest pusta, zostanie użyta nazwa produktu.",
|
|
@@ -3,6 +3,7 @@ import { useCallback } from 'react';
|
|
|
3
3
|
import { useParams } from 'react-router';
|
|
4
4
|
import { useValidators, DetailView, createDeenruvForm, getMutation, useMutation, useSettings, } from '@deenruv/react-ui-devkit';
|
|
5
5
|
import { CollectionsDetailView } from "./_components/CollectionDetailView.js";
|
|
6
|
+
import { CollectionStorefrontAction } from "./_components/collectionStorefrontAction";
|
|
6
7
|
const CreateCollectionMutation = getMutation('createCollection');
|
|
7
8
|
const EditCollectionMutation = getMutation('updateCollection');
|
|
8
9
|
const DeleteCollectionMutation = getMutation('deleteCollection');
|
|
@@ -73,5 +74,7 @@ export const CollectionsDetailPage = () => {
|
|
|
73
74
|
onSubmitted: onSubmitHandler,
|
|
74
75
|
onDeleted: onDeleteHandler,
|
|
75
76
|
}),
|
|
77
|
+
}, topActions: {
|
|
78
|
+
inline: [_jsx(CollectionStorefrontAction, {}, "collection-storefront-action")],
|
|
76
79
|
} }) }));
|
|
77
80
|
};
|
package/dist/pages/collections/_components/collectionStorefrontAction/CollectionStorefrontAction.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useDetailView, useGlobalStore, useSettings, useTranslation } from '@deenruv/react-ui-devkit';
|
|
3
|
+
import { StorefrontAction } from "../../../../components/storefrontAction";
|
|
4
|
+
import { getCollectionStorefrontActionState, } from './CollectionStorefrontAction.logic';
|
|
5
|
+
const COLLECTION_STOREFRONT_FORM_KEYS = ['CreateCollectionInput', 'translations', 'isPrivate'];
|
|
6
|
+
export const CollectionStorefrontAction = () => {
|
|
7
|
+
const { t } = useTranslation('collections');
|
|
8
|
+
const selectedChannelCode = useSettings((state) => state.selectedChannel?.code);
|
|
9
|
+
const languageCode = useSettings((state) => state.translationsLanguage);
|
|
10
|
+
const resolveStorefrontEntityUrl = useGlobalStore((state) => state.ui?.resolveStorefrontEntityUrl);
|
|
11
|
+
const { entity, form, id, loading } = useDetailView('collections-detail-view', ...COLLECTION_STOREFRONT_FORM_KEYS);
|
|
12
|
+
const formTranslations = form.base.watch('translations');
|
|
13
|
+
const formIsPrivate = form.base.watch('isPrivate');
|
|
14
|
+
if (!id || loading || !entity || !resolveStorefrontEntityUrl)
|
|
15
|
+
return null;
|
|
16
|
+
const state = getCollectionStorefrontActionState({
|
|
17
|
+
collection: entity,
|
|
18
|
+
selectedChannelCode,
|
|
19
|
+
languageCode,
|
|
20
|
+
formTranslations,
|
|
21
|
+
formIsPrivate,
|
|
22
|
+
resolveStorefrontEntityUrl,
|
|
23
|
+
});
|
|
24
|
+
const label = t('storefrontAction.label');
|
|
25
|
+
if (state.kind === 'hidden')
|
|
26
|
+
return null;
|
|
27
|
+
const disabledTooltips = {
|
|
28
|
+
collectionPrivate: t('storefrontAction.disabled.collectionPrivate'),
|
|
29
|
+
missingChannel: t('storefrontAction.disabled.missingChannel'),
|
|
30
|
+
missingSlug: t('storefrontAction.disabled.missingSlug'),
|
|
31
|
+
unsavedPrivate: t('storefrontAction.disabled.unsavedPrivate'),
|
|
32
|
+
unsavedSlug: t('storefrontAction.disabled.unsavedSlug'),
|
|
33
|
+
resolverFailed: t('storefrontAction.disabled.resolverFailed'),
|
|
34
|
+
resolverEmpty: t('storefrontAction.disabled.resolverEmpty'),
|
|
35
|
+
urlNotAbsolute: t('storefrontAction.disabled.urlNotAbsolute'),
|
|
36
|
+
unsupportedProtocol: t('storefrontAction.disabled.unsupportedProtocol'),
|
|
37
|
+
};
|
|
38
|
+
return (_jsx(StorefrontAction, { label: label, state: state.kind === 'ready'
|
|
39
|
+
? { kind: 'ready', url: state.url }
|
|
40
|
+
: { kind: 'disabled', tooltip: disabledTooltips[state.reason] } }));
|
|
41
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { getStorefrontEntityUrlState, } from '../../../../components/storefrontAction/StorefrontAction.logic';
|
|
2
|
+
const getFormSlug = (formTranslations, languageCode) => {
|
|
3
|
+
if (!Array.isArray(formTranslations))
|
|
4
|
+
return undefined;
|
|
5
|
+
const translation = formTranslations.find((value) => typeof value === 'object' && value !== null && 'languageCode' in value && value.languageCode === languageCode);
|
|
6
|
+
return typeof translation?.slug === 'string' ? translation.slug : undefined;
|
|
7
|
+
};
|
|
8
|
+
export const normalizeCollectionBreadcrumbs = (collection, persistedSlug) => {
|
|
9
|
+
const ancestors = collection.breadcrumbs
|
|
10
|
+
.slice(1)
|
|
11
|
+
.filter(({ id }) => id !== collection.id)
|
|
12
|
+
.map(({ id, slug }) => ({ id, slug }));
|
|
13
|
+
return [...ancestors, { id: collection.id, slug: persistedSlug }];
|
|
14
|
+
};
|
|
15
|
+
export const getCollectionStorefrontActionState = ({ collection, selectedChannelCode, languageCode, formTranslations, formIsPrivate, resolveStorefrontEntityUrl, }) => {
|
|
16
|
+
if (!selectedChannelCode)
|
|
17
|
+
return { kind: 'disabled', reason: 'missingChannel' };
|
|
18
|
+
const persistedTranslation = languageCode
|
|
19
|
+
? collection.translations.find((translation) => translation.languageCode === languageCode)
|
|
20
|
+
: undefined;
|
|
21
|
+
if (!languageCode || typeof persistedTranslation?.slug !== 'string' || !persistedTranslation.slug.trim()) {
|
|
22
|
+
return { kind: 'disabled', reason: 'missingSlug' };
|
|
23
|
+
}
|
|
24
|
+
const context = {
|
|
25
|
+
entityType: 'collection',
|
|
26
|
+
entityId: collection.id,
|
|
27
|
+
slug: persistedTranslation.slug,
|
|
28
|
+
channelCode: selectedChannelCode,
|
|
29
|
+
languageCode,
|
|
30
|
+
breadcrumbs: normalizeCollectionBreadcrumbs(collection, persistedTranslation.slug),
|
|
31
|
+
};
|
|
32
|
+
const urlState = getStorefrontEntityUrlState(context, resolveStorefrontEntityUrl);
|
|
33
|
+
if (urlState.kind === 'hidden')
|
|
34
|
+
return urlState;
|
|
35
|
+
if (collection.isPrivate)
|
|
36
|
+
return { kind: 'disabled', reason: 'collectionPrivate' };
|
|
37
|
+
if (formIsPrivate !== collection.isPrivate) {
|
|
38
|
+
return { kind: 'disabled', reason: 'unsavedPrivate' };
|
|
39
|
+
}
|
|
40
|
+
if (getFormSlug(formTranslations, languageCode) !== persistedTranslation.slug) {
|
|
41
|
+
return { kind: 'disabled', reason: 'unsavedSlug' };
|
|
42
|
+
}
|
|
43
|
+
return urlState.kind === 'ready' ? { ...urlState, context } : urlState;
|
|
44
|
+
};
|
|
@@ -4,6 +4,7 @@ import { VariantsTab } from "./_components/VariantsTab";
|
|
|
4
4
|
import { OptionsTab } from "./_components/OptionsTab";
|
|
5
5
|
import { ProductDetailView } from './_components/ProductDetailView';
|
|
6
6
|
import { ProductDetailSidebar } from './_components/ProductDetailSidebar';
|
|
7
|
+
import { ProductStorefrontAction } from './_components/productStorefrontAction';
|
|
7
8
|
import { DEFAULT_CHANNEL_CODE, useTranslation, createDeenruvForm, DetailView, useMutation, useSettings, } from '@deenruv/react-ui-devkit';
|
|
8
9
|
import { $, Permission, scalars, typedGql } from '@deenruv/admin-types';
|
|
9
10
|
import { useMemo } from 'react';
|
|
@@ -123,7 +124,9 @@ export const ProductsDetailPage = () => {
|
|
|
123
124
|
throw new Error('No id');
|
|
124
125
|
},
|
|
125
126
|
}),
|
|
126
|
-
}, defaultTabs: defaultTabs,
|
|
127
|
+
}, defaultTabs: defaultTabs, topActions: {
|
|
128
|
+
inline: [_jsx(ProductStorefrontAction, {}, "product-storefront-action")],
|
|
129
|
+
}, permissions: {
|
|
127
130
|
create: Permission.CreateProduct,
|
|
128
131
|
edit: Permission.UpdateProduct,
|
|
129
132
|
delete: Permission.DeleteProduct,
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useDetailView, useGlobalStore, useSettings, useTranslation } from '@deenruv/react-ui-devkit';
|
|
3
|
+
import { StorefrontAction } from "../../../../components/storefrontAction";
|
|
4
|
+
import { getProductStorefrontActionState, } from './ProductStorefrontAction.logic';
|
|
5
|
+
const PRODUCT_STOREFRONT_FORM_KEYS = ['CreateProductInput', 'translations', 'enabled'];
|
|
6
|
+
export const ProductStorefrontAction = () => {
|
|
7
|
+
const { t } = useTranslation('products');
|
|
8
|
+
const selectedChannelCode = useSettings((state) => state.selectedChannel?.code);
|
|
9
|
+
const languageCode = useSettings((state) => state.translationsLanguage);
|
|
10
|
+
const resolveStorefrontEntityUrl = useGlobalStore((state) => state.ui?.resolveStorefrontEntityUrl);
|
|
11
|
+
const { entity, form, id } = useDetailView('products-detail-view', ...PRODUCT_STOREFRONT_FORM_KEYS);
|
|
12
|
+
const formTranslations = form.base.watch('translations');
|
|
13
|
+
const formEnabled = form.base.watch('enabled');
|
|
14
|
+
if (!id || !entity || !resolveStorefrontEntityUrl)
|
|
15
|
+
return null;
|
|
16
|
+
const state = getProductStorefrontActionState({
|
|
17
|
+
product: entity,
|
|
18
|
+
selectedChannelCode,
|
|
19
|
+
languageCode,
|
|
20
|
+
formTranslations,
|
|
21
|
+
formEnabled,
|
|
22
|
+
resolveStorefrontEntityUrl,
|
|
23
|
+
});
|
|
24
|
+
const label = t('storefrontAction.label');
|
|
25
|
+
if (state.kind === 'hidden')
|
|
26
|
+
return null;
|
|
27
|
+
const disabledTooltips = {
|
|
28
|
+
productDisabled: t('storefrontAction.disabled.productDisabled'),
|
|
29
|
+
missingChannel: t('storefrontAction.disabled.missingChannel'),
|
|
30
|
+
channelNotAssigned: t('storefrontAction.disabled.channelNotAssigned'),
|
|
31
|
+
missingSlug: t('storefrontAction.disabled.missingSlug'),
|
|
32
|
+
unsavedSlug: t('storefrontAction.disabled.unsavedSlug'),
|
|
33
|
+
unsavedEnabled: t('storefrontAction.disabled.unsavedEnabled'),
|
|
34
|
+
resolverFailed: t('storefrontAction.disabled.resolverFailed'),
|
|
35
|
+
resolverEmpty: t('storefrontAction.disabled.resolverEmpty'),
|
|
36
|
+
urlNotAbsolute: t('storefrontAction.disabled.urlNotAbsolute'),
|
|
37
|
+
unsupportedProtocol: t('storefrontAction.disabled.unsupportedProtocol'),
|
|
38
|
+
};
|
|
39
|
+
return (_jsx(StorefrontAction, { label: label, state: state.kind === 'ready'
|
|
40
|
+
? { kind: 'ready', url: state.url }
|
|
41
|
+
: { kind: 'disabled', tooltip: disabledTooltips[state.reason] } }));
|
|
42
|
+
};
|
package/dist/pages/products/_components/productStorefrontAction/ProductStorefrontAction.logic.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { getStorefrontEntityUrlState, } from '../../../../components/storefrontAction/StorefrontAction.logic';
|
|
2
|
+
const getFormSlug = (formTranslations, languageCode) => {
|
|
3
|
+
if (!Array.isArray(formTranslations))
|
|
4
|
+
return undefined;
|
|
5
|
+
const translation = formTranslations.find((value) => typeof value === 'object' && value !== null && 'languageCode' in value && value.languageCode === languageCode);
|
|
6
|
+
return typeof translation?.slug === 'string' ? translation.slug : undefined;
|
|
7
|
+
};
|
|
8
|
+
export const getProductStorefrontActionState = ({ product, selectedChannelCode, languageCode, formTranslations, formEnabled, resolveStorefrontEntityUrl, }) => {
|
|
9
|
+
if (!selectedChannelCode)
|
|
10
|
+
return { kind: 'disabled', reason: 'missingChannel' };
|
|
11
|
+
const persistedTranslation = languageCode
|
|
12
|
+
? product.translations.find((translation) => translation.languageCode === languageCode)
|
|
13
|
+
: undefined;
|
|
14
|
+
if (!languageCode || typeof persistedTranslation?.slug !== 'string' || !persistedTranslation.slug.trim()) {
|
|
15
|
+
return { kind: 'disabled', reason: 'missingSlug' };
|
|
16
|
+
}
|
|
17
|
+
const context = {
|
|
18
|
+
entityType: 'product',
|
|
19
|
+
entityId: product.id,
|
|
20
|
+
slug: persistedTranslation.slug,
|
|
21
|
+
channelCode: selectedChannelCode,
|
|
22
|
+
languageCode,
|
|
23
|
+
};
|
|
24
|
+
const urlState = getStorefrontEntityUrlState(context, resolveStorefrontEntityUrl);
|
|
25
|
+
if (urlState.kind === 'hidden')
|
|
26
|
+
return urlState;
|
|
27
|
+
if (!product.enabled)
|
|
28
|
+
return { kind: 'disabled', reason: 'productDisabled' };
|
|
29
|
+
if (!product.channels.some(({ code }) => code === selectedChannelCode)) {
|
|
30
|
+
return { kind: 'disabled', reason: 'channelNotAssigned' };
|
|
31
|
+
}
|
|
32
|
+
if (formEnabled !== product.enabled) {
|
|
33
|
+
return { kind: 'disabled', reason: 'unsavedEnabled' };
|
|
34
|
+
}
|
|
35
|
+
if (getFormSlug(formTranslations, languageCode) !== persistedTranslation.slug) {
|
|
36
|
+
return { kind: 'disabled', reason: 'unsavedSlug' };
|
|
37
|
+
}
|
|
38
|
+
return urlState.kind === 'ready' ? { ...urlState, context } : urlState;
|
|
39
|
+
};
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const ADMIN_DASHBOARD_VERSION = '1.0.17-dev.
|
|
1
|
+
export const ADMIN_DASHBOARD_VERSION = '1.0.17-dev.15';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deenruv/admin-dashboard",
|
|
3
|
-
"version": "1.0.17-dev.
|
|
3
|
+
"version": "1.0.17-dev.15",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"style": "dist/index.css",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -80,10 +80,10 @@
|
|
|
80
80
|
"yup": "^1.7.1",
|
|
81
81
|
"zod": "^4.4.3",
|
|
82
82
|
"zustand": "^5.0.14",
|
|
83
|
-
"@deenruv/admin-dashboard": "1.0.17-dev.
|
|
84
|
-
"@deenruv/admin-types": "1.0.17-dev.
|
|
85
|
-
"@deenruv/deenruv-examples-plugin": "1.0.17-dev.
|
|
86
|
-
"@deenruv/react-ui-devkit": "1.0.17-dev.
|
|
83
|
+
"@deenruv/admin-dashboard": "1.0.17-dev.15",
|
|
84
|
+
"@deenruv/admin-types": "1.0.17-dev.15",
|
|
85
|
+
"@deenruv/deenruv-examples-plugin": "1.0.17-dev.15",
|
|
86
|
+
"@deenruv/react-ui-devkit": "1.0.17-dev.15"
|
|
87
87
|
},
|
|
88
88
|
"devDependencies": {
|
|
89
89
|
"@tailwindcss/typography": "^0.5.20",
|