Skip to content

Commit 69d72b5

Browse files
authored
Merge pull request #409 from CodeForPhilly/relocate-save-button
move save button to bottom right corner with validation button
2 parents ad7a8e3 + c08b73a commit 69d72b5

File tree

1 file changed

+79
-49
lines changed

1 file changed

+79
-49
lines changed

builder-frontend/src/components/project/FormEditorView.tsx

Lines changed: 79 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
import {
2-
onCleanup, onMount,
3-
createEffect, createSignal, createResource,
4-
For, Match, Show, Switch,
2+
onCleanup,
3+
onMount,
4+
createEffect,
5+
createSignal,
6+
createResource,
7+
For,
8+
Match,
9+
Show,
10+
Switch,
511
Accessor,
612
} from "solid-js";
713
import toast from "solid-toast";
@@ -11,8 +17,10 @@ import { FormEditor } from "@bpmn-io/form-js-editor";
1117
import Drawer from "@corvu/drawer"; // 'corvu/drawer'
1218

1319
import CustomFormFieldsModule from "./formJsExtensions/customFormFields";
14-
import { customKeyModule } from './formJsExtensions/customKeyDropdown/customKeyDropdownProvider';
15-
import PathOptionsService, { pathOptionsModule } from './formJsExtensions/customKeyDropdown/pathOptionsService';
20+
import { customKeyModule } from "./formJsExtensions/customKeyDropdown/customKeyDropdownProvider";
21+
import PathOptionsService, {
22+
pathOptionsModule,
23+
} from "./formJsExtensions/customKeyDropdown/pathOptionsService";
1624

1725
import { saveFormSchema, fetchFormPaths } from "../../api/screener";
1826
import { extractFormPaths } from "../../utils/formSchemaUtils";
@@ -34,7 +42,7 @@ function FormEditorView({ formSchema, setFormSchema }) {
3442
if (!screenerId) return [];
3543
const response = await fetchFormPaths(screenerId);
3644
return response.paths;
37-
}
45+
},
3846
);
3947

4048
let timeoutId;
@@ -55,7 +63,7 @@ function FormEditorView({ formSchema, setFormSchema }) {
5563
// FilterFormComponentsModule,
5664
CustomFormFieldsModule,
5765
pathOptionsModule,
58-
customKeyModule
66+
customKeyModule,
5967
],
6068
});
6169

@@ -82,10 +90,15 @@ function FormEditorView({ formSchema, setFormSchema }) {
8290

8391
// Only set key if the field supports keys and doesn't already have one set
8492
// Skip group components as they don't use keys
85-
if (field && field.id && field.type !== 'group' && field.type !== 'default') {
93+
if (
94+
field &&
95+
field.id &&
96+
field.type !== "group" &&
97+
field.type !== "default"
98+
) {
8699
// Use setTimeout to ensure the field is fully added before modifying
87100
setTimeout(() => {
88-
modeling.editFormField(field, 'key', field.id);
101+
modeling.editFormField(field, "key", field.id);
89102
}, 0);
90103
}
91104
});
@@ -104,13 +117,19 @@ function FormEditorView({ formSchema, setFormSchema }) {
104117
if (!formEditor || formPaths.loading) return;
105118

106119
const currentFormPaths: FormPath[] = formPaths() || [];
107-
const validPathSet = new Set(currentFormPaths.map((formPath: FormPath) => formPath.path));
120+
const validPathSet = new Set(
121+
currentFormPaths.map((formPath: FormPath) => formPath.path),
122+
);
108123

109-
const pathOptionsService = formEditor.get("pathOptionsService") as PathOptionsService;
124+
const pathOptionsService = formEditor.get(
125+
"pathOptionsService",
126+
) as PathOptionsService;
110127
pathOptionsService.setOptions(
111-
currentFormPaths.map(
112-
(formPath: FormPath) => ({ value: formPath.path, label: formPath.path, type: formPath.type })
113-
)
128+
currentFormPaths.map((formPath: FormPath) => ({
129+
value: formPath.path,
130+
label: formPath.path,
131+
type: formPath.type,
132+
})),
114133
);
115134

116135
// Clean up any form fields with keys that are no longer valid options
@@ -128,21 +147,22 @@ function FormEditorView({ formSchema, setFormSchema }) {
128147
field.key &&
129148
!validPathSet.has(field.key) &&
130149
field.key !== field.id &&
131-
field.type !== 'expression'
150+
field.type !== "expression"
132151
) {
133152
invalidFields.push(field.key);
134-
modeling.editFormField(field, 'key', field.id);
153+
modeling.editFormField(field, "key", field.id);
135154
}
136155
}
137156

