ソースを参照

Implemented gitlab integration list

jnfrati 4 年 前
コミット
bbdad34af0

+ 205 - 0
dashboard/src/main/home/integrations/GitlabIntegrationList.tsx

@@ -0,0 +1,205 @@
+import React, { useContext, useRef, useState } from "react";
+import ConfirmOverlay from "../../../components/ConfirmOverlay";
+import styled from "styled-components";
+import { Context } from "../../../shared/Context";
+import api from "../../../shared/api";
+import { integrationList } from "shared/common";
+import DynamicLink from "components/DynamicLink";
+
+interface Props {
+  gitlabData: any[];
+}
+
+const GitlabIntegrationList: React.FC<Props> = (props) => {
+  const [isDelete, setIsDelete] = useState(false);
+  const [deleteIndex, setDeleteIndex] = useState(-1); // guaranteed to be set when used
+  const { currentProject, setCurrentError } = useContext(Context);
+  const deleted = useRef(new Set());
+
+  const handleDelete = () => {
+    alert("NOT IMPLEMENTED");
+    // api
+    //   .deleteSlackIntegration(
+    //     "<token>",
+    //     {},
+    //     {
+    //       project_id: currentProject.id,
+    //       slack_integration_id: props.gitlabData[deleteIndex].id,
+    //     }
+    //   )
+    //   .then(() => {
+    //     deleted.current.add(deleteIndex);
+    //     setIsDelete(false);
+    //   })
+    //   .catch((err) => {
+    //     setCurrentError(err);
+    //   });
+  };
+
+  return (
+    <>
+      <ConfirmOverlay
+        show={isDelete}
+        message={
+          deleteIndex != -1 &&
+          `Are you sure you want to delete the gitlab instance ${props.gitlabData[deleteIndex].instance_url}?`
+        }
+        onYes={handleDelete}
+        onNo={() => setIsDelete(false)}
+      />
+      <StyledIntegrationList>
+        {props.gitlabData?.length > 0 ? (
+          props.gitlabData.map((inst, idx) => {
+            if (deleted.current.has(idx)) return null;
+            return (
+              <Integration
+                onClick={() => {}}
+                disabled={false}
+                key={`${inst.team_id}-${inst.channel}`}
+              >
+                <MainRow disabled={false}>
+                  <Flex>
+                    <Icon src={integrationList.gitlab.icon} />
+                    <Label>{inst.instance_url}</Label>
+                  </Flex>
+                  <MaterialIconTray disabled={false}>
+                    <i
+                      className="material-icons"
+                      onClick={() => {
+                        setDeleteIndex(idx);
+                        setIsDelete(true);
+                      }}
+                    >
+                      delete
+                    </i>
+                    <i
+                      className="material-icons"
+                      onClick={() => {
+                        window.open(inst.instance_url, "_blank");
+                      }}
+                    >
+                      launch
+                    </i>
+                  </MaterialIconTray>
+                </MainRow>
+              </Integration>
+            );
+          })
+        ) : (
+          <Placeholder>No GitLab instances setted up yet.</Placeholder>
+        )}
+      </StyledIntegrationList>
+    </>
+  );
+};
+
+export default GitlabIntegrationList;
+
+const Placeholder = styled.div`
+  width: 100%;
+  height: 250px;
+  display: flex;
+  align-items: center;
+  font-size: 13px;
+  font-family: "Work Sans", sans-serif;
+  justify-content: center;
+  margin-top: 30px;
+  background: #ffffff11;
+  color: #ffffff44;
+  border-radius: 5px;
+`;
+
+const Label = styled.div`
+  color: #ffffff;
+  font-size: 14px;
+  font-weight: 500;
+`;
+
+const StyledIntegrationList = styled.div`
+  margin-top: 20px;
+  margin-bottom: 80px;
+`;
+
+const MainRow = styled.div`
+  height: 70px;
+  width: 100%;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  padding: 25px;
+  border-radius: 5px;
+  :hover {
+    background: ${(props: { disabled: boolean }) =>
+      props.disabled ? "" : "#ffffff11"};
+    > i {
+      background: ${(props: { disabled: boolean }) =>
+        props.disabled ? "" : "#ffffff11"};
+    }
+  }
+
+  > i {
+    border-radius: 20px;
+    font-size: 18px;
+    padding: 5px;
+    color: #ffffff44;
+    margin-right: -7px;
+    :hover {
+      background: ${(props: { disabled: boolean }) =>
+        props.disabled ? "" : "#ffffff11"};
+    }
+  }
+`;
+
+const Integration = styled.div`
+  margin-left: -2px;
+  display: flex;
+  flex-direction: column;
+  background: #26282f;
+  cursor: ${(props: { disabled: boolean }) =>
+    props.disabled ? "not-allowed" : "pointer"};
+  margin-bottom: 15px;
+  border-radius: 8px;
+  box-shadow: 0 4px 15px 0px #00000055;
+`;
+
+const Icon = styled.img`
+  width: 27px;
+  margin-right: 12px;
+  margin-bottom: -1px;
+`;
+
+const Flex = styled.div`
+  display: flex;
+  align-items: center;
+
+  > i {
+    cursor: pointer;
+    font-size: 24px;
+    color: #969fbbaa;
+    padding: 3px;
+    margin-right: 11px;
+    border-radius: 100px;
+    :hover {
+      background: #ffffff11;
+    }
+  }
+`;
+
+const MaterialIconTray = styled.div`
+  max-width: 60px;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  > i {
+    background: #26282f;
+    border-radius: 20px;
+    font-size: 18px;
+    padding: 5px;
+    margin: 0 5px;
+    color: #ffffff44;
+    :hover {
+      background: ${(props: { disabled: boolean }) =>
+        props.disabled ? "" : "#ffffff11"};
+    }
+  }
+`;

