@plusscommunities/pluss-feature-builder-web-c 1.0.7 → 1.0.9-beta.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.
Files changed (119) hide show
  1. package/dist/{index.cjs.js → index.js} +3803 -3504
  2. package/dist/index.js.map +1 -0
  3. package/package.json +20 -27
  4. package/.babelrc +0 -4
  5. package/rollup.config.js +0 -69
  6. package/src/actions/featureBuilderStringsActions.js +0 -88
  7. package/src/actions/featureDefinitionsIndex.js +0 -258
  8. package/src/actions/formActions.js +0 -301
  9. package/src/actions/index.js +0 -12
  10. package/src/actions/listingActions.js +0 -352
  11. package/src/actions/wizardActions.js +0 -228
  12. package/src/components/ActivityCardExample.jsx +0 -86
  13. package/src/components/ActivityCardExample.module.css +0 -130
  14. package/src/components/BackgroundLoader.jsx +0 -33
  15. package/src/components/BackgroundLoader.module.css +0 -46
  16. package/src/components/BaseFieldConfig.jsx +0 -305
  17. package/src/components/BaseFieldConfig.module.css +0 -42
  18. package/src/components/CenteredContainer.jsx +0 -29
  19. package/src/components/CenteredContainer.module.css +0 -171
  20. package/src/components/DeleteConfirmationPopup.jsx +0 -95
  21. package/src/components/DeleteConfirmationPopup.module.css +0 -12
  22. package/src/components/ErrorBoundary.jsx +0 -134
  23. package/src/components/ErrorBoundary.module.css +0 -77
  24. package/src/components/ErrorMessage.jsx +0 -85
  25. package/src/components/ErrorMessage.module.css +0 -116
  26. package/src/components/ExampleDisplay.jsx +0 -26
  27. package/src/components/ExampleDisplay.module.css +0 -3
  28. package/src/components/FeatureBuilderSidebar.jsx +0 -84
  29. package/src/components/FeatureBuilderSuccessPopup.jsx +0 -49
  30. package/src/components/FeatureBuilderSuccessPopup.module.css +0 -41
  31. package/src/components/FeatureBuilderWelcomePopup.jsx +0 -51
  32. package/src/components/FeatureBuilderWelcomePopup.module.css +0 -21
  33. package/src/components/FeatureListingCard.jsx +0 -104
  34. package/src/components/FeatureListingCard.module.css +0 -62
  35. package/src/components/Fields.jsx +0 -423
  36. package/src/components/Fields.module.css +0 -159
  37. package/src/components/IconLoader.jsx +0 -153
  38. package/src/components/IconLoader.module.css +0 -92
  39. package/src/components/IconSelector.jsx +0 -111
  40. package/src/components/IconSelector.module.css +0 -197
  41. package/src/components/ListingEditor.jsx +0 -405
  42. package/src/components/ListingEditor.module.css +0 -14
  43. package/src/components/ListingSuccessPopup.jsx +0 -52
  44. package/src/components/LoadingScreen.jsx +0 -54
  45. package/src/components/LoadingScreen.module.css +0 -103
  46. package/src/components/LoadingState.jsx +0 -40
  47. package/src/components/LoadingState.module.css +0 -18
  48. package/src/components/PreviewFull.js +0 -24
  49. package/src/components/PreviewFull.module.css +0 -11
  50. package/src/components/PreviewGrid.js +0 -14
  51. package/src/components/PreviewWidget.js +0 -27
  52. package/src/components/PreviewWidget.module.css +0 -15
  53. package/src/components/SidebarLayout.jsx +0 -252
  54. package/src/components/SidebarLayout.module.css +0 -71
  55. package/src/components/SkeletonLoader.jsx +0 -128
  56. package/src/components/SkeletonLoader.module.css +0 -295
  57. package/src/components/SortButtonGroup.jsx +0 -34
  58. package/src/components/SortButtonGroup.module.css +0 -51
  59. package/src/components/ToastContainer.jsx +0 -98
  60. package/src/components/ToastContainer.module.css +0 -156
  61. package/src/components/ToggleSwitch.js +0 -40
  62. package/src/components/ToggleSwitch.module.css +0 -48
  63. package/src/components/TwoColumnInput.jsx +0 -29
  64. package/src/components/TwoColumnInput.module.css +0 -32
  65. package/src/components/ViewFull.js +0 -139
  66. package/src/components/ViewFull.module.css +0 -71
  67. package/src/components/ViewWidget.js +0 -62
  68. package/src/components/ViewWidget.module.css +0 -28
  69. package/src/components/iconCategories.js +0 -135
  70. package/src/components/iconImports.js +0 -409
  71. package/src/components/index.js +0 -59
  72. package/src/components/listing/FileListItem.jsx +0 -86
  73. package/src/components/listing/GalleryDisplay.jsx +0 -330
  74. package/src/components/listing/GalleryDisplay.module.css +0 -309
  75. package/src/components/listing/ListingCTAInput.jsx +0 -82
  76. package/src/components/listing/ListingDescriptionInput.jsx +0 -73
  77. package/src/components/listing/ListingField.jsx +0 -101
  78. package/src/components/listing/ListingField.module.css +0 -106
  79. package/src/components/listing/ListingFileInput.jsx +0 -273
  80. package/src/components/listing/ListingFileInput.module.css +0 -189
  81. package/src/components/listing/ListingForm.jsx +0 -90
  82. package/src/components/listing/ListingForm.module.css +0 -38
  83. package/src/components/listing/ListingGalleryInput.jsx +0 -239
  84. package/src/components/listing/ListingGalleryInput.module.css +0 -132
  85. package/src/components/listing/ListingImageInput.jsx +0 -153
  86. package/src/components/listing/ListingTextInput.jsx +0 -72
  87. package/src/feature.config.js +0 -130
  88. package/src/helper/index.js +0 -135
  89. package/src/hooks/useFeatureDefinitionLoader.js +0 -66
  90. package/src/images/full.png +0 -0
  91. package/src/images/fullNoTitle.png +0 -0
  92. package/src/images/previewWidget.png +0 -0
  93. package/src/images/widget.png +0 -0
  94. package/src/index.js +0 -38
  95. package/src/pages/CreateListingPage.jsx +0 -49
  96. package/src/pages/EditListingPage.jsx +0 -58
  97. package/src/reducers/featureBuilderReducer.js +0 -739
  98. package/src/screens/CreateListing.module.css +0 -45
  99. package/src/screens/Form.module.css +0 -744
  100. package/src/screens/FormFieldsStep.jsx +0 -626
  101. package/src/screens/FormLayoutStep.jsx +0 -405
  102. package/src/screens/FormOverviewStep.jsx +0 -389
  103. package/src/screens/ListingScreen.jsx +0 -477
  104. package/src/screens/ListingScreen.module.css +0 -333
  105. package/src/selectors/featureBuilderSelectors.js +0 -533
  106. package/src/types/index.js +0 -91
  107. package/src/utils/textUtils.js +0 -89
  108. package/src/validators/galleryValidators.js +0 -345
  109. package/src/values.config.a.js +0 -49
  110. package/src/values.config.b.js +0 -49
  111. package/src/values.config.c.js +0 -49
  112. package/src/values.config.d.js +0 -49
  113. package/src/values.config.default.js +0 -49
  114. package/src/values.config.js +0 -49
  115. package/src/webapi/featureDefinitionActions.js +0 -0
  116. package/src/webapi/featuresActions.js +0 -90
  117. package/src/webapi/helper.js +0 -4
  118. package/src/webapi/index.js +0 -12
  119. package/src/webapi/listingActions.js +0 -176
