sdess09 2 роки тому
батько
коміт
bd71ac6f3e

Різницю між файлами не показано, бо вона завелика
+ 506 - 441
dashboard/src/components/ProvisionerSettings.tsx


+ 93 - 68
dashboard/src/main/home/sidebar/ClusterList.tsx

@@ -1,30 +1,38 @@
-import React, { useState, useEffect, useRef, useContext } from "react";
+import React, { useContext, useEffect, useRef, useState } from "react";
+import { withRouter } from "react-router";
 import styled from "styled-components";
-import gradient from "assets/gradient.png";
-import api from "shared/api";
-import infra from "assets/cluster.svg";
 
-import { Context } from "shared/Context";
-import { ClusterType } from "shared/types";
-import { RouteComponentProps, withRouter } from "react-router";
 import Icon from "components/porter/Icon";
-import Spacer from "components/porter/Spacer";
+
+import api from "shared/api";
+import { Context } from "shared/Context";
 import { pushFiltered } from "shared/routing";
-import SidebarLink from "./SidebarLink";
-import { OFState } from "main/home/onboarding/state";
-import ProvisionClusterModal from "./ProvisionClusterModal";
+import { type ClusterType } from "shared/types";
+import infra from "assets/cluster.svg";
 
+import ProvisionClusterModal from "./ProvisionClusterModal";
+import SidebarLink from "./SidebarLink";
 
