@plusscommunities/pluss-feature-builder-web-d 1.0.2-beta.7 → 1.0.2-beta.9
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/dist/index.cjs.js +165 -238
- package/package.json +1 -1
- package/src/actions/formActions.js +148 -148
- package/src/actions/wizardActions.js +166 -166
- package/src/components/BaseFieldConfig.jsx +3 -3
- package/src/components/FeatureBuilderSuccessPopup.jsx +9 -15
- package/src/components/FeatureBuilderSuccessPopup.module.css +1 -3
- package/src/components/Fields.jsx +31 -68
- package/src/components/ListingEditor.jsx +2 -2
- package/src/components/SidebarLayout.jsx +4 -4
- package/src/components/listing/ListingFileInput.jsx +98 -80
- package/src/components/listing/ListingFileInput.module.css +1 -4
- package/src/components/listing/ListingGalleryInput.module.css +2 -1
- package/src/images/full.png +0 -0
- package/src/images/fullNoTitle.png +0 -0
- package/src/images/previewWidget.png +0 -0
- package/src/images/widget.png +0 -0
- package/src/reducers/featureBuilderReducer.js +12 -6
- package/src/screens/FormFieldsStep.jsx +4 -67
- package/src/screens/FormLayoutStep.jsx +383 -420
- package/src/screens/FormOverviewStep.jsx +349 -349
- package/src/selectors/featureBuilderSelectors.js +1 -6
|
@@ -5,18 +5,14 @@ import { SidebarLayout } from "../components/SidebarLayout.jsx";
|
|
|
5
5
|
import { values } from "../values.config.js";
|
|
6
6
|
import { PlussCore } from "../feature.config";
|
|
7
7
|
import styles from "./Form.module.css";
|
|
8
|
-
import fieldStyles from "../components/Fields.module.css";
|
|
9
8
|
import { Field } from "../components/Fields.jsx";
|
|
10
9
|
import { iconImports } from "../components/iconImports";
|
|
11
10
|
import {
|
|
12
11
|
Text,
|
|
13
12
|
LoadingState,
|
|
14
|
-
SkeletonLoader,
|
|
15
|
-
DropdownInput,
|
|
16
13
|
Button,
|
|
17
14
|
ErrorBoundary,
|
|
18
15
|
Popup,
|
|
19
|
-
CenteredContainer,
|
|
20
16
|
} from "../components";
|
|
21
17
|
|
|
22
18
|
import ToastContainer from "../components/ToastContainer.jsx";
|
|
@@ -31,7 +27,6 @@ import {
|
|
|
31
27
|
selectIsEditMode,
|
|
32
28
|
selectIsStepValid,
|
|
33
29
|
selectStepErrors,
|
|
34
|
-
selectCurrentStep,
|
|
35
30
|
selectFormIsSubmitting,
|
|
36
31
|
selectFormSubmitError,
|
|
37
32
|
selectFormSubmitSuccess,
|
|
@@ -122,28 +117,20 @@ const FormFieldsStepInner = (props) => {
|
|
|
122
117
|
},
|
|
123
118
|
];
|
|
124
119
|
|
|
125
|
-
// Use custom hook to handle definition loading
|
|
126
120
|
const { definition, definitionIsLoading, reloadDefinition } =
|
|
127
121
|
useFeatureDefinitionLoader();
|
|
128
122
|
|
|
129
|
-
// Get form state for display name
|
|
130
123
|
const formDisplayName = useSelector(selectFormDisplayName);
|
|
131
124
|
|
|
132
|
-
// Get wizard state
|
|
133
125
|
const isCreateMode = useSelector(selectIsCreateMode);
|
|
134
126
|
const isEditMode = useSelector(selectIsEditMode);
|
|
135
|
-
|
|
136
|
-
// Get validation state
|
|
137
127
|
const isStepValid = useSelector(selectIsStepValid("fields"));
|
|
138
128
|
const stepErrors = useSelector(selectStepErrors("fields"));
|
|
139
129
|
const showWarnings = !isStepValid && Object.keys(stepErrors).length > 0;
|
|
140
|
-
|
|
141
|
-
// Get submission state
|
|
142
130
|
const isSubmitting = useSelector(selectFormIsSubmitting);
|
|
143
131
|
const submitError = useSelector(selectFormSubmitError);
|
|
144
132
|
const submitSuccess = useSelector(selectFormSubmitSuccess);
|
|
145
133
|
|
|
146
|
-
// Toast management functions
|
|
147
134
|
const addToast = (type, message) => {
|
|
148
135
|
const id = Date.now();
|
|
149
136
|
setToasts((prev) => [...prev, { id, type, message, isVisible: true }]);
|
|
@@ -153,9 +140,6 @@ const FormFieldsStepInner = (props) => {
|
|
|
153
140
|
setToasts((prev) => prev.filter((toast) => toast.id !== id));
|
|
154
141
|
};
|
|
155
142
|
|
|
156
|
-
// Note: Removed automatic redirect after successful save in edit mode
|
|
157
|
-
// User should stay on the current step until they manually navigate
|
|
158
|
-
|
|
159
143
|
// Handle successful submission with optimistic update and redirect
|
|
160
144
|
React.useEffect(() => {
|
|
161
145
|
if (submitSuccess && !isSubmitting) {
|
|
@@ -163,14 +147,11 @@ const FormFieldsStepInner = (props) => {
|
|
|
163
147
|
addToast("success", "Changes saved");
|
|
164
148
|
dispatch(clearFormSubmissionState());
|
|
165
149
|
} else {
|
|
166
|
-
// In create mode, show success toast and redirect immediately
|
|
167
150
|
addToast("success", "Feature created successfully");
|
|
168
|
-
|
|
169
|
-
// Clear submission state and redirect to overview step
|
|
170
151
|
dispatch(clearFormSubmissionState());
|
|
171
152
|
setTimeout(() => {
|
|
172
153
|
history.push(values.routeFormOverviewStep);
|
|
173
|
-
}, 1000);
|
|
154
|
+
}, 1000);
|
|
174
155
|
}
|
|
175
156
|
}
|
|
176
157
|
}, [submitSuccess, isEditMode, isSubmitting, dispatch, history]);
|
|
@@ -185,7 +166,6 @@ const FormFieldsStepInner = (props) => {
|
|
|
185
166
|
}
|
|
186
167
|
}, [submitError]);
|
|
187
168
|
|
|
188
|
-
// Scroll to top when validation errors appear
|
|
189
169
|
useEffect(() => {
|
|
190
170
|
if (showWarnings) {
|
|
191
171
|
// Scroll to top of form to show validation errors
|
|
@@ -193,29 +173,18 @@ const FormFieldsStepInner = (props) => {
|
|
|
193
173
|
}
|
|
194
174
|
}, [showWarnings]);
|
|
195
175
|
|
|
196
|
-
// Error boundary handlers
|
|
197
176
|
const handleRefresh = () => {
|
|
198
|
-
// Refresh current step data
|
|
199
177
|
dispatch(validateAndUpdateStep("fields"));
|
|
200
178
|
};
|
|
201
179
|
|
|
202
|
-
const handleBack = () => {
|
|
203
|
-
// Go to overview step
|
|
204
|
-
history.push(values.routeFormOverviewStep);
|
|
205
|
-
};
|
|
206
|
-
|
|
207
180
|
useEffect(() => {
|
|
208
|
-
// Set current step when component mounts
|
|
209
181
|
dispatch(setCurrentStepAndSave("fields"));
|
|
210
182
|
}, [dispatch]);
|
|
211
183
|
|
|
212
|
-
// Add effect to handle definition loading and validation in edit mode
|
|
213
|
-
// ADD THIS EFFECT: Hydrate form data from definition on refresh
|
|
214
184
|
useEffect(() => {
|
|
215
185
|
if (definition && !definitionIsLoading && isFormInitial) {
|
|
216
186
|
dispatch(setInitialValues(definition));
|
|
217
187
|
|
|
218
|
-
// In edit mode, trigger validation after setting initial values
|
|
219
188
|
if (isEditMode) {
|
|
220
189
|
setTimeout(() => {
|
|
221
190
|
dispatch(validateAndUpdateStep("fields"));
|
|
@@ -226,9 +195,7 @@ const FormFieldsStepInner = (props) => {
|
|
|
226
195
|
|
|
227
196
|
useEffect(() => {
|
|
228
197
|
// In edit mode, trigger validation when definition is available
|
|
229
|
-
// Note: The new effect above handles the data population, this handles re-validation
|
|
230
198
|
if (isEditMode && definition && !definitionIsLoading && !isFormInitial) {
|
|
231
|
-
// Only validate if form is NOT initial (meaning it has data)
|
|
232
199
|
setTimeout(() => {
|
|
233
200
|
dispatch(validateAndUpdateStep("fields"));
|
|
234
201
|
}, 100);
|
|
@@ -237,16 +204,16 @@ const FormFieldsStepInner = (props) => {
|
|
|
237
204
|
|
|
238
205
|
function handleAddField(fieldType) {
|
|
239
206
|
dispatch(addField(fieldType));
|
|
240
|
-
setShowFieldSelector(false);
|
|
207
|
+
setShowFieldSelector(false);
|
|
241
208
|
}
|
|
242
209
|
|
|
243
210
|
function handleOpenFieldSelector() {
|
|
244
|
-
setReplacingFieldIndex(null);
|
|
211
|
+
setReplacingFieldIndex(null);
|
|
245
212
|
setShowFieldSelector(true);
|
|
246
213
|
}
|
|
247
214
|
|
|
248
215
|
function handleCloseFieldSelector() {
|
|
249
|
-
setReplacingFieldIndex(null);
|
|
216
|
+
setReplacingFieldIndex(null);
|
|
250
217
|
setShowFieldSelector(false);
|
|
251
218
|
}
|
|
252
219
|
|
|
@@ -255,7 +222,6 @@ const FormFieldsStepInner = (props) => {
|
|
|
255
222
|
}
|
|
256
223
|
|
|
257
224
|
function handleReplaceField(fieldIndex) {
|
|
258
|
-
// Store the field index to replace and open the field selector
|
|
259
225
|
setReplacingFieldIndex(fieldIndex);
|
|
260
226
|
setShowFieldSelector(true);
|
|
261
227
|
}
|
|
@@ -263,82 +229,55 @@ const FormFieldsStepInner = (props) => {
|
|
|
263
229
|
function handleAddReplacementField(fieldType) {
|
|
264
230
|
const fieldIndex = replacingFieldIndex;
|
|
265
231
|
if (fieldIndex !== null) {
|
|
266
|
-
// Delete the current field at this index
|
|
267
232
|
const currentField = allFields[fieldIndex];
|
|
268
233
|
if (currentField && !currentField.isMandatory) {
|
|
269
234
|
dispatch(deleteField(currentField.id));
|
|
270
235
|
}
|
|
271
|
-
|
|
272
|
-
// Add the new field
|
|
273
236
|
dispatch(addField(fieldType));
|
|
274
|
-
|
|
275
|
-
// Reset replacement state
|
|
276
237
|
setReplacingFieldIndex(null);
|
|
277
238
|
setShowFieldSelector(false);
|
|
278
239
|
}
|
|
279
240
|
}
|
|
280
241
|
|
|
281
242
|
function handleNext() {
|
|
282
|
-
// Validate before proceeding
|
|
283
243
|
const validationResult = dispatch(validateAndUpdateStep("fields"));
|
|
284
|
-
|
|
285
|
-
// If validation passes, navigate to next step
|
|
286
244
|
if (validationResult?.isValid) {
|
|
287
|
-
// Clear form submission state when changing steps
|
|
288
245
|
dispatch(clearFormSubmissionState());
|
|
289
|
-
|
|
290
246
|
if (isCreateMode) {
|
|
291
247
|
history.push(values.routeFormLayoutStep);
|
|
292
248
|
} else {
|
|
293
|
-
// In edit mode, navigate directly
|
|
294
249
|
history.push(values.routeFormLayoutStep);
|
|
295
250
|
}
|
|
296
251
|
}
|
|
297
252
|
// If validation fails, scroll to top to show error summary
|
|
298
253
|
else {
|
|
299
|
-
// Scroll to top of form to show validation errors
|
|
300
254
|
window.scrollTo({ top: 0, behavior: "smooth" });
|
|
301
255
|
}
|
|
302
256
|
}
|
|
303
257
|
|
|
304
258
|
function handlePrevious() {
|
|
305
|
-
// Clear form submission state when changing steps
|
|
306
259
|
dispatch(clearFormSubmissionState());
|
|
307
|
-
|
|
308
260
|
if (isCreateMode) {
|
|
309
261
|
history.push(values.routeFormOverviewStep);
|
|
310
262
|
} else {
|
|
311
|
-
// In edit mode, go back to overview screen
|
|
312
263
|
history.push(values.routeFormOverviewStep);
|
|
313
264
|
}
|
|
314
265
|
}
|
|
315
266
|
|
|
316
267
|
function handleSaveStep() {
|
|
317
|
-
// Validate before saving in edit mode
|
|
318
268
|
const validationResult = dispatch(validateAndUpdateStep("fields"));
|
|
319
|
-
|
|
320
|
-
// If validation passes, save the entire form
|
|
321
269
|
if (validationResult?.isValid) {
|
|
322
270
|
dispatch(submitForm());
|
|
323
271
|
}
|
|
324
272
|
// If validation fails, scroll to top to show error summary
|
|
325
273
|
else {
|
|
326
|
-
// Scroll to top of form to show validation errors
|
|
327
274
|
window.scrollTo({ top: 0, behavior: "smooth" });
|
|
328
275
|
}
|
|
329
276
|
}
|
|
330
277
|
|
|
331
|
-
// Get all fields in unified list (base + custom)
|
|
332
278
|
const allFields = fields || [];
|
|
333
|
-
|
|
334
|
-
// Create sorted copy for rendering
|
|
335
279
|
const sortedFields = allFields.slice().sort((a, b) => a.order - b.order);
|
|
336
280
|
|
|
337
|
-
// Filter description fields for summary demo
|
|
338
|
-
const descriptionFields = allFields.filter(
|
|
339
|
-
(field) => field.type === "description",
|
|
340
|
-
);
|
|
341
|
-
|
|
342
281
|
// Check for definition management permission
|
|
343
282
|
if (
|
|
344
283
|
!PlussCore.Session.validateAccess(
|
|
@@ -665,11 +604,9 @@ const useField = (id) => {
|
|
|
665
604
|
}
|
|
666
605
|
|
|
667
606
|
function setUseAsSummary(value) {
|
|
668
|
-
// When setting a field as summary, use the new action to ensure only one field is selected
|
|
669
607
|
if (value) {
|
|
670
608
|
dispatch(setSummaryField(id));
|
|
671
609
|
} else {
|
|
672
|
-
// When unsetting, use regular update to unset this specific field
|
|
673
610
|
const updatedField = { values: { ...values, useAsSummary: false } };
|
|
674
611
|
dispatch(updateFieldValuesById(id, updatedField));
|
|
675
612
|
}
|