@acorex/platform 21.0.0-next.71 → 21.0.0-next.73
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/contracts/README.md +3 -0
- package/fesm2022/acorex-platform-auth.mjs +82 -60
- package/fesm2022/acorex-platform-auth.mjs.map +1 -1
- package/fesm2022/{acorex-platform-common-common-settings.provider-Bi1RYif5.mjs → acorex-platform-common-common-settings.provider-Ytey9uhY.mjs} +15 -1
- package/fesm2022/acorex-platform-common-common-settings.provider-Ytey9uhY.mjs.map +1 -0
- package/fesm2022/acorex-platform-common.mjs +3796 -1677
- package/fesm2022/acorex-platform-common.mjs.map +1 -1
- package/fesm2022/acorex-platform-contracts.mjs +10 -0
- package/fesm2022/acorex-platform-contracts.mjs.map +1 -0
- package/fesm2022/acorex-platform-core.mjs +1126 -114
- package/fesm2022/acorex-platform-core.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-builder.mjs +56 -170
- package/fesm2022/acorex-platform-layout-builder.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-components.mjs +254 -53
- package/fesm2022/acorex-platform-layout-components.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-designer.mjs +199 -126
- package/fesm2022/acorex-platform-layout-designer.mjs.map +1 -1
- package/fesm2022/{acorex-platform-layout-entity-attachments-page.component-D8iQnT-R.mjs → acorex-platform-layout-entity-attachments-page.component-B0EkdqvH.mjs} +6 -1
- package/fesm2022/acorex-platform-layout-entity-attachments-page.component-B0EkdqvH.mjs.map +1 -0
- package/fesm2022/acorex-platform-layout-entity.mjs +403 -460
- package/fesm2022/acorex-platform-layout-entity.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-views.mjs +675 -301
- package/fesm2022/acorex-platform-layout-views.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-widget-core.mjs +126 -75
- package/fesm2022/acorex-platform-layout-widget-core.mjs.map +1 -1
- package/fesm2022/{acorex-platform-layout-widgets-tabular-data-edit-popup.component-BcpRkpJp.mjs → acorex-platform-layout-widgets-tabular-data-edit-popup.component-DjpZU6gz.mjs} +2 -2
- package/fesm2022/{acorex-platform-layout-widgets-tabular-data-edit-popup.component-BcpRkpJp.mjs.map → acorex-platform-layout-widgets-tabular-data-edit-popup.component-DjpZU6gz.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-layout-widgets-tabular-data-view-popup.component-DQtK4lxl.mjs → acorex-platform-layout-widgets-tabular-data-view-popup.component-gX-3Kx9I.mjs} +2 -2
- package/fesm2022/{acorex-platform-layout-widgets-tabular-data-view-popup.component-DQtK4lxl.mjs.map → acorex-platform-layout-widgets-tabular-data-view-popup.component-gX-3Kx9I.mjs.map} +1 -1
- package/fesm2022/acorex-platform-layout-widgets.mjs +450 -750
- package/fesm2022/acorex-platform-layout-widgets.mjs.map +1 -1
- package/fesm2022/acorex-platform-themes-default-error-401.component-B1nsdpTY.mjs +48 -0
- package/fesm2022/acorex-platform-themes-default-error-401.component-B1nsdpTY.mjs.map +1 -0
- package/fesm2022/acorex-platform-themes-default-error-404.component-D4UvRe8u.mjs +42 -0
- package/fesm2022/acorex-platform-themes-default-error-404.component-D4UvRe8u.mjs.map +1 -0
- package/fesm2022/acorex-platform-themes-default.mjs +79 -35
- package/fesm2022/acorex-platform-themes-default.mjs.map +1 -1
- package/fesm2022/acorex-platform-themes-shared-settings.provider-BjuzSe0T.mjs.map +1 -1
- package/fesm2022/acorex-platform-themes-shared.mjs +3 -0
- package/fesm2022/acorex-platform-themes-shared.mjs.map +1 -1
- package/fesm2022/acorex-platform-workflow.mjs +57 -54
- package/fesm2022/acorex-platform-workflow.mjs.map +1 -1
- package/package.json +5 -1
- package/types/acorex-platform-auth.d.ts +31 -22
- package/types/acorex-platform-common.d.ts +892 -259
- package/types/acorex-platform-contracts.d.ts +39 -0
- package/types/acorex-platform-core.d.ts +291 -47
- package/types/acorex-platform-layout-builder.d.ts +10 -22
- package/types/acorex-platform-layout-components.d.ts +86 -14
- package/types/acorex-platform-layout-entity.d.ts +218 -212
- package/types/acorex-platform-layout-views.d.ts +125 -67
- package/types/acorex-platform-layout-widget-core.d.ts +56 -62
- package/types/acorex-platform-layout-widgets.d.ts +78 -65
- package/types/acorex-platform-themes-default.d.ts +14 -4
- package/fesm2022/acorex-platform-common-common-settings.provider-Bi1RYif5.mjs.map +0 -1
- package/fesm2022/acorex-platform-layout-entity-attachments-page.component-D8iQnT-R.mjs.map +0 -1
- package/fesm2022/acorex-platform-themes-default-error-401.component-C7EYJzSr.mjs +0 -31
- package/fesm2022/acorex-platform-themes-default-error-401.component-C7EYJzSr.mjs.map +0 -1
- package/fesm2022/acorex-platform-themes-default-error-404.component-7MVLMwIa.mjs +0 -25
- package/fesm2022/acorex-platform-themes-default-error-404.component-7MVLMwIa.mjs.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { signal, computed, Injectable, InjectionToken, inject, ElementRef, effect, untracked, EventEmitter, Injector, ChangeDetectorRef, ViewChild, Input, Output, ChangeDetectionStrategy, Component, input, output, ViewContainerRef, Directive, NgModule } from '@angular/core';
|
|
3
3
|
import { convertArrayToDataSource, AXDataSource, AX_STYLE_COLOR_TYPES, AX_STYLE_LOOK_TYPES } from '@acorex/cdk/common';
|
|
4
|
-
import { AXPContextStore, AXPDataSourceDefinitionProviderService, extractValue, AXPExpressionEvaluatorService, getSmart } from '@acorex/platform/core';
|
|
4
|
+
import { AXPContextStore, isSelectionValueEqual, isFormValueEqual, AXPDataSourceDefinitionProviderService, extractValue, AXPExpressionEvaluatorService, getSmart } from '@acorex/platform/core';
|
|
5
5
|
export { normalizeDefinitionCategories } from '@acorex/platform/core';
|
|
6
6
|
import { set, merge, cloneDeep, isNil, get, isEqual, isUndefined, isObjectLike, sum, isEmpty, isString } from 'lodash-es';
|
|
7
7
|
import { Subject, BehaviorSubject, filter } from 'rxjs';
|
|
@@ -65,7 +65,6 @@ class AXPWidgetCoreService {
|
|
|
65
65
|
return [AXPPageStatus.Processing, AXPPageStatus.Submitting, AXPPageStatus.Rendering].includes(this.status());
|
|
66
66
|
}, ...(ngDevMode ? [{ debugName: "isBusy" }] : /* istanbul ignore next */ []));
|
|
67
67
|
this.registeredWidgetsCount = signal(0, ...(ngDevMode ? [{ debugName: "registeredWidgetsCount" }] : /* istanbul ignore next */ []));
|
|
68
|
-
/** Bumped when a widget reports dirty-state changes via `api().isDirty()`. */
|
|
69
68
|
this.dirtyWidgetsRevision = signal(0, ...(ngDevMode ? [{ debugName: "dirtyWidgetsRevision" }] : /* istanbul ignore next */ []));
|
|
70
69
|
this.dirtyWidgetsRevisionSignal = this.dirtyWidgetsRevision.asReadonly();
|
|
71
70
|
}
|
|
@@ -81,22 +80,19 @@ class AXPWidgetCoreService {
|
|
|
81
80
|
}
|
|
82
81
|
detectStatus() {
|
|
83
82
|
const statuses = Array.from(this.widgets.values()).map((c) => c.status());
|
|
84
|
-
// Rendering statuses
|
|
85
83
|
if (statuses.some((status) => status === AXPWidgetStatus.Rendering)) {
|
|
86
84
|
return AXPPageStatus.Rendering;
|
|
87
85
|
}
|
|
88
86
|
if (statuses.every((status) => status === AXPWidgetStatus.Rendered)) {
|
|
89
87
|
return AXPPageStatus.Rendered;
|
|
90
88
|
}
|
|
91
|
-
// Processing statuses
|
|
92
89
|
if (statuses.some((status) => status === AXPWidgetStatus.Processing)) {
|
|
93
90
|
return AXPPageStatus.Processing;
|
|
94
91
|
}
|
|
95
|
-
// Error handling
|
|
96
92
|
if (statuses.some((status) => status === AXPWidgetStatus.Error)) {
|
|
97
93
|
return AXPPageStatus.Error;
|
|
98
94
|
}
|
|
99
|
-
return AXPPageStatus.Rendered;
|
|
95
|
+
return AXPPageStatus.Rendered;
|
|
100
96
|
}
|
|
101
97
|
refresh() {
|
|
102
98
|
setTimeout(() => {
|
|
@@ -131,11 +127,6 @@ class AXPWidgetCoreService {
|
|
|
131
127
|
getWidget(id) {
|
|
132
128
|
return this.widgets.get(id);
|
|
133
129
|
}
|
|
134
|
-
/**
|
|
135
|
-
* Waits until a widget with the given id is registered, then resolves with it.
|
|
136
|
-
* If the widget is already registered, resolves immediately.
|
|
137
|
-
* Optionally accepts a timeout (in ms) after which it resolves with undefined.
|
|
138
|
-
*/
|
|
139
130
|
async waitForWidget(id, timeoutMs) {
|
|
140
131
|
const existing = this.widgets.get(id);
|
|
141
132
|
if (existing) {
|
|
@@ -165,28 +156,12 @@ class AXPWidgetCoreService {
|
|
|
165
156
|
}
|
|
166
157
|
});
|
|
167
158
|
}
|
|
168
|
-
/**
|
|
169
|
-
* Returns a list of registered widget ids (names).
|
|
170
|
-
*/
|
|
171
159
|
listRegisteredWidgetNames() {
|
|
172
160
|
return Array.from(this.widgets.keys());
|
|
173
161
|
}
|
|
174
|
-
/** Notifies listeners that a widget's composite dirty state may have changed. */
|
|
175
162
|
notifyWidgetDirtyChanged() {
|
|
176
163
|
this.dirtyWidgetsRevision.update((value) => value + 1);
|
|
177
164
|
}
|
|
178
|
-
/**
|
|
179
|
-
* Returns whether any registered widget reports dirty state via `api().isDirty()`.
|
|
180
|
-
*/
|
|
181
|
-
hasDirtyWidgets() {
|
|
182
|
-
for (const widget of this.widgets.values()) {
|
|
183
|
-
const isDirty = widget.api()?.['isDirty'];
|
|
184
|
-
if (typeof isDirty === 'function' && isDirty()) {
|
|
185
|
-
return true;
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
return false;
|
|
189
|
-
}
|
|
190
165
|
ngOnDestroy() { }
|
|
191
166
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWidgetCoreService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
192
167
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWidgetCoreService }); }
|
|
@@ -503,7 +478,7 @@ class AXPValueWidgetComponent extends AXPLayoutBaseWidgetComponent {
|
|
|
503
478
|
this.detectFullPath();
|
|
504
479
|
// Set defaultValue if it exists and the path doesn't exist in context
|
|
505
480
|
if (!isNil(this.defaultValue) && this.fullPath() && !this.contextService.hasValue(this.fullPath())) {
|
|
506
|
-
this.setValue(this.defaultValue
|
|
481
|
+
this.setValue(this.defaultValue);
|
|
507
482
|
}
|
|
508
483
|
}
|
|
509
484
|
//
|
|
@@ -516,31 +491,38 @@ class AXPValueWidgetComponent extends AXPLayoutBaseWidgetComponent {
|
|
|
516
491
|
}
|
|
517
492
|
return rawValue;
|
|
518
493
|
}
|
|
519
|
-
setValue(value
|
|
494
|
+
setValue(value) {
|
|
520
495
|
if (this.node.valueTransforms?.setter) {
|
|
521
496
|
value = this.node.valueTransforms?.setter(value);
|
|
522
497
|
}
|
|
498
|
+
const path = this.fullPath();
|
|
499
|
+
if (!path) {
|
|
500
|
+
return;
|
|
501
|
+
}
|
|
523
502
|
const oldValue = this.getValue();
|
|
524
503
|
value = isUndefined(value) ? null : value;
|
|
525
504
|
if (isNil(value) && isNil(oldValue)) {
|
|
526
505
|
return;
|
|
527
506
|
}
|
|
507
|
+
const savedAtPath = this.contextService.getSavedValue(path);
|
|
508
|
+
if (this.contextService.isSavedCommitted() &&
|
|
509
|
+
isSelectionValueEqual(value, savedAtPath) &&
|
|
510
|
+
!isEqual(oldValue, savedAtPath)) {
|
|
511
|
+
this.contextService.update(path, cloneDeep(savedAtPath));
|
|
512
|
+
this.onValueChanged.next({ sender: this });
|
|
513
|
+
return;
|
|
514
|
+
}
|
|
528
515
|
// Reordered arrays must persist even when items are deep-equal (e.g. empty row objects).
|
|
529
516
|
const isArrayReorder = Array.isArray(oldValue) &&
|
|
530
517
|
Array.isArray(value) &&
|
|
531
518
|
oldValue.length === value.length &&
|
|
532
519
|
oldValue.some((v, i) => v !== value[i]);
|
|
533
|
-
|
|
520
|
+
const isArrayLengthChange = Array.isArray(value) && (!Array.isArray(oldValue) || value.length !== oldValue.length);
|
|
521
|
+
if (!isArrayReorder && !isArrayLengthChange && isFormValueEqual(oldValue, value)) {
|
|
534
522
|
return;
|
|
535
523
|
}
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
this.onValueChanged.next({ sender: this });
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
/** Persists a user-initiated value change into the shared context store. */
|
|
542
|
-
setUserValue(value) {
|
|
543
|
-
this.setValue(value, { origin: 'user' });
|
|
524
|
+
this.contextService.update(path, value);
|
|
525
|
+
this.onValueChanged.next({ sender: this });
|
|
544
526
|
}
|
|
545
527
|
detectFullPath() {
|
|
546
528
|
const sections = [];
|
|
@@ -578,7 +560,7 @@ class AXPValueWidgetComponent extends AXPLayoutBaseWidgetComponent {
|
|
|
578
560
|
}
|
|
579
561
|
handleValueChanged(e) {
|
|
580
562
|
if (e.isUserInteraction) {
|
|
581
|
-
this.
|
|
563
|
+
this.setValue(e.value);
|
|
582
564
|
}
|
|
583
565
|
}
|
|
584
566
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPValueWidgetComponent, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
@@ -1335,11 +1317,16 @@ class AXPWidgetColumnRendererComponent extends AXDataTableColumnComponent {
|
|
|
1335
1317
|
this.allowResizing = this.mergedOptions().allowResizing || true;
|
|
1336
1318
|
this.allowSorting = this.sortEnabled;
|
|
1337
1319
|
this.cdr.detectChanges();
|
|
1320
|
+
this.fixed = this.columnFixed;
|
|
1338
1321
|
}
|
|
1339
1322
|
ngOnChanges() {
|
|
1340
1323
|
this.allowSorting = this.sortEnabled;
|
|
1341
1324
|
this.sortOrder = this.headerSortDirection;
|
|
1342
1325
|
this.sortIndex = this.headerSortPriority;
|
|
1326
|
+
this.fixed = this.columnFixed;
|
|
1327
|
+
if (this.customWidth) {
|
|
1328
|
+
this.width = this.customWidth;
|
|
1329
|
+
}
|
|
1343
1330
|
}
|
|
1344
1331
|
//#region ---- Performance Optimization Methods ----
|
|
1345
1332
|
/**
|
|
@@ -1503,7 +1490,7 @@ class AXPWidgetColumnRendererComponent extends AXDataTableColumnComponent {
|
|
|
1503
1490
|
return rowInjector;
|
|
1504
1491
|
}
|
|
1505
1492
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWidgetColumnRendererComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
1506
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXPWidgetColumnRendererComponent, isStandalone: false, selector: "axp-widget-column-renderer", inputs: { caption: "caption", customExpandIcon: "customExpandIcon", customCollapseIcon: "customCollapseIcon", customWidth: "customWidth", node: "node", footerTemplate: "footerTemplate", expandHandler: "expandHandler", sortEnabled: "sortEnabled", headerSortDirection: "headerSortDirection", headerSortPriority: "headerSortPriority", cellTemplate: "cellTemplate", headerTemplate: "headerTemplate" }, outputs: { sortToggle: "sortToggle" }, providers: [
|
|
1493
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXPWidgetColumnRendererComponent, isStandalone: false, selector: "axp-widget-column-renderer", inputs: { caption: "caption", customExpandIcon: "customExpandIcon", customCollapseIcon: "customCollapseIcon", customWidth: "customWidth", node: "node", footerTemplate: "footerTemplate", expandHandler: "expandHandler", sortEnabled: "sortEnabled", headerSortDirection: "headerSortDirection", headerSortPriority: "headerSortPriority", columnFixed: "columnFixed", cellTemplate: "cellTemplate", headerTemplate: "headerTemplate" }, outputs: { sortToggle: "sortToggle" }, providers: [
|
|
1507
1494
|
AXPWidgetCoreService,
|
|
1508
1495
|
{ provide: AXDataTableColumnComponent, useExisting: AXPWidgetColumnRendererComponent },
|
|
1509
1496
|
], viewQueries: [{ propertyName: "_contentFooterTemplate", first: true, predicate: ["footer"], descendants: true }, { propertyName: "_contentCellTemplate", first: true, predicate: ["cell"], descendants: true }, { propertyName: "_contentHeaderTemplate", first: true, predicate: ["header"], descendants: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: `
|
|
@@ -1658,6 +1645,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
1658
1645
|
type: Input
|
|
1659
1646
|
}], headerSortPriority: [{
|
|
1660
1647
|
type: Input
|
|
1648
|
+
}], columnFixed: [{
|
|
1649
|
+
type: Input
|
|
1661
1650
|
}], sortToggle: [{
|
|
1662
1651
|
type: Output
|
|
1663
1652
|
}], cellTemplate: [{
|
|
@@ -1672,13 +1661,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
1672
1661
|
args: ['header']
|
|
1673
1662
|
}] } });
|
|
1674
1663
|
|
|
1664
|
+
/** Idle period after widgets register / hydrate before committing the saved baseline. */
|
|
1665
|
+
const FORM_SAVED_BASELINE_IDLE_MS = 500;
|
|
1675
1666
|
class AXPWidgetContainerComponent {
|
|
1676
1667
|
set context(value) {
|
|
1677
|
-
|
|
1678
|
-
if (isEqual(this.contextService.data(), value)) {
|
|
1679
|
-
return;
|
|
1680
|
-
}
|
|
1681
|
-
this.contextService.set(value);
|
|
1668
|
+
this.syncExternalContext(value);
|
|
1682
1669
|
}
|
|
1683
1670
|
set functions(v) {
|
|
1684
1671
|
this.builderService.setFunctions(v);
|
|
@@ -1687,25 +1674,38 @@ class AXPWidgetContainerComponent {
|
|
|
1687
1674
|
this.contextService = inject(AXPContextStore);
|
|
1688
1675
|
this.builderService = inject(AXPWidgetCoreService);
|
|
1689
1676
|
this.onContextChanged = new EventEmitter();
|
|
1690
|
-
|
|
1677
|
+
this.isSavedCommitted = computed(() => this.contextService.isSavedCommitted(), ...(ngDevMode ? [{ debugName: "isSavedCommitted" }] : /* istanbul ignore next */ []));
|
|
1691
1678
|
this.isFormDirty = computed(() => {
|
|
1692
|
-
this.
|
|
1693
|
-
|
|
1679
|
+
if (!this.contextService.isSavedCommitted()) {
|
|
1680
|
+
return false;
|
|
1681
|
+
}
|
|
1682
|
+
this.contextService.data();
|
|
1683
|
+
return this.contextService.isDirty();
|
|
1694
1684
|
}, ...(ngDevMode ? [{ debugName: "isFormDirty" }] : /* istanbul ignore next */ []));
|
|
1695
|
-
this.status = computed(() => {
|
|
1696
|
-
|
|
1697
|
-
}, ...(ngDevMode ? [{ debugName: "status" }] : /* istanbul ignore next */ []));
|
|
1698
|
-
this.isBusy = computed(() => {
|
|
1699
|
-
return this.builderService.isBusy();
|
|
1700
|
-
}, ...(ngDevMode ? [{ debugName: "isBusy" }] : /* istanbul ignore next */ []));
|
|
1685
|
+
this.status = computed(() => this.builderService.status(), ...(ngDevMode ? [{ debugName: "status" }] : /* istanbul ignore next */ []));
|
|
1686
|
+
this.isBusy = computed(() => this.builderService.isBusy(), ...(ngDevMode ? [{ debugName: "isBusy" }] : /* istanbul ignore next */ []));
|
|
1701
1687
|
effect(() => {
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1688
|
+
const isDirty = this.isFormDirty();
|
|
1689
|
+
const data = this.contextService.data();
|
|
1690
|
+
const changeEvent = this.contextService.changeEvent();
|
|
1691
|
+
if (!this.contextService.isChanged() && this.lastEmittedFormDirty === isDirty) {
|
|
1692
|
+
return;
|
|
1693
|
+
}
|
|
1694
|
+
this.lastEmittedFormDirty = isDirty;
|
|
1695
|
+
this.onContextChanged.emit({
|
|
1696
|
+
...changeEvent,
|
|
1697
|
+
data: cloneDeep(data),
|
|
1698
|
+
isFormDirty: isDirty,
|
|
1699
|
+
});
|
|
1700
|
+
});
|
|
1701
|
+
effect(() => {
|
|
1702
|
+
if (this.contextService.isSavedCommitted()) {
|
|
1703
|
+
return;
|
|
1704
|
+
}
|
|
1705
|
+
if (this.builderService.registeredWidgetsCount() === 0) {
|
|
1706
|
+
return;
|
|
1708
1707
|
}
|
|
1708
|
+
untracked(() => void this.settleSavedBaseline());
|
|
1709
1709
|
});
|
|
1710
1710
|
}
|
|
1711
1711
|
refresh() {
|
|
@@ -1714,17 +1714,61 @@ class AXPWidgetContainerComponent {
|
|
|
1714
1714
|
find(name) {
|
|
1715
1715
|
return this.builderService.waitForWidget(name);
|
|
1716
1716
|
}
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
const
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1717
|
+
syncExternalContext(value) {
|
|
1718
|
+
const next = cloneDeep(value ?? {});
|
|
1719
|
+
const current = this.contextService.data();
|
|
1720
|
+
if (isEqual(current, next)) {
|
|
1721
|
+
return;
|
|
1722
|
+
}
|
|
1723
|
+
if (this.contextService.isSavedCommitted() && this.isFormDirty()) {
|
|
1724
|
+
return;
|
|
1725
|
+
}
|
|
1726
|
+
if (this.contextService.isSavedCommitted()) {
|
|
1727
|
+
this.contextService.set(next);
|
|
1728
|
+
void this.settleSavedBaseline();
|
|
1729
|
+
return;
|
|
1730
|
+
}
|
|
1731
|
+
if (this.contextService.isChanged()) {
|
|
1725
1732
|
return;
|
|
1726
1733
|
}
|
|
1727
1734
|
this.contextService.set(next);
|
|
1735
|
+
void this.settleSavedBaseline();
|
|
1736
|
+
}
|
|
1737
|
+
/** Commits the current data as saved after widget hydration settles. */
|
|
1738
|
+
settleSavedBaseline() {
|
|
1739
|
+
this.clearSavedBaselineTimer();
|
|
1740
|
+
return new Promise((resolve) => {
|
|
1741
|
+
const commit = () => {
|
|
1742
|
+
if (this.builderService.registeredWidgetsCount() === 0) {
|
|
1743
|
+
this.savedBaselineTimer = setTimeout(commit, FORM_SAVED_BASELINE_IDLE_MS);
|
|
1744
|
+
return;
|
|
1745
|
+
}
|
|
1746
|
+
this.contextService.commitSaved();
|
|
1747
|
+
this.lastEmittedFormDirty = undefined;
|
|
1748
|
+
this.savedBaselineTimer = undefined;
|
|
1749
|
+
resolve();
|
|
1750
|
+
};
|
|
1751
|
+
this.savedBaselineTimer = setTimeout(commit, FORM_SAVED_BASELINE_IDLE_MS);
|
|
1752
|
+
});
|
|
1753
|
+
}
|
|
1754
|
+
async replaceContext(value) {
|
|
1755
|
+
this.clearSavedBaselineTimer();
|
|
1756
|
+
this.contextService.set(cloneDeep(value));
|
|
1757
|
+
// Commit immediately so save/replace is clean even when `set()` no-ops (data already matches).
|
|
1758
|
+
this.contextService.commitSaved();
|
|
1759
|
+
this.lastEmittedFormDirty = undefined;
|
|
1760
|
+
await this.settleSavedBaseline();
|
|
1761
|
+
}
|
|
1762
|
+
revertAndSettle() {
|
|
1763
|
+
this.clearSavedBaselineTimer();
|
|
1764
|
+
this.contextService.revertToSaved();
|
|
1765
|
+
this.lastEmittedFormDirty = undefined;
|
|
1766
|
+
}
|
|
1767
|
+
clearSavedBaselineTimer() {
|
|
1768
|
+
if (this.savedBaselineTimer) {
|
|
1769
|
+
clearTimeout(this.savedBaselineTimer);
|
|
1770
|
+
this.savedBaselineTimer = undefined;
|
|
1771
|
+
}
|
|
1728
1772
|
}
|
|
1729
1773
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWidgetContainerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1730
1774
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.9", type: AXPWidgetContainerComponent, isStandalone: false, selector: "axp-widgets-container", inputs: { context: "context", functions: "functions" }, outputs: { onContextChanged: "onContextChanged" }, host: { styleAttribute: "display: contents;" }, providers: [AXPWidgetCoreService, AXPContextStore], ngImport: i0, template: `<ng-content></ng-content>`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
@@ -1801,6 +1845,7 @@ class AXPWidgetRendererDirective {
|
|
|
1801
1845
|
this.isVisible = signal(true, ...(ngDevMode ? [{ debugName: "isVisible" }] : /* istanbul ignore next */ []));
|
|
1802
1846
|
this.expressionEvaluators = new Map();
|
|
1803
1847
|
this.renderTimeoutId = null;
|
|
1848
|
+
this.renderGeneration = 0;
|
|
1804
1849
|
this.hasInitialRender = false;
|
|
1805
1850
|
this.onContextChanged = new Subject();
|
|
1806
1851
|
this.onLoadEvent = new Subject();
|
|
@@ -2159,18 +2204,18 @@ class AXPWidgetRendererDirective {
|
|
|
2159
2204
|
}
|
|
2160
2205
|
}
|
|
2161
2206
|
rerenderComponent() {
|
|
2162
|
-
// Clear any pending render operation to prevent double rendering
|
|
2163
2207
|
if (this.renderTimeoutId) {
|
|
2164
2208
|
clearTimeout(this.renderTimeoutId);
|
|
2165
2209
|
this.renderTimeoutId = null;
|
|
2166
2210
|
}
|
|
2167
|
-
|
|
2168
|
-
this.isLoading.set(false);
|
|
2169
|
-
// Schedule the component loading
|
|
2211
|
+
const generation = ++this.renderGeneration;
|
|
2170
2212
|
this.renderTimeoutId = setTimeout(async () => {
|
|
2171
|
-
await this.loadComponent();
|
|
2172
2213
|
this.renderTimeoutId = null;
|
|
2173
|
-
|
|
2214
|
+
if (generation !== this.renderGeneration) {
|
|
2215
|
+
return;
|
|
2216
|
+
}
|
|
2217
|
+
await this.loadComponent();
|
|
2218
|
+
}, 0);
|
|
2174
2219
|
}
|
|
2175
2220
|
ngOnDestroy() {
|
|
2176
2221
|
if (this.renderTimeoutId) {
|
|
@@ -2559,7 +2604,10 @@ class AXPWidgetRendererDirective {
|
|
|
2559
2604
|
return this.contextService.data();
|
|
2560
2605
|
},
|
|
2561
2606
|
isDirty: () => {
|
|
2562
|
-
|
|
2607
|
+
if (!this.contextService.isSavedCommitted()) {
|
|
2608
|
+
return false;
|
|
2609
|
+
}
|
|
2610
|
+
return this.contextService.isDirty();
|
|
2563
2611
|
},
|
|
2564
2612
|
/**
|
|
2565
2613
|
* Host/widget-under-edit `options` from the shared context store (same values as
|
|
@@ -3392,6 +3440,9 @@ var AXPWidgetGroupEnum;
|
|
|
3392
3440
|
AXPWidgetGroupEnum["BaseWidget"] = "base-widget";
|
|
3393
3441
|
})(AXPWidgetGroupEnum || (AXPWidgetGroupEnum = {}));
|
|
3394
3442
|
|
|
3443
|
+
//#region ---- Contracts barrel ----
|
|
3444
|
+
//#endregion
|
|
3445
|
+
|
|
3395
3446
|
const AXP_STYLING_PROPERTY_GROUP = {
|
|
3396
3447
|
name: 'styling',
|
|
3397
3448
|
order: 1,
|