@plusscommunities/pluss-feature-builder-web-b 1.0.2-beta.5 → 1.0.2-beta.7

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plusscommunities/pluss-feature-builder-web-b",
3
- "version": "1.0.2-beta.5",
3
+ "version": "1.0.2-beta.7",
4
4
  "description": "Contains the feature builder extension for the pluss communities ",
5
5
  "main": "dist/index.cjs.js",
6
6
  "scripts": {
@@ -23,8 +23,7 @@ export const FEATURE_DELETE_REQUEST = `${REDUCER_PREFIX}_FEATURE_DELETE_REQUEST`
23
23
  export const FEATURE_DELETE_FAILURE = `${REDUCER_PREFIX}_FEATURE_DELETE_FAILURE`;
24
24
 
25
25
  // Wizard synchronization action types
26
- export const SYNC_WIZARD_MODE_FROM_DEFINITION =
27
- `${REDUCER_PREFIX}_SYNC_WIZARD_MODE_FROM_DEFINITION`;
26
+ export const SYNC_WIZARD_MODE_FROM_DEFINITION = `${REDUCER_PREFIX}_SYNC_WIZARD_MODE_FROM_DEFINITION`;
28
27
  export const SET_WIZARD_MODE = `${REDUCER_PREFIX}_SET_WIZARD_MODE`;
29
28
 
30
29
  function fetchFeaturesRequest() {
@@ -161,7 +160,7 @@ export function fetchFeatureDefinitions() {
161
160
  }
162
161
  } catch (err) {
163
162
  // Check if it's a 404 (feature doesn't exist)
164
- if (err.response && err.response.status === 404) {
163
+ if (err.response?.status === 404) {
165
164
  // 404: Feature doesn't exist → create mode
166
165
  dispatch(fetchFeaturesSuccess(null, "create"));
167
166
 
@@ -1,19 +1,9 @@
1
- /**
2
- * Form Actions for Feature Builder
3
- * Manages form state including title, icon, fields, layout, and submission
4
- * Handles CRUD operations for form fields and layout configuration
5
- * Coordinates with external menu updates and feature definition actions
6
- *
7
- * @namespace formActions
8
- */
9
-
10
1
  import { featureDefinitionActions } from "../webapi/featuresActions";
11
2
  import { values } from "../values.config";
12
3
  import {
13
- updateFeatureBuilderString,
14
- updateFeatureBuilderIcon,
4
+ updateFeatureBuilderString,
5
+ updateFeatureBuilderIcon,
15
6
  } from "./featureBuilderStringsActions";
16
- import { toTitleCase } from "../utils/textUtils";
17
7
 
18
8
  /**
19
9
  * @typedef {Object} FieldValues
@@ -40,20 +30,20 @@ import { toTitleCase } from "../utils/textUtils";
40
30
  */
41
31
 
42
32
  export const actionsTypes = {
43
- SET_INITIAL_VALUES: `${values.reducerKey.toUpperCase()}_SET_INITIAL_VALUES`,
44
- SET_TITLE: `${values.reducerKey.toUpperCase()}_SET_TITLE`,
45
- SET_ICON: `${values.reducerKey.toUpperCase()}_SET_ICON`,
46
- SET_DISPLAY_NAME: `${values.reducerKey.toUpperCase()}_SET_DISPLAY_NAME`,
47
- ADD_FIELD: `${values.reducerKey.toUpperCase()}_ADD_FIELD`,
48
- DELETE_FIELD: `${values.reducerKey.toUpperCase()}_DELETE_FIELD`,
49
- UPDATE_FIELD: `${values.reducerKey.toUpperCase()}_UPDATE_FIELD`,
50
- SET_LAYOUT_GRID_ICON: `${values.reducerKey.toUpperCase()}_SET_LAYOUT_GRID_ICON`,
51
- SET_LAYOUT_TYPE: `${values.reducerKey.toUpperCase()}_SET_LAYOUT_TYPE`,
52
- SUBMIT_FORM_REQUEST: `${values.reducerKey.toUpperCase()}_SUBMIT_FORM_REQUEST`,
53
- SUBMIT_FORM_SUCCESS: `${values.reducerKey.toUpperCase()}_SUBMIT_FORM_SUCCESS`,
54
- SUBMIT_FORM_FAILURE: `${values.reducerKey.toUpperCase()}_SUBMIT_FORM_FAILURE`,
55
- CLEAR_FORM_SUBMISSION_STATE: `${values.reducerKey.toUpperCase()}_CLEAR_FORM_SUBMISSION_STATE`,
56
- SET_SUMMARY_FIELD: `${values.reducerKey.toUpperCase()}_SET_SUMMARY_FIELD`,
33
+ SET_INITIAL_VALUES: `${values.reducerKey.toUpperCase()}_SET_INITIAL_VALUES`,
34
+ SET_TITLE: `${values.reducerKey.toUpperCase()}_SET_TITLE`,
35
+ SET_ICON: `${values.reducerKey.toUpperCase()}_SET_ICON`,
36
+ SET_DISPLAY_NAME: `${values.reducerKey.toUpperCase()}_SET_DISPLAY_NAME`,
37
+ ADD_FIELD: `${values.reducerKey.toUpperCase()}_ADD_FIELD`,
38
+ DELETE_FIELD: `${values.reducerKey.toUpperCase()}_DELETE_FIELD`,
39
+ UPDATE_FIELD: `${values.reducerKey.toUpperCase()}_UPDATE_FIELD`,
40
+ SET_LAYOUT_GRID_ICON: `${values.reducerKey.toUpperCase()}_SET_LAYOUT_GRID_ICON`,
41
+ SET_LAYOUT_TYPE: `${values.reducerKey.toUpperCase()}_SET_LAYOUT_TYPE`,
42
+ SUBMIT_FORM_REQUEST: `${values.reducerKey.toUpperCase()}_SUBMIT_FORM_REQUEST`,
43
+ SUBMIT_FORM_SUCCESS: `${values.reducerKey.toUpperCase()}_SUBMIT_FORM_SUCCESS`,
44
+ SUBMIT_FORM_FAILURE: `${values.reducerKey.toUpperCase()}_SUBMIT_FORM_FAILURE`,
45
+ CLEAR_FORM_SUBMISSION_STATE: `${values.reducerKey.toUpperCase()}_CLEAR_FORM_SUBMISSION_STATE`,
46
+ SET_SUMMARY_FIELD: `${values.reducerKey.toUpperCase()}_SET_SUMMARY_FIELD`,
57
47
  };
58
48
 
59
49
  /**
@@ -76,11 +66,11 @@ export const actionsTypes = {
76
66
  * }));
77
67
  */
78
68
  export const setInitialValues = (initialValues) => {
79
- return { type: actionsTypes.SET_INITIAL_VALUES, payload: initialValues };
69
+ return { type: actionsTypes.SET_INITIAL_VALUES, payload: initialValues };
80
70
  };
81
71
 
82
72
  export const setTitle = (title) => {
83
- return { type: actionsTypes.SET_TITLE, payload: title };
73
+ return { type: actionsTypes.SET_TITLE, payload: title };
84
74
  };
85
75
 
86
76
  /**
@@ -95,16 +85,16 @@ export const setTitle = (title) => {
95
85
  * dispatch(setDisplayName('Contact Information'));
96
86
  */
97
87
  export const setDisplayName = (displayName) => {
98
- return (dispatch) => {
99
- // Update menu string when display name changes (will be title cased in updateFeatureBuilderString)
100
- dispatch(updateFeatureBuilderString(displayName));
88
+ return (dispatch) => {
89
+ // Update menu string when display name changes (will be title cased in updateFeatureBuilderString)
90
+ dispatch(updateFeatureBuilderString(displayName));
101
91
 
102
- // Dispatch the actual action
103
- dispatch({
104
- type: actionsTypes.SET_DISPLAY_NAME,
105
- payload: displayName,
106
- });
107
- };
92
+ // Dispatch the actual action
93
+ dispatch({
94
+ type: actionsTypes.SET_DISPLAY_NAME,
95
+ payload: displayName,
96
+ });
97
+ };
108
98
  };
109
99
 
110
100
  /**
@@ -118,16 +108,16 @@ export const setDisplayName = (displayName) => {
118
108
  * dispatch(setIcon('fa-user'));
119
109
  */
120
110
  export const setIcon = (icon) => {
121
- return (dispatch) => {
122
- // Update menu icon when icon changes
123
- dispatch(updateFeatureBuilderIcon(icon));
111
+ return (dispatch) => {
112
+ // Update menu icon when icon changes
113
+ dispatch(updateFeatureBuilderIcon(icon));
124
114
 
125
- // Dispatch the actual action
126
- dispatch({
127
- type: actionsTypes.SET_ICON,
128
- payload: icon,
129
- });
130
- };
115
+ // Dispatch the actual action
116
+ dispatch({
117
+ type: actionsTypes.SET_ICON,
118
+ payload: icon,
119
+ });
120
+ };
131
121
  };
132
122
 
133
123
  /**
@@ -142,20 +132,20 @@ export const setIcon = (icon) => {
142
132
  * dispatch(addField('image'));
143
133
  */
144
134
  export const addField = (fieldType = "text") => {
145
- // Generate a unique ID for the new field
146
- const fieldId = `custom-field-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
147
- return {
148
- type: actionsTypes.ADD_FIELD,
149
- payload: { id: fieldId, type: fieldType },
150
- };
135
+ // Generate a unique ID for the new field
136
+ const fieldId = `custom-field-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
137
+ return {
138
+ type: actionsTypes.ADD_FIELD,
139
+ payload: { id: fieldId, type: fieldType },
140
+ };
151
141
  };
152
142
 
153
143
  export const deleteField = (id) => {
154
- return { type: actionsTypes.DELETE_FIELD, payload: id };
144
+ return { type: actionsTypes.DELETE_FIELD, payload: id };
155
145
  };
156
146
 
157
147
  export const updateFieldById = (id, updatedField) => {
158
- return { type: actionsTypes.UPDATE_FIELD, payload: { id, updatedField } };
148
+ return { type: actionsTypes.UPDATE_FIELD, payload: { id, updatedField } };
159
149
  };
160
150
 
161
151
  /**
@@ -170,31 +160,31 @@ export const updateFieldById = (id, updatedField) => {
170
160
  * dispatch(setSummaryField('field-description-123'));
171
161
  */
172
162
  export const setSummaryField = (fieldId) => {
173
- return { type: actionsTypes.SET_SUMMARY_FIELD, payload: fieldId };
163
+ return { type: actionsTypes.SET_SUMMARY_FIELD, payload: fieldId };
174
164
  };
175
165
 
176
166
  export const setGridLayoutIcon = (imageUrl) => {
177
- return { type: actionsTypes.SET_LAYOUT_GRID_ICON, payload: imageUrl };
167
+ return { type: actionsTypes.SET_LAYOUT_GRID_ICON, payload: imageUrl };
178
168
  };
179
169
 
180
170
  export const setLayoutType = (layoutType) => {
181
- return { type: actionsTypes.SET_LAYOUT_TYPE, payload: layoutType };
171
+ return { type: actionsTypes.SET_LAYOUT_TYPE, payload: layoutType };
182
172
  };
183
173
 
184
174
  const submitFormRequest = () => {
185
- return { type: actionsTypes.SUBMIT_FORM_REQUEST };
175
+ return { type: actionsTypes.SUBMIT_FORM_REQUEST };
186
176
  };
187
177
 
188
178
  const submitFormSuccess = () => {
189
- return { type: actionsTypes.SUBMIT_FORM_SUCCESS };
179
+ return { type: actionsTypes.SUBMIT_FORM_SUCCESS };
190
180
  };
191
181
 
192
182
  const submitFormFailure = (error) => {
193
- return { type: actionsTypes.SUBMIT_FORM_FAILURE, payload: error };
183
+ return { type: actionsTypes.SUBMIT_FORM_FAILURE, payload: error };
194
184
  };
195
185
 
196
186
  export const clearFormSubmissionState = () => {
197
- return { type: actionsTypes.CLEAR_FORM_SUBMISSION_STATE };
187
+ return { type: actionsTypes.CLEAR_FORM_SUBMISSION_STATE };
198
188
  };
199
189
 
200
190
  /**
@@ -205,107 +195,107 @@ export const clearFormSubmissionState = () => {
205
195
  * @throws {Error} When form validation fails or API submission encounters error
206
196
  */
207
197
  export function submitForm() {
208
- return async (dispatch, getState) => {
209
- const state = getState()[values.reducerKey];
210
- const form = state && state.form;
211
- if (!form) {
212
- dispatch(
213
- submitFormFailure(
214
- new Error(
215
- "Form data is missing. Please refresh the page and try again.",
216
- ),
217
- ),
218
- );
219
- return;
220
- }
198
+ return async (dispatch, getState) => {
199
+ const state = getState()[values.reducerKey];
200
+ const form = state?.form;
201
+ if (!form) {
202
+ dispatch(
203
+ submitFormFailure(
204
+ new Error(
205
+ "Form data is missing. Please refresh the page and try again.",
206
+ ),
207
+ ),
208
+ );
209
+ return;
210
+ }
221
211
 
222
- dispatch(submitFormRequest());
223
- try {
224
- // Get site from auth store
225
- const site = getState().auth.site;
226
- if (!site) {
227
- throw new Error(
228
- "Authentication error: Site context not found. Please refresh and login again.",
229
- );
230
- }
212
+ dispatch(submitFormRequest());
213
+ try {
214
+ // Get site from auth store
215
+ const site = getState().auth.site;
216
+ if (!site) {
217
+ throw new Error(
218
+ "Authentication error: Site context not found. Please refresh and login again.",
219
+ );
220
+ }
231
221
 
232
- // Use mode from fetch instead of checking definition ID
233
- const definitionState = state && state.definition;
234
- const mode = definitionState && definitionState.mode; // Use stored mode from fetch
235
- const definitionId = definitionState && definitionState.id;
222
+ // Use mode from fetch instead of checking definition ID
223
+ const definitionState = state?.definition;
224
+ const mode = definitionState?.mode; // Use stored mode from fetch
225
+ const definitionId = definitionState?.id;
236
226
 
237
- if (mode === "edit") {
238
- // Always update when in edit mode
239
- const updatedDefinition = {
240
- id: definitionId,
241
- site: site, // Include site from auth store
242
- featureDefinition: {
243
- // Wrap in expected structure for backend
244
- title: form.title,
245
- icon: form.icon,
246
- displayName: form.displayName,
247
- layout: form.layout,
248
- fields: form.fields,
249
- },
250
- };
251
- await featureDefinitionActions.edit(updatedDefinition, site);
252
- } else {
253
- // Always create when in create mode (or mode is undefined/null)
254
- if (!values.featureId || !site) {
255
- throw new Error(
256
- "Authentication error: Missing required context (featureId or site).",
257
- );
258
- }
259
- await featureDefinitionActions.create(
260
- values.featureId,
261
- site, // Use actual site from auth store
262
- {
263
- title: form.title,
264
- icon: form.icon,
265
- displayName: form.displayName,
266
- layout: form.layout,
267
- fields: form.fields,
268
- },
269
- );
270
- }
227
+ if (mode === "edit") {
228
+ // Always update when in edit mode
229
+ const updatedDefinition = {
230
+ id: definitionId,
231
+ site: site, // Include site from auth store
232
+ featureDefinition: {
233
+ // Wrap in expected structure for backend
234
+ title: form.title,
235
+ icon: form.icon,
236
+ displayName: form.displayName,
237
+ layout: form.layout,
238
+ fields: form.fields,
239
+ },
240
+ };
241
+ await featureDefinitionActions.edit(updatedDefinition, site);
242
+ } else {
243
+ // Always create when in create mode (or mode is undefined/null)
244
+ if (!values.featureId || !site) {
245
+ throw new Error(
246
+ "Authentication error: Missing required context (featureId or site).",
247
+ );
248
+ }
249
+ await featureDefinitionActions.create(
250
+ values.featureId,
251
+ site, // Use actual site from auth store
252
+ {
253
+ title: form.title,
254
+ icon: form.icon,
255
+ displayName: form.displayName,
256
+ layout: form.layout,
257
+ fields: form.fields,
258
+ },
259
+ );
260
+ }
271
261
 
272
- dispatch(submitFormSuccess());
273
- } catch (err) {
274
- // Handle different types of errors
275
- let errorToDisplay = err;
262
+ dispatch(submitFormSuccess());
263
+ } catch (err) {
264
+ // Handle different types of errors
265
+ let errorToDisplay = err;
276
266
 
277
- if (err.response) {
278
- // API error (400, 401, 404, 500, etc.)
279
- const { status, data } = err.response;
280
- if (status === 400 && data && data.error) {
281
- errorToDisplay = new Error(`Validation error: ${data.error}`);
282
- } else if (status === 401) {
283
- errorToDisplay = new Error(
284
- "You are not authorized to perform this action",
285
- );
286
- } else if (status === 404) {
287
- errorToDisplay = new Error("Feature definition not found");
288
- } else if (status >= 500) {
289
- errorToDisplay = new Error("Server error. Please try again later.");
290
- } else {
291
- errorToDisplay = new Error(
292
- (data && data.error) || `Request failed with status ${status}`,
293
- );
294
- }
295
- } else if (err.request) {
296
- // Network error (no response received)
297
- errorToDisplay = new Error(
298
- "Network error. Please check your connection and try again.",
299
- );
300
- } else if (err.message) {
301
- // Other JavaScript errors
302
- errorToDisplay = err;
303
- } else {
304
- // Unknown error
305
- errorToDisplay = new Error("An unexpected error occurred while saving");
306
- }
267
+ if (err.response) {
268
+ // API error (400, 401, 404, 500, etc.)
269
+ const { status, data } = err.response;
270
+ if (status === 400 && data?.error) {
271
+ errorToDisplay = new Error(`Validation error: ${data.error}`);
272
+ } else if (status === 401) {
273
+ errorToDisplay = new Error(
274
+ "You are not authorized to perform this action",
275
+ );
276
+ } else if (status === 404) {
277
+ errorToDisplay = new Error("Feature definition not found");
278
+ } else if (status >= 500) {
279
+ errorToDisplay = new Error("Server error. Please try again later.");
280
+ } else {
281
+ errorToDisplay = new Error(
282
+ data?.error || `Request failed with status ${status}`,
283
+ );
284
+ }
285
+ } else if (err.request) {
286
+ // Network error (no response received)
287
+ errorToDisplay = new Error(
288
+ "Network error. Please check your connection and try again.",
289
+ );
290
+ } else if (err.message) {
291
+ // Other JavaScript errors
292
+ errorToDisplay = err;
293
+ } else {
294
+ // Unknown error
295
+ errorToDisplay = new Error("An unexpected error occurred while saving");
296
+ }
307
297
 
308
- dispatch(submitFormFailure(errorToDisplay));
309
- }
310
- };
298
+ dispatch(submitFormFailure(errorToDisplay));
299
+ }
300
+ };
311
301
  }
@@ -212,7 +212,7 @@ export const undeleteListing = (id) => {
212
212
  const response = await webApiActions.undelete(id, site);
213
213
  // If API returns the restored listing, use it; otherwise we'll need to refetch
214
214
  const restoredListing = response.data;
215
- if (restoredListing && restoredListing.id) {
215
+ if (restoredListing?.id) {
216
216
  dispatch(undeleteListingSuccess(restoredListing));
217
217
  } else {
218
218
  // Trigger a refetch by dispatching the success with just ID, then fetch updated listings