Skip to content

Commit

Permalink
docs(headless): add samples for automatic facet controllers (#3054)
Browse files Browse the repository at this point in the history
  • Loading branch information
aprudhomme-coveo authored Jul 28, 2023
1 parent 1958cc6 commit 6649e88
Show file tree
Hide file tree
Showing 6 changed files with 212 additions and 0 deletions.
26 changes: 26 additions & 0 deletions packages/headless/doc-parser/use-cases/search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,32 @@ const controllers: ControllerConfiguration[] = [
],
},
},
{
initializer: 'buildAutomaticFacetBuilder',
samplePaths: {
react_class: [
'packages/samples/headless-react/src/components/automatic-facet-builder/automatic-facet-builder.class.tsx',
'packages/samples/headless-react/src/components/automatic-facet/automatic-facet.class.tsx',
],
react_fn: [
'packages/samples/headless-react/src/components/automatic-facet-builder/automatic-facet-builder.fn.tsx',
'packages/samples/headless-react/src/components/automatic-facet/automatic-facet.fn.tsx',
],
},
},
{
initializer: 'buildAutomaticFacet',
samplePaths: {
react_fn: [
'packages/samples/headless-react/src/components/automatic-facet/automatic-facet.fn.tsx',
'packages/samples/headless-react/src/components/automatic-facet-builder/automatic-facet-builder.fn.tsx',
],
react_class: [
'packages/samples/headless-react/src/components/automatic-facet/automatic-facet.class.tsx',
'packages/samples/headless-react/src/components/automatic-facet-builder/automatic-facet-builder.class.tsx',
],
},
},
];