138157
// Notify user if we reset any fields
139158
if (invalidFields.length > 0) {
140159
setIsUnsaved(true);
141160
const fieldCount = invalidFields.length;
142-
const message = fieldCount === 1
143-
? `1 field had an invalid key "${invalidFields[0]}" and was reset.`
144-
: `${fieldCount} fields had invalid keys and were reset: ${invalidFields.join(', ')}`;
145-
toast(message, { duration: 5000, icon: '⚠️' });
161+
const message =
162+
fieldCount === 1
163+
? `1 field had an invalid key "${invalidFields[0]}" and was reset.`
164+
: `${fieldCount} fields had invalid keys and were reset: ${invalidFields.join(", ")}`;
165+
toast(message, { duration: 5000, icon: "⚠️" });
146166
handleSave();
147167
}
148168
}
@@ -167,40 +187,50 @@ function FormEditorView({ formSchema, setFormSchema }) {
167187
<div class="flex-8 overflow-auto">
168188
<div class="h-full" ref={(el) => (container = el)} />
169189
</div>
170-
<div class="flex-1 border-l-4 border-l-gray-200">
171-
<div id="form-editor-save_container" class="flex flex-col p-10 gap-4 place-items-center">
172-
<Switch>
173-
<Match when={isUnsaved()}>
174-
<div onClick={handleSave} class="btn-default btn-yellow">
175-
Save
176-
</div>
177-
</Match>
178-
<Match when={isSaving()}>
179-
<div
180-
onClick={handleSave}
181-
class="btn-default btn-gray cursor-not-allowed"
182-
>
183-
Saving...
184-
</div>
185-
</Match>
186-
<Match when={!isUnsaved() && !isSaving()}>
187-
<div onClick={handleSave} class="btn-default btn-blue">
188-
Save
189-
</div>
190-
</Match>
191-
</Switch>
192-
</div>
193-
</div>
194-
<FormValidationDrawer formSchema={formSchema} expectedInputPaths={formPaths} />
190+
<FormValidationDrawer
191+
formSchema={formSchema}
192+
expectedInputPaths={formPaths}
193+
/>
194+
</div>
195+
<div id="form-editor-save_container" class="fixed bottom-20 right-5 z-40">
196+
<Switch>
197+
<Match when={isUnsaved()}>
198+
<div
199+
onClick={handleSave}
200+
class="btn-default btn-yellow shadow-[0_0_10px_rgba(0,0,0,0.4)]"
201+
>
202+
Save
203+
</div>
204+
</Match>
205+
<Match when={isSaving()}>
206+
<div
207+
onClick={handleSave}
208+
class="btn-default btn-gray cursor-not-allowed shadow-[0_0_10px_rgba(0,0,0,0.4)]"
209+
>
210+
Saving...
211+
</div>
212+
</Match>
213+
<Match when={!isUnsaved() && !isSaving()}>
214+
<div
215+
onClick={handleSave}
216+
class="btn-default btn-blue shadow-[0_0_10px_rgba(0,0,0,0.4)]"
217+
>
218+
Save
219+
</div>
220+
</Match>
221+
</Switch>
195222
</div>
196223
</>
197224
);
198225
}
199226

200-
const FormValidationDrawer = (
201-
{ formSchema, expectedInputPaths }:
202-
{formSchema: any, expectedInputPaths: Accessor<FormPath[]>}
203-
) => {
227+
const FormValidationDrawer = ({
228+
formSchema,
229+
expectedInputPaths,
230+
}: {
231+
formSchema: any;
232+
expectedInputPaths: Accessor<FormPath[]>;
233+
}) => {
204234
const formOutputs = () =>
205235
formSchema() ? extractFormPaths(formSchema()) : [];
206236

0 commit comments

Comments
 (0)