@smartsoft001/crud-shell-angular 2.125.0 → 2.127.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, Component, input, Directive, computed, signal, InjectionToken, Pipe, NgModule, viewChild, viewChildren, output, ChangeDetectorRef, effect, Injector } from '@angular/core';
3
- import { NgrxStoreService, PaginationMode, BaseComponent as BaseComponent$1, PopoverService, StyleService, ButtonComponent, MenuService, FormComponent, ListComponent as ListComponent$1, SharedModule, DetailsComponent, AuthService, CreateDynamicComponent, DynamicComponentLoader, ToastService, DetailsService, DynamicContentDirective, HardwareService, ListMode, FILE_SERVICE_CONFIG } from '@smartsoft001/angular';
4
- import { toSignal } from '@angular/core/rxjs-interop';
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 { map, first } from 'rxjs/operators';
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: "22.0.8", ngImport: i0, type: CrudConfig, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
256
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: CrudConfig });
257
+ }
258
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", 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: "22.0.8", ngImport: i0, type: CrudFullConfig, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
279
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: CrudFullConfig });
280
+ }
281
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", 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,115 +292,425 @@ 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
- class CrudFacade {
291
- store;
292
- config;
293
- loaded;
294
- loading;
295
- selected;
296
- multiSelected;
297
- list;
298
- filter;
299
- totalCount;
300
- links;
301
- error;
302
- constructor(store, config) {
303
- this.store = store;
304
- this.config = config;
305
- if (NgrxStoreService.store) {
306
- this.store = NgrxStoreService.store;
307
- }
308
- // Initialize all signals in the constructor (injection context)
309
- this.loaded = toSignal(this.store.pipe(select$1(getCrudLoaded(this.config.entity))));
310
- this.loading = toSignal(this.store.pipe(select$1(getCrudLoaded(this.config.entity)), map((l) => !l)));
311
- this.selected = toSignal(this.store.pipe(select$1(getCrudSelected(this.config.entity))));
312
- this.multiSelected = toSignal(this.store.pipe(select$1(getCrudMultiSelected(this.config.entity))));
313
- this.list = toSignal(this.store.pipe(select$1(getCrudList(this.config.entity))));
314
- this.filter = toSignal(this.store.pipe(select$1(getCrudFilter(this.config.entity))));
315
- this.totalCount = toSignal(this.store.pipe(select$1(getCrudTotalCount(this.config.entity))));
316
- this.links = toSignal(this.store.pipe(select$1(getCrudLinks(this.config.entity))));
317
- this.error = toSignal(this.store.pipe(select$1(getCrudError(this.config.entity))));
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: "22.0.8", ngImport: i0, type: SocketService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
302
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: SocketService });
303
+ }
304
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: SocketService, decorators: [{
305
+ type: Injectable
306
+ }] });
307
+ class NotSocketService {
308
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: NotSocketService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
309
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: NotSocketService });
310
+ }
311
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", 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
- this.store.dispatch(create(this.config.entity, item));
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.store.dispatch(createMany(this.config.entity, { items, options }));
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
- select(id) {
340
- this.store.dispatch(select(this.config.entity, id));
341
+ getById(id) {
342
+ return firstValueFrom(this.http.get(this.config.apiUrl + '/' + id));
341
343
  }
342
- unselect() {
343
- this.store.dispatch(unselect(this.config.entity));
344
+ getList(filter = null) {
345
+ return firstValueFrom(this.http.get(this.config.apiUrl + this.getQuery(filter)));
344
346
  }
345
- multiSelect(items) {
346
- this.store.dispatch(multiSelect(this.config.entity, items));
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.getStore().dispatch(update(this.config.entity, item));
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.getStore().dispatch(updatePartial(this.config.entity, item));
392
+ return firstValueFrom(this.http.patch(this.config.apiUrl + '/' + item.id, item));
356
393
  }
357
394
  updatePartialMany(items) {
358
- this.getStore().dispatch(updatePartialMany(this.config.entity, items));
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.getStore().dispatch(deleteItem(this.config.entity, id));
401
+ return firstValueFrom(this.http.delete(this.config.apiUrl + '/' + id));
362
402
  }
363
- getStore() {
364
- if (NgrxStoreService.store)
365
- return NgrxStoreService.store;
366
- return this.store;
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: CrudFacade, deps: [{ token: i1.Store }, { token: CrudConfig }], target: i0.ɵɵFactoryTarget.Injectable });
369
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudFacade });
430
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: CrudService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
431
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: CrudService });
370
432
  }
371
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudFacade, decorators: [{
433
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: CrudService, decorators: [{
372
434
  type: Injectable
373
- }], ctorParameters: () => [{ type: i1.Store }, { type: CrudConfig }] });
435
+ }] });
374
436
 
375
- const initialState = {
376
- loaded: false,
377
- };
378
- const crudReducer = (state, action, entity) => {
379
- if (!state) {
380
- state = { ...initialState };
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;
381
449
  }
382
- switch (action.type) {
383
- case `[${entity}] Create`:
384
- return {
385
- ...state,
386
- loaded: false,
387
- error: null,
388
- };
389
- case `[${entity}] Create Success`:
390
- return {
391
- ...state,
392
- loaded: true,
393
- error: null,
394
- };
395
- case `[${entity}] Create Failure`:
396
- return {
397
- ...state,
398
- loaded: true,
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: "22.0.8", 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: "22.0.8", ngImport: i0, type: CrudEffects });
600
+ }
601
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", 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: "22.0.8", ngImport: i0, type: CrudFacade, deps: [{ token: i1.Store }, { token: CrudConfig }], target: i0.ɵɵFactoryTarget.Injectable });
684
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: CrudFacade });
685
+ }
686
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", 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,
707
+ loaded: true,
708
+ error: null,
709
+ };
710
+ case `[${entity}] Create Failure`:
711
+ return {
712
+ ...state,
713
+ loaded: true,
399
714
  error: action.error,
400
715
  };
401
716
  case `[${entity}] Create Many`:
@@ -586,11 +901,12 @@ function getReducer(entity) {
586
901
  };
587
902
  }
588
903
 
589
- class ExportComponent extends BaseComponent$1 {
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,16 +920,23 @@ class ExportComponent extends BaseComponent$1 {
604
920
  offset: undefined,
605
921
  limit: undefined,
606
922
  }, format);
607
- const loading = this.facade.loading();
608
- if (loading)
609
- return;
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
  }
615
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ExportComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
616
- 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: `
930
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: ExportBaseComponent, deps: null, target: i0.ɵɵFactoryTarget.Directive });
931
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.8", type: ExportBaseComponent, isStandalone: true, usesInheritance: true, ngImport: i0 });
932
+ }
933
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: ExportBaseComponent, decorators: [{
934
+ type: Directive
935
+ }] });
936
+
937
+ class ExportComponent extends ExportBaseComponent {
938
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: ExportComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
939
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.0.8", type: ExportComponent, isStandalone: true, selector: "smart-crud-export", usesInheritance: true, ngImport: i0, template: `
617
940
  <div class="smart:p-5">
618
941
  <p class="smart:my-2.5 smart:mx-0">
619
942
  <smart-button
