@masterteam/form-builder 0.0.1 → 0.0.2
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/.angular/cache/21.0.2/ng-packagr/db70d8f07b5a2d2d1c3124ca92e8d56d14fb894dce4d4867ba7c0db29ba913a3 +1 -1
- package/.angular/cache/21.0.2/ng-packagr/tsbuildinfo/masterteam-form-builder.tsbuildinfo +1 -1
- package/assets/i18n/ar.json +2 -0
- package/assets/i18n/en.json +2 -0
- package/package.json +2 -2
- package/src/lib/fb-field-form/fb-field-form.ts +4 -3
- package/src/lib/fb-preview-form/fb-preview-form.ts +22 -17
- package/src/lib/fb-section/fb-section.ts +10 -3
- package/src/lib/form-builder.html +83 -29
- package/src/lib/form-builder.model.ts +2 -35
- package/src/lib/form-builder.ts +21 -21
- package/src/store/form-builder/form-builder.actions.ts +15 -0
- package/src/store/form-builder/form-builder.facade.ts +13 -0
- package/src/store/form-builder/form-builder.model.ts +35 -0
- package/src/store/form-builder/form-builder.state.ts +97 -4
package/assets/i18n/ar.json
CHANGED
package/assets/i18n/en.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@masterteam/form-builder",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"directory": ".",
|
|
6
6
|
"linkDirectory": false,
|
|
@@ -21,8 +21,8 @@
|
|
|
21
21
|
"tailwindcss-primeui": "^0.6.1",
|
|
22
22
|
"tslib": "^2.8.1",
|
|
23
23
|
"@masterteam/properties": "^0.0.26",
|
|
24
|
-
"@masterteam/components": "^0.0.75",
|
|
25
24
|
"@masterteam/forms": "^0.0.33",
|
|
25
|
+
"@masterteam/components": "^0.0.76",
|
|
26
26
|
"@masterteam/icons": "^0.0.12"
|
|
27
27
|
},
|
|
28
28
|
"sideEffects": false,
|
|
@@ -21,9 +21,9 @@ import { ConfirmationService } from '@masterteam/components/confirmation';
|
|
|
21
21
|
import type {
|
|
22
22
|
EnrichedFormField,
|
|
23
23
|
EnrichedFormSection,
|
|
24
|
-
|
|
24
|
+
FieldWidth,
|
|
25
|
+
} from '../../store/form-builder/form-builder.model';
|
|
25
26
|
import { FormBuilderFacade } from '../../store/form-builder';
|
|
26
|
-
import type { FieldWidth } from '../../store/form-builder/form-builder.model';
|
|
27
27
|
import {
|
|
28
28
|
FBFieldConditions,
|
|
29
29
|
ConditionFieldProperty,
|
|
@@ -208,7 +208,8 @@ export class FBFieldForm {
|
|
|
208
208
|
header: this.transloco.translate('formBuilder.set-conditions'),
|
|
209
209
|
styleClass: '!w-[calc(100%-25rem)] !absolute ',
|
|
210
210
|
position: 'start',
|
|
211
|
-
modal:
|
|
211
|
+
modal: true,
|
|
212
|
+
dismissible: true,
|
|
212
213
|
appendTo: '#page-content',
|
|
213
214
|
inputValues: {
|
|
214
215
|
initialFormula: this.conditionalDisplayFormula(),
|
|
@@ -13,7 +13,7 @@ import { DynamicFormConfig, DynamicFieldConfig } from '@masterteam/components';
|
|
|
13
13
|
import { Tabs } from '@masterteam/components/tabs';
|
|
14
14
|
import { ModalService } from '@masterteam/components/modal';
|
|
15
15
|
import { ModalRef } from '@masterteam/components/dialog';
|
|
16
|
-
import type { EnrichedFormSection } from '
|
|
16
|
+
import type { EnrichedFormSection } from '../../store/form-builder/form-builder.model';
|
|
17
17
|
|
|
18
18
|
type PreviewMode = 'create' | 'edit';
|
|
19
19
|
|
|
@@ -103,24 +103,29 @@ export class FBPreviewForm {
|
|
|
103
103
|
*/
|
|
104
104
|
private mapFieldType(viewType: string): string {
|
|
105
105
|
const typeMap: Record<string, string> = {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
106
|
+
User: 'select',
|
|
107
|
+
Text: 'text',
|
|
108
|
+
LongText: 'editor-field',
|
|
109
|
+
Percentage: 'slider',
|
|
110
|
+
Date: 'date',
|
|
111
|
+
Currency: 'text',
|
|
112
|
+
Number: 'number',
|
|
113
|
+
Lookup: 'select',
|
|
114
|
+
LookupMultiSelect: 'select',
|
|
115
|
+
Checkbox: 'toggle',
|
|
116
|
+
InternalModule: 'select',
|
|
117
|
+
DynamicList: 'select',
|
|
118
|
+
API: 'select',
|
|
119
|
+
Time: 'date',
|
|
120
|
+
Status: 'select',
|
|
121
|
+
Attachment: 'attachment',
|
|
122
|
+
EditableListView: 'actionableTable',
|
|
123
|
+
LookupLog: 'actionableTable',
|
|
124
|
+
LookupMatrix: 'select',
|
|
125
|
+
Location: 'select',
|
|
121
126
|
};
|
|
122
127
|
|
|
123
|
-
return typeMap[viewType
|
|
128
|
+
return typeMap[viewType] ?? 'text';
|
|
124
129
|
}
|
|
125
130
|
|
|
126
131
|
/**
|
|
@@ -7,7 +7,10 @@ import {
|
|
|
7
7
|
signal,
|
|
8
8
|
effect,
|
|
9
9
|
} from '@angular/core';
|
|
10
|
-
import {
|
|
10
|
+
import type {
|
|
11
|
+
EnrichedFormField,
|
|
12
|
+
EnrichedFormSection,
|
|
13
|
+
} from '../../store/form-builder/form-builder.model';
|
|
11
14
|
import { ConfirmationService } from '@masterteam/components/confirmation';
|
|
12
15
|
import { ModalService } from '@masterteam/components/modal';
|
|
13
16
|
import { TranslocoService } from '@jsverse/transloco';
|
|
@@ -127,7 +130,9 @@ export class FBSection {
|
|
|
127
130
|
styleClass: '!w-100 !absolute ',
|
|
128
131
|
position: 'end',
|
|
129
132
|
appendTo: '#page-content',
|
|
130
|
-
modal:
|
|
133
|
+
modal: true,
|
|
134
|
+
dismissible: true,
|
|
135
|
+
|
|
131
136
|
inputValues: {
|
|
132
137
|
sectionId: section.id,
|
|
133
138
|
initialData: section.name,
|
|
@@ -152,7 +157,9 @@ export class FBSection {
|
|
|
152
157
|
height: '20vw',
|
|
153
158
|
styleClass: '!w-100 !absolute !shadow-none',
|
|
154
159
|
position: 'end',
|
|
155
|
-
modal:
|
|
160
|
+
modal: true,
|
|
161
|
+
dismissible: true,
|
|
162
|
+
|
|
156
163
|
appendTo: '#page-content',
|
|
157
164
|
inputValues: {
|
|
158
165
|
initialData: field,
|
|
@@ -1,15 +1,33 @@
|
|
|
1
1
|
<ng-container *transloco="let t; prefix: 'formBuilder'">
|
|
2
2
|
<div class="flex gap-4 h-full w-full overflow-hidden" cdkDropListGroup>
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
3
|
+
<!-- Properties Sidebar -->
|
|
4
|
+
<mt-card
|
|
5
|
+
class="z-1 w-1/5 min-w-xs shrink-0 h-full flex flex-col overflow-hidden"
|
|
6
|
+
>
|
|
7
|
+
<ng-template #headless>
|
|
8
|
+
<!-- Header -->
|
|
9
|
+
<div class="flex items-center justify-between px-4 pt-5">
|
|
10
|
+
<h3 class="text-xl font-semibold">{{ t("form-elements") }}</h3>
|
|
11
|
+
</div>
|
|
12
12
|
|
|
13
|
+
@if (properties().length === 0) {
|
|
14
|
+
@if (isLoading()) {
|
|
15
|
+
<!-- Properties Loading Skeleton -->
|
|
16
|
+
<div class="p-4 space-y-3">
|
|
17
|
+
<p-skeleton height="2rem" styleClass="mb-4" />
|
|
18
|
+
@for (i of [1, 2, 3, 4, 5, 6]; track i) {
|
|
19
|
+
<p-skeleton height="3rem" styleClass="rounded-lg" />
|
|
20
|
+
}
|
|
21
|
+
</div>
|
|
22
|
+
} @else {
|
|
23
|
+
<!-- No Properties State -->
|
|
24
|
+
<div class="flex-1 flex items-center justify-center p-4">
|
|
25
|
+
<div class="text-center text-muted-color">
|
|
26
|
+
<p class="text-sm">{{ t("no-properties") }}</p>
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
}
|
|
30
|
+
} @else {
|
|
13
31
|
<!-- Tabs using PrimeNG -->
|
|
14
32
|
<p-tabs
|
|
15
33
|
[(value)]="activeTab"
|
|
@@ -61,9 +79,9 @@
|
|
|
61
79
|
}
|
|
62
80
|
</p-tabpanels>
|
|
63
81
|
</p-tabs>
|
|
64
|
-
|
|
65
|
-
</
|
|
66
|
-
|
|
82
|
+
}
|
|
83
|
+
</ng-template>
|
|
84
|
+
</mt-card>
|
|
67
85
|
|
|
68
86
|
<!-- Main Canvas Area -->
|
|
69
87
|
<div class="flex flex-col gap-4 flex-1 w-full h-full overflow-y-auto">
|
|
@@ -74,38 +92,74 @@
|
|
|
74
92
|
icon="layout.layout-top"
|
|
75
93
|
[label]="t('add-section')"
|
|
76
94
|
(onClick)="addSection()"
|
|
95
|
+
[disabled]="isLoading()"
|
|
77
96
|
></mt-button>
|
|
78
97
|
<mt-button
|
|
79
98
|
icon="general.eye"
|
|
80
99
|
[label]="t('preview')"
|
|
81
100
|
(onClick)="openPreview()"
|
|
101
|
+
[disabled]="isLoading()"
|
|
82
102
|
></mt-button>
|
|
83
103
|
<mt-button
|
|
84
104
|
icon="finance.credit-card-plus"
|
|
85
105
|
[label]="t('reset')"
|
|
86
106
|
(onClick)="resetFormConfiguration()"
|
|
107
|
+
[disabled]="isLoading()"
|
|
87
108
|
></mt-button>
|
|
88
109
|
</div>
|
|
89
110
|
</ng-template>
|
|
90
111
|
</mt-card>
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
112
|
+
|
|
113
|
+
@if (isLoading()) {
|
|
114
|
+
<!-- Form Loading Skeleton -->
|
|
115
|
+
@for (i of [1, 2]; track i) {
|
|
116
|
+
<mt-card>
|
|
117
|
+
<ng-template #headless>
|
|
118
|
+
<div class="p-4 space-y-4">
|
|
119
|
+
<!-- Section header skeleton -->
|
|
120
|
+
<div class="flex items-center justify-between">
|
|
121
|
+
<p-skeleton width="10rem" height="1.5rem" />
|
|
122
|
+
<div class="flex gap-2">
|
|
123
|
+
<p-skeleton width="2rem" height="2rem" shape="circle" />
|
|
124
|
+
<p-skeleton width="2rem" height="2rem" shape="circle" />
|
|
125
|
+
</div>
|
|
126
|
+
</div>
|
|
127
|
+
<!-- Fields skeleton -->
|
|
128
|
+
<div class="grid grid-cols-12 gap-4">
|
|
129
|
+
<div class="col-span-6">
|
|
130
|
+
<p-skeleton height="4rem" styleClass="rounded-lg" />
|
|
131
|
+
</div>
|
|
132
|
+
<div class="col-span-6">
|
|
133
|
+
<p-skeleton height="4rem" styleClass="rounded-lg" />
|
|
134
|
+
</div>
|
|
135
|
+
<div class="col-span-12">
|
|
136
|
+
<p-skeleton height="4rem" styleClass="rounded-lg" />
|
|
137
|
+
</div>
|
|
138
|
+
</div>
|
|
139
|
+
</div>
|
|
140
|
+
</ng-template>
|
|
141
|
+
</mt-card>
|
|
142
|
+
}
|
|
143
|
+
} @else {
|
|
144
|
+
@for (section of enrichedSections(); track section.id) {
|
|
145
|
+
<mt-fb-section
|
|
146
|
+
[section]="section"
|
|
147
|
+
[sectionsCount]="enrichedSections().length"
|
|
148
|
+
[allSections]="enrichedSections()"
|
|
149
|
+
(onFieldDrop)="drop($event)"
|
|
150
|
+
>
|
|
151
|
+
</mt-fb-section>
|
|
152
|
+
} @empty {
|
|
153
|
+
<mt-card>
|
|
154
|
+
<div class="h-27 p-4">
|
|
155
|
+
<div
|
|
156
|
+
class="flex justify-center items-center gap-4 h-full border-2 border-primary rounded-xl bg-primary-200 text-primary"
|
|
157
|
+
>
|
|
158
|
+
<span>{{ t("no-section") }}</span>
|
|
159
|
+
</div>
|
|
106
160
|
</div>
|
|
107
|
-
</
|
|
108
|
-
|
|
161
|
+
</mt-card>
|
|
162
|
+
}
|
|
109
163
|
}
|
|
110
164
|
</div>
|
|
111
165
|
</div>
|
|
@@ -3,9 +3,10 @@ import type {
|
|
|
3
3
|
FormField as BaseFormField,
|
|
4
4
|
FormSection as BaseFormSection,
|
|
5
5
|
FieldWidth,
|
|
6
|
+
PropertyItem,
|
|
6
7
|
} from '../store/form-builder/form-builder.model';
|
|
7
8
|
|
|
8
|
-
export type { FieldType, FieldWidth };
|
|
9
|
+
export type { FieldType, FieldWidth, PropertyItem };
|
|
9
10
|
|
|
10
11
|
// Re-export base types
|
|
11
12
|
export type FormField = BaseFormField;
|
|
@@ -24,37 +25,3 @@ export interface EnrichedFormField extends BaseFormField {
|
|
|
24
25
|
export interface EnrichedFormSection extends Omit<BaseFormSection, 'fields'> {
|
|
25
26
|
fields: EnrichedFormField[];
|
|
26
27
|
}
|
|
27
|
-
export interface PropertyItem {
|
|
28
|
-
id: number;
|
|
29
|
-
key: string;
|
|
30
|
-
normalizedKey: string;
|
|
31
|
-
viewType: string;
|
|
32
|
-
viewTypeLabel: string;
|
|
33
|
-
name: string | Record<string, string>;
|
|
34
|
-
description?: string;
|
|
35
|
-
defaultValue?: unknown;
|
|
36
|
-
order?: number;
|
|
37
|
-
canBeDeleted?: boolean;
|
|
38
|
-
displayOverView?: boolean;
|
|
39
|
-
enabled?: boolean;
|
|
40
|
-
formula?: unknown[];
|
|
41
|
-
isBasic?: boolean;
|
|
42
|
-
isCalculated?: boolean;
|
|
43
|
-
isConfigurable?: boolean;
|
|
44
|
-
isHiddenInCreation?: boolean;
|
|
45
|
-
isHiddenInEdition?: boolean;
|
|
46
|
-
isLive?: boolean;
|
|
47
|
-
isLog?: boolean;
|
|
48
|
-
isRequired?: boolean;
|
|
49
|
-
isSystem?: boolean;
|
|
50
|
-
isTranslatable?: boolean;
|
|
51
|
-
shownInTable?: boolean;
|
|
52
|
-
includeInSummary?: boolean;
|
|
53
|
-
dependsOn?: unknown[];
|
|
54
|
-
isFilterFormula?: boolean;
|
|
55
|
-
configuration?: Record<string, unknown>;
|
|
56
|
-
category?: string;
|
|
57
|
-
valueOnCreation?: boolean;
|
|
58
|
-
isRelated?: boolean;
|
|
59
|
-
[key: string]: unknown;
|
|
60
|
-
}
|
package/src/lib/form-builder.ts
CHANGED
|
@@ -1,26 +1,20 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Component,
|
|
3
|
-
computed,
|
|
4
|
-
inject,
|
|
5
|
-
input,
|
|
6
|
-
signal,
|
|
7
|
-
effect,
|
|
8
|
-
} from '@angular/core';
|
|
1
|
+
import { Component, computed, inject, signal, effect } from '@angular/core';
|
|
9
2
|
import { CommonModule } from '@angular/common';
|
|
10
3
|
import { FormsModule } from '@angular/forms';
|
|
11
4
|
import { TabsModule } from 'primeng/tabs';
|
|
5
|
+
import { SkeletonModule } from 'primeng/skeleton';
|
|
12
6
|
import { Button } from '@masterteam/components/button';
|
|
13
7
|
import { Card } from '@masterteam/components/card';
|
|
14
8
|
import { ModalService } from '@masterteam/components/modal';
|
|
15
9
|
import { ConfirmationService } from '@masterteam/components/confirmation';
|
|
16
10
|
import { TranslocoDirective, TranslocoService } from '@jsverse/transloco';
|
|
17
11
|
import { FBSection } from './fb-section/fb-section';
|
|
18
|
-
import {
|
|
12
|
+
import type {
|
|
19
13
|
EnrichedFormSection,
|
|
20
14
|
EnrichedFormField,
|
|
15
|
+
FieldWidth,
|
|
21
16
|
PropertyItem,
|
|
22
|
-
} from '
|
|
23
|
-
import type { FieldWidth } from '../store/form-builder/form-builder.model';
|
|
17
|
+
} from '../store/form-builder/form-builder.model';
|
|
24
18
|
import { CdkDragDrop, DragDropModule } from '@angular/cdk/drag-drop';
|
|
25
19
|
import { FBSectionForm } from './fb-section-form/fb-section-form';
|
|
26
20
|
import { FBPreviewForm } from './fb-preview-form/fb-preview-form';
|
|
@@ -33,6 +27,7 @@ import { FormBuilderFacade } from '../store/form-builder/form-builder.facade';
|
|
|
33
27
|
CommonModule,
|
|
34
28
|
FormsModule,
|
|
35
29
|
TabsModule,
|
|
30
|
+
SkeletonModule,
|
|
36
31
|
Button,
|
|
37
32
|
Card,
|
|
38
33
|
TranslocoDirective,
|
|
@@ -50,14 +45,12 @@ export class FormBuilder {
|
|
|
50
45
|
|
|
51
46
|
private dialogRef: any;
|
|
52
47
|
|
|
53
|
-
// Inputs - only properties needed from parent
|
|
54
|
-
readonly properties = input<PropertyItem[]>([]);
|
|
55
|
-
|
|
56
48
|
// Local UI state
|
|
57
49
|
readonly activeTab = signal<string>('system');
|
|
58
50
|
|
|
59
51
|
// State from facade
|
|
60
52
|
readonly sections = this.facade.sections;
|
|
53
|
+
readonly properties = this.facade.properties;
|
|
61
54
|
readonly isLoading = this.facade.isLoadingFormConfiguration;
|
|
62
55
|
readonly error = this.facade.formConfigurationError;
|
|
63
56
|
|
|
@@ -113,8 +106,8 @@ export class FormBuilder {
|
|
|
113
106
|
(p) => !usedPropertyIds.has(p.id),
|
|
114
107
|
);
|
|
115
108
|
|
|
116
|
-
const systemProps = availableProps.filter((p) => p
|
|
117
|
-
const customProps = availableProps.filter((p) => !p
|
|
109
|
+
const systemProps = availableProps.filter((p) => p['isSystem']);
|
|
110
|
+
const customProps = availableProps.filter((p) => !p['isSystem']);
|
|
118
111
|
|
|
119
112
|
if (systemProps.length > 0) {
|
|
120
113
|
tabs.push({ id: 'system', title: 'System', properties: systemProps });
|
|
@@ -142,12 +135,17 @@ export class FormBuilder {
|
|
|
142
135
|
|
|
143
136
|
if (event.previousContainer === event.container) {
|
|
144
137
|
// Reordering within the same section
|
|
145
|
-
const
|
|
138
|
+
const fields = [...(event.container.data as EnrichedFormField[])];
|
|
139
|
+
const [movedField] = fields.splice(event.previousIndex, 1);
|
|
140
|
+
fields.splice(event.currentIndex, 0, movedField);
|
|
146
141
|
|
|
147
|
-
//
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
142
|
+
// Build bulk reorder payload with new order values
|
|
143
|
+
const reorderPayload = fields.map((field, index) => ({
|
|
144
|
+
id: field.id,
|
|
145
|
+
order: index,
|
|
146
|
+
}));
|
|
147
|
+
|
|
148
|
+
this.facade.reorderFields(targetSectionId, reorderPayload);
|
|
151
149
|
} else if (event.previousContainer.id.startsWith('toolbox-')) {
|
|
152
150
|
// Adding from toolbox
|
|
153
151
|
const propertyItem = event.item.data as PropertyItem;
|
|
@@ -176,6 +174,7 @@ export class FormBuilder {
|
|
|
176
174
|
position: 'end',
|
|
177
175
|
appendTo: '#page-content',
|
|
178
176
|
modal: true,
|
|
177
|
+
dismissible: true,
|
|
179
178
|
inputValues: {
|
|
180
179
|
sectionsCount: this.sections().length,
|
|
181
180
|
},
|
|
@@ -188,6 +187,7 @@ export class FormBuilder {
|
|
|
188
187
|
styleClass: '!w-[80vw] ',
|
|
189
188
|
position: 'end',
|
|
190
189
|
modal: true,
|
|
190
|
+
dismissible: true,
|
|
191
191
|
inputValues: {
|
|
192
192
|
sections: this.enrichedSections(),
|
|
193
193
|
},
|
|
@@ -2,6 +2,8 @@ import type {
|
|
|
2
2
|
AddFieldPayload,
|
|
3
3
|
AddSectionPayload,
|
|
4
4
|
MoveFieldPayload,
|
|
5
|
+
PropertyItem,
|
|
6
|
+
ReorderFieldPayload,
|
|
5
7
|
UpdateFieldPayload,
|
|
6
8
|
UpdateSectionPayload,
|
|
7
9
|
} from './form-builder.model';
|
|
@@ -25,6 +27,11 @@ export class ResetFormBuilderState {
|
|
|
25
27
|
static readonly type = '[FormBuilder] Reset State';
|
|
26
28
|
}
|
|
27
29
|
|
|
30
|
+
export class SetProperties {
|
|
31
|
+
static readonly type = '[FormBuilder] Set Properties';
|
|
32
|
+
constructor(public properties: PropertyItem[]) {}
|
|
33
|
+
}
|
|
34
|
+
|
|
28
35
|
// ============================================================================
|
|
29
36
|
// Form Configuration Actions
|
|
30
37
|
// ============================================================================
|
|
@@ -88,6 +95,14 @@ export class DeleteField {
|
|
|
88
95
|
) {}
|
|
89
96
|
}
|
|
90
97
|
|
|
98
|
+
export class ReorderFields {
|
|
99
|
+
static readonly type = '[FormBuilder] Reorder Fields';
|
|
100
|
+
constructor(
|
|
101
|
+
public sectionId: string,
|
|
102
|
+
public payload: ReorderFieldPayload[],
|
|
103
|
+
) {}
|
|
104
|
+
}
|
|
105
|
+
|
|
91
106
|
export class MoveField {
|
|
92
107
|
static readonly type = '[FormBuilder] Move Field';
|
|
93
108
|
constructor(
|
|
@@ -6,6 +6,8 @@ import {
|
|
|
6
6
|
AddSectionPayload,
|
|
7
7
|
FormBuilderActionKey,
|
|
8
8
|
MoveFieldPayload,
|
|
9
|
+
PropertyItem,
|
|
10
|
+
ReorderFieldPayload,
|
|
9
11
|
UpdateFieldPayload,
|
|
10
12
|
UpdateSectionPayload,
|
|
11
13
|
} from './form-builder.model';
|
|
@@ -16,9 +18,11 @@ import {
|
|
|
16
18
|
DeleteSection,
|
|
17
19
|
GetFormConfiguration,
|
|
18
20
|
MoveField,
|
|
21
|
+
ReorderFields,
|
|
19
22
|
ResetFormBuilderState,
|
|
20
23
|
ResetFormConfiguration,
|
|
21
24
|
SetModuleInfo,
|
|
25
|
+
SetProperties,
|
|
22
26
|
UpdateField,
|
|
23
27
|
UpdateSection,
|
|
24
28
|
} from './form-builder.actions';
|
|
@@ -36,6 +40,7 @@ export class FormBuilderFacade {
|
|
|
36
40
|
|
|
37
41
|
readonly formConfiguration = select(FormBuilderState.getFormConfiguration);
|
|
38
42
|
readonly sections = select(FormBuilderState.getSections);
|
|
43
|
+
readonly properties = select(FormBuilderState.getProperties);
|
|
39
44
|
readonly moduleType = select(FormBuilderState.getModuleType);
|
|
40
45
|
readonly moduleId = select(FormBuilderState.getModuleId);
|
|
41
46
|
|
|
@@ -144,6 +149,10 @@ export class FormBuilderFacade {
|
|
|
144
149
|
return this.store.dispatch(new ResetFormBuilderState());
|
|
145
150
|
}
|
|
146
151
|
|
|
152
|
+
setProperties(properties: PropertyItem[]) {
|
|
153
|
+
return this.store.dispatch(new SetProperties(properties));
|
|
154
|
+
}
|
|
155
|
+
|
|
147
156
|
// ============================================================================
|
|
148
157
|
// Form Configuration Dispatchers
|
|
149
158
|
// ============================================================================
|
|
@@ -188,6 +197,10 @@ export class FormBuilderFacade {
|
|
|
188
197
|
return this.store.dispatch(new DeleteField(sectionId, fieldId));
|
|
189
198
|
}
|
|
190
199
|
|
|
200
|
+
reorderFields(sectionId: string, payload: ReorderFieldPayload[]) {
|
|
201
|
+
return this.store.dispatch(new ReorderFields(sectionId, payload));
|
|
202
|
+
}
|
|
203
|
+
|
|
191
204
|
moveField(sectionId: string, fieldId: string, payload: MoveFieldPayload) {
|
|
192
205
|
return this.store.dispatch(new MoveField(sectionId, fieldId, payload));
|
|
193
206
|
}
|
|
@@ -18,6 +18,7 @@ export enum FormBuilderActionKey {
|
|
|
18
18
|
UpdateField = 'updateField',
|
|
19
19
|
DeleteField = 'deleteField',
|
|
20
20
|
MoveField = 'moveField',
|
|
21
|
+
ReorderFields = 'reorderFields',
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
// ============================================================================
|
|
@@ -96,6 +97,37 @@ export interface MoveFieldPayload {
|
|
|
96
97
|
order?: number;
|
|
97
98
|
}
|
|
98
99
|
|
|
100
|
+
export interface ReorderFieldPayload {
|
|
101
|
+
id: string;
|
|
102
|
+
order: number;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// ============================================================================
|
|
106
|
+
// Property Item (for enrichment)
|
|
107
|
+
// ============================================================================
|
|
108
|
+
export interface PropertyItem {
|
|
109
|
+
id: number;
|
|
110
|
+
name: string | Record<string, string>;
|
|
111
|
+
viewType?: string;
|
|
112
|
+
[key: string]: any;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// ============================================================================
|
|
116
|
+
// Enriched Types (for UI display)
|
|
117
|
+
// ============================================================================
|
|
118
|
+
|
|
119
|
+
// Enriched field with UI properties (from PropertyItem)
|
|
120
|
+
export interface EnrichedFormField extends FormField {
|
|
121
|
+
name: string;
|
|
122
|
+
type: string;
|
|
123
|
+
data?: any;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Enriched section for UI display
|
|
127
|
+
export interface EnrichedFormSection extends Omit<FormSection, 'fields'> {
|
|
128
|
+
fields: EnrichedFormField[];
|
|
129
|
+
}
|
|
130
|
+
|
|
99
131
|
// ============================================================================
|
|
100
132
|
// State Model
|
|
101
133
|
// ============================================================================
|
|
@@ -109,4 +141,7 @@ export interface FormBuilderStateModel extends LoadingStateShape<FormBuilderActi
|
|
|
109
141
|
|
|
110
142
|
// Form data
|
|
111
143
|
formConfiguration: FormConfiguration | null;
|
|
144
|
+
|
|
145
|
+
// Properties for field enrichment
|
|
146
|
+
properties: PropertyItem[];
|
|
112
147
|
}
|