Sfoglia il codice sorgente

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

sunguroku 5 anni fa
parent
commit
5b1b2471aa

+ 2 - 2
dashboard/src/components/TabSelector.tsx

@@ -95,10 +95,10 @@ const Tab = styled.div`
 
 const StyledTabSelector = styled.div`
   display: flex;
-  width: calc(100% - 4px);
+  width: calc(100% - 2px);
   align-items: center;
   border-bottom: 1px solid #aaaabb55;
   padding-bottom: 1px;
-  margin-left: 2px;
+  margin-left: 1px;
   position: relative;
 `;

+ 1 - 1
dashboard/src/components/repo-selector/ActionConfEditor.tsx

@@ -16,7 +16,7 @@ type PropsType = {
   setActionConfig: (x: ActionConfigType) => void;
   setBranch: (x: string) => void;
   setPath: (x: boolean) => void;
-  reset: () => void;
+  reset: any;
 };
 
 type StateType = {

+ 0 - 2
dashboard/src/components/values-form/InputArray.tsx

@@ -1,8 +1,6 @@
 import React, { Component } from "react";
 import styled from "styled-components";
 
-import InputRow from "./InputRow";
-
 type PropsType = {
   label?: string;
   values: string[];

+ 185 - 0
dashboard/src/components/values-form/KeyValueArray.tsx

@@ -0,0 +1,185 @@
+import React, { Component } from "react";
+import styled from "styled-components";
+
+type PropsType = {
+  label?: string;
+  values: any;
+  setValues: (x: any) => void;
+  width?: string;
+};
+
+type StateType = {
+  values: any[];
+};
+
+export default class KeyValueArray extends Component<PropsType, StateType> {
+  state = {
+    values: [] as any[],
+  }
+
+  componentDidMount() {
+    let arr = [] as any[];
+    Object.keys(this.props.values).forEach((key: string, i: number) => {
+      arr.push({ key, value: this.props.values[key] });
+    });
+    this.setState({ values: arr });
+  }
+
+  valuesToObject = () => {
+    let obj = {} as any;
+    this.state.values.forEach((entry: any, i: number) => {
+      obj[entry.key] = entry.value; 
+    });
+    return obj;
+  }
+
+  renderInputList = () => {
+    return (
+      <>
+        {this.state.values.map((entry: any, i: number) => {
+          return (
+            <InputWrapper key={i}>
+              <Input
+                placeholder="ex: key"
+                width="270px"
+                value={entry.key}
+                onChange={(e: any) => {
+                  this.state.values[i].key = e.target.value;
+                  this.setState({ values: this.state.values });
+
+                  let obj = this.valuesToObject();
+                  this.props.setValues(obj);
+                }}
+              />
+              <Spacer />
+              <Input
+                placeholder="ex: value"
+                width="270px"
+                value={entry.value}
+                onChange={(e: any) => {
+                  this.state.values[i].value = e.target.value;
+                  this.setState({ values: this.state.values });
+
+                  let obj = this.valuesToObject();
+                  this.props.setValues(obj);
+                }}
+              />
+              <DeleteButton onClick={() => {
+                this.state.values.splice(i, 1);
+                this.setState({ values: this.state.values });
+
+                let obj = this.valuesToObject();
+                this.props.setValues(obj);
+              }}>
+                <i className="material-icons">cancel</i>
+              </DeleteButton>
+            </InputWrapper>
+          );
+        })}
+      </>
+    );
+  }
+
+  render() {
+    return (
+      <StyledInputArray>
+        <Label>{this.props.label}</Label>
+        {
+          this.state.values.length === 0
+          ? <></>
+          : this.renderInputList()
+        }
+        <AddRowButton onClick={() => {
+          this.state.values.push({ key: '', value: '' });
+          this.setState({ values: this.state.values });
+        }}>
+          <i className="material-icons">add</i> Add Row
+        </AddRowButton>
+      </StyledInputArray>
+    );
+  }
+}
+
+const Spacer = styled.div`
+  width: 10px;
+  height: 20px;
+`;
+
+const AddRowButton = styled.div`
+  display: flex;
+  align-items: center;
+  margin-top: 5px;
+  width: 270px;
+  font-size: 13px;
+  color: #aaaabb;
+  height: 32px;
+  border-radius: 3px;
+  cursor: pointer;
+  background: #ffffff11;
+  :hover {
+    background: #ffffff22;
+  }
+
+  > i {
+    color: #ffffff44;
+    font-size: 16px;
+    margin-left: 8px;
+    margin-right: 10px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+  }
+`;
+
+const DeleteButton = styled.div`
+  width: 15px;
+  height: 15px;
+  display: flex;
+  align-items: center;
+  margin-left: 8px;
+  margin-top: -3px;
+  justify-content: center;
+  
+  > i {
+    font-size: 17px;
+    color: #ffffff44;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    cursor: pointer;
+    :hover {
+      color: #ffffff88;
+    }
+  }
+`;
+
+const InputWrapper = styled.div`
+  display: flex;
+  align-items: center;
+`;
+
+const Input = styled.input`
+  outline: none;
+  border: none;
+  margin-bottom: 5px;
+  font-size: 13px;
+  background: #ffffff11;
+  border: 1px solid #ffffff55;
+  border-radius: 3px;
+  width: ${(props: { disabled?: boolean; width: string }) =>
+    props.width ? props.width : "270px"};
+  color: ${(props: { disabled?: boolean; width: string }) =>
+    props.disabled ? "#ffffff44" : "white"};
+  padding: 5px 10px;
+  height: 35px;
+`;
+
+const Label = styled.div`
+  color: #ffffff;
+  margin-bottom: 10px;
+`;
+
+const StyledInputArray = styled.div`
+  margin-bottom: 15px;
+  margin-top: 22px;
+`;

+ 13 - 1
dashboard/src/components/values-form/ValuesForm.tsx

@@ -12,7 +12,8 @@ import Helper from "./Helper";
 import Heading from "./Heading";
 import ExpandableResource from "../ExpandableResource";
 import VeleroForm from "../forms/VeleroForm";
-import InputArray from "./InputArray";
+import InputArray from './InputArray';
+import KeyValueArray from './KeyValueArray';
 
 type PropsType = {
   sections?: Section[];
@@ -22,6 +23,7 @@ type PropsType = {
 
 type StateType = any;
 
+// Requires an internal representation unlike other values components because metaState value underdetermines input order
 export default class ValuesForm extends Component<PropsType, StateType> {
   getInputValue = (item: FormElement) => {
     let key = item.name || item.variable;
@@ -70,6 +72,16 @@ export default class ValuesForm extends Component<PropsType, StateType> {
               label={item.label}
             />
           );
+        case "key-value-array":
+          return (
+            <KeyValueArray
+              values={this.props.metaState[key]}
+              setValues={(x: any) => {
+                this.props.setMetaState({ [key]: x });
+              }}
+              label={item.label}
+            />
+          );
         case "array-input":
           return (
             <InputArray

+ 3 - 0
dashboard/src/components/values-form/ValuesWrapper.tsx

@@ -60,6 +60,9 @@ export default class ValuesWrapper extends Component<PropsType, StateType> {
               case "array-input":
                 metaState[key] = def ? def : [];
                 break;
+              case "key-value-array":
+                metaState[key] = def ? def : {};
+                break;
               case "number-input":
                 metaState[key] = def.toString() ? def : "";
                 break;

+ 1 - 1
dashboard/src/main/home/cluster-dashboard/expanded-chart/ExpandedChart.tsx

@@ -383,7 +383,7 @@ export default class ExpandedChart extends Component<PropsType, StateType> {
     if (this.state.devOpsMode) {
       tabOptions.push(
         { label: "Manifests", value: "list" },
-        { label: "Raw Values", value: "values" }
+        { label: "Helm Values", value: "values" }
       );
     }
 

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

@@ -13,8 +13,8 @@ import hardcodedNames from "./hardcodedNameDict";
 import { Link } from "react-router-dom";
 
 const tabOptions = [
-  { label: "Launch service", value: "docker" },
-  { label: "Community Templates", value: "community" },
+  { label: "New Application", value: "docker" },
+  { label: "Community Add-ons", value: "community" },
 ];
 
 type PropsType = {};

+ 1 - 1
dashboard/src/main/home/launch/expanded-template/ExpandedTemplate.tsx

@@ -129,7 +129,7 @@ const LoadingWrapper = styled.div`
 `;
 
 const StyledExpandedTemplate = styled.div`
-  width: calc(90% - 150px);
+  width: 100%;
   min-width: 300px;
   padding-top: 30px;
 `;

+ 74 - 34
dashboard/src/main/home/launch/expanded-template/LaunchTemplate.tsx

@@ -523,21 +523,45 @@ export default class LaunchTemplate extends Component<PropsType, StateType> {
 
     return (
       <StyledLaunchTemplate>
-        <ClusterSection>
-          {this.props.hideBackButton ? null : (
-            <Flex>
-              <i className="material-icons" onClick={this.props.hideLaunch}>
-                keyboard_backspace
-              </i>
-            </Flex>
-          )}
-          <Template>
+        {
+          name !== 'docker' && 
+            <HeaderSection>
+            <i
+              className="material-icons"
+              onClick={this.props.hideLaunch}
+            >
+              keyboard_backspace
+            </i>
             {icon
               ? this.renderIcon(icon)
               : this.renderIcon(currentTemplate.icon)}
-            {name}
-          </Template>
-          <i className="material-icons">arrow_right_alt</i>
+            <Title>{name}</Title>
+          </HeaderSection>
+        }
+        <DarkMatter antiHeight="-13px" />
+        <Heading isAtTop={true}>Name</Heading>
+        <Subtitle>
+          Randomly generated if left blank. 
+          <Warning
+            highlight={
+              !isAlphanumeric(this.state.templateName) &&
+              this.state.templateName !== ""
+            }
+          >
+            Lowercase letters, numbers, and "-" only.
+          </Warning>
+        </Subtitle>
+        <DarkMatter antiHeight="-29px" />
+        <InputRow
+          type="text"
+          value={this.state.templateName}
+          setValue={(x: string) => this.setState({ templateName: x })}
+          placeholder="ex: doctor-scientist"
+          width="100%"
+        />
+        <Heading>Destination</Heading>
+        <Subtitle>Specify the cluster and namespace you would like to deploy your application to.</Subtitle>
+        <ClusterSection>
           <ClusterLabel>
             <i className="material-icons">device_hub</i>Cluster
           </ClusterLabel>
@@ -569,26 +593,6 @@ export default class LaunchTemplate extends Component<PropsType, StateType> {
             closeOverlay={true}
           />
         </ClusterSection>
-        <Subtitle>
-          Template name
-          <Warning
-            highlight={
-              !isAlphanumeric(this.state.templateName) &&
-              this.state.templateName !== ""
-            }
-          >
-            (lowercase letters, numbers, and "-" only)
-          </Warning>
-          . (Optional)
-        </Subtitle>
-        <DarkMatter antiHeight="-27px" />
-        <InputRow
-          type="text"
-          value={this.state.templateName}
-          setValue={(x: string) => this.setState({ templateName: x })}
-          placeholder="ex: doctor-scientist"
-          width="100%"
-        />
         {this.renderSourceSelector()}
         {this.renderSettingsRegion()}
       </StyledLaunchTemplate>
@@ -598,6 +602,41 @@ export default class LaunchTemplate extends Component<PropsType, StateType> {
 
 LaunchTemplate.contextType = Context;
 
+const Title = styled.div`
+  font-size: 24px;
+  font-weight: 600;
+  font-family: "Work Sans", sans-serif;
+  margin-left: 10px;
+  border-radius: 2px;
+  color: #ffffff;
+`;
+
+const HeaderSection = styled.div`
+  display: flex;
+  align-items: center;
+
+  > i {
+    cursor: pointer;
+    font-size 24px;
+    color: #969Fbbaa;
+    padding: 3px;
+    border-radius: 100px;
+    :hover {
+      background: #ffffff11;
+    }
+  }
+`;
+
+const Heading = styled.div<{ isAtTop?: boolean }>`
+  color: white;
+  font-weight: 500;
+  font-size: 16px;
+  margin-bottom: 5px;
+  margin-top: ${(props) => (props.isAtTop ? "10px" : "30px")};
+  display: flex;
+  align-items: center;
+`;
+
 const Warning = styled.span<{ highlight: boolean; makeFlush?: boolean }>`
   color: ${(props) => (props.highlight ? "#f5cb42" : "")};
   margin-left: ${(props) => (props.makeFlush ? "" : "5px")};
@@ -638,7 +677,7 @@ const DarkMatter = styled.div<{ antiHeight?: string }>`
 `;
 
 const Subtitle = styled.div`
-  padding: 11px 0px 20px;
+  padding: 11px 0px 16px;
   font-family: "Work Sans", sans-serif;
   font-size: 13px;
   color: #aaaabb;
@@ -695,8 +734,9 @@ const ClusterSection = styled.div`
   color: #ffffff;
   font-family: "Work Sans", sans-serif;
   font-size: 14px;
+  margin-top: 2px;
   font-weight: 500;
-  margin-bottom: 15px;
+  margin-bottom: 22px;
 
   > i {
     font-size: 25px;

+ 1 - 1
dashboard/src/main/home/launch/expanded-template/TemplateInfo.tsx

@@ -301,7 +301,7 @@ const TitleSection = styled.div`
   flex-direction: row;
   height: 40px;
   justify-content: space-between;
-  width: calc(100% + 42px);
+  width: 100%;
   align-items: center;
 `;