@@ -630,9 +953,9 @@ 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
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ExportComponent, decorators: [{
958
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: ExportComponent, decorators: [{
636
959
  type: Component,
637
960
  args: [{
638
961
  selector: 'smart-crud-export',
@@ -655,17 +978,95 @@ 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, /* @ts-ignore */
1011
+ ...(ngDevMode ? [{ debugName: "_pendingFilter" }] : /* istanbul ignore next */ []));
1012
+ /** Snapshot of `filter()` that `_pendingFilter` was derived from. */
1013
+ _pendingFilterSource;
664
1014
  possibilities;
665
- item = input(...(ngDevMode ? [undefined, { debugName: "item" }] : []));
666
- filter = input(...(ngDevMode ? [undefined, { debugName: "filter" }] : []));
1015
+ item = input(/* @ts-ignore */
1016
+ ...(ngDevMode ? [undefined, { debugName: "item" }] : /* istanbul ignore next */ []));
1017
+ filter = input(/* @ts-ignore */
1018
+ ...(ngDevMode ? [undefined, { debugName: "filter" }] : /* istanbul ignore next */ []));
1019
+ /**
1020
+ * The filter the component should read from: the pending working copy when it
1021
+ * is still in sync with the current input, otherwise the raw input. Once the
1022
+ * store update arrives (a new `filter()` reference), the pending copy is
1023
+ * considered stale and the fresh input wins.
1024
+ */
1025
+ effectiveFilter = computed(() => {
1026
+ const source = this.filter();
1027
+ const pending = this._pendingFilter();
1028
+ if (pending && source === this._pendingFilterSource)
1029
+ return pending;
1030
+ return source;
1031
+ }, /* @ts-ignore */
1032
+ ...(ngDevMode ? [{ debugName: "effectiveFilter" }] : /* istanbul ignore next */ []));
1033
+ /**
1034
+ * OnPush-safe replacement for `@if (value)` in templates (partial GAP-19).
1035
+ * True when filter().query has a matching entry (key + type) with a
1036
+ * non-empty value.
1037
+ */
1038
+ hasValue = computed(() => {
1039
+ const filter = this.effectiveFilter();
1040
+ const item = this.item();
1041
+ if (!filter || !item || !filter.query)
1042
+ return false;
1043
+ const query = filter.query.find((q) => q.key === item.key && q.type === item.type);
1044
+ if (!query)
1045
+ return false;
1046
+ const val = query.value;
1047
+ return val !== null && val !== undefined && val !== '';
1048
+ }, /* @ts-ignore */
1049
+ ...(ngDevMode ? [{ debugName: "hasValue" }] : /* istanbul ignore next */ []));
1050
+ /**
1051
+ * OnPush-safe replacement for `@if (minValue)` in templates (partial
1052
+ * GAP-19). True when filter().query has a matching `>=` entry (range "from")
1053
+ * with a non-empty value.
1054
+ */
1055
+ hasMinValue = computed(() => this.hasQueryValue('>='), /* @ts-ignore */
1056
+ ...(ngDevMode ? [{ debugName: "hasMinValue" }] : /* istanbul ignore next */ []));
1057
+ /**
1058
+ * OnPush-safe replacement for `@if (maxValue)` in templates (partial
1059
+ * GAP-19). True when filter().query has a matching `<=` entry (range "to")
1060
+ * with a non-empty value.
1061
+ */
1062
+ hasMaxValue = computed(() => this.hasQueryValue('<='), /* @ts-ignore */
1063
+ ...(ngDevMode ? [{ debugName: "hasMaxValue" }] : /* istanbul ignore next */ []));
1064
+ /** Lazily-built model instance used to derive field options/labels. */
1065
+ get model() {
1066
+ return (this._model ??= new this.config.type());
1067
+ }
667
1068
  get value() {
668
- const filter = this.filter();
1069
+ const filter = this.effectiveFilter();
669
1070
  const item = this.item();
670
1071
  if (!filter || !item || !filter.query)
671
1072
  return null;
@@ -681,7 +1082,7 @@ class BaseComponent {
681
1082
  this.refresh(val);
682
1083
  }
683
1084
  get minValue() {
684
- const filter = this.filter();
1085
+ const filter = this.effectiveFilter();
685
1086
  const item = this.item();
686
1087
  if (!filter || !item || !filter.query)
687
1088
  return null;
@@ -697,7 +1098,7 @@ class BaseComponent {
697
1098
  this.refresh(val, '>=');
698
1099
  }
699
1100
  get maxValue() {
700
- const filter = this.filter();
1101
+ const filter = this.effectiveFilter();
701
1102
  const item = this.item();
702
1103
  if (!filter || !item || !filter.query)
703
1104
  return null;
@@ -715,8 +1116,51 @@ class BaseComponent {
715
1116
  get lang() {
716
1117
  return this.translateService.currentLang;
717
1118
  }
1119
+ /**
1120
+ * Returns a filter object safe to mutate. The store-bound `filter()` input is
1121
+ * frozen under NgRx `strictStateImmutability`, so when (any part of) the
1122
+ * source is frozen we hand back a deep-enough clone — object + query array +
1123
+ * query entries — leaving the store untouched. When the source is a plain,
1124
+ * extensible object (no immutability checks active) we keep operating on it in
1125
+ * place so consumers that hold the same reference still observe the change.
1126
+ */
1127
+ cloneFilter() {
1128
+ const source = this.effectiveFilter();
1129
+ if (!source)
1130
+ return undefined;
1131
+ if (!this.isMutationSafe(source)) {
1132
+ return {
1133
+ ...source,
1134
+ query: source.query ? source.query.map((q) => ({ ...q })) : [],
1135
+ };
1136
+ }
1137
+ return source;
1138
+ }
1139
+ /**
1140
+ * True when `filter` (and its query array + entries) can be mutated directly,
1141
+ * i.e. nothing is frozen.
1142
+ */
1143
+ isMutationSafe(filter) {
1144
+ if (Object.isFrozen(filter))
1145
+ return false;
1146
+ const query = filter.query;
1147
+ if (!query)
1148
+ return true;
1149
+ if (Object.isFrozen(query))
1150
+ return false;
1151
+ return query.every((q) => !Object.isFrozen(q));
1152
+ }
1153
+ /**
1154
+ * Records the mutated clone as the pending working copy (so read getters
1155
+ * reflect it immediately) and dispatches it through the facade.
1156
+ */
1157
+ commitFilter(filter) {
1158
+ this._pendingFilterSource = this.filter();
1159
+ this._pendingFilter.set(filter);
1160
+ this.facade.read(filter);
1161
+ }
718
1162
  refresh(val, type = null) {
719
- const filter = this.filter();
1163
+ const filter = this.cloneFilter();
720
1164
  const item = this.item();
721
1165
  if (!filter || !item)
722
1166
  return;
@@ -726,7 +1170,7 @@ class BaseComponent {
726
1170
  filter.query = [];
727
1171
  filter.offset = 0;
728
1172
  if (this.isArrayType()) {
729
- this.refreshForArray(val, type);
1173
+ this.refreshForArray(filter, val, type);
730
1174
  return;
731
1175
  }
732
1176
  let query = filter.query.find((q) => q.key === item.key && q.type === type);
@@ -737,7 +1181,7 @@ class BaseComponent {
737
1181
  filter.query.splice(index, 1);
738
1182
  }
739
1183
  }
740
- this.facade.read(filter);
1184
+ this.commitFilter(filter);
741
1185
  return;
742
1186
  }
743
1187
  if (!query) {
@@ -750,32 +1194,100 @@ class BaseComponent {
750
1194
  }
751
1195
  query.value = val;
752
1196
  query.label = item.label;
753
- this.facade.read(filter);
1197
+ this.commitFilter(filter);
1198
+ }
1199
+ /**
1200
+ * Builds the `InputOptions` consumed by shared `smart-input-*` components for
1201
+ * a single reactive control. When `withPossibilities` is true (radio/select
1202
+ * style filters) the base `possibilities` signal is mapped into the
1203
+ * `{ id, text, checked }` shape the shared inputs expect; otherwise it is
1204
+ * omitted (text/flag filters do not need possibilities).
1205
+ */
1206
+ buildInputOptions(control, withPossibilities = false) {
1207
+ const options = {
1208
+ treeLevel: 0,
1209
+ control,
1210
+ model: this.model,
1211
+ fieldKey: this.item()?.key ?? '',
1212
+ };
1213
+ if (withPossibilities) {
1214
+ const source = this.possibilities ? this.possibilities() : [];
1215
+ options.possibilities = signal(source.map(({ id, text }) => ({ id, text, checked: false })), /* @ts-ignore */
1216
+ ...(ngDevMode ? [{ debugName: "possibilities" }] : /* istanbul ignore next */ []));
1217
+ }
1218
+ return options;
1219
+ }
1220
+ /**
1221
+ * Creates a reactive control bridged to the legacy filter state for a given
1222
+ * query slot: seeded from the current query value for that slot (`null` ->
1223
+ * `value` / `item.type`, `'>='` -> `minValue`, `'<='` -> `maxValue`), and
1224
+ * wired so every change re-runs the (debounced) `refresh` for that slot.
1225
+ */
1226
+ bindControl(type = null) {
1227
+ const seed = type === '>='
1228
+ ? this.minValue
1229
+ : type === '<='
1230
+ ? this.maxValue
1231
+ : this.value;
1232
+ const control = new UntypedFormControl(seed);
1233
+ control.valueChanges
1234
+ .pipe(takeUntilDestroyed(this.destroyRef))
1235
+ .subscribe((v) => this.refresh(v, type));
1236
+ // TODO(GAP-19): re-sync control when filter() changes externally
1237
+ return control;
1238
+ }
1239
+ /**
1240
+ * Creates a reactive control bridged to the default (`value` / `item.type`)
1241
+ * query slot.
1242
+ */
1243
+ bindValueControl() {
1244
+ return this.bindControl(null);
754
1245
  }
755
1246
  clear() {
756
- const filter = this.filter();
1247
+ const filter = this.cloneFilter();
757
1248
  const item = this.item();
758
1249
  if (!filter || !item || !filter.query)
759
1250
  return;
760
1251
  filter.query = filter.query?.filter((q) => q.key !== item.key);
761
1252
  filter.offset = 0;
762
- this.facade.read(filter);
1253
+ this.commitFilter(filter);
763
1254
  }
764
1255
  ngOnInit() {
765
1256
  this.initPossibilities();
766
1257
  }
767
1258
  initPossibilities() {
768
1259
  const item = this.item();
769
- if (item?.possibilities) {
770
- this.possibilities = item.possibilities;
1260
+ if (!item)
1261
+ return;
1262
+ let possibilities = item.possibilities;
1263
+ if (this.modelPossibilitiesProvider) {
1264
+ const fromProvider = this.modelPossibilitiesProvider.get(this.config.type);
1265
+ if (fromProvider && fromProvider[item.key]) {
1266
+ possibilities = toSignal(fromProvider[item.key], {
1267
+ initialValue: [],
1268
+ injector: this.injector,
1269
+ });
1270
+ }
771
1271
  }
1272
+ if (possibilities)
1273
+ this.possibilities = possibilities;
1274
+ }
1275
+ hasQueryValue(type) {
1276
+ const filter = this.effectiveFilter();
1277
+ const item = this.item();
1278
+ if (!filter || !item || !filter.query)
1279
+ return false;
1280
+ const query = filter.query.find((q) => q.key === item.key && q.type === type);
1281
+ if (!query)
1282
+ return false;
1283
+ const val = query.value;
1284
+ return val !== null && val !== undefined && val !== '';
772
1285
  }
773
1286
  isArrayType() {
774
1287
  const item = this.item();
775
1288
  return item?.fieldType === FieldType.check;
776
1289
  }
777
- refreshForArray(vals, type) {
778
- const filter = this.filter();
1290
+ refreshForArray(filter, vals, type) {
779
1291
  const item = this.item();
780
1292
  if (!filter || !item)
781
1293
  return;
@@ -789,7 +1301,7 @@ class BaseComponent {
789
1301
  }
790
1302
  });
791
1303
  if (vals === null || vals === undefined || !vals.length) {
792
- this.facade.read(filter);
1304
+ this.commitFilter(filter);
793
1305
  return;
794
1306
  }
795
1307
  vals.forEach((val) => {
@@ -800,10 +1312,10 @@ class BaseComponent {
800
1312
  };
801
1313
  filter.query.push(query);
802
1314
  });
803
- this.facade.read(filter);
1315
+ this.commitFilter(filter);
804
1316
  }
805
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: BaseComponent, deps: [], target: i0.ɵɵFactoryTarget.Directive });
806
- 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 });
1317
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: BaseComponent, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1318
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.8", 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 });
807
1319
  }
808
1320
  __decorate([
809
1321
  Debounce(500),
@@ -811,105 +1323,121 @@ __decorate([
811
1323
  __metadata("design:paramtypes", [Object, Object]),
812
1324
  __metadata("design:returntype", void 0)
813
1325
  ], BaseComponent.prototype, "refresh", null);
814
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: BaseComponent, decorators: [{
1326
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: BaseComponent, decorators: [{
815
1327
  type: Directive
816
1328
  }], 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
1329
 
1330
+ // TODO(FRA-293 GAP-19): re-sync rendered checked state when filter() changes
1331
+ // externally (the `value` getter already reads the reactive filter() signal,
1332
+ // so the `list` computed stays OnPush-safe).
818
1333
  class FilterCheckComponent extends BaseComponent {
819
1334
  list;
820
- ngAfterContentInit() {
1335
+ hasCheckedValues = computed(() => {
1336
+ const v = this.value;
1337
+ return Array.isArray(v) && v.length > 0;
1338
+ }, /* @ts-ignore */
1339
+ ...(ngDevMode ? [{ debugName: "hasCheckedValues" }] : /* istanbul ignore next */ []));
1340
+ ngOnInit() {
1341
+ super.ngOnInit();
821
1342
  this.list = computed(() => {
822
- const possibilities = this.possibilities();
1343
+ const possibilities = this.possibilities ? this.possibilities() : [];
1344
+ const v = this.value ?? [];
823
1345
  return possibilities.map((pos) => ({
824
1346
  value: pos,
825
- isCheck: this.value.some((r) => r === pos.id),
1347
+ isCheck: v.some((r) => r === pos.id),
826
1348
  }));
827
- }, ...(ngDevMode ? [{ debugName: "list" }] : []));
1349
+ }, /* @ts-ignore */
1350
+ ...(ngDevMode ? [{ debugName: "list" }] : /* istanbul ignore next */ []));
828
1351
  }
829
1352
  onCheckChange(checked, entry) {
830
- if (checked && !this.value.some((r) => r === entry.value.id)) {
831
- this.value = [...this.value, entry.value.id];
1353
+ if (checked && !(this.value ?? []).some((r) => r === entry.value.id)) {
1354
+ this.value = [...(this.value ?? []), entry.value.id];
832
1355
  }
833
- if (!checked && this.value.some((r) => r === entry.value.id)) {
1356
+ if (!checked && (this.value ?? []).some((r) => r === entry.value.id)) {
834
1357
  this.value = this.value?.filter((r) => r !== entry.value.id);
835
1358
  }
836
1359
  }
837
- 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
- <!-- <ion-row>-->
840
- <!-- <ion-col>-->
841
- <!-- <ion-item-divider class="text-xl font-light">-->
842
- <!-- <ion-icon class="mr-6 text-2xl" slot="start" name="filter-outline"></ion-icon>-->
843
- <!-- <ion-label>-->
844
- {{ item()?.label || '' | translate }}
845
- <!-- </ion-label>-->
846
- @if (value?.length) {
847
- <!-- <ion-button-->
848
- <!-- slot="end"-->
849
- <!-- color="danger"-->
850
- <!-- (click)="refresh([])"-->
851
- <!-- class="square-button m-0 p-0 text-lg h-9 w-9"-->
852
- <!-- >-->
853
- <!-- <ion-icon class="text-2xl m-0 p-0" slot="icon-only" name="close-outline"></ion-icon>-->
854
- <!-- </ion-button>-->
855
- }
856
- <!-- </ion-item-divider>-->
857
-
858
- @for (entry of list(); track entry) {
859
- <!-- <ion-item>-->
860
- <!--<ion-label>-->{{ entry.value.text | translate
861
- }}<!--</ion-label>-->
862
- <!-- <ion-checkbox-->
863
- <!-- slot="end"-->
864
- <!-- [checked]="entry.isCheck"-->
865
- <!-- (ionChange)="onCheckChange($event.detail.checked, entry)"-->
866
- <!-- ></ion-checkbox>-->
867
- <!-- </ion-item>-->
868
- }
869
- <!-- </ion-col>-->
870
- <!-- </ion-row>-->
871
- `, isInline: true, styles: [":host{width:100%;margin-bottom:1.2rem}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }] });
1360
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: FilterCheckComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1361
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: FilterCheckComponent, isStandalone: true, selector: "smart-crud-filter-check", host: { classAttribute: "smart:block smart:w-full" }, usesInheritance: true, ngImport: i0, template: `
1362
+ <fieldset class="smart:w-full">
1363
+ <legend
1364
+ class="smart:flex smart:items-center smart:justify-between smart:text-sm smart:font-medium smart:text-gray-900"
1365
+ >
1366
+ <span>{{ item()?.label || '' | translate }}</span>
1367
+ @if (hasCheckedValues()) {
1368
+ <button
1369
+ type="button"
1370
+ (click)="refresh([])"
1371
+ aria-label="clear"
1372
+ class="smart:rounded smart:px-2 smart:py-1 smart:text-red-600 smart:hover:bg-red-50"
1373
+ >
1374
+ ×
1375
+ </button>
1376
+ }
1377
+ </legend>
1378
+ <div class="smart:mt-2 smart:space-y-2">
1379
+ @for (entry of list(); track entry.value.id) {
1380
+ <label class="smart:flex smart:items-center smart:gap-x-2">
1381
+ <input
1382
+ type="checkbox"
1383
+ [checked]="entry.isCheck"
1384
+ (change)="onCheckChange($any($event.target).checked, entry)"
1385
+ class="smart:h-4 smart:w-4 smart:rounded smart:border-gray-300 smart:text-indigo-600 smart:focus:ring-indigo-500"
1386
+ />
1387
+ <span class="smart:text-sm smart:text-gray-900">{{
1388
+ entry.value.text | translate
1389
+ }}</span>
1390
+ </label>
1391
+ }
1392
+ </div>
1393
+ </fieldset>
1394
+ `, isInline: true, dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
872
1395
  }
873
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FilterCheckComponent, decorators: [{
1396
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: FilterCheckComponent, decorators: [{
874
1397
  type: Component,
875
- args: [{ selector: 'smart-crud-filter-check', template: `
876
- <!-- <ion-row>-->
877
- <!-- <ion-col>-->
878
- <!-- <ion-item-divider class="text-xl font-light">-->
879
- <!-- <ion-icon class="mr-6 text-2xl" slot="start" name="filter-outline"></ion-icon>-->
880
- <!-- <ion-label>-->
881
- {{ item()?.label || '' | translate }}
882
- <!-- </ion-label>-->
883
- @if (value?.length) {
884
- <!-- <ion-button-->
885
- <!-- slot="end"-->
886
- <!-- color="danger"-->
887
- <!-- (click)="refresh([])"-->
888
- <!-- class="square-button m-0 p-0 text-lg h-9 w-9"-->
889
- <!-- >-->
890
- <!-- <ion-icon class="text-2xl m-0 p-0" slot="icon-only" name="close-outline"></ion-icon>-->
891
- <!-- </ion-button>-->
892
- }
893
- <!-- </ion-item-divider>-->
894
-
895
- @for (entry of list(); track entry) {
896
- <!-- <ion-item>-->
897
- <!--<ion-label>-->{{ entry.value.text | translate
898
- }}<!--</ion-label>-->
899
- <!-- <ion-checkbox-->
900
- <!-- slot="end"-->
901
- <!-- [checked]="entry.isCheck"-->
902
- <!-- (ionChange)="onCheckChange($event.detail.checked, entry)"-->
903
- <!-- ></ion-checkbox>-->
904
- <!-- </ion-item>-->
905
- }
906
- <!-- </ion-col>-->
907
- <!-- </ion-row>-->
908
- `, imports: [TranslatePipe], styles: [":host{width:100%;margin-bottom:1.2rem}\n"] }]
1398
+ args: [{
1399
+ selector: 'smart-crud-filter-check',
1400
+ host: { class: 'smart:block smart:w-full' },
1401
+ template: `
1402
+ <fieldset class="smart:w-full">
1403
+ <legend
1404
+ class="smart:flex smart:items-center smart:justify-between smart:text-sm smart:font-medium smart:text-gray-900"
1405
+ >
1406
+ <span>{{ item()?.label || '' | translate }}</span>
1407
+ @if (hasCheckedValues()) {
1408
+ <button
1409
+ type="button"
1410
+ (click)="refresh([])"
1411
+ aria-label="clear"
1412
+ class="smart:rounded smart:px-2 smart:py-1 smart:text-red-600 smart:hover:bg-red-50"
1413
+ >
1414
+ ×
1415
+ </button>
1416
+ }
1417
+ </legend>
1418
+ <div class="smart:mt-2 smart:space-y-2">
1419
+ @for (entry of list(); track entry.value.id) {
1420
+ <label class="smart:flex smart:items-center smart:gap-x-2">
1421
+ <input
1422
+ type="checkbox"
1423
+ [checked]="entry.isCheck"
1424
+ (change)="onCheckChange($any($event.target).checked, entry)"
1425
+ class="smart:h-4 smart:w-4 smart:rounded smart:border-gray-300 smart:text-indigo-600 smart:focus:ring-indigo-500"
1426
+ />
1427
+ <span class="smart:text-sm smart:text-gray-900">{{
1428
+ entry.value.text | translate
1429
+ }}</span>
1430
+ </label>
1431
+ }
1432
+ </div>
1433
+ </fieldset>
1434
+ `,
1435
+ imports: [TranslatePipe],
1436
+ changeDetection: ChangeDetectionStrategy.OnPush,
1437
+ }]
909
1438
  }] });
910
1439
 
911
1440
  class FilterDateComponent extends BaseComponent {
912
- id = GuidService.create();
913
1441
  get allowAdvanced() {
914
1442
  const item = this.item();
915
1443
  return item?.type === '=';
@@ -944,293 +1472,782 @@ class FilterDateComponent extends BaseComponent {
944
1472
  get customMaxValue() {
945
1473
  return this.maxValue;
946
1474
  }
947
- 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", usesInheritance: true, ngImport: i0, template: "<!--<ion-row>-->\n<!-- <ion-col>-->\n<!-- <ion-label>-->\n{{ item()?.label || '' | translate }}\n<!-- </ion-label>-->\n<!-- <ion-item button=\"true\" id=\"open-date-input-{{ id }}\" color=\"primary\">-->\n<!-- <ion-text>-->\n{{ customValue ? customValue : ('select' | translate) }}\n<!-- </ion-text>-->\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 <!-- ></ion-datetime>-->\n</ng-template>\n<!-- </ion-popover>-->\n<!-- </ion-item>-->\n<!-- </ion-col>-->\n\n@if (value) {\n <!-- <ion-col size=\"auto\">-->\n <!-- <ion-button color=\"danger\" (click)=\"refresh(null)\" 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", 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" }] });
1475
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: FilterDateComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1476
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: FilterDateComponent, isStandalone: true, selector: "smart-crud-filter-date", host: { classAttribute: "smart:block smart:w-full" }, usesInheritance: true, ngImport: i0, template: `
1477
+ <label class="smart:mb-1 smart:block smart:text-sm smart:font-medium">
1478
+ {{ item()?.label || '' | translate }}
1479
+ </label>
1480
+ <div class="smart:flex smart:w-full smart:items-end smart:gap-2">
1481
+ <smart-date-edit
1482
+ class="smart:flex-1"
1483
+ [ngModel]="customValue || ''"
1484
+ (ngModelChange)="customValue = $event"
1485
+ ></smart-date-edit>
1486
+ @if (hasValue()) {
1487
+ <button
1488
+ type="button"
1489
+ (click)="refresh(null)"
1490
+ aria-label="clear"
1491
+ class="smart:shrink-0 smart:rounded smart:px-2 smart:py-2 smart:text-red-600 smart:hover:bg-red-50"
1492
+ >
1493
+ ×
1494
+ </button>
1495
+ }
1496
+ </div>
1497
+ `, 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 });
1498
+ }
1499
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: FilterDateComponent, decorators: [{
1500
+ type: Component,
1501
+ args: [{
1502
+ selector: 'smart-crud-filter-date',
1503
+ host: { class: 'smart:block smart:w-full' },
1504
+ // TODO(FRA-293 GAP-19): re-sync picker when filter() changes externally
1505
+ template: `
1506
+ <label class="smart:mb-1 smart:block smart:text-sm smart:font-medium">
1507
+ {{ item()?.label || '' | translate }}
1508
+ </label>
1509
+ <div class="smart:flex smart:w-full smart:items-end smart:gap-2">
1510
+ <smart-date-edit
1511
+ class="smart:flex-1"
1512
+ [ngModel]="customValue || ''"
1513
+ (ngModelChange)="customValue = $event"
1514
+ ></smart-date-edit>
1515
+ @if (hasValue()) {
1516
+ <button
1517
+ type="button"
1518
+ (click)="refresh(null)"
1519
+ aria-label="clear"
1520
+ class="smart:shrink-0 smart:rounded smart:px-2 smart:py-2 smart:text-red-600 smart:hover:bg-red-50"
1521
+ >
1522
+ ×
1523
+ </button>
1524
+ }
1525
+ </div>
1526
+ `,
1527
+ imports: [DateEditComponent, FormsModule, TranslatePipe],
1528
+ changeDetection: ChangeDetectionStrategy.OnPush,
1529
+ }]
1530
+ }] });
1531
+
1532
+ class FilterDateTimeComponent extends FilterDateComponent {
1533
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: FilterDateTimeComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1534
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: FilterDateTimeComponent, isStandalone: true, selector: "smart-crud-filter-date-time", host: { classAttribute: "smart:block smart:w-full" }, usesInheritance: true, ngImport: i0, template: `
1535
+ <label class="smart:mb-1 smart:block smart:text-sm smart:font-medium">
1536
+ {{ item()?.label || '' | translate }}
1537
+ </label>
1538
+ <div class="smart:flex smart:w-full smart:flex-col smart:gap-2">
1539
+ <div class="smart:flex smart:w-full smart:items-end smart:gap-2">
1540
+ <label class="smart:text-sm">{{ 'from' | translate }}</label>
1541
+ <input
1542
+ type="datetime-local"
1543
+ class="smart:flex-1 smart:rounded smart:border smart:border-gray-300 smart:px-2 smart:py-1"
1544
+ [ngModel]="customMinValue || ''"
1545
+ (ngModelChange)="customMinValue = $event"
1546
+ />
1547
+ @if (hasMinValue()) {
1548
+ <button
1549
+ type="button"
1550
+ (click)="refresh(null, '>=')"
1551
+ aria-label="clear-from"
1552
+ class="smart:shrink-0 smart:rounded smart:px-2 smart:py-2 smart:text-red-600 smart:hover:bg-red-50"
1553
+ >
1554
+ ×
1555
+ </button>
1556
+ }
1557
+ </div>
1558
+ <div class="smart:flex smart:w-full smart:items-end smart:gap-2">
1559
+ <label class="smart:text-sm">{{ 'to' | translate }}</label>
1560
+ <input
1561
+ type="datetime-local"
1562
+ class="smart:flex-1 smart:rounded smart:border smart:border-gray-300 smart:px-2 smart:py-1"
1563
+ [ngModel]="customMaxValue || ''"
1564
+ (ngModelChange)="customMaxValue = $event"
1565
+ />
1566
+ @if (hasMaxValue()) {
1567
+ <button
1568
+ type="button"
1569
+ (click)="refresh(null, '<=')"
1570
+ aria-label="clear-to"
1571
+ class="smart:shrink-0 smart:rounded smart:px-2 smart:py-2 smart:text-red-600 smart:hover:bg-red-50"
1572
+ >
1573
+ ×
1574
+ </button>
1575
+ }
1576
+ </div>
1577
+ </div>
1578
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[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 });
1579
+ }
1580
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: FilterDateTimeComponent, decorators: [{
1581
+ type: Component,
1582
+ args: [{
1583
+ selector: 'smart-crud-filter-date-time',
1584
+ host: { class: 'smart:block smart:w-full' },
1585
+ // TODO(FRA-293 GAP-19): re-sync picker when filter() changes externally
1586
+ template: `
1587
+ <label class="smart:mb-1 smart:block smart:text-sm smart:font-medium">
1588
+ {{ item()?.label || '' | translate }}
1589
+ </label>
1590
+ <div class="smart:flex smart:w-full smart:flex-col smart:gap-2">
1591
+ <div class="smart:flex smart:w-full smart:items-end smart:gap-2">
1592
+ <label class="smart:text-sm">{{ 'from' | translate }}</label>
1593
+ <input
1594
+ type="datetime-local"
1595
+ class="smart:flex-1 smart:rounded smart:border smart:border-gray-300 smart:px-2 smart:py-1"
1596
+ [ngModel]="customMinValue || ''"
1597
+ (ngModelChange)="customMinValue = $event"
1598
+ />
1599
+ @if (hasMinValue()) {
1600
+ <button
1601
+ type="button"
1602
+ (click)="refresh(null, '>=')"
1603
+ aria-label="clear-from"
1604
+ class="smart:shrink-0 smart:rounded smart:px-2 smart:py-2 smart:text-red-600 smart:hover:bg-red-50"
1605
+ >
1606
+ ×
1607
+ </button>
1608
+ }
1609
+ </div>
1610
+ <div class="smart:flex smart:w-full smart:items-end smart:gap-2">
1611
+ <label class="smart:text-sm">{{ 'to' | translate }}</label>
1612
+ <input
1613
+ type="datetime-local"
1614
+ class="smart:flex-1 smart:rounded smart:border smart:border-gray-300 smart:px-2 smart:py-1"
1615
+ [ngModel]="customMaxValue || ''"
1616
+ (ngModelChange)="customMaxValue = $event"
1617
+ />
1618
+ @if (hasMaxValue()) {
1619
+ <button
1620
+ type="button"
1621
+ (click)="refresh(null, '<=')"
1622
+ aria-label="clear-to"
1623
+ class="smart:shrink-0 smart:rounded smart:px-2 smart:py-2 smart:text-red-600 smart:hover:bg-red-50"
1624
+ >
1625
+ ×
1626
+ </button>
1627
+ }
1628
+ </div>
1629
+ </div>
1630
+ `,
1631
+ imports: [TranslatePipe, FormsModule],
1632
+ changeDetection: ChangeDetectionStrategy.OnPush,
1633
+ }]
1634
+ }] });
1635
+
1636
+ class FilterDateWithEditComponent extends FilterDateComponent {
1637
+ advanced = signal(false, /* @ts-ignore */
1638
+ ...(ngDevMode ? [{ debugName: "advanced" }] : /* istanbul ignore next */ []));
1639
+ toggleAdvanced() {
1640
+ this.advanced.update((val) => !val);
1641
+ if (this.advanced()) {
1642
+ this.value = null;
1643
+ }
1644
+ }
1645
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: FilterDateWithEditComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1646
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: FilterDateWithEditComponent, isStandalone: true, selector: "smart-crud-filter-date-with-edit", host: { classAttribute: "smart:block smart:w-full" }, usesInheritance: true, ngImport: i0, template: `
1647
+ <label class="smart:mb-1 smart:block smart:text-sm smart:font-medium">
1648
+ {{ item()?.label || '' | translate }}
1649
+ </label>
1650
+
1651
+ @if (!advanced()) {
1652
+ <div class="smart:flex smart:w-full smart:items-end smart:gap-2">
1653
+ <smart-date-edit
1654
+ class="smart:flex-1"
1655
+ [ngModel]="customValue || ''"
1656
+ (ngModelChange)="customValue = $event"
1657
+ ></smart-date-edit>
1658
+ @if (allowAdvanced) {
1659
+ <button
1660
+ type="button"
1661
+ (click)="toggleAdvanced()"
1662
+ aria-label="advanced"
1663
+ class="smart:shrink-0 smart:rounded smart:px-2 smart:py-2 smart:hover:bg-gray-100"
1664
+ >
1665
+
1666
+ </button>
1667
+ }
1668
+ @if (hasValue()) {
1669
+ <button
1670
+ type="button"
1671
+ (click)="refresh(null)"
1672
+ aria-label="clear"
1673
+ class="smart:shrink-0 smart:rounded smart:px-2 smart:py-2 smart:text-red-600 smart:hover:bg-red-50"
1674
+ >
1675
+ ×
1676
+ </button>
1677
+ }
1678
+ </div>
1679
+ } @else if (allowAdvanced) {
1680
+ <button
1681
+ type="button"
1682
+ (click)="toggleAdvanced()"
1683
+ aria-label="advanced"
1684
+ class="smart:mb-2 smart:rounded smart:px-2 smart:py-2 smart:hover:bg-gray-100"
1685
+ >
1686
+
1687
+ </button>
1688
+ }
1689
+
1690
+ @if ((advanced() || hasMinValue() || hasMaxValue()) && allowAdvanced) {
1691
+ <div class="smart:flex smart:w-full smart:flex-col smart:gap-2">
1692
+ <div class="smart:flex smart:w-full smart:items-end smart:gap-2">
1693
+ <label class="smart:text-sm">{{ 'from' | translate }}</label>
1694
+ <smart-date-edit
1695
+ class="smart:flex-1"
1696
+ [ngModel]="customMinValue || ''"
1697
+ (ngModelChange)="customMinValue = $event"
1698
+ ></smart-date-edit>
1699
+ @if (hasMinValue()) {
1700
+ <button
1701
+ type="button"
1702
+ (click)="refresh(null, '>=')"
1703
+ aria-label="clear-from"
1704
+ class="smart:shrink-0 smart:rounded smart:px-2 smart:py-2 smart:text-red-600 smart:hover:bg-red-50"
1705
+ >
1706
+ ×
1707
+ </button>
1708
+ }
1709
+ </div>
1710
+ <div class="smart:flex smart:w-full smart:items-end smart:gap-2">
1711
+ <label class="smart:text-sm">{{ 'to' | translate }}</label>
1712
+ <smart-date-edit
1713
+ class="smart:flex-1"
1714
+ [ngModel]="customMaxValue || ''"
1715
+ (ngModelChange)="customMaxValue = $event"
1716
+ ></smart-date-edit>
1717
+ @if (hasMaxValue()) {
1718
+ <button
1719
+ type="button"
1720
+ (click)="refresh(null, '<=')"
1721
+ aria-label="clear-to"
1722
+ class="smart:shrink-0 smart:rounded smart:px-2 smart:py-2 smart:text-red-600 smart:hover:bg-red-50"
1723
+ >
1724
+ ×
1725
+ </button>
1726
+ }
1727
+ </div>
1728
+ </div>
1729
+ }
1730
+ `, 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
1731
  }
950
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FilterDateComponent, decorators: [{
1732
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: FilterDateWithEditComponent, decorators: [{
951
1733
  type: Component,
952
- args: [{ selector: 'smart-crud-filter-date', imports: [FormsModule, TranslatePipe], template: "<!--<ion-row>-->\n<!-- <ion-col>-->\n<!-- <ion-label>-->\n{{ item()?.label || '' | translate }}\n<!-- </ion-label>-->\n<!-- <ion-item button=\"true\" id=\"open-date-input-{{ id }}\" color=\"primary\">-->\n<!-- <ion-text>-->\n{{ customValue ? customValue : ('select' | translate) }}\n<!-- </ion-text>-->\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 <!-- ></ion-datetime>-->\n</ng-template>\n<!-- </ion-popover>-->\n<!-- </ion-item>-->\n<!-- </ion-col>-->\n\n@if (value) {\n <!-- <ion-col size=\"auto\">-->\n <!-- <ion-button color=\"danger\" (click)=\"refresh(null)\" 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", styles: [":host{width:100%}:host .square-button{height:var(--smart-button-height)!important}\n"] }]
1734
+ args: [{
1735
+ selector: 'smart-crud-filter-date-with-edit',
1736
+ host: { class: 'smart:block smart:w-full' },
1737
+ // TODO(FRA-293 GAP-19): re-sync picker when filter() changes externally
1738
+ template: `
1739
+ <label class="smart:mb-1 smart:block smart:text-sm smart:font-medium">
1740
+ {{ item()?.label || '' | translate }}
1741
+ </label>
1742
+
1743
+ @if (!advanced()) {
1744
+ <div class="smart:flex smart:w-full smart:items-end smart:gap-2">
1745
+ <smart-date-edit
1746
+ class="smart:flex-1"
1747
+ [ngModel]="customValue || ''"
1748
+ (ngModelChange)="customValue = $event"
1749
+ ></smart-date-edit>
1750
+ @if (allowAdvanced) {
1751
+ <button
1752
+ type="button"
1753
+ (click)="toggleAdvanced()"
1754
+ aria-label="advanced"
1755
+ class="smart:shrink-0 smart:rounded smart:px-2 smart:py-2 smart:hover:bg-gray-100"
1756
+ >
1757
+
1758
+ </button>
1759
+ }
1760
+ @if (hasValue()) {
1761
+ <button
1762
+ type="button"
1763
+ (click)="refresh(null)"
1764
+ aria-label="clear"
1765
+ class="smart:shrink-0 smart:rounded smart:px-2 smart:py-2 smart:text-red-600 smart:hover:bg-red-50"
1766
+ >
1767
+ ×
1768
+ </button>
1769
+ }
1770
+ </div>
1771
+ } @else if (allowAdvanced) {
1772
+ <button
1773
+ type="button"
1774
+ (click)="toggleAdvanced()"
1775
+ aria-label="advanced"
1776
+ class="smart:mb-2 smart:rounded smart:px-2 smart:py-2 smart:hover:bg-gray-100"
1777
+ >
1778
+
1779
+ </button>
1780
+ }
1781
+
1782
+ @if ((advanced() || hasMinValue() || hasMaxValue()) && allowAdvanced) {
1783
+ <div class="smart:flex smart:w-full smart:flex-col smart:gap-2">
1784
+ <div class="smart:flex smart:w-full smart:items-end smart:gap-2">
1785
+ <label class="smart:text-sm">{{ 'from' | translate }}</label>
1786
+ <smart-date-edit
1787
+ class="smart:flex-1"
1788
+ [ngModel]="customMinValue || ''"
1789
+ (ngModelChange)="customMinValue = $event"
1790
+ ></smart-date-edit>
1791
+ @if (hasMinValue()) {
1792
+ <button
1793
+ type="button"
1794
+ (click)="refresh(null, '>=')"
1795
+ aria-label="clear-from"
1796
+ class="smart:shrink-0 smart:rounded smart:px-2 smart:py-2 smart:text-red-600 smart:hover:bg-red-50"
1797
+ >
1798
+ ×
1799
+ </button>
1800
+ }
1801
+ </div>
1802
+ <div class="smart:flex smart:w-full smart:items-end smart:gap-2">
1803
+ <label class="smart:text-sm">{{ 'to' | translate }}</label>
1804
+ <smart-date-edit
1805
+ class="smart:flex-1"
1806
+ [ngModel]="customMaxValue || ''"
1807
+ (ngModelChange)="customMaxValue = $event"
1808
+ ></smart-date-edit>
1809
+ @if (hasMaxValue()) {
1810
+ <button
1811
+ type="button"
1812
+ (click)="refresh(null, '<=')"
1813
+ aria-label="clear-to"
1814
+ class="smart:shrink-0 smart:rounded smart:px-2 smart:py-2 smart:text-red-600 smart:hover:bg-red-50"
1815
+ >
1816
+ ×
1817
+ </button>
1818
+ }
1819
+ </div>
1820
+ </div>
1821
+ }
1822
+ `,
1823
+ imports: [DateEditComponent, FormsModule, TranslatePipe],
1824
+ changeDetection: ChangeDetectionStrategy.OnPush,
1825
+ }]
953
1826
  }] });
954
1827
 
955
- class FilterDateTimeComponent extends FilterDateComponent {
956
- _subscriptions = new Subscription();
957
- id = GuidService.create();
958
- // @ViewChild(IonDatetime, { read: IonDatetime, static: false })
959
- // dateTimePicker: IonDatetime;
1828
+ class FilterFlagComponent extends BaseComponent {
1829
+ inputOptions = signal(undefined, /* @ts-ignore */
1830
+ ...(ngDevMode ? [{ debugName: "inputOptions" }] : /* istanbul ignore next */ []));
1831
+ fieldOptions = signal(undefined, /* @ts-ignore */
1832
+ ...(ngDevMode ? [{ debugName: "fieldOptions" }] : /* istanbul ignore next */ []));
960
1833
  ngOnInit() {
961
1834
  super.ngOnInit();
962
- // if (this.dateTimePicker) {
963
- // this._subscriptions.add(
964
- // this.dateTimePicker.ionChange.subscribe((val: CustomEvent) => {
965
- // this.customValue = val.detail.value;
966
- // }),
967
- // );
968
- // } else {
969
- // console.error('dateTimePicker not found!');
970
- // }
971
- }
972
- ngOnDestroy() {
973
- if (this._subscriptions) {
974
- this._subscriptions.unsubscribe();
1835
+ const control = this.bindValueControl();
1836
+ this.inputOptions.set(this.buildInputOptions(control));
1837
+ }
1838
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: FilterFlagComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1839
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: FilterFlagComponent, isStandalone: true, selector: "smart-crud-filter-flag", host: { classAttribute: "smart:block smart:w-full" }, usesInheritance: true, ngImport: i0, template: `
1840
+ @if (inputOptions()) {
1841
+ <div class="smart:flex smart:w-full smart:items-center smart:gap-2">
1842
+ <smart-input-flag
1843
+ class="smart:flex-1"
1844
+ [options]="inputOptions()!"
1845
+ [fieldOptions]="fieldOptions()"
1846
+ ></smart-input-flag>
1847
+ @if (value === true || value === false) {
1848
+ <button
1849
+ type="button"
1850
+ (click)="refresh(null)"
1851
+ aria-label="clear"
1852
+ class="smart:shrink-0 smart:rounded smart:px-2 smart:py-2 smart:text-red-600 smart:hover:bg-red-50"
1853
+ >
1854
+ ×
1855
+ </button>
975
1856
  }
1857
+ </div>
976
1858
  }
977
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FilterDateTimeComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
978
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: FilterDateTimeComponent, isStandalone: true, selector: "smart-crud-filter-date-time", usesInheritance: true, ngImport: i0, template: "<!--<ion-row>-->\n<!-- <ion-col>-->\n<!-- <ion-label>-->\n{{ item()?.label || '' | translate }}\n<!-- </ion-label>-->\n<!-- </ion-col>-->\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<!--<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 HH:mm:ss\"-->\n<!-- [(ngModel)]=\"customMinValue\"-->\n<!-- pattern=\"^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}$\"-->\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 HH:mm:ss\"-->\n<!-- [(ngModel)]=\"customMaxValue\"-->\n<!-- pattern=\"^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}$\"-->\n<!-- ></ion-input>-->\n<!-- </ion-item>-->\n<!-- </ion-col>-->\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", 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" }] });
1859
+ `, isInline: true, dependencies: [{ kind: "component", type: InputFlagComponent, selector: "smart-input-flag" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
979
1860
  }
980
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FilterDateTimeComponent, decorators: [{
1861
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: FilterFlagComponent, decorators: [{
981
1862
  type: Component,
982
- args: [{ selector: 'smart-crud-filter-date-time', imports: [TranslatePipe, FormsModule], template: "<!--<ion-row>-->\n<!-- <ion-col>-->\n<!-- <ion-label>-->\n{{ item()?.label || '' | translate }}\n<!-- </ion-label>-->\n<!-- </ion-col>-->\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<!--<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 HH:mm:ss\"-->\n<!-- [(ngModel)]=\"customMinValue\"-->\n<!-- pattern=\"^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}$\"-->\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 HH:mm:ss\"-->\n<!-- [(ngModel)]=\"customMaxValue\"-->\n<!-- pattern=\"^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}$\"-->\n<!-- ></ion-input>-->\n<!-- </ion-item>-->\n<!-- </ion-col>-->\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", styles: [":host{width:100%}:host .square-button{height:var(--smart-button-height)!important}\n"] }]
983
- }] });
984
-
985
- class FilterDateWithEditComponent extends FilterDateComponent {
986
- _subscriptions = new Subscription();
987
- advanced = signal(false, ...(ngDevMode ? [{ debugName: "advanced" }] : []));
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
- }
997
- ngOnInit() {
998
- super.ngOnInit();
999
- // if (this.dateTimePicker) {
1000
- // this._subscriptions.add(
1001
- // this.dateTimePicker.ionChange.subscribe((val: CustomEvent) => {
1002
- // this.customValue = val.detail.value;
1003
- // }),
1004
- // );
1005
- // } else {
1006
- // console.error('dateTimePicker not found!');
1007
- // }
1008
- }
1009
- ngOnDestroy() {
1010
- if (this._subscriptions) {
1011
- this._subscriptions.unsubscribe();
1863
+ args: [{
1864
+ selector: 'smart-crud-filter-flag',
1865
+ host: { class: 'smart:block smart:w-full' },
1866
+ template: `
1867
+ @if (inputOptions()) {
1868
+ <div class="smart:flex smart:w-full smart:items-center smart:gap-2">
1869
+ <smart-input-flag
1870
+ class="smart:flex-1"
1871
+ [options]="inputOptions()!"
1872
+ [fieldOptions]="fieldOptions()"
1873
+ ></smart-input-flag>
1874
+ @if (value === true || value === false) {
1875
+ <button
1876
+ type="button"
1877
+ (click)="refresh(null)"
1878
+ aria-label="clear"
1879
+ class="smart:shrink-0 smart:rounded smart:px-2 smart:py-2 smart:text-red-600 smart:hover:bg-red-50"
1880
+ >
1881
+ ×
1882
+ </button>
1012
1883
  }
1884
+ </div>
1013
1885
  }
1014
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FilterDateWithEditComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
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" }] });
1049
- }
1050
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FilterFlagComponent, decorators: [{
1051
- type: Component,
1052
- args: [{ selector: 'smart-crud-filter-flag', template: `
1053
- <!-- <ion-row>-->
1054
- <!-- <ion-col>-->
1055
- <div
1056
- class="flag-container w-full flex flex-row flex-nowrap justify-between pr-5"
1057
- >
1058
- <!-- <ion-label class="align-middle my-6" position="static">-->
1059
- {{ item()?.label || '' | translate }}
1060
- <!-- </ion-label>-->
1061
- <!-- <ion-checkbox [(ngModel)]="value" slot="end"></ion-checkbox>-->
1062
- </div>
1063
- <!-- </ion-col>-->
1064
- @if (typeof value === 'boolean') {
1065
- <!-- <ion-col size="auto">-->
1066
- <!-- <ion-button-->
1067
- <!-- color="danger"-->
1068
- <!-- (click)="refresh(null)"-->
1069
- <!-- class="square-button m-3"-->
1070
- <!-- >-->
1071
- <!-- <ion-icon slot="icon-only" name="close-outline"></ion-icon>-->
1072
- <!-- </ion-button>-->
1073
- <!-- </ion-col>-->
1074
- }
1075
- <!-- </ion-row>-->
1076
- `, imports: [TranslatePipe, FormsModule], styles: [":host{width:100%}:host .square-button{height:var(--smart-button-height)!important}\n"] }]
1886
+ `,
1887
+ imports: [InputFlagComponent],
1888
+ changeDetection: ChangeDetectionStrategy.OnPush,
1889
+ }]
1077
1890
  }] });
1078
1891
 
1892
+ // TODO(FRA-293 GAP-19): the advanced range controls (minControl/maxControl)
1893
+ // are not re-synced when filter() changes externally; see bindControl().
1079
1894
  class FilterIntComponent extends BaseComponent {
1080
- _subscriptions = new Subscription();
1081
- advanced = signal(false, ...(ngDevMode ? [{ debugName: "advanced" }] : []));
1895
+ valueOptions = signal(undefined, /* @ts-ignore */
1896
+ ...(ngDevMode ? [{ debugName: "valueOptions" }] : /* istanbul ignore next */ []));
1897
+ valueFieldOptions = signal(undefined, /* @ts-ignore */
1898
+ ...(ngDevMode ? [{ debugName: "valueFieldOptions" }] : /* istanbul ignore next */ []));
1899
+ advanced = signal(false, /* @ts-ignore */
1900
+ ...(ngDevMode ? [{ debugName: "advanced" }] : /* istanbul ignore next */ []));
1901
+ minControl;
1902
+ maxControl;
1082
1903
  get allowAdvanced() {
1083
1904
  return this.item()?.type === '=';
1084
1905
  }
1085
1906
  ngOnInit() {
1086
1907
  super.ngOnInit();
1087
- }
1088
- ngOnDestroy() {
1089
- if (this._subscriptions) {
1090
- this._subscriptions.unsubscribe();
1091
- }
1908
+ const valueControl = this.bindControl(null);
1909
+ this.minControl = this.bindControl('>=');
1910
+ this.maxControl = this.bindControl('<=');
1911
+ this.valueOptions.set(this.buildInputOptions(valueControl));
1912
+ this.valueFieldOptions.set(undefined);
1092
1913
  }
1093
1914
  toggleAdvanced() {
1094
1915
  this.advanced.update((val) => !val);
1095
1916
  if (this.advanced())
1096
1917
  this.value = null;
1097
1918
  }
1098
- 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", usesInheritance: true, ngImport: i0, template: "<!--<ion-row>-->\n<!-- <ion-col>-->\n<!-- <ion-label>-->\n{{ item()?.label || '' | translate }}\n<!-- </ion-label>-->\n@if (!advanced()) {\n <!-- <ion-input [(ngModel)]=\"value\" type=\"number\" step=\"1\"></ion-input>-->\n}\n<!-- </ion-col>-->\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@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 [(ngModel)]=\"minValue\" type=\"number\" step=\"1\"></ion-input>-->\n <!-- </ion-item>-->\n <!-- </ion-col>-->\n @if (minValue) {\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 [(ngModel)]=\"maxValue\" type=\"number\" step=\"1\"></ion-input>-->\n <!-- </ion-item>-->\n <!-- </ion-col>-->\n @if (maxValue) {\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" }] });
1919
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: FilterIntComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1920
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: FilterIntComponent, isStandalone: true, selector: "smart-crud-filter-int", host: { classAttribute: "smart:block smart:w-full" }, usesInheritance: true, ngImport: i0, template: `
1921
+ @if (valueOptions()) {
1922
+ <div class="smart:flex smart:w-full smart:items-end smart:gap-2">
1923
+ @if (!advanced()) {
1924
+ <smart-input-int
1925
+ class="smart:flex-1"
1926
+ [options]="valueOptions()!"
1927
+ [fieldOptions]="valueFieldOptions()"
1928
+ ></smart-input-int>
1929
+ }
1930
+
1931
+ @if (allowAdvanced) {
1932
+ <button
1933
+ type="button"
1934
+ (click)="toggleAdvanced()"
1935
+ [disabled]="hasMinValue() || hasMaxValue()"
1936
+ aria-label="settings"
1937
+ 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"
1938
+ >
1939
+
1940
+ </button>
1941
+ }
1942
+
1943
+ @if (hasValue() || hasMinValue() || hasMaxValue()) {
1944
+ <button
1945
+ type="button"
1946
+ (click)="clear()"
1947
+ aria-label="clear"
1948
+ class="smart:shrink-0 smart:rounded smart:px-2 smart:py-2 smart:text-red-600 smart:hover:bg-red-50"
1949
+ >
1950
+ ×
1951
+ </button>
1952
+ }
1953
+ </div>
1954
+
1955
+ @if ((advanced() || hasMinValue() || hasMaxValue()) && allowAdvanced) {
1956
+ <div
1957
+ class="smart:mt-2 smart:flex smart:w-full smart:items-end smart:gap-2"
1958
+ >
1959
+ <div class="smart:flex-1">
1960
+ <label
1961
+ class="smart:block smart:text-sm/6 smart:font-medium smart:text-gray-900 smart:dark:text-white"
1962
+ >
1963
+ {{ 'from' | translate }}
1964
+ </label>
1965
+ <input
1966
+ type="number"
1967
+ step="1"
1968
+ [formControl]="minControl"
1969
+ 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"
1970
+ />
1971
+ </div>
1972
+ @if (hasMinValue()) {
1973
+ <button
1974
+ type="button"
1975
+ (click)="refresh(null, '>=')"
1976
+ aria-label="clear-from"
1977
+ class="smart:shrink-0 smart:rounded smart:px-2 smart:py-2 smart:text-red-600 smart:hover:bg-red-50"
1978
+ >
1979
+ ×
1980
+ </button>
1981
+ }
1982
+
1983
+ <div class="smart:flex-1">
1984
+ <label
1985
+ class="smart:block smart:text-sm/6 smart:font-medium smart:text-gray-900 smart:dark:text-white"
1986
+ >
1987
+ {{ 'to' | translate }}
1988
+ </label>
1989
+ <input
1990
+ type="number"
1991
+ step="1"
1992
+ [formControl]="maxControl"
1993
+ 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"
1994
+ />
1995
+ </div>
1996
+ @if (hasMaxValue()) {
1997
+ <button
1998
+ type="button"
1999
+ (click)="refresh(null, '<=')"
2000
+ aria-label="clear-to"
2001
+ class="smart:shrink-0 smart:rounded smart:px-2 smart:py-2 smart:text-red-600 smart:hover:bg-red-50"
2002
+ >
2003
+ ×
2004
+ </button>
2005
+ }
2006
+ </div>
2007
+ }
2008
+ }
2009
+ `, 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]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NumberValueAccessor, selector: "input[type=number]:not([ngNoCva])[formControlName],input[type=number]:not([ngNoCva])[formControl],input[type=number]:not([ngNoCva])[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
2010
  }
1101
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FilterIntComponent, decorators: [{
2011
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: FilterIntComponent, decorators: [{
1102
2012
  type: Component,
1103
- args: [{ selector: 'smart-crud-filter-int', imports: [TranslatePipe, FormsModule], template: "<!--<ion-row>-->\n<!-- <ion-col>-->\n<!-- <ion-label>-->\n{{ item()?.label || '' | translate }}\n<!-- </ion-label>-->\n@if (!advanced()) {\n <!-- <ion-input [(ngModel)]=\"value\" type=\"number\" step=\"1\"></ion-input>-->\n}\n<!-- </ion-col>-->\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@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 [(ngModel)]=\"minValue\" type=\"number\" step=\"1\"></ion-input>-->\n <!-- </ion-item>-->\n <!-- </ion-col>-->\n @if (minValue) {\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 [(ngModel)]=\"maxValue\" type=\"number\" step=\"1\"></ion-input>-->\n <!-- </ion-item>-->\n <!-- </ion-col>-->\n @if (maxValue) {\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"] }]
2013
+ args: [{
2014
+ selector: 'smart-crud-filter-int',
2015
+ host: { class: 'smart:block smart:w-full' },
2016
+ template: `
2017
+ @if (valueOptions()) {
2018
+ <div class="smart:flex smart:w-full smart:items-end smart:gap-2">
2019
+ @if (!advanced()) {
2020
+ <smart-input-int
2021
+ class="smart:flex-1"
2022
+ [options]="valueOptions()!"
2023
+ [fieldOptions]="valueFieldOptions()"
2024
+ ></smart-input-int>
2025
+ }
2026
+
2027
+ @if (allowAdvanced) {
2028
+ <button
2029
+ type="button"
2030
+ (click)="toggleAdvanced()"
2031
+ [disabled]="hasMinValue() || hasMaxValue()"
2032
+ aria-label="settings"
2033
+ 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"
2034
+ >
2035
+
2036
+ </button>
2037
+ }
2038
+
2039
+ @if (hasValue() || hasMinValue() || hasMaxValue()) {
2040
+ <button
2041
+ type="button"
2042
+ (click)="clear()"
2043
+ aria-label="clear"
2044
+ class="smart:shrink-0 smart:rounded smart:px-2 smart:py-2 smart:text-red-600 smart:hover:bg-red-50"
2045
+ >
2046
+ ×
2047
+ </button>
2048
+ }
2049
+ </div>
2050
+
2051
+ @if ((advanced() || hasMinValue() || hasMaxValue()) && allowAdvanced) {
2052
+ <div
2053
+ class="smart:mt-2 smart:flex smart:w-full smart:items-end smart:gap-2"
2054
+ >
2055
+ <div class="smart:flex-1">
2056
+ <label
2057
+ class="smart:block smart:text-sm/6 smart:font-medium smart:text-gray-900 smart:dark:text-white"
2058
+ >
2059
+ {{ 'from' | translate }}
2060
+ </label>
2061
+ <input
2062
+ type="number"
2063
+ step="1"
2064
+ [formControl]="minControl"
2065
+ 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"
2066
+ />
2067
+ </div>
2068
+ @if (hasMinValue()) {
2069
+ <button
2070
+ type="button"
2071
+ (click)="refresh(null, '>=')"
2072
+ aria-label="clear-from"
2073
+ class="smart:shrink-0 smart:rounded smart:px-2 smart:py-2 smart:text-red-600 smart:hover:bg-red-50"
2074
+ >
2075
+ ×
2076
+ </button>
2077
+ }
2078
+
2079
+ <div class="smart:flex-1">
2080
+ <label
2081
+ class="smart:block smart:text-sm/6 smart:font-medium smart:text-gray-900 smart:dark:text-white"
2082
+ >
2083
+ {{ 'to' | translate }}
2084
+ </label>
2085
+ <input
2086
+ type="number"
2087
+ step="1"
2088
+ [formControl]="maxControl"
2089
+ 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"
2090
+ />
2091
+ </div>
2092
+ @if (hasMaxValue()) {
2093
+ <button
2094
+ type="button"
2095
+ (click)="refresh(null, '<=')"
2096
+ aria-label="clear-to"
2097
+ class="smart:shrink-0 smart:rounded smart:px-2 smart:py-2 smart:text-red-600 smart:hover:bg-red-50"
2098
+ >
2099
+ ×
2100
+ </button>
2101
+ }
2102
+ </div>
2103
+ }
2104
+ }
2105
+ `,
2106
+ imports: [InputIntComponent, ReactiveFormsModule, TranslatePipe],
2107
+ changeDetection: ChangeDetectionStrategy.OnPush,
2108
+ }]
1104
2109
  }] });
1105
2110
 
1106
2111
  class FilterRadioComponent extends BaseComponent {
1107
- 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
- <!-- <ion-row>-->
1110
- <!-- <ion-col>-->
1111
- <!-- <ion-radio-group [(ngModel)]="value">-->
1112
- <!-- <ion-item-divider class="font-light text-xl">-->
1113
- <!-- <ion-icon class="mr-6 text-2xl" slot="start" name="filter-outline"></ion-icon>-->
1114
- <!-- <ion-label>-->
1115
- {{ item()?.label || '' | translate }}
1116
- <!-- </ion-label>-->
1117
- @if (value || value === false) {
1118
- <!-- <ion-button-->
1119
- <!-- slot="end"-->
1120
- <!-- color="danger"-->
1121
- <!-- (click)="refresh(null)"-->
1122
- <!-- class="square-button m-0 text-lg h-9 w-9 p-0"-->
1123
- <!-- >-->
1124
- <!-- <ion-icon class="mr-6 text-2xl m-0 p-0" slot="icon-only" name="close-outline"></ion-icon>-->
1125
- <!-- </ion-button>-->
1126
- }
1127
- <!-- </ion-item-divider>-->
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" }] });
2112
+ inputOptions = signal(undefined, /* @ts-ignore */
2113
+ ...(ngDevMode ? [{ debugName: "inputOptions" }] : /* istanbul ignore next */ []));
2114
+ fieldOptions = signal(undefined, /* @ts-ignore */
2115
+ ...(ngDevMode ? [{ debugName: "fieldOptions" }] : /* istanbul ignore next */ []));
2116
+ ngOnInit() {
2117
+ super.ngOnInit();
2118
+ const control = this.bindControl(null);
2119
+ this.inputOptions.set(this.buildInputOptions(control, true));
2120
+ }
2121
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: FilterRadioComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
2122
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: FilterRadioComponent, isStandalone: true, selector: "smart-crud-filter-radio", host: { classAttribute: "smart:mb-5 smart:block smart:w-full" }, usesInheritance: true, ngImport: i0, template: `
2123
+ @if (inputOptions()) {
2124
+ <div class="smart:flex smart:w-full smart:items-start smart:gap-2">
2125
+ <smart-input-radio
2126
+ class="smart:flex-1"
2127
+ [options]="inputOptions()!"
2128
+ [fieldOptions]="fieldOptions()"
2129
+ ></smart-input-radio>
2130
+ @if (value || value === false) {
2131
+ <button
2132
+ type="button"
2133
+ (click)="refresh(null)"
2134
+ aria-label="clear"
2135
+ class="smart:shrink-0 smart:rounded smart:px-2 smart:py-1 smart:text-red-600 smart:hover:bg-red-50"
2136
+ >
2137
+ ×
2138
+ </button>
2139
+ }
2140
+ </div>
2141
+ }
2142
+ `, isInline: true, dependencies: [{ kind: "component", type: InputRadioComponent, selector: "smart-input-radio" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1139
2143
  }
1140
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FilterRadioComponent, decorators: [{
2144
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: FilterRadioComponent, decorators: [{
1141
2145
  type: Component,
1142
- args: [{ selector: 'smart-crud-filter-radio', template: `
1143
- <!-- <ion-row>-->
1144
- <!-- <ion-col>-->
1145
- <!-- <ion-radio-group [(ngModel)]="value">-->
1146
- <!-- <ion-item-divider class="font-light text-xl">-->
1147
- <!-- <ion-icon class="mr-6 text-2xl" slot="start" name="filter-outline"></ion-icon>-->
1148
- <!-- <ion-label>-->
1149
- {{ item()?.label || '' | translate }}
1150
- <!-- </ion-label>-->
1151
- @if (value || value === false) {
1152
- <!-- <ion-button-->
1153
- <!-- slot="end"-->
1154
- <!-- color="danger"-->
1155
- <!-- (click)="refresh(null)"-->
1156
- <!-- class="square-button m-0 text-lg h-9 w-9 p-0"-->
1157
- <!-- >-->
1158
- <!-- <ion-icon class="mr-6 text-2xl m-0 p-0" slot="icon-only" name="close-outline"></ion-icon>-->
1159
- <!-- </ion-button>-->
1160
- }
1161
- <!-- </ion-item-divider>-->
1162
-
1163
- @for (item of possibilities(); track item) {
1164
- <!-- <ion-item>-->
1165
- <!-- <ion-label>{{ item.text | translate }}</ion-label>-->
1166
- <!-- <ion-radio class="mr-10" [value]="item.id"></ion-radio>-->
1167
- <!-- </ion-item>-->
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"] }]
2146
+ args: [{
2147
+ selector: 'smart-crud-filter-radio',
2148
+ host: { class: 'smart:mb-5 smart:block smart:w-full' },
2149
+ template: `
2150
+ @if (inputOptions()) {
2151
+ <div class="smart:flex smart:w-full smart:items-start smart:gap-2">
2152
+ <smart-input-radio
2153
+ class="smart:flex-1"
2154
+ [options]="inputOptions()!"
2155
+ [fieldOptions]="fieldOptions()"
2156
+ ></smart-input-radio>
2157
+ @if (value || value === false) {
2158
+ <button
2159
+ type="button"
2160
+ (click)="refresh(null)"
2161
+ aria-label="clear"
2162
+ class="smart:shrink-0 smart:rounded smart:px-2 smart:py-1 smart:text-red-600 smart:hover:bg-red-50"
2163
+ >
2164
+ ×
2165
+ </button>
2166
+ }
2167
+ </div>
2168
+ }
2169
+ `,
2170
+ imports: [InputRadioComponent],
2171
+ changeDetection: ChangeDetectionStrategy.OnPush,
2172
+ }]
1173
2173
  }] });
1174
2174
 
1175
2175
  class FilterTextComponent extends BaseComponent {
1176
- 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
- <!-- <ion-row>-->
1179
- <!-- <ion-col>-->
1180
- <!-- <ion-label position="floating">-->
1181
- {{ item()?.label || '' | translate }}
1182
- <!-- </ion-label>-->
1183
- <!-- <ion-input [(ngModel)]="value"></ion-input>-->
1184
- <!-- </ion-col>-->
1185
- @if (value) {
1186
- <!-- <ion-col size="auto">-->
1187
- <!-- <ion-button-->
1188
- <!-- color="danger"-->
1189
- <!-- (click)="refresh(null)"-->
1190
- <!-- class="square-button m-3"-->
1191
- <!-- >-->
1192
- <!-- <ion-icon slot="icon-only" name="close-outline"></ion-icon>-->
1193
- <!-- </ion-button>-->
1194
- <!-- </ion-col>-->
1195
- }
1196
- <!-- </ion-row>-->
1197
- `, 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" }] });
2176
+ inputOptions = signal(undefined, /* @ts-ignore */
2177
+ ...(ngDevMode ? [{ debugName: "inputOptions" }] : /* istanbul ignore next */ []));
2178
+ fieldOptions = signal(undefined, /* @ts-ignore */
2179
+ ...(ngDevMode ? [{ debugName: "fieldOptions" }] : /* istanbul ignore next */ []));
2180
+ ngOnInit() {
2181
+ super.ngOnInit();
2182
+ const control = this.bindValueControl();
2183
+ this.inputOptions.set(this.buildInputOptions(control));
2184
+ }
2185
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: FilterTextComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
2186
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: FilterTextComponent, isStandalone: true, selector: "smart-crud-filter-text", host: { classAttribute: "smart:block smart:w-full" }, usesInheritance: true, ngImport: i0, template: `
2187
+ @if (inputOptions()) {
2188
+ <div class="smart:flex smart:w-full smart:items-end smart:gap-2">
2189
+ <smart-input-text
2190
+ class="smart:flex-1"
2191
+ [options]="inputOptions()!"
2192
+ [fieldOptions]="fieldOptions()"
2193
+ ></smart-input-text>
2194
+ @if (hasValue()) {
2195
+ <button
2196
+ type="button"
2197
+ (click)="refresh(null)"
2198
+ aria-label="clear"
2199
+ class="smart:shrink-0 smart:rounded smart:px-2 smart:py-2 smart:text-red-600 smart:hover:bg-red-50"
2200
+ >
2201
+ ×
2202
+ </button>
2203
+ }
2204
+ </div>
2205
+ }
2206
+ `, isInline: true, dependencies: [{ kind: "component", type: InputTextComponent, selector: "smart-input-text" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1198
2207
  }
1199
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FilterTextComponent, decorators: [{
2208
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: FilterTextComponent, decorators: [{
1200
2209
  type: Component,
1201
- args: [{ selector: 'smart-crud-filter-text', template: `
1202
- <!-- <ion-row>-->
1203
- <!-- <ion-col>-->
1204
- <!-- <ion-label position="floating">-->
1205
- {{ item()?.label || '' | translate }}
1206
- <!-- </ion-label>-->
1207
- <!-- <ion-input [(ngModel)]="value"></ion-input>-->
1208
- <!-- </ion-col>-->
1209
- @if (value) {
1210
- <!-- <ion-col size="auto">-->
1211
- <!-- <ion-button-->
1212
- <!-- color="danger"-->
1213
- <!-- (click)="refresh(null)"-->
1214
- <!-- class="square-button m-3"-->
1215
- <!-- >-->
1216
- <!-- <ion-icon slot="icon-only" name="close-outline"></ion-icon>-->
1217
- <!-- </ion-button>-->
1218
- <!-- </ion-col>-->
1219
- }
1220
- <!-- </ion-row>-->
1221
- `, imports: [TranslatePipe, FormsModule], styles: [":host{width:100%}:host .square-button{height:var(--smart-button-height)!important}\n"] }]
2210
+ args: [{
2211
+ selector: 'smart-crud-filter-text',
2212
+ host: { class: 'smart:block smart:w-full' },
2213
+ template: `
2214
+ @if (inputOptions()) {
2215
+ <div class="smart:flex smart:w-full smart:items-end smart:gap-2">
2216
+ <smart-input-text
2217
+ class="smart:flex-1"
2218
+ [options]="inputOptions()!"
2219
+ [fieldOptions]="fieldOptions()"
2220
+ ></smart-input-text>
2221
+ @if (hasValue()) {
2222
+ <button
2223
+ type="button"
2224
+ (click)="refresh(null)"
2225
+ aria-label="clear"
2226
+ class="smart:shrink-0 smart:rounded smart:px-2 smart:py-2 smart:text-red-600 smart:hover:bg-red-50"
2227
+ >
2228
+ ×
2229
+ </button>
2230
+ }
2231
+ </div>
2232
+ }
2233
+ `,
2234
+ imports: [InputTextComponent],
2235
+ changeDetection: ChangeDetectionStrategy.OnPush,
2236
+ }]
1222
2237
  }] });
1223
2238
 
1224
2239
  class FilterComponent {
1225
2240
  FieldType = FieldType;
1226
- item = input(...(ngDevMode ? [undefined, { debugName: "item" }] : []));
1227
- filter = input(...(ngDevMode ? [undefined, { debugName: "filter" }] : []));
1228
- 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: "<!--<ion-item>-->\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<!--</ion-item>-->\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" }] });
2241
+ item = input(/* @ts-ignore */
2242
+ ...(ngDevMode ? [undefined, { debugName: "item" }] : /* istanbul ignore next */ []));
2243
+ filter = input(/* @ts-ignore */
2244
+ ...(ngDevMode ? [undefined, { debugName: "filter" }] : /* istanbul ignore next */ []));
2245
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: FilterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2246
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", 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 ($safeNavigationMigration(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" }], changeDetection: i0.ChangeDetectionStrategy.Eager });
1230
2247
  }
1231
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FilterComponent, decorators: [{
2248
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: FilterComponent, decorators: [{
1232
2249
  type: Component,
1233
- args: [{ selector: 'smart-crud-filter', imports: [
2250
+ args: [{ selector: 'smart-crud-filter', changeDetection: ChangeDetectionStrategy.Eager, imports: [
1234
2251
  FilterTextComponent,
1235
2252
  FilterIntComponent,
1236
2253
  FilterFlagComponent,
@@ -1239,9 +2256,62 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImpor
1239
2256
  FilterDateTimeComponent,
1240
2257
  FilterDateWithEditComponent,
1241
2258
  FilterDateComponent,
1242
- ], template: "<!--<ion-item>-->\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<!--</ion-item>-->\n" }]
2259
+ ], template: "<div class=\"smart:py-1\">\n @switch ($safeNavigationMigration(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
2260
  }], propDecorators: { item: [{ type: i0.Input, args: [{ isSignal: true, alias: "item", required: false }] }], filter: [{ type: i0.Input, args: [{ isSignal: true, alias: "filter", required: false }] }] } });
1244
2261
 
2262
+ // Rendered by an OnPush concrete (FiltersComponent). The base exposes signals
2263
+ // (`list()`, `filter()`) and is therefore OnPush-compatible.
2264
+ class FiltersBaseComponent {
2265
+ menuService = inject(MenuService);
2266
+ config = inject((CrudConfig));
2267
+ facade = inject((CrudFacade));
2268
+ styleService = inject(StyleService);
2269
+ elementRef = inject(ElementRef);
2270
+ list;
2271
+ filter;
2272
+ /**
2273
+ * Hide menu used only from MenuService
2274
+ */
2275
+ hideMenu = input(false, /* @ts-ignore */
2276
+ ...(ngDevMode ? [{ debugName: "hideMenu" }] : /* istanbul ignore next */ []));
2277
+ async onClose() {
2278
+ await this.menuService.closeEnd();
2279
+ }
2280
+ ngOnInit() {
2281
+ this.styleService.init(this.elementRef);
2282
+ this.list = signal([], /* @ts-ignore */
2283
+ ...(ngDevMode ? [{ debugName: "list" }] : /* istanbul ignore next */ []));
2284
+ const modelFilters = getModelOptions(this.config.type)?.filters;
2285
+ this.list.set([
2286
+ ...(modelFilters
2287
+ ? modelFilters.map((item) => {
2288
+ if (!item.label) {
2289
+ item.label = 'MODEL.' + item.key;
2290
+ }
2291
+ return item;
2292
+ })
2293
+ : []),
2294
+ ...getModelFieldsWithOptions(new this.config.type())
2295
+ .filter((item) => item.options?.list?.filter)
2296
+ .map((item) => ({
2297
+ key: item.key,
2298
+ type: item.options.type === FieldType.text ||
2299
+ item.options.type === FieldType.longText
2300
+ ? '~='
2301
+ : '=',
2302
+ label: 'MODEL.' + item.key,
2303
+ fieldType: item.options.type,
2304
+ })),
2305
+ ]);
2306
+ this.filter = this.facade.filter;
2307
+ }
2308
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: FiltersBaseComponent, deps: [], target: i0.ɵɵFactoryTarget.Directive });
2309
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.8", type: FiltersBaseComponent, isStandalone: true, inputs: { hideMenu: { classPropertyName: "hideMenu", publicName: "hideMenu", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 });
2310
+ }
2311
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: FiltersBaseComponent, decorators: [{
2312
+ type: Directive
2313
+ }], propDecorators: { hideMenu: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideMenu", required: false }] }] } });
2314
+
1245
2315
  /**
1246
2316
  * This component is only to use in crud module
1247
2317
  * @requires CrudModule
@@ -1297,97 +2367,79 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImpor
1297
2367
  })
1298
2368
  body: string;
1299
2369
  */
1300
- class FiltersComponent {
1301
- menuService = inject(MenuService);
1302
- config = inject((CrudConfig));
1303
- facade = inject((CrudFacade));
1304
- styleService = inject(StyleService);
1305
- elementRef = inject(ElementRef);
1306
- list;
1307
- filter;
1308
- /**
1309
- * Hide menu used only from MenuService
1310
- */
1311
- hideMenu = input(false, ...(ngDevMode ? [{ debugName: "hideMenu" }] : []));
1312
- async onClose() {
1313
- await this.menuService.closeEnd();
1314
- }
1315
- ngOnInit() {
1316
- this.styleService.init(this.elementRef);
1317
- this.list = signal([], ...(ngDevMode ? [{ debugName: "list" }] : []));
1318
- const modelFilters = getModelOptions(this.config.type)?.filters;
1319
- this.list.set([
1320
- ...(modelFilters
1321
- ? modelFilters.map((item) => {
1322
- if (!item.label) {
1323
- item.label = 'MODEL.' + item.key;
1324
- }
1325
- return item;
1326
- })
1327
- : []),
1328
- ...getModelFieldsWithOptions(new this.config.type())
1329
- .filter((item) => item.options?.list?.filter)
1330
- .map((item) => ({
1331
- key: item.key,
1332
- type: item.options.type === FieldType.text ||
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">&nbsp;</div>
1361
- <!--</ion-content>-->
1362
- `, isInline: true, dependencies: [{ kind: "component", type: FilterComponent, selector: "smart-crud-filter", inputs: ["item", "filter"] }] });
2370
+ class FiltersComponent extends FiltersBaseComponent {
2371
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: FiltersComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
2372
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: FiltersComponent, isStandalone: true, selector: "smart-crud-filters", usesInheritance: true, ngImport: i0, template: `
2373
+ <div class="smart:flex smart:h-full smart:flex-col">
2374
+ @if (!hideMenu()) {
2375
+ <header
2376
+ class="smart:flex smart:items-center smart:justify-between smart:border-b smart:border-gray-200 smart:px-4 smart:py-3"
2377
+ >
2378
+ <h2 class="smart:text-lg smart:font-semibold smart:text-gray-900">
2379
+ {{ 'filters' | translate }}
2380
+ </h2>
2381
+ <button
2382
+ type="button"
2383
+ (click)="onClose()"
2384
+ aria-label="close"
2385
+ class="smart:rounded smart:p-1 smart:text-gray-500 smart:hover:bg-gray-100"
2386
+ >
2387
+
2388
+ </button>
2389
+ </header>
2390
+ }
2391
+ <div
2392
+ class="smart:flex-1 smart:space-y-4 smart:overflow-y-auto smart:px-4 smart:py-3"
2393
+ >
2394
+ @for (item of list(); track item.key) {
2395
+ <smart-crud-filter
2396
+ [item]="item"
2397
+ [filter]="filter()"
2398
+ ></smart-crud-filter>
2399
+ }
2400
+ </div>
2401
+ </div>
2402
+ `, 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
2403
  }
1364
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FiltersComponent, decorators: [{
2404
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: FiltersComponent, decorators: [{
1365
2405
  type: Component,
1366
2406
  args: [{
1367
2407
  selector: 'smart-crud-filters',
2408
+ changeDetection: ChangeDetectionStrategy.OnPush,
1368
2409
  template: `
1369
- <!--<ion-header [hidden]="hideMenu()">-->
1370
- <!-- <ion-toolbar>-->
1371
- <!-- <ion-buttons slot="end">-->
1372
- <!-- <ion-button (click)="onClose()">-->
1373
- <!-- <ion-icon slot="icon-only" name="close"> </ion-icon>-->
1374
- <!-- </ion-button>-->
1375
- <!-- </ion-buttons>-->
1376
- <!-- <ion-title>{{ 'filters' | translate }}</ion-title>-->
1377
- <!-- </ion-toolbar>-->
1378
- <!--</ion-header>-->
1379
- <!--<ion-content style="height: 100vh">-->
1380
- <!-- <ion-list>-->
1381
- @for (item of list(); track item) {
1382
- <smart-crud-filter [item]="item" [filter]="filter()"></smart-crud-filter>
1383
- }
1384
- <!-- </ion-list>-->
1385
- <div class="h-20">&nbsp;</div>
1386
- <!--</ion-content>-->
2410
+ <div class="smart:flex smart:h-full smart:flex-col">
2411
+ @if (!hideMenu()) {
2412
+ <header
2413
+ class="smart:flex smart:items-center smart:justify-between smart:border-b smart:border-gray-200 smart:px-4 smart:py-3"
2414
+ >
2415
+ <h2 class="smart:text-lg smart:font-semibold smart:text-gray-900">
2416
+ {{ 'filters' | translate }}
2417
+ </h2>
2418
+ <button
2419
+ type="button"
2420
+ (click)="onClose()"
2421
+ aria-label="close"
2422
+ class="smart:rounded smart:p-1 smart:text-gray-500 smart:hover:bg-gray-100"
2423
+ >
2424
+
2425
+ </button>
2426
+ </header>
2427
+ }
2428
+ <div
2429
+ class="smart:flex-1 smart:space-y-4 smart:overflow-y-auto smart:px-4 smart:py-3"
2430
+ >
2431
+ @for (item of list(); track item.key) {
2432
+ <smart-crud-filter
2433
+ [item]="item"
2434
+ [filter]="filter()"
2435
+ ></smart-crud-filter>
2436
+ }
2437
+ </div>
2438
+ </div>
1387
2439
  `,
1388
- imports: [FilterComponent],
2440
+ imports: [FilterComponent, TranslatePipe],
1389
2441
  }]
1390
- }], propDecorators: { hideMenu: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideMenu", required: false }] }] } });
2442
+ }] });
1391
2443
 
1392
2444
  class FiltersConfigComponent {
1393
2445
  facade = inject((CrudFacade));
@@ -1409,118 +2461,67 @@ class FiltersConfigComponent {
1409
2461
  this.query = computed(() => {
1410
2462
  const filter = this.facade.filter();
1411
2463
  return filter?.query?.filter((i) => !i.hidden) || [];
1412
- }, ...(ngDevMode ? [{ debugName: "query" }] : []));
2464
+ }, /* @ts-ignore */
2465
+ ...(ngDevMode ? [{ debugName: "query" }] : /* istanbul ignore next */ []));
1413
2466
  }
1414
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FiltersConfigComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1415
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: FiltersConfigComponent, isStandalone: true, selector: "smart-crud-filters-config", ngImport: i0, template: `
2467
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: FiltersConfigComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2468
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: FiltersConfigComponent, isStandalone: true, selector: "smart-crud-filters-config", ngImport: i0, template: `
1416
2469
  @let query = this.query();
1417
- @if (query && query?.length) {
1418
- <!-- <ion-toolbar>-->
1419
- @for (item of query; track item) {
1420
- <!-- <ion-chip (click)="onRemoveQuery(item)" color="medium" outline="true">-->
1421
- <!-- <ion-icon name="filter-circle-outline" color="primary"></ion-icon>-->
1422
- <!-- <ion-label>-->
1423
- {{ 'MODEL.' + item.key | translate }} {{ item.type }}
1424
- {{ item.value | translate }}
1425
- <!-- </ion-label>-->
1426
- <!-- <ion-icon name="close" color="danger"></ion-icon>-->
1427
- <!-- </ion-chip>-->
1428
- }
1429
- <!-- </ion-toolbar>-->
2470
+ @if (query && query.length) {
2471
+ <div class="smart:flex smart:flex-wrap smart:gap-2 smart:px-4 smart:py-2">
2472
+ @for (item of query; track item) {
2473
+ <button
2474
+ type="button"
2475
+ (click)="onRemoveQuery(item)"
2476
+ 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"
2477
+ [attr.aria-label]="
2478
+ ('remove' | translate) + ' ' + ('MODEL.' + item.key | translate)
2479
+ "
2480
+ >
2481
+ <span
2482
+ >{{ 'MODEL.' + item.key | translate }} {{ item.type }}
2483
+ {{ item.value | translate }}</span
2484
+ >
2485
+ <span aria-hidden="true" class="smart:text-red-600">✕</span>
2486
+ </button>
2487
+ }
2488
+ </div>
1430
2489
  }
1431
- `, isInline: true, styles: [":host ion-label{font-size:var(--small-font-size)}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }] });
2490
+ `, isInline: true, dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1432
2491
  }
1433
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FiltersConfigComponent, decorators: [{
2492
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: FiltersConfigComponent, decorators: [{
1434
2493
  type: Component,
1435
- args: [{ selector: 'smart-crud-filters-config', template: `
2494
+ args: [{
2495
+ selector: 'smart-crud-filters-config',
2496
+ template: `
1436
2497
  @let query = this.query();
1437
- @if (query && query?.length) {
1438
- <!-- <ion-toolbar>-->
1439
- @for (item of query; track item) {
1440
- <!-- <ion-chip (click)="onRemoveQuery(item)" color="medium" outline="true">-->
1441
- <!-- <ion-icon name="filter-circle-outline" color="primary"></ion-icon>-->
1442
- <!-- <ion-label>-->
1443
- {{ 'MODEL.' + item.key | translate }} {{ item.type }}
1444
- {{ item.value | translate }}
1445
- <!-- </ion-label>-->
1446
- <!-- <ion-icon name="close" color="danger"></ion-icon>-->
1447
- <!-- </ion-chip>-->
1448
- }
1449
- <!-- </ion-toolbar>-->
1450
- }
1451
- `, imports: [TranslatePipe], styles: [":host ion-label{font-size:var(--small-font-size)}\n"] }]
1452
- }] });
1453
-
1454
- /**
1455
- * @deprecated - please, use IModelPossibilitiesProvider from @smartsoft001/angular
1456
- */
1457
- class ICrudModelPossibilitiesProvider {
1458
- }
1459
- /**
1460
- * @deprecated - please, use MODEL_POSSIBILITIES_PROVIDER from @smartsoft001/angular
1461
- */
1462
- const CRUD_MODEL_POSSIBILITIES_PROVIDER = new InjectionToken('CRUD_MODEL_POSSIBILITIES_PROVIDER');
1463
-
1464
- class FormOptionsPipe {
1465
- modelPossibilitiesProvider = inject(CRUD_MODEL_POSSIBILITIES_PROVIDER);
1466
- transform(item, mode, type, uniqueProvider, inputComponents) {
1467
- if (!mode || !type)
1468
- return null;
1469
- let possibilities = {};
1470
- if (type && this.modelPossibilitiesProvider) {
1471
- possibilities = this.modelPossibilitiesProvider.get(type);
1472
- }
1473
- if (mode === 'create') {
1474
- return {
1475
- mode: 'create',
1476
- possibilities,
1477
- inputComponents,
1478
- uniqueProvider,
1479
- model: new type(),
1480
- show: true,
1481
- };
1482
- }
1483
- else {
1484
- const model = new type();
1485
- if (item) {
1486
- Object.keys(item).forEach((key) => {
1487
- model[key] = item[key];
1488
- });
1489
- }
1490
- return {
1491
- mode: mode,
1492
- uniqueProvider,
1493
- possibilities: possibilities,
1494
- inputComponents,
1495
- model: model,
1496
- show: true,
1497
- };
2498
+ @if (query && query.length) {
2499
+ <div class="smart:flex smart:flex-wrap smart:gap-2 smart:px-4 smart:py-2">
2500
+ @for (item of query; track item) {
2501
+ <button
2502
+ type="button"
2503
+ (click)="onRemoveQuery(item)"
2504
+ 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"
2505
+ [attr.aria-label]="
2506
+ ('remove' | translate) + ' ' + ('MODEL.' + item.key | translate)
2507
+ "
2508
+ >
2509
+ <span
2510
+ >{{ 'MODEL.' + item.key | translate }} {{ item.type }}
2511
+ {{ item.value | translate }}</span
2512
+ >
2513
+ <span aria-hidden="true" class="smart:text-red-600">✕</span>
2514
+ </button>
1498
2515
  }
1499
- }
1500
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FormOptionsPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
1501
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.1", ngImport: i0, type: FormOptionsPipe, isStandalone: true, name: "smartFormOptions" });
1502
- }
1503
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FormOptionsPipe, decorators: [{
1504
- type: Pipe,
1505
- args: [{
1506
- name: 'smartFormOptions',
1507
- }]
1508
- }] });
1509
-
1510
- class CrudPipesModule {
1511
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudPipesModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1512
- static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.1", ngImport: i0, type: CrudPipesModule, imports: [FormOptionsPipe], exports: [FormOptionsPipe] });
1513
- static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudPipesModule });
1514
- }
1515
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudPipesModule, decorators: [{
1516
- type: NgModule,
1517
- args: [{
1518
- exports: [FormOptionsPipe],
1519
- imports: [FormOptionsPipe],
2516
+ </div>
2517
+ }
2518
+ `,
2519
+ imports: [TranslatePipe],
2520
+ changeDetection: ChangeDetectionStrategy.OnPush,
1520
2521
  }]
1521
2522
  }] });
1522
2523
 
1523
- class MultiselectComponent {
2524
+ class MultiselectBaseComponent {
1524
2525
  facade = inject((CrudFacade));
1525
2526
  config = inject((CrudFullConfig));
1526
2527
  menuService = inject(MenuService);
@@ -1559,7 +2560,8 @@ class MultiselectComponent {
1559
2560
  });
1560
2561
  this.item = model;
1561
2562
  return list;
1562
- }, ...(ngDevMode ? [{ debugName: "list" }] : []));
2563
+ }, /* @ts-ignore */
2564
+ ...(ngDevMode ? [{ debugName: "list" }] : /* istanbul ignore next */ []));
1563
2565
  }
1564
2566
  async onClose() {
1565
2567
  await this.menuService.closeEnd();
@@ -1572,10 +2574,77 @@ class MultiselectComponent {
1572
2574
  onValidChange(valid) {
1573
2575
  this.valid = valid;
1574
2576
  }
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" }] });
2577
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: MultiselectBaseComponent, deps: [], target: i0.ɵɵFactoryTarget.Directive });
2578
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.8", type: MultiselectBaseComponent, isStandalone: true, ngImport: i0 });
2579
+ }
2580
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: MultiselectBaseComponent, decorators: [{
2581
+ type: Directive
2582
+ }], ctorParameters: () => [] });
2583
+
2584
+ class FormOptionsPipe {
2585
+ modelPossibilitiesProvider = inject(CRUD_MODEL_POSSIBILITIES_PROVIDER, { optional: true });
2586
+ transform(item, mode, type, uniqueProvider, inputComponents) {
2587
+ if (!mode || !type)
2588
+ return null;
2589
+ let possibilities = {};
2590
+ if (type && this.modelPossibilitiesProvider) {
2591
+ possibilities = this.modelPossibilitiesProvider.get(type);
2592
+ }
2593
+ if (mode === 'create') {
2594
+ return {
2595
+ mode: 'create',
2596
+ possibilities,
2597
+ inputComponents,
2598
+ uniqueProvider,
2599
+ model: new type(),
2600
+ show: true,
2601
+ };
2602
+ }
2603
+ else {
2604
+ const model = new type();
2605
+ if (item) {
2606
+ Object.keys(item).forEach((key) => {
2607
+ model[key] = item[key];
2608
+ });
2609
+ }
2610
+ return {
2611
+ mode: mode,
2612
+ uniqueProvider,
2613
+ possibilities: possibilities,
2614
+ inputComponents,
2615
+ model: model,
2616
+ show: true,
2617
+ };
2618
+ }
2619
+ }
2620
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: FormOptionsPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
2621
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "22.0.8", ngImport: i0, type: FormOptionsPipe, isStandalone: true, name: "smartFormOptions" });
2622
+ }
2623
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: FormOptionsPipe, decorators: [{
2624
+ type: Pipe,
2625
+ args: [{
2626
+ name: 'smartFormOptions',
2627
+ }]
2628
+ }] });
2629
+
2630
+ class CrudPipesModule {
2631
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: CrudPipesModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
2632
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "22.0.8", ngImport: i0, type: CrudPipesModule, imports: [FormOptionsPipe], exports: [FormOptionsPipe] });
2633
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: CrudPipesModule });
2634
+ }
2635
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: CrudPipesModule, decorators: [{
2636
+ type: NgModule,
2637
+ args: [{
2638
+ exports: [FormOptionsPipe],
2639
+ imports: [FormOptionsPipe],
2640
+ }]
2641
+ }] });
2642
+
2643
+ class MultiselectComponent extends MultiselectBaseComponent {
2644
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: MultiselectComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
2645
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", 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]=\"\n $safeNavigationMigration(config?.list?.components?.multi)\n \"\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
2646
  }
1578
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: MultiselectComponent, decorators: [{
2647
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: MultiselectComponent, decorators: [{
1579
2648
  type: Component,
1580
2649
  args: [{ selector: 'smart-crud-multiselect', imports: [
1581
2650
  TranslatePipe,
@@ -1584,8 +2653,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImpor
1584
2653
  FormOptionsPipe,
1585
2654
  FormComponent,
1586
2655
  ButtonComponent,
1587
- ], 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" }]
1588
- }], ctorParameters: () => [] });
2656
+ ], 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]=\"\n $safeNavigationMigration(config?.list?.components?.multi)\n \"\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" }]
2657
+ }] });
1589
2658
 
1590
2659
  class CrudListGroupService {
1591
2660
  facade = inject((CrudFacade));
@@ -1630,8 +2699,8 @@ class CrudListGroupService {
1630
2699
  query: newQuery,
1631
2700
  });
1632
2701
  }
1633
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudListGroupService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1634
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudListGroupService });
2702
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: CrudListGroupService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2703
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: CrudListGroupService });
1635
2704
  }
1636
2705
  __decorate([
1637
2706
  debounce(250),
@@ -1639,16 +2708,19 @@ __decorate([
1639
2708
  __metadata("design:paramtypes", []),
1640
2709
  __metadata("design:returntype", void 0)
1641
2710
  ], CrudListGroupService.prototype, "refresh", null);
1642
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudListGroupService, decorators: [{
2711
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: CrudListGroupService, decorators: [{
1643
2712
  type: Injectable
1644
2713
  }], propDecorators: { refresh: [] } });
1645
2714
 
1646
- class GroupComponent extends BaseComponent$1 {
2715
+ class GroupBaseComponent extends BaseComponent$1 {
1647
2716
  styleService = inject(StyleService);
1648
2717
  elementRef = inject(ElementRef);
1649
2718
  groupService = inject((CrudListGroupService));
1650
- groups = input(null, ...(ngDevMode ? [{ debugName: "groups" }] : []));
1651
- listOptions = input(null, ...(ngDevMode ? [{ debugName: "listOptions" }] : []));
2719
+ cd = inject(ChangeDetectorRef);
2720
+ groups = input(null, /* @ts-ignore */
2721
+ ...(ngDevMode ? [{ debugName: "groups" }] : /* istanbul ignore next */ []));
2722
+ listOptions = input(null, /* @ts-ignore */
2723
+ ...(ngDevMode ? [{ debugName: "listOptions" }] : /* istanbul ignore next */ []));
1652
2724
  change(val, item, force = false) {
1653
2725
  const groups = this.groups();
1654
2726
  if (groups) {
@@ -1659,7 +2731,16 @@ class GroupComponent extends BaseComponent$1 {
1659
2731
  });
1660
2732
  }
1661
2733
  this.groupService.change(val, item, force);
1662
- item.show = val;
2734
+ if (val) {
2735
+ setTimeout(() => {
2736
+ item.show = val;
2737
+ this.cd.detectChanges();
2738
+ });
2739
+ }
2740
+ else {
2741
+ item.show = val;
2742
+ this.cd.detectChanges();
2743
+ }
1663
2744
  }
1664
2745
  ngOnInit() {
1665
2746
  this.styleService.init(this.elementRef);
@@ -1671,292 +2752,175 @@ class GroupComponent extends BaseComponent$1 {
1671
2752
  }
1672
2753
  super.ngOnDestroy();
1673
2754
  }
1674
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: GroupComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1675
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: GroupComponent, isStandalone: true, selector: "smart-crud-group", 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, template: `
1676
- <!-- TODO: AccordionComponent moved to @smartsoft001-pro/angular (FRA-101)
1677
- @for (item of groups(); track item.key) {
1678
- <smart-accordion
1679
- [show]="item.show || false"
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
- -->
2755
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: GroupBaseComponent, deps: null, target: i0.ɵɵFactoryTarget.Directive });
2756
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.8", 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 });
2757
+ }
2758
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: GroupBaseComponent, decorators: [{
2759
+ type: Directive
2760
+ }], propDecorators: { groups: [{ type: i0.Input, args: [{ isSignal: true, alias: "groups", required: false }] }], listOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "listOptions", required: false }] }] } });
1701
2761
 
1702
- <!-- TODO: remove this template after moving to @smartsoft001-pro/angular (FRA-101) -->
2762
+ class GroupComponent extends GroupBaseComponent {
2763
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: GroupComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
2764
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: GroupComponent, isStandalone: true, selector: "smart-crud-group", usesInheritance: true, ngImport: i0, template: `
1703
2765
  @for (item of groups(); track item.key) {
1704
- <div (click)="change(!item.show, item)">
1705
- {{ item.text | translate }}
2766
+ <div class="smart:border-b smart:border-gray-200">
2767
+ <button
2768
+ type="button"
2769
+ (click)="change(!item.show, item)"
2770
+ [attr.aria-expanded]="item.show || false"
2771
+ [attr.aria-controls]="'smart-crud-group-' + item.key"
2772
+ class="smart:flex smart:w-full smart:items-center smart:justify-between smart:py-3 smart:text-left smart:text-sm"
2773
+ [class.smart:font-bold]="item.show"
2774
+ >
2775
+ <span>{{ item.text | translate }}</span>
2776
+ <span aria-hidden="true" class="smart:text-gray-500">{{
2777
+ item.show ? '▾' : '▸'
2778
+ }}</span>
2779
+ </button>
2780
+ @if (item.show) {
2781
+ <div [id]="'smart-crud-group-' + item.key" class="smart:pb-3">
2782
+ @if (!item.children && listOptions()) {
2783
+ <smart-list [options]="listOptions()!"></smart-list>
2784
+ }
2785
+ @if (item.children) {
2786
+ <div class="smart:ml-12">
2787
+ <smart-crud-group
2788
+ [groups]="item.children"
2789
+ [listOptions]="listOptions()"
2790
+ ></smart-crud-group>
2791
+ </div>
2792
+ }
2793
+ </div>
2794
+ }
1706
2795
  </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
2796
  }
1719
- `, isInline: true, dependencies: [{ kind: "component", type: GroupComponent, selector: "smart-crud-group", inputs: ["groups", "listOptions"] }, { kind: "component", type:
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" }] });
2797
+ `, 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
2798
  }
1726
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: GroupComponent, decorators: [{
2799
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: GroupComponent, decorators: [{
1727
2800
  type: Component,
1728
2801
  args: [{
1729
2802
  selector: 'smart-crud-group',
2803
+ changeDetection: ChangeDetectionStrategy.OnPush,
1730
2804
  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
2805
  @for (item of groups(); track item.key) {
1759
- <div (click)="change(!item.show, item)">
1760
- {{ item.text | translate }}
2806
+ <div class="smart:border-b smart:border-gray-200">
2807
+ <button
2808
+ type="button"
2809
+ (click)="change(!item.show, item)"
2810
+ [attr.aria-expanded]="item.show || false"
2811
+ [attr.aria-controls]="'smart-crud-group-' + item.key"
2812
+ class="smart:flex smart:w-full smart:items-center smart:justify-between smart:py-3 smart:text-left smart:text-sm"
2813
+ [class.smart:font-bold]="item.show"
2814
+ >
2815
+ <span>{{ item.text | translate }}</span>
2816
+ <span aria-hidden="true" class="smart:text-gray-500">{{
2817
+ item.show ? '▾' : '▸'
2818
+ }}</span>
2819
+ </button>
2820
+ @if (item.show) {
2821
+ <div [id]="'smart-crud-group-' + item.key" class="smart:pb-3">
2822
+ @if (!item.children && listOptions()) {
2823
+ <smart-list [options]="listOptions()!"></smart-list>
2824
+ }
2825
+ @if (item.children) {
2826
+ <div class="smart:ml-12">
2827
+ <smart-crud-group
2828
+ [groups]="item.children"
2829
+ [listOptions]="listOptions()"
2830
+ ></smart-crud-group>
2831
+ </div>
2832
+ }
2833
+ </div>
2834
+ }
1761
2835
  </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
2836
  }
1774
2837
  `,
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
- ],
1784
- }]
1785
- }], propDecorators: { groups: [{ type: i0.Input, args: [{ isSignal: true, alias: "groups", required: false }] }], listOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "listOptions", required: false }] }] } });
1786
-
1787
- class CrudListPaginationFactory {
1788
- facade = inject((CrudFacade));
1789
- async create(options) {
1790
- return {
1791
- 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
- if (this.facade.loaded()) {
1798
- setTimeout(() => {
1799
- res(options.provider.getLinks() && options.provider.getLinks().next);
1800
- });
1801
- }
1802
- const filter = options.provider.getFilter();
1803
- this.facade.read({
1804
- ...filter,
1805
- offset: (filter.offset || 0) + (filter.limit || 0),
1806
- });
1807
- });
1808
- },
1809
- loadPrevPage: () => {
1810
- if (!options.provider.getLinks() || !options.provider.getLinks().prev)
1811
- return Promise.resolve(false);
1812
- return new Promise((res) => {
1813
- const loaded = this.facade.loaded();
1814
- if (loaded) {
1815
- setTimeout(() => {
1816
- res(options.provider.getLinks() && options.provider.getLinks().prev);
1817
- });
1818
- }
1819
- const filter = options.provider.getFilter();
1820
- this.facade.read({
1821
- ...filter,
1822
- offset: (filter.offset || 0) - (filter.limit || 0),
1823
- });
1824
- });
1825
- },
1826
- page: computed(() => {
1827
- const f = this.facade.filter();
1828
- return f?.limit ? (f.offset || 0) / f.limit + 1 : 0;
1829
- }),
1830
- totalPages: computed(() => {
1831
- const filter = this.facade.filter();
1832
- const totalCount = this.facade.totalCount();
1833
- return filter?.limit && totalCount
1834
- ? Math.ceil(totalCount / filter.limit)
1835
- : 0;
1836
- }),
1837
- };
1838
- }
1839
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudListPaginationFactory, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1840
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudListPaginationFactory });
1841
- }
1842
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudListPaginationFactory, decorators: [{
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('&', '') : '';
2838
+ imports: [ListComponent$1, TranslatePipe],
2839
+ }]
2840
+ }] });
2841
+
2842
+ class CrudListPaginationFactory {
2843
+ facade = inject((CrudFacade));
2844
+ injector = inject(Injector);
2845
+ async create(options) {
2846
+ return {
2847
+ mode: options.mode,
2848
+ limit: options.limit,
2849
+ loadNextPage: () => {
2850
+ if (!options.provider.getLinks() || !options.provider.getLinks().next)
2851
+ return Promise.resolve(false);
2852
+ return new Promise((res) => {
2853
+ toObservable(this.facade.loaded, { injector: this.injector })
2854
+ .pipe(filter((l) => !!l), take(1))
2855
+ .subscribe(() => {
2856
+ setTimeout(() => {
2857
+ res(options.provider.getLinks() &&
2858
+ options.provider.getLinks().next);
2859
+ });
2860
+ });
2861
+ const currentFilter = options.provider.getFilter();
2862
+ this.facade.read({
2863
+ ...currentFilter,
2864
+ offset: (currentFilter.offset || 0) + (currentFilter.limit || 0),
2865
+ });
2866
+ });
2867
+ },
2868
+ loadPrevPage: () => {
2869
+ if (!options.provider.getLinks() || !options.provider.getLinks().prev)
2870
+ return Promise.resolve(false);
2871
+ return new Promise((res) => {
2872
+ toObservable(this.facade.loaded, { injector: this.injector })
2873
+ .pipe(filter((l) => !!l), take(1))
2874
+ .subscribe(() => {
2875
+ setTimeout(() => {
2876
+ res(options.provider.getLinks() &&
2877
+ options.provider.getLinks().prev);
2878
+ });
2879
+ });
2880
+ const currentFilter = options.provider.getFilter();
2881
+ this.facade.read({
2882
+ ...currentFilter,
2883
+ offset: (currentFilter.offset || 0) - (currentFilter.limit || 0),
2884
+ });
2885
+ });
2886
+ },
2887
+ page: computed(() => {
2888
+ const f = this.facade.filter();
2889
+ return f?.limit ? (f.offset || 0) / f.limit + 1 : 0;
2890
+ }),
2891
+ totalPages: computed(() => {
2892
+ const filter = this.facade.filter();
2893
+ const totalCount = this.facade.totalCount();
2894
+ return filter?.limit && totalCount
2895
+ ? Math.ceil(totalCount / filter.limit)
2896
+ : 0;
2897
+ }),
2898
+ };
1955
2899
  }
1956
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1957
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudService });
2900
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: CrudListPaginationFactory, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2901
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: CrudListPaginationFactory });
2902
+ }
2903
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: CrudListPaginationFactory, decorators: [{
2904
+ type: Injectable
2905
+ }] });
2906
+
2907
+ class CrudModelLabelProvider extends IModelLabelProvider {
2908
+ translateService = inject(TranslateService);
2909
+ // Delegate to an app-level provider if one exists higher in the injector tree;
2910
+ // otherwise fall back to translating 'MODEL.<key>'. (FRA-293 GAP / belt-and-suspenders.)
2911
+ parent = inject(IModelLabelProvider, {
2912
+ optional: true,
2913
+ skipSelf: true,
2914
+ });
2915
+ get(options) {
2916
+ if (this.parent)
2917
+ return this.parent.get(options);
2918
+ return signal(this.translateService.instant('MODEL.' + options.key));
2919
+ }
2920
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: CrudModelLabelProvider, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
2921
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: CrudModelLabelProvider });
1958
2922
  }
