@ecodev/natural 44.0.6 → 45.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  import '@angular/localize/init';
2
2
  import * as i0 from '@angular/core';
3
3
  import { Directive, Component, Inject, Injectable, HostBinding, HostListener, InjectionToken, Input, NgModule, EventEmitter, ChangeDetectionStrategy, Output, ContentChildren, Pipe, TemplateRef, ViewEncapsulation, ViewChild, Injector, Optional, Self, ContentChild, createEnvironmentInjector, createComponent, PLATFORM_ID, ErrorHandler } from '@angular/core';
4
- import { Subject, BehaviorSubject, of, timer, EMPTY, Observable, first as first$1, combineLatest, ReplaySubject, forkJoin, merge as merge$1, asyncScheduler, catchError } from 'rxjs';
4
+ import { Subject, BehaviorSubject, of, timer, switchMap as switchMap$1, endWith, last, EMPTY, Observable, first as first$1, combineLatest, ReplaySubject, debounceTime as debounceTime$1, raceWith, take as take$1, mergeMap, shareReplay as shareReplay$1, catchError, forkJoin, map as map$1, merge as merge$1, tap as tap$1, asyncScheduler } from 'rxjs';
5
5
  import * as i3 from '@angular/forms';
6
6
  import { FormGroup, FormArray, Validators, UntypedFormGroup, UntypedFormArray, UntypedFormControl, FormsModule, FormControl, FormControlDirective, FormControlName, ReactiveFormsModule } from '@angular/forms';
7
7
  import * as i2$1 from '@angular/router';
@@ -13,7 +13,7 @@ import * as i4 from '@angular/material/button';
13
13
  import { MatButtonModule } from '@angular/material/button';
14
14
  import * as i2 from '@angular/material/snack-bar';
15
15
  import { MatSnackBarModule } from '@angular/material/snack-bar';
16
- import { switchMap, map, first, filter, finalize, takeUntil, take, tap, takeWhile, debounceTime, shareReplay, mergeMap, startWith, distinctUntilChanged, throttleTime } from 'rxjs/operators';
16
+ import { switchMap, map, first, filter, finalize, takeUntil, take, tap, takeWhile, debounceTime, shareReplay, startWith, distinctUntilChanged, throttleTime } from 'rxjs/operators';
17
17
  import * as i7$2 from '@angular/material/table';
18
18
  import { MatTableDataSource, MatTableModule } from '@angular/material/table';
19
19
  import { DataSource, SelectionModel } from '@angular/cdk/collections';
@@ -2346,51 +2346,50 @@ class NaturalAbstractDetail extends NaturalAbstractPanel {
2346
2346
  this.form.disable();
2347
2347
  this.service
2348
2348
  .create(this.data.model)
2349
- .pipe(finalize(() => this.form.enable()))
2350
- .subscribe(model => {
2349
+ .pipe(switchMap$1(model => {
2351
2350
  this.alertService.info($localize `Créé`);
2352
2351
  this.form.patchValue(model);
2353
- this.postCreate(model).subscribe({
2354
- complete: () => {
2355
- if (redirect) {
2356
- if (this.isPanel) {
2357
- const oldUrl = this.router.url;
2358
- const nextUrl = this.panelData?.config.params.nextRoute;
2359
- const newUrl = oldUrl.replace('/new', '/' + model.id) + (nextUrl ? '/' + nextUrl : '');
2360
- this.router.navigateByUrl(newUrl); // replace /new by /123
2361
- }
2362
- else {
2363
- this.router.navigate(['..', model.id], { relativeTo: this.route });
2364
- }
2365
- }
2366
- },
2367
- });
2368
- });
2352
+ return this.postCreate(model).pipe(endWith(model), last());
2353
+ }), switchMap$1(model => {
2354
+ if (redirect) {
2355
+ if (this.isPanel) {
2356
+ const oldUrl = this.router.url;
2357
+ const nextUrl = this.panelData?.config.params.nextRoute;
2358
+ const newUrl = oldUrl.replace('/new', '/' + model.id) + (nextUrl ? '/' + nextUrl : '');
2359
+ return this.router.navigateByUrl(newUrl); // replace /new by /123
2360
+ }
2361
+ else {
2362
+ return this.router.navigate(['..', model.id], { relativeTo: this.route });
2363
+ }
2364
+ }
2365
+ return EMPTY;
2366
+ }), finalize(() => this.form.enable()))
2367
+ .subscribe();
2369
2368
  }
