Skip to content

Commit

Permalink
Merge branch 'master' into SFINT-5491
Browse files Browse the repository at this point in the history
  • Loading branch information
SimonMilord authored Aug 9, 2024
2 parents ee914e0 + f7a9061 commit cbf1e78
Show file tree
Hide file tree
Showing 10 changed files with 306 additions and 69 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2202,14 +2202,14 @@ export declare interface AtomicSortDropdown extends Components.AtomicSortDropdow


@ProxyCmp({
inputs: ['expression', 'label']
inputs: ['expression', 'label', 'tabsExcluded', 'tabsIncluded']
})
@Component({
selector: 'atomic-sort-expression',
changeDetection: ChangeDetectionStrategy.OnPush,
template: '<ng-content></ng-content>',
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
inputs: ['expression', 'label'],
inputs: ['expression', 'label', 'tabsExcluded', 'tabsIncluded'],
})
export class AtomicSortExpression {
protected el: HTMLElement;
Expand Down
16 changes: 16 additions & 0 deletions packages/atomic/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3349,6 +3349,14 @@ export namespace Components {
* The non-localized label to display for this expression.
*/
"label": string;
/**
* The tabs on which the sort expression must not be displayed. This property should not be used at the same time as `tabs-included`. Set this property as a stringified JSON array, e.g., ```html <atomic-sort-expression tabs-excluded='["tabIDA", "tabIDB"]'></atomic-sort-expression> ``` If you don't set this property, the sort expression can be displayed on any tab. Otherwise, the sort expression won't be displayed on any of the specified tabs.
*/
"tabsExcluded": string[] | string;
/**
* The tabs on which the sort expression can be displayed. This property should not be used at the same time as `tabs-excluded`. Set this property as a stringified JSON array, e.g., ```html <atomic-sort-expression tabs-included='["tabIDA", "tabIDB"]'></atomic-sort-expression snippet> ``` If you don't set this property, the sort expression can be displayed on any tab. Otherwise, the sort expression can only be displayed on the specified tabs.
*/
"tabsIncluded": string[] | string;
}
interface AtomicTab {
/**
Expand Down Expand Up @@ -8886,6 +8894,14 @@ declare namespace LocalJSX {
* The non-localized label to display for this expression.
*/
"label": string;
/**
* The tabs on which the sort expression must not be displayed. This property should not be used at the same time as `tabs-included`. Set this property as a stringified JSON array, e.g., ```html <atomic-sort-expression tabs-excluded='["tabIDA", "tabIDB"]'></atomic-sort-expression> ``` If you don't set this property, the sort expression can be displayed on any tab. Otherwise, the sort expression won't be displayed on any of the specified tabs.
*/
"tabsExcluded"?: string[] | string;
/**
* The tabs on which the sort expression can be displayed. This property should not be used at the same time as `tabs-excluded`. Set this property as a stringified JSON array, e.g., ```html <atomic-sort-expression tabs-included='["tabIDA", "tabIDB"]'></atomic-sort-expression snippet> ``` If you don't set this property, the sort expression can be displayed on any tab. Otherwise, the sort expression can only be displayed on the specified tabs.
*/
"tabsIncluded"?: string[] | string;
}
interface AtomicTab {
/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,17 @@ import {
SearchStatus,
FacetManager,
buildFacetManager,
TabManager,
TabManagerState,
buildTabManager,
} from '@coveo/headless';
import {Component, h, State, Prop, Element, Watch} from '@stencil/core';
import {
BindStateToController,
InitializableComponent,
InitializeBindings,
} from '../../../utils/initialization-utils';
import {shouldDisplayOnCurrentTab} from '../../../utils/tab-utils';
import {sortByDocumentPosition} from '../../../utils/utils';
import {findSection} from '../../common/atomic-layout-section/sections';
import {
Expand Down Expand Up @@ -95,6 +99,10 @@ export class AtomicRefineModal implements InitializableComponent {
@State()
public facetManagerState!: FacetManagerState;
@State() @BindStateToController('sort') public sortState!: SortState;
public tabManager!: TabManager;
@BindStateToController('tabManager')
@State()
public tabManagerState!: TabManagerState;
@State() public error!: Error;

@Prop({mutable: true}) openButton?: HTMLElement;
Expand Down Expand Up @@ -126,6 +134,7 @@ export class AtomicRefineModal implements InitializableComponent {
this.querySummary = buildQuerySummary(this.bindings.engine);
this.searchStatus = buildSearchStatus(this.bindings.engine);
this.facetManager = buildFacetManager(this.bindings.engine);
this.tabManager = buildTabManager(this.bindings.engine);
this.watchEnabled(this.isOpen);
}

Expand Down Expand Up @@ -229,7 +238,16 @@ export class AtomicRefineModal implements InitializableComponent {
option && this.sort.sortBy(option.criteria);
}

private buildOption({expression, criteria, label}: SortDropdownOption) {
private buildOption({expression, criteria, label, tabs}: SortDropdownOption) {
if (
!shouldDisplayOnCurrentTab(
[...tabs.included],
[...tabs.excluded],
this.tabManagerState?.activeTab
)
) {
return;
}
return (
<option value={expression} selected={this.sort.isSortedBy(criteria)}>
{this.bindings.i18n.t(label)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
import {makeDesktopQuery} from '../atomic-layout/search-layout';

export interface SortDropdownOption {
tabs: {included: string[] | string; excluded: string[] | string};
expression: string;
criteria: SortCriterion[];
label: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,18 @@ import {
buildSearchStatus,
SearchStatus,
SearchStatusState,
TabManager,
TabManagerState,
buildTabManager,
loadSortCriteriaActions,
} from '@coveo/headless';
import {Component, h, State, Element} from '@stencil/core';
import {
BindStateToController,
InitializableComponent,
InitializeBindings,
} from '../../../utils/initialization-utils';
import {shouldDisplayOnCurrentTab} from '../../../utils/tab-utils';
import {randomID} from '../../../utils/utils';
import {SortContainer} from '../../common/sort/container';
import {SortGuard} from '../../common/sort/guard';
Expand Down Expand Up @@ -50,6 +55,10 @@ export class AtomicSortDropdown implements InitializableComponent {
@BindStateToController('searchStatus')
@State()
private searchStatusState!: SearchStatusState;
public tabManager!: TabManager;
@BindStateToController('tabManager')
@State()
public tabManagerState!: TabManagerState;
@State() public error!: Error;

public initialize() {
Expand All @@ -60,6 +69,7 @@ export class AtomicSortDropdown implements InitializableComponent {
criterion: this.bindings.store.state.sortOptions[0]?.criteria,
},
});
this.tabManager = buildTabManager(this.bindings.engine);
}

private buildOptions() {
Expand All @@ -76,22 +86,34 @@ export class AtomicSortDropdown implements InitializableComponent {

this.bindings.store.set(
'sortOptions',
sortExpressionElements.map(({expression, label}) => {
new Schema({
label: new StringValue({emptyAllowed: false, required: true}),
}).validate({label});
sortExpressionElements.map(
({expression, label, tabsIncluded, tabsExcluded}) => {
new Schema({
label: new StringValue({emptyAllowed: false, required: true}),
}).validate({label});

return {
criteria: parseCriterionExpression(expression),
expression,
label,
};
})
return {
tabs: {
included: tabsIncluded,
excluded: tabsExcluded,
},
criteria: parseCriterionExpression(expression),
expression,
label,
};
}
)
);
}

private get options() {
return this.bindings.store.state.sortOptions;
return this.bindings.store.state.sortOptions.filter(({tabs}) =>
shouldDisplayOnCurrentTab(
[...tabs.included],
[...tabs.excluded],
this.tabManagerState?.activeTab
)
);
}

private select(e: Event) {
Expand All @@ -101,6 +123,21 @@ export class AtomicSortDropdown implements InitializableComponent {
);
option && this.sort.sortBy(option.criteria);
}
public componentShouldUpdate(): void {
if (
this.options.some(
(option) => option.expression === this.sortState.sortCriteria
)
) {
return;
}

const action = loadSortCriteriaActions(
this.bindings.engine
).updateSortCriterion(this.options[0]?.criteria);

this.bindings.engine.dispatch(action);
}

public render() {
const {hasError, hasResults, firstSearchExecuted} = this.searchStatusState;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {Component, Prop, Element, h} from '@stencil/core';
import {ArrayProp} from '../../../utils/props-utils';

/**
* The `atomic-sort-expression` component defines a sort expression. This component must be inside an `atomic-sort-dropdown` component.
Expand Down Expand Up @@ -28,9 +29,41 @@ export class AtomicSortExpression {
* You can specify multiple sort criteria to be used in the same request by separating them with a comma (e.g., `criteria="size ascending, date ascending"`).
*/
@Prop({reflect: true}) public expression!: string;
/**
* The tabs on which the sort expression can be displayed. This property should not be used at the same time as `tabs-excluded`.
*
* Set this property as a stringified JSON array, e.g.,
* ```html
* <atomic-sort-expression tabs-included='["tabIDA", "tabIDB"]'></atomic-sort-expression snippet>
* ```
* If you don't set this property, the sort expression can be displayed on any tab. Otherwise, the sort expression can only be displayed on the specified tabs.
*/
@ArrayProp()
@Prop({reflect: true, mutable: true})
public tabsIncluded: string[] | string = '[]';

/**
* The tabs on which the sort expression must not be displayed. This property should not be used at the same time as `tabs-included`.
*
* Set this property as a stringified JSON array, e.g.,
* ```html
* <atomic-sort-expression tabs-excluded='["tabIDA", "tabIDB"]'></atomic-sort-expression>
* ```
* If you don't set this property, the sort expression can be displayed on any tab. Otherwise, the sort expression won't be displayed on any of the specified tabs.
*/
@ArrayProp()
@Prop({reflect: true, mutable: true})
public tabsExcluded: string[] | string = '[]';

public render() {
if (this.tabsIncluded.length > 0 && this.tabsExcluded.length > 0) {
console.warn(
'Values for both "tabs-included" and "tabs-excluded" have been provided. This is could lead to unexpected behaviors.'
);
}

const dropdownComponent = 'atomic-sort-dropdown';

if (!this.host.closest(dropdownComponent)) {
const error = new Error(
`The "${this.host.nodeName.toLowerCase()}" component has to be used inside an ${dropdownComponent} element.`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,35 @@ export const Default: Story = {
decorators: [
(story) => html`
${story()}
<atomic-refine-toggle></atomic-refine-toggle>
<div style="padding:10px;">
<atomic-sort-dropdown>
<atomic-sort-expression
tabs-excluded='["article"]'
label="Name descending"
expression="name descending"
></atomic-sort-expression>
<atomic-sort-expression
tabs-excluded='["article"]'
label="Name ascending"
expression="name ascending"
></atomic-sort-expression>
<atomic-sort-expression
tabs-included='["article"]'
label="Most Recent"
expression="date descending"
></atomic-sort-expression>
<atomic-sort-expression
tabs-included='["article"]'
label="Least Recent"
expression="date ascending"
></atomic-sort-expression>
<atomic-sort-expression
label="relevance"
expression="relevancy"
></atomic-sort-expression>
</atomic-sort-dropdown>
</div>
<div style="display: flex;">
<atomic-smart-snippet
tabs-included='["article", "documentation"]'
Expand Down
Loading

0 comments on commit cbf1e78

Please sign in to comment.