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

feat(headless commerce ssr): merge controller props and ControllerDefinitionOption #4316

Merged
merged 117 commits into from
Sep 6, 2024
Merged
Show file tree
Hide file tree
Changes from 116 commits
Commits
Show all changes
117 commits
Select commit Hold shift + click to select a range
9ac3b3e
add CoreEngineNext type
y-lakhdar Jul 15, 2024
da8d657
draft commerce engine
y-lakhdar Jul 15, 2024
9dfd822
add commerce engine
y-lakhdar Jul 17, 2024
9b55110
revert CommerceEngineOptions modification
y-lakhdar Jul 17, 2024
1eec820
Merge branch 'master' of github.com:coveo/ui-kit into KIT-3390
y-lakhdar Jul 17, 2024
4335428
convert type to interface
y-lakhdar Jul 17, 2024
5011f94
remove legacySearchAction type
y-lakhdar Jul 23, 2024
cbe8ea1
add note
y-lakhdar Jul 25, 2024
c0d257c
remove search type support
y-lakhdar Jul 25, 2024
0d69866
add ssr.index.ts
y-lakhdar Jul 25, 2024
5c63b4e
add sample
y-lakhdar Jul 25, 2024
eed1bfd
draft
y-lakhdar Jul 25, 2024
ec998c1
revert samples
y-lakhdar Jul 25, 2024
68ea3c7
remove ssr sample
y-lakhdar Jul 25, 2024
8fc01df
clean PR
y-lakhdar Jul 25, 2024
1abd6b5
mixed reset
y-lakhdar Jul 25, 2024
045963a
clean PR
y-lakhdar Jul 25, 2024
ca34fe8
update readme
y-lakhdar Jul 25, 2024
2d5ddf3
add navigator context provider
y-lakhdar Jul 25, 2024
99593c6
log warning when context provider is missing
y-lakhdar Jul 26, 2024
243b35b
add nextjs implementation of navigator context
y-lakhdar Jul 26, 2024
b0f23c7
add navigator context doc
y-lakhdar Jul 26, 2024
71c825a
remove hard coded client id fallback
y-lakhdar Jul 26, 2024
5aab898
rename const
y-lakhdar Jul 26, 2024
455cde8
renaming vars
y-lakhdar Jul 26, 2024
6a336ec
add NavigatorContext in ssr sample
y-lakhdar Jul 30, 2024
eea5fc9
Merge branch 'master' of github.com:coveo/ui-kit into KIT-3395
y-lakhdar Aug 1, 2024
d61812e
lock
y-lakhdar Aug 1, 2024
84de638
fix merge conflicts
y-lakhdar Aug 1, 2024
bd17441
revert merge concfix merge conflicts
y-lakhdar Aug 1, 2024
f8254c1
delete unecessary file
y-lakhdar Aug 1, 2024
66ec80a
lock
y-lakhdar Aug 1, 2024
43f0930
add doc to Navigator Context
y-lakhdar Aug 1, 2024
462cba8
fix build:doc
y-lakhdar Aug 1, 2024
26ea809
Merge branch 'KIT-3395' of github.com:coveo/ui-kit into KIT-3116
y-lakhdar Aug 1, 2024
f59533b
apply corrections
y-lakhdar Aug 1, 2024
c7b4942
Merge branch 'KIT-3116' of github.com:coveo/ui-kit into KIT-3394
y-lakhdar Aug 1, 2024
1506117
setup generic solution type logic
y-lakhdar Aug 1, 2024
3fc881d
update samples
y-lakhdar Aug 1, 2024
bb0c354
simplify config
y-lakhdar Aug 1, 2024
7e46c00
move middleware
y-lakhdar Aug 1, 2024
bdfc6f4
updated sample org public creds
y-lakhdar Aug 1, 2024
dd8798b
update sub-controller definition types
y-lakhdar Aug 1, 2024
b62325a
remove unused controllers
y-lakhdar Aug 1, 2024
37b12ca
use simper functions
y-lakhdar Aug 1, 2024
c45a4e3
fix fetch static state typing inference
y-lakhdar Aug 2, 2024
f8f8eaf
clean PR
y-lakhdar Aug 2, 2024
cfe4e26
rename listing and search definition
y-lakhdar Aug 2, 2024
3c09c32
remove searchbox definitions
y-lakhdar Aug 2, 2024
6748d58
Merge branch 'master' into KIT-3116
y-lakhdar Aug 5, 2024
198691a
update page-router sample
y-lakhdar Aug 5, 2024
7f50b51
Merge branch 'KIT-3116' of github.com:coveo/ui-kit into KIT-3116
y-lakhdar Aug 5, 2024
0bb2483
Merge branch 'master' into KIT-3116
alexprudhomme Aug 5, 2024
a2b1dff
Start working on sub-controller define functions
fbeaudoincoveo Aug 6, 2024
957d0bb
Add console logs
fbeaudoincoveo Aug 6, 2024
ca38a20
Rework summary component
fbeaudoincoveo Aug 7, 2024
bcee02a
Add pagination component
fbeaudoincoveo Aug 7, 2024
ee18f4f
Rework showmore component
fbeaudoincoveo Aug 7, 2024
2ee91d5
Add sort exports
fbeaudoincoveo Aug 7, 2024
c60ee05
Add sort component
fbeaudoincoveo Aug 7, 2024
c3b4c86
Define sort controller
fbeaudoincoveo Aug 7, 2024
2a2c25d
Adjust listingpage component
fbeaudoincoveo Aug 7, 2024
7a1a40c
Merge branch 'master' into KIT-3116
alexprudhomme Aug 7, 2024
832fec4
Expose interactiveProduct on ProductList type
fbeaudoincoveo Aug 7, 2024
077002d
fix pages-router by splitting contextProvider in two different strate…
alexprudhomme Aug 8, 2024
30e6dfc
Add basic PDP
fbeaudoincoveo Aug 8, 2024
95af8a6
Log product views
fbeaudoincoveo Aug 8, 2024
39bb0e3
Use sample commerce config
fbeaudoincoveo Aug 8, 2024
6e13c9f
Merge branch 'master' into KIT-3116
y-lakhdar Aug 8, 2024
222a94b
Merge branch 'KIT-3116' of https://github.com/coveo/ui-kit into KIT-3116
alexprudhomme Aug 8, 2024
fceeb03
Merge branch 'KIT-3116' into KIT-3394
alexprudhomme Aug 8, 2024
a0a6f31
Merge branch 'master' into KIT-3394
y-lakhdar Aug 8, 2024
7736236
Move sub-controller definitions to dedicated files & update exports
fbeaudoincoveo Aug 9, 2024
91ab8b2
Use Pagination component by default
fbeaudoincoveo Aug 9, 2024
11195a8
Add TODOs
fbeaudoincoveo Aug 9, 2024
3eca213
Use p instead of div
fbeaudoincoveo Aug 9, 2024
d963f6f
Add suspense fallback
fbeaudoincoveo Aug 9, 2024
61c921a
Merge branch 'master' into KIT-3394
alexprudhomme Aug 9, 2024
9b13c62
Merge branch 'KIT-3394' into KIT-3392
alexprudhomme Aug 9, 2024
f0d1fb0
Simplify typing
fbeaudoincoveo Aug 9, 2024
3674ca7
Merge branch 'KIT-3392' of github.com:coveo/ui-kit into KIT-3392
fbeaudoincoveo Aug 9, 2024
8c145c1
Readd @internal tag
fbeaudoincoveo Aug 9, 2024
ebae0ea
Remove .ts extension from export
fbeaudoincoveo Aug 9, 2024
f4b28bf
Add summary state exports and fix sample
fbeaudoincoveo Aug 9, 2024
6411044
Rename function
fbeaudoincoveo Aug 9, 2024
56b207a
replace AnyAction with UnknownAction
y-lakhdar Aug 9, 2024
ffafff0
Merge branch 'master' into KIT-3394
y-lakhdar Aug 9, 2024
fb822ca
apply corrections
y-lakhdar Aug 9, 2024
ace9d83
Apply suggestions from code review
y-lakhdar Aug 9, 2024
286f0de
revert engine config
y-lakhdar Aug 9, 2024
e83dffc
lint
y-lakhdar Aug 9, 2024
b53e6dd
Merge branch 'KIT-3394' of github.com:coveo/ui-kit into KIT-3394
y-lakhdar Aug 9, 2024
31f1ac1
Merge branch 'KIT-3394' into KIT-3392
fbeaudoincoveo Aug 13, 2024
a0ce081
Add CAPI to cspell
fbeaudoincoveo Aug 16, 2024
a714b18
Refactor CoreCommerceFacet to expose state getter
fbeaudoincoveo Aug 16, 2024
b96d00d
Refactor RegularFacet to expose state getter
fbeaudoincoveo Aug 16, 2024
3e56ca9
Refactor CategoryFacet to expose state getter
fbeaudoincoveo Aug 16, 2024
d77b264
Refactor NumericFacet to expose state getter
fbeaudoincoveo Aug 16, 2024
de0af20
Refactor DateFacet to expose state getter
fbeaudoincoveo Aug 16, 2024
7144ebf
Refactor response selectors into redux selectors
fbeaudoincoveo Aug 16, 2024
2e8990d
Export MappedGeneratedFacetController type
fbeaudoincoveo Aug 16, 2024
0e1848e
Add SSR FacetGenerator
fbeaudoincoveo Aug 16, 2024
8c84455
Add SSR facet generator tests
fbeaudoincoveo Aug 16, 2024
e6bee06
Add facet generator related exports
fbeaudoincoveo Aug 16, 2024
70f614c
Add SSR facet generator in sample
fbeaudoincoveo Aug 16, 2024
3d1727d
Change warning message
fbeaudoincoveo Aug 16, 2024
d32c7e6
Merge branch 'master' of github.com:coveo/ui-kit into KIT-3397
y-lakhdar Aug 24, 2024
28ea874
add facet to search page
y-lakhdar Aug 24, 2024
b5ed750
merge options
y-lakhdar Aug 24, 2024
35c0654
Merge branch 'master' into KIT-3397
y-lakhdar Aug 26, 2024
adc4146
Merge branch 'KIT-3397' into KIT-3486
y-lakhdar Aug 26, 2024
2e96d93
Apply review comment
fbeaudoincoveo Aug 26, 2024
d819318
Merge branch 'KIT-3397' into KIT-3486
y-lakhdar Aug 26, 2024
842f32f
Fix failing tests
fbeaudoincoveo Aug 26, 2024
6ef6291
Merge branch 'master' into KIT-3397
fbeaudoincoveo Aug 26, 2024
64264b2
Merge branch 'KIT-3397' into KIT-3486
louis-bompart Aug 27, 2024
fc45ef1
Merge branch 'master' of github.com:coveo/ui-kit into KIT-3486
y-lakhdar Sep 3, 2024
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
1 change: 1 addition & 0 deletions .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"bloup",
"bpsb",
"btoashim",
"CAPI",
"cfcomment",
"cfpage",
"cfspace",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,9 +133,7 @@ export class AtomicCommerceFacets implements InitializableComponent<Bindings> {
></atomic-commerce-category-facet>
);
default: {
this.bindings.engine.logger.warn(
`Unexpected facet type ${facet.state.type}.`
);
this.bindings.engine.logger.warn('Unexpected facet type.');
return;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,7 @@ export type CategoryFacetSearchState =
export type CategoryFacetSearch = Omit<
ReturnType<typeof buildCoreCategoryFacetSearch>,
'showMoreResults' | 'updateCaptions' | 'state'
> & {
state: CategoryFacetSearchState;
};
>;

export function buildCategoryFacetSearch(
engine: CommerceEngine,
Expand All @@ -40,7 +38,7 @@ export function buildCategoryFacetSearch(
throw loadReducerError;
}

const {showMoreResults, updateCaptions, ...restOfFacetSearch} =
const {showMoreResults, state, updateCaptions, ...restOfFacetSearch} =
buildCoreCategoryFacetSearch(engine, {
...props,
executeFacetSearchActionCreator: (facetId: string) =>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
import {createSelector} from '@reduxjs/toolkit';
import {
CommerceEngine,
CommerceEngineState,
} from '../../../../../app/commerce-engine/commerce-engine';
import {CommerceEngine} from '../../../../../app/commerce-engine/commerce-engine';
import {stateKey} from '../../../../../app/state-key';
import {
toggleSelectCategoryFacetValue,
Expand All @@ -11,6 +7,7 @@ import {
import {CategoryFacetValueRequest} from '../../../../../features/commerce/facets/facet-set/interfaces/request';
import {defaultNumberOfValuesIncrement} from '../../../../../features/facets/category-facet-set/category-facet-set-actions';
import {findActiveValueAncestry} from '../../../../../features/facets/category-facet-set/category-facet-utils';
import {categoryFacetSearchStateSelector} from '../../../../../features/facets/facet-search-set/category/category-facet-search-state-selector';
import {
CategoryFacetValue,
CoreCommerceFacet,
Expand All @@ -32,13 +29,17 @@ export type CategoryFacetOptions = Omit<
> &
SearchableFacetOptions;

export type CategoryFacetState = CoreCommerceFacetState<CategoryFacetValue> & {
export type CategoryFacetState = Omit<
CoreCommerceFacetState<CategoryFacetValue>,
'type'
> & {
activeValue?: CategoryFacetValue;
canShowLessValues: boolean;
canShowMoreValues: boolean;
hasActiveValues: boolean;
selectedValueAncestry?: CategoryFacetValue[];
facetSearch: CategoryFacetSearchState;
type: 'hierarchical';
};

/**
Expand Down Expand Up @@ -85,27 +86,13 @@ export function buildCategoryFacet(
coreController;
const {dispatch} = engine;
const getFacetId = () => coreController.state.facetId;
const createFacetSearch = () => {
return buildCategoryFacetSearch(engine, {
options: {facetId: getFacetId(), ...options.facetSearch},
select: () => {
dispatch(options.fetchProductsActionCreator());
},
isForFieldSuggestions: false,
});
};

const facetSearch = createFacetSearch();
const {state, ...restOfFacetSearch} = facetSearch;
const facetSearchStateSelector = createSelector(
(state: CommerceEngineState) => state.categoryFacetSearchSet[getFacetId()],
(facetSearch) => ({
isLoading: facetSearch.isLoading,
moreValuesAvailable: facetSearch.response.moreValuesAvailable,
query: facetSearch.options.query,
values: facetSearch.response.values,
})
);
const facetSearch = buildCategoryFacetSearch(engine, {
options: {facetId: getFacetId(), ...options.facetSearch},
select: () => {
dispatch(options.fetchProductsActionCreator());
},
isForFieldSuggestions: false,
});

return {
deselectAll,
Expand Down Expand Up @@ -136,35 +123,49 @@ export function buildCategoryFacet(
dispatch(options.fetchProductsActionCreator());
},

facetSearch: restOfFacetSearch,
facetSearch,

get state() {
const selectedValueAncestry = findActiveValueAncestry(
coreController.state.values
return getCategoryFacetState(
coreController.state,
categoryFacetSearchStateSelector(engine[stateKey], getFacetId())
);
const activeValue = selectedValueAncestry.length
? selectedValueAncestry[selectedValueAncestry.length - 1]
: undefined;
const canShowLessValues = activeValue
? activeValue.children.length > defaultNumberOfValuesIncrement
: false;
const canShowMoreValues =
activeValue?.moreValuesAvailable ??
coreController.state.canShowMoreValues ??
false;
const hasActiveValues = !!activeValue;

return {
...coreController.state,
activeValue,
canShowLessValues,
canShowMoreValues,
hasActiveValues,
selectedValueAncestry,
facetSearch: facetSearchStateSelector(engine[stateKey]),
};
},

type: 'hierarchical',
};
}

export const getCategoryFacetState = (
coreState: CoreCommerceFacetState<CategoryFacetValue>,
facetSearchSelector: ReturnType<typeof categoryFacetSearchStateSelector>
): CategoryFacetState => {
const {values} = coreState;
const selectedValueAncestry = findActiveValueAncestry(values);
const activeValue = selectedValueAncestry.length
? selectedValueAncestry[selectedValueAncestry.length - 1]
: undefined;
const canShowLessValues = activeValue
? activeValue.children.length > defaultNumberOfValuesIncrement
: false;
const canShowMoreValues =
activeValue?.moreValuesAvailable ?? coreState.canShowMoreValues ?? false;
const hasActiveValues = !!activeValue;
return {
...coreState,
activeValue,
canShowLessValues,
canShowMoreValues,
facetSearch: {
isLoading: facetSearchSelector?.isLoading ?? false,
moreValuesAvailable:
facetSearchSelector?.response.moreValuesAvailable ?? false,
query: facetSearchSelector?.options.query ?? '',
values: facetSearchSelector?.response.values ?? [],
},
hasActiveValues,
selectedValueAncestry,
type: 'hierarchical',
values,
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,12 @@ export type DateFacetOptions = Omit<
'toggleSelectActionCreator' | 'toggleExcludeActionCreator'
>;

export type DateFacetState = CoreCommerceFacetState<DateFacetValue>;
export type DateFacetState = Omit<
CoreCommerceFacetState<DateFacetValue>,
'type'
> & {
type: 'dateRange';
};

/**
* The `DateFacet` sub-controller offers a high-level programming interface for implementing date commerce
Expand Down Expand Up @@ -86,9 +91,18 @@ export function buildCommerceDateFacet(
},

get state() {
return coreController.state;
return getDateFacetState(coreController.state);
},

type: 'dateRange',
};
}

export const getDateFacetState = (
coreState: CoreCommerceFacetState<DateFacetValue>
): DateFacetState => {
return {
...coreState,
type: 'dateRange',
};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
import {SolutionType} from '../../../../../app/commerce-ssr-engine/types/common';
import {AnyFacetResponse} from '../../../../../features/commerce/facets/facet-set/interfaces/response';
import {CommerceAppState} from '../../../../../state/commerce-app-state';
import {buildMockCategoryFacetSearch} from '../../../../../test/mock-category-facet-search';
import {buildMockCommerceFacetRequest} from '../../../../../test/mock-commerce-facet-request';
import {
buildMockCategoryFacetResponse,
buildMockCommerceDateFacetResponse,
buildMockCommerceNumericFacetResponse,
buildMockCommerceRegularFacetResponse,
} from '../../../../../test/mock-commerce-facet-response';
import {buildMockCommerceState} from '../../../../../test/mock-commerce-state';
import {
buildMockSSRCommerceEngine,
MockedCommerceEngine,
} from '../../../../../test/mock-engine-v2';
import {buildMockFacetSearch} from '../../../../../test/mock-facet-search';
import {buildProductListing} from '../../../product-listing/headless-product-listing';
import {buildSearch} from '../../../search/headless-search';
import {FacetType} from '../headless-core-commerce-facet';
import {GeneratedFacetControllers} from './headless-commerce-facet-generator';
import {
buildFacetGenerator,
FacetGenerator,
FacetGeneratorOptions,
} from './headless-commerce-facet-generator.ssr';

describe('SSR FacetGenerator', () => {
let engine: MockedCommerceEngine;
let state: CommerceAppState;
let options: FacetGeneratorOptions;
let facetGenerator: FacetGenerator;
let facetsInEngineState: {facetId: string; type: FacetType}[];

function initEngine(preloadedState = buildMockCommerceState()) {
engine = buildMockSSRCommerceEngine({...preloadedState});
}

function initCommerceFacetGenerator() {
facetGenerator = buildFacetGenerator(engine, options);
}

function setFacetState(config = facetsInEngineState) {
for (const facet of config) {
const {facetId, type} = facet;
state.facetOrder.push(facetId);
let response: AnyFacetResponse;
switch (type) {
case 'dateRange':
response = buildMockCommerceDateFacetResponse({facetId, type});
break;
case 'hierarchical':
response = buildMockCategoryFacetResponse({facetId, type});
break;
case 'numericalRange':
response = buildMockCommerceNumericFacetResponse({facetId, type});
break;
case 'regular':
default:
response = buildMockCommerceRegularFacetResponse({facetId, type});
}
if (options.props.solutionType === SolutionType.listing) {
state.productListing.facets.push(response);
} else {
state.commerceSearch.facets.push(response);
}

state.commerceFacetSet[facet.facetId] = {
request: buildMockCommerceFacetRequest({
facetId: facet.facetId,
type: facet.type,
}),
};
if (type === 'regular') {
state.facetSearchSet[facet.facetId] = buildMockFacetSearch();
} else if (type === 'hierarchical') {
state.categoryFacetSearchSet[facet.facetId] =
buildMockCategoryFacetSearch();
}
}
}

beforeEach(() => {
jest.resetAllMocks();
});
describe.each([
{
solutionType: SolutionType.listing,
buildGeneratedCSRFacetControllersFunction: () =>
buildProductListing(engine).facetGenerator().facets,
},
{
solutionType: SolutionType.search,
buildGeneratedCSRFacetControllersFunction: () =>
buildSearch(engine).facetGenerator().facets,
},
])(
'when solutionType is $solutionType',
({solutionType, buildGeneratedCSRFacetControllersFunction}) => {
let generatedCSRFacetControllers: GeneratedFacetControllers;
beforeEach(() => {
options = {props: {solutionType}};
facetsInEngineState = [
{
facetId: 'category-facet',
type: 'hierarchical',
},
{
facetId: 'date-facet',
type: 'dateRange',
},
{
facetId: 'numeric-facet',
type: 'numericalRange',
},
{
facetId: 'regular-facet',
type: 'regular',
},
];
state = buildMockCommerceState();
setFacetState(facetsInEngineState);
initEngine(state);
initCommerceFacetGenerator();

generatedCSRFacetControllers =
buildGeneratedCSRFacetControllersFunction();
});

it('initialized', () => {
expect(facetGenerator).toBeTruthy();
});
it('#state is an array containing the state of each facet', () => {
expect(facetGenerator.state.length).toBe(4);
expect(
facetGenerator.state.map((facet) => ({
facetId: facet.facetId,
type: facet.type,
}))
).toEqual(facetsInEngineState);
});

it('#getFacetController returns facet controller for the given facet id and type', () => {
for (const facetInEngineState of facetsInEngineState) {
const {facetId, type} = facetInEngineState;
const generatedSSRFacetController = facetGenerator.getFacetController(
facetId,
type
);
const generatedCSRFacetController = generatedCSRFacetControllers.find(
(controller) => controller.state.facetId === facetId
);
expect(generatedSSRFacetController).toBeTruthy();
expect(generatedSSRFacetController?.type).toBe(
generatedCSRFacetController?.type
);
expect(generatedSSRFacetController?.state).toEqual(
generatedCSRFacetController?.state
);
}
});
}
);
});
Loading
Loading