2370
2369
  delete(redirectionRoute) {
2370
+ this.form.disable();
2371
2371
  this.alertService
2372
2372
  .confirm($localize `Suppression`, $localize `Voulez-vous supprimer définitivement cet élément ?`, $localize `Supprimer définitivement`)
2373
- .subscribe(confirmed => {
2374
- if (confirmed) {
2375
- this.preDelete(this.data.model);
2376
- this.form.disable();
2377
- this.service
2378
- .delete([this.data.model])
2379
- .pipe(finalize(() => this.form.enable()))
2380
- .subscribe(() => {
2381
- this.alertService.info($localize `Supprimé`);
2382
- if (!this.isPanel) {
2383
- const defaultRoute = ['../../' + kebabCase(this.key)];
2384
- this.router.navigate(redirectionRoute ? redirectionRoute : defaultRoute, {
2385
- relativeTo: this.route,
2386
- });
2387
- }
2388
- else {
2389
- this.panelService?.goToPenultimatePanel();
2390
- }
2391
- });
2373
+ .pipe(switchMap$1(confirmed => {
2374
+ if (!confirmed) {
2375
+ return EMPTY;
2392
2376
  }
2393
- });
2377
+ this.preDelete(this.data.model);
2378
+ return this.service.delete([this.data.model]).pipe(switchMap$1(() => {
2379
+ this.alertService.info($localize `Supprimé`);
2380
+ if (this.isPanel) {
2381
+ this.panelService?.goToPenultimatePanel();
2382
+ return EMPTY;
2383
+ }
2384
+ else {
2385
+ const defaultRoute = ['../../' + kebabCase(this.key)];
2386
+ return this.router.navigate(redirectionRoute ? redirectionRoute : defaultRoute, {
2387
+ relativeTo: this.route,
2388
+ });
2389
+ }
2390
+ }));
2391
+ }), finalize(() => this.form.enable()))
2392
+ .subscribe();
2394
2393
  }
2395
2394
  postUpdate(model) { }
2396
2395
  /**
@@ -3553,6 +3552,7 @@ function cancellableTimeout(canceller, milliSeconds = 0) {
3553
3552
  function debug(debugName) {
3554
3553
  return tap({
3555
3554
  subscribe: () => console.log('SUBSCRIBE', debugName),
3555
+ unsubscribe: () => console.log('UNSUBSCRIBE', debugName),
3556
3556
  next: value => console.log('NEXT', debugName, value),
3557
3557
  error: error => console.log('ERROR', debugName, error),
3558
3558
  complete: () => console.log('COMPLETE', debugName),
@@ -3560,18 +3560,15 @@ function debug(debugName) {
3560
3560
  }
3561
3561
 
3562
3562
  class NaturalAbstractModelService {
3563
- constructor(apollo, name, oneQuery, allQuery, createMutation, updateMutation, deleteMutation) {
3563
+ constructor(apollo, naturalDebounceService, name, oneQuery, allQuery, createMutation, updateMutation, deleteMutation) {
3564
3564
  this.apollo = apollo;
3565
+ this.naturalDebounceService = naturalDebounceService;
3565
3566
  this.name = name;
3566
3567
  this.oneQuery = oneQuery;
3567
3568
  this.allQuery = allQuery;
3568
3569
  this.createMutation = createMutation;
3569
3570
  this.updateMutation = updateMutation;
3570
3571
  this.deleteMutation = deleteMutation;
3571
- /**
3572
- * Stores the debounced update function
3573
- */
3574
- this.debouncedUpdateCache = new Map();
3575
3572
  /**
3576
3573
  * Store the creation mutations that are pending
3577
3574
  */
@@ -3803,36 +3800,7 @@ class NaturalAbstractModelService {
3803
3800
  this.throwIfNotQuery(this.updateMutation);
3804
3801
  // Keep a single instance of the debounced update function
3805
3802
  const id = object.id;
3806
- let debounced = this.debouncedUpdateCache.get(id);
3807
- if (!debounced) {
3808
- const source = new ReplaySubject(1);
3809
- let wasCancelled = false;
3810
- const canceller = new Subject();
3811
- canceller.subscribe(() => {
3812
- wasCancelled = true;
3813
- source.complete();
3814
- canceller.complete();
3815
- });
3816
- // Create debounced update function
3817
- const result = source.pipe(debounceTime(2000), // Wait 2sec.
3818
- take(1), mergeMap(() => {
3819
- this.debouncedUpdateCache.delete(id);
3820
- if (wasCancelled) {
3821
- return EMPTY;
3822
- }
3823
- return this.updateNow(object);
3824
- }), shareReplay());
3825
- debounced = {
3826
- source,
3827
- canceller,
3828
- result,
3829
- };
3830
- this.debouncedUpdateCache.set(id, debounced);
3831
- }
3832
- // Notify our debounced update each time we ask to update
3833
- debounced.source.next();
3834
- // Return and observable that is updated when mutation is done
3835
- return debounced.result;
3803
+ return this.naturalDebounceService.debounce(this, id, this.updateNow(object));
3836
3804
  }
3837
3805
  /**
3838
3806
  * Update an object immediately when subscribing
@@ -3884,8 +3852,7 @@ class NaturalAbstractModelService {
3884
3852
  this.throwIfNotQuery(this.deleteMutation);
3885
3853
  const ids = objects.map(o => {
3886
3854
  // Cancel pending update
3887
- const debounced = this.debouncedUpdateCache.get(o.id);
3888
- debounced?.canceller.next();
3855
+ this.naturalDebounceService.cancel(this, o.id);
3889
3856
  return o.id;
3890
3857
  });
3891
3858
  const variables = merge({
@@ -4066,6 +4033,131 @@ class NaturalAbstractModelService {
4066
4033
  }
4067
4034
  }
4068
4035
 
4036
+ /**
4037
+ * Debounce subscriptions to observable, with possibility to cancel one, or flush all of them. Typically,
4038
+ * observables are object updates, so `NaturalAbstractModelService.updateNow()`.
4039
+ *
4040
+ * `key` must be an instance of `NaturalAbstractModelService` to separate objects by their types. So User with ID 1 is
4041
+ * not confused with Product with ID 1. It has no other purpose.
4042
+ *
4043
+ * `id` should be the ID of the object that will be updated.
4044
+ */
4045
+ class NaturalDebounceService {
4046
+ constructor() {
4047
+ this.flusher = new Subject();
4048
+ /**
4049
+ * Stores the debounced update function
4050
+ */
4051
+ this.allDebouncedUpdateCache = new Map();
4052
+ }
4053
+ /**
4054
+ * Debounce the given source observable for a short time. If called multiple times with the same key and id,
4055
+ * it will postpone the subscription to the source observable.
4056
+ *
4057
+ * Giving the same key and id but a different source observable will replace the original observable, but
4058
+ * keep the same debouncing timeline.
4059
+ */
4060
+ debounce(key, id, source) {
4061
+ const debouncedUpdateCache = this.getMap(key);
4062
+ let debounced = debouncedUpdateCache.get(id);
4063
+ if (debounced) {
4064
+ debounced.source = source;
4065
+ }
4066
+ else {
4067
+ const debouncer = new ReplaySubject(1);
4068
+ let wasCancelled = false;
4069
+ const canceller = new Subject();
4070
+ canceller.subscribe(() => {
4071
+ wasCancelled = true;
4072
+ debouncer.complete();
4073
+ canceller.complete();
4074
+ this.delete(key, id);
4075
+ });
4076
+ debounced = {
4077
+ debouncer,
4078
+ canceller,
4079
+ source,
4080
+ result: debouncer.pipe(debounceTime$1(2000), // Wait 2 seconds...
4081
+ raceWith(this.flusher), // ...unless flusher is triggered
4082
+ take$1(1), mergeMap(() => {
4083
+ this.delete(key, id);
4084
+ if (wasCancelled || !debounced) {
4085
+ return EMPTY;
4086
+ }
4087
+ return debounced.source;
4088
+ }), shareReplay$1()),
4089
+ };
4090
+ debouncedUpdateCache.set(id, debounced);
4091
+ }
4092
+ // Notify our debounced update each time we ask to update
4093
+ debounced.debouncer.next();
4094
+ // Return and observable that is updated when mutation is done
4095
+ return debounced.result;
4096
+ }
4097
+ cancel(key, id) {
4098
+ const debounced = this.allDebouncedUpdateCache.get(key)?.get(id);
4099
+ debounced?.canceller.next();
4100
+ }
4101
+ /**
4102
+ * Immediately execute all pending updates.
4103
+ *
4104
+ * It should typically be called before login out.
4105
+ *
4106
+ * The returned observable will complete when all updates complete, even if some of them error.
4107
+ */
4108
+ flush() {
4109
+ const all = [];
4110
+ this.allDebouncedUpdateCache.forEach(map => map.forEach(debounced => {
4111
+ all.push(debounced.result.pipe(catchError(() => of(undefined))));
4112
+ }));
4113
+ if (!all.length) {
4114
+ all.push(of(undefined));
4115
+ }
4116
+ return new Observable(subscriber => {
4117
+ const subscription = forkJoin(all)
4118
+ .pipe(map$1(() => undefined))
4119
+ .subscribe(subscriber);
4120
+ // Flush only after subscription process is finished
4121
+ this.flusher.next();
4122
+ return subscription;
4123
+ });
4124
+ }
4125
+ /**
4126
+ * Count of pending updates
4127
+ */
4128
+ get count() {
4129
+ let count = 0;
4130
+ this.allDebouncedUpdateCache.forEach(map => (count += map.size));
4131
+ return count;
4132
+ }
4133
+ getMap(key) {
4134
+ let debouncedUpdateCache = this.allDebouncedUpdateCache.get(key);
4135
+ if (!debouncedUpdateCache) {
4136
+ debouncedUpdateCache = new Map();
4137
+ this.allDebouncedUpdateCache.set(key, debouncedUpdateCache);
4138
+ }
4139
+ return debouncedUpdateCache;
4140
+ }
4141
+ delete(key, id) {
4142
+ const map = this.allDebouncedUpdateCache.get(key);
4143
+ if (!map) {
4144
+ return;
4145
+ }
4146
+ map.delete(id);
4147
+ if (!map.size) {
4148
+ this.allDebouncedUpdateCache.delete(key);
4149
+ }
4150
+ }
4151
+ }
4152
+ NaturalDebounceService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.1", ngImport: i0, type: NaturalDebounceService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
4153
+ NaturalDebounceService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.1.1", ngImport: i0, type: NaturalDebounceService, providedIn: 'root' });
4154
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.1", ngImport: i0, type: NaturalDebounceService, decorators: [{
4155
+ type: Injectable,
4156
+ args: [{
4157
+ providedIn: 'root',
4158
+ }]
4159
+ }] });
4160
+
4069
4161
  const enumTypeQuery = gql `
4070
4162
  query EnumType($name: String!) {
4071
4163
  __type(name: $name) {
@@ -4273,6 +4365,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.1", ngImpor
4273
4365
  }]
4274
4366
  }], ctorParameters: function () { return [{ type: i1$1.Apollo }]; } });
4275
4367
 
4368
+ const patterns = [
4369
+ /^(?<day>\d{1,2})\.(?<month>\d{1,2})\.(?<year>\d{4}|\d{2})$/,
4370
+ /^(?<day>\d{1,2})-(?<month>\d{1,2})-(?<year>\d{4}|\d{2})$/,
4371
+ /^(?<day>\d{1,2})\/(?<month>\d{1,2})\/(?<year>\d{4}|\d{2})$/,
4372
+ /^(?<day>\d{1,2})\\(?<month>\d{1,2})\\(?<year>\d{4}|\d{2})$/,
4373
+ // strict ISO format
4374
+ /^(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})$/,
4375
+ ];
4276
4376
  class NaturalSwissParsingDateAdapter extends NativeDateAdapter {
4277
4377
  /**
4278
4378
  * Parse commonly accepted swiss format, such as:
@@ -4286,24 +4386,24 @@ class NaturalSwissParsingDateAdapter extends NativeDateAdapter {
4286
4386
  return new Date(value);
4287
4387
  }
4288
4388
  if (typeof value === 'string') {
4289
- let m = value.match(/(\d{1,2})\.(\d{1,2})\.(\d{4}|\d{2})/);
4290
- if (m) {
4291
- let year = +m[3];
4292
- // Assume year 2000 if only two digits
4293
- if (year < 100) {
4294
- year += 2000;
4389
+ const trimmed = value.trim();
4390
+ for (const pattern of patterns) {
4391
+ const m = trimmed.match(pattern);
4392
+ if (m?.groups) {
4393
+ const year = +m.groups.year;
4394
+ const month = +m.groups.month;
4395
+ const day = +m.groups.day;
4396
+ return this.createDateIfValid(year, month, day);
4295
4397
  }
4296
- return this.createDateIfValid(year, +m[2], +m[1]);
4297
- }
4298
- // Attempt strict ISO format
4299
- m = value.match(/(\d{4})-(\d{2})-(\d{2})/);
4300
- if (m) {
4301
- return this.createDateIfValid(+m[1], +m[2], +m[3]);
4302
4398
  }
4303
4399
  }
4304
4400
  return null;
4305
4401
  }
4306
4402
  createDateIfValid(year, month, date) {
4403
+ // Assume year 2000 if only two digits
4404
+ if (year < 100) {
4405
+ year += 2000;
4406
+ }
4307
4407
  month = month - 1;
4308
4408
  if (month >= 0 && month <= 11 && date >= 1 && date <= 31) {
4309
4409
  return this.createDate(year, month, date);
@@ -8069,6 +8169,17 @@ function createFileInput(document) {
8069
8169
  fileElem.type = 'file';
8070
8170
  return fileElem;
8071
8171
  }
8172
+ function isDirectory(file) {
8173
+ return file
8174
+ .slice(0, 1)
8175
+ .text()
8176
+ .then(text => {
8177
+ // Firefox will return empty string for a folder, so we must check that special case.
8178
+ // That means that any empty file will incorrectly be interpreted as a folder on all
8179
+ // browsers, but that's tolerable because there is no real use-case to upload an empty file.
8180
+ return text !== '';
8181
+ }, () => false);
8182
+ }
8072
8183
  function stopEvent(event) {
8073
8184
  event.preventDefault();
8074
8185
  event.stopPropagation();
@@ -8164,10 +8275,6 @@ class NaturalAbstractFile extends NaturalAbstractController {
8164
8275
  this.element = element;
8165
8276
  this.naturalFileService = naturalFileService;
8166
8277
  this.document = document;
8167
- this.validators = [
8168
- { name: 'accept', fn: this.acceptValidator },
8169
- { name: 'fileSize', fn: this.fileSizeValidator },
8170
- ];
8171
8278
  /**
8172
8279
  * Whether we should accept a single file or multiple files
8173
8280
  */
@@ -8264,8 +8371,7 @@ class NaturalAbstractFile extends NaturalAbstractController {
8264
8371
  valid: [],
8265
8372
  invalid: [],
8266
8373
  };
8267
- for (const file of files) {
8268
- const error = this.validate(file);
8374
+ forkJoin(files.map(file => this.validate(file).pipe(tap$1(error => {
8269
8375
  if (error) {
8270
8376
  selection.invalid.push({
8271
8377
  file: file,
@@ -8275,17 +8381,18 @@ class NaturalAbstractFile extends NaturalAbstractController {
8275
8381
  else {
8276
8382
  selection.valid.push(file);
8277
8383
  }
8278
- }
8279
- if (selection.valid.length) {
8280
- this.fileChange.emit(selection.valid[0]);
8281
- }
8282
- if (selection.valid.length || selection.invalid.length) {
8283
- this.filesChange.emit(selection);
8284
- if (this.broadcast) {
8285
- this.naturalFileService.filesChanged.next(selection);
8384
+ })))).subscribe(() => {
8385
+ if (selection.valid.length) {
8386
+ this.fileChange.emit(selection.valid[0]);
8286
8387
  }
8287
- }
8288
- this.getFileElement().value = '';
8388
+ if (selection.valid.length || selection.invalid.length) {
8389
+ this.filesChange.emit(selection);
8390
+ if (this.broadcast) {
8391
+ this.naturalFileService.filesChanged.next(selection);
8392
+ }
8393
+ }
8394
+ this.getFileElement().value = '';
8395
+ });
8289
8396
  }
8290
8397
  /**
8291
8398
  * Called when input has files
@@ -8332,18 +8439,18 @@ class NaturalAbstractFile extends NaturalAbstractController {
8332
8439
  this.handleFiles(files);
8333
8440
  }
8334
8441
  validate(file) {
8335
- for (const validator of this.validators) {
8336
- if (!validator.fn.call(this, file)) {
8337
- return validator.name;
8442
+ return forkJoin({
8443
+ accept: of(acceptType(this.accept, file.type, file.name)),
8444
+ fileSize: of(!(this.maxSize && file.size > this.maxSize)),
8445
+ directory: isDirectory(file),
8446
+ }).pipe(map$1(result => {
8447
+ for (const [key, value] of Object.entries(result)) {
8448
+ if (!value) {
8449
+ return key;
8450
+ }
8338
8451
  }
8339
- }
8340
- return null;
8341
- }
8342
- acceptValidator(item) {
8343
- return acceptType(this.accept, item.type, item.name);
8344
- }
8345
- fileSizeValidator(item) {
8346
- return !(this.maxSize && item.size > this.maxSize);
8452
+ return null;
8453
+ }));
8347
8454
  }
8348
8455
  }
8349
8456
  NaturalAbstractFile.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.1", ngImport: i0, type: NaturalAbstractFile, deps: [{ token: i0.ElementRef }, { token: NaturalFileService }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Directive });
@@ -8695,9 +8802,21 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.1", ngImpor
8695
8802
  */
8696
8803
 
8697
8804
  class NaturalFixedButtonDetailComponent {
8698
- constructor() {
8805
+ constructor(route) {
8806
+ this.canChange = true;
8807
+ this.isCreation = false;
8699
8808
  this.create = new EventEmitter();
8700
8809
  this.delete = new EventEmitter();
8810
+ route.params.subscribe(() => (this.canChange = true));
8811
+ }
8812
+ get model() {
8813
+ return this._model;
8814
+ }
8815
+ set model(value) {
8816
+ this._model = value;
8817
+ if (this.canChange) {
8818
+ this.isCreation = !this._model.id;
8819
+ }
8701
8820
  }
8702
8821
  clickCreate() {
8703
8822
  if (this.form.enabled) {
@@ -8710,12 +8829,12 @@ class NaturalFixedButtonDetailComponent {
8710
8829
  }
8711
8830
  }
8712
8831
  }
8713
- NaturalFixedButtonDetailComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.1", ngImport: i0, type: NaturalFixedButtonDetailComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
8714
- NaturalFixedButtonDetailComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.1.1", type: NaturalFixedButtonDetailComponent, selector: "natural-fixed-button-detail", inputs: { model: "model", form: "form" }, outputs: { create: "create", delete: "delete" }, ngImport: i0, template: "<natural-fixed-button\n (click)=\"clickCreate()\"\n *ngIf=\"!model.id\"\n [disabled]=\"form.disabled\"\n [color]=\"form.valid ? 'accent' : 'warn'\"\n class=\"detail-speed-dial\"\n icon=\"save\"\n></natural-fixed-button>\n\n<natural-fixed-button\n (click)=\"clickDelete()\"\n *ngIf=\"model.id && (!model.permissions || model.permissions.delete)\"\n [disabled]=\"form.disabled\"\n class=\"detail-speed-dial\"\n color=\"warn\"\n icon=\"delete_forever\"\n i18n-matTooltip\n matTooltip=\"Supprimer d\u00E9finitivement\"\n matTooltipPosition=\"left\"\n></natural-fixed-button>\n", styles: [""], dependencies: [{ kind: "directive", type: i1$3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: NaturalFixedButtonComponent, selector: "natural-fixed-button", inputs: ["icon", "link", "color", "disabled"] }, { kind: "directive", type: i7.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }] });
8832
+ NaturalFixedButtonDetailComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.1", ngImport: i0, type: NaturalFixedButtonDetailComponent, deps: [{ token: i2$1.ActivatedRoute }], target: i0.ɵɵFactoryTarget.Component });
8833
+ NaturalFixedButtonDetailComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.1.1", type: NaturalFixedButtonDetailComponent, selector: "natural-fixed-button-detail", inputs: { model: "model", form: "form" }, outputs: { create: "create", delete: "delete" }, ngImport: i0, template: "<natural-fixed-button\n (click)=\"clickCreate()\"\n *ngIf=\"isCreation\"\n [disabled]=\"form.disabled\"\n [color]=\"form.valid ? 'accent' : 'warn'\"\n class=\"detail-speed-dial\"\n icon=\"save\"\n></natural-fixed-button>\n\n<natural-fixed-button\n (click)=\"clickDelete()\"\n *ngIf=\"!isCreation && (!model.permissions || model.permissions.delete)\"\n [disabled]=\"form.disabled\"\n class=\"detail-speed-dial\"\n color=\"warn\"\n icon=\"delete_forever\"\n i18n-matTooltip\n matTooltip=\"Supprimer d\u00E9finitivement\"\n matTooltipPosition=\"left\"\n></natural-fixed-button>\n", styles: [""], dependencies: [{ kind: "directive", type: i1$3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: NaturalFixedButtonComponent, selector: "natural-fixed-button", inputs: ["icon", "link", "color", "disabled"] }, { kind: "directive", type: i7.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }] });
8715
8834
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.1", ngImport: i0, type: NaturalFixedButtonDetailComponent, decorators: [{
8716
8835
  type: Component,
8717
- args: [{ selector: 'natural-fixed-button-detail', template: "<natural-fixed-button\n (click)=\"clickCreate()\"\n *ngIf=\"!model.id\"\n [disabled]=\"form.disabled\"\n [color]=\"form.valid ? 'accent' : 'warn'\"\n class=\"detail-speed-dial\"\n icon=\"save\"\n></natural-fixed-button>\n\n<natural-fixed-button\n (click)=\"clickDelete()\"\n *ngIf=\"model.id && (!model.permissions || model.permissions.delete)\"\n [disabled]=\"form.disabled\"\n class=\"detail-speed-dial\"\n color=\"warn\"\n icon=\"delete_forever\"\n i18n-matTooltip\n matTooltip=\"Supprimer d\u00E9finitivement\"\n matTooltipPosition=\"left\"\n></natural-fixed-button>\n" }]
8718
- }], propDecorators: { model: [{
8836
+ args: [{ selector: 'natural-fixed-button-detail', template: "<natural-fixed-button\n (click)=\"clickCreate()\"\n *ngIf=\"isCreation\"\n [disabled]=\"form.disabled\"\n [color]=\"form.valid ? 'accent' : 'warn'\"\n class=\"detail-speed-dial\"\n icon=\"save\"\n></natural-fixed-button>\n\n<natural-fixed-button\n (click)=\"clickDelete()\"\n *ngIf=\"!isCreation && (!model.permissions || model.permissions.delete)\"\n [disabled]=\"form.disabled\"\n class=\"detail-speed-dial\"\n color=\"warn\"\n icon=\"delete_forever\"\n i18n-matTooltip\n matTooltip=\"Supprimer d\u00E9finitivement\"\n matTooltipPosition=\"left\"\n></natural-fixed-button>\n" }]
8837
+ }], ctorParameters: function () { return [{ type: i2$1.ActivatedRoute }]; }, propDecorators: { model: [{
8719
8838
  type: Input
8720
8839
  }], form: [{
8721
8840
  type: Input
@@ -10842,5 +10961,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.1", ngImpor
10842
10961
  * Generated bundle index. Do not edit.
10843
10962
  */
10844
10963
 
10845
- export { AvatarComponent, AvatarService, FileComponent, IconsConfigService, LOCAL_STORAGE, NATURAL_DROPDOWN_DATA, NATURAL_SEO_CONFIG, NaturalAbstractController, NaturalAbstractDetail, NaturalAbstractEditableList, NaturalAbstractList, NaturalAbstractModelService, NaturalAbstractNavigableList, NaturalAbstractPanel, NaturalAlertModule, NaturalAlertService, NaturalAvatarModule, NaturalCapitalizePipe, NaturalColumnsPickerColumnDirective, NaturalColumnsPickerComponent, NaturalColumnsPickerModule, NaturalCommonModule, NaturalConfirmComponent, NaturalDataSource, NaturalDetailHeaderComponent, NaturalDetailHeaderModule, NaturalDialogTriggerComponent, NaturalDialogTriggerModule, NaturalDropdownComponentsModule, NaturalDropdownRef, NaturalEllipsisPipe, NaturalEnumPipe, NaturalEnumService, NaturalErrorHandler, NaturalErrorModule, NaturalFileDropDirective, NaturalFileModule, NaturalFileSelectDirective, NaturalFileService, NaturalFixedButtonComponent, NaturalFixedButtonDetailComponent, NaturalFixedButtonDetailModule, NaturalFixedButtonModule, NaturalHierarchicSelectorComponent, NaturalHierarchicSelectorDialogComponent, NaturalHierarchicSelectorDialogService, NaturalHierarchicSelectorModule, NaturalHierarchicSelectorService, NaturalHttpPrefixDirective, NaturalIconComponent, NaturalIconModule, NaturalLinkMutationService, NaturalLinkableTabDirective, NaturalLoggerConfigExtra, NaturalLoggerConfigUrl, NaturalMatomoModule, NaturalMatomoService, NaturalMemoryStorage, NaturalPanelsComponent, NaturalPanelsModule, NaturalPanelsService, NaturalPersistenceService, NaturalQueryVariablesManager, NaturalRelationsComponent, NaturalRelationsModule, NaturalSearchComponent, NaturalSearchModule, NaturalSelectComponent, NaturalSelectEnumComponent, NaturalSelectHierarchicComponent, NaturalSelectModule, NaturalSeoService, NaturalSidenavComponent, NaturalSidenavContainerComponent, NaturalSidenavContentComponent, NaturalSidenavModule, NaturalSidenavService, NaturalSidenavStackService, NaturalSrcDensityDirective, NaturalStampComponent, NaturalStampModule, NaturalSwissDatePipe, NaturalSwissParsingDateAdapter, NaturalTableButtonComponent, NaturalTableButtonModule, PanelsHooksConfig, SESSION_STORAGE, SortingOrder, TypeDateComponent, TypeDateRangeComponent, TypeHierarchicSelectorComponent, TypeNaturalSelectComponent, TypeNumberComponent, TypeSelectComponent, TypeTextComponent, available, cancellableTimeout, cleanSameValues, collectErrors, copyToClipboard, debug, decimal, deepFreeze, deliverableEmail, ensureHttpPrefix, fallbackIfNoOpenedPanels, formatIsoDate, formatIsoDateTime, fromUrl, getForegroundColor, hasFilesAndProcessDate, ifValid, integer, localStorageFactory, localStorageProvider, lowerCaseFirstLetter, makePlural, memoryLocalStorageProvider, memorySessionStorageProvider, mergeOverrideArray, money, naturalPanelsUrlMatcher, relationsToIds, replaceObjectKeepingReference, replaceOperatorByField, replaceOperatorByName, sessionStorageFactory, sessionStorageProvider, toGraphQLDoctrineFilter, toNavigationParameters, toUrl, unique, upperCaseFirstLetter, urlValidator, validTlds, validateAllFormControls, wrapLike };
10964
+ export { AvatarComponent, AvatarService, FileComponent, IconsConfigService, LOCAL_STORAGE, NATURAL_DROPDOWN_DATA, NATURAL_SEO_CONFIG, NaturalAbstractController, NaturalAbstractDetail, NaturalAbstractEditableList, NaturalAbstractList, NaturalAbstractModelService, NaturalAbstractNavigableList, NaturalAbstractPanel, NaturalAlertModule, NaturalAlertService, NaturalAvatarModule, NaturalCapitalizePipe, NaturalColumnsPickerColumnDirective, NaturalColumnsPickerComponent, NaturalColumnsPickerModule, NaturalCommonModule, NaturalConfirmComponent, NaturalDataSource, NaturalDebounceService, NaturalDetailHeaderComponent, NaturalDetailHeaderModule, NaturalDialogTriggerComponent, NaturalDialogTriggerModule, NaturalDropdownComponentsModule, NaturalDropdownRef, NaturalEllipsisPipe, NaturalEnumPipe, NaturalEnumService, NaturalErrorHandler, NaturalErrorModule, NaturalFileDropDirective, NaturalFileModule, NaturalFileSelectDirective, NaturalFileService, NaturalFixedButtonComponent, NaturalFixedButtonDetailComponent, NaturalFixedButtonDetailModule, NaturalFixedButtonModule, NaturalHierarchicSelectorComponent, NaturalHierarchicSelectorDialogComponent, NaturalHierarchicSelectorDialogService, NaturalHierarchicSelectorModule, NaturalHierarchicSelectorService, NaturalHttpPrefixDirective, NaturalIconComponent, NaturalIconModule, NaturalLinkMutationService, NaturalLinkableTabDirective, NaturalLoggerConfigExtra, NaturalLoggerConfigUrl, NaturalMatomoModule, NaturalMatomoService, NaturalMemoryStorage, NaturalPanelsComponent, NaturalPanelsModule, NaturalPanelsService, NaturalPersistenceService, NaturalQueryVariablesManager, NaturalRelationsComponent, NaturalRelationsModule, NaturalSearchComponent, NaturalSearchModule, NaturalSelectComponent, NaturalSelectEnumComponent, NaturalSelectHierarchicComponent, NaturalSelectModule, NaturalSeoService, NaturalSidenavComponent, NaturalSidenavContainerComponent, NaturalSidenavContentComponent, NaturalSidenavModule, NaturalSidenavService, NaturalSidenavStackService, NaturalSrcDensityDirective, NaturalStampComponent, NaturalStampModule, NaturalSwissDatePipe, NaturalSwissParsingDateAdapter, NaturalTableButtonComponent, NaturalTableButtonModule, PanelsHooksConfig, SESSION_STORAGE, SortingOrder, TypeDateComponent, TypeDateRangeComponent, TypeHierarchicSelectorComponent, TypeNaturalSelectComponent, TypeNumberComponent, TypeSelectComponent, TypeTextComponent, available, cancellableTimeout, cleanSameValues, collectErrors, copyToClipboard, debug, decimal, deepFreeze, deliverableEmail, ensureHttpPrefix, fallbackIfNoOpenedPanels, formatIsoDate, formatIsoDateTime, fromUrl, getForegroundColor, hasFilesAndProcessDate, ifValid, integer, localStorageFactory, localStorageProvider, lowerCaseFirstLetter, makePlural, memoryLocalStorageProvider, memorySessionStorageProvider, mergeOverrideArray, money, naturalPanelsUrlMatcher, relationsToIds, replaceObjectKeepingReference, replaceOperatorByField, replaceOperatorByName, sessionStorageFactory, sessionStorageProvider, toGraphQLDoctrineFilter, toNavigationParameters, toUrl, unique, upperCaseFirstLetter, urlValidator, validTlds, validateAllFormControls, wrapLike };
10846
10965
  //# sourceMappingURL=ecodev-natural.mjs.map