-const ClusterList: React.FC<PropsType> = (props) => {
-  const { setCurrentCluster, user, currentCluster, currentProject, setHasFinishedOnboarding } = useContext(Context);
+type ClusterOptions = {
+  label: string;
+  value: string;
+};
+type NavButtonProps = {
+  disabled?: boolean;
+  active?: boolean;
+};
+const ClusterList: React.FC = (props) => {
+  const { setCurrentCluster, currentCluster, currentProject } =
+    useContext(Context);
   const [expanded, setExpanded] = useState<boolean>(false);
-  const [clusterModalVisible, setClusterModalVisible] = useState<boolean>(false);
+  const [clusterModalVisible, setClusterModalVisible] =
+    useState<boolean>(false);
   const wrapperRef = useRef<HTMLDivElement>(null);
   const [clusters, setClusters] = useState<ClusterType[]>([]);
-  const [options, setOptions] = useState<any[]>([]);
+  const [options, setOptions] = useState<ClusterOptions[]>([]);
 
   useEffect(() => {
-    const handleClickOutside = (e: MouseEvent) => {
+    const handleClickOutside = (e: MouseEvent): void => {
       if (
         wrapperRef.current &&
         !wrapperRef.current.contains(e.target as Node)
@@ -46,62 +54,69 @@ const ClusterList: React.FC<PropsType> = (props) => {
         .getClusters("<token>", {}, { id: currentProject?.id })
         .then((res) => {
           if (res.data) {
-            let clusters = res.data;
-            clusters.sort((a: any, b: any) => a.id - b.id);
+            const clusters = res.data;
+            clusters.sort(
+              (a: { id: number }, b: { id: number }) => a.id - b.id
+            );
             if (clusters.length > 0) {
-              let options = clusters.map((item: { name: any; vanity_name: string; }) => ({
-                label: (item.vanity_name ? item.vanity_name : item.name),
-                value: item.name
-              }));
+              const options: ClusterOptions[] = clusters.map(
+                (item: { vanity_name: string; name: string }) => ({
+                  label: item.vanity_name ? item.vanity_name : item.name,
+                  value: item.name,
+                })
+              );
               setClusters(clusters);
               setOptions(options);
             }
           }
+        })
+        .catch((error) => {
+          if (error) {
+            setClusters([]);
+            setOptions([]);
+          }
         });
     }
   }, [currentProject, currentCluster]);
-  const truncate = (input: string) => input.length > 27 ? `${input.substring(0, 27)}...` : input;
 
-  const renderOptionList = () =>
+  const truncate = (input: string): string =>
+    input.length > 27 ? `${input.substring(0, 27)}...` : input;
+
+  const renderOptionList = (): JSX.Element[] =>
     options.map((option, i: number) => (
-      <Option
+      <OptionDiv
         key={i}
         selected={option.value === currentCluster?.name}
         title={option.label}
         onClick={() => {
           setExpanded(false);
-          const cluster = clusters.find(c => c.name === option.value);
+          const cluster = clusters.find((c) => c.name === option.value);
           setCurrentCluster(cluster);
           pushFiltered(props, "/apps", ["project_id"], {});
         }}
       >
         <Icon src={infra} height={"14px"} />
         <ClusterLabel>{option.label}</ClusterLabel>
-      </Option>
-
+      </OptionDiv>
     ));
 
-  const renderDropdown = () =>
+  const renderDropdown = (): false | JSX.Element =>
     expanded && (
       <>
         <Dropdown>
           {renderOptionList()}
-
-          {/* Connect Cluster Option */}
-          {
-            currentProject?.enable_reprovision && <Option
+          {currentProject?.enable_reprovision && (
+            <OptionDiv
+              selected={false}
               onClick={() => {
-                setClusterModalVisible(true)
+                setClusterModalVisible(true);
                 setExpanded(false);
-
-              }}>
-
-              <Plus>+</Plus>    Deploy new cluster
-            </Option>
-          }
-
+              }}
+            >
+              <Plus>+</Plus> Deploy new cluster
+            </OptionDiv>
+          )}
         </Dropdown>
-
       </>
     );
 
@@ -109,33 +124,43 @@ const ClusterList: React.FC<PropsType> = (props) => {
     return (
       <StyledClusterSection ref={wrapperRef}>
         <MainSelector
-          onClick={() => setExpanded(!expanded)}
+          onClick={() => {
+            setExpanded(!expanded);
+          }}
           expanded={expanded}
         >
-
-          <NavButton>
+          <NavButton active={false} path={``}>
             <Img src={infra} />
-            <ClusterName>{truncate(currentCluster.vanity_name ? currentCluster.vanity_name : currentCluster?.name)}</ClusterName>
+            <ClusterName>
+              {truncate(
+                currentCluster.vanity_name
+                  ? currentCluster.vanity_name
+                  : currentCluster?.name
+              )}
+            </ClusterName>
 
             <i className="material-icons">arrow_drop_down</i>
           </NavButton>
         </MainSelector>
         {renderDropdown()}
-        {
-          clusterModalVisible && <ProvisionClusterModal
-            closeModal={() => setClusterModalVisible(false)} />
-        }
-      </StyledClusterSection >
+        {clusterModalVisible && (
+          <ProvisionClusterModal
+            closeModal={() => {
+              setClusterModalVisible(false);
+            }}
+          />
+        )}
+      </StyledClusterSection>
     );
   }
 
   return (
     <InitializeButton
-      onClick={() =>
+      onClick={() => {
         pushFiltered(props, "/new-cluster", ["cluster_id"], {
           new_cluster: true,
-        })
-      }
+        });
+      }}
     >
       <Plus>+</Plus> Create a cluster
     </InitializeButton>
@@ -148,7 +173,7 @@ const ClusterLabel = styled.div`
   overflow: hidden;
   white-space: nowrap;
   text-overflow: ellipsis;
-  margin-left: 12px
+  margin-left: 12px;
 `;
 
 const Plus = styled.div`
@@ -167,7 +192,7 @@ const InitializeButton = styled.div`
   font-size: 13px;
   font-weight: 500;
   border-radius: 3px;
-  color: ${props => props.theme.text.primary};
+  color: ${(props) => props.theme.text.primary};
   padding-bottom: 1px;
   cursor: pointer;
   background: #ffffff11;
@@ -177,7 +202,7 @@ const InitializeButton = styled.div`
   }
 `;
 
-const Option = styled.div<{ selected: boolean }>`
+const OptionDiv = styled.div<{ selected: boolean }>`
   width: 100%;
   height: 45px;
   display: flex;
@@ -187,8 +212,8 @@ const Option = styled.div<{ selected: boolean }>`
   padding: 0 15px;
   cursor: pointer;
   padding-right: 10px;
-  text-decoration: ${props => props.selected ? "underline" : "none"};
-  color: ${props => props.theme.text.primary};
+  text-decoration: ${(props) => (props.selected ? "underline" : "none")};
+  color: ${(props) => props.theme.text.primary};
   opacity: 0.6;
   :hover {
     opacity: 1;
@@ -210,7 +235,7 @@ const Dropdown = styled.div`
   width: 230px;
   max-height: 500px;
   border-radius: 5px;
-  border: 1px solid #494B4F;
+  border: 1px solid #494b4f;
   z-index: 999;
   overflow-y: auto;
   margin-bottom: 20px;
@@ -222,7 +247,7 @@ const ClusterName = styled.div`
   text-overflow: ellipsis;
   display: flex;
   align-items: center;
-  max-width: 200px; 
+  max-width: 200px;
 `;
 
 const MainSelector = styled.div`
@@ -233,7 +258,7 @@ const MainSelector = styled.div`
   font-size: 14px;
   cursor: pointer;
   padding: 10px 0;
-  
+
   :hover {
     > i {
       background: #ffffff22;
@@ -249,14 +274,14 @@ const MainSelector = styled.div`
     justify-content: center;
     border-radius: 20px;
     background: ${(props: { expanded: boolean }) =>
-    props.expanded ? "#ffffff22" : ""};
+      props.expanded ? "#ffffff22" : ""};
   }
 `;
 
 const StyledClusterSection = styled.div`
   position: relative;
   margin-left: 3px;
-  background: #181B20;
+  background: #181b20;
   border: 1px solid #383a3f;
   border-left: none;
 `;
@@ -269,14 +294,15 @@ const NavButton = styled(SidebarLink)`
   border-radius: 5px;
   margin-left: 16px;
   font-size: 13px;
-  color: ${props => props.theme.text.primary};
+  color: ${(props) => props.theme.text.primary};
   cursor: ${(props: { disabled?: boolean }) =>
     props.disabled ? "not-allowed" : "pointer"};
 
-  background: ${(props: any) => (props.active ? "#ffffff11" : "")};
+  background: ${(props: NavButtonProps) => (props.active ? "#ffffff11" : "")};
 
   :hover {
-    background: ${(props: any) => (props.active ? "#ffffff11" : "#ffffff08")};
+    background: ${(props: NavButtonProps) =>
+      props.active ? "#ffffff11" : "#ffffff08"};
   }
 
   &.active {
@@ -299,7 +325,6 @@ const NavButton = styled(SidebarLink)`
   }
 `;
 
-
 const Img = styled.img<{ enlarge?: boolean }>`
   padding: ${(props) => (props.enlarge ? "0 0 0 1px" : "4px")};
   height: 25px;

+ 12 - 21
dashboard/src/main/home/sidebar/ClusterListContainer.tsx

@@ -1,27 +1,18 @@
-import React, { Component } from "react";
+import React, { useContext } from "react";
 
 import { Context } from "shared/Context";
-import ClusterList from "./ClusterList";
-
-type PropsType = {};
 
-type StateType = {};
+import ClusterList from "./ClusterList";
 
-// Props in context to project section to trigger update on context change
-export default class ClusterListContainer extends Component<
-  PropsType,
-  StateType
-> {
-  state = {};
+const ClusterListContainer = (): JSX.Element => {
+  const context = useContext(Context);
 
-  render() {
-    return (
-      <ClusterList
-        currentProject={this.context.currentProject}
-        projects={this.context.projects}
-      />
-    );
-  }
-}
+  return (
+    <ClusterList
+      currentProject={context.currentProject}
+      projects={context.projects}
+    />
+  );
+};
 
-ClusterListContainer.contextType = Context;
+export default ClusterListContainer;

+ 49 - 64
dashboard/src/main/home/sidebar/ProvisionClusterModal.tsx

@@ -1,73 +1,58 @@
-import { RouteComponentProps, withRouter } from "react-router";
-import styled, { css } from "styled-components";
-import React, { useContext, useEffect, useState } from "react";
-import Loading from "components/Loading";
+import React, { useState } from "react";
+import { withRouter, type RouteComponentProps } from "react-router";
+import styled from "styled-components";
 
 import Modal from "components/porter/Modal";
+import Spacer from "components/porter/Spacer";
 import Text from "components/porter/Text";
-import AWSCredentialsList from "./AddCluster/AWSCredentialList";
-import { InfraCredentials } from "shared/types";
 import ProvisionerSettings from "components/ProvisionerSettings";
-import Spacer from "components/porter/Spacer";
-import ProvisionerForm from "components/ProvisionerForm";
-
-
-type Props = RouteComponentProps & {
-    closeModal: () => void;
-
-}
-
-const ProvisionClusterModal: React.FC<Props> = ({
-    closeModal,
 
-}) => {
-    const [currentCredential, setCurrentCredential] = useState<InfraCredentials>(
-        null
-    );
-    const [currentStep, setCurrentStep] = useState("cloud");
-    const [targetArn, setTargetARN] = useState("")
+import { type InfraCredentials } from "shared/types";
 
-    return (
-        <Modal closeModal={closeModal} width={"1000px"}>
-            <Text size={16}>
-                Provision A New Cluster
-            </Text>
-            <Spacer y={1} />
-            <ScrollableContent>
-                {currentCredential && targetArn ? (
-                    <>
-                        <ProvisionerSettings
-                            credentialId={targetArn}
-                            closeModal={closeModal}
-                        />
-                        {/* Uncommented for future use if needed.
-                    <ProvisionerForm
-                        goBack={() => setCurrentStep("credentials")}
-                        credentialId={String(currentCredential.aws_integration_id)}
-                        provider={"aws"}
-                    /> */}
-                    </>
-                ) : (
-                    <AWSCredentialsList
-                        setTargetARN={setTargetARN}
-                        selectCredential={
-                            (i) => setCurrentCredential({
-                                aws_integration_id: i,
-                            })
-                        }
-                    />
-                )}
-            </ScrollableContent>
-        </Modal >
-    )
-}
+import AWSCredentialsList from "./AddCluster/AWSCredentialList";
 
-export default ProvisionClusterModal;
+type Props = RouteComponentProps & {
+  closeModal: () => void;
+};
+
+const ProvisionClusterModal: React.FC<Props> = ({ closeModal }) => {
+  const [currentCredential, setCurrentCredential] =
+    useState<InfraCredentials | null>(null);
+  const [targetArn, setTargetARN] = useState("");
+
+  return (
+    <Modal closeModal={closeModal} width={"1000px"}>
+      <Text size={16}>Provision A New Cluster</Text>
+      <Spacer y={1} />
+      <ScrollableContent>
+        {currentCredential && targetArn ? (
+          <>
+            <ProvisionerSettings
+              credentialId={targetArn}
+              closeModal={closeModal}
+            />
+          </>
+        ) : (
+          <AWSCredentialsList
+            setTargetARN={setTargetARN}
+            selectCredential={(i) => {
+              setCurrentCredential({
+                aws_integration_id: i,
+              });
+            }}
+          />
+        )}
+      </ScrollableContent>
+    </Modal>
+  );
+};
+
+export default withRouter(ProvisionClusterModal);
 
 const ScrollableContent = styled.div`
-    width: 100%;
-    max-height: 700px;  // or whatever height you prefer
-    overflow-y: auto;
-    padding: 10px;
-    position: relative;
-`;
+  width: 100%;
+  max-height: 700px; // or whatever height you prefer
+  overflow-y: auto;
+  padding: 10px;
+  position: relative;
+`;

Деякі файли не було показано, через те що забагато файлів було змінено