فهرست منبع

Merge branch 'beta.3.integration-frontend' into main

sunguroku 5 سال پیش
والد
کامیت
573014744a

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

@@ -114,7 +114,7 @@ export default class Home extends Component<PropsType, StateType> {
   // TODO: move into ClusterDashboard
   renderDashboard = () => {
     let { currentCluster, setCurrentModal } = this.context;
-    if (this.state.showWelcome || currentCluster && !currentCluster.name) {
+    if (currentCluster && !currentCluster.name) {
       return (
         <DashboardWrapper>
           <Placeholder>

+ 10 - 21
dashboard/src/main/home/provisioner/AWSFormSection.tsx

@@ -55,19 +55,9 @@ export default class AWSFormSection extends Component<PropsType, StateType> {
       infras.forEach(
         (infra: InfraType, i: number) => {
           let { kind, status } = infra;
-          if (
-            kind === 'ecr'
-            && (status === 'creating' || status === 'created')
-          ) {
+          if (status === 'creating' || status === 'created') {
             filtered = filtered.filter((item: any) => {
-              return item.value !== 'ecr';
-            });
-          } else if (
-            kind === 'eks'
-            && (status === 'creating' || status === 'created')
-          ) {
-            filtered = filtered.filter((item: any) => {
-              return item.value !== 'eks';
+              return item.value !== kind;
             });
           }
         }
@@ -116,6 +106,10 @@ export default class AWSFormSection extends Component<PropsType, StateType> {
         handleError();
         return;
       } else {
+        let proj = res.data;
+
+        // Need to set project list for dropdown
+        // TODO: consolidate into ProjectSection (case on exists in list on set)
         api.getProjects('<token>', {}, { 
           id: user.userId 
         }, (err: any, res: any) => {
@@ -125,13 +119,8 @@ export default class AWSFormSection extends Component<PropsType, StateType> {
             return;
           }
           setProjects(res.data);
-          if (res.data.length > 0) {
-            let tgtProject = res.data.find((el: ProjectType) => {
-              return el.name === projectName;
-            });
-            setCurrentProject(tgtProject);
-            callback && callback();
-          } 
+          setCurrentProject(proj);
+          callback && callback();
         });
       }
     });
@@ -288,8 +277,8 @@ export default class AWSFormSection extends Component<PropsType, StateType> {
             isRequired={true}
           />
           <Br />
-          <Heading>Resources</Heading>
-          <Helper>Porter will provision the following resources</Helper>
+          <Heading>AWS Resources</Heading>
+          <Helper>Porter will provision the following AWS resources</Helper>
           <CheckboxList
             options={provisionOptions}
             selected={selectedInfras}

+ 238 - 0
dashboard/src/main/home/provisioner/DOFormSection.tsx

@@ -0,0 +1,238 @@
+import React, { Component } from 'react';
+import styled from 'styled-components';
+
+import close from '../../../assets/close.png';
+import { isAlphanumeric } from '../../../shared/common';
+import api from '../../../shared/api';
+import { Context } from '../../../shared/Context';
+import { ProjectType, InfraType } from '../../../shared/types';
+
+import InputRow from '../../../components/values-form/InputRow';
+import Helper from '../../../components/values-form/Helper';
+import Heading from '../../../components/values-form/Heading';
+import SaveButton from '../../../components/SaveButton';
+import CheckboxList from '../../../components/values-form/CheckboxList';
+
+type PropsType = {
+  setSelectedProvisioner: (x: string | null) => void,
+  handleError: () => void,
+  projectName: string,
+  infras: InfraType[],
+};
+
+type StateType = {
+  selectedInfras: { value: string, label: string }[],
+};
+
+const provisionOptions = [
+  { value: 'docr', label: 'Digital Ocean Container Registry' },
+  { value: 'doks', label: 'Digital Ocean Kubernetes Service' },
+];
+
+// TODO: Consolidate across forms w/ HOC
+export default class DOFormSection extends Component<PropsType, StateType> {
+  state = {
+    selectedInfras: [...provisionOptions],
+  }
+
+  componentDidMount = () => {
+    let { infras } = this.props;
+    let { selectedInfras } = this.state;
+
+    if (infras) {
+      
+      // From the dashboard, only uncheck and disable if "creating" or "created"
+      let filtered = selectedInfras;
+      infras.forEach(
+        (infra: InfraType, i: number) => {
+          let { kind, status } = infra;
+          if (status === 'creating' || status === 'created') {
+            filtered = filtered.filter((item: any) => {
+              return item.value !== kind;
+            });
+          }
+        }
+      );
+      this.setState({ selectedInfras: filtered });
+    }
+  }
+
+  checkFormDisabled = () => {
+    let { 
+      selectedInfras,
+    } = this.state;
+    let { projectName } = this.props;
+    if (projectName || projectName === '') {
+      return !isAlphanumeric(projectName) || selectedInfras.length === 0;
+    } else {
+      return selectedInfras.length === 0;
+    }
+  }
+
+  // Step 1: Create a project
+  createProject = (callback?: any) => {
+    console.log('Creating project');
+    let { projectName, handleError } = this.props;
+    let { 
+      user, 
+      setProjects, 
+      setCurrentProject, 
+    } = this.context;
+
+    api.createProject('<token>', { name: projectName }, {
+    }, (err: any, res: any) => {
+      if (err) {
+        console.log(err);
+        handleError();
+        return;
+      } else {
+        let proj = res.data;
+
+        // Need to set project list for dropdown
+        // TODO: consolidate into ProjectSection (case on exists in list on set)
+        api.getProjects('<token>', {}, { 
+          id: user.userId 
+        }, (err: any, res: any) => {
+          if (err) {
+            console.log(err);
+            handleError();
+            return;
+          }
+          setProjects(res.data);
+          setCurrentProject(proj);
+          callback && callback();
+        });
+      }
+    });
+  }
+
+  // TODO: handle generically (with > 2 steps)
+  onCreateDO = () => {
+    let { projectName } = this.props;
+    let { selectedInfras } = this.state;
+    let { currentProject } = this.context;
+
+    if (!projectName) {
+      window.location.href = `/api/oauth/projects/${currentProject.id}/digitalocean`;
+    } else {
+      this.createProject(() => {
+        console.log('redirecting...')
+        window.location.href = `/api/oauth/projects/${currentProject.id}/digitalocean`;
+      });
+    }
+  }
+
+  render() {
+    let { setSelectedProvisioner } = this.props;
+    let {
+      selectedInfras,
+    } = this.state;
+
+    return (
+      <StyledAWSFormSection>
+        <FormSection>
+          <CloseButton onClick={() => setSelectedProvisioner(null)}>
+            <CloseButtonImg src={close} />
+          </CloseButton>
+          <Heading isAtTop={true}>DigitalOcean Resources</Heading>
+          <Helper>Porter will provision the following DigitalOcean resources</Helper>
+          <CheckboxList
+            options={provisionOptions}
+            selected={selectedInfras}
+            setSelected={(x: { value: string, label: string }[]) => {
+              this.setState({ selectedInfras: x });
+            }}
+          />
+        </FormSection>
+        {this.props.children ? this.props.children : <Padding />}
+        <SaveButton
+          text='Submit'
+          disabled={this.checkFormDisabled()}
+          onClick={this.onCreateDO}
+          makeFlush={true}
+          helper='Note: Provisioning can take up to 15 minutes'
+        />
+      </StyledAWSFormSection>
+    );
+  }
+}
+
+DOFormSection.contextType = Context;
+
+const Padding = styled.div`
+  height: 15px;
+`;
+
+const Br = styled.div`
+  width: 100%;
+  height: 2px;
+`;
+
+const StyledAWSFormSection = styled.div`
+  position: relative;
+  padding-bottom: 35px;
+`;
+
+const FormSection = styled.div`
+  background: #ffffff11;
+  margin-top: 25px;
+  background: #26282f;
+  border-radius: 5px;
+  margin-bottom: 25px;
+  padding: 25px;
+  padding-bottom: 16px;
+  font-size: 13px;
+  animation: fadeIn 0.3s 0s;
+  position: relative;
+`;
+
+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 GuideButton = styled.a`
+  display: flex;
+  align-items: center;
+  margin-left: 20px;
+  color: #aaaabb;
+  font-size: 13px;
+  margin-bottom: -1px;
+  border: 1px solid #aaaabb;
+  padding: 5px 10px;
+  padding-left: 6px;
+  border-radius: 5px;
+  cursor: pointer;
+  :hover {
+    background: #ffffff11;
+    color: #ffffff;
+    border: 1px solid #ffffff;
+
+    > i {
+      color: #ffffff;
+    }
+  }
+
+  > i {
+    color: #aaaabb;
+    font-size: 16px;
+    margin-right: 6px;
+  }
+`;
+
+const CloseButtonImg = styled.img`
+  width: 14px;
+  margin: 0 auto;
+`;

+ 15 - 3
dashboard/src/main/home/provisioner/ProvisionerSettings.tsx

@@ -8,6 +8,7 @@ import { InfraType } from '../../../shared/types';
 import Helper from '../../../components/values-form/Helper';
 import AWSFormSection from './AWSFormSection';
 import GCPFormSection from './GCPFormSection';
+import DOFormSection from './DOFormSection';
 import SaveButton from '../../../components/SaveButton';
 import ExistingClusterSection from './ExistingClusterSection';
 
@@ -100,7 +101,16 @@ export default class NewProject extends Component<PropsType, StateType> {
           />
         );
       case 'do':
-        return <h1>most</h1>;
+        return (
+          <DOFormSection 
+            handleError={this.handleError}
+            projectName={projectName}
+            infras={infras}
+            setSelectedProvisioner={(x: string | null) => {
+              this.setState({ selectedProvider: x });
+            }}
+          />
+        )
       default:
         return (
           <ExistingClusterSection 
@@ -119,8 +129,10 @@ export default class NewProject extends Component<PropsType, StateType> {
     return (
       <StyledProvisionerSettings>
         <Helper>
-          Need a cluster? Provision through Porter: 
-          {isInNewProject && <Required>*</Required>}
+          {isInNewProject 
+            ? <>Select your hosting backend:<Required>*</Required></>
+            : 'Need a cluster? Provision through Porter:'
+          }
         </Helper>
         {!selectedProvider ? (
           <BlockList>