1959
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudService, decorators: [{
2923
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: CrudModelLabelProvider, decorators: [{
1960
2924
  type: Injectable
1961
2925
  }] });
1962
2926
 
@@ -1977,8 +2941,8 @@ const COMPONENTS = [
1977
2941
  GroupComponent,
1978
2942
  ];
1979
2943
  class CrudComponentsModule {
1980
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudComponentsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1981
- static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.1", ngImport: i0, type: CrudComponentsModule, imports: [ExportComponent,
2944
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: CrudComponentsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
2945
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "22.0.8", ngImport: i0, type: CrudComponentsModule, imports: [ExportComponent,
1982
2946
  FilterComponent,
1983
2947
  FilterTextComponent,
1984
2948
  FiltersConfigComponent,
@@ -2009,7 +2973,13 @@ class CrudComponentsModule {
2009
2973
  FilterIntComponent,
2010
2974
  MultiselectComponent,
2011
2975
  GroupComponent] });
2012
- static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudComponentsModule, providers: [CrudService, CrudFacade, CrudListPaginationFactory], imports: [ExportComponent,
2976
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: CrudComponentsModule, providers: [
2977
+ CrudService,
2978
+ CrudFacade,
2979
+ SocketService,
2980
+ CrudListPaginationFactory,
2981
+ { provide: IModelLabelProvider, useClass: CrudModelLabelProvider },
2982
+ ], imports: [ExportComponent,
2013
2983
  FilterComponent,
2014
2984
  FilterTextComponent,
2015
2985
  FilterDateComponent,
@@ -2026,7 +2996,7 @@ class CrudComponentsModule {
2026
2996
  CommonModule,
2027
2997
  DynamicIoModule, CrudPipesModule] });
