@smartsoft001/crud-shell-angular 2.124.0 → 2.126.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.
|
@@ -1,57 +1,26 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { Injectable, inject, ElementRef,
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
2
|
+
import { Injectable, inject, ElementRef, Injector, Directive, ChangeDetectionStrategy, Component, InjectionToken, DestroyRef, signal, input, computed, Pipe, NgModule, ChangeDetectorRef, viewChild, viewChildren, output, effect } from '@angular/core';
|
|
3
|
+
import { toSignal, toObservable, takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
4
|
+
import { map, first, filter, take } from 'rxjs/operators';
|
|
5
|
+
import { NgrxStoreService, PaginationMode, BaseComponent as BaseComponent$1, PopoverService, StyleService, ButtonComponent, DateEditComponent, InputFlagComponent, InputIntComponent, InputRadioComponent, InputTextComponent, MenuService, FormComponent, ListComponent as ListComponent$1, IModelLabelProvider, SharedModule, DetailsComponent, AuthService, CreateDynamicComponent, DynamicComponentLoader, ToastService, DetailsService, DynamicContentDirective, PageComponent, HardwareService, ListMode, FILE_SERVICE_CONFIG } from '@smartsoft001/angular';
|
|
6
|
+
import 'reflect-metadata';
|
|
5
7
|
import * as i1 from '@ngrx/store';
|
|
6
8
|
import { createFeatureSelector, createSelector, select as select$1 } from '@ngrx/store';
|
|
7
|
-
import {
|
|
9
|
+
import { HttpClient } from '@angular/common/http';
|
|
10
|
+
import { firstValueFrom, Subscription, BehaviorSubject, combineLatest, Subject } from 'rxjs';
|
|
8
11
|
import { FieldType, getModelOptions, getModelFieldsWithOptions } from '@smartsoft001/models';
|
|
9
12
|
import { TranslateService, TranslatePipe } from '@ngx-translate/core';
|
|
10
13
|
import { __decorate, __metadata } from 'tslib';
|
|
14
|
+
import * as i1$1 from '@angular/forms';
|
|
15
|
+
import { UntypedFormControl, FormsModule, ReactiveFormsModule, UntypedFormGroup, UntypedFormArray } from '@angular/forms';
|
|
11
16
|
import { Debounce, debounce } from 'lodash-decorators';
|
|
12
|
-
import { FormsModule, UntypedFormControl, UntypedFormGroup, UntypedFormArray } from '@angular/forms';
|
|
13
17
|
import moment from 'moment';
|
|
14
|
-
import { GuidService, SpecificationService } from '@smartsoft001/utils';
|
|
15
|
-
import { Subscription, firstValueFrom, BehaviorSubject, combineLatest, Subject } from 'rxjs';
|
|
16
|
-
import { NgComponentOutlet, NgClass, CommonModule, NgTemplateOutlet, Location } from '@angular/common';
|
|
17
18
|
import * as _ from 'lodash';
|
|
19
|
+
import { NgComponentOutlet, CommonModule, NgTemplateOutlet, Location } from '@angular/common';
|
|
18
20
|
import { DynamicIoDirective, DynamicIoModule } from 'ng-dynamic-component';
|
|
19
|
-
import { HttpClient } from '@angular/common/http';
|
|
20
|
-
import 'reflect-metadata';
|
|
21
21
|
import * as i3 from '@angular/router';
|
|
22
22
|
import { Router, ActivatedRoute, RouterModule } from '@angular/router';
|
|
23
|
-
|
|
24
|
-
class CrudConfig {
|
|
25
|
-
apiUrl;
|
|
26
|
-
entity;
|
|
27
|
-
type;
|
|
28
|
-
reducerFactory;
|
|
29
|
-
baseQuery;
|
|
30
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudConfig, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
31
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudConfig });
|
|
32
|
-
}
|
|
33
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudConfig, decorators: [{
|
|
34
|
-
type: Injectable
|
|
35
|
-
}] });
|
|
36
|
-
class CrudFullConfig extends CrudConfig {
|
|
37
|
-
title;
|
|
38
|
-
details;
|
|
39
|
-
edit;
|
|
40
|
-
add;
|
|
41
|
-
remove;
|
|
42
|
-
search;
|
|
43
|
-
export;
|
|
44
|
-
pagination;
|
|
45
|
-
sort;
|
|
46
|
-
list;
|
|
47
|
-
buttons;
|
|
48
|
-
inputComponents;
|
|
49
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudFullConfig, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
|
|
50
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudFullConfig });
|
|
51
|
-
}
|
|
52
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudFullConfig, decorators: [{
|
|
53
|
-
type: Injectable
|
|
54
|
-
}] });
|
|
23
|
+
import { SpecificationService } from '@smartsoft001/utils';
|
|
55
24
|
|
|
56
25
|
/*
|
|
57
26
|
* Create
|
|
@@ -277,6 +246,42 @@ const deleteFailure = function (entity, id, error) {
|
|
|
277
246
|
};
|
|
278
247
|
};
|
|
279
248
|
|
|
249
|
+
class CrudConfig {
|
|
250
|
+
apiUrl;
|
|
251
|
+
entity;
|
|
252
|
+
type;
|
|
253
|
+
reducerFactory;
|
|
254
|
+
baseQuery;
|
|
255
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudConfig, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
256
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudConfig });
|
|
257
|
+
}
|
|
258
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudConfig, decorators: [{
|
|
259
|
+
type: Injectable
|
|
260
|
+
}] });
|
|
261
|
+
class CrudFullConfig extends CrudConfig {
|
|
262
|
+
title;
|
|
263
|
+
details;
|
|
264
|
+
edit;
|
|
265
|
+
add;
|
|
266
|
+
remove;
|
|
267
|
+
search;
|
|
268
|
+
export;
|
|
269
|
+
pagination;
|
|
270
|
+
sort;
|
|
271
|
+
list;
|
|
272
|
+
buttons;
|
|
273
|
+
inputComponents;
|
|
274
|
+
// Declarative tier-2 styling surface (FRA-293 Faza 2).
|
|
275
|
+
// Deep threading into IListOptions/IPageOptions lands in Phase 3.
|
|
276
|
+
cssClass;
|
|
277
|
+
variant;
|
|
278
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudFullConfig, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
|
|
279
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudFullConfig });
|
|
280
|
+
}
|
|
281
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudFullConfig, decorators: [{
|
|
282
|
+
type: Injectable
|
|
283
|
+
}] });
|
|
284
|
+
|
|
280
285
|
const getCrudState = (entity) => createFeatureSelector(entity);
|
|
281
286
|
const getCrudSelected = (entity) => createSelector(getCrudState(entity), (state) => state.selected);
|
|
282
287
|
const getCrudMultiSelected = (entity) => createSelector(getCrudState(entity), (state) => state.multiSelected);
|
|
@@ -287,108 +292,418 @@ const getCrudLoaded = (entity) => createSelector(getCrudState(entity), (state) =
|
|
|
287
292
|
const getCrudFilter = (entity) => createSelector(getCrudState(entity), (state) => state?.filter);
|
|
288
293
|
const getCrudError = (entity) => createSelector(getCrudState(entity), (state) => state?.error);
|
|
289
294
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
295
|
+
// NOTE: Restored 1:1 from the legacy library (FRA-293 / GAP-01).
|
|
296
|
+
// This is an inert stub: both classes are empty injectables. The original
|
|
297
|
+
// real-time implementation never existed as live code — the constructor below
|
|
298
|
+
// (which would have extended ngx-socket-io's `Socket`) was always commented out.
|
|
299
|
+
// `NotSocketService` is the null-object fallback used when `options.socket` is off.
|
|
300
|
+
class SocketService {
|
|
301
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: SocketService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
302
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: SocketService });
|
|
303
|
+
}
|
|
304
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: SocketService, decorators: [{
|
|
305
|
+
type: Injectable
|
|
306
|
+
}] });
|
|
307
|
+
class NotSocketService {
|
|
308
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: NotSocketService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
309
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: NotSocketService });
|
|
310
|
+
}
|
|
311
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: NotSocketService, decorators: [{
|
|
312
|
+
type: Injectable
|
|
313
|
+
}] });
|
|
314
|
+
|
|
315
|
+
class CrudService {
|
|
316
|
+
config = inject((CrudConfig));
|
|
317
|
+
http = inject(HttpClient);
|
|
318
|
+
socket = inject((SocketService), { optional: true });
|
|
319
|
+
// changes(criteria: { id?: string } = {}): Observable<ItemChangedData> {
|
|
320
|
+
// this.socket.emit('changes', criteria);
|
|
321
|
+
// return this.socket.fromEvent('changes');
|
|
322
|
+
// }
|
|
323
|
+
_formatMap = {
|
|
324
|
+
csv: 'text/csv',
|
|
325
|
+
xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
|
326
|
+
};
|
|
319
327
|
create(item) {
|
|
320
|
-
|
|
328
|
+
return firstValueFrom(this.http
|
|
329
|
+
.post(this.config.apiUrl, item, { observe: 'response' })
|
|
330
|
+
.pipe(map((response) => {
|
|
331
|
+
const location = response.headers['Location'];
|
|
332
|
+
if (!location)
|
|
333
|
+
return null;
|
|
334
|
+
const array = location.split('/');
|
|
335
|
+
return array[array.length - 1];
|
|
336
|
+
})));
|
|
321
337
|
}
|
|
322
338
|
createMany(items, options) {
|
|
323
|
-
this.
|
|
324
|
-
}
|
|
325
|
-
read(filter = {}) {
|
|
326
|
-
let baseQuery = [];
|
|
327
|
-
if (this.config.baseQuery) {
|
|
328
|
-
baseQuery = this.config.baseQuery;
|
|
329
|
-
}
|
|
330
|
-
const fullFilter = {
|
|
331
|
-
...(filter ? filter : {}),
|
|
332
|
-
query: filter && filter.query ? filter.query : baseQuery,
|
|
333
|
-
};
|
|
334
|
-
this.store.dispatch(read(this.config.entity, fullFilter));
|
|
335
|
-
}
|
|
336
|
-
clear() {
|
|
337
|
-
this.store.dispatch(clear(this.config.entity));
|
|
339
|
+
return firstValueFrom(this.http.post(this.config.apiUrl + '/bulk?mode=' + options.mode, items));
|
|
338
340
|
}
|
|
339
|
-
|
|
340
|
-
this.
|
|
341
|
+
getById(id) {
|
|
342
|
+
return firstValueFrom(this.http.get(this.config.apiUrl + '/' + id));
|
|
341
343
|
}
|
|
342
|
-
|
|
343
|
-
this.
|
|
344
|
+
getList(filter = null) {
|
|
345
|
+
return firstValueFrom(this.http.get(this.config.apiUrl + this.getQuery(filter)));
|
|
344
346
|
}
|
|
345
|
-
|
|
346
|
-
|
|
347
|
+
exportList(filter = null, format) {
|
|
348
|
+
if (!format) {
|
|
349
|
+
format = 'csv';
|
|
350
|
+
}
|
|
351
|
+
if (format === 'xlsx') {
|
|
352
|
+
return firstValueFrom(this.http
|
|
353
|
+
.get(this.config.apiUrl + this.getQuery(filter), {
|
|
354
|
+
headers: {
|
|
355
|
+
'Content-Type': this._formatMap[format],
|
|
356
|
+
},
|
|
357
|
+
observe: 'response',
|
|
358
|
+
reportProgress: false,
|
|
359
|
+
responseType: 'blob',
|
|
360
|
+
})
|
|
361
|
+
.pipe(map((res) => {
|
|
362
|
+
const downloadLink = document.createElement('a');
|
|
363
|
+
const blob = res.body;
|
|
364
|
+
downloadLink.href = URL.createObjectURL(blob);
|
|
365
|
+
downloadLink.download = 'data.' + format;
|
|
366
|
+
document.body.appendChild(downloadLink);
|
|
367
|
+
downloadLink.click();
|
|
368
|
+
document.body.removeChild(downloadLink);
|
|
369
|
+
})));
|
|
370
|
+
}
|
|
371
|
+
return firstValueFrom(this.http
|
|
372
|
+
.get(this.config.apiUrl + this.getQuery(filter), {
|
|
373
|
+
headers: {
|
|
374
|
+
'Content-Type': this._formatMap[format],
|
|
375
|
+
},
|
|
376
|
+
responseType: 'text',
|
|
377
|
+
})
|
|
378
|
+
.pipe(map((res) => {
|
|
379
|
+
const downloadLink = document.createElement('a');
|
|
380
|
+
const blob = new Blob(['\ufeff', res]);
|
|
381
|
+
downloadLink.href = URL.createObjectURL(blob);
|
|
382
|
+
downloadLink.download = 'data.' + format;
|
|
383
|
+
document.body.appendChild(downloadLink);
|
|
384
|
+
downloadLink.click();
|
|
385
|
+
document.body.removeChild(downloadLink);
|
|
386
|
+
})));
|
|
347
387
|
}
|
|
348
388
|
update(item) {
|
|
349
|
-
this.
|
|
350
|
-
}
|
|
351
|
-
export(filter = {}, format) {
|
|
352
|
-
this.getStore().dispatch(exportList(this.config.entity, filter, format));
|
|
389
|
+
return firstValueFrom(this.http.put(this.config.apiUrl + '/' + item.id, item));
|
|
353
390
|
}
|
|
354
391
|
updatePartial(item) {
|
|
355
|
-
this.
|
|
392
|
+
return firstValueFrom(this.http.patch(this.config.apiUrl + '/' + item.id, item));
|
|
356
393
|
}
|
|
357
394
|
updatePartialMany(items) {
|
|
358
|
-
|
|
395
|
+
const updatePromises = items.map((item) => {
|
|
396
|
+
return this.updatePartial(item);
|
|
397
|
+
});
|
|
398
|
+
return Promise.all(updatePromises);
|
|
359
399
|
}
|
|
360
400
|
delete(id) {
|
|
361
|
-
this.
|
|
401
|
+
return firstValueFrom(this.http.delete(this.config.apiUrl + '/' + id));
|
|
362
402
|
}
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
403
|
+
getQuery(filter) {
|
|
404
|
+
let query = '';
|
|
405
|
+
if (filter && filter.searchText) {
|
|
406
|
+
query += '&$search=' + filter.searchText;
|
|
407
|
+
}
|
|
408
|
+
if (filter && filter.limit) {
|
|
409
|
+
query += `&limit=${filter.limit}&offset=${filter.offset ? filter.offset : 0}`;
|
|
410
|
+
}
|
|
411
|
+
if (filter && filter.sortBy) {
|
|
412
|
+
query += `&sort=${(filter.sortDesc ? '-' : '') + filter.sortBy}`;
|
|
413
|
+
}
|
|
414
|
+
if (filter && filter.query) {
|
|
415
|
+
filter.query.forEach((q) => {
|
|
416
|
+
if (q.value &&
|
|
417
|
+
typeof q.value === 'string' &&
|
|
418
|
+
q.value.match(/^-?\d+$/) &&
|
|
419
|
+
q.value[0] !== "'" &&
|
|
420
|
+
q.value[0] !== '"') {
|
|
421
|
+
query += '&' + q.key + q.type + `'${q.value}'`;
|
|
422
|
+
}
|
|
423
|
+
else {
|
|
424
|
+
query += '&' + q.key + q.type + q.value;
|
|
425
|
+
}
|
|
426
|
+
});
|
|
427
|
+
}
|
|
428
|
+
return query ? '?' + query.replace('&', '') : '';
|
|
367
429
|
}
|
|
368
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type:
|
|
369
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type:
|
|
430
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
431
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudService });
|
|
370
432
|
}
|
|
371
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type:
|
|
433
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudService, decorators: [{
|
|
372
434
|
type: Injectable
|
|
373
|
-
}]
|
|
435
|
+
}] });
|
|
374
436
|
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
437
|
+
class CrudEffects {
|
|
438
|
+
actions$;
|
|
439
|
+
service;
|
|
440
|
+
config;
|
|
441
|
+
store;
|
|
442
|
+
state;
|
|
443
|
+
constructor(actions$, service, config, store, state) {
|
|
444
|
+
this.actions$ = actions$;
|
|
445
|
+
this.service = service;
|
|
446
|
+
this.config = config;
|
|
447
|
+
this.store = store;
|
|
448
|
+
this.state = state;
|
|
449
|
+
}
|
|
450
|
+
init() {
|
|
451
|
+
const metadata = Reflect.getMetadata(this.config.entity, CrudEffects);
|
|
452
|
+
if (metadata)
|
|
453
|
+
return;
|
|
454
|
+
Reflect.defineMetadata(this.config.entity, true, CrudEffects);
|
|
455
|
+
this.actions$.subscribe((action) => {
|
|
456
|
+
switch (action.type) {
|
|
457
|
+
case `[${this.config.entity}] Create`:
|
|
458
|
+
this.service
|
|
459
|
+
.create(action.item)
|
|
460
|
+
.then(() => this.store.dispatch(createSuccess(this.config.entity, action.item)))
|
|
461
|
+
.catch((error) => {
|
|
462
|
+
this.store.dispatch(createFailure(this.config.entity, action.item, error));
|
|
463
|
+
});
|
|
464
|
+
break;
|
|
465
|
+
case `[${this.config.entity}] Create Success`: {
|
|
466
|
+
const createState = this.state.getValue()[this.config.entity];
|
|
467
|
+
this.store.dispatch(read(this.config.entity, createState?.filter ? { ...createState.filter, offset: 0 } : null));
|
|
468
|
+
break;
|
|
469
|
+
}
|
|
470
|
+
case `[${this.config.entity}] Create Many`:
|
|
471
|
+
this.service
|
|
472
|
+
.createMany(action.data.items, action.data.options)
|
|
473
|
+
.then(() => this.store.dispatch(createManySuccess(this.config.entity, {
|
|
474
|
+
items: action.data.items,
|
|
475
|
+
options: action.data.options,
|
|
476
|
+
})))
|
|
477
|
+
.catch((error) => {
|
|
478
|
+
this.store.dispatch(createManyFailure(this.config.entity, {
|
|
479
|
+
items: action.data.items,
|
|
480
|
+
options: action.data.options,
|
|
481
|
+
}, error));
|
|
482
|
+
});
|
|
483
|
+
break;
|
|
484
|
+
case `[${this.config.entity}] Create Many Success`: {
|
|
485
|
+
const createManyState = this.state.getValue()[this.config.entity];
|
|
486
|
+
this.store.dispatch(read(this.config.entity, createManyState?.filter
|
|
487
|
+
? { ...createManyState.filter, offset: 0 }
|
|
488
|
+
: null));
|
|
489
|
+
break;
|
|
490
|
+
}
|
|
491
|
+
case `[${this.config.entity}] Read`:
|
|
492
|
+
this.service
|
|
493
|
+
.getList(action?.filter)
|
|
494
|
+
.then((result) => this.store.dispatch(readSuccess(this.config.entity, action?.filter, result)))
|
|
495
|
+
.catch((error) => {
|
|
496
|
+
this.store.dispatch(readFailure(this.config.entity, action?.filter, error));
|
|
497
|
+
});
|
|
498
|
+
break;
|
|
499
|
+
case `[${this.config.entity}] Export`:
|
|
500
|
+
this.service
|
|
501
|
+
.exportList(action?.filter, action.format)
|
|
502
|
+
.then(() => this.store.dispatch(exportListSuccess(this.config.entity, action?.filter)))
|
|
503
|
+
.catch((error) => {
|
|
504
|
+
this.store.dispatch(exportListFailure(this.config.entity, action?.filter, error));
|
|
505
|
+
});
|
|
506
|
+
break;
|
|
507
|
+
case `[${this.config.entity}] Select`:
|
|
508
|
+
this.service
|
|
509
|
+
.getById(action.id)
|
|
510
|
+
.then((result) => this.store.dispatch(selectSuccess(this.config.entity, action.id, result)))
|
|
511
|
+
.catch((error) => {
|
|
512
|
+
this.store.dispatch(selectFailure(this.config.entity, action.id, error));
|
|
513
|
+
});
|
|
514
|
+
break;
|
|
515
|
+
case `[${this.config.entity}] Update`:
|
|
516
|
+
this.service
|
|
517
|
+
.updatePartial(action.item)
|
|
518
|
+
.then(() => this.store.dispatch(updateSuccess(this.config.entity, action.item)))
|
|
519
|
+
.catch((error) => {
|
|
520
|
+
this.store.dispatch(updateFailure(this.config.entity, action.item, error));
|
|
521
|
+
this.store.dispatch(read(this.config.entity));
|
|
522
|
+
});
|
|
523
|
+
break;
|
|
524
|
+
case `[${this.config.entity}] Update Success`:
|
|
525
|
+
this.store
|
|
526
|
+
.pipe(select$1(getCrudFilter(this.config.entity)), first())
|
|
527
|
+
.subscribe((filter) => {
|
|
528
|
+
this.store.dispatch(read(this.config.entity, {
|
|
529
|
+
...filter,
|
|
530
|
+
offset: 0,
|
|
531
|
+
}));
|
|
532
|
+
this.store.dispatch(select(this.config.entity, action.item.id));
|
|
533
|
+
});
|
|
534
|
+
break;
|
|
535
|
+
case `[${this.config.entity}] Update partial`:
|
|
536
|
+
this.service
|
|
537
|
+
.updatePartial(action.item)
|
|
538
|
+
.then(() => this.store.dispatch(updatePartialSuccess(this.config.entity, action.item)))
|
|
539
|
+
.catch((error) => {
|
|
540
|
+
this.store.dispatch(updatePartialFailure(this.config.entity, action.item, error));
|
|
541
|
+
this.store.dispatch(read(this.config.entity));
|
|
542
|
+
});
|
|
543
|
+
break;
|
|
544
|
+
case `[${this.config.entity}] Update partial Success`:
|
|
545
|
+
this.store
|
|
546
|
+
.pipe(select$1(getCrudFilter(this.config.entity)), first())
|
|
547
|
+
.subscribe((filter) => {
|
|
548
|
+
this.store.dispatch(read(this.config.entity, {
|
|
549
|
+
...filter,
|
|
550
|
+
offset: 0,
|
|
551
|
+
}));
|
|
552
|
+
this.store.dispatch(select(this.config.entity, action.item.id));
|
|
553
|
+
});
|
|
554
|
+
break;
|
|
555
|
+
case `[${this.config.entity}] Update partial many`:
|
|
556
|
+
this.service
|
|
557
|
+
.updatePartialMany(action.items)
|
|
558
|
+
.then(() => this.store.dispatch(updatePartialManySuccess(this.config.entity, action.items)))
|
|
559
|
+
.catch((error) => {
|
|
560
|
+
this.store.dispatch(updatePartialManyFailure(this.config.entity, action.items, error));
|
|
561
|
+
this.store.dispatch(read(this.config.entity));
|
|
562
|
+
});
|
|
563
|
+
break;
|
|
564
|
+
case `[${this.config.entity}] Update partial many Success`:
|
|
565
|
+
this.store
|
|
566
|
+
.pipe(select$1(getCrudFilter(this.config.entity)), first())
|
|
567
|
+
.subscribe((filter) => {
|
|
568
|
+
this.store.dispatch(read(this.config.entity, {
|
|
569
|
+
...filter,
|
|
570
|
+
offset: 0,
|
|
571
|
+
}));
|
|
572
|
+
});
|
|
573
|
+
break;
|
|
574
|
+
case `[${this.config.entity}] Delete`:
|
|
575
|
+
this.service
|
|
576
|
+
.delete(action.id)
|
|
577
|
+
.then(() => this.store.dispatch(deleteSuccess(this.config.entity, action.id)))
|
|
578
|
+
.catch((error) => {
|
|
579
|
+
this.store.dispatch(deleteFailure(this.config.entity, action.id, error));
|
|
580
|
+
});
|
|
581
|
+
break;
|
|
582
|
+
case `[${this.config.entity}] Delete Success`:
|
|
583
|
+
this.store
|
|
584
|
+
.pipe(select$1(getCrudFilter(this.config.entity)), first())
|
|
585
|
+
.subscribe((filter) => {
|
|
586
|
+
this.store.dispatch(read(this.config.entity, {
|
|
587
|
+
...filter,
|
|
588
|
+
offset: 0,
|
|
589
|
+
}));
|
|
590
|
+
});
|
|
591
|
+
break;
|
|
592
|
+
default:
|
|
593
|
+
console.warn(`No effect for action type ${action.type} in entity ${this.config.entity}`);
|
|
594
|
+
break;
|
|
595
|
+
}
|
|
596
|
+
});
|
|
597
|
+
}
|
|
598
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudEffects, deps: [{ token: i1.ActionsSubject }, { token: CrudService }, { token: CrudConfig }, { token: i1.Store }, { token: i1.State }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
599
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudEffects });
|
|
600
|
+
}
|
|
601
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudEffects, decorators: [{
|
|
602
|
+
type: Injectable
|
|
603
|
+
}], ctorParameters: () => [{ type: i1.ActionsSubject }, { type: CrudService }, { type: CrudConfig }, { type: i1.Store }, { type: i1.State }] });
|
|
604
|
+
|
|
605
|
+
class CrudFacade {
|
|
606
|
+
store;
|
|
607
|
+
config;
|
|
608
|
+
loaded;
|
|
609
|
+
loading;
|
|
610
|
+
selected;
|
|
611
|
+
multiSelected;
|
|
612
|
+
list;
|
|
613
|
+
filter;
|
|
614
|
+
totalCount;
|
|
615
|
+
links;
|
|
616
|
+
error;
|
|
617
|
+
constructor(store, config) {
|
|
618
|
+
this.store = store;
|
|
619
|
+
this.config = config;
|
|
620
|
+
if (NgrxStoreService.store) {
|
|
621
|
+
this.store = NgrxStoreService.store;
|
|
622
|
+
}
|
|
623
|
+
// Initialize all signals in the constructor (injection context)
|
|
624
|
+
this.loaded = toSignal(this.store.pipe(select$1(getCrudLoaded(this.config.entity))));
|
|
625
|
+
this.loading = toSignal(this.store.pipe(select$1(getCrudLoaded(this.config.entity)), map((l) => !l)));
|
|
626
|
+
this.selected = toSignal(this.store.pipe(select$1(getCrudSelected(this.config.entity))));
|
|
627
|
+
this.multiSelected = toSignal(this.store.pipe(select$1(getCrudMultiSelected(this.config.entity))));
|
|
628
|
+
this.list = toSignal(this.store.pipe(select$1(getCrudList(this.config.entity))));
|
|
629
|
+
this.filter = toSignal(this.store.pipe(select$1(getCrudFilter(this.config.entity))));
|
|
630
|
+
this.totalCount = toSignal(this.store.pipe(select$1(getCrudTotalCount(this.config.entity))));
|
|
631
|
+
this.links = toSignal(this.store.pipe(select$1(getCrudLinks(this.config.entity))));
|
|
632
|
+
this.error = toSignal(this.store.pipe(select$1(getCrudError(this.config.entity))));
|
|
633
|
+
}
|
|
634
|
+
create(item) {
|
|
635
|
+
this.store.dispatch(create(this.config.entity, item));
|
|
636
|
+
}
|
|
637
|
+
createMany(items, options) {
|
|
638
|
+
this.store.dispatch(createMany(this.config.entity, { items, options }));
|
|
639
|
+
}
|
|
640
|
+
read(filter = {}) {
|
|
641
|
+
let baseQuery = [];
|
|
642
|
+
if (this.config.baseQuery) {
|
|
643
|
+
baseQuery = this.config.baseQuery;
|
|
644
|
+
}
|
|
645
|
+
const fullFilter = {
|
|
646
|
+
...(filter ? filter : {}),
|
|
647
|
+
query: filter && filter.query ? filter.query : baseQuery,
|
|
648
|
+
};
|
|
649
|
+
this.store.dispatch(read(this.config.entity, fullFilter));
|
|
650
|
+
}
|
|
651
|
+
clear() {
|
|
652
|
+
this.store.dispatch(clear(this.config.entity));
|
|
653
|
+
}
|
|
654
|
+
select(id) {
|
|
655
|
+
this.store.dispatch(select(this.config.entity, id));
|
|
656
|
+
}
|
|
657
|
+
unselect() {
|
|
658
|
+
this.store.dispatch(unselect(this.config.entity));
|
|
659
|
+
}
|
|
660
|
+
multiSelect(items) {
|
|
661
|
+
this.store.dispatch(multiSelect(this.config.entity, items));
|
|
662
|
+
}
|
|
663
|
+
update(item) {
|
|
664
|
+
this.getStore().dispatch(update(this.config.entity, item));
|
|
665
|
+
}
|
|
666
|
+
export(filter = {}, format) {
|
|
667
|
+
this.getStore().dispatch(exportList(this.config.entity, filter, format));
|
|
668
|
+
}
|
|
669
|
+
updatePartial(item) {
|
|
670
|
+
this.getStore().dispatch(updatePartial(this.config.entity, item));
|
|
671
|
+
}
|
|
672
|
+
updatePartialMany(items) {
|
|
673
|
+
this.getStore().dispatch(updatePartialMany(this.config.entity, items));
|
|
674
|
+
}
|
|
675
|
+
delete(id) {
|
|
676
|
+
this.getStore().dispatch(deleteItem(this.config.entity, id));
|
|
677
|
+
}
|
|
678
|
+
getStore() {
|
|
679
|
+
if (NgrxStoreService.store)
|
|
680
|
+
return NgrxStoreService.store;
|
|
681
|
+
return this.store;
|
|
682
|
+
}
|
|
683
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudFacade, deps: [{ token: i1.Store }, { token: CrudConfig }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
684
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudFacade });
|
|
685
|
+
}
|
|
686
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudFacade, decorators: [{
|
|
687
|
+
type: Injectable
|
|
688
|
+
}], ctorParameters: () => [{ type: i1.Store }, { type: CrudConfig }] });
|
|
689
|
+
|
|
690
|
+
const initialState = {
|
|
691
|
+
loaded: false,
|
|
692
|
+
};
|
|
693
|
+
const crudReducer = (state, action, entity) => {
|
|
694
|
+
if (!state) {
|
|
695
|
+
state = { ...initialState };
|
|
696
|
+
}
|
|
697
|
+
switch (action.type) {
|
|
698
|
+
case `[${entity}] Create`:
|
|
699
|
+
return {
|
|
700
|
+
...state,
|
|
701
|
+
loaded: false,
|
|
702
|
+
error: null,
|
|
703
|
+
};
|
|
704
|
+
case `[${entity}] Create Success`:
|
|
705
|
+
return {
|
|
706
|
+
...state,
|
|
392
707
|
loaded: true,
|
|
393
708
|
error: null,
|
|
394
709
|
};
|
|
@@ -586,11 +901,12 @@ function getReducer(entity) {
|
|
|
586
901
|
};
|
|
587
902
|
}
|
|
588
903
|
|
|
589
|
-
class
|
|
904
|
+
class ExportBaseComponent extends BaseComponent$1 {
|
|
590
905
|
facade = inject((CrudFacade));
|
|
591
906
|
popoverService = inject(PopoverService);
|
|
592
907
|
styleService = inject(StyleService);
|
|
593
908
|
elementRef = inject(ElementRef);
|
|
909
|
+
injector = inject(Injector);
|
|
594
910
|
buttonExportCsvOptions = this.initButtonExportOptions('csv');
|
|
595
911
|
buttonExportXlsxOptions = this.initButtonExportOptions('xlsx');
|
|
596
912
|
ngOnInit() {
|
|
@@ -604,14 +920,21 @@ class ExportComponent extends BaseComponent$1 {
|
|
|
604
920
|
offset: undefined,
|
|
605
921
|
limit: undefined,
|
|
606
922
|
}, format);
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
this.popoverService.close().then();
|
|
923
|
+
toObservable(this.facade.loaded, { injector: this.injector })
|
|
924
|
+
.pipe(filter((l) => !!l), take(1))
|
|
925
|
+
.subscribe(() => this.popoverService.close().then());
|
|
611
926
|
},
|
|
612
927
|
loading: this.facade.loading,
|
|
613
928
|
};
|
|
614
929
|
}
|
|
930
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ExportBaseComponent, deps: null, target: i0.ɵɵFactoryTarget.Directive });
|
|
931
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.1", type: ExportBaseComponent, isStandalone: true, usesInheritance: true, ngImport: i0 });
|
|
932
|
+
}
|
|
933
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ExportBaseComponent, decorators: [{
|
|
934
|
+
type: Directive
|
|
935
|
+
}] });
|
|
936
|
+
|
|
937
|
+
class ExportComponent extends ExportBaseComponent {
|
|
615
938
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ExportComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
616
939
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.1", type: ExportComponent, isStandalone: true, selector: "smart-crud-export", usesInheritance: true, ngImport: i0, template: `
|
|
617
940
|
<div class="smart:p-5">
|
|
@@ -630,7 +953,7 @@ class ExportComponent extends BaseComponent$1 {
|
|
|
630
953
|
>
|
|
631
954
|
</p>
|
|
632
955
|
</div>
|
|
633
|
-
`, isInline: true, dependencies: [{ kind: "component", type: ButtonComponent, selector: "smart-button", inputs: ["options", "disabled", "class"] }] });
|
|
956
|
+
`, isInline: true, dependencies: [{ kind: "component", type: ButtonComponent, selector: "smart-button", inputs: ["options", "disabled", "class"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
634
957
|
}
|
|
635
958
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ExportComponent, decorators: [{
|
|
636
959
|
type: Component,
|
|
@@ -655,17 +978,88 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImpor
|
|
|
655
978
|
</div>
|
|
656
979
|
`,
|
|
657
980
|
imports: [ButtonComponent],
|
|
981
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
658
982
|
}]
|
|
659
983
|
}] });
|
|
660
984
|
|
|
985
|
+
/**
|
|
986
|
+
* @deprecated - please, use IModelPossibilitiesProvider from @smartsoft001/angular
|
|
987
|
+
*/
|
|
988
|
+
class ICrudModelPossibilitiesProvider {
|
|
989
|
+
}
|
|
990
|
+
/**
|
|
991
|
+
* @deprecated - please, use MODEL_POSSIBILITIES_PROVIDER from @smartsoft001/angular
|
|
992
|
+
*/
|
|
993
|
+
const CRUD_MODEL_POSSIBILITIES_PROVIDER = new InjectionToken('CRUD_MODEL_POSSIBILITIES_PROVIDER');
|
|
994
|
+
|
|
661
995
|
class BaseComponent {
|
|
662
996
|
facade = inject((CrudFacade));
|
|
663
997
|
translateService = inject(TranslateService);
|
|
998
|
+
config = inject((CrudConfig));
|
|
999
|
+
modelPossibilitiesProvider = inject(CRUD_MODEL_POSSIBILITIES_PROVIDER, { optional: true });
|
|
1000
|
+
injector = inject(Injector);
|
|
1001
|
+
destroyRef = inject(DestroyRef);
|
|
1002
|
+
_model;
|
|
1003
|
+
/**
|
|
1004
|
+
* Local, mutation-free working copy of the last filter this component pushed
|
|
1005
|
+
* to `facade.read(...)`. The store-bound `filter()` input is frozen under
|
|
1006
|
+
* NgRx `strictStateImmutability`, so refresh/clear operate on a clone; the
|
|
1007
|
+
* read getters (`value`, `minValue`, `maxValue`, `hasValue`, …) prefer this
|
|
1008
|
+
* pending copy until the real store update flows back through the input.
|
|
1009
|
+
*/
|
|
1010
|
+
_pendingFilter = signal(undefined, ...(ngDevMode ? [{ debugName: "_pendingFilter" }] : []));
|
|
1011
|
+
/** Snapshot of `filter()` that `_pendingFilter` was derived from. */
|
|
1012
|
+
_pendingFilterSource;
|
|
664
1013
|
possibilities;
|
|
665
1014
|
item = input(...(ngDevMode ? [undefined, { debugName: "item" }] : []));
|
|
666
1015
|
filter = input(...(ngDevMode ? [undefined, { debugName: "filter" }] : []));
|
|
1016
|
+
/**
|
|
1017
|
+
* The filter the component should read from: the pending working copy when it
|
|
1018
|
+
* is still in sync with the current input, otherwise the raw input. Once the
|
|
1019
|
+
* store update arrives (a new `filter()` reference), the pending copy is
|
|
1020
|
+
* considered stale and the fresh input wins.
|
|
1021
|
+
*/
|
|
1022
|
+
effectiveFilter = computed(() => {
|
|
1023
|
+
const source = this.filter();
|
|
1024
|
+
const pending = this._pendingFilter();
|
|
1025
|
+
if (pending && source === this._pendingFilterSource)
|
|
1026
|
+
return pending;
|
|
1027
|
+
return source;
|
|
1028
|
+
}, ...(ngDevMode ? [{ debugName: "effectiveFilter" }] : []));
|
|
1029
|
+
/**
|
|
1030
|
+
* OnPush-safe replacement for `@if (value)` in templates (partial GAP-19).
|
|
1031
|
+
* True when filter().query has a matching entry (key + type) with a
|
|
1032
|
+
* non-empty value.
|
|
1033
|
+
*/
|
|
1034
|
+
hasValue = computed(() => {
|
|
1035
|
+
const filter = this.effectiveFilter();
|
|
1036
|
+
const item = this.item();
|
|
1037
|
+
if (!filter || !item || !filter.query)
|
|
1038
|
+
return false;
|
|
1039
|
+
const query = filter.query.find((q) => q.key === item.key && q.type === item.type);
|
|
1040
|
+
if (!query)
|
|
1041
|
+
return false;
|
|
1042
|
+
const val = query.value;
|
|
1043
|
+
return val !== null && val !== undefined && val !== '';
|
|
1044
|
+
}, ...(ngDevMode ? [{ debugName: "hasValue" }] : []));
|
|
1045
|
+
/**
|
|
1046
|
+
* OnPush-safe replacement for `@if (minValue)` in templates (partial
|
|
1047
|
+
* GAP-19). True when filter().query has a matching `>=` entry (range "from")
|
|
1048
|
+
* with a non-empty value.
|
|
1049
|
+
*/
|
|
1050
|
+
hasMinValue = computed(() => this.hasQueryValue('>='), ...(ngDevMode ? [{ debugName: "hasMinValue" }] : []));
|
|
1051
|
+
/**
|
|
1052
|
+
* OnPush-safe replacement for `@if (maxValue)` in templates (partial
|
|
1053
|
+
* GAP-19). True when filter().query has a matching `<=` entry (range "to")
|
|
1054
|
+
* with a non-empty value.
|
|
1055
|
+
*/
|
|
1056
|
+
hasMaxValue = computed(() => this.hasQueryValue('<='), ...(ngDevMode ? [{ debugName: "hasMaxValue" }] : []));
|
|
1057
|
+
/** Lazily-built model instance used to derive field options/labels. */
|
|
1058
|
+
get model() {
|
|
1059
|
+
return (this._model ??= new this.config.type());
|
|
1060
|
+
}
|
|
667
1061
|
get value() {
|
|
668
|
-
const filter = this.
|
|
1062
|
+
const filter = this.effectiveFilter();
|
|
669
1063
|
const item = this.item();
|
|
670
1064
|
if (!filter || !item || !filter.query)
|
|
671
1065
|
return null;
|
|
@@ -681,7 +1075,7 @@ class BaseComponent {
|
|
|
681
1075
|
this.refresh(val);
|
|
682
1076
|
}
|
|
683
1077
|
get minValue() {
|
|
684
|
-
const filter = this.
|
|
1078
|
+
const filter = this.effectiveFilter();
|
|
685
1079
|
const item = this.item();
|
|
686
1080
|
if (!filter || !item || !filter.query)
|
|
687
1081
|
return null;
|
|
@@ -697,7 +1091,7 @@ class BaseComponent {
|
|
|
697
1091
|
this.refresh(val, '>=');
|
|
698
1092
|
}
|
|
699
1093
|
get maxValue() {
|
|
700
|
-
const filter = this.
|
|
1094
|
+
const filter = this.effectiveFilter();
|
|
701
1095
|
const item = this.item();
|
|
702
1096
|
if (!filter || !item || !filter.query)
|
|
703
1097
|
return null;
|
|
@@ -715,8 +1109,51 @@ class BaseComponent {
|
|
|
715
1109
|
get lang() {
|
|
716
1110
|
return this.translateService.currentLang;
|
|
717
1111
|
}
|
|
1112
|
+
/**
|
|
1113
|
+
* Returns a filter object safe to mutate. The store-bound `filter()` input is
|
|
1114
|
+
* frozen under NgRx `strictStateImmutability`, so when (any part of) the
|
|
1115
|
+
* source is frozen we hand back a deep-enough clone — object + query array +
|
|
1116
|
+
* query entries — leaving the store untouched. When the source is a plain,
|
|
1117
|
+
* extensible object (no immutability checks active) we keep operating on it in
|
|
1118
|
+
* place so consumers that hold the same reference still observe the change.
|
|
1119
|
+
*/
|
|
1120
|
+
cloneFilter() {
|
|
1121
|
+
const source = this.effectiveFilter();
|
|
1122
|
+
if (!source)
|
|
1123
|
+
return undefined;
|
|
1124
|
+
if (!this.isMutationSafe(source)) {
|
|
1125
|
+
return {
|
|
1126
|
+
...source,
|
|
1127
|
+
query: source.query ? source.query.map((q) => ({ ...q })) : [],
|
|
1128
|
+
};
|
|
1129
|
+
}
|
|
1130
|
+
return source;
|
|
1131
|
+
}
|
|
1132
|
+
/**
|
|
1133
|
+
* True when `filter` (and its query array + entries) can be mutated directly,
|
|
1134
|
+
* i.e. nothing is frozen.
|
|
1135
|
+
*/
|
|
1136
|
+
isMutationSafe(filter) {
|
|
1137
|
+
if (Object.isFrozen(filter))
|
|
1138
|
+
return false;
|
|
1139
|
+
const query = filter.query;
|
|
1140
|
+
if (!query)
|
|
1141
|
+
return true;
|
|
1142
|
+
if (Object.isFrozen(query))
|
|
1143
|
+
return false;
|
|
1144
|
+
return query.every((q) => !Object.isFrozen(q));
|
|
1145
|
+
}
|
|
1146
|
+
/**
|
|
1147
|
+
* Records the mutated clone as the pending working copy (so read getters
|
|
1148
|
+
* reflect it immediately) and dispatches it through the facade.
|
|
1149
|
+
*/
|
|
1150
|
+
commitFilter(filter) {
|
|
1151
|
+
this._pendingFilterSource = this.filter();
|
|
1152
|
+
this._pendingFilter.set(filter);
|
|
1153
|
+
this.facade.read(filter);
|
|
1154
|
+
}
|
|
718
1155
|
refresh(val, type = null) {
|
|
719
|
-
const filter = this.
|
|
1156
|
+
const filter = this.cloneFilter();
|
|
720
1157
|
const item = this.item();
|
|
721
1158
|
if (!filter || !item)
|
|
722
1159
|
return;
|
|
@@ -726,7 +1163,7 @@ class BaseComponent {
|
|
|
726
1163
|
filter.query = [];
|
|
727
1164
|
filter.offset = 0;
|
|
728
1165
|
if (this.isArrayType()) {
|
|
729
|
-
this.refreshForArray(val, type);
|
|
1166
|
+
this.refreshForArray(filter, val, type);
|
|
730
1167
|
return;
|
|
731
1168
|
}
|
|
732
1169
|
let query = filter.query.find((q) => q.key === item.key && q.type === type);
|
|
@@ -737,7 +1174,7 @@ class BaseComponent {
|
|
|
737
1174
|
filter.query.splice(index, 1);
|
|
738
1175
|
}
|
|
739
1176
|
}
|
|
740
|
-
this.
|
|
1177
|
+
this.commitFilter(filter);
|
|
741
1178
|
return;
|
|
742
1179
|
}
|
|
743
1180
|
if (!query) {
|
|
@@ -750,32 +1187,99 @@ class BaseComponent {
|
|
|
750
1187
|
}
|
|
751
1188
|
query.value = val;
|
|
752
1189
|
query.label = item.label;
|
|
753
|
-
this.
|
|
1190
|
+
this.commitFilter(filter);
|
|
1191
|
+
}
|
|
1192
|
+
/**
|
|
1193
|
+
* Builds the `InputOptions` consumed by shared `smart-input-*` components for
|
|
1194
|
+
* a single reactive control. When `withPossibilities` is true (radio/select
|
|
1195
|
+
* style filters) the base `possibilities` signal is mapped into the
|
|
1196
|
+
* `{ id, text, checked }` shape the shared inputs expect; otherwise it is
|
|
1197
|
+
* omitted (text/flag filters do not need possibilities).
|
|
1198
|
+
*/
|
|
1199
|
+
buildInputOptions(control, withPossibilities = false) {
|
|
1200
|
+
const options = {
|
|
1201
|
+
treeLevel: 0,
|
|
1202
|
+
control,
|
|
1203
|
+
model: this.model,
|
|
1204
|
+
fieldKey: this.item()?.key ?? '',
|
|
1205
|
+
};
|
|
1206
|
+
if (withPossibilities) {
|
|
1207
|
+
const source = this.possibilities ? this.possibilities() : [];
|
|
1208
|
+
options.possibilities = signal(source.map(({ id, text }) => ({ id, text, checked: false })), ...(ngDevMode ? [{ debugName: "possibilities" }] : []));
|
|
1209
|
+
}
|
|
1210
|
+
return options;
|
|
1211
|
+
}
|
|
1212
|
+
/**
|
|
1213
|
+
* Creates a reactive control bridged to the legacy filter state for a given
|
|
1214
|
+
* query slot: seeded from the current query value for that slot (`null` ->
|
|
1215
|
+
* `value` / `item.type`, `'>='` -> `minValue`, `'<='` -> `maxValue`), and
|
|
1216
|
+
* wired so every change re-runs the (debounced) `refresh` for that slot.
|
|
1217
|
+
*/
|
|
1218
|
+
bindControl(type = null) {
|
|
1219
|
+
const seed = type === '>='
|
|
1220
|
+
? this.minValue
|
|
1221
|
+
: type === '<='
|
|
1222
|
+
? this.maxValue
|
|
1223
|
+
: this.value;
|
|
1224
|
+
const control = new UntypedFormControl(seed);
|
|
1225
|
+
control.valueChanges
|
|
1226
|
+
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
1227
|
+
.subscribe((v) => this.refresh(v, type));
|
|
1228
|
+
// TODO(GAP-19): re-sync control when filter() changes externally
|
|
1229
|
+
return control;
|
|
1230
|
+
}
|
|
1231
|
+
/**
|
|
1232
|
+
* Creates a reactive control bridged to the default (`value` / `item.type`)
|
|
1233
|
+
* query slot.
|
|
1234
|
+
*/
|
|
1235
|
+
bindValueControl() {
|
|
1236
|
+
return this.bindControl(null);
|
|
754
1237
|
}
|
|
755
1238
|
clear() {
|
|
756
|
-
const filter = this.
|
|
1239
|
+
const filter = this.cloneFilter();
|
|
757
1240
|
const item = this.item();
|
|
758
1241
|
if (!filter || !item || !filter.query)
|
|
759
1242
|
return;
|
|
760
1243
|
filter.query = filter.query?.filter((q) => q.key !== item.key);
|
|
761
1244
|
filter.offset = 0;
|
|
762
|
-
this.
|
|
1245
|
+
this.commitFilter(filter);
|
|
763
1246
|
}
|
|
764
1247
|
ngOnInit() {
|
|
765
1248
|
this.initPossibilities();
|
|
766
1249
|
}
|
|
767
1250
|
initPossibilities() {
|
|
768
1251
|
const item = this.item();
|
|
769
|
-
if (item
|
|
770
|
-
|
|
1252
|
+
if (!item)
|
|
1253
|
+
return;
|
|
1254
|
+
let possibilities = item.possibilities;
|
|
1255
|
+
if (this.modelPossibilitiesProvider) {
|
|
1256
|
+
const fromProvider = this.modelPossibilitiesProvider.get(this.config.type);
|
|
1257
|
+
if (fromProvider && fromProvider[item.key]) {
|
|
1258
|
+
possibilities = toSignal(fromProvider[item.key], {
|
|
1259
|
+
initialValue: [],
|
|
1260
|
+
injector: this.injector,
|
|
1261
|
+
});
|
|
1262
|
+
}
|
|
771
1263
|
}
|
|
1264
|
+
if (possibilities)
|
|
1265
|
+
this.possibilities = possibilities;
|
|
1266
|
+
}
|
|
1267
|
+
hasQueryValue(type) {
|
|
1268
|
+
const filter = this.effectiveFilter();
|
|
1269
|
+
const item = this.item();
|
|
1270
|
+
if (!filter || !item || !filter.query)
|
|
1271
|
+
return false;
|
|
1272
|
+
const query = filter.query.find((q) => q.key === item.key && q.type === type);
|
|
1273
|
+
if (!query)
|
|
1274
|
+
return false;
|
|
1275
|
+
const val = query.value;
|
|
1276
|
+
return val !== null && val !== undefined && val !== '';
|
|
772
1277
|
}
|
|
773
1278
|
isArrayType() {
|
|
774
1279
|
const item = this.item();
|
|
775
1280
|
return item?.fieldType === FieldType.check;
|
|
776
1281
|
}
|
|
777
|
-
refreshForArray(vals, type) {
|
|
778
|
-
const filter = this.filter();
|
|
1282
|
+
refreshForArray(filter, vals, type) {
|
|
779
1283
|
const item = this.item();
|
|
780
1284
|
if (!filter || !item)
|
|
781
1285
|
return;
|
|
@@ -789,7 +1293,7 @@ class BaseComponent {
|
|
|
789
1293
|
}
|
|
790
1294
|
});
|
|
791
1295
|
if (vals === null || vals === undefined || !vals.length) {
|
|
792
|
-
this.
|
|
1296
|
+
this.commitFilter(filter);
|
|
793
1297
|
return;
|
|
794
1298
|
}
|
|
795
1299
|
vals.forEach((val) => {
|
|
@@ -800,7 +1304,7 @@ class BaseComponent {
|
|
|
800
1304
|
};
|
|
801
1305
|
filter.query.push(query);
|
|
802
1306
|
});
|
|
803
|
-
this.
|
|
1307
|
+
this.commitFilter(filter);
|
|
804
1308
|
}
|
|
805
1309
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: BaseComponent, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
806
1310
|
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.1", type: BaseComponent, isStandalone: true, inputs: { item: { classPropertyName: "item", publicName: "item", isSignal: true, isRequired: false, transformFunction: null }, filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 });
|
|
@@ -815,101 +1319,115 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImpor
|
|
|
815
1319
|
type: Directive
|
|
816
1320
|
}], propDecorators: { item: [{ type: i0.Input, args: [{ isSignal: true, alias: "item", required: false }] }], filter: [{ type: i0.Input, args: [{ isSignal: true, alias: "filter", required: false }] }], refresh: [] } });
|
|
817
1321
|
|
|
1322
|
+
// TODO(FRA-293 GAP-19): re-sync rendered checked state when filter() changes
|
|
1323
|
+
// externally (the `value` getter already reads the reactive filter() signal,
|
|
1324
|
+
// so the `list` computed stays OnPush-safe).
|
|
818
1325
|
class FilterCheckComponent extends BaseComponent {
|
|
819
1326
|
list;
|
|
820
|
-
|
|
1327
|
+
hasCheckedValues = computed(() => {
|
|
1328
|
+
const v = this.value;
|
|
1329
|
+
return Array.isArray(v) && v.length > 0;
|
|
1330
|
+
}, ...(ngDevMode ? [{ debugName: "hasCheckedValues" }] : []));
|
|
1331
|
+
ngOnInit() {
|
|
1332
|
+
super.ngOnInit();
|
|
821
1333
|
this.list = computed(() => {
|
|
822
|
-
const possibilities = this.possibilities();
|
|
1334
|
+
const possibilities = this.possibilities ? this.possibilities() : [];
|
|
1335
|
+
const v = this.value ?? [];
|
|
823
1336
|
return possibilities.map((pos) => ({
|
|
824
1337
|
value: pos,
|
|
825
|
-
isCheck:
|
|
1338
|
+
isCheck: v.some((r) => r === pos.id),
|
|
826
1339
|
}));
|
|
827
1340
|
}, ...(ngDevMode ? [{ debugName: "list" }] : []));
|
|
828
1341
|
}
|
|
829
1342
|
onCheckChange(checked, entry) {
|
|
830
|
-
if (checked && !this.value.some((r) => r === entry.value.id)) {
|
|
831
|
-
this.value = [...this.value, entry.value.id];
|
|
1343
|
+
if (checked && !(this.value ?? []).some((r) => r === entry.value.id)) {
|
|
1344
|
+
this.value = [...(this.value ?? []), entry.value.id];
|
|
832
1345
|
}
|
|
833
|
-
if (!checked && this.value.some((r) => r === entry.value.id)) {
|
|
1346
|
+
if (!checked && (this.value ?? []).some((r) => r === entry.value.id)) {
|
|
834
1347
|
this.value = this.value?.filter((r) => r !== entry.value.id);
|
|
835
1348
|
}
|
|
836
1349
|
}
|
|
837
1350
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FilterCheckComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
838
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: FilterCheckComponent, isStandalone: true, selector: "smart-crud-filter-check", usesInheritance: true, ngImport: i0, template: `
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
`, isInline: true,
|
|
1351
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: FilterCheckComponent, isStandalone: true, selector: "smart-crud-filter-check", host: { classAttribute: "smart:block smart:w-full" }, usesInheritance: true, ngImport: i0, template: `
|
|
1352
|
+
<fieldset class="smart:w-full">
|
|
1353
|
+
<legend
|
|
1354
|
+
class="smart:flex smart:items-center smart:justify-between smart:text-sm smart:font-medium smart:text-gray-900"
|
|
1355
|
+
>
|
|
1356
|
+
<span>{{ item()?.label || '' | translate }}</span>
|
|
1357
|
+
@if (hasCheckedValues()) {
|
|
1358
|
+
<button
|
|
1359
|
+
type="button"
|
|
1360
|
+
(click)="refresh([])"
|
|
1361
|
+
aria-label="clear"
|
|
1362
|
+
class="smart:rounded smart:px-2 smart:py-1 smart:text-red-600 smart:hover:bg-red-50"
|
|
1363
|
+
>
|
|
1364
|
+
×
|
|
1365
|
+
</button>
|
|
1366
|
+
}
|
|
1367
|
+
</legend>
|
|
1368
|
+
<div class="smart:mt-2 smart:space-y-2">
|
|
1369
|
+
@for (entry of list(); track entry.value.id) {
|
|
1370
|
+
<label class="smart:flex smart:items-center smart:gap-x-2">
|
|
1371
|
+
<input
|
|
1372
|
+
type="checkbox"
|
|
1373
|
+
[checked]="entry.isCheck"
|
|
1374
|
+
(change)="onCheckChange($any($event.target).checked, entry)"
|
|
1375
|
+
class="smart:h-4 smart:w-4 smart:rounded smart:border-gray-300 smart:text-indigo-600 smart:focus:ring-indigo-500"
|
|
1376
|
+
/>
|
|
1377
|
+
<span class="smart:text-sm smart:text-gray-900">{{
|
|
1378
|
+
entry.value.text | translate
|
|
1379
|
+
}}</span>
|
|
1380
|
+
</label>
|
|
1381
|
+
}
|
|
1382
|
+
</div>
|
|
1383
|
+
</fieldset>
|
|
1384
|
+
`, isInline: true, dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
872
1385
|
}
|
|
873
1386
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FilterCheckComponent, decorators: [{
|
|
874
1387
|
type: Component,
|
|
875
|
-
args: [{
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
1388
|
+
args: [{
|
|
1389
|
+
selector: 'smart-crud-filter-check',
|
|
1390
|
+
host: { class: 'smart:block smart:w-full' },
|
|
1391
|
+
template: `
|
|
1392
|
+
<fieldset class="smart:w-full">
|
|
1393
|
+
<legend
|
|
1394
|
+
class="smart:flex smart:items-center smart:justify-between smart:text-sm smart:font-medium smart:text-gray-900"
|
|
1395
|
+
>
|
|
1396
|
+
<span>{{ item()?.label || '' | translate }}</span>
|
|
1397
|
+
@if (hasCheckedValues()) {
|
|
1398
|
+
<button
|
|
1399
|
+
type="button"
|
|
1400
|
+
(click)="refresh([])"
|
|
1401
|
+
aria-label="clear"
|
|
1402
|
+
class="smart:rounded smart:px-2 smart:py-1 smart:text-red-600 smart:hover:bg-red-50"
|
|
1403
|
+
>
|
|
1404
|
+
×
|
|
1405
|
+
</button>
|
|
1406
|
+
}
|
|
1407
|
+
</legend>
|
|
1408
|
+
<div class="smart:mt-2 smart:space-y-2">
|
|
1409
|
+
@for (entry of list(); track entry.value.id) {
|
|
1410
|
+
<label class="smart:flex smart:items-center smart:gap-x-2">
|
|
1411
|
+
<input
|
|
1412
|
+
type="checkbox"
|
|
1413
|
+
[checked]="entry.isCheck"
|
|
1414
|
+
(change)="onCheckChange($any($event.target).checked, entry)"
|
|
1415
|
+
class="smart:h-4 smart:w-4 smart:rounded smart:border-gray-300 smart:text-indigo-600 smart:focus:ring-indigo-500"
|
|
1416
|
+
/>
|
|
1417
|
+
<span class="smart:text-sm smart:text-gray-900">{{
|
|
1418
|
+
entry.value.text | translate
|
|
1419
|
+
}}</span>
|
|
1420
|
+
</label>
|
|
1421
|
+
}
|
|
1422
|
+
</div>
|
|
1423
|
+
</fieldset>
|
|
1424
|
+
`,
|
|
1425
|
+
imports: [TranslatePipe],
|
|
1426
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1427
|
+
}]
|
|
909
1428
|
}] });
|
|
910
1429
|
|
|
911
1430
|
class FilterDateComponent extends BaseComponent {
|
|
912
|
-
id = GuidService.create();
|
|
913
1431
|
get allowAdvanced() {
|
|
914
1432
|
const item = this.item();
|
|
915
1433
|
return item?.type === '=';
|
|
@@ -945,150 +1463,437 @@ class FilterDateComponent extends BaseComponent {
|
|
|
945
1463
|
return this.maxValue;
|
|
946
1464
|
}
|
|
947
1465
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FilterDateComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
948
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: FilterDateComponent, isStandalone: true, selector: "smart-crud-filter-date",
|
|
1466
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: FilterDateComponent, isStandalone: true, selector: "smart-crud-filter-date", host: { classAttribute: "smart:block smart:w-full" }, usesInheritance: true, ngImport: i0, template: `
|
|
1467
|
+
<label class="smart:mb-1 smart:block smart:text-sm smart:font-medium">
|
|
1468
|
+
{{ item()?.label || '' | translate }}
|
|
1469
|
+
</label>
|
|
1470
|
+
<div class="smart:flex smart:w-full smart:items-end smart:gap-2">
|
|
1471
|
+
<smart-date-edit
|
|
1472
|
+
class="smart:flex-1"
|
|
1473
|
+
[ngModel]="customValue || ''"
|
|
1474
|
+
(ngModelChange)="customValue = $event"
|
|
1475
|
+
></smart-date-edit>
|
|
1476
|
+
@if (hasValue()) {
|
|
1477
|
+
<button
|
|
1478
|
+
type="button"
|
|
1479
|
+
(click)="refresh(null)"
|
|
1480
|
+
aria-label="clear"
|
|
1481
|
+
class="smart:shrink-0 smart:rounded smart:px-2 smart:py-2 smart:text-red-600 smart:hover:bg-red-50"
|
|
1482
|
+
>
|
|
1483
|
+
×
|
|
1484
|
+
</button>
|
|
1485
|
+
}
|
|
1486
|
+
</div>
|
|
1487
|
+
`, isInline: true, dependencies: [{ kind: "component", type: DateEditComponent, selector: "smart-date-edit", inputs: ["variant", "class", "ngModel"], outputs: ["ngModelChange", "validChange"] }, { kind: "ngmodule", type: FormsModule }, { 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: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
949
1488
|
}
|
|
950
1489
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FilterDateComponent, decorators: [{
|
|
951
1490
|
type: Component,
|
|
952
|
-
args: [{
|
|
1491
|
+
args: [{
|
|
1492
|
+
selector: 'smart-crud-filter-date',
|
|
1493
|
+
host: { class: 'smart:block smart:w-full' },
|
|
1494
|
+
// TODO(FRA-293 GAP-19): re-sync picker when filter() changes externally
|
|
1495
|
+
template: `
|
|
1496
|
+
<label class="smart:mb-1 smart:block smart:text-sm smart:font-medium">
|
|
1497
|
+
{{ item()?.label || '' | translate }}
|
|
1498
|
+
</label>
|
|
1499
|
+
<div class="smart:flex smart:w-full smart:items-end smart:gap-2">
|
|
1500
|
+
<smart-date-edit
|
|
1501
|
+
class="smart:flex-1"
|
|
1502
|
+
[ngModel]="customValue || ''"
|
|
1503
|
+
(ngModelChange)="customValue = $event"
|
|
1504
|
+
></smart-date-edit>
|
|
1505
|
+
@if (hasValue()) {
|
|
1506
|
+
<button
|
|
1507
|
+
type="button"
|
|
1508
|
+
(click)="refresh(null)"
|
|
1509
|
+
aria-label="clear"
|
|
1510
|
+
class="smart:shrink-0 smart:rounded smart:px-2 smart:py-2 smart:text-red-600 smart:hover:bg-red-50"
|
|
1511
|
+
>
|
|
1512
|
+
×
|
|
1513
|
+
</button>
|
|
1514
|
+
}
|
|
1515
|
+
</div>
|
|
1516
|
+
`,
|
|
1517
|
+
imports: [DateEditComponent, FormsModule, TranslatePipe],
|
|
1518
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1519
|
+
}]
|
|
953
1520
|
}] });
|
|
954
1521
|
|
|
955
1522
|
class FilterDateTimeComponent extends FilterDateComponent {
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
1523
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FilterDateTimeComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
1524
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: FilterDateTimeComponent, isStandalone: true, selector: "smart-crud-filter-date-time", host: { classAttribute: "smart:block smart:w-full" }, usesInheritance: true, ngImport: i0, template: `
|
|
1525
|
+
<label class="smart:mb-1 smart:block smart:text-sm smart:font-medium">
|
|
1526
|
+
{{ item()?.label || '' | translate }}
|
|
1527
|
+
</label>
|
|
1528
|
+
<div class="smart:flex smart:w-full smart:flex-col smart:gap-2">
|
|
1529
|
+
<div class="smart:flex smart:w-full smart:items-end smart:gap-2">
|
|
1530
|
+
<label class="smart:text-sm">{{ 'from' | translate }}</label>
|
|
1531
|
+
<input
|
|
1532
|
+
type="datetime-local"
|
|
1533
|
+
class="smart:flex-1 smart:rounded smart:border smart:border-gray-300 smart:px-2 smart:py-1"
|
|
1534
|
+
[ngModel]="customMinValue || ''"
|
|
1535
|
+
(ngModelChange)="customMinValue = $event"
|
|
1536
|
+
/>
|
|
1537
|
+
@if (hasMinValue()) {
|
|
1538
|
+
<button
|
|
1539
|
+
type="button"
|
|
1540
|
+
(click)="refresh(null, '>=')"
|
|
1541
|
+
aria-label="clear-from"
|
|
1542
|
+
class="smart:shrink-0 smart:rounded smart:px-2 smart:py-2 smart:text-red-600 smart:hover:bg-red-50"
|
|
1543
|
+
>
|
|
1544
|
+
×
|
|
1545
|
+
</button>
|
|
1546
|
+
}
|
|
1547
|
+
</div>
|
|
1548
|
+
<div class="smart:flex smart:w-full smart:items-end smart:gap-2">
|
|
1549
|
+
<label class="smart:text-sm">{{ 'to' | translate }}</label>
|
|
1550
|
+
<input
|
|
1551
|
+
type="datetime-local"
|
|
1552
|
+
class="smart:flex-1 smart:rounded smart:border smart:border-gray-300 smart:px-2 smart:py-1"
|
|
1553
|
+
[ngModel]="customMaxValue || ''"
|
|
1554
|
+
(ngModelChange)="customMaxValue = $event"
|
|
1555
|
+
/>
|
|
1556
|
+
@if (hasMaxValue()) {
|
|
1557
|
+
<button
|
|
1558
|
+
type="button"
|
|
1559
|
+
(click)="refresh(null, '<=')"
|
|
1560
|
+
aria-label="clear-to"
|
|
1561
|
+
class="smart:shrink-0 smart:rounded smart:px-2 smart:py-2 smart:text-red-600 smart:hover:bg-red-50"
|
|
1562
|
+
>
|
|
1563
|
+
×
|
|
1564
|
+
</button>
|
|
1565
|
+
}
|
|
1566
|
+
</div>
|
|
1567
|
+
</div>
|
|
1568
|
+
`, isInline: true, dependencies: [{ 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: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1569
|
+
}
|
|
1570
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FilterDateTimeComponent, decorators: [{
|
|
1571
|
+
type: Component,
|
|
1572
|
+
args: [{
|
|
1573
|
+
selector: 'smart-crud-filter-date-time',
|
|
1574
|
+
host: { class: 'smart:block smart:w-full' },
|
|
1575
|
+
// TODO(FRA-293 GAP-19): re-sync picker when filter() changes externally
|
|
1576
|
+
template: `
|
|
1577
|
+
<label class="smart:mb-1 smart:block smart:text-sm smart:font-medium">
|
|
1578
|
+
{{ item()?.label || '' | translate }}
|
|
1579
|
+
</label>
|
|
1580
|
+
<div class="smart:flex smart:w-full smart:flex-col smart:gap-2">
|
|
1581
|
+
<div class="smart:flex smart:w-full smart:items-end smart:gap-2">
|
|
1582
|
+
<label class="smart:text-sm">{{ 'from' | translate }}</label>
|
|
1583
|
+
<input
|
|
1584
|
+
type="datetime-local"
|
|
1585
|
+
class="smart:flex-1 smart:rounded smart:border smart:border-gray-300 smart:px-2 smart:py-1"
|
|
1586
|
+
[ngModel]="customMinValue || ''"
|
|
1587
|
+
(ngModelChange)="customMinValue = $event"
|
|
1588
|
+
/>
|
|
1589
|
+
@if (hasMinValue()) {
|
|
1590
|
+
<button
|
|
1591
|
+
type="button"
|
|
1592
|
+
(click)="refresh(null, '>=')"
|
|
1593
|
+
aria-label="clear-from"
|
|
1594
|
+
class="smart:shrink-0 smart:rounded smart:px-2 smart:py-2 smart:text-red-600 smart:hover:bg-red-50"
|
|
1595
|
+
>
|
|
1596
|
+
×
|
|
1597
|
+
</button>
|
|
1598
|
+
}
|
|
1599
|
+
</div>
|
|
1600
|
+
<div class="smart:flex smart:w-full smart:items-end smart:gap-2">
|
|
1601
|
+
<label class="smart:text-sm">{{ 'to' | translate }}</label>
|
|
1602
|
+
<input
|
|
1603
|
+
type="datetime-local"
|
|
1604
|
+
class="smart:flex-1 smart:rounded smart:border smart:border-gray-300 smart:px-2 smart:py-1"
|
|
1605
|
+
[ngModel]="customMaxValue || ''"
|
|
1606
|
+
(ngModelChange)="customMaxValue = $event"
|
|
1607
|
+
/>
|
|
1608
|
+
@if (hasMaxValue()) {
|
|
1609
|
+
<button
|
|
1610
|
+
type="button"
|
|
1611
|
+
(click)="refresh(null, '<=')"
|
|
1612
|
+
aria-label="clear-to"
|
|
1613
|
+
class="smart:shrink-0 smart:rounded smart:px-2 smart:py-2 smart:text-red-600 smart:hover:bg-red-50"
|
|
1614
|
+
>
|
|
1615
|
+
×
|
|
1616
|
+
</button>
|
|
1617
|
+
}
|
|
1618
|
+
</div>
|
|
1619
|
+
</div>
|
|
1620
|
+
`,
|
|
1621
|
+
imports: [TranslatePipe, FormsModule],
|
|
1622
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1623
|
+
}]
|
|
1624
|
+
}] });
|
|
1625
|
+
|
|
1626
|
+
class FilterDateWithEditComponent extends FilterDateComponent {
|
|
1627
|
+
advanced = signal(false, ...(ngDevMode ? [{ debugName: "advanced" }] : []));
|
|
1628
|
+
toggleAdvanced() {
|
|
1629
|
+
this.advanced.update((val) => !val);
|
|
1630
|
+
if (this.advanced()) {
|
|
1631
|
+
this.value = null;
|
|
1632
|
+
}
|
|
971
1633
|
}
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
1634
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FilterDateWithEditComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
1635
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: FilterDateWithEditComponent, isStandalone: true, selector: "smart-crud-filter-date-with-edit", host: { classAttribute: "smart:block smart:w-full" }, usesInheritance: true, ngImport: i0, template: `
|
|
1636
|
+
<label class="smart:mb-1 smart:block smart:text-sm smart:font-medium">
|
|
1637
|
+
{{ item()?.label || '' | translate }}
|
|
1638
|
+
</label>
|
|
1639
|
+
|
|
1640
|
+
@if (!advanced()) {
|
|
1641
|
+
<div class="smart:flex smart:w-full smart:items-end smart:gap-2">
|
|
1642
|
+
<smart-date-edit
|
|
1643
|
+
class="smart:flex-1"
|
|
1644
|
+
[ngModel]="customValue || ''"
|
|
1645
|
+
(ngModelChange)="customValue = $event"
|
|
1646
|
+
></smart-date-edit>
|
|
1647
|
+
@if (allowAdvanced) {
|
|
1648
|
+
<button
|
|
1649
|
+
type="button"
|
|
1650
|
+
(click)="toggleAdvanced()"
|
|
1651
|
+
aria-label="advanced"
|
|
1652
|
+
class="smart:shrink-0 smart:rounded smart:px-2 smart:py-2 smart:hover:bg-gray-100"
|
|
1653
|
+
>
|
|
1654
|
+
⚙
|
|
1655
|
+
</button>
|
|
1656
|
+
}
|
|
1657
|
+
@if (hasValue()) {
|
|
1658
|
+
<button
|
|
1659
|
+
type="button"
|
|
1660
|
+
(click)="refresh(null)"
|
|
1661
|
+
aria-label="clear"
|
|
1662
|
+
class="smart:shrink-0 smart:rounded smart:px-2 smart:py-2 smart:text-red-600 smart:hover:bg-red-50"
|
|
1663
|
+
>
|
|
1664
|
+
×
|
|
1665
|
+
</button>
|
|
975
1666
|
}
|
|
1667
|
+
</div>
|
|
1668
|
+
} @else if (allowAdvanced) {
|
|
1669
|
+
<button
|
|
1670
|
+
type="button"
|
|
1671
|
+
(click)="toggleAdvanced()"
|
|
1672
|
+
aria-label="advanced"
|
|
1673
|
+
class="smart:mb-2 smart:rounded smart:px-2 smart:py-2 smart:hover:bg-gray-100"
|
|
1674
|
+
>
|
|
1675
|
+
⚙
|
|
1676
|
+
</button>
|
|
976
1677
|
}
|
|
977
|
-
|
|
978
|
-
|
|
1678
|
+
|
|
1679
|
+
@if ((advanced() || hasMinValue() || hasMaxValue()) && allowAdvanced) {
|
|
1680
|
+
<div class="smart:flex smart:w-full smart:flex-col smart:gap-2">
|
|
1681
|
+
<div class="smart:flex smart:w-full smart:items-end smart:gap-2">
|
|
1682
|
+
<label class="smart:text-sm">{{ 'from' | translate }}</label>
|
|
1683
|
+
<smart-date-edit
|
|
1684
|
+
class="smart:flex-1"
|
|
1685
|
+
[ngModel]="customMinValue || ''"
|
|
1686
|
+
(ngModelChange)="customMinValue = $event"
|
|
1687
|
+
></smart-date-edit>
|
|
1688
|
+
@if (hasMinValue()) {
|
|
1689
|
+
<button
|
|
1690
|
+
type="button"
|
|
1691
|
+
(click)="refresh(null, '>=')"
|
|
1692
|
+
aria-label="clear-from"
|
|
1693
|
+
class="smart:shrink-0 smart:rounded smart:px-2 smart:py-2 smart:text-red-600 smart:hover:bg-red-50"
|
|
1694
|
+
>
|
|
1695
|
+
×
|
|
1696
|
+
</button>
|
|
1697
|
+
}
|
|
1698
|
+
</div>
|
|
1699
|
+
<div class="smart:flex smart:w-full smart:items-end smart:gap-2">
|
|
1700
|
+
<label class="smart:text-sm">{{ 'to' | translate }}</label>
|
|
1701
|
+
<smart-date-edit
|
|
1702
|
+
class="smart:flex-1"
|
|
1703
|
+
[ngModel]="customMaxValue || ''"
|
|
1704
|
+
(ngModelChange)="customMaxValue = $event"
|
|
1705
|
+
></smart-date-edit>
|
|
1706
|
+
@if (hasMaxValue()) {
|
|
1707
|
+
<button
|
|
1708
|
+
type="button"
|
|
1709
|
+
(click)="refresh(null, '<=')"
|
|
1710
|
+
aria-label="clear-to"
|
|
1711
|
+
class="smart:shrink-0 smart:rounded smart:px-2 smart:py-2 smart:text-red-600 smart:hover:bg-red-50"
|
|
1712
|
+
>
|
|
1713
|
+
×
|
|
1714
|
+
</button>
|
|
1715
|
+
}
|
|
1716
|
+
</div>
|
|
1717
|
+
</div>
|
|
1718
|
+
}
|
|
1719
|
+
`, isInline: true, dependencies: [{ kind: "component", type: DateEditComponent, selector: "smart-date-edit", inputs: ["variant", "class", "ngModel"], outputs: ["ngModelChange", "validChange"] }, { kind: "ngmodule", type: FormsModule }, { 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: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
979
1720
|
}
|
|
980
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type:
|
|
1721
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FilterDateWithEditComponent, decorators: [{
|
|
981
1722
|
type: Component,
|
|
982
|
-
args: [{
|
|
1723
|
+
args: [{
|
|
1724
|
+
selector: 'smart-crud-filter-date-with-edit',
|
|
1725
|
+
host: { class: 'smart:block smart:w-full' },
|
|
1726
|
+
// TODO(FRA-293 GAP-19): re-sync picker when filter() changes externally
|
|
1727
|
+
template: `
|
|
1728
|
+
<label class="smart:mb-1 smart:block smart:text-sm smart:font-medium">
|
|
1729
|
+
{{ item()?.label || '' | translate }}
|
|
1730
|
+
</label>
|
|
1731
|
+
|
|
1732
|
+
@if (!advanced()) {
|
|
1733
|
+
<div class="smart:flex smart:w-full smart:items-end smart:gap-2">
|
|
1734
|
+
<smart-date-edit
|
|
1735
|
+
class="smart:flex-1"
|
|
1736
|
+
[ngModel]="customValue || ''"
|
|
1737
|
+
(ngModelChange)="customValue = $event"
|
|
1738
|
+
></smart-date-edit>
|
|
1739
|
+
@if (allowAdvanced) {
|
|
1740
|
+
<button
|
|
1741
|
+
type="button"
|
|
1742
|
+
(click)="toggleAdvanced()"
|
|
1743
|
+
aria-label="advanced"
|
|
1744
|
+
class="smart:shrink-0 smart:rounded smart:px-2 smart:py-2 smart:hover:bg-gray-100"
|
|
1745
|
+
>
|
|
1746
|
+
⚙
|
|
1747
|
+
</button>
|
|
1748
|
+
}
|
|
1749
|
+
@if (hasValue()) {
|
|
1750
|
+
<button
|
|
1751
|
+
type="button"
|
|
1752
|
+
(click)="refresh(null)"
|
|
1753
|
+
aria-label="clear"
|
|
1754
|
+
class="smart:shrink-0 smart:rounded smart:px-2 smart:py-2 smart:text-red-600 smart:hover:bg-red-50"
|
|
1755
|
+
>
|
|
1756
|
+
×
|
|
1757
|
+
</button>
|
|
1758
|
+
}
|
|
1759
|
+
</div>
|
|
1760
|
+
} @else if (allowAdvanced) {
|
|
1761
|
+
<button
|
|
1762
|
+
type="button"
|
|
1763
|
+
(click)="toggleAdvanced()"
|
|
1764
|
+
aria-label="advanced"
|
|
1765
|
+
class="smart:mb-2 smart:rounded smart:px-2 smart:py-2 smart:hover:bg-gray-100"
|
|
1766
|
+
>
|
|
1767
|
+
⚙
|
|
1768
|
+
</button>
|
|
1769
|
+
}
|
|
1770
|
+
|
|
1771
|
+
@if ((advanced() || hasMinValue() || hasMaxValue()) && allowAdvanced) {
|
|
1772
|
+
<div class="smart:flex smart:w-full smart:flex-col smart:gap-2">
|
|
1773
|
+
<div class="smart:flex smart:w-full smart:items-end smart:gap-2">
|
|
1774
|
+
<label class="smart:text-sm">{{ 'from' | translate }}</label>
|
|
1775
|
+
<smart-date-edit
|
|
1776
|
+
class="smart:flex-1"
|
|
1777
|
+
[ngModel]="customMinValue || ''"
|
|
1778
|
+
(ngModelChange)="customMinValue = $event"
|
|
1779
|
+
></smart-date-edit>
|
|
1780
|
+
@if (hasMinValue()) {
|
|
1781
|
+
<button
|
|
1782
|
+
type="button"
|
|
1783
|
+
(click)="refresh(null, '>=')"
|
|
1784
|
+
aria-label="clear-from"
|
|
1785
|
+
class="smart:shrink-0 smart:rounded smart:px-2 smart:py-2 smart:text-red-600 smart:hover:bg-red-50"
|
|
1786
|
+
>
|
|
1787
|
+
×
|
|
1788
|
+
</button>
|
|
1789
|
+
}
|
|
1790
|
+
</div>
|
|
1791
|
+
<div class="smart:flex smart:w-full smart:items-end smart:gap-2">
|
|
1792
|
+
<label class="smart:text-sm">{{ 'to' | translate }}</label>
|
|
1793
|
+
<smart-date-edit
|
|
1794
|
+
class="smart:flex-1"
|
|
1795
|
+
[ngModel]="customMaxValue || ''"
|
|
1796
|
+
(ngModelChange)="customMaxValue = $event"
|
|
1797
|
+
></smart-date-edit>
|
|
1798
|
+
@if (hasMaxValue()) {
|
|
1799
|
+
<button
|
|
1800
|
+
type="button"
|
|
1801
|
+
(click)="refresh(null, '<=')"
|
|
1802
|
+
aria-label="clear-to"
|
|
1803
|
+
class="smart:shrink-0 smart:rounded smart:px-2 smart:py-2 smart:text-red-600 smart:hover:bg-red-50"
|
|
1804
|
+
>
|
|
1805
|
+
×
|
|
1806
|
+
</button>
|
|
1807
|
+
}
|
|
1808
|
+
</div>
|
|
1809
|
+
</div>
|
|
1810
|
+
}
|
|
1811
|
+
`,
|
|
1812
|
+
imports: [DateEditComponent, FormsModule, TranslatePipe],
|
|
1813
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1814
|
+
}]
|
|
983
1815
|
}] });
|
|
984
1816
|
|
|
985
|
-
class
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
id = GuidService.create();
|
|
989
|
-
// @ViewChild(IonDatetime, { read: IonDatetime, static: false })
|
|
990
|
-
// dateTimePicker: IonDatetime;
|
|
991
|
-
toggleAdvanced() {
|
|
992
|
-
this.advanced.update((val) => !val);
|
|
993
|
-
if (this.advanced()) {
|
|
994
|
-
this.value = null;
|
|
995
|
-
}
|
|
996
|
-
}
|
|
1817
|
+
class FilterFlagComponent extends BaseComponent {
|
|
1818
|
+
inputOptions = signal(undefined, ...(ngDevMode ? [{ debugName: "inputOptions" }] : []));
|
|
1819
|
+
fieldOptions = signal(undefined, ...(ngDevMode ? [{ debugName: "fieldOptions" }] : []));
|
|
997
1820
|
ngOnInit() {
|
|
998
1821
|
super.ngOnInit();
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
// this.dateTimePicker.ionChange.subscribe((val: CustomEvent) => {
|
|
1002
|
-
// this.customValue = val.detail.value;
|
|
1003
|
-
// }),
|
|
1004
|
-
// );
|
|
1005
|
-
// } else {
|
|
1006
|
-
// console.error('dateTimePicker not found!');
|
|
1007
|
-
// }
|
|
1822
|
+
const control = this.bindValueControl();
|
|
1823
|
+
this.inputOptions.set(this.buildInputOptions(control));
|
|
1008
1824
|
}
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1825
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FilterFlagComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
1826
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: FilterFlagComponent, isStandalone: true, selector: "smart-crud-filter-flag", host: { classAttribute: "smart:block smart:w-full" }, usesInheritance: true, ngImport: i0, template: `
|
|
1827
|
+
@if (inputOptions()) {
|
|
1828
|
+
<div class="smart:flex smart:w-full smart:items-center smart:gap-2">
|
|
1829
|
+
<smart-input-flag
|
|
1830
|
+
class="smart:flex-1"
|
|
1831
|
+
[options]="inputOptions()!"
|
|
1832
|
+
[fieldOptions]="fieldOptions()"
|
|
1833
|
+
></smart-input-flag>
|
|
1834
|
+
@if (value === true || value === false) {
|
|
1835
|
+
<button
|
|
1836
|
+
type="button"
|
|
1837
|
+
(click)="refresh(null)"
|
|
1838
|
+
aria-label="clear"
|
|
1839
|
+
class="smart:shrink-0 smart:rounded smart:px-2 smart:py-2 smart:text-red-600 smart:hover:bg-red-50"
|
|
1840
|
+
>
|
|
1841
|
+
×
|
|
1842
|
+
</button>
|
|
1012
1843
|
}
|
|
1844
|
+
</div>
|
|
1013
1845
|
}
|
|
1014
|
-
|
|
1015
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: FilterDateWithEditComponent, isStandalone: true, selector: "smart-crud-filter-date-with-edit", usesInheritance: true, ngImport: i0, template: "<!--<ion-row>-->\n<!-- <ion-col>-->\n<!-- <ion-label>-->\n{{ item()?.label || '' | translate }}\n<!-- </ion-label>-->\n\n@if (!advanced()) {\n <!-- <ion-input-->\n <!-- placeholder=\"YYYY-MM-DD\"-->\n <!-- [(ngModel)]=\"customValue\"-->\n <!-- [pattern]=\"'([12]\\\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\\\d|3[01]))'\"-->\n <!-- ></ion-input>-->\n}\n<!-- </ion-col>-->\n\n@if (!advanced()) {\n <!-- <ion-col size=\"auto\">-->\n <!-- <ion-button id=\"open-date-input-{{ id }}\" class=\"square-button m-3\">-->\n <!-- <ion-icon slot=\"icon-only\" name=\"calendar-outline\"></ion-icon>-->\n <!-- <ion-popover trigger=\"open-date-input-{{ id }}\" show-backdrop=\"false\">-->\n <ng-template>\n <!-- <ion-datetime-->\n <!-- displayFormat=\"YYYY-MM-DD\"-->\n <!-- pickerFormat=\"YYYY-MM-DD\"-->\n <!-- [(ngModel)]=\"customValue\"-->\n <!-- presentation=\"date\"-->\n <!-- first-day-of-week=\"1\"-->\n <!-- locale=\"{{ lang }}\"-->\n <!-- ></ion-datetime>-->\n </ng-template>\n <!-- </ion-popover>-->\n <!-- </ion-button>-->\n <!-- </ion-col>-->\n}\n@if (allowAdvanced) {\n <!-- <ion-col size=\"auto\">-->\n <!-- <ion-button-->\n <!-- (click)=\"toggleAdvanced()\"-->\n <!-- class=\"square-button m-3\"-->\n <!-- [disabled]=\"minValue || maxValue\"-->\n <!-- >-->\n @if (!advanced()) {\n <!-- <ion-icon slot=\"icon-only\" name=\"settings-outline\"></ion-icon>-->\n } @else {\n <!-- <ion-icon slot=\"icon-only\" name=\"settings\"></ion-icon>-->\n }\n <!-- </ion-button>-->\n <!-- </ion-col>-->\n}\n@if (value || minValue || maxValue) {\n <!-- <ion-col size=\"auto\">-->\n <!-- <ion-button color=\"danger\" (click)=\"clear()\" class=\"square-button m-3\">-->\n <!-- <ion-icon slot=\"icon-only\" name=\"close-outline\"></ion-icon>-->\n <!-- </ion-button>-->\n <!-- </ion-col>-->\n}\n<!--</ion-row>-->\n\n@if ((advanced() || minValue || maxValue) && allowAdvanced) {\n <!-- <ion-row>-->\n <!-- <ion-col>-->\n <!-- <ion-item>-->\n <!-- <ion-label>-->\n {{ 'from' | translate }}\n <!-- </ion-label>-->\n <!-- <ion-input-->\n <!-- placeholder=\"YYYY-MM-DD\"-->\n <!-- [(ngModel)]=\"customMinValue\"-->\n <!-- [pattern]=\"'([12]\\\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\\\d|3[01]))'\"-->\n <!-- ></ion-input>-->\n <!-- </ion-item>-->\n <!-- </ion-col>-->\n @if (customMinValue) {\n <!-- <ion-col size=\"auto\">-->\n <!-- <ion-button-->\n <!-- color=\"danger\"-->\n <!-- (click)=\"refresh(null, '>=')\"-->\n <!-- class=\"square-button m-3\"-->\n <!-- >-->\n <!-- <ion-icon slot=\"icon-only\" name=\"close-outline\"></ion-icon>-->\n <!-- </ion-button>-->\n <!-- </ion-col>-->\n }\n <!-- <ion-col>-->\n <!-- <ion-item>-->\n <!-- <ion-label>-->\n {{ 'to' | translate }}\n <!-- </ion-label>-->\n <!-- <ion-input-->\n <!-- placeholder=\"YYYY-MM-DD\"-->\n <!-- [(ngModel)]=\"customMaxValue\"-->\n <!-- [pattern]=\"'([12]\\\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\\\d|3[01]))'\"-->\n <!-- ></ion-input>-->\n <!-- </ion-item>-->\n <!-- </ion-col>-->\n\n @if (customMaxValue) {\n <!-- <ion-col size=\"auto\">-->\n <!-- <ion-button-->\n <!-- color=\"danger\"-->\n <!-- (click)=\"refresh(null, '<=')\"-->\n <!-- class=\"square-button m-3\"-->\n <!-- >-->\n <!-- <ion-icon slot=\"icon-only\" name=\"close-outline\"></ion-icon>-->\n <!-- </ion-button>-->\n <!-- </ion-col>-->\n }\n <!-- </ion-row>-->\n}\n", styles: [":host{width:100%}:host .square-button{height:var(--smart-button-height)!important}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
|
|
1016
|
-
}
|
|
1017
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FilterDateWithEditComponent, decorators: [{
|
|
1018
|
-
type: Component,
|
|
1019
|
-
args: [{ selector: 'smart-crud-filter-date-with-edit', imports: [TranslatePipe, FormsModule], template: "<!--<ion-row>-->\n<!-- <ion-col>-->\n<!-- <ion-label>-->\n{{ item()?.label || '' | translate }}\n<!-- </ion-label>-->\n\n@if (!advanced()) {\n <!-- <ion-input-->\n <!-- placeholder=\"YYYY-MM-DD\"-->\n <!-- [(ngModel)]=\"customValue\"-->\n <!-- [pattern]=\"'([12]\\\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\\\d|3[01]))'\"-->\n <!-- ></ion-input>-->\n}\n<!-- </ion-col>-->\n\n@if (!advanced()) {\n <!-- <ion-col size=\"auto\">-->\n <!-- <ion-button id=\"open-date-input-{{ id }}\" class=\"square-button m-3\">-->\n <!-- <ion-icon slot=\"icon-only\" name=\"calendar-outline\"></ion-icon>-->\n <!-- <ion-popover trigger=\"open-date-input-{{ id }}\" show-backdrop=\"false\">-->\n <ng-template>\n <!-- <ion-datetime-->\n <!-- displayFormat=\"YYYY-MM-DD\"-->\n <!-- pickerFormat=\"YYYY-MM-DD\"-->\n <!-- [(ngModel)]=\"customValue\"-->\n <!-- presentation=\"date\"-->\n <!-- first-day-of-week=\"1\"-->\n <!-- locale=\"{{ lang }}\"-->\n <!-- ></ion-datetime>-->\n </ng-template>\n <!-- </ion-popover>-->\n <!-- </ion-button>-->\n <!-- </ion-col>-->\n}\n@if (allowAdvanced) {\n <!-- <ion-col size=\"auto\">-->\n <!-- <ion-button-->\n <!-- (click)=\"toggleAdvanced()\"-->\n <!-- class=\"square-button m-3\"-->\n <!-- [disabled]=\"minValue || maxValue\"-->\n <!-- >-->\n @if (!advanced()) {\n <!-- <ion-icon slot=\"icon-only\" name=\"settings-outline\"></ion-icon>-->\n } @else {\n <!-- <ion-icon slot=\"icon-only\" name=\"settings\"></ion-icon>-->\n }\n <!-- </ion-button>-->\n <!-- </ion-col>-->\n}\n@if (value || minValue || maxValue) {\n <!-- <ion-col size=\"auto\">-->\n <!-- <ion-button color=\"danger\" (click)=\"clear()\" class=\"square-button m-3\">-->\n <!-- <ion-icon slot=\"icon-only\" name=\"close-outline\"></ion-icon>-->\n <!-- </ion-button>-->\n <!-- </ion-col>-->\n}\n<!--</ion-row>-->\n\n@if ((advanced() || minValue || maxValue) && allowAdvanced) {\n <!-- <ion-row>-->\n <!-- <ion-col>-->\n <!-- <ion-item>-->\n <!-- <ion-label>-->\n {{ 'from' | translate }}\n <!-- </ion-label>-->\n <!-- <ion-input-->\n <!-- placeholder=\"YYYY-MM-DD\"-->\n <!-- [(ngModel)]=\"customMinValue\"-->\n <!-- [pattern]=\"'([12]\\\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\\\d|3[01]))'\"-->\n <!-- ></ion-input>-->\n <!-- </ion-item>-->\n <!-- </ion-col>-->\n @if (customMinValue) {\n <!-- <ion-col size=\"auto\">-->\n <!-- <ion-button-->\n <!-- color=\"danger\"-->\n <!-- (click)=\"refresh(null, '>=')\"-->\n <!-- class=\"square-button m-3\"-->\n <!-- >-->\n <!-- <ion-icon slot=\"icon-only\" name=\"close-outline\"></ion-icon>-->\n <!-- </ion-button>-->\n <!-- </ion-col>-->\n }\n <!-- <ion-col>-->\n <!-- <ion-item>-->\n <!-- <ion-label>-->\n {{ 'to' | translate }}\n <!-- </ion-label>-->\n <!-- <ion-input-->\n <!-- placeholder=\"YYYY-MM-DD\"-->\n <!-- [(ngModel)]=\"customMaxValue\"-->\n <!-- [pattern]=\"'([12]\\\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\\\d|3[01]))'\"-->\n <!-- ></ion-input>-->\n <!-- </ion-item>-->\n <!-- </ion-col>-->\n\n @if (customMaxValue) {\n <!-- <ion-col size=\"auto\">-->\n <!-- <ion-button-->\n <!-- color=\"danger\"-->\n <!-- (click)=\"refresh(null, '<=')\"-->\n <!-- class=\"square-button m-3\"-->\n <!-- >-->\n <!-- <ion-icon slot=\"icon-only\" name=\"close-outline\"></ion-icon>-->\n <!-- </ion-button>-->\n <!-- </ion-col>-->\n }\n <!-- </ion-row>-->\n}\n", styles: [":host{width:100%}:host .square-button{height:var(--smart-button-height)!important}\n"] }]
|
|
1020
|
-
}] });
|
|
1021
|
-
|
|
1022
|
-
class FilterFlagComponent extends BaseComponent {
|
|
1023
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FilterFlagComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
1024
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: FilterFlagComponent, isStandalone: true, selector: "smart-crud-filter-flag", usesInheritance: true, ngImport: i0, template: `
|
|
1025
|
-
<!-- <ion-row>-->
|
|
1026
|
-
<!-- <ion-col>-->
|
|
1027
|
-
<div
|
|
1028
|
-
class="flag-container w-full flex flex-row flex-nowrap justify-between pr-5"
|
|
1029
|
-
>
|
|
1030
|
-
<!-- <ion-label class="align-middle my-6" position="static">-->
|
|
1031
|
-
{{ item()?.label || '' | translate }}
|
|
1032
|
-
<!-- </ion-label>-->
|
|
1033
|
-
<!-- <ion-checkbox [(ngModel)]="value" slot="end"></ion-checkbox>-->
|
|
1034
|
-
</div>
|
|
1035
|
-
<!-- </ion-col>-->
|
|
1036
|
-
@if (typeof value === 'boolean') {
|
|
1037
|
-
<!-- <ion-col size="auto">-->
|
|
1038
|
-
<!-- <ion-button-->
|
|
1039
|
-
<!-- color="danger"-->
|
|
1040
|
-
<!-- (click)="refresh(null)"-->
|
|
1041
|
-
<!-- class="square-button m-3"-->
|
|
1042
|
-
<!-- >-->
|
|
1043
|
-
<!-- <ion-icon slot="icon-only" name="close-outline"></ion-icon>-->
|
|
1044
|
-
<!-- </ion-button>-->
|
|
1045
|
-
<!-- </ion-col>-->
|
|
1046
|
-
}
|
|
1047
|
-
<!-- </ion-row>-->
|
|
1048
|
-
`, isInline: true, styles: [":host{width:100%}:host .square-button{height:var(--smart-button-height)!important}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
|
|
1846
|
+
`, isInline: true, dependencies: [{ kind: "component", type: InputFlagComponent, selector: "smart-input-flag" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1049
1847
|
}
|
|
1050
1848
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FilterFlagComponent, decorators: [{
|
|
1051
1849
|
type: Component,
|
|
1052
|
-
args: [{
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
}
|
|
1075
|
-
|
|
1076
|
-
|
|
1850
|
+
args: [{
|
|
1851
|
+
selector: 'smart-crud-filter-flag',
|
|
1852
|
+
host: { class: 'smart:block smart:w-full' },
|
|
1853
|
+
template: `
|
|
1854
|
+
@if (inputOptions()) {
|
|
1855
|
+
<div class="smart:flex smart:w-full smart:items-center smart:gap-2">
|
|
1856
|
+
<smart-input-flag
|
|
1857
|
+
class="smart:flex-1"
|
|
1858
|
+
[options]="inputOptions()!"
|
|
1859
|
+
[fieldOptions]="fieldOptions()"
|
|
1860
|
+
></smart-input-flag>
|
|
1861
|
+
@if (value === true || value === false) {
|
|
1862
|
+
<button
|
|
1863
|
+
type="button"
|
|
1864
|
+
(click)="refresh(null)"
|
|
1865
|
+
aria-label="clear"
|
|
1866
|
+
class="smart:shrink-0 smart:rounded smart:px-2 smart:py-2 smart:text-red-600 smart:hover:bg-red-50"
|
|
1867
|
+
>
|
|
1868
|
+
×
|
|
1869
|
+
</button>
|
|
1870
|
+
}
|
|
1871
|
+
</div>
|
|
1872
|
+
}
|
|
1873
|
+
`,
|
|
1874
|
+
imports: [InputFlagComponent],
|
|
1875
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1876
|
+
}]
|
|
1077
1877
|
}] });
|
|
1078
1878
|
|
|
1879
|
+
// TODO(FRA-293 GAP-19): the advanced range controls (minControl/maxControl)
|
|
1880
|
+
// are not re-synced when filter() changes externally; see bindControl().
|
|
1079
1881
|
class FilterIntComponent extends BaseComponent {
|
|
1080
|
-
|
|
1882
|
+
valueOptions = signal(undefined, ...(ngDevMode ? [{ debugName: "valueOptions" }] : []));
|
|
1883
|
+
valueFieldOptions = signal(undefined, ...(ngDevMode ? [{ debugName: "valueFieldOptions" }] : []));
|
|
1081
1884
|
advanced = signal(false, ...(ngDevMode ? [{ debugName: "advanced" }] : []));
|
|
1885
|
+
minControl;
|
|
1886
|
+
maxControl;
|
|
1082
1887
|
get allowAdvanced() {
|
|
1083
1888
|
return this.item()?.type === '=';
|
|
1084
1889
|
}
|
|
1085
1890
|
ngOnInit() {
|
|
1086
1891
|
super.ngOnInit();
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1892
|
+
const valueControl = this.bindControl(null);
|
|
1893
|
+
this.minControl = this.bindControl('>=');
|
|
1894
|
+
this.maxControl = this.bindControl('<=');
|
|
1895
|
+
this.valueOptions.set(this.buildInputOptions(valueControl));
|
|
1896
|
+
this.valueFieldOptions.set(undefined);
|
|
1092
1897
|
}
|
|
1093
1898
|
toggleAdvanced() {
|
|
1094
1899
|
this.advanced.update((val) => !val);
|
|
@@ -1096,129 +1901,319 @@ class FilterIntComponent extends BaseComponent {
|
|
|
1096
1901
|
this.value = null;
|
|
1097
1902
|
}
|
|
1098
1903
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FilterIntComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
1099
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: FilterIntComponent, isStandalone: true, selector: "smart-crud-filter-int",
|
|
1904
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: FilterIntComponent, isStandalone: true, selector: "smart-crud-filter-int", host: { classAttribute: "smart:block smart:w-full" }, usesInheritance: true, ngImport: i0, template: `
|
|
1905
|
+
@if (valueOptions()) {
|
|
1906
|
+
<div class="smart:flex smart:w-full smart:items-end smart:gap-2">
|
|
1907
|
+
@if (!advanced()) {
|
|
1908
|
+
<smart-input-int
|
|
1909
|
+
class="smart:flex-1"
|
|
1910
|
+
[options]="valueOptions()!"
|
|
1911
|
+
[fieldOptions]="valueFieldOptions()"
|
|
1912
|
+
></smart-input-int>
|
|
1913
|
+
}
|
|
1914
|
+
|
|
1915
|
+
@if (allowAdvanced) {
|
|
1916
|
+
<button
|
|
1917
|
+
type="button"
|
|
1918
|
+
(click)="toggleAdvanced()"
|
|
1919
|
+
[disabled]="hasMinValue() || hasMaxValue()"
|
|
1920
|
+
aria-label="settings"
|
|
1921
|
+
class="smart:shrink-0 smart:rounded smart:px-2 smart:py-2 smart:text-gray-600 smart:hover:bg-gray-100 smart:disabled:opacity-40"
|
|
1922
|
+
>
|
|
1923
|
+
⚙
|
|
1924
|
+
</button>
|
|
1925
|
+
}
|
|
1926
|
+
|
|
1927
|
+
@if (hasValue() || hasMinValue() || hasMaxValue()) {
|
|
1928
|
+
<button
|
|
1929
|
+
type="button"
|
|
1930
|
+
(click)="clear()"
|
|
1931
|
+
aria-label="clear"
|
|
1932
|
+
class="smart:shrink-0 smart:rounded smart:px-2 smart:py-2 smart:text-red-600 smart:hover:bg-red-50"
|
|
1933
|
+
>
|
|
1934
|
+
×
|
|
1935
|
+
</button>
|
|
1936
|
+
}
|
|
1937
|
+
</div>
|
|
1938
|
+
|
|
1939
|
+
@if ((advanced() || hasMinValue() || hasMaxValue()) && allowAdvanced) {
|
|
1940
|
+
<div
|
|
1941
|
+
class="smart:mt-2 smart:flex smart:w-full smart:items-end smart:gap-2"
|
|
1942
|
+
>
|
|
1943
|
+
<div class="smart:flex-1">
|
|
1944
|
+
<label
|
|
1945
|
+
class="smart:block smart:text-sm/6 smart:font-medium smart:text-gray-900 smart:dark:text-white"
|
|
1946
|
+
>
|
|
1947
|
+
{{ 'from' | translate }}
|
|
1948
|
+
</label>
|
|
1949
|
+
<input
|
|
1950
|
+
type="number"
|
|
1951
|
+
step="1"
|
|
1952
|
+
[formControl]="minControl"
|
|
1953
|
+
class="smart:mt-2 smart:block smart:w-full smart:rounded-md smart:bg-white smart:px-3 smart:py-1.5 smart:text-base smart:text-gray-900 smart:outline-1 -outline-offset-1 smart:outline-gray-300 smart:focus:outline-2 smart:focus:outline-offset-2 smart:focus:outline-indigo-600 smart:dark:bg-white/5 smart:dark:text-white smart:dark:outline-white/10"
|
|
1954
|
+
/>
|
|
1955
|
+
</div>
|
|
1956
|
+
@if (hasMinValue()) {
|
|
1957
|
+
<button
|
|
1958
|
+
type="button"
|
|
1959
|
+
(click)="refresh(null, '>=')"
|
|
1960
|
+
aria-label="clear-from"
|
|
1961
|
+
class="smart:shrink-0 smart:rounded smart:px-2 smart:py-2 smart:text-red-600 smart:hover:bg-red-50"
|
|
1962
|
+
>
|
|
1963
|
+
×
|
|
1964
|
+
</button>
|
|
1965
|
+
}
|
|
1966
|
+
|
|
1967
|
+
<div class="smart:flex-1">
|
|
1968
|
+
<label
|
|
1969
|
+
class="smart:block smart:text-sm/6 smart:font-medium smart:text-gray-900 smart:dark:text-white"
|
|
1970
|
+
>
|
|
1971
|
+
{{ 'to' | translate }}
|
|
1972
|
+
</label>
|
|
1973
|
+
<input
|
|
1974
|
+
type="number"
|
|
1975
|
+
step="1"
|
|
1976
|
+
[formControl]="maxControl"
|
|
1977
|
+
class="smart:mt-2 smart:block smart:w-full smart:rounded-md smart:bg-white smart:px-3 smart:py-1.5 smart:text-base smart:text-gray-900 smart:outline-1 -outline-offset-1 smart:outline-gray-300 smart:focus:outline-2 smart:focus:outline-offset-2 smart:focus:outline-indigo-600 smart:dark:bg-white/5 smart:dark:text-white smart:dark:outline-white/10"
|
|
1978
|
+
/>
|
|
1979
|
+
</div>
|
|
1980
|
+
@if (hasMaxValue()) {
|
|
1981
|
+
<button
|
|
1982
|
+
type="button"
|
|
1983
|
+
(click)="refresh(null, '<=')"
|
|
1984
|
+
aria-label="clear-to"
|
|
1985
|
+
class="smart:shrink-0 smart:rounded smart:px-2 smart:py-2 smart:text-red-600 smart:hover:bg-red-50"
|
|
1986
|
+
>
|
|
1987
|
+
×
|
|
1988
|
+
</button>
|
|
1989
|
+
}
|
|
1990
|
+
</div>
|
|
1991
|
+
}
|
|
1992
|
+
}
|
|
1993
|
+
`, isInline: true, dependencies: [{ kind: "component", type: InputIntComponent, selector: "smart-input-int" }, { kind: "ngmodule", type: ReactiveFormsModule }, { 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.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1100
1994
|
}
|
|
1101
1995
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FilterIntComponent, decorators: [{
|
|
1102
1996
|
type: Component,
|
|
1103
|
-
args: [{
|
|
1997
|
+
args: [{
|
|
1998
|
+
selector: 'smart-crud-filter-int',
|
|
1999
|
+
host: { class: 'smart:block smart:w-full' },
|
|
2000
|
+
template: `
|
|
2001
|
+
@if (valueOptions()) {
|
|
2002
|
+
<div class="smart:flex smart:w-full smart:items-end smart:gap-2">
|
|
2003
|
+
@if (!advanced()) {
|
|
2004
|
+
<smart-input-int
|
|
2005
|
+
class="smart:flex-1"
|
|
2006
|
+
[options]="valueOptions()!"
|
|
2007
|
+
[fieldOptions]="valueFieldOptions()"
|
|
2008
|
+
></smart-input-int>
|
|
2009
|
+
}
|
|
2010
|
+
|
|
2011
|
+
@if (allowAdvanced) {
|
|
2012
|
+
<button
|
|
2013
|
+
type="button"
|
|
2014
|
+
(click)="toggleAdvanced()"
|
|
2015
|
+
[disabled]="hasMinValue() || hasMaxValue()"
|
|
2016
|
+
aria-label="settings"
|
|
2017
|
+
class="smart:shrink-0 smart:rounded smart:px-2 smart:py-2 smart:text-gray-600 smart:hover:bg-gray-100 smart:disabled:opacity-40"
|
|
2018
|
+
>
|
|
2019
|
+
⚙
|
|
2020
|
+
</button>
|
|
2021
|
+
}
|
|
2022
|
+
|
|
2023
|
+
@if (hasValue() || hasMinValue() || hasMaxValue()) {
|
|
2024
|
+
<button
|
|
2025
|
+
type="button"
|
|
2026
|
+
(click)="clear()"
|
|
2027
|
+
aria-label="clear"
|
|
2028
|
+
class="smart:shrink-0 smart:rounded smart:px-2 smart:py-2 smart:text-red-600 smart:hover:bg-red-50"
|
|
2029
|
+
>
|
|
2030
|
+
×
|
|
2031
|
+
</button>
|
|
2032
|
+
}
|
|
2033
|
+
</div>
|
|
2034
|
+
|
|
2035
|
+
@if ((advanced() || hasMinValue() || hasMaxValue()) && allowAdvanced) {
|
|
2036
|
+
<div
|
|
2037
|
+
class="smart:mt-2 smart:flex smart:w-full smart:items-end smart:gap-2"
|
|
2038
|
+
>
|
|
2039
|
+
<div class="smart:flex-1">
|
|
2040
|
+
<label
|
|
2041
|
+
class="smart:block smart:text-sm/6 smart:font-medium smart:text-gray-900 smart:dark:text-white"
|
|
2042
|
+
>
|
|
2043
|
+
{{ 'from' | translate }}
|
|
2044
|
+
</label>
|
|
2045
|
+
<input
|
|
2046
|
+
type="number"
|
|
2047
|
+
step="1"
|
|
2048
|
+
[formControl]="minControl"
|
|
2049
|
+
class="smart:mt-2 smart:block smart:w-full smart:rounded-md smart:bg-white smart:px-3 smart:py-1.5 smart:text-base smart:text-gray-900 smart:outline-1 -outline-offset-1 smart:outline-gray-300 smart:focus:outline-2 smart:focus:outline-offset-2 smart:focus:outline-indigo-600 smart:dark:bg-white/5 smart:dark:text-white smart:dark:outline-white/10"
|
|
2050
|
+
/>
|
|
2051
|
+
</div>
|
|
2052
|
+
@if (hasMinValue()) {
|
|
2053
|
+
<button
|
|
2054
|
+
type="button"
|
|
2055
|
+
(click)="refresh(null, '>=')"
|
|
2056
|
+
aria-label="clear-from"
|
|
2057
|
+
class="smart:shrink-0 smart:rounded smart:px-2 smart:py-2 smart:text-red-600 smart:hover:bg-red-50"
|
|
2058
|
+
>
|
|
2059
|
+
×
|
|
2060
|
+
</button>
|
|
2061
|
+
}
|
|
2062
|
+
|
|
2063
|
+
<div class="smart:flex-1">
|
|
2064
|
+
<label
|
|
2065
|
+
class="smart:block smart:text-sm/6 smart:font-medium smart:text-gray-900 smart:dark:text-white"
|
|
2066
|
+
>
|
|
2067
|
+
{{ 'to' | translate }}
|
|
2068
|
+
</label>
|
|
2069
|
+
<input
|
|
2070
|
+
type="number"
|
|
2071
|
+
step="1"
|
|
2072
|
+
[formControl]="maxControl"
|
|
2073
|
+
class="smart:mt-2 smart:block smart:w-full smart:rounded-md smart:bg-white smart:px-3 smart:py-1.5 smart:text-base smart:text-gray-900 smart:outline-1 -outline-offset-1 smart:outline-gray-300 smart:focus:outline-2 smart:focus:outline-offset-2 smart:focus:outline-indigo-600 smart:dark:bg-white/5 smart:dark:text-white smart:dark:outline-white/10"
|
|
2074
|
+
/>
|
|
2075
|
+
</div>
|
|
2076
|
+
@if (hasMaxValue()) {
|
|
2077
|
+
<button
|
|
2078
|
+
type="button"
|
|
2079
|
+
(click)="refresh(null, '<=')"
|
|
2080
|
+
aria-label="clear-to"
|
|
2081
|
+
class="smart:shrink-0 smart:rounded smart:px-2 smart:py-2 smart:text-red-600 smart:hover:bg-red-50"
|
|
2082
|
+
>
|
|
2083
|
+
×
|
|
2084
|
+
</button>
|
|
2085
|
+
}
|
|
2086
|
+
</div>
|
|
2087
|
+
}
|
|
2088
|
+
}
|
|
2089
|
+
`,
|
|
2090
|
+
imports: [InputIntComponent, ReactiveFormsModule, TranslatePipe],
|
|
2091
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
2092
|
+
}]
|
|
1104
2093
|
}] });
|
|
1105
2094
|
|
|
1106
2095
|
class FilterRadioComponent extends BaseComponent {
|
|
2096
|
+
inputOptions = signal(undefined, ...(ngDevMode ? [{ debugName: "inputOptions" }] : []));
|
|
2097
|
+
fieldOptions = signal(undefined, ...(ngDevMode ? [{ debugName: "fieldOptions" }] : []));
|
|
2098
|
+
ngOnInit() {
|
|
2099
|
+
super.ngOnInit();
|
|
2100
|
+
const control = this.bindControl(null);
|
|
2101
|
+
this.inputOptions.set(this.buildInputOptions(control, true));
|
|
2102
|
+
}
|
|
1107
2103
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FilterRadioComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
1108
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: FilterRadioComponent, isStandalone: true, selector: "smart-crud-filter-radio", usesInheritance: true, ngImport: i0, template: `
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
@for (item of possibilities(); track item) {
|
|
1130
|
-
<!-- <ion-item>-->
|
|
1131
|
-
<!-- <ion-label>{{ item.text | translate }}</ion-label>-->
|
|
1132
|
-
<!-- <ion-radio class="mr-10" [value]="item.id"></ion-radio>-->
|
|
1133
|
-
<!-- </ion-item>-->
|
|
1134
|
-
}
|
|
1135
|
-
<!-- </ion-radio-group>-->
|
|
1136
|
-
<!-- </ion-col>-->
|
|
1137
|
-
<!-- </ion-row>-->
|
|
1138
|
-
`, isInline: true, styles: [":host{width:100%;margin-bottom:1.2rem}:host ion-item-divider{//--padding-end: .8rem;//--ion-background-color: linear-gradient(// 90deg,// transparent,// var(--ion-color-light) //)}:host ion-item-divider ion-icon{//--color: var(--ion-color-primary)}:host ion-item-divider ion-label{//--padding: var(--smart-button-padding-left) / 2 // var(--smart-button-padding-top) / 2 var(--smart-button-padding-right) / // 2 var(--smart-button-padding-bottom) / 2}:host ion-item-divider .square-button{//--padding-start: .2em;//--padding-end: .2em}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
|
|
2104
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: FilterRadioComponent, isStandalone: true, selector: "smart-crud-filter-radio", host: { classAttribute: "smart:mb-5 smart:block smart:w-full" }, usesInheritance: true, ngImport: i0, template: `
|
|
2105
|
+
@if (inputOptions()) {
|
|
2106
|
+
<div class="smart:flex smart:w-full smart:items-start smart:gap-2">
|
|
2107
|
+
<smart-input-radio
|
|
2108
|
+
class="smart:flex-1"
|
|
2109
|
+
[options]="inputOptions()!"
|
|
2110
|
+
[fieldOptions]="fieldOptions()"
|
|
2111
|
+
></smart-input-radio>
|
|
2112
|
+
@if (value || value === false) {
|
|
2113
|
+
<button
|
|
2114
|
+
type="button"
|
|
2115
|
+
(click)="refresh(null)"
|
|
2116
|
+
aria-label="clear"
|
|
2117
|
+
class="smart:shrink-0 smart:rounded smart:px-2 smart:py-1 smart:text-red-600 smart:hover:bg-red-50"
|
|
2118
|
+
>
|
|
2119
|
+
×
|
|
2120
|
+
</button>
|
|
2121
|
+
}
|
|
2122
|
+
</div>
|
|
2123
|
+
}
|
|
2124
|
+
`, isInline: true, dependencies: [{ kind: "component", type: InputRadioComponent, selector: "smart-input-radio" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1139
2125
|
}
|
|
1140
2126
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FilterRadioComponent, decorators: [{
|
|
1141
2127
|
type: Component,
|
|
1142
|
-
args: [{
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
<!-- </ion-radio-group>-->
|
|
1170
|
-
<!-- </ion-col>-->
|
|
1171
|
-
<!-- </ion-row>-->
|
|
1172
|
-
`, imports: [TranslatePipe, FormsModule], styles: [":host{width:100%;margin-bottom:1.2rem}:host ion-item-divider{//--padding-end: .8rem;//--ion-background-color: linear-gradient(// 90deg,// transparent,// var(--ion-color-light) //)}:host ion-item-divider ion-icon{//--color: var(--ion-color-primary)}:host ion-item-divider ion-label{//--padding: var(--smart-button-padding-left) / 2 // var(--smart-button-padding-top) / 2 var(--smart-button-padding-right) / // 2 var(--smart-button-padding-bottom) / 2}:host ion-item-divider .square-button{//--padding-start: .2em;//--padding-end: .2em}\n"] }]
|
|
2128
|
+
args: [{
|
|
2129
|
+
selector: 'smart-crud-filter-radio',
|
|
2130
|
+
host: { class: 'smart:mb-5 smart:block smart:w-full' },
|
|
2131
|
+
template: `
|
|
2132
|
+
@if (inputOptions()) {
|
|
2133
|
+
<div class="smart:flex smart:w-full smart:items-start smart:gap-2">
|
|
2134
|
+
<smart-input-radio
|
|
2135
|
+
class="smart:flex-1"
|
|
2136
|
+
[options]="inputOptions()!"
|
|
2137
|
+
[fieldOptions]="fieldOptions()"
|
|
2138
|
+
></smart-input-radio>
|
|
2139
|
+
@if (value || value === false) {
|
|
2140
|
+
<button
|
|
2141
|
+
type="button"
|
|
2142
|
+
(click)="refresh(null)"
|
|
2143
|
+
aria-label="clear"
|
|
2144
|
+
class="smart:shrink-0 smart:rounded smart:px-2 smart:py-1 smart:text-red-600 smart:hover:bg-red-50"
|
|
2145
|
+
>
|
|
2146
|
+
×
|
|
2147
|
+
</button>
|
|
2148
|
+
}
|
|
2149
|
+
</div>
|
|
2150
|
+
}
|
|
2151
|
+
`,
|
|
2152
|
+
imports: [InputRadioComponent],
|
|
2153
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
2154
|
+
}]
|
|
1173
2155
|
}] });
|
|
1174
2156
|
|
|
1175
2157
|
class FilterTextComponent extends BaseComponent {
|
|
2158
|
+
inputOptions = signal(undefined, ...(ngDevMode ? [{ debugName: "inputOptions" }] : []));
|
|
2159
|
+
fieldOptions = signal(undefined, ...(ngDevMode ? [{ debugName: "fieldOptions" }] : []));
|
|
2160
|
+
ngOnInit() {
|
|
2161
|
+
super.ngOnInit();
|
|
2162
|
+
const control = this.bindValueControl();
|
|
2163
|
+
this.inputOptions.set(this.buildInputOptions(control));
|
|
2164
|
+
}
|
|
1176
2165
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FilterTextComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
1177
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: FilterTextComponent, isStandalone: true, selector: "smart-crud-filter-text", usesInheritance: true, ngImport: i0, template: `
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
`, isInline: true,
|
|
2166
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: FilterTextComponent, isStandalone: true, selector: "smart-crud-filter-text", host: { classAttribute: "smart:block smart:w-full" }, usesInheritance: true, ngImport: i0, template: `
|
|
2167
|
+
@if (inputOptions()) {
|
|
2168
|
+
<div class="smart:flex smart:w-full smart:items-end smart:gap-2">
|
|
2169
|
+
<smart-input-text
|
|
2170
|
+
class="smart:flex-1"
|
|
2171
|
+
[options]="inputOptions()!"
|
|
2172
|
+
[fieldOptions]="fieldOptions()"
|
|
2173
|
+
></smart-input-text>
|
|
2174
|
+
@if (hasValue()) {
|
|
2175
|
+
<button
|
|
2176
|
+
type="button"
|
|
2177
|
+
(click)="refresh(null)"
|
|
2178
|
+
aria-label="clear"
|
|
2179
|
+
class="smart:shrink-0 smart:rounded smart:px-2 smart:py-2 smart:text-red-600 smart:hover:bg-red-50"
|
|
2180
|
+
>
|
|
2181
|
+
×
|
|
2182
|
+
</button>
|
|
2183
|
+
}
|
|
2184
|
+
</div>
|
|
2185
|
+
}
|
|
2186
|
+
`, isInline: true, dependencies: [{ kind: "component", type: InputTextComponent, selector: "smart-input-text" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1198
2187
|
}
|
|
1199
2188
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FilterTextComponent, decorators: [{
|
|
1200
2189
|
type: Component,
|
|
1201
|
-
args: [{
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
2190
|
+
args: [{
|
|
2191
|
+
selector: 'smart-crud-filter-text',
|
|
2192
|
+
host: { class: 'smart:block smart:w-full' },
|
|
2193
|
+
template: `
|
|
2194
|
+
@if (inputOptions()) {
|
|
2195
|
+
<div class="smart:flex smart:w-full smart:items-end smart:gap-2">
|
|
2196
|
+
<smart-input-text
|
|
2197
|
+
class="smart:flex-1"
|
|
2198
|
+
[options]="inputOptions()!"
|
|
2199
|
+
[fieldOptions]="fieldOptions()"
|
|
2200
|
+
></smart-input-text>
|
|
2201
|
+
@if (hasValue()) {
|
|
2202
|
+
<button
|
|
2203
|
+
type="button"
|
|
2204
|
+
(click)="refresh(null)"
|
|
2205
|
+
aria-label="clear"
|
|
2206
|
+
class="smart:shrink-0 smart:rounded smart:px-2 smart:py-2 smart:text-red-600 smart:hover:bg-red-50"
|
|
2207
|
+
>
|
|
2208
|
+
×
|
|
2209
|
+
</button>
|
|
2210
|
+
}
|
|
2211
|
+
</div>
|
|
2212
|
+
}
|
|
2213
|
+
`,
|
|
2214
|
+
imports: [InputTextComponent],
|
|
2215
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
2216
|
+
}]
|
|
1222
2217
|
}] });
|
|
1223
2218
|
|
|
1224
2219
|
class FilterComponent {
|
|
@@ -1226,7 +2221,7 @@ class FilterComponent {
|
|
|
1226
2221
|
item = input(...(ngDevMode ? [undefined, { debugName: "item" }] : []));
|
|
1227
2222
|
filter = input(...(ngDevMode ? [undefined, { debugName: "filter" }] : []));
|
|
1228
2223
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FilterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1229
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: FilterComponent, isStandalone: true, selector: "smart-crud-filter", inputs: { item: { classPropertyName: "item", publicName: "item", isSignal: true, isRequired: false, transformFunction: null }, filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "
|
|
2224
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: FilterComponent, isStandalone: true, selector: "smart-crud-filter", inputs: { item: { classPropertyName: "item", publicName: "item", isSignal: true, isRequired: false, transformFunction: null }, filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"smart:py-1\">\n @switch (item()?.fieldType) {\n @case (FieldType.date) {\n <smart-crud-filter-date\n [item]=\"item()\"\n [filter]=\"filter()\"\n ></smart-crud-filter-date>\n }\n @case (FieldType.dateWithEdit) {\n <smart-crud-filter-date-with-edit\n [item]=\"item()\"\n [filter]=\"filter()\"\n ></smart-crud-filter-date-with-edit>\n }\n @case (FieldType.dateTime) {\n <smart-crud-filter-date-time\n [item]=\"item()\"\n [filter]=\"filter()\"\n ></smart-crud-filter-date-time>\n }\n @case (FieldType.radio) {\n <smart-crud-filter-radio\n [item]=\"item()\"\n [filter]=\"filter()\"\n ></smart-crud-filter-radio>\n }\n @case (FieldType.check) {\n <smart-crud-filter-check\n [item]=\"item()\"\n [filter]=\"filter()\"\n ></smart-crud-filter-check>\n }\n @case (FieldType.flag) {\n <smart-crud-filter-flag\n [item]=\"item()\"\n [filter]=\"filter()\"\n ></smart-crud-filter-flag>\n }\n @case (FieldType.int) {\n <smart-crud-filter-int\n [item]=\"item()\"\n [filter]=\"filter()\"\n ></smart-crud-filter-int>\n }\n @default {\n <smart-crud-filter-text\n [item]=\"item()\"\n [filter]=\"filter()\"\n ></smart-crud-filter-text>\n }\n }\n</div>\n", dependencies: [{ kind: "component", type: FilterTextComponent, selector: "smart-crud-filter-text" }, { kind: "component", type: FilterIntComponent, selector: "smart-crud-filter-int" }, { kind: "component", type: FilterFlagComponent, selector: "smart-crud-filter-flag" }, { kind: "component", type: FilterCheckComponent, selector: "smart-crud-filter-check" }, { kind: "component", type: FilterRadioComponent, selector: "smart-crud-filter-radio" }, { kind: "component", type: FilterDateTimeComponent, selector: "smart-crud-filter-date-time" }, { kind: "component", type: FilterDateWithEditComponent, selector: "smart-crud-filter-date-with-edit" }, { kind: "component", type: FilterDateComponent, selector: "smart-crud-filter-date" }] });
|
|
1230
2225
|
}
|
|
1231
2226
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FilterComponent, decorators: [{
|
|
1232
2227
|
type: Component,
|
|
@@ -1239,9 +2234,60 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImpor
|
|
|
1239
2234
|
FilterDateTimeComponent,
|
|
1240
2235
|
FilterDateWithEditComponent,
|
|
1241
2236
|
FilterDateComponent,
|
|
1242
|
-
], template: "
|
|
2237
|
+
], template: "<div class=\"smart:py-1\">\n @switch (item()?.fieldType) {\n @case (FieldType.date) {\n <smart-crud-filter-date\n [item]=\"item()\"\n [filter]=\"filter()\"\n ></smart-crud-filter-date>\n }\n @case (FieldType.dateWithEdit) {\n <smart-crud-filter-date-with-edit\n [item]=\"item()\"\n [filter]=\"filter()\"\n ></smart-crud-filter-date-with-edit>\n }\n @case (FieldType.dateTime) {\n <smart-crud-filter-date-time\n [item]=\"item()\"\n [filter]=\"filter()\"\n ></smart-crud-filter-date-time>\n }\n @case (FieldType.radio) {\n <smart-crud-filter-radio\n [item]=\"item()\"\n [filter]=\"filter()\"\n ></smart-crud-filter-radio>\n }\n @case (FieldType.check) {\n <smart-crud-filter-check\n [item]=\"item()\"\n [filter]=\"filter()\"\n ></smart-crud-filter-check>\n }\n @case (FieldType.flag) {\n <smart-crud-filter-flag\n [item]=\"item()\"\n [filter]=\"filter()\"\n ></smart-crud-filter-flag>\n }\n @case (FieldType.int) {\n <smart-crud-filter-int\n [item]=\"item()\"\n [filter]=\"filter()\"\n ></smart-crud-filter-int>\n }\n @default {\n <smart-crud-filter-text\n [item]=\"item()\"\n [filter]=\"filter()\"\n ></smart-crud-filter-text>\n }\n }\n</div>\n" }]
|
|
1243
2238
|
}], propDecorators: { item: [{ type: i0.Input, args: [{ isSignal: true, alias: "item", required: false }] }], filter: [{ type: i0.Input, args: [{ isSignal: true, alias: "filter", required: false }] }] } });
|
|
1244
2239
|
|
|
2240
|
+
// Rendered by an OnPush concrete (FiltersComponent). The base exposes signals
|
|
2241
|
+
// (`list()`, `filter()`) and is therefore OnPush-compatible.
|
|
2242
|
+
class FiltersBaseComponent {
|
|
2243
|
+
menuService = inject(MenuService);
|
|
2244
|
+
config = inject((CrudConfig));
|
|
2245
|
+
facade = inject((CrudFacade));
|
|
2246
|
+
styleService = inject(StyleService);
|
|
2247
|
+
elementRef = inject(ElementRef);
|
|
2248
|
+
list;
|
|
2249
|
+
filter;
|
|
2250
|
+
/**
|
|
2251
|
+
* Hide menu used only from MenuService
|
|
2252
|
+
*/
|
|
2253
|
+
hideMenu = input(false, ...(ngDevMode ? [{ debugName: "hideMenu" }] : []));
|
|
2254
|
+
async onClose() {
|
|
2255
|
+
await this.menuService.closeEnd();
|
|
2256
|
+
}
|
|
2257
|
+
ngOnInit() {
|
|
2258
|
+
this.styleService.init(this.elementRef);
|
|
2259
|
+
this.list = signal([], ...(ngDevMode ? [{ debugName: "list" }] : []));
|
|
2260
|
+
const modelFilters = getModelOptions(this.config.type)?.filters;
|
|
2261
|
+
this.list.set([
|
|
2262
|
+
...(modelFilters
|
|
2263
|
+
? modelFilters.map((item) => {
|
|
2264
|
+
if (!item.label) {
|
|
2265
|
+
item.label = 'MODEL.' + item.key;
|
|
2266
|
+
}
|
|
2267
|
+
return item;
|
|
2268
|
+
})
|
|
2269
|
+
: []),
|
|
2270
|
+
...getModelFieldsWithOptions(new this.config.type())
|
|
2271
|
+
.filter((item) => item.options?.list?.filter)
|
|
2272
|
+
.map((item) => ({
|
|
2273
|
+
key: item.key,
|
|
2274
|
+
type: item.options.type === FieldType.text ||
|
|
2275
|
+
item.options.type === FieldType.longText
|
|
2276
|
+
? '~='
|
|
2277
|
+
: '=',
|
|
2278
|
+
label: 'MODEL.' + item.key,
|
|
2279
|
+
fieldType: item.options.type,
|
|
2280
|
+
})),
|
|
2281
|
+
]);
|
|
2282
|
+
this.filter = this.facade.filter;
|
|
2283
|
+
}
|
|
2284
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FiltersBaseComponent, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
2285
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.1", type: FiltersBaseComponent, isStandalone: true, inputs: { hideMenu: { classPropertyName: "hideMenu", publicName: "hideMenu", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 });
|
|
2286
|
+
}
|
|
2287
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FiltersBaseComponent, decorators: [{
|
|
2288
|
+
type: Directive
|
|
2289
|
+
}], propDecorators: { hideMenu: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideMenu", required: false }] }] } });
|
|
2290
|
+
|
|
1245
2291
|
/**
|
|
1246
2292
|
* This component is only to use in crud module
|
|
1247
2293
|
* @requires CrudModule
|
|
@@ -1297,97 +2343,79 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImpor
|
|
|
1297
2343
|
})
|
|
1298
2344
|
body: string;
|
|
1299
2345
|
*/
|
|
1300
|
-
class FiltersComponent {
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
item.options.type === FieldType.longText
|
|
1334
|
-
? '~='
|
|
1335
|
-
: '=',
|
|
1336
|
-
label: 'MODEL.' + item.key,
|
|
1337
|
-
fieldType: item.options.type,
|
|
1338
|
-
})),
|
|
1339
|
-
]);
|
|
1340
|
-
this.filter = this.facade.filter;
|
|
1341
|
-
}
|
|
1342
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FiltersComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1343
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: FiltersComponent, isStandalone: true, selector: "smart-crud-filters", inputs: { hideMenu: { classPropertyName: "hideMenu", publicName: "hideMenu", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
|
|
1344
|
-
<!--<ion-header [hidden]="hideMenu()">-->
|
|
1345
|
-
<!-- <ion-toolbar>-->
|
|
1346
|
-
<!-- <ion-buttons slot="end">-->
|
|
1347
|
-
<!-- <ion-button (click)="onClose()">-->
|
|
1348
|
-
<!-- <ion-icon slot="icon-only" name="close"> </ion-icon>-->
|
|
1349
|
-
<!-- </ion-button>-->
|
|
1350
|
-
<!-- </ion-buttons>-->
|
|
1351
|
-
<!-- <ion-title>{{ 'filters' | translate }}</ion-title>-->
|
|
1352
|
-
<!-- </ion-toolbar>-->
|
|
1353
|
-
<!--</ion-header>-->
|
|
1354
|
-
<!--<ion-content style="height: 100vh">-->
|
|
1355
|
-
<!-- <ion-list>-->
|
|
1356
|
-
@for (item of list(); track item) {
|
|
1357
|
-
<smart-crud-filter [item]="item" [filter]="filter()"></smart-crud-filter>
|
|
1358
|
-
}
|
|
1359
|
-
<!-- </ion-list>-->
|
|
1360
|
-
<div class="h-20"> </div>
|
|
1361
|
-
<!--</ion-content>-->
|
|
1362
|
-
`, isInline: true, dependencies: [{ kind: "component", type: FilterComponent, selector: "smart-crud-filter", inputs: ["item", "filter"] }] });
|
|
2346
|
+
class FiltersComponent extends FiltersBaseComponent {
|
|
2347
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FiltersComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
2348
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: FiltersComponent, isStandalone: true, selector: "smart-crud-filters", usesInheritance: true, ngImport: i0, template: `
|
|
2349
|
+
<div class="smart:flex smart:h-full smart:flex-col">
|
|
2350
|
+
@if (!hideMenu()) {
|
|
2351
|
+
<header
|
|
2352
|
+
class="smart:flex smart:items-center smart:justify-between smart:border-b smart:border-gray-200 smart:px-4 smart:py-3"
|
|
2353
|
+
>
|
|
2354
|
+
<h2 class="smart:text-lg smart:font-semibold smart:text-gray-900">
|
|
2355
|
+
{{ 'filters' | translate }}
|
|
2356
|
+
</h2>
|
|
2357
|
+
<button
|
|
2358
|
+
type="button"
|
|
2359
|
+
(click)="onClose()"
|
|
2360
|
+
aria-label="close"
|
|
2361
|
+
class="smart:rounded smart:p-1 smart:text-gray-500 smart:hover:bg-gray-100"
|
|
2362
|
+
>
|
|
2363
|
+
✕
|
|
2364
|
+
</button>
|
|
2365
|
+
</header>
|
|
2366
|
+
}
|
|
2367
|
+
<div
|
|
2368
|
+
class="smart:flex-1 smart:space-y-4 smart:overflow-y-auto smart:px-4 smart:py-3"
|
|
2369
|
+
>
|
|
2370
|
+
@for (item of list(); track item.key) {
|
|
2371
|
+
<smart-crud-filter
|
|
2372
|
+
[item]="item"
|
|
2373
|
+
[filter]="filter()"
|
|
2374
|
+
></smart-crud-filter>
|
|
2375
|
+
}
|
|
2376
|
+
</div>
|
|
2377
|
+
</div>
|
|
2378
|
+
`, isInline: true, dependencies: [{ kind: "component", type: FilterComponent, selector: "smart-crud-filter", inputs: ["item", "filter"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1363
2379
|
}
|
|
1364
2380
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FiltersComponent, decorators: [{
|
|
1365
2381
|
type: Component,
|
|
1366
2382
|
args: [{
|
|
1367
2383
|
selector: 'smart-crud-filters',
|
|
2384
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1368
2385
|
template: `
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
2386
|
+
<div class="smart:flex smart:h-full smart:flex-col">
|
|
2387
|
+
@if (!hideMenu()) {
|
|
2388
|
+
<header
|
|
2389
|
+
class="smart:flex smart:items-center smart:justify-between smart:border-b smart:border-gray-200 smart:px-4 smart:py-3"
|
|
2390
|
+
>
|
|
2391
|
+
<h2 class="smart:text-lg smart:font-semibold smart:text-gray-900">
|
|
2392
|
+
{{ 'filters' | translate }}
|
|
2393
|
+
</h2>
|
|
2394
|
+
<button
|
|
2395
|
+
type="button"
|
|
2396
|
+
(click)="onClose()"
|
|
2397
|
+
aria-label="close"
|
|
2398
|
+
class="smart:rounded smart:p-1 smart:text-gray-500 smart:hover:bg-gray-100"
|
|
2399
|
+
>
|
|
2400
|
+
✕
|
|
2401
|
+
</button>
|
|
2402
|
+
</header>
|
|
2403
|
+
}
|
|
2404
|
+
<div
|
|
2405
|
+
class="smart:flex-1 smart:space-y-4 smart:overflow-y-auto smart:px-4 smart:py-3"
|
|
2406
|
+
>
|
|
2407
|
+
@for (item of list(); track item.key) {
|
|
2408
|
+
<smart-crud-filter
|
|
2409
|
+
[item]="item"
|
|
2410
|
+
[filter]="filter()"
|
|
2411
|
+
></smart-crud-filter>
|
|
2412
|
+
}
|
|
2413
|
+
</div>
|
|
2414
|
+
</div>
|
|
1387
2415
|
`,
|
|
1388
|
-
imports: [FilterComponent],
|
|
2416
|
+
imports: [FilterComponent, TranslatePipe],
|
|
1389
2417
|
}]
|
|
1390
|
-
}]
|
|
2418
|
+
}] });
|
|
1391
2419
|
|
|
1392
2420
|
class FiltersConfigComponent {
|
|
1393
2421
|
facade = inject((CrudFacade));
|
|
@@ -1414,55 +2442,121 @@ class FiltersConfigComponent {
|
|
|
1414
2442
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FiltersConfigComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1415
2443
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: FiltersConfigComponent, isStandalone: true, selector: "smart-crud-filters-config", ngImport: i0, template: `
|
|
1416
2444
|
@let query = this.query();
|
|
1417
|
-
@if (query && query
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
2445
|
+
@if (query && query.length) {
|
|
2446
|
+
<div class="smart:flex smart:flex-wrap smart:gap-2 smart:px-4 smart:py-2">
|
|
2447
|
+
@for (item of query; track item) {
|
|
2448
|
+
<button
|
|
2449
|
+
type="button"
|
|
2450
|
+
(click)="onRemoveQuery(item)"
|
|
2451
|
+
class="smart:inline-flex smart:items-center smart:gap-1 smart:rounded-full smart:border smart:border-gray-300 smart:bg-gray-50 smart:px-3 smart:py-1 smart:text-sm smart:text-gray-700 smart:hover:bg-gray-100"
|
|
2452
|
+
[attr.aria-label]="
|
|
2453
|
+
('remove' | translate) + ' ' + ('MODEL.' + item.key | translate)
|
|
2454
|
+
"
|
|
2455
|
+
>
|
|
2456
|
+
<span
|
|
2457
|
+
>{{ 'MODEL.' + item.key | translate }} {{ item.type }}
|
|
2458
|
+
{{ item.value | translate }}</span
|
|
2459
|
+
>
|
|
2460
|
+
<span aria-hidden="true" class="smart:text-red-600">✕</span>
|
|
2461
|
+
</button>
|
|
2462
|
+
}
|
|
2463
|
+
</div>
|
|
1430
2464
|
}
|
|
1431
|
-
`, isInline: true,
|
|
2465
|
+
`, isInline: true, dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1432
2466
|
}
|
|
1433
2467
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FiltersConfigComponent, decorators: [{
|
|
1434
2468
|
type: Component,
|
|
1435
|
-
args: [{
|
|
2469
|
+
args: [{
|
|
2470
|
+
selector: 'smart-crud-filters-config',
|
|
2471
|
+
template: `
|
|
1436
2472
|
@let query = this.query();
|
|
1437
|
-
@if (query && query
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
2473
|
+
@if (query && query.length) {
|
|
2474
|
+
<div class="smart:flex smart:flex-wrap smart:gap-2 smart:px-4 smart:py-2">
|
|
2475
|
+
@for (item of query; track item) {
|
|
2476
|
+
<button
|
|
2477
|
+
type="button"
|
|
2478
|
+
(click)="onRemoveQuery(item)"
|
|
2479
|
+
class="smart:inline-flex smart:items-center smart:gap-1 smart:rounded-full smart:border smart:border-gray-300 smart:bg-gray-50 smart:px-3 smart:py-1 smart:text-sm smart:text-gray-700 smart:hover:bg-gray-100"
|
|
2480
|
+
[attr.aria-label]="
|
|
2481
|
+
('remove' | translate) + ' ' + ('MODEL.' + item.key | translate)
|
|
2482
|
+
"
|
|
2483
|
+
>
|
|
2484
|
+
<span
|
|
2485
|
+
>{{ 'MODEL.' + item.key | translate }} {{ item.type }}
|
|
2486
|
+
{{ item.value | translate }}</span
|
|
2487
|
+
>
|
|
2488
|
+
<span aria-hidden="true" class="smart:text-red-600">✕</span>
|
|
2489
|
+
</button>
|
|
2490
|
+
}
|
|
2491
|
+
</div>
|
|
1450
2492
|
}
|
|
1451
|
-
`,
|
|
2493
|
+
`,
|
|
2494
|
+
imports: [TranslatePipe],
|
|
2495
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
2496
|
+
}]
|
|
1452
2497
|
}] });
|
|
1453
2498
|
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
2499
|
+
class MultiselectBaseComponent {
|
|
2500
|
+
facade = inject((CrudFacade));
|
|
2501
|
+
config = inject((CrudFullConfig));
|
|
2502
|
+
menuService = inject(MenuService);
|
|
2503
|
+
_list;
|
|
2504
|
+
_changes;
|
|
2505
|
+
item;
|
|
2506
|
+
valid;
|
|
2507
|
+
buttonOptions = {
|
|
2508
|
+
click: async () => {
|
|
2509
|
+
const result = this._list.map((item) => {
|
|
2510
|
+
return {
|
|
2511
|
+
...this._changes,
|
|
2512
|
+
id: item.id,
|
|
2513
|
+
};
|
|
2514
|
+
});
|
|
2515
|
+
this.facade.updatePartialMany(result);
|
|
2516
|
+
await this.menuService.closeEnd();
|
|
2517
|
+
},
|
|
2518
|
+
confirm: true,
|
|
2519
|
+
};
|
|
2520
|
+
lock;
|
|
2521
|
+
showForm = false;
|
|
2522
|
+
list;
|
|
2523
|
+
constructor() {
|
|
2524
|
+
this.list = computed(() => {
|
|
2525
|
+
const list = this.facade.multiSelected() || [];
|
|
2526
|
+
this.lock = true;
|
|
2527
|
+
const model = new this.config.type();
|
|
2528
|
+
const fieldsWithOptions = getModelFieldsWithOptions(model)?.filter((f) => f.options.update?.multi);
|
|
2529
|
+
this.showForm = !!fieldsWithOptions.length;
|
|
2530
|
+
fieldsWithOptions.forEach(({ key }) => {
|
|
2531
|
+
const uniques = _.uniq(list.map((i) => i[key]));
|
|
2532
|
+
if (uniques.length === 1) {
|
|
2533
|
+
model[key] = uniques[0];
|
|
2534
|
+
}
|
|
2535
|
+
});
|
|
2536
|
+
this.item = model;
|
|
2537
|
+
return list;
|
|
2538
|
+
}, ...(ngDevMode ? [{ debugName: "list" }] : []));
|
|
2539
|
+
}
|
|
2540
|
+
async onClose() {
|
|
2541
|
+
await this.menuService.closeEnd();
|
|
2542
|
+
}
|
|
2543
|
+
onPartialChange(changes, list) {
|
|
2544
|
+
this.lock = false;
|
|
2545
|
+
this._list = list;
|
|
2546
|
+
this._changes = changes;
|
|
2547
|
+
}
|
|
2548
|
+
onValidChange(valid) {
|
|
2549
|
+
this.valid = valid;
|
|
2550
|
+
}
|
|
2551
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: MultiselectBaseComponent, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
2552
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.1", type: MultiselectBaseComponent, isStandalone: true, ngImport: i0 });
|
|
1458
2553
|
}
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
const CRUD_MODEL_POSSIBILITIES_PROVIDER = new InjectionToken('CRUD_MODEL_POSSIBILITIES_PROVIDER');
|
|
2554
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: MultiselectBaseComponent, decorators: [{
|
|
2555
|
+
type: Directive
|
|
2556
|
+
}], ctorParameters: () => [] });
|
|
1463
2557
|
|
|
1464
2558
|
class FormOptionsPipe {
|
|
1465
|
-
modelPossibilitiesProvider = inject(CRUD_MODEL_POSSIBILITIES_PROVIDER);
|
|
2559
|
+
modelPossibilitiesProvider = inject(CRUD_MODEL_POSSIBILITIES_PROVIDER, { optional: true });
|
|
1466
2560
|
transform(item, mode, type, uniqueProvider, inputComponents) {
|
|
1467
2561
|
if (!mode || !type)
|
|
1468
2562
|
return null;
|
|
@@ -1520,60 +2614,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImpor
|
|
|
1520
2614
|
}]
|
|
1521
2615
|
}] });
|
|
1522
2616
|
|
|
1523
|
-
class MultiselectComponent {
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
menuService = inject(MenuService);
|
|
1527
|
-
_list;
|
|
1528
|
-
_changes;
|
|
1529
|
-
item;
|
|
1530
|
-
valid;
|
|
1531
|
-
buttonOptions = {
|
|
1532
|
-
click: async () => {
|
|
1533
|
-
const result = this._list.map((item) => {
|
|
1534
|
-
return {
|
|
1535
|
-
...this._changes,
|
|
1536
|
-
id: item.id,
|
|
1537
|
-
};
|
|
1538
|
-
});
|
|
1539
|
-
this.facade.updatePartialMany(result);
|
|
1540
|
-
await this.menuService.closeEnd();
|
|
1541
|
-
},
|
|
1542
|
-
confirm: true,
|
|
1543
|
-
};
|
|
1544
|
-
lock;
|
|
1545
|
-
showForm = false;
|
|
1546
|
-
list;
|
|
1547
|
-
constructor() {
|
|
1548
|
-
this.list = computed(() => {
|
|
1549
|
-
const list = this.facade.multiSelected() || [];
|
|
1550
|
-
this.lock = true;
|
|
1551
|
-
const model = new this.config.type();
|
|
1552
|
-
const fieldsWithOptions = getModelFieldsWithOptions(model)?.filter((f) => f.options.update?.multi);
|
|
1553
|
-
this.showForm = !!fieldsWithOptions.length;
|
|
1554
|
-
fieldsWithOptions.forEach(({ key }) => {
|
|
1555
|
-
const uniques = _.uniq(list.map((i) => i[key]));
|
|
1556
|
-
if (uniques.length === 1) {
|
|
1557
|
-
model[key] = uniques[0];
|
|
1558
|
-
}
|
|
1559
|
-
});
|
|
1560
|
-
this.item = model;
|
|
1561
|
-
return list;
|
|
1562
|
-
}, ...(ngDevMode ? [{ debugName: "list" }] : []));
|
|
1563
|
-
}
|
|
1564
|
-
async onClose() {
|
|
1565
|
-
await this.menuService.closeEnd();
|
|
1566
|
-
}
|
|
1567
|
-
onPartialChange(changes, list) {
|
|
1568
|
-
this.lock = false;
|
|
1569
|
-
this._list = list;
|
|
1570
|
-
this._changes = changes;
|
|
1571
|
-
}
|
|
1572
|
-
onValidChange(valid) {
|
|
1573
|
-
this.valid = valid;
|
|
1574
|
-
}
|
|
1575
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: MultiselectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1576
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: MultiselectComponent, isStandalone: true, selector: "smart-crud-multiselect", ngImport: i0, template: "@let list = this.list();\n@if (list) {\n <!-- <ion-header>-->\n <!-- <ion-toolbar>-->\n <!-- <ion-buttons slot=\"end\">-->\n <!-- <ion-button (click)=\"onClose()\">-->\n <!-- <ion-icon slot=\"icon-only\" name=\"close\"> </ion-icon>-->\n <!-- </ion-button>-->\n <!-- </ion-buttons>-->\n <!--<ion-title>-->{{ 'selected' | translate }}: {{ list?.length\n }}<!--</ion-title>-->\n <!-- </ion-toolbar>-->\n <!-- </ion-header>-->\n\n @if (config?.list?.components?.multi) {\n <div>\n <ng-template\n [ngComponentOutlet]=\"config?.list?.components?.multi\"\n [ndcDynamicInputs]=\"{ items: list }\"\n ></ng-template>\n </div>\n }\n\n @if (showForm && item) {\n <div>\n <smart-form\n [options]=\"item | smartFormOptions: 'multiUpdate' : config.type\"\n (valuePartialChange)=\"onPartialChange($event, list)\"\n (validChange)=\"onValidChange($event)\"\n ></smart-form>\n\n <smart-button\n class=\"smart:float-right\"\n [disabled]=\"lock || !valid\"\n [options]=\"buttonOptions\"\n >\n {{ 'change' | translate }}\n </smart-button>\n </div>\n }\n}\n", dependencies: [{ kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "directive", type: DynamicIoDirective, selector: "[ndcDynamicInputs],[ndcDynamicOutputs]", inputs: ["ndcDynamicInputs", "ndcDynamicOutputs"], exportAs: ["ndcDynamicIo"] }, { kind: "component", type: FormComponent, selector: "smart-form", inputs: ["options", "class"], outputs: ["invokeSubmit", "valueChange", "valuePartialChange", "validChange"] }, { kind: "component", type: ButtonComponent, selector: "smart-button", inputs: ["options", "disabled", "class"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }, { kind: "pipe", type: FormOptionsPipe, name: "smartFormOptions" }] });
|
|
2617
|
+
class MultiselectComponent extends MultiselectBaseComponent {
|
|
2618
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: MultiselectComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
2619
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: MultiselectComponent, isStandalone: true, selector: "smart-crud-multiselect", usesInheritance: true, ngImport: i0, template: "@let list = this.list();\n@if (list) {\n <header\n class=\"smart:flex smart:items-center smart:justify-between smart:border-b smart:border-gray-200 smart:px-4 smart:py-3\"\n >\n <h2 class=\"smart:text-lg smart:font-semibold smart:text-gray-900\">\n {{ 'selected' | translate }}: {{ list.length }}\n </h2>\n <button\n type=\"button\"\n (click)=\"onClose()\"\n aria-label=\"close\"\n class=\"smart:rounded smart:p-1 smart:text-gray-500 smart:hover:bg-gray-100\"\n >\n \u2715\n </button>\n </header>\n\n @if (config?.list?.components?.multi) {\n <div>\n <ng-template\n [ngComponentOutlet]=\"config?.list?.components?.multi\"\n [ndcDynamicInputs]=\"{ items: list }\"\n ></ng-template>\n </div>\n }\n\n @if (showForm && item) {\n <div>\n <smart-form\n [options]=\"item | smartFormOptions: 'multiUpdate' : config.type\"\n (valuePartialChange)=\"onPartialChange($event, list)\"\n (validChange)=\"onValidChange($event)\"\n ></smart-form>\n\n <smart-button\n class=\"smart:float-right\"\n [disabled]=\"lock || !valid\"\n [options]=\"buttonOptions\"\n >\n {{ 'change' | translate }}\n </smart-button>\n </div>\n }\n}\n", dependencies: [{ kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "directive", type: DynamicIoDirective, selector: "[ndcDynamicInputs],[ndcDynamicOutputs]", inputs: ["ndcDynamicInputs", "ndcDynamicOutputs"], exportAs: ["ndcDynamicIo"] }, { kind: "component", type: FormComponent, selector: "smart-form", inputs: ["options", "class"], outputs: ["invokeSubmit", "valueChange", "valuePartialChange", "validChange"] }, { kind: "component", type: ButtonComponent, selector: "smart-button", inputs: ["options", "disabled", "class"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }, { kind: "pipe", type: FormOptionsPipe, name: "smartFormOptions" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1577
2620
|
}
|
|
1578
2621
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: MultiselectComponent, decorators: [{
|
|
1579
2622
|
type: Component,
|
|
@@ -1584,8 +2627,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImpor
|
|
|
1584
2627
|
FormOptionsPipe,
|
|
1585
2628
|
FormComponent,
|
|
1586
2629
|
ButtonComponent,
|
|
1587
|
-
], template: "@let list = this.list();\n@if (list) {\n
|
|
1588
|
-
}]
|
|
2630
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "@let list = this.list();\n@if (list) {\n <header\n class=\"smart:flex smart:items-center smart:justify-between smart:border-b smart:border-gray-200 smart:px-4 smart:py-3\"\n >\n <h2 class=\"smart:text-lg smart:font-semibold smart:text-gray-900\">\n {{ 'selected' | translate }}: {{ list.length }}\n </h2>\n <button\n type=\"button\"\n (click)=\"onClose()\"\n aria-label=\"close\"\n class=\"smart:rounded smart:p-1 smart:text-gray-500 smart:hover:bg-gray-100\"\n >\n \u2715\n </button>\n </header>\n\n @if (config?.list?.components?.multi) {\n <div>\n <ng-template\n [ngComponentOutlet]=\"config?.list?.components?.multi\"\n [ndcDynamicInputs]=\"{ items: list }\"\n ></ng-template>\n </div>\n }\n\n @if (showForm && item) {\n <div>\n <smart-form\n [options]=\"item | smartFormOptions: 'multiUpdate' : config.type\"\n (valuePartialChange)=\"onPartialChange($event, list)\"\n (validChange)=\"onValidChange($event)\"\n ></smart-form>\n\n <smart-button\n class=\"smart:float-right\"\n [disabled]=\"lock || !valid\"\n [options]=\"buttonOptions\"\n >\n {{ 'change' | translate }}\n </smart-button>\n </div>\n }\n}\n" }]
|
|
2631
|
+
}] });
|
|
1589
2632
|
|
|
1590
2633
|
class CrudListGroupService {
|
|
1591
2634
|
facade = inject((CrudFacade));
|
|
@@ -1643,10 +2686,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImpor
|
|
|
1643
2686
|
type: Injectable
|
|
1644
2687
|
}], propDecorators: { refresh: [] } });
|
|
1645
2688
|
|
|
1646
|
-
class
|
|
2689
|
+
class GroupBaseComponent extends BaseComponent$1 {
|
|
1647
2690
|
styleService = inject(StyleService);
|
|
1648
2691
|
elementRef = inject(ElementRef);
|
|
1649
2692
|
groupService = inject((CrudListGroupService));
|
|
2693
|
+
cd = inject(ChangeDetectorRef);
|
|
1650
2694
|
groups = input(null, ...(ngDevMode ? [{ debugName: "groups" }] : []));
|
|
1651
2695
|
listOptions = input(null, ...(ngDevMode ? [{ debugName: "listOptions" }] : []));
|
|
1652
2696
|
change(val, item, force = false) {
|
|
@@ -1659,7 +2703,16 @@ class GroupComponent extends BaseComponent$1 {
|
|
|
1659
2703
|
});
|
|
1660
2704
|
}
|
|
1661
2705
|
this.groupService.change(val, item, force);
|
|
1662
|
-
|
|
2706
|
+
if (val) {
|
|
2707
|
+
setTimeout(() => {
|
|
2708
|
+
item.show = val;
|
|
2709
|
+
this.cd.detectChanges();
|
|
2710
|
+
});
|
|
2711
|
+
}
|
|
2712
|
+
else {
|
|
2713
|
+
item.show = val;
|
|
2714
|
+
this.cd.detectChanges();
|
|
2715
|
+
}
|
|
1663
2716
|
}
|
|
1664
2717
|
ngOnInit() {
|
|
1665
2718
|
this.styleService.init(this.elementRef);
|
|
@@ -1671,292 +2724,175 @@ class GroupComponent extends BaseComponent$1 {
|
|
|
1671
2724
|
}
|
|
1672
2725
|
super.ngOnDestroy();
|
|
1673
2726
|
}
|
|
1674
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type:
|
|
1675
|
-
static
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
[
|
|
1680
|
-
(showChange)="change($event, item)"
|
|
1681
|
-
>
|
|
1682
|
-
<smart-accordion-header [ngClass]="{ 'font-bold': item.show }">
|
|
1683
|
-
{{ item.text | translate }}
|
|
1684
|
-
</smart-accordion-header>
|
|
1685
|
-
<smart-accordion-body>
|
|
1686
|
-
@if (item.show && !item.children && listOptions()) {
|
|
1687
|
-
<smart-list [options]="listOptions()!"></smart-list>
|
|
1688
|
-
}
|
|
1689
|
-
@if (item.children) {
|
|
1690
|
-
<div style="margin-left: 50px">
|
|
1691
|
-
<smart-crud-group
|
|
1692
|
-
[groups]="item.children"
|
|
1693
|
-
[listOptions]="listOptions()"
|
|
1694
|
-
></smart-crud-group>
|
|
1695
|
-
</div>
|
|
1696
|
-
}
|
|
1697
|
-
</smart-accordion-body>
|
|
1698
|
-
</smart-accordion>
|
|
1699
|
-
}
|
|
1700
|
-
-->
|
|
2727
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: GroupBaseComponent, deps: null, target: i0.ɵɵFactoryTarget.Directive });
|
|
2728
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.1", type: GroupBaseComponent, isStandalone: true, inputs: { groups: { classPropertyName: "groups", publicName: "groups", isSignal: true, isRequired: false, transformFunction: null }, listOptions: { classPropertyName: "listOptions", publicName: "listOptions", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0 });
|
|
2729
|
+
}
|
|
2730
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: GroupBaseComponent, decorators: [{
|
|
2731
|
+
type: Directive
|
|
2732
|
+
}], propDecorators: { groups: [{ type: i0.Input, args: [{ isSignal: true, alias: "groups", required: false }] }], listOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "listOptions", required: false }] }] } });
|
|
1701
2733
|
|
|
1702
|
-
|
|
2734
|
+
class GroupComponent extends GroupBaseComponent {
|
|
2735
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: GroupComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
2736
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: GroupComponent, isStandalone: true, selector: "smart-crud-group", usesInheritance: true, ngImport: i0, template: `
|
|
1703
2737
|
@for (item of groups(); track item.key) {
|
|
1704
|
-
<div
|
|
1705
|
-
|
|
2738
|
+
<div class="smart:border-b smart:border-gray-200">
|
|
2739
|
+
<button
|
|
2740
|
+
type="button"
|
|
2741
|
+
(click)="change(!item.show, item)"
|
|
2742
|
+
[attr.aria-expanded]="item.show || false"
|
|
2743
|
+
[attr.aria-controls]="'smart-crud-group-' + item.key"
|
|
2744
|
+
class="smart:flex smart:w-full smart:items-center smart:justify-between smart:py-3 smart:text-left smart:text-sm"
|
|
2745
|
+
[class.smart:font-bold]="item.show"
|
|
2746
|
+
>
|
|
2747
|
+
<span>{{ item.text | translate }}</span>
|
|
2748
|
+
<span aria-hidden="true" class="smart:text-gray-500">{{
|
|
2749
|
+
item.show ? '▾' : '▸'
|
|
2750
|
+
}}</span>
|
|
2751
|
+
</button>
|
|
2752
|
+
@if (item.show) {
|
|
2753
|
+
<div [id]="'smart-crud-group-' + item.key" class="smart:pb-3">
|
|
2754
|
+
@if (!item.children && listOptions()) {
|
|
2755
|
+
<smart-list [options]="listOptions()!"></smart-list>
|
|
2756
|
+
}
|
|
2757
|
+
@if (item.children) {
|
|
2758
|
+
<div class="smart:ml-12">
|
|
2759
|
+
<smart-crud-group
|
|
2760
|
+
[groups]="item.children"
|
|
2761
|
+
[listOptions]="listOptions()"
|
|
2762
|
+
></smart-crud-group>
|
|
2763
|
+
</div>
|
|
2764
|
+
}
|
|
2765
|
+
</div>
|
|
2766
|
+
}
|
|
1706
2767
|
</div>
|
|
1707
|
-
@if (item.show && !item.children && listOptions()) {
|
|
1708
|
-
<smart-list [options]="listOptions()!"></smart-list>
|
|
1709
|
-
}
|
|
1710
|
-
@if (item.children) {
|
|
1711
|
-
<div style="margin-left: 50px">
|
|
1712
|
-
<smart-crud-group
|
|
1713
|
-
[groups]="item.children"
|
|
1714
|
-
[listOptions]="listOptions()"
|
|
1715
|
-
></smart-crud-group>
|
|
1716
|
-
</div>
|
|
1717
|
-
}
|
|
1718
2768
|
}
|
|
1719
|
-
`, isInline: true, dependencies: [{ kind: "component", type: GroupComponent, selector: "smart-crud-group", inputs: ["
|
|
1720
|
-
// TODO: AccordionComponent moved to @smartsoft001-pro/angular (FRA-101)
|
|
1721
|
-
// AccordionComponent,
|
|
1722
|
-
// AccordionHeaderComponent,
|
|
1723
|
-
// AccordionBodyComponent,
|
|
1724
|
-
ListComponent$1, selector: "smart-list", inputs: ["options", "class"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
|
|
2769
|
+
`, isInline: true, dependencies: [{ kind: "component", type: GroupComponent, selector: "smart-crud-group" }, { kind: "component", type: ListComponent$1, selector: "smart-list", inputs: ["options", "class"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1725
2770
|
}
|
|
1726
2771
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: GroupComponent, decorators: [{
|
|
1727
2772
|
type: Component,
|
|
1728
2773
|
args: [{
|
|
1729
2774
|
selector: 'smart-crud-group',
|
|
2775
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1730
2776
|
template: `
|
|
1731
|
-
<!-- TODO: AccordionComponent moved to @smartsoft001-pro/angular (FRA-101)
|
|
1732
|
-
@for (item of groups(); track item.key) {
|
|
1733
|
-
<smart-accordion
|
|
1734
|
-
[show]="item.show || false"
|
|
1735
|
-
(showChange)="change($event, item)"
|
|
1736
|
-
>
|
|
1737
|
-
<smart-accordion-header [ngClass]="{ 'font-bold': item.show }">
|
|
1738
|
-
{{ item.text | translate }}
|
|
1739
|
-
</smart-accordion-header>
|
|
1740
|
-
<smart-accordion-body>
|
|
1741
|
-
@if (item.show && !item.children && listOptions()) {
|
|
1742
|
-
<smart-list [options]="listOptions()!"></smart-list>
|
|
1743
|
-
}
|
|
1744
|
-
@if (item.children) {
|
|
1745
|
-
<div style="margin-left: 50px">
|
|
1746
|
-
<smart-crud-group
|
|
1747
|
-
[groups]="item.children"
|
|
1748
|
-
[listOptions]="listOptions()"
|
|
1749
|
-
></smart-crud-group>
|
|
1750
|
-
</div>
|
|
1751
|
-
}
|
|
1752
|
-
</smart-accordion-body>
|
|
1753
|
-
</smart-accordion>
|
|
1754
|
-
}
|
|
1755
|
-
-->
|
|
1756
|
-
|
|
1757
|
-
<!-- TODO: remove this template after moving to @smartsoft001-pro/angular (FRA-101) -->
|
|
1758
2777
|
@for (item of groups(); track item.key) {
|
|
1759
|
-
<div
|
|
1760
|
-
|
|
2778
|
+
<div class="smart:border-b smart:border-gray-200">
|
|
2779
|
+
<button
|
|
2780
|
+
type="button"
|
|
2781
|
+
(click)="change(!item.show, item)"
|
|
2782
|
+
[attr.aria-expanded]="item.show || false"
|
|
2783
|
+
[attr.aria-controls]="'smart-crud-group-' + item.key"
|
|
2784
|
+
class="smart:flex smart:w-full smart:items-center smart:justify-between smart:py-3 smart:text-left smart:text-sm"
|
|
2785
|
+
[class.smart:font-bold]="item.show"
|
|
2786
|
+
>
|
|
2787
|
+
<span>{{ item.text | translate }}</span>
|
|
2788
|
+
<span aria-hidden="true" class="smart:text-gray-500">{{
|
|
2789
|
+
item.show ? '▾' : '▸'
|
|
2790
|
+
}}</span>
|
|
2791
|
+
</button>
|
|
2792
|
+
@if (item.show) {
|
|
2793
|
+
<div [id]="'smart-crud-group-' + item.key" class="smart:pb-3">
|
|
2794
|
+
@if (!item.children && listOptions()) {
|
|
2795
|
+
<smart-list [options]="listOptions()!"></smart-list>
|
|
2796
|
+
}
|
|
2797
|
+
@if (item.children) {
|
|
2798
|
+
<div class="smart:ml-12">
|
|
2799
|
+
<smart-crud-group
|
|
2800
|
+
[groups]="item.children"
|
|
2801
|
+
[listOptions]="listOptions()"
|
|
2802
|
+
></smart-crud-group>
|
|
2803
|
+
</div>
|
|
2804
|
+
}
|
|
2805
|
+
</div>
|
|
2806
|
+
}
|
|
1761
2807
|
</div>
|
|
1762
|
-
@if (item.show && !item.children && listOptions()) {
|
|
1763
|
-
<smart-list [options]="listOptions()!"></smart-list>
|
|
1764
|
-
}
|
|
1765
|
-
@if (item.children) {
|
|
1766
|
-
<div style="margin-left: 50px">
|
|
1767
|
-
<smart-crud-group
|
|
1768
|
-
[groups]="item.children"
|
|
1769
|
-
[listOptions]="listOptions()"
|
|
1770
|
-
></smart-crud-group>
|
|
1771
|
-
</div>
|
|
1772
|
-
}
|
|
1773
2808
|
}
|
|
1774
2809
|
`,
|
|
1775
|
-
imports: [
|
|
1776
|
-
// TODO: AccordionComponent moved to @smartsoft001-pro/angular (FRA-101)
|
|
1777
|
-
// AccordionComponent,
|
|
1778
|
-
// AccordionHeaderComponent,
|
|
1779
|
-
// AccordionBodyComponent,
|
|
1780
|
-
ListComponent$1,
|
|
1781
|
-
NgClass,
|
|
1782
|
-
TranslatePipe,
|
|
1783
|
-
],
|
|
2810
|
+
imports: [ListComponent$1, TranslatePipe],
|
|
1784
2811
|
}]
|
|
1785
|
-
}]
|
|
2812
|
+
}] });
|
|
1786
2813
|
|
|
1787
2814
|
class CrudListPaginationFactory {
|
|
1788
2815
|
facade = inject((CrudFacade));
|
|
2816
|
+
injector = inject(Injector);
|
|
1789
2817
|
async create(options) {
|
|
1790
2818
|
return {
|
|
1791
2819
|
mode: options.mode,
|
|
1792
|
-
limit: options.limit,
|
|
1793
|
-
loadNextPage: () => {
|
|
1794
|
-
if (!options.provider.getLinks() || !options.provider.getLinks().next)
|
|
1795
|
-
return Promise.resolve(false);
|
|
1796
|
-
return new Promise((res) => {
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
});
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
const
|
|
1833
|
-
return
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
}
|
|
1842
|
-
|
|
1843
|
-
type: Injectable
|
|
1844
|
-
}] });
|
|
1845
|
-
|
|
1846
|
-
class CrudService {
|
|
1847
|
-
config = inject((CrudConfig));
|
|
1848
|
-
http = inject(HttpClient);
|
|
1849
|
-
_formatMap = {
|
|
1850
|
-
csv: 'text/csv',
|
|
1851
|
-
xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
|
1852
|
-
};
|
|
1853
|
-
create(item) {
|
|
1854
|
-
return firstValueFrom(this.http
|
|
1855
|
-
.post(this.config.apiUrl, item, { observe: 'response' })
|
|
1856
|
-
.pipe(map((response) => {
|
|
1857
|
-
const location = response.headers['Location'];
|
|
1858
|
-
if (!location)
|
|
1859
|
-
return null;
|
|
1860
|
-
const array = location.split('/');
|
|
1861
|
-
return array[array.length - 1];
|
|
1862
|
-
})));
|
|
1863
|
-
}
|
|
1864
|
-
createMany(items, options) {
|
|
1865
|
-
return firstValueFrom(this.http.post(this.config.apiUrl + '/bulk?mode=' + options.mode, items));
|
|
1866
|
-
}
|
|
1867
|
-
getById(id) {
|
|
1868
|
-
return firstValueFrom(this.http.get(this.config.apiUrl + '/' + id));
|
|
1869
|
-
}
|
|
1870
|
-
getList(filter = null) {
|
|
1871
|
-
return firstValueFrom(this.http.get(this.config.apiUrl + this.getQuery(filter)));
|
|
1872
|
-
}
|
|
1873
|
-
exportList(filter = null, format) {
|
|
1874
|
-
if (!format) {
|
|
1875
|
-
format = 'csv';
|
|
1876
|
-
}
|
|
1877
|
-
if (format === 'xlsx') {
|
|
1878
|
-
return firstValueFrom(this.http
|
|
1879
|
-
.get(this.config.apiUrl + this.getQuery(filter), {
|
|
1880
|
-
headers: {
|
|
1881
|
-
'Content-Type': this._formatMap[format],
|
|
1882
|
-
},
|
|
1883
|
-
observe: 'response',
|
|
1884
|
-
reportProgress: false,
|
|
1885
|
-
responseType: 'blob',
|
|
1886
|
-
})
|
|
1887
|
-
.pipe(map((res) => {
|
|
1888
|
-
const downloadLink = document.createElement('a');
|
|
1889
|
-
const blob = res.body;
|
|
1890
|
-
downloadLink.href = URL.createObjectURL(blob);
|
|
1891
|
-
downloadLink.download = 'data.' + format;
|
|
1892
|
-
document.body.appendChild(downloadLink);
|
|
1893
|
-
downloadLink.click();
|
|
1894
|
-
document.body.removeChild(downloadLink);
|
|
1895
|
-
})));
|
|
1896
|
-
}
|
|
1897
|
-
return firstValueFrom(this.http
|
|
1898
|
-
.get(this.config.apiUrl + this.getQuery(filter), {
|
|
1899
|
-
headers: {
|
|
1900
|
-
'Content-Type': this._formatMap[format],
|
|
1901
|
-
},
|
|
1902
|
-
responseType: 'text',
|
|
1903
|
-
})
|
|
1904
|
-
.pipe(map((res) => {
|
|
1905
|
-
const downloadLink = document.createElement('a');
|
|
1906
|
-
const blob = new Blob(['\ufeff', res]);
|
|
1907
|
-
downloadLink.href = URL.createObjectURL(blob);
|
|
1908
|
-
downloadLink.download = 'data.' + format;
|
|
1909
|
-
document.body.appendChild(downloadLink);
|
|
1910
|
-
downloadLink.click();
|
|
1911
|
-
document.body.removeChild(downloadLink);
|
|
1912
|
-
})));
|
|
1913
|
-
}
|
|
1914
|
-
update(item) {
|
|
1915
|
-
return firstValueFrom(this.http.put(this.config.apiUrl + '/' + item.id, item));
|
|
1916
|
-
}
|
|
1917
|
-
updatePartial(item) {
|
|
1918
|
-
return firstValueFrom(this.http.patch(this.config.apiUrl + '/' + item.id, item));
|
|
1919
|
-
}
|
|
1920
|
-
updatePartialMany(items) {
|
|
1921
|
-
const updatePromises = items.map((item) => {
|
|
1922
|
-
return this.updatePartial(item);
|
|
1923
|
-
});
|
|
1924
|
-
return Promise.all(updatePromises);
|
|
1925
|
-
}
|
|
1926
|
-
delete(id) {
|
|
1927
|
-
return firstValueFrom(this.http.delete(this.config.apiUrl + '/' + id));
|
|
1928
|
-
}
|
|
1929
|
-
getQuery(filter) {
|
|
1930
|
-
let query = '';
|
|
1931
|
-
if (filter && filter.searchText) {
|
|
1932
|
-
query += '&$search=' + filter.searchText;
|
|
1933
|
-
}
|
|
1934
|
-
if (filter && filter.limit) {
|
|
1935
|
-
query += `&limit=${filter.limit}&offset=${filter.offset ? filter.offset : 0}`;
|
|
1936
|
-
}
|
|
1937
|
-
if (filter && filter.sortBy) {
|
|
1938
|
-
query += `&sort=${(filter.sortDesc ? '-' : '') + filter.sortBy}`;
|
|
1939
|
-
}
|
|
1940
|
-
if (filter && filter.query) {
|
|
1941
|
-
filter.query.forEach((q) => {
|
|
1942
|
-
if (q.value &&
|
|
1943
|
-
typeof q.value === 'string' &&
|
|
1944
|
-
q.value.match(/^-?\d+$/) &&
|
|
1945
|
-
q.value[0] !== "'" &&
|
|
1946
|
-
q.value[0] !== '"') {
|
|
1947
|
-
query += '&' + q.key + q.type + `'${q.value}'`;
|
|
1948
|
-
}
|
|
1949
|
-
else {
|
|
1950
|
-
query += '&' + q.key + q.type + q.value;
|
|
1951
|
-
}
|
|
1952
|
-
});
|
|
1953
|
-
}
|
|
1954
|
-
return query ? '?' + query.replace('&', '') : '';
|
|
2820
|
+
limit: options.limit,
|
|
2821
|
+
loadNextPage: () => {
|
|
2822
|
+
if (!options.provider.getLinks() || !options.provider.getLinks().next)
|
|
2823
|
+
return Promise.resolve(false);
|
|
2824
|
+
return new Promise((res) => {
|
|
2825
|
+
toObservable(this.facade.loaded, { injector: this.injector })
|
|
2826
|
+
.pipe(filter((l) => !!l), take(1))
|
|
2827
|
+
.subscribe(() => {
|
|
2828
|
+
setTimeout(() => {
|
|
2829
|
+
res(options.provider.getLinks() &&
|
|
2830
|
+
options.provider.getLinks().next);
|
|
2831
|
+
});
|
|
2832
|
+
});
|
|
2833
|
+
const currentFilter = options.provider.getFilter();
|
|
2834
|
+
this.facade.read({
|
|
2835
|
+
...currentFilter,
|
|
2836
|
+
offset: (currentFilter.offset || 0) + (currentFilter.limit || 0),
|
|
2837
|
+
});
|
|
2838
|
+
});
|
|
2839
|
+
},
|
|
2840
|
+
loadPrevPage: () => {
|
|
2841
|
+
if (!options.provider.getLinks() || !options.provider.getLinks().prev)
|
|
2842
|
+
return Promise.resolve(false);
|
|
2843
|
+
return new Promise((res) => {
|
|
2844
|
+
toObservable(this.facade.loaded, { injector: this.injector })
|
|
2845
|
+
.pipe(filter((l) => !!l), take(1))
|
|
2846
|
+
.subscribe(() => {
|
|
2847
|
+
setTimeout(() => {
|
|
2848
|
+
res(options.provider.getLinks() &&
|
|
2849
|
+
options.provider.getLinks().prev);
|
|
2850
|
+
});
|
|
2851
|
+
});
|
|
2852
|
+
const currentFilter = options.provider.getFilter();
|
|
2853
|
+
this.facade.read({
|
|
2854
|
+
...currentFilter,
|
|
2855
|
+
offset: (currentFilter.offset || 0) - (currentFilter.limit || 0),
|
|
2856
|
+
});
|
|
2857
|
+
});
|
|
2858
|
+
},
|
|
2859
|
+
page: computed(() => {
|
|
2860
|
+
const f = this.facade.filter();
|
|
2861
|
+
return f?.limit ? (f.offset || 0) / f.limit + 1 : 0;
|
|
2862
|
+
}),
|
|
2863
|
+
totalPages: computed(() => {
|
|
2864
|
+
const filter = this.facade.filter();
|
|
2865
|
+
const totalCount = this.facade.totalCount();
|
|
2866
|
+
return filter?.limit && totalCount
|
|
2867
|
+
? Math.ceil(totalCount / filter.limit)
|
|
2868
|
+
: 0;
|
|
2869
|
+
}),
|
|
2870
|
+
};
|
|
1955
2871
|
}
|
|
1956
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type:
|
|
1957
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type:
|
|
2872
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudListPaginationFactory, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
2873
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudListPaginationFactory });
|
|
1958
2874
|
}
|
|
1959
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type:
|
|
2875
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudListPaginationFactory, decorators: [{
|
|
2876
|
+
type: Injectable
|
|
2877
|
+
}] });
|
|
2878
|
+
|
|
2879
|
+
class CrudModelLabelProvider extends IModelLabelProvider {
|
|
2880
|
+
translateService = inject(TranslateService);
|
|
2881
|
+
// Delegate to an app-level provider if one exists higher in the injector tree;
|
|
2882
|
+
// otherwise fall back to translating 'MODEL.<key>'. (FRA-293 GAP / belt-and-suspenders.)
|
|
2883
|
+
parent = inject(IModelLabelProvider, {
|
|
2884
|
+
optional: true,
|
|
2885
|
+
skipSelf: true,
|
|
2886
|
+
});
|
|
2887
|
+
get(options) {
|
|
2888
|
+
if (this.parent)
|
|
2889
|
+
return this.parent.get(options);
|
|
2890
|
+
return signal(this.translateService.instant('MODEL.' + options.key));
|
|
2891
|
+
}
|
|
2892
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudModelLabelProvider, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
|
|
2893
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudModelLabelProvider });
|
|
2894
|
+
}
|
|
2895
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudModelLabelProvider, decorators: [{
|
|
1960
2896
|
type: Injectable
|
|
1961
2897
|
}] });
|
|
1962
2898
|
|
|
@@ -2009,7 +2945,13 @@ class CrudComponentsModule {
|
|
|
2009
2945
|
FilterIntComponent,
|
|
2010
2946
|
MultiselectComponent,
|
|
2011
2947
|
GroupComponent] });
|
|
2012
|
-
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudComponentsModule, providers: [
|
|
2948
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudComponentsModule, providers: [
|
|
2949
|
+
CrudService,
|
|
2950
|
+
CrudFacade,
|
|
2951
|
+
SocketService,
|
|
2952
|
+
CrudListPaginationFactory,
|
|
2953
|
+
{ provide: IModelLabelProvider, useClass: CrudModelLabelProvider },
|
|
2954
|
+
], imports: [ExportComponent,
|
|
2013
2955
|
FilterComponent,
|
|
2014
2956
|
FilterTextComponent,
|
|
2015
2957
|
FilterDateComponent,
|
|
@@ -2038,178 +2980,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImpor
|
|
|
2038
2980
|
DynamicIoModule,
|
|
2039
2981
|
],
|
|
2040
2982
|
exports: [CrudPipesModule, ...COMPONENTS],
|
|
2041
|
-
providers: [
|
|
2983
|
+
providers: [
|
|
2984
|
+
CrudService,
|
|
2985
|
+
CrudFacade,
|
|
2986
|
+
SocketService,
|
|
2987
|
+
CrudListPaginationFactory,
|
|
2988
|
+
{ provide: IModelLabelProvider, useClass: CrudModelLabelProvider },
|
|
2989
|
+
],
|
|
2042
2990
|
}]
|
|
2043
2991
|
}] });
|
|
2044
2992
|
|
|
2045
|
-
class CrudEffects {
|
|
2046
|
-
actions$;
|
|
2047
|
-
service;
|
|
2048
|
-
config;
|
|
2049
|
-
store;
|
|
2050
|
-
state;
|
|
2051
|
-
constructor(actions$, service, config, store, state) {
|
|
2052
|
-
this.actions$ = actions$;
|
|
2053
|
-
this.service = service;
|
|
2054
|
-
this.config = config;
|
|
2055
|
-
this.store = store;
|
|
2056
|
-
this.state = state;
|
|
2057
|
-
}
|
|
2058
|
-
init() {
|
|
2059
|
-
const metadata = Reflect.getMetadata(this.config.entity, CrudEffects);
|
|
2060
|
-
if (metadata)
|
|
2061
|
-
return;
|
|
2062
|
-
Reflect.defineMetadata(this.config.entity, true, CrudEffects);
|
|
2063
|
-
this.actions$.subscribe((action) => {
|
|
2064
|
-
switch (action.type) {
|
|
2065
|
-
case `[${this.config.entity}] Create`:
|
|
2066
|
-
this.service
|
|
2067
|
-
.create(action.item)
|
|
2068
|
-
.then(() => this.store.dispatch(createSuccess(this.config.entity, action.item)))
|
|
2069
|
-
.catch((error) => {
|
|
2070
|
-
this.store.dispatch(createFailure(this.config.entity, action.item, error));
|
|
2071
|
-
});
|
|
2072
|
-
break;
|
|
2073
|
-
case `[${this.config.entity}] Create Success`: {
|
|
2074
|
-
const createState = this.state.getValue()[this.config.entity];
|
|
2075
|
-
this.store.dispatch(read(this.config.entity, createState?.filter ? { ...createState.filter, offset: 0 } : null));
|
|
2076
|
-
break;
|
|
2077
|
-
}
|
|
2078
|
-
case `[${this.config.entity}] Create Many`:
|
|
2079
|
-
this.service
|
|
2080
|
-
.createMany(action.data.items, action.data.options)
|
|
2081
|
-
.then(() => this.store.dispatch(createManySuccess(this.config.entity, {
|
|
2082
|
-
items: action.data.items,
|
|
2083
|
-
options: action.data.options,
|
|
2084
|
-
})))
|
|
2085
|
-
.catch((error) => {
|
|
2086
|
-
this.store.dispatch(createManyFailure(this.config.entity, {
|
|
2087
|
-
items: action.data.items,
|
|
2088
|
-
options: action.data.options,
|
|
2089
|
-
}, error));
|
|
2090
|
-
});
|
|
2091
|
-
break;
|
|
2092
|
-
case `[${this.config.entity}] Create Many Success`: {
|
|
2093
|
-
const createManyState = this.state.getValue()[this.config.entity];
|
|
2094
|
-
this.store.dispatch(read(this.config.entity, createManyState?.filter
|
|
2095
|
-
? { ...createManyState.filter, offset: 0 }
|
|
2096
|
-
: null));
|
|
2097
|
-
break;
|
|
2098
|
-
}
|
|
2099
|
-
case `[${this.config.entity}] Read`:
|
|
2100
|
-
this.service
|
|
2101
|
-
.getList(action?.filter)
|
|
2102
|
-
.then((result) => this.store.dispatch(readSuccess(this.config.entity, action?.filter, result)))
|
|
2103
|
-
.catch((error) => {
|
|
2104
|
-
this.store.dispatch(readFailure(this.config.entity, action?.filter, error));
|
|
2105
|
-
});
|
|
2106
|
-
break;
|
|
2107
|
-
case `[${this.config.entity}] Export`:
|
|
2108
|
-
this.service
|
|
2109
|
-
.exportList(action?.filter, action.format)
|
|
2110
|
-
.then(() => this.store.dispatch(exportListSuccess(this.config.entity, action?.filter)))
|
|
2111
|
-
.catch((error) => {
|
|
2112
|
-
this.store.dispatch(exportListFailure(this.config.entity, action?.filter, error));
|
|
2113
|
-
});
|
|
2114
|
-
break;
|
|
2115
|
-
case `[${this.config.entity}] Select`:
|
|
2116
|
-
this.service
|
|
2117
|
-
.getById(action.id)
|
|
2118
|
-
.then((result) => this.store.dispatch(selectSuccess(this.config.entity, action.id, result)))
|
|
2119
|
-
.catch((error) => {
|
|
2120
|
-
this.store.dispatch(selectFailure(this.config.entity, action.id, error));
|
|
2121
|
-
});
|
|
2122
|
-
break;
|
|
2123
|
-
case `[${this.config.entity}] Update`:
|
|
2124
|
-
this.service
|
|
2125
|
-
.updatePartial(action.item)
|
|
2126
|
-
.then(() => this.store.dispatch(updateSuccess(this.config.entity, action.item)))
|
|
2127
|
-
.catch((error) => {
|
|
2128
|
-
this.store.dispatch(updateFailure(this.config.entity, action.item, error));
|
|
2129
|
-
this.store.dispatch(read(this.config.entity));
|
|
2130
|
-
});
|
|
2131
|
-
break;
|
|
2132
|
-
case `[${this.config.entity}] Update Success`:
|
|
2133
|
-
this.store
|
|
2134
|
-
.pipe(select$1(getCrudFilter(this.config.entity)), first())
|
|
2135
|
-
.subscribe((filter) => {
|
|
2136
|
-
this.store.dispatch(read(this.config.entity, {
|
|
2137
|
-
...filter,
|
|
2138
|
-
offset: 0,
|
|
2139
|
-
}));
|
|
2140
|
-
this.store.dispatch(select(this.config.entity, action.item.id));
|
|
2141
|
-
});
|
|
2142
|
-
break;
|
|
2143
|
-
case `[${this.config.entity}] Update partial`:
|
|
2144
|
-
this.service
|
|
2145
|
-
.updatePartial(action.item)
|
|
2146
|
-
.then(() => this.store.dispatch(updatePartialSuccess(this.config.entity, action.item)))
|
|
2147
|
-
.catch((error) => {
|
|
2148
|
-
this.store.dispatch(updatePartialFailure(this.config.entity, action.item, error));
|
|
2149
|
-
this.store.dispatch(read(this.config.entity));
|
|
2150
|
-
});
|
|
2151
|
-
break;
|
|
2152
|
-
case `[${this.config.entity}] Update partial Success`:
|
|
2153
|
-
this.store
|
|
2154
|
-
.pipe(select$1(getCrudFilter(this.config.entity)), first())
|
|
2155
|
-
.subscribe((filter) => {
|
|
2156
|
-
this.store.dispatch(read(this.config.entity, {
|
|
2157
|
-
...filter,
|
|
2158
|
-
offset: 0,
|
|
2159
|
-
}));
|
|
2160
|
-
this.store.dispatch(select(this.config.entity, action.item.id));
|
|
2161
|
-
});
|
|
2162
|
-
break;
|
|
2163
|
-
case `[${this.config.entity}] Update partial many`:
|
|
2164
|
-
this.service
|
|
2165
|
-
.updatePartialMany(action.items)
|
|
2166
|
-
.then(() => this.store.dispatch(updatePartialManySuccess(this.config.entity, action.items)))
|
|
2167
|
-
.catch((error) => {
|
|
2168
|
-
this.store.dispatch(updatePartialManyFailure(this.config.entity, action.items, error));
|
|
2169
|
-
this.store.dispatch(read(this.config.entity));
|
|
2170
|
-
});
|
|
2171
|
-
break;
|
|
2172
|
-
case `[${this.config.entity}] Update partial many Success`:
|
|
2173
|
-
this.store
|
|
2174
|
-
.pipe(select$1(getCrudFilter(this.config.entity)), first())
|
|
2175
|
-
.subscribe((filter) => {
|
|
2176
|
-
this.store.dispatch(read(this.config.entity, {
|
|
2177
|
-
...filter,
|
|
2178
|
-
offset: 0,
|
|
2179
|
-
}));
|
|
2180
|
-
});
|
|
2181
|
-
break;
|
|
2182
|
-
case `[${this.config.entity}] Delete`:
|
|
2183
|
-
this.service
|
|
2184
|
-
.delete(action.id)
|
|
2185
|
-
.then(() => this.store.dispatch(deleteSuccess(this.config.entity, action.id)))
|
|
2186
|
-
.catch((error) => {
|
|
2187
|
-
this.store.dispatch(deleteFailure(this.config.entity, action.id, error));
|
|
2188
|
-
});
|
|
2189
|
-
break;
|
|
2190
|
-
case `[${this.config.entity}] Delete Success`:
|
|
2191
|
-
this.store
|
|
2192
|
-
.pipe(select$1(getCrudFilter(this.config.entity)), first())
|
|
2193
|
-
.subscribe((filter) => {
|
|
2194
|
-
this.store.dispatch(read(this.config.entity, {
|
|
2195
|
-
...filter,
|
|
2196
|
-
offset: 0,
|
|
2197
|
-
}));
|
|
2198
|
-
});
|
|
2199
|
-
break;
|
|
2200
|
-
default:
|
|
2201
|
-
console.warn(`No effect for action type ${action.type} in entity ${this.config.entity}`);
|
|
2202
|
-
break;
|
|
2203
|
-
}
|
|
2204
|
-
});
|
|
2205
|
-
}
|
|
2206
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudEffects, deps: [{ token: i1.ActionsSubject }, { token: CrudService }, { token: CrudConfig }, { token: i1.Store }, { token: i1.State }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
2207
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudEffects });
|
|
2208
|
-
}
|
|
2209
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudEffects, decorators: [{
|
|
2210
|
-
type: Injectable
|
|
2211
|
-
}], ctorParameters: () => [{ type: i1.ActionsSubject }, { type: CrudService }, { type: CrudConfig }, { type: i1.Store }, { type: i1.State }] });
|
|
2212
|
-
|
|
2213
2993
|
class CrudItemPageBaseComponent extends BaseComponent$1 {
|
|
2214
2994
|
config = inject((CrudFullConfig));
|
|
2215
2995
|
facade = inject((CrudFacade));
|
|
@@ -2351,6 +3131,7 @@ class ItemComponent extends CreateDynamicComponent('crud-item-page') {
|
|
|
2351
3131
|
_mode;
|
|
2352
3132
|
pageOptions = signal({
|
|
2353
3133
|
title: '',
|
|
3134
|
+
variant: this.config.variant,
|
|
2354
3135
|
showBackButton: true,
|
|
2355
3136
|
hideMenuButton: true,
|
|
2356
3137
|
}, ...(ngDevMode ? [{ debugName: "pageOptions" }] : []));
|
|
@@ -2370,7 +3151,6 @@ class ItemComponent extends CreateDynamicComponent('crud-item-page') {
|
|
|
2370
3151
|
}
|
|
2371
3152
|
selected;
|
|
2372
3153
|
standardComponents = viewChildren(ItemStandardComponent, ...(ngDevMode ? [{ debugName: "standardComponents" }] : []));
|
|
2373
|
-
// @ViewChild(IonContent, { static: true }) content: IonContent; //TODO: rewrite when rewriting ionic
|
|
2374
3154
|
contentTpl = viewChild('contentTpl', ...(ngDevMode ? [{ debugName: "contentTpl" }] : []));
|
|
2375
3155
|
topTpl = viewChild('topTpl', ...(ngDevMode ? [{ debugName: "topTpl" }] : []));
|
|
2376
3156
|
bottomTpl = viewChild('bottomTpl', ...(ngDevMode ? [{ debugName: "bottomTpl" }] : []));
|
|
@@ -2666,54 +3446,54 @@ class ItemComponent extends CreateDynamicComponent('crud-item-page') {
|
|
|
2666
3446
|
}
|
|
2667
3447
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2668
3448
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: ItemComponent, isStandalone: true, selector: "smart-crud-item-page", viewQueries: [{ propertyName: "standardComponents", predicate: ItemStandardComponent, descendants: true, isSignal: true }, { propertyName: "contentTpl", first: true, predicate: ["contentTpl"], descendants: true, isSignal: true }, { propertyName: "topTpl", first: true, predicate: ["topTpl"], descendants: true, isSignal: true }, { propertyName: "bottomTpl", first: true, predicate: ["bottomTpl"], descendants: true, isSignal: true }, { propertyName: "dynamicContents", predicate: DynamicContentDirective, descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: `
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
`, isInline: true, dependencies: [{ kind: "component", type:
|
|
3449
|
+
<smart-page [options]="pageOptions()" [class]="config.cssClass || ''">
|
|
3450
|
+
<div #topTpl class="text-xl py-2.5 separator"></div>
|
|
3451
|
+
@if (template() === 'default') {
|
|
3452
|
+
<smart-crud-item-standard-page
|
|
3453
|
+
[detailsOptions]="detailsOptions()"
|
|
3454
|
+
[mode]="mode"
|
|
3455
|
+
[uniqueProvider]="uniqueProvider()"
|
|
3456
|
+
(onPartialChange)="onPartialChange($event)"
|
|
3457
|
+
(onChange)="onChange($event)"
|
|
3458
|
+
(onValidChange)="onValidChange($event)"
|
|
3459
|
+
>
|
|
3460
|
+
<ng-container [ngTemplateOutlet]="contentTpl"></ng-container>
|
|
3461
|
+
</smart-crud-item-standard-page>
|
|
3462
|
+
}
|
|
3463
|
+
<ng-template #contentTpl>
|
|
3464
|
+
<ng-content></ng-content>
|
|
3465
|
+
</ng-template>
|
|
3466
|
+
<div class="dynamic-content"></div>
|
|
3467
|
+
<div #bottomTpl class="text-xl py-2.5 separator"></div>
|
|
3468
|
+
</smart-page>
|
|
3469
|
+
`, isInline: true, dependencies: [{ kind: "component", type: PageComponent, selector: "smart-page", inputs: ["options", "class"] }, { kind: "component", type: ItemStandardComponent, selector: "smart-crud-item-standard-page" }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] });
|
|
2690
3470
|
}
|
|
2691
3471
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ItemComponent, decorators: [{
|
|
2692
3472
|
type: Component,
|
|
2693
3473
|
args: [{
|
|
2694
3474
|
selector: 'smart-crud-item-page',
|
|
2695
|
-
imports: [
|
|
3475
|
+
imports: [PageComponent, ItemStandardComponent, NgTemplateOutlet],
|
|
2696
3476
|
template: `
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
3477
|
+
<smart-page [options]="pageOptions()" [class]="config.cssClass || ''">
|
|
3478
|
+
<div #topTpl class="text-xl py-2.5 separator"></div>
|
|
3479
|
+
@if (template() === 'default') {
|
|
3480
|
+
<smart-crud-item-standard-page
|
|
3481
|
+
[detailsOptions]="detailsOptions()"
|
|
3482
|
+
[mode]="mode"
|
|
3483
|
+
[uniqueProvider]="uniqueProvider()"
|
|
3484
|
+
(onPartialChange)="onPartialChange($event)"
|
|
3485
|
+
(onChange)="onChange($event)"
|
|
3486
|
+
(onValidChange)="onValidChange($event)"
|
|
3487
|
+
>
|
|
3488
|
+
<ng-container [ngTemplateOutlet]="contentTpl"></ng-container>
|
|
3489
|
+
</smart-crud-item-standard-page>
|
|
3490
|
+
}
|
|
3491
|
+
<ng-template #contentTpl>
|
|
3492
|
+
<ng-content></ng-content>
|
|
3493
|
+
</ng-template>
|
|
3494
|
+
<div class="dynamic-content"></div>
|
|
3495
|
+
<div #bottomTpl class="text-xl py-2.5 separator"></div>
|
|
3496
|
+
</smart-page>
|
|
2717
3497
|
`,
|
|
2718
3498
|
}]
|
|
2719
3499
|
}], ctorParameters: () => [], propDecorators: { standardComponents: [{ type: i0.ViewChildren, args: [i0.forwardRef(() => ItemStandardComponent), { isSignal: true }] }], contentTpl: [{ type: i0.ViewChild, args: ['contentTpl', { isSignal: true }] }], topTpl: [{ type: i0.ViewChild, args: ['topTpl', { isSignal: true }] }], bottomTpl: [{ type: i0.ViewChild, args: ['bottomTpl', { isSignal: true }] }], dynamicContents: [{ type: i0.ViewChildren, args: [i0.forwardRef(() => DynamicContentDirective), { isSignal: true }] }] } });
|
|
@@ -2750,7 +3530,7 @@ class ListStandardComponent extends CrudListPageBaseComponent {
|
|
|
2750
3530
|
[listOptions]="listOptions() || null"
|
|
2751
3531
|
></smart-crud-group>
|
|
2752
3532
|
}
|
|
2753
|
-
`, isInline: true, dependencies: [{ kind: "component", type: FiltersConfigComponent, selector: "smart-crud-filters-config" }, { kind: "component", type: ListComponent$1, selector: "smart-list", inputs: ["options", "class"] }, { kind: "component", type: GroupComponent, selector: "smart-crud-group"
|
|
3533
|
+
`, isInline: true, dependencies: [{ kind: "component", type: FiltersConfigComponent, selector: "smart-crud-filters-config" }, { kind: "component", type: ListComponent$1, selector: "smart-list", inputs: ["options", "class"] }, { kind: "component", type: GroupComponent, selector: "smart-crud-group" }] });
|
|
2754
3534
|
}
|
|
2755
3535
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ListStandardComponent, decorators: [{
|
|
2756
3536
|
type: Component,
|
|
@@ -2843,7 +3623,7 @@ class ListComponent extends CreateDynamicComponent('crud-list-page') {
|
|
|
2843
3623
|
if (this.config.list?.resetQuery === 'beforeInit') {
|
|
2844
3624
|
newFilter = {
|
|
2845
3625
|
query: this.config.baseQuery ? [...this.config.baseQuery] : [],
|
|
2846
|
-
paginationMode: this.config.list
|
|
3626
|
+
paginationMode: this.config.list?.paginationMode,
|
|
2847
3627
|
limit: this.config.pagination
|
|
2848
3628
|
? this.config.pagination.limit
|
|
2849
3629
|
: undefined,
|
|
@@ -2862,7 +3642,7 @@ class ListComponent extends CreateDynamicComponent('crud-list-page') {
|
|
|
2862
3642
|
}
|
|
2863
3643
|
else {
|
|
2864
3644
|
newFilter = {
|
|
2865
|
-
paginationMode: this.config.list
|
|
3645
|
+
paginationMode: this.config.list?.paginationMode,
|
|
2866
3646
|
limit: this.searchService.filter?.limit
|
|
2867
3647
|
? this.searchService.filter.limit
|
|
2868
3648
|
: this.config.pagination
|
|
@@ -2892,6 +3672,7 @@ class ListComponent extends CreateDynamicComponent('crud-list-page') {
|
|
|
2892
3672
|
const endButtons = this.getEndButtons();
|
|
2893
3673
|
this.pageOptions.set({
|
|
2894
3674
|
title: this.config.title || '',
|
|
3675
|
+
variant: this.config.variant,
|
|
2895
3676
|
search: this.config.search
|
|
2896
3677
|
? {
|
|
2897
3678
|
text: computed(() => this.filter()?.searchText ?? ''),
|
|
@@ -3008,8 +3789,8 @@ class ListComponent extends CreateDynamicComponent('crud-list-page') {
|
|
|
3008
3789
|
}
|
|
3009
3790
|
: undefined,
|
|
3010
3791
|
pagination: await this.paginationFacade.create({
|
|
3011
|
-
mode: this.config.list
|
|
3012
|
-
limit: this.config.pagination
|
|
3792
|
+
mode: this.config.list?.paginationMode,
|
|
3793
|
+
limit: this.config.pagination?.limit ?? 0,
|
|
3013
3794
|
provider: {
|
|
3014
3795
|
getFilter: () => {
|
|
3015
3796
|
return this.filter() || {};
|
|
@@ -3125,42 +3906,42 @@ class ListComponent extends CreateDynamicComponent('crud-list-page') {
|
|
|
3125
3906
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ListComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
3126
3907
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: ListComponent, isStandalone: true, selector: "smart-crud-list-page", viewQueries: [{ propertyName: "topTpl", first: true, predicate: ["topTpl"], descendants: true, isSignal: true }, { propertyName: "contentTpl", first: true, predicate: ["contentTpl"], descendants: true, isSignal: true }, { propertyName: "dynamicContents", predicate: DynamicContentDirective, descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: `
|
|
3127
3908
|
@if (filter() && pageOptions()) {
|
|
3128
|
-
|
|
3129
|
-
|
|
3909
|
+
<smart-page [options]="pageOptions()" [class]="config.cssClass || ''">
|
|
3910
|
+
<div #topTpl></div>
|
|
3130
3911
|
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3912
|
+
@if (template() === 'default' && listOptions()) {
|
|
3913
|
+
<smart-crud-list-standard-page [listOptions]="listOptions()">
|
|
3914
|
+
<ng-container [ngTemplateOutlet]="contentTpl"></ng-container>
|
|
3915
|
+
</smart-crud-list-standard-page>
|
|
3916
|
+
}
|
|
3917
|
+
<ng-template #contentTpl>
|
|
3918
|
+
<ng-content></ng-content>
|
|
3919
|
+
</ng-template>
|
|
3920
|
+
<div class="dynamic-content"></div>
|
|
3921
|
+
</smart-page>
|
|
3141
3922
|
}
|
|
3142
|
-
`, isInline: true, dependencies: [{ kind: "component", type: ListStandardComponent, selector: "smart-crud-list-standard-page" }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] });
|
|
3923
|
+
`, isInline: true, dependencies: [{ kind: "component", type: PageComponent, selector: "smart-page", inputs: ["options", "class"] }, { kind: "component", type: ListStandardComponent, selector: "smart-crud-list-standard-page" }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] });
|
|
3143
3924
|
}
|
|
3144
3925
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ListComponent, decorators: [{
|
|
3145
3926
|
type: Component,
|
|
3146
3927
|
args: [{
|
|
3147
3928
|
selector: 'smart-crud-list-page',
|
|
3148
|
-
imports: [ListStandardComponent, NgTemplateOutlet],
|
|
3929
|
+
imports: [PageComponent, ListStandardComponent, NgTemplateOutlet],
|
|
3149
3930
|
template: `
|
|
3150
3931
|
@if (filter() && pageOptions()) {
|
|
3151
|
-
|
|
3152
|
-
|
|
3932
|
+
<smart-page [options]="pageOptions()" [class]="config.cssClass || ''">
|
|
3933
|
+
<div #topTpl></div>
|
|
3153
3934
|
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3935
|
+
@if (template() === 'default' && listOptions()) {
|
|
3936
|
+
<smart-crud-list-standard-page [listOptions]="listOptions()">
|
|
3937
|
+
<ng-container [ngTemplateOutlet]="contentTpl"></ng-container>
|
|
3938
|
+
</smart-crud-list-standard-page>
|
|
3939
|
+
}
|
|
3940
|
+
<ng-template #contentTpl>
|
|
3941
|
+
<ng-content></ng-content>
|
|
3942
|
+
</ng-template>
|
|
3943
|
+
<div class="dynamic-content"></div>
|
|
3944
|
+
</smart-page>
|
|
3164
3945
|
}
|
|
3165
3946
|
`,
|
|
3166
3947
|
}]
|
|
@@ -3255,7 +4036,9 @@ class CrudCoreModule {
|
|
|
3255
4036
|
CrudEffects,
|
|
3256
4037
|
PageService,
|
|
3257
4038
|
CrudFacade,
|
|
4039
|
+
SocketService,
|
|
3258
4040
|
CrudListPaginationFactory,
|
|
4041
|
+
{ provide: IModelLabelProvider, useClass: CrudModelLabelProvider },
|
|
3259
4042
|
], imports: [SharedModule,
|
|
3260
4043
|
CrudPipesModule,
|
|
3261
4044
|
FormsModule,
|
|
@@ -3279,7 +4062,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImpor
|
|
|
3279
4062
|
CrudEffects,
|
|
3280
4063
|
PageService,
|
|
3281
4064
|
CrudFacade,
|
|
4065
|
+
SocketService,
|
|
3282
4066
|
CrudListPaginationFactory,
|
|
4067
|
+
{ provide: IModelLabelProvider, useClass: CrudModelLabelProvider },
|
|
3283
4068
|
],
|
|
3284
4069
|
}]
|
|
3285
4070
|
}], ctorParameters: () => [{ type: CrudConfig }, { type: CrudEffects }] });
|
|
@@ -3294,6 +4079,9 @@ class CrudModule {
|
|
|
3294
4079
|
provide: FILE_SERVICE_CONFIG,
|
|
3295
4080
|
useValue: { apiUrl: options.config.apiUrl },
|
|
3296
4081
|
},
|
|
4082
|
+
...(options.socket
|
|
4083
|
+
? [SocketService]
|
|
4084
|
+
: [{ provide: SocketService, useClass: NotSocketService }]),
|
|
3297
4085
|
],
|
|
3298
4086
|
};
|
|
3299
4087
|
}
|
|
@@ -3332,5 +4120,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImpor
|
|
|
3332
4120
|
* Generated bundle index. Do not edit.
|
|
3333
4121
|
*/
|
|
3334
4122
|
|
|
3335
|
-
export { CRUD_MODEL_POSSIBILITIES_PROVIDER, CrudComponentsModule, CrudConfig, CrudCoreModule, CrudFacade, CrudFullConfig, CrudFullModule, CrudItemPageBaseComponent, CrudListPageBaseComponent, CrudListPaginationFactory, CrudModule, CrudPipesModule, CrudSearchService, CrudService, ExportComponent, FilterCheckComponent, FilterComponent, FilterDateComponent, FilterDateTimeComponent, FilterDateWithEditComponent, FilterFlagComponent, FilterIntComponent, FilterRadioComponent, FilterTextComponent, FiltersComponent, FiltersConfigComponent, FormOptionsPipe, GroupComponent, ICrudModelPossibilitiesProvider, ItemComponent, ItemStandardComponent, ListComponent, ListStandardComponent, MultiselectComponent, PAGES, PageService, getCrudError, getCrudFilter, getCrudLinks, getCrudList, getCrudLoaded, getCrudMultiSelected, getCrudSelected, getCrudState, getCrudTotalCount, getReducer, initialState };
|
|
4123
|
+
export { CRUD_MODEL_POSSIBILITIES_PROVIDER, CrudComponentsModule, CrudConfig, CrudCoreModule, CrudEffects, CrudFacade, CrudFullConfig, CrudFullModule, CrudItemPageBaseComponent, CrudListPageBaseComponent, CrudListPaginationFactory, CrudModelLabelProvider, CrudModule, CrudPipesModule, CrudSearchService, CrudService, ExportBaseComponent, ExportComponent, FilterCheckComponent, FilterComponent, FilterDateComponent, FilterDateTimeComponent, FilterDateWithEditComponent, FilterFlagComponent, FilterIntComponent, FilterRadioComponent, FilterTextComponent, FiltersBaseComponent, FiltersComponent, FiltersConfigComponent, FormOptionsPipe, GroupBaseComponent, GroupComponent, ICrudModelPossibilitiesProvider, ItemComponent, ItemStandardComponent, ListComponent, ListStandardComponent, MultiselectBaseComponent, MultiselectComponent, PAGES, PageService, clear, create, createFailure, createMany, createManyFailure, createManySuccess, createSuccess, deleteFailure, deleteItem, deleteSuccess, exportList, exportListFailure, exportListSuccess, getCrudError, getCrudFilter, getCrudLinks, getCrudList, getCrudLoaded, getCrudMultiSelected, getCrudSelected, getCrudState, getCrudTotalCount, getReducer, initialState, multiSelect, read, readFailure, readSuccess, select, selectFailure, selectSuccess, unselect, update, updateFailure, updatePartial, updatePartialFailure, updatePartialMany, updatePartialManyFailure, updatePartialManySuccess, updatePartialSuccess, updateSuccess };
|
|
3336
4124
|
//# sourceMappingURL=smartsoft001-crud-shell-angular.mjs.map
|