Skip to content

Commit add7aa0

Browse files
authored
Merge pull request #1445 from rowyio/develop
Develop
2 parents a0ddfae + fd8df49 commit add7aa0

File tree

29 files changed

+1028
-233
lines changed

29 files changed

+1028
-233
lines changed

src/App.tsx

+7
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,12 @@ const SetupPage = lazy(() => import("@src/pages/SetupPage" /* webpackChunkName:
4141
const Navigation = lazy(() => import("@src/layouts/Navigation" /* webpackChunkName: "Navigation" */));
4242
// prettier-ignore
4343
const TableSettingsDialog = lazy(() => import("@src/components/TableSettingsDialog" /* webpackChunkName: "TableSettingsDialog" */));
44+
const ProjectSettingsDialog = lazy(
45+
() =>
46+
import(
47+
"@src/components/ProjectSettingsDialog" /* webpackChunkName: "ProjectSettingsDialog" */
48+
)
49+
);
4450

4551
// prettier-ignore
4652
const TablesPage = lazy(() => import("@src/pages/TablesPage" /* webpackChunkName: "TablesPage" */));
@@ -99,6 +105,7 @@ export default function App() {
99105
<RequireAuth>
100106
<Navigation>
101107
<TableSettingsDialog />
108+
<ProjectSettingsDialog />
102109
</Navigation>
103110
</RequireAuth>
104111
}

src/atoms/projectScope/ui.ts

+20
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,26 @@ export const tableSettingsDialogAtom = atom(
131131
}
132132
);
133133

