@quadrel-enterprise-ui/framework 20.9.1-beta.137.1 → 20.10.0-beta.139.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.
@@ -27062,6 +27062,43 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
27062
27062
  type: Input
27063
27063
  }] } });
27064
27064
 
27065
+ class QdPageCommitActionExecutor {
27066
+ static execute(action, values, context) {
27067
+ const { formGroupManager, navigationInterceptor, destroyed$, onAfterSnapshot } = context;
27068
+ const captured = formGroupManager.captureFormValues();
27069
+ let result$;
27070
+ navigationInterceptor.executeWithBypass(() => {
27071
+ const handlerResult = action.handler(values);
27072
+ if (isObservable(handlerResult))
27073
+ result$ = handlerResult;
27074
+ });
27075
+ const applySuccess = () => {
27076
+ formGroupManager.setFormGroupsSnapshot(captured);
27077
+ navigationInterceptor.executeWithBypass(() => {
27078
+ onAfterSnapshot?.();
27079
+ try {
27080
+ action.onSuccess?.();
27081
+ }
27082
+ catch (err) {
27083
+ console.error('QD-UI | QdPage - onSuccess callback threw after form was marked as saved.', err);
27084
+ }
27085
+ });
27086
+ };
27087
+ if (result$) {
27088
+ result$.pipe(take(1), takeUntil(destroyed$)).subscribe({
27089
+ next: ok => {
27090
+ if (ok)
27091
+ applySuccess();
27092
+ },
27093
+ error: err => console.error('QD-UI | QdPage - Commit action observable errored — form was not marked as saved. Catch errors via catchError() in your handler.', err)
27094
+ });
27095
+ }
27096
+ else {
27097
+ applySuccess();
27098
+ }
27099
+ }
27100
+ }
27101
+
27065
27102
  /**
27066
27103
  * The QdFormGroupManagerService provides centralized registration, snapshotting, and value tracking
27067
27104
  * for multiple Angular `FormGroup` instances. It supports efficient state restoration, including dynamic
@@ -27180,7 +27217,7 @@ class QdFormGroupManagerService {
27180
27217
  * Captures a deep-cloned snapshot of all current form values without mutating internal state.
27181
27218
  *
27182
27219
  * 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
27220
+ * so the snapshot can later be set to exactly those values — even if the user edits the form
27184
27221
  * while an async commit action is pending.
27185
27222
  *
27186
27223
  * Throws if any form value is not structured-cloneable (functions, symbols, DOM nodes).
@@ -27192,7 +27229,7 @@ class QdFormGroupManagerService {
27192
27229
  captured.set(key, structuredClone(fg.getRawValue()));
27193
27230
  }
27194
27231
  catch (err) {
27195
- throw new Error(`QdFormGroupManagerService: captureFormValues() failed for group "${key}". ` +
27232
+ throw new Error(`QD-UI | QdFormGroupManager - captureFormValues() failed for group "${key}". ` +
27196
27233
  `Form values must be structured-cloneable. Non-cloneable values like functions, ` +
27197
27234
  `symbols, or DOM nodes are not supported. Original error: ${String(err)}`);
27198
27235
  }
@@ -27200,13 +27237,13 @@ class QdFormGroupManagerService {
27200
27237
  return captured;
27201
27238
  }
27202
27239
  /**
27203
- * Replaces the internal baseline snapshot with the provided values.
27240
+ * Replaces the internal saved snapshot with the provided values.
27204
27241
  *
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.
27242
+ * Intended to be paired with `captureFormValues()` so that the snapshot can be set to the
27243
+ * values present when a commit action was initiated — independent of whether the user edited
27244
+ * the form in the meantime.
27208
27245
  */
27209
- commitBaseline(values) {
27246
+ setFormGroupsSnapshot(values) {
27210
27247
  values.forEach((snapshot, key) => this._formGroupsSnapshot.set(key, snapshot));
27211
27248
  }
27212
27249
  restoreFormGroupsFromSnapshot() {
@@ -27218,20 +27255,6 @@ class QdFormGroupManagerService {
27218
27255
  });
27219
27256
  this.cancelPendingAsyncValidation();
27220
27257
  }
