@sinequa/atomic-angular 1.8.0 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/sinequa-atomic-angular.mjs +75 -92
- package/fesm2022/sinequa-atomic-angular.mjs.map +1 -1
- package/index.d.ts +201 -609
- package/package.json +1 -1
|
@@ -3540,16 +3540,33 @@ class AggregationsService {
|
|
|
3540
3540
|
}
|
|
3541
3541
|
/* aggregations helpers fot the filters components */
|
|
3542
3542
|
getAuthorizedFilters(aggregations, includedFilters = [], excludedFilters = [], homepageOnly = false) {
|
|
3543
|
+
// An explicit list is a deliberate developer choice: it bypasses the `hidden`
|
|
3544
|
+
// admin rule. The rule only applies to the default, config-driven path.
|
|
3545
|
+
const explicit = aggregations !== undefined;
|
|
3543
3546
|
const agg = aggregations || this.appStore.getAuthorizedFilters();
|
|
3544
3547
|
const authorizedFilters = agg
|
|
3545
3548
|
.filter((f) => this.getFilterCriteria()(f)) // filter only the filters present
|
|
3546
3549
|
.filter((f) => !homepageOnly || this.getHomepageFilterCriteria()(f)) // when requested, keep only filters flagged `homepage: true`
|
|
3547
3550
|
.filter((f) => !this.getLeftOnlyFilterCriteria()(f)) // exclude left-only filters (rendered in the left drawer, not the bar)
|
|
3551
|
+
.filter((f) => explicit || !this.getHiddenFilterCriteria()(f)) // exclude admin-hidden filters (default path only)
|
|
3548
3552
|
.filter((f) => !excludedFilters.includes(f.name))
|
|
3549
3553
|
.filter((f) => !includedFilters.length || includedFilters.includes(f.name))
|
|
3550
3554
|
.map((f) => ({ field: f.column, column: f.column, name: f.name })); // field is needed for filters constructions
|
|
3551
3555
|
return authorizedFilters;
|
|
3552
3556
|
}
|
|
3557
|
+
/**
|
|
3558
|
+
* Removes the aggregations flagged `hidden: true` in the `filters` custom JSON
|
|
3559
|
+
* configuration (the administrator does not want them displayed).
|
|
3560
|
+
*
|
|
3561
|
+
* Exposed for consumers that build their own aggregation list without going through
|
|
3562
|
+
* {@link getAuthorizedFilters} (e.g. the aside filters drawer).
|
|
3563
|
+
*
|
|
3564
|
+
* @param aggregations - The aggregations to filter.
|
|
3565
|
+
* @returns The aggregations that are not flagged hidden.
|
|
3566
|
+
*/
|
|
3567
|
+
rejectHidden(aggregations) {
|
|
3568
|
+
return aggregations.filter((agg) => !this.getHiddenFilterCriteria()(agg));
|
|
3569
|
+
}
|
|
3553
3570
|
/**
|
|
3554
3571
|
* Determines whether a custom JSON filter refers to the given aggregation.
|
|
3555
3572
|
*
|
|
@@ -3593,6 +3610,10 @@ class AggregationsService {
|
|
|
3593
3610
|
// `position: 'both'` (and an undefined position) stay in the bar.
|
|
3594
3611
|
return (agg) => this.appStore.filters().some((filter) => filter.position === "left" && this.matchesAggregation(filter, agg));
|
|
3595
3612
|
};
|
|
3613
|
+
getHiddenFilterCriteria = () => {
|
|
3614
|
+
// an aggregation is hidden when a matching filter in the custom JSON has `hidden: true`
|
|
3615
|
+
return (agg) => this.appStore.filters().some((filter) => filter.hidden && this.matchesAggregation(filter, agg));
|
|
3616
|
+
};
|
|
3596
3617
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: AggregationsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
3597
3618
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: AggregationsService, providedIn: "root" });
|
|
3598
3619
|
}
|
|
@@ -15392,28 +15413,55 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
15392
15413
|
class AsideFiltersComponent {
|
|
15393
15414
|
cn = cn;
|
|
15394
15415
|
class = input(...(ngDevMode ? [undefined, { debugName: "class" }] : []));
|
|
15395
|
-
|
|
15416
|
+
/**
|
|
15417
|
+
* Explicit, developer-defined list of aggregations to display.
|
|
15418
|
+
*
|
|
15419
|
+
* Each entry is an aggregation **name** (preferred) or **column** — e.g.
|
|
15420
|
+
* `['Authors', 'Sources', 'Geo']`. Although typed as `string[]`, this is the list of
|
|
15421
|
+
* aggregations to render, not a list of raw column keys.
|
|
15422
|
+
*
|
|
15423
|
+
* When provided, it fully bypasses the JSON `filters` configuration (neither
|
|
15424
|
+
* `position`, `getAuthorized`, nor the admin `hidden` rule are applied): the listed
|
|
15425
|
+
* aggregations are rendered as-is, in the given order, provided they exist in the
|
|
15426
|
+
* {@link AggregationsStore}. When empty (default), the component falls back to the
|
|
15427
|
+
* JSON-driven behavior (`position: 'left' | 'both'`, excluding `hidden` aggregations).
|
|
15428
|
+
*
|
|
15429
|
+
* Resolution tries by `name` first — the canonical, unambiguous identifier, since a
|
|
15430
|
+
* `column` can be shared by several aggregations with distinct names — then falls back
|
|
15431
|
+
* to the first aggregation matching the given column. Prefer passing names.
|
|
15432
|
+
*/
|
|
15433
|
+
aggregations = input([], ...(ngDevMode ? [{ debugName: "aggregations" }] : []));
|
|
15434
|
+
/**
|
|
15435
|
+
* When `true` (default), every section shares the same `id`, producing a native
|
|
15436
|
+
* `<details name>` accordion where a single section is open at a time. When `false`,
|
|
15437
|
+
* each section gets a unique id (based on the aggregation `name`) and expands
|
|
15438
|
+
* independently — closer to a typical SBA v2 "Facets List".
|
|
15439
|
+
*/
|
|
15440
|
+
exclusive = input(true, ...(ngDevMode ? [{ debugName: "exclusive", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
15396
15441
|
appStore = inject(AppStore);
|
|
15442
|
+
aggregationsStore = inject(AggregationsStore);
|
|
15443
|
+
aggregationsService = inject(AggregationsService);
|
|
15397
15444
|
asideFilters = computed(() => {
|
|
15398
|
-
|
|
15445
|
+
const explicit = this.aggregations();
|
|
15446
|
+
// Explicit developer-defined list → render exactly as passed, bypassing the JSON config.
|
|
15447
|
+
if (explicit.length > 0) {
|
|
15448
|
+
return explicit
|
|
15449
|
+
.map((key) => this.aggregationsStore.getAggregation(key, "name") ?? this.aggregationsStore.getAggregation(key, "column"))
|
|
15450
|
+
.filter((agg) => !!agg)
|
|
15451
|
+
.map((agg) => ({ name: agg.name, column: agg.column }));
|
|
15452
|
+
}
|
|
15453
|
+
// Default JSON-driven behavior:
|
|
15454
|
+
// `left` filters live only in the drawer, `both` filters live in the drawer and the bar.
|
|
15455
|
+
// Admin-hidden aggregations are excluded (the rule lives in the service).
|
|
15399
15456
|
const asideFilters = this.appStore.filters().filter((f) => f.position === "left" || f.position === "both");
|
|
15400
|
-
return this.appStore.getAuthorized(asideFilters);
|
|
15457
|
+
return this.aggregationsService.rejectHidden(this.appStore.getAuthorized(asideFilters));
|
|
15401
15458
|
}, ...(ngDevMode ? [{ debugName: "asideFilters" }] : []));
|
|
15402
|
-
/**
|
|
15403
|
-
* Checks if the specified column is a date filter.
|
|
15404
|
-
*
|
|
15405
|
-
* @param column The column name to check.
|
|
15406
|
-
* @returns True if the column is a date filter, false otherwise.
|
|
15407
|
-
*/
|
|
15408
|
-
isDate(column) {
|
|
15409
|
-
return this.appStore.isDateColumn(column);
|
|
15410
|
-
}
|
|
15411
15459
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: AsideFiltersComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
15412
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: AsideFiltersComponent, isStandalone: true, selector: "aside-filters, AsideFilters, asidefilters", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null },
|
|
15460
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: AsideFiltersComponent, isStandalone: true, selector: "aside-filters, AsideFilters, asidefilters", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, aggregations: { classPropertyName: "aggregations", publicName: "aggregations", isSignal: true, isRequired: false, transformFunction: null }, exclusive: { classPropertyName: "exclusive", publicName: "exclusive", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "cn('flex flex-col gap-2 overflow-auto', class())" } }, ngImport: i0, template: `
|
|
15413
15461
|
<div class="flex flex-col gap-2">
|
|
15414
15462
|
@for (agg of asideFilters(); track agg.name) {
|
|
15415
15463
|
<Aggregation
|
|
15416
|
-
id="aside-filters"
|
|
15464
|
+
[id]="exclusive() ? 'aside-filters' : 'aside-filters-' + agg.name"
|
|
15417
15465
|
[name]="agg.name"
|
|
15418
15466
|
[column]="agg.column"
|
|
15419
15467
|
[collapsible]="true"
|
|
@@ -15432,7 +15480,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
15432
15480
|
<div class="flex flex-col gap-2">
|
|
15433
15481
|
@for (agg of asideFilters(); track agg.name) {
|
|
15434
15482
|
<Aggregation
|
|
15435
|
-
id="aside-filters"
|
|
15483
|
+
[id]="exclusive() ? 'aside-filters' : 'aside-filters-' + agg.name"
|
|
15436
15484
|
[name]="agg.name"
|
|
15437
15485
|
[column]="agg.column"
|
|
15438
15486
|
[collapsible]="true"
|
|
@@ -15445,7 +15493,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
15445
15493
|
"[class]": "cn('flex flex-col gap-2 overflow-auto', class())"
|
|
15446
15494
|
}
|
|
15447
15495
|
}]
|
|
15448
|
-
}], propDecorators: { class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }],
|
|
15496
|
+
}], propDecorators: { class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], aggregations: [{ type: i0.Input, args: [{ isSignal: true, alias: "aggregations", required: false }] }], exclusive: [{ type: i0.Input, args: [{ isSignal: true, alias: "exclusive", required: false }] }] } });
|
|
15449
15497
|
|
|
15450
15498
|
class FilterButtonComponent {
|
|
15451
15499
|
name = input(...(ngDevMode ? [undefined, { debugName: "name" }] : []));
|
|
@@ -15656,92 +15704,27 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
15656
15704
|
const FILTERS_BREAKPOINT = new InjectionToken('FILTERS_BREAKPOINT', { factory: () => 5 });
|
|
15657
15705
|
|
|
15658
15706
|
class MoreComponent {
|
|
15659
|
-
cn = cn;
|
|
15660
15707
|
count = input(2, ...(ngDevMode ? [{ debugName: "count" }] : []));
|
|
15661
15708
|
includedFilters = input([], ...(ngDevMode ? [{ debugName: "includedFilters" }] : []));
|
|
15662
15709
|
excludedFilters = input([], ...(ngDevMode ? [{ debugName: "excludedFilters" }] : []));
|
|
15663
15710
|
aggregations = input(...(ngDevMode ? [undefined, { debugName: "aggregations" }] : []));
|
|
15664
15711
|
homepage = input(false, ...(ngDevMode ? [{ debugName: "homepage", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
15665
|
-
appStore = inject(AppStore);
|
|
15666
|
-
aggregationsStore = inject(AggregationsStore);
|
|
15667
|
-
queryParamsStore = inject(QueryParamsStore);
|
|
15668
15712
|
aggregationsService = inject(AggregationsService);
|
|
15669
15713
|
/**
|
|
15670
|
-
*
|
|
15714
|
+
* The overflow filters rendered as accordions: the authorized filters beyond the
|
|
15715
|
+
* first `count` (which are already shown in the bar).
|
|
15671
15716
|
*
|
|
15672
15717
|
* @remarks
|
|
15673
|
-
*
|
|
15674
|
-
*
|
|
15675
|
-
*
|
|
15718
|
+
* Pure display wiring — authorization (and the admin `hidden` rule) is handled by
|
|
15719
|
+
* {@link AggregationsService.getAuthorizedFilters}; `toSpliced` just drops the
|
|
15720
|
+
* filters already shown in the bar.
|
|
15676
15721
|
*/
|
|
15677
|
-
filters =
|
|
15678
|
-
|
|
15679
|
-
|
|
15680
|
-
* Filters out any filters where the `hidden` property is set to true.
|
|
15681
|
-
*
|
|
15682
|
-
* @returns An array of filters that are not hidden
|
|
15683
|
-
*/
|
|
15684
|
-
visibleFilters = computed(() => {
|
|
15685
|
-
const filters = this.filters().filter((f) => !f.hidden);
|
|
15686
|
-
return filters;
|
|
15687
|
-
}, ...(ngDevMode ? [{ debugName: "visibleFilters" }] : []));
|
|
15688
|
-
constructor() {
|
|
15689
|
-
effect(() => {
|
|
15690
|
-
const count = this.count();
|
|
15691
|
-
const authorizedFilters = this.aggregationsService
|
|
15692
|
-
.getAuthorizedFilters(this.aggregations(), this.includedFilters(), this.excludedFilters(), this.homepage())
|
|
15693
|
-
.toSpliced(0, count);
|
|
15694
|
-
const f = authorizedFilters.map((agg) => {
|
|
15695
|
-
const { icon = "far fa-list", hidden = false } = this.appStore.getAggregationCustomization(agg.column, agg.name) || {};
|
|
15696
|
-
return {
|
|
15697
|
-
name: agg.name,
|
|
15698
|
-
column: agg.column,
|
|
15699
|
-
icon,
|
|
15700
|
-
count: 0,
|
|
15701
|
-
isTree: false,
|
|
15702
|
-
disabled: false,
|
|
15703
|
-
hidden
|
|
15704
|
-
};
|
|
15705
|
-
});
|
|
15706
|
-
this.filters.set(f);
|
|
15707
|
-
this.updateFilters();
|
|
15708
|
-
});
|
|
15709
|
-
}
|
|
15710
|
-
clearFilter(field) {
|
|
15711
|
-
this.queryParamsStore.removeFilter(field);
|
|
15712
|
-
}
|
|
15713
|
-
updateFilters() {
|
|
15714
|
-
this.filters.update((filters) => {
|
|
15715
|
-
return filters.map((filter) => {
|
|
15716
|
-
const agg = this.aggregationsStore.getAggregation(filter.name);
|
|
15717
|
-
const f = this.queryParamsStore.getFilter({ name: agg?.name, field: agg?.column });
|
|
15718
|
-
const count = f?.count || 0;
|
|
15719
|
-
const { display = agg?.isTree ? undefined : filter.display } = this.appStore.getAggregationCustomization(filter.column) || {};
|
|
15720
|
-
return {
|
|
15721
|
-
...filter,
|
|
15722
|
-
name: agg?.name || filter.name,
|
|
15723
|
-
display,
|
|
15724
|
-
isTree: agg?.isTree || false,
|
|
15725
|
-
count,
|
|
15726
|
-
disabled: !!(!agg?.items || agg.items?.length === 0) // Disable if no items
|
|
15727
|
-
};
|
|
15728
|
-
});
|
|
15729
|
-
});
|
|
15730
|
-
}
|
|
15731
|
-
/**
|
|
15732
|
-
* Checks whether there are active filters for the current aggregation column.
|
|
15733
|
-
*
|
|
15734
|
-
* if True, the clear button is shown.
|
|
15735
|
-
*
|
|
15736
|
-
* @returns {boolean} `true` if the filter count for the aggregation column is greater than 0, otherwise `false`.
|
|
15737
|
-
*/
|
|
15738
|
-
hasFilters(aggregation) {
|
|
15739
|
-
const { count = 0 } = this.queryParamsStore.getFilter({ field: aggregation.column, name: aggregation.name }) || {};
|
|
15740
|
-
return count > 0;
|
|
15741
|
-
}
|
|
15722
|
+
filters = computed(() => this.aggregationsService
|
|
15723
|
+
.getAuthorizedFilters(this.aggregations(), this.includedFilters(), this.excludedFilters(), this.homepage())
|
|
15724
|
+
.toSpliced(0, this.count()), ...(ngDevMode ? [{ debugName: "filters" }] : []));
|
|
15742
15725
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: MoreComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
15743
15726
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: MoreComponent, isStandalone: true, selector: "more, More", inputs: { count: { classPropertyName: "count", publicName: "count", isSignal: true, isRequired: false, transformFunction: null }, includedFilters: { classPropertyName: "includedFilters", publicName: "includedFilters", isSignal: true, isRequired: false, transformFunction: null }, excludedFilters: { classPropertyName: "excludedFilters", publicName: "excludedFilters", isSignal: true, isRequired: false, transformFunction: null }, aggregations: { classPropertyName: "aggregations", publicName: "aggregations", isSignal: true, isRequired: false, transformFunction: null }, homepage: { classPropertyName: "homepage", publicName: "homepage", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "divide-y divide-muted-foreground/18" }, ngImport: i0, template: `
|
|
15744
|
-
@for (filter of
|
|
15727
|
+
@for (filter of filters(); track $index) {
|
|
15745
15728
|
<Aggregation
|
|
15746
15729
|
class="w-60 max-w-80 px-1 [--height:15lh]"
|
|
15747
15730
|
id="more-filters"
|
|
@@ -15757,7 +15740,7 @@ class MoreComponent {
|
|
|
15757
15740
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: MoreComponent, decorators: [{
|
|
15758
15741
|
type: Component,
|
|
15759
15742
|
args: [{ selector: "more, More", standalone: true, imports: [AggregationComponent, TranslocoPipe], template: `
|
|
15760
|
-
@for (filter of
|
|
15743
|
+
@for (filter of filters(); track $index) {
|
|
15761
15744
|
<Aggregation
|
|
15762
15745
|
class="w-60 max-w-80 px-1 [--height:15lh]"
|
|
15763
15746
|
id="more-filters"
|
|
@@ -15771,7 +15754,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
15771
15754
|
`, host: {
|
|
15772
15755
|
class: "divide-y divide-muted-foreground/18"
|
|
15773
15756
|
}, styles: [":host{scrollbar-width:none}\n"] }]
|
|
15774
|
-
}],
|
|
15757
|
+
}], propDecorators: { count: [{ type: i0.Input, args: [{ isSignal: true, alias: "count", required: false }] }], includedFilters: [{ type: i0.Input, args: [{ isSignal: true, alias: "includedFilters", required: false }] }], excludedFilters: [{ type: i0.Input, args: [{ isSignal: true, alias: "excludedFilters", required: false }] }], aggregations: [{ type: i0.Input, args: [{ isSignal: true, alias: "aggregations", required: false }] }], homepage: [{ type: i0.Input, args: [{ isSignal: true, alias: "homepage", required: false }] }] } });
|
|
15775
15758
|
|
|
15776
15759
|
class MoreButtonComponent {
|
|
15777
15760
|
appStore = inject(AppStore);
|