Skip to content

Commit 517f252

Browse files
renemadsenclaude
andcommitted
fix(visual-editor): load DB FieldType IDs once in container, pass to modal synchronously
The modal's field type dropdown needs DB-correct IDs for new field creation, but the previous async approach (loading inside the modal) caused race conditions and empty dropdowns. Fix: load FieldTypes from the DB once in the visual editor container component on init, pass them to the field modal via MAT_DIALOG_DATA. The modal receives dbFieldTypes synchronously in its constructor and passes them to getTranslatedTypes(), which remaps the hardcoded enum ordinals to actual DB IDs by matching on the type name string. If dbFieldTypes is empty (API not loaded yet), falls back to the hardcoded enum ordinals — preserving the original behavior. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent f456488 commit 517f252

File tree

2 files changed

+28
-32
lines changed

2 files changed

+28
-32
lines changed

eform-client/src/app/modules/eforms/eform-visual-editor/components/eform-visual-editor-elements/field/visual-editor-field-modal/visual-editor-field-modal.component.ts

Lines changed: 15 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import * as R from 'ramda';
1414
import {AuthStateService} from 'src/app/common/store';
1515
import {TranslateService} from '@ngx-translate/core';
1616
import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog';
17-
import {EFormService, TranslationRequestModel, TranslationService} from 'src/app/common/services';
17+
import {TranslationRequestModel, TranslationService} from 'src/app/common/services';
1818
import {selectCurrentUserIsAdmin} from 'src/app/state/auth/auth.selector';
1919
import {Store} from '@ngrx/store';
2020

