@plusscommunities/pluss-feature-builder-web-a 1.0.2-beta.0
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/.babelrc +4 -0
- package/dist/index.cjs.js +7792 -0
- package/package.json +54 -0
- package/rollup.config.js +68 -0
- package/src/actions/featureBuilderStringsActions.js +88 -0
- package/src/actions/featureDefinitionsIndex.js +258 -0
- package/src/actions/formActions.js +311 -0
- package/src/actions/index.js +12 -0
- package/src/actions/listingActions.js +350 -0
- package/src/actions/wizardActions.js +240 -0
- package/src/components/ActivityCardExample.jsx +86 -0
- package/src/components/ActivityCardExample.module.css +130 -0
- package/src/components/BackgroundLoader.jsx +33 -0
- package/src/components/BackgroundLoader.module.css +46 -0
- package/src/components/BaseFieldConfig.jsx +305 -0
- package/src/components/BaseFieldConfig.module.css +42 -0
- package/src/components/CenteredContainer.jsx +29 -0
- package/src/components/CenteredContainer.module.css +171 -0
- package/src/components/DeleteConfirmationPopup.jsx +95 -0
- package/src/components/DeleteConfirmationPopup.module.css +12 -0
- package/src/components/ErrorBoundary.jsx +134 -0
- package/src/components/ErrorBoundary.module.css +77 -0
- package/src/components/ErrorMessage.jsx +85 -0
- package/src/components/ErrorMessage.module.css +116 -0
- package/src/components/ExampleDisplay.jsx +26 -0
- package/src/components/ExampleDisplay.module.css +3 -0
- package/src/components/FeatureBuilderSidebar.jsx +84 -0
- package/src/components/FeatureBuilderSuccessPopup.jsx +55 -0
- package/src/components/FeatureBuilderSuccessPopup.module.css +43 -0
- package/src/components/FeatureBuilderWelcomePopup.jsx +51 -0
- package/src/components/FeatureBuilderWelcomePopup.module.css +21 -0
- package/src/components/FeatureListingCard.jsx +104 -0
- package/src/components/FeatureListingCard.module.css +62 -0
- package/src/components/Fields.jsx +460 -0
- package/src/components/Fields.module.css +159 -0
- package/src/components/IconLoader.jsx +153 -0
- package/src/components/IconLoader.module.css +92 -0
- package/src/components/IconSelector.jsx +112 -0
- package/src/components/IconSelector.module.css +197 -0
- package/src/components/ListingEditor.jsx +406 -0
- package/src/components/ListingEditor.module.css +14 -0
- package/src/components/ListingSuccessPopup.jsx +52 -0
- package/src/components/LoadingScreen.jsx +54 -0
- package/src/components/LoadingScreen.module.css +103 -0
- package/src/components/LoadingState.jsx +40 -0
- package/src/components/LoadingState.module.css +18 -0
- package/src/components/PreviewFull.js +24 -0
- package/src/components/PreviewFull.module.css +11 -0
- package/src/components/PreviewGrid.js +14 -0
- package/src/components/PreviewWidget.js +27 -0
- package/src/components/PreviewWidget.module.css +15 -0
- package/src/components/SidebarLayout.jsx +292 -0
- package/src/components/SidebarLayout.module.css +145 -0
- package/src/components/SkeletonLoader.jsx +128 -0
- package/src/components/SkeletonLoader.module.css +295 -0
- package/src/components/SortButtonGroup.jsx +34 -0
- package/src/components/SortButtonGroup.module.css +51 -0
- package/src/components/ToastContainer.jsx +98 -0
- package/src/components/ToastContainer.module.css +156 -0
- package/src/components/ToggleSwitch.js +40 -0
- package/src/components/ToggleSwitch.module.css +48 -0
- package/src/components/TwoColumnInput.jsx +29 -0
- package/src/components/TwoColumnInput.module.css +32 -0
- package/src/components/ViewFull.js +139 -0
- package/src/components/ViewFull.module.css +71 -0
- package/src/components/ViewWidget.js +62 -0
- package/src/components/ViewWidget.module.css +28 -0
- package/src/components/iconCategories.js +135 -0
- package/src/components/iconImports.js +409 -0
- package/src/components/index.js +61 -0
- package/src/components/listing/FileListItem.jsx +86 -0
- package/src/components/listing/GalleryDisplay.jsx +331 -0
- package/src/components/listing/GalleryDisplay.module.css +309 -0
- package/src/components/listing/ListingCTAInput.jsx +82 -0
- package/src/components/listing/ListingDescriptionInput.jsx +73 -0
- package/src/components/listing/ListingField.jsx +101 -0
- package/src/components/listing/ListingField.module.css +106 -0
- package/src/components/listing/ListingFileInput.jsx +255 -0
- package/src/components/listing/ListingFileInput.module.css +192 -0
- package/src/components/listing/ListingForm.jsx +90 -0
- package/src/components/listing/ListingForm.module.css +38 -0
- package/src/components/listing/ListingGalleryInput.jsx +236 -0
- package/src/components/listing/ListingGalleryInput.module.css +131 -0
- package/src/components/listing/ListingImageInput.jsx +153 -0
- package/src/components/listing/ListingTextInput.jsx +72 -0
- package/src/feature.config.js +130 -0
- package/src/helper/index.js +135 -0
- package/src/hooks/useFeatureDefinitionLoader.js +62 -0
- 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/index.js +38 -0
- package/src/pages/CreateListingPage.jsx +49 -0
- package/src/pages/EditListingPage.jsx +58 -0
- package/src/reducers/featureBuilderReducer.js +744 -0
- package/src/screens/CreateListing.module.css +45 -0
- package/src/screens/Form.module.css +734 -0
- package/src/screens/FormFieldsStep.jsx +689 -0
- package/src/screens/FormLayoutStep.jsx +445 -0
- package/src/screens/FormOverviewStep.jsx +396 -0
- package/src/screens/ListingScreen.jsx +478 -0
- package/src/screens/ListingScreen.module.css +333 -0
- package/src/selectors/featureBuilderSelectors.js +529 -0
- package/src/types/index.js +91 -0
- package/src/utils/textUtils.js +89 -0
- package/src/validators/galleryValidators.js +345 -0
- package/src/values.config.a.js +49 -0
- package/src/values.config.b.js +49 -0
- package/src/values.config.c.js +49 -0
- package/src/values.config.d.js +49 -0
- package/src/values.config.js +49 -0
- package/src/webapi/featureDefinitionActions.js +0 -0
- package/src/webapi/featuresActions.js +90 -0
- package/src/webapi/helper.js +4 -0
- package/src/webapi/index.js +12 -0
- package/src/webapi/listingActions.js +176 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { PlussCore } from "../feature.config";
|
|
3
|
+
const { Components } = PlussCore;
|
|
4
|
+
const { Text } = Components;
|
|
5
|
+
import fullNoTitle from "../images/fullNoTitle.png";
|
|
6
|
+
import styles from "./PreviewFull.module.css";
|
|
7
|
+
|
|
8
|
+
const PreviewFull = ({ backgroundColor, widgetTitle, titleClassName }) => {
|
|
9
|
+
return (
|
|
10
|
+
<div className={styles.previewFull}>
|
|
11
|
+
<Text type="body" className={titleClassName}>
|
|
12
|
+
{widgetTitle}
|
|
13
|
+
</Text>
|
|
14
|
+
<img
|
|
15
|
+
className={styles.previewFull__image}
|
|
16
|
+
style={{ backgroundColor }}
|
|
17
|
+
src={fullNoTitle}
|
|
18
|
+
alt="fullNoTitle"
|
|
19
|
+
/>
|
|
20
|
+
</div>
|
|
21
|
+
);
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export default PreviewFull;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
const SVG_PATH =
|
|
4
|
+
"M12.1875 0.9375C11.1548 0.9375 9.67896 1.25977 8.7616 1.87866C7.0166 1.94275 5.82275 3.16772 5.62683 5.11047C5.50781 6.30981 5.61768 7.16858 5.68909 7.73621C5.71472 7.93396 5.74219 8.15735 5.73303 8.22327C5.71838 8.31116 5.70374 8.39905 5.69092 8.48694C5.61401 8.4906 5.54626 8.50159 5.48584 8.51807C4.71313 8.72498 4.38904 9.85474 4.73511 11.1456C4.98596 12.0813 5.51147 12.7844 6.08643 13.0005C6.38306 13.9087 6.81885 14.8114 7.36084 15.6244L3.03955 18.1274C1.16455 19.2114 0 21.2329 0 23.399V26.7188C0 27.4933 0.631714 28.125 1.40625 28.125H19.519C20.6287 29.2786 22.1832 30 23.9062 30C27.2662 30 30 27.2662 30 23.9062C30 21.2402 28.2751 18.9734 25.8856 18.1494L21.8115 15.5127C22.4158 14.7931 22.9193 13.8977 23.2397 12.9419C23.6847 12.7478 24.0765 12.2168 24.267 11.4972C24.3823 11.0669 24.4061 10.6329 24.3311 10.274C24.2377 9.80896 23.9777 9.48669 23.6224 9.39148C23.5986 9.38416 23.573 9.37866 23.5455 9.375C23.4979 9.06738 23.4174 8.76709 23.2892 8.39905C23.3734 8.42102 23.465 8.45032 23.5437 8.48145C23.703 8.54919 23.8898 8.52173 24.0234 8.4082C24.1589 8.29651 24.2194 8.1189 24.1827 7.94861C23.606 5.31006 21.6467 3.73535 18.9441 3.73535H18.5962C18.5248 3.73535 18.446 3.74084 18.371 3.74634C17.1332 1.9519 15.1355 0.9375 12.6562 0.9375H12.1875ZM12.1875 1.875H12.6562C15.5017 1.875 17.5562 3.32886 18.3984 5.89783C18.0743 5.86121 17.7393 5.90149 17.5104 6.12305C17.3309 6.29333 17.1625 6.62109 17.3749 7.19971C17.6642 7.98523 17.7667 8.45032 17.7979 9.1095C17.8052 9.27795 17.9041 9.4281 18.0524 9.505C18.2007 9.58008 18.3801 9.57092 18.5211 9.47937C18.598 9.42993 18.6383 9.42444 18.6475 9.42444C18.761 9.46289 18.9661 10.0342 18.7335 10.9039C18.5028 11.7664 18.0597 12.1307 17.9224 12.1307C17.7136 12.1252 17.5323 12.2681 17.4738 12.4658C16.6827 15.1227 14.6155 17.8125 12.1875 17.8125C9.75952 17.8125 7.69226 15.1227 6.90125 12.4658C6.84265 12.2681 6.66138 12.1307 6.45264 12.1307C6.31531 12.1307 5.87219 11.7664 5.64148 10.9039C5.4071 10.0269 5.61768 9.45374 5.72571 9.42444C5.72754 9.42444 5.76782 9.42444 5.85205 9.47937C5.99487 9.57092 6.17432 9.58008 6.32263 9.505C6.47278 9.4281 6.56799 9.27795 6.57715 9.1095C6.58813 8.86414 6.61377 8.62061 6.65588 8.38623C6.69067 8.18481 6.66321 7.95959 6.61926 7.61719C6.55151 7.09167 6.45081 6.297 6.56067 5.20386C6.70898 3.70789 7.58606 2.8125 8.91357 2.8125C9.01611 2.8125 9.11316 2.77954 9.19556 2.71912C9.83826 2.23755 11.1237 1.875 12.1875 1.875ZM18.913 4.67285H18.9459C20.9491 4.67285 22.4121 5.66528 23.0566 7.42676C22.8461 7.43042 22.6392 7.48352 22.4835 7.63367C22.3224 7.78564 22.1704 8.07312 22.3535 8.56384C22.5641 9.13879 22.6392 9.47571 22.6611 9.95361C22.6685 10.1221 22.7655 10.2722 22.9156 10.3491C23.0621 10.4224 23.2361 10.415 23.3752 10.329C23.4338 10.4608 23.4851 10.7977 23.3624 11.2555C23.2178 11.792 22.9486 12.0612 22.8735 12.0831H22.8717C22.6648 12.0831 22.4817 12.2186 22.4231 12.4182C22.0312 13.7366 21.2512 14.9469 20.3394 15.6537C20.1343 15.813 20.0958 16.1078 20.2551 16.311C20.3467 16.4319 20.4858 16.4941 20.625 16.4941C20.7257 16.4941 20.8264 16.463 20.9125 16.3971C20.9912 16.3348 21.0681 16.2653 21.145 16.1993L23.6591 17.8253C22.9193 17.8546 22.2144 18.0103 21.5643 18.2812C21.4856 18.2318 21.416 18.1732 21.3354 18.1274L17.0142 15.6244C17.5562 14.8114 17.9901 13.9087 18.2886 13.0005C18.8617 12.7844 19.389 12.0831 19.6381 11.1456C19.9841 9.85474 19.6619 8.72498 18.8892 8.51807C18.8306 8.50342 18.761 8.4906 18.6841 8.48694C18.62 7.98523 18.4918 7.51648 18.2538 6.87561C18.2483 6.8573 18.2428 6.84082 18.2373 6.82617C18.4021 6.83899 18.6676 6.90674 18.8837 6.99463C19.0466 7.06238 19.2316 7.03491 19.3652 6.92139C19.4989 6.80969 19.5593 6.63208 19.5209 6.46179C19.3799 5.81543 19.1748 5.21667 18.913 4.67285ZM9.62219 4.74609C9.28711 4.7168 8.9502 4.86877 8.75793 5.16357L8.00537 6.30432C7.86255 6.52039 7.92297 6.81152 8.13904 6.95435C8.2196 7.00745 8.3075 7.03125 8.39539 7.03125C8.54919 7.03125 8.69751 6.95801 8.78906 6.82068L9.53979 5.67993L10.2722 6.03699C11.6071 6.68701 13.0994 7.03125 14.5844 7.03125H15.7819C16.04 7.03125 16.2506 6.82068 16.2506 6.5625C16.2506 6.30432 16.04 6.09375 15.7819 6.09375H14.5844C13.2404 6.09375 11.8909 5.78247 10.6842 5.19287L9.95178 4.83582C9.84558 4.78455 9.73389 4.75525 9.62219 4.74609ZM7.9248 16.3788C9.06555 17.7704 10.5487 18.75 12.1875 18.75C13.8263 18.75 15.3094 17.7722 16.4502 16.3806L20.6104 18.7885C18.9294 19.8761 17.8125 21.7621 17.8125 23.9062C17.8125 25.1147 18.1696 26.239 18.7793 27.1875H1.40625C1.14807 27.1875 0.9375 26.9769 0.9375 26.7188V23.399C0.9375 21.5662 1.92261 19.856 3.51013 18.9368L7.9248 16.3788ZM23.9062 18.75C26.7499 18.75 29.0625 21.0626 29.0625 23.9062C29.0625 26.7499 26.7499 29.0625 23.9062 29.0625C21.0626 29.0625 18.75 26.7499 18.75 23.9062C18.75 21.0626 21.0626 18.75 23.9062 18.75ZM8.4668 18.75C8.28369 18.739 8.10425 18.8361 8.01819 19.0082C7.90283 19.2407 7.99622 19.5227 8.22693 19.6381L11.9769 21.5131C12.0447 21.546 12.1161 21.5625 12.1875 21.5625C12.2589 21.5625 12.3322 21.546 12.3981 21.5131L16.1481 19.6381C16.3788 19.5227 16.4722 19.2407 16.3568 19.0082C16.2415 18.7775 15.9595 18.6841 15.7269 18.7994L12.1875 20.5701L8.64807 18.7994C8.58948 18.7701 8.52722 18.7555 8.4668 18.75ZM23.9062 20.625C23.6481 20.625 23.4375 20.8356 23.4375 21.0938V23.4375H21.0938C20.8356 23.4375 20.625 23.6481 20.625 23.9062C20.625 24.1644 20.8356 24.375 21.0938 24.375H23.4375V26.7188C23.4375 26.9769 23.6481 27.1875 23.9062 27.1875C24.1644 27.1875 24.375 26.9769 24.375 26.7188V24.375H26.7188C26.9769 24.375 27.1875 24.1644 27.1875 23.9062C27.1875 23.6481 26.9769 23.4375 26.7188 23.4375H24.375V21.0938C24.375 20.8356 24.1644 20.625 23.9062 20.625ZM2.8125 24.375C2.55432 24.375 2.34375 24.5856 2.34375 24.8438V25.7812C2.34375 26.0394 2.55432 26.25 2.8125 26.25C3.07068 26.25 3.28125 26.0394 3.28125 25.7812V24.8438C3.28125 24.5856 3.07068 24.375 2.8125 24.375ZM5.15625 24.375C4.89807 24.375 4.6875 24.5856 4.6875 24.8438V25.7812C4.6875 26.0394 4.89807 26.25 5.15625 26.25C5.41443 26.25 5.625 26.0394 5.625 25.7812V24.8438C5.625 24.5856 5.41443 24.375 5.15625 24.375ZM7.5 24.375C7.24182 24.375 7.03125 24.5856 7.03125 24.8438V25.7812C7.03125 26.0394 7.24182 26.25 7.5 26.25C7.75818 26.25 7.96875 26.0394 7.96875 25.7812V24.8438C7.96875 24.5856 7.75818 24.375 7.5 24.375ZM9.84375 24.375C9.58557 24.375 9.375 24.5856 9.375 24.8438V25.7812C9.375 26.0394 9.58557 26.25 9.84375 26.25C10.1019 26.25 10.3125 26.0394 10.3125 25.7812V24.8438C10.3125 24.5856 10.1019 24.375 9.84375 24.375ZM12.1875 24.375C11.9293 24.375 11.7188 24.5856 11.7188 24.8438V25.7812C11.7188 26.0394 11.9293 26.25 12.1875 26.25C12.4457 26.25 12.6562 26.0394 12.6562 25.7812V24.8438C12.6562 24.5856 12.4457 24.375 12.1875 24.375ZM14.5312 24.375C14.2731 24.375 14.0625 24.5856 14.0625 24.8438V25.7812C14.0625 26.0394 14.2731 26.25 14.5312 26.25C14.7894 26.25 15 26.0394 15 25.7812V24.8438C15 24.5856 14.7894 24.375 14.5312 24.375ZM16.875 24.375C16.6168 24.375 16.4062 24.5856 16.4062 24.8438V25.7812C16.4062 26.0394 16.6168 26.25 16.875 26.25C17.1332 26.25 17.3438 26.0394 17.3438 25.7812V24.8438C17.3438 24.5856 17.1332 24.375 16.875 24.375Z";
|
|
5
|
+
|
|
6
|
+
const PreviewGrid = ({ colour }) => {
|
|
7
|
+
return (
|
|
8
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox={"0 0 30 30"}>
|
|
9
|
+
<path key={SVG_PATH.substring(0, 20)} d={SVG_PATH} fill={colour} />
|
|
10
|
+
</svg>
|
|
11
|
+
);
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export default PreviewGrid;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { PlussCore } from "../feature.config";
|
|
3
|
+
const { Components } = PlussCore;
|
|
4
|
+
const { Text } = Components;
|
|
5
|
+
import previewWidget from "../images/previewWidget.png";
|
|
6
|
+
import styles from "./PreviewWidget.module.css";
|
|
7
|
+
|
|
8
|
+
const PreviewWidget = ({ backgroundColor, widgetTitle, titleClassName }) => {
|
|
9
|
+
return (
|
|
10
|
+
<div className={styles.previewWidget}>
|
|
11
|
+
<img
|
|
12
|
+
className={styles.previewWidget__image}
|
|
13
|
+
style={{ backgroundColor }}
|
|
14
|
+
src={previewWidget}
|
|
15
|
+
alt="previewWidget"
|
|
16
|
+
/>
|
|
17
|
+
<Text
|
|
18
|
+
type="body"
|
|
19
|
+
className={`${titleClassName} ${styles.previewWidget__title}`}
|
|
20
|
+
>
|
|
21
|
+
{widgetTitle}
|
|
22
|
+
</Text>
|
|
23
|
+
</div>
|
|
24
|
+
);
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export default PreviewWidget;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/* PreviewWidget BEM CSS Module */
|
|
2
|
+
|
|
3
|
+
/* Block */
|
|
4
|
+
.previewWidget {
|
|
5
|
+
position: relative;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/* Elements */
|
|
9
|
+
.previewWidget__image {
|
|
10
|
+
width: 100%;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.previewWidget__title {
|
|
14
|
+
/* Title styles are handled by titleClassName prop */
|
|
15
|
+
}
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
import React, { useEffect, useState } from "react";
|
|
2
|
+
import { useSelector } from "react-redux";
|
|
3
|
+
import { withRouter } from "react-router";
|
|
4
|
+
import { HubSidebar, DeleteConfirmationPopup } from "./index.js";
|
|
5
|
+
import {
|
|
6
|
+
selectWizardMode,
|
|
7
|
+
selectCurrentStep,
|
|
8
|
+
selectIsStepComplete,
|
|
9
|
+
selectIsStepAccessible,
|
|
10
|
+
selectStepProgress,
|
|
11
|
+
selectIsEditMode,
|
|
12
|
+
selectIsCreateMode,
|
|
13
|
+
selectDefinition,
|
|
14
|
+
selectDefinitionId,
|
|
15
|
+
} from "../selectors/featureBuilderSelectors";
|
|
16
|
+
import { goToStep } from "../actions/wizardActions";
|
|
17
|
+
import { useDispatch } from "react-redux";
|
|
18
|
+
import { PlussCore } from "../feature.config";
|
|
19
|
+
import { values } from "../values.config";
|
|
20
|
+
import styles from "./SidebarLayout.module.css";
|
|
21
|
+
|
|
22
|
+
const { Helper, Session } = PlussCore;
|
|
23
|
+
const { getUrl } = Helper;
|
|
24
|
+
const { authedFunction } = Session;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Sidebar Layout component for feature builder wizard
|
|
28
|
+
* Provides navigation sidebar with step progression, completion tracking
|
|
29
|
+
* Includes delete functionality for feature definitions
|
|
30
|
+
* Manages step accessibility based on wizard mode and validation state
|
|
31
|
+
*
|
|
32
|
+
* @param {Object} props - Component props
|
|
33
|
+
* @param {React.ReactNode} props.children - Child components to render in main content area
|
|
34
|
+
* @param {Object} props.history - React Router history object for navigation
|
|
35
|
+
* @returns {React.ReactElement} Layout component with sidebar navigation
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* <SidebarLayout history={historyObject}>
|
|
39
|
+
* <YourMainContent />
|
|
40
|
+
* </SidebarLayout>
|
|
41
|
+
*/
|
|
42
|
+
const SideBarInner = (props) => {
|
|
43
|
+
const { children, history } = props;
|
|
44
|
+
const dispatch = useDispatch();
|
|
45
|
+
|
|
46
|
+
// Get wizard state
|
|
47
|
+
const mode = useSelector(selectWizardMode);
|
|
48
|
+
const isEditMode = useSelector(selectIsEditMode);
|
|
49
|
+
const isCreateMode = useSelector(selectIsCreateMode);
|
|
50
|
+
const currentStep = useSelector(selectCurrentStep);
|
|
51
|
+
const stepProgress = useSelector(selectStepProgress);
|
|
52
|
+
const definition = useSelector(selectDefinition);
|
|
53
|
+
const definitionId = useSelector(selectDefinitionId);
|
|
54
|
+
const auth = useSelector((state) => state.auth);
|
|
55
|
+
|
|
56
|
+
// Delete functionality state
|
|
57
|
+
const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);
|
|
58
|
+
const [isDeleting, setIsDeleting] = useState(false);
|
|
59
|
+
|
|
60
|
+
const goTo = (url) => history.push(url);
|
|
61
|
+
|
|
62
|
+
const isSelected = (url) => {
|
|
63
|
+
return history.location.pathname === url;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
// Define step configuration with dynamic URL based on mode
|
|
67
|
+
const getStepUrl = (stepKey) => {
|
|
68
|
+
// Always use /definition/ in the URL since that's how routes are registered
|
|
69
|
+
return `/feature-builder/definition/${stepKey}`;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const steps = [
|
|
73
|
+
{
|
|
74
|
+
key: "overview",
|
|
75
|
+
text: "Feature Overview",
|
|
76
|
+
icon: "info-circle",
|
|
77
|
+
url: getStepUrl("overview"),
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
key: "fields",
|
|
81
|
+
text: "Configure Fields",
|
|
82
|
+
icon: "edit",
|
|
83
|
+
url: getStepUrl("fields"),
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
key: "layout",
|
|
87
|
+
text: "Choose Layout",
|
|
88
|
+
icon: "columns",
|
|
89
|
+
url: getStepUrl("layout"),
|
|
90
|
+
},
|
|
91
|
+
];
|
|
92
|
+
|
|
93
|
+
// Build sidebar items based on mode
|
|
94
|
+
const buildSidebarItems = () => {
|
|
95
|
+
return steps.map((step, index) => {
|
|
96
|
+
const isCompleted = selectIsStepComplete(step.key);
|
|
97
|
+
const isAccessible = selectIsStepAccessible(step.key);
|
|
98
|
+
|
|
99
|
+
// Add step number to text for better clarity
|
|
100
|
+
const stepText = `${index + 1}. ${step.text}`;
|
|
101
|
+
|
|
102
|
+
const itemProps = {
|
|
103
|
+
type: "navItem",
|
|
104
|
+
text: stepText,
|
|
105
|
+
icon: step.icon,
|
|
106
|
+
selected: isSelected(step.url),
|
|
107
|
+
onclick: isAccessible
|
|
108
|
+
? () => {
|
|
109
|
+
goTo(step.url);
|
|
110
|
+
dispatch(goToStep(step.key));
|
|
111
|
+
}
|
|
112
|
+
: null,
|
|
113
|
+
isFontAwesome: true,
|
|
114
|
+
// Enhanced completion indicator
|
|
115
|
+
completed: isCompleted,
|
|
116
|
+
// Allow navigation to completed steps even in create mode
|
|
117
|
+
disabled: mode === "create" && !isAccessible,
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
return itemProps;
|
|
121
|
+
});
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
// Determine sidebar title - always use "Build Your Feature" now
|
|
125
|
+
const getSidebarTitle = () => {
|
|
126
|
+
return "Build Your Feature";
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
// Simple help text
|
|
130
|
+
const getHelpText = () => {
|
|
131
|
+
return "Get help with feature builder";
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
// Build sidebar sections - simplified without progress section
|
|
135
|
+
const sidebarSections = [
|
|
136
|
+
{
|
|
137
|
+
title: getSidebarTitle(),
|
|
138
|
+
items: buildSidebarItems(),
|
|
139
|
+
},
|
|
140
|
+
];
|
|
141
|
+
|
|
142
|
+
// Delete functionality handlers
|
|
143
|
+
const handleDeleteClick = () => {
|
|
144
|
+
setShowDeleteConfirm(true);
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
const handleConfirmDelete = async () => {
|
|
148
|
+
if (!definition) return;
|
|
149
|
+
|
|
150
|
+
setIsDeleting(true);
|
|
151
|
+
try {
|
|
152
|
+
await authedFunction({
|
|
153
|
+
method: "POST",
|
|
154
|
+
url: getUrl("feature-builder", "definition/update/delete"),
|
|
155
|
+
data: { id: definitionId, site: auth.site },
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
// Redirect to welcome screen after deletion
|
|
159
|
+
history.push("/feature-builder/definition/overview");
|
|
160
|
+
} finally {
|
|
161
|
+
setIsDeleting(false);
|
|
162
|
+
setShowDeleteConfirm(false);
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
const handleCancelDelete = () => {
|
|
167
|
+
setShowDeleteConfirm(false);
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
// Add effect to manually attach click handlers since HubSidebar might not use onclick properly
|
|
171
|
+
useEffect(() => {
|
|
172
|
+
const attachClickHandlers = () => {
|
|
173
|
+
const stepsWithUrls = [
|
|
174
|
+
{ key: "overview", url: getStepUrl("overview") },
|
|
175
|
+
{ key: "fields", url: getStepUrl("fields") },
|
|
176
|
+
{ key: "layout", url: getStepUrl("layout") },
|
|
177
|
+
];
|
|
178
|
+
|
|
179
|
+
stepsWithUrls.forEach((step) => {
|
|
180
|
+
const navItem = Array.from(
|
|
181
|
+
document.querySelectorAll(".sideNav-item"),
|
|
182
|
+
).find(
|
|
183
|
+
(item) =>
|
|
184
|
+
item.textContent &&
|
|
185
|
+
item.textContent.includes(
|
|
186
|
+
step.key === "overview"
|
|
187
|
+
? "Feature Overview"
|
|
188
|
+
: step.key === "fields"
|
|
189
|
+
? "Configure Fields"
|
|
190
|
+
: "Choose Layout",
|
|
191
|
+
),
|
|
192
|
+
);
|
|
193
|
+
|
|
194
|
+
if (navItem) {
|
|
195
|
+
// Remove any existing click listeners
|
|
196
|
+
navItem.onclick = null;
|
|
197
|
+
|
|
198
|
+
// Check if this step is accessible
|
|
199
|
+
const isAccessible = selectIsStepAccessible(step.key)({
|
|
200
|
+
[values.reducerKey]: {
|
|
201
|
+
wizard: {
|
|
202
|
+
mode: mode,
|
|
203
|
+
navigation: {
|
|
204
|
+
currentStep: currentStep,
|
|
205
|
+
},
|
|
206
|
+
},
|
|
207
|
+
},
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
// Add our click handler only if accessible
|
|
211
|
+
if (isAccessible) {
|
|
212
|
+
navItem.onclick = (event) => {
|
|
213
|
+
event.preventDefault();
|
|
214
|
+
event.stopPropagation();
|
|
215
|
+
history.push(step.url);
|
|
216
|
+
dispatch(goToStep(step.key));
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Make sure it's styled appropriately
|
|
221
|
+
navItem.style.cursor = isAccessible ? "pointer" : "not-allowed";
|
|
222
|
+
navItem.style.pointerEvents = "auto";
|
|
223
|
+
navItem.style.opacity = isAccessible ? "1" : "0.5";
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
// Initial attachment
|
|
229
|
+
attachClickHandlers();
|
|
230
|
+
|
|
231
|
+
// Re-attach after a short delay to ensure HubSidebar has rendered
|
|
232
|
+
const timeoutId = setTimeout(attachClickHandlers, 100);
|
|
233
|
+
|
|
234
|
+
// Also try to re-attach when DOM changes (observe for mutations)
|
|
235
|
+
const observer = new MutationObserver(() => {
|
|
236
|
+
setTimeout(attachClickHandlers, 50);
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
// Start observing the document body for changes
|
|
240
|
+
observer.observe(document.body, {
|
|
241
|
+
childList: true,
|
|
242
|
+
subtree: true,
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
return () => {
|
|
246
|
+
clearTimeout(timeoutId);
|
|
247
|
+
observer.disconnect();
|
|
248
|
+
};
|
|
249
|
+
}, [history, dispatch, isEditMode, isCreateMode, currentStep]);
|
|
250
|
+
|
|
251
|
+
// Show sidebar in all modes
|
|
252
|
+
const shouldShowSidebar = true;
|
|
253
|
+
|
|
254
|
+
return (
|
|
255
|
+
<div className="hub-wrapperContainer">
|
|
256
|
+
{shouldShowSidebar && (
|
|
257
|
+
<HubSidebar
|
|
258
|
+
sections={sidebarSections}
|
|
259
|
+
helpGuide={{
|
|
260
|
+
text: getHelpText(),
|
|
261
|
+
url: "https://www.plusscommunities.com/user-guide",
|
|
262
|
+
}}
|
|
263
|
+
/>
|
|
264
|
+
)}
|
|
265
|
+
|
|
266
|
+
{/* Dev Delete Button - Absolute positioned at bottom of sidebar */}
|
|
267
|
+
{shouldShowSidebar && (
|
|
268
|
+
<button onClick={handleDeleteClick} className={styles.devDeleteButton}>
|
|
269
|
+
DELETE FEATURE DEF
|
|
270
|
+
</button>
|
|
271
|
+
)}
|
|
272
|
+
|
|
273
|
+
<div className="hub-contentWrapper">
|
|
274
|
+
<div className={styles.fullWidthContainer}>
|
|
275
|
+
<div className={styles.contentContainer}>{children}</div>
|
|
276
|
+
</div>
|
|
277
|
+
</div>
|
|
278
|
+
|
|
279
|
+
{/* Delete Confirmation Popup */}
|
|
280
|
+
<DeleteConfirmationPopup
|
|
281
|
+
isOpen={showDeleteConfirm}
|
|
282
|
+
listing={definition}
|
|
283
|
+
onConfirm={handleConfirmDelete}
|
|
284
|
+
onCancel={handleCancelDelete}
|
|
285
|
+
isDeleting={isDeleting}
|
|
286
|
+
deleteType="featureDefinition"
|
|
287
|
+
/>
|
|
288
|
+
</div>
|
|
289
|
+
);
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
export const SidebarLayout = withRouter(SideBarInner);
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
.fullWidthContent {
|
|
2
|
+
max-width: 100%;
|
|
3
|
+
margin-left: auto;
|
|
4
|
+
margin-right: auto;
|
|
5
|
+
padding: 2rem 2rem 3rem 2rem; /* Add extra bottom padding */
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/* Full-width container that allows scrollbar at edge */
|
|
9
|
+
.fullWidthContainer {
|
|
10
|
+
display: flex;
|
|
11
|
+
flex-direction: column;
|
|
12
|
+
flex: 1;
|
|
13
|
+
min-height: 0; /* Allow content to determine height */
|
|
14
|
+
width: 100%; /* Take full width to ensure scrollbar is at edge */
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/* Content container to keep content centered */
|
|
18
|
+
.contentContainer {
|
|
19
|
+
display: flex;
|
|
20
|
+
flex-direction: column;
|
|
21
|
+
flex: 1;
|
|
22
|
+
min-height: 0;
|
|
23
|
+
max-width: 960px;
|
|
24
|
+
margin: 0 auto;
|
|
25
|
+
padding: 64px 32px;
|
|
26
|
+
width: 100%;
|
|
27
|
+
box-sizing: border-box;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/* Legacy container class for backward compatibility */
|
|
31
|
+
.container{
|
|
32
|
+
display: flex;
|
|
33
|
+
flex-direction: column;
|
|
34
|
+
flex: 1;
|
|
35
|
+
min-height: 0; /* Allow content to determine height */
|
|
36
|
+
max-width: 960px;
|
|
37
|
+
margin: 0 auto;
|
|
38
|
+
padding: 64px 32px;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/* Responsive adjustments for content container */
|
|
42
|
+
@media (max-width: 768px) {
|
|
43
|
+
.contentContainer {
|
|
44
|
+
padding: 1.5rem 1.5rem 2.5rem 1.5rem; /* Slightly reduced but still adequate */
|
|
45
|
+
}
|
|
46
|
+
.container {
|
|
47
|
+
padding: 1.5rem 1.5rem 2.5rem 1.5rem; /* Legacy container support */
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
@media (max-width: 480px) {
|
|
52
|
+
.contentContainer {
|
|
53
|
+
padding: 1rem 1rem 2rem 1rem; /* Maintain padding on small screens */
|
|
54
|
+
}
|
|
55
|
+
.container {
|
|
56
|
+
padding: 1rem 1rem 2rem 1rem; /* Legacy container support */
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/* Enhanced sidebar navigation for progress indication */
|
|
61
|
+
:global(.hub-sideBar) {
|
|
62
|
+
/* Make sidebar more prominent during creation mode */
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
:global(.sideNav-item.isCurrent) {
|
|
66
|
+
background: var(--colour-purple, #6e79c5) !important;
|
|
67
|
+
color: var(--colour-white, #ffffff) !important;
|
|
68
|
+
font-weight: 600 !important;
|
|
69
|
+
border-left: 4px solid var(--colour-branding-dark, #364196) !important;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
:global(.sideNav-item.isCurrent) i {
|
|
73
|
+
color: var(--colour-white, #ffffff) !important;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
:global(.sideNav-item.isCompleted) {
|
|
77
|
+
color: var(--colour-branding-dark, #364196) !important;
|
|
78
|
+
position: relative;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
:global(.sideNav-item.isCompleted::after) {
|
|
82
|
+
content: "✓";
|
|
83
|
+
position: absolute;
|
|
84
|
+
right: 1rem;
|
|
85
|
+
top: 50%;
|
|
86
|
+
transform: translateY(-50%);
|
|
87
|
+
color: var(--colour-branding-dark, #364196);
|
|
88
|
+
font-weight: bold;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
:global(.sideNav-item.isDisabled) {
|
|
92
|
+
opacity: 0.4;
|
|
93
|
+
cursor: not-allowed;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/* Enhanced progress section */
|
|
97
|
+
:global(.hub-sideBar-section) {
|
|
98
|
+
border-bottom: 2px solid var(--colour-branding-main-fade, rgba(74, 87, 183, 0.15));
|
|
99
|
+
padding-bottom: 1rem;
|
|
100
|
+
margin-bottom: 1rem;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
:global(.hub-sideBar-section:last-child) {
|
|
104
|
+
border-bottom: none;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/* Delete button styling - bold red for development */
|
|
108
|
+
.deleteButton {
|
|
109
|
+
color: #dc3545 !important;
|
|
110
|
+
font-weight: bold !important;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
:global(.sideNav-item.deleteButton) {
|
|
114
|
+
color: #dc3545 !important;
|
|
115
|
+
font-weight: bold !important;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
:global(.sideNav-item.deleteButton:hover) {
|
|
119
|
+
background-color: rgba(220, 53, 69, 0.1) !important;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
:global(.sideNav-item.deleteButton i) {
|
|
123
|
+
color: #dc3545 !important;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/* Development delete button */
|
|
127
|
+
.devDeleteButton {
|
|
128
|
+
position: absolute;
|
|
129
|
+
bottom: 20px;
|
|
130
|
+
left: 20px;
|
|
131
|
+
background-color: #ff0000;
|
|
132
|
+
color: #ffffff;
|
|
133
|
+
border: none;
|
|
134
|
+
padding: 8px 12px;
|
|
135
|
+
border-radius: 4px;
|
|
136
|
+
cursor: pointer;
|
|
137
|
+
font-size: 12px;
|
|
138
|
+
font-weight: bold;
|
|
139
|
+
z-index: 1000;
|
|
140
|
+
box-shadow: 0 2px 4px rgba(0,0,0,0.3);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
.devDeleteButton:hover {
|
|
144
|
+
background-color: #cc0000;
|
|
145
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import styles from "./SkeletonLoader.module.css";
|
|
3
|
+
|
|
4
|
+
const SkeletonLoader = ({ type = "card", count = 1, className = "" }) => {
|
|
5
|
+
const renderSkeletonItem = () => {
|
|
6
|
+
switch (type) {
|
|
7
|
+
case "listing-card":
|
|
8
|
+
return (
|
|
9
|
+
<div className={styles.listingCard}>
|
|
10
|
+
<div className={styles.listingCardHeader}>
|
|
11
|
+
<div className={`${styles.skeletonItem} ${styles.icon}`}></div>
|
|
12
|
+
<div className={`${styles.skeletonItem} ${styles.title}`}></div>
|
|
13
|
+
</div>
|
|
14
|
+
<div className={styles.listingCardBody}>
|
|
15
|
+
<div
|
|
16
|
+
className={`${styles.skeletonItem} ${styles.description}`}
|
|
17
|
+
></div>
|
|
18
|
+
<div
|
|
19
|
+
className={`${styles.skeletonItem} ${styles.description}`}
|
|
20
|
+
></div>
|
|
21
|
+
</div>
|
|
22
|
+
<div className={styles.listingCardFooter}>
|
|
23
|
+
<div
|
|
24
|
+
className={`${styles.skeletonItem} ${styles.smallText}`}
|
|
25
|
+
></div>
|
|
26
|
+
<div className={`${styles.skeletonItem} ${styles.button}`}></div>
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
case "form-field":
|
|
32
|
+
return (
|
|
33
|
+
<div className={styles.formField}>
|
|
34
|
+
<div className={styles.formFieldHeader}>
|
|
35
|
+
<div
|
|
36
|
+
className={`${styles.skeletonItem} ${styles.fieldType}`}
|
|
37
|
+
></div>
|
|
38
|
+
<div
|
|
39
|
+
className={`${styles.skeletonItem} ${styles.fieldActions}`}
|
|
40
|
+
></div>
|
|
41
|
+
</div>
|
|
42
|
+
<div className={styles.formFieldBody}>
|
|
43
|
+
<div className={`${styles.skeletonItem} ${styles.label}`}></div>
|
|
44
|
+
<div className={`${styles.skeletonItem} ${styles.input}`}></div>
|
|
45
|
+
<div
|
|
46
|
+
className={`${styles.skeletonItem} ${styles.helpText}`}
|
|
47
|
+
></div>
|
|
48
|
+
</div>
|
|
49
|
+
</div>
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
case "layout-option":
|
|
53
|
+
return (
|
|
54
|
+
<div className={styles.layoutOption}>
|
|
55
|
+
<div
|
|
56
|
+
className={`${styles.skeletonItem} ${styles.layoutPreview}`}
|
|
57
|
+
></div>
|
|
58
|
+
<div className={styles.layoutContent}>
|
|
59
|
+
<div
|
|
60
|
+
className={`${styles.skeletonItem} ${styles.layoutTitle}`}
|
|
61
|
+
></div>
|
|
62
|
+
<div
|
|
63
|
+
className={`${styles.skeletonItem} ${styles.layoutDescription}`}
|
|
64
|
+
></div>
|
|
65
|
+
</div>
|
|
66
|
+
</div>
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
case "form-input":
|
|
70
|
+
return (
|
|
71
|
+
<div className={styles.formInput}>
|
|
72
|
+
<div className={`${styles.skeletonItem} ${styles.label}`}></div>
|
|
73
|
+
<div className={`${styles.skeletonItem} ${styles.input}`}></div>
|
|
74
|
+
</div>
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
case "button":
|
|
78
|
+
return (
|
|
79
|
+
<div className={`${styles.skeletonItem} ${styles.button}`}></div>
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
case "table-row":
|
|
83
|
+
return (
|
|
84
|
+
<tr className={styles.tableRow}>
|
|
85
|
+
<td>
|
|
86
|
+
<div
|
|
87
|
+
className={`${styles.skeletonItem} ${styles.tableDate}`}
|
|
88
|
+
></div>
|
|
89
|
+
</td>
|
|
90
|
+
<td>
|
|
91
|
+
<div
|
|
92
|
+
className={`${styles.skeletonItem} ${styles.tableTitle}`}
|
|
93
|
+
></div>
|
|
94
|
+
</td>
|
|
95
|
+
<td>
|
|
96
|
+
<div
|
|
97
|
+
className={`${styles.skeletonItem} ${styles.tableActions}`}
|
|
98
|
+
></div>
|
|
99
|
+
</td>
|
|
100
|
+
</tr>
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
case "text":
|
|
104
|
+
return <div className={`${styles.skeletonItem} ${styles.text}`}></div>;
|
|
105
|
+
|
|
106
|
+
default:
|
|
107
|
+
return (
|
|
108
|
+
<div className={styles.card}>
|
|
109
|
+
<div className={`${styles.skeletonItem} ${styles.header}`}></div>
|
|
110
|
+
<div className={`${styles.skeletonItem} ${styles.content}`}></div>
|
|
111
|
+
<div className={`${styles.skeletonItem} ${styles.footer}`}></div>
|
|
112
|
+
</div>
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
return (
|
|
118
|
+
<div className={`${styles.skeletonLoader} ${className}`}>
|
|
119
|
+
{Array.from({ length: count }).map((_, index) => (
|
|
120
|
+
<div key={index} className={styles.skeletonItemWrapper}>
|
|
121
|
+
{renderSkeletonItem()}
|
|
122
|
+
</div>
|
|
123
|
+
))}
|
|
124
|
+
</div>
|
|
125
|
+
);
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
export default SkeletonLoader;
|