@sinequa/atomic-angular 0.4.37 → 0.4.45
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.
|
@@ -812,14 +812,19 @@ class OperatorPipe {
|
|
|
812
812
|
return `> ${new Intl.DateTimeFormat(locale).format(new Date(start))} ≤ ${new Intl.DateTimeFormat(locale).format(new Date(end))}`;
|
|
813
813
|
}
|
|
814
814
|
if (filter?.operator === 'and') {
|
|
815
|
-
const
|
|
816
|
-
const
|
|
817
|
-
|
|
818
|
-
|
|
815
|
+
const filters = filter.filters;
|
|
816
|
+
const from = filters?.find((f) => f.operator === 'gte')?.value;
|
|
817
|
+
const to = filters?.find((f) => f.operator === 'lte')?.value;
|
|
818
|
+
if (from && to) {
|
|
819
|
+
return `≥ ${new Intl.DateTimeFormat(locale).format(new Date(from))} ≤ ${new Intl.DateTimeFormat(locale).format(new Date(to))}`;
|
|
819
820
|
}
|
|
820
|
-
|
|
821
|
-
return new Intl.DateTimeFormat(locale).format(
|
|
821
|
+
if (from) {
|
|
822
|
+
return `≥ ${new Intl.DateTimeFormat(locale).format(new Date(from))}`;
|
|
823
|
+
}
|
|
824
|
+
if (to) {
|
|
825
|
+
return `≤ ${new Intl.DateTimeFormat(locale).format(new Date(to))}`;
|
|
822
826
|
}
|
|
827
|
+
return filter?.display ?? filter?.value ?? '';
|
|
823
828
|
}
|
|
824
829
|
const date = new Date(filter?.value || '');
|
|
825
830
|
if (isNaN(date.getTime())) {
|
|
@@ -2814,13 +2819,34 @@ function withUserSettingsFeatures() {
|
|
|
2814
2819
|
alerts: [],
|
|
2815
2820
|
assistants: {},
|
|
2816
2821
|
language: undefined,
|
|
2817
|
-
collapseAssistant: undefined
|
|
2822
|
+
collapseAssistant: undefined,
|
|
2823
|
+
agents: { isDebugMode: false }
|
|
2818
2824
|
});
|
|
2819
2825
|
}
|
|
2820
2826
|
})));
|
|
2821
2827
|
}
|
|
2822
2828
|
|
|
2823
|
-
|
|
2829
|
+
function withAgentsFeatures() {
|
|
2830
|
+
return signalStoreFeature(withState({
|
|
2831
|
+
agents: { isDebugMode: false }
|
|
2832
|
+
}), withComputed((store) => ({
|
|
2833
|
+
isDebugMode: computed(() => store.agents()?.isDebugMode ?? false)
|
|
2834
|
+
})), withMethods((store) => ({
|
|
2835
|
+
async setDebugMode(value) {
|
|
2836
|
+
try {
|
|
2837
|
+
await patchUserSettings({ agents: { ...store.agents(), isDebugMode: value } }, { type: 'Agent_DebugMode_Toggle' });
|
|
2838
|
+
patchState(store, (state) => ({
|
|
2839
|
+
agents: { ...state.agents, isDebugMode: value }
|
|
2840
|
+
}));
|
|
2841
|
+
}
|
|
2842
|
+
catch (e) {
|
|
2843
|
+
error('setDebugMode failed', e);
|
|
2844
|
+
}
|
|
2845
|
+
}
|
|
2846
|
+
})));
|
|
2847
|
+
}
|
|
2848
|
+
|
|
2849
|
+
const UserSettingsStore = signalStore({ providedIn: 'root' }, withDevtools('UserSettings'), withBookmarkFeatures(), withRecentSearchesFeatures(), withSavedSearchesFeatures(), withBasketsFeatures(), withAssistantFeatures(), withUserSettingsFeatures(), withAlertsFeatures(), withAgentsFeatures(), withDarkModeFeatures());
|
|
2824
2850
|
|
|
2825
2851
|
class QueryService {
|
|
2826
2852
|
http = inject(HttpClient);
|
|
@@ -3656,18 +3682,26 @@ class ApplicationService {
|
|
|
3656
3682
|
}
|
|
3657
3683
|
const { light, dark, alt } = general.logo || {};
|
|
3658
3684
|
document.documentElement.style.setProperty("--logo-alt-text", `'${alt || general.name}'`);
|
|
3685
|
+
// light mode logo configuration
|
|
3659
3686
|
if (light?.small) {
|
|
3660
3687
|
document.documentElement.style.setProperty("--logo-light-small", `url('${light.small}')`);
|
|
3661
3688
|
}
|
|
3662
3689
|
if (light?.large) {
|
|
3663
3690
|
document.documentElement.style.setProperty("--logo-light-large", `url('${light.large}')`);
|
|
3664
3691
|
}
|
|
3692
|
+
if (light?.sidebar) {
|
|
3693
|
+
document.documentElement.style.setProperty("--logo-light-sidebar", `url('${light.sidebar}')`);
|
|
3694
|
+
}
|
|
3695
|
+
// dark mode logo configuration
|
|
3665
3696
|
if (dark?.small) {
|
|
3666
3697
|
document.documentElement.style.setProperty("--logo-dark-small", `url('${dark.small}')`);
|
|
3667
3698
|
}
|
|
3668
3699
|
if (dark?.large) {
|
|
3669
3700
|
document.documentElement.style.setProperty("--logo-dark-large", `url('${dark.large}')`);
|
|
3670
3701
|
}
|
|
3702
|
+
if (dark?.sidebar) {
|
|
3703
|
+
document.documentElement.style.setProperty("--logo-dark-sidebar", `url('${dark.sidebar}')`);
|
|
3704
|
+
}
|
|
3671
3705
|
}
|
|
3672
3706
|
/**
|
|
3673
3707
|
* Sets the document title with optional application name prefix.
|
|
@@ -5397,10 +5431,13 @@ class MissingTermsComponent {
|
|
|
5397
5431
|
return this.article()
|
|
5398
5432
|
.termspresence?.filter(tp => tp.presence === 'missing')
|
|
5399
5433
|
.map(tp => {
|
|
5400
|
-
const
|
|
5434
|
+
const bracketMatch = tp.term.match(/^\[(.+)\]$/);
|
|
5435
|
+
const cleanTerm = bracketMatch ? bracketMatch[1] : tp.term;
|
|
5436
|
+
const escapedTerm = cleanTerm.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
5437
|
+
const text = (query.text || '').replace(new RegExp(`\\b${escapedTerm}\\b`, 'gi'), '').replace(/\s+/g, ' ').trim();
|
|
5401
5438
|
return {
|
|
5402
|
-
value:
|
|
5403
|
-
queryParams: { q: `${text} +[${
|
|
5439
|
+
value: cleanTerm,
|
|
5440
|
+
queryParams: { q: `${text} +[${cleanTerm}]` }
|
|
5404
5441
|
};
|
|
5405
5442
|
});
|
|
5406
5443
|
}, ...(ngDevMode ? [{ debugName: "missingTerms" }] : []));
|
|
@@ -5532,7 +5569,7 @@ class CollectionsDialog {
|
|
|
5532
5569
|
{{ collection.name }}
|
|
5533
5570
|
</li>
|
|
5534
5571
|
} @empty {
|
|
5535
|
-
<li class="py-4 text-center text-neutral-500">
|
|
5572
|
+
<li class="list-none py-4 text-center text-neutral-500">
|
|
5536
5573
|
{{ 'collections.noCollections' | transloco }}
|
|
5537
5574
|
</li>
|
|
5538
5575
|
}
|
|
@@ -5616,7 +5653,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
5616
5653
|
{{ collection.name }}
|
|
5617
5654
|
</li>
|
|
5618
5655
|
} @empty {
|
|
5619
|
-
<li class="py-4 text-center text-neutral-500">
|
|
5656
|
+
<li class="list-none py-4 text-center text-neutral-500">
|
|
5620
5657
|
{{ 'collections.noCollections' | transloco }}
|
|
5621
5658
|
</li>
|
|
5622
5659
|
}
|
|
@@ -7147,6 +7184,7 @@ class NavbarTabsComponent {
|
|
|
7147
7184
|
[noTruncate]="noTruncate()"
|
|
7148
7185
|
[style.--tab-min-width]="minTabWidth()"
|
|
7149
7186
|
[attr.aria-selected]="this.currentPath() === tab.path"
|
|
7187
|
+
[attr.disabled]="showCount() && tab.count === 0 ? '' : null"
|
|
7150
7188
|
[active]="this.currentPath() === tab.path"
|
|
7151
7189
|
[routerLink]="[tab.routerLink]"
|
|
7152
7190
|
[queryParams]="{ n: tab.queryName, q: searchText(), t: tab.wsQueryTab, f: undefined, sort: undefined, id: undefined, page: undefined }"
|
|
@@ -7239,6 +7277,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
7239
7277
|
[noTruncate]="noTruncate()"
|
|
7240
7278
|
[style.--tab-min-width]="minTabWidth()"
|
|
7241
7279
|
[attr.aria-selected]="this.currentPath() === tab.path"
|
|
7280
|
+
[attr.disabled]="showCount() && tab.count === 0 ? '' : null"
|
|
7242
7281
|
[active]="this.currentPath() === tab.path"
|
|
7243
7282
|
[routerLink]="[tab.routerLink]"
|
|
7244
7283
|
[queryParams]="{ n: tab.queryName, q: searchText(), t: tab.wsQueryTab, f: undefined, sort: undefined, id: undefined, page: undefined }"
|
|
@@ -8486,6 +8525,7 @@ class AggregationListComponent {
|
|
|
8486
8525
|
aggregationsService = inject(AggregationsService);
|
|
8487
8526
|
el = inject(ElementRef);
|
|
8488
8527
|
injector = inject(Injector);
|
|
8528
|
+
destroyRef = inject(DestroyRef);
|
|
8489
8529
|
class = input("", ...(ngDevMode ? [{ debugName: "class" }] : []));
|
|
8490
8530
|
/**
|
|
8491
8531
|
* The name of the <details> element. When you provide the same id, the component work as an accordion
|
|
@@ -8653,6 +8693,15 @@ class AggregationListComponent {
|
|
|
8653
8693
|
const suggests = (await withFetch(() => fetchSuggestField(this.normalizedSearchText(), [this.aggregation()?.column || ""], query), this.injector)) || [];
|
|
8654
8694
|
this.suggests.set(suggests);
|
|
8655
8695
|
});
|
|
8696
|
+
this.destroyRef.onDestroy(() => {
|
|
8697
|
+
// If the popover is closed with unapplied selections, reset $selected to undefined
|
|
8698
|
+
// so that processAggregation can recompute it from active filters on next open
|
|
8699
|
+
if (this.selection()) {
|
|
8700
|
+
this.aggregation()?.items?.forEach(item => {
|
|
8701
|
+
item.$selected = undefined;
|
|
8702
|
+
});
|
|
8703
|
+
}
|
|
8704
|
+
});
|
|
8656
8705
|
}
|
|
8657
8706
|
/**
|
|
8658
8707
|
* Clears the current filter for the aggregation column.
|
|
@@ -8761,8 +8810,10 @@ class AggregationListComponent {
|
|
|
8761
8810
|
* If the item is deselected, the selection count is decremented by 1.
|
|
8762
8811
|
*/
|
|
8763
8812
|
select() {
|
|
8764
|
-
this.
|
|
8765
|
-
this.
|
|
8813
|
+
const selectedItems = this.items().filter(item => item.$selected);
|
|
8814
|
+
this.onSelect.emit(selectedItems);
|
|
8815
|
+
// Keep apply visible if items are selected, or if active filters exist (user may be deselecting to clear)
|
|
8816
|
+
this.selection.set(selectedItems.length > 0 || this.hasFilters());
|
|
8766
8817
|
}
|
|
8767
8818
|
/**
|
|
8768
8819
|
* Updates the collapsed status on header click if the component is collapsible.
|
|
@@ -8882,12 +8933,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
8882
8933
|
}], ctorParameters: () => [], propDecorators: { scrollElement: [{ type: i0.ViewChild, args: ["scrollElement", { isSignal: true }] }], searchInput: [{ type: i0.ViewChild, args: ["searchInput", { isSignal: true }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: true }] }], column: [{ type: i0.Input, args: [{ isSignal: true, alias: "column", required: true }] }], onSelect: [{ type: i0.Output, args: ["onSelect"] }], onApply: [{ type: i0.Output, args: ["onApply"] }], onClear: [{ type: i0.Output, args: ["onClear"] }], collapsible: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsible", required: false }] }], collapsed: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsed", required: false }] }], searchable: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchable", required: false }] }], showFiltersCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "showFiltersCount", required: false }] }], searchText: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchText", required: false }] }, { type: i0.Output, args: ["searchTextChange"] }] } });
|
|
8883
8934
|
|
|
8884
8935
|
class AggregationDateComponent extends AggregationListComponent {
|
|
8885
|
-
destroyRef;
|
|
8886
8936
|
dateRangeDialog = viewChild(AggregationDateRangeDialogComponent, ...(ngDevMode ? [{ debugName: "dateRangeDialog" }] : []));
|
|
8887
8937
|
title = input({ label: "Date", icon: "far fa-calendar-day" }, ...(ngDevMode ? [{ debugName: "title" }] : []));
|
|
8888
8938
|
displayEmptyDistributionIntervals = input(false, ...(ngDevMode ? [{ debugName: "displayEmptyDistributionIntervals" }] : []));
|
|
8889
8939
|
allowCustomRange = inject(FILTER_DATE_ALLOW_CUSTOM_RANGE);
|
|
8890
8940
|
transloco = inject(TranslocoService);
|
|
8941
|
+
name = input(null, ...(ngDevMode ? [{ debugName: "name" }] : []));
|
|
8891
8942
|
dateOptions = computed(() => translateAggregationToDateOptions(this.aggregation(), this.displayEmptyDistributionIntervals()), ...(ngDevMode ? [{ debugName: "dateOptions" }] : []));
|
|
8892
8943
|
form = new FormGroup({
|
|
8893
8944
|
option: new FormControl(null),
|
|
@@ -8900,26 +8951,28 @@ class AggregationDateComponent extends AggregationListComponent {
|
|
|
8900
8951
|
lang = signal(this.transloco.getActiveLang(), ...(ngDevMode ? [{ debugName: "lang" }] : []));
|
|
8901
8952
|
validSelection = signal(false, ...(ngDevMode ? [{ debugName: "validSelection" }] : []));
|
|
8902
8953
|
formValue = toSignal(this.form.valueChanges, { initialValue: this.form.value });
|
|
8903
|
-
|
|
8904
|
-
const
|
|
8905
|
-
|
|
8906
|
-
|
|
8907
|
-
|
|
8908
|
-
const
|
|
8909
|
-
return
|
|
8910
|
-
}, ...(ngDevMode ? [{ debugName: "
|
|
8911
|
-
constructor(
|
|
8954
|
+
customRangeFrom = computed(() => {
|
|
8955
|
+
const from = this.formValue().customRange?.from;
|
|
8956
|
+
return from ? new Date(from).toLocaleDateString(this.lang()) : "";
|
|
8957
|
+
}, ...(ngDevMode ? [{ debugName: "customRangeFrom" }] : []));
|
|
8958
|
+
customRangeTo = computed(() => {
|
|
8959
|
+
const to = this.formValue().customRange?.to;
|
|
8960
|
+
return to ? new Date(to).toLocaleDateString(this.lang()) : "";
|
|
8961
|
+
}, ...(ngDevMode ? [{ debugName: "customRangeTo" }] : []));
|
|
8962
|
+
constructor() {
|
|
8912
8963
|
super();
|
|
8913
|
-
this.destroyRef = destroyRef;
|
|
8914
8964
|
this.transloco.langChanges$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((lang) => {
|
|
8915
8965
|
this.lang.set(lang);
|
|
8916
8966
|
});
|
|
8917
8967
|
// apply current date filter from queryParamsStore
|
|
8918
8968
|
effect(() => {
|
|
8919
|
-
this.
|
|
8920
|
-
|
|
8921
|
-
|
|
8922
|
-
|
|
8969
|
+
const agg = this.aggregation();
|
|
8970
|
+
if (agg) {
|
|
8971
|
+
this.updateForm(this.queryParamsStore.getFilter({
|
|
8972
|
+
field: agg.column,
|
|
8973
|
+
name: agg.name
|
|
8974
|
+
}));
|
|
8975
|
+
}
|
|
8923
8976
|
});
|
|
8924
8977
|
this.form.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((changes) => {
|
|
8925
8978
|
this.validSelection.set(!!changes.option &&
|
|
@@ -8937,6 +8990,9 @@ class AggregationDateComponent extends AggregationListComponent {
|
|
|
8937
8990
|
}
|
|
8938
8991
|
return null;
|
|
8939
8992
|
}, ...(ngDevMode ? [{ debugName: "aggregation" }] : []));
|
|
8993
|
+
select() {
|
|
8994
|
+
this.selection.set(true);
|
|
8995
|
+
}
|
|
8940
8996
|
apply() {
|
|
8941
8997
|
try {
|
|
8942
8998
|
const filter = this.getFormValueFilter();
|
|
@@ -8965,6 +9021,10 @@ class AggregationDateComponent extends AggregationListComponent {
|
|
|
8965
9021
|
this.onClear.emit();
|
|
8966
9022
|
}
|
|
8967
9023
|
}
|
|
9024
|
+
selectAndOpenDialog() {
|
|
9025
|
+
this.select();
|
|
9026
|
+
this.dateRangeDialog()?.open();
|
|
9027
|
+
}
|
|
8968
9028
|
onRangeSelected(range) {
|
|
8969
9029
|
this.form.patchValue({
|
|
8970
9030
|
option: "custom-range",
|
|
@@ -8993,6 +9053,12 @@ class AggregationDateComponent extends AggregationListComponent {
|
|
|
8993
9053
|
from = filter.start;
|
|
8994
9054
|
to = filter.end;
|
|
8995
9055
|
break;
|
|
9056
|
+
case "and": {
|
|
9057
|
+
const filters = filter.filters;
|
|
9058
|
+
from = filters?.find((f) => f.operator === "gte")?.value ?? null;
|
|
9059
|
+
to = filters?.find((f) => f.operator === "lte")?.value ?? null;
|
|
9060
|
+
break;
|
|
9061
|
+
}
|
|
8996
9062
|
}
|
|
8997
9063
|
}
|
|
8998
9064
|
const formValue = {
|
|
@@ -9013,13 +9079,15 @@ class AggregationDateComponent extends AggregationListComponent {
|
|
|
9013
9079
|
if (value.option !== "custom-range") {
|
|
9014
9080
|
const dateOption = this.dateOptions().find((option) => option.display === value.option);
|
|
9015
9081
|
const aggregation = this.aggregation();
|
|
9016
|
-
|
|
9082
|
+
const name = aggregation?.name ?? this.name() ?? undefined;
|
|
9083
|
+
const column = aggregation?.column ?? this.column() ?? undefined;
|
|
9084
|
+
if (!name && !column) {
|
|
9017
9085
|
throw new Error("filters.aggregationNotFound");
|
|
9018
9086
|
}
|
|
9019
9087
|
return {
|
|
9020
|
-
name:
|
|
9088
|
+
name: name,
|
|
9021
9089
|
operator: dateOption?.operator || "eq",
|
|
9022
|
-
field:
|
|
9090
|
+
field: column,
|
|
9023
9091
|
display: dateOption?.display ?? "",
|
|
9024
9092
|
filters: dateOption?.filters,
|
|
9025
9093
|
value: dateOption?.value
|
|
@@ -9030,18 +9098,30 @@ class AggregationDateComponent extends AggregationListComponent {
|
|
|
9030
9098
|
// if from is null, operator is lte
|
|
9031
9099
|
// if both are not null, operator is between
|
|
9032
9100
|
const aggregation = this.aggregation();
|
|
9033
|
-
|
|
9101
|
+
const name = aggregation?.name ?? this.name() ?? undefined;
|
|
9102
|
+
const column = aggregation?.column ?? this.column() ?? undefined;
|
|
9103
|
+
if (!name && !column) {
|
|
9034
9104
|
throw new Error("filters.aggregationNotFound");
|
|
9035
9105
|
}
|
|
9036
9106
|
const filter = {
|
|
9037
|
-
name:
|
|
9038
|
-
field:
|
|
9107
|
+
name: name,
|
|
9108
|
+
field: column,
|
|
9039
9109
|
display: value.option
|
|
9040
9110
|
};
|
|
9041
9111
|
if (value.customRange.from && value.customRange.to) {
|
|
9042
|
-
filter.operator = "
|
|
9043
|
-
filter.
|
|
9044
|
-
|
|
9112
|
+
filter.operator = "and";
|
|
9113
|
+
filter.filters = [
|
|
9114
|
+
{
|
|
9115
|
+
field: column,
|
|
9116
|
+
operator: "gte",
|
|
9117
|
+
value: value.customRange.from,
|
|
9118
|
+
},
|
|
9119
|
+
{
|
|
9120
|
+
field: column,
|
|
9121
|
+
operator: "lte",
|
|
9122
|
+
value: value.customRange.to
|
|
9123
|
+
}
|
|
9124
|
+
];
|
|
9045
9125
|
}
|
|
9046
9126
|
else if (value.customRange.from) {
|
|
9047
9127
|
filter.operator = "gte";
|
|
@@ -9058,12 +9138,13 @@ class AggregationDateComponent extends AggregationListComponent {
|
|
|
9058
9138
|
}
|
|
9059
9139
|
throw new Error("filters.filterInvalid");
|
|
9060
9140
|
}
|
|
9061
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: AggregationDateComponent, deps: [
|
|
9062
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.18", type: AggregationDateComponent, isStandalone: true, selector: "aggregation-date, AggregationDate, aggregationdate", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, displayEmptyDistributionIntervals: { classPropertyName: "displayEmptyDistributionIntervals", publicName: "displayEmptyDistributionIntervals", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "@container" }, providers: [provideTranslocoScope("filters")], viewQueries: [{ propertyName: "dateRangeDialog", first: true, predicate: AggregationDateRangeDialogComponent, descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<details [attr.open]=\"expanded()\" [attr.name]=\"id()\" class=\"group space-y-2\">\r\n <summary\r\n [class.cursor-pointer]=\"collapsible()\"\r\n class=\"m-0 flex h-8 w-full items-center pl-1 font-semibold select-none\"\r\n (click)=\"onHeaderClick($event)\">\r\n <ng-content select=\"label\">\r\n @if (aggregation()?.icon) {\r\n <i class=\"fa-fw {{ aggregation()?.icon }} mr-1\" aria-hidden=\"true\"></i>\r\n }\r\n <span class=\"grow\">{{\r\n aggregation()?.display | syslang | transloco\r\n }}</span>\r\n </ng-content>\r\n\r\n @if (hasFilters()) {\r\n <button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n [attr.title]=\"'filters.clearFilters' | transloco\"\r\n [attr.aria-label]=\"'filters.clearFilters' | transloco\"\r\n (click)=\"clear()\"\r\n (keydown.enter)=\"clear()\">\r\n <i class=\"fa-fw far fa-filter-circle-xmark\" aria-hidden=\"true\"></i>\r\n <span class=\"sr-only\">{{ \"filters.clearFilters\" | transloco }}</span>\r\n </button>\r\n }\r\n\r\n @if (selection() && validSelection()) {\r\n <button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n [attr.title]=\"'filters.applyFilters' | transloco\"\r\n [attr.aria-label]=\"'filters.applyFilters' | transloco\"\r\n (click)=\"apply()\"\r\n (keydown.enter)=\"apply()\">\r\n <i class=\"fa-fw far fa-filter\" aria-hidden=\"true\"></i>\r\n <span class=\"sr-only\">{{ \"filters.applyFilters\" | transloco }}</span>\r\n </button>\r\n }\r\n @if (collapsible()) {\r\n <button\r\n variant=\"none\"\r\n title=\"Open/Close\"\r\n class=\"cursor-pointer [&_svg]:transition-transform [&_svg]:duration-150 group-open:[&_svg]:rotate-90\">\r\n <chevronright />\r\n </button>\r\n }\r\n </summary>\r\n\r\n <!-- content wrapper -->\r\n <form [formGroup]=\"form\">\r\n <ul\r\n class=\"scrollbar-thin flex max-h-[calc(var(--height,100%)-100px)] snap-y snap-start flex-col gap-1 overflow-auto pt-2\"\r\n role=\"list\">\r\n @for (option of dateOptions(); track $index) {\r\n <li\r\n role=\"listitem\"\r\n tabindex=\"0\"\r\n (click)=\"radio.click()\"\r\n [attr.aria-label]=\"option.display | syslang | transloco\"\r\n [class]=\"\r\n cn(\r\n 'flex p-0 px-2 leading-7',\r\n form.get('option')?.value === option.display && 'bg-accent',\r\n option.hidden && 'hidden',\r\n option.disabled && 'disabled pointer-events-none text-neutral-300'\r\n )\r\n \"\r\n [attr.aria-hidden]=\"option.disabled\">\r\n <input\r\n #radio\r\n type=\"radio\"\r\n formControlName=\"option\"\r\n id=\"date-filter-{{ option.display }}\"\r\n [attr.disabled]=\"option.disabled ? true : null\"\r\n [attr.aria-disabled]=\"option.disabled\"\r\n (click)=\"select()\"\r\n value=\"{{ option.display }}\" />\r\n\r\n <label\r\n for=\"date-filter-{{ option.display }}\"\r\n class=\"grow cursor-pointer p-1\">\r\n {{ option.display | syslang | transloco }}\r\n </label>\r\n </li>\r\n }\r\n\r\n @if (allowCustomRange) {\r\n <li\r\n role=\"listitem\"\r\n aria-label=\"open date range picker\"\r\n class=\"flex px-2 leading-7\"\r\n [class.select]=\"form.get('option')?.value === 'custom-range'\">\r\n <input\r\n type=\"radio\"\r\n formControlName=\"option\"\r\n id=\"date-filter-range-dialog\"\r\n value=\"custom-range\"\r\n (click)=\"select()\" />\r\n
|
|
9141
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: AggregationDateComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
9142
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.18", type: AggregationDateComponent, isStandalone: true, selector: "aggregation-date, AggregationDate, aggregationdate", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, displayEmptyDistributionIntervals: { classPropertyName: "displayEmptyDistributionIntervals", publicName: "displayEmptyDistributionIntervals", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "@container" }, providers: [provideTranslocoScope("filters")], viewQueries: [{ propertyName: "dateRangeDialog", first: true, predicate: AggregationDateRangeDialogComponent, descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<details [attr.open]=\"expanded()\" [attr.name]=\"id()\" class=\"group space-y-2\">\r\n <summary\r\n [class.cursor-pointer]=\"collapsible()\"\r\n class=\"m-0 flex h-8 w-full items-center pl-1 font-semibold select-none\"\r\n (click)=\"onHeaderClick($event)\">\r\n <ng-content select=\"label\">\r\n @if (aggregation()?.icon) {\r\n <i class=\"fa-fw {{ aggregation()?.icon }} mr-1\" aria-hidden=\"true\"></i>\r\n }\r\n <span class=\"grow\">{{\r\n aggregation()?.display | syslang | transloco\r\n }}</span>\r\n </ng-content>\r\n\r\n @if (hasFilters()) {\r\n <button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n [attr.title]=\"'filters.clearFilters' | transloco\"\r\n [attr.aria-label]=\"'filters.clearFilters' | transloco\"\r\n (click)=\"clear()\"\r\n (keydown.enter)=\"clear()\">\r\n <i class=\"fa-fw far fa-filter-circle-xmark\" aria-hidden=\"true\"></i>\r\n <span class=\"sr-only\">{{ \"filters.clearFilters\" | transloco }}</span>\r\n </button>\r\n }\r\n\r\n @if (selection() && validSelection()) {\r\n <button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n [attr.title]=\"'filters.applyFilters' | transloco\"\r\n [attr.aria-label]=\"'filters.applyFilters' | transloco\"\r\n (click)=\"apply()\"\r\n (keydown.enter)=\"apply()\">\r\n <i class=\"fa-fw far fa-filter\" aria-hidden=\"true\"></i>\r\n <span class=\"sr-only\">{{ \"filters.applyFilters\" | transloco }}</span>\r\n </button>\r\n }\r\n @if (collapsible()) {\r\n <button\r\n variant=\"none\"\r\n title=\"Open/Close\"\r\n class=\"cursor-pointer [&_svg]:transition-transform [&_svg]:duration-150 group-open:[&_svg]:rotate-90\">\r\n <chevronright />\r\n </button>\r\n }\r\n </summary>\r\n\r\n <!-- content wrapper -->\r\n <form [formGroup]=\"form\">\r\n <ul\r\n class=\"scrollbar-thin flex max-h-[calc(var(--height,100%)-100px)] snap-y snap-start flex-col gap-1 overflow-auto pt-2\"\r\n role=\"list\">\r\n @for (option of dateOptions(); track $index) {\r\n <li\r\n role=\"listitem\"\r\n tabindex=\"0\"\r\n (click)=\"radio.click()\"\r\n [attr.aria-label]=\"option.display | syslang | transloco\"\r\n [class]=\"\r\n cn(\r\n 'flex p-0 px-2 leading-7',\r\n form.get('option')?.value === option.display && 'bg-accent',\r\n option.hidden && 'hidden',\r\n option.disabled && 'disabled pointer-events-none text-neutral-300'\r\n )\r\n \"\r\n [attr.aria-hidden]=\"option.disabled\">\r\n <input\r\n #radio\r\n type=\"radio\"\r\n formControlName=\"option\"\r\n id=\"date-filter-{{ option.display }}\"\r\n [attr.disabled]=\"option.disabled ? true : null\"\r\n [attr.aria-disabled]=\"option.disabled\"\r\n (click)=\"select()\"\r\n value=\"{{ option.display }}\" />\r\n\r\n <label\r\n for=\"date-filter-{{ option.display }}\"\r\n class=\"grow cursor-pointer p-1\">\r\n {{ option.display | syslang | transloco }}\r\n </label>\r\n </li>\r\n }\r\n\r\n @if (allowCustomRange) {\r\n <li\r\n role=\"listitem\"\r\n aria-label=\"open date range picker\"\r\n class=\"flex px-2 leading-7\"\r\n [class.select]=\"form.get('option')?.value === 'custom-range'\">\r\n <input\r\n type=\"radio\"\r\n formControlName=\"option\"\r\n id=\"date-filter-range-dialog\"\r\n value=\"custom-range\"\r\n (click)=\"select()\" />\r\n <div\r\n class=\"@container flex grow justify-end gap-1 p-1 @max-[340px]:flex-wrap\">\r\n <div class=\"flex gap-1\">\r\n <label for=\"datepicker-range-start\" class=\"min-w-10 truncate\">{{\r\n \"filters.from\" | transloco\r\n }}</label>\r\n <input\r\n id=\"datepicker-range-start\"\r\n name=\"start\"\r\n type=\"text\"\r\n readonly\r\n class=\"h-8 max-w-[13ch] min-w-[13ch]\"\r\n [value]=\"customRangeFrom()\"\r\n (click)=\"selectAndOpenDialog()\" />\r\n </div>\r\n <div class=\"flex gap-1\">\r\n <label\r\n for=\"datepicker-range-end\"\r\n class=\"min-w-10 truncate text-right\"\r\n >{{ \"filters.to\" | transloco }}</label\r\n >\r\n <input\r\n id=\"datepicker-range-end\"\r\n name=\"end\"\r\n type=\"text\"\r\n readonly\r\n class=\"h-8 max-w-[13ch] min-w-[13ch]\"\r\n [value]=\"customRangeTo()\"\r\n (click)=\"selectAndOpenDialog()\" />\r\n </div>\r\n </div>\r\n </li>\r\n }\r\n </ul>\r\n </form>\r\n</details>\r\n\r\n<aggregation-date-range-dialog\r\n [lang]=\"lang()\"\r\n [useDateRange]=\"false\"\r\n [min]=\"form.get('customRange.from')?.value || undefined\"\r\n [max]=\"form.get('customRange.to')?.value || undefined\"\r\n (rangeSelected)=\"onRangeSelected($event)\" />\r\n", styles: [":host{display:block;min-width:200px}ul[role=list]{scrollbar-width:thin}\n"], dependencies: [{ kind: "directive", type: InputComponent, selector: "input[type=\"text\"], input[type=\"email\"], input[type=\"number\"], input[type=\"password\"], input[type=\"tel\"], input[type=\"url\"], input[type=\"time\"], input[type=\"file\"]", inputs: ["class", "variant", "decoration"] }, { kind: "directive", type: ButtonComponent, selector: "button", inputs: ["class", "variant", "decoration", "scheme", "iconOnly", "size"] }, { kind: "directive", type: ListItemComponent, selector: "[role=\"listitem\"], [role=\"option\"]", inputs: ["class", "variant", "decoration"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.RadioControlValueAccessor, selector: "input[type=radio][formControlName],input[type=radio][formControl],input[type=radio][ngModel]", inputs: ["name", "formControlName", "value"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: ChevronRightIcon, selector: "chevron-right, ChevronRight, chevronright, ChevronRightIcon", inputs: ["class"] }, { kind: "component", type: AggregationDateRangeDialogComponent, selector: "aggregation-date-range-dialog", inputs: ["min", "max", "lang", "useDateRange"], outputs: ["rangeSelected"] }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }, { kind: "pipe", type: SyslangPipe, name: "syslang" }] });
|
|
9063
9143
|
}
|
|
9064
9144
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: AggregationDateComponent, decorators: [{
|
|
9065
9145
|
type: Component,
|
|
9066
9146
|
args: [{ selector: "aggregation-date, AggregationDate, aggregationdate", standalone: true, providers: [provideTranslocoScope("filters")], imports: [
|
|
9147
|
+
InputComponent,
|
|
9067
9148
|
ButtonComponent,
|
|
9068
9149
|
ListItemComponent,
|
|
9069
9150
|
ReactiveFormsModule,
|
|
@@ -9073,8 +9154,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
9073
9154
|
AggregationDateRangeDialogComponent
|
|
9074
9155
|
], host: {
|
|
9075
9156
|
class: "@container"
|
|
9076
|
-
}, template: "<details [attr.open]=\"expanded()\" [attr.name]=\"id()\" class=\"group space-y-2\">\r\n <summary\r\n [class.cursor-pointer]=\"collapsible()\"\r\n class=\"m-0 flex h-8 w-full items-center pl-1 font-semibold select-none\"\r\n (click)=\"onHeaderClick($event)\">\r\n <ng-content select=\"label\">\r\n @if (aggregation()?.icon) {\r\n <i class=\"fa-fw {{ aggregation()?.icon }} mr-1\" aria-hidden=\"true\"></i>\r\n }\r\n <span class=\"grow\">{{\r\n aggregation()?.display | syslang | transloco\r\n }}</span>\r\n </ng-content>\r\n\r\n @if (hasFilters()) {\r\n <button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n [attr.title]=\"'filters.clearFilters' | transloco\"\r\n [attr.aria-label]=\"'filters.clearFilters' | transloco\"\r\n (click)=\"clear()\"\r\n (keydown.enter)=\"clear()\">\r\n <i class=\"fa-fw far fa-filter-circle-xmark\" aria-hidden=\"true\"></i>\r\n <span class=\"sr-only\">{{ \"filters.clearFilters\" | transloco }}</span>\r\n </button>\r\n }\r\n\r\n @if (selection() && validSelection()) {\r\n <button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n [attr.title]=\"'filters.applyFilters' | transloco\"\r\n [attr.aria-label]=\"'filters.applyFilters' | transloco\"\r\n (click)=\"apply()\"\r\n (keydown.enter)=\"apply()\">\r\n <i class=\"fa-fw far fa-filter\" aria-hidden=\"true\"></i>\r\n <span class=\"sr-only\">{{ \"filters.applyFilters\" | transloco }}</span>\r\n </button>\r\n }\r\n @if (collapsible()) {\r\n <button\r\n variant=\"none\"\r\n title=\"Open/Close\"\r\n class=\"cursor-pointer [&_svg]:transition-transform [&_svg]:duration-150 group-open:[&_svg]:rotate-90\">\r\n <chevronright />\r\n </button>\r\n }\r\n </summary>\r\n\r\n <!-- content wrapper -->\r\n <form [formGroup]=\"form\">\r\n <ul\r\n class=\"scrollbar-thin flex max-h-[calc(var(--height,100%)-100px)] snap-y snap-start flex-col gap-1 overflow-auto pt-2\"\r\n role=\"list\">\r\n @for (option of dateOptions(); track $index) {\r\n <li\r\n role=\"listitem\"\r\n tabindex=\"0\"\r\n (click)=\"radio.click()\"\r\n [attr.aria-label]=\"option.display | syslang | transloco\"\r\n [class]=\"\r\n cn(\r\n 'flex p-0 px-2 leading-7',\r\n form.get('option')?.value === option.display && 'bg-accent',\r\n option.hidden && 'hidden',\r\n option.disabled && 'disabled pointer-events-none text-neutral-300'\r\n )\r\n \"\r\n [attr.aria-hidden]=\"option.disabled\">\r\n <input\r\n #radio\r\n type=\"radio\"\r\n formControlName=\"option\"\r\n id=\"date-filter-{{ option.display }}\"\r\n [attr.disabled]=\"option.disabled ? true : null\"\r\n [attr.aria-disabled]=\"option.disabled\"\r\n (click)=\"select()\"\r\n value=\"{{ option.display }}\" />\r\n\r\n <label\r\n for=\"date-filter-{{ option.display }}\"\r\n class=\"grow cursor-pointer p-1\">\r\n {{ option.display | syslang | transloco }}\r\n </label>\r\n </li>\r\n }\r\n\r\n @if (allowCustomRange) {\r\n <li\r\n role=\"listitem\"\r\n aria-label=\"open date range picker\"\r\n class=\"flex px-2 leading-7\"\r\n [class.select]=\"form.get('option')?.value === 'custom-range'\">\r\n <input\r\n type=\"radio\"\r\n formControlName=\"option\"\r\n id=\"date-filter-range-dialog\"\r\n value=\"custom-range\"\r\n (click)=\"select()\" />\r\n
|
|
9077
|
-
}], ctorParameters: () => [
|
|
9157
|
+
}, template: "<details [attr.open]=\"expanded()\" [attr.name]=\"id()\" class=\"group space-y-2\">\r\n <summary\r\n [class.cursor-pointer]=\"collapsible()\"\r\n class=\"m-0 flex h-8 w-full items-center pl-1 font-semibold select-none\"\r\n (click)=\"onHeaderClick($event)\">\r\n <ng-content select=\"label\">\r\n @if (aggregation()?.icon) {\r\n <i class=\"fa-fw {{ aggregation()?.icon }} mr-1\" aria-hidden=\"true\"></i>\r\n }\r\n <span class=\"grow\">{{\r\n aggregation()?.display | syslang | transloco\r\n }}</span>\r\n </ng-content>\r\n\r\n @if (hasFilters()) {\r\n <button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n [attr.title]=\"'filters.clearFilters' | transloco\"\r\n [attr.aria-label]=\"'filters.clearFilters' | transloco\"\r\n (click)=\"clear()\"\r\n (keydown.enter)=\"clear()\">\r\n <i class=\"fa-fw far fa-filter-circle-xmark\" aria-hidden=\"true\"></i>\r\n <span class=\"sr-only\">{{ \"filters.clearFilters\" | transloco }}</span>\r\n </button>\r\n }\r\n\r\n @if (selection() && validSelection()) {\r\n <button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n [attr.title]=\"'filters.applyFilters' | transloco\"\r\n [attr.aria-label]=\"'filters.applyFilters' | transloco\"\r\n (click)=\"apply()\"\r\n (keydown.enter)=\"apply()\">\r\n <i class=\"fa-fw far fa-filter\" aria-hidden=\"true\"></i>\r\n <span class=\"sr-only\">{{ \"filters.applyFilters\" | transloco }}</span>\r\n </button>\r\n }\r\n @if (collapsible()) {\r\n <button\r\n variant=\"none\"\r\n title=\"Open/Close\"\r\n class=\"cursor-pointer [&_svg]:transition-transform [&_svg]:duration-150 group-open:[&_svg]:rotate-90\">\r\n <chevronright />\r\n </button>\r\n }\r\n </summary>\r\n\r\n <!-- content wrapper -->\r\n <form [formGroup]=\"form\">\r\n <ul\r\n class=\"scrollbar-thin flex max-h-[calc(var(--height,100%)-100px)] snap-y snap-start flex-col gap-1 overflow-auto pt-2\"\r\n role=\"list\">\r\n @for (option of dateOptions(); track $index) {\r\n <li\r\n role=\"listitem\"\r\n tabindex=\"0\"\r\n (click)=\"radio.click()\"\r\n [attr.aria-label]=\"option.display | syslang | transloco\"\r\n [class]=\"\r\n cn(\r\n 'flex p-0 px-2 leading-7',\r\n form.get('option')?.value === option.display && 'bg-accent',\r\n option.hidden && 'hidden',\r\n option.disabled && 'disabled pointer-events-none text-neutral-300'\r\n )\r\n \"\r\n [attr.aria-hidden]=\"option.disabled\">\r\n <input\r\n #radio\r\n type=\"radio\"\r\n formControlName=\"option\"\r\n id=\"date-filter-{{ option.display }}\"\r\n [attr.disabled]=\"option.disabled ? true : null\"\r\n [attr.aria-disabled]=\"option.disabled\"\r\n (click)=\"select()\"\r\n value=\"{{ option.display }}\" />\r\n\r\n <label\r\n for=\"date-filter-{{ option.display }}\"\r\n class=\"grow cursor-pointer p-1\">\r\n {{ option.display | syslang | transloco }}\r\n </label>\r\n </li>\r\n }\r\n\r\n @if (allowCustomRange) {\r\n <li\r\n role=\"listitem\"\r\n aria-label=\"open date range picker\"\r\n class=\"flex px-2 leading-7\"\r\n [class.select]=\"form.get('option')?.value === 'custom-range'\">\r\n <input\r\n type=\"radio\"\r\n formControlName=\"option\"\r\n id=\"date-filter-range-dialog\"\r\n value=\"custom-range\"\r\n (click)=\"select()\" />\r\n <div\r\n class=\"@container flex grow justify-end gap-1 p-1 @max-[340px]:flex-wrap\">\r\n <div class=\"flex gap-1\">\r\n <label for=\"datepicker-range-start\" class=\"min-w-10 truncate\">{{\r\n \"filters.from\" | transloco\r\n }}</label>\r\n <input\r\n id=\"datepicker-range-start\"\r\n name=\"start\"\r\n type=\"text\"\r\n readonly\r\n class=\"h-8 max-w-[13ch] min-w-[13ch]\"\r\n [value]=\"customRangeFrom()\"\r\n (click)=\"selectAndOpenDialog()\" />\r\n </div>\r\n <div class=\"flex gap-1\">\r\n <label\r\n for=\"datepicker-range-end\"\r\n class=\"min-w-10 truncate text-right\"\r\n >{{ \"filters.to\" | transloco }}</label\r\n >\r\n <input\r\n id=\"datepicker-range-end\"\r\n name=\"end\"\r\n type=\"text\"\r\n readonly\r\n class=\"h-8 max-w-[13ch] min-w-[13ch]\"\r\n [value]=\"customRangeTo()\"\r\n (click)=\"selectAndOpenDialog()\" />\r\n </div>\r\n </div>\r\n </li>\r\n }\r\n </ul>\r\n </form>\r\n</details>\r\n\r\n<aggregation-date-range-dialog\r\n [lang]=\"lang()\"\r\n [useDateRange]=\"false\"\r\n [min]=\"form.get('customRange.from')?.value || undefined\"\r\n [max]=\"form.get('customRange.to')?.value || undefined\"\r\n (rangeSelected)=\"onRangeSelected($event)\" />\r\n", styles: [":host{display:block;min-width:200px}ul[role=list]{scrollbar-width:thin}\n"] }]
|
|
9158
|
+
}], ctorParameters: () => [], propDecorators: { dateRangeDialog: [{ type: i0.ViewChild, args: [i0.forwardRef(() => AggregationDateRangeDialogComponent), { isSignal: true }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], displayEmptyDistributionIntervals: [{ type: i0.Input, args: [{ isSignal: true, alias: "displayEmptyDistributionIntervals", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }] } });
|
|
9078
9159
|
|
|
9079
9160
|
/**
|
|
9080
9161
|
* Component that allows users to select a date or a date range for filtering search results.
|
|
@@ -9083,7 +9164,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
9083
9164
|
*/
|
|
9084
9165
|
class DateComponent extends AggregationDateComponent {
|
|
9085
9166
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: DateComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
9086
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.18", type: DateComponent, isStandalone: true, selector: "date-filter,DateFilter", host: { classAttribute: "@container" }, providers: [provideTranslocoScope("filters")], usesInheritance: true, ngImport: i0, template: "<details [attr.open]=\"expanded()\" [attr.name]=\"id()\" class=\"group space-y-2\">\r\n <summary\r\n [class.cursor-pointer]=\"collapsible()\"\r\n class=\"m-0 flex h-8 w-full items-center pl-1 font-semibold select-none\"\r\n (click)=\"onHeaderClick($event)\">\r\n <ng-content select=\"label\">\r\n @if (aggregation()?.icon) {\r\n <i class=\"fa-fw {{ aggregation()?.icon }} mr-1\" aria-hidden=\"true\"></i>\r\n }\r\n <span class=\"grow\">{{\r\n aggregation()?.display | syslang | transloco\r\n }}</span>\r\n </ng-content>\r\n\r\n @if (hasFilters()) {\r\n <button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n [attr.title]=\"'filters.clearFilters' | transloco\"\r\n [attr.aria-label]=\"'filters.clearFilters' | transloco\"\r\n (click)=\"clear()\"\r\n (keydown.enter)=\"clear()\">\r\n <i class=\"fa-fw far fa-filter-circle-xmark\" aria-hidden=\"true\"></i>\r\n <span class=\"sr-only\">{{ \"filters.clearFilters\" | transloco }}</span>\r\n </button>\r\n }\r\n\r\n @if (selection() && validSelection()) {\r\n <button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n [attr.title]=\"'filters.applyFilters' | transloco\"\r\n [attr.aria-label]=\"'filters.applyFilters' | transloco\"\r\n (click)=\"apply()\"\r\n (keydown.enter)=\"apply()\">\r\n <i class=\"fa-fw far fa-filter\" aria-hidden=\"true\"></i>\r\n <span class=\"sr-only\">{{ \"filters.applyFilters\" | transloco }}</span>\r\n </button>\r\n }\r\n @if (collapsible()) {\r\n <button\r\n variant=\"none\"\r\n title=\"Open/Close\"\r\n class=\"cursor-pointer [&_svg]:transition-transform [&_svg]:duration-150 group-open:[&_svg]:rotate-90\">\r\n <chevronright />\r\n </button>\r\n }\r\n </summary>\r\n\r\n <!-- content wrapper -->\r\n <form [formGroup]=\"form\">\r\n <ul\r\n class=\"scrollbar-thin flex max-h-[calc(var(--height,100%)-100px)] snap-y snap-start flex-col gap-1 overflow-auto pt-2\"\r\n role=\"list\">\r\n @for (option of dateOptions(); track $index) {\r\n <li\r\n role=\"listitem\"\r\n tabindex=\"0\"\r\n (click)=\"radio.click()\"\r\n [attr.aria-label]=\"option.display | syslang | transloco\"\r\n [class]=\"\r\n cn(\r\n 'flex p-0 px-2 leading-7',\r\n form.get('option')?.value === option.display && 'bg-accent',\r\n option.hidden && 'hidden',\r\n option.disabled && 'disabled pointer-events-none text-neutral-300'\r\n )\r\n \"\r\n [attr.aria-hidden]=\"option.disabled\">\r\n <input\r\n #radio\r\n type=\"radio\"\r\n formControlName=\"option\"\r\n id=\"date-filter-{{ option.display }}\"\r\n [attr.disabled]=\"option.disabled ? true : null\"\r\n [attr.aria-disabled]=\"option.disabled\"\r\n (click)=\"select()\"\r\n value=\"{{ option.display }}\" />\r\n\r\n <label\r\n for=\"date-filter-{{ option.display }}\"\r\n class=\"grow cursor-pointer p-1\">\r\n {{ option.display | syslang | transloco }}\r\n </label>\r\n </li>\r\n }\r\n\r\n @if (allowCustomRange) {\r\n <li\r\n role=\"listitem\"\r\n aria-label=\"open date range picker\"\r\n class=\"flex px-2 leading-7\"\r\n [class.select]=\"form.get('option')?.value === 'custom-range'\">\r\n <input\r\n type=\"radio\"\r\n formControlName=\"option\"\r\n id=\"date-filter-range-dialog\"\r\n value=\"custom-range\"\r\n (click)=\"select()\" />\r\n
|
|
9167
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.18", type: DateComponent, isStandalone: true, selector: "date-filter,DateFilter", host: { classAttribute: "@container" }, providers: [provideTranslocoScope("filters")], usesInheritance: true, ngImport: i0, template: "<details [attr.open]=\"expanded()\" [attr.name]=\"id()\" class=\"group space-y-2\">\r\n <summary\r\n [class.cursor-pointer]=\"collapsible()\"\r\n class=\"m-0 flex h-8 w-full items-center pl-1 font-semibold select-none\"\r\n (click)=\"onHeaderClick($event)\">\r\n <ng-content select=\"label\">\r\n @if (aggregation()?.icon) {\r\n <i class=\"fa-fw {{ aggregation()?.icon }} mr-1\" aria-hidden=\"true\"></i>\r\n }\r\n <span class=\"grow\">{{\r\n aggregation()?.display | syslang | transloco\r\n }}</span>\r\n </ng-content>\r\n\r\n @if (hasFilters()) {\r\n <button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n [attr.title]=\"'filters.clearFilters' | transloco\"\r\n [attr.aria-label]=\"'filters.clearFilters' | transloco\"\r\n (click)=\"clear()\"\r\n (keydown.enter)=\"clear()\">\r\n <i class=\"fa-fw far fa-filter-circle-xmark\" aria-hidden=\"true\"></i>\r\n <span class=\"sr-only\">{{ \"filters.clearFilters\" | transloco }}</span>\r\n </button>\r\n }\r\n\r\n @if (selection() && validSelection()) {\r\n <button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n [attr.title]=\"'filters.applyFilters' | transloco\"\r\n [attr.aria-label]=\"'filters.applyFilters' | transloco\"\r\n (click)=\"apply()\"\r\n (keydown.enter)=\"apply()\">\r\n <i class=\"fa-fw far fa-filter\" aria-hidden=\"true\"></i>\r\n <span class=\"sr-only\">{{ \"filters.applyFilters\" | transloco }}</span>\r\n </button>\r\n }\r\n @if (collapsible()) {\r\n <button\r\n variant=\"none\"\r\n title=\"Open/Close\"\r\n class=\"cursor-pointer [&_svg]:transition-transform [&_svg]:duration-150 group-open:[&_svg]:rotate-90\">\r\n <chevronright />\r\n </button>\r\n }\r\n </summary>\r\n\r\n <!-- content wrapper -->\r\n <form [formGroup]=\"form\">\r\n <ul\r\n class=\"scrollbar-thin flex max-h-[calc(var(--height,100%)-100px)] snap-y snap-start flex-col gap-1 overflow-auto pt-2\"\r\n role=\"list\">\r\n @for (option of dateOptions(); track $index) {\r\n <li\r\n role=\"listitem\"\r\n tabindex=\"0\"\r\n (click)=\"radio.click()\"\r\n [attr.aria-label]=\"option.display | syslang | transloco\"\r\n [class]=\"\r\n cn(\r\n 'flex p-0 px-2 leading-7',\r\n form.get('option')?.value === option.display && 'bg-accent',\r\n option.hidden && 'hidden',\r\n option.disabled && 'disabled pointer-events-none text-neutral-300'\r\n )\r\n \"\r\n [attr.aria-hidden]=\"option.disabled\">\r\n <input\r\n #radio\r\n type=\"radio\"\r\n formControlName=\"option\"\r\n id=\"date-filter-{{ option.display }}\"\r\n [attr.disabled]=\"option.disabled ? true : null\"\r\n [attr.aria-disabled]=\"option.disabled\"\r\n (click)=\"select()\"\r\n value=\"{{ option.display }}\" />\r\n\r\n <label\r\n for=\"date-filter-{{ option.display }}\"\r\n class=\"grow cursor-pointer p-1\">\r\n {{ option.display | syslang | transloco }}\r\n </label>\r\n </li>\r\n }\r\n\r\n @if (allowCustomRange) {\r\n <li\r\n role=\"listitem\"\r\n aria-label=\"open date range picker\"\r\n class=\"flex px-2 leading-7\"\r\n [class.select]=\"form.get('option')?.value === 'custom-range'\">\r\n <input\r\n type=\"radio\"\r\n formControlName=\"option\"\r\n id=\"date-filter-range-dialog\"\r\n value=\"custom-range\"\r\n (click)=\"select()\" />\r\n <div\r\n class=\"@container flex grow justify-end gap-1 p-1 @max-[340px]:flex-wrap\">\r\n <div class=\"flex gap-1\">\r\n <label for=\"datepicker-range-start\" class=\"min-w-10 truncate\">{{\r\n \"filters.from\" | transloco\r\n }}</label>\r\n <input\r\n id=\"datepicker-range-start\"\r\n name=\"start\"\r\n type=\"text\"\r\n readonly\r\n class=\"h-8 max-w-[13ch] min-w-[13ch]\"\r\n [value]=\"customRangeFrom()\"\r\n (click)=\"selectAndOpenDialog()\" />\r\n </div>\r\n <div class=\"flex gap-1\">\r\n <label\r\n for=\"datepicker-range-end\"\r\n class=\"min-w-10 truncate text-right\"\r\n >{{ \"filters.to\" | transloco }}</label\r\n >\r\n <input\r\n id=\"datepicker-range-end\"\r\n name=\"end\"\r\n type=\"text\"\r\n readonly\r\n class=\"h-8 max-w-[13ch] min-w-[13ch]\"\r\n [value]=\"customRangeTo()\"\r\n (click)=\"selectAndOpenDialog()\" />\r\n </div>\r\n </div>\r\n </li>\r\n }\r\n </ul>\r\n </form>\r\n</details>\r\n\r\n<aggregation-date-range-dialog\r\n [lang]=\"lang()\"\r\n [useDateRange]=\"false\"\r\n [min]=\"form.get('customRange.from')?.value || undefined\"\r\n [max]=\"form.get('customRange.to')?.value || undefined\"\r\n (rangeSelected)=\"onRangeSelected($event)\" />\r\n", styles: [":host{display:block;min-width:200px}ul[role=list]{scrollbar-width:thin}\n"], dependencies: [{ kind: "directive", type: ButtonComponent, selector: "button", inputs: ["class", "variant", "decoration", "scheme", "iconOnly", "size"] }, { kind: "directive", type: ListItemComponent, selector: "[role=\"listitem\"], [role=\"option\"]", inputs: ["class", "variant", "decoration"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.RadioControlValueAccessor, selector: "input[type=radio][formControlName],input[type=radio][formControl],input[type=radio][ngModel]", inputs: ["name", "formControlName", "value"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: ChevronRightIcon, selector: "chevron-right, ChevronRight, chevronright, ChevronRightIcon", inputs: ["class"] }, { kind: "component", type: AggregationDateRangeDialogComponent, selector: "aggregation-date-range-dialog", inputs: ["min", "max", "lang", "useDateRange"], outputs: ["rangeSelected"] }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }, { kind: "pipe", type: SyslangPipe, name: "syslang" }] });
|
|
9087
9168
|
}
|
|
9088
9169
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: DateComponent, decorators: [{
|
|
9089
9170
|
type: Component,
|
|
@@ -9097,7 +9178,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
9097
9178
|
AggregationDateRangeDialogComponent
|
|
9098
9179
|
], host: {
|
|
9099
9180
|
class: "@container"
|
|
9100
|
-
}, template: "<details [attr.open]=\"expanded()\" [attr.name]=\"id()\" class=\"group space-y-2\">\r\n <summary\r\n [class.cursor-pointer]=\"collapsible()\"\r\n class=\"m-0 flex h-8 w-full items-center pl-1 font-semibold select-none\"\r\n (click)=\"onHeaderClick($event)\">\r\n <ng-content select=\"label\">\r\n @if (aggregation()?.icon) {\r\n <i class=\"fa-fw {{ aggregation()?.icon }} mr-1\" aria-hidden=\"true\"></i>\r\n }\r\n <span class=\"grow\">{{\r\n aggregation()?.display | syslang | transloco\r\n }}</span>\r\n </ng-content>\r\n\r\n @if (hasFilters()) {\r\n <button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n [attr.title]=\"'filters.clearFilters' | transloco\"\r\n [attr.aria-label]=\"'filters.clearFilters' | transloco\"\r\n (click)=\"clear()\"\r\n (keydown.enter)=\"clear()\">\r\n <i class=\"fa-fw far fa-filter-circle-xmark\" aria-hidden=\"true\"></i>\r\n <span class=\"sr-only\">{{ \"filters.clearFilters\" | transloco }}</span>\r\n </button>\r\n }\r\n\r\n @if (selection() && validSelection()) {\r\n <button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n [attr.title]=\"'filters.applyFilters' | transloco\"\r\n [attr.aria-label]=\"'filters.applyFilters' | transloco\"\r\n (click)=\"apply()\"\r\n (keydown.enter)=\"apply()\">\r\n <i class=\"fa-fw far fa-filter\" aria-hidden=\"true\"></i>\r\n <span class=\"sr-only\">{{ \"filters.applyFilters\" | transloco }}</span>\r\n </button>\r\n }\r\n @if (collapsible()) {\r\n <button\r\n variant=\"none\"\r\n title=\"Open/Close\"\r\n class=\"cursor-pointer [&_svg]:transition-transform [&_svg]:duration-150 group-open:[&_svg]:rotate-90\">\r\n <chevronright />\r\n </button>\r\n }\r\n </summary>\r\n\r\n <!-- content wrapper -->\r\n <form [formGroup]=\"form\">\r\n <ul\r\n class=\"scrollbar-thin flex max-h-[calc(var(--height,100%)-100px)] snap-y snap-start flex-col gap-1 overflow-auto pt-2\"\r\n role=\"list\">\r\n @for (option of dateOptions(); track $index) {\r\n <li\r\n role=\"listitem\"\r\n tabindex=\"0\"\r\n (click)=\"radio.click()\"\r\n [attr.aria-label]=\"option.display | syslang | transloco\"\r\n [class]=\"\r\n cn(\r\n 'flex p-0 px-2 leading-7',\r\n form.get('option')?.value === option.display && 'bg-accent',\r\n option.hidden && 'hidden',\r\n option.disabled && 'disabled pointer-events-none text-neutral-300'\r\n )\r\n \"\r\n [attr.aria-hidden]=\"option.disabled\">\r\n <input\r\n #radio\r\n type=\"radio\"\r\n formControlName=\"option\"\r\n id=\"date-filter-{{ option.display }}\"\r\n [attr.disabled]=\"option.disabled ? true : null\"\r\n [attr.aria-disabled]=\"option.disabled\"\r\n (click)=\"select()\"\r\n value=\"{{ option.display }}\" />\r\n\r\n <label\r\n for=\"date-filter-{{ option.display }}\"\r\n class=\"grow cursor-pointer p-1\">\r\n {{ option.display | syslang | transloco }}\r\n </label>\r\n </li>\r\n }\r\n\r\n @if (allowCustomRange) {\r\n <li\r\n role=\"listitem\"\r\n aria-label=\"open date range picker\"\r\n class=\"flex px-2 leading-7\"\r\n [class.select]=\"form.get('option')?.value === 'custom-range'\">\r\n <input\r\n type=\"radio\"\r\n formControlName=\"option\"\r\n id=\"date-filter-range-dialog\"\r\n value=\"custom-range\"\r\n (click)=\"select()\" />\r\n
|
|
9181
|
+
}, template: "<details [attr.open]=\"expanded()\" [attr.name]=\"id()\" class=\"group space-y-2\">\r\n <summary\r\n [class.cursor-pointer]=\"collapsible()\"\r\n class=\"m-0 flex h-8 w-full items-center pl-1 font-semibold select-none\"\r\n (click)=\"onHeaderClick($event)\">\r\n <ng-content select=\"label\">\r\n @if (aggregation()?.icon) {\r\n <i class=\"fa-fw {{ aggregation()?.icon }} mr-1\" aria-hidden=\"true\"></i>\r\n }\r\n <span class=\"grow\">{{\r\n aggregation()?.display | syslang | transloco\r\n }}</span>\r\n </ng-content>\r\n\r\n @if (hasFilters()) {\r\n <button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n [attr.title]=\"'filters.clearFilters' | transloco\"\r\n [attr.aria-label]=\"'filters.clearFilters' | transloco\"\r\n (click)=\"clear()\"\r\n (keydown.enter)=\"clear()\">\r\n <i class=\"fa-fw far fa-filter-circle-xmark\" aria-hidden=\"true\"></i>\r\n <span class=\"sr-only\">{{ \"filters.clearFilters\" | transloco }}</span>\r\n </button>\r\n }\r\n\r\n @if (selection() && validSelection()) {\r\n <button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n [attr.title]=\"'filters.applyFilters' | transloco\"\r\n [attr.aria-label]=\"'filters.applyFilters' | transloco\"\r\n (click)=\"apply()\"\r\n (keydown.enter)=\"apply()\">\r\n <i class=\"fa-fw far fa-filter\" aria-hidden=\"true\"></i>\r\n <span class=\"sr-only\">{{ \"filters.applyFilters\" | transloco }}</span>\r\n </button>\r\n }\r\n @if (collapsible()) {\r\n <button\r\n variant=\"none\"\r\n title=\"Open/Close\"\r\n class=\"cursor-pointer [&_svg]:transition-transform [&_svg]:duration-150 group-open:[&_svg]:rotate-90\">\r\n <chevronright />\r\n </button>\r\n }\r\n </summary>\r\n\r\n <!-- content wrapper -->\r\n <form [formGroup]=\"form\">\r\n <ul\r\n class=\"scrollbar-thin flex max-h-[calc(var(--height,100%)-100px)] snap-y snap-start flex-col gap-1 overflow-auto pt-2\"\r\n role=\"list\">\r\n @for (option of dateOptions(); track $index) {\r\n <li\r\n role=\"listitem\"\r\n tabindex=\"0\"\r\n (click)=\"radio.click()\"\r\n [attr.aria-label]=\"option.display | syslang | transloco\"\r\n [class]=\"\r\n cn(\r\n 'flex p-0 px-2 leading-7',\r\n form.get('option')?.value === option.display && 'bg-accent',\r\n option.hidden && 'hidden',\r\n option.disabled && 'disabled pointer-events-none text-neutral-300'\r\n )\r\n \"\r\n [attr.aria-hidden]=\"option.disabled\">\r\n <input\r\n #radio\r\n type=\"radio\"\r\n formControlName=\"option\"\r\n id=\"date-filter-{{ option.display }}\"\r\n [attr.disabled]=\"option.disabled ? true : null\"\r\n [attr.aria-disabled]=\"option.disabled\"\r\n (click)=\"select()\"\r\n value=\"{{ option.display }}\" />\r\n\r\n <label\r\n for=\"date-filter-{{ option.display }}\"\r\n class=\"grow cursor-pointer p-1\">\r\n {{ option.display | syslang | transloco }}\r\n </label>\r\n </li>\r\n }\r\n\r\n @if (allowCustomRange) {\r\n <li\r\n role=\"listitem\"\r\n aria-label=\"open date range picker\"\r\n class=\"flex px-2 leading-7\"\r\n [class.select]=\"form.get('option')?.value === 'custom-range'\">\r\n <input\r\n type=\"radio\"\r\n formControlName=\"option\"\r\n id=\"date-filter-range-dialog\"\r\n value=\"custom-range\"\r\n (click)=\"select()\" />\r\n <div\r\n class=\"@container flex grow justify-end gap-1 p-1 @max-[340px]:flex-wrap\">\r\n <div class=\"flex gap-1\">\r\n <label for=\"datepicker-range-start\" class=\"min-w-10 truncate\">{{\r\n \"filters.from\" | transloco\r\n }}</label>\r\n <input\r\n id=\"datepicker-range-start\"\r\n name=\"start\"\r\n type=\"text\"\r\n readonly\r\n class=\"h-8 max-w-[13ch] min-w-[13ch]\"\r\n [value]=\"customRangeFrom()\"\r\n (click)=\"selectAndOpenDialog()\" />\r\n </div>\r\n <div class=\"flex gap-1\">\r\n <label\r\n for=\"datepicker-range-end\"\r\n class=\"min-w-10 truncate text-right\"\r\n >{{ \"filters.to\" | transloco }}</label\r\n >\r\n <input\r\n id=\"datepicker-range-end\"\r\n name=\"end\"\r\n type=\"text\"\r\n readonly\r\n class=\"h-8 max-w-[13ch] min-w-[13ch]\"\r\n [value]=\"customRangeTo()\"\r\n (click)=\"selectAndOpenDialog()\" />\r\n </div>\r\n </div>\r\n </li>\r\n }\r\n </ul>\r\n </form>\r\n</details>\r\n\r\n<aggregation-date-range-dialog\r\n [lang]=\"lang()\"\r\n [useDateRange]=\"false\"\r\n [min]=\"form.get('customRange.from')?.value || undefined\"\r\n [max]=\"form.get('customRange.to')?.value || undefined\"\r\n (rangeSelected)=\"onRangeSelected($event)\" />\r\n", styles: [":host{display:block;min-width:200px}ul[role=list]{scrollbar-width:thin}\n"] }]
|
|
9101
9182
|
}] });
|
|
9102
9183
|
|
|
9103
9184
|
class ArticleEntities {
|
|
@@ -10050,6 +10131,7 @@ class ChangePasswordComponent {
|
|
|
10050
10131
|
principalStore = inject(PrincipalStore);
|
|
10051
10132
|
applicationService = inject(ApplicationService);
|
|
10052
10133
|
location = inject(Location);
|
|
10134
|
+
auditService = inject(AuditService);
|
|
10053
10135
|
currentPassword = model("", ...(ngDevMode ? [{ debugName: "currentPassword" }] : []));
|
|
10054
10136
|
newPassword = model("", ...(ngDevMode ? [{ debugName: "newPassword" }] : []));
|
|
10055
10137
|
confirmPassword = model("", ...(ngDevMode ? [{ debugName: "confirmPassword" }] : []));
|
|
@@ -10095,11 +10177,13 @@ class ChangePasswordComponent {
|
|
|
10095
10177
|
const msg = res.message ?? this.transloco.translate("login.passwordChangeFailed");
|
|
10096
10178
|
this.errorMsg.set(msg);
|
|
10097
10179
|
notify.error(msg, { duration: 2500 });
|
|
10180
|
+
this.auditService.notify({ type: 'Change_Password_Failed' });
|
|
10098
10181
|
return;
|
|
10099
10182
|
}
|
|
10100
10183
|
notify.success(this.transloco.translate("login.passwordChanged"), {
|
|
10101
10184
|
duration: 2000
|
|
10102
10185
|
});
|
|
10186
|
+
this.auditService.notify({ type: 'Change_Password_Success_Form' });
|
|
10103
10187
|
const username = this.effectiveUsername();
|
|
10104
10188
|
if (!username) {
|
|
10105
10189
|
notify.info(this.transloco.translate("login.loginAfterPasswordChangeMissingUser"), { duration: 3000 });
|
|
@@ -10388,6 +10472,7 @@ class ForgotPasswordComponent {
|
|
|
10388
10472
|
cancel = output();
|
|
10389
10473
|
success = output();
|
|
10390
10474
|
transloco = inject(TranslocoService);
|
|
10475
|
+
auditService = inject(AuditService);
|
|
10391
10476
|
userName = model("", ...(ngDevMode ? [{ debugName: "userName" }] : []));
|
|
10392
10477
|
pending = signal(false, ...(ngDevMode ? [{ debugName: "pending" }] : []));
|
|
10393
10478
|
errorMsg = signal(null, ...(ngDevMode ? [{ debugName: "errorMsg" }] : []));
|
|
@@ -10400,6 +10485,9 @@ class ForgotPasswordComponent {
|
|
|
10400
10485
|
notify.success(this.transloco.translate("login.resetEmailSent", {
|
|
10401
10486
|
email: res.email ?? ""
|
|
10402
10487
|
}));
|
|
10488
|
+
this.auditService.notify({
|
|
10489
|
+
type: 'Send_Reset_Password_Link'
|
|
10490
|
+
});
|
|
10403
10491
|
this.success.emit();
|
|
10404
10492
|
}
|
|
10405
10493
|
catch (e) {
|
|
@@ -10536,6 +10624,7 @@ class SignInComponent {
|
|
|
10536
10624
|
applicationService = inject(ApplicationService);
|
|
10537
10625
|
principalStore = inject(PrincipalStore);
|
|
10538
10626
|
transloco = inject(TranslocoService);
|
|
10627
|
+
auditService = inject(AuditService);
|
|
10539
10628
|
authenticated = signal(isAuthenticated(), ...(ngDevMode ? [{ debugName: "authenticated" }] : []));
|
|
10540
10629
|
user = signal(getState(this.principalStore), ...(ngDevMode ? [{ debugName: "user" }] : []));
|
|
10541
10630
|
expiresSoonNotified = signal(false, ...(ngDevMode ? [{ debugName: "expiresSoonNotified" }] : []));
|
|
@@ -10586,8 +10675,13 @@ class SignInComponent {
|
|
|
10586
10675
|
this.router.navigate(["/login"]);
|
|
10587
10676
|
}
|
|
10588
10677
|
async handleLogin() {
|
|
10589
|
-
login().
|
|
10678
|
+
login().then((result) => {
|
|
10679
|
+
if (result) {
|
|
10680
|
+
this.auditService.notifyLogin();
|
|
10681
|
+
}
|
|
10682
|
+
}).catch(error => {
|
|
10590
10683
|
warn("An error occurred while logging in", error);
|
|
10684
|
+
this.auditService.notify({ type: 'Login_Denied' });
|
|
10591
10685
|
this.router.navigate(["error"]);
|
|
10592
10686
|
});
|
|
10593
10687
|
}
|
|
@@ -10596,8 +10690,11 @@ class SignInComponent {
|
|
|
10596
10690
|
return;
|
|
10597
10691
|
try {
|
|
10598
10692
|
const response = await login(this.credentials());
|
|
10599
|
-
if (!response)
|
|
10693
|
+
if (!response) {
|
|
10694
|
+
this.auditService.notify({ type: 'Login_Denied' });
|
|
10600
10695
|
return;
|
|
10696
|
+
}
|
|
10697
|
+
this.auditService.notifyLogin();
|
|
10601
10698
|
const { createRoutes = false } = globalConfig;
|
|
10602
10699
|
await this.applicationService.initialize(createRoutes);
|
|
10603
10700
|
this.checkPasswordExpiresSoon();
|
|
@@ -10605,7 +10702,7 @@ class SignInComponent {
|
|
|
10605
10702
|
this.router.navigateByUrl(url);
|
|
10606
10703
|
}
|
|
10607
10704
|
catch (err) {
|
|
10608
|
-
const { status, errorMessage } = err;
|
|
10705
|
+
const { status, errorMessage, message } = err;
|
|
10609
10706
|
if (status === 401 &&
|
|
10610
10707
|
errorMessage?.toLowerCase().includes("password expired")) {
|
|
10611
10708
|
sessionStorage.setItem("passwordExpiredFlow", "true");
|
|
@@ -10618,7 +10715,8 @@ class SignInComponent {
|
|
|
10618
10715
|
});
|
|
10619
10716
|
return;
|
|
10620
10717
|
}
|
|
10621
|
-
|
|
10718
|
+
// For other errors, show a generic error message
|
|
10719
|
+
notify.error("Login", { description: message ?? errorMessage });
|
|
10622
10720
|
}
|
|
10623
10721
|
}
|
|
10624
10722
|
handleBack() {
|
|
@@ -10634,7 +10732,7 @@ class SignInComponent {
|
|
|
10634
10732
|
cdkTrapFocusAutoCapture="true"
|
|
10635
10733
|
class="bg-card rounded-xl shadow-sm">
|
|
10636
10734
|
<CardHeader class="flex flex-col items-center gap-3 text-center">
|
|
10637
|
-
<img class="h-12 content-(--logo-large
|
|
10735
|
+
<img class="h-12 content-(--logo-large)" alt="logo" />
|
|
10638
10736
|
</CardHeader>
|
|
10639
10737
|
|
|
10640
10738
|
<CardContent class="grid gap-4">
|
|
@@ -10714,7 +10812,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
10714
10812
|
cdkTrapFocusAutoCapture="true"
|
|
10715
10813
|
class="bg-card rounded-xl shadow-sm">
|
|
10716
10814
|
<CardHeader class="flex flex-col items-center gap-3 text-center">
|
|
10717
|
-
<img class="h-12 content-(--logo-large
|
|
10815
|
+
<img class="h-12 content-(--logo-large)" alt="logo" />
|
|
10718
10816
|
</CardHeader>
|
|
10719
10817
|
|
|
10720
10818
|
<CardContent class="grid gap-4">
|
|
@@ -10986,7 +11084,7 @@ class BookmarksComponent {
|
|
|
10986
11084
|
this.range.set(this.range() + (this.config.itemsPerPage ?? 10));
|
|
10987
11085
|
}
|
|
10988
11086
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: BookmarksComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
10989
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.18", type: BookmarksComponent, isStandalone: true, selector: "bookmarks, Bookmarks", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null } }, providers: [provideTranslocoScope("bookmarks")], ngImport: i0, template: "@if (floating) {\r\n <div class=\"p-2\">\r\n <label class=\"text-xl font-bold\">{{ \"bookmarks.label\" | transloco }}</label>\r\n <Separator />\r\n </div>\r\n}\r\n\r\n<ul class=\"flex max-h-[460px] flex-col overflow-auto\" role=\"list\">\r\n @for (bookmark of paginatedBookmarks(); track $index) {\r\n <li\r\n role=\"listitem\"\r\n class=\"group h-10\"\r\n tabindex=\"0\"\r\n (click)=\"onClick(bookmark)\"\r\n (keydown.enter)=\"onClick(bookmark)\">\r\n <BookmarkIcon solid class=\"shrink-0\" />\r\n\r\n <p class=\"line-clamp-1\">{{ bookmark.label }}</p>\r\n\r\n @if (bookmark.author) {\r\n <Badge variant=\"ghost\" class=\"text-grey-500 text-xs\">\r\n <UserIcon class=\"size-3\" />\r\n <span class=\"line-clamp-1\">{{ bookmark.author }}</span>\r\n </Badge>\r\n }\r\n @if (bookmark.parentFolder) {\r\n <Badge variant=\"ghost\" class=\"text-grey-500 text-xs\">\r\n <FolderIcon class=\"size-3\" />\r\n <span class=\"line-clamp-1\">{{ bookmark.parentFolder }}</span>\r\n </Badge>\r\n }\r\n\r\n <button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n title=\"{{ 'bookmarks.openBookmark' | transloco }}\"\r\n class=\"text-destructive ms-auto group-hover:visible\"\r\n [attr.title]=\"'bookmarks.removeBookmark' | transloco\"\r\n [attr.aria-label]=\"'bookmarks.removeBookmark' | transloco\"\r\n (click)=\"onDelete(bookmark, $event)\">\r\n <TrashIcon />\r\n </button>\r\n </li>\r\n } @empty {\r\n <li class=\"py-4 text-center text-neutral-500\">\r\n {{ \"bookmarks.noBookmarks\" | transloco }}\r\n </li>\r\n }\r\n</ul>\r\n\r\n<div class=\"flex flex-col px-2\">\r\n @if (hasMore() && config.showLoadMore) {\r\n <button\r\n variant=\"ghost\"\r\n class=\"w-full\"\r\n tabindex=\"0\"\r\n [attr.title]=\"'loadMore' | transloco\"\r\n (click)=\"loadMore($event)\">\r\n {{ \"loadMore\" | transloco }}\r\n </button>\r\n }\r\n <button\r\n variant=\"link\"\r\n class=\"ml-auto\"\r\n [attr.title]=\"'seeMore' | transloco\"\r\n [routerLink]=\"[config.routerLink]\">\r\n {{ \"seeMore\" | transloco }}\r\n </button>\r\n</div>\r\n", styles: [":host ul{scrollbar-width:thin}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: ListItemComponent, selector: "[role=\"listitem\"], [role=\"option\"]", inputs: ["class", "variant", "decoration"] }, { kind: "directive", type: ButtonComponent, selector: "button", inputs: ["class", "variant", "decoration", "scheme", "iconOnly", "size"] }, { kind: "directive", type: Separator, selector: "separator, Separator", inputs: ["class", "orientation"] }, { kind: "component", type: BookmarkIcon, selector: "bookmark-icon, BookmarkIcon", inputs: ["class", "solid"] }, { kind: "component", type: UserIcon, selector: "user-icon, UserIcon", inputs: ["class"] }, { kind: "component", type: TrashIcon, selector: "trash-icon, TrashIcon", inputs: ["class"] }, { kind: "component", type: FolderIcon, selector: "folder-icon, FolderIcon", inputs: ["class"] }, { kind: "directive", type: BadgeComponent, selector: "badge, Badge", inputs: ["class", "variant", "size"] }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }] });
|
|
11087
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.18", type: BookmarksComponent, isStandalone: true, selector: "bookmarks, Bookmarks", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null } }, providers: [provideTranslocoScope("bookmarks")], ngImport: i0, template: "@if (floating) {\r\n <div class=\"p-2\">\r\n <label class=\"text-xl font-bold\">{{ \"bookmarks.label\" | transloco }}</label>\r\n <Separator />\r\n </div>\r\n}\r\n\r\n<ul class=\"flex max-h-[460px] flex-col overflow-auto\" role=\"list\">\r\n @for (bookmark of paginatedBookmarks(); track $index) {\r\n <li\r\n role=\"listitem\"\r\n class=\"group h-10\"\r\n tabindex=\"0\"\r\n (click)=\"onClick(bookmark)\"\r\n (keydown.enter)=\"onClick(bookmark)\">\r\n <BookmarkIcon solid class=\"shrink-0\" />\r\n\r\n <p class=\"line-clamp-1\">{{ bookmark.label }}</p>\r\n\r\n @if (bookmark.author) {\r\n <Badge variant=\"ghost\" class=\"text-grey-500 text-xs\">\r\n <UserIcon class=\"size-3\" />\r\n <span class=\"line-clamp-1\">{{ bookmark.author }}</span>\r\n </Badge>\r\n }\r\n @if (bookmark.parentFolder) {\r\n <Badge variant=\"ghost\" class=\"text-grey-500 text-xs\">\r\n <FolderIcon class=\"size-3\" />\r\n <span class=\"line-clamp-1\">{{ bookmark.parentFolder }}</span>\r\n </Badge>\r\n }\r\n\r\n <button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n title=\"{{ 'bookmarks.openBookmark' | transloco }}\"\r\n class=\"text-destructive ms-auto group-hover:visible\"\r\n [attr.title]=\"'bookmarks.removeBookmark' | transloco\"\r\n [attr.aria-label]=\"'bookmarks.removeBookmark' | transloco\"\r\n (click)=\"onDelete(bookmark, $event)\">\r\n <TrashIcon />\r\n </button>\r\n </li>\r\n } @empty {\r\n <li class=\"list-none py-4 text-center text-neutral-500\">\r\n {{ \"bookmarks.noBookmarks\" | transloco }}\r\n </li>\r\n }\r\n</ul>\r\n\r\n<div class=\"flex flex-col px-2\">\r\n @if (hasMore() && config.showLoadMore) {\r\n <button\r\n variant=\"ghost\"\r\n class=\"w-full\"\r\n tabindex=\"0\"\r\n [attr.title]=\"'loadMore' | transloco\"\r\n (click)=\"loadMore($event)\">\r\n {{ \"loadMore\" | transloco }}\r\n </button>\r\n }\r\n <button\r\n variant=\"link\"\r\n class=\"ml-auto\"\r\n [attr.title]=\"'seeMore' | transloco\"\r\n [routerLink]=\"[config.routerLink]\">\r\n {{ \"seeMore\" | transloco }}\r\n </button>\r\n</div>\r\n", styles: [":host ul{scrollbar-width:thin}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: ListItemComponent, selector: "[role=\"listitem\"], [role=\"option\"]", inputs: ["class", "variant", "decoration"] }, { kind: "directive", type: ButtonComponent, selector: "button", inputs: ["class", "variant", "decoration", "scheme", "iconOnly", "size"] }, { kind: "directive", type: Separator, selector: "separator, Separator", inputs: ["class", "orientation"] }, { kind: "component", type: BookmarkIcon, selector: "bookmark-icon, BookmarkIcon", inputs: ["class", "solid"] }, { kind: "component", type: UserIcon, selector: "user-icon, UserIcon", inputs: ["class"] }, { kind: "component", type: TrashIcon, selector: "trash-icon, TrashIcon", inputs: ["class"] }, { kind: "component", type: FolderIcon, selector: "folder-icon, FolderIcon", inputs: ["class"] }, { kind: "directive", type: BadgeComponent, selector: "badge, Badge", inputs: ["class", "variant", "size"] }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }] });
|
|
10990
11088
|
}
|
|
10991
11089
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: BookmarksComponent, decorators: [{
|
|
10992
11090
|
type: Component,
|
|
@@ -11001,7 +11099,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
11001
11099
|
TrashIcon,
|
|
11002
11100
|
FolderIcon,
|
|
11003
11101
|
BadgeComponent
|
|
11004
|
-
], providers: [provideTranslocoScope("bookmarks")], template: "@if (floating) {\r\n <div class=\"p-2\">\r\n <label class=\"text-xl font-bold\">{{ \"bookmarks.label\" | transloco }}</label>\r\n <Separator />\r\n </div>\r\n}\r\n\r\n<ul class=\"flex max-h-[460px] flex-col overflow-auto\" role=\"list\">\r\n @for (bookmark of paginatedBookmarks(); track $index) {\r\n <li\r\n role=\"listitem\"\r\n class=\"group h-10\"\r\n tabindex=\"0\"\r\n (click)=\"onClick(bookmark)\"\r\n (keydown.enter)=\"onClick(bookmark)\">\r\n <BookmarkIcon solid class=\"shrink-0\" />\r\n\r\n <p class=\"line-clamp-1\">{{ bookmark.label }}</p>\r\n\r\n @if (bookmark.author) {\r\n <Badge variant=\"ghost\" class=\"text-grey-500 text-xs\">\r\n <UserIcon class=\"size-3\" />\r\n <span class=\"line-clamp-1\">{{ bookmark.author }}</span>\r\n </Badge>\r\n }\r\n @if (bookmark.parentFolder) {\r\n <Badge variant=\"ghost\" class=\"text-grey-500 text-xs\">\r\n <FolderIcon class=\"size-3\" />\r\n <span class=\"line-clamp-1\">{{ bookmark.parentFolder }}</span>\r\n </Badge>\r\n }\r\n\r\n <button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n title=\"{{ 'bookmarks.openBookmark' | transloco }}\"\r\n class=\"text-destructive ms-auto group-hover:visible\"\r\n [attr.title]=\"'bookmarks.removeBookmark' | transloco\"\r\n [attr.aria-label]=\"'bookmarks.removeBookmark' | transloco\"\r\n (click)=\"onDelete(bookmark, $event)\">\r\n <TrashIcon />\r\n </button>\r\n </li>\r\n } @empty {\r\n <li class=\"py-4 text-center text-neutral-500\">\r\n {{ \"bookmarks.noBookmarks\" | transloco }}\r\n </li>\r\n }\r\n</ul>\r\n\r\n<div class=\"flex flex-col px-2\">\r\n @if (hasMore() && config.showLoadMore) {\r\n <button\r\n variant=\"ghost\"\r\n class=\"w-full\"\r\n tabindex=\"0\"\r\n [attr.title]=\"'loadMore' | transloco\"\r\n (click)=\"loadMore($event)\">\r\n {{ \"loadMore\" | transloco }}\r\n </button>\r\n }\r\n <button\r\n variant=\"link\"\r\n class=\"ml-auto\"\r\n [attr.title]=\"'seeMore' | transloco\"\r\n [routerLink]=\"[config.routerLink]\">\r\n {{ \"seeMore\" | transloco }}\r\n </button>\r\n</div>\r\n", styles: [":host ul{scrollbar-width:thin}\n"] }]
|
|
11102
|
+
], providers: [provideTranslocoScope("bookmarks")], template: "@if (floating) {\r\n <div class=\"p-2\">\r\n <label class=\"text-xl font-bold\">{{ \"bookmarks.label\" | transloco }}</label>\r\n <Separator />\r\n </div>\r\n}\r\n\r\n<ul class=\"flex max-h-[460px] flex-col overflow-auto\" role=\"list\">\r\n @for (bookmark of paginatedBookmarks(); track $index) {\r\n <li\r\n role=\"listitem\"\r\n class=\"group h-10\"\r\n tabindex=\"0\"\r\n (click)=\"onClick(bookmark)\"\r\n (keydown.enter)=\"onClick(bookmark)\">\r\n <BookmarkIcon solid class=\"shrink-0\" />\r\n\r\n <p class=\"line-clamp-1\">{{ bookmark.label }}</p>\r\n\r\n @if (bookmark.author) {\r\n <Badge variant=\"ghost\" class=\"text-grey-500 text-xs\">\r\n <UserIcon class=\"size-3\" />\r\n <span class=\"line-clamp-1\">{{ bookmark.author }}</span>\r\n </Badge>\r\n }\r\n @if (bookmark.parentFolder) {\r\n <Badge variant=\"ghost\" class=\"text-grey-500 text-xs\">\r\n <FolderIcon class=\"size-3\" />\r\n <span class=\"line-clamp-1\">{{ bookmark.parentFolder }}</span>\r\n </Badge>\r\n }\r\n\r\n <button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n title=\"{{ 'bookmarks.openBookmark' | transloco }}\"\r\n class=\"text-destructive ms-auto group-hover:visible\"\r\n [attr.title]=\"'bookmarks.removeBookmark' | transloco\"\r\n [attr.aria-label]=\"'bookmarks.removeBookmark' | transloco\"\r\n (click)=\"onDelete(bookmark, $event)\">\r\n <TrashIcon />\r\n </button>\r\n </li>\r\n } @empty {\r\n <li class=\"list-none py-4 text-center text-neutral-500\">\r\n {{ \"bookmarks.noBookmarks\" | transloco }}\r\n </li>\r\n }\r\n</ul>\r\n\r\n<div class=\"flex flex-col px-2\">\r\n @if (hasMore() && config.showLoadMore) {\r\n <button\r\n variant=\"ghost\"\r\n class=\"w-full\"\r\n tabindex=\"0\"\r\n [attr.title]=\"'loadMore' | transloco\"\r\n (click)=\"loadMore($event)\">\r\n {{ \"loadMore\" | transloco }}\r\n </button>\r\n }\r\n <button\r\n variant=\"link\"\r\n class=\"ml-auto\"\r\n [attr.title]=\"'seeMore' | transloco\"\r\n [routerLink]=\"[config.routerLink]\">\r\n {{ \"seeMore\" | transloco }}\r\n </button>\r\n</div>\r\n", styles: [":host ul{scrollbar-width:thin}\n"] }]
|
|
11005
11103
|
}], ctorParameters: () => [], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }] } });
|
|
11006
11104
|
|
|
11007
11105
|
class DeleteCollectionDialog {
|
|
@@ -11126,11 +11224,11 @@ class CollectionsComponent {
|
|
|
11126
11224
|
this.range.set(this.range() + (this.config.itemsPerPage ?? 10));
|
|
11127
11225
|
}
|
|
11128
11226
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: CollectionsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
11129
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.18", type: CollectionsComponent, isStandalone: true, selector: "app-collections", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null } }, providers: [provideTranslocoScope("collections")], viewQueries: [{ propertyName: "deleteCollectionDialog", first: true, predicate: DeleteCollectionDialog, descendants: true, isSignal: true }], ngImport: i0, template: "@if (floating) {\r\n <div class=\"p-2\">\r\n <label class=\"text-xl font-bold\">{{\r\n \"collections.label\" | transloco\r\n }}</label>\r\n <Separator />\r\n </div>\r\n}\r\n\r\n<ul class=\"flex max-h-[460px] flex-col overflow-auto\">\r\n @for (collection of paginatedCollections(); track $index) {\r\n <li\r\n role=\"listitem\"\r\n class=\"group grid grid-cols-[min-content_auto_min-content] items-center\"\r\n tabindex=\"0\"\r\n (click)=\"onClick(collection)\"\r\n (keydown.enter)=\"onClick(collection)\">\r\n <i class=\"fas fa-inbox ps-2\"></i>\r\n\r\n <p class=\"mx-2 line-clamp-1\">{{ collection.name }}</p>\r\n\r\n <button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n class=\"text-destructive invisible group-hover:visible\"\r\n title=\"{{ 'collections.deleteCollection' | transloco }}\"\r\n [attr.aria-label]=\"'collections.deleteCollection' | transloco\"\r\n (click)=\"onDelete(collection, $index, $event)\">\r\n <TrashIcon />\r\n </button>\r\n </li>\r\n } @empty {\r\n <li class=\"list-none py-4 text-center text-neutral-500\">\r\n {{ \"collections.noCollections\" | transloco }}\r\n </li>\r\n }\r\n</ul>\r\n\r\n<div class=\"flex flex-col px-2\">\r\n @if (hasMore() && config.showLoadMore) {\r\n <button\r\n variant=\"outline\"\r\n class=\"w-full\"\r\n tabindex=\"0\"\r\n [attr.title]=\"'loadMore' | transloco\"\r\n (click)=\"loadMore($event)\">\r\n {{ \"loadMore\" | transloco }}\r\n </button>\r\n }\r\n <button\r\n variant=\"link\"\r\n class=\"ml-auto\"\r\n [attr.title]=\"'seeMore' | transloco\"\r\n [routerLink]=\"[config.routerLink]\">\r\n {{ \"seeMore\" | transloco }}\r\n </button>\r\n</div>\r\n\r\n<delete-collection-dialog />\r\n", dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: DeleteCollectionDialog, selector: "delete-collection-dialog" }, { kind: "directive", type: ButtonComponent, selector: "button", inputs: ["class", "variant", "decoration", "scheme", "iconOnly", "size"] }, { kind: "directive", type: ListItemComponent, selector: "[role=\"listitem\"], [role=\"option\"]", inputs: ["class", "variant", "decoration"] }, { kind: "directive", type: Separator, selector: "separator, Separator", inputs: ["class", "orientation"] }, { kind: "component", type: TrashIcon, selector: "trash-icon, TrashIcon", inputs: ["class"] }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }] });
|
|
11227
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.18", type: CollectionsComponent, isStandalone: true, selector: "app-collections, collections", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null } }, providers: [provideTranslocoScope("collections")], viewQueries: [{ propertyName: "deleteCollectionDialog", first: true, predicate: DeleteCollectionDialog, descendants: true, isSignal: true }], ngImport: i0, template: "@if (floating) {\r\n <div class=\"p-2\">\r\n <label class=\"text-xl font-bold\">{{\r\n \"collections.label\" | transloco\r\n }}</label>\r\n <Separator />\r\n </div>\r\n}\r\n\r\n<ul class=\"flex max-h-[460px] flex-col overflow-auto\">\r\n @for (collection of paginatedCollections(); track $index) {\r\n <li\r\n role=\"listitem\"\r\n class=\"group grid grid-cols-[min-content_auto_min-content] items-center\"\r\n tabindex=\"0\"\r\n (click)=\"onClick(collection)\"\r\n (keydown.enter)=\"onClick(collection)\">\r\n <i class=\"fas fa-inbox ps-2\"></i>\r\n\r\n <p class=\"mx-2 line-clamp-1\">{{ collection.name }}</p>\r\n\r\n <button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n class=\"text-destructive invisible group-hover:visible\"\r\n title=\"{{ 'collections.deleteCollection' | transloco }}\"\r\n [attr.aria-label]=\"'collections.deleteCollection' | transloco\"\r\n (click)=\"onDelete(collection, $index, $event)\">\r\n <TrashIcon />\r\n </button>\r\n </li>\r\n } @empty {\r\n <li class=\"list-none py-4 text-center text-neutral-500\">\r\n {{ \"collections.noCollections\" | transloco }}\r\n </li>\r\n }\r\n</ul>\r\n\r\n<div class=\"flex flex-col px-2\">\r\n @if (hasMore() && config.showLoadMore) {\r\n <button\r\n variant=\"outline\"\r\n class=\"w-full\"\r\n tabindex=\"0\"\r\n [attr.title]=\"'loadMore' | transloco\"\r\n (click)=\"loadMore($event)\">\r\n {{ \"loadMore\" | transloco }}\r\n </button>\r\n }\r\n <button\r\n variant=\"link\"\r\n class=\"ml-auto\"\r\n [attr.title]=\"'seeMore' | transloco\"\r\n [routerLink]=\"[config.routerLink]\">\r\n {{ \"seeMore\" | transloco }}\r\n </button>\r\n</div>\r\n\r\n<delete-collection-dialog />\r\n", dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: DeleteCollectionDialog, selector: "delete-collection-dialog" }, { kind: "directive", type: ButtonComponent, selector: "button", inputs: ["class", "variant", "decoration", "scheme", "iconOnly", "size"] }, { kind: "directive", type: ListItemComponent, selector: "[role=\"listitem\"], [role=\"option\"]", inputs: ["class", "variant", "decoration"] }, { kind: "directive", type: Separator, selector: "separator, Separator", inputs: ["class", "orientation"] }, { kind: "component", type: TrashIcon, selector: "trash-icon, TrashIcon", inputs: ["class"] }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }] });
|
|
11130
11228
|
}
|
|
11131
11229
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: CollectionsComponent, decorators: [{
|
|
11132
11230
|
type: Component,
|
|
11133
|
-
args: [{ selector: "app-collections", standalone: true, imports: [
|
|
11231
|
+
args: [{ selector: "app-collections, collections", standalone: true, imports: [
|
|
11134
11232
|
TranslocoPipe,
|
|
11135
11233
|
RouterLink,
|
|
11136
11234
|
DeleteCollectionDialog,
|
|
@@ -13012,6 +13110,7 @@ class AggregationTreeComponent {
|
|
|
13012
13110
|
aggregationsService = inject(AggregationsService);
|
|
13013
13111
|
el = inject(ElementRef);
|
|
13014
13112
|
injector = inject(Injector);
|
|
13113
|
+
destroyRef = inject(DestroyRef);
|
|
13015
13114
|
class = input("", ...(ngDevMode ? [{ debugName: "class" }] : []));
|
|
13016
13115
|
/**
|
|
13017
13116
|
* The name of the <details> element. When you provide the same id, the component work as an accordion
|
|
@@ -13200,6 +13299,21 @@ class AggregationTreeComponent {
|
|
|
13200
13299
|
effect(() => {
|
|
13201
13300
|
this.filters.set(this.getFilters());
|
|
13202
13301
|
});
|
|
13302
|
+
this.destroyRef.onDestroy(() => {
|
|
13303
|
+
// If the popover is closed with unapplied selections, reset state so it doesn't persist when reopening
|
|
13304
|
+
if (this.selection()) {
|
|
13305
|
+
sessionStorage.removeItem(`agg-${this.aggregation()?.column}`);
|
|
13306
|
+
const unselect = (items) => {
|
|
13307
|
+
items.forEach((item) => {
|
|
13308
|
+
item.$selected = false;
|
|
13309
|
+
item.$selectedVisually = false;
|
|
13310
|
+
if (item.items)
|
|
13311
|
+
unselect(item.items);
|
|
13312
|
+
});
|
|
13313
|
+
};
|
|
13314
|
+
unselect(this.items());
|
|
13315
|
+
}
|
|
13316
|
+
});
|
|
13203
13317
|
}
|
|
13204
13318
|
// compare currentItems and updatedItems to add the new sub items
|
|
13205
13319
|
// from updatedItems into currentItems to not alter the already loaded items
|
|
@@ -13349,8 +13463,10 @@ class AggregationTreeComponent {
|
|
|
13349
13463
|
* If the item is deselected, the selection count is decremented by 1.
|
|
13350
13464
|
*/
|
|
13351
13465
|
select() {
|
|
13352
|
-
this.
|
|
13353
|
-
this.
|
|
13466
|
+
const selectedItems = this.getFlattenTreeItems().filter(item => item.$selected);
|
|
13467
|
+
this.onSelect.emit(selectedItems);
|
|
13468
|
+
// Keep apply visible if items are selected, or if active filters exist (user may be deselecting to clear)
|
|
13469
|
+
this.selection.set(selectedItems.length > 0 || this.hasFilters());
|
|
13354
13470
|
this.verifySelected();
|
|
13355
13471
|
sessionStorage.setItem(`agg-${this.aggregation()?.column}`, JSON.stringify([...this.items()]));
|
|
13356
13472
|
}
|
|
@@ -13805,7 +13921,7 @@ class AggregationComponent {
|
|
|
13805
13921
|
(onClear)="onClear.emit($event)"
|
|
13806
13922
|
/>
|
|
13807
13923
|
}
|
|
13808
|
-
`, isInline: true, dependencies: [{ kind: "component", type: AggregationListComponent, selector: "AggregationList, aggregation-list, aggregationlist", inputs: ["class", "id", "name", "column", "collapsible", "collapsed", "searchable", "showFiltersCount", "searchText"], outputs: ["onSelect", "onApply", "onClear", "searchTextChange"] }, { kind: "component", type: AggregationTreeComponent, selector: "AggregationTree, aggregation-tree, aggregationtree", inputs: ["class", "id", "name", "column", "expandedLevel", "collapsible", "collapsed", "searchable", "showFiltersCount", "searchText"], outputs: ["onSelect", "onApply", "onClear", "searchTextChange"] }, { kind: "component", type: AggregationDateComponent, selector: "aggregation-date, AggregationDate, aggregationdate", inputs: ["title", "displayEmptyDistributionIntervals"] }] });
|
|
13924
|
+
`, isInline: true, dependencies: [{ kind: "component", type: AggregationListComponent, selector: "AggregationList, aggregation-list, aggregationlist", inputs: ["class", "id", "name", "column", "collapsible", "collapsed", "searchable", "showFiltersCount", "searchText"], outputs: ["onSelect", "onApply", "onClear", "searchTextChange"] }, { kind: "component", type: AggregationTreeComponent, selector: "AggregationTree, aggregation-tree, aggregationtree", inputs: ["class", "id", "name", "column", "expandedLevel", "collapsible", "collapsed", "searchable", "showFiltersCount", "searchText"], outputs: ["onSelect", "onApply", "onClear", "searchTextChange"] }, { kind: "component", type: AggregationDateComponent, selector: "aggregation-date, AggregationDate, aggregationdate", inputs: ["title", "displayEmptyDistributionIntervals", "name"] }] });
|
|
13809
13925
|
}
|
|
13810
13926
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: AggregationComponent, decorators: [{
|
|
13811
13927
|
type: Component,
|
|
@@ -13911,7 +14027,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
13911
14027
|
}], propDecorators: { class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }] } });
|
|
13912
14028
|
|
|
13913
14029
|
class FilterButtonComponent {
|
|
13914
|
-
name = input
|
|
14030
|
+
name = input(...(ngDevMode ? [undefined, { debugName: "name" }] : []));
|
|
13915
14031
|
column = input.required(...(ngDevMode ? [{ debugName: "column" }] : []));
|
|
13916
14032
|
position = input("bottom-start", ...(ngDevMode ? [{ debugName: "position" }] : []));
|
|
13917
14033
|
offset = input(8, ...(ngDevMode ? [{ debugName: "offset" }] : []));
|
|
@@ -13934,15 +14050,20 @@ class FilterButtonComponent {
|
|
|
13934
14050
|
appStore = inject(AppStore);
|
|
13935
14051
|
constructor() {
|
|
13936
14052
|
effect(() => {
|
|
13937
|
-
const
|
|
13938
|
-
const
|
|
14053
|
+
const name = this.name();
|
|
14054
|
+
const column = this.column();
|
|
14055
|
+
let agg = undefined;
|
|
14056
|
+
if (name) {
|
|
14057
|
+
agg = this.aggregationsStore.getAggregation(name);
|
|
14058
|
+
if (!agg)
|
|
14059
|
+
return;
|
|
14060
|
+
}
|
|
14061
|
+
const f = this.queryParamsStore.getFilter({ name: name, field: column });
|
|
13939
14062
|
const count = f?.count || 0;
|
|
13940
|
-
if (!agg)
|
|
13941
|
-
return;
|
|
13942
14063
|
// retrieve customization fron the custom JSON provided by the server
|
|
13943
|
-
const { icon, hidden = false, display } = this.appStore.getAggregationCustomization(
|
|
14064
|
+
const { icon, hidden = false, display } = this.appStore.getAggregationCustomization(column, name) || {};
|
|
13944
14065
|
const r = {
|
|
13945
|
-
name
|
|
14066
|
+
name,
|
|
13946
14067
|
column: this.column(),
|
|
13947
14068
|
icon,
|
|
13948
14069
|
hidden,
|
|
@@ -13954,6 +14075,10 @@ class FilterButtonComponent {
|
|
|
13954
14075
|
// to be able to display the date range
|
|
13955
14076
|
legacyFilter: this.isDate(this.column()) ? f : undefined
|
|
13956
14077
|
};
|
|
14078
|
+
if (this.isDate(this.column())) {
|
|
14079
|
+
// for date filters, we want to display the date range in the button
|
|
14080
|
+
r.disabled = false; // date filters should never be disabled, even if they have no items, because they can still be applied with a custom range
|
|
14081
|
+
}
|
|
13957
14082
|
this.filter.set(r);
|
|
13958
14083
|
});
|
|
13959
14084
|
effect(() => {
|
|
@@ -13971,7 +14096,7 @@ class FilterButtonComponent {
|
|
|
13971
14096
|
return this.appStore.isDateColumn(column);
|
|
13972
14097
|
}
|
|
13973
14098
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: FilterButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
13974
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.18", type: FilterButtonComponent, isStandalone: true, selector: "filter-button, FilterButton", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired:
|
|
14099
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.18", type: FilterButtonComponent, isStandalone: true, selector: "filter-button, FilterButton", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, column: { classPropertyName: "column", publicName: "column", isSignal: true, isRequired: true, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, offset: { classPropertyName: "offset", publicName: "offset", isSignal: true, isRequired: false, transformFunction: null }, expandedLevel: { classPropertyName: "expandedLevel", publicName: "expandedLevel", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "listitem" }, properties: { "class.hidden": "filter().hidden" } }, viewQueries: [{ propertyName: "popoverRef", first: true, predicate: PopoverComponent, descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
13975
14100
|
<Popover [disabled]="filter().disabled" class="group">
|
|
13976
14101
|
<button
|
|
13977
14102
|
[variant]="variant()"
|
|
@@ -13994,11 +14119,7 @@ class FilterButtonComponent {
|
|
|
13994
14119
|
}
|
|
13995
14120
|
|
|
13996
14121
|
<!-- show the count of selected items -->
|
|
13997
|
-
@if (filter().
|
|
13998
|
-
<Badge size="xs" >
|
|
13999
|
-
{{ filter().count }}
|
|
14000
|
-
</Badge>
|
|
14001
|
-
} @else if (filter().count > 1) {
|
|
14122
|
+
@if (filter().count > 1) {
|
|
14002
14123
|
<Badge size="xs" class="pb-0.5">+{{ filter().count - 1 }}</Badge>
|
|
14003
14124
|
}
|
|
14004
14125
|
</button>
|
|
@@ -14009,15 +14130,23 @@ class FilterButtonComponent {
|
|
|
14009
14130
|
[offset]="offset()"
|
|
14010
14131
|
>
|
|
14011
14132
|
@if(contentRef.isVisible) {
|
|
14133
|
+
@let name = filter().name;
|
|
14134
|
+
@let column = filter().column;
|
|
14135
|
+
@if(name) {
|
|
14012
14136
|
<Aggregation
|
|
14013
14137
|
class="w-60 [--height:19lh]"
|
|
14014
14138
|
id="filter-{{ filter().column }}"
|
|
14015
|
-
[name]="
|
|
14016
|
-
[column]="
|
|
14139
|
+
[name]="name"
|
|
14140
|
+
[column]="column"
|
|
14017
14141
|
[expandedLevel]="expandedLevel()"
|
|
14018
14142
|
(onApply)="popoverRef()?.close()"
|
|
14019
14143
|
(onClear)="popoverRef()?.close()"
|
|
14020
14144
|
/>
|
|
14145
|
+
} @else {
|
|
14146
|
+
<div class="p-4 text-sm text-foreground/60">
|
|
14147
|
+
{{ 'INVALID_FILTER_NAME' | transloco }}
|
|
14148
|
+
</div>
|
|
14149
|
+
}
|
|
14021
14150
|
}
|
|
14022
14151
|
</PopoverContent>
|
|
14023
14152
|
</Popover>
|
|
@@ -14061,11 +14190,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
14061
14190
|
}
|
|
14062
14191
|
|
|
14063
14192
|
<!-- show the count of selected items -->
|
|
14064
|
-
@if (filter().
|
|
14065
|
-
<Badge size="xs" >
|
|
14066
|
-
{{ filter().count }}
|
|
14067
|
-
</Badge>
|
|
14068
|
-
} @else if (filter().count > 1) {
|
|
14193
|
+
@if (filter().count > 1) {
|
|
14069
14194
|
<Badge size="xs" class="pb-0.5">+{{ filter().count - 1 }}</Badge>
|
|
14070
14195
|
}
|
|
14071
14196
|
</button>
|
|
@@ -14076,15 +14201,23 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
14076
14201
|
[offset]="offset()"
|
|
14077
14202
|
>
|
|
14078
14203
|
@if(contentRef.isVisible) {
|
|
14204
|
+
@let name = filter().name;
|
|
14205
|
+
@let column = filter().column;
|
|
14206
|
+
@if(name) {
|
|
14079
14207
|
<Aggregation
|
|
14080
14208
|
class="w-60 [--height:19lh]"
|
|
14081
14209
|
id="filter-{{ filter().column }}"
|
|
14082
|
-
[name]="
|
|
14083
|
-
[column]="
|
|
14210
|
+
[name]="name"
|
|
14211
|
+
[column]="column"
|
|
14084
14212
|
[expandedLevel]="expandedLevel()"
|
|
14085
14213
|
(onApply)="popoverRef()?.close()"
|
|
14086
14214
|
(onClear)="popoverRef()?.close()"
|
|
14087
14215
|
/>
|
|
14216
|
+
} @else {
|
|
14217
|
+
<div class="p-4 text-sm text-foreground/60">
|
|
14218
|
+
{{ 'INVALID_FILTER_NAME' | transloco }}
|
|
14219
|
+
</div>
|
|
14220
|
+
}
|
|
14088
14221
|
}
|
|
14089
14222
|
</PopoverContent>
|
|
14090
14223
|
</Popover>
|
|
@@ -14094,7 +14227,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
14094
14227
|
role: "listitem"
|
|
14095
14228
|
}
|
|
14096
14229
|
}]
|
|
14097
|
-
}], ctorParameters: () => [], propDecorators: { name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required:
|
|
14230
|
+
}], ctorParameters: () => [], propDecorators: { name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], column: [{ type: i0.Input, args: [{ isSignal: true, alias: "column", required: true }] }], position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }], offset: [{ type: i0.Input, args: [{ isSignal: true, alias: "offset", required: false }] }], expandedLevel: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandedLevel", required: false }] }], popoverRef: [{ type: i0.ViewChild, args: [i0.forwardRef(() => PopoverComponent), { isSignal: true }] }] } });
|
|
14098
14231
|
|
|
14099
14232
|
const FILTERS_BREAKPOINT = new InjectionToken('FILTERS_BREAKPOINT', { factory: () => 5 });
|
|
14100
14233
|
|