@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
package/package.json
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@plusscommunities/pluss-feature-builder-web-a",
|
|
3
|
+
"version": "1.0.2-beta.0",
|
|
4
|
+
"description": "Contains the feature builder extension for the pluss communities ",
|
|
5
|
+
"main": "dist/index.cjs.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"build": "npm i && rollup -c",
|
|
8
|
+
"betapatch": "npm version prepatch --preid=beta",
|
|
9
|
+
"patch": "npm version patch",
|
|
10
|
+
"betaupload": "npm run build && npm publish --access public --tag beta && rm -rf node_modules",
|
|
11
|
+
"betaupload:p": "npm run betapatch && npm run betaupload",
|
|
12
|
+
"upload": "npm run build && npm publish --access public && rm -rf node_modules",
|
|
13
|
+
"upload:p": "npm run patch && npm run upload",
|
|
14
|
+
"copy:add": "run(){ ext=${1:-default}; test -f src/values.config.$ext.js || cp src/values.config.default.js src/values.config.$ext.js; }; run",
|
|
15
|
+
"copy:get": "echo $npm_package_name",
|
|
16
|
+
"copy:set": "run(){ target='@plusscommunities/pluss-feature-builder-web'; ext=${1:-default}; [ $ext == 'default' ] && replace=$target || replace=$target'-'$ext; echo 'Setting target to '$replace; test -f src/values.config.$ext.js && cp -f src/values.config.$ext.js src/values.config.js; REPLACE=$replace node -e 'const pkg=require(\"./package.json\"); pkg.name=process.env.REPLACE; require(\"fs\").writeFileSync(\"./package.json\", JSON.stringify(pkg, null, 2))'; }; run",
|
|
17
|
+
"copy:betaupload": "npm run betapatch; for file in `ls ./src/values.config.*.js`; do dup=`echo $file | sed 's/.*values\\.config\\.\\(.*\\)\\.js/\\1/'`; npm run copy:set $dup; npm run betaupload; done; npm run copy:set;",
|
|
18
|
+
"copy:upload": "npm run patch; for file in `ls ./src/values.config.*.js`; do dup=`echo $file | sed 's/.*values\\.config\\.\\(.*\\)\\.js/\\1/'`; npm run copy:set $dup; npm run upload; done; npm run copy:set;"
|
|
19
|
+
},
|
|
20
|
+
"author": "Phillip Suh",
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@babel/cli": "^7.14.3",
|
|
23
|
+
"@babel/core": "^7.14.3",
|
|
24
|
+
"@babel/plugin-transform-class-properties": "^7.27.1",
|
|
25
|
+
"@babel/plugin-transform-optional-chaining": "^7.14.5",
|
|
26
|
+
"@babel/plugin-transform-react-jsx": "^7.14.3",
|
|
27
|
+
"@babel/plugin-transform-runtime": "^7.14.3",
|
|
28
|
+
"@babel/preset-env": "^7.14.2",
|
|
29
|
+
"@babel/preset-react": "^7.13.13",
|
|
30
|
+
"@rollup/plugin-babel": "^5.3.0",
|
|
31
|
+
"@rollup/plugin-image": "^2.0.6",
|
|
32
|
+
"@rollup/plugin-json": "^4.1.0",
|
|
33
|
+
"autoprefixer": "^10.2.6",
|
|
34
|
+
"rollup": "^2.50.1",
|
|
35
|
+
"rollup-plugin-local-resolve": "^1.0.7",
|
|
36
|
+
"rollup-plugin-styles": "^3.14.1"
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"@babel/runtime": "^7.14.0"
|
|
40
|
+
},
|
|
41
|
+
"peerDependencies": {
|
|
42
|
+
"@fortawesome/fontawesome-svg-core": "^6.4.0",
|
|
43
|
+
"@fortawesome/free-solid-svg-icons": "^6.4.0",
|
|
44
|
+
"@fortawesome/react-fontawesome": "^0.2.0",
|
|
45
|
+
"@plusscommunities/pluss-core-web": "^1.6.15-beta.1",
|
|
46
|
+
"lodash": "^4.17.4",
|
|
47
|
+
"moment": "^2.30.1",
|
|
48
|
+
"react": "^16.14.0",
|
|
49
|
+
"react-bootstrap": "^0.31.2",
|
|
50
|
+
"react-dom": "^16.14.0",
|
|
51
|
+
"react-fontawesome": "^1.6.1"
|
|
52
|
+
},
|
|
53
|
+
"keywords": []
|
|
54
|
+
}
|
package/rollup.config.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import styles from "rollup-plugin-styles";
|
|
2
|
+
const autoprefixer = require("autoprefixer");
|
|
3
|
+
import babel from "@rollup/plugin-babel";
|
|
4
|
+
import json from "@rollup/plugin-json";
|
|
5
|
+
import image from "@rollup/plugin-image";
|
|
6
|
+
import localResolve from "rollup-plugin-local-resolve";
|
|
7
|
+
|
|
8
|
+
// the entry point for the library
|
|
9
|
+
const input = "src/index.js";
|
|
10
|
+
|
|
11
|
+
var MODE = [
|
|
12
|
+
{
|
|
13
|
+
format: "cjs",
|
|
14
|
+
},
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
var config = [];
|
|
18
|
+
|
|
19
|
+
MODE.map((m) => {
|
|
20
|
+
var conf = {
|
|
21
|
+
input: input,
|
|
22
|
+
output: {
|
|
23
|
+
// then name of your package
|
|
24
|
+
name: "@plusscommunities/pluss-feature-builder-web",
|
|
25
|
+
file: `dist/index.${m.format}.js`,
|
|
26
|
+
format: m.format,
|
|
27
|
+
exports: "auto",
|
|
28
|
+
},
|
|
29
|
+
// this externelizes react to prevent rollup from compiling it
|
|
30
|
+
external: [
|
|
31
|
+
"react",
|
|
32
|
+
"react-dom",
|
|
33
|
+
"react-redux",
|
|
34
|
+
"react-router-dom",
|
|
35
|
+
"@fortawesome/react-fontawesome",
|
|
36
|
+
"@fortawesome/fontawesome-svg-core",
|
|
37
|
+
"@fortawesome/free-solid-svg-icons",
|
|
38
|
+
"@plusscommunities/pluss-core-web",
|
|
39
|
+
/@babel\/runtime/,
|
|
40
|
+
],
|
|
41
|
+
plugins: [
|
|
42
|
+
// these are babel comfigurations
|
|
43
|
+
babel({
|
|
44
|
+
exclude: "node_modules/**",
|
|
45
|
+
presets: ["@babel/preset-react", "@babel/preset-env"],
|
|
46
|
+
plugins: [
|
|
47
|
+
"@babel/transform-runtime",
|
|
48
|
+
"@babel/plugin-transform-react-jsx",
|
|
49
|
+
"@babel/plugin-transform-optional-chaining",
|
|
50
|
+
["@babel/plugin-transform-class-properties", { loose: true }],
|
|
51
|
+
],
|
|
52
|
+
babelHelpers: "runtime",
|
|
53
|
+
}),
|
|
54
|
+
// this adds support for styles
|
|
55
|
+
styles({
|
|
56
|
+
postcss: {
|
|
57
|
+
plugins: [autoprefixer()],
|
|
58
|
+
},
|
|
59
|
+
}),
|
|
60
|
+
json(),
|
|
61
|
+
image(),
|
|
62
|
+
localResolve(),
|
|
63
|
+
],
|
|
64
|
+
};
|
|
65
|
+
config.push(conf);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
export default [...config];
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import {
|
|
2
|
+
selectFormTitle,
|
|
3
|
+
selectFormIcon,
|
|
4
|
+
} from "../selectors/featureBuilderSelectors";
|
|
5
|
+
import { values } from "../values.config";
|
|
6
|
+
import { capitalizeTextWithFallback, toTitleCase } from "../utils/textUtils";
|
|
7
|
+
|
|
8
|
+
// IMPORTANT: Using local UPDATE_STRINGS action type to make extension self-contained
|
|
9
|
+
// The main app's StringsReducer will handle this action type the same way
|
|
10
|
+
export const UPDATE_STRINGS = "UPDATE_STRINGS";
|
|
11
|
+
|
|
12
|
+
export const updateFeatureBuilderString = (title) => (dispatch, getState) => {
|
|
13
|
+
const currentStrings = getState().strings?.config || {};
|
|
14
|
+
const titleCased = toTitleCase(title) || values.textMenuTitle;
|
|
15
|
+
const updatedStrings = {
|
|
16
|
+
...currentStrings,
|
|
17
|
+
sideNav: {
|
|
18
|
+
...currentStrings.sideNav,
|
|
19
|
+
[values.featureKey]: titleCased,
|
|
20
|
+
[values.menuKey]: `Manage ${titleCased}`,
|
|
21
|
+
},
|
|
22
|
+
permission: {
|
|
23
|
+
...currentStrings.permission,
|
|
24
|
+
[values.permissionFeatureBuilderDefinition]: `Manage custom feature ${titleCased}`,
|
|
25
|
+
[values.permissionFeatureBuilderContent]: `Manage ${titleCased} content`,
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
dispatch({
|
|
30
|
+
type: UPDATE_STRINGS,
|
|
31
|
+
payload: updatedStrings,
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export const updateFeatureBuilderStringFromStore =
|
|
36
|
+
() => (dispatch, getState) => {
|
|
37
|
+
const title = selectFormTitle(getState());
|
|
38
|
+
dispatch(updateFeatureBuilderString(title));
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export const updateFeatureBuilderIcon = (icon) => (dispatch, getState) => {
|
|
42
|
+
const currentStrings = getState().strings?.config || {};
|
|
43
|
+
const updatedStrings = {
|
|
44
|
+
...currentStrings,
|
|
45
|
+
sideNav: {
|
|
46
|
+
...currentStrings.sideNav,
|
|
47
|
+
[values.featureKey + "-icon"]: icon,
|
|
48
|
+
[values.menuKey + "-icon"]: icon,
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
dispatch({
|
|
53
|
+
type: UPDATE_STRINGS,
|
|
54
|
+
payload: updatedStrings,
|
|
55
|
+
});
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export const updateFeatureBuilderStringAndIcon = () => (dispatch, getState) => {
|
|
59
|
+
const title = selectFormTitle(getState());
|
|
60
|
+
const icon = selectFormIcon(getState());
|
|
61
|
+
|
|
62
|
+
// Update title separately (will be title cased in updateFeatureBuilderString)
|
|
63
|
+
dispatch(updateFeatureBuilderString(title));
|
|
64
|
+
|
|
65
|
+
// Update icon as string
|
|
66
|
+
dispatch(updateFeatureBuilderIcon(icon));
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export const updatePermissionNames = (featureTitle) => (dispatch, getState) => {
|
|
70
|
+
const currentStrings = getState().strings?.config || {};
|
|
71
|
+
|
|
72
|
+
const titleCasedFeature = toTitleCase(featureTitle, "");
|
|
73
|
+
const updatedStrings = {
|
|
74
|
+
...currentStrings,
|
|
75
|
+
permission: {
|
|
76
|
+
...currentStrings.permission,
|
|
77
|
+
[values.permissionFeatureBuilderDefinition]: `Create and Edit ${titleCasedFeature} Features`,
|
|
78
|
+
[values.permissionFeatureBuilderContent]: `Manage ${titleCasedFeature} Content`,
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const result = dispatch({
|
|
83
|
+
type: UPDATE_STRINGS,
|
|
84
|
+
payload: updatedStrings,
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
return result;
|
|
88
|
+
};
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
import { featureDefinitionActions } from "../webapi/featuresActions";
|
|
2
|
+
import { values } from "../values.config.js";
|
|
3
|
+
import {
|
|
4
|
+
updateFeatureBuilderString,
|
|
5
|
+
updateFeatureBuilderIcon,
|
|
6
|
+
updatePermissionNames,
|
|
7
|
+
} from "./featureBuilderStringsActions";
|
|
8
|
+
|
|
9
|
+
export const FETCH_FEATURES_REQUEST = "FETCH_FEATURES_REQUEST";
|
|
10
|
+
export const FETCH_FEATURES_SUCCESS = "FETCH_FEATURES_SUCCESS";
|
|
11
|
+
export const FETCH_FEATURES_FAILURE = "FETCH_FEATURES_FAILURE";
|
|
12
|
+
|
|
13
|
+
export const FEATURE_CREATE_REQUEST = "FEATURE_CREATE_REQUEST";
|
|
14
|
+
export const FEATURE_CREATE_SUCCESS = "FEATURE_CREATE_SUCCESS";
|
|
15
|
+
export const FEATURE_CREATE_FAILURE = "FEATURE_CREATE_FAILURE";
|
|
16
|
+
|
|
17
|
+
export const FEATURE_EDIT_REQUEST = "FEATURE_EDIT_REQUEST";
|
|
18
|
+
export const FEATURE_EDIT_SUCCESS = "FEATURE_EDIT_SUCCESS";
|
|
19
|
+
export const FEATURE_EDIT_FAILURE = "FEATURE_EDIT_FAILURE";
|
|
20
|
+
|
|
21
|
+
export const FEATURE_DELETE_REQUEST = "FEATURE_DELETE_REQUEST";
|
|
22
|
+
export const FEATURE_DELETE_FAILURE = "FEATURE_DELETE_FAILURE";
|
|
23
|
+
|
|
24
|
+
// Wizard synchronization action types
|
|
25
|
+
export const SYNC_WIZARD_MODE_FROM_DEFINITION =
|
|
26
|
+
"SYNC_WIZARD_MODE_FROM_DEFINITION";
|
|
27
|
+
export const SET_WIZARD_MODE = "SET_WIZARD_MODE";
|
|
28
|
+
|
|
29
|
+
function fetchFeaturesRequest() {
|
|
30
|
+
return { type: FETCH_FEATURES_REQUEST };
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function fetchFeaturesSuccess(data, mode) {
|
|
34
|
+
return { type: FETCH_FEATURES_SUCCESS, payload: { data, mode } };
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function fetchFeaturesFailure(data) {
|
|
38
|
+
return { type: FETCH_FEATURES_FAILURE, payload: data };
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function deleteFeatureRequest(id) {
|
|
42
|
+
return { type: FEATURE_DELETE_REQUEST, payload: id };
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function deleteFeatureFailure(id) {
|
|
46
|
+
return { type: FEATURE_DELETE_FAILURE, payload: id };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Action creators for wizard synchronization
|
|
50
|
+
function syncWizardModeFromDefinition(mode) {
|
|
51
|
+
return { type: SYNC_WIZARD_MODE_FROM_DEFINITION, payload: mode };
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function setWizardMode(mode) {
|
|
55
|
+
return { type: SET_WIZARD_MODE, payload: mode };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Action creators for create operations
|
|
59
|
+
function createFeatureRequest() {
|
|
60
|
+
return { type: FEATURE_CREATE_REQUEST };
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function createFeatureSuccess(featureDefinition) {
|
|
64
|
+
return (dispatch) => {
|
|
65
|
+
// Update menu string with title and icon from created definition
|
|
66
|
+
const title = featureDefinition?.title;
|
|
67
|
+
const icon = featureDefinition?.icon;
|
|
68
|
+
|
|
69
|
+
dispatch(updateFeatureBuilderString(title));
|
|
70
|
+
dispatch(updateFeatureBuilderIcon(icon));
|
|
71
|
+
|
|
72
|
+
// Update permission names based on feature title
|
|
73
|
+
dispatch(updatePermissionNames(title));
|
|
74
|
+
|
|
75
|
+
// Dispatch the actual success action
|
|
76
|
+
dispatch({
|
|
77
|
+
type: FEATURE_CREATE_SUCCESS,
|
|
78
|
+
payload: featureDefinition,
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
// After creation, switch wizard to edit mode
|
|
82
|
+
dispatch(setWizardMode("edit"));
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function createFeatureFailure(error) {
|
|
87
|
+
return { type: FEATURE_CREATE_FAILURE, payload: error };
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Action creators for edit operations
|
|
91
|
+
function editFeatureRequest() {
|
|
92
|
+
return { type: FEATURE_EDIT_REQUEST };
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function editFeatureSuccess(featureDefinition) {
|
|
96
|
+
return (dispatch) => {
|
|
97
|
+
// Update menu string with title and icon from edited definition
|
|
98
|
+
const title = featureDefinition?.title;
|
|
99
|
+
const icon = featureDefinition?.icon;
|
|
100
|
+
|
|
101
|
+
dispatch(updateFeatureBuilderString(title));
|
|
102
|
+
dispatch(updateFeatureBuilderIcon(icon));
|
|
103
|
+
|
|
104
|
+
// Update permission names based on feature title
|
|
105
|
+
dispatch(updatePermissionNames(title));
|
|
106
|
+
|
|
107
|
+
// Dispatch the actual success action
|
|
108
|
+
dispatch({
|
|
109
|
+
type: FEATURE_EDIT_SUCCESS,
|
|
110
|
+
payload: featureDefinition,
|
|
111
|
+
});
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function editFeatureFailure(error) {
|
|
116
|
+
return { type: FEATURE_EDIT_FAILURE, payload: error };
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Thunk actions using the new webapi
|
|
120
|
+
export function fetchFeatureDefinitions() {
|
|
121
|
+
return async (dispatch, getState) => {
|
|
122
|
+
dispatch(fetchFeaturesRequest());
|
|
123
|
+
try {
|
|
124
|
+
// Get site from auth store
|
|
125
|
+
const site = getState().auth.site;
|
|
126
|
+
if (!site) {
|
|
127
|
+
throw new Error(
|
|
128
|
+
"Authentication error: Site context not found. Please refresh and login again.",
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
const response = await featureDefinitionActions.getSingle(
|
|
132
|
+
values.featureId,
|
|
133
|
+
site,
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
// Check HTTP status to determine mode
|
|
137
|
+
if (response.status >= 200 && response.status < 300) {
|
|
138
|
+
// 2XX: Feature exists → edit mode
|
|
139
|
+
dispatch(fetchFeaturesSuccess(response.data, "edit"));
|
|
140
|
+
|
|
141
|
+
// Update menu string with title and icon from fetched definition
|
|
142
|
+
const featureDefinitionWrapper =
|
|
143
|
+
response.data?.featureDefinition || response.data;
|
|
144
|
+
const definition =
|
|
145
|
+
featureDefinitionWrapper?.definition || featureDefinitionWrapper;
|
|
146
|
+
const title = definition?.title;
|
|
147
|
+
const icon = definition?.icon;
|
|
148
|
+
dispatch(updateFeatureBuilderString(title));
|
|
149
|
+
dispatch(updateFeatureBuilderIcon(icon));
|
|
150
|
+
|
|
151
|
+
// Synchronize wizard mode with definition
|
|
152
|
+
dispatch(syncWizardModeFromDefinition("edit"));
|
|
153
|
+
} else {
|
|
154
|
+
// Unexpected success status → treat as error
|
|
155
|
+
dispatch(
|
|
156
|
+
fetchFeaturesFailure(
|
|
157
|
+
new Error(`Unexpected response status: ${response.status}`),
|
|
158
|
+
),
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
} catch (err) {
|
|
162
|
+
// Check if it's a 404 (feature doesn't exist)
|
|
163
|
+
if (err.response && err.response.status === 404) {
|
|
164
|
+
// 404: Feature doesn't exist → create mode
|
|
165
|
+
dispatch(fetchFeaturesSuccess(null, "create"));
|
|
166
|
+
|
|
167
|
+
// Reset menu string to default when no feature exists
|
|
168
|
+
dispatch(updateFeatureBuilderString(null));
|
|
169
|
+
|
|
170
|
+
// Synchronize wizard mode with definition
|
|
171
|
+
dispatch(syncWizardModeFromDefinition("create"));
|
|
172
|
+
} else {
|
|
173
|
+
// Other errors: network, server, auth
|
|
174
|
+
dispatch(fetchFeaturesFailure(err));
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export function fetchFeatureDefinition(id) {
|
|
181
|
+
return async (dispatch, getState) => {
|
|
182
|
+
dispatch(fetchFeaturesRequest());
|
|
183
|
+
try {
|
|
184
|
+
// Get site from auth store
|
|
185
|
+
const site = getState().auth.site;
|
|
186
|
+
if (!site) {
|
|
187
|
+
throw new Error(
|
|
188
|
+
"Authentication error: Site context not found. Please refresh and login again.",
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
const { data } = await featureDefinitionActions.getSingle(id, site);
|
|
192
|
+
dispatch(fetchFeaturesSuccess(data));
|
|
193
|
+
} catch (err) {
|
|
194
|
+
dispatch(fetchFeaturesFailure(err));
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
export function createFeatureDefinition(id, site, featureDefinition) {
|
|
200
|
+
return async (dispatch) => {
|
|
201
|
+
dispatch(createFeatureRequest());
|
|
202
|
+
try {
|
|
203
|
+
if (!values.featureId || !site) {
|
|
204
|
+
throw new Error(
|
|
205
|
+
"Authentication error: Missing required context (featureId or site).",
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
const { data } = await featureDefinitionActions.create(
|
|
209
|
+
id,
|
|
210
|
+
site,
|
|
211
|
+
featureDefinition,
|
|
212
|
+
);
|
|
213
|
+
dispatch(createFeatureSuccess(data));
|
|
214
|
+
} catch (err) {
|
|
215
|
+
dispatch(createFeatureFailure(err));
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
export function editFeatureDefinition(featureDefinitionData) {
|
|
221
|
+
return async (dispatch, getState) => {
|
|
222
|
+
dispatch(editFeatureRequest());
|
|
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
|
+
}
|
|
231
|
+
const { data } = await featureDefinitionActions.edit(
|
|
232
|
+
featureDefinitionData,
|
|
233
|
+
site,
|
|
234
|
+
);
|
|
235
|
+
dispatch(editFeatureSuccess(data));
|
|
236
|
+
} catch (err) {
|
|
237
|
+
dispatch(editFeatureFailure(err));
|
|
238
|
+
}
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
export function deleteFeatureDefinition(id) {
|
|
243
|
+
return async (dispatch, getState) => {
|
|
244
|
+
dispatch(deleteFeatureRequest({ id }));
|
|
245
|
+
try {
|
|
246
|
+
// Get site from auth store
|
|
247
|
+
const site = getState().auth.site;
|
|
248
|
+
if (!site) {
|
|
249
|
+
throw new Error(
|
|
250
|
+
"Authentication error: Site context not found. Please refresh and login again.",
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
await featureDefinitionActions.delete(id, site);
|
|
254
|
+
} catch (err) {
|
|
255
|
+
dispatch(deleteFeatureFailure({ id }));
|
|
256
|
+
}
|
|
257
|
+
};
|
|
258
|
+
}
|