@masterteam/form-builder 0.0.1 → 0.0.3
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/assets/form-builder.css +2 -4
- package/assets/i18n/ar.json +2 -0
- package/assets/i18n/en.json +2 -0
- package/fesm2022/masterteam-form-builder.mjs +1908 -0
- package/fesm2022/masterteam-form-builder.mjs.map +1 -0
- package/package.json +16 -16
- package/types/masterteam-form-builder.d.ts +297 -0
- package/.angular/cache/21.0.2/ng-packagr/db70d8f07b5a2d2d1c3124ca92e8d56d14fb894dce4d4867ba7c0db29ba913a3 +0 -1
- package/.angular/cache/21.0.2/ng-packagr/tsbuildinfo/masterteam-form-builder.tsbuildinfo +0 -1
- package/BACKEND_API_SPEC.md +0 -338
- package/angular.json +0 -26
- package/ng-package.json +0 -13
- package/src/lib/fb-field-conditions/condition-constants.ts +0 -262
- package/src/lib/fb-field-conditions/fb-field-conditions.html +0 -35
- package/src/lib/fb-field-conditions/fb-field-conditions.ts +0 -123
- package/src/lib/fb-field-form/fb-field-form.html +0 -59
- package/src/lib/fb-field-form/fb-field-form.ts +0 -249
- package/src/lib/fb-preview-form/fb-preview-form.html +0 -31
- package/src/lib/fb-preview-form/fb-preview-form.ts +0 -142
- package/src/lib/fb-section/fb-section.html +0 -130
- package/src/lib/fb-section/fb-section.ts +0 -204
- package/src/lib/fb-section-form/fb-section-form.html +0 -38
- package/src/lib/fb-section-form/fb-section-form.ts +0 -128
- package/src/lib/form-builder.html +0 -112
- package/src/lib/form-builder.model.ts +0 -60
- package/src/lib/form-builder.scss +0 -20
- package/src/lib/form-builder.ts +0 -208
- package/src/public-api.ts +0 -6
- package/src/store/form-builder/api.model.ts +0 -13
- package/src/store/form-builder/form-builder.actions.ts +0 -98
- package/src/store/form-builder/form-builder.facade.ts +0 -194
- package/src/store/form-builder/form-builder.model.ts +0 -112
- package/src/store/form-builder/form-builder.state.ts +0 -575
- package/src/store/form-builder/index.ts +0 -5
- package/tsconfig.json +0 -31
|
@@ -1,575 +0,0 @@
|
|
|
1
|
-
import { HttpClient } from '@angular/common/http';
|
|
2
|
-
import { inject, Injectable } from '@angular/core';
|
|
3
|
-
import { Action, Selector, State, StateContext } from '@ngxs/store';
|
|
4
|
-
import {
|
|
5
|
-
CrudStateBase,
|
|
6
|
-
handleApiRequest,
|
|
7
|
-
Response,
|
|
8
|
-
} from '@masterteam/components';
|
|
9
|
-
|
|
10
|
-
import {
|
|
11
|
-
FormBuilderActionKey,
|
|
12
|
-
FormBuilderStateModel,
|
|
13
|
-
FormConfiguration,
|
|
14
|
-
FormField,
|
|
15
|
-
FormSection,
|
|
16
|
-
} from './form-builder.model';
|
|
17
|
-
import {
|
|
18
|
-
AddField,
|
|
19
|
-
AddSection,
|
|
20
|
-
DeleteField,
|
|
21
|
-
DeleteSection,
|
|
22
|
-
GetFormConfiguration,
|
|
23
|
-
MoveField,
|
|
24
|
-
ResetFormBuilderState,
|
|
25
|
-
ResetFormConfiguration,
|
|
26
|
-
SetModuleInfo,
|
|
27
|
-
UpdateField,
|
|
28
|
-
UpdateSection,
|
|
29
|
-
} from './form-builder.actions';
|
|
30
|
-
|
|
31
|
-
// Default State
|
|
32
|
-
const DEFAULT_STATE: FormBuilderStateModel = {
|
|
33
|
-
// Module configuration
|
|
34
|
-
moduleType: null,
|
|
35
|
-
moduleId: null,
|
|
36
|
-
parentModuleType: null,
|
|
37
|
-
parentModuleId: null,
|
|
38
|
-
parentPath: '',
|
|
39
|
-
|
|
40
|
-
// Form data
|
|
41
|
-
formConfiguration: null,
|
|
42
|
-
|
|
43
|
-
// Loading state (from LoadingStateShape)
|
|
44
|
-
loadingActive: [],
|
|
45
|
-
errors: {},
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
@State<FormBuilderStateModel>({
|
|
49
|
-
name: 'formBuilder',
|
|
50
|
-
defaults: DEFAULT_STATE,
|
|
51
|
-
})
|
|
52
|
-
@Injectable()
|
|
53
|
-
export class FormBuilderState extends CrudStateBase<
|
|
54
|
-
FormSection,
|
|
55
|
-
FormBuilderStateModel,
|
|
56
|
-
FormBuilderActionKey
|
|
57
|
-
> {
|
|
58
|
-
private http = inject(HttpClient);
|
|
59
|
-
private baseUrl = 'formConfigurations';
|
|
60
|
-
|
|
61
|
-
// ============================================================================
|
|
62
|
-
// Helpers
|
|
63
|
-
// ============================================================================
|
|
64
|
-
|
|
65
|
-
private getApiPath(state: FormBuilderStateModel): string {
|
|
66
|
-
const { parentPath, moduleType, moduleId } = state;
|
|
67
|
-
return `${this.baseUrl}${parentPath}/${moduleType}/${moduleId}`;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// ============================================================================
|
|
71
|
-
// Selectors
|
|
72
|
-
// ============================================================================
|
|
73
|
-
|
|
74
|
-
@Selector()
|
|
75
|
-
static getState(state: FormBuilderStateModel): FormBuilderStateModel {
|
|
76
|
-
return state ?? DEFAULT_STATE;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
@Selector()
|
|
80
|
-
static getFormConfiguration(
|
|
81
|
-
state: FormBuilderStateModel,
|
|
82
|
-
): FormConfiguration | null {
|
|
83
|
-
return state?.formConfiguration ?? null;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
@Selector()
|
|
87
|
-
static getSections(state: FormBuilderStateModel): FormSection[] {
|
|
88
|
-
return state?.formConfiguration?.sections ?? [];
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
@Selector()
|
|
92
|
-
static getModuleType(state: FormBuilderStateModel): string | null {
|
|
93
|
-
return state?.moduleType ?? null;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
@Selector()
|
|
97
|
-
static getModuleId(state: FormBuilderStateModel): string | number | null {
|
|
98
|
-
return state?.moduleId ?? null;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// ============================================================================
|
|
102
|
-
// Module Configuration Actions
|
|
103
|
-
// ============================================================================
|
|
104
|
-
|
|
105
|
-
@Action(SetModuleInfo)
|
|
106
|
-
setModuleInfo(
|
|
107
|
-
ctx: StateContext<FormBuilderStateModel>,
|
|
108
|
-
action: SetModuleInfo,
|
|
109
|
-
) {
|
|
110
|
-
let parentPath = '';
|
|
111
|
-
if (action.parentModuleType && action.parentModuleId) {
|
|
112
|
-
parentPath = `/${action.parentModuleType}/${action.parentModuleId}`;
|
|
113
|
-
} else if (action.parentPath) {
|
|
114
|
-
parentPath = action.parentPath;
|
|
115
|
-
}
|
|
116
|
-
ctx.patchState({
|
|
117
|
-
moduleType: action.moduleType,
|
|
118
|
-
moduleId: action.moduleId,
|
|
119
|
-
parentModuleType: action.parentModuleType ?? null,
|
|
120
|
-
parentModuleId: action.parentModuleId ?? null,
|
|
121
|
-
parentPath: parentPath ?? '',
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
@Action(ResetFormBuilderState)
|
|
126
|
-
resetState(ctx: StateContext<FormBuilderStateModel>) {
|
|
127
|
-
ctx.setState(DEFAULT_STATE);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
// ============================================================================
|
|
131
|
-
// Form Configuration Actions
|
|
132
|
-
// ============================================================================
|
|
133
|
-
|
|
134
|
-
@Action(GetFormConfiguration)
|
|
135
|
-
getFormConfiguration(ctx: StateContext<FormBuilderStateModel>) {
|
|
136
|
-
const state = ctx.getState();
|
|
137
|
-
const apiPath = this.getApiPath(state);
|
|
138
|
-
const req$ = this.http.get<Response<FormConfiguration>>(apiPath);
|
|
139
|
-
|
|
140
|
-
return this.load(ctx, {
|
|
141
|
-
key: FormBuilderActionKey.GetFormConfiguration,
|
|
142
|
-
request$: req$,
|
|
143
|
-
updateState: (_state, data) => ({
|
|
144
|
-
formConfiguration: data ?? null,
|
|
145
|
-
}),
|
|
146
|
-
});
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
@Action(ResetFormConfiguration)
|
|
150
|
-
resetFormConfiguration(ctx: StateContext<FormBuilderStateModel>) {
|
|
151
|
-
const state = ctx.getState();
|
|
152
|
-
const apiPath = `${this.getApiPath(state)}/reset`;
|
|
153
|
-
const req$ = this.http.delete<Response<FormConfiguration>>(apiPath);
|
|
154
|
-
|
|
155
|
-
return handleApiRequest({
|
|
156
|
-
ctx,
|
|
157
|
-
key: FormBuilderActionKey.ResetFormConfiguration,
|
|
158
|
-
request$: req$,
|
|
159
|
-
onSuccess: (res, _currentState) => ({
|
|
160
|
-
formConfiguration: res.data ?? null,
|
|
161
|
-
}),
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
// ============================================================================
|
|
166
|
-
// Section Actions
|
|
167
|
-
// ============================================================================
|
|
168
|
-
|
|
169
|
-
@Action(AddSection)
|
|
170
|
-
addSection(ctx: StateContext<FormBuilderStateModel>, action: AddSection) {
|
|
171
|
-
const state = ctx.getState();
|
|
172
|
-
const apiPath = `${this.getApiPath(state)}/sections`;
|
|
173
|
-
const req$ = this.http.post<Response<FormSection>>(apiPath, action.payload);
|
|
174
|
-
|
|
175
|
-
return handleApiRequest({
|
|
176
|
-
ctx,
|
|
177
|
-
key: FormBuilderActionKey.AddSection,
|
|
178
|
-
request$: req$,
|
|
179
|
-
onSuccess: (res, currentState) => {
|
|
180
|
-
const sections = this.adapter.addOne(
|
|
181
|
-
currentState.formConfiguration?.sections ?? [],
|
|
182
|
-
res.data,
|
|
183
|
-
);
|
|
184
|
-
return {
|
|
185
|
-
formConfiguration: {
|
|
186
|
-
...currentState.formConfiguration!,
|
|
187
|
-
sections,
|
|
188
|
-
},
|
|
189
|
-
};
|
|
190
|
-
},
|
|
191
|
-
});
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
@Action(UpdateSection)
|
|
195
|
-
updateSection(
|
|
196
|
-
ctx: StateContext<FormBuilderStateModel>,
|
|
197
|
-
action: UpdateSection,
|
|
198
|
-
) {
|
|
199
|
-
const state = ctx.getState();
|
|
200
|
-
const apiPath = `${this.getApiPath(state)}/sections/${action.sectionId}`;
|
|
201
|
-
const req$ = this.http.put<Response<FormSection>>(apiPath, action.payload);
|
|
202
|
-
|
|
203
|
-
return handleApiRequest({
|
|
204
|
-
ctx,
|
|
205
|
-
key: FormBuilderActionKey.UpdateSection,
|
|
206
|
-
request$: req$,
|
|
207
|
-
onSuccess: (res, currentState) => {
|
|
208
|
-
const sections = this.adapter.upsertOne(
|
|
209
|
-
currentState.formConfiguration?.sections ?? [],
|
|
210
|
-
res.data,
|
|
211
|
-
'id',
|
|
212
|
-
);
|
|
213
|
-
return {
|
|
214
|
-
formConfiguration: {
|
|
215
|
-
...currentState.formConfiguration!,
|
|
216
|
-
sections,
|
|
217
|
-
},
|
|
218
|
-
};
|
|
219
|
-
},
|
|
220
|
-
});
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
@Action(DeleteSection)
|
|
224
|
-
deleteSection(
|
|
225
|
-
ctx: StateContext<FormBuilderStateModel>,
|
|
226
|
-
action: DeleteSection,
|
|
227
|
-
) {
|
|
228
|
-
const state = ctx.getState();
|
|
229
|
-
const apiPath = `${this.getApiPath(state)}/sections/${action.sectionId}`;
|
|
230
|
-
const req$ = this.http.delete<Response<{ id: string }>>(apiPath);
|
|
231
|
-
|
|
232
|
-
return handleApiRequest({
|
|
233
|
-
ctx,
|
|
234
|
-
key: FormBuilderActionKey.DeleteSection,
|
|
235
|
-
request$: req$,
|
|
236
|
-
onSuccess: (res, currentState) => {
|
|
237
|
-
const sections = this.adapter.removeOne(
|
|
238
|
-
currentState.formConfiguration?.sections ?? [],
|
|
239
|
-
res.data.id,
|
|
240
|
-
'id',
|
|
241
|
-
);
|
|
242
|
-
return {
|
|
243
|
-
formConfiguration: {
|
|
244
|
-
...currentState.formConfiguration!,
|
|
245
|
-
sections,
|
|
246
|
-
},
|
|
247
|
-
};
|
|
248
|
-
},
|
|
249
|
-
});
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
// ============================================================================
|
|
253
|
-
// Field Actions
|
|
254
|
-
// ============================================================================
|
|
255
|
-
|
|
256
|
-
@Action(AddField)
|
|
257
|
-
addField(ctx: StateContext<FormBuilderStateModel>, action: AddField) {
|
|
258
|
-
const state = ctx.getState();
|
|
259
|
-
const apiPath = `${this.getApiPath(state)}/sections/${action.sectionId}/fields`;
|
|
260
|
-
const req$ = this.http.post<Response<FormField>>(apiPath, action.payload);
|
|
261
|
-
|
|
262
|
-
// Generate temp ID for optimistic update
|
|
263
|
-
const tempId = `temp_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
264
|
-
const tempField: FormField = {
|
|
265
|
-
id: tempId,
|
|
266
|
-
sectionId: action.sectionId,
|
|
267
|
-
propertyId: action.payload.propertyId,
|
|
268
|
-
width: action.payload.width,
|
|
269
|
-
order: action.payload.order ?? 0,
|
|
270
|
-
hiddenInCreation: action.payload.hiddenInCreation,
|
|
271
|
-
_pending: true,
|
|
272
|
-
};
|
|
273
|
-
|
|
274
|
-
// Optimistically add the temp field
|
|
275
|
-
const sectionsWithTemp = (state.formConfiguration?.sections ?? []).map(
|
|
276
|
-
(section) => {
|
|
277
|
-
if (section.id === action.sectionId) {
|
|
278
|
-
const fields = [...section.fields];
|
|
279
|
-
const insertIndex = action.payload.order ?? fields.length;
|
|
280
|
-
fields.splice(insertIndex, 0, tempField);
|
|
281
|
-
return { ...section, fields };
|
|
282
|
-
}
|
|
283
|
-
return section;
|
|
284
|
-
},
|
|
285
|
-
);
|
|
286
|
-
ctx.patchState({
|
|
287
|
-
formConfiguration: {
|
|
288
|
-
...state.formConfiguration!,
|
|
289
|
-
sections: sectionsWithTemp,
|
|
290
|
-
},
|
|
291
|
-
});
|
|
292
|
-
|
|
293
|
-
return handleApiRequest({
|
|
294
|
-
ctx,
|
|
295
|
-
key: FormBuilderActionKey.AddField,
|
|
296
|
-
request$: req$,
|
|
297
|
-
onSuccess: (res, currentState) => {
|
|
298
|
-
const newField = res.data;
|
|
299
|
-
// Replace temp field with real field
|
|
300
|
-
const sections = (currentState.formConfiguration?.sections ?? []).map(
|
|
301
|
-
(section) => {
|
|
302
|
-
if (section.id === action.sectionId) {
|
|
303
|
-
return {
|
|
304
|
-
...section,
|
|
305
|
-
fields: section.fields.map((f) =>
|
|
306
|
-
f.id === tempId ? newField : f,
|
|
307
|
-
),
|
|
308
|
-
};
|
|
309
|
-
}
|
|
310
|
-
return section;
|
|
311
|
-
},
|
|
312
|
-
);
|
|
313
|
-
return {
|
|
314
|
-
formConfiguration: {
|
|
315
|
-
...currentState.formConfiguration!,
|
|
316
|
-
sections,
|
|
317
|
-
},
|
|
318
|
-
};
|
|
319
|
-
},
|
|
320
|
-
onError: (_error, currentState) => {
|
|
321
|
-
// Remove temp field on error
|
|
322
|
-
const sections = (currentState.formConfiguration?.sections ?? []).map(
|
|
323
|
-
(section) => {
|
|
324
|
-
if (section.id === action.sectionId) {
|
|
325
|
-
return {
|
|
326
|
-
...section,
|
|
327
|
-
fields: section.fields.filter((f) => f.id !== tempId),
|
|
328
|
-
};
|
|
329
|
-
}
|
|
330
|
-
return section;
|
|
331
|
-
},
|
|
332
|
-
);
|
|
333
|
-
return {
|
|
334
|
-
formConfiguration: {
|
|
335
|
-
...currentState.formConfiguration!,
|
|
336
|
-
sections,
|
|
337
|
-
},
|
|
338
|
-
};
|
|
339
|
-
},
|
|
340
|
-
});
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
@Action(UpdateField)
|
|
344
|
-
updateField(ctx: StateContext<FormBuilderStateModel>, action: UpdateField) {
|
|
345
|
-
const state = ctx.getState();
|
|
346
|
-
const apiPath = `${this.getApiPath(state)}/sections/${action.sectionId}/fields/${action.fieldId}`;
|
|
347
|
-
const req$ = this.http.put<Response<FormField>>(apiPath, action.payload);
|
|
348
|
-
|
|
349
|
-
// Apply optimistic update for order changes
|
|
350
|
-
if (action.payload.order !== undefined) {
|
|
351
|
-
const newOrder = action.payload.order;
|
|
352
|
-
const sections = (state.formConfiguration?.sections ?? []).map(
|
|
353
|
-
(section) => {
|
|
354
|
-
if (section.id === action.sectionId) {
|
|
355
|
-
const fields = [...section.fields];
|
|
356
|
-
const currentIndex = fields.findIndex(
|
|
357
|
-
(f) => f.id === action.fieldId,
|
|
358
|
-
);
|
|
359
|
-
if (currentIndex !== -1) {
|
|
360
|
-
const [movedField] = fields.splice(currentIndex, 1);
|
|
361
|
-
fields.splice(newOrder, 0, movedField);
|
|
362
|
-
}
|
|
363
|
-
return { ...section, fields };
|
|
364
|
-
}
|
|
365
|
-
return section;
|
|
366
|
-
},
|
|
367
|
-
);
|
|
368
|
-
ctx.patchState({
|
|
369
|
-
formConfiguration: {
|
|
370
|
-
...state.formConfiguration!,
|
|
371
|
-
sections,
|
|
372
|
-
},
|
|
373
|
-
});
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
return handleApiRequest({
|
|
377
|
-
ctx,
|
|
378
|
-
key: FormBuilderActionKey.UpdateField,
|
|
379
|
-
request$: req$,
|
|
380
|
-
onSuccess: (res, currentState) => {
|
|
381
|
-
const updatedField = res.data;
|
|
382
|
-
const sections = (currentState.formConfiguration?.sections ?? []).map(
|
|
383
|
-
(section) => {
|
|
384
|
-
if (section.id === action.sectionId) {
|
|
385
|
-
// Update the field and sort by order
|
|
386
|
-
const updatedFields = section.fields.map((f) =>
|
|
387
|
-
f.id === updatedField.id ? updatedField : f,
|
|
388
|
-
);
|
|
389
|
-
return {
|
|
390
|
-
...section,
|
|
391
|
-
fields: updatedFields.sort((a, b) => a.order - b.order),
|
|
392
|
-
};
|
|
393
|
-
}
|
|
394
|
-
return section;
|
|
395
|
-
},
|
|
396
|
-
);
|
|
397
|
-
return {
|
|
398
|
-
formConfiguration: {
|
|
399
|
-
...currentState.formConfiguration!,
|
|
400
|
-
sections,
|
|
401
|
-
},
|
|
402
|
-
};
|
|
403
|
-
},
|
|
404
|
-
onError: (_error, _currentState) => {
|
|
405
|
-
// Revert optimistic update on error - reload original state
|
|
406
|
-
if (action.payload.order !== undefined) {
|
|
407
|
-
return {
|
|
408
|
-
formConfiguration: state.formConfiguration,
|
|
409
|
-
};
|
|
410
|
-
}
|
|
411
|
-
return {};
|
|
412
|
-
},
|
|
413
|
-
});
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
@Action(DeleteField)
|
|
417
|
-
deleteField(ctx: StateContext<FormBuilderStateModel>, action: DeleteField) {
|
|
418
|
-
const state = ctx.getState();
|
|
419
|
-
const apiPath = `${this.getApiPath(state)}/sections/${action.sectionId}/fields/${action.fieldId}`;
|
|
420
|
-
const req$ =
|
|
421
|
-
this.http.delete<Response<{ id: string; sectionId: string }>>(apiPath);
|
|
422
|
-
|
|
423
|
-
// Optimistically mark field as deleting
|
|
424
|
-
const sectionsWithDeleting = (state.formConfiguration?.sections ?? []).map(
|
|
425
|
-
(section) => {
|
|
426
|
-
if (section.id === action.sectionId) {
|
|
427
|
-
return {
|
|
428
|
-
...section,
|
|
429
|
-
fields: section.fields.map((f) =>
|
|
430
|
-
f.id === action.fieldId ? { ...f, _deleting: true } : f,
|
|
431
|
-
),
|
|
432
|
-
};
|
|
433
|
-
}
|
|
434
|
-
return section;
|
|
435
|
-
},
|
|
436
|
-
);
|
|
437
|
-
ctx.patchState({
|
|
438
|
-
formConfiguration: {
|
|
439
|
-
...state.formConfiguration!,
|
|
440
|
-
sections: sectionsWithDeleting,
|
|
441
|
-
},
|
|
442
|
-
});
|
|
443
|
-
|
|
444
|
-
return handleApiRequest({
|
|
445
|
-
ctx,
|
|
446
|
-
key: FormBuilderActionKey.DeleteField,
|
|
447
|
-
request$: req$,
|
|
448
|
-
onSuccess: (res, currentState) => {
|
|
449
|
-
const { id: deletedId, sectionId } = res.data;
|
|
450
|
-
const sections = (currentState.formConfiguration?.sections ?? []).map(
|
|
451
|
-
(section) => {
|
|
452
|
-
if (section.id === sectionId) {
|
|
453
|
-
return {
|
|
454
|
-
...section,
|
|
455
|
-
fields: section.fields.filter((f) => f.id !== deletedId),
|
|
456
|
-
};
|
|
457
|
-
}
|
|
458
|
-
return section;
|
|
459
|
-
},
|
|
460
|
-
);
|
|
461
|
-
return {
|
|
462
|
-
formConfiguration: {
|
|
463
|
-
...currentState.formConfiguration!,
|
|
464
|
-
sections,
|
|
465
|
-
},
|
|
466
|
-
};
|
|
467
|
-
},
|
|
468
|
-
onError: (_error, currentState) => {
|
|
469
|
-
// Remove _deleting flag on error
|
|
470
|
-
const sections = (currentState.formConfiguration?.sections ?? []).map(
|
|
471
|
-
(section) => {
|
|
472
|
-
if (section.id === action.sectionId) {
|
|
473
|
-
return {
|
|
474
|
-
...section,
|
|
475
|
-
fields: section.fields.map((f) =>
|
|
476
|
-
f.id === action.fieldId ? { ...f, _deleting: false } : f,
|
|
477
|
-
),
|
|
478
|
-
};
|
|
479
|
-
}
|
|
480
|
-
return section;
|
|
481
|
-
},
|
|
482
|
-
);
|
|
483
|
-
return {
|
|
484
|
-
formConfiguration: {
|
|
485
|
-
...currentState.formConfiguration!,
|
|
486
|
-
sections,
|
|
487
|
-
},
|
|
488
|
-
};
|
|
489
|
-
},
|
|
490
|
-
});
|
|
491
|
-
}
|
|
492
|
-
|
|
493
|
-
@Action(MoveField)
|
|
494
|
-
moveField(ctx: StateContext<FormBuilderStateModel>, action: MoveField) {
|
|
495
|
-
const state = ctx.getState();
|
|
496
|
-
const apiPath = `${this.getApiPath(state)}/sections/${action.sectionId}/fields/${action.fieldId}/move`;
|
|
497
|
-
const req$ = this.http.put<Response<FormField>>(apiPath, action.payload);
|
|
498
|
-
|
|
499
|
-
// Apply optimistic update - move field immediately
|
|
500
|
-
const sourceSectionId = action.sectionId;
|
|
501
|
-
const targetSectionId = action.payload.targetSectionId;
|
|
502
|
-
const targetOrder = action.payload.order ?? 0;
|
|
503
|
-
|
|
504
|
-
let movedFieldData: FormField | null = null;
|
|
505
|
-
const optimisticSections = (state.formConfiguration?.sections ?? []).map(
|
|
506
|
-
(section) => {
|
|
507
|
-
if (section.id === sourceSectionId) {
|
|
508
|
-
const fieldToMove = section.fields.find(
|
|
509
|
-
(f) => f.id === action.fieldId,
|
|
510
|
-
);
|
|
511
|
-
if (fieldToMove) {
|
|
512
|
-
movedFieldData = { ...fieldToMove, order: targetOrder };
|
|
513
|
-
}
|
|
514
|
-
return {
|
|
515
|
-
...section,
|
|
516
|
-
fields: section.fields.filter((f) => f.id !== action.fieldId),
|
|
517
|
-
};
|
|
518
|
-
}
|
|
519
|
-
return section;
|
|
520
|
-
},
|
|
521
|
-
);
|
|
522
|
-
|
|
523
|
-
// Add to target section
|
|
524
|
-
const sectionsWithMoved = optimisticSections.map((section) => {
|
|
525
|
-
if (section.id === targetSectionId && movedFieldData) {
|
|
526
|
-
const fields = [...section.fields];
|
|
527
|
-
fields.splice(targetOrder, 0, movedFieldData);
|
|
528
|
-
return { ...section, fields };
|
|
529
|
-
}
|
|
530
|
-
return section;
|
|
531
|
-
});
|
|
532
|
-
|
|
533
|
-
ctx.patchState({
|
|
534
|
-
formConfiguration: {
|
|
535
|
-
...state.formConfiguration!,
|
|
536
|
-
sections: sectionsWithMoved,
|
|
537
|
-
},
|
|
538
|
-
});
|
|
539
|
-
|
|
540
|
-
return handleApiRequest({
|
|
541
|
-
ctx,
|
|
542
|
-
key: FormBuilderActionKey.MoveField,
|
|
543
|
-
request$: req$,
|
|
544
|
-
onSuccess: (res, currentState) => {
|
|
545
|
-
const movedField = res.data;
|
|
546
|
-
const sections = (currentState.formConfiguration?.sections ?? []).map(
|
|
547
|
-
(section) => {
|
|
548
|
-
// Update the moved field with server response
|
|
549
|
-
if (section.id === targetSectionId) {
|
|
550
|
-
return {
|
|
551
|
-
...section,
|
|
552
|
-
fields: section.fields
|
|
553
|
-
.map((f) => (f.id === movedField.id ? movedField : f))
|
|
554
|
-
.sort((a, b) => a.order - b.order),
|
|
555
|
-
};
|
|
556
|
-
}
|
|
557
|
-
return section;
|
|
558
|
-
},
|
|
559
|
-
);
|
|
560
|
-
return {
|
|
561
|
-
formConfiguration: {
|
|
562
|
-
...currentState.formConfiguration!,
|
|
563
|
-
sections,
|
|
564
|
-
},
|
|
565
|
-
};
|
|
566
|
-
},
|
|
567
|
-
onError: (_error, _currentState) => {
|
|
568
|
-
// Revert optimistic update on error
|
|
569
|
-
return {
|
|
570
|
-
formConfiguration: state.formConfiguration,
|
|
571
|
-
};
|
|
572
|
-
},
|
|
573
|
-
});
|
|
574
|
-
}
|
|
575
|
-
}
|
package/tsconfig.json
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"extends": "../../../tsconfig.json",
|
|
3
|
-
"compilerOptions": {
|
|
4
|
-
"paths": {
|
|
5
|
-
"@masterteam/components": [
|
|
6
|
-
"../../../dist/masterteam/components"
|
|
7
|
-
],
|
|
8
|
-
"@masterteam/components/*": [
|
|
9
|
-
"../../../dist/masterteam/components/*"
|
|
10
|
-
],
|
|
11
|
-
"@masterteam/forms": [
|
|
12
|
-
"../../../dist/masterteam/forms"
|
|
13
|
-
],
|
|
14
|
-
"@masterteam/forms/*": [
|
|
15
|
-
"../../../dist/masterteam/forms/*"
|
|
16
|
-
],
|
|
17
|
-
"@masterteam/icons": [
|
|
18
|
-
"../../../dist/masterteam/icons"
|
|
19
|
-
],
|
|
20
|
-
"@masterteam/properties": [
|
|
21
|
-
"../../../dist/masterteam/properties"
|
|
22
|
-
]
|
|
23
|
-
}
|
|
24
|
-
},
|
|
25
|
-
"angularCompilerOptions": {
|
|
26
|
-
"compilationMode": "partial"
|
|
27
|
-
},
|
|
28
|
-
"exclude": [
|
|
29
|
-
"node_modules"
|
|
30
|
-
]
|
|
31
|
-
}
|