134+
export type ProjectSettingsDialogTab =
135+
| "general"
136+
| "rowy-run"
137+
| "services"
138+
| "secrets";
139+
export type ProjectSettingsDialogState = {
140+
open: boolean;
141+
tab: ProjectSettingsDialogTab;
142+
};
143+
export const projectSettingsDialogAtom = atom(
144+
{ open: false, tab: "secrets" } as ProjectSettingsDialogState,
145+
(_, set, update?: Partial<ProjectSettingsDialogState>) => {
146+
set(projectSettingsDialogAtom, {
147+
open: true,
148+
tab: "secrets",
149+
...update,
150+
});
151+
}
152+
);
153+
134154
/**
135155
* Store the current ID of the table being edited in tableSettingsDialog
136156
* to derive tableSettingsDialogSchemaAtom

src/atoms/projectScope/user.ts

+6
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@ export const themeOverriddenAtom = atomWithStorage(
3030
false
3131
);
3232

33+
/** User's default table settings (affecting saving and popup behavior) */
34+
export const defaultTableSettingsAtom = atom((get) => {
35+
const userSettings = get(userSettingsAtom);
36+
return userSettings.defaultTableSettings;
37+
});
38+
3339
/** Customized base theme based on project and user settings */
3440
export const customizedThemesAtom = atom((get) => {
3541
const publicSettings = get(publicSettingsAtom);

src/components/CodeEditor/extensions.d.ts

+11
Original file line numberDiff line numberDiff line change
@@ -128,4 +128,15 @@ type PushNotificationRequest = {
128128
type PushNotificationBody = (
129129
context: ExtensionContext
130130
) => Message | Message[] | Promise<Message | Message[]>;
131+
131132
type TaskBody = (context: ExtensionContext) => Promise<any>;
133+
134+
type BuildshipAuthenticatedTriggerBody = (
135+
context: ExtensionContext
136+
) => Promise<{
137+
buildshipConfig: {
138+
projectId: string;
139+
workflowId: string;
140+
};
141+
body: string;
142+
}>;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,282 @@
1+
import React from "react";
2+
import { useAtom } from "jotai";
3+
import {
4+
projectScope,
5+
projectSettingsDialogAtom,
6+
ProjectSettingsDialogTab,
7+
rowyRunAtom,
8+
secretNamesAtom,
9+
updateSecretNamesAtom,
10+
} from "@src/atoms/projectScope";
11+
import Modal from "@src/components/Modal";
12+
import { Box, Button, Paper, Tab, Tooltip, Typography } from "@mui/material";
13+
import { TabContext, TabPanel, TabList } from "@mui/lab";
14+
import DeleteOutlineIcon from "@mui/icons-material/DeleteOutline";
15+
import EditIcon from "@mui/icons-material/Edit";
16+
import SecretDetailsModal from "./SecretDetailsModal";
17+
import { runRoutes } from "@src/constants/runRoutes";
18+
19+
export default function ProjectSettingsDialog() {
20+
const [{ open, tab }, setProjectSettingsDialog] = useAtom(
21+
projectSettingsDialogAtom,
22+
projectScope
23+
);
24+
const [secretNames] = useAtom(secretNamesAtom, projectScope);
25+
const [secretDetailsModal, setSecretDetailsModal] = React.useState<{
26+
open: boolean;
27+
loading?: boolean;
28+
mode?: "add" | "edit" | "delete";
29+
secretName?: string;
30+
error?: string;
31+
}>({
32+
open: false,
33+
});
34+
const [rowyRun] = useAtom(rowyRunAtom, projectScope);
35+
const [updateSecretNames] = useAtom(updateSecretNamesAtom, projectScope);
36+
37+
if (!open) return null;
38+
39+
const handleClose = () => {
40+
setProjectSettingsDialog({ open: false });
41+
};
42+
43+
const handleTabChange = (
44+
event: React.SyntheticEvent,
45+
newTab: ProjectSettingsDialogTab
46+
) => {
47+
setProjectSettingsDialog({ tab: newTab });
48+
};
49+
50+
console.log(secretDetailsModal);
51+
52+
return (
53+
<>
54+
<Modal
55+
onClose={handleClose}
56+
open={open}
57+
maxWidth="sm"
58+
fullWidth
59+
title={"Project settings"}
60+
sx={{
61+
".MuiDialogContent-root": {
62+
display: "flex",
63+
flexDirection: "column",
64+
height: "100%",
65+
},
66+
}}
67+
children={
68+
<>
69+
<TabContext value={tab}>
70+
<Box
71+
sx={{
72+
borderBottom: 1,
73+
borderColor: "divider",
74+
}}
75+
>
76+
<TabList value={tab} onChange={handleTabChange}>
77+
<Tab label="Secret keys" value={"secrets"} />
78+
</TabList>
79+
</Box>
80+
<TabPanel
81+
value={tab}
82+
sx={{
83+
overflowY: "scroll",
84+
}}
85+
>
86+
<Paper elevation={1} variant={"outlined"}>
87+
<Box
88+
sx={{
89+
display: "flex",
90+
justifyContent: "space-between",
91+
alignItems: "center",
92+
padding: 3,
93+
}}
94+
>
95+
<Typography variant="h6" sx={{ fontWeight: "bold" }}>
96+
Secrets
97+
</Typography>
98+
<Button
99+
variant="contained"
100+
color="primary"
101+
onClick={() => {
102+
setSecretDetailsModal({
103+
open: true,
104+
mode: "add",
105+
});
106+
}}
107+
>
108+
Add secret key
109+
</Button>
110+
</Box>
111+
{secretNames.secretNames?.map((secretName) => (
112+
<Box
113+
key={secretName}
114+
sx={{
115+
display: "flex",
116+
justifyContent: "space-between",
117+
alignItems: "center",
118+
padding: 3,
119+
borderTop: 1,
120+
borderColor: "divider",
121+
}}
122+
>
123+
<Typography variant="body2" color="text.secondary">
124+
{secretName}
125+
</Typography>
126+
<Box>
127+
<Tooltip title={"Edit"}>
128+
<Button
129+
variant="outlined"
130+
color="primary"
131+
style={{
132+
minWidth: "40px",
133+
paddingLeft: 0,
134+
paddingRight: 0,
135+
marginRight: "8px",
136+
}}
137+
onClick={() => {
138+
setSecretDetailsModal({
139+
open: true,
140+
mode: "edit",
141+
secretName,
142+
});
143+
}}
144+
>
145+
<EditIcon color={"secondary"} />
146+
</Button>
147+
</Tooltip>
148+
<Tooltip title={"Delete"}>
149+
<Button
150+
variant="outlined"
151+
color="primary"
152+
style={{
153+
minWidth: "40px",
154+
paddingLeft: 0,
155+
paddingRight: 0,
156+
}}
157+
onClick={() => {
158+
console.log("setting", {
159+
open: true,
160+
mode: "delete",
161+
secretName,
162+
});
163+
setSecretDetailsModal({
164+
open: true,
165+
mode: "delete",
166+
secretName,
167+
});
168+
}}
169+
>
170+
<DeleteOutlineIcon color={"secondary"} />
171+
</Button>
172+
</Tooltip>
173+
</Box>
174+
</Box>
175+
))}
176+
</Paper>
177+
</TabPanel>
178+
</TabContext>
179+
</>
180+
}
181+
/>
182+
<SecretDetailsModal
183+
open={secretDetailsModal.open}
184+
mode={secretDetailsModal.mode}
185+
error={secretDetailsModal.error}
186+
loading={secretDetailsModal.loading}
187+
secretName={secretDetailsModal.secretName}
188+
handleClose={() => {
189+
setSecretDetailsModal({ ...secretDetailsModal, open: false });
190+
}}
191+
handleAdd={async (newSecretName, secretValue) => {
192+
setSecretDetailsModal({
193+
...secretDetailsModal,
194+
loading: true,
195+
});
196+
try {
197+
await rowyRun({
198+
route: runRoutes.addSecret,
199+
body: {
200+
name: newSecretName,
201+
value: secretValue,
202+
},
203+
});
204+
setSecretDetailsModal({
205+
...secretDetailsModal,
206+
open: false,
207+
loading: false,
208+
});
209+
// update secret name causes an unknown modal-related bug, to be fixed
210+
// updateSecretNames?.();
211+
} catch (error: any) {
212+
console.error(error);
213+
setSecretDetailsModal({
214+
...secretDetailsModal,
215+
error: error.message,
216+
});
217+
}
218+
}}
219+
handleEdit={async (secretName, secretValue) => {
220+
setSecretDetailsModal({
221+
...secretDetailsModal,
222+
loading: true,
223+
});
224+
try {
225+
await rowyRun({
226+
route: runRoutes.editSecret,
227+
body: {
228+
name: secretName,
229+
value: secretValue,
230+
},
231+
});
232+
setSecretDetailsModal({
233+
...secretDetailsModal,
234+
open: false,
235+
loading: false,
236+
});
237+
// update secret name causes an unknown modal-related bug, to be fixed
238+
// updateSecretNames?.();
239+
} catch (error: any) {
240+
console.error(error);
241+
setSecretDetailsModal({
242+
...secretDetailsModal,
243+
error: error.message,
244+
});
245+
}
246+
}}
247+
handleDelete={async (secretName) => {
248+
setSecretDetailsModal({
249+
...secretDetailsModal,
250+
loading: true,
251+
});
252+
try {
253+
await rowyRun({
254+
route: runRoutes.deleteSecret,
255+
body: {
256+
name: secretName,
257+
},
258+
});
259+
console.log("Setting", {
260+
...secretDetailsModal,
261+
open: false,
262+
loading: false,
263+
});
264+
setSecretDetailsModal({
265+
...secretDetailsModal,
266+
open: false,
267+
loading: false,
268+
});
269+
// update secret name causes an unknown modal-related bug, to be fixed
270+
// updateSecretNames?.();
271+
} catch (error: any) {
272+
console.error(error);
273+
setSecretDetailsModal({
274+
...secretDetailsModal,
275+
error: error.message,
276+
});
277+
}
278+
}}
279+
/>
280+
</>
281+
);
282+
}

0 commit comments

Comments
 (0)