@plusscommunities/pluss-feature-builder-web-a 1.0.2-beta.0 → 1.0.2-beta.10
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 +1380 -1337
- package/package.json +1 -1
- package/rollup.config.js +1 -0
- package/src/actions/featureDefinitionsIndex.js +15 -15
- package/src/actions/formActions.js +31 -30
- package/src/actions/listingActions.js +27 -25
- package/src/actions/wizardActions.js +23 -35
- package/src/components/BaseFieldConfig.jsx +234 -234
- package/src/components/IconLoader.jsx +138 -138
- package/src/components/IconSelector.jsx +0 -1
- package/src/components/ListingEditor.jsx +2 -3
- package/src/components/SidebarLayout.jsx +49 -89
- package/src/components/SidebarLayout.module.css +0 -74
- package/src/components/index.js +0 -2
- package/src/components/listing/GalleryDisplay.jsx +0 -1
- package/src/components/listing/ListingFileInput.jsx +98 -80
- package/src/components/listing/ListingFileInput.module.css +1 -4
- package/src/components/listing/ListingGalleryInput.jsx +4 -1
- package/src/components/listing/ListingGalleryInput.module.css +2 -1
- package/src/hooks/useFeatureDefinitionLoader.js +6 -2
- 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 +6 -6
- package/src/reducers/featureBuilderReducer.js +18 -22
- package/src/screens/Form.module.css +11 -1
- package/src/screens/FormLayoutStep.jsx +422 -424
- package/src/screens/FormOverviewStep.jsx +3 -10
- package/src/screens/ListingScreen.jsx +0 -1
- package/src/selectors/featureBuilderSelectors.js +47 -43
|
@@ -9,145 +9,145 @@ const { Apis } = PlussCore;
|
|
|
9
9
|
const { fileActions } = Apis;
|
|
10
10
|
|
|
11
11
|
const IconLoader = ({
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
value,
|
|
13
|
+
defaultValue,
|
|
14
|
+
onChange,
|
|
15
|
+
onRemove,
|
|
16
|
+
disableRemove = false,
|
|
17
|
+
featureId,
|
|
18
18
|
}) => {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
19
|
+
const [isUploading, setIsUploading] = useState(false);
|
|
20
|
+
const fileInputRef = useRef(null);
|
|
21
|
+
|
|
22
|
+
// Determine which icon to show
|
|
23
|
+
const hasCustomIcon =
|
|
24
|
+
value && typeof value === "string" && value.startsWith("http");
|
|
25
|
+
const iconToShow = defaultValue || "star";
|
|
26
|
+
|
|
27
|
+
// Generate filename with feature ID
|
|
28
|
+
const generateFilename = (file, featureId) => {
|
|
29
|
+
const timestamp = Date.now();
|
|
30
|
+
const ext = file.name.split(".").pop();
|
|
31
|
+
return `build-your-feature-${featureId || "new"}-${timestamp}.${ext}`;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
// Get FontAwesome icon component directly (no async needed)
|
|
35
|
+
const iconComponent = !hasCustomIcon ? iconImports[iconToShow] : null;
|
|
36
|
+
|
|
37
|
+
const handleFileSelect = async (event) => {
|
|
38
|
+
const file = event.target.files[0];
|
|
39
|
+
if (!file || isUploading) return;
|
|
40
|
+
|
|
41
|
+
// Validate file type - only accept images
|
|
42
|
+
if (!file.type.startsWith("image/")) {
|
|
43
|
+
alert("Please upload an image file (JPEG, PNG, GIF, or WebP)");
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
setIsUploading(true);
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
// Compress and upload the image
|
|
51
|
+
const compressedFile = await fileActions.compressImage(
|
|
52
|
+
file,
|
|
53
|
+
1400,
|
|
54
|
+
0.8,
|
|
55
|
+
false,
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
const filename = generateFilename(compressedFile, featureId);
|
|
59
|
+
const url = await fileActions.uploadMediaAsync(compressedFile, filename);
|
|
60
|
+
|
|
61
|
+
if (onChange) {
|
|
62
|
+
onChange(url);
|
|
63
|
+
}
|
|
64
|
+
} catch (error) {
|
|
65
|
+
alert("Failed to upload image. Please try again.");
|
|
66
|
+
} finally {
|
|
67
|
+
setIsUploading(false);
|
|
68
|
+
// Reset file input
|
|
69
|
+
if (fileInputRef.current) {
|
|
70
|
+
fileInputRef.current.value = "";
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const handleUploadClick = () => {
|
|
76
|
+
if (fileInputRef.current && !isUploading) {
|
|
77
|
+
fileInputRef.current.click();
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
const handleRemove = () => {
|
|
82
|
+
if (onRemove && !disableRemove) {
|
|
83
|
+
onRemove();
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
// Container will use CSS modules classes
|
|
88
|
+
// Custom styling through props is deprecated in favor of CSS consistency
|
|
89
|
+
|
|
90
|
+
return (
|
|
91
|
+
<div className={`${styles.iconLoader} ${styles.iconLoader__container}`}>
|
|
92
|
+
{/* Show the icon/image */}
|
|
93
|
+
{hasCustomIcon ? (
|
|
94
|
+
<img
|
|
95
|
+
src={value}
|
|
96
|
+
alt="Custom icon"
|
|
97
|
+
className={styles.iconLoader__image}
|
|
98
|
+
/>
|
|
99
|
+
) : (
|
|
100
|
+
<div className={styles.iconLoader__iconContainer}>
|
|
101
|
+
{iconComponent ? (
|
|
102
|
+
<FontAwesomeIcon
|
|
103
|
+
icon={iconComponent}
|
|
104
|
+
className={`${styles.iconLoader__icon} ${styles.iconLoader__iconLarge}`}
|
|
105
|
+
/>
|
|
106
|
+
) : (
|
|
107
|
+
<div className={styles.iconLoader__fallbackText}>{iconToShow}</div>
|
|
108
|
+
)}
|
|
109
|
+
</div>
|
|
110
|
+
)}
|
|
111
|
+
|
|
112
|
+
{/* Upload/Delete button overlay - only shows on hover */}
|
|
113
|
+
<div className={styles.iconLoader__buttonOverlay}>
|
|
114
|
+
{hasCustomIcon ? (
|
|
115
|
+
<Button
|
|
116
|
+
buttonType="secondary"
|
|
117
|
+
isActive
|
|
118
|
+
onClick={handleRemove}
|
|
119
|
+
disabled={disableRemove || isUploading}
|
|
120
|
+
size="small"
|
|
121
|
+
leftIcon="times"
|
|
122
|
+
aria-label="Delete icon"
|
|
123
|
+
>
|
|
124
|
+
Delete
|
|
125
|
+
</Button>
|
|
126
|
+
) : (
|
|
127
|
+
<Button
|
|
128
|
+
buttonType="primary"
|
|
129
|
+
onClick={() => {}}
|
|
130
|
+
disabled={isUploading}
|
|
131
|
+
size="small"
|
|
132
|
+
leftIcon="upload"
|
|
133
|
+
loading={isUploading}
|
|
134
|
+
aria-label="Upload icon"
|
|
135
|
+
>
|
|
136
|
+
Upload
|
|
137
|
+
</Button>
|
|
138
|
+
)}
|
|
139
|
+
</div>
|
|
140
|
+
|
|
141
|
+
{/* Hidden file input */}
|
|
142
|
+
<input
|
|
143
|
+
ref={fileInputRef}
|
|
144
|
+
type="file"
|
|
145
|
+
accept="image/jpeg,image/png,image/gif,image/webp,image/svg"
|
|
146
|
+
onChange={handleFileSelect}
|
|
147
|
+
className={styles.iconLoader__hiddenInput}
|
|
148
|
+
/>
|
|
149
|
+
</div>
|
|
150
|
+
);
|
|
151
151
|
};
|
|
152
152
|
|
|
153
153
|
export default IconLoader;
|
|
@@ -32,7 +32,6 @@ import {
|
|
|
32
32
|
import { fetchFeatureDefinitions } from "../actions/featureDefinitionsIndex.js";
|
|
33
33
|
import { values } from "../values.config.js";
|
|
34
34
|
|
|
35
|
-
|
|
36
35
|
const ListingEditor = ({ mode = "create", listingId, onSuccess, onCancel }) => {
|
|
37
36
|
const isEditMode = mode === "edit";
|
|
38
37
|
const dispatch = useDispatch();
|
|
@@ -169,8 +168,8 @@ const ListingEditor = ({ mode = "create", listingId, onSuccess, onCancel }) => {
|
|
|
169
168
|
|
|
170
169
|
// formData always has structure { fields: {...} } after our fixes
|
|
171
170
|
const submissionData = isEditMode
|
|
172
|
-
? { id: listingId, fields: formData.fields }
|
|
173
|
-
: { fields: formData.fields };
|
|
171
|
+
? { id: listingId, fields: formData.fields, site: auth.site }
|
|
172
|
+
: { fields: formData.fields, site: auth.site };
|
|
174
173
|
|
|
175
174
|
const actionPromise = dispatch(
|
|
176
175
|
isEditMode ? editListing(submissionData) : createListing(submissionData),
|
|
@@ -1,32 +1,23 @@
|
|
|
1
|
-
import React, { useEffect
|
|
1
|
+
import React, { useEffect } from "react";
|
|
2
2
|
import { useSelector } from "react-redux";
|
|
3
3
|
import { withRouter } from "react-router";
|
|
4
|
-
import { HubSidebar
|
|
4
|
+
import { HubSidebar } from "./index.js";
|
|
5
5
|
import {
|
|
6
6
|
selectWizardMode,
|
|
7
7
|
selectCurrentStep,
|
|
8
8
|
selectIsStepComplete,
|
|
9
9
|
selectIsStepAccessible,
|
|
10
|
-
selectStepProgress,
|
|
11
10
|
selectIsEditMode,
|
|
12
11
|
selectIsCreateMode,
|
|
13
|
-
selectDefinition,
|
|
14
|
-
selectDefinitionId,
|
|
15
12
|
} from "../selectors/featureBuilderSelectors";
|
|
16
13
|
import { goToStep } from "../actions/wizardActions";
|
|
17
14
|
import { useDispatch } from "react-redux";
|
|
18
|
-
import { PlussCore } from "../feature.config";
|
|
19
15
|
import { values } from "../values.config";
|
|
20
16
|
import styles from "./SidebarLayout.module.css";
|
|
21
17
|
|
|
22
|
-
const { Helper, Session } = PlussCore;
|
|
23
|
-
const { getUrl } = Helper;
|
|
24
|
-
const { authedFunction } = Session;
|
|
25
|
-
|
|
26
18
|
/**
|
|
27
19
|
* Sidebar Layout component for feature builder wizard
|
|
28
20
|
* Provides navigation sidebar with step progression, completion tracking
|
|
29
|
-
* Includes delete functionality for feature definitions
|
|
30
21
|
* Manages step accessibility based on wizard mode and validation state
|
|
31
22
|
*
|
|
32
23
|
* @param {Object} props - Component props
|
|
@@ -48,14 +39,6 @@ const SideBarInner = (props) => {
|
|
|
48
39
|
const isEditMode = useSelector(selectIsEditMode);
|
|
49
40
|
const isCreateMode = useSelector(selectIsCreateMode);
|
|
50
41
|
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
42
|
|
|
60
43
|
const goTo = (url) => history.push(url);
|
|
61
44
|
|
|
@@ -65,8 +48,17 @@ const SideBarInner = (props) => {
|
|
|
65
48
|
|
|
66
49
|
// Define step configuration with dynamic URL based on mode
|
|
67
50
|
const getStepUrl = (stepKey) => {
|
|
68
|
-
//
|
|
69
|
-
|
|
51
|
+
// Use routes from values.config to support different variants (-a, -b, -c, -d)
|
|
52
|
+
switch (stepKey) {
|
|
53
|
+
case "overview":
|
|
54
|
+
return values.routeFormOverviewStep;
|
|
55
|
+
case "fields":
|
|
56
|
+
return values.routeFormFieldsStep;
|
|
57
|
+
case "layout":
|
|
58
|
+
return values.routeFormLayoutStep;
|
|
59
|
+
default:
|
|
60
|
+
return "";
|
|
61
|
+
}
|
|
70
62
|
};
|
|
71
63
|
|
|
72
64
|
const steps = [
|
|
@@ -92,6 +84,8 @@ const SideBarInner = (props) => {
|
|
|
92
84
|
|
|
93
85
|
// Build sidebar items based on mode
|
|
94
86
|
const buildSidebarItems = () => {
|
|
87
|
+
const isWizardMode = mode === "create";
|
|
88
|
+
|
|
95
89
|
return steps.map((step, index) => {
|
|
96
90
|
const isCompleted = selectIsStepComplete(step.key);
|
|
97
91
|
const isAccessible = selectIsStepAccessible(step.key);
|
|
@@ -104,17 +98,19 @@ const SideBarInner = (props) => {
|
|
|
104
98
|
text: stepText,
|
|
105
99
|
icon: step.icon,
|
|
106
100
|
selected: isSelected(step.url),
|
|
107
|
-
onclick:
|
|
108
|
-
?
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
101
|
+
onclick: isWizardMode
|
|
102
|
+
? null
|
|
103
|
+
: isAccessible
|
|
104
|
+
? () => {
|
|
105
|
+
goTo(step.url);
|
|
106
|
+
dispatch(goToStep(step.key));
|
|
107
|
+
}
|
|
108
|
+
: null,
|
|
113
109
|
isFontAwesome: true,
|
|
114
110
|
// Enhanced completion indicator
|
|
115
111
|
completed: isCompleted,
|
|
116
|
-
//
|
|
117
|
-
disabled: mode === "create"
|
|
112
|
+
// Disable all navigation in create mode, otherwise respect accessibility
|
|
113
|
+
disabled: mode === "create" || !isAccessible,
|
|
118
114
|
};
|
|
119
115
|
|
|
120
116
|
return itemProps;
|
|
@@ -139,36 +135,10 @@ const SideBarInner = (props) => {
|
|
|
139
135
|
},
|
|
140
136
|
];
|
|
141
137
|
|
|
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
138
|
// Add effect to manually attach click handlers since HubSidebar might not use onclick properly
|
|
171
139
|
useEffect(() => {
|
|
140
|
+
const isWizardMode = mode === "create";
|
|
141
|
+
|
|
172
142
|
const attachClickHandlers = () => {
|
|
173
143
|
const stepsWithUrls = [
|
|
174
144
|
{ key: "overview", url: getStepUrl("overview") },
|
|
@@ -176,19 +146,12 @@ const SideBarInner = (props) => {
|
|
|
176
146
|
{ key: "layout", url: getStepUrl("layout") },
|
|
177
147
|
];
|
|
178
148
|
|
|
179
|
-
stepsWithUrls.forEach((step) => {
|
|
149
|
+
stepsWithUrls.forEach((step, index) => {
|
|
180
150
|
const navItem = Array.from(
|
|
181
|
-
document.querySelectorAll(".sideNav-item"),
|
|
151
|
+
document.querySelectorAll(".hub-wrapperContainer .sideNav-item"),
|
|
182
152
|
).find(
|
|
183
153
|
(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
|
-
),
|
|
154
|
+
item.textContent && item.textContent.includes(`${index + 1}.`),
|
|
192
155
|
);
|
|
193
156
|
|
|
194
157
|
if (navItem) {
|
|
@@ -207,8 +170,12 @@ const SideBarInner = (props) => {
|
|
|
207
170
|
},
|
|
208
171
|
});
|
|
209
172
|
|
|
210
|
-
//
|
|
211
|
-
|
|
173
|
+
// Check if this is the current step (selected)
|
|
174
|
+
const isCurrentStep = isSelected(step.url);
|
|
175
|
+
|
|
176
|
+
// In wizard mode, don't attach any click handlers
|
|
177
|
+
// Only attach click handler if not in wizard mode AND accessible
|
|
178
|
+
if (!isWizardMode && isAccessible) {
|
|
212
179
|
navItem.onclick = (event) => {
|
|
213
180
|
event.preventDefault();
|
|
214
181
|
event.stopPropagation();
|
|
@@ -218,9 +185,19 @@ const SideBarInner = (props) => {
|
|
|
218
185
|
}
|
|
219
186
|
|
|
220
187
|
// Make sure it's styled appropriately
|
|
221
|
-
|
|
222
|
-
navItem.style.pointerEvents = "auto";
|
|
223
|
-
|
|
188
|
+
// In wizard mode: block clicks, but keep current step visible
|
|
189
|
+
navItem.style.pointerEvents = isWizardMode ? "none" : "auto";
|
|
190
|
+
|
|
191
|
+
if (isWizardMode) {
|
|
192
|
+
// Current step: full opacity, not-allowed cursor
|
|
193
|
+
// Other steps: reduced opacity
|
|
194
|
+
navItem.style.opacity = isCurrentStep ? "1" : "0.4";
|
|
195
|
+
navItem.style.cursor = "not-allowed";
|
|
196
|
+
} else {
|
|
197
|
+
// Not in wizard mode: normal styling based on accessibility
|
|
198
|
+
navItem.style.cursor = isAccessible ? "pointer" : "not-allowed";
|
|
199
|
+
navItem.style.opacity = isAccessible ? "1" : "0.5";
|
|
200
|
+
}
|
|
224
201
|
}
|
|
225
202
|
});
|
|
226
203
|
};
|
|
@@ -263,28 +240,11 @@ const SideBarInner = (props) => {
|
|
|
263
240
|
/>
|
|
264
241
|
)}
|
|
265
242
|
|
|
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
243
|
<div className="hub-contentWrapper">
|
|
274
244
|
<div className={styles.fullWidthContainer}>
|
|
275
245
|
<div className={styles.contentContainer}>{children}</div>
|
|
276
246
|
</div>
|
|
277
247
|
</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
248
|
</div>
|
|
289
249
|
);
|
|
290
250
|
};
|
|
@@ -58,40 +58,6 @@
|
|
|
58
58
|
}
|
|
59
59
|
|
|
60
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
61
|
|
|
96
62
|
/* Enhanced progress section */
|
|
97
63
|
:global(.hub-sideBar-section) {
|
|
@@ -103,43 +69,3 @@
|
|
|
103
69
|
:global(.hub-sideBar-section:last-child) {
|
|
104
70
|
border-bottom: none;
|
|
105
71
|
}
|
|
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
|
-
}
|
package/src/components/index.js
CHANGED