Просмотр исходного кода

Implemented install or upgrade button for porter agent

jnfrati 4 лет назад
Родитель
Сommit
3dd78307ef

+ 2 - 3
dashboard/src/main/home/cluster-dashboard/dashboard/Dashboard.tsx

@@ -11,11 +11,10 @@ import { NamespaceList } from "./NamespaceList";
 import ClusterSettings from "./ClusterSettings";
 import useAuth from "shared/auth/useAuth";
 import Metrics from "./Metrics";
-import EventsTab from "./events/EventsTab";
 import EnvironmentList from "./preview-environments/EnvironmentList";
 import { useLocation } from "react-router";
 import { getQueryParam } from "shared/routing";
-import IncidentsTable from "./incidents/IncidentsTable";
+import IncidentsTab from "./incidents/IncidentsTab";
 
 type TabEnum =
   | "preview_environments"
@@ -55,7 +54,7 @@ export const Dashboard: React.FunctionComponent = () => {
         }
         return <NodeList />;
       case "incidents":
-        return <IncidentsTable />;
+        return <IncidentsTab />;
       case "settings":
         return <ClusterSettings />;
       case "metrics":

+ 192 - 0
dashboard/src/main/home/cluster-dashboard/dashboard/incidents/IncidentsTab.tsx

@@ -0,0 +1,192 @@
+import Loading from "components/Loading";
+import React, { useContext, useEffect, useState } from "react";
+import api from "shared/api";
+import { Context } from "shared/Context";
+import styled from "styled-components";
+import IncidentsTable from "./IncidentsTable";
+
+export type DetectAgentResponse = {
+  version: string;
+};
+
+const IncidentsTab = () => {
+  const { currentProject, currentCluster } = useContext(Context);
+  const [isAgentInstalled, setIsAgentInstalled] = useState(false);
+  const [isAgentOutdated, setIsAgentOutdated] = useState(false);
+  const [isLoading, setIsLoading] = useState(true);
+
+  useEffect(() => {
+    api
+      .detectPorterAgent<DetectAgentResponse>(
+        "<token>",
+        {},
+        {
+          project_id: currentProject.id,
+          cluster_id: currentCluster.id,
+        }
+      )
+      .then((res) => res.data)
+      .then((data) => {
+        if (data.version === "v1") {
+          setIsAgentInstalled(true);
+          setIsAgentOutdated(true);
+        } else {
+          setIsAgentInstalled(true);
+          setIsAgentOutdated(false);
+        }
+      })
+      .catch(() => {
+        setIsAgentInstalled(false);
+      })
+      .finally(() => {
+        setIsLoading(false);
+      });
+  }, []);
+
+  const upgradeAgent = async () => {
+    const project_id = currentProject?.id;
+    const cluster_id = currentCluster?.id;
+    try {
+      await api.upgradePorterAgent(
+        "<token>",
+        {},
+        {
+          project_id,
+          cluster_id,
+        }
+      );
+      setIsAgentOutdated(false);
+    } catch (err) {
+      setIsAgentOutdated(true);
+    }
+  };
+
+  const installAgent = async () => {
+    const project_id = currentProject?.id;
+    const cluster_id = currentCluster?.id;
+
+    api
+      .installPorterAgent("<token>", {}, { project_id, cluster_id })
+      .then(() => {
+        setIsAgentInstalled(true);
+      })
+      .catch(() => {
+        setIsAgentInstalled(false);
+      });
+  };
+
+  const triggerInstall = () => {
+    if (isAgentOutdated) {
+      upgradeAgent();
+      return;
+    }
+
+    installAgent();
+  };
+
+  if (isLoading) {
+    return (
+      <StyledCard>
+        <Loading height="200px" />
+      </StyledCard>
+    );
+  }
+
+  if (!isAgentInstalled || isAgentOutdated) {
+    return (
+      <StyledCard>
+        <Placeholder>
+          <InstallPorterAgentButton onClick={() => triggerInstall()}>
+            <i className="material-icons">add</i> Enable incidents detection
+          </InstallPorterAgentButton>
+        </Placeholder>
+      </StyledCard>
+    );
+  }
+
+  return (
+    <StyledCard>
+      <IncidentsTable />
+    </StyledCard>
+  );
+};
+
+export default IncidentsTab;
+
+const StyledCard = styled.div`
+  margin-top: 35px;
+  background: #26282f;
+  padding: 14px;
+  border-radius: 8px;
+  box-shadow: 0 4px 15px 0px #00000055;
+  position: relative;
+  border: 2px solid #9eb4ff00;
+  width: 100%;
+  height: 100%;
+  :not(:last-child) {
+    margin-bottom: 25px;
+  }
+`;
+
+const InstallPorterAgentButton = styled.button`
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  justify-content: space-between;
+  font-size: 13px;
+  cursor: pointer;
+  font-family: "Work Sans", sans-serif;
+  border: none;
+  border-radius: 5px;
+  color: white;
+  height: 35px;
+  padding: 0px 8px;
+  padding-bottom: 1px;
+  margin-top: 20px;
+  font-weight: 500;
+  padding-right: 15px;
+  overflow: hidden;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+  box-shadow: 0 5px 8px 0px #00000010;
+  cursor: ${(props: { disabled?: boolean }) =>
+    props.disabled ? "not-allowed" : "pointer"};
+  background: ${(props: { disabled?: boolean }) =>
+    props.disabled ? "#aaaabbee" : "#5561C0"};
+  :hover {
+    filter: ${(props) => (!props.disabled ? "brightness(120%)" : "")};
+  }
+  > i {
+    color: white;
+    width: 18px;
+    height: 18px;
+    font-weight: 600;
+    font-size: 12px;
+    border-radius: 20px;
+    display: flex;
+    align-items: center;
+    margin-right: 5px;
+    justify-content: center;
+  }
+`;
+
+const Placeholder = styled.div`
+  padding: 30px;
+  margin-top: 35px;
+  padding-bottom: 40px;
+  font-size: 13px;
+  color: #ffffff44;
+  min-height: 400px;
+  height: 50vh;
+  background: #26282f;
+  border-radius: 8px;
+  width: 100%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+
+  > i {
+    font-size: 18px;
+    margin-right: 8px;
+  }
+`;

+ 9 - 34
dashboard/src/main/home/cluster-dashboard/dashboard/incidents/IncidentsTable.tsx

@@ -79,41 +79,16 @@ const IncidentsTable = () => {
   }, [incidents]);
 
   return (
-    <TableWrapper>
-      <StyledCard>
-        <Table
-          columns={columns}
-          data={data}
-          isLoading={incidents === null}
-          onRowClick={(row: any) => {
-            pushFiltered(
-              `/cluster-dashboard/incidents/${row?.original?.id}`,
-              []
-            );
-          }}
-          hasError={hasError}
-        />
-      </StyledCard>
-    </TableWrapper>
+    <Table
+      columns={columns}
+      data={data}
+      isLoading={incidents === null}
+      onRowClick={(row: any) => {
+        pushFiltered(`/cluster-dashboard/incidents/${row?.original?.id}`, []);
+      }}
+      hasError={hasError}
+    />
   );
 };
 
 export default IncidentsTable;
-
-const TableWrapper = styled.div`
-  margin-top: 35px;
-`;
-
-const StyledCard = styled.div`
-  background: #26282f;
-  padding: 14px;
-  border-radius: 8px;
-  box-shadow: 0 4px 15px 0px #00000055;
-  position: relative;
-  border: 2px solid #9eb4ff00;
-  width: 100%;
-  height: 100%;
-  :not(:last-child) {
-    margin-bottom: 25px;
-  }
-`;

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

@@ -1643,6 +1643,15 @@ const getIncidentLogsByLogId = baseApi<
     `/api/projects/${project_id}/clusters/${cluster_id}/namespaces/${namespace}/releases/${name}/incidents/logs/${log_id}`
 );
 
+const upgradePorterAgent = baseApi<
+  {},
+  { project_id: number; cluster_id: number }
+>(
+  "GET",
+  ({ project_id, cluster_id }) =>
+    `/api/projects/${project_id}/clusters/${cluster_id}/agent/upgrade`
+);
+
 // Bundle export to allow default api import (api.<method> is more readable)
 export default {
   checkAuth,
@@ -1800,4 +1809,5 @@ export default {
   getIncidentsByReleaseName,
   getIncidentById,
   getIncidentLogsByLogId,
+  upgradePorterAgent,
 };