@mintplayer/ng-spark 22.23.0 → 22.25.0
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/README.md +196 -0
- package/fesm2022/mintplayer-ng-spark-attribute-description.mjs +100 -47
- package/fesm2022/mintplayer-ng-spark-attribute-description.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-client-operations.mjs +310 -329
- package/fesm2022/mintplayer-ng-spark-client-operations.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-column-filter.mjs +175 -135
- package/fesm2022/mintplayer-ng-spark-column-filter.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-contributions.mjs +721 -0
- package/fesm2022/mintplayer-ng-spark-contributions.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-grid.mjs +2385 -1118
- package/fesm2022/mintplayer-ng-spark-grid.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-history.mjs +598 -0
- package/fesm2022/mintplayer-ng-spark-history.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-icon.mjs +64 -27
- package/fesm2022/mintplayer-ng-spark-icon.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-models.mjs +405 -762
- package/fesm2022/mintplayer-ng-spark-models.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-moderation.mjs +1212 -0
- package/fesm2022/mintplayer-ng-spark-moderation.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-panels.mjs +60 -0
- package/fesm2022/mintplayer-ng-spark-panels.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-pipes.mjs +1158 -765
- package/fesm2022/mintplayer-ng-spark-pipes.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-po-create.mjs +273 -169
- package/fesm2022/mintplayer-ng-spark-po-create.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-po-detail.mjs +795 -410
- package/fesm2022/mintplayer-ng-spark-po-detail.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-po-edit.mjs +1196 -280
- package/fesm2022/mintplayer-ng-spark-po-edit.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-po-form.mjs +2244 -1224
- package/fesm2022/mintplayer-ng-spark-po-form.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-query-list.mjs +571 -303
- package/fesm2022/mintplayer-ng-spark-query-list.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-renderers.mjs +44 -55
- package/fesm2022/mintplayer-ng-spark-renderers.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-retry-action-modal.mjs +216 -177
- package/fesm2022/mintplayer-ng-spark-retry-action-modal.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-routes.mjs +24 -28
- package/fesm2022/mintplayer-ng-spark-routes.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-services.mjs +625 -640
- package/fesm2022/mintplayer-ng-spark-services.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-shell.mjs +1031 -397
- package/fesm2022/mintplayer-ng-spark-shell.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-soft-delete.mjs +294 -0
- package/fesm2022/mintplayer-ng-spark-soft-delete.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark.mjs +14 -48
- package/fesm2022/mintplayer-ng-spark.mjs.map +1 -1
- package/package.json +23 -2
- package/types/mintplayer-ng-spark-attribute-description.d.ts +25 -18
- package/types/mintplayer-ng-spark-client-operations.d.ts +139 -160
- package/types/mintplayer-ng-spark-column-filter.d.ts +73 -55
- package/types/mintplayer-ng-spark-contributions.d.ts +231 -0
- package/types/mintplayer-ng-spark-grid.d.ts +917 -448
- package/types/mintplayer-ng-spark-history.d.ts +216 -0
- package/types/mintplayer-ng-spark-icon.d.ts +15 -13
- package/types/mintplayer-ng-spark-models.d.ts +681 -573
- package/types/mintplayer-ng-spark-moderation.d.ts +402 -0
- package/types/mintplayer-ng-spark-panels.d.ts +143 -0
- package/types/mintplayer-ng-spark-pipes.d.ts +131 -149
- package/types/mintplayer-ng-spark-po-create.d.ts +46 -37
- package/types/mintplayer-ng-spark-po-detail.d.ts +180 -117
- package/types/mintplayer-ng-spark-po-edit.d.ts +367 -64
- package/types/mintplayer-ng-spark-po-form.d.ts +558 -373
- package/types/mintplayer-ng-spark-query-list.d.ts +143 -82
- package/types/mintplayer-ng-spark-renderers.d.ts +121 -85
- package/types/mintplayer-ng-spark-retry-action-modal.d.ts +31 -34
- package/types/mintplayer-ng-spark-routes.d.ts +7 -11
- package/types/mintplayer-ng-spark-services.d.ts +377 -261
- package/types/mintplayer-ng-spark-shell.d.ts +228 -132
- package/types/mintplayer-ng-spark-soft-delete.d.ts +90 -0
- package/types/mintplayer-ng-spark.d.ts +19 -12
|
@@ -1,1228 +1,2248 @@
|
|
|
1
|
-
import * as i0 from
|
|
2
|
-
import {
|
|
3
|
-
import * as i1
|
|
4
|
-
import { CommonModule,
|
|
5
|
-
import * as i1 from
|
|
6
|
-
import { FormsModule } from
|
|
7
|
-
import {
|
|
8
|
-
import { Color } from
|
|
9
|
-
import { BsCardComponent, BsCardHeaderComponent } from
|
|
10
|
-
import { BsFormComponent, BsFormControlDirective } from
|
|
11
|
-
import {
|
|
12
|
-
import { BsInputGroupComponent } from
|
|
13
|
-
import { BsButtonTypeDirective } from
|
|
14
|
-
import { BsSelectComponent, BsSelectOption } from
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import { BsCheckboxComponent } from
|
|
18
|
-
import { BsSpinnerComponent } from
|
|
19
|
-
import { BsTabControlComponent, BsTabPageComponent, BsTabPageHeaderDirective } from
|
|
20
|
-
import { BsTableComponent } from
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import { SparkIconComponent } from
|
|
25
|
-
import { SparkAttributeDescriptionComponent } from
|
|
26
|
-
import { SPARK_ATTRIBUTE_RENDERERS, withDeclaredInputs } from
|
|
27
|
-
import {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
1
|
+
import * as i0 from "@angular/core";
|
|
2
|
+
import { ChangeDetectionStrategy, Component, DestroyRef, computed, effect, inject, input, model, output, signal } from "@angular/core";
|
|
3
|
+
import * as i1 from "@angular/common";
|
|
4
|
+
import { CommonModule, NgComponentOutlet, NgTemplateOutlet } from "@angular/common";
|
|
5
|
+
import * as i1$1 from "@angular/forms";
|
|
6
|
+
import { FormsModule } from "@angular/forms";
|
|
7
|
+
import { CdkDrag, CdkDragHandle, CdkDragPreview, CdkDropList, moveItemInArray } from "@angular/cdk/drag-drop";
|
|
8
|
+
import { Color } from "@mintplayer/ng-bootstrap";
|
|
9
|
+
import { BsCardComponent, BsCardHeaderComponent } from "@mintplayer/ng-bootstrap/card";
|
|
10
|
+
import { BsFormComponent, BsFormControlDirective } from "@mintplayer/ng-bootstrap/form";
|
|
11
|
+
import { BsColFormLabelDirective, BsGridColDirective, BsGridColumnDirective, BsGridComponent, BsGridRowDirective } from "@mintplayer/ng-bootstrap/grid";
|
|
12
|
+
import { BsInputGroupComponent } from "@mintplayer/ng-bootstrap/input-group";
|
|
13
|
+
import { BsButtonTypeDirective } from "@mintplayer/ng-bootstrap/button-type";
|
|
14
|
+
import { BsSelectComponent, BsSelectOption } from "@mintplayer/ng-bootstrap/select";
|
|
15
|
+
import { BsTreeSelectComponent, InMemoryTreeSelectProvider } from "@mintplayer/ng-bootstrap/tree-select";
|
|
16
|
+
import { BsModalBodyDirective, BsModalDirective, BsModalFooterDirective, BsModalHeaderDirective, BsModalHostComponent } from "@mintplayer/ng-bootstrap/modal";
|
|
17
|
+
import { BsCheckboxComponent } from "@mintplayer/ng-bootstrap/checkbox";
|
|
18
|
+
import { BsSpinnerComponent } from "@mintplayer/ng-bootstrap/spinner";
|
|
19
|
+
import { BsTabControlComponent, BsTabPageComponent, BsTabPageHeaderDirective } from "@mintplayer/ng-bootstrap/tab-control";
|
|
20
|
+
import { BsTableComponent } from "@mintplayer/ng-bootstrap/table";
|
|
21
|
+
import { SparkLanguageService, SparkService } from "@mintplayer/ng-spark/services";
|
|
22
|
+
import { AsDetailCellValuePipe, AsDetailColumnsPipe, AsDetailDisplayValuePipe, AsDetailRowRendererPipe, AsDetailTypePipe, CanCreateDetailRowPipe, CanDeleteDetailRowPipe, CanEditDetailRowPipe, ErrorForAttributePipe, InlineRefOptionsPipe, InputTypePipe, LookupDisplayTypePipe, LookupOptionsPipe, ReferenceAttrValuePipe, ResolveTranslationPipe, TranslateKeyPipe } from "@mintplayer/ng-spark/pipes";
|
|
23
|
+
import { AS_DETAIL_ROW_KEY, ELookupDisplayType, EReferenceDisplayType, ShowedOn, applyOverlay, evaluateRules, hasShowedOnFlag, mergeRefreshValues, nestedPoToDict, overlayFromResponse, resolveTranslation } from "@mintplayer/ng-spark/models";
|
|
24
|
+
import { SparkIconComponent } from "@mintplayer/ng-spark/icon";
|
|
25
|
+
import { SparkAttributeDescriptionComponent } from "@mintplayer/ng-spark/attribute-description";
|
|
26
|
+
import { SPARK_ATTRIBUTE_RENDERERS, rowRendererInputs, withDeclaredInputs } from "@mintplayer/ng-spark/renderers";
|
|
27
|
+
import { BsDatatableColumnDirective, BsDatatableComponent, BsRowTemplateDirective, DatatableSettings } from "@mintplayer/ng-bootstrap/datatable";
|
|
28
|
+
var SparkReferencePickerComponent = class SparkReferencePickerComponent {
|
|
29
|
+
sparkService = inject(SparkService);
|
|
30
|
+
lang = inject(SparkLanguageService);
|
|
31
|
+
value = input(null, ...ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []);
|
|
32
|
+
options = input([], ...ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []);
|
|
33
|
+
referenceType = input(void 0, ...ngDevMode ? [{ debugName: "referenceType" }] : /* istanbul ignore next */ []);
|
|
34
|
+
isInvalid = input(false, ...ngDevMode ? [{ debugName: "isInvalid" }] : /* istanbul ignore next */ []);
|
|
35
|
+
inputId = input(void 0, ...ngDevMode ? [{ debugName: "inputId" }] : /* istanbul ignore next */ []);
|
|
36
|
+
title = input("", ...ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []);
|
|
37
|
+
valueChange = output();
|
|
38
|
+
colors = Color;
|
|
39
|
+
showModal = signal(false, ...ngDevMode ? [{ debugName: "showModal" }] : /* istanbul ignore next */ []);
|
|
40
|
+
entityType = signal(null, ...ngDevMode ? [{ debugName: "entityType" }] : /* istanbul ignore next */ []);
|
|
41
|
+
pagination = signal(void 0, ...ngDevMode ? [{ debugName: "pagination" }] : /* istanbul ignore next */ []);
|
|
42
|
+
settings = signal(new DatatableSettings({
|
|
43
|
+
perPage: {
|
|
44
|
+
values: [
|
|
45
|
+
10,
|
|
46
|
+
25,
|
|
47
|
+
50
|
|
48
|
+
],
|
|
49
|
+
selected: 10
|
|
50
|
+
},
|
|
51
|
+
page: {
|
|
52
|
+
values: [1],
|
|
53
|
+
selected: 1
|
|
54
|
+
},
|
|
55
|
+
sortColumns: []
|
|
56
|
+
}), ...ngDevMode ? [{ debugName: "settings" }] : /* istanbul ignore next */ []);
|
|
57
|
+
searchTerm = "";
|
|
58
|
+
visibleAttributes = computed(() => {
|
|
59
|
+
return this.entityType()?.attributes.filter((a) => a.isVisible).sort((a, b) => a.order - b.order) || [];
|
|
60
|
+
}, ...ngDevMode ? [{ debugName: "visibleAttributes" }] : /* istanbul ignore next */ []);
|
|
61
|
+
rows = computed(() => this.pagination()?.data ?? [], ...ngDevMode ? [{ debugName: "rows" }] : /* istanbul ignore next */ []);
|
|
62
|
+
displayValue = computed(() => {
|
|
63
|
+
const id = this.value();
|
|
64
|
+
if (!id) return this.lang.t("common.notSelected");
|
|
65
|
+
return this.options().find((o) => o.id === id)?.breadcrumb || id;
|
|
66
|
+
}, ...ngDevMode ? [{ debugName: "displayValue" }] : /* istanbul ignore next */ []);
|
|
67
|
+
async open() {
|
|
68
|
+
this.searchTerm = "";
|
|
69
|
+
this.settings.set(new DatatableSettings({
|
|
70
|
+
perPage: {
|
|
71
|
+
values: [
|
|
72
|
+
10,
|
|
73
|
+
25,
|
|
74
|
+
50
|
|
75
|
+
],
|
|
76
|
+
selected: 10
|
|
77
|
+
},
|
|
78
|
+
page: {
|
|
79
|
+
values: [1],
|
|
80
|
+
selected: 1
|
|
81
|
+
},
|
|
82
|
+
sortColumns: []
|
|
83
|
+
}));
|
|
84
|
+
const refType = this.referenceType();
|
|
85
|
+
if (!this.entityType() && refType) {
|
|
86
|
+
const types = await this.sparkService.getEntityTypes();
|
|
87
|
+
this.entityType.set(types.find((t) => t.clrType === refType) || null);
|
|
88
|
+
}
|
|
89
|
+
this.applyFilter();
|
|
90
|
+
this.showModal.set(true);
|
|
91
|
+
}
|
|
92
|
+
onSearchChange() {
|
|
93
|
+
this.settings().page.selected = 1;
|
|
94
|
+
this.applyFilter();
|
|
95
|
+
}
|
|
96
|
+
applyFilter() {
|
|
97
|
+
let filteredItems = this.options();
|
|
98
|
+
if (this.searchTerm.trim()) {
|
|
99
|
+
const term = this.searchTerm.toLowerCase().trim();
|
|
100
|
+
filteredItems = this.options().filter((item) => {
|
|
101
|
+
if (item.breadcrumb?.toLowerCase().includes(term)) return true;
|
|
102
|
+
return item.values.some((v) => {
|
|
103
|
+
const value = v.breadcrumb ?? v.value;
|
|
104
|
+
if (value == null) return false;
|
|
105
|
+
return String(value).toLowerCase().includes(term);
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
const totalPages = Math.ceil(filteredItems.length / this.settings().perPage.selected) || 1;
|
|
110
|
+
this.pagination.set({
|
|
111
|
+
data: filteredItems,
|
|
112
|
+
totalRecords: filteredItems.length,
|
|
113
|
+
totalPages,
|
|
114
|
+
perPage: this.settings().perPage.selected,
|
|
115
|
+
page: this.settings().page.selected
|
|
116
|
+
});
|
|
117
|
+
this.settings().page.values = Array.from({ length: totalPages }, (_, i) => i + 1);
|
|
118
|
+
if (this.settings().page.selected > totalPages) this.settings().page.selected = 1;
|
|
119
|
+
}
|
|
120
|
+
clearSearch() {
|
|
121
|
+
this.searchTerm = "";
|
|
122
|
+
this.onSearchChange();
|
|
123
|
+
}
|
|
124
|
+
select(item) {
|
|
125
|
+
this.valueChange.emit(item.id ?? null);
|
|
126
|
+
this.close();
|
|
127
|
+
}
|
|
128
|
+
close() {
|
|
129
|
+
this.showModal.set(false);
|
|
130
|
+
this.searchTerm = "";
|
|
131
|
+
}
|
|
132
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
133
|
+
minVersion: "12.0.0",
|
|
134
|
+
version: "22.2.0",
|
|
135
|
+
ngImport: i0,
|
|
136
|
+
type: SparkReferencePickerComponent,
|
|
137
|
+
deps: [],
|
|
138
|
+
target: i0.ɵɵFactoryTarget.Component
|
|
139
|
+
});
|
|
140
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({
|
|
141
|
+
minVersion: "17.0.0",
|
|
142
|
+
version: "22.2.0",
|
|
143
|
+
type: SparkReferencePickerComponent,
|
|
144
|
+
isStandalone: true,
|
|
145
|
+
selector: "spark-reference-picker",
|
|
146
|
+
inputs: {
|
|
147
|
+
value: {
|
|
148
|
+
classPropertyName: "value",
|
|
149
|
+
publicName: "value",
|
|
150
|
+
isSignal: true,
|
|
151
|
+
isRequired: false,
|
|
152
|
+
transformFunction: null
|
|
153
|
+
},
|
|
154
|
+
options: {
|
|
155
|
+
classPropertyName: "options",
|
|
156
|
+
publicName: "options",
|
|
157
|
+
isSignal: true,
|
|
158
|
+
isRequired: false,
|
|
159
|
+
transformFunction: null
|
|
160
|
+
},
|
|
161
|
+
referenceType: {
|
|
162
|
+
classPropertyName: "referenceType",
|
|
163
|
+
publicName: "referenceType",
|
|
164
|
+
isSignal: true,
|
|
165
|
+
isRequired: false,
|
|
166
|
+
transformFunction: null
|
|
167
|
+
},
|
|
168
|
+
isInvalid: {
|
|
169
|
+
classPropertyName: "isInvalid",
|
|
170
|
+
publicName: "isInvalid",
|
|
171
|
+
isSignal: true,
|
|
172
|
+
isRequired: false,
|
|
173
|
+
transformFunction: null
|
|
174
|
+
},
|
|
175
|
+
inputId: {
|
|
176
|
+
classPropertyName: "inputId",
|
|
177
|
+
publicName: "inputId",
|
|
178
|
+
isSignal: true,
|
|
179
|
+
isRequired: false,
|
|
180
|
+
transformFunction: null
|
|
181
|
+
},
|
|
182
|
+
title: {
|
|
183
|
+
classPropertyName: "title",
|
|
184
|
+
publicName: "title",
|
|
185
|
+
isSignal: true,
|
|
186
|
+
isRequired: false,
|
|
187
|
+
transformFunction: null
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
outputs: { valueChange: "valueChange" },
|
|
191
|
+
ngImport: i0,
|
|
192
|
+
template: "<bs-input-group>\n <input\n type=\"text\"\n [id]=\"inputId()\"\n [value]=\"displayValue()\"\n readonly\n [class.is-invalid]=\"isInvalid()\">\n <button\n type=\"button\"\n bsInputGroupBtn\n [color]=\"colors.secondary\"\n (click)=\"open()\">\n ...\n </button>\n</bs-input-group>\n\n<bs-modal [isOpen]=\"showModal()\" (isOpenChange)=\"!$event && close()\">\n <div *bsModal class=\"reference-modal\">\n <div bsModalHeader>\n <h5 class=\"modal-title\">{{ 'common.select' | t }} {{ title() }}</h5>\n </div>\n\n <div bsModalBody>\n <!-- bs-modal portals its content into a CDK overlay outside the host form, so the\n modal needs its own <bs-form> context for inputs to pick up .form-control styles. -->\n <bs-form>\n @if (entityType()) {\n <!-- Search box -->\n <bs-grid>\n <div bsRow class=\"mb-3\">\n <div [md]=\"12\">\n <bs-input-group>\n <span class=\"addon\">\n <spark-icon name=\"search\" />\n </span>\n <input\n type=\"text\"\n [placeholder]=\"'common.search' | t\"\n [(ngModel)]=\"searchTerm\"\n (ngModelChange)=\"onSearchChange()\">\n @if (searchTerm) {\n <button\n type=\"button\"\n class=\"btn btn-outline-secondary\"\n (click)=\"clearSearch()\">\n <spark-icon name=\"x-lg\" />\n </button>\n }\n </bs-input-group>\n </div>\n @if (searchTerm && pagination()) {\n <div [md]=\"12\" class=\"text-end mt-1\">\n <span class=\"text-muted\">\n {{ pagination()!.totalRecords }} {{ pagination()!.totalRecords === 1 ? ('common.resultFound' | t) : ('common.resultsFound' | t) }}\n </span>\n </div>\n }\n </div>\n </bs-grid>\n\n <bs-datatable\n [(settings)]=\"settings\"\n [data]=\"rows()\"\n (rowClick)=\"select($event.row)\">\n @for (attr of visibleAttributes(); track attr.id) {\n <div *bsDatatableColumn=\"attr.name; sortable: true\">\n {{ attr.label | resolveTranslation:attr.name }}\n <spark-attribute-description [description]=\"attr.description\" />\n </div>\n }\n\n <ng-container *bsRowTemplate=\"let item\">\n @for (attr of visibleAttributes(); track attr.id) {\n <td>{{ $any(item) | referenceAttrValue:attr.name }}</td>\n }\n </ng-container>\n </bs-datatable>\n } @else {\n <div class=\"text-center p-3\">\n <bs-spinner />\n </div>\n }\n </bs-form>\n </div>\n\n <div bsModalFooter>\n <button type=\"button\" [color]=\"colors.secondary\" (click)=\"close()\">{{ 'common.cancel' | t }}</button>\n </div>\n </div>\n</bs-modal>\n",
|
|
193
|
+
dependencies: [
|
|
194
|
+
{
|
|
195
|
+
kind: "ngmodule",
|
|
196
|
+
type: FormsModule
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
kind: "directive",
|
|
200
|
+
type: i1$1.DefaultValueAccessor,
|
|
201
|
+
selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]"
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
kind: "directive",
|
|
205
|
+
type: i1$1.NgControlStatus,
|
|
206
|
+
selector: "[formControlName],[ngModel],[formControl]"
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
kind: "directive",
|
|
210
|
+
type: i1$1.NgModel,
|
|
211
|
+
selector: "[ngModel]:not([formControlName]):not([formControl])",
|
|
212
|
+
inputs: [
|
|
213
|
+
"name",
|
|
214
|
+
"disabled",
|
|
215
|
+
"ngModel",
|
|
216
|
+
"ngModelOptions"
|
|
217
|
+
],
|
|
218
|
+
outputs: ["ngModelChange"],
|
|
219
|
+
exportAs: ["ngModel"]
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
kind: "component",
|
|
223
|
+
type: BsFormComponent,
|
|
224
|
+
selector: "bs-form",
|
|
225
|
+
inputs: ["action", "method"],
|
|
226
|
+
outputs: ["submitted"]
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
kind: "directive",
|
|
230
|
+
type: BsFormControlDirective,
|
|
231
|
+
selector: "bs-form input:not(.no-form-control), bs-form textarea:not(.no-form-control)"
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
kind: "component",
|
|
235
|
+
type: BsGridComponent,
|
|
236
|
+
selector: "bs-grid",
|
|
237
|
+
inputs: ["stopFullWidthAt"]
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
kind: "directive",
|
|
241
|
+
type: BsGridRowDirective,
|
|
242
|
+
selector: "[bsRow]"
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
kind: "directive",
|
|
246
|
+
type: BsGridColumnDirective,
|
|
247
|
+
selector: "[xxs],[xs],[sm],[md],[lg],[xl],[xxl]",
|
|
248
|
+
inputs: [
|
|
249
|
+
"xxs",
|
|
250
|
+
"xs",
|
|
251
|
+
"sm",
|
|
252
|
+
"md",
|
|
253
|
+
"lg",
|
|
254
|
+
"xl",
|
|
255
|
+
"xxl"
|
|
256
|
+
]
|
|
257
|
+
},
|
|
258
|
+
{
|
|
259
|
+
kind: "component",
|
|
260
|
+
type: BsInputGroupComponent,
|
|
261
|
+
selector: "bs-input-group",
|
|
262
|
+
inputs: ["size"]
|
|
263
|
+
},
|
|
264
|
+
{
|
|
265
|
+
kind: "directive",
|
|
266
|
+
type: BsButtonTypeDirective,
|
|
267
|
+
selector: "button[color],input[type=\"button\"][color],input[type=\"submit\"][color],a[color]",
|
|
268
|
+
inputs: ["color"]
|
|
269
|
+
},
|
|
270
|
+
{
|
|
271
|
+
kind: "component",
|
|
272
|
+
type: BsModalHostComponent,
|
|
273
|
+
selector: "bs-modal",
|
|
274
|
+
inputs: [
|
|
275
|
+
"isOpen",
|
|
276
|
+
"closeOnEscape",
|
|
277
|
+
"scrollable"
|
|
278
|
+
],
|
|
279
|
+
outputs: ["isOpenChange"]
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
kind: "directive",
|
|
283
|
+
type: BsModalDirective,
|
|
284
|
+
selector: "[bsModal]"
|
|
285
|
+
},
|
|
286
|
+
{
|
|
287
|
+
kind: "directive",
|
|
288
|
+
type: BsModalHeaderDirective,
|
|
289
|
+
selector: "[bsModalHeader]"
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
kind: "directive",
|
|
293
|
+
type: BsModalBodyDirective,
|
|
294
|
+
selector: "[bsModalBody]"
|
|
295
|
+
},
|
|
296
|
+
{
|
|
297
|
+
kind: "directive",
|
|
298
|
+
type: BsModalFooterDirective,
|
|
299
|
+
selector: "[bsModalFooter]"
|
|
300
|
+
},
|
|
301
|
+
{
|
|
302
|
+
kind: "component",
|
|
303
|
+
type: BsDatatableComponent,
|
|
304
|
+
selector: "bs-datatable",
|
|
305
|
+
inputs: [
|
|
306
|
+
"columns",
|
|
307
|
+
"data",
|
|
308
|
+
"fetch",
|
|
309
|
+
"distincts",
|
|
310
|
+
"labels",
|
|
311
|
+
"settings",
|
|
312
|
+
"selectionMode",
|
|
313
|
+
"selectable",
|
|
314
|
+
"selection",
|
|
315
|
+
"rowKey",
|
|
316
|
+
"resizableColumns",
|
|
317
|
+
"pagination",
|
|
318
|
+
"virtualScroll",
|
|
319
|
+
"itemSize",
|
|
320
|
+
"virtualBuffer",
|
|
321
|
+
"isResponsive",
|
|
322
|
+
"compareWith",
|
|
323
|
+
"tree",
|
|
324
|
+
"idKey",
|
|
325
|
+
"childCountKey",
|
|
326
|
+
"treeIndent",
|
|
327
|
+
"expandedIds",
|
|
328
|
+
"selectionStrategy"
|
|
329
|
+
],
|
|
330
|
+
outputs: [
|
|
331
|
+
"settingsChange",
|
|
332
|
+
"selectionChange",
|
|
333
|
+
"rowClick",
|
|
334
|
+
"rowDblClick",
|
|
335
|
+
"rowContextMenu",
|
|
336
|
+
"expandedIdsChange",
|
|
337
|
+
"rowExpand",
|
|
338
|
+
"rowCollapse",
|
|
339
|
+
"filterChange"
|
|
340
|
+
]
|
|
341
|
+
},
|
|
342
|
+
{
|
|
343
|
+
kind: "directive",
|
|
344
|
+
type: BsDatatableColumnDirective,
|
|
345
|
+
selector: "[bsDatatableColumn]",
|
|
346
|
+
inputs: [
|
|
347
|
+
"bsDatatableColumn",
|
|
348
|
+
"bsDatatableColumnSortable",
|
|
349
|
+
"bsDatatableColumnFilterable",
|
|
350
|
+
"bsDatatableColumnFilterActive",
|
|
351
|
+
"bsDatatableColumnFilterSummary",
|
|
352
|
+
"bsDatatableColumnFilterSelection",
|
|
353
|
+
"bsDatatableColumnFilterMode",
|
|
354
|
+
"bsDatatableColumnFilterInputType",
|
|
355
|
+
"bsDatatableColumnFilterOperators"
|
|
356
|
+
]
|
|
357
|
+
},
|
|
358
|
+
{
|
|
359
|
+
kind: "directive",
|
|
360
|
+
type: BsRowTemplateDirective,
|
|
361
|
+
selector: "[bsRowTemplate]"
|
|
362
|
+
},
|
|
363
|
+
{
|
|
364
|
+
kind: "component",
|
|
365
|
+
type: BsSpinnerComponent,
|
|
366
|
+
selector: "bs-spinner",
|
|
367
|
+
inputs: ["type", "color"]
|
|
368
|
+
},
|
|
369
|
+
{
|
|
370
|
+
kind: "component",
|
|
371
|
+
type: SparkIconComponent,
|
|
372
|
+
selector: "spark-icon",
|
|
373
|
+
inputs: ["name"]
|
|
374
|
+
},
|
|
375
|
+
{
|
|
376
|
+
kind: "component",
|
|
377
|
+
type: SparkAttributeDescriptionComponent,
|
|
378
|
+
selector: "spark-attribute-description",
|
|
379
|
+
inputs: ["description", "position"]
|
|
380
|
+
},
|
|
381
|
+
{
|
|
382
|
+
kind: "pipe",
|
|
383
|
+
type: TranslateKeyPipe,
|
|
384
|
+
name: "t"
|
|
385
|
+
},
|
|
386
|
+
{
|
|
387
|
+
kind: "pipe",
|
|
388
|
+
type: ResolveTranslationPipe,
|
|
389
|
+
name: "resolveTranslation"
|
|
390
|
+
},
|
|
391
|
+
{
|
|
392
|
+
kind: "pipe",
|
|
393
|
+
type: ReferenceAttrValuePipe,
|
|
394
|
+
name: "referenceAttrValue"
|
|
395
|
+
}
|
|
396
|
+
],
|
|
397
|
+
changeDetection: i0.ChangeDetectionStrategy.OnPush
|
|
398
|
+
});
|
|
399
|
+
};
|
|
400
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
401
|
+
minVersion: "12.0.0",
|
|
402
|
+
version: "22.2.0",
|
|
403
|
+
ngImport: i0,
|
|
404
|
+
type: SparkReferencePickerComponent,
|
|
405
|
+
decorators: [{
|
|
406
|
+
type: Component,
|
|
407
|
+
args: [{
|
|
408
|
+
selector: "spark-reference-picker",
|
|
409
|
+
imports: [
|
|
410
|
+
FormsModule,
|
|
411
|
+
BsFormComponent,
|
|
412
|
+
BsFormControlDirective,
|
|
413
|
+
BsGridComponent,
|
|
414
|
+
BsGridRowDirective,
|
|
415
|
+
BsGridColumnDirective,
|
|
416
|
+
BsInputGroupComponent,
|
|
417
|
+
BsButtonTypeDirective,
|
|
418
|
+
BsModalHostComponent,
|
|
419
|
+
BsModalDirective,
|
|
420
|
+
BsModalHeaderDirective,
|
|
421
|
+
BsModalBodyDirective,
|
|
422
|
+
BsModalFooterDirective,
|
|
423
|
+
BsDatatableComponent,
|
|
424
|
+
BsDatatableColumnDirective,
|
|
425
|
+
BsRowTemplateDirective,
|
|
426
|
+
BsSpinnerComponent,
|
|
427
|
+
SparkIconComponent,
|
|
428
|
+
TranslateKeyPipe,
|
|
429
|
+
ResolveTranslationPipe,
|
|
430
|
+
ReferenceAttrValuePipe,
|
|
431
|
+
SparkAttributeDescriptionComponent
|
|
432
|
+
],
|
|
433
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
434
|
+
template: "<bs-input-group>\n <input\n type=\"text\"\n [id]=\"inputId()\"\n [value]=\"displayValue()\"\n readonly\n [class.is-invalid]=\"isInvalid()\">\n <button\n type=\"button\"\n bsInputGroupBtn\n [color]=\"colors.secondary\"\n (click)=\"open()\">\n ...\n </button>\n</bs-input-group>\n\n<bs-modal [isOpen]=\"showModal()\" (isOpenChange)=\"!$event && close()\">\n <div *bsModal class=\"reference-modal\">\n <div bsModalHeader>\n <h5 class=\"modal-title\">{{ 'common.select' | t }} {{ title() }}</h5>\n </div>\n\n <div bsModalBody>\n <!-- bs-modal portals its content into a CDK overlay outside the host form, so the\n modal needs its own <bs-form> context for inputs to pick up .form-control styles. -->\n <bs-form>\n @if (entityType()) {\n <!-- Search box -->\n <bs-grid>\n <div bsRow class=\"mb-3\">\n <div [md]=\"12\">\n <bs-input-group>\n <span class=\"addon\">\n <spark-icon name=\"search\" />\n </span>\n <input\n type=\"text\"\n [placeholder]=\"'common.search' | t\"\n [(ngModel)]=\"searchTerm\"\n (ngModelChange)=\"onSearchChange()\">\n @if (searchTerm) {\n <button\n type=\"button\"\n class=\"btn btn-outline-secondary\"\n (click)=\"clearSearch()\">\n <spark-icon name=\"x-lg\" />\n </button>\n }\n </bs-input-group>\n </div>\n @if (searchTerm && pagination()) {\n <div [md]=\"12\" class=\"text-end mt-1\">\n <span class=\"text-muted\">\n {{ pagination()!.totalRecords }} {{ pagination()!.totalRecords === 1 ? ('common.resultFound' | t) : ('common.resultsFound' | t) }}\n </span>\n </div>\n }\n </div>\n </bs-grid>\n\n <bs-datatable\n [(settings)]=\"settings\"\n [data]=\"rows()\"\n (rowClick)=\"select($event.row)\">\n @for (attr of visibleAttributes(); track attr.id) {\n <div *bsDatatableColumn=\"attr.name; sortable: true\">\n {{ attr.label | resolveTranslation:attr.name }}\n <spark-attribute-description [description]=\"attr.description\" />\n </div>\n }\n\n <ng-container *bsRowTemplate=\"let item\">\n @for (attr of visibleAttributes(); track attr.id) {\n <td>{{ $any(item) | referenceAttrValue:attr.name }}</td>\n }\n </ng-container>\n </bs-datatable>\n } @else {\n <div class=\"text-center p-3\">\n <bs-spinner />\n </div>\n }\n </bs-form>\n </div>\n\n <div bsModalFooter>\n <button type=\"button\" [color]=\"colors.secondary\" (click)=\"close()\">{{ 'common.cancel' | t }}</button>\n </div>\n </div>\n</bs-modal>\n"
|
|
435
|
+
}]
|
|
436
|
+
}],
|
|
437
|
+
propDecorators: {
|
|
438
|
+
value: [{
|
|
439
|
+
type: i0.Input,
|
|
440
|
+
args: [{
|
|
441
|
+
isSignal: true,
|
|
442
|
+
alias: "value",
|
|
443
|
+
required: false
|
|
444
|
+
}]
|
|
445
|
+
}],
|
|
446
|
+
options: [{
|
|
447
|
+
type: i0.Input,
|
|
448
|
+
args: [{
|
|
449
|
+
isSignal: true,
|
|
450
|
+
alias: "options",
|
|
451
|
+
required: false
|
|
452
|
+
}]
|
|
453
|
+
}],
|
|
454
|
+
referenceType: [{
|
|
455
|
+
type: i0.Input,
|
|
456
|
+
args: [{
|
|
457
|
+
isSignal: true,
|
|
458
|
+
alias: "referenceType",
|
|
459
|
+
required: false
|
|
460
|
+
}]
|
|
461
|
+
}],
|
|
462
|
+
isInvalid: [{
|
|
463
|
+
type: i0.Input,
|
|
464
|
+
args: [{
|
|
465
|
+
isSignal: true,
|
|
466
|
+
alias: "isInvalid",
|
|
467
|
+
required: false
|
|
468
|
+
}]
|
|
469
|
+
}],
|
|
470
|
+
inputId: [{
|
|
471
|
+
type: i0.Input,
|
|
472
|
+
args: [{
|
|
473
|
+
isSignal: true,
|
|
474
|
+
alias: "inputId",
|
|
475
|
+
required: false
|
|
476
|
+
}]
|
|
477
|
+
}],
|
|
478
|
+
title: [{
|
|
479
|
+
type: i0.Input,
|
|
480
|
+
args: [{
|
|
481
|
+
isSignal: true,
|
|
482
|
+
alias: "title",
|
|
483
|
+
required: false
|
|
484
|
+
}]
|
|
485
|
+
}],
|
|
486
|
+
valueChange: [{
|
|
487
|
+
type: i0.Output,
|
|
488
|
+
args: ["valueChange"]
|
|
489
|
+
}]
|
|
490
|
+
}
|
|
491
|
+
});
|
|
492
|
+
var SparkLookupPickerComponent = class SparkLookupPickerComponent {
|
|
493
|
+
value = input(null, ...ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []);
|
|
494
|
+
options = input([], ...ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []);
|
|
495
|
+
isInvalid = input(false, ...ngDevMode ? [{ debugName: "isInvalid" }] : /* istanbul ignore next */ []);
|
|
496
|
+
inputId = input(void 0, ...ngDevMode ? [{ debugName: "inputId" }] : /* istanbul ignore next */ []);
|
|
497
|
+
title = input("", ...ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []);
|
|
498
|
+
valueChange = output();
|
|
499
|
+
colors = Color;
|
|
500
|
+
showModal = signal(false, ...ngDevMode ? [{ debugName: "showModal" }] : /* istanbul ignore next */ []);
|
|
501
|
+
searchTerm = signal("", ...ngDevMode ? [{ debugName: "searchTerm" }] : /* istanbul ignore next */ []);
|
|
502
|
+
displayValue = computed(() => {
|
|
503
|
+
const key = this.value();
|
|
504
|
+
if (key == null || key === "") return "";
|
|
505
|
+
const selected = this.options().find((o) => o.key === String(key));
|
|
506
|
+
if (!selected) return String(key);
|
|
507
|
+
return resolveTranslation(selected.values) || selected.key;
|
|
508
|
+
}, ...ngDevMode ? [{ debugName: "displayValue" }] : /* istanbul ignore next */ []);
|
|
509
|
+
filteredItems = computed(() => {
|
|
510
|
+
if (!this.searchTerm().trim()) return this.options();
|
|
511
|
+
const term = this.searchTerm().toLowerCase().trim();
|
|
512
|
+
return this.options().filter((item) => {
|
|
513
|
+
return resolveTranslation(item.values).toLowerCase().includes(term) || item.key.toLowerCase().includes(term);
|
|
514
|
+
});
|
|
515
|
+
}, ...ngDevMode ? [{ debugName: "filteredItems" }] : /* istanbul ignore next */ []);
|
|
516
|
+
open() {
|
|
517
|
+
this.searchTerm.set("");
|
|
518
|
+
this.showModal.set(true);
|
|
519
|
+
}
|
|
520
|
+
select(item) {
|
|
521
|
+
this.valueChange.emit(item.key);
|
|
522
|
+
this.close();
|
|
523
|
+
}
|
|
524
|
+
close() {
|
|
525
|
+
this.showModal.set(false);
|
|
526
|
+
this.searchTerm.set("");
|
|
527
|
+
}
|
|
528
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
529
|
+
minVersion: "12.0.0",
|
|
530
|
+
version: "22.2.0",
|
|
531
|
+
ngImport: i0,
|
|
532
|
+
type: SparkLookupPickerComponent,
|
|
533
|
+
deps: [],
|
|
534
|
+
target: i0.ɵɵFactoryTarget.Component
|
|
535
|
+
});
|
|
536
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({
|
|
537
|
+
minVersion: "17.0.0",
|
|
538
|
+
version: "22.2.0",
|
|
539
|
+
type: SparkLookupPickerComponent,
|
|
540
|
+
isStandalone: true,
|
|
541
|
+
selector: "spark-lookup-picker",
|
|
542
|
+
inputs: {
|
|
543
|
+
value: {
|
|
544
|
+
classPropertyName: "value",
|
|
545
|
+
publicName: "value",
|
|
546
|
+
isSignal: true,
|
|
547
|
+
isRequired: false,
|
|
548
|
+
transformFunction: null
|
|
549
|
+
},
|
|
550
|
+
options: {
|
|
551
|
+
classPropertyName: "options",
|
|
552
|
+
publicName: "options",
|
|
553
|
+
isSignal: true,
|
|
554
|
+
isRequired: false,
|
|
555
|
+
transformFunction: null
|
|
556
|
+
},
|
|
557
|
+
isInvalid: {
|
|
558
|
+
classPropertyName: "isInvalid",
|
|
559
|
+
publicName: "isInvalid",
|
|
560
|
+
isSignal: true,
|
|
561
|
+
isRequired: false,
|
|
562
|
+
transformFunction: null
|
|
563
|
+
},
|
|
564
|
+
inputId: {
|
|
565
|
+
classPropertyName: "inputId",
|
|
566
|
+
publicName: "inputId",
|
|
567
|
+
isSignal: true,
|
|
568
|
+
isRequired: false,
|
|
569
|
+
transformFunction: null
|
|
570
|
+
},
|
|
571
|
+
title: {
|
|
572
|
+
classPropertyName: "title",
|
|
573
|
+
publicName: "title",
|
|
574
|
+
isSignal: true,
|
|
575
|
+
isRequired: false,
|
|
576
|
+
transformFunction: null
|
|
577
|
+
}
|
|
578
|
+
},
|
|
579
|
+
outputs: { valueChange: "valueChange" },
|
|
580
|
+
ngImport: i0,
|
|
581
|
+
template: "<bs-input-group>\n <input\n type=\"text\"\n [id]=\"inputId()\"\n [value]=\"displayValue()\"\n readonly\n [class.is-invalid]=\"isInvalid()\">\n <button\n type=\"button\"\n bsInputGroupBtn\n [color]=\"colors.secondary\"\n (click)=\"open()\">\n ...\n </button>\n</bs-input-group>\n\n<bs-modal [isOpen]=\"showModal()\" (isOpenChange)=\"!$event && close()\">\n <div *bsModal>\n <div bsModalHeader>\n <h5 class=\"modal-title\">{{ 'common.select' | t }} {{ title() }}</h5>\n </div>\n\n <div bsModalBody>\n <!-- bs-modal portals its content into a CDK overlay outside the host form, so the\n modal needs its own <bs-form> context for inputs to pick up .form-control styles. -->\n <bs-form>\n <!-- Search box -->\n <bs-grid>\n <div bsRow class=\"mb-3\">\n <div [col]>\n <bs-input-group>\n <span class=\"addon\">\n <spark-icon name=\"search\" />\n </span>\n <input\n type=\"text\"\n [placeholder]=\"'common.search' | t\"\n [ngModel]=\"searchTerm()\"\n (ngModelChange)=\"searchTerm.set($event)\">\n @if (searchTerm()) {\n <button\n type=\"button\"\n class=\"btn btn-outline-secondary\"\n (click)=\"searchTerm.set('')\">\n <spark-icon name=\"x-lg\" />\n </button>\n }\n </bs-input-group>\n </div>\n </div>\n </bs-grid>\n\n <!-- List of items -->\n <bs-table [striped]=\"true\" [hover]=\"true\">\n <tbody class=\"align-middle\">\n @for (item of filteredItems(); track item.key) {\n <tr\n [class.table-primary]=\"value() === item.key\"\n (click)=\"select(item)\"\n style=\"cursor: pointer;\">\n <td>{{ item.values | resolveTranslation:item.key }}</td>\n </tr>\n } @empty {\n <tr>\n <td class=\"text-center text-muted\">{{ 'common.noItemsFound' | t }}</td>\n </tr>\n }\n </tbody>\n </bs-table>\n </bs-form>\n </div>\n\n <div bsModalFooter>\n <button type=\"button\" [color]=\"colors.secondary\" (click)=\"close()\">{{ 'common.cancel' | t }}</button>\n </div>\n </div>\n</bs-modal>\n",
|
|
582
|
+
dependencies: [
|
|
583
|
+
{
|
|
584
|
+
kind: "ngmodule",
|
|
585
|
+
type: FormsModule
|
|
586
|
+
},
|
|
587
|
+
{
|
|
588
|
+
kind: "directive",
|
|
589
|
+
type: i1$1.DefaultValueAccessor,
|
|
590
|
+
selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]"
|
|
591
|
+
},
|
|
592
|
+
{
|
|
593
|
+
kind: "directive",
|
|
594
|
+
type: i1$1.NgControlStatus,
|
|
595
|
+
selector: "[formControlName],[ngModel],[formControl]"
|
|
596
|
+
},
|
|
597
|
+
{
|
|
598
|
+
kind: "directive",
|
|
599
|
+
type: i1$1.NgModel,
|
|
600
|
+
selector: "[ngModel]:not([formControlName]):not([formControl])",
|
|
601
|
+
inputs: [
|
|
602
|
+
"name",
|
|
603
|
+
"disabled",
|
|
604
|
+
"ngModel",
|
|
605
|
+
"ngModelOptions"
|
|
606
|
+
],
|
|
607
|
+
outputs: ["ngModelChange"],
|
|
608
|
+
exportAs: ["ngModel"]
|
|
609
|
+
},
|
|
610
|
+
{
|
|
611
|
+
kind: "component",
|
|
612
|
+
type: BsFormComponent,
|
|
613
|
+
selector: "bs-form",
|
|
614
|
+
inputs: ["action", "method"],
|
|
615
|
+
outputs: ["submitted"]
|
|
616
|
+
},
|
|
617
|
+
{
|
|
618
|
+
kind: "directive",
|
|
619
|
+
type: BsFormControlDirective,
|
|
620
|
+
selector: "bs-form input:not(.no-form-control), bs-form textarea:not(.no-form-control)"
|
|
621
|
+
},
|
|
622
|
+
{
|
|
623
|
+
kind: "component",
|
|
624
|
+
type: BsGridComponent,
|
|
625
|
+
selector: "bs-grid",
|
|
626
|
+
inputs: ["stopFullWidthAt"]
|
|
627
|
+
},
|
|
628
|
+
{
|
|
629
|
+
kind: "directive",
|
|
630
|
+
type: BsGridRowDirective,
|
|
631
|
+
selector: "[bsRow]"
|
|
632
|
+
},
|
|
633
|
+
{
|
|
634
|
+
kind: "directive",
|
|
635
|
+
type: BsGridColDirective,
|
|
636
|
+
selector: "[col]",
|
|
637
|
+
inputs: ["col"]
|
|
638
|
+
},
|
|
639
|
+
{
|
|
640
|
+
kind: "component",
|
|
641
|
+
type: BsInputGroupComponent,
|
|
642
|
+
selector: "bs-input-group",
|
|
643
|
+
inputs: ["size"]
|
|
644
|
+
},
|
|
645
|
+
{
|
|
646
|
+
kind: "directive",
|
|
647
|
+
type: BsButtonTypeDirective,
|
|
648
|
+
selector: "button[color],input[type=\"button\"][color],input[type=\"submit\"][color],a[color]",
|
|
649
|
+
inputs: ["color"]
|
|
650
|
+
},
|
|
651
|
+
{
|
|
652
|
+
kind: "component",
|
|
653
|
+
type: BsModalHostComponent,
|
|
654
|
+
selector: "bs-modal",
|
|
655
|
+
inputs: [
|
|
656
|
+
"isOpen",
|
|
657
|
+
"closeOnEscape",
|
|
658
|
+
"scrollable"
|
|
659
|
+
],
|
|
660
|
+
outputs: ["isOpenChange"]
|
|
661
|
+
},
|
|
662
|
+
{
|
|
663
|
+
kind: "directive",
|
|
664
|
+
type: BsModalDirective,
|
|
665
|
+
selector: "[bsModal]"
|
|
666
|
+
},
|
|
667
|
+
{
|
|
668
|
+
kind: "directive",
|
|
669
|
+
type: BsModalHeaderDirective,
|
|
670
|
+
selector: "[bsModalHeader]"
|
|
671
|
+
},
|
|
672
|
+
{
|
|
673
|
+
kind: "directive",
|
|
674
|
+
type: BsModalBodyDirective,
|
|
675
|
+
selector: "[bsModalBody]"
|
|
676
|
+
},
|
|
677
|
+
{
|
|
678
|
+
kind: "directive",
|
|
679
|
+
type: BsModalFooterDirective,
|
|
680
|
+
selector: "[bsModalFooter]"
|
|
681
|
+
},
|
|
682
|
+
{
|
|
683
|
+
kind: "component",
|
|
684
|
+
type: BsTableComponent,
|
|
685
|
+
selector: "bs-table",
|
|
686
|
+
inputs: [
|
|
687
|
+
"isResponsive",
|
|
688
|
+
"striped",
|
|
689
|
+
"hover",
|
|
690
|
+
"border",
|
|
691
|
+
"ariaRowCount"
|
|
692
|
+
]
|
|
693
|
+
},
|
|
694
|
+
{
|
|
695
|
+
kind: "component",
|
|
696
|
+
type: SparkIconComponent,
|
|
697
|
+
selector: "spark-icon",
|
|
698
|
+
inputs: ["name"]
|
|
699
|
+
},
|
|
700
|
+
{
|
|
701
|
+
kind: "pipe",
|
|
702
|
+
type: TranslateKeyPipe,
|
|
703
|
+
name: "t"
|
|
704
|
+
},
|
|
705
|
+
{
|
|
706
|
+
kind: "pipe",
|
|
707
|
+
type: ResolveTranslationPipe,
|
|
708
|
+
name: "resolveTranslation"
|
|
709
|
+
}
|
|
710
|
+
],
|
|
711
|
+
changeDetection: i0.ChangeDetectionStrategy.OnPush
|
|
712
|
+
});
|
|
713
|
+
};
|
|
714
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
715
|
+
minVersion: "12.0.0",
|
|
716
|
+
version: "22.2.0",
|
|
717
|
+
ngImport: i0,
|
|
718
|
+
type: SparkLookupPickerComponent,
|
|
719
|
+
decorators: [{
|
|
720
|
+
type: Component,
|
|
721
|
+
args: [{
|
|
722
|
+
selector: "spark-lookup-picker",
|
|
723
|
+
imports: [
|
|
724
|
+
FormsModule,
|
|
725
|
+
BsFormComponent,
|
|
726
|
+
BsFormControlDirective,
|
|
727
|
+
BsGridComponent,
|
|
728
|
+
BsGridRowDirective,
|
|
729
|
+
BsGridColDirective,
|
|
730
|
+
BsInputGroupComponent,
|
|
731
|
+
BsButtonTypeDirective,
|
|
732
|
+
BsModalHostComponent,
|
|
733
|
+
BsModalDirective,
|
|
734
|
+
BsModalHeaderDirective,
|
|
735
|
+
BsModalBodyDirective,
|
|
736
|
+
BsModalFooterDirective,
|
|
737
|
+
BsTableComponent,
|
|
738
|
+
SparkIconComponent,
|
|
739
|
+
TranslateKeyPipe,
|
|
740
|
+
ResolveTranslationPipe
|
|
741
|
+
],
|
|
742
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
743
|
+
template: "<bs-input-group>\n <input\n type=\"text\"\n [id]=\"inputId()\"\n [value]=\"displayValue()\"\n readonly\n [class.is-invalid]=\"isInvalid()\">\n <button\n type=\"button\"\n bsInputGroupBtn\n [color]=\"colors.secondary\"\n (click)=\"open()\">\n ...\n </button>\n</bs-input-group>\n\n<bs-modal [isOpen]=\"showModal()\" (isOpenChange)=\"!$event && close()\">\n <div *bsModal>\n <div bsModalHeader>\n <h5 class=\"modal-title\">{{ 'common.select' | t }} {{ title() }}</h5>\n </div>\n\n <div bsModalBody>\n <!-- bs-modal portals its content into a CDK overlay outside the host form, so the\n modal needs its own <bs-form> context for inputs to pick up .form-control styles. -->\n <bs-form>\n <!-- Search box -->\n <bs-grid>\n <div bsRow class=\"mb-3\">\n <div [col]>\n <bs-input-group>\n <span class=\"addon\">\n <spark-icon name=\"search\" />\n </span>\n <input\n type=\"text\"\n [placeholder]=\"'common.search' | t\"\n [ngModel]=\"searchTerm()\"\n (ngModelChange)=\"searchTerm.set($event)\">\n @if (searchTerm()) {\n <button\n type=\"button\"\n class=\"btn btn-outline-secondary\"\n (click)=\"searchTerm.set('')\">\n <spark-icon name=\"x-lg\" />\n </button>\n }\n </bs-input-group>\n </div>\n </div>\n </bs-grid>\n\n <!-- List of items -->\n <bs-table [striped]=\"true\" [hover]=\"true\">\n <tbody class=\"align-middle\">\n @for (item of filteredItems(); track item.key) {\n <tr\n [class.table-primary]=\"value() === item.key\"\n (click)=\"select(item)\"\n style=\"cursor: pointer;\">\n <td>{{ item.values | resolveTranslation:item.key }}</td>\n </tr>\n } @empty {\n <tr>\n <td class=\"text-center text-muted\">{{ 'common.noItemsFound' | t }}</td>\n </tr>\n }\n </tbody>\n </bs-table>\n </bs-form>\n </div>\n\n <div bsModalFooter>\n <button type=\"button\" [color]=\"colors.secondary\" (click)=\"close()\">{{ 'common.cancel' | t }}</button>\n </div>\n </div>\n</bs-modal>\n"
|
|
744
|
+
}]
|
|
745
|
+
}],
|
|
746
|
+
propDecorators: {
|
|
747
|
+
value: [{
|
|
748
|
+
type: i0.Input,
|
|
749
|
+
args: [{
|
|
750
|
+
isSignal: true,
|
|
751
|
+
alias: "value",
|
|
752
|
+
required: false
|
|
753
|
+
}]
|
|
754
|
+
}],
|
|
755
|
+
options: [{
|
|
756
|
+
type: i0.Input,
|
|
757
|
+
args: [{
|
|
758
|
+
isSignal: true,
|
|
759
|
+
alias: "options",
|
|
760
|
+
required: false
|
|
761
|
+
}]
|
|
762
|
+
}],
|
|
763
|
+
isInvalid: [{
|
|
764
|
+
type: i0.Input,
|
|
765
|
+
args: [{
|
|
766
|
+
isSignal: true,
|
|
767
|
+
alias: "isInvalid",
|
|
768
|
+
required: false
|
|
769
|
+
}]
|
|
770
|
+
}],
|
|
771
|
+
inputId: [{
|
|
772
|
+
type: i0.Input,
|
|
773
|
+
args: [{
|
|
774
|
+
isSignal: true,
|
|
775
|
+
alias: "inputId",
|
|
776
|
+
required: false
|
|
777
|
+
}]
|
|
778
|
+
}],
|
|
779
|
+
title: [{
|
|
780
|
+
type: i0.Input,
|
|
781
|
+
args: [{
|
|
782
|
+
isSignal: true,
|
|
783
|
+
alias: "title",
|
|
784
|
+
required: false
|
|
785
|
+
}]
|
|
786
|
+
}],
|
|
787
|
+
valueChange: [{
|
|
788
|
+
type: i0.Output,
|
|
789
|
+
args: ["valueChange"]
|
|
790
|
+
}]
|
|
791
|
+
}
|
|
792
|
+
});
|
|
793
|
+
var RefreshCoordinator = class {
|
|
794
|
+
host;
|
|
795
|
+
queue = Promise.resolve();
|
|
796
|
+
sequence = 0;
|
|
797
|
+
settled = 0;
|
|
798
|
+
pending = /* @__PURE__ */ new Set();
|
|
799
|
+
timers = /* @__PURE__ */ new Map();
|
|
800
|
+
constructor(host) {
|
|
801
|
+
this.host = host;
|
|
802
|
+
}
|
|
803
|
+
get isRefreshing() {
|
|
804
|
+
return this.sequence !== this.settled;
|
|
805
|
+
}
|
|
806
|
+
markPending(attributeName) {
|
|
807
|
+
this.pending.add(attributeName);
|
|
808
|
+
}
|
|
809
|
+
dispatch(attributeName, mode) {
|
|
810
|
+
switch (mode) {
|
|
811
|
+
case "immediate": return this.trigger(attributeName);
|
|
812
|
+
case "debounced": return this.trigger(attributeName, { debounceMs: 300 });
|
|
813
|
+
case "blur":
|
|
814
|
+
this.markPending(attributeName);
|
|
815
|
+
return Promise.resolve();
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
blur(attributeName) {
|
|
819
|
+
this.clearTimer(attributeName);
|
|
820
|
+
if (!this.pending.delete(attributeName)) return Promise.resolve();
|
|
821
|
+
return this.trigger(attributeName);
|
|
822
|
+
}
|
|
823
|
+
async flush() {
|
|
824
|
+
for (const name of [...this.timers.keys()]) this.clearTimer(name);
|
|
825
|
+
const names = [...this.pending];
|
|
826
|
+
this.pending.clear();
|
|
827
|
+
for (const name of names) await this.trigger(name);
|
|
828
|
+
await this.queue;
|
|
829
|
+
}
|
|
830
|
+
dispose() {
|
|
831
|
+
for (const name of [...this.timers.keys()]) this.clearTimer(name);
|
|
832
|
+
this.pending.clear();
|
|
833
|
+
}
|
|
834
|
+
trigger(attributeName, options) {
|
|
835
|
+
const debounceMs = options?.debounceMs ?? 0;
|
|
836
|
+
if (debounceMs > 0) {
|
|
837
|
+
this.clearTimer(attributeName);
|
|
838
|
+
this.pending.add(attributeName);
|
|
839
|
+
this.timers.set(attributeName, setTimeout(() => {
|
|
840
|
+
this.timers.delete(attributeName);
|
|
841
|
+
if (this.pending.delete(attributeName)) this.trigger(attributeName);
|
|
842
|
+
}, debounceMs));
|
|
843
|
+
return Promise.resolve();
|
|
844
|
+
}
|
|
845
|
+
this.clearTimer(attributeName);
|
|
846
|
+
this.pending.delete(attributeName);
|
|
847
|
+
const ticket = ++this.sequence;
|
|
848
|
+
this.host.setBusy(true);
|
|
849
|
+
this.queue = this.queue.then(async () => {
|
|
850
|
+
const sent = { ...this.host.currentValues() };
|
|
851
|
+
try {
|
|
852
|
+
const response = await this.host.send(attributeName);
|
|
853
|
+
if (ticket !== this.sequence) return;
|
|
854
|
+
this.host.apply(response, sent);
|
|
855
|
+
} finally {
|
|
856
|
+
this.settled = Math.max(this.settled, ticket);
|
|
857
|
+
if (!this.isRefreshing) this.host.setBusy(false);
|
|
858
|
+
}
|
|
859
|
+
});
|
|
860
|
+
return this.queue;
|
|
861
|
+
}
|
|
862
|
+
clearTimer(attributeName) {
|
|
863
|
+
const timer = this.timers.get(attributeName);
|
|
864
|
+
if (timer === void 0) return;
|
|
865
|
+
clearTimeout(timer);
|
|
866
|
+
this.timers.delete(attributeName);
|
|
867
|
+
}
|
|
868
|
+
};
|
|
869
|
+
function effectiveTrigger(attr) {
|
|
870
|
+
switch (attr?.triggersRefresh) {
|
|
871
|
+
case "Auto": return isDiscreteEditor(attr) ? "change" : "blur";
|
|
872
|
+
case "ValueChanged": return "change";
|
|
873
|
+
case "Blur": return isDiscreteEditor(attr) ? "change" : "blur";
|
|
874
|
+
default: return "none";
|
|
875
|
+
}
|
|
154
876
|
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
* Reusable LookupReference value picker: a readonly textbox showing the current selection's
|
|
162
|
-
* translated label plus a "…" button that opens a searchable modal list over the active
|
|
163
|
-
* `options`. Per-instance state, so it serves both top-level lookup attributes (display type
|
|
164
|
-
* Modal) and individual inline AsDetail lookup cells. Emits the picked key via `valueChange`.
|
|
165
|
-
*/
|
|
166
|
-
class SparkLookupPickerComponent {
|
|
167
|
-
/** Currently selected lookup key (or null when unset). */
|
|
168
|
-
value = input(null, /* @ts-ignore */
|
|
169
|
-
...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
170
|
-
/** Active lookup values to pick from. */
|
|
171
|
-
options = input([], /* @ts-ignore */
|
|
172
|
-
...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
|
|
173
|
-
/** Renders the field with the Bootstrap is-invalid state. */
|
|
174
|
-
isInvalid = input(false, /* @ts-ignore */
|
|
175
|
-
...(ngDevMode ? [{ debugName: "isInvalid" }] : /* istanbul ignore next */ []));
|
|
176
|
-
/** Optional id forwarded to the readonly input (for label association). */
|
|
177
|
-
inputId = input(undefined, /* @ts-ignore */
|
|
178
|
-
...(ngDevMode ? [{ debugName: "inputId" }] : /* istanbul ignore next */ []));
|
|
179
|
-
/** Optional resolved label appended to the modal header ("Select {title}"). */
|
|
180
|
-
title = input('', /* @ts-ignore */
|
|
181
|
-
...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
182
|
-
valueChange = output();
|
|
183
|
-
colors = Color;
|
|
184
|
-
showModal = signal(false, /* @ts-ignore */
|
|
185
|
-
...(ngDevMode ? [{ debugName: "showModal" }] : /* istanbul ignore next */ []));
|
|
186
|
-
searchTerm = signal('', /* @ts-ignore */
|
|
187
|
-
...(ngDevMode ? [{ debugName: "searchTerm" }] : /* istanbul ignore next */ []));
|
|
188
|
-
displayValue = computed(() => {
|
|
189
|
-
const key = this.value();
|
|
190
|
-
if (key == null || key === '')
|
|
191
|
-
return '';
|
|
192
|
-
const selected = this.options().find(o => o.key === String(key));
|
|
193
|
-
if (!selected)
|
|
194
|
-
return String(key);
|
|
195
|
-
return resolveTranslation(selected.values) || selected.key;
|
|
196
|
-
}, /* @ts-ignore */
|
|
197
|
-
...(ngDevMode ? [{ debugName: "displayValue" }] : /* istanbul ignore next */ []));
|
|
198
|
-
filteredItems = computed(() => {
|
|
199
|
-
if (!this.searchTerm().trim()) {
|
|
200
|
-
return this.options();
|
|
201
|
-
}
|
|
202
|
-
const term = this.searchTerm().toLowerCase().trim();
|
|
203
|
-
return this.options().filter(item => {
|
|
204
|
-
const translation = resolveTranslation(item.values);
|
|
205
|
-
return translation.toLowerCase().includes(term) || item.key.toLowerCase().includes(term);
|
|
206
|
-
});
|
|
207
|
-
}, /* @ts-ignore */
|
|
208
|
-
...(ngDevMode ? [{ debugName: "filteredItems" }] : /* istanbul ignore next */ []));
|
|
209
|
-
open() {
|
|
210
|
-
this.searchTerm.set('');
|
|
211
|
-
this.showModal.set(true);
|
|
212
|
-
}
|
|
213
|
-
select(item) {
|
|
214
|
-
this.valueChange.emit(item.key);
|
|
215
|
-
this.close();
|
|
216
|
-
}
|
|
217
|
-
close() {
|
|
218
|
-
this.showModal.set(false);
|
|
219
|
-
this.searchTerm.set('');
|
|
220
|
-
}
|
|
221
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: SparkLookupPickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
222
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: SparkLookupPickerComponent, isStandalone: true, selector: "spark-lookup-picker", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, isInvalid: { classPropertyName: "isInvalid", publicName: "isInvalid", isSignal: true, isRequired: false, transformFunction: null }, inputId: { classPropertyName: "inputId", publicName: "inputId", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange" }, ngImport: i0, template: "<bs-input-group>\n <input\n type=\"text\"\n [id]=\"inputId()\"\n [value]=\"displayValue()\"\n readonly\n [class.is-invalid]=\"isInvalid()\">\n <button\n type=\"button\"\n bsInputGroupBtn\n [color]=\"colors.secondary\"\n (click)=\"open()\">\n ...\n </button>\n</bs-input-group>\n\n<bs-modal [isOpen]=\"showModal()\" (isOpenChange)=\"!$event && close()\">\n <div *bsModal>\n <div bsModalHeader>\n <h5 class=\"modal-title\">{{ 'common.select' | t }} {{ title() }}</h5>\n </div>\n\n <div bsModalBody>\n <!-- bs-modal portals its content into a CDK overlay outside the host form, so the\n modal needs its own <bs-form> context for inputs to pick up .form-control styles. -->\n <bs-form>\n <!-- Search box -->\n <bs-grid>\n <div bsRow class=\"mb-3\">\n <div [col]>\n <bs-input-group>\n <span class=\"addon\">\n <spark-icon name=\"search\" />\n </span>\n <input\n type=\"text\"\n [placeholder]=\"'common.search' | t\"\n [ngModel]=\"searchTerm()\"\n (ngModelChange)=\"searchTerm.set($event)\">\n @if (searchTerm()) {\n <button\n type=\"button\"\n class=\"btn btn-outline-secondary\"\n (click)=\"searchTerm.set('')\">\n <spark-icon name=\"x-lg\" />\n </button>\n }\n </bs-input-group>\n </div>\n </div>\n </bs-grid>\n\n <!-- List of items -->\n <bs-table [striped]=\"true\" [hover]=\"true\">\n <tbody class=\"align-middle\">\n @for (item of filteredItems(); track item.key) {\n <tr\n [class.table-primary]=\"value() === item.key\"\n (click)=\"select(item)\"\n style=\"cursor: pointer;\">\n <td>{{ item.values | resolveTranslation:item.key }}</td>\n </tr>\n } @empty {\n <tr>\n <td class=\"text-center text-muted\">{{ 'common.noItemsFound' | t }}</td>\n </tr>\n }\n </tbody>\n </bs-table>\n </bs-form>\n </div>\n\n <div bsModalFooter>\n <button type=\"button\" [color]=\"colors.secondary\" (click)=\"close()\">{{ 'common.cancel' | t }}</button>\n </div>\n </div>\n</bs-modal>\n", dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: BsFormComponent, selector: "bs-form", inputs: ["action", "method"], outputs: ["submitted"] }, { kind: "directive", type: BsFormControlDirective, selector: "bs-form input:not(.no-form-control), bs-form textarea:not(.no-form-control)" }, { kind: "component", type: BsGridComponent, selector: "bs-grid", inputs: ["stopFullWidthAt"] }, { kind: "directive", type: BsGridRowDirective, selector: "[bsRow]" }, { kind: "directive", type: BsGridColDirective, selector: "[col]", inputs: ["col"] }, { kind: "component", type: BsInputGroupComponent, selector: "bs-input-group", inputs: ["size"] }, { kind: "directive", type: BsButtonTypeDirective, selector: "button[color],input[type=\"button\"][color],input[type=\"submit\"][color],a[color]", inputs: ["color"] }, { kind: "component", type: BsModalHostComponent, selector: "bs-modal", inputs: ["isOpen", "closeOnEscape", "scrollable"], outputs: ["isOpenChange"] }, { kind: "directive", type: BsModalDirective, selector: "[bsModal]" }, { kind: "directive", type: BsModalHeaderDirective, selector: "[bsModalHeader]" }, { kind: "directive", type: BsModalBodyDirective, selector: "[bsModalBody]" }, { kind: "directive", type: BsModalFooterDirective, selector: "[bsModalFooter]" }, { kind: "component", type: BsTableComponent, selector: "bs-table", inputs: ["isResponsive", "striped", "hover", "border", "ariaRowCount"] }, { kind: "component", type: SparkIconComponent, selector: "spark-icon", inputs: ["name"] }, { kind: "pipe", type: TranslateKeyPipe, name: "t" }, { kind: "pipe", type: ResolveTranslationPipe, name: "resolveTranslation" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
877
|
+
function refreshDispatch(attr) {
|
|
878
|
+
switch (effectiveTrigger(attr)) {
|
|
879
|
+
case "change": return isDiscreteEditor(attr) ? "immediate" : "debounced";
|
|
880
|
+
case "blur": return "blur";
|
|
881
|
+
default: return null;
|
|
882
|
+
}
|
|
223
883
|
}
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
* response *will* arrive. It is discarded by sequence number rather than prevented.
|
|
240
|
-
*/
|
|
241
|
-
class RefreshCoordinator {
|
|
242
|
-
host;
|
|
243
|
-
queue = Promise.resolve();
|
|
244
|
-
sequence = 0;
|
|
245
|
-
settled = 0;
|
|
246
|
-
pending = new Set();
|
|
247
|
-
constructor(host) {
|
|
248
|
-
this.host = host;
|
|
249
|
-
}
|
|
250
|
-
/** Whether a refresh is in flight. */
|
|
251
|
-
get isRefreshing() {
|
|
252
|
-
return this.sequence !== this.settled;
|
|
253
|
-
}
|
|
254
|
-
/**
|
|
255
|
-
* Marks `attributeName` as needing a refresh without sending one — for free-text editors, which
|
|
256
|
-
* would otherwise issue a request per keystroke. Flushed by {@link blur} or {@link flush}.
|
|
257
|
-
*/
|
|
258
|
-
markPending(attributeName) {
|
|
259
|
-
this.pending.add(attributeName);
|
|
260
|
-
}
|
|
261
|
-
/** Sends a pending refresh for `attributeName`, if one was marked. */
|
|
262
|
-
blur(attributeName) {
|
|
263
|
-
if (!this.pending.delete(attributeName))
|
|
264
|
-
return Promise.resolve();
|
|
265
|
-
return this.trigger(attributeName);
|
|
266
|
-
}
|
|
267
|
-
/**
|
|
268
|
-
* Sends every refresh still marked pending. Called before save, so a value typed and never blurred
|
|
269
|
-
* — the user tabbing straight to the save button — is still reflected before the object goes.
|
|
270
|
-
*/
|
|
271
|
-
async flush() {
|
|
272
|
-
const names = [...this.pending];
|
|
273
|
-
this.pending.clear();
|
|
274
|
-
for (const name of names)
|
|
275
|
-
await this.trigger(name);
|
|
276
|
-
await this.queue;
|
|
277
|
-
}
|
|
278
|
-
/** Sends a refresh immediately — discrete editors, where every change is a committed one. */
|
|
279
|
-
trigger(attributeName) {
|
|
280
|
-
const ticket = ++this.sequence;
|
|
281
|
-
this.host.setBusy(true);
|
|
282
|
-
this.queue = this.queue.then(async () => {
|
|
283
|
-
const sent = { ...this.host.currentValues() };
|
|
284
|
-
try {
|
|
285
|
-
const response = await this.host.send(attributeName);
|
|
286
|
-
// A newer refresh was dispatched while this one was in flight, so this response describes a
|
|
287
|
-
// form state that no longer exists. Applying it would resurrect superseded metadata.
|
|
288
|
-
if (ticket !== this.sequence)
|
|
289
|
-
return;
|
|
290
|
-
this.host.apply(response, sent);
|
|
291
|
-
}
|
|
292
|
-
finally {
|
|
293
|
-
this.settled = Math.max(this.settled, ticket);
|
|
294
|
-
if (!this.isRefreshing)
|
|
295
|
-
this.host.setBusy(false);
|
|
296
|
-
}
|
|
297
|
-
});
|
|
298
|
-
return this.queue;
|
|
299
|
-
}
|
|
884
|
+
function isDiscreteEditor(attr) {
|
|
885
|
+
if (!attr) return false;
|
|
886
|
+
if (attr.lookupReferenceType) return true;
|
|
887
|
+
switch ((attr.dataType ?? "").toLowerCase()) {
|
|
888
|
+
case "reference":
|
|
889
|
+
case "lookupreference":
|
|
890
|
+
case "boolean":
|
|
891
|
+
case "bool":
|
|
892
|
+
case "date":
|
|
893
|
+
case "datetime":
|
|
894
|
+
case "dateonly":
|
|
895
|
+
case "enum":
|
|
896
|
+
case "color": return true;
|
|
897
|
+
default: return false;
|
|
898
|
+
}
|
|
300
899
|
}
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
*/
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
continue;
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: SparkPoFormComponent, isStandalone: true, selector: "spark-po-form", inputs: { entityType: { classPropertyName: "entityType", publicName: "entityType", isSignal: true, isRequired: false, transformFunction: null }, formData: { classPropertyName: "formData", publicName: "formData", isSignal: true, isRequired: false, transformFunction: null }, validationErrors: { classPropertyName: "validationErrors", publicName: "validationErrors", isSignal: true, isRequired: false, transformFunction: null }, showButtons: { classPropertyName: "showButtons", publicName: "showButtons", isSignal: true, isRequired: false, transformFunction: null }, isSaving: { classPropertyName: "isSaving", publicName: "isSaving", isSignal: true, isRequired: false, transformFunction: null }, parentId: { classPropertyName: "parentId", publicName: "parentId", isSignal: true, isRequired: false, transformFunction: null }, parentType: { classPropertyName: "parentType", publicName: "parentType", isSignal: true, isRequired: false, transformFunction: null }, objectTypeId: { classPropertyName: "objectTypeId", publicName: "objectTypeId", isSignal: true, isRequired: false, transformFunction: null }, objectId: { classPropertyName: "objectId", publicName: "objectId", isSignal: true, isRequired: false, transformFunction: null }, triggerPathPrefix: { classPropertyName: "triggerPathPrefix", publicName: "triggerPathPrefix", isSignal: true, isRequired: false, transformFunction: null }, refreshOverlay: { classPropertyName: "refreshOverlay", publicName: "refreshOverlay", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { formData: "formDataChange", save: "save", cancel: "cancel", nestedTriggerRequested: "nestedTriggerRequested", nestedTriggerBlurred: "nestedTriggerBlurred", refreshOverlay: "refreshOverlayChange" }, ngImport: i0, template: "<bs-form>\n @if (entityType()) {\n <bs-grid>\n <bs-tab-control>\n @for (tab of resolvedTabs(); track tab.id) {\n <bs-tab-page>\n <ng-template bsTabPageHeader>{{ tab.label | resolveTranslation:tab.name }}</ng-template>\n <ng-container *ngTemplateOutlet=\"tabContent; context: { $implicit: tab }\"></ng-container>\n </bs-tab-page>\n }\n </bs-tab-control>\n\n <ng-template #tabContent let-tab>\n @if (tab.id === '__default__') {\n @if (ungroupedAttributes().length > 0) {\n <bs-card class=\"d-block m-3\">\n <div class=\"p-3\">\n @for (attr of ungroupedAttributes(); track attr.id) {\n <ng-container *ngTemplateOutlet=\"attrField; context: { $implicit: attr }\"></ng-container>\n }\n </div>\n </bs-card>\n }\n }\n @for (group of groupsForTab(tab); track group.id) {\n @if (attrsForGroup(group); as groupAttrs) {\n @if (groupAttrs.length > 0) {\n <bs-card class=\"d-block m-3\">\n @if (group.label) {\n <bs-card-header>{{ group.label | resolveTranslation:group.name }}</bs-card-header>\n }\n <div class=\"p-3\">\n @for (attr of groupAttrs; track attr.id) {\n <ng-container *ngTemplateOutlet=\"attrField; context: { $implicit: attr }\"></ng-container>\n }\n </div>\n </bs-card>\n }\n }\n }\n </ng-template>\n\n <ng-template #attrField let-attr>\n <div bsRow class=\"mb-3\">\n <label [md]=\"4\" bsColFormLabel [for]=\"attr.name\">\n {{ attr.label | resolveTranslation:attr.name }}\n @if (attr.isRequired) {\n <span class=\"text-danger\">*</span>\n }\n <spark-attribute-description [description]=\"attr.description\" />\n </label>\n <div [md]=\"8\">\n <!-- A lookup wins over the raw data type. `[LookupReference]` does not change dataType \u2014\n only `[Reference]` does \u2014 so a lookup-backed bool still reports 'boolean' here. Tested\n first, this branch swallowed it into a two-state checkbox and the select below was\n unreachable, which made a declared lookup silently do nothing. -->\n @if (attr.dataType === 'boolean' && !attr.lookupReferenceType) {\n <bs-checkbox\n [ngModel]=\"formData()[attr.name]\"\n (ngModelChange)=\"formData()[attr.name] = $event; onFieldChange(attr)\">\n </bs-checkbox>\n } @else if (attr.lookupReferenceType) {\n @if ((attr | lookupDisplayType:lookupReferenceOptions()) === ELookupDisplayType.Modal) {\n <spark-lookup-picker\n [value]=\"formData()[attr.name]\"\n [options]=\"getLookupOptions(attr)\"\n [inputId]=\"attr.name\"\n [title]=\"attr.label | resolveTranslation:attr.name\"\n [isInvalid]=\"hasError(attr.name)\"\n (valueChange)=\"onLookupValueChange(attr, $event)\">\n </spark-lookup-picker>\n } @else {\n <bs-select\n class=\"w-100\"\n [ngModel]=\"formData()[attr.name]\"\n (ngModelChange)=\"formData()[attr.name] = $event; onFieldChange(attr)\"\n [id]=\"attr.name\"\n [class.is-invalid]=\"hasError(attr.name)\">\n <option [ngValue]=\"null\">{{ 'common.selectPlaceholder' | t }}</option>\n @for (option of (attr | lookupOptions:lookupReferenceOptions()); track option.key) {\n <option [ngValue]=\"option.key\">\n {{ option.values | resolveTranslation:option.key }}\n </option>\n }\n </bs-select>\n }\n } @else if (attr.dataType === 'Reference' && attr.isArray) {\n <bs-tree-select\n mode=\"multiple\"\n variant=\"textbox\"\n [showClear]=\"true\"\n [placeholder]=\"'common.search' | t\"\n [provider]=\"getReferenceProvider(attr)\"\n [ngModel]=\"referenceTreeValues()[attr.name] || []\"\n (ngModelChange)=\"onReferenceTreeChange(attr, $event)\"\n [ngModelOptions]=\"{ standalone: true }\">\n </bs-tree-select>\n } @else if (attr.dataType === 'Reference') {\n <spark-reference-picker\n [value]=\"formData()[attr.name]\"\n [options]=\"referenceOptions()[attr.name] || []\"\n [referenceType]=\"attr.referenceType\"\n [inputId]=\"attr.name\"\n [title]=\"attr.label | resolveTranslation:attr.name\"\n [isInvalid]=\"hasError(attr.name)\"\n (valueChange)=\"onReferenceValueChange(attr, $event)\">\n </spark-reference-picker>\n } @else if (attr.dataType === 'AsDetail' && attr.isArray && attr.editMode === 'inline') {\n <!-- One source of truth for an inline cell, reused by the row and by the drag\n preview. The preview is a live Angular view (not a cloneNode), so its\n <bs-select> binds to row[col.name] and shows the value while dragging. -->\n <ng-template #inlineDetailCell let-row=\"row\" let-col=\"col\" let-attr=\"attr\" let-rowIndex=\"rowIndex\">\n <td>\n <!-- A row the caller may not edit renders through the same read-only span as a\n read-only column: still fully readable, just not editable. Hiding it would\n hide the data, and the save path would silently restore any edit anyway. -->\n @if (col.isReadOnly || !(attr | canEditDetailRow:asDetailPermissions())) {\n <span class=\"text-muted\">{{ row | asDetailCellValue:attr:col:asDetailReferenceOptions() }}</span>\n } @else if (getAsDetailCellEditRenderer(col); as editRenderer) {\n <ng-container *ngComponentOutlet=\"editRenderer; inputs: getAsDetailCellEditRendererInputs(editRenderer, row, col)\"></ng-container>\n } @else if (col.dataType === 'AsDetail') {\n <!-- Nested AsDetail can't flatten into a row: escalate to the row modal,\n where the recursive spark-po-form renders the nested structure. -->\n <div class=\"d-flex align-items-center gap-1\">\n <span class=\"text-truncate flex-grow-1\">{{ row | asDetailCellValue:attr:col:asDetailReferenceOptions() }}</span>\n <button type=\"button\" class=\"btn btn-sm btn-outline-secondary\" (click)=\"editArrayItem(attr, rowIndex)\">\n <spark-icon name=\"pencil\" />\n </button>\n </div>\n } @else if (col.dataType === 'boolean' && !col.lookupReferenceType) {\n <!-- Same precedence as the top-level chain above: a lookup-backed column must\n reach its select rather than being swallowed by the checkbox. -->\n <bs-checkbox\n [(ngModel)]=\"row[col.name]\"\n (ngModelChange)=\"onInlineCellChange(attr, rowIndex, col)\">\n </bs-checkbox>\n } @else if (col.dataType === 'Reference' && col.query) {\n @if (col.referenceDisplayType === EReferenceDisplayType.Modal) {\n <spark-reference-picker\n [value]=\"row[col.name]\"\n [options]=\"(attr | inlineRefOptions:col:asDetailReferenceOptions())\"\n [referenceType]=\"col.referenceType\"\n [title]=\"col.label | resolveTranslation:col.name\"\n [isInvalid]=\"hasInlineError(attr, rowIndex, col)\"\n (valueChange)=\"row[col.name] = $event; onInlineCellChange(attr, rowIndex, col)\">\n </spark-reference-picker>\n } @else {\n <bs-select\n class=\"w-100\"\n [(ngModel)]=\"row[col.name]\"\n (ngModelChange)=\"onInlineCellChange(attr, rowIndex, col)\"\n [class.is-invalid]=\"hasInlineError(attr, rowIndex, col)\">\n <option [ngValue]=\"null\">{{ 'common.selectPlaceholder' | t }}</option>\n @for (option of (attr | inlineRefOptions:col:asDetailReferenceOptions()); track option.id) {\n <option [ngValue]=\"option.id\">\n {{ option.breadcrumb || option.id }}\n </option>\n }\n </bs-select>\n }\n } @else if (col.lookupReferenceType) {\n @if ((col | lookupDisplayType:lookupReferenceOptions()) === ELookupDisplayType.Modal) {\n <spark-lookup-picker\n [value]=\"row[col.name]\"\n [options]=\"getLookupOptions(col)\"\n [title]=\"col.label | resolveTranslation:col.name\"\n [isInvalid]=\"hasInlineError(attr, rowIndex, col)\"\n (valueChange)=\"row[col.name] = $event; onInlineCellChange(attr, rowIndex, col)\">\n </spark-lookup-picker>\n } @else {\n <bs-select\n class=\"w-100\"\n [(ngModel)]=\"row[col.name]\"\n (ngModelChange)=\"onInlineCellChange(attr, rowIndex, col)\"\n [class.is-invalid]=\"hasInlineError(attr, rowIndex, col)\">\n <option [ngValue]=\"null\">{{ 'common.selectPlaceholder' | t }}</option>\n @for (option of getLookupOptions(col); track option.key) {\n <option [ngValue]=\"option.key\">\n {{ option.values | resolveTranslation:option.key }}\n </option>\n }\n </bs-select>\n }\n } @else if (col.dataType === 'MultiLineString') {\n <textarea\n [(ngModel)]=\"row[col.name]\"\n [required]=\"col.isRequired\"\n rows=\"3\"\n [class.is-invalid]=\"hasInlineError(attr, rowIndex, col)\"\n (ngModelChange)=\"onInlineCellChange(attr, rowIndex, col)\"\n (blur)=\"onInlineCellBlur(attr, rowIndex, col)\"></textarea>\n } @else {\n <input\n [type]=\"col.dataType | inputType\"\n [(ngModel)]=\"row[col.name]\"\n [required]=\"col.isRequired\"\n [step]=\"col.dataType === 'decimal' ? '0.01' : '1'\"\n [class.is-invalid]=\"hasInlineError(attr, rowIndex, col)\"\n (ngModelChange)=\"onInlineCellChange(attr, rowIndex, col)\"\n (blur)=\"onInlineCellBlur(attr, rowIndex, col)\">\n }\n @if (inlineErrorMessage(attr, rowIndex, col); as errorMsg) {\n <div class=\"invalid-feedback d-block\">{{ errorMsg }}</div>\n }\n </td>\n </ng-template>\n <bs-table [isResponsive]=\"true\" class=\"mb-1\">\n <thead>\n <tr>\n @if (attr.isSortable) {\n <th style=\"width: 32px\"></th>\n }\n @for (col of (attr | asDetailColumns:asDetailTypes()); track col.name) {\n <th>{{ col.label | resolveTranslation:col.name }}<spark-attribute-description [description]=\"col.description\" /></th>\n }\n <th style=\"width: 50px\"></th>\n </tr>\n </thead>\n <tbody class=\"align-middle\" cdkDropList [cdkDropListDisabled]=\"!attr.isSortable\" (cdkDropListDropped)=\"onAsDetailReorder(attr, $event)\">\n @for (row of formData()[attr.name] || []; track $index; let rowIndex = $index) {\n <tr cdkDrag [cdkDragDisabled]=\"!attr.isSortable\">\n @if (attr.isSortable) {\n <td class=\"text-center text-muted\" style=\"cursor: move; touch-action: none\" cdkDragHandle>\n <spark-icon name=\"grip-vertical\" />\n </td>\n }\n @for (col of (attr | asDetailColumns:asDetailTypes()); track col.name) {\n <ng-container *ngTemplateOutlet=\"inlineDetailCell; context: { row: row, col: col, attr: attr, rowIndex: rowIndex }\"></ng-container>\n }\n <td class=\"text-nowrap\">\n @if (attr | canDeleteDetailRow:asDetailPermissions()) {\n <button type=\"button\" [color]=\"colors.secondary\" (click)=\"removeArrayItem(attr, rowIndex)\">\n <spark-icon name=\"trash\" />\n </button>\n }\n </td>\n\n <!-- Floating preview = a LIVE view of the row's cells (not CDK's cloneNode),\n so <bs-select> shows its value instead of blanking. The in-grid\n placeholder still uses CDK's default clone (exact row height) and is\n hidden via .cdk-drag-placeholder { visibility:hidden } in the styles,\n so the drop gap is blank without collapsing/shifting the other rows. -->\n <ng-template cdkDragPreview>\n <table class=\"table mb-0 bg-body shadow-sm spark-drag-preview\">\n <tbody class=\"align-middle\">\n <tr>\n @if (attr.isSortable) {\n <td class=\"text-center text-muted\" style=\"width: 32px\"><spark-icon name=\"grip-vertical\" /></td>\n }\n @for (col of (attr | asDetailColumns:asDetailTypes()); track col.name) {\n <ng-container *ngTemplateOutlet=\"inlineDetailCell; context: { row: row, col: col, attr: attr, rowIndex: rowIndex }\"></ng-container>\n }\n </tr>\n </tbody>\n </table>\n </ng-template>\n </tr>\n } @empty {\n <tr>\n <td [attr.colspan]=\"(attr | asDetailColumns:asDetailTypes()).length + (attr.isSortable ? 2 : 1)\" class=\"text-center text-muted\">\n {{ 'common.noItemsFound' | t }}\n </td>\n </tr>\n }\n </tbody>\n </bs-table>\n @for (err of rowLifecycleErrorsFor(attr.name); track $index) {\n <div class=\"text-danger small mt-1\">{{ err.errorMessage | resolveTranslation }}</div>\n }\n @if (attr | canCreateDetailRow:asDetailPermissions()) {\n <button type=\"button\" [color]=\"colors.primary\" class=\"w-100 rounded-0\" (click)=\"addInlineRow(attr)\">\n <spark-icon name=\"plus\" /> {{ 'common.add' | t }}\n </button>\n }\n } @else if (attr.dataType === 'AsDetail' && attr.isArray) {\n <bs-table [isResponsive]=\"true\" class=\"mb-1\">\n <thead>\n <tr>\n @if (attr.isSortable) {\n <th style=\"width: 32px\"></th>\n }\n @for (col of (attr | asDetailColumns:asDetailTypes()); track col.name) {\n <th>{{ col.label | resolveTranslation:col.name }}<spark-attribute-description [description]=\"col.description\" /></th>\n }\n <th style=\"width: 80px\"></th>\n </tr>\n </thead>\n <tbody class=\"align-middle\" cdkDropList [cdkDropListDisabled]=\"!attr.isSortable\" (cdkDropListDropped)=\"onAsDetailReorder(attr, $event)\">\n @for (row of formData()[attr.name] || []; track $index) {\n <tr cdkDrag [cdkDragDisabled]=\"!attr.isSortable\">\n @if (attr.isSortable) {\n <td class=\"text-center text-muted\" style=\"cursor: move; touch-action: none\" cdkDragHandle>\n <spark-icon name=\"grip-vertical\" />\n </td>\n }\n @for (col of (attr | asDetailColumns:asDetailTypes()); track col.name) {\n <td>\n @if (getAsDetailCellRendererComponent(col); as cellRenderer) {\n <ng-container *ngComponentOutlet=\"cellRenderer; inputs: getAsDetailCellRendererInputs(cellRenderer, row, col)\"></ng-container>\n } @else {\n {{ row | asDetailCellValue:attr:col:asDetailReferenceOptions() }}\n }\n </td>\n }\n <td class=\"text-nowrap\">\n @if (attr | canEditDetailRow:asDetailPermissions()) {\n <button type=\"button\" class=\"btn btn-sm btn-outline-secondary me-1\" (click)=\"editArrayItem(attr, $index)\">\n <spark-icon name=\"pencil\" />\n </button>\n }\n @if (attr | canDeleteDetailRow:asDetailPermissions()) {\n <button type=\"button\" class=\"btn btn-sm btn-outline-danger\" (click)=\"removeArrayItem(attr, $index)\">\n <spark-icon name=\"trash\" />\n </button>\n }\n </td>\n </tr>\n } @empty {\n <tr>\n <td [attr.colspan]=\"(attr | asDetailColumns:asDetailTypes()).length + (attr.isSortable ? 2 : 1)\" class=\"text-center text-muted\">\n {{ 'common.noItemsFound' | t }}\n </td>\n </tr>\n }\n </tbody>\n </bs-table>\n @for (err of rowLifecycleErrorsFor(attr.name); track $index) {\n <div class=\"text-danger small mt-1\">{{ err.errorMessage | resolveTranslation }}</div>\n }\n @if (attr | canCreateDetailRow:asDetailPermissions()) {\n <button type=\"button\" [color]=\"colors.primary\" class=\"w-100 rounded-0\" (click)=\"addArrayItem(attr)\">\n <spark-icon name=\"plus\" /> {{ 'common.add' | t }}\n </button>\n }\n } @else if (attr.dataType === 'AsDetail') {\n <bs-input-group>\n <input\n type=\"text\"\n [id]=\"attr.name\"\n [value]=\"attr | asDetailDisplayValue:formData():asDetailTypes()\"\n readonly\n [class.is-invalid]=\"hasError(attr.name)\">\n <button\n type=\"button\"\n bsInputGroupBtn\n [color]=\"colors.secondary\"\n (click)=\"openAsDetailEditor(attr)\">\n <spark-icon name=\"pencil\" />\n </button>\n </bs-input-group>\n } @else if (getEditRendererComponent(attr); as editComp) {\n <ng-container *ngComponentOutlet=\"editComp; inputs: getEditRendererInputs(editComp, attr)\"></ng-container>\n } @else if (attr.dataType === 'MultiLineString') {\n <textarea\n [id]=\"attr.name\"\n [ngModel]=\"formData()[attr.name]\"\n (ngModelChange)=\"formData()[attr.name] = $event; onFieldChange(attr)\"\n (blur)=\"onFieldBlur(attr)\"\n [name]=\"attr.name\"\n [required]=\"attr.isRequired\"\n rows=\"6\"\n [class.is-invalid]=\"hasError(attr.name)\"></textarea>\n } @else {\n <input\n [type]=\"attr.dataType | inputType\"\n [id]=\"attr.name\"\n [ngModel]=\"formData()[attr.name]\"\n (ngModelChange)=\"formData()[attr.name] = $event; onFieldChange(attr)\"\n (blur)=\"onFieldBlur(attr)\"\n [name]=\"attr.name\"\n [required]=\"attr.isRequired\"\n [step]=\"attr.dataType === 'decimal' ? '0.01' : '1'\"\n [class.is-invalid]=\"hasError(attr.name)\">\n }\n @if (attr.name | errorForAttribute:validationErrors(); as errorMsg) {\n <div class=\"invalid-feedback d-block\">\n {{ errorMsg }}\n </div>\n }\n </div>\n </div>\n </ng-template>\n\n @if (showButtons()) {\n <div bsRow class=\"mt-4\">\n <div [md]=\"4\"></div>\n <div [md]=\"8\" class=\"d-flex justify-content-end gap-2\">\n <button type=\"button\" [color]=\"colors.secondary\" (click)=\"onCancel()\" [disabled]=\"isSaving()\">{{ 'common.cancel' | t }}</button>\n <button type=\"submit\" [color]=\"colors.primary\" [disabled]=\"isSaving()\" (click)=\"onSave()\">\n @if (isSaving()) {\n <bs-spinner class=\"me-1\" />\n }\n {{ 'common.save' | t }}\n </button>\n </div>\n </div>\n }\n </bs-grid>\n}\n\n<!-- Modal for editing AsDetail objects -->\n<bs-modal [isOpen]=\"showAsDetailModal()\" (isOpenChange)=\"!$event && closeAsDetailModal()\">\n <div *bsModal>\n <div bsModalHeader>\n <h5 class=\"modal-title\">{{ 'common.edit' | t }} {{ editingAsDetailAttr()?.label | resolveTranslation:editingAsDetailAttr()?.name }}</h5>\n </div>\n\n @if (editingAsDetailAttr(); as attr) {\n <div bsModalBody>\n <spark-po-form\n [entityType]=\"attr | asDetailType:asDetailTypes()\"\n [(formData)]=\"asDetailFormData\"\n [parentId]=\"parentId()\"\n [parentType]=\"parentType()\"\n [triggerPathPrefix]=\"attr.isArray ? null : attr.name\"\n (nestedTriggerRequested)=\"onEmbeddedTrigger(attr.name, $event)\"\n (nestedTriggerBlurred)=\"onEmbeddedTriggerBlur($event)\">\n </spark-po-form>\n </div>\n }\n\n <div bsModalFooter>\n <button type=\"button\" [color]=\"colors.secondary\" (click)=\"closeAsDetailModal()\">{{ 'common.cancel' | t }}</button>\n <button type=\"button\" [color]=\"colors.primary\" (click)=\"saveAsDetailObject()\">{{ 'common.save' | t }}</button>\n </div>\n </div>\n</bs-modal>\n</bs-form>\n", styles: [":host ::ng-deep .cdk-drag-placeholder{visibility:hidden}\n"], dependencies: [{ kind: "component", type: SparkPoFormComponent, selector: "spark-po-form", inputs: ["entityType", "formData", "validationErrors", "showButtons", "isSaving", "parentId", "parentType", "objectTypeId", "objectId", "triggerPathPrefix", "refreshOverlay"], outputs: ["formDataChange", "save", "cancel", "nestedTriggerRequested", "nestedTriggerBlurred", "refreshOverlayChange"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "directive", type: CdkDragPreview, selector: "ng-template[cdkDragPreview]", inputs: ["data", "matchSize"] }, { kind: "component", type: BsCardComponent, selector: "bs-card", inputs: ["color", "outline"] }, { kind: "component", type: BsCardHeaderComponent, selector: "bs-card-header", inputs: ["color", "navStyle"] }, { kind: "component", type: BsFormComponent, selector: "bs-form", inputs: ["action", "method"], outputs: ["submitted"] }, { kind: "directive", type: BsFormControlDirective, selector: "bs-form input:not(.no-form-control), bs-form textarea:not(.no-form-control)" }, { kind: "component", type: BsGridComponent, selector: "bs-grid", inputs: ["stopFullWidthAt"] }, { kind: "directive", type: BsGridRowDirective, selector: "[bsRow]" }, { kind: "directive", type: BsGridColumnDirective, selector: "[xxs],[xs],[sm],[md],[lg],[xl],[xxl]", inputs: ["xxs", "xs", "sm", "md", "lg", "xl", "xxl"] }, { kind: "directive", type: BsColFormLabelDirective, selector: "[bsColFormLabel]" }, { kind: "directive", type: BsButtonTypeDirective, selector: "button[color],input[type=\"button\"][color],input[type=\"submit\"][color],a[color]", inputs: ["color"] }, { kind: "component", type: BsInputGroupComponent, selector: "bs-input-group", inputs: ["size"] }, { kind: "component", type: BsSelectComponent, selector: "bs-select", inputs: ["identifier", "size", "multiple", "numberVisible", "disabled"] }, { kind: "directive", type: BsSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "component", type: BsTreeSelectComponent, selector: "bs-tree-select", inputs: ["provider", "mode", "variant", "cascadeSelect", "placeholder", "showClear", "panelScrollHeight", "searchDebounceMs", "disabled", "value"], outputs: ["valueChange", "opened", "closed", "cleared"] }, { kind: "component", type: BsModalHostComponent, selector: "bs-modal", inputs: ["isOpen", "closeOnEscape", "scrollable"], outputs: ["isOpenChange"] }, { kind: "directive", type: BsModalDirective, selector: "[bsModal]" }, { kind: "directive", type: BsModalHeaderDirective, selector: "[bsModalHeader]" }, { kind: "directive", type: BsModalBodyDirective, selector: "[bsModalBody]" }, { kind: "directive", type: BsModalFooterDirective, selector: "[bsModalFooter]" }, { kind: "component", type: BsTableComponent, selector: "bs-table", inputs: ["isResponsive", "striped", "hover", "border", "ariaRowCount"] }, { kind: "component", type: BsCheckboxComponent, selector: "bs-checkbox", inputs: ["type", "isToggled", "indeterminate", "name", "value", "group"], outputs: ["isToggledChange", "indeterminateChange"] }, { kind: "component", type: BsSpinnerComponent, selector: "bs-spinner", inputs: ["type", "color"] }, { kind: "component", type: BsTabControlComponent, selector: "bs-tab-control", inputs: ["border", "selectFirstTab", "tabsPosition"] }, { kind: "component", type: BsTabPageComponent, selector: "bs-tab-page", inputs: ["disabled"] }, { kind: "directive", type: BsTabPageHeaderDirective, selector: "[bsTabPageHeader]" }, { kind: "component", type: SparkIconComponent, selector: "spark-icon", inputs: ["name"] }, { kind: "component", type: SparkReferencePickerComponent, selector: "spark-reference-picker", inputs: ["value", "options", "referenceType", "isInvalid", "inputId", "title"], outputs: ["valueChange"] }, { kind: "component", type: SparkLookupPickerComponent, selector: "spark-lookup-picker", inputs: ["value", "options", "isInvalid", "inputId", "title"], outputs: ["valueChange"] }, { kind: "component", type: SparkAttributeDescriptionComponent, selector: "spark-attribute-description", inputs: ["description", "position"] }, { kind: "pipe", type: TranslateKeyPipe, name: "t" }, { kind: "pipe", type: ResolveTranslationPipe, name: "resolveTranslation" }, { kind: "pipe", type: InputTypePipe, name: "inputType" }, { kind: "pipe", type: LookupDisplayTypePipe, name: "lookupDisplayType" }, { kind: "pipe", type: LookupOptionsPipe, name: "lookupOptions" }, { kind: "pipe", type: AsDetailDisplayValuePipe, name: "asDetailDisplayValue" }, { kind: "pipe", type: AsDetailTypePipe, name: "asDetailType" }, { kind: "pipe", type: AsDetailColumnsPipe, name: "asDetailColumns" }, { kind: "pipe", type: AsDetailCellValuePipe, name: "asDetailCellValue" }, { kind: "pipe", type: CanCreateDetailRowPipe, name: "canCreateDetailRow" }, { kind: "pipe", type: CanDeleteDetailRowPipe, name: "canDeleteDetailRow" }, { kind: "pipe", type: CanEditDetailRowPipe, name: "canEditDetailRow" }, { kind: "pipe", type: InlineRefOptionsPipe, name: "inlineRefOptions" }, { kind: "pipe", type: ErrorForAttributePipe, name: "errorForAttribute" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
args: [{ selector: 'spark-po-form', imports: [CommonModule, NgTemplateOutlet, NgComponentOutlet, FormsModule, CdkDropList, CdkDrag, CdkDragHandle, CdkDragPreview, BsCardComponent, BsCardHeaderComponent, BsFormComponent, BsFormControlDirective, BsGridComponent, BsGridRowDirective, BsGridColumnDirective, BsGridColDirective, BsColFormLabelDirective, BsButtonTypeDirective, BsInputGroupComponent, BsSelectComponent, BsSelectOption, BsTreeSelectComponent, BsModalHostComponent, BsModalDirective, BsModalHeaderDirective, BsModalBodyDirective, BsModalFooterDirective, BsTableComponent, BsCheckboxComponent, BsSpinnerComponent, BsTabControlComponent, BsTabPageComponent, BsTabPageHeaderDirective, SparkIconComponent, SparkPoFormComponent, SparkReferencePickerComponent, SparkLookupPickerComponent, TranslateKeyPipe, ResolveTranslationPipe, InputTypePipe, LookupDisplayTypePipe, LookupOptionsPipe, AsDetailDisplayValuePipe, AsDetailTypePipe, AsDetailColumnsPipe, AsDetailCellValuePipe, CanCreateDetailRowPipe, CanDeleteDetailRowPipe, CanEditDetailRowPipe, InlineRefOptionsPipe, ErrorForAttributePipe, SparkAttributeDescriptionComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<bs-form>\n @if (entityType()) {\n <bs-grid>\n <bs-tab-control>\n @for (tab of resolvedTabs(); track tab.id) {\n <bs-tab-page>\n <ng-template bsTabPageHeader>{{ tab.label | resolveTranslation:tab.name }}</ng-template>\n <ng-container *ngTemplateOutlet=\"tabContent; context: { $implicit: tab }\"></ng-container>\n </bs-tab-page>\n }\n </bs-tab-control>\n\n <ng-template #tabContent let-tab>\n @if (tab.id === '__default__') {\n @if (ungroupedAttributes().length > 0) {\n <bs-card class=\"d-block m-3\">\n <div class=\"p-3\">\n @for (attr of ungroupedAttributes(); track attr.id) {\n <ng-container *ngTemplateOutlet=\"attrField; context: { $implicit: attr }\"></ng-container>\n }\n </div>\n </bs-card>\n }\n }\n @for (group of groupsForTab(tab); track group.id) {\n @if (attrsForGroup(group); as groupAttrs) {\n @if (groupAttrs.length > 0) {\n <bs-card class=\"d-block m-3\">\n @if (group.label) {\n <bs-card-header>{{ group.label | resolveTranslation:group.name }}</bs-card-header>\n }\n <div class=\"p-3\">\n @for (attr of groupAttrs; track attr.id) {\n <ng-container *ngTemplateOutlet=\"attrField; context: { $implicit: attr }\"></ng-container>\n }\n </div>\n </bs-card>\n }\n }\n }\n </ng-template>\n\n <ng-template #attrField let-attr>\n <div bsRow class=\"mb-3\">\n <label [md]=\"4\" bsColFormLabel [for]=\"attr.name\">\n {{ attr.label | resolveTranslation:attr.name }}\n @if (attr.isRequired) {\n <span class=\"text-danger\">*</span>\n }\n <spark-attribute-description [description]=\"attr.description\" />\n </label>\n <div [md]=\"8\">\n <!-- A lookup wins over the raw data type. `[LookupReference]` does not change dataType \u2014\n only `[Reference]` does \u2014 so a lookup-backed bool still reports 'boolean' here. Tested\n first, this branch swallowed it into a two-state checkbox and the select below was\n unreachable, which made a declared lookup silently do nothing. -->\n @if (attr.dataType === 'boolean' && !attr.lookupReferenceType) {\n <bs-checkbox\n [ngModel]=\"formData()[attr.name]\"\n (ngModelChange)=\"formData()[attr.name] = $event; onFieldChange(attr)\">\n </bs-checkbox>\n } @else if (attr.lookupReferenceType) {\n @if ((attr | lookupDisplayType:lookupReferenceOptions()) === ELookupDisplayType.Modal) {\n <spark-lookup-picker\n [value]=\"formData()[attr.name]\"\n [options]=\"getLookupOptions(attr)\"\n [inputId]=\"attr.name\"\n [title]=\"attr.label | resolveTranslation:attr.name\"\n [isInvalid]=\"hasError(attr.name)\"\n (valueChange)=\"onLookupValueChange(attr, $event)\">\n </spark-lookup-picker>\n } @else {\n <bs-select\n class=\"w-100\"\n [ngModel]=\"formData()[attr.name]\"\n (ngModelChange)=\"formData()[attr.name] = $event; onFieldChange(attr)\"\n [id]=\"attr.name\"\n [class.is-invalid]=\"hasError(attr.name)\">\n <option [ngValue]=\"null\">{{ 'common.selectPlaceholder' | t }}</option>\n @for (option of (attr | lookupOptions:lookupReferenceOptions()); track option.key) {\n <option [ngValue]=\"option.key\">\n {{ option.values | resolveTranslation:option.key }}\n </option>\n }\n </bs-select>\n }\n } @else if (attr.dataType === 'Reference' && attr.isArray) {\n <bs-tree-select\n mode=\"multiple\"\n variant=\"textbox\"\n [showClear]=\"true\"\n [placeholder]=\"'common.search' | t\"\n [provider]=\"getReferenceProvider(attr)\"\n [ngModel]=\"referenceTreeValues()[attr.name] || []\"\n (ngModelChange)=\"onReferenceTreeChange(attr, $event)\"\n [ngModelOptions]=\"{ standalone: true }\">\n </bs-tree-select>\n } @else if (attr.dataType === 'Reference') {\n <spark-reference-picker\n [value]=\"formData()[attr.name]\"\n [options]=\"referenceOptions()[attr.name] || []\"\n [referenceType]=\"attr.referenceType\"\n [inputId]=\"attr.name\"\n [title]=\"attr.label | resolveTranslation:attr.name\"\n [isInvalid]=\"hasError(attr.name)\"\n (valueChange)=\"onReferenceValueChange(attr, $event)\">\n </spark-reference-picker>\n } @else if (attr.dataType === 'AsDetail' && attr.isArray && attr.editMode === 'inline') {\n <!-- One source of truth for an inline cell, reused by the row and by the drag\n preview. The preview is a live Angular view (not a cloneNode), so its\n <bs-select> binds to row[col.name] and shows the value while dragging. -->\n <ng-template #inlineDetailCell let-row=\"row\" let-col=\"col\" let-attr=\"attr\" let-rowIndex=\"rowIndex\">\n <td>\n <!-- A row the caller may not edit renders through the same read-only span as a\n read-only column: still fully readable, just not editable. Hiding it would\n hide the data, and the save path would silently restore any edit anyway. -->\n @if (col.isReadOnly || !(attr | canEditDetailRow:asDetailPermissions())) {\n <span class=\"text-muted\">{{ row | asDetailCellValue:attr:col:asDetailReferenceOptions() }}</span>\n } @else if (getAsDetailCellEditRenderer(col); as editRenderer) {\n <ng-container *ngComponentOutlet=\"editRenderer; inputs: getAsDetailCellEditRendererInputs(editRenderer, row, col)\"></ng-container>\n } @else if (col.dataType === 'AsDetail') {\n <!-- Nested AsDetail can't flatten into a row: escalate to the row modal,\n where the recursive spark-po-form renders the nested structure. -->\n <div class=\"d-flex align-items-center gap-1\">\n <span class=\"text-truncate flex-grow-1\">{{ row | asDetailCellValue:attr:col:asDetailReferenceOptions() }}</span>\n <button type=\"button\" class=\"btn btn-sm btn-outline-secondary\" (click)=\"editArrayItem(attr, rowIndex)\">\n <spark-icon name=\"pencil\" />\n </button>\n </div>\n } @else if (col.dataType === 'boolean' && !col.lookupReferenceType) {\n <!-- Same precedence as the top-level chain above: a lookup-backed column must\n reach its select rather than being swallowed by the checkbox. -->\n <bs-checkbox\n [(ngModel)]=\"row[col.name]\"\n (ngModelChange)=\"onInlineCellChange(attr, rowIndex, col)\">\n </bs-checkbox>\n } @else if (col.dataType === 'Reference' && col.query) {\n @if (col.referenceDisplayType === EReferenceDisplayType.Modal) {\n <spark-reference-picker\n [value]=\"row[col.name]\"\n [options]=\"(attr | inlineRefOptions:col:asDetailReferenceOptions())\"\n [referenceType]=\"col.referenceType\"\n [title]=\"col.label | resolveTranslation:col.name\"\n [isInvalid]=\"hasInlineError(attr, rowIndex, col)\"\n (valueChange)=\"row[col.name] = $event; onInlineCellChange(attr, rowIndex, col)\">\n </spark-reference-picker>\n } @else {\n <bs-select\n class=\"w-100\"\n [(ngModel)]=\"row[col.name]\"\n (ngModelChange)=\"onInlineCellChange(attr, rowIndex, col)\"\n [class.is-invalid]=\"hasInlineError(attr, rowIndex, col)\">\n <option [ngValue]=\"null\">{{ 'common.selectPlaceholder' | t }}</option>\n @for (option of (attr | inlineRefOptions:col:asDetailReferenceOptions()); track option.id) {\n <option [ngValue]=\"option.id\">\n {{ option.breadcrumb || option.id }}\n </option>\n }\n </bs-select>\n }\n } @else if (col.lookupReferenceType) {\n @if ((col | lookupDisplayType:lookupReferenceOptions()) === ELookupDisplayType.Modal) {\n <spark-lookup-picker\n [value]=\"row[col.name]\"\n [options]=\"getLookupOptions(col)\"\n [title]=\"col.label | resolveTranslation:col.name\"\n [isInvalid]=\"hasInlineError(attr, rowIndex, col)\"\n (valueChange)=\"row[col.name] = $event; onInlineCellChange(attr, rowIndex, col)\">\n </spark-lookup-picker>\n } @else {\n <bs-select\n class=\"w-100\"\n [(ngModel)]=\"row[col.name]\"\n (ngModelChange)=\"onInlineCellChange(attr, rowIndex, col)\"\n [class.is-invalid]=\"hasInlineError(attr, rowIndex, col)\">\n <option [ngValue]=\"null\">{{ 'common.selectPlaceholder' | t }}</option>\n @for (option of getLookupOptions(col); track option.key) {\n <option [ngValue]=\"option.key\">\n {{ option.values | resolveTranslation:option.key }}\n </option>\n }\n </bs-select>\n }\n } @else if (col.dataType === 'MultiLineString') {\n <textarea\n [(ngModel)]=\"row[col.name]\"\n [required]=\"col.isRequired\"\n rows=\"3\"\n [class.is-invalid]=\"hasInlineError(attr, rowIndex, col)\"\n (ngModelChange)=\"onInlineCellChange(attr, rowIndex, col)\"\n (blur)=\"onInlineCellBlur(attr, rowIndex, col)\"></textarea>\n } @else {\n <input\n [type]=\"col.dataType | inputType\"\n [(ngModel)]=\"row[col.name]\"\n [required]=\"col.isRequired\"\n [step]=\"col.dataType === 'decimal' ? '0.01' : '1'\"\n [class.is-invalid]=\"hasInlineError(attr, rowIndex, col)\"\n (ngModelChange)=\"onInlineCellChange(attr, rowIndex, col)\"\n (blur)=\"onInlineCellBlur(attr, rowIndex, col)\">\n }\n @if (inlineErrorMessage(attr, rowIndex, col); as errorMsg) {\n <div class=\"invalid-feedback d-block\">{{ errorMsg }}</div>\n }\n </td>\n </ng-template>\n <bs-table [isResponsive]=\"true\" class=\"mb-1\">\n <thead>\n <tr>\n @if (attr.isSortable) {\n <th style=\"width: 32px\"></th>\n }\n @for (col of (attr | asDetailColumns:asDetailTypes()); track col.name) {\n <th>{{ col.label | resolveTranslation:col.name }}<spark-attribute-description [description]=\"col.description\" /></th>\n }\n <th style=\"width: 50px\"></th>\n </tr>\n </thead>\n <tbody class=\"align-middle\" cdkDropList [cdkDropListDisabled]=\"!attr.isSortable\" (cdkDropListDropped)=\"onAsDetailReorder(attr, $event)\">\n @for (row of formData()[attr.name] || []; track $index; let rowIndex = $index) {\n <tr cdkDrag [cdkDragDisabled]=\"!attr.isSortable\">\n @if (attr.isSortable) {\n <td class=\"text-center text-muted\" style=\"cursor: move; touch-action: none\" cdkDragHandle>\n <spark-icon name=\"grip-vertical\" />\n </td>\n }\n @for (col of (attr | asDetailColumns:asDetailTypes()); track col.name) {\n <ng-container *ngTemplateOutlet=\"inlineDetailCell; context: { row: row, col: col, attr: attr, rowIndex: rowIndex }\"></ng-container>\n }\n <td class=\"text-nowrap\">\n @if (attr | canDeleteDetailRow:asDetailPermissions()) {\n <button type=\"button\" [color]=\"colors.secondary\" (click)=\"removeArrayItem(attr, rowIndex)\">\n <spark-icon name=\"trash\" />\n </button>\n }\n </td>\n\n <!-- Floating preview = a LIVE view of the row's cells (not CDK's cloneNode),\n so <bs-select> shows its value instead of blanking. The in-grid\n placeholder still uses CDK's default clone (exact row height) and is\n hidden via .cdk-drag-placeholder { visibility:hidden } in the styles,\n so the drop gap is blank without collapsing/shifting the other rows. -->\n <ng-template cdkDragPreview>\n <table class=\"table mb-0 bg-body shadow-sm spark-drag-preview\">\n <tbody class=\"align-middle\">\n <tr>\n @if (attr.isSortable) {\n <td class=\"text-center text-muted\" style=\"width: 32px\"><spark-icon name=\"grip-vertical\" /></td>\n }\n @for (col of (attr | asDetailColumns:asDetailTypes()); track col.name) {\n <ng-container *ngTemplateOutlet=\"inlineDetailCell; context: { row: row, col: col, attr: attr, rowIndex: rowIndex }\"></ng-container>\n }\n </tr>\n </tbody>\n </table>\n </ng-template>\n </tr>\n } @empty {\n <tr>\n <td [attr.colspan]=\"(attr | asDetailColumns:asDetailTypes()).length + (attr.isSortable ? 2 : 1)\" class=\"text-center text-muted\">\n {{ 'common.noItemsFound' | t }}\n </td>\n </tr>\n }\n </tbody>\n </bs-table>\n @for (err of rowLifecycleErrorsFor(attr.name); track $index) {\n <div class=\"text-danger small mt-1\">{{ err.errorMessage | resolveTranslation }}</div>\n }\n @if (attr | canCreateDetailRow:asDetailPermissions()) {\n <button type=\"button\" [color]=\"colors.primary\" class=\"w-100 rounded-0\" (click)=\"addInlineRow(attr)\">\n <spark-icon name=\"plus\" /> {{ 'common.add' | t }}\n </button>\n }\n } @else if (attr.dataType === 'AsDetail' && attr.isArray) {\n <bs-table [isResponsive]=\"true\" class=\"mb-1\">\n <thead>\n <tr>\n @if (attr.isSortable) {\n <th style=\"width: 32px\"></th>\n }\n @for (col of (attr | asDetailColumns:asDetailTypes()); track col.name) {\n <th>{{ col.label | resolveTranslation:col.name }}<spark-attribute-description [description]=\"col.description\" /></th>\n }\n <th style=\"width: 80px\"></th>\n </tr>\n </thead>\n <tbody class=\"align-middle\" cdkDropList [cdkDropListDisabled]=\"!attr.isSortable\" (cdkDropListDropped)=\"onAsDetailReorder(attr, $event)\">\n @for (row of formData()[attr.name] || []; track $index) {\n <tr cdkDrag [cdkDragDisabled]=\"!attr.isSortable\">\n @if (attr.isSortable) {\n <td class=\"text-center text-muted\" style=\"cursor: move; touch-action: none\" cdkDragHandle>\n <spark-icon name=\"grip-vertical\" />\n </td>\n }\n @for (col of (attr | asDetailColumns:asDetailTypes()); track col.name) {\n <td>\n @if (getAsDetailCellRendererComponent(col); as cellRenderer) {\n <ng-container *ngComponentOutlet=\"cellRenderer; inputs: getAsDetailCellRendererInputs(cellRenderer, row, col)\"></ng-container>\n } @else {\n {{ row | asDetailCellValue:attr:col:asDetailReferenceOptions() }}\n }\n </td>\n }\n <td class=\"text-nowrap\">\n @if (attr | canEditDetailRow:asDetailPermissions()) {\n <button type=\"button\" class=\"btn btn-sm btn-outline-secondary me-1\" (click)=\"editArrayItem(attr, $index)\">\n <spark-icon name=\"pencil\" />\n </button>\n }\n @if (attr | canDeleteDetailRow:asDetailPermissions()) {\n <button type=\"button\" class=\"btn btn-sm btn-outline-danger\" (click)=\"removeArrayItem(attr, $index)\">\n <spark-icon name=\"trash\" />\n </button>\n }\n </td>\n </tr>\n } @empty {\n <tr>\n <td [attr.colspan]=\"(attr | asDetailColumns:asDetailTypes()).length + (attr.isSortable ? 2 : 1)\" class=\"text-center text-muted\">\n {{ 'common.noItemsFound' | t }}\n </td>\n </tr>\n }\n </tbody>\n </bs-table>\n @for (err of rowLifecycleErrorsFor(attr.name); track $index) {\n <div class=\"text-danger small mt-1\">{{ err.errorMessage | resolveTranslation }}</div>\n }\n @if (attr | canCreateDetailRow:asDetailPermissions()) {\n <button type=\"button\" [color]=\"colors.primary\" class=\"w-100 rounded-0\" (click)=\"addArrayItem(attr)\">\n <spark-icon name=\"plus\" /> {{ 'common.add' | t }}\n </button>\n }\n } @else if (attr.dataType === 'AsDetail') {\n <bs-input-group>\n <input\n type=\"text\"\n [id]=\"attr.name\"\n [value]=\"attr | asDetailDisplayValue:formData():asDetailTypes()\"\n readonly\n [class.is-invalid]=\"hasError(attr.name)\">\n <button\n type=\"button\"\n bsInputGroupBtn\n [color]=\"colors.secondary\"\n (click)=\"openAsDetailEditor(attr)\">\n <spark-icon name=\"pencil\" />\n </button>\n </bs-input-group>\n } @else if (getEditRendererComponent(attr); as editComp) {\n <ng-container *ngComponentOutlet=\"editComp; inputs: getEditRendererInputs(editComp, attr)\"></ng-container>\n } @else if (attr.dataType === 'MultiLineString') {\n <textarea\n [id]=\"attr.name\"\n [ngModel]=\"formData()[attr.name]\"\n (ngModelChange)=\"formData()[attr.name] = $event; onFieldChange(attr)\"\n (blur)=\"onFieldBlur(attr)\"\n [name]=\"attr.name\"\n [required]=\"attr.isRequired\"\n rows=\"6\"\n [class.is-invalid]=\"hasError(attr.name)\"></textarea>\n } @else {\n <input\n [type]=\"attr.dataType | inputType\"\n [id]=\"attr.name\"\n [ngModel]=\"formData()[attr.name]\"\n (ngModelChange)=\"formData()[attr.name] = $event; onFieldChange(attr)\"\n (blur)=\"onFieldBlur(attr)\"\n [name]=\"attr.name\"\n [required]=\"attr.isRequired\"\n [step]=\"attr.dataType === 'decimal' ? '0.01' : '1'\"\n [class.is-invalid]=\"hasError(attr.name)\">\n }\n @if (attr.name | errorForAttribute:validationErrors(); as errorMsg) {\n <div class=\"invalid-feedback d-block\">\n {{ errorMsg }}\n </div>\n }\n </div>\n </div>\n </ng-template>\n\n @if (showButtons()) {\n <div bsRow class=\"mt-4\">\n <div [md]=\"4\"></div>\n <div [md]=\"8\" class=\"d-flex justify-content-end gap-2\">\n <button type=\"button\" [color]=\"colors.secondary\" (click)=\"onCancel()\" [disabled]=\"isSaving()\">{{ 'common.cancel' | t }}</button>\n <button type=\"submit\" [color]=\"colors.primary\" [disabled]=\"isSaving()\" (click)=\"onSave()\">\n @if (isSaving()) {\n <bs-spinner class=\"me-1\" />\n }\n {{ 'common.save' | t }}\n </button>\n </div>\n </div>\n }\n </bs-grid>\n}\n\n<!-- Modal for editing AsDetail objects -->\n<bs-modal [isOpen]=\"showAsDetailModal()\" (isOpenChange)=\"!$event && closeAsDetailModal()\">\n <div *bsModal>\n <div bsModalHeader>\n <h5 class=\"modal-title\">{{ 'common.edit' | t }} {{ editingAsDetailAttr()?.label | resolveTranslation:editingAsDetailAttr()?.name }}</h5>\n </div>\n\n @if (editingAsDetailAttr(); as attr) {\n <div bsModalBody>\n <spark-po-form\n [entityType]=\"attr | asDetailType:asDetailTypes()\"\n [(formData)]=\"asDetailFormData\"\n [parentId]=\"parentId()\"\n [parentType]=\"parentType()\"\n [triggerPathPrefix]=\"attr.isArray ? null : attr.name\"\n (nestedTriggerRequested)=\"onEmbeddedTrigger(attr.name, $event)\"\n (nestedTriggerBlurred)=\"onEmbeddedTriggerBlur($event)\">\n </spark-po-form>\n </div>\n }\n\n <div bsModalFooter>\n <button type=\"button\" [color]=\"colors.secondary\" (click)=\"closeAsDetailModal()\">{{ 'common.cancel' | t }}</button>\n <button type=\"button\" [color]=\"colors.primary\" (click)=\"saveAsDetailObject()\">{{ 'common.save' | t }}</button>\n </div>\n </div>\n</bs-modal>\n</bs-form>\n", styles: [":host ::ng-deep .cdk-drag-placeholder{visibility:hidden}\n"] }]
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
900
|
+
var SparkPoFormComponent = class SparkPoFormComponent {
|
|
901
|
+
sparkService = inject(SparkService);
|
|
902
|
+
translations = inject(SparkLanguageService);
|
|
903
|
+
rendererRegistry = inject(SPARK_ATTRIBUTE_RENDERERS);
|
|
904
|
+
entityType = input(null, ...ngDevMode ? [{ debugName: "entityType" }] : /* istanbul ignore next */ []);
|
|
905
|
+
formData = model({}, ...ngDevMode ? [{ debugName: "formData" }] : /* istanbul ignore next */ []);
|
|
906
|
+
validationErrors = input([], ...ngDevMode ? [{ debugName: "validationErrors" }] : /* istanbul ignore next */ []);
|
|
907
|
+
showButtons = input(false, ...ngDevMode ? [{ debugName: "showButtons" }] : /* istanbul ignore next */ []);
|
|
908
|
+
isSaving = input(false, ...ngDevMode ? [{ debugName: "isSaving" }] : /* istanbul ignore next */ []);
|
|
909
|
+
parentId = input(void 0, ...ngDevMode ? [{ debugName: "parentId" }] : /* istanbul ignore next */ []);
|
|
910
|
+
parentType = input(void 0, ...ngDevMode ? [{ debugName: "parentType" }] : /* istanbul ignore next */ []);
|
|
911
|
+
save = output();
|
|
912
|
+
cancel = output();
|
|
913
|
+
objectTypeId = input(void 0, ...ngDevMode ? [{ debugName: "objectTypeId" }] : /* istanbul ignore next */ []);
|
|
914
|
+
objectId = input(void 0, ...ngDevMode ? [{ debugName: "objectId" }] : /* istanbul ignore next */ []);
|
|
915
|
+
triggerPathPrefix = input(null, ...ngDevMode ? [{ debugName: "triggerPathPrefix" }] : /* istanbul ignore next */ []);
|
|
916
|
+
nestedTriggerRequested = output();
|
|
917
|
+
nestedTriggerBlurred = output();
|
|
918
|
+
refreshOverlay = model({}, ...ngDevMode ? [{ debugName: "refreshOverlay" }] : /* istanbul ignore next */ []);
|
|
919
|
+
isRefreshing = signal(false, ...ngDevMode ? [{ debugName: "isRefreshing" }] : /* istanbul ignore next */ []);
|
|
920
|
+
colors = Color;
|
|
921
|
+
referenceOptions = signal({}, ...ngDevMode ? [{ debugName: "referenceOptions" }] : /* istanbul ignore next */ []);
|
|
922
|
+
referenceProviders = signal({}, ...ngDevMode ? [{ debugName: "referenceProviders" }] : /* istanbul ignore next */ []);
|
|
923
|
+
referenceNodes = signal({}, ...ngDevMode ? [{ debugName: "referenceNodes" }] : /* istanbul ignore next */ []);
|
|
924
|
+
asDetailTypes = signal({}, ...ngDevMode ? [{ debugName: "asDetailTypes" }] : /* istanbul ignore next */ []);
|
|
925
|
+
lookupReferenceOptions = signal({}, ...ngDevMode ? [{ debugName: "lookupReferenceOptions" }] : /* istanbul ignore next */ []);
|
|
926
|
+
editingAsDetailAttr = signal(null, ...ngDevMode ? [{ debugName: "editingAsDetailAttr" }] : /* istanbul ignore next */ []);
|
|
927
|
+
asDetailFormData = signal({}, ...ngDevMode ? [{ debugName: "asDetailFormData" }] : /* istanbul ignore next */ []);
|
|
928
|
+
showAsDetailModal = signal(false, ...ngDevMode ? [{ debugName: "showAsDetailModal" }] : /* istanbul ignore next */ []);
|
|
929
|
+
editingArrayIndex = signal(null, ...ngDevMode ? [{ debugName: "editingArrayIndex" }] : /* istanbul ignore next */ []);
|
|
930
|
+
asDetailPermissions = signal({}, ...ngDevMode ? [{ debugName: "asDetailPermissions" }] : /* istanbul ignore next */ []);
|
|
931
|
+
rowLifecycleErrors = signal({}, ...ngDevMode ? [{ debugName: "rowLifecycleErrors" }] : /* istanbul ignore next */ []);
|
|
932
|
+
rowLifecycleErrorsFor(attrName) {
|
|
933
|
+
return this.rowLifecycleErrors()[attrName] ?? [];
|
|
934
|
+
}
|
|
935
|
+
asDetailReferenceOptions = signal({}, ...ngDevMode ? [{ debugName: "asDetailReferenceOptions" }] : /* istanbul ignore next */ []);
|
|
936
|
+
ELookupDisplayType = ELookupDisplayType;
|
|
937
|
+
EReferenceDisplayType = EReferenceDisplayType;
|
|
938
|
+
optionSourceAttributes = computed(() => {
|
|
939
|
+
return this.entityType()?.attributes.filter((a) => hasShowedOnFlag(a.showedOn, ShowedOn.PersistentObject)).sort((a, b) => a.order - b.order) || [];
|
|
940
|
+
}, ...ngDevMode ? [{ debugName: "optionSourceAttributes" }] : /* istanbul ignore next */ []);
|
|
941
|
+
editableAttributes = computed(() => {
|
|
942
|
+
const overlay = this.refreshOverlay();
|
|
943
|
+
return this.entityType()?.attributes.map((a) => applyOverlay(a, overlay[a.name])).filter((a) => a.isVisible && !a.isReadOnly && hasShowedOnFlag(a.showedOn, ShowedOn.PersistentObject)).sort((a, b) => a.order - b.order) || [];
|
|
944
|
+
}, ...ngDevMode ? [{ debugName: "editableAttributes" }] : /* istanbul ignore next */ []);
|
|
945
|
+
static DEFAULT_TAB = {
|
|
946
|
+
id: "__default__",
|
|
947
|
+
name: "Algemeen",
|
|
948
|
+
label: {
|
|
949
|
+
nl: "Algemeen",
|
|
950
|
+
en: "General"
|
|
951
|
+
},
|
|
952
|
+
order: 0
|
|
953
|
+
};
|
|
954
|
+
ungroupedAttributes = computed(() => {
|
|
955
|
+
const attrs = this.editableAttributes();
|
|
956
|
+
const groupIds = new Set((this.entityType()?.groups || []).map((g) => g.id));
|
|
957
|
+
return attrs.filter((a) => !a.group || !groupIds.has(a.group));
|
|
958
|
+
}, ...ngDevMode ? [{ debugName: "ungroupedAttributes" }] : /* istanbul ignore next */ []);
|
|
959
|
+
resolvedTabs = computed(() => {
|
|
960
|
+
const et = this.entityType();
|
|
961
|
+
const definedTabs = et?.tabs?.length ? [...et.tabs].sort((a, b) => a.order - b.order) : [];
|
|
962
|
+
const hasUngroupedAttrs = this.ungroupedAttributes().length > 0;
|
|
963
|
+
const hasUntabbedGroups = (et?.groups || []).some((g) => !g.tab);
|
|
964
|
+
if (hasUngroupedAttrs || hasUntabbedGroups || definedTabs.length === 0) return [SparkPoFormComponent.DEFAULT_TAB, ...definedTabs];
|
|
965
|
+
return definedTabs;
|
|
966
|
+
}, ...ngDevMode ? [{ debugName: "resolvedTabs" }] : /* istanbul ignore next */ []);
|
|
967
|
+
groupsForTab(tab) {
|
|
968
|
+
const groups = this.entityType()?.groups || [];
|
|
969
|
+
if (tab.id === "__default__") return groups.filter((g) => !g.tab).sort((a, b) => a.order - b.order);
|
|
970
|
+
return groups.filter((g) => g.tab === tab.id).sort((a, b) => a.order - b.order);
|
|
971
|
+
}
|
|
972
|
+
attrsForGroup(group) {
|
|
973
|
+
return this.editableAttributes().filter((a) => a.group === group.id);
|
|
974
|
+
}
|
|
975
|
+
constructor() {
|
|
976
|
+
inject(DestroyRef).onDestroy(() => this.refreshCoordinator.dispose());
|
|
977
|
+
effect(() => {
|
|
978
|
+
const et = this.entityType();
|
|
979
|
+
this.parentId();
|
|
980
|
+
this.parentType();
|
|
981
|
+
if (et) {
|
|
982
|
+
this.loadReferenceOptions();
|
|
983
|
+
this.loadAsDetailTypes();
|
|
984
|
+
this.loadLookupReferenceOptions();
|
|
985
|
+
}
|
|
986
|
+
});
|
|
987
|
+
}
|
|
988
|
+
toRecord(entries) {
|
|
989
|
+
const result = {};
|
|
990
|
+
for (const [key, value] of entries) result[key] = value;
|
|
991
|
+
return result;
|
|
992
|
+
}
|
|
993
|
+
async loadReferenceOptions() {
|
|
994
|
+
const refAttrs = this.optionSourceAttributes().filter((a) => a.dataType === "Reference" && a.query);
|
|
995
|
+
if (refAttrs.length === 0) return;
|
|
996
|
+
const entries = await Promise.all(refAttrs.filter((a) => a.query).map(async (attr) => {
|
|
997
|
+
const result = await this.sparkService.executeQueryByName(attr.query, {
|
|
998
|
+
parentId: this.parentId(),
|
|
999
|
+
parentType: this.parentType()
|
|
1000
|
+
});
|
|
1001
|
+
return [attr.name, result.items];
|
|
1002
|
+
}));
|
|
1003
|
+
const optionsByAttr = this.toRecord(entries);
|
|
1004
|
+
this.referenceOptions.set(optionsByAttr);
|
|
1005
|
+
const providers = {};
|
|
1006
|
+
const nodesByAttr = {};
|
|
1007
|
+
for (const attr of refAttrs) {
|
|
1008
|
+
if (!attr.isArray) continue;
|
|
1009
|
+
const nodes = (optionsByAttr[attr.name] || []).filter((po) => !!po.id).map((po) => ({
|
|
1010
|
+
id: po.id,
|
|
1011
|
+
label: po.breadcrumb || po.id
|
|
1012
|
+
}));
|
|
1013
|
+
providers[attr.name] = new InMemoryTreeSelectProvider(nodes);
|
|
1014
|
+
nodesByAttr[attr.name] = this.toRecord(nodes.map((n) => [n.id, n]));
|
|
1015
|
+
}
|
|
1016
|
+
this.referenceProviders.set(providers);
|
|
1017
|
+
this.referenceNodes.set(nodesByAttr);
|
|
1018
|
+
}
|
|
1019
|
+
referenceTreeValues = computed(() => {
|
|
1020
|
+
const fd = this.formData();
|
|
1021
|
+
const nodesByAttr = this.referenceNodes();
|
|
1022
|
+
const result = {};
|
|
1023
|
+
for (const attr of this.editableAttributes()) {
|
|
1024
|
+
if (attr.dataType !== "Reference" || !attr.isArray) continue;
|
|
1025
|
+
const ids = Array.isArray(fd[attr.name]) ? fd[attr.name] : [];
|
|
1026
|
+
const nodeMap = nodesByAttr[attr.name] || {};
|
|
1027
|
+
result[attr.name] = ids.map((id) => nodeMap[id] ?? {
|
|
1028
|
+
id,
|
|
1029
|
+
label: id
|
|
1030
|
+
});
|
|
1031
|
+
}
|
|
1032
|
+
return result;
|
|
1033
|
+
}, ...ngDevMode ? [{ debugName: "referenceTreeValues" }] : /* istanbul ignore next */ []);
|
|
1034
|
+
getReferenceProvider(attr) {
|
|
1035
|
+
return this.referenceProviders()[attr.name];
|
|
1036
|
+
}
|
|
1037
|
+
onReferenceTreeChange(attr, value) {
|
|
1038
|
+
const nodes = Array.isArray(value) ? value : value ? [value] : [];
|
|
1039
|
+
const data = { ...this.formData() };
|
|
1040
|
+
data[attr.name] = nodes.map((n) => n.id);
|
|
1041
|
+
this.formData.set(data);
|
|
1042
|
+
}
|
|
1043
|
+
async loadAsDetailTypes() {
|
|
1044
|
+
const asDetailAttrs = this.optionSourceAttributes().filter((a) => a.dataType === "AsDetail" && a.asDetailType);
|
|
1045
|
+
if (asDetailAttrs.length === 0) return;
|
|
1046
|
+
const types = await this.sparkService.getEntityTypes();
|
|
1047
|
+
const newAsDetailTypes = {};
|
|
1048
|
+
const embedded = this.entityType()?.detailTypes ?? [];
|
|
1049
|
+
for (const attr of asDetailAttrs) {
|
|
1050
|
+
const asDetailType = types.find((t) => t.clrType === attr.asDetailType) ?? embedded.find((t) => t.clrType === attr.asDetailType);
|
|
1051
|
+
if (asDetailType) {
|
|
1052
|
+
newAsDetailTypes[attr.name] = asDetailType;
|
|
1053
|
+
if (attr.isArray) {
|
|
1054
|
+
const perms = await this.sparkService.getPermissions(asDetailType.id);
|
|
1055
|
+
this.asDetailPermissions.update((prev) => ({
|
|
1056
|
+
...prev,
|
|
1057
|
+
[attr.name]: perms
|
|
1058
|
+
}));
|
|
1059
|
+
const refCols = asDetailType.attributes.filter((a) => a.dataType === "Reference" && a.query);
|
|
1060
|
+
if (refCols.length > 0) {
|
|
1061
|
+
const refEntries = await Promise.all(refCols.filter((c) => c.query).map(async (col) => {
|
|
1062
|
+
const result = await this.sparkService.executeQueryByName(col.query, {
|
|
1063
|
+
parentId: this.parentId(),
|
|
1064
|
+
parentType: this.parentType()
|
|
1065
|
+
});
|
|
1066
|
+
return [col.name, result.items];
|
|
1067
|
+
}));
|
|
1068
|
+
this.asDetailReferenceOptions.update((prev) => ({
|
|
1069
|
+
...prev,
|
|
1070
|
+
[attr.name]: this.toRecord(refEntries)
|
|
1071
|
+
}));
|
|
1072
|
+
}
|
|
1073
|
+
const lookupCols = asDetailType.attributes.filter((a) => a.lookupReferenceType);
|
|
1074
|
+
for (const col of lookupCols) {
|
|
1075
|
+
const lookupName = col.lookupReferenceType;
|
|
1076
|
+
if (!this.lookupReferenceOptions()[lookupName]) {
|
|
1077
|
+
const ref = await this.sparkService.getLookupReference(lookupName);
|
|
1078
|
+
this.lookupReferenceOptions.update((prev) => ({
|
|
1079
|
+
...prev,
|
|
1080
|
+
[lookupName]: ref
|
|
1081
|
+
}));
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
}
|
|
1087
|
+
this.asDetailTypes.set(newAsDetailTypes);
|
|
1088
|
+
}
|
|
1089
|
+
async loadLookupReferenceOptions() {
|
|
1090
|
+
const lookupAttrs = this.optionSourceAttributes().filter((a) => a.lookupReferenceType);
|
|
1091
|
+
if (lookupAttrs.length === 0) return;
|
|
1092
|
+
const lookupNames = [...new Set(lookupAttrs.map((a) => a.lookupReferenceType))];
|
|
1093
|
+
const entries = await Promise.all(lookupNames.map(async (name) => {
|
|
1094
|
+
return [name, await this.sparkService.getLookupReference(name)];
|
|
1095
|
+
}));
|
|
1096
|
+
this.lookupReferenceOptions.set(this.toRecord(entries));
|
|
1097
|
+
}
|
|
1098
|
+
getLookupOptions(attr) {
|
|
1099
|
+
return (attr.lookupReferenceType ? this.lookupReferenceOptions()[attr.lookupReferenceType] : null)?.values.filter((v) => v.isActive) || [];
|
|
1100
|
+
}
|
|
1101
|
+
onReferenceValueChange(attr, id) {
|
|
1102
|
+
const data = { ...this.formData() };
|
|
1103
|
+
data[attr.name] = id;
|
|
1104
|
+
this.formData.set(data);
|
|
1105
|
+
}
|
|
1106
|
+
onLookupValueChange(attr, key) {
|
|
1107
|
+
const data = { ...this.formData() };
|
|
1108
|
+
data[attr.name] = key;
|
|
1109
|
+
this.formData.set(data);
|
|
1110
|
+
}
|
|
1111
|
+
getEditRendererComponent(attr) {
|
|
1112
|
+
if (!attr.renderer) return null;
|
|
1113
|
+
return this.rendererRegistry.find((r) => r.name === attr.renderer)?.editComponent ?? null;
|
|
1114
|
+
}
|
|
1115
|
+
getEditRendererInputs(component, attr) {
|
|
1116
|
+
return withDeclaredInputs(component, {
|
|
1117
|
+
value: this.formData()[attr.name],
|
|
1118
|
+
attribute: attr,
|
|
1119
|
+
options: attr.rendererOptions,
|
|
1120
|
+
valueChange: (newValue) => {
|
|
1121
|
+
const data = { ...this.formData() };
|
|
1122
|
+
data[attr.name] = newValue;
|
|
1123
|
+
this.formData.set(data);
|
|
1124
|
+
}
|
|
1125
|
+
});
|
|
1126
|
+
}
|
|
1127
|
+
getAsDetailCellRendererComponent(col) {
|
|
1128
|
+
if (!col.renderer) return null;
|
|
1129
|
+
return this.rendererRegistry.find((r) => r.name === col.renderer)?.columnComponent ?? null;
|
|
1130
|
+
}
|
|
1131
|
+
getRowRendererInputs(renderer, row) {
|
|
1132
|
+
return rowRendererInputs(renderer, row, this.objectId());
|
|
1133
|
+
}
|
|
1134
|
+
getAsDetailCellRendererInputs(component, row, col) {
|
|
1135
|
+
return withDeclaredInputs(component, {
|
|
1136
|
+
value: row[col.name],
|
|
1137
|
+
attribute: col,
|
|
1138
|
+
options: col.rendererOptions,
|
|
1139
|
+
item: row
|
|
1140
|
+
});
|
|
1141
|
+
}
|
|
1142
|
+
getAsDetailCellEditRenderer(col) {
|
|
1143
|
+
if (!col.renderer) return null;
|
|
1144
|
+
return this.rendererRegistry.find((r) => r.name === col.renderer)?.editComponent ?? null;
|
|
1145
|
+
}
|
|
1146
|
+
getAsDetailCellEditRendererInputs(component, row, col) {
|
|
1147
|
+
return withDeclaredInputs(component, {
|
|
1148
|
+
value: row[col.name],
|
|
1149
|
+
attribute: col,
|
|
1150
|
+
options: col.rendererOptions,
|
|
1151
|
+
item: row,
|
|
1152
|
+
valueChange: (newValue) => {
|
|
1153
|
+
row[col.name] = newValue;
|
|
1154
|
+
this.onFieldChange();
|
|
1155
|
+
}
|
|
1156
|
+
});
|
|
1157
|
+
}
|
|
1158
|
+
clientRuleFailures = computed(() => {
|
|
1159
|
+
const values = this.formData();
|
|
1160
|
+
return this.editableAttributes().flatMap((attr) => evaluateRules(attr, values[attr.name]));
|
|
1161
|
+
}, ...ngDevMode ? [{ debugName: "clientRuleFailures" }] : /* istanbul ignore next */ []);
|
|
1162
|
+
hasError(attrName) {
|
|
1163
|
+
return this.clientRuleFailures().some((f) => f.attributeName === attrName) || this.validationErrors().some((e) => e.attributeName === attrName);
|
|
1164
|
+
}
|
|
1165
|
+
inlineErrorPath(attr, rowIndex, col) {
|
|
1166
|
+
return `${attr.name}[${rowIndex}].${col.name}`;
|
|
1167
|
+
}
|
|
1168
|
+
hasInlineError(attr, rowIndex, col) {
|
|
1169
|
+
const path = this.inlineErrorPath(attr, rowIndex, col);
|
|
1170
|
+
return this.validationErrors().some((e) => e.attributeName === path);
|
|
1171
|
+
}
|
|
1172
|
+
inlineErrorMessage(attr, rowIndex, col) {
|
|
1173
|
+
const path = this.inlineErrorPath(attr, rowIndex, col);
|
|
1174
|
+
const error = this.validationErrors().find((e) => e.attributeName === path);
|
|
1175
|
+
return error ? resolveTranslation(error.errorMessage) : null;
|
|
1176
|
+
}
|
|
1177
|
+
onFieldChange(attr) {
|
|
1178
|
+
this.formData.set({ ...this.formData() });
|
|
1179
|
+
if (attr) this.noteChange(attr);
|
|
1180
|
+
}
|
|
1181
|
+
onInlineCellChange(attr, rowIndex, col) {
|
|
1182
|
+
this.onFieldChange();
|
|
1183
|
+
const dispatch = refreshDispatch(col);
|
|
1184
|
+
if (!dispatch || !this.objectTypeId()) return;
|
|
1185
|
+
const path = this.inlineErrorPath(attr, rowIndex, col);
|
|
1186
|
+
this.pendingNestedTrigger = {
|
|
1187
|
+
kind: "row",
|
|
1188
|
+
attribute: attr.name,
|
|
1189
|
+
rowIndex
|
|
1190
|
+
};
|
|
1191
|
+
this.refreshCoordinator.dispatch(path, dispatch);
|
|
1192
|
+
}
|
|
1193
|
+
pendingNestedTrigger = null;
|
|
1194
|
+
onEmbeddedTrigger(attributeName, event) {
|
|
1195
|
+
if (!this.objectTypeId()) return;
|
|
1196
|
+
this.pendingNestedTrigger = {
|
|
1197
|
+
kind: "object",
|
|
1198
|
+
attribute: attributeName
|
|
1199
|
+
};
|
|
1200
|
+
this.refreshCoordinator.dispatch(event.path, event.dispatch);
|
|
1201
|
+
}
|
|
1202
|
+
onEmbeddedTriggerBlur(path) {
|
|
1203
|
+
if (!this.objectTypeId()) return;
|
|
1204
|
+
this.refreshCoordinator.blur(path);
|
|
1205
|
+
}
|
|
1206
|
+
applyNestedResponse(nested, response) {
|
|
1207
|
+
this.pendingNestedTrigger = null;
|
|
1208
|
+
if (nested.kind === "row") {
|
|
1209
|
+
const rows = this.formData()[nested.attribute];
|
|
1210
|
+
const row = Array.isArray(rows) ? rows[nested.rowIndex] : void 0;
|
|
1211
|
+
if (row) {
|
|
1212
|
+
for (const attribute of response.attributes ?? []) row[attribute.name] = attribute.value ?? null;
|
|
1213
|
+
this.formData.set({ ...this.formData() });
|
|
1214
|
+
}
|
|
1215
|
+
} else {
|
|
1216
|
+
const next = { ...this.asDetailFormData() };
|
|
1217
|
+
for (const attribute of response.attributes ?? []) next[attribute.name] = attribute.value ?? null;
|
|
1218
|
+
this.asDetailFormData.set(next);
|
|
1219
|
+
}
|
|
1220
|
+
const overlay = overlayFromResponse(response);
|
|
1221
|
+
this.asDetailTypes.update((prev) => {
|
|
1222
|
+
const type = prev[nested.attribute];
|
|
1223
|
+
if (!type) return prev;
|
|
1224
|
+
return {
|
|
1225
|
+
...prev,
|
|
1226
|
+
[nested.attribute]: {
|
|
1227
|
+
...type,
|
|
1228
|
+
attributes: type.attributes.map((a) => applyOverlay(a, overlay[a.name]))
|
|
1229
|
+
}
|
|
1230
|
+
};
|
|
1231
|
+
});
|
|
1232
|
+
}
|
|
1233
|
+
onInlineCellBlur(attr, rowIndex, col) {
|
|
1234
|
+
if (effectiveTrigger(col) === "none" || !this.objectTypeId()) return;
|
|
1235
|
+
this.refreshCoordinator.blur(this.inlineErrorPath(attr, rowIndex, col));
|
|
1236
|
+
}
|
|
1237
|
+
onFieldBlur(attr) {
|
|
1238
|
+
if (this.triggerPathPrefix()) {
|
|
1239
|
+
if (effectiveTrigger(attr) === "none") return;
|
|
1240
|
+
this.nestedTriggerBlurred.emit(this.nestedTriggerPath(attr));
|
|
1241
|
+
return;
|
|
1242
|
+
}
|
|
1243
|
+
if (!this.canRefresh(attr)) return;
|
|
1244
|
+
this.refreshCoordinator.blur(attr.name);
|
|
1245
|
+
}
|
|
1246
|
+
noteChange(attr) {
|
|
1247
|
+
const dispatch = refreshDispatch(attr);
|
|
1248
|
+
if (this.triggerPathPrefix()) {
|
|
1249
|
+
if (!dispatch) return;
|
|
1250
|
+
this.nestedTriggerRequested.emit({
|
|
1251
|
+
path: this.nestedTriggerPath(attr),
|
|
1252
|
+
dispatch
|
|
1253
|
+
});
|
|
1254
|
+
return;
|
|
1255
|
+
}
|
|
1256
|
+
if (!dispatch || !this.canRefresh(attr)) return;
|
|
1257
|
+
this.refreshCoordinator.dispatch(attr.name, dispatch);
|
|
1258
|
+
}
|
|
1259
|
+
nestedTriggerPath(attr) {
|
|
1260
|
+
return `${this.triggerPathPrefix()}.${attr.name}`;
|
|
1261
|
+
}
|
|
1262
|
+
canRefresh(attr) {
|
|
1263
|
+
return effectiveTrigger(attr) !== "none" && !!this.objectTypeId();
|
|
1264
|
+
}
|
|
1265
|
+
refreshCoordinator = new RefreshCoordinator({
|
|
1266
|
+
send: (triggeredBy) => this.sparkService.refresh(this.objectTypeId(), this.buildRefreshPayload(), triggeredBy),
|
|
1267
|
+
currentValues: () => this.formData(),
|
|
1268
|
+
apply: (response, sent) => {
|
|
1269
|
+
const nested = this.pendingNestedTrigger;
|
|
1270
|
+
if (nested) {
|
|
1271
|
+
this.applyNestedResponse(nested, response);
|
|
1272
|
+
return;
|
|
1273
|
+
}
|
|
1274
|
+
this.refreshOverlay.set(overlayFromResponse(response));
|
|
1275
|
+
this.formData.set(mergeRefreshValues(sent, this.formData(), response));
|
|
1276
|
+
this.applyRefreshedOptions(response);
|
|
1277
|
+
},
|
|
1278
|
+
setBusy: (busy) => this.isRefreshing.set(busy)
|
|
1279
|
+
});
|
|
1280
|
+
buildRefreshPayload() {
|
|
1281
|
+
const et = this.entityType();
|
|
1282
|
+
const values = this.embeddedValues();
|
|
1283
|
+
return {
|
|
1284
|
+
id: this.objectId(),
|
|
1285
|
+
name: et?.name ?? "",
|
|
1286
|
+
objectTypeId: et?.id ?? this.objectTypeId(),
|
|
1287
|
+
attributes: (et?.attributes ?? []).map((a) => ({
|
|
1288
|
+
name: a.name,
|
|
1289
|
+
value: values[a.name] ?? null,
|
|
1290
|
+
isValueChanged: true
|
|
1291
|
+
}))
|
|
1292
|
+
};
|
|
1293
|
+
}
|
|
1294
|
+
embeddedValues() {
|
|
1295
|
+
const nested = this.pendingNestedTrigger;
|
|
1296
|
+
if (nested?.kind !== "object") return this.formData();
|
|
1297
|
+
return {
|
|
1298
|
+
...this.formData(),
|
|
1299
|
+
[nested.attribute]: this.asDetailFormData()
|
|
1300
|
+
};
|
|
1301
|
+
}
|
|
1302
|
+
applyRefreshedOptions(response) {
|
|
1303
|
+
const replaced = (response.attributes ?? []).map((a) => [a.name, a.options]).filter(([, options]) => options !== void 0 && options !== null);
|
|
1304
|
+
if (replaced.length === 0) return;
|
|
1305
|
+
const byName = new Map(this.optionSourceAttributes().map((a) => [a.name, a]));
|
|
1306
|
+
this.lookupReferenceOptions.update((prev) => {
|
|
1307
|
+
const next = { ...prev };
|
|
1308
|
+
for (const [name, options] of replaced) {
|
|
1309
|
+
const attr = byName.get(name);
|
|
1310
|
+
if (!attr?.lookupReferenceType) continue;
|
|
1311
|
+
next[attr.lookupReferenceType] = {
|
|
1312
|
+
...next[attr.lookupReferenceType] ?? {
|
|
1313
|
+
name: attr.lookupReferenceType,
|
|
1314
|
+
isTransient: true,
|
|
1315
|
+
displayType: ELookupDisplayType.Dropdown
|
|
1316
|
+
},
|
|
1317
|
+
values: (options ?? []).map((o) => ({
|
|
1318
|
+
key: o.key,
|
|
1319
|
+
values: o.label ?? { en: o.key },
|
|
1320
|
+
isActive: true
|
|
1321
|
+
}))
|
|
1322
|
+
};
|
|
1323
|
+
}
|
|
1324
|
+
return next;
|
|
1325
|
+
});
|
|
1326
|
+
this.referenceOptions.update((prev) => {
|
|
1327
|
+
const next = { ...prev };
|
|
1328
|
+
for (const [name, options] of replaced) {
|
|
1329
|
+
if (byName.get(name)?.dataType !== "Reference") continue;
|
|
1330
|
+
next[name] = (options ?? []).map((o) => ({
|
|
1331
|
+
id: o.key,
|
|
1332
|
+
breadcrumb: o.label ? resolveTranslation(o.label) : o.key,
|
|
1333
|
+
values: []
|
|
1334
|
+
}));
|
|
1335
|
+
}
|
|
1336
|
+
return next;
|
|
1337
|
+
});
|
|
1338
|
+
}
|
|
1339
|
+
async flushPendingRefresh() {
|
|
1340
|
+
await this.refreshCoordinator.flush();
|
|
1341
|
+
}
|
|
1342
|
+
async onSave() {
|
|
1343
|
+
await this.flushPendingRefresh();
|
|
1344
|
+
if (this.clientRuleFailures().length > 0) return;
|
|
1345
|
+
this.save.emit();
|
|
1346
|
+
}
|
|
1347
|
+
onCancel() {
|
|
1348
|
+
this.cancel.emit();
|
|
1349
|
+
}
|
|
1350
|
+
openAsDetailEditor(attr) {
|
|
1351
|
+
this.editingAsDetailAttr.set(attr);
|
|
1352
|
+
this.editingArrayIndex.set(null);
|
|
1353
|
+
this.asDetailFormData.set({ ...this.formData()[attr.name] || {} });
|
|
1354
|
+
this.showAsDetailModal.set(true);
|
|
1355
|
+
}
|
|
1356
|
+
saveAsDetailObject() {
|
|
1357
|
+
const attr = this.editingAsDetailAttr();
|
|
1358
|
+
if (attr) {
|
|
1359
|
+
const data = { ...this.formData() };
|
|
1360
|
+
if (attr.isArray) {
|
|
1361
|
+
const arr = [...data[attr.name] || []];
|
|
1362
|
+
const idx = this.editingArrayIndex();
|
|
1363
|
+
if (idx !== null) arr[idx] = { ...this.asDetailFormData() };
|
|
1364
|
+
else arr.push({ ...this.asDetailFormData() });
|
|
1365
|
+
data[attr.name] = arr;
|
|
1366
|
+
} else data[attr.name] = { ...this.asDetailFormData() };
|
|
1367
|
+
this.formData.set(data);
|
|
1368
|
+
}
|
|
1369
|
+
this.closeAsDetailModal();
|
|
1370
|
+
}
|
|
1371
|
+
closeAsDetailModal() {
|
|
1372
|
+
this.showAsDetailModal.set(false);
|
|
1373
|
+
this.editingAsDetailAttr.set(null);
|
|
1374
|
+
this.editingArrayIndex.set(null);
|
|
1375
|
+
this.asDetailFormData.set({});
|
|
1376
|
+
}
|
|
1377
|
+
roundTripsRowLifecycle(attr) {
|
|
1378
|
+
return this.asDetailTypes()[attr.name]?.serverSideRowLifecycle === true;
|
|
1379
|
+
}
|
|
1380
|
+
rowTypeId(attr) {
|
|
1381
|
+
return this.asDetailTypes()[attr.name]?.id;
|
|
1382
|
+
}
|
|
1383
|
+
parentTypeForWire() {
|
|
1384
|
+
return this.parentType() ?? this.entityType()?.id;
|
|
1385
|
+
}
|
|
1386
|
+
async buildNewRow(attr) {
|
|
1387
|
+
const typeId = this.rowTypeId(attr);
|
|
1388
|
+
if (!this.roundTripsRowLifecycle(attr) || !typeId) return {};
|
|
1389
|
+
this.clearRowLifecycleError(attr.name);
|
|
1390
|
+
try {
|
|
1391
|
+
const po = await this.sparkService.newObject(typeId, {
|
|
1392
|
+
asDetailAttribute: attr.name,
|
|
1393
|
+
parentType: this.parentTypeForWire(),
|
|
1394
|
+
parentId: this.objectId()
|
|
1395
|
+
});
|
|
1396
|
+
return nestedPoToDict(po);
|
|
1397
|
+
} catch (e) {
|
|
1398
|
+
this.captureRowLifecycleError(attr.name, e);
|
|
1399
|
+
return null;
|
|
1400
|
+
}
|
|
1401
|
+
}
|
|
1402
|
+
async mayRemoveRow(attr, row) {
|
|
1403
|
+
const typeId = this.rowTypeId(attr);
|
|
1404
|
+
const parentId = this.objectId();
|
|
1405
|
+
const parentType = this.parentTypeForWire();
|
|
1406
|
+
const rowKey = row?.[AS_DETAIL_ROW_KEY];
|
|
1407
|
+
if (!this.roundTripsRowLifecycle(attr) || !typeId || !parentId || !parentType || !rowKey) return true;
|
|
1408
|
+
this.clearRowLifecycleError(attr.name);
|
|
1409
|
+
try {
|
|
1410
|
+
await this.sparkService.deleteRow(typeId, {
|
|
1411
|
+
asDetailAttribute: attr.name,
|
|
1412
|
+
parentType,
|
|
1413
|
+
parentId,
|
|
1414
|
+
rowKey
|
|
1415
|
+
});
|
|
1416
|
+
return true;
|
|
1417
|
+
} catch (e) {
|
|
1418
|
+
this.captureRowLifecycleError(attr.name, e);
|
|
1419
|
+
return false;
|
|
1420
|
+
}
|
|
1421
|
+
}
|
|
1422
|
+
clearRowLifecycleError(attrName) {
|
|
1423
|
+
this.rowLifecycleErrors.update((prev) => {
|
|
1424
|
+
const next = { ...prev };
|
|
1425
|
+
delete next[attrName];
|
|
1426
|
+
return next;
|
|
1427
|
+
});
|
|
1428
|
+
}
|
|
1429
|
+
captureRowLifecycleError(attrName, e) {
|
|
1430
|
+
const error = e;
|
|
1431
|
+
const errors = error?.error?.result?.errors ?? error?.error?.errors;
|
|
1432
|
+
const resolved = error?.status === 400 && errors?.length ? errors : [{
|
|
1433
|
+
attributeName: "",
|
|
1434
|
+
errorMessage: { en: error?.error?.result?.error || error?.error?.error || error?.message || "The server refused this change." },
|
|
1435
|
+
ruleType: "error"
|
|
1436
|
+
}];
|
|
1437
|
+
this.rowLifecycleErrors.update((prev) => ({
|
|
1438
|
+
...prev,
|
|
1439
|
+
[attrName]: resolved
|
|
1440
|
+
}));
|
|
1441
|
+
}
|
|
1442
|
+
async addInlineRow(attr) {
|
|
1443
|
+
const row = await this.buildNewRow(attr);
|
|
1444
|
+
if (row === null) return;
|
|
1445
|
+
const data = { ...this.formData() };
|
|
1446
|
+
const arr = [...data[attr.name] || []];
|
|
1447
|
+
arr.push(row);
|
|
1448
|
+
data[attr.name] = arr;
|
|
1449
|
+
this.formData.set(data);
|
|
1450
|
+
}
|
|
1451
|
+
async addArrayItem(attr) {
|
|
1452
|
+
const row = await this.buildNewRow(attr);
|
|
1453
|
+
if (row === null) return;
|
|
1454
|
+
this.editingAsDetailAttr.set(attr);
|
|
1455
|
+
this.editingArrayIndex.set(null);
|
|
1456
|
+
this.asDetailFormData.set(row);
|
|
1457
|
+
this.showAsDetailModal.set(true);
|
|
1458
|
+
}
|
|
1459
|
+
editArrayItem(attr, index) {
|
|
1460
|
+
this.editingAsDetailAttr.set(attr);
|
|
1461
|
+
this.editingArrayIndex.set(index);
|
|
1462
|
+
const arr = this.formData()[attr.name] || [];
|
|
1463
|
+
this.asDetailFormData.set({ ...arr[index] || {} });
|
|
1464
|
+
this.showAsDetailModal.set(true);
|
|
1465
|
+
}
|
|
1466
|
+
async removeArrayItem(attr, index) {
|
|
1467
|
+
const current = this.formData()[attr.name] || [];
|
|
1468
|
+
if (!await this.mayRemoveRow(attr, current[index])) return;
|
|
1469
|
+
const data = { ...this.formData() };
|
|
1470
|
+
const arr = [...current];
|
|
1471
|
+
arr.splice(index, 1);
|
|
1472
|
+
data[attr.name] = arr;
|
|
1473
|
+
this.formData.set(data);
|
|
1474
|
+
}
|
|
1475
|
+
onAsDetailReorder(attr, event) {
|
|
1476
|
+
if (event.previousIndex === event.currentIndex) return;
|
|
1477
|
+
const data = { ...this.formData() };
|
|
1478
|
+
const arr = [...data[attr.name] ?? []];
|
|
1479
|
+
moveItemInArray(arr, event.previousIndex, event.currentIndex);
|
|
1480
|
+
data[attr.name] = arr;
|
|
1481
|
+
this.formData.set(data);
|
|
1482
|
+
}
|
|
1483
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
1484
|
+
minVersion: "12.0.0",
|
|
1485
|
+
version: "22.2.0",
|
|
1486
|
+
ngImport: i0,
|
|
1487
|
+
type: SparkPoFormComponent,
|
|
1488
|
+
deps: [],
|
|
1489
|
+
target: i0.ɵɵFactoryTarget.Component
|
|
1490
|
+
});
|
|
1491
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({
|
|
1492
|
+
minVersion: "17.0.0",
|
|
1493
|
+
version: "22.2.0",
|
|
1494
|
+
type: SparkPoFormComponent,
|
|
1495
|
+
isStandalone: true,
|
|
1496
|
+
selector: "spark-po-form",
|
|
1497
|
+
inputs: {
|
|
1498
|
+
entityType: {
|
|
1499
|
+
classPropertyName: "entityType",
|
|
1500
|
+
publicName: "entityType",
|
|
1501
|
+
isSignal: true,
|
|
1502
|
+
isRequired: false,
|
|
1503
|
+
transformFunction: null
|
|
1504
|
+
},
|
|
1505
|
+
formData: {
|
|
1506
|
+
classPropertyName: "formData",
|
|
1507
|
+
publicName: "formData",
|
|
1508
|
+
isSignal: true,
|
|
1509
|
+
isRequired: false,
|
|
1510
|
+
transformFunction: null
|
|
1511
|
+
},
|
|
1512
|
+
validationErrors: {
|
|
1513
|
+
classPropertyName: "validationErrors",
|
|
1514
|
+
publicName: "validationErrors",
|
|
1515
|
+
isSignal: true,
|
|
1516
|
+
isRequired: false,
|
|
1517
|
+
transformFunction: null
|
|
1518
|
+
},
|
|
1519
|
+
showButtons: {
|
|
1520
|
+
classPropertyName: "showButtons",
|
|
1521
|
+
publicName: "showButtons",
|
|
1522
|
+
isSignal: true,
|
|
1523
|
+
isRequired: false,
|
|
1524
|
+
transformFunction: null
|
|
1525
|
+
},
|
|
1526
|
+
isSaving: {
|
|
1527
|
+
classPropertyName: "isSaving",
|
|
1528
|
+
publicName: "isSaving",
|
|
1529
|
+
isSignal: true,
|
|
1530
|
+
isRequired: false,
|
|
1531
|
+
transformFunction: null
|
|
1532
|
+
},
|
|
1533
|
+
parentId: {
|
|
1534
|
+
classPropertyName: "parentId",
|
|
1535
|
+
publicName: "parentId",
|
|
1536
|
+
isSignal: true,
|
|
1537
|
+
isRequired: false,
|
|
1538
|
+
transformFunction: null
|
|
1539
|
+
},
|
|
1540
|
+
parentType: {
|
|
1541
|
+
classPropertyName: "parentType",
|
|
1542
|
+
publicName: "parentType",
|
|
1543
|
+
isSignal: true,
|
|
1544
|
+
isRequired: false,
|
|
1545
|
+
transformFunction: null
|
|
1546
|
+
},
|
|
1547
|
+
objectTypeId: {
|
|
1548
|
+
classPropertyName: "objectTypeId",
|
|
1549
|
+
publicName: "objectTypeId",
|
|
1550
|
+
isSignal: true,
|
|
1551
|
+
isRequired: false,
|
|
1552
|
+
transformFunction: null
|
|
1553
|
+
},
|
|
1554
|
+
objectId: {
|
|
1555
|
+
classPropertyName: "objectId",
|
|
1556
|
+
publicName: "objectId",
|
|
1557
|
+
isSignal: true,
|
|
1558
|
+
isRequired: false,
|
|
1559
|
+
transformFunction: null
|
|
1560
|
+
},
|
|
1561
|
+
triggerPathPrefix: {
|
|
1562
|
+
classPropertyName: "triggerPathPrefix",
|
|
1563
|
+
publicName: "triggerPathPrefix",
|
|
1564
|
+
isSignal: true,
|
|
1565
|
+
isRequired: false,
|
|
1566
|
+
transformFunction: null
|
|
1567
|
+
},
|
|
1568
|
+
refreshOverlay: {
|
|
1569
|
+
classPropertyName: "refreshOverlay",
|
|
1570
|
+
publicName: "refreshOverlay",
|
|
1571
|
+
isSignal: true,
|
|
1572
|
+
isRequired: false,
|
|
1573
|
+
transformFunction: null
|
|
1574
|
+
}
|
|
1575
|
+
},
|
|
1576
|
+
outputs: {
|
|
1577
|
+
formData: "formDataChange",
|
|
1578
|
+
save: "save",
|
|
1579
|
+
cancel: "cancel",
|
|
1580
|
+
nestedTriggerRequested: "nestedTriggerRequested",
|
|
1581
|
+
nestedTriggerBlurred: "nestedTriggerBlurred",
|
|
1582
|
+
refreshOverlay: "refreshOverlayChange"
|
|
1583
|
+
},
|
|
1584
|
+
ngImport: i0,
|
|
1585
|
+
template: "<bs-form>\n @if (entityType()) {\n <bs-grid>\n <bs-tab-control>\n @for (tab of resolvedTabs(); track tab.id) {\n <bs-tab-page>\n <ng-template bsTabPageHeader>{{ tab.label | resolveTranslation:tab.name }}</ng-template>\n <ng-container *ngTemplateOutlet=\"tabContent; context: { $implicit: tab }\"></ng-container>\n </bs-tab-page>\n }\n </bs-tab-control>\n\n <ng-template #tabContent let-tab>\n @if (tab.id === '__default__') {\n @if (ungroupedAttributes().length > 0) {\n <bs-card class=\"d-block m-3\">\n <div class=\"p-3\">\n @for (attr of ungroupedAttributes(); track attr.id) {\n <ng-container *ngTemplateOutlet=\"attrField; context: { $implicit: attr }\"></ng-container>\n }\n </div>\n </bs-card>\n }\n }\n @for (group of groupsForTab(tab); track group.id) {\n @if (attrsForGroup(group); as groupAttrs) {\n @if (groupAttrs.length > 0) {\n <bs-card class=\"d-block m-3\">\n @if (group.label) {\n <bs-card-header>{{ group.label | resolveTranslation:group.name }}</bs-card-header>\n }\n <div class=\"p-3\">\n @for (attr of groupAttrs; track attr.id) {\n <ng-container *ngTemplateOutlet=\"attrField; context: { $implicit: attr }\"></ng-container>\n }\n </div>\n </bs-card>\n }\n }\n }\n </ng-template>\n\n <ng-template #attrField let-attr>\n <div bsRow class=\"mb-3\">\n <label [md]=\"4\" bsColFormLabel [for]=\"attr.name\">\n {{ attr.label | resolveTranslation:attr.name }}\n @if (attr.isRequired) {\n <span class=\"text-danger\">*</span>\n }\n <spark-attribute-description [description]=\"attr.description\" />\n </label>\n <div [md]=\"8\">\n <!-- A lookup wins over the raw data type. `[LookupReference]` does not change dataType —\n only `[Reference]` does — so a lookup-backed bool still reports 'boolean' here. Tested\n first, this branch swallowed it into a two-state checkbox and the select below was\n unreachable, which made a declared lookup silently do nothing. -->\n @if (attr.dataType === 'boolean' && !attr.lookupReferenceType) {\n <bs-checkbox\n [ngModel]=\"formData()[attr.name]\"\n (ngModelChange)=\"formData()[attr.name] = $event; onFieldChange(attr)\">\n </bs-checkbox>\n } @else if (attr.lookupReferenceType) {\n @if ((attr | lookupDisplayType:lookupReferenceOptions()) === ELookupDisplayType.Modal) {\n <spark-lookup-picker\n [value]=\"formData()[attr.name]\"\n [options]=\"getLookupOptions(attr)\"\n [inputId]=\"attr.name\"\n [title]=\"attr.label | resolveTranslation:attr.name\"\n [isInvalid]=\"hasError(attr.name)\"\n (valueChange)=\"onLookupValueChange(attr, $event)\">\n </spark-lookup-picker>\n } @else {\n <bs-select\n class=\"w-100\"\n [ngModel]=\"formData()[attr.name]\"\n (ngModelChange)=\"formData()[attr.name] = $event; onFieldChange(attr)\"\n [id]=\"attr.name\"\n [class.is-invalid]=\"hasError(attr.name)\">\n <option [ngValue]=\"null\">{{ 'common.selectPlaceholder' | t }}</option>\n @for (option of (attr | lookupOptions:lookupReferenceOptions()); track option.key) {\n <option [ngValue]=\"option.key\">\n {{ option.values | resolveTranslation:option.key }}\n </option>\n }\n </bs-select>\n }\n } @else if (attr.dataType === 'Reference' && attr.isArray) {\n <bs-tree-select\n mode=\"multiple\"\n variant=\"textbox\"\n [showClear]=\"true\"\n [placeholder]=\"'common.search' | t\"\n [provider]=\"getReferenceProvider(attr)\"\n [ngModel]=\"referenceTreeValues()[attr.name] || []\"\n (ngModelChange)=\"onReferenceTreeChange(attr, $event)\"\n [ngModelOptions]=\"{ standalone: true }\">\n </bs-tree-select>\n } @else if (attr.dataType === 'Reference') {\n <spark-reference-picker\n [value]=\"formData()[attr.name]\"\n [options]=\"referenceOptions()[attr.name] || []\"\n [referenceType]=\"attr.referenceType\"\n [inputId]=\"attr.name\"\n [title]=\"attr.label | resolveTranslation:attr.name\"\n [isInvalid]=\"hasError(attr.name)\"\n (valueChange)=\"onReferenceValueChange(attr, $event)\">\n </spark-reference-picker>\n } @else if (attr.dataType === 'AsDetail' && attr.isArray && attr.editMode === 'inline') {\n <!-- One source of truth for an inline cell, reused by the row and by the drag\n preview. The preview is a live Angular view (not a cloneNode), so its\n <bs-select> binds to row[col.name] and shows the value while dragging. -->\n <ng-template #inlineDetailCell let-row=\"row\" let-col=\"col\" let-attr=\"attr\" let-rowIndex=\"rowIndex\" let-rowRenderer=\"rowRenderer\">\n <td>\n <!-- A row the caller may not edit renders through the same read-only span as a\n read-only column: still fully readable, just not editable. Hiding it would\n hide the data, and the save path would silently restore any edit anyway. -->\n @if (col.isReadOnly || !(attr | canEditDetailRow:asDetailPermissions())) {\n <span class=\"text-muted\">{{ row | asDetailCellValue:attr:col:asDetailReferenceOptions() }}</span>\n } @else if (getAsDetailCellEditRenderer(col); as editRenderer) {\n <ng-container *ngComponentOutlet=\"editRenderer; inputs: getAsDetailCellEditRendererInputs(editRenderer, row, col)\"></ng-container>\n } @else if (col.dataType === 'AsDetail') {\n <!-- Nested AsDetail can't flatten into a row: escalate to the row modal,\n where the recursive spark-po-form renders the nested structure. -->\n <div class=\"d-flex align-items-center gap-1\">\n <span class=\"text-truncate flex-grow-1\">{{ row | asDetailCellValue:attr:col:asDetailReferenceOptions() }}</span>\n <button type=\"button\" class=\"btn btn-sm btn-outline-secondary\" (click)=\"editArrayItem(attr, rowIndex)\">\n <spark-icon name=\"pencil\" />\n </button>\n </div>\n } @else if (col.dataType === 'boolean' && !col.lookupReferenceType) {\n <!-- Same precedence as the top-level chain above: a lookup-backed column must\n reach its select rather than being swallowed by the checkbox. -->\n <bs-checkbox\n [(ngModel)]=\"row[col.name]\"\n (ngModelChange)=\"onInlineCellChange(attr, rowIndex, col)\">\n </bs-checkbox>\n } @else if (col.dataType === 'Reference' && col.query) {\n @if (col.referenceDisplayType === EReferenceDisplayType.Modal) {\n <spark-reference-picker\n [value]=\"row[col.name]\"\n [options]=\"(attr | inlineRefOptions:col:asDetailReferenceOptions())\"\n [referenceType]=\"col.referenceType\"\n [title]=\"col.label | resolveTranslation:col.name\"\n [isInvalid]=\"hasInlineError(attr, rowIndex, col)\"\n (valueChange)=\"row[col.name] = $event; onInlineCellChange(attr, rowIndex, col)\">\n </spark-reference-picker>\n } @else {\n <bs-select\n class=\"w-100\"\n [(ngModel)]=\"row[col.name]\"\n (ngModelChange)=\"onInlineCellChange(attr, rowIndex, col)\"\n [class.is-invalid]=\"hasInlineError(attr, rowIndex, col)\">\n <option [ngValue]=\"null\">{{ 'common.selectPlaceholder' | t }}</option>\n @for (option of (attr | inlineRefOptions:col:asDetailReferenceOptions()); track option.id) {\n <option [ngValue]=\"option.id\">\n {{ option.breadcrumb || option.id }}\n </option>\n }\n </bs-select>\n }\n } @else if (col.lookupReferenceType) {\n @if ((col | lookupDisplayType:lookupReferenceOptions()) === ELookupDisplayType.Modal) {\n <spark-lookup-picker\n [value]=\"row[col.name]\"\n [options]=\"getLookupOptions(col)\"\n [title]=\"col.label | resolveTranslation:col.name\"\n [isInvalid]=\"hasInlineError(attr, rowIndex, col)\"\n (valueChange)=\"row[col.name] = $event; onInlineCellChange(attr, rowIndex, col)\">\n </spark-lookup-picker>\n } @else {\n <bs-select\n class=\"w-100\"\n [(ngModel)]=\"row[col.name]\"\n (ngModelChange)=\"onInlineCellChange(attr, rowIndex, col)\"\n [class.is-invalid]=\"hasInlineError(attr, rowIndex, col)\">\n <option [ngValue]=\"null\">{{ 'common.selectPlaceholder' | t }}</option>\n @for (option of getLookupOptions(col); track option.key) {\n <option [ngValue]=\"option.key\">\n {{ option.values | resolveTranslation:option.key }}\n </option>\n }\n </bs-select>\n }\n } @else if (col.dataType === 'MultiLineString') {\n <textarea\n [(ngModel)]=\"row[col.name]\"\n [required]=\"col.isRequired\"\n rows=\"3\"\n [class.is-invalid]=\"hasInlineError(attr, rowIndex, col)\"\n (ngModelChange)=\"onInlineCellChange(attr, rowIndex, col)\"\n (blur)=\"onInlineCellBlur(attr, rowIndex, col)\"></textarea>\n } @else {\n <input\n [type]=\"col.dataType | inputType\"\n [(ngModel)]=\"row[col.name]\"\n [required]=\"col.isRequired\"\n [step]=\"col.dataType === 'decimal' ? '0.01' : '1'\"\n [class.is-invalid]=\"hasInlineError(attr, rowIndex, col)\"\n (ngModelChange)=\"onInlineCellChange(attr, rowIndex, col)\"\n (blur)=\"onInlineCellBlur(attr, rowIndex, col)\">\n }\n @if (inlineErrorMessage(attr, rowIndex, col); as errorMsg) {\n <div class=\"invalid-feedback d-block\">{{ errorMsg }}</div>\n }\n <!-- Passed for the first cell only: a row renderer (rowComponent) draws its\n attributes once per row, under that cell, instead of as columns. -->\n @if (rowRenderer) {\n <div class=\"spark-row-renderer\">\n <ng-container *ngComponentOutlet=\"rowRenderer.component; inputs: getRowRendererInputs(rowRenderer, row)\"></ng-container>\n </div>\n }\n </td>\n </ng-template>\n <bs-table [isResponsive]=\"true\" class=\"mb-1\">\n <thead>\n <tr>\n @if (attr.isSortable) {\n <th style=\"width: 32px\"></th>\n }\n @for (col of (attr | asDetailColumns:asDetailTypes():rendererRegistry); track col.name) {\n <th>{{ col.label | resolveTranslation:col.name }}<spark-attribute-description [description]=\"col.description\" /></th>\n }\n <th style=\"width: 50px\"></th>\n </tr>\n </thead>\n @let inlineRowRenderer = (attr | asDetailRowRenderer:asDetailTypes():rendererRegistry);\n <tbody class=\"align-middle\" cdkDropList [cdkDropListDisabled]=\"!attr.isSortable\" (cdkDropListDropped)=\"onAsDetailReorder(attr, $event)\">\n @for (row of formData()[attr.name] || []; track $index; let rowIndex = $index) {\n <tr cdkDrag [cdkDragDisabled]=\"!attr.isSortable\">\n @if (attr.isSortable) {\n <td class=\"text-center text-muted\" style=\"cursor: move; touch-action: none\" cdkDragHandle>\n <spark-icon name=\"grip-vertical\" />\n </td>\n }\n @for (col of (attr | asDetailColumns:asDetailTypes():rendererRegistry); track col.name; let firstCol = $first) {\n <ng-container *ngTemplateOutlet=\"inlineDetailCell; context: { row: row, col: col, attr: attr, rowIndex: rowIndex, rowRenderer: firstCol ? inlineRowRenderer : null }\"></ng-container>\n }\n <td class=\"text-nowrap\">\n @if (attr | canDeleteDetailRow:asDetailPermissions()) {\n <button type=\"button\" [color]=\"colors.secondary\" (click)=\"removeArrayItem(attr, rowIndex)\">\n <spark-icon name=\"trash\" />\n </button>\n }\n </td>\n\n <!-- Floating preview = a LIVE view of the row's cells (not CDK's cloneNode),\n so <bs-select> shows its value instead of blanking. The in-grid\n placeholder still uses CDK's default clone (exact row height) and is\n hidden via .cdk-drag-placeholder { visibility:hidden } in the styles,\n so the drop gap is blank without collapsing/shifting the other rows. -->\n <ng-template cdkDragPreview>\n <table class=\"table mb-0 bg-body shadow-sm spark-drag-preview\">\n <tbody class=\"align-middle\">\n <tr>\n @if (attr.isSortable) {\n <td class=\"text-center text-muted\" style=\"width: 32px\"><spark-icon name=\"grip-vertical\" /></td>\n }\n @for (col of (attr | asDetailColumns:asDetailTypes():rendererRegistry); track col.name) {\n <ng-container *ngTemplateOutlet=\"inlineDetailCell; context: { row: row, col: col, attr: attr, rowIndex: rowIndex }\"></ng-container>\n }\n </tr>\n </tbody>\n </table>\n </ng-template>\n </tr>\n } @empty {\n <tr>\n <td [attr.colspan]=\"(attr | asDetailColumns:asDetailTypes():rendererRegistry).length + (attr.isSortable ? 2 : 1)\" class=\"text-center text-muted\">\n {{ 'common.noItemsFound' | t }}\n </td>\n </tr>\n }\n </tbody>\n </bs-table>\n @for (err of rowLifecycleErrorsFor(attr.name); track $index) {\n <div class=\"text-danger small mt-1\">{{ err.errorMessage | resolveTranslation }}</div>\n }\n @if (attr | canCreateDetailRow:asDetailPermissions()) {\n <button type=\"button\" [color]=\"colors.primary\" class=\"w-100 rounded-0\" (click)=\"addInlineRow(attr)\">\n <spark-icon name=\"plus\" /> {{ 'common.add' | t }}\n </button>\n }\n } @else if (attr.dataType === 'AsDetail' && attr.isArray) {\n <bs-table [isResponsive]=\"true\" class=\"mb-1\">\n <thead>\n <tr>\n @if (attr.isSortable) {\n <th style=\"width: 32px\"></th>\n }\n @for (col of (attr | asDetailColumns:asDetailTypes():rendererRegistry); track col.name) {\n <th>{{ col.label | resolveTranslation:col.name }}<spark-attribute-description [description]=\"col.description\" /></th>\n }\n <th style=\"width: 80px\"></th>\n </tr>\n </thead>\n <tbody class=\"align-middle\" cdkDropList [cdkDropListDisabled]=\"!attr.isSortable\" (cdkDropListDropped)=\"onAsDetailReorder(attr, $event)\">\n @let modalRowRenderer = (attr | asDetailRowRenderer:asDetailTypes():rendererRegistry);\n @for (row of formData()[attr.name] || []; track $index) {\n <tr cdkDrag [cdkDragDisabled]=\"!attr.isSortable\">\n @if (attr.isSortable) {\n <td class=\"text-center text-muted\" style=\"cursor: move; touch-action: none\" cdkDragHandle>\n <spark-icon name=\"grip-vertical\" />\n </td>\n }\n @for (col of (attr | asDetailColumns:asDetailTypes():rendererRegistry); track col.name; let firstCol = $first) {\n <td>\n @if (getAsDetailCellRendererComponent(col); as cellRenderer) {\n <ng-container *ngComponentOutlet=\"cellRenderer; inputs: getAsDetailCellRendererInputs(cellRenderer, row, col)\"></ng-container>\n } @else {\n {{ row | asDetailCellValue:attr:col:asDetailReferenceOptions() }}\n }\n @if (firstCol && modalRowRenderer) {\n <div class=\"spark-row-renderer\">\n <ng-container *ngComponentOutlet=\"modalRowRenderer.component; inputs: getRowRendererInputs(modalRowRenderer, row)\"></ng-container>\n </div>\n }\n </td>\n }\n <td class=\"text-nowrap\">\n @if (attr | canEditDetailRow:asDetailPermissions()) {\n <button type=\"button\" class=\"btn btn-sm btn-outline-secondary me-1\" (click)=\"editArrayItem(attr, $index)\">\n <spark-icon name=\"pencil\" />\n </button>\n }\n @if (attr | canDeleteDetailRow:asDetailPermissions()) {\n <button type=\"button\" class=\"btn btn-sm btn-outline-danger\" (click)=\"removeArrayItem(attr, $index)\">\n <spark-icon name=\"trash\" />\n </button>\n }\n </td>\n </tr>\n } @empty {\n <tr>\n <td [attr.colspan]=\"(attr | asDetailColumns:asDetailTypes():rendererRegistry).length + (attr.isSortable ? 2 : 1)\" class=\"text-center text-muted\">\n {{ 'common.noItemsFound' | t }}\n </td>\n </tr>\n }\n </tbody>\n </bs-table>\n @for (err of rowLifecycleErrorsFor(attr.name); track $index) {\n <div class=\"text-danger small mt-1\">{{ err.errorMessage | resolveTranslation }}</div>\n }\n @if (attr | canCreateDetailRow:asDetailPermissions()) {\n <button type=\"button\" [color]=\"colors.primary\" class=\"w-100 rounded-0\" (click)=\"addArrayItem(attr)\">\n <spark-icon name=\"plus\" /> {{ 'common.add' | t }}\n </button>\n }\n } @else if (attr.dataType === 'AsDetail') {\n <bs-input-group>\n <input\n type=\"text\"\n [id]=\"attr.name\"\n [value]=\"attr | asDetailDisplayValue:formData():asDetailTypes()\"\n readonly\n [class.is-invalid]=\"hasError(attr.name)\">\n <button\n type=\"button\"\n bsInputGroupBtn\n [color]=\"colors.secondary\"\n (click)=\"openAsDetailEditor(attr)\">\n <spark-icon name=\"pencil\" />\n </button>\n </bs-input-group>\n } @else if (getEditRendererComponent(attr); as editComp) {\n <ng-container *ngComponentOutlet=\"editComp; inputs: getEditRendererInputs(editComp, attr)\"></ng-container>\n } @else if (attr.dataType === 'MultiLineString') {\n <textarea\n [id]=\"attr.name\"\n [ngModel]=\"formData()[attr.name]\"\n (ngModelChange)=\"formData()[attr.name] = $event; onFieldChange(attr)\"\n (blur)=\"onFieldBlur(attr)\"\n [name]=\"attr.name\"\n [required]=\"attr.isRequired\"\n rows=\"6\"\n [class.is-invalid]=\"hasError(attr.name)\"></textarea>\n } @else {\n <input\n [type]=\"attr.dataType | inputType\"\n [id]=\"attr.name\"\n [ngModel]=\"formData()[attr.name]\"\n (ngModelChange)=\"formData()[attr.name] = $event; onFieldChange(attr)\"\n (blur)=\"onFieldBlur(attr)\"\n [name]=\"attr.name\"\n [required]=\"attr.isRequired\"\n [step]=\"attr.dataType === 'decimal' ? '0.01' : '1'\"\n [class.is-invalid]=\"hasError(attr.name)\">\n }\n @if (attr.name | errorForAttribute:validationErrors(); as errorMsg) {\n <div class=\"invalid-feedback d-block\">\n {{ errorMsg }}\n </div>\n }\n </div>\n </div>\n </ng-template>\n\n @if (showButtons()) {\n <div bsRow class=\"mt-4\">\n <div [md]=\"4\"></div>\n <div [md]=\"8\" class=\"d-flex justify-content-end gap-2\">\n <button type=\"button\" [color]=\"colors.secondary\" (click)=\"onCancel()\" [disabled]=\"isSaving()\">{{ 'common.cancel' | t }}</button>\n <button type=\"submit\" [color]=\"colors.primary\" [disabled]=\"isSaving()\" (click)=\"onSave()\">\n @if (isSaving()) {\n <bs-spinner class=\"me-1\" />\n }\n {{ 'common.save' | t }}\n </button>\n </div>\n </div>\n }\n </bs-grid>\n}\n\n<!-- Modal for editing AsDetail objects -->\n<bs-modal [isOpen]=\"showAsDetailModal()\" (isOpenChange)=\"!$event && closeAsDetailModal()\">\n <div *bsModal>\n <div bsModalHeader>\n <h5 class=\"modal-title\">{{ 'common.edit' | t }} {{ editingAsDetailAttr()?.label | resolveTranslation:editingAsDetailAttr()?.name }}</h5>\n </div>\n\n @if (editingAsDetailAttr(); as attr) {\n <div bsModalBody>\n <spark-po-form\n [entityType]=\"attr | asDetailType:asDetailTypes()\"\n [(formData)]=\"asDetailFormData\"\n [parentId]=\"parentId()\"\n [parentType]=\"parentType()\"\n [triggerPathPrefix]=\"attr.isArray ? null : attr.name\"\n (nestedTriggerRequested)=\"onEmbeddedTrigger(attr.name, $event)\"\n (nestedTriggerBlurred)=\"onEmbeddedTriggerBlur($event)\">\n </spark-po-form>\n </div>\n }\n\n <div bsModalFooter>\n <button type=\"button\" [color]=\"colors.secondary\" (click)=\"closeAsDetailModal()\">{{ 'common.cancel' | t }}</button>\n <button type=\"button\" [color]=\"colors.primary\" (click)=\"saveAsDetailObject()\">{{ 'common.save' | t }}</button>\n </div>\n </div>\n</bs-modal>\n</bs-form>\n",
|
|
1586
|
+
styles: [":host ::ng-deep .cdk-drag-placeholder{visibility:hidden}\n"],
|
|
1587
|
+
dependencies: [
|
|
1588
|
+
{
|
|
1589
|
+
kind: "component",
|
|
1590
|
+
type: SparkPoFormComponent,
|
|
1591
|
+
selector: "spark-po-form",
|
|
1592
|
+
inputs: [
|
|
1593
|
+
"entityType",
|
|
1594
|
+
"formData",
|
|
1595
|
+
"validationErrors",
|
|
1596
|
+
"showButtons",
|
|
1597
|
+
"isSaving",
|
|
1598
|
+
"parentId",
|
|
1599
|
+
"parentType",
|
|
1600
|
+
"objectTypeId",
|
|
1601
|
+
"objectId",
|
|
1602
|
+
"triggerPathPrefix",
|
|
1603
|
+
"refreshOverlay"
|
|
1604
|
+
],
|
|
1605
|
+
outputs: [
|
|
1606
|
+
"formDataChange",
|
|
1607
|
+
"save",
|
|
1608
|
+
"cancel",
|
|
1609
|
+
"nestedTriggerRequested",
|
|
1610
|
+
"nestedTriggerBlurred",
|
|
1611
|
+
"refreshOverlayChange"
|
|
1612
|
+
]
|
|
1613
|
+
},
|
|
1614
|
+
{
|
|
1615
|
+
kind: "ngmodule",
|
|
1616
|
+
type: CommonModule
|
|
1617
|
+
},
|
|
1618
|
+
{
|
|
1619
|
+
kind: "directive",
|
|
1620
|
+
type: i1.NgComponentOutlet,
|
|
1621
|
+
selector: "[ngComponentOutlet]",
|
|
1622
|
+
inputs: [
|
|
1623
|
+
"ngComponentOutlet",
|
|
1624
|
+
"ngComponentOutletInputs",
|
|
1625
|
+
"ngComponentOutletInjector",
|
|
1626
|
+
"ngComponentOutletEnvironmentInjector",
|
|
1627
|
+
"ngComponentOutletContent",
|
|
1628
|
+
"ngComponentOutletNgModule"
|
|
1629
|
+
],
|
|
1630
|
+
exportAs: ["ngComponentOutlet"]
|
|
1631
|
+
},
|
|
1632
|
+
{
|
|
1633
|
+
kind: "directive",
|
|
1634
|
+
type: i1.NgTemplateOutlet,
|
|
1635
|
+
selector: "[ngTemplateOutlet]",
|
|
1636
|
+
inputs: [
|
|
1637
|
+
"ngTemplateOutletContext",
|
|
1638
|
+
"ngTemplateOutlet",
|
|
1639
|
+
"ngTemplateOutletInjector"
|
|
1640
|
+
]
|
|
1641
|
+
},
|
|
1642
|
+
{
|
|
1643
|
+
kind: "ngmodule",
|
|
1644
|
+
type: FormsModule
|
|
1645
|
+
},
|
|
1646
|
+
{
|
|
1647
|
+
kind: "directive",
|
|
1648
|
+
type: i1$1.NgSelectOption,
|
|
1649
|
+
selector: "option",
|
|
1650
|
+
inputs: ["ngValue", "value"]
|
|
1651
|
+
},
|
|
1652
|
+
{
|
|
1653
|
+
kind: "directive",
|
|
1654
|
+
type: i1$1.ɵNgSelectMultipleOption,
|
|
1655
|
+
selector: "option",
|
|
1656
|
+
inputs: ["ngValue", "value"]
|
|
1657
|
+
},
|
|
1658
|
+
{
|
|
1659
|
+
kind: "directive",
|
|
1660
|
+
type: i1$1.DefaultValueAccessor,
|
|
1661
|
+
selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]"
|
|
1662
|
+
},
|
|
1663
|
+
{
|
|
1664
|
+
kind: "directive",
|
|
1665
|
+
type: i1$1.NgControlStatus,
|
|
1666
|
+
selector: "[formControlName],[ngModel],[formControl]"
|
|
1667
|
+
},
|
|
1668
|
+
{
|
|
1669
|
+
kind: "directive",
|
|
1670
|
+
type: i1$1.RequiredValidator,
|
|
1671
|
+
selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",
|
|
1672
|
+
inputs: ["required"]
|
|
1673
|
+
},
|
|
1674
|
+
{
|
|
1675
|
+
kind: "directive",
|
|
1676
|
+
type: i1$1.NgModel,
|
|
1677
|
+
selector: "[ngModel]:not([formControlName]):not([formControl])",
|
|
1678
|
+
inputs: [
|
|
1679
|
+
"name",
|
|
1680
|
+
"disabled",
|
|
1681
|
+
"ngModel",
|
|
1682
|
+
"ngModelOptions"
|
|
1683
|
+
],
|
|
1684
|
+
outputs: ["ngModelChange"],
|
|
1685
|
+
exportAs: ["ngModel"]
|
|
1686
|
+
},
|
|
1687
|
+
{
|
|
1688
|
+
kind: "directive",
|
|
1689
|
+
type: CdkDropList,
|
|
1690
|
+
selector: "[cdkDropList], cdk-drop-list",
|
|
1691
|
+
inputs: [
|
|
1692
|
+
"cdkDropListConnectedTo",
|
|
1693
|
+
"cdkDropListData",
|
|
1694
|
+
"cdkDropListOrientation",
|
|
1695
|
+
"id",
|
|
1696
|
+
"cdkDropListLockAxis",
|
|
1697
|
+
"cdkDropListDisabled",
|
|
1698
|
+
"cdkDropListSortingDisabled",
|
|
1699
|
+
"cdkDropListEnterPredicate",
|
|
1700
|
+
"cdkDropListSortPredicate",
|
|
1701
|
+
"cdkDropListAutoScrollDisabled",
|
|
1702
|
+
"cdkDropListAutoScrollStep",
|
|
1703
|
+
"cdkDropListElementContainer",
|
|
1704
|
+
"cdkDropListHasAnchor"
|
|
1705
|
+
],
|
|
1706
|
+
outputs: [
|
|
1707
|
+
"cdkDropListDropped",
|
|
1708
|
+
"cdkDropListEntered",
|
|
1709
|
+
"cdkDropListExited",
|
|
1710
|
+
"cdkDropListSorted"
|
|
1711
|
+
],
|
|
1712
|
+
exportAs: ["cdkDropList"]
|
|
1713
|
+
},
|
|
1714
|
+
{
|
|
1715
|
+
kind: "directive",
|
|
1716
|
+
type: CdkDrag,
|
|
1717
|
+
selector: "[cdkDrag]",
|
|
1718
|
+
inputs: [
|
|
1719
|
+
"cdkDragData",
|
|
1720
|
+
"cdkDragLockAxis",
|
|
1721
|
+
"cdkDragRootElement",
|
|
1722
|
+
"cdkDragBoundary",
|
|
1723
|
+
"cdkDragStartDelay",
|
|
1724
|
+
"cdkDragFreeDragPosition",
|
|
1725
|
+
"cdkDragDisabled",
|
|
1726
|
+
"cdkDragConstrainPosition",
|
|
1727
|
+
"cdkDragPreviewClass",
|
|
1728
|
+
"cdkDragPreviewContainer",
|
|
1729
|
+
"cdkDragScale"
|
|
1730
|
+
],
|
|
1731
|
+
outputs: [
|
|
1732
|
+
"cdkDragStarted",
|
|
1733
|
+
"cdkDragReleased",
|
|
1734
|
+
"cdkDragEnded",
|
|
1735
|
+
"cdkDragEntered",
|
|
1736
|
+
"cdkDragExited",
|
|
1737
|
+
"cdkDragDropped",
|
|
1738
|
+
"cdkDragMoved"
|
|
1739
|
+
],
|
|
1740
|
+
exportAs: ["cdkDrag"]
|
|
1741
|
+
},
|
|
1742
|
+
{
|
|
1743
|
+
kind: "directive",
|
|
1744
|
+
type: CdkDragHandle,
|
|
1745
|
+
selector: "[cdkDragHandle]",
|
|
1746
|
+
inputs: ["cdkDragHandleDisabled"]
|
|
1747
|
+
},
|
|
1748
|
+
{
|
|
1749
|
+
kind: "directive",
|
|
1750
|
+
type: CdkDragPreview,
|
|
1751
|
+
selector: "ng-template[cdkDragPreview]",
|
|
1752
|
+
inputs: ["data", "matchSize"]
|
|
1753
|
+
},
|
|
1754
|
+
{
|
|
1755
|
+
kind: "component",
|
|
1756
|
+
type: BsCardComponent,
|
|
1757
|
+
selector: "bs-card",
|
|
1758
|
+
inputs: ["color", "outline"]
|
|
1759
|
+
},
|
|
1760
|
+
{
|
|
1761
|
+
kind: "component",
|
|
1762
|
+
type: BsCardHeaderComponent,
|
|
1763
|
+
selector: "bs-card-header",
|
|
1764
|
+
inputs: ["color", "navStyle"]
|
|
1765
|
+
},
|
|
1766
|
+
{
|
|
1767
|
+
kind: "component",
|
|
1768
|
+
type: BsFormComponent,
|
|
1769
|
+
selector: "bs-form",
|
|
1770
|
+
inputs: ["action", "method"],
|
|
1771
|
+
outputs: ["submitted"]
|
|
1772
|
+
},
|
|
1773
|
+
{
|
|
1774
|
+
kind: "directive",
|
|
1775
|
+
type: BsFormControlDirective,
|
|
1776
|
+
selector: "bs-form input:not(.no-form-control), bs-form textarea:not(.no-form-control)"
|
|
1777
|
+
},
|
|
1778
|
+
{
|
|
1779
|
+
kind: "component",
|
|
1780
|
+
type: BsGridComponent,
|
|
1781
|
+
selector: "bs-grid",
|
|
1782
|
+
inputs: ["stopFullWidthAt"]
|
|
1783
|
+
},
|
|
1784
|
+
{
|
|
1785
|
+
kind: "directive",
|
|
1786
|
+
type: BsGridRowDirective,
|
|
1787
|
+
selector: "[bsRow]"
|
|
1788
|
+
},
|
|
1789
|
+
{
|
|
1790
|
+
kind: "directive",
|
|
1791
|
+
type: BsGridColumnDirective,
|
|
1792
|
+
selector: "[xxs],[xs],[sm],[md],[lg],[xl],[xxl]",
|
|
1793
|
+
inputs: [
|
|
1794
|
+
"xxs",
|
|
1795
|
+
"xs",
|
|
1796
|
+
"sm",
|
|
1797
|
+
"md",
|
|
1798
|
+
"lg",
|
|
1799
|
+
"xl",
|
|
1800
|
+
"xxl"
|
|
1801
|
+
]
|
|
1802
|
+
},
|
|
1803
|
+
{
|
|
1804
|
+
kind: "directive",
|
|
1805
|
+
type: BsColFormLabelDirective,
|
|
1806
|
+
selector: "[bsColFormLabel]"
|
|
1807
|
+
},
|
|
1808
|
+
{
|
|
1809
|
+
kind: "directive",
|
|
1810
|
+
type: BsButtonTypeDirective,
|
|
1811
|
+
selector: "button[color],input[type=\"button\"][color],input[type=\"submit\"][color],a[color]",
|
|
1812
|
+
inputs: ["color"]
|
|
1813
|
+
},
|
|
1814
|
+
{
|
|
1815
|
+
kind: "component",
|
|
1816
|
+
type: BsInputGroupComponent,
|
|
1817
|
+
selector: "bs-input-group",
|
|
1818
|
+
inputs: ["size"]
|
|
1819
|
+
},
|
|
1820
|
+
{
|
|
1821
|
+
kind: "component",
|
|
1822
|
+
type: BsSelectComponent,
|
|
1823
|
+
selector: "bs-select",
|
|
1824
|
+
inputs: [
|
|
1825
|
+
"identifier",
|
|
1826
|
+
"size",
|
|
1827
|
+
"multiple",
|
|
1828
|
+
"numberVisible",
|
|
1829
|
+
"disabled"
|
|
1830
|
+
]
|
|
1831
|
+
},
|
|
1832
|
+
{
|
|
1833
|
+
kind: "directive",
|
|
1834
|
+
type: BsSelectOption,
|
|
1835
|
+
selector: "option",
|
|
1836
|
+
inputs: ["ngValue", "value"]
|
|
1837
|
+
},
|
|
1838
|
+
{
|
|
1839
|
+
kind: "component",
|
|
1840
|
+
type: BsTreeSelectComponent,
|
|
1841
|
+
selector: "bs-tree-select",
|
|
1842
|
+
inputs: [
|
|
1843
|
+
"provider",
|
|
1844
|
+
"mode",
|
|
1845
|
+
"variant",
|
|
1846
|
+
"cascadeSelect",
|
|
1847
|
+
"placeholder",
|
|
1848
|
+
"showClear",
|
|
1849
|
+
"panelScrollHeight",
|
|
1850
|
+
"searchDebounceMs",
|
|
1851
|
+
"disabled",
|
|
1852
|
+
"value"
|
|
1853
|
+
],
|
|
1854
|
+
outputs: [
|
|
1855
|
+
"valueChange",
|
|
1856
|
+
"opened",
|
|
1857
|
+
"closed",
|
|
1858
|
+
"cleared"
|
|
1859
|
+
]
|
|
1860
|
+
},
|
|
1861
|
+
{
|
|
1862
|
+
kind: "component",
|
|
1863
|
+
type: BsModalHostComponent,
|
|
1864
|
+
selector: "bs-modal",
|
|
1865
|
+
inputs: [
|
|
1866
|
+
"isOpen",
|
|
1867
|
+
"closeOnEscape",
|
|
1868
|
+
"scrollable"
|
|
1869
|
+
],
|
|
1870
|
+
outputs: ["isOpenChange"]
|
|
1871
|
+
},
|
|
1872
|
+
{
|
|
1873
|
+
kind: "directive",
|
|
1874
|
+
type: BsModalDirective,
|
|
1875
|
+
selector: "[bsModal]"
|
|
1876
|
+
},
|
|
1877
|
+
{
|
|
1878
|
+
kind: "directive",
|
|
1879
|
+
type: BsModalHeaderDirective,
|
|
1880
|
+
selector: "[bsModalHeader]"
|
|
1881
|
+
},
|
|
1882
|
+
{
|
|
1883
|
+
kind: "directive",
|
|
1884
|
+
type: BsModalBodyDirective,
|
|
1885
|
+
selector: "[bsModalBody]"
|
|
1886
|
+
},
|
|
1887
|
+
{
|
|
1888
|
+
kind: "directive",
|
|
1889
|
+
type: BsModalFooterDirective,
|
|
1890
|
+
selector: "[bsModalFooter]"
|
|
1891
|
+
},
|
|
1892
|
+
{
|
|
1893
|
+
kind: "component",
|
|
1894
|
+
type: BsTableComponent,
|
|
1895
|
+
selector: "bs-table",
|
|
1896
|
+
inputs: [
|
|
1897
|
+
"isResponsive",
|
|
1898
|
+
"striped",
|
|
1899
|
+
"hover",
|
|
1900
|
+
"border",
|
|
1901
|
+
"ariaRowCount"
|
|
1902
|
+
]
|
|
1903
|
+
},
|
|
1904
|
+
{
|
|
1905
|
+
kind: "component",
|
|
1906
|
+
type: BsCheckboxComponent,
|
|
1907
|
+
selector: "bs-checkbox",
|
|
1908
|
+
inputs: [
|
|
1909
|
+
"type",
|
|
1910
|
+
"isToggled",
|
|
1911
|
+
"indeterminate",
|
|
1912
|
+
"name",
|
|
1913
|
+
"value",
|
|
1914
|
+
"group"
|
|
1915
|
+
],
|
|
1916
|
+
outputs: ["isToggledChange", "indeterminateChange"]
|
|
1917
|
+
},
|
|
1918
|
+
{
|
|
1919
|
+
kind: "component",
|
|
1920
|
+
type: BsSpinnerComponent,
|
|
1921
|
+
selector: "bs-spinner",
|
|
1922
|
+
inputs: ["type", "color"]
|
|
1923
|
+
},
|
|
1924
|
+
{
|
|
1925
|
+
kind: "component",
|
|
1926
|
+
type: BsTabControlComponent,
|
|
1927
|
+
selector: "bs-tab-control",
|
|
1928
|
+
inputs: [
|
|
1929
|
+
"border",
|
|
1930
|
+
"selectFirstTab",
|
|
1931
|
+
"tabsPosition"
|
|
1932
|
+
]
|
|
1933
|
+
},
|
|
1934
|
+
{
|
|
1935
|
+
kind: "component",
|
|
1936
|
+
type: BsTabPageComponent,
|
|
1937
|
+
selector: "bs-tab-page",
|
|
1938
|
+
inputs: ["disabled"]
|
|
1939
|
+
},
|
|
1940
|
+
{
|
|
1941
|
+
kind: "directive",
|
|
1942
|
+
type: BsTabPageHeaderDirective,
|
|
1943
|
+
selector: "[bsTabPageHeader]"
|
|
1944
|
+
},
|
|
1945
|
+
{
|
|
1946
|
+
kind: "component",
|
|
1947
|
+
type: SparkIconComponent,
|
|
1948
|
+
selector: "spark-icon",
|
|
1949
|
+
inputs: ["name"]
|
|
1950
|
+
},
|
|
1951
|
+
{
|
|
1952
|
+
kind: "component",
|
|
1953
|
+
type: SparkReferencePickerComponent,
|
|
1954
|
+
selector: "spark-reference-picker",
|
|
1955
|
+
inputs: [
|
|
1956
|
+
"value",
|
|
1957
|
+
"options",
|
|
1958
|
+
"referenceType",
|
|
1959
|
+
"isInvalid",
|
|
1960
|
+
"inputId",
|
|
1961
|
+
"title"
|
|
1962
|
+
],
|
|
1963
|
+
outputs: ["valueChange"]
|
|
1964
|
+
},
|
|
1965
|
+
{
|
|
1966
|
+
kind: "component",
|
|
1967
|
+
type: SparkLookupPickerComponent,
|
|
1968
|
+
selector: "spark-lookup-picker",
|
|
1969
|
+
inputs: [
|
|
1970
|
+
"value",
|
|
1971
|
+
"options",
|
|
1972
|
+
"isInvalid",
|
|
1973
|
+
"inputId",
|
|
1974
|
+
"title"
|
|
1975
|
+
],
|
|
1976
|
+
outputs: ["valueChange"]
|
|
1977
|
+
},
|
|
1978
|
+
{
|
|
1979
|
+
kind: "component",
|
|
1980
|
+
type: SparkAttributeDescriptionComponent,
|
|
1981
|
+
selector: "spark-attribute-description",
|
|
1982
|
+
inputs: ["description", "position"]
|
|
1983
|
+
},
|
|
1984
|
+
{
|
|
1985
|
+
kind: "pipe",
|
|
1986
|
+
type: TranslateKeyPipe,
|
|
1987
|
+
name: "t"
|
|
1988
|
+
},
|
|
1989
|
+
{
|
|
1990
|
+
kind: "pipe",
|
|
1991
|
+
type: ResolveTranslationPipe,
|
|
1992
|
+
name: "resolveTranslation"
|
|
1993
|
+
},
|
|
1994
|
+
{
|
|
1995
|
+
kind: "pipe",
|
|
1996
|
+
type: InputTypePipe,
|
|
1997
|
+
name: "inputType"
|
|
1998
|
+
},
|
|
1999
|
+
{
|
|
2000
|
+
kind: "pipe",
|
|
2001
|
+
type: LookupDisplayTypePipe,
|
|
2002
|
+
name: "lookupDisplayType"
|
|
2003
|
+
},
|
|
2004
|
+
{
|
|
2005
|
+
kind: "pipe",
|
|
2006
|
+
type: LookupOptionsPipe,
|
|
2007
|
+
name: "lookupOptions"
|
|
2008
|
+
},
|
|
2009
|
+
{
|
|
2010
|
+
kind: "pipe",
|
|
2011
|
+
type: AsDetailDisplayValuePipe,
|
|
2012
|
+
name: "asDetailDisplayValue"
|
|
2013
|
+
},
|
|
2014
|
+
{
|
|
2015
|
+
kind: "pipe",
|
|
2016
|
+
type: AsDetailTypePipe,
|
|
2017
|
+
name: "asDetailType"
|
|
2018
|
+
},
|
|
2019
|
+
{
|
|
2020
|
+
kind: "pipe",
|
|
2021
|
+
type: AsDetailColumnsPipe,
|
|
2022
|
+
name: "asDetailColumns"
|
|
2023
|
+
},
|
|
2024
|
+
{
|
|
2025
|
+
kind: "pipe",
|
|
2026
|
+
type: AsDetailRowRendererPipe,
|
|
2027
|
+
name: "asDetailRowRenderer"
|
|
2028
|
+
},
|
|
2029
|
+
{
|
|
2030
|
+
kind: "pipe",
|
|
2031
|
+
type: AsDetailCellValuePipe,
|
|
2032
|
+
name: "asDetailCellValue"
|
|
2033
|
+
},
|
|
2034
|
+
{
|
|
2035
|
+
kind: "pipe",
|
|
2036
|
+
type: CanCreateDetailRowPipe,
|
|
2037
|
+
name: "canCreateDetailRow"
|
|
2038
|
+
},
|
|
2039
|
+
{
|
|
2040
|
+
kind: "pipe",
|
|
2041
|
+
type: CanDeleteDetailRowPipe,
|
|
2042
|
+
name: "canDeleteDetailRow"
|
|
2043
|
+
},
|
|
2044
|
+
{
|
|
2045
|
+
kind: "pipe",
|
|
2046
|
+
type: CanEditDetailRowPipe,
|
|
2047
|
+
name: "canEditDetailRow"
|
|
2048
|
+
},
|
|
2049
|
+
{
|
|
2050
|
+
kind: "pipe",
|
|
2051
|
+
type: InlineRefOptionsPipe,
|
|
2052
|
+
name: "inlineRefOptions"
|
|
2053
|
+
},
|
|
2054
|
+
{
|
|
2055
|
+
kind: "pipe",
|
|
2056
|
+
type: ErrorForAttributePipe,
|
|
2057
|
+
name: "errorForAttribute"
|
|
2058
|
+
}
|
|
2059
|
+
],
|
|
2060
|
+
changeDetection: i0.ChangeDetectionStrategy.OnPush
|
|
2061
|
+
});
|
|
2062
|
+
};
|
|
2063
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
2064
|
+
minVersion: "12.0.0",
|
|
2065
|
+
version: "22.2.0",
|
|
2066
|
+
ngImport: i0,
|
|
2067
|
+
type: SparkPoFormComponent,
|
|
2068
|
+
decorators: [{
|
|
2069
|
+
type: Component,
|
|
2070
|
+
args: [{
|
|
2071
|
+
selector: "spark-po-form",
|
|
2072
|
+
imports: [
|
|
2073
|
+
CommonModule,
|
|
2074
|
+
NgTemplateOutlet,
|
|
2075
|
+
NgComponentOutlet,
|
|
2076
|
+
FormsModule,
|
|
2077
|
+
CdkDropList,
|
|
2078
|
+
CdkDrag,
|
|
2079
|
+
CdkDragHandle,
|
|
2080
|
+
CdkDragPreview,
|
|
2081
|
+
BsCardComponent,
|
|
2082
|
+
BsCardHeaderComponent,
|
|
2083
|
+
BsFormComponent,
|
|
2084
|
+
BsFormControlDirective,
|
|
2085
|
+
BsGridComponent,
|
|
2086
|
+
BsGridRowDirective,
|
|
2087
|
+
BsGridColumnDirective,
|
|
2088
|
+
BsGridColDirective,
|
|
2089
|
+
BsColFormLabelDirective,
|
|
2090
|
+
BsButtonTypeDirective,
|
|
2091
|
+
BsInputGroupComponent,
|
|
2092
|
+
BsSelectComponent,
|
|
2093
|
+
BsSelectOption,
|
|
2094
|
+
BsTreeSelectComponent,
|
|
2095
|
+
BsModalHostComponent,
|
|
2096
|
+
BsModalDirective,
|
|
2097
|
+
BsModalHeaderDirective,
|
|
2098
|
+
BsModalBodyDirective,
|
|
2099
|
+
BsModalFooterDirective,
|
|
2100
|
+
BsTableComponent,
|
|
2101
|
+
BsCheckboxComponent,
|
|
2102
|
+
BsSpinnerComponent,
|
|
2103
|
+
BsTabControlComponent,
|
|
2104
|
+
BsTabPageComponent,
|
|
2105
|
+
BsTabPageHeaderDirective,
|
|
2106
|
+
SparkIconComponent,
|
|
2107
|
+
SparkPoFormComponent,
|
|
2108
|
+
SparkReferencePickerComponent,
|
|
2109
|
+
SparkLookupPickerComponent,
|
|
2110
|
+
TranslateKeyPipe,
|
|
2111
|
+
ResolveTranslationPipe,
|
|
2112
|
+
InputTypePipe,
|
|
2113
|
+
LookupDisplayTypePipe,
|
|
2114
|
+
LookupOptionsPipe,
|
|
2115
|
+
AsDetailDisplayValuePipe,
|
|
2116
|
+
AsDetailTypePipe,
|
|
2117
|
+
AsDetailColumnsPipe,
|
|
2118
|
+
AsDetailRowRendererPipe,
|
|
2119
|
+
AsDetailCellValuePipe,
|
|
2120
|
+
CanCreateDetailRowPipe,
|
|
2121
|
+
CanDeleteDetailRowPipe,
|
|
2122
|
+
CanEditDetailRowPipe,
|
|
2123
|
+
InlineRefOptionsPipe,
|
|
2124
|
+
ErrorForAttributePipe,
|
|
2125
|
+
SparkAttributeDescriptionComponent
|
|
2126
|
+
],
|
|
2127
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
2128
|
+
template: "<bs-form>\n @if (entityType()) {\n <bs-grid>\n <bs-tab-control>\n @for (tab of resolvedTabs(); track tab.id) {\n <bs-tab-page>\n <ng-template bsTabPageHeader>{{ tab.label | resolveTranslation:tab.name }}</ng-template>\n <ng-container *ngTemplateOutlet=\"tabContent; context: { $implicit: tab }\"></ng-container>\n </bs-tab-page>\n }\n </bs-tab-control>\n\n <ng-template #tabContent let-tab>\n @if (tab.id === '__default__') {\n @if (ungroupedAttributes().length > 0) {\n <bs-card class=\"d-block m-3\">\n <div class=\"p-3\">\n @for (attr of ungroupedAttributes(); track attr.id) {\n <ng-container *ngTemplateOutlet=\"attrField; context: { $implicit: attr }\"></ng-container>\n }\n </div>\n </bs-card>\n }\n }\n @for (group of groupsForTab(tab); track group.id) {\n @if (attrsForGroup(group); as groupAttrs) {\n @if (groupAttrs.length > 0) {\n <bs-card class=\"d-block m-3\">\n @if (group.label) {\n <bs-card-header>{{ group.label | resolveTranslation:group.name }}</bs-card-header>\n }\n <div class=\"p-3\">\n @for (attr of groupAttrs; track attr.id) {\n <ng-container *ngTemplateOutlet=\"attrField; context: { $implicit: attr }\"></ng-container>\n }\n </div>\n </bs-card>\n }\n }\n }\n </ng-template>\n\n <ng-template #attrField let-attr>\n <div bsRow class=\"mb-3\">\n <label [md]=\"4\" bsColFormLabel [for]=\"attr.name\">\n {{ attr.label | resolveTranslation:attr.name }}\n @if (attr.isRequired) {\n <span class=\"text-danger\">*</span>\n }\n <spark-attribute-description [description]=\"attr.description\" />\n </label>\n <div [md]=\"8\">\n <!-- A lookup wins over the raw data type. `[LookupReference]` does not change dataType —\n only `[Reference]` does — so a lookup-backed bool still reports 'boolean' here. Tested\n first, this branch swallowed it into a two-state checkbox and the select below was\n unreachable, which made a declared lookup silently do nothing. -->\n @if (attr.dataType === 'boolean' && !attr.lookupReferenceType) {\n <bs-checkbox\n [ngModel]=\"formData()[attr.name]\"\n (ngModelChange)=\"formData()[attr.name] = $event; onFieldChange(attr)\">\n </bs-checkbox>\n } @else if (attr.lookupReferenceType) {\n @if ((attr | lookupDisplayType:lookupReferenceOptions()) === ELookupDisplayType.Modal) {\n <spark-lookup-picker\n [value]=\"formData()[attr.name]\"\n [options]=\"getLookupOptions(attr)\"\n [inputId]=\"attr.name\"\n [title]=\"attr.label | resolveTranslation:attr.name\"\n [isInvalid]=\"hasError(attr.name)\"\n (valueChange)=\"onLookupValueChange(attr, $event)\">\n </spark-lookup-picker>\n } @else {\n <bs-select\n class=\"w-100\"\n [ngModel]=\"formData()[attr.name]\"\n (ngModelChange)=\"formData()[attr.name] = $event; onFieldChange(attr)\"\n [id]=\"attr.name\"\n [class.is-invalid]=\"hasError(attr.name)\">\n <option [ngValue]=\"null\">{{ 'common.selectPlaceholder' | t }}</option>\n @for (option of (attr | lookupOptions:lookupReferenceOptions()); track option.key) {\n <option [ngValue]=\"option.key\">\n {{ option.values | resolveTranslation:option.key }}\n </option>\n }\n </bs-select>\n }\n } @else if (attr.dataType === 'Reference' && attr.isArray) {\n <bs-tree-select\n mode=\"multiple\"\n variant=\"textbox\"\n [showClear]=\"true\"\n [placeholder]=\"'common.search' | t\"\n [provider]=\"getReferenceProvider(attr)\"\n [ngModel]=\"referenceTreeValues()[attr.name] || []\"\n (ngModelChange)=\"onReferenceTreeChange(attr, $event)\"\n [ngModelOptions]=\"{ standalone: true }\">\n </bs-tree-select>\n } @else if (attr.dataType === 'Reference') {\n <spark-reference-picker\n [value]=\"formData()[attr.name]\"\n [options]=\"referenceOptions()[attr.name] || []\"\n [referenceType]=\"attr.referenceType\"\n [inputId]=\"attr.name\"\n [title]=\"attr.label | resolveTranslation:attr.name\"\n [isInvalid]=\"hasError(attr.name)\"\n (valueChange)=\"onReferenceValueChange(attr, $event)\">\n </spark-reference-picker>\n } @else if (attr.dataType === 'AsDetail' && attr.isArray && attr.editMode === 'inline') {\n <!-- One source of truth for an inline cell, reused by the row and by the drag\n preview. The preview is a live Angular view (not a cloneNode), so its\n <bs-select> binds to row[col.name] and shows the value while dragging. -->\n <ng-template #inlineDetailCell let-row=\"row\" let-col=\"col\" let-attr=\"attr\" let-rowIndex=\"rowIndex\" let-rowRenderer=\"rowRenderer\">\n <td>\n <!-- A row the caller may not edit renders through the same read-only span as a\n read-only column: still fully readable, just not editable. Hiding it would\n hide the data, and the save path would silently restore any edit anyway. -->\n @if (col.isReadOnly || !(attr | canEditDetailRow:asDetailPermissions())) {\n <span class=\"text-muted\">{{ row | asDetailCellValue:attr:col:asDetailReferenceOptions() }}</span>\n } @else if (getAsDetailCellEditRenderer(col); as editRenderer) {\n <ng-container *ngComponentOutlet=\"editRenderer; inputs: getAsDetailCellEditRendererInputs(editRenderer, row, col)\"></ng-container>\n } @else if (col.dataType === 'AsDetail') {\n <!-- Nested AsDetail can't flatten into a row: escalate to the row modal,\n where the recursive spark-po-form renders the nested structure. -->\n <div class=\"d-flex align-items-center gap-1\">\n <span class=\"text-truncate flex-grow-1\">{{ row | asDetailCellValue:attr:col:asDetailReferenceOptions() }}</span>\n <button type=\"button\" class=\"btn btn-sm btn-outline-secondary\" (click)=\"editArrayItem(attr, rowIndex)\">\n <spark-icon name=\"pencil\" />\n </button>\n </div>\n } @else if (col.dataType === 'boolean' && !col.lookupReferenceType) {\n <!-- Same precedence as the top-level chain above: a lookup-backed column must\n reach its select rather than being swallowed by the checkbox. -->\n <bs-checkbox\n [(ngModel)]=\"row[col.name]\"\n (ngModelChange)=\"onInlineCellChange(attr, rowIndex, col)\">\n </bs-checkbox>\n } @else if (col.dataType === 'Reference' && col.query) {\n @if (col.referenceDisplayType === EReferenceDisplayType.Modal) {\n <spark-reference-picker\n [value]=\"row[col.name]\"\n [options]=\"(attr | inlineRefOptions:col:asDetailReferenceOptions())\"\n [referenceType]=\"col.referenceType\"\n [title]=\"col.label | resolveTranslation:col.name\"\n [isInvalid]=\"hasInlineError(attr, rowIndex, col)\"\n (valueChange)=\"row[col.name] = $event; onInlineCellChange(attr, rowIndex, col)\">\n </spark-reference-picker>\n } @else {\n <bs-select\n class=\"w-100\"\n [(ngModel)]=\"row[col.name]\"\n (ngModelChange)=\"onInlineCellChange(attr, rowIndex, col)\"\n [class.is-invalid]=\"hasInlineError(attr, rowIndex, col)\">\n <option [ngValue]=\"null\">{{ 'common.selectPlaceholder' | t }}</option>\n @for (option of (attr | inlineRefOptions:col:asDetailReferenceOptions()); track option.id) {\n <option [ngValue]=\"option.id\">\n {{ option.breadcrumb || option.id }}\n </option>\n }\n </bs-select>\n }\n } @else if (col.lookupReferenceType) {\n @if ((col | lookupDisplayType:lookupReferenceOptions()) === ELookupDisplayType.Modal) {\n <spark-lookup-picker\n [value]=\"row[col.name]\"\n [options]=\"getLookupOptions(col)\"\n [title]=\"col.label | resolveTranslation:col.name\"\n [isInvalid]=\"hasInlineError(attr, rowIndex, col)\"\n (valueChange)=\"row[col.name] = $event; onInlineCellChange(attr, rowIndex, col)\">\n </spark-lookup-picker>\n } @else {\n <bs-select\n class=\"w-100\"\n [(ngModel)]=\"row[col.name]\"\n (ngModelChange)=\"onInlineCellChange(attr, rowIndex, col)\"\n [class.is-invalid]=\"hasInlineError(attr, rowIndex, col)\">\n <option [ngValue]=\"null\">{{ 'common.selectPlaceholder' | t }}</option>\n @for (option of getLookupOptions(col); track option.key) {\n <option [ngValue]=\"option.key\">\n {{ option.values | resolveTranslation:option.key }}\n </option>\n }\n </bs-select>\n }\n } @else if (col.dataType === 'MultiLineString') {\n <textarea\n [(ngModel)]=\"row[col.name]\"\n [required]=\"col.isRequired\"\n rows=\"3\"\n [class.is-invalid]=\"hasInlineError(attr, rowIndex, col)\"\n (ngModelChange)=\"onInlineCellChange(attr, rowIndex, col)\"\n (blur)=\"onInlineCellBlur(attr, rowIndex, col)\"></textarea>\n } @else {\n <input\n [type]=\"col.dataType | inputType\"\n [(ngModel)]=\"row[col.name]\"\n [required]=\"col.isRequired\"\n [step]=\"col.dataType === 'decimal' ? '0.01' : '1'\"\n [class.is-invalid]=\"hasInlineError(attr, rowIndex, col)\"\n (ngModelChange)=\"onInlineCellChange(attr, rowIndex, col)\"\n (blur)=\"onInlineCellBlur(attr, rowIndex, col)\">\n }\n @if (inlineErrorMessage(attr, rowIndex, col); as errorMsg) {\n <div class=\"invalid-feedback d-block\">{{ errorMsg }}</div>\n }\n <!-- Passed for the first cell only: a row renderer (rowComponent) draws its\n attributes once per row, under that cell, instead of as columns. -->\n @if (rowRenderer) {\n <div class=\"spark-row-renderer\">\n <ng-container *ngComponentOutlet=\"rowRenderer.component; inputs: getRowRendererInputs(rowRenderer, row)\"></ng-container>\n </div>\n }\n </td>\n </ng-template>\n <bs-table [isResponsive]=\"true\" class=\"mb-1\">\n <thead>\n <tr>\n @if (attr.isSortable) {\n <th style=\"width: 32px\"></th>\n }\n @for (col of (attr | asDetailColumns:asDetailTypes():rendererRegistry); track col.name) {\n <th>{{ col.label | resolveTranslation:col.name }}<spark-attribute-description [description]=\"col.description\" /></th>\n }\n <th style=\"width: 50px\"></th>\n </tr>\n </thead>\n @let inlineRowRenderer = (attr | asDetailRowRenderer:asDetailTypes():rendererRegistry);\n <tbody class=\"align-middle\" cdkDropList [cdkDropListDisabled]=\"!attr.isSortable\" (cdkDropListDropped)=\"onAsDetailReorder(attr, $event)\">\n @for (row of formData()[attr.name] || []; track $index; let rowIndex = $index) {\n <tr cdkDrag [cdkDragDisabled]=\"!attr.isSortable\">\n @if (attr.isSortable) {\n <td class=\"text-center text-muted\" style=\"cursor: move; touch-action: none\" cdkDragHandle>\n <spark-icon name=\"grip-vertical\" />\n </td>\n }\n @for (col of (attr | asDetailColumns:asDetailTypes():rendererRegistry); track col.name; let firstCol = $first) {\n <ng-container *ngTemplateOutlet=\"inlineDetailCell; context: { row: row, col: col, attr: attr, rowIndex: rowIndex, rowRenderer: firstCol ? inlineRowRenderer : null }\"></ng-container>\n }\n <td class=\"text-nowrap\">\n @if (attr | canDeleteDetailRow:asDetailPermissions()) {\n <button type=\"button\" [color]=\"colors.secondary\" (click)=\"removeArrayItem(attr, rowIndex)\">\n <spark-icon name=\"trash\" />\n </button>\n }\n </td>\n\n <!-- Floating preview = a LIVE view of the row's cells (not CDK's cloneNode),\n so <bs-select> shows its value instead of blanking. The in-grid\n placeholder still uses CDK's default clone (exact row height) and is\n hidden via .cdk-drag-placeholder { visibility:hidden } in the styles,\n so the drop gap is blank without collapsing/shifting the other rows. -->\n <ng-template cdkDragPreview>\n <table class=\"table mb-0 bg-body shadow-sm spark-drag-preview\">\n <tbody class=\"align-middle\">\n <tr>\n @if (attr.isSortable) {\n <td class=\"text-center text-muted\" style=\"width: 32px\"><spark-icon name=\"grip-vertical\" /></td>\n }\n @for (col of (attr | asDetailColumns:asDetailTypes():rendererRegistry); track col.name) {\n <ng-container *ngTemplateOutlet=\"inlineDetailCell; context: { row: row, col: col, attr: attr, rowIndex: rowIndex }\"></ng-container>\n }\n </tr>\n </tbody>\n </table>\n </ng-template>\n </tr>\n } @empty {\n <tr>\n <td [attr.colspan]=\"(attr | asDetailColumns:asDetailTypes():rendererRegistry).length + (attr.isSortable ? 2 : 1)\" class=\"text-center text-muted\">\n {{ 'common.noItemsFound' | t }}\n </td>\n </tr>\n }\n </tbody>\n </bs-table>\n @for (err of rowLifecycleErrorsFor(attr.name); track $index) {\n <div class=\"text-danger small mt-1\">{{ err.errorMessage | resolveTranslation }}</div>\n }\n @if (attr | canCreateDetailRow:asDetailPermissions()) {\n <button type=\"button\" [color]=\"colors.primary\" class=\"w-100 rounded-0\" (click)=\"addInlineRow(attr)\">\n <spark-icon name=\"plus\" /> {{ 'common.add' | t }}\n </button>\n }\n } @else if (attr.dataType === 'AsDetail' && attr.isArray) {\n <bs-table [isResponsive]=\"true\" class=\"mb-1\">\n <thead>\n <tr>\n @if (attr.isSortable) {\n <th style=\"width: 32px\"></th>\n }\n @for (col of (attr | asDetailColumns:asDetailTypes():rendererRegistry); track col.name) {\n <th>{{ col.label | resolveTranslation:col.name }}<spark-attribute-description [description]=\"col.description\" /></th>\n }\n <th style=\"width: 80px\"></th>\n </tr>\n </thead>\n <tbody class=\"align-middle\" cdkDropList [cdkDropListDisabled]=\"!attr.isSortable\" (cdkDropListDropped)=\"onAsDetailReorder(attr, $event)\">\n @let modalRowRenderer = (attr | asDetailRowRenderer:asDetailTypes():rendererRegistry);\n @for (row of formData()[attr.name] || []; track $index) {\n <tr cdkDrag [cdkDragDisabled]=\"!attr.isSortable\">\n @if (attr.isSortable) {\n <td class=\"text-center text-muted\" style=\"cursor: move; touch-action: none\" cdkDragHandle>\n <spark-icon name=\"grip-vertical\" />\n </td>\n }\n @for (col of (attr | asDetailColumns:asDetailTypes():rendererRegistry); track col.name; let firstCol = $first) {\n <td>\n @if (getAsDetailCellRendererComponent(col); as cellRenderer) {\n <ng-container *ngComponentOutlet=\"cellRenderer; inputs: getAsDetailCellRendererInputs(cellRenderer, row, col)\"></ng-container>\n } @else {\n {{ row | asDetailCellValue:attr:col:asDetailReferenceOptions() }}\n }\n @if (firstCol && modalRowRenderer) {\n <div class=\"spark-row-renderer\">\n <ng-container *ngComponentOutlet=\"modalRowRenderer.component; inputs: getRowRendererInputs(modalRowRenderer, row)\"></ng-container>\n </div>\n }\n </td>\n }\n <td class=\"text-nowrap\">\n @if (attr | canEditDetailRow:asDetailPermissions()) {\n <button type=\"button\" class=\"btn btn-sm btn-outline-secondary me-1\" (click)=\"editArrayItem(attr, $index)\">\n <spark-icon name=\"pencil\" />\n </button>\n }\n @if (attr | canDeleteDetailRow:asDetailPermissions()) {\n <button type=\"button\" class=\"btn btn-sm btn-outline-danger\" (click)=\"removeArrayItem(attr, $index)\">\n <spark-icon name=\"trash\" />\n </button>\n }\n </td>\n </tr>\n } @empty {\n <tr>\n <td [attr.colspan]=\"(attr | asDetailColumns:asDetailTypes():rendererRegistry).length + (attr.isSortable ? 2 : 1)\" class=\"text-center text-muted\">\n {{ 'common.noItemsFound' | t }}\n </td>\n </tr>\n }\n </tbody>\n </bs-table>\n @for (err of rowLifecycleErrorsFor(attr.name); track $index) {\n <div class=\"text-danger small mt-1\">{{ err.errorMessage | resolveTranslation }}</div>\n }\n @if (attr | canCreateDetailRow:asDetailPermissions()) {\n <button type=\"button\" [color]=\"colors.primary\" class=\"w-100 rounded-0\" (click)=\"addArrayItem(attr)\">\n <spark-icon name=\"plus\" /> {{ 'common.add' | t }}\n </button>\n }\n } @else if (attr.dataType === 'AsDetail') {\n <bs-input-group>\n <input\n type=\"text\"\n [id]=\"attr.name\"\n [value]=\"attr | asDetailDisplayValue:formData():asDetailTypes()\"\n readonly\n [class.is-invalid]=\"hasError(attr.name)\">\n <button\n type=\"button\"\n bsInputGroupBtn\n [color]=\"colors.secondary\"\n (click)=\"openAsDetailEditor(attr)\">\n <spark-icon name=\"pencil\" />\n </button>\n </bs-input-group>\n } @else if (getEditRendererComponent(attr); as editComp) {\n <ng-container *ngComponentOutlet=\"editComp; inputs: getEditRendererInputs(editComp, attr)\"></ng-container>\n } @else if (attr.dataType === 'MultiLineString') {\n <textarea\n [id]=\"attr.name\"\n [ngModel]=\"formData()[attr.name]\"\n (ngModelChange)=\"formData()[attr.name] = $event; onFieldChange(attr)\"\n (blur)=\"onFieldBlur(attr)\"\n [name]=\"attr.name\"\n [required]=\"attr.isRequired\"\n rows=\"6\"\n [class.is-invalid]=\"hasError(attr.name)\"></textarea>\n } @else {\n <input\n [type]=\"attr.dataType | inputType\"\n [id]=\"attr.name\"\n [ngModel]=\"formData()[attr.name]\"\n (ngModelChange)=\"formData()[attr.name] = $event; onFieldChange(attr)\"\n (blur)=\"onFieldBlur(attr)\"\n [name]=\"attr.name\"\n [required]=\"attr.isRequired\"\n [step]=\"attr.dataType === 'decimal' ? '0.01' : '1'\"\n [class.is-invalid]=\"hasError(attr.name)\">\n }\n @if (attr.name | errorForAttribute:validationErrors(); as errorMsg) {\n <div class=\"invalid-feedback d-block\">\n {{ errorMsg }}\n </div>\n }\n </div>\n </div>\n </ng-template>\n\n @if (showButtons()) {\n <div bsRow class=\"mt-4\">\n <div [md]=\"4\"></div>\n <div [md]=\"8\" class=\"d-flex justify-content-end gap-2\">\n <button type=\"button\" [color]=\"colors.secondary\" (click)=\"onCancel()\" [disabled]=\"isSaving()\">{{ 'common.cancel' | t }}</button>\n <button type=\"submit\" [color]=\"colors.primary\" [disabled]=\"isSaving()\" (click)=\"onSave()\">\n @if (isSaving()) {\n <bs-spinner class=\"me-1\" />\n }\n {{ 'common.save' | t }}\n </button>\n </div>\n </div>\n }\n </bs-grid>\n}\n\n<!-- Modal for editing AsDetail objects -->\n<bs-modal [isOpen]=\"showAsDetailModal()\" (isOpenChange)=\"!$event && closeAsDetailModal()\">\n <div *bsModal>\n <div bsModalHeader>\n <h5 class=\"modal-title\">{{ 'common.edit' | t }} {{ editingAsDetailAttr()?.label | resolveTranslation:editingAsDetailAttr()?.name }}</h5>\n </div>\n\n @if (editingAsDetailAttr(); as attr) {\n <div bsModalBody>\n <spark-po-form\n [entityType]=\"attr | asDetailType:asDetailTypes()\"\n [(formData)]=\"asDetailFormData\"\n [parentId]=\"parentId()\"\n [parentType]=\"parentType()\"\n [triggerPathPrefix]=\"attr.isArray ? null : attr.name\"\n (nestedTriggerRequested)=\"onEmbeddedTrigger(attr.name, $event)\"\n (nestedTriggerBlurred)=\"onEmbeddedTriggerBlur($event)\">\n </spark-po-form>\n </div>\n }\n\n <div bsModalFooter>\n <button type=\"button\" [color]=\"colors.secondary\" (click)=\"closeAsDetailModal()\">{{ 'common.cancel' | t }}</button>\n <button type=\"button\" [color]=\"colors.primary\" (click)=\"saveAsDetailObject()\">{{ 'common.save' | t }}</button>\n </div>\n </div>\n</bs-modal>\n</bs-form>\n",
|
|
2129
|
+
styles: [":host ::ng-deep .cdk-drag-placeholder{visibility:hidden}\n"]
|
|
2130
|
+
}]
|
|
2131
|
+
}],
|
|
2132
|
+
ctorParameters: () => [],
|
|
2133
|
+
propDecorators: {
|
|
2134
|
+
entityType: [{
|
|
2135
|
+
type: i0.Input,
|
|
2136
|
+
args: [{
|
|
2137
|
+
isSignal: true,
|
|
2138
|
+
alias: "entityType",
|
|
2139
|
+
required: false
|
|
2140
|
+
}]
|
|
2141
|
+
}],
|
|
2142
|
+
formData: [{
|
|
2143
|
+
type: i0.Input,
|
|
2144
|
+
args: [{
|
|
2145
|
+
isSignal: true,
|
|
2146
|
+
alias: "formData",
|
|
2147
|
+
required: false
|
|
2148
|
+
}]
|
|
2149
|
+
}, {
|
|
2150
|
+
type: i0.Output,
|
|
2151
|
+
args: ["formDataChange"]
|
|
2152
|
+
}],
|
|
2153
|
+
validationErrors: [{
|
|
2154
|
+
type: i0.Input,
|
|
2155
|
+
args: [{
|
|
2156
|
+
isSignal: true,
|
|
2157
|
+
alias: "validationErrors",
|
|
2158
|
+
required: false
|
|
2159
|
+
}]
|
|
2160
|
+
}],
|
|
2161
|
+
showButtons: [{
|
|
2162
|
+
type: i0.Input,
|
|
2163
|
+
args: [{
|
|
2164
|
+
isSignal: true,
|
|
2165
|
+
alias: "showButtons",
|
|
2166
|
+
required: false
|
|
2167
|
+
}]
|
|
2168
|
+
}],
|
|
2169
|
+
isSaving: [{
|
|
2170
|
+
type: i0.Input,
|
|
2171
|
+
args: [{
|
|
2172
|
+
isSignal: true,
|
|
2173
|
+
alias: "isSaving",
|
|
2174
|
+
required: false
|
|
2175
|
+
}]
|
|
2176
|
+
}],
|
|
2177
|
+
parentId: [{
|
|
2178
|
+
type: i0.Input,
|
|
2179
|
+
args: [{
|
|
2180
|
+
isSignal: true,
|
|
2181
|
+
alias: "parentId",
|
|
2182
|
+
required: false
|
|
2183
|
+
}]
|
|
2184
|
+
}],
|
|
2185
|
+
parentType: [{
|
|
2186
|
+
type: i0.Input,
|
|
2187
|
+
args: [{
|
|
2188
|
+
isSignal: true,
|
|
2189
|
+
alias: "parentType",
|
|
2190
|
+
required: false
|
|
2191
|
+
}]
|
|
2192
|
+
}],
|
|
2193
|
+
save: [{
|
|
2194
|
+
type: i0.Output,
|
|
2195
|
+
args: ["save"]
|
|
2196
|
+
}],
|
|
2197
|
+
cancel: [{
|
|
2198
|
+
type: i0.Output,
|
|
2199
|
+
args: ["cancel"]
|
|
2200
|
+
}],
|
|
2201
|
+
objectTypeId: [{
|
|
2202
|
+
type: i0.Input,
|
|
2203
|
+
args: [{
|
|
2204
|
+
isSignal: true,
|
|
2205
|
+
alias: "objectTypeId",
|
|
2206
|
+
required: false
|
|
2207
|
+
}]
|
|
2208
|
+
}],
|
|
2209
|
+
objectId: [{
|
|
2210
|
+
type: i0.Input,
|
|
2211
|
+
args: [{
|
|
2212
|
+
isSignal: true,
|
|
2213
|
+
alias: "objectId",
|
|
2214
|
+
required: false
|
|
2215
|
+
}]
|
|
2216
|
+
}],
|
|
2217
|
+
triggerPathPrefix: [{
|
|
2218
|
+
type: i0.Input,
|
|
2219
|
+
args: [{
|
|
2220
|
+
isSignal: true,
|
|
2221
|
+
alias: "triggerPathPrefix",
|
|
2222
|
+
required: false
|
|
2223
|
+
}]
|
|
2224
|
+
}],
|
|
2225
|
+
nestedTriggerRequested: [{
|
|
2226
|
+
type: i0.Output,
|
|
2227
|
+
args: ["nestedTriggerRequested"]
|
|
2228
|
+
}],
|
|
2229
|
+
nestedTriggerBlurred: [{
|
|
2230
|
+
type: i0.Output,
|
|
2231
|
+
args: ["nestedTriggerBlurred"]
|
|
2232
|
+
}],
|
|
2233
|
+
refreshOverlay: [{
|
|
2234
|
+
type: i0.Input,
|
|
2235
|
+
args: [{
|
|
2236
|
+
isSignal: true,
|
|
2237
|
+
alias: "refreshOverlay",
|
|
2238
|
+
required: false
|
|
2239
|
+
}]
|
|
2240
|
+
}, {
|
|
2241
|
+
type: i0.Output,
|
|
2242
|
+
args: ["refreshOverlayChange"]
|
|
2243
|
+
}]
|
|
2244
|
+
}
|
|
2245
|
+
});
|
|
1227
2246
|
export { SparkLookupPickerComponent, SparkPoFormComponent, SparkReferencePickerComponent };
|
|
1228
|
-
|
|
2247
|
+
|
|
2248
|
+
//# sourceMappingURL=mintplayer-ng-spark-po-form.mjs.map
|