const actionLoaders: ActionLoaderConfiguration[] = [
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import {
buildAutomaticFacetBuilder,
AutomaticFacetBuilderProps,
AutomaticFacetBuilderState,
AutomaticFacetBuilder as HeadlessAutomaticFacetBuilder,
Unsubscribe,
} from '@coveo/headless';
import {Component, ContextType} from 'react';
import {AppContext} from '../../context/engine';
import {AutomaticFacet} from '../automatic-facet/automatic-facet.class';

export class AutomaticFacetBuilder extends Component<
AutomaticFacetBuilderProps,
AutomaticFacetBuilderState
> {
static contextType = AppContext;
context!: ContextType<typeof AppContext>;

private controller!: HeadlessAutomaticFacetBuilder;
private unsubscribe: Unsubscribe = () => {};

componentDidMount() {
this.controller = buildAutomaticFacetBuilder(
this.context.engine!,
this.props
);
this.updateState();

this.unsubscribe = this.controller.subscribe(() => this.updateState());
}

componentWillUnmount() {
this.unsubscribe();
}

private updateState() {
this.setState(this.controller.state);
}

render() {
if (!this.state) {
return null;
}
const automaticFacets = this.state.automaticFacets.map((facet) => {
return (
<AutomaticFacet
key={facet.state.field}
controller={facet}
></AutomaticFacet>
);
});
return automaticFacets;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import {AutomaticFacetBuilder as HeadlessAutomaticFacetBuilder} from '@coveo/headless';
import {FunctionComponent, useEffect, useState} from 'react';
import {AutomaticFacet as AutomaticFacetFn} from '../automatic-facet/automatic-facet.fn';

interface AutomaticFacetBuilderProps {
controller: HeadlessAutomaticFacetBuilder;
}

export const AutomaticFacetBuilder: FunctionComponent<
AutomaticFacetBuilderProps
> = (props) => {
const {controller} = props;
const [state, setState] = useState(controller.state);

useEffect(() => controller.subscribe(() => setState(controller.state)), []);

const automaticFacets = state.automaticFacets.map((facet) => {
return (
<AutomaticFacetFn
key={facet.state.field}
controller={facet}
></AutomaticFacetFn>
);
});
return <div>{automaticFacets}</div>;
};

// usage

/**
* ```tsx
* const props: AutomaticFacetBuilderProps = {desiredCount: 5}
* const controller = buildAutomaticFacetBuilder(engine, props);
*
* <AutomaticFacetBuilder controller={controller} />;
* ```
*/
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import {
AutomaticFacetState,
AutomaticFacet as HeadlessAutomaticFacet,
Unsubscribe,
} from '@coveo/headless';
import {Component} from 'react';

interface AutomaticFacetProps {
controller: HeadlessAutomaticFacet;
}
export class AutomaticFacet extends Component<
AutomaticFacetProps,
AutomaticFacetState
> {
private controller!: HeadlessAutomaticFacet;
private unsubscribe: Unsubscribe = () => {};

componentDidMount() {
this.controller = this.props.controller;
this.updateState();

this.unsubscribe = this.controller.subscribe(() => this.updateState());
}

componentWillUnmount() {
this.unsubscribe();
}

private updateState() {
this.setState(this.controller.state);
}

render() {
if (!this.state) {
return null;
}
return (
<ul>
{this.state.values.map((value) => (
<li key={value.value}>
<input
type="checkbox"
checked={value.state === 'selected'}
onChange={() => this.controller.toggleSelect(value)}
/>
{value.value} ({value.numberOfResults} results)
</li>
))}
</ul>
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import {AutomaticFacet as HeadlessAutomaticFacet} from '@coveo/headless';
import {FunctionComponent, useEffect, useState} from 'react';

interface AutomaticFacetProps {
controller: HeadlessAutomaticFacet;
}

export const AutomaticFacet: FunctionComponent<AutomaticFacetProps> = (
props
) => {
const {controller} = props;
const [state, setState] = useState(controller.state);

useEffect(() => controller.subscribe(() => setState(controller.state)), []);

return (
<ul>
{state.values.map((value) => (
<li key={value.value}>
<input
type="checkbox"
checked={value.state === 'selected'}
onChange={() => controller.toggleSelect(value)}
/>
{value.value} ({value.numberOfResults} results)
</li>
))}
</ul>
);
};
13 changes: 13 additions & 0 deletions packages/samples/headless-react/src/pages/SearchPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,14 @@ import {
RecentResultsList as HeadlessRecentResultsList,
buildRecentResultsList,
InstantResults as HeadlessInstantResults,
AutomaticFacetBuilder as HeadlessAutomaticFacetBuilder,
buildInstantResults,
buildAutomaticFacetBuilder,
} from '@coveo/headless';
import filesize from 'filesize';
import {Component} from 'react';
import {AutomaticFacetBuilder} from '../components/automatic-facet-builder/automatic-facet-builder.class';
import {AutomaticFacetBuilder as AutomaticFacetBuilderFn} from '../components/automatic-facet-builder/automatic-facet-builder.fn';
import {BreadcrumbManager} from '../components/breadcrumb-manager/breadcrumb-manager.class';
import {BreadcrumbManager as BreadcrumbManagerFn} from '../components/breadcrumb-manager/breadcrumb-manager.fn';
import {CategoryFacet} from '../components/category-facet/category-facet.class';
Expand Down Expand Up @@ -225,6 +229,7 @@ export class SearchPage extends Component {
private readonly recentResultsList: HeadlessRecentResultsList;
private readonly instantResults: HeadlessInstantResults;
private readonly searchboxInstantResults: HeadlessSearchBox;
private readonly automaticFacetBuilder: HeadlessAutomaticFacetBuilder;

private unsubscribeUrlManager!: Unsubscribe;

Expand Down Expand Up @@ -273,6 +278,10 @@ export class SearchPage extends Component {

this.facetManager = buildFacetManager(this.engine);

this.automaticFacetBuilder = buildAutomaticFacetBuilder(this.engine, {
desiredCount: 5,
});

this.geographyFacet = buildCategoryFacet(this.engine, {
options: {
field: 'geographicalhierarchy',
Expand Down Expand Up @@ -585,6 +594,7 @@ export class SearchPage extends Component {
<StaticFilterFn id="filetypes-b" values={this.staticFilterValues} />
</Section>
<Section title="facet">
<AutomaticFacetBuilder desiredCount={5}></AutomaticFacetBuilder>
<FacetManager>
<CategoryFacet
field="geographicalhierarchy"
Expand Down Expand Up @@ -628,6 +638,9 @@ export class SearchPage extends Component {
/>
<DateFilter field="date" facetId="date-3" />
</FacetManager>
<AutomaticFacetBuilderFn
controller={this.automaticFacetBuilder}
></AutomaticFacetBuilderFn>
<FacetManagerFn controller={this.facetManager}>
<CategoryFacetFn controller={this.geographyFacet} />
<FacetFn controller={this.objectTypeFacet} />
Expand Down

0 comments on commit 6649e88

Please sign in to comment.