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

Add support for facets sorting (default by count) #222

Merged
merged 2 commits into from
Jan 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 7 additions & 0 deletions addon-test-support/table-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,13 @@ export default class TableManager implements ITableManager {
payload: {
name: 'The Foo Fighters'
},
count: 29
},
{
identifier: 'band:2',
payload: {
name: 'Arctic Monkeys'
},
count: 4
}
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<OSS::InputContainer
@value={{this.searchQuery}}
@onChange={{this.onInputChanged}}
@placeholder={{t "hypertable.column.filtering.search_term.placeholder"}}
@placeholder={{this.searchPlaceholder}}
>
<:suffix>
{{#if (gt this.searchQuery.length 0)}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
import { debounce } from '@ember/runloop';
import { inject as service } from '@ember/service';
import { isEmpty } from '@ember/utils';

import { IntlService } from 'ember-intl';

import TableHandler from '@upfluence/hypertable/core/handler';
import { Column, Facet, FacetsResponse, Filter } from '@upfluence/hypertable/core/interfaces';

Expand All @@ -12,12 +15,16 @@ interface FacetsLoaderArgs {
column: Column;
facettingKey: string;
searchEnabled: boolean;
searchPlaceholder?: string;
sortCompareFn?(a: Facet, b: Facet): number;
}

const SEARCH_DEBOUNCE_TIME: number = 300;
const FACET_APPLY_DEBOUNCE_TIME: number = 300;

export default class HyperTableV2FacetsLoader extends Component<FacetsLoaderArgs> {
@service declare intl: IntlService;

@tracked loading = false;
@tracked facets: Facet[] = [];
@tracked appliedFacets: string[] = [];
Expand All @@ -43,10 +50,18 @@ export default class HyperTableV2FacetsLoader extends Component<FacetsLoaderArgs
return this.args.searchEnabled ?? false;
}

get searchPlaceholder(): string {
return this.args.searchPlaceholder ?? this.intl.t('hypertable.column.filtering.search_term.placeholder');
}

get skeletonStyle(): string {
return ['width: 100%', 'height: 10px'].join(';');
}

get facetsSorter(): (a: Facet, b: Facet) => number {
return this.args.sortCompareFn ?? this.defaultSortCompareFn;
}

@action
onInputChanged(): void {
debounce(this, this.fetchFacets, SEARCH_DEBOUNCE_TIME);
Expand Down Expand Up @@ -123,7 +138,7 @@ export default class HyperTableV2FacetsLoader extends Component<FacetsLoaderArgs
this.searchQuery
)
.then(({ facets, filtering_key }: FacetsResponse) => {
this.facets = facets;
this.facets = facets.sort(this.facetsSorter);
this.filteringKey = filtering_key;

const filterForKey = this.args.column.filters.find((v) => v.key === this.filteringKey);
Expand All @@ -138,4 +153,8 @@ export default class HyperTableV2FacetsLoader extends Component<FacetsLoaderArgs
this.loading = false;
});
}

private defaultSortCompareFn(a: Facet, b: Facet): number {
return (b.count ?? 0) - (a.count ?? 0);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ module('Integration | Component | hyper-table-v2/facets-loader', function (hooks
});

module('facet display', function () {
test('the facets are displayed correctly using the dedicated named block', async function (assert: Assert) {
test('the facets are displayed correctly using the dedicated named block & are ordered by count value', async function (assert: Assert) {
await render(
hbs`
<HyperTableV2::FilteringRenderers::Common::FacetsLoader @handler={{this.handler}} @column={{this.column}} @searchEnabled={{false}}>
Expand All @@ -33,8 +33,32 @@ module('Integration | Component | hyper-table-v2/facets-loader', function (hooks
</HyperTableV2::FilteringRenderers::Common::FacetsLoader>`
);

assert.dom('.hypertable__facetting .item').exists({ count: 1 });
assert.dom('.hypertable__facetting .item').hasText('The Foo Fighters');
assert.dom('.hypertable__facetting .item').exists({ count: 2 });
assert.dom('.hypertable__facetting > div:nth-child(1) .item').hasText('The Foo Fighters');
assert.dom('.hypertable__facetting > div:nth-child(2) .item').hasText('Arctic Monkeys');
});

test('the facets are ordered using the @sortCompareFn arg function when provided', async function (assert: Assert) {
this.sortCompareFn = sinon.stub().callsFake((a, b) => {
if (a.payload.name < b.payload.name) return -1;
if (a.payload.name > b.payload.name) return 1;
return 0;
});

await render(
hbs`
<HyperTableV2::FilteringRenderers::Common::FacetsLoader @handler={{this.handler}} @column={{this.column}} @searchEnabled={{false}} @sortCompareFn={{this.sortCompareFn}}>
<:facet-item as |facetting|>
{{facetting.facet.payload.name}}
</:facet-item>
</HyperTableV2::FilteringRenderers::Common::FacetsLoader>`
);

assert.dom('.hypertable__facetting .item').exists({ count: 2 });
assert.dom('.hypertable__facetting > div:nth-child(1) .item').hasText('Arctic Monkeys');
assert.dom('.hypertable__facetting > div:nth-child(2) .item').hasText('The Foo Fighters');

assert.ok(this.sortCompareFn.calledOnce);
});
});

Expand Down Expand Up @@ -94,6 +118,26 @@ module('Integration | Component | hyper-table-v2/facets-loader', function (hooks
assert.dom('.oss-input-container').exists();
});

test('the default search placeholder is displayed when no searchPlaceholder arg is provided', async function (assert: Assert) {
await render(
hbs`<HyperTableV2::FilteringRenderers::Common::FacetsLoader @handler={{this.handler}} @column={{this.column}} @searchEnabled={{true}}/>`
);

assert.dom('.oss-input-container').exists();
assert
.dom('.oss-input-container input')
.hasAttribute('placeholder', this.intl.t('hypertable.column.filtering.search_term.placeholder'));
});

test('the search input has the provided searchPlaceholder arg properly used', async function (assert: Assert) {
await render(
hbs`<HyperTableV2::FilteringRenderers::Common::FacetsLoader @handler={{this.handler}} @column={{this.column}} @searchEnabled={{true}} @searchPlaceholder="foobar..." />`
);

assert.dom('.oss-input-container').exists();
assert.dom('.oss-input-container input').hasAttribute('placeholder', 'foobar...');
});

test('facets are fetched with the typed keyword when searching', async function (assert: Assert) {
const handlerSpy = sinon.spy(this.handler);

Expand Down
7 changes: 7 additions & 0 deletions tests/unit/core/handler-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,13 @@ module('Unit | core/handler', function (hooks) {
payload: {
name: 'The Foo Fighters'
},
count: 29
},
{
identifier: 'band:2',
payload: {
name: 'Arctic Monkeys'
},
count: 4
}
],
Expand Down