2028
2998
  }
2029
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudComponentsModule, decorators: [{
2999
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: CrudComponentsModule, decorators: [{
2030
3000
  type: NgModule,
2031
3001
  args: [{
2032
3002
  imports: [
@@ -2038,188 +3008,31 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImpor
2038
3008
  DynamicIoModule,
2039
3009
  ],
2040
3010
  exports: [CrudPipesModule, ...COMPONENTS],
2041
- providers: [CrudService, CrudFacade, CrudListPaginationFactory],
3011
+ providers: [
3012
+ CrudService,
3013
+ CrudFacade,
3014
+ SocketService,
3015
+ CrudListPaginationFactory,
3016
+ { provide: IModelLabelProvider, useClass: CrudModelLabelProvider },
3017
+ ],
2042
3018
  }]
2043
3019
  }] });
2044
3020
 
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
3021
  class CrudItemPageBaseComponent extends BaseComponent$1 {
2214
3022
  config = inject((CrudFullConfig));
2215
3023
  facade = inject((CrudFacade));
2216
3024
  static smartType = 'crud-item-page';
2217
3025
  selected;
2218
- contentTpl = viewChild('contentTpl', ...(ngDevMode ? [{ debugName: "contentTpl" }] : []));
2219
- formComponents = viewChildren(FormComponent, ...(ngDevMode ? [{ debugName: "formComponents" }] : []));
2220
- detailsOptions = input(...(ngDevMode ? [undefined, { debugName: "detailsOptions" }] : []));
2221
- mode = input(...(ngDevMode ? [undefined, { debugName: "mode" }] : []));
2222
- uniqueProvider = input(...(ngDevMode ? [undefined, { debugName: "uniqueProvider" }] : []));
3026
+ contentTpl = viewChild('contentTpl', /* @ts-ignore */
3027
+ ...(ngDevMode ? [{ debugName: "contentTpl" }] : /* istanbul ignore next */ []));
3028
+ formComponents = viewChildren(FormComponent, /* @ts-ignore */
3029
+ ...(ngDevMode ? [{ debugName: "formComponents" }] : /* istanbul ignore next */ []));
3030
+ detailsOptions = input(/* @ts-ignore */
3031
+ ...(ngDevMode ? [undefined, { debugName: "detailsOptions" }] : /* istanbul ignore next */ []));
3032
+ mode = input(/* @ts-ignore */
3033
+ ...(ngDevMode ? [undefined, { debugName: "mode" }] : /* istanbul ignore next */ []));
3034
+ uniqueProvider = input(/* @ts-ignore */
3035
+ ...(ngDevMode ? [undefined, { debugName: "uniqueProvider" }] : /* istanbul ignore next */ []));
2223
3036
  onPartialChange = output();
2224
3037
  onChange = output();
2225
3038
  onValidChange = output();
@@ -2227,16 +3040,16 @@ class CrudItemPageBaseComponent extends BaseComponent$1 {
2227
3040
  super();
2228
3041
  this.selected = this.facade.selected;
2229
3042
  }
2230
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudItemPageBaseComponent, deps: [], target: i0.ɵɵFactoryTarget.Directive });
2231
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "21.2.1", type: CrudItemPageBaseComponent, isStandalone: true, inputs: { detailsOptions: { classPropertyName: "detailsOptions", publicName: "detailsOptions", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, uniqueProvider: { classPropertyName: "uniqueProvider", publicName: "uniqueProvider", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onPartialChange: "onPartialChange", onChange: "onChange", onValidChange: "onValidChange" }, viewQueries: [{ propertyName: "contentTpl", first: true, predicate: ["contentTpl"], descendants: true, isSignal: true }, { propertyName: "formComponents", predicate: FormComponent, descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0 });
3043
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: CrudItemPageBaseComponent, deps: [], target: i0.ɵɵFactoryTarget.Directive });
3044
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "22.0.8", type: CrudItemPageBaseComponent, isStandalone: true, inputs: { detailsOptions: { classPropertyName: "detailsOptions", publicName: "detailsOptions", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, uniqueProvider: { classPropertyName: "uniqueProvider", publicName: "uniqueProvider", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onPartialChange: "onPartialChange", onChange: "onChange", onValidChange: "onValidChange" }, viewQueries: [{ propertyName: "contentTpl", first: true, predicate: ["contentTpl"], descendants: true, isSignal: true }, { propertyName: "formComponents", predicate: FormComponent, descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0 });
2232
3045
  }
2233
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudItemPageBaseComponent, decorators: [{
3046
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: CrudItemPageBaseComponent, decorators: [{
2234
3047
  type: Directive
2235
3048
  }], ctorParameters: () => [], propDecorators: { contentTpl: [{ type: i0.ViewChild, args: ['contentTpl', { isSignal: true }] }], formComponents: [{ type: i0.ViewChildren, args: [i0.forwardRef(() => FormComponent), { isSignal: true }] }], detailsOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "detailsOptions", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], uniqueProvider: [{ type: i0.Input, args: [{ isSignal: true, alias: "uniqueProvider", required: false }] }], onPartialChange: [{ type: i0.Output, args: ["onPartialChange"] }], onChange: [{ type: i0.Output, args: ["onChange"] }], onValidChange: [{ type: i0.Output, args: ["onValidChange"] }] } });
