@acorex/platform 20.3.0-next.12 → 20.3.0-next.13
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/common/index.d.ts +399 -368
- package/core/index.d.ts +3 -2
- package/fesm2022/acorex-platform-auth.mjs +19 -19
- package/fesm2022/acorex-platform-auth.mjs.map +1 -1
- package/fesm2022/acorex-platform-common.mjs +114 -162
- package/fesm2022/acorex-platform-common.mjs.map +1 -1
- package/fesm2022/acorex-platform-core.mjs +45 -44
- package/fesm2022/acorex-platform-core.mjs.map +1 -1
- package/fesm2022/acorex-platform-domain.mjs +16 -16
- package/fesm2022/acorex-platform-domain.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-builder.mjs +1231 -2418
- package/fesm2022/acorex-platform-layout-builder.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-components.mjs +1317 -254
- package/fesm2022/acorex-platform-layout-components.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-designer.mjs +81 -81
- package/fesm2022/acorex-platform-layout-designer.mjs.map +1 -1
- package/fesm2022/{acorex-platform-layout-entity-create-entity.command-764ie8R8.mjs → acorex-platform-layout-entity-create-entity.command-CuueLekJ.mjs} +4 -4
- package/fesm2022/{acorex-platform-layout-entity-create-entity.command-764ie8R8.mjs.map → acorex-platform-layout-entity-create-entity.command-CuueLekJ.mjs.map} +1 -1
- package/fesm2022/acorex-platform-layout-entity.mjs +473 -183
- package/fesm2022/acorex-platform-layout-entity.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-views.mjs +21 -21
- package/fesm2022/acorex-platform-layout-views.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-widget-core.mjs +2667 -0
- package/fesm2022/acorex-platform-layout-widget-core.mjs.map +1 -0
- package/fesm2022/{acorex-platform-widgets-button-widget-designer.component-DSaD9Fwc.mjs → acorex-platform-layout-widgets-button-widget-designer.component-C82aG5Rf.mjs} +5 -5
- package/fesm2022/acorex-platform-layout-widgets-button-widget-designer.component-C82aG5Rf.mjs.map +1 -0
- package/fesm2022/{acorex-platform-widgets-extra-properties-schema-widget-edit.component-D9mf08rU.mjs → acorex-platform-layout-widgets-extra-properties-schema-widget-edit.component-CMmz70I8.mjs} +5 -5
- package/fesm2022/acorex-platform-layout-widgets-extra-properties-schema-widget-edit.component-CMmz70I8.mjs.map +1 -0
- package/fesm2022/{acorex-platform-widgets-extra-properties-schema-widget-view.component-D6GQ-eyr.mjs → acorex-platform-layout-widgets-extra-properties-schema-widget-view.component-DDOyf7NG.mjs} +5 -5
- package/fesm2022/acorex-platform-layout-widgets-extra-properties-schema-widget-view.component-DDOyf7NG.mjs.map +1 -0
- package/fesm2022/{acorex-platform-widgets-extra-properties-values-widget-edit.component-DVbIdVZ6.mjs → acorex-platform-layout-widgets-extra-properties-values-widget-edit.component-flsveRJc.mjs} +5 -5
- package/fesm2022/acorex-platform-layout-widgets-extra-properties-values-widget-edit.component-flsveRJc.mjs.map +1 -0
- package/fesm2022/{acorex-platform-widgets-extra-properties-values-widget-view.component-D-aM64Hu.mjs → acorex-platform-layout-widgets-extra-properties-values-widget-view.component-CFXLM9Ls.mjs} +5 -5
- package/fesm2022/acorex-platform-layout-widgets-extra-properties-values-widget-view.component-CFXLM9Ls.mjs.map +1 -0
- package/fesm2022/{acorex-platform-widgets-extra-properties-widget-edit.component-em2-aU8E.mjs → acorex-platform-layout-widgets-extra-properties-widget-edit.component-1Wd5IUpo.mjs} +5 -5
- package/fesm2022/acorex-platform-layout-widgets-extra-properties-widget-edit.component-1Wd5IUpo.mjs.map +1 -0
- package/fesm2022/{acorex-platform-widgets-extra-properties-widget-view.component-BeuIofdr.mjs → acorex-platform-layout-widgets-extra-properties-widget-view.component-WLyXXg19.mjs} +5 -5
- package/fesm2022/acorex-platform-layout-widgets-extra-properties-widget-view.component-WLyXXg19.mjs.map +1 -0
- package/fesm2022/{acorex-platform-widgets-file-list-popup.component-Cmtq2bBV.mjs → acorex-platform-layout-widgets-file-list-popup.component-DxTXIO_k.mjs} +8 -8
- package/fesm2022/acorex-platform-layout-widgets-file-list-popup.component-DxTXIO_k.mjs.map +1 -0
- package/fesm2022/{acorex-platform-widgets-page-widget-designer.component-B-ZEi2yd.mjs → acorex-platform-layout-widgets-page-widget-designer.component-44YSAqDc.mjs} +7 -7
- package/fesm2022/acorex-platform-layout-widgets-page-widget-designer.component-44YSAqDc.mjs.map +1 -0
- package/fesm2022/{acorex-platform-widgets-tabular-data-edit-popup.component-CMqq_iOj.mjs → acorex-platform-layout-widgets-tabular-data-edit-popup.component-Dat0cqWe.mjs} +8 -8
- package/fesm2022/acorex-platform-layout-widgets-tabular-data-edit-popup.component-Dat0cqWe.mjs.map +1 -0
- package/fesm2022/{acorex-platform-widgets-tabular-data-view-popup.component-CRpjdiNz.mjs → acorex-platform-layout-widgets-tabular-data-view-popup.component-CtJBzqq_.mjs} +4 -4
- package/fesm2022/acorex-platform-layout-widgets-tabular-data-view-popup.component-CtJBzqq_.mjs.map +1 -0
- package/fesm2022/{acorex-platform-widgets-text-block-widget-designer.component-DeSmBqMa.mjs → acorex-platform-layout-widgets-text-block-widget-designer.component-Djpj1fNO.mjs} +5 -5
- package/fesm2022/acorex-platform-layout-widgets-text-block-widget-designer.component-Djpj1fNO.mjs.map +1 -0
- package/fesm2022/{acorex-platform-widgets.mjs → acorex-platform-layout-widgets.mjs} +987 -616
- package/fesm2022/acorex-platform-layout-widgets.mjs.map +1 -0
- package/fesm2022/acorex-platform-native.mjs +7 -7
- package/fesm2022/acorex-platform-native.mjs.map +1 -1
- package/fesm2022/acorex-platform-runtime.mjs +40 -40
- package/fesm2022/acorex-platform-runtime.mjs.map +1 -1
- package/fesm2022/acorex-platform-themes-default-entity-master-create-view.component-oOA674Jd.mjs +115 -0
- package/fesm2022/acorex-platform-themes-default-entity-master-create-view.component-oOA674Jd.mjs.map +1 -0
- package/fesm2022/{acorex-platform-themes-default-entity-master-list-view.component-7BB4LdjK.mjs → acorex-platform-themes-default-entity-master-list-view.component-Bk4p9oHD.mjs} +15 -15
- package/fesm2022/{acorex-platform-themes-default-entity-master-list-view.component-7BB4LdjK.mjs.map → acorex-platform-themes-default-entity-master-list-view.component-Bk4p9oHD.mjs.map} +1 -1
- package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-CrDQOCpB.mjs +101 -0
- package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-CrDQOCpB.mjs.map +1 -0
- package/fesm2022/{acorex-platform-themes-default-entity-master-single-view.component-BExtm1JE.mjs → acorex-platform-themes-default-entity-master-single-view.component-CT-1gX4H.mjs} +17 -17
- package/fesm2022/acorex-platform-themes-default-entity-master-single-view.component-CT-1gX4H.mjs.map +1 -0
- package/fesm2022/{acorex-platform-themes-default-error-401.component-DrO1PEOH.mjs → acorex-platform-themes-default-error-401.component-CHJFmJ2W.mjs} +4 -4
- package/fesm2022/{acorex-platform-themes-default-error-401.component-DrO1PEOH.mjs.map → acorex-platform-themes-default-error-401.component-CHJFmJ2W.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-themes-default-error-404.component-DqVq0oHX.mjs → acorex-platform-themes-default-error-404.component-Db8KkVIF.mjs} +4 -4
- package/fesm2022/{acorex-platform-themes-default-error-404.component-DqVq0oHX.mjs.map → acorex-platform-themes-default-error-404.component-Db8KkVIF.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-themes-default-error-offline.component-Bt2PTL7_.mjs → acorex-platform-themes-default-error-offline.component-DH39Viy-.mjs} +4 -4
- package/fesm2022/{acorex-platform-themes-default-error-offline.component-Bt2PTL7_.mjs.map → acorex-platform-themes-default-error-offline.component-DH39Viy-.mjs.map} +1 -1
- package/fesm2022/acorex-platform-themes-default.mjs +44 -44
- package/fesm2022/acorex-platform-themes-default.mjs.map +1 -1
- package/fesm2022/{acorex-platform-themes-shared-icon-chooser-view.component-BgEh06Tn.mjs → acorex-platform-themes-shared-icon-chooser-view.component-mFBYGE0_.mjs} +5 -5
- package/fesm2022/acorex-platform-themes-shared-icon-chooser-view.component-mFBYGE0_.mjs.map +1 -0
- package/fesm2022/{acorex-platform-themes-shared-settings.provider-CLUKU4y0.mjs → acorex-platform-themes-shared-settings.provider-DY2xFnrv.mjs} +8 -8
- package/fesm2022/acorex-platform-themes-shared-settings.provider-DY2xFnrv.mjs.map +1 -0
- package/fesm2022/{acorex-platform-themes-shared-theme-color-chooser-column.component-AeOQxjbS.mjs → acorex-platform-themes-shared-theme-color-chooser-column.component-viyyova6.mjs} +5 -5
- package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-column.component-viyyova6.mjs.map +1 -0
- package/fesm2022/{acorex-platform-themes-shared-theme-color-chooser-view.component-DEVzRd6-.mjs → acorex-platform-themes-shared-theme-color-chooser-view.component-BrUtKTXd.mjs} +5 -5
- package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-view.component-BrUtKTXd.mjs.map +1 -0
- package/fesm2022/acorex-platform-themes-shared.mjs +66 -55
- package/fesm2022/acorex-platform-themes-shared.mjs.map +1 -1
- package/fesm2022/acorex-platform-workflow.mjs +27 -39
- package/fesm2022/acorex-platform-workflow.mjs.map +1 -1
- package/layout/builder/README.md +2 -3
- package/layout/builder/index.d.ts +456 -879
- package/layout/components/index.d.ts +261 -81
- package/layout/designer/index.d.ts +4 -4
- package/layout/entity/index.d.ts +551 -13
- package/layout/views/index.d.ts +13 -13
- package/layout/widget-core/README.md +4 -0
- package/layout/widget-core/index.d.ts +950 -0
- package/layout/widgets/README.md +4 -0
- package/{widgets → layout/widgets}/index.d.ts +95 -61
- package/package.json +9 -5
- package/themes/shared/index.d.ts +2 -2
- package/workflow/index.d.ts +3 -173
- package/fesm2022/acorex-platform-themes-default-entity-master-create-view.component-Ct-ri59W.mjs +0 -115
- package/fesm2022/acorex-platform-themes-default-entity-master-create-view.component-Ct-ri59W.mjs.map +0 -1
- package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-BDJR088o.mjs +0 -101
- package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-BDJR088o.mjs.map +0 -1
- package/fesm2022/acorex-platform-themes-default-entity-master-single-view.component-BExtm1JE.mjs.map +0 -1
- package/fesm2022/acorex-platform-themes-shared-icon-chooser-view.component-BgEh06Tn.mjs.map +0 -1
- package/fesm2022/acorex-platform-themes-shared-settings.provider-CLUKU4y0.mjs.map +0 -1
- package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-column.component-AeOQxjbS.mjs.map +0 -1
- package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-view.component-DEVzRd6-.mjs.map +0 -1
- package/fesm2022/acorex-platform-widgets-button-widget-designer.component-DSaD9Fwc.mjs.map +0 -1
- package/fesm2022/acorex-platform-widgets-extra-properties-schema-widget-edit.component-D9mf08rU.mjs.map +0 -1
- package/fesm2022/acorex-platform-widgets-extra-properties-schema-widget-view.component-D6GQ-eyr.mjs.map +0 -1
- package/fesm2022/acorex-platform-widgets-extra-properties-values-widget-edit.component-DVbIdVZ6.mjs.map +0 -1
- package/fesm2022/acorex-platform-widgets-extra-properties-values-widget-view.component-D-aM64Hu.mjs.map +0 -1
- package/fesm2022/acorex-platform-widgets-extra-properties-widget-edit.component-em2-aU8E.mjs.map +0 -1
- package/fesm2022/acorex-platform-widgets-extra-properties-widget-view.component-BeuIofdr.mjs.map +0 -1
- package/fesm2022/acorex-platform-widgets-file-list-popup.component-Cmtq2bBV.mjs.map +0 -1
- package/fesm2022/acorex-platform-widgets-page-widget-designer.component-B-ZEi2yd.mjs.map +0 -1
- package/fesm2022/acorex-platform-widgets-tabular-data-edit-popup.component-CMqq_iOj.mjs.map +0 -1
- package/fesm2022/acorex-platform-widgets-tabular-data-view-popup.component-CRpjdiNz.mjs.map +0 -1
- package/fesm2022/acorex-platform-widgets-text-block-widget-designer.component-DeSmBqMa.mjs.map +0 -1
- package/fesm2022/acorex-platform-widgets.mjs.map +0 -1
- package/widgets/README.md +0 -4
|
@@ -1,2518 +1,1331 @@
|
|
|
1
|
-
import * as i0 from '@angular/core';
|
|
2
|
-
import { signal, computed, Injectable, InjectionToken, inject, ElementRef, effect, Injector, ChangeDetectorRef, ViewChild, Input, ChangeDetectionStrategy, Component, EventEmitter, Output, input, output, ViewContainerRef, Directive, Optional, Inject, NgModule } from '@angular/core';
|
|
3
|
-
import { convertArrayToDataSource, AXDataSource } from '@acorex/cdk/common';
|
|
4
|
-
import { setSmart, AXPDataSourceDefinitionProviderService, extractValue, getSmart, AXPExpressionEvaluatorService } from '@acorex/platform/core';
|
|
5
|
-
import { set, cloneDeep, isEqual, get, merge, isNil, isUndefined, isObjectLike, sum, isEmpty, isString } from 'lodash-es';
|
|
6
|
-
import { Subject, BehaviorSubject, filter } from 'rxjs';
|
|
7
|
-
import { signalStore, withState, withComputed, withMethods, patchState } from '@ngrx/signals';
|
|
8
|
-
import * as i1$1 from '@acorex/components/skeleton';
|
|
9
|
-
import { AXSkeletonModule } from '@acorex/components/skeleton';
|
|
10
|
-
import * as i2 from '@acorex/core/translation';
|
|
11
|
-
import { AXTranslationService, AXTranslationModule } from '@acorex/core/translation';
|
|
12
|
-
import { PortalModule } from '@angular/cdk/portal';
|
|
13
|
-
import * as i1 from '@angular/common';
|
|
14
1
|
import { CommonModule } from '@angular/common';
|
|
15
|
-
import
|
|
16
|
-
import {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
(function (AXPPageStatus) {
|
|
20
|
-
// Idle statuses
|
|
21
|
-
AXPPageStatus["Idle"] = "idle";
|
|
22
|
-
// Rendering statuses
|
|
23
|
-
AXPPageStatus["Rendering"] = "rendering";
|
|
24
|
-
AXPPageStatus["Rendered"] = "rendered";
|
|
25
|
-
// Processing statuses
|
|
26
|
-
AXPPageStatus["Processing"] = "processing";
|
|
27
|
-
// Submission statuses
|
|
28
|
-
AXPPageStatus["Submitting"] = "submitting";
|
|
29
|
-
AXPPageStatus["Submitted"] = "submitted";
|
|
30
|
-
// Validation statuses
|
|
31
|
-
AXPPageStatus["Validating"] = "validating";
|
|
32
|
-
AXPPageStatus["Validated"] = "validated";
|
|
33
|
-
// Error handling
|
|
34
|
-
AXPPageStatus["Error"] = "error";
|
|
35
|
-
})(AXPPageStatus || (AXPPageStatus = {}));
|
|
36
|
-
var AXPWidgetStatus;
|
|
37
|
-
(function (AXPWidgetStatus) {
|
|
38
|
-
// Rendering statuses
|
|
39
|
-
AXPWidgetStatus["Rendering"] = "rendering";
|
|
40
|
-
AXPWidgetStatus["Rendered"] = "rendered";
|
|
41
|
-
// Processing statuses
|
|
42
|
-
AXPWidgetStatus["Processing"] = "processing";
|
|
43
|
-
// Error handling
|
|
44
|
-
AXPWidgetStatus["Error"] = "error";
|
|
45
|
-
})(AXPWidgetStatus || (AXPWidgetStatus = {}));
|
|
2
|
+
import * as i0 from '@angular/core';
|
|
3
|
+
import { Injectable, Input, Component, NgModule } from '@angular/core';
|
|
4
|
+
import * as i1 from '@acorex/platform/layout/widget-core';
|
|
5
|
+
import { AXPWidgetCoreModule } from '@acorex/platform/layout/widget-core';
|
|
46
6
|
|
|
47
|
-
class AXPLayoutElement {
|
|
48
|
-
api() {
|
|
49
|
-
return {};
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
7
|
class AXPLayoutBuilderService {
|
|
53
|
-
constructor() {
|
|
54
|
-
this.variables$ = signal({}, ...(ngDevMode ? [{ debugName: "variables$" }] : []));
|
|
55
|
-
this.functions$ = signal({}, ...(ngDevMode ? [{ debugName: "functions$" }] : []));
|
|
56
|
-
this.onRefresh = new Subject();
|
|
57
|
-
this.widgets = new Map();
|
|
58
|
-
this.onWidgetRegistered = new Subject();
|
|
59
|
-
this.status$ = signal(AXPPageStatus.Rendering, ...(ngDevMode ? [{ debugName: "status$" }] : []));
|
|
60
|
-
this.status = this.status$.asReadonly();
|
|
61
|
-
this.isBusy = computed(() => {
|
|
62
|
-
return [AXPPageStatus.Processing, AXPPageStatus.Submitting, AXPPageStatus.Rendering].includes(this.status());
|
|
63
|
-
}, ...(ngDevMode ? [{ debugName: "isBusy" }] : []));
|
|
64
|
-
}
|
|
65
|
-
get variables() {
|
|
66
|
-
return this.variables$();
|
|
67
|
-
}
|
|
68
|
-
get functions() {
|
|
69
|
-
return this.functions$();
|
|
70
|
-
}
|
|
71
|
-
updateStatus() {
|
|
72
|
-
this.status$.update(() => this.detectStatus());
|
|
73
|
-
}
|
|
74
|
-
detectStatus() {
|
|
75
|
-
const statuses = Array.from(this.widgets.values()).map((c) => c.status());
|
|
76
|
-
// Rendering statuses
|
|
77
|
-
if (statuses.some((status) => status === AXPWidgetStatus.Rendering)) {
|
|
78
|
-
return AXPPageStatus.Rendering;
|
|
79
|
-
}
|
|
80
|
-
if (statuses.every((status) => status === AXPWidgetStatus.Rendered)) {
|
|
81
|
-
return AXPPageStatus.Rendered;
|
|
82
|
-
}
|
|
83
|
-
// Processing statuses
|
|
84
|
-
if (statuses.some((status) => status === AXPWidgetStatus.Processing)) {
|
|
85
|
-
return AXPPageStatus.Processing;
|
|
86
|
-
}
|
|
87
|
-
// Error handling
|
|
88
|
-
if (statuses.some((status) => status === AXPWidgetStatus.Error)) {
|
|
89
|
-
return AXPPageStatus.Error;
|
|
90
|
-
}
|
|
91
|
-
return AXPPageStatus.Rendered; // Default to Loaded when all widgets are in a completed state
|
|
92
|
-
}
|
|
93
|
-
refresh() {
|
|
94
|
-
setTimeout(() => {
|
|
95
|
-
this.onRefresh.next();
|
|
96
|
-
}, 0);
|
|
97
|
-
}
|
|
98
|
-
setStatus(status) {
|
|
99
|
-
this.status$.set(status);
|
|
100
|
-
}
|
|
101
|
-
setVariables(...args) {
|
|
102
|
-
if (args.length == 0)
|
|
103
|
-
return;
|
|
104
|
-
else if (args.length == 1)
|
|
105
|
-
this.variables$.set(args[0]);
|
|
106
|
-
else if (args.length == 2) {
|
|
107
|
-
this.variables$.update((v) => set(v, args[0], args[1]));
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
setFunctions(...args) {
|
|
111
|
-
if (args.length == 0)
|
|
112
|
-
return;
|
|
113
|
-
else if (args.length == 1)
|
|
114
|
-
this.functions$.set(args[0]);
|
|
115
|
-
else if (args.length == 2) {
|
|
116
|
-
this.functions$.update((v) => set(v, args[0], args[1]));
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
registerWidget(id, widget) {
|
|
120
|
-
this.widgets.set(id, widget);
|
|
121
|
-
this.onWidgetRegistered.next({ id, widget });
|
|
122
|
-
}
|
|
123
|
-
getWidget(id) {
|
|
124
|
-
return this.widgets.get(id);
|
|
125
|
-
}
|
|
126
8
|
/**
|
|
127
|
-
*
|
|
128
|
-
* If the widget is already registered, resolves immediately.
|
|
129
|
-
* Optionally accepts a timeout (in ms) after which it resolves with undefined.
|
|
9
|
+
* Create a new layout builder
|
|
130
10
|
*/
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
if (existing) {
|
|
134
|
-
return existing;
|
|
135
|
-
}
|
|
136
|
-
return new Promise((resolve) => {
|
|
137
|
-
let resolved = false;
|
|
138
|
-
let timer = null;
|
|
139
|
-
const sub = this.onWidgetRegistered.subscribe(({ id: registeredId, widget }) => {
|
|
140
|
-
if (registeredId === id && !resolved) {
|
|
141
|
-
resolved = true;
|
|
142
|
-
sub.unsubscribe();
|
|
143
|
-
if (timer) {
|
|
144
|
-
clearTimeout(timer);
|
|
145
|
-
}
|
|
146
|
-
resolve(widget);
|
|
147
|
-
}
|
|
148
|
-
});
|
|
149
|
-
if (timeoutMs != null && timeoutMs > 0) {
|
|
150
|
-
timer = setTimeout(() => {
|
|
151
|
-
if (!resolved) {
|
|
152
|
-
resolved = true;
|
|
153
|
-
sub.unsubscribe();
|
|
154
|
-
resolve(undefined);
|
|
155
|
-
}
|
|
156
|
-
}, timeoutMs);
|
|
157
|
-
}
|
|
158
|
-
});
|
|
11
|
+
create() {
|
|
12
|
+
return new LayoutBuilder();
|
|
159
13
|
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
class AXPLayoutContextChangeEvent {
|
|
169
|
-
}
|
|
170
|
-
const AXPLayoutBuilderContextStore = signalStore(
|
|
171
|
-
// Initial State
|
|
172
|
-
withState(() => ({
|
|
173
|
-
data: {}, // Shared context data
|
|
174
|
-
state: 'initiated', // Current state
|
|
175
|
-
initialSnapshot: {}, // Snapshot of the first initialized state
|
|
176
|
-
previousSnapshot: {}, // Snapshot of the previous state
|
|
177
|
-
lastChange: {
|
|
178
|
-
state: 'initiated',
|
|
179
|
-
}, // Last change event
|
|
180
|
-
})),
|
|
181
|
-
// Computed Signals
|
|
182
|
-
withComputed(({ data, state, lastChange, initialSnapshot, previousSnapshot }) => ({
|
|
183
|
-
isChanged: computed(() => state() === 'changed'),
|
|
184
|
-
isReset: computed(() => state() === 'restored'),
|
|
185
|
-
isInitiated: computed(() => state() === 'initiated'),
|
|
186
|
-
isEmpty: computed(() => Object.keys(data()).length === 0),
|
|
187
|
-
isDirty: computed(() => !isEqual(data(), previousSnapshot())),
|
|
188
|
-
snapshot: computed(() => cloneDeep(data())), // Current data snapshot
|
|
189
|
-
initial: computed(() => cloneDeep(initialSnapshot())), // Initial snapshot
|
|
190
|
-
previous: computed(() => cloneDeep(previousSnapshot())), // Previous snapshot
|
|
191
|
-
changeEvent: computed(() => lastChange()), // Reactive last change event
|
|
192
|
-
})),
|
|
193
|
-
// Methods for State Management
|
|
194
|
-
withMethods((store) => ({
|
|
195
|
-
// Update a specific value
|
|
196
|
-
update(path, value) {
|
|
197
|
-
const currentData = cloneDeep(store.data());
|
|
198
|
-
const oldValue = get(currentData, path);
|
|
199
|
-
// Skip if the value hasn't changed
|
|
200
|
-
if (isEqual(oldValue, value)) {
|
|
201
|
-
return;
|
|
202
|
-
}
|
|
203
|
-
// Update the value and prepare the change event
|
|
204
|
-
const updatedData = setSmart(currentData, path, value);
|
|
205
|
-
const changeEvent = {
|
|
206
|
-
oldValue,
|
|
207
|
-
newValue: value,
|
|
208
|
-
path,
|
|
209
|
-
state: 'changed',
|
|
210
|
-
data: updatedData,
|
|
211
|
-
};
|
|
212
|
-
// Patch the state
|
|
213
|
-
patchState(store, {
|
|
214
|
-
previousSnapshot: store.snapshot(), // Save the previous state
|
|
215
|
-
data: updatedData,
|
|
216
|
-
state: 'changed',
|
|
217
|
-
lastChange: changeEvent,
|
|
218
|
-
});
|
|
219
|
-
},
|
|
220
|
-
patch(context) {
|
|
221
|
-
const currentData = cloneDeep(store.data());
|
|
222
|
-
// Update the value and prepare the change event
|
|
223
|
-
const updatedData = { ...currentData, ...context };
|
|
224
|
-
const changeEvent = {
|
|
225
|
-
state: 'patch',
|
|
226
|
-
data: updatedData,
|
|
227
|
-
};
|
|
228
|
-
// Patch the state
|
|
229
|
-
patchState(store, {
|
|
230
|
-
previousSnapshot: store.snapshot(), // Save the previous state
|
|
231
|
-
data: updatedData,
|
|
232
|
-
state: 'changed',
|
|
233
|
-
lastChange: changeEvent,
|
|
234
|
-
});
|
|
235
|
-
},
|
|
236
|
-
// Reset to the initial state
|
|
237
|
-
reset() {
|
|
238
|
-
const initialData = store.initial();
|
|
239
|
-
const changeEvent = {
|
|
240
|
-
oldValue: cloneDeep(store.data()), // Current data becomes old value
|
|
241
|
-
newValue: cloneDeep(initialData), // Reset to the initial state
|
|
242
|
-
path: '',
|
|
243
|
-
state: 'restored',
|
|
244
|
-
data: initialData,
|
|
14
|
+
/**
|
|
15
|
+
* Convert Layout Builder definition to Layout Renderer format
|
|
16
|
+
* با processing و cleaning options
|
|
17
|
+
*/
|
|
18
|
+
convertToLayoutRenderer(definition) {
|
|
19
|
+
const layoutDefinition = {
|
|
20
|
+
zones: {},
|
|
21
|
+
styles: definition.layoutConfig ? this.convertGridLayoutToStyles(definition.layoutConfig) : {}
|
|
245
22
|
};
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
// Initialize the state
|
|
254
|
-
set(initialData) {
|
|
255
|
-
const currentData = store.data();
|
|
256
|
-
if (isEqual(currentData, initialData)) {
|
|
257
|
-
return; // Skip if the current state matches the initial state
|
|
258
|
-
}
|
|
259
|
-
const changeEvent = {
|
|
260
|
-
oldValue: null,
|
|
261
|
-
newValue: cloneDeep(initialData),
|
|
262
|
-
path: '',
|
|
263
|
-
state: 'initiated',
|
|
264
|
-
data: initialData,
|
|
23
|
+
const layoutNodes = [];
|
|
24
|
+
let nodeCounter = 0;
|
|
25
|
+
// Helper: count all nodes recursively
|
|
26
|
+
const countNodes = (nodes) => {
|
|
27
|
+
if (!nodes || nodes.length === 0)
|
|
28
|
+
return 0;
|
|
29
|
+
return nodes.reduce((acc, n) => acc + 1 + countNodes(n.children), 0);
|
|
265
30
|
};
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
contact: 'contact-editor',
|
|
286
|
-
dateTime: 'date-time-editor',
|
|
287
|
-
largeText: 'large-text-editor',
|
|
288
|
-
number: 'number-editor',
|
|
289
|
-
numberUnit: 'number-unit-editor',
|
|
290
|
-
password: 'password-editor',
|
|
291
|
-
richText: 'rich-text-editor',
|
|
292
|
-
select: 'select-editor',
|
|
293
|
-
selectionList: 'selection-list-editor',
|
|
294
|
-
text: 'text-editor',
|
|
295
|
-
table: 'table-editor',
|
|
296
|
-
toggle: 'toggle-editor',
|
|
297
|
-
blockLayout: 'block-layout',
|
|
298
|
-
pageLayout: 'page-layout',
|
|
299
|
-
repeaterLayout: 'repeater-layout',
|
|
300
|
-
textBlockLayout: 'text-block-layout',
|
|
301
|
-
fileUploader: 'file-uploader',
|
|
302
|
-
fileTypeExtension: 'file-type-extension',
|
|
303
|
-
map: 'map',
|
|
304
|
-
imageMarker: 'image-marker',
|
|
305
|
-
image: 'image',
|
|
306
|
-
gallery: 'gallery',
|
|
307
|
-
signature: 'signature',
|
|
308
|
-
buttonAction: 'button-action',
|
|
309
|
-
document: 'document-layout',
|
|
310
|
-
lookup: 'lookup-editor',
|
|
311
|
-
formField: 'form-field',
|
|
312
|
-
qrcode: 'qrcode',
|
|
313
|
-
advancedGrid: 'advanced-grid-layout',
|
|
314
|
-
advancedGridItem: 'advanced-grid-item-layout',
|
|
315
|
-
grid: 'grid-layout',
|
|
316
|
-
gridItem: 'grid-item-layout',
|
|
317
|
-
// gridRow: 'grid-row-layout',
|
|
318
|
-
widgetSelector: 'widget-selector',
|
|
319
|
-
template: 'template',
|
|
320
|
-
templateDesigner: 'template-designer',
|
|
321
|
-
cronJob: 'cron-job',
|
|
322
|
-
spacing: 'spacing',
|
|
323
|
-
direction: 'direction',
|
|
324
|
-
border: 'border',
|
|
325
|
-
flexLayout: 'flex-layout',
|
|
326
|
-
flexItem: 'flex-item-layout',
|
|
327
|
-
tableLayout: 'table-layout',
|
|
328
|
-
tableItem: 'table-item-layout',
|
|
329
|
-
avatar: 'avatar',
|
|
330
|
-
themePaletteChooser: 'theme-palette-chooser',
|
|
331
|
-
themeModeChooser: 'theme-mode-chooser',
|
|
332
|
-
menuOrientationChooser: 'menu-orientation-chooser',
|
|
333
|
-
fontStyleChooser: 'font-style-chooser',
|
|
334
|
-
fontSizeChooser: 'font-size-chooser',
|
|
335
|
-
iconChooser: 'icon-chooser',
|
|
336
|
-
themeColorChooser: 'theme-color-chooser',
|
|
337
|
-
gridOptions: 'grid-options',
|
|
338
|
-
gridItemOptions: 'grid-item-options',
|
|
339
|
-
advancedGridOptions: 'advanced-grid-options',
|
|
340
|
-
stringFilter: 'string-filter',
|
|
341
|
-
numberFilter: 'number-filter',
|
|
342
|
-
dateTimeFilter: 'datetime-filter',
|
|
343
|
-
booleanFilter: 'boolean-filter',
|
|
344
|
-
lookupFilter: 'lookup-filter',
|
|
345
|
-
flexOptions: 'flex-options',
|
|
346
|
-
flexItemOptions: 'flex-item-options',
|
|
347
|
-
selectFilter: 'select-filter',
|
|
348
|
-
requiredValidation: 'required-validation',
|
|
349
|
-
regularExpressionValidation: 'regular-expression-validation',
|
|
350
|
-
minLengthValidation: 'min-length-validation',
|
|
351
|
-
maxLengthValidation: 'max-length-validation',
|
|
352
|
-
lessThanValidation: 'less-than-validation',
|
|
353
|
-
greaterThanValidation: 'greater-than-validation',
|
|
354
|
-
betweenValidation: 'between-validation',
|
|
355
|
-
equalValidation: 'equal-validation',
|
|
356
|
-
callbackValidation: 'callback-validation',
|
|
357
|
-
donutChart: 'donut-chart',
|
|
358
|
-
lineChart: 'line-chart',
|
|
359
|
-
barChart: 'bar-chart',
|
|
360
|
-
gaugeChart: 'gauge-chart',
|
|
361
|
-
stickyNote: 'sticky-note',
|
|
362
|
-
clockCalendar: 'clock-calendar',
|
|
363
|
-
analogClock: 'analog-clock',
|
|
364
|
-
weather: 'weather',
|
|
365
|
-
minimalWeather: 'minimal-weather',
|
|
366
|
-
advancedWeather: 'advanced-weather',
|
|
367
|
-
metaData: 'meta-data-editor',
|
|
368
|
-
templateEditor: 'template-box-editor',
|
|
369
|
-
panel: 'panel',
|
|
370
|
-
notification: 'notification',
|
|
371
|
-
taskBoard: 'task-board',
|
|
372
|
-
comment: 'comment',
|
|
373
|
-
list: 'list',
|
|
374
|
-
listToolbar: 'list-toolbar',
|
|
375
|
-
entityList: 'entity-list',
|
|
376
|
-
documentUploader: 'document-uploader',
|
|
377
|
-
};
|
|
378
|
-
|
|
379
|
-
function cloneProperty(property, values) {
|
|
380
|
-
return merge(cloneDeep(property), values);
|
|
381
|
-
}
|
|
382
|
-
function createStringProperty(ctor) {
|
|
383
|
-
return {
|
|
384
|
-
name: ctor.name,
|
|
385
|
-
title: ctor.title,
|
|
386
|
-
group: ctor.group,
|
|
387
|
-
schema: {
|
|
388
|
-
dataType: 'string',
|
|
389
|
-
defaultValue: ctor.defaultValue,
|
|
390
|
-
interface: {
|
|
391
|
-
name: ctor.name,
|
|
392
|
-
path: ctor.path ?? ctor.name,
|
|
393
|
-
type: AXPWidgetsCatalog.text,
|
|
394
|
-
},
|
|
395
|
-
},
|
|
396
|
-
visible: !isNil(ctor.visible) ? ctor.visible : true,
|
|
397
|
-
};
|
|
398
|
-
}
|
|
399
|
-
function createNumberProperty(ctor) {
|
|
400
|
-
return {
|
|
401
|
-
name: ctor.name,
|
|
402
|
-
title: ctor.title,
|
|
403
|
-
group: ctor.group,
|
|
404
|
-
schema: {
|
|
405
|
-
dataType: 'number',
|
|
406
|
-
defaultValue: ctor.defaultValue,
|
|
407
|
-
interface: {
|
|
408
|
-
name: ctor.name,
|
|
409
|
-
path: ctor.path ?? ctor.name,
|
|
410
|
-
type: AXPWidgetsCatalog.number,
|
|
411
|
-
options: ctor.options,
|
|
412
|
-
},
|
|
413
|
-
},
|
|
414
|
-
visible: !isNil(ctor.visible) ? ctor.visible : true,
|
|
415
|
-
};
|
|
416
|
-
}
|
|
417
|
-
function createBooleanProperty(ctor) {
|
|
418
|
-
return {
|
|
419
|
-
name: ctor.name,
|
|
420
|
-
title: ctor.title,
|
|
421
|
-
group: ctor.group,
|
|
422
|
-
schema: {
|
|
423
|
-
dataType: 'boolean',
|
|
424
|
-
defaultValue: ctor.defaultValue ?? false,
|
|
425
|
-
interface: {
|
|
426
|
-
name: ctor.name,
|
|
427
|
-
path: ctor.path ?? ctor.name,
|
|
428
|
-
type: AXPWidgetsCatalog.toggle,
|
|
429
|
-
},
|
|
430
|
-
},
|
|
431
|
-
visible: ctor.visible ?? true,
|
|
432
|
-
};
|
|
433
|
-
}
|
|
434
|
-
function createSelectProperty(ctor) {
|
|
435
|
-
return {
|
|
436
|
-
name: ctor.name,
|
|
437
|
-
title: ctor.title,
|
|
438
|
-
group: ctor.group,
|
|
439
|
-
schema: {
|
|
440
|
-
dataType: 'string',
|
|
441
|
-
defaultValue: Array.isArray(ctor.defaultValue)
|
|
442
|
-
? ctor.defaultValue.map((item) => (typeof item === 'string' ? { id: item } : item))
|
|
443
|
-
: typeof ctor.defaultValue === 'string'
|
|
444
|
-
? { id: ctor.defaultValue, title: ctor.defaultValue }
|
|
445
|
-
: ctor.defaultValue,
|
|
446
|
-
interface: {
|
|
447
|
-
name: ctor.name,
|
|
448
|
-
path: ctor.path ?? ctor.name,
|
|
449
|
-
type: AXPWidgetsCatalog.select,
|
|
450
|
-
options: {
|
|
451
|
-
dataSource: ctor.dataSource.map((item) => (typeof item === 'string' ? { id: item, title: item } : item)),
|
|
452
|
-
},
|
|
453
|
-
},
|
|
454
|
-
},
|
|
455
|
-
visible: ctor.visible ?? true,
|
|
456
|
-
};
|
|
457
|
-
}
|
|
458
|
-
const AXP_WIDGET_TOKEN = new InjectionToken('AXP_WIDGET_TOKEN');
|
|
459
|
-
const AXP_WIDGET_COLUMN_TOKEN = new InjectionToken('AXP_WIDGET_COLUMN_TOKEN');
|
|
460
|
-
|
|
461
|
-
class AXPBaseWidgetComponent extends AXPLayoutElement {
|
|
462
|
-
constructor() {
|
|
463
|
-
super(...arguments);
|
|
464
|
-
this.token = inject(AXP_WIDGET_TOKEN);
|
|
465
|
-
this.host = inject(ElementRef).nativeElement;
|
|
466
|
-
this.layoutService = inject(AXPLayoutBuilderService);
|
|
467
|
-
this.contextService = inject(AXPLayoutBuilderContextStore);
|
|
468
|
-
this.config = this.token.config;
|
|
469
|
-
this.node = this.token.node;
|
|
470
|
-
this.name = this.token.node.name;
|
|
471
|
-
this.component = this;
|
|
472
|
-
this._options = signal(this.token.options ?? {}, ...(ngDevMode ? [{ debugName: "_options" }] : []));
|
|
473
|
-
this.options = this._options.asReadonly();
|
|
474
|
-
this.onOptionsChanged = new Subject();
|
|
475
|
-
this._status = signal(AXPWidgetStatus.Rendering, ...(ngDevMode ? [{ debugName: "_status" }] : []));
|
|
476
|
-
this.status = this._status.asReadonly();
|
|
477
|
-
this.onStatusChanged = new BehaviorSubject(this._status());
|
|
478
|
-
this.#statusEffect = effect(() => {
|
|
479
|
-
this.onStatusChanged.next(this.status());
|
|
480
|
-
}, ...(ngDevMode ? [{ debugName: "#statusEffect" }] : []));
|
|
481
|
-
this.isBusy = computed(() => [AXPWidgetStatus.Rendering, AXPWidgetStatus.Processing].includes(this.status()), ...(ngDevMode ? [{ debugName: "isBusy" }] : []));
|
|
482
|
-
this._children = signal(this.token.node.children ?? [], ...(ngDevMode ? [{ debugName: "_children" }] : []));
|
|
483
|
-
this.children = this._children.asReadonly();
|
|
484
|
-
}
|
|
485
|
-
get id() {
|
|
486
|
-
return this._id;
|
|
487
|
-
}
|
|
488
|
-
#statusEffect;
|
|
489
|
-
outputs() {
|
|
490
|
-
return [];
|
|
491
|
-
}
|
|
492
|
-
ngOnInit() {
|
|
493
|
-
if (get(this.node, '__meta__.added')) {
|
|
494
|
-
this.onAdded();
|
|
495
|
-
}
|
|
496
|
-
this.setStatus(AXPWidgetStatus.Rendered);
|
|
497
|
-
}
|
|
498
|
-
setStatus(status) {
|
|
499
|
-
this._status.set(status);
|
|
500
|
-
this.layoutService.updateStatus();
|
|
501
|
-
}
|
|
502
|
-
setOptions(values) {
|
|
503
|
-
const oldValue = this.options();
|
|
504
|
-
const value = cloneDeep(values);
|
|
505
|
-
this._options.set({ ...oldValue, ...value });
|
|
506
|
-
this.onOptionsChanged.next({ sender: this });
|
|
507
|
-
}
|
|
508
|
-
output(name) {
|
|
509
|
-
const outputs = this.outputs().map((c) => (typeof c == 'string' ? { name: c, value: c } : c));
|
|
510
|
-
if (outputs.some((c) => c.name == name)) {
|
|
511
|
-
const opt = get(this, name);
|
|
512
|
-
if (typeof opt == 'function') {
|
|
513
|
-
return opt();
|
|
514
|
-
}
|
|
515
|
-
return opt;
|
|
516
|
-
}
|
|
517
|
-
return null;
|
|
518
|
-
}
|
|
519
|
-
call(name, ...args) {
|
|
520
|
-
const fn = get(this, name);
|
|
521
|
-
if (fn && typeof fn == 'function') {
|
|
522
|
-
fn.bind(this)(...args);
|
|
523
|
-
}
|
|
524
|
-
}
|
|
525
|
-
setChildren(children) {
|
|
526
|
-
this._children.set([...children]);
|
|
527
|
-
}
|
|
528
|
-
onAdded() { }
|
|
529
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPBaseWidgetComponent, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
530
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPBaseWidgetComponent }); }
|
|
531
|
-
}
|
|
532
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPBaseWidgetComponent, decorators: [{
|
|
533
|
-
type: Injectable
|
|
534
|
-
}] });
|
|
535
|
-
class AXPLayoutBaseWidgetComponent extends AXPBaseWidgetComponent {
|
|
536
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPLayoutBaseWidgetComponent, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
537
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPLayoutBaseWidgetComponent }); }
|
|
538
|
-
}
|
|
539
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPLayoutBaseWidgetComponent, decorators: [{
|
|
540
|
-
type: Injectable
|
|
541
|
-
}] });
|
|
542
|
-
class AXPValueWidgetComponent extends AXPLayoutBaseWidgetComponent {
|
|
543
|
-
constructor() {
|
|
544
|
-
super(...arguments);
|
|
545
|
-
this.path = this.token.node.path;
|
|
546
|
-
this.defaultValue = this.token.defaultValue ?? this.token.node.defaultValue;
|
|
547
|
-
this._isValueWidget = false;
|
|
548
|
-
this.isValueWidget = () => this._isValueWidget;
|
|
549
|
-
this.onValueChanged = new Subject();
|
|
550
|
-
this.fullPath = signal(null, ...(ngDevMode ? [{ debugName: "fullPath" }] : []));
|
|
551
|
-
this.parentPath = signal(null, ...(ngDevMode ? [{ debugName: "parentPath" }] : []));
|
|
552
|
-
this.getValue = computed(() => {
|
|
553
|
-
return this.fullPath() ? this.extractValue(this.fullPath()) : null;
|
|
554
|
-
}, ...(ngDevMode ? [{ debugName: "getValue", equal: isEqual }] : [{ equal: isEqual }]));
|
|
555
|
-
this.validationRules = computed(() => {
|
|
556
|
-
const validationsRaw = this.options()['validations'];
|
|
557
|
-
if (validationsRaw == null) {
|
|
558
|
-
return [];
|
|
559
|
-
}
|
|
560
|
-
return Object.values(this.options()['validations'])
|
|
561
|
-
.filter((c) => c != null)
|
|
562
|
-
.map((c) => ({
|
|
563
|
-
rule: c.rule,
|
|
564
|
-
message: c.message,
|
|
565
|
-
options: c.options,
|
|
566
|
-
}));
|
|
567
|
-
}, ...(ngDevMode ? [{ debugName: "validationRules" }] : []));
|
|
568
|
-
}
|
|
569
|
-
ngOnInit() {
|
|
570
|
-
this._isValueWidget = this.config.properties?.some((c) => c.name == 'path') ?? false;
|
|
571
|
-
if (this.isValueWidget()) {
|
|
572
|
-
this.detectFullPath();
|
|
573
|
-
if (!isNil(this.defaultValue) && isNil(this.getValue())) {
|
|
574
|
-
this.setValue(this.defaultValue);
|
|
575
|
-
}
|
|
576
|
-
}
|
|
577
|
-
//
|
|
578
|
-
super.ngOnInit();
|
|
579
|
-
}
|
|
580
|
-
extractValue(path) {
|
|
581
|
-
const rawValue = this.contextService.getValue(path);
|
|
582
|
-
if (this.node.valueTransforms?.getter) {
|
|
583
|
-
return this.node.valueTransforms?.getter(rawValue);
|
|
584
|
-
}
|
|
585
|
-
return rawValue;
|
|
586
|
-
}
|
|
587
|
-
setValue(value) {
|
|
588
|
-
if (this.node.valueTransforms?.setter) {
|
|
589
|
-
value = this.node.valueTransforms?.setter(value);
|
|
590
|
-
}
|
|
591
|
-
const oldValue = this.getValue();
|
|
592
|
-
value = isUndefined(value) ? null : value;
|
|
593
|
-
if (isNil(value) && isNil(oldValue)) {
|
|
594
|
-
return;
|
|
595
|
-
}
|
|
596
|
-
if (isEqual(oldValue, value)) {
|
|
597
|
-
return;
|
|
598
|
-
}
|
|
599
|
-
if (this.fullPath()) {
|
|
600
|
-
this.contextService.update(this.fullPath(), value);
|
|
601
|
-
this.onValueChanged.next({ sender: this });
|
|
602
|
-
}
|
|
603
|
-
}
|
|
604
|
-
detectFullPath() {
|
|
605
|
-
const sections = [];
|
|
606
|
-
const ids = [];
|
|
607
|
-
//
|
|
608
|
-
let parent = this;
|
|
609
|
-
//
|
|
610
|
-
while (parent) {
|
|
611
|
-
const isValueWidget = parent instanceof AXPValueWidgetComponent && parent.isValueWidget();
|
|
612
|
-
const valueParent = parent;
|
|
613
|
-
const path = valueParent.path ?? (isValueWidget ? valueParent.name : null);
|
|
614
|
-
const id = valueParent.name;
|
|
615
|
-
//
|
|
616
|
-
if (path) {
|
|
617
|
-
sections.push(path);
|
|
618
|
-
}
|
|
619
|
-
if (parent.index != null && isValueWidget) {
|
|
620
|
-
sections.push(`[${parent.index}]`);
|
|
621
|
-
}
|
|
622
|
-
if (id) {
|
|
623
|
-
ids.push(id);
|
|
624
|
-
if (parent.index != null) {
|
|
625
|
-
ids.push(`${parent.index}`);
|
|
31
|
+
const totalNodeCount = countNodes(definition.nodes);
|
|
32
|
+
const hasMultipleNodes = totalNodeCount > 1;
|
|
33
|
+
// Process nodes recursively - flatten everything into the same zone
|
|
34
|
+
const processNodes = (nodes, parentZone = 'main') => {
|
|
35
|
+
nodes.forEach((node) => {
|
|
36
|
+
if (!node.widget)
|
|
37
|
+
return;
|
|
38
|
+
// Create layout node for widget
|
|
39
|
+
const nodeId = node.id || `widget-${nodeCounter++}`;
|
|
40
|
+
const layoutNode = {
|
|
41
|
+
id: nodeId,
|
|
42
|
+
type: node.widget.type,
|
|
43
|
+
zone: parentZone,
|
|
44
|
+
mode: node.mode || 'edit',
|
|
45
|
+
options: node.widget.options || {}
|
|
46
|
+
};
|
|
47
|
+
// Convert layout config to node layout
|
|
48
|
+
if (node.layout) {
|
|
49
|
+
layoutNode.layout = this.convertToNodeLayout(node.layout);
|
|
626
50
|
}
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
//
|
|
631
|
-
this.fullPath.set(sections.reverse().join('.'));
|
|
632
|
-
this.parentPath.set(sections.slice(0, sections.length - 1).join('.'));
|
|
633
|
-
this._id = this.name || this.parent ? ids.reverse().join('_') : null;
|
|
634
|
-
if (this._id) {
|
|
635
|
-
this.layoutService.registerWidget(this._id, this);
|
|
636
|
-
}
|
|
637
|
-
}
|
|
638
|
-
handleValueChanged(e) {
|
|
639
|
-
if (e.isUserInteraction) {
|
|
640
|
-
this.setValue(e.value);
|
|
641
|
-
}
|
|
642
|
-
}
|
|
643
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPValueWidgetComponent, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
644
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPValueWidgetComponent }); }
|
|
645
|
-
}
|
|
646
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPValueWidgetComponent, decorators: [{
|
|
647
|
-
type: Injectable
|
|
648
|
-
}] });
|
|
649
|
-
class AXPDataListWidgetComponent extends AXPValueWidgetComponent {
|
|
650
|
-
constructor() {
|
|
651
|
-
super(...arguments);
|
|
652
|
-
this.dataService = inject(AXPDataSourceDefinitionProviderService);
|
|
653
|
-
this.textField = computed(() => this.options()['textField'] ?? 'title', ...(ngDevMode ? [{ debugName: "textField" }] : []));
|
|
654
|
-
this.valueField = computed(() => this.options()['valueField'] ?? 'id', ...(ngDevMode ? [{ debugName: "valueField" }] : []));
|
|
655
|
-
this.dataSource = signal(convertArrayToDataSource([]), ...(ngDevMode ? [{ debugName: "dataSource" }] : []));
|
|
656
|
-
this.isReady = computed(() => {
|
|
657
|
-
const key = this.dataSource().config?.key;
|
|
658
|
-
const valueField = this.valueField();
|
|
659
|
-
const result = key == valueField;
|
|
660
|
-
return result;
|
|
661
|
-
}, ...(ngDevMode ? [{ debugName: "isReady" }] : []));
|
|
662
|
-
this.selectedItems = signal([], ...(ngDevMode ? [{ debugName: "selectedItems" }] : []));
|
|
663
|
-
this.rf = effect(async () => {
|
|
664
|
-
const rawValue = this.options()['dataSource'];
|
|
665
|
-
// static datasource class
|
|
666
|
-
if (rawValue instanceof AXDataSource) {
|
|
667
|
-
this.dataSource.set(rawValue);
|
|
668
|
-
}
|
|
669
|
-
// static array datasource
|
|
670
|
-
else if (Array.isArray(rawValue)) {
|
|
671
|
-
const ds = new AXDataSource({
|
|
672
|
-
key: this.valueField(),
|
|
673
|
-
pageSize: 10,
|
|
674
|
-
load: async (e) => {
|
|
675
|
-
const raw = this.options()['dataSource'];
|
|
676
|
-
return {
|
|
677
|
-
items: raw,
|
|
678
|
-
total: raw.length,
|
|
679
|
-
};
|
|
680
|
-
},
|
|
681
|
-
byKey: (key) => {
|
|
682
|
-
const raw = this.options()['dataSource'];
|
|
683
|
-
const item = raw.filter((c) => c[this.valueField()] == key);
|
|
684
|
-
return Promise.resolve(item[0]);
|
|
685
|
-
},
|
|
686
|
-
});
|
|
687
|
-
this.dataSource.set(ds);
|
|
688
|
-
}
|
|
689
|
-
// resolve data source by name
|
|
690
|
-
else if (rawValue && (typeof rawValue == 'string' || typeof rawValue == 'object')) {
|
|
691
|
-
const id = typeof rawValue == 'object' ? rawValue['id'] : rawValue;
|
|
692
|
-
const c = await this.dataService.get(id);
|
|
693
|
-
if (this.mode == 'designer' && c?.samples?.length) {
|
|
694
|
-
this.dataSource.set(convertArrayToDataSource(c.samples, {
|
|
695
|
-
key: this.valueField(),
|
|
696
|
-
pageSize: 500,
|
|
697
|
-
}));
|
|
51
|
+
else if (hasMultipleNodes && definition.layoutConfig) {
|
|
52
|
+
// Apply default layout for multi-node structures when node has no explicit layout
|
|
53
|
+
layoutNode.layout = this.convertToNodeLayout(definition.layoutConfig);
|
|
698
54
|
}
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
if (
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
}
|
|
705
|
-
else if (ds) {
|
|
706
|
-
this.dataSource.set(ds);
|
|
707
|
-
}
|
|
708
|
-
// empty datasource
|
|
709
|
-
else {
|
|
710
|
-
this.dataSource.set(convertArrayToDataSource([]));
|
|
711
|
-
}
|
|
55
|
+
// Add order if specified
|
|
56
|
+
if (node.order !== undefined) {
|
|
57
|
+
if (!layoutNode.layout)
|
|
58
|
+
layoutNode.layout = {};
|
|
59
|
+
layoutNode.layout.order = typeof node.order === 'number' ? node.order : parseInt(node.order.toString());
|
|
712
60
|
}
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
this.effect2 = effect(async () => {
|
|
720
|
-
const value = this.getValue();
|
|
721
|
-
const items = [];
|
|
722
|
-
if (Array.isArray(value)) {
|
|
723
|
-
items.push(...(await Promise.all(value.map((item) => this.extractItem(item)))));
|
|
724
|
-
}
|
|
725
|
-
else {
|
|
726
|
-
items.push(await this.extractItem(value));
|
|
727
|
-
}
|
|
728
|
-
this.selectedItems.set(items.filter((c) => c != null));
|
|
729
|
-
}, ...(ngDevMode ? [{ debugName: "effect2" }] : []));
|
|
730
|
-
}
|
|
731
|
-
async extractItem(item) {
|
|
732
|
-
if (isNil(item)) {
|
|
733
|
-
return null;
|
|
734
|
-
}
|
|
735
|
-
if (isObjectLike(item) && get(item, this.textField()) != null) {
|
|
736
|
-
return item;
|
|
737
|
-
}
|
|
738
|
-
const key = extractValue(item, this.valueField());
|
|
739
|
-
const ds = this.dataSource();
|
|
740
|
-
if (ds.config?.byKey) {
|
|
741
|
-
const found = await ds.config?.byKey(key);
|
|
742
|
-
if (found) {
|
|
743
|
-
return found;
|
|
744
|
-
}
|
|
745
|
-
}
|
|
746
|
-
return isObjectLike(item)
|
|
747
|
-
? item
|
|
748
|
-
: {
|
|
749
|
-
[this.valueField()]: item,
|
|
750
|
-
[this.textField()]: item,
|
|
751
|
-
};
|
|
752
|
-
}
|
|
753
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPDataListWidgetComponent, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
754
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPDataListWidgetComponent }); }
|
|
755
|
-
}
|
|
756
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPDataListWidgetComponent, decorators: [{
|
|
757
|
-
type: Injectable
|
|
758
|
-
}] });
|
|
759
|
-
class AXPColumnWidgetComponent {
|
|
760
|
-
constructor() {
|
|
761
|
-
this.token = inject(AXP_WIDGET_COLUMN_TOKEN);
|
|
762
|
-
this.path = this.token.path;
|
|
763
|
-
this.options = this.token.options ?? {};
|
|
764
|
-
this.rawValue = null;
|
|
765
|
-
this.nullText = this.options['nullText'];
|
|
766
|
-
this.nullValue = this.options['nullValue'];
|
|
767
|
-
this.value = computed(() => {
|
|
768
|
-
if (isNil(this.rawValue) && !isNil(this.nullValue)) {
|
|
769
|
-
return this.nullValue;
|
|
770
|
-
}
|
|
771
|
-
return this.rawValue;
|
|
772
|
-
}, ...(ngDevMode ? [{ debugName: "value" }] : []));
|
|
773
|
-
}
|
|
774
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPColumnWidgetComponent, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
775
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPColumnWidgetComponent }); }
|
|
776
|
-
}
|
|
777
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPColumnWidgetComponent, decorators: [{
|
|
778
|
-
type: Injectable
|
|
779
|
-
}] });
|
|
780
|
-
|
|
781
|
-
class AXPBoxModelLayoutWidgetComponent extends AXPLayoutBaseWidgetComponent {
|
|
782
|
-
constructor() {
|
|
783
|
-
super(...arguments);
|
|
784
|
-
this.hostBoxStyle = computed(() => {
|
|
785
|
-
const options = this.options();
|
|
786
|
-
const style = {};
|
|
787
|
-
const spacing = options?.['spacing'];
|
|
788
|
-
const border = options?.['border'];
|
|
789
|
-
const backgroundColor = options?.['backgroundColor'];
|
|
790
|
-
const direction = options?.['direction'];
|
|
791
|
-
const overflow = options?.['overflow'];
|
|
792
|
-
const overflowX = options?.['overflowX'];
|
|
793
|
-
const overflowY = options?.['overflowY'];
|
|
794
|
-
style['background-color'] = backgroundColor ?? '';
|
|
795
|
-
style['padding'] = spacing?.padding ?? '';
|
|
796
|
-
style['margin'] = spacing?.margin ?? '';
|
|
797
|
-
style['border-radius'] = border?.radius ?? '';
|
|
798
|
-
style['border-width'] = border?.width ?? '';
|
|
799
|
-
style['border-color'] = border?.color ?? '';
|
|
800
|
-
style['border-style'] = border?.style ?? '';
|
|
801
|
-
style['overflow'] = overflow ?? '';
|
|
802
|
-
style['overflow-x'] = overflowX ?? '';
|
|
803
|
-
style['overflow-y'] = overflowY ?? '';
|
|
804
|
-
style['direction'] = direction ?? '';
|
|
805
|
-
return style;
|
|
806
|
-
}, ...(ngDevMode ? [{ debugName: "hostBoxStyle" }] : []));
|
|
807
|
-
this.blockStyle = computed(() => {
|
|
808
|
-
const options = this.options();
|
|
809
|
-
const style = { ...this.hostBoxStyle() };
|
|
810
|
-
const width = options?.['width'];
|
|
811
|
-
const minWidth = options?.['minWidth'];
|
|
812
|
-
const maxWidth = options?.['maxWidth'];
|
|
813
|
-
const height = options?.['height'];
|
|
814
|
-
const minHeight = options?.['minHeight'];
|
|
815
|
-
const maxHeight = options?.['maxHeight'];
|
|
816
|
-
style['min-width'] = minWidth ?? '';
|
|
817
|
-
style['width'] = width ?? '';
|
|
818
|
-
style['max-width'] = maxWidth ?? '';
|
|
819
|
-
style['min-height'] = minHeight ?? '';
|
|
820
|
-
style['height'] = height ?? '';
|
|
821
|
-
style['max-height'] = maxHeight ?? '';
|
|
822
|
-
return style;
|
|
823
|
-
}, ...(ngDevMode ? [{ debugName: "blockStyle" }] : []));
|
|
824
|
-
this.inlineStyle = computed(() => {
|
|
825
|
-
return { ...this.hostBoxStyle() };
|
|
826
|
-
}, ...(ngDevMode ? [{ debugName: "inlineStyle" }] : []));
|
|
827
|
-
this.blockClass = computed(() => {
|
|
828
|
-
return {
|
|
829
|
-
'ax-block': true,
|
|
830
|
-
'ax-w-full': true,
|
|
831
|
-
// 'ax-widget-outline': true,
|
|
832
|
-
};
|
|
833
|
-
}, ...(ngDevMode ? [{ debugName: "blockClass" }] : []));
|
|
834
|
-
this.inlineClass = computed(() => {
|
|
835
|
-
return {
|
|
836
|
-
'ax-inline-block': true,
|
|
837
|
-
};
|
|
838
|
-
}, ...(ngDevMode ? [{ debugName: "inlineClass" }] : []));
|
|
839
|
-
}
|
|
840
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPBoxModelLayoutWidgetComponent, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
841
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPBoxModelLayoutWidgetComponent }); }
|
|
842
|
-
}
|
|
843
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPBoxModelLayoutWidgetComponent, decorators: [{
|
|
844
|
-
type: Injectable
|
|
845
|
-
}] });
|
|
846
|
-
|
|
847
|
-
class AXPBlockBaseLayoutWidgetComponent extends AXPBoxModelLayoutWidgetComponent {
|
|
848
|
-
constructor() {
|
|
849
|
-
super(...arguments);
|
|
850
|
-
this.hostClass = computed(() => this.blockClass(), ...(ngDevMode ? [{ debugName: "hostClass" }] : []));
|
|
851
|
-
this.hostStyle = computed(() => this.blockStyle(), ...(ngDevMode ? [{ debugName: "hostStyle" }] : []));
|
|
852
|
-
}
|
|
853
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPBlockBaseLayoutWidgetComponent, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
854
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPBlockBaseLayoutWidgetComponent }); }
|
|
855
|
-
}
|
|
856
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPBlockBaseLayoutWidgetComponent, decorators: [{
|
|
857
|
-
type: Injectable
|
|
858
|
-
}] });
|
|
859
|
-
|
|
860
|
-
class AXPFlexBaseLayoutWidgetComponent extends AXPBlockBaseLayoutWidgetComponent {
|
|
861
|
-
constructor() {
|
|
862
|
-
super(...arguments);
|
|
863
|
-
this.flex = computed(() => this.options(), ...(ngDevMode ? [{ debugName: "flex" }] : []));
|
|
864
|
-
this.hostFlexStyle = computed(() => {
|
|
865
|
-
const blockStyle = this.blockStyle();
|
|
866
|
-
const style = { ...blockStyle };
|
|
867
|
-
const flex = this.flex();
|
|
868
|
-
if (isNil(flex?.flexDirection)) {
|
|
869
|
-
style['flex-direction'] = '';
|
|
870
|
-
}
|
|
871
|
-
else {
|
|
872
|
-
style['flex-direction'] = flex.flexDirection;
|
|
873
|
-
}
|
|
874
|
-
if (isNil(flex?.flexWrap)) {
|
|
875
|
-
style['flex-wrap'] = '';
|
|
876
|
-
}
|
|
877
|
-
else {
|
|
878
|
-
style['flex-wrap'] = flex.flexWrap;
|
|
879
|
-
}
|
|
880
|
-
//TODO NEED TO FIX LATER
|
|
881
|
-
style['overflow'] = flex?.flexWrap === 'nowrap' ? 'auto' : '';
|
|
882
|
-
//END
|
|
883
|
-
if (isNil(flex?.justifyContent)) {
|
|
884
|
-
style['justify-content'] = '';
|
|
885
|
-
}
|
|
886
|
-
else {
|
|
887
|
-
style['justify-content'] = flex.justifyContent;
|
|
888
|
-
}
|
|
889
|
-
if (isNil(flex?.alignItems)) {
|
|
890
|
-
style['align-items'] = '';
|
|
891
|
-
}
|
|
892
|
-
else {
|
|
893
|
-
style['align-items'] = flex.alignItems;
|
|
894
|
-
}
|
|
895
|
-
if (isNil(flex?.gap)) {
|
|
896
|
-
style['gap'] = '';
|
|
897
|
-
}
|
|
898
|
-
else {
|
|
899
|
-
style['gap'] = flex.gap;
|
|
900
|
-
}
|
|
901
|
-
return style;
|
|
902
|
-
}, ...(ngDevMode ? [{ debugName: "hostFlexStyle" }] : []));
|
|
903
|
-
this.hostFlexClass = computed(() => {
|
|
904
|
-
return {
|
|
905
|
-
...this.blockClass(),
|
|
906
|
-
'ax-flex': true,
|
|
907
|
-
'ax-h-full': true,
|
|
908
|
-
};
|
|
909
|
-
}, ...(ngDevMode ? [{ debugName: "hostFlexClass" }] : []));
|
|
910
|
-
this.hostClass = computed(() => {
|
|
911
|
-
return this.hostFlexClass();
|
|
912
|
-
}, ...(ngDevMode ? [{ debugName: "hostClass" }] : []));
|
|
913
|
-
this.hostStyle = computed(() => {
|
|
914
|
-
return this.hostFlexStyle();
|
|
915
|
-
}, ...(ngDevMode ? [{ debugName: "hostStyle" }] : []));
|
|
916
|
-
}
|
|
917
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPFlexBaseLayoutWidgetComponent, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
918
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPFlexBaseLayoutWidgetComponent }); }
|
|
919
|
-
}
|
|
920
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPFlexBaseLayoutWidgetComponent, decorators: [{
|
|
921
|
-
type: Injectable
|
|
922
|
-
}] });
|
|
923
|
-
|
|
924
|
-
class AXPInlineBaseLayoutWidgetComponent extends AXPBoxModelLayoutWidgetComponent {
|
|
925
|
-
constructor() {
|
|
926
|
-
super(...arguments);
|
|
927
|
-
this.hostClass = computed(() => this.inlineClass(), ...(ngDevMode ? [{ debugName: "hostClass" }] : []));
|
|
928
|
-
this.hostStyle = computed(() => this.inlineStyle(), ...(ngDevMode ? [{ debugName: "hostStyle" }] : []));
|
|
929
|
-
}
|
|
930
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPInlineBaseLayoutWidgetComponent, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
931
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPInlineBaseLayoutWidgetComponent }); }
|
|
932
|
-
}
|
|
933
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPInlineBaseLayoutWidgetComponent, decorators: [{
|
|
934
|
-
type: Injectable
|
|
935
|
-
}] });
|
|
936
|
-
|
|
937
|
-
class AXPFlexItemBaseLayoutWidgetComponent extends AXPInlineBaseLayoutWidgetComponent {
|
|
938
|
-
constructor() {
|
|
939
|
-
super(...arguments);
|
|
940
|
-
this.flexItem = computed(() => this.options(), ...(ngDevMode ? [{ debugName: "flexItem" }] : []));
|
|
941
|
-
this.hostFlexItemStyle = computed(() => {
|
|
942
|
-
const inlineStyle = this.blockStyle();
|
|
943
|
-
const style = { ...inlineStyle };
|
|
944
|
-
const fi = this.flexItem();
|
|
945
|
-
if (isNil(fi?.order)) {
|
|
946
|
-
style['order'] = '';
|
|
947
|
-
}
|
|
948
|
-
else {
|
|
949
|
-
style['order'] = fi.order;
|
|
950
|
-
}
|
|
951
|
-
if (isNil(fi?.grow)) {
|
|
952
|
-
style['flex-grow'] = '';
|
|
953
|
-
}
|
|
954
|
-
else {
|
|
955
|
-
style['flex-grow'] = fi.grow;
|
|
956
|
-
}
|
|
957
|
-
if (isNil(fi?.shrink)) {
|
|
958
|
-
style['flex-shrink'] = '';
|
|
959
|
-
}
|
|
960
|
-
else {
|
|
961
|
-
style['flex-shrink'] = fi.shrink;
|
|
962
|
-
}
|
|
963
|
-
if (isNil(fi?.basis)) {
|
|
964
|
-
style['flex-basis'] = '';
|
|
965
|
-
}
|
|
966
|
-
else {
|
|
967
|
-
style['flex-basis'] = fi.basis;
|
|
968
|
-
}
|
|
969
|
-
if (isNil(fi?.alignSelf)) {
|
|
970
|
-
style['align-self'] = '';
|
|
971
|
-
}
|
|
972
|
-
else {
|
|
973
|
-
style['align-self'] = fi.alignSelf;
|
|
974
|
-
}
|
|
975
|
-
return style;
|
|
976
|
-
}, ...(ngDevMode ? [{ debugName: "hostFlexItemStyle" }] : []));
|
|
977
|
-
this.hostFlexItemClass = computed(() => {
|
|
978
|
-
return {
|
|
979
|
-
...this.blockClass(),
|
|
980
|
-
};
|
|
981
|
-
}, ...(ngDevMode ? [{ debugName: "hostFlexItemClass" }] : []));
|
|
982
|
-
this.hostClass = computed(() => {
|
|
983
|
-
return this.hostFlexItemClass();
|
|
984
|
-
}, ...(ngDevMode ? [{ debugName: "hostClass" }] : []));
|
|
985
|
-
this.hostStyle = computed(() => {
|
|
986
|
-
return this.hostFlexItemStyle();
|
|
987
|
-
}, ...(ngDevMode ? [{ debugName: "hostStyle" }] : []));
|
|
988
|
-
}
|
|
989
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPFlexItemBaseLayoutWidgetComponent, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
990
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPFlexItemBaseLayoutWidgetComponent }); }
|
|
991
|
-
}
|
|
992
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPFlexItemBaseLayoutWidgetComponent, decorators: [{
|
|
993
|
-
type: Injectable
|
|
994
|
-
}] });
|
|
995
|
-
|
|
996
|
-
class AXPGridBaseLayoutWidgetComponent extends AXPBlockBaseLayoutWidgetComponent {
|
|
997
|
-
constructor() {
|
|
998
|
-
super(...arguments);
|
|
999
|
-
this.grid = computed(() => this.options()?.['grid'], ...(ngDevMode ? [{ debugName: "grid" }] : []));
|
|
1000
|
-
this.hostGridStyle = computed(() => {
|
|
1001
|
-
const style = { ...this.inlineStyle() };
|
|
1002
|
-
const g = this.grid()?.default;
|
|
1003
|
-
if (g?.gap)
|
|
1004
|
-
style['gap'] = g.gap;
|
|
1005
|
-
return style;
|
|
1006
|
-
}, ...(ngDevMode ? [{ debugName: "hostGridStyle" }] : []));
|
|
1007
|
-
this.hostGridClass = computed(() => {
|
|
1008
|
-
const cls = {
|
|
1009
|
-
...this.inlineClass(),
|
|
1010
|
-
'ax-grid': true,
|
|
1011
|
-
};
|
|
1012
|
-
const g = this.grid()?.default;
|
|
1013
|
-
if (g?.columns)
|
|
1014
|
-
cls[`lg:ax-grid-cols-${g.columns}`] = true;
|
|
1015
|
-
if (g?.rows)
|
|
1016
|
-
cls[`lg:ax-grid-rows-${g.rows}`] = true;
|
|
1017
|
-
if (g?.justifyItems)
|
|
1018
|
-
cls[`lg:ax-justify-items-${g.justifyItems}`] = true;
|
|
1019
|
-
if (g?.alignItems)
|
|
1020
|
-
cls[`lg:ax-align-items-${g.alignItems}`] = true;
|
|
1021
|
-
if (g?.autoFlow)
|
|
1022
|
-
cls[`lg:ax-grid-flow-${g.autoFlow}`] = true;
|
|
1023
|
-
return cls;
|
|
1024
|
-
}, ...(ngDevMode ? [{ debugName: "hostGridClass" }] : []));
|
|
1025
|
-
this.hostClass = computed(() => this.hostGridClass(), ...(ngDevMode ? [{ debugName: "hostClass" }] : []));
|
|
1026
|
-
this.hostStyle = computed(() => this.hostGridStyle(), ...(ngDevMode ? [{ debugName: "hostStyle" }] : []));
|
|
1027
|
-
}
|
|
1028
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPGridBaseLayoutWidgetComponent, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1029
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPGridBaseLayoutWidgetComponent }); }
|
|
1030
|
-
}
|
|
1031
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPGridBaseLayoutWidgetComponent, decorators: [{
|
|
1032
|
-
type: Injectable
|
|
1033
|
-
}] });
|
|
1034
|
-
|
|
1035
|
-
class AXPGridItemBaseLayoutWidgetComponent extends AXPFlexBaseLayoutWidgetComponent {
|
|
1036
|
-
constructor() {
|
|
1037
|
-
super(...arguments);
|
|
1038
|
-
this.gridItem = computed(() => this.options(), ...(ngDevMode ? [{ debugName: "gridItem" }] : []));
|
|
1039
|
-
this.hostGridItemStyle = computed(() => {
|
|
1040
|
-
const style = { ...this.hostFlexStyle() };
|
|
1041
|
-
const g = this.gridItem();
|
|
1042
|
-
if (g?.alignSelf)
|
|
1043
|
-
style['align-self'] = g.alignSelf;
|
|
1044
|
-
if (g?.justifySelf)
|
|
1045
|
-
style['justify-self'] = g.justifySelf;
|
|
1046
|
-
return style;
|
|
1047
|
-
}, ...(ngDevMode ? [{ debugName: "hostGridItemStyle" }] : []));
|
|
1048
|
-
this.hostGridItemClass = computed(() => {
|
|
1049
|
-
const cls = { ...this.hostFlexClass() };
|
|
1050
|
-
const g = this.gridItem();
|
|
1051
|
-
if (g?.colSpan)
|
|
1052
|
-
cls[`lg:ax-col-span-${g.colSpan}`] = true;
|
|
1053
|
-
if (g?.colStart)
|
|
1054
|
-
cls[`lg:ax-col-start-${g.colStart}`] = true;
|
|
1055
|
-
if (g?.colEnd)
|
|
1056
|
-
cls[`lg:ax-col-end-${g.colEnd}`] = true;
|
|
1057
|
-
if (g?.rowSpan)
|
|
1058
|
-
cls[`lg:ax-row-span-${g.rowSpan}`] = true;
|
|
1059
|
-
if (g?.rowStart)
|
|
1060
|
-
cls[`lg:ax-row-start-${g.rowStart}`] = true;
|
|
1061
|
-
if (g?.rowEnd)
|
|
1062
|
-
cls[`lg:ax-row-end-${g.rowEnd}`] = true;
|
|
1063
|
-
return cls;
|
|
1064
|
-
}, ...(ngDevMode ? [{ debugName: "hostGridItemClass" }] : []));
|
|
1065
|
-
this.hostClass = computed(() => this.hostGridItemClass(), ...(ngDevMode ? [{ debugName: "hostClass" }] : []));
|
|
1066
|
-
this.hostStyle = computed(() => this.hostGridItemStyle(), ...(ngDevMode ? [{ debugName: "hostStyle" }] : []));
|
|
1067
|
-
}
|
|
1068
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPGridItemBaseLayoutWidgetComponent, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1069
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPGridItemBaseLayoutWidgetComponent }); }
|
|
1070
|
-
}
|
|
1071
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPGridItemBaseLayoutWidgetComponent, decorators: [{
|
|
1072
|
-
type: Injectable
|
|
1073
|
-
}] });
|
|
1074
|
-
|
|
1075
|
-
class AXPTableBaseLayoutWidgetComponent extends AXPBlockBaseLayoutWidgetComponent {
|
|
1076
|
-
constructor() {
|
|
1077
|
-
super(...arguments);
|
|
1078
|
-
this.hostTableClass = computed(() => ({
|
|
1079
|
-
...this.blockClass(),
|
|
1080
|
-
}), ...(ngDevMode ? [{ debugName: "hostTableClass" }] : []));
|
|
1081
|
-
this.hostTableStyle = computed(() => {
|
|
1082
|
-
const style = { ...this.blockStyle() };
|
|
1083
|
-
style['overflow-x'] = 'auto';
|
|
1084
|
-
return style;
|
|
1085
|
-
}, ...(ngDevMode ? [{ debugName: "hostTableStyle" }] : []));
|
|
1086
|
-
this.hostClass = computed(() => this.hostTableClass(), ...(ngDevMode ? [{ debugName: "hostClass" }] : []));
|
|
1087
|
-
this.hostStyle = computed(() => this.hostTableStyle(), ...(ngDevMode ? [{ debugName: "hostStyle" }] : []));
|
|
1088
|
-
}
|
|
1089
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPTableBaseLayoutWidgetComponent, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1090
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPTableBaseLayoutWidgetComponent }); }
|
|
1091
|
-
}
|
|
1092
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPTableBaseLayoutWidgetComponent, decorators: [{
|
|
1093
|
-
type: Injectable
|
|
1094
|
-
}] });
|
|
1095
|
-
|
|
1096
|
-
class AXPTableItemOpsBaseLayoutWidgetComponent extends AXPBlockBaseLayoutWidgetComponent {
|
|
1097
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPTableItemOpsBaseLayoutWidgetComponent, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1098
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPTableItemOpsBaseLayoutWidgetComponent }); }
|
|
1099
|
-
}
|
|
1100
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPTableItemOpsBaseLayoutWidgetComponent, decorators: [{
|
|
1101
|
-
type: Injectable
|
|
1102
|
-
}] });
|
|
1103
|
-
|
|
1104
|
-
class AXPTableItemBaseLayoutWidgetComponent extends AXPTableItemOpsBaseLayoutWidgetComponent {
|
|
1105
|
-
constructor() {
|
|
1106
|
-
super(...arguments);
|
|
1107
|
-
this.colSpan = computed(() => {
|
|
1108
|
-
const v = this.options()?.colSpan;
|
|
1109
|
-
return v ? Math.max(1, v) : 1;
|
|
1110
|
-
}, ...(ngDevMode ? [{ debugName: "colSpan" }] : []));
|
|
1111
|
-
this.rowSpan = computed(() => {
|
|
1112
|
-
const v = this.options()?.rowSpan;
|
|
1113
|
-
return v ? Math.max(1, v) : 1;
|
|
1114
|
-
}, ...(ngDevMode ? [{ debugName: "rowSpan" }] : []));
|
|
1115
|
-
this.hostClass = computed(() => this.blockClass(), ...(ngDevMode ? [{ debugName: "hostClass" }] : []));
|
|
1116
|
-
this.hostStyle = computed(() => this.blockStyle(), ...(ngDevMode ? [{ debugName: "hostStyle" }] : []));
|
|
1117
|
-
}
|
|
1118
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPTableItemBaseLayoutWidgetComponent, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1119
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPTableItemBaseLayoutWidgetComponent }); }
|
|
1120
|
-
}
|
|
1121
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPTableItemBaseLayoutWidgetComponent, decorators: [{
|
|
1122
|
-
type: Injectable
|
|
1123
|
-
}] });
|
|
1124
|
-
|
|
1125
|
-
class AXPWidgetRegistryService {
|
|
1126
|
-
/**
|
|
1127
|
-
*
|
|
1128
|
-
*/
|
|
1129
|
-
constructor() {
|
|
1130
|
-
this.types = new Map();
|
|
1131
|
-
AXPWidgetRegistryService.instance = this;
|
|
1132
|
-
}
|
|
1133
|
-
register(widget) {
|
|
1134
|
-
this.types.set(widget.name, widget);
|
|
1135
|
-
}
|
|
1136
|
-
extend(parentName, widget) {
|
|
1137
|
-
const parentWidget = this.resolve(parentName);
|
|
1138
|
-
const newWidget = merge({}, parentWidget, widget);
|
|
1139
|
-
newWidget.name = widget.name;
|
|
1140
|
-
this.register(newWidget);
|
|
1141
|
-
}
|
|
1142
|
-
resolve(name) {
|
|
1143
|
-
const widget = this.types.get(name);
|
|
1144
|
-
if (!widget) {
|
|
1145
|
-
throw new Error(`Widget with name "${name}" does not exist.`);
|
|
1146
|
-
}
|
|
1147
|
-
return widget;
|
|
1148
|
-
}
|
|
1149
|
-
all() {
|
|
1150
|
-
return Array.from(this.types.values());
|
|
1151
|
-
}
|
|
1152
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPWidgetRegistryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1153
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPWidgetRegistryService, providedIn: 'root' }); }
|
|
1154
|
-
}
|
|
1155
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPWidgetRegistryService, decorators: [{
|
|
1156
|
-
type: Injectable,
|
|
1157
|
-
args: [{
|
|
1158
|
-
providedIn: 'root',
|
|
1159
|
-
}]
|
|
1160
|
-
}], ctorParameters: () => [] });
|
|
1161
|
-
|
|
1162
|
-
class AXPWidgetColumnRendererComponent extends AXDataTableColumnComponent {
|
|
1163
|
-
constructor() {
|
|
1164
|
-
super(...arguments);
|
|
1165
|
-
this.widgetRegistery = inject(AXPWidgetRegistryService);
|
|
1166
|
-
this.grid = inject(AXBaseDataTable);
|
|
1167
|
-
this.mergedOptions = signal({}, ...(ngDevMode ? [{ debugName: "mergedOptions" }] : []));
|
|
1168
|
-
this.loadingRow = signal(null, ...(ngDevMode ? [{ debugName: "loadingRow" }] : []));
|
|
1169
|
-
this.injector = inject(Injector);
|
|
1170
|
-
this.cdr = inject(ChangeDetectorRef);
|
|
1171
|
-
}
|
|
1172
|
-
get node() {
|
|
1173
|
-
return this._node;
|
|
1174
|
-
}
|
|
1175
|
-
set node(v) {
|
|
1176
|
-
this._node = v;
|
|
1177
|
-
}
|
|
1178
|
-
get renderFooterTemplate() {
|
|
1179
|
-
return this.footerTemplate ?? this._contentFooterTemplate;
|
|
1180
|
-
}
|
|
1181
|
-
get renderCellTemplate() {
|
|
1182
|
-
return this.cellTemplate ?? this._contentCellTemplate;
|
|
1183
|
-
}
|
|
1184
|
-
async handleExpandRow(row) {
|
|
1185
|
-
this.loadingRow.set(row);
|
|
1186
|
-
await this.grid.expandRow(row);
|
|
1187
|
-
this.loadingRow.set(null);
|
|
1188
|
-
// if (row.data?.__meta__?.expanded === undefined) {
|
|
1189
|
-
// this.width = `${parseInt(this.width as string) + 24}px`;
|
|
1190
|
-
// }
|
|
1191
|
-
}
|
|
1192
|
-
get renderHeaderTemplate() {
|
|
1193
|
-
return this.headerTemplate ?? this._contentHeaderTemplate;
|
|
1194
|
-
}
|
|
1195
|
-
get loadingEnabled() {
|
|
1196
|
-
return true;
|
|
1197
|
-
}
|
|
1198
|
-
get name() {
|
|
1199
|
-
return `col-${this.node.path}`;
|
|
1200
|
-
}
|
|
1201
|
-
async ngOnInit() {
|
|
1202
|
-
const widget = this.widgetRegistery.resolve(this.node.type);
|
|
1203
|
-
const mode = 'column';
|
|
1204
|
-
this.component = await widget?.components[mode]?.component();
|
|
1205
|
-
//
|
|
1206
|
-
const props = widget?.components[mode]?.properties
|
|
1207
|
-
?.filter((c) => c.schema.defaultValue)
|
|
1208
|
-
.map((c) => ({ [c.name]: c.schema.defaultValue }))
|
|
1209
|
-
.reduce((acc, curr) => {
|
|
1210
|
-
return { ...acc, ...curr };
|
|
1211
|
-
}, {});
|
|
1212
|
-
//
|
|
1213
|
-
this.mergedOptions.set(merge(props, this.node.options) || {});
|
|
1214
|
-
const tokenValue = {
|
|
1215
|
-
path: this.node.path,
|
|
1216
|
-
options: this.mergedOptions(),
|
|
1217
|
-
};
|
|
1218
|
-
this.widgetInjector = Injector.create({
|
|
1219
|
-
parent: this.injector,
|
|
1220
|
-
providers: [
|
|
1221
|
-
{
|
|
1222
|
-
provide: AXP_WIDGET_COLUMN_TOKEN,
|
|
1223
|
-
useValue: tokenValue,
|
|
1224
|
-
},
|
|
1225
|
-
],
|
|
1226
|
-
});
|
|
1227
|
-
this.width = this.customWidth ? this.customWidth : (this.mergedOptions().width ?? '200px');
|
|
1228
|
-
this.allowResizing = this.mergedOptions().allowResizing || true;
|
|
1229
|
-
this.cdr.detectChanges();
|
|
1230
|
-
}
|
|
1231
|
-
getInputs(data) {
|
|
1232
|
-
return {
|
|
1233
|
-
rawValue: getSmart(data, this.node.path),
|
|
1234
|
-
rowData: data,
|
|
1235
|
-
};
|
|
1236
|
-
}
|
|
1237
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPWidgetColumnRendererComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
1238
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.8", type: AXPWidgetColumnRendererComponent, isStandalone: false, selector: "axp-widget-column-renderer", inputs: { caption: "caption", customExpandIcon: "customExpandIcon", customCollapseIcon: "customCollapseIcon", customWidth: "customWidth", node: "node", footerTemplate: "footerTemplate", expandHandler: "expandHandler", cellTemplate: "cellTemplate", headerTemplate: "headerTemplate" }, providers: [
|
|
1239
|
-
AXPLayoutBuilderService,
|
|
1240
|
-
{ provide: AXDataTableColumnComponent, useExisting: AXPWidgetColumnRendererComponent },
|
|
1241
|
-
], 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, ngImport: i0, template: `
|
|
1242
|
-
<ng-template #header>{{ caption | translate | async }}</ng-template>
|
|
1243
|
-
<ng-template #cell let-row>
|
|
1244
|
-
<div class="ax-flex ax-gap-2 ax-items-center">
|
|
1245
|
-
@if (expandHandler) {
|
|
1246
|
-
<div
|
|
1247
|
-
(click)="handleExpandRow(row)"
|
|
1248
|
-
class="ax-expand-handler"
|
|
1249
|
-
[class.ax-invisible]="row.data.hasChild === false"
|
|
1250
|
-
id="ax-expand-handler-container"
|
|
1251
|
-
[style.padding-inline-start.rem]="row.data?.__meta__?.level * 2"
|
|
1252
|
-
>
|
|
1253
|
-
@if (loadingRow() === row) {
|
|
1254
|
-
<i class="fas fa-spinner-third ax-animate-twSpin ax-animate-infinite"></i>
|
|
1255
|
-
} @else {
|
|
1256
|
-
@if (row.data?.__meta__?.expanded) {
|
|
1257
|
-
<i [class]="customCollapseIcon || 'far fa-minus-square ax-text-md ax-opacity-75'"></i>
|
|
1258
|
-
} @else {
|
|
1259
|
-
<i [class]="customExpandIcon || 'far fa-plus-square ax-text-md ax-opacity-75'"></i>
|
|
1260
|
-
}
|
|
1261
|
-
}
|
|
1262
|
-
</div>
|
|
1263
|
-
}
|
|
1264
|
-
@if (component && widgetInjector && row?.data) {
|
|
1265
|
-
<ng-container
|
|
1266
|
-
*ngComponentOutlet="component; injector: widgetInjector; inputs: getInputs(row.data)"
|
|
1267
|
-
></ng-container>
|
|
1268
|
-
}
|
|
1269
|
-
</div>
|
|
1270
|
-
</ng-template>
|
|
1271
|
-
<ng-template #footer></ng-template>
|
|
1272
|
-
`, isInline: true, dependencies: [{ kind: "directive", type: i1.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"], exportAs: ["ngComponentOutlet"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i2.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1273
|
-
}
|
|
1274
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPWidgetColumnRendererComponent, decorators: [{
|
|
1275
|
-
type: Component,
|
|
1276
|
-
args: [{
|
|
1277
|
-
selector: 'axp-widget-column-renderer',
|
|
1278
|
-
template: `
|
|
1279
|
-
<ng-template #header>{{ caption | translate | async }}</ng-template>
|
|
1280
|
-
<ng-template #cell let-row>
|
|
1281
|
-
<div class="ax-flex ax-gap-2 ax-items-center">
|
|
1282
|
-
@if (expandHandler) {
|
|
1283
|
-
<div
|
|
1284
|
-
(click)="handleExpandRow(row)"
|
|
1285
|
-
class="ax-expand-handler"
|
|
1286
|
-
[class.ax-invisible]="row.data.hasChild === false"
|
|
1287
|
-
id="ax-expand-handler-container"
|
|
1288
|
-
[style.padding-inline-start.rem]="row.data?.__meta__?.level * 2"
|
|
1289
|
-
>
|
|
1290
|
-
@if (loadingRow() === row) {
|
|
1291
|
-
<i class="fas fa-spinner-third ax-animate-twSpin ax-animate-infinite"></i>
|
|
1292
|
-
} @else {
|
|
1293
|
-
@if (row.data?.__meta__?.expanded) {
|
|
1294
|
-
<i [class]="customCollapseIcon || 'far fa-minus-square ax-text-md ax-opacity-75'"></i>
|
|
1295
|
-
} @else {
|
|
1296
|
-
<i [class]="customExpandIcon || 'far fa-plus-square ax-text-md ax-opacity-75'"></i>
|
|
1297
|
-
}
|
|
1298
|
-
}
|
|
1299
|
-
</div>
|
|
1300
|
-
}
|
|
1301
|
-
@if (component && widgetInjector && row?.data) {
|
|
1302
|
-
<ng-container
|
|
1303
|
-
*ngComponentOutlet="component; injector: widgetInjector; inputs: getInputs(row.data)"
|
|
1304
|
-
></ng-container>
|
|
1305
|
-
}
|
|
1306
|
-
</div>
|
|
1307
|
-
</ng-template>
|
|
1308
|
-
<ng-template #footer></ng-template>
|
|
1309
|
-
`,
|
|
1310
|
-
providers: [
|
|
1311
|
-
AXPLayoutBuilderService,
|
|
1312
|
-
{ provide: AXDataTableColumnComponent, useExisting: AXPWidgetColumnRendererComponent },
|
|
1313
|
-
],
|
|
1314
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1315
|
-
inputs: ['caption'],
|
|
1316
|
-
standalone: false,
|
|
1317
|
-
}]
|
|
1318
|
-
}], propDecorators: { customExpandIcon: [{
|
|
1319
|
-
type: Input
|
|
1320
|
-
}], customCollapseIcon: [{
|
|
1321
|
-
type: Input
|
|
1322
|
-
}], customWidth: [{
|
|
1323
|
-
type: Input
|
|
1324
|
-
}], node: [{
|
|
1325
|
-
type: Input,
|
|
1326
|
-
args: [{ required: true }]
|
|
1327
|
-
}], footerTemplate: [{
|
|
1328
|
-
type: Input
|
|
1329
|
-
}], _contentFooterTemplate: [{
|
|
1330
|
-
type: ViewChild,
|
|
1331
|
-
args: ['footer']
|
|
1332
|
-
}], expandHandler: [{
|
|
1333
|
-
type: Input
|
|
1334
|
-
}], cellTemplate: [{
|
|
1335
|
-
type: Input
|
|
1336
|
-
}], _contentCellTemplate: [{
|
|
1337
|
-
type: ViewChild,
|
|
1338
|
-
args: ['cell']
|
|
1339
|
-
}], headerTemplate: [{
|
|
1340
|
-
type: Input
|
|
1341
|
-
}], _contentHeaderTemplate: [{
|
|
1342
|
-
type: ViewChild,
|
|
1343
|
-
args: ['header']
|
|
1344
|
-
}] } });
|
|
1345
|
-
|
|
1346
|
-
class AXPWidgetContainerComponent {
|
|
1347
|
-
set context(value) {
|
|
1348
|
-
this.contextService.set(value);
|
|
1349
|
-
}
|
|
1350
|
-
set functions(v) {
|
|
1351
|
-
this.builderService.setFunctions(v);
|
|
1352
|
-
}
|
|
1353
|
-
constructor() {
|
|
1354
|
-
this.contextService = inject(AXPLayoutBuilderContextStore);
|
|
1355
|
-
this.builderService = inject(AXPLayoutBuilderService);
|
|
1356
|
-
this.onContextChanged = new EventEmitter();
|
|
1357
|
-
this.status = computed(() => {
|
|
1358
|
-
return this.builderService.status();
|
|
1359
|
-
}, ...(ngDevMode ? [{ debugName: "status" }] : []));
|
|
1360
|
-
this.isBusy = computed(() => {
|
|
1361
|
-
return this.builderService.isBusy();
|
|
1362
|
-
}, ...(ngDevMode ? [{ debugName: "isBusy" }] : []));
|
|
1363
|
-
effect(() => {
|
|
1364
|
-
if (this.contextService.isChanged()) {
|
|
1365
|
-
this.onContextChanged.emit(this.contextService.changeEvent());
|
|
1366
|
-
}
|
|
1367
|
-
});
|
|
1368
|
-
}
|
|
1369
|
-
refresh() {
|
|
1370
|
-
this.builderService.refresh();
|
|
1371
|
-
}
|
|
1372
|
-
find(name) {
|
|
1373
|
-
return this.builderService.waitForWidget(name);
|
|
1374
|
-
}
|
|
1375
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPWidgetContainerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1376
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.8", type: AXPWidgetContainerComponent, isStandalone: false, selector: "axp-widgets-container", inputs: { context: "context", functions: "functions" }, outputs: { onContextChanged: "onContextChanged" }, host: { styleAttribute: "display: contents;" }, providers: [AXPLayoutBuilderService, AXPLayoutBuilderContextStore], ngImport: i0, template: `<ng-content></ng-content>`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1377
|
-
}
|
|
1378
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPWidgetContainerComponent, decorators: [{
|
|
1379
|
-
type: Component,
|
|
1380
|
-
args: [{
|
|
1381
|
-
selector: 'axp-widgets-container',
|
|
1382
|
-
template: `<ng-content></ng-content>`,
|
|
1383
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1384
|
-
host: { style: 'display: contents;' },
|
|
1385
|
-
providers: [AXPLayoutBuilderService, AXPLayoutBuilderContextStore],
|
|
1386
|
-
standalone: false,
|
|
1387
|
-
}]
|
|
1388
|
-
}], ctorParameters: () => [], propDecorators: { onContextChanged: [{
|
|
1389
|
-
type: Output
|
|
1390
|
-
}], context: [{
|
|
1391
|
-
type: Input
|
|
1392
|
-
}], functions: [{
|
|
1393
|
-
type: Input
|
|
1394
|
-
}] } });
|
|
1395
|
-
|
|
1396
|
-
class AXPWidgetPlaceholderComponent {
|
|
1397
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPWidgetPlaceholderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1398
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.8", type: AXPWidgetPlaceholderComponent, isStandalone: true, selector: "axp-widget-placeholder", ngImport: i0, template: `<div>
|
|
1399
|
-
<ax-skeleton class="ax-w-full ax-h-10 ax-rounded-md"></ax-skeleton>
|
|
1400
|
-
</div>`, isInline: true, dependencies: [{ kind: "ngmodule", type: AXSkeletonModule }, { kind: "component", type: i1$1.AXSkeletonComponent, selector: "ax-skeleton", inputs: ["animated"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1401
|
-
}
|
|
1402
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPWidgetPlaceholderComponent, decorators: [{
|
|
1403
|
-
type: Component,
|
|
1404
|
-
args: [{
|
|
1405
|
-
selector: 'axp-widget-placeholder',
|
|
1406
|
-
template: `<div>
|
|
1407
|
-
<ax-skeleton class="ax-w-full ax-h-10 ax-rounded-md"></ax-skeleton>
|
|
1408
|
-
</div>`,
|
|
1409
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1410
|
-
imports: [AXSkeletonModule],
|
|
1411
|
-
standalone: true,
|
|
1412
|
-
}]
|
|
1413
|
-
}] });
|
|
1414
|
-
|
|
1415
|
-
class AXPWidgetRendererDirective {
|
|
1416
|
-
//#endregion
|
|
1417
|
-
//#endregion
|
|
1418
|
-
constructor() {
|
|
1419
|
-
this.parentNode = input(...(ngDevMode ? [undefined, { debugName: "parentNode" }] : []));
|
|
1420
|
-
this.index = input(...(ngDevMode ? [undefined, { debugName: "index" }] : []));
|
|
1421
|
-
this.mode = input.required(...(ngDevMode ? [{ debugName: "mode" }] : []));
|
|
1422
|
-
this.node = input.required(...(ngDevMode ? [{ debugName: "node" }] : []));
|
|
1423
|
-
this._options = signal({}, ...(ngDevMode ? [{ debugName: "_options" }] : []));
|
|
1424
|
-
this.options = this._options.asReadonly();
|
|
1425
|
-
this.onOptionsChanged = output();
|
|
1426
|
-
this.onValueChanged = output();
|
|
1427
|
-
//#region ---- Properties ----
|
|
1428
|
-
this.mergedOptions = signal({}, ...(ngDevMode ? [{ debugName: "mergedOptions" }] : []));
|
|
1429
|
-
this.injector = inject(Injector);
|
|
1430
|
-
this.builderService = inject(AXPLayoutBuilderService);
|
|
1431
|
-
this.contextService = inject(AXPLayoutBuilderContextStore);
|
|
1432
|
-
this.widgetRegistery = inject(AXPWidgetRegistryService);
|
|
1433
|
-
this.unsubscriber = inject(AXUnsubscriber);
|
|
1434
|
-
this.translateService = inject(AXTranslationService);
|
|
1435
|
-
this.widgetService = inject(AXPWidgetRegistryService);
|
|
1436
|
-
this.expressionEvaluator = inject(AXPExpressionEvaluatorService);
|
|
1437
|
-
this.viewContainerRef = inject(ViewContainerRef);
|
|
1438
|
-
this.isLoading = signal(false, ...(ngDevMode ? [{ debugName: "isLoading" }] : []));
|
|
1439
|
-
this.expressionEvaluators = new Map();
|
|
1440
|
-
this.renderTimeoutId = null;
|
|
1441
|
-
this.hasInitialRender = false;
|
|
1442
|
-
this.onContextChanged = new Subject();
|
|
1443
|
-
//#region ---- Performance Optimization Properties ----
|
|
1444
|
-
this.contextUpdateQueue = new Set();
|
|
1445
|
-
this.contextUpdateTimeout = null;
|
|
1446
|
-
this.CONTEXT_UPDATE_DEBOUNCE_MS = 4; // ~250fps for large forms
|
|
1447
|
-
// Removed visibility detection - not needed for current implementation
|
|
1448
|
-
// Expression result caching
|
|
1449
|
-
this.expressionCache = new Map();
|
|
1450
|
-
this.EXPRESSION_CACHE_TTL = 500; // Cache for 500ms (increased for better hit rate)
|
|
1451
|
-
// Options change tracking
|
|
1452
|
-
this.lastAppliedOptions = null;
|
|
1453
|
-
// Expression result tracking
|
|
1454
|
-
this.lastExpressionResults = new Map();
|
|
1455
|
-
// Buffer for context changes that happen before initial render completes
|
|
1456
|
-
this.preRenderContextQueue = new Set();
|
|
1457
|
-
effect(async () => {
|
|
1458
|
-
const changed = this.contextService.changeEvent();
|
|
1459
|
-
// Don't trigger re-render during initial setup
|
|
1460
|
-
if (!this.hasInitialRender) {
|
|
1461
|
-
if (changed.path) {
|
|
1462
|
-
this.preRenderContextQueue.add(changed.path);
|
|
1463
|
-
// console.log(`📝 [${this.node().type}] Buffered pre-render context change: ${changed.path}`);
|
|
61
|
+
// Process widget options and content
|
|
62
|
+
this.processWidgetOptions(layoutNode, node);
|
|
63
|
+
layoutNodes.push(layoutNode);
|
|
64
|
+
// Recursively add children into the same zone (flat)
|
|
65
|
+
if (node.children && node.children.length > 0) {
|
|
66
|
+
processNodes(node.children, parentZone);
|
|
1464
67
|
}
|
|
68
|
+
});
|
|
69
|
+
};
|
|
70
|
+
// Create zones in order and assign auto-order to nodes (recursively)
|
|
71
|
+
let nodeOrder = 1;
|
|
72
|
+
const assignOrder = (nodes) => {
|
|
73
|
+
if (!nodes)
|
|
1465
74
|
return;
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
// console.log(`🎯 [${this.node().type}] Context change detected: ${changed.path}`);
|
|
1470
|
-
this.queueContextUpdate(changed.path);
|
|
1471
|
-
}
|
|
1472
|
-
});
|
|
1473
|
-
this.builderService.onRefresh.pipe(this.unsubscriber.takeUntilDestroy).subscribe(async () => {
|
|
1474
|
-
await this.processBatchedUpdates();
|
|
1475
|
-
});
|
|
1476
|
-
}
|
|
1477
|
-
//#region ---- Expression Caching Methods ----
|
|
1478
|
-
getCachedExpressionResult(expressionKey) {
|
|
1479
|
-
const cached = this.expressionCache.get(expressionKey);
|
|
1480
|
-
if (cached && performance.now() - cached.timestamp < this.EXPRESSION_CACHE_TTL) {
|
|
1481
|
-
// console.log(`💾 [${this.node().type}] Using cached expression result for '${expressionKey}'`);
|
|
1482
|
-
return cached.value;
|
|
1483
|
-
}
|
|
1484
|
-
return null;
|
|
1485
|
-
}
|
|
1486
|
-
setCachedExpressionResult(expressionKey, value) {
|
|
1487
|
-
this.expressionCache.set(expressionKey, {
|
|
1488
|
-
value,
|
|
1489
|
-
timestamp: performance.now(),
|
|
1490
|
-
});
|
|
1491
|
-
}
|
|
1492
|
-
clearExpressionCache() {
|
|
1493
|
-
this.expressionCache.clear();
|
|
1494
|
-
}
|
|
1495
|
-
isPathAffectingExpressions(changedPath) {
|
|
1496
|
-
// console.log(
|
|
1497
|
-
// `🔍 [${this.node().type}] Checking if path '${changedPath}' affects expressions. Expression count: ${this.expressionEvaluators.size}`,
|
|
1498
|
-
// );
|
|
1499
|
-
// If widget has no expressions, no need to clear cache
|
|
1500
|
-
if (this.expressionEvaluators.size === 0) {
|
|
1501
|
-
// console.log(`🔍 [${this.node().type}] Path '${changedPath}' - no expressions, keeping cache`);
|
|
1502
|
-
return false;
|
|
1503
|
-
}
|
|
1504
|
-
// Use the same logic as hasExpressionDependency to check for actual dependencies
|
|
1505
|
-
if (this.hasExpressionDependency(changedPath)) {
|
|
1506
|
-
// console.log(`🔍 [${this.node().type}] Path '${changedPath}' affects expressions - clearing cache`);
|
|
1507
|
-
return true;
|
|
1508
|
-
}
|
|
1509
|
-
// console.log(`🔍 [${this.node().type}] Path '${changedPath}' does not affect expressions - keeping cache`);
|
|
1510
|
-
return false;
|
|
1511
|
-
}
|
|
1512
|
-
//#endregion
|
|
1513
|
-
//#region ---- Context Batching Methods ----
|
|
1514
|
-
queueContextUpdate(path) {
|
|
1515
|
-
if (path) {
|
|
1516
|
-
// console.log(`🔄 [${this.node().type}] Queueing context update for path: ${path}`);
|
|
1517
|
-
this.contextUpdateQueue.add(path);
|
|
1518
|
-
// Clear existing timeout
|
|
1519
|
-
if (this.contextUpdateTimeout) {
|
|
1520
|
-
clearTimeout(this.contextUpdateTimeout);
|
|
1521
|
-
}
|
|
1522
|
-
// Debounce updates
|
|
1523
|
-
this.contextUpdateTimeout = setTimeout(() => {
|
|
1524
|
-
// console.log(`⚡ [${this.node().type}] Processing batched updates for ${this.contextUpdateQueue.size} paths`);
|
|
1525
|
-
this.processBatchedUpdates();
|
|
1526
|
-
}, this.CONTEXT_UPDATE_DEBOUNCE_MS);
|
|
1527
|
-
}
|
|
1528
|
-
}
|
|
1529
|
-
async processBatchedUpdates() {
|
|
1530
|
-
if (this.contextUpdateQueue.size === 0)
|
|
1531
|
-
return;
|
|
1532
|
-
const startTime = performance.now();
|
|
1533
|
-
const paths = Array.from(this.contextUpdateQueue);
|
|
1534
|
-
this.contextUpdateQueue.clear();
|
|
1535
|
-
// console.log(`📊 [${this.node().type}] Processing ${paths.length} paths:`, paths);
|
|
1536
|
-
// Clear expression cache only if changed paths affect this widget's expressions
|
|
1537
|
-
const shouldClearCache = paths.some((path) => this.isPathAffectingExpressions(path));
|
|
1538
|
-
if (shouldClearCache) {
|
|
1539
|
-
// console.log(`🗑️ [${this.node().type}] Clearing expression cache due to expression-affecting path change`);
|
|
1540
|
-
this.clearExpressionCache();
|
|
1541
|
-
}
|
|
1542
|
-
// Process updates in batches
|
|
1543
|
-
const optionsStartTime = performance.now();
|
|
1544
|
-
const hasOptionsUpdate = await this.updateOptionsBasedOnContext();
|
|
1545
|
-
const optionsTime = performance.now() - optionsStartTime;
|
|
1546
|
-
if (typeof hasOptionsUpdate === 'number' && hasOptionsUpdate > 0) {
|
|
1547
|
-
// console.log(`🔧 [${this.node().type}] Options updated (${optionsTime.toFixed(2)}ms)`);
|
|
1548
|
-
this.applyOptions();
|
|
1549
|
-
}
|
|
1550
|
-
// Check formulas for any of the changed paths
|
|
1551
|
-
const formulaStartTime = performance.now();
|
|
1552
|
-
const formulaNeedsUpdate = paths.some((path) => this.checkFormulaForUpdate(this.node().formula, path));
|
|
1553
|
-
if (formulaNeedsUpdate) {
|
|
1554
|
-
// console.log(`🧮 [${this.node().type}] Formula needs update`);
|
|
1555
|
-
await this.updateValueBasedOnFormula();
|
|
1556
|
-
}
|
|
1557
|
-
const formulaTime = performance.now() - formulaStartTime;
|
|
1558
|
-
// Emit context changes
|
|
1559
|
-
paths.forEach((path) => {
|
|
1560
|
-
this.onContextChanged.next({ path });
|
|
1561
|
-
});
|
|
1562
|
-
const totalTime = performance.now() - startTime;
|
|
1563
|
-
// console.log(
|
|
1564
|
-
// `✅ [${this.node().type}] Batch processing completed in ${totalTime.toFixed(2)}ms (options: ${optionsTime.toFixed(2)}ms, formula: ${formulaTime.toFixed(2)}ms)`,
|
|
1565
|
-
// );
|
|
1566
|
-
}
|
|
1567
|
-
//#endregion
|
|
1568
|
-
//#region ---- Context Relevance Filtering ----
|
|
1569
|
-
isRelevantContextChange(changedPath) {
|
|
1570
|
-
const node = this.node();
|
|
1571
|
-
// 1. Direct path match - widget's own field
|
|
1572
|
-
if (node.path === changedPath) {
|
|
1573
|
-
return true;
|
|
1574
|
-
}
|
|
1575
|
-
// 2. Parent path match - widget is inside the changed container
|
|
1576
|
-
if (node.path && changedPath.startsWith(node.path + '.')) {
|
|
1577
|
-
return true;
|
|
1578
|
-
}
|
|
1579
|
-
// 3. Child path match - changed field is inside this widget's container
|
|
1580
|
-
if (node.path && node.path.startsWith(changedPath + '.')) {
|
|
1581
|
-
return true;
|
|
1582
|
-
}
|
|
1583
|
-
// 4. Expression dependency check - if widget has expressions that depend on this path
|
|
1584
|
-
if (this.hasExpressionDependency(changedPath)) {
|
|
1585
|
-
return true;
|
|
1586
|
-
}
|
|
1587
|
-
// 5. Formula dependency check - if widget's formula depends on this path
|
|
1588
|
-
if (node.formula && this.checkFormulaForUpdate(node.formula, changedPath)) {
|
|
1589
|
-
return true;
|
|
1590
|
-
}
|
|
1591
|
-
// 6. Trigger dependency check - if widget has triggers that depend on this path
|
|
1592
|
-
if (this.hasTriggerDependency(changedPath)) {
|
|
1593
|
-
return true;
|
|
1594
|
-
}
|
|
1595
|
-
return false;
|
|
1596
|
-
}
|
|
1597
|
-
hasExpressionDependency(changedPath) {
|
|
1598
|
-
// Check if any cached expressions depend on the changed path
|
|
1599
|
-
for (const [path, evaluator] of this.expressionEvaluators) {
|
|
1600
|
-
// Check if the expression path itself contains the changed path
|
|
1601
|
-
if (path.includes(changedPath)) {
|
|
1602
|
-
return true;
|
|
1603
|
-
}
|
|
1604
|
-
// Parse the actual expression content to check for context.eval() calls
|
|
1605
|
-
// We need to get the original expression string to analyze it
|
|
1606
|
-
const node = this.node();
|
|
1607
|
-
const expressionValue = this.getExpressionValueFromNode(node, path);
|
|
1608
|
-
if (expressionValue && typeof expressionValue === 'string') {
|
|
1609
|
-
// Look for context.eval() calls that reference the changed path
|
|
1610
|
-
const contextEvalRegex = /context\.eval\(['"]([^'\"]+)['"]\)/g;
|
|
1611
|
-
let match;
|
|
1612
|
-
while ((match = contextEvalRegex.exec(expressionValue)) !== null) {
|
|
1613
|
-
const evalPath = match[1];
|
|
1614
|
-
// Normalize Id-suffixed segments to dot-id form (e.g., 'typeId' -> 'type.id', 'party.typeId' -> 'party.type.id')
|
|
1615
|
-
const normalizePath = (p) => {
|
|
1616
|
-
if (!p)
|
|
1617
|
-
return p;
|
|
1618
|
-
const parts = p.split('.');
|
|
1619
|
-
const last = parts[parts.length - 1];
|
|
1620
|
-
if (last && last.endsWith('Id')) {
|
|
1621
|
-
parts.splice(parts.length - 1, 1, last.slice(0, -2), 'id');
|
|
1622
|
-
}
|
|
1623
|
-
return parts.join('.');
|
|
1624
|
-
};
|
|
1625
|
-
const isSegmentSuffix = (a, b) => {
|
|
1626
|
-
if (!a || !b)
|
|
1627
|
-
return false;
|
|
1628
|
-
const pa = a.split('.');
|
|
1629
|
-
const pb = b.split('.');
|
|
1630
|
-
if (pb.length > pa.length)
|
|
1631
|
-
return false;
|
|
1632
|
-
for (let i = 1; i <= pb.length; i++) {
|
|
1633
|
-
if (pa[pa.length - i] !== pb[pb.length - i])
|
|
1634
|
-
return false;
|
|
1635
|
-
}
|
|
1636
|
-
return true;
|
|
1637
|
-
};
|
|
1638
|
-
const evalNorm = normalizePath(evalPath);
|
|
1639
|
-
const changedNorm = normalizePath(changedPath);
|
|
1640
|
-
// Debug log for dependency check
|
|
1641
|
-
// console.log(
|
|
1642
|
-
// `🧭 [${this.node().type}] dep-check expr='${path}', changed='${changedPath}', eval='${evalPath}', evalNorm='${evalNorm}', changedNorm='${changedNorm}'`,
|
|
1643
|
-
// );
|
|
1644
|
-
// Generic direct and hierarchical dependency checks (raw and normalized)
|
|
1645
|
-
const rawMatch = evalPath === changedPath ||
|
|
1646
|
-
evalPath.startsWith(changedPath + '.') ||
|
|
1647
|
-
changedPath.startsWith(evalPath + '.') ||
|
|
1648
|
-
isSegmentSuffix(evalPath, changedPath) ||
|
|
1649
|
-
isSegmentSuffix(changedPath, evalPath);
|
|
1650
|
-
const normMatch = evalNorm === changedNorm ||
|
|
1651
|
-
evalNorm.startsWith(changedNorm + '.') ||
|
|
1652
|
-
changedNorm.startsWith(evalNorm + '.') ||
|
|
1653
|
-
isSegmentSuffix(evalNorm, changedNorm) ||
|
|
1654
|
-
isSegmentSuffix(changedNorm, evalNorm);
|
|
1655
|
-
if (rawMatch || normMatch) {
|
|
1656
|
-
// console.log(
|
|
1657
|
-
// `🔍 [${this.node().type}] Expression '${path}' depends on '${changedPath}' via context.eval('${evalPath}') (generic match)`,
|
|
1658
|
-
// );
|
|
1659
|
-
return true;
|
|
1660
|
-
}
|
|
1661
|
-
// Check for path aliases/mappings (e.g., typeId.id <-> type.id)
|
|
1662
|
-
if (this.isPathAlias(evalPath, changedPath)) {
|
|
1663
|
-
// console.log(
|
|
1664
|
-
// `🔍 [${this.node().type}] Expression '${path}' depends on '${changedPath}' via context.eval('${evalPath}') (path alias)`,
|
|
1665
|
-
// );
|
|
1666
|
-
return true;
|
|
1667
|
-
}
|
|
75
|
+
nodes.forEach(n => {
|
|
76
|
+
if (n.order === undefined || n.order === null) {
|
|
77
|
+
n.order = nodeOrder++;
|
|
1668
78
|
}
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
//
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
}
|
|
1685
|
-
}
|
|
1686
|
-
// Check if changedPath ends with 'Id' and has a property
|
|
1687
|
-
if (changedPath.endsWith('Id') && changedPath.includes('.')) {
|
|
1688
|
-
const basePath = changedPath.substring(0, changedPath.lastIndexOf('Id'));
|
|
1689
|
-
const property = changedPath.substring(changedPath.lastIndexOf('.') + 1);
|
|
1690
|
-
const mappedPath = `${basePath}.${property}`;
|
|
1691
|
-
if (evalPath === mappedPath) {
|
|
1692
|
-
// console.log(`🔍 [${this.node().type}] Path alias detected: '${evalPath}' <-> '${changedPath}'`);
|
|
1693
|
-
return true;
|
|
1694
|
-
}
|
|
1695
|
-
}
|
|
1696
|
-
// Check for direct 'Id' suffix mapping (e.g., typeId <-> type.id)
|
|
1697
|
-
if (evalPath.endsWith('Id') && !evalPath.includes('.')) {
|
|
1698
|
-
const basePath = evalPath.substring(0, evalPath.lastIndexOf('Id'));
|
|
1699
|
-
const mappedPath = `${basePath}.id`;
|
|
1700
|
-
if (changedPath === mappedPath) {
|
|
1701
|
-
// console.log(`🔍 [${this.node().type}] Path alias detected: '${evalPath}' <-> '${changedPath}'`);
|
|
1702
|
-
return true;
|
|
1703
|
-
}
|
|
1704
|
-
}
|
|
1705
|
-
if (changedPath.endsWith('Id') && !changedPath.includes('.')) {
|
|
1706
|
-
const basePath = changedPath.substring(0, changedPath.lastIndexOf('Id'));
|
|
1707
|
-
const mappedPath = `${basePath}.id`;
|
|
1708
|
-
if (evalPath === mappedPath) {
|
|
1709
|
-
// console.log(`🔍 [${this.node().type}] Path alias detected: '${evalPath}' <-> '${changedPath}'`);
|
|
1710
|
-
return true;
|
|
1711
|
-
}
|
|
79
|
+
if (n.children && n.children.length > 0)
|
|
80
|
+
assignOrder(n.children);
|
|
81
|
+
});
|
|
82
|
+
};
|
|
83
|
+
assignOrder(definition.nodes);
|
|
84
|
+
// Always create a default main zone when there are nodes
|
|
85
|
+
if (totalNodeCount > 0) {
|
|
86
|
+
layoutDefinition.zones['main'] = {
|
|
87
|
+
layout: {
|
|
88
|
+
type: 'flex',
|
|
89
|
+
flexDirection: definition.direction === 'horizontal' ? 'row' : 'column',
|
|
90
|
+
gap: '16px'
|
|
91
|
+
},
|
|
92
|
+
order: 0 // Main zone gets order 0 (first)
|
|
93
|
+
};
|
|
1712
94
|
}
|
|
1713
|
-
|
|
95
|
+
processNodes(definition.nodes);
|
|
96
|
+
return {
|
|
97
|
+
layoutDefinition,
|
|
98
|
+
layoutNodes
|
|
99
|
+
};
|
|
1714
100
|
}
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
101
|
+
// Removed container mapping helpers - all nodes are treated uniformly
|
|
102
|
+
/**
|
|
103
|
+
* Convert grid layout options to CSS styles
|
|
104
|
+
*/
|
|
105
|
+
convertGridLayoutToStyles(layout) {
|
|
106
|
+
const styles = {};
|
|
107
|
+
// Handle responsive positions
|
|
108
|
+
if (layout.positions) {
|
|
109
|
+
// Use largest breakpoint for base styles
|
|
110
|
+
const position = layout.positions.xxl || layout.positions.xl || layout.positions.lg ||
|
|
111
|
+
layout.positions.md || layout.positions.sm;
|
|
112
|
+
if (position) {
|
|
113
|
+
if (position.colSpan && position.colSpan < 12) {
|
|
114
|
+
styles['width'] = `${(position.colSpan / 12) * 100}%`;
|
|
1727
115
|
}
|
|
1728
116
|
}
|
|
1729
|
-
return typeof current === 'string' ? current : null;
|
|
1730
|
-
}
|
|
1731
|
-
catch (error) {
|
|
1732
|
-
// console.error('Error extracting expression value from node:', error);
|
|
1733
|
-
return null;
|
|
1734
|
-
}
|
|
1735
|
-
}
|
|
1736
|
-
hasTriggerDependency(changedPath) {
|
|
1737
|
-
const node = this.node();
|
|
1738
|
-
const triggers = node.triggers || node.options?.['triggers'] || this.mergedOptions()?.triggers;
|
|
1739
|
-
if (!triggers)
|
|
1740
|
-
return false;
|
|
1741
|
-
// Check if any trigger event depends on the changed path
|
|
1742
|
-
for (const trigger of triggers) {
|
|
1743
|
-
if (trigger.event && trigger.event.includes(changedPath)) {
|
|
1744
|
-
return true;
|
|
1745
|
-
}
|
|
1746
|
-
}
|
|
1747
|
-
return false;
|
|
1748
|
-
}
|
|
1749
|
-
//#endregion
|
|
1750
|
-
// Removed visibility detection methods - not needed for current implementation
|
|
1751
|
-
// Detect input changes
|
|
1752
|
-
ngOnChanges(changes) {
|
|
1753
|
-
if (changes['mode'] || changes['node']) {
|
|
1754
|
-
// Check if either 'mode' or 'node' has changed
|
|
1755
|
-
this.rerenderComponent();
|
|
1756
|
-
}
|
|
1757
|
-
}
|
|
1758
|
-
rerenderComponent() {
|
|
1759
|
-
// Clear any pending render operation to prevent double rendering
|
|
1760
|
-
if (this.renderTimeoutId) {
|
|
1761
|
-
clearTimeout(this.renderTimeoutId);
|
|
1762
|
-
this.renderTimeoutId = null;
|
|
1763
|
-
}
|
|
1764
|
-
// Reset loading state to allow re-rendering
|
|
1765
|
-
this.isLoading.set(false);
|
|
1766
|
-
// Schedule the component loading
|
|
1767
|
-
this.renderTimeoutId = setTimeout(async () => {
|
|
1768
|
-
await this.loadComponent();
|
|
1769
|
-
this.renderTimeoutId = null;
|
|
1770
|
-
});
|
|
1771
|
-
}
|
|
1772
|
-
ngOnDestroy() {
|
|
1773
|
-
if (this.renderTimeoutId) {
|
|
1774
|
-
clearTimeout(this.renderTimeoutId);
|
|
1775
|
-
}
|
|
1776
|
-
if (this.contextUpdateTimeout) {
|
|
1777
|
-
clearTimeout(this.contextUpdateTimeout);
|
|
1778
|
-
}
|
|
1779
|
-
if (this.componentRef) {
|
|
1780
|
-
this.componentRef.destroy();
|
|
1781
117
|
}
|
|
118
|
+
return styles;
|
|
1782
119
|
}
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
//
|
|
1795
|
-
const widget = this.widgetRegistery.resolve(this.node().type);
|
|
1796
|
-
//
|
|
1797
|
-
const propertiesToProcess = [
|
|
1798
|
-
...(widget?.properties ?? []),
|
|
1799
|
-
...(widget?.components[this.mode()]?.properties ?? []),
|
|
1800
|
-
]?.filter((c) => c.schema.defaultValue != null);
|
|
1801
|
-
// Process default values (evaluate expressions if needed)
|
|
1802
|
-
const props = {};
|
|
1803
|
-
for (const property of propertiesToProcess) {
|
|
1804
|
-
const defaultValue = property.schema.defaultValue;
|
|
1805
|
-
if (typeof defaultValue === 'string' && this.expressionEvaluator.isExpression(defaultValue)) {
|
|
1806
|
-
// Evaluate expression for default value
|
|
1807
|
-
try {
|
|
1808
|
-
const evaluatedValue = await this.evaluateExpression(defaultValue);
|
|
1809
|
-
props[property.name] = evaluatedValue;
|
|
1810
|
-
}
|
|
1811
|
-
catch (error) {
|
|
1812
|
-
// console.error(`Error evaluating default value expression for property ${property.name}:`, error);
|
|
1813
|
-
props[property.name] = cloneDeep(defaultValue); // Fallback to original value
|
|
1814
|
-
}
|
|
120
|
+
/**
|
|
121
|
+
* Convert grid layout to node layout configuration
|
|
122
|
+
*/
|
|
123
|
+
convertToNodeLayout(layout) {
|
|
124
|
+
const nodeLayout = {};
|
|
125
|
+
if (layout.positions) {
|
|
126
|
+
const position = layout.positions.xxl || layout.positions.xl || layout.positions.lg ||
|
|
127
|
+
layout.positions.md || layout.positions.sm;
|
|
128
|
+
if (position) {
|
|
129
|
+
if (position.colSpan && position.colSpan < 12) {
|
|
130
|
+
nodeLayout.flex = `0 0 ${(position.colSpan / 12) * 100}%`;
|
|
1815
131
|
}
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
props[property.name] = cloneDeep(defaultValue);
|
|
132
|
+
if (position.rowSpan && position.rowSpan > 1) {
|
|
133
|
+
nodeLayout.gridArea = `span ${position.rowSpan}`;
|
|
1819
134
|
}
|
|
1820
135
|
}
|
|
1821
|
-
//
|
|
1822
|
-
this.mergedOptions.set(merge(props, widget?.options, this.node().options) || {});
|
|
1823
|
-
this.expressionEvaluators.clear();
|
|
1824
|
-
// Register expressions from widget defaults and node options to cover related-entity cases
|
|
1825
|
-
this.preprocessAndInitialOptions(cloneDeep(widget?.options));
|
|
1826
|
-
this.preprocessAndInitialOptions(cloneDeep(this.node().options));
|
|
1827
|
-
await this.updateOptionsBasedOnContext();
|
|
1828
|
-
//
|
|
1829
|
-
this._options.update((val) => ({ ...val, ...this.mergedOptions() }));
|
|
1830
|
-
// Evaluate default value
|
|
1831
|
-
let defaultValue = this.node().defaultValue;
|
|
1832
|
-
if (defaultValue && this.expressionEvaluator.isExpression(defaultValue)) {
|
|
1833
|
-
defaultValue = await this.evaluateExpression(defaultValue);
|
|
1834
|
-
}
|
|
1835
|
-
//
|
|
1836
|
-
const tokenValue = {
|
|
1837
|
-
node: this.node(),
|
|
1838
|
-
defaultValue: defaultValue,
|
|
1839
|
-
options: this.mergedOptions(),
|
|
1840
|
-
config: widget,
|
|
1841
|
-
};
|
|
1842
|
-
const token = Injector.create({
|
|
1843
|
-
parent: this.injector,
|
|
1844
|
-
providers: [
|
|
1845
|
-
{
|
|
1846
|
-
provide: AXP_WIDGET_TOKEN,
|
|
1847
|
-
useValue: tokenValue,
|
|
1848
|
-
},
|
|
1849
|
-
],
|
|
1850
|
-
});
|
|
1851
|
-
//
|
|
1852
|
-
const loadingRef = this.viewContainerRef.createComponent(AXPWidgetPlaceholderComponent);
|
|
1853
|
-
//
|
|
1854
|
-
const com = await widget?.components[this.mode()]?.component();
|
|
1855
|
-
if (!com) {
|
|
1856
|
-
// console.error(`${this.node().type} widget component not found with mode: ${this.mode()}`);
|
|
1857
|
-
return;
|
|
1858
|
-
}
|
|
1859
|
-
this.componentRef = this.viewContainerRef.createComponent(com, { injector: token });
|
|
1860
|
-
this.instance = this.componentRef.instance;
|
|
1861
|
-
this.instance.setStatus(AXPWidgetStatus.Rendering);
|
|
1862
|
-
this.instance.parent = this.parentNode();
|
|
1863
|
-
this.instance.index = this.index();
|
|
1864
|
-
this.instance.mode = this.mode();
|
|
1865
|
-
this.instance.setStatus(AXPWidgetStatus.Rendered);
|
|
1866
|
-
this.instance?.onOptionsChanged?.pipe(this.unsubscriber.takeUntilDestroy).subscribe((c) => {
|
|
1867
|
-
this.onOptionsChanged.emit({ sender: this, widget: c.sender });
|
|
1868
|
-
});
|
|
1869
|
-
this.instance?.onValueChanged?.pipe(this.unsubscriber.takeUntilDestroy).subscribe((c) => {
|
|
1870
|
-
this.onValueChanged.emit({ sender: this, widget: c.sender });
|
|
1871
|
-
});
|
|
1872
|
-
await this.updateValueBasedOnFormula();
|
|
1873
|
-
await this.assignTriggers();
|
|
1874
|
-
//
|
|
1875
|
-
loadingRef.destroy();
|
|
1876
|
-
// Mark that initial render is complete
|
|
1877
|
-
this.hasInitialRender = true;
|
|
1878
|
-
// Re-evaluate expressions after initial render to catch late-arriving related context
|
|
1879
|
-
if (this.expressionEvaluators.size > 0) {
|
|
1880
|
-
// console.log(`🔄 [${this.node().type}] Re-evaluating expressions after initial render`);
|
|
1881
|
-
await this.updateOptionsBasedOnContext();
|
|
1882
|
-
this.applyOptions();
|
|
1883
|
-
}
|
|
1884
|
-
// Process any buffered pre-render context changes now that the component is ready
|
|
1885
|
-
if (this.preRenderContextQueue.size > 0) {
|
|
1886
|
-
// console.log(
|
|
1887
|
-
// `🚀 [${this.node().type}] Processing ${this.preRenderContextQueue.size} buffered pre-render changes`,
|
|
1888
|
-
// );
|
|
1889
|
-
this.preRenderContextQueue.forEach((p) => this.contextUpdateQueue.add(p));
|
|
1890
|
-
this.preRenderContextQueue.clear();
|
|
1891
|
-
await this.processBatchedUpdates();
|
|
1892
|
-
}
|
|
1893
|
-
}
|
|
1894
|
-
catch (error) {
|
|
1895
|
-
// console.error('Error loading component:', error);
|
|
1896
|
-
}
|
|
1897
|
-
finally {
|
|
1898
|
-
this.isLoading.set(false);
|
|
1899
136
|
}
|
|
137
|
+
return nodeLayout;
|
|
1900
138
|
}
|
|
1901
|
-
|
|
1902
|
-
|
|
139
|
+
/**
|
|
140
|
+
* Process widget options based on actual widget configurations
|
|
141
|
+
*/
|
|
142
|
+
processWidgetOptions(layoutNode, sourceNode) {
|
|
143
|
+
if (!sourceNode.widget?.options)
|
|
1903
144
|
return;
|
|
1904
|
-
const
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
145
|
+
const options = sourceNode.widget.options;
|
|
146
|
+
const processedOptions = { ...options };
|
|
147
|
+
// Process based on actual widget type
|
|
148
|
+
switch (sourceNode.widget.type) {
|
|
149
|
+
case 'text-block-layout':
|
|
150
|
+
// Text Block Widget - فقط content
|
|
151
|
+
processedOptions.content = this.processTextBlockContent(options);
|
|
152
|
+
break;
|
|
153
|
+
case 'grid-layout':
|
|
154
|
+
// Grid Layout Widget - complete grid system
|
|
155
|
+
processedOptions.grid = this.processGridOptions(options);
|
|
156
|
+
processedOptions.spacing = this.processSpacingOptions(options);
|
|
157
|
+
processedOptions.border = this.processBorderOptions(options);
|
|
158
|
+
if (options.backgroundColor)
|
|
159
|
+
processedOptions.backgroundColor = options.backgroundColor;
|
|
160
|
+
break;
|
|
161
|
+
case 'flex-layout':
|
|
162
|
+
// Flex Layout Widget
|
|
163
|
+
processedOptions.flex = this.processFlexOptions(options);
|
|
164
|
+
break;
|
|
165
|
+
case 'panel-layout':
|
|
166
|
+
// Panel Layout Widget
|
|
167
|
+
processedOptions.panel = this.processPanelOptions(options);
|
|
168
|
+
break;
|
|
169
|
+
case 'tag':
|
|
170
|
+
// Tag Widget (custom)
|
|
171
|
+
processedOptions.label = options.label || options.content || 'Tag';
|
|
172
|
+
processedOptions.tone = options.tone || 'primary';
|
|
173
|
+
break;
|
|
174
|
+
default:
|
|
175
|
+
// Generic processing برای custom widgets
|
|
176
|
+
if (options.content) {
|
|
177
|
+
processedOptions.content = this.processGenericContent(options);
|
|
178
|
+
}
|
|
179
|
+
break;
|
|
1914
180
|
}
|
|
181
|
+
layoutNode.options = processedOptions;
|
|
1915
182
|
}
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
183
|
+
/**
|
|
184
|
+
* Process text-block-layout content
|
|
185
|
+
*/
|
|
186
|
+
processTextBlockContent(options) {
|
|
187
|
+
if (!options.content)
|
|
188
|
+
return '';
|
|
189
|
+
let content = options.content;
|
|
190
|
+
// اگر قبلاً HTML tag داره، استفاده کن
|
|
191
|
+
if (content.includes('<')) {
|
|
192
|
+
return content;
|
|
1919
193
|
}
|
|
1920
|
-
//
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
checkFormulaForUpdate(formula, path) {
|
|
1925
|
-
if (formula) {
|
|
1926
|
-
const regex = /context\.eval\('([^']+)'\)/g;
|
|
1927
|
-
const matches = formula.match(regex);
|
|
1928
|
-
const nodes = matches ? matches.map((match) => match.match(/'([^']+)'/)[1]) : [];
|
|
1929
|
-
return nodes.includes(path);
|
|
194
|
+
// تبدیل plain text به HTML با styling مناسب
|
|
195
|
+
if (options.type === 'heading' || options.level === 'h1' || options.level === 'h2') {
|
|
196
|
+
const level = options.level || 'h2';
|
|
197
|
+
return `<${level} style="margin: 0 0 16px 0; color: #333; font-weight: 600;">${content}</${level}>`;
|
|
1930
198
|
}
|
|
1931
|
-
|
|
1932
|
-
return
|
|
1933
|
-
}
|
|
1934
|
-
preprocessAndInitialOptions(obj, pathPrefix = '') {
|
|
1935
|
-
if (!obj) {
|
|
1936
|
-
return;
|
|
199
|
+
if (options.weight === 'bold' || options.bold) {
|
|
200
|
+
return `<strong style="color: #333;">${content}</strong>`;
|
|
1937
201
|
}
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
// CRITICAL FIX: Skip trigger actions during options processing
|
|
1941
|
-
//
|
|
1942
|
-
// PROBLEM: Trigger actions were being evaluated immediately during widget setup/options processing,
|
|
1943
|
-
// causing them to execute before the actual trigger event occurred. This meant triggers would fire
|
|
1944
|
-
// during initialization instead of when the specified context path actually changed.
|
|
1945
|
-
//
|
|
1946
|
-
// ROOT CAUSE: The expression evaluator was processing trigger action expressions (like console.log
|
|
1947
|
-
// or widget.setValue calls) as part of the normal options preprocessing, treating them as dynamic
|
|
1948
|
-
// expressions that needed immediate evaluation.
|
|
1949
|
-
//
|
|
1950
|
-
// SOLUTION: Detect when we're processing trigger actions and store them as static values without
|
|
1951
|
-
// expression evaluation. This ensures trigger actions are only evaluated when the trigger's
|
|
1952
|
-
// subscription callback actually fires (when the event condition is met).
|
|
1953
|
-
//
|
|
1954
|
-
// RESULT: Triggers now only execute when their event filters pass (e.g., when the specified
|
|
1955
|
-
// context path changes), not during widget initialization.
|
|
1956
|
-
if (currentPath.includes('triggers') && (key === 'action' || currentPath.endsWith('.action'))) {
|
|
1957
|
-
// Apply static values directly without expression evaluation
|
|
1958
|
-
this.mergedOptions.update((currentOptions) => {
|
|
1959
|
-
return set(currentOptions, currentPath, value);
|
|
1960
|
-
});
|
|
1961
|
-
return;
|
|
1962
|
-
}
|
|
1963
|
-
if (typeof value === 'string' && this.expressionEvaluator.isExpression(value)) {
|
|
1964
|
-
// Cache dynamic expression for later evaluation
|
|
1965
|
-
this.expressionEvaluators.set(currentPath, () => this.evaluateExpression(value));
|
|
1966
|
-
}
|
|
1967
|
-
else if (typeof value === 'object' &&
|
|
1968
|
-
value !== null &&
|
|
1969
|
-
(value.constructor === Object || Array.isArray(value))) {
|
|
1970
|
-
// Recursively handle nested objects
|
|
1971
|
-
this.preprocessAndInitialOptions(value, currentPath);
|
|
1972
|
-
}
|
|
1973
|
-
else {
|
|
1974
|
-
// Apply static values directly
|
|
1975
|
-
this.mergedOptions.update((currentOptions) => {
|
|
1976
|
-
return set(currentOptions, currentPath, value);
|
|
1977
|
-
});
|
|
1978
|
-
}
|
|
1979
|
-
});
|
|
202
|
+
// Default text styling
|
|
203
|
+
return `<span style="color: #333; line-height: 1.5;">${content}</span>`;
|
|
1980
204
|
}
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
}
|
|
1994
|
-
// Evaluate expression if not cached
|
|
1995
|
-
const evalStartTime = performance.now();
|
|
1996
|
-
const newValue = await evaluator();
|
|
1997
|
-
const evalTime = performance.now() - evalStartTime;
|
|
1998
|
-
// Check if result has actually changed using Lodash isEqual
|
|
1999
|
-
const lastValue = this.lastExpressionResults.get(path);
|
|
2000
|
-
const hasChanged = !isEqual(newValue, lastValue);
|
|
2001
|
-
if (hasChanged) {
|
|
2002
|
-
// console.log(
|
|
2003
|
-
// `📝 [${this.node().type}] Expression '${path}' evaluated in ${evalTime.toFixed(2)}ms - value changed`,
|
|
2004
|
-
// );
|
|
2005
|
-
// Cache the result and track it
|
|
2006
|
-
this.setCachedExpressionResult(path, newValue);
|
|
2007
|
-
this.lastExpressionResults.set(path, cloneDeep(newValue));
|
|
2008
|
-
return { path, newValue, fromCache: false, hasChanged: true };
|
|
2009
|
-
}
|
|
2010
|
-
else {
|
|
2011
|
-
// console.log(
|
|
2012
|
-
// `📝 [${this.node().type}] Expression '${path}' evaluated in ${evalTime.toFixed(2)}ms - value unchanged, skipping update`,
|
|
2013
|
-
// );
|
|
2014
|
-
// Cache the result but don't update
|
|
2015
|
-
this.setCachedExpressionResult(path, newValue);
|
|
2016
|
-
this.lastExpressionResults.set(path, cloneDeep(newValue));
|
|
2017
|
-
return { path, newValue, fromCache: false, hasChanged: false };
|
|
205
|
+
/**
|
|
206
|
+
* Process grid-layout options
|
|
207
|
+
*/
|
|
208
|
+
processGridOptions(options) {
|
|
209
|
+
return {
|
|
210
|
+
default: {
|
|
211
|
+
columns: options.columns || 12,
|
|
212
|
+
rows: options.rows || 'auto',
|
|
213
|
+
gap: options.gap || '16px',
|
|
214
|
+
justifyItems: options.justifyItems || 'stretch',
|
|
215
|
+
alignItems: options.alignItems || 'stretch',
|
|
216
|
+
autoFlow: options.autoFlow || 'row'
|
|
2018
217
|
}
|
|
2019
|
-
}
|
|
2020
|
-
// Wait for all evaluators to complete
|
|
2021
|
-
const updates = await Promise.all(updatePromises);
|
|
2022
|
-
// Filter updates to only include those that have actually changed
|
|
2023
|
-
const changedUpdates = updates.filter((update) => update.hasChanged !== false);
|
|
2024
|
-
// Apply updates to mergedOptions only for changed values
|
|
2025
|
-
if (changedUpdates.length > 0) {
|
|
2026
|
-
this.mergedOptions.update((o) => {
|
|
2027
|
-
const updatedOptions = { ...o };
|
|
2028
|
-
changedUpdates.forEach(({ path, newValue }) => {
|
|
2029
|
-
set(updatedOptions, path, newValue);
|
|
2030
|
-
});
|
|
2031
|
-
return updatedOptions;
|
|
2032
|
-
});
|
|
2033
|
-
}
|
|
2034
|
-
const cacheHits = updates.filter((update) => update.fromCache).length;
|
|
2035
|
-
const skippedUpdates = updates.length - changedUpdates.length;
|
|
2036
|
-
// console.log(
|
|
2037
|
-
// `📋 [${this.node().type}] Applied ${changedUpdates.length} expression updates (${cacheHits} cache hits, ${skippedUpdates} skipped)`,
|
|
2038
|
-
// );
|
|
2039
|
-
return changedUpdates.length;
|
|
2040
|
-
}
|
|
2041
|
-
async updateValueBasedOnFormula() {
|
|
2042
|
-
if (this.node().formula) {
|
|
2043
|
-
const value = await this.evaluateExpression(this.node().formula);
|
|
2044
|
-
this.instance.setValue(value);
|
|
2045
|
-
}
|
|
2046
|
-
}
|
|
2047
|
-
async evaluateExpression(templateExpression) {
|
|
2048
|
-
try {
|
|
2049
|
-
const scope = this.buildExpressionScope();
|
|
2050
|
-
return await this.expressionEvaluator.evaluate(templateExpression, scope);
|
|
2051
|
-
}
|
|
2052
|
-
catch (error) {
|
|
2053
|
-
// console.error('Error evaluating expression:', error);
|
|
2054
|
-
return false;
|
|
2055
|
-
}
|
|
218
|
+
};
|
|
2056
219
|
}
|
|
2057
|
-
|
|
220
|
+
/**
|
|
221
|
+
* Process spacing options
|
|
222
|
+
*/
|
|
223
|
+
processSpacingOptions(options) {
|
|
224
|
+
if (!options.spacing && !options.padding && !options.margin)
|
|
225
|
+
return undefined;
|
|
2058
226
|
return {
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
widget: this.getWidgetScope(),
|
|
2062
|
-
methods: this.getFunctionScope(),
|
|
2063
|
-
vars: this.getVariablesScope(),
|
|
227
|
+
padding: options.spacing?.padding || options.padding || '0px',
|
|
228
|
+
margin: options.spacing?.margin || options.margin || '0px'
|
|
2064
229
|
};
|
|
2065
230
|
}
|
|
2066
|
-
|
|
231
|
+
/**
|
|
232
|
+
* Process border options
|
|
233
|
+
*/
|
|
234
|
+
processBorderOptions(options) {
|
|
235
|
+
if (!options.border && !options.borderRadius && !options.borderWidth)
|
|
236
|
+
return undefined;
|
|
2067
237
|
return {
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
return value;
|
|
2073
|
-
},
|
|
2074
|
-
set: (path, value) => {
|
|
2075
|
-
this.contextService.update(path, value);
|
|
2076
|
-
},
|
|
2077
|
-
data: () => {
|
|
2078
|
-
return this.contextService.data();
|
|
2079
|
-
},
|
|
2080
|
-
isDirty: () => {
|
|
2081
|
-
return this.contextService.isDirty();
|
|
2082
|
-
},
|
|
238
|
+
radius: options.border?.radius || options.borderRadius || '0px',
|
|
239
|
+
width: options.border?.width || options.borderWidth || '0px',
|
|
240
|
+
color: options.border?.color || options.borderColor || '#ddd',
|
|
241
|
+
style: options.border?.style || options.borderStyle || 'solid'
|
|
2083
242
|
};
|
|
2084
243
|
}
|
|
2085
|
-
|
|
244
|
+
/**
|
|
245
|
+
* Process flex-layout options
|
|
246
|
+
*/
|
|
247
|
+
processFlexOptions(options) {
|
|
2086
248
|
return {
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
}
|
|
2093
|
-
// Ensure c.path exists
|
|
2094
|
-
if (!c.path) {
|
|
2095
|
-
return false;
|
|
2096
|
-
}
|
|
2097
|
-
// Pattern: "prefix*" - matches paths that start with prefix
|
|
2098
|
-
if (path.endsWith('*')) {
|
|
2099
|
-
const prefix = path.substring(0, path.length - 1);
|
|
2100
|
-
return c.path.startsWith(prefix);
|
|
2101
|
-
}
|
|
2102
|
-
// Pattern: "*suffix" - matches paths that end with suffix
|
|
2103
|
-
else if (path.startsWith('*')) {
|
|
2104
|
-
const suffix = path.substring(1);
|
|
2105
|
-
return c.path.endsWith(suffix);
|
|
2106
|
-
}
|
|
2107
|
-
// Exact match
|
|
2108
|
-
else {
|
|
2109
|
-
return c.path === path;
|
|
2110
|
-
}
|
|
2111
|
-
}));
|
|
2112
|
-
},
|
|
2113
|
-
from: (event) => get(this.instance.api(), event),
|
|
249
|
+
flexDirection: options.flexDirection || 'row',
|
|
250
|
+
justifyContent: options.justifyContent || 'flex-start',
|
|
251
|
+
alignItems: options.alignItems || 'stretch',
|
|
252
|
+
gap: options.gap || '16px',
|
|
253
|
+
flexWrap: options.flexWrap || 'nowrap'
|
|
2114
254
|
};
|
|
2115
255
|
}
|
|
2116
|
-
|
|
256
|
+
/**
|
|
257
|
+
* Process panel-layout options
|
|
258
|
+
*/
|
|
259
|
+
processPanelOptions(options) {
|
|
2117
260
|
return {
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
this.instance.setValue(value);
|
|
2123
|
-
},
|
|
2124
|
-
clear: () => {
|
|
2125
|
-
this.instance.setValue(undefined);
|
|
2126
|
-
},
|
|
2127
|
-
refresh: () => {
|
|
2128
|
-
const refresh = this.instance?.['refresh'];
|
|
2129
|
-
if (refresh && typeof refresh === 'function') {
|
|
2130
|
-
refresh.bind(this.instance)();
|
|
2131
|
-
}
|
|
2132
|
-
},
|
|
2133
|
-
output: (name) => {
|
|
2134
|
-
this.instance.output(name);
|
|
2135
|
-
},
|
|
2136
|
-
find: (id) => {
|
|
2137
|
-
return this.builderService.getWidget(id);
|
|
2138
|
-
},
|
|
261
|
+
title: options.title || '',
|
|
262
|
+
collapsible: options.collapsible || false,
|
|
263
|
+
collapsed: options.collapsed || false,
|
|
264
|
+
padding: options.padding || '16px'
|
|
2139
265
|
};
|
|
2140
266
|
}
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
267
|
+
/**
|
|
268
|
+
* Process tag content
|
|
269
|
+
*/
|
|
270
|
+
processTagContent(options) {
|
|
271
|
+
return options.label || options.content || 'Tag';
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Process generic content
|
|
275
|
+
*/
|
|
276
|
+
processGenericContent(options) {
|
|
277
|
+
if (!options.content)
|
|
278
|
+
return '';
|
|
279
|
+
// اگر HTML tags داره، استفاده کن
|
|
280
|
+
if (options.content.includes('<')) {
|
|
281
|
+
return options.content;
|
|
282
|
+
}
|
|
283
|
+
// Plain text با basic styling
|
|
284
|
+
return `<span style="color: #333;">${options.content}</span>`;
|
|
285
|
+
}
|
|
286
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: AXPLayoutBuilderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
287
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: AXPLayoutBuilderService, providedIn: 'root' }); }
|
|
288
|
+
}
|
|
289
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: AXPLayoutBuilderService, decorators: [{
|
|
290
|
+
type: Injectable,
|
|
291
|
+
args: [{
|
|
292
|
+
providedIn: 'root'
|
|
293
|
+
}]
|
|
294
|
+
}] });
|
|
295
|
+
//#region ---- Layout Builder Implementation ----
|
|
296
|
+
class LayoutBuilder {
|
|
297
|
+
constructor() {
|
|
298
|
+
this.state = {
|
|
299
|
+
nodes: [],
|
|
300
|
+
mode: 'edit',
|
|
301
|
+
direction: 'vertical',
|
|
302
|
+
look: 'normal',
|
|
303
|
+
layoutConfig: {
|
|
304
|
+
positions: {
|
|
305
|
+
sm: { colSpan: 12 },
|
|
306
|
+
md: { colSpan: 8 },
|
|
307
|
+
lg: { colSpan: 6 },
|
|
308
|
+
xl: { colSpan: 5 },
|
|
309
|
+
xxl: { colSpan: 4 },
|
|
310
|
+
},
|
|
2151
311
|
},
|
|
2152
312
|
};
|
|
2153
|
-
// Add custom functions from builder service
|
|
2154
|
-
Object.entries(this.builderService.functions).forEach(([key, fn]) => {
|
|
2155
|
-
scope[key] = (...args) => {
|
|
2156
|
-
return fn(...args);
|
|
2157
|
-
};
|
|
2158
|
-
});
|
|
2159
|
-
return scope;
|
|
2160
313
|
}
|
|
2161
|
-
|
|
314
|
+
widget(name, delegate) {
|
|
315
|
+
const widgetBuilder = new WidgetBuilder(name);
|
|
316
|
+
if (delegate) {
|
|
317
|
+
delegate(widgetBuilder);
|
|
318
|
+
}
|
|
319
|
+
this.state.nodes.push(widgetBuilder.build());
|
|
320
|
+
return this;
|
|
321
|
+
}
|
|
322
|
+
layout(config) {
|
|
323
|
+
this.state.layoutConfig = { ...this.state.layoutConfig, ...config };
|
|
324
|
+
return this;
|
|
325
|
+
}
|
|
326
|
+
mode(mode) {
|
|
327
|
+
this.state.mode = mode;
|
|
328
|
+
return this;
|
|
329
|
+
}
|
|
330
|
+
direction(direction) {
|
|
331
|
+
this.state.direction = direction;
|
|
332
|
+
return this;
|
|
333
|
+
}
|
|
334
|
+
look(look) {
|
|
335
|
+
this.state.look = look;
|
|
336
|
+
return this;
|
|
337
|
+
}
|
|
338
|
+
// Predefined layout containers at root level - delegate pattern required
|
|
339
|
+
grid(delegate) {
|
|
340
|
+
const container = new GridContainerBuilder();
|
|
341
|
+
if (delegate) {
|
|
342
|
+
delegate(container);
|
|
343
|
+
}
|
|
344
|
+
this.state.nodes.push(container.build());
|
|
345
|
+
return this;
|
|
346
|
+
}
|
|
347
|
+
flex(delegate) {
|
|
348
|
+
const container = new FlexContainerBuilder();
|
|
349
|
+
if (delegate) {
|
|
350
|
+
delegate(container);
|
|
351
|
+
}
|
|
352
|
+
this.state.nodes.push(container.build());
|
|
353
|
+
return this;
|
|
354
|
+
}
|
|
355
|
+
panel(delegate) {
|
|
356
|
+
const container = new PanelContainerBuilder();
|
|
357
|
+
if (delegate) {
|
|
358
|
+
delegate(container);
|
|
359
|
+
}
|
|
360
|
+
this.state.nodes.push(container.build());
|
|
361
|
+
return this;
|
|
362
|
+
}
|
|
363
|
+
page(delegate) {
|
|
364
|
+
const container = new PageContainerBuilder();
|
|
365
|
+
if (delegate) {
|
|
366
|
+
delegate(container);
|
|
367
|
+
}
|
|
368
|
+
this.state.nodes.push(container.build());
|
|
369
|
+
return this;
|
|
370
|
+
}
|
|
371
|
+
tabset(delegate) {
|
|
372
|
+
const container = new TabsetContainerBuilder();
|
|
373
|
+
if (delegate) {
|
|
374
|
+
delegate(container);
|
|
375
|
+
}
|
|
376
|
+
this.state.nodes.push(container.build());
|
|
377
|
+
return this;
|
|
378
|
+
}
|
|
379
|
+
// Direct widget methods at root level
|
|
380
|
+
textBox(options) {
|
|
381
|
+
const widgetBuilder = new WidgetBuilder().textBox(options);
|
|
382
|
+
this.state.nodes.push(widgetBuilder.build());
|
|
383
|
+
return this;
|
|
384
|
+
}
|
|
385
|
+
largeTextBox(options) {
|
|
386
|
+
const widgetBuilder = new WidgetBuilder().largeTextBox(options);
|
|
387
|
+
this.state.nodes.push(widgetBuilder.build());
|
|
388
|
+
return this;
|
|
389
|
+
}
|
|
390
|
+
richText(options) {
|
|
391
|
+
const widgetBuilder = new WidgetBuilder().richText(options);
|
|
392
|
+
this.state.nodes.push(widgetBuilder.build());
|
|
393
|
+
return this;
|
|
394
|
+
}
|
|
395
|
+
passwordBox(options) {
|
|
396
|
+
const widgetBuilder = new WidgetBuilder().passwordBox(options);
|
|
397
|
+
this.state.nodes.push(widgetBuilder.build());
|
|
398
|
+
return this;
|
|
399
|
+
}
|
|
400
|
+
numberBox(options) {
|
|
401
|
+
const widgetBuilder = new WidgetBuilder().numberBox(options);
|
|
402
|
+
this.state.nodes.push(widgetBuilder.build());
|
|
403
|
+
return this;
|
|
404
|
+
}
|
|
405
|
+
selectBox(options) {
|
|
406
|
+
const widgetBuilder = new WidgetBuilder().selectBox(options);
|
|
407
|
+
this.state.nodes.push(widgetBuilder.build());
|
|
408
|
+
return this;
|
|
409
|
+
}
|
|
410
|
+
lookupBox(options) {
|
|
411
|
+
const widgetBuilder = new WidgetBuilder().lookupBox(options);
|
|
412
|
+
this.state.nodes.push(widgetBuilder.build());
|
|
413
|
+
return this;
|
|
414
|
+
}
|
|
415
|
+
selectionList(options) {
|
|
416
|
+
const widgetBuilder = new WidgetBuilder().selectionList(options);
|
|
417
|
+
this.state.nodes.push(widgetBuilder.build());
|
|
418
|
+
return this;
|
|
419
|
+
}
|
|
420
|
+
dateTimeBox(options) {
|
|
421
|
+
const widgetBuilder = new WidgetBuilder().dateTimeBox(options);
|
|
422
|
+
this.state.nodes.push(widgetBuilder.build());
|
|
423
|
+
return this;
|
|
424
|
+
}
|
|
425
|
+
toggleSwitch(options) {
|
|
426
|
+
const widgetBuilder = new WidgetBuilder().toggleSwitch(options);
|
|
427
|
+
this.state.nodes.push(widgetBuilder.build());
|
|
428
|
+
return this;
|
|
429
|
+
}
|
|
430
|
+
colorBox(options) {
|
|
431
|
+
const widgetBuilder = new WidgetBuilder().colorBox(options);
|
|
432
|
+
this.state.nodes.push(widgetBuilder.build());
|
|
433
|
+
return this;
|
|
434
|
+
}
|
|
435
|
+
customWidget(type, options) {
|
|
436
|
+
const widgetBuilder = new WidgetBuilder().customWidget(type, options);
|
|
437
|
+
this.state.nodes.push(widgetBuilder.build());
|
|
438
|
+
return this;
|
|
439
|
+
}
|
|
440
|
+
build() {
|
|
2162
441
|
return {
|
|
2163
|
-
|
|
442
|
+
nodes: this.state.nodes,
|
|
443
|
+
mode: this.state.mode,
|
|
444
|
+
direction: this.state.direction,
|
|
445
|
+
look: this.state.look,
|
|
446
|
+
layoutConfig: this.state.layoutConfig,
|
|
2164
447
|
};
|
|
2165
448
|
}
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
return;
|
|
2172
|
-
}
|
|
2173
|
-
for (const trigger of triggers) {
|
|
2174
|
-
try {
|
|
2175
|
-
const event = await this.evaluateTrigger(trigger.event);
|
|
2176
|
-
if (event) {
|
|
2177
|
-
event.pipe(this.unsubscriber.takeUntilDestroy).subscribe(() => {
|
|
2178
|
-
const exec = async (action) => {
|
|
2179
|
-
if (!isEmpty(action) && isString(action)) {
|
|
2180
|
-
await this.evaluateAction(action);
|
|
2181
|
-
}
|
|
2182
|
-
};
|
|
2183
|
-
const actions = Array.isArray(trigger.action) ? trigger.action : [trigger.action];
|
|
2184
|
-
actions.forEach(async (a) => await exec(a));
|
|
2185
|
-
});
|
|
2186
|
-
}
|
|
2187
|
-
}
|
|
2188
|
-
catch (error) {
|
|
2189
|
-
// console.error('Error assigning trigger:', error);
|
|
2190
|
-
}
|
|
449
|
+
render() {
|
|
450
|
+
console.log('render() called, state:', JSON.parse(JSON.stringify(this.state)));
|
|
451
|
+
if (!this.state.nodes || !Array.isArray(this.state.nodes)) {
|
|
452
|
+
console.error('Invalid nodes in state:', this.state.nodes);
|
|
453
|
+
return {};
|
|
2191
454
|
}
|
|
2192
|
-
}
|
|
2193
|
-
async evaluateTrigger(templateExpression) {
|
|
2194
455
|
try {
|
|
2195
|
-
const
|
|
2196
|
-
|
|
2197
|
-
//
|
|
2198
|
-
if (
|
|
2199
|
-
return
|
|
2200
|
-
}
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
456
|
+
const nodes = this.transformToWidgetNodes(this.state.nodes);
|
|
457
|
+
console.log('render() transformed nodes:', JSON.parse(JSON.stringify(nodes)));
|
|
458
|
+
// No nodes
|
|
459
|
+
if (!nodes || nodes.length === 0) {
|
|
460
|
+
return {};
|
|
461
|
+
}
|
|
462
|
+
// Single node → return directly
|
|
463
|
+
if (nodes.length === 1) {
|
|
464
|
+
return nodes[0];
|
|
465
|
+
}
|
|
466
|
+
// Multiple nodes → wrap in a container node with layout config
|
|
467
|
+
const flexDirection = this.state.direction === 'horizontal' ? 'row' : 'column';
|
|
468
|
+
const container = {
|
|
469
|
+
type: 'flex-layout',
|
|
470
|
+
name: 'root',
|
|
471
|
+
options: {
|
|
472
|
+
flexDirection,
|
|
473
|
+
gap: '16px',
|
|
474
|
+
},
|
|
475
|
+
children: nodes,
|
|
476
|
+
};
|
|
477
|
+
return container;
|
|
2204
478
|
}
|
|
2205
479
|
catch (error) {
|
|
2206
|
-
|
|
2207
|
-
return
|
|
2208
|
-
}
|
|
480
|
+
console.error('Error in render():', error);
|
|
481
|
+
return {};
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
transformToWidgetNodes(nodes) {
|
|
485
|
+
console.log('transformToWidgetNodes called with nodes:', nodes);
|
|
486
|
+
const sorted = this.sortNodes(nodes);
|
|
487
|
+
// Helper to compute flex-item options from grid layout positions
|
|
488
|
+
const toFlexItemOptions = (layout, order) => {
|
|
489
|
+
let colSpan;
|
|
490
|
+
const positions = layout?.positions ?? this.state.layoutConfig?.positions;
|
|
491
|
+
if (positions) {
|
|
492
|
+
colSpan = positions.xxl?.colSpan || positions.xl?.colSpan || positions.lg?.colSpan || positions.md?.colSpan || positions.sm?.colSpan;
|
|
493
|
+
}
|
|
494
|
+
const basis = colSpan && colSpan > 0 && colSpan <= 12 ? `${(colSpan / 12) * 100}%` : undefined;
|
|
495
|
+
const opt = {};
|
|
496
|
+
if (basis)
|
|
497
|
+
opt.basis = basis;
|
|
498
|
+
if (order !== undefined)
|
|
499
|
+
opt.order = typeof order === 'number' ? order : parseInt(order.toString());
|
|
500
|
+
return opt;
|
|
501
|
+
};
|
|
502
|
+
const multipleSiblings = sorted.length > 1;
|
|
503
|
+
return sorted.map((node) => {
|
|
504
|
+
console.log('Processing node:', node);
|
|
505
|
+
// Build the actual widget node
|
|
506
|
+
const widget = {
|
|
507
|
+
type: node.widget?.type || 'unknown',
|
|
508
|
+
name: node.id,
|
|
509
|
+
options: {
|
|
510
|
+
...node.widget?.options,
|
|
511
|
+
mode: node.mode,
|
|
512
|
+
visible: node.visible,
|
|
513
|
+
disabled: node.disabled,
|
|
514
|
+
readonly: node.readonly,
|
|
515
|
+
},
|
|
516
|
+
};
|
|
517
|
+
if (node.children && node.children.length > 0) {
|
|
518
|
+
widget.children = this.transformToWidgetNodes(this.sortNodes(node.children));
|
|
519
|
+
}
|
|
520
|
+
// If we have multiple siblings at this level, wrap each item in a flex-item container
|
|
521
|
+
if (multipleSiblings) {
|
|
522
|
+
const flexItemOptions = toFlexItemOptions(node.layout, node.order);
|
|
523
|
+
const wrapped = {
|
|
524
|
+
type: 'flex-item-layout',
|
|
525
|
+
name: `${node.id || 'item'}-container`,
|
|
526
|
+
options: {
|
|
527
|
+
...flexItemOptions,
|
|
528
|
+
},
|
|
529
|
+
children: [widget],
|
|
530
|
+
};
|
|
531
|
+
return wrapped;
|
|
532
|
+
}
|
|
533
|
+
return widget;
|
|
534
|
+
});
|
|
2209
535
|
}
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
536
|
+
sortNodes(nodes) {
|
|
537
|
+
if (!Array.isArray(nodes))
|
|
538
|
+
return [];
|
|
539
|
+
return nodes
|
|
540
|
+
.map((n, idx) => ({ n, idx }))
|
|
541
|
+
.sort((a, b) => {
|
|
542
|
+
const ao = a.n.order;
|
|
543
|
+
const bo = b.n.order;
|
|
544
|
+
const aHas = ao !== undefined && ao !== null;
|
|
545
|
+
const bHas = bo !== undefined && bo !== null;
|
|
546
|
+
if (aHas && bHas) {
|
|
547
|
+
if (typeof ao === 'number' && typeof bo === 'number')
|
|
548
|
+
return ao - bo;
|
|
549
|
+
return String(ao).localeCompare(String(bo));
|
|
550
|
+
}
|
|
551
|
+
if (aHas && !bHas)
|
|
552
|
+
return -1;
|
|
553
|
+
if (!aHas && bHas)
|
|
554
|
+
return 1;
|
|
555
|
+
return a.idx - b.idx;
|
|
556
|
+
})
|
|
557
|
+
.map(x => x.n);
|
|
2218
558
|
}
|
|
2219
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPWidgetRendererDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
2220
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.1.8", type: AXPWidgetRendererDirective, isStandalone: false, selector: "[axp-widget-renderer]", inputs: { parentNode: { classPropertyName: "parentNode", publicName: "parentNode", isSignal: true, isRequired: false, transformFunction: null }, index: { classPropertyName: "index", publicName: "index", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: true, transformFunction: null }, node: { classPropertyName: "node", publicName: "node", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { onOptionsChanged: "onOptionsChanged", onValueChanged: "onValueChanged" }, providers: [
|
|
2221
|
-
{
|
|
2222
|
-
provide: AXUnsubscriber,
|
|
2223
|
-
},
|
|
2224
|
-
], exportAs: ["widgetRenderer"], usesOnChanges: true, ngImport: i0 }); }
|
|
2225
559
|
}
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
},
|
|
2235
|
-
],
|
|
2236
|
-
standalone: false,
|
|
2237
|
-
}]
|
|
2238
|
-
}], ctorParameters: () => [] });
|
|
2239
|
-
|
|
2240
|
-
const COMPONENTS = [AXPWidgetContainerComponent, AXPWidgetColumnRendererComponent, AXPWidgetRendererDirective];
|
|
2241
|
-
class AXPLayoutBuilderModule {
|
|
2242
|
-
static forRoot(config) {
|
|
2243
|
-
return {
|
|
2244
|
-
ngModule: AXPLayoutBuilderModule,
|
|
2245
|
-
providers: [
|
|
2246
|
-
{
|
|
2247
|
-
provide: 'AXPLayoutBuilderModuleFactory',
|
|
2248
|
-
useFactory: (registry) => async () => {
|
|
2249
|
-
await Promise.all(config?.widgets?.map((w) => Promise.resolve(registry.register(w))) || []);
|
|
2250
|
-
await Promise.all(config?.extendedWidgets?.map((ew) => Promise.resolve(registry.extend(ew.parentName, ew.widget))) || []);
|
|
2251
|
-
},
|
|
2252
|
-
deps: [AXPWidgetRegistryService],
|
|
2253
|
-
multi: true,
|
|
2254
|
-
},
|
|
2255
|
-
],
|
|
560
|
+
//#endregion
|
|
561
|
+
//#region ---- Container Builder Implementation ----
|
|
562
|
+
// Base Container Builder
|
|
563
|
+
class BaseContainerBuilder {
|
|
564
|
+
constructor(containerType) {
|
|
565
|
+
this.containerState = {
|
|
566
|
+
type: 'widget',
|
|
567
|
+
children: [],
|
|
2256
568
|
};
|
|
569
|
+
this.containerState.widget = { type: containerType, options: {} };
|
|
570
|
+
}
|
|
571
|
+
baseId(id) {
|
|
572
|
+
this.containerState.id = id;
|
|
573
|
+
return this;
|
|
574
|
+
}
|
|
575
|
+
baseLayout(value) {
|
|
576
|
+
if (typeof value === 'number') {
|
|
577
|
+
this.containerState.layout = {
|
|
578
|
+
positions: {
|
|
579
|
+
sm: { colSpan: 12 },
|
|
580
|
+
md: { colSpan: 12 },
|
|
581
|
+
lg: { colSpan: value },
|
|
582
|
+
xl: { colSpan: value },
|
|
583
|
+
xxl: { colSpan: value },
|
|
584
|
+
},
|
|
585
|
+
};
|
|
586
|
+
}
|
|
587
|
+
else {
|
|
588
|
+
this.containerState.layout = value;
|
|
589
|
+
}
|
|
590
|
+
return this;
|
|
591
|
+
}
|
|
592
|
+
// Base methods shared by all containers
|
|
593
|
+
ensureChildren() {
|
|
594
|
+
this.containerState.children = this.containerState.children || [];
|
|
2257
595
|
}
|
|
2258
|
-
|
|
596
|
+
addDirectWidget(type, options) {
|
|
597
|
+
const child = new WidgetBuilder();
|
|
598
|
+
child.customWidget(type, options);
|
|
599
|
+
this.ensureChildren();
|
|
600
|
+
this.containerState.children.push(child.build());
|
|
601
|
+
return this;
|
|
602
|
+
}
|
|
603
|
+
build() {
|
|
2259
604
|
return {
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
},
|
|
2271
|
-
],
|
|
605
|
+
id: this.containerState.id,
|
|
606
|
+
name: this.containerState.name,
|
|
607
|
+
widget: this.containerState.widget,
|
|
608
|
+
children: this.containerState.children,
|
|
609
|
+
layout: this.containerState.layout,
|
|
610
|
+
mode: this.containerState.mode,
|
|
611
|
+
order: this.containerState.order,
|
|
612
|
+
visible: this.containerState.visible,
|
|
613
|
+
disabled: this.containerState.disabled,
|
|
614
|
+
readonly: this.containerState.readonly,
|
|
2272
615
|
};
|
|
2273
616
|
}
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
constructor(
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
617
|
+
}
|
|
618
|
+
// Flex Container Builder
|
|
619
|
+
class FlexContainerBuilder extends BaseContainerBuilder {
|
|
620
|
+
constructor() {
|
|
621
|
+
super('flex-layout');
|
|
622
|
+
}
|
|
623
|
+
id(id) {
|
|
624
|
+
return this.baseId(id);
|
|
625
|
+
}
|
|
626
|
+
layout(value) {
|
|
627
|
+
return this.baseLayout(value);
|
|
628
|
+
}
|
|
629
|
+
mode(mode) {
|
|
630
|
+
this.containerState.mode = mode;
|
|
631
|
+
return this;
|
|
632
|
+
}
|
|
633
|
+
order(value) {
|
|
634
|
+
this.containerState.order = value;
|
|
635
|
+
return this;
|
|
636
|
+
}
|
|
637
|
+
visible(condition) {
|
|
638
|
+
this.containerState.visible = condition;
|
|
639
|
+
return this;
|
|
640
|
+
}
|
|
641
|
+
disabled(condition) {
|
|
642
|
+
this.containerState.disabled = condition;
|
|
643
|
+
return this;
|
|
644
|
+
}
|
|
645
|
+
readonly(condition) {
|
|
646
|
+
this.containerState.readonly = condition;
|
|
647
|
+
return this;
|
|
648
|
+
}
|
|
649
|
+
setOptions(options) {
|
|
650
|
+
this.containerState.widget.options = { ...this.containerState.widget.options, ...options };
|
|
651
|
+
return this;
|
|
652
|
+
}
|
|
653
|
+
// Individual fluent methods for Flex
|
|
654
|
+
setFlexDirection(direction) {
|
|
655
|
+
return this.setOptions({ flexDirection: direction });
|
|
656
|
+
}
|
|
657
|
+
setFlexWrap(wrap) {
|
|
658
|
+
return this.setOptions({ flexWrap: wrap });
|
|
659
|
+
}
|
|
660
|
+
setJustifyContent(justify) {
|
|
661
|
+
return this.setOptions({ justifyContent: justify });
|
|
662
|
+
}
|
|
663
|
+
setAlignItems(align) {
|
|
664
|
+
return this.setOptions({ alignItems: align });
|
|
665
|
+
}
|
|
666
|
+
setGap(gap) {
|
|
667
|
+
return this.setOptions({ gap });
|
|
668
|
+
}
|
|
669
|
+
setBackgroundColor(color) {
|
|
670
|
+
return this.setOptions({ backgroundColor: color });
|
|
671
|
+
}
|
|
672
|
+
setPadding(padding) {
|
|
673
|
+
return this.setOptions({ spacing: { padding } });
|
|
674
|
+
}
|
|
675
|
+
setMargin(margin) {
|
|
676
|
+
return this.setOptions({ spacing: { margin } });
|
|
677
|
+
}
|
|
678
|
+
addContainer(name, delegate) {
|
|
679
|
+
// Implementation will be simplified for now
|
|
680
|
+
return this;
|
|
681
|
+
}
|
|
682
|
+
addWidget(name, delegate) {
|
|
683
|
+
const childWidget = new WidgetBuilder(name);
|
|
684
|
+
if (delegate) {
|
|
685
|
+
delegate(childWidget);
|
|
686
|
+
}
|
|
687
|
+
this.ensureChildren();
|
|
688
|
+
this.containerState.children.push(childWidget.build());
|
|
689
|
+
return this;
|
|
690
|
+
}
|
|
691
|
+
textBox(options) {
|
|
692
|
+
return this.addDirectWidget('text-editor', options);
|
|
693
|
+
}
|
|
694
|
+
largeTextBox(options) {
|
|
695
|
+
return this.addDirectWidget('large-text-editor', options);
|
|
696
|
+
}
|
|
697
|
+
richText(options) {
|
|
698
|
+
return this.addDirectWidget('rich-text-editor', options);
|
|
699
|
+
}
|
|
700
|
+
passwordBox(options) {
|
|
701
|
+
return this.addDirectWidget('password-editor', options);
|
|
702
|
+
}
|
|
703
|
+
numberBox(options) {
|
|
704
|
+
return this.addDirectWidget('number-editor', options);
|
|
705
|
+
}
|
|
706
|
+
selectBox(options) {
|
|
707
|
+
return this.addDirectWidget('select-editor', options);
|
|
708
|
+
}
|
|
709
|
+
lookupBox(options) {
|
|
710
|
+
return this.addDirectWidget('lookup-editor', options);
|
|
711
|
+
}
|
|
712
|
+
selectionList(options) {
|
|
713
|
+
return this.addDirectWidget('selection-list', options);
|
|
714
|
+
}
|
|
715
|
+
dateTimeBox(options) {
|
|
716
|
+
return this.addDirectWidget('date-time-editor', options);
|
|
717
|
+
}
|
|
718
|
+
toggleSwitch(options) {
|
|
719
|
+
return this.addDirectWidget('toggle-editor', options);
|
|
720
|
+
}
|
|
721
|
+
colorBox(options) {
|
|
722
|
+
return this.addDirectWidget('color-editor', options);
|
|
723
|
+
}
|
|
724
|
+
customWidget(type, options) {
|
|
725
|
+
return this.addDirectWidget(type, options);
|
|
2281
726
|
}
|
|
2282
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPLayoutBuilderModule, deps: [{ token: 'AXPLayoutBuilderModuleFactory', optional: true }], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
2283
|
-
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.1.8", ngImport: i0, type: AXPLayoutBuilderModule, declarations: [AXPWidgetContainerComponent, AXPWidgetColumnRendererComponent, AXPWidgetRendererDirective], imports: [CommonModule, PortalModule, AXSkeletonModule, CommonModule, AXTranslationModule], exports: [AXPWidgetContainerComponent, AXPWidgetColumnRendererComponent, AXPWidgetRendererDirective] }); }
|
|
2284
|
-
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPLayoutBuilderModule, imports: [CommonModule, PortalModule, AXSkeletonModule, CommonModule, AXTranslationModule] }); }
|
|
2285
727
|
}
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
728
|
+
// Grid Container Builder
|
|
729
|
+
class GridContainerBuilder extends BaseContainerBuilder {
|
|
730
|
+
constructor() {
|
|
731
|
+
super('grid-layout');
|
|
732
|
+
}
|
|
733
|
+
id(id) { return this.baseId(id); }
|
|
734
|
+
layout(value) { return this.baseLayout(value); }
|
|
735
|
+
mode(mode) { this.containerState.mode = mode; return this; }
|
|
736
|
+
order(value) { this.containerState.order = value; return this; }
|
|
737
|
+
visible(condition) { this.containerState.visible = condition; return this; }
|
|
738
|
+
disabled(condition) { this.containerState.disabled = condition; return this; }
|
|
739
|
+
readonly(condition) { this.containerState.readonly = condition; return this; }
|
|
740
|
+
setOptions(options) {
|
|
741
|
+
this.containerState.widget.options = { ...this.containerState.widget.options, ...options };
|
|
742
|
+
return this;
|
|
743
|
+
}
|
|
744
|
+
// Individual fluent methods for Grid
|
|
745
|
+
setColumns(columns) {
|
|
746
|
+
return this.setOptions({ grid: { default: { columns } } });
|
|
747
|
+
}
|
|
748
|
+
setRows(rows) {
|
|
749
|
+
return this.setOptions({ grid: { default: { rows } } });
|
|
750
|
+
}
|
|
751
|
+
setGap(gap) {
|
|
752
|
+
return this.setOptions({ grid: { default: { gap } } });
|
|
753
|
+
}
|
|
754
|
+
setJustifyItems(justify) {
|
|
755
|
+
return this.setOptions({ grid: { default: { justifyItems: justify } } });
|
|
756
|
+
}
|
|
757
|
+
setAlignItems(align) {
|
|
758
|
+
return this.setOptions({ grid: { default: { alignItems: align } } });
|
|
759
|
+
}
|
|
760
|
+
setAutoFlow(flow) {
|
|
761
|
+
return this.setOptions({ grid: { default: { autoFlow: flow } } });
|
|
762
|
+
}
|
|
763
|
+
setBackgroundColor(color) {
|
|
764
|
+
return this.setOptions({ backgroundColor: color });
|
|
765
|
+
}
|
|
766
|
+
setPadding(padding) {
|
|
767
|
+
return this.setOptions({ spacing: { padding } });
|
|
768
|
+
}
|
|
769
|
+
setMargin(margin) {
|
|
770
|
+
return this.setOptions({ spacing: { margin } });
|
|
771
|
+
}
|
|
772
|
+
addContainer(name, delegate) { return this; }
|
|
773
|
+
addWidget(name, delegate) {
|
|
774
|
+
const childWidget = new WidgetBuilder(name);
|
|
775
|
+
if (delegate)
|
|
776
|
+
delegate(childWidget);
|
|
777
|
+
this.ensureChildren();
|
|
778
|
+
this.containerState.children.push(childWidget.build());
|
|
779
|
+
return this;
|
|
780
|
+
}
|
|
781
|
+
textBox(options) { return this.addDirectWidget('text-editor', options); }
|
|
782
|
+
largeTextBox(options) { return this.addDirectWidget('large-text-editor', options); }
|
|
783
|
+
richText(options) { return this.addDirectWidget('rich-text-editor', options); }
|
|
784
|
+
passwordBox(options) { return this.addDirectWidget('password-editor', options); }
|
|
785
|
+
numberBox(options) { return this.addDirectWidget('number-editor', options); }
|
|
786
|
+
selectBox(options) { return this.addDirectWidget('select-editor', options); }
|
|
787
|
+
lookupBox(options) { return this.addDirectWidget('lookup-editor', options); }
|
|
788
|
+
selectionList(options) { return this.addDirectWidget('selection-list', options); }
|
|
789
|
+
dateTimeBox(options) { return this.addDirectWidget('date-time-editor', options); }
|
|
790
|
+
toggleSwitch(options) { return this.addDirectWidget('toggle-editor', options); }
|
|
791
|
+
colorBox(options) { return this.addDirectWidget('color-editor', options); }
|
|
792
|
+
customWidget(type, options) { return this.addDirectWidget(type, options); }
|
|
793
|
+
}
|
|
794
|
+
// Panel Container Builder
|
|
795
|
+
class PanelContainerBuilder extends BaseContainerBuilder {
|
|
796
|
+
constructor() {
|
|
797
|
+
super('panel-layout');
|
|
798
|
+
}
|
|
799
|
+
id(id) { return this.baseId(id); }
|
|
800
|
+
layout(value) { return this.baseLayout(value); }
|
|
801
|
+
mode(mode) { this.containerState.mode = mode; return this; }
|
|
802
|
+
order(value) { this.containerState.order = value; return this; }
|
|
803
|
+
visible(condition) { this.containerState.visible = condition; return this; }
|
|
804
|
+
disabled(condition) { this.containerState.disabled = condition; return this; }
|
|
805
|
+
readonly(condition) { this.containerState.readonly = condition; return this; }
|
|
806
|
+
setOptions(options) {
|
|
807
|
+
this.containerState.widget.options = { ...this.containerState.widget.options, ...options };
|
|
808
|
+
return this;
|
|
809
|
+
}
|
|
810
|
+
// Individual fluent methods for Panel
|
|
811
|
+
setCaption(caption) {
|
|
812
|
+
return this.setOptions({ caption });
|
|
813
|
+
}
|
|
814
|
+
setIcon(icon) {
|
|
815
|
+
return this.setOptions({ icon });
|
|
816
|
+
}
|
|
817
|
+
setLook(look) {
|
|
818
|
+
return this.setOptions({ look });
|
|
819
|
+
}
|
|
820
|
+
setShowHeader(show) {
|
|
821
|
+
return this.setOptions({ showHeader: show });
|
|
822
|
+
}
|
|
823
|
+
setCollapsed(collapsed) {
|
|
824
|
+
return this.setOptions({ collapsed });
|
|
825
|
+
}
|
|
826
|
+
addContainer(name, delegate) { return this; }
|
|
827
|
+
addWidget(name, delegate) {
|
|
828
|
+
const childWidget = new WidgetBuilder(name);
|
|
829
|
+
if (delegate)
|
|
830
|
+
delegate(childWidget);
|
|
831
|
+
this.ensureChildren();
|
|
832
|
+
this.containerState.children.push(childWidget.build());
|
|
833
|
+
return this;
|
|
834
|
+
}
|
|
835
|
+
textBox(options) { return this.addDirectWidget('text-editor', options); }
|
|
836
|
+
largeTextBox(options) { return this.addDirectWidget('large-text-editor', options); }
|
|
837
|
+
richText(options) { return this.addDirectWidget('rich-text-editor', options); }
|
|
838
|
+
passwordBox(options) { return this.addDirectWidget('password-editor', options); }
|
|
839
|
+
numberBox(options) { return this.addDirectWidget('number-editor', options); }
|
|
840
|
+
selectBox(options) { return this.addDirectWidget('select-editor', options); }
|
|
841
|
+
lookupBox(options) { return this.addDirectWidget('lookup-editor', options); }
|
|
842
|
+
selectionList(options) { return this.addDirectWidget('selection-list', options); }
|
|
843
|
+
dateTimeBox(options) { return this.addDirectWidget('date-time-editor', options); }
|
|
844
|
+
toggleSwitch(options) { return this.addDirectWidget('toggle-editor', options); }
|
|
845
|
+
colorBox(options) { return this.addDirectWidget('color-editor', options); }
|
|
846
|
+
customWidget(type, options) { return this.addDirectWidget(type, options); }
|
|
847
|
+
}
|
|
848
|
+
// Page Container Builder
|
|
849
|
+
class PageContainerBuilder extends BaseContainerBuilder {
|
|
850
|
+
constructor() {
|
|
851
|
+
super('page-layout');
|
|
852
|
+
}
|
|
853
|
+
id(id) { return this.baseId(id); }
|
|
854
|
+
layout(value) { return this.baseLayout(value); }
|
|
855
|
+
mode(mode) { this.containerState.mode = mode; return this; }
|
|
856
|
+
order(value) { this.containerState.order = value; return this; }
|
|
857
|
+
visible(condition) { this.containerState.visible = condition; return this; }
|
|
858
|
+
disabled(condition) { this.containerState.disabled = condition; return this; }
|
|
859
|
+
readonly(condition) { this.containerState.readonly = condition; return this; }
|
|
860
|
+
setOptions(options) {
|
|
861
|
+
this.containerState.widget.options = { ...this.containerState.widget.options, ...options };
|
|
862
|
+
return this;
|
|
863
|
+
}
|
|
864
|
+
// Individual fluent methods for Page
|
|
865
|
+
setBackgroundColor(color) {
|
|
866
|
+
return this.setOptions({ backgroundColor: color });
|
|
867
|
+
}
|
|
868
|
+
setTheme(theme) {
|
|
869
|
+
return this.setOptions({ theme });
|
|
870
|
+
}
|
|
871
|
+
setHasHeader(hasHeader) {
|
|
872
|
+
return this.setOptions({ hasHeader });
|
|
873
|
+
}
|
|
874
|
+
setHasFooter(hasFooter) {
|
|
875
|
+
return this.setOptions({ hasFooter });
|
|
876
|
+
}
|
|
877
|
+
setDirection(direction) {
|
|
878
|
+
return this.setOptions({ direction });
|
|
879
|
+
}
|
|
880
|
+
addContainer(name, delegate) { return this; }
|
|
881
|
+
addWidget(name, delegate) {
|
|
882
|
+
const childWidget = new WidgetBuilder(name);
|
|
883
|
+
if (delegate)
|
|
884
|
+
delegate(childWidget);
|
|
885
|
+
this.ensureChildren();
|
|
886
|
+
this.containerState.children.push(childWidget.build());
|
|
887
|
+
return this;
|
|
888
|
+
}
|
|
889
|
+
textBox(options) { return this.addDirectWidget('text-editor', options); }
|
|
890
|
+
largeTextBox(options) { return this.addDirectWidget('large-text-editor', options); }
|
|
891
|
+
richText(options) { return this.addDirectWidget('rich-text-editor', options); }
|
|
892
|
+
passwordBox(options) { return this.addDirectWidget('password-editor', options); }
|
|
893
|
+
numberBox(options) { return this.addDirectWidget('number-editor', options); }
|
|
894
|
+
selectBox(options) { return this.addDirectWidget('select-editor', options); }
|
|
895
|
+
lookupBox(options) { return this.addDirectWidget('lookup-editor', options); }
|
|
896
|
+
selectionList(options) { return this.addDirectWidget('selection-list', options); }
|
|
897
|
+
dateTimeBox(options) { return this.addDirectWidget('date-time-editor', options); }
|
|
898
|
+
toggleSwitch(options) { return this.addDirectWidget('toggle-editor', options); }
|
|
899
|
+
colorBox(options) { return this.addDirectWidget('color-editor', options); }
|
|
900
|
+
customWidget(type, options) { return this.addDirectWidget(type, options); }
|
|
901
|
+
}
|
|
902
|
+
// Tabset Container Builder
|
|
903
|
+
class TabsetContainerBuilder extends BaseContainerBuilder {
|
|
904
|
+
constructor() {
|
|
905
|
+
super('tabset-layout');
|
|
906
|
+
}
|
|
907
|
+
id(id) { return this.baseId(id); }
|
|
908
|
+
layout(value) { return this.baseLayout(value); }
|
|
909
|
+
mode(mode) { this.containerState.mode = mode; return this; }
|
|
910
|
+
order(value) { this.containerState.order = value; return this; }
|
|
911
|
+
visible(condition) { this.containerState.visible = condition; return this; }
|
|
912
|
+
disabled(condition) { this.containerState.disabled = condition; return this; }
|
|
913
|
+
readonly(condition) { this.containerState.readonly = condition; return this; }
|
|
914
|
+
setOptions(options) {
|
|
915
|
+
this.containerState.widget.options = { ...this.containerState.widget.options, ...options };
|
|
916
|
+
return this;
|
|
917
|
+
}
|
|
918
|
+
// Individual fluent methods for Tabset
|
|
919
|
+
setLook(look) {
|
|
920
|
+
return this.setOptions({ look });
|
|
921
|
+
}
|
|
922
|
+
setOrientation(orientation) {
|
|
923
|
+
return this.setOptions({ orientation });
|
|
924
|
+
}
|
|
925
|
+
setActiveIndex(index) {
|
|
926
|
+
return this.setOptions({ activeIndex: index });
|
|
927
|
+
}
|
|
928
|
+
addContainer(name, delegate) { return this; }
|
|
929
|
+
addWidget(name, delegate) {
|
|
930
|
+
const childWidget = new WidgetBuilder(name);
|
|
931
|
+
if (delegate)
|
|
932
|
+
delegate(childWidget);
|
|
933
|
+
this.ensureChildren();
|
|
934
|
+
this.containerState.children.push(childWidget.build());
|
|
935
|
+
return this;
|
|
936
|
+
}
|
|
937
|
+
textBox(options) { return this.addDirectWidget('text-editor', options); }
|
|
938
|
+
largeTextBox(options) { return this.addDirectWidget('large-text-editor', options); }
|
|
939
|
+
richText(options) { return this.addDirectWidget('rich-text-editor', options); }
|
|
940
|
+
passwordBox(options) { return this.addDirectWidget('password-editor', options); }
|
|
941
|
+
numberBox(options) { return this.addDirectWidget('number-editor', options); }
|
|
942
|
+
selectBox(options) { return this.addDirectWidget('select-editor', options); }
|
|
943
|
+
lookupBox(options) { return this.addDirectWidget('lookup-editor', options); }
|
|
944
|
+
selectionList(options) { return this.addDirectWidget('selection-list', options); }
|
|
945
|
+
dateTimeBox(options) { return this.addDirectWidget('date-time-editor', options); }
|
|
946
|
+
toggleSwitch(options) { return this.addDirectWidget('toggle-editor', options); }
|
|
947
|
+
colorBox(options) { return this.addDirectWidget('color-editor', options); }
|
|
948
|
+
customWidget(type, options) { return this.addDirectWidget(type, options); }
|
|
949
|
+
}
|
|
950
|
+
//#endregion
|
|
951
|
+
//#region ---- Widget Builder Implementation ----
|
|
952
|
+
class WidgetBuilder {
|
|
953
|
+
constructor(name) {
|
|
954
|
+
this.widgetState = {
|
|
955
|
+
type: 'widget',
|
|
956
|
+
children: [],
|
|
957
|
+
};
|
|
958
|
+
if (name) {
|
|
959
|
+
this.widgetState.name = name;
|
|
2313
960
|
}
|
|
2314
961
|
}
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
962
|
+
// No utility methods needed - widget options are pure now
|
|
963
|
+
isContainerWidgetType(type) {
|
|
964
|
+
if (!type)
|
|
965
|
+
return false;
|
|
966
|
+
return ['grid-layout', 'flex-layout', 'panel-layout', 'page-layout', 'tabset-layout'].includes(type);
|
|
967
|
+
}
|
|
968
|
+
id(id) {
|
|
969
|
+
this.widgetState.id = id;
|
|
970
|
+
return this;
|
|
971
|
+
}
|
|
972
|
+
layout(value) {
|
|
973
|
+
if (typeof value === 'number') {
|
|
974
|
+
this.widgetState.layout = {
|
|
975
|
+
positions: {
|
|
976
|
+
sm: { colSpan: 12 },
|
|
977
|
+
md: { colSpan: 12 },
|
|
978
|
+
lg: { colSpan: value },
|
|
979
|
+
xl: { colSpan: value },
|
|
980
|
+
xxl: { colSpan: value },
|
|
981
|
+
}
|
|
982
|
+
};
|
|
2318
983
|
}
|
|
2319
|
-
|
|
2320
|
-
|
|
984
|
+
else {
|
|
985
|
+
this.widgetState.layout = value;
|
|
986
|
+
}
|
|
987
|
+
return this;
|
|
988
|
+
}
|
|
989
|
+
mode(mode) {
|
|
990
|
+
this.widgetState.mode = mode;
|
|
991
|
+
return this;
|
|
992
|
+
}
|
|
993
|
+
visible(condition) {
|
|
994
|
+
this.widgetState.visible = condition;
|
|
995
|
+
return this;
|
|
996
|
+
}
|
|
997
|
+
disabled(condition) {
|
|
998
|
+
this.widgetState.disabled = condition;
|
|
999
|
+
return this;
|
|
1000
|
+
}
|
|
1001
|
+
readonly(condition) {
|
|
1002
|
+
this.widgetState.readonly = condition;
|
|
1003
|
+
return this;
|
|
1004
|
+
}
|
|
1005
|
+
order(value) {
|
|
1006
|
+
this.widgetState.order = value;
|
|
1007
|
+
return this;
|
|
1008
|
+
}
|
|
1009
|
+
// Container helpers - delegate pattern required
|
|
1010
|
+
grid(delegate) {
|
|
1011
|
+
const container = new GridContainerBuilder();
|
|
1012
|
+
if (delegate) {
|
|
1013
|
+
delegate(container);
|
|
1014
|
+
}
|
|
1015
|
+
const built = container.build();
|
|
1016
|
+
this.widgetState.widget = built.widget;
|
|
1017
|
+
this.widgetState.children = built.children;
|
|
1018
|
+
return this;
|
|
1019
|
+
}
|
|
1020
|
+
flex(delegate) {
|
|
1021
|
+
const container = new FlexContainerBuilder();
|
|
1022
|
+
if (delegate) {
|
|
1023
|
+
delegate(container);
|
|
1024
|
+
}
|
|
1025
|
+
const built = container.build();
|
|
1026
|
+
this.widgetState.widget = built.widget;
|
|
1027
|
+
this.widgetState.children = built.children;
|
|
1028
|
+
return this;
|
|
1029
|
+
}
|
|
1030
|
+
panel(delegate) {
|
|
1031
|
+
const container = new PanelContainerBuilder();
|
|
1032
|
+
if (delegate) {
|
|
1033
|
+
delegate(container);
|
|
1034
|
+
}
|
|
1035
|
+
const built = container.build();
|
|
1036
|
+
this.widgetState.widget = built.widget;
|
|
1037
|
+
this.widgetState.children = built.children;
|
|
1038
|
+
return this;
|
|
1039
|
+
}
|
|
1040
|
+
page(delegate) {
|
|
1041
|
+
const container = new PageContainerBuilder();
|
|
1042
|
+
if (delegate) {
|
|
1043
|
+
delegate(container);
|
|
1044
|
+
}
|
|
1045
|
+
const built = container.build();
|
|
1046
|
+
this.widgetState.widget = built.widget;
|
|
1047
|
+
this.widgetState.children = built.children;
|
|
1048
|
+
return this;
|
|
1049
|
+
}
|
|
1050
|
+
tabset(delegate) {
|
|
1051
|
+
const container = new TabsetContainerBuilder();
|
|
1052
|
+
if (delegate) {
|
|
1053
|
+
delegate(container);
|
|
1054
|
+
}
|
|
1055
|
+
const built = container.build();
|
|
1056
|
+
this.widgetState.widget = built.widget;
|
|
1057
|
+
this.widgetState.children = built.children;
|
|
1058
|
+
return this;
|
|
1059
|
+
}
|
|
1060
|
+
widget(name, delegate) {
|
|
1061
|
+
const child = new WidgetBuilder(name);
|
|
1062
|
+
if (delegate) {
|
|
1063
|
+
delegate(child);
|
|
1064
|
+
}
|
|
1065
|
+
this.widgetState.children = this.widgetState.children || [];
|
|
1066
|
+
this.widgetState.children.push(child.build());
|
|
1067
|
+
return this;
|
|
1068
|
+
}
|
|
1069
|
+
// Widget type methods
|
|
1070
|
+
textBox(options) {
|
|
1071
|
+
if (this.isContainerWidgetType(this.widgetState.widget?.type)) {
|
|
1072
|
+
const child = new WidgetBuilder();
|
|
1073
|
+
child.textBox(options);
|
|
1074
|
+
this.widgetState.children.push(child.build());
|
|
1075
|
+
return this;
|
|
2321
1076
|
}
|
|
2322
|
-
else
|
|
2323
|
-
|
|
1077
|
+
else {
|
|
1078
|
+
this.widgetState.widget = {
|
|
1079
|
+
type: 'text-editor',
|
|
1080
|
+
options,
|
|
1081
|
+
};
|
|
1082
|
+
return this;
|
|
2324
1083
|
}
|
|
2325
|
-
|
|
2326
|
-
|
|
1084
|
+
}
|
|
1085
|
+
largeTextBox(options) {
|
|
1086
|
+
if (this.isContainerWidgetType(this.widgetState.widget?.type)) {
|
|
1087
|
+
const child = new WidgetBuilder();
|
|
1088
|
+
child.largeTextBox(options);
|
|
1089
|
+
this.widgetState.children.push(child.build());
|
|
1090
|
+
return this;
|
|
2327
1091
|
}
|
|
2328
1092
|
else {
|
|
2329
|
-
|
|
1093
|
+
this.widgetState.widget = {
|
|
1094
|
+
type: 'large-text-editor',
|
|
1095
|
+
options,
|
|
1096
|
+
};
|
|
1097
|
+
return this;
|
|
2330
1098
|
}
|
|
2331
1099
|
}
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
1100
|
+
richText(options) {
|
|
1101
|
+
if (this.isContainerWidgetType(this.widgetState.widget?.type)) {
|
|
1102
|
+
const child = new WidgetBuilder();
|
|
1103
|
+
child.richText(options);
|
|
1104
|
+
this.widgetState.children.push(child.build());
|
|
1105
|
+
return this;
|
|
1106
|
+
}
|
|
1107
|
+
else {
|
|
1108
|
+
this.widgetState.widget = {
|
|
1109
|
+
type: 'rich-text-editor',
|
|
1110
|
+
options,
|
|
1111
|
+
};
|
|
1112
|
+
return this;
|
|
1113
|
+
}
|
|
2335
1114
|
}
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
1115
|
+
passwordBox(options) {
|
|
1116
|
+
if (this.isContainerWidgetType(this.widgetState.widget?.type)) {
|
|
1117
|
+
const child = new WidgetBuilder();
|
|
1118
|
+
child.passwordBox(options);
|
|
1119
|
+
this.widgetState.children.push(child.build());
|
|
1120
|
+
return this;
|
|
1121
|
+
}
|
|
1122
|
+
else {
|
|
1123
|
+
this.widgetState.widget = {
|
|
1124
|
+
type: 'password-editor',
|
|
1125
|
+
options,
|
|
1126
|
+
};
|
|
1127
|
+
return this;
|
|
1128
|
+
}
|
|
2344
1129
|
}
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
1130
|
+
numberBox(options) {
|
|
1131
|
+
if (this.isContainerWidgetType(this.widgetState.widget?.type)) {
|
|
1132
|
+
const child = new WidgetBuilder();
|
|
1133
|
+
child.numberBox(options);
|
|
1134
|
+
this.widgetState.children.push(child.build());
|
|
1135
|
+
return this;
|
|
1136
|
+
}
|
|
1137
|
+
else {
|
|
1138
|
+
this.widgetState.widget = {
|
|
1139
|
+
type: 'number-editor',
|
|
1140
|
+
options,
|
|
1141
|
+
};
|
|
1142
|
+
return this;
|
|
1143
|
+
}
|
|
2353
1144
|
}
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
1145
|
+
selectBox(options) {
|
|
1146
|
+
if (this.isContainerWidgetType(this.widgetState.widget?.type)) {
|
|
1147
|
+
const child = new WidgetBuilder();
|
|
1148
|
+
child.selectBox(options);
|
|
1149
|
+
this.widgetState.children.push(child.build());
|
|
1150
|
+
return this;
|
|
1151
|
+
}
|
|
1152
|
+
else {
|
|
1153
|
+
this.widgetState.widget = {
|
|
1154
|
+
type: 'select-editor',
|
|
1155
|
+
options,
|
|
1156
|
+
};
|
|
1157
|
+
return this;
|
|
1158
|
+
}
|
|
2359
1159
|
}
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
}
|
|
1160
|
+
lookupBox(options) {
|
|
1161
|
+
if (this.isContainerWidgetType(this.widgetState.widget?.type)) {
|
|
1162
|
+
const child = new WidgetBuilder();
|
|
1163
|
+
child.lookupBox(options);
|
|
1164
|
+
this.widgetState.children.push(child.build());
|
|
1165
|
+
return this;
|
|
1166
|
+
}
|
|
1167
|
+
else {
|
|
1168
|
+
this.widgetState.widget = {
|
|
1169
|
+
type: 'lookup-editor',
|
|
1170
|
+
options,
|
|
1171
|
+
};
|
|
1172
|
+
return this;
|
|
1173
|
+
}
|
|
2367
1174
|
}
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
]),
|
|
2383
|
-
};
|
|
1175
|
+
selectionList(options) {
|
|
1176
|
+
if (this.isContainerWidgetType(this.widgetState.widget?.type)) {
|
|
1177
|
+
const child = new WidgetBuilder();
|
|
1178
|
+
child.selectionList(options);
|
|
1179
|
+
this.widgetState.children.push(child.build());
|
|
1180
|
+
return this;
|
|
1181
|
+
}
|
|
1182
|
+
else {
|
|
1183
|
+
this.widgetState.widget = {
|
|
1184
|
+
type: 'selection-list',
|
|
1185
|
+
options,
|
|
1186
|
+
};
|
|
1187
|
+
return this;
|
|
1188
|
+
}
|
|
2384
1189
|
}
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
]),
|
|
2400
|
-
color: AXPPropertyEditorHelper.condenseShorthand([
|
|
2401
|
-
`${input.color.top}${units.color.top}`,
|
|
2402
|
-
`${input.color.right}${units.color.right}`,
|
|
2403
|
-
`${input.color.bottom}${units.color.bottom}`,
|
|
2404
|
-
`${input.color.left}${units.color.left}`,
|
|
2405
|
-
]),
|
|
2406
|
-
style: AXPPropertyEditorHelper.condenseShorthand([
|
|
2407
|
-
`${input.style.top}${units.style.top}`,
|
|
2408
|
-
`${input.style.right}${units.style.right}`,
|
|
2409
|
-
`${input.style.bottom}${units.style.bottom}`,
|
|
2410
|
-
`${input.style.left}${units.style.left}`,
|
|
2411
|
-
]),
|
|
2412
|
-
};
|
|
1190
|
+
dateTimeBox(options) {
|
|
1191
|
+
if (this.isContainerWidgetType(this.widgetState.widget?.type)) {
|
|
1192
|
+
const child = new WidgetBuilder();
|
|
1193
|
+
child.dateTimeBox(options);
|
|
1194
|
+
this.widgetState.children.push(child.build());
|
|
1195
|
+
return this;
|
|
1196
|
+
}
|
|
1197
|
+
else {
|
|
1198
|
+
this.widgetState.widget = {
|
|
1199
|
+
type: 'date-time-editor',
|
|
1200
|
+
options,
|
|
1201
|
+
};
|
|
1202
|
+
return this;
|
|
1203
|
+
}
|
|
2413
1204
|
}
|
|
2414
|
-
|
|
2415
|
-
if (
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
if (!match)
|
|
2421
|
-
throw new Error(`Invalid unit format: ${input}`);
|
|
2422
|
-
return { value: parseFloat(match[1]), unit: match[2] || '' };
|
|
2423
|
-
}
|
|
2424
|
-
static getValueFromUnit(value, unit) {
|
|
2425
|
-
return unit ? `${value}${unit}` : `${value}`;
|
|
2426
|
-
}
|
|
2427
|
-
static parseGap(gap) {
|
|
2428
|
-
const parts = gap.split(/\s+/);
|
|
2429
|
-
const match = parts[0].match(/^(\d+\.?\d*)([a-z%]+)$/);
|
|
2430
|
-
if (!match) {
|
|
2431
|
-
throw new Error('Invalid gap format');
|
|
1205
|
+
toggleSwitch(options) {
|
|
1206
|
+
if (this.isContainerWidgetType(this.widgetState.widget?.type)) {
|
|
1207
|
+
const child = new WidgetBuilder();
|
|
1208
|
+
child.toggleSwitch(options);
|
|
1209
|
+
this.widgetState.children.push(child.build());
|
|
1210
|
+
return this;
|
|
2432
1211
|
}
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
}
|
|
2440
|
-
yValue = parseFloat(secondMatch[1]);
|
|
1212
|
+
else {
|
|
1213
|
+
this.widgetState.widget = {
|
|
1214
|
+
type: 'toggle-editor',
|
|
1215
|
+
options,
|
|
1216
|
+
};
|
|
1217
|
+
return this;
|
|
2441
1218
|
}
|
|
2442
|
-
return {
|
|
2443
|
-
values: {
|
|
2444
|
-
x: parseFloat(xValue),
|
|
2445
|
-
y: yValue,
|
|
2446
|
-
},
|
|
2447
|
-
unit,
|
|
2448
|
-
};
|
|
2449
1219
|
}
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
1220
|
+
colorBox(options) {
|
|
1221
|
+
if (this.isContainerWidgetType(this.widgetState.widget?.type)) {
|
|
1222
|
+
const child = new WidgetBuilder();
|
|
1223
|
+
child.colorBox(options);
|
|
1224
|
+
this.widgetState.children.push(child.build());
|
|
1225
|
+
return this;
|
|
1226
|
+
}
|
|
1227
|
+
else {
|
|
1228
|
+
this.widgetState.widget = {
|
|
1229
|
+
type: 'color-editor',
|
|
1230
|
+
options,
|
|
1231
|
+
};
|
|
1232
|
+
return this;
|
|
2454
1233
|
}
|
|
2455
|
-
return parseInt(match[1], 10);
|
|
2456
1234
|
}
|
|
2457
|
-
|
|
2458
|
-
if (
|
|
2459
|
-
|
|
1235
|
+
customWidget(type, options) {
|
|
1236
|
+
if (this.isContainerWidgetType(this.widgetState.widget?.type)) {
|
|
1237
|
+
const child = new WidgetBuilder();
|
|
1238
|
+
child.customWidget(type, options);
|
|
1239
|
+
this.widgetState.children.push(child.build());
|
|
1240
|
+
return this;
|
|
2460
1241
|
}
|
|
2461
|
-
|
|
1242
|
+
else {
|
|
1243
|
+
this.widgetState.widget = {
|
|
1244
|
+
type,
|
|
1245
|
+
options: options,
|
|
1246
|
+
};
|
|
1247
|
+
return this;
|
|
1248
|
+
}
|
|
1249
|
+
}
|
|
1250
|
+
build() {
|
|
1251
|
+
return {
|
|
1252
|
+
id: this.widgetState.id,
|
|
1253
|
+
name: this.widgetState.name,
|
|
1254
|
+
widget: this.widgetState.widget,
|
|
1255
|
+
children: this.widgetState.children,
|
|
1256
|
+
layout: this.widgetState.layout,
|
|
1257
|
+
mode: this.widgetState.mode,
|
|
1258
|
+
order: this.widgetState.order,
|
|
1259
|
+
visible: this.widgetState.visible,
|
|
1260
|
+
disabled: this.widgetState.disabled,
|
|
1261
|
+
readonly: this.widgetState.readonly,
|
|
1262
|
+
};
|
|
2462
1263
|
}
|
|
2463
1264
|
}
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
1265
|
+
|
|
1266
|
+
class AXPLayoutRendererComponent {
|
|
1267
|
+
constructor() {
|
|
1268
|
+
this.renderedNode = {};
|
|
1269
|
+
}
|
|
1270
|
+
ngOnInit() {
|
|
1271
|
+
if (this.builder) {
|
|
1272
|
+
this.renderedNode = {
|
|
1273
|
+
type: 'block-layout',
|
|
1274
|
+
mode: this.builder.mode ?? 'view',
|
|
1275
|
+
children: (this.builder.nodes ?? []).map((node) => ({
|
|
1276
|
+
type: node.widget?.type ?? 'text-block-layout',
|
|
1277
|
+
mode: node.mode ?? 'view',
|
|
1278
|
+
children: (node.children ?? []).map((child) => ({
|
|
1279
|
+
type: child.widget?.type ?? 'text-block-layout',
|
|
1280
|
+
mode: child.mode ?? 'view',
|
|
1281
|
+
})),
|
|
1282
|
+
})),
|
|
1283
|
+
};
|
|
2470
1284
|
}
|
|
2471
1285
|
}
|
|
2472
|
-
|
|
1286
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: AXPLayoutRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1287
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.2.4", type: AXPLayoutRendererComponent, isStandalone: true, selector: "axp-layout-renderer", inputs: { builder: "builder" }, ngImport: i0, template: `
|
|
1288
|
+
<axp-widgets-container>
|
|
1289
|
+
<ng-container
|
|
1290
|
+
axp-widget-renderer
|
|
1291
|
+
[node]="renderedNode"
|
|
1292
|
+
[mode]="builder?.mode ?? 'view'">
|
|
1293
|
+
</ng-container>
|
|
1294
|
+
</axp-widgets-container>
|
|
1295
|
+
`, isInline: true, styles: [":host{display:block;width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXPWidgetCoreModule }, { kind: "component", type: i1.AXPWidgetContainerComponent, selector: "axp-widgets-container", inputs: ["context", "functions"], outputs: ["onContextChanged"] }, { kind: "directive", type: i1.AXPWidgetRendererDirective, selector: "[axp-widget-renderer]", inputs: ["parentNode", "index", "mode", "node"], outputs: ["onOptionsChanged", "onValueChanged"], exportAs: ["widgetRenderer"] }] }); }
|
|
2473
1296
|
}
|
|
1297
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: AXPLayoutRendererComponent, decorators: [{
|
|
1298
|
+
type: Component,
|
|
1299
|
+
args: [{ selector: 'axp-layout-renderer', standalone: true, imports: [CommonModule, AXPWidgetCoreModule], template: `
|
|
1300
|
+
<axp-widgets-container>
|
|
1301
|
+
<ng-container
|
|
1302
|
+
axp-widget-renderer
|
|
1303
|
+
[node]="renderedNode"
|
|
1304
|
+
[mode]="builder?.mode ?? 'view'">
|
|
1305
|
+
</ng-container>
|
|
1306
|
+
</axp-widgets-container>
|
|
1307
|
+
`, styles: [":host{display:block;width:100%}\n"] }]
|
|
1308
|
+
}], propDecorators: { builder: [{
|
|
1309
|
+
type: Input
|
|
1310
|
+
}] } });
|
|
2474
1311
|
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
}
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
title: 'Action',
|
|
2489
|
-
};
|
|
2490
|
-
const AXP_WIDGETS_ADVANCE_CATEGORY = {
|
|
2491
|
-
name: 'advance',
|
|
2492
|
-
order: 4,
|
|
2493
|
-
title: 'Advance',
|
|
2494
|
-
};
|
|
2495
|
-
const AXP_WIDGETS_CATEGORIES = [
|
|
2496
|
-
AXP_WIDGETS_LAYOUT_CATEGORY,
|
|
2497
|
-
AXP_WIDGETS_EDITOR_CATEGORY,
|
|
2498
|
-
AXP_WIDGETS_ACTION_CATEGORY,
|
|
2499
|
-
AXP_WIDGETS_ADVANCE_CATEGORY,
|
|
2500
|
-
];
|
|
2501
|
-
|
|
2502
|
-
var AXPWidgetGroupEnum;
|
|
2503
|
-
(function (AXPWidgetGroupEnum) {
|
|
2504
|
-
AXPWidgetGroupEnum["FormElement"] = "form-element";
|
|
2505
|
-
AXPWidgetGroupEnum["DashboardWidget"] = "dashboard-widget";
|
|
2506
|
-
AXPWidgetGroupEnum["FormTemplate"] = "form-template";
|
|
2507
|
-
AXPWidgetGroupEnum["PropertyEditor"] = "property-editor";
|
|
2508
|
-
AXPWidgetGroupEnum["MetaData"] = "meta-data";
|
|
2509
|
-
AXPWidgetGroupEnum["SettingWidget"] = "setting-widget";
|
|
2510
|
-
AXPWidgetGroupEnum["EntityWidget"] = "entity-widget";
|
|
2511
|
-
})(AXPWidgetGroupEnum || (AXPWidgetGroupEnum = {}));
|
|
1312
|
+
class LayoutBuilderModule {
|
|
1313
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: LayoutBuilderModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
1314
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.2.4", ngImport: i0, type: LayoutBuilderModule, imports: [CommonModule, AXPLayoutRendererComponent], exports: [AXPLayoutRendererComponent] }); }
|
|
1315
|
+
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: LayoutBuilderModule, providers: [AXPLayoutBuilderService], imports: [CommonModule, AXPLayoutRendererComponent] }); }
|
|
1316
|
+
}
|
|
1317
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: LayoutBuilderModule, decorators: [{
|
|
1318
|
+
type: NgModule,
|
|
1319
|
+
args: [{
|
|
1320
|
+
imports: [CommonModule, AXPLayoutRendererComponent],
|
|
1321
|
+
providers: [AXPLayoutBuilderService],
|
|
1322
|
+
exports: [AXPLayoutRendererComponent],
|
|
1323
|
+
}]
|
|
1324
|
+
}] });
|
|
2512
1325
|
|
|
2513
1326
|
/**
|
|
2514
1327
|
* Generated bundle index. Do not edit.
|
|
2515
1328
|
*/
|
|
2516
1329
|
|
|
2517
|
-
export {
|
|
1330
|
+
export { AXPLayoutBuilderService, AXPLayoutRendererComponent, LayoutBuilderModule };
|
|
2518
1331
|
//# sourceMappingURL=acorex-platform-layout-builder.mjs.map
|