@sinequa/atomic-angular 0.3.8 → 0.3.15
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.
|
@@ -1544,7 +1544,7 @@ class QueryService {
|
|
|
1544
1544
|
transloco = inject(TranslocoService);
|
|
1545
1545
|
API_URL = `${globalConfig.backendUrl}/api/v1`;
|
|
1546
1546
|
// Represents the last result of a search operation with getResult().
|
|
1547
|
-
result = {};
|
|
1547
|
+
result = signal({}, ...(ngDevMode ? [{ debugName: "result" }] : []));
|
|
1548
1548
|
audit;
|
|
1549
1549
|
/**
|
|
1550
1550
|
* Performs a search query.
|
|
@@ -1558,20 +1558,21 @@ class QueryService {
|
|
|
1558
1558
|
// if audit is set, always use it
|
|
1559
1559
|
// if this.audit is set and audit is not set use this.audit
|
|
1560
1560
|
// if this.audit is not set and audit is not set use default audit
|
|
1561
|
-
const newAudit = audit ?? this.audit ?? { type:
|
|
1561
|
+
const newAudit = audit ?? this.audit ?? { type: "Search_Text", detail: { querytext: q?.text } };
|
|
1562
1562
|
const $auditRecord = { auditEvents: [newAudit] };
|
|
1563
1563
|
this.audit = undefined; // reset this.audit after using it
|
|
1564
|
+
this.result.set({}); // reset results for new search
|
|
1564
1565
|
const { app } = globalConfig;
|
|
1565
1566
|
const currentQuery = q ?? this.queryParamsStore.getQuery();
|
|
1566
1567
|
const query = includeQueryParams ? { ...this.queryParamsStore.getQuery(), ...currentQuery } : currentQuery;
|
|
1567
1568
|
// Check if the search query is empty and if empty searches are allowed
|
|
1568
1569
|
// If not allowed, return an empty result
|
|
1569
1570
|
// basket overrides this rule
|
|
1570
|
-
if (!query.basket && query.action !==
|
|
1571
|
-
const allowEmptySearch = this.appStore.allowEmptySearch(query?.name ||
|
|
1572
|
-
if (allowEmptySearch === false && query?.text ===
|
|
1573
|
-
warn(
|
|
1574
|
-
notify.warning(this.transloco.translate(
|
|
1571
|
+
if (!query.basket && query.action !== "open") {
|
|
1572
|
+
const allowEmptySearch = this.appStore.allowEmptySearch(query?.name || "");
|
|
1573
|
+
if (allowEmptySearch === false && query?.text === "") {
|
|
1574
|
+
warn("QueryService.search: Empty search query is not allowed. Returning empty result.");
|
|
1575
|
+
notify.warning(this.transloco.translate("searches.emptySearch"));
|
|
1575
1576
|
return of({ records: [] });
|
|
1576
1577
|
}
|
|
1577
1578
|
}
|
|
@@ -1580,8 +1581,8 @@ class QueryService {
|
|
|
1580
1581
|
query,
|
|
1581
1582
|
$auditRecord
|
|
1582
1583
|
};
|
|
1583
|
-
return this.http.post(this.API_URL +
|
|
1584
|
-
error(
|
|
1584
|
+
return this.http.post(this.API_URL + "/query", body).pipe(catchError((err) => {
|
|
1585
|
+
error("queryService.getResults failure - error: ", err);
|
|
1585
1586
|
return of({});
|
|
1586
1587
|
}), map((result) => {
|
|
1587
1588
|
// update $hasMore flag
|
|
@@ -1599,19 +1600,21 @@ class QueryService {
|
|
|
1599
1600
|
}
|
|
1600
1601
|
});
|
|
1601
1602
|
return result;
|
|
1602
|
-
}), map(result => {
|
|
1603
|
-
result.records?.map((article) => Object.assign(article, { value: article.title, type:
|
|
1603
|
+
}), map((result) => {
|
|
1604
|
+
result.records?.map((article) => Object.assign(article, { value: article.title, type: "default" }));
|
|
1604
1605
|
return result;
|
|
1605
|
-
}), map(result => {
|
|
1606
|
+
}), map((result) => {
|
|
1606
1607
|
const r = {
|
|
1607
1608
|
...result,
|
|
1608
|
-
nextPage: result.page !== undefined && result.page < Math.ceil(result.rowCount / result.pageSize)
|
|
1609
|
+
nextPage: result.page !== undefined && result.page < Math.ceil(result.rowCount / result.pageSize)
|
|
1610
|
+
? result.page + 1
|
|
1611
|
+
: undefined,
|
|
1609
1612
|
previousPage: result.page !== undefined && result.page > 1 ? result.page - 1 : undefined
|
|
1610
1613
|
};
|
|
1611
1614
|
return r;
|
|
1612
|
-
}), tap(response => {
|
|
1613
|
-
this.result
|
|
1614
|
-
info(
|
|
1615
|
+
}), tap((response) => {
|
|
1616
|
+
this.result.set(response);
|
|
1617
|
+
info("queryService.getResults success - data: ", response);
|
|
1615
1618
|
}));
|
|
1616
1619
|
}
|
|
1617
1620
|
/**
|
|
@@ -1622,7 +1625,7 @@ class QueryService {
|
|
|
1622
1625
|
* @returns An Observable that emits an array of Result objects.
|
|
1623
1626
|
*/
|
|
1624
1627
|
bulkSearch(q, audit) {
|
|
1625
|
-
const { app =
|
|
1628
|
+
const { app = "" } = globalConfig;
|
|
1626
1629
|
const body = {
|
|
1627
1630
|
methods: [],
|
|
1628
1631
|
propagateErrors: true,
|
|
@@ -1630,15 +1633,15 @@ class QueryService {
|
|
|
1630
1633
|
};
|
|
1631
1634
|
for (const query of q) {
|
|
1632
1635
|
body.methods.push({
|
|
1633
|
-
method:
|
|
1636
|
+
method: "query",
|
|
1634
1637
|
app,
|
|
1635
1638
|
query
|
|
1636
1639
|
});
|
|
1637
1640
|
}
|
|
1638
|
-
return this.http.post(this.API_URL +
|
|
1639
|
-
error(
|
|
1641
|
+
return this.http.post(this.API_URL + "/multi", body).pipe(catchError((err) => {
|
|
1642
|
+
error("queryService.bulkSearch failure - error: ", err);
|
|
1640
1643
|
return EMPTY;
|
|
1641
|
-
}), map(response => {
|
|
1644
|
+
}), map((response) => {
|
|
1642
1645
|
// update $hasMore flag
|
|
1643
1646
|
response.results.forEach((result) => {
|
|
1644
1647
|
result.aggregations.forEach((agg) => {
|
|
@@ -1656,11 +1659,13 @@ class QueryService {
|
|
|
1656
1659
|
});
|
|
1657
1660
|
});
|
|
1658
1661
|
return response.results;
|
|
1659
|
-
}), map(results => {
|
|
1660
|
-
results.forEach(result
|
|
1662
|
+
}), map((results) => {
|
|
1663
|
+
results.forEach((result) => {
|
|
1664
|
+
result.records?.map((article) => Object.assign(article, { value: article.title, type: "default" }));
|
|
1665
|
+
});
|
|
1661
1666
|
return results;
|
|
1662
|
-
}), map(results => {
|
|
1663
|
-
return results.map(result => {
|
|
1667
|
+
}), map((results) => {
|
|
1668
|
+
return results.map((result) => {
|
|
1664
1669
|
const r = {
|
|
1665
1670
|
...result,
|
|
1666
1671
|
nextPage: result.page < Math.ceil(result.rowCount / result.pageSize) ? result.page + 1 : undefined,
|
|
@@ -1670,8 +1675,8 @@ class QueryService {
|
|
|
1670
1675
|
});
|
|
1671
1676
|
}),
|
|
1672
1677
|
// map(response => ResultsSchema.parse(response) as T),
|
|
1673
|
-
tap(response => {
|
|
1674
|
-
info(
|
|
1678
|
+
tap((response) => {
|
|
1679
|
+
info("queryService.bulkSearch success - data: ", response);
|
|
1675
1680
|
}));
|
|
1676
1681
|
}
|
|
1677
1682
|
/**
|
|
@@ -1681,21 +1686,21 @@ class QueryService {
|
|
|
1681
1686
|
*/
|
|
1682
1687
|
gotoPage(page) {
|
|
1683
1688
|
const audit = {
|
|
1684
|
-
type:
|
|
1689
|
+
type: "Search_GotoPage",
|
|
1685
1690
|
detail: {
|
|
1686
1691
|
page: page,
|
|
1687
|
-
fromresultid: this.result
|
|
1692
|
+
fromresultid: this.result()?.id ?? null
|
|
1688
1693
|
}
|
|
1689
1694
|
};
|
|
1690
1695
|
this.queryParamsStore.patch({ page }, audit);
|
|
1691
1696
|
}
|
|
1692
1697
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: QueryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1693
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: QueryService, providedIn:
|
|
1698
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: QueryService, providedIn: "root" });
|
|
1694
1699
|
}
|
|
1695
1700
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: QueryService, decorators: [{
|
|
1696
1701
|
type: Injectable,
|
|
1697
1702
|
args: [{
|
|
1698
|
-
providedIn:
|
|
1703
|
+
providedIn: "root"
|
|
1699
1704
|
}]
|
|
1700
1705
|
}] });
|
|
1701
1706
|
|
|
@@ -3443,7 +3448,7 @@ class PreviewService {
|
|
|
3443
3448
|
const query = this.queryParamsStore.getQuery();
|
|
3444
3449
|
try {
|
|
3445
3450
|
const detail = this.getAuditPreviewDetail(article.id, query);
|
|
3446
|
-
const result = this.queryService.result;
|
|
3451
|
+
const result = this.queryService.result();
|
|
3447
3452
|
this.auditService.notifyDocument("Click_ResultLink", article, result || detail.resultid || "", {
|
|
3448
3453
|
querytext: detail.querytext,
|
|
3449
3454
|
querylang: detail.querylang,
|
|
@@ -3573,7 +3578,7 @@ class PreviewService {
|
|
|
3573
3578
|
this.sendMessage({ action: "highlight", highlights });
|
|
3574
3579
|
}
|
|
3575
3580
|
getAuditPreviewDetail(id, q) {
|
|
3576
|
-
const results = this.queryService.result;
|
|
3581
|
+
const results = this.queryService.result();
|
|
3577
3582
|
const queryLanguage = results?.queryAnalysis?.queryLanguage ||
|
|
3578
3583
|
q?.questionLanguage ||
|
|
3579
3584
|
(q.name && this.appStore.getQueryByName(q.name)?.questionLanguage) ||
|
|
@@ -4570,7 +4575,14 @@ function withQueryParamsFeatures() {
|
|
|
4570
4575
|
* @returns Query The constructed query object.
|
|
4571
4576
|
*/
|
|
4572
4577
|
getQuery() {
|
|
4573
|
-
const { filters: allFilters = [], sort, tab, basket, text: queryText = "",
|
|
4578
|
+
const { filters: allFilters = [], sort, tab, basket, text: queryText = "", spellingCorrectionMode } = getState(store);
|
|
4579
|
+
// check if a query name is defined
|
|
4580
|
+
// if not, try to get it from the route data or from the default query in the app store
|
|
4581
|
+
let { name } = getState(store);
|
|
4582
|
+
if (!name) {
|
|
4583
|
+
const routeData = route.snapshot.firstChild?.children[0]?.data;
|
|
4584
|
+
name = routeData ? routeData["queryName"] : appStore.getDefaultQuery()?.name || "";
|
|
4585
|
+
}
|
|
4574
4586
|
let text = queryText;
|
|
4575
4587
|
// remove concepts filters from the query to add them in the query expression
|
|
4576
4588
|
const [conceptsFilters] = allFilters.filter((f) => f.field === "concepts");
|
|
@@ -6742,6 +6754,15 @@ class NavbarTabsComponent {
|
|
|
6742
6754
|
* This works only if tabSearch is enabled in the administration panel.
|
|
6743
6755
|
*/
|
|
6744
6756
|
showCount = input(true, ...(ngDevMode ? [{ debugName: "showCount", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
6757
|
+
/**
|
|
6758
|
+
* The base path for the search routes.
|
|
6759
|
+
* This value is provided as an input property and defaults to "search".
|
|
6760
|
+
*
|
|
6761
|
+
* @remarks
|
|
6762
|
+
* This path is used to find the corresponding route configuration and its children
|
|
6763
|
+
* to populate the tabs in the navbar.
|
|
6764
|
+
*/
|
|
6765
|
+
path = input("search", ...(ngDevMode ? [{ debugName: "path" }] : []));
|
|
6745
6766
|
searchText = computed(() => {
|
|
6746
6767
|
const state = getState(this.queryParamsStore);
|
|
6747
6768
|
return state.text || "";
|
|
@@ -6762,8 +6783,9 @@ class NavbarTabsComponent {
|
|
|
6762
6783
|
}, ...(ngDevMode ? [{ debugName: "currentPath" }] : []));
|
|
6763
6784
|
// create tabs from the search routes
|
|
6764
6785
|
tabs = computed(() => {
|
|
6786
|
+
const result = this.queryService.result();
|
|
6765
6787
|
const r = this.router.config
|
|
6766
|
-
.find((item) => item.path ===
|
|
6788
|
+
.find((item) => item.path === this.path())
|
|
6767
6789
|
?.children?.filter((c) => c.path !== "**")
|
|
6768
6790
|
.map((child) => {
|
|
6769
6791
|
const data = child.data;
|
|
@@ -6771,11 +6793,14 @@ class NavbarTabsComponent {
|
|
|
6771
6793
|
display: data?.display || child.path || "",
|
|
6772
6794
|
wsQueryTab: data?.wsQueryTab || child.path || "",
|
|
6773
6795
|
path: child.path || "",
|
|
6774
|
-
routerLink:
|
|
6796
|
+
routerLink: `/${this.path()}/${child.path}`,
|
|
6775
6797
|
icon: data?.icon || "",
|
|
6776
6798
|
queryName: data?.queryName,
|
|
6799
|
+
// get the count from the last search result if showCount is true and queryName matches
|
|
6777
6800
|
count: this.showCount()
|
|
6778
|
-
?
|
|
6801
|
+
? result.queryName === data?.queryName
|
|
6802
|
+
? result.tabs?.find((tab) => tab.name === (data?.wsQueryTab || child.path))?.count
|
|
6803
|
+
: undefined
|
|
6779
6804
|
: undefined
|
|
6780
6805
|
};
|
|
6781
6806
|
}) ?? [];
|
|
@@ -6787,7 +6812,7 @@ class NavbarTabsComponent {
|
|
|
6787
6812
|
this.drawerStack.closeAll();
|
|
6788
6813
|
}
|
|
6789
6814
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NavbarTabsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
6790
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: NavbarTabsComponent, isStandalone: true, selector: "navbar-tabs", inputs: { showCount: { classPropertyName: "showCount", publicName: "showCount", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
|
|
6815
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: NavbarTabsComponent, isStandalone: true, selector: "navbar-tabs", inputs: { showCount: { classPropertyName: "showCount", publicName: "showCount", isSignal: true, isRequired: false, transformFunction: null }, path: { classPropertyName: "path", publicName: "path", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
|
|
6791
6816
|
<!-- do not display the tabs if there are no tabs -->
|
|
6792
6817
|
@if (tabs().length > 0) {
|
|
6793
6818
|
<div overflowManager class="relative col-span-2 col-start-2 row-start-2 flex" (count)="visibleTabCount.set($event)">
|
|
@@ -6931,7 +6956,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
6931
6956
|
}
|
|
6932
6957
|
`
|
|
6933
6958
|
}]
|
|
6934
|
-
}], propDecorators: { showCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "showCount", required: false }] }] } });
|
|
6959
|
+
}], propDecorators: { showCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "showCount", required: false }] }], path: [{ type: i0.Input, args: [{ isSignal: true, alias: "path", required: false }] }] } });
|
|
6935
6960
|
|
|
6936
6961
|
class NoResultComponent {
|
|
6937
6962
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NoResultComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
@@ -7068,7 +7093,7 @@ class PreviewNavigator {
|
|
|
7068
7093
|
<button
|
|
7069
7094
|
variant="ghost"
|
|
7070
7095
|
size="icon"
|
|
7071
|
-
class="dark:text-
|
|
7096
|
+
class="dark:text-white dark:hover:bg-background/10"
|
|
7072
7097
|
aria-label="Page précédente"
|
|
7073
7098
|
(click)="preview.firstPage()"
|
|
7074
7099
|
[disabled]="isFirst()">
|
|
@@ -7077,19 +7102,19 @@ class PreviewNavigator {
|
|
|
7077
7102
|
<button
|
|
7078
7103
|
variant="ghost"
|
|
7079
7104
|
size="icon"
|
|
7080
|
-
class="dark:text-
|
|
7105
|
+
class="dark:text-white dark:hover:bg-background/10"
|
|
7081
7106
|
aria-label="Page précédente"
|
|
7082
7107
|
(click)="preview.prevPage()"
|
|
7083
7108
|
[disabled]="isFirst()">
|
|
7084
7109
|
<chevron-left />
|
|
7085
7110
|
</button>
|
|
7086
7111
|
|
|
7087
|
-
<div class="dark:text-
|
|
7112
|
+
<div class="dark:text-white inline-flex items-center gap-1 px-1 tabular-nums">
|
|
7088
7113
|
<input
|
|
7089
7114
|
#page
|
|
7090
7115
|
type="text"
|
|
7091
7116
|
decoration="outline"
|
|
7092
|
-
class="dark:hover:bg-background/10 dark:text-
|
|
7117
|
+
class="dark:hover:bg-background/10 dark:text-white dark:border-foreground w-14 py-0.5 text-center invalid:bg-red-200"
|
|
7093
7118
|
[min]="1"
|
|
7094
7119
|
[max]="total() || 1"
|
|
7095
7120
|
[value]="current()"
|
|
@@ -7104,7 +7129,7 @@ class PreviewNavigator {
|
|
|
7104
7129
|
<button
|
|
7105
7130
|
variant="ghost"
|
|
7106
7131
|
size="icon"
|
|
7107
|
-
class="dark:text-
|
|
7132
|
+
class="dark:text-white dark:hover:bg-background/10"
|
|
7108
7133
|
aria-label="Page suivante"
|
|
7109
7134
|
(click)="preview.nextPage()"
|
|
7110
7135
|
[disabled]="isLast()">
|
|
@@ -7113,7 +7138,7 @@ class PreviewNavigator {
|
|
|
7113
7138
|
<button
|
|
7114
7139
|
variant="ghost"
|
|
7115
7140
|
size="icon"
|
|
7116
|
-
class="dark:text-
|
|
7141
|
+
class="dark:text-white dark:hover:bg-background/10"
|
|
7117
7142
|
aria-label="Page suivante"
|
|
7118
7143
|
(click)="preview.lastPage()"
|
|
7119
7144
|
[disabled]="isLast()">
|
|
@@ -7137,7 +7162,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
7137
7162
|
<button
|
|
7138
7163
|
variant="ghost"
|
|
7139
7164
|
size="icon"
|
|
7140
|
-
class="dark:text-
|
|
7165
|
+
class="dark:text-white dark:hover:bg-background/10"
|
|
7141
7166
|
aria-label="Page précédente"
|
|
7142
7167
|
(click)="preview.firstPage()"
|
|
7143
7168
|
[disabled]="isFirst()">
|
|
@@ -7146,19 +7171,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
7146
7171
|
<button
|
|
7147
7172
|
variant="ghost"
|
|
7148
7173
|
size="icon"
|
|
7149
|
-
class="dark:text-
|
|
7174
|
+
class="dark:text-white dark:hover:bg-background/10"
|
|
7150
7175
|
aria-label="Page précédente"
|
|
7151
7176
|
(click)="preview.prevPage()"
|
|
7152
7177
|
[disabled]="isFirst()">
|
|
7153
7178
|
<chevron-left />
|
|
7154
7179
|
</button>
|
|
7155
7180
|
|
|
7156
|
-
<div class="dark:text-
|
|
7181
|
+
<div class="dark:text-white inline-flex items-center gap-1 px-1 tabular-nums">
|
|
7157
7182
|
<input
|
|
7158
7183
|
#page
|
|
7159
7184
|
type="text"
|
|
7160
7185
|
decoration="outline"
|
|
7161
|
-
class="dark:hover:bg-background/10 dark:text-
|
|
7186
|
+
class="dark:hover:bg-background/10 dark:text-white dark:border-foreground w-14 py-0.5 text-center invalid:bg-red-200"
|
|
7162
7187
|
[min]="1"
|
|
7163
7188
|
[max]="total() || 1"
|
|
7164
7189
|
[value]="current()"
|
|
@@ -7173,7 +7198,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
7173
7198
|
<button
|
|
7174
7199
|
variant="ghost"
|
|
7175
7200
|
size="icon"
|
|
7176
|
-
class="dark:text-
|
|
7201
|
+
class="dark:text-white dark:hover:bg-background/10"
|
|
7177
7202
|
aria-label="Page suivante"
|
|
7178
7203
|
(click)="preview.nextPage()"
|
|
7179
7204
|
[disabled]="isLast()">
|
|
@@ -7182,7 +7207,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
7182
7207
|
<button
|
|
7183
7208
|
variant="ghost"
|
|
7184
7209
|
size="icon"
|
|
7185
|
-
class="dark:text-
|
|
7210
|
+
class="dark:text-white dark:hover:bg-background/10"
|
|
7186
7211
|
aria-label="Page suivante"
|
|
7187
7212
|
(click)="preview.lastPage()"
|
|
7188
7213
|
[disabled]="isLast()">
|
|
@@ -10666,6 +10691,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
10666
10691
|
|
|
10667
10692
|
class AggregationComponent {
|
|
10668
10693
|
cn = cn;
|
|
10694
|
+
searchInput = viewChild("searchInput", ...(ngDevMode ? [{ debugName: "searchInput" }] : []));
|
|
10669
10695
|
/* stores */
|
|
10670
10696
|
aggregationsStore = inject(AggregationsStore);
|
|
10671
10697
|
queryParamsStore = inject(QueryParamsStore);
|
|
@@ -10824,6 +10850,14 @@ class AggregationComponent {
|
|
|
10824
10850
|
effect(() => {
|
|
10825
10851
|
sessionStorage.removeItem(`agg-${this.column()}`);
|
|
10826
10852
|
});
|
|
10853
|
+
effect(() => {
|
|
10854
|
+
// focus the search input when expanded
|
|
10855
|
+
if (this.searchInput()?.nativeElement && this.expanded() !== null) {
|
|
10856
|
+
setTimeout(() => {
|
|
10857
|
+
this.searchInput()?.nativeElement.focus();
|
|
10858
|
+
}, 0);
|
|
10859
|
+
}
|
|
10860
|
+
});
|
|
10827
10861
|
effect(async () => {
|
|
10828
10862
|
if (this.debouncedSearchText() === "" || this.aggregation() === null) {
|
|
10829
10863
|
this.suggests.set([]);
|
|
@@ -11268,7 +11302,7 @@ class AggregationComponent {
|
|
|
11268
11302
|
});
|
|
11269
11303
|
}
|
|
11270
11304
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: AggregationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
11271
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: AggregationComponent, isStandalone: true, selector: "Aggregation, aggregation", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: true, transformFunction: null }, column: { classPropertyName: "column", publicName: "column", isSignal: true, isRequired: true, transformFunction: null }, collapsible: { classPropertyName: "collapsible", publicName: "collapsible", isSignal: true, isRequired: false, transformFunction: null }, collapsed: { classPropertyName: "collapsed", publicName: "collapsed", isSignal: true, isRequired: false, transformFunction: null }, searchable: { classPropertyName: "searchable", publicName: "searchable", isSignal: true, isRequired: false, transformFunction: null }, showFiltersCount: { classPropertyName: "showFiltersCount", publicName: "showFiltersCount", isSignal: true, isRequired: false, transformFunction: null }, searchText: { classPropertyName: "searchText", publicName: "searchText", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onSelect: "onSelect", searchText: "searchTextChange" }, host: { properties: { "class": "cn(\"block h-[inherit] max-h-[inherit]\",class())" } }, ngImport: i0, template: "<details (toggle)=\"onToggle($event)\" [attr.open]=\"expanded()\" [attr.name]=\"id()\" class=\"group space-y-2\">\n <summary [class.cursor-pointer]=\"collapsible() && !isEmpty()\" [class.text-muted-foreground]=\"isEmpty()\"\n class=\"m-0 mt-1 flex gap-1 h-8 w-full select-none items-center pl-1 font-semibold\" (click)=\"onHeaderClick($event)\">\n <ng-content select=\"label\">\n @if (aggregation()?.icon) {\n <i class=\"fa-fw {{ aggregation()?.icon }} mr-1\" aria-hidden=\"true\"></i>\n }\n <span class=\"grow\">{{ aggregation()?.display | syslang | transloco }}</span>\n </ng-content>\n\n @if (showFiltersCount() && filtersCount() > 0) {\n <!-- count -->\n <Badge size=\"xs\" class=\"ml-1 pb-0.5\">\n {{ filtersCount() }}\n </Badge>\n }\n <!-- apply filter block -->\n @if (!isCollapsed()) {\n <ButtonGroup>\n @if (hasFilters()) {\n <button variant=\"outline\" size=\"icon\" class=\"size-6\" [attr.title]=\"'filters.clearFilters' | transloco\"\n [attr.aria-label]=\"'filters.clearFilters' | transloco\" (click)=\"$event.stopPropagation(); clear()\">\n <i class=\"fa-fw far fa-filter-circle-xmark\"></i>\n </button>\n }\n @if (selection()) {\n <button variant=\"
|
|
11305
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: AggregationComponent, isStandalone: true, selector: "Aggregation, aggregation", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: true, transformFunction: null }, column: { classPropertyName: "column", publicName: "column", isSignal: true, isRequired: true, transformFunction: null }, collapsible: { classPropertyName: "collapsible", publicName: "collapsible", isSignal: true, isRequired: false, transformFunction: null }, collapsed: { classPropertyName: "collapsed", publicName: "collapsed", isSignal: true, isRequired: false, transformFunction: null }, searchable: { classPropertyName: "searchable", publicName: "searchable", isSignal: true, isRequired: false, transformFunction: null }, showFiltersCount: { classPropertyName: "showFiltersCount", publicName: "showFiltersCount", isSignal: true, isRequired: false, transformFunction: null }, searchText: { classPropertyName: "searchText", publicName: "searchText", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onSelect: "onSelect", searchText: "searchTextChange" }, host: { properties: { "class": "cn(\"block h-[inherit] max-h-[inherit]\",class())" } }, viewQueries: [{ propertyName: "searchInput", first: true, predicate: ["searchInput"], descendants: true, isSignal: true }], ngImport: i0, template: "<details (toggle)=\"onToggle($event)\" [attr.open]=\"expanded()\" [attr.name]=\"id()\" class=\"group space-y-2\">\n <summary [class.cursor-pointer]=\"collapsible() && !isEmpty()\" [class.text-muted-foreground]=\"isEmpty()\"\n class=\"m-0 mt-1 flex gap-1 h-8 w-full select-none items-center pl-1 font-semibold\" (click)=\"onHeaderClick($event)\">\n <ng-content select=\"label\">\n @if (aggregation()?.icon) {\n <i class=\"fa-fw {{ aggregation()?.icon }} mr-1\" aria-hidden=\"true\"></i>\n }\n <span class=\"grow\">{{ aggregation()?.display | syslang | transloco }}</span>\n </ng-content>\n\n @if (showFiltersCount() && filtersCount() > 0) {\n <!-- count -->\n <Badge size=\"xs\" class=\"ml-1 pb-0.5\">\n {{ filtersCount() }}\n </Badge>\n }\n <!-- apply filter block -->\n @if (!isCollapsed()) {\n <ButtonGroup>\n @if (hasFilters()) {\n <button variant=\"outline\" size=\"icon\" class=\"size-6\" [attr.title]=\"'filters.clearFilters' | transloco\"\n [attr.aria-label]=\"'filters.clearFilters' | transloco\" (click)=\"$event.stopPropagation(); clear()\">\n <i class=\"fa-fw far fa-filter-circle-xmark\"></i>\n </button>\n }\n @if (selection()) {\n <button variant=\"primary\" size=\"xs\" [attr.title]=\"'filters.applyFilters' | transloco\"\n [attr.aria-label]=\"'filters.applyFilters' | transloco\" (click)=\"$event.stopPropagation(); apply()\" class=\"px-1 h-4\">\n <FilterIcon class=\"size-4\"/>\n {{ 'filters.apply' | transloco }}\n </button>\n }\n\n <!-- select / unselect all -->\n @if (isAllSelected()) {\n <button variant=\"outline\" size=\"icon\" class=\"size-6\" [attr.title]=\"'filters.unselectAllFilters' | transloco\"\n [attr.aria-label]=\"'filters.unselectAllFilters' | transloco\" (click)=\"$event.stopPropagation(); unselectAll()\">\n <i class=\"fa-fw far fa-check-square\"></i>\n </button>\n } @else {\n <button variant=\"outline\" size=\"icon\" class=\"size-6\" [attr.title]=\"'filters.selectAllFilters' | transloco\"\n [attr.aria-label]=\"'filters.selectAllFilters' | transloco\" (click)=\"$event.stopPropagation(); selectAll()\">\n <i class=\"fa-fw far fa-square\"></i>\n </button>\n }\n </ButtonGroup>\n }\n\n @if (collapsible()) {\n <button variant=\"none\" title=\"Open/Close\"\n class=\"cursor-pointer [&_svg]:transition-transform [&_svg]:duration-150 group-open:[&_svg]:rotate-90\">\n <chevronright />\n </button>\n }\n </summary>\n\n <!-- content wrapper -->\n @if (aggregation()?.searchable && items().length) {\n <InputGroup class=\"group/item mt-1\">\n <input #searchInput input-group id=\"aggregation-input-{{column()}}\" type=\"text\" [attr.placeholder]=\"'search' | transloco\" [(ngModel)]=\"searchText\" class=\"mt-1\"/>\n <InputGroupAddon>\n <SearchIcon class=\"text-foreground size-4 rotate-0 transition-[rotate] duration-500 group-focus-within/item:rotate-90\" />\n </InputGroupAddon>\n </InputGroup>\n }\n\n <ul class=\"scrollbar-thin max-h-[calc(var(--height,100%)-100px)] snap-y snap-start overflow-auto\" role=\"list\"\n [attr.aria-label]=\"aggregation()?.display | syslang | transloco\">\n @for (item of items(); track $index) {\n <AggregationItem [node]=\"item\" [path]=\"[]\" [field]=\"aggregation()?.column\" (onSelect)=\"select()\"\n (onOpen)=\"open($event)\" (onFilter)=\"quickFilter($event)\" />\n }\n </ul>\n @if (aggregation()?.$hasMore && this.searchedItems().length === 0) {\n <button decoration=\"underline\" class=\"mt-1 flex w-full justify-center\" [attr.aria-label]=\"'loadMore' | transloco\"\n (click)=\"loadMore()\">\n {{ 'loadMore' | transloco }}\n </button>\n }\n</details>\n", styles: ["AggregationItem:has(+AggregationItem){margin-bottom:var(--agg-item-gap, 0)}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { 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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: ButtonComponent, selector: "button,a[role=\"button\"]", inputs: ["class", "variant", "decoration", "size"] }, { kind: "component", type: AggregationItemComponent, selector: "aggregation-item, AggregationItem, aggregationitem", inputs: ["node", "path", "field"], outputs: ["onSelect", "onOpen", "onFilter"] }, { kind: "directive", type: BadgeComponent, selector: "badge, Badge", inputs: ["class", "variant"] }, { kind: "component", type: ChevronRightIcon, selector: "chevron-right, ChevronRight, chevronright, ChevronRightIcon", inputs: ["class"] }, { kind: "directive", type: ButtonGroup, selector: "button-group, ButtonGroup", inputs: ["class", "orientation"] }, { kind: "directive", type: InputGroupInput, selector: "input[input-group]", inputs: ["class", "type", "placeholder", "disabled"] }, { kind: "directive", type: InputGroupComponent, selector: "input-group, inputgroup, InputGroup", inputs: ["class"] }, { kind: "directive", type: InputGroupAddonComponent, selector: "input-group-addon, inputgroupaddon, InputGroupAddon", inputs: ["class", "align"] }, { kind: "component", type: SearchIcon, selector: "SearchIcon", inputs: ["class"] }, { kind: "component", type: FilterIcon, selector: "filter-icon, FilterIcon", inputs: ["class"] }, { kind: "pipe", type: SyslangPipe, name: "syslang" }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }] });
|
|
11272
11306
|
}
|
|
11273
11307
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: AggregationComponent, decorators: [{
|
|
11274
11308
|
type: Component,
|
|
@@ -11289,8 +11323,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
11289
11323
|
FilterIcon
|
|
11290
11324
|
], standalone: true, host: {
|
|
11291
11325
|
"[class]": 'cn("block h-[inherit] max-h-[inherit]",class())'
|
|
11292
|
-
}, template: "<details (toggle)=\"onToggle($event)\" [attr.open]=\"expanded()\" [attr.name]=\"id()\" class=\"group space-y-2\">\n <summary [class.cursor-pointer]=\"collapsible() && !isEmpty()\" [class.text-muted-foreground]=\"isEmpty()\"\n class=\"m-0 mt-1 flex gap-1 h-8 w-full select-none items-center pl-1 font-semibold\" (click)=\"onHeaderClick($event)\">\n <ng-content select=\"label\">\n @if (aggregation()?.icon) {\n <i class=\"fa-fw {{ aggregation()?.icon }} mr-1\" aria-hidden=\"true\"></i>\n }\n <span class=\"grow\">{{ aggregation()?.display | syslang | transloco }}</span>\n </ng-content>\n\n @if (showFiltersCount() && filtersCount() > 0) {\n <!-- count -->\n <Badge size=\"xs\" class=\"ml-1 pb-0.5\">\n {{ filtersCount() }}\n </Badge>\n }\n <!-- apply filter block -->\n @if (!isCollapsed()) {\n <ButtonGroup>\n @if (hasFilters()) {\n <button variant=\"outline\" size=\"icon\" class=\"size-6\" [attr.title]=\"'filters.clearFilters' | transloco\"\n [attr.aria-label]=\"'filters.clearFilters' | transloco\" (click)=\"$event.stopPropagation(); clear()\">\n <i class=\"fa-fw far fa-filter-circle-xmark\"></i>\n </button>\n }\n @if (selection()) {\n <button variant=\"
|
|
11293
|
-
}], ctorParameters: () => [], propDecorators: { 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"] }], 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"] }] } });
|
|
11326
|
+
}, template: "<details (toggle)=\"onToggle($event)\" [attr.open]=\"expanded()\" [attr.name]=\"id()\" class=\"group space-y-2\">\n <summary [class.cursor-pointer]=\"collapsible() && !isEmpty()\" [class.text-muted-foreground]=\"isEmpty()\"\n class=\"m-0 mt-1 flex gap-1 h-8 w-full select-none items-center pl-1 font-semibold\" (click)=\"onHeaderClick($event)\">\n <ng-content select=\"label\">\n @if (aggregation()?.icon) {\n <i class=\"fa-fw {{ aggregation()?.icon }} mr-1\" aria-hidden=\"true\"></i>\n }\n <span class=\"grow\">{{ aggregation()?.display | syslang | transloco }}</span>\n </ng-content>\n\n @if (showFiltersCount() && filtersCount() > 0) {\n <!-- count -->\n <Badge size=\"xs\" class=\"ml-1 pb-0.5\">\n {{ filtersCount() }}\n </Badge>\n }\n <!-- apply filter block -->\n @if (!isCollapsed()) {\n <ButtonGroup>\n @if (hasFilters()) {\n <button variant=\"outline\" size=\"icon\" class=\"size-6\" [attr.title]=\"'filters.clearFilters' | transloco\"\n [attr.aria-label]=\"'filters.clearFilters' | transloco\" (click)=\"$event.stopPropagation(); clear()\">\n <i class=\"fa-fw far fa-filter-circle-xmark\"></i>\n </button>\n }\n @if (selection()) {\n <button variant=\"primary\" size=\"xs\" [attr.title]=\"'filters.applyFilters' | transloco\"\n [attr.aria-label]=\"'filters.applyFilters' | transloco\" (click)=\"$event.stopPropagation(); apply()\" class=\"px-1 h-4\">\n <FilterIcon class=\"size-4\"/>\n {{ 'filters.apply' | transloco }}\n </button>\n }\n\n <!-- select / unselect all -->\n @if (isAllSelected()) {\n <button variant=\"outline\" size=\"icon\" class=\"size-6\" [attr.title]=\"'filters.unselectAllFilters' | transloco\"\n [attr.aria-label]=\"'filters.unselectAllFilters' | transloco\" (click)=\"$event.stopPropagation(); unselectAll()\">\n <i class=\"fa-fw far fa-check-square\"></i>\n </button>\n } @else {\n <button variant=\"outline\" size=\"icon\" class=\"size-6\" [attr.title]=\"'filters.selectAllFilters' | transloco\"\n [attr.aria-label]=\"'filters.selectAllFilters' | transloco\" (click)=\"$event.stopPropagation(); selectAll()\">\n <i class=\"fa-fw far fa-square\"></i>\n </button>\n }\n </ButtonGroup>\n }\n\n @if (collapsible()) {\n <button variant=\"none\" title=\"Open/Close\"\n class=\"cursor-pointer [&_svg]:transition-transform [&_svg]:duration-150 group-open:[&_svg]:rotate-90\">\n <chevronright />\n </button>\n }\n </summary>\n\n <!-- content wrapper -->\n @if (aggregation()?.searchable && items().length) {\n <InputGroup class=\"group/item mt-1\">\n <input #searchInput input-group id=\"aggregation-input-{{column()}}\" type=\"text\" [attr.placeholder]=\"'search' | transloco\" [(ngModel)]=\"searchText\" class=\"mt-1\"/>\n <InputGroupAddon>\n <SearchIcon class=\"text-foreground size-4 rotate-0 transition-[rotate] duration-500 group-focus-within/item:rotate-90\" />\n </InputGroupAddon>\n </InputGroup>\n }\n\n <ul class=\"scrollbar-thin max-h-[calc(var(--height,100%)-100px)] snap-y snap-start overflow-auto\" role=\"list\"\n [attr.aria-label]=\"aggregation()?.display | syslang | transloco\">\n @for (item of items(); track $index) {\n <AggregationItem [node]=\"item\" [path]=\"[]\" [field]=\"aggregation()?.column\" (onSelect)=\"select()\"\n (onOpen)=\"open($event)\" (onFilter)=\"quickFilter($event)\" />\n }\n </ul>\n @if (aggregation()?.$hasMore && this.searchedItems().length === 0) {\n <button decoration=\"underline\" class=\"mt-1 flex w-full justify-center\" [attr.aria-label]=\"'loadMore' | transloco\"\n (click)=\"loadMore()\">\n {{ 'loadMore' | transloco }}\n </button>\n }\n</details>\n", styles: ["AggregationItem:has(+AggregationItem){margin-bottom:var(--agg-item-gap, 0)}\n"] }]
|
|
11327
|
+
}], ctorParameters: () => [], propDecorators: { 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"] }], 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"] }] } });
|
|
11294
11328
|
|
|
11295
11329
|
/**
|
|
11296
11330
|
* Injection token that indicates whether custom date ranges are allowed.
|
|
@@ -11627,7 +11661,8 @@ class FilterButtonComponent {
|
|
|
11627
11661
|
[variant]="variant()"
|
|
11628
11662
|
class="group-open:border-foreground/50 group-open:border"
|
|
11629
11663
|
[attr.data-disabled]="filter().disabled"
|
|
11630
|
-
[disabled]="filter().disabled || null"
|
|
11664
|
+
[disabled]="filter().disabled || null"
|
|
11665
|
+
>
|
|
11631
11666
|
<!-- display the filter icon if set -->
|
|
11632
11667
|
@if (filter().icon) {
|
|
11633
11668
|
<i class="fa-fw {{ filter().icon }} " aria-hidden="true"></i>
|
|
@@ -11651,11 +11686,12 @@ class FilterButtonComponent {
|
|
|
11651
11686
|
}
|
|
11652
11687
|
</button>
|
|
11653
11688
|
|
|
11654
|
-
<PopoverContent
|
|
11689
|
+
<PopoverContent #contentRef="popoverContent"
|
|
11655
11690
|
class="min-w-fit w-max max-w-[90vw]"
|
|
11656
11691
|
[position]="position()"
|
|
11657
11692
|
[offset]="offset()"
|
|
11658
11693
|
>
|
|
11694
|
+
@if(contentRef.isVisible) {
|
|
11659
11695
|
@if (isDate(filter().column)) {
|
|
11660
11696
|
<DateFilter
|
|
11661
11697
|
class="*:details-content:[--height:19lh] w-max max-w-80"
|
|
@@ -11671,9 +11707,10 @@ class FilterButtonComponent {
|
|
|
11671
11707
|
[column]="filter().column"
|
|
11672
11708
|
id="filter-{{ filter().column }}" />
|
|
11673
11709
|
}
|
|
11710
|
+
}
|
|
11674
11711
|
</PopoverContent>
|
|
11675
11712
|
</Popover>
|
|
11676
|
-
`, isInline: true, dependencies: [{ kind: "directive", type: ButtonComponent, selector: "button,a[role=\"button\"]", inputs: ["class", "variant", "decoration", "size"] }, { kind: "component", type: PopoverComponent, selector: "popover, Popover", inputs: ["disabled", "closeOnScroll"], outputs: ["closed"] }, { kind: "directive", type: PopoverContentComponent, selector: "popover-content, PopoverContent, popovercontent", inputs: ["position", "keepOpen", "class", "offset"] }, { kind: "component", type: AggregationComponent, selector: "Aggregation, aggregation", inputs: ["class", "id", "name", "column", "collapsible", "collapsed", "searchable", "showFiltersCount", "searchText"], outputs: ["onSelect", "searchTextChange"] }, { kind: "component", type: DateComponent, selector: "date-filter,DateFilter", inputs: ["title", "displayEmptyDistributionIntervals"] }, { kind: "directive", type: BadgeComponent, selector: "badge, Badge", inputs: ["class", "variant"] }, { kind: "pipe", type: OperatorPipe, name: "operator" }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }, { kind: "pipe", type: SyslangPipe, name: "syslang" }] });
|
|
11713
|
+
`, isInline: true, dependencies: [{ kind: "directive", type: ButtonComponent, selector: "button,a[role=\"button\"]", inputs: ["class", "variant", "decoration", "size"] }, { kind: "component", type: PopoverComponent, selector: "popover, Popover", inputs: ["disabled", "closeOnScroll"], outputs: ["closed"] }, { kind: "directive", type: PopoverContentComponent, selector: "popover-content, PopoverContent, popovercontent", inputs: ["position", "keepOpen", "class", "offset"], exportAs: ["popoverContent"] }, { kind: "component", type: AggregationComponent, selector: "Aggregation, aggregation", inputs: ["class", "id", "name", "column", "collapsible", "collapsed", "searchable", "showFiltersCount", "searchText"], outputs: ["onSelect", "searchTextChange"] }, { kind: "component", type: DateComponent, selector: "date-filter,DateFilter", inputs: ["title", "displayEmptyDistributionIntervals"] }, { kind: "directive", type: BadgeComponent, selector: "badge, Badge", inputs: ["class", "variant"] }, { kind: "pipe", type: OperatorPipe, name: "operator" }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }, { kind: "pipe", type: SyslangPipe, name: "syslang" }] });
|
|
11677
11714
|
}
|
|
11678
11715
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: FilterButtonComponent, decorators: [{
|
|
11679
11716
|
type: Component,
|
|
@@ -11697,7 +11734,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
11697
11734
|
[variant]="variant()"
|
|
11698
11735
|
class="group-open:border-foreground/50 group-open:border"
|
|
11699
11736
|
[attr.data-disabled]="filter().disabled"
|
|
11700
|
-
[disabled]="filter().disabled || null"
|
|
11737
|
+
[disabled]="filter().disabled || null"
|
|
11738
|
+
>
|
|
11701
11739
|
<!-- display the filter icon if set -->
|
|
11702
11740
|
@if (filter().icon) {
|
|
11703
11741
|
<i class="fa-fw {{ filter().icon }} " aria-hidden="true"></i>
|
|
@@ -11721,11 +11759,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
11721
11759
|
}
|
|
11722
11760
|
</button>
|
|
11723
11761
|
|
|
11724
|
-
<PopoverContent
|
|
11762
|
+
<PopoverContent #contentRef="popoverContent"
|
|
11725
11763
|
class="min-w-fit w-max max-w-[90vw]"
|
|
11726
11764
|
[position]="position()"
|
|
11727
11765
|
[offset]="offset()"
|
|
11728
11766
|
>
|
|
11767
|
+
@if(contentRef.isVisible) {
|
|
11729
11768
|
@if (isDate(filter().column)) {
|
|
11730
11769
|
<DateFilter
|
|
11731
11770
|
class="*:details-content:[--height:19lh] w-max max-w-80"
|
|
@@ -11741,6 +11780,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
11741
11780
|
[column]="filter().column"
|
|
11742
11781
|
id="filter-{{ filter().column }}" />
|
|
11743
11782
|
}
|
|
11783
|
+
}
|
|
11744
11784
|
</PopoverContent>
|
|
11745
11785
|
</Popover>
|
|
11746
11786
|
`,
|
|
@@ -11928,11 +11968,13 @@ class MoreButtonComponent {
|
|
|
11928
11968
|
}
|
|
11929
11969
|
</button>
|
|
11930
11970
|
|
|
11931
|
-
<PopoverContent [position]="position()" class="min-w-max">
|
|
11971
|
+
<PopoverContent #contentRef="popoverContent" [position]="position()" class="min-w-max">
|
|
11972
|
+
@if(contentRef.isVisible) {
|
|
11932
11973
|
<More [count]="count()" [includedFilters]="includedFilters()" [excludedFilters]="excludedFilters()" [aggregations]="aggregations()" class="block h-full w-full max-w-80 [--height:55vh] min-w-40 overflow-hidden" />
|
|
11974
|
+
}
|
|
11933
11975
|
</PopoverContent>
|
|
11934
11976
|
</Popover>
|
|
11935
|
-
`, isInline: true, dependencies: [{ kind: "directive", type: ButtonComponent, selector: "button,a[role=\"button\"]", inputs: ["class", "variant", "decoration", "size"] }, { kind: "component", type: PopoverComponent, selector: "popover, Popover", inputs: ["disabled", "closeOnScroll"], outputs: ["closed"] }, { kind: "directive", type: PopoverContentComponent, selector: "popover-content, PopoverContent, popovercontent", inputs: ["position", "keepOpen", "class", "offset"] }, { kind: "component", type: MoreComponent, selector: "more, More", inputs: ["count", "includedFilters", "excludedFilters", "aggregations"] }, { kind: "directive", type: BadgeComponent, selector: "badge, Badge", inputs: ["class", "variant"] }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }] });
|
|
11977
|
+
`, isInline: true, dependencies: [{ kind: "directive", type: ButtonComponent, selector: "button,a[role=\"button\"]", inputs: ["class", "variant", "decoration", "size"] }, { kind: "component", type: PopoverComponent, selector: "popover, Popover", inputs: ["disabled", "closeOnScroll"], outputs: ["closed"] }, { kind: "directive", type: PopoverContentComponent, selector: "popover-content, PopoverContent, popovercontent", inputs: ["position", "keepOpen", "class", "offset"], exportAs: ["popoverContent"] }, { kind: "component", type: MoreComponent, selector: "more, More", inputs: ["count", "includedFilters", "excludedFilters", "aggregations"] }, { kind: "directive", type: BadgeComponent, selector: "badge, Badge", inputs: ["class", "variant"] }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }] });
|
|
11936
11978
|
}
|
|
11937
11979
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: MoreButtonComponent, decorators: [{
|
|
11938
11980
|
type: Component,
|
|
@@ -11956,8 +11998,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
11956
11998
|
}
|
|
11957
11999
|
</button>
|
|
11958
12000
|
|
|
11959
|
-
<PopoverContent [position]="position()" class="min-w-max">
|
|
12001
|
+
<PopoverContent #contentRef="popoverContent" [position]="position()" class="min-w-max">
|
|
12002
|
+
@if(contentRef.isVisible) {
|
|
11960
12003
|
<More [count]="count()" [includedFilters]="includedFilters()" [excludedFilters]="excludedFilters()" [aggregations]="aggregations()" class="block h-full w-full max-w-80 [--height:55vh] min-w-40 overflow-hidden" />
|
|
12004
|
+
}
|
|
11961
12005
|
</PopoverContent>
|
|
11962
12006
|
</Popover>
|
|
11963
12007
|
`
|
|
@@ -12412,22 +12456,26 @@ class MultiSelectLabelsComponent {
|
|
|
12412
12456
|
labelsField = input(...(ngDevMode ? [undefined, { debugName: "labelsField" }] : []));
|
|
12413
12457
|
anchor = signal(`--${guid()}`, ...(ngDevMode ? [{ debugName: "anchor" }] : []));
|
|
12414
12458
|
suggestedLabels = signal([], ...(ngDevMode ? [{ debugName: "suggestedLabels" }] : []));
|
|
12415
|
-
labelInput = model(
|
|
12459
|
+
labelInput = model("", ...(ngDevMode ? [{ debugName: "labelInput" }] : []));
|
|
12416
12460
|
debouncedLabelInput = debouncedSignal(this.labelInput, DEBOUNCE_DELAY);
|
|
12417
|
-
popover = viewChild(
|
|
12461
|
+
popover = viewChild("LabelsPopover", ...(ngDevMode ? [{ debugName: "popover" }] : []));
|
|
12418
12462
|
popoverElement = computed(() => this.popover()?.nativeElement, ...(ngDevMode ? [{ debugName: "popoverElement" }] : []));
|
|
12419
12463
|
labels = signal([], ...(ngDevMode ? [{ debugName: "labels" }] : []));
|
|
12464
|
+
hasError = signal(false, ...(ngDevMode ? [{ debugName: "hasError" }] : []));
|
|
12420
12465
|
id = signal(`labels-form-${guid()}`, ...(ngDevMode ? [{ debugName: "id" }] : []));
|
|
12421
12466
|
constructor() {
|
|
12422
12467
|
afterEveryRender(() => {
|
|
12423
12468
|
this.popoverElement().style.positionAnchor = this.anchor();
|
|
12424
12469
|
});
|
|
12425
12470
|
effect(() => {
|
|
12426
|
-
|
|
12471
|
+
const article = this.article();
|
|
12472
|
+
const labelsField = this.labelsField();
|
|
12473
|
+
if (!article)
|
|
12427
12474
|
return;
|
|
12428
|
-
if (!
|
|
12475
|
+
if (!labelsField)
|
|
12429
12476
|
return;
|
|
12430
|
-
|
|
12477
|
+
const labels = article[labelsField];
|
|
12478
|
+
this.labels.set(labels || []);
|
|
12431
12479
|
});
|
|
12432
12480
|
effect(() => {
|
|
12433
12481
|
this.fetchLabels(this.debouncedLabelInput(), this.isPublic());
|
|
@@ -12445,14 +12493,14 @@ class MultiSelectLabelsComponent {
|
|
|
12445
12493
|
event.stopImmediatePropagation();
|
|
12446
12494
|
if (this.labelInput().length === 0)
|
|
12447
12495
|
return;
|
|
12448
|
-
if (event.key ===
|
|
12496
|
+
if (event.key === "Enter") {
|
|
12449
12497
|
this.addLabel(this.labelInput(), this.isPublic());
|
|
12450
|
-
this.labelInput.set(
|
|
12498
|
+
this.labelInput.set("");
|
|
12451
12499
|
}
|
|
12452
12500
|
}
|
|
12453
12501
|
async fetchLabels(text, isPublic) {
|
|
12454
12502
|
const labels = (await withFetch(() => fetchLabels(text, isPublic), this.injector)) || [];
|
|
12455
|
-
const unappliedLabels = labels.filter(label => !this.labels().some(l => l === label));
|
|
12503
|
+
const unappliedLabels = labels.filter((label) => !this.labels().some((l) => l === label));
|
|
12456
12504
|
this.suggestedLabels.set(unappliedLabels);
|
|
12457
12505
|
unappliedLabels.length ? this.popoverElement().showPopover() : this.popoverElement().hidePopover();
|
|
12458
12506
|
}
|
|
@@ -12470,12 +12518,21 @@ class MultiSelectLabelsComponent {
|
|
|
12470
12518
|
* @returns A promise that resolves once the label has been added and the article updated.
|
|
12471
12519
|
*/
|
|
12472
12520
|
async addLabel(label, isPublic) {
|
|
12473
|
-
|
|
12474
|
-
this.
|
|
12475
|
-
|
|
12476
|
-
|
|
12477
|
-
|
|
12478
|
-
|
|
12521
|
+
this.hasError.set(false);
|
|
12522
|
+
const article = this.article();
|
|
12523
|
+
if (!article)
|
|
12524
|
+
return;
|
|
12525
|
+
try {
|
|
12526
|
+
await labels.add([label], [article.id], isPublic);
|
|
12527
|
+
const currentLabels = this.labels();
|
|
12528
|
+
this.labels.set([...currentLabels, label]);
|
|
12529
|
+
this.updateArticleWithLabels();
|
|
12530
|
+
this.labelInput.set("");
|
|
12531
|
+
this.suggestedLabels.set([]);
|
|
12532
|
+
}
|
|
12533
|
+
catch {
|
|
12534
|
+
this.hasError.set(true);
|
|
12535
|
+
}
|
|
12479
12536
|
}
|
|
12480
12537
|
/**
|
|
12481
12538
|
* Removes a label from the current list of labels and updates the associated article.
|
|
@@ -12485,9 +12542,18 @@ class MultiSelectLabelsComponent {
|
|
|
12485
12542
|
* @returns A promise that resolves once the label is removed and the article is updated.
|
|
12486
12543
|
*/
|
|
12487
12544
|
async removeLabel(label, isPublic) {
|
|
12488
|
-
this.
|
|
12489
|
-
|
|
12490
|
-
|
|
12545
|
+
this.hasError.set(false);
|
|
12546
|
+
const article = this.article();
|
|
12547
|
+
if (!article)
|
|
12548
|
+
return;
|
|
12549
|
+
try {
|
|
12550
|
+
await labels.remove([label], [article.id], isPublic);
|
|
12551
|
+
this.labels.set(this.labels().filter((l) => l !== label));
|
|
12552
|
+
this.updateArticleWithLabels();
|
|
12553
|
+
}
|
|
12554
|
+
catch {
|
|
12555
|
+
this.hasError.set(true);
|
|
12556
|
+
}
|
|
12491
12557
|
}
|
|
12492
12558
|
/**
|
|
12493
12559
|
* Updates the article object by assigning the current labels to the specified labels field.
|
|
@@ -12499,13 +12565,18 @@ class MultiSelectLabelsComponent {
|
|
|
12499
12565
|
* Ensure that `this.article`, `this.labelsField`, and `this.labels` return valid values
|
|
12500
12566
|
* before invoking this method to avoid runtime errors.
|
|
12501
12567
|
*
|
|
12502
|
-
* @throws {TypeError} If `this.article` or `this.labelsField` returns `undefined`.
|
|
12503
12568
|
*/
|
|
12504
12569
|
updateArticleWithLabels() {
|
|
12505
|
-
|
|
12570
|
+
const article = this.article();
|
|
12571
|
+
const labelsField = this.labelsField();
|
|
12572
|
+
if (!article)
|
|
12573
|
+
return;
|
|
12574
|
+
if (!labelsField)
|
|
12575
|
+
return;
|
|
12576
|
+
article[labelsField] = this.labels();
|
|
12506
12577
|
}
|
|
12507
12578
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: MultiSelectLabelsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
12508
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: MultiSelectLabelsComponent, isStandalone: true, selector: "multiselect-labels, multiselectlabels, MultiSelectLabels", inputs: { article: { classPropertyName: "article", publicName: "article", isSignal: true, isRequired: false, transformFunction: null }, isPublic: { classPropertyName: "isPublic", publicName: "isPublic", isSignal: true, isRequired: false, transformFunction: null }, allowModification: { classPropertyName: "allowModification", publicName: "allowModification", isSignal: true, isRequired: false, transformFunction: null }, labelsField: { classPropertyName: "labelsField", publicName: "labelsField", isSignal: true, isRequired: false, transformFunction: null }, labelInput: { classPropertyName: "labelInput", publicName: "labelInput", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { article: "articleChange", labelInput: "labelInputChange" }, viewQueries: [{ propertyName: "popover", first: true, predicate: ["LabelsPopover"], descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
12579
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: MultiSelectLabelsComponent, isStandalone: true, selector: "multiselect-labels, multiselectlabels, MultiSelectLabels", inputs: { article: { classPropertyName: "article", publicName: "article", isSignal: true, isRequired: false, transformFunction: null }, isPublic: { classPropertyName: "isPublic", publicName: "isPublic", isSignal: true, isRequired: false, transformFunction: null }, allowModification: { classPropertyName: "allowModification", publicName: "allowModification", isSignal: true, isRequired: false, transformFunction: null }, labelsField: { classPropertyName: "labelsField", publicName: "labelsField", isSignal: true, isRequired: false, transformFunction: null }, labelInput: { classPropertyName: "labelInput", publicName: "labelInput", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { article: "articleChange", labelInput: "labelInputChange" }, providers: [provideTranslocoScope("labels")], viewQueries: [{ propertyName: "popover", first: true, predicate: ["LabelsPopover"], descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
12509
12580
|
<div class="anchor" [ngStyle]="{ 'anchor-name': anchor() }">
|
|
12510
12581
|
<label [htmlFor]="id()" class="font-semibold">{{ (isPublic() ? 'labels.publicLabels' : 'labels.privateLabels') | transloco }}</label>
|
|
12511
12582
|
<input
|
|
@@ -12542,11 +12613,16 @@ class MultiSelectLabelsComponent {
|
|
|
12542
12613
|
</Badge>
|
|
12543
12614
|
}
|
|
12544
12615
|
</div>
|
|
12616
|
+
@if (hasError()) {
|
|
12617
|
+
<div class="p-4 w-full bg-destructive/20 border-destructive">
|
|
12618
|
+
{{ 'labels.error' | transloco }}
|
|
12619
|
+
</div>
|
|
12620
|
+
}
|
|
12545
12621
|
`, isInline: true, styles: [".anchor:has(.popover:popover-open){z-index:var(--z-menu, 1000);border-radius:var(--radius) var(--radius) 0 0}.anchor .popover::backdrop{background-color:transparent;-webkit-backdrop-filter:none;backdrop-filter:none}.popover{width:anchor-size(width);top:anchor(bottom);left:anchor(left)}@supports (-moz-appearance: none){.popover{margin:calc(33.3333333333vh + 30px) 25vw;width:50vw}}@supports (background: -webkit-named-image(i)){.popover{margin:calc(33.3333333333vh + 30px) 25vw;width:50vw}}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { 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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { 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\"]", inputs: ["class", "variant", "decoration"] }, { kind: "directive", type: BadgeComponent, selector: "badge, Badge", inputs: ["class", "variant"] }, { kind: "directive", type: ListItemComponent, selector: "[role=\"listitem\"], [role=\"option\"]", inputs: ["class", "variant", "decoration"] }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }] });
|
|
12546
12622
|
}
|
|
12547
12623
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: MultiSelectLabelsComponent, decorators: [{
|
|
12548
12624
|
type: Component,
|
|
12549
|
-
args: [{ selector:
|
|
12625
|
+
args: [{ selector: "multiselect-labels, multiselectlabels, MultiSelectLabels", providers: [provideTranslocoScope("labels")], standalone: true, imports: [FormsModule, NgStyle, TranslocoPipe, InputComponent, BadgeComponent, ListItemComponent], template: `
|
|
12550
12626
|
<div class="anchor" [ngStyle]="{ 'anchor-name': anchor() }">
|
|
12551
12627
|
<label [htmlFor]="id()" class="font-semibold">{{ (isPublic() ? 'labels.publicLabels' : 'labels.privateLabels') | transloco }}</label>
|
|
12552
12628
|
<input
|
|
@@ -12583,8 +12659,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
12583
12659
|
</Badge>
|
|
12584
12660
|
}
|
|
12585
12661
|
</div>
|
|
12662
|
+
@if (hasError()) {
|
|
12663
|
+
<div class="p-4 w-full bg-destructive/20 border-destructive">
|
|
12664
|
+
{{ 'labels.error' | transloco }}
|
|
12665
|
+
</div>
|
|
12666
|
+
}
|
|
12586
12667
|
`, styles: [".anchor:has(.popover:popover-open){z-index:var(--z-menu, 1000);border-radius:var(--radius) var(--radius) 0 0}.anchor .popover::backdrop{background-color:transparent;-webkit-backdrop-filter:none;backdrop-filter:none}.popover{width:anchor-size(width);top:anchor(bottom);left:anchor(left)}@supports (-moz-appearance: none){.popover{margin:calc(33.3333333333vh + 30px) 25vw;width:50vw}}@supports (background: -webkit-named-image(i)){.popover{margin:calc(33.3333333333vh + 30px) 25vw;width:50vw}}\n"] }]
|
|
12587
|
-
}], ctorParameters: () => [], propDecorators: { article: [{ type: i0.Input, args: [{ isSignal: true, alias: "article", required: false }] }, { type: i0.Output, args: ["articleChange"] }], isPublic: [{ type: i0.Input, args: [{ isSignal: true, alias: "isPublic", required: false }] }], allowModification: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowModification", required: false }] }], labelsField: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelsField", required: false }] }], labelInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelInput", required: false }] }, { type: i0.Output, args: ["labelInputChange"] }], popover: [{ type: i0.ViewChild, args: [
|
|
12668
|
+
}], ctorParameters: () => [], propDecorators: { article: [{ type: i0.Input, args: [{ isSignal: true, alias: "article", required: false }] }, { type: i0.Output, args: ["articleChange"] }], isPublic: [{ type: i0.Input, args: [{ isSignal: true, alias: "isPublic", required: false }] }], allowModification: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowModification", required: false }] }], labelsField: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelsField", required: false }] }], labelInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelInput", required: false }] }, { type: i0.Output, args: ["labelInputChange"] }], popover: [{ type: i0.ViewChild, args: ["LabelsPopover", { isSignal: true }] }] } });
|
|
12588
12669
|
|
|
12589
12670
|
class LabelsEditDialog {
|
|
12590
12671
|
destroyRef;
|