@zambon-dev/library 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/zambon-dev-library.mjs +3795 -0
- package/fesm2022/zambon-dev-library.mjs.map +1 -0
- package/index.d.ts +10 -0
- package/lib/components/base.component.d.ts +9 -0
- package/lib/components/catalog-select/catalog-select.component.d.ts +112 -0
- package/lib/components/data-grid/data-grid.component.d.ts +49 -0
- package/lib/components/data-grid-row/data-grid-row.component.d.ts +30 -0
- package/lib/components/form-group/form-group.component.d.ts +8 -0
- package/lib/components/form-input/form-input.component.d.ts +47 -0
- package/lib/components/form-input-group/form-input-group.component.d.ts +40 -0
- package/lib/components/group-accordion/group-accordion.component.d.ts +13 -0
- package/lib/components/group-container/group-container.component.d.ts +16 -0
- package/lib/components/group-scroll-spy/group-scroll-spy.component.d.ts +14 -0
- package/lib/components/index.d.ts +18 -0
- package/lib/components/modal/modal.component.d.ts +26 -0
- package/lib/components/multi-editor/multi-editor.component.d.ts +30 -0
- package/lib/components/multi-select/multi-select.component.d.ts +25 -0
- package/lib/components/multi-select/result-grid/result-grid.component.d.ts +18 -0
- package/lib/components/ribbon/ribbon.component.d.ts +5 -0
- package/lib/components/ribbon-button/ribbon-button.component.d.ts +31 -0
- package/lib/components/ribbon-group/ribbon-group.component.d.ts +10 -0
- package/lib/components/sidebar/sidebar.component.d.ts +34 -0
- package/lib/components/sidebar-item/sidebar-item.component.d.ts +30 -0
- package/lib/directives/index.d.ts +1 -0
- package/lib/directives/scroll-spy.directive.d.ts +16 -0
- package/lib/helpers/date-helpers.d.ts +3 -0
- package/lib/helpers/guid-helper.d.ts +3 -0
- package/lib/helpers/index.d.ts +3 -0
- package/lib/helpers/route-formatter.d.ts +4 -0
- package/lib/library.module.d.ts +27 -0
- package/lib/models/batch-update.d.ts +4 -0
- package/lib/models/catalog-entry.d.ts +4 -0
- package/lib/models/catalog-result.d.ts +5 -0
- package/lib/models/configs/data-grid-configs.d.ts +9 -0
- package/lib/models/configs/grid-configs.d.ts +9 -0
- package/lib/models/configs/index.d.ts +2 -0
- package/lib/models/data-grid-parameters.d.ts +12 -0
- package/lib/models/grid-column.d.ts +9 -0
- package/lib/models/index.d.ts +13 -0
- package/lib/models/modal.interface.d.ts +7 -0
- package/lib/models/multi-editor-changes.d.ts +6 -0
- package/lib/models/multi-selector-changes.d.ts +4 -0
- package/lib/models/ribbon-button-option.d.ts +13 -0
- package/lib/models/ribbon-group-child.d.ts +3 -0
- package/lib/models/sidebar/index.d.ts +3 -0
- package/lib/models/sidebar/sidebar-configs.d.ts +9 -0
- package/lib/models/sidebar/sidebar-menu.d.ts +12 -0
- package/lib/models/sidebar/sidebar-profile.d.ts +5 -0
- package/lib/models/tab-view.d.ts +5 -0
- package/lib/pipes/enum.d.ts +12 -0
- package/lib/pipes/index.d.ts +3 -0
- package/lib/pipes/replace-many.pipe.d.ts +9 -0
- package/lib/pipes/replace.pipe.d.ts +7 -0
- package/lib/services/catalog.service.d.ts +11 -0
- package/lib/services/configs-providers/data-grid-configs.provider.d.ts +8 -0
- package/lib/services/configs-providers/grid-configs.provider.d.ts +9 -0
- package/lib/services/configs-providers/index.d.ts +2 -0
- package/lib/services/data-providers/data-provider.service.d.ts +29 -0
- package/lib/services/data-providers/index.d.ts +1 -0
- package/lib/services/datasets/base.dataset.d.ts +15 -0
- package/lib/services/datasets/data-grid.dataset.d.ts +33 -0
- package/lib/services/datasets/grid.dataset.d.ts +55 -0
- package/lib/services/datasets/index.d.ts +5 -0
- package/lib/services/datasets/multi-editor.dataset.d.ts +22 -0
- package/lib/services/datasets/multi-select-result.dataset.d.ts +26 -0
- package/lib/services/form-group.service.d.ts +5 -0
- package/lib/services/form.service.d.ts +39 -0
- package/lib/services/index.d.ts +6 -0
- package/lib/services/sidebar.service.d.ts +27 -0
- package/lib/validators/date.validators.d.ts +13 -0
- package/lib/validators/index.d.ts +1 -0
- package/package.json +49 -0
|
@@ -0,0 +1,3795 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { Component, inject, Injectable, EventEmitter, InjectionToken, Input, Output, KeyValueDiffers, ViewContainerRef, TemplateRef, ElementRef, HostListener, ViewChild, ChangeDetectorRef, ChangeDetectionStrategy, NgZone, Directive, ContentChildren, Pipe, NgModule } from '@angular/core';
|
|
3
|
+
import { Subject, ReplaySubject, take, tap, map, takeUntil, filter, debounceTime, startWith, pairwise, Observable, forkJoin, switchMap, of, delay } from 'rxjs';
|
|
4
|
+
import { Overlay, OverlayPositionBuilder } from '@angular/cdk/overlay';
|
|
5
|
+
import { TemplatePortal } from '@angular/cdk/portal';
|
|
6
|
+
import * as i1 from '@angular/common';
|
|
7
|
+
import { formatDate, CommonModule, NgIf, NgSwitch, NgSwitchCase, KeyValuePipe, NgFor, NgStyle, NgTemplateOutlet, NgClass } from '@angular/common';
|
|
8
|
+
import * as i1$1 from '@angular/forms';
|
|
9
|
+
import { FormGroupDirective, FormGroupName, FormsModule, ReactiveFormsModule, ControlContainer, FormControl, FormArray, FormGroup } from '@angular/forms';
|
|
10
|
+
import { TranslatePipe, TranslateService } from '@ngx-translate/core';
|
|
11
|
+
import { HttpClient } from '@angular/common/http';
|
|
12
|
+
import { ActivatedRoute, Router, NavigationStart, NavigationEnd } from '@angular/router';
|
|
13
|
+
import * as i1$2 from '@angular/cdk/scrolling';
|
|
14
|
+
import { CdkVirtualScrollViewport, ScrollingModule } from '@angular/cdk/scrolling';
|
|
15
|
+
import * as i2 from 'ngx-resize-observer';
|
|
16
|
+
import { NgxResizeObserverModule } from 'ngx-resize-observer';
|
|
17
|
+
|
|
18
|
+
class BaseComponent {
|
|
19
|
+
//#region ViewChilds, Inputs, Outputs
|
|
20
|
+
//#endregion
|
|
21
|
+
//#region Host listeners
|
|
22
|
+
//#endregion
|
|
23
|
+
//#region Variables
|
|
24
|
+
destroy$ = new Subject();
|
|
25
|
+
//#endregion
|
|
26
|
+
//#region Properties
|
|
27
|
+
//#endregion
|
|
28
|
+
//#region Constructor and Angular life cycle methods
|
|
29
|
+
ngOnDestroy() {
|
|
30
|
+
this.destroy$.next(true);
|
|
31
|
+
this.destroy$.complete();
|
|
32
|
+
}
|
|
33
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: BaseComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
34
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.6", type: BaseComponent, isStandalone: true, selector: "ng-component", ngImport: i0, template: '', isInline: true });
|
|
35
|
+
}
|
|
36
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: BaseComponent, decorators: [{
|
|
37
|
+
type: Component,
|
|
38
|
+
args: [{ template: '' }]
|
|
39
|
+
}] });
|
|
40
|
+
|
|
41
|
+
class CatalogService {
|
|
42
|
+
//#region ViewChilds, Inputs, Outputs
|
|
43
|
+
//#endregion
|
|
44
|
+
//#region Variables
|
|
45
|
+
http = inject(HttpClient);
|
|
46
|
+
//#endregion
|
|
47
|
+
//#region Properties
|
|
48
|
+
//#endregion
|
|
49
|
+
//#region Constructor and Angular life cycle methods
|
|
50
|
+
//#endregion
|
|
51
|
+
//#region Event handlers
|
|
52
|
+
//#endregion
|
|
53
|
+
//#region Public methods
|
|
54
|
+
search(endpoint, maxResults, criteria, filters = null) {
|
|
55
|
+
return this.http.post(`${endpoint}`, { maxResults, criteria, filters });
|
|
56
|
+
}
|
|
57
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: CatalogService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
58
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: CatalogService, providedIn: 'root' });
|
|
59
|
+
}
|
|
60
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: CatalogService, decorators: [{
|
|
61
|
+
type: Injectable,
|
|
62
|
+
args: [{
|
|
63
|
+
providedIn: 'root'
|
|
64
|
+
}]
|
|
65
|
+
}] });
|
|
66
|
+
|
|
67
|
+
class DataProviderService {
|
|
68
|
+
//#region ViewChilds, Inputs, Outputs
|
|
69
|
+
//#endregion
|
|
70
|
+
//#region Variables
|
|
71
|
+
activatedRoute = inject(ActivatedRoute);
|
|
72
|
+
destroy$ = new Subject();
|
|
73
|
+
shouldLazyLoad = false;
|
|
74
|
+
_entityID;
|
|
75
|
+
errorSubject = new Subject();
|
|
76
|
+
isLoading = false;
|
|
77
|
+
isModelLoaded = false;
|
|
78
|
+
modelCache = new ReplaySubject(1);
|
|
79
|
+
//#endregion
|
|
80
|
+
//#region Properties
|
|
81
|
+
get entityID() {
|
|
82
|
+
return this._entityID;
|
|
83
|
+
}
|
|
84
|
+
get hasEntityID() {
|
|
85
|
+
return !!this.entityID;
|
|
86
|
+
}
|
|
87
|
+
//#endregion
|
|
88
|
+
//#region Constructor and Angular life cycle methods
|
|
89
|
+
constructor() {
|
|
90
|
+
this.activatedRoute.paramMap
|
|
91
|
+
.pipe(take(1))
|
|
92
|
+
.subscribe((paramMap) => {
|
|
93
|
+
const newID = Number(paramMap.get('id'));
|
|
94
|
+
if (newID !== this.entityID) {
|
|
95
|
+
this._entityID = newID;
|
|
96
|
+
// Need to wait for the data-provider to be initialized.
|
|
97
|
+
queueMicrotask(() => {
|
|
98
|
+
// When lazy loading, the model should be loaded by the consuming component.
|
|
99
|
+
if (!this.shouldLazyLoad) {
|
|
100
|
+
this.refreshModel();
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
ngOnDestroy() {
|
|
107
|
+
this.destroy$.next(true);
|
|
108
|
+
this.destroy$.complete();
|
|
109
|
+
}
|
|
110
|
+
//#endregion
|
|
111
|
+
//#region Event handlers
|
|
112
|
+
//#endregion
|
|
113
|
+
//#region Public methods
|
|
114
|
+
getError$() {
|
|
115
|
+
return this.errorSubject.asObservable();
|
|
116
|
+
}
|
|
117
|
+
getModel$() {
|
|
118
|
+
if (!this.isModelLoaded && !this.shouldLazyLoad) {
|
|
119
|
+
this.refreshModel();
|
|
120
|
+
}
|
|
121
|
+
return this.modelCache.asObservable();
|
|
122
|
+
}
|
|
123
|
+
refreshModel() {
|
|
124
|
+
if (this.isLoading) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
this.isLoading = true;
|
|
128
|
+
this.loadModel(this.entityID)
|
|
129
|
+
.pipe(take(1))
|
|
130
|
+
.subscribe({
|
|
131
|
+
next: (model) => {
|
|
132
|
+
this.isLoading = false;
|
|
133
|
+
this.updateModel(model);
|
|
134
|
+
},
|
|
135
|
+
error: (error) => {
|
|
136
|
+
this.isLoading = false;
|
|
137
|
+
this.isModelLoaded = true;
|
|
138
|
+
this.modelCache.next(null);
|
|
139
|
+
this.errorSubject.next(error);
|
|
140
|
+
},
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
resetForNewEntity() {
|
|
144
|
+
this._entityID = undefined;
|
|
145
|
+
this.isModelLoaded = false;
|
|
146
|
+
this.modelCache.next(null);
|
|
147
|
+
}
|
|
148
|
+
updateModel(model) {
|
|
149
|
+
this.isModelLoaded = true;
|
|
150
|
+
// Update entity ID if changed.
|
|
151
|
+
if (model && model.id !== this.entityID) {
|
|
152
|
+
this._entityID = model.id;
|
|
153
|
+
}
|
|
154
|
+
this.modelCache.next(model);
|
|
155
|
+
}
|
|
156
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: DataProviderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
157
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: DataProviderService });
|
|
158
|
+
}
|
|
159
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: DataProviderService, decorators: [{
|
|
160
|
+
type: Injectable
|
|
161
|
+
}], ctorParameters: () => [] });
|
|
162
|
+
|
|
163
|
+
class BaseDataset {
|
|
164
|
+
//#region ViewChilds, Inputs, Outputs
|
|
165
|
+
//#endregion
|
|
166
|
+
//#region Variables
|
|
167
|
+
dataProvider;
|
|
168
|
+
destroy$ = new Subject();
|
|
169
|
+
// TODO: Remove.
|
|
170
|
+
_parentEntityId;
|
|
171
|
+
//#endregion
|
|
172
|
+
//#region Properties
|
|
173
|
+
// TODO: Remove.
|
|
174
|
+
get parentEntityId() {
|
|
175
|
+
return this._parentEntityId;
|
|
176
|
+
}
|
|
177
|
+
set parentEntityId(value) {
|
|
178
|
+
this._parentEntityId = value;
|
|
179
|
+
}
|
|
180
|
+
//#endregion
|
|
181
|
+
//#region Constructor and Angular life cycle methods
|
|
182
|
+
constructor() {
|
|
183
|
+
this.dataProvider = inject(DataProviderService, { optional: true });
|
|
184
|
+
}
|
|
185
|
+
ngOnDestroy() {
|
|
186
|
+
this.destroy$.next(true);
|
|
187
|
+
this.destroy$.complete();
|
|
188
|
+
}
|
|
189
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: BaseDataset, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
190
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: BaseDataset });
|
|
191
|
+
}
|
|
192
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: BaseDataset, decorators: [{
|
|
193
|
+
type: Injectable
|
|
194
|
+
}], ctorParameters: () => [] });
|
|
195
|
+
|
|
196
|
+
class DateHelpers {
|
|
197
|
+
//#region Public methods
|
|
198
|
+
static diffDays(initialDate, finalDate) {
|
|
199
|
+
const initialDateOnly = new Date(initialDate.getFullYear(), initialDate.getMonth(), initialDate.getDate());
|
|
200
|
+
const finalDateOnly = new Date(finalDate.getFullYear(), finalDate.getMonth(), finalDate.getDate());
|
|
201
|
+
const diff = initialDateOnly.getTime() - finalDateOnly.getTime();
|
|
202
|
+
return Math.floor(diff / (1000 * 60 * 60 * 24));
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
class GuidHelper {
|
|
207
|
+
static generateGUID() {
|
|
208
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
|
209
|
+
const r = (Math.random() * 16) | 0;
|
|
210
|
+
const v = c === 'x' ? r : (r & 0x3) | 0x8;
|
|
211
|
+
return v.toString(16);
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
class RouterFormatter {
|
|
217
|
+
//#region ViewChilds, Inputs, Outputs
|
|
218
|
+
//#endregion
|
|
219
|
+
//#region Variables
|
|
220
|
+
//#endregion
|
|
221
|
+
//#region Properties
|
|
222
|
+
//#endregion
|
|
223
|
+
//#region Constructor and Angular life cycle methods
|
|
224
|
+
//#endregion
|
|
225
|
+
//#region Event handlers
|
|
226
|
+
//#endregion
|
|
227
|
+
//#region Public methods
|
|
228
|
+
static getURL(route) {
|
|
229
|
+
let parentRoute = '';
|
|
230
|
+
if (route.parent) {
|
|
231
|
+
parentRoute = this.getURL(route.parent);
|
|
232
|
+
}
|
|
233
|
+
let path = route.routeConfig?.path ?? '';
|
|
234
|
+
route.paramMap.keys
|
|
235
|
+
.forEach(k => {
|
|
236
|
+
path = path.replace(':' + k, k === 'view'
|
|
237
|
+
? ''
|
|
238
|
+
: (route.paramMap.get(k) ?? ''));
|
|
239
|
+
});
|
|
240
|
+
if (!route.parent || (parentRoute !== '' && parentRoute !== '/' && route.routeConfig?.path && path)) {
|
|
241
|
+
parentRoute += '/';
|
|
242
|
+
}
|
|
243
|
+
return parentRoute + path;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
class GridConfigsProvider {
|
|
248
|
+
//#region ViewChilds, Inputs, Outputs
|
|
249
|
+
//#endregion
|
|
250
|
+
//#region Variables
|
|
251
|
+
_configs;
|
|
252
|
+
//#endregion
|
|
253
|
+
//#region Properties
|
|
254
|
+
get configs() {
|
|
255
|
+
return this._configs;
|
|
256
|
+
}
|
|
257
|
+
//#endregion
|
|
258
|
+
//#region Constructor and Angular life cycle methods
|
|
259
|
+
constructor() {
|
|
260
|
+
this._configs = {
|
|
261
|
+
loadingDisplayText: 'Loading...',
|
|
262
|
+
messageOnEmpty: 'No results',
|
|
263
|
+
recordBlockSize: 100,
|
|
264
|
+
rowHeight: 41.6,
|
|
265
|
+
rowsToDisplay: 6,
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: GridConfigsProvider, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
269
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: GridConfigsProvider });
|
|
270
|
+
}
|
|
271
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: GridConfigsProvider, decorators: [{
|
|
272
|
+
type: Injectable
|
|
273
|
+
}], ctorParameters: () => [] });
|
|
274
|
+
|
|
275
|
+
const KEY_FIELD = '_key';
|
|
276
|
+
class GridDataset extends BaseDataset {
|
|
277
|
+
//#region ViewChilds, Inputs, Outputs
|
|
278
|
+
//#endregion
|
|
279
|
+
//#region Variables
|
|
280
|
+
configs;
|
|
281
|
+
filtersChanged = new EventEmitter();
|
|
282
|
+
isLoading = false;
|
|
283
|
+
loadedLastRow = false;
|
|
284
|
+
loadFinished = new EventEmitter();
|
|
285
|
+
loadStarted = new EventEmitter();
|
|
286
|
+
compareProperty = 'id';
|
|
287
|
+
configsProvider;
|
|
288
|
+
focusedRow = null;
|
|
289
|
+
recordBlock = 0;
|
|
290
|
+
_hasBeenLoaded = false;
|
|
291
|
+
_loadedKeys;
|
|
292
|
+
_loadedRows;
|
|
293
|
+
queryFilters;
|
|
294
|
+
//#endregion
|
|
295
|
+
//#region Properties
|
|
296
|
+
get filters() {
|
|
297
|
+
return this.queryFilters;
|
|
298
|
+
}
|
|
299
|
+
get hasBeenLoaded() {
|
|
300
|
+
return this._hasBeenLoaded;
|
|
301
|
+
}
|
|
302
|
+
get hasLoadedRows() {
|
|
303
|
+
return !!this._loadedRows && this._loadedRows.length > 0;
|
|
304
|
+
}
|
|
305
|
+
get keyProperty() {
|
|
306
|
+
return this.compareProperty;
|
|
307
|
+
}
|
|
308
|
+
get loadedKeys() {
|
|
309
|
+
return this._loadedKeys;
|
|
310
|
+
}
|
|
311
|
+
get loadedRows() {
|
|
312
|
+
return this._loadedRows;
|
|
313
|
+
}
|
|
314
|
+
get parentEntityId() {
|
|
315
|
+
return super.parentEntityId;
|
|
316
|
+
}
|
|
317
|
+
set parentEntityId(value) {
|
|
318
|
+
super.parentEntityId = value;
|
|
319
|
+
if (!!this.loadedRows) {
|
|
320
|
+
this.refresh();
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
//#endregion
|
|
324
|
+
//#region Constructor and Angular life cycle methods
|
|
325
|
+
constructor() {
|
|
326
|
+
super();
|
|
327
|
+
this.configsProvider = inject(GridConfigsProvider);
|
|
328
|
+
this.configs = JSON.parse(JSON.stringify(this.configsProvider.configs));
|
|
329
|
+
}
|
|
330
|
+
//#endregion
|
|
331
|
+
//#region Event handlers
|
|
332
|
+
//#endregion
|
|
333
|
+
//#region Public methods
|
|
334
|
+
addNewRow(row) {
|
|
335
|
+
this.updateLoadedRows([row]);
|
|
336
|
+
}
|
|
337
|
+
clearFocusedRow() {
|
|
338
|
+
this.focusedRow = null;
|
|
339
|
+
}
|
|
340
|
+
getRowData(key) {
|
|
341
|
+
if (this.hasLoadedRows) {
|
|
342
|
+
const index = this._loadedKeys.indexOf(key);
|
|
343
|
+
return this.loadedRows[index];
|
|
344
|
+
}
|
|
345
|
+
return null;
|
|
346
|
+
}
|
|
347
|
+
getRowID(key) {
|
|
348
|
+
const row = this.getRowData(key);
|
|
349
|
+
return this.compareProperty.split('.')
|
|
350
|
+
.reduce((row, property) => row[property], row);
|
|
351
|
+
}
|
|
352
|
+
getRowInternalKey(row) {
|
|
353
|
+
return row[KEY_FIELD];
|
|
354
|
+
}
|
|
355
|
+
hasRowWithID(id) {
|
|
356
|
+
if (!this.hasLoadedRows) {
|
|
357
|
+
return false;
|
|
358
|
+
}
|
|
359
|
+
const loadedIDs = this.compareProperty.split('.')
|
|
360
|
+
.reduce((loadedRows, property) => loadedRows.map((row) => row[property]), this._loadedRows ?? [])
|
|
361
|
+
.map((row) => typeof id === 'string' ? `${row}`
|
|
362
|
+
: typeof id === 'number' ? parseInt(`${row}`)
|
|
363
|
+
: row);
|
|
364
|
+
return loadedIDs.indexOf(id) >= 0;
|
|
365
|
+
}
|
|
366
|
+
isKeyExists(key) {
|
|
367
|
+
return this.hasLoadedRows && this._loadedKeys.some((x) => x === key);
|
|
368
|
+
}
|
|
369
|
+
loadRows() {
|
|
370
|
+
if (this.isLoading) {
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
this.isLoading = true;
|
|
374
|
+
this.loadStarted.emit();
|
|
375
|
+
const parameters = {
|
|
376
|
+
endRow: this.configsProvider.configs.recordBlockSize,
|
|
377
|
+
filters: this.queryFilters,
|
|
378
|
+
startRow: this.recordBlock,
|
|
379
|
+
};
|
|
380
|
+
this.getData(parameters)
|
|
381
|
+
.pipe(take(1))
|
|
382
|
+
.subscribe({
|
|
383
|
+
next: (rows) => {
|
|
384
|
+
this.updateLoadedRows(rows ?? []);
|
|
385
|
+
this.isLoading = false;
|
|
386
|
+
this._hasBeenLoaded = true;
|
|
387
|
+
this.loadFinished.emit(true);
|
|
388
|
+
},
|
|
389
|
+
error: (_) => {
|
|
390
|
+
this.isLoading = false;
|
|
391
|
+
this.loadFinished.emit(false);
|
|
392
|
+
}
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
refresh() {
|
|
396
|
+
if (this.focusedRow) {
|
|
397
|
+
this.clearFocusedRow();
|
|
398
|
+
}
|
|
399
|
+
this.clearLoadedRows();
|
|
400
|
+
this.loadRows();
|
|
401
|
+
}
|
|
402
|
+
removeKeys(keys) {
|
|
403
|
+
if (!this.hasLoadedRows) {
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
keys.forEach((key) => {
|
|
407
|
+
if (this.focusedRow === key) {
|
|
408
|
+
this.clearFocusedRow();
|
|
409
|
+
}
|
|
410
|
+
const indexToRemove = this._loadedKeys.indexOf(key);
|
|
411
|
+
if (indexToRemove >= 0) {
|
|
412
|
+
// Need to set again the array values to trigger the change detection.
|
|
413
|
+
this._loadedKeys = this._loadedKeys.filter((_, index) => index !== indexToRemove);
|
|
414
|
+
this._loadedRows = this._loadedRows.filter((_, index) => index !== indexToRemove);
|
|
415
|
+
}
|
|
416
|
+
});
|
|
417
|
+
}
|
|
418
|
+
setFilters(filters) {
|
|
419
|
+
this.queryFilters = filters;
|
|
420
|
+
this.filtersChanged.emit(filters);
|
|
421
|
+
this.refresh();
|
|
422
|
+
}
|
|
423
|
+
setFocusedRow(key) {
|
|
424
|
+
this.focusedRow = key;
|
|
425
|
+
}
|
|
426
|
+
updateRow(key, newRowData) {
|
|
427
|
+
if (!this.hasLoadedRows) {
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
430
|
+
const index = this._loadedKeys.indexOf(key);
|
|
431
|
+
if (index >= 0) {
|
|
432
|
+
// Need to set the KEY_FIELD value into the new data, to make sure this information is not lost.
|
|
433
|
+
newRowData[KEY_FIELD] = key;
|
|
434
|
+
this._loadedRows[index] = newRowData;
|
|
435
|
+
// Need to update loaded rows to force displayed rows to refresh.
|
|
436
|
+
this.updateLoadedRows([]);
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
//#endregion
|
|
440
|
+
//#region Private methods
|
|
441
|
+
clearLoadedRows() {
|
|
442
|
+
this._hasBeenLoaded = false;
|
|
443
|
+
this._loadedRows = undefined;
|
|
444
|
+
this._loadedKeys = undefined;
|
|
445
|
+
this.recordBlock = 0;
|
|
446
|
+
this.loadedLastRow = false;
|
|
447
|
+
}
|
|
448
|
+
updateLoadedRows(rows) {
|
|
449
|
+
// Assign individual key to each row.
|
|
450
|
+
rows.forEach((row) => {
|
|
451
|
+
row[KEY_FIELD] = GuidHelper.generateGUID();
|
|
452
|
+
});
|
|
453
|
+
this._loadedRows = [...this._loadedRows ?? [], ...rows];
|
|
454
|
+
this._loadedKeys = [...this._loadedKeys ?? [], ...rows.map((row) => row[KEY_FIELD])];
|
|
455
|
+
this.recordBlock += rows.length;
|
|
456
|
+
if (rows.length < this.configsProvider.configs.recordBlockSize) {
|
|
457
|
+
this.loadedLastRow = true;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: GridDataset, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
461
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: GridDataset });
|
|
462
|
+
}
|
|
463
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: GridDataset, decorators: [{
|
|
464
|
+
type: Injectable
|
|
465
|
+
}], ctorParameters: () => [] });
|
|
466
|
+
|
|
467
|
+
class DataGridDataset extends GridDataset {
|
|
468
|
+
//#region ViewChilds, Inputs, Outputs
|
|
469
|
+
selectedRowsChanged = new EventEmitter();
|
|
470
|
+
//#endregion
|
|
471
|
+
//#region Variables
|
|
472
|
+
columns;
|
|
473
|
+
configs;
|
|
474
|
+
selectedRowKeys = [];
|
|
475
|
+
//#endregion
|
|
476
|
+
//#region Properties
|
|
477
|
+
get columnsSize() {
|
|
478
|
+
const sizes = [];
|
|
479
|
+
if (this.configs.multiSelect) {
|
|
480
|
+
sizes.push(this.configs.multiSelectSize ?? 'minmax(1.5rem,min-content)');
|
|
481
|
+
}
|
|
482
|
+
sizes.push(...this.columns.map((col) => col.size ?? 'minmax(0,1fr)'));
|
|
483
|
+
return sizes.join(' ');
|
|
484
|
+
}
|
|
485
|
+
get hasSelectedRows() {
|
|
486
|
+
return this.selectedRowKeys.length > 0;
|
|
487
|
+
}
|
|
488
|
+
//#endregion
|
|
489
|
+
//#region Constructor and Angular life cycle methods
|
|
490
|
+
constructor() {
|
|
491
|
+
super();
|
|
492
|
+
this.configs = JSON.parse(JSON.stringify(this.configsProvider.configs));
|
|
493
|
+
}
|
|
494
|
+
//#endregion
|
|
495
|
+
//#region Event handlers
|
|
496
|
+
//#endregion
|
|
497
|
+
//#region Public methods
|
|
498
|
+
clearSelection() {
|
|
499
|
+
if (!this.hasLoadedRows || !this.hasSelectedRows) {
|
|
500
|
+
return;
|
|
501
|
+
}
|
|
502
|
+
const selectedKeys = this.selectedRowKeys;
|
|
503
|
+
this.selectedRowKeys = [];
|
|
504
|
+
this.clearFocusedRow();
|
|
505
|
+
this.selectedRowsChanged.emit(selectedKeys.reduce((keys, key) => {
|
|
506
|
+
keys[key] = {
|
|
507
|
+
rowData: this.getRowData(key),
|
|
508
|
+
selected: false
|
|
509
|
+
};
|
|
510
|
+
return keys;
|
|
511
|
+
}, {}));
|
|
512
|
+
}
|
|
513
|
+
deselectRow(key) {
|
|
514
|
+
if (!this.hasLoadedRows || !this.isKeySelected(key)) {
|
|
515
|
+
return;
|
|
516
|
+
}
|
|
517
|
+
this.removeSelectedRow(key);
|
|
518
|
+
this.selectedRowsChanged.emit({
|
|
519
|
+
[key]: {
|
|
520
|
+
rowData: this.getRowData(key),
|
|
521
|
+
selected: false,
|
|
522
|
+
}
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
deselectRowID(id) {
|
|
526
|
+
if (!this.hasLoadedRows) {
|
|
527
|
+
return;
|
|
528
|
+
}
|
|
529
|
+
const index = this.loadedKeys.map((key) => this.getRowID(key))
|
|
530
|
+
.indexOf(id);
|
|
531
|
+
const key = this.loadedKeys[index];
|
|
532
|
+
this.deselectRow(key);
|
|
533
|
+
}
|
|
534
|
+
getSelectedRowsData() {
|
|
535
|
+
if (!this.hasLoadedRows || !this.hasSelectedRows) {
|
|
536
|
+
return [];
|
|
537
|
+
}
|
|
538
|
+
return this.selectedRowKeys.map((key) => this.loadedKeys.indexOf(key))
|
|
539
|
+
.filter((index) => index >= 0)
|
|
540
|
+
.map((index) => this.loadedRows[index]);
|
|
541
|
+
}
|
|
542
|
+
isKeySelected(key) {
|
|
543
|
+
return this.selectedRowKeys.indexOf(key) >= 0;
|
|
544
|
+
}
|
|
545
|
+
refresh() {
|
|
546
|
+
if (this.hasSelectedRows) {
|
|
547
|
+
this.clearSelection();
|
|
548
|
+
}
|
|
549
|
+
super.refresh();
|
|
550
|
+
}
|
|
551
|
+
removeKeys(keys) {
|
|
552
|
+
if (!this.hasLoadedRows) {
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
555
|
+
if (this.hasSelectedRows) {
|
|
556
|
+
keys.filter((key) => this.isKeySelected(key))
|
|
557
|
+
.forEach((key) => {
|
|
558
|
+
this.removeSelectedRow(key);
|
|
559
|
+
});
|
|
560
|
+
}
|
|
561
|
+
super.removeKeys(keys);
|
|
562
|
+
}
|
|
563
|
+
selectRow(key) {
|
|
564
|
+
if (!this.hasLoadedRows) {
|
|
565
|
+
return;
|
|
566
|
+
}
|
|
567
|
+
if (!this.configs.multiSelect) {
|
|
568
|
+
if (this.isKeySelected(key)) {
|
|
569
|
+
return;
|
|
570
|
+
}
|
|
571
|
+
// Clear current selected row.
|
|
572
|
+
this.removeSelectedRow(this.selectedRowKeys[0]);
|
|
573
|
+
}
|
|
574
|
+
if (!this.isKeySelected(key)) {
|
|
575
|
+
this.selectedRowKeys.push(key);
|
|
576
|
+
this.selectedRowsChanged.emit({
|
|
577
|
+
[key]: {
|
|
578
|
+
rowData: this.getRowData(key),
|
|
579
|
+
selected: true,
|
|
580
|
+
}
|
|
581
|
+
});
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
selectRowID(id) {
|
|
585
|
+
if (!this.hasLoadedRows) {
|
|
586
|
+
return;
|
|
587
|
+
}
|
|
588
|
+
if (this.hasRowWithID(id)) {
|
|
589
|
+
const rowIndex = this.loadedRows.findIndex((row) => row[this.compareProperty] === id);
|
|
590
|
+
if (rowIndex < 0) {
|
|
591
|
+
return;
|
|
592
|
+
}
|
|
593
|
+
const key = this.loadedKeys[rowIndex];
|
|
594
|
+
if (!!key) {
|
|
595
|
+
this.selectRow(key);
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
selectRows(keys) {
|
|
600
|
+
if (!this.hasLoadedRows || !this.configs.multiSelect) {
|
|
601
|
+
return;
|
|
602
|
+
}
|
|
603
|
+
// Filter only the keys that are not selected yet.
|
|
604
|
+
const keysNotSelected = keys.filter((key) => !this.isKeySelected(key));
|
|
605
|
+
if (keysNotSelected.length > 0) {
|
|
606
|
+
this.selectedRowKeys.push(...keysNotSelected);
|
|
607
|
+
this.selectedRowsChanged.emit(keys.reduce((keys, key) => {
|
|
608
|
+
keys[key] = {
|
|
609
|
+
rowData: this.getRowData(key),
|
|
610
|
+
selected: true,
|
|
611
|
+
};
|
|
612
|
+
return keys;
|
|
613
|
+
}, {}));
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
setFocusedRow(key) {
|
|
617
|
+
super.setFocusedRow(key);
|
|
618
|
+
if (!this.configs.multiSelect) {
|
|
619
|
+
this.selectRow(key);
|
|
620
|
+
}
|
|
621
|
+
else if (this.configs.selectOnClick ?? true) {
|
|
622
|
+
if (this.isKeySelected(key)) {
|
|
623
|
+
this.deselectRow(key);
|
|
624
|
+
}
|
|
625
|
+
else {
|
|
626
|
+
this.selectRow(key);
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
//#endregion
|
|
631
|
+
//#region Private methods
|
|
632
|
+
removeSelectedRow(key) {
|
|
633
|
+
const index = this.selectedRowKeys.indexOf(key);
|
|
634
|
+
if (index >= 0) {
|
|
635
|
+
this.selectedRowKeys.splice(index, 1);
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: DataGridDataset, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
639
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: DataGridDataset });
|
|
640
|
+
}
|
|
641
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: DataGridDataset, decorators: [{
|
|
642
|
+
type: Injectable
|
|
643
|
+
}], ctorParameters: () => [] });
|
|
644
|
+
|
|
645
|
+
class MultiEditorDataset extends BaseDataset {
|
|
646
|
+
//#region ViewChilds, Inputs, Outputs
|
|
647
|
+
savedChanges = new EventEmitter();
|
|
648
|
+
//#endregion
|
|
649
|
+
//#region Variables
|
|
650
|
+
dataGridDataset;
|
|
651
|
+
fakeIDsGenerated = [];
|
|
652
|
+
modifiedValues = {
|
|
653
|
+
changed: {},
|
|
654
|
+
removed: [],
|
|
655
|
+
};
|
|
656
|
+
//#endregion
|
|
657
|
+
//#region Properties
|
|
658
|
+
//#endregion
|
|
659
|
+
//#region Constructor and Angular life cycle methods
|
|
660
|
+
constructor() {
|
|
661
|
+
super();
|
|
662
|
+
this.dataGridDataset = inject(DataGridDataset);
|
|
663
|
+
}
|
|
664
|
+
//#endregion
|
|
665
|
+
//#region Event handlers
|
|
666
|
+
//#endregion
|
|
667
|
+
//#region Public methods
|
|
668
|
+
clearChangedValues() {
|
|
669
|
+
this.fakeIDsGenerated = [];
|
|
670
|
+
this.modifiedValues = {
|
|
671
|
+
changed: {},
|
|
672
|
+
removed: [],
|
|
673
|
+
};
|
|
674
|
+
}
|
|
675
|
+
removeValue(key) {
|
|
676
|
+
if (this.modifiedValues.changed[key]) {
|
|
677
|
+
delete this.modifiedValues.changed[key];
|
|
678
|
+
}
|
|
679
|
+
const id = this.dataGridDataset.getRowID(key);
|
|
680
|
+
this.dataGridDataset.removeKeys([key]);
|
|
681
|
+
if (!id) {
|
|
682
|
+
return;
|
|
683
|
+
}
|
|
684
|
+
if (this.fakeIDsGenerated.indexOf(id) < 0) {
|
|
685
|
+
this.modifiedValues.removed.push(id);
|
|
686
|
+
}
|
|
687
|
+
else {
|
|
688
|
+
this.fakeIDsGenerated.splice(this.fakeIDsGenerated.indexOf(id), 1);
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
saveChanges() {
|
|
692
|
+
const batchUpdate = {
|
|
693
|
+
entitiesToInsertOrUpdate: Object.entries(this.modifiedValues.changed).map(([_, v]) => v),
|
|
694
|
+
entitiesToDelete: this.modifiedValues.removed,
|
|
695
|
+
};
|
|
696
|
+
return this.saveData(batchUpdate)
|
|
697
|
+
.pipe(tap(() => this.savedChanges.emit()));
|
|
698
|
+
}
|
|
699
|
+
storeFakeIDGenerated(id) {
|
|
700
|
+
if (this.fakeIDsGenerated.indexOf(id) >= 0) {
|
|
701
|
+
return;
|
|
702
|
+
}
|
|
703
|
+
this.fakeIDsGenerated.push(id);
|
|
704
|
+
}
|
|
705
|
+
updateValues(key, newRowData) {
|
|
706
|
+
this.modifiedValues.changed[key] = newRowData;
|
|
707
|
+
this.dataGridDataset.updateRow(key, newRowData);
|
|
708
|
+
}
|
|
709
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: MultiEditorDataset, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
710
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: MultiEditorDataset });
|
|
711
|
+
}
|
|
712
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: MultiEditorDataset, decorators: [{
|
|
713
|
+
type: Injectable
|
|
714
|
+
}], ctorParameters: () => [] });
|
|
715
|
+
|
|
716
|
+
class MultiSelectResultDataset extends GridDataset {
|
|
717
|
+
//#region ViewChilds, Inputs, Outputs
|
|
718
|
+
savedChanges = new EventEmitter();
|
|
719
|
+
//#endregion
|
|
720
|
+
//#region Variables
|
|
721
|
+
displayedIDs = [];
|
|
722
|
+
displayedRows = [];
|
|
723
|
+
_idsToAdd = [];
|
|
724
|
+
_idsToRemove = [];
|
|
725
|
+
addedRowData = [];
|
|
726
|
+
//#endregion
|
|
727
|
+
//#region Properties
|
|
728
|
+
get idsToAdd() {
|
|
729
|
+
return this._idsToAdd;
|
|
730
|
+
}
|
|
731
|
+
get idsToRemove() {
|
|
732
|
+
return this._idsToRemove;
|
|
733
|
+
}
|
|
734
|
+
//#endregion
|
|
735
|
+
//#region Constructor and Angular life cycle methods
|
|
736
|
+
//#endregion
|
|
737
|
+
//#region Event handlers
|
|
738
|
+
//#endregion
|
|
739
|
+
//#region Public methods
|
|
740
|
+
refresh() {
|
|
741
|
+
this.clearSelection();
|
|
742
|
+
super.refresh();
|
|
743
|
+
}
|
|
744
|
+
saveChanges() {
|
|
745
|
+
const changes = {
|
|
746
|
+
idsToAdd: this.idsToAdd,
|
|
747
|
+
idsToRemove: this.idsToRemove,
|
|
748
|
+
};
|
|
749
|
+
return this.saveData(changes)
|
|
750
|
+
.pipe(tap(() => {
|
|
751
|
+
this.savedChanges.emit();
|
|
752
|
+
this.clearSelection();
|
|
753
|
+
this.clearLoadedRows();
|
|
754
|
+
}));
|
|
755
|
+
}
|
|
756
|
+
setIDToAdd(idToAdd, rowData) {
|
|
757
|
+
const index = this._idsToRemove.indexOf(idToAdd);
|
|
758
|
+
if (index >= 0) {
|
|
759
|
+
this._idsToRemove.splice(index, 1);
|
|
760
|
+
}
|
|
761
|
+
else if (!this.isExistingID(idToAdd)) {
|
|
762
|
+
this._idsToAdd.push(idToAdd);
|
|
763
|
+
this.addedRowData.push(rowData);
|
|
764
|
+
}
|
|
765
|
+
this.updateDisplayedRows();
|
|
766
|
+
}
|
|
767
|
+
setIDToRemove(idToRemove) {
|
|
768
|
+
const index = this._idsToAdd.indexOf(idToRemove);
|
|
769
|
+
if (index >= 0) {
|
|
770
|
+
this._idsToAdd.splice(index, 1);
|
|
771
|
+
this.addedRowData.splice(index, 1);
|
|
772
|
+
}
|
|
773
|
+
else if (this.isExistingID(idToRemove)) {
|
|
774
|
+
this._idsToRemove.push(idToRemove);
|
|
775
|
+
}
|
|
776
|
+
this.updateDisplayedRows();
|
|
777
|
+
}
|
|
778
|
+
updateLoadedRows(rows) {
|
|
779
|
+
super.updateLoadedRows(rows);
|
|
780
|
+
this.updateDisplayedRows();
|
|
781
|
+
}
|
|
782
|
+
//#endregion
|
|
783
|
+
//#region Private methods
|
|
784
|
+
clearSelection() {
|
|
785
|
+
this._idsToAdd = [];
|
|
786
|
+
this._idsToRemove = [];
|
|
787
|
+
this.addedRowData = [];
|
|
788
|
+
this.updateDisplayedRows();
|
|
789
|
+
}
|
|
790
|
+
isExistingID(id) {
|
|
791
|
+
return (this.loadedKeys ?? [])
|
|
792
|
+
.map((key) => this.getRowID(key))
|
|
793
|
+
.indexOf(id) >= 0;
|
|
794
|
+
}
|
|
795
|
+
updateDisplayedRows() {
|
|
796
|
+
const loadedKeys = (this.loadedKeys ?? [])
|
|
797
|
+
.filter((key) => this.idsToRemove.indexOf(this.getRowID(key)) < 0);
|
|
798
|
+
this.displayedIDs = loadedKeys.map((key) => this.getRowID(key));
|
|
799
|
+
this.displayedIDs.push(...this._idsToAdd);
|
|
800
|
+
this.displayedRows = loadedKeys.map((key) => this.getRowData(key));
|
|
801
|
+
this.displayedRows.push(...this.addedRowData);
|
|
802
|
+
}
|
|
803
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: MultiSelectResultDataset, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
|
|
804
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: MultiSelectResultDataset });
|
|
805
|
+
}
|
|
806
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: MultiSelectResultDataset, decorators: [{
|
|
807
|
+
type: Injectable
|
|
808
|
+
}] });
|
|
809
|
+
|
|
810
|
+
class FormGroupService {
|
|
811
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: FormGroupService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
812
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: FormGroupService });
|
|
813
|
+
}
|
|
814
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: FormGroupService, decorators: [{
|
|
815
|
+
type: Injectable
|
|
816
|
+
}] });
|
|
817
|
+
|
|
818
|
+
class FormService {
|
|
819
|
+
//#region ViewChilds, Inputs, Outputs
|
|
820
|
+
fieldRefreshed = new EventEmitter();
|
|
821
|
+
modelRefreshed = new EventEmitter;
|
|
822
|
+
//#endregion
|
|
823
|
+
//#region Variables
|
|
824
|
+
_loading = false;
|
|
825
|
+
_model = null;
|
|
826
|
+
currentMode = 'view';
|
|
827
|
+
editCanceled$ = new Subject();
|
|
828
|
+
form;
|
|
829
|
+
initialValue;
|
|
830
|
+
//#endregion
|
|
831
|
+
//#region Properties
|
|
832
|
+
get editCanceled() {
|
|
833
|
+
return this.editCanceled$.asObservable();
|
|
834
|
+
}
|
|
835
|
+
get isEditMode() {
|
|
836
|
+
return this.currentMode === 'edit';
|
|
837
|
+
}
|
|
838
|
+
get isValid() {
|
|
839
|
+
return this.form?.valid ?? false;
|
|
840
|
+
}
|
|
841
|
+
get loading() {
|
|
842
|
+
return this._loading;
|
|
843
|
+
}
|
|
844
|
+
set loading(value) {
|
|
845
|
+
if (this._loading !== value) {
|
|
846
|
+
this._loading = value;
|
|
847
|
+
if (value) {
|
|
848
|
+
this.form?.disable();
|
|
849
|
+
}
|
|
850
|
+
else if (this.isEditMode) {
|
|
851
|
+
this.form?.enable();
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
get model() {
|
|
856
|
+
return this._model;
|
|
857
|
+
}
|
|
858
|
+
set model(value) {
|
|
859
|
+
if (this._model !== value) {
|
|
860
|
+
this._model = value;
|
|
861
|
+
this.modelRefreshed.emit(value);
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
//#endregion
|
|
865
|
+
//#region Constructor and Angular life cycle methods
|
|
866
|
+
//#endregion
|
|
867
|
+
//#region Event handlers
|
|
868
|
+
//#endregion
|
|
869
|
+
//#region Public methods
|
|
870
|
+
beginEdit() {
|
|
871
|
+
this.currentMode = 'edit';
|
|
872
|
+
this.form?.enable();
|
|
873
|
+
}
|
|
874
|
+
beginFieldLoading(fieldName) {
|
|
875
|
+
this.fieldRefreshed.emit({
|
|
876
|
+
fieldName,
|
|
877
|
+
loading: true
|
|
878
|
+
});
|
|
879
|
+
}
|
|
880
|
+
cancelEdit() {
|
|
881
|
+
this.currentMode = 'view';
|
|
882
|
+
this.form?.disable();
|
|
883
|
+
this.resetForm();
|
|
884
|
+
this.editCanceled$.next();
|
|
885
|
+
}
|
|
886
|
+
disableForm() {
|
|
887
|
+
this.form?.disable();
|
|
888
|
+
}
|
|
889
|
+
enableForm() {
|
|
890
|
+
if (this.isEditMode) {
|
|
891
|
+
this.form?.enable();
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
getModelFromForm() {
|
|
895
|
+
return this.form?.getRawValue();
|
|
896
|
+
}
|
|
897
|
+
initializeForm(form) {
|
|
898
|
+
this.form = form;
|
|
899
|
+
this.initialValue = form.getRawValue();
|
|
900
|
+
if (this.currentMode === 'view') {
|
|
901
|
+
this.form.disable();
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
markAllAsTouched() {
|
|
905
|
+
if (!this.form) {
|
|
906
|
+
return;
|
|
907
|
+
}
|
|
908
|
+
this.form.markAllAsTouched();
|
|
909
|
+
}
|
|
910
|
+
resetForm() {
|
|
911
|
+
if (!this.form) {
|
|
912
|
+
return;
|
|
913
|
+
}
|
|
914
|
+
this.form.reset();
|
|
915
|
+
if (!!this.model) {
|
|
916
|
+
this.form.patchValue(this.model);
|
|
917
|
+
}
|
|
918
|
+
else if (!!this.initialValue) {
|
|
919
|
+
this.form.patchValue(this.initialValue);
|
|
920
|
+
}
|
|
921
|
+
this.form.updateValueAndValidity();
|
|
922
|
+
}
|
|
923
|
+
setFieldValue(fieldName, value) {
|
|
924
|
+
this.fieldRefreshed.emit({
|
|
925
|
+
fieldName,
|
|
926
|
+
loading: false,
|
|
927
|
+
value,
|
|
928
|
+
});
|
|
929
|
+
}
|
|
930
|
+
setValidationErrorsFromHttpResponse(errorResponse) {
|
|
931
|
+
if (!errorResponse || !this.form) {
|
|
932
|
+
return;
|
|
933
|
+
}
|
|
934
|
+
// Error 400 = Validation issues
|
|
935
|
+
if (errorResponse.status === 400 && errorResponse.error && errorResponse.error.errors) {
|
|
936
|
+
const errors = errorResponse.error.errors;
|
|
937
|
+
Object.keys(errors)
|
|
938
|
+
.map((x) => { return { key: x, field: x.substring(0, 1).toLocaleLowerCase() + x.substring(1, x.length) }; })
|
|
939
|
+
.forEach((err) => {
|
|
940
|
+
setTimeout(() => {
|
|
941
|
+
const field = this.form.get(err.field);
|
|
942
|
+
field?.setErrors({ [errors[err.key][0]]: true });
|
|
943
|
+
field?.markAsTouched();
|
|
944
|
+
});
|
|
945
|
+
});
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: FormService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
949
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: FormService });
|
|
950
|
+
}
|
|
951
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: FormService, decorators: [{
|
|
952
|
+
type: Injectable
|
|
953
|
+
}] });
|
|
954
|
+
|
|
955
|
+
class RibbonGroupChild {
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
const SIDEBAR_CONFIGS = new InjectionToken('', {
|
|
959
|
+
providedIn: 'root',
|
|
960
|
+
factory: () => new SidebarConfigs(),
|
|
961
|
+
});
|
|
962
|
+
class SidebarConfigs {
|
|
963
|
+
errorText = 'Error';
|
|
964
|
+
loadingText = 'Loading';
|
|
965
|
+
logoCollapsedPath;
|
|
966
|
+
logoExpandedPath;
|
|
967
|
+
constructor(options = {}) {
|
|
968
|
+
Object.assign(this, options);
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
class SidebarMenu {
|
|
973
|
+
childCount = 0;
|
|
974
|
+
children = [];
|
|
975
|
+
height;
|
|
976
|
+
icon;
|
|
977
|
+
id = 0;
|
|
978
|
+
label = '';
|
|
979
|
+
isSelected = false;
|
|
980
|
+
parent = null;
|
|
981
|
+
url;
|
|
982
|
+
constructor(options = {}) {
|
|
983
|
+
Object.assign(this, options);
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
class SidebarService {
|
|
988
|
+
//#region ViewChilds, Inputs, Outputs
|
|
989
|
+
childrenFailed = new EventEmitter();
|
|
990
|
+
childrenLoading = new EventEmitter();
|
|
991
|
+
childrenInitialized = new EventEmitter();
|
|
992
|
+
menuUrlSelected = new EventEmitter();
|
|
993
|
+
selectionChanged = new EventEmitter();
|
|
994
|
+
//#endregion
|
|
995
|
+
//#region Variables
|
|
996
|
+
isActive = false;
|
|
997
|
+
isCollapsed = false;
|
|
998
|
+
shouldActivate = false;
|
|
999
|
+
menus = [];
|
|
1000
|
+
selectedMenu = null;
|
|
1001
|
+
//#endregion
|
|
1002
|
+
//#region Properties
|
|
1003
|
+
//#endregion
|
|
1004
|
+
//#region Constructor and Angular life cycle methods
|
|
1005
|
+
//#endregion
|
|
1006
|
+
//#region Public methods
|
|
1007
|
+
deselectAll() {
|
|
1008
|
+
this.menus
|
|
1009
|
+
.filter((menu) => menu.isSelected)
|
|
1010
|
+
.forEach((menu) => {
|
|
1011
|
+
this.deselectMenu(menu);
|
|
1012
|
+
});
|
|
1013
|
+
}
|
|
1014
|
+
loadChildren(parentMenu) {
|
|
1015
|
+
this.childrenLoading.emit(parentMenu);
|
|
1016
|
+
this.loadMenus(parentMenu)
|
|
1017
|
+
.pipe(take(1), map((menus) => menus.map((menu) => new SidebarMenu(menu))))
|
|
1018
|
+
.subscribe({
|
|
1019
|
+
next: (childrenMenus) => {
|
|
1020
|
+
parentMenu.children = childrenMenus;
|
|
1021
|
+
childrenMenus.forEach((childMenu) => childMenu.parent = parentMenu);
|
|
1022
|
+
},
|
|
1023
|
+
error: (exception) => {
|
|
1024
|
+
this.childrenFailed.emit(parentMenu);
|
|
1025
|
+
throw exception;
|
|
1026
|
+
}
|
|
1027
|
+
});
|
|
1028
|
+
}
|
|
1029
|
+
loadRoot() {
|
|
1030
|
+
return this.loadMenus(null)
|
|
1031
|
+
.pipe(take(1), map((menus) => menus.map((menu) => new SidebarMenu(menu))), tap((menus) => this.menus = menus));
|
|
1032
|
+
}
|
|
1033
|
+
select(menu) {
|
|
1034
|
+
if (menu.childCount > 0 && (menu.children?.length ?? 0) === 0) {
|
|
1035
|
+
this.loadChildren(menu);
|
|
1036
|
+
}
|
|
1037
|
+
const hasUrl = (menu.url?.length ?? 0) > 0;
|
|
1038
|
+
// In case we're deselecting the menu because a child was selected, we need to keep track of the original selection state.
|
|
1039
|
+
const isSelected = menu.isSelected;
|
|
1040
|
+
if (!!this.selectedMenu && this.selectedMenu !== menu) {
|
|
1041
|
+
this.deselectAll();
|
|
1042
|
+
}
|
|
1043
|
+
if (!isSelected) {
|
|
1044
|
+
this.selectedMenu = menu;
|
|
1045
|
+
this.selectMenu(menu);
|
|
1046
|
+
if (hasUrl) {
|
|
1047
|
+
this.menuUrlSelected.emit(menu);
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
else if (hasUrl) {
|
|
1051
|
+
// Menu with a URL is already selected — navigate again instead of toggling off.
|
|
1052
|
+
this.menuUrlSelected.emit(menu);
|
|
1053
|
+
}
|
|
1054
|
+
else {
|
|
1055
|
+
this.selectedMenu = null;
|
|
1056
|
+
this.deselectMenu(menu);
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
//#endregion
|
|
1060
|
+
//#region Private methods
|
|
1061
|
+
deselectMenu(menu, shouldUpdateParents = true) {
|
|
1062
|
+
if (!menu.isSelected) {
|
|
1063
|
+
return;
|
|
1064
|
+
}
|
|
1065
|
+
menu.isSelected = false;
|
|
1066
|
+
this.selectionChanged.emit(menu);
|
|
1067
|
+
if ((menu.children?.length ?? 0) > 0) {
|
|
1068
|
+
menu.children
|
|
1069
|
+
.filter((child) => child.isSelected)
|
|
1070
|
+
.forEach((child) => {
|
|
1071
|
+
const shouldUpdateParents = false;
|
|
1072
|
+
this.deselectMenu(child, shouldUpdateParents);
|
|
1073
|
+
});
|
|
1074
|
+
}
|
|
1075
|
+
if (!!menu.parent && shouldUpdateParents) {
|
|
1076
|
+
while (!!menu.parent) {
|
|
1077
|
+
this.selectionChanged.emit(menu.parent);
|
|
1078
|
+
menu = menu.parent;
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
selectMenu(menu) {
|
|
1083
|
+
menu.isSelected = true;
|
|
1084
|
+
this.selectionChanged.emit(menu);
|
|
1085
|
+
if (!!menu.parent) {
|
|
1086
|
+
this.selectMenu(menu.parent);
|
|
1087
|
+
}
|
|
1088
|
+
}
|
|
1089
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: SidebarService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1090
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: SidebarService, providedIn: 'root' });
|
|
1091
|
+
}
|
|
1092
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: SidebarService, decorators: [{
|
|
1093
|
+
type: Injectable,
|
|
1094
|
+
args: [{
|
|
1095
|
+
providedIn: 'root'
|
|
1096
|
+
}]
|
|
1097
|
+
}] });
|
|
1098
|
+
|
|
1099
|
+
class FormInputComponent extends BaseComponent {
|
|
1100
|
+
//#region ViewChilds, Inputs, Outputs
|
|
1101
|
+
autofocus = false;
|
|
1102
|
+
controlName = '';
|
|
1103
|
+
disabledControlName;
|
|
1104
|
+
displayReadOnlyAsDisabled = true;
|
|
1105
|
+
fixedValue;
|
|
1106
|
+
format;
|
|
1107
|
+
invalid = false;
|
|
1108
|
+
isDisabled = true;
|
|
1109
|
+
isFullHeight = false;
|
|
1110
|
+
maxLength;
|
|
1111
|
+
min;
|
|
1112
|
+
readOnly = false;
|
|
1113
|
+
rows;
|
|
1114
|
+
step = 1;
|
|
1115
|
+
type = 'text';
|
|
1116
|
+
blur = new EventEmitter();
|
|
1117
|
+
change = new EventEmitter();
|
|
1118
|
+
fixedValueChanged = new EventEmitter();
|
|
1119
|
+
input = new EventEmitter();
|
|
1120
|
+
focus = new EventEmitter();
|
|
1121
|
+
//#endregion
|
|
1122
|
+
//#region Host listeners
|
|
1123
|
+
//#endregion
|
|
1124
|
+
//#region Variables
|
|
1125
|
+
formGroupDirective = inject(FormGroupDirective);
|
|
1126
|
+
formGroupName = inject(FormGroupName, { optional: true });
|
|
1127
|
+
formService = inject(FormService);
|
|
1128
|
+
//#endregion
|
|
1129
|
+
//#region Properties
|
|
1130
|
+
get formControl() {
|
|
1131
|
+
return this.controlName
|
|
1132
|
+
? this.formGroup.get(this.controlName)
|
|
1133
|
+
: null;
|
|
1134
|
+
}
|
|
1135
|
+
get formControlName() {
|
|
1136
|
+
return [
|
|
1137
|
+
...this.parentGroups,
|
|
1138
|
+
this.controlName,
|
|
1139
|
+
].join('.');
|
|
1140
|
+
}
|
|
1141
|
+
get formGroup() {
|
|
1142
|
+
let formGroup = this.formGroupDirective.form;
|
|
1143
|
+
for (let group of this.parentGroups) {
|
|
1144
|
+
formGroup = formGroup.get(group);
|
|
1145
|
+
}
|
|
1146
|
+
return formGroup;
|
|
1147
|
+
}
|
|
1148
|
+
get isFormControl() {
|
|
1149
|
+
return !!this.controlName && this.controlName.length > 0;
|
|
1150
|
+
}
|
|
1151
|
+
get isFormEditMode() {
|
|
1152
|
+
return this.formService.isEditMode;
|
|
1153
|
+
}
|
|
1154
|
+
get parentGroups() {
|
|
1155
|
+
return this.formGroupName?.path ?? [];
|
|
1156
|
+
}
|
|
1157
|
+
get stepAttributeValue() {
|
|
1158
|
+
if (this.type === 'number') {
|
|
1159
|
+
return this.step;
|
|
1160
|
+
}
|
|
1161
|
+
return null;
|
|
1162
|
+
}
|
|
1163
|
+
get minAttributeValue() {
|
|
1164
|
+
if (this.type === 'number') {
|
|
1165
|
+
return this.min ?? null;
|
|
1166
|
+
}
|
|
1167
|
+
return null;
|
|
1168
|
+
}
|
|
1169
|
+
//#endregion
|
|
1170
|
+
//#region Constructor and Angular life cycle methods
|
|
1171
|
+
constructor() {
|
|
1172
|
+
super();
|
|
1173
|
+
}
|
|
1174
|
+
ngOnInit() {
|
|
1175
|
+
switch (this.type) {
|
|
1176
|
+
case 'number':
|
|
1177
|
+
if (!!this.formControl) {
|
|
1178
|
+
this.formControl.valueChanges
|
|
1179
|
+
.pipe(takeUntil(this.destroy$))
|
|
1180
|
+
.subscribe((value) => {
|
|
1181
|
+
if (value !== null && value === '') {
|
|
1182
|
+
this.formControl?.setValue(null);
|
|
1183
|
+
}
|
|
1184
|
+
});
|
|
1185
|
+
}
|
|
1186
|
+
break;
|
|
1187
|
+
case 'date':
|
|
1188
|
+
if (this.format === undefined) {
|
|
1189
|
+
this.format = 'yyyy-MM-dd';
|
|
1190
|
+
}
|
|
1191
|
+
if (!!this.formControl) {
|
|
1192
|
+
this.formControl.valueChanges
|
|
1193
|
+
.pipe(takeUntil(this.destroy$))
|
|
1194
|
+
.subscribe((value) => {
|
|
1195
|
+
if (value !== null) {
|
|
1196
|
+
try {
|
|
1197
|
+
if (value !== formatDate(value, 'yyyy-MM-dd', 'en')) {
|
|
1198
|
+
this.formControl?.setValue(formatDate(value, 'yyyy-MM-dd', 'en'), { emitEvent: false });
|
|
1199
|
+
}
|
|
1200
|
+
}
|
|
1201
|
+
catch {
|
|
1202
|
+
this.formControl?.setValue(null, { emitEvent: false });
|
|
1203
|
+
}
|
|
1204
|
+
}
|
|
1205
|
+
});
|
|
1206
|
+
}
|
|
1207
|
+
break;
|
|
1208
|
+
}
|
|
1209
|
+
}
|
|
1210
|
+
//#endregion
|
|
1211
|
+
//#region Event handlers
|
|
1212
|
+
onBlur() {
|
|
1213
|
+
this.blur.emit();
|
|
1214
|
+
}
|
|
1215
|
+
onChange(value) {
|
|
1216
|
+
this.change.emit(value);
|
|
1217
|
+
}
|
|
1218
|
+
onFocus() {
|
|
1219
|
+
this.focus.emit();
|
|
1220
|
+
}
|
|
1221
|
+
onInput() {
|
|
1222
|
+
this.input.emit();
|
|
1223
|
+
}
|
|
1224
|
+
onValueChanged(newText) {
|
|
1225
|
+
this.fixedValue = newText;
|
|
1226
|
+
this.fixedValueChanged.emit(this.fixedValue);
|
|
1227
|
+
}
|
|
1228
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: FormInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1229
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.6", type: FormInputComponent, isStandalone: true, selector: "lib-form-input", inputs: { autofocus: "autofocus", controlName: "controlName", disabledControlName: "disabledControlName", displayReadOnlyAsDisabled: "displayReadOnlyAsDisabled", fixedValue: "fixedValue", format: "format", invalid: "invalid", isDisabled: "isDisabled", isFullHeight: "isFullHeight", maxLength: "maxLength", min: "min", readOnly: "readOnly", rows: "rows", step: "step", type: "type" }, outputs: { blur: "blur", change: "change", fixedValueChanged: "fixedValueChanged", input: "input", focus: "focus" }, host: { properties: { "class.full-height": "isFullHeight" } }, usesInheritance: true, ngImport: i0, template: "<ng-container *ngIf=\"formGroupDirective.form?.enabled || isFormEditMode;else disabledControl\">\n <ng-container [ngSwitch]=\"type\">\n \n <textarea *ngSwitchCase=\"'textarea'\"\n [attr.autofocus]=\"autofocus ? true : null\"\n [attr.maxLength]=\"maxLength ?? null\"\n [attr.rows]=\"rows\"\n [class.invalid]=\"invalid\"\n [formControlName]=\"controlName\"\n (blur)=\"onBlur()\"\n (focus)=\"onFocus()\"\n (input)=\"onInput()\">\n </textarea>\n\n <ng-container *ngSwitchCase=\"'checkbox'\">\n <input *ngIf=\"isFormControl; else fixedCheckbox\"\n class=\"switch\"\n type=\"checkbox\"\n [attr.autofocus]=\"autofocus ? true : null\"\n [class.invalid]=\"invalid\"\n [formControlName]=\"controlName\"\n (blur)=\"onBlur()\"\n (focus)=\"onFocus()\"\n (input)=\"onInput()\" />\n\n <ng-template #fixedCheckbox>\n <input\n class=\"switch\"\n type=\"checkbox\"\n [(ngModel)]=\"fixedValue\"\n [attr.readonly]=\"true\"\n [class.invalid]=\"invalid\"\n [class.readonly-as-disabled]=\"displayReadOnlyAsDisabled\"\n [disabled]=\"isDisabled\"\n [ngModelOptions]=\"{ standalone: true }\"\n (blur)=\"onBlur()\"\n (change)=\"onChange($event)\"\n (focus)=\"onFocus()\"\n (input)=\"onInput()\"\n (ngModelChange)=\"onValueChanged($event)\" />\n </ng-template>\n </ng-container>\n\n\n <ng-container *ngSwitchDefault>\n <input *ngIf=\"isFormControl; else fixedTextBox\"\n [attr.autofocus]=\"autofocus ? true : null\"\n [attr.maxLength]=\"maxLength ?? null\"\n [attr.min]=\"minAttributeValue\"\n [attr.readonly]=\"readOnly ? true : null\"\n [attr.step]=\"stepAttributeValue\"\n [class.invalid]=\"invalid\"\n [class.readonly-as-disabled]=\"displayReadOnlyAsDisabled\"\n [formControlName]=\"controlName\"\n [type]=\"type\"\n (blur)=\"onBlur()\"\n (focus)=\"onFocus()\"\n (input)=\"onInput()\" />\n\n <ng-template #fixedTextBox>\n <input\n type=\"text\"\n [attr.maxLength]=\"maxLength ?? null\"\n [attr.min]=\"minAttributeValue\"\n [attr.readonly]=\"true\"\n [attr.step]=\"stepAttributeValue\"\n [class.invalid]=\"invalid\"\n [class.readonly-as-disabled]=\"displayReadOnlyAsDisabled\"\n [disabled]=\"isDisabled\"\n [ngModel]=\"type === 'date' || type === 'datetime-local' ? (fixedValue | date: format) : ( type === 'number' ? (fixedValue | number) : fixedValue )\" \n [ngModelOptions]=\"{ standalone: true }\"\n (blur)=\"onBlur()\"\n (focus)=\"onFocus()\"\n (input)=\"onInput()\"\n (ngModelChange)=\"onValueChanged($event)\" />\n </ng-template>\n </ng-container>\n\n </ng-container>\n</ng-container>\n\n<ng-template #disabledControl>\n <ng-container [ngSwitch]=\"type\">\n <label *ngSwitchCase=\"'checkbox'\">\n <i [ngClass]=\"fixedValue ?? formGroupDirective.form.get(disabledControlName ?? controlName)?.value ? 'fa-solid fa-square-check' : 'fa-regular fa-square'\"></i>\n </label>\n\n <label *ngSwitchCase=\"'date'\">\n {{ fixedValue ?? formGroupDirective.form.get(disabledControlName ?? controlName)?.value | date: format }}\n </label>\n\n <label *ngSwitchCase=\"'datetime-local'\">\n {{ fixedValue ?? formGroupDirective.form.get(disabledControlName ?? controlName)?.value | date: format }}\n </label>\n\n <label *ngSwitchCase=\"'number'\">\n {{ fixedValue ?? formGroupDirective.form.get(disabledControlName ?? controlName)?.value | number: format }}\n </label>\n\n <label class=\"text\" *ngSwitchDefault>{{ fixedValue ?? formGroupDirective.form.get(disabledControlName ?? controlName)?.value }}</label>\n </ng-container>\n</ng-template>\n\n<ng-template #fixedTextbox let-fixedValue=\"fixedValue\">\n \n</ng-template>\n", styles: ["@charset \"UTF-8\";:host{display:block}:host.full-height{height:100%}:host.full-height textarea{height:100%}input,textarea{--tw-border-opacity: 1;border-color:rgb(156 163 175 / var(--tw-border-opacity, 1))}input:focus,textarea:focus{--tw-border-opacity: 1;border-color:rgb(156 163 175 / var(--tw-border-opacity, 1));--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000);--tw-ring-color: rgb(0 107 182 / .3) }input,textarea{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}input:invalid,textarea:invalid{--tw-border-opacity: 1;border-color:rgb(248 113 113 / var(--tw-border-opacity, 1))}input:disabled,input.readonly-as-disabled[readonly],textarea:disabled,textarea.readonly-as-disabled[readonly]{--tw-bg-opacity: 1;background-color:rgb(241 245 249 / var(--tw-bg-opacity, 1))}input.ng-invalid.ng-touched,input.invalid,textarea.ng-invalid.ng-touched,textarea.invalid{--tw-border-opacity: 1;border-color:rgb(220 38 38 / var(--tw-border-opacity, 1))}input[type=text],input[type=number],input[type=password],input[type=date],input[type=datetime-local],input[type=email],input[type=file],input[type=month],input[type=tel],input[type=time],input[type=url],input[type=week],textarea{display:block;width:100%;border-radius:.375rem;padding:.25rem .5rem;--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}input[type=text].ng-invalid.ng-touched,input[type=text].invalid,input[type=number].ng-invalid.ng-touched,input[type=number].invalid,input[type=password].ng-invalid.ng-touched,input[type=password].invalid,input[type=date].ng-invalid.ng-touched,input[type=date].invalid,input[type=datetime-local].ng-invalid.ng-touched,input[type=datetime-local].invalid,input[type=email].ng-invalid.ng-touched,input[type=email].invalid,input[type=file].ng-invalid.ng-touched,input[type=file].invalid,input[type=month].ng-invalid.ng-touched,input[type=month].invalid,input[type=tel].ng-invalid.ng-touched,input[type=tel].invalid,input[type=time].ng-invalid.ng-touched,input[type=time].invalid,input[type=url].ng-invalid.ng-touched,input[type=url].invalid,input[type=week].ng-invalid.ng-touched,input[type=week].invalid,textarea.ng-invalid.ng-touched,textarea.invalid{margin-right:-2.25rem;padding-right:2.25rem;transition-property:none}input[type=text].ng-invalid.ng-touched:focus,input[type=text].invalid:focus,input[type=number].ng-invalid.ng-touched:focus,input[type=number].invalid:focus,input[type=password].ng-invalid.ng-touched:focus,input[type=password].invalid:focus,input[type=date].ng-invalid.ng-touched:focus,input[type=date].invalid:focus,input[type=datetime-local].ng-invalid.ng-touched:focus,input[type=datetime-local].invalid:focus,input[type=email].ng-invalid.ng-touched:focus,input[type=email].invalid:focus,input[type=file].ng-invalid.ng-touched:focus,input[type=file].invalid:focus,input[type=month].ng-invalid.ng-touched:focus,input[type=month].invalid:focus,input[type=tel].ng-invalid.ng-touched:focus,input[type=tel].invalid:focus,input[type=time].ng-invalid.ng-touched:focus,input[type=time].invalid:focus,input[type=url].ng-invalid.ng-touched:focus,input[type=url].invalid:focus,input[type=week].ng-invalid.ng-touched:focus,input[type=week].invalid:focus,textarea.ng-invalid.ng-touched:focus,textarea.invalid:focus{--tw-ring-color: rgb(248 113 113 / .3) }input[type=text].ng-invalid.ng-touched,input[type=text].invalid,input[type=number].ng-invalid.ng-touched,input[type=number].invalid,input[type=password].ng-invalid.ng-touched,input[type=password].invalid,input[type=date].ng-invalid.ng-touched,input[type=date].invalid,input[type=datetime-local].ng-invalid.ng-touched,input[type=datetime-local].invalid,input[type=email].ng-invalid.ng-touched,input[type=email].invalid,input[type=file].ng-invalid.ng-touched,input[type=file].invalid,input[type=month].ng-invalid.ng-touched,input[type=month].invalid,input[type=tel].ng-invalid.ng-touched,input[type=tel].invalid,input[type=time].ng-invalid.ng-touched,input[type=time].invalid,input[type=url].ng-invalid.ng-touched,input[type=url].invalid,input[type=week].ng-invalid.ng-touched,input[type=week].invalid,textarea.ng-invalid.ng-touched,textarea.invalid{background-size:1.125rem 1.125rem;background-position:right .5625rem center;background-repeat:no-repeat;background-image:url(\"data:image/svg+xml,%3csvg class='text-white' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e\")}input[type=checkbox]{position:relative;margin-top:.25rem;margin-bottom:.25rem;height:1.25rem;width:1.25rem;border-radius:.25rem;padding:.125rem;display:inline-flex;flex-direction:row;justify-content:flex-end;appearance:none;--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}input[type=checkbox]:disabled{pointer-events:none;opacity:.5}input[type=checkbox]:not(.switch){border-width:2px;--tw-shadow: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1);--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}input[type=checkbox]:not(.switch):focus{--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow);--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}input[type=checkbox]:not(.switch):before{border-radius:.25rem;--tw-content: \"\";content:var(--tw-content);position:absolute;inset:0;display:flex;align-items:center;justify-content:center;padding:.25rem;font-family:\"Font Awesome 6 Free\";font-weight:900}input[type=checkbox]:checked{border-color:#006bb6cc;--tw-bg-opacity: 1;background-color:rgb(0 107 182 / var(--tw-bg-opacity, 1));background-image:none}input[type=checkbox]:checked:before{--tw-content: \"\\f00c\";content:var(--tw-content);--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}input[type=checkbox]:disabled~label{opacity:.5}input[type=checkbox]~label{margin-left:.5rem;-webkit-user-select:none;user-select:none}input[type=checkbox].switch{height:1.5rem;width:3rem;border-radius:2rem;appearance:none;--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}input[type=checkbox].switch:before{aspect-ratio:1 / 1;height:100%;border-radius:9999px;--tw-content: \"\";content:var(--tw-content);background-color:#6b728099}input[type=checkbox].switch:after{flex-grow:1;--tw-content: \"\";content:var(--tw-content);transition:flex-grow .15s ease-in-out}input[type=checkbox].switch:focus:before{background-color:#3b82f699}input[type=checkbox].switch:checked{border-color:#006bb6cc;--tw-bg-opacity: 1;background-color:rgb(0 107 182 / var(--tw-bg-opacity, 1));background-image:none}input[type=checkbox].switch:checked:before{--tw-content: \"\";content:var(--tw-content);--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}input[type=checkbox].switch:checked:after{flex-grow:0}label{display:block;overflow-wrap:break-word;padding-top:.25rem;padding-bottom:.25rem}label.text{white-space:pre-wrap}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i1.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { kind: "pipe", type: i1.DecimalPipe, name: "number" }, { kind: "pipe", type: i1.DatePipe, name: "date" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.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$1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }], viewProviders: [{ provide: ControlContainer, useExisting: FormGroupDirective }] });
|
|
1230
|
+
}
|
|
1231
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: FormInputComponent, decorators: [{
|
|
1232
|
+
type: Component,
|
|
1233
|
+
args: [{ selector: 'lib-form-input', imports: [
|
|
1234
|
+
CommonModule,
|
|
1235
|
+
FormsModule,
|
|
1236
|
+
NgIf,
|
|
1237
|
+
NgSwitch,
|
|
1238
|
+
NgSwitchCase,
|
|
1239
|
+
ReactiveFormsModule,
|
|
1240
|
+
], viewProviders: [{ provide: ControlContainer, useExisting: FormGroupDirective }], host: {
|
|
1241
|
+
'[class.full-height]': 'isFullHeight'
|
|
1242
|
+
}, template: "<ng-container *ngIf=\"formGroupDirective.form?.enabled || isFormEditMode;else disabledControl\">\n <ng-container [ngSwitch]=\"type\">\n \n <textarea *ngSwitchCase=\"'textarea'\"\n [attr.autofocus]=\"autofocus ? true : null\"\n [attr.maxLength]=\"maxLength ?? null\"\n [attr.rows]=\"rows\"\n [class.invalid]=\"invalid\"\n [formControlName]=\"controlName\"\n (blur)=\"onBlur()\"\n (focus)=\"onFocus()\"\n (input)=\"onInput()\">\n </textarea>\n\n <ng-container *ngSwitchCase=\"'checkbox'\">\n <input *ngIf=\"isFormControl; else fixedCheckbox\"\n class=\"switch\"\n type=\"checkbox\"\n [attr.autofocus]=\"autofocus ? true : null\"\n [class.invalid]=\"invalid\"\n [formControlName]=\"controlName\"\n (blur)=\"onBlur()\"\n (focus)=\"onFocus()\"\n (input)=\"onInput()\" />\n\n <ng-template #fixedCheckbox>\n <input\n class=\"switch\"\n type=\"checkbox\"\n [(ngModel)]=\"fixedValue\"\n [attr.readonly]=\"true\"\n [class.invalid]=\"invalid\"\n [class.readonly-as-disabled]=\"displayReadOnlyAsDisabled\"\n [disabled]=\"isDisabled\"\n [ngModelOptions]=\"{ standalone: true }\"\n (blur)=\"onBlur()\"\n (change)=\"onChange($event)\"\n (focus)=\"onFocus()\"\n (input)=\"onInput()\"\n (ngModelChange)=\"onValueChanged($event)\" />\n </ng-template>\n </ng-container>\n\n\n <ng-container *ngSwitchDefault>\n <input *ngIf=\"isFormControl; else fixedTextBox\"\n [attr.autofocus]=\"autofocus ? true : null\"\n [attr.maxLength]=\"maxLength ?? null\"\n [attr.min]=\"minAttributeValue\"\n [attr.readonly]=\"readOnly ? true : null\"\n [attr.step]=\"stepAttributeValue\"\n [class.invalid]=\"invalid\"\n [class.readonly-as-disabled]=\"displayReadOnlyAsDisabled\"\n [formControlName]=\"controlName\"\n [type]=\"type\"\n (blur)=\"onBlur()\"\n (focus)=\"onFocus()\"\n (input)=\"onInput()\" />\n\n <ng-template #fixedTextBox>\n <input\n type=\"text\"\n [attr.maxLength]=\"maxLength ?? null\"\n [attr.min]=\"minAttributeValue\"\n [attr.readonly]=\"true\"\n [attr.step]=\"stepAttributeValue\"\n [class.invalid]=\"invalid\"\n [class.readonly-as-disabled]=\"displayReadOnlyAsDisabled\"\n [disabled]=\"isDisabled\"\n [ngModel]=\"type === 'date' || type === 'datetime-local' ? (fixedValue | date: format) : ( type === 'number' ? (fixedValue | number) : fixedValue )\" \n [ngModelOptions]=\"{ standalone: true }\"\n (blur)=\"onBlur()\"\n (focus)=\"onFocus()\"\n (input)=\"onInput()\"\n (ngModelChange)=\"onValueChanged($event)\" />\n </ng-template>\n </ng-container>\n\n </ng-container>\n</ng-container>\n\n<ng-template #disabledControl>\n <ng-container [ngSwitch]=\"type\">\n <label *ngSwitchCase=\"'checkbox'\">\n <i [ngClass]=\"fixedValue ?? formGroupDirective.form.get(disabledControlName ?? controlName)?.value ? 'fa-solid fa-square-check' : 'fa-regular fa-square'\"></i>\n </label>\n\n <label *ngSwitchCase=\"'date'\">\n {{ fixedValue ?? formGroupDirective.form.get(disabledControlName ?? controlName)?.value | date: format }}\n </label>\n\n <label *ngSwitchCase=\"'datetime-local'\">\n {{ fixedValue ?? formGroupDirective.form.get(disabledControlName ?? controlName)?.value | date: format }}\n </label>\n\n <label *ngSwitchCase=\"'number'\">\n {{ fixedValue ?? formGroupDirective.form.get(disabledControlName ?? controlName)?.value | number: format }}\n </label>\n\n <label class=\"text\" *ngSwitchDefault>{{ fixedValue ?? formGroupDirective.form.get(disabledControlName ?? controlName)?.value }}</label>\n </ng-container>\n</ng-template>\n\n<ng-template #fixedTextbox let-fixedValue=\"fixedValue\">\n \n</ng-template>\n", styles: ["@charset \"UTF-8\";:host{display:block}:host.full-height{height:100%}:host.full-height textarea{height:100%}input,textarea{--tw-border-opacity: 1;border-color:rgb(156 163 175 / var(--tw-border-opacity, 1))}input:focus,textarea:focus{--tw-border-opacity: 1;border-color:rgb(156 163 175 / var(--tw-border-opacity, 1));--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000);--tw-ring-color: rgb(0 107 182 / .3) }input,textarea{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}input:invalid,textarea:invalid{--tw-border-opacity: 1;border-color:rgb(248 113 113 / var(--tw-border-opacity, 1))}input:disabled,input.readonly-as-disabled[readonly],textarea:disabled,textarea.readonly-as-disabled[readonly]{--tw-bg-opacity: 1;background-color:rgb(241 245 249 / var(--tw-bg-opacity, 1))}input.ng-invalid.ng-touched,input.invalid,textarea.ng-invalid.ng-touched,textarea.invalid{--tw-border-opacity: 1;border-color:rgb(220 38 38 / var(--tw-border-opacity, 1))}input[type=text],input[type=number],input[type=password],input[type=date],input[type=datetime-local],input[type=email],input[type=file],input[type=month],input[type=tel],input[type=time],input[type=url],input[type=week],textarea{display:block;width:100%;border-radius:.375rem;padding:.25rem .5rem;--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}input[type=text].ng-invalid.ng-touched,input[type=text].invalid,input[type=number].ng-invalid.ng-touched,input[type=number].invalid,input[type=password].ng-invalid.ng-touched,input[type=password].invalid,input[type=date].ng-invalid.ng-touched,input[type=date].invalid,input[type=datetime-local].ng-invalid.ng-touched,input[type=datetime-local].invalid,input[type=email].ng-invalid.ng-touched,input[type=email].invalid,input[type=file].ng-invalid.ng-touched,input[type=file].invalid,input[type=month].ng-invalid.ng-touched,input[type=month].invalid,input[type=tel].ng-invalid.ng-touched,input[type=tel].invalid,input[type=time].ng-invalid.ng-touched,input[type=time].invalid,input[type=url].ng-invalid.ng-touched,input[type=url].invalid,input[type=week].ng-invalid.ng-touched,input[type=week].invalid,textarea.ng-invalid.ng-touched,textarea.invalid{margin-right:-2.25rem;padding-right:2.25rem;transition-property:none}input[type=text].ng-invalid.ng-touched:focus,input[type=text].invalid:focus,input[type=number].ng-invalid.ng-touched:focus,input[type=number].invalid:focus,input[type=password].ng-invalid.ng-touched:focus,input[type=password].invalid:focus,input[type=date].ng-invalid.ng-touched:focus,input[type=date].invalid:focus,input[type=datetime-local].ng-invalid.ng-touched:focus,input[type=datetime-local].invalid:focus,input[type=email].ng-invalid.ng-touched:focus,input[type=email].invalid:focus,input[type=file].ng-invalid.ng-touched:focus,input[type=file].invalid:focus,input[type=month].ng-invalid.ng-touched:focus,input[type=month].invalid:focus,input[type=tel].ng-invalid.ng-touched:focus,input[type=tel].invalid:focus,input[type=time].ng-invalid.ng-touched:focus,input[type=time].invalid:focus,input[type=url].ng-invalid.ng-touched:focus,input[type=url].invalid:focus,input[type=week].ng-invalid.ng-touched:focus,input[type=week].invalid:focus,textarea.ng-invalid.ng-touched:focus,textarea.invalid:focus{--tw-ring-color: rgb(248 113 113 / .3) }input[type=text].ng-invalid.ng-touched,input[type=text].invalid,input[type=number].ng-invalid.ng-touched,input[type=number].invalid,input[type=password].ng-invalid.ng-touched,input[type=password].invalid,input[type=date].ng-invalid.ng-touched,input[type=date].invalid,input[type=datetime-local].ng-invalid.ng-touched,input[type=datetime-local].invalid,input[type=email].ng-invalid.ng-touched,input[type=email].invalid,input[type=file].ng-invalid.ng-touched,input[type=file].invalid,input[type=month].ng-invalid.ng-touched,input[type=month].invalid,input[type=tel].ng-invalid.ng-touched,input[type=tel].invalid,input[type=time].ng-invalid.ng-touched,input[type=time].invalid,input[type=url].ng-invalid.ng-touched,input[type=url].invalid,input[type=week].ng-invalid.ng-touched,input[type=week].invalid,textarea.ng-invalid.ng-touched,textarea.invalid{background-size:1.125rem 1.125rem;background-position:right .5625rem center;background-repeat:no-repeat;background-image:url(\"data:image/svg+xml,%3csvg class='text-white' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e\")}input[type=checkbox]{position:relative;margin-top:.25rem;margin-bottom:.25rem;height:1.25rem;width:1.25rem;border-radius:.25rem;padding:.125rem;display:inline-flex;flex-direction:row;justify-content:flex-end;appearance:none;--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}input[type=checkbox]:disabled{pointer-events:none;opacity:.5}input[type=checkbox]:not(.switch){border-width:2px;--tw-shadow: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1);--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}input[type=checkbox]:not(.switch):focus{--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow);--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}input[type=checkbox]:not(.switch):before{border-radius:.25rem;--tw-content: \"\";content:var(--tw-content);position:absolute;inset:0;display:flex;align-items:center;justify-content:center;padding:.25rem;font-family:\"Font Awesome 6 Free\";font-weight:900}input[type=checkbox]:checked{border-color:#006bb6cc;--tw-bg-opacity: 1;background-color:rgb(0 107 182 / var(--tw-bg-opacity, 1));background-image:none}input[type=checkbox]:checked:before{--tw-content: \"\\f00c\";content:var(--tw-content);--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}input[type=checkbox]:disabled~label{opacity:.5}input[type=checkbox]~label{margin-left:.5rem;-webkit-user-select:none;user-select:none}input[type=checkbox].switch{height:1.5rem;width:3rem;border-radius:2rem;appearance:none;--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}input[type=checkbox].switch:before{aspect-ratio:1 / 1;height:100%;border-radius:9999px;--tw-content: \"\";content:var(--tw-content);background-color:#6b728099}input[type=checkbox].switch:after{flex-grow:1;--tw-content: \"\";content:var(--tw-content);transition:flex-grow .15s ease-in-out}input[type=checkbox].switch:focus:before{background-color:#3b82f699}input[type=checkbox].switch:checked{border-color:#006bb6cc;--tw-bg-opacity: 1;background-color:rgb(0 107 182 / var(--tw-bg-opacity, 1));background-image:none}input[type=checkbox].switch:checked:before{--tw-content: \"\";content:var(--tw-content);--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}input[type=checkbox].switch:checked:after{flex-grow:0}label{display:block;overflow-wrap:break-word;padding-top:.25rem;padding-bottom:.25rem}label.text{white-space:pre-wrap}\n"] }]
|
|
1243
|
+
}], ctorParameters: () => [], propDecorators: { autofocus: [{
|
|
1244
|
+
type: Input
|
|
1245
|
+
}], controlName: [{
|
|
1246
|
+
type: Input
|
|
1247
|
+
}], disabledControlName: [{
|
|
1248
|
+
type: Input
|
|
1249
|
+
}], displayReadOnlyAsDisabled: [{
|
|
1250
|
+
type: Input
|
|
1251
|
+
}], fixedValue: [{
|
|
1252
|
+
type: Input
|
|
1253
|
+
}], format: [{
|
|
1254
|
+
type: Input
|
|
1255
|
+
}], invalid: [{
|
|
1256
|
+
type: Input
|
|
1257
|
+
}], isDisabled: [{
|
|
1258
|
+
type: Input
|
|
1259
|
+
}], isFullHeight: [{
|
|
1260
|
+
type: Input
|
|
1261
|
+
}], maxLength: [{
|
|
1262
|
+
type: Input
|
|
1263
|
+
}], min: [{
|
|
1264
|
+
type: Input
|
|
1265
|
+
}], readOnly: [{
|
|
1266
|
+
type: Input
|
|
1267
|
+
}], rows: [{
|
|
1268
|
+
type: Input
|
|
1269
|
+
}], step: [{
|
|
1270
|
+
type: Input
|
|
1271
|
+
}], type: [{
|
|
1272
|
+
type: Input
|
|
1273
|
+
}], blur: [{
|
|
1274
|
+
type: Output
|
|
1275
|
+
}], change: [{
|
|
1276
|
+
type: Output
|
|
1277
|
+
}], fixedValueChanged: [{
|
|
1278
|
+
type: Output
|
|
1279
|
+
}], input: [{
|
|
1280
|
+
type: Output
|
|
1281
|
+
}], focus: [{
|
|
1282
|
+
type: Output
|
|
1283
|
+
}] } });
|
|
1284
|
+
|
|
1285
|
+
class FormInputGroupComponent extends BaseComponent {
|
|
1286
|
+
//#region ViewChilds, Inputs, Outputs
|
|
1287
|
+
autofocus = false;
|
|
1288
|
+
alignContent = 'center';
|
|
1289
|
+
controlName;
|
|
1290
|
+
fixedValue;
|
|
1291
|
+
format;
|
|
1292
|
+
label;
|
|
1293
|
+
isDisabled = true;
|
|
1294
|
+
isFullHeight = false;
|
|
1295
|
+
maxLength;
|
|
1296
|
+
min;
|
|
1297
|
+
notes = '';
|
|
1298
|
+
readOnly = false;
|
|
1299
|
+
rows;
|
|
1300
|
+
showLabel = true;
|
|
1301
|
+
step = 1;
|
|
1302
|
+
template;
|
|
1303
|
+
type = 'text';
|
|
1304
|
+
validations = {};
|
|
1305
|
+
//#endregion
|
|
1306
|
+
//#region Host listeners
|
|
1307
|
+
//#endregion
|
|
1308
|
+
//#region Variables
|
|
1309
|
+
formGroupDirective = inject(FormGroupDirective);
|
|
1310
|
+
formGroupName = inject(FormGroupName, { optional: true });
|
|
1311
|
+
formService = inject(FormService);
|
|
1312
|
+
loadingField = false;
|
|
1313
|
+
//#endregion
|
|
1314
|
+
//#region Properties
|
|
1315
|
+
get formControl() {
|
|
1316
|
+
return this.controlName
|
|
1317
|
+
? this.formGroup.get(this.controlName)
|
|
1318
|
+
: null;
|
|
1319
|
+
}
|
|
1320
|
+
get formGroup() {
|
|
1321
|
+
let formGroup = this.formGroupDirective.form;
|
|
1322
|
+
for (let group of this.parentGroups) {
|
|
1323
|
+
formGroup = formGroup.get(group);
|
|
1324
|
+
}
|
|
1325
|
+
return formGroup;
|
|
1326
|
+
}
|
|
1327
|
+
get hasNotes() {
|
|
1328
|
+
return !!this.notes && this.notes.length > 0;
|
|
1329
|
+
}
|
|
1330
|
+
get parentGroups() {
|
|
1331
|
+
return this.formGroupName?.path ?? [];
|
|
1332
|
+
}
|
|
1333
|
+
//#endregion
|
|
1334
|
+
//#region Constructor and Angular life cycle methods
|
|
1335
|
+
constructor() {
|
|
1336
|
+
super();
|
|
1337
|
+
}
|
|
1338
|
+
ngOnInit() {
|
|
1339
|
+
this.formControl?.statusChanges
|
|
1340
|
+
.pipe(takeUntil(this.destroy$))
|
|
1341
|
+
.subscribe(() => {
|
|
1342
|
+
this.loadingField = false;
|
|
1343
|
+
});
|
|
1344
|
+
this.formControl?.valueChanges
|
|
1345
|
+
.pipe(takeUntil(this.destroy$))
|
|
1346
|
+
.subscribe(() => {
|
|
1347
|
+
this.loadingField = false;
|
|
1348
|
+
});
|
|
1349
|
+
this.formService.fieldRefreshed
|
|
1350
|
+
.pipe(takeUntil(this.destroy$), filter((field) => field.fieldName === this.controlName))
|
|
1351
|
+
.subscribe((field) => {
|
|
1352
|
+
this.loadingField = field.loading ?? false;
|
|
1353
|
+
});
|
|
1354
|
+
}
|
|
1355
|
+
//#endregion
|
|
1356
|
+
//#region Event handlers
|
|
1357
|
+
//#endregion
|
|
1358
|
+
//#region Public methods
|
|
1359
|
+
hasValidation(errorKey) {
|
|
1360
|
+
return Object.keys(this.validations).indexOf(errorKey) >= 0;
|
|
1361
|
+
}
|
|
1362
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: FormInputGroupComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1363
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.6", type: FormInputGroupComponent, isStandalone: true, selector: "lib-form-input-group", inputs: { autofocus: "autofocus", alignContent: "alignContent", controlName: "controlName", fixedValue: "fixedValue", format: "format", label: "label", isDisabled: "isDisabled", isFullHeight: "isFullHeight", maxLength: "maxLength", min: "min", notes: "notes", readOnly: "readOnly", rows: "rows", showLabel: "showLabel", step: "step", template: "template", type: "type", validations: "validations" }, host: { properties: { "class.full-height": "isFullHeight" } }, usesInheritance: true, ngImport: i0, template: "<label *ngIf=\"showLabel\"\n[attr.for]=\"controlName\">\n {{ label | translate }}:\n</label>\n\n<div class=\"field\"\n[class.col-span-2]=\"!showLabel\"\n[ngStyle]=\"{ 'align-content': alignContent }\" >\n <div class=\"loading\" *ngIf=\"(loadingField || (formService.loading && formService.model === null)); else content\">\n <div></div>\n </div>\n\n <ng-template #content>\n <ng-container *ngTemplateOutlet=\"template ? template : defaultTemplate\">\n </ng-container>\n \n <div class=\"validations\" [class.show]=\"formControl?.invalid\" *ngIf=\"formControl?.touched\">\n <ng-container *ngFor=\"let error of formControl?.errors | keyvalue\">\n <span *ngIf=\"hasValidation(error.key)\">{{ validations[error.key] | translate }}</span>\n <ng-template #defaultValidationError>{{ error.key }}</ng-template>\n </ng-container>\n </div>\n \n <ng-template #defaultTemplate>\n <lib-form-input #formInput\n [autofocus]=\"autofocus\"\n [controlName]=\"controlName\"\n [fixedValue]=\"fixedValue\"\n [format]=\"format\"\n [isDisabled]=\"isDisabled\"\n [isFullHeight]=\"isFullHeight\"\n [min]=\"min\"\n [maxLength]=\"maxLength\"\n [readOnly]=\"readOnly\"\n [rows]=\"rows\"\n [step]=\"step\"\n [type]=\"type\">\n </lib-form-input>\n </ng-template>\n \n <span class=\"text-sm italic\" *ngIf=\"hasNotes\">\n *{{ notes | translate }}\n </span>\n </ng-template>\n\n</div>\n", styles: [":host{grid-column:span 2 / span 2;display:grid;grid-template-columns:subgrid;gap:.75rem}:host.full-height{max-height:100%;overflow:auto}label{white-space:nowrap;padding-top:.25rem;padding-bottom:.25rem;text-align:right;font-size:.75rem;font-weight:700;text-transform:uppercase;line-height:1.5rem;letter-spacing:.025em;--tw-text-opacity: 1;color:rgb(55 65 81 / var(--tw-text-opacity, 1))}.field .validations{flex-basis:100%;font-size:.875rem;line-height:1.25rem;--tw-text-opacity: 1;color:rgb(220 38 38 / var(--tw-text-opacity, 1))}.field .validations.show{margin-top:.25rem}.field .validations span{display:block}.field .loading{max-width:24rem}@keyframes pulse{50%{opacity:.5}}.field .loading{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}.field .loading *{height:.625rem;width:100%;border-radius:9999px;--tw-bg-opacity: 1;background-color:rgb(229 231 235 / var(--tw-bg-opacity, 1))}@media (prefers-color-scheme: dark){.field .loading *{--tw-bg-opacity: 1;background-color:rgb(55 65 81 / var(--tw-bg-opacity, 1))}}\n"], dependencies: [{ kind: "component", type: FormInputComponent, selector: "lib-form-input", inputs: ["autofocus", "controlName", "disabledControlName", "displayReadOnlyAsDisabled", "fixedValue", "format", "invalid", "isDisabled", "isFullHeight", "maxLength", "min", "readOnly", "rows", "step", "type"], outputs: ["blur", "change", "fixedValueChanged", "input", "focus"] }, { kind: "pipe", type: KeyValuePipe, name: "keyvalue" }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
|
|
1364
|
+
}
|
|
1365
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: FormInputGroupComponent, decorators: [{
|
|
1366
|
+
type: Component,
|
|
1367
|
+
args: [{ selector: 'lib-form-input-group', imports: [
|
|
1368
|
+
FormInputComponent,
|
|
1369
|
+
KeyValuePipe,
|
|
1370
|
+
NgFor,
|
|
1371
|
+
NgIf,
|
|
1372
|
+
NgStyle,
|
|
1373
|
+
NgTemplateOutlet,
|
|
1374
|
+
TranslatePipe,
|
|
1375
|
+
], host: {
|
|
1376
|
+
'[class.full-height]': 'isFullHeight'
|
|
1377
|
+
}, template: "<label *ngIf=\"showLabel\"\n[attr.for]=\"controlName\">\n {{ label | translate }}:\n</label>\n\n<div class=\"field\"\n[class.col-span-2]=\"!showLabel\"\n[ngStyle]=\"{ 'align-content': alignContent }\" >\n <div class=\"loading\" *ngIf=\"(loadingField || (formService.loading && formService.model === null)); else content\">\n <div></div>\n </div>\n\n <ng-template #content>\n <ng-container *ngTemplateOutlet=\"template ? template : defaultTemplate\">\n </ng-container>\n \n <div class=\"validations\" [class.show]=\"formControl?.invalid\" *ngIf=\"formControl?.touched\">\n <ng-container *ngFor=\"let error of formControl?.errors | keyvalue\">\n <span *ngIf=\"hasValidation(error.key)\">{{ validations[error.key] | translate }}</span>\n <ng-template #defaultValidationError>{{ error.key }}</ng-template>\n </ng-container>\n </div>\n \n <ng-template #defaultTemplate>\n <lib-form-input #formInput\n [autofocus]=\"autofocus\"\n [controlName]=\"controlName\"\n [fixedValue]=\"fixedValue\"\n [format]=\"format\"\n [isDisabled]=\"isDisabled\"\n [isFullHeight]=\"isFullHeight\"\n [min]=\"min\"\n [maxLength]=\"maxLength\"\n [readOnly]=\"readOnly\"\n [rows]=\"rows\"\n [step]=\"step\"\n [type]=\"type\">\n </lib-form-input>\n </ng-template>\n \n <span class=\"text-sm italic\" *ngIf=\"hasNotes\">\n *{{ notes | translate }}\n </span>\n </ng-template>\n\n</div>\n", styles: [":host{grid-column:span 2 / span 2;display:grid;grid-template-columns:subgrid;gap:.75rem}:host.full-height{max-height:100%;overflow:auto}label{white-space:nowrap;padding-top:.25rem;padding-bottom:.25rem;text-align:right;font-size:.75rem;font-weight:700;text-transform:uppercase;line-height:1.5rem;letter-spacing:.025em;--tw-text-opacity: 1;color:rgb(55 65 81 / var(--tw-text-opacity, 1))}.field .validations{flex-basis:100%;font-size:.875rem;line-height:1.25rem;--tw-text-opacity: 1;color:rgb(220 38 38 / var(--tw-text-opacity, 1))}.field .validations.show{margin-top:.25rem}.field .validations span{display:block}.field .loading{max-width:24rem}@keyframes pulse{50%{opacity:.5}}.field .loading{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}.field .loading *{height:.625rem;width:100%;border-radius:9999px;--tw-bg-opacity: 1;background-color:rgb(229 231 235 / var(--tw-bg-opacity, 1))}@media (prefers-color-scheme: dark){.field .loading *{--tw-bg-opacity: 1;background-color:rgb(55 65 81 / var(--tw-bg-opacity, 1))}}\n"] }]
|
|
1378
|
+
}], ctorParameters: () => [], propDecorators: { autofocus: [{
|
|
1379
|
+
type: Input
|
|
1380
|
+
}], alignContent: [{
|
|
1381
|
+
type: Input
|
|
1382
|
+
}], controlName: [{
|
|
1383
|
+
type: Input
|
|
1384
|
+
}], fixedValue: [{
|
|
1385
|
+
type: Input
|
|
1386
|
+
}], format: [{
|
|
1387
|
+
type: Input
|
|
1388
|
+
}], label: [{
|
|
1389
|
+
type: Input
|
|
1390
|
+
}], isDisabled: [{
|
|
1391
|
+
type: Input
|
|
1392
|
+
}], isFullHeight: [{
|
|
1393
|
+
type: Input
|
|
1394
|
+
}], maxLength: [{
|
|
1395
|
+
type: Input
|
|
1396
|
+
}], min: [{
|
|
1397
|
+
type: Input
|
|
1398
|
+
}], notes: [{
|
|
1399
|
+
type: Input
|
|
1400
|
+
}], readOnly: [{
|
|
1401
|
+
type: Input
|
|
1402
|
+
}], rows: [{
|
|
1403
|
+
type: Input
|
|
1404
|
+
}], showLabel: [{
|
|
1405
|
+
type: Input
|
|
1406
|
+
}], step: [{
|
|
1407
|
+
type: Input
|
|
1408
|
+
}], template: [{
|
|
1409
|
+
type: Input
|
|
1410
|
+
}], type: [{
|
|
1411
|
+
type: Input
|
|
1412
|
+
}], validations: [{
|
|
1413
|
+
type: Input
|
|
1414
|
+
}] } });
|
|
1415
|
+
|
|
1416
|
+
class CatalogSelectComponent extends BaseComponent {
|
|
1417
|
+
//#region HostListeners
|
|
1418
|
+
bodyMouseDown(event) {
|
|
1419
|
+
const target = event.target;
|
|
1420
|
+
if (this.isDropDownShown && !target.closest('.catalog-container.show')) {
|
|
1421
|
+
this.wasClickedOutside = (event.button === 0 && !target.closest('.dropdown-container')) ?? false;
|
|
1422
|
+
}
|
|
1423
|
+
}
|
|
1424
|
+
bodyMouseUp(event) {
|
|
1425
|
+
if (this.isDropDownShown && this.wasClickedOutside) {
|
|
1426
|
+
this.closeDropdownOverlay();
|
|
1427
|
+
this.wasClickedOutside = false;
|
|
1428
|
+
}
|
|
1429
|
+
}
|
|
1430
|
+
//#endregion
|
|
1431
|
+
//#region ViewChilds, Inputs, Outputs
|
|
1432
|
+
dropdownTemplate;
|
|
1433
|
+
inputElement;
|
|
1434
|
+
autofocus = false;
|
|
1435
|
+
controlName;
|
|
1436
|
+
displayControlName;
|
|
1437
|
+
displayProperty = 'display';
|
|
1438
|
+
set entriesList(value) {
|
|
1439
|
+
if (this._entriesList !== value) {
|
|
1440
|
+
this._entriesList = value;
|
|
1441
|
+
if (this.isSubscriptionInitialized) {
|
|
1442
|
+
this.entriesDataSource = [];
|
|
1443
|
+
this.initializeEntriesDataSource();
|
|
1444
|
+
this.refreshSearch();
|
|
1445
|
+
}
|
|
1446
|
+
}
|
|
1447
|
+
}
|
|
1448
|
+
set filters(value) {
|
|
1449
|
+
if (this._filters !== value) {
|
|
1450
|
+
this._filters = value;
|
|
1451
|
+
this.updateFilters();
|
|
1452
|
+
}
|
|
1453
|
+
}
|
|
1454
|
+
label;
|
|
1455
|
+
maxEntries = 100;
|
|
1456
|
+
minimumLengthSearch = 3;
|
|
1457
|
+
notes = '';
|
|
1458
|
+
readOnly = false;
|
|
1459
|
+
searchEndpoint;
|
|
1460
|
+
validations = {};
|
|
1461
|
+
valueProperty = 'value';
|
|
1462
|
+
//#endregion
|
|
1463
|
+
//#region Variables
|
|
1464
|
+
displayedEntries = [];
|
|
1465
|
+
focusedIndex = -1;
|
|
1466
|
+
isDropDownShown = false;
|
|
1467
|
+
isFocused = false;
|
|
1468
|
+
isLoading = false;
|
|
1469
|
+
selectedValue;
|
|
1470
|
+
shouldUseCriteria = false;
|
|
1471
|
+
showFailureMessage = false;
|
|
1472
|
+
showMinimumCharactersMessage = false;
|
|
1473
|
+
showNoResultsMessage = false;
|
|
1474
|
+
static instanceCounter = 0;
|
|
1475
|
+
_entriesList;
|
|
1476
|
+
_filters = {};
|
|
1477
|
+
catalogService = inject(CatalogService);
|
|
1478
|
+
dataGridDataset = inject(DataGridDataset, { optional: true });
|
|
1479
|
+
entriesDataSource = [];
|
|
1480
|
+
filterDiffer;
|
|
1481
|
+
formGroup = inject(FormGroupDirective);
|
|
1482
|
+
formGroupName = inject(FormGroupName, { optional: true });
|
|
1483
|
+
instanceId;
|
|
1484
|
+
isDataInitialized = false;
|
|
1485
|
+
isSubscriptionInitialized = false;
|
|
1486
|
+
keyValueDiffers = inject(KeyValueDiffers);
|
|
1487
|
+
lastCriteriaUsed = null;
|
|
1488
|
+
overlay = inject(Overlay);
|
|
1489
|
+
overlayRef;
|
|
1490
|
+
positionBuilder = inject(OverlayPositionBuilder);
|
|
1491
|
+
searchSubject = new Subject();
|
|
1492
|
+
viewContainerRef = inject(ViewContainerRef);
|
|
1493
|
+
wasClickedOutside = false;
|
|
1494
|
+
//#endregion
|
|
1495
|
+
//#region Properties
|
|
1496
|
+
get entriesList() {
|
|
1497
|
+
return this._entriesList;
|
|
1498
|
+
}
|
|
1499
|
+
get filters() {
|
|
1500
|
+
return this._filters;
|
|
1501
|
+
}
|
|
1502
|
+
get activeDescendantId() {
|
|
1503
|
+
if (this.focusedIndex >= 0 && this.focusedIndex < this.displayedEntries.length) {
|
|
1504
|
+
return `catalog-select-${this.instanceId}-option-${this.focusedIndex}`;
|
|
1505
|
+
}
|
|
1506
|
+
return null;
|
|
1507
|
+
}
|
|
1508
|
+
get displayControl() {
|
|
1509
|
+
return this.formGroup.form.get(this.formDisplayControlName);
|
|
1510
|
+
}
|
|
1511
|
+
get formControl() {
|
|
1512
|
+
return this.formGroup.form.get(this.formControlName);
|
|
1513
|
+
}
|
|
1514
|
+
get formControlName() {
|
|
1515
|
+
return [
|
|
1516
|
+
...this.formGroupName?.path ?? [],
|
|
1517
|
+
this.controlName
|
|
1518
|
+
].join('.');
|
|
1519
|
+
}
|
|
1520
|
+
get formDisplayControlName() {
|
|
1521
|
+
return [
|
|
1522
|
+
...this.formGroupName?.path ?? [],
|
|
1523
|
+
this.displayControlName
|
|
1524
|
+
].join('.');
|
|
1525
|
+
}
|
|
1526
|
+
get isInvalid() {
|
|
1527
|
+
return this.formControl.invalid;
|
|
1528
|
+
}
|
|
1529
|
+
get isTouched() {
|
|
1530
|
+
return this.formControl.touched;
|
|
1531
|
+
}
|
|
1532
|
+
get listboxId() {
|
|
1533
|
+
return `catalog-select-${this.instanceId}-listbox`;
|
|
1534
|
+
}
|
|
1535
|
+
get showClearButton() {
|
|
1536
|
+
return this.selectedValue != null && !this.readOnly && (this.formControl?.enabled ?? false);
|
|
1537
|
+
}
|
|
1538
|
+
get hasSearchEndpoint() {
|
|
1539
|
+
return !!this.searchEndpoint && this.searchEndpoint.length > 0;
|
|
1540
|
+
}
|
|
1541
|
+
//#endregion
|
|
1542
|
+
//#region Constructor and Angular life cycle methods
|
|
1543
|
+
constructor() {
|
|
1544
|
+
super();
|
|
1545
|
+
this.instanceId = CatalogSelectComponent.instanceCounter++;
|
|
1546
|
+
}
|
|
1547
|
+
ngAfterViewInit() {
|
|
1548
|
+
this.setInputAriaAttributes();
|
|
1549
|
+
}
|
|
1550
|
+
ngOnDestroy() {
|
|
1551
|
+
this.closeDropdownOverlay();
|
|
1552
|
+
super.ngOnDestroy();
|
|
1553
|
+
}
|
|
1554
|
+
ngOnInit() {
|
|
1555
|
+
// Check and add the display control, if it does not exist.
|
|
1556
|
+
const wasFormDisabled = this.formGroup.form.disabled;
|
|
1557
|
+
this.checkAndAddDisplayControl();
|
|
1558
|
+
if (wasFormDisabled) {
|
|
1559
|
+
this.formGroup.form.disable();
|
|
1560
|
+
}
|
|
1561
|
+
// Initialize the entries data source from the entries list, if provided.
|
|
1562
|
+
this.initializeEntriesDataSource();
|
|
1563
|
+
// Initialize the search functionality.
|
|
1564
|
+
this.initializeSearch();
|
|
1565
|
+
// Subscribe to changes in the display control to apply search criteria.
|
|
1566
|
+
this.displayControl?.valueChanges
|
|
1567
|
+
.pipe(takeUntil(this.destroy$), tap(() => {
|
|
1568
|
+
if (!this.isFocused) {
|
|
1569
|
+
return;
|
|
1570
|
+
}
|
|
1571
|
+
this.isLoading = true;
|
|
1572
|
+
this.resetMessages();
|
|
1573
|
+
}), debounceTime(500), startWith(null), pairwise())
|
|
1574
|
+
.subscribe(([previous, current]) => {
|
|
1575
|
+
if (!this.isFocused || previous === current) {
|
|
1576
|
+
this.isLoading = false;
|
|
1577
|
+
return;
|
|
1578
|
+
}
|
|
1579
|
+
this.applySearchCriteria(current);
|
|
1580
|
+
});
|
|
1581
|
+
this.filterDiffer = this.keyValueDiffers.find(this._filters).create();
|
|
1582
|
+
// Subscribe to changes in the form control to update the selected value and display control states.
|
|
1583
|
+
this.syncFormControlsEnabledDisabled();
|
|
1584
|
+
this.formControl?.valueChanges
|
|
1585
|
+
.pipe(takeUntil(this.destroy$))
|
|
1586
|
+
.subscribe((value) => {
|
|
1587
|
+
this.syncFormControlsEnabledDisabled();
|
|
1588
|
+
if (this.selectedValue === value) {
|
|
1589
|
+
return;
|
|
1590
|
+
}
|
|
1591
|
+
this.selectedValue = value;
|
|
1592
|
+
if (this.hasSearchEndpoint) {
|
|
1593
|
+
if (!value) {
|
|
1594
|
+
this.displayControl?.reset(null, { emitEvent: false });
|
|
1595
|
+
}
|
|
1596
|
+
}
|
|
1597
|
+
else {
|
|
1598
|
+
const display = this.entriesDataSource.filter((entry) => entry.value === value)[0]?.display ?? '';
|
|
1599
|
+
this.displayControl?.setValue(display, { emitEvent: false });
|
|
1600
|
+
}
|
|
1601
|
+
});
|
|
1602
|
+
// Initial sync: if the form control already has a value (e.g., the model was loaded
|
|
1603
|
+
// before this component initialized), sync the display control immediately.
|
|
1604
|
+
this.syncDisplayFromCurrentValue();
|
|
1605
|
+
}
|
|
1606
|
+
//#endregion
|
|
1607
|
+
//#region Event handlers
|
|
1608
|
+
onContainerBlur() {
|
|
1609
|
+
this.isFocused = false;
|
|
1610
|
+
}
|
|
1611
|
+
onContainerClick() {
|
|
1612
|
+
if ((!this.isDropDownShown || this.readOnly)
|
|
1613
|
+
&& (this.formGroup.form?.enabled ?? false)
|
|
1614
|
+
&& (this.formGroup.form?.get(this.formControlName)?.enabled ?? false)) {
|
|
1615
|
+
this.openDropdownOverlay();
|
|
1616
|
+
}
|
|
1617
|
+
}
|
|
1618
|
+
onContainerFocus() {
|
|
1619
|
+
this.isFocused = true;
|
|
1620
|
+
if (!this.isDropDownShown && !this.readOnly
|
|
1621
|
+
&& (this.formGroup.form?.enabled ?? false)
|
|
1622
|
+
&& (this.formGroup.form?.get(this.formControlName)?.enabled ?? false)) {
|
|
1623
|
+
this.openDropdownOverlay();
|
|
1624
|
+
}
|
|
1625
|
+
}
|
|
1626
|
+
onClearClick(event) {
|
|
1627
|
+
event.stopPropagation();
|
|
1628
|
+
if (this.formControl) {
|
|
1629
|
+
this.formControl.setValue(null);
|
|
1630
|
+
this.formControl.markAsDirty();
|
|
1631
|
+
this.formControl.markAsTouched();
|
|
1632
|
+
}
|
|
1633
|
+
if (this.displayControl) {
|
|
1634
|
+
this.displayControl.setValue('', { emitEvent: false });
|
|
1635
|
+
this.displayControl.markAsDirty();
|
|
1636
|
+
this.displayControl.markAsTouched();
|
|
1637
|
+
}
|
|
1638
|
+
this.selectedValue = null;
|
|
1639
|
+
}
|
|
1640
|
+
onKeyDown(event) {
|
|
1641
|
+
switch (event.key) {
|
|
1642
|
+
case 'ArrowDown':
|
|
1643
|
+
event.preventDefault();
|
|
1644
|
+
if (!this.isDropDownShown) {
|
|
1645
|
+
this.openDropdownOverlay();
|
|
1646
|
+
}
|
|
1647
|
+
if (this.displayedEntries.length > 0) {
|
|
1648
|
+
this.focusedIndex = Math.min(this.focusedIndex + 1, this.displayedEntries.length - 1);
|
|
1649
|
+
this.scrollFocusedItemIntoView();
|
|
1650
|
+
}
|
|
1651
|
+
this.updateInputAriaActiveDescendant();
|
|
1652
|
+
break;
|
|
1653
|
+
case 'ArrowUp':
|
|
1654
|
+
event.preventDefault();
|
|
1655
|
+
if (this.isDropDownShown && this.displayedEntries.length > 0) {
|
|
1656
|
+
this.focusedIndex = Math.max(this.focusedIndex - 1, 0);
|
|
1657
|
+
this.scrollFocusedItemIntoView();
|
|
1658
|
+
}
|
|
1659
|
+
this.updateInputAriaActiveDescendant();
|
|
1660
|
+
break;
|
|
1661
|
+
case 'Enter':
|
|
1662
|
+
event.preventDefault();
|
|
1663
|
+
if (this.isDropDownShown && this.focusedIndex >= 0 && this.focusedIndex < this.displayedEntries.length) {
|
|
1664
|
+
this.onDropDownItemClick(this.displayedEntries[this.focusedIndex]);
|
|
1665
|
+
}
|
|
1666
|
+
break;
|
|
1667
|
+
case 'Escape':
|
|
1668
|
+
if (this.isDropDownShown) {
|
|
1669
|
+
event.preventDefault();
|
|
1670
|
+
this.closeDropdownOverlay();
|
|
1671
|
+
}
|
|
1672
|
+
break;
|
|
1673
|
+
case 'Tab':
|
|
1674
|
+
if (this.isDropDownShown) {
|
|
1675
|
+
this.closeDropdownOverlay();
|
|
1676
|
+
}
|
|
1677
|
+
break;
|
|
1678
|
+
}
|
|
1679
|
+
}
|
|
1680
|
+
onDropDownErrorClick() {
|
|
1681
|
+
this.refreshSearch();
|
|
1682
|
+
}
|
|
1683
|
+
onDropDownItemClick(entry) {
|
|
1684
|
+
if (this.displayControl) {
|
|
1685
|
+
this.displayControl.markAsDirty();
|
|
1686
|
+
this.displayControl.markAllAsTouched();
|
|
1687
|
+
this.displayControl.setValue(entry.display, { emitEvent: false });
|
|
1688
|
+
}
|
|
1689
|
+
if (this.formControl) {
|
|
1690
|
+
this.formControl.markAsDirty();
|
|
1691
|
+
this.formControl.markAsTouched();
|
|
1692
|
+
this.formControl.setValue(entry.value);
|
|
1693
|
+
}
|
|
1694
|
+
this.closeDropdownOverlay();
|
|
1695
|
+
}
|
|
1696
|
+
onDropDownMessageClick() {
|
|
1697
|
+
this.closeDropdownOverlay();
|
|
1698
|
+
}
|
|
1699
|
+
//#endregion
|
|
1700
|
+
//#region Public methods
|
|
1701
|
+
getOptionId(index) {
|
|
1702
|
+
return `catalog-select-${this.instanceId}-option-${index}`;
|
|
1703
|
+
}
|
|
1704
|
+
//#endregion
|
|
1705
|
+
//#region Private methods
|
|
1706
|
+
applySearchCriteria(criteria) {
|
|
1707
|
+
this.isLoading = true;
|
|
1708
|
+
this.resetMessages();
|
|
1709
|
+
this.searchSubject.next(criteria);
|
|
1710
|
+
}
|
|
1711
|
+
checkAndAddDisplayControl() {
|
|
1712
|
+
let parent = this.formGroup.form;
|
|
1713
|
+
const controlNames = this.formDisplayControlName.split('.');
|
|
1714
|
+
controlNames.forEach((name, index) => {
|
|
1715
|
+
if (index < controlNames.length - 1) {
|
|
1716
|
+
parent = parent.get(name);
|
|
1717
|
+
}
|
|
1718
|
+
else {
|
|
1719
|
+
if (!parent.get(name)) {
|
|
1720
|
+
parent.addControl(name, new FormControl(''));
|
|
1721
|
+
}
|
|
1722
|
+
}
|
|
1723
|
+
});
|
|
1724
|
+
}
|
|
1725
|
+
closeDropdownOverlay() {
|
|
1726
|
+
this.isDropDownShown = false;
|
|
1727
|
+
this.focusedIndex = -1;
|
|
1728
|
+
this.updateInputAriaActiveDescendant();
|
|
1729
|
+
if (this.overlayRef) {
|
|
1730
|
+
this.overlayRef.detach();
|
|
1731
|
+
this.overlayRef.dispose();
|
|
1732
|
+
this.overlayRef = undefined;
|
|
1733
|
+
}
|
|
1734
|
+
}
|
|
1735
|
+
initializeEntriesDataSource() {
|
|
1736
|
+
if (this.hasSearchEndpoint || !this._entriesList || this._entriesList.length === 0) {
|
|
1737
|
+
return;
|
|
1738
|
+
}
|
|
1739
|
+
const observables = [];
|
|
1740
|
+
this._entriesList.forEach((entry) => {
|
|
1741
|
+
const value = entry[this.valueProperty];
|
|
1742
|
+
const display = entry[this.displayProperty];
|
|
1743
|
+
if (display instanceof Observable) {
|
|
1744
|
+
this.entriesDataSource.push({ value: value, display: 'Loading...' });
|
|
1745
|
+
observables.push(display
|
|
1746
|
+
.pipe(take(1), tap(v => {
|
|
1747
|
+
this.entriesDataSource.filter(x => x.value === value)[0].display = v;
|
|
1748
|
+
if (this.selectedValue === value) {
|
|
1749
|
+
this.displayControl.setValue(v);
|
|
1750
|
+
}
|
|
1751
|
+
})));
|
|
1752
|
+
}
|
|
1753
|
+
else {
|
|
1754
|
+
this.entriesDataSource.push({ value, display });
|
|
1755
|
+
}
|
|
1756
|
+
});
|
|
1757
|
+
forkJoin(observables)
|
|
1758
|
+
.pipe(take(1))
|
|
1759
|
+
.subscribe(() => {
|
|
1760
|
+
});
|
|
1761
|
+
}
|
|
1762
|
+
initializeSearch() {
|
|
1763
|
+
this.searchSubject
|
|
1764
|
+
.pipe(takeUntil(this.destroy$), switchMap((criteria) => {
|
|
1765
|
+
this.lastCriteriaUsed = criteria;
|
|
1766
|
+
if (!this.hasSearchEndpoint) {
|
|
1767
|
+
if (this.entriesDataSource.length === 0) {
|
|
1768
|
+
return of(null).pipe(take(1));
|
|
1769
|
+
}
|
|
1770
|
+
return of(this.entriesDataSource.filter((entry) => entry.display.toLowerCase().indexOf(criteria?.toLowerCase() ?? '') > -1)).pipe(take(1));
|
|
1771
|
+
}
|
|
1772
|
+
this.updateMinimumCharactersMessageVisibility(criteria ?? '');
|
|
1773
|
+
if (this.showMinimumCharactersMessage) {
|
|
1774
|
+
return of(null).pipe(take(1));
|
|
1775
|
+
}
|
|
1776
|
+
return this.catalogService.search(this.searchEndpoint, this.maxEntries, criteria ?? '', this.filters)
|
|
1777
|
+
.pipe(take(1));
|
|
1778
|
+
})).subscribe({
|
|
1779
|
+
next: (result) => {
|
|
1780
|
+
this.isLoading = false;
|
|
1781
|
+
this.displayedEntries = [];
|
|
1782
|
+
if (Array.isArray(result) && result.length > 0) {
|
|
1783
|
+
this.displayedEntries = result;
|
|
1784
|
+
}
|
|
1785
|
+
else if (result?.entries && Array.isArray(result.entries)) {
|
|
1786
|
+
const catalogResult = result;
|
|
1787
|
+
if (!catalogResult) {
|
|
1788
|
+
return;
|
|
1789
|
+
}
|
|
1790
|
+
this.displayedEntries = catalogResult.entries;
|
|
1791
|
+
if (!this.isDataInitialized) {
|
|
1792
|
+
// The shouldUseCriteria is only set from the initialization.
|
|
1793
|
+
this.isDataInitialized = true;
|
|
1794
|
+
this.shouldUseCriteria = catalogResult.shouldUseCriteria ?? false;
|
|
1795
|
+
this.showMinimumCharactersMessage = this.displayedEntries.length === 0;
|
|
1796
|
+
}
|
|
1797
|
+
}
|
|
1798
|
+
// Try to filter out already loaded rows from the data grid dataset.
|
|
1799
|
+
if (this.displayedEntries.length > 0 && this.dataGridDataset) {
|
|
1800
|
+
this.displayedEntries = this.tryFilterFromDataset(this.displayedEntries);
|
|
1801
|
+
}
|
|
1802
|
+
if (!this.showMinimumCharactersMessage && this.displayedEntries.length === 0) {
|
|
1803
|
+
this.showNoResultsMessage = true;
|
|
1804
|
+
}
|
|
1805
|
+
},
|
|
1806
|
+
error: (_) => {
|
|
1807
|
+
this.isLoading = false;
|
|
1808
|
+
this.displayedEntries = [];
|
|
1809
|
+
this.showFailureMessage = true;
|
|
1810
|
+
// Set a new subscription to allow retrying the search later.
|
|
1811
|
+
this.initializeSearch();
|
|
1812
|
+
}
|
|
1813
|
+
});
|
|
1814
|
+
if (!this.isSubscriptionInitialized) {
|
|
1815
|
+
this.isSubscriptionInitialized = true;
|
|
1816
|
+
this.applySearchCriteria(null);
|
|
1817
|
+
}
|
|
1818
|
+
}
|
|
1819
|
+
openDropdownOverlay() {
|
|
1820
|
+
// Defensive cleanup of any stale overlay before creating a new one.
|
|
1821
|
+
if (this.overlayRef) {
|
|
1822
|
+
this.overlayRef.detach();
|
|
1823
|
+
this.overlayRef.dispose();
|
|
1824
|
+
this.overlayRef = undefined;
|
|
1825
|
+
}
|
|
1826
|
+
const positionStrategy = this.positionBuilder
|
|
1827
|
+
.flexibleConnectedTo(this.inputElement)
|
|
1828
|
+
.withPositions([
|
|
1829
|
+
{
|
|
1830
|
+
originX: 'start',
|
|
1831
|
+
originY: 'bottom',
|
|
1832
|
+
overlayX: 'start',
|
|
1833
|
+
overlayY: 'top',
|
|
1834
|
+
},
|
|
1835
|
+
{
|
|
1836
|
+
originX: 'start',
|
|
1837
|
+
originY: 'top',
|
|
1838
|
+
overlayX: 'start',
|
|
1839
|
+
overlayY: 'bottom',
|
|
1840
|
+
}
|
|
1841
|
+
]);
|
|
1842
|
+
this.overlayRef = this.overlay.create({
|
|
1843
|
+
positionStrategy,
|
|
1844
|
+
hasBackdrop: false,
|
|
1845
|
+
scrollStrategy: this.overlay.scrollStrategies.reposition(),
|
|
1846
|
+
});
|
|
1847
|
+
// Set overlay width to match input field
|
|
1848
|
+
const inputRect = this.inputElement.nativeElement.getBoundingClientRect();
|
|
1849
|
+
this.overlayRef.updateSize({ width: inputRect.width });
|
|
1850
|
+
const portal = new TemplatePortal(this.dropdownTemplate, this.viewContainerRef);
|
|
1851
|
+
this.overlayRef.attach(portal);
|
|
1852
|
+
this.isDropDownShown = true;
|
|
1853
|
+
this.focusedIndex = this.selectedValue != null
|
|
1854
|
+
? this.displayedEntries.findIndex((entry) => entry.value === this.selectedValue)
|
|
1855
|
+
: -1;
|
|
1856
|
+
this.updateInputAriaActiveDescendant();
|
|
1857
|
+
// Re-evaluate minimum characters message visibility when opening the dropdown,
|
|
1858
|
+
// in case it was incorrectly reset by a programmatic value change.
|
|
1859
|
+
if (this.shouldUseCriteria && !this.isLoading) {
|
|
1860
|
+
this.updateMinimumCharactersMessageVisibility(this.displayControl?.value ?? '');
|
|
1861
|
+
}
|
|
1862
|
+
// Scroll the selected item into view after the overlay renders.
|
|
1863
|
+
if (this.focusedIndex >= 0) {
|
|
1864
|
+
requestAnimationFrame(() => this.scrollFocusedItemIntoView());
|
|
1865
|
+
}
|
|
1866
|
+
}
|
|
1867
|
+
refreshSearch(reInitialize = false) {
|
|
1868
|
+
if (reInitialize) {
|
|
1869
|
+
this.isDataInitialized = false;
|
|
1870
|
+
}
|
|
1871
|
+
this.applySearchCriteria(this.lastCriteriaUsed);
|
|
1872
|
+
}
|
|
1873
|
+
resetMessages() {
|
|
1874
|
+
this.showFailureMessage = false;
|
|
1875
|
+
this.showNoResultsMessage = false;
|
|
1876
|
+
this.showMinimumCharactersMessage = false;
|
|
1877
|
+
}
|
|
1878
|
+
syncDisplayFromCurrentValue() {
|
|
1879
|
+
const currentValue = this.formControl?.value;
|
|
1880
|
+
if (currentValue == null || this.selectedValue === currentValue) {
|
|
1881
|
+
return;
|
|
1882
|
+
}
|
|
1883
|
+
this.selectedValue = currentValue;
|
|
1884
|
+
if (!this.hasSearchEndpoint) {
|
|
1885
|
+
const display = this.entriesDataSource.filter((entry) => entry.value === currentValue)[0]?.display ?? '';
|
|
1886
|
+
this.displayControl?.setValue(display, { emitEvent: false });
|
|
1887
|
+
}
|
|
1888
|
+
}
|
|
1889
|
+
syncFormControlsEnabledDisabled() {
|
|
1890
|
+
if (this.formControl.enabled !== this.displayControl.enabled) {
|
|
1891
|
+
if (this.formControl.disabled) {
|
|
1892
|
+
this.displayControl.disable({ emitEvent: false });
|
|
1893
|
+
}
|
|
1894
|
+
else {
|
|
1895
|
+
this.displayControl.enable({ emitEvent: false });
|
|
1896
|
+
}
|
|
1897
|
+
}
|
|
1898
|
+
}
|
|
1899
|
+
tryFilterFromDataset(results) {
|
|
1900
|
+
if (this.dataGridDataset
|
|
1901
|
+
&& this.controlName === this.dataGridDataset?.keyProperty
|
|
1902
|
+
&& this.dataGridDataset.hasLoadedRows) {
|
|
1903
|
+
// If the control name is matching the ID property of the data grid dataset, filter out the loaded rows to remove duplicated IDs.
|
|
1904
|
+
const loadedIDs = this.dataGridDataset.loadedKeys.map((key) => this.dataGridDataset.getRowID(key));
|
|
1905
|
+
return results.filter((result) => loadedIDs.indexOf(result.value) < 0);
|
|
1906
|
+
}
|
|
1907
|
+
return results;
|
|
1908
|
+
}
|
|
1909
|
+
updateFilters() {
|
|
1910
|
+
if (!this.filterDiffer || !this.filters) {
|
|
1911
|
+
return;
|
|
1912
|
+
}
|
|
1913
|
+
const changes = this.filterDiffer.diff(this.filters);
|
|
1914
|
+
if (changes) {
|
|
1915
|
+
const reInitialize = true;
|
|
1916
|
+
this.refreshSearch(reInitialize);
|
|
1917
|
+
}
|
|
1918
|
+
}
|
|
1919
|
+
updateMinimumCharactersMessageVisibility(criteria) {
|
|
1920
|
+
this.showMinimumCharactersMessage =
|
|
1921
|
+
this.shouldUseCriteria
|
|
1922
|
+
&& this.minimumLengthSearch > 0
|
|
1923
|
+
&& (criteria?.length ?? 0) < this.minimumLengthSearch;
|
|
1924
|
+
}
|
|
1925
|
+
getNativeInput() {
|
|
1926
|
+
return this.inputElement?.nativeElement?.querySelector('input') ?? null;
|
|
1927
|
+
}
|
|
1928
|
+
scrollFocusedItemIntoView() {
|
|
1929
|
+
if (!this.overlayRef || this.focusedIndex < 0) {
|
|
1930
|
+
return;
|
|
1931
|
+
}
|
|
1932
|
+
const optionId = this.getOptionId(this.focusedIndex);
|
|
1933
|
+
const element = this.overlayRef.overlayElement.querySelector('#' + optionId);
|
|
1934
|
+
if (element) {
|
|
1935
|
+
element.scrollIntoView({ block: 'nearest' });
|
|
1936
|
+
}
|
|
1937
|
+
}
|
|
1938
|
+
setInputAriaAttributes() {
|
|
1939
|
+
const input = this.getNativeInput();
|
|
1940
|
+
if (!input) {
|
|
1941
|
+
return;
|
|
1942
|
+
}
|
|
1943
|
+
input.setAttribute('role', 'combobox');
|
|
1944
|
+
input.setAttribute('aria-autocomplete', 'list');
|
|
1945
|
+
input.setAttribute('aria-expanded', String(this.isDropDownShown));
|
|
1946
|
+
input.setAttribute('aria-haspopup', 'listbox');
|
|
1947
|
+
input.setAttribute('aria-owns', this.listboxId);
|
|
1948
|
+
}
|
|
1949
|
+
updateInputAriaActiveDescendant() {
|
|
1950
|
+
const input = this.getNativeInput();
|
|
1951
|
+
if (!input) {
|
|
1952
|
+
return;
|
|
1953
|
+
}
|
|
1954
|
+
input.setAttribute('aria-expanded', String(this.isDropDownShown));
|
|
1955
|
+
const descendantId = this.activeDescendantId;
|
|
1956
|
+
if (descendantId) {
|
|
1957
|
+
input.setAttribute('aria-activedescendant', descendantId);
|
|
1958
|
+
}
|
|
1959
|
+
else {
|
|
1960
|
+
input.removeAttribute('aria-activedescendant');
|
|
1961
|
+
}
|
|
1962
|
+
}
|
|
1963
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: CatalogSelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1964
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.6", type: CatalogSelectComponent, isStandalone: true, selector: "lib-catalog-select", inputs: { autofocus: "autofocus", controlName: "controlName", displayControlName: "displayControlName", displayProperty: "displayProperty", entriesList: "entriesList", filters: "filters", label: "label", maxEntries: "maxEntries", minimumLengthSearch: "minimumLengthSearch", notes: "notes", readOnly: "readOnly", searchEndpoint: "searchEndpoint", validations: "validations", valueProperty: "valueProperty" }, host: { listeners: { "body:mousedown": "bodyMouseDown($event)", "body:mouseup": "bodyMouseUp($event)" } }, viewQueries: [{ propertyName: "dropdownTemplate", first: true, predicate: ["dropdownTemplate"], descendants: true, read: TemplateRef }, { propertyName: "inputElement", first: true, predicate: ["input"], descendants: true, read: ElementRef }], usesInheritance: true, ngImport: i0, template: "<lib-form-input-group\n[controlName]=\"controlName\"\n[label]=\"label\"\n[notes]=\"notes\"\n[template]=\"template\"\n[validations]=\"validations\">\n</lib-form-input-group>\n\n<ng-template #template>\n <div class=\"catalog-container\"\n [class.show]=\"isDropDownShown\">\n <lib-form-input #input\n [class.fixed-content]=\"readOnly && !shouldUseCriteria\"\n [autofocus]=\"autofocus\"\n [controlName]=\"displayControlName\"\n [invalid]=\"isInvalid && isTouched\"\n [readOnly]=\"readOnly\"\n (blur)=\"onContainerBlur()\"\n (click)=\"onContainerClick()\"\n (focus)=\"onContainerFocus()\"\n (keydown)=\"onKeyDown($event)\">\n </lib-form-input>\n <button *ngIf=\"showClearButton\"\n class=\"clear-button\"\n type=\"button\"\n tabindex=\"-1\"\n (click)=\"onClearClick($event)\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n</ng-template>\n\n<ng-template #dropdownTemplate>\n <div class=\"dropdown-container\">\n <ul class=\"dropdown\"\n role=\"listbox\"\n [attr.id]=\"listboxId\">\n <li *ngIf=\"isLoading\"\n (click)=\"onDropDownMessageClick()\">\n {{ 'CatalogSelect-Loading' | translate }}\n </li>\n\n <li *ngIf=\"shouldUseCriteria && showMinimumCharactersMessage\"\n title=\"{{ 'CatalogSelect-MinimumLengthSearch' | translate: { minimumLengthSearch: minimumLengthSearch } }}\"\n (click)=\"onDropDownMessageClick()\">\n {{ 'CatalogSelect-MinimumLengthSearch' | translate: { minimumLengthSearch: minimumLengthSearch } }}\n </li>\n\n <li *ngIf=\"showNoResultsMessage\"\n title=\"{{ 'CatalogSelect-NoResultsFound' | translate }}\"\n (click)=\"onDropDownMessageClick()\">\n {{ 'CatalogSelect-NoResultsFound' | translate }}\n </li>\n\n <li *ngIf=\"showFailureMessage\"\n class=\"error\"\n title=\"{{ 'CatalogSelect-FailureMessage' | translate }}\"\n (click)=\"onDropDownErrorClick()\">\n {{ 'CatalogSelect-FailureMessage' | translate }}\n </li>\n\n <li class=\"dropdown-item\" *ngFor=\"let entry of displayedEntries; let i = index\"\n role=\"option\"\n [attr.id]=\"getOptionId(i)\"\n [attr.aria-selected]=\"selectedValue === entry.value\"\n [class.focused]=\"focusedIndex === i\"\n [class.selected]=\"selectedValue === entry.value\"\n (click)=\"onDropDownItemClick(entry)\">\n {{ entry.display }}\n </li>\n </ul>\n </div>\n</ng-template>", styles: [":host-context{grid-column:span 2 / span 2;display:grid;grid-template-columns:subgrid}.catalog-container{position:relative}.catalog-container .clear-button{position:absolute;right:1.75rem;top:50%;display:flex;--tw-translate-y: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));align-items:center;justify-content:center;height:1.25rem;width:1.25rem;border-radius:9999px;--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity, 1))}.catalog-container .clear-button:hover{--tw-bg-opacity: 1;background-color:rgb(229 231 235 / var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity, 1))}.catalog-container .clear-button{z-index:10;cursor:pointer;border-style:none;background-color:transparent;padding:0;font-size:.875rem;line-height:1.25rem;line-height:1}.catalog-container:has(.clear-button) lib-form-input ::ng-deep input{padding-right:3.5rem}div lib-form-input ::ng-deep input{cursor:pointer;text-overflow:ellipsis;background-size:1.125rem 1.125rem;background-position:right .5625rem center;background-repeat:no-repeat;padding-right:2.25rem;background-image:url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'><path fill='%239ca3af' d='M233.4 406.6c12.5 12.5 32.8 12.5 45.3 0l192-192c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L256 338.7 86.6 169.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l192 192z'/%3e%3c/svg%3e\")}.dropdown-container{width:100%;-webkit-user-select:none;user-select:none}.dropdown{overflow-y:auto;overscroll-behavior:none;border-radius:.375rem;border-width:1px;--tw-border-opacity: 1;border-color:rgb(156 163 175 / var(--tw-border-opacity, 1));--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1));--tw-shadow: 0 1px 3px 0 rgb(0 0 0 / .1), 0 1px 2px -1px rgb(0 0 0 / .1);--tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow);max-height:13rem}.dropdown li{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding:.25rem .5rem}.dropdown li:not(.dropdown-item){font-size:.875rem;line-height:1.25rem}.dropdown li.dropdown-item{cursor:pointer}.dropdown li.dropdown-item:nth-child(2n){background-color:#f5f5f4b3}.dropdown li.dropdown-item.selected{background-color:#59a5db33;font-weight:700}.dropdown li.dropdown-item.focused{background-color:#59a5db4d;outline:2px solid transparent;outline-offset:2px}.dropdown li.dropdown-item:hover,.dropdown li.dropdown-item:nth-child(2n):hover,.dropdown li.dropdown-item.selected:hover,.dropdown li.dropdown-item.focused:hover{background-color:#59a5db80}lib-form-input-group{flex-basis:100%}\n"], dependencies: [{ kind: "component", type: FormInputComponent, selector: "lib-form-input", inputs: ["autofocus", "controlName", "disabledControlName", "displayReadOnlyAsDisabled", "fixedValue", "format", "invalid", "isDisabled", "isFullHeight", "maxLength", "min", "readOnly", "rows", "step", "type"], outputs: ["blur", "change", "fixedValueChanged", "input", "focus"] }, { kind: "component", type: FormInputGroupComponent, selector: "lib-form-input-group", inputs: ["autofocus", "alignContent", "controlName", "fixedValue", "format", "label", "isDisabled", "isFullHeight", "maxLength", "min", "notes", "readOnly", "rows", "showLabel", "step", "template", "type", "validations"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
|
|
1965
|
+
}
|
|
1966
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: CatalogSelectComponent, decorators: [{
|
|
1967
|
+
type: Component,
|
|
1968
|
+
args: [{ selector: 'lib-catalog-select', imports: [
|
|
1969
|
+
FormInputComponent,
|
|
1970
|
+
FormInputGroupComponent,
|
|
1971
|
+
NgFor,
|
|
1972
|
+
NgIf,
|
|
1973
|
+
TranslatePipe,
|
|
1974
|
+
], template: "<lib-form-input-group\n[controlName]=\"controlName\"\n[label]=\"label\"\n[notes]=\"notes\"\n[template]=\"template\"\n[validations]=\"validations\">\n</lib-form-input-group>\n\n<ng-template #template>\n <div class=\"catalog-container\"\n [class.show]=\"isDropDownShown\">\n <lib-form-input #input\n [class.fixed-content]=\"readOnly && !shouldUseCriteria\"\n [autofocus]=\"autofocus\"\n [controlName]=\"displayControlName\"\n [invalid]=\"isInvalid && isTouched\"\n [readOnly]=\"readOnly\"\n (blur)=\"onContainerBlur()\"\n (click)=\"onContainerClick()\"\n (focus)=\"onContainerFocus()\"\n (keydown)=\"onKeyDown($event)\">\n </lib-form-input>\n <button *ngIf=\"showClearButton\"\n class=\"clear-button\"\n type=\"button\"\n tabindex=\"-1\"\n (click)=\"onClearClick($event)\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n</ng-template>\n\n<ng-template #dropdownTemplate>\n <div class=\"dropdown-container\">\n <ul class=\"dropdown\"\n role=\"listbox\"\n [attr.id]=\"listboxId\">\n <li *ngIf=\"isLoading\"\n (click)=\"onDropDownMessageClick()\">\n {{ 'CatalogSelect-Loading' | translate }}\n </li>\n\n <li *ngIf=\"shouldUseCriteria && showMinimumCharactersMessage\"\n title=\"{{ 'CatalogSelect-MinimumLengthSearch' | translate: { minimumLengthSearch: minimumLengthSearch } }}\"\n (click)=\"onDropDownMessageClick()\">\n {{ 'CatalogSelect-MinimumLengthSearch' | translate: { minimumLengthSearch: minimumLengthSearch } }}\n </li>\n\n <li *ngIf=\"showNoResultsMessage\"\n title=\"{{ 'CatalogSelect-NoResultsFound' | translate }}\"\n (click)=\"onDropDownMessageClick()\">\n {{ 'CatalogSelect-NoResultsFound' | translate }}\n </li>\n\n <li *ngIf=\"showFailureMessage\"\n class=\"error\"\n title=\"{{ 'CatalogSelect-FailureMessage' | translate }}\"\n (click)=\"onDropDownErrorClick()\">\n {{ 'CatalogSelect-FailureMessage' | translate }}\n </li>\n\n <li class=\"dropdown-item\" *ngFor=\"let entry of displayedEntries; let i = index\"\n role=\"option\"\n [attr.id]=\"getOptionId(i)\"\n [attr.aria-selected]=\"selectedValue === entry.value\"\n [class.focused]=\"focusedIndex === i\"\n [class.selected]=\"selectedValue === entry.value\"\n (click)=\"onDropDownItemClick(entry)\">\n {{ entry.display }}\n </li>\n </ul>\n </div>\n</ng-template>", styles: [":host-context{grid-column:span 2 / span 2;display:grid;grid-template-columns:subgrid}.catalog-container{position:relative}.catalog-container .clear-button{position:absolute;right:1.75rem;top:50%;display:flex;--tw-translate-y: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));align-items:center;justify-content:center;height:1.25rem;width:1.25rem;border-radius:9999px;--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity, 1))}.catalog-container .clear-button:hover{--tw-bg-opacity: 1;background-color:rgb(229 231 235 / var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity, 1))}.catalog-container .clear-button{z-index:10;cursor:pointer;border-style:none;background-color:transparent;padding:0;font-size:.875rem;line-height:1.25rem;line-height:1}.catalog-container:has(.clear-button) lib-form-input ::ng-deep input{padding-right:3.5rem}div lib-form-input ::ng-deep input{cursor:pointer;text-overflow:ellipsis;background-size:1.125rem 1.125rem;background-position:right .5625rem center;background-repeat:no-repeat;padding-right:2.25rem;background-image:url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'><path fill='%239ca3af' d='M233.4 406.6c12.5 12.5 32.8 12.5 45.3 0l192-192c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L256 338.7 86.6 169.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l192 192z'/%3e%3c/svg%3e\")}.dropdown-container{width:100%;-webkit-user-select:none;user-select:none}.dropdown{overflow-y:auto;overscroll-behavior:none;border-radius:.375rem;border-width:1px;--tw-border-opacity: 1;border-color:rgb(156 163 175 / var(--tw-border-opacity, 1));--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1));--tw-shadow: 0 1px 3px 0 rgb(0 0 0 / .1), 0 1px 2px -1px rgb(0 0 0 / .1);--tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow);max-height:13rem}.dropdown li{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding:.25rem .5rem}.dropdown li:not(.dropdown-item){font-size:.875rem;line-height:1.25rem}.dropdown li.dropdown-item{cursor:pointer}.dropdown li.dropdown-item:nth-child(2n){background-color:#f5f5f4b3}.dropdown li.dropdown-item.selected{background-color:#59a5db33;font-weight:700}.dropdown li.dropdown-item.focused{background-color:#59a5db4d;outline:2px solid transparent;outline-offset:2px}.dropdown li.dropdown-item:hover,.dropdown li.dropdown-item:nth-child(2n):hover,.dropdown li.dropdown-item.selected:hover,.dropdown li.dropdown-item.focused:hover{background-color:#59a5db80}lib-form-input-group{flex-basis:100%}\n"] }]
|
|
1975
|
+
}], ctorParameters: () => [], propDecorators: { bodyMouseDown: [{
|
|
1976
|
+
type: HostListener,
|
|
1977
|
+
args: ['body:mousedown', ['$event']]
|
|
1978
|
+
}], bodyMouseUp: [{
|
|
1979
|
+
type: HostListener,
|
|
1980
|
+
args: ['body:mouseup', ['$event']]
|
|
1981
|
+
}], dropdownTemplate: [{
|
|
1982
|
+
type: ViewChild,
|
|
1983
|
+
args: ['dropdownTemplate', { read: TemplateRef }]
|
|
1984
|
+
}], inputElement: [{
|
|
1985
|
+
type: ViewChild,
|
|
1986
|
+
args: ['input', { read: ElementRef }]
|
|
1987
|
+
}], autofocus: [{
|
|
1988
|
+
type: Input
|
|
1989
|
+
}], controlName: [{
|
|
1990
|
+
type: Input
|
|
1991
|
+
}], displayControlName: [{
|
|
1992
|
+
type: Input
|
|
1993
|
+
}], displayProperty: [{
|
|
1994
|
+
type: Input
|
|
1995
|
+
}], entriesList: [{
|
|
1996
|
+
type: Input
|
|
1997
|
+
}], filters: [{
|
|
1998
|
+
type: Input
|
|
1999
|
+
}], label: [{
|
|
2000
|
+
type: Input
|
|
2001
|
+
}], maxEntries: [{
|
|
2002
|
+
type: Input
|
|
2003
|
+
}], minimumLengthSearch: [{
|
|
2004
|
+
type: Input
|
|
2005
|
+
}], notes: [{
|
|
2006
|
+
type: Input
|
|
2007
|
+
}], readOnly: [{
|
|
2008
|
+
type: Input
|
|
2009
|
+
}], searchEndpoint: [{
|
|
2010
|
+
type: Input
|
|
2011
|
+
}], validations: [{
|
|
2012
|
+
type: Input
|
|
2013
|
+
}], valueProperty: [{
|
|
2014
|
+
type: Input
|
|
2015
|
+
}] } });
|
|
2016
|
+
|
|
2017
|
+
class DataGridRowComponent extends BaseComponent {
|
|
2018
|
+
//#region ViewChilds, Inputs, Outputs
|
|
2019
|
+
disabled = false;
|
|
2020
|
+
isFirstRow = false;
|
|
2021
|
+
set rowData(value) {
|
|
2022
|
+
this._rowData = value;
|
|
2023
|
+
this.refreshSelection();
|
|
2024
|
+
}
|
|
2025
|
+
selectionResized = new EventEmitter();
|
|
2026
|
+
//#endregion
|
|
2027
|
+
//#region Host listeners
|
|
2028
|
+
setFocus() {
|
|
2029
|
+
if (!this.disabled) {
|
|
2030
|
+
this.dataGridDataset.setFocusedRow(this.rowKey);
|
|
2031
|
+
if (this.dataGridDataset.configs.multiSelect && (this.dataGridDataset.configs.selectOnClick ?? true)) {
|
|
2032
|
+
this.selected = this.isRowDataSelected;
|
|
2033
|
+
}
|
|
2034
|
+
}
|
|
2035
|
+
}
|
|
2036
|
+
//#endregion
|
|
2037
|
+
//#region Variables
|
|
2038
|
+
changeDetectorRef = inject(ChangeDetectorRef);
|
|
2039
|
+
dataGridDataset = inject(DataGridDataset);
|
|
2040
|
+
selected = false;
|
|
2041
|
+
_rowData;
|
|
2042
|
+
isWidthSet = {};
|
|
2043
|
+
//#endregion
|
|
2044
|
+
//#region Properties
|
|
2045
|
+
get rowData() {
|
|
2046
|
+
return this._rowData;
|
|
2047
|
+
}
|
|
2048
|
+
get columns() {
|
|
2049
|
+
return this.dataGridDataset.columns;
|
|
2050
|
+
}
|
|
2051
|
+
get isRowDataSelected() {
|
|
2052
|
+
return this.dataGridDataset.isKeySelected(this.rowKey);
|
|
2053
|
+
}
|
|
2054
|
+
get rowKey() {
|
|
2055
|
+
return this.dataGridDataset.getRowInternalKey(this.rowData);
|
|
2056
|
+
}
|
|
2057
|
+
//#endregion
|
|
2058
|
+
//#region Constructor and Angular life cycle methods
|
|
2059
|
+
constructor() {
|
|
2060
|
+
super();
|
|
2061
|
+
}
|
|
2062
|
+
ngOnInit() {
|
|
2063
|
+
this.selected = this.isRowDataSelected;
|
|
2064
|
+
this.dataGridDataset.selectedRowsChanged
|
|
2065
|
+
.pipe(takeUntil(this.destroy$))
|
|
2066
|
+
.subscribe((selectionChanges) => {
|
|
2067
|
+
if (this.rowKey in selectionChanges) {
|
|
2068
|
+
this.selected = selectionChanges[this.rowKey].selected;
|
|
2069
|
+
this.changeDetectorRef.detectChanges();
|
|
2070
|
+
}
|
|
2071
|
+
});
|
|
2072
|
+
}
|
|
2073
|
+
//#endregion
|
|
2074
|
+
//#region Event handlers
|
|
2075
|
+
onResize(colIndex, event) {
|
|
2076
|
+
if (this.isWidthSet[colIndex]) {
|
|
2077
|
+
return;
|
|
2078
|
+
}
|
|
2079
|
+
const width = event.contentRect.width;
|
|
2080
|
+
if (width <= 0) {
|
|
2081
|
+
return;
|
|
2082
|
+
}
|
|
2083
|
+
if (this.columns[colIndex].realSize != width) {
|
|
2084
|
+
this.columns[colIndex].realSize = width;
|
|
2085
|
+
this.isWidthSet[colIndex] = true;
|
|
2086
|
+
}
|
|
2087
|
+
}
|
|
2088
|
+
onResizeSelection(event) {
|
|
2089
|
+
const width = event.contentRect.width;
|
|
2090
|
+
this.selectionResized.emit(width);
|
|
2091
|
+
}
|
|
2092
|
+
onToggleSelection() {
|
|
2093
|
+
if (this.disabled || (this.dataGridDataset.configs.multiSelect && (this.dataGridDataset.configs.selectOnClick ?? true))) {
|
|
2094
|
+
return;
|
|
2095
|
+
}
|
|
2096
|
+
this.selected = !this.selected;
|
|
2097
|
+
if (this.selected) {
|
|
2098
|
+
this.dataGridDataset.selectRow(this.rowKey);
|
|
2099
|
+
}
|
|
2100
|
+
else {
|
|
2101
|
+
this.dataGridDataset.deselectRow(this.rowKey);
|
|
2102
|
+
}
|
|
2103
|
+
}
|
|
2104
|
+
//#endregion
|
|
2105
|
+
//#region Public methods
|
|
2106
|
+
getValue(field) {
|
|
2107
|
+
return field.split('.').reduce((value, field) => value[field], this.rowData);
|
|
2108
|
+
}
|
|
2109
|
+
//#endregion
|
|
2110
|
+
//#region Private methods
|
|
2111
|
+
refreshSelection() {
|
|
2112
|
+
this.selected = this.isRowDataSelected;
|
|
2113
|
+
}
|
|
2114
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: DataGridRowComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2115
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.6", type: DataGridRowComponent, isStandalone: true, selector: "lib-data-grid-row", inputs: { disabled: "disabled", isFirstRow: "isFirstRow", rowData: "rowData" }, outputs: { selectionResized: "selectionResized" }, host: { listeners: { "click": "setFocus()" }, properties: { "class.focused": "dataGridDataset.focusedRow === rowData", "class.selected": "dataGridDataset.isKeySelected(rowKey)" } }, usesInheritance: true, ngImport: i0, template: "<div *ngIf=\"dataGridDataset.configs.multiSelect\"\nclass=\"cell\"\n(click)=\"onToggleSelection()\"\n(onResize)=\"onResizeSelection($event)\">\n <input class=\"form-input\"\n type=\"checkbox\"\n [attr.disabled]=\"disabled\"\n [(ngModel)]=\"selected\" />\n</div> \n\n<div #cell\n*ngFor=\"let column of columns; index as i\"\nclass=\"cell\"\n[class.disabled]=\"disabled\"\n[ngClass]=\"column.customClass\">\n <div *ngIf=\"isFirstRow\"\n class=\"spacer\"\n (onResize)=\"onResize(i, $event)\"></div>\n\n <ng-container *ngTemplateOutlet=\"column.template ? column.template : simpleTemplate; context: { rowData: rowData, column: column }\">\n </ng-container>\n</div>\n\n<ng-template #simpleTemplate let-rowData=\"rowData\" let-column=\"column\">\n <span>{{ getValue(column.field) }}</span>\n</ng-template>", styles: [":host{grid-column:1 / -1;display:grid;grid-template-columns:subgrid}.cell{position:relative;align-content:center;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.cell.disabled{pointer-events:none;cursor:default;overflow:hidden;text-overflow:ellipsis;opacity:.6}.cell input{vertical-align:super}.spacer{position:absolute;inset:0;z-index:-1;height:0px}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: NgxResizeObserverModule }, { kind: "directive", type: i2.NgxResizeObserverDirective, selector: "[onResize]", inputs: ["resizeBoxModel"], outputs: ["onResize"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2116
|
+
}
|
|
2117
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: DataGridRowComponent, decorators: [{
|
|
2118
|
+
type: Component,
|
|
2119
|
+
args: [{ selector: 'lib-data-grid-row', host: {
|
|
2120
|
+
'[class.focused]': 'dataGridDataset.focusedRow === rowData',
|
|
2121
|
+
'[class.selected]': 'dataGridDataset.isKeySelected(rowKey)',
|
|
2122
|
+
}, changeDetection: ChangeDetectionStrategy.OnPush, imports: [
|
|
2123
|
+
FormsModule,
|
|
2124
|
+
NgClass,
|
|
2125
|
+
NgIf,
|
|
2126
|
+
NgFor,
|
|
2127
|
+
NgTemplateOutlet,
|
|
2128
|
+
NgxResizeObserverModule,
|
|
2129
|
+
], template: "<div *ngIf=\"dataGridDataset.configs.multiSelect\"\nclass=\"cell\"\n(click)=\"onToggleSelection()\"\n(onResize)=\"onResizeSelection($event)\">\n <input class=\"form-input\"\n type=\"checkbox\"\n [attr.disabled]=\"disabled\"\n [(ngModel)]=\"selected\" />\n</div> \n\n<div #cell\n*ngFor=\"let column of columns; index as i\"\nclass=\"cell\"\n[class.disabled]=\"disabled\"\n[ngClass]=\"column.customClass\">\n <div *ngIf=\"isFirstRow\"\n class=\"spacer\"\n (onResize)=\"onResize(i, $event)\"></div>\n\n <ng-container *ngTemplateOutlet=\"column.template ? column.template : simpleTemplate; context: { rowData: rowData, column: column }\">\n </ng-container>\n</div>\n\n<ng-template #simpleTemplate let-rowData=\"rowData\" let-column=\"column\">\n <span>{{ getValue(column.field) }}</span>\n</ng-template>", styles: [":host{grid-column:1 / -1;display:grid;grid-template-columns:subgrid}.cell{position:relative;align-content:center;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.cell.disabled{pointer-events:none;cursor:default;overflow:hidden;text-overflow:ellipsis;opacity:.6}.cell input{vertical-align:super}.spacer{position:absolute;inset:0;z-index:-1;height:0px}\n"] }]
|
|
2130
|
+
}], ctorParameters: () => [], propDecorators: { disabled: [{
|
|
2131
|
+
type: Input
|
|
2132
|
+
}], isFirstRow: [{
|
|
2133
|
+
type: Input
|
|
2134
|
+
}], rowData: [{
|
|
2135
|
+
type: Input
|
|
2136
|
+
}], selectionResized: [{
|
|
2137
|
+
type: Output
|
|
2138
|
+
}], setFocus: [{
|
|
2139
|
+
type: HostListener,
|
|
2140
|
+
args: ['click']
|
|
2141
|
+
}] } });
|
|
2142
|
+
|
|
2143
|
+
class DataGridComponent extends BaseComponent {
|
|
2144
|
+
//#region ViewChilds, Inputs, Outputs
|
|
2145
|
+
bodyElement;
|
|
2146
|
+
viewport;
|
|
2147
|
+
disabled = false;
|
|
2148
|
+
lazyLoadRows = false;
|
|
2149
|
+
showButtons = false;
|
|
2150
|
+
//#endregion
|
|
2151
|
+
//#region Variables
|
|
2152
|
+
changeDetectorRef = inject(ChangeDetectorRef);
|
|
2153
|
+
dataGridDataset = inject(DataGridDataset);
|
|
2154
|
+
hasFailed = false;
|
|
2155
|
+
headerRightMargin = 0;
|
|
2156
|
+
loading = false;
|
|
2157
|
+
bodyResized$ = new Subject();
|
|
2158
|
+
bodyResizeObserver;
|
|
2159
|
+
gridRoute = '';
|
|
2160
|
+
isGridCurrentUrl = false;
|
|
2161
|
+
lastPosition = 0;
|
|
2162
|
+
ngZone = inject(NgZone);
|
|
2163
|
+
router = inject(Router);
|
|
2164
|
+
selectionColRealSize;
|
|
2165
|
+
//#endregion
|
|
2166
|
+
//#region Properties
|
|
2167
|
+
get bodyMinHeight() {
|
|
2168
|
+
let rowsToDisplay = this.configs.rowsToDisplay ?? 3;
|
|
2169
|
+
let rowsCount = this.dataGridDataset.loadedRows?.length ?? 0;
|
|
2170
|
+
if (rowsCount === 0) {
|
|
2171
|
+
rowsCount = 1;
|
|
2172
|
+
}
|
|
2173
|
+
if (rowsCount < rowsToDisplay) {
|
|
2174
|
+
rowsToDisplay = rowsCount;
|
|
2175
|
+
}
|
|
2176
|
+
return rowsToDisplay * this.configs.rowHeight;
|
|
2177
|
+
}
|
|
2178
|
+
get columns() {
|
|
2179
|
+
return this.dataGridDataset.columns;
|
|
2180
|
+
}
|
|
2181
|
+
get configs() {
|
|
2182
|
+
return this.dataGridDataset.configs;
|
|
2183
|
+
}
|
|
2184
|
+
get gridColumns() {
|
|
2185
|
+
return this.dataGridDataset.columnsSize;
|
|
2186
|
+
}
|
|
2187
|
+
get hasBeenLoaded() {
|
|
2188
|
+
return this.dataGridDataset.hasBeenLoaded;
|
|
2189
|
+
}
|
|
2190
|
+
get hasLoadedRows() {
|
|
2191
|
+
return (this.dataGridDataset.loadedRows?.length ?? 0) > 0;
|
|
2192
|
+
}
|
|
2193
|
+
get hasMessageToDisplayWhenEmpty() {
|
|
2194
|
+
return this.messageToDisplayWhenEmpty.length > 0;
|
|
2195
|
+
}
|
|
2196
|
+
get isHideColumns() {
|
|
2197
|
+
return this.dataGridDataset.configs.hideColumnHeaders ?? false;
|
|
2198
|
+
}
|
|
2199
|
+
get isShowMultiSelect() {
|
|
2200
|
+
return this.dataGridDataset.configs.multiSelect ?? false;
|
|
2201
|
+
}
|
|
2202
|
+
get messageToDisplayWhenEmpty() {
|
|
2203
|
+
return this.dataGridDataset?.configs?.messageOnEmpty ?? '';
|
|
2204
|
+
}
|
|
2205
|
+
get messageToDisplayWhenLazyLoad() {
|
|
2206
|
+
return this.dataGridDataset?.configs?.messageOnLazyLoad ?? '';
|
|
2207
|
+
}
|
|
2208
|
+
get messageToDisplayWhenFailed() {
|
|
2209
|
+
return this.dataGridDataset?.configs?.messageOnFailed ?? '';
|
|
2210
|
+
}
|
|
2211
|
+
get selectionColWidth() {
|
|
2212
|
+
return this.selectionColRealSize
|
|
2213
|
+
? `${this.selectionColRealSize}px`
|
|
2214
|
+
: this.configs.multiSelectSize ?? 'minmax(1.5rem,min-content)';
|
|
2215
|
+
}
|
|
2216
|
+
get shouldDisplayMessageWhenEmpty() {
|
|
2217
|
+
return this.dataGridDataset?.configs?.showMessageOnEmpty ?? true;
|
|
2218
|
+
}
|
|
2219
|
+
//#endregion
|
|
2220
|
+
//#region Constructor and Angular life cycle methods
|
|
2221
|
+
constructor() {
|
|
2222
|
+
super();
|
|
2223
|
+
}
|
|
2224
|
+
ngOnInit() {
|
|
2225
|
+
this.gridRoute = this.router.url;
|
|
2226
|
+
this.isGridCurrentUrl = true;
|
|
2227
|
+
this.router.events
|
|
2228
|
+
.pipe(takeUntil(this.destroy$), filter((events) => events instanceof NavigationStart || events instanceof NavigationEnd))
|
|
2229
|
+
.subscribe((event) => {
|
|
2230
|
+
if (event instanceof NavigationStart && this.isGridCurrentUrl) {
|
|
2231
|
+
this.lastPosition = this.viewport?.measureScrollOffset() ?? 0;
|
|
2232
|
+
this.isGridCurrentUrl = false;
|
|
2233
|
+
}
|
|
2234
|
+
else if (event instanceof NavigationEnd && event.url === this.gridRoute) {
|
|
2235
|
+
this.viewport?.scrollTo({ top: this.lastPosition });
|
|
2236
|
+
this.viewport?.checkViewportSize();
|
|
2237
|
+
this.isGridCurrentUrl = true;
|
|
2238
|
+
}
|
|
2239
|
+
});
|
|
2240
|
+
this.dataGridDataset.loadStarted
|
|
2241
|
+
.pipe(takeUntil(this.destroy$))
|
|
2242
|
+
.subscribe(() => {
|
|
2243
|
+
this.loading = true;
|
|
2244
|
+
});
|
|
2245
|
+
this.dataGridDataset.loadFinished
|
|
2246
|
+
.pipe(takeUntil(this.destroy$))
|
|
2247
|
+
.subscribe((isSuccess) => {
|
|
2248
|
+
this.loading = false;
|
|
2249
|
+
this.hasFailed = !isSuccess;
|
|
2250
|
+
setTimeout(() => {
|
|
2251
|
+
const viewportWidth = this.viewport?.measureViewportSize('horizontal') ?? 0;
|
|
2252
|
+
if (viewportWidth > 0) {
|
|
2253
|
+
this.headerRightMargin = this.bodyElement.nativeElement.clientWidth - viewportWidth;
|
|
2254
|
+
}
|
|
2255
|
+
}, 100);
|
|
2256
|
+
this.changeDetectorRef.detectChanges();
|
|
2257
|
+
setTimeout(() => {
|
|
2258
|
+
this.viewport?.checkViewportSize();
|
|
2259
|
+
});
|
|
2260
|
+
});
|
|
2261
|
+
if (!this.lazyLoadRows) {
|
|
2262
|
+
if (!this.dataGridDataset.loadedRows) {
|
|
2263
|
+
this.loading = true;
|
|
2264
|
+
}
|
|
2265
|
+
this.dataGridDataset.loadRows();
|
|
2266
|
+
}
|
|
2267
|
+
else if (this.dataGridDataset.isLoading) {
|
|
2268
|
+
this.loading = true;
|
|
2269
|
+
}
|
|
2270
|
+
}
|
|
2271
|
+
ngAfterViewInit() {
|
|
2272
|
+
this.viewport?.renderedRangeStream
|
|
2273
|
+
.pipe(takeUntil(this.destroy$))
|
|
2274
|
+
.subscribe((listRange) => {
|
|
2275
|
+
const loadedRows = this.dataGridDataset.loadedRows?.length ?? 0;
|
|
2276
|
+
if (this.hasLoadedRows && !this.loading && listRange.end >= loadedRows && !this.dataGridDataset.loadedLastRow) {
|
|
2277
|
+
this.loading = true;
|
|
2278
|
+
this.dataGridDataset.loadRows();
|
|
2279
|
+
}
|
|
2280
|
+
});
|
|
2281
|
+
this.bodyResized$
|
|
2282
|
+
.pipe(debounceTime(150), takeUntil(this.destroy$))
|
|
2283
|
+
.subscribe(() => {
|
|
2284
|
+
const viewportWidth = this.viewport?.measureViewportSize('horizontal') ?? 0;
|
|
2285
|
+
if (viewportWidth > 0) {
|
|
2286
|
+
this.headerRightMargin = this.bodyElement.nativeElement.clientWidth - viewportWidth;
|
|
2287
|
+
}
|
|
2288
|
+
this.viewport?.checkViewportSize();
|
|
2289
|
+
this.changeDetectorRef.detectChanges();
|
|
2290
|
+
});
|
|
2291
|
+
this.ngZone.runOutsideAngular(() => {
|
|
2292
|
+
this.bodyResizeObserver = new ResizeObserver(() => {
|
|
2293
|
+
this.bodyResized$.next();
|
|
2294
|
+
});
|
|
2295
|
+
this.bodyResizeObserver.observe(this.bodyElement.nativeElement);
|
|
2296
|
+
});
|
|
2297
|
+
}
|
|
2298
|
+
ngOnDestroy() {
|
|
2299
|
+
this.bodyResizeObserver?.disconnect();
|
|
2300
|
+
super.ngOnDestroy();
|
|
2301
|
+
}
|
|
2302
|
+
//#endregion
|
|
2303
|
+
//#region Event handlers
|
|
2304
|
+
onSelectionResized(newSize) {
|
|
2305
|
+
if (this.selectionColRealSize != newSize) {
|
|
2306
|
+
this.selectionColRealSize = newSize;
|
|
2307
|
+
}
|
|
2308
|
+
}
|
|
2309
|
+
//#endregion
|
|
2310
|
+
//#region Public methods
|
|
2311
|
+
isFirstVisibleRow(rowIndex) {
|
|
2312
|
+
const renderedRange = this.viewport?.getRenderedRange();
|
|
2313
|
+
if (renderedRange) {
|
|
2314
|
+
return rowIndex === renderedRange.start;
|
|
2315
|
+
}
|
|
2316
|
+
return false;
|
|
2317
|
+
}
|
|
2318
|
+
//#endregion
|
|
2319
|
+
//#region Private methods
|
|
2320
|
+
trackByFn(index, item) {
|
|
2321
|
+
return item.key;
|
|
2322
|
+
}
|
|
2323
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: DataGridComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2324
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.6", type: DataGridComponent, isStandalone: true, selector: "lib-data-grid", inputs: { disabled: "disabled", lazyLoadRows: "lazyLoadRows", showButtons: "showButtons" }, host: { properties: { "class.no-borders": "showButtons" } }, viewQueries: [{ propertyName: "bodyElement", first: true, predicate: ["body"], descendants: true }, { propertyName: "viewport", first: true, predicate: CdkVirtualScrollViewport, descendants: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"buttons\"\n*ngIf=\"showButtons\">\n <ng-content select=\"[buttons]\"></ng-content>\n</div>\n\n<div class=\"header\"\n[class.hide]=\"isHideColumns\"\n[style.padding-right.px]=\"headerRightMargin\">\n <div class=\"header-row\">\n <div *ngIf=\"isShowMultiSelect\"\n class=\"header-cell selection\"\n [ngStyle]=\"{\n 'width': selectionColWidth ? selectionColWidth : null\n }\">\n \n </div>\n \n <div *ngFor=\"let column of columns\"\n class=\"header-cell\"\n [ngStyle]=\"{\n 'width.px': column.realSize ?? 0 > 0 ? column.realSize : null\n }\">\n <span>{{ column.headerName | translate }}</span>\n </div>\n </div>\n</div>\n\n<div #body\nclass=\"body\"\n[style.min-height.px]=\"bodyMinHeight\">\n <cdk-virtual-scroll-viewport\n [itemSize]=\"configs.rowHeight\"\n [style.grid-template-columns]=\"gridColumns\">\n <lib-data-grid-row #row\n *cdkVirtualFor=\"let row of dataGridDataset.loadedRows; index as i; trackBy: trackByFn\"\n [disabled]=\"disabled\"\n [isFirstRow]=\"isFirstVisibleRow(i)\"\n [rowData]=\"row\"\n [style.height.px]=\"configs.rowHeight\"\n (selectionResized)=\"onSelectionResized($event)\">\n </lib-data-grid-row>\n\n <div *ngIf=\"loading\"\n class=\"loading\"\n [style.height.px]=\"configs.rowHeight\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle class=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\"></circle>\n <path class=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"></path>\n </svg>\n \n <span>\n {{ dataGridDataset.configs.loadingDisplayText ?? '' | translate }} \n </span>\n </div>\n \n <div *ngIf=\"!loading && !hasBeenLoaded && lazyLoadRows\"\n class=\"message\"\n [style.height.px]=\"configs.rowHeight\">\n <span>\n {{ messageToDisplayWhenLazyLoad | translate }}\n </span>\n </div>\n\n <ng-container *ngIf=\"!loading && hasBeenLoaded && (!hasLoadedRows || hasFailed)\">\n <div *ngIf=\"!hasFailed && !hasLoadedRows && hasMessageToDisplayWhenEmpty && shouldDisplayMessageWhenEmpty\"\n class=\"message\"\n [style.height.px]=\"configs.rowHeight\">\n <span>\n {{ messageToDisplayWhenEmpty | translate }}\n </span>\n </div>\n\n <div *ngIf=\"hasFailed\"\n class=\"message\"\n [style.height.px]=\"configs.rowHeight\">\n <span>\n <i class=\"fas fa-exclamation-triangle mr-2 text-yellow-600\"></i>{{ messageToDisplayWhenFailed | translate }}\n </span>\n </div>\n </ng-container>\n </cdk-virtual-scroll-viewport>\n</div>", styles: [":host-context{display:flex;-webkit-user-select:none;user-select:none;flex-direction:column;overflow:hidden}:host-context:not(.no-borders){border-radius:.5rem;border-width:1px;border-color:#d1d5dbe6;--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}:host-context.no-borders .header .header-row{padding-top:.375rem;padding-bottom:.375rem}:host-context.no-borders .body lib-data-grid-row{padding-top:.25rem;padding-bottom:.25rem}.header-row,lib-data-grid-row,.loading,.message{gap:1rem;padding-left:1rem;padding-right:1rem}.header{border-bottom-width:1px;border-color:#d1d5dbe6;background-color:#e5e7eb66;font-weight:700}.header.hide{display:none}.header .header-row{display:flex;flex-direction:row;padding-top:.75rem;padding-bottom:.75rem}.header .header-cell{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.header .header-cell:not(.selection){flex-grow:1}.body{position:relative;flex-grow:1}.body cdk-virtual-scroll-viewport{position:absolute;inset:0}.body cdk-virtual-scroll-viewport ::ng-deep .cdk-virtual-scroll-content-wrapper{display:grid;grid-template-columns:inherit}.body lib-data-grid-row{margin-top:-1px;cursor:pointer;border-top-width:1px;border-bottom-width:1px;border-color:#cbd5e180;padding-top:.5rem;padding-bottom:.5rem}.body lib-data-grid-row:nth-child(2n){background-color:#f8fafcb3}.body lib-data-grid-row:hover{background-color:#bfdbfe33}.body lib-data-grid-row.focused{z-index:1;border-color:#94a3b899}.body lib-data-grid-row.selected{position:relative;z-index:10;--tw-border-opacity: 1;border-color:rgb(147 197 253 / var(--tw-border-opacity, 1));background-color:#bfdbfe4d}.body lib-data-grid-row.selected:hover{background-color:#bfdbfe66}.body .loading,.body .message{display:flex;align-items:center;gap:.5rem;white-space:nowrap;height:2.5rem;border-bottom-width:1px;border-color:#cbd5e180;grid-column:1 / -1}.body .loading span,.body .message span{overflow:hidden;text-overflow:ellipsis}.body .loading svg{height:1.5rem;min-height:1.5rem;width:1.5rem;min-width:1.5rem}@keyframes spin{to{transform:rotate(360deg)}}.body .loading svg{animation:spin 1s linear infinite;transition-property:opacity;transition-duration:.2s;transition-timing-function:cubic-bezier(.4,0,.2,1)}.buttons{display:flex;border-top-width:1px;border-bottom-width:1px;border-color:#d1d5dbe6;padding:.25rem}\n"], dependencies: [{ kind: "component", type: DataGridRowComponent, selector: "lib-data-grid-row", inputs: ["disabled", "isFirstRow", "rowData"], outputs: ["selectionResized"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: ScrollingModule }, { kind: "directive", type: i1$2.CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i1$2.CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i1$2.CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
|
|
2325
|
+
}
|
|
2326
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: DataGridComponent, decorators: [{
|
|
2327
|
+
type: Component,
|
|
2328
|
+
args: [{ selector: 'lib-data-grid', host: {
|
|
2329
|
+
'[class.no-borders]': 'showButtons',
|
|
2330
|
+
}, imports: [
|
|
2331
|
+
DataGridRowComponent,
|
|
2332
|
+
NgFor,
|
|
2333
|
+
NgIf,
|
|
2334
|
+
NgStyle,
|
|
2335
|
+
ScrollingModule,
|
|
2336
|
+
TranslatePipe,
|
|
2337
|
+
], template: "<div class=\"buttons\"\n*ngIf=\"showButtons\">\n <ng-content select=\"[buttons]\"></ng-content>\n</div>\n\n<div class=\"header\"\n[class.hide]=\"isHideColumns\"\n[style.padding-right.px]=\"headerRightMargin\">\n <div class=\"header-row\">\n <div *ngIf=\"isShowMultiSelect\"\n class=\"header-cell selection\"\n [ngStyle]=\"{\n 'width': selectionColWidth ? selectionColWidth : null\n }\">\n \n </div>\n \n <div *ngFor=\"let column of columns\"\n class=\"header-cell\"\n [ngStyle]=\"{\n 'width.px': column.realSize ?? 0 > 0 ? column.realSize : null\n }\">\n <span>{{ column.headerName | translate }}</span>\n </div>\n </div>\n</div>\n\n<div #body\nclass=\"body\"\n[style.min-height.px]=\"bodyMinHeight\">\n <cdk-virtual-scroll-viewport\n [itemSize]=\"configs.rowHeight\"\n [style.grid-template-columns]=\"gridColumns\">\n <lib-data-grid-row #row\n *cdkVirtualFor=\"let row of dataGridDataset.loadedRows; index as i; trackBy: trackByFn\"\n [disabled]=\"disabled\"\n [isFirstRow]=\"isFirstVisibleRow(i)\"\n [rowData]=\"row\"\n [style.height.px]=\"configs.rowHeight\"\n (selectionResized)=\"onSelectionResized($event)\">\n </lib-data-grid-row>\n\n <div *ngIf=\"loading\"\n class=\"loading\"\n [style.height.px]=\"configs.rowHeight\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle class=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\"></circle>\n <path class=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"></path>\n </svg>\n \n <span>\n {{ dataGridDataset.configs.loadingDisplayText ?? '' | translate }} \n </span>\n </div>\n \n <div *ngIf=\"!loading && !hasBeenLoaded && lazyLoadRows\"\n class=\"message\"\n [style.height.px]=\"configs.rowHeight\">\n <span>\n {{ messageToDisplayWhenLazyLoad | translate }}\n </span>\n </div>\n\n <ng-container *ngIf=\"!loading && hasBeenLoaded && (!hasLoadedRows || hasFailed)\">\n <div *ngIf=\"!hasFailed && !hasLoadedRows && hasMessageToDisplayWhenEmpty && shouldDisplayMessageWhenEmpty\"\n class=\"message\"\n [style.height.px]=\"configs.rowHeight\">\n <span>\n {{ messageToDisplayWhenEmpty | translate }}\n </span>\n </div>\n\n <div *ngIf=\"hasFailed\"\n class=\"message\"\n [style.height.px]=\"configs.rowHeight\">\n <span>\n <i class=\"fas fa-exclamation-triangle mr-2 text-yellow-600\"></i>{{ messageToDisplayWhenFailed | translate }}\n </span>\n </div>\n </ng-container>\n </cdk-virtual-scroll-viewport>\n</div>", styles: [":host-context{display:flex;-webkit-user-select:none;user-select:none;flex-direction:column;overflow:hidden}:host-context:not(.no-borders){border-radius:.5rem;border-width:1px;border-color:#d1d5dbe6;--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}:host-context.no-borders .header .header-row{padding-top:.375rem;padding-bottom:.375rem}:host-context.no-borders .body lib-data-grid-row{padding-top:.25rem;padding-bottom:.25rem}.header-row,lib-data-grid-row,.loading,.message{gap:1rem;padding-left:1rem;padding-right:1rem}.header{border-bottom-width:1px;border-color:#d1d5dbe6;background-color:#e5e7eb66;font-weight:700}.header.hide{display:none}.header .header-row{display:flex;flex-direction:row;padding-top:.75rem;padding-bottom:.75rem}.header .header-cell{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.header .header-cell:not(.selection){flex-grow:1}.body{position:relative;flex-grow:1}.body cdk-virtual-scroll-viewport{position:absolute;inset:0}.body cdk-virtual-scroll-viewport ::ng-deep .cdk-virtual-scroll-content-wrapper{display:grid;grid-template-columns:inherit}.body lib-data-grid-row{margin-top:-1px;cursor:pointer;border-top-width:1px;border-bottom-width:1px;border-color:#cbd5e180;padding-top:.5rem;padding-bottom:.5rem}.body lib-data-grid-row:nth-child(2n){background-color:#f8fafcb3}.body lib-data-grid-row:hover{background-color:#bfdbfe33}.body lib-data-grid-row.focused{z-index:1;border-color:#94a3b899}.body lib-data-grid-row.selected{position:relative;z-index:10;--tw-border-opacity: 1;border-color:rgb(147 197 253 / var(--tw-border-opacity, 1));background-color:#bfdbfe4d}.body lib-data-grid-row.selected:hover{background-color:#bfdbfe66}.body .loading,.body .message{display:flex;align-items:center;gap:.5rem;white-space:nowrap;height:2.5rem;border-bottom-width:1px;border-color:#cbd5e180;grid-column:1 / -1}.body .loading span,.body .message span{overflow:hidden;text-overflow:ellipsis}.body .loading svg{height:1.5rem;min-height:1.5rem;width:1.5rem;min-width:1.5rem}@keyframes spin{to{transform:rotate(360deg)}}.body .loading svg{animation:spin 1s linear infinite;transition-property:opacity;transition-duration:.2s;transition-timing-function:cubic-bezier(.4,0,.2,1)}.buttons{display:flex;border-top-width:1px;border-bottom-width:1px;border-color:#d1d5dbe6;padding:.25rem}\n"] }]
|
|
2338
|
+
}], ctorParameters: () => [], propDecorators: { bodyElement: [{
|
|
2339
|
+
type: ViewChild,
|
|
2340
|
+
args: ['body']
|
|
2341
|
+
}], viewport: [{
|
|
2342
|
+
type: ViewChild,
|
|
2343
|
+
args: [CdkVirtualScrollViewport]
|
|
2344
|
+
}], disabled: [{
|
|
2345
|
+
type: Input
|
|
2346
|
+
}], lazyLoadRows: [{
|
|
2347
|
+
type: Input
|
|
2348
|
+
}], showButtons: [{
|
|
2349
|
+
type: Input
|
|
2350
|
+
}] } });
|
|
2351
|
+
|
|
2352
|
+
class FormGroupComponent {
|
|
2353
|
+
//#region ViewChilds, Inputs, Outputs
|
|
2354
|
+
shouldExpand = false;
|
|
2355
|
+
label;
|
|
2356
|
+
//#endregion
|
|
2357
|
+
//#region Variables
|
|
2358
|
+
//#endregion
|
|
2359
|
+
//#region Properties
|
|
2360
|
+
get hasTitle() {
|
|
2361
|
+
return !!this.label;
|
|
2362
|
+
}
|
|
2363
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: FormGroupComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2364
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.6", type: FormGroupComponent, isStandalone: true, selector: "lib-form-group", inputs: { shouldExpand: "shouldExpand", label: "label" }, host: { properties: { "class.expand": "shouldExpand" } }, ngImport: i0, template: "<h3 *ngIf=\"hasTitle\"\nclass=\"title\" >\n {{ label | translate }}\n</h3>\n\n<div class=\"content\"\n[class.has-title]=\"hasTitle\">\n <ng-content></ng-content>\n</div>", styles: [":host-context.expand{display:flex;max-height:100%;flex-direction:column;overflow-y:hidden}:host-context.expand .content{max-height:100%;flex-grow:1;overflow-y:hidden}.title{font-size:1.125rem;line-height:1.75rem;font-weight:600}.content{display:grid;grid-auto-rows:auto;grid-template-columns:min-content minmax(0,1fr);gap:.25rem}.content.has-title{border-top-width:1px;border-color:#d1d5dbe6;padding:.75rem .5rem .5rem}\n"], dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
|
|
2365
|
+
}
|
|
2366
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: FormGroupComponent, decorators: [{
|
|
2367
|
+
type: Component,
|
|
2368
|
+
args: [{ selector: 'lib-form-group', imports: [
|
|
2369
|
+
NgIf,
|
|
2370
|
+
TranslatePipe,
|
|
2371
|
+
], host: {
|
|
2372
|
+
'[class.expand]': 'shouldExpand'
|
|
2373
|
+
}, template: "<h3 *ngIf=\"hasTitle\"\nclass=\"title\" >\n {{ label | translate }}\n</h3>\n\n<div class=\"content\"\n[class.has-title]=\"hasTitle\">\n <ng-content></ng-content>\n</div>", styles: [":host-context.expand{display:flex;max-height:100%;flex-direction:column;overflow-y:hidden}:host-context.expand .content{max-height:100%;flex-grow:1;overflow-y:hidden}.title{font-size:1.125rem;line-height:1.75rem;font-weight:600}.content{display:grid;grid-auto-rows:auto;grid-template-columns:min-content minmax(0,1fr);gap:.25rem}.content.has-title{border-top-width:1px;border-color:#d1d5dbe6;padding:.75rem .5rem .5rem}\n"] }]
|
|
2374
|
+
}], propDecorators: { shouldExpand: [{
|
|
2375
|
+
type: Input
|
|
2376
|
+
}], label: [{
|
|
2377
|
+
type: Input
|
|
2378
|
+
}] } });
|
|
2379
|
+
|
|
2380
|
+
class GroupAccordionComponent {
|
|
2381
|
+
//#region ViewChilds, Inputs, Outputs
|
|
2382
|
+
containerElementRef;
|
|
2383
|
+
label;
|
|
2384
|
+
//#endregion
|
|
2385
|
+
//#region Variables
|
|
2386
|
+
_maxHeight = -1;
|
|
2387
|
+
collapsed = false;
|
|
2388
|
+
//#endregion
|
|
2389
|
+
//#region Properties
|
|
2390
|
+
get maxHeight() {
|
|
2391
|
+
return this._maxHeight;
|
|
2392
|
+
}
|
|
2393
|
+
//#endregion
|
|
2394
|
+
//#region Constructor and Angular life cycle methods
|
|
2395
|
+
//#endregion
|
|
2396
|
+
//#region Event handlers
|
|
2397
|
+
onToggle() {
|
|
2398
|
+
// Before collapsing, we set the max height style for the closing effect.
|
|
2399
|
+
if (!this.collapsed) {
|
|
2400
|
+
this.setMaxHeight();
|
|
2401
|
+
}
|
|
2402
|
+
setTimeout(() => {
|
|
2403
|
+
this.collapsed = !this.collapsed;
|
|
2404
|
+
// After expanding, we wait the transition to end and remove the max height.
|
|
2405
|
+
if (!this.collapsed) {
|
|
2406
|
+
this.clearMaxHeight();
|
|
2407
|
+
}
|
|
2408
|
+
});
|
|
2409
|
+
}
|
|
2410
|
+
//#endregion
|
|
2411
|
+
//#region Public methods
|
|
2412
|
+
//#endregion
|
|
2413
|
+
//#region Private methods
|
|
2414
|
+
clearMaxHeight() {
|
|
2415
|
+
setTimeout(() => {
|
|
2416
|
+
this._maxHeight = -1;
|
|
2417
|
+
}, 150);
|
|
2418
|
+
}
|
|
2419
|
+
setMaxHeight() {
|
|
2420
|
+
this._maxHeight = this.containerElementRef?.nativeElement?.offsetHeight ?? 0;
|
|
2421
|
+
}
|
|
2422
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: GroupAccordionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2423
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.6", type: GroupAccordionComponent, isStandalone: true, selector: "lib-group-accordion", inputs: { label: "label" }, host: { properties: { "class.collapsed": "collapsed" } }, viewQueries: [{ propertyName: "containerElementRef", first: true, predicate: ["container"], descendants: true }], ngImport: i0, template: "<div class=\"title\">\n <h6 (click)=\"onToggle()\"><i class=\"fas fa-chevron-down fa-sm\"></i>{{ this.label }}</h6>\n</div>\n\n<div #container class=\"content animate\"\n[ngStyle]=\"maxHeight >= 0 && {\n 'height.px': maxHeight,\n 'max-height.px': maxHeight\n} || null\">\n <div #maxHeighContainer>\n <ng-content></ng-content>\n </div>\n</div>", styles: [":host-context{margin-bottom:1rem;display:flex;flex-direction:column}:host-context.collapsed i{--tw-rotate: -90deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}:host-context.collapsed .content{max-height:0px!important;overflow:hidden!important}:host-context:not(.collapsed) .content{animation:show .15s}.title{-webkit-user-select:none;user-select:none}.title i{margin-right:.5rem;padding-top:.25rem;--tw-text-opacity: 1;color:rgb(100 116 139 / var(--tw-text-opacity, 1));transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.title h6{margin-bottom:0;display:inline;height:3rem;cursor:pointer;text-overflow:ellipsis;white-space:nowrap;padding-left:.25rem;padding-right:.5rem;font-size:1.125rem;text-transform:uppercase;line-height:3rem}.content{box-sizing:content-box;flex-grow:1;overflow-y:hidden;padding-left:.25rem;padding-right:.25rem}.content.animate{transition-property:max-height;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.content div{padding-bottom:.25rem}@media (min-width: 1024px){.content div{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:.75rem}}@media (min-width: 1280px){.content div{grid-template-columns:repeat(3,minmax(0,1fr))}}.content div{height:100%}@keyframes show{0%{overflow:hidden}99%{overflow:hidden}to{overflow:auto}}\n"], dependencies: [{ kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
|
|
2424
|
+
}
|
|
2425
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: GroupAccordionComponent, decorators: [{
|
|
2426
|
+
type: Component,
|
|
2427
|
+
args: [{ selector: 'lib-group-accordion', host: { '[class.collapsed]': 'collapsed' }, imports: [
|
|
2428
|
+
NgStyle,
|
|
2429
|
+
], template: "<div class=\"title\">\n <h6 (click)=\"onToggle()\"><i class=\"fas fa-chevron-down fa-sm\"></i>{{ this.label }}</h6>\n</div>\n\n<div #container class=\"content animate\"\n[ngStyle]=\"maxHeight >= 0 && {\n 'height.px': maxHeight,\n 'max-height.px': maxHeight\n} || null\">\n <div #maxHeighContainer>\n <ng-content></ng-content>\n </div>\n</div>", styles: [":host-context{margin-bottom:1rem;display:flex;flex-direction:column}:host-context.collapsed i{--tw-rotate: -90deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}:host-context.collapsed .content{max-height:0px!important;overflow:hidden!important}:host-context:not(.collapsed) .content{animation:show .15s}.title{-webkit-user-select:none;user-select:none}.title i{margin-right:.5rem;padding-top:.25rem;--tw-text-opacity: 1;color:rgb(100 116 139 / var(--tw-text-opacity, 1));transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.title h6{margin-bottom:0;display:inline;height:3rem;cursor:pointer;text-overflow:ellipsis;white-space:nowrap;padding-left:.25rem;padding-right:.5rem;font-size:1.125rem;text-transform:uppercase;line-height:3rem}.content{box-sizing:content-box;flex-grow:1;overflow-y:hidden;padding-left:.25rem;padding-right:.25rem}.content.animate{transition-property:max-height;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.content div{padding-bottom:.25rem}@media (min-width: 1024px){.content div{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:.75rem}}@media (min-width: 1280px){.content div{grid-template-columns:repeat(3,minmax(0,1fr))}}.content div{height:100%}@keyframes show{0%{overflow:hidden}99%{overflow:hidden}to{overflow:auto}}\n"] }]
|
|
2430
|
+
}], propDecorators: { containerElementRef: [{
|
|
2431
|
+
type: ViewChild,
|
|
2432
|
+
args: ['container']
|
|
2433
|
+
}], label: [{
|
|
2434
|
+
type: Input,
|
|
2435
|
+
args: [{ required: true }]
|
|
2436
|
+
}] } });
|
|
2437
|
+
|
|
2438
|
+
class ScrollSpyDirective {
|
|
2439
|
+
//#region ViewChilds, Inputs, Outputs
|
|
2440
|
+
spiedTags = [];
|
|
2441
|
+
activeSectionChange = new EventEmitter();
|
|
2442
|
+
//#endregion
|
|
2443
|
+
//#region Variables
|
|
2444
|
+
_el = inject(ElementRef);
|
|
2445
|
+
activeSection = null;
|
|
2446
|
+
sections = new Array();
|
|
2447
|
+
//#endregion
|
|
2448
|
+
//#region Properties
|
|
2449
|
+
//#endregion
|
|
2450
|
+
//#region Constructor and Angular life cycle methods
|
|
2451
|
+
ngAfterViewInit() {
|
|
2452
|
+
this.updateSections(Array.from(this._el.nativeElement.children));
|
|
2453
|
+
}
|
|
2454
|
+
//#endregion
|
|
2455
|
+
//#region Event handlers
|
|
2456
|
+
onScroll(event) {
|
|
2457
|
+
const scrollTop = event.target.scrollTop;
|
|
2458
|
+
const scrollHeight = event.target.scrollHeight;
|
|
2459
|
+
const maxScroll = Math.round(event.target.scrollHeight - event.target.getBoundingClientRect().height);
|
|
2460
|
+
const currentScroll = Math.round(scrollTop * scrollHeight / maxScroll);
|
|
2461
|
+
if (currentScroll >= scrollHeight) {
|
|
2462
|
+
this.select(this.sections.length - 1);
|
|
2463
|
+
return;
|
|
2464
|
+
}
|
|
2465
|
+
const elements = this.sections.filter(el => (el.offsetTop) <= currentScroll);
|
|
2466
|
+
this.select(elements.length > 0 ? elements.length - 1 : 0);
|
|
2467
|
+
}
|
|
2468
|
+
//#endregion
|
|
2469
|
+
//#region Public methods
|
|
2470
|
+
scrollTo(section) {
|
|
2471
|
+
this._el.nativeElement.scrollTop = this.sections[section].offsetTop;
|
|
2472
|
+
}
|
|
2473
|
+
select(section) {
|
|
2474
|
+
if (section !== this.activeSection) {
|
|
2475
|
+
this.activeSection = section;
|
|
2476
|
+
this.activeSectionChange.emit(section);
|
|
2477
|
+
}
|
|
2478
|
+
}
|
|
2479
|
+
//#endregion
|
|
2480
|
+
//#region Private methods
|
|
2481
|
+
updateSections(children) {
|
|
2482
|
+
children.forEach(el => {
|
|
2483
|
+
if (this.spiedTags.some(spiedTag => spiedTag.toUpperCase() === el.tagName.toUpperCase())) {
|
|
2484
|
+
this.sections.push(el);
|
|
2485
|
+
}
|
|
2486
|
+
else {
|
|
2487
|
+
this.updateSections(Array.from(el.children));
|
|
2488
|
+
}
|
|
2489
|
+
});
|
|
2490
|
+
}
|
|
2491
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: ScrollSpyDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
2492
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.1.6", type: ScrollSpyDirective, isStandalone: true, selector: "[libScrollSpy]", inputs: { spiedTags: "spiedTags" }, outputs: { activeSectionChange: "activeSectionChange" }, host: { listeners: { "scroll": "onScroll($event)" } }, ngImport: i0 });
|
|
2493
|
+
}
|
|
2494
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: ScrollSpyDirective, decorators: [{
|
|
2495
|
+
type: Directive,
|
|
2496
|
+
args: [{
|
|
2497
|
+
selector: '[libScrollSpy]'
|
|
2498
|
+
}]
|
|
2499
|
+
}], propDecorators: { spiedTags: [{
|
|
2500
|
+
type: Input
|
|
2501
|
+
}], activeSectionChange: [{
|
|
2502
|
+
type: Output
|
|
2503
|
+
}], onScroll: [{
|
|
2504
|
+
type: HostListener,
|
|
2505
|
+
args: ['scroll', ['$event']]
|
|
2506
|
+
}] } });
|
|
2507
|
+
|
|
2508
|
+
class GroupContainerComponent {
|
|
2509
|
+
scrollSpy;
|
|
2510
|
+
sections;
|
|
2511
|
+
get titles() {
|
|
2512
|
+
return this.sections?.map(x => x.label) ?? [];
|
|
2513
|
+
}
|
|
2514
|
+
activeSection = 0;
|
|
2515
|
+
title;
|
|
2516
|
+
icon;
|
|
2517
|
+
activeSectionChanged(index) {
|
|
2518
|
+
this.activeSection = index;
|
|
2519
|
+
}
|
|
2520
|
+
scrollTo(section) {
|
|
2521
|
+
this.scrollSpy.scrollTo(section);
|
|
2522
|
+
}
|
|
2523
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: GroupContainerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2524
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.6", type: GroupContainerComponent, isStandalone: true, selector: "lib-group-container", inputs: { title: "title", icon: "icon" }, queries: [{ propertyName: "sections", predicate: GroupAccordionComponent, descendants: true }], viewQueries: [{ propertyName: "scrollSpy", first: true, predicate: ScrollSpyDirective, descendants: true }], ngImport: i0, template: "<div class=\"title\">\n <i *ngIf=\"!!title && !!icon\" class=\"fas fa-fw\" [ngClass]=\"icon\"></i>\n\n <h4 *ngIf=\"!!title\">{{ title | translate }}</h4>\n\n <svg *ngIf=\"!title\" [ngClass]=\"''\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle class=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\"></circle>\n <path class=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"></path>\n </svg>\n</div>\n\n<div class=\"content-container\">\n <ng-content></ng-content>\n</div>", styles: [":host-context{position:relative;display:flex;flex-grow:1;flex-direction:column;overflow:hidden;border-radius:.5rem;border-width:1px;border-color:#d1d5dbe6;background-color:#fffc}.title{display:flex;height:2rem;align-items:center;text-overflow:ellipsis;border-bottom-width:1px;border-color:#d1d5dbe6;padding:.25rem .5rem}.title i{padding-right:.5rem;--tw-text-opacity: 1;color:rgb(100 116 139 / var(--tw-text-opacity, 1))}.title h4{font-weight:600}.title svg{height:1.25rem;width:1.25rem}@keyframes spin{to{transform:rotate(360deg)}}.title svg{animation:spin 1s linear infinite}.content-container{position:relative;display:flex;flex-grow:1;overflow:hidden}.content-container ::ng-deep>*{flex-grow:1;overflow:hidden}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
|
|
2525
|
+
}
|
|
2526
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: GroupContainerComponent, decorators: [{
|
|
2527
|
+
type: Component,
|
|
2528
|
+
args: [{ selector: 'lib-group-container', imports: [
|
|
2529
|
+
NgClass,
|
|
2530
|
+
NgIf,
|
|
2531
|
+
TranslatePipe,
|
|
2532
|
+
], template: "<div class=\"title\">\n <i *ngIf=\"!!title && !!icon\" class=\"fas fa-fw\" [ngClass]=\"icon\"></i>\n\n <h4 *ngIf=\"!!title\">{{ title | translate }}</h4>\n\n <svg *ngIf=\"!title\" [ngClass]=\"''\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle class=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\"></circle>\n <path class=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"></path>\n </svg>\n</div>\n\n<div class=\"content-container\">\n <ng-content></ng-content>\n</div>", styles: [":host-context{position:relative;display:flex;flex-grow:1;flex-direction:column;overflow:hidden;border-radius:.5rem;border-width:1px;border-color:#d1d5dbe6;background-color:#fffc}.title{display:flex;height:2rem;align-items:center;text-overflow:ellipsis;border-bottom-width:1px;border-color:#d1d5dbe6;padding:.25rem .5rem}.title i{padding-right:.5rem;--tw-text-opacity: 1;color:rgb(100 116 139 / var(--tw-text-opacity, 1))}.title h4{font-weight:600}.title svg{height:1.25rem;width:1.25rem}@keyframes spin{to{transform:rotate(360deg)}}.title svg{animation:spin 1s linear infinite}.content-container{position:relative;display:flex;flex-grow:1;overflow:hidden}.content-container ::ng-deep>*{flex-grow:1;overflow:hidden}\n"] }]
|
|
2533
|
+
}], propDecorators: { scrollSpy: [{
|
|
2534
|
+
type: ViewChild,
|
|
2535
|
+
args: [ScrollSpyDirective]
|
|
2536
|
+
}], sections: [{
|
|
2537
|
+
type: ContentChildren,
|
|
2538
|
+
args: [GroupAccordionComponent, { descendants: true }]
|
|
2539
|
+
}], title: [{
|
|
2540
|
+
type: Input
|
|
2541
|
+
}], icon: [{
|
|
2542
|
+
type: Input
|
|
2543
|
+
}] } });
|
|
2544
|
+
|
|
2545
|
+
class GroupScrollSpyComponent {
|
|
2546
|
+
scrollSpy;
|
|
2547
|
+
sections;
|
|
2548
|
+
get titles() {
|
|
2549
|
+
return this.sections?.map(x => x.label) ?? [];
|
|
2550
|
+
}
|
|
2551
|
+
activeSection = 0;
|
|
2552
|
+
activeSectionChanged(index) {
|
|
2553
|
+
this.activeSection = index;
|
|
2554
|
+
}
|
|
2555
|
+
scrollTo(section) {
|
|
2556
|
+
this.scrollSpy.scrollTo(section);
|
|
2557
|
+
}
|
|
2558
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: GroupScrollSpyComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2559
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.6", type: GroupScrollSpyComponent, isStandalone: true, selector: "lib-group-scroll-spy", queries: [{ propertyName: "sections", predicate: GroupAccordionComponent, descendants: true }], viewQueries: [{ propertyName: "scrollSpy", first: true, predicate: ScrollSpyDirective, descendants: true }], ngImport: i0, template: "<div class=\"scroll-spy\">\n <a *ngFor=\"let title of titles; let i = index\"\n class=\"item\" [class.active]=\"i === activeSection\"\n (click)=\"scrollTo(i)\"\n >{{ title }}</a>\n</div>\n\n<div class=\"content\" libScrollSpy\n[class.no-scroll-spy]=\"titles.length === 0\"\n[spiedTags]=\"['lib-group-accordion']\"\n(activeSectionChange)=\"activeSectionChanged($event)\"\n>\n <ng-content></ng-content>\n</div>", styles: [":host-context{position:relative;display:flex;height:100%;max-height:100%;min-height:100%;flex-grow:1;overflow:hidden}.content{display:flex;flex-grow:1;flex-direction:column;overflow:auto;scroll-behavior:smooth;padding:.75rem .75rem .25rem}@media (min-width: 768px){.content{padding-right:10.5rem}.content.no-scroll-spy{padding-right:.75rem}}.scroll-spy{position:absolute;top:.75rem;right:.75rem;display:none;width:9rem;-webkit-user-select:none;user-select:none;flex-direction:column}@media (min-width: 768px){.scroll-spy{display:flex}}.scroll-spy a{cursor:pointer;border-left-width:2px;--tw-border-opacity: 1;border-left-color:rgb(209 213 219 / var(--tw-border-opacity, 1));padding:.5rem 1rem;font-size:.875rem;line-height:1.25rem;--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity, 1))}.scroll-spy a.active{--tw-border-opacity: 1;border-left-color:rgb(0 107 182 / var(--tw-border-opacity, 1));--tw-text-opacity: 1;color:rgb(0 107 182 / var(--tw-text-opacity, 1))}.scroll-spy a:active{background-color:#006bb61a}\n"], dependencies: [{ kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: ScrollSpyDirective, selector: "[libScrollSpy]", inputs: ["spiedTags"], outputs: ["activeSectionChange"] }] });
|
|
2560
|
+
}
|
|
2561
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: GroupScrollSpyComponent, decorators: [{
|
|
2562
|
+
type: Component,
|
|
2563
|
+
args: [{ selector: 'lib-group-scroll-spy', imports: [
|
|
2564
|
+
NgFor,
|
|
2565
|
+
ScrollSpyDirective,
|
|
2566
|
+
], template: "<div class=\"scroll-spy\">\n <a *ngFor=\"let title of titles; let i = index\"\n class=\"item\" [class.active]=\"i === activeSection\"\n (click)=\"scrollTo(i)\"\n >{{ title }}</a>\n</div>\n\n<div class=\"content\" libScrollSpy\n[class.no-scroll-spy]=\"titles.length === 0\"\n[spiedTags]=\"['lib-group-accordion']\"\n(activeSectionChange)=\"activeSectionChanged($event)\"\n>\n <ng-content></ng-content>\n</div>", styles: [":host-context{position:relative;display:flex;height:100%;max-height:100%;min-height:100%;flex-grow:1;overflow:hidden}.content{display:flex;flex-grow:1;flex-direction:column;overflow:auto;scroll-behavior:smooth;padding:.75rem .75rem .25rem}@media (min-width: 768px){.content{padding-right:10.5rem}.content.no-scroll-spy{padding-right:.75rem}}.scroll-spy{position:absolute;top:.75rem;right:.75rem;display:none;width:9rem;-webkit-user-select:none;user-select:none;flex-direction:column}@media (min-width: 768px){.scroll-spy{display:flex}}.scroll-spy a{cursor:pointer;border-left-width:2px;--tw-border-opacity: 1;border-left-color:rgb(209 213 219 / var(--tw-border-opacity, 1));padding:.5rem 1rem;font-size:.875rem;line-height:1.25rem;--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity, 1))}.scroll-spy a.active{--tw-border-opacity: 1;border-left-color:rgb(0 107 182 / var(--tw-border-opacity, 1));--tw-text-opacity: 1;color:rgb(0 107 182 / var(--tw-text-opacity, 1))}.scroll-spy a:active{background-color:#006bb61a}\n"] }]
|
|
2567
|
+
}], propDecorators: { scrollSpy: [{
|
|
2568
|
+
type: ViewChild,
|
|
2569
|
+
args: [ScrollSpyDirective]
|
|
2570
|
+
}], sections: [{
|
|
2571
|
+
type: ContentChildren,
|
|
2572
|
+
args: [GroupAccordionComponent, { descendants: true }]
|
|
2573
|
+
}] } });
|
|
2574
|
+
|
|
2575
|
+
class ModalComponent extends BaseComponent {
|
|
2576
|
+
//#region ViewChilds, Inputs, Outputs
|
|
2577
|
+
closeButtonText = 'Close';
|
|
2578
|
+
dialog = true;
|
|
2579
|
+
modalProcessing = false;
|
|
2580
|
+
position = 'center';
|
|
2581
|
+
size = 'auto';
|
|
2582
|
+
title;
|
|
2583
|
+
closed = new EventEmitter();
|
|
2584
|
+
//#endregion
|
|
2585
|
+
//#region Variables
|
|
2586
|
+
_show = false;
|
|
2587
|
+
clickedOutside = false;
|
|
2588
|
+
elementRef;
|
|
2589
|
+
//#endregion
|
|
2590
|
+
//#region Properties
|
|
2591
|
+
get isShown() {
|
|
2592
|
+
return this._show;
|
|
2593
|
+
}
|
|
2594
|
+
//#endregion
|
|
2595
|
+
//#region Constructor and Angular life cycle methods
|
|
2596
|
+
constructor() {
|
|
2597
|
+
super();
|
|
2598
|
+
this.elementRef = inject(ElementRef);
|
|
2599
|
+
}
|
|
2600
|
+
//#endregion
|
|
2601
|
+
//#region Event handlers
|
|
2602
|
+
onCloseClick() {
|
|
2603
|
+
if (!this.modalProcessing && this.isShown) {
|
|
2604
|
+
this.closeModal();
|
|
2605
|
+
}
|
|
2606
|
+
}
|
|
2607
|
+
//#endregion
|
|
2608
|
+
//#region Public methods
|
|
2609
|
+
closeModal() {
|
|
2610
|
+
if (this.isShown) {
|
|
2611
|
+
this.toggleModal();
|
|
2612
|
+
}
|
|
2613
|
+
}
|
|
2614
|
+
toggleModal() {
|
|
2615
|
+
const wasShown = this._show;
|
|
2616
|
+
const body = document.querySelector('body');
|
|
2617
|
+
body?.classList.toggle('modal-active');
|
|
2618
|
+
this._show = body?.classList.contains('modal-active') ?? false;
|
|
2619
|
+
if (this.isShown) {
|
|
2620
|
+
this.clickedOutside = false;
|
|
2621
|
+
const autofocus = this.elementRef.nativeElement.querySelector('[autofocus]');
|
|
2622
|
+
if (autofocus && !!autofocus.focus) {
|
|
2623
|
+
autofocus.focus();
|
|
2624
|
+
}
|
|
2625
|
+
}
|
|
2626
|
+
else if (wasShown) {
|
|
2627
|
+
this.closed.emit();
|
|
2628
|
+
}
|
|
2629
|
+
}
|
|
2630
|
+
//#endregion
|
|
2631
|
+
//#region Private methods
|
|
2632
|
+
//#endregion
|
|
2633
|
+
//#region Host listeners
|
|
2634
|
+
bodyMouseDown(event) {
|
|
2635
|
+
if (this.dialog && this.isShown) {
|
|
2636
|
+
const target = event.target;
|
|
2637
|
+
this.clickedOutside = (!this.modalProcessing && event.button === 0 && target.closest('lib-modal') && !target.closest('.modal-content')) ?? false;
|
|
2638
|
+
}
|
|
2639
|
+
}
|
|
2640
|
+
bodyMouseUp(event) {
|
|
2641
|
+
if (this.dialog && this.isShown) {
|
|
2642
|
+
if (this.clickedOutside && !this.modalProcessing) {
|
|
2643
|
+
this.toggleModal();
|
|
2644
|
+
}
|
|
2645
|
+
}
|
|
2646
|
+
}
|
|
2647
|
+
documentKeyDown(event) {
|
|
2648
|
+
event = event || window.event;
|
|
2649
|
+
let isEscape = false;
|
|
2650
|
+
if ('key' in event) {
|
|
2651
|
+
isEscape = (event.key === 'Escape' || event.key === 'Esc');
|
|
2652
|
+
}
|
|
2653
|
+
else {
|
|
2654
|
+
isEscape = (event.keyCode === 27);
|
|
2655
|
+
}
|
|
2656
|
+
if (!this.modalProcessing && this.isShown && isEscape && document.body.classList.contains('modal-active')) {
|
|
2657
|
+
this.toggleModal();
|
|
2658
|
+
}
|
|
2659
|
+
}
|
|
2660
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: ModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2661
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.6", type: ModalComponent, isStandalone: true, selector: "lib-modal", inputs: { closeButtonText: "closeButtonText", dialog: "dialog", modalProcessing: "modalProcessing", position: "position", size: "size", title: "title" }, outputs: { closed: "closed" }, host: { attributes: { "title": "" }, listeners: { "body:mousedown": "bodyMouseDown($event)", "body:mouseup": "bodyMouseUp($event)", "document:keydown.escape": "documentKeyDown($event)" }, properties: { "class.show": "isShown" } }, usesInheritance: true, ngImport: i0, template: "<div class=\"modal-overlay\"></div>\n\n<div class=\"modal-container size-{{ size }} {{ position }}\">\n <form class=\"modal-content\">\n <div class=\"modal-header\" *ngIf=\"title\">\n <p class=\"text-2xl font-bold\">{{ title }}</p>\n\n <button type=\"button\" class=\"modal-close\" (click)=\"toggleModal()\">\n <svg class=\"fill-current text-black\" xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" viewBox=\"0 0 18 18\">\n <path d=\"M14.53 4.53l-1.06-1.06L9 7.94 4.53 3.47 3.47 4.53 7.94 9l-4.47 4.47 1.06 1.06L9 10.06l4.47 4.47 1.06-1.06L10.06 9z\"></path>\n </svg>\n </button>\n </div>\n\n <div class=\"modal-body\">\n <ng-content select=\"[body]\"></ng-content>\n </div>\n\n <div class=\"modal-footer\">\n <button type=\"button\" class=\"btn gray-300\" [disabled]=\"modalProcessing\" (click)=\"onCloseClick()\">{{ closeButtonText }}</button>\n\n <ng-content select=\"[footer]\"></ng-content>\n </div>\n </form>\n</div>", styles: ["body.modal-active{overflow-x:hidden;overflow-y:visible!important}:host{position:fixed;top:0;left:0;z-index:50;height:100%;width:100%}:host:not(.show){pointer-events:none;opacity:0;transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s;transition-delay:.15s}:host:not(.show) .modal-overlay{opacity:0;transition-delay:.15s}:host:not(.show) .modal-container.top,:host:not(.show) .modal-container.center{--tw-translate-y: -3.5rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}:host:not(.show) .modal-container.bottom{--tw-translate-y: 3.5rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}:host:not(.show) .modal-container.left{--tw-translate-x: -3.5rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}:host:not(.show) .modal-container.right{--tw-translate-x: 3.5rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}:host:not(.show) .modal-container .modal-content{animation:hidden 0s ease-in-out forwards}.modal-overlay{position:fixed;inset:0;height:100vh;width:100vw;--tw-bg-opacity: 1;background-color:rgb(0 0 0 / var(--tw-bg-opacity, 1));opacity:.5;transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.modal-container{margin:auto;display:grid;height:100%;max-height:100vh;min-height:100%;grid-template-columns:repeat(1,minmax(0,1fr));padding:1.75rem;transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.3s}.modal-container.top{align-items:flex-start}.modal-container.bottom{align-items:flex-end}.modal-container.left{margin-right:0;align-items:center}.modal-container.right{margin-left:0;align-items:center}.modal-container.center{align-items:center}.modal-container.size-sm{max-width:24rem}.modal-container.size-md{max-width:28rem}.modal-container.size-lg{max-width:32rem}.modal-container.size-xl{max-width:36rem}.modal-container.size-2xl{max-width:42rem}.modal-container.size-3xl{max-width:48rem}.modal-container.size-4xl{max-width:56rem}.modal-container.size-5xl{max-width:64rem}.modal-container.size-6xl{max-width:72rem}.modal-container.size-7xl{max-width:80rem}.modal-container.size-full{max-width:100%}.modal-container.size-auto{width:100%}@media (min-width: 640px){.modal-container.size-auto{max-width:640px}}@media (min-width: 768px){.modal-container.size-auto{max-width:768px}}@media (min-width: 1024px){.modal-container.size-auto{max-width:1024px}}@media (min-width: 1280px){.modal-container.size-auto{max-width:1280px}}@media (min-width: 1536px){.modal-container.size-auto{max-width:1536px}}.modal-container .modal-content{position:relative;width:100%;border-radius:.375rem;border-width:1px;border-color:#0003;--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1));background-clip:padding-box;outline-width:0px;display:grid;max-height:100%;grid-template-rows:min-content 1fr min-content;overflow:hidden;--tw-shadow: 0 0 4px 0 rgba(0,0,0,.2), 0 3px 20px 0 rgba(0,0,0,.19);--tw-shadow-colored: 0 0 4px 0 var(--tw-shadow-color), 0 3px 20px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow);animation:shown .3s ease-in-out forwards}.modal-container .modal-content .modal-header{border-bottom-width:1px;--tw-border-opacity: 1;border-color:rgb(209 213 219 / var(--tw-border-opacity, 1));padding:1rem}.modal-container .modal-content .modal-header .modal-close{position:absolute;top:0;right:0;margin:.5rem;cursor:pointer;padding:.5rem;opacity:.6}.modal-container .modal-content .modal-body{overflow:hidden;padding:1rem}.modal-container .modal-content .modal-footer{display:grid;grid-auto-columns:min-content;grid-auto-flow:column;justify-content:flex-end;gap:.25rem;white-space:nowrap;border-top-width:1px;--tw-border-opacity: 1;border-color:rgb(209 213 219 / var(--tw-border-opacity, 1));padding:.75rem}.modal-container .modal-content .modal-footer>*,.modal-container .modal-content .modal-footer ::ng-deep div[footer]>*{display:grid;grid-auto-columns:min-content;grid-auto-flow:column;gap:.25rem}@keyframes hidden{0%{display:flex}to{display:none}}@keyframes shown{0%{opacity:0}to{opacity:1}}\n"], dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
|
|
2662
|
+
}
|
|
2663
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: ModalComponent, decorators: [{
|
|
2664
|
+
type: Component,
|
|
2665
|
+
args: [{ selector: 'lib-modal', host: {
|
|
2666
|
+
'title': '', // This is to ensure that the title input does not conflict with the native HTML title attribute.
|
|
2667
|
+
'[class.show]': 'isShown',
|
|
2668
|
+
}, imports: [
|
|
2669
|
+
NgIf,
|
|
2670
|
+
], template: "<div class=\"modal-overlay\"></div>\n\n<div class=\"modal-container size-{{ size }} {{ position }}\">\n <form class=\"modal-content\">\n <div class=\"modal-header\" *ngIf=\"title\">\n <p class=\"text-2xl font-bold\">{{ title }}</p>\n\n <button type=\"button\" class=\"modal-close\" (click)=\"toggleModal()\">\n <svg class=\"fill-current text-black\" xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" viewBox=\"0 0 18 18\">\n <path d=\"M14.53 4.53l-1.06-1.06L9 7.94 4.53 3.47 3.47 4.53 7.94 9l-4.47 4.47 1.06 1.06L9 10.06l4.47 4.47 1.06-1.06L10.06 9z\"></path>\n </svg>\n </button>\n </div>\n\n <div class=\"modal-body\">\n <ng-content select=\"[body]\"></ng-content>\n </div>\n\n <div class=\"modal-footer\">\n <button type=\"button\" class=\"btn gray-300\" [disabled]=\"modalProcessing\" (click)=\"onCloseClick()\">{{ closeButtonText }}</button>\n\n <ng-content select=\"[footer]\"></ng-content>\n </div>\n </form>\n</div>", styles: ["body.modal-active{overflow-x:hidden;overflow-y:visible!important}:host{position:fixed;top:0;left:0;z-index:50;height:100%;width:100%}:host:not(.show){pointer-events:none;opacity:0;transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s;transition-delay:.15s}:host:not(.show) .modal-overlay{opacity:0;transition-delay:.15s}:host:not(.show) .modal-container.top,:host:not(.show) .modal-container.center{--tw-translate-y: -3.5rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}:host:not(.show) .modal-container.bottom{--tw-translate-y: 3.5rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}:host:not(.show) .modal-container.left{--tw-translate-x: -3.5rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}:host:not(.show) .modal-container.right{--tw-translate-x: 3.5rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}:host:not(.show) .modal-container .modal-content{animation:hidden 0s ease-in-out forwards}.modal-overlay{position:fixed;inset:0;height:100vh;width:100vw;--tw-bg-opacity: 1;background-color:rgb(0 0 0 / var(--tw-bg-opacity, 1));opacity:.5;transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.modal-container{margin:auto;display:grid;height:100%;max-height:100vh;min-height:100%;grid-template-columns:repeat(1,minmax(0,1fr));padding:1.75rem;transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.3s}.modal-container.top{align-items:flex-start}.modal-container.bottom{align-items:flex-end}.modal-container.left{margin-right:0;align-items:center}.modal-container.right{margin-left:0;align-items:center}.modal-container.center{align-items:center}.modal-container.size-sm{max-width:24rem}.modal-container.size-md{max-width:28rem}.modal-container.size-lg{max-width:32rem}.modal-container.size-xl{max-width:36rem}.modal-container.size-2xl{max-width:42rem}.modal-container.size-3xl{max-width:48rem}.modal-container.size-4xl{max-width:56rem}.modal-container.size-5xl{max-width:64rem}.modal-container.size-6xl{max-width:72rem}.modal-container.size-7xl{max-width:80rem}.modal-container.size-full{max-width:100%}.modal-container.size-auto{width:100%}@media (min-width: 640px){.modal-container.size-auto{max-width:640px}}@media (min-width: 768px){.modal-container.size-auto{max-width:768px}}@media (min-width: 1024px){.modal-container.size-auto{max-width:1024px}}@media (min-width: 1280px){.modal-container.size-auto{max-width:1280px}}@media (min-width: 1536px){.modal-container.size-auto{max-width:1536px}}.modal-container .modal-content{position:relative;width:100%;border-radius:.375rem;border-width:1px;border-color:#0003;--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1));background-clip:padding-box;outline-width:0px;display:grid;max-height:100%;grid-template-rows:min-content 1fr min-content;overflow:hidden;--tw-shadow: 0 0 4px 0 rgba(0,0,0,.2), 0 3px 20px 0 rgba(0,0,0,.19);--tw-shadow-colored: 0 0 4px 0 var(--tw-shadow-color), 0 3px 20px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow);animation:shown .3s ease-in-out forwards}.modal-container .modal-content .modal-header{border-bottom-width:1px;--tw-border-opacity: 1;border-color:rgb(209 213 219 / var(--tw-border-opacity, 1));padding:1rem}.modal-container .modal-content .modal-header .modal-close{position:absolute;top:0;right:0;margin:.5rem;cursor:pointer;padding:.5rem;opacity:.6}.modal-container .modal-content .modal-body{overflow:hidden;padding:1rem}.modal-container .modal-content .modal-footer{display:grid;grid-auto-columns:min-content;grid-auto-flow:column;justify-content:flex-end;gap:.25rem;white-space:nowrap;border-top-width:1px;--tw-border-opacity: 1;border-color:rgb(209 213 219 / var(--tw-border-opacity, 1));padding:.75rem}.modal-container .modal-content .modal-footer>*,.modal-container .modal-content .modal-footer ::ng-deep div[footer]>*{display:grid;grid-auto-columns:min-content;grid-auto-flow:column;gap:.25rem}@keyframes hidden{0%{display:flex}to{display:none}}@keyframes shown{0%{opacity:0}to{opacity:1}}\n"] }]
|
|
2671
|
+
}], ctorParameters: () => [], propDecorators: { closeButtonText: [{
|
|
2672
|
+
type: Input
|
|
2673
|
+
}], dialog: [{
|
|
2674
|
+
type: Input
|
|
2675
|
+
}], modalProcessing: [{
|
|
2676
|
+
type: Input
|
|
2677
|
+
}], position: [{
|
|
2678
|
+
type: Input
|
|
2679
|
+
}], size: [{
|
|
2680
|
+
type: Input
|
|
2681
|
+
}], title: [{
|
|
2682
|
+
type: Input
|
|
2683
|
+
}], closed: [{
|
|
2684
|
+
type: Output
|
|
2685
|
+
}], bodyMouseDown: [{
|
|
2686
|
+
type: HostListener,
|
|
2687
|
+
args: ['body:mousedown', ['$event']]
|
|
2688
|
+
}], bodyMouseUp: [{
|
|
2689
|
+
type: HostListener,
|
|
2690
|
+
args: ['body:mouseup', ['$event']]
|
|
2691
|
+
}], documentKeyDown: [{
|
|
2692
|
+
type: HostListener,
|
|
2693
|
+
args: ['document:keydown.escape', ['$event']]
|
|
2694
|
+
}] } });
|
|
2695
|
+
|
|
2696
|
+
class MultiEditorComponent extends ModalComponent {
|
|
2697
|
+
//#region ViewChilds, Inputs, Outputs
|
|
2698
|
+
modal;
|
|
2699
|
+
addButtonLabel = 'Add row';
|
|
2700
|
+
formGroup;
|
|
2701
|
+
removeButtonLabel = 'Remove row';
|
|
2702
|
+
showAddButton = true;
|
|
2703
|
+
showDeleteButton = true;
|
|
2704
|
+
//#endregion
|
|
2705
|
+
//#region Variables
|
|
2706
|
+
gridLoading = false;
|
|
2707
|
+
dataGridDataset = inject(DataGridDataset);
|
|
2708
|
+
formService = inject(FormService);
|
|
2709
|
+
multiEditorDataset = inject(MultiEditorDataset);
|
|
2710
|
+
selectedKey;
|
|
2711
|
+
selectedValue;
|
|
2712
|
+
//#endregion
|
|
2713
|
+
//#region Properties
|
|
2714
|
+
get formLoading() {
|
|
2715
|
+
return this.formService.loading;
|
|
2716
|
+
}
|
|
2717
|
+
get hasSelectedKey() {
|
|
2718
|
+
return !!this.selectedKey;
|
|
2719
|
+
}
|
|
2720
|
+
//#endregion
|
|
2721
|
+
//#region Constructor and Angular life cycle methods
|
|
2722
|
+
constructor() {
|
|
2723
|
+
super();
|
|
2724
|
+
}
|
|
2725
|
+
ngOnInit() {
|
|
2726
|
+
this.dataGridDataset.loadFinished
|
|
2727
|
+
.pipe(takeUntil(this.destroy$))
|
|
2728
|
+
.subscribe(() => {
|
|
2729
|
+
this.multiEditorDataset.clearChangedValues();
|
|
2730
|
+
this.gridLoading = false;
|
|
2731
|
+
this.selectedKey = undefined;
|
|
2732
|
+
this.selectedValue = undefined;
|
|
2733
|
+
});
|
|
2734
|
+
this.dataGridDataset.selectedRowsChanged
|
|
2735
|
+
.pipe(takeUntil(this.destroy$))
|
|
2736
|
+
.subscribe(() => {
|
|
2737
|
+
if (this.gridLoading || !this.dataGridDataset.hasLoadedRows || !this.dataGridDataset.hasSelectedRows) {
|
|
2738
|
+
return;
|
|
2739
|
+
}
|
|
2740
|
+
if (this.formGroup.disabled) {
|
|
2741
|
+
this.formGroup.enable();
|
|
2742
|
+
}
|
|
2743
|
+
const selectedRowKey = this.dataGridDataset.selectedRowKeys[0];
|
|
2744
|
+
if (!!this.selectedKey && this.formGroup.enabled && !this.formGroup.valid && this.selectedKey !== selectedRowKey) {
|
|
2745
|
+
// If the form is invalid, need to stay in the same selected row.
|
|
2746
|
+
this.dataGridDataset.selectRow(this.selectedKey);
|
|
2747
|
+
this.formGroup.markAllAsTouched();
|
|
2748
|
+
}
|
|
2749
|
+
else {
|
|
2750
|
+
this.selectedKey = selectedRowKey;
|
|
2751
|
+
this.selectedValue = this.dataGridDataset.getRowData(selectedRowKey);
|
|
2752
|
+
this.formService.model = this.selectedValue;
|
|
2753
|
+
this.formGroup.reset();
|
|
2754
|
+
this.formGroup.patchValue(this.selectedValue);
|
|
2755
|
+
}
|
|
2756
|
+
});
|
|
2757
|
+
this.formGroup.valueChanges
|
|
2758
|
+
.pipe(takeUntil(this.destroy$))
|
|
2759
|
+
.subscribe((_) => {
|
|
2760
|
+
if (this.selectedKey && this.formGroup.dirty) {
|
|
2761
|
+
this.multiEditorDataset.updateValues(this.selectedKey, this.formGroup.getRawValue());
|
|
2762
|
+
}
|
|
2763
|
+
});
|
|
2764
|
+
// Start with an empty form and, since there is no selected row, disable the form.
|
|
2765
|
+
this.formGroup.disable({ emitEvent: false });
|
|
2766
|
+
}
|
|
2767
|
+
//#endregion
|
|
2768
|
+
//#region Event handlers
|
|
2769
|
+
onDeleteClick() {
|
|
2770
|
+
if (!this.selectedKey) {
|
|
2771
|
+
return;
|
|
2772
|
+
}
|
|
2773
|
+
this.multiEditorDataset.removeValue(this.selectedKey);
|
|
2774
|
+
this.selectedKey = undefined;
|
|
2775
|
+
this.formGroup.reset({ emitEvent: false });
|
|
2776
|
+
this.clearAllFormArrays(this.formGroup);
|
|
2777
|
+
this.formGroup.disable({ emitEvent: false });
|
|
2778
|
+
}
|
|
2779
|
+
onNewClick() {
|
|
2780
|
+
const fakeNewID = (Math.floor(Math.random() * (999999 - 100000)) + 100000) * -1;
|
|
2781
|
+
const newModel = this.multiEditorDataset.newData(fakeNewID);
|
|
2782
|
+
if (!!newModel) {
|
|
2783
|
+
this.multiEditorDataset.storeFakeIDGenerated(fakeNewID);
|
|
2784
|
+
this.dataGridDataset.addNewRow(newModel);
|
|
2785
|
+
const newKey = this.dataGridDataset.loadedKeys[this.dataGridDataset.loadedKeys.length - 1];
|
|
2786
|
+
this.dataGridDataset.selectRow(newKey);
|
|
2787
|
+
}
|
|
2788
|
+
}
|
|
2789
|
+
onSaveClick() {
|
|
2790
|
+
if (this.selectedKey) {
|
|
2791
|
+
this.formGroup.markAllAsTouched();
|
|
2792
|
+
}
|
|
2793
|
+
if (!this.selectedKey || this.formGroup.valid) {
|
|
2794
|
+
this.modalProcessing = true;
|
|
2795
|
+
this.formGroup.disable();
|
|
2796
|
+
this.multiEditorDataset.saveChanges()
|
|
2797
|
+
.pipe(take(1))
|
|
2798
|
+
.subscribe({
|
|
2799
|
+
next: (_) => {
|
|
2800
|
+
this.modalProcessing = false;
|
|
2801
|
+
this.toggleModal();
|
|
2802
|
+
},
|
|
2803
|
+
error: (e) => {
|
|
2804
|
+
this.modalProcessing = false;
|
|
2805
|
+
this.formGroup.enable();
|
|
2806
|
+
if (e.status === 400 && e.error.errors) {
|
|
2807
|
+
this.dataGridDataset.selectRowID(e.error.entityKey);
|
|
2808
|
+
this.formService.setValidationErrorsFromHttpResponse(e);
|
|
2809
|
+
}
|
|
2810
|
+
}
|
|
2811
|
+
});
|
|
2812
|
+
}
|
|
2813
|
+
}
|
|
2814
|
+
//#endregion
|
|
2815
|
+
//#region Public methods
|
|
2816
|
+
closeModal() {
|
|
2817
|
+
this.modal.closeModal();
|
|
2818
|
+
}
|
|
2819
|
+
toggleModal() {
|
|
2820
|
+
this.modal.toggleModal();
|
|
2821
|
+
if (this.modal.isShown) {
|
|
2822
|
+
this.gridLoading = true;
|
|
2823
|
+
this.dataGridDataset.refresh();
|
|
2824
|
+
this.selectedKey = undefined;
|
|
2825
|
+
this.formGroup.reset({ emitEvent: false });
|
|
2826
|
+
this.clearAllFormArrays(this.formGroup);
|
|
2827
|
+
this.formGroup.disable({ emitEvent: false });
|
|
2828
|
+
}
|
|
2829
|
+
}
|
|
2830
|
+
//#endregion
|
|
2831
|
+
//#region Private methods
|
|
2832
|
+
clearAllFormArrays(form) {
|
|
2833
|
+
Object.keys(form.controls).forEach((key) => {
|
|
2834
|
+
const control = form.get(key);
|
|
2835
|
+
if (control instanceof FormArray) {
|
|
2836
|
+
control.clear({ emitEvent: false });
|
|
2837
|
+
}
|
|
2838
|
+
// Check for nested FormArrays.
|
|
2839
|
+
if (control instanceof FormGroup) {
|
|
2840
|
+
this.clearAllFormArrays(control);
|
|
2841
|
+
}
|
|
2842
|
+
});
|
|
2843
|
+
}
|
|
2844
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: MultiEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2845
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.6", type: MultiEditorComponent, isStandalone: true, selector: "lib-multi-editor", inputs: { addButtonLabel: "addButtonLabel", formGroup: "formGroup", removeButtonLabel: "removeButtonLabel", showAddButton: "showAddButton", showDeleteButton: "showDeleteButton" }, viewQueries: [{ propertyName: "modal", first: true, predicate: ModalComponent, descendants: true }], usesInheritance: true, ngImport: i0, template: "<lib-modal\n[closeButtonText]=\"closeButtonText | translate\"\n[dialog]=\"dialog\"\n[modalProcessing]=\"modalProcessing\"\n[position]=\"position\"\n[size]=\"size\"\n[title]=\"title\">\n <div body class=\"body-content\">\n <div class=\"data-grid\">\n <lib-data-grid [disabled]=\"modalProcessing\" [lazyLoadRows]=\"true\"></lib-data-grid>\n </div>\n\n <div class=\"data\">\n <div class=\"buttons\">\n <a *ngIf=\"showAddButton\"\n class=\"btn gray-500\"\n [class.disabled]=\"modalProcessing || gridLoading || formLoading || formGroup.invalid\"\n (click)=\"onNewClick()\">\n {{ addButtonLabel }}\n </a>\n\n <a *ngIf=\"showDeleteButton && hasSelectedKey\"\n class=\"btn red-500\"\n [class.disabled]=\"modalProcessing || gridLoading || formLoading\"\n (click)=\"onDeleteClick()\">\n {{ removeButtonLabel }}\n </a>\n </div>\n\n <lib-form-group>\n <ng-content></ng-content>\n </lib-form-group>\n </div>\n </div>\n\n <div footer>\n <button\n class=\"btn blue-500\"\n type=\"button\"\n [class.disabled]=\"gridLoading || formLoading\"\n [class.loading]=\"modalProcessing\"\n (click)=\"onSaveClick()\">\n {{ 'Button-Modal-MultiEditor-Confirm' | translate }}\n </button>\n </div>\n</lib-modal>", styles: [".body-content{display:grid;grid-auto-columns:minmax(0,1fr);grid-auto-flow:column;gap:1rem;overflow:clip;overflow-clip-margin:4px}.data-grid{display:grid;-webkit-user-select:none;user-select:none;overflow:hidden}.data{display:grid;-webkit-user-select:none;user-select:none;overflow:clip;overflow-clip-margin:4px;min-height:24rem;grid-template-rows:min-content minmax(0,1fr);gap:.5rem}.data .buttons{display:grid;grid-auto-columns:auto;grid-auto-flow:column;gap:.5rem;border-bottom-color:#d1d5dbe6}\n"], dependencies: [{ kind: "component", type: DataGridComponent, selector: "lib-data-grid", inputs: ["disabled", "lazyLoadRows", "showButtons"] }, { kind: "component", type: ModalComponent, selector: "lib-modal", inputs: ["closeButtonText", "dialog", "modalProcessing", "position", "size", "title"], outputs: ["closed"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: FormGroupComponent, selector: "lib-form-group", inputs: ["shouldExpand", "label"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
|
|
2846
|
+
}
|
|
2847
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: MultiEditorComponent, decorators: [{
|
|
2848
|
+
type: Component,
|
|
2849
|
+
args: [{ selector: 'lib-multi-editor', imports: [
|
|
2850
|
+
DataGridComponent,
|
|
2851
|
+
ModalComponent,
|
|
2852
|
+
NgIf,
|
|
2853
|
+
FormGroupComponent,
|
|
2854
|
+
TranslatePipe,
|
|
2855
|
+
], template: "<lib-modal\n[closeButtonText]=\"closeButtonText | translate\"\n[dialog]=\"dialog\"\n[modalProcessing]=\"modalProcessing\"\n[position]=\"position\"\n[size]=\"size\"\n[title]=\"title\">\n <div body class=\"body-content\">\n <div class=\"data-grid\">\n <lib-data-grid [disabled]=\"modalProcessing\" [lazyLoadRows]=\"true\"></lib-data-grid>\n </div>\n\n <div class=\"data\">\n <div class=\"buttons\">\n <a *ngIf=\"showAddButton\"\n class=\"btn gray-500\"\n [class.disabled]=\"modalProcessing || gridLoading || formLoading || formGroup.invalid\"\n (click)=\"onNewClick()\">\n {{ addButtonLabel }}\n </a>\n\n <a *ngIf=\"showDeleteButton && hasSelectedKey\"\n class=\"btn red-500\"\n [class.disabled]=\"modalProcessing || gridLoading || formLoading\"\n (click)=\"onDeleteClick()\">\n {{ removeButtonLabel }}\n </a>\n </div>\n\n <lib-form-group>\n <ng-content></ng-content>\n </lib-form-group>\n </div>\n </div>\n\n <div footer>\n <button\n class=\"btn blue-500\"\n type=\"button\"\n [class.disabled]=\"gridLoading || formLoading\"\n [class.loading]=\"modalProcessing\"\n (click)=\"onSaveClick()\">\n {{ 'Button-Modal-MultiEditor-Confirm' | translate }}\n </button>\n </div>\n</lib-modal>", styles: [".body-content{display:grid;grid-auto-columns:minmax(0,1fr);grid-auto-flow:column;gap:1rem;overflow:clip;overflow-clip-margin:4px}.data-grid{display:grid;-webkit-user-select:none;user-select:none;overflow:hidden}.data{display:grid;-webkit-user-select:none;user-select:none;overflow:clip;overflow-clip-margin:4px;min-height:24rem;grid-template-rows:min-content minmax(0,1fr);gap:.5rem}.data .buttons{display:grid;grid-auto-columns:auto;grid-auto-flow:column;gap:.5rem;border-bottom-color:#d1d5dbe6}\n"] }]
|
|
2856
|
+
}], ctorParameters: () => [], propDecorators: { modal: [{
|
|
2857
|
+
type: ViewChild,
|
|
2858
|
+
args: [ModalComponent]
|
|
2859
|
+
}], addButtonLabel: [{
|
|
2860
|
+
type: Input
|
|
2861
|
+
}], formGroup: [{
|
|
2862
|
+
type: Input
|
|
2863
|
+
}], removeButtonLabel: [{
|
|
2864
|
+
type: Input
|
|
2865
|
+
}], showAddButton: [{
|
|
2866
|
+
type: Input
|
|
2867
|
+
}], showDeleteButton: [{
|
|
2868
|
+
type: Input
|
|
2869
|
+
}] } });
|
|
2870
|
+
|
|
2871
|
+
class MultiSelectResultGridComponent extends BaseComponent {
|
|
2872
|
+
//#region ViewChilds, Inputs, Outputs
|
|
2873
|
+
isDisabled = false;
|
|
2874
|
+
template;
|
|
2875
|
+
//#endregion
|
|
2876
|
+
//#region Variables
|
|
2877
|
+
dataGridDataset = inject(DataGridDataset);
|
|
2878
|
+
isLoading = true;
|
|
2879
|
+
resultDataset = inject(MultiSelectResultDataset);
|
|
2880
|
+
//#endregion
|
|
2881
|
+
//#region Properties
|
|
2882
|
+
//#endregion
|
|
2883
|
+
//#region Constructor and Angular life cycle methods
|
|
2884
|
+
constructor() {
|
|
2885
|
+
super();
|
|
2886
|
+
}
|
|
2887
|
+
ngOnInit() {
|
|
2888
|
+
this.resultDataset.loadStarted
|
|
2889
|
+
.pipe(takeUntil(this.destroy$))
|
|
2890
|
+
.subscribe(() => {
|
|
2891
|
+
this.isLoading = true;
|
|
2892
|
+
});
|
|
2893
|
+
this.resultDataset.loadFinished
|
|
2894
|
+
.pipe(takeUntil(this.destroy$))
|
|
2895
|
+
.subscribe(() => {
|
|
2896
|
+
this.isLoading = false;
|
|
2897
|
+
});
|
|
2898
|
+
}
|
|
2899
|
+
//#endregion
|
|
2900
|
+
//#region Event handlers
|
|
2901
|
+
onItemRemoved(rowIndex) {
|
|
2902
|
+
const id = this.resultDataset.displayedIDs[rowIndex];
|
|
2903
|
+
this.dataGridDataset.deselectRowID(id);
|
|
2904
|
+
}
|
|
2905
|
+
onScrolled(event) {
|
|
2906
|
+
const currentScroll = event.target.scrollTop + event.target.clientHeight;
|
|
2907
|
+
const scrollHeight = event.target.scrollHeight - event.target.clientHeight;
|
|
2908
|
+
if (currentScroll > scrollHeight && !this.isLoading && !this.resultDataset.loadedLastRow) {
|
|
2909
|
+
this.isLoading = true;
|
|
2910
|
+
this.resultDataset.loadRows();
|
|
2911
|
+
}
|
|
2912
|
+
}
|
|
2913
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: MultiSelectResultGridComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2914
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.6", type: MultiSelectResultGridComponent, isStandalone: true, selector: "lib-multi-select-result-grid", inputs: { isDisabled: "isDisabled", template: "template" }, host: { classAttribute: "flex-grow" }, usesInheritance: true, ngImport: i0, template: "<div\nclass=\"body\"\n(scroll)=\"onScrolled($event)\">\n <div\n class=\"row\"\n *ngFor=\"let row of resultDataset.displayedRows; let i = index\">\n <div class=\"cell\">\n <a\n class=\"remove\"\n [class.disabled]=\"isDisabled\"\n (click)=\"onItemRemoved(i)\">\n <i class=\"fas fa-times\"></i>\n </a>\n </div> \n\n <div class=\"cell\">\n <div>\n <ng-container *ngTemplateOutlet=\"template; context: { rowData: row }\">\n </ng-container>\n </div>\n </div>\n </div>\n\n <div\n class=\"loading\"\n *ngIf=\"isLoading\">\n <svg [ngClass]=\"''\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle class=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\"></circle>\n <path class=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"></path>\n </svg>\n\n <span>\n {{ resultDataset.configs.loadingDisplayText ?? '' | translate }} \n </span>\n </div>\n</div>", styles: [":host-context{display:grid;-webkit-user-select:none;user-select:none;grid-template-rows:auto 1fr;overflow:hidden}:host-context:not(.no-borders){border-radius:.5rem;border-width:1px;border-color:#d1d5dbe6;--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.body{overflow:overlay}.body .row{border-bottom-width:1px;border-color:#cbd5e180;margin-top:0;cursor:pointer;display:grid;grid-auto-flow:column;grid-template-columns:min-content minmax(0,1fr);gap:1rem;padding:.5rem 1rem}.body .row:nth-child(2n){background-color:#f8fafcb3}.body .row:hover{background-color:#bfdbfe33}.body .row.focused{z-index:1;border-color:#94a3b899}.body .row.selected{position:relative;z-index:10;--tw-border-opacity: 1;border-color:rgb(147 197 253 / var(--tw-border-opacity, 1));background-color:#bfdbfe4d}.body .row.selected:hover{background-color:#bfdbfe66}.body .row .cell{white-space:nowrap;display:flex;align-items:center}.body .row .cell a{padding-left:.5rem;padding-right:.5rem;font-size:1.125rem;line-height:1.75rem}.body .row .cell a:not(.disabled){cursor:pointer}.body .row .cell a.disabled{--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity, 1))}.body .row .cell .remove{--tw-text-opacity: 1;color:rgb(239 68 68 / var(--tw-text-opacity, 1))}.body .row .cell.disabled{pointer-events:none;cursor:default;opacity:.6}.body .row .cell>*{overflow:hidden;text-overflow:ellipsis}.body .row .cell div{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.body .loading{margin-bottom:.5rem;display:flex;height:2.5rem;align-items:center;border-bottom-width:1px;border-color:#cbd5e180;padding-left:1rem;padding-right:1rem}.body .loading svg{height:1.5rem;width:1.5rem}@keyframes spin{to{transform:rotate(360deg)}}.body .loading svg{animation:spin 1s linear infinite;transition-property:opacity;transition-duration:.2s;transition-timing-function:cubic-bezier(.4,0,.2,1)}.body .loading span{padding-left:.5rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
|
|
2915
|
+
}
|
|
2916
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: MultiSelectResultGridComponent, decorators: [{
|
|
2917
|
+
type: Component,
|
|
2918
|
+
args: [{ selector: 'lib-multi-select-result-grid', host: {
|
|
2919
|
+
'class': 'flex-grow'
|
|
2920
|
+
}, imports: [
|
|
2921
|
+
CommonModule,
|
|
2922
|
+
NgFor,
|
|
2923
|
+
NgIf,
|
|
2924
|
+
TranslatePipe,
|
|
2925
|
+
], template: "<div\nclass=\"body\"\n(scroll)=\"onScrolled($event)\">\n <div\n class=\"row\"\n *ngFor=\"let row of resultDataset.displayedRows; let i = index\">\n <div class=\"cell\">\n <a\n class=\"remove\"\n [class.disabled]=\"isDisabled\"\n (click)=\"onItemRemoved(i)\">\n <i class=\"fas fa-times\"></i>\n </a>\n </div> \n\n <div class=\"cell\">\n <div>\n <ng-container *ngTemplateOutlet=\"template; context: { rowData: row }\">\n </ng-container>\n </div>\n </div>\n </div>\n\n <div\n class=\"loading\"\n *ngIf=\"isLoading\">\n <svg [ngClass]=\"''\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle class=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\"></circle>\n <path class=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"></path>\n </svg>\n\n <span>\n {{ resultDataset.configs.loadingDisplayText ?? '' | translate }} \n </span>\n </div>\n</div>", styles: [":host-context{display:grid;-webkit-user-select:none;user-select:none;grid-template-rows:auto 1fr;overflow:hidden}:host-context:not(.no-borders){border-radius:.5rem;border-width:1px;border-color:#d1d5dbe6;--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.body{overflow:overlay}.body .row{border-bottom-width:1px;border-color:#cbd5e180;margin-top:0;cursor:pointer;display:grid;grid-auto-flow:column;grid-template-columns:min-content minmax(0,1fr);gap:1rem;padding:.5rem 1rem}.body .row:nth-child(2n){background-color:#f8fafcb3}.body .row:hover{background-color:#bfdbfe33}.body .row.focused{z-index:1;border-color:#94a3b899}.body .row.selected{position:relative;z-index:10;--tw-border-opacity: 1;border-color:rgb(147 197 253 / var(--tw-border-opacity, 1));background-color:#bfdbfe4d}.body .row.selected:hover{background-color:#bfdbfe66}.body .row .cell{white-space:nowrap;display:flex;align-items:center}.body .row .cell a{padding-left:.5rem;padding-right:.5rem;font-size:1.125rem;line-height:1.75rem}.body .row .cell a:not(.disabled){cursor:pointer}.body .row .cell a.disabled{--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity, 1))}.body .row .cell .remove{--tw-text-opacity: 1;color:rgb(239 68 68 / var(--tw-text-opacity, 1))}.body .row .cell.disabled{pointer-events:none;cursor:default;opacity:.6}.body .row .cell>*{overflow:hidden;text-overflow:ellipsis}.body .row .cell div{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.body .loading{margin-bottom:.5rem;display:flex;height:2.5rem;align-items:center;border-bottom-width:1px;border-color:#cbd5e180;padding-left:1rem;padding-right:1rem}.body .loading svg{height:1.5rem;width:1.5rem}@keyframes spin{to{transform:rotate(360deg)}}.body .loading svg{animation:spin 1s linear infinite;transition-property:opacity;transition-duration:.2s;transition-timing-function:cubic-bezier(.4,0,.2,1)}.body .loading span{padding-left:.5rem}\n"] }]
|
|
2926
|
+
}], ctorParameters: () => [], propDecorators: { isDisabled: [{
|
|
2927
|
+
type: Input
|
|
2928
|
+
}], template: [{
|
|
2929
|
+
type: Input
|
|
2930
|
+
}] } });
|
|
2931
|
+
|
|
2932
|
+
class MultiSelectComponent extends ModalComponent {
|
|
2933
|
+
//#region ViewChilds, Inputs, Outputs
|
|
2934
|
+
modal;
|
|
2935
|
+
itemTemplate;
|
|
2936
|
+
//#endregion
|
|
2937
|
+
//#region Variables
|
|
2938
|
+
isResultGridLoading = false;
|
|
2939
|
+
isSearchGridLoading = false;
|
|
2940
|
+
resultDataset = inject(MultiSelectResultDataset);
|
|
2941
|
+
searchCriteria = '';
|
|
2942
|
+
_searchColumn = '';
|
|
2943
|
+
dataGridDataset = inject(DataGridDataset);
|
|
2944
|
+
//#endregion
|
|
2945
|
+
//#region Properties
|
|
2946
|
+
get searchColumn() {
|
|
2947
|
+
if (this._searchColumn.length === 0) {
|
|
2948
|
+
let columnName = this.dataGridDataset.columns.filter((col) => col.field !== '')[0]?.field ?? 'Search';
|
|
2949
|
+
columnName = columnName.charAt(0).toUpperCase() + columnName.slice(1);
|
|
2950
|
+
this._searchColumn = columnName;
|
|
2951
|
+
}
|
|
2952
|
+
return this._searchColumn;
|
|
2953
|
+
}
|
|
2954
|
+
//#endregion
|
|
2955
|
+
//#region Constructor and Angular life cycle methods
|
|
2956
|
+
constructor() {
|
|
2957
|
+
super();
|
|
2958
|
+
this.dataGridDataset.configs.multiSelect = true;
|
|
2959
|
+
this.closeButtonText = 'Button-Modal-Cancel';
|
|
2960
|
+
}
|
|
2961
|
+
ngOnInit() {
|
|
2962
|
+
this.dataGridDataset.loadStarted
|
|
2963
|
+
.pipe(takeUntil(this.destroy$))
|
|
2964
|
+
.subscribe(() => {
|
|
2965
|
+
this.isSearchGridLoading = true;
|
|
2966
|
+
});
|
|
2967
|
+
this.dataGridDataset.loadFinished
|
|
2968
|
+
.pipe(takeUntil(this.destroy$))
|
|
2969
|
+
.subscribe(() => {
|
|
2970
|
+
this.isSearchGridLoading = false;
|
|
2971
|
+
this.updateSelectedItems();
|
|
2972
|
+
});
|
|
2973
|
+
this.resultDataset.loadFinished
|
|
2974
|
+
.pipe(takeUntil(this.destroy$))
|
|
2975
|
+
.subscribe(() => {
|
|
2976
|
+
this.isResultGridLoading = false;
|
|
2977
|
+
this.updateSelectedItems();
|
|
2978
|
+
});
|
|
2979
|
+
this.dataGridDataset.selectedRowsChanged
|
|
2980
|
+
.pipe(takeUntil(this.destroy$))
|
|
2981
|
+
.subscribe((selectionChanges) => {
|
|
2982
|
+
if (this.isSearchGridLoading || this.isResultGridLoading) {
|
|
2983
|
+
return;
|
|
2984
|
+
}
|
|
2985
|
+
Object.keys(selectionChanges)
|
|
2986
|
+
.forEach((key) => {
|
|
2987
|
+
const selection = selectionChanges[key];
|
|
2988
|
+
const id = this.dataGridDataset.getRowID(key);
|
|
2989
|
+
if (selection.selected) {
|
|
2990
|
+
this.resultDataset.setIDToAdd(id, selection.rowData);
|
|
2991
|
+
}
|
|
2992
|
+
else {
|
|
2993
|
+
this.resultDataset.setIDToRemove(id);
|
|
2994
|
+
}
|
|
2995
|
+
});
|
|
2996
|
+
});
|
|
2997
|
+
}
|
|
2998
|
+
//#endregion
|
|
2999
|
+
//#region Event handlers
|
|
3000
|
+
onSave() {
|
|
3001
|
+
this.modalProcessing = true;
|
|
3002
|
+
this.resultDataset.saveChanges()
|
|
3003
|
+
.pipe(take(1))
|
|
3004
|
+
.subscribe(() => {
|
|
3005
|
+
this.modalProcessing = false;
|
|
3006
|
+
this.toggleModal();
|
|
3007
|
+
});
|
|
3008
|
+
}
|
|
3009
|
+
onSearch() {
|
|
3010
|
+
const filters = this.dataGridDataset.filters ?? {};
|
|
3011
|
+
this.isSearchGridLoading = true;
|
|
3012
|
+
if (this.searchCriteria.length > 0) {
|
|
3013
|
+
filters[this.searchColumn] = this.searchCriteria;
|
|
3014
|
+
this.dataGridDataset.setFilters(filters);
|
|
3015
|
+
}
|
|
3016
|
+
else if (Object.keys(filters).includes(this.searchColumn)) {
|
|
3017
|
+
this.clearSearch();
|
|
3018
|
+
}
|
|
3019
|
+
}
|
|
3020
|
+
//#endregion
|
|
3021
|
+
//#region Public methods
|
|
3022
|
+
closeModal() {
|
|
3023
|
+
this.modal.closeModal();
|
|
3024
|
+
}
|
|
3025
|
+
toggleModal() {
|
|
3026
|
+
this.modal.toggleModal();
|
|
3027
|
+
if (this.modal.isShown) {
|
|
3028
|
+
this.searchCriteria = '';
|
|
3029
|
+
this.clearSearch();
|
|
3030
|
+
this.isResultGridLoading = true;
|
|
3031
|
+
this.resultDataset.refresh();
|
|
3032
|
+
}
|
|
3033
|
+
}
|
|
3034
|
+
//#endregion
|
|
3035
|
+
//#regiosn Private methods
|
|
3036
|
+
clearSearch() {
|
|
3037
|
+
const filters = this.dataGridDataset.filters ?? {};
|
|
3038
|
+
if (Object.keys(filters).includes(this.searchColumn)) {
|
|
3039
|
+
delete filters[this.searchColumn];
|
|
3040
|
+
}
|
|
3041
|
+
this.dataGridDataset.setFilters(filters);
|
|
3042
|
+
}
|
|
3043
|
+
updateSelectedItems() {
|
|
3044
|
+
if (this.isSearchGridLoading || this.isResultGridLoading) {
|
|
3045
|
+
return;
|
|
3046
|
+
}
|
|
3047
|
+
// Filter by the results that are not marked to be removed.
|
|
3048
|
+
const idsFromResult = (this.resultDataset.loadedKeys ?? [])
|
|
3049
|
+
.map((key) => this.resultDataset.getRowID(key))
|
|
3050
|
+
.filter((id) => this.resultDataset.idsToRemove.indexOf(id) < 0);
|
|
3051
|
+
idsFromResult.push(...this.resultDataset.idsToAdd);
|
|
3052
|
+
// Get each corresponding key from the data grid.
|
|
3053
|
+
const keysToSelect = (this.dataGridDataset.loadedKeys ?? [])
|
|
3054
|
+
.filter((key) => idsFromResult.indexOf(this.dataGridDataset.getRowID(key)) >= 0);
|
|
3055
|
+
this.dataGridDataset.selectRows(keysToSelect);
|
|
3056
|
+
}
|
|
3057
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: MultiSelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3058
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.6", type: MultiSelectComponent, isStandalone: true, selector: "lib-multi-select", inputs: { itemTemplate: "itemTemplate" }, viewQueries: [{ propertyName: "modal", first: true, predicate: ModalComponent, descendants: true }], usesInheritance: true, ngImport: i0, template: "<lib-modal\n[closeButtonText]=\"closeButtonText | translate\"\n[dialog]=\"dialog\"\n[modalProcessing]=\"modalProcessing\"\n[position]=\"position\"\n[size]=\"size\"\n[title]=\"title\">\n <div body class=\"body-content\">\n <div class=\"search-grid\">\n <div class=\"search\">\n <input\n class=\"form-input\"\n placeholder=\"Search...\"\n type=\"text\"\n [(ngModel)]=\"searchCriteria\"\n [disabled]=\"modalProcessing || isSearchGridLoading\"\n (keydown.enter)=\"onSearch()\" />\n </div>\n \n <lib-data-grid\n [disabled]=\"modalProcessing || isSearchGridLoading || isResultGridLoading\"\n [lazyLoadRows]=\"true\">\n </lib-data-grid>\n </div>\n\n <lib-multi-select-result-grid\n [isDisabled]=\"modalProcessing || isSearchGridLoading || isResultGridLoading\"\n [template]=\"itemTemplate\">\n </lib-multi-select-result-grid>\n </div>\n\n <div footer>\n <button\n class=\"btn blue-500\"\n type=\"button\"\n [class.loading]=\"modalProcessing\"\n (click)=\"onSave()\">\n {{ 'Button-Modal-MultiSelect-Confirm' | translate }}\n </button>\n </div>\n</lib-modal>", styles: [".body-content{display:grid;height:100%;grid-auto-columns:minmax(0,1fr);grid-auto-flow:column;gap:1rem;grid-template-rows:min-content minmax(0,1fr);grid-auto-flow:row!important;overflow:clip;overflow-clip-margin:4px}.search-grid{display:grid;grid-template-rows:subgrid}.search-grid,lib-multi-select-result-grid{grid-row:1 / -1}lib-multi-select-result-grid{min-height:24rem}\n"], dependencies: [{ kind: "component", type: DataGridComponent, selector: "lib-data-grid", inputs: ["disabled", "lazyLoadRows", "showButtons"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.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$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: ModalComponent, selector: "lib-modal", inputs: ["closeButtonText", "dialog", "modalProcessing", "position", "size", "title"], outputs: ["closed"] }, { kind: "component", type: MultiSelectResultGridComponent, selector: "lib-multi-select-result-grid", inputs: ["isDisabled", "template"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
|
|
3059
|
+
}
|
|
3060
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: MultiSelectComponent, decorators: [{
|
|
3061
|
+
type: Component,
|
|
3062
|
+
args: [{ selector: 'lib-multi-select', imports: [
|
|
3063
|
+
DataGridComponent,
|
|
3064
|
+
FormsModule,
|
|
3065
|
+
ModalComponent,
|
|
3066
|
+
MultiSelectResultGridComponent,
|
|
3067
|
+
TranslatePipe,
|
|
3068
|
+
], template: "<lib-modal\n[closeButtonText]=\"closeButtonText | translate\"\n[dialog]=\"dialog\"\n[modalProcessing]=\"modalProcessing\"\n[position]=\"position\"\n[size]=\"size\"\n[title]=\"title\">\n <div body class=\"body-content\">\n <div class=\"search-grid\">\n <div class=\"search\">\n <input\n class=\"form-input\"\n placeholder=\"Search...\"\n type=\"text\"\n [(ngModel)]=\"searchCriteria\"\n [disabled]=\"modalProcessing || isSearchGridLoading\"\n (keydown.enter)=\"onSearch()\" />\n </div>\n \n <lib-data-grid\n [disabled]=\"modalProcessing || isSearchGridLoading || isResultGridLoading\"\n [lazyLoadRows]=\"true\">\n </lib-data-grid>\n </div>\n\n <lib-multi-select-result-grid\n [isDisabled]=\"modalProcessing || isSearchGridLoading || isResultGridLoading\"\n [template]=\"itemTemplate\">\n </lib-multi-select-result-grid>\n </div>\n\n <div footer>\n <button\n class=\"btn blue-500\"\n type=\"button\"\n [class.loading]=\"modalProcessing\"\n (click)=\"onSave()\">\n {{ 'Button-Modal-MultiSelect-Confirm' | translate }}\n </button>\n </div>\n</lib-modal>", styles: [".body-content{display:grid;height:100%;grid-auto-columns:minmax(0,1fr);grid-auto-flow:column;gap:1rem;grid-template-rows:min-content minmax(0,1fr);grid-auto-flow:row!important;overflow:clip;overflow-clip-margin:4px}.search-grid{display:grid;grid-template-rows:subgrid}.search-grid,lib-multi-select-result-grid{grid-row:1 / -1}lib-multi-select-result-grid{min-height:24rem}\n"] }]
|
|
3069
|
+
}], ctorParameters: () => [], propDecorators: { modal: [{
|
|
3070
|
+
type: ViewChild,
|
|
3071
|
+
args: [ModalComponent]
|
|
3072
|
+
}], itemTemplate: [{
|
|
3073
|
+
type: Input
|
|
3074
|
+
}] } });
|
|
3075
|
+
|
|
3076
|
+
class SidebarItemComponent extends BaseComponent {
|
|
3077
|
+
//#region ViewChilds, Inputs, Outputs
|
|
3078
|
+
menuContainer;
|
|
3079
|
+
menu;
|
|
3080
|
+
level = 0;
|
|
3081
|
+
//#endregion
|
|
3082
|
+
//#region Variables
|
|
3083
|
+
hasFailed = false;
|
|
3084
|
+
isLoading = false;
|
|
3085
|
+
isSelected = false;
|
|
3086
|
+
_childHeight = 0;
|
|
3087
|
+
changeDetectorRef = inject(ChangeDetectorRef);
|
|
3088
|
+
sidebarService = inject(SidebarService);
|
|
3089
|
+
//#endregion
|
|
3090
|
+
//#region Properties
|
|
3091
|
+
get childHeight() {
|
|
3092
|
+
return this._childHeight;
|
|
3093
|
+
}
|
|
3094
|
+
get areChildrenLoaded() {
|
|
3095
|
+
return this.isParent && (this.menu.children?.length ?? 0) > 0;
|
|
3096
|
+
}
|
|
3097
|
+
get isActive() {
|
|
3098
|
+
return this.sidebarService.isActive;
|
|
3099
|
+
}
|
|
3100
|
+
get isCollapsed() {
|
|
3101
|
+
return this.sidebarService.isCollapsed;
|
|
3102
|
+
}
|
|
3103
|
+
get isParent() {
|
|
3104
|
+
return this.menu.childCount > 0;
|
|
3105
|
+
}
|
|
3106
|
+
get hasIcon() {
|
|
3107
|
+
return !!this.menu.icon && this.menu.icon.length > 0;
|
|
3108
|
+
}
|
|
3109
|
+
//#endregion
|
|
3110
|
+
//#region Constructor and Angular life cycle methods
|
|
3111
|
+
constructor() {
|
|
3112
|
+
super();
|
|
3113
|
+
}
|
|
3114
|
+
ngAfterViewInit() {
|
|
3115
|
+
if (!!this.menu && !!this.menu.parent) {
|
|
3116
|
+
this.menu.height = this.menuContainer?.nativeElement?.offsetHeight ?? 0;
|
|
3117
|
+
this.sidebarService.childrenInitialized.emit(this.menu.parent);
|
|
3118
|
+
}
|
|
3119
|
+
}
|
|
3120
|
+
ngOnInit() {
|
|
3121
|
+
if (this.isParent) {
|
|
3122
|
+
this.sidebarService.childrenFailed
|
|
3123
|
+
.pipe(takeUntil(this.destroy$), filter((menu) => menu.id === this.menu.id), delay(1000))
|
|
3124
|
+
.subscribe((_menu) => {
|
|
3125
|
+
this.hasFailed = true;
|
|
3126
|
+
this.isLoading = false;
|
|
3127
|
+
this.isSelected = false;
|
|
3128
|
+
this.menu.isSelected = false;
|
|
3129
|
+
this.changeDetectorRef.detectChanges();
|
|
3130
|
+
});
|
|
3131
|
+
this.sidebarService.childrenLoading
|
|
3132
|
+
.pipe(takeUntil(this.destroy$), filter((menu) => menu.id === this.menu.id))
|
|
3133
|
+
.subscribe((_menu) => {
|
|
3134
|
+
this.hasFailed = false;
|
|
3135
|
+
this.isLoading = true;
|
|
3136
|
+
});
|
|
3137
|
+
this.sidebarService.childrenInitialized
|
|
3138
|
+
.pipe(takeUntil(this.destroy$), filter((menu) => menu.id === this.menu.id && this.menu.children.every((child) => (child.height ?? 0) > 0)))
|
|
3139
|
+
.subscribe((_menu) => {
|
|
3140
|
+
this.isLoading = false;
|
|
3141
|
+
this.hasFailed = false;
|
|
3142
|
+
this.updateSubMenuHeight();
|
|
3143
|
+
if (!!this.menu.parent) {
|
|
3144
|
+
this.sidebarService.childrenInitialized.emit(this.menu.parent);
|
|
3145
|
+
}
|
|
3146
|
+
this.changeDetectorRef.detectChanges();
|
|
3147
|
+
});
|
|
3148
|
+
}
|
|
3149
|
+
this.sidebarService.selectionChanged
|
|
3150
|
+
.pipe(takeUntil(this.destroy$), filter((menu) => menu.id === this.menu.id))
|
|
3151
|
+
.subscribe((menu) => {
|
|
3152
|
+
this.isSelected = menu.isSelected;
|
|
3153
|
+
this.updateSubMenuHeight();
|
|
3154
|
+
});
|
|
3155
|
+
}
|
|
3156
|
+
//#endregion
|
|
3157
|
+
//#region Event handlers
|
|
3158
|
+
onSelectItem() {
|
|
3159
|
+
if (this.sidebarService.shouldActivate) {
|
|
3160
|
+
this.sidebarService.isActive = true;
|
|
3161
|
+
}
|
|
3162
|
+
this.sidebarService.select(this.menu);
|
|
3163
|
+
}
|
|
3164
|
+
//#endregion
|
|
3165
|
+
//#region Public methods
|
|
3166
|
+
//#endregion
|
|
3167
|
+
//#region Private methods
|
|
3168
|
+
trackByFn(_index, item) {
|
|
3169
|
+
return item.id;
|
|
3170
|
+
}
|
|
3171
|
+
getChildHeight(menu) {
|
|
3172
|
+
if (menu.isSelected) {
|
|
3173
|
+
return menu.children.reduce((height, childMenu) => height + (childMenu.height ?? 0) + this.getChildHeight(childMenu), 0);
|
|
3174
|
+
}
|
|
3175
|
+
return 0;
|
|
3176
|
+
}
|
|
3177
|
+
updateSubMenuHeight() {
|
|
3178
|
+
this._childHeight = this.getChildHeight(this.menu);
|
|
3179
|
+
}
|
|
3180
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: SidebarItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3181
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.6", type: SidebarItemComponent, isStandalone: true, selector: "lib-sidebar-item", inputs: { menu: "menu", level: "level" }, host: { properties: { "class.active": "isActive", "class.expanded": "!isCollapsed", "class.first-level": "level === 0", "class.selected": "isSelected" } }, viewQueries: [{ propertyName: "menuContainer", first: true, predicate: ["menuContainer"], descendants: true }], usesInheritance: true, ngImport: i0, template: "<li>\n <div #menuContainer\n [class.failed]=\"hasFailed\"\n [class.loading]=\"isLoading\"\n [class.parent]=\"isParent\"\n [class.selected]=\"isSelected\"\n (click)=\"onSelectItem()\">\n <a>\n <i *ngIf=\"hasIcon\" class=\"fa-solid fa-fw {{ menu.icon }}\"></i>\n <span>{{ menu.label | translate }}</span>\n </a>\n\n <div class=\"loading\" *ngIf=\"isParent\">\n <svg class=\"animate-spin text-white\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle class=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\"></circle>\n <path class=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"></path>\n </svg>\n </div>\n </div>\n\n <ul *ngIf=\"isParent\"\n [class.open]=\"isSelected\"\n [ngStyle]=\"{\n 'height.px': childHeight,\n 'max-height.px': childHeight\n }\">\n <lib-sidebar-item *ngFor=\"let child of menu.children; trackBy: trackByFn\"\n [menu]=\"child\"\n [level]=\"level+1\">\n </lib-sidebar-item>\n </ul>\n</li>", styles: ["@charset \"UTF-8\";:host{position:relative;display:block}@media (max-width: 767px){:host:not(.active) li>ul{height:0px!important}}@media (min-width: 768px){:host:not(.expanded):not(.active) li>ul{height:0px!important}:host.expanded li>div.parent:not(.loading):after{opacity:1}:host.expanded li>div.parent a{padding-right:2rem}:host.expanded li>div.parent.loading .loading{opacity:1!important}:host.expanded li>div a i{margin-left:0;font-size:1.125rem;line-height:1.75rem}:host.expanded li>div a span{opacity:1}}:host.active li>div.parent:not(.loading):after{opacity:1}:host.active li>div.parent a{padding-right:2rem}:host.active li>div.parent.loading .loading{opacity:1!important}:host.active li>div a i{margin-left:0;font-size:1.125rem;line-height:1.75rem}:host.active li>div a span{opacity:1}:host.expanded li .selected:not(.loading).parent:after,:host.active li .selected:not(.loading).parent:after{--tw-rotate: -90deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}:host.first-level:before{position:absolute;top:0;left:0;bottom:0;z-index:10;width:0px;--tw-bg-opacity: 1;background-color:rgb(243 244 246 / var(--tw-bg-opacity, 1));--tw-content: \"\";content:var(--tw-content);transition-property:width;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:var(--sidebar-animation-duration);will-change:width}:host.first-level.selected:before{width:4px}li{position:relative;height:100%}li>div{position:relative;overflow:hidden;height:var(--sidebar-item-height);line-height:var(--sidebar-item-height)}li>div:hover{--tw-bg-opacity: 1;background-color:rgb(51 65 85 / var(--tw-bg-opacity, 1))}li>div.parent:after{position:absolute;top:0;right:.75rem;width:10px;font-weight:800;transition-property:opacity;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1);opacity:0;font-family:\"Font Awesome 6 Free\";transition-duration:var(--sidebar-animation-duration);will-change:opacity}li>div.parent:not(.failed):after{--tw-content: \"\\f104\";content:var(--tw-content)}li>div.parent.failed:after{right:1rem;--tw-content: \"\\f071\";content:var(--tw-content)}li>div a{display:block;height:100%;cursor:pointer;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding-left:.75rem;padding-right:.75rem;text-align:left;width:var(--sidebar-expanded-width)}li>div a i{margin-right:.5rem;font-size:1.25rem;line-height:1.75rem;transition-property:font-size,line-height,margin-left;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1);margin-left:var(--sidebar-icon-collapsed-margin);transition-duration:var(--sidebar-animation-duration);will-change:font-size,line-height,margin-left}li>div a span{text-overflow:ellipsis;opacity:0;transition-property:opacity;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:var(--sidebar-animation-duration);will-change:opacity}li>div .loading{position:absolute;top:0;right:.55rem;height:100%;width:1rem;opacity:0;transition-property:opacity;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:var(--sidebar-animation-duration);will-change:opacity}li>div .loading svg{height:100%;width:100%}li>ul{overflow:hidden;transition-property:height,max-height;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:var(--sidebar-animation-duration);will-change:height,max-height}li>ul a{padding-left:1.25rem}\n"], dependencies: [{ kind: "component", type: SidebarItemComponent, selector: "lib-sidebar-item", inputs: ["menu", "level"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
|
|
3182
|
+
}
|
|
3183
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: SidebarItemComponent, decorators: [{
|
|
3184
|
+
type: Component,
|
|
3185
|
+
args: [{ selector: 'lib-sidebar-item', imports: [
|
|
3186
|
+
NgFor,
|
|
3187
|
+
NgIf,
|
|
3188
|
+
NgStyle,
|
|
3189
|
+
TranslatePipe,
|
|
3190
|
+
], host: {
|
|
3191
|
+
'[class.active]': 'isActive',
|
|
3192
|
+
'[class.expanded]': '!isCollapsed',
|
|
3193
|
+
'[class.first-level]': 'level === 0',
|
|
3194
|
+
'[class.selected]': 'isSelected',
|
|
3195
|
+
}, template: "<li>\n <div #menuContainer\n [class.failed]=\"hasFailed\"\n [class.loading]=\"isLoading\"\n [class.parent]=\"isParent\"\n [class.selected]=\"isSelected\"\n (click)=\"onSelectItem()\">\n <a>\n <i *ngIf=\"hasIcon\" class=\"fa-solid fa-fw {{ menu.icon }}\"></i>\n <span>{{ menu.label | translate }}</span>\n </a>\n\n <div class=\"loading\" *ngIf=\"isParent\">\n <svg class=\"animate-spin text-white\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle class=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\"></circle>\n <path class=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"></path>\n </svg>\n </div>\n </div>\n\n <ul *ngIf=\"isParent\"\n [class.open]=\"isSelected\"\n [ngStyle]=\"{\n 'height.px': childHeight,\n 'max-height.px': childHeight\n }\">\n <lib-sidebar-item *ngFor=\"let child of menu.children; trackBy: trackByFn\"\n [menu]=\"child\"\n [level]=\"level+1\">\n </lib-sidebar-item>\n </ul>\n</li>", styles: ["@charset \"UTF-8\";:host{position:relative;display:block}@media (max-width: 767px){:host:not(.active) li>ul{height:0px!important}}@media (min-width: 768px){:host:not(.expanded):not(.active) li>ul{height:0px!important}:host.expanded li>div.parent:not(.loading):after{opacity:1}:host.expanded li>div.parent a{padding-right:2rem}:host.expanded li>div.parent.loading .loading{opacity:1!important}:host.expanded li>div a i{margin-left:0;font-size:1.125rem;line-height:1.75rem}:host.expanded li>div a span{opacity:1}}:host.active li>div.parent:not(.loading):after{opacity:1}:host.active li>div.parent a{padding-right:2rem}:host.active li>div.parent.loading .loading{opacity:1!important}:host.active li>div a i{margin-left:0;font-size:1.125rem;line-height:1.75rem}:host.active li>div a span{opacity:1}:host.expanded li .selected:not(.loading).parent:after,:host.active li .selected:not(.loading).parent:after{--tw-rotate: -90deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}:host.first-level:before{position:absolute;top:0;left:0;bottom:0;z-index:10;width:0px;--tw-bg-opacity: 1;background-color:rgb(243 244 246 / var(--tw-bg-opacity, 1));--tw-content: \"\";content:var(--tw-content);transition-property:width;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:var(--sidebar-animation-duration);will-change:width}:host.first-level.selected:before{width:4px}li{position:relative;height:100%}li>div{position:relative;overflow:hidden;height:var(--sidebar-item-height);line-height:var(--sidebar-item-height)}li>div:hover{--tw-bg-opacity: 1;background-color:rgb(51 65 85 / var(--tw-bg-opacity, 1))}li>div.parent:after{position:absolute;top:0;right:.75rem;width:10px;font-weight:800;transition-property:opacity;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1);opacity:0;font-family:\"Font Awesome 6 Free\";transition-duration:var(--sidebar-animation-duration);will-change:opacity}li>div.parent:not(.failed):after{--tw-content: \"\\f104\";content:var(--tw-content)}li>div.parent.failed:after{right:1rem;--tw-content: \"\\f071\";content:var(--tw-content)}li>div a{display:block;height:100%;cursor:pointer;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding-left:.75rem;padding-right:.75rem;text-align:left;width:var(--sidebar-expanded-width)}li>div a i{margin-right:.5rem;font-size:1.25rem;line-height:1.75rem;transition-property:font-size,line-height,margin-left;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1);margin-left:var(--sidebar-icon-collapsed-margin);transition-duration:var(--sidebar-animation-duration);will-change:font-size,line-height,margin-left}li>div a span{text-overflow:ellipsis;opacity:0;transition-property:opacity;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:var(--sidebar-animation-duration);will-change:opacity}li>div .loading{position:absolute;top:0;right:.55rem;height:100%;width:1rem;opacity:0;transition-property:opacity;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:var(--sidebar-animation-duration);will-change:opacity}li>div .loading svg{height:100%;width:100%}li>ul{overflow:hidden;transition-property:height,max-height;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:var(--sidebar-animation-duration);will-change:height,max-height}li>ul a{padding-left:1.25rem}\n"] }]
|
|
3196
|
+
}], ctorParameters: () => [], propDecorators: { menuContainer: [{
|
|
3197
|
+
type: ViewChild,
|
|
3198
|
+
args: ['menuContainer']
|
|
3199
|
+
}], menu: [{
|
|
3200
|
+
type: Input
|
|
3201
|
+
}], level: [{
|
|
3202
|
+
type: Input
|
|
3203
|
+
}] } });
|
|
3204
|
+
|
|
3205
|
+
class SidebarComponent extends BaseComponent {
|
|
3206
|
+
//#region ViewChilds, Inputs, Outputs
|
|
3207
|
+
//#endregion
|
|
3208
|
+
//#region Host listeners
|
|
3209
|
+
onBodyMouseDown(event) {
|
|
3210
|
+
if (this.isActive && event.target) {
|
|
3211
|
+
const target = event.target;
|
|
3212
|
+
this.wasClickedOutside = (event.button === 0 && !target.closest('lib-sidebar')) ?? false;
|
|
3213
|
+
}
|
|
3214
|
+
}
|
|
3215
|
+
onBodyMouseUp(_event) {
|
|
3216
|
+
if (this.wasClickedOutside) {
|
|
3217
|
+
this.wasClickedOutside = false;
|
|
3218
|
+
this.deactivate();
|
|
3219
|
+
}
|
|
3220
|
+
}
|
|
3221
|
+
onDocumentKeyDown(event) {
|
|
3222
|
+
event = event || window.event;
|
|
3223
|
+
let isEscapeKey = false;
|
|
3224
|
+
if ('key' in event) {
|
|
3225
|
+
isEscapeKey = (event.key === 'Escape' || event.key === 'Esc');
|
|
3226
|
+
}
|
|
3227
|
+
else {
|
|
3228
|
+
isEscapeKey = (event.keyCode === 27);
|
|
3229
|
+
}
|
|
3230
|
+
if (isEscapeKey) {
|
|
3231
|
+
this.deactivate();
|
|
3232
|
+
}
|
|
3233
|
+
}
|
|
3234
|
+
onResize(_event) {
|
|
3235
|
+
this.updateShouldActivate();
|
|
3236
|
+
}
|
|
3237
|
+
//#endregion
|
|
3238
|
+
//#region Variables
|
|
3239
|
+
sidebarConfigs = inject(SIDEBAR_CONFIGS);
|
|
3240
|
+
configErrorText = this.sidebarConfigs.errorText;
|
|
3241
|
+
configLoadingText = this.sidebarConfigs.loadingText;
|
|
3242
|
+
configLogoCollapsedPath = this.sidebarConfigs.logoCollapsedPath;
|
|
3243
|
+
configLogoExpandedPath = this.sidebarConfigs.logoExpandedPath;
|
|
3244
|
+
hasFailed = false;
|
|
3245
|
+
menus = [];
|
|
3246
|
+
profile;
|
|
3247
|
+
sidebarService = inject(SidebarService);
|
|
3248
|
+
wasClickedOutside = false;
|
|
3249
|
+
//#endregion
|
|
3250
|
+
//#region Properties
|
|
3251
|
+
get hasProfileImage() {
|
|
3252
|
+
return this.isProfileLoaded && (this.profile.image?.length ?? 0) > 0;
|
|
3253
|
+
}
|
|
3254
|
+
get isActive() {
|
|
3255
|
+
return this.sidebarService.isActive;
|
|
3256
|
+
}
|
|
3257
|
+
get isCollapsed() {
|
|
3258
|
+
return this.sidebarService.isCollapsed;
|
|
3259
|
+
}
|
|
3260
|
+
get isLoading() {
|
|
3261
|
+
return this.menus.length === 0;
|
|
3262
|
+
}
|
|
3263
|
+
get isProfileLoaded() {
|
|
3264
|
+
return !!this.profile;
|
|
3265
|
+
}
|
|
3266
|
+
//#endregion
|
|
3267
|
+
//#region Constructor and Angular life cycle methods
|
|
3268
|
+
constructor() {
|
|
3269
|
+
super();
|
|
3270
|
+
}
|
|
3271
|
+
ngAfterViewInit() {
|
|
3272
|
+
this.updateShouldActivate();
|
|
3273
|
+
}
|
|
3274
|
+
ngOnInit() {
|
|
3275
|
+
this.sidebarService.menuUrlSelected
|
|
3276
|
+
.pipe(takeUntil(this.destroy$))
|
|
3277
|
+
.subscribe((_menu) => this.deactivate());
|
|
3278
|
+
this.sidebarService.loadRoot()
|
|
3279
|
+
.pipe(take(1))
|
|
3280
|
+
.subscribe({
|
|
3281
|
+
next: (menus) => this.menus = menus,
|
|
3282
|
+
error: () => this.hasFailed = true
|
|
3283
|
+
});
|
|
3284
|
+
this.profile = this.sidebarService.getUserProfile();
|
|
3285
|
+
}
|
|
3286
|
+
//#endregion
|
|
3287
|
+
//#region Event handlers
|
|
3288
|
+
//#endregion
|
|
3289
|
+
//#region Public methods
|
|
3290
|
+
collapse() {
|
|
3291
|
+
this.sidebarService.isCollapsed = !this.sidebarService.isCollapsed;
|
|
3292
|
+
this.sidebarService.isActive = false;
|
|
3293
|
+
if (this.sidebarService.isCollapsed) {
|
|
3294
|
+
this.sidebarService.deselectAll();
|
|
3295
|
+
}
|
|
3296
|
+
this.updateShouldActivate();
|
|
3297
|
+
}
|
|
3298
|
+
//#endregion
|
|
3299
|
+
//#region Private methods
|
|
3300
|
+
trackByFn(_index, item) {
|
|
3301
|
+
return item.id;
|
|
3302
|
+
}
|
|
3303
|
+
deactivate() {
|
|
3304
|
+
if (this.sidebarService.isActive) {
|
|
3305
|
+
this.sidebarService.isActive = false;
|
|
3306
|
+
this.sidebarService.deselectAll();
|
|
3307
|
+
}
|
|
3308
|
+
}
|
|
3309
|
+
updateShouldActivate() {
|
|
3310
|
+
this.sidebarService.shouldActivate =
|
|
3311
|
+
(window.innerWidth <= 767 && !this.sidebarService.isCollapsed)
|
|
3312
|
+
|| this.sidebarService.isCollapsed;
|
|
3313
|
+
}
|
|
3314
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: SidebarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3315
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.6", type: SidebarComponent, isStandalone: true, selector: "lib-sidebar", host: { listeners: { "body:mousedown": "onBodyMouseDown($event)", "body:mouseup": "onBodyMouseUp($event)", "document:keydown.escape": "onDocumentKeyDown($event)", "window:resize": "onResize($event)" }, properties: { "class.active": "isActive", "class.expanded": "!isCollapsed" } }, usesInheritance: true, ngImport: i0, template: "<div class=\"header\">\n <div class=\"logo-container\">\n <img class=\"collapsed\" [src]=\"configLogoCollapsedPath\" />\n <img class=\"expanded\" [src]=\"configLogoExpandedPath\" />\n </div>\n\n <div class=\"profile-container\" *ngIf=\"isProfileLoaded\">\n <div class=\"picture\" *ngIf=\"hasProfileImage\">\n <img [src]=\"profile!.image\" />\n </div>\n\n <div class=\"profile\">\n <h4>{{ profile!.name }}</h4>\n <h5>{{ profile!.title }}</h5>\n </div>\n </div>\n</div> \n\n<nav>\n <ul *ngIf=\"!isLoading; else loading\">\n <lib-sidebar-item *ngFor=\"let menu of menus; trackBy: trackByFn\"\n [menu]=\"menu\">\n </lib-sidebar-item>\n\n <div class=\"error\" *ngIf=\"hasFailed\">\n <div>\n <i class=\"fa-solid fa-fw fa-triangle-exclamation\"></i>\n <span>{{ configErrorText }}</span>\n </div>\n </div>\n </ul>\n</nav>\n\n<ng-template #loading>\n <div class=\"loading\">\n <div>\n <svg class=\"animate-spin text-white\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle class=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\"></circle>\n <path class=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"></path>\n </svg>\n <span>{{ configLoadingText }}</span>\n </div>\n </div>\n</ng-template>", styles: [":host{display:grid;height:100%;-webkit-user-select:none;user-select:none;overflow-x:hidden;--tw-bg-opacity: 1;background-color:rgb(0 67 114 / var(--tw-bg-opacity, 1));transition-property:margin-left,width;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1);margin-left:calc(var(--sidebar-collapsed-width) * -1);transition-duration:var(--sidebar-animation-duration);width:var(--sidebar-collapsed-width);will-change:margin-left,width;grid-template-rows:auto minmax(0,1fr);grid-template-areas:\"header\" \"nav\"}@media (min-width: 768px){:host{margin-left:0}:host.expanded{width:var(--sidebar-expanded-width)}:host.expanded .header .logo-container img.collapsed{opacity:0}:host.expanded .header .logo-container img.expanded{opacity:1}:host.expanded .header .profile-container .profile{padding-left:.5rem;opacity:1;width:calc(var(--sidebar-expanded-width) - var(--sidebar-picture-size) - 24px)}:host.expanded .loading i,:host.expanded .error i{margin-left:0;font-size:1.125rem;line-height:1.75rem}:host.expanded .loading svg,:host.expanded .error svg{margin-top:-4px;margin-left:1px;height:1.25rem;width:1.25rem}:host.expanded .loading span,:host.expanded .error span{opacity:1}}:host.active{width:var(--sidebar-expanded-width)}:host.active .header .logo-container img.collapsed{opacity:0}:host.active .header .logo-container img.expanded{opacity:1}:host.active .header .profile-container .profile{padding-left:.5rem;opacity:1;width:calc(var(--sidebar-expanded-width) - var(--sidebar-picture-size) - 24px)}:host.active .loading i,:host.active .error i{margin-left:0;font-size:1.125rem;line-height:1.75rem}:host.active .loading svg,:host.active .error svg{margin-top:-4px;margin-left:1px;height:1.25rem;width:1.25rem}:host.active .loading span,:host.active .error span{opacity:1}:host.expanded,:host.active{margin-left:0}.header{padding-top:.5rem;padding-bottom:.75rem;grid-area:header}.header .logo-container{position:relative;width:100%;overflow:hidden;text-align:center;height:var(--sidebar-logo-height)}.header .logo-container img{margin:auto;max-height:100%;min-width:fit-content;transition-property:opacity;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:var(--sidebar-animation-duration);will-change:opacity}.header .logo-container img.expanded{position:absolute;top:0;left:50%;--tw-translate-x: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));opacity:0}.header .profile-container{margin-left:.75rem;margin-right:.75rem;margin-top:.5rem;display:flex;flex-wrap:nowrap;height:var(--sidebar-picture-size)}.header .profile-container .picture{flex-shrink:0;overflow:hidden;border-radius:9999px;min-width:var(--sidebar-picture-size);width:var(--sidebar-picture-size)}.header .profile-container .picture img{min-width:var(--sidebar-picture-size)}.header .profile-container .profile{width:0px;overflow:hidden;white-space:nowrap;padding-left:0;opacity:0;transition-timing-function:cubic-bezier(.4,0,.2,1);transition:opacity var(--sidebar-animation-duration) ease-in-out,padding-left var(--sidebar-animation-duration) ease-in-out,width var(--sidebar-animation-duration) ease-in-out;will-change:width,opacity,padding-left}.header .profile-container .profile h4,.header .profile-container .profile h5{overflow:hidden;text-overflow:ellipsis;height:calc(var(--sidebar-picture-size) / 2);animation:text-clip .2s forwards}.header .profile-container .profile h4{font-weight:500;--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.header .profile-container .profile h5{font-size:.875rem;line-height:1.25rem;--tw-text-opacity: 1;color:rgb(209 213 219 / var(--tw-text-opacity, 1))}nav{overflow-y:auto;grid-area:nav;scrollbar-width:thin;scrollbar-color:rgba(0,0,0,.2) transparent}nav::-webkit-scrollbar{height:0px;width:7px}nav::-webkit-scrollbar-track{background-color:transparent}nav::-webkit-scrollbar-thumb{background-color:#0003;border-radius:10px;transition:background .2s ease}nav::-webkit-scrollbar-thumb:hover{background-color:#0000008c}nav:hover::-webkit-scrollbar-thumb{background-color:#00000073}@media screen and (max-width: 480px){nav{scrollbar-width:thin}nav::-webkit-scrollbar{width:5px}}ul,.loading{position:relative;background-color:#002f50cc}ul lib-sidebar-item,.loading,.error{font-weight:500;--tw-text-opacity: 1;color:rgb(229 231 235 / var(--tw-text-opacity, 1))}.loading,.error{overflow:hidden;height:var(--sidebar-item-height);line-height:var(--sidebar-item-height)}.loading>div,.error>div{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding-left:.75rem;padding-right:.75rem;text-align:left;width:var(--sidebar-expanded-width)}.loading i,.error i{margin-right:.5rem;font-size:1.25rem;line-height:1.75rem;transition-property:font-size,line-height,margin-left;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1);margin-left:var(--sidebar-icon-collapsed-margin);transition-duration:var(--sidebar-animation-duration);will-change:font-size,line-height,margin-left}.loading svg,.error svg{margin-top:-4px;margin-left:.5rem;display:inline;height:1.5rem;width:1.5rem;transition-property:height,margin-left,width;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:var(--sidebar-animation-duration);will-change:height,margin-left,width}.loading svg+span,.error svg+span{margin-left:.6rem}.loading span,.error span{transition-property:opacity;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1);opacity:0;transition-duration:var(--sidebar-animation-duration)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: SidebarItemComponent, selector: "lib-sidebar-item", inputs: ["menu", "level"] }] });
|
|
3316
|
+
}
|
|
3317
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: SidebarComponent, decorators: [{
|
|
3318
|
+
type: Component,
|
|
3319
|
+
args: [{ selector: 'lib-sidebar', imports: [
|
|
3320
|
+
CommonModule,
|
|
3321
|
+
NgFor,
|
|
3322
|
+
NgIf,
|
|
3323
|
+
SidebarItemComponent,
|
|
3324
|
+
], host: {
|
|
3325
|
+
'[class.active]': 'isActive',
|
|
3326
|
+
'[class.expanded]': '!isCollapsed',
|
|
3327
|
+
}, template: "<div class=\"header\">\n <div class=\"logo-container\">\n <img class=\"collapsed\" [src]=\"configLogoCollapsedPath\" />\n <img class=\"expanded\" [src]=\"configLogoExpandedPath\" />\n </div>\n\n <div class=\"profile-container\" *ngIf=\"isProfileLoaded\">\n <div class=\"picture\" *ngIf=\"hasProfileImage\">\n <img [src]=\"profile!.image\" />\n </div>\n\n <div class=\"profile\">\n <h4>{{ profile!.name }}</h4>\n <h5>{{ profile!.title }}</h5>\n </div>\n </div>\n</div> \n\n<nav>\n <ul *ngIf=\"!isLoading; else loading\">\n <lib-sidebar-item *ngFor=\"let menu of menus; trackBy: trackByFn\"\n [menu]=\"menu\">\n </lib-sidebar-item>\n\n <div class=\"error\" *ngIf=\"hasFailed\">\n <div>\n <i class=\"fa-solid fa-fw fa-triangle-exclamation\"></i>\n <span>{{ configErrorText }}</span>\n </div>\n </div>\n </ul>\n</nav>\n\n<ng-template #loading>\n <div class=\"loading\">\n <div>\n <svg class=\"animate-spin text-white\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle class=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\"></circle>\n <path class=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"></path>\n </svg>\n <span>{{ configLoadingText }}</span>\n </div>\n </div>\n</ng-template>", styles: [":host{display:grid;height:100%;-webkit-user-select:none;user-select:none;overflow-x:hidden;--tw-bg-opacity: 1;background-color:rgb(0 67 114 / var(--tw-bg-opacity, 1));transition-property:margin-left,width;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1);margin-left:calc(var(--sidebar-collapsed-width) * -1);transition-duration:var(--sidebar-animation-duration);width:var(--sidebar-collapsed-width);will-change:margin-left,width;grid-template-rows:auto minmax(0,1fr);grid-template-areas:\"header\" \"nav\"}@media (min-width: 768px){:host{margin-left:0}:host.expanded{width:var(--sidebar-expanded-width)}:host.expanded .header .logo-container img.collapsed{opacity:0}:host.expanded .header .logo-container img.expanded{opacity:1}:host.expanded .header .profile-container .profile{padding-left:.5rem;opacity:1;width:calc(var(--sidebar-expanded-width) - var(--sidebar-picture-size) - 24px)}:host.expanded .loading i,:host.expanded .error i{margin-left:0;font-size:1.125rem;line-height:1.75rem}:host.expanded .loading svg,:host.expanded .error svg{margin-top:-4px;margin-left:1px;height:1.25rem;width:1.25rem}:host.expanded .loading span,:host.expanded .error span{opacity:1}}:host.active{width:var(--sidebar-expanded-width)}:host.active .header .logo-container img.collapsed{opacity:0}:host.active .header .logo-container img.expanded{opacity:1}:host.active .header .profile-container .profile{padding-left:.5rem;opacity:1;width:calc(var(--sidebar-expanded-width) - var(--sidebar-picture-size) - 24px)}:host.active .loading i,:host.active .error i{margin-left:0;font-size:1.125rem;line-height:1.75rem}:host.active .loading svg,:host.active .error svg{margin-top:-4px;margin-left:1px;height:1.25rem;width:1.25rem}:host.active .loading span,:host.active .error span{opacity:1}:host.expanded,:host.active{margin-left:0}.header{padding-top:.5rem;padding-bottom:.75rem;grid-area:header}.header .logo-container{position:relative;width:100%;overflow:hidden;text-align:center;height:var(--sidebar-logo-height)}.header .logo-container img{margin:auto;max-height:100%;min-width:fit-content;transition-property:opacity;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:var(--sidebar-animation-duration);will-change:opacity}.header .logo-container img.expanded{position:absolute;top:0;left:50%;--tw-translate-x: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));opacity:0}.header .profile-container{margin-left:.75rem;margin-right:.75rem;margin-top:.5rem;display:flex;flex-wrap:nowrap;height:var(--sidebar-picture-size)}.header .profile-container .picture{flex-shrink:0;overflow:hidden;border-radius:9999px;min-width:var(--sidebar-picture-size);width:var(--sidebar-picture-size)}.header .profile-container .picture img{min-width:var(--sidebar-picture-size)}.header .profile-container .profile{width:0px;overflow:hidden;white-space:nowrap;padding-left:0;opacity:0;transition-timing-function:cubic-bezier(.4,0,.2,1);transition:opacity var(--sidebar-animation-duration) ease-in-out,padding-left var(--sidebar-animation-duration) ease-in-out,width var(--sidebar-animation-duration) ease-in-out;will-change:width,opacity,padding-left}.header .profile-container .profile h4,.header .profile-container .profile h5{overflow:hidden;text-overflow:ellipsis;height:calc(var(--sidebar-picture-size) / 2);animation:text-clip .2s forwards}.header .profile-container .profile h4{font-weight:500;--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.header .profile-container .profile h5{font-size:.875rem;line-height:1.25rem;--tw-text-opacity: 1;color:rgb(209 213 219 / var(--tw-text-opacity, 1))}nav{overflow-y:auto;grid-area:nav;scrollbar-width:thin;scrollbar-color:rgba(0,0,0,.2) transparent}nav::-webkit-scrollbar{height:0px;width:7px}nav::-webkit-scrollbar-track{background-color:transparent}nav::-webkit-scrollbar-thumb{background-color:#0003;border-radius:10px;transition:background .2s ease}nav::-webkit-scrollbar-thumb:hover{background-color:#0000008c}nav:hover::-webkit-scrollbar-thumb{background-color:#00000073}@media screen and (max-width: 480px){nav{scrollbar-width:thin}nav::-webkit-scrollbar{width:5px}}ul,.loading{position:relative;background-color:#002f50cc}ul lib-sidebar-item,.loading,.error{font-weight:500;--tw-text-opacity: 1;color:rgb(229 231 235 / var(--tw-text-opacity, 1))}.loading,.error{overflow:hidden;height:var(--sidebar-item-height);line-height:var(--sidebar-item-height)}.loading>div,.error>div{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding-left:.75rem;padding-right:.75rem;text-align:left;width:var(--sidebar-expanded-width)}.loading i,.error i{margin-right:.5rem;font-size:1.25rem;line-height:1.75rem;transition-property:font-size,line-height,margin-left;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1);margin-left:var(--sidebar-icon-collapsed-margin);transition-duration:var(--sidebar-animation-duration);will-change:font-size,line-height,margin-left}.loading svg,.error svg{margin-top:-4px;margin-left:.5rem;display:inline;height:1.5rem;width:1.5rem;transition-property:height,margin-left,width;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:var(--sidebar-animation-duration);will-change:height,margin-left,width}.loading svg+span,.error svg+span{margin-left:.6rem}.loading span,.error span{transition-property:opacity;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1);opacity:0;transition-duration:var(--sidebar-animation-duration)}\n"] }]
|
|
3328
|
+
}], ctorParameters: () => [], propDecorators: { onBodyMouseDown: [{
|
|
3329
|
+
type: HostListener,
|
|
3330
|
+
args: ['body:mousedown', ['$event']]
|
|
3331
|
+
}], onBodyMouseUp: [{
|
|
3332
|
+
type: HostListener,
|
|
3333
|
+
args: ['body:mouseup', ['$event']]
|
|
3334
|
+
}], onDocumentKeyDown: [{
|
|
3335
|
+
type: HostListener,
|
|
3336
|
+
args: ['document:keydown.escape', ['$event']]
|
|
3337
|
+
}], onResize: [{
|
|
3338
|
+
type: HostListener,
|
|
3339
|
+
args: ['window:resize', ['$event']]
|
|
3340
|
+
}] } });
|
|
3341
|
+
|
|
3342
|
+
class RibbonButtonComponent {
|
|
3343
|
+
//#region ViewChilds, Inputs, Outputs
|
|
3344
|
+
color = 'text-primary-500';
|
|
3345
|
+
defaultOption = -1;
|
|
3346
|
+
disabled = false;
|
|
3347
|
+
icon;
|
|
3348
|
+
iconSize = 'large';
|
|
3349
|
+
label = '';
|
|
3350
|
+
loading = false;
|
|
3351
|
+
options = [];
|
|
3352
|
+
action = new EventEmitter();
|
|
3353
|
+
//#endregion
|
|
3354
|
+
//#region Host listeners
|
|
3355
|
+
bodyMouseDown(event) {
|
|
3356
|
+
if (this.showDropdown) {
|
|
3357
|
+
const target = event.target;
|
|
3358
|
+
const button = target.closest('.button-container')?.parentElement;
|
|
3359
|
+
this.clickedOutside =
|
|
3360
|
+
event.button === 0
|
|
3361
|
+
&& !target.closest('.options-dropdown')
|
|
3362
|
+
&& (!button || (!button?.classList.contains('dropdown') && !button?.classList.contains('open')));
|
|
3363
|
+
}
|
|
3364
|
+
}
|
|
3365
|
+
bodyMouseUp(event) {
|
|
3366
|
+
if (this.showDropdown && this.clickedOutside) {
|
|
3367
|
+
this.showDropdown = false;
|
|
3368
|
+
}
|
|
3369
|
+
}
|
|
3370
|
+
documentKeyDown(event) {
|
|
3371
|
+
event = event || window.event;
|
|
3372
|
+
let isEscape = false;
|
|
3373
|
+
if ('key' in event) {
|
|
3374
|
+
isEscape = (event.key === 'Escape' || event.key === 'Esc');
|
|
3375
|
+
}
|
|
3376
|
+
else {
|
|
3377
|
+
isEscape = (event.keyCode === 27);
|
|
3378
|
+
}
|
|
3379
|
+
if (this.showDropdown && isEscape) {
|
|
3380
|
+
this.showDropdown = false;
|
|
3381
|
+
}
|
|
3382
|
+
}
|
|
3383
|
+
//#endregion
|
|
3384
|
+
//#region Variables
|
|
3385
|
+
showDropdown = false;
|
|
3386
|
+
status = null;
|
|
3387
|
+
clickedOutside = false;
|
|
3388
|
+
//#endregion
|
|
3389
|
+
//#region Properties
|
|
3390
|
+
get buttonIcon() {
|
|
3391
|
+
switch (this.status) {
|
|
3392
|
+
case 'success':
|
|
3393
|
+
return 'fa-check';
|
|
3394
|
+
case 'failure':
|
|
3395
|
+
return 'fa-times';
|
|
3396
|
+
case 'warning':
|
|
3397
|
+
return 'fa-exclamation';
|
|
3398
|
+
default:
|
|
3399
|
+
return this.icon ?? '';
|
|
3400
|
+
}
|
|
3401
|
+
}
|
|
3402
|
+
get isButtonDisabled() {
|
|
3403
|
+
return this.disabled || this.loading || (this.options.length > 0 && !this.options.some((option) => this.isOptionVisible(option)));
|
|
3404
|
+
}
|
|
3405
|
+
//#endregion
|
|
3406
|
+
//#region Constructor and Angular life cycle methods
|
|
3407
|
+
//#endregion
|
|
3408
|
+
//#region Event handlers
|
|
3409
|
+
onButtonClicked() {
|
|
3410
|
+
if (this.options.length > 0) {
|
|
3411
|
+
if (this.defaultOption >= 0 && this.defaultOption < this.options.length) {
|
|
3412
|
+
this.showDropdown = false;
|
|
3413
|
+
this.action.emit(this.options[this.defaultOption].id);
|
|
3414
|
+
}
|
|
3415
|
+
else {
|
|
3416
|
+
this.onShowHideDropdown();
|
|
3417
|
+
}
|
|
3418
|
+
}
|
|
3419
|
+
else {
|
|
3420
|
+
this.action.emit();
|
|
3421
|
+
}
|
|
3422
|
+
}
|
|
3423
|
+
onOptionClicked(option) {
|
|
3424
|
+
this.showDropdown = false;
|
|
3425
|
+
this.action.emit(option.id);
|
|
3426
|
+
}
|
|
3427
|
+
onShowHideDropdown() {
|
|
3428
|
+
this.showDropdown = !this.showDropdown;
|
|
3429
|
+
}
|
|
3430
|
+
//#endregion
|
|
3431
|
+
//#region Public methods
|
|
3432
|
+
finishLoading(status) {
|
|
3433
|
+
this.loading = false;
|
|
3434
|
+
this.status = status;
|
|
3435
|
+
setTimeout(() => {
|
|
3436
|
+
this.status = null;
|
|
3437
|
+
}, 1000);
|
|
3438
|
+
}
|
|
3439
|
+
startLoading() {
|
|
3440
|
+
this.loading = true;
|
|
3441
|
+
}
|
|
3442
|
+
isOptionDisabled(option) {
|
|
3443
|
+
return option.isDisabled || ((option.allowedActions?.length ?? 0) > 0 && option.isAccessAllowed === undefined);
|
|
3444
|
+
}
|
|
3445
|
+
isOptionVisible(option) {
|
|
3446
|
+
return (option.isVisible ?? true) && (option.allowedActions === undefined || option.allowedActions.length === 0 || option.isAccessAllowed === true || (option.isAccessAllowed == undefined && option.allowedActions?.length > 0));
|
|
3447
|
+
}
|
|
3448
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: RibbonButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3449
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.6", type: RibbonButtonComponent, isStandalone: true, selector: "lib-ribbon-button", inputs: { color: "color", defaultOption: "defaultOption", disabled: "disabled", icon: "icon", iconSize: "iconSize", label: "label", loading: "loading", options: "options" }, outputs: { action: "action" }, host: { listeners: { "body:mousedown": "bodyMouseDown($event)", "body:mouseup": "bodyMouseUp($event)", "document:keydown.escape": "documentKeyDown($event)" }, properties: { "class.dropdown": "options.length > 0", "class.show": "showDropdown" } }, ngImport: i0, template: "<div class=\"button-container\">\n <a class=\"button\"\n [class.disabled]=\"isButtonDisabled\"\n [class.success]=\"status === 'success'\"\n [class.warning]=\"status === 'warning'\"\n [class.failure]=\"status === 'failure'\"\n [class.small]=\"iconSize === 'small'\"\n (click)=\"onButtonClicked()\"\n >\n <span class=\"icon\" [class.loading]=\"loading\">\n <i class=\"fas fa-fw\" [ngClass]=\"[ buttonIcon, color ]\"></i>\n \n <svg [ngClass]=\"[ color ]\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle class=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\"></circle>\n <path class=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"></path>\n </svg>\n </span>\n \n <span class=\"label\" [class.text-white]=\"status !== null\">\n {{ label | translate }}\n </span>\n </a>\n \n <a class=\"button-dropdown\" *ngIf=\"options.length > 0\"\n [class.disabled]=\"isButtonDisabled\"\n [class.success]=\"status === 'success'\"\n [class.warning]=\"status === 'warning'\"\n [class.failure]=\"status === 'failure'\"\n [class.small]=\"iconSize === 'small'\"\n (click)=\"onShowHideDropdown()\"\n >\n <i class=\"fas fa-chevron-down\" [ngClass]=\"[ color ]\"></i>\n </a>\n</div>\n\n<ul class=\"options-dropdown\" *ngIf=\"options.length > 0\">\n <li *ngFor=\"let option of options; let i = index\"\n [class.default-option]=\"i === defaultOption\"\n [class.disabled]=\"isOptionDisabled(option)\"\n [class.hidden]=\"!isOptionVisible(option)\"\n (click)=\"onOptionClicked(option)\"\n >\n <i class=\"fas fa-fw\" *ngIf=\"!!option.icon\" [ngClass]=\"[ option.icon, color ]\"></i> {{ option.label | translate }}\n </li>\n</ul>", styles: [":host-context.dropdown .button{border-top-right-radius:0;border-bottom-right-radius:0}.button-container{display:flex}.button{border-radius:.5rem;padding-left:.75rem;padding-right:.75rem}.button.success .icon i,.button.success .label,.button.warning .icon i,.button.warning .label,.button.failure .icon i,.button.failure .label{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.button.small{padding-left:.5rem;padding-right:.5rem}.button.small .icon i{height:1.75rem;font-size:1.5rem;line-height:2rem}@media (min-width: 768px){.button.small .icon i{font-size:1.25rem;line-height:1.75rem}}.button.small .icon svg{height:1.5rem}.button.small .label{font-size:.875rem;line-height:1.25rem}.button .icon{position:relative;display:flex;height:2rem;flex-direction:column;align-items:center;justify-content:center;text-align:center;font-size:2.25rem;line-height:2.5rem}@media (min-width: 768px){.button .icon{font-size:1.875rem;line-height:2.25rem}}.button .icon i{transition-property:all;transition-duration:.2s;transition-timing-function:cubic-bezier(.4,0,.2,1)}.button .icon svg{position:absolute;height:2rem;width:2rem}@keyframes spin{to{transform:rotate(360deg)}}.button .icon svg{animation:spin 1s linear infinite;opacity:0;transition-property:opacity;transition-duration:.2s;transition-timing-function:cubic-bezier(.4,0,.2,1)}.button .icon.loading i{opacity:0}.button .icon.loading svg{opacity:1}.button .label{margin-top:.5rem;text-align:center;--tw-text-opacity: 1;color:rgb(31 41 55 / var(--tw-text-opacity, 1));transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-duration:.2s;transition-timing-function:cubic-bezier(.4,0,.2,1)}.button-dropdown{justify-content:center;border-top-right-radius:.5rem;border-bottom-right-radius:.5rem;padding-left:.25rem;padding-right:.25rem}.button-dropdown.success i,.button-dropdown.warning i,.button-dropdown.failure i{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.button-dropdown.small{font-size:.875rem;line-height:1.25rem}@media (min-width: 768px){.button-dropdown.small{font-size:1rem;line-height:1.5rem}}.button,.button-dropdown{display:flex;cursor:pointer;-webkit-user-select:none;user-select:none;flex-direction:column;padding-top:.5rem;padding-bottom:.5rem;transition-property:all;transition-duration:.2s;transition-timing-function:cubic-bezier(.4,0,.2,1)}.button:hover,.button-dropdown:hover{background-color:#d1d5dbcc}.button:focus,.button-dropdown:focus{background-color:#d1d5dbcc}.button:active,.button-dropdown:active{background-color:#9ca3af99}.button:disabled,.button.disabled,.button-dropdown:disabled,.button-dropdown.disabled{pointer-events:none;opacity:.6}.button.success,.button-dropdown.success{background-color:#16a34abf}.button.warning,.button-dropdown.warning{background-color:#ca8a04bf}.button.failure,.button-dropdown.failure{background-color:#dc2626bf}.button.small,.button-dropdown.small{padding-top:.25rem;padding-bottom:.25rem}ul{z-index:1;min-width:fit-content;-webkit-user-select:none;user-select:none}ul li{cursor:pointer;white-space:nowrap;padding:.5rem 1rem}ul li.default-option{display:none}ul li.disabled{pointer-events:none;opacity:.6}ul li:hover{--tw-bg-opacity: 1;background-color:rgb(230 244 255 / var(--tw-bg-opacity, 1))}ul li i{margin-right:.25rem}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
|
|
3450
|
+
}
|
|
3451
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: RibbonButtonComponent, decorators: [{
|
|
3452
|
+
type: Component,
|
|
3453
|
+
args: [{ selector: 'lib-ribbon-button', host: {
|
|
3454
|
+
'[class.dropdown]': 'options.length > 0',
|
|
3455
|
+
'[class.show]': 'showDropdown',
|
|
3456
|
+
}, imports: [
|
|
3457
|
+
NgClass,
|
|
3458
|
+
NgFor,
|
|
3459
|
+
NgIf,
|
|
3460
|
+
TranslatePipe,
|
|
3461
|
+
], template: "<div class=\"button-container\">\n <a class=\"button\"\n [class.disabled]=\"isButtonDisabled\"\n [class.success]=\"status === 'success'\"\n [class.warning]=\"status === 'warning'\"\n [class.failure]=\"status === 'failure'\"\n [class.small]=\"iconSize === 'small'\"\n (click)=\"onButtonClicked()\"\n >\n <span class=\"icon\" [class.loading]=\"loading\">\n <i class=\"fas fa-fw\" [ngClass]=\"[ buttonIcon, color ]\"></i>\n \n <svg [ngClass]=\"[ color ]\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle class=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\"></circle>\n <path class=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"></path>\n </svg>\n </span>\n \n <span class=\"label\" [class.text-white]=\"status !== null\">\n {{ label | translate }}\n </span>\n </a>\n \n <a class=\"button-dropdown\" *ngIf=\"options.length > 0\"\n [class.disabled]=\"isButtonDisabled\"\n [class.success]=\"status === 'success'\"\n [class.warning]=\"status === 'warning'\"\n [class.failure]=\"status === 'failure'\"\n [class.small]=\"iconSize === 'small'\"\n (click)=\"onShowHideDropdown()\"\n >\n <i class=\"fas fa-chevron-down\" [ngClass]=\"[ color ]\"></i>\n </a>\n</div>\n\n<ul class=\"options-dropdown\" *ngIf=\"options.length > 0\">\n <li *ngFor=\"let option of options; let i = index\"\n [class.default-option]=\"i === defaultOption\"\n [class.disabled]=\"isOptionDisabled(option)\"\n [class.hidden]=\"!isOptionVisible(option)\"\n (click)=\"onOptionClicked(option)\"\n >\n <i class=\"fas fa-fw\" *ngIf=\"!!option.icon\" [ngClass]=\"[ option.icon, color ]\"></i> {{ option.label | translate }}\n </li>\n</ul>", styles: [":host-context.dropdown .button{border-top-right-radius:0;border-bottom-right-radius:0}.button-container{display:flex}.button{border-radius:.5rem;padding-left:.75rem;padding-right:.75rem}.button.success .icon i,.button.success .label,.button.warning .icon i,.button.warning .label,.button.failure .icon i,.button.failure .label{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.button.small{padding-left:.5rem;padding-right:.5rem}.button.small .icon i{height:1.75rem;font-size:1.5rem;line-height:2rem}@media (min-width: 768px){.button.small .icon i{font-size:1.25rem;line-height:1.75rem}}.button.small .icon svg{height:1.5rem}.button.small .label{font-size:.875rem;line-height:1.25rem}.button .icon{position:relative;display:flex;height:2rem;flex-direction:column;align-items:center;justify-content:center;text-align:center;font-size:2.25rem;line-height:2.5rem}@media (min-width: 768px){.button .icon{font-size:1.875rem;line-height:2.25rem}}.button .icon i{transition-property:all;transition-duration:.2s;transition-timing-function:cubic-bezier(.4,0,.2,1)}.button .icon svg{position:absolute;height:2rem;width:2rem}@keyframes spin{to{transform:rotate(360deg)}}.button .icon svg{animation:spin 1s linear infinite;opacity:0;transition-property:opacity;transition-duration:.2s;transition-timing-function:cubic-bezier(.4,0,.2,1)}.button .icon.loading i{opacity:0}.button .icon.loading svg{opacity:1}.button .label{margin-top:.5rem;text-align:center;--tw-text-opacity: 1;color:rgb(31 41 55 / var(--tw-text-opacity, 1));transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-duration:.2s;transition-timing-function:cubic-bezier(.4,0,.2,1)}.button-dropdown{justify-content:center;border-top-right-radius:.5rem;border-bottom-right-radius:.5rem;padding-left:.25rem;padding-right:.25rem}.button-dropdown.success i,.button-dropdown.warning i,.button-dropdown.failure i{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.button-dropdown.small{font-size:.875rem;line-height:1.25rem}@media (min-width: 768px){.button-dropdown.small{font-size:1rem;line-height:1.5rem}}.button,.button-dropdown{display:flex;cursor:pointer;-webkit-user-select:none;user-select:none;flex-direction:column;padding-top:.5rem;padding-bottom:.5rem;transition-property:all;transition-duration:.2s;transition-timing-function:cubic-bezier(.4,0,.2,1)}.button:hover,.button-dropdown:hover{background-color:#d1d5dbcc}.button:focus,.button-dropdown:focus{background-color:#d1d5dbcc}.button:active,.button-dropdown:active{background-color:#9ca3af99}.button:disabled,.button.disabled,.button-dropdown:disabled,.button-dropdown.disabled{pointer-events:none;opacity:.6}.button.success,.button-dropdown.success{background-color:#16a34abf}.button.warning,.button-dropdown.warning{background-color:#ca8a04bf}.button.failure,.button-dropdown.failure{background-color:#dc2626bf}.button.small,.button-dropdown.small{padding-top:.25rem;padding-bottom:.25rem}ul{z-index:1;min-width:fit-content;-webkit-user-select:none;user-select:none}ul li{cursor:pointer;white-space:nowrap;padding:.5rem 1rem}ul li.default-option{display:none}ul li.disabled{pointer-events:none;opacity:.6}ul li:hover{--tw-bg-opacity: 1;background-color:rgb(230 244 255 / var(--tw-bg-opacity, 1))}ul li i{margin-right:.25rem}\n"] }]
|
|
3462
|
+
}], propDecorators: { color: [{
|
|
3463
|
+
type: Input
|
|
3464
|
+
}], defaultOption: [{
|
|
3465
|
+
type: Input
|
|
3466
|
+
}], disabled: [{
|
|
3467
|
+
type: Input
|
|
3468
|
+
}], icon: [{
|
|
3469
|
+
type: Input
|
|
3470
|
+
}], iconSize: [{
|
|
3471
|
+
type: Input
|
|
3472
|
+
}], label: [{
|
|
3473
|
+
type: Input
|
|
3474
|
+
}], loading: [{
|
|
3475
|
+
type: Input
|
|
3476
|
+
}], options: [{
|
|
3477
|
+
type: Input
|
|
3478
|
+
}], action: [{
|
|
3479
|
+
type: Output
|
|
3480
|
+
}], bodyMouseDown: [{
|
|
3481
|
+
type: HostListener,
|
|
3482
|
+
args: ['body:mousedown', ['$event']]
|
|
3483
|
+
}], bodyMouseUp: [{
|
|
3484
|
+
type: HostListener,
|
|
3485
|
+
args: ['body:mouseup', ['$event']]
|
|
3486
|
+
}], documentKeyDown: [{
|
|
3487
|
+
type: HostListener,
|
|
3488
|
+
args: ['document:keydown.escape', ['$event']]
|
|
3489
|
+
}] } });
|
|
3490
|
+
|
|
3491
|
+
class RibbonComponent {
|
|
3492
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: RibbonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3493
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.6", type: RibbonComponent, isStandalone: true, selector: "lib-ribbon", ngImport: i0, template: "<div>\n <ng-content></ng-content>\n</div>\n\n<ng-content select=\"[right]\"></ng-content>", styles: [":host-context{position:relative;display:flex;flex-direction:row;border-radius:.5rem;border-width:1px;padding:.25rem;border-color:#d1d5dbe6;background-color:#e5e7ebcc;justify-content:space-between}:host-context div{display:inline-flex;gap:.5rem}:host-context ::ng-deep *[right]{display:flex}:host-context ::ng-deep *[right] lib-ribbon-group{margin-right:.5rem;margin-left:0}:host-context ::ng-deep *[right] lib-ribbon-group:first-child{margin-right:0;padding-right:0;padding-left:.5rem}:host-context ::ng-deep *[right] lib-ribbon-group:after{left:-.25rem}:host-context ::ng-deep *[right] lib-ribbon-group lib-ribbon-button .options-dropdown{right:0}\n"] });
|
|
3494
|
+
}
|
|
3495
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: RibbonComponent, decorators: [{
|
|
3496
|
+
type: Component,
|
|
3497
|
+
args: [{ selector: 'lib-ribbon', template: "<div>\n <ng-content></ng-content>\n</div>\n\n<ng-content select=\"[right]\"></ng-content>", styles: [":host-context{position:relative;display:flex;flex-direction:row;border-radius:.5rem;border-width:1px;padding:.25rem;border-color:#d1d5dbe6;background-color:#e5e7ebcc;justify-content:space-between}:host-context div{display:inline-flex;gap:.5rem}:host-context ::ng-deep *[right]{display:flex}:host-context ::ng-deep *[right] lib-ribbon-group{margin-right:.5rem;margin-left:0}:host-context ::ng-deep *[right] lib-ribbon-group:first-child{margin-right:0;padding-right:0;padding-left:.5rem}:host-context ::ng-deep *[right] lib-ribbon-group:after{left:-.25rem}:host-context ::ng-deep *[right] lib-ribbon-group lib-ribbon-button .options-dropdown{right:0}\n"] }]
|
|
3498
|
+
}] });
|
|
3499
|
+
|
|
3500
|
+
class RibbonGroupComponent {
|
|
3501
|
+
//#region ViewChilds, Inputs, Outputs
|
|
3502
|
+
children;
|
|
3503
|
+
label = '';
|
|
3504
|
+
//#endregion
|
|
3505
|
+
//#region Host listeners
|
|
3506
|
+
//#endregion
|
|
3507
|
+
//#region Variables
|
|
3508
|
+
//#endregion
|
|
3509
|
+
//#region Properties
|
|
3510
|
+
get hasChildren() {
|
|
3511
|
+
return this.children?.some(x => x.visible) ?? false;
|
|
3512
|
+
}
|
|
3513
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: RibbonGroupComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3514
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.6", type: RibbonGroupComponent, isStandalone: true, selector: "lib-ribbon-group", inputs: { label: "label" }, host: { properties: { "class.hidden": "!hasChildren" } }, queries: [{ propertyName: "children", predicate: RibbonGroupChild, descendants: true }], ngImport: i0, template: "<div class=\"content\">\n <ng-content></ng-content>\n</div>\n\n<div class=\"label\">\n <span>{{ label }}</span>\n</div>", styles: [":host-context{position:relative;padding-right:.5rem}:host-context:after{position:absolute;right:-.25rem;top:.25rem;bottom:.25rem;width:1px;--tw-content: \"\";content:var(--tw-content);background-color:#9ca3af99}:host-context .content{display:flex;flex-direction:row;flex-wrap:nowrap}:host-context .label{-webkit-user-select:none;user-select:none;padding-top:.05rem;text-align:center;font-size:.875rem;line-height:1.25rem;--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity, 1))}\n"] });
|
|
3515
|
+
}
|
|
3516
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: RibbonGroupComponent, decorators: [{
|
|
3517
|
+
type: Component,
|
|
3518
|
+
args: [{ selector: 'lib-ribbon-group', host: { '[class.hidden]': '!hasChildren' }, template: "<div class=\"content\">\n <ng-content></ng-content>\n</div>\n\n<div class=\"label\">\n <span>{{ label }}</span>\n</div>", styles: [":host-context{position:relative;padding-right:.5rem}:host-context:after{position:absolute;right:-.25rem;top:.25rem;bottom:.25rem;width:1px;--tw-content: \"\";content:var(--tw-content);background-color:#9ca3af99}:host-context .content{display:flex;flex-direction:row;flex-wrap:nowrap}:host-context .label{-webkit-user-select:none;user-select:none;padding-top:.05rem;text-align:center;font-size:.875rem;line-height:1.25rem;--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity, 1))}\n"] }]
|
|
3519
|
+
}], propDecorators: { children: [{
|
|
3520
|
+
type: ContentChildren,
|
|
3521
|
+
args: [RibbonGroupChild, { descendants: true }]
|
|
3522
|
+
}], label: [{
|
|
3523
|
+
type: Input
|
|
3524
|
+
}] } });
|
|
3525
|
+
|
|
3526
|
+
class EnumTranslatePipe {
|
|
3527
|
+
//#region ViewChilds, Inputs, Outputs
|
|
3528
|
+
//#endregion
|
|
3529
|
+
//#region Variables
|
|
3530
|
+
translate = inject(TranslateService);
|
|
3531
|
+
//#endregion
|
|
3532
|
+
//#region Properties
|
|
3533
|
+
//#endregion
|
|
3534
|
+
//#region Constructor and Angular life cycle methods
|
|
3535
|
+
//#endregion
|
|
3536
|
+
//#region Event handlers
|
|
3537
|
+
//#endregion
|
|
3538
|
+
//#region Public methods
|
|
3539
|
+
transform(enumType) {
|
|
3540
|
+
return Object.keys(enumType)
|
|
3541
|
+
.filter(key => isNaN(Number(key)))
|
|
3542
|
+
.map(key => ({
|
|
3543
|
+
value: enumType[key],
|
|
3544
|
+
display: this.translate.get(key),
|
|
3545
|
+
}));
|
|
3546
|
+
}
|
|
3547
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: EnumTranslatePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
3548
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.1.6", ngImport: i0, type: EnumTranslatePipe, isStandalone: true, name: "enumTranslate" });
|
|
3549
|
+
}
|
|
3550
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: EnumTranslatePipe, decorators: [{
|
|
3551
|
+
type: Pipe,
|
|
3552
|
+
args: [{
|
|
3553
|
+
name: 'enumTranslate'
|
|
3554
|
+
}]
|
|
3555
|
+
}] });
|
|
3556
|
+
|
|
3557
|
+
class ReplaceManyPipe {
|
|
3558
|
+
//#region ViewChilds, Inputs, Outputs
|
|
3559
|
+
//#endregion
|
|
3560
|
+
//#region Variables
|
|
3561
|
+
//#endregion
|
|
3562
|
+
//#region Properties
|
|
3563
|
+
//#endregion
|
|
3564
|
+
//#region Constructor and Angular life cycle methods
|
|
3565
|
+
//#endregion
|
|
3566
|
+
//#region Event handlers
|
|
3567
|
+
//#endregion
|
|
3568
|
+
//#region Public methods
|
|
3569
|
+
transform(message, replaceArgs) {
|
|
3570
|
+
if (replaceArgs) {
|
|
3571
|
+
for (const [key, value] of Object.entries(replaceArgs)) {
|
|
3572
|
+
message = message.replace(key, value ?? '');
|
|
3573
|
+
}
|
|
3574
|
+
}
|
|
3575
|
+
return message;
|
|
3576
|
+
}
|
|
3577
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: ReplaceManyPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
3578
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.1.6", ngImport: i0, type: ReplaceManyPipe, isStandalone: true, name: "replaceMany" });
|
|
3579
|
+
}
|
|
3580
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: ReplaceManyPipe, decorators: [{
|
|
3581
|
+
type: Pipe,
|
|
3582
|
+
args: [{
|
|
3583
|
+
name: 'replaceMany'
|
|
3584
|
+
}]
|
|
3585
|
+
}] });
|
|
3586
|
+
|
|
3587
|
+
class ReplacePipe {
|
|
3588
|
+
//#region ViewChilds, Inputs, Outputs
|
|
3589
|
+
//#endregion
|
|
3590
|
+
//#region Variables
|
|
3591
|
+
//#endregion
|
|
3592
|
+
//#region Properties
|
|
3593
|
+
//#endregion
|
|
3594
|
+
//#region Constructor and Angular life cycle methods
|
|
3595
|
+
//#endregion
|
|
3596
|
+
//#region Event handlers
|
|
3597
|
+
//#endregion
|
|
3598
|
+
//#region Public methods
|
|
3599
|
+
transform(message, searchValue, replaceValue) {
|
|
3600
|
+
return message.replace(searchValue, replaceValue ?? '');
|
|
3601
|
+
}
|
|
3602
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: ReplacePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
3603
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.1.6", ngImport: i0, type: ReplacePipe, isStandalone: true, name: "replace" });
|
|
3604
|
+
}
|
|
3605
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: ReplacePipe, decorators: [{
|
|
3606
|
+
type: Pipe,
|
|
3607
|
+
args: [{
|
|
3608
|
+
name: 'replace'
|
|
3609
|
+
}]
|
|
3610
|
+
}] });
|
|
3611
|
+
|
|
3612
|
+
/**
|
|
3613
|
+
* @deprecated Use standalone component imports instead of LibraryModule.
|
|
3614
|
+
* Import individual components directly in your component's `imports` array.
|
|
3615
|
+
*/
|
|
3616
|
+
class LibraryModule {
|
|
3617
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: LibraryModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
3618
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.1.6", ngImport: i0, type: LibraryModule, imports: [CatalogSelectComponent, DataGridComponent, DataGridRowComponent, FormInputComponent, FormInputGroupComponent, FormGroupComponent, GroupAccordionComponent, GroupContainerComponent, GroupScrollSpyComponent, SidebarComponent, ModalComponent, MultiEditorComponent, MultiSelectComponent, MultiSelectResultGridComponent, RibbonComponent, RibbonButtonComponent, RibbonGroupComponent, ScrollSpyDirective, EnumTranslatePipe, ReplacePipe, ReplaceManyPipe], exports: [CatalogSelectComponent, DataGridComponent, DataGridRowComponent, FormInputComponent, FormInputGroupComponent, FormGroupComponent, GroupAccordionComponent, GroupContainerComponent, GroupScrollSpyComponent, SidebarComponent, ModalComponent, MultiEditorComponent, MultiSelectComponent, MultiSelectResultGridComponent, RibbonComponent, RibbonButtonComponent, RibbonGroupComponent, ScrollSpyDirective, EnumTranslatePipe, ReplacePipe, ReplaceManyPipe] });
|
|
3619
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: LibraryModule, imports: [CatalogSelectComponent,
|
|
3620
|
+
DataGridComponent,
|
|
3621
|
+
DataGridRowComponent,
|
|
3622
|
+
FormInputComponent,
|
|
3623
|
+
FormInputGroupComponent,
|
|
3624
|
+
SidebarComponent,
|
|
3625
|
+
MultiEditorComponent,
|
|
3626
|
+
MultiSelectComponent,
|
|
3627
|
+
MultiSelectResultGridComponent] });
|
|
3628
|
+
}
|
|
3629
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: LibraryModule, decorators: [{
|
|
3630
|
+
type: NgModule,
|
|
3631
|
+
args: [{
|
|
3632
|
+
declarations: [],
|
|
3633
|
+
imports: [
|
|
3634
|
+
CatalogSelectComponent,
|
|
3635
|
+
DataGridComponent,
|
|
3636
|
+
DataGridRowComponent,
|
|
3637
|
+
FormInputComponent,
|
|
3638
|
+
FormInputGroupComponent,
|
|
3639
|
+
FormGroupComponent,
|
|
3640
|
+
GroupAccordionComponent,
|
|
3641
|
+
GroupContainerComponent,
|
|
3642
|
+
GroupScrollSpyComponent,
|
|
3643
|
+
SidebarComponent,
|
|
3644
|
+
ModalComponent,
|
|
3645
|
+
MultiEditorComponent,
|
|
3646
|
+
MultiSelectComponent,
|
|
3647
|
+
MultiSelectResultGridComponent,
|
|
3648
|
+
RibbonComponent,
|
|
3649
|
+
RibbonButtonComponent,
|
|
3650
|
+
RibbonGroupComponent,
|
|
3651
|
+
ScrollSpyDirective,
|
|
3652
|
+
EnumTranslatePipe,
|
|
3653
|
+
ReplacePipe,
|
|
3654
|
+
ReplaceManyPipe,
|
|
3655
|
+
],
|
|
3656
|
+
exports: [
|
|
3657
|
+
CatalogSelectComponent,
|
|
3658
|
+
DataGridComponent,
|
|
3659
|
+
DataGridRowComponent,
|
|
3660
|
+
FormInputComponent,
|
|
3661
|
+
FormInputGroupComponent,
|
|
3662
|
+
FormGroupComponent,
|
|
3663
|
+
GroupAccordionComponent,
|
|
3664
|
+
GroupContainerComponent,
|
|
3665
|
+
GroupScrollSpyComponent,
|
|
3666
|
+
SidebarComponent,
|
|
3667
|
+
ModalComponent,
|
|
3668
|
+
MultiEditorComponent,
|
|
3669
|
+
MultiSelectComponent,
|
|
3670
|
+
MultiSelectResultGridComponent,
|
|
3671
|
+
RibbonComponent,
|
|
3672
|
+
RibbonButtonComponent,
|
|
3673
|
+
RibbonGroupComponent,
|
|
3674
|
+
ScrollSpyDirective,
|
|
3675
|
+
EnumTranslatePipe,
|
|
3676
|
+
ReplacePipe,
|
|
3677
|
+
ReplaceManyPipe,
|
|
3678
|
+
]
|
|
3679
|
+
}]
|
|
3680
|
+
}] });
|
|
3681
|
+
|
|
3682
|
+
class DataGridConfigsProvider extends GridConfigsProvider {
|
|
3683
|
+
//#region ViewChilds, Inputs, Outputs
|
|
3684
|
+
//#endregion
|
|
3685
|
+
//#region Variables
|
|
3686
|
+
//#endregion
|
|
3687
|
+
//#region Properties
|
|
3688
|
+
//#endregion
|
|
3689
|
+
//#region Constructor and Angular life cycle methods
|
|
3690
|
+
constructor() {
|
|
3691
|
+
super();
|
|
3692
|
+
this._configs =
|
|
3693
|
+
{
|
|
3694
|
+
...this._configs,
|
|
3695
|
+
multiSelect: false,
|
|
3696
|
+
multiSelectSize: 'minmax(1.5rem, min-content)',
|
|
3697
|
+
};
|
|
3698
|
+
}
|
|
3699
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: DataGridConfigsProvider, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
3700
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: DataGridConfigsProvider });
|
|
3701
|
+
}
|
|
3702
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: DataGridConfigsProvider, decorators: [{
|
|
3703
|
+
type: Injectable
|
|
3704
|
+
}], ctorParameters: () => [] });
|
|
3705
|
+
|
|
3706
|
+
class DateValidators {
|
|
3707
|
+
//#region Public methods
|
|
3708
|
+
static greaterThanControl(controlName) {
|
|
3709
|
+
return (control) => {
|
|
3710
|
+
const compareControl = control.parent?.get(controlName);
|
|
3711
|
+
if (!!control.value && !!compareControl?.value && new Date(control.value) <= new Date(compareControl?.value)) {
|
|
3712
|
+
return { 'greaterThanControl': true };
|
|
3713
|
+
}
|
|
3714
|
+
return null;
|
|
3715
|
+
};
|
|
3716
|
+
}
|
|
3717
|
+
static greaterThanOrEqualControl(controlName) {
|
|
3718
|
+
return (control) => {
|
|
3719
|
+
const compareControl = control.parent?.get(controlName);
|
|
3720
|
+
if (!!control.value && !!compareControl?.value && new Date(control.value) < new Date(compareControl?.value)) {
|
|
3721
|
+
return { 'greaterThanOrEqualControl': true };
|
|
3722
|
+
}
|
|
3723
|
+
return null;
|
|
3724
|
+
};
|
|
3725
|
+
}
|
|
3726
|
+
static greaterThanOrEqualToday(control) {
|
|
3727
|
+
let today = new Date();
|
|
3728
|
+
if (!!control.value && new Date(control.value) < today) {
|
|
3729
|
+
return { 'greaterThanOrEqualToday': true };
|
|
3730
|
+
}
|
|
3731
|
+
return null;
|
|
3732
|
+
}
|
|
3733
|
+
static greaterThanToday(control) {
|
|
3734
|
+
let today = new Date();
|
|
3735
|
+
if (!!control.value && new Date(control.value) <= today) {
|
|
3736
|
+
return { 'greaterThanToday': true };
|
|
3737
|
+
}
|
|
3738
|
+
return null;
|
|
3739
|
+
}
|
|
3740
|
+
static lessThanControl(controlName) {
|
|
3741
|
+
return (control) => {
|
|
3742
|
+
const compareControl = control.parent?.get(controlName);
|
|
3743
|
+
if (!!control.value && !!compareControl?.value && new Date(control.value) >= new Date(compareControl?.value)) {
|
|
3744
|
+
return { 'lessThanControl': true };
|
|
3745
|
+
}
|
|
3746
|
+
return null;
|
|
3747
|
+
};
|
|
3748
|
+
}
|
|
3749
|
+
static lessThanOrEqualControl(controlName) {
|
|
3750
|
+
return (control) => {
|
|
3751
|
+
const compareControl = control.parent?.get(controlName);
|
|
3752
|
+
if (!!control.value && !!compareControl?.value && new Date(control.value) > new Date(compareControl?.value)) {
|
|
3753
|
+
return { 'lessThanOrEqualControl': true };
|
|
3754
|
+
}
|
|
3755
|
+
return null;
|
|
3756
|
+
};
|
|
3757
|
+
}
|
|
3758
|
+
static lessThanOrEqualToday(control) {
|
|
3759
|
+
let today = new Date();
|
|
3760
|
+
if (!!control.value && new Date(control.value) > today) {
|
|
3761
|
+
return { 'lessThanOrEqualToday': true };
|
|
3762
|
+
}
|
|
3763
|
+
return null;
|
|
3764
|
+
}
|
|
3765
|
+
static lessThanToday(control) {
|
|
3766
|
+
let today = new Date();
|
|
3767
|
+
if (!!control.value && new Date(control.value) >= today) {
|
|
3768
|
+
return { 'lessThanToday': true };
|
|
3769
|
+
}
|
|
3770
|
+
return null;
|
|
3771
|
+
}
|
|
3772
|
+
static maxDate(maxDate) {
|
|
3773
|
+
return (control) => {
|
|
3774
|
+
if (!!control.value && new Date(control.value) > maxDate) {
|
|
3775
|
+
return { 'maxDate': true };
|
|
3776
|
+
}
|
|
3777
|
+
return null;
|
|
3778
|
+
};
|
|
3779
|
+
}
|
|
3780
|
+
static minDate(minDate) {
|
|
3781
|
+
return (control) => {
|
|
3782
|
+
if (!!control.value && new Date(control.value) < minDate) {
|
|
3783
|
+
return { 'minDate': true };
|
|
3784
|
+
}
|
|
3785
|
+
return null;
|
|
3786
|
+
};
|
|
3787
|
+
}
|
|
3788
|
+
}
|
|
3789
|
+
|
|
3790
|
+
/**
|
|
3791
|
+
* Generated bundle index. Do not edit.
|
|
3792
|
+
*/
|
|
3793
|
+
|
|
3794
|
+
export { BaseComponent, BaseDataset, CatalogSelectComponent, CatalogService, DataGridComponent, DataGridConfigsProvider, DataGridDataset, DataGridRowComponent, DataProviderService, DateHelpers, DateValidators, EnumTranslatePipe, FormGroupComponent, FormGroupService, FormInputComponent, FormInputGroupComponent, FormService, GridConfigsProvider, GridDataset, GroupAccordionComponent, GroupContainerComponent, GroupScrollSpyComponent, GuidHelper, LibraryModule, ModalComponent, MultiEditorComponent, MultiEditorDataset, MultiSelectComponent, MultiSelectResultDataset, MultiSelectResultGridComponent, ReplaceManyPipe, ReplacePipe, RibbonButtonComponent, RibbonComponent, RibbonGroupChild, RibbonGroupComponent, RouterFormatter, SIDEBAR_CONFIGS, ScrollSpyDirective, SidebarComponent, SidebarConfigs, SidebarMenu, SidebarService };
|
|
3795
|
+
//# sourceMappingURL=zambon-dev-library.mjs.map
|