+ 22 - 3
dashboard/src/main/home/integrations/IntegrationCategories.tsx

@@ -10,6 +10,7 @@ import { pushFiltered } from "shared/routing";
 import Loading from "../../../components/Loading";
 import SlackIntegrationList from "./SlackIntegrationList";
 import TitleSection from "components/TitleSection";
+import GitlabIntegrationList from "./GitlabIntegrationList";
 
 type Props = RouteComponentProps & {
   category: string;
@@ -22,6 +23,7 @@ const IntegrationCategories: React.FC<Props> = (props) => {
   const [currentIntegrationData, setCurrentIntegrationData] = useState([]);
   const [loading, setLoading] = useState(false);
   const [slackData, setSlackData] = useState([]);
+  const [gitlabData, setGitlabData] = useState([]);
 
   const { currentProject, setCurrentModal } = useContext(Context);
 
@@ -79,6 +81,17 @@ const IntegrationCategories: React.FC<Props> = (props) => {
           })
           .catch(console.log);
         break;
+      case "gitlab":
+        api
+          .getGitlabIntegration(
+            "<token>",
+            {},
+            { project_id: currentProject.id }
+          )
+          .then((res) => {
+            setGitlabData(res.data);
+            setLoading(false);
+          });
       default:
         console.log("Unknown integration category.");
     }
@@ -110,7 +123,11 @@ const IntegrationCategories: React.FC<Props> = (props) => {
         </TitleSection>
         <Button
           onClick={() => {
-            if (props.category != "slack") {
+            if (props.category === "gitlab") {
+              pushFiltered(props, `/integrations/gitlab/create/gitlab`, [
+                "project_id",
+              ]);
+            } else if (props.category != "slack") {
               setCurrentModal("IntegrationsModal", {
                 category: currentCategory,
                 setCurrentIntegration: (x: string) =>
@@ -131,6 +148,8 @@ const IntegrationCategories: React.FC<Props> = (props) => {
       </Flex>
       {loading ? (
         <Loading />
+      ) : props.category === "gitlab" ? (
+        <GitlabIntegrationList gitlabData={gitlabData} />
       ) : props.category == "slack" ? (
         <SlackIntegrationList slackData={slackData} />
       ) : (
@@ -158,8 +177,8 @@ const Flex = styled.div`
 
   > i {
     cursor: pointer;
-    font-size 24px;
-    color: #969Fbbaa;
+    font-size: 24px;
+    color: #969fbbaa;
     padding: 3px;
     margin-right: 11px;
     border-radius: 100px;

+ 8 - 4
dashboard/src/main/home/integrations/Integrations.tsx

@@ -12,7 +12,11 @@ import TitleSection from "components/TitleSection";
 
 type PropsType = RouteComponentProps;
 
-const IntegrationCategoryStrings = ["registry", "slack"]; /*"kubernetes",*/
+const IntegrationCategoryStrings = [
+  "registry",
+  "slack",
+  "gitlab",
+]; /*"kubernetes",*/
 
 const Integrations: React.FC<PropsType> = (props) => {
   return (
@@ -69,7 +73,7 @@ const Integrations: React.FC<PropsType> = (props) => {
 
             <IntegrationList
               currentCategory={""}
-              integrations={["registry", "slack"]}
+              integrations={["registry", "slack", "gitlab"]}
               setCurrent={(x) =>
                 pushFiltered(props, `/integrations/${x}`, ["project_id"])
               }
@@ -106,8 +110,8 @@ const Flex = styled.div`
 
   > i {
     cursor: pointer;
-    font-size 24px;
-    color: #969Fbbaa;
+    font-size: 24px;
+    color: #969fbbaa;
     padding: 3px;
     margin-right: 11px;
     border-radius: 100px;

+ 18 - 0
dashboard/src/shared/api.tsx

@@ -61,6 +61,11 @@ const getAzureIntegration = baseApi<{}, { project_id: number }>(
   ({ project_id }) => `/api/projects/${project_id}/integrations/azure`
 );
 
+const getGitlabIntegration = baseApi<{}, { project_id: number }>(
+  "GET",
+  ({ project_id }) => `/api/projects/${project_id}/integrations/gitlab`
+);
+
 const createAWSIntegration = baseApi<
   {
     aws_region: string;
@@ -99,6 +104,17 @@ const createAzureIntegration = baseApi<
   return `/api/projects/${pathParams.id}/integrations/azure`;
 });
 
+const createGitlabIntegration = baseApi<
+  {
+    instance_url: string;
+    client_id: string;
+    client_secret: string;
+  },
+  { id: number }
+>("POST", (pathParams) => {
+  return `/api/projects/${pathParams.id}/integrations/gitlab`;
+});
+
 const createEmailVerification = baseApi<{}, {}>("POST", (pathParams) => {
   return `/api/email/verify/initiate`;
 });
@@ -1807,9 +1823,11 @@ export default {
   getAWSIntegration,
   getGCPIntegration,
   getAzureIntegration,
+  getGitlabIntegration,
   createAWSIntegration,
   overwriteAWSIntegration,
   createAzureIntegration,
+  createGitlabIntegration,
   createEmailVerification,
   createEnvironment,
   deleteEnvironment,

+ 1 - 0
dashboard/src/shared/common.tsx

@@ -108,6 +108,7 @@ export const integrationList: any = {
   gitlab: {
     icon: "https://about.gitlab.com/images/press/logo/png/gitlab-icon-rgb.png",
     label: "Gitlab",
+    buttonText: "Add instance",
   },
   rds: {
     icon: