Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(atomic): replace @stencil/store with in-house implementation #4814

Merged
merged 26 commits into from
Jan 16, 2025
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
800c67d
no more get() and set()
alexprudhomme Dec 20, 2024
49bf2e4
migrate commerce store
alexprudhomme Dec 20, 2024
bf8e05b
commerce recommendation store in progress
alexprudhomme Dec 20, 2024
2955e5c
recs store
alexprudhomme Dec 23, 2024
d2d64a8
insight store
alexprudhomme Dec 23, 2024
0a56686
search + remove common store
alexprudhomme Dec 23, 2024
c486e23
clean up
alexprudhomme Dec 23, 2024
8e4b709
clean up into common functions
alexprudhomme Dec 23, 2024
1e7ed4d
extends from base store
alexprudhomme Dec 27, 2024
50b358f
refactor(atomic): replace @stencil/store with in-house implementation
alexprudhomme Jan 2, 2025
d172967
forgot to add the rec getUniqueId From engine
alexprudhomme Jan 2, 2025
edf4dd8
Merge branch 'store-refactor' into replace-stencil-store
alexprudhomme Jan 2, 2025
dae91f7
Merge branch 'master' into store-refactor
alexprudhomme Jan 2, 2025
7f2ae94
Merge branch 'store-refactor' into replace-stencil-store
alexprudhomme Jan 2, 2025
5eba4fe
Update atomic-commerce-product-list.tsx
alexprudhomme Jan 6, 2025
4d417a6
re add get & set functions
alexprudhomme Jan 8, 2025
900874e
Merge branch 'master' into store-refactor
alexprudhomme Jan 13, 2025
09eda8e
Update atomic-search-interface.tsx
alexprudhomme Jan 13, 2025
c34d404
Update interfaces.ts
alexprudhomme Jan 15, 2025
462b915
Merge branch 'master' into store-refactor
alexprudhomme Jan 15, 2025
ffadff2
Merge branch 'store-refactor' into replace-stencil-store
alexprudhomme Jan 15, 2025
601186c
implement get and set
alexprudhomme Jan 15, 2025
0a532fb
Merge branch 'master' into replace-stencil-store
alexprudhomme Jan 15, 2025
954b05c
Merge branch 'master' into replace-stencil-store
alexprudhomme Jan 16, 2025
db1af65
Add generated files
Jan 16, 2025
5d3a4c0
Trigger Build
alexprudhomme Jan 16, 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
14 changes: 0 additions & 14 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion packages/atomic/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@
"@coveo/headless": "3.12.0",
"@popperjs/core": "^2.11.6",
"@salesforce-ux/design-system": "^2.16.1",
"@stencil/store": "2.0.16",
"dayjs": "1.11.13",
"dompurify": "3.2.3",
"escape-html": "1.0.3",
Expand Down
32 changes: 18 additions & 14 deletions packages/atomic/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,20 @@ import { NumberInputType } from "./components/common/facets/facet-number-input/n
import { NumericFilter, NumericFilterState, RelativeDateUnit } from "./components/common/types";
import { InsightEngine, FacetSortCriterion as InsightFacetSortCriterion, FoldedResult as InsightFoldedResult, InteractiveResult as InsightInteractiveResult, LogLevel as InsightLogLevel, RangeFacetRangeAlgorithm as InsightRangeFacetRangeAlgorithm, RangeFacetSortCriterion as InsightRangeFacetSortCriterion, Result as InsightResult, ResultTemplate as InsightResultTemplate, ResultTemplateCondition as InsightResultTemplateCondition, UserAction as IUserAction } from "./components/insight";
import { InsightInitializationOptions } from "./components/insight/atomic-insight-interface/atomic-insight-interface";
import { AtomicInsightStore } from "./components/insight/atomic-insight-interface/store";
import { InsightStore } from "./components/insight/atomic-insight-interface/store";
import { InsightResultActionClickedEvent } from "./components/insight/atomic-insight-result-action/atomic-insight-result-action";
import { InsightResultAttachToCaseEvent } from "./components/insight/atomic-insight-result-attach-to-case-action/atomic-insight-result-attach-to-case-action";
import { Section } from "./components/common/atomic-layout-section/sections";
import { AtomicCommonStore, AtomicCommonStoreData } from "./components/common/interface/store";
import { CommerceStore } from "./components/commerce/atomic-commerce-interface/store";
import { CommerceRecommendationStore } from "./components/commerce/atomic-commerce-recommendation-interface/store";
import { SelectChildProductEventArgs } from "./components/commerce/product-template-components/atomic-product-children/atomic-product-children";
import { TruncateAfter } from "./components/common/expandable-text/expandable-text";
import { RecommendationEngine } from "@coveo/headless/recommendation";
import { InteractiveResult as RecsInteractiveResult, LogLevel as RecsLogLevel, Result as RecsResult, ResultTemplate as RecsResultTemplate, ResultTemplateCondition as RecsResultTemplateCondition } from "./components/recommendations";
import { RecsInitializationOptions } from "./components/recommendations/atomic-recs-interface/atomic-recs-interface";
import { AtomicRecsStore } from "./components/recommendations/atomic-recs-interface/store";
import { RecsStore } from "./components/recommendations/atomic-recs-interface/store";
import { Bindings as Bindings1 } from "./components/search/atomic-search-interface/atomic-search-interface";
import { SearchStore } from "./components/search/atomic-search-interface/store";
import { AriaLabelGenerator as AriaLabelGenerator1 } from "./components/search/search-box-suggestions/atomic-search-box-instant-results/atomic-search-box-instant-results";
import { InitializationOptions } from "./components/search/atomic-search-interface/atomic-search-interface";
export { AutomaticFacet, CategoryFacetSortCriterion, DateFilterRange, DateRangeRequest, FacetResultsMustMatch, FacetSortCriterion, FoldedResult, GeneratedAnswer, GeneratedAnswerCitation, InlineLink, InteractiveCitation, InteractiveResult, LogLevel as LogLevel1, RangeFacetRangeAlgorithm, RangeFacetSortCriterion, Result, ResultTemplate, ResultTemplateCondition, SearchEngine, SearchStatus } from "@coveo/headless";
Expand All @@ -55,18 +57,20 @@ export { NumberInputType } from "./components/common/facets/facet-number-input/n
export { NumericFilter, NumericFilterState, RelativeDateUnit } from "./components/common/types";
export { InsightEngine, FacetSortCriterion as InsightFacetSortCriterion, FoldedResult as InsightFoldedResult, InteractiveResult as InsightInteractiveResult, LogLevel as InsightLogLevel, RangeFacetRangeAlgorithm as InsightRangeFacetRangeAlgorithm, RangeFacetSortCriterion as InsightRangeFacetSortCriterion, Result as InsightResult, ResultTemplate as InsightResultTemplate, ResultTemplateCondition as InsightResultTemplateCondition, UserAction as IUserAction } from "./components/insight";
export { InsightInitializationOptions } from "./components/insight/atomic-insight-interface/atomic-insight-interface";
export { AtomicInsightStore } from "./components/insight/atomic-insight-interface/store";
export { InsightStore } from "./components/insight/atomic-insight-interface/store";
export { InsightResultActionClickedEvent } from "./components/insight/atomic-insight-result-action/atomic-insight-result-action";
export { InsightResultAttachToCaseEvent } from "./components/insight/atomic-insight-result-attach-to-case-action/atomic-insight-result-attach-to-case-action";
export { Section } from "./components/common/atomic-layout-section/sections";
export { AtomicCommonStore, AtomicCommonStoreData } from "./components/common/interface/store";
export { CommerceStore } from "./components/commerce/atomic-commerce-interface/store";
export { CommerceRecommendationStore } from "./components/commerce/atomic-commerce-recommendation-interface/store";
export { SelectChildProductEventArgs } from "./components/commerce/product-template-components/atomic-product-children/atomic-product-children";
export { TruncateAfter } from "./components/common/expandable-text/expandable-text";
export { RecommendationEngine } from "@coveo/headless/recommendation";
export { InteractiveResult as RecsInteractiveResult, LogLevel as RecsLogLevel, Result as RecsResult, ResultTemplate as RecsResultTemplate, ResultTemplateCondition as RecsResultTemplateCondition } from "./components/recommendations";
export { RecsInitializationOptions } from "./components/recommendations/atomic-recs-interface/atomic-recs-interface";
export { AtomicRecsStore } from "./components/recommendations/atomic-recs-interface/store";
export { RecsStore } from "./components/recommendations/atomic-recs-interface/store";
export { Bindings as Bindings1 } from "./components/search/atomic-search-interface/atomic-search-interface";
export { SearchStore } from "./components/search/atomic-search-interface/store";
export { AriaLabelGenerator as AriaLabelGenerator1 } from "./components/search/search-box-suggestions/atomic-search-box-instant-results/atomic-search-box-instant-results";
export { InitializationOptions } from "./components/search/atomic-search-interface/atomic-search-interface";
export namespace Components {
Expand Down Expand Up @@ -1409,7 +1413,7 @@ export namespace Components {
/**
* Global Atomic state.
*/
"store"?: AtomicInsightStore;
"store"?: InsightStore;
}
interface AtomicInsightResultAction {
/**
Expand Down Expand Up @@ -2052,7 +2056,7 @@ export namespace Components {
* Global Atomic state.
* @alpha
*/
"store"?: AtomicCommonStore<AtomicCommonStoreData>;
"store"?: CommerceStore | CommerceRecommendationStore;
}
/**
* @alpha The `atomic-product-children` component renders a section that allows the user to select a nested product (e.g., a color variant of a given product).
Expand Down Expand Up @@ -2696,7 +2700,7 @@ export namespace Components {
/**
* Global Atomic state.
*/
"store"?: AtomicRecsStore;
"store"?: RecsStore;
}
/**
* A [result template](https://docs.coveo.com/en/atomic/latest/usage/displaying-results#defining-a-result-template) determines the format of the query results, depending on the conditions that are defined for each template.
Expand Down Expand Up @@ -2818,7 +2822,7 @@ export namespace Components {
/**
* Global Atomic state.
*/
"store"?: AtomicCommonStore<AtomicCommonStoreData>;
"store"?: SearchStore;
}
/**
* The `atomic-result-badge` element renders a badge to highlight special features of a result.
Expand Down Expand Up @@ -7567,7 +7571,7 @@ declare namespace LocalJSX {
/**
* Global Atomic state.
*/
"store"?: AtomicInsightStore;
"store"?: InsightStore;
}
interface AtomicInsightResultAction {
/**
Expand Down Expand Up @@ -8185,7 +8189,7 @@ declare namespace LocalJSX {
* Global Atomic state.
* @alpha
*/
"store"?: AtomicCommonStore<AtomicCommonStoreData>;
"store"?: CommerceStore | CommerceRecommendationStore;
}
/**
* @alpha The `atomic-product-children` component renders a section that allows the user to select a nested product (e.g., a color variant of a given product).
Expand Down Expand Up @@ -8789,7 +8793,7 @@ declare namespace LocalJSX {
/**
* Global Atomic state.
*/
"store"?: AtomicRecsStore;
"store"?: RecsStore;
}
/**
* A [result template](https://docs.coveo.com/en/atomic/latest/usage/displaying-results#defining-a-result-template) determines the format of the query results, depending on the conditions that are defined for each template.
Expand Down Expand Up @@ -8908,7 +8912,7 @@ declare namespace LocalJSX {
/**
* Global Atomic state.
*/
"store"?: AtomicCommonStore<AtomicCommonStoreData>;
"store"?: SearchStore;
}
/**
* The `atomic-result-badge` element renders a badge to highlight special features of a result.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,14 @@ import {
noProductsSelector,
} from '../atomic-commerce-layout/commerce-layout';
import {getAnalyticsConfig} from './analytics-config';
import {AtomicCommerceStore, createAtomicCommerceStore} from './store';
import {CommerceStore, createCommerceStore} from './store';

const FirstRequestExecutedFlag = 'firstRequestExecuted';

export type CommerceInitializationOptions = CommerceEngineConfiguration;
export type CommerceBindings = CommonBindings<
CommerceEngine,
AtomicCommerceStore,
CommerceStore,
HTMLAtomicCommerceInterfaceElement
> &
NonceBindings;
Expand Down Expand Up @@ -81,7 +81,7 @@ export class AtomicCommerceInterface
private unsubscribeUrlManager: Unsubscribe = () => {};
private unsubscribeSummary: Unsubscribe = () => {};
private initialized = false;
private store: AtomicCommerceStore;
private store: CommerceStore;
private commonInterfaceHelper: CommonAtomicInterfaceHelper<CommerceEngine>;

@Element() public host!: HTMLAtomicCommerceInterfaceElement;
Expand Down Expand Up @@ -178,7 +178,7 @@ export class AtomicCommerceInterface
this,
'CoveoAtomic'
);
this.store = createAtomicCommerceStore(this.type);
this.store = createCommerceStore(this.type);
}

public connectedCallback() {
Expand Down Expand Up @@ -220,7 +220,7 @@ export class AtomicCommerceInterface

@Watch('iconAssetsPath')
public updateIconAssetsPath() {
this.store.set('iconAssetsPath', this.iconAssetsPath);
this.store.state.iconAssetsPath = this.iconAssetsPath;
}

public disconnectedCallback() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,78 +1,58 @@
import {
CommerceEngine,
Selectors,
NumericFacetValue,
DateFacetValue,
SortCriterion,
ChildProduct,
} from '@coveo/headless/commerce';
import {DEFAULT_MOBILE_BREAKPOINT} from '../../../utils/replace-breakpoint';
import {
FacetInfo,
FacetStore,
FacetValueFormat,
} from '../../common/facets/facet-common-store';
import {
createAtomicCommonStore,
AtomicCommonStoreData,
AtomicCommonStore,
BaseStore,
createBaseStore,
ResultListInfo,
setLoadingFlag,
unsetLoadingFlag,
} from '../../common/interface/store';
import {makeDesktopQuery} from '../../search/atomic-layout/search-layout';

export interface SortDropdownOption {
expression: string;
criteria: SortCriterion[];
label: string;
}

export interface AtomicStoreData extends AtomicCommonStoreData {
facets: FacetStore<FacetInfo>;
numericFacets: FacetStore<FacetInfo & FacetValueFormat<NumericFacetValue>>;
dateFacets: FacetStore<FacetInfo & FacetValueFormat<DateFacetValue>>;
categoryFacets: FacetStore<FacetInfo>;
sortOptions: SortDropdownOption[];
interface Data {
loadingFlags: string[];
iconAssetsPath: string;
resultList: ResultListInfo | undefined;
mobileBreakpoint: string;
currentQuickviewPosition: number;
activeProductChild: ChildProduct | undefined;
}

export interface AtomicCommerceStore
extends AtomicCommonStore<AtomicStoreData> {
export type CommerceStore = BaseStore<Data> & {
unsetLoadingFlag(loadingFlag: string): void;
setLoadingFlag(flag: string): void;
isMobile(): boolean;
}

export interface FacetInfoMap {
[facetId: string]:
| FacetInfo
| (FacetInfo & FacetValueFormat<NumericFacetValue>)
| (FacetInfo & FacetValueFormat<DateFacetValue>);
}
getUniqueIDFromEngine(engine: CommerceEngine): string;
};

export function createAtomicCommerceStore(
export function createCommerceStore(
type: 'search' | 'product-listing'
): AtomicCommerceStore {
const commonStore = createAtomicCommonStore<AtomicStoreData>({
): CommerceStore {
const store = createBaseStore({
loadingFlags: [],
facets: {},
numericFacets: {},
dateFacets: {},
categoryFacets: {},
facetElements: [],
sortOptions: [],
iconAssetsPath: '',
resultList: undefined,
mobileBreakpoint: DEFAULT_MOBILE_BREAKPOINT,
fieldsToInclude: [],
currentQuickviewPosition: -1,
activeProductChild: undefined,
});

return {
...commonStore,
...store,

unsetLoadingFlag(loadingFlag: string) {
unsetLoadingFlag(store, loadingFlag);
},

setLoadingFlag(loadingFlag: string) {
setLoadingFlag(store, loadingFlag);
},

isMobile() {
return !window.matchMedia(
makeDesktopQuery(commonStore.state.mobileBreakpoint)
).matches;
return !window.matchMedia(makeDesktopQuery(store.state.mobileBreakpoint))
.matches;
},

getUniqueIDFromEngine(engine: CommerceEngine): string {
Expand All @@ -81,10 +61,6 @@ export function createAtomicCommerceStore(
return Selectors.Search.responseIdSelector(engine);
case 'product-listing':
return Selectors.ProductListing.responseIdSelector(engine);
default:
throw new Error(
`getUniqueIDFromEngine not implemented for this interface type, ${type}`
);
}
},
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
BindStateToController,
InitializeBindings,
} from '../../../utils/initialization-utils';
import {createAppLoadedListener} from '../../common/interface/store';
import {LoadMoreButton} from '../../common/load-more/button';
import {LoadMoreContainer} from '../../common/load-more/container';
import {LoadMoreGuard} from '../../common/load-more/guard';
Expand Down Expand Up @@ -49,6 +50,7 @@ export class AtomicLoadMoreProducts {
private productListingOrSearchState!: ProductListingState | SearchState;

@State() public error!: Error;
@State() private isAppLoaded = false;

public initialize() {
if (this.bindings.interfaceElement.type === 'product-listing') {
Expand All @@ -57,6 +59,10 @@ export class AtomicLoadMoreProducts {
this.listingOrSearch = buildSearch(this.bindings.engine);
}
this.pagination = this.listingOrSearch.pagination();

createAppLoadedListener(this.bindings.store, (isAppLoaded) => {
this.isAppLoaded = isAppLoaded;
});
}

private get lastProduct() {
Expand All @@ -73,7 +79,7 @@ export class AtomicLoadMoreProducts {
return (
<LoadMoreGuard
hasResults={this.paginationState.totalEntries > 0}
isLoaded={this.bindings.store.isAppLoaded()}
isLoaded={this.isAppLoaded}
>
<LoadMoreContainer>
<LoadMoreSummary
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
InitializeBindings,
} from '../../../utils/initialization-utils';
import {randomID} from '../../../utils/utils';
import {createAppLoadedListener} from '../../common/interface/store';
import {
PagerNextButton,
PagerPageButton,
Expand Down Expand Up @@ -59,6 +60,7 @@ export class AtomicCommercePager
public pagerState!: PaginationState;

@State() error!: Error;
@State() private isAppLoaded = false;

@Event({
eventName: 'atomic/scrollToTop',
Expand Down Expand Up @@ -99,6 +101,9 @@ export class AtomicCommercePager
this.listingOrSearch = buildSearch(this.bindings.engine);
}
this.pager = this.listingOrSearch.pagination();
createAppLoadedListener(this.bindings.store, (isAppLoaded) => {
this.isAppLoaded = isAppLoaded;
});
}

private validateProps() {
Expand All @@ -120,7 +125,7 @@ export class AtomicCommercePager
<PagerGuard
hasError={false}
hasItems={this.pagerState.totalPages > 1}
isAppLoaded={this.bindings.store.isAppLoaded()}
isAppLoaded={this.isAppLoaded}
>
<PagerNavigation i18n={this.bindings.i18n}>
<PagerPreviousButton
Expand Down
Loading
Loading