27221
- restoreFormGroup(fg, snapshot) {
27222
- Object.entries(fg.controls).forEach(([ctrlKey, ctrl]) => {
27223
- const newValue = snapshot[ctrlKey];
27224
- if (ctrl instanceof FormArray && Array.isArray(newValue)) {
27225
- this.resetFormArrayToValues(ctrl, newValue);
27226
- }
27227
- else if (ctrl instanceof FormGroup && newValue && typeof newValue === 'object') {
27228
- this.restoreFormGroup(ctrl, newValue);
27229
- }
27230
- else {
27231
- ctrl.reset(newValue);
27232
- }
27233
- });
27234
- }
27235
27258
  /**
27236
27259
  * Cancels any in-flight async validators on all registered form groups.
27237
27260
  *
@@ -27255,6 +27278,20 @@ class QdFormGroupManagerService {
27255
27278
  }
27256
27279
  });
27257
27280
  }
27281
+ restoreFormGroup(fg, snapshot) {
27282
+ Object.entries(fg.controls).forEach(([ctrlKey, ctrl]) => {
27283
+ const newValue = snapshot[ctrlKey];
27284
+ if (ctrl instanceof FormArray && Array.isArray(newValue)) {
27285
+ this.resetFormArrayToValues(ctrl, newValue);
27286
+ }
27287
+ else if (ctrl instanceof FormGroup && newValue && typeof newValue === 'object') {
27288
+ this.restoreFormGroup(ctrl, newValue);
27289
+ }
27290
+ else {
27291
+ ctrl.reset(newValue);
27292
+ }
27293
+ });
27294
+ }
27258
27295
  collectPendingControls(control) {
27259
27296
  const result = [];
27260
27297
  if (control instanceof FormGroup) {
@@ -27336,14 +27373,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
27336
27373
  *
27337
27374
  * #### When navigation is allowed
27338
27375
  *
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).
27376
+ * - No unsaved changes exist — the form is either pristine or the framework has updated the
27377
+ * saved snapshot after a successful commit action (Submit, Save, SaveDraft).
27341
27378
  * - The page switches to view mode via `deactivate()`.
27342
27379
  *
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.
27380
+ * The service has no concept of "pending actions" or bypass windows. Framework actions update the
27381
+ * saved snapshot directly via `QdFormGroupManagerService.setFormGroupsSnapshot(...)`; cancel-discard
27382
+ * flows reset the form to the saved snapshot via `restoreFormGroupsFromSnapshot()`. Either way, the
27383
+ * interceptor only observes the resulting form state — there is no time window where a bypass is active.
27347
27384
  */