@@ -29,7 +29,6 @@ export class VisualEditorFieldModalComponent implements OnInit {
2929
private authStore = inject(Store);
3030
private translateService = inject(TranslateService);
3131
private translationService = inject(TranslationService);
32-
private eformService = inject(EFormService);
3332
dialogRef = inject<MatDialogRef<VisualEditorFieldModalComponent>>(MatDialogRef);
3433

3534
@ViewChild('popTemplate', { static: true }) popTemplate;
@@ -39,6 +38,7 @@ export class VisualEditorFieldModalComponent implements OnInit {
3938
fieldTypes: EformVisualEditorFieldTypeModel[];
4039
appLanguages: LanguagesModel = new LanguagesModel();
4140
translationPossible = false;
41+
private dbFieldTypes: {id: number; type: string}[] = [];
4242
public selectCurrentUserIsAdmin$ = this.authStore.select(selectCurrentUserIsAdmin);
4343

4444
get languages() {
@@ -51,44 +51,26 @@ export class VisualEditorFieldModalComponent implements OnInit {
5151
}
5252

5353
setFieldTypes() {
54-
this.buildFieldTypeList(null);
54+
const db = this.dbFieldTypes.length > 0 ? this.dbFieldTypes : undefined;
55+
const allTypes = getTranslatedTypes(this.translateService, db);
5556

56-
this.eformService.getFieldTypes().subscribe(res => {
57-
if (res?.success && res.model?.length > 0) {
58-
this.buildFieldTypeList(res.model);
59-
}
60-
});
61-
}
62-
63-
private buildFieldTypeList(dbFieldTypes: {id: number; type: string}[] | null) {
64-
const allTypes = getTranslatedTypes(this.translateService, dbFieldTypes ?? undefined);
65-
66-
const adminOnlyNames = ['Audio', 'Movie', 'NumberStepper'];
67-
const fieldGroupName = 'FieldGroup';
68-
69-
let fieldGroupId: number | undefined;
70-
let adminIds: number[] = [];
71-
72-
if (dbFieldTypes) {
73-
fieldGroupId = dbFieldTypes.find(ft => ft.type === fieldGroupName)?.id;
74-
adminIds = dbFieldTypes.filter(ft => adminOnlyNames.includes(ft.type)).map(ft => ft.id);
75-
} else {
76-
fieldGroupId = EformFieldTypesEnum.FieldGroup;
77-
adminIds = [EformFieldTypesEnum.Audio, EformFieldTypesEnum.Movie, EformFieldTypesEnum.NumberStepper];
78-
}
57+
const fieldGroupId = db
58+
? db.find(ft => ft.type === 'FieldGroup')?.id ?? EformFieldTypesEnum.FieldGroup
59+
: EformFieldTypesEnum.FieldGroup;
60+
const adminOnlyIds = db
61+
? db.filter(ft => ['Audio', 'Movie', 'NumberStepper'].includes(ft.type)).map(ft => ft.id)
62+
: [EformFieldTypesEnum.Audio, EformFieldTypesEnum.Movie, EformFieldTypesEnum.NumberStepper];
7963

8064
if (this.recursionModel.fieldIsNested) {
8165
this.fieldTypes = allTypes.filter(x => x.id !== fieldGroupId);
8266
} else {
8367
this.fieldTypes = [...allTypes];
8468
}
85-
8669
this.selectCurrentUserIsAdmin$.subscribe((isAdmin) => {
8770
if (isAdmin) {
88-
this.fieldTypes = [
89-
...this.fieldTypes,
90-
...allTypes.filter(x => adminIds.includes(x.id))
91-
];
71+
this.fieldTypes = [...this.fieldTypes, ...allTypes.filter(
72+
(x) => adminOnlyIds.includes(x.id)
73+
)];
9274
}
9375
});
9476
}
@@ -123,11 +105,13 @@ export class VisualEditorFieldModalComponent implements OnInit {
123105
model?: EformVisualEditorRecursionFieldModel;
124106
appLanguages: LanguagesModel;
125107
translationPossible: boolean;
108+
dbFieldTypes?: {id: number; type: string}[];
126109
}>(MAT_DIALOG_DATA);
127110

128111
this.translationPossible = model.translationPossible;
129112
this.selectedLanguages = model.selectedLanguages;
130113
this.appLanguages = model.appLanguages;
114+
this.dbFieldTypes = model.dbFieldTypes ?? [];
131115
// this.setSelectedLanguage();
132116
if (model.model) {
133117
this.recursionModel = R.clone(model.model);

eform-client/src/app/modules/eforms/eform-visual-editor/components/eform-visual-editor-page/eform-visual-editor-container/eform-visual-editor-container.component.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
EformVisualEditorUpdateModel, LanguagesModel,
1717
} from 'src/app/common/models';
1818
import {
19+
EFormService,
1920
EformDocxReportService,
2021
EformTagService,
2122
EformVisualEditorService, TranslationService,
@@ -57,6 +58,7 @@ export class EformVisualEditorContainerComponent implements OnInit, OnDestroy {
5758
private reportService = inject(EformDocxReportService);
5859
private appSettingsStateService = inject(AppSettingsStateService);
5960
private translationService = inject(TranslationService);
61+
private eformService = inject(EFormService);
6062

6163
@ViewChild('tagsModal') tagsModal: EformsTagsComponent;
6264

@@ -83,6 +85,7 @@ export class EformVisualEditorContainerComponent implements OnInit, OnDestroy {
8385
getLanguagesSub$: Subscription;
8486
appLanguages: LanguagesModel = new LanguagesModel();
8587
translationPossible: boolean;
88+
dbFieldTypes: {id: number; type: string; description: string}[] = [];
8689
public selectCurrentUserIsAdmin$ = this.authStore.select(selectCurrentUserIsAdmin);
8790
private selectCurrentUserLocale$ = this.authStore.select(selectCurrentUserLocale);
8891

@@ -129,6 +132,15 @@ export class EformVisualEditorContainerComponent implements OnInit, OnDestroy {
129132

130133
ngOnInit(): void {
131134
this.getEnabledLanguages();
135+
this.loadDbFieldTypes();
136+
}
137+
138+
loadDbFieldTypes() {
139+
this.eformService.getFieldTypes().subscribe(res => {
140+
if (res?.success && res.model) {
141+
this.dbFieldTypes = res.model;
142+
}
143+
});
132144
}
133145

134146
getReportHeaders(templateId: number) {
@@ -320,7 +332,7 @@ export class EformVisualEditorContainerComponent implements OnInit, OnDestroy {
320332
showFieldModal(model?: EformVisualEditorRecursionFieldModel) {
321333
this.visualEditorFieldModalComponentAfterClosedSub$ = this.dialog.open(VisualEditorFieldModalComponent,
322334
// eslint-disable-next-line max-len
323-
{...dialogConfigHelper(this.overlay, {model: model, selectedLanguages: this.selectedLanguages, appLanguages: this.appLanguages, translationPossible: this.translationPossible}), minWidth: 600})
335+
{...dialogConfigHelper(this.overlay, {model: model, selectedLanguages: this.selectedLanguages, appLanguages: this.appLanguages, translationPossible: this.translationPossible, dbFieldTypes: this.dbFieldTypes}), minWidth: 600})
324336
.afterClosed()
325337
.subscribe(data => data.result ? (data.create ? this.onFieldCreate(data.model) : this.onFieldUpdate(data.model)) : undefined);
326338
}

0 commit comments

Comments
 (0)