Justin Rhee 3 лет назад
Родитель
Сommit
11e1225867

+ 78 - 0
dashboard/src/components/ExpandableSection.tsx

@@ -0,0 +1,78 @@
+import React, { useState } from "react";
+import styled from "styled-components";
+
+type Props = {
+  Header: any;
+  ExpandedSection: any;
+};
+
+const ExpandableSection: React.FC<Props> = ({
+  Header,
+  ExpandedSection,
+}) => {
+  const [isExpanded, setIsExpanded] = useState(false);
+
+  return (
+    <StyledExpandableSection isExpanded={isExpanded}>
+      <HeaderRow 
+        isExpanded={isExpanded}
+        onClick={() => setIsExpanded(!isExpanded)}
+      >
+        <i className="material-icons">arrow_drop_down</i> 
+        {Header}
+      </HeaderRow>
+      {
+        isExpanded && (
+          ExpandedSection
+        )
+      }
+    </StyledExpandableSection>
+  );
+};
+
+export default ExpandableSection;
+
+const HeaderRow = styled.div<{ isExpanded: boolean }>`
+  display: flex;
+  align-items: center;
+  height: 40px;
+  font-size: 13px;
+  width: 100%;
+  padding-left: 10px;
+  cursor: pointer;
+  :hover {
+    background: ${props => props.isExpanded && "#ffffff18"};
+  }
+
+  > i {
+    margin-right: 8px;
+    color: #ffffff66;
+    font-size: 20px;
+    cursor: pointer;
+    border-radius: 20px;
+    transform: ${props => props.isExpanded ? "" : "rotate(-90deg)"};
+  }
+`;
+
+const StyledExpandableSection = styled.div<{ isExpanded: boolean }>`
+  width: 100%;
+  height: ${props => props.isExpanded ? "" : "40px"};
+  max-height: 255px;
+  overflow: hidden;
+  border-radius: 5px;
+  background: #26292e;
+  border: 1px solid #494b4f;
+  :hover {
+    border: 1px solid #7a7b80;
+  }
+  animation: ${props => props.isExpanded ? "expandRevisions 0.3s" : ""};
+  animation-timing-function: ease-out;
+  @keyframes expandRevisions {
+    from {
+      max-height: 40px;
+    }
+    to {
+      max-height: 250px;
+    }
+  }
+`;

+ 18 - 2
dashboard/src/components/ProvisionerSettings.tsx

@@ -49,7 +49,7 @@ const ProvisionerForm: React.FC<Props> = ({
   credentialId,
   clusterId,
 }) => {
-  const { currentProject } = useContext(Context);
+  const { currentProject, currentCluster } = useContext(Context);
   const [createStatus, setCreateStatus] = useState("");
   const [clusterName, setClusterName] = useState("");
   const [awsRegion, setAwsRegion] = useState("us-east-1");
@@ -58,6 +58,7 @@ const ProvisionerForm: React.FC<Props> = ({
   const [minInstances, setMinInstances] = useState(1);
   const [maxInstances, setMaxInstances] = useState(10);
   const [cidrRange, setCidrRange] = useState("172.0.0.0/16");
+  const [isReadOnly, setIsReadOnly] = useState(false);
 
   const createCluster = async () => {
     var data: any = {
@@ -101,6 +102,13 @@ const ProvisionerForm: React.FC<Props> = ({
     }
   }
 
+  useEffect(() => {
+    setIsReadOnly(
+      currentCluster.status === "UPDATING" || 
+      currentCluster.status === "UPDATING_UNAVAILABLE"
+    );
+  }, []);
+
   return (
     <>
       <StyledForm>
@@ -108,6 +116,7 @@ const ProvisionerForm: React.FC<Props> = ({
         <InputRow
           width="350px"
           isRequired
+          disabled={isReadOnly}
           type="string"
           value={clusterName}
           setValue={(x: string) => setClusterName(x)}
@@ -117,6 +126,7 @@ const ProvisionerForm: React.FC<Props> = ({
         <SelectRow
           options={regionOptions}
           width="350px"
+          disabled={isReadOnly}
           value={awsRegion}
           scrollBuffer={true}
           dropdownMaxHeight="240px"
@@ -126,6 +136,7 @@ const ProvisionerForm: React.FC<Props> = ({
         <SelectRow
           options={machineTypeOptions}
           width="350px"
+          disabled={isReadOnly}
           value={machineType}
           scrollBuffer={true}
           dropdownMaxHeight="240px"
@@ -148,6 +159,7 @@ const ProvisionerForm: React.FC<Props> = ({
               <InputRow
                 width="350px"
                 type="number"
+                disabled={isReadOnly}
                 value={minInstances}
                 setValue={(x: number) => setMinInstances(x)}
                 label="Minimum number of application EC2 instances"
@@ -156,6 +168,7 @@ const ProvisionerForm: React.FC<Props> = ({
               <InputRow
                 width="350px"
                 type="number"
+                disabled={isReadOnly}
                 value={maxInstances}
                 setValue={(x: number) => setMaxInstances(x)}
                 label="Minimum number of application EC2 instances"
@@ -164,6 +177,7 @@ const ProvisionerForm: React.FC<Props> = ({
               <InputRow
                 width="350px"
                 type="string"
+                disabled={isReadOnly}
                 value={cidrRange}
                 setValue={(x: string) => setCidrRange(x)}
                 label="VPC CIDR range"
@@ -174,10 +188,12 @@ const ProvisionerForm: React.FC<Props> = ({
         }
       </StyledForm>
       <SaveButton
-        disabled={!clusterName && true}
+        disabled={(!clusterName && true) || isReadOnly}
         onClick={createCluster}
         clearPosition
         text="Provision"
+        statusPosition="right"
+        status={isReadOnly && "Provisioning is still in progress"}
       />
     </>
   );

+ 22 - 33
dashboard/src/components/Selector.tsx

@@ -10,6 +10,7 @@ export type SelectorPropsType = {
   setActiveValue: (x: string) => void;
   width: string;
   height?: string;
+  disabled?: boolean;
   dropdownLabel?: string;
   dropdownWidth?: string;
   dropdownMaxHeight?: string;
@@ -162,11 +163,14 @@ export default class Selector extends Component<SelectorPropsType, StateType> {
       <StyledSelector width={this.props.width}>
         <MainSelector
           ref={this.parentRef}
+          disabled={this.props.disabled}
           onClick={() => {
-            if (this.props.refreshOptions) {
-              this.props.refreshOptions();
+            if (!this.props.disabled) {
+              if (this.props.refreshOptions) {
+                this.props.refreshOptions();
+              }
+              this.setState({ expanded: !this.state.expanded });
             }
-            this.setState({ expanded: !this.state.expanded });
           }}
           expanded={this.state.expanded}
           width={this.props.width}
@@ -306,15 +310,6 @@ const Option = styled.div`
   }
 `;
 
-const CloseOverlay = styled.div`
-  position: fixed;
-  top: 0;
-  left: 0;
-  width: 100%;
-  height: 100%;
-  z-index: 999;
-`;
-
 const Dropdown = styled.div`
   background: #26282f;
   width: ${(props: { dropdownWidth: string; dropdownMaxHeight: string }) =>
@@ -333,40 +328,34 @@ const StyledSelector = styled.div<{ width: string }>`
   width: ${(props) => props.width};
 `;
 
-const MainSelector = styled.div`
-  width: ${(props: { expanded: boolean; width: string; height?: string }) =>
-    props.width};
-  height: ${(props: { expanded: boolean; width: string; height?: string }) =>
-    props.height ? props.height : "35px"};
+const MainSelector = styled.div<{ 
+  disabled?: boolean;
+  expanded: boolean;
+  width: string;
+  height?: string;
+}>`
+  width: ${props => props.width};
+  height: ${props => props.height ? props.height : "35px"};
   border: 1px solid #ffffff55;
   font-size: 13px;
   padding: 5px 10px;
   padding-left: 15px;
   border-radius: 3px;
   display: flex;
+  color: ${props => props.disabled ? "#ffffff44" : "#ffffff"};
   justify-content: space-between;
   align-items: center;
-  cursor: pointer;
-  background: ${(props: {
-    expanded: boolean;
-    width: string;
-    height?: string;
-  }) => (props.expanded ? "#ffffff33" : "#ffffff11")};
+  cursor: ${props => props.disabled ? "not-allowed" : "pointer"};
+  background: ${props => props.expanded ? "#ffffff33" : "#ffffff11"};
   :hover {
-    background: ${(props: {
-      expanded: boolean;
-      width: string;
-      height?: string;
-    }) => (props.expanded ? "#ffffff33" : "#ffffff22")};
+    background: ${props => props.expanded ? "#ffffff33" : (
+      props.disabled ? "#ffffff11" : "#ffffff22"
+    )};
   }
 
   > i {
     font-size: 20px;
-    transform: ${(props: {
-      expanded: boolean;
-      width: string;
-      height?: string;
-    }) => (props.expanded ? "rotate(180deg)" : "")};
+    transform: ${props => props.expanded ? "rotate(180deg)" : ""};
   }
 `;
 

+ 2 - 0
dashboard/src/components/form-components/SelectRow.tsx

@@ -13,6 +13,7 @@ type PropsType = {
   dropdownMaxHeight?: string;
   scrollBuffer?: boolean;
   doc?: string;
+  disabled?: boolean;
   selectorProps?: Partial<SelectorPropsType>;
 };
 
@@ -32,6 +33,7 @@ export default class SelectRow extends Component<PropsType, StateType> {
         </Wrapper>
         <SelectWrapper>
           <Selector
+            disabled={this.props.disabled}
             scrollBuffer={this.props.scrollBuffer}
             activeValue={this.props.value}
             setActiveValue={this.props.setActiveValue}

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

@@ -207,12 +207,14 @@ export const Dashboard: React.FunctionComponent = () => {
         context.currentProject.capi_provisioner_enabled && (
           <>
             <ProvisionerStatus />
+            {/*
             <RevisionHeader isCurrent={true} showRevisions={false}>
               <RevisionPreview>
                 Current version - <Revision>No. 4</Revision>
                 <i className="material-icons">arrow_drop_down</i>
               </RevisionPreview>
             </RevisionHeader>
+            */}
           </>
         )
       }

+ 26 - 21
dashboard/src/main/home/cluster-dashboard/dashboard/ProvisionerStatus.tsx

@@ -5,6 +5,7 @@ import api from "shared/api";
 import loading from "assets/loading.gif";
 
 import { Context } from "shared/Context";
+import ExpandableSection from "components/ExpandableSection";
 
 type Props = {};
 
@@ -14,28 +15,40 @@ const ProvisionerStatus: React.FC<Props> = ({}) => {
 
   return (
     <StyledProvisionerStatus>
-      <Flex>
-        <Icon src="https://img.stackshare.io/service/7991/amazon-eks.png" />
-        Elastic Kubernetes Service
-        <Status>
-          <Img src={loading} /> Updating
-        </Status>
-      </Flex>
+      <ExpandableSection
+        Header={(
+          <>
+            <Icon src="https://img.stackshare.io/service/7991/amazon-eks.png" />
+            Elastic Kubernetes Service
+            <Status>
+              <Img src={loading} /> Updating
+            </Status>
+          </>
+        )}
+        ExpandedSection={(
+          <DummyLogs>[Logs unimplemented]</DummyLogs>
+        )}
+      />
     </StyledProvisionerStatus>
   );
 };
 
 export default ProvisionerStatus;
 
-const Icon = styled.img`
-  height: 20px;
-  margin-right: 10px;
-`;
-
-const Flex = styled.div`
+const DummyLogs = styled.div`
+  height: 150px;
+  width: 100%;
   display: flex;
   align-items: center;
+  justify-content: center;
   font-size: 13px;
+  background: #101420;
+  font-family: monospace;
+`;
+
+const Icon = styled.img`
+  height: 20px;
+  margin-right: 10px;
 `;
 
 const Img = styled.img`
@@ -51,13 +64,5 @@ const Status = styled.div`
 `;
 
 const StyledProvisionerStatus = styled.div`
-  border-radius: 5px;
-  background: #26292e;
-  border: 1px solid #494b4f;
-  height: 40px;
   margin-bottom: 22px;
-  font-size: 14px;
-  padding-left: 12px;
-  display: flex;
-  align-items: center;
 `;

+ 4 - 9
dashboard/src/main/home/cluster-dashboard/expanded-chart/RevisionSection.tsx

@@ -323,11 +323,11 @@ class RevisionSection extends Component<PropsType, StateType> {
           }}
         >
           <RevisionPreview>
+            <i className="material-icons">arrow_drop_down</i>
             {isCurrent
               ? `Current revision`
               : `Previewing revision (not deployed)`}{" "}
             - <Revision>No. {this.props.chart.version}</Revision>
-            <i className="material-icons">arrow_drop_down</i>
           </RevisionPreview>
           {this.props.shouldUpdate && isCurrent && (
             <div>
@@ -470,24 +470,19 @@ const RevisionHeader = styled.div`
   height: 40px;
   font-size: 13px;
   width: 100%;
-  padding-left: 15px;
+  padding-left: 10px;
   cursor: pointer;
   :hover {
     background: ${props => props.showRevisions && "#ffffff18"};
-    > div > i {
-      background: ${props => props.showRevisions && "#ffffff22"};
-    }
   }
 
   > div > i {
-    margin-left: 12px;
+    margin-right: 8px;
     font-size: 20px;
     cursor: pointer;
     border-radius: 20px;
-    background: ${(props: { showRevisions: boolean; isCurrent: boolean }) =>
-      props.showRevisions ? "#ffffff18" : ""};
     transform: ${(props: { showRevisions: boolean; isCurrent: boolean }) =>
-      props.showRevisions ? "rotate(180deg)" : ""};
+      props.showRevisions ? "" : "rotate(-90deg)"};
   }
 `;