@canmingir/link 1.2.64 → 1.2.66
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/components/settings/context/settings-provider.jsx +1 -1
- package/src/http/index.js +9 -9
- package/src/http/user.js +5 -5
- package/src/layouts/common/ProjectBar/index.jsx +6 -6
- package/src/lib/{NucDialog/NucDialog.jsx → APITreeDialog/APITreeDialog.jsx} +6 -8
- package/src/lib/APITreeDialog/index.js +1 -0
- package/src/lib/Flow/layouts/InfoNode.jsx +6 -2
- package/src/lib/index.js +1 -1
- package/src/pages/Callback.jsx +5 -5
- package/src/pages/LoginPage.jsx +2 -2
- package/src/stories/APITree.stories.jsx +18 -8
- package/src/widgets/Login/CognitoLogin.jsx +3 -3
- package/src/widgets/Login/DemoLogin.jsx +3 -3
- package/src/widgets/Login/Login.jsx +2 -2
- package/src/widgets/SettingsDialog.jsx +9 -8
- package/src/ContextProvider/ContextProvider.jsx +0 -19
- package/src/context/Context.js +0 -98
- package/src/context/reducer.js +0 -632
- package/src/layouts/AppLayout.jsx +0 -113
- package/src/lib/NucDialog/index.js +0 -1
- package/src/templates/ActionTemplate.js +0 -24
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@ import { useLocalStorage } from "../../../hooks/use-local-storage";
|
|
|
5
5
|
|
|
6
6
|
import { useCallback, useMemo, useState } from "react";
|
|
7
7
|
|
|
8
|
-
const STORAGE_KEY = "settings";
|
|
8
|
+
const STORAGE_KEY = "link.settings";
|
|
9
9
|
|
|
10
10
|
export function SettingsProvider({ children, defaultSettings }) {
|
|
11
11
|
const { state, update, reset } = useLocalStorage(
|
package/src/http/index.js
CHANGED
|
@@ -14,7 +14,7 @@ const instance = axios.create({
|
|
|
14
14
|
|
|
15
15
|
instance.interceptors.request.use((request) => {
|
|
16
16
|
const { base } = config();
|
|
17
|
-
const accessToken = storage.get("link", "
|
|
17
|
+
const accessToken = storage.get("link", "accesstoken");
|
|
18
18
|
|
|
19
19
|
if (!accessToken) {
|
|
20
20
|
window.location.href = base === "/" ? "/login" : `${base}/login`;
|
|
@@ -40,11 +40,11 @@ function processQueue(error, token = null) {
|
|
|
40
40
|
|
|
41
41
|
async function doRefresh() {
|
|
42
42
|
const { appId } = config();
|
|
43
|
-
const projectId = storage.get("
|
|
44
|
-
const identityProvider = storage.get("link", "
|
|
43
|
+
const projectId = storage.get("link", "projectid");
|
|
44
|
+
const identityProvider = storage.get("link", "identityprovider");
|
|
45
45
|
|
|
46
46
|
const { data } = await oauth.post("/oauth", {
|
|
47
|
-
refreshToken: storage.get("link", "
|
|
47
|
+
refreshToken: storage.get("link", "refreshtoken"),
|
|
48
48
|
appId,
|
|
49
49
|
projectId,
|
|
50
50
|
identityProvider,
|
|
@@ -54,9 +54,9 @@ async function doRefresh() {
|
|
|
54
54
|
}),
|
|
55
55
|
});
|
|
56
56
|
|
|
57
|
-
storage.set("link", "
|
|
57
|
+
storage.set("link", "accesstoken", data.accessToken);
|
|
58
58
|
if (data.refreshToken) {
|
|
59
|
-
storage.set("link", "
|
|
59
|
+
storage.set("link", "refreshtoken", data.refreshToken);
|
|
60
60
|
}
|
|
61
61
|
return data.accessToken;
|
|
62
62
|
}
|
|
@@ -81,7 +81,7 @@ instance.interceptors.response.use(
|
|
|
81
81
|
"Bearer ",
|
|
82
82
|
""
|
|
83
83
|
);
|
|
84
|
-
const storedToken = storage.get("link", "
|
|
84
|
+
const storedToken = storage.get("link", "accesstoken");
|
|
85
85
|
|
|
86
86
|
if (storedToken && storedToken !== usedToken) {
|
|
87
87
|
originalRequest.headers["Authorization"] = `Bearer ${storedToken}`;
|
|
@@ -107,8 +107,8 @@ instance.interceptors.response.use(
|
|
|
107
107
|
} catch (refreshError) {
|
|
108
108
|
processQueue(refreshError, null);
|
|
109
109
|
const { base } = config();
|
|
110
|
-
storage.remove("link", "
|
|
111
|
-
storage.remove("link", "
|
|
110
|
+
storage.remove("link", "accesstoken");
|
|
111
|
+
storage.remove("link", "refreshtoken");
|
|
112
112
|
window.location.href = `${window.location.origin}${base}/login`;
|
|
113
113
|
return Promise.reject(refreshError);
|
|
114
114
|
} finally {
|
package/src/http/user.js
CHANGED
|
@@ -13,7 +13,7 @@ const instance = axios.create({
|
|
|
13
13
|
});
|
|
14
14
|
|
|
15
15
|
instance.interceptors.request.use(async (request) => {
|
|
16
|
-
const refreshToken = await storage.get("link", "
|
|
16
|
+
const refreshToken = await storage.get("link", "refreshtoken");
|
|
17
17
|
if (refreshToken) {
|
|
18
18
|
request.headers["Authorization"] = `Bearer ${refreshToken}`;
|
|
19
19
|
}
|
|
@@ -22,7 +22,7 @@ instance.interceptors.request.use(async (request) => {
|
|
|
22
22
|
|
|
23
23
|
instance.getUserDetails = async () => {
|
|
24
24
|
try {
|
|
25
|
-
const refreshToken = storage.get("link", "
|
|
25
|
+
const refreshToken = storage.get("link", "refreshtoken");
|
|
26
26
|
|
|
27
27
|
if (!refreshToken) {
|
|
28
28
|
return null;
|
|
@@ -47,8 +47,8 @@ instance.getUserDetails = async () => {
|
|
|
47
47
|
|
|
48
48
|
instance.getPermittedUsers = async () => {
|
|
49
49
|
const { appId } = config();
|
|
50
|
-
const projectId = storage.get("
|
|
51
|
-
const identityProvider = storage.get("link", "
|
|
50
|
+
const projectId = storage.get("link", "projectid");
|
|
51
|
+
const identityProvider = storage.get("link", "identityprovider");
|
|
52
52
|
|
|
53
53
|
const response = await http.get("/permissions");
|
|
54
54
|
|
|
@@ -110,7 +110,7 @@ instance.getPermittedUsers = async () => {
|
|
|
110
110
|
}
|
|
111
111
|
|
|
112
112
|
if (identityProvider?.toUpperCase() === "COGNITO") {
|
|
113
|
-
const accessToken = await storage.get("link", "
|
|
113
|
+
const accessToken = await storage.get("link", "accesstoken");
|
|
114
114
|
let currentUserId = null;
|
|
115
115
|
|
|
116
116
|
try {
|
|
@@ -45,7 +45,7 @@ function ProjectBar() {
|
|
|
45
45
|
}, [projectCreated]);
|
|
46
46
|
|
|
47
47
|
const id = window.matchMedia("projectId").matches;
|
|
48
|
-
const [selectedProjectId] = useStorage("
|
|
48
|
+
const [selectedProjectId] = useStorage("link", "projectid", id);
|
|
49
49
|
|
|
50
50
|
const [selectedProject, setSelectedProject] = useState();
|
|
51
51
|
|
|
@@ -91,7 +91,7 @@ function ProjectBar() {
|
|
|
91
91
|
const handleSelect = (project) => {
|
|
92
92
|
const { id: projectId } = project;
|
|
93
93
|
|
|
94
|
-
const identityProviderRaw = storage.get("link", "
|
|
94
|
+
const identityProviderRaw = storage.get("link", "identityprovider");
|
|
95
95
|
const identityProvider = identityProviderRaw?.toUpperCase();
|
|
96
96
|
|
|
97
97
|
const payload = {
|
|
@@ -104,7 +104,7 @@ function ProjectBar() {
|
|
|
104
104
|
payload.username = "admin";
|
|
105
105
|
payload.password = "admin";
|
|
106
106
|
} else {
|
|
107
|
-
payload.refreshToken = storage.get("link", "
|
|
107
|
+
payload.refreshToken = storage.get("link", "refreshtoken");
|
|
108
108
|
}
|
|
109
109
|
|
|
110
110
|
const request = oauth.post("/oauth", payload);
|
|
@@ -112,9 +112,9 @@ function ProjectBar() {
|
|
|
112
112
|
request
|
|
113
113
|
.then(({ data }) => {
|
|
114
114
|
const { refreshToken, accessToken } = data;
|
|
115
|
-
storage.set("link", "
|
|
116
|
-
storage.set("link", "
|
|
117
|
-
storage.set("
|
|
115
|
+
storage.set("link", "accesstoken", accessToken);
|
|
116
|
+
storage.set("link", "refreshtoken", refreshToken);
|
|
117
|
+
storage.set("link", "projectid", projectId);
|
|
118
118
|
})
|
|
119
119
|
.finally(() => {
|
|
120
120
|
setSelectedProject(project);
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
|
|
3
1
|
import { Close, Fullscreen, FullscreenExit } from "@mui/icons-material";
|
|
4
2
|
import {
|
|
5
3
|
Dialog,
|
|
@@ -8,9 +6,9 @@ import {
|
|
|
8
6
|
DialogTitle,
|
|
9
7
|
IconButton,
|
|
10
8
|
} from "@mui/material";
|
|
11
|
-
import {
|
|
9
|
+
import React, { useState } from "react";
|
|
12
10
|
|
|
13
|
-
function
|
|
11
|
+
function APITreeDialog({
|
|
14
12
|
title,
|
|
15
13
|
minWidth = 600,
|
|
16
14
|
children,
|
|
@@ -20,7 +18,7 @@ function NucDialog({
|
|
|
20
18
|
maximizedDimensions = { width: "65rem", height: "50rem" },
|
|
21
19
|
minimizedDimensions = { width: "55rem", height: "40rem" },
|
|
22
20
|
}) {
|
|
23
|
-
const [maximized] =
|
|
21
|
+
const [maximized, setMaximized] = useState(false);
|
|
24
22
|
const currentDimensions = maximized
|
|
25
23
|
? maximizedDimensions
|
|
26
24
|
: minimizedDimensions;
|
|
@@ -63,7 +61,7 @@ function NucDialog({
|
|
|
63
61
|
{maximized ? (
|
|
64
62
|
<IconButton
|
|
65
63
|
aria-label="collapse"
|
|
66
|
-
onClick={() =>
|
|
64
|
+
onClick={() => setMaximized(false)}
|
|
67
65
|
sx={{
|
|
68
66
|
position: "absolute",
|
|
69
67
|
right: 48,
|
|
@@ -76,7 +74,7 @@ function NucDialog({
|
|
|
76
74
|
) : (
|
|
77
75
|
<IconButton
|
|
78
76
|
aria-label="expand"
|
|
79
|
-
onClick={() =>
|
|
77
|
+
onClick={() => setMaximized(true)}
|
|
80
78
|
sx={{
|
|
81
79
|
position: "absolute",
|
|
82
80
|
right: 48,
|
|
@@ -105,4 +103,4 @@ function NucDialog({
|
|
|
105
103
|
);
|
|
106
104
|
}
|
|
107
105
|
|
|
108
|
-
export default
|
|
106
|
+
export default APITreeDialog;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from "./APITreeDialog";
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import { Iconify } from "@canmingir/link/platform/components";
|
|
2
|
+
|
|
1
3
|
import React, { useEffect, useState } from "react";
|
|
2
4
|
import { alpha, styled } from "@mui/material/styles";
|
|
3
5
|
|
|
4
|
-
import { Iconify } from "@canmingir/link/platform/components";
|
|
5
|
-
|
|
6
6
|
const ANIMATION_DELAY_MS = 200;
|
|
7
7
|
|
|
8
8
|
const MainContainer = styled("div", {
|
|
@@ -79,6 +79,10 @@ const IconContainer = styled("div", {
|
|
|
79
79
|
display: "flex",
|
|
80
80
|
alignItems: "center",
|
|
81
81
|
justifyContent: "center",
|
|
82
|
+
boxShadow: `
|
|
83
|
+
4px 4px 0 rgba(255, 255, 255, 0.1),
|
|
84
|
+
5px 5px 5px rgba(0, 0, 0, 0.5)
|
|
85
|
+
`,
|
|
82
86
|
|
|
83
87
|
'[data-hovered="true"] &': {
|
|
84
88
|
backgroundColor: hoverBg,
|
package/src/lib/index.js
CHANGED
|
@@ -42,7 +42,7 @@ export { default as APIPath } from "./APIPath";
|
|
|
42
42
|
export { default as APITypes } from "./APITypes";
|
|
43
43
|
export { default as BlankTreeMessage } from "./BlankTreeMessage";
|
|
44
44
|
export { default as DialogTooltip } from "./DialogTootip";
|
|
45
|
-
export { default as
|
|
45
|
+
export { default as APITreeDialog } from "./APITreeDialog";
|
|
46
46
|
export { default as ParamTable } from "./ParamTable";
|
|
47
47
|
export { default as ResourceMenu } from "./ResourceMenu";
|
|
48
48
|
export { default as Schema } from "./Schema";
|
package/src/pages/Callback.jsx
CHANGED
|
@@ -72,10 +72,10 @@ function Callback() {
|
|
|
72
72
|
const defaultProjectId = "05708cf7-b9bf-4209-95fe-68d9138d2032";
|
|
73
73
|
|
|
74
74
|
if (projectBar) {
|
|
75
|
-
projectId = storage.get("
|
|
75
|
+
projectId = storage.get("link", "projectid");
|
|
76
76
|
} else {
|
|
77
77
|
projectId = defaultProjectId;
|
|
78
|
-
storage.set("
|
|
78
|
+
storage.set("link", "projectid", projectId);
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
oauth
|
|
@@ -91,10 +91,10 @@ function Callback() {
|
|
|
91
91
|
const accessToken = data.accessToken;
|
|
92
92
|
const refreshToken = data.refreshToken;
|
|
93
93
|
|
|
94
|
-
storage.set("link", "
|
|
95
|
-
storage.set("link", "
|
|
94
|
+
storage.set("link", "accesstoken", accessToken);
|
|
95
|
+
storage.set("link", "refreshtoken", refreshToken);
|
|
96
96
|
// TODO - update provider info
|
|
97
|
-
storage.set("link", "
|
|
97
|
+
storage.set("link", "identityprovider", identityProvider);
|
|
98
98
|
|
|
99
99
|
publish("LOGIN", { data: data });
|
|
100
100
|
|
package/src/pages/LoginPage.jsx
CHANGED
|
@@ -2,10 +2,10 @@ import APIDialogAction from "../lib/APIDialogAction/APIDialogAction";
|
|
|
2
2
|
import APIParams from "../lib/APIParams/APIParams";
|
|
3
3
|
import APIPath from "../lib/APIPath/APIPath";
|
|
4
4
|
import APITree from "../lib/APITree/APITree";
|
|
5
|
+
import APITreeDialog from "../lib/APITreeDialog/APITreeDialog";
|
|
5
6
|
import APITypes from "../lib/APITypes/APITypes";
|
|
6
7
|
import CssBaseline from "@mui/material/CssBaseline";
|
|
7
8
|
import NewAPIBody from "../lib/NewApiBody/NewAPIBody";
|
|
8
|
-
import NucDialog from "../lib/NucDialog/NucDialog";
|
|
9
9
|
|
|
10
10
|
import { Box, Divider } from "@mui/material";
|
|
11
11
|
import React, { useEffect, useRef, useState } from "react";
|
|
@@ -80,7 +80,8 @@ export default {
|
|
|
80
80
|
description: {
|
|
81
81
|
component:
|
|
82
82
|
"APITree displays API endpoints in a tree structure grouped by path segments. " +
|
|
83
|
-
"It
|
|
83
|
+
"It is a controlled component: selection and expansion are driven by the " +
|
|
84
|
+
"selected/expanded props and reported via onSelect/onExpand.",
|
|
84
85
|
},
|
|
85
86
|
},
|
|
86
87
|
layout: "centered",
|
|
@@ -92,6 +93,8 @@ const ALL_METHODS = ["GET", "POST", "PUT", "DELETE", "PATCH"];
|
|
|
92
93
|
const APIWorkspace = () => {
|
|
93
94
|
const [view, setView] = useState("PARAMS");
|
|
94
95
|
const [dialogKey, setDialogKey] = useState(0);
|
|
96
|
+
const [expanded, setExpanded] = useState(["/", "/items"]);
|
|
97
|
+
const [selectedItem, setSelectedItem] = useState(null);
|
|
95
98
|
|
|
96
99
|
const methodRef = useRef("GET");
|
|
97
100
|
const pathRef = useRef("/");
|
|
@@ -337,10 +340,17 @@ const APIWorkspace = () => {
|
|
|
337
340
|
return (
|
|
338
341
|
<Box sx={{ display: "flex", height: "100%", gap: 2 }}>
|
|
339
342
|
<Box sx={{ width: 280, flexShrink: 0, height: "100%" }}>
|
|
340
|
-
<APITree
|
|
343
|
+
<APITree
|
|
344
|
+
api={api}
|
|
345
|
+
theme={theme}
|
|
346
|
+
expanded={expanded}
|
|
347
|
+
selected={selectedItem}
|
|
348
|
+
onExpand={(_event, itemIds) => setExpanded(itemIds)}
|
|
349
|
+
onSelect={(_event, itemId) => setSelectedItem(itemId)}
|
|
350
|
+
/>
|
|
341
351
|
</Box>
|
|
342
352
|
|
|
343
|
-
<
|
|
353
|
+
<APITreeDialog
|
|
344
354
|
title={dialogTitle}
|
|
345
355
|
open={dialog.open}
|
|
346
356
|
handleClose={handleCloseDialog}
|
|
@@ -398,7 +408,7 @@ const APIWorkspace = () => {
|
|
|
398
408
|
<APITypes tstypes={[]} nuctypes={types} typesRef={typesRef} />
|
|
399
409
|
)}
|
|
400
410
|
</Box>
|
|
401
|
-
</
|
|
411
|
+
</APITreeDialog>
|
|
402
412
|
</Box>
|
|
403
413
|
);
|
|
404
414
|
};
|
|
@@ -420,9 +430,9 @@ export const APITreeWorkspace = {
|
|
|
420
430
|
docs: {
|
|
421
431
|
description: {
|
|
422
432
|
story:
|
|
423
|
-
"Full workspace:
|
|
424
|
-
"
|
|
425
|
-
"
|
|
433
|
+
"Full workspace: click a method node to select it, then use the API dialog " +
|
|
434
|
+
"events (API_DIALOG_OPEN) to add or edit endpoints, configuring the path, " +
|
|
435
|
+
"method, params, and body before saving.",
|
|
426
436
|
},
|
|
427
437
|
},
|
|
428
438
|
},
|
|
@@ -69,9 +69,9 @@ export default function CognitoLogin() {
|
|
|
69
69
|
|
|
70
70
|
const data = await res.json();
|
|
71
71
|
|
|
72
|
-
storage.set("link", "
|
|
73
|
-
storage.set("link", "
|
|
74
|
-
storage.set("link", "
|
|
72
|
+
storage.set("link", "accesstoken", data.accessToken);
|
|
73
|
+
storage.set("link", "refreshtoken", data.refreshToken);
|
|
74
|
+
storage.set("link", "identityprovider", "COGNITO");
|
|
75
75
|
|
|
76
76
|
navigate("/");
|
|
77
77
|
} catch (e) {
|
|
@@ -43,9 +43,9 @@ export default function DemoLogin() {
|
|
|
43
43
|
|
|
44
44
|
const data = await res.json();
|
|
45
45
|
|
|
46
|
-
storage.set("link", "
|
|
47
|
-
storage.set("link", "
|
|
48
|
-
storage.set("link", "
|
|
46
|
+
storage.set("link", "accesstoken", data.accessToken);
|
|
47
|
+
storage.set("link", "refreshtoken", data.refreshToken);
|
|
48
|
+
storage.set("link", "identityprovider", "DEMO");
|
|
49
49
|
|
|
50
50
|
navigate("/");
|
|
51
51
|
}
|
|
@@ -18,8 +18,8 @@ export default function Auth0LoginView() {
|
|
|
18
18
|
|
|
19
19
|
function token() {
|
|
20
20
|
if (
|
|
21
|
-
storage.get("link", "
|
|
22
|
-
storage.get("link", "
|
|
21
|
+
storage.get("link", "refreshtoken") &&
|
|
22
|
+
storage.get("link", "accesstoken")
|
|
23
23
|
) {
|
|
24
24
|
return true;
|
|
25
25
|
} else {
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
import Iconify from "../components/Iconify";
|
|
2
|
+
import config from "../config/config";
|
|
3
|
+
import { useEvent } from "@nucleoidai/react-event";
|
|
4
|
+
import useSettings from "../hooks/useSettings";
|
|
5
|
+
import { useSettingsContext } from "../components/settings/context";
|
|
6
|
+
import { useStorage } from "@nucleoidjs/webstorage";
|
|
7
|
+
import { useUser } from "../hooks/use-user";
|
|
8
|
+
|
|
1
9
|
import {
|
|
2
10
|
Avatar,
|
|
3
11
|
Box,
|
|
@@ -23,13 +31,6 @@ import {
|
|
|
23
31
|
import { Button, Dialog, DialogActions, DialogContent } from "@mui/material";
|
|
24
32
|
import React, { useEffect, useState } from "react";
|
|
25
33
|
|
|
26
|
-
import Iconify from "../components/Iconify";
|
|
27
|
-
import config from "../config/config";
|
|
28
|
-
import { useEvent } from "@nucleoidai/react-event";
|
|
29
|
-
import useSettings from "../hooks/useSettings";
|
|
30
|
-
import { useSettingsContext } from "../components/settings/context";
|
|
31
|
-
import { useUser } from "../hooks/use-user";
|
|
32
|
-
|
|
33
34
|
let pkg = {
|
|
34
35
|
name: "",
|
|
35
36
|
version: "",
|
|
@@ -296,7 +297,7 @@ const Permission = () => {
|
|
|
296
297
|
};
|
|
297
298
|
|
|
298
299
|
const Settings = () => {
|
|
299
|
-
const projectId =
|
|
300
|
+
const [projectId] = useStorage("link", "projectid");
|
|
300
301
|
const { settings, updateSettings } = useSettings(projectId);
|
|
301
302
|
const { beta, onUpdate } = useSettingsContext();
|
|
302
303
|
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
|
|
3
|
-
const ContextStore = React.createContext();
|
|
4
|
-
ContextStore.displayName = "ContextStore";
|
|
5
|
-
|
|
6
|
-
const useContext = () => React.useContext(ContextStore);
|
|
7
|
-
|
|
8
|
-
const ContextProvider = ({ children, state, reducer }) => {
|
|
9
|
-
const [contextState, contextDispatch] = React.useReducer(reducer, state);
|
|
10
|
-
|
|
11
|
-
return (
|
|
12
|
-
<ContextStore.Provider value={[contextState, contextDispatch]}>
|
|
13
|
-
{children}
|
|
14
|
-
</ContextStore.Provider>
|
|
15
|
-
);
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
export { useContext };
|
|
19
|
-
export default ContextProvider;
|
package/src/context/Context.js
DELETED
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
class Context {
|
|
2
|
-
constructor(data = {}) {
|
|
3
|
-
this.login = data.login !== undefined ? data.login : false;
|
|
4
|
-
this.itemId = data.itemId || null;
|
|
5
|
-
|
|
6
|
-
this.specification = {
|
|
7
|
-
api: [],
|
|
8
|
-
functions: [],
|
|
9
|
-
types: [],
|
|
10
|
-
declarations: [],
|
|
11
|
-
...(data.specification || {}),
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
this.pages = {
|
|
15
|
-
api: {
|
|
16
|
-
selected: { path: "/", method: "get" },
|
|
17
|
-
dialog: {
|
|
18
|
-
type: null,
|
|
19
|
-
action: null,
|
|
20
|
-
open: false,
|
|
21
|
-
view: null,
|
|
22
|
-
map: {},
|
|
23
|
-
params: {},
|
|
24
|
-
},
|
|
25
|
-
resourceMenu: {
|
|
26
|
-
open: false,
|
|
27
|
-
anchor: null,
|
|
28
|
-
path: null,
|
|
29
|
-
},
|
|
30
|
-
...(data.pages?.api || {}),
|
|
31
|
-
},
|
|
32
|
-
functions: {
|
|
33
|
-
selected: null,
|
|
34
|
-
dialog: {
|
|
35
|
-
type: null,
|
|
36
|
-
open: false,
|
|
37
|
-
},
|
|
38
|
-
AIDialog: {
|
|
39
|
-
open: false,
|
|
40
|
-
},
|
|
41
|
-
...(data.pages?.functions || {}),
|
|
42
|
-
},
|
|
43
|
-
logic: {
|
|
44
|
-
selected: null,
|
|
45
|
-
AIDialog: {
|
|
46
|
-
open: false,
|
|
47
|
-
},
|
|
48
|
-
...(data.pages?.logic || {}),
|
|
49
|
-
},
|
|
50
|
-
query: {
|
|
51
|
-
results: null,
|
|
52
|
-
...(data.pages?.query || {}),
|
|
53
|
-
},
|
|
54
|
-
...(data.pages || {}),
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
static copy(context) {
|
|
59
|
-
const copied = new Context();
|
|
60
|
-
|
|
61
|
-
copied.login = context.login;
|
|
62
|
-
copied.itemId = context.itemId;
|
|
63
|
-
|
|
64
|
-
copied.specification = {
|
|
65
|
-
api: context.specification?.api ? [...context.specification.api] : [],
|
|
66
|
-
functions: context.specification?.functions
|
|
67
|
-
? [...context.specification.functions]
|
|
68
|
-
: [],
|
|
69
|
-
types: context.specification?.types
|
|
70
|
-
? [...context.specification.types]
|
|
71
|
-
: [],
|
|
72
|
-
declarations: context.specification?.declarations
|
|
73
|
-
? [...context.specification.declarations]
|
|
74
|
-
: [],
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
copied.pages = JSON.parse(JSON.stringify(context.pages || {}));
|
|
78
|
-
|
|
79
|
-
return copied;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
get(path) {
|
|
83
|
-
const keys = path.split(".");
|
|
84
|
-
let result = this;
|
|
85
|
-
|
|
86
|
-
for (const key of keys) {
|
|
87
|
-
if (result && typeof result === "object" && key in result) {
|
|
88
|
-
result = result[key];
|
|
89
|
-
} else {
|
|
90
|
-
return undefined;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
return result;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
export default Context;
|
package/src/context/reducer.js
DELETED
|
@@ -1,632 +0,0 @@
|
|
|
1
|
-
import ActionTemplate from "../templates/ActionTemplate.js";
|
|
2
|
-
import Context from "./Context.js";
|
|
3
|
-
import { jwtDecode } from "jwt-decode";
|
|
4
|
-
import { publish } from "@nucleoidai/react-event";
|
|
5
|
-
import { storage } from "@nucleoidjs/webstorage";
|
|
6
|
-
import { v4 as uuid } from "uuid";
|
|
7
|
-
|
|
8
|
-
let login = true;
|
|
9
|
-
const itemId = storage.get("itemId");
|
|
10
|
-
try {
|
|
11
|
-
const token = storage.get("link", "accessToken");
|
|
12
|
-
const decodedToken = jwtDecode(token);
|
|
13
|
-
|
|
14
|
-
if (decodedToken.exp * 1000 < Date.now()) {
|
|
15
|
-
login = false;
|
|
16
|
-
}
|
|
17
|
-
} catch (err) {
|
|
18
|
-
login = false;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export const initialState = new Context({
|
|
22
|
-
login,
|
|
23
|
-
itemId,
|
|
24
|
-
specification: {
|
|
25
|
-
api: [],
|
|
26
|
-
functions: [],
|
|
27
|
-
types: [],
|
|
28
|
-
declarations: [],
|
|
29
|
-
},
|
|
30
|
-
pages: {
|
|
31
|
-
api: {
|
|
32
|
-
selected: { path: "/", method: "get" },
|
|
33
|
-
dialog: {
|
|
34
|
-
type: null,
|
|
35
|
-
action: null,
|
|
36
|
-
open: false,
|
|
37
|
-
view: null,
|
|
38
|
-
map: {},
|
|
39
|
-
params: {},
|
|
40
|
-
},
|
|
41
|
-
resourceMenu: {
|
|
42
|
-
open: false,
|
|
43
|
-
anchor: null,
|
|
44
|
-
path: null,
|
|
45
|
-
},
|
|
46
|
-
},
|
|
47
|
-
functions: {
|
|
48
|
-
selected: null,
|
|
49
|
-
dialog: {
|
|
50
|
-
type: null,
|
|
51
|
-
open: false,
|
|
52
|
-
},
|
|
53
|
-
AIDialog: {
|
|
54
|
-
open: false,
|
|
55
|
-
},
|
|
56
|
-
},
|
|
57
|
-
logic: {
|
|
58
|
-
selected: null,
|
|
59
|
-
AIDialog: {
|
|
60
|
-
open: false,
|
|
61
|
-
},
|
|
62
|
-
},
|
|
63
|
-
query: {
|
|
64
|
-
results: null,
|
|
65
|
-
},
|
|
66
|
-
},
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
export const reducer = (context, action) => {
|
|
70
|
-
context = Context.copy(context);
|
|
71
|
-
|
|
72
|
-
const { specification, pages } = context;
|
|
73
|
-
|
|
74
|
-
switch (action.type) {
|
|
75
|
-
case "LOGIN": {
|
|
76
|
-
context.login = true;
|
|
77
|
-
break;
|
|
78
|
-
}
|
|
79
|
-
case "LOGOUT": {
|
|
80
|
-
storage.clear();
|
|
81
|
-
context.login = false;
|
|
82
|
-
break;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
case "ITEM_SELECT": {
|
|
86
|
-
context.itemId = action.payload;
|
|
87
|
-
storage.set("itemId", context.itemId);
|
|
88
|
-
break;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
case "ITEM_DELETE": {
|
|
92
|
-
storage.remove("itemId");
|
|
93
|
-
context.itemId = null;
|
|
94
|
-
break;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
case "SET_PROJECT": {
|
|
98
|
-
specification.api = action.payload.project.specification.api;
|
|
99
|
-
specification.functions = action.payload.project.specification.functions;
|
|
100
|
-
specification.types = action.payload.project.specification.types;
|
|
101
|
-
pages.api.selected.path = "/";
|
|
102
|
-
break;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
case "OPEN_API_DIALOG": {
|
|
106
|
-
const { type, action: dialogAction } = action.payload;
|
|
107
|
-
pages.api.dialog.type = type;
|
|
108
|
-
pages.api.dialog.action = dialogAction;
|
|
109
|
-
pages.api.dialog.open = true;
|
|
110
|
-
break;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
case "SAVE_API_DIALOG": {
|
|
114
|
-
const {
|
|
115
|
-
path,
|
|
116
|
-
method,
|
|
117
|
-
request,
|
|
118
|
-
response,
|
|
119
|
-
params,
|
|
120
|
-
types,
|
|
121
|
-
summary,
|
|
122
|
-
description,
|
|
123
|
-
} = action.payload;
|
|
124
|
-
|
|
125
|
-
const newApi = {
|
|
126
|
-
path,
|
|
127
|
-
method,
|
|
128
|
-
request,
|
|
129
|
-
response,
|
|
130
|
-
params,
|
|
131
|
-
summary,
|
|
132
|
-
description,
|
|
133
|
-
action: ActionTemplate[method.toUpperCase()],
|
|
134
|
-
};
|
|
135
|
-
pages.api.dialog.open = false;
|
|
136
|
-
specification.api.push(newApi);
|
|
137
|
-
pages.api.selected = { path, method };
|
|
138
|
-
publish("SELECTED_API_CHANGED", {
|
|
139
|
-
path: path,
|
|
140
|
-
method: method,
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
specification.types = types;
|
|
144
|
-
break;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
case "CLOSE_API_DIALOG": {
|
|
148
|
-
pages.api.dialog.open = false;
|
|
149
|
-
break;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
case "SET_API_DIALOG_VIEW":
|
|
153
|
-
pages.api.dialog.view = action.payload.view;
|
|
154
|
-
break;
|
|
155
|
-
|
|
156
|
-
case "SET_SELECTED_API": {
|
|
157
|
-
if (action.payload.method === null) {
|
|
158
|
-
const endpoint = specification.api.find(
|
|
159
|
-
(endpoint) => endpoint.path === action.payload.path
|
|
160
|
-
);
|
|
161
|
-
|
|
162
|
-
if (endpoint && endpoint.method) {
|
|
163
|
-
action.payload.method = endpoint.method;
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
pages.api.selected = {
|
|
167
|
-
path: action.payload.path,
|
|
168
|
-
method: action.payload.method,
|
|
169
|
-
};
|
|
170
|
-
|
|
171
|
-
publish("SELECTED_API_CHANGED", {
|
|
172
|
-
path: action.payload.path,
|
|
173
|
-
method: action.payload.method,
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
break;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
case "SET_SELECTED_FUNCTION": {
|
|
180
|
-
pages.functions.selected = action.payload.function;
|
|
181
|
-
break;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
case "SET_SELECTED_LOGIC": {
|
|
185
|
-
pages.logic.selected = action.payload.logic;
|
|
186
|
-
break;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
// ===== Resource Menu Actions =====
|
|
190
|
-
case "OPEN_RESOURCE_MENU":
|
|
191
|
-
pages.api.resourceMenu.open = true;
|
|
192
|
-
pages.api.resourceMenu.anchor = action.payload.anchor;
|
|
193
|
-
pages.api.resourceMenu.path = action.payload.path;
|
|
194
|
-
break;
|
|
195
|
-
|
|
196
|
-
case "DELETE_RESOURCE": {
|
|
197
|
-
const { path } = action.payload;
|
|
198
|
-
|
|
199
|
-
specification.api = specification.api.filter(
|
|
200
|
-
(api) => !api.path.startsWith(path)
|
|
201
|
-
);
|
|
202
|
-
|
|
203
|
-
if (pages.api.selected.path.startsWith(path)) {
|
|
204
|
-
if (specification.api.length > 0) {
|
|
205
|
-
pages.api.selected.path = specification.api[0].path;
|
|
206
|
-
pages.api.selected.method = specification.api[0].method;
|
|
207
|
-
} else {
|
|
208
|
-
pages.api.selected.path = "/";
|
|
209
|
-
pages.api.selected.method = "get";
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
publish("SELECTED_API_CHANGED", {
|
|
213
|
-
path: pages.api.selected.path,
|
|
214
|
-
method: pages.api.selected.method,
|
|
215
|
-
});
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
break;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
case "DELETE_METHOD": {
|
|
222
|
-
const { path, method } = pages.api.selected;
|
|
223
|
-
|
|
224
|
-
const routeIndex = specification.api.findIndex(
|
|
225
|
-
(route) =>
|
|
226
|
-
route.path === path &&
|
|
227
|
-
route.method.toLowerCase() === method.toLowerCase()
|
|
228
|
-
);
|
|
229
|
-
|
|
230
|
-
if (routeIndex !== -1) {
|
|
231
|
-
specification.api.splice(routeIndex, 1);
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
const samePathRoutes = specification.api.filter(
|
|
235
|
-
(route) => route.path === path
|
|
236
|
-
);
|
|
237
|
-
if (samePathRoutes.length > 0) {
|
|
238
|
-
context.pages.api.selected.method = samePathRoutes[0].method;
|
|
239
|
-
} else {
|
|
240
|
-
context.pages.api.selected.method = null;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
break;
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
case "CLOSE_RESOURCE_MENU":
|
|
247
|
-
pages.api.resourceMenu.open = false;
|
|
248
|
-
pages.api.resourceMenu = {};
|
|
249
|
-
break;
|
|
250
|
-
|
|
251
|
-
// ===== Function Dialog Actions =====
|
|
252
|
-
case "OPEN_FUNCTION_DIALOG": {
|
|
253
|
-
pages.functions.dialog.type = action.payload.type;
|
|
254
|
-
pages.functions.dialog.open = true;
|
|
255
|
-
break;
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
case "OPEN_AI_DIALOG": {
|
|
259
|
-
const page = action.payload.page;
|
|
260
|
-
pages[page].AIDialog.open = true;
|
|
261
|
-
break;
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
case "CLOSE_AI_DIALOG": {
|
|
265
|
-
const page = action.payload.page;
|
|
266
|
-
pages[page].AIDialog.open = false;
|
|
267
|
-
break;
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
case "SAVE_LOGIC_DIALOG": {
|
|
271
|
-
const { description, summary, definition } = action.payload;
|
|
272
|
-
const declarations = specification.declarations;
|
|
273
|
-
|
|
274
|
-
declarations.push({
|
|
275
|
-
description,
|
|
276
|
-
summary,
|
|
277
|
-
definition,
|
|
278
|
-
});
|
|
279
|
-
|
|
280
|
-
publish("LOGIC_ADDED", {
|
|
281
|
-
declaration: declarations[declarations.length - 1],
|
|
282
|
-
});
|
|
283
|
-
|
|
284
|
-
break;
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
case "SAVE_FUNCTION_DIALOG": {
|
|
288
|
-
const { path, type, definition, params, ext } = action.payload;
|
|
289
|
-
const functions = specification.functions;
|
|
290
|
-
|
|
291
|
-
functions.push({
|
|
292
|
-
path,
|
|
293
|
-
type,
|
|
294
|
-
ext,
|
|
295
|
-
definition,
|
|
296
|
-
params,
|
|
297
|
-
});
|
|
298
|
-
|
|
299
|
-
publish("CONTEXT_CHANGED", {
|
|
300
|
-
files: [{ key: `${path}.${ext}`, value: definition }],
|
|
301
|
-
});
|
|
302
|
-
|
|
303
|
-
break;
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
case "DELETE_FUNCTION": {
|
|
307
|
-
const { path } = action.payload;
|
|
308
|
-
|
|
309
|
-
if (specification.functions.length > 1) {
|
|
310
|
-
const index = specification.functions.findIndex(
|
|
311
|
-
(data) => data.path === path
|
|
312
|
-
);
|
|
313
|
-
|
|
314
|
-
const deletedFunction = specification.functions[index];
|
|
315
|
-
specification.functions.splice(index, 1);
|
|
316
|
-
|
|
317
|
-
const remainingFunctions = specification.functions.filter(
|
|
318
|
-
(data) => data.path !== path
|
|
319
|
-
);
|
|
320
|
-
|
|
321
|
-
const files = remainingFunctions.map((func) => ({
|
|
322
|
-
key: `${func.path}.ts`,
|
|
323
|
-
value: func,
|
|
324
|
-
}));
|
|
325
|
-
|
|
326
|
-
publish("CONTEXT_CHANGED", {
|
|
327
|
-
files: [{ key: `${deletedFunction.path}.ts` }, ...files],
|
|
328
|
-
});
|
|
329
|
-
context.pages.functions.selected = specification.functions[0].path;
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
break;
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
case "CLOSE_FUNCTION_DIALOG": {
|
|
336
|
-
pages.functions.dialog.open = false;
|
|
337
|
-
break;
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
// ===== Type Management Actions =====
|
|
341
|
-
case "UPDATE_TYPE": {
|
|
342
|
-
const { id, name, type } = action.payload;
|
|
343
|
-
const map = pages.api.dialog.map;
|
|
344
|
-
|
|
345
|
-
if (name !== undefined) map[id].name = name;
|
|
346
|
-
if (type !== undefined) {
|
|
347
|
-
if (map[id].type === "array") map[id].items.type = type;
|
|
348
|
-
else {
|
|
349
|
-
map[id].type = type;
|
|
350
|
-
|
|
351
|
-
if (type === "array") map[id].items = { type: "integer" };
|
|
352
|
-
else if (type === "object") map[id].properties = {};
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
break;
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
case "ADD_SCHEMA_PROPERTY": {
|
|
360
|
-
const { id } = action.payload;
|
|
361
|
-
const map = pages.api.dialog.map;
|
|
362
|
-
const key = uuid();
|
|
363
|
-
map[key] = map[id].properties[key] = {
|
|
364
|
-
id: key,
|
|
365
|
-
type: "integer",
|
|
366
|
-
};
|
|
367
|
-
break;
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
case "REMOVE_SCHEMA_PROPERTY": {
|
|
371
|
-
const { id } = action.payload;
|
|
372
|
-
const map = pages.api.dialog.map;
|
|
373
|
-
delete map[id];
|
|
374
|
-
break;
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
case "ADD_PARAM": {
|
|
378
|
-
const map = pages.api.dialog.map;
|
|
379
|
-
const id = uuid();
|
|
380
|
-
pages.api.dialog.params[id] = map[id] = {
|
|
381
|
-
id,
|
|
382
|
-
type: "string",
|
|
383
|
-
required: true,
|
|
384
|
-
};
|
|
385
|
-
break;
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
case "REMOVE_PARAM": {
|
|
389
|
-
const { id } = action.payload;
|
|
390
|
-
const map = pages.api.dialog.map;
|
|
391
|
-
delete pages.api.dialog.params[id];
|
|
392
|
-
delete map[id];
|
|
393
|
-
break;
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
case "QUERY_RESULTS": {
|
|
397
|
-
const query = context.get("pages.query");
|
|
398
|
-
query.results = action.payload.results;
|
|
399
|
-
break;
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
// ===== CRUD Actions =====
|
|
403
|
-
case "CREATE_SAMPLE_CRUD": {
|
|
404
|
-
const { api, functions } = specification;
|
|
405
|
-
const className = action.payload.resource;
|
|
406
|
-
const resource = action.payload.resource.toLowerCase() + "s";
|
|
407
|
-
|
|
408
|
-
const template = {
|
|
409
|
-
request: { type: "object", properties: {} },
|
|
410
|
-
response: { type: "object", properties: {} },
|
|
411
|
-
};
|
|
412
|
-
|
|
413
|
-
api[`/${resource}`] = {
|
|
414
|
-
get: {
|
|
415
|
-
...template,
|
|
416
|
-
summary: `Get ${className} list`,
|
|
417
|
-
description: `Get ${className} list`,
|
|
418
|
-
action: `function action(req) {\n return ${className};\n}\n`,
|
|
419
|
-
},
|
|
420
|
-
post: {
|
|
421
|
-
...template,
|
|
422
|
-
summary: `Create ${className}`,
|
|
423
|
-
description: `Create ${className}`,
|
|
424
|
-
action: `function action(req) {\n return new ${className}();\n}\n`,
|
|
425
|
-
},
|
|
426
|
-
};
|
|
427
|
-
api[`/${resource}/{${resource}}`] = {
|
|
428
|
-
get: {
|
|
429
|
-
...template,
|
|
430
|
-
summary: `Get ${className}`,
|
|
431
|
-
description: `Get ${className}`,
|
|
432
|
-
action: `function action(req) {\n const ${resource} = req.params.${resource};\n return ${className}[${resource}];\n}\n`,
|
|
433
|
-
},
|
|
434
|
-
put: {
|
|
435
|
-
...template,
|
|
436
|
-
summary: `Update ${className}`,
|
|
437
|
-
description: `Update ${className}`,
|
|
438
|
-
action: `function action(req) {\n const ${resource} = req.params.${resource};\n return ${className}[${resource}];\n}\n`,
|
|
439
|
-
},
|
|
440
|
-
del: {
|
|
441
|
-
...template,
|
|
442
|
-
summary: `Delete ${className}`,
|
|
443
|
-
description: `Delete ${className}`,
|
|
444
|
-
action: `function action(req) {\n const ${resource} = req.params.${resource};\n delete ${className}[${resource}];\n}\n`,
|
|
445
|
-
},
|
|
446
|
-
};
|
|
447
|
-
|
|
448
|
-
const sample = {
|
|
449
|
-
definition: `class ${className} {\n constructor() {\n }\n}\n`,
|
|
450
|
-
ext: "ts",
|
|
451
|
-
params: [],
|
|
452
|
-
path: `/${className}`,
|
|
453
|
-
type: "CLASS",
|
|
454
|
-
};
|
|
455
|
-
|
|
456
|
-
functions.push(sample);
|
|
457
|
-
|
|
458
|
-
publish("CONTEXT_CHANGED", {
|
|
459
|
-
files: [
|
|
460
|
-
{ key: `${sample.path}.${sample.ext}`, value: sample.definition },
|
|
461
|
-
],
|
|
462
|
-
});
|
|
463
|
-
|
|
464
|
-
break;
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
case "UPDATE_API_SCHEMAS": {
|
|
468
|
-
const { path, method, requestSchema, responseSchema } = action.payload;
|
|
469
|
-
const apiIndex = specification.api.findIndex(
|
|
470
|
-
(api) => api.path === path && api.method === method
|
|
471
|
-
);
|
|
472
|
-
|
|
473
|
-
if (apiIndex !== -1) {
|
|
474
|
-
specification.api[apiIndex].request = {
|
|
475
|
-
...specification.api[apiIndex].request,
|
|
476
|
-
schema: requestSchema,
|
|
477
|
-
};
|
|
478
|
-
specification.api[apiIndex].response = {
|
|
479
|
-
...specification.api[apiIndex].response,
|
|
480
|
-
schema: responseSchema,
|
|
481
|
-
};
|
|
482
|
-
}
|
|
483
|
-
break;
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
case "UPDATE_API_SUMMARY": {
|
|
487
|
-
const { path, method, newSummary } = action.payload;
|
|
488
|
-
const apiEndpoint = specification.api.find(
|
|
489
|
-
(api) => api.path === path && api.method === method
|
|
490
|
-
);
|
|
491
|
-
if (apiEndpoint) {
|
|
492
|
-
apiEndpoint.summary = newSummary;
|
|
493
|
-
}
|
|
494
|
-
break;
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
case "UPDATE_API_DESCRIPTION": {
|
|
498
|
-
const { path, method, newDescription } = action.payload;
|
|
499
|
-
const apiEndpoint = specification.api.find(
|
|
500
|
-
(api) => api.path === path && api.method === method
|
|
501
|
-
);
|
|
502
|
-
if (apiEndpoint) {
|
|
503
|
-
apiEndpoint.description = newDescription;
|
|
504
|
-
}
|
|
505
|
-
break;
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
case "DELETE_API": {
|
|
509
|
-
const selectedIndex = specification.api.findIndex(
|
|
510
|
-
(api) =>
|
|
511
|
-
api.path === pages.api.selected.path &&
|
|
512
|
-
api.method === pages.api.selected.method
|
|
513
|
-
);
|
|
514
|
-
|
|
515
|
-
if (selectedIndex > -1) {
|
|
516
|
-
specification.api.splice(selectedIndex, 1);
|
|
517
|
-
if (specification.api.length > 0) {
|
|
518
|
-
pages.api.selected.path = specification.api[0].path;
|
|
519
|
-
pages.api.selected.method = specification.api[0].method;
|
|
520
|
-
} else {
|
|
521
|
-
pages.api.selected.path = "/";
|
|
522
|
-
pages.api.selected.method = "get";
|
|
523
|
-
}
|
|
524
|
-
}
|
|
525
|
-
pages.api.dialog.open = false;
|
|
526
|
-
|
|
527
|
-
break;
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
case "UPDATE_API_TYPES": {
|
|
531
|
-
const { updatedTypes } = action.payload;
|
|
532
|
-
const typeIndex = specification.types.findIndex(
|
|
533
|
-
(type) => type.name === updatedTypes.name
|
|
534
|
-
);
|
|
535
|
-
const updatedType = {
|
|
536
|
-
...specification.types[typeIndex],
|
|
537
|
-
schema: {
|
|
538
|
-
...updatedTypes,
|
|
539
|
-
},
|
|
540
|
-
};
|
|
541
|
-
if (typeIndex !== -1) {
|
|
542
|
-
specification.types[typeIndex] = updatedType;
|
|
543
|
-
} else {
|
|
544
|
-
specification.types.push(updatedTypes);
|
|
545
|
-
}
|
|
546
|
-
break;
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
case "ADD_TYPE": {
|
|
550
|
-
const { typeName } = action.payload;
|
|
551
|
-
const newType = {
|
|
552
|
-
name: typeName,
|
|
553
|
-
schema: {
|
|
554
|
-
name: typeName,
|
|
555
|
-
type: "object",
|
|
556
|
-
properties: [
|
|
557
|
-
{ type: "string", name: "id" },
|
|
558
|
-
{ type: "string", name: "name" },
|
|
559
|
-
],
|
|
560
|
-
},
|
|
561
|
-
};
|
|
562
|
-
specification.types.push(newType);
|
|
563
|
-
break;
|
|
564
|
-
}
|
|
565
|
-
|
|
566
|
-
case "DELETE_TYPE": {
|
|
567
|
-
const { typeName } = action.payload;
|
|
568
|
-
const typeIndex = specification.types.findIndex(
|
|
569
|
-
(type) => type.name === typeName
|
|
570
|
-
);
|
|
571
|
-
|
|
572
|
-
if (typeIndex !== -1) {
|
|
573
|
-
specification.types.splice(typeIndex, 1);
|
|
574
|
-
}
|
|
575
|
-
break;
|
|
576
|
-
}
|
|
577
|
-
|
|
578
|
-
case "UPDATE_TYPE_NAME": {
|
|
579
|
-
const { oldTypeName, newTypeName } = action.payload;
|
|
580
|
-
const typeIndex = specification.types.findIndex(
|
|
581
|
-
(type) => type.name === oldTypeName
|
|
582
|
-
);
|
|
583
|
-
|
|
584
|
-
if (typeIndex !== -1) {
|
|
585
|
-
specification.types[typeIndex].name = newTypeName;
|
|
586
|
-
specification.types[typeIndex].schema.name = newTypeName;
|
|
587
|
-
}
|
|
588
|
-
break;
|
|
589
|
-
}
|
|
590
|
-
|
|
591
|
-
case "SAVE_API_PARAMS": {
|
|
592
|
-
console.log("SAVE_API_PARAMS", action.payload);
|
|
593
|
-
const { path, method, params } = action.payload;
|
|
594
|
-
const apiIndex = specification.api.findIndex(
|
|
595
|
-
(api) => api.path === path && api.method === method
|
|
596
|
-
);
|
|
597
|
-
|
|
598
|
-
if (apiIndex !== -1) {
|
|
599
|
-
specification.api[apiIndex].params = params;
|
|
600
|
-
}
|
|
601
|
-
break;
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
case "UPDATE_API_PATH_METHOD": {
|
|
605
|
-
const { path, method } = action.payload;
|
|
606
|
-
|
|
607
|
-
const apiIndex = specification.api.findIndex(
|
|
608
|
-
(api) =>
|
|
609
|
-
api.path === pages.api.selected.path &&
|
|
610
|
-
api.method === pages.api.selected.method
|
|
611
|
-
);
|
|
612
|
-
|
|
613
|
-
if (apiIndex !== -1) {
|
|
614
|
-
specification.api[apiIndex].path = path;
|
|
615
|
-
specification.api[apiIndex].method = method;
|
|
616
|
-
}
|
|
617
|
-
|
|
618
|
-
pages.api.selected = {
|
|
619
|
-
...pages.api.selected,
|
|
620
|
-
path: path,
|
|
621
|
-
method: method,
|
|
622
|
-
};
|
|
623
|
-
|
|
624
|
-
break;
|
|
625
|
-
}
|
|
626
|
-
|
|
627
|
-
default:
|
|
628
|
-
}
|
|
629
|
-
|
|
630
|
-
console.debug("reducer", action.type, context);
|
|
631
|
-
return context;
|
|
632
|
-
};
|
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
import { Box } from "@mui/material";
|
|
2
|
-
import MiniTopBar from "../components/MiniTopBar";
|
|
3
|
-
import Sidebar from "../components/Sidebar";
|
|
4
|
-
import TopNavBar from "../components/TopNavBar";
|
|
5
|
-
import config from "../config/config";
|
|
6
|
-
import { useContext } from "../ContextProvider/ContextProvider";
|
|
7
|
-
import user from "../http/user";
|
|
8
|
-
|
|
9
|
-
import { Outlet, useLocation } from "react-router-dom";
|
|
10
|
-
import React, { useEffect, useState } from "react";
|
|
11
|
-
|
|
12
|
-
function AppLayout() {
|
|
13
|
-
const [anchorElUser, setAnchorElUser] = useState(null);
|
|
14
|
-
const [isCollapsed, setIsCollapsed] = useState(false);
|
|
15
|
-
const [isSubmenuOpen, setSubmenuOpen] = useState(false);
|
|
16
|
-
const [selectedItem, setSelectedItem] = useState();
|
|
17
|
-
const [state, dispatch] = useContext();
|
|
18
|
-
const [miniTopMenu, setMiniTopMenu] = useState(false);
|
|
19
|
-
const [userData, setUserData] = useState(null);
|
|
20
|
-
const location = useLocation();
|
|
21
|
-
const globalConfig = useConfig();
|
|
22
|
-
|
|
23
|
-
const toggleCollapse = () => {
|
|
24
|
-
setIsCollapsed(!isCollapsed);
|
|
25
|
-
if (isSubmenuOpen) {
|
|
26
|
-
setSubmenuOpen(false);
|
|
27
|
-
}
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
const handleOpenUserMenu = (event) => {
|
|
31
|
-
setAnchorElUser(event.currentTarget);
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
const handleCloseUserMenu = () => {
|
|
35
|
-
setAnchorElUser(null);
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
const handleItemSelect = (item) => {
|
|
39
|
-
dispatch({ type: "ITEM_SELECT", payload: item.id });
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
useEffect(() => {
|
|
43
|
-
const foundItem = globalConfig.itemsData.find(
|
|
44
|
-
(item) => item.id === state.itemId
|
|
45
|
-
);
|
|
46
|
-
|
|
47
|
-
if (foundItem) {
|
|
48
|
-
setSelectedItem(foundItem);
|
|
49
|
-
}
|
|
50
|
-
selectedItem && setSubmenuOpen(false);
|
|
51
|
-
|
|
52
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
53
|
-
}, []);
|
|
54
|
-
|
|
55
|
-
useEffect(() => {
|
|
56
|
-
user.get("https://api.github.com/user").then((response) => {
|
|
57
|
-
setUserData(response.data);
|
|
58
|
-
});
|
|
59
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
60
|
-
}, [state.login]);
|
|
61
|
-
|
|
62
|
-
useEffect(() => {
|
|
63
|
-
const targetPage = globalConfig.topMenu.find(
|
|
64
|
-
(target) => target.url === location.pathname
|
|
65
|
-
);
|
|
66
|
-
|
|
67
|
-
targetPage?.hideTopBar
|
|
68
|
-
? (setMiniTopMenu(true), setIsCollapsed(true))
|
|
69
|
-
: (setMiniTopMenu(false), setIsCollapsed(false));
|
|
70
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
71
|
-
}, [location]);
|
|
72
|
-
|
|
73
|
-
return (
|
|
74
|
-
<Box>
|
|
75
|
-
{state.login &&
|
|
76
|
-
(miniTopMenu ? (
|
|
77
|
-
<MiniTopBar />
|
|
78
|
-
) : (
|
|
79
|
-
<TopNavBar
|
|
80
|
-
sx={{ flexShrink: 0 }}
|
|
81
|
-
anchorElUser={anchorElUser}
|
|
82
|
-
handleOpenUserMenu={handleOpenUserMenu}
|
|
83
|
-
handleCloseUserMenu={handleCloseUserMenu}
|
|
84
|
-
routes={globalConfig.topMenu}
|
|
85
|
-
itemsData={globalConfig.itemsData}
|
|
86
|
-
onItemSelect={handleItemSelect}
|
|
87
|
-
sideBarToggle={toggleCollapse}
|
|
88
|
-
selectedItem={selectedItem}
|
|
89
|
-
setSelectedItem={setSelectedItem}
|
|
90
|
-
itemUrl="/"
|
|
91
|
-
itemName="ITEEEEEM"
|
|
92
|
-
userData={userData}
|
|
93
|
-
/>
|
|
94
|
-
))}
|
|
95
|
-
|
|
96
|
-
<Box sx={{ display: "flex", flexGrow: 1 }}>
|
|
97
|
-
{state.itemId ? (
|
|
98
|
-
<Sidebar
|
|
99
|
-
sx={{ flexShrink: 0 }}
|
|
100
|
-
routes={globalConfig.sideMenu}
|
|
101
|
-
isCollapsed={isCollapsed}
|
|
102
|
-
currentPage={location.pathname}
|
|
103
|
-
/>
|
|
104
|
-
) : null}
|
|
105
|
-
<Box sx={{ flexGrow: 1, overflow: "auto" }}>
|
|
106
|
-
<Outlet />
|
|
107
|
-
</Box>
|
|
108
|
-
</Box>
|
|
109
|
-
</Box>
|
|
110
|
-
);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
export default AppLayout;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { default } from "./NucDialog";
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
const ActionTemplate = {
|
|
2
|
-
GET: `function action(req) {
|
|
3
|
-
// Implement your GET logic here
|
|
4
|
-
return {};
|
|
5
|
-
}`,
|
|
6
|
-
POST: `function action(req) {
|
|
7
|
-
// Implement your POST logic here
|
|
8
|
-
return {};
|
|
9
|
-
}`,
|
|
10
|
-
PUT: `function action(req) {
|
|
11
|
-
// Implement your PUT logic here
|
|
12
|
-
return {};
|
|
13
|
-
}`,
|
|
14
|
-
DELETE: `function action(req) {
|
|
15
|
-
// Implement your DELETE logic here
|
|
16
|
-
return {};
|
|
17
|
-
}`,
|
|
18
|
-
PATCH: `function action(req) {
|
|
19
|
-
// Implement your PATCH logic here
|
|
20
|
-
return {};
|
|
21
|
-
}`,
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
export default ActionTemplate;
|