@@ -1,477 +0,0 @@
1
- import React, { useEffect, useState } from "react";
2
- import { useSelector, useDispatch } from "react-redux";
3
- import { withRouter } from "react-router-dom";
4
- import { Table } from "react-bootstrap";
5
- import { PlussCore } from "../feature.config";
6
- import {
7
- fetchListing,
8
- fetchListingSilent,
9
- deleteListing,
10
- undeleteListing,
11
- setSortBy,
12
- setShowDeleted,
13
- } from "../actions/listingActions";
14
- import { fetchFeatureDefinitions } from "../actions/featureDefinitionsIndex.js";
15
- import { capitalizeTextWithFallback } from "../utils/textUtils";
16
- import {
17
- selectSortedListings,
18
- selectActiveListings,
19
- selectDeletedListings,
20
- selectSortBy,
21
- selectShowDeleted,
22
- selectListingsIsLoading,
23
- selectListingsError,
24
- selectListingsIsInitiallyLoaded,
25
- selectListingsIsRestoring,
26
- selectDefinition,
27
- selectDefinitionIsLoading,
28
- selectDefinitionError,
29
- selectHasDefinition,
30
- } from "../selectors/featureBuilderSelectors";
31
- import {
32
- DeleteConfirmationPopup,
33
- ErrorMessage,
34
- LoadingState,
35
- FeatureBuilderSidebar,
36
- SortButtonGroup,
37
- ToggleSwitch,
38
- Header,
39
- ErrorBoundary,
40
- AddButton,
41
- } from "../components";
42
-
43
- import { values } from "../values.config.js";
44
-
45
- import styles from "./ListingScreen.module.css";
46
- import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
47
- import { faPen, faTrash } from "@fortawesome/free-solid-svg-icons";
48
-
49
- const { Button, Text } = PlussCore.Components;
50
-
51
- const ListingScreen = (props) => {
52
- const { history } = props;
53
- const dispatch = useDispatch();
54
- const auth = useSelector((state) => state.auth);
55
- const sortedListings = useSelector(selectSortedListings);
56
- const activeListings = useSelector(selectActiveListings);
57
- const deletedListings = useSelector(selectDeletedListings);
58
- const sortBy = useSelector(selectSortBy);
59
- const showDeleted = useSelector(selectShowDeleted);
60
- const isLoading = useSelector(selectListingsIsLoading);
61
- const isInitiallyLoaded = useSelector(selectListingsIsInitiallyLoaded);
62
- const error = useSelector(selectListingsError);
63
- const isRestoring = useSelector(selectListingsIsRestoring);
64
- const definition = useSelector(selectDefinition);
65
- const displayName = definition?.displayName || definition?.title || "Feature";
66
- const isDefinitionLoading = useSelector(selectDefinitionIsLoading);
67
- const definitionError = useSelector(selectDefinitionError);
68
- const hasDefinition = useSelector(selectHasDefinition);
69
-
70
- const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);
71
- const [listingToDelete, setListingToDelete] = useState(null);
72
- const [deleteMessage, setDeleteMessage] = useState("");
73
- const [isDeleting, setIsDeleting] = useState(false);
74
-
75
- // Error handling state
76
- const [actionError, setActionError] = useState("");
77
- const [showActionError, setShowActionError] = useState(false);
78
-
79
- useEffect(() => {
80
- // Always fetch feature definitions
81
- dispatch(fetchFeatureDefinitions());
82
-
83
- // Check data freshness - if no listings exist or data is stale, fetch with loading
84
- const dataNeedsRefresh =
85
- !isInitiallyLoaded ||
86
- sortedListings.length === 0 ||
87
- (sortedListings.length > 0 && !sortedListings[0].id);
88
-
89
- if (dataNeedsRefresh) {
90
- // Data is empty or invalid - show loading and fetch
91
- dispatch(fetchListing());
92
- } else {
93
- // Data exists - refresh in background silently
94
- dispatch(fetchListingSilent());
95
- }
96
- }, [dispatch, isInitiallyLoaded, sortedListings.length]);
97
-
98
- // Helper function to show action errors
99
- const showActionErrorMessage = (message) => {
100
- setActionError(message);
101
- setShowActionError(true);
102
- // Auto-hide after 5 seconds
103
- setTimeout(() => {
104
- setShowActionError(false);
105
- }, 5000);
106
- };
107
-
108
- // Smart refresh with data freshness check
109
- const handleSmartRefresh = () => {
110
- // Force fresh data load regardless of current state
111
- dispatch(fetchListing());
112
- };
113
-
114
- const handleDeleteClick = (listing) => {
115
- setListingToDelete(listing);
116
- setShowDeleteConfirm(true);
117
- setDeleteMessage("");
118
- };
119
-
120
- const handleEditClick = (listing) => {
121
- const id = listing.id || listing._id;
122
- history.push(values.routeEditListing.replace(":id", id));
123
- };
124
-
125
- const handleCreateClick = () => {
126
- history.push(values.routeCreateListing);
127
- };
128
-
129
- const handleConfirmDelete = () => {
130
- if (listingToDelete) {
131
- setIsDeleting(true);
132
- dispatch(deleteListing(listingToDelete.id))
133
- .then(() => {
134
- const title =
135
- (listingToDelete.fields &&
136
- listingToDelete.fields["mandatory-title"]) ||
137
- "Item";
138
- setDeleteMessage(
139
- `${capitalizeTextWithFallback(title, "Item")} deleted. You can restore it anytime.`,
140
- );
141
- setShowDeleteConfirm(false);
142
- setListingToDelete(null);
143
- setIsDeleting(false);
144
- // Clear message after 3 seconds
145
- setTimeout(() => setDeleteMessage(""), 3000);
146
- })
147
- .catch((error) => {
148
- const errorMessage = error.message || "Network error";
149
- showActionErrorMessage(
150
- `Can't delete listing right now. Check your internet connection and try again. (${errorMessage})`,
151
- );
152
- setShowDeleteConfirm(false);
153
- setListingToDelete(null);
154
- setIsDeleting(false);
155
- });
156
- }
157
- };
158
-
159
- const handleCancelDelete = () => {
160
- setShowDeleteConfirm(false);
161
- setListingToDelete(null);
162
- };
163
-
164
- const handleRestoreClick = (listing) => {
165
- dispatch(undeleteListing(listing.id))
166
- .then(() => {
167
- const title =
168
- (listing.fields && listing.fields["mandatory-title"]) || "Item";
169
- setDeleteMessage(
170
- `${capitalizeTextWithFallback(title, "Item")} restored and ready to use.`,
171
- );
172
- // Clear message after 3 seconds
173
- setTimeout(() => setDeleteMessage(""), 3000);
174
- })
175
- .catch((error) => {
176
- const errorMessage = error.message || "Network error";
177
- showActionErrorMessage(
178
- `Can't restore listing right now. Check your internet connection and try again. (${errorMessage})`,
179
- );
180
- });
181
- };
182
-
183
- const handleSortChange = (sortType) => {
184
- dispatch(setSortBy(sortType));
185
- };
186
-
187
- const handleToggleDeleted = (showDeleted) => {
188
- dispatch(setShowDeleted(showDeleted));
189
- };
190
-
191
- const handleShowDeletedListings = () => {
192
- dispatch(setShowDeleted(true));
193
- };
194
-
195
- const renderTableRows = () => {
196
- const source = sortedListings;
197
-
198
- return source.map((listing) => {
199
- const id = listing.id || listing._id;
200
- const title =
201
- (listing.fields && listing.fields["mandatory-title"]) || "Untitled";
202
- const modifiedAt =
203
- listing.editedAt ||
204
- listing.updatedAt ||
205
- listing.createdAt ||
206
- new Date();
207
- const isDeleted = !!listing.deletedAt;
208
-
209
- return (
210
- <tr
211
- key={id}
212
- className={isDeleted ? styles["listingScreen__row--deleted"] : ""}
213
- >
214
- <td>
215
- {new Date(modifiedAt).toLocaleDateString("en-AU", {
216
- day: "numeric",
217
- month: "short",
218
- year: "2-digit",
219
- })}
220
- </td>
221
- <td>
222
- <div className={styles.titleContainer}>
223
- <span
224
- onClick={() => handleEditClick(listing)}
225
- className={
226
- isDeleted ? styles["title--deleted"] : styles["titleLink"]
227
- }
228
- >
229
- {title}
230
- </span>
231
- {isDeleted && <span className={styles.deletedTag}>Deleted</span>}
232
- </div>
233
- </td>
234
- <td>
235
- <div className={styles.actions}>
236
- {!isDeleted && (
237
- <span
238
- onClick={() => handleEditClick(listing)}
239
- className={styles.actionIcon}
240
- title="Edit"
241
- >
242
- <FontAwesomeIcon icon={faPen} />
243
- </span>
244
- )}
245
-
246
- {!isDeleted && (
247
- <span
248
- onClick={() => handleDeleteClick(listing)}
249
- className={styles.actionIcon}
250
- title="Delete"
251
- >
252
- <FontAwesomeIcon icon={faTrash} />
253
- </span>
254
- )}
255
- {isDeleted && (
256
- <Button
257
- onClick={() => handleRestoreClick(listing)}
258
- buttonType="outlinedAction"
259
- disabled={isRestoring}
260
- narrow
261
- leftIcon={isRestoring ? "sync" : "undo"}
262
- loading={isRestoring}
263
- >
264
- {isRestoring ? "Restoring..." : "Restore"}
265
- </Button>
266
- )}
267
- </div>
268
- </td>
269
- </tr>
270
- );
271
- });
272
- };
273
-
274
- // Check for content management permission
275
- if (
276
- !PlussCore.Session.validateAccess(
277
- auth.site,
278
- values.permissionFeatureBuilderContent,
279
- auth,
280
- )
281
- ) {
282
- return (
283
- <div className="hub-wrapperContainer">
284
- <FeatureBuilderSidebar />
285
- <div className="hub-contentWrapper">
286
- <div className={styles.welcomeContainer}>
287
- <div className={styles.welcomeHeader}>
288
- <Text type="h1" className={styles.welcomeTitle}>
289
- Access Restricted
290
- </Text>
291
- <Text type="body" className={styles.welcomeSubtitle}>
292
- You don't have permission to manage feature content. Please
293
- contact your administrator if you need access.
294
- </Text>
295
- </div>
296
- </div>
297
- </div>
298
- </div>
299
- );
300
- }
301
-
302
- // Don't show full-screen loading, use skeleton states instead
303
-
304
- return (
305
- <ErrorBoundary
306
- title="Unable to load listings"
307
- message="If you continue to experience issues loading your listings, please try refreshing the page or contact support."
308
- onRetry={handleSmartRefresh}
309
- >
310
- <div className="hub-wrapperContainer">
311
- <FeatureBuilderSidebar />
312
- <div className="hub-headerContentWrapper">
313
- <Header />
314
- <div className={styles.root}>
315
- <div className={styles.header}>
316
- <div className={styles.headerText}>
317
- <Text type="h1">Manage Your {displayName} Listings</Text>
318
- <Text type="bodyLarge">
319
- View, edit, and manage all your {displayName.toLowerCase()}{" "}
320
- listings
321
- </Text>
322
- </div>
323
- {sortedListings.length > 0 && (
324
- <div className={styles.headerActions}>
325
- <div className={styles.sortSection}>
326
- <Text type="help" className={styles.uppercase}>
327
- SORT BY
328
- </Text>
329
- {SortButtonGroup && (
330
- <SortButtonGroup
331
- currentSort={sortBy}
332
- onSortChange={handleSortChange}
333
- />
334
- )}
335
- </div>
336
- <div className={styles.toggleContainer}>
337
- <Text type="body">Show deleted {displayName} listing</Text>
338
- <ToggleSwitch
339
- isActive={showDeleted}
340
- onChange={handleToggleDeleted}
341
- />
342
- </div>
343
- </div>
344
- )}
345
- </div>
346
-
347
- {/* Action errors (delete, restore, toggle) */}
348
- {showActionError && (
349
- <ErrorMessage
350
- message={actionError}
351
- variant="error"
352
- onClose={() => setShowActionError(false)}
353
- />
354
- )}
355
-
356
- {/* Success messages */}
357
- {deleteMessage && deleteMessage.includes("success") && (
358
- <ErrorMessage
359
- message={deleteMessage}
360
- variant="success"
361
- onClose={() => setDeleteMessage("")}
362
- />
363
- )}
364
-
365
- {/* General listing errors */}
366
- {error && (
367
- <ErrorMessage
368
- message={`Error loading listings: ${error}`}
369
- variant="error"
370
- />
371
- )}
372
-
373
- {!hasDefinition && !isDefinitionLoading && (
374
- <div className={styles.empty}>
375
- <div className="emptyState" />
376
- <p>
377
- No feature definition exists. Please create a feature
378
- definition first before creating listings.
379
- </p>
380
- <Button
381
- buttonType="primary"
382
- leftIcon="plus"
383
- onClick={handleCreateClick}
384
- isActive={true}
385
- >
386
- Add {displayName}
387
- </Button>
388
- </div>
389
- )}
390
-
391
- {definitionError && (
392
- <ErrorMessage
393
- message={`Error loading feature definition: ${definitionError}`}
394
- variant="error"
395
- />
396
- )}
397
-
398
- {isLoading ? (
399
- <div className={styles.loadingContainer}>
400
- <LoadingState message="Loading data..." />
401
- </div>
402
- ) : sortedListings.length > 0 ? (
403
- <Table className="plussTable" striped bordered condensed hover>
404
- <thead>
405
- <tr key="header">
406
- <th className={styles.dateColumn}>Last modified at</th>
407
- <th>Title</th>
408
- <th className={styles.actionsColumn}>Actions</th>
409
- </tr>
410
- </thead>
411
- <tbody>{renderTableRows()}</tbody>
412
- </Table>
413
- ) : hasDefinition ? (
414
- // Smart empty state logic
415
- activeListings.length === 0 &&
416
- deletedListings.length > 0 &&
417
- !showDeleted ? (
418
- <div className={styles.empty}>
419
- <div className="emptyState" />
420
- <p>
421
- You have {deletedListings.length} deleted{" "}
422
- {displayName.toLowerCase()} listing
423
- {deletedListings.length > 1 ? "s" : ""}.
424
- </p>
425
- <div className={styles.emptyActions}>
426
- <Button
427
- buttonType="primary"
428
- leftIcon="plus"
429
- onClick={handleCreateClick}
430
- className={styles.emptySecondaryButton}
431
- isActive
432
- >
433
- Add new {displayName}
434
- </Button>
435
- <Button
436
- buttonType="secondary"
437
- leftIcon="eye"
438
- onClick={handleShowDeletedListings}
439
- className={styles.emptyPrimaryButton}
440
- >
441
- Show deleted listing
442
- {deletedListings.length > 1 ? "s" : ""}
443
- </Button>
444
- </div>
445
- </div>
446
- ) : (
447
- // Regular empty state
448
- <div className={styles.empty}>
449
- <div className="emptyState" />
450
- <p>No {displayName.toLowerCase()} listings found.</p>
451
- <Button
452
- buttonType="primary"
453
- leftIcon="plus"
454
- onClick={handleCreateClick}
455
- isActive
456
- >
457
- Add {displayName}
458
- </Button>
459
- </div>
460
- )
461
- ) : null}
462
-
463
- <DeleteConfirmationPopup
464
- isOpen={showDeleteConfirm}
465
- listing={listingToDelete}
466
- onConfirm={handleConfirmDelete}
467
- onCancel={handleCancelDelete}
468
- isDeleting={isDeleting}
469
- />
470
- </div>
471
- </div>
472
- </div>
473
- </ErrorBoundary>
474
- );
475
- };
476
-
477
- export default withRouter(ListingScreen);