27348
27385
  class QdPageNavigationInterceptorService {
27349
27386
  router = inject(Router);
@@ -27651,38 +27688,17 @@ class QdPageObjectHeaderComponent {
27651
27688
  }
27652
27689
  save() {
27653
27690
  const saveAction = this.saveButton;
27654
- const applySuccess = (captured) => {
27655
- this.formGroupManagerService.cancelPendingAsyncValidation();
27656
- this.pageStoreService.toggleViewonly(true);
27657
- if (captured) {
27658
- this.formGroupManagerService.commitBaseline(captured);
27659
- }
27660
- else {
27661
- this.formGroupManagerService.takeFormGroupsSnapshot();
27662
- }
27663
- saveAction?.onSuccess?.();
27664
- };
27665
- if (!saveAction?.handler) {
27666
- this.navigationInterceptor.executeWithBypass(() => applySuccess(null));
27691
+ if (!saveAction)
27667
27692
  return;
27668
- }
27669
- const captured = this.formGroupManagerService.captureFormValues();
27670
- let result;
27671
- this.navigationInterceptor.executeWithBypass(() => {
27672
- result = saveAction.handler(this.formGroupManagerService.getAllValues());
27693
+ QdPageCommitActionExecutor.execute(saveAction, this.formGroupManagerService.getAllValues(), {
27694
+ formGroupManager: this.formGroupManagerService,
27695
+ navigationInterceptor: this.navigationInterceptor,
27696
+ destroyed$: this._destroyed$,
27697
+ onAfterSnapshot: () => {
27698
+ this.formGroupManagerService.cancelPendingAsyncValidation();
27699
+ this.pageStoreService.toggleViewonly(true);
27700
+ }
27673
27701
  });
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
- }
27686
27702
  }
27687
27703
  changeContext(context, selection, event) {
27688
27704
  event.stopPropagation();
@@ -28771,7 +28787,7 @@ class QdPageSubmitActionService {
28771
28787
  key: 'submit',
28772
28788
  action: {
28773
28789
  titleI18n: this._labelI18n,
28774
- handler: () => this.executeSubmit(),
28790
+ handler: (...args) => this.executeSubmit(...args),
28775
28791
  isDisabled: true,
28776
28792
  isVisible: this._isVisible,
28777
28793
  type: QdFooterActionType.Primary
@@ -28779,33 +28795,16 @@ class QdPageSubmitActionService {
28779
28795
  }
28780
28796
  ]);
28781
28797
  }
28782
- executeSubmit() {
28798
+ executeSubmit(...args) {
28783
28799
  const action = this._submitAction;
28784
- if (!action?.handler)
28800
+ if (!action)
28785
28801
  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);
28802
+ const values = this.formGroupManagerService.hasFormGroups() ? this.formGroupManagerService.getAllValues() : args;
28803
+ QdPageCommitActionExecutor.execute(action, values, {
28804
+ formGroupManager: this.formGroupManagerService,
28805
+ navigationInterceptor: this.navigationInterceptor,
28806
+ destroyed$: this._destroyed$
28793
28807
  });
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
- }
28809
28808
  }
28810
28809
  trackFormValidity() {
28811
28810
  this._cancelTrackFormValidity$.next();
@@ -28820,7 +28819,7 @@ class QdPageSubmitActionService {
28820
28819
  key: 'submit',
28821
28820
  action: {
28822
28821
  titleI18n: this._labelI18n,
28823
- handler: () => this.executeSubmit(),
28822
+ handler: (...args) => this.executeSubmit(...args),
28824
28823
  isDisabled: !isValid,
28825
28824
  isVisible: this._isVisible,
28826
28825
  type: QdFooterActionType.Primary
@@ -29315,7 +29314,7 @@ class QdPageComponent {
29315
29314
  if (this.config.pageType === 'create' && this.config?.pageTypeConfig?.cancel !== undefined)
29316
29315
  this.handleCancelActionWithFormChanges();
29317
29316
  if (this.config.pageType === 'create' && this.config?.pageTypeConfig?.saveDraft !== undefined)
29318
- this.initSaveDraftFooterAction();
29317
+ this.initSaveDraftFooterAction(this.config.pageTypeConfig.saveDraft);
29319
29318
  if (this.config.pageType === 'inspect')
29320
29319
  this.pageStoreService.isViewonly$
29321
29320
  .pipe(takeUntil(this._destroyed$))
@@ -29371,15 +29370,14 @@ class QdPageComponent {
29371
29370
  ]);
29372
29371
  });
29373
29372
  }
29374
- initSaveDraftFooterAction() {
29375
- const pageTypeConfig = this.config.pageTypeConfig;
29373
+ initSaveDraftFooterAction(saveDraft) {
29376
29374
  this.footerService.setActions([
29377
29375
  {
29378
29376
  key: 'saveDraft',
29379
29377
  action: {
29380
- titleI18n: pageTypeConfig.saveDraft.label?.i18n ?? 'i18n.qd.page.footer.saveDraft',
29378
+ titleI18n: saveDraft.label?.i18n ?? 'i18n.qd.page.footer.saveDraft',
29381
29379
  type: QdFooterActionType.Secondary,
29382
- handler: this.generateCommitActionHandler(pageTypeConfig.saveDraft),
29380
+ handler: this.generateCommitActionHandler(saveDraft),
29383
29381
  isVisible: true,
29384
29382
  isDisabled: false
29385
29383
  }
@@ -29408,29 +29406,12 @@ class QdPageComponent {
29408
29406
  }
29409
29407
  generateCommitActionHandler(action) {
29410
29408
  return (...args) => {
29411
- if (!action?.handler)
29412
- return;
29413
29409
  const values = this.formGroupManagerService.hasFormGroups() ? this.formGroupManagerService.getAllValues() : args;
29414
- const captured = this.formGroupManagerService.captureFormValues();
29415
- let result;
29416
- this.navigationInterceptor.executeWithBypass(() => {
29417
- result = action.handler(values);
29410
+ QdPageCommitActionExecutor.execute(action, values, {
29411
+ formGroupManager: this.formGroupManagerService,
29412
+ navigationInterceptor: this.navigationInterceptor,
29413
+ destroyed$: this._destroyed$
29418
29414
  });
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
- }
29434
29415
  };
29435
29416
  }
29436
29417
  setupCancelConfirmation() {
@@ -32728,9 +32709,11 @@ class QdQuickEditComponent {
32728
32709
  window.setTimeout(() => this.focusFirstControl());
32729
32710
  }
32730
32711
  removeRow(index) {
32731
- if (this.config.removeConfirmationMessage) {
32712
+ const { hasRemoveConfirmation, removeConfirmationMessage } = this.config;
32713
+ if (hasRemoveConfirmation || removeConfirmationMessage) {
32714
+ const message = removeConfirmationMessage ?? { i18n: 'i18n.qd.quick.edit.removeConfirmation.message' };
32732
32715
  this.confirmationDialogService
32733
- .showConfirmDialog({ message: this.config.removeConfirmationMessage }, (this.testId ?? 'quick-edit') + '-remove-confirmation')
32716
+ .showConfirmDialog({ message }, (this.testId ?? 'quick-edit') + '-remove-confirmation')
32734
32717
  .pipe(filter$1(confirmed => confirmed))
32735
32718
  .subscribe(() => this.executeRemoveRow(index));
32736
32719
  return;