@solidev/data 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +27 -0
- package/README.md +40 -44
- package/fesm2022/solidev-data-mdedit.mjs +668 -0
- package/fesm2022/solidev-data-mdedit.mjs.map +1 -0
- package/fesm2022/solidev-data-richedit.mjs +1119 -36
- package/fesm2022/solidev-data-richedit.mjs.map +1 -1
- package/fesm2022/solidev-data.mjs +832 -721
- package/fesm2022/solidev-data.mjs.map +1 -1
- package/package.json +20 -2
- package/types/solidev-data-mdedit.d.ts +277 -0
- package/types/solidev-data-richedit.d.ts +283 -9
- package/types/solidev-data.d.ts +832 -781
|
@@ -1,23 +1,22 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { InjectionToken,
|
|
2
|
+
import { InjectionToken, inject, TransferState, PLATFORM_ID, makeStateKey, Injectable, input, ViewChild, Component, signal, model, DestroyRef, Pipe, LOCALE_ID, DEFAULT_CURRENCY_CODE, output, NgZone, effect, untracked, EventEmitter, ElementRef, Directive, NgModule, ApplicationRef } from '@angular/core';
|
|
3
3
|
import { __decorate } from 'tslib';
|
|
4
|
-
import * as i1$
|
|
4
|
+
import * as i1$2 from '@angular/forms';
|
|
5
5
|
import { FormControl, Validators, FormGroup, ReactiveFormsModule, UntypedFormControl, NG_VALUE_ACCESSOR, UntypedFormGroup } from '@angular/forms';
|
|
6
6
|
import { throwError, ReplaySubject, share, combineLatest, of, BehaviorSubject, takeUntil, NEVER, Subject, debounceTime, distinctUntilChanged, firstValueFrom, isObservable, timer, Observable, merge } from 'rxjs';
|
|
7
7
|
import { tap, switchMap, map, catchError, filter, take, throttleTime, mergeMap, finalize, first } from 'rxjs/operators';
|
|
8
|
+
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
|
|
8
9
|
import { isPlatformServer, AsyncPipe, NgTemplateOutlet, formatNumber, getCurrencySymbol, formatCurrency, DatePipe } from '@angular/common';
|
|
9
|
-
import * as i1 from '@angular/common/http';
|
|
10
|
-
import { HttpErrorResponse } from '@angular/common/http';
|
|
11
10
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
12
|
-
import * as i1
|
|
11
|
+
import * as i1 from '@angular/cdk/drag-drop';
|
|
13
12
|
import { DragDropModule, CDK_DRAG_CONFIG } from '@angular/cdk/drag-drop';
|
|
14
|
-
import * as i1$
|
|
13
|
+
import * as i1$1 from '@ng-bootstrap/ng-bootstrap';
|
|
15
14
|
import { NgbOffcanvas, NgbOffcanvasModule, NgbDropdownModule, NgbTypeaheadModule, NgbPaginationModule } from '@ng-bootstrap/ng-bootstrap';
|
|
16
15
|
import { CdkScrollableModule } from '@angular/cdk/scrolling';
|
|
17
16
|
import { jwtDecode } from 'jwt-decode';
|
|
18
|
-
import * as i1$
|
|
17
|
+
import * as i1$3 from '@angular/router';
|
|
19
18
|
import { Router, ActivatedRoute, NavigationEnd, RouterModule } from '@angular/router';
|
|
20
|
-
import
|
|
19
|
+
import { SwUpdate } from '@angular/service-worker';
|
|
21
20
|
|
|
22
21
|
/**
|
|
23
22
|
* Base URL of the REST API every {@link Collection} builds its endpoints on.
|
|
@@ -37,7 +36,7 @@ import * as i1$5 from '@angular/service-worker';
|
|
|
37
36
|
* // https://api.example.com/v1/path/to/things
|
|
38
37
|
* ```
|
|
39
38
|
*/
|
|
40
|
-
const DATA_API_URL = new InjectionToken(
|
|
39
|
+
const DATA_API_URL = new InjectionToken('data.api.url');
|
|
41
40
|
/**
|
|
42
41
|
* Time window, in milliseconds, during which {@link DataBackend} may answer GET
|
|
43
42
|
* requests from Angular's `TransferState` instead of hitting the network.
|
|
@@ -59,7 +58,7 @@ const DATA_API_URL = new InjectionToken("data.api.url");
|
|
|
59
58
|
* providers: [{ provide: DATA_MAX_TRANSFERSTATE_TIME, useValue: 10000 }]
|
|
60
59
|
* ```
|
|
61
60
|
*/
|
|
62
|
-
const DATA_MAX_TRANSFERSTATE_TIME = new InjectionToken(
|
|
61
|
+
const DATA_MAX_TRANSFERSTATE_TIME = new InjectionToken('data.max.transfer.state');
|
|
63
62
|
/**
|
|
64
63
|
* Bootstrap 5 flavour of {@link DataDisplayConfig}, and the fallback used when no
|
|
65
64
|
* {@link DATA_DISPLAY_CONFIG} is provided.
|
|
@@ -69,22 +68,22 @@ const DATA_MAX_TRANSFERSTATE_TIME = new InjectionToken("data.max.transfer.state"
|
|
|
69
68
|
*/
|
|
70
69
|
const BootstrapDataDisplayConfig = {
|
|
71
70
|
dispEdit: {
|
|
72
|
-
defaultMode:
|
|
71
|
+
defaultMode: 'dd',
|
|
73
72
|
inputClasses: {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
73
|
+
'input.text': 'form-control',
|
|
74
|
+
'input.email': 'form-control',
|
|
75
|
+
'input.datetime': 'form-control',
|
|
76
|
+
'input.date': 'form-control',
|
|
77
|
+
'input.number': 'form-control',
|
|
78
|
+
'input.decimal': 'form-control',
|
|
79
|
+
'input.checkbox': 'form-control',
|
|
80
|
+
'input.password': 'form-control',
|
|
81
|
+
textarea: 'form-control',
|
|
82
|
+
quill: '',
|
|
83
|
+
fkselect: 'form-control',
|
|
84
|
+
select: 'form-select',
|
|
86
85
|
},
|
|
87
|
-
}
|
|
86
|
+
},
|
|
88
87
|
};
|
|
89
88
|
/**
|
|
90
89
|
* Styling contract for the generated display/edit widgets.
|
|
@@ -107,7 +106,51 @@ const BootstrapDataDisplayConfig = {
|
|
|
107
106
|
* }]
|
|
108
107
|
* ```
|
|
109
108
|
*/
|
|
110
|
-
const DATA_DISPLAY_CONFIG = new InjectionToken(
|
|
109
|
+
const DATA_DISPLAY_CONFIG = new InjectionToken('data.display.config');
|
|
110
|
+
|
|
111
|
+
// Deliberately dependency-free: `fields/base.ts` needs this, and `data-model.ts`
|
|
112
|
+
// imports from `fields/base.ts` -- putting it in either would close a cycle.
|
|
113
|
+
/**
|
|
114
|
+
* A model seen as the untyped property bag it also is.
|
|
115
|
+
*
|
|
116
|
+
* Fields are declared by decorators and reached by name at runtime — `dispedit`
|
|
117
|
+
* reads `<field>_details`, filters read `filter.field` — so the data layer
|
|
118
|
+
* constantly indexes models with a string the compiler cannot resolve. This is
|
|
119
|
+
* the one sanctioned way to do it: it yields `unknown`, so the value has to be
|
|
120
|
+
* narrowed where it is used instead of silently becoming `any` and disabling
|
|
121
|
+
* type-checking for the rest of the expression.
|
|
122
|
+
*
|
|
123
|
+
* ```ts
|
|
124
|
+
* const details = fieldValues(model)[`${field}_details`] as R[] | undefined;
|
|
125
|
+
* fieldValues(model)[field] = event.id;
|
|
126
|
+
* ```
|
|
127
|
+
*
|
|
128
|
+
* @param target model (or any object) to index by field name
|
|
129
|
+
*/
|
|
130
|
+
function fieldValues(target) {
|
|
131
|
+
return target;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Renders an unknown value as display text.
|
|
135
|
+
*
|
|
136
|
+
* `String(value)` is not enough here: values read through {@link fieldValues}
|
|
137
|
+
* can be objects, and `String({})` yields `[object Object]`. Nullish becomes an
|
|
138
|
+
* empty string, objects are JSON-encoded, everything else goes through
|
|
139
|
+
* `String`.
|
|
140
|
+
*
|
|
141
|
+
* @param value value read off a model, a form or a payload
|
|
142
|
+
*/
|
|
143
|
+
function asText(value) {
|
|
144
|
+
if (value === null || value === undefined) {
|
|
145
|
+
return '';
|
|
146
|
+
}
|
|
147
|
+
if (typeof value === 'object') {
|
|
148
|
+
return JSON.stringify(value);
|
|
149
|
+
}
|
|
150
|
+
// Objects were handled above; what is left stringifies meaningfully.
|
|
151
|
+
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
|
152
|
+
return String(value);
|
|
153
|
+
}
|
|
111
154
|
|
|
112
155
|
/**
|
|
113
156
|
* Symbol under which every field's metadata is stored, directly on the model
|
|
@@ -115,6 +158,13 @@ const DATA_DISPLAY_CONFIG = new InjectionToken("data.display.config");
|
|
|
115
158
|
* `reflect-metadata`: a plain `Map` hung off this Symbol is the whole store.
|
|
116
159
|
*/
|
|
117
160
|
const PROPERTY_METADATA_KEY = Symbol('ngxDataMetadata');
|
|
161
|
+
/**
|
|
162
|
+
* The metadata store hung off a prototype under {@link PROPERTY_METADATA_KEY}.
|
|
163
|
+
* A symbol key, so this cannot go through `fieldValues()`.
|
|
164
|
+
*/
|
|
165
|
+
function metadataStore(target) {
|
|
166
|
+
return target;
|
|
167
|
+
}
|
|
118
168
|
/**
|
|
119
169
|
* Returns the metadata map owned by `target`, creating it on first use.
|
|
120
170
|
*
|
|
@@ -124,8 +174,10 @@ const PROPERTY_METADATA_KEY = Symbol('ngxDataMetadata');
|
|
|
124
174
|
*/
|
|
125
175
|
function getOrCreateFieldsMap(target) {
|
|
126
176
|
if (!Object.prototype.hasOwnProperty.call(target, PROPERTY_METADATA_KEY)) {
|
|
127
|
-
const inherited = target[PROPERTY_METADATA_KEY];
|
|
128
|
-
const map = inherited
|
|
177
|
+
const inherited = metadataStore(target)[PROPERTY_METADATA_KEY];
|
|
178
|
+
const map = inherited
|
|
179
|
+
? new Map(inherited)
|
|
180
|
+
: new Map();
|
|
129
181
|
Object.defineProperty(target, PROPERTY_METADATA_KEY, {
|
|
130
182
|
value: map,
|
|
131
183
|
enumerable: false,
|
|
@@ -134,7 +186,7 @@ function getOrCreateFieldsMap(target) {
|
|
|
134
186
|
});
|
|
135
187
|
return map;
|
|
136
188
|
}
|
|
137
|
-
return target[PROPERTY_METADATA_KEY];
|
|
189
|
+
return metadataStore(target)[PROPERTY_METADATA_KEY];
|
|
138
190
|
}
|
|
139
191
|
/**
|
|
140
192
|
* Reads the field metadata declared on a model, accepting either the class
|
|
@@ -145,7 +197,7 @@ function getOrCreateFieldsMap(target) {
|
|
|
145
197
|
*/
|
|
146
198
|
function getFieldsMetadata(target) {
|
|
147
199
|
const proto = typeof target === 'function' ? target.prototype : target;
|
|
148
|
-
return proto[PROPERTY_METADATA_KEY];
|
|
200
|
+
return metadataStore(proto)[PROPERTY_METADATA_KEY];
|
|
149
201
|
}
|
|
150
202
|
/**
|
|
151
203
|
* Runtime behaviour of a single field: one manager instance is built per
|
|
@@ -243,7 +295,7 @@ class BaseFieldManager {
|
|
|
243
295
|
* @param instance model whose value seeds the control
|
|
244
296
|
*/
|
|
245
297
|
formControl(instance) {
|
|
246
|
-
return new FormControl(instance[this.fname] || this.getDefaultValue(), this.validators);
|
|
298
|
+
return new FormControl(fieldValues(instance)[this.fname] || this.getDefaultValue(), this.validators);
|
|
247
299
|
}
|
|
248
300
|
/**
|
|
249
301
|
* Converts a raw JSON value coming from the API into the model value.
|
|
@@ -270,10 +322,10 @@ class BaseFieldManager {
|
|
|
270
322
|
* interpolation.
|
|
271
323
|
*
|
|
272
324
|
* @param data value to render
|
|
273
|
-
* @param
|
|
325
|
+
* @param _format reserved; ignored by the base implementation
|
|
274
326
|
*/
|
|
275
|
-
toString(data,
|
|
276
|
-
return
|
|
327
|
+
toString(data, _format = 'default') {
|
|
328
|
+
return String(data);
|
|
277
329
|
}
|
|
278
330
|
/**
|
|
279
331
|
* Public accessor for this field's default value, invoking the
|
|
@@ -293,6 +345,7 @@ class BaseFieldManager {
|
|
|
293
345
|
getValidators() {
|
|
294
346
|
const v = [];
|
|
295
347
|
if (this.required) {
|
|
348
|
+
// eslint-disable-next-line @typescript-eslint/unbound-method -- Validators.* are static and `this`-free
|
|
296
349
|
v.push(Validators.required);
|
|
297
350
|
}
|
|
298
351
|
return v;
|
|
@@ -320,11 +373,6 @@ class BaseFieldManager {
|
|
|
320
373
|
return this.defaultValue;
|
|
321
374
|
}
|
|
322
375
|
}
|
|
323
|
-
/**
|
|
324
|
-
* Lists a target's own string and symbol keys. Used to copy decorator options
|
|
325
|
-
* verbatim into the stored metadata.
|
|
326
|
-
*/
|
|
327
|
-
const ownKeys = (target) => Object.getOwnPropertyNames(target).concat(Object.getOwnPropertySymbols(target));
|
|
328
376
|
/**
|
|
329
377
|
* The factory behind every field decorator in the library — `charField`,
|
|
330
378
|
* `foreignKeyField` and the rest are all one-line calls to it. Reach for it
|
|
@@ -349,25 +397,25 @@ function genericDataField(meta, type, manager) {
|
|
|
349
397
|
return (target, propertyKey) => {
|
|
350
398
|
// Utilisation du store symbolisé au lieu de Reflect
|
|
351
399
|
const allMetadata = getOrCreateFieldsMap(target);
|
|
352
|
-
const cname = `${target.constructor.__name}`;
|
|
400
|
+
const cname = `${String(target.constructor.__name)}`;
|
|
353
401
|
if ((cname === `undefined` || cname === '') && type !== 'primaryField') {
|
|
354
|
-
throw Error(`Decorator ${type} allowed only on classes with static __name
|
|
402
|
+
throw Error(`Decorator ${type} allowed only on classes with static __name ` +
|
|
403
|
+
`field : "${cname}" found on field "${String(propertyKey)}"`);
|
|
355
404
|
}
|
|
356
405
|
const pk = `${cname}__${String(propertyKey)}`;
|
|
357
406
|
let cm = allMetadata.get(pk);
|
|
358
407
|
/* istanbul ignore if */
|
|
359
408
|
if (cm) {
|
|
360
|
-
throw Error(`Field ${pk} already defined = ${cm}`);
|
|
361
|
-
}
|
|
362
|
-
cm = {};
|
|
363
|
-
for (const key of ownKeys(meta)) {
|
|
364
|
-
cm[key] = meta[key];
|
|
409
|
+
throw Error(`Field ${pk} already defined = ${JSON.stringify(cm)}`);
|
|
365
410
|
}
|
|
411
|
+
cm = { ...meta };
|
|
366
412
|
if (meta.name === undefined) {
|
|
367
413
|
cm.name = `${String(propertyKey)}`;
|
|
368
414
|
}
|
|
369
415
|
cm.type = type;
|
|
370
416
|
cm.self = pk;
|
|
417
|
+
// `cm` is `meta` plus the resolved name/type/self, so it is an `MD`;
|
|
418
|
+
// the copy above loses that on the way through the stored shape.
|
|
371
419
|
cm.manager = new manager(cm);
|
|
372
420
|
allMetadata.set(pk, cm);
|
|
373
421
|
// Plus besoin de Reflect.defineMetadata : la Map est déjà stockée sur le prototype.
|
|
@@ -396,6 +444,13 @@ class PrimaryFieldManager extends BaseFieldManager {
|
|
|
396
444
|
*/
|
|
397
445
|
const primaryField = (updates = {}) => genericDataField(updates, 'primaryField', PrimaryFieldManager);
|
|
398
446
|
|
|
447
|
+
/**
|
|
448
|
+
* The class a prototype-chain level belongs to, as the library sees it: a
|
|
449
|
+
* constructor carrying the `__name` every model declares.
|
|
450
|
+
*/
|
|
451
|
+
function modelClassOf(level) {
|
|
452
|
+
return level.constructor;
|
|
453
|
+
}
|
|
399
454
|
/**
|
|
400
455
|
* Base class for every model in the library: a plain class whose fields are
|
|
401
456
|
* declared with field decorators, which turns it into something the rest of the
|
|
@@ -481,6 +536,13 @@ class DataModel {
|
|
|
481
536
|
* @throws Error if no field metadata is reachable at all, which should be
|
|
482
537
|
* impossible since `DataModel` itself declares `id`.
|
|
483
538
|
*/
|
|
539
|
+
// `Collection<any>`, deliberately. `DataModelType<T>` is `new (_coll?:
|
|
540
|
+
// Collection<T>) => T`, so a subclass has to stay assignable to a
|
|
541
|
+
// constructor taking a collection *of itself*. Naming any concrete type
|
|
542
|
+
// here -- `Collection<DataModel>` included -- closes that loop and makes
|
|
543
|
+
// `new Collection(backend, url, MyModel)` stop type-checking for every
|
|
544
|
+
// model in every consumer.
|
|
545
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
484
546
|
constructor(_coll) {
|
|
485
547
|
this._coll = _coll;
|
|
486
548
|
// Remplacement de Reflect.getMetadata par getFieldsMetadata
|
|
@@ -493,13 +555,13 @@ class DataModel {
|
|
|
493
555
|
// Get all fields from current class and its parents
|
|
494
556
|
const fields = new Map();
|
|
495
557
|
let parent = Object.getPrototypeOf(this);
|
|
496
|
-
while (parent.
|
|
558
|
+
while (modelClassOf(parent).name !== 'Object') {
|
|
497
559
|
for (const f of md.keys()) {
|
|
498
560
|
const fieldName = f.split('__')[1];
|
|
499
561
|
if (fields.has(fieldName)) {
|
|
500
562
|
continue;
|
|
501
563
|
}
|
|
502
|
-
if (f.indexOf(parent.
|
|
564
|
+
if (f.indexOf(`${modelClassOf(parent).__name}__`) === 0) {
|
|
503
565
|
fields.set(fieldName, md.get(f));
|
|
504
566
|
}
|
|
505
567
|
}
|
|
@@ -515,9 +577,24 @@ class DataModel {
|
|
|
515
577
|
* with "Missing collection". The getter casts away the optional, so it lies
|
|
516
578
|
* about `undefined` on an unattached model.
|
|
517
579
|
*/
|
|
580
|
+
// `Collection<any>`, deliberately. `DataModelType<T>` is `new (_coll?:
|
|
581
|
+
// Collection<T>) => T`, so a subclass has to stay assignable to a
|
|
582
|
+
// constructor taking a collection *of itself*. Naming any concrete type
|
|
583
|
+
// here -- `Collection<DataModel>` included -- closes that loop and makes
|
|
584
|
+
// `new Collection(backend, url, MyModel)` stop type-checking for every
|
|
585
|
+
// model in every consumer.
|
|
586
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
518
587
|
get _collection() {
|
|
588
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
519
589
|
return this._coll;
|
|
520
590
|
}
|
|
591
|
+
// `Collection<any>`, deliberately. `DataModelType<T>` is `new (_coll?:
|
|
592
|
+
// Collection<T>) => T`, so a subclass has to stay assignable to a
|
|
593
|
+
// constructor taking a collection *of itself*. Naming any concrete type
|
|
594
|
+
// here -- `Collection<DataModel>` included -- closes that loop and makes
|
|
595
|
+
// `new Collection(backend, url, MyModel)` stop type-checking for every
|
|
596
|
+
// model in every consumer.
|
|
597
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
521
598
|
set _collection(coll) {
|
|
522
599
|
this._coll = coll;
|
|
523
600
|
}
|
|
@@ -571,7 +648,7 @@ class DataModel {
|
|
|
571
648
|
let haveError = false;
|
|
572
649
|
for (const f of this.FN) {
|
|
573
650
|
if (!partial || (partial && Object.keys(data).indexOf(f) !== -1)) {
|
|
574
|
-
const ferr = this.setFV(f, this.FM(f).fromJson(data[f]), check);
|
|
651
|
+
const ferr = this.setFV(f, this.FM(f).fromJson(fieldValues(data)[f]), check);
|
|
575
652
|
if (ferr !== null) {
|
|
576
653
|
errors[f] = ferr;
|
|
577
654
|
haveError = true;
|
|
@@ -597,6 +674,10 @@ class DataModel {
|
|
|
597
674
|
*
|
|
598
675
|
* @param fields single field name or list of names to restrict the output to
|
|
599
676
|
*/
|
|
677
|
+
// The payload's shape is the model's own, which only the caller knows.
|
|
678
|
+
// Narrowing this to `Record<string, unknown>` would force every consumer
|
|
679
|
+
// reading a property off the result to cast, so it stays `any` until a major.
|
|
680
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
600
681
|
toJson(fields) {
|
|
601
682
|
if (fields && !Array.isArray(fields)) {
|
|
602
683
|
fields = [fields];
|
|
@@ -638,6 +719,9 @@ class DataModel {
|
|
|
638
719
|
* @returns an observable of the **raw response body**, not of this model, even
|
|
639
720
|
* when `update` is `true`
|
|
640
721
|
*/
|
|
722
|
+
// `T` is unused, but it comes first in the parameter list: removing it
|
|
723
|
+
// would silently change what `action<A, B>()` call sites mean.
|
|
724
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
641
725
|
action(method, name, { body = undefined, update = false, updatePartial = true, updateCheck = false,
|
|
642
726
|
// updateRaise = false,
|
|
643
727
|
params = {}, headers = {}, } = {}) {
|
|
@@ -676,9 +760,12 @@ class DataModel {
|
|
|
676
760
|
*/
|
|
677
761
|
FM(field) {
|
|
678
762
|
if (this.F.has(field)) {
|
|
763
|
+
// The map is keyed by name and holds managers of every field type; only
|
|
764
|
+
// the caller knows which one this field is.
|
|
679
765
|
return this.F.get(field).manager;
|
|
680
766
|
}
|
|
681
|
-
throw new Error(`${field} not found in ${
|
|
767
|
+
throw new Error(`${field} not found in [${[...this.FN].join(',')}] ` +
|
|
768
|
+
`on model ${this.constructor.__name}`);
|
|
682
769
|
}
|
|
683
770
|
/**
|
|
684
771
|
* Reads a field's value by name, for code that only knows the field at runtime.
|
|
@@ -690,7 +777,7 @@ class DataModel {
|
|
|
690
777
|
* @param field field name
|
|
691
778
|
*/
|
|
692
779
|
FV(field) {
|
|
693
|
-
return this[field];
|
|
780
|
+
return fieldValues(this)[field];
|
|
694
781
|
}
|
|
695
782
|
/**
|
|
696
783
|
* Writes a field's value by name, optionally validating it first.
|
|
@@ -723,7 +810,7 @@ class DataModel {
|
|
|
723
810
|
}
|
|
724
811
|
}
|
|
725
812
|
}
|
|
726
|
-
this[field] = value;
|
|
813
|
+
fieldValues(this)[field] = value;
|
|
727
814
|
return null;
|
|
728
815
|
}
|
|
729
816
|
FC(field) {
|
|
@@ -787,7 +874,9 @@ class DataModel {
|
|
|
787
874
|
updateModel: true,
|
|
788
875
|
}) {
|
|
789
876
|
if (this._coll) {
|
|
790
|
-
return this._coll.update(this, fields, {
|
|
877
|
+
return this._coll.update(this, fields, {
|
|
878
|
+
updateModel,
|
|
879
|
+
});
|
|
791
880
|
}
|
|
792
881
|
return throwError(() => new Error('Missing collection'));
|
|
793
882
|
}
|
|
@@ -942,11 +1031,7 @@ class Queryset {
|
|
|
942
1031
|
* receives the most recent page rather than waiting for the next `get()`.
|
|
943
1032
|
*/
|
|
944
1033
|
results = this._results.asObservable().pipe(share());
|
|
945
|
-
_full = combineLatest([
|
|
946
|
-
this.results,
|
|
947
|
-
this.loading,
|
|
948
|
-
this.meta,
|
|
949
|
-
]);
|
|
1034
|
+
_full = combineLatest([this.results, this.loading, this.meta]);
|
|
950
1035
|
/**
|
|
951
1036
|
* The three streams combined into `[results, loading, meta]`, for templates
|
|
952
1037
|
* that would otherwise need three `async` pipes.
|
|
@@ -1045,10 +1130,10 @@ class Queryset {
|
|
|
1045
1130
|
* request, so a paginator must call {@link get} afterwards.
|
|
1046
1131
|
*
|
|
1047
1132
|
* @param page 1-based page number
|
|
1048
|
-
* @param
|
|
1133
|
+
* @param _fragment currently ignored; reserved for the URL-syncing behaviour
|
|
1049
1134
|
* that is commented out in the implementation
|
|
1050
1135
|
*/
|
|
1051
|
-
setPage(page = 1,
|
|
1136
|
+
setPage(page = 1, _fragment) {
|
|
1052
1137
|
if (page !== this.page) {
|
|
1053
1138
|
this.page = page;
|
|
1054
1139
|
// if (this.options.router) {
|
|
@@ -1324,13 +1409,11 @@ class Collection {
|
|
|
1324
1409
|
* either way.
|
|
1325
1410
|
*/
|
|
1326
1411
|
save(model, { updateModel = true } = {}) {
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
: this.backend.post.bind(this.backend);
|
|
1330
|
-
let url = model.id !== undefined ? this.getUrl(model.id) : this.getUrl();
|
|
1412
|
+
const saveMethod = model.id !== undefined ? this.backend.patch.bind(this.backend) : this.backend.post.bind(this.backend);
|
|
1413
|
+
const url = model.id !== undefined ? this.getUrl(model.id) : this.getUrl();
|
|
1331
1414
|
return saveMethod(this, url, { body: model.toJson() }).pipe(map((res) => this.fromJson(res)), tap((res) => {
|
|
1332
1415
|
if (updateModel) {
|
|
1333
|
-
model.fromJson(res);
|
|
1416
|
+
model.fromJson(fieldValues(res));
|
|
1334
1417
|
}
|
|
1335
1418
|
}));
|
|
1336
1419
|
}
|
|
@@ -1347,13 +1430,11 @@ class Collection {
|
|
|
1347
1430
|
* @param updateModel feed the server's response back into `model` (defaults to `true`)
|
|
1348
1431
|
*/
|
|
1349
1432
|
update(model, fields = [], { updateModel = true } = {}) {
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
: this.backend.post.bind(this.backend);
|
|
1353
|
-
let url = model.id !== undefined ? this.getUrl(model.id) : this.getUrl();
|
|
1433
|
+
const saveMethod = model.id !== undefined ? this.backend.patch.bind(this.backend) : this.backend.post.bind(this.backend);
|
|
1434
|
+
const url = model.id !== undefined ? this.getUrl(model.id) : this.getUrl();
|
|
1354
1435
|
return saveMethod(this, url, { body: model.toJson(fields) }).pipe(map((res) => this.fromJson(res)), tap((res) => {
|
|
1355
1436
|
if (updateModel) {
|
|
1356
|
-
model.fromJson(res);
|
|
1437
|
+
model.fromJson(fieldValues(res));
|
|
1357
1438
|
}
|
|
1358
1439
|
}));
|
|
1359
1440
|
}
|
|
@@ -1418,7 +1499,7 @@ class Collection {
|
|
|
1418
1499
|
* {@link action}
|
|
1419
1500
|
* @param headers extra headers
|
|
1420
1501
|
*/
|
|
1421
|
-
raw({ method = 'GET', prefix = '', suffix = '', params = {}, body = {}, headers = {}, } = {}) {
|
|
1502
|
+
raw({ method = 'GET', prefix = '', suffix = '', params = {}, body: _body = {}, headers = {}, } = {}) {
|
|
1422
1503
|
return this.backend.action(this, method, this.getUrl(null, { suffix, prefix }), {
|
|
1423
1504
|
params,
|
|
1424
1505
|
headers,
|
|
@@ -1438,7 +1519,10 @@ class Collection {
|
|
|
1438
1519
|
* forward it to the backend
|
|
1439
1520
|
* @param headers extra headers
|
|
1440
1521
|
*/
|
|
1441
|
-
|
|
1522
|
+
// `RT` is unused -- `blob()` always resolves to a Blob -- but dropping it
|
|
1523
|
+
// would be a breaking change for callers writing `blob<T>()`.
|
|
1524
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
1525
|
+
blob({ method = 'GET', prefix = '', suffix = '', params = {}, body: _body = {}, headers = {}, } = {}) {
|
|
1442
1526
|
return this.backend.blob(this, method, this.getUrl(null, { suffix, prefix }), {
|
|
1443
1527
|
params,
|
|
1444
1528
|
headers,
|
|
@@ -1486,6 +1570,11 @@ class Collection {
|
|
|
1486
1570
|
* only when {@link DATA_MAX_TRANSFERSTATE_TIME} is provided and greater than
|
|
1487
1571
|
* zero — see {@link _cachedGet} for the exact conditions.
|
|
1488
1572
|
*
|
|
1573
|
+
* Dependencies are resolved with `inject()`, so a subclass declares **no
|
|
1574
|
+
* constructor**. To point one at a different API — a second backend alongside
|
|
1575
|
+
* the main one — override {@link apiUrl} rather than passing a URL through
|
|
1576
|
+
* `super()`; {@link maxTransferstateTime} is overridable the same way.
|
|
1577
|
+
*
|
|
1489
1578
|
* @example
|
|
1490
1579
|
* ```ts
|
|
1491
1580
|
* @Injectable({ providedIn: 'root' })
|
|
@@ -1495,6 +1584,13 @@ class Collection {
|
|
|
1495
1584
|
* }
|
|
1496
1585
|
* }
|
|
1497
1586
|
*
|
|
1587
|
+
* @Injectable({ providedIn: 'root' })
|
|
1588
|
+
* export class SupportBackend extends DataBackend {
|
|
1589
|
+
* public override get apiUrl(): string {
|
|
1590
|
+
* return 'https://support.example.com/api';
|
|
1591
|
+
* }
|
|
1592
|
+
* }
|
|
1593
|
+
*
|
|
1498
1594
|
* providers: [
|
|
1499
1595
|
* { provide: DATA_API_URL, useValue: 'https://api.example.com' },
|
|
1500
1596
|
* { provide: DataBackend, useClass: AuthBackend },
|
|
@@ -1502,32 +1598,17 @@ class Collection {
|
|
|
1502
1598
|
* ```
|
|
1503
1599
|
*/
|
|
1504
1600
|
class DataBackend {
|
|
1505
|
-
_http;
|
|
1506
|
-
_transferState;
|
|
1507
|
-
_platform;
|
|
1508
|
-
_apiUrl;
|
|
1509
|
-
_maxTransferstateTime;
|
|
1510
1601
|
/**
|
|
1511
1602
|
* Instantiation timestamp, used as the origin of the TransferState validity
|
|
1512
1603
|
* window (see {@link _cachedGet}) — the window runs from backend creation, not
|
|
1513
1604
|
* from each entry's insertion.
|
|
1514
1605
|
*/
|
|
1515
1606
|
_created = new Date();
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
* @param _maxTransferstateTime TransferState window in ms; optional, `0`
|
|
1522
|
-
* (the default) disables caching entirely
|
|
1523
|
-
*/
|
|
1524
|
-
constructor(_http, _transferState, _platform, _apiUrl, _maxTransferstateTime = 0) {
|
|
1525
|
-
this._http = _http;
|
|
1526
|
-
this._transferState = _transferState;
|
|
1527
|
-
this._platform = _platform;
|
|
1528
|
-
this._apiUrl = _apiUrl;
|
|
1529
|
-
this._maxTransferstateTime = _maxTransferstateTime;
|
|
1530
|
-
}
|
|
1607
|
+
_http = inject(HttpClient);
|
|
1608
|
+
_transferState = inject(TransferState);
|
|
1609
|
+
_platform = inject(PLATFORM_ID);
|
|
1610
|
+
_apiUrl = inject(DATA_API_URL);
|
|
1611
|
+
_maxTransferstateTime = inject(DATA_MAX_TRANSFERSTATE_TIME, { optional: true }) ?? 0;
|
|
1531
1612
|
/**
|
|
1532
1613
|
* Base URL every collection URL is built on, as provided via
|
|
1533
1614
|
* {@link DATA_API_URL}. Read by `Collection.getUrl()`; exposed so custom
|
|
@@ -1536,6 +1617,13 @@ class DataBackend {
|
|
|
1536
1617
|
get apiUrl() {
|
|
1537
1618
|
return this._apiUrl;
|
|
1538
1619
|
}
|
|
1620
|
+
/**
|
|
1621
|
+
* TransferState window in ms, from {@link DATA_MAX_TRANSFERSTATE_TIME}; `0`
|
|
1622
|
+
* disables the cache. Overridable for the same reason as {@link apiUrl}.
|
|
1623
|
+
*/
|
|
1624
|
+
get maxTransferstateTime() {
|
|
1625
|
+
return this._maxTransferstateTime;
|
|
1626
|
+
}
|
|
1539
1627
|
/**
|
|
1540
1628
|
* Issues an arbitrary request and returns the parsed JSON body.
|
|
1541
1629
|
*
|
|
@@ -1562,7 +1650,6 @@ class DataBackend {
|
|
|
1562
1650
|
});
|
|
1563
1651
|
}
|
|
1564
1652
|
else {
|
|
1565
|
-
// @ts-ignore
|
|
1566
1653
|
return this._http.request(method, url, {
|
|
1567
1654
|
body,
|
|
1568
1655
|
params,
|
|
@@ -1586,7 +1673,6 @@ class DataBackend {
|
|
|
1586
1673
|
* @return an observable of the response as a `Blob`
|
|
1587
1674
|
*/
|
|
1588
1675
|
blob(collection, method, url, { body = undefined, params = {}, headers = {} } = {}) {
|
|
1589
|
-
// @ts-ignore
|
|
1590
1676
|
return this._http.request(method, url, {
|
|
1591
1677
|
body,
|
|
1592
1678
|
params,
|
|
@@ -1687,16 +1773,13 @@ class DataBackend {
|
|
|
1687
1773
|
const cur_headers = this.headers(headers);
|
|
1688
1774
|
const key = makeStateKey(url + '|' + JSON.stringify(params) + '|' + JSON.stringify(cur_headers));
|
|
1689
1775
|
if (collection.useTransferState &&
|
|
1690
|
-
this.
|
|
1776
|
+
this.maxTransferstateTime > 0 &&
|
|
1691
1777
|
this._transferState.hasKey(key) &&
|
|
1692
|
-
new Date().getTime() - this._created.getTime() <
|
|
1693
|
-
this._maxTransferstateTime) {
|
|
1778
|
+
new Date().getTime() - this._created.getTime() < this.maxTransferstateTime) {
|
|
1694
1779
|
return of(this._transferState.get(key, null));
|
|
1695
1780
|
}
|
|
1696
1781
|
return this._http.get(url, { headers: cur_headers, params }).pipe(tap((result) => {
|
|
1697
|
-
if (collection.useTransferState &&
|
|
1698
|
-
isPlatformServer(this._platform) &&
|
|
1699
|
-
this._maxTransferstateTime > 0) {
|
|
1782
|
+
if (collection.useTransferState && isPlatformServer(this._platform) && this.maxTransferstateTime > 0) {
|
|
1700
1783
|
this._transferState.set(key, result);
|
|
1701
1784
|
}
|
|
1702
1785
|
}));
|
|
@@ -1751,26 +1834,15 @@ class DataBackend {
|
|
|
1751
1834
|
headers(headers) {
|
|
1752
1835
|
return Object.assign({}, headers);
|
|
1753
1836
|
}
|
|
1754
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
1755
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.
|
|
1837
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: DataBackend, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1838
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: DataBackend, providedIn: 'root' });
|
|
1756
1839
|
}
|
|
1757
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
1840
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: DataBackend, decorators: [{
|
|
1758
1841
|
type: Injectable,
|
|
1759
1842
|
args: [{
|
|
1760
1843
|
providedIn: 'root',
|
|
1761
1844
|
}]
|
|
1762
|
-
}]
|
|
1763
|
-
type: Inject,
|
|
1764
|
-
args: [PLATFORM_ID]
|
|
1765
|
-
}] }, { type: undefined, decorators: [{
|
|
1766
|
-
type: Inject,
|
|
1767
|
-
args: [DATA_API_URL]
|
|
1768
|
-
}] }, { type: undefined, decorators: [{
|
|
1769
|
-
type: Optional
|
|
1770
|
-
}, {
|
|
1771
|
-
type: Inject,
|
|
1772
|
-
args: [DATA_MAX_TRANSFERSTATE_TIME]
|
|
1773
|
-
}] }] });
|
|
1845
|
+
}] });
|
|
1774
1846
|
|
|
1775
1847
|
/**
|
|
1776
1848
|
* The columns of a list: which exist, which are shown, and in what order.
|
|
@@ -1822,9 +1894,7 @@ class ModelListFields {
|
|
|
1822
1894
|
priority: c.priority || 0,
|
|
1823
1895
|
});
|
|
1824
1896
|
}
|
|
1825
|
-
tmp.sort((b, a) => a.priority === b.priority
|
|
1826
|
-
? b.position - a.position
|
|
1827
|
-
: a.priority - b.priority);
|
|
1897
|
+
tmp.sort((b, a) => (a.priority === b.priority ? b.position - a.position : a.priority - b.priority));
|
|
1828
1898
|
let pos = 0;
|
|
1829
1899
|
for (const i of tmp) {
|
|
1830
1900
|
i.position = pos;
|
|
@@ -1856,7 +1926,6 @@ class ModelListFields {
|
|
|
1856
1926
|
}
|
|
1857
1927
|
}
|
|
1858
1928
|
// Set defaults
|
|
1859
|
-
let out = [];
|
|
1860
1929
|
for (const fe of defaults) {
|
|
1861
1930
|
for (const f of tmp) {
|
|
1862
1931
|
if (f.name === fe) {
|
|
@@ -1895,7 +1964,7 @@ class ModelListFields {
|
|
|
1895
1964
|
const disabled = filtered.filter((f) => !f.enabled);
|
|
1896
1965
|
let ei = 0;
|
|
1897
1966
|
let di = 0;
|
|
1898
|
-
|
|
1967
|
+
while (ei + di < filtered.length) {
|
|
1899
1968
|
if (enabled[ei] && disabled[di]) {
|
|
1900
1969
|
if (enabled[ei].priority > disabled[di].priority) {
|
|
1901
1970
|
ordered.push(enabled[ei]);
|
|
@@ -2155,7 +2224,7 @@ class ModelListPaginator {
|
|
|
2155
2224
|
getPage() {
|
|
2156
2225
|
return this._page;
|
|
2157
2226
|
}
|
|
2158
|
-
_updateOutput(
|
|
2227
|
+
_updateOutput(_from = '') {
|
|
2159
2228
|
this._output.next({ page: this._page, page_size: this._page_size });
|
|
2160
2229
|
}
|
|
2161
2230
|
}
|
|
@@ -2280,7 +2349,7 @@ class ModelListSorter {
|
|
|
2280
2349
|
return -1;
|
|
2281
2350
|
}
|
|
2282
2351
|
_updateOutput(_from = '') {
|
|
2283
|
-
|
|
2352
|
+
const out = [];
|
|
2284
2353
|
for (const v of this._values) {
|
|
2285
2354
|
out.push(`${v.direction === 'asc' ? '' : '-'}${v.field}`);
|
|
2286
2355
|
}
|
|
@@ -2445,9 +2514,7 @@ class ModelListFilter {
|
|
|
2445
2514
|
if (this.multi && this._mvalue.size > 0) {
|
|
2446
2515
|
filter[this.field] = this.getMultiValue();
|
|
2447
2516
|
}
|
|
2448
|
-
else if (!this.multi &&
|
|
2449
|
-
this._value !== undefined &&
|
|
2450
|
-
this._value !== null) {
|
|
2517
|
+
else if (!this.multi && this._value !== undefined && this._value !== null) {
|
|
2451
2518
|
filter[this.field] = this.getValue();
|
|
2452
2519
|
}
|
|
2453
2520
|
}
|
|
@@ -2522,7 +2589,7 @@ class ModelListFilter {
|
|
|
2522
2589
|
* meaningful for single-valued filters.
|
|
2523
2590
|
*/
|
|
2524
2591
|
getValue() {
|
|
2525
|
-
return
|
|
2592
|
+
return String(this._value?.value);
|
|
2526
2593
|
}
|
|
2527
2594
|
/**
|
|
2528
2595
|
* The current single value with its description, or `null` when unset. Used
|
|
@@ -2533,26 +2600,26 @@ class ModelListFilter {
|
|
|
2533
2600
|
return this._value;
|
|
2534
2601
|
}
|
|
2535
2602
|
mtoggle(value, desc, notify = true) {
|
|
2536
|
-
if (this._mvalue.has(
|
|
2537
|
-
this._mvalue.delete(
|
|
2603
|
+
if (this._mvalue.has(String(value))) {
|
|
2604
|
+
this._mvalue.delete(String(value));
|
|
2538
2605
|
}
|
|
2539
2606
|
else {
|
|
2540
|
-
this._mvalue.set(
|
|
2607
|
+
this._mvalue.set(String(value), desc);
|
|
2541
2608
|
}
|
|
2542
2609
|
this.notify(notify);
|
|
2543
2610
|
return true;
|
|
2544
2611
|
}
|
|
2545
2612
|
mset(value, desc, notify = true) {
|
|
2546
|
-
if (!this._mvalue.has(
|
|
2547
|
-
this._mvalue.set(
|
|
2613
|
+
if (!this._mvalue.has(String(value))) {
|
|
2614
|
+
this._mvalue.set(String(value), desc);
|
|
2548
2615
|
this.notify(notify);
|
|
2549
2616
|
return true;
|
|
2550
2617
|
}
|
|
2551
2618
|
return false;
|
|
2552
2619
|
}
|
|
2553
2620
|
munset(value, desc, notify = true) {
|
|
2554
|
-
if (this._mvalue.has(
|
|
2555
|
-
this._mvalue.delete(
|
|
2621
|
+
if (this._mvalue.has(String(value))) {
|
|
2622
|
+
this._mvalue.delete(String(value));
|
|
2556
2623
|
this.notify(notify);
|
|
2557
2624
|
return true;
|
|
2558
2625
|
}
|
|
@@ -2801,9 +2868,7 @@ class ModelListFilters {
|
|
|
2801
2868
|
this._output$.next(filter);
|
|
2802
2869
|
this._enabled$.next(this._enabled);
|
|
2803
2870
|
this._available$.next(this._available);
|
|
2804
|
-
this._groups$.next(this._groups
|
|
2805
|
-
.filter((g) => g.allowed && g.enabled)
|
|
2806
|
-
.sort((a, b) => a.position - b.position));
|
|
2871
|
+
this._groups$.next(this._groups.filter((g) => g.allowed && g.enabled).sort((a, b) => a.position - b.position));
|
|
2807
2872
|
}
|
|
2808
2873
|
}
|
|
2809
2874
|
|
|
@@ -2825,6 +2890,8 @@ class ModelListFilters {
|
|
|
2825
2890
|
* instance while the interceptor and `ModelListService` hold another, so `logout$`
|
|
2826
2891
|
* would never reach the list cache and stale data would survive a logout.
|
|
2827
2892
|
*/
|
|
2893
|
+
// The app that provides this token specialises all three parameters; naming
|
|
2894
|
+
// them here would force every consumer to cast on injection.
|
|
2828
2895
|
const DATA_AUTH_SERVICE = new InjectionToken('data.auth.service');
|
|
2829
2896
|
/**
|
|
2830
2897
|
* Extra origins, beyond `DATA_API_URL`, whose requests should carry the auth token.
|
|
@@ -2877,16 +2944,13 @@ class AuthInterceptor {
|
|
|
2877
2944
|
return next.handle(req);
|
|
2878
2945
|
}
|
|
2879
2946
|
// If the request is refresh or login url, skip auth
|
|
2880
|
-
if (req.url.startsWith(this._auth.refreshUrl) ||
|
|
2881
|
-
req.url.startsWith(this._auth.loginUrl)) {
|
|
2947
|
+
if (req.url.startsWith(this._auth.refreshUrl) || req.url.startsWith(this._auth.loginUrl)) {
|
|
2882
2948
|
return next.handle(req);
|
|
2883
2949
|
}
|
|
2884
2950
|
// If the request is not for the api, and not for one of the urls specified in the
|
|
2885
2951
|
// DATA_AUTH_URLS injection token, skip auth
|
|
2886
2952
|
if (!req.url.startsWith(this._apiUrl) &&
|
|
2887
|
-
!(this._urls &&
|
|
2888
|
-
this._urls.length > 0 &&
|
|
2889
|
-
this._urls.some((url) => req.url.startsWith(url)))) {
|
|
2953
|
+
!(this._urls && this._urls.length > 0 && this._urls.some((url) => req.url.startsWith(url)))) {
|
|
2890
2954
|
return next.handle(req);
|
|
2891
2955
|
}
|
|
2892
2956
|
if (!this._auth.isAnonymous) {
|
|
@@ -2931,15 +2995,13 @@ class AuthInterceptor {
|
|
|
2931
2995
|
}
|
|
2932
2996
|
}
|
|
2933
2997
|
_addToken(request, token) {
|
|
2934
|
-
const headers = request.headers
|
|
2935
|
-
.delete('Authorization')
|
|
2936
|
-
.append('Authorization', `Bearer ${token}`);
|
|
2998
|
+
const headers = request.headers.delete('Authorization').append('Authorization', `Bearer ${token}`);
|
|
2937
2999
|
return request.clone({ headers });
|
|
2938
3000
|
}
|
|
2939
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
2940
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.
|
|
3001
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: AuthInterceptor, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
3002
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: AuthInterceptor, providedIn: 'root' });
|
|
2941
3003
|
}
|
|
2942
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
3004
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: AuthInterceptor, decorators: [{
|
|
2943
3005
|
type: Injectable,
|
|
2944
3006
|
args: [{
|
|
2945
3007
|
providedIn: 'root',
|
|
@@ -3142,11 +3204,12 @@ class ModelList {
|
|
|
3142
3204
|
class ModelListService {
|
|
3143
3205
|
/** Kept lists, keyed by `name` only. See the class doc for what that implies. */
|
|
3144
3206
|
_instances = new Map();
|
|
3207
|
+
// Only `logout$` is used here, so the three type parameters are irrelevant.
|
|
3208
|
+
// See DATA_AUTH_SERVICE: the app specialises the three parameters.
|
|
3209
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
3145
3210
|
_auth = inject(DATA_AUTH_SERVICE);
|
|
3146
3211
|
constructor() {
|
|
3147
|
-
this._auth.logout
|
|
3148
|
-
.pipe(takeUntilDestroyed())
|
|
3149
|
-
.subscribe(() => this.reset());
|
|
3212
|
+
this._auth.logout$.pipe(takeUntilDestroyed()).subscribe(() => this.reset());
|
|
3150
3213
|
}
|
|
3151
3214
|
/**
|
|
3152
3215
|
* Tear down and forget every cached list.
|
|
@@ -3221,6 +3284,7 @@ class ModelListService {
|
|
|
3221
3284
|
}
|
|
3222
3285
|
}
|
|
3223
3286
|
else {
|
|
3287
|
+
// The cache is keyed by name and holds lists of every model type.
|
|
3224
3288
|
ml = this._instances.get(name);
|
|
3225
3289
|
}
|
|
3226
3290
|
if (!ml.started) {
|
|
@@ -3240,10 +3304,10 @@ class ModelListService {
|
|
|
3240
3304
|
}
|
|
3241
3305
|
return ml;
|
|
3242
3306
|
}
|
|
3243
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
3244
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.
|
|
3307
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ModelListService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
3308
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ModelListService, providedIn: 'root' });
|
|
3245
3309
|
}
|
|
3246
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
3310
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ModelListService, decorators: [{
|
|
3247
3311
|
type: Injectable,
|
|
3248
3312
|
args: [{
|
|
3249
3313
|
providedIn: 'root',
|
|
@@ -3295,7 +3359,7 @@ class ModelListFieldsSelectorComponent {
|
|
|
3295
3359
|
else {
|
|
3296
3360
|
pos -= 1;
|
|
3297
3361
|
}
|
|
3298
|
-
this.list().fields.setPosition($event.item.data, pos);
|
|
3362
|
+
this.list().fields.setPosition(String($event.item.data), pos);
|
|
3299
3363
|
}
|
|
3300
3364
|
/** Show or hide column `f`, depending on its current state. */
|
|
3301
3365
|
toggle(f) {
|
|
@@ -3306,17 +3370,12 @@ class ModelListFieldsSelectorComponent {
|
|
|
3306
3370
|
this.list().fields.enable(f.name);
|
|
3307
3371
|
}
|
|
3308
3372
|
}
|
|
3309
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
3310
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.
|
|
3373
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ModelListFieldsSelectorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3374
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: ModelListFieldsSelectorComponent, isStandalone: true, selector: "data-model-list-fields-selector", inputs: { list: { classPropertyName: "list", publicName: "list", isSignal: true, isRequired: true, transformFunction: null } }, providers: [{ provide: CDK_DRAG_CONFIG, useValue: DragConfig }], viewQueries: [{ propertyName: "ofctpl", first: true, predicate: ["selector"], descendants: true, static: true }], ngImport: i0, template: "<i\n class=\"bi bi-list-ul\"\n (click)=\"open()\"\n role=\"button\"\n tabindex=\"0\"\n aria-label=\"Choix des champs\"\n (keydown.enter)=\"open()\"\n (keydown.space)=\"$event.preventDefault(); open()\"\n></i>\n<ng-template #selector let-offcanvas>\n <div class=\"offcanvas-header\">\n <h4 class=\"offcanvas-title\">Choix des champs</h4>\n <button class=\"btn-close\" type=\"button\" aria-label=\"Close\" (click)=\"offcanvas.dismiss('x')\"></button>\n </div>\n <div class=\"offcanvas-body\" cdkScrollable>\n @if (list().fields.fields | async; as fields) {\n <div class=\"fields-list\" cdkDropList cdkDropListLockAxis=\"y\" (cdkDropListDropped)=\"drop($event)\">\n @for (f of fields; track f) {\n @if (seeMore || f.priority >= 0) {\n <div\n class=\"field-box\"\n cdkDrag\n (click)=\"toggle(f)\"\n (keydown.enter)=\"toggle(f)\"\n (keydown.space)=\"$event.preventDefault(); toggle(f)\"\n tabindex=\"0\"\n [cdkDragData]=\"f.name\"\n [class.enabled]=\"f.enabled\"\n [class.compact]=\"fields.length>30\"\n [attr.arial-label]=\"f.label\"\n role=\"button\"\n >\n {{ f.label }}\n <span class=\"badge bg-info\">{{ f.priority }}</span>\n </div>\n }\n }\n </div>\n }\n <button class=\"btn btn-sm btn-link\" (click)=\"seeMore = !seeMore\">plus de champs</button>\n </div>\n</ng-template>\n", styles: [".fields-list{width:100%;max-width:100%;border:var(--bs-border-style) var(--bs-border-width) var(--bs-border-color);min-height:50px;display:block;background:var(--bs-body-bg-rgb);border-radius:var(--bs-border-radius-sm);overflow:hidden}.field-box{padding:.5rem 1rem;border-bottom:solid 1px #ccc;color:var(--bs-black);display:flex;flex-direction:row;align-items:center;justify-content:space-between;box-sizing:border-box;cursor:move;background:#fff;font-size:var(--bs-body-font-size)}.field-box.compact{padding:.2rem 1rem;font-size:.9rem}.field-box.enabled{background-color:var(--bs-success);color:var(--bs-white)}.cdk-drag-preview{box-sizing:border-box;border-radius:var(--bs-border-radius-sm);box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.cdk-drag-placeholder{opacity:0}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.field-box:last-child{border:none}.fields-list.cdk-drop-list-dragging .field-box:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}\n"], dependencies: [{ kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i1.ɵɵCdkScrollable, selector: "[cdk-scrollable], [cdkScrollable]" }, { kind: "directive", type: i1.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i1.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "ngmodule", type: CdkScrollableModule }, { kind: "ngmodule", type: NgbOffcanvasModule }, { kind: "pipe", type: AsyncPipe, name: "async" }] });
|
|
3311
3375
|
}
|
|
3312
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
3376
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ModelListFieldsSelectorComponent, decorators: [{
|
|
3313
3377
|
type: Component,
|
|
3314
|
-
args: [{ selector: 'data-model-list-fields-selector', imports: [
|
|
3315
|
-
AsyncPipe,
|
|
3316
|
-
DragDropModule,
|
|
3317
|
-
CdkScrollableModule,
|
|
3318
|
-
NgbOffcanvasModule,
|
|
3319
|
-
], providers: [{ provide: CDK_DRAG_CONFIG, useValue: DragConfig }], template: "<i class=\"bi bi-list-ul\" (click)=\"open()\" role=\"button\" aria-label=\"Choix des champs\"></i>\n<ng-template #selector let-offcanvas>\n <div class=\"offcanvas-header\">\n <h4 class=\"offcanvas-title\">Choix des champs</h4>\n <button class=\"btn-close\" type=\"button\" aria-label=\"Close\" (click)=\"offcanvas.dismiss('x')\"></button>\n </div>\n <div class=\"offcanvas-body\" cdkScrollable>\n @if (list().fields.fields|async; as fields) {\n <div class=\"fields-list\" cdkDropList cdkDropListLockAxis=\"y\" (cdkDropListDropped)=\"drop($event)\">\n @for (f of fields; track f) {\n @if (seeMore || f.priority >= 0) {\n <div class=\"field-box\" cdkDrag (click)=\"toggle(f)\" [cdkDragData]=\"f.name\" [class.enabled]=\"f.enabled\" [class.compact]=\"fields.length>30\" [attr.arial-label]=\"f.label\" role=\"button\">{{f.label}}<span class=\"badge bg-info\"> {{f.priority}}</span></div>\n }\n }\n </div>\n }\n <button class=\"btn btn-sm btn-link\" (click)=\"seeMore=!seeMore\">plus de champs</button>\n </div>\n</ng-template>", styles: [".fields-list{width:100%;max-width:100%;border:var(--bs-border-style) var(--bs-border-width) var(--bs-border-color);min-height:50px;display:block;background:var(--bs-body-bg-rgb);border-radius:var(--bs-border-radius-sm);overflow:hidden}.field-box{padding:.5rem 1rem;border-bottom:solid 1px #ccc;color:var(--bs-black);display:flex;flex-direction:row;align-items:center;justify-content:space-between;box-sizing:border-box;cursor:move;background:#fff;font-size:var(--bs-body-font-size)}.field-box.compact{padding:.2rem 1rem;font-size:.9rem}.field-box.enabled{background-color:var(--bs-success);color:var(--bs-white)}.cdk-drag-preview{box-sizing:border-box;border-radius:var(--bs-border-radius-sm);box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.cdk-drag-placeholder{opacity:0}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.field-box:last-child{border:none}.fields-list.cdk-drop-list-dragging .field-box:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}\n"] }]
|
|
3378
|
+
args: [{ selector: 'data-model-list-fields-selector', imports: [AsyncPipe, DragDropModule, CdkScrollableModule, NgbOffcanvasModule], providers: [{ provide: CDK_DRAG_CONFIG, useValue: DragConfig }], template: "<i\n class=\"bi bi-list-ul\"\n (click)=\"open()\"\n role=\"button\"\n tabindex=\"0\"\n aria-label=\"Choix des champs\"\n (keydown.enter)=\"open()\"\n (keydown.space)=\"$event.preventDefault(); open()\"\n></i>\n<ng-template #selector let-offcanvas>\n <div class=\"offcanvas-header\">\n <h4 class=\"offcanvas-title\">Choix des champs</h4>\n <button class=\"btn-close\" type=\"button\" aria-label=\"Close\" (click)=\"offcanvas.dismiss('x')\"></button>\n </div>\n <div class=\"offcanvas-body\" cdkScrollable>\n @if (list().fields.fields | async; as fields) {\n <div class=\"fields-list\" cdkDropList cdkDropListLockAxis=\"y\" (cdkDropListDropped)=\"drop($event)\">\n @for (f of fields; track f) {\n @if (seeMore || f.priority >= 0) {\n <div\n class=\"field-box\"\n cdkDrag\n (click)=\"toggle(f)\"\n (keydown.enter)=\"toggle(f)\"\n (keydown.space)=\"$event.preventDefault(); toggle(f)\"\n tabindex=\"0\"\n [cdkDragData]=\"f.name\"\n [class.enabled]=\"f.enabled\"\n [class.compact]=\"fields.length>30\"\n [attr.arial-label]=\"f.label\"\n role=\"button\"\n >\n {{ f.label }}\n <span class=\"badge bg-info\">{{ f.priority }}</span>\n </div>\n }\n }\n </div>\n }\n <button class=\"btn btn-sm btn-link\" (click)=\"seeMore = !seeMore\">plus de champs</button>\n </div>\n</ng-template>\n", styles: [".fields-list{width:100%;max-width:100%;border:var(--bs-border-style) var(--bs-border-width) var(--bs-border-color);min-height:50px;display:block;background:var(--bs-body-bg-rgb);border-radius:var(--bs-border-radius-sm);overflow:hidden}.field-box{padding:.5rem 1rem;border-bottom:solid 1px #ccc;color:var(--bs-black);display:flex;flex-direction:row;align-items:center;justify-content:space-between;box-sizing:border-box;cursor:move;background:#fff;font-size:var(--bs-body-font-size)}.field-box.compact{padding:.2rem 1rem;font-size:.9rem}.field-box.enabled{background-color:var(--bs-success);color:var(--bs-white)}.cdk-drag-preview{box-sizing:border-box;border-radius:var(--bs-border-radius-sm);box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.cdk-drag-placeholder{opacity:0}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.field-box:last-child{border:none}.fields-list.cdk-drop-list-dragging .field-box:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}\n"] }]
|
|
3320
3379
|
}], propDecorators: { list: [{ type: i0.Input, args: [{ isSignal: true, alias: "list", required: true }] }], ofctpl: [{
|
|
3321
3380
|
type: ViewChild,
|
|
3322
3381
|
args: ['selector', { static: true }]
|
|
@@ -3357,7 +3416,9 @@ class ModelListSorterComponent {
|
|
|
3357
3416
|
/** This field is sorted descending. */
|
|
3358
3417
|
isDown = signal(false, /* @ts-ignore */
|
|
3359
3418
|
...(ngDevMode ? [{ debugName: "isDown" }] : /* istanbul ignore next */ []));
|
|
3360
|
-
constructor() {
|
|
3419
|
+
constructor() {
|
|
3420
|
+
// Dependencies are resolved with inject().
|
|
3421
|
+
}
|
|
3361
3422
|
/** Sort ascending on this field. */
|
|
3362
3423
|
setUp() {
|
|
3363
3424
|
this.list().sorter.set(this.field(), 'asc');
|
|
@@ -3365,9 +3426,7 @@ class ModelListSorterComponent {
|
|
|
3365
3426
|
}
|
|
3366
3427
|
/** Re-read this field's sort state from the list's sorter into the signals. */
|
|
3367
3428
|
update() {
|
|
3368
|
-
this.getCount.set(this.list().sorter.get(this.field())
|
|
3369
|
-
? this.list().sorter.getAll().length
|
|
3370
|
-
: 0);
|
|
3429
|
+
this.getCount.set(this.list().sorter.get(this.field()) ? this.list().sorter.getAll().length : 0);
|
|
3371
3430
|
this.getOrder.set(this.list().sorter.getOrder(this.field()));
|
|
3372
3431
|
this.isDown.set(this.getIsDown());
|
|
3373
3432
|
this.isUp.set(this.getIsUp());
|
|
@@ -3396,12 +3455,12 @@ class ModelListSorterComponent {
|
|
|
3396
3455
|
}
|
|
3397
3456
|
return false;
|
|
3398
3457
|
}
|
|
3399
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
3400
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.
|
|
3458
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ModelListSorterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3459
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: ModelListSorterComponent, isStandalone: true, selector: "data-model-list-sorter", inputs: { list: { classPropertyName: "list", publicName: "list", isSignal: true, isRequired: true, transformFunction: null }, field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<span class=\"dirs\">\n @if (getOrder() >= 0 || getCount() > 1) {\n <span\n (click)=\"cancel()\"\n role=\"button\"\n tabindex=\"0\"\n aria-label=\"Annuler le tri\"\n (keydown.enter)=\"cancel()\"\n (keydown.space)=\"$event.preventDefault(); cancel()\"\n >\n @if (getCount() > 1) {\n <span class=\"count\">{{ getOrder() }}</span>\n }\n <span class=\"bi bi-x\"></span>\n </span>\n }\n <span\n class=\"bi bi-sort-down-alt\"\n (click)=\"setUp()\"\n [class.active]=\"isUp()\"\n role=\"button\"\n tabindex=\"0\"\n aria-label=\"Trier par ordre croissant\"\n (keydown.enter)=\"setUp()\"\n (keydown.space)=\"$event.preventDefault(); setUp()\"\n ></span>\n <span\n class=\"bi bi-sort-down\"\n (click)=\"setDown()\"\n [class.active]=\"isDown()\"\n role=\"button\"\n tabindex=\"0\"\n aria-label=\"Trier par ordre d\u00E9croissant\"\n (keydown.enter)=\"setDown()\"\n (keydown.space)=\"$event.preventDefault(); setDown()\"\n ></span>\n \n</span>\n<ng-content></ng-content>\n", styles: [".dirs{color:#d3d3d3}.dirs .count{font-size:.7rem;margin-right:-.1rem;vertical-align:super}.active{color:#000}\n"] });
|
|
3401
3460
|
}
|
|
3402
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
3461
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ModelListSorterComponent, decorators: [{
|
|
3403
3462
|
type: Component,
|
|
3404
|
-
args: [{ selector: 'data-model-list-sorter', imports: [], template: "<span class=\"dirs\"
|
|
3463
|
+
args: [{ selector: 'data-model-list-sorter', imports: [], template: "<span class=\"dirs\">\n @if (getOrder() >= 0 || getCount() > 1) {\n <span\n (click)=\"cancel()\"\n role=\"button\"\n tabindex=\"0\"\n aria-label=\"Annuler le tri\"\n (keydown.enter)=\"cancel()\"\n (keydown.space)=\"$event.preventDefault(); cancel()\"\n >\n @if (getCount() > 1) {\n <span class=\"count\">{{ getOrder() }}</span>\n }\n <span class=\"bi bi-x\"></span>\n </span>\n }\n <span\n class=\"bi bi-sort-down-alt\"\n (click)=\"setUp()\"\n [class.active]=\"isUp()\"\n role=\"button\"\n tabindex=\"0\"\n aria-label=\"Trier par ordre croissant\"\n (keydown.enter)=\"setUp()\"\n (keydown.space)=\"$event.preventDefault(); setUp()\"\n ></span>\n <span\n class=\"bi bi-sort-down\"\n (click)=\"setDown()\"\n [class.active]=\"isDown()\"\n role=\"button\"\n tabindex=\"0\"\n aria-label=\"Trier par ordre d\u00E9croissant\"\n (keydown.enter)=\"setDown()\"\n (keydown.space)=\"$event.preventDefault(); setDown()\"\n ></span>\n \n</span>\n<ng-content></ng-content>\n", styles: [".dirs{color:#d3d3d3}.dirs .count{font-size:.7rem;margin-right:-.1rem;vertical-align:super}.active{color:#000}\n"] }]
|
|
3405
3464
|
}], ctorParameters: () => [], propDecorators: { list: [{ type: i0.Input, args: [{ isSignal: true, alias: "list", required: true }] }], field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }] } });
|
|
3406
3465
|
|
|
3407
3466
|
/**
|
|
@@ -3468,12 +3527,12 @@ class ModelListFieldHeaderComponent {
|
|
|
3468
3527
|
this.list().fields.move(f.name, 'after', this.field());
|
|
3469
3528
|
this.list().fields.enable(f.name);
|
|
3470
3529
|
}
|
|
3471
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
3472
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.
|
|
3530
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ModelListFieldHeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3531
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: ModelListFieldHeaderComponent, isStandalone: true, selector: "data-model-list-field-header", inputs: { list: { classPropertyName: "list", publicName: "list", isSignal: true, isRequired: true, transformFunction: null }, field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null }, sort: { classPropertyName: "sort", publicName: "sort", isSignal: true, isRequired: false, transformFunction: null }, sortField: { classPropertyName: "sortField", publicName: "sortField", isSignal: true, isRequired: false, transformFunction: null }, menuMode: { classPropertyName: "menuMode", publicName: "menuMode", isSignal: true, isRequired: false, transformFunction: null }, sortMode: { classPropertyName: "sortMode", publicName: "sortMode", isSignal: true, isRequired: false, transformFunction: null }, display: { classPropertyName: "display", publicName: "display", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { display: "displayChange" }, viewQueries: [{ propertyName: "mnu", first: true, predicate: ["mnu"], descendants: true }], ngImport: i0, template: "<ng-template #label>\n <span #ref><ng-content></ng-content></span>\n @if (!ref.children.length) {\n <span>{{ list().fields.get(field())?.label || field() }}</span>\n }\n</ng-template>\n<div class=\"d-flex flex-row justify-content-between align-items-end slabel\">\n <div class=\"flex-grow-1\">\n @if (sort() && dispSortMode() === \"side\") {\n <data-model-list-sorter [list]=\"list()\" [field]=\"sortField() || field()\">\n <ng-container *ngTemplateOutlet=\"label\"></ng-container>\n </data-model-list-sorter>\n }\n @if (!sort() || dispSortMode() === \"hide\") {\n <ng-container *ngTemplateOutlet=\"label\"></ng-container>\n }\n </div>\n @if (dispMenuMode() === \"side\") {\n <div class=\"navicons d-flex flex-row\" [attr.aria-label]=\"'Gestion champs'\">\n <i\n class=\"bi bi-caret-left-fill\"\n role=\"button\"\n tabindex=\"0\"\n aria-label=\"D\u00E9placer vers la gauche\"\n (click)=\"list().fields.move(field(), 'before')\"\n (keydown.enter)=\"list().fields.move(field(), 'before')\"\n (keydown.space)=\"$event.preventDefault(); list().fields.move(field(), 'before')\"\n ></i>\n <div ngbDropdown #mnu=\"ngbDropdown\" [container]=\"'body'\">\n <i class=\"bi bi-record\" ngbDropdownToggle aria-label=\"Ouvrir la boite de dialogue des champs\" role=\"button\"></i>\n <div ngbDropdownMenu>\n <button ngbDropdownItem (click)=\"disable()\">\n <i class=\"bi bi-trash me-2\"></i>\n Supprimer\n </button>\n <h6 class=\"dropdown-header\">Ajouter une colonne apr\u00E8s</h6>\n @for (f of list().fields.fields | async; track f) {\n @if (f.allowed && !f.enabled) {\n <button ngbDropdownItem (click)=\"enable(f)\" [attr.aria-label]=\"f.label || f.name\">\n <i class=\"bi bi-plus-circle me-2\"></i>\n {{ f.label || f.name }}\n </button>\n }\n }\n </div>\n </div>\n <i\n class=\"bi bi-caret-right-fill\"\n role=\"button\"\n tabindex=\"0\"\n aria-label=\"D\u00E9placer vers la droite\"\n (click)=\"list().fields.move(field(), 'after')\"\n (keydown.enter)=\"list().fields.move(field(), 'after')\"\n (keydown.space)=\"$event.preventDefault(); list().fields.move(field(), 'after')\"\n ></i>\n </div>\n }\n</div>\n", styles: [".slabel .navicons{opacity:0}.slabel:hover .navicons,.slabel.active .navicons{opacity:1!important}.dropdown-toggle:after{display:none!important}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: NgbDropdownModule }, { kind: "directive", type: i1$1.NgbDropdown, selector: "[ngbDropdown]", inputs: ["autoClose", "dropdownClass", "open", "placement", "popperOptions", "container", "display"], outputs: ["openChange"], exportAs: ["ngbDropdown"] }, { kind: "directive", type: i1$1.NgbDropdownToggle, selector: "[ngbDropdownToggle]" }, { kind: "directive", type: i1$1.NgbDropdownMenu, selector: "[ngbDropdownMenu]" }, { kind: "directive", type: i1$1.NgbDropdownItem, selector: "[ngbDropdownItem]", inputs: ["tabindex", "disabled"] }, { kind: "directive", type: i1$1.NgbDropdownButtonItem, selector: "button[ngbDropdownItem]" }, { kind: "component", type: ModelListSorterComponent, selector: "data-model-list-sorter", inputs: ["list", "field"] }, { kind: "pipe", type: AsyncPipe, name: "async" }] });
|
|
3473
3532
|
}
|
|
3474
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
3533
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ModelListFieldHeaderComponent, decorators: [{
|
|
3475
3534
|
type: Component,
|
|
3476
|
-
args: [{ selector: 'data-model-list-field-header', imports: [AsyncPipe, NgTemplateOutlet, NgbDropdownModule, ModelListSorterComponent], template: "
|
|
3535
|
+
args: [{ selector: 'data-model-list-field-header', imports: [AsyncPipe, NgTemplateOutlet, NgbDropdownModule, ModelListSorterComponent], template: "<ng-template #label>\n <span #ref><ng-content></ng-content></span>\n @if (!ref.children.length) {\n <span>{{ list().fields.get(field())?.label || field() }}</span>\n }\n</ng-template>\n<div class=\"d-flex flex-row justify-content-between align-items-end slabel\">\n <div class=\"flex-grow-1\">\n @if (sort() && dispSortMode() === \"side\") {\n <data-model-list-sorter [list]=\"list()\" [field]=\"sortField() || field()\">\n <ng-container *ngTemplateOutlet=\"label\"></ng-container>\n </data-model-list-sorter>\n }\n @if (!sort() || dispSortMode() === \"hide\") {\n <ng-container *ngTemplateOutlet=\"label\"></ng-container>\n }\n </div>\n @if (dispMenuMode() === \"side\") {\n <div class=\"navicons d-flex flex-row\" [attr.aria-label]=\"'Gestion champs'\">\n <i\n class=\"bi bi-caret-left-fill\"\n role=\"button\"\n tabindex=\"0\"\n aria-label=\"D\u00E9placer vers la gauche\"\n (click)=\"list().fields.move(field(), 'before')\"\n (keydown.enter)=\"list().fields.move(field(), 'before')\"\n (keydown.space)=\"$event.preventDefault(); list().fields.move(field(), 'before')\"\n ></i>\n <div ngbDropdown #mnu=\"ngbDropdown\" [container]=\"'body'\">\n <i class=\"bi bi-record\" ngbDropdownToggle aria-label=\"Ouvrir la boite de dialogue des champs\" role=\"button\"></i>\n <div ngbDropdownMenu>\n <button ngbDropdownItem (click)=\"disable()\">\n <i class=\"bi bi-trash me-2\"></i>\n Supprimer\n </button>\n <h6 class=\"dropdown-header\">Ajouter une colonne apr\u00E8s</h6>\n @for (f of list().fields.fields | async; track f) {\n @if (f.allowed && !f.enabled) {\n <button ngbDropdownItem (click)=\"enable(f)\" [attr.aria-label]=\"f.label || f.name\">\n <i class=\"bi bi-plus-circle me-2\"></i>\n {{ f.label || f.name }}\n </button>\n }\n }\n </div>\n </div>\n <i\n class=\"bi bi-caret-right-fill\"\n role=\"button\"\n tabindex=\"0\"\n aria-label=\"D\u00E9placer vers la droite\"\n (click)=\"list().fields.move(field(), 'after')\"\n (keydown.enter)=\"list().fields.move(field(), 'after')\"\n (keydown.space)=\"$event.preventDefault(); list().fields.move(field(), 'after')\"\n ></i>\n </div>\n }\n</div>\n", styles: [".slabel .navicons{opacity:0}.slabel:hover .navicons,.slabel.active .navicons{opacity:1!important}.dropdown-toggle:after{display:none!important}\n"] }]
|
|
3477
3536
|
}], propDecorators: { list: [{ type: i0.Input, args: [{ isSignal: true, alias: "list", required: true }] }], field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], sort: [{ type: i0.Input, args: [{ isSignal: true, alias: "sort", required: false }] }], sortField: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortField", required: false }] }], menuMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "menuMode", required: false }] }], sortMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortMode", required: false }] }], display: [{ type: i0.Input, args: [{ isSignal: true, alias: "display", required: false }] }, { type: i0.Output, args: ["displayChange"] }], mnu: [{
|
|
3478
3537
|
type: ViewChild,
|
|
3479
3538
|
args: ['mnu', { static: false }]
|
|
@@ -3531,9 +3590,7 @@ class ModelListFiltersSelectComponent {
|
|
|
3531
3590
|
*/
|
|
3532
3591
|
ngOnInit() {
|
|
3533
3592
|
if (this.mode() === 'select') {
|
|
3534
|
-
this.selectForm.valueChanges
|
|
3535
|
-
.pipe(takeUntilDestroyed(this.destroy$))
|
|
3536
|
-
.subscribe((f) => {
|
|
3593
|
+
this.selectForm.valueChanges.pipe(takeUntilDestroyed(this.destroy$)).subscribe((f) => {
|
|
3537
3594
|
if (f) {
|
|
3538
3595
|
f.enabled = !f.enabled;
|
|
3539
3596
|
this.list().filters.update();
|
|
@@ -3542,14 +3599,33 @@ class ModelListFiltersSelectComponent {
|
|
|
3542
3599
|
});
|
|
3543
3600
|
}
|
|
3544
3601
|
}
|
|
3545
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
3546
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.
|
|
3602
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ModelListFiltersSelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3603
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: ModelListFiltersSelectComponent, isStandalone: true, selector: "data-model-list-filters-select", inputs: { list: { classPropertyName: "list", publicName: "list", isSignal: true, isRequired: true, transformFunction: null }, containerClasses: { classPropertyName: "containerClasses", publicName: "containerClasses", isSignal: true, isRequired: false, transformFunction: null }, itemActiveClasses: { classPropertyName: "itemActiveClasses", publicName: "itemActiveClasses", isSignal: true, isRequired: false, transformFunction: null }, itemInactiveClasses: { classPropertyName: "itemInactiveClasses", publicName: "itemInactiveClasses", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (mode() === \"badge\") {\n @for (f of list().filters.available | async; track f) {\n <span\n (click)=\"toggle(f)\"\n [class]=\"containerClasses()\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-pressed]=\"f.enabled\"\n [attr.aria-label]=\"f.label\"\n (keydown.enter)=\"toggle(f)\"\n (keydown.space)=\"$event.preventDefault(); toggle(f)\"\n >\n @if (f.enabled) {\n <span [class]=\"itemActiveClasses()\" [title]=\"f.desc\">\n <i class=\"bi bi-check2-square me-2\"></i>\n <span>{{ f.label }}</span>\n </span>\n }\n @if (!f.enabled) {\n <span [class]=\"itemInactiveClasses()\" [title]=\"f.desc\">\n <i class=\"bi bi-square me-2\"></i>\n <span>{{ f.label }}</span>\n </span>\n }\n </span>\n }\n}\n@if (mode() === \"badge_summary\") {\n @for (f of list().filters.available | async; track f) {\n <span\n (click)=\"toggle(f)\"\n [class]=\"containerClasses()\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-pressed]=\"f.enabled\"\n [attr.aria-label]=\"f.label\"\n (keydown.enter)=\"toggle(f)\"\n (keydown.space)=\"$event.preventDefault(); toggle(f)\"\n >\n @if (f.enabled) {\n <span [class]=\"itemActiveClasses()\" [title]=\"f.desc\">\n <i class=\"bi bi-check2-square me-2\"></i>\n <span>{{ f.label }} : {{ f.summary || \"...\" }}</span>\n </span>\n }\n </span>\n }\n}\n@if (mode() === \"select\") {\n <select class=\"form-select\" [formControl]=\"selectForm\">\n <option [ngValue]=\"null\">-- Ajouter un filtre --</option>\n @for (f of list().filters.available | async; track f) {\n @if (!f.enabled && !f.group) {\n <option [ngValue]=\"f\">{{ f.label }}</option>\n }\n }\n @for (g of list().filters.groups | async; track g) {\n <optgroup [label]=\"g.label\">\n @for (f of g.filters; track f) {\n @if (!f.enabled && f.allowed) {\n <option [ngValue]=\"f\">{{ f.label }}</option>\n }\n }\n </optgroup>\n }\n </select>\n}\n", styles: [""], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$2.SelectControlValueAccessor, selector: "select:not([multiple]):not([ngNoCva])[formControlName],select:not([multiple]):not([ngNoCva])[formControl],select:not([multiple]):not([ngNoCva])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "pipe", type: AsyncPipe, name: "async" }] });
|
|
3547
3604
|
}
|
|
3548
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
3605
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ModelListFiltersSelectComponent, decorators: [{
|
|
3549
3606
|
type: Component,
|
|
3550
|
-
args: [{ selector: 'data-model-list-filters-select', imports: [AsyncPipe, ReactiveFormsModule], template: "
|
|
3607
|
+
args: [{ selector: 'data-model-list-filters-select', imports: [AsyncPipe, ReactiveFormsModule], template: "@if (mode() === \"badge\") {\n @for (f of list().filters.available | async; track f) {\n <span\n (click)=\"toggle(f)\"\n [class]=\"containerClasses()\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-pressed]=\"f.enabled\"\n [attr.aria-label]=\"f.label\"\n (keydown.enter)=\"toggle(f)\"\n (keydown.space)=\"$event.preventDefault(); toggle(f)\"\n >\n @if (f.enabled) {\n <span [class]=\"itemActiveClasses()\" [title]=\"f.desc\">\n <i class=\"bi bi-check2-square me-2\"></i>\n <span>{{ f.label }}</span>\n </span>\n }\n @if (!f.enabled) {\n <span [class]=\"itemInactiveClasses()\" [title]=\"f.desc\">\n <i class=\"bi bi-square me-2\"></i>\n <span>{{ f.label }}</span>\n </span>\n }\n </span>\n }\n}\n@if (mode() === \"badge_summary\") {\n @for (f of list().filters.available | async; track f) {\n <span\n (click)=\"toggle(f)\"\n [class]=\"containerClasses()\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-pressed]=\"f.enabled\"\n [attr.aria-label]=\"f.label\"\n (keydown.enter)=\"toggle(f)\"\n (keydown.space)=\"$event.preventDefault(); toggle(f)\"\n >\n @if (f.enabled) {\n <span [class]=\"itemActiveClasses()\" [title]=\"f.desc\">\n <i class=\"bi bi-check2-square me-2\"></i>\n <span>{{ f.label }} : {{ f.summary || \"...\" }}</span>\n </span>\n }\n </span>\n }\n}\n@if (mode() === \"select\") {\n <select class=\"form-select\" [formControl]=\"selectForm\">\n <option [ngValue]=\"null\">-- Ajouter un filtre --</option>\n @for (f of list().filters.available | async; track f) {\n @if (!f.enabled && !f.group) {\n <option [ngValue]=\"f\">{{ f.label }}</option>\n }\n }\n @for (g of list().filters.groups | async; track g) {\n <optgroup [label]=\"g.label\">\n @for (f of g.filters; track f) {\n @if (!f.enabled && f.allowed) {\n <option [ngValue]=\"f\">{{ f.label }}</option>\n }\n }\n </optgroup>\n }\n </select>\n}\n" }]
|
|
3551
3608
|
}], propDecorators: { list: [{ type: i0.Input, args: [{ isSignal: true, alias: "list", required: true }] }], containerClasses: [{ type: i0.Input, args: [{ isSignal: true, alias: "containerClasses", required: false }] }], itemActiveClasses: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemActiveClasses", required: false }] }], itemInactiveClasses: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemInactiveClasses", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }] } });
|
|
3552
3609
|
|
|
3610
|
+
let _sequence = 0;
|
|
3611
|
+
/**
|
|
3612
|
+
* Returns a document-unique DOM id, as `<prefix>-<n>`.
|
|
3613
|
+
*
|
|
3614
|
+
* Used to wire a `<label [attr.for]>` to the control its template owns: the
|
|
3615
|
+
* widgets in this library are instantiated repeatedly on the same page, so a
|
|
3616
|
+
* hard-coded id would collide and silently break the association.
|
|
3617
|
+
*
|
|
3618
|
+
* The counter is module-level and starts at zero in each JS context, so a
|
|
3619
|
+
* server-rendered page and its client hydration agree as long as components are
|
|
3620
|
+
* created in the same order — which is what Angular does.
|
|
3621
|
+
*
|
|
3622
|
+
* @param prefix identifies the widget, e.g. `data-filter`
|
|
3623
|
+
*/
|
|
3624
|
+
function uniqueId(prefix) {
|
|
3625
|
+
_sequence += 1;
|
|
3626
|
+
return `${prefix}-${_sequence}`;
|
|
3627
|
+
}
|
|
3628
|
+
|
|
3553
3629
|
/**
|
|
3554
3630
|
* Widget for {@link ModelListTextFilter}: a text input that pushes what the
|
|
3555
3631
|
* user types into the filter, debounced by 250 ms so that a burst of keystrokes
|
|
@@ -3566,6 +3642,8 @@ class ModelListTextFilterComponent {
|
|
|
3566
3642
|
/** CSS classes for the widget's container, overridden by the filter's `displayClasses`. */
|
|
3567
3643
|
classes = input('', /* @ts-ignore */
|
|
3568
3644
|
...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
|
|
3645
|
+
/** Id shared by the label and its control, so clicking the label focuses it. */
|
|
3646
|
+
inputId = uniqueId('data-filter');
|
|
3569
3647
|
/** Backs the text input. */
|
|
3570
3648
|
fc = new FormControl(null);
|
|
3571
3649
|
destroy$ = inject(DestroyRef);
|
|
@@ -3575,14 +3653,14 @@ class ModelListTextFilterComponent {
|
|
|
3575
3653
|
* is debounced before updating the filter and refreshing the list.
|
|
3576
3654
|
*/
|
|
3577
3655
|
ngOnInit() {
|
|
3578
|
-
this.filter()
|
|
3579
|
-
.pipe(takeUntilDestroyed(this.destroy$))
|
|
3656
|
+
this.filter()
|
|
3657
|
+
.valueChanges.pipe(takeUntilDestroyed(this.destroy$))
|
|
3580
3658
|
.subscribe((val) => {
|
|
3581
|
-
this.fc.setValue(val.value, {
|
|
3659
|
+
this.fc.setValue(val.value, {
|
|
3660
|
+
emitEvent: false,
|
|
3661
|
+
});
|
|
3582
3662
|
});
|
|
3583
|
-
this.fc.valueChanges
|
|
3584
|
-
.pipe(debounceTime(250), takeUntilDestroyed(this.destroy$))
|
|
3585
|
-
.subscribe((val) => {
|
|
3663
|
+
this.fc.valueChanges.pipe(debounceTime(250), takeUntilDestroyed(this.destroy$)).subscribe((val) => {
|
|
3586
3664
|
if (this.filter().set(val, val || '')) {
|
|
3587
3665
|
this.list().filters.update();
|
|
3588
3666
|
}
|
|
@@ -3596,12 +3674,12 @@ class ModelListTextFilterComponent {
|
|
|
3596
3674
|
this.filter().enabled = false;
|
|
3597
3675
|
this.list().filters.update();
|
|
3598
3676
|
}
|
|
3599
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
3600
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.
|
|
3677
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ModelListTextFilterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3678
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.3", type: ModelListTextFilterComponent, isStandalone: true, selector: "data-model-list-text-filter", inputs: { list: { classPropertyName: "list", publicName: "list", isSignal: true, isRequired: true, transformFunction: null }, filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: true, transformFunction: null }, classes: { classPropertyName: "classes", publicName: "classes", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"filteritem\" [class]=\"filter().displayClasses || classes()\">\n <div\n class=\"trash float-end\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"'D\u00E9sactiver le filtre ' + filter().label\"\n (click)=\"disable()\"\n (keydown.enter)=\"disable()\"\n (keydown.space)=\"$event.preventDefault(); disable()\"\n >\n <i class=\"bi bi-trash\"></i>\n </div>\n <label [attr.for]=\"inputId\">{{ filter().label }}</label>\n <input [attr.id]=\"inputId\" class=\"form-control\" type=\"text\" [formControl]=\"fc\" [placeholder]=\"filter().help\" />\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.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$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }] });
|
|
3601
3679
|
}
|
|
3602
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
3680
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ModelListTextFilterComponent, decorators: [{
|
|
3603
3681
|
type: Component,
|
|
3604
|
-
args: [{ selector: 'data-model-list-text-filter', imports: [ReactiveFormsModule], template: "
|
|
3682
|
+
args: [{ selector: 'data-model-list-text-filter', imports: [ReactiveFormsModule], template: "<div class=\"filteritem\" [class]=\"filter().displayClasses || classes()\">\n <div\n class=\"trash float-end\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"'D\u00E9sactiver le filtre ' + filter().label\"\n (click)=\"disable()\"\n (keydown.enter)=\"disable()\"\n (keydown.space)=\"$event.preventDefault(); disable()\"\n >\n <i class=\"bi bi-trash\"></i>\n </div>\n <label [attr.for]=\"inputId\">{{ filter().label }}</label>\n <input [attr.id]=\"inputId\" class=\"form-control\" type=\"text\" [formControl]=\"fc\" [placeholder]=\"filter().help\" />\n</div>\n" }]
|
|
3605
3683
|
}], propDecorators: { list: [{ type: i0.Input, args: [{ isSignal: true, alias: "list", required: true }] }], filter: [{ type: i0.Input, args: [{ isSignal: true, alias: "filter", required: true }] }], classes: [{ type: i0.Input, args: [{ isSignal: true, alias: "classes", required: false }] }] } });
|
|
3606
3684
|
|
|
3607
3685
|
/**
|
|
@@ -3620,8 +3698,10 @@ class ModelListAutocompleteFilterComponent {
|
|
|
3620
3698
|
/** CSS classes for the widget's container, overridden by the filter's `displayClasses`. */
|
|
3621
3699
|
classes = input('', /* @ts-ignore */
|
|
3622
3700
|
...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
|
|
3701
|
+
/** Id shared by the label and its control, so clicking the label focuses it. */
|
|
3702
|
+
inputId = uniqueId('data-filter');
|
|
3623
3703
|
/** Backs the typeahead input; its value is the selected model, not a string. */
|
|
3624
|
-
fc = new
|
|
3704
|
+
fc = new FormControl(null);
|
|
3625
3705
|
/** Bound search function handed to ngb-typeahead. */
|
|
3626
3706
|
search = this._search.bind(this);
|
|
3627
3707
|
/** Bound formatter handed to ngb-typeahead for both the input and the results. */
|
|
@@ -3639,9 +3719,7 @@ class ModelListAutocompleteFilterComponent {
|
|
|
3639
3719
|
*/
|
|
3640
3720
|
ngOnInit() {
|
|
3641
3721
|
this._setDisplay();
|
|
3642
|
-
this.fc.valueChanges
|
|
3643
|
-
.pipe(debounceTime(250), takeUntilDestroyed(this.destroy$))
|
|
3644
|
-
.subscribe((val) => {
|
|
3722
|
+
this.fc.valueChanges.pipe(debounceTime(250), takeUntilDestroyed(this.destroy$)).subscribe((val) => {
|
|
3645
3723
|
if (val) {
|
|
3646
3724
|
if (this.filter().set(val.id, this._display(val))) {
|
|
3647
3725
|
this.list().filters.update();
|
|
@@ -3669,8 +3747,8 @@ class ModelListAutocompleteFilterComponent {
|
|
|
3669
3747
|
if (!this.filter().scroll) {
|
|
3670
3748
|
return;
|
|
3671
3749
|
}
|
|
3672
|
-
const elem = $event.currentTarget.nextElementSibling
|
|
3673
|
-
elem
|
|
3750
|
+
const elem = $event.currentTarget.nextElementSibling?.getElementsByClassName('active')[0];
|
|
3751
|
+
elem?.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
|
|
3674
3752
|
}
|
|
3675
3753
|
/**
|
|
3676
3754
|
* Builds the labelling function from the filter's `display` option: a field
|
|
@@ -3682,7 +3760,7 @@ class ModelListAutocompleteFilterComponent {
|
|
|
3682
3760
|
const display = this.filter().display;
|
|
3683
3761
|
if (display) {
|
|
3684
3762
|
if (typeof display === 'string') {
|
|
3685
|
-
this._tpl = (model) =>
|
|
3763
|
+
this._tpl = (model) => String(fieldValues(model)[display]);
|
|
3686
3764
|
}
|
|
3687
3765
|
else if (typeof display === 'function') {
|
|
3688
3766
|
this._tpl = display.bind(this);
|
|
@@ -3690,13 +3768,12 @@ class ModelListAutocompleteFilterComponent {
|
|
|
3690
3768
|
}
|
|
3691
3769
|
else {
|
|
3692
3770
|
this._tpl = (model) => {
|
|
3693
|
-
|
|
3694
|
-
|
|
3771
|
+
const display = model._display;
|
|
3772
|
+
if (display) {
|
|
3773
|
+
return display;
|
|
3695
3774
|
}
|
|
3696
3775
|
else {
|
|
3697
|
-
return
|
|
3698
|
-
model['title'] ||
|
|
3699
|
-
model['id']}`;
|
|
3776
|
+
return String(fieldValues(model)['name'] ?? fieldValues(model)['title'] ?? fieldValues(model)['id']);
|
|
3700
3777
|
}
|
|
3701
3778
|
};
|
|
3702
3779
|
}
|
|
@@ -3722,8 +3799,7 @@ class ModelListAutocompleteFilterComponent {
|
|
|
3722
3799
|
const f = {};
|
|
3723
3800
|
// Generate filter
|
|
3724
3801
|
for (const k of Object.keys(this.filter().filter)) {
|
|
3725
|
-
if (this.filter().filter[k] !== null ||
|
|
3726
|
-
this.filter().filter[k] !== undefined) {
|
|
3802
|
+
if (this.filter().filter[k] !== null || this.filter().filter[k] !== undefined) {
|
|
3727
3803
|
f[k] = this.filter().filter[k];
|
|
3728
3804
|
}
|
|
3729
3805
|
}
|
|
@@ -3735,12 +3811,12 @@ class ModelListAutocompleteFilterComponent {
|
|
|
3735
3811
|
return this.filter().queryset.get();
|
|
3736
3812
|
}), takeUntilDestroyed(this.destroy$));
|
|
3737
3813
|
}
|
|
3738
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
3739
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.
|
|
3814
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ModelListAutocompleteFilterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3815
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.3", type: ModelListAutocompleteFilterComponent, isStandalone: true, selector: "data-model-list-autocomplete-filter", inputs: { list: { classPropertyName: "list", publicName: "list", isSignal: true, isRequired: true, transformFunction: null }, filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: true, transformFunction: null }, classes: { classPropertyName: "classes", publicName: "classes", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"filteritem\" [class]=\"filter().displayClasses || classes()\">\n <div\n class=\"trash float-end\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"'D\u00E9sactiver le filtre ' + filter().label\"\n (click)=\"disable()\"\n (keydown.enter)=\"disable()\"\n (keydown.space)=\"$event.preventDefault(); disable()\"\n >\n <i class=\"bi bi-trash\"></i>\n </div>\n <label [attr.for]=\"inputId\">{{ filter().label }}</label>\n <input\n [attr.id]=\"inputId\"\n class=\"form-control\"\n [formControl]=\"fc\"\n [ngbTypeahead]=\"search\"\n [editable]=\"false\"\n [focusFirst]=\"true\"\n [inputFormatter]=\"display\"\n [resultFormatter]=\"display\"\n [placeholder]=\"filter().help\"\n (keyup.arrowDown)=\"scrollAction($event)\"\n (keyup.arrowUp)=\"scrollAction($event)\"\n #th=\"ngbTypeahead\"\n [class.tascroll]=\"filter().scroll\"\n />\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: NgbTypeaheadModule }, { kind: "directive", type: i1$1.NgbTypeahead, selector: "input[ngbTypeahead]", inputs: ["autocomplete", "container", "editable", "focusFirst", "inputFormatter", "ngbTypeahead", "resultFormatter", "resultTemplate", "selectOnExact", "showHint", "placement", "popperOptions", "popupClass"], outputs: ["selectItem"], exportAs: ["ngbTypeahead"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.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$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }] });
|
|
3740
3816
|
}
|
|
3741
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
3817
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ModelListAutocompleteFilterComponent, decorators: [{
|
|
3742
3818
|
type: Component,
|
|
3743
|
-
args: [{ selector: 'data-model-list-autocomplete-filter', imports: [NgbTypeaheadModule, ReactiveFormsModule], template: "
|
|
3819
|
+
args: [{ selector: 'data-model-list-autocomplete-filter', imports: [NgbTypeaheadModule, ReactiveFormsModule], template: "<div class=\"filteritem\" [class]=\"filter().displayClasses || classes()\">\n <div\n class=\"trash float-end\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"'D\u00E9sactiver le filtre ' + filter().label\"\n (click)=\"disable()\"\n (keydown.enter)=\"disable()\"\n (keydown.space)=\"$event.preventDefault(); disable()\"\n >\n <i class=\"bi bi-trash\"></i>\n </div>\n <label [attr.for]=\"inputId\">{{ filter().label }}</label>\n <input\n [attr.id]=\"inputId\"\n class=\"form-control\"\n [formControl]=\"fc\"\n [ngbTypeahead]=\"search\"\n [editable]=\"false\"\n [focusFirst]=\"true\"\n [inputFormatter]=\"display\"\n [resultFormatter]=\"display\"\n [placeholder]=\"filter().help\"\n (keyup.arrowDown)=\"scrollAction($event)\"\n (keyup.arrowUp)=\"scrollAction($event)\"\n #th=\"ngbTypeahead\"\n [class.tascroll]=\"filter().scroll\"\n />\n</div>\n" }]
|
|
3744
3820
|
}], propDecorators: { list: [{ type: i0.Input, args: [{ isSignal: true, alias: "list", required: true }] }], filter: [{ type: i0.Input, args: [{ isSignal: true, alias: "filter", required: true }] }], classes: [{ type: i0.Input, args: [{ isSignal: true, alias: "classes", required: false }] }] } });
|
|
3745
3821
|
|
|
3746
3822
|
/**
|
|
@@ -3767,12 +3843,12 @@ class ModelListAutocompleteMultiFilterComponent extends ModelListAutocompleteFil
|
|
|
3767
3843
|
this.list().filters.update();
|
|
3768
3844
|
this.fc.setValue(null);
|
|
3769
3845
|
}
|
|
3770
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
3771
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.
|
|
3846
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ModelListAutocompleteMultiFilterComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
3847
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: ModelListAutocompleteMultiFilterComponent, isStandalone: true, selector: "data-model-list-autocomplete-multi-filter", usesInheritance: true, ngImport: i0, template: "<div class=\"filteritem\" [class]=\"filter().displayClasses || classes()\">\n <div\n class=\"trash float-end\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"'D\u00E9sactiver le filtre ' + filter().label\"\n (click)=\"disable()\"\n (keydown.enter)=\"disable()\"\n (keydown.space)=\"$event.preventDefault(); disable()\"\n >\n <i class=\"bi bi-trash\"></i>\n </div>\n <label [attr.for]=\"inputId\">{{ filter().label }}</label>\n <input\n [attr.id]=\"inputId\"\n class=\"form-control\"\n [formControl]=\"fc\"\n [ngbTypeahead]=\"search\"\n [editable]=\"false\"\n [focusFirst]=\"true\"\n [inputFormatter]=\"display\"\n [resultFormatter]=\"display\"\n [placeholder]=\"filter().help\"\n (keyup.arrowDown)=\"scrollAction($event)\"\n (keyup.arrowUp)=\"scrollAction($event)\"\n #th=\"ngbTypeahead\"\n [class.tascroll]=\"filter().scroll\"\n />\n <div class=\"enabled mt-1\">\n @for (e of filter().mcurrent$ | async; track e) {\n <div>\n <i\n class=\"bi bi-trash me-2\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"'Retirer ' + e.desc\"\n (click)=\"unset(e.value, e.desc)\"\n (keydown.enter)=\"unset(e.value, e.desc)\"\n (keydown.space)=\"$event.preventDefault(); unset(e.value, e.desc)\"\n ></i>\n {{ e.desc }}\n </div>\n }\n </div>\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: NgbTypeaheadModule }, { kind: "directive", type: i1$1.NgbTypeahead, selector: "input[ngbTypeahead]", inputs: ["autocomplete", "container", "editable", "focusFirst", "inputFormatter", "ngbTypeahead", "resultFormatter", "resultTemplate", "selectOnExact", "showHint", "placement", "popperOptions", "popupClass"], outputs: ["selectItem"], exportAs: ["ngbTypeahead"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.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$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "pipe", type: AsyncPipe, name: "async" }] });
|
|
3772
3848
|
}
|
|
3773
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
3849
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ModelListAutocompleteMultiFilterComponent, decorators: [{
|
|
3774
3850
|
type: Component,
|
|
3775
|
-
args: [{ selector: 'data-model-list-autocomplete-multi-filter', imports: [AsyncPipe, NgbTypeaheadModule, ReactiveFormsModule], template: "
|
|
3851
|
+
args: [{ selector: 'data-model-list-autocomplete-multi-filter', imports: [AsyncPipe, NgbTypeaheadModule, ReactiveFormsModule], template: "<div class=\"filteritem\" [class]=\"filter().displayClasses || classes()\">\n <div\n class=\"trash float-end\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"'D\u00E9sactiver le filtre ' + filter().label\"\n (click)=\"disable()\"\n (keydown.enter)=\"disable()\"\n (keydown.space)=\"$event.preventDefault(); disable()\"\n >\n <i class=\"bi bi-trash\"></i>\n </div>\n <label [attr.for]=\"inputId\">{{ filter().label }}</label>\n <input\n [attr.id]=\"inputId\"\n class=\"form-control\"\n [formControl]=\"fc\"\n [ngbTypeahead]=\"search\"\n [editable]=\"false\"\n [focusFirst]=\"true\"\n [inputFormatter]=\"display\"\n [resultFormatter]=\"display\"\n [placeholder]=\"filter().help\"\n (keyup.arrowDown)=\"scrollAction($event)\"\n (keyup.arrowUp)=\"scrollAction($event)\"\n #th=\"ngbTypeahead\"\n [class.tascroll]=\"filter().scroll\"\n />\n <div class=\"enabled mt-1\">\n @for (e of filter().mcurrent$ | async; track e) {\n <div>\n <i\n class=\"bi bi-trash me-2\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"'Retirer ' + e.desc\"\n (click)=\"unset(e.value, e.desc)\"\n (keydown.enter)=\"unset(e.value, e.desc)\"\n (keydown.space)=\"$event.preventDefault(); unset(e.value, e.desc)\"\n ></i>\n {{ e.desc }}\n </div>\n }\n </div>\n</div>\n" }]
|
|
3776
3852
|
}] });
|
|
3777
3853
|
|
|
3778
3854
|
/**
|
|
@@ -3790,23 +3866,25 @@ class ModelListDatetimeFilterComponent {
|
|
|
3790
3866
|
/** CSS classes for the widget's container, overridden by the filter's `displayClasses`. */
|
|
3791
3867
|
classes = input('', /* @ts-ignore */
|
|
3792
3868
|
...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
|
|
3869
|
+
/** Id shared by the label and its control, so clicking the label focuses it. */
|
|
3870
|
+
inputId = uniqueId('data-filter');
|
|
3793
3871
|
/** Backs the date/time input. */
|
|
3794
|
-
fc = new FormControl();
|
|
3872
|
+
fc = new FormControl(null);
|
|
3795
3873
|
destroy$ = inject(DestroyRef);
|
|
3796
3874
|
/**
|
|
3797
3875
|
* Binds the input to the filter both ways, debouncing changes by 250 ms
|
|
3798
3876
|
* before refreshing the list.
|
|
3799
3877
|
*/
|
|
3800
3878
|
ngOnInit() {
|
|
3801
|
-
this.filter()
|
|
3802
|
-
.pipe(takeUntilDestroyed(this.destroy$))
|
|
3879
|
+
this.filter()
|
|
3880
|
+
.valueChanges.pipe(takeUntilDestroyed(this.destroy$))
|
|
3803
3881
|
.subscribe((val) => {
|
|
3804
|
-
this.fc.setValue(val.value, {
|
|
3882
|
+
this.fc.setValue(val.value, {
|
|
3883
|
+
emitEvent: false,
|
|
3884
|
+
});
|
|
3805
3885
|
});
|
|
3806
|
-
this.fc.valueChanges
|
|
3807
|
-
.
|
|
3808
|
-
.subscribe((val) => {
|
|
3809
|
-
if (this.filter().set(val, val)) {
|
|
3886
|
+
this.fc.valueChanges.pipe(debounceTime(250), takeUntilDestroyed(this.destroy$)).subscribe((val) => {
|
|
3887
|
+
if (this.filter().set(val, val ?? '')) {
|
|
3810
3888
|
this.list().filters.update();
|
|
3811
3889
|
}
|
|
3812
3890
|
});
|
|
@@ -3819,12 +3897,12 @@ class ModelListDatetimeFilterComponent {
|
|
|
3819
3897
|
this.filter().enabled = false;
|
|
3820
3898
|
this.list().filters.update();
|
|
3821
3899
|
}
|
|
3822
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
3823
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.
|
|
3900
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ModelListDatetimeFilterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3901
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.3", type: ModelListDatetimeFilterComponent, isStandalone: true, selector: "data-model-list-datetime-filter", inputs: { list: { classPropertyName: "list", publicName: "list", isSignal: true, isRequired: true, transformFunction: null }, filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: true, transformFunction: null }, classes: { classPropertyName: "classes", publicName: "classes", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"filteritem\" [class]=\"filter().displayClasses || classes()\">\n <div\n class=\"trash float-end\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"'D\u00E9sactiver le filtre ' + filter().label\"\n (click)=\"disable()\"\n (keydown.enter)=\"disable()\"\n (keydown.space)=\"$event.preventDefault(); disable()\"\n >\n <i class=\"bi bi-trash\"></i>\n </div>\n <label [attr.for]=\"inputId\">{{ filter().label }}</label>\n <input\n [attr.id]=\"inputId\"\n class=\"form-control\"\n type=\"datetime-local\"\n [formControl]=\"fc\"\n [placeholder]=\"filter().help\"\n />\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.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$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }] });
|
|
3824
3902
|
}
|
|
3825
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
3903
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ModelListDatetimeFilterComponent, decorators: [{
|
|
3826
3904
|
type: Component,
|
|
3827
|
-
args: [{ selector: 'data-model-list-datetime-filter', imports: [ReactiveFormsModule], template: "
|
|
3905
|
+
args: [{ selector: 'data-model-list-datetime-filter', imports: [ReactiveFormsModule], template: "<div class=\"filteritem\" [class]=\"filter().displayClasses || classes()\">\n <div\n class=\"trash float-end\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"'D\u00E9sactiver le filtre ' + filter().label\"\n (click)=\"disable()\"\n (keydown.enter)=\"disable()\"\n (keydown.space)=\"$event.preventDefault(); disable()\"\n >\n <i class=\"bi bi-trash\"></i>\n </div>\n <label [attr.for]=\"inputId\">{{ filter().label }}</label>\n <input\n [attr.id]=\"inputId\"\n class=\"form-control\"\n type=\"datetime-local\"\n [formControl]=\"fc\"\n [placeholder]=\"filter().help\"\n />\n</div>\n" }]
|
|
3828
3906
|
}], propDecorators: { list: [{ type: i0.Input, args: [{ isSignal: true, alias: "list", required: true }] }], filter: [{ type: i0.Input, args: [{ isSignal: true, alias: "filter", required: true }] }], classes: [{ type: i0.Input, args: [{ isSignal: true, alias: "classes", required: false }] }] } });
|
|
3829
3907
|
|
|
3830
3908
|
/**
|
|
@@ -3842,6 +3920,8 @@ class ModelListDatetimeRangeFilterComponent {
|
|
|
3842
3920
|
/** CSS classes for the widget's container, overridden by the filter's `displayClasses`. */
|
|
3843
3921
|
classes = input('', /* @ts-ignore */
|
|
3844
3922
|
...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
|
|
3923
|
+
/** Id shared by the label and its control, so clicking the label focuses it. */
|
|
3924
|
+
inputId = uniqueId('data-filter');
|
|
3845
3925
|
/** Backs the interval's start input. */
|
|
3846
3926
|
fc1 = new FormControl();
|
|
3847
3927
|
/** Backs the interval's end input. */
|
|
@@ -3852,12 +3932,12 @@ class ModelListDatetimeRangeFilterComponent {
|
|
|
3852
3932
|
* both filled in, and splits an incoming value back across the two inputs.
|
|
3853
3933
|
*/
|
|
3854
3934
|
ngOnInit() {
|
|
3855
|
-
this.filter()
|
|
3856
|
-
.pipe(takeUntilDestroyed(this.destroy$))
|
|
3935
|
+
this.filter()
|
|
3936
|
+
.valueChanges.pipe(takeUntilDestroyed(this.destroy$))
|
|
3857
3937
|
.subscribe((val) => {
|
|
3858
3938
|
// If value is not an array, return
|
|
3859
3939
|
if (val && !Array.isArray(val)) {
|
|
3860
|
-
const [v1, v2] = val.value.split('--');
|
|
3940
|
+
const [v1, v2] = String(val.value).split('--');
|
|
3861
3941
|
this.fc1.setValue(v1, { emitEvent: false });
|
|
3862
3942
|
this.fc2.setValue(v2, { emitEvent: false });
|
|
3863
3943
|
}
|
|
@@ -3880,12 +3960,12 @@ class ModelListDatetimeRangeFilterComponent {
|
|
|
3880
3960
|
this.filter().enabled = false;
|
|
3881
3961
|
this.list().filters.update();
|
|
3882
3962
|
}
|
|
3883
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
3884
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.
|
|
3963
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ModelListDatetimeRangeFilterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3964
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.3", type: ModelListDatetimeRangeFilterComponent, isStandalone: true, selector: "data-model-list-datetime-range-filter", inputs: { list: { classPropertyName: "list", publicName: "list", isSignal: true, isRequired: true, transformFunction: null }, filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: true, transformFunction: null }, classes: { classPropertyName: "classes", publicName: "classes", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"filteritem\" [class]=\"filter().displayClasses || classes()\">\n <div\n class=\"trash float-end\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"'D\u00E9sactiver le filtre ' + filter().label\"\n (click)=\"disable()\"\n (keydown.enter)=\"disable()\"\n (keydown.space)=\"$event.preventDefault(); disable()\"\n >\n <i class=\"bi bi-trash\"></i>\n </div>\n <label [attr.for]=\"inputId\">{{ filter().label }}</label>\n <input\n [attr.id]=\"inputId\"\n class=\"form-control form-control-sm mb-1\"\n type=\"datetime-local\"\n [formControl]=\"fc1\"\n [placeholder]=\"filter().help\"\n />\n <input class=\"form-control form-control-sm\" type=\"datetime-local\" [formControl]=\"fc2\" [placeholder]=\"filter().help\" />\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.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$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }] });
|
|
3885
3965
|
}
|
|
3886
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
3966
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ModelListDatetimeRangeFilterComponent, decorators: [{
|
|
3887
3967
|
type: Component,
|
|
3888
|
-
args: [{ selector: 'data-model-list-datetime-range-filter', imports: [ReactiveFormsModule], template: "
|
|
3968
|
+
args: [{ selector: 'data-model-list-datetime-range-filter', imports: [ReactiveFormsModule], template: "<div class=\"filteritem\" [class]=\"filter().displayClasses || classes()\">\n <div\n class=\"trash float-end\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"'D\u00E9sactiver le filtre ' + filter().label\"\n (click)=\"disable()\"\n (keydown.enter)=\"disable()\"\n (keydown.space)=\"$event.preventDefault(); disable()\"\n >\n <i class=\"bi bi-trash\"></i>\n </div>\n <label [attr.for]=\"inputId\">{{ filter().label }}</label>\n <input\n [attr.id]=\"inputId\"\n class=\"form-control form-control-sm mb-1\"\n type=\"datetime-local\"\n [formControl]=\"fc1\"\n [placeholder]=\"filter().help\"\n />\n <input class=\"form-control form-control-sm\" type=\"datetime-local\" [formControl]=\"fc2\" [placeholder]=\"filter().help\" />\n</div>\n" }]
|
|
3889
3969
|
}], propDecorators: { list: [{ type: i0.Input, args: [{ isSignal: true, alias: "list", required: true }] }], filter: [{ type: i0.Input, args: [{ isSignal: true, alias: "filter", required: true }] }], classes: [{ type: i0.Input, args: [{ isSignal: true, alias: "classes", required: false }] }] } });
|
|
3890
3970
|
|
|
3891
3971
|
/**
|
|
@@ -3903,6 +3983,8 @@ class ModelListFlagsFilterComponent {
|
|
|
3903
3983
|
/** CSS classes for the widget's container, overridden by the filter's `displayClasses`. */
|
|
3904
3984
|
classes = input('', /* @ts-ignore */
|
|
3905
3985
|
...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
|
|
3986
|
+
/** Id shared by the label and its control, so clicking the label focuses it. */
|
|
3987
|
+
inputId = uniqueId('data-filter');
|
|
3906
3988
|
/** Backs the dropdown; reset to `null` after each pick. */
|
|
3907
3989
|
fc = new FormControl(null);
|
|
3908
3990
|
/** The available flags and their counts, fetched once on init. */
|
|
@@ -3916,9 +3998,7 @@ class ModelListFlagsFilterComponent {
|
|
|
3916
3998
|
ngOnInit() {
|
|
3917
3999
|
if (this.filter().collection && this.filter().action) {
|
|
3918
4000
|
this.flags$ = this.filter().collection.action(null, 'GET', this.filter().action);
|
|
3919
|
-
this.fc.valueChanges
|
|
3920
|
-
.pipe(debounceTime(250), takeUntilDestroyed(this.destroy$))
|
|
3921
|
-
.subscribe((val) => {
|
|
4001
|
+
this.fc.valueChanges.pipe(debounceTime(250), takeUntilDestroyed(this.destroy$)).subscribe((val) => {
|
|
3922
4002
|
if (val !== null) {
|
|
3923
4003
|
if (this.filter().set(val, val)) {
|
|
3924
4004
|
this.list().filters.update();
|
|
@@ -3948,12 +4028,12 @@ class ModelListFlagsFilterComponent {
|
|
|
3948
4028
|
this.filter().enabled = false;
|
|
3949
4029
|
this.list().filters.update();
|
|
3950
4030
|
}
|
|
3951
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
3952
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.
|
|
4031
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ModelListFlagsFilterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
4032
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: ModelListFlagsFilterComponent, isStandalone: true, selector: "data-model-list-flags-filter", inputs: { list: { classPropertyName: "list", publicName: "list", isSignal: true, isRequired: true, transformFunction: null }, filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: true, transformFunction: null }, classes: { classPropertyName: "classes", publicName: "classes", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"filteritem\" [class]=\"filter().displayClasses || classes()\">\n <div\n class=\"trash float-end\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"'D\u00E9sactiver le filtre ' + filter().label\"\n (click)=\"disable()\"\n (keydown.enter)=\"disable()\"\n (keydown.space)=\"$event.preventDefault(); disable()\"\n >\n <i class=\"bi bi-trash\"></i>\n </div>\n <label [attr.for]=\"inputId\">{{ filter().label }}</label>\n <select [attr.id]=\"inputId\" class=\"form-select\" [formControl]=\"fc\">\n <option [ngValue]=\"null\">-- {{ filter().help }} --</option>\n @for (c of flags$ | async; track c) {\n <option [ngValue]=\"c.flag\">{{ c.flag }} ({{ c.count }})</option>\n }\n </select>\n <div class=\"enabled mt-1\">\n @for (e of filter().mcurrent$ | async; track e) {\n <div>\n <i\n class=\"bi bi-trash me-2\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"'Retirer ' + e.desc\"\n (click)=\"unset(e.value, e.desc)\"\n (keydown.enter)=\"unset(e.value, e.desc)\"\n (keydown.space)=\"$event.preventDefault(); unset(e.value, e.desc)\"\n ></i>\n {{ e.desc }}\n </div>\n }\n </div>\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$2.SelectControlValueAccessor, selector: "select:not([multiple]):not([ngNoCva])[formControlName],select:not([multiple]):not([ngNoCva])[formControl],select:not([multiple]):not([ngNoCva])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "pipe", type: AsyncPipe, name: "async" }] });
|
|
3953
4033
|
}
|
|
3954
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
4034
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ModelListFlagsFilterComponent, decorators: [{
|
|
3955
4035
|
type: Component,
|
|
3956
|
-
args: [{ selector: 'data-model-list-flags-filter', imports: [AsyncPipe, ReactiveFormsModule], template: "
|
|
4036
|
+
args: [{ selector: 'data-model-list-flags-filter', imports: [AsyncPipe, ReactiveFormsModule], template: "<div class=\"filteritem\" [class]=\"filter().displayClasses || classes()\">\n <div\n class=\"trash float-end\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"'D\u00E9sactiver le filtre ' + filter().label\"\n (click)=\"disable()\"\n (keydown.enter)=\"disable()\"\n (keydown.space)=\"$event.preventDefault(); disable()\"\n >\n <i class=\"bi bi-trash\"></i>\n </div>\n <label [attr.for]=\"inputId\">{{ filter().label }}</label>\n <select [attr.id]=\"inputId\" class=\"form-select\" [formControl]=\"fc\">\n <option [ngValue]=\"null\">-- {{ filter().help }} --</option>\n @for (c of flags$ | async; track c) {\n <option [ngValue]=\"c.flag\">{{ c.flag }} ({{ c.count }})</option>\n }\n </select>\n <div class=\"enabled mt-1\">\n @for (e of filter().mcurrent$ | async; track e) {\n <div>\n <i\n class=\"bi bi-trash me-2\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"'Retirer ' + e.desc\"\n (click)=\"unset(e.value, e.desc)\"\n (keydown.enter)=\"unset(e.value, e.desc)\"\n (keydown.space)=\"$event.preventDefault(); unset(e.value, e.desc)\"\n ></i>\n {{ e.desc }}\n </div>\n }\n </div>\n</div>\n" }]
|
|
3957
4037
|
}], propDecorators: { list: [{ type: i0.Input, args: [{ isSignal: true, alias: "list", required: true }] }], filter: [{ type: i0.Input, args: [{ isSignal: true, alias: "filter", required: true }] }], classes: [{ type: i0.Input, args: [{ isSignal: true, alias: "classes", required: false }] }] } });
|
|
3958
4038
|
|
|
3959
4039
|
/**
|
|
@@ -3974,8 +4054,10 @@ class ModelListGeodistanceFilterComponent {
|
|
|
3974
4054
|
/** CSS classes for the widget's container, overridden by the filter's `displayClasses`. */
|
|
3975
4055
|
classes = input('', /* @ts-ignore */
|
|
3976
4056
|
...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
|
|
4057
|
+
/** Id shared by the label and its control, so clicking the label focuses it. */
|
|
4058
|
+
inputId = uniqueId('data-filter');
|
|
3977
4059
|
/** Backs the place typeahead; its value is a {@link GeoSearchResult}. */
|
|
3978
|
-
fc = new FormControl();
|
|
4060
|
+
fc = new FormControl(null);
|
|
3979
4061
|
/** Backs the distance dropdown; its value pairs an operator and a distance, e.g. `'lte,50'`. */
|
|
3980
4062
|
fd = new FormControl('');
|
|
3981
4063
|
/** Bound search function handed to ngb-typeahead. */
|
|
@@ -3994,7 +4076,7 @@ class ModelListGeodistanceFilterComponent {
|
|
|
3994
4076
|
combineLatest([address, distance])
|
|
3995
4077
|
.pipe(takeUntilDestroyed(this.destroy$))
|
|
3996
4078
|
.subscribe(([val, dist]) => {
|
|
3997
|
-
if (this.filter().set(`${dist},${val.lng},${val.lat}`, val.label)) {
|
|
4079
|
+
if (this.filter().set(`${String(dist)},${val.lng},${val.lat}`, val.label)) {
|
|
3998
4080
|
this.list().filters.update();
|
|
3999
4081
|
}
|
|
4000
4082
|
});
|
|
@@ -4027,15 +4109,15 @@ class ModelListGeodistanceFilterComponent {
|
|
|
4027
4109
|
if (!this.filter().scroll) {
|
|
4028
4110
|
return;
|
|
4029
4111
|
}
|
|
4030
|
-
const elem = $event.currentTarget.nextElementSibling
|
|
4031
|
-
elem
|
|
4112
|
+
const elem = $event.currentTarget.nextElementSibling?.getElementsByClassName('active')[0];
|
|
4113
|
+
elem?.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
|
|
4032
4114
|
}
|
|
4033
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
4034
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.
|
|
4115
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ModelListGeodistanceFilterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
4116
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.3", type: ModelListGeodistanceFilterComponent, isStandalone: true, selector: "data-model-list-geodistance-filter", inputs: { list: { classPropertyName: "list", publicName: "list", isSignal: true, isRequired: true, transformFunction: null }, filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: true, transformFunction: null }, classes: { classPropertyName: "classes", publicName: "classes", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"filteritem\" [class]=\"filter().displayClasses || classes()\">\n <div\n class=\"trash float-end\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"'D\u00E9sactiver le filtre ' + filter().label\"\n (click)=\"disable()\"\n (keydown.enter)=\"disable()\"\n (keydown.space)=\"$event.preventDefault(); disable()\"\n >\n <i class=\"bi bi-trash\"></i>\n </div>\n <label [attr.for]=\"inputId\">{{ filter().label }}</label>\n <div class=\"row g-1\">\n <div class=\"col-4\">\n <select [attr.id]=\"inputId\" class=\"form-select\" [formControl]=\"fd\">\n <option value=\"\">Distance</option>\n <option value=\"lte,10\">< 10 km</option>\n <option value=\"lte,20\">< 20 km</option>\n <option value=\"lte,30\">< 30 km</option>\n <option value=\"lte,50\">< 50 km</option>\n <option value=\"lte,80\">< 80 km</option>\n <option value=\"lte,100\">< 100 km</option>\n <option value=\"lte,150\">< 150 km</option>\n <option value=\"lte,200\">< 200 km</option>\n <option value=\"lte,250\">< 250 km</option>\n <option value=\"lte,300\">< 300 km</option>\n <option value=\"lte,500\">< 500 km</option>\n <option value=\"lte,1000\">< 1000 km</option>\n </select>\n </div>\n <div class=\"col-8\">\n <input\n class=\"form-control\"\n [formControl]=\"fc\"\n [ngbTypeahead]=\"search\"\n [editable]=\"false\"\n [focusFirst]=\"true\"\n [inputFormatter]=\"display\"\n [resultFormatter]=\"display\"\n [placeholder]=\"filter().help\"\n (keyup.arrowDown)=\"scrollAction($event)\"\n (keyup.arrowUp)=\"scrollAction($event)\"\n #th=\"ngbTypeahead\"\n [class.tascroll]=\"filter().scroll\"\n />\n </div>\n </div>\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: NgbTypeaheadModule }, { kind: "directive", type: i1$1.NgbTypeahead, selector: "input[ngbTypeahead]", inputs: ["autocomplete", "container", "editable", "focusFirst", "inputFormatter", "ngbTypeahead", "resultFormatter", "resultTemplate", "selectOnExact", "showHint", "placement", "popperOptions", "popupClass"], outputs: ["selectItem"], exportAs: ["ngbTypeahead"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$2.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$2.SelectControlValueAccessor, selector: "select:not([multiple]):not([ngNoCva])[formControlName],select:not([multiple]):not([ngNoCva])[formControl],select:not([multiple]):not([ngNoCva])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }] });
|
|
4035
4117
|
}
|
|
4036
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
4118
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ModelListGeodistanceFilterComponent, decorators: [{
|
|
4037
4119
|
type: Component,
|
|
4038
|
-
args: [{ selector: 'data-model-list-geodistance-filter', imports: [NgbTypeaheadModule, ReactiveFormsModule], template: "
|
|
4120
|
+
args: [{ selector: 'data-model-list-geodistance-filter', imports: [NgbTypeaheadModule, ReactiveFormsModule], template: "<div class=\"filteritem\" [class]=\"filter().displayClasses || classes()\">\n <div\n class=\"trash float-end\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"'D\u00E9sactiver le filtre ' + filter().label\"\n (click)=\"disable()\"\n (keydown.enter)=\"disable()\"\n (keydown.space)=\"$event.preventDefault(); disable()\"\n >\n <i class=\"bi bi-trash\"></i>\n </div>\n <label [attr.for]=\"inputId\">{{ filter().label }}</label>\n <div class=\"row g-1\">\n <div class=\"col-4\">\n <select [attr.id]=\"inputId\" class=\"form-select\" [formControl]=\"fd\">\n <option value=\"\">Distance</option>\n <option value=\"lte,10\">< 10 km</option>\n <option value=\"lte,20\">< 20 km</option>\n <option value=\"lte,30\">< 30 km</option>\n <option value=\"lte,50\">< 50 km</option>\n <option value=\"lte,80\">< 80 km</option>\n <option value=\"lte,100\">< 100 km</option>\n <option value=\"lte,150\">< 150 km</option>\n <option value=\"lte,200\">< 200 km</option>\n <option value=\"lte,250\">< 250 km</option>\n <option value=\"lte,300\">< 300 km</option>\n <option value=\"lte,500\">< 500 km</option>\n <option value=\"lte,1000\">< 1000 km</option>\n </select>\n </div>\n <div class=\"col-8\">\n <input\n class=\"form-control\"\n [formControl]=\"fc\"\n [ngbTypeahead]=\"search\"\n [editable]=\"false\"\n [focusFirst]=\"true\"\n [inputFormatter]=\"display\"\n [resultFormatter]=\"display\"\n [placeholder]=\"filter().help\"\n (keyup.arrowDown)=\"scrollAction($event)\"\n (keyup.arrowUp)=\"scrollAction($event)\"\n #th=\"ngbTypeahead\"\n [class.tascroll]=\"filter().scroll\"\n />\n </div>\n </div>\n</div>\n" }]
|
|
4039
4121
|
}], propDecorators: { list: [{ type: i0.Input, args: [{ isSignal: true, alias: "list", required: true }] }], filter: [{ type: i0.Input, args: [{ isSignal: true, alias: "filter", required: true }] }], classes: [{ type: i0.Input, args: [{ isSignal: true, alias: "classes", required: false }] }] } });
|
|
4040
4122
|
|
|
4041
4123
|
/**
|
|
@@ -4053,6 +4135,8 @@ class ModelListSelectFilterComponent {
|
|
|
4053
4135
|
/** CSS classes for the widget's container, overridden by the filter's `displayClasses`. */
|
|
4054
4136
|
classes = input('', /* @ts-ignore */
|
|
4055
4137
|
...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
|
|
4138
|
+
/** Id shared by the label and its control, so clicking the label focuses it. */
|
|
4139
|
+
inputId = uniqueId('data-filter');
|
|
4056
4140
|
/** Backs the dropdown; `null` means no selection. */
|
|
4057
4141
|
fc = new FormControl(null);
|
|
4058
4142
|
destroy$ = inject(DestroyRef);
|
|
@@ -4062,17 +4146,12 @@ class ModelListSelectFilterComponent {
|
|
|
4062
4146
|
* choices stream is combined in rather than merely rendered.
|
|
4063
4147
|
*/
|
|
4064
4148
|
ngOnInit() {
|
|
4065
|
-
this.filter()
|
|
4066
|
-
.pipe(takeUntilDestroyed(this.destroy$))
|
|
4149
|
+
this.filter()
|
|
4150
|
+
.valueChanges.pipe(takeUntilDestroyed(this.destroy$))
|
|
4067
4151
|
.subscribe((val) => {
|
|
4068
|
-
this.fc.setValue(val ? val.value : null, {
|
|
4069
|
-
emitEvent: false,
|
|
4070
|
-
});
|
|
4152
|
+
this.fc.setValue(val ? val.value : null, { emitEvent: false });
|
|
4071
4153
|
});
|
|
4072
|
-
combineLatest([
|
|
4073
|
-
this.filter().choices,
|
|
4074
|
-
this.fc.valueChanges.pipe(debounceTime(250)),
|
|
4075
|
-
])
|
|
4154
|
+
combineLatest([this.filter().choices, this.fc.valueChanges.pipe(debounceTime(250))])
|
|
4076
4155
|
.pipe(takeUntilDestroyed(this.destroy$))
|
|
4077
4156
|
.subscribe(([choices, val]) => {
|
|
4078
4157
|
if (val === null) {
|
|
@@ -4099,12 +4178,12 @@ class ModelListSelectFilterComponent {
|
|
|
4099
4178
|
this.filter().enabled = false;
|
|
4100
4179
|
this.list().filters.update();
|
|
4101
4180
|
}
|
|
4102
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
4103
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.
|
|
4181
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ModelListSelectFilterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
4182
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: ModelListSelectFilterComponent, isStandalone: true, selector: "data-model-list-select-filter", inputs: { list: { classPropertyName: "list", publicName: "list", isSignal: true, isRequired: true, transformFunction: null }, filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: true, transformFunction: null }, classes: { classPropertyName: "classes", publicName: "classes", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"filteritem\" [class]=\"filter().displayClasses || classes()\">\n <div\n class=\"trash float-end\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"'D\u00E9sactiver le filtre ' + filter().label\"\n (click)=\"disable()\"\n (keydown.enter)=\"disable()\"\n (keydown.space)=\"$event.preventDefault(); disable()\"\n >\n <i class=\"bi bi-trash\"></i>\n </div>\n <label [attr.for]=\"inputId\">{{ filter().label }}</label>\n <select [attr.id]=\"inputId\" class=\"form-select\" [formControl]=\"fc\">\n <option [ngValue]=\"null\">-- {{ filter().help }} --</option>\n @for (c of filter().choices | async; track c) {\n <option [ngValue]=\"c.value\">{{ c.desc }}</option>\n }\n </select>\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$2.SelectControlValueAccessor, selector: "select:not([multiple]):not([ngNoCva])[formControlName],select:not([multiple]):not([ngNoCva])[formControl],select:not([multiple]):not([ngNoCva])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "pipe", type: AsyncPipe, name: "async" }] });
|
|
4104
4183
|
}
|
|
4105
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
4184
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ModelListSelectFilterComponent, decorators: [{
|
|
4106
4185
|
type: Component,
|
|
4107
|
-
args: [{ selector: 'data-model-list-select-filter', imports: [AsyncPipe, ReactiveFormsModule], template: "
|
|
4186
|
+
args: [{ selector: 'data-model-list-select-filter', imports: [AsyncPipe, ReactiveFormsModule], template: "<div class=\"filteritem\" [class]=\"filter().displayClasses || classes()\">\n <div\n class=\"trash float-end\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"'D\u00E9sactiver le filtre ' + filter().label\"\n (click)=\"disable()\"\n (keydown.enter)=\"disable()\"\n (keydown.space)=\"$event.preventDefault(); disable()\"\n >\n <i class=\"bi bi-trash\"></i>\n </div>\n <label [attr.for]=\"inputId\">{{ filter().label }}</label>\n <select [attr.id]=\"inputId\" class=\"form-select\" [formControl]=\"fc\">\n <option [ngValue]=\"null\">-- {{ filter().help }} --</option>\n @for (c of filter().choices | async; track c) {\n <option [ngValue]=\"c.value\">{{ c.desc }}</option>\n }\n </select>\n</div>\n" }]
|
|
4108
4187
|
}], propDecorators: { list: [{ type: i0.Input, args: [{ isSignal: true, alias: "list", required: true }] }], filter: [{ type: i0.Input, args: [{ isSignal: true, alias: "filter", required: true }] }], classes: [{ type: i0.Input, args: [{ isSignal: true, alias: "classes", required: false }] }] } });
|
|
4109
4188
|
|
|
4110
4189
|
/**
|
|
@@ -4122,6 +4201,8 @@ class ModelListSelectMultiFilterComponent {
|
|
|
4122
4201
|
/** CSS classes for the widget's container, overridden by the filter's `displayClasses`. */
|
|
4123
4202
|
classes = input('', /* @ts-ignore */
|
|
4124
4203
|
...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
|
|
4204
|
+
/** Id shared by the label and its control, so clicking the label focuses it. */
|
|
4205
|
+
inputId = uniqueId('data-filter');
|
|
4125
4206
|
/** Backs the dropdown; reset to `null` after each pick so the same option can be re-picked. */
|
|
4126
4207
|
fc = new FormControl(null);
|
|
4127
4208
|
destroy$ = inject(DestroyRef);
|
|
@@ -4131,10 +4212,7 @@ class ModelListSelectMultiFilterComponent {
|
|
|
4131
4212
|
* the picked value's description for its chip.
|
|
4132
4213
|
*/
|
|
4133
4214
|
ngOnInit() {
|
|
4134
|
-
combineLatest([
|
|
4135
|
-
this.filter().choices,
|
|
4136
|
-
this.fc.valueChanges.pipe(debounceTime(250)),
|
|
4137
|
-
])
|
|
4215
|
+
combineLatest([this.filter().choices, this.fc.valueChanges.pipe(debounceTime(250))])
|
|
4138
4216
|
.pipe(takeUntilDestroyed(this.destroy$))
|
|
4139
4217
|
.subscribe(([choices, val]) => {
|
|
4140
4218
|
for (const ch of choices) {
|
|
@@ -4168,12 +4246,12 @@ class ModelListSelectMultiFilterComponent {
|
|
|
4168
4246
|
this.filter().enabled = false;
|
|
4169
4247
|
this.list().filters.update();
|
|
4170
4248
|
}
|
|
4171
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
4172
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.
|
|
4249
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ModelListSelectMultiFilterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
4250
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: ModelListSelectMultiFilterComponent, isStandalone: true, selector: "data-model-list-select-multi-filter", inputs: { list: { classPropertyName: "list", publicName: "list", isSignal: true, isRequired: true, transformFunction: null }, filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: true, transformFunction: null }, classes: { classPropertyName: "classes", publicName: "classes", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"filteritem\" [class]=\"filter().displayClasses || classes()\">\n <div\n class=\"trash float-end\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"'D\u00E9sactiver le filtre ' + filter().label\"\n (click)=\"disable()\"\n (keydown.enter)=\"disable()\"\n (keydown.space)=\"$event.preventDefault(); disable()\"\n >\n <i class=\"bi bi-trash\"></i>\n </div>\n <label [attr.for]=\"inputId\">{{ filter().label }}</label>\n <select [attr.id]=\"inputId\" class=\"form-select\" [formControl]=\"fc\">\n <option [ngValue]=\"null\">-- {{ filter().help }} --</option>\n @for (c of filter().choices | async; track c) {\n <option [ngValue]=\"c.value\">{{ c.desc }}</option>\n }\n </select>\n <div class=\"enabled mt-1\">\n @for (e of filter().mcurrent$ | async; track e) {\n <div>\n <i\n class=\"bi bi-trash me-2\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"'Retirer ' + e.desc\"\n (click)=\"unset(e.value, e.desc)\"\n (keydown.enter)=\"unset(e.value, e.desc)\"\n (keydown.space)=\"$event.preventDefault(); unset(e.value, e.desc)\"\n ></i>\n {{ e.desc }}\n </div>\n }\n </div>\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$2.SelectControlValueAccessor, selector: "select:not([multiple]):not([ngNoCva])[formControlName],select:not([multiple]):not([ngNoCva])[formControl],select:not([multiple]):not([ngNoCva])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "pipe", type: AsyncPipe, name: "async" }] });
|
|
4173
4251
|
}
|
|
4174
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
4252
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ModelListSelectMultiFilterComponent, decorators: [{
|
|
4175
4253
|
type: Component,
|
|
4176
|
-
args: [{ selector: 'data-model-list-select-multi-filter', imports: [AsyncPipe, ReactiveFormsModule], template: "
|
|
4254
|
+
args: [{ selector: 'data-model-list-select-multi-filter', imports: [AsyncPipe, ReactiveFormsModule], template: "<div class=\"filteritem\" [class]=\"filter().displayClasses || classes()\">\n <div\n class=\"trash float-end\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"'D\u00E9sactiver le filtre ' + filter().label\"\n (click)=\"disable()\"\n (keydown.enter)=\"disable()\"\n (keydown.space)=\"$event.preventDefault(); disable()\"\n >\n <i class=\"bi bi-trash\"></i>\n </div>\n <label [attr.for]=\"inputId\">{{ filter().label }}</label>\n <select [attr.id]=\"inputId\" class=\"form-select\" [formControl]=\"fc\">\n <option [ngValue]=\"null\">-- {{ filter().help }} --</option>\n @for (c of filter().choices | async; track c) {\n <option [ngValue]=\"c.value\">{{ c.desc }}</option>\n }\n </select>\n <div class=\"enabled mt-1\">\n @for (e of filter().mcurrent$ | async; track e) {\n <div>\n <i\n class=\"bi bi-trash me-2\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"'Retirer ' + e.desc\"\n (click)=\"unset(e.value, e.desc)\"\n (keydown.enter)=\"unset(e.value, e.desc)\"\n (keydown.space)=\"$event.preventDefault(); unset(e.value, e.desc)\"\n ></i>\n {{ e.desc }}\n </div>\n }\n </div>\n</div>\n" }]
|
|
4177
4255
|
}], propDecorators: { list: [{ type: i0.Input, args: [{ isSignal: true, alias: "list", required: true }] }], filter: [{ type: i0.Input, args: [{ isSignal: true, alias: "filter", required: true }] }], classes: [{ type: i0.Input, args: [{ isSignal: true, alias: "classes", required: false }] }] } });
|
|
4178
4256
|
|
|
4179
4257
|
/**
|
|
@@ -4199,8 +4277,9 @@ class Level {
|
|
|
4199
4277
|
this.fc = new FormControl('');
|
|
4200
4278
|
this.choices = choices;
|
|
4201
4279
|
this.subs = this.fc.valueChanges.subscribe((val) => {
|
|
4202
|
-
|
|
4203
|
-
|
|
4280
|
+
const selected = val ? Number(val) : undefined;
|
|
4281
|
+
if (this.selected !== selected) {
|
|
4282
|
+
this.selected = selected;
|
|
4204
4283
|
this.tree.updated(this);
|
|
4205
4284
|
}
|
|
4206
4285
|
});
|
|
@@ -4257,9 +4336,7 @@ class Tree {
|
|
|
4257
4336
|
let values = [];
|
|
4258
4337
|
const levels = this.levels();
|
|
4259
4338
|
if (levels.length === 0) {
|
|
4260
|
-
values = await firstValueFrom(this.qs
|
|
4261
|
-
.filter({ level: levels.length, parent: 'null', ...this.filter })
|
|
4262
|
-
.get());
|
|
4339
|
+
values = await firstValueFrom(this.qs.filter({ level: levels.length, parent: 'null', ...this.filter }).get());
|
|
4263
4340
|
}
|
|
4264
4341
|
else {
|
|
4265
4342
|
const parent = fparent ? fparent : levels[levels.length - 1].selected;
|
|
@@ -4276,7 +4353,7 @@ class Tree {
|
|
|
4276
4353
|
if (values.length > 0) {
|
|
4277
4354
|
const level = new Level(this, levels.length, []);
|
|
4278
4355
|
for (const v of values) {
|
|
4279
|
-
level.choices.push({ value: v.id, desc: this.
|
|
4356
|
+
level.choices.push({ value: v.id, desc: this._label(v) });
|
|
4280
4357
|
}
|
|
4281
4358
|
this.levels.update((ls) => [...ls, level]);
|
|
4282
4359
|
return level;
|
|
@@ -4300,7 +4377,7 @@ class Tree {
|
|
|
4300
4377
|
}
|
|
4301
4378
|
}
|
|
4302
4379
|
this.levels.set(newLevels);
|
|
4303
|
-
this.addLevel();
|
|
4380
|
+
void this.addLevel();
|
|
4304
4381
|
if (level.selected) {
|
|
4305
4382
|
this.changed.next(level.selected);
|
|
4306
4383
|
}
|
|
@@ -4323,16 +4400,26 @@ class Tree {
|
|
|
4323
4400
|
* exceeds `maxLevel` without reaching a root, which signals either a cycle
|
|
4324
4401
|
* or a `maxLevel` set too low.
|
|
4325
4402
|
*/
|
|
4403
|
+
/** Labels one node: `[display]` as a field name, as a function, or `id`. */
|
|
4404
|
+
_label(node) {
|
|
4405
|
+
if (typeof this.display === 'function') {
|
|
4406
|
+
return this.display(node);
|
|
4407
|
+
}
|
|
4408
|
+
if (typeof this.display === 'string') {
|
|
4409
|
+
return String(fieldValues(node)[this.display]);
|
|
4410
|
+
}
|
|
4411
|
+
return String(node.id);
|
|
4412
|
+
}
|
|
4326
4413
|
async prepare(value) {
|
|
4327
4414
|
// console.log('prepare', value);
|
|
4328
4415
|
const levels = [];
|
|
4329
4416
|
let cur = (await firstValueFrom(this.qs.filter({ id: value, ...this.filter }).get()))[0];
|
|
4330
4417
|
levels.push(cur);
|
|
4331
4418
|
let nlev = 0;
|
|
4332
|
-
while (cur
|
|
4419
|
+
while (fieldValues(cur)['parent'] !== null) {
|
|
4333
4420
|
cur = (await firstValueFrom(this.qs
|
|
4334
4421
|
.filter({
|
|
4335
|
-
id: cur
|
|
4422
|
+
id: fieldValues(cur)['parent'],
|
|
4336
4423
|
...this.filter,
|
|
4337
4424
|
})
|
|
4338
4425
|
.get()))[0];
|
|
@@ -4354,7 +4441,9 @@ class Tree {
|
|
|
4354
4441
|
}
|
|
4355
4442
|
}
|
|
4356
4443
|
/** Empty stub; does nothing. */
|
|
4357
|
-
reset() {
|
|
4444
|
+
reset() {
|
|
4445
|
+
// Nothing to reset: the tree rebuilds itself from the filter value.
|
|
4446
|
+
}
|
|
4358
4447
|
}
|
|
4359
4448
|
/**
|
|
4360
4449
|
* Widget for {@link ModelListTreeFilter}: a chain of dropdowns, one per level
|
|
@@ -4371,6 +4460,8 @@ class ModelListTreeFilterComponent {
|
|
|
4371
4460
|
/** CSS classes for the widget's container, overridden by the filter's `displayClasses`. */
|
|
4372
4461
|
classes = input('', /* @ts-ignore */
|
|
4373
4462
|
...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
|
|
4463
|
+
/** Id shared by the label and its control, so clicking the label focuses it. */
|
|
4464
|
+
inputId = uniqueId('data-filter');
|
|
4374
4465
|
/** The dropdown chain rendered by the template; built on init. */
|
|
4375
4466
|
tree;
|
|
4376
4467
|
destroy$ = inject(DestroyRef);
|
|
@@ -4389,9 +4480,7 @@ class ModelListTreeFilterComponent {
|
|
|
4389
4480
|
else {
|
|
4390
4481
|
await this.tree.addLevel();
|
|
4391
4482
|
}
|
|
4392
|
-
this.tree.changed
|
|
4393
|
-
.pipe(debounceTime(250), takeUntilDestroyed(this.destroy$))
|
|
4394
|
-
.subscribe((val) => {
|
|
4483
|
+
this.tree.changed.pipe(debounceTime(250), takeUntilDestroyed(this.destroy$)).subscribe((val) => {
|
|
4395
4484
|
if (val === null) {
|
|
4396
4485
|
filter.clear();
|
|
4397
4486
|
this.list().filters.update();
|
|
@@ -4421,12 +4510,12 @@ class ModelListTreeFilterComponent {
|
|
|
4421
4510
|
this.filter().enabled = false;
|
|
4422
4511
|
this.list().filters.update();
|
|
4423
4512
|
}
|
|
4424
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
4425
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.
|
|
4513
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ModelListTreeFilterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
4514
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: ModelListTreeFilterComponent, isStandalone: true, selector: "data-model-list-tree-filter", inputs: { list: { classPropertyName: "list", publicName: "list", isSignal: true, isRequired: true, transformFunction: null }, filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: true, transformFunction: null }, classes: { classPropertyName: "classes", publicName: "classes", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"filteritem\" [class]=\"filter().displayClasses || classes()\">\n <div\n class=\"trash float-end\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"'D\u00E9sactiver le filtre ' + filter().label\"\n (click)=\"disable()\"\n (keydown.enter)=\"disable()\"\n (keydown.space)=\"$event.preventDefault(); disable()\"\n >\n <i class=\"bi bi-trash\"></i>\n </div>\n <label [attr.for]=\"inputId\">{{ filter().label }}</label>\n @for (l of tree.levels(); track l) {\n <div class=\"levelselect\">\n <select [attr.id]=\"$first ? inputId : null\" class=\"form-select form-select-sm\" [formControl]=\"l.fc\">\n <option value=\"\">{{ filter().help }}</option>\n @for (ch of l.choices; track ch) {\n <option [value]=\"ch.value\">{{ ch.desc }}</option>\n }\n </select>\n </div>\n }\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$2.SelectControlValueAccessor, selector: "select:not([multiple]):not([ngNoCva])[formControlName],select:not([multiple]):not([ngNoCva])[formControl],select:not([multiple]):not([ngNoCva])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }] });
|
|
4426
4515
|
}
|
|
4427
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
4516
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ModelListTreeFilterComponent, decorators: [{
|
|
4428
4517
|
type: Component,
|
|
4429
|
-
args: [{ selector: 'data-model-list-tree-filter', imports: [ReactiveFormsModule], template: "
|
|
4518
|
+
args: [{ selector: 'data-model-list-tree-filter', imports: [ReactiveFormsModule], template: "<div class=\"filteritem\" [class]=\"filter().displayClasses || classes()\">\n <div\n class=\"trash float-end\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"'D\u00E9sactiver le filtre ' + filter().label\"\n (click)=\"disable()\"\n (keydown.enter)=\"disable()\"\n (keydown.space)=\"$event.preventDefault(); disable()\"\n >\n <i class=\"bi bi-trash\"></i>\n </div>\n <label [attr.for]=\"inputId\">{{ filter().label }}</label>\n @for (l of tree.levels(); track l) {\n <div class=\"levelselect\">\n <select [attr.id]=\"$first ? inputId : null\" class=\"form-select form-select-sm\" [formControl]=\"l.fc\">\n <option value=\"\">{{ filter().help }}</option>\n @for (ch of l.choices; track ch) {\n <option [value]=\"ch.value\">{{ ch.desc }}</option>\n }\n </select>\n </div>\n }\n</div>\n" }]
|
|
4430
4519
|
}], propDecorators: { list: [{ type: i0.Input, args: [{ isSignal: true, alias: "list", required: true }] }], filter: [{ type: i0.Input, args: [{ isSignal: true, alias: "filter", required: true }] }], classes: [{ type: i0.Input, args: [{ isSignal: true, alias: "classes", required: false }] }] } });
|
|
4431
4520
|
|
|
4432
4521
|
/**
|
|
@@ -4444,23 +4533,26 @@ class ModelListNumberFilterComponent {
|
|
|
4444
4533
|
/** CSS classes for the widget's container, overridden by the filter's `displayClasses`. */
|
|
4445
4534
|
classes = input('', /* @ts-ignore */
|
|
4446
4535
|
...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
|
|
4536
|
+
/** Id shared by the label and its control, so clicking the label focuses it. */
|
|
4537
|
+
inputId = uniqueId('data-filter');
|
|
4447
4538
|
/** Backs the number input. */
|
|
4448
|
-
fc = new
|
|
4539
|
+
fc = new FormControl(null);
|
|
4449
4540
|
destroy$ = inject(DestroyRef);
|
|
4450
4541
|
/**
|
|
4451
4542
|
* Binds the input to the filter both ways, debouncing the user's input by
|
|
4452
4543
|
* 250 ms before updating the filter and refreshing the list.
|
|
4453
4544
|
*/
|
|
4454
4545
|
ngOnInit() {
|
|
4455
|
-
this.filter()
|
|
4456
|
-
.pipe(takeUntilDestroyed(this.destroy$))
|
|
4546
|
+
this.filter()
|
|
4547
|
+
.valueChanges.pipe(takeUntilDestroyed(this.destroy$))
|
|
4457
4548
|
.subscribe((val) => {
|
|
4458
|
-
|
|
4549
|
+
const value = val.value;
|
|
4550
|
+
this.fc.setValue(value === null ? null : Number(value), {
|
|
4551
|
+
emitEvent: false,
|
|
4552
|
+
});
|
|
4459
4553
|
});
|
|
4460
|
-
this.fc.valueChanges
|
|
4461
|
-
.
|
|
4462
|
-
.subscribe((val) => {
|
|
4463
|
-
if (this.filter().set(val, val)) {
|
|
4554
|
+
this.fc.valueChanges.pipe(debounceTime(250), takeUntilDestroyed(this.destroy$)).subscribe((val) => {
|
|
4555
|
+
if (this.filter().set(val, val === null ? '' : String(val))) {
|
|
4464
4556
|
this.list().filters.update();
|
|
4465
4557
|
}
|
|
4466
4558
|
});
|
|
@@ -4483,12 +4575,12 @@ class ModelListNumberFilterComponent {
|
|
|
4483
4575
|
this.filter().setOperator(eq);
|
|
4484
4576
|
this.list().filters.update();
|
|
4485
4577
|
}
|
|
4486
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
4487
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.
|
|
4578
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ModelListNumberFilterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
4579
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: ModelListNumberFilterComponent, isStandalone: true, selector: "data-model-list-number-filter", inputs: { list: { classPropertyName: "list", publicName: "list", isSignal: true, isRequired: true, transformFunction: null }, filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: true, transformFunction: null }, classes: { classPropertyName: "classes", publicName: "classes", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"filteritem\" [class]=\"filter().displayClasses || classes()\">\n <div\n class=\"trash float-end\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"'D\u00E9sactiver le filtre ' + filter().label\"\n (click)=\"disable()\"\n (keydown.enter)=\"disable()\"\n (keydown.space)=\"$event.preventDefault(); disable()\"\n >\n <div class=\"bi bi-trash\"></div>\n </div>\n <label [attr.for]=\"inputId\">{{ filter().label }}</label>\n <div class=\"input-group\" ngbDropdown>\n <button class=\"btn btn-outline-secondary\" type=\"button\" ngbDropdownToggle>\n <span class=\"me-2\">{{ filter().operator.label }}</span>\n <div class=\"dropdown-menu\" ngbDropdownMenu>\n @for (op of filter().operations; track op) {\n <button\n ngbDropdownItem\n (click)=\"selectOp(op.operator)\"\n [class.text-primary]=\"op.operator === filter().operator.operator\"\n >\n {{ op.label }}\n </button>\n }\n </div>\n </button>\n <input [attr.id]=\"inputId\" class=\"form-control\" type=\"number\" [formControl]=\"fc\" [placeholder]=\"filter().help\" />\n </div>\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.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$2.NumberValueAccessor, selector: "input[type=number]:not([ngNoCva])[formControlName],input[type=number]:not([ngNoCva])[formControl],input[type=number]:not([ngNoCva])[ngModel]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: NgbDropdownModule }, { kind: "directive", type: i1$1.NgbDropdown, selector: "[ngbDropdown]", inputs: ["autoClose", "dropdownClass", "open", "placement", "popperOptions", "container", "display"], outputs: ["openChange"], exportAs: ["ngbDropdown"] }, { kind: "directive", type: i1$1.NgbDropdownToggle, selector: "[ngbDropdownToggle]" }, { kind: "directive", type: i1$1.NgbDropdownMenu, selector: "[ngbDropdownMenu]" }, { kind: "directive", type: i1$1.NgbDropdownItem, selector: "[ngbDropdownItem]", inputs: ["tabindex", "disabled"] }, { kind: "directive", type: i1$1.NgbDropdownButtonItem, selector: "button[ngbDropdownItem]" }] });
|
|
4488
4580
|
}
|
|
4489
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
4581
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ModelListNumberFilterComponent, decorators: [{
|
|
4490
4582
|
type: Component,
|
|
4491
|
-
args: [{ selector: 'data-model-list-number-filter', imports: [ReactiveFormsModule, NgbDropdownModule], template: "
|
|
4583
|
+
args: [{ selector: 'data-model-list-number-filter', imports: [ReactiveFormsModule, NgbDropdownModule], template: "<div class=\"filteritem\" [class]=\"filter().displayClasses || classes()\">\n <div\n class=\"trash float-end\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"'D\u00E9sactiver le filtre ' + filter().label\"\n (click)=\"disable()\"\n (keydown.enter)=\"disable()\"\n (keydown.space)=\"$event.preventDefault(); disable()\"\n >\n <div class=\"bi bi-trash\"></div>\n </div>\n <label [attr.for]=\"inputId\">{{ filter().label }}</label>\n <div class=\"input-group\" ngbDropdown>\n <button class=\"btn btn-outline-secondary\" type=\"button\" ngbDropdownToggle>\n <span class=\"me-2\">{{ filter().operator.label }}</span>\n <div class=\"dropdown-menu\" ngbDropdownMenu>\n @for (op of filter().operations; track op) {\n <button\n ngbDropdownItem\n (click)=\"selectOp(op.operator)\"\n [class.text-primary]=\"op.operator === filter().operator.operator\"\n >\n {{ op.label }}\n </button>\n }\n </div>\n </button>\n <input [attr.id]=\"inputId\" class=\"form-control\" type=\"number\" [formControl]=\"fc\" [placeholder]=\"filter().help\" />\n </div>\n</div>\n" }]
|
|
4492
4584
|
}], propDecorators: { list: [{ type: i0.Input, args: [{ isSignal: true, alias: "list", required: true }] }], filter: [{ type: i0.Input, args: [{ isSignal: true, alias: "filter", required: true }] }], classes: [{ type: i0.Input, args: [{ isSignal: true, alias: "classes", required: false }] }] } });
|
|
4493
4585
|
|
|
4494
4586
|
/**
|
|
@@ -4506,23 +4598,25 @@ class ModelListDateFilterComponent {
|
|
|
4506
4598
|
/** CSS classes for the widget's container, overridden by the filter's `displayClasses`. */
|
|
4507
4599
|
classes = input('', /* @ts-ignore */
|
|
4508
4600
|
...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
|
|
4601
|
+
/** Id shared by the label and its control, so clicking the label focuses it. */
|
|
4602
|
+
inputId = uniqueId('data-filter');
|
|
4509
4603
|
/** Backs the date input. */
|
|
4510
|
-
fc = new FormControl();
|
|
4604
|
+
fc = new FormControl(null);
|
|
4511
4605
|
destroy$ = inject(DestroyRef);
|
|
4512
4606
|
/**
|
|
4513
4607
|
* Binds the input to the filter both ways, debouncing changes by 250 ms
|
|
4514
4608
|
* before refreshing the list.
|
|
4515
4609
|
*/
|
|
4516
4610
|
ngOnInit() {
|
|
4517
|
-
this.filter()
|
|
4518
|
-
.pipe(takeUntilDestroyed(this.destroy$))
|
|
4611
|
+
this.filter()
|
|
4612
|
+
.valueChanges.pipe(takeUntilDestroyed(this.destroy$))
|
|
4519
4613
|
.subscribe((val) => {
|
|
4520
|
-
this.fc.setValue(val.value, {
|
|
4614
|
+
this.fc.setValue(val.value, {
|
|
4615
|
+
emitEvent: false,
|
|
4616
|
+
});
|
|
4521
4617
|
});
|
|
4522
|
-
this.fc.valueChanges
|
|
4523
|
-
.
|
|
4524
|
-
.subscribe((val) => {
|
|
4525
|
-
if (this.filter().set(val, val)) {
|
|
4618
|
+
this.fc.valueChanges.pipe(debounceTime(250), takeUntilDestroyed(this.destroy$)).subscribe((val) => {
|
|
4619
|
+
if (this.filter().set(val, val ?? '')) {
|
|
4526
4620
|
this.list().filters.update();
|
|
4527
4621
|
}
|
|
4528
4622
|
});
|
|
@@ -4535,12 +4629,12 @@ class ModelListDateFilterComponent {
|
|
|
4535
4629
|
this.filter().enabled = false;
|
|
4536
4630
|
this.list().filters.update();
|
|
4537
4631
|
}
|
|
4538
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
4539
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.
|
|
4632
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ModelListDateFilterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
4633
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.3", type: ModelListDateFilterComponent, isStandalone: true, selector: "data-model-list-date-filter", inputs: { list: { classPropertyName: "list", publicName: "list", isSignal: true, isRequired: true, transformFunction: null }, filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: true, transformFunction: null }, classes: { classPropertyName: "classes", publicName: "classes", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"filteritem\" [class]=\"filter().displayClasses || classes()\">\n <div\n class=\"trash float-end\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"'D\u00E9sactiver le filtre ' + filter().label\"\n (click)=\"disable()\"\n (keydown.enter)=\"disable()\"\n (keydown.space)=\"$event.preventDefault(); disable()\"\n >\n <i class=\"bi bi-trash\"></i>\n </div>\n <label [attr.for]=\"inputId\">{{ filter().label }}</label>\n <input [attr.id]=\"inputId\" class=\"form-control\" type=\"date\" [formControl]=\"fc\" [placeholder]=\"filter().help\" />\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.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$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }] });
|
|
4540
4634
|
}
|
|
4541
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
4635
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ModelListDateFilterComponent, decorators: [{
|
|
4542
4636
|
type: Component,
|
|
4543
|
-
args: [{ selector: 'data-model-list-date-filter', imports: [ReactiveFormsModule], template: "
|
|
4637
|
+
args: [{ selector: 'data-model-list-date-filter', imports: [ReactiveFormsModule], template: "<div class=\"filteritem\" [class]=\"filter().displayClasses || classes()\">\n <div\n class=\"trash float-end\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"'D\u00E9sactiver le filtre ' + filter().label\"\n (click)=\"disable()\"\n (keydown.enter)=\"disable()\"\n (keydown.space)=\"$event.preventDefault(); disable()\"\n >\n <i class=\"bi bi-trash\"></i>\n </div>\n <label [attr.for]=\"inputId\">{{ filter().label }}</label>\n <input [attr.id]=\"inputId\" class=\"form-control\" type=\"date\" [formControl]=\"fc\" [placeholder]=\"filter().help\" />\n</div>\n" }]
|
|
4544
4638
|
}], propDecorators: { list: [{ type: i0.Input, args: [{ isSignal: true, alias: "list", required: true }] }], filter: [{ type: i0.Input, args: [{ isSignal: true, alias: "filter", required: true }] }], classes: [{ type: i0.Input, args: [{ isSignal: true, alias: "classes", required: false }] }] } });
|
|
4545
4639
|
|
|
4546
4640
|
// SEE: register filter components and load them dynamically to allow user defined filters
|
|
@@ -4571,10 +4665,10 @@ class ModelListFiltersComponent {
|
|
|
4571
4665
|
*/
|
|
4572
4666
|
itemClasses = input('', /* @ts-ignore */
|
|
4573
4667
|
...(ngDevMode ? [{ debugName: "itemClasses" }] : /* istanbul ignore next */ []));
|
|
4574
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
4575
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.
|
|
4668
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ModelListFiltersComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
4669
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: ModelListFiltersComponent, isStandalone: true, selector: "data-model-list-filters", inputs: { list: { classPropertyName: "list", publicName: "list", isSignal: true, isRequired: true, transformFunction: null }, containerClasses: { classPropertyName: "containerClasses", publicName: "containerClasses", isSignal: true, isRequired: false, transformFunction: null }, itemClasses: { classPropertyName: "itemClasses", publicName: "itemClasses", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div [class]=\"containerClasses()\">\n @for (f of list().filters.enabled | async; track f) {\n @switch (f.type) {\n @case (\"autocomplete\") {\n <data-model-list-autocomplete-filter\n [filter]=\"$any(f)\"\n [list]=\"list()\"\n [class]=\"itemClasses()\"\n ></data-model-list-autocomplete-filter>\n }\n @case (\"autocompletemulti\") {\n <data-model-list-autocomplete-multi-filter\n [filter]=\"$any(f)\"\n [list]=\"list()\"\n [class]=\"itemClasses()\"\n ></data-model-list-autocomplete-multi-filter>\n }\n @case (\"datetime\") {\n <data-model-list-datetime-filter\n [filter]=\"$any(f)\"\n [list]=\"list()\"\n [class]=\"itemClasses()\"\n ></data-model-list-datetime-filter>\n }\n @case (\"date\") {\n <data-model-list-date-filter\n [filter]=\"$any(f)\"\n [list]=\"list()\"\n [class]=\"itemClasses()\"\n ></data-model-list-date-filter>\n }\n @case (\"datetimerange\") {\n <data-model-list-datetime-range-filter\n [filter]=\"$any(f)\"\n [list]=\"list()\"\n [class]=\"itemClasses()\"\n ></data-model-list-datetime-range-filter>\n }\n @case (\"flags\") {\n <data-model-list-flags-filter\n [filter]=\"$any(f)\"\n [list]=\"list()\"\n [class]=\"itemClasses()\"\n ></data-model-list-flags-filter>\n }\n @case (\"geodistance\") {\n <data-model-list-geodistance-filter\n [filter]=\"$any(f)\"\n [list]=\"list()\"\n [class]=\"itemClasses()\"\n ></data-model-list-geodistance-filter>\n }\n @case (\"number\") {\n <data-model-list-number-filter\n [filter]=\"$any(f)\"\n [list]=\"list()\"\n [class]=\"itemClasses()\"\n ></data-model-list-number-filter>\n }\n @case (\"select\") {\n <data-model-list-select-filter\n [filter]=\"$any(f)\"\n [list]=\"list()\"\n [class]=\"itemClasses()\"\n ></data-model-list-select-filter>\n }\n @case (\"selectmulti\") {\n <data-model-list-select-multi-filter\n [filter]=\"$any(f)\"\n [list]=\"list()\"\n [class]=\"itemClasses()\"\n ></data-model-list-select-multi-filter>\n }\n @case (\"text\") {\n <data-model-list-text-filter\n [filter]=\"$any(f)\"\n [list]=\"list()\"\n [class]=\"itemClasses()\"\n ></data-model-list-text-filter>\n }\n @case (\"tree\") {\n <data-model-list-tree-filter\n [filter]=\"$any(f)\"\n [list]=\"list()\"\n [class]=\"itemClasses()\"\n ></data-model-list-tree-filter>\n }\n }\n }\n</div>\n", styles: [""], dependencies: [{ kind: "component", type: ModelListTextFilterComponent, selector: "data-model-list-text-filter", inputs: ["list", "filter", "classes"] }, { kind: "component", type: ModelListNumberFilterComponent, selector: "data-model-list-number-filter", inputs: ["list", "filter", "classes"] }, { kind: "component", type: ModelListAutocompleteFilterComponent, selector: "data-model-list-autocomplete-filter", inputs: ["list", "filter", "classes"] }, { kind: "component", type: ModelListAutocompleteMultiFilterComponent, selector: "data-model-list-autocomplete-multi-filter" }, { kind: "component", type: ModelListDatetimeFilterComponent, selector: "data-model-list-datetime-filter", inputs: ["list", "filter", "classes"] }, { kind: "component", type: ModelListDateFilterComponent, selector: "data-model-list-date-filter", inputs: ["list", "filter", "classes"] }, { kind: "component", type: ModelListDatetimeRangeFilterComponent, selector: "data-model-list-datetime-range-filter", inputs: ["list", "filter", "classes"] }, { kind: "component", type: ModelListFlagsFilterComponent, selector: "data-model-list-flags-filter", inputs: ["list", "filter", "classes"] }, { kind: "component", type: ModelListGeodistanceFilterComponent, selector: "data-model-list-geodistance-filter", inputs: ["list", "filter", "classes"] }, { kind: "component", type: ModelListSelectFilterComponent, selector: "data-model-list-select-filter", inputs: ["list", "filter", "classes"] }, { kind: "component", type: ModelListSelectMultiFilterComponent, selector: "data-model-list-select-multi-filter", inputs: ["list", "filter", "classes"] }, { kind: "component", type: ModelListTreeFilterComponent, selector: "data-model-list-tree-filter", inputs: ["list", "filter", "classes"] }, { kind: "pipe", type: AsyncPipe, name: "async" }] });
|
|
4576
4670
|
}
|
|
4577
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
4671
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ModelListFiltersComponent, decorators: [{
|
|
4578
4672
|
type: Component,
|
|
4579
4673
|
args: [{ selector: 'data-model-list-filters', imports: [
|
|
4580
4674
|
AsyncPipe,
|
|
@@ -4590,7 +4684,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
|
|
|
4590
4684
|
ModelListSelectFilterComponent,
|
|
4591
4685
|
ModelListSelectMultiFilterComponent,
|
|
4592
4686
|
ModelListTreeFilterComponent,
|
|
4593
|
-
], template: "
|
|
4687
|
+
], template: "<div [class]=\"containerClasses()\">\n @for (f of list().filters.enabled | async; track f) {\n @switch (f.type) {\n @case (\"autocomplete\") {\n <data-model-list-autocomplete-filter\n [filter]=\"$any(f)\"\n [list]=\"list()\"\n [class]=\"itemClasses()\"\n ></data-model-list-autocomplete-filter>\n }\n @case (\"autocompletemulti\") {\n <data-model-list-autocomplete-multi-filter\n [filter]=\"$any(f)\"\n [list]=\"list()\"\n [class]=\"itemClasses()\"\n ></data-model-list-autocomplete-multi-filter>\n }\n @case (\"datetime\") {\n <data-model-list-datetime-filter\n [filter]=\"$any(f)\"\n [list]=\"list()\"\n [class]=\"itemClasses()\"\n ></data-model-list-datetime-filter>\n }\n @case (\"date\") {\n <data-model-list-date-filter\n [filter]=\"$any(f)\"\n [list]=\"list()\"\n [class]=\"itemClasses()\"\n ></data-model-list-date-filter>\n }\n @case (\"datetimerange\") {\n <data-model-list-datetime-range-filter\n [filter]=\"$any(f)\"\n [list]=\"list()\"\n [class]=\"itemClasses()\"\n ></data-model-list-datetime-range-filter>\n }\n @case (\"flags\") {\n <data-model-list-flags-filter\n [filter]=\"$any(f)\"\n [list]=\"list()\"\n [class]=\"itemClasses()\"\n ></data-model-list-flags-filter>\n }\n @case (\"geodistance\") {\n <data-model-list-geodistance-filter\n [filter]=\"$any(f)\"\n [list]=\"list()\"\n [class]=\"itemClasses()\"\n ></data-model-list-geodistance-filter>\n }\n @case (\"number\") {\n <data-model-list-number-filter\n [filter]=\"$any(f)\"\n [list]=\"list()\"\n [class]=\"itemClasses()\"\n ></data-model-list-number-filter>\n }\n @case (\"select\") {\n <data-model-list-select-filter\n [filter]=\"$any(f)\"\n [list]=\"list()\"\n [class]=\"itemClasses()\"\n ></data-model-list-select-filter>\n }\n @case (\"selectmulti\") {\n <data-model-list-select-multi-filter\n [filter]=\"$any(f)\"\n [list]=\"list()\"\n [class]=\"itemClasses()\"\n ></data-model-list-select-multi-filter>\n }\n @case (\"text\") {\n <data-model-list-text-filter\n [filter]=\"$any(f)\"\n [list]=\"list()\"\n [class]=\"itemClasses()\"\n ></data-model-list-text-filter>\n }\n @case (\"tree\") {\n <data-model-list-tree-filter\n [filter]=\"$any(f)\"\n [list]=\"list()\"\n [class]=\"itemClasses()\"\n ></data-model-list-tree-filter>\n }\n }\n }\n</div>\n" }]
|
|
4594
4688
|
}], propDecorators: { list: [{ type: i0.Input, args: [{ isSignal: true, alias: "list", required: true }] }], containerClasses: [{ type: i0.Input, args: [{ isSignal: true, alias: "containerClasses", required: false }] }], itemClasses: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemClasses", required: false }] }] } });
|
|
4595
4689
|
|
|
4596
4690
|
/**
|
|
@@ -4727,7 +4821,7 @@ class ModelListAutocompleteFilter extends ModelListFilter {
|
|
|
4727
4821
|
this.display = params.display;
|
|
4728
4822
|
this.searchparam = params.searchparam ? params.searchparam : 'search';
|
|
4729
4823
|
if (!params.collection && !params.queryset) {
|
|
4730
|
-
throw 'Missing related data (collection or queryset)';
|
|
4824
|
+
throw new Error('Missing related data (collection or queryset)');
|
|
4731
4825
|
}
|
|
4732
4826
|
this.collection = params.collection;
|
|
4733
4827
|
if (params.collection && !params.queryset) {
|
|
@@ -4809,12 +4903,12 @@ class ModelListDatetimeFilter extends ModelListFilter {
|
|
|
4809
4903
|
/** Sets the filter type to `datetime`. */
|
|
4810
4904
|
constructor(params) {
|
|
4811
4905
|
super(params);
|
|
4812
|
-
this.type =
|
|
4813
|
-
if (this.label ==
|
|
4814
|
-
this.label =
|
|
4906
|
+
this.type = 'datetime';
|
|
4907
|
+
if (this.label == '') {
|
|
4908
|
+
this.label = 'Sélectionnez par date/heure';
|
|
4815
4909
|
}
|
|
4816
|
-
if (this.help ==
|
|
4817
|
-
this.help =
|
|
4910
|
+
if (this.help == '') {
|
|
4911
|
+
this.help = 'Date/heure cible';
|
|
4818
4912
|
}
|
|
4819
4913
|
}
|
|
4820
4914
|
}
|
|
@@ -4879,12 +4973,12 @@ class ModelListDatetimerangeFilter extends ModelListFilter {
|
|
|
4879
4973
|
/** Sets the filter type to `datetimerange`. */
|
|
4880
4974
|
constructor(params) {
|
|
4881
4975
|
super(params);
|
|
4882
|
-
this.type =
|
|
4883
|
-
if (this.label ==
|
|
4884
|
-
this.label =
|
|
4976
|
+
this.type = 'datetimerange';
|
|
4977
|
+
if (this.label == '') {
|
|
4978
|
+
this.label = 'Sélectionnez par intervalle de date/heure';
|
|
4885
4979
|
}
|
|
4886
|
-
if (this.help ==
|
|
4887
|
-
this.help =
|
|
4980
|
+
if (this.help == '') {
|
|
4981
|
+
this.help = 'Date/heure';
|
|
4888
4982
|
}
|
|
4889
4983
|
}
|
|
4890
4984
|
}
|
|
@@ -4940,7 +5034,7 @@ class ModelListFlagsFilter extends ModelListFilter {
|
|
|
4940
5034
|
this.help = "Nom de l'étiquette";
|
|
4941
5035
|
}
|
|
4942
5036
|
if (!params.collection) {
|
|
4943
|
-
throw 'Missing collection for flags filter';
|
|
5037
|
+
throw new Error('Missing collection for flags filter');
|
|
4944
5038
|
}
|
|
4945
5039
|
this.collection = params.collection;
|
|
4946
5040
|
if (params.action) {
|
|
@@ -5080,7 +5174,7 @@ class ModelListNumberFilter extends ModelListFilter {
|
|
|
5080
5174
|
* {@link ModelListFilters.update} afterwards to re-run the query.
|
|
5081
5175
|
*/
|
|
5082
5176
|
setOperator(op) {
|
|
5083
|
-
for (
|
|
5177
|
+
for (const o of this.operations) {
|
|
5084
5178
|
if (op === o.operator) {
|
|
5085
5179
|
this.operator = o;
|
|
5086
5180
|
}
|
|
@@ -5163,14 +5257,14 @@ class ModelListSelectFilter extends ModelListFilter {
|
|
|
5163
5257
|
this.help = 'Choix par liste déroulante';
|
|
5164
5258
|
}
|
|
5165
5259
|
if (!params.choices && !params.model) {
|
|
5166
|
-
throw 'Missing choices for select filter';
|
|
5260
|
+
throw new Error('Missing choices for select filter');
|
|
5167
5261
|
}
|
|
5168
5262
|
if (!params.choices && params.model) {
|
|
5169
5263
|
const m = new params.model();
|
|
5170
5264
|
const f = m.FM(params.mfield || params.field);
|
|
5171
5265
|
const ch = f.choices;
|
|
5172
5266
|
if (!ch) {
|
|
5173
|
-
throw 'No choices found for model/field';
|
|
5267
|
+
throw new Error('No choices found for model/field');
|
|
5174
5268
|
}
|
|
5175
5269
|
this.choices = of(ch);
|
|
5176
5270
|
}
|
|
@@ -5188,7 +5282,9 @@ class ModelListSelectFilter extends ModelListFilter {
|
|
|
5188
5282
|
}
|
|
5189
5283
|
}
|
|
5190
5284
|
/** Empty stub; the constructor applies `default` itself. Does nothing. */
|
|
5191
|
-
setDefault() {
|
|
5285
|
+
setDefault() {
|
|
5286
|
+
// The choices carry their own default; nothing to seed here.
|
|
5287
|
+
}
|
|
5192
5288
|
}
|
|
5193
5289
|
|
|
5194
5290
|
/**
|
|
@@ -5223,15 +5319,6 @@ class ModelListSelectFilter extends ModelListFilter {
|
|
|
5223
5319
|
class ModelListSelectMultiFilter extends ModelListSelectFilter {
|
|
5224
5320
|
/** Always `true`: this filter joins its values into one query parameter. */
|
|
5225
5321
|
multi = true;
|
|
5226
|
-
// `default` is inherited from ModelListFilter (typed `any`) and set by the
|
|
5227
|
-
// base constructor. We intentionally do NOT re-declare it here: under
|
|
5228
|
-
// useDefineForClassFields:true a field re-declaration without initializer
|
|
5229
|
-
// would clobber the base-constructor value back to undefined.
|
|
5230
|
-
/**
|
|
5231
|
-
* Switches the filter type to `selectmulti` and selects each `default`
|
|
5232
|
-
* choice. The parent constructor has already resolved the choices and
|
|
5233
|
-
* enforced the `choices`-or-`model` requirement.
|
|
5234
|
-
*/
|
|
5235
5322
|
constructor(params) {
|
|
5236
5323
|
super(params);
|
|
5237
5324
|
this.type = 'selectmulti';
|
|
@@ -5402,9 +5489,7 @@ class BanAdapter {
|
|
|
5402
5489
|
* `score` is applied.
|
|
5403
5490
|
*/
|
|
5404
5491
|
search(text) {
|
|
5405
|
-
return this._http
|
|
5406
|
-
.get(`${this._baseUrl}`, { params: { q: text } })
|
|
5407
|
-
.pipe(map((r) => {
|
|
5492
|
+
return this._http.get(`${this._baseUrl}`, { params: { q: text } }).pipe(map((r) => {
|
|
5408
5493
|
const out = [];
|
|
5409
5494
|
for (const f of r.features) {
|
|
5410
5495
|
out.push({
|
|
@@ -5488,23 +5573,19 @@ class ModelListPaginatorComponent {
|
|
|
5488
5573
|
this.perPageControl.setValue(this.pageSize(), { emitEvent: false });
|
|
5489
5574
|
}
|
|
5490
5575
|
});
|
|
5491
|
-
this.perPageControl.valueChanges
|
|
5492
|
-
.
|
|
5493
|
-
.subscribe((count) => {
|
|
5494
|
-
list.paginator.setPageSize(count);
|
|
5576
|
+
this.perPageControl.valueChanges.pipe(takeUntilDestroyed(this.destroy$)).subscribe((count) => {
|
|
5577
|
+
list.paginator.setPageSize(Number(count));
|
|
5495
5578
|
});
|
|
5496
|
-
this.directAccess.valueChanges
|
|
5497
|
-
.pipe(takeUntilDestroyed(this.destroy$), debounceTime(400))
|
|
5498
|
-
.subscribe((count) => {
|
|
5579
|
+
this.directAccess.valueChanges.pipe(takeUntilDestroyed(this.destroy$), debounceTime(400)).subscribe((count) => {
|
|
5499
5580
|
list.paginator.setPage(+count);
|
|
5500
5581
|
});
|
|
5501
5582
|
}
|
|
5502
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
5503
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.
|
|
5583
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ModelListPaginatorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
5584
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: ModelListPaginatorComponent, isStandalone: true, selector: "data-model-list-paginator", inputs: { list: { classPropertyName: "list", publicName: "list", isSignal: true, isRequired: true, transformFunction: null }, maxPages: { classPropertyName: "maxPages", publicName: "maxPages", isSignal: true, isRequired: false, transformFunction: null }, hide: { classPropertyName: "hide", publicName: "hide", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (!hide()) {\n <div class=\"row\">\n <div class=\"col-sm-4\">\n <select class=\"form-select perpage\" [formControl]=\"perPageControl\">\n @if (maxPages() >= 10) {\n <option value=\"10\">10 / page</option>\n }\n @if (maxPages() >= 20) {\n <option value=\"20\">20 / page</option>\n }\n @if (maxPages() >= 50) {\n <option value=\"50\">50 / page</option>\n }\n @if (maxPages() >= 100) {\n <option value=\"100\">100 / page</option>\n }\n @if (maxPages() >= 200) {\n <option value=\"200\">200 / page</option>\n }\n @if (maxPages() >= 500) {\n <option value=\"500\">500 / page</option>\n }\n @if (maxPages() >= 1000) {\n <option value=\"1000\">1000 / page</option>\n }\n @if (maxPages() >= 2000) {\n <option value=\"2000\">2000 / page</option>\n }\n @if (maxPages() >= 5000) {\n <option value=\"5000\">5000 / page</option>\n }\n @if (maxPages() >= 10000) {\n <option value=\"10000\">10000 / page</option>\n }\n </select>\n </div>\n @if (list()) {\n <div class=\"col-sm-5 pagination\">\n <div class=\"text-xs-center\">\n <ngb-pagination\n [pageSize]=\"pageSize()\"\n [collectionSize]=\"curCount()\"\n [page]=\"curPage()\"\n (pageChange)=\"onPageChange($event)\"\n [maxSize]=\"5\"\n [rotate]=\"true\"\n ></ngb-pagination>\n </div>\n </div>\n }\n <div class=\"col-sm-3 results\">\n <div>\n {{ curCount() }} r\u00E9sultats -\n <span\n (click)=\"showDirectAccess = !showDirectAccess\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-expanded]=\"showDirectAccess\"\n (keydown.enter)=\"showDirectAccess = !showDirectAccess\"\n (keydown.space)=\"$event.preventDefault(); showDirectAccess = !showDirectAccess\"\n >\n acces direct\n </span>\n </div>\n @if (showDirectAccess) {\n <div>\n <input class=\"form-control\" [formControl]=\"directAccess\" type=\"number\" placeholder=\"Aller \u00E0 la page\" />\n </div>\n }\n </div>\n </div>\n}\n", styles: [""], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$2.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$2.NumberValueAccessor, selector: "input[type=number]:not([ngNoCva])[formControlName],input[type=number]:not([ngNoCva])[formControl],input[type=number]:not([ngNoCva])[ngModel]" }, { kind: "directive", type: i1$2.SelectControlValueAccessor, selector: "select:not([multiple]):not([ngNoCva])[formControlName],select:not([multiple]):not([ngNoCva])[formControl],select:not([multiple]):not([ngNoCva])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: NgbPaginationModule }, { kind: "component", type: i1$1.NgbPagination, selector: "ngb-pagination", inputs: ["disabled", "boundaryLinks", "directionLinks", "ellipses", "rotate", "collectionSize", "maxSize", "page", "pageSize", "size"], outputs: ["pageChange"] }] });
|
|
5504
5585
|
}
|
|
5505
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
5586
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ModelListPaginatorComponent, decorators: [{
|
|
5506
5587
|
type: Component,
|
|
5507
|
-
args: [{ selector: 'data-model-list-paginator', imports: [ReactiveFormsModule, NgbPaginationModule], template: "
|
|
5588
|
+
args: [{ selector: 'data-model-list-paginator', imports: [ReactiveFormsModule, NgbPaginationModule], template: "@if (!hide()) {\n <div class=\"row\">\n <div class=\"col-sm-4\">\n <select class=\"form-select perpage\" [formControl]=\"perPageControl\">\n @if (maxPages() >= 10) {\n <option value=\"10\">10 / page</option>\n }\n @if (maxPages() >= 20) {\n <option value=\"20\">20 / page</option>\n }\n @if (maxPages() >= 50) {\n <option value=\"50\">50 / page</option>\n }\n @if (maxPages() >= 100) {\n <option value=\"100\">100 / page</option>\n }\n @if (maxPages() >= 200) {\n <option value=\"200\">200 / page</option>\n }\n @if (maxPages() >= 500) {\n <option value=\"500\">500 / page</option>\n }\n @if (maxPages() >= 1000) {\n <option value=\"1000\">1000 / page</option>\n }\n @if (maxPages() >= 2000) {\n <option value=\"2000\">2000 / page</option>\n }\n @if (maxPages() >= 5000) {\n <option value=\"5000\">5000 / page</option>\n }\n @if (maxPages() >= 10000) {\n <option value=\"10000\">10000 / page</option>\n }\n </select>\n </div>\n @if (list()) {\n <div class=\"col-sm-5 pagination\">\n <div class=\"text-xs-center\">\n <ngb-pagination\n [pageSize]=\"pageSize()\"\n [collectionSize]=\"curCount()\"\n [page]=\"curPage()\"\n (pageChange)=\"onPageChange($event)\"\n [maxSize]=\"5\"\n [rotate]=\"true\"\n ></ngb-pagination>\n </div>\n </div>\n }\n <div class=\"col-sm-3 results\">\n <div>\n {{ curCount() }} r\u00E9sultats -\n <span\n (click)=\"showDirectAccess = !showDirectAccess\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-expanded]=\"showDirectAccess\"\n (keydown.enter)=\"showDirectAccess = !showDirectAccess\"\n (keydown.space)=\"$event.preventDefault(); showDirectAccess = !showDirectAccess\"\n >\n acces direct\n </span>\n </div>\n @if (showDirectAccess) {\n <div>\n <input class=\"form-control\" [formControl]=\"directAccess\" type=\"number\" placeholder=\"Aller \u00E0 la page\" />\n </div>\n }\n </div>\n </div>\n}\n" }]
|
|
5508
5589
|
}], propDecorators: { list: [{ type: i0.Input, args: [{ isSignal: true, alias: "list", required: true }] }], maxPages: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxPages", required: false }] }], hide: [{ type: i0.Input, args: [{ isSignal: true, alias: "hide", required: false }] }] } });
|
|
5509
5590
|
|
|
5510
5591
|
/**
|
|
@@ -5534,14 +5615,14 @@ class ChoicePipe {
|
|
|
5534
5615
|
if (!value) {
|
|
5535
5616
|
return '-';
|
|
5536
5617
|
}
|
|
5537
|
-
const fvalue = value[field];
|
|
5618
|
+
const fvalue = fieldValues(value)[field];
|
|
5538
5619
|
if (mode === 'code') {
|
|
5539
|
-
return
|
|
5620
|
+
return asText(fvalue);
|
|
5540
5621
|
}
|
|
5541
5622
|
const manager = value.FM(field);
|
|
5542
5623
|
const choices = manager.choices;
|
|
5543
5624
|
if (!choices) {
|
|
5544
|
-
return
|
|
5625
|
+
return asText(fvalue);
|
|
5545
5626
|
}
|
|
5546
5627
|
for (const ch of choices) {
|
|
5547
5628
|
if (ch.value === fvalue) {
|
|
@@ -5549,16 +5630,16 @@ class ChoicePipe {
|
|
|
5549
5630
|
return ch.desc;
|
|
5550
5631
|
}
|
|
5551
5632
|
else {
|
|
5552
|
-
return `[${fvalue}] ${ch.desc}`;
|
|
5633
|
+
return `[${asText(fvalue)}] ${ch.desc}`;
|
|
5553
5634
|
}
|
|
5554
5635
|
}
|
|
5555
5636
|
}
|
|
5556
|
-
return `[${fvalue}] ??`;
|
|
5637
|
+
return `[${asText(fvalue)}] ??`;
|
|
5557
5638
|
}
|
|
5558
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
5559
|
-
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "22.1.
|
|
5639
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ChoicePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
5640
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "22.1.3", ngImport: i0, type: ChoicePipe, isStandalone: true, name: "choice" });
|
|
5560
5641
|
}
|
|
5561
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
5642
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ChoicePipe, decorators: [{
|
|
5562
5643
|
type: Pipe,
|
|
5563
5644
|
args: [{
|
|
5564
5645
|
name: 'choice',
|
|
@@ -5594,14 +5675,14 @@ class PChoicePipe {
|
|
|
5594
5675
|
return '-';
|
|
5595
5676
|
}
|
|
5596
5677
|
// Use value from input, not from field
|
|
5597
|
-
const fvalue = value; //- (model
|
|
5678
|
+
const fvalue = value; //- fieldValues(model)[field];
|
|
5598
5679
|
if (mode === 'code') {
|
|
5599
|
-
return
|
|
5680
|
+
return asText(fvalue);
|
|
5600
5681
|
}
|
|
5601
5682
|
const manager = model.FM(field);
|
|
5602
5683
|
const choices = manager.choices;
|
|
5603
5684
|
if (!choices) {
|
|
5604
|
-
return
|
|
5685
|
+
return asText(fvalue);
|
|
5605
5686
|
}
|
|
5606
5687
|
for (const ch of choices) {
|
|
5607
5688
|
if (ch.value === fvalue) {
|
|
@@ -5609,16 +5690,16 @@ class PChoicePipe {
|
|
|
5609
5690
|
return ch.desc;
|
|
5610
5691
|
}
|
|
5611
5692
|
else {
|
|
5612
|
-
return `[${fvalue}] ${ch.desc}`;
|
|
5693
|
+
return `[${asText(fvalue)}] ${ch.desc}`;
|
|
5613
5694
|
}
|
|
5614
5695
|
}
|
|
5615
5696
|
}
|
|
5616
|
-
return `[${fvalue}] ??`;
|
|
5697
|
+
return `[${asText(fvalue)}] ??`;
|
|
5617
5698
|
}
|
|
5618
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
5619
|
-
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "22.1.
|
|
5699
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: PChoicePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
5700
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "22.1.3", ngImport: i0, type: PChoicePipe, isStandalone: true, name: "pchoice" });
|
|
5620
5701
|
}
|
|
5621
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
5702
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: PChoicePipe, decorators: [{
|
|
5622
5703
|
type: Pipe,
|
|
5623
5704
|
args: [{
|
|
5624
5705
|
name: 'pchoice',
|
|
@@ -5679,7 +5760,7 @@ class FactorPipe {
|
|
|
5679
5760
|
return null;
|
|
5680
5761
|
}
|
|
5681
5762
|
locale = locale || this._locale;
|
|
5682
|
-
const fvalue = value[field];
|
|
5763
|
+
const fvalue = fieldValues(value)[field];
|
|
5683
5764
|
if (!isValue(fvalue))
|
|
5684
5765
|
return null;
|
|
5685
5766
|
const manager = value.FM(field);
|
|
@@ -5688,10 +5769,10 @@ class FactorPipe {
|
|
|
5688
5769
|
const num = strToNumber(fvalue);
|
|
5689
5770
|
return formatNumber(num / factor, locale, digitsInfo);
|
|
5690
5771
|
}
|
|
5691
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
5692
|
-
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "22.1.
|
|
5772
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: FactorPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
5773
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "22.1.3", ngImport: i0, type: FactorPipe, isStandalone: true, name: "factor" });
|
|
5693
5774
|
}
|
|
5694
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
5775
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: FactorPipe, decorators: [{
|
|
5695
5776
|
type: Pipe,
|
|
5696
5777
|
args: [{
|
|
5697
5778
|
name: 'factor',
|
|
@@ -5726,7 +5807,7 @@ class PFactorPipe {
|
|
|
5726
5807
|
return null;
|
|
5727
5808
|
locale = locale || this._locale;
|
|
5728
5809
|
// Use value from input, not from model
|
|
5729
|
-
const fvalue = value; // (model
|
|
5810
|
+
const fvalue = value; // fieldValues(model)[field];
|
|
5730
5811
|
if (!isValue(fvalue))
|
|
5731
5812
|
return null;
|
|
5732
5813
|
const manager = model.FM(field);
|
|
@@ -5735,10 +5816,10 @@ class PFactorPipe {
|
|
|
5735
5816
|
const num = strToNumber(fvalue);
|
|
5736
5817
|
return formatNumber(num / factor, locale, digitsInfo);
|
|
5737
5818
|
}
|
|
5738
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
5739
|
-
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "22.1.
|
|
5819
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: PFactorPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
5820
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "22.1.3", ngImport: i0, type: PFactorPipe, isStandalone: true, name: "pfactor" });
|
|
5740
5821
|
}
|
|
5741
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
5822
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: PFactorPipe, decorators: [{
|
|
5742
5823
|
type: Pipe,
|
|
5743
5824
|
args: [{
|
|
5744
5825
|
name: 'pfactor',
|
|
@@ -5776,7 +5857,7 @@ class FactorcPipe {
|
|
|
5776
5857
|
transform(value, field, currencyCode, display, digitsInfo, locale) {
|
|
5777
5858
|
if (!value)
|
|
5778
5859
|
return null;
|
|
5779
|
-
const fvalue = value[field];
|
|
5860
|
+
const fvalue = fieldValues(value)[field];
|
|
5780
5861
|
if (!isValue(fvalue))
|
|
5781
5862
|
return null;
|
|
5782
5863
|
locale = locale || this._locale;
|
|
@@ -5797,10 +5878,10 @@ class FactorcPipe {
|
|
|
5797
5878
|
const num = strToNumber(fvalue);
|
|
5798
5879
|
return formatCurrency(num / factor, locale, currency, currencyCode, digitsInfo);
|
|
5799
5880
|
}
|
|
5800
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
5801
|
-
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "22.1.
|
|
5881
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: FactorcPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
5882
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "22.1.3", ngImport: i0, type: FactorcPipe, isStandalone: true, name: "factorc" });
|
|
5802
5883
|
}
|
|
5803
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
5884
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: FactorcPipe, decorators: [{
|
|
5804
5885
|
type: Pipe,
|
|
5805
5886
|
args: [{
|
|
5806
5887
|
name: 'factorc',
|
|
@@ -5838,7 +5919,7 @@ class PFactorcPipe {
|
|
|
5838
5919
|
if (!value)
|
|
5839
5920
|
return null;
|
|
5840
5921
|
// Use value from input, not from model
|
|
5841
|
-
const fvalue = value; // (model
|
|
5922
|
+
const fvalue = value; // fieldValues(model)[field];
|
|
5842
5923
|
if (!isValue(fvalue)) {
|
|
5843
5924
|
return null;
|
|
5844
5925
|
}
|
|
@@ -5860,10 +5941,10 @@ class PFactorcPipe {
|
|
|
5860
5941
|
const num = strToNumber(fvalue);
|
|
5861
5942
|
return formatCurrency(num / factor, locale, currency, currencyCode, digitsInfo);
|
|
5862
5943
|
}
|
|
5863
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
5864
|
-
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "22.1.
|
|
5944
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: PFactorcPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
5945
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "22.1.3", ngImport: i0, type: PFactorcPipe, isStandalone: true, name: "pfactorc" });
|
|
5865
5946
|
}
|
|
5866
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
5947
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: PFactorcPipe, decorators: [{
|
|
5867
5948
|
type: Pipe,
|
|
5868
5949
|
args: [{
|
|
5869
5950
|
name: 'pfactorc',
|
|
@@ -5930,6 +6011,12 @@ class FkselectComponent {
|
|
|
5930
6011
|
/** Label shown next to the control. */
|
|
5931
6012
|
label = input('', /* @ts-ignore */
|
|
5932
6013
|
...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
6014
|
+
/**
|
|
6015
|
+
* Id put on the search input, and pointed at by `[label]`'s `for`. Defaults
|
|
6016
|
+
* to a generated one; dispedit passes its own so its label drives this input.
|
|
6017
|
+
*/
|
|
6018
|
+
inputId = input(uniqueId('data-fkselect'), /* @ts-ignore */
|
|
6019
|
+
...(ngDevMode ? [{ debugName: "inputId" }] : /* istanbul ignore next */ []));
|
|
5933
6020
|
/** Placeholder for the search input. */
|
|
5934
6021
|
placeholder = input('', /* @ts-ignore */
|
|
5935
6022
|
...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
@@ -5963,13 +6050,14 @@ class FkselectComponent {
|
|
|
5963
6050
|
this.queryset.set(this.collection().queryset());
|
|
5964
6051
|
}
|
|
5965
6052
|
else if (!this.queryset() && model && model._collection) {
|
|
5966
|
-
|
|
5967
|
-
|
|
5968
|
-
|
|
5969
|
-
|
|
5970
|
-
|
|
5971
|
-
|
|
5972
|
-
|
|
6053
|
+
// Fallback: the source model's own collection, assumed to hold the
|
|
6054
|
+
// related instances. Nothing can check that assumption.
|
|
6055
|
+
const coll = model._collection;
|
|
6056
|
+
this.collection.set(coll);
|
|
6057
|
+
this.queryset.set(coll.queryset());
|
|
6058
|
+
}
|
|
6059
|
+
this.fc = new FormControl(null);
|
|
6060
|
+
this.fc.valueChanges.pipe(takeUntilDestroyed(this.destroy$), distinctUntilChanged()).subscribe((value) => {
|
|
5973
6061
|
if (value) {
|
|
5974
6062
|
this.selected.emit(value);
|
|
5975
6063
|
}
|
|
@@ -5977,16 +6065,14 @@ class FkselectComponent {
|
|
|
5977
6065
|
const display = this.display();
|
|
5978
6066
|
if (display) {
|
|
5979
6067
|
if (typeof display === 'string') {
|
|
5980
|
-
this._tpl = (model) =>
|
|
6068
|
+
this._tpl = (model) => String(fieldValues(model)[display]);
|
|
5981
6069
|
}
|
|
5982
6070
|
else if (typeof display === 'function') {
|
|
5983
6071
|
this._tpl = display.bind(this);
|
|
5984
6072
|
}
|
|
5985
6073
|
}
|
|
5986
6074
|
else {
|
|
5987
|
-
this._tpl = (model) =>
|
|
5988
|
-
model['title'] ||
|
|
5989
|
-
model['id']}`;
|
|
6075
|
+
this._tpl = (model) => String(fieldValues(model)['name'] ?? fieldValues(model)['title'] ?? fieldValues(model)['id']);
|
|
5990
6076
|
}
|
|
5991
6077
|
}
|
|
5992
6078
|
/** Emit {@link cleared} so the parent can null the relation. */
|
|
@@ -5999,13 +6085,9 @@ class FkselectComponent {
|
|
|
5999
6085
|
*/
|
|
6000
6086
|
_display(x) {
|
|
6001
6087
|
if (x) {
|
|
6002
|
-
|
|
6003
|
-
|
|
6004
|
-
|
|
6005
|
-
}
|
|
6006
|
-
else {
|
|
6007
|
-
return x._display;
|
|
6008
|
-
}
|
|
6088
|
+
const display = x._display;
|
|
6089
|
+
if (display) {
|
|
6090
|
+
return typeof display === 'function' ? display() : display;
|
|
6009
6091
|
}
|
|
6010
6092
|
if (this._tpl) {
|
|
6011
6093
|
return this._tpl(x);
|
|
@@ -6034,13 +6116,13 @@ class FkselectComponent {
|
|
|
6034
6116
|
return qs.get();
|
|
6035
6117
|
}));
|
|
6036
6118
|
}
|
|
6037
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
6038
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.
|
|
6119
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: FkselectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
6120
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: FkselectComponent, isStandalone: true, selector: "data-fkselect", inputs: { model: { classPropertyName: "model", publicName: "model", isSignal: true, isRequired: false, transformFunction: null }, field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: false, transformFunction: null }, edit: { classPropertyName: "edit", publicName: "edit", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, queryset: { classPropertyName: "queryset", publicName: "queryset", isSignal: true, isRequired: false, transformFunction: null }, collection: { classPropertyName: "collection", publicName: "collection", isSignal: true, isRequired: false, transformFunction: null }, update: { classPropertyName: "update", publicName: "update", isSignal: true, isRequired: false, transformFunction: null }, filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, display: { classPropertyName: "display", publicName: "display", isSignal: true, isRequired: false, transformFunction: null }, search: { classPropertyName: "search", publicName: "search", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, inputId: { classPropertyName: "inputId", publicName: "inputId", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, inputClasses: { classPropertyName: "inputClasses", publicName: "inputClasses", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { queryset: "querysetChange", collection: "collectionChange", selected: "selected", cancelled: "cancelled", cleared: "cleared" }, ngImport: i0, template: "<div class=\"form-group\">\n @if (label()) {\n <label [attr.for]=\"inputId()\">{{ label() }}</label>\n }\n <div class=\"input-group\">\n <input\n [attr.id]=\"inputId()\"\n class=\"form-control\"\n [formControl]=\"fc\"\n [placeholder]=\"placeholder()\"\n [ngbTypeahead]=\"searchFn\"\n [editable]=\"false\"\n [focusFirst]=\"true\"\n [inputFormatter]=\"displayFn\"\n [resultFormatter]=\"displayFn\"\n (keyup.escape)=\"cancelled.emit()\"\n />\n <div class=\"input-group-text\">\n <i\n class=\"bi bi-trash float-end pointer\"\n role=\"button\"\n tabindex=\"0\"\n aria-label=\"Vider la s\u00E9lection\"\n (click)=\"clearAction()\"\n (keydown.enter)=\"clearAction()\"\n (keydown.space)=\"$event.preventDefault(); clearAction()\"\n ></i>\n </div>\n </div>\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.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$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: NgbTypeaheadModule }, { kind: "directive", type: i1$1.NgbTypeahead, selector: "input[ngbTypeahead]", inputs: ["autocomplete", "container", "editable", "focusFirst", "inputFormatter", "ngbTypeahead", "resultFormatter", "resultTemplate", "selectOnExact", "showHint", "placement", "popperOptions", "popupClass"], outputs: ["selectItem"], exportAs: ["ngbTypeahead"] }] });
|
|
6039
6121
|
}
|
|
6040
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
6122
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: FkselectComponent, decorators: [{
|
|
6041
6123
|
type: Component,
|
|
6042
|
-
args: [{ selector: 'data-fkselect', imports: [ReactiveFormsModule, NgbTypeaheadModule], template: "
|
|
6043
|
-
}], propDecorators: { model: [{ type: i0.Input, args: [{ isSignal: true, alias: "model", required: false }] }], field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: false }] }], edit: [{ type: i0.Input, args: [{ isSignal: true, alias: "edit", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], queryset: [{ type: i0.Input, args: [{ isSignal: true, alias: "queryset", required: false }] }, { type: i0.Output, args: ["querysetChange"] }], collection: [{ type: i0.Input, args: [{ isSignal: true, alias: "collection", required: false }] }, { type: i0.Output, args: ["collectionChange"] }], update: [{ type: i0.Input, args: [{ isSignal: true, alias: "update", required: false }] }], filter: [{ type: i0.Input, args: [{ isSignal: true, alias: "filter", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], display: [{ type: i0.Input, args: [{ isSignal: true, alias: "display", required: false }] }], search: [{ type: i0.Input, args: [{ isSignal: true, alias: "search", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], inputClasses: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputClasses", required: false }] }], selected: [{ type: i0.Output, args: ["selected"] }], cancelled: [{ type: i0.Output, args: ["cancelled"] }], cleared: [{ type: i0.Output, args: ["cleared"] }] } });
|
|
6124
|
+
args: [{ selector: 'data-fkselect', imports: [ReactiveFormsModule, NgbTypeaheadModule], template: "<div class=\"form-group\">\n @if (label()) {\n <label [attr.for]=\"inputId()\">{{ label() }}</label>\n }\n <div class=\"input-group\">\n <input\n [attr.id]=\"inputId()\"\n class=\"form-control\"\n [formControl]=\"fc\"\n [placeholder]=\"placeholder()\"\n [ngbTypeahead]=\"searchFn\"\n [editable]=\"false\"\n [focusFirst]=\"true\"\n [inputFormatter]=\"displayFn\"\n [resultFormatter]=\"displayFn\"\n (keyup.escape)=\"cancelled.emit()\"\n />\n <div class=\"input-group-text\">\n <i\n class=\"bi bi-trash float-end pointer\"\n role=\"button\"\n tabindex=\"0\"\n aria-label=\"Vider la s\u00E9lection\"\n (click)=\"clearAction()\"\n (keydown.enter)=\"clearAction()\"\n (keydown.space)=\"$event.preventDefault(); clearAction()\"\n ></i>\n </div>\n </div>\n</div>\n" }]
|
|
6125
|
+
}], propDecorators: { model: [{ type: i0.Input, args: [{ isSignal: true, alias: "model", required: false }] }], field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: false }] }], edit: [{ type: i0.Input, args: [{ isSignal: true, alias: "edit", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], queryset: [{ type: i0.Input, args: [{ isSignal: true, alias: "queryset", required: false }] }, { type: i0.Output, args: ["querysetChange"] }], collection: [{ type: i0.Input, args: [{ isSignal: true, alias: "collection", required: false }] }, { type: i0.Output, args: ["collectionChange"] }], update: [{ type: i0.Input, args: [{ isSignal: true, alias: "update", required: false }] }], filter: [{ type: i0.Input, args: [{ isSignal: true, alias: "filter", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], display: [{ type: i0.Input, args: [{ isSignal: true, alias: "display", required: false }] }], search: [{ type: i0.Input, args: [{ isSignal: true, alias: "search", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], inputId: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputId", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], inputClasses: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputClasses", required: false }] }], selected: [{ type: i0.Output, args: ["selected"] }], cancelled: [{ type: i0.Output, args: ["cancelled"] }], cleared: [{ type: i0.Output, args: ["cleared"] }] } });
|
|
6044
6126
|
|
|
6045
6127
|
/** Default lifetime in milliseconds per severity: the more severe, the longer it stays on screen. */
|
|
6046
6128
|
var DEFAULT_TIMEOUTS;
|
|
@@ -6065,7 +6147,7 @@ const DEFAULT_MESSAGE_TIMEOUT = 5000;
|
|
|
6065
6147
|
* When not provided, messages are silent. Keys are the sound names the service uses:
|
|
6066
6148
|
* `success`, `info`, `warning` and `error`.
|
|
6067
6149
|
*/
|
|
6068
|
-
const DATA_MESSAGE_SOUNDS = new InjectionToken(
|
|
6150
|
+
const DATA_MESSAGE_SOUNDS = new InjectionToken('data.message.sounds');
|
|
6069
6151
|
/**
|
|
6070
6152
|
* A single user-facing notification: a title, an optional body, an optional trace for
|
|
6071
6153
|
* debugging, and a countdown.
|
|
@@ -6082,7 +6164,7 @@ class Message {
|
|
|
6082
6164
|
ttl;
|
|
6083
6165
|
status = STATUS[STATUS.UNDISP];
|
|
6084
6166
|
showTrace = false;
|
|
6085
|
-
constructor(title, type = 1 /* TYPE.INFO */, message =
|
|
6167
|
+
constructor(title, type = 1 /* TYPE.INFO */, message = '', trace = null, ttl = DEFAULT_MESSAGE_TIMEOUT) {
|
|
6086
6168
|
this.title = title;
|
|
6087
6169
|
this.type = type;
|
|
6088
6170
|
this.message = message;
|
|
@@ -6092,18 +6174,18 @@ class Message {
|
|
|
6092
6174
|
/** Bootstrap alert classes matching this message's severity, bound by the message zone template. */
|
|
6093
6175
|
get style() {
|
|
6094
6176
|
if (this.type === 3 /* TYPE.DANGER */) {
|
|
6095
|
-
return
|
|
6177
|
+
return 'alert alert-dismissible alert-danger';
|
|
6096
6178
|
}
|
|
6097
6179
|
if (this.type === 1 /* TYPE.INFO */) {
|
|
6098
|
-
return
|
|
6180
|
+
return 'alert alert-dismissible alert-info';
|
|
6099
6181
|
}
|
|
6100
6182
|
if (this.type === 2 /* TYPE.WARNING */) {
|
|
6101
|
-
return
|
|
6183
|
+
return 'alert alert-dismissible alert-warning';
|
|
6102
6184
|
}
|
|
6103
6185
|
if (this.type === 0 /* TYPE.SUCCESS */) {
|
|
6104
|
-
return
|
|
6186
|
+
return 'alert alert-dismissible alert-success';
|
|
6105
6187
|
}
|
|
6106
|
-
return
|
|
6188
|
+
return 'alert alert-dismissible alert-success';
|
|
6107
6189
|
}
|
|
6108
6190
|
/** Marks the message as dismissed so it is filtered out of the next emission. Prefer {@link DataMessageService.ack}, which also refreshes the stream. */
|
|
6109
6191
|
ack() {
|
|
@@ -6181,21 +6263,21 @@ class DataMessageService {
|
|
|
6181
6263
|
this._subscription.unsubscribe();
|
|
6182
6264
|
}
|
|
6183
6265
|
/** Reports a completed operation. Short-lived by default (3 s) and plays the `success` sound if configured. */
|
|
6184
|
-
success(title, message =
|
|
6266
|
+
success(title, message = '', trace = null, timeout = DEFAULT_TIMEOUTS.SUCCESS) {
|
|
6185
6267
|
this._messages.push(new Message(title, 0 /* TYPE.SUCCESS */, message, trace, timeout));
|
|
6186
|
-
this.play(
|
|
6268
|
+
this.play('success');
|
|
6187
6269
|
this._notify();
|
|
6188
6270
|
}
|
|
6189
6271
|
/** Reports neutral information the user does not have to act on. Defaults to a 4 s lifetime. */
|
|
6190
|
-
info(title, message =
|
|
6272
|
+
info(title, message = '', trace = null, timeout = DEFAULT_TIMEOUTS.INFO) {
|
|
6191
6273
|
this._messages.push(new Message(title, 1 /* TYPE.INFO */, message, trace, timeout));
|
|
6192
|
-
this.play(
|
|
6274
|
+
this.play('info');
|
|
6193
6275
|
this._notify();
|
|
6194
6276
|
}
|
|
6195
6277
|
/** Reports a problem the user should notice but that did not abort the operation. Stays 10 s by default. */
|
|
6196
|
-
warning(title, message =
|
|
6278
|
+
warning(title, message = '', trace = null, timeout = DEFAULT_TIMEOUTS.WARNING) {
|
|
6197
6279
|
this._messages.push(new Message(title, 2 /* TYPE.WARNING */, message, trace, timeout));
|
|
6198
|
-
this.play(
|
|
6280
|
+
this.play('warning');
|
|
6199
6281
|
this._notify();
|
|
6200
6282
|
}
|
|
6201
6283
|
/**
|
|
@@ -6204,17 +6286,17 @@ class DataMessageService {
|
|
|
6204
6286
|
* Note that the `timeout` argument is currently ignored: the message is always created
|
|
6205
6287
|
* with {@link DEFAULT_TIMEOUTS.DANGER}.
|
|
6206
6288
|
*/
|
|
6207
|
-
danger(title, message =
|
|
6208
|
-
this._messages.push(new Message(title, 3 /* TYPE.DANGER */, message, trace,
|
|
6209
|
-
this.play(
|
|
6289
|
+
danger(title, message = '', trace = null, timeout = DEFAULT_TIMEOUTS.DANGER) {
|
|
6290
|
+
this._messages.push(new Message(title, 3 /* TYPE.DANGER */, message, trace, timeout));
|
|
6291
|
+
this.play('error');
|
|
6210
6292
|
this._notify();
|
|
6211
6293
|
}
|
|
6212
6294
|
/** Alias for {@link danger}, for callers that think in terms of "error" rather than severity. */
|
|
6213
|
-
error(title, message =
|
|
6295
|
+
error(title, message = '', trace = null) {
|
|
6214
6296
|
this.danger(title, message, trace);
|
|
6215
6297
|
}
|
|
6216
6298
|
/** Logs to the console only — nothing is shown to the user and no message is queued. */
|
|
6217
|
-
debug(title, message =
|
|
6299
|
+
debug(title, message = '', trace = null) {
|
|
6218
6300
|
console.log(title, message, trace);
|
|
6219
6301
|
}
|
|
6220
6302
|
/**
|
|
@@ -6231,30 +6313,32 @@ class DataMessageService {
|
|
|
6231
6313
|
* nothing when the token or the key is absent. Called automatically by the severity
|
|
6232
6314
|
* methods; call it directly only for custom cues.
|
|
6233
6315
|
*/
|
|
6234
|
-
play(type =
|
|
6316
|
+
play(type = 'notify') {
|
|
6235
6317
|
if (this.sounds && this.sounds[type]) {
|
|
6236
6318
|
const audio = new Audio(this.sounds[type]);
|
|
6237
|
-
|
|
6319
|
+
// Rejects whenever the browser's autoplay policy blocks the sound
|
|
6320
|
+
// (no user gesture yet). A missing notification cue is not worth
|
|
6321
|
+
// surfacing, but the rejection must be handled all the same.
|
|
6322
|
+
audio.play().catch(() => undefined);
|
|
6238
6323
|
}
|
|
6239
6324
|
}
|
|
6240
6325
|
_notify() {
|
|
6241
6326
|
const out = [];
|
|
6242
6327
|
for (const message of this._messages) {
|
|
6243
|
-
if (
|
|
6244
|
-
(message.status === STATUS[STATUS.DISP])) {
|
|
6328
|
+
if (message.status === STATUS[STATUS.UNDISP] || message.status === STATUS[STATUS.DISP]) {
|
|
6245
6329
|
message.status = STATUS[STATUS.DISP];
|
|
6246
6330
|
out.push(message);
|
|
6247
6331
|
}
|
|
6248
6332
|
}
|
|
6249
6333
|
this._messages$.next(out);
|
|
6250
6334
|
}
|
|
6251
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
6252
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.
|
|
6335
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: DataMessageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
6336
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: DataMessageService, providedIn: 'root' });
|
|
6253
6337
|
}
|
|
6254
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
6338
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: DataMessageService, decorators: [{
|
|
6255
6339
|
type: Injectable,
|
|
6256
6340
|
args: [{
|
|
6257
|
-
providedIn:
|
|
6341
|
+
providedIn: 'root',
|
|
6258
6342
|
}]
|
|
6259
6343
|
}], ctorParameters: () => [] });
|
|
6260
6344
|
|
|
@@ -6268,9 +6352,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
|
|
|
6268
6352
|
*
|
|
6269
6353
|
* On init, if no `[values]` are supplied, the initial selection is read from
|
|
6270
6354
|
* the model's `<field>_details` sibling property (built by string
|
|
6271
|
-
* concatenation).
|
|
6272
|
-
*
|
|
6273
|
-
*
|
|
6355
|
+
* concatenation). When that property is missing the selection simply starts
|
|
6356
|
+
* empty — which is the normal case for an unsaved model, as rendered by a
|
|
6357
|
+
* creation form. On a model that has an `id`, a missing `_details` is instead a
|
|
6358
|
+
* configuration problem (field left out of the request's `fields=`, or a
|
|
6359
|
+
* misspelled `[field]`) and is reported with a `console.warn`. A queryset, on
|
|
6360
|
+
* the other hand, is mandatory — supplied directly, derived from
|
|
6361
|
+
* `[collection]`, or from the model's `_collection`.
|
|
6274
6362
|
*
|
|
6275
6363
|
* Options are labelled via each target's `_display` (getter or method), falling
|
|
6276
6364
|
* back to `[display]`, then `name` / `title` / `id`.
|
|
@@ -6319,6 +6407,12 @@ class M2mselectComponent {
|
|
|
6319
6407
|
/** Label shown next to the control. */
|
|
6320
6408
|
label = input('', /* @ts-ignore */
|
|
6321
6409
|
...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
6410
|
+
/**
|
|
6411
|
+
* Id put on the search input, and pointed at by `[label]`'s `for`. Defaults
|
|
6412
|
+
* to a generated one; dispedit passes its own so its label drives this input.
|
|
6413
|
+
*/
|
|
6414
|
+
inputId = input(uniqueId('data-m2mselect'), /* @ts-ignore */
|
|
6415
|
+
...(ngDevMode ? [{ debugName: "inputId" }] : /* istanbul ignore next */ []));
|
|
6322
6416
|
/** Placeholder for the search input. */
|
|
6323
6417
|
placeholder = input('', /* @ts-ignore */
|
|
6324
6418
|
...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
@@ -6351,13 +6445,17 @@ class M2mselectComponent {
|
|
|
6351
6445
|
destroy$ = inject(DestroyRef);
|
|
6352
6446
|
/**
|
|
6353
6447
|
* Control value accessor onChange dummy callback;
|
|
6354
|
-
* @param
|
|
6448
|
+
* @param _fks
|
|
6355
6449
|
*/
|
|
6356
|
-
onChange = (
|
|
6450
|
+
onChange = (_fks) => {
|
|
6451
|
+
// Replaced by registerOnChange when used inside a form.
|
|
6452
|
+
};
|
|
6357
6453
|
/**
|
|
6358
6454
|
* Control value accessor onTouched dummy callback;
|
|
6359
6455
|
*/
|
|
6360
|
-
onTouched = () => {
|
|
6456
|
+
onTouched = () => {
|
|
6457
|
+
// Replaced by registerOnTouched when used inside a form.
|
|
6458
|
+
};
|
|
6361
6459
|
/**
|
|
6362
6460
|
* OnChange register from controlValueAccessor
|
|
6363
6461
|
* @param onChange callback
|
|
@@ -6377,7 +6475,7 @@ class M2mselectComponent {
|
|
|
6377
6475
|
* - ensures queryset is available
|
|
6378
6476
|
* - creates form control for input
|
|
6379
6477
|
* - creates display function
|
|
6380
|
-
* - ensure values are set from
|
|
6478
|
+
* - ensure values are set from whichever source is available
|
|
6381
6479
|
*/
|
|
6382
6480
|
ngOnInit() {
|
|
6383
6481
|
// Create queryset if not given
|
|
@@ -6387,17 +6485,18 @@ class M2mselectComponent {
|
|
|
6387
6485
|
this.queryset.set(this.collection().queryset());
|
|
6388
6486
|
}
|
|
6389
6487
|
else if (!this.queryset() && model && model._collection) {
|
|
6390
|
-
|
|
6391
|
-
|
|
6488
|
+
// Fallback: the source model's own collection, assumed to hold the
|
|
6489
|
+
// related instances. Nothing can check that assumption.
|
|
6490
|
+
const coll = model._collection;
|
|
6491
|
+
this.collection.set(coll);
|
|
6492
|
+
this.queryset.set(coll.queryset());
|
|
6392
6493
|
}
|
|
6393
6494
|
if (!this.queryset()) {
|
|
6394
6495
|
throw Error('queryset is mandatory for m2m select');
|
|
6395
6496
|
}
|
|
6396
6497
|
// Create form control for typeahead and subscribe for changes
|
|
6397
6498
|
this.fc = new UntypedFormControl('');
|
|
6398
|
-
this.fc.valueChanges
|
|
6399
|
-
.pipe(takeUntilDestroyed(this.destroy$), distinctUntilChanged())
|
|
6400
|
-
.subscribe((value) => {
|
|
6499
|
+
this.fc.valueChanges.pipe(takeUntilDestroyed(this.destroy$), distinctUntilChanged()).subscribe((value) => {
|
|
6401
6500
|
if (value) {
|
|
6402
6501
|
this.onAdd(value);
|
|
6403
6502
|
}
|
|
@@ -6406,23 +6505,37 @@ class M2mselectComponent {
|
|
|
6406
6505
|
const display = this.display();
|
|
6407
6506
|
if (display) {
|
|
6408
6507
|
if (typeof display === 'string') {
|
|
6409
|
-
this._tpl = (m) => `${m[display]}`;
|
|
6508
|
+
this._tpl = (m) => `${String(fieldValues(m)[display])}`;
|
|
6410
6509
|
}
|
|
6411
6510
|
else if (typeof display === 'function') {
|
|
6412
6511
|
this._tpl = display.bind(this);
|
|
6413
6512
|
}
|
|
6414
6513
|
}
|
|
6415
6514
|
else {
|
|
6416
|
-
this._tpl = (m) =>
|
|
6515
|
+
this._tpl = (m) => {
|
|
6516
|
+
const v = fieldValues(m);
|
|
6517
|
+
return `${String(v['name'] ?? v['title'] ?? v['id'])}`;
|
|
6518
|
+
};
|
|
6417
6519
|
}
|
|
6418
6520
|
// Get values from model if not already given
|
|
6419
|
-
|
|
6420
|
-
if (
|
|
6421
|
-
|
|
6422
|
-
|
|
6521
|
+
const field = this.field();
|
|
6522
|
+
if (this.values() === undefined && model && field) {
|
|
6523
|
+
const details = fieldValues(model)[`${field}_details`];
|
|
6524
|
+
if (details === undefined && model.id !== undefined) {
|
|
6525
|
+
// The model comes from the API but carries no details for this
|
|
6526
|
+
// relation: either the field was left out of the request's `fields=`,
|
|
6527
|
+
// or `[field]` doesn't match the model's. Worth reporting, but not
|
|
6528
|
+
// worth breaking the display for — the selection just starts empty.
|
|
6529
|
+
console.warn(`m2mselect: no "${field}_details" on the model, starting with an ` +
|
|
6530
|
+
`empty selection. Check that "${field}" is requested in the ` +
|
|
6531
|
+
`fields= of the query, and that [field] is spelled correctly.`, model);
|
|
6532
|
+
}
|
|
6533
|
+
this.values.set(details ?? []);
|
|
6534
|
+
}
|
|
6535
|
+
// No model or field given, or an unsaved model (creation form): the
|
|
6536
|
+
// details sibling cannot exist yet, an empty selection is expected.
|
|
6423
6537
|
if (this.values() === undefined) {
|
|
6424
|
-
|
|
6425
|
-
throw Error('no values available');
|
|
6538
|
+
this.values.set([]);
|
|
6426
6539
|
}
|
|
6427
6540
|
}
|
|
6428
6541
|
/**
|
|
@@ -6508,7 +6621,7 @@ class M2mselectComponent {
|
|
|
6508
6621
|
const values = [];
|
|
6509
6622
|
for (const k of pks) {
|
|
6510
6623
|
let found = false;
|
|
6511
|
-
for (
|
|
6624
|
+
for (const v of this.values() ?? []) {
|
|
6512
6625
|
if (v.id == k) {
|
|
6513
6626
|
values.push(v);
|
|
6514
6627
|
found = true;
|
|
@@ -6533,13 +6646,9 @@ class M2mselectComponent {
|
|
|
6533
6646
|
*/
|
|
6534
6647
|
_display(x) {
|
|
6535
6648
|
if (x) {
|
|
6536
|
-
|
|
6537
|
-
|
|
6538
|
-
|
|
6539
|
-
}
|
|
6540
|
-
else {
|
|
6541
|
-
return x._display;
|
|
6542
|
-
}
|
|
6649
|
+
const display = x._display;
|
|
6650
|
+
if (display) {
|
|
6651
|
+
return typeof display === 'function' ? display() : display;
|
|
6543
6652
|
}
|
|
6544
6653
|
if (this._tpl) {
|
|
6545
6654
|
return this._tpl(x);
|
|
@@ -6567,16 +6676,16 @@ class M2mselectComponent {
|
|
|
6567
6676
|
return qs.get();
|
|
6568
6677
|
}));
|
|
6569
6678
|
}
|
|
6570
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
6571
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.
|
|
6679
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: M2mselectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
6680
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: M2mselectComponent, isStandalone: true, selector: "data-m2mselect", inputs: { model: { classPropertyName: "model", publicName: "model", isSignal: true, isRequired: false, transformFunction: null }, field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: false, transformFunction: null }, edit: { classPropertyName: "edit", publicName: "edit", isSignal: true, isRequired: false, transformFunction: null }, values: { classPropertyName: "values", publicName: "values", isSignal: true, isRequired: false, transformFunction: null }, queryset: { classPropertyName: "queryset", publicName: "queryset", isSignal: true, isRequired: false, transformFunction: null }, collection: { classPropertyName: "collection", publicName: "collection", isSignal: true, isRequired: false, transformFunction: null }, filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, display: { classPropertyName: "display", publicName: "display", isSignal: true, isRequired: false, transformFunction: null }, search: { classPropertyName: "search", publicName: "search", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, inputId: { classPropertyName: "inputId", publicName: "inputId", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, emptyLabel: { classPropertyName: "emptyLabel", publicName: "emptyLabel", isSignal: true, isRequired: false, transformFunction: null }, inputClasses: { classPropertyName: "inputClasses", publicName: "inputClasses", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { values: "valuesChange", queryset: "querysetChange", collection: "collectionChange", added: "added", removed: "removed", cancelled: "cancelled", cleared: "cleared", detailsChanged: "detailsChanged", changed: "changed" }, providers: [
|
|
6572
6681
|
{
|
|
6573
6682
|
provide: NG_VALUE_ACCESSOR,
|
|
6574
6683
|
multi: true,
|
|
6575
6684
|
useExisting: M2mselectComponent,
|
|
6576
6685
|
},
|
|
6577
|
-
], ngImport: i0, template: "
|
|
6686
|
+
], ngImport: i0, template: "<div class=\"form-group\">\n @if (label()) {\n <label [attr.for]=\"inputId()\">{{ label() }}</label>\n }\n <div class=\"input-group\">\n <input\n [attr.id]=\"inputId()\"\n class=\"form-control\"\n [formControl]=\"fc\"\n [placeholder]=\"placeholder()\"\n [ngbTypeahead]=\"searchFn\"\n [editable]=\"false\"\n [focusFirst]=\"true\"\n [inputFormatter]=\"displayFn\"\n [resultFormatter]=\"displayFn\"\n (keyup.escape)=\"cancelled.emit()\"\n />\n <div class=\"input-group-text\">\n <i\n class=\"bi bi-trash float-end pointer\"\n role=\"button\"\n tabindex=\"0\"\n aria-label=\"Vider la s\u00E9lection\"\n (click)=\"cleared.emit()\"\n (keydown.enter)=\"cleared.emit()\"\n (keydown.space)=\"$event.preventDefault(); cleared.emit()\"\n ></i>\n </div>\n </div>\n @for (i of values(); track i) {\n <div>\n <i\n class=\"bi bi-trash ms-2 float-end\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"'Retirer ' + displayFn(i)\"\n (click)=\"onRemove(i)\"\n (keydown.enter)=\"onRemove(i)\"\n (keydown.space)=\"$event.preventDefault(); onRemove(i)\"\n ></i>\n {{ displayFn(i) }}\n </div>\n }\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.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$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: NgbTypeaheadModule }, { kind: "directive", type: i1$1.NgbTypeahead, selector: "input[ngbTypeahead]", inputs: ["autocomplete", "container", "editable", "focusFirst", "inputFormatter", "ngbTypeahead", "resultFormatter", "resultTemplate", "selectOnExact", "showHint", "placement", "popperOptions", "popupClass"], outputs: ["selectItem"], exportAs: ["ngbTypeahead"] }] });
|
|
6578
6687
|
}
|
|
6579
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
6688
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: M2mselectComponent, decorators: [{
|
|
6580
6689
|
type: Component,
|
|
6581
6690
|
args: [{ selector: 'data-m2mselect', providers: [
|
|
6582
6691
|
{
|
|
@@ -6584,8 +6693,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
|
|
|
6584
6693
|
multi: true,
|
|
6585
6694
|
useExisting: M2mselectComponent,
|
|
6586
6695
|
},
|
|
6587
|
-
], imports: [ReactiveFormsModule, NgbTypeaheadModule], template: "
|
|
6588
|
-
}], propDecorators: { model: [{ type: i0.Input, args: [{ isSignal: true, alias: "model", required: false }] }], field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: false }] }], edit: [{ type: i0.Input, args: [{ isSignal: true, alias: "edit", required: false }] }], values: [{ type: i0.Input, args: [{ isSignal: true, alias: "values", required: false }] }, { type: i0.Output, args: ["valuesChange"] }], queryset: [{ type: i0.Input, args: [{ isSignal: true, alias: "queryset", required: false }] }, { type: i0.Output, args: ["querysetChange"] }], collection: [{ type: i0.Input, args: [{ isSignal: true, alias: "collection", required: false }] }, { type: i0.Output, args: ["collectionChange"] }], filter: [{ type: i0.Input, args: [{ isSignal: true, alias: "filter", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], display: [{ type: i0.Input, args: [{ isSignal: true, alias: "display", required: false }] }], search: [{ type: i0.Input, args: [{ isSignal: true, alias: "search", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], emptyLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyLabel", required: false }] }], inputClasses: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputClasses", required: false }] }], added: [{ type: i0.Output, args: ["added"] }], removed: [{ type: i0.Output, args: ["removed"] }], cancelled: [{ type: i0.Output, args: ["cancelled"] }], cleared: [{ type: i0.Output, args: ["cleared"] }], detailsChanged: [{ type: i0.Output, args: ["detailsChanged"] }], changed: [{ type: i0.Output, args: ["changed"] }] } });
|
|
6696
|
+
], imports: [ReactiveFormsModule, NgbTypeaheadModule], template: "<div class=\"form-group\">\n @if (label()) {\n <label [attr.for]=\"inputId()\">{{ label() }}</label>\n }\n <div class=\"input-group\">\n <input\n [attr.id]=\"inputId()\"\n class=\"form-control\"\n [formControl]=\"fc\"\n [placeholder]=\"placeholder()\"\n [ngbTypeahead]=\"searchFn\"\n [editable]=\"false\"\n [focusFirst]=\"true\"\n [inputFormatter]=\"displayFn\"\n [resultFormatter]=\"displayFn\"\n (keyup.escape)=\"cancelled.emit()\"\n />\n <div class=\"input-group-text\">\n <i\n class=\"bi bi-trash float-end pointer\"\n role=\"button\"\n tabindex=\"0\"\n aria-label=\"Vider la s\u00E9lection\"\n (click)=\"cleared.emit()\"\n (keydown.enter)=\"cleared.emit()\"\n (keydown.space)=\"$event.preventDefault(); cleared.emit()\"\n ></i>\n </div>\n </div>\n @for (i of values(); track i) {\n <div>\n <i\n class=\"bi bi-trash ms-2 float-end\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"'Retirer ' + displayFn(i)\"\n (click)=\"onRemove(i)\"\n (keydown.enter)=\"onRemove(i)\"\n (keydown.space)=\"$event.preventDefault(); onRemove(i)\"\n ></i>\n {{ displayFn(i) }}\n </div>\n }\n</div>\n" }]
|
|
6697
|
+
}], propDecorators: { model: [{ type: i0.Input, args: [{ isSignal: true, alias: "model", required: false }] }], field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: false }] }], edit: [{ type: i0.Input, args: [{ isSignal: true, alias: "edit", required: false }] }], values: [{ type: i0.Input, args: [{ isSignal: true, alias: "values", required: false }] }, { type: i0.Output, args: ["valuesChange"] }], queryset: [{ type: i0.Input, args: [{ isSignal: true, alias: "queryset", required: false }] }, { type: i0.Output, args: ["querysetChange"] }], collection: [{ type: i0.Input, args: [{ isSignal: true, alias: "collection", required: false }] }, { type: i0.Output, args: ["collectionChange"] }], filter: [{ type: i0.Input, args: [{ isSignal: true, alias: "filter", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], display: [{ type: i0.Input, args: [{ isSignal: true, alias: "display", required: false }] }], search: [{ type: i0.Input, args: [{ isSignal: true, alias: "search", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], inputId: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputId", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], emptyLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyLabel", required: false }] }], inputClasses: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputClasses", required: false }] }], added: [{ type: i0.Output, args: ["added"] }], removed: [{ type: i0.Output, args: ["removed"] }], cancelled: [{ type: i0.Output, args: ["cancelled"] }], cleared: [{ type: i0.Output, args: ["cleared"] }], detailsChanged: [{ type: i0.Output, args: ["detailsChanged"] }], changed: [{ type: i0.Output, args: ["changed"] }] } });
|
|
6589
6698
|
|
|
6590
6699
|
/**
|
|
6591
6700
|
* Displays and edits a single model field, choosing its own widgets from the
|
|
@@ -6664,6 +6773,8 @@ class DispeditComponent {
|
|
|
6664
6773
|
*/
|
|
6665
6774
|
field = input.required(/* @ts-ignore */
|
|
6666
6775
|
...(ngDevMode ? [{ debugName: "field" }] : /* istanbul ignore next */ []));
|
|
6776
|
+
/** Id tying the label to whichever control the editor renders. */
|
|
6777
|
+
inputId = uniqueId('data-dispedit');
|
|
6667
6778
|
/**
|
|
6668
6779
|
* External form group, for `inline` / `form` modes.
|
|
6669
6780
|
*
|
|
@@ -6837,8 +6948,7 @@ class DispeditComponent {
|
|
|
6837
6948
|
* Display config, overridable via the DATA_DISPLAY_CONFIG injection token.
|
|
6838
6949
|
* By default, bs5 config is used.
|
|
6839
6950
|
*/
|
|
6840
|
-
dconf = inject(DATA_DISPLAY_CONFIG, { optional: true }) ??
|
|
6841
|
-
BootstrapDataDisplayConfig;
|
|
6951
|
+
dconf = inject(DATA_DISPLAY_CONFIG, { optional: true }) ?? BootstrapDataDisplayConfig;
|
|
6842
6952
|
_msgs = inject(DataMessageService);
|
|
6843
6953
|
/**
|
|
6844
6954
|
* Recompute all derived values / edit mode on any (trigger) input change.
|
|
@@ -6885,8 +6995,7 @@ class DispeditComponent {
|
|
|
6885
6995
|
this.realPlaceholder.set(this.placeholder() || this.manager()?.description || '');
|
|
6886
6996
|
this.realDefault.set(this.default());
|
|
6887
6997
|
this.save = this.save === undefined ? this.mode() === 'dd' : this.save;
|
|
6888
|
-
if ((!this.edit() && this.mode() === 'dd') ||
|
|
6889
|
-
(!this.editable() && this.mode() === 'inline')) {
|
|
6998
|
+
if ((!this.edit() && this.mode() === 'dd') || (!this.editable() && this.mode() === 'inline')) {
|
|
6890
6999
|
this.enableDisplayMode();
|
|
6891
7000
|
}
|
|
6892
7001
|
else {
|
|
@@ -6940,10 +7049,11 @@ class DispeditComponent {
|
|
|
6940
7049
|
if (fg && model && fg.valid) {
|
|
6941
7050
|
switch (this.realEditor()) {
|
|
6942
7051
|
case 'input.decimal':
|
|
6943
|
-
model[this.field()] = Math.round(fg.value[this.field()] *
|
|
7052
|
+
fieldValues(model)[this.field()] = Math.round(fg.value[this.field()] *
|
|
7053
|
+
(this.manager().factor || 1));
|
|
6944
7054
|
break;
|
|
6945
7055
|
default:
|
|
6946
|
-
model[this.field()] = fg.value[this.field()];
|
|
7056
|
+
fieldValues(model)[this.field()] = fieldValues(fg.value)[this.field()];
|
|
6947
7057
|
}
|
|
6948
7058
|
if (this.save === true) {
|
|
6949
7059
|
return this._save();
|
|
@@ -6982,7 +7092,7 @@ class DispeditComponent {
|
|
|
6982
7092
|
async setDefault() {
|
|
6983
7093
|
const model = this.model();
|
|
6984
7094
|
if (model) {
|
|
6985
|
-
model[this.field()] = this.realDefault();
|
|
7095
|
+
fieldValues(model)[this.field()] = this.realDefault();
|
|
6986
7096
|
this.fg().controls[this.field()].setValue(this.realDefault(), {
|
|
6987
7097
|
emitEvent: false,
|
|
6988
7098
|
});
|
|
@@ -7005,8 +7115,8 @@ class DispeditComponent {
|
|
|
7005
7115
|
const form = this.form();
|
|
7006
7116
|
if (model) {
|
|
7007
7117
|
if ($event !== null) {
|
|
7008
|
-
model[this.field()] = $event.id;
|
|
7009
|
-
model[`${this.field()}_details`] = $event;
|
|
7118
|
+
fieldValues(model)[this.field()] = $event.id;
|
|
7119
|
+
fieldValues(model)[`${this.field()}_details`] = $event;
|
|
7010
7120
|
if (form) {
|
|
7011
7121
|
const fv = {};
|
|
7012
7122
|
fv[this.field()] = $event.id;
|
|
@@ -7016,8 +7126,8 @@ class DispeditComponent {
|
|
|
7016
7126
|
}
|
|
7017
7127
|
}
|
|
7018
7128
|
else {
|
|
7019
|
-
model[this.field()] = null;
|
|
7020
|
-
delete model[`${this.field()}_details`];
|
|
7129
|
+
fieldValues(model)[this.field()] = null;
|
|
7130
|
+
delete fieldValues(model)[`${this.field()}_details`];
|
|
7021
7131
|
if (form) {
|
|
7022
7132
|
const fv = {};
|
|
7023
7133
|
fv[this.field()] = null;
|
|
@@ -7061,8 +7171,9 @@ class DispeditComponent {
|
|
|
7061
7171
|
catch (e) {
|
|
7062
7172
|
console.error(e);
|
|
7063
7173
|
let msg = '';
|
|
7064
|
-
|
|
7065
|
-
|
|
7174
|
+
const apiErrors = e?.error;
|
|
7175
|
+
if (apiErrors?.[this.field()]) {
|
|
7176
|
+
msg = `${String(apiErrors[this.field()])}`;
|
|
7066
7177
|
}
|
|
7067
7178
|
this._msgs.error("Erreur lors de l'enregistrement", msg, JSON.stringify(e));
|
|
7068
7179
|
return;
|
|
@@ -7077,13 +7188,9 @@ class DispeditComponent {
|
|
|
7077
7188
|
}
|
|
7078
7189
|
_display(x) {
|
|
7079
7190
|
if (x) {
|
|
7080
|
-
|
|
7081
|
-
|
|
7082
|
-
|
|
7083
|
-
}
|
|
7084
|
-
else {
|
|
7085
|
-
return x._display;
|
|
7086
|
-
}
|
|
7191
|
+
const display = x._display;
|
|
7192
|
+
if (display) {
|
|
7193
|
+
return typeof display === 'function' ? display() : display;
|
|
7087
7194
|
}
|
|
7088
7195
|
if (this._tpl) {
|
|
7089
7196
|
return this._tpl(x);
|
|
@@ -7095,16 +7202,14 @@ class DispeditComponent {
|
|
|
7095
7202
|
const display = this.display();
|
|
7096
7203
|
if (display) {
|
|
7097
7204
|
if (typeof display === 'string') {
|
|
7098
|
-
this._tpl = (model) =>
|
|
7205
|
+
this._tpl = (model) => String(fieldValues(model)[display]);
|
|
7099
7206
|
}
|
|
7100
7207
|
else if (typeof display === 'function') {
|
|
7101
7208
|
this._tpl = display.bind(this);
|
|
7102
7209
|
}
|
|
7103
7210
|
}
|
|
7104
7211
|
else {
|
|
7105
|
-
this._tpl = (model) =>
|
|
7106
|
-
model['title'] ||
|
|
7107
|
-
model['id']}`;
|
|
7212
|
+
this._tpl = (model) => String(fieldValues(model)['name'] ?? fieldValues(model)['title'] ?? fieldValues(model)['id']);
|
|
7108
7213
|
}
|
|
7109
7214
|
}
|
|
7110
7215
|
_getChoices() {
|
|
@@ -7114,8 +7219,11 @@ class DispeditComponent {
|
|
|
7114
7219
|
if (inputChoices && inputChoices.length) {
|
|
7115
7220
|
choices = inputChoices;
|
|
7116
7221
|
}
|
|
7117
|
-
else
|
|
7118
|
-
|
|
7222
|
+
else {
|
|
7223
|
+
const managerChoices = this.manager()?.choices;
|
|
7224
|
+
if (managerChoices) {
|
|
7225
|
+
choices = managerChoices;
|
|
7226
|
+
}
|
|
7119
7227
|
}
|
|
7120
7228
|
// Set display value
|
|
7121
7229
|
if (choices && choices.length > 0) {
|
|
@@ -7129,11 +7237,7 @@ class DispeditComponent {
|
|
|
7129
7237
|
const viewer = this.viewer();
|
|
7130
7238
|
const manager = this.manager();
|
|
7131
7239
|
const realChoices = this.realChoices();
|
|
7132
|
-
this.realDisplay.set(viewer
|
|
7133
|
-
? viewer
|
|
7134
|
-
: manager?.displayType
|
|
7135
|
-
? manager.displayType
|
|
7136
|
-
: 'text');
|
|
7240
|
+
this.realDisplay.set(viewer ? viewer : manager?.displayType ? manager.displayType : 'text');
|
|
7137
7241
|
if (realChoices && realChoices.length) {
|
|
7138
7242
|
this.realDisplay.set('choice');
|
|
7139
7243
|
}
|
|
@@ -7163,10 +7267,8 @@ class DispeditComponent {
|
|
|
7163
7267
|
}
|
|
7164
7268
|
this.fg.set(fg);
|
|
7165
7269
|
if (this.mode() === 'inline') {
|
|
7166
|
-
fg.valueChanges
|
|
7167
|
-
.
|
|
7168
|
-
.subscribe(() => {
|
|
7169
|
-
this.update();
|
|
7270
|
+
fg.valueChanges.pipe(takeUntilDestroyed(this._destroyRef)).subscribe(() => {
|
|
7271
|
+
void this.update();
|
|
7170
7272
|
});
|
|
7171
7273
|
}
|
|
7172
7274
|
}
|
|
@@ -7175,8 +7277,8 @@ class DispeditComponent {
|
|
|
7175
7277
|
const field = this.field();
|
|
7176
7278
|
const fg = this.fg();
|
|
7177
7279
|
switch (this.realEditor()) {
|
|
7178
|
-
case 'input.datetime':
|
|
7179
|
-
const value = model[field];
|
|
7280
|
+
case 'input.datetime': {
|
|
7281
|
+
const value = fieldValues(model)[field];
|
|
7180
7282
|
const now = new Date();
|
|
7181
7283
|
const localnow = new Date(now.getTime() - now.getTimezoneOffset() * 60000);
|
|
7182
7284
|
if (value === null) {
|
|
@@ -7188,17 +7290,16 @@ class DispeditComponent {
|
|
|
7188
7290
|
const localtime = new Date(time.getTime() - offset * 60000);
|
|
7189
7291
|
fg.controls[field].setValue(localtime.toISOString().substring(0, 16), { emitEvent: true });
|
|
7190
7292
|
}
|
|
7191
|
-
this.realDefault.set(this.default() || this.manager()?.required
|
|
7192
|
-
? localnow.toISOString().substring(0, 16)
|
|
7193
|
-
: null);
|
|
7293
|
+
this.realDefault.set(this.default() || this.manager()?.required ? localnow.toISOString().substring(0, 16) : null);
|
|
7194
7294
|
break;
|
|
7195
|
-
|
|
7196
|
-
|
|
7295
|
+
}
|
|
7296
|
+
case 'input.date': {
|
|
7297
|
+
const dt = fieldValues(model.toJson([field]))[field];
|
|
7197
7298
|
fg.controls[field].setValue(dt);
|
|
7198
7299
|
break;
|
|
7300
|
+
}
|
|
7199
7301
|
case 'input.decimal':
|
|
7200
|
-
fg.controls[field].setValue(model[field] /
|
|
7201
|
-
(this.manager().factor || 1));
|
|
7302
|
+
fg.controls[field].setValue(fieldValues(model)[field] / (this.manager().factor || 1));
|
|
7202
7303
|
}
|
|
7203
7304
|
}
|
|
7204
7305
|
_setEditorClasses() {
|
|
@@ -7210,13 +7311,13 @@ class DispeditComponent {
|
|
|
7210
7311
|
_getDisplayValue() {
|
|
7211
7312
|
const model = this.model();
|
|
7212
7313
|
const field = this.field();
|
|
7213
|
-
const value = model[field];
|
|
7314
|
+
const value = fieldValues(model)[field];
|
|
7214
7315
|
this.dispValue.set(value);
|
|
7215
7316
|
const realChoices = this.realChoices();
|
|
7216
7317
|
if (realChoices) {
|
|
7217
7318
|
for (const c of realChoices) {
|
|
7218
7319
|
if (c === value) {
|
|
7219
|
-
this.txtValue.set(c);
|
|
7320
|
+
this.txtValue.set(String(c.desc ?? c.value));
|
|
7220
7321
|
return;
|
|
7221
7322
|
}
|
|
7222
7323
|
else if (c.value !== undefined && c.value === value) {
|
|
@@ -7237,40 +7338,37 @@ class DispeditComponent {
|
|
|
7237
7338
|
}
|
|
7238
7339
|
else {
|
|
7239
7340
|
switch (this.realDisplay()) {
|
|
7240
|
-
case 'fkdetails':
|
|
7241
|
-
const details = model[`${field}_details`];
|
|
7341
|
+
case 'fkdetails': {
|
|
7342
|
+
const details = fieldValues(model)[`${field}_details`];
|
|
7242
7343
|
this.txtValue.set(this._display(details));
|
|
7243
7344
|
break;
|
|
7244
|
-
|
|
7245
|
-
|
|
7345
|
+
}
|
|
7346
|
+
case 'm2mdetails': {
|
|
7347
|
+
const m2mDetails = this.m2mValues || fieldValues(model)[`${field}_details`];
|
|
7246
7348
|
const tv = [];
|
|
7247
7349
|
for (const v of m2mDetails || []) {
|
|
7248
7350
|
tv.push(this._display(v));
|
|
7249
7351
|
}
|
|
7250
7352
|
this.txtValues.set(tv);
|
|
7251
7353
|
break;
|
|
7354
|
+
}
|
|
7252
7355
|
case 'decimal':
|
|
7253
|
-
this.txtValue.set(`${value /
|
|
7254
|
-
(this.manager().factor || 1)}`);
|
|
7356
|
+
this.txtValue.set(`${value / (this.manager().factor || 1)}`);
|
|
7255
7357
|
break;
|
|
7256
7358
|
default:
|
|
7257
|
-
this.txtValue.set(
|
|
7359
|
+
this.txtValue.set(asText(value));
|
|
7258
7360
|
}
|
|
7259
7361
|
}
|
|
7260
7362
|
}
|
|
7261
|
-
_setDisplayClasses() {
|
|
7262
|
-
|
|
7263
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: DispeditComponent, isStandalone: true, selector: "data-dispedit", inputs: { model: { classPropertyName: "model", publicName: "model", isSignal: true, isRequired: true, transformFunction: null }, field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null }, form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: false, transformFunction: null }, edit: { classPropertyName: "edit", publicName: "edit", isSignal: true, isRequired: false, transformFunction: null }, editable: { classPropertyName: "editable", publicName: "editable", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, choices: { classPropertyName: "choices", publicName: "choices", isSignal: true, isRequired: false, transformFunction: null }, inputClasses: { classPropertyName: "inputClasses", publicName: "inputClasses", isSignal: true, isRequired: false, transformFunction: null }, editor: { classPropertyName: "editor", publicName: "editor", isSignal: true, isRequired: false, transformFunction: null }, viewer: { classPropertyName: "viewer", publicName: "viewer", isSignal: true, isRequired: false, transformFunction: null }, default: { classPropertyName: "default", publicName: "default", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, help: { classPropertyName: "help", publicName: "help", isSignal: true, isRequired: false, transformFunction: null }, hideLabel: { classPropertyName: "hideLabel", publicName: "hideLabel", isSignal: true, isRequired: false, transformFunction: null }, queryset: { classPropertyName: "queryset", publicName: "queryset", isSignal: true, isRequired: false, transformFunction: null }, collection: { classPropertyName: "collection", publicName: "collection", isSignal: true, isRequired: false, transformFunction: null }, display: { classPropertyName: "display", publicName: "display", isSignal: true, isRequired: false, transformFunction: null }, filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { edit: "editChange", inputClasses: "inputClassesChange", viewer: "viewerChange", changed: "changed" }, ngImport: i0, template: "<ng-template #titleTpl>\n <ng-content></ng-content>\n</ng-template>\n\n<!-- TEMPLATE affichage -->\n<ng-template #dispTpl>\n @switch (realDisplay()) {\n @case (\"text\") {\n <span class=\"editable disp-text\" (click)=\"enableEditMode()\">{{\n txtValue()\n }}</span>\n }\n @case (\"choice\") {\n <span class=\"editable disp-choice\" (click)=\"enableEditMode()\">{{\n txtValue()\n }}</span>\n }\n @case (\"decimal\") {\n <span class=\"editable disp-decimal\" (click)=\"enableEditMode()\">{{\n txtValue()\n }}</span>\n }\n @case (\"boolean\") {\n <span class=\"editable disp-boolean\" (click)=\"enableEditMode()\">{{\n txtValue()\n }}</span>\n }\n @case (\"fkdetails\") {\n <span class=\"editable disp-fkdetails\" (click)=\"enableEditMode()\">\n <div class=\"fkitem\">{{ txtValue() }}</div></span\n >\n }\n @case (\"m2mdetails\") {\n <span class=\"editable disp-m2mdetails\" (click)=\"enableEditMode()\">\n @for (v of txtValues(); track v) {\n <div class=\"m2mitem\">{{ v }}</div>\n }\n </span>\n }\n @case (\"datetime\") {\n <span class=\"editable disp-datetime\" (click)=\"enableEditMode()\">\n @if (dispValue()) {\n {{ txtValue() | date: \"short\" }}\n }\n @if (!dispValue()) {\n {{ txtValue() }}\n }\n </span>\n }\n @case (\"date\") {\n <span class=\"editable disp-datetime\" (click)=\"enableEditMode()\">\n @if (dispValue()) {\n {{ txtValue() | date: \"shortDate\" }}\n }\n @if (!dispValue()) {\n {{ txtValue() }}\n }\n </span>\n }\n }\n</ng-template>\n\n<!-- TEMPLATE \u00E9dition -->\n<ng-template #editTpl let-form=\"form\">\n @switch (realEditor()) {\n @case (\"input.text\") {\n <input\n type=\"text\"\n [formControl]=\"form.get(field())\"\n [class]=\"inputClasses()\"\n (keyup.escape)=\"unsetEdit()\"\n [placeholder]=\"realPlaceholder()\"\n />\n @if (realHelp()) {\n <div class=\"form-text\">\n {{ realHelp() }}\n @if (required()) {\n <span class=\"ms-1\">(requis)</span>\n }\n </div>\n }\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['minlength']\"\n >\n Trop court : {{ $any(manager()).minLength }} caract\u00E8res minimum...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['maxlength']\"\n >\n Trop long : {{ $any(manager()).maxLength }} caract\u00E8res maximum...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['pattern']\"\n >\n Format invalide...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['required']\"\n >\n Ce champ est requis...\n </div>\n }\n @case (\"input.email\") {\n <input\n type=\"email\"\n [formControl]=\"form.get(field())\"\n [class]=\"inputClasses()\"\n (keyup.escape)=\"unsetEdit()\"\n [placeholder]=\"realPlaceholder()\"\n />\n @if (realHelp()) {\n <div class=\"form-text\">\n {{ realHelp() }}\n @if (required()) {\n <span class=\"ms-1\">(requis)</span>\n }\n </div>\n }\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['minlength']\"\n >\n Trop court : {{ $any(manager()).minLength }} caract\u00E8res minimum...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['maxlength']\"\n >\n Trop long : {{ $any(manager()).maxLength }} caract\u00E8res maximum...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['pattern']\"\n >\n Format invalide...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['email']\"\n >\n Format d'email invalide...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['required']\"\n >\n Ce champ est requis...\n </div>\n }\n @case (\"input.password\") {\n <input\n type=\"password\"\n [formControl]=\"form.get(field())\"\n [class]=\"inputClasses()\"\n (keyup.escape)=\"unsetEdit()\"\n [placeholder]=\"realPlaceholder()\"\n />\n @if (realHelp()) {\n <div class=\"form-text\">\n {{ realHelp() }}\n @if (required()) {\n <span class=\"ms-1\">(requis)</span>\n }\n </div>\n }\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['minlength']\"\n >\n Trop court : {{ $any(manager()).minLength }} caract\u00E8res minimum...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['maxlength']\"\n >\n Trop long : {{ $any(manager()).maxLength }} caract\u00E8res maximum...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['pattern']\"\n >\n Format invalide...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['required']\"\n >\n Ce champ est requis...\n </div>\n }\n @case (\"input.datetime\") {\n <input\n type=\"datetime-local\"\n [formControl]=\"form.get(field())\"\n [class]=\"inputClasses()\"\n (keyup.escape)=\"unsetEdit()\"\n (keyup.enter)=\"update()\"\n />\n <div class=\"form-text\">{{ realHelp() }}</div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['required']\"\n >\n Ce champ est requis...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['minDate']\"\n >\n Doit \u00EAtre post\u00E9rieur \u00E0 {{ $any(manager()).min | date: \"short\" }}...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['maxDate']\"\n >\n Doit \u00EAtre ant\u00E9rieur \u00E0 {{ $any(manager()).max | date: \"short\" }}...\n </div>\n }\n @case (\"input.date\") {\n <input\n type=\"date\"\n [formControl]=\"form.get(field())\"\n [class]=\"inputClasses()\"\n (keyup.escape)=\"unsetEdit()\"\n (keyup.enter)=\"update()\"\n />\n <div class=\"form-text\">{{ realHelp() }}</div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['required']\"\n >\n Ce champ est requis...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['minDate']\"\n >\n Doit \u00EAtre post\u00E9rieur \u00E0 {{ $any(manager()).min | date: \"short\" }}...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['maxDate']\"\n >\n Doit \u00EAtre ant\u00E9rieur \u00E0 {{ $any(manager()).max | date: \"short\" }}...\n </div>\n }\n @case (\"input.number\") {\n <input\n type=\"number\"\n [formControl]=\"form.get(field())\"\n [class]=\"inputClasses()\"\n (keyup.escape)=\"unsetEdit()\"\n [placeholder]=\"realPlaceholder()\"\n />\n @if (realHelp()) {\n <div class=\"form-text\">\n {{ realHelp() }}\n @if (required()) {\n <span class=\"ms-1\">(requis)</span>\n }\n </div>\n }\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['min']\"\n >\n Trop petit : minimum {{ $any(manager()).min }}...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['max']\"\n >\n Trop grand : maximum {{ $any(manager()).max }}...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['required']\"\n >\n Ce champ est requis...\n </div>\n }\n @case (\"input.decimal\") {\n <input\n type=\"number\"\n [formControl]=\"form.get(field())\"\n [class]=\"inputClasses()\"\n (keyup.escape)=\"unsetEdit()\"\n [placeholder]=\"realPlaceholder()\"\n />\n @if (realHelp()) {\n <div class=\"form-text\">\n {{ realHelp() }}\n @if (required()) {\n <span class=\"ms-1\">(requis)</span>\n }\n </div>\n }\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['min']\"\n >\n Trop petit : minimum {{ $any(manager()).min }}...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['max']\"\n >\n Trop grand : maximum {{ $any(manager()).max }}...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['required']\"\n >\n Ce champ est requis...\n </div>\n }\n @case (\"input.checkbox\") {\n @let v = $any(this.model())[this.field()];\n <div class=\"btn-group btn-group-sm\" role=\"group\">\n <button\n type=\"button\"\n [class]=\"v===true ? 'btn btn-primary' : 'btn btn-outline-primary'\"\n (click)=\"form.get(field())?.setValue(true); update()\"\n (keyup.escape)=\"unsetEdit()\"\n >\n Oui\n </button>\n <button\n type=\"button\"\n [class]=\"v===false ? 'btn btn-primary' : 'btn btn-outline-primary'\"\n (click)=\"form.get(field())?.setValue(false); update()\"\n (keyup.escape)=\"unsetEdit()\"\n >\n Non\n </button>\n </div>\n <div class=\"form-text\">{{ realHelp() }}</div>\n }\n @case (\"textarea\") {\n <textarea\n [formControl]=\"form.get(field())\"\n (keyup.escape)=\"unsetEdit()\"\n [class]=\"inputClasses()\"\n (keyup.control.enter)=\"update()\"\n [placeholder]=\"realPlaceholder()\"\n ></textarea>\n @if (mode() === \"dd\") {\n <button\n class=\"btn btn-sm btn-link w-100 dispedit-text-update-button\"\n (click)=\"update()\"\n >\n <i class=\"bi bi-save\"></i>\n </button>\n }\n @if (realHelp()) {\n <div class=\"form-text\">\n {{ realHelp() }}\n @if (required()) {\n <span class=\"ms-1\">(requis)</span>\n }\n </div>\n }\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['minlength']\"\n >\n Trop court : {{ $any(manager()).minLength }} caract\u00E8res minimum...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['maxlength']\"\n >\n Trop long : {{ $any(manager()).maxLength }} caract\u00E8res maximum...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['pattern']\"\n >\n Format invalide...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['required']\"\n >\n Ce champ est requis...\n </div>\n }\n @case (\"fkselect\") {\n <data-fkselect\n [collection]=\"collection()\"\n [filter]=\"filter()\"\n [display]=\"display()\"\n (selected)=\"selectedRefItem($event)\"\n [placeholder]=\"placeholder()\"\n (cancelled)=\"unsetEdit()\"\n (cleared)=\"selectedRefItem(null)\"\n ></data-fkselect>\n }\n @case (\"m2mselect\") {\n <data-m2mselect\n [collection]=\"collection()\"\n [filter]=\"filter()\"\n (changed)=\"update()\"\n [formControl]=\"form.get(field())\"\n (detailsChanged)=\"onM2MValuesChanges($event)\"\n [model]=\"model()\"\n [field]=\"field()\"\n [placeholder]=\"placeholder()\"\n ></data-m2mselect>\n }\n @case (\"select\") {\n <select\n [formControl]=\"form.get(field())\"\n (keyup.escape)=\"unsetEdit()\"\n (change)=\"update()\"\n [class]=\"inputClasses()\"\n >\n @for (c of realChoices(); track c) {\n <option [ngValue]=\"c.value !== undefined ? c.value : c\">\n {{ c.desc ? c.desc : c }}\n </option>\n }\n </select>\n <div class=\"form-text\">{{ realHelp() }}</div>\n }\n }\n</ng-template>\n<!-- Disp/edit toggler-->\n<ng-template #dispeditTpl>\n @if (!edit()) {\n <ng-container *ngTemplateOutlet=\"dispTpl\"></ng-container>\n }\n @if (edit()) {\n @if (fg(); as fg) {\n <form [formGroup]=\"fg\" (submit)=\"update()\">\n <ng-container\n *ngTemplateOutlet=\"editTpl; context: { form: fg }\"\n ></ng-container>\n </form>\n }\n }\n</ng-template>\n<!-- DispEdit noform-->\n<ng-template #dispeditFormTpl>\n @if (!edit()) {\n <ng-container *ngTemplateOutlet=\"dispTpl\"></ng-container>\n }\n @if (edit()) {\n @if (form()) {\n <ng-container\n *ngTemplateOutlet=\"editTpl; context: { form: form() }\"\n ></ng-container>\n }\n }\n</ng-template>\n<!-- Dd display-->\n@if (mode() === \"dd\") {\n @if (!hideLabel()) {\n <dt [class.required]=\"required()\">\n <span class=\"editable\" (click)=\"toggleEdit()\">\n <ng-container *ngTemplateOutlet=\"titleTpl\"></ng-container\n ></span>\n @if (realDefault() !== undefined && edit()) {\n <span class=\"pointer float-end\" (click)=\"setDefault()\"\n ><i class=\"bi bi-trash ms-2\"></i\n ></span>\n }\n </dt>\n }\n <dd [class.mb-0]=\"hideLabel()\">\n <ng-container *ngTemplateOutlet=\"dispeditTpl\"></ng-container>\n </dd>\n}\n<!-- Inline display-->\n@if (mode() === \"inline\") {\n @if (!hideLabel()) {\n @if (realDefault() !== undefined && edit()) {\n <span class=\"pointer float-end\" (click)=\"setDefault()\"\n ><i class=\"bi bi-trash ms-2\"></i\n ></span>\n }\n <label [class.required]=\"required()\">\n <ng-container *ngTemplateOutlet=\"titleTpl\"></ng-container>\n </label>\n }\n <ng-container *ngTemplateOutlet=\"dispeditTpl\"></ng-container>\n}\n<!-- Form display-->\n@if (mode() === \"form\") {\n @if (!hideLabel()) {\n @if (realDefault() !== undefined && edit()) {\n <span class=\"pointer float-end\" (click)=\"setDefault()\"\n ><i class=\"bi bi-trash ms-2\"></i\n ></span>\n }\n <label [class.required]=\"required()\">\n <ng-container *ngTemplateOutlet=\"titleTpl\"></ng-container>\n </label>\n }\n <ng-container *ngTemplateOutlet=\"dispeditFormTpl\"></ng-container>\n}\n", styles: [".editable{cursor:pointer}form.inline{display:inline-block}.required{font-weight:700}.required:after{content:\" (*)\"}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$3.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$3.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$3.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$3.NumberValueAccessor, selector: "input[type=number]:not([ngNoCva])[formControlName],input[type=number]:not([ngNoCva])[formControl],input[type=number]:not([ngNoCva])[ngModel]" }, { kind: "directive", type: i1$3.SelectControlValueAccessor, selector: "select:not([multiple]):not([ngNoCva])[formControlName],select:not([multiple]):not([ngNoCva])[formControl],select:not([multiple]):not([ngNoCva])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$3.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: FkselectComponent, selector: "data-fkselect", inputs: ["model", "field", "edit", "value", "queryset", "collection", "update", "filter", "mode", "display", "search", "label", "placeholder", "inputClasses"], outputs: ["querysetChange", "collectionChange", "selected", "cancelled", "cleared"] }, { kind: "component", type: M2mselectComponent, selector: "data-m2mselect", inputs: ["model", "field", "edit", "values", "queryset", "collection", "filter", "mode", "display", "search", "label", "placeholder", "emptyLabel", "inputClasses"], outputs: ["valuesChange", "querysetChange", "collectionChange", "added", "removed", "cancelled", "cleared", "detailsChanged", "changed"] }, { kind: "pipe", type: DatePipe, name: "date" }] });
|
|
7363
|
+
_setDisplayClasses() {
|
|
7364
|
+
// Reserved: display classes are currently applied in the template.
|
|
7365
|
+
}
|
|
7366
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: DispeditComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
7367
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: DispeditComponent, isStandalone: true, selector: "data-dispedit", inputs: { model: { classPropertyName: "model", publicName: "model", isSignal: true, isRequired: true, transformFunction: null }, field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null }, form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: false, transformFunction: null }, edit: { classPropertyName: "edit", publicName: "edit", isSignal: true, isRequired: false, transformFunction: null }, editable: { classPropertyName: "editable", publicName: "editable", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, choices: { classPropertyName: "choices", publicName: "choices", isSignal: true, isRequired: false, transformFunction: null }, inputClasses: { classPropertyName: "inputClasses", publicName: "inputClasses", isSignal: true, isRequired: false, transformFunction: null }, editor: { classPropertyName: "editor", publicName: "editor", isSignal: true, isRequired: false, transformFunction: null }, viewer: { classPropertyName: "viewer", publicName: "viewer", isSignal: true, isRequired: false, transformFunction: null }, default: { classPropertyName: "default", publicName: "default", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, help: { classPropertyName: "help", publicName: "help", isSignal: true, isRequired: false, transformFunction: null }, hideLabel: { classPropertyName: "hideLabel", publicName: "hideLabel", isSignal: true, isRequired: false, transformFunction: null }, queryset: { classPropertyName: "queryset", publicName: "queryset", isSignal: true, isRequired: false, transformFunction: null }, collection: { classPropertyName: "collection", publicName: "collection", isSignal: true, isRequired: false, transformFunction: null }, display: { classPropertyName: "display", publicName: "display", isSignal: true, isRequired: false, transformFunction: null }, filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { edit: "editChange", inputClasses: "inputClassesChange", viewer: "viewerChange", changed: "changed" }, ngImport: i0, template: "<ng-template #titleTpl>\n <ng-content></ng-content>\n</ng-template>\n\n<!-- TEMPLATE affichage -->\n<ng-template #dispTpl>\n @switch (realDisplay()) {\n @case (\"text\") {\n <span\n class=\"editable disp-text\"\n role=\"button\"\n tabindex=\"0\"\n (click)=\"enableEditMode()\"\n (keydown.enter)=\"enableEditMode()\"\n (keydown.space)=\"$event.preventDefault(); enableEditMode()\"\n >\n {{ txtValue() }}\n </span>\n }\n @case (\"choice\") {\n <span\n class=\"editable disp-choice\"\n role=\"button\"\n tabindex=\"0\"\n (click)=\"enableEditMode()\"\n (keydown.enter)=\"enableEditMode()\"\n (keydown.space)=\"$event.preventDefault(); enableEditMode()\"\n >\n {{ txtValue() }}\n </span>\n }\n @case (\"decimal\") {\n <span\n class=\"editable disp-decimal\"\n role=\"button\"\n tabindex=\"0\"\n (click)=\"enableEditMode()\"\n (keydown.enter)=\"enableEditMode()\"\n (keydown.space)=\"$event.preventDefault(); enableEditMode()\"\n >\n {{ txtValue() }}\n </span>\n }\n @case (\"boolean\") {\n <span\n class=\"editable disp-boolean\"\n role=\"button\"\n tabindex=\"0\"\n (click)=\"enableEditMode()\"\n (keydown.enter)=\"enableEditMode()\"\n (keydown.space)=\"$event.preventDefault(); enableEditMode()\"\n >\n {{ txtValue() }}\n </span>\n }\n @case (\"fkdetails\") {\n <span\n class=\"editable disp-fkdetails\"\n role=\"button\"\n tabindex=\"0\"\n (click)=\"enableEditMode()\"\n (keydown.enter)=\"enableEditMode()\"\n (keydown.space)=\"$event.preventDefault(); enableEditMode()\"\n >\n <div class=\"fkitem\">{{ txtValue() }}</div>\n </span>\n }\n @case (\"m2mdetails\") {\n <span\n class=\"editable disp-m2mdetails\"\n role=\"button\"\n tabindex=\"0\"\n (click)=\"enableEditMode()\"\n (keydown.enter)=\"enableEditMode()\"\n (keydown.space)=\"$event.preventDefault(); enableEditMode()\"\n >\n @for (v of txtValues(); track v) {\n <div class=\"m2mitem\">{{ v }}</div>\n }\n </span>\n }\n @case (\"datetime\") {\n <span\n class=\"editable disp-datetime\"\n role=\"button\"\n tabindex=\"0\"\n (click)=\"enableEditMode()\"\n (keydown.enter)=\"enableEditMode()\"\n (keydown.space)=\"$event.preventDefault(); enableEditMode()\"\n >\n @if (dispValue()) {\n {{ txtValue() | date: \"short\" }}\n }\n @if (!dispValue()) {\n {{ txtValue() }}\n }\n </span>\n }\n @case (\"date\") {\n <span\n class=\"editable disp-datetime\"\n role=\"button\"\n tabindex=\"0\"\n (click)=\"enableEditMode()\"\n (keydown.enter)=\"enableEditMode()\"\n (keydown.space)=\"$event.preventDefault(); enableEditMode()\"\n >\n @if (dispValue()) {\n {{ txtValue() | date: \"shortDate\" }}\n }\n @if (!dispValue()) {\n {{ txtValue() }}\n }\n </span>\n }\n }\n</ng-template>\n\n<!-- TEMPLATE \u00E9dition -->\n<ng-template #editTpl let-form=\"form\">\n @switch (realEditor()) {\n @case (\"input.text\") {\n <input\n [attr.id]=\"inputId\"\n type=\"text\"\n [formControl]=\"form.get(field())\"\n [class]=\"inputClasses()\"\n (keyup.escape)=\"unsetEdit()\"\n [placeholder]=\"realPlaceholder()\"\n />\n @if (realHelp()) {\n <div class=\"form-text\">\n {{ realHelp() }}\n @if (required()) {\n <span class=\"ms-1\">(requis)</span>\n }\n </div>\n }\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['minlength']\"\n >\n Trop court : {{ $any(manager()).minLength }} caract\u00E8res minimum...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['maxlength']\"\n >\n Trop long : {{ $any(manager()).maxLength }} caract\u00E8res maximum...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['pattern']\"\n >\n Format invalide...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['required']\"\n >\n Ce champ est requis...\n </div>\n }\n @case (\"input.email\") {\n <input\n [attr.id]=\"inputId\"\n type=\"email\"\n [formControl]=\"form.get(field())\"\n [class]=\"inputClasses()\"\n (keyup.escape)=\"unsetEdit()\"\n [placeholder]=\"realPlaceholder()\"\n />\n @if (realHelp()) {\n <div class=\"form-text\">\n {{ realHelp() }}\n @if (required()) {\n <span class=\"ms-1\">(requis)</span>\n }\n </div>\n }\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['minlength']\"\n >\n Trop court : {{ $any(manager()).minLength }} caract\u00E8res minimum...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['maxlength']\"\n >\n Trop long : {{ $any(manager()).maxLength }} caract\u00E8res maximum...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['pattern']\"\n >\n Format invalide...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['email']\"\n >\n Format d'email invalide...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['required']\"\n >\n Ce champ est requis...\n </div>\n }\n @case (\"input.password\") {\n <input\n [attr.id]=\"inputId\"\n type=\"password\"\n [formControl]=\"form.get(field())\"\n [class]=\"inputClasses()\"\n (keyup.escape)=\"unsetEdit()\"\n [placeholder]=\"realPlaceholder()\"\n />\n @if (realHelp()) {\n <div class=\"form-text\">\n {{ realHelp() }}\n @if (required()) {\n <span class=\"ms-1\">(requis)</span>\n }\n </div>\n }\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['minlength']\"\n >\n Trop court : {{ $any(manager()).minLength }} caract\u00E8res minimum...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['maxlength']\"\n >\n Trop long : {{ $any(manager()).maxLength }} caract\u00E8res maximum...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['pattern']\"\n >\n Format invalide...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['required']\"\n >\n Ce champ est requis...\n </div>\n }\n @case (\"input.datetime\") {\n <input\n [attr.id]=\"inputId\"\n type=\"datetime-local\"\n [formControl]=\"form.get(field())\"\n [class]=\"inputClasses()\"\n (keyup.escape)=\"unsetEdit()\"\n (keyup.enter)=\"update()\"\n />\n <div class=\"form-text\">{{ realHelp() }}</div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['required']\"\n >\n Ce champ est requis...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['minDate']\"\n >\n Doit \u00EAtre post\u00E9rieur \u00E0 {{ $any(manager()).min | date: \"short\" }}...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['maxDate']\"\n >\n Doit \u00EAtre ant\u00E9rieur \u00E0 {{ $any(manager()).max | date: \"short\" }}...\n </div>\n }\n @case (\"input.date\") {\n <input\n [attr.id]=\"inputId\"\n type=\"date\"\n [formControl]=\"form.get(field())\"\n [class]=\"inputClasses()\"\n (keyup.escape)=\"unsetEdit()\"\n (keyup.enter)=\"update()\"\n />\n <div class=\"form-text\">{{ realHelp() }}</div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['required']\"\n >\n Ce champ est requis...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['minDate']\"\n >\n Doit \u00EAtre post\u00E9rieur \u00E0 {{ $any(manager()).min | date: \"short\" }}...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['maxDate']\"\n >\n Doit \u00EAtre ant\u00E9rieur \u00E0 {{ $any(manager()).max | date: \"short\" }}...\n </div>\n }\n @case (\"input.number\") {\n <input\n [attr.id]=\"inputId\"\n type=\"number\"\n [formControl]=\"form.get(field())\"\n [class]=\"inputClasses()\"\n (keyup.escape)=\"unsetEdit()\"\n [placeholder]=\"realPlaceholder()\"\n />\n @if (realHelp()) {\n <div class=\"form-text\">\n {{ realHelp() }}\n @if (required()) {\n <span class=\"ms-1\">(requis)</span>\n }\n </div>\n }\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['min']\"\n >\n Trop petit : minimum {{ $any(manager()).min }}...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['max']\"\n >\n Trop grand : maximum {{ $any(manager()).max }}...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['required']\"\n >\n Ce champ est requis...\n </div>\n }\n @case (\"input.decimal\") {\n <input\n [attr.id]=\"inputId\"\n type=\"number\"\n [formControl]=\"form.get(field())\"\n [class]=\"inputClasses()\"\n (keyup.escape)=\"unsetEdit()\"\n [placeholder]=\"realPlaceholder()\"\n />\n @if (realHelp()) {\n <div class=\"form-text\">\n {{ realHelp() }}\n @if (required()) {\n <span class=\"ms-1\">(requis)</span>\n }\n </div>\n }\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['min']\"\n >\n Trop petit : minimum {{ $any(manager()).min }}...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['max']\"\n >\n Trop grand : maximum {{ $any(manager()).max }}...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['required']\"\n >\n Ce champ est requis...\n </div>\n }\n @case (\"input.checkbox\") {\n @let v = $any(this.model())[this.field()];\n <div class=\"btn-group btn-group-sm\" role=\"group\">\n <button\n type=\"button\"\n [class]=\"v === true ? 'btn btn-primary' : 'btn btn-outline-primary'\"\n (click)=\"form.get(field())?.setValue(true); update()\"\n (keyup.escape)=\"unsetEdit()\"\n >\n Oui\n </button>\n <button\n type=\"button\"\n [class]=\"v === false ? 'btn btn-primary' : 'btn btn-outline-primary'\"\n (click)=\"form.get(field())?.setValue(false); update()\"\n (keyup.escape)=\"unsetEdit()\"\n >\n Non\n </button>\n </div>\n <div class=\"form-text\">{{ realHelp() }}</div>\n }\n @case (\"textarea\") {\n <textarea\n [attr.id]=\"inputId\"\n [formControl]=\"form.get(field())\"\n (keyup.escape)=\"unsetEdit()\"\n [class]=\"inputClasses()\"\n (keyup.control.enter)=\"update()\"\n [placeholder]=\"realPlaceholder()\"\n ></textarea>\n @if (mode() === \"dd\") {\n <button class=\"btn btn-sm btn-link w-100 dispedit-text-update-button\" (click)=\"update()\">\n <i class=\"bi bi-save\"></i>\n </button>\n }\n @if (realHelp()) {\n <div class=\"form-text\">\n {{ realHelp() }}\n @if (required()) {\n <span class=\"ms-1\">(requis)</span>\n }\n </div>\n }\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['minlength']\"\n >\n Trop court : {{ $any(manager()).minLength }} caract\u00E8res minimum...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['maxlength']\"\n >\n Trop long : {{ $any(manager()).maxLength }} caract\u00E8res maximum...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['pattern']\"\n >\n Format invalide...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['required']\"\n >\n Ce champ est requis...\n </div>\n }\n @case (\"fkselect\") {\n <data-fkselect\n [inputId]=\"inputId\"\n [collection]=\"collection()\"\n [filter]=\"filter()\"\n [display]=\"display()\"\n (selected)=\"selectedRefItem($event)\"\n [placeholder]=\"placeholder()\"\n (cancelled)=\"unsetEdit()\"\n (cleared)=\"selectedRefItem(null)\"\n ></data-fkselect>\n }\n @case (\"m2mselect\") {\n <data-m2mselect\n [inputId]=\"inputId\"\n [collection]=\"collection()\"\n [filter]=\"filter()\"\n (changed)=\"update()\"\n [formControl]=\"form.get(field())\"\n (detailsChanged)=\"onM2MValuesChanges($event)\"\n [model]=\"model()\"\n [field]=\"field()\"\n [placeholder]=\"placeholder()\"\n ></data-m2mselect>\n }\n @case (\"select\") {\n <select\n [attr.id]=\"inputId\"\n [formControl]=\"form.get(field())\"\n (keyup.escape)=\"unsetEdit()\"\n (change)=\"update()\"\n [class]=\"inputClasses()\"\n >\n @for (c of realChoices(); track c) {\n <option [ngValue]=\"c.value !== undefined ? c.value : c\">\n {{ c.desc ? c.desc : c }}\n </option>\n }\n </select>\n <div class=\"form-text\">{{ realHelp() }}</div>\n }\n }\n</ng-template>\n<!-- Disp/edit toggler-->\n<ng-template #dispeditTpl>\n @if (!edit()) {\n <ng-container *ngTemplateOutlet=\"dispTpl\"></ng-container>\n }\n @if (edit()) {\n @if (fg(); as fg) {\n <form [formGroup]=\"fg\" (submit)=\"update()\">\n <ng-container *ngTemplateOutlet=\"editTpl; context: { form: fg }\"></ng-container>\n </form>\n }\n }\n</ng-template>\n<!-- DispEdit noform-->\n<ng-template #dispeditFormTpl>\n @if (!edit()) {\n <ng-container *ngTemplateOutlet=\"dispTpl\"></ng-container>\n }\n @if (edit()) {\n @if (form()) {\n <ng-container *ngTemplateOutlet=\"editTpl; context: { form: form() }\"></ng-container>\n }\n }\n</ng-template>\n<!-- Dd display-->\n@if (mode() === \"dd\") {\n @if (!hideLabel()) {\n <dt [class.required]=\"required()\">\n <span\n class=\"editable\"\n role=\"button\"\n tabindex=\"0\"\n (click)=\"toggleEdit()\"\n (keydown.enter)=\"toggleEdit()\"\n (keydown.space)=\"$event.preventDefault(); toggleEdit()\"\n >\n <ng-container *ngTemplateOutlet=\"titleTpl\"></ng-container>\n </span>\n @if (realDefault() !== undefined && edit()) {\n <span\n class=\"pointer float-end\"\n role=\"button\"\n tabindex=\"0\"\n aria-label=\"R\u00E9tablir la valeur par d\u00E9faut\"\n (click)=\"setDefault()\"\n (keydown.enter)=\"setDefault()\"\n (keydown.space)=\"$event.preventDefault(); setDefault()\"\n >\n <i class=\"bi bi-trash ms-2\"></i>\n </span>\n }\n </dt>\n }\n <dd [class.mb-0]=\"hideLabel()\">\n <ng-container *ngTemplateOutlet=\"dispeditTpl\"></ng-container>\n </dd>\n}\n<!-- Inline display-->\n@if (mode() === \"inline\") {\n @if (!hideLabel()) {\n @if (realDefault() !== undefined && edit()) {\n <span\n class=\"pointer float-end\"\n role=\"button\"\n tabindex=\"0\"\n aria-label=\"R\u00E9tablir la valeur par d\u00E9faut\"\n (click)=\"setDefault()\"\n (keydown.enter)=\"setDefault()\"\n (keydown.space)=\"$event.preventDefault(); setDefault()\"\n >\n <i class=\"bi bi-trash ms-2\"></i>\n </span>\n }\n <label [class.required]=\"required()\" [attr.for]=\"inputId\">\n <ng-container *ngTemplateOutlet=\"titleTpl\"></ng-container>\n </label>\n }\n <ng-container *ngTemplateOutlet=\"dispeditTpl\"></ng-container>\n}\n<!-- Form display-->\n@if (mode() === \"form\") {\n @if (!hideLabel()) {\n @if (realDefault() !== undefined && edit()) {\n <span\n class=\"pointer float-end\"\n role=\"button\"\n tabindex=\"0\"\n aria-label=\"R\u00E9tablir la valeur par d\u00E9faut\"\n (click)=\"setDefault()\"\n (keydown.enter)=\"setDefault()\"\n (keydown.space)=\"$event.preventDefault(); setDefault()\"\n >\n <i class=\"bi bi-trash ms-2\"></i>\n </span>\n }\n <label [class.required]=\"required()\" [attr.for]=\"inputId\">\n <ng-container *ngTemplateOutlet=\"titleTpl\"></ng-container>\n </label>\n }\n <ng-container *ngTemplateOutlet=\"dispeditFormTpl\"></ng-container>\n}\n", styles: [".editable{cursor:pointer}form.inline{display:inline-block}.required{font-weight:700}.required:after{content:\" (*)\"}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$2.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$2.NumberValueAccessor, selector: "input[type=number]:not([ngNoCva])[formControlName],input[type=number]:not([ngNoCva])[formControl],input[type=number]:not([ngNoCva])[ngModel]" }, { kind: "directive", type: i1$2.SelectControlValueAccessor, selector: "select:not([multiple]):not([ngNoCva])[formControlName],select:not([multiple]):not([ngNoCva])[formControl],select:not([multiple]):not([ngNoCva])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: FkselectComponent, selector: "data-fkselect", inputs: ["model", "field", "edit", "value", "queryset", "collection", "update", "filter", "mode", "display", "search", "label", "inputId", "placeholder", "inputClasses"], outputs: ["querysetChange", "collectionChange", "selected", "cancelled", "cleared"] }, { kind: "component", type: M2mselectComponent, selector: "data-m2mselect", inputs: ["model", "field", "edit", "values", "queryset", "collection", "filter", "mode", "display", "search", "label", "inputId", "placeholder", "emptyLabel", "inputClasses"], outputs: ["valuesChange", "querysetChange", "collectionChange", "added", "removed", "cancelled", "cleared", "detailsChanged", "changed"] }, { kind: "pipe", type: DatePipe, name: "date" }] });
|
|
7264
7368
|
}
|
|
7265
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
7369
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: DispeditComponent, decorators: [{
|
|
7266
7370
|
type: Component,
|
|
7267
|
-
args: [{ selector: 'data-dispedit', imports: [
|
|
7268
|
-
DatePipe,
|
|
7269
|
-
NgTemplateOutlet,
|
|
7270
|
-
ReactiveFormsModule,
|
|
7271
|
-
FkselectComponent,
|
|
7272
|
-
M2mselectComponent,
|
|
7273
|
-
], template: "<ng-template #titleTpl>\n <ng-content></ng-content>\n</ng-template>\n\n<!-- TEMPLATE affichage -->\n<ng-template #dispTpl>\n @switch (realDisplay()) {\n @case (\"text\") {\n <span class=\"editable disp-text\" (click)=\"enableEditMode()\">{{\n txtValue()\n }}</span>\n }\n @case (\"choice\") {\n <span class=\"editable disp-choice\" (click)=\"enableEditMode()\">{{\n txtValue()\n }}</span>\n }\n @case (\"decimal\") {\n <span class=\"editable disp-decimal\" (click)=\"enableEditMode()\">{{\n txtValue()\n }}</span>\n }\n @case (\"boolean\") {\n <span class=\"editable disp-boolean\" (click)=\"enableEditMode()\">{{\n txtValue()\n }}</span>\n }\n @case (\"fkdetails\") {\n <span class=\"editable disp-fkdetails\" (click)=\"enableEditMode()\">\n <div class=\"fkitem\">{{ txtValue() }}</div></span\n >\n }\n @case (\"m2mdetails\") {\n <span class=\"editable disp-m2mdetails\" (click)=\"enableEditMode()\">\n @for (v of txtValues(); track v) {\n <div class=\"m2mitem\">{{ v }}</div>\n }\n </span>\n }\n @case (\"datetime\") {\n <span class=\"editable disp-datetime\" (click)=\"enableEditMode()\">\n @if (dispValue()) {\n {{ txtValue() | date: \"short\" }}\n }\n @if (!dispValue()) {\n {{ txtValue() }}\n }\n </span>\n }\n @case (\"date\") {\n <span class=\"editable disp-datetime\" (click)=\"enableEditMode()\">\n @if (dispValue()) {\n {{ txtValue() | date: \"shortDate\" }}\n }\n @if (!dispValue()) {\n {{ txtValue() }}\n }\n </span>\n }\n }\n</ng-template>\n\n<!-- TEMPLATE \u00E9dition -->\n<ng-template #editTpl let-form=\"form\">\n @switch (realEditor()) {\n @case (\"input.text\") {\n <input\n type=\"text\"\n [formControl]=\"form.get(field())\"\n [class]=\"inputClasses()\"\n (keyup.escape)=\"unsetEdit()\"\n [placeholder]=\"realPlaceholder()\"\n />\n @if (realHelp()) {\n <div class=\"form-text\">\n {{ realHelp() }}\n @if (required()) {\n <span class=\"ms-1\">(requis)</span>\n }\n </div>\n }\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['minlength']\"\n >\n Trop court : {{ $any(manager()).minLength }} caract\u00E8res minimum...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['maxlength']\"\n >\n Trop long : {{ $any(manager()).maxLength }} caract\u00E8res maximum...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['pattern']\"\n >\n Format invalide...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['required']\"\n >\n Ce champ est requis...\n </div>\n }\n @case (\"input.email\") {\n <input\n type=\"email\"\n [formControl]=\"form.get(field())\"\n [class]=\"inputClasses()\"\n (keyup.escape)=\"unsetEdit()\"\n [placeholder]=\"realPlaceholder()\"\n />\n @if (realHelp()) {\n <div class=\"form-text\">\n {{ realHelp() }}\n @if (required()) {\n <span class=\"ms-1\">(requis)</span>\n }\n </div>\n }\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['minlength']\"\n >\n Trop court : {{ $any(manager()).minLength }} caract\u00E8res minimum...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['maxlength']\"\n >\n Trop long : {{ $any(manager()).maxLength }} caract\u00E8res maximum...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['pattern']\"\n >\n Format invalide...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['email']\"\n >\n Format d'email invalide...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['required']\"\n >\n Ce champ est requis...\n </div>\n }\n @case (\"input.password\") {\n <input\n type=\"password\"\n [formControl]=\"form.get(field())\"\n [class]=\"inputClasses()\"\n (keyup.escape)=\"unsetEdit()\"\n [placeholder]=\"realPlaceholder()\"\n />\n @if (realHelp()) {\n <div class=\"form-text\">\n {{ realHelp() }}\n @if (required()) {\n <span class=\"ms-1\">(requis)</span>\n }\n </div>\n }\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['minlength']\"\n >\n Trop court : {{ $any(manager()).minLength }} caract\u00E8res minimum...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['maxlength']\"\n >\n Trop long : {{ $any(manager()).maxLength }} caract\u00E8res maximum...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['pattern']\"\n >\n Format invalide...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['required']\"\n >\n Ce champ est requis...\n </div>\n }\n @case (\"input.datetime\") {\n <input\n type=\"datetime-local\"\n [formControl]=\"form.get(field())\"\n [class]=\"inputClasses()\"\n (keyup.escape)=\"unsetEdit()\"\n (keyup.enter)=\"update()\"\n />\n <div class=\"form-text\">{{ realHelp() }}</div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['required']\"\n >\n Ce champ est requis...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['minDate']\"\n >\n Doit \u00EAtre post\u00E9rieur \u00E0 {{ $any(manager()).min | date: \"short\" }}...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['maxDate']\"\n >\n Doit \u00EAtre ant\u00E9rieur \u00E0 {{ $any(manager()).max | date: \"short\" }}...\n </div>\n }\n @case (\"input.date\") {\n <input\n type=\"date\"\n [formControl]=\"form.get(field())\"\n [class]=\"inputClasses()\"\n (keyup.escape)=\"unsetEdit()\"\n (keyup.enter)=\"update()\"\n />\n <div class=\"form-text\">{{ realHelp() }}</div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['required']\"\n >\n Ce champ est requis...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['minDate']\"\n >\n Doit \u00EAtre post\u00E9rieur \u00E0 {{ $any(manager()).min | date: \"short\" }}...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['maxDate']\"\n >\n Doit \u00EAtre ant\u00E9rieur \u00E0 {{ $any(manager()).max | date: \"short\" }}...\n </div>\n }\n @case (\"input.number\") {\n <input\n type=\"number\"\n [formControl]=\"form.get(field())\"\n [class]=\"inputClasses()\"\n (keyup.escape)=\"unsetEdit()\"\n [placeholder]=\"realPlaceholder()\"\n />\n @if (realHelp()) {\n <div class=\"form-text\">\n {{ realHelp() }}\n @if (required()) {\n <span class=\"ms-1\">(requis)</span>\n }\n </div>\n }\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['min']\"\n >\n Trop petit : minimum {{ $any(manager()).min }}...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['max']\"\n >\n Trop grand : maximum {{ $any(manager()).max }}...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['required']\"\n >\n Ce champ est requis...\n </div>\n }\n @case (\"input.decimal\") {\n <input\n type=\"number\"\n [formControl]=\"form.get(field())\"\n [class]=\"inputClasses()\"\n (keyup.escape)=\"unsetEdit()\"\n [placeholder]=\"realPlaceholder()\"\n />\n @if (realHelp()) {\n <div class=\"form-text\">\n {{ realHelp() }}\n @if (required()) {\n <span class=\"ms-1\">(requis)</span>\n }\n </div>\n }\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['min']\"\n >\n Trop petit : minimum {{ $any(manager()).min }}...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['max']\"\n >\n Trop grand : maximum {{ $any(manager()).max }}...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['required']\"\n >\n Ce champ est requis...\n </div>\n }\n @case (\"input.checkbox\") {\n @let v = $any(this.model())[this.field()];\n <div class=\"btn-group btn-group-sm\" role=\"group\">\n <button\n type=\"button\"\n [class]=\"v===true ? 'btn btn-primary' : 'btn btn-outline-primary'\"\n (click)=\"form.get(field())?.setValue(true); update()\"\n (keyup.escape)=\"unsetEdit()\"\n >\n Oui\n </button>\n <button\n type=\"button\"\n [class]=\"v===false ? 'btn btn-primary' : 'btn btn-outline-primary'\"\n (click)=\"form.get(field())?.setValue(false); update()\"\n (keyup.escape)=\"unsetEdit()\"\n >\n Non\n </button>\n </div>\n <div class=\"form-text\">{{ realHelp() }}</div>\n }\n @case (\"textarea\") {\n <textarea\n [formControl]=\"form.get(field())\"\n (keyup.escape)=\"unsetEdit()\"\n [class]=\"inputClasses()\"\n (keyup.control.enter)=\"update()\"\n [placeholder]=\"realPlaceholder()\"\n ></textarea>\n @if (mode() === \"dd\") {\n <button\n class=\"btn btn-sm btn-link w-100 dispedit-text-update-button\"\n (click)=\"update()\"\n >\n <i class=\"bi bi-save\"></i>\n </button>\n }\n @if (realHelp()) {\n <div class=\"form-text\">\n {{ realHelp() }}\n @if (required()) {\n <span class=\"ms-1\">(requis)</span>\n }\n </div>\n }\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['minlength']\"\n >\n Trop court : {{ $any(manager()).minLength }} caract\u00E8res minimum...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['maxlength']\"\n >\n Trop long : {{ $any(manager()).maxLength }} caract\u00E8res maximum...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['pattern']\"\n >\n Format invalide...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['required']\"\n >\n Ce champ est requis...\n </div>\n }\n @case (\"fkselect\") {\n <data-fkselect\n [collection]=\"collection()\"\n [filter]=\"filter()\"\n [display]=\"display()\"\n (selected)=\"selectedRefItem($event)\"\n [placeholder]=\"placeholder()\"\n (cancelled)=\"unsetEdit()\"\n (cleared)=\"selectedRefItem(null)\"\n ></data-fkselect>\n }\n @case (\"m2mselect\") {\n <data-m2mselect\n [collection]=\"collection()\"\n [filter]=\"filter()\"\n (changed)=\"update()\"\n [formControl]=\"form.get(field())\"\n (detailsChanged)=\"onM2MValuesChanges($event)\"\n [model]=\"model()\"\n [field]=\"field()\"\n [placeholder]=\"placeholder()\"\n ></data-m2mselect>\n }\n @case (\"select\") {\n <select\n [formControl]=\"form.get(field())\"\n (keyup.escape)=\"unsetEdit()\"\n (change)=\"update()\"\n [class]=\"inputClasses()\"\n >\n @for (c of realChoices(); track c) {\n <option [ngValue]=\"c.value !== undefined ? c.value : c\">\n {{ c.desc ? c.desc : c }}\n </option>\n }\n </select>\n <div class=\"form-text\">{{ realHelp() }}</div>\n }\n }\n</ng-template>\n<!-- Disp/edit toggler-->\n<ng-template #dispeditTpl>\n @if (!edit()) {\n <ng-container *ngTemplateOutlet=\"dispTpl\"></ng-container>\n }\n @if (edit()) {\n @if (fg(); as fg) {\n <form [formGroup]=\"fg\" (submit)=\"update()\">\n <ng-container\n *ngTemplateOutlet=\"editTpl; context: { form: fg }\"\n ></ng-container>\n </form>\n }\n }\n</ng-template>\n<!-- DispEdit noform-->\n<ng-template #dispeditFormTpl>\n @if (!edit()) {\n <ng-container *ngTemplateOutlet=\"dispTpl\"></ng-container>\n }\n @if (edit()) {\n @if (form()) {\n <ng-container\n *ngTemplateOutlet=\"editTpl; context: { form: form() }\"\n ></ng-container>\n }\n }\n</ng-template>\n<!-- Dd display-->\n@if (mode() === \"dd\") {\n @if (!hideLabel()) {\n <dt [class.required]=\"required()\">\n <span class=\"editable\" (click)=\"toggleEdit()\">\n <ng-container *ngTemplateOutlet=\"titleTpl\"></ng-container\n ></span>\n @if (realDefault() !== undefined && edit()) {\n <span class=\"pointer float-end\" (click)=\"setDefault()\"\n ><i class=\"bi bi-trash ms-2\"></i\n ></span>\n }\n </dt>\n }\n <dd [class.mb-0]=\"hideLabel()\">\n <ng-container *ngTemplateOutlet=\"dispeditTpl\"></ng-container>\n </dd>\n}\n<!-- Inline display-->\n@if (mode() === \"inline\") {\n @if (!hideLabel()) {\n @if (realDefault() !== undefined && edit()) {\n <span class=\"pointer float-end\" (click)=\"setDefault()\"\n ><i class=\"bi bi-trash ms-2\"></i\n ></span>\n }\n <label [class.required]=\"required()\">\n <ng-container *ngTemplateOutlet=\"titleTpl\"></ng-container>\n </label>\n }\n <ng-container *ngTemplateOutlet=\"dispeditTpl\"></ng-container>\n}\n<!-- Form display-->\n@if (mode() === \"form\") {\n @if (!hideLabel()) {\n @if (realDefault() !== undefined && edit()) {\n <span class=\"pointer float-end\" (click)=\"setDefault()\"\n ><i class=\"bi bi-trash ms-2\"></i\n ></span>\n }\n <label [class.required]=\"required()\">\n <ng-container *ngTemplateOutlet=\"titleTpl\"></ng-container>\n </label>\n }\n <ng-container *ngTemplateOutlet=\"dispeditFormTpl\"></ng-container>\n}\n", styles: [".editable{cursor:pointer}form.inline{display:inline-block}.required{font-weight:700}.required:after{content:\" (*)\"}\n"] }]
|
|
7371
|
+
args: [{ selector: 'data-dispedit', imports: [DatePipe, NgTemplateOutlet, ReactiveFormsModule, FkselectComponent, M2mselectComponent], template: "<ng-template #titleTpl>\n <ng-content></ng-content>\n</ng-template>\n\n<!-- TEMPLATE affichage -->\n<ng-template #dispTpl>\n @switch (realDisplay()) {\n @case (\"text\") {\n <span\n class=\"editable disp-text\"\n role=\"button\"\n tabindex=\"0\"\n (click)=\"enableEditMode()\"\n (keydown.enter)=\"enableEditMode()\"\n (keydown.space)=\"$event.preventDefault(); enableEditMode()\"\n >\n {{ txtValue() }}\n </span>\n }\n @case (\"choice\") {\n <span\n class=\"editable disp-choice\"\n role=\"button\"\n tabindex=\"0\"\n (click)=\"enableEditMode()\"\n (keydown.enter)=\"enableEditMode()\"\n (keydown.space)=\"$event.preventDefault(); enableEditMode()\"\n >\n {{ txtValue() }}\n </span>\n }\n @case (\"decimal\") {\n <span\n class=\"editable disp-decimal\"\n role=\"button\"\n tabindex=\"0\"\n (click)=\"enableEditMode()\"\n (keydown.enter)=\"enableEditMode()\"\n (keydown.space)=\"$event.preventDefault(); enableEditMode()\"\n >\n {{ txtValue() }}\n </span>\n }\n @case (\"boolean\") {\n <span\n class=\"editable disp-boolean\"\n role=\"button\"\n tabindex=\"0\"\n (click)=\"enableEditMode()\"\n (keydown.enter)=\"enableEditMode()\"\n (keydown.space)=\"$event.preventDefault(); enableEditMode()\"\n >\n {{ txtValue() }}\n </span>\n }\n @case (\"fkdetails\") {\n <span\n class=\"editable disp-fkdetails\"\n role=\"button\"\n tabindex=\"0\"\n (click)=\"enableEditMode()\"\n (keydown.enter)=\"enableEditMode()\"\n (keydown.space)=\"$event.preventDefault(); enableEditMode()\"\n >\n <div class=\"fkitem\">{{ txtValue() }}</div>\n </span>\n }\n @case (\"m2mdetails\") {\n <span\n class=\"editable disp-m2mdetails\"\n role=\"button\"\n tabindex=\"0\"\n (click)=\"enableEditMode()\"\n (keydown.enter)=\"enableEditMode()\"\n (keydown.space)=\"$event.preventDefault(); enableEditMode()\"\n >\n @for (v of txtValues(); track v) {\n <div class=\"m2mitem\">{{ v }}</div>\n }\n </span>\n }\n @case (\"datetime\") {\n <span\n class=\"editable disp-datetime\"\n role=\"button\"\n tabindex=\"0\"\n (click)=\"enableEditMode()\"\n (keydown.enter)=\"enableEditMode()\"\n (keydown.space)=\"$event.preventDefault(); enableEditMode()\"\n >\n @if (dispValue()) {\n {{ txtValue() | date: \"short\" }}\n }\n @if (!dispValue()) {\n {{ txtValue() }}\n }\n </span>\n }\n @case (\"date\") {\n <span\n class=\"editable disp-datetime\"\n role=\"button\"\n tabindex=\"0\"\n (click)=\"enableEditMode()\"\n (keydown.enter)=\"enableEditMode()\"\n (keydown.space)=\"$event.preventDefault(); enableEditMode()\"\n >\n @if (dispValue()) {\n {{ txtValue() | date: \"shortDate\" }}\n }\n @if (!dispValue()) {\n {{ txtValue() }}\n }\n </span>\n }\n }\n</ng-template>\n\n<!-- TEMPLATE \u00E9dition -->\n<ng-template #editTpl let-form=\"form\">\n @switch (realEditor()) {\n @case (\"input.text\") {\n <input\n [attr.id]=\"inputId\"\n type=\"text\"\n [formControl]=\"form.get(field())\"\n [class]=\"inputClasses()\"\n (keyup.escape)=\"unsetEdit()\"\n [placeholder]=\"realPlaceholder()\"\n />\n @if (realHelp()) {\n <div class=\"form-text\">\n {{ realHelp() }}\n @if (required()) {\n <span class=\"ms-1\">(requis)</span>\n }\n </div>\n }\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['minlength']\"\n >\n Trop court : {{ $any(manager()).minLength }} caract\u00E8res minimum...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['maxlength']\"\n >\n Trop long : {{ $any(manager()).maxLength }} caract\u00E8res maximum...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['pattern']\"\n >\n Format invalide...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['required']\"\n >\n Ce champ est requis...\n </div>\n }\n @case (\"input.email\") {\n <input\n [attr.id]=\"inputId\"\n type=\"email\"\n [formControl]=\"form.get(field())\"\n [class]=\"inputClasses()\"\n (keyup.escape)=\"unsetEdit()\"\n [placeholder]=\"realPlaceholder()\"\n />\n @if (realHelp()) {\n <div class=\"form-text\">\n {{ realHelp() }}\n @if (required()) {\n <span class=\"ms-1\">(requis)</span>\n }\n </div>\n }\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['minlength']\"\n >\n Trop court : {{ $any(manager()).minLength }} caract\u00E8res minimum...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['maxlength']\"\n >\n Trop long : {{ $any(manager()).maxLength }} caract\u00E8res maximum...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['pattern']\"\n >\n Format invalide...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['email']\"\n >\n Format d'email invalide...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['required']\"\n >\n Ce champ est requis...\n </div>\n }\n @case (\"input.password\") {\n <input\n [attr.id]=\"inputId\"\n type=\"password\"\n [formControl]=\"form.get(field())\"\n [class]=\"inputClasses()\"\n (keyup.escape)=\"unsetEdit()\"\n [placeholder]=\"realPlaceholder()\"\n />\n @if (realHelp()) {\n <div class=\"form-text\">\n {{ realHelp() }}\n @if (required()) {\n <span class=\"ms-1\">(requis)</span>\n }\n </div>\n }\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['minlength']\"\n >\n Trop court : {{ $any(manager()).minLength }} caract\u00E8res minimum...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['maxlength']\"\n >\n Trop long : {{ $any(manager()).maxLength }} caract\u00E8res maximum...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['pattern']\"\n >\n Format invalide...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['required']\"\n >\n Ce champ est requis...\n </div>\n }\n @case (\"input.datetime\") {\n <input\n [attr.id]=\"inputId\"\n type=\"datetime-local\"\n [formControl]=\"form.get(field())\"\n [class]=\"inputClasses()\"\n (keyup.escape)=\"unsetEdit()\"\n (keyup.enter)=\"update()\"\n />\n <div class=\"form-text\">{{ realHelp() }}</div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['required']\"\n >\n Ce champ est requis...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['minDate']\"\n >\n Doit \u00EAtre post\u00E9rieur \u00E0 {{ $any(manager()).min | date: \"short\" }}...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['maxDate']\"\n >\n Doit \u00EAtre ant\u00E9rieur \u00E0 {{ $any(manager()).max | date: \"short\" }}...\n </div>\n }\n @case (\"input.date\") {\n <input\n [attr.id]=\"inputId\"\n type=\"date\"\n [formControl]=\"form.get(field())\"\n [class]=\"inputClasses()\"\n (keyup.escape)=\"unsetEdit()\"\n (keyup.enter)=\"update()\"\n />\n <div class=\"form-text\">{{ realHelp() }}</div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['required']\"\n >\n Ce champ est requis...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['minDate']\"\n >\n Doit \u00EAtre post\u00E9rieur \u00E0 {{ $any(manager()).min | date: \"short\" }}...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['maxDate']\"\n >\n Doit \u00EAtre ant\u00E9rieur \u00E0 {{ $any(manager()).max | date: \"short\" }}...\n </div>\n }\n @case (\"input.number\") {\n <input\n [attr.id]=\"inputId\"\n type=\"number\"\n [formControl]=\"form.get(field())\"\n [class]=\"inputClasses()\"\n (keyup.escape)=\"unsetEdit()\"\n [placeholder]=\"realPlaceholder()\"\n />\n @if (realHelp()) {\n <div class=\"form-text\">\n {{ realHelp() }}\n @if (required()) {\n <span class=\"ms-1\">(requis)</span>\n }\n </div>\n }\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['min']\"\n >\n Trop petit : minimum {{ $any(manager()).min }}...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['max']\"\n >\n Trop grand : maximum {{ $any(manager()).max }}...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['required']\"\n >\n Ce champ est requis...\n </div>\n }\n @case (\"input.decimal\") {\n <input\n [attr.id]=\"inputId\"\n type=\"number\"\n [formControl]=\"form.get(field())\"\n [class]=\"inputClasses()\"\n (keyup.escape)=\"unsetEdit()\"\n [placeholder]=\"realPlaceholder()\"\n />\n @if (realHelp()) {\n <div class=\"form-text\">\n {{ realHelp() }}\n @if (required()) {\n <span class=\"ms-1\">(requis)</span>\n }\n </div>\n }\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['min']\"\n >\n Trop petit : minimum {{ $any(manager()).min }}...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['max']\"\n >\n Trop grand : maximum {{ $any(manager()).max }}...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['required']\"\n >\n Ce champ est requis...\n </div>\n }\n @case (\"input.checkbox\") {\n @let v = $any(this.model())[this.field()];\n <div class=\"btn-group btn-group-sm\" role=\"group\">\n <button\n type=\"button\"\n [class]=\"v === true ? 'btn btn-primary' : 'btn btn-outline-primary'\"\n (click)=\"form.get(field())?.setValue(true); update()\"\n (keyup.escape)=\"unsetEdit()\"\n >\n Oui\n </button>\n <button\n type=\"button\"\n [class]=\"v === false ? 'btn btn-primary' : 'btn btn-outline-primary'\"\n (click)=\"form.get(field())?.setValue(false); update()\"\n (keyup.escape)=\"unsetEdit()\"\n >\n Non\n </button>\n </div>\n <div class=\"form-text\">{{ realHelp() }}</div>\n }\n @case (\"textarea\") {\n <textarea\n [attr.id]=\"inputId\"\n [formControl]=\"form.get(field())\"\n (keyup.escape)=\"unsetEdit()\"\n [class]=\"inputClasses()\"\n (keyup.control.enter)=\"update()\"\n [placeholder]=\"realPlaceholder()\"\n ></textarea>\n @if (mode() === \"dd\") {\n <button class=\"btn btn-sm btn-link w-100 dispedit-text-update-button\" (click)=\"update()\">\n <i class=\"bi bi-save\"></i>\n </button>\n }\n @if (realHelp()) {\n <div class=\"form-text\">\n {{ realHelp() }}\n @if (required()) {\n <span class=\"ms-1\">(requis)</span>\n }\n </div>\n }\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['minlength']\"\n >\n Trop court : {{ $any(manager()).minLength }} caract\u00E8res minimum...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['maxlength']\"\n >\n Trop long : {{ $any(manager()).maxLength }} caract\u00E8res maximum...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['pattern']\"\n >\n Format invalide...\n </div>\n <div\n class=\"invalid-feedback mt-0\"\n [class.d-block]=\"form && !form.controls[field()].pristine && form.controls[field()].errors?.['required']\"\n >\n Ce champ est requis...\n </div>\n }\n @case (\"fkselect\") {\n <data-fkselect\n [inputId]=\"inputId\"\n [collection]=\"collection()\"\n [filter]=\"filter()\"\n [display]=\"display()\"\n (selected)=\"selectedRefItem($event)\"\n [placeholder]=\"placeholder()\"\n (cancelled)=\"unsetEdit()\"\n (cleared)=\"selectedRefItem(null)\"\n ></data-fkselect>\n }\n @case (\"m2mselect\") {\n <data-m2mselect\n [inputId]=\"inputId\"\n [collection]=\"collection()\"\n [filter]=\"filter()\"\n (changed)=\"update()\"\n [formControl]=\"form.get(field())\"\n (detailsChanged)=\"onM2MValuesChanges($event)\"\n [model]=\"model()\"\n [field]=\"field()\"\n [placeholder]=\"placeholder()\"\n ></data-m2mselect>\n }\n @case (\"select\") {\n <select\n [attr.id]=\"inputId\"\n [formControl]=\"form.get(field())\"\n (keyup.escape)=\"unsetEdit()\"\n (change)=\"update()\"\n [class]=\"inputClasses()\"\n >\n @for (c of realChoices(); track c) {\n <option [ngValue]=\"c.value !== undefined ? c.value : c\">\n {{ c.desc ? c.desc : c }}\n </option>\n }\n </select>\n <div class=\"form-text\">{{ realHelp() }}</div>\n }\n }\n</ng-template>\n<!-- Disp/edit toggler-->\n<ng-template #dispeditTpl>\n @if (!edit()) {\n <ng-container *ngTemplateOutlet=\"dispTpl\"></ng-container>\n }\n @if (edit()) {\n @if (fg(); as fg) {\n <form [formGroup]=\"fg\" (submit)=\"update()\">\n <ng-container *ngTemplateOutlet=\"editTpl; context: { form: fg }\"></ng-container>\n </form>\n }\n }\n</ng-template>\n<!-- DispEdit noform-->\n<ng-template #dispeditFormTpl>\n @if (!edit()) {\n <ng-container *ngTemplateOutlet=\"dispTpl\"></ng-container>\n }\n @if (edit()) {\n @if (form()) {\n <ng-container *ngTemplateOutlet=\"editTpl; context: { form: form() }\"></ng-container>\n }\n }\n</ng-template>\n<!-- Dd display-->\n@if (mode() === \"dd\") {\n @if (!hideLabel()) {\n <dt [class.required]=\"required()\">\n <span\n class=\"editable\"\n role=\"button\"\n tabindex=\"0\"\n (click)=\"toggleEdit()\"\n (keydown.enter)=\"toggleEdit()\"\n (keydown.space)=\"$event.preventDefault(); toggleEdit()\"\n >\n <ng-container *ngTemplateOutlet=\"titleTpl\"></ng-container>\n </span>\n @if (realDefault() !== undefined && edit()) {\n <span\n class=\"pointer float-end\"\n role=\"button\"\n tabindex=\"0\"\n aria-label=\"R\u00E9tablir la valeur par d\u00E9faut\"\n (click)=\"setDefault()\"\n (keydown.enter)=\"setDefault()\"\n (keydown.space)=\"$event.preventDefault(); setDefault()\"\n >\n <i class=\"bi bi-trash ms-2\"></i>\n </span>\n }\n </dt>\n }\n <dd [class.mb-0]=\"hideLabel()\">\n <ng-container *ngTemplateOutlet=\"dispeditTpl\"></ng-container>\n </dd>\n}\n<!-- Inline display-->\n@if (mode() === \"inline\") {\n @if (!hideLabel()) {\n @if (realDefault() !== undefined && edit()) {\n <span\n class=\"pointer float-end\"\n role=\"button\"\n tabindex=\"0\"\n aria-label=\"R\u00E9tablir la valeur par d\u00E9faut\"\n (click)=\"setDefault()\"\n (keydown.enter)=\"setDefault()\"\n (keydown.space)=\"$event.preventDefault(); setDefault()\"\n >\n <i class=\"bi bi-trash ms-2\"></i>\n </span>\n }\n <label [class.required]=\"required()\" [attr.for]=\"inputId\">\n <ng-container *ngTemplateOutlet=\"titleTpl\"></ng-container>\n </label>\n }\n <ng-container *ngTemplateOutlet=\"dispeditTpl\"></ng-container>\n}\n<!-- Form display-->\n@if (mode() === \"form\") {\n @if (!hideLabel()) {\n @if (realDefault() !== undefined && edit()) {\n <span\n class=\"pointer float-end\"\n role=\"button\"\n tabindex=\"0\"\n aria-label=\"R\u00E9tablir la valeur par d\u00E9faut\"\n (click)=\"setDefault()\"\n (keydown.enter)=\"setDefault()\"\n (keydown.space)=\"$event.preventDefault(); setDefault()\"\n >\n <i class=\"bi bi-trash ms-2\"></i>\n </span>\n }\n <label [class.required]=\"required()\" [attr.for]=\"inputId\">\n <ng-container *ngTemplateOutlet=\"titleTpl\"></ng-container>\n </label>\n }\n <ng-container *ngTemplateOutlet=\"dispeditFormTpl\"></ng-container>\n}\n", styles: [".editable{cursor:pointer}form.inline{display:inline-block}.required{font-weight:700}.required:after{content:\" (*)\"}\n"] }]
|
|
7274
7372
|
}], propDecorators: { model: [{ type: i0.Input, args: [{ isSignal: true, alias: "model", required: true }] }], field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], form: [{ type: i0.Input, args: [{ isSignal: true, alias: "form", required: false }] }], edit: [{ type: i0.Input, args: [{ isSignal: true, alias: "edit", required: false }] }, { type: i0.Output, args: ["editChange"] }], editable: [{ type: i0.Input, args: [{ isSignal: true, alias: "editable", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], choices: [{ type: i0.Input, args: [{ isSignal: true, alias: "choices", required: false }] }], inputClasses: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputClasses", required: false }] }, { type: i0.Output, args: ["inputClassesChange"] }], editor: [{ type: i0.Input, args: [{ isSignal: true, alias: "editor", required: false }] }], viewer: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewer", required: false }] }, { type: i0.Output, args: ["viewerChange"] }], default: [{ type: i0.Input, args: [{ isSignal: true, alias: "default", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], help: [{ type: i0.Input, args: [{ isSignal: true, alias: "help", required: false }] }], hideLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideLabel", required: false }] }], queryset: [{ type: i0.Input, args: [{ isSignal: true, alias: "queryset", required: false }] }], collection: [{ type: i0.Input, args: [{ isSignal: true, alias: "collection", required: false }] }], display: [{ type: i0.Input, args: [{ isSignal: true, alias: "display", required: false }] }], filter: [{ type: i0.Input, args: [{ isSignal: true, alias: "filter", required: false }] }], changed: [{ type: i0.Output, args: ["changed"] }] } });
|
|
7275
7373
|
|
|
7276
7374
|
/**
|
|
@@ -7360,13 +7458,14 @@ class FlagsComponent {
|
|
|
7360
7458
|
* from the model field, and wire the dropdown so that selecting a value adds
|
|
7361
7459
|
* the flag (debounced 250ms).
|
|
7362
7460
|
*/
|
|
7363
|
-
|
|
7461
|
+
ngOnInit() {
|
|
7364
7462
|
const model = this.model();
|
|
7365
7463
|
if (!this.flags() && model._collection) {
|
|
7366
7464
|
this.flags.set(model._collection.action(null, 'GET', this.get_flags_endpoint()));
|
|
7367
7465
|
}
|
|
7368
|
-
|
|
7369
|
-
|
|
7466
|
+
const flags = model && this.field() && fieldValues(model)[this.field()];
|
|
7467
|
+
if (flags) {
|
|
7468
|
+
this.curflags.set(flags);
|
|
7370
7469
|
}
|
|
7371
7470
|
else {
|
|
7372
7471
|
console.warn('Model or field problem in flagsfield component');
|
|
@@ -7374,17 +7473,15 @@ class FlagsComponent {
|
|
|
7374
7473
|
}
|
|
7375
7474
|
this.ft = new FormControl('');
|
|
7376
7475
|
this.fs = new FormControl('');
|
|
7377
|
-
this.fs.valueChanges
|
|
7378
|
-
.pipe(takeUntilDestroyed(this.destroy$), debounceTime(250))
|
|
7379
|
-
.subscribe((value) => {
|
|
7476
|
+
this.fs.valueChanges.pipe(takeUntilDestroyed(this.destroy$), debounceTime(250)).subscribe((value) => {
|
|
7380
7477
|
if (value) {
|
|
7381
|
-
this.addFlag(value);
|
|
7478
|
+
void this.addFlag(value);
|
|
7382
7479
|
}
|
|
7383
7480
|
});
|
|
7384
7481
|
}
|
|
7385
7482
|
/** Add the flag currently typed in the free-text input. */
|
|
7386
7483
|
async addFreeFlag() {
|
|
7387
|
-
await this.addFlag(this.ft.value);
|
|
7484
|
+
await this.addFlag(this.ft.value ?? '');
|
|
7388
7485
|
}
|
|
7389
7486
|
/**
|
|
7390
7487
|
* Add a flag and persist, unless it is already present.
|
|
@@ -7403,7 +7500,7 @@ class FlagsComponent {
|
|
|
7403
7500
|
this._msg.success('Flag enregistré avec succès');
|
|
7404
7501
|
}
|
|
7405
7502
|
catch (e) {
|
|
7406
|
-
this._msg.error('Erreur lors de la sauvegarde', e);
|
|
7503
|
+
this._msg.error('Erreur lors de la sauvegarde', String(e));
|
|
7407
7504
|
}
|
|
7408
7505
|
}
|
|
7409
7506
|
else {
|
|
@@ -7416,7 +7513,7 @@ class FlagsComponent {
|
|
|
7416
7513
|
* both inputs. Reports success or failure through the message service.
|
|
7417
7514
|
*/
|
|
7418
7515
|
async update() {
|
|
7419
|
-
this.model()[this.field()] = this.curflags();
|
|
7516
|
+
fieldValues(this.model())[this.field()] = this.curflags();
|
|
7420
7517
|
try {
|
|
7421
7518
|
await firstValueFrom(this.model().update([this.field()]));
|
|
7422
7519
|
this.fs.setValue('', { emitEvent: false });
|
|
@@ -7424,7 +7521,7 @@ class FlagsComponent {
|
|
|
7424
7521
|
this._msg.success('Flag enregistré avec succès');
|
|
7425
7522
|
}
|
|
7426
7523
|
catch (error) {
|
|
7427
|
-
this._msg.error('Erreur lors de la sauvegarde', `API Return : ${error}`, error._body);
|
|
7524
|
+
this._msg.error('Erreur lors de la sauvegarde', `API Return : ${String(error)}`, error._body);
|
|
7428
7525
|
}
|
|
7429
7526
|
}
|
|
7430
7527
|
/**
|
|
@@ -7449,7 +7546,7 @@ class FlagsComponent {
|
|
|
7449
7546
|
this._msg.success('Removed');
|
|
7450
7547
|
}
|
|
7451
7548
|
catch (e) {
|
|
7452
|
-
this._msg.error('Removing flag failed', e);
|
|
7549
|
+
this._msg.error('Removing flag failed', String(e));
|
|
7453
7550
|
}
|
|
7454
7551
|
}
|
|
7455
7552
|
else {
|
|
@@ -7477,12 +7574,12 @@ class FlagsComponent {
|
|
|
7477
7574
|
this.edit.set(false);
|
|
7478
7575
|
}
|
|
7479
7576
|
}
|
|
7480
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
7481
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.
|
|
7577
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: FlagsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
7578
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: FlagsComponent, isStandalone: true, selector: "data-flags", inputs: { model: { classPropertyName: "model", publicName: "model", isSignal: true, isRequired: true, transformFunction: null }, field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: false, transformFunction: null }, get_flags_endpoint: { classPropertyName: "get_flags_endpoint", publicName: "get_flags_endpoint", isSignal: true, isRequired: false, transformFunction: null }, edit: { classPropertyName: "edit", publicName: "edit", isSignal: true, isRequired: false, transformFunction: null }, editable: { classPropertyName: "editable", publicName: "editable", isSignal: true, isRequired: false, transformFunction: null }, flags: { classPropertyName: "flags", publicName: "flags", isSignal: true, isRequired: false, transformFunction: null }, free: { classPropertyName: "free", publicName: "free", isSignal: true, isRequired: false, transformFunction: null }, create: { classPropertyName: "create", publicName: "create", isSignal: true, isRequired: false, transformFunction: null }, action: { classPropertyName: "action", publicName: "action", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { edit: "editChange", flags: "flagsChange" }, ngImport: i0, template: "<dt\n (click)=\"toggleEdit()\"\n role=\"button\"\n tabindex=\"0\"\n (keydown.enter)=\"toggleEdit()\"\n (keydown.space)=\"$event.preventDefault(); toggleEdit()\"\n>\n <ng-content></ng-content>\n</dt>\n@if (!edit()) {\n <dd\n (click)=\"toggleEdit()\"\n role=\"button\"\n tabindex=\"0\"\n (keydown.enter)=\"toggleEdit()\"\n (keydown.space)=\"$event.preventDefault(); toggleEdit()\"\n >\n @for (flag of curflags(); track flag) {\n <span class=\"badge bg-info me-1\">{{ flag }}</span>\n }\n </dd>\n}\n@if (edit()) {\n <dd>\n <div class=\"row\">\n @if (!free()) {\n <div class=\"col\">\n <select class=\"form-select form-select-sm\" [formControl]=\"fs\">\n @for (flag of flaglist(); track flag) {\n <option [value]=\"flag.flag\">\n {{ flag.flag }}\n @if (flag.count) {\n <span class=\"ms-1\">({{ flag.count }})</span>\n }\n </option>\n }\n </select>\n </div>\n @if (create()) {\n <div class=\"col\">\n <input\n class=\"form-control form-control-sm\"\n placeholder=\"Nouveau flag\"\n [formControl]=\"ft\"\n (keyup.enter)=\"addFreeFlag()\"\n />\n </div>\n }\n }\n @if (free()) {\n <div class=\"col-12\">\n <input\n class=\"form-control form-select-sm\"\n placeholder=\"Nouveau flag\"\n [formControl]=\"ft\"\n (keyup.enter)=\"addFreeFlag()\"\n (keyup.escape)=\"toggleEdit()\"\n />\n </div>\n }\n </div>\n <div class=\"row\">\n <div class=\"col-sm-12\">\n @for (flag of curflags(); track flag) {\n <span\n class=\"badge bg-info me-1\"\n (click)=\"removeFlag(flag)\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"'Retirer le flag ' + flag\"\n (keydown.enter)=\"removeFlag(flag)\"\n (keydown.space)=\"$event.preventDefault(); removeFlag(flag)\"\n >\n <i class=\"bi bi-trash me-1\"></i>\n {{ flag }}\n </span>\n }\n <i\n class=\"bi bi-x-lg text-muted ms-2\"\n role=\"button\"\n tabindex=\"0\"\n aria-label=\"Fermer l'\u00E9dition\"\n (click)=\"toggleEdit()\"\n (keydown.enter)=\"toggleEdit()\"\n (keydown.space)=\"$event.preventDefault(); toggleEdit()\"\n ></i>\n </div>\n </div>\n </dd>\n}\n", styles: [""], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$2.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$2.SelectControlValueAccessor, selector: "select:not([multiple]):not([ngNoCva])[formControlName],select:not([multiple]):not([ngNoCva])[formControl],select:not([multiple]):not([ngNoCva])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }] });
|
|
7482
7579
|
}
|
|
7483
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
7580
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: FlagsComponent, decorators: [{
|
|
7484
7581
|
type: Component,
|
|
7485
|
-
args: [{ selector: 'data-flags', imports: [ReactiveFormsModule], template: "\n
|
|
7582
|
+
args: [{ selector: 'data-flags', imports: [ReactiveFormsModule], template: "<dt\n (click)=\"toggleEdit()\"\n role=\"button\"\n tabindex=\"0\"\n (keydown.enter)=\"toggleEdit()\"\n (keydown.space)=\"$event.preventDefault(); toggleEdit()\"\n>\n <ng-content></ng-content>\n</dt>\n@if (!edit()) {\n <dd\n (click)=\"toggleEdit()\"\n role=\"button\"\n tabindex=\"0\"\n (keydown.enter)=\"toggleEdit()\"\n (keydown.space)=\"$event.preventDefault(); toggleEdit()\"\n >\n @for (flag of curflags(); track flag) {\n <span class=\"badge bg-info me-1\">{{ flag }}</span>\n }\n </dd>\n}\n@if (edit()) {\n <dd>\n <div class=\"row\">\n @if (!free()) {\n <div class=\"col\">\n <select class=\"form-select form-select-sm\" [formControl]=\"fs\">\n @for (flag of flaglist(); track flag) {\n <option [value]=\"flag.flag\">\n {{ flag.flag }}\n @if (flag.count) {\n <span class=\"ms-1\">({{ flag.count }})</span>\n }\n </option>\n }\n </select>\n </div>\n @if (create()) {\n <div class=\"col\">\n <input\n class=\"form-control form-control-sm\"\n placeholder=\"Nouveau flag\"\n [formControl]=\"ft\"\n (keyup.enter)=\"addFreeFlag()\"\n />\n </div>\n }\n }\n @if (free()) {\n <div class=\"col-12\">\n <input\n class=\"form-control form-select-sm\"\n placeholder=\"Nouveau flag\"\n [formControl]=\"ft\"\n (keyup.enter)=\"addFreeFlag()\"\n (keyup.escape)=\"toggleEdit()\"\n />\n </div>\n }\n </div>\n <div class=\"row\">\n <div class=\"col-sm-12\">\n @for (flag of curflags(); track flag) {\n <span\n class=\"badge bg-info me-1\"\n (click)=\"removeFlag(flag)\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"'Retirer le flag ' + flag\"\n (keydown.enter)=\"removeFlag(flag)\"\n (keydown.space)=\"$event.preventDefault(); removeFlag(flag)\"\n >\n <i class=\"bi bi-trash me-1\"></i>\n {{ flag }}\n </span>\n }\n <i\n class=\"bi bi-x-lg text-muted ms-2\"\n role=\"button\"\n tabindex=\"0\"\n aria-label=\"Fermer l'\u00E9dition\"\n (click)=\"toggleEdit()\"\n (keydown.enter)=\"toggleEdit()\"\n (keydown.space)=\"$event.preventDefault(); toggleEdit()\"\n ></i>\n </div>\n </div>\n </dd>\n}\n" }]
|
|
7486
7583
|
}], propDecorators: { model: [{ type: i0.Input, args: [{ isSignal: true, alias: "model", required: true }] }], field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: false }] }], get_flags_endpoint: [{ type: i0.Input, args: [{ isSignal: true, alias: "get_flags_endpoint", required: false }] }], edit: [{ type: i0.Input, args: [{ isSignal: true, alias: "edit", required: false }] }, { type: i0.Output, args: ["editChange"] }], editable: [{ type: i0.Input, args: [{ isSignal: true, alias: "editable", required: false }] }], flags: [{ type: i0.Input, args: [{ isSignal: true, alias: "flags", required: false }] }, { type: i0.Output, args: ["flagsChange"] }], free: [{ type: i0.Input, args: [{ isSignal: true, alias: "free", required: false }] }], create: [{ type: i0.Input, args: [{ isSignal: true, alias: "create", required: false }] }], action: [{ type: i0.Input, args: [{ isSignal: true, alias: "action", required: false }] }] } });
|
|
7487
7584
|
|
|
7488
7585
|
/**
|
|
@@ -7542,13 +7639,13 @@ class SafeDeleteComponent {
|
|
|
7542
7639
|
* First step: run the dry-run delete and open the confirmation panel with its
|
|
7543
7640
|
* result. Nothing is destroyed here.
|
|
7544
7641
|
*
|
|
7545
|
-
* @param
|
|
7642
|
+
* @param _model unused; the component always acts on its own `[model]` input.
|
|
7546
7643
|
*/
|
|
7547
|
-
async checkDelete(
|
|
7644
|
+
async checkDelete(_model) {
|
|
7548
7645
|
const service = this.service() || this.model()._collection;
|
|
7549
7646
|
if (service) {
|
|
7550
7647
|
try {
|
|
7551
|
-
this.result.set(await firstValueFrom(service.delete(this.model(), { params: { doit: 'no' } })));
|
|
7648
|
+
this.result.set((await firstValueFrom(service.delete(this.model(), { params: { doit: 'no' } }))));
|
|
7552
7649
|
this.ofc = this._ofc.open(this._dialogRef, {
|
|
7553
7650
|
position: 'end',
|
|
7554
7651
|
});
|
|
@@ -7587,7 +7684,7 @@ class SafeDeleteComponent {
|
|
|
7587
7684
|
const service = this.service() || this.model()._collection;
|
|
7588
7685
|
if (service) {
|
|
7589
7686
|
try {
|
|
7590
|
-
this.result.set(await firstValueFrom(service.delete(this.model(), { params: { doit: 'really' } })));
|
|
7687
|
+
this.result.set((await firstValueFrom(service.delete(this.model(), { params: { doit: 'really' } }))));
|
|
7591
7688
|
if (this.messages().success) {
|
|
7592
7689
|
this._msgs.success(this.messages().success);
|
|
7593
7690
|
}
|
|
@@ -7603,12 +7700,12 @@ class SafeDeleteComponent {
|
|
|
7603
7700
|
}
|
|
7604
7701
|
}
|
|
7605
7702
|
}
|
|
7606
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
7607
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.
|
|
7703
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: SafeDeleteComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
7704
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: SafeDeleteComponent, isStandalone: true, selector: "data-safe-delete", inputs: { model: { classPropertyName: "model", publicName: "model", isSignal: true, isRequired: true, transformFunction: null }, service: { classPropertyName: "service", publicName: "service", isSignal: true, isRequired: false, transformFunction: null }, actionFn: { classPropertyName: "actionFn", publicName: "actionFn", isSignal: true, isRequired: false, transformFunction: null }, checks: { classPropertyName: "checks", publicName: "checks", isSignal: true, isRequired: false, transformFunction: null }, messages: { classPropertyName: "messages", publicName: "messages", isSignal: true, isRequired: false, transformFunction: null }, display: { classPropertyName: "display", publicName: "display", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { deleted: "deleted" }, viewQueries: [{ propertyName: "_dialogRef", first: true, predicate: ["dialog"], descendants: true, static: true }], ngImport: i0, template: "<ng-template #dialog let-offcanvas>\n <div class=\"offcanvas-header\">\n <h2 class=\"offcanvas-title text-danger text-center\">\n <i class=\"bi bi-trash me-2\"></i>\n Supprimer r\u00E9ellement ??\n </h2>\n </div>\n @if (result(); as result) {\n <div class=\"offcanvas-body text-danger\">\n <div class=\"text-center my-4 fs-1\">\n <i class=\"bi bi-exclamation-diamond my-5\"></i>\n </div>\n <div class=\"fs-4\">\n <p>La suppression de cet \u00E9l\u00E9ment supprimera {{ result.count }} \u00E9l\u00E9ments dans la base de donn\u00E9es..</p>\n </div>\n <table class=\"table table-sm table-striped table-danger\">\n <thead>\n <tr>\n <th>Type d'\u00E9l\u00E9ment</th>\n <th>Nombre</th>\n </tr>\n </thead>\n <tbody>\n @for (rl of result.details; track rl) {\n <tr>\n <td>{{ checks()[rl[0]] ? checks()[rl[0]] : rl[0] }}</td>\n <td>{{ rl[1] }}</td>\n </tr>\n }\n </tbody>\n </table>\n <button class=\"w-100 btn btn-lg btn-danger\" (click)=\"reallyDelete()\">\n <i class=\"bi bi-trash me-2\"></i>\n Je confirme la suppression\n </button>\n <button class=\"w-100 btn btn-outline-secondary my-3\" (click)=\"offcanvas.close()\">\n <i class=\"bi bi-door-open me-2\"></i>\n Je renonce \u00E0 la suppression\n </button>\n </div>\n }\n</ng-template>\n<ng-template #contentTpl>\n <ng-content></ng-content>\n</ng-template>\n@if (display() === \"button\") {\n <button class=\"btn btn-sm btn-danger\" (click)=\"checkDelete(model())\">\n <i class=\"bi bi-trash\"></i>\n <ng-container *ngTemplateOutlet=\"contentTpl\"></ng-container>\n </button>\n}\n@if (display() === \"fbutton\") {\n <button class=\"btn btn-sm btn-outline-danger float-end\" (click)=\"checkDelete(model())\">\n <i class=\"bi bi-trash mx-2\"></i>\n </button>\n}\n@if (display() === \"icon\") {\n <i\n class=\"bi bi-trash mx-2\"\n (click)=\"checkDelete(model())\"\n role=\"button\"\n tabindex=\"0\"\n aria-label=\"Supprimer\"\n (keydown.enter)=\"checkDelete(model())\"\n (keydown.space)=\"$event.preventDefault(); checkDelete(model())\"\n ></i>\n}\n@if (display() === \"custom\") {\n <div\n (click)=\"checkDelete(model())\"\n role=\"button\"\n tabindex=\"0\"\n (keydown.enter)=\"checkDelete(model())\"\n (keydown.space)=\"$event.preventDefault(); checkDelete(model())\"\n >\n <ng-container *ngTemplateOutlet=\"contentTpl\"></ng-container>\n </div>\n}\n", styles: [""], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: NgbOffcanvasModule }] });
|
|
7608
7705
|
}
|
|
7609
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
7706
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: SafeDeleteComponent, decorators: [{
|
|
7610
7707
|
type: Component,
|
|
7611
|
-
args: [{ selector: 'data-safe-delete', imports: [NgTemplateOutlet, NgbOffcanvasModule], template: "
|
|
7708
|
+
args: [{ selector: 'data-safe-delete', imports: [NgTemplateOutlet, NgbOffcanvasModule], template: "<ng-template #dialog let-offcanvas>\n <div class=\"offcanvas-header\">\n <h2 class=\"offcanvas-title text-danger text-center\">\n <i class=\"bi bi-trash me-2\"></i>\n Supprimer r\u00E9ellement ??\n </h2>\n </div>\n @if (result(); as result) {\n <div class=\"offcanvas-body text-danger\">\n <div class=\"text-center my-4 fs-1\">\n <i class=\"bi bi-exclamation-diamond my-5\"></i>\n </div>\n <div class=\"fs-4\">\n <p>La suppression de cet \u00E9l\u00E9ment supprimera {{ result.count }} \u00E9l\u00E9ments dans la base de donn\u00E9es..</p>\n </div>\n <table class=\"table table-sm table-striped table-danger\">\n <thead>\n <tr>\n <th>Type d'\u00E9l\u00E9ment</th>\n <th>Nombre</th>\n </tr>\n </thead>\n <tbody>\n @for (rl of result.details; track rl) {\n <tr>\n <td>{{ checks()[rl[0]] ? checks()[rl[0]] : rl[0] }}</td>\n <td>{{ rl[1] }}</td>\n </tr>\n }\n </tbody>\n </table>\n <button class=\"w-100 btn btn-lg btn-danger\" (click)=\"reallyDelete()\">\n <i class=\"bi bi-trash me-2\"></i>\n Je confirme la suppression\n </button>\n <button class=\"w-100 btn btn-outline-secondary my-3\" (click)=\"offcanvas.close()\">\n <i class=\"bi bi-door-open me-2\"></i>\n Je renonce \u00E0 la suppression\n </button>\n </div>\n }\n</ng-template>\n<ng-template #contentTpl>\n <ng-content></ng-content>\n</ng-template>\n@if (display() === \"button\") {\n <button class=\"btn btn-sm btn-danger\" (click)=\"checkDelete(model())\">\n <i class=\"bi bi-trash\"></i>\n <ng-container *ngTemplateOutlet=\"contentTpl\"></ng-container>\n </button>\n}\n@if (display() === \"fbutton\") {\n <button class=\"btn btn-sm btn-outline-danger float-end\" (click)=\"checkDelete(model())\">\n <i class=\"bi bi-trash mx-2\"></i>\n </button>\n}\n@if (display() === \"icon\") {\n <i\n class=\"bi bi-trash mx-2\"\n (click)=\"checkDelete(model())\"\n role=\"button\"\n tabindex=\"0\"\n aria-label=\"Supprimer\"\n (keydown.enter)=\"checkDelete(model())\"\n (keydown.space)=\"$event.preventDefault(); checkDelete(model())\"\n ></i>\n}\n@if (display() === \"custom\") {\n <div\n (click)=\"checkDelete(model())\"\n role=\"button\"\n tabindex=\"0\"\n (keydown.enter)=\"checkDelete(model())\"\n (keydown.space)=\"$event.preventDefault(); checkDelete(model())\"\n >\n <ng-container *ngTemplateOutlet=\"contentTpl\"></ng-container>\n </div>\n}\n" }]
|
|
7612
7709
|
}], propDecorators: { model: [{ type: i0.Input, args: [{ isSignal: true, alias: "model", required: true }] }], service: [{ type: i0.Input, args: [{ isSignal: true, alias: "service", required: false }] }], actionFn: [{ type: i0.Input, args: [{ isSignal: true, alias: "actionFn", required: false }] }], checks: [{ type: i0.Input, args: [{ isSignal: true, alias: "checks", required: false }] }], messages: [{ type: i0.Input, args: [{ isSignal: true, alias: "messages", required: false }] }], deleted: [{ type: i0.Output, args: ["deleted"] }], display: [{ type: i0.Input, args: [{ isSignal: true, alias: "display", required: false }] }], _dialogRef: [{
|
|
7613
7710
|
type: ViewChild,
|
|
7614
7711
|
args: ['dialog', { static: true }]
|
|
@@ -7663,7 +7760,7 @@ class CharFieldManager extends BaseFieldManager {
|
|
|
7663
7760
|
if (typeof data === 'string') {
|
|
7664
7761
|
return data;
|
|
7665
7762
|
}
|
|
7666
|
-
return
|
|
7763
|
+
return asText(data);
|
|
7667
7764
|
}
|
|
7668
7765
|
}
|
|
7669
7766
|
/**
|
|
@@ -7697,6 +7794,7 @@ class EmailFieldManager extends CharFieldManager {
|
|
|
7697
7794
|
get validators() {
|
|
7698
7795
|
const v = super.getValidators();
|
|
7699
7796
|
if (this.validate) {
|
|
7797
|
+
// eslint-disable-next-line @typescript-eslint/unbound-method -- Validators.* are static and `this`-free
|
|
7700
7798
|
v.push(Validators.email);
|
|
7701
7799
|
}
|
|
7702
7800
|
return v;
|
|
@@ -7719,7 +7817,6 @@ class PasswordFieldManager extends CharFieldManager {
|
|
|
7719
7817
|
/** Renders a masked `input.password` editor. */
|
|
7720
7818
|
editorType = 'input.password';
|
|
7721
7819
|
}
|
|
7722
|
-
/* eslint-disable max-len */
|
|
7723
7820
|
/**
|
|
7724
7821
|
* Declares a single-line string field — the default choice for any short text
|
|
7725
7822
|
* value. Renders a text input, or a dropdown as soon as `choices` is given.
|
|
@@ -7877,7 +7974,7 @@ class DateFieldManager extends BaseFieldManager {
|
|
|
7877
7974
|
return null;
|
|
7878
7975
|
}
|
|
7879
7976
|
const date = new Date(data);
|
|
7880
|
-
if (date instanceof Date && !isNaN(date)) {
|
|
7977
|
+
if (date instanceof Date && !isNaN(date.getTime())) {
|
|
7881
7978
|
return date;
|
|
7882
7979
|
}
|
|
7883
7980
|
return null;
|
|
@@ -8030,7 +8127,7 @@ class DatetimeFieldManager extends DateFieldManager {
|
|
|
8030
8127
|
else {
|
|
8031
8128
|
date = new Date(data);
|
|
8032
8129
|
}
|
|
8033
|
-
if (date instanceof Date && !isNaN(date)) {
|
|
8130
|
+
if (date instanceof Date && !isNaN(date.getTime())) {
|
|
8034
8131
|
return date;
|
|
8035
8132
|
}
|
|
8036
8133
|
return null;
|
|
@@ -8130,14 +8227,14 @@ class DetailsFieldManager extends BaseFieldManager {
|
|
|
8130
8227
|
if (this.model) {
|
|
8131
8228
|
if (!this.many) {
|
|
8132
8229
|
const d = new this.model(coll);
|
|
8133
|
-
d.fromJson(data);
|
|
8230
|
+
d.fromJson(fieldValues(data));
|
|
8134
8231
|
return d;
|
|
8135
8232
|
}
|
|
8136
8233
|
else {
|
|
8137
8234
|
const out = [];
|
|
8138
8235
|
for (const dt of data) {
|
|
8139
8236
|
const d = new this.model(coll);
|
|
8140
|
-
d.fromJson(dt);
|
|
8237
|
+
d.fromJson(fieldValues(dt));
|
|
8141
8238
|
out.push(d);
|
|
8142
8239
|
}
|
|
8143
8240
|
return out;
|
|
@@ -8160,7 +8257,6 @@ class ManyToManyFieldManager extends BaseFieldManager {
|
|
|
8160
8257
|
/** Rendered by `m2mdetails`, which reads `<field>_details`. */
|
|
8161
8258
|
displayType = 'm2mdetails';
|
|
8162
8259
|
}
|
|
8163
|
-
/* eslint-disable max-len */
|
|
8164
8260
|
/**
|
|
8165
8261
|
* Declares the id half of a foreign key: the plain number the API stores.
|
|
8166
8262
|
*
|
|
@@ -8363,7 +8459,6 @@ class DecimalFieldManager extends IntegerFieldManager {
|
|
|
8363
8459
|
/** Renders an `input.decimal` editor, which multiplies back by `factor` on save. */
|
|
8364
8460
|
editorType = 'input.decimal';
|
|
8365
8461
|
}
|
|
8366
|
-
/* eslint-disable max-len */
|
|
8367
8462
|
/**
|
|
8368
8463
|
* Declares a whole-number field: counts, quantities, positions. Rendered as a
|
|
8369
8464
|
* number input, with optional `min`/`max` validators.
|
|
@@ -8429,10 +8524,13 @@ class ComputedFieldManager extends BaseFieldManager {
|
|
|
8429
8524
|
* Deserialises nothing: the body is empty, so the return is always
|
|
8430
8525
|
* `undefined`. A computed field takes no value from the payload.
|
|
8431
8526
|
*
|
|
8432
|
-
* @param
|
|
8433
|
-
* @param
|
|
8527
|
+
* @param _data ignored
|
|
8528
|
+
* @param _coll ignored
|
|
8434
8529
|
*/
|
|
8435
|
-
fromJson(
|
|
8530
|
+
fromJson(_data, _coll) {
|
|
8531
|
+
// A computed field is derived on the client; the payload holds nothing.
|
|
8532
|
+
return undefined;
|
|
8533
|
+
}
|
|
8436
8534
|
}
|
|
8437
8535
|
/**
|
|
8438
8536
|
* Declares a display-only field derived on the client, typically backed by a
|
|
@@ -8494,18 +8592,16 @@ class MessageZoneComponent {
|
|
|
8494
8592
|
messages = inject(DataMessageService);
|
|
8495
8593
|
destroy$ = inject(DestroyRef);
|
|
8496
8594
|
ngOnInit() {
|
|
8497
|
-
this.messages.current
|
|
8498
|
-
.pipe(takeUntilDestroyed(this.destroy$))
|
|
8499
|
-
.subscribe((messages) => {
|
|
8595
|
+
this.messages.current.pipe(takeUntilDestroyed(this.destroy$)).subscribe((messages) => {
|
|
8500
8596
|
this.current.set(messages);
|
|
8501
8597
|
});
|
|
8502
8598
|
}
|
|
8503
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
8504
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.
|
|
8599
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: MessageZoneComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
8600
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: MessageZoneComponent, isStandalone: true, selector: "data-message-zone", inputs: { filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"messagezone\">\n @for (message of current(); track message) {\n <div\n class=\"alert\"\n animate.enter=\"fade-enter\"\n animate.leave=\"fade-leave\"\n [class]=\"message.style\"\n (click)=\"message.showTrace = !message.showTrace\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-expanded]=\"message.showTrace\"\n aria-label=\"Afficher la trace\"\n (keydown.enter)=\"message.showTrace = !message.showTrace\"\n (keydown.space)=\"$event.preventDefault(); message.showTrace = !message.showTrace\"\n >\n <button class=\"btn-close\" type=\"button\" (click)=\"messages.ack(message)\" aria-label=\"Close\"></button>\n <strong>{{ message.title }}</strong>\n {{ message.message }}\n @if (message.showTrace) {\n <div class=\"pretrace\">{{ message.trace }}</div>\n }\n </div>\n }\n</div>\n", styles: [".messagezone{position:fixed;top:30px;right:40px;width:35vw;height:auto;z-index:1050}.messagezone .pretrace{white-space:pre-wrap;font-family:monospace;font-size:.7rem}.fade-enter{animation:message-fade-in .55s ease}.fade-leave{animation:message-fade-out .55s ease}@keyframes message-fade-in{0%{opacity:0}to{opacity:1}}@keyframes message-fade-out{0%{opacity:1}to{opacity:0}}\n"] });
|
|
8505
8601
|
}
|
|
8506
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
8602
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: MessageZoneComponent, decorators: [{
|
|
8507
8603
|
type: Component,
|
|
8508
|
-
args: [{ selector: 'data-message-zone', imports: [], template: "
|
|
8604
|
+
args: [{ selector: 'data-message-zone', imports: [], template: "<div class=\"messagezone\">\n @for (message of current(); track message) {\n <div\n class=\"alert\"\n animate.enter=\"fade-enter\"\n animate.leave=\"fade-leave\"\n [class]=\"message.style\"\n (click)=\"message.showTrace = !message.showTrace\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-expanded]=\"message.showTrace\"\n aria-label=\"Afficher la trace\"\n (keydown.enter)=\"message.showTrace = !message.showTrace\"\n (keydown.space)=\"$event.preventDefault(); message.showTrace = !message.showTrace\"\n >\n <button class=\"btn-close\" type=\"button\" (click)=\"messages.ack(message)\" aria-label=\"Close\"></button>\n <strong>{{ message.title }}</strong>\n {{ message.message }}\n @if (message.showTrace) {\n <div class=\"pretrace\">{{ message.trace }}</div>\n }\n </div>\n }\n</div>\n", styles: [".messagezone{position:fixed;top:30px;right:40px;width:35vw;height:auto;z-index:1050}.messagezone .pretrace{white-space:pre-wrap;font-family:monospace;font-size:.7rem}.fade-enter{animation:message-fade-in .55s ease}.fade-leave{animation:message-fade-out .55s ease}@keyframes message-fade-in{0%{opacity:0}to{opacity:1}}@keyframes message-fade-out{0%{opacity:1}to{opacity:0}}\n"] }]
|
|
8509
8605
|
}], propDecorators: { filter: [{ type: i0.Input, args: [{ isSignal: true, alias: "filter", required: false }] }] } });
|
|
8510
8606
|
|
|
8511
8607
|
/**
|
|
@@ -8567,7 +8663,6 @@ class QuerysetMock {
|
|
|
8567
8663
|
* @param _coll parent mock, used as the fallback source of rows
|
|
8568
8664
|
* @param options recorded to match `Queryset`'s shape; no option is acted on
|
|
8569
8665
|
*/
|
|
8570
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
8571
8666
|
constructor(_coll, options = {}) {
|
|
8572
8667
|
this._coll = _coll;
|
|
8573
8668
|
this.options = options;
|
|
@@ -8585,7 +8680,7 @@ class QuerysetMock {
|
|
|
8585
8680
|
get meta() {
|
|
8586
8681
|
return of({
|
|
8587
8682
|
nav: { count: 100, next: 1, page: 1, pages: 10, prev: null, size: 10 },
|
|
8588
|
-
parameters: { page:
|
|
8683
|
+
parameters: { page: 'page', page_size: 'page_size' },
|
|
8589
8684
|
});
|
|
8590
8685
|
}
|
|
8591
8686
|
/** `[results, loading, meta]` combined, mirroring `Queryset.full`. */
|
|
@@ -8593,19 +8688,19 @@ class QuerysetMock {
|
|
|
8593
8688
|
return combineLatest([this.results, this.loading, this.meta]);
|
|
8594
8689
|
}
|
|
8595
8690
|
/** No-op returning `this`; the filter is discarded. See the class-level caveat. */
|
|
8596
|
-
filter(
|
|
8691
|
+
filter(_params = {}) {
|
|
8597
8692
|
return this;
|
|
8598
8693
|
}
|
|
8599
8694
|
/** No-op returning `this`; the ordering is discarded. See the class-level caveat. */
|
|
8600
|
-
sort(...
|
|
8695
|
+
sort(..._sorting) {
|
|
8601
8696
|
return this;
|
|
8602
8697
|
}
|
|
8603
8698
|
/** No-op returning `this`; {@link pageSize} is left untouched. */
|
|
8604
|
-
paginateBy(
|
|
8699
|
+
paginateBy(_pageSize = 20) {
|
|
8605
8700
|
return this;
|
|
8606
8701
|
}
|
|
8607
8702
|
/** No-op returning `this`; {@link page} is left untouched. */
|
|
8608
|
-
setPage(
|
|
8703
|
+
setPage(_page) {
|
|
8609
8704
|
return this;
|
|
8610
8705
|
}
|
|
8611
8706
|
/** Always returns `{}`, since no query state is retained. */
|
|
@@ -8675,7 +8770,7 @@ class CollectionMock {
|
|
|
8675
8770
|
* id, so a test that fetches two different ids gets the same instance back.
|
|
8676
8771
|
* Reassign `mockValue` between calls if that matters.
|
|
8677
8772
|
*/
|
|
8678
|
-
fetch(
|
|
8773
|
+
fetch(_id, _suffix = '') {
|
|
8679
8774
|
return of(this.mockValue);
|
|
8680
8775
|
}
|
|
8681
8776
|
/**
|
|
@@ -8683,7 +8778,7 @@ class CollectionMock {
|
|
|
8683
8778
|
* the call, assert on the effects rather than on the invocation, or spy on this
|
|
8684
8779
|
* method when you need to check what was requested.
|
|
8685
8780
|
*/
|
|
8686
|
-
action(
|
|
8781
|
+
action(_model, _method, _action, _params) {
|
|
8687
8782
|
return of(this.actionValue);
|
|
8688
8783
|
}
|
|
8689
8784
|
/**
|
|
@@ -8699,7 +8794,7 @@ class CollectionMock {
|
|
|
8699
8794
|
* real `Collection.list()` unwraps. Arguments are ignored, so filters are not
|
|
8700
8795
|
* applied; set {@link mockValues} to whatever the filtered result should be.
|
|
8701
8796
|
*/
|
|
8702
|
-
list(
|
|
8797
|
+
list(_query = {}, _suffix = '') {
|
|
8703
8798
|
return of({ results: this.mockValues });
|
|
8704
8799
|
}
|
|
8705
8800
|
/**
|
|
@@ -8844,7 +8939,7 @@ class DataUploaderService {
|
|
|
8844
8939
|
initInputEvents(input) {
|
|
8845
8940
|
return input.subscribe((event) => {
|
|
8846
8941
|
switch (event.type) {
|
|
8847
|
-
case 'uploadFile':
|
|
8942
|
+
case 'uploadFile': {
|
|
8848
8943
|
const uploadFileIndex = this.queue.findIndex((file) => file === event.file);
|
|
8849
8944
|
if (uploadFileIndex !== -1 && event.file) {
|
|
8850
8945
|
this.uploadScheduler.next({
|
|
@@ -8853,11 +8948,13 @@ class DataUploaderService {
|
|
|
8853
8948
|
});
|
|
8854
8949
|
}
|
|
8855
8950
|
break;
|
|
8856
|
-
|
|
8951
|
+
}
|
|
8952
|
+
case 'uploadAll': {
|
|
8857
8953
|
const files = this.queue.filter((file) => file.progress.status === UploadStatus.Queue);
|
|
8858
8954
|
files.forEach((file) => this.uploadScheduler.next({ file: file, event: event }));
|
|
8859
8955
|
break;
|
|
8860
|
-
|
|
8956
|
+
}
|
|
8957
|
+
case 'cancel': {
|
|
8861
8958
|
const id = event.id || null;
|
|
8862
8959
|
if (!id) {
|
|
8863
8960
|
return;
|
|
@@ -8877,6 +8974,7 @@ class DataUploaderService {
|
|
|
8877
8974
|
}
|
|
8878
8975
|
});
|
|
8879
8976
|
break;
|
|
8977
|
+
}
|
|
8880
8978
|
case 'cancelAll':
|
|
8881
8979
|
this.subs.forEach((sub) => {
|
|
8882
8980
|
if (sub.sub) {
|
|
@@ -8889,7 +8987,7 @@ class DataUploaderService {
|
|
|
8889
8987
|
}
|
|
8890
8988
|
});
|
|
8891
8989
|
break;
|
|
8892
|
-
case 'remove':
|
|
8990
|
+
case 'remove': {
|
|
8893
8991
|
if (!event.id) {
|
|
8894
8992
|
return;
|
|
8895
8993
|
}
|
|
@@ -8900,6 +8998,7 @@ class DataUploaderService {
|
|
|
8900
8998
|
this.serviceEvents.emit({ type: 'removed', file: file });
|
|
8901
8999
|
}
|
|
8902
9000
|
break;
|
|
9001
|
+
}
|
|
8903
9002
|
case 'removeAll':
|
|
8904
9003
|
if (this.queue.length) {
|
|
8905
9004
|
this.queue = [];
|
|
@@ -8962,9 +9061,7 @@ class DataUploaderService {
|
|
|
8962
9061
|
const percentage = Math.round((e.loaded * 100) / e.total);
|
|
8963
9062
|
const diff = new Date().getTime() - time;
|
|
8964
9063
|
speed = Math.round((e.loaded / diff) * 1000);
|
|
8965
|
-
progressStartTime =
|
|
8966
|
-
(file.progress.data && file.progress.data.startTime) ||
|
|
8967
|
-
new Date().getTime();
|
|
9064
|
+
progressStartTime = (file.progress.data && file.progress.data.startTime) || new Date().getTime();
|
|
8968
9065
|
eta = Math.ceil((e.total - e.loaded) / speed);
|
|
8969
9066
|
file.progress = {
|
|
8970
9067
|
status: UploadStatus.Uploading,
|
|
@@ -9004,7 +9101,7 @@ class DataUploaderService {
|
|
|
9004
9101
|
try {
|
|
9005
9102
|
file.response = JSON.parse(xhr.response);
|
|
9006
9103
|
}
|
|
9007
|
-
catch
|
|
9104
|
+
catch {
|
|
9008
9105
|
file.response = xhr.response;
|
|
9009
9106
|
}
|
|
9010
9107
|
file.responseHeaders = this.parseResponseHeaders(xhr.getAllResponseHeaders());
|
|
@@ -9033,7 +9130,7 @@ class DataUploaderService {
|
|
|
9033
9130
|
this.serviceEvents.emit({ type: 'start', file: file });
|
|
9034
9131
|
xhr.send(bodyToSend);
|
|
9035
9132
|
}
|
|
9036
|
-
catch
|
|
9133
|
+
catch {
|
|
9037
9134
|
observer.complete();
|
|
9038
9135
|
}
|
|
9039
9136
|
return () => {
|
|
@@ -9078,7 +9175,7 @@ class DataUploaderService {
|
|
|
9078
9175
|
if (this.allContentTypesAllowed()) {
|
|
9079
9176
|
return true;
|
|
9080
9177
|
}
|
|
9081
|
-
return
|
|
9178
|
+
return this.contentTypes.find((type) => type === mimetype) !== undefined;
|
|
9082
9179
|
}
|
|
9083
9180
|
/** Whether a file is within {@link maxFileSize}. A falsy limit (including `0`) means no limit. */
|
|
9084
9181
|
isFileSizeAllowed(fileSize) {
|
|
@@ -9160,7 +9257,7 @@ class NgFileDropDirective {
|
|
|
9160
9257
|
this._sub = [];
|
|
9161
9258
|
const options = this.options();
|
|
9162
9259
|
const concurrency = (options && options.concurrency) || Number.POSITIVE_INFINITY;
|
|
9163
|
-
const allowedContentTypes = (options && options.allowedContentTypes) || [
|
|
9260
|
+
const allowedContentTypes = (options && options.allowedContentTypes) || ['*'];
|
|
9164
9261
|
const maxUploads = (options && options.maxUploads) || Number.POSITIVE_INFINITY;
|
|
9165
9262
|
const maxFileSize = (options && options.maxFileSize) || Number.POSITIVE_INFINITY;
|
|
9166
9263
|
this.upload = new DataUploaderService(concurrency, allowedContentTypes, maxUploads, maxFileSize);
|
|
@@ -9172,13 +9269,13 @@ class NgFileDropDirective {
|
|
|
9172
9269
|
if (uploadInput instanceof EventEmitter) {
|
|
9173
9270
|
this._sub.push(this.upload.initInputEvents(uploadInput));
|
|
9174
9271
|
}
|
|
9175
|
-
this.el.addEventListener(
|
|
9176
|
-
this.el.addEventListener(
|
|
9177
|
-
this.el.addEventListener(
|
|
9272
|
+
this.el.addEventListener('drop', this.stopEvent, false);
|
|
9273
|
+
this.el.addEventListener('dragenter', this.stopEvent, false);
|
|
9274
|
+
this.el.addEventListener('dragover', this.stopEvent, false);
|
|
9178
9275
|
}
|
|
9179
9276
|
ngOnDestroy() {
|
|
9180
9277
|
if (this._sub) {
|
|
9181
|
-
this._sub.forEach(sub => sub.unsubscribe());
|
|
9278
|
+
this._sub.forEach((sub) => sub.unsubscribe());
|
|
9182
9279
|
}
|
|
9183
9280
|
}
|
|
9184
9281
|
stopEvent = (e) => {
|
|
@@ -9189,16 +9286,18 @@ class NgFileDropDirective {
|
|
|
9189
9286
|
onDrop(e) {
|
|
9190
9287
|
e.stopPropagation();
|
|
9191
9288
|
e.preventDefault();
|
|
9192
|
-
const event = { type:
|
|
9289
|
+
const event = { type: 'drop' };
|
|
9193
9290
|
this.uploadOutput.emit(event);
|
|
9194
|
-
|
|
9291
|
+
if (e.dataTransfer) {
|
|
9292
|
+
this.upload.handleFiles(e.dataTransfer.files);
|
|
9293
|
+
}
|
|
9195
9294
|
}
|
|
9196
9295
|
/** Emits `dragOver` while a drag hovers the zone, for highlighting it. Bound to the host `dragover` event. */
|
|
9197
9296
|
onDragOver(e) {
|
|
9198
9297
|
if (!e) {
|
|
9199
9298
|
return;
|
|
9200
9299
|
}
|
|
9201
|
-
const event = { type:
|
|
9300
|
+
const event = { type: 'dragOver' };
|
|
9202
9301
|
this.uploadOutput.emit(event);
|
|
9203
9302
|
}
|
|
9204
9303
|
/** Emits `dragOut` when a drag leaves the zone, to clear the highlight. Bound to the host `dragleave` event. */
|
|
@@ -9206,20 +9305,20 @@ class NgFileDropDirective {
|
|
|
9206
9305
|
if (!e) {
|
|
9207
9306
|
return;
|
|
9208
9307
|
}
|
|
9209
|
-
const event = { type:
|
|
9308
|
+
const event = { type: 'dragOut' };
|
|
9210
9309
|
this.uploadOutput.emit(event);
|
|
9211
9310
|
}
|
|
9212
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
9213
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.
|
|
9311
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: NgFileDropDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
9312
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.3", type: NgFileDropDirective, isStandalone: true, selector: "[dataFileDrop]", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, uploadInput: { classPropertyName: "uploadInput", publicName: "uploadInput", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { uploadOutput: "uploadOutput" }, host: { listeners: { "drop": "onDrop($event)", "dragover": "onDragOver($event)", "dragleave": "onDragLeave($event)" } }, ngImport: i0 });
|
|
9214
9313
|
}
|
|
9215
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
9314
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: NgFileDropDirective, decorators: [{
|
|
9216
9315
|
type: Directive,
|
|
9217
9316
|
args: [{
|
|
9218
|
-
selector:
|
|
9317
|
+
selector: '[dataFileDrop]',
|
|
9219
9318
|
host: {
|
|
9220
|
-
|
|
9221
|
-
|
|
9222
|
-
|
|
9319
|
+
'(drop)': 'onDrop($event)',
|
|
9320
|
+
'(dragover)': 'onDragOver($event)',
|
|
9321
|
+
'(dragleave)': 'onDragLeave($event)',
|
|
9223
9322
|
},
|
|
9224
9323
|
}]
|
|
9225
9324
|
}], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], uploadInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "uploadInput", required: false }] }], uploadOutput: [{ type: i0.Output, args: ["uploadOutput"] }] } });
|
|
@@ -9253,12 +9352,12 @@ class NgFileSelectDirective {
|
|
|
9253
9352
|
this._sub = [];
|
|
9254
9353
|
const options = this.options();
|
|
9255
9354
|
const concurrency = (options && options.concurrency) || Number.POSITIVE_INFINITY;
|
|
9256
|
-
const allowedContentTypes = (options && options.allowedContentTypes) || [
|
|
9355
|
+
const allowedContentTypes = (options && options.allowedContentTypes) || ['*'];
|
|
9257
9356
|
const maxUploads = (options && options.maxUploads) || Number.POSITIVE_INFINITY;
|
|
9258
9357
|
const maxFileSize = (options && options.maxFileSize) || Number.POSITIVE_INFINITY;
|
|
9259
9358
|
this.upload = new DataUploaderService(concurrency, allowedContentTypes, maxUploads, maxFileSize);
|
|
9260
9359
|
this.el = this.elementRef.nativeElement;
|
|
9261
|
-
this.el.addEventListener(
|
|
9360
|
+
this.el.addEventListener('change', this.fileListener, false);
|
|
9262
9361
|
this._sub.push(this.upload.serviceEvents.subscribe((event) => {
|
|
9263
9362
|
this.uploadOutput.emit(event);
|
|
9264
9363
|
}));
|
|
@@ -9269,8 +9368,8 @@ class NgFileSelectDirective {
|
|
|
9269
9368
|
}
|
|
9270
9369
|
ngOnDestroy() {
|
|
9271
9370
|
if (this.el) {
|
|
9272
|
-
this.el.removeEventListener(
|
|
9273
|
-
this._sub.forEach(sub => sub.unsubscribe());
|
|
9371
|
+
this.el.removeEventListener('change', this.fileListener, false);
|
|
9372
|
+
this._sub.forEach((sub) => sub.unsubscribe());
|
|
9274
9373
|
}
|
|
9275
9374
|
}
|
|
9276
9375
|
fileListener = () => {
|
|
@@ -9278,13 +9377,13 @@ class NgFileSelectDirective {
|
|
|
9278
9377
|
this.upload.handleFiles(this.el.files);
|
|
9279
9378
|
}
|
|
9280
9379
|
};
|
|
9281
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
9282
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.
|
|
9380
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: NgFileSelectDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
9381
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.3", type: NgFileSelectDirective, isStandalone: true, selector: "[dataFileSelect]", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, uploadInput: { classPropertyName: "uploadInput", publicName: "uploadInput", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { uploadOutput: "uploadOutput" }, ngImport: i0 });
|
|
9283
9382
|
}
|
|
9284
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
9383
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: NgFileSelectDirective, decorators: [{
|
|
9285
9384
|
type: Directive,
|
|
9286
9385
|
args: [{
|
|
9287
|
-
selector:
|
|
9386
|
+
selector: '[dataFileSelect]',
|
|
9288
9387
|
}]
|
|
9289
9388
|
}], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], uploadInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "uploadInput", required: false }] }], uploadOutput: [{ type: i0.Output, args: ["uploadOutput"] }] } });
|
|
9290
9389
|
|
|
@@ -9294,11 +9393,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
|
|
|
9294
9393
|
* as a thin compatibility shim and will be removed in a future major version.
|
|
9295
9394
|
*/
|
|
9296
9395
|
class NgxUploaderModule {
|
|
9297
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
9298
|
-
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "22.1.
|
|
9299
|
-
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "22.1.
|
|
9396
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: NgxUploaderModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
9397
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "22.1.3", ngImport: i0, type: NgxUploaderModule, imports: [NgFileDropDirective, NgFileSelectDirective], exports: [NgFileDropDirective, NgFileSelectDirective] });
|
|
9398
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: NgxUploaderModule });
|
|
9300
9399
|
}
|
|
9301
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
9400
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: NgxUploaderModule, decorators: [{
|
|
9302
9401
|
type: NgModule,
|
|
9303
9402
|
args: [{
|
|
9304
9403
|
imports: [NgFileDropDirective, NgFileSelectDirective],
|
|
@@ -9441,11 +9540,6 @@ const DATA_AUTH_USER_SERVICE = new InjectionToken('data.auth.user.service');
|
|
|
9441
9540
|
* @typeParam UserData - the decoded JWT payload, at least an {@link IJwtBaseData}.
|
|
9442
9541
|
*/
|
|
9443
9542
|
class AuthServiceBase {
|
|
9444
|
-
userService;
|
|
9445
|
-
_params;
|
|
9446
|
-
_router;
|
|
9447
|
-
_http;
|
|
9448
|
-
_msgs;
|
|
9449
9543
|
/**
|
|
9450
9544
|
* Emits every time {@link logout} runs, whether triggered by the user, by a failed
|
|
9451
9545
|
* token refresh, or by a login error.
|
|
@@ -9460,12 +9554,13 @@ class AuthServiceBase {
|
|
|
9460
9554
|
_user$ = new ReplaySubject(1);
|
|
9461
9555
|
_token;
|
|
9462
9556
|
_fetched;
|
|
9463
|
-
|
|
9464
|
-
|
|
9465
|
-
|
|
9466
|
-
|
|
9467
|
-
|
|
9468
|
-
|
|
9557
|
+
/** Collection used to fetch the logged-in user, from {@link DATA_AUTH_USER_SERVICE}. */
|
|
9558
|
+
userService = inject(DATA_AUTH_USER_SERVICE);
|
|
9559
|
+
_params = inject(DATA_AUTH_PARAMS);
|
|
9560
|
+
_router = inject(Router);
|
|
9561
|
+
_http = inject(HttpClient);
|
|
9562
|
+
_msgs = inject(DataMessageService);
|
|
9563
|
+
constructor() {
|
|
9469
9564
|
this.autoLogin();
|
|
9470
9565
|
}
|
|
9471
9566
|
/** True when no access token is held, i.e. no session is active. Checked by {@link AuthInterceptor} before attaching a token. */
|
|
@@ -9498,9 +9593,7 @@ class AuthServiceBase {
|
|
|
9498
9593
|
get currentUser$() {
|
|
9499
9594
|
// Needs refresh ?
|
|
9500
9595
|
if (!this.isAnonymous &&
|
|
9501
|
-
(!this._fetched ||
|
|
9502
|
-
Date.now() - this._fetched >
|
|
9503
|
-
(this._params.userFetchValiditySeconds || 3600) * 1000)) {
|
|
9596
|
+
(!this._fetched || Date.now() - this._fetched > (this._params.userFetchValiditySeconds || 3600) * 1000)) {
|
|
9504
9597
|
this._fetched = Date.now();
|
|
9505
9598
|
return this._fetchUser().pipe(switchMap(() => {
|
|
9506
9599
|
return this._user$.asObservable();
|
|
@@ -9583,7 +9676,7 @@ class AuthServiceBase {
|
|
|
9583
9676
|
return this._fetchUser();
|
|
9584
9677
|
}), map(() => 'success'), tap(() => this.saveAuth()), catchError((error) => {
|
|
9585
9678
|
this.logout();
|
|
9586
|
-
const code = error.error?.code || error
|
|
9679
|
+
const code = error.error?.code || error.code || 'error';
|
|
9587
9680
|
console.error(code, error);
|
|
9588
9681
|
return of(code);
|
|
9589
9682
|
}));
|
|
@@ -9602,7 +9695,7 @@ class AuthServiceBase {
|
|
|
9602
9695
|
});
|
|
9603
9696
|
return this._fetchUser().pipe(map(() => 'success'), tap(() => this.saveAuth()), catchError((error) => {
|
|
9604
9697
|
this.logout();
|
|
9605
|
-
const code = error.error?.code || error
|
|
9698
|
+
const code = error.error?.code || error.code || 'error';
|
|
9606
9699
|
console.error(code, error);
|
|
9607
9700
|
return of(code);
|
|
9608
9701
|
}));
|
|
@@ -9618,9 +9711,7 @@ class AuthServiceBase {
|
|
|
9618
9711
|
if (this._params.requestReactivateUrl) {
|
|
9619
9712
|
const payload = {};
|
|
9620
9713
|
payload[this._params.loginField] = username;
|
|
9621
|
-
return this._http
|
|
9622
|
-
.post(this._params.requestReactivateUrl, payload)
|
|
9623
|
-
.pipe(map(() => true), catchError(() => of(false)));
|
|
9714
|
+
return this._http.post(this._params.requestReactivateUrl, payload).pipe(map(() => true), catchError(() => of(false)));
|
|
9624
9715
|
}
|
|
9625
9716
|
return of(false);
|
|
9626
9717
|
}
|
|
@@ -9649,9 +9740,7 @@ class AuthServiceBase {
|
|
|
9649
9740
|
const payload = {};
|
|
9650
9741
|
payload[this._params.loginField] = username;
|
|
9651
9742
|
payload[this._params.tokenField] = token;
|
|
9652
|
-
return this._http
|
|
9653
|
-
.post(this._params.processReactivateUrl, payload)
|
|
9654
|
-
.pipe(map(() => true), catchError(() => of(false)));
|
|
9743
|
+
return this._http.post(this._params.processReactivateUrl, payload).pipe(map(() => true), catchError(() => of(false)));
|
|
9655
9744
|
}
|
|
9656
9745
|
return of(false);
|
|
9657
9746
|
}
|
|
@@ -9715,7 +9804,7 @@ class AuthServiceBase {
|
|
|
9715
9804
|
console.error('Token refresh error', err, caught);
|
|
9716
9805
|
this.logout();
|
|
9717
9806
|
this._msgs.warning('Vous devez vous reconnecter');
|
|
9718
|
-
this._router.navigate(this._params.loginRoute);
|
|
9807
|
+
void this._router.navigate(this._params.loginRoute);
|
|
9719
9808
|
return of(null);
|
|
9720
9809
|
}), tap((tok) => {
|
|
9721
9810
|
console.log('Token refresh response', tok);
|
|
@@ -9759,18 +9848,12 @@ class AuthServiceBase {
|
|
|
9759
9848
|
});
|
|
9760
9849
|
}
|
|
9761
9850
|
}
|
|
9762
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
9763
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.
|
|
9851
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: AuthServiceBase, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
9852
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: AuthServiceBase });
|
|
9764
9853
|
}
|
|
9765
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
9854
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: AuthServiceBase, decorators: [{
|
|
9766
9855
|
type: Injectable
|
|
9767
|
-
}], ctorParameters: () => [
|
|
9768
|
-
type: Inject,
|
|
9769
|
-
args: [DATA_AUTH_USER_SERVICE]
|
|
9770
|
-
}] }, { type: undefined, decorators: [{
|
|
9771
|
-
type: Inject,
|
|
9772
|
-
args: [DATA_AUTH_PARAMS]
|
|
9773
|
-
}] }, { type: i1$4.Router }, { type: i1.HttpClient }, { type: DataMessageService }] });
|
|
9856
|
+
}], ctorParameters: () => [] });
|
|
9774
9857
|
|
|
9775
9858
|
/**
|
|
9776
9859
|
* Identity helper that type-checks a route `data` literal against {@link BaseRouteParams}
|
|
@@ -9827,9 +9910,10 @@ class Link {
|
|
|
9827
9910
|
* missing from `ctx` are reset to `null`, not left over from the previous context.
|
|
9828
9911
|
*/
|
|
9829
9912
|
context(ctx) {
|
|
9913
|
+
const values = fieldValues(ctx ?? {});
|
|
9830
9914
|
for (const n of this._params) {
|
|
9831
|
-
if (
|
|
9832
|
-
this._cargs[n] =
|
|
9915
|
+
if (values[n]) {
|
|
9916
|
+
this._cargs[n] = values[n];
|
|
9833
9917
|
}
|
|
9834
9918
|
else {
|
|
9835
9919
|
this._cargs[n] = null;
|
|
@@ -9951,7 +10035,7 @@ class BreadcrumbComponent {
|
|
|
9951
10035
|
// Get icon
|
|
9952
10036
|
for (const u of p.url) {
|
|
9953
10037
|
url.push(u.path);
|
|
9954
|
-
|
|
10038
|
+
const rtd = {
|
|
9955
10039
|
icon: this.getIcon(rdata, data),
|
|
9956
10040
|
title: this.getTitle(rdata, data, u),
|
|
9957
10041
|
path: url.join('/'),
|
|
@@ -9967,7 +10051,7 @@ class BreadcrumbComponent {
|
|
|
9967
10051
|
}
|
|
9968
10052
|
else {
|
|
9969
10053
|
url.push(p.url.join('/'));
|
|
9970
|
-
|
|
10054
|
+
const rtd = {
|
|
9971
10055
|
icon: this.getIcon(rdata, data),
|
|
9972
10056
|
title: this.getTitle(rdata, data),
|
|
9973
10057
|
path: url.join('/'),
|
|
@@ -10030,12 +10114,12 @@ class BreadcrumbComponent {
|
|
|
10030
10114
|
}
|
|
10031
10115
|
return '';
|
|
10032
10116
|
}
|
|
10033
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
10034
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.
|
|
10117
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: BreadcrumbComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
10118
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: BreadcrumbComponent, isStandalone: true, selector: "data-breadcrumb", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, icons: { classPropertyName: "icons", publicName: "icons", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<nav aria-label=\"breadcrumb\">\n <ol class=\"breadcrumb\">\n @for (p of tree(); track p) {\n @if (!p.current) {\n <li class=\"breadcrumb-item\">\n <a class=\"breadcrumb-item\" [routerLink]=\"p.path\">\n @if (icons() && p.icon) {\n <i class=\"me-2\" [class]=\"p.icon\"></i>\n {{ p.title }}\n }\n @if (!(icons() && p.icon)) {\n {{ p.title }}\n }\n </a>\n </li>\n }\n @if (p.current) {\n <li class=\"breadcrumb-item active\" aria-current=\"page\">\n @if (icons() && p.icon) {\n <i class=\"me-1\" [class]=\"p.icon\"></i>\n {{ p.title }}\n }\n @if (!(icons() && p.icon)) {\n {{ p.title }}\n }\n </li>\n }\n }\n </ol>\n</nav>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1$3.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "browserUrl", "routerLink"] }] });
|
|
10035
10119
|
}
|
|
10036
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
10120
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: BreadcrumbComponent, decorators: [{
|
|
10037
10121
|
type: Component,
|
|
10038
|
-
args: [{ selector: 'data-breadcrumb', imports: [RouterModule], template: "
|
|
10122
|
+
args: [{ selector: 'data-breadcrumb', imports: [RouterModule], template: "<nav aria-label=\"breadcrumb\">\n <ol class=\"breadcrumb\">\n @for (p of tree(); track p) {\n @if (!p.current) {\n <li class=\"breadcrumb-item\">\n <a class=\"breadcrumb-item\" [routerLink]=\"p.path\">\n @if (icons() && p.icon) {\n <i class=\"me-2\" [class]=\"p.icon\"></i>\n {{ p.title }}\n }\n @if (!(icons() && p.icon)) {\n {{ p.title }}\n }\n </a>\n </li>\n }\n @if (p.current) {\n <li class=\"breadcrumb-item active\" aria-current=\"page\">\n @if (icons() && p.icon) {\n <i class=\"me-1\" [class]=\"p.icon\"></i>\n {{ p.title }}\n }\n @if (!(icons() && p.icon)) {\n {{ p.title }}\n }\n </li>\n }\n }\n </ol>\n</nav>\n" }]
|
|
10039
10123
|
}], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], icons: [{ type: i0.Input, args: [{ isSignal: true, alias: "icons", required: false }] }] } });
|
|
10040
10124
|
|
|
10041
10125
|
/**
|
|
@@ -10102,7 +10186,7 @@ class TabMemoryService {
|
|
|
10102
10186
|
static targetToString(target) {
|
|
10103
10187
|
let out = '';
|
|
10104
10188
|
for (const t of target) {
|
|
10105
|
-
out += `/${t}`;
|
|
10189
|
+
out += `/${String(t)}`;
|
|
10106
10190
|
}
|
|
10107
10191
|
return out;
|
|
10108
10192
|
}
|
|
@@ -10143,16 +10227,17 @@ class TabMemoryService {
|
|
|
10143
10227
|
const tm = localStorage.getItem('tabmem');
|
|
10144
10228
|
if (tm) {
|
|
10145
10229
|
const tmd = JSON.parse(tm);
|
|
10146
|
-
|
|
10147
|
-
|
|
10230
|
+
const entry = tmd[name];
|
|
10231
|
+
if (entry?.value) {
|
|
10232
|
+
return entry.value;
|
|
10148
10233
|
}
|
|
10149
10234
|
}
|
|
10150
10235
|
return null;
|
|
10151
10236
|
}
|
|
10152
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
10153
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.
|
|
10237
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: TabMemoryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
10238
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: TabMemoryService, providedIn: 'root' });
|
|
10154
10239
|
}
|
|
10155
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
10240
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: TabMemoryService, decorators: [{
|
|
10156
10241
|
type: Injectable,
|
|
10157
10242
|
args: [{
|
|
10158
10243
|
providedIn: 'root',
|
|
@@ -10186,6 +10271,43 @@ const slugify = (str) => {
|
|
|
10186
10271
|
return str;
|
|
10187
10272
|
};
|
|
10188
10273
|
|
|
10274
|
+
/**
|
|
10275
|
+
* Teach jsdom the layout APIs CodeMirror and ProseMirror expect.
|
|
10276
|
+
*
|
|
10277
|
+
* Both editors measure the document to place the caret and decide what to
|
|
10278
|
+
* render, and jsdom has no layout engine: `getClientRects()` returns an empty
|
|
10279
|
+
* list and `elementFromPoint` does not exist at all. Zeroed rectangles are
|
|
10280
|
+
* enough — nothing in a spec depends on real geometry, it just has to not throw.
|
|
10281
|
+
*
|
|
10282
|
+
* Call it from `beforeEach` in any spec that instantiates an editor view. It is
|
|
10283
|
+
* idempotent, and only patches what is missing.
|
|
10284
|
+
*/
|
|
10285
|
+
function installEditorDomShims() {
|
|
10286
|
+
const rect = () => new DOMRect(0, 0, 0, 0);
|
|
10287
|
+
const rectList = () => {
|
|
10288
|
+
const list = [rect()];
|
|
10289
|
+
list.item = (index) => (index === 0 ? rect() : null);
|
|
10290
|
+
return list;
|
|
10291
|
+
};
|
|
10292
|
+
if (!Range.prototype.getClientRects) {
|
|
10293
|
+
Range.prototype.getClientRects = rectList;
|
|
10294
|
+
}
|
|
10295
|
+
if (!Range.prototype.getBoundingClientRect) {
|
|
10296
|
+
Range.prototype.getBoundingClientRect = rect;
|
|
10297
|
+
}
|
|
10298
|
+
if (!Element.prototype.getClientRects) {
|
|
10299
|
+
Element.prototype.getClientRects = rectList;
|
|
10300
|
+
}
|
|
10301
|
+
if (!document.elementFromPoint) {
|
|
10302
|
+
document.elementFromPoint = () => null;
|
|
10303
|
+
}
|
|
10304
|
+
if (!document.createRange().getClientRects) {
|
|
10305
|
+
// jsdom builds ranges from the prototype patched above; this is only a
|
|
10306
|
+
// guard for the case where an environment overrides createRange.
|
|
10307
|
+
Range.prototype.getClientRects = rectList;
|
|
10308
|
+
}
|
|
10309
|
+
}
|
|
10310
|
+
|
|
10189
10311
|
// By default, Underscore uses ERB-style template delimiters, change the
|
|
10190
10312
|
// following template settings to use alternative delimiters.
|
|
10191
10313
|
const settings = {
|
|
@@ -10200,7 +10322,7 @@ const settings = {
|
|
|
10200
10322
|
const noMatch = /.^/;
|
|
10201
10323
|
// Certain characters need to be escaped so that they can be put into a
|
|
10202
10324
|
// string literal.
|
|
10203
|
-
|
|
10325
|
+
const escapes = {
|
|
10204
10326
|
'\\': '\\',
|
|
10205
10327
|
"'": "'",
|
|
10206
10328
|
r: '\r',
|
|
@@ -10209,27 +10331,11 @@ let escapes = {
|
|
|
10209
10331
|
u2028: '\u2028',
|
|
10210
10332
|
u2029: '\u2029',
|
|
10211
10333
|
};
|
|
10212
|
-
for (
|
|
10334
|
+
for (const p in escapes) {
|
|
10213
10335
|
escapes[escapes[p]] = p;
|
|
10214
10336
|
}
|
|
10215
10337
|
const escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
|
|
10216
|
-
|
|
10217
|
-
/**
|
|
10218
|
-
* Compiles (and optionally renders) an Underscore-style string template, using ERB
|
|
10219
|
-
* delimiters: `<%= expr %>` interpolates, `<% code %>` evaluates, and a `print()` helper
|
|
10220
|
-
* is available inside evaluated code.
|
|
10221
|
-
*
|
|
10222
|
-
* Called with `data`, it renders immediately and returns the resulting string; without
|
|
10223
|
-
* `data`, it returns a reusable render function carrying a `source` property with the
|
|
10224
|
-
* generated code. `objectName` renames the variable the data is exposed under — but note
|
|
10225
|
-
* it mutates module-level settings, so it persists for subsequent calls too.
|
|
10226
|
-
*
|
|
10227
|
-
* Within this library it backs route title templates (see {@link TplFn}). Two caveats:
|
|
10228
|
-
* compilation goes through `new Function`, so it will not run under a Content Security
|
|
10229
|
-
* Policy without `unsafe-eval`; and the escaping delimiter `<%- expr %>` is not usable,
|
|
10230
|
-
* as the code it emits calls `_.escape` while no `_` is in scope.
|
|
10231
|
-
*/
|
|
10232
|
-
const tmpl = (text, data, objectName) => {
|
|
10338
|
+
function tmpl(text, data, objectName) {
|
|
10233
10339
|
if (objectName) {
|
|
10234
10340
|
settings.variable = objectName;
|
|
10235
10341
|
}
|
|
@@ -10256,22 +10362,21 @@ const tmpl = (text, data, objectName) => {
|
|
|
10256
10362
|
source = 'with(obj||{}){\n' + source + '}\n';
|
|
10257
10363
|
}
|
|
10258
10364
|
source =
|
|
10259
|
-
"var __p='';var print=function(){__p+=Array.prototype.join.call(arguments, '')};\n" +
|
|
10260
|
-
|
|
10261
|
-
|
|
10262
|
-
|
|
10365
|
+
"var __p='';var print=function(){__p+=Array.prototype.join.call(arguments, '')};\n" + source + 'return __p;\n';
|
|
10366
|
+
// The whole point of this module: `source` is the template compiled to JS.
|
|
10367
|
+
// eslint-disable-next-line @typescript-eslint/no-implied-eval
|
|
10368
|
+
const render = new Function(settings.variable || 'obj', source);
|
|
10263
10369
|
if (data) {
|
|
10264
10370
|
return render(data);
|
|
10265
10371
|
}
|
|
10266
|
-
const template = (data) => {
|
|
10267
|
-
return render
|
|
10268
|
-
};
|
|
10372
|
+
const template = ((data) => {
|
|
10373
|
+
return render(data);
|
|
10374
|
+
});
|
|
10269
10375
|
// Provide the compiled function source as a convenience for build time
|
|
10270
10376
|
// precompilation.
|
|
10271
|
-
template.source =
|
|
10272
|
-
'function(' + (settings.variable || 'obj') + '){\n' + source + '}';
|
|
10377
|
+
template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}';
|
|
10273
10378
|
return template;
|
|
10274
|
-
}
|
|
10379
|
+
}
|
|
10275
10380
|
|
|
10276
10381
|
/**
|
|
10277
10382
|
* Watches the service worker for a newly deployed version and exposes it as a simple
|
|
@@ -10284,12 +10389,10 @@ const tmpl = (text, data, objectName) => {
|
|
|
10284
10389
|
* Harmless without a service worker: the checks fail and are logged as warnings.
|
|
10285
10390
|
*/
|
|
10286
10391
|
class UpdateService {
|
|
10287
|
-
appRef;
|
|
10288
|
-
swUpdate;
|
|
10289
10392
|
stable = false;
|
|
10290
|
-
|
|
10291
|
-
|
|
10292
|
-
|
|
10393
|
+
appRef = inject(ApplicationRef);
|
|
10394
|
+
swUpdate = inject(SwUpdate);
|
|
10395
|
+
constructor() {
|
|
10293
10396
|
this._available$ = new ReplaySubject(1);
|
|
10294
10397
|
this._available$.next(false);
|
|
10295
10398
|
const appIsStable$ = this.appRef.isStable
|
|
@@ -10297,27 +10400,35 @@ class UpdateService {
|
|
|
10297
10400
|
.pipe(tap(() => console.log('App is stable')));
|
|
10298
10401
|
const checkInterval$ = timer(10 * 1000, 5 * 60 * 1000);
|
|
10299
10402
|
const checkWhenStable$ = merge(appIsStable$, checkInterval$);
|
|
10300
|
-
const updatesAvailable = swUpdate.versionUpdates.pipe(tap((evt) => console.log('Version updates event', evt)), filter((evt) => evt.type === 'VERSION_READY'), map((evt) => ({
|
|
10403
|
+
const updatesAvailable = this.swUpdate.versionUpdates.pipe(tap((evt) => console.log('Version updates event', evt)), filter((evt) => evt.type === 'VERSION_READY'), map((evt) => ({
|
|
10301
10404
|
type: 'UPDATE_AVAILABLE',
|
|
10302
10405
|
current: evt.currentVersion,
|
|
10303
10406
|
available: evt.latestVersion,
|
|
10304
10407
|
})));
|
|
10305
|
-
updatesAvailable.pipe(takeUntilDestroyed()).subscribe(
|
|
10408
|
+
updatesAvailable.pipe(takeUntilDestroyed()).subscribe(() => {
|
|
10306
10409
|
this._available$.next(true);
|
|
10307
10410
|
});
|
|
10308
|
-
checkWhenStable$.pipe(takeUntilDestroyed()).subscribe(
|
|
10411
|
+
checkWhenStable$.pipe(takeUntilDestroyed()).subscribe(() => {
|
|
10309
10412
|
this.stable = true;
|
|
10310
|
-
|
|
10311
|
-
console.log('Checking for update');
|
|
10312
|
-
const res = await swUpdate.checkForUpdate();
|
|
10313
|
-
console.log('Check for update result', res);
|
|
10314
|
-
}
|
|
10315
|
-
catch (e) {
|
|
10316
|
-
console.warn('No service worker');
|
|
10317
|
-
}
|
|
10413
|
+
void this._checkForUpdate();
|
|
10318
10414
|
});
|
|
10319
10415
|
}
|
|
10320
10416
|
_available$;
|
|
10417
|
+
/**
|
|
10418
|
+
* Asks the service worker whether a new version is available. Swallows the
|
|
10419
|
+
* failure raised when no service worker is registered, which is the normal
|
|
10420
|
+
* case in development.
|
|
10421
|
+
*/
|
|
10422
|
+
async _checkForUpdate() {
|
|
10423
|
+
try {
|
|
10424
|
+
console.log('Checking for update');
|
|
10425
|
+
const res = await this.swUpdate.checkForUpdate();
|
|
10426
|
+
console.log('Check for update result', res);
|
|
10427
|
+
}
|
|
10428
|
+
catch {
|
|
10429
|
+
console.warn('No service worker');
|
|
10430
|
+
}
|
|
10431
|
+
}
|
|
10321
10432
|
/**
|
|
10322
10433
|
* Whether a new version is ready to be activated. Starts at `false`, becomes `true` on
|
|
10323
10434
|
* `VERSION_READY`, and returns to `false` once the user activates or dismisses it.
|
|
@@ -10341,15 +10452,15 @@ class UpdateService {
|
|
|
10341
10452
|
dismiss() {
|
|
10342
10453
|
this._available$.next(false);
|
|
10343
10454
|
}
|
|
10344
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
10345
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.
|
|
10455
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: UpdateService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
10456
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: UpdateService, providedIn: 'root' });
|
|
10346
10457
|
}
|
|
10347
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
10458
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: UpdateService, decorators: [{
|
|
10348
10459
|
type: Injectable,
|
|
10349
10460
|
args: [{
|
|
10350
10461
|
providedIn: 'root',
|
|
10351
10462
|
}]
|
|
10352
|
-
}], ctorParameters: () => [
|
|
10463
|
+
}], ctorParameters: () => [] });
|
|
10353
10464
|
|
|
10354
10465
|
/**
|
|
10355
10466
|
* Snackbar prompting the user to reload when {@link UpdateService} reports a new
|
|
@@ -10362,12 +10473,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
|
|
|
10362
10473
|
class UpdateComponent {
|
|
10363
10474
|
/** The update service backing the prompt; also bound directly by the template. */
|
|
10364
10475
|
update = inject(UpdateService);
|
|
10365
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
10366
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.
|
|
10476
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: UpdateComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
10477
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: UpdateComponent, isStandalone: true, selector: "data-update", ngImport: i0, template: "@if (update.available$ | async) {\n <div class=\"snack\">\n <p>Une nouvelle version de l'application est disponible.</p>\n <div class=\"row\">\n <div class=\"col-sm-6\">\n <button class=\"btn btn-primary btn-block w-100\" (click)=\"update.activate()\">L'ACTIVER MAINTENANT</button>\n </div>\n <div class=\"col-sm-6\">\n <button class=\"btn btn-warning btn-block w-100\" (click)=\"update.dismiss()\">Plus tard</button>\n </div>\n </div>\n </div>\n}\n", styles: [".snack{position:fixed;bottom:0;margin-left:auto;margin-right:auto;left:auto;right:auto;background-color:#ff7a00cc;padding:20px;z-index:2000;border-top:1px solid rgb(255,122,0);font-size:1.5rem;font-weight:700;color:#8b0000;width:100%;text-align:center}\n"], dependencies: [{ kind: "pipe", type: AsyncPipe, name: "async" }] });
|
|
10367
10478
|
}
|
|
10368
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
10479
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: UpdateComponent, decorators: [{
|
|
10369
10480
|
type: Component,
|
|
10370
|
-
args: [{ selector: 'data-update', imports: [AsyncPipe], template: "
|
|
10481
|
+
args: [{ selector: 'data-update', imports: [AsyncPipe], template: "@if (update.available$ | async) {\n <div class=\"snack\">\n <p>Une nouvelle version de l'application est disponible.</p>\n <div class=\"row\">\n <div class=\"col-sm-6\">\n <button class=\"btn btn-primary btn-block w-100\" (click)=\"update.activate()\">L'ACTIVER MAINTENANT</button>\n </div>\n <div class=\"col-sm-6\">\n <button class=\"btn btn-warning btn-block w-100\" (click)=\"update.dismiss()\">Plus tard</button>\n </div>\n </div>\n </div>\n}\n", styles: [".snack{position:fixed;bottom:0;margin-left:auto;margin-right:auto;left:auto;right:auto;background-color:#ff7a00cc;padding:20px;z-index:2000;border-top:1px solid rgb(255,122,0);font-size:1.5rem;font-weight:700;color:#8b0000;width:100%;text-align:center}\n"] }]
|
|
10371
10482
|
}] });
|
|
10372
10483
|
|
|
10373
10484
|
/*
|
|
@@ -10379,5 +10490,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
|
|
|
10379
10490
|
* Generated bundle index. Do not edit.
|
|
10380
10491
|
*/
|
|
10381
10492
|
|
|
10382
|
-
export { AuthInterceptor, AuthServiceBase, BanAdapter, BaseFieldManager, BootstrapDataDisplayConfig, BreadcrumbComponent, ChoicePipe, Collection, CollectionMock, DATA_API_URL, DATA_AUTH_PARAMS, DATA_AUTH_SERVICE, DATA_AUTH_URLS, DATA_AUTH_USER_SERVICE, DATA_DISPLAY_CONFIG, DATA_MAX_TRANSFERSTATE_TIME, DATA_MESSAGE_SOUNDS, DEFAULT_TIMEOUTS, DataBackend, DataMessageService, DataModel, DataUploaderService, DispeditComponent, FactorPipe, FactorcPipe, FkselectComponent, FlagsComponent, Jwt, Link, M2mselectComponent, Message, MessageZoneComponent, ModelList, ModelListAutocompleteFilter, ModelListAutocompleteMultiFilter, ModelListDateFilter, ModelListDatetimeFilter, ModelListDatetimerangeFilter, ModelListFieldHeaderComponent, ModelListFieldsSelectorComponent, ModelListFilter, ModelListFilterGroup, ModelListFilters, ModelListFiltersComponent, ModelListFiltersSelectComponent, ModelListFlagsFilter, ModelListGeodistanceFilter, ModelListNumberFilter, ModelListNumberOperations, ModelListPaginatorComponent, ModelListSelectFilter, ModelListSelectMultiFilter, ModelListService, ModelListSorterComponent, ModelListTextFilter, ModelListTreeFilter, NavDriver, NgFileDropDirective, NgFileSelectDirective, NgxUploaderModule, PChoicePipe, PFactorPipe, PFactorcPipe, Queryset, RData, STATUS, SafeDeleteComponent, TabMemoryService, UpdateComponent, UpdateService, UploadStatus, booleanField, charField, computedField, dateField, datetimeField, decimalField, detailsField, emailField, floatField, foreignKeyField, humanizeBytes, integerField, isValue, manyToManyField, passwordField, primaryField, reverseForeignKeyField, slugify, strToNumber, textField, tmpl };
|
|
10493
|
+
export { AuthInterceptor, AuthServiceBase, BanAdapter, BaseFieldManager, BootstrapDataDisplayConfig, BreadcrumbComponent, ChoicePipe, Collection, CollectionMock, DATA_API_URL, DATA_AUTH_PARAMS, DATA_AUTH_SERVICE, DATA_AUTH_URLS, DATA_AUTH_USER_SERVICE, DATA_DISPLAY_CONFIG, DATA_MAX_TRANSFERSTATE_TIME, DATA_MESSAGE_SOUNDS, DEFAULT_TIMEOUTS, DataBackend, DataMessageService, DataModel, DataUploaderService, DispeditComponent, FactorPipe, FactorcPipe, FkselectComponent, FlagsComponent, Jwt, Link, M2mselectComponent, Message, MessageZoneComponent, ModelList, ModelListAutocompleteFilter, ModelListAutocompleteMultiFilter, ModelListDateFilter, ModelListDatetimeFilter, ModelListDatetimerangeFilter, ModelListFieldHeaderComponent, ModelListFieldsSelectorComponent, ModelListFilter, ModelListFilterGroup, ModelListFilters, ModelListFiltersComponent, ModelListFiltersSelectComponent, ModelListFlagsFilter, ModelListGeodistanceFilter, ModelListNumberFilter, ModelListNumberOperations, ModelListPaginatorComponent, ModelListSelectFilter, ModelListSelectMultiFilter, ModelListService, ModelListSorterComponent, ModelListTextFilter, ModelListTreeFilter, NavDriver, NgFileDropDirective, NgFileSelectDirective, NgxUploaderModule, PChoicePipe, PFactorPipe, PFactorcPipe, Queryset, RData, STATUS, SafeDeleteComponent, TabMemoryService, UpdateComponent, UpdateService, UploadStatus, asText, booleanField, charField, computedField, dateField, datetimeField, decimalField, detailsField, emailField, fieldValues, floatField, foreignKeyField, humanizeBytes, installEditorDomShims, integerField, isValue, manyToManyField, passwordField, primaryField, reverseForeignKeyField, slugify, strToNumber, textField, tmpl, uniqueId };
|
|
10383
10494
|
//# sourceMappingURL=solidev-data.mjs.map
|