verben-authentication-ui 1.0.37 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -1
- package/esm2022/src/lib/base/core/base-data-page.facade.mjs +215 -0
- package/esm2022/src/lib/base/core/base-data-page.service.mjs +103 -0
- package/esm2022/src/lib/base/core/base-data-page.state.mjs +203 -0
- package/esm2022/src/lib/base/handlers/filter-handler.service.mjs +53 -0
- package/esm2022/src/lib/base/handlers/search-handler.service.mjs +31 -0
- package/esm2022/src/lib/base/handlers/sort-handler.service.mjs +49 -0
- package/esm2022/src/lib/base/models/api-payload.mjs +4 -0
- package/esm2022/src/lib/base/models/page-config.interface.mjs +2 -0
- package/esm2022/src/lib/base/public-api.mjs +14 -6
- package/esm2022/src/lib/base/utils/column-helpers.mjs +45 -0
- package/esm2022/src/lib/components/button/button.component.mjs +3 -3
- package/esm2022/src/lib/components/forgot-password/forgot-password.component.mjs +2 -2
- package/esm2022/src/lib/components/mail/mail.component.mjs +3 -3
- package/esm2022/src/lib/components/mail-validation/mail-validation.component.mjs +5 -5
- package/esm2022/src/lib/components/o-auth/o-auth.component.mjs +3 -3
- package/esm2022/src/lib/components/otp-input/otp-input.component.mjs +2 -2
- package/esm2022/src/lib/components/reset-password/reset-password.component.mjs +2 -2
- package/esm2022/src/lib/components/role-control/base-table-style.mjs +6 -6
- package/esm2022/src/lib/components/role-control/role-control.component.mjs +3 -3
- package/esm2022/src/lib/components/sign-in/sign-in.component.mjs +4 -4
- package/esm2022/src/lib/components/sign-up/sign-up.component.mjs +6 -6
- package/esm2022/src/lib/components/sso/base-table-style.mjs +6 -6
- package/esm2022/src/lib/components/sso/sso-form/sso-form.component.mjs +3 -3
- package/esm2022/src/lib/components/sso/sso.component.mjs +3 -3
- package/esm2022/src/lib/components/two-factor-auth-otp/two-factor-auth-otp.component.mjs +4 -4
- package/esm2022/src/lib/components/two-factor-auth-setup/two-factor-auth-setup.component.mjs +5 -5
- package/esm2022/src/lib/components/user-management/public-api.mjs +2 -1
- package/esm2022/src/lib/components/user-management/user-management-card/user-management-card.component.mjs +23 -0
- package/esm2022/src/lib/components/user-management/user-management-form/user-management-form.component.mjs +53 -91
- package/esm2022/src/lib/components/user-management/user-management-table/user-management-table.component.mjs +68 -0
- package/esm2022/src/lib/components/user-management/user-management.component.mjs +98 -509
- package/esm2022/src/lib/components/user-management/user-management.module.mjs +11 -80
- package/esm2022/src/lib/components/user-management/user-status-badge/user-status-badge.component.mjs +8 -6
- package/esm2022/src/lib/components/user-management/user.config.mjs +94 -0
- package/esm2022/src/lib/components/user-management/user.facade.mjs +118 -0
- package/esm2022/src/lib/components/user-management/user.service.mjs +60 -0
- package/esm2022/src/lib/components/user-management/user.state.mjs +33 -0
- package/esm2022/src/lib/components/user-request/user-request.component.mjs +8 -8
- package/esm2022/src/lib/components/user-request-approval/public-api.mjs +2 -2
- package/esm2022/src/lib/components/user-request-approval/user-access-request-status-badge/user-access-request-status-badge.component.mjs +8 -6
- package/esm2022/src/lib/components/user-request-approval/user-access-request.config.mjs +79 -0
- package/esm2022/src/lib/components/user-request-approval/user-access-request.facade.mjs +123 -0
- package/esm2022/src/lib/components/user-request-approval/user-access-request.service.mjs +74 -0
- package/esm2022/src/lib/components/user-request-approval/user-access-request.state.mjs +26 -0
- package/esm2022/src/lib/components/user-request-approval/user-request-approval-card/user-request-approval-card.component.mjs +23 -0
- package/esm2022/src/lib/components/user-request-approval/user-request-approval-form/user-request-approval-form.component.mjs +124 -0
- package/esm2022/src/lib/components/user-request-approval/user-request-approval-table/user-request-approval-table.component.mjs +44 -0
- package/esm2022/src/lib/components/user-request-approval/user-request-approval.component.mjs +101 -273
- package/esm2022/src/lib/components/user-request-approval/user-request-approval.module.mjs +10 -74
- package/fesm2022/verben-authentication-ui-src-lib-base.mjs +596 -214
- package/fesm2022/verben-authentication-ui-src-lib-base.mjs.map +1 -1
- package/fesm2022/verben-authentication-ui-src-lib-components-button.mjs +2 -2
- package/fesm2022/verben-authentication-ui-src-lib-components-button.mjs.map +1 -1
- package/fesm2022/verben-authentication-ui-src-lib-components-forgot-password.mjs +2 -2
- package/fesm2022/verben-authentication-ui-src-lib-components-forgot-password.mjs.map +1 -1
- package/fesm2022/verben-authentication-ui-src-lib-components-mail-validation.mjs +4 -4
- package/fesm2022/verben-authentication-ui-src-lib-components-mail-validation.mjs.map +1 -1
- package/fesm2022/verben-authentication-ui-src-lib-components-mail.mjs +2 -2
- package/fesm2022/verben-authentication-ui-src-lib-components-mail.mjs.map +1 -1
- package/fesm2022/verben-authentication-ui-src-lib-components-o-auth.mjs +2 -2
- package/fesm2022/verben-authentication-ui-src-lib-components-o-auth.mjs.map +1 -1
- package/fesm2022/verben-authentication-ui-src-lib-components-otp-input.mjs +2 -2
- package/fesm2022/verben-authentication-ui-src-lib-components-otp-input.mjs.map +1 -1
- package/fesm2022/verben-authentication-ui-src-lib-components-reset-password.mjs +2 -2
- package/fesm2022/verben-authentication-ui-src-lib-components-reset-password.mjs.map +1 -1
- package/fesm2022/verben-authentication-ui-src-lib-components-role-control.mjs +7 -7
- package/fesm2022/verben-authentication-ui-src-lib-components-role-control.mjs.map +1 -1
- package/fesm2022/verben-authentication-ui-src-lib-components-sign-in.mjs +3 -3
- package/fesm2022/verben-authentication-ui-src-lib-components-sign-in.mjs.map +1 -1
- package/fesm2022/verben-authentication-ui-src-lib-components-sign-up.mjs +5 -5
- package/fesm2022/verben-authentication-ui-src-lib-components-sign-up.mjs.map +1 -1
- package/fesm2022/verben-authentication-ui-src-lib-components-sso.mjs +9 -9
- package/fesm2022/verben-authentication-ui-src-lib-components-sso.mjs.map +1 -1
- package/fesm2022/verben-authentication-ui-src-lib-components-two-factor-auth-otp.mjs +3 -3
- package/fesm2022/verben-authentication-ui-src-lib-components-two-factor-auth-otp.mjs.map +1 -1
- package/fesm2022/verben-authentication-ui-src-lib-components-two-factor-auth-setup.mjs +4 -4
- package/fesm2022/verben-authentication-ui-src-lib-components-two-factor-auth-setup.mjs.map +1 -1
- package/fesm2022/verben-authentication-ui-src-lib-components-user-management.mjs +468 -831
- package/fesm2022/verben-authentication-ui-src-lib-components-user-management.mjs.map +1 -1
- package/fesm2022/verben-authentication-ui-src-lib-components-user-request-approval.mjs +509 -952
- package/fesm2022/verben-authentication-ui-src-lib-components-user-request-approval.mjs.map +1 -1
- package/fesm2022/verben-authentication-ui-src-lib-components-user-request.mjs +7 -7
- package/fesm2022/verben-authentication-ui-src-lib-components-user-request.mjs.map +1 -1
- package/package.json +36 -42
- package/src/lib/base/README.md +99 -0
- package/src/lib/base/core/base-data-page.facade.d.ts +65 -0
- package/src/lib/base/core/base-data-page.service.d.ts +43 -0
- package/src/lib/base/core/base-data-page.state.d.ts +68 -0
- package/src/lib/base/handlers/filter-handler.service.d.ts +13 -0
- package/src/lib/base/handlers/search-handler.service.d.ts +20 -0
- package/src/lib/base/handlers/sort-handler.service.d.ts +13 -0
- package/src/lib/base/models/api-payload.d.ts +2 -0
- package/src/lib/base/models/page-config.interface.d.ts +21 -0
- package/src/lib/base/public-api.d.ts +9 -5
- package/src/lib/base/utils/column-helpers.d.ts +16 -0
- package/src/lib/components/user-management/public-api.d.ts +1 -0
- package/src/lib/components/user-management/user-management-card/user-management-card.component.d.ts +11 -0
- package/src/lib/components/user-management/user-management-form/user-management-form.component.d.ts +12 -14
- package/src/lib/components/user-management/user-management-table/user-management-table.component.d.ts +30 -0
- package/src/lib/components/user-management/user-management.component.d.ts +28 -124
- package/src/lib/components/user-management/user-management.module.d.ts +8 -8
- package/src/lib/components/user-management/user-status-badge/user-status-badge.component.d.ts +1 -1
- package/src/lib/components/user-management/user.config.d.ts +13 -0
- package/src/lib/components/user-management/user.facade.d.ts +42 -0
- package/src/lib/components/user-management/user.service.d.ts +26 -0
- package/src/lib/components/user-management/user.state.d.ts +19 -0
- package/src/lib/components/user-request-approval/public-api.d.ts +1 -1
- package/src/lib/components/user-request-approval/user-access-request-status-badge/user-access-request-status-badge.component.d.ts +1 -1
- package/src/lib/components/user-request-approval/user-access-request.config.d.ts +13 -0
- package/src/lib/components/user-request-approval/user-access-request.facade.d.ts +36 -0
- package/src/lib/components/user-request-approval/user-access-request.service.d.ts +30 -0
- package/src/lib/components/user-request-approval/user-access-request.state.d.ts +16 -0
- package/src/lib/components/user-request-approval/user-request-approval-card/user-request-approval-card.component.d.ts +11 -0
- package/src/lib/components/user-request-approval/user-request-approval-form/user-request-approval-form.component.d.ts +47 -0
- package/src/lib/components/user-request-approval/user-request-approval-table/user-request-approval-table.component.d.ts +20 -0
- package/src/lib/components/user-request-approval/user-request-approval.component.d.ts +29 -68
- package/src/lib/components/user-request-approval/user-request-approval.module.d.ts +7 -6
- package/esm2022/src/lib/base/base-data.component.mjs +0 -80
- package/esm2022/src/lib/base/base-data.facade.mjs +0 -130
- package/esm2022/src/lib/base/base-data.service.mjs +0 -21
- package/esm2022/src/lib/base/base-data.state.mjs +0 -74
- package/esm2022/src/lib/base/models.mjs +0 -2
- package/esm2022/src/lib/components/user-management/base-table-style.mjs +0 -53
- package/esm2022/src/lib/components/user-management/services/user-management.service.mjs +0 -110
- package/esm2022/src/lib/components/user-management/user-management.columns.mjs +0 -53
- package/esm2022/src/lib/components/user-request-approval/access-request.columns.mjs +0 -29
- package/esm2022/src/lib/components/user-request-approval/base-table-style.mjs +0 -53
- package/esm2022/src/lib/components/user-request-approval/facades/user-access-request.facade.mjs +0 -260
- package/esm2022/src/lib/components/user-request-approval/helper.mjs +0 -56
- package/esm2022/src/lib/components/user-request-approval/services/user-access-request.service.mjs +0 -92
- package/esm2022/src/lib/components/user-request-approval/states/user-access-request.state.mjs +0 -92
- package/esm2022/src/lib/components/user-request-approval/user-request-form/user-request-form.component.mjs +0 -105
- package/esm2022/src/lib/components/user-request-process/index.mjs +0 -2
- package/esm2022/src/lib/components/user-request-process/public-api.mjs +0 -3
- package/esm2022/src/lib/components/user-request-process/user-request-process.component.mjs +0 -11
- package/esm2022/src/lib/components/user-request-process/user-request-process.module.mjs +0 -18
- package/esm2022/src/lib/components/user-request-process/verben-authentication-ui-src-lib-components-user-request-process.mjs +0 -5
- package/fesm2022/verben-authentication-ui-src-lib-components-user-request-process.mjs +0 -34
- package/fesm2022/verben-authentication-ui-src-lib-components-user-request-process.mjs.map +0 -1
- package/src/lib/base/base-data.component.d.ts +0 -32
- package/src/lib/base/base-data.facade.d.ts +0 -27
- package/src/lib/base/base-data.service.d.ts +0 -14
- package/src/lib/base/base-data.state.d.ts +0 -28
- package/src/lib/base/models.d.ts +0 -11
- package/src/lib/components/user-management/base-table-style.d.ts +0 -1
- package/src/lib/components/user-management/services/user-management.service.d.ts +0 -44
- package/src/lib/components/user-management/user-management.columns.d.ts +0 -3
- package/src/lib/components/user-request-approval/access-request.columns.d.ts +0 -3
- package/src/lib/components/user-request-approval/base-table-style.d.ts +0 -1
- package/src/lib/components/user-request-approval/facades/user-access-request.facade.d.ts +0 -39
- package/src/lib/components/user-request-approval/helper.d.ts +0 -7
- package/src/lib/components/user-request-approval/services/user-access-request.service.d.ts +0 -64
- package/src/lib/components/user-request-approval/states/user-access-request.state.d.ts +0 -35
- package/src/lib/components/user-request-approval/user-request-form/user-request-form.component.d.ts +0 -34
- package/src/lib/components/user-request-process/index.d.ts +0 -1
- package/src/lib/components/user-request-process/public-api.d.ts +0 -2
- package/src/lib/components/user-request-process/user-request-process.component.d.ts +0 -5
- package/src/lib/components/user-request-process/user-request-process.module.d.ts +0 -7
|
@@ -1,43 +1,163 @@
|
|
|
1
|
+
import { SearchPropertyValueType, SortDirection, SearchOperator, SearchPropertySign, ErrorResponse } from 'verben-authentication-ui/src/lib/models';
|
|
2
|
+
export { SearchOperator, SearchPropertySign, SearchPropertyValueType, SortDirection } from 'verben-authentication-ui/src/lib/models';
|
|
1
3
|
import * as i0 from '@angular/core';
|
|
2
|
-
import {
|
|
3
|
-
import { BehaviorSubject, Subject,
|
|
4
|
-
import
|
|
4
|
+
import { signal, Injectable } from '@angular/core';
|
|
5
|
+
import { BehaviorSubject, lastValueFrom, Subject, debounce, timer, distinctUntilChanged, takeUntil } from 'rxjs';
|
|
6
|
+
import * as i1 from 'verben-authentication-ui/src/lib/services';
|
|
7
|
+
import { SortDirection as SortDirection$1 } from 'verben-ng-ui';
|
|
5
8
|
|
|
6
|
-
|
|
9
|
+
// Re-export the shared API payload models so base-page consumers can import
|
|
10
|
+
// them from a single place without reaching into the models entry point.
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Extract property name from column definition.
|
|
14
|
+
* Only columns with accessorKey can be used for filter/sort.
|
|
15
|
+
*/
|
|
16
|
+
function getPropertyName(column) {
|
|
17
|
+
if (!column.accessorKey) {
|
|
18
|
+
throw new Error(`Column '${column.id}' must have accessorKey for filter/sort operations`);
|
|
19
|
+
}
|
|
20
|
+
return String(column.accessorKey);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Infer API property type from column definition.
|
|
24
|
+
* Uses basic heuristics based on the accessor key name.
|
|
25
|
+
*/
|
|
26
|
+
function inferPropertyType(column) {
|
|
27
|
+
if (!column.accessorKey) {
|
|
28
|
+
return SearchPropertyValueType.String;
|
|
29
|
+
}
|
|
30
|
+
const propertyName = String(column.accessorKey).toLowerCase();
|
|
31
|
+
// Date detection. Includes the common audit fields (CreatedAt, UpdatedAt,
|
|
32
|
+
// ModifiedAt, DeletedAt) whose names contain neither "date" nor "time".
|
|
33
|
+
if (propertyName.includes('date') ||
|
|
34
|
+
propertyName.includes('time') ||
|
|
35
|
+
/^(created|updated|modified|deleted)/.test(propertyName)) {
|
|
36
|
+
return SearchPropertyValueType.Date;
|
|
37
|
+
}
|
|
38
|
+
if (propertyName.startsWith('is') || propertyName.startsWith('has')) {
|
|
39
|
+
return SearchPropertyValueType.Bool;
|
|
40
|
+
}
|
|
41
|
+
if (propertyName.includes('count') ||
|
|
42
|
+
propertyName.includes('amount') ||
|
|
43
|
+
propertyName.includes('price') ||
|
|
44
|
+
propertyName.includes('total')) {
|
|
45
|
+
return SearchPropertyValueType.Decimal;
|
|
46
|
+
}
|
|
47
|
+
return SearchPropertyValueType.String;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Find a column by its id.
|
|
51
|
+
*/
|
|
52
|
+
function findColumn(columns, columnId) {
|
|
53
|
+
return columns.find((col) => col.id === columnId);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Abstract state management for base data pages.
|
|
58
|
+
* Tracks items, loading state, query params, filters, sorts, search, and
|
|
59
|
+
* visible columns. Card data is held in signals for cheap change detection.
|
|
60
|
+
*/
|
|
61
|
+
class BaseDataPageState {
|
|
7
62
|
updating$ = new BehaviorSubject(false);
|
|
8
63
|
items$ = new BehaviorSubject([]);
|
|
9
|
-
|
|
64
|
+
totalCount$ = new BehaviorSubject(0);
|
|
10
65
|
queryParams$ = new BehaviorSubject({
|
|
11
66
|
skip: 0,
|
|
12
67
|
limit: 20,
|
|
13
|
-
sortOrder:
|
|
68
|
+
sortOrder: SortDirection.Asc,
|
|
14
69
|
});
|
|
15
|
-
|
|
70
|
+
searchTerm$ = new BehaviorSubject('');
|
|
71
|
+
filters$ = new BehaviorSubject([]);
|
|
72
|
+
sorts$ = new BehaviorSubject([]);
|
|
73
|
+
visibleColumns$ = new BehaviorSubject([]);
|
|
74
|
+
cardData = signal([]);
|
|
75
|
+
currentCardData = signal(null);
|
|
76
|
+
cardDataMapper;
|
|
77
|
+
/**
|
|
78
|
+
* Stable identity for a record. The auth models key on uppercase `Id`/`Code`
|
|
79
|
+
* and only sometimes carry a lowercase `id`, so match across all three rather
|
|
80
|
+
* than assuming one is populated.
|
|
81
|
+
*/
|
|
82
|
+
getItemKey(item) {
|
|
83
|
+
return item.Id || item.id || item.Code;
|
|
84
|
+
}
|
|
85
|
+
updateCardDataFromItems(items) {
|
|
86
|
+
if (this.cardDataMapper) {
|
|
87
|
+
this.cardData.set(items.map((item) => this.cardDataMapper(item)));
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
// ===== Loading State =====
|
|
16
91
|
isUpdating$() {
|
|
17
92
|
return this.updating$.asObservable();
|
|
18
93
|
}
|
|
19
94
|
setUpdating(isUpdating) {
|
|
20
95
|
this.updating$.next(isUpdating);
|
|
21
96
|
}
|
|
97
|
+
// ===== Items =====
|
|
22
98
|
getItems$() {
|
|
23
99
|
return this.items$.asObservable();
|
|
24
100
|
}
|
|
101
|
+
getItemsValue() {
|
|
102
|
+
return this.items$.getValue();
|
|
103
|
+
}
|
|
25
104
|
setItems(items) {
|
|
26
105
|
this.items$.next(items);
|
|
106
|
+
this.updateCardDataFromItems(items);
|
|
27
107
|
}
|
|
28
108
|
appendItems(newItems) {
|
|
29
|
-
const
|
|
30
|
-
this.items$.next(
|
|
109
|
+
const allItems = [...this.items$.getValue(), ...newItems];
|
|
110
|
+
this.items$.next(allItems);
|
|
111
|
+
this.updateCardDataFromItems(allItems);
|
|
31
112
|
}
|
|
32
|
-
|
|
33
|
-
|
|
113
|
+
addItem(item) {
|
|
114
|
+
const allItems = [item, ...this.items$.getValue()];
|
|
115
|
+
this.items$.next(allItems);
|
|
116
|
+
this.updateCardDataFromItems(allItems);
|
|
34
117
|
}
|
|
35
|
-
|
|
36
|
-
|
|
118
|
+
updateItem(updatedItem) {
|
|
119
|
+
const items = this.items$.getValue();
|
|
120
|
+
const key = this.getItemKey(updatedItem);
|
|
121
|
+
const index = items.findIndex((item) => this.getItemKey(item) === key);
|
|
122
|
+
if (index !== -1) {
|
|
123
|
+
items[index] = updatedItem;
|
|
124
|
+
const allItems = [...items];
|
|
125
|
+
this.items$.next(allItems);
|
|
126
|
+
this.updateCardDataFromItems(allItems);
|
|
127
|
+
}
|
|
37
128
|
}
|
|
38
|
-
|
|
39
|
-
|
|
129
|
+
/** Update the item when its key already exists, otherwise prepend it. */
|
|
130
|
+
upsertItem(item) {
|
|
131
|
+
const key = this.getItemKey(item);
|
|
132
|
+
const exists = this.items$
|
|
133
|
+
.getValue()
|
|
134
|
+
.some((existing) => this.getItemKey(existing) === key);
|
|
135
|
+
if (exists) {
|
|
136
|
+
this.updateItem(item);
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
this.addItem(item);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
removeItem(itemKey) {
|
|
143
|
+
const filteredItems = this.items$
|
|
144
|
+
.getValue()
|
|
145
|
+
.filter((item) => this.getItemKey(item) !== itemKey);
|
|
146
|
+
this.items$.next(filteredItems);
|
|
147
|
+
this.updateCardDataFromItems(filteredItems);
|
|
148
|
+
}
|
|
149
|
+
clearItems() {
|
|
150
|
+
this.items$.next([]);
|
|
151
|
+
this.updateCardDataFromItems([]);
|
|
152
|
+
}
|
|
153
|
+
// ===== Total Count =====
|
|
154
|
+
getTotalCount$() {
|
|
155
|
+
return this.totalCount$.asObservable();
|
|
40
156
|
}
|
|
157
|
+
setTotalCount(count) {
|
|
158
|
+
this.totalCount$.next(count);
|
|
159
|
+
}
|
|
160
|
+
// ===== Query Parameters =====
|
|
41
161
|
getQueryParams$() {
|
|
42
162
|
return this.queryParams$.asObservable();
|
|
43
163
|
}
|
|
@@ -48,258 +168,520 @@ class BaseDataState {
|
|
|
48
168
|
this.queryParams$.next({ ...this.queryParams$.getValue(), ...params });
|
|
49
169
|
}
|
|
50
170
|
resetPagination() {
|
|
171
|
+
this.queryParams$.next({ ...this.queryParams$.getValue(), skip: 0 });
|
|
172
|
+
}
|
|
173
|
+
incrementPagination() {
|
|
51
174
|
const currentParams = this.queryParams$.getValue();
|
|
52
|
-
this.queryParams$.next({
|
|
175
|
+
this.queryParams$.next({
|
|
176
|
+
...currentParams,
|
|
177
|
+
skip: currentParams.skip + currentParams.limit,
|
|
178
|
+
});
|
|
53
179
|
}
|
|
54
|
-
|
|
55
|
-
|
|
180
|
+
// ===== Search =====
|
|
181
|
+
getSearchTerm$() {
|
|
182
|
+
return this.searchTerm$.asObservable();
|
|
56
183
|
}
|
|
57
|
-
|
|
58
|
-
this.
|
|
184
|
+
getSearchTermValue() {
|
|
185
|
+
return this.searchTerm$.getValue();
|
|
59
186
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
const currentItems = this.items$.getValue();
|
|
63
|
-
this.items$.next([...currentItems, item]);
|
|
187
|
+
setSearchTerm(term) {
|
|
188
|
+
this.searchTerm$.next(term);
|
|
64
189
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
if (index !== -1) {
|
|
69
|
-
items[index] = updatedItem;
|
|
70
|
-
this.items$.next([...items]);
|
|
71
|
-
}
|
|
190
|
+
// ===== Filters =====
|
|
191
|
+
getFilters$() {
|
|
192
|
+
return this.filters$.asObservable();
|
|
72
193
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
this.items$.next(currentItems.filter((item) => item.Id !== itemId));
|
|
194
|
+
getFiltersValue() {
|
|
195
|
+
return this.filters$.getValue();
|
|
76
196
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
class BaseDataService {
|
|
80
|
-
http;
|
|
81
|
-
baseUrl;
|
|
82
|
-
constructor(http, baseUrl) {
|
|
83
|
-
this.http = http;
|
|
84
|
-
this.baseUrl = baseUrl;
|
|
197
|
+
setFilters(filters) {
|
|
198
|
+
this.filters$.next(filters);
|
|
85
199
|
}
|
|
86
|
-
|
|
87
|
-
|
|
200
|
+
clearFilters() {
|
|
201
|
+
this.filters$.next([]);
|
|
88
202
|
}
|
|
89
|
-
|
|
90
|
-
|
|
203
|
+
// ===== Sorts =====
|
|
204
|
+
getSorts$() {
|
|
205
|
+
return this.sorts$.asObservable();
|
|
91
206
|
}
|
|
92
|
-
|
|
93
|
-
return this.
|
|
207
|
+
getSortsValue() {
|
|
208
|
+
return this.sorts$.getValue();
|
|
94
209
|
}
|
|
95
|
-
|
|
96
|
-
|
|
210
|
+
setSorts(sorts) {
|
|
211
|
+
this.sorts$.next(sorts);
|
|
97
212
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
class BaseDataFacade {
|
|
101
|
-
state;
|
|
102
|
-
service;
|
|
103
|
-
searchSubject = new Subject();
|
|
104
|
-
destroy$ = new Subject();
|
|
105
|
-
constructor(state, service) {
|
|
106
|
-
this.state = state;
|
|
107
|
-
this.service = service;
|
|
108
|
-
this.setupSearchHandler();
|
|
213
|
+
clearSorts() {
|
|
214
|
+
this.sorts$.next([]);
|
|
109
215
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
.subscribe((searchTerm) => {
|
|
114
|
-
this.handleSearch(searchTerm);
|
|
115
|
-
});
|
|
216
|
+
// ===== Visible Columns =====
|
|
217
|
+
getVisibleColumns$() {
|
|
218
|
+
return this.visibleColumns$.asObservable();
|
|
116
219
|
}
|
|
117
|
-
|
|
118
|
-
this.
|
|
119
|
-
this.destroy$.complete();
|
|
220
|
+
getVisibleColumnsValue() {
|
|
221
|
+
return this.visibleColumns$.getValue();
|
|
120
222
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
return this.state.isUpdating$();
|
|
223
|
+
setVisibleColumns(columns) {
|
|
224
|
+
this.visibleColumns$.next(columns);
|
|
124
225
|
}
|
|
125
|
-
|
|
126
|
-
|
|
226
|
+
// ===== Card Data =====
|
|
227
|
+
setCardDataMapper(mapper) {
|
|
228
|
+
this.cardDataMapper = mapper;
|
|
127
229
|
}
|
|
128
|
-
|
|
129
|
-
return this.
|
|
230
|
+
getCardData() {
|
|
231
|
+
return this.cardData;
|
|
130
232
|
}
|
|
131
|
-
|
|
132
|
-
|
|
233
|
+
setCardData(data) {
|
|
234
|
+
this.cardData.set(data);
|
|
133
235
|
}
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
this.searchSubject.next(term);
|
|
236
|
+
getCurrentCardData() {
|
|
237
|
+
return this.currentCardData;
|
|
137
238
|
}
|
|
138
|
-
|
|
139
|
-
this.
|
|
140
|
-
this.state.resetPagination();
|
|
141
|
-
await this.loadItems();
|
|
239
|
+
setCurrentCardData(data) {
|
|
240
|
+
this.currentCardData.set(data);
|
|
142
241
|
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
.toPromise();
|
|
155
|
-
if (response?.Result) {
|
|
156
|
-
this.state.setItems(response?.Result);
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
catch (error) {
|
|
160
|
-
console.error('Failed to load items:', error);
|
|
161
|
-
throw error;
|
|
162
|
-
}
|
|
163
|
-
finally {
|
|
164
|
-
this.state.setUpdating(false);
|
|
165
|
-
}
|
|
242
|
+
// ===== Reset All =====
|
|
243
|
+
reset() {
|
|
244
|
+
this.clearItems();
|
|
245
|
+
this.setSearchTerm('');
|
|
246
|
+
this.clearFilters();
|
|
247
|
+
this.clearSorts();
|
|
248
|
+
this.setVisibleColumns([]);
|
|
249
|
+
this.cardData.set([]);
|
|
250
|
+
this.currentCardData.set(null);
|
|
251
|
+
this.resetPagination();
|
|
252
|
+
this.setTotalCount(0);
|
|
166
253
|
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Converts FilterCondition[] emitted by lib-data-filter into the
|
|
258
|
+
* SearchPropertyValue[] payload the search API expects.
|
|
259
|
+
*/
|
|
260
|
+
class FilterHandlerService {
|
|
261
|
+
buildFilterPayload(filters, columns) {
|
|
262
|
+
return filters
|
|
263
|
+
.map((filter) => {
|
|
264
|
+
const column = findColumn(columns, filter.columnId);
|
|
265
|
+
if (!column) {
|
|
266
|
+
console.warn(`Column not found for filter: ${filter.columnId}`);
|
|
267
|
+
return null;
|
|
178
268
|
}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
269
|
+
const propertyName = getPropertyName(column);
|
|
270
|
+
const propertyType = inferPropertyType(column);
|
|
271
|
+
const sign = this.mapOperatorToSign(filter.operator);
|
|
272
|
+
return {
|
|
273
|
+
PropertyName: propertyName,
|
|
274
|
+
EntityValue: String(filter.value),
|
|
275
|
+
Type: propertyType,
|
|
276
|
+
Operator: SearchOperator.And,
|
|
277
|
+
Sign: sign,
|
|
278
|
+
};
|
|
279
|
+
})
|
|
280
|
+
.filter(Boolean);
|
|
281
|
+
}
|
|
282
|
+
mapOperatorToSign(operator) {
|
|
283
|
+
const operatorMap = {
|
|
284
|
+
startsWith: SearchPropertySign.LIKE,
|
|
285
|
+
endsWith: SearchPropertySign.LIKE,
|
|
286
|
+
contains: SearchPropertySign.LIKE,
|
|
287
|
+
equals: SearchPropertySign.EQ,
|
|
288
|
+
equal: SearchPropertySign.EQ,
|
|
289
|
+
greaterThan: SearchPropertySign.GT,
|
|
290
|
+
lessThan: SearchPropertySign.LT,
|
|
291
|
+
on: SearchPropertySign.EQ,
|
|
292
|
+
before: SearchPropertySign.LT,
|
|
293
|
+
after: SearchPropertySign.GT,
|
|
294
|
+
};
|
|
295
|
+
return operatorMap[operator] || SearchPropertySign.EQ;
|
|
296
|
+
}
|
|
297
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FilterHandlerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
298
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FilterHandlerService, providedIn: 'root' });
|
|
299
|
+
}
|
|
300
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FilterHandlerService, decorators: [{
|
|
301
|
+
type: Injectable,
|
|
302
|
+
args: [{ providedIn: 'root' }]
|
|
303
|
+
}] });
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Converts SortCondition[] emitted by lib-data-sort into the
|
|
307
|
+
* SearchPropertyValue[] payload the search API expects.
|
|
308
|
+
*/
|
|
309
|
+
class SortHandlerService {
|
|
310
|
+
buildSortPayload(sorts, columns) {
|
|
311
|
+
return sorts
|
|
312
|
+
.map((sort) => {
|
|
313
|
+
const column = findColumn(columns, sort.columnId);
|
|
314
|
+
if (!column) {
|
|
315
|
+
console.warn(`Column not found for sort: ${sort.columnId}`);
|
|
316
|
+
return null;
|
|
194
317
|
}
|
|
318
|
+
const propertyName = getPropertyName(column);
|
|
319
|
+
const propertyType = inferPropertyType(column);
|
|
320
|
+
return {
|
|
321
|
+
PropertyName: propertyName,
|
|
322
|
+
EntityValue: '',
|
|
323
|
+
Type: propertyType,
|
|
324
|
+
Operator: SearchOperator.And,
|
|
325
|
+
Sign: SearchPropertySign.EQ,
|
|
326
|
+
Sort: this.mapSortDirection(sort.direction),
|
|
327
|
+
};
|
|
328
|
+
})
|
|
329
|
+
.filter(Boolean);
|
|
330
|
+
}
|
|
331
|
+
mapSortDirection(direction) {
|
|
332
|
+
switch (direction) {
|
|
333
|
+
case SortDirection$1.Asc:
|
|
334
|
+
return SortDirection.Asc;
|
|
335
|
+
case SortDirection$1.Desc:
|
|
336
|
+
return SortDirection.Desc;
|
|
337
|
+
default:
|
|
338
|
+
return SortDirection.None;
|
|
195
339
|
}
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
340
|
+
}
|
|
341
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SortHandlerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
342
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SortHandlerService, providedIn: 'root' });
|
|
343
|
+
}
|
|
344
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SortHandlerService, decorators: [{
|
|
345
|
+
type: Injectable,
|
|
346
|
+
args: [{ providedIn: 'root' }]
|
|
347
|
+
}] });
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* Abstract base service for data pages.
|
|
351
|
+
* Handles list/search/save/delete with filter and sort support.
|
|
352
|
+
*
|
|
353
|
+
* The concrete URLs are built by the protected `*Url` seams below so that
|
|
354
|
+
* services whose API does not follow the default `Get{Endpoint}/{skip}/{limit}`
|
|
355
|
+
* conventions (e.g. plural names or a trailing sort suffix) can override just
|
|
356
|
+
* the URL without reimplementing the request-selection logic in `getData()`.
|
|
357
|
+
* When `baseUrl` is omitted, HttpWebRequestService falls back to the
|
|
358
|
+
* AuthenticationAPI base.
|
|
359
|
+
*/
|
|
360
|
+
class BaseDataPageService {
|
|
361
|
+
server;
|
|
362
|
+
filterHandler;
|
|
363
|
+
sortHandler;
|
|
364
|
+
baseUrl;
|
|
365
|
+
constructor(server, filterHandler, sortHandler, baseUrl) {
|
|
366
|
+
this.server = server;
|
|
367
|
+
this.filterHandler = filterHandler;
|
|
368
|
+
this.sortHandler = sortHandler;
|
|
369
|
+
this.baseUrl = baseUrl;
|
|
370
|
+
}
|
|
371
|
+
// ===== URL seams (override in child services when the API deviates) =====
|
|
372
|
+
listUrl(skip, limit) {
|
|
373
|
+
return `Get${this.getEndpoint()}/${skip}/${limit}`;
|
|
374
|
+
}
|
|
375
|
+
searchTermUrl(term, skip, limit) {
|
|
376
|
+
return `Get${this.getEndpoint()}WithParam/${term}/${skip}/${limit}`;
|
|
377
|
+
}
|
|
378
|
+
filterSearchUrl(skip, limit) {
|
|
379
|
+
return `Search${this.getEndpoint()}/${skip}/${limit}`;
|
|
380
|
+
}
|
|
381
|
+
saveUrl() {
|
|
382
|
+
return `Save${this.getEndpoint()}`;
|
|
383
|
+
}
|
|
384
|
+
deleteUrl(itemIds) {
|
|
385
|
+
return `${this.getEndpoint()}/${itemIds.join(',')}`;
|
|
386
|
+
}
|
|
387
|
+
// ===== Payload =====
|
|
388
|
+
buildPayload(filters, sorts, columns) {
|
|
389
|
+
const filterPayload = this.filterHandler.buildFilterPayload(filters, columns);
|
|
390
|
+
const sortPayload = this.sortHandler.buildSortPayload(sorts, columns);
|
|
391
|
+
return [...filterPayload, ...sortPayload];
|
|
392
|
+
}
|
|
393
|
+
// ===== Reads =====
|
|
394
|
+
/**
|
|
395
|
+
* Fetch data, automatically choosing the endpoint based on parameters:
|
|
396
|
+
* search-only -> GET WithParam, filters/sorts -> POST Search, otherwise plain GET.
|
|
397
|
+
*/
|
|
398
|
+
async getData(skip, limit, filters, sorts, searchTerm, columns) {
|
|
399
|
+
const hasFilters = !!filters && filters.length > 0;
|
|
400
|
+
const hasSorts = !!sorts && sorts.length > 0;
|
|
401
|
+
if (searchTerm && !hasFilters && !hasSorts) {
|
|
402
|
+
return this.server.get(this.searchTermUrl(searchTerm, skip, limit), this.baseUrl);
|
|
199
403
|
}
|
|
200
|
-
|
|
201
|
-
|
|
404
|
+
if (hasFilters || hasSorts) {
|
|
405
|
+
if (!columns) {
|
|
406
|
+
throw new Error('Columns required for filter/sort operations');
|
|
407
|
+
}
|
|
408
|
+
const payload = this.buildPayload(filters || [], sorts || [], columns);
|
|
409
|
+
return this.server.post(this.filterSearchUrl(skip, limit), payload, this.baseUrl);
|
|
202
410
|
}
|
|
411
|
+
return this.server.get(this.listUrl(skip, limit), this.baseUrl);
|
|
412
|
+
}
|
|
413
|
+
// ===== Writes =====
|
|
414
|
+
async saveItems(items) {
|
|
415
|
+
return this.server.post(this.saveUrl(), items, this.baseUrl);
|
|
203
416
|
}
|
|
204
|
-
async
|
|
417
|
+
async deleteItems(itemIds) {
|
|
418
|
+
// HttpWebRequestService.delete returns a raw observable that rejects on HTTP
|
|
419
|
+
// error (unlike get/post, which resolve an ErrorResponse), so normalize here
|
|
420
|
+
// to keep the facade's error-handling contract uniform.
|
|
205
421
|
try {
|
|
206
|
-
this.
|
|
207
|
-
|
|
208
|
-
this.state.removeItem(itemId);
|
|
422
|
+
const result = await lastValueFrom(this.server.delete(this.deleteUrl(itemIds), this.baseUrl));
|
|
423
|
+
return result ?? false;
|
|
209
424
|
}
|
|
210
|
-
catch (
|
|
211
|
-
|
|
212
|
-
|
|
425
|
+
catch (err) {
|
|
426
|
+
const msg = err?.error?.ErrorMsg || err?.ErrorMsg || err?.message || 'Delete failed';
|
|
427
|
+
return new ErrorResponse(msg);
|
|
213
428
|
}
|
|
214
|
-
|
|
215
|
-
|
|
429
|
+
}
|
|
430
|
+
// ===== Export =====
|
|
431
|
+
async exportData(filters, sorts, searchTerm, columns) {
|
|
432
|
+
const result = await this.getData(0, 999999, filters, sorts, searchTerm, columns);
|
|
433
|
+
if (result instanceof ErrorResponse) {
|
|
434
|
+
return result;
|
|
216
435
|
}
|
|
436
|
+
return result.Result || [];
|
|
217
437
|
}
|
|
218
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type:
|
|
219
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type:
|
|
438
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: BaseDataPageService, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable });
|
|
439
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: BaseDataPageService });
|
|
220
440
|
}
|
|
221
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type:
|
|
441
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: BaseDataPageService, decorators: [{
|
|
222
442
|
type: Injectable
|
|
223
|
-
}], ctorParameters: () => [{ type:
|
|
443
|
+
}], ctorParameters: () => [{ type: i1.HttpWebRequestService }, { type: FilterHandlerService }, { type: SortHandlerService }, { type: undefined }] });
|
|
224
444
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
445
|
+
/**
|
|
446
|
+
* Debounces search terms. Emits the term after the user stops typing.
|
|
447
|
+
* Provided per page so each page owns its own debounce stream.
|
|
448
|
+
*
|
|
449
|
+
* `search$` is a stable observable whose debounce interval is read live from
|
|
450
|
+
* `debounceMs`, so `setDebounceTime()` can be called after subscribers have
|
|
451
|
+
* attached (e.g. from a runtime `@Input`) and still take effect.
|
|
452
|
+
*/
|
|
453
|
+
class SearchHandlerService {
|
|
454
|
+
searchSubject = new Subject();
|
|
455
|
+
debounceMs = 500;
|
|
456
|
+
search$ = this.searchSubject.asObservable().pipe(debounce(() => timer(this.debounceMs)), distinctUntilChanged());
|
|
457
|
+
search(term) {
|
|
458
|
+
this.searchSubject.next(term);
|
|
237
459
|
}
|
|
238
|
-
|
|
239
|
-
this.
|
|
240
|
-
this.loadInitialData();
|
|
460
|
+
setDebounceTime(ms) {
|
|
461
|
+
this.debounceMs = ms;
|
|
241
462
|
}
|
|
242
463
|
ngOnDestroy() {
|
|
243
|
-
this.
|
|
244
|
-
this.destroy$.complete();
|
|
464
|
+
this.searchSubject.complete();
|
|
245
465
|
}
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
466
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SearchHandlerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
467
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SearchHandlerService });
|
|
468
|
+
}
|
|
469
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SearchHandlerService, decorators: [{
|
|
470
|
+
type: Injectable
|
|
471
|
+
}] });
|
|
472
|
+
|
|
473
|
+
/**
|
|
474
|
+
* Abstract facade for base data pages.
|
|
475
|
+
* Orchestrates state, service, and search handler, and surfaces the host app's
|
|
476
|
+
* busy indicator / toasts through UtilService.
|
|
477
|
+
*/
|
|
478
|
+
class BaseDataPageFacade {
|
|
479
|
+
state;
|
|
480
|
+
service;
|
|
481
|
+
searchHandler;
|
|
482
|
+
utilService;
|
|
483
|
+
config;
|
|
484
|
+
destroy$ = new Subject();
|
|
485
|
+
cardSelectionCleared = new Subject();
|
|
486
|
+
constructor(state, service, searchHandler, utilService, config) {
|
|
487
|
+
this.state = state;
|
|
488
|
+
this.service = service;
|
|
489
|
+
this.searchHandler = searchHandler;
|
|
490
|
+
this.utilService = utilService;
|
|
491
|
+
this.config = config;
|
|
492
|
+
this.initializeSearchHandler();
|
|
493
|
+
this.state.setVisibleColumns(this.config.columns);
|
|
494
|
+
if (this.config.cardDataMapper) {
|
|
495
|
+
this.state.setCardDataMapper(this.config.cardDataMapper);
|
|
263
496
|
}
|
|
497
|
+
// Drive the host busy indicator from the shared loading flag.
|
|
498
|
+
this.state
|
|
499
|
+
.isUpdating$()
|
|
500
|
+
.pipe(takeUntil(this.destroy$))
|
|
501
|
+
.subscribe((loading) => this.utilService.sendBI(loading));
|
|
264
502
|
}
|
|
265
|
-
|
|
266
|
-
|
|
503
|
+
// ===== Configuration =====
|
|
504
|
+
getConfig() {
|
|
505
|
+
return this.config;
|
|
267
506
|
}
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
507
|
+
getColumns() {
|
|
508
|
+
return this.config.columns;
|
|
509
|
+
}
|
|
510
|
+
// ===== Observables =====
|
|
511
|
+
get items$() {
|
|
512
|
+
return this.state.getItems$();
|
|
513
|
+
}
|
|
514
|
+
get isLoading$() {
|
|
515
|
+
return this.state.isUpdating$();
|
|
516
|
+
}
|
|
517
|
+
get totalCount$() {
|
|
518
|
+
return this.state.getTotalCount$();
|
|
519
|
+
}
|
|
520
|
+
get filters$() {
|
|
521
|
+
return this.state.getFilters$();
|
|
522
|
+
}
|
|
523
|
+
get sorts$() {
|
|
524
|
+
return this.state.getSorts$();
|
|
525
|
+
}
|
|
526
|
+
get searchTerm$() {
|
|
527
|
+
return this.state.getSearchTerm$();
|
|
528
|
+
}
|
|
529
|
+
get visibleColumns$() {
|
|
530
|
+
return this.state.getVisibleColumns$();
|
|
531
|
+
}
|
|
532
|
+
get cardData() {
|
|
533
|
+
return this.state.getCardData();
|
|
534
|
+
}
|
|
535
|
+
get currentCardData() {
|
|
536
|
+
return this.state.getCurrentCardData();
|
|
537
|
+
}
|
|
538
|
+
/**
|
|
539
|
+
* Emits when a refetch invalidates the current card selection.
|
|
540
|
+
* Card views listen to this to clear their own selection state.
|
|
541
|
+
*/
|
|
542
|
+
get cardSelectionCleared$() {
|
|
543
|
+
return this.cardSelectionCleared.asObservable();
|
|
544
|
+
}
|
|
545
|
+
// ===== Data Loading =====
|
|
546
|
+
async loadData() {
|
|
547
|
+
this.clearCardSelection();
|
|
548
|
+
this.state.setUpdating(true);
|
|
549
|
+
this.state.clearItems();
|
|
550
|
+
this.state.resetPagination();
|
|
551
|
+
const params = this.state.getQueryParamsValue();
|
|
552
|
+
const filters = this.state.getFiltersValue();
|
|
553
|
+
const sorts = this.state.getSortsValue();
|
|
554
|
+
const searchTerm = this.state.getSearchTermValue();
|
|
555
|
+
const result = await this.service.getData(params.skip, params.limit, filters, sorts, searchTerm, this.config.columns);
|
|
556
|
+
this.state.setUpdating(false);
|
|
557
|
+
if (result instanceof ErrorResponse) {
|
|
558
|
+
this.utilService.showError(result.ErrorMsg);
|
|
559
|
+
return;
|
|
271
560
|
}
|
|
272
|
-
|
|
273
|
-
|
|
561
|
+
this.state.setItems(result.Result || []);
|
|
562
|
+
this.state.setTotalCount(result.Total || 0);
|
|
563
|
+
}
|
|
564
|
+
addItem(item) {
|
|
565
|
+
this.state.addItem(item);
|
|
566
|
+
}
|
|
567
|
+
async loadMore() {
|
|
568
|
+
this.state.setUpdating(true);
|
|
569
|
+
this.state.incrementPagination();
|
|
570
|
+
const params = this.state.getQueryParamsValue();
|
|
571
|
+
const filters = this.state.getFiltersValue();
|
|
572
|
+
const sorts = this.state.getSortsValue();
|
|
573
|
+
const searchTerm = this.state.getSearchTermValue();
|
|
574
|
+
const result = await this.service.getData(params.skip, params.limit, filters, sorts, searchTerm, this.config.columns);
|
|
575
|
+
this.state.setUpdating(false);
|
|
576
|
+
if (result instanceof ErrorResponse) {
|
|
577
|
+
this.utilService.showError(result.ErrorMsg);
|
|
578
|
+
return;
|
|
274
579
|
}
|
|
580
|
+
this.state.appendItems(result.Result || []);
|
|
581
|
+
}
|
|
582
|
+
async refresh() {
|
|
583
|
+
await this.loadData();
|
|
584
|
+
}
|
|
585
|
+
// ===== Search =====
|
|
586
|
+
onSearch(term) {
|
|
587
|
+
this.searchHandler.search(term);
|
|
275
588
|
}
|
|
276
|
-
|
|
277
|
-
this.
|
|
589
|
+
initializeSearchHandler() {
|
|
590
|
+
if (this.config.searchDebounceTime) {
|
|
591
|
+
this.searchHandler.setDebounceTime(this.config.searchDebounceTime);
|
|
592
|
+
}
|
|
593
|
+
this.searchHandler.search$.pipe(takeUntil(this.destroy$)).subscribe((term) => {
|
|
594
|
+
this.state.setSearchTerm(term);
|
|
595
|
+
this.loadData();
|
|
596
|
+
});
|
|
278
597
|
}
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
this.
|
|
598
|
+
// ===== Filters / Sorts =====
|
|
599
|
+
async applyFilters(filters) {
|
|
600
|
+
this.state.setFilters(filters);
|
|
601
|
+
await this.loadData();
|
|
602
|
+
}
|
|
603
|
+
async clearFilters() {
|
|
604
|
+
this.state.clearFilters();
|
|
605
|
+
await this.loadData();
|
|
606
|
+
}
|
|
607
|
+
async applySorts(sorts) {
|
|
608
|
+
this.state.setSorts(sorts);
|
|
609
|
+
await this.loadData();
|
|
610
|
+
}
|
|
611
|
+
async clearSorts() {
|
|
612
|
+
this.state.clearSorts();
|
|
613
|
+
await this.loadData();
|
|
614
|
+
}
|
|
615
|
+
// ===== Visible Columns =====
|
|
616
|
+
updateVisibleColumns(columns) {
|
|
617
|
+
this.state.setVisibleColumns(columns);
|
|
618
|
+
}
|
|
619
|
+
// ===== Card Data =====
|
|
620
|
+
selectCard(cardData) {
|
|
621
|
+
this.state.setCurrentCardData(cardData);
|
|
622
|
+
}
|
|
623
|
+
/**
|
|
624
|
+
* Drop the current card selection because the data it referred to is being
|
|
625
|
+
* replaced. Called by loadData(); deliberately not by loadMore(), which only
|
|
626
|
+
* appends and leaves an existing selection valid.
|
|
627
|
+
*/
|
|
628
|
+
clearCardSelection() {
|
|
629
|
+
this.state.setCurrentCardData(null);
|
|
630
|
+
this.cardSelectionCleared.next();
|
|
631
|
+
}
|
|
632
|
+
// ===== CRUD =====
|
|
633
|
+
async saveItems(items) {
|
|
634
|
+
this.state.setUpdating(true);
|
|
635
|
+
const result = await this.service.saveItems(items);
|
|
636
|
+
this.state.setUpdating(false);
|
|
637
|
+
if (result instanceof ErrorResponse) {
|
|
638
|
+
this.utilService.showError(result.ErrorMsg);
|
|
639
|
+
return false;
|
|
640
|
+
}
|
|
641
|
+
this.utilService.showSuccess('Record(s) saved successfully');
|
|
642
|
+
result.forEach((savedItem) => this.state.upsertItem(savedItem));
|
|
643
|
+
return true;
|
|
644
|
+
}
|
|
645
|
+
async deleteItems(itemIds) {
|
|
646
|
+
this.state.setUpdating(true);
|
|
647
|
+
const result = await this.service.deleteItems(itemIds);
|
|
648
|
+
this.state.setUpdating(false);
|
|
649
|
+
if (result instanceof ErrorResponse) {
|
|
650
|
+
this.utilService.showError(result.ErrorMsg);
|
|
651
|
+
return false;
|
|
652
|
+
}
|
|
653
|
+
itemIds.forEach((id) => this.state.removeItem(id));
|
|
654
|
+
return true;
|
|
655
|
+
}
|
|
656
|
+
// ===== Export =====
|
|
657
|
+
async exportData() {
|
|
658
|
+
const filters = this.state.getFiltersValue();
|
|
659
|
+
const sorts = this.state.getSortsValue();
|
|
660
|
+
const searchTerm = this.state.getSearchTermValue();
|
|
661
|
+
const result = await this.service.exportData(filters, sorts, searchTerm, this.config.columns);
|
|
662
|
+
if (result instanceof ErrorResponse) {
|
|
663
|
+
return [];
|
|
664
|
+
}
|
|
665
|
+
return result;
|
|
282
666
|
}
|
|
283
|
-
|
|
284
|
-
|
|
667
|
+
// ===== Cleanup =====
|
|
668
|
+
ngOnDestroy() {
|
|
669
|
+
this.destroy$.next();
|
|
670
|
+
this.destroy$.complete();
|
|
671
|
+
this.cardSelectionCleared.complete();
|
|
285
672
|
}
|
|
286
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type:
|
|
287
|
-
static
|
|
673
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: BaseDataPageFacade, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable });
|
|
674
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: BaseDataPageFacade });
|
|
288
675
|
}
|
|
289
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type:
|
|
290
|
-
type:
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
}], selectionChange: [{
|
|
295
|
-
type: Output
|
|
296
|
-
}], exportData: [{
|
|
297
|
-
type: Output
|
|
298
|
-
}] } });
|
|
676
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: BaseDataPageFacade, decorators: [{
|
|
677
|
+
type: Injectable
|
|
678
|
+
}], ctorParameters: () => [{ type: BaseDataPageState }, { type: BaseDataPageService }, { type: SearchHandlerService }, { type: i1.UtilService }, { type: undefined }] });
|
|
679
|
+
|
|
680
|
+
// Models and interfaces
|
|
299
681
|
|
|
300
682
|
/**
|
|
301
683
|
* Generated bundle index. Do not edit.
|
|
302
684
|
*/
|
|
303
685
|
|
|
304
|
-
export {
|
|
686
|
+
export { BaseDataPageFacade, BaseDataPageService, BaseDataPageState, FilterHandlerService, SearchHandlerService, SortHandlerService, findColumn, getPropertyName, inferPropertyType };
|
|
305
687
|
//# sourceMappingURL=verben-authentication-ui-src-lib-base.mjs.map
|