2236
3049
 
2237
3050
  class ItemStandardComponent extends CrudItemPageBaseComponent {
2238
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ItemStandardComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
2239
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: ItemStandardComponent, isStandalone: true, selector: "smart-crud-item-standard-page", usesInheritance: true, ngImport: i0, template: `
3051
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: ItemStandardComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
3052
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: ItemStandardComponent, isStandalone: true, selector: "smart-crud-item-standard-page", usesInheritance: true, ngImport: i0, template: `
2240
3053
  @if (mode() === 'details') {
2241
3054
  @if (detailsOptions()) {
2242
3055
  <smart-details [options]="detailsOptions()"></smart-details>
@@ -2251,7 +3064,7 @@ class ItemStandardComponent extends CrudItemPageBaseComponent {
2251
3064
  selected()
2252
3065
  | smartFormOptions
2253
3066
  : mode()
2254
- : config?.type
3067
+ : $safeNavigationMigration(config?.type)
2255
3068
  : uniqueProvider()
2256
3069
  : config.inputComponents
2257
3070
  "
@@ -2262,9 +3075,9 @@ class ItemStandardComponent extends CrudItemPageBaseComponent {
2262
3075
  </ng-template>
2263
3076
 
2264
3077
  <br /><br />
2265
- `, isInline: true, styles: [""], dependencies: [{ kind: "component", type: DetailsComponent, selector: "smart-details", inputs: ["options", "class"] }, { kind: "component", type: FormComponent, selector: "smart-form", inputs: ["options", "class"], outputs: ["invokeSubmit", "valueChange", "valuePartialChange", "validChange"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: FormOptionsPipe, name: "smartFormOptions" }] });
3078
+ `, isInline: true, styles: [""], dependencies: [{ kind: "component", type: DetailsComponent, selector: "smart-details", inputs: ["options", "class"] }, { kind: "component", type: FormComponent, selector: "smart-form", inputs: ["options", "class"], outputs: ["invokeSubmit", "valueChange", "valuePartialChange", "validChange"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: FormOptionsPipe, name: "smartFormOptions" }], changeDetection: i0.ChangeDetectionStrategy.Eager });
2266
3079
  }
2267
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ItemStandardComponent, decorators: [{
3080
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: ItemStandardComponent, decorators: [{
2268
3081
  type: Component,
2269
3082
  args: [{ selector: 'smart-crud-item-standard-page', template: `
2270
3083
  @if (mode() === 'details') {
@@ -2281,7 +3094,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImpor
2281
3094
  selected()
2282
3095
  | smartFormOptions
2283
3096
  : mode()
2284
- : config?.type
3097
+ : $safeNavigationMigration(config?.type)
2285
3098
  : uniqueProvider()
2286
3099
  : config.inputComponents
2287
3100
  "
@@ -2292,7 +3105,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImpor
2292
3105
  </ng-template>
2293
3106
 
2294
3107
  <br /><br />
2295
- `, imports: [
3108
+ `, changeDetection: ChangeDetectionStrategy.Eager, imports: [
2296
3109
  DetailsComponent,
2297
3110
  FormComponent,
2298
3111
  FormOptionsPipe,
@@ -2326,10 +3139,10 @@ class PageService {
2326
3139
  val.remove = false;
2327
3140
  }
2328
3141
  }
2329
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: PageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2330
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: PageService });
3142
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: PageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
3143
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: PageService });
2331
3144
  }
2332
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: PageService, decorators: [{
3145
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: PageService, decorators: [{
2333
3146
  type: Injectable
2334
3147
  }] });
2335
3148
 
@@ -2351,9 +3164,11 @@ class ItemComponent extends CreateDynamicComponent('crud-item-page') {
2351
3164
  _mode;
2352
3165
  pageOptions = signal({
2353
3166
  title: '',
3167
+ variant: this.config.variant,
2354
3168
  showBackButton: true,
2355
3169
  hideMenuButton: true,
2356
- }, ...(ngDevMode ? [{ debugName: "pageOptions" }] : []));
3170
+ }, /* @ts-ignore */
3171
+ ...(ngDevMode ? [{ debugName: "pageOptions" }] : /* istanbul ignore next */ []));
2357
3172
  detailsOptions;
2358
3173
  id;
2359
3174
  formValue;
@@ -2362,19 +3177,24 @@ class ItemComponent extends CreateDynamicComponent('crud-item-page') {
2362
3177
  formPartialValue;
2363
3178
  uniqueProvider;
2364
3179
  set mode(val) {
2365
- this._mode = signal(val, ...(ngDevMode ? [{ debugName: "_mode" }] : []));
3180
+ this._mode = signal(val, /* @ts-ignore */
3181
+ ...(ngDevMode ? [{ debugName: "_mode" }] : /* istanbul ignore next */ []));
2366
3182
  this.refreshDynamicInstance();
2367
3183
  }
2368
3184
  get mode() {
2369
3185
  return this._mode();
2370
3186
  }
2371
3187
  selected;
2372
- standardComponents = viewChildren(ItemStandardComponent, ...(ngDevMode ? [{ debugName: "standardComponents" }] : []));
2373
- // @ViewChild(IonContent, { static: true }) content: IonContent; //TODO: rewrite when rewriting ionic
2374
- contentTpl = viewChild('contentTpl', ...(ngDevMode ? [{ debugName: "contentTpl" }] : []));
2375
- topTpl = viewChild('topTpl', ...(ngDevMode ? [{ debugName: "topTpl" }] : []));
2376
- bottomTpl = viewChild('bottomTpl', ...(ngDevMode ? [{ debugName: "bottomTpl" }] : []));
2377
- dynamicContents = viewChildren(DynamicContentDirective, ...(ngDevMode ? [{ debugName: "dynamicContents" }] : []));
3188
+ standardComponents = viewChildren(ItemStandardComponent, /* @ts-ignore */
3189
+ ...(ngDevMode ? [{ debugName: "standardComponents" }] : /* istanbul ignore next */ []));
3190
+ contentTpl = viewChild('contentTpl', /* @ts-ignore */
3191
+ ...(ngDevMode ? [{ debugName: "contentTpl" }] : /* istanbul ignore next */ []));
3192
+ topTpl = viewChild('topTpl', /* @ts-ignore */
3193
+ ...(ngDevMode ? [{ debugName: "topTpl" }] : /* istanbul ignore next */ []));
3194
+ bottomTpl = viewChild('bottomTpl', /* @ts-ignore */
3195
+ ...(ngDevMode ? [{ debugName: "bottomTpl" }] : /* istanbul ignore next */ []));
3196
+ dynamicContents = viewChildren(DynamicContentDirective, /* @ts-ignore */
3197
+ ...(ngDevMode ? [{ debugName: "dynamicContents" }] : /* istanbul ignore next */ []));
2378
3198
  subscription = new Subscription();
2379
3199
  constructor() {
2380
3200
  super();
@@ -2664,56 +3484,57 @@ class ItemComponent extends CreateDynamicComponent('crud-item-page') {
2664
3484
  });
2665
3485
  }
2666
3486
  }
2667
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2668
- 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
- <!-- <smart-page [options]="pageOptions()">-->
2670
- <div #topTpl class="text-xl py-2.5 separator"></div>
2671
- @if (template() === 'default') {
2672
- <smart-crud-item-standard-page
2673
- [detailsOptions]="detailsOptions()"
2674
- [mode]="mode"
2675
- [uniqueProvider]="uniqueProvider()"
2676
- (onPartialChange)="onPartialChange($event)"
2677
- (onChange)="onChange($event)"
2678
- (onValidChange)="onValidChange($event)"
2679
- >
2680
- <ng-container [ngTemplateOutlet]="contentTpl"></ng-container>
2681
- </smart-crud-item-standard-page>
2682
- }
2683
- <ng-template #contentTpl>
2684
- <ng-content></ng-content>
2685
- </ng-template>
2686
- <div class="dynamic-content"></div>
2687
- <div #bottomTpl class="text-xl py-2.5 separator"></div>
2688
- <!-- </smart-page>-->
2689
- `, isInline: true, dependencies: [{ kind: "component", type: /*PageComponent,*/ ItemStandardComponent, selector: "smart-crud-item-standard-page" }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] });
3487
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: ItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3488
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", 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: `
3489
+ <smart-page [options]="pageOptions()" [class]="config.cssClass || ''">
3490
+ <div #topTpl class="text-xl py-2.5 separator"></div>
3491
+ @if (template() === 'default') {
3492
+ <smart-crud-item-standard-page
3493
+ [detailsOptions]="detailsOptions()"
3494
+ [mode]="mode"
3495
+ [uniqueProvider]="uniqueProvider()"
3496
+ (onPartialChange)="onPartialChange($event)"
3497
+ (onChange)="onChange($event)"
3498
+ (onValidChange)="onValidChange($event)"
3499
+ >
3500
+ <ng-container [ngTemplateOutlet]="contentTpl"></ng-container>
3501
+ </smart-crud-item-standard-page>
3502
+ }
3503
+ <ng-template #contentTpl>
3504
+ <ng-content></ng-content>
3505
+ </ng-template>
3506
+ <div class="dynamic-content"></div>
3507
+ <div #bottomTpl class="text-xl py-2.5 separator"></div>
3508
+ </smart-page>
3509
+ `, 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"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
2690
3510
  }
2691
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ItemComponent, decorators: [{
3511
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: ItemComponent, decorators: [{
2692
3512
  type: Component,
2693
3513
  args: [{
2694
3514
  selector: 'smart-crud-item-page',
2695
- imports: [/*PageComponent,*/ ItemStandardComponent, NgTemplateOutlet],
3515
+ imports: [PageComponent, ItemStandardComponent, NgTemplateOutlet],
3516
+ changeDetection: ChangeDetectionStrategy.Eager,
2696
3517
  template: `
2697
- <!-- <smart-page [options]="pageOptions()">-->
2698
- <div #topTpl class="text-xl py-2.5 separator"></div>
2699
- @if (template() === 'default') {
2700
- <smart-crud-item-standard-page
2701
- [detailsOptions]="detailsOptions()"
2702
- [mode]="mode"
2703
- [uniqueProvider]="uniqueProvider()"
2704
- (onPartialChange)="onPartialChange($event)"
2705
- (onChange)="onChange($event)"
2706
- (onValidChange)="onValidChange($event)"
2707
- >
2708
- <ng-container [ngTemplateOutlet]="contentTpl"></ng-container>
2709
- </smart-crud-item-standard-page>
2710
- }
2711
- <ng-template #contentTpl>
2712
- <ng-content></ng-content>
2713
- </ng-template>
2714
- <div class="dynamic-content"></div>
2715
- <div #bottomTpl class="text-xl py-2.5 separator"></div>
2716
- <!-- </smart-page>-->
3518
+ <smart-page [options]="pageOptions()" [class]="config.cssClass || ''">
3519
+ <div #topTpl class="text-xl py-2.5 separator"></div>
3520
+ @if (template() === 'default') {
3521
+ <smart-crud-item-standard-page
3522
+ [detailsOptions]="detailsOptions()"
3523
+ [mode]="mode"
3524
+ [uniqueProvider]="uniqueProvider()"
3525
+ (onPartialChange)="onPartialChange($event)"
3526
+ (onChange)="onChange($event)"
3527
+ (onValidChange)="onValidChange($event)"
3528
+ >
3529
+ <ng-container [ngTemplateOutlet]="contentTpl"></ng-container>
3530
+ </smart-crud-item-standard-page>
3531
+ }
3532
+ <ng-template #contentTpl>
3533
+ <ng-content></ng-content>
3534
+ </ng-template>
3535
+ <div class="dynamic-content"></div>
3536
+ <div #bottomTpl class="text-xl py-2.5 separator"></div>
3537
+ </smart-page>
2717
3538
  `,
2718
3539
  }]
2719
3540
  }], 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 }] }] } });
@@ -2721,23 +3542,26 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImpor
2721
3542
  class CrudListPageBaseComponent extends BaseComponent$1 {
2722
3543
  config = inject((CrudFullConfig));
2723
3544
  static smartType = 'crud-list-page';
2724
- contentTpl = viewChild('contentTpl', ...(ngDevMode ? [{ debugName: "contentTpl" }] : []));
2725
- listOptions = input(...(ngDevMode ? [undefined, { debugName: "listOptions" }] : []));
2726
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudListPageBaseComponent, deps: null, target: i0.ɵɵFactoryTarget.Directive });
2727
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "21.2.1", type: CrudListPageBaseComponent, isStandalone: true, inputs: { listOptions: { classPropertyName: "listOptions", publicName: "listOptions", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "contentTpl", first: true, predicate: ["contentTpl"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0 });
3545
+ contentTpl = viewChild('contentTpl', /* @ts-ignore */
3546
+ ...(ngDevMode ? [{ debugName: "contentTpl" }] : /* istanbul ignore next */ []));
3547
+ listOptions = input(/* @ts-ignore */
3548
+ ...(ngDevMode ? [undefined, { debugName: "listOptions" }] : /* istanbul ignore next */ []));
3549
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: CrudListPageBaseComponent, deps: null, target: i0.ɵɵFactoryTarget.Directive });
3550
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "22.0.8", type: CrudListPageBaseComponent, isStandalone: true, inputs: { listOptions: { classPropertyName: "listOptions", publicName: "listOptions", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "contentTpl", first: true, predicate: ["contentTpl"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0 });
2728
3551
  }
2729
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudListPageBaseComponent, decorators: [{
3552
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: CrudListPageBaseComponent, decorators: [{
2730
3553
  type: Directive
2731
3554
  }], propDecorators: { contentTpl: [{ type: i0.ViewChild, args: ['contentTpl', { isSignal: true }] }], listOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "listOptions", required: false }] }] } });
2732
3555
 
2733
3556
  class ListStandardComponent extends CrudListPageBaseComponent {
2734
3557
  facade = inject((CrudFacade));
2735
3558
  config = inject((CrudFullConfig));
2736
- isSearch = computed(() => !!this.facade.filter()?.searchText, ...(ngDevMode ? [{ debugName: "isSearch" }] : []));
2737
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ListStandardComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
2738
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: ListStandardComponent, isStandalone: true, selector: "smart-crud-list-standard-page", providers: [CrudListGroupService], usesInheritance: true, ngImport: i0, template: `
3559
+ isSearch = computed(() => !!this.facade.filter()?.searchText, /* @ts-ignore */
3560
+ ...(ngDevMode ? [{ debugName: "isSearch" }] : /* istanbul ignore next */ []));
3561
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: ListStandardComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
3562
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: ListStandardComponent, isStandalone: true, selector: "smart-crud-list-standard-page", providers: [CrudListGroupService], usesInheritance: true, ngImport: i0, template: `
2739
3563
  <smart-crud-filters-config></smart-crud-filters-config>
2740
- @let groups = config.list?.groups;
3564
+ @let groups = $safeNavigationMigration(config.list?.groups);
2741
3565
  @if (listOptions()) {
2742
3566
  <smart-list
2743
3567
  [hidden]="groups && !isSearch()"
@@ -2750,15 +3574,15 @@ class ListStandardComponent extends CrudListPageBaseComponent {
2750
3574
  [listOptions]="listOptions() || null"
2751
3575
  ></smart-crud-group>
2752
3576
  }
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", inputs: ["groups", "listOptions"] }] });
3577
+ `, 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" }], changeDetection: i0.ChangeDetectionStrategy.Eager });
2754
3578
  }
2755
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ListStandardComponent, decorators: [{
3579
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: ListStandardComponent, decorators: [{
2756
3580
  type: Component,
2757
3581
  args: [{
2758
3582
  selector: 'smart-crud-list-standard-page',
2759
3583
  template: `
2760
3584
  <smart-crud-filters-config></smart-crud-filters-config>
2761
- @let groups = config.list?.groups;
3585
+ @let groups = $safeNavigationMigration(config.list?.groups);
2762
3586
  @if (listOptions()) {
2763
3587
  <smart-list
2764
3588
  [hidden]="groups && !isSearch()"
@@ -2773,6 +3597,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImpor
2773
3597
  }
2774
3598
  `,
2775
3599
  imports: [FiltersConfigComponent, ListComponent$1, GroupComponent],
3600
+ changeDetection: ChangeDetectionStrategy.Eager,
2776
3601
  providers: [CrudListGroupService],
2777
3602
  }]
2778
3603
  }] });
@@ -2803,10 +3628,10 @@ class CrudSearchService {
2803
3628
  setEnabled(val) {
2804
3629
  this._enabledSource.next(val);
2805
3630
  }
2806
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudSearchService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2807
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudSearchService, providedIn: 'root' });
3631
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: CrudSearchService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
3632
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: CrudSearchService, providedIn: 'root' });
2808
3633
  }
2809
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudSearchService, decorators: [{
3634
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: CrudSearchService, decorators: [{
2810
3635
  type: Injectable,
2811
3636
  args: [{
2812
3637
  providedIn: 'root',
@@ -2826,13 +3651,18 @@ class ListComponent extends CreateDynamicComponent('crud-list-page') {
2826
3651
  config = inject((CrudFullConfig));
2827
3652
  searchService = inject(CrudSearchService);
2828
3653
  _cleanMultiSelected$ = new Subject();
2829
- pageOptions = signal(null, ...(ngDevMode ? [{ debugName: "pageOptions" }] : []));
2830
- listOptions = signal(null, ...(ngDevMode ? [{ debugName: "listOptions" }] : []));
3654
+ pageOptions = signal(null, /* @ts-ignore */
3655
+ ...(ngDevMode ? [{ debugName: "pageOptions" }] : /* istanbul ignore next */ []));
3656
+ listOptions = signal(null, /* @ts-ignore */
3657
+ ...(ngDevMode ? [{ debugName: "listOptions" }] : /* istanbul ignore next */ []));
2831
3658
  links = this.facade.links;
2832
3659
  filter = this.facade.filter;
2833
- topTpl = viewChild('topTpl', ...(ngDevMode ? [{ debugName: "topTpl" }] : []));
2834
- contentTpl = viewChild('contentTpl', ...(ngDevMode ? [{ debugName: "contentTpl" }] : []));
2835
- dynamicContents = viewChildren(DynamicContentDirective, ...(ngDevMode ? [{ debugName: "dynamicContents" }] : []));
3660
+ topTpl = viewChild('topTpl', /* @ts-ignore */
3661
+ ...(ngDevMode ? [{ debugName: "topTpl" }] : /* istanbul ignore next */ []));
3662
+ contentTpl = viewChild('contentTpl', /* @ts-ignore */
3663
+ ...(ngDevMode ? [{ debugName: "contentTpl" }] : /* istanbul ignore next */ []));
3664
+ dynamicContents = viewChildren(DynamicContentDirective, /* @ts-ignore */
3665
+ ...(ngDevMode ? [{ debugName: "dynamicContents" }] : /* istanbul ignore next */ []));
2836
3666
  refreshProperties() {
2837
3667
  this.baseComponentRef.setInput('listOptions', this.listOptions());
2838
3668
  }
@@ -2843,7 +3673,7 @@ class ListComponent extends CreateDynamicComponent('crud-list-page') {
2843
3673
  if (this.config.list?.resetQuery === 'beforeInit') {
2844
3674
  newFilter = {
2845
3675
  query: this.config.baseQuery ? [...this.config.baseQuery] : [],
2846
- paginationMode: this.config.list.paginationMode,
3676
+ paginationMode: this.config.list?.paginationMode,
2847
3677
  limit: this.config.pagination
2848
3678
  ? this.config.pagination.limit
2849
3679
  : undefined,
@@ -2862,7 +3692,7 @@ class ListComponent extends CreateDynamicComponent('crud-list-page') {
2862
3692
  }
2863
3693
  else {
2864
3694
  newFilter = {
2865
- paginationMode: this.config.list.paginationMode,
3695
+ paginationMode: this.config.list?.paginationMode,
2866
3696
  limit: this.searchService.filter?.limit
2867
3697
  ? this.searchService.filter.limit
2868
3698
  : this.config.pagination
@@ -2892,6 +3722,7 @@ class ListComponent extends CreateDynamicComponent('crud-list-page') {
2892
3722
  const endButtons = this.getEndButtons();
2893
3723
  this.pageOptions.set({
2894
3724
  title: this.config.title || '',
3725
+ variant: this.config.variant,
2895
3726
  search: this.config.search
2896
3727
  ? {
2897
3728
  text: computed(() => this.filter()?.searchText ?? ''),
@@ -3008,8 +3839,8 @@ class ListComponent extends CreateDynamicComponent('crud-list-page') {
3008
3839
  }
3009
3840
  : undefined,
3010
3841
  pagination: await this.paginationFacade.create({
3011
- mode: this.config.list.paginationMode,
3012
- limit: this.config.pagination.limit,
3842
+ mode: this.config.list?.paginationMode,
3843
+ limit: this.config.pagination?.limit ?? 0,
3013
3844
  provider: {
3014
3845
  getFilter: () => {
3015
3846
  return this.filter() || {};
@@ -3122,45 +3953,46 @@ class ListComponent extends CreateDynamicComponent('crud-list-page') {
3122
3953
  }
3123
3954
  });
3124
3955
  }
3125
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ListComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
3126
- 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: `
3956
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: ListComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
3957
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", 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
3958
  @if (filter() && pageOptions()) {
3128
- <!-- <smart-page [options]="pageOptions()">-->
3129
- <div #topTpl></div>
3959
+ <smart-page [options]="pageOptions()" [class]="config.cssClass || ''">
3960
+ <div #topTpl></div>
3130
3961
 
3131
- @if (template() === 'default' && listOptions()) {
3132
- <smart-crud-list-standard-page [listOptions]="listOptions()">
3133
- <ng-container [ngTemplateOutlet]="contentTpl"></ng-container>
3134
- </smart-crud-list-standard-page>
3135
- }
3136
- <ng-template #contentTpl>
3137
- <ng-content></ng-content>
3138
- </ng-template>
3139
- <div class="dynamic-content"></div>
3140
- <!-- </smart-page>-->
3962
+ @if (template() === 'default' && listOptions()) {
3963
+ <smart-crud-list-standard-page [listOptions]="listOptions()">
3964
+ <ng-container [ngTemplateOutlet]="contentTpl"></ng-container>
3965
+ </smart-crud-list-standard-page>
3966
+ }
3967
+ <ng-template #contentTpl>
3968
+ <ng-content></ng-content>
3969
+ </ng-template>
3970
+ <div class="dynamic-content"></div>
3971
+ </smart-page>
3141
3972
  }
3142
- `, isInline: true, dependencies: [{ kind: "component", type: ListStandardComponent, selector: "smart-crud-list-standard-page" }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] });
3973
+ `, 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"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
3143
3974
  }
3144
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ListComponent, decorators: [{
3975
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: ListComponent, decorators: [{
3145
3976
  type: Component,
3146
3977
  args: [{
3147
3978
  selector: 'smart-crud-list-page',
3148
- imports: [ListStandardComponent, NgTemplateOutlet],
3979
+ imports: [PageComponent, ListStandardComponent, NgTemplateOutlet],
3980
+ changeDetection: ChangeDetectionStrategy.Eager,
3149
3981
  template: `
3150
3982
  @if (filter() && pageOptions()) {
3151
- <!-- <smart-page [options]="pageOptions()">-->
3152
- <div #topTpl></div>
3983
+ <smart-page [options]="pageOptions()" [class]="config.cssClass || ''">
3984
+ <div #topTpl></div>
3153
3985
 
3154
- @if (template() === 'default' && listOptions()) {
3155
- <smart-crud-list-standard-page [listOptions]="listOptions()">
3156
- <ng-container [ngTemplateOutlet]="contentTpl"></ng-container>
3157
- </smart-crud-list-standard-page>
3158
- }
3159
- <ng-template #contentTpl>
3160
- <ng-content></ng-content>
3161
- </ng-template>
3162
- <div class="dynamic-content"></div>
3163
- <!-- </smart-page>-->
3986
+ @if (template() === 'default' && listOptions()) {
3987
+ <smart-crud-list-standard-page [listOptions]="listOptions()">
3988
+ <ng-container [ngTemplateOutlet]="contentTpl"></ng-container>
3989
+ </smart-crud-list-standard-page>
3990
+ }
3991
+ <ng-template #contentTpl>
3992
+ <ng-content></ng-content>
3993
+ </ng-template>
3994
+ <div class="dynamic-content"></div>
3995
+ </smart-page>
3164
3996
  }
3165
3997
  `,
3166
3998
  }]
@@ -3179,8 +4011,8 @@ class CrudFullModule {
3179
4011
  : getReducer(config.entity));
3180
4012
  effects.init();
3181
4013
  }
3182
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudFullModule, deps: [{ token: CrudConfig }, { token: CrudEffects }], target: i0.ɵɵFactoryTarget.NgModule });
3183
- static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.1", ngImport: i0, type: CrudFullModule, imports: [ItemComponent,
4014
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: CrudFullModule, deps: [{ token: CrudConfig }, { token: CrudEffects }], target: i0.ɵɵFactoryTarget.NgModule });
4015
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "22.0.8", ngImport: i0, type: CrudFullModule, imports: [ItemComponent,
3184
4016
  ListComponent,
3185
4017
  ListStandardComponent,
3186
4018
  ItemStandardComponent, SharedModule,
@@ -3190,7 +4022,7 @@ class CrudFullModule {
3190
4022
  ListComponent,
3191
4023
  ListStandardComponent,
3192
4024
  ItemStandardComponent, CrudComponentsModule] });
3193
- static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudFullModule, providers: [
4025
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: CrudFullModule, providers: [
3194
4026
  CrudService,
3195
4027
  CrudListGroupService,
3196
4028
  PageService,
@@ -3208,7 +4040,7 @@ class CrudFullModule {
3208
4040
  CommonModule,
3209
4041
  CrudComponentsModule, CrudComponentsModule] });
3210
4042
  }
3211
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudFullModule, decorators: [{
4043
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: CrudFullModule, decorators: [{
3212
4044
  type: NgModule,
3213
4045
  args: [{
3214
4046
  imports: [
@@ -3243,26 +4075,28 @@ class CrudCoreModule {
3243
4075
  : getReducer(config.entity));
3244
4076
  effects.init();
3245
4077
  }
3246
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudCoreModule, deps: [{ token: CrudConfig }, { token: CrudEffects }], target: i0.ɵɵFactoryTarget.NgModule });
3247
- static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.1", ngImport: i0, type: CrudCoreModule, imports: [SharedModule,
4078
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: CrudCoreModule, deps: [{ token: CrudConfig }, { token: CrudEffects }], target: i0.ɵɵFactoryTarget.NgModule });
4079
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "22.0.8", ngImport: i0, type: CrudCoreModule, imports: [SharedModule,
3248
4080
  CrudPipesModule,
3249
4081
  FormsModule,
3250
4082
  CommonModule,
3251
4083
  CrudComponentsModule], exports: [CrudComponentsModule] });
3252
- static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudCoreModule, providers: [
4084
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: CrudCoreModule, providers: [
3253
4085
  CrudService,
3254
4086
  CrudListGroupService,
3255
4087
  CrudEffects,
3256
4088
  PageService,
3257
4089
  CrudFacade,
4090
+ SocketService,
3258
4091
  CrudListPaginationFactory,
4092
+ { provide: IModelLabelProvider, useClass: CrudModelLabelProvider },
3259
4093
  ], imports: [SharedModule,
3260
4094
  CrudPipesModule,
3261
4095
  FormsModule,
3262
4096
  CommonModule,
3263
4097
  CrudComponentsModule, CrudComponentsModule] });
3264
4098
  }
3265
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudCoreModule, decorators: [{
4099
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: CrudCoreModule, decorators: [{
3266
4100
  type: NgModule,
3267
4101
  args: [{
3268
4102
  imports: [
@@ -3279,7 +4113,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImpor
3279
4113
  CrudEffects,
3280
4114
  PageService,
3281
4115
  CrudFacade,
4116
+ SocketService,
3282
4117
  CrudListPaginationFactory,
4118
+ { provide: IModelLabelProvider, useClass: CrudModelLabelProvider },
3283
4119
  ],
3284
4120
  }]
3285
4121
  }], ctorParameters: () => [{ type: CrudConfig }, { type: CrudEffects }] });
@@ -3294,6 +4130,9 @@ class CrudModule {
3294
4130
  provide: FILE_SERVICE_CONFIG,
3295
4131
  useValue: { apiUrl: options.config.apiUrl },
3296
4132
  },
4133
+ ...(options.socket
4134
+ ? [SocketService]
4135
+ : [{ provide: SocketService, useClass: NotSocketService }]),
3297
4136
  ],
3298
4137
  };
3299
4138
  }
@@ -3303,9 +4142,9 @@ class CrudModule {
3303
4142
  : getReducer(config.entity));
3304
4143
  effects.init();
3305
4144
  }
3306
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudModule, deps: [{ token: CrudConfig }, { token: CrudEffects }], target: i0.ɵɵFactoryTarget.NgModule });
3307
- static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.1", ngImport: i0, type: CrudModule });
3308
- static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudModule, providers: [
4145
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: CrudModule, deps: [{ token: CrudConfig }, { token: CrudEffects }], target: i0.ɵɵFactoryTarget.NgModule });
4146
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "22.0.8", ngImport: i0, type: CrudModule });
4147
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: CrudModule, providers: [
3309
4148
  CrudService,
3310
4149
  CrudListGroupService,
3311
4150
  CrudEffects,
@@ -3314,7 +4153,7 @@ class CrudModule {
3314
4153
  CrudListPaginationFactory,
3315
4154
  ] });
3316
4155
  }
3317
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CrudModule, decorators: [{
4156
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: CrudModule, decorators: [{
3318
4157
  type: NgModule,
3319
4158
  args: [{
3320
4159
  providers: [
@@ -3332,5 +4171,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImpor
3332
4171
  * Generated bundle index. Do not edit.
3333
4172
  */
3334
4173
 
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 };
4174
+ 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
4175
  //# sourceMappingURL=smartsoft001-crud-shell-angular.mjs.map