@quadrel-enterprise-ui/framework 20.8.0 → 20.9.1-beta.137.1
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/fesm2022/quadrel-enterprise-ui-framework-dialog-confirm.module-BQLiEzSo.mjs +42 -0
- package/fesm2022/quadrel-enterprise-ui-framework-dialog-confirm.module-BQLiEzSo.mjs.map +1 -0
- package/fesm2022/quadrel-enterprise-ui-framework.mjs +353 -249
- package/fesm2022/quadrel-enterprise-ui-framework.mjs.map +1 -1
- package/index.d.ts +186 -36
- package/package.json +1 -1
- package/src/assets/i18n/de.json +2 -0
- package/src/assets/i18n/en.json +2 -0
- package/src/assets/i18n/fr.json +2 -0
- package/src/assets/i18n/it.json +2 -0
|
@@ -1146,18 +1146,43 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
1146
1146
|
}]
|
|
1147
1147
|
}] });
|
|
1148
1148
|
|
|
1149
|
+
const GENERIC_DEFAULTS = {
|
|
1150
|
+
title: { i18n: 'i18n.qd.dialog.confirm.title' },
|
|
1151
|
+
confirm: { i18n: 'i18n.qd.dialog.confirm.proceed' },
|
|
1152
|
+
cancel: { i18n: 'i18n.qd.dialog.action.cancel' }
|
|
1153
|
+
};
|
|
1154
|
+
const CANCEL_DEFAULTS = {
|
|
1155
|
+
title: { i18n: 'i18n.qd.page.cancel.confirmation.dialog.title' },
|
|
1156
|
+
message: { i18n: 'i18n.qd.page.cancel.confirmation.dialog.message' },
|
|
1157
|
+
confirm: { i18n: 'i18n.qd.page.cancel.confirmation.dialog.proceed' },
|
|
1158
|
+
cancel: { i18n: 'i18n.qd.page.cancel.confirmation.dialog.close' }
|
|
1159
|
+
};
|
|
1149
1160
|
class QdConfirmationDialogOpenerService {
|
|
1150
1161
|
dialog = inject(Dialog);
|
|
1151
|
-
|
|
1152
|
-
|
|
1162
|
+
showConfirmDialog(config, testId = 'dialog-confirm') {
|
|
1163
|
+
const resolved = {
|
|
1164
|
+
title: config.title ?? GENERIC_DEFAULTS.title,
|
|
1165
|
+
message: config.message,
|
|
1166
|
+
confirm: config.confirm ?? GENERIC_DEFAULTS.confirm,
|
|
1167
|
+
cancel: config.cancel ?? GENERIC_DEFAULTS.cancel
|
|
1168
|
+
};
|
|
1169
|
+
return from(import('./quadrel-enterprise-ui-framework-dialog-confirm.module-BQLiEzSo.mjs').then(m => m.QdDialogConfirmComponent)).pipe(switchMap(component => {
|
|
1153
1170
|
const dialogRef = this.open(component, {
|
|
1154
|
-
title:
|
|
1171
|
+
title: resolved.title,
|
|
1155
1172
|
dialogSize: QdDialogSize.Small,
|
|
1156
|
-
data:
|
|
1173
|
+
data: { ...resolved, testId }
|
|
1157
1174
|
});
|
|
1158
1175
|
return dialogRef.closed.pipe(map$1(result => !!result));
|
|
1159
1176
|
}));
|
|
1160
1177
|
}
|
|
1178
|
+
showDiscardConfirmDialog(message, testId = 'cancel-confirmation') {
|
|
1179
|
+
return this.showConfirmDialog({
|
|
1180
|
+
title: CANCEL_DEFAULTS.title,
|
|
1181
|
+
message: message ?? CANCEL_DEFAULTS.message,
|
|
1182
|
+
confirm: CANCEL_DEFAULTS.confirm,
|
|
1183
|
+
cancel: CANCEL_DEFAULTS.cancel
|
|
1184
|
+
}, testId);
|
|
1185
|
+
}
|
|
1161
1186
|
open(component, config) {
|
|
1162
1187
|
config.panelClass = 'qd-custom-panel';
|
|
1163
1188
|
config.width = config.dialogSize || QdDialogSize.Default;
|
|
@@ -1470,7 +1495,7 @@ class QdDialogComponent {
|
|
|
1470
1495
|
}
|
|
1471
1496
|
confirmAndClose() {
|
|
1472
1497
|
this.dialog
|
|
1473
|
-
.
|
|
1498
|
+
.showDiscardConfirmDialog(this.config.cancel?.confirmationMessage, 'dialog-cancel-confirmation')
|
|
1474
1499
|
.pipe(take(1))
|
|
1475
1500
|
.subscribe(confirmed => {
|
|
1476
1501
|
if (!confirmed)
|
|
@@ -9186,7 +9211,7 @@ class QdDateAdapter {
|
|
|
9186
9211
|
static parseToDate(formatted) {
|
|
9187
9212
|
if (!formatted)
|
|
9188
9213
|
return new Date();
|
|
9189
|
-
return moment(formatted, '
|
|
9214
|
+
return moment(formatted, 'DD.MM.YYYY').toDate();
|
|
9190
9215
|
}
|
|
9191
9216
|
/**
|
|
9192
9217
|
* Converts a localized Swiss date and time string into a JavaScript Date object.
|
|
@@ -9206,9 +9231,9 @@ class QdDateAdapter {
|
|
|
9206
9231
|
return new Date(new Date().setHours(hours, minutes, 0, 0));
|
|
9207
9232
|
}
|
|
9208
9233
|
else if (date && !time) {
|
|
9209
|
-
return moment(date, '
|
|
9234
|
+
return moment(date, 'DD.MM.YYYY').toDate();
|
|
9210
9235
|
}
|
|
9211
|
-
let format = '
|
|
9236
|
+
let format = 'DD.MM.YYYY ';
|
|
9212
9237
|
switch (time.length) {
|
|
9213
9238
|
case 8:
|
|
9214
9239
|
format = format + 'HH:mm:ss';
|
|
@@ -9217,14 +9242,14 @@ class QdDateAdapter {
|
|
|
9217
9242
|
default:
|
|
9218
9243
|
format = format + 'HH:mm';
|
|
9219
9244
|
}
|
|
9220
|
-
return moment(`${date} ${time}`, format
|
|
9245
|
+
return moment(`${date} ${time}`, format).toDate();
|
|
9221
9246
|
}
|
|
9222
9247
|
/**
|
|
9223
9248
|
* Converts a localized date string into a Moment.js object.
|
|
9224
9249
|
* If the input is null or undefined, it returns undefined.
|
|
9225
9250
|
*/
|
|
9226
9251
|
static parseToMoment(formatted) {
|
|
9227
|
-
return formatted ? moment(formatted, '
|
|
9252
|
+
return formatted ? moment(formatted, 'DD.MM.YYYY').locale('de') : undefined;
|
|
9228
9253
|
}
|
|
9229
9254
|
/**
|
|
9230
9255
|
* Formats a Moment.js object into a localized date string.
|
|
@@ -9233,7 +9258,7 @@ class QdDateAdapter {
|
|
|
9233
9258
|
static formatToLocalizedDateString(momentObj) {
|
|
9234
9259
|
if (!momentObj)
|
|
9235
9260
|
return '';
|
|
9236
|
-
return momentObj.
|
|
9261
|
+
return momentObj.format('DD.MM.YYYY');
|
|
9237
9262
|
}
|
|
9238
9263
|
/**
|
|
9239
9264
|
* Formats a JavaScript Date object into a localized date string.
|
|
@@ -9258,7 +9283,7 @@ class QdDateAdapter {
|
|
|
9258
9283
|
* Returns true if the date is valid, otherwise false.
|
|
9259
9284
|
*/
|
|
9260
9285
|
static isLocalizedDateStringValid(formatted) {
|
|
9261
|
-
return moment(formatted, '
|
|
9286
|
+
return moment(formatted, 'DD.MM.YYYY', true).isValid();
|
|
9262
9287
|
}
|
|
9263
9288
|
/**
|
|
9264
9289
|
* Validates if a date-time string matches the Swiss `DD.MM.YYYY HH:mm:ss` format.
|
|
@@ -9314,9 +9339,8 @@ class QdCalendarComponent {
|
|
|
9314
9339
|
this.setWeekdays();
|
|
9315
9340
|
this.todayDate = moment();
|
|
9316
9341
|
this.months = moment.months();
|
|
9317
|
-
|
|
9318
|
-
|
|
9319
|
-
: this.todayDate).year());
|
|
9342
|
+
const parsedSelected = QdDateAdapter.parseToMoment(this.selectedDate);
|
|
9343
|
+
this.years = this.getYears((parsedSelected?.isValid() ? parsedSelected : this.todayDate).year());
|
|
9320
9344
|
this.setCurrentDate();
|
|
9321
9345
|
this.generateCalendar(this.currentDate);
|
|
9322
9346
|
}
|
|
@@ -9406,9 +9430,8 @@ class QdCalendarComponent {
|
|
|
9406
9430
|
return this.todayDate.isSame(momentObj, 'day');
|
|
9407
9431
|
}
|
|
9408
9432
|
setCurrentDate() {
|
|
9409
|
-
const
|
|
9410
|
-
|
|
9411
|
-
: this.todayDate);
|
|
9433
|
+
const parsedDate = QdDateAdapter.parseToMoment(this.selectedDate);
|
|
9434
|
+
const currentDate = (this.currentDate = parsedDate?.isValid() ? parsedDate : this.todayDate);
|
|
9412
9435
|
this.currentDate = currentDate;
|
|
9413
9436
|
this.selectedDate = QdDateAdapter.formatToLocalizedDateString(currentDate);
|
|
9414
9437
|
}
|
|
@@ -10970,6 +10993,7 @@ class QdInputComponent {
|
|
|
10970
10993
|
hasAutofocus;
|
|
10971
10994
|
hasOptions = false;
|
|
10972
10995
|
_value = { value: '' };
|
|
10996
|
+
_displayValue = '';
|
|
10973
10997
|
control;
|
|
10974
10998
|
_optionsResolver;
|
|
10975
10999
|
_subs = new Subscription();
|
|
@@ -11039,6 +11063,7 @@ class QdInputComponent {
|
|
|
11039
11063
|
}
|
|
11040
11064
|
writeValue(value) {
|
|
11041
11065
|
this._value = getValueWithUnit(value, this.config);
|
|
11066
|
+
this._displayValue = String(this._value.value ?? '');
|
|
11042
11067
|
}
|
|
11043
11068
|
setDisabledState(disabled) {
|
|
11044
11069
|
this.disabled = disabled;
|
|
@@ -11169,7 +11194,7 @@ class QdInputComponent {
|
|
|
11169
11194
|
provide: QD_FOCUSABLE_TOKEN,
|
|
11170
11195
|
useExisting: QdInputComponent
|
|
11171
11196
|
}
|
|
11172
|
-
], viewQueries: [{ propertyName: "inputElement", first: true, predicate: ["input"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<qd-form-label\n [label]=\"label\"\n [readonly]=\"readonly\"\n [viewonly]=\"viewonly\"\n [control]=\"control\"\n [tooltip]=\"config?.tooltip\"\n [data-test-id]=\"testId\"\n></qd-form-label>\n\n<ng-container *ngIf=\"!readonly && !viewonly && !hasOptions\">\n <div class=\"qd-input-input\" (keydown.enter)=\"emitEnterClick()\">\n <ng-container *ngTemplateOutlet=\"inputBox\"></ng-container>\n </div>\n\n <span class=\"qd-input-character-counter\" *ngIf=\"hasMaxLength\">{{ numberOfCharacters }} / {{ maxLength }}</span>\n\n <qd-form-hint\n *ngIf=\"hint || hasError\"\n [hint]=\"hint\"\n [control]=\"control\"\n [hasError]=\"hasError\"\n [hintAction]=\"hintAction\"\n [data-test-id]=\"testId\"\n ></qd-form-hint>\n</ng-container>\n\n<div *ngIf=\"!readonly && !viewonly && hasOptions\">\n <div\n class=\"qd-input-input\"\n qdInputOptions\n [qdPopoverMinWidth]=\"200\"\n [config]=\"config\"\n [value]=\"_value.value\"\n (optionSelected)=\"handleOptionSelected($event)\"\n (enterClick)=\"emitEnterClick()\"\n >\n <!-- handle (enterClick) by options directive here because event has to be fired after selection -->\n <ng-container *ngTemplateOutlet=\"inputBox\"></ng-container>\n </div>\n\n <span class=\"qd-input-character-counter\" *ngIf=\"hasMaxLength\">{{ numberOfCharacters }} / {{ maxLength }}</span>\n\n <qd-form-hint\n *ngIf=\"hint || hasError\"\n [hint]=\"hint\"\n [control]=\"control\"\n [hasError]=\"hasError\"\n [hintAction]=\"hintAction\"\n [data-test-id]=\"testId\"\n ></qd-form-hint>\n</div>\n\n<qd-form-readonly\n *ngIf=\"readonly\"\n [values]=\"valueAsList\"\n [readonlyAction]=\"readonlyAction\"\n [data-test-id]=\"testId\"\n></qd-form-readonly>\n\n<qd-form-viewonly\n *ngIf=\"viewonly\"\n [values]=\"valueAsList\"\n [viewonlyAction]=\"viewonlyAction\"\n [data-test-id]=\"testId\"\n></qd-form-viewonly>\n\n<ng-template #inputBox>\n <input\n #input\n [placeholder]=\"placeholder | translate\"\n [value]=\"hasOptions ? (_value.value.toString() | translate) :
|
|
11197
|
+
], viewQueries: [{ propertyName: "inputElement", first: true, predicate: ["input"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<qd-form-label\n [label]=\"label\"\n [readonly]=\"readonly\"\n [viewonly]=\"viewonly\"\n [control]=\"control\"\n [tooltip]=\"config?.tooltip\"\n [data-test-id]=\"testId\"\n></qd-form-label>\n\n<ng-container *ngIf=\"!readonly && !viewonly && !hasOptions\">\n <div class=\"qd-input-input\" (keydown.enter)=\"emitEnterClick()\">\n <ng-container *ngTemplateOutlet=\"inputBox\"></ng-container>\n </div>\n\n <span class=\"qd-input-character-counter\" *ngIf=\"hasMaxLength\">{{ numberOfCharacters }} / {{ maxLength }}</span>\n\n <qd-form-hint\n *ngIf=\"hint || hasError\"\n [hint]=\"hint\"\n [control]=\"control\"\n [hasError]=\"hasError\"\n [hintAction]=\"hintAction\"\n [data-test-id]=\"testId\"\n ></qd-form-hint>\n</ng-container>\n\n<div *ngIf=\"!readonly && !viewonly && hasOptions\">\n <div\n class=\"qd-input-input\"\n qdInputOptions\n [qdPopoverMinWidth]=\"200\"\n [config]=\"config\"\n [value]=\"_value.value\"\n (optionSelected)=\"handleOptionSelected($event)\"\n (enterClick)=\"emitEnterClick()\"\n >\n <!-- handle (enterClick) by options directive here because event has to be fired after selection -->\n <ng-container *ngTemplateOutlet=\"inputBox\"></ng-container>\n </div>\n\n <span class=\"qd-input-character-counter\" *ngIf=\"hasMaxLength\">{{ numberOfCharacters }} / {{ maxLength }}</span>\n\n <qd-form-hint\n *ngIf=\"hint || hasError\"\n [hint]=\"hint\"\n [control]=\"control\"\n [hasError]=\"hasError\"\n [hintAction]=\"hintAction\"\n [data-test-id]=\"testId\"\n ></qd-form-hint>\n</div>\n\n<qd-form-readonly\n *ngIf=\"readonly\"\n [values]=\"valueAsList\"\n [readonlyAction]=\"readonlyAction\"\n [data-test-id]=\"testId\"\n></qd-form-readonly>\n\n<qd-form-viewonly\n *ngIf=\"viewonly\"\n [values]=\"valueAsList\"\n [viewonlyAction]=\"viewonlyAction\"\n [data-test-id]=\"testId\"\n></qd-form-viewonly>\n\n<ng-template #inputBox>\n <input\n #input\n [placeholder]=\"placeholder | translate\"\n [value]=\"hasOptions ? (_value.value.toString() | translate) : _displayValue\"\n (input)=\"handleInput($event)\"\n (focus)=\"handleInputFocus()\"\n (blur)=\"handleInputBlur()\"\n [disabled]=\"disabled || readonly\"\n [type]=\"inputType\"\n [attr.inputmode]=\"inputMode\"\n [qdAutofocus]=\"hasAutofocus\"\n [attr.data-test-id]=\"testId + '-input'\"\n [step]=\"config?.step\"\n required\n />\n <div class=\"qd-input-suffix\">\n <qd-icon *ngIf=\"hasError && !hasOnlyUnitsError\" class=\"qd-input-error-icon\" icon=\"exclamationCircleSolid\"></qd-icon>\n <qd-icon *ngIf=\"clearable\" class=\"qd-input-clearable-icon\" icon=\"timesLarge\" (click)=\"clearInput()\"></qd-icon>\n <ng-content select=\"[qdIconButton]\"></ng-content>\n </div>\n <qd-input-units\n *ngIf=\"hasUnits\"\n [unit]=\"_value.unit\"\n [config]=\"config\"\n (unitChange)=\"handleUnitChange($event)\"\n (opened)=\"handleUnitsOpened()\"\n (closed)=\"handleUnitsClosed()\"\n ></qd-input-units>\n <div class=\"qd-input-suffix\" *ngIf=\"hasError && hasOnlyUnitsError\">\n <qd-icon class=\"qd-input-error-icon\" icon=\"exclamationCircleSolid\"></qd-icon>\n </div>\n</ng-template>\n", styles: [":host{position:relative;display:block;width:100%;flex-direction:column;margin-bottom:.75rem}:host .qd-input-input{display:flex;overflow:hidden;height:2.25rem;align-items:center;padding:0 .0625rem 0 .5rem;border:.0625rem solid rgb(180,180,180);border-radius:0;margin-bottom:.375rem;background-color:#fff}:host .qd-input-input:hover,:host .qd-input-input:active{padding:.0625rem 0 .0625rem .4375rem;border:.125rem solid rgb(23,23,23);border-radius:0}:host .qd-input-input input{overflow:hidden;width:100%;flex-grow:1;border:none;background-color:#fff;color:#171717;font-size:.875rem;line-height:1.875rem}:host .qd-input-input input:hover,:host .qd-input-input input:focus,:host .qd-input-input input:active{border:none;outline:none}:host .qd-input-input input::placeholder{color:#b4b4b4}:host .qd-input-input input:focus::placeholder{display:block;color:#b4b4b4}:host .qd-input-input .qd-input-suffix{display:flex;align-items:center;margin-left:.75rem}:host .qd-input-input .qd-input-suffix ::ng-deep .qd-input-error-icon{padding-right:.5rem;color:#c70023}:host .qd-input-input .qd-input-suffix ::ng-deep .qd-input-error-icon+.qd-input-clearable-icon{margin-left:-.25rem}:host .qd-input-input .qd-input-suffix ::ng-deep .qd-input-clearable-icon{margin-right:.5625rem;color:#979797;cursor:pointer;font-size:1.25rem;line-height:2rem}:host .qd-input-input .qd-input-suffix ::ng-deep .qd-input-clearable-icon:hover,:host .qd-input-input .qd-input-suffix ::ng-deep .qd-input-clearable-icon:focus,:host .qd-input-input .qd-input-suffix ::ng-deep .qd-input-clearable-icon:active{color:#171717}:host .qd-input-input qd-input-units+.qd-input-suffix{margin:0 0 0 -.1875rem}:host .qd-input-character-counter{padding-left:.125rem;color:#757575;float:right;font-size:.75rem;font-weight:300;line-height:.75rem}:host:after{display:block;height:0;clear:both;content:\".\";visibility:hidden}:host.qd-input-focus .qd-input-input{padding:.0625rem 0 .0625rem .4375rem;border:.125rem solid rgb(0,102,153);border-radius:0;outline:none}:host.qd-input-readonly .qd-input-readonly{color:#171717;font-size:.875rem;line-height:2.25rem}:host.qd-input-viewonly .qd-input-viewonly{color:#171717;font-size:.875rem;line-height:2.25rem}:host.qd-input-disabled .qd-input-input{border:.0625rem solid rgb(151,151,151);background-color:#f5f5f5}:host.qd-input-disabled .qd-input-input input{background-color:#f5f5f5;color:#979797}:host.qd-input-disabled .qd-input-input input::placeholder{opacity:0}:host.qd-input-disabled .qd-input-input:hover,:host.qd-input-disabled .qd-input-input:active{padding:0 .0625rem 0 .5rem;border:.0625rem solid rgb(151,151,151);background-color:#f5f5f5}:host.qd-input-disabled.qd-input-focus{border-color:#ff9b00}:host.qd-input--readonly-action .qd-input-readonly{color:#069;cursor:pointer}:host.qd-input--readonly-action .qd-input-readonly:hover,:host.qd-input--readonly-action .qd-input-readonly:active,:host.qd-input--readonly-action .qd-input-readonly:focus{text-decoration:underline}:host.qd-input--viewonly-action .qd-input-viewonly{color:#069;cursor:pointer}:host.qd-input--viewonly-action .qd-input-viewonly:hover,:host.qd-input--viewonly-action .qd-input-viewonly:active,:host.qd-input--viewonly-action .qd-input-viewonly:focus{text-decoration:underline}:host.qd-input-error .qd-input-input,:host.qd-input-error-from-outside .qd-input-input{padding:0 .0625rem 0 .5rem;border:.0625rem solid rgb(199,0,35)}:host.qd-input-error .qd-input-input:hover,:host.qd-input-error .qd-input-input:active,:host.qd-input-error-from-outside .qd-input-input:hover,:host.qd-input-error-from-outside .qd-input-input:active{padding:.0625rem 0 .0625rem .4375rem;border:.125rem solid rgb(199,0,35)}:host.qd-input-error.qd-input-focus,:host.qd-input-error-from-outside.qd-input-focus{border-color:#c70023}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: QdAutofocusDirective, selector: "[qdAutofocus]", inputs: ["qdAutofocus"] }, { kind: "component", type: QdIconComponent, selector: "qd-icon", inputs: ["icon"] }, { kind: "component", type: QdFormHintComponent, selector: "qd-form-hint", inputs: ["hint", "control", "hasError", "hintAction", "data-test-id"] }, { kind: "component", type: QdFormLabelComponent, selector: "qd-form-label", inputs: ["label", "isDisabled", "readonly", "viewonly", "control", "tooltip", "data-test-id"] }, { kind: "component", type: QdFormReadonlyComponent, selector: "qd-form-readonly", inputs: ["values", "readonlyAction", "data-test-id"] }, { kind: "component", type: QdFormViewonlyComponent, selector: "qd-form-viewonly", inputs: ["values", "viewonlyAction", "data-test-id"] }, { kind: "component", type: QdInputUnitsComponent, selector: "qd-input-units", inputs: ["config", "unit"], outputs: ["unitChange", "opened", "closed"] }, { kind: "directive", type: QdInputOptionsDirective, selector: "[qdInputOptions]", inputs: ["value", "config"], outputs: ["enterClick", "optionSelected"] }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }] });
|
|
11173
11198
|
}
|
|
11174
11199
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdInputComponent, decorators: [{
|
|
11175
11200
|
type: Component,
|
|
@@ -11187,7 +11212,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
11187
11212
|
provide: QD_FOCUSABLE_TOKEN,
|
|
11188
11213
|
useExisting: QdInputComponent
|
|
11189
11214
|
}
|
|
11190
|
-
], standalone: false, template: "<qd-form-label\n [label]=\"label\"\n [readonly]=\"readonly\"\n [viewonly]=\"viewonly\"\n [control]=\"control\"\n [tooltip]=\"config?.tooltip\"\n [data-test-id]=\"testId\"\n></qd-form-label>\n\n<ng-container *ngIf=\"!readonly && !viewonly && !hasOptions\">\n <div class=\"qd-input-input\" (keydown.enter)=\"emitEnterClick()\">\n <ng-container *ngTemplateOutlet=\"inputBox\"></ng-container>\n </div>\n\n <span class=\"qd-input-character-counter\" *ngIf=\"hasMaxLength\">{{ numberOfCharacters }} / {{ maxLength }}</span>\n\n <qd-form-hint\n *ngIf=\"hint || hasError\"\n [hint]=\"hint\"\n [control]=\"control\"\n [hasError]=\"hasError\"\n [hintAction]=\"hintAction\"\n [data-test-id]=\"testId\"\n ></qd-form-hint>\n</ng-container>\n\n<div *ngIf=\"!readonly && !viewonly && hasOptions\">\n <div\n class=\"qd-input-input\"\n qdInputOptions\n [qdPopoverMinWidth]=\"200\"\n [config]=\"config\"\n [value]=\"_value.value\"\n (optionSelected)=\"handleOptionSelected($event)\"\n (enterClick)=\"emitEnterClick()\"\n >\n <!-- handle (enterClick) by options directive here because event has to be fired after selection -->\n <ng-container *ngTemplateOutlet=\"inputBox\"></ng-container>\n </div>\n\n <span class=\"qd-input-character-counter\" *ngIf=\"hasMaxLength\">{{ numberOfCharacters }} / {{ maxLength }}</span>\n\n <qd-form-hint\n *ngIf=\"hint || hasError\"\n [hint]=\"hint\"\n [control]=\"control\"\n [hasError]=\"hasError\"\n [hintAction]=\"hintAction\"\n [data-test-id]=\"testId\"\n ></qd-form-hint>\n</div>\n\n<qd-form-readonly\n *ngIf=\"readonly\"\n [values]=\"valueAsList\"\n [readonlyAction]=\"readonlyAction\"\n [data-test-id]=\"testId\"\n></qd-form-readonly>\n\n<qd-form-viewonly\n *ngIf=\"viewonly\"\n [values]=\"valueAsList\"\n [viewonlyAction]=\"viewonlyAction\"\n [data-test-id]=\"testId\"\n></qd-form-viewonly>\n\n<ng-template #inputBox>\n <input\n #input\n [placeholder]=\"placeholder | translate\"\n [value]=\"hasOptions ? (_value.value.toString() | translate) :
|
|
11215
|
+
], standalone: false, template: "<qd-form-label\n [label]=\"label\"\n [readonly]=\"readonly\"\n [viewonly]=\"viewonly\"\n [control]=\"control\"\n [tooltip]=\"config?.tooltip\"\n [data-test-id]=\"testId\"\n></qd-form-label>\n\n<ng-container *ngIf=\"!readonly && !viewonly && !hasOptions\">\n <div class=\"qd-input-input\" (keydown.enter)=\"emitEnterClick()\">\n <ng-container *ngTemplateOutlet=\"inputBox\"></ng-container>\n </div>\n\n <span class=\"qd-input-character-counter\" *ngIf=\"hasMaxLength\">{{ numberOfCharacters }} / {{ maxLength }}</span>\n\n <qd-form-hint\n *ngIf=\"hint || hasError\"\n [hint]=\"hint\"\n [control]=\"control\"\n [hasError]=\"hasError\"\n [hintAction]=\"hintAction\"\n [data-test-id]=\"testId\"\n ></qd-form-hint>\n</ng-container>\n\n<div *ngIf=\"!readonly && !viewonly && hasOptions\">\n <div\n class=\"qd-input-input\"\n qdInputOptions\n [qdPopoverMinWidth]=\"200\"\n [config]=\"config\"\n [value]=\"_value.value\"\n (optionSelected)=\"handleOptionSelected($event)\"\n (enterClick)=\"emitEnterClick()\"\n >\n <!-- handle (enterClick) by options directive here because event has to be fired after selection -->\n <ng-container *ngTemplateOutlet=\"inputBox\"></ng-container>\n </div>\n\n <span class=\"qd-input-character-counter\" *ngIf=\"hasMaxLength\">{{ numberOfCharacters }} / {{ maxLength }}</span>\n\n <qd-form-hint\n *ngIf=\"hint || hasError\"\n [hint]=\"hint\"\n [control]=\"control\"\n [hasError]=\"hasError\"\n [hintAction]=\"hintAction\"\n [data-test-id]=\"testId\"\n ></qd-form-hint>\n</div>\n\n<qd-form-readonly\n *ngIf=\"readonly\"\n [values]=\"valueAsList\"\n [readonlyAction]=\"readonlyAction\"\n [data-test-id]=\"testId\"\n></qd-form-readonly>\n\n<qd-form-viewonly\n *ngIf=\"viewonly\"\n [values]=\"valueAsList\"\n [viewonlyAction]=\"viewonlyAction\"\n [data-test-id]=\"testId\"\n></qd-form-viewonly>\n\n<ng-template #inputBox>\n <input\n #input\n [placeholder]=\"placeholder | translate\"\n [value]=\"hasOptions ? (_value.value.toString() | translate) : _displayValue\"\n (input)=\"handleInput($event)\"\n (focus)=\"handleInputFocus()\"\n (blur)=\"handleInputBlur()\"\n [disabled]=\"disabled || readonly\"\n [type]=\"inputType\"\n [attr.inputmode]=\"inputMode\"\n [qdAutofocus]=\"hasAutofocus\"\n [attr.data-test-id]=\"testId + '-input'\"\n [step]=\"config?.step\"\n required\n />\n <div class=\"qd-input-suffix\">\n <qd-icon *ngIf=\"hasError && !hasOnlyUnitsError\" class=\"qd-input-error-icon\" icon=\"exclamationCircleSolid\"></qd-icon>\n <qd-icon *ngIf=\"clearable\" class=\"qd-input-clearable-icon\" icon=\"timesLarge\" (click)=\"clearInput()\"></qd-icon>\n <ng-content select=\"[qdIconButton]\"></ng-content>\n </div>\n <qd-input-units\n *ngIf=\"hasUnits\"\n [unit]=\"_value.unit\"\n [config]=\"config\"\n (unitChange)=\"handleUnitChange($event)\"\n (opened)=\"handleUnitsOpened()\"\n (closed)=\"handleUnitsClosed()\"\n ></qd-input-units>\n <div class=\"qd-input-suffix\" *ngIf=\"hasError && hasOnlyUnitsError\">\n <qd-icon class=\"qd-input-error-icon\" icon=\"exclamationCircleSolid\"></qd-icon>\n </div>\n</ng-template>\n", styles: [":host{position:relative;display:block;width:100%;flex-direction:column;margin-bottom:.75rem}:host .qd-input-input{display:flex;overflow:hidden;height:2.25rem;align-items:center;padding:0 .0625rem 0 .5rem;border:.0625rem solid rgb(180,180,180);border-radius:0;margin-bottom:.375rem;background-color:#fff}:host .qd-input-input:hover,:host .qd-input-input:active{padding:.0625rem 0 .0625rem .4375rem;border:.125rem solid rgb(23,23,23);border-radius:0}:host .qd-input-input input{overflow:hidden;width:100%;flex-grow:1;border:none;background-color:#fff;color:#171717;font-size:.875rem;line-height:1.875rem}:host .qd-input-input input:hover,:host .qd-input-input input:focus,:host .qd-input-input input:active{border:none;outline:none}:host .qd-input-input input::placeholder{color:#b4b4b4}:host .qd-input-input input:focus::placeholder{display:block;color:#b4b4b4}:host .qd-input-input .qd-input-suffix{display:flex;align-items:center;margin-left:.75rem}:host .qd-input-input .qd-input-suffix ::ng-deep .qd-input-error-icon{padding-right:.5rem;color:#c70023}:host .qd-input-input .qd-input-suffix ::ng-deep .qd-input-error-icon+.qd-input-clearable-icon{margin-left:-.25rem}:host .qd-input-input .qd-input-suffix ::ng-deep .qd-input-clearable-icon{margin-right:.5625rem;color:#979797;cursor:pointer;font-size:1.25rem;line-height:2rem}:host .qd-input-input .qd-input-suffix ::ng-deep .qd-input-clearable-icon:hover,:host .qd-input-input .qd-input-suffix ::ng-deep .qd-input-clearable-icon:focus,:host .qd-input-input .qd-input-suffix ::ng-deep .qd-input-clearable-icon:active{color:#171717}:host .qd-input-input qd-input-units+.qd-input-suffix{margin:0 0 0 -.1875rem}:host .qd-input-character-counter{padding-left:.125rem;color:#757575;float:right;font-size:.75rem;font-weight:300;line-height:.75rem}:host:after{display:block;height:0;clear:both;content:\".\";visibility:hidden}:host.qd-input-focus .qd-input-input{padding:.0625rem 0 .0625rem .4375rem;border:.125rem solid rgb(0,102,153);border-radius:0;outline:none}:host.qd-input-readonly .qd-input-readonly{color:#171717;font-size:.875rem;line-height:2.25rem}:host.qd-input-viewonly .qd-input-viewonly{color:#171717;font-size:.875rem;line-height:2.25rem}:host.qd-input-disabled .qd-input-input{border:.0625rem solid rgb(151,151,151);background-color:#f5f5f5}:host.qd-input-disabled .qd-input-input input{background-color:#f5f5f5;color:#979797}:host.qd-input-disabled .qd-input-input input::placeholder{opacity:0}:host.qd-input-disabled .qd-input-input:hover,:host.qd-input-disabled .qd-input-input:active{padding:0 .0625rem 0 .5rem;border:.0625rem solid rgb(151,151,151);background-color:#f5f5f5}:host.qd-input-disabled.qd-input-focus{border-color:#ff9b00}:host.qd-input--readonly-action .qd-input-readonly{color:#069;cursor:pointer}:host.qd-input--readonly-action .qd-input-readonly:hover,:host.qd-input--readonly-action .qd-input-readonly:active,:host.qd-input--readonly-action .qd-input-readonly:focus{text-decoration:underline}:host.qd-input--viewonly-action .qd-input-viewonly{color:#069;cursor:pointer}:host.qd-input--viewonly-action .qd-input-viewonly:hover,:host.qd-input--viewonly-action .qd-input-viewonly:active,:host.qd-input--viewonly-action .qd-input-viewonly:focus{text-decoration:underline}:host.qd-input-error .qd-input-input,:host.qd-input-error-from-outside .qd-input-input{padding:0 .0625rem 0 .5rem;border:.0625rem solid rgb(199,0,35)}:host.qd-input-error .qd-input-input:hover,:host.qd-input-error .qd-input-input:active,:host.qd-input-error-from-outside .qd-input-input:hover,:host.qd-input-error-from-outside .qd-input-input:active{padding:.0625rem 0 .0625rem .4375rem;border:.125rem solid rgb(199,0,35)}:host.qd-input-error.qd-input-focus,:host.qd-input-error-from-outside.qd-input-focus{border-color:#c70023}\n"] }]
|
|
11191
11216
|
}], propDecorators: { formControlName: [{
|
|
11192
11217
|
type: Input
|
|
11193
11218
|
}], value: [{
|
|
@@ -11409,8 +11434,6 @@ class QdDatepickerComponent {
|
|
|
11409
11434
|
this.displayedDateTime = date ? QdDateAdapter.formatToDateTimeLocaleString(date, this.config?.enableSeconds) : '';
|
|
11410
11435
|
this.displayedTime = date ? QdDateAdapter.formatToTimeLocaleString(date, this.config?.enableSeconds) : '';
|
|
11411
11436
|
this.changeDetectorRef.detectChanges();
|
|
11412
|
-
this.valueChange.emit(date);
|
|
11413
|
-
this._onChange(date);
|
|
11414
11437
|
}
|
|
11415
11438
|
setDisabledState(disabled) {
|
|
11416
11439
|
this.disabled = disabled;
|
|
@@ -12848,7 +12871,7 @@ class QdValidators {
|
|
|
12848
12871
|
return ({ value }) => {
|
|
12849
12872
|
if (!value)
|
|
12850
12873
|
return null;
|
|
12851
|
-
const localizedFormat = moment().
|
|
12874
|
+
const localizedFormat = moment().format('DD.MM.YYYY');
|
|
12852
12875
|
const formattedErrorKey = { date: { key: errorKey, params: { format: localizedFormat } } };
|
|
12853
12876
|
if (value === 'Invalid Date')
|
|
12854
12877
|
return formattedErrorKey;
|
|
@@ -18161,37 +18184,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
18161
18184
|
}]
|
|
18162
18185
|
}], ctorParameters: () => [] });
|
|
18163
18186
|
|
|
18164
|
-
class QdCancelDialogComponent {
|
|
18165
|
-
dialogRef = inject(DialogRef);
|
|
18166
|
-
i18n;
|
|
18167
|
-
handler;
|
|
18168
|
-
ngOnInit() {
|
|
18169
|
-
this.i18n =
|
|
18170
|
-
this.dialogRef.config.data?.cancel?.confirmationMessage?.i18n ??
|
|
18171
|
-
'i18n.qd.page.cancel.confirmation.dialog.message';
|
|
18172
|
-
this.handler = this.dialogRef.config.data?.cancel?.handler;
|
|
18173
|
-
}
|
|
18174
|
-
close() {
|
|
18175
|
-
this.dialogRef.close(false);
|
|
18176
|
-
}
|
|
18177
|
-
confirm() {
|
|
18178
|
-
if (this.handler)
|
|
18179
|
-
this.handler();
|
|
18180
|
-
this.dialogRef.close(true);
|
|
18181
|
-
}
|
|
18182
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdCancelDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
18183
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdCancelDialogComponent, isStandalone: false, selector: "qd-cancel-dialog", ngImport: i0, template: "<qd-dialog>\n <qd-text-section>\n <qd-text-section-paragraph>\n {{ i18n | translate }}\n </qd-text-section-paragraph>\n </qd-text-section>\n\n <qd-dialog-action>\n <button\n qdButton\n qdButtonGhost\n color=\"secondary\"\n (click)=\"close()\"\n data-test-id=\"dialog-cancel-confirmation-dialog-close\"\n >\n {{ \"i18n.qd.page.cancel.confirmation.dialog.close\" | translate }}\n </button>\n\n <button qdButton color=\"error\" (click)=\"confirm()\" data-test-id=\"dialog-cancel-confirmation-dialog-proceed\">\n {{ \"i18n.qd.page.cancel.confirmation.dialog.proceed\" | translate }}\n </button>\n </qd-dialog-action>\n</qd-dialog>\n", dependencies: [{ kind: "component", type: QdButtonComponent, selector: "button[qdButton], a[qdButton], button[qd-button]", inputs: ["disabled", "color", "icon", "data-test-id", "additionalInfo"] }, { kind: "directive", type: QdButtonGhostDirective, selector: "button[qdButtonGhost], a[qdButtonGhost]" }, { kind: "component", type: QdTextSectionComponent, selector: "qd-text-section" }, { kind: "component", type: QdTextSectionParagraphComponent, selector: "qd-text-section-paragraph" }, { kind: "component", type: QdDialogActionComponent, selector: "qd-dialog-action" }, { kind: "component", type: QdDialogComponent, selector: "qd-dialog" }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }] });
|
|
18184
|
-
}
|
|
18185
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdCancelDialogComponent, decorators: [{
|
|
18186
|
-
type: Component,
|
|
18187
|
-
args: [{ selector: 'qd-cancel-dialog', standalone: false, template: "<qd-dialog>\n <qd-text-section>\n <qd-text-section-paragraph>\n {{ i18n | translate }}\n </qd-text-section-paragraph>\n </qd-text-section>\n\n <qd-dialog-action>\n <button\n qdButton\n qdButtonGhost\n color=\"secondary\"\n (click)=\"close()\"\n data-test-id=\"dialog-cancel-confirmation-dialog-close\"\n >\n {{ \"i18n.qd.page.cancel.confirmation.dialog.close\" | translate }}\n </button>\n\n <button qdButton color=\"error\" (click)=\"confirm()\" data-test-id=\"dialog-cancel-confirmation-dialog-proceed\">\n {{ \"i18n.qd.page.cancel.confirmation.dialog.proceed\" | translate }}\n </button>\n </qd-dialog-action>\n</qd-dialog>\n" }]
|
|
18188
|
-
}] });
|
|
18189
|
-
|
|
18190
|
-
var cancelDialog_component = /*#__PURE__*/Object.freeze({
|
|
18191
|
-
__proto__: null,
|
|
18192
|
-
QdCancelDialogComponent: QdCancelDialogComponent
|
|
18193
|
-
});
|
|
18194
|
-
|
|
18195
18187
|
class QdDialogModule {
|
|
18196
18188
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdDialogModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
18197
18189
|
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.18", ngImport: i0, type: QdDialogModule, declarations: [QdDialogActionComponent,
|
|
@@ -18203,8 +18195,7 @@ class QdDialogModule {
|
|
|
18203
18195
|
QdDialogConfirmationSuccessDirective,
|
|
18204
18196
|
QdDialogRecordStepperComponent,
|
|
18205
18197
|
QdPageDialogWithBreadcrumbsComponent,
|
|
18206
|
-
QdPendingChangesGuardDirective,
|
|
18207
|
-
QdCancelDialogComponent], imports: [CommonModule,
|
|
18198
|
+
QdPendingChangesGuardDirective], imports: [CommonModule,
|
|
18208
18199
|
TranslateModule,
|
|
18209
18200
|
RouterModule,
|
|
18210
18201
|
DialogModule,
|
|
@@ -18268,8 +18259,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
18268
18259
|
QdDialogConfirmationSuccessDirective,
|
|
18269
18260
|
QdDialogRecordStepperComponent,
|
|
18270
18261
|
QdPageDialogWithBreadcrumbsComponent,
|
|
18271
|
-
QdPendingChangesGuardDirective
|
|
18272
|
-
QdCancelDialogComponent
|
|
18262
|
+
QdPendingChangesGuardDirective
|
|
18273
18263
|
],
|
|
18274
18264
|
exports: [
|
|
18275
18265
|
QdDialogActionComponent,
|
|
@@ -24270,6 +24260,7 @@ class QdTableComponent {
|
|
|
24270
24260
|
fillingWidthService = inject(QdTableFillingWidthService);
|
|
24271
24261
|
breakpointService = inject(QdBreakpointService);
|
|
24272
24262
|
resolverService = inject(QdTableResolverService);
|
|
24263
|
+
confirmationDialogService = inject(QdConfirmationDialogOpenerService);
|
|
24273
24264
|
/**
|
|
24274
24265
|
* Configuration of the table. The generic type specifies the column definition. <br />
|
|
24275
24266
|
*
|
|
@@ -24472,6 +24463,17 @@ class QdTableComponent {
|
|
|
24472
24463
|
if (action.highlightOnRevisit) {
|
|
24473
24464
|
this.tableStoreService.setLastVisitedRow(resolveRowIdentifier(recentAction.rowData, recentAction.index, this.config.trackRowBy));
|
|
24474
24465
|
}
|
|
24466
|
+
if (action.confirmationMessage) {
|
|
24467
|
+
this.confirmationDialogService
|
|
24468
|
+
.showConfirmDialog({ message: action.confirmationMessage }, this.testId + '-confirmation')
|
|
24469
|
+
.pipe(filter(confirmed => confirmed))
|
|
24470
|
+
.subscribe(() => {
|
|
24471
|
+
const result = action.handler(recentAction);
|
|
24472
|
+
if (action.refresh?.isEnabled)
|
|
24473
|
+
this.processSecondaryActionRefresh(result, action.refresh);
|
|
24474
|
+
});
|
|
24475
|
+
return;
|
|
24476
|
+
}
|
|
24475
24477
|
const result = action.handler(recentAction);
|
|
24476
24478
|
if (action.refresh?.isEnabled)
|
|
24477
24479
|
this.processSecondaryActionRefresh(result, action.refresh);
|
|
@@ -26465,30 +26467,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
26465
26467
|
}]
|
|
26466
26468
|
}] });
|
|
26467
26469
|
|
|
26468
|
-
class QdPageCancelConfirmationDialogComponent {
|
|
26469
|
-
dialogRef = inject(DialogRef);
|
|
26470
|
-
i18n;
|
|
26471
|
-
handler;
|
|
26472
|
-
ngOnInit() {
|
|
26473
|
-
this.i18n =
|
|
26474
|
-
this.dialogRef.config.data.cancel.confirmationMessage?.i18n ?? 'i18n.qd.page.cancel.confirmation.dialog.message';
|
|
26475
|
-
this.handler = this.dialogRef.config.data.cancel.handler;
|
|
26476
|
-
}
|
|
26477
|
-
close() {
|
|
26478
|
-
this.dialogRef.close(false);
|
|
26479
|
-
}
|
|
26480
|
-
confirm() {
|
|
26481
|
-
this.dialogRef.close(true);
|
|
26482
|
-
this.handler();
|
|
26483
|
-
}
|
|
26484
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdPageCancelConfirmationDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
26485
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdPageCancelConfirmationDialogComponent, isStandalone: false, selector: "qd-page-cancel-confirmation-dialog", ngImport: i0, template: "<qd-dialog>\n <qd-text-section>\n <qd-text-section-paragraph>\n {{ i18n | translate }}\n </qd-text-section-paragraph>\n </qd-text-section>\n\n <qd-dialog-action>\n <button\n qdButton\n qdButtonGhost\n color=\"secondary\"\n (click)=\"close()\"\n data-test-id=\"page-cancel-confirmation-dialog-close\"\n >\n {{ \"i18n.qd.page.cancel.confirmation.dialog.close\" | translate }}\n </button>\n\n <button qdButton color=\"error\" (click)=\"confirm()\" data-test-id=\"page-cancel-confirmation-dialog-proceed\">\n {{ \"i18n.qd.page.cancel.confirmation.dialog.proceed\" | translate }}\n </button>\n </qd-dialog-action>\n</qd-dialog>\n", styles: [""], dependencies: [{ kind: "component", type: QdButtonComponent, selector: "button[qdButton], a[qdButton], button[qd-button]", inputs: ["disabled", "color", "icon", "data-test-id", "additionalInfo"] }, { kind: "directive", type: QdButtonGhostDirective, selector: "button[qdButtonGhost], a[qdButtonGhost]" }, { kind: "component", type: QdDialogActionComponent, selector: "qd-dialog-action" }, { kind: "component", type: QdDialogComponent, selector: "qd-dialog" }, { kind: "component", type: QdTextSectionComponent, selector: "qd-text-section" }, { kind: "component", type: QdTextSectionParagraphComponent, selector: "qd-text-section-paragraph" }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }] });
|
|
26486
|
-
}
|
|
26487
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdPageCancelConfirmationDialogComponent, decorators: [{
|
|
26488
|
-
type: Component,
|
|
26489
|
-
args: [{ selector: 'qd-page-cancel-confirmation-dialog', standalone: false, template: "<qd-dialog>\n <qd-text-section>\n <qd-text-section-paragraph>\n {{ i18n | translate }}\n </qd-text-section-paragraph>\n </qd-text-section>\n\n <qd-dialog-action>\n <button\n qdButton\n qdButtonGhost\n color=\"secondary\"\n (click)=\"close()\"\n data-test-id=\"page-cancel-confirmation-dialog-close\"\n >\n {{ \"i18n.qd.page.cancel.confirmation.dialog.close\" | translate }}\n </button>\n\n <button qdButton color=\"error\" (click)=\"confirm()\" data-test-id=\"page-cancel-confirmation-dialog-proceed\">\n {{ \"i18n.qd.page.cancel.confirmation.dialog.proceed\" | translate }}\n </button>\n </qd-dialog-action>\n</qd-dialog>\n" }]
|
|
26490
|
-
}] });
|
|
26491
|
-
|
|
26492
26470
|
/**
|
|
26493
26471
|
* The **QdPageControlPanel** is used to display information and functions relevant to a specific business case, which is related to a specific Object Model.
|
|
26494
26472
|
*
|
|
@@ -27198,6 +27176,39 @@ class QdFormGroupManagerService {
|
|
|
27198
27176
|
takeFormGroupsSnapshot() {
|
|
27199
27177
|
this._formGroups.forEach((fg, key) => this._formGroupsSnapshot.set(key, fg.getRawValue()));
|
|
27200
27178
|
}
|
|
27179
|
+
/**
|
|
27180
|
+
* Captures a deep-cloned snapshot of all current form values without mutating internal state.
|
|
27181
|
+
*
|
|
27182
|
+
* Used by framework orchestration code that needs to remember the "at click time" state of a form
|
|
27183
|
+
* so the baseline can later be committed to exactly that state — even if the user edits the form
|
|
27184
|
+
* while an async commit action is pending.
|
|
27185
|
+
*
|
|
27186
|
+
* Throws if any form value is not structured-cloneable (functions, symbols, DOM nodes).
|
|
27187
|
+
*/
|
|
27188
|
+
captureFormValues() {
|
|
27189
|
+
const captured = new Map();
|
|
27190
|
+
this._formGroups.forEach((fg, key) => {
|
|
27191
|
+
try {
|
|
27192
|
+
captured.set(key, structuredClone(fg.getRawValue()));
|
|
27193
|
+
}
|
|
27194
|
+
catch (err) {
|
|
27195
|
+
throw new Error(`QdFormGroupManagerService: captureFormValues() failed for group "${key}". ` +
|
|
27196
|
+
`Form values must be structured-cloneable. Non-cloneable values like functions, ` +
|
|
27197
|
+
`symbols, or DOM nodes are not supported. Original error: ${String(err)}`);
|
|
27198
|
+
}
|
|
27199
|
+
});
|
|
27200
|
+
return captured;
|
|
27201
|
+
}
|
|
27202
|
+
/**
|
|
27203
|
+
* Replaces the internal baseline snapshot with the provided values.
|
|
27204
|
+
*
|
|
27205
|
+
* Intended to be paired with `captureFormValues()` so that the baseline can be advanced to the
|
|
27206
|
+
* values present when a commit action was initiated — independent of whether the user edited the
|
|
27207
|
+
* form in the meantime.
|
|
27208
|
+
*/
|
|
27209
|
+
commitBaseline(values) {
|
|
27210
|
+
values.forEach((snapshot, key) => this._formGroupsSnapshot.set(key, snapshot));
|
|
27211
|
+
}
|
|
27201
27212
|
restoreFormGroupsFromSnapshot() {
|
|
27202
27213
|
this._formGroups.forEach((fg, key) => {
|
|
27203
27214
|
const snapshot = this._formGroupsSnapshot.get(key);
|
|
@@ -27309,6 +27320,122 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
27309
27320
|
type: Injectable
|
|
27310
27321
|
}] });
|
|
27311
27322
|
|
|
27323
|
+
/**
|
|
27324
|
+
* Intercepts router navigation when unsaved form changes exist on a QdPage.
|
|
27325
|
+
*
|
|
27326
|
+
* Provided per `QdPageComponent`. Activated automatically when the page enters an editable state
|
|
27327
|
+
* (create pages or inspect pages in edit mode). Deactivated when the page returns to view mode.
|
|
27328
|
+
*
|
|
27329
|
+
* #### When navigation is intercepted
|
|
27330
|
+
*
|
|
27331
|
+
* - A `NavigationStart` event occurs (browser back, shell back button, or programmatic navigation).
|
|
27332
|
+
* - The registered form groups report unsaved changes via `QdFormGroupManagerService.$hasValuesChanged()`.
|
|
27333
|
+
*
|
|
27334
|
+
* The navigation is cancelled and a confirmation dialog is shown. The user can either discard
|
|
27335
|
+
* changes and proceed or stay on the page.
|
|
27336
|
+
*
|
|
27337
|
+
* #### When navigation is allowed
|
|
27338
|
+
*
|
|
27339
|
+
* - No unsaved changes exist — the form is either pristine or the framework has advanced the
|
|
27340
|
+
* baseline after a successful commit action (Submit, Save, SaveDraft).
|
|
27341
|
+
* - The page switches to view mode via `deactivate()`.
|
|
27342
|
+
*
|
|
27343
|
+
* The service has no concept of "pending actions" or bypass windows. Framework actions advance the
|
|
27344
|
+
* baseline directly via `QdFormGroupManagerService.commitBaseline(...)`; cancel-discard flows reset
|
|
27345
|
+
* the baseline via `restoreFormGroupsFromSnapshot()`. Either way, the interceptor only observes the
|
|
27346
|
+
* resulting form state — there is no time window where a bypass is active.
|
|
27347
|
+
*/
|
|
27348
|
+
class QdPageNavigationInterceptorService {
|
|
27349
|
+
router = inject(Router);
|
|
27350
|
+
formGroupManager = inject(QdFormGroupManagerService);
|
|
27351
|
+
confirmationDialog = inject(QdConfirmationDialogOpenerService);
|
|
27352
|
+
_destroy$ = new Subject();
|
|
27353
|
+
_deactivate$ = new Subject();
|
|
27354
|
+
/**
|
|
27355
|
+
* Guards the re-dispatched navigation issued after the user confirms discard. While the dialog
|
|
27356
|
+
* is open and while the confirmed target is being re-dispatched, the router events must not
|
|
27357
|
+
* re-enter the interception pipeline — otherwise the dialog would open recursively.
|
|
27358
|
+
*/
|
|
27359
|
+
_bypassInterception = false;
|
|
27360
|
+
/**
|
|
27361
|
+
* URL of the navigation target accepted by the user in the most recent discard-confirm dialog.
|
|
27362
|
+
* Set by `navigateToConfirmedTarget()` and consumed once by `shouldIntercept()` when the
|
|
27363
|
+
* corresponding `NavigationStart` arrives.
|
|
27364
|
+
*/
|
|
27365
|
+
_confirmedTargetUrl;
|
|
27366
|
+
_confirmationMessage;
|
|
27367
|
+
ngOnDestroy() {
|
|
27368
|
+
this._confirmedTargetUrl = undefined;
|
|
27369
|
+
this._destroy$.next();
|
|
27370
|
+
this._destroy$.complete();
|
|
27371
|
+
this._deactivate$.complete();
|
|
27372
|
+
}
|
|
27373
|
+
/**
|
|
27374
|
+
* Starts intercepting navigation events. Replaces any previously active listener.
|
|
27375
|
+
*/
|
|
27376
|
+
activate(confirmationMessage) {
|
|
27377
|
+
this._confirmationMessage = confirmationMessage;
|
|
27378
|
+
this._deactivate$.next();
|
|
27379
|
+
this.listenForUnsavedNavigationAttempts();
|
|
27380
|
+
}
|
|
27381
|
+
/**
|
|
27382
|
+
* Stops intercepting and clears the pending confirmed-target bypass.
|
|
27383
|
+
*/
|
|
27384
|
+
deactivate() {
|
|
27385
|
+
this._deactivate$.next();
|
|
27386
|
+
this._confirmedTargetUrl = undefined;
|
|
27387
|
+
}
|
|
27388
|
+
/**
|
|
27389
|
+
* Runs the given action while temporarily suppressing navigation interception.
|
|
27390
|
+
*
|
|
27391
|
+
* Used by framework commit-action orchestration to wrap synchronous handler invocations and
|
|
27392
|
+
* post-commit `onSuccess` callbacks: any router navigation that occurs during `action()` is
|
|
27393
|
+
* passed through without raising the unsaved-changes dialog. Restoration happens in a `finally`
|
|
27394
|
+
* block, so the flag is released even if `action()` throws.
|
|
27395
|
+
*/
|
|
27396
|
+
executeWithBypass(action) {
|
|
27397
|
+
this._bypassInterception = true;
|
|
27398
|
+
try {
|
|
27399
|
+
action();
|
|
27400
|
+
}
|
|
27401
|
+
finally {
|
|
27402
|
+
this._bypassInterception = false;
|
|
27403
|
+
}
|
|
27404
|
+
}
|
|
27405
|
+
listenForUnsavedNavigationAttempts() {
|
|
27406
|
+
this.router.events
|
|
27407
|
+
.pipe(filter$1((event) => event instanceof NavigationStart), filter$1(() => !this._bypassInterception), filter$1(event => this.shouldIntercept(event)), concatMap$1(event => this.checkForPendingChanges(event)), filter$1(({ hasChanges }) => hasChanges), exhaustMap(({ event }) => this.cancelNavigationAndConfirm(event)), filter$1(({ confirmed }) => confirmed), takeUntil$1(this._deactivate$), takeUntil$1(this._destroy$))
|
|
27408
|
+
.subscribe(({ targetUrl }) => this.navigateToConfirmedTarget(targetUrl));
|
|
27409
|
+
}
|
|
27410
|
+
shouldIntercept(event) {
|
|
27411
|
+
if (this._confirmedTargetUrl !== undefined && this._confirmedTargetUrl === event.url) {
|
|
27412
|
+
this._confirmedTargetUrl = undefined;
|
|
27413
|
+
return false;
|
|
27414
|
+
}
|
|
27415
|
+
return true;
|
|
27416
|
+
}
|
|
27417
|
+
checkForPendingChanges(event) {
|
|
27418
|
+
return this.formGroupManager.$hasValuesChanged().pipe(take$1(1), map$1(hasChanges => ({ event, hasChanges })));
|
|
27419
|
+
}
|
|
27420
|
+
cancelNavigationAndConfirm(event) {
|
|
27421
|
+
this._bypassInterception = true;
|
|
27422
|
+
void this.router.navigateByUrl(this.router.url, { skipLocationChange: true });
|
|
27423
|
+
return this.confirmationDialog
|
|
27424
|
+
.showDiscardConfirmDialog(this._confirmationMessage, 'page-navigation-confirmation')
|
|
27425
|
+
.pipe(map$1(confirmed => ({ confirmed, targetUrl: event.url })), finalize(() => (this._bypassInterception = false)));
|
|
27426
|
+
}
|
|
27427
|
+
navigateToConfirmedTarget(targetUrl) {
|
|
27428
|
+
this._bypassInterception = false;
|
|
27429
|
+
this._confirmedTargetUrl = targetUrl;
|
|
27430
|
+
void this.router.navigateByUrl(targetUrl);
|
|
27431
|
+
}
|
|
27432
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdPageNavigationInterceptorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
27433
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdPageNavigationInterceptorService });
|
|
27434
|
+
}
|
|
27435
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdPageNavigationInterceptorService, decorators: [{
|
|
27436
|
+
type: Injectable
|
|
27437
|
+
}] });
|
|
27438
|
+
|
|
27312
27439
|
class QdResolverTriggerService {
|
|
27313
27440
|
route = inject(ActivatedRoute, { optional: true });
|
|
27314
27441
|
shouldTriggerResolver(triggerOn) {
|
|
@@ -27358,8 +27485,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
27358
27485
|
class QdPageObjectHeaderComponent {
|
|
27359
27486
|
pageObjectResolver = inject(QD_PAGE_OBJECT_RESOLVER_TOKEN, { optional: true });
|
|
27360
27487
|
formGroupManagerService = inject(QdFormGroupManagerService, { optional: true });
|
|
27488
|
+
navigationInterceptor = inject(QdPageNavigationInterceptorService);
|
|
27361
27489
|
dialogComponent = inject(QdDialogComponent, { optional: true });
|
|
27362
27490
|
dialog = inject(QdDialogService);
|
|
27491
|
+
confirmationDialogService = inject(QdConfirmationDialogOpenerService);
|
|
27363
27492
|
contextService = inject(QdContextService);
|
|
27364
27493
|
resolverTriggerService = inject(QdResolverTriggerService);
|
|
27365
27494
|
pageStoreService = inject(QdPageStoreService);
|
|
@@ -27521,13 +27650,39 @@ class QdPageObjectHeaderComponent {
|
|
|
27521
27650
|
});
|
|
27522
27651
|
}
|
|
27523
27652
|
save() {
|
|
27524
|
-
const
|
|
27653
|
+
const saveAction = this.saveButton;
|
|
27654
|
+
const applySuccess = (captured) => {
|
|
27525
27655
|
this.formGroupManagerService.cancelPendingAsyncValidation();
|
|
27526
27656
|
this.pageStoreService.toggleViewonly(true);
|
|
27527
|
-
|
|
27657
|
+
if (captured) {
|
|
27658
|
+
this.formGroupManagerService.commitBaseline(captured);
|
|
27659
|
+
}
|
|
27660
|
+
else {
|
|
27661
|
+
this.formGroupManagerService.takeFormGroupsSnapshot();
|
|
27662
|
+
}
|
|
27663
|
+
saveAction?.onSuccess?.();
|
|
27528
27664
|
};
|
|
27529
|
-
|
|
27530
|
-
|
|
27665
|
+
if (!saveAction?.handler) {
|
|
27666
|
+
this.navigationInterceptor.executeWithBypass(() => applySuccess(null));
|
|
27667
|
+
return;
|
|
27668
|
+
}
|
|
27669
|
+
const captured = this.formGroupManagerService.captureFormValues();
|
|
27670
|
+
let result;
|
|
27671
|
+
this.navigationInterceptor.executeWithBypass(() => {
|
|
27672
|
+
result = saveAction.handler(this.formGroupManagerService.getAllValues());
|
|
27673
|
+
});
|
|
27674
|
+
if (isObservable(result)) {
|
|
27675
|
+
result.pipe(take(1), takeUntil(this._destroyed$)).subscribe({
|
|
27676
|
+
next: ok => {
|
|
27677
|
+
if (ok)
|
|
27678
|
+
this.navigationInterceptor.executeWithBypass(() => applySuccess(captured));
|
|
27679
|
+
},
|
|
27680
|
+
error: err => console.error('QdPage save action observable errored — baseline not committed. Catch errors via catchError() in your handler.', err)
|
|
27681
|
+
});
|
|
27682
|
+
}
|
|
27683
|
+
else {
|
|
27684
|
+
this.navigationInterceptor.executeWithBypass(() => applySuccess(captured));
|
|
27685
|
+
}
|
|
27531
27686
|
}
|
|
27532
27687
|
changeContext(context, selection, event) {
|
|
27533
27688
|
event.stopPropagation();
|
|
@@ -27555,7 +27710,7 @@ class QdPageObjectHeaderComponent {
|
|
|
27555
27710
|
.subscribe();
|
|
27556
27711
|
}
|
|
27557
27712
|
initContexts() {
|
|
27558
|
-
this.contexts$ = this.contextService.contexts$.pipe(map(contexts => contexts.filter(context => context.selection || this.config.pageType === 'overview')), map(contexts => contexts
|
|
27713
|
+
this.contexts$ = this.contextService.contexts$.pipe(map(contexts => contexts.filter(context => context.selection || this.config.pageType === 'overview')), map(contexts => contexts.map(({ selection, context }) => ({
|
|
27559
27714
|
label: context.label.i18n,
|
|
27560
27715
|
value: Array.isArray(selection?.value)
|
|
27561
27716
|
? selection?.value.filter(item => item !== null && item !== undefined)
|
|
@@ -27566,7 +27721,7 @@ class QdPageObjectHeaderComponent {
|
|
|
27566
27721
|
selection: selection?.value ?? []
|
|
27567
27722
|
}))));
|
|
27568
27723
|
this.contexts$
|
|
27569
|
-
.pipe(takeUntil(this._destroyed$), tap(contexts => (this._availableContexts = contexts
|
|
27724
|
+
.pipe(takeUntil(this._destroyed$), tap(contexts => (this._availableContexts = contexts.length)))
|
|
27570
27725
|
.subscribe();
|
|
27571
27726
|
}
|
|
27572
27727
|
updateCustomActions() {
|
|
@@ -27608,15 +27763,13 @@ class QdPageObjectHeaderComponent {
|
|
|
27608
27763
|
return { actions };
|
|
27609
27764
|
}
|
|
27610
27765
|
openCancelDialog() {
|
|
27611
|
-
this.
|
|
27612
|
-
|
|
27613
|
-
|
|
27614
|
-
|
|
27615
|
-
|
|
27616
|
-
|
|
27617
|
-
|
|
27618
|
-
.subscribe(confirm => {
|
|
27619
|
-
if (confirm) {
|
|
27766
|
+
const cancelConfig = this.config.pageTypeConfig?.cancel;
|
|
27767
|
+
this.confirmationDialogService
|
|
27768
|
+
.showDiscardConfirmDialog(cancelConfig?.confirmationMessage, this.testId + '-cancel-confirmation')
|
|
27769
|
+
.pipe(takeUntil(this._destroyed$))
|
|
27770
|
+
.subscribe(confirmed => {
|
|
27771
|
+
if (confirmed) {
|
|
27772
|
+
cancelConfig?.handler?.();
|
|
27620
27773
|
this.formGroupManagerService.restoreFormGroupsFromSnapshot();
|
|
27621
27774
|
this.pageStoreService.toggleViewonly(true);
|
|
27622
27775
|
}
|
|
@@ -28587,126 +28740,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
28587
28740
|
type: Output
|
|
28588
28741
|
}] } });
|
|
28589
28742
|
|
|
28590
|
-
/**
|
|
28591
|
-
* Intercepts router navigation when unsaved form changes exist on a QdPage.
|
|
28592
|
-
*
|
|
28593
|
-
* Provided per `QdPageComponent`. Activated automatically when the page enters an editable state
|
|
28594
|
-
* (create pages or inspect pages in edit mode). Deactivated when the page returns to view mode.
|
|
28595
|
-
*
|
|
28596
|
-
* #### When navigation is intercepted
|
|
28597
|
-
*
|
|
28598
|
-
* - The user has unsaved form changes (tracked via `QdFormGroupManagerService`).
|
|
28599
|
-
* - A `NavigationStart` event occurs (browser back, shell back button, or programmatic navigation).
|
|
28600
|
-
*
|
|
28601
|
-
* The current navigation is cancelled, and a confirmation dialog is shown. The user can either
|
|
28602
|
-
* discard changes and proceed or cancel and stay on the page.
|
|
28603
|
-
*
|
|
28604
|
-
* #### When navigation is allowed
|
|
28605
|
-
*
|
|
28606
|
-
* - No unsaved changes exist — navigation proceeds silently.
|
|
28607
|
-
* - A framework action (Submit, SaveDraft) wraps its handler via `executeWithBypass()`.
|
|
28608
|
-
* - A confirmed discard sets `allowNextNavigation()` before the cancel handler navigates.
|
|
28609
|
-
* - The page switches to view mode via `deactivate()`.
|
|
28610
|
-
*
|
|
28611
|
-
* Custom actions defined by the application are not bypassed. If a custom action navigates away
|
|
28612
|
-
* while unsaved changes exist, the confirmation dialog is shown.
|
|
28613
|
-
*/
|
|
28614
|
-
class QdPageNavigationInterceptorService {
|
|
28615
|
-
router = inject(Router);
|
|
28616
|
-
formGroupManager = inject(QdFormGroupManagerService);
|
|
28617
|
-
confirmationDialog = inject(QdConfirmationDialogOpenerService);
|
|
28618
|
-
_destroy$ = new Subject();
|
|
28619
|
-
_deactivate$ = new Subject();
|
|
28620
|
-
_bypassInterception = false;
|
|
28621
|
-
_allowedTargetUrls = new Set();
|
|
28622
|
-
_confirmationMessage;
|
|
28623
|
-
ngOnDestroy() {
|
|
28624
|
-
this._allowedTargetUrls.clear();
|
|
28625
|
-
this._destroy$.next();
|
|
28626
|
-
this._destroy$.complete();
|
|
28627
|
-
this._deactivate$.complete();
|
|
28628
|
-
}
|
|
28629
|
-
/**
|
|
28630
|
-
* Starts intercepting navigation events. Replaces any previously active listener.
|
|
28631
|
-
*/
|
|
28632
|
-
activate(confirmationMessage) {
|
|
28633
|
-
this._confirmationMessage = confirmationMessage;
|
|
28634
|
-
this._deactivate$.next();
|
|
28635
|
-
this.listenForUnsavedNavigationAttempts();
|
|
28636
|
-
}
|
|
28637
|
-
/**
|
|
28638
|
-
* Stops intercepting and clears all pending URL bypasses.
|
|
28639
|
-
*/
|
|
28640
|
-
deactivate() {
|
|
28641
|
-
this._deactivate$.next();
|
|
28642
|
-
this._allowedTargetUrls.clear();
|
|
28643
|
-
}
|
|
28644
|
-
/**
|
|
28645
|
-
* Whitelists the next navigation so it bypasses interception.
|
|
28646
|
-
* Without a URL, any next navigation is bypassed (wildcard). With a URL, only that
|
|
28647
|
-
* specific navigation is bypassed — non-matching navigations are still intercepted.
|
|
28648
|
-
*/
|
|
28649
|
-
allowNextNavigation(targetUrl) {
|
|
28650
|
-
this._allowedTargetUrls.add(targetUrl ?? '*');
|
|
28651
|
-
}
|
|
28652
|
-
/**
|
|
28653
|
-
* Executes the callback with interception temporarily disabled.
|
|
28654
|
-
* The callback must navigate synchronously — async navigation after the callback returns
|
|
28655
|
-
* will not be bypassed. This works because Angular's router emits NavigationStart
|
|
28656
|
-
* synchronously within the navigateByUrl() / navigate() call.
|
|
28657
|
-
*/
|
|
28658
|
-
executeWithBypass(fn) {
|
|
28659
|
-
this._bypassInterception = true;
|
|
28660
|
-
try {
|
|
28661
|
-
fn();
|
|
28662
|
-
}
|
|
28663
|
-
finally {
|
|
28664
|
-
this._bypassInterception = false;
|
|
28665
|
-
}
|
|
28666
|
-
}
|
|
28667
|
-
listenForUnsavedNavigationAttempts() {
|
|
28668
|
-
this.router.events
|
|
28669
|
-
.pipe(filter$1((event) => event instanceof NavigationStart), filter$1(() => !this._bypassInterception), filter$1(event => this.shouldIntercept(event)), concatMap$1(event => this.checkForPendingChanges(event)), filter$1(({ hasChanges }) => hasChanges), exhaustMap(({ event }) => this.cancelNavigationAndConfirm(event)), filter$1(({ confirmed }) => confirmed), takeUntil$1(this._deactivate$), takeUntil$1(this._destroy$))
|
|
28670
|
-
.subscribe(({ targetUrl }) => this.navigateToConfirmedTarget(targetUrl));
|
|
28671
|
-
}
|
|
28672
|
-
shouldIntercept(event) {
|
|
28673
|
-
if (this._allowedTargetUrls.has('*')) {
|
|
28674
|
-
this._allowedTargetUrls.clear();
|
|
28675
|
-
return false;
|
|
28676
|
-
}
|
|
28677
|
-
if (this._allowedTargetUrls.has(event.url)) {
|
|
28678
|
-
this._allowedTargetUrls.delete(event.url);
|
|
28679
|
-
return false;
|
|
28680
|
-
}
|
|
28681
|
-
return true;
|
|
28682
|
-
}
|
|
28683
|
-
checkForPendingChanges(event) {
|
|
28684
|
-
return this.formGroupManager.$hasValuesChanged().pipe(take$1(1), map$1(hasChanges => ({ event, hasChanges })));
|
|
28685
|
-
}
|
|
28686
|
-
cancelNavigationAndConfirm(event) {
|
|
28687
|
-
this._bypassInterception = true;
|
|
28688
|
-
void this.router.navigateByUrl(this.router.url, { skipLocationChange: true });
|
|
28689
|
-
return this.confirmationDialog
|
|
28690
|
-
.showCancelConfirmation({ cancel: { confirmationMessage: this._confirmationMessage } })
|
|
28691
|
-
.pipe(map$1(confirmed => ({ confirmed, targetUrl: event.url })), finalize(() => (this._bypassInterception = false)));
|
|
28692
|
-
}
|
|
28693
|
-
navigateToConfirmedTarget(targetUrl) {
|
|
28694
|
-
this._bypassInterception = false;
|
|
28695
|
-
this._allowedTargetUrls.add(targetUrl);
|
|
28696
|
-
void this.router.navigateByUrl(targetUrl);
|
|
28697
|
-
}
|
|
28698
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdPageNavigationInterceptorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
28699
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdPageNavigationInterceptorService });
|
|
28700
|
-
}
|
|
28701
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdPageNavigationInterceptorService, decorators: [{
|
|
28702
|
-
type: Injectable
|
|
28703
|
-
}] });
|
|
28704
|
-
|
|
28705
28743
|
class QdPageSubmitActionService {
|
|
28706
28744
|
footerService = inject(QdPageFooterService);
|
|
28707
28745
|
formGroupManagerService = inject(QdFormGroupManagerService);
|
|
28746
|
+
navigationInterceptor = inject(QdPageNavigationInterceptorService);
|
|
28708
28747
|
_labelI18n = 'i18n.qd.page.footer.submit';
|
|
28709
|
-
|
|
28748
|
+
_submitAction;
|
|
28710
28749
|
_isVisible = true;
|
|
28711
28750
|
_destroyed$ = new Subject();
|
|
28712
28751
|
_cancelTrackFormValidity$ = new Subject();
|
|
@@ -28720,9 +28759,9 @@ class QdPageSubmitActionService {
|
|
|
28720
28759
|
this._isVisible = isVisible;
|
|
28721
28760
|
this.configureSubmitAction(pageTypeConfig.submit);
|
|
28722
28761
|
}
|
|
28723
|
-
configureSubmitAction(
|
|
28724
|
-
this._labelI18n =
|
|
28725
|
-
this.
|
|
28762
|
+
configureSubmitAction(action) {
|
|
28763
|
+
this._labelI18n = action.label?.i18n || 'i18n.qd.page.footer.submit';
|
|
28764
|
+
this._submitAction = action;
|
|
28726
28765
|
this.registerSubmitAction();
|
|
28727
28766
|
this.trackFormValidity();
|
|
28728
28767
|
}
|
|
@@ -28732,7 +28771,7 @@ class QdPageSubmitActionService {
|
|
|
28732
28771
|
key: 'submit',
|
|
28733
28772
|
action: {
|
|
28734
28773
|
titleI18n: this._labelI18n,
|
|
28735
|
-
handler: this.
|
|
28774
|
+
handler: () => this.executeSubmit(),
|
|
28736
28775
|
isDisabled: true,
|
|
28737
28776
|
isVisible: this._isVisible,
|
|
28738
28777
|
type: QdFooterActionType.Primary
|
|
@@ -28740,12 +28779,33 @@ class QdPageSubmitActionService {
|
|
|
28740
28779
|
}
|
|
28741
28780
|
]);
|
|
28742
28781
|
}
|
|
28743
|
-
|
|
28744
|
-
|
|
28745
|
-
|
|
28746
|
-
|
|
28747
|
-
|
|
28748
|
-
|
|
28782
|
+
executeSubmit() {
|
|
28783
|
+
const action = this._submitAction;
|
|
28784
|
+
if (!action?.handler)
|
|
28785
|
+
return;
|
|
28786
|
+
const values = this.formGroupManagerService.hasFormGroups()
|
|
28787
|
+
? this.formGroupManagerService.getAllValues()
|
|
28788
|
+
: undefined;
|
|
28789
|
+
const captured = this.formGroupManagerService.captureFormValues();
|
|
28790
|
+
let result;
|
|
28791
|
+
this.navigationInterceptor.executeWithBypass(() => {
|
|
28792
|
+
result = action.handler(values);
|
|
28793
|
+
});
|
|
28794
|
+
if (isObservable(result)) {
|
|
28795
|
+
result.pipe(take(1), takeUntil(this._destroyed$)).subscribe({
|
|
28796
|
+
next: ok => {
|
|
28797
|
+
if (!ok)
|
|
28798
|
+
return;
|
|
28799
|
+
this.formGroupManagerService.commitBaseline(captured);
|
|
28800
|
+
this.navigationInterceptor.executeWithBypass(() => action.onSuccess?.());
|
|
28801
|
+
},
|
|
28802
|
+
error: err => console.error('QdPage commit action observable errored — baseline not committed. Catch errors via catchError() in your handler.', err)
|
|
28803
|
+
});
|
|
28804
|
+
}
|
|
28805
|
+
else {
|
|
28806
|
+
this.formGroupManagerService.commitBaseline(captured);
|
|
28807
|
+
this.navigationInterceptor.executeWithBypass(() => action.onSuccess?.());
|
|
28808
|
+
}
|
|
28749
28809
|
}
|
|
28750
28810
|
trackFormValidity() {
|
|
28751
28811
|
this._cancelTrackFormValidity$.next();
|
|
@@ -28760,7 +28820,7 @@ class QdPageSubmitActionService {
|
|
|
28760
28820
|
key: 'submit',
|
|
28761
28821
|
action: {
|
|
28762
28822
|
titleI18n: this._labelI18n,
|
|
28763
|
-
handler: this.
|
|
28823
|
+
handler: () => this.executeSubmit(),
|
|
28764
28824
|
isDisabled: !isValid,
|
|
28765
28825
|
isVisible: this._isVisible,
|
|
28766
28826
|
type: QdFooterActionType.Primary
|
|
@@ -28884,7 +28944,15 @@ const SAFE_BOTTOM_OFFSET_PX = 64;
|
|
|
28884
28944
|
* handler: () => handleCancel()
|
|
28885
28945
|
* },
|
|
28886
28946
|
* save: {
|
|
28887
|
-
* handler: (
|
|
28947
|
+
* handler: () => saveApi.save(form.value).pipe(
|
|
28948
|
+
* tap(result => notifications.success('Saved')),
|
|
28949
|
+
* map(() => true),
|
|
28950
|
+
* catchError(err => {
|
|
28951
|
+
* notifications.showError(err);
|
|
28952
|
+
* return of(false);
|
|
28953
|
+
* })
|
|
28954
|
+
* ),
|
|
28955
|
+
* onSuccess: () => router.navigate(['/overview'])
|
|
28888
28956
|
* }
|
|
28889
28957
|
* }
|
|
28890
28958
|
* };
|
|
@@ -29002,7 +29070,8 @@ const SAFE_BOTTOM_OFFSET_PX = 64;
|
|
|
29002
29070
|
* pageType: 'create',
|
|
29003
29071
|
* pageTypeConfig: {
|
|
29004
29072
|
* submit: {
|
|
29005
|
-
* handler: (formValues) =>
|
|
29073
|
+
* handler: (formValues) => createApi.create(formValues).pipe(map(() => true)),
|
|
29074
|
+
* onSuccess: () => router.navigate(['/items'])
|
|
29006
29075
|
* }
|
|
29007
29076
|
* }
|
|
29008
29077
|
* };
|
|
@@ -29095,7 +29164,14 @@ const SAFE_BOTTOM_OFFSET_PX = 64;
|
|
|
29095
29164
|
* handler: () => handleCancel()
|
|
29096
29165
|
* },
|
|
29097
29166
|
* save: {
|
|
29098
|
-
* handler: (formValues) =>
|
|
29167
|
+
* handler: (formValues) => saveApi.save(formValues).pipe(
|
|
29168
|
+
* map(() => true),
|
|
29169
|
+
* catchError(err => {
|
|
29170
|
+
* notifications.showError(err);
|
|
29171
|
+
* return of(false);
|
|
29172
|
+
* })
|
|
29173
|
+
* ),
|
|
29174
|
+
* onSuccess: () => router.navigate(['/overview'])
|
|
29099
29175
|
* }
|
|
29100
29176
|
* }
|
|
29101
29177
|
* };
|
|
@@ -29164,6 +29240,7 @@ class QdPageComponent {
|
|
|
29164
29240
|
bottomOffset$ = inject(QD_SAFE_BOTTOM_OFFSET, { optional: true });
|
|
29165
29241
|
dialogRef = inject(DialogRef, { optional: true });
|
|
29166
29242
|
navigationInterceptor = inject(QdPageNavigationInterceptorService);
|
|
29243
|
+
confirmationDialogService = inject(QdConfirmationDialogOpenerService);
|
|
29167
29244
|
/**
|
|
29168
29245
|
* This property defines the configuration for the QdPage component, including the page type,
|
|
29169
29246
|
* title, and specific configurations for each type of page.
|
|
@@ -29264,11 +29341,14 @@ class QdPageComponent {
|
|
|
29264
29341
|
const action = pageTypeConfig[actionKey];
|
|
29265
29342
|
if (!action)
|
|
29266
29343
|
continue;
|
|
29344
|
+
const handler = actionKey === 'cancel'
|
|
29345
|
+
? () => action.handler()
|
|
29346
|
+
: this.generateCommitActionHandler(action);
|
|
29267
29347
|
actions.push({
|
|
29268
29348
|
actionKey,
|
|
29269
29349
|
partialAction: {
|
|
29270
29350
|
...(action?.label?.i18n ? { titleI18n: action.label.i18n } : {}),
|
|
29271
|
-
handler
|
|
29351
|
+
handler
|
|
29272
29352
|
}
|
|
29273
29353
|
});
|
|
29274
29354
|
}
|
|
@@ -29285,11 +29365,7 @@ class QdPageComponent {
|
|
|
29285
29365
|
partialAction: {
|
|
29286
29366
|
handler: hasChanged
|
|
29287
29367
|
? () => this.setupCancelConfirmation()
|
|
29288
|
-
: () =>
|
|
29289
|
-
this.navigationInterceptor.executeWithBypass(() => {
|
|
29290
|
-
this.config?.pageTypeConfig?.cancel?.handler();
|
|
29291
|
-
});
|
|
29292
|
-
}
|
|
29368
|
+
: () => this.config?.pageTypeConfig?.cancel?.handler()
|
|
29293
29369
|
}
|
|
29294
29370
|
}
|
|
29295
29371
|
]);
|
|
@@ -29301,9 +29377,9 @@ class QdPageComponent {
|
|
|
29301
29377
|
{
|
|
29302
29378
|
key: 'saveDraft',
|
|
29303
29379
|
action: {
|
|
29304
|
-
titleI18n: pageTypeConfig.saveDraft
|
|
29380
|
+
titleI18n: pageTypeConfig.saveDraft.label?.i18n ?? 'i18n.qd.page.footer.saveDraft',
|
|
29305
29381
|
type: QdFooterActionType.Secondary,
|
|
29306
|
-
handler: this.
|
|
29382
|
+
handler: this.generateCommitActionHandler(pageTypeConfig.saveDraft),
|
|
29307
29383
|
isVisible: true,
|
|
29308
29384
|
isDisabled: false
|
|
29309
29385
|
}
|
|
@@ -29330,30 +29406,49 @@ class QdPageComponent {
|
|
|
29330
29406
|
if (this._isInitialized)
|
|
29331
29407
|
this.operationModeChanged.emit(mode);
|
|
29332
29408
|
}
|
|
29333
|
-
|
|
29409
|
+
generateCommitActionHandler(action) {
|
|
29334
29410
|
return (...args) => {
|
|
29335
|
-
if (!handler)
|
|
29411
|
+
if (!action?.handler)
|
|
29336
29412
|
return;
|
|
29337
29413
|
const values = this.formGroupManagerService.hasFormGroups() ? this.formGroupManagerService.getAllValues() : args;
|
|
29338
|
-
this.
|
|
29414
|
+
const captured = this.formGroupManagerService.captureFormValues();
|
|
29415
|
+
let result;
|
|
29416
|
+
this.navigationInterceptor.executeWithBypass(() => {
|
|
29417
|
+
result = action.handler(values);
|
|
29418
|
+
});
|
|
29419
|
+
if (isObservable(result)) {
|
|
29420
|
+
result.pipe(take(1), takeUntil(this._destroyed$)).subscribe({
|
|
29421
|
+
next: ok => {
|
|
29422
|
+
if (!ok)
|
|
29423
|
+
return;
|
|
29424
|
+
this.formGroupManagerService.commitBaseline(captured);
|
|
29425
|
+
this.navigationInterceptor.executeWithBypass(() => action.onSuccess?.());
|
|
29426
|
+
},
|
|
29427
|
+
error: err => console.error('QdPage commit action observable errored — baseline not committed. Catch errors via catchError() in your handler.', err)
|
|
29428
|
+
});
|
|
29429
|
+
}
|
|
29430
|
+
else {
|
|
29431
|
+
this.formGroupManagerService.commitBaseline(captured);
|
|
29432
|
+
this.navigationInterceptor.executeWithBypass(() => action.onSuccess?.());
|
|
29433
|
+
}
|
|
29339
29434
|
};
|
|
29340
29435
|
}
|
|
29341
29436
|
setupCancelConfirmation() {
|
|
29342
|
-
this.
|
|
29343
|
-
|
|
29344
|
-
|
|
29345
|
-
|
|
29346
|
-
|
|
29347
|
-
|
|
29348
|
-
|
|
29349
|
-
|
|
29437
|
+
const cancelConfig = this.config.pageTypeConfig?.cancel;
|
|
29438
|
+
this.confirmationDialogService
|
|
29439
|
+
.showDiscardConfirmDialog(cancelConfig?.confirmationMessage, this.testId + '-cancel-confirmation')
|
|
29440
|
+
.pipe(filter$1(result => result), takeUntil(this._destroyed$))
|
|
29441
|
+
.subscribe(() => {
|
|
29442
|
+
this.formGroupManagerService.restoreFormGroupsFromSnapshot();
|
|
29443
|
+
cancelConfig?.handler?.();
|
|
29444
|
+
});
|
|
29350
29445
|
}
|
|
29351
29446
|
initSubmitValidation() {
|
|
29352
29447
|
this._cancelSubmitValidation$.next();
|
|
29353
29448
|
this.formGroupManagerService
|
|
29354
29449
|
.$areFormGroupsValid()
|
|
29355
29450
|
.pipe(takeUntil(this._cancelSubmitValidation$), takeUntil(this._destroyed$), tap(isValid => {
|
|
29356
|
-
const submitDisabledInfoText = this.config.
|
|
29451
|
+
const submitDisabledInfoText = this.config.pageTypeConfig?.submit?.disabledInfo;
|
|
29357
29452
|
this.footerService.updateActions([
|
|
29358
29453
|
{
|
|
29359
29454
|
actionKey: 'submit',
|
|
@@ -29545,7 +29640,6 @@ class QdPageModule {
|
|
|
29545
29640
|
QdConnectFormStateToPageDirective,
|
|
29546
29641
|
QdPageFooterCustomContentDirective,
|
|
29547
29642
|
QdContextSelectDialogComponent,
|
|
29548
|
-
QdPageCancelConfirmationDialogComponent,
|
|
29549
29643
|
QdPageInfoBannerComponent], imports: [CommonModule,
|
|
29550
29644
|
TranslateModule,
|
|
29551
29645
|
QdButtonModule,
|
|
@@ -29630,7 +29724,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
29630
29724
|
QdConnectFormStateToPageDirective,
|
|
29631
29725
|
QdPageFooterCustomContentDirective,
|
|
29632
29726
|
QdContextSelectDialogComponent,
|
|
29633
|
-
QdPageCancelConfirmationDialogComponent,
|
|
29634
29727
|
QdPageInfoBannerComponent
|
|
29635
29728
|
],
|
|
29636
29729
|
exports: [
|
|
@@ -32486,6 +32579,7 @@ class QdQuickEditComponent {
|
|
|
32486
32579
|
eventBrokerService = inject(QdEventBrokerService, { optional: true });
|
|
32487
32580
|
changeDetectorRef = inject(ChangeDetectorRef);
|
|
32488
32581
|
controlContainer = inject(ControlContainer, { optional: true, self: true });
|
|
32582
|
+
confirmationDialogService = inject(QdConfirmationDialogOpenerService);
|
|
32489
32583
|
/**
|
|
32490
32584
|
* Configuration of the QuickEdit. The generic type specifies the column definition. <br />
|
|
32491
32585
|
*
|
|
@@ -32634,6 +32728,16 @@ class QdQuickEditComponent {
|
|
|
32634
32728
|
window.setTimeout(() => this.focusFirstControl());
|
|
32635
32729
|
}
|
|
32636
32730
|
removeRow(index) {
|
|
32731
|
+
if (this.config.removeConfirmationMessage) {
|
|
32732
|
+
this.confirmationDialogService
|
|
32733
|
+
.showConfirmDialog({ message: this.config.removeConfirmationMessage }, (this.testId ?? 'quick-edit') + '-remove-confirmation')
|
|
32734
|
+
.pipe(filter$1(confirmed => confirmed))
|
|
32735
|
+
.subscribe(() => this.executeRemoveRow(index));
|
|
32736
|
+
return;
|
|
32737
|
+
}
|
|
32738
|
+
this.executeRemoveRow(index);
|
|
32739
|
+
}
|
|
32740
|
+
executeRemoveRow(index) {
|
|
32637
32741
|
this.redrawOnNextChange();
|
|
32638
32742
|
if (this.controlContainer) {
|
|
32639
32743
|
this.controlContainer.control.removeAt(index);
|