ソースを参照

display failure reason

Justin Rhee 3 年 前
コミット
736c2ed053

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

@@ -12,6 +12,7 @@ import Heading from "components/form-components/Heading";
 import Helper from "./form-components/Helper";
 import Helper from "./form-components/Helper";
 import InputRow from "./form-components/InputRow";
 import InputRow from "./form-components/InputRow";
 import SaveButton from "./SaveButton";
 import SaveButton from "./SaveButton";
+import Loading from "./Loading";
 
 
 type Props = {
 type Props = {
   goBack: () => void;
   goBack: () => void;
@@ -41,7 +42,6 @@ const CredentialsForm: React.FC<Props> = ({
   const [createStatus, setCreateStatus] = useState("");
   const [createStatus, setCreateStatus] = useState("");
 
 
   useEffect(() => {
   useEffect(() => {
-    console.log("great creds")
     api
     api
       .getAWSIntegration(
       .getAWSIntegration(
         "<token>",
         "<token>",
@@ -51,9 +51,7 @@ const CredentialsForm: React.FC<Props> = ({
         }
         }
       )
       )
       .then(({ data }) => {
       .then(({ data }) => {
-        console.log("creds data", data);
         if (!Array.isArray(data)) {
         if (!Array.isArray(data)) {
-          console.log("no creds");
           setAWSCredentials([]);
           setAWSCredentials([]);
         } else {
         } else {
           setAWSCredentials(data);
           setAWSCredentials(data);
@@ -192,7 +190,7 @@ const CredentialsForm: React.FC<Props> = ({
       </Helper>
       </Helper>
       {
       {
         isLoading ? (
         isLoading ? (
-          <>Loading . . .</>
+          <Loading height="150px" />
         ) : (
         ) : (
           renderContent()
           renderContent()
         )
         )

+ 0 - 2
dashboard/src/components/TitleSection.tsx

@@ -69,10 +69,8 @@ const BackButton = styled.div`
 `;
 `;
 
 
 const StyledTitleSection = styled.div`
 const StyledTitleSection = styled.div`
-  margin-bottom: 15px;
   display: flex;
   display: flex;
   align-items: center;
   align-items: center;
-  height: 35px;
 `;
 `;
 
 
 const Icon = styled.img<{ width: string }>`
 const Icon = styled.img<{ width: string }>`

+ 20 - 6
dashboard/src/components/porter/LoadingBar.tsx

@@ -5,16 +5,28 @@ type Props = {
   percent?: number;
   percent?: number;
   completed?: number;
   completed?: number;
   total?: number;
   total?: number;
+  color?: string;
 };
 };
 
 
 const LoadingBar: React.FC<Props> = ({
 const LoadingBar: React.FC<Props> = ({
   percent,
   percent,
   completed,
   completed,
   total,
   total,
+  color,
 }) => {
 }) => {
+  const getColor = () => {
+    switch (color) {
+      case "failed":
+        return "#cc3d42";
+      default:
+        return color;
+    }
+  };
+  
   return (
   return (
     <StyledLoadingBar>
     <StyledLoadingBar>
-      <LoadingFill 
+      <LoadingFill
+        color={getColor()}
         percent={(percent || ((100.0 * completed) / total)) + "%"}
         percent={(percent || ((100.0 * completed) / total)) + "%"}
       />
       />
     </StyledLoadingBar>
     </StyledLoadingBar>
@@ -33,17 +45,19 @@ const StyledLoadingBar = styled.div`
 
 
 const movingGradient = keyframes`
 const movingGradient = keyframes`
   0% {
   0% {
-      background-position: left bottom;
+    background-position: left bottom;
   }
   }
-
   100% {
   100% {
-      background-position: right bottom;
+    background-position: right bottom;
   }
   }
 `;
 `;
 
 
-const LoadingFill = styled.div<{ percent: string }>`
+const LoadingFill = styled.div<{ 
+  percent: string;
+  color?: string;
+}>`
   width: ${props => props.percent};
   width: ${props => props.percent};
-  background: linear-gradient(to right, #8ce1ff, #616FEE);
+  background: ${props => props.color || "linear-gradient(to right, #8ce1ff, #616FEE)"};
   height: 100%;
   height: 100%;
   background-size: 250% 100%;
   background-size: 250% 100%;
   animation: ${movingGradient} 2s infinite;
   animation: ${movingGradient} 2s infinite;

+ 1 - 1
dashboard/src/main/home/cluster-dashboard/ClusterDashboard.tsx

@@ -240,7 +240,7 @@ class ClusterDashboard extends Component<PropsType, StateType> {
 
 
     return (
     return (
       <>
       <>
-        <ControlRow style={{ marginTop: "35px" }}>
+        <ControlRow>
           <FilterWrapper>
           <FilterWrapper>
             <LastRunStatusSelector
             <LastRunStatusSelector
               lastRunStatus={this.state.lastRunStatus}
               lastRunStatus={this.state.lastRunStatus}

+ 14 - 19
dashboard/src/main/home/cluster-dashboard/DashboardHeader.tsx

@@ -4,6 +4,7 @@ import styled from "styled-components";
 import { Context } from "shared/Context";
 import { Context } from "shared/Context";
 
 
 import TitleSection from "components/TitleSection";
 import TitleSection from "components/TitleSection";
+import Spacer from "components/porter/Spacer";
 
 
 type PropsType = {
 type PropsType = {
   image?: any;
   image?: any;
@@ -28,20 +29,20 @@ export default class DashboardHeader extends Component<PropsType, StateType> {
           {this.props.title}
           {this.props.title}
         </TitleSection>
         </TitleSection>
 
 
-        <Br />
-
         {this.props.description && (
         {this.props.description && (
-          <InfoSection>
-            <TopRow>
-              <InfoLabel>
-                <i className="material-icons">info</i> Info
-              </InfoLabel>
-            </TopRow>
-            <Description>{this.props.description}</Description>
-          </InfoSection>
+          <>
+            <Spacer height="35px" />
+            <InfoSection>
+              <TopRow>
+                <InfoLabel>
+                  <i className="material-icons">info</i> Info
+                </InfoLabel>
+              </TopRow>
+              <Description>{this.props.description}</Description>
+            </InfoSection>
+          </>
         )}
         )}
-
-        {!this.props.disableLineBreak && <LineBreak />}
+        <Spacer height="35px" />
       </>
       </>
     );
     );
   }
   }
@@ -49,11 +50,6 @@ export default class DashboardHeader extends Component<PropsType, StateType> {
 
 
 DashboardHeader.contextType = Context;
 DashboardHeader.contextType = Context;
 
 
-const Br = styled.div`
-  width: 100%;
-  height: 1px;
-`;
-
 const LineBreak = styled.div`
 const LineBreak = styled.div`
   width: calc(100% - 0px);
   width: calc(100% - 0px);
   height: 1px;
   height: 1px;
@@ -89,10 +85,9 @@ const InfoLabel = styled.div`
 `;
 `;
 
 
 const InfoSection = styled.div`
 const InfoSection = styled.div`
-  margin-top: 15px;
+
   font-family: "Work Sans", sans-serif;
   font-family: "Work Sans", sans-serif;
   margin-left: 0px;
   margin-left: 0px;
-  margin-bottom: 35px;
 `;
 `;
 
 
 const ClusterLabel = styled.div`
 const ClusterLabel = styled.div`

+ 57 - 49
dashboard/src/main/home/cluster-dashboard/dashboard/ClusterRevisionSelector.tsx

@@ -16,17 +16,20 @@ import {
   EnumKubernetesKind, 
   EnumKubernetesKind, 
   EnumCloudProvider 
   EnumCloudProvider 
 } from "@porter-dev/api-contracts";
 } from "@porter-dev/api-contracts";
+import Spacer from "components/porter/Spacer";
 
 
 type Props = {
 type Props = {
   selectedClusterVersion: any;
   selectedClusterVersion: any;
   setSelectedClusterVersion: any;
   setSelectedClusterVersion: any;
   setShowProvisionerStatus: any;
   setShowProvisionerStatus: any;
+  setProvisionFailureReason: any;
 };
 };
 
 
 const ClusterRevisionSelector: React.FC<Props> = ({
 const ClusterRevisionSelector: React.FC<Props> = ({
   selectedClusterVersion,
   selectedClusterVersion,
   setSelectedClusterVersion,
   setSelectedClusterVersion,
   setShowProvisionerStatus,
   setShowProvisionerStatus,
+  setProvisionFailureReason,
 }) => {
 }) => {
   const { currentProject, currentCluster } = useContext(Context);
   const { currentProject, currentCluster } = useContext(Context);
   const [versions, setVersions] = useState<any[]>(null);
   const [versions, setVersions] = useState<any[]>(null);
@@ -37,6 +40,7 @@ const ClusterRevisionSelector: React.FC<Props> = ({
 
 
   const processVersions = (data: any) => {
   const processVersions = (data: any) => {
     setFailedContractId("");
     setFailedContractId("");
+    setProvisionFailureReason("");
     data.sort((a: any, b: any) => {
     data.sort((a: any, b: any) => {
       return Date.parse(a.CreatedAt) > Date.parse(b.CreatedAt) ? -1 : 1;
       return Date.parse(a.CreatedAt) > Date.parse(b.CreatedAt) ? -1 : 1;
     });
     });
@@ -47,6 +51,7 @@ const ClusterRevisionSelector: React.FC<Props> = ({
 
 
       if (data[0].condition !== "") {
       if (data[0].condition !== "") {
         setFailedContractId(data[0].id);
         setFailedContractId(data[0].id);
+        setProvisionFailureReason(data[0].condition);
       }
       }
     }
     }
 
 
@@ -206,59 +211,62 @@ const deleteContract = () => {
         hideSelector ? (
         hideSelector ? (
           <></>
           <></>
         ) : (
         ) : (
-          <StyledClusterRevisionSelector>
-            <ExpandableSection
-              isInitiallyExpanded={false}
-              color={selectedId <= 0 ? "#ffffff66" : "#f5cb42"}
-              Header={(
-                <>
-                  <Label isCurrent={selectedId <= 0}>
-                    {
-                      selectedId === 0 ? (
-                        "Current version -"
-                      ) : (
-                        selectedId === -1 ? (
-                          failedContractId ? (
-                            ""
+          <>
+            <StyledClusterRevisionSelector>
+              <ExpandableSection
+                isInitiallyExpanded={false}
+                color={selectedId <= 0 ? "#ffffff66" : "#f5cb42"}
+                Header={(
+                  <>
+                    <Label isCurrent={selectedId <= 0}>
+                      {
+                        selectedId === 0 ? (
+                          "Current version -"
+                        ) : (
+                          selectedId === -1 ? (
+                            failedContractId ? (
+                              ""
+                            ) : (
+                              "In progress -"
+                            )
                           ) : (
                           ) : (
-                            "In progress -"
+                            "Previewing version (not deployed) -"
                           )
                           )
+                        )
+                      }
+                    </Label>
+                    {
+                      selectedId === -1 ? (
+                        failedContractId ? (
+                          <><WarningIcon src={warning} /> Last update failed</>
                         ) : (
                         ) : (
-                          "Previewing version (not deployed) -"
+                          <><Img src={loading} /> Updating</>
                         )
                         )
-                      )
-                    }
-                  </Label>
-                  {
-                    selectedId === -1 ? (
-                      failedContractId ? (
-                        <><WarningIcon src={warning} /> Last update failed</>
                       ) : (
                       ) : (
-                        <><Img src={loading} /> Updating</>
+                        `No. ${versions?.length - selectedId}`
                       )
                       )
-                    ) : (
-                      `No. ${versions?.length - selectedId}`
-                    )
-                  }
-                </>
-              )}
-              ExpandedSection={(
-                <TableWrapper>
-                  <RevisionsTable>
-                    <tbody>
-                      <Tr disableHover={true}>
-                        <Th>Version no.</Th>
-                        <Th>Created</Th>
-                        {/* <Th>Rollback</Th> */}
-                      </Tr>
-                      {(pendingContract || failedContractId) && renderActiveAttempt()}
-                      {renderVersionList()}
-                    </tbody>
-                  </RevisionsTable>
-                </TableWrapper>
-              )}
-            />
-          </StyledClusterRevisionSelector>
+                    }
+                  </>
+                )}
+                ExpandedSection={(
+                  <TableWrapper>
+                    <RevisionsTable>
+                      <tbody>
+                        <Tr disableHover={true}>
+                          <Th>Version no.</Th>
+                          <Th>Created</Th>
+                          {/* <Th>Rollback</Th> */}
+                        </Tr>
+                        {(pendingContract || failedContractId) && renderActiveAttempt()}
+                        {renderVersionList()}
+                      </tbody>
+                    </RevisionsTable>
+                  </TableWrapper>
+                )}
+              />
+            </StyledClusterRevisionSelector>
+            <Spacer y={1} />
+          </>
         )
         )
       }
       }
     </>
     </>
@@ -286,9 +294,9 @@ const DeleteButton = styled.div`
 `;
 `;
 
 
 const WarningIcon = styled.img`
 const WarningIcon = styled.img`
-  height: 20px;
+  height: 18px;
   margin-right: 10px;
   margin-right: 10px;
-  margin-left: -4px;
+  margin-left: -8px;
 `;
 `;
 
 
 const Failed = styled.div`
 const Failed = styled.div`

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

@@ -37,6 +37,7 @@ export const Dashboard: React.FunctionComponent = () => {
   const location = useLocation();
   const location = useLocation();
   const [selectedClusterVersion, setSelectedClusterVersion] = useState(null);
   const [selectedClusterVersion, setSelectedClusterVersion] = useState(null);
   const [showProvisionerStatus, setShowProvisionerStatus] = useState(false);
   const [showProvisionerStatus, setShowProvisionerStatus] = useState(false);
+  const [provisionFailureReason, setProvisionFailureReason] = useState("");
   const [ingressIp, setIngressIp] = useState(null);
   const [ingressIp, setIngressIp] = useState(null);
   const [ingressError, setIngressError] = useState(null);
   const [ingressError, setIngressError] = useState(null);
 
 
@@ -104,6 +105,7 @@ export const Dashboard: React.FunctionComponent = () => {
 
 
   // Need to reset tab to reset views that don't auto-update on cluster switch (esp namespaces + settings)
   // Need to reset tab to reset views that don't auto-update on cluster switch (esp namespaces + settings)
   useEffect(() => {
   useEffect(() => {
+    setShowProvisionerStatus(false);
     if (context.currentProject.capi_provisioner_enabled) {
     if (context.currentProject.capi_provisioner_enabled) {
       setCurrentTab("configuration");
       setCurrentTab("configuration");
     } else {
     } else {
@@ -187,6 +189,7 @@ export const Dashboard: React.FunctionComponent = () => {
             selectedClusterVersion={selectedClusterVersion}
             selectedClusterVersion={selectedClusterVersion}
             setSelectedClusterVersion={setSelectedClusterVersion}
             setSelectedClusterVersion={setSelectedClusterVersion}
             setShowProvisionerStatus={setShowProvisionerStatus}
             setShowProvisionerStatus={setShowProvisionerStatus}
+            setProvisionFailureReason={setProvisionFailureReason}
           />
           />
           {(
           {(
             showProvisionerStatus && (
             showProvisionerStatus && (
@@ -195,8 +198,10 @@ export const Dashboard: React.FunctionComponent = () => {
             )
             )
           ) && (
           ) && (
             <>
             <>
+              <ProvisionerStatus
+                provisionFailureReason={provisionFailureReason}
+              />
               <Spacer y={1} />
               <Spacer y={1} />
-              <ProvisionerStatus />
             </>
             </>
           )}
           )}
           <TabSelector
           <TabSelector

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

@@ -12,9 +12,13 @@ import Spacer from "components/porter/Spacer";
 import Helper from "components/form-components/Helper";
 import Helper from "components/form-components/Helper";
 import Text from "components/porter/Text";
 import Text from "components/porter/Text";
 
 
-type Props = {};
+type Props = {
+  provisionFailureReason: string;
+};
 
 
-const ProvisionerStatus: React.FC<Props> = ({}) => {
+const ProvisionerStatus: React.FC<Props> = ({
+  provisionFailureReason,
+}) => {
   const { currentProject, currentCluster } = useContext(Context);
   const { currentProject, currentCluster } = useContext(Context);
   const [progress, setProgress] = useState(1);
   const [progress, setProgress] = useState(1);
 
 
@@ -54,15 +58,19 @@ const ProvisionerStatus: React.FC<Props> = ({}) => {
           AWS provisioning status
           AWS provisioning status
         </Flex>
         </Flex>
         <Spacer height="18px" />
         <Spacer height="18px" />
-        <LoadingBar completed={progress} total={4} />
+        <LoadingBar
+          color={provisionFailureReason && "failed"}
+          completed={progress} 
+          total={5} 
+        />
         <Spacer height="18px" />
         <Spacer height="18px" />
         <Text color="#aaaabb">
         <Text color="#aaaabb">
           Setup can take up to 20 minutes. You can close this window and come back later. 
           Setup can take up to 20 minutes. You can close this window and come back later. 
         </Text>
         </Text>
       </HeaderSection>
       </HeaderSection>
       {
       {
-        false && (
-          <DummyLogs>[Logs unimplemented]</DummyLogs>
+        provisionFailureReason && (
+          <DummyLogs>Error: {provisionFailureReason}</DummyLogs>
         )
         )
       }
       }
     </StyledProvisionerStatus>
     </StyledProvisionerStatus>
@@ -82,11 +90,9 @@ const HeaderSection = styled.div`
 `;
 `;
 
 
 const DummyLogs = styled.div`
 const DummyLogs = styled.div`
-  height: 150px;
+  padding: 15px;
   width: 100%;
   width: 100%;
   display: flex;
   display: flex;
-  align-items: center;
-  justify-content: center;
   font-size: 13px;
   font-size: 13px;
   background: #101420;
   background: #101420;
   font-family: monospace;
   font-family: monospace;
@@ -111,7 +117,6 @@ const Status = styled.div`
 `;
 `;
 
 
 const StyledProvisionerStatus = styled.div`
 const StyledProvisionerStatus = styled.div`
-  margin-bottom: 22px;
   border-radius: 5px;
   border-radius: 5px;
   background: #26292e;
   background: #26292e;
   border: 1px solid #494b4f;
   border: 1px solid #494b4f;

+ 1 - 1
dashboard/src/main/home/cluster-dashboard/preview-environments/environments/EnvironmentsList.tsx

@@ -136,7 +136,7 @@ const ControlRow = styled.div`
   margin-left: auto;
   margin-left: auto;
   justify-content: space-between;
   justify-content: space-between;
   align-items: center;
   align-items: center;
-  margin: 35px 0 30px;
+  margin-bottom: 30px;
   padding-left: 0px;
   padding-left: 0px;
 `;
 `;
 
 

+ 2 - 1
dashboard/src/main/home/dashboard/Dashboard.tsx

@@ -19,6 +19,7 @@ import Banner from "components/Banner";
 
 
 import { pushFiltered, pushQueryParams } from "shared/routing";
 import { pushFiltered, pushQueryParams } from "shared/routing";
 import { withAuth, WithAuthProps } from "shared/auth/AuthorizationHoc";
 import { withAuth, WithAuthProps } from "shared/auth/AuthorizationHoc";
+import Spacer from "components/porter/Spacer";
 
 
 type PropsType = RouteComponentProps &
 type PropsType = RouteComponentProps &
   WithAuthProps & {
   WithAuthProps & {
@@ -179,7 +180,7 @@ class Dashboard extends Component<PropsType, StateType> {
                     </i>
                     </i>
                   )}
                   )}
                 </TitleSection>
                 </TitleSection>
-                <Br />
+                <Spacer height="15px" />
 
 
                 <InfoSection>
                 <InfoSection>
                   <TopRow>
                   <TopRow>

+ 1 - 1
dashboard/src/main/home/infrastructure/InfrastructureList.tsx

@@ -178,7 +178,7 @@ const InfrastructureList = () => {
         <DashboardIcon>
         <DashboardIcon>
           <i className="material-icons">build_circle</i>
           <i className="material-icons">build_circle</i>
         </DashboardIcon>
         </DashboardIcon>
-        Managed Infrastructure
+        Managed infrastructure (legacy)
       </StyledTitleSection>
       </StyledTitleSection>
       <InfoSection>
       <InfoSection>
         <Description>
         <Description>

+ 0 - 1
dashboard/src/main/home/integrations/IntegrationList.tsx

@@ -267,7 +267,6 @@ const Placeholder = styled.div`
 `;
 `;
 
 
 const StyledIntegrationList = styled.div`
 const StyledIntegrationList = styled.div`
-  margin-top: 30px;
   margin-bottom: 80px;
   margin-bottom: 80px;
 `;
 `;
 
 

+ 2 - 1
dashboard/src/main/home/integrations/Integrations.tsx

@@ -10,6 +10,7 @@ import IntegrationCategories from "./IntegrationCategories";
 import IntegrationList from "./IntegrationList";
 import IntegrationList from "./IntegrationList";
 import TitleSection from "components/TitleSection";
 import TitleSection from "components/TitleSection";
 import { Context } from "shared/Context";
 import { Context } from "shared/Context";
+import Spacer from "components/porter/Spacer";
 
 
 type PropsType = RouteComponentProps;
 type PropsType = RouteComponentProps;
 
 
@@ -75,7 +76,7 @@ const Integrations: React.FC<PropsType> = (props) => {
         <Route>
         <Route>
           <div>
           <div>
             <TitleSection>Integrations</TitleSection>
             <TitleSection>Integrations</TitleSection>
-
+            <Spacer y={1} />
             <IntegrationList
             <IntegrationList
               currentCategory={""}
               currentCategory={""}
               integrations={IntegrationCategoryStrings}
               integrations={IntegrationCategoryStrings}

+ 2 - 0
dashboard/src/main/home/launch/Launch.tsx

@@ -18,6 +18,7 @@ import { RouteComponentProps, withRouter } from "react-router";
 import { getQueryParam, getQueryParams } from "shared/routing";
 import { getQueryParam, getQueryParams } from "shared/routing";
 import TemplateList from "./TemplateList";
 import TemplateList from "./TemplateList";
 import { capitalize } from "lodash";
 import { capitalize } from "lodash";
+import Spacer from "components/porter/Spacer";
 
 
 const initialTabOptions = [
 const initialTabOptions = [
   { label: "New application", value: "porter" },
   { label: "New application", value: "porter" },
@@ -421,6 +422,7 @@ class Templates extends Component<PropsType, StateType> {
               <i className="material-icons">help_outline</i>
               <i className="material-icons">help_outline</i>
             </a>
             </a>
           </TitleSection>
           </TitleSection>
+          <Spacer height="20px" />
           {this.renderContents()}
           {this.renderContents()}
         </TemplatesWrapper>
         </TemplatesWrapper>
       );
       );

+ 2 - 0
dashboard/src/main/home/project-settings/ProjectSettings.tsx

@@ -14,6 +14,7 @@ import { getQueryParam } from "shared/routing";
 import BillingPage from "./BillingPage";
 import BillingPage from "./BillingPage";
 import APITokensSection from "./APITokensSection";
 import APITokensSection from "./APITokensSection";
 import _ from "lodash";
 import _ from "lodash";
+import Spacer from "components/porter/Spacer";
 
 
 type PropsType = RouteComponentProps & WithAuthProps & {};
 type PropsType = RouteComponentProps & WithAuthProps & {};
 
 
@@ -185,6 +186,7 @@ class ProjectSettings extends Component<PropsType, StateType> {
     return (
     return (
       <StyledProjectSettings>
       <StyledProjectSettings>
         <TitleSection>Project settings</TitleSection>
         <TitleSection>Project settings</TitleSection>
+        <Spacer height="20px" />
         <TabRegion
         <TabRegion
           currentTab={this.state.currentTab}
           currentTab={this.state.currentTab}
           setCurrentTab={(x: string) => this.setState({ currentTab: x })}
           setCurrentTab={(x: string) => this.setState({ currentTab: x })}