Quellcode durchsuchen

handle null creds response

Justin Rhee vor 3 Jahren
Ursprung
Commit
f57f90bfeb

+ 3 - 2
dashboard/src/components/CredentialsForm.tsx

@@ -51,9 +51,10 @@ const CredentialsForm: React.FC<Props> = ({
       )
       .then(({ data }) => {
         if (!Array.isArray(data)) {
-          throw Error("Data is not an array");
+          setAWSCredentials([]);
+        } else {
+          setAWSCredentials(data);
         }
-        setAWSCredentials(data);
         setIsLoading(false);
       })
       .catch((err) => {

+ 0 - 0
dashboard/src/components/ExpandableSection.tsx → dashboard/src/components/porter/ExpandableSection.tsx


+ 52 - 0
dashboard/src/components/porter/LoadingBar.tsx

@@ -0,0 +1,52 @@
+import React, { useEffect, useState } from "react";
+import styled, { keyframes } from "styled-components";
+
+type Props = {
+  percent?: number;
+  completed?: number;
+  total?: number;
+};
+
+const LoadingBar: React.FC<Props> = ({
+  percent,
+  completed,
+  total,
+}) => {
+  return (
+    <StyledLoadingBar>
+      <LoadingFill 
+        percent={(percent || ((100.0 * completed) / total)) + "%"}
+      />
+    </StyledLoadingBar>
+  );
+};
+
+export default LoadingBar;
+
+const StyledLoadingBar = styled.div`
+  background: #ffffff22;
+  width: 100%;
+  height: 8px;
+  overflow: hidden;
+  border-radius: 100px;
+`;
+
+const movingGradient = keyframes`
+  0% {
+      background-position: left bottom;
+  }
+
+  100% {
+      background-position: right bottom;
+  }
+`;
+
+const LoadingFill = styled.div<{ percent: string }>`
+  width: ${props => props.percent};
+  background: linear-gradient(to right, #8ce1ff, #616FEE);
+  height: 100%;
+  background-size: 250% 100%;
+  animation: ${movingGradient} 2s infinite;
+  animation-timing-function: ease-in-out;
+  animation-direction: alternate;
+`;

+ 31 - 0
dashboard/src/components/porter/Spacer.tsx

@@ -0,0 +1,31 @@
+import React, { useEffect, useState } from "react";
+import styled from "styled-components";
+
+type Props = {
+  height?: string;
+  y?: number;
+  inline?: boolean;
+};
+
+const Spacer: React.FC<Props> = ({
+  height,
+  y,
+  inline,
+}) => {
+  const getCalcHeight = () => {
+    return 25 * y;
+  };
+  
+  return (
+    <StyledSpacer
+      height={height || (getCalcHeight() + "px")}
+    />
+  );
+};
+
+export default Spacer;
+
+const StyledSpacer = styled.div<{ height: string }>`
+  height: ${props => props.height};
+  width: ${props => props.height ? "100%" : ""};
+`;

+ 24 - 0
dashboard/src/components/porter/TemplateComponent.tsx

@@ -0,0 +1,24 @@
+import React, { useEffect, useState } from "react";
+import styled from "styled-components";
+
+type Props = {
+};
+
+const TemplateComponent: React.FC<Props> = ({
+}) => {
+  const [isExpanded, setIsExpanded] = useState(false);
+
+  useEffect(() => {
+    // Do something
+  }, []);
+
+  return (
+    <StyledTemplateComponent>
+    </StyledTemplateComponent>
+  );
+};
+
+export default TemplateComponent;
+
+const StyledTemplateComponent = styled.div`
+`;

+ 42 - 0
dashboard/src/components/porter/Text.tsx

@@ -0,0 +1,42 @@
+import React, { useEffect, useState } from "react";
+import styled from "styled-components";
+
+type Props = {
+  size?: number;
+  color?: string;
+  children: any;
+};
+
+const Text: React.FC<Props> = ({
+  size,
+  color,
+  children
+}) => {
+  const getColor = () => {
+    switch (color) {
+      case "helper":
+        return "#aaaabb";
+      default:
+        return color;
+    }
+  };
+  
+  return (
+    <StyledText
+      size={size}
+      color={getColor()}
+    >
+      {children}
+    </StyledText>
+  );
+};
+
+export default Text;
+
+const StyledText = styled.div<{ 
+  size?: number; 
+  color?: string 
+}>`
+  color: ${props => props.color || "#ffffff"};
+  font-size: ${props => props.size || 13}px;
+`;

+ 1 - 2
dashboard/src/main/home/cluster-dashboard/dashboard/ClusterRevisionSelector.tsx

@@ -7,7 +7,7 @@ import warning from "assets/warning.png";
 
 import { readableDate } from "shared/string_utils";
 import { Context } from "shared/Context";
-import ExpandableSection from "components/ExpandableSection";
+import ExpandableSection from "components/porter/ExpandableSection";
 import { 
   Contract, 
   Cluster, 
@@ -383,5 +383,4 @@ const Label = styled.div<{ isCurrent?: boolean }>`
 `;
 
 const StyledClusterRevisionSelector = styled.div`
-  margin-bottom: 22px;
 `;

+ 5 - 1
dashboard/src/main/home/cluster-dashboard/dashboard/Dashboard.tsx

@@ -21,6 +21,7 @@ import Metrics from "./Metrics";
 
 import CopyToClipboard from "components/CopyToClipboard";
 import Loading from "components/Loading";
+import Spacer from "components/porter/Spacer";
 
 type TabEnum = "nodes" | "settings" | "namespaces" | "metrics" | "incidents" | "configuration";
 
@@ -193,7 +194,10 @@ export const Dashboard: React.FunctionComponent = () => {
               context.currentCluster.status === "UPDATING_UNAVAILABLE"
             )
           ) && (
-            <ProvisionerStatus />
+            <>
+              <Spacer y={1} />
+              <ProvisionerStatus />
+            </>
           )}
           <TabSelector
             options={currentTabOptions}

+ 67 - 14
dashboard/src/main/home/cluster-dashboard/dashboard/ProvisionerStatus.tsx

@@ -6,34 +6,81 @@ import api from "shared/api";
 import loading from "assets/loading.gif";
 
 import { Context } from "shared/Context";
-import ExpandableSection from "components/ExpandableSection";
+import ExpandableSection from "components/porter/ExpandableSection";
+import LoadingBar from "components/porter/LoadingBar";
+import Spacer from "components/porter/Spacer";
+import Helper from "components/form-components/Helper";
+import Text from "components/porter/Text";
 
 type Props = {};
 
 const ProvisionerStatus: React.FC<Props> = ({}) => {
-  const { currentProject, setCurrentCluster } = useContext(Context);
-  const [isExpanded, setIsExpanded] = useState(false);
+  const { currentProject, currentCluster } = useContext(Context);
+  const [progress, setProgress] = useState(1);
+
+  // Continuously poll provisioning status
+  const pollProvisioningStatus = async () => {
+    try {
+      const res = await api.getClusterStatus(
+        "<token>",
+        {},
+        {
+          project_id: currentProject.id,
+          cluster_id: currentCluster.id,
+        }
+      );
+      const { status } = res.data;
+      switch (status) {
+        case status["BOOTSTRAP_READY"]:
+          setProgress(2);
+          break;
+        case status["CONTROL_PLANE_READY"]:
+          setProgress(3);
+          break;
+        case status["INFRASTRUCTURE_READY"]:
+          setProgress(4);
+          break;
+        default:
+          setProgress(1);
+      }
+    } catch (error) {}
+  };
 
   return (
     <StyledProvisionerStatus>
-      <ExpandableSection
-        isInitiallyExpanded={true}
-        Header={(
-          <>
-            <Icon src={aws} />
-            AWS provisioning status
-          </>
-        )}
-        ExpandedSection={(
+      <HeaderSection>
+        <Flex>
+          <Icon src={aws} />
+          AWS provisioning status
+        </Flex>
+        <Spacer height="18px" />
+        <LoadingBar completed={progress} total={4} />
+        <Spacer height="18px" />
+        <Text color="#aaaabb">
+          Setup can take up to 20 minutes. You can close this window and come back later. 
+        </Text>
+      </HeaderSection>
+      {
+        false && (
           <DummyLogs>[Logs unimplemented]</DummyLogs>
-        )}
-      />
+        )
+      }
     </StyledProvisionerStatus>
   );
 };
 
 export default ProvisionerStatus;
 
+const Flex = styled.div`
+  display: flex;
+  align-items: center;
+`;
+
+const HeaderSection = styled.div`
+  padding: 15px;
+  padding-bottom: 18px;
+`;
+
 const DummyLogs = styled.div`
   height: 150px;
   width: 100%;
@@ -65,4 +112,10 @@ const Status = styled.div`
 
 const StyledProvisionerStatus = styled.div`
   margin-bottom: 22px;
+  border-radius: 5px;
+  background: #26292e;
+  border: 1px solid #494b4f;
+  font-size: 13px;
+  width: 100%;
+  overflow: hidden;
 `;

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

@@ -749,6 +749,16 @@ const getCluster = baseApi<
   return `/api/projects/${pathParams.project_id}/clusters/${pathParams.cluster_id}`;
 });
 
+const getClusterStatus = baseApi<
+  {},
+  {
+    project_id: number;
+    cluster_id: number;
+  }
+>("GET", (pathParams) => {
+  return `/api/projects/${pathParams.project_id}/clusters/${pathParams.cluster_id}/status`;
+});
+
 const getClusterNodes = baseApi<
   {},
   {
@@ -2431,6 +2441,7 @@ export default {
   getCluster,
   getClusterNodes,
   getClusterNode,
+  getClusterStatus,
   getConfigMap,
   getPRDeploymentList,
   getPRDeploymentByID,