|
|
@@ -2,13 +2,14 @@ import Helper from "components/form-components/Helper";
|
|
|
import InputRow from "components/form-components/InputRow";
|
|
|
import SelectRow from "components/form-components/SelectRow";
|
|
|
import UploadArea from "components/form-components/UploadArea";
|
|
|
+import Loading from "components/Loading";
|
|
|
import SaveButton from "components/SaveButton";
|
|
|
import { OFState } from "main/home/onboarding/state";
|
|
|
import {
|
|
|
GCPProvisionerConfig,
|
|
|
GCPRegistryConfig,
|
|
|
} from "main/home/onboarding/types";
|
|
|
-import React, { useState } from "react";
|
|
|
+import React, { useEffect, useState } from "react";
|
|
|
import api from "shared/api";
|
|
|
import styled from "styled-components";
|
|
|
import { useSnapshot } from "valtio";
|
|
|
@@ -41,13 +42,74 @@ const regionOptions = [
|
|
|
{ value: "us-west4", label: "us-west4" },
|
|
|
];
|
|
|
|
|
|
+const readableDate = (s: string) => {
|
|
|
+ const ts = new Date(s);
|
|
|
+ const date = ts.toLocaleDateString();
|
|
|
+ const time = ts.toLocaleTimeString([], {
|
|
|
+ hour: "numeric",
|
|
|
+ minute: "2-digit",
|
|
|
+ });
|
|
|
+ return `${time} on ${date}`;
|
|
|
+};
|
|
|
+
|
|
|
export const CredentialsForm: React.FC<{
|
|
|
nextFormStep: (data: Partial<GCPRegistryConfig>) => void;
|
|
|
project: any;
|
|
|
}> = ({ nextFormStep, project }) => {
|
|
|
+ const snap = useSnapshot(OFState);
|
|
|
const [projectId, setProjectId] = useState("");
|
|
|
const [serviceAccountKey, setServiceAccountKey] = useState("");
|
|
|
const [buttonStatus, setButtonStatus] = useState("");
|
|
|
+ const [showForm, setShowForm] = useState(false);
|
|
|
+ const [lastConnectedAccount, setLastConnectedAccount] = useState(null);
|
|
|
+ const [isLoading, setIsLoading] = useState(true);
|
|
|
+
|
|
|
+ useEffect(() => {
|
|
|
+ api
|
|
|
+ .getGCPIntegration("<token>", {}, { project_id: project.id })
|
|
|
+ .then((res) => {
|
|
|
+ let integrations = res.data;
|
|
|
+ if (!Array.isArray(integrations) || !integrations.length) {
|
|
|
+ setShowForm(true);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // DO NOT USE THE INTEGRATION ID FROM THE CONNECTED REGISTRY
|
|
|
+ integrations = integrations.filter((i) => {
|
|
|
+ return (
|
|
|
+ i.id !== snap.StateHandler?.connected_registry?.credentials?.id
|
|
|
+ );
|
|
|
+ });
|
|
|
+
|
|
|
+ // filter can change the type from integrations so just in case
|
|
|
+ // we check again that integrations is an array
|
|
|
+ if (!Array.isArray(integrations) || !integrations) {
|
|
|
+ setShowForm(true);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ integrations.sort((a, b) => b.id - a.id);
|
|
|
+
|
|
|
+ let lastUsed = integrations.find((i) => {
|
|
|
+ i.id === snap.StateHandler?.provision_resources?.credentials?.id;
|
|
|
+ });
|
|
|
+
|
|
|
+ if (!lastUsed) {
|
|
|
+ setShowForm(true);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ setLastConnectedAccount(lastUsed);
|
|
|
+ setShowForm(false);
|
|
|
+ })
|
|
|
+ .catch((err) => {
|
|
|
+ setShowForm(true);
|
|
|
+ console.error(err);
|
|
|
+ })
|
|
|
+ .finally(() => {
|
|
|
+ setIsLoading(false);
|
|
|
+ });
|
|
|
+ }, []);
|
|
|
|
|
|
const validate = () => {
|
|
|
if (!projectId) {
|
|
|
@@ -92,33 +154,85 @@ export const CredentialsForm: React.FC<{
|
|
|
setButtonStatus("Something went wrong, please try again");
|
|
|
}
|
|
|
};
|
|
|
+
|
|
|
+ const continueToNextStep = (integration_id: number) => {
|
|
|
+ nextFormStep({
|
|
|
+ credentials: {
|
|
|
+ id: integration_id,
|
|
|
+ },
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
+ if (isLoading) {
|
|
|
+ return <Loading />;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (showForm) {
|
|
|
+ return (
|
|
|
+ <>
|
|
|
+ <InputRow
|
|
|
+ type="text"
|
|
|
+ value={projectId}
|
|
|
+ setValue={(x: string) => {
|
|
|
+ setProjectId(x);
|
|
|
+ }}
|
|
|
+ label="🏷️ GCP Project ID"
|
|
|
+ placeholder="ex: blindfold-ceiling-24601"
|
|
|
+ width="100%"
|
|
|
+ isRequired={true}
|
|
|
+ />
|
|
|
+
|
|
|
+ <Helper>Service account credentials for GCP permissions.</Helper>
|
|
|
+ <UploadArea
|
|
|
+ setValue={(x: any) => setServiceAccountKey(x)}
|
|
|
+ label="🔒 GCP Key Data (JSON)"
|
|
|
+ placeholder="Choose a file or drag it here."
|
|
|
+ width="100%"
|
|
|
+ height="100%"
|
|
|
+ isRequired={true}
|
|
|
+ />
|
|
|
+ <SaveButton
|
|
|
+ text="Continue"
|
|
|
+ disabled={false}
|
|
|
+ onClick={submit}
|
|
|
+ makeFlush={true}
|
|
|
+ clearPosition={true}
|
|
|
+ status={buttonStatus}
|
|
|
+ statusPosition={"right"}
|
|
|
+ />
|
|
|
+ </>
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
return (
|
|
|
<>
|
|
|
- <InputRow
|
|
|
- type="text"
|
|
|
- value={projectId}
|
|
|
- setValue={(x: string) => {
|
|
|
- setProjectId(x);
|
|
|
- }}
|
|
|
- label="🏷️ GCP Project ID"
|
|
|
- placeholder="ex: blindfold-ceiling-24601"
|
|
|
- width="100%"
|
|
|
- isRequired={true}
|
|
|
- />
|
|
|
-
|
|
|
- <Helper>Service account credentials for GCP permissions.</Helper>
|
|
|
- <UploadArea
|
|
|
- setValue={(x: any) => setServiceAccountKey(x)}
|
|
|
- label="🔒 GCP Key Data (JSON)"
|
|
|
- placeholder="Choose a file or drag it here."
|
|
|
- width="100%"
|
|
|
- height="100%"
|
|
|
- isRequired={true}
|
|
|
+ <div>
|
|
|
+ Last connected account:
|
|
|
+ <div>
|
|
|
+ <b>ARN: </b>
|
|
|
+ {lastConnectedAccount?.aws_arn}
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <b>Connected on:</b> {readableDate(lastConnectedAccount?.created_at)}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <Br />
|
|
|
+ <SaveButton
|
|
|
+ text="Connect another account"
|
|
|
+ disabled={false}
|
|
|
+ onClick={() => setShowForm(true)}
|
|
|
+ makeFlush={true}
|
|
|
+ clearPosition={true}
|
|
|
+ status={""}
|
|
|
+ statusPosition={"right"}
|
|
|
/>
|
|
|
+ <Br />
|
|
|
+ <b>Or</b>
|
|
|
+ <Br />
|
|
|
<SaveButton
|
|
|
- text="Continue"
|
|
|
+ text="Continue with current account"
|
|
|
disabled={false}
|
|
|
- onClick={submit}
|
|
|
+ onClick={() => continueToNextStep(lastConnectedAccount?.id)}
|
|
|
makeFlush={true}
|
|
|
clearPosition={true}
|
|
|
status={buttonStatus}
|