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

recreated lost tailscale changes

jusrhee 4 лет назад
Родитель
Сommit
cc3e37e223

+ 4 - 1
dashboard/src/components/values-form/FormWrapper.tsx

@@ -78,7 +78,10 @@ export default class FormWrapper extends Component<PropsType, StateType> {
       };
       if (tabs) {
         tabs.forEach((tab: any, i: number) => {
-          if (tab?.name && tab.label) {
+
+          // Exclude value if omitFromLaunch is set
+          let omit = tab.settings?.omitFromLaunch && this.props.externalValues?.isLaunch;
+          if (tab?.name && tab.label && !omit) {
             // If a tab is valid, extract state
             tab.sections?.forEach((section: Section, i: number) => {
               section?.contents?.forEach((item: FormElement, i: number) => {

+ 25 - 2
dashboard/src/components/values-form/Heading.tsx

@@ -1,9 +1,18 @@
 import React from "react";
 import styled from "styled-components";
 
-export default function Heading(props: { isAtTop?: boolean; children: any }) {
+export default function Heading(props: { isAtTop?: boolean; children: any; docs?: string }) {
   return (
-    <StyledHeading isAtTop={props.isAtTop}>{props.children}</StyledHeading>
+    <StyledHeading isAtTop={props.isAtTop}>
+      {props.children}
+      {
+        props.docs && (
+          <a href={props.docs} target="_blank">
+            <i className="material-icons">help_outline</i>
+          </a>
+        )
+      }
+    </StyledHeading>
   );
 }
 
@@ -15,4 +24,18 @@ const StyledHeading = styled.div<{ isAtTop: boolean }>`
   margin-bottom: 5px;
   display: flex;
   align-items: center;
+
+  > a {
+    > i {
+      display: flex;
+      align-items: center;
+      margin-bottom: -2px;
+      font-size: 16px;
+      margin-left: 12px;
+      color: #858faaaa;
+      :hover {
+        color: #aaaabb;
+      }
+    }
+  }
 `;

+ 114 - 0
dashboard/src/components/values-form/ServiceRow.tsx

@@ -0,0 +1,114 @@
+import React, { Component } from "react";
+import styled from "styled-components";
+import { Context } from "shared/Context";
+import { hardcodedNames, hardcodedIcons } from "shared/hardcodedNameDict";
+
+type PropsType = {
+  service: {
+    clusterIP: string,
+    name: string,
+    release: string,
+    app: string,
+    namespace: string,
+    type?: string,
+  }
+};
+
+type StateType = any;
+
+export default class ServiceRow extends Component<
+  PropsType,
+  StateType
+> {
+  render() {
+    let { clusterIP, name, namespace, type, app, release } = this.props.service;
+    name = name || release;
+    type = type || app;
+    return (
+      <>
+      { name && type && hardcodedNames[type] && hardcodedIcons[type] && namespace !== "kube-system" &&
+        <StyledServiceRow>
+          <Flex>
+            <Icon src={hardcodedIcons[type]} />
+            <Type>{hardcodedNames[type]}</Type>
+            <Name>{name}</Name> <Dash>-</Dash> <IP>{clusterIP}</IP>
+          </Flex>
+          <TagWrapper>
+            Namespace: <NamespaceTag>{namespace}</NamespaceTag>
+          </TagWrapper>
+        </StyledServiceRow>
+      }
+      </>
+    );
+  }
+}
+
+ServiceRow.contextType = Context;
+
+const Flex = styled.div`
+  display: flex;
+  align-items: center;
+`;
+
+const TagWrapper = styled.div`
+  float: right;
+  height: 20px;
+  font-size: 13px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  color: #ffffff44;
+  border-right: 0;
+  border-radius: 3px;
+  padding-left: 5px;
+`;
+
+const NamespaceTag = styled.div`
+  height: 20px;
+  margin-left: 6px;
+  color: #aaaabb;
+  border-radius: 3px;
+  font-size: 13px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  padding-left: 3px;
+  border-top-left-radius: 0px;
+  border-bottom-left-radius: 0px;
+`;
+
+
+const Dash = styled.div`
+  margin-right: 10px;
+`;
+
+const Icon = styled.img`
+  width: 20px;
+  margin-right: 12px;
+`;
+
+const Type = styled.div`
+  color: #aaaabb;
+  margin-right: 15px;
+`;
+
+const Name = styled.div`
+  margin-right: 10px;
+`;
+
+const IP = styled.div`
+  user-select: text;
+  font-weight: 500;
+`;
+
+const StyledServiceRow = styled.div`
+  width: 100%;
+  height: 40px;
+  background: #ffffff11;
+  margin-bottom: 15px;
+  border-radius: 5px;
+  padding: 15px;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+`;

+ 25 - 9
dashboard/src/components/values-form/ValuesForm.tsx

@@ -18,6 +18,7 @@ import SelectRow from "./SelectRow";
 import Helper from "./Helper";
 import Heading from "./Heading";
 import ExpandableResource from "../ExpandableResource";
+import ServiceRow from "./ServiceRow";
 import VeleroForm from "../forms/VeleroForm";
 import InputArray from "./InputArray";
 import KeyValueArray from "./KeyValueArray";
@@ -68,26 +69,40 @@ export default class ValuesForm extends Component<PropsType, StateType> {
 
       switch (item.type) {
         case "heading":
-          return <Heading key={i}>{item.label}</Heading>;
+          return <Heading key={i} docs={item.settings?.docs}>{item.label}</Heading>;
         case "subtitle":
           return <Helper key={i}>{item.label}</Helper>;
-        case "resource-list":
+        case "service-ip-list":
           if (Array.isArray(item.value)) {
             return (
               <ResourceList key={key}>
-                {item.value?.map((resource: any, i: number) => {
+                {item.value?.map((service: any, i: number) => {
                   return (
-                    <ExpandableResource
-                      key={i}
-                      resource={resource}
-                      isLast={i === item.value.length - 1}
-                      roundAllCorners={true}
-                    />
+                    <ServiceRow service={service} key={i} />
                   );
                 })}
               </ResourceList>
             );
           }
+        case "resource-list":
+          if (Array.isArray(item.value)) {
+            return (
+              <ResourceList key={key}>
+                {item.value?.map((resource: any, i: number) => {
+                  if (resource.data) {
+                    return (
+                      <ExpandableResource
+                        key={i}
+                        resource={resource}
+                        isLast={i === item.value.length - 1}
+                        roundAllCorners={true}
+                      />
+                    );
+                  }
+                })}
+              </ResourceList>
+            );
+          }
         case "checkbox":
           return (
             <CheckboxRow
@@ -181,6 +196,7 @@ export default class ValuesForm extends Component<PropsType, StateType> {
             <InputRow
               key={key}
               width="100%"
+              placeholder={item.placeholder}
               isRequired={item.required}
               type="password"
               value={this.getInputValue(item)}

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

@@ -11,7 +11,7 @@ import Loading from "components/Loading";
 import LaunchFlow from "./launch-flow/LaunchFlow";
 import NoClusterPlaceholder from "../NoClusterPlaceholder";
 
-import hardcodedNames from "./hardcodedNameDict";
+import { hardcodedNames } from "shared/hardcodedNameDict";
 import semver from "semver";
 
 const tabOptions = [

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

@@ -9,7 +9,7 @@ import { PorterTemplate } from "shared/types";
 import Helper from "components/values-form/Helper";
 import Selector from "components/Selector";
 
-import hardcodedNames from "../hardcodedNameDict";
+import { hardcodedNames } from "shared/hardcodedNameDict";
 
 type PropsType = {
   currentTemplate: any;

+ 0 - 20
dashboard/src/main/home/launch/hardcodedNameDict.tsx

@@ -1,20 +0,0 @@
-const hardcodedNames: { [key: string]: string } = {
-  docker: "Docker",
-  "https-issuer": "HTTPS Issuer",
-  metabase: "Metabase",
-  mongodb: "MongoDB",
-  mysql: "MySQL",
-  postgresql: "PostgreSQL",
-  redis: "Redis",
-  ubuntu: "Ubuntu",
-  web: "Web Service",
-  worker: "Worker",
-  job: "Job",
-  "cert-manager": "Cert Manager",
-  elasticsearch: "Elasticsearch",
-  prometheus: "Prometheus",
-  rabbitmq: "RabbitMQ",
-  logdna: "LogDNA",
-};
-
-export default hardcodedNames;

+ 1 - 1
dashboard/src/main/home/launch/launch-flow/LaunchFlow.tsx

@@ -8,7 +8,7 @@ import api from "shared/api";
 import { Context } from "shared/Context";
 import { pushFiltered } from "shared/routing";
 
-import hardcodedNames from "../hardcodedNameDict";
+import { hardcodedNames } from "shared/hardcodedNameDict";
 import SourcePage from "./SourcePage";
 import SettingsPage from "./SettingsPage";
 

+ 1 - 0
dashboard/src/shared/types.tsx

@@ -135,6 +135,7 @@ export interface FormElement {
   placeholder?: string;
   value?: any;
   settings?: {
+    docs?: string;
     default?: number | string | boolean;
     options?: any[];
     omitUnitFromValue?: boolean;

+ 4 - 0
internal/models/templates.go

@@ -30,6 +30,9 @@ type FormTab struct {
 	Name     string         `yaml:"name" json:"name"`
 	Label    string         `yaml:"label" json:"label"`
 	Sections []*FormSection `yaml:"sections" json:"sections,omitempty"`
+	Settings struct {
+		OmitFromLaunch bool `yaml:"omitFromLaunch,omitempty" json:"omitFromLaunch,omitempty"`
+	} `yaml:"settings,omitempty" json:"settings,omitempty"`
 }
 
 // FormSection is a section of a form
@@ -51,6 +54,7 @@ type FormContent struct {
 	Placeholder string       `yaml:"placeholder,omitempty" json:"placeholder,omitempty"`
 	Value       interface{}  `yaml:"value,omitempty" json:"value,omitempty"`
 	Settings    struct {
+		Docs               string      `yaml:"docs,omitempty" json:"docs,omitempty"`
 		Default            interface{} `yaml:"default,omitempty" json:"default,omitempty"`
 		Unit               interface{} `yaml:"unit,omitempty" json:"unit,omitempty"`
 		OmitUnitFromValue  bool        `yaml:"omitUnitFromValue,omitempty" json:"omitUnitFromValue,omitempty"`