Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
de6f52f
chore(VCST-3470): refactor extension points
ivan-kalachikov Nov 19, 2025
8003bc6
Merge branch 'dev' into chore/VCST-3470-refactor-extensions
ivan-kalachikov Nov 19, 2025
ad840ae
fix: resolve comment - refactor missed old extension point composable
ivan-kalachikov Nov 21, 2025
e6a47e7
Merge branch 'dev' into chore/VCST-3470-refactor-extensions
Aleksandra-Mitricheva Nov 24, 2025
d1ae5b1
fix: variations extension points
ivan-kalachikov Nov 25, 2025
178b51c
Merge branch 'dev' into chore/VCST-3470-refactor-extensions
ivan-kalachikov Nov 26, 2025
1efbff1
feat: add EP for variations item
ivan-kalachikov Nov 27, 2025
1304b5a
Merge branch 'dev' into chore/VCST-3470-refactor-extensions
Aleksandra-Mitricheva Nov 27, 2025
9c7cbe1
fix(VCST-4285): filter clipping in select-address-filter (#2079)
goldenmaya Nov 28, 2025
2319292
fix(VCST-4337): add inStock_variations filter to search dropdown (#2084)
goldenmaya Nov 28, 2025
df1249e
fix(VCST-4335): bottom of product cards must have equal heights (#2080)
muller39 Nov 28, 2025
be2c985
feat(VCST-3965): unify display of qty fields and stock alerts in vari…
muller39 Nov 28, 2025
ebec3c5
fix(VCST-4220): long email breaks (#2068)
muller39 Nov 28, 2025
060f3a8
feat(VCST-4232): migrate storyfn to storyobj (#2066)
muller39 Nov 28, 2025
23fa59b
Merge branch 'dev' into chore/VCST-3470-refactor-extensions
ivan-kalachikov Nov 28, 2025
4589e18
chore: update module manifest
ivan-kalachikov Nov 28, 2025
11cab4c
chore: update module manifest
ivan-kalachikov Nov 28, 2025
baad665
chore: update module manifest
ivan-kalachikov Nov 28, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
301 changes: 150 additions & 151 deletions backend-packages.json

Large diffs are not rendered by default.

21 changes: 11 additions & 10 deletions client-app/modules/back-in-stock/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { defineAsyncComponent } from "vue";
import { useNavigations } from "@/core/composables";
import { useModuleSettings } from "@/core/composables/useModuleSettings";
import { useUser } from "@/shared/account/composables";
import { useCustomProductComponents } from "@/shared/common/composables";
import { CUSTOM_PRODUCT_COMPONENT_IDS } from "@/shared/common/constants";
import { useExtensionRegistry } from "@/shared/common/composables/extensionRegistry/useExtensionRegistry";
import { EXTENSION_NAMES } from "@/shared/common/constants";
import { loadModuleLocale } from "../utils";
import { MODULE_ID, ENABLED_KEY } from "./constants";
import type { MenuType } from "@/core/types";
Expand All @@ -17,7 +17,7 @@ const BackInStockButton = defineAsyncComponent(() => import("./components/back-i

const { isEnabled } = useModuleSettings(MODULE_ID);
const { mergeMenuSchema } = useNavigations();
const { registerComponent } = useCustomProductComponents();
const { register } = useExtensionRegistry();

const route: RouteRecordRaw = {
path: "back-in-stock",
Expand Down Expand Up @@ -64,16 +64,17 @@ export function init(router: Router, i18n: I18n) {
}
if (isAuthenticated.value && isEnabled(ENABLED_KEY)) {
mergeMenuSchema(menuItems);
registerComponent({
id: CUSTOM_PRODUCT_COMPONENT_IDS.CARD_BUTTON,
register("productCard", EXTENSION_NAMES.productCard.cardButton, {
component: BackInStockButton,
shouldRender: (product, options) =>
!product.availabilityData.isInStock && (options?.forceProductAsVariation === true || !product.hasVariations),
condition: (product) => !product.availabilityData?.isInStock && !product.hasVariations,
});
registerComponent({
id: CUSTOM_PRODUCT_COMPONENT_IDS.PAGE_SIDEBAR_BUTTON,
register("productPage", EXTENSION_NAMES.productPage.sidebarButton, {
component: BackInStockButton,
shouldRender: (product) => !product.availabilityData.isInStock && !product.hasVariations,
condition: (product) => !product.availabilityData?.isInStock && !product.hasVariations,
});
register("productPage", EXTENSION_NAMES.productPage.variationItemButton, {
component: BackInStockButton,
condition: (product) => !product.availabilityData?.isInStock,
});
}
}
30 changes: 16 additions & 14 deletions client-app/modules/push-messages/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,11 @@ import { MODULE_ID_PUSH_MESSAGES } from "@/core/constants/modules";
import { loadModuleLocale } from "@/modules/utils";
import { ROUTES } from "@/router/routes/constants";
import { useUser } from "@/shared/account/composables/useUser";
import { useCustomHeaderLinkComponents } from "@/shared/layout/composables/useCustomHeaderLinkComponents";
import { useCustomMobileHeaderComponents } from "@/shared/layout/composables/useCustomMobileHeaderComponents";
import { useCustomMobileMenuLinkComponents } from "@/shared/layout/composables/useCustomMobileMenuLinkComponents";
import { useExtensionRegistry } from "@/shared/common/composables/extensionRegistry/useExtensionRegistry";
import { pushMessagesTypePolices } from "./api/graphql/typePolices";
import { PUSH_MESSAGES_MODULE_ENABLED_KEY, PUSH_MESSAGES_MODULE_FCM_ENABLED_KEY } from "./constants";
import type { MenuType } from "@/core/types";
import type { I18n } from "@/i18n";
import type { ElementType } from "@/shared/layout/composables/useCustomHeaderLinkComponents";
import type { ElementType as HeaderElementType } from "@/shared/layout/composables/useCustomMobileHeaderComponents";
import type { DeepPartial } from "utility-types";
import type { Router, RouteRecordRaw } from "vue-router";

Expand Down Expand Up @@ -67,17 +63,17 @@ const menuItems: DeepPartial<MenuType> = {
const Notifications = () => import("@/modules/push-messages/pages/notifications.vue");
const PushMessage = () => import("@/modules/push-messages/pages/push-message.vue");

const menuLinkCustomElement: ElementType = {
const menuLinkCustomElement = {
id: "push-messages",
component: defineAsyncComponent(() => import("./components/link-push-messages.vue")),
};

const menuLinkCustomElementMobile: ElementType = {
const menuLinkCustomElementMobile = {
id: "push-messages",
component: defineAsyncComponent(() => import("./components/link-push-messages-mobile.vue")),
};

const headerWidgetCustomElementMobile: HeaderElementType = {
const headerWidgetCustomElementMobile = {
id: "push-messages",
component: defineAsyncComponent(() => import("./components/push-messages-mobile.vue")),
};
Expand Down Expand Up @@ -108,9 +104,7 @@ export async function init(router: Router, i18n: I18n) {

if (isModuleEnabled) {
const { mergeMenuSchema } = useNavigations();
const { registerCustomLinkComponent } = useCustomHeaderLinkComponents();
const { registerCustomLinkComponent: registerCustomMobileLinkComponent } = useCustomMobileMenuLinkComponents();
const { registerCustomComponent: registerCustomMobileHeaderComponent } = useCustomMobileHeaderComponents();
const { register } = useExtensionRegistry();
const route: RouteRecordRaw = {
path: "notifications",
name: "Notifications",
Expand All @@ -120,9 +114,17 @@ export async function init(router: Router, i18n: I18n) {
cache.policies.addTypePolicies(pushMessagesTypePolices);
mergeMenuSchema(menuItems);
void loadModuleLocale(i18n, "push-messages");
registerCustomLinkComponent(menuLinkCustomElement);
registerCustomMobileLinkComponent(menuLinkCustomElementMobile);
registerCustomMobileHeaderComponent(headerWidgetCustomElementMobile);

register("headerMenu", "push-messages", {
component: menuLinkCustomElement.component,
});
register("mobileMenu", "push-messages", {
component: menuLinkCustomElementMobile.component,
});
register("mobileHeader", "push-messages", {
component: headerWidgetCustomElementMobile.component,
});

router.addRoute("Account", route); // NOTE: This route must be added before any asynchronous calls. Delaying it can cause a 404 error if accessed prematurely.
}

Expand Down
16 changes: 5 additions & 11 deletions client-app/shared/catalog/components/product-card.vue
Original file line number Diff line number Diff line change
Expand Up @@ -64,15 +64,12 @@
:single-line="viewMode === 'grid'"
/>

<component
:is="getComponent(CUSTOM_PRODUCT_COMPONENT_IDS.CARD_BUTTON)"
v-if="
isComponentRegistered(CUSTOM_PRODUCT_COMPONENT_IDS.CARD_BUTTON) &&
shouldRenderComponent(CUSTOM_PRODUCT_COMPONENT_IDS.CARD_BUTTON, product)
"
<ExtensionPoint
v-if="$canRenderExtensionPoint('productCard', EXTENSION_NAMES.productCard.cardButton, product)"
:name="EXTENSION_NAMES.productCard.cardButton"
category="productCard"
:product="product"
is-text-shown
v-bind="getComponentProps(CUSTOM_PRODUCT_COMPONENT_IDS.CARD_BUTTON)"
/>

<VcProductButton
Expand Down Expand Up @@ -158,8 +155,7 @@ import {
import { useProductVariations } from "@/shared/catalog/composables/useProductVariations";
import { useProducts } from "@/shared/catalog/composables/useProducts";
import { PRODUCT_VARIATIONS_LAYOUT_PROPERTY_NAME } from "@/shared/catalog/constants/product";
import { useCustomProductComponents } from "@/shared/common/composables/useCustomProductComponents";
import { CUSTOM_PRODUCT_COMPONENT_IDS } from "@/shared/common/constants";
import { EXTENSION_NAMES } from "@/shared/common/constants";
import { AddToCompareCatalog } from "@/shared/compare/components";
import { AddToList } from "@/shared/wishlists";
import BadgesWrapper from "./badges-wrapper.vue";
Expand Down Expand Up @@ -197,8 +193,6 @@ const productCard = useTemplateRef("productCard");

const { browserTarget: browserTargetFromSetting } = useBrowserTarget();

const { isComponentRegistered, getComponent, shouldRenderComponent, getComponentProps } = useCustomProductComponents();

const { isEnabled } = useModuleSettings(CUSTOMER_REVIEWS_MODULE_ID);
const productReviewsEnabled = isEnabled(CUSTOMER_REVIEWS_ENABLED_KEY);

Expand Down
15 changes: 5 additions & 10 deletions client-app/shared/catalog/components/product-price.vue
Original file line number Diff line number Diff line change
Expand Up @@ -85,14 +85,11 @@
</div>

<div class="mt-4 print:hidden">
<component
:is="getComponent(CUSTOM_PRODUCT_COMPONENT_IDS.PAGE_SIDEBAR_BUTTON)"
v-if="
isComponentRegistered(CUSTOM_PRODUCT_COMPONENT_IDS.PAGE_SIDEBAR_BUTTON) &&
shouldRenderComponent(CUSTOM_PRODUCT_COMPONENT_IDS.PAGE_SIDEBAR_BUTTON, product)
"
<ExtensionPoint
v-if="$canRenderExtensionPoint('productPage', EXTENSION_NAMES.productPage.sidebarButton, product)"
:name="EXTENSION_NAMES.productPage.sidebarButton"
category="productPage"
:product="product"
v-bind="getComponentProps(CUSTOM_PRODUCT_COMPONENT_IDS.PAGE_SIDEBAR_BUTTON)"
/>

<component v-else :is="product.isConfigurable ? AddToCart : AddToCartSimple" :product="product">
Expand All @@ -117,8 +114,7 @@ import { useShortCart } from "@/shared/cart/composables";
import { useConfigurableProduct } from "@/shared/catalog/composables";
import { useProductVariationProperties } from "@/shared/catalog/composables/useProductVariationProperties";
import { PRODUCT_VARIATIONS_LAYOUT_PROPERTY_VALUES } from "@/shared/catalog/constants/product";
import { useCustomProductComponents } from "@/shared/common/composables";
import { CUSTOM_PRODUCT_COMPONENT_IDS } from "@/shared/common/constants";
import { EXTENSION_NAMES } from "@/shared/common/constants";
import CountInCart from "./count-in-cart.vue";
import InStock from "./in-stock.vue";
import Price from "./price.vue";
Expand All @@ -139,7 +135,6 @@ const variations = toRef(props, "variations");

const { cart } = useShortCart();
const { configuredLineItem, loading: configuredLineItemLoading } = useConfigurableProduct(product.value.id);
const { getComponent, isComponentRegistered, shouldRenderComponent, getComponentProps } = useCustomProductComponents();
const { variationResult } = useProductVariationProperties(computed(() => variations.value ?? []));

const isDigital = computed<boolean>(() => props.product.productType === ProductType.Digital);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,11 @@
with-properties
show-placed-price
>
<component
:is="getComponent(CUSTOM_PRODUCT_COMPONENT_IDS.CARD_BUTTON)"
v-if="
isComponentRegistered(CUSTOM_PRODUCT_COMPONENT_IDS.CARD_BUTTON) &&
shouldRenderComponent(CUSTOM_PRODUCT_COMPONENT_IDS.CARD_BUTTON, variation, {
forceProductAsVariation: true,
})
"
<ExtensionPoint
:name="EXTENSION_NAMES.productPage.variationItemButton"
category="productPage"
:product="variation"
v-bind="getComponentProps(CUSTOM_PRODUCT_COMPONENT_IDS.CARD_BUTTON)"
v-if="$canRenderExtensionPoint('productPage', EXTENSION_NAMES.productPage.variationItemButton, variation)"
/>

<AddToCartSimple v-else :product="variation">
Expand Down Expand Up @@ -56,8 +51,7 @@ import { PropertyType } from "@/core/api/graphql/types";
import { useBrowserTarget } from "@/core/composables";
import { getPropertiesGroupedByName } from "@/core/utilities";
import { PRODUCT_VARIATIONS_LAYOUT_PROPERTY_NAME } from "@/shared/catalog/constants/product";
import { useCustomProductComponents } from "@/shared/common/composables";
import { CUSTOM_PRODUCT_COMPONENT_IDS } from "@/shared/common/constants";
import { EXTENSION_NAMES } from "@/shared/common/constants";
import CountInCart from "../count-in-cart.vue";
import InStock from "../in-stock.vue";
import type { Product } from "@/core/api/graphql/types";
Expand All @@ -81,8 +75,6 @@ const pageNumber = toRef(props, "pageNumber");

const { browserTarget } = useBrowserTarget();

const { isComponentRegistered, getComponent, shouldRenderComponent, getComponentProps } = useCustomProductComponents();

function getProperties(variation: Product) {
return Object.values(
getPropertiesGroupedByName(sortBy(variation.properties, ["displayOrder", "name"]) ?? [], PropertyType.Variation),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,16 +72,11 @@
</td>

<td class="variations-table__col variations-table__col--quantity">
<component
:is="getComponent(CUSTOM_PRODUCT_COMPONENT_IDS.CARD_BUTTON)"
v-if="
isComponentRegistered(CUSTOM_PRODUCT_COMPONENT_IDS.CARD_BUTTON) &&
shouldRenderComponent(CUSTOM_PRODUCT_COMPONENT_IDS.CARD_BUTTON, variation, {
forceProductAsVariation: true,
})
"
<ExtensionPoint
:name="EXTENSION_NAMES.productPage.variationItemButton"
category="productPage"
:product="variation"
v-bind="getComponentProps(CUSTOM_PRODUCT_COMPONENT_IDS.CARD_BUTTON)"
v-if="$canRenderExtensionPoint('productPage', EXTENSION_NAMES.productPage.variationItemButton, variation)"
/>

<AddToCartSimple v-else :product="variation">
Expand All @@ -101,8 +96,7 @@ import { useI18n } from "vue-i18n";
import { PropertyType } from "@/core/api/graphql/types";
import { MAX_DISPLAY_IN_STOCK_QUANTITY } from "@/core/constants";
import { getPropertyValue, getPropertiesGroupedByName } from "@/core/utilities";
import { useCustomProductComponents } from "@/shared/common/composables";
import { CUSTOM_PRODUCT_COMPONENT_IDS } from "@/shared/common/constants";
import { EXTENSION_NAMES } from "@/shared/common/constants";
import CountInCart from "../count-in-cart.vue";
import type { Product } from "@/core/api/graphql/types";
import type { ISortInfo } from "@/core/types";
Expand Down Expand Up @@ -133,8 +127,6 @@ const props = defineProps<IProps>();

const { t } = useI18n();

const { isComponentRegistered, getComponent, shouldRenderComponent, getComponentProps } = useCustomProductComponents();

const variations = computed(() => props.variations);
const productProperties = computed<IProductProperties[]>(() => {
const properties: IProductProperties[] = [];
Expand Down
1 change: 0 additions & 1 deletion client-app/shared/common/composables/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
export * from "./useCustomProductComponents";
export * from "./useGoogleMaps";
export * from "./useSlugInfo";

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export const EXTENSION_NAMES = merge({}, INITIAL_EXTENSION_NAMES, {
},
productPage: {
sidebarButton: "sidebar-button",
variationItemButton: "variation-item-button",
},
paymentPage: {
paymentMethods: "payment-methods",
Expand Down
2 changes: 1 addition & 1 deletion client-app/shared/common/constants/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export * from "./customProductComponents";
export * from "./extensionPointsNames";
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@

<ul class="-mx-2 flex items-center">
<li v-for="item in desktopMainMenuItems" :key="item.id">
<component :is="(item.id && customLinkComponents[item.id]) || LinkDefault" :item="item" />
<ExtensionPoint category="headerMenu" :name="item.id" :item="item">
<LinkDefault :item="item" />
</ExtensionPoint>
</li>
</ul>
</nav>
Expand Down Expand Up @@ -79,7 +81,6 @@ import { useRoute, useRouter } from "vue-router";
import { useNavigations, useWhiteLabeling } from "@/core/composables";
import { useUser } from "@/shared/account/composables/useUser";
import { SearchBar } from "@/shared/layout";
import { useCustomHeaderLinkComponents } from "@/shared/layout/composables/useCustomHeaderLinkComponents";
import CatalogMenu from "./catalog-menu.vue";
import type { StyleValue } from "vue";
import LinkDefault from "@/shared/layout/components/header/_internal/link-components/link-default.vue";
Expand All @@ -94,7 +95,6 @@ const router = useRouter();
const { organization } = useUser();
const { logoUrl } = useWhiteLabeling();
const { catalogMenuItems, desktopMainMenuItems } = useNavigations();
const { customLinkComponents } = useCustomHeaderLinkComponents();

const bottomHeader = ref<HTMLElement | null>(null);
const catalogMenuElement = shallowRef<HTMLElement | null>(null);
Expand Down
Loading