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

show project page on provision error when reloading

jusrhee 5 лет назад
Родитель
Сommit
695e12b4a4

+ 1 - 1
dashboard/src/components/SaveButton.tsx

@@ -86,7 +86,7 @@ const StatusWrapper = styled.div`
 
   > i {
     font-size: 18px;
-    margin-right: 5px;
+    margin-right: 10px;
     color: ${(props: { successful: boolean }) => props.successful ? '#4797ff' : '#fcba03'};
   }
 

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

@@ -13,6 +13,7 @@ import Loading from '../../components/Loading';
 import Templates from './templates/Templates';
 import Integrations from "./integrations/Integrations";
 import UpdateProjectModal from './modals/UpdateProjectModal';
+import UpdateClusterModal from './modals/UpdateClusterModal';
 import ClusterInstructionsModal from './modals/ClusterInstructionsModal';
 import IntegrationsModal from './modals/IntegrationsModal';
 import IntegrationsInstructionsModal from './modals/IntegrationsInstructionsModal';
@@ -67,7 +68,7 @@ export default class Home extends Component<PropsType, StateType> {
                   viewData.push({
                     infra_id: el.id,
                     kind: el.kind,
-                  })
+                  });
                 }
               });
 

+ 188 - 0
dashboard/src/main/home/modals/UpdateClusterModal.tsx

@@ -0,0 +1,188 @@
+import React, { Component } from 'react';
+import styled from 'styled-components';
+import close from '../../../assets/close.png';
+import gradient from '../../../assets/gradient.jpg';
+
+import api from '../../../shared/api';
+import { Context } from '../../../shared/Context';
+
+import SaveButton from '../../../components/SaveButton';
+import InputRow from '../../../components/values-form/InputRow';
+import ConfirmOverlay from '../../../components/ConfirmOverlay';
+
+type PropsType = {
+};
+
+type StateType = {
+  clusterName: string,
+  status: string | null,
+  showDeleteOverlay: boolean
+};
+
+export default class UpdateClusterModal extends Component<PropsType, StateType> {
+  state = {
+    clusterName: this.context.currentCluster.name,
+    status: null as string | null,
+    showDeleteOverlay: false,
+  };
+  
+  handleDelete = () => {
+    let { currentProject, currentCluster } = this.context;
+    this.setState({ status: 'loading' });
+    api.deleteCluster('<token>', {}, { 
+      project_id: currentProject.id,
+      cluster_id: currentCluster.id,
+    }, (err: any, res: any) => {
+      if (err) {
+        this.setState({ status: 'error' });
+        // console.log(err)
+      } else {
+        alert('nice');
+        this.setState({ status: 'successful', showDeleteOverlay: false });
+      }
+    });
+  }
+
+  render() {
+    return (
+      <StyledUpdateProjectModal>
+        <CloseButton onClick={() => {
+          this.context.setCurrentModal(null, null);
+        }}>
+          <CloseButtonImg src={close} />
+        </CloseButton>
+
+        <ModalTitle>Cluster Settings</ModalTitle>
+        <Subtitle>
+          Cluster name
+        </Subtitle>
+
+        <InputWrapper>
+          <ProjectIcon>
+            <ProjectImage src={gradient} />
+            <Letter>{this.state.clusterName ? this.state.clusterName[0].toUpperCase() : '-'}</Letter>
+          </ProjectIcon>
+          <InputRow
+            disabled={true}
+            type='string'
+            value={this.state.clusterName}
+            setValue={(x: string) => this.setState({ clusterName: x })}
+            placeholder='ex: perspective-vortex'
+            width='470px'
+          />
+        </InputWrapper>
+
+        <SaveButton
+          text='Delete Cluster'
+          color='#b91133'
+          onClick={() => this.setState({ showDeleteOverlay: true })}
+          status={this.state.status}
+        />
+
+        <ConfirmOverlay
+          show={this.state.showDeleteOverlay}
+          message={`Are you sure you want to delete ${this.state.clusterName}?`}
+          onYes={this.handleDelete}
+          onNo={() => this.setState({ showDeleteOverlay: false })}
+        />
+      </StyledUpdateProjectModal>
+      );
+  }
+}
+
+UpdateClusterModal.contextType = Context;
+
+const Letter = styled.div`
+  height: 100%;
+  width: 100%;
+  position: absolute;
+  background: #00000028;
+  top: 0;
+  left: 0;
+  display: flex;
+  color: white;
+  align-items: center;
+  justify-content: center;
+`;
+
+const ProjectImage = styled.img`
+  width: 100%;
+  height: 100%;
+`;
+
+const ProjectIcon = styled.div`
+  width: 25px;
+  min-width: 25px;
+  height: 25px;
+  border-radius: 3px;
+  overflow: hidden;
+  position: relative;
+  margin-right: 10px;
+  font-weight: 400;
+  margin-top: 14px;
+`;
+
+const InputWrapper = styled.div`
+  display: flex;
+  align-items: center;
+`;
+
+const Subtitle = styled.div`
+  margin-top: 23px;
+  font-family: 'Work Sans', sans-serif;
+  font-size: 13px;
+  color: #aaaabb;
+  overflow: hidden;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+  margin-bottom: -10px;
+`;
+
+const ModalTitle = styled.div`
+  margin: 0px 0px 13px;
+  display: flex;
+  flex: 1;
+  font-family: 'Assistant';
+  font-size: 18px;
+  color: #ffffff;
+  user-select: none;
+  font-weight: 700;
+  align-items: center;
+  position: relative;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+`;
+
+const CloseButton = styled.div`
+  position: absolute;
+  display: block;
+  width: 40px;
+  height: 40px;
+  padding: 13px 0 12px 0;
+  z-index: 1;
+  text-align: center;
+  border-radius: 50%;
+  right: 15px;
+  top: 12px;
+  cursor: pointer;
+  :hover {
+    background-color: #ffffff11;
+  }
+`;
+
+const CloseButtonImg = styled.img`
+  width: 14px;
+  margin: 0 auto;
+`;
+
+const StyledUpdateProjectModal= styled.div`
+  width: 100%;
+  position: absolute;
+  left: 0;
+  top: 0;
+  height: 100%;
+  padding: 25px 32px;
+  overflow: hidden;
+  border-radius: 6px;
+  background: #202227;
+`;

+ 13 - 3
dashboard/src/main/home/new-project/NewProject.tsx

@@ -211,7 +211,12 @@ export default class NewProject extends Component<PropsType, StateType> {
         ecr_name: `${proj.name}-registry`
       }, {id: proj.id}, (err: any, ecr:any) => {
         if (err) {
-          console.log(err)
+          this.setState({ 
+            status: 'Please provide valid AWS credentials.',
+            awsRegion: '',
+            awsAccessId: '',
+            awsSecretKey: '', 
+          });
           return;
         }
 
@@ -232,7 +237,7 @@ export default class NewProject extends Component<PropsType, StateType> {
       aws_cluster_id: clusterName,
     }, { id: proj.id }, (err: any, res: any) => {
       if (err) {
-        console.log(err)
+        console.log(err);
         return;
       }
 
@@ -241,7 +246,12 @@ export default class NewProject extends Component<PropsType, StateType> {
         eks_name: clusterName,
       }, { id: proj.id}, (err: any, eks: any) => {
         if (err) {
-          console.log(err)
+          this.setState({ 
+            status: 'Please provide valid AWS credentials.',
+            awsRegion: '',
+            awsAccessId: '',
+            awsSecretKey: '', 
+          });
           return;
         }
 

+ 4 - 5
dashboard/src/main/home/new-project/Provisioner.tsx

@@ -37,9 +37,9 @@ export default class Provisioner extends Component<PropsType, StateType> {
 
   isJSON = (str: string) => {
     try {
-        JSON.parse(str);
+      JSON.parse(str);
     } catch (e) {
-        return false;
+      return false;
     }
     return true;
   }
@@ -49,8 +49,6 @@ export default class Provisioner extends Component<PropsType, StateType> {
     let protocol = process.env.NODE_ENV == 'production' ? 'wss' : 'ws'
     let viewData = this.props.viewData || []
 
-    console.log("viewData", viewData)
-
     let websockets = viewData.map((infra: any) => {
       let ws = new WebSocket(`${protocol}://${process.env.API_SERVER}/api/projects/${currentProject.id}/provision/${infra.kind}/${infra.infra_id}/logs`)
       
@@ -166,7 +164,8 @@ export default class Provisioner extends Component<PropsType, StateType> {
       currentStep += this.state.currentStep[key]
     }
 
-    if (currentStep === maxStep) {
+    if (maxStep !== 0 && currentStep === maxStep) {
+      console.log('Provisioning complete.')
       this.props.setCurrentView('dashboard');
     }
 

+ 7 - 4
dashboard/src/main/home/sidebar/ProjectSection.tsx

@@ -28,17 +28,20 @@ export default class ProjectSection extends Component<PropsType, StateType> {
       if (err) {
         console.log(err);
       } else if (res.data) {
-        let anyProvisioning = false;
+
+        let viewData = [] as any[]
         res.data.forEach((el: InfraType) => {
           if (el.status === 'creating') {
-            anyProvisioning = true;
-            this.props.setCurrentView('provisioner', {
+            viewData.push({
               infra_id: el.id,
               kind: el.kind,
             });
           }
         });
-        if (!anyProvisioning) {
+
+        if (viewData.length > 0) {
+          this.props.setCurrentView('provisioner', viewData);
+        } else {
           this.props.setCurrentView('dashboard');
         }
       }

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

@@ -276,8 +276,26 @@ const getInfra = baseApi<{
   return `/api/projects/${pathParams.project_id}/infra`;
 });
 
+const destroyCluster = baseApi<{
+}, {
+  project_id: number,
+  infra_id: number,
+}>('POST', pathParams => {
+  return `/projects/${pathParams.project_id}/infra/${pathParams.infra_id}/eks/destroy`;
+});
+
+const deleteCluster = baseApi<{
+}, {
+  project_id: number,
+  cluster_id: number,
+}>('DELETE', pathParams => {
+  return `/projects/${pathParams.project_id}/clusters/${pathParams.cluster_id}`;
+})
+
 // Bundle export to allow default api import (api.<method> is more readable)
 export default {
+  deleteCluster,
+  destroyCluster,
   getInfra,
   linkGithubProject,
   getGitRepos,