@sumaris-net/ngx-components 1.6.7 → 1.6.12

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 +125 -117
  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/public_api.js +3 -3
  6. package/esm2015/src/app/core/auth/form/form-auth.js +2 -2
  7. package/esm2015/src/app/core/services/model/filter.model.js +1 -1
  8. package/esm2015/src/app/core/services/model/referential.model.js +1 -1
  9. package/esm2015/src/app/core/table/table.class.js +8 -8
  10. package/esm2015/src/app/shared/material/autocomplete/material.autocomplete.js +25 -22
  11. package/esm2015/src/app/shared/material/boolean/material.boolean.js +3 -4
  12. package/esm2015/src/app/shared/material/chips/material.chips.js +21 -9
  13. package/esm2015/src/app/shared/material/datetime/material.date.js +41 -41
  14. package/esm2015/src/app/shared/material/datetime/material.datetime.js +29 -29
  15. package/esm2015/src/app/shared/pipes/translate-context.pipe.js +3 -5
  16. package/fesm2015/sumaris-net.ngx-components.js +123 -111
  17. package/fesm2015/sumaris-net.ngx-components.js.map +1 -1
  18. package/package.json +1 -1
  19. package/public_api.d.ts +2 -2
  20. package/src/app/core/services/model/filter.model.d.ts +1 -1
  21. package/src/app/core/services/model/referential.model.d.ts +3 -3
  22. package/src/app/core/table/table.class.d.ts +4 -4
  23. package/src/app/shared/material/boolean/material.boolean.d.ts +0 -1
  24. package/src/app/shared/material/datetime/material.date.d.ts +6 -6
  25. package/src/app/shared/material/datetime/material.datetime.d.ts +9 -9
  26. package/src/app/shared/pipes/translate-context.pipe.d.ts +1 -1
  27. package/sumaris-net.ngx-components.metadata.json +1 -1
@@ -1189,9 +1189,10 @@ class MatAutocompleteField {
1189
1189
  // Filter if not enough character
1190
1190
  filter(value => value.length >= this.suggestLengthThreshold),
1191
1191
  // Wait a debounce time
1192
- debounceTime(this.debounceTime),
1192
+ debounceTime(this.debounceTime)
1193
1193
  // DEBUG
1194
- tap((value) => console.debug(this.logPrefix + ' Search text changes:', value))),
1194
+ //,tap((value) => this.debug && console.debug(this.logPrefix + ' Search text changes:', value))
1195
+ ),
1195
1196
  // Object set: use it (no distinctUntilChanged() pipe need)
1196
1197
  this.formControl.valueChanges
1197
1198
  .pipe(startWith(this.formControl.value), filter(value => (this.searchable && isNotNil(value) && typeof value === 'object')), tap(value => {
@@ -1207,35 +1208,38 @@ class MatAutocompleteField {
1207
1208
  this.matInputText.nativeElement.value = this.displayValue;
1208
1209
  }
1209
1210
  }
1210
- }),
1211
+ })
1211
1212
  // DEBUG
1212
- tap(value => this.debug && console.debug(this.logPrefix + ' Received an object value: ', value))),
1213
+ //,tap(value => this.debug && console.debug(this.logPrefix + ' Received an object value: ', value))
1214
+ ),
1213
1215
  // On dropdown button click (no distinctUntilChanged(), nor debounceTime)
1214
1216
  this.dropButtonClick
1215
1217
  .pipe(filter(event => this.searchable && this.enabled && (!event || !event.defaultPrevented)), map(_ => this.showAllOnFocus ? '*' : this.formControl.value),
1216
- // Make enough characters
1218
+ // Make sure there is enough characters
1217
1219
  filter(thresholdFilterFn)),
1218
1220
  // Merge some observables, with a common distinctUntilChanged() pipe, and NO debounceTime
1219
1221
  merge(
1220
1222
  // Focus or click => Load all
1221
1223
  merge(this.focused, this.clicked)
1222
- .pipe(filter(_ => this.enabled && this.searchable), map(_ => this.showAllOnFocus ? '*' : this.formControl.value),
1223
- // DEBUG
1224
- tap(value => this.debug && console.debug(this.logPrefix + ' Received focused or clicked event: ', value))), merge(this.$inputItems, this._$filter)
1225
- .pipe(filter(_ => this.searchable && this.enabled), map(_ => this.formControl.value),
1224
+ .pipe(filter(_ => this.enabled && this.searchable), map(_ => this.showAllOnFocus ? '*' : this.formControl.value)
1226
1225
  // DEBUG
1227
- tap(value => this.debug && console.debug(this.logPrefix + ' Received $inputItems or filter event: ', value))))
1226
+ //,tap(value => this.debug && console.debug(this.logPrefix + ' Received focused or clicked event: ', value))
1227
+ ), merge(this.$inputItems, this._$filter)
1228
+ .pipe(filter(_ => this.searchable && this.enabled), map(_ => this.formControl.value)))
1228
1229
  .pipe(
1229
1230
  // Make sure there is enough characters
1230
1231
  filter(thresholdFilterFn),
1231
1232
  // Distinguish changes
1232
1233
  // - do NOT filter if loading, to force update after a blur event
1233
- distinctUntilChanged((v1, v2) => !this.loading && (v1 === v2 || this.equals(v1, v2)))))
1234
+ distinctUntilChanged((v1, v2) => !this.loading && (v1 === v2 || this.equals(v1, v2)))
1235
+ // DEBUG
1236
+ //,tap(value => this.debug && console.debug(this.logPrefix + ' Received update event: ', value))
1237
+ ))
1234
1238
  .pipe(
1235
1239
  // Suggest values
1236
1240
  mergeMap(value => this.suggest(value, this.filter)),
1237
1241
  // DEBUG
1238
- tap(items => this.debug && console.debug(this.logPrefix + ' Received from suggest: ', items)),
1242
+ //tap(items => this.debug && console.debug(this.logPrefix + ' Received from suggest: ', items)),
1239
1243
  // Store implicit value (will use it onBlur if not other value selected)
1240
1244
  tap(items => this.updateImplicitValue(items)));
1241
1245
  // Fetch more events
@@ -1268,9 +1272,10 @@ class MatAutocompleteField {
1268
1272
  this._subscription.add(this.blurred
1269
1273
  .pipe(
1270
1274
  // Skip if not searchable
1271
- filter(_ => this.searchable), map(_ => this.formControl.value),
1275
+ filter(_ => this.searchable), map(_ => this.formControl.value)
1272
1276
  // DEBUG
1273
- tap(value => console.debug(this.logPrefix + ' Received blurred event: ', value)))
1277
+ //,tap(value => this.debug && console.debug(this.logPrefix + ' Received blurred event: ', value)),
1278
+ )
1274
1279
  .subscribe(value => {
1275
1280
  // When leave component without object, use implicit value if :
1276
1281
  // - an explicit value
@@ -1356,7 +1361,7 @@ class MatAutocompleteField {
1356
1361
  }
1357
1362
  writeValue(value) {
1358
1363
  // DEBUG
1359
- // console.debug(this.logPrefix + ' Writing value: ', value);
1364
+ // if (this.debug) console.debug(this.logPrefix + ' Writing value: ', value);
1360
1365
  if (value !== this.formControl.value) {
1361
1366
  this.formControl.patchValue(value, { emitEvent: false });
1362
1367
  this._onChangeCallback(value);
@@ -1394,18 +1399,16 @@ class MatAutocompleteField {
1394
1399
  event.stopPropagation();
1395
1400
  event.returnValue = false;
1396
1401
  // DEBUG
1397
- if (this.debug)
1398
- console.debug(this.logPrefix + ' Cancelling focus event');
1402
+ //if (this.debug) console.debug(this.logPrefix + ' Cancelling focus event');
1399
1403
  return false;
1400
1404
  }
1401
- if (this.debug)
1402
- console.debug(this.logPrefix + ' Select input content');
1405
+ // DEBUG
1406
+ //if (this.debug) console.debug(this.logPrefix + ' Select input content');
1403
1407
  const hasContent = true; // selectInputContent(event);
1404
1408
  // If combo is empty, or if has content but should force to show panel on focus
1405
1409
  if (!hasContent || this.showPanelOnFocus || this.showAllOnFocus) {
1406
1410
  // DEBUG
1407
- if (this.debug)
1408
- console.debug(this.logPrefix + ' Emit focus event');
1411
+ //if (this.debug) console.debug(this.logPrefix + ' Emit focus event');
1409
1412
  this.focused.emit();
1410
1413
  return true;
1411
1414
  }
@@ -2605,12 +2608,10 @@ class TranslateContextPipe {
2605
2608
  constructor(translate) {
2606
2609
  this.translate = translate;
2607
2610
  }
2608
- transform(query, ...params) {
2611
+ transform(query, context, interpolateParams) {
2609
2612
  if (!query || !query.length)
2610
2613
  return query;
2611
- const suffix = params && params.length ? params[0] : '';
2612
- params = suffix && params.slice(1);
2613
- return this.translate.instant(query, suffix, params);
2614
+ return this.translate.instant(query, context, interpolateParams);
2614
2615
  }
2615
2616
  }
2616
2617
  TranslateContextPipe.decorators = [
@@ -4599,44 +4600,6 @@ class MatDate {
4599
4600
  this.markForCheck();
4600
4601
  this._onChangeCallback(dateStr);
4601
4602
  }
4602
- updatePattern(pattern) {
4603
- pattern = pattern !== 'COMMON.DATE_PATTERN' ? pattern : 'L';
4604
- if (this.displayPattern !== pattern) {
4605
- this.displayPattern = pattern;
4606
- this.dayPattern = pattern;
4607
- this.markForCheck();
4608
- }
4609
- }
4610
- onFormChange(dayValue) {
4611
- if (this.writing)
4612
- return; // Skip if call by self
4613
- this.writing = true;
4614
- // Make to remove placeholder chars
4615
- while (dayValue && dayValue.indexOf(this.placeholderChar) !== -1) {
4616
- dayValue = dayValue.replace(this.placeholderChar, '');
4617
- }
4618
- let date;
4619
- // Parse day string
4620
- date = dayValue && this.dateAdapter.parse(dayValue, this.dayPattern) || null;
4621
- // Reset time
4622
- date = date && date.utc(true).hour(0).minute(0).seconds(0).millisecond(0);
4623
- // update date picker
4624
- this._value = date && this.dateAdapter.parse(date.clone(), DATE_ISO_PATTERN);
4625
- // Get the model value
4626
- const dateStr = date && date.isValid() && this.dateAdapter.format(date, DATE_ISO_PATTERN).replace('+00:00', 'Z') || date;
4627
- //console.debug("[mat-date-time] Setting date: ", dateStr);
4628
- this.formControl.patchValue(dateStr, { emitEvent: false });
4629
- //this.formControl.updateValueAndValidity();
4630
- this.writing = false;
4631
- this.markForCheck();
4632
- this._onChangeCallback(dateStr);
4633
- }
4634
- checkIfTouched() {
4635
- if (this.dayControl.touched) {
4636
- this.markForCheck();
4637
- this._onTouchedCallback();
4638
- }
4639
- }
4640
4603
  openDatePickerIfMobile(event, datePicker) {
4641
4604
  return __awaiter(this, void 0, void 0, function* () {
4642
4605
  if (!this.mobile || event.defaultPrevented)
@@ -4676,7 +4639,45 @@ class MatDate {
4676
4639
  }
4677
4640
  });
4678
4641
  }
4679
- /* -- protected method -- */
4642
+ /* -- private method -- */
4643
+ updatePattern(pattern) {
4644
+ pattern = pattern !== 'COMMON.DATE_PATTERN' ? pattern : 'L';
4645
+ if (this.displayPattern !== pattern) {
4646
+ this.displayPattern = pattern;
4647
+ this.dayPattern = pattern;
4648
+ this.markForCheck();
4649
+ }
4650
+ }
4651
+ onFormChange(dayValue) {
4652
+ if (this.writing)
4653
+ return; // Skip if call by self
4654
+ this.writing = true;
4655
+ // Make to remove placeholder chars
4656
+ while (dayValue && dayValue.indexOf(this.placeholderChar) !== -1) {
4657
+ dayValue = dayValue.replace(this.placeholderChar, '');
4658
+ }
4659
+ let date;
4660
+ // Parse day string
4661
+ date = dayValue && this.dateAdapter.parse(dayValue, this.dayPattern) || null;
4662
+ // Reset time
4663
+ date = date && date.utc(true).hour(0).minute(0).seconds(0).millisecond(0);
4664
+ // update date picker
4665
+ this._value = date && this.dateAdapter.parse(date.clone(), DATE_ISO_PATTERN);
4666
+ // Get the model value
4667
+ const dateStr = date && date.isValid() && this.dateAdapter.format(date, DATE_ISO_PATTERN).replace('+00:00', 'Z') || date;
4668
+ //console.debug("[mat-date-time] Setting date: ", dateStr);
4669
+ this.formControl.patchValue(dateStr, { emitEvent: false });
4670
+ //this.formControl.updateValueAndValidity();
4671
+ this.writing = false;
4672
+ this.markForCheck();
4673
+ this._onChangeCallback(dateStr);
4674
+ }
4675
+ checkIfTouched() {
4676
+ if (this.dayControl.touched) {
4677
+ this.markForCheck();
4678
+ this._onTouchedCallback();
4679
+ }
4680
+ }
4680
4681
  waitKeyboardHide(waitKeyboardDelay) {
4681
4682
  return __awaiter(this, void 0, void 0, function* () {
4682
4683
  if (!this.keyboard || !this.keyboard.isVisible)
@@ -4801,7 +4802,7 @@ class MatDateTime {
4801
4802
  }
4802
4803
  ngOnInit() {
4803
4804
  this.mobile = isNil(this.mobile) ? this.platform.is('mobile') : this.mobile;
4804
- this.waitHideKeyboardDelay = this.mobile && KEYBOARD_HIDE_DELAY_MS || 0;
4805
+ this.keyboardHideDelay = this.mobile && KEYBOARD_HIDE_DELAY_MS || 0;
4805
4806
  this.formControl = this.formControl || this.formControlName && this.formGroupDir && this.formGroupDir.form.get(this.formControlName);
4806
4807
  if (!this.formControl)
4807
4808
  throw new Error('Missing mandatory attribute \'formControl\' or \'formControlName\' in <mat-date-time-field>.');
@@ -4925,10 +4926,6 @@ class MatDateTime {
4925
4926
  this.disabling = false;
4926
4927
  this.markForCheck();
4927
4928
  }
4928
- updatePattern(patterns) {
4929
- this.displayPattern = (patterns['COMMON.DATE_TIME_PATTERN'] !== 'COMMON.DATE_TIME_PATTERN' ? patterns['COMMON.DATE_TIME_PATTERN'] : 'L LT');
4930
- this.dayPattern = (patterns['COMMON.DATE_PATTERN'] !== 'COMMON.DATE_PATTERN' ? patterns['COMMON.DATE_PATTERN'] : 'L');
4931
- }
4932
4929
  onDatePickerChange(event) {
4933
4930
  // Make sure event is valid
4934
4931
  if (!event || (event.value !== null && !isMoment(event.value))) {
@@ -4966,7 +4963,7 @@ class MatDateTime {
4966
4963
  return;
4967
4964
  this.preventEvent(event);
4968
4965
  // Make sure the keyboard is closed
4969
- yield this.hideKeyboard(false);
4966
+ yield this.waitKeyboardHide(false);
4970
4967
  // Open the picker
4971
4968
  this.openDatePicker(null, datePicker);
4972
4969
  });
@@ -4987,7 +4984,7 @@ class MatDateTime {
4987
4984
  return;
4988
4985
  this.preventEvent(event);
4989
4986
  // Make sure the keyboard is closed
4990
- yield this.hideKeyboard(true);
4987
+ yield this.waitKeyboardHide(true);
4991
4988
  // Open the picker
4992
4989
  this.openTimePicker(null);
4993
4990
  });
@@ -5006,12 +5003,6 @@ class MatDateTime {
5006
5003
  event.stopPropagation();
5007
5004
  event.returnValue = false;
5008
5005
  }
5009
- checkIfTouched() {
5010
- if (this.dateFormControl.touched || this.timeFormControl.touched) {
5011
- this._onTouchedCallback();
5012
- this.markForCheck();
5013
- }
5014
- }
5015
5006
  focus() {
5016
5007
  if (!this.matInputs.length)
5017
5008
  return;
@@ -5027,7 +5018,31 @@ class MatDateTime {
5027
5018
  this.markAsTouched();
5028
5019
  this.markAsDirty();
5029
5020
  }
5030
- /* -- protected method -- */
5021
+ /* -- private method -- */
5022
+ updatePattern(patterns) {
5023
+ this.displayPattern = (patterns['COMMON.DATE_TIME_PATTERN'] !== 'COMMON.DATE_TIME_PATTERN' ? patterns['COMMON.DATE_TIME_PATTERN'] : 'L LT');
5024
+ this.dayPattern = (patterns['COMMON.DATE_PATTERN'] !== 'COMMON.DATE_PATTERN' ? patterns['COMMON.DATE_PATTERN'] : 'L');
5025
+ }
5026
+ checkIfTouched() {
5027
+ if (this.dateFormControl.touched || this.timeFormControl.touched) {
5028
+ this._onTouchedCallback();
5029
+ this.markForCheck();
5030
+ }
5031
+ }
5032
+ waitKeyboardHide(waitKeyboardDelay) {
5033
+ return __awaiter(this, void 0, void 0, function* () {
5034
+ if (!this.keyboard || !this.keyboard.isVisible)
5035
+ return; // ok, already hidden (or not accessible)
5036
+ // Force keyboard to be hide
5037
+ this.keyboard.hide();
5038
+ // Wait hide occur
5039
+ yield this.keyboard.onKeyboardHide().pipe(first()).toPromise();
5040
+ // Wait an additional delay if need (depending on the OS)
5041
+ if (this.keyboardHideDelay > 0 && waitKeyboardDelay) {
5042
+ yield sleep(this.keyboardHideDelay);
5043
+ }
5044
+ });
5045
+ }
5031
5046
  emitChange(value) {
5032
5047
  // Get the model value
5033
5048
  const dateStr = toDateISOString(value) || null;
@@ -5040,20 +5055,6 @@ class MatDateTime {
5040
5055
  this.checkIfTouched();
5041
5056
  }
5042
5057
  }
5043
- hideKeyboard(waitIsHidden) {
5044
- return __awaiter(this, void 0, void 0, function* () {
5045
- if (!this.keyboard.isVisible)
5046
- return; // ok, already hidden
5047
- // Force keyboard to be hide
5048
- this.keyboard.hide();
5049
- // Wait hide occur
5050
- yield this.keyboard.onKeyboardHide().pipe(first()).toPromise();
5051
- // Wait an additional delay if need (depending on the OS)
5052
- if (this.waitHideKeyboardDelay > 0 && waitIsHidden) {
5053
- yield sleep(this.waitHideKeyboardDelay);
5054
- }
5055
- });
5056
- }
5057
5058
  updateTabIndex() {
5058
5059
  if (isNil(this._tabindex) || this._tabindex === -1)
5059
5060
  return; // skip
@@ -5886,7 +5887,7 @@ class MatBooleanField {
5886
5887
  MatBooleanField.decorators = [
5887
5888
  { type: Component, args: [{
5888
5889
  selector: 'mat-boolean-field',
5889
- template: "<mat-form-field *ngIf=\"readonly; else writable\"\n [floatLabel]=\"floatLabel\"\n class=\"mat-form-field-disabled {{classList}}\">\n <div matPrefix>\n <ng-container *ngTemplateOutlet=\"matPrefixTemplate\"></ng-container>\n </div>\n <input matInput hidden type=\"text\" readonly\n [placeholder]=\"placeholder\"\n [formControl]=\"formControl\">\n <ion-text>{{(formControl.value == null && 'COMMON.EMPTY_OPTION' || (formControl.value === true && yesLabel) || noLabel) | translate }}</ion-text>\n <div matSuffix>\n <ng-container *ngTemplateOutlet=\"matSuffixTemplate\"></ng-container>\n </div>\n</mat-form-field>\n\n<ng-template #writable>\n <ng-container [ngSwitch]=\"style\">\n\n <!-- Radio -->\n <mat-form-field *ngSwitchCase=\"'radio'\"\n [floatLabel]=\"showRadio && (!floatLabel || floatLabel === 'auto') ? 'always': floatLabel\"\n class=\"mat-boolean-field mat-boolean-field-radio {{classList}}\">\n <mat-label *ngIf=\"placeholder && floatLabel!=='never'\">\n {{placeholder}}\n <span [hidden]=\"showRadio\">({{yesLabel|translate}}/{{'COMMON.NO'|translate}})</span>\n </mat-label>\n <div matPrefix>\n <ng-container *ngTemplateOutlet=\"matPrefixTemplate\"></ng-container>\n </div>\n <input matInput #fakeInput type=\"text\" readonly=\"true\"\n [formControl]=\"formControl\"\n (focus)=\"_onFocusFakeInput($event)\"\n [required]=\"required\"\n [class.cdk-visually-hidden]=\"showRadio\"\n [tabindex]=\"tabindex\">\n\n <!-- radio button -->\n <mat-radio-group [hidden]=\"!showRadio\"\n [formControl]=\"formControl\"\n (change)=\"onRadioValueChanged($event)\">\n <mat-radio-button #yesButton [value]=\"true\">\n <span>{{yesLabel|translate}}</span>\n </mat-radio-button>&nbsp;\n <mat-radio-button #noButton [value]=\"false\">\n <span>{{noLabel|translate}}</span>\n </mat-radio-button>\n </mat-radio-group>\n\n <mat-error *ngIf=\"formControl.hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n\n <div matSuffix>\n <ng-container *ngTemplateOutlet=\"matSuffixTemplate\"></ng-container>\n </div>\n </mat-form-field>\n\n <!-- Checkbox -->\n <mat-form-field *ngSwitchCase=\"'checkbox'\"\n [floatLabel]=\"floatLabel\"\n class=\"mat-boolean-field mat-boolean-field-checkbox {{classList}}\">\n <mat-label *ngIf=\"placeholder && !showRadio\">\n {{placeholder}}\n </mat-label>\n <div matPrefix>\n <ng-container *ngTemplateOutlet=\"matPrefixTemplate\"></ng-container>\n </div>\n <input matInput #matInput\n [formControl]=\"formControl\"\n (focus)=\"_onFocusFakeInput($event)\"\n [required]=\"required\"\n [class.cdk-visually-hidden]=\"showRadio\"\n [tabindex]=\"tabindex\">\n\n <ion-label>&nbsp;</ion-label>\n\n <!-- checkbox, when compact -->\n <mat-checkbox #checkboxButton\n [formControl]=\"formControl\"\n (change)=\"onCheckboxValueChanged($event)\"\n [indeterminate]=\"value===undefined\"\n [hidden]=\"!showRadio\"\n [tabindex]=\"tabindex\">\n </mat-checkbox>\n\n <mat-error *ngIf=\"formControl.hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n\n <div matSuffix>\n <ng-container *ngTemplateOutlet=\"matSuffixTemplate\"></ng-container>\n </div>\n </mat-form-field>\n\n <!-- Buttons -->\n <mat-form-field *ngSwitchCase=\"'button'\"\n [floatLabel]=\"floatLabel === 'never' ? 'never' : 'always'\"\n class=\"mat-boolean-field mat-boolean-field-button {{classList}}\">\n <div matPrefix>\n <ng-container *ngTemplateOutlet=\"matPrefixTemplate\"></ng-container>\n </div>\n <input matInput type=\"text\" hidden\n [formControl]=\"formControl\"\n [placeholder]=\"placeholder\"\n [required]=\"required\">\n <div class=\"mat-form-field-buttons\"\n [style.--buttons-col-count]=\"buttonsColCount\"\n *ngIf=\"!formControl.disabled; else disabledLabel\">\n <!-- yes -->\n <ion-button class=\"mat-form-field-button\"\n [tabindex]=\"_tabindex\"\n (click)=\"writeValue(true, $event)\"\n (keyup.enter)=\"writeValue(true, $event)\"\n [color]=\"_value == null ? 'tertiary' : (_value === true) ? 'accent' : 'light'\">\n <ion-icon *ngIf=\"showButtonIcons && yesIcon; let icon\" slot=\"start\" [name]=\"icon\"></ion-icon>\n {{yesLabel|translate}}\n </ion-button>\n\n <!-- No button -->\n <ion-button class=\"mat-form-field-button\"\n [tabindex]=\"_tabindex !== undefined ? (_tabindex + 1) : undefined\"\n (click)=\"writeValue(false, $event)\"\n (keyup.enter)=\"writeValue(false, $event)\"\n [color]=\"_value == null ? 'tertiary' : (_value === false) ? 'accent' : 'light'\">\n <ion-icon *ngIf=\"showButtonIcons && noIcon; let icon\" slot=\"start\" [name]=\"icon\"></ion-icon>\n {{noLabel|translate}}\n </ion-button>\n </div>\n <ng-template #disabledLabel>\n <ion-label><i translate>COMMON.EMPTY_OPTION</i></ion-label>\n </ng-template>\n\n <mat-error *ngIf=\"formControl.hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n <div matSuffix>\n <ng-container *ngTemplateOutlet=\"matSuffixTemplate\"></ng-container>\n </div>\n\n </mat-form-field>\n </ng-container>\n\n <div class=\"cdk-visually-hidden\">\n <div #suffix><ng-content select=\"[matSuffix]\"></ng-content></div>\n </div>\n\n</ng-template>\n\n\n<ng-template #matPrefixTemplate>\n <ng-content select=\"[matPrefix]\"></ng-content>\n</ng-template>\n<ng-template #matSuffixTemplate>\n <ng-content select=\"[matSuffix]\"></ng-content>\n</ng-template>\n",
5890
+ template: "<mat-form-field *ngIf=\"readonly; else writable\"\n [floatLabel]=\"floatLabel\"\n class=\"mat-form-field-disabled {{classList}}\">\n <div matPrefix>\n <ng-container *ngTemplateOutlet=\"matPrefixTemplate\"></ng-container>\n </div>\n <input matInput hidden type=\"text\" readonly\n [placeholder]=\"placeholder\"\n [formControl]=\"formControl\">\n <ion-text>{{(formControl.value == null && 'COMMON.EMPTY_OPTION' || (formControl.value === true && yesLabel) || noLabel) | translate }}</ion-text>\n <div matSuffix>\n <ng-container *ngTemplateOutlet=\"matSuffixTemplate\"></ng-container>\n </div>\n</mat-form-field>\n\n<ng-template #writable>\n <ng-container [ngSwitch]=\"style\">\n\n <!-- Radio -->\n <mat-form-field *ngSwitchCase=\"'radio'\"\n [floatLabel]=\"showRadio && (!floatLabel || floatLabel === 'auto') ? 'always': floatLabel\"\n class=\"mat-boolean-field mat-boolean-field-radio {{classList}}\">\n <mat-label *ngIf=\"placeholder && floatLabel!=='never'\">\n {{placeholder}}\n <span [hidden]=\"showRadio\">({{yesLabel|translate}}/{{'COMMON.NO'|translate}})</span>\n </mat-label>\n <div matPrefix>\n <ng-container *ngTemplateOutlet=\"matPrefixTemplate\"></ng-container>\n </div>\n <input matInput #fakeInput type=\"text\" readonly=\"true\"\n [formControl]=\"formControl\"\n (focus)=\"_onFocusFakeInput($event)\"\n [required]=\"required\"\n [class.cdk-visually-hidden]=\"showRadio\"\n [tabindex]=\"tabindex\">\n\n <!-- radio button -->\n <mat-radio-group [hidden]=\"!showRadio\"\n [formControl]=\"formControl\"\n (change)=\"onRadioValueChanged($event)\">\n <mat-radio-button #yesButton [value]=\"true\">\n <span>{{yesLabel|translate}}</span>\n </mat-radio-button>&nbsp;\n <mat-radio-button #noButton [value]=\"false\">\n <span>{{noLabel|translate}}</span>\n </mat-radio-button>\n </mat-radio-group>\n\n <mat-error *ngIf=\"formControl.hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n\n <div matSuffix>\n <ng-container *ngTemplateOutlet=\"matSuffixTemplate\"></ng-container>\n </div>\n </mat-form-field>\n\n <!-- Checkbox -->\n <mat-form-field *ngSwitchCase=\"'checkbox'\"\n [floatLabel]=\"floatLabel\"\n class=\"mat-boolean-field mat-boolean-field-checkbox {{classList}}\">\n <mat-label *ngIf=\"placeholder && !showRadio\">\n {{placeholder}}\n </mat-label>\n <div matPrefix>\n <ng-container *ngTemplateOutlet=\"matPrefixTemplate\"></ng-container>\n </div>\n <input matInput #matInput\n [formControl]=\"formControl\"\n (focus)=\"_onFocusFakeInput($event)\"\n [required]=\"required\"\n [class.cdk-visually-hidden]=\"showRadio\"\n [tabindex]=\"tabindex\">\n\n <ion-label>&nbsp;</ion-label>\n\n <!-- checkbox, when compact -->\n <mat-checkbox #checkboxButton\n [formControl]=\"formControl\"\n (change)=\"onCheckboxValueChanged($event)\"\n [indeterminate]=\"value===undefined\"\n [hidden]=\"!showRadio\"\n [tabindex]=\"tabindex\">\n </mat-checkbox>\n\n <mat-error *ngIf=\"formControl.hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n\n <div matSuffix>\n <ng-container *ngTemplateOutlet=\"matSuffixTemplate\"></ng-container>\n </div>\n </mat-form-field>\n\n <!-- Buttons -->\n <mat-form-field *ngSwitchCase=\"'button'\"\n [floatLabel]=\"floatLabel === 'never' ? 'never' : 'always'\"\n class=\"mat-boolean-field mat-boolean-field-button {{classList}}\">\n <div matPrefix>\n <ng-container *ngTemplateOutlet=\"matPrefixTemplate\"></ng-container>\n </div>\n <input matInput type=\"text\" hidden\n [formControl]=\"formControl\"\n [placeholder]=\"placeholder\"\n [required]=\"required\">\n <div class=\"mat-form-field-buttons\"\n [style.--buttons-col-count]=\"buttonsColCount\"\n *ngIf=\"!formControl.disabled; else disabledLabel\">\n <!-- yes -->\n <ion-button class=\"mat-form-field-button\"\n [tabindex]=\"_tabindex\"\n (click)=\"writeValue(true, $event)\"\n (keyup.enter)=\"writeValue(true, $event)\"\n [color]=\"_value == null ? 'tertiary' : (_value === true) ? 'accent' : 'light'\">\n <ion-icon *ngIf=\"showButtonIcons && yesIcon; let icon\" slot=\"start\" [name]=\"icon\"></ion-icon>\n {{yesLabel|translate}}\n </ion-button>\n\n <!-- No button -->\n <ion-button class=\"mat-form-field-button\"\n [tabindex]=\"_tabindex !== undefined ? (_tabindex + 1) : undefined\"\n (click)=\"writeValue(false, $event)\"\n (keyup.enter)=\"writeValue(false, $event)\"\n [color]=\"_value == null ? 'tertiary' : (_value === false) ? 'accent' : 'light'\">\n <ion-icon *ngIf=\"showButtonIcons && noIcon; let icon\" slot=\"start\" [name]=\"icon\"></ion-icon>\n {{noLabel|translate}}\n </ion-button>\n </div>\n <ng-template #disabledLabel>\n <ion-label><i translate>COMMON.EMPTY_OPTION</i></ion-label>\n </ng-template>\n\n <mat-error *ngIf=\"formControl.hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n <div matSuffix>\n <ng-container *ngTemplateOutlet=\"matSuffixTemplate\"></ng-container>\n </div>\n\n </mat-form-field>\n </ng-container>\n\n</ng-template>\n\n\n<ng-template #matPrefixTemplate>\n <ng-content select=\"[matPrefix]\"></ng-content>\n</ng-template>\n<ng-template #matSuffixTemplate>\n <ng-content select=\"[matSuffix]\"></ng-content>\n</ng-template>\n",
5890
5891
  providers: [
5891
5892
  DEFAULT_VALUE_ACCESSOR$1
5892
5893
  ],
@@ -5924,8 +5925,7 @@ MatBooleanField.propDecorators = {
5924
5925
  yesButton: [{ type: ViewChild, args: ['yesButton',] }],
5925
5926
  noButton: [{ type: ViewChild, args: ['noButton',] }],
5926
5927
  checkboxButton: [{ type: ViewChild, args: ['checkboxButton',] }],
5927
- fakeInput: [{ type: ViewChild, args: ['fakeInput',] }],
5928
- suffixDiv: [{ type: ViewChild, args: ['suffix', { static: false },] }]
5928
+ fakeInput: [{ type: ViewChild, args: ['fakeInput',] }]
5929
5929
  };
5930
5930
 
5931
5931
  class SharedMatBooleanModule {
@@ -7004,7 +7004,7 @@ class MatChipsField {
7004
7004
  // Wait a debounce time
7005
7005
  debounceTime(this.debounceTime)
7006
7006
  // DEBUG
7007
- //tap((value) => console.debug(this.logPrefix + ' Search text changes:', value))
7007
+ //,tap((value) => this.debug && console.debug(this.logPrefix + ' Search text changes:', value))
7008
7008
  ),
7009
7009
  // Object set: use it (no distinctUntilChanged() pipe need)
7010
7010
  this.inputControl.valueChanges
@@ -7020,18 +7020,25 @@ class MatChipsField {
7020
7020
  merge(
7021
7021
  // Focus or click => Load all
7022
7022
  merge(this.focused, this.clicked)
7023
- .pipe(filter(_ => this.enabled), map((_) => this.showAllOnFocus ? '*' : this.inputControl.value)), merge(this.$inputItems, this._$filter)
7023
+ .pipe(filter(_ => this.enabled), map((_) => this.showAllOnFocus ? '*' : this.inputControl.value)
7024
+ // DEBUG
7025
+ //,tap(value => this.debug && console.debug(this.logPrefix + ' Received focused or clicked event: ', value))
7026
+ ), merge(this.$inputItems, this._$filter)
7024
7027
  .pipe(filter(_ => this.enabled), map(_ => this.inputControl.value)))
7025
7028
  .pipe(
7026
7029
  // Make sure there is enough characters
7027
7030
  filter(thresholdFilterFn),
7028
7031
  // Distinguish changes
7029
- distinctUntilChanged()))
7032
+ // - do NOT filter if loading, to force update after a blur event
7033
+ distinctUntilChanged((v1, v2) => !this.loading && (v1 === v2 || this.equals(v1, v2)))
7034
+ // DEBUG
7035
+ //,tap(value => this.debug && console.debug(this.logPrefix + ' Received update event: ', value))
7036
+ ))
7030
7037
  .pipe(
7031
7038
  // Suggest values
7032
7039
  mergeMap(value => this.suggest(value, this.filter)),
7033
7040
  // DEBUG
7034
- //tap(items => console.debug(this.logPrefix + ' Received from suggest: ', items)),
7041
+ //tap(items => this.debug && console.debug(this.logPrefix + ' Received from suggest: ', items)),
7035
7042
  // Store implicit value (will use it onBlur if not other value selected)
7036
7043
  tap(items => this.updateImplicitValue(items)));
7037
7044
  // Fetch more events
@@ -7052,7 +7059,10 @@ class MatChipsField {
7052
7059
  .subscribe(items => this.$filteredItems.next(items)));
7053
7060
  // Applying implicit value, on blur
7054
7061
  this._subscription.add(this.blurred
7055
- .pipe(map(_ => this.formControl.value))
7062
+ .pipe(map(_ => this.formControl.value)
7063
+ // DEBUG
7064
+ //,tap(value => this.debug && console.debug(this.logPrefix + ' Received blurred event: ', value)),
7065
+ )
7056
7066
  .subscribe(value => {
7057
7067
  // When leave component without object, use implicit value if :
7058
7068
  // - an explicit value
@@ -7164,6 +7174,8 @@ class MatChipsField {
7164
7174
  this._reload$.next(value || '*');
7165
7175
  }
7166
7176
  writeValue(value) {
7177
+ // DEBUG
7178
+ // if (this.debug) console.debug(this.logPrefix + ' Writing value: ', value);
7167
7179
  if (value && !Array.isArray(value)) {
7168
7180
  value = [value];
7169
7181
  }
@@ -7415,9 +7427,9 @@ MatChipsField.propDecorators = {
7415
7427
  showLoadingSpinner: [{ type: Input }],
7416
7428
  chipColor: [{ type: Input }],
7417
7429
  debug: [{ type: Input }],
7418
- clicked: [{ type: Output }],
7419
- blurred: [{ type: Output }],
7420
- focused: [{ type: Output }],
7430
+ clicked: [{ type: Output, args: ['click',] }],
7431
+ blurred: [{ type: Output, args: ['blur',] }],
7432
+ focused: [{ type: Output, args: ['focus',] }],
7421
7433
  dropButtonClick: [{ type: Output }],
7422
7434
  keydownEscape: [{ type: Output, args: ['keydown.escape',] }],
7423
7435
  keyupEnter: [{ type: Output, args: ['keyup.enter',] }],
@@ -17511,7 +17523,7 @@ class AuthForm extends AppForm {
17511
17523
  this.form.get('username').setValidators(Validators.required);
17512
17524
  }
17513
17525
  // Enable/disable registration link
17514
- this.canRegister = config.getProperty(CORE_CONFIG_OPTIONS.REGISTRATION_ENABLE);
17526
+ this.canRegister = config.getPropertyAsBoolean(CORE_CONFIG_OPTIONS.REGISTRATION_ENABLE);
17515
17527
  this.markForCheck();
17516
17528
  }));
17517
17529
  // For DEV only
@@ -21381,13 +21393,6 @@ class AppTable {
21381
21393
  markAsLoaded(opts) {
21382
21394
  this.setLoading(false, opts);
21383
21395
  }
21384
- markRowAsDirty(row, opts) {
21385
- var _a;
21386
- row = row || this.editedRow;
21387
- if (row)
21388
- (_a = row.validator) === null || _a === void 0 ? void 0 : _a.markAsDirty(opts);
21389
- this.markAsDirty(opts);
21390
- }
21391
21396
  markAsReady(opts) {
21392
21397
  if (this.readySubject.value !== true) {
21393
21398
  this.readySubject.next(true);
@@ -22508,6 +22513,13 @@ class AppTable {
22508
22513
  equals(d1, d2) {
22509
22514
  return EntityUtils.equals(d1, d2, 'id');
22510
22515
  }
22516
+ markRowAsDirty(row, opts) {
22517
+ var _a;
22518
+ row = row || this.editedRow;
22519
+ if (row)
22520
+ (_a = row.validator) === null || _a === void 0 ? void 0 : _a.markAsDirty(opts);
22521
+ this.markAsDirty(opts);
22522
+ }
22511
22523
  /* -- private method -- */
22512
22524
  setLoading(value, opts) {
22513
22525
  if (this.loadingSubject.value !== value) {