@sumaris-net/ngx-components 0.28.0 → 0.28.4

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.
Files changed (27) hide show
  1. package/bundles/sumaris-net.ngx-components.umd.js +135 -63
  2. package/bundles/sumaris-net.ngx-components.umd.js.map +1 -1
  3. package/bundles/sumaris-net.ngx-components.umd.min.js +2 -2
  4. package/bundles/sumaris-net.ngx-components.umd.min.js.map +1 -1
  5. package/esm2015/src/app/core/account/account.js +4 -5
  6. package/esm2015/src/app/core/auth/form/form-auth.js +3 -4
  7. package/esm2015/src/app/core/form/editor.class.js +10 -2
  8. package/esm2015/src/app/core/form/entity-editor.class.js +15 -7
  9. package/esm2015/src/app/core/form/form.class.js +24 -10
  10. package/esm2015/src/app/core/form/list.form.js +2 -3
  11. package/esm2015/src/app/core/form/properties.form.js +2 -3
  12. package/esm2015/src/app/core/settings/settings.page.js +3 -4
  13. package/esm2015/src/app/shared/dates.js +2 -2
  14. package/esm2015/src/app/shared/pipes/translate-context.pipe.js +4 -8
  15. package/esm2015/src/app/shared/services/translate-context.service.js +38 -13
  16. package/fesm2015/sumaris-net.ngx-components.js +95 -46
  17. package/fesm2015/sumaris-net.ngx-components.js.map +1 -1
  18. package/package.json +1 -1
  19. package/src/app/core/account/account.d.ts +0 -1
  20. package/src/app/core/auth/form/form-auth.d.ts +0 -1
  21. package/src/app/core/form/editor.class.d.ts +2 -0
  22. package/src/app/core/form/form.class.d.ts +10 -2
  23. package/src/app/core/form/list.form.d.ts +0 -1
  24. package/src/app/core/form/properties.form.d.ts +0 -1
  25. package/src/app/core/settings/settings.page.d.ts +0 -1
  26. package/src/app/shared/services/translate-context.service.d.ts +10 -0
  27. package/sumaris-net.ngx-components.metadata.json +1 -1
@@ -36,7 +36,7 @@ import { MatAutocomplete, MatAutocompleteTrigger, MatAutocompleteModule, MAT_AUT
36
36
  import { __awaiter, __decorate } from 'tslib';
37
37
  import * as i1$6 from '@angular/forms';
38
38
  import { NG_VALUE_ACCESSOR, FormGroupDirective, AbstractControl, FormGroup, FormArray, FormControl, ReactiveFormsModule, Validators, FormBuilder } from '@angular/forms';
39
- import { timer, merge, fromEvent, Subscription, BehaviorSubject, Subject, isObservable, of, noop as noop$8, Observable, defer, from, combineLatest, EMPTY } from 'rxjs';
39
+ import { timer, merge, fromEvent, Subscription, BehaviorSubject, Subject, isObservable, noop as noop$8, Observable, defer, of, from, combineLatest, EMPTY } from 'rxjs';
40
40
  import { filter, first, map, takeUntil, startWith, debounceTime, takeWhile, switchMap, tap, distinctUntilChanged, mergeMap, catchError, throttleTime, skip } from 'rxjs/operators';
41
41
  import * as i1$1 from '@ngx-translate/core';
42
42
  import { TranslateService, TranslateModule } from '@ngx-translate/core';
@@ -2112,7 +2112,7 @@ class DateUtils {
2112
2112
  return date1 && date2 && date1.isSameOrBefore(date2) ? date1 : date2;
2113
2113
  }
2114
2114
  static max(date1, date2) {
2115
- return date1 && date2 && date1.isSameOrAfter(date2) ? date1 : date2;
2115
+ return !date1 ? date2 : (!date2 || date1.isSameOrAfter(date2) ? date1 : date2);
2116
2116
  }
2117
2117
  }
2118
2118
  function toDateISOString(value) {
@@ -2431,23 +2431,41 @@ class TranslateContextService {
2431
2431
  }
2432
2432
  get(key, context, interpolateParams) {
2433
2433
  // No context: do a normal translate
2434
- if (!isNil(context))
2434
+ if (!key || !isNil(context))
2435
2435
  return this.translate.get(key, interpolateParams);
2436
2436
  // Compute a contextual i18n key, using the context as suffix
2437
- const contextKey = this.contextualKey(key, context);
2437
+ const contextualKeys = this.contextualKeys(key, context);
2438
2438
  // Return the contextual translation, or default of not exists
2439
- return this.translate.get(contextKey, interpolateParams)
2440
- .pipe(mergeMap(translation => (translation !== contextKey) ? of(translation) : this.translate.get(key)));
2439
+ return this.translate.get(contextualKeys, interpolateParams)
2440
+ .pipe(map(translations => this.findFirstValid(contextualKeys, translations) || key));
2441
2441
  }
2442
2442
  instant(key, context, interpolateParams) {
2443
2443
  // No context: do a normal translate
2444
- if (isNilOrBlank(context))
2444
+ if (!key || isNilOrBlank(context))
2445
2445
  return this.translate.instant(key, interpolateParams);
2446
2446
  // Compute a contextual i18n key, using the context as suffix
2447
- const contextualKey = this.contextualKey(key, context);
2448
- // Return the contextual translation, or default of not exists
2449
- const translation = this.translate.instant(contextualKey, interpolateParams);
2450
- return (translation !== contextualKey) ? translation : this.translate.instant(key, interpolateParams);
2447
+ const contextualKeys = this.contextualKeys(key, context);
2448
+ const translations = this.translate.instant(contextualKeys, interpolateParams);
2449
+ return this.findFirstValid(contextualKeys, translations) || key;
2450
+ }
2451
+ /**
2452
+ * Compute contextual i18n keys, using the context as suffix.<br>
2453
+ * Suffix can be simple name (like 'aaa' - will return ['<key>.aaa']) or complexe (like 'aaa.bbb' - will return ['<key>.aaa.bbb', '<key>.aaa']
2454
+ *
2455
+ * @param key
2456
+ * @param context
2457
+ * @private
2458
+ */
2459
+ contextualKeys(key, context) {
2460
+ return context.split('.')
2461
+ .filter(isNotNilOrBlank)
2462
+ .reduce((res, item) => {
2463
+ const inheritedContext = res.length > 0 ? (res[res.length - 1] + '.') : '';
2464
+ return res.concat(inheritedContext + item);
2465
+ }, [])
2466
+ .reverse() // Start with children, ends with parent key
2467
+ .map(contextItem => this.contextualKey(key, contextItem))
2468
+ .concat(key);
2451
2469
  }
2452
2470
  /**
2453
2471
  * Compute a contextual i18n key, using the context as suffix
@@ -2467,6 +2485,14 @@ class TranslateContextService {
2467
2485
  ? `${context}${key}`
2468
2486
  : parts.slice(0, parts.length - 1).concat(context + parts[parts.length - 1]).join('.');
2469
2487
  }
2488
+ findFirstValid(keys, translations) {
2489
+ // For eac contextual key: try to find translation, then use the first valid
2490
+ for (let key of keys) {
2491
+ if (translations[key] !== key)
2492
+ return translations[key];
2493
+ }
2494
+ return undefined;
2495
+ }
2470
2496
  }
2471
2497
  TranslateContextService.ɵprov = i0.ɵɵdefineInjectable({ factory: function TranslateContextService_Factory() { return new TranslateContextService(i0.ɵɵinject(i1$1.TranslateService)); }, token: TranslateContextService, providedIn: "root" });
2472
2498
  TranslateContextService.decorators = [
@@ -2508,12 +2534,11 @@ class TranslateContextPipe {
2508
2534
  return this.value;
2509
2535
  }
2510
2536
  }
2511
- TranslateContextPipe.ɵprov = i0.ɵɵdefineInjectable({ factory: function TranslateContextPipe_Factory() { return new TranslateContextPipe(i0.ɵɵinject(TranslateContextService), i0.ɵɵinject(i0.ChangeDetectorRef)); }, token: TranslateContextPipe, providedIn: "root" });
2512
2537
  TranslateContextPipe.decorators = [
2538
+ { type: Injectable },
2513
2539
  { type: Pipe, args: [{
2514
2540
  name: 'translateContext'
2515
- },] },
2516
- { type: Injectable, args: [{ providedIn: 'root' },] }
2541
+ },] }
2517
2542
  ];
2518
2543
  TranslateContextPipe.ctorParameters = () => [
2519
2544
  { type: TranslateContextService },
@@ -2526,12 +2551,11 @@ class TranslatablePipe {
2526
2551
  return (_a = changeCaseToUnderscore(value)) === null || _a === void 0 ? void 0 : _a.toUpperCase();
2527
2552
  }
2528
2553
  }
2529
- TranslatablePipe.ɵprov = i0.ɵɵdefineInjectable({ factory: function TranslatablePipe_Factory() { return new TranslatablePipe(); }, token: TranslatablePipe, providedIn: "root" });
2530
2554
  TranslatablePipe.decorators = [
2531
2555
  { type: Pipe, args: [{
2532
2556
  name: 'translatable'
2533
2557
  },] },
2534
- { type: Injectable, args: [{ providedIn: 'root' },] }
2558
+ { type: Injectable }
2535
2559
  ];
2536
2560
 
2537
2561
  class PropertyGetPipe {
@@ -16659,7 +16683,7 @@ class AppForm {
16659
16683
  this.error = null;
16660
16684
  this._enable = false;
16661
16685
  this._$ready = new BehaviorSubject(false);
16662
- this._loading = true;
16686
+ this._$loading = new BehaviorSubject(true);
16663
16687
  this.i18nFieldPrefix = null;
16664
16688
  this._subscription = new Subscription();
16665
16689
  this.debug = false;
@@ -16675,8 +16699,20 @@ class AppForm {
16675
16699
  });
16676
16700
  this.autocompleteFields = this.autocompleteHelper.fields;
16677
16701
  }
16678
- get _ready() {
16679
- return this._$ready.value == true;
16702
+ /**
16703
+ * @deprecated
16704
+ */
16705
+ set _loading(value) {
16706
+ this._$loading.next(value);
16707
+ }
16708
+ /**
16709
+ * @deprecated
16710
+ */
16711
+ get _loading() {
16712
+ return this._$loading.value;
16713
+ }
16714
+ get loading() {
16715
+ return this._$loading.value;
16680
16716
  }
16681
16717
  get value() {
16682
16718
  return this.form.value;
@@ -16770,9 +16806,11 @@ class AppForm {
16770
16806
  if (this.debug)
16771
16807
  console.debug('[form] Updating form (using entity)', data);
16772
16808
  // Convert object to json, then apply it to form (e.g. convert 'undefined' into 'null')
16773
- AppFormUtils.copyEntity2Form(data, this.form, Object.assign({ emitEvent: false, onlySelf: true }, opts));
16774
- if (!opts || opts.emitEvent !== true)
16809
+ AppFormUtils.copyEntity2Form(data, this.form, opts);
16810
+ if (!opts || opts.emitEvent !== false) {
16811
+ this.markAsLoaded({ emitEvent: false });
16775
16812
  this.markForCheck();
16813
+ }
16776
16814
  }
16777
16815
  reset(data, opts) {
16778
16816
  if (data) {
@@ -16821,15 +16859,15 @@ class AppForm {
16821
16859
  this.markForCheck();
16822
16860
  }
16823
16861
  markAsLoading(opts) {
16824
- if (!this._loading) {
16825
- this._loading = true;
16862
+ if (this._$loading.value !== true) {
16863
+ this._$loading.next(true);
16826
16864
  if (!opts || opts.emitEvent !== false)
16827
16865
  this.markForCheck();
16828
16866
  }
16829
16867
  }
16830
16868
  markAsLoaded(opts) {
16831
- if (this._loading) {
16832
- this._loading = false;
16869
+ if (this._$loading.value !== false) {
16870
+ this._$loading.next(false);
16833
16871
  if (!opts || opts.emitEvent !== false)
16834
16872
  this.markForCheck();
16835
16873
  }
@@ -16919,7 +16957,6 @@ class AuthForm extends AppForm {
16919
16957
  this.network = network;
16920
16958
  this.cd = cd;
16921
16959
  this.environment = environment;
16922
- this.loading = false;
16923
16960
  this.canWorkOffline = false;
16924
16961
  this.showPwd = false;
16925
16962
  this.onCancel = new EventEmitter();
@@ -16967,13 +17004,13 @@ class AuthForm extends AppForm {
16967
17004
  }
16968
17005
  if (this.form.invalid || this.loading)
16969
17006
  return;
16970
- this.loading = true;
17007
+ this.markAsLoading();
16971
17008
  const data = this.form.value;
16972
17009
  this.showPwd = false; // Hide password
16973
17010
  this.error = null; // Reset error
16974
17011
  this.registerSubscription(this.onSubmit
16975
17012
  .pipe(debounceTime(500))
16976
- .subscribe(res => this.loading = false));
17013
+ .subscribe(res => this.markAsLoaded()));
16977
17014
  setTimeout(() => this.onSubmit.emit({
16978
17015
  username: data.username,
16979
17016
  password: data.password,
@@ -17612,7 +17649,6 @@ class AccountPage extends AppForm {
17612
17649
  this.translate = translate;
17613
17650
  this.settings = settings;
17614
17651
  this.cd = cd;
17615
- this.loading = true;
17616
17652
  this.email = {
17617
17653
  confirmed: false,
17618
17654
  notConfirmed: false,
@@ -17642,7 +17678,7 @@ class AccountPage extends AppForm {
17642
17678
  this.onLogin(this.accountService.account);
17643
17679
  }
17644
17680
  else {
17645
- this.loading = false;
17681
+ this.markAsLoaded();
17646
17682
  }
17647
17683
  }));
17648
17684
  }
@@ -17659,7 +17695,7 @@ class AccountPage extends AppForm {
17659
17695
  this.enable();
17660
17696
  this.markAsPristine();
17661
17697
  this.startListenChanges();
17662
- this.loading = false;
17698
+ this.markAsLoaded();
17663
17699
  }
17664
17700
  onLogout() {
17665
17701
  this.isLogin = false;
@@ -17676,7 +17712,7 @@ class AccountPage extends AppForm {
17676
17712
  refresh(event) {
17677
17713
  return __awaiter(this, void 0, void 0, function* () {
17678
17714
  this.disable();
17679
- this.loading = true;
17715
+ this.markAsLoading();
17680
17716
  return this.accountService.refresh();
17681
17717
  });
17682
17718
  }
@@ -18149,7 +18185,6 @@ class SettingsPage extends AppForm {
18149
18185
  this.cd = cd;
18150
18186
  this.network = network;
18151
18187
  this.locales = locales;
18152
- this.loading = true;
18153
18188
  this.saving = false;
18154
18189
  this.usageModes = ['FIELD', 'DESK'];
18155
18190
  this.propertyDefinitionsByKey = {};
@@ -18209,7 +18244,7 @@ class SettingsPage extends AppForm {
18209
18244
  }
18210
18245
  load() {
18211
18246
  return __awaiter(this, void 0, void 0, function* () {
18212
- this.loading = true;
18247
+ this.markAsLoading();
18213
18248
  console.debug('[settings] Loading settings...');
18214
18249
  const data = this.settings.settings;
18215
18250
  // Set defaults
@@ -18240,7 +18275,7 @@ class SettingsPage extends AppForm {
18240
18275
  this.enable({ emitEvent: false });
18241
18276
  // Apply inheritance
18242
18277
  this.setAccountInheritance(data.accountInheritance, { emitEvent: false });
18243
- this.loading = false;
18278
+ this.markAsLoaded();
18244
18279
  this.error = null;
18245
18280
  this.markForCheck();
18246
18281
  }
@@ -18425,7 +18460,6 @@ class AppPropertiesForm extends AppForm {
18425
18460
  this.settings = settings;
18426
18461
  this.cd = cd;
18427
18462
  this.formGroupDir = formGroupDir;
18428
- this.loading = true;
18429
18463
  this.definitionsMapByKey = {};
18430
18464
  this.definitionsByIndex = {};
18431
18465
  //this.debug = !environment.production;
@@ -18494,7 +18528,7 @@ class AppPropertiesForm extends AppForm {
18494
18528
  this.helper.resize(values.length);
18495
18529
  this.helper.formArray.patchValue(values, { emitEvent: false });
18496
18530
  this.markAsPristine();
18497
- this.loading = false;
18531
+ this.markAsLoaded();
18498
18532
  }
18499
18533
  /* -- protected methods -- */
18500
18534
  getPropertyFormGroup(data) {
@@ -18538,7 +18572,6 @@ class AppListForm extends AppForm {
18538
18572
  this.settings = settings;
18539
18573
  this.cd = cd;
18540
18574
  this.formGroupDir = formGroupDir;
18541
- this.loading = true;
18542
18575
  this.selection = new SelectionModel(true, []);
18543
18576
  this.displayWithFn = referentialToString;
18544
18577
  this.onNewItem = new EventEmitter();
@@ -18622,7 +18655,7 @@ class AppListForm extends AppForm {
18622
18655
  }
18623
18656
  this.selection.clear();
18624
18657
  this.markAsPristine();
18625
- this.loading = false;
18658
+ this.markAsLoaded();
18626
18659
  }
18627
18660
  /** Whether the number of selected elements matches the total number of rows. */
18628
18661
  isAllSelected() {
@@ -22017,6 +22050,9 @@ class AppEditor {
22017
22050
  get tables() {
22018
22051
  return this._children && this._children.filter(c => c instanceof AppTable);
22019
22052
  }
22053
+ get forms() {
22054
+ return this._children && this._children.filter(c => c instanceof AppForm);
22055
+ }
22020
22056
  get dirty() {
22021
22057
  var _a;
22022
22058
  return this._dirty || (((_a = this._children) === null || _a === void 0 ? void 0 : _a.findIndex(c => c.enabled && c.dirty)) !== -1) || false;
@@ -22137,10 +22173,15 @@ class AppEditor {
22137
22173
  }
22138
22174
  }
22139
22175
  markAsLoaded(opts) {
22176
+ var _a;
22140
22177
  if (this._loading) {
22141
22178
  this._loading = false;
22142
- if (!opts || opts.emitEvent !== false)
22179
+ if (!opts || opts.emitEvent !== false) {
22180
+ // Emit to children forms
22181
+ // Tables should be changed by parent
22182
+ (_a = this.forms) === null || _a === void 0 ? void 0 : _a.forEach(c => c.markAsLoaded(opts));
22143
22183
  this.markForCheck();
22184
+ }
22144
22185
  }
22145
22186
  }
22146
22187
  markAsReady(opts) {
@@ -22658,12 +22699,20 @@ class AppEntityEditor extends AppTabEditor {
22658
22699
  this.error = null;
22659
22700
  // New data
22660
22701
  if (isNil(id)) {
22661
- // Create using default values
22662
- const data = new this.dataType();
22663
- this._usageMode = this.computeUsageMode(data);
22664
- yield this.onNewEntity(data, opts);
22665
- yield this.updateView(data, Object.assign({ openTabIndex: 0 }, opts));
22666
- this.markAsLoaded();
22702
+ try {
22703
+ // Create using default values
22704
+ const data = new this.dataType();
22705
+ this._usageMode = this.computeUsageMode(data);
22706
+ yield this.onNewEntity(data, opts);
22707
+ yield this.updateView(data, Object.assign({ openTabIndex: 0 }, opts));
22708
+ }
22709
+ catch (err) {
22710
+ this.setError(err);
22711
+ this.selectedTabIndex = 0;
22712
+ }
22713
+ finally {
22714
+ this.markAsLoaded();
22715
+ }
22667
22716
  }
22668
22717
  // Load existing data
22669
22718
  else {