Skip to content

Commit 29664d5

Browse files
committed
feat!: support for data connectors on user and group namespaces (#3315)
1 parent a21b3d9 commit 29664d5

File tree

47 files changed

+5739
-118
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+5739
-118
lines changed

client/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222
"storybook-wait-server": "wait-on http://127.0.0.1:6006",
2323
"storybook-test": "test-storybook",
2424
"storybook-compile-and-test": "concurrently -k -s first -n 'BUILD,TEST' -c 'magenta,blue' 'npm run storybook-build && npm run storybook-start-server' 'npm run storybook-wait-server && npm run storybook-test'",
25-
"generate-api": "npm run generate-api:dataServicesUser && npm run generate-api:namespaceV2 && npm run generate-api:projectV2 && npm run generate-api:platform && npm run generate-api:searchV2 && npm run generate-api:storages",
25+
"generate-api": "npm run generate-api:data-connectors && npm run generate-api:dataServicesUser && npm run generate-api:namespaceV2 && npm run generate-api:projectV2 && npm run generate-api:platform && npm run generate-api:searchV2 && npm run generate-api:storages",
26+
"generate-api:data-connectors": "rtk-query-codegen-openapi src/features/projectsV2/api/data-connectors.api-config.ts",
2627
"generate-api:dataServicesUser": "rtk-query-codegen-openapi src/features/user/dataServicesUser.api/dataServicesUser.api-config.ts",
2728
"generate-api:namespaceV2": "rtk-query-codegen-openapi src/features/projectsV2/api/namespace.api-config.ts",
2829
"generate-api:projectV2": "rtk-query-codegen-openapi src/features/projectsV2/api/projectV2.api-config.ts",

client/src/features/ProjectPageV2/ProjectPageContent/DataSources/DataSourceCredentialsModal.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import {
2828
} from "../../../projectsV2/api/projectV2.enhanced-api";
2929
import type { CloudStorageGetRead } from "../../../projectsV2/api/storagesV2.api";
3030
import type { SessionStartCloudStorageConfiguration } from "../../../sessionsV2/startSessionOptionsV2.types";
31-
import CloudStorageSecretsModal from "../../../sessionsV2/DataConnectorSecretsModal";
31+
import DataStorageSecretsModal from "../../../sessionsV2/DataStorageSecretsModal";
3232

3333
import useDataSourceConfiguration from "./useDataSourceConfiguration.hook";
3434
import { Loader } from "../../../../components/Loader";
@@ -188,7 +188,7 @@ export default function DataSourceCredentialsModal({
188188
}
189189

190190
return (
191-
<CloudStorageSecretsModal
191+
<DataStorageSecretsModal
192192
cloudStorageConfigs={cloudStorageConfigs}
193193
context="storage"
194194
isOpen={isOpen}

client/src/features/ProjectPageV2/ProjectPageContent/DataSources/DataSourceDisplay.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import {
3131
} from "reactstrap";
3232

3333
import { Loader } from "../../../../components/Loader";
34-
import DataConnectorModal from "../../../dataConnectorsV2/components/DataConnectorModal";
34+
import DataSourceModal from "./DataSourceModal";
3535
import {
3636
type CloudStorageGetRead,
3737
useDeleteStoragesV2ByStorageIdMutation,
@@ -174,7 +174,7 @@ export function DataSourceActions({
174174
isOpen={isDeleteOpen}
175175
toggleModal={toggleDelete}
176176
/>
177-
<DataConnectorModal
177+
<DataSourceModal
178178
currentStorage={storage}
179179
isOpen={isEditOpen}
180180
toggle={toggleEdit}

client/src/features/dataConnectorsV2/components/DataConnectorModal.tsx renamed to client/src/features/ProjectPageV2/ProjectPageContent/DataSources/DataSourceModal.tsx

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,53 +23,53 @@ import { useCallback, useEffect, useMemo, useState } from "react";
2323
import { ArrowCounterclockwise } from "react-bootstrap-icons";
2424
import { Button, Modal, ModalBody, ModalFooter, ModalHeader } from "reactstrap";
2525

26-
import { RtkOrNotebooksError } from "../../../components/errors/RtkErrorAlert";
27-
import { usePostStoragesV2ByStorageIdSecretsMutation } from "../../projectsV2/api/projectV2.enhanced-api";
26+
import { RtkOrNotebooksError } from "../../../../components/errors/RtkErrorAlert";
27+
import { usePostStoragesV2ByStorageIdSecretsMutation } from "../../../projectsV2/api/projectV2.enhanced-api";
2828
import {
2929
CloudStorageGetV2Read,
3030
CloudStoragePatch,
3131
PostStoragesV2ApiArg,
3232
RCloneConfig,
3333
usePatchStoragesV2ByStorageIdMutation,
3434
usePostStoragesV2Mutation,
35-
} from "../../projectsV2/api/storagesV2.api";
35+
} from "../../../projectsV2/api/storagesV2.api";
3636

37-
import AddStorageBreadcrumbNavbar from "../../project/components/cloudStorage/AddStorageBreadcrumbNavbar";
37+
import AddStorageBreadcrumbNavbar from "../../../project/components/cloudStorage/AddStorageBreadcrumbNavbar";
3838
import {
3939
useGetCloudStorageSchemaQuery,
4040
useTestCloudStorageConnectionMutation,
41-
} from "../../project/components/cloudStorage/projectCloudStorage.api";
41+
} from "../../../project/components/cloudStorage/projectCloudStorage.api";
4242
import {
4343
CLOUD_STORAGE_SENSITIVE_FIELD_TOKEN,
4444
CLOUD_STORAGE_TOTAL_STEPS,
4545
EMPTY_CLOUD_STORAGE_DETAILS,
4646
EMPTY_CLOUD_STORAGE_STATE,
47-
} from "../../project/components/cloudStorage/projectCloudStorage.constants";
47+
} from "../../../project/components/cloudStorage/projectCloudStorage.constants";
4848
import {
4949
AddCloudStorageForProjectParams,
5050
AddCloudStorageState,
5151
CloudStorageDetails,
5252
CloudStorageDetailsOptions,
5353
CredentialSaveStatus,
5454
TestCloudStorageConnectionParams,
55-
} from "../../project/components/cloudStorage/projectCloudStorage.types";
55+
} from "../../../project/components/cloudStorage/projectCloudStorage.types";
5656

5757
import {
5858
AddCloudStorageContinueButton,
5959
AddCloudStorageBackButton,
6060
AddCloudStorageConnectionTestResult,
6161
AddCloudStorageHeaderContent,
62-
} from "../../project/components/cloudStorage/cloudStorageModalComponents";
62+
} from "../../../project/components/cloudStorage/cloudStorageModalComponents";
6363
import {
6464
findSensitive,
6565
getCurrentStorageDetails,
6666
getSchemaProviders,
6767
hasProviderShortlist,
68-
} from "../../project/utils/projectCloudStorage.utils";
68+
} from "../../../project/utils/projectCloudStorage.utils";
6969

70-
import styles from "../../project/components/cloudStorage/CloudStorage.module.scss";
70+
import styles from "../../../project/components/cloudStorage/CloudStorage.module.scss";
7171

72-
import DataConnectorModalBody from "./DataConnectorModalBody";
72+
import DataSourceModalBody from "./DataSourceModalBody";
7373

7474
interface DataConnectorModalProps {
7575
currentStorage?: CloudStorageGetV2Read | null;
@@ -484,7 +484,7 @@ export default function DataConnectorModal({
484484
</ModalHeader>
485485

486486
<ModalBody data-cy="cloud-storage-edit-body">
487-
<DataConnectorModalBody
487+
<DataSourceModalBody
488488
addResultStorageName={addResultStorageName}
489489
credentialSaveStatus={credentialSaveStatus}
490490
isV2={true}

client/src/features/dataConnectorsV2/components/DataConnectorModalBody.tsx renamed to client/src/features/ProjectPageV2/ProjectPageContent/DataSources/DataSourceModalBody.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,27 +18,27 @@
1818

1919
import cx from "classnames";
2020

21-
import { Loader } from "../../../components/Loader";
22-
import { RtkOrNotebooksError } from "../../../components/errors/RtkErrorAlert";
21+
import { Loader } from "../../../../components/Loader";
22+
import { RtkOrNotebooksError } from "../../../../components/errors/RtkErrorAlert";
2323

24-
import { CLOUD_STORAGE_TOTAL_STEPS } from "../../project/components/cloudStorage/projectCloudStorage.constants";
24+
import { CLOUD_STORAGE_TOTAL_STEPS } from "../../../project/components/cloudStorage/projectCloudStorage.constants";
2525
import type {
2626
AddCloudStorageState,
2727
CloudStorageDetails,
2828
CloudStorageSchema,
29-
} from "../../project/components/cloudStorage/projectCloudStorage.types";
29+
} from "../../../project/components/cloudStorage/projectCloudStorage.types";
3030
import {
3131
AddCloudStorageSuccessAlert,
3232
type AddCloudStorageBodyContentProps,
33-
} from "../../project/components/cloudStorage/cloudStorageModalComponents";
33+
} from "../../../project/components/cloudStorage/cloudStorageModalComponents";
3434
import {
3535
AddStorageAdvanced,
3636
AddStorageAdvancedToggle,
3737
AddStorageMount,
3838
AddStorageOptions,
3939
AddStorageType,
40-
} from "../../project/components/cloudStorage/AddOrEditCloudStorage";
41-
import type { CloudStorageSecretGet } from "../../projectsV2/api/storagesV2.api";
40+
} from "../../../project/components/cloudStorage/AddOrEditCloudStorage";
41+
import type { CloudStorageSecretGet } from "../../../projectsV2/api/storagesV2.api";
4242

4343
interface AddOrEditCloudStorageProps {
4444
schema: CloudStorageSchema[];

client/src/features/ProjectPageV2/ProjectPageContent/DataSources/DataSourcesBox.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@ import cx from "classnames";
1919
import { useCallback, useState } from "react";
2020
import { Database, PlusLg } from "react-bootstrap-icons";
2121
import { Loader } from "../../../../components/Loader";
22-
import DataConnectorModal from "../../../dataConnectorsV2/components/DataConnectorModal";
2322
import { Project } from "../../../projectsV2/api/projectV2.api";
2423
import { useGetStoragesV2Query } from "../../../projectsV2/api/storagesV2.api";
2524
import AccessGuard from "../../utils/AccessGuard";
2625
import useProjectAccess from "../../utils/useProjectAccess.hook";
2726
import { DataSourceDisplay } from "./DataSourceDisplay";
27+
import DataSourceModal from "./DataSourceModal";
2828
import {
2929
Badge,
3030
Button,
@@ -117,7 +117,7 @@ export function DataSourcesDisplay({ project }: { project: Project }) {
117117
</ListGroup>
118118
)}
119119
</CardBody>
120-
<DataConnectorModal
120+
<DataSourceModal
121121
currentStorage={null}
122122
isOpen={isOpen}
123123
toggle={toggle}
Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
/*!
2+
* Copyright 2024 - Swiss Data Science Center (SDSC)
3+
* A partnership between École Polytechnique Fédérale de Lausanne (EPFL) and
4+
* Eidgenössische Technische Hochschule Zürich (ETHZ).
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
import cx from "classnames";
19+
import { useCallback, useEffect, useState } from "react";
20+
import { Lock, Pencil, Trash, XLg } from "react-bootstrap-icons";
21+
import {
22+
Button,
23+
Col,
24+
DropdownItem,
25+
Input,
26+
Modal,
27+
ModalBody,
28+
ModalFooter,
29+
ModalHeader,
30+
Row,
31+
} from "reactstrap";
32+
33+
import { Loader } from "../../../components/Loader";
34+
import DataConnectorModal from "./DataConnectorModal";
35+
import type { DataConnectorRead } from "../../projectsV2/api/data-connectors.api";
36+
import { useDeleteDataConnectorsByDataConnectorIdMutation } from "../../projectsV2/api/data-connectors.enhanced-api";
37+
import DataConnectorCredentialsModal from "./DataConnectorCredentialsModal";
38+
import { ButtonWithMenuV2 } from "../../../components/buttons/Button";
39+
40+
interface DataConnectorDeleteModalProps {
41+
dataConnector: DataConnectorRead;
42+
isOpen: boolean;
43+
onDelete: () => void;
44+
toggleModal: () => void;
45+
}
46+
function DataConnectorDeleteModal({
47+
dataConnector,
48+
onDelete,
49+
toggleModal,
50+
isOpen,
51+
}: DataConnectorDeleteModalProps) {
52+
const [deleteDataConnector, { isLoading, isSuccess }] =
53+
useDeleteDataConnectorsByDataConnectorIdMutation();
54+
55+
const [typedName, setTypedName] = useState("");
56+
const onChange = useCallback(
57+
(e: React.ChangeEvent<HTMLInputElement>) => {
58+
setTypedName(e.target.value.trim());
59+
},
60+
[setTypedName]
61+
);
62+
63+
useEffect(() => {
64+
if (isSuccess) {
65+
onDelete();
66+
}
67+
}, [isSuccess, onDelete]);
68+
const onDeleteDataCollector = () => {
69+
deleteDataConnector({
70+
dataConnectorId: dataConnector.id,
71+
});
72+
};
73+
74+
return (
75+
<Modal size="lg" isOpen={isOpen} toggle={toggleModal} centered>
76+
<ModalHeader className="text-danger" toggle={toggleModal}>
77+
Delete data connector
78+
</ModalHeader>
79+
<ModalBody>
80+
<Row>
81+
<Col>
82+
<p>
83+
Are you sure you want to delete this data connector? It will
84+
affect all projects that use it. Please type{" "}
85+
<strong>{dataConnector.slug}</strong>, the slug of the data
86+
connector, to confirm.
87+
</p>
88+
<Input
89+
data-cy="delete-confirmation-input"
90+
value={typedName}
91+
onChange={onChange}
92+
/>
93+
</Col>
94+
</Row>
95+
</ModalBody>
96+
<ModalFooter>
97+
<div className="d-flex justify-content-end">
98+
<Button color="outline-danger" onClick={toggleModal}>
99+
<XLg className={cx("bi", "me-1")} />
100+
Cancel
101+
</Button>
102+
<Button
103+
color="danger"
104+
className={cx("float-right", "ms-2")}
105+
disabled={typedName !== dataConnector.slug.trim()}
106+
data-cy="delete-data-connector-modal-button"
107+
type="submit"
108+
onClick={onDeleteDataCollector}
109+
>
110+
{isLoading ? (
111+
<>
112+
<Loader className="me-1" inline size={16} />
113+
Deleting data connector
114+
</>
115+
) : (
116+
<>
117+
<Trash className={cx("bi", "me-1")} />
118+
Remove data connector
119+
</>
120+
)}
121+
</Button>
122+
</div>
123+
</ModalFooter>
124+
</Modal>
125+
);
126+
}
127+
export default function DataConnectorActions({
128+
dataConnector,
129+
toggleView,
130+
}: {
131+
dataConnector: DataConnectorRead;
132+
toggleView: () => void;
133+
}) {
134+
const [isCredentialsOpen, setCredentialsOpen] = useState(false);
135+
const [isDeleteOpen, setIsDeleteOpen] = useState(false);
136+
const [isEditOpen, setIsEditOpen] = useState(false);
137+
const onDelete = useCallback(() => {
138+
setIsDeleteOpen(false);
139+
toggleView();
140+
}, [toggleView]);
141+
const toggleCredentials = useCallback(() => {
142+
setCredentialsOpen((open) => !open);
143+
}, []);
144+
const toggleDelete = useCallback(() => {
145+
setIsDeleteOpen((open) => !open);
146+
}, []);
147+
const toggleEdit = useCallback(() => {
148+
setIsEditOpen((open) => !open);
149+
}, []);
150+
151+
const defaultAction = (
152+
<Button
153+
className="text-nowrap"
154+
color="outline-primary"
155+
data-cy="data-connector-edit"
156+
onClick={toggleEdit}
157+
size="sm"
158+
>
159+
<Pencil className={cx("bi", "me-1")} />
160+
Edit
161+
</Button>
162+
);
163+
164+
return (
165+
<>
166+
<ButtonWithMenuV2
167+
color="outline-primary"
168+
default={defaultAction}
169+
preventPropagation
170+
size="sm"
171+
>
172+
<DropdownItem
173+
data-cy="data-connector-credentials"
174+
onClick={toggleCredentials}
175+
>
176+
<Lock className={cx("bi", "me-1")} />
177+
Credentials
178+
</DropdownItem>
179+
<DropdownItem data-cy="data-connector-delete" onClick={toggleDelete}>
180+
<Trash className={cx("bi", "me-1")} />
181+
Remove
182+
</DropdownItem>
183+
</ButtonWithMenuV2>
184+
<DataConnectorCredentialsModal
185+
dataConnector={dataConnector}
186+
setOpen={setCredentialsOpen}
187+
isOpen={isCredentialsOpen}
188+
/>
189+
<DataConnectorDeleteModal
190+
dataConnector={dataConnector}
191+
isOpen={isDeleteOpen}
192+
onDelete={onDelete}
193+
toggleModal={toggleDelete}
194+
/>
195+
<DataConnectorModal
196+
dataConnector={dataConnector}
197+
isOpen={isEditOpen}
198+
namespace={dataConnector.namespace}
199+
toggle={toggleEdit}
200+
/>
201+
</>
202+
);
203+
}

0 commit comments

Comments
 (0)