Feroze Mohideen пре 3 година
родитељ
комит
6819928c39

+ 58 - 26
dashboard/src/components/porter/Input.tsx

@@ -1,6 +1,7 @@
 import React, { useEffect, useState } from "react";
 import styled from "styled-components";
 import { boolean } from "zod";
+import Tooltip from "./Tooltip";
 
 type Props = {
   placeholder: string;
@@ -13,6 +14,7 @@ type Props = {
   error?: string;
   children?: React.ReactNode;
   disabled?: boolean;
+  disabledTooltip?: string;
 };
 
 const Input: React.FC<Props> = ({
@@ -26,34 +28,64 @@ const Input: React.FC<Props> = ({
   error,
   children,
   disabled,
+  disabledTooltip,
 }) => {
   return (
-    <Block width={width}>
-      {
-        label && (
-          <Label>{label}</Label>
-        )
-      }
-      <StyledInput
-        value={value}
-        onChange={e => setValue(e.target.value)}
-        placeholder={placeholder}
-        width={width}
-        height={height}
-        type={type || "text"}
-        hasError={(error && true) || (error === "")}
-        disabled={disabled ? disabled : false}
-      />
-      {
-        error && (
-          <Error>
-            <i className="material-icons">error</i>
-            {error}
-          </Error>
-        )
-      }
-      {children}
-    </Block>
+    disabled && disabledTooltip ?
+      <Tooltip content={disabledTooltip} position="right">
+        <Block width={width}>
+          {
+            label && (
+              <Label>{label}</Label>
+            )
+          }
+          <StyledInput
+            value={value}
+            onChange={e => setValue(e.target.value)}
+            placeholder={placeholder}
+            width={width}
+            height={height}
+            type={type || "text"}
+            hasError={(error && true) || (error === "")}
+            disabled={disabled ? disabled : false}
+          />
+          {
+            error && (
+              <Error>
+                <i className="material-icons">error</i>
+                {error}
+              </Error>
+            )
+          }
+          {children}
+        </Block>
+      </Tooltip> :
+      <Block width={width} >
+        {
+          label && (
+            <Label>{label}</Label>
+          )
+        }
+        <StyledInput
+          value={value}
+          onChange={e => setValue(e.target.value)}
+          placeholder={placeholder}
+          width={width}
+          height={height}
+          type={type || "text"}
+          hasError={(error && true) || (error === "")}
+          disabled={disabled ? disabled : false}
+        />
+        {
+          error && (
+            <Error>
+              <i className="material-icons">error</i>
+              {error}
+            </Error>
+          )
+        }
+        {children}
+      </Block >
   );
 };
 

+ 7 - 4
dashboard/src/components/porter/Tooltip.tsx

@@ -7,6 +7,7 @@ interface TooltipProps {
   content: React.ReactNode;
   position?: "top" | "right" | "bottom" | "left";
   hidden?: boolean;
+  width?: string;
 }
 
 const Tooltip: React.FC<TooltipProps> = ({
@@ -14,6 +15,7 @@ const Tooltip: React.FC<TooltipProps> = ({
   content,
   position = "top",
   hidden = false,
+  width,
 }) => {
   const [isVisible, setIsVisible] = useState(false);
 
@@ -27,7 +29,7 @@ const Tooltip: React.FC<TooltipProps> = ({
   return (
     <TooltipContainer onMouseEnter={showTooltip} onMouseLeave={hideTooltip}>
       {isVisible && (
-        <TooltipContent position={position}>{content}</TooltipContent>
+        <TooltipContent position={position} width={width}>{content}</TooltipContent>
       )}
       {children}
     </TooltipContainer>
@@ -41,7 +43,7 @@ const TooltipContainer = styled.div`
   display: inline-flex;
 `;
 
-const TooltipContent = styled.div<{ position: string }>`
+const TooltipContent = styled.div<{ position: string, width?: string }>`
   background-color: #333;
   color: #fff;
   padding: 8px;
@@ -49,7 +51,8 @@ const TooltipContent = styled.div<{ position: string }>`
   font-size: 14px;
   position: absolute;
   z-index: 10;
-  max-width: 200px;
+  max-width: ${({ width }) => width ?? "200px"};
+  width: ${({ width }) => width ?? "200px"};
   text-align: center;
   white-space: pre-wrap;
   word-wrap: break-word;
@@ -64,7 +67,7 @@ const TooltipContent = styled.div<{ position: string }>`
         `;
       case "right":
         return `
-          top: 50%;
+          top: 70%;
           left: 100%;
           transform: translateY(-50%) translateX(8px);
         `;

+ 33 - 24
dashboard/src/main/home/app-dashboard/expanded-app/ExpandedApp.tsx

@@ -85,6 +85,7 @@ const ExpandedApp: React.FC<Props> = ({ ...props }) => {
   const [envVars, setEnvVars] = useState<KeyValueType[]>([]);
   const [updating, setUpdating] = useState<boolean>(false);
   const [updateError, setUpdateError] = useState<string>("");
+  const [subdomain, setSubdomain] = useState<string>("");
 
   const getPorterApp = async () => {
     setIsLoading(true);
@@ -279,6 +280,8 @@ const ExpandedApp: React.FC<Props> = ({ ...props }) => {
       if (helmValues && Object.keys(helmValues).length > 0) {
         const envs = Service.retrieveEnvFromHelmValues(helmValues);
         setEnvVars(envs);
+        const subdomain = Service.retrieveSubdomainFromHelmValues(svcs, helmValues);
+        setSubdomain(subdomain);
       }
     }
   };
@@ -568,11 +571,17 @@ const ExpandedApp: React.FC<Props> = ({ ...props }) => {
               </>
             )}
           </Container>
-          <Spacer y={1} />
+          <Spacer y={0.5} />
+          {subdomain && (
+            <>
+              <Container><Text><a href={subdomain} target="_blank">{subdomain}</a></Text></Container>
+              <Spacer y={0.5} />
+            </>
+          )}
           <Text color="#aaaabb66">
             Last deployed {getReadableDate(appData.chart.info.last_deployed)}
           </Text>
-          <Spacer y={1} />
+          <Spacer y={0.5} />
           {deleting ? (
             <Fieldset>
               <Text size={16}>
@@ -609,7 +618,7 @@ const ExpandedApp: React.FC<Props> = ({ ...props }) => {
                     shouldUpdate={
                       appData.chart.latest_version &&
                       appData.chart.latest_version !==
-                        appData.chart.chart.metadata.version
+                      appData.chart.chart.metadata.version
                     }
                     latestVersion={appData.chart.latest_version}
                     upgradeVersion={appUpgradeVersion}
@@ -623,27 +632,6 @@ const ExpandedApp: React.FC<Props> = ({ ...props }) => {
                   appData.app.git_repo_id
                     ? workflowCheckPassed
                       ? [
-                          { label: "Events", value: "events" },
-                          { label: "Logs", value: "logs" },
-                          { label: "Metrics", value: "metrics" },
-                          { label: "Overview", value: "overview" },
-                          {
-                            label: "Environment variables",
-                            value: "environment-variables",
-                          },
-                          { label: "Build settings", value: "build-settings" },
-                          { label: "Settings", value: "settings" },
-                        ]
-                      : [
-                          { label: "Overview", value: "overview" },
-                          {
-                            label: "Environment variables",
-                            value: "environment-variables",
-                          },
-                          { label: "Build settings", value: "build-settings" },
-                          { label: "Settings", value: "settings" },
-                        ]
-                    : [
                         { label: "Events", value: "events" },
                         { label: "Logs", value: "logs" },
                         { label: "Metrics", value: "metrics" },
@@ -652,8 +640,29 @@ const ExpandedApp: React.FC<Props> = ({ ...props }) => {
                           label: "Environment variables",
                           value: "environment-variables",
                         },
+                        { label: "Build settings", value: "build-settings" },
                         { label: "Settings", value: "settings" },
                       ]
+                      : [
+                        { label: "Overview", value: "overview" },
+                        {
+                          label: "Environment variables",
+                          value: "environment-variables",
+                        },
+                        { label: "Build settings", value: "build-settings" },
+                        { label: "Settings", value: "settings" },
+                      ]
+                    : [
+                      { label: "Events", value: "events" },
+                      { label: "Logs", value: "logs" },
+                      { label: "Metrics", value: "metrics" },
+                      { label: "Overview", value: "overview" },
+                      {
+                        label: "Environment variables",
+                        value: "environment-variables",
+                      },
+                      { label: "Settings", value: "settings" },
+                    ]
                 }
                 currentTab={tab}
                 setCurrentTab={setTab}

+ 4 - 0
dashboard/src/main/home/app-dashboard/new-app-flow/JobTabs.tsx

@@ -31,6 +31,7 @@ const JobTabs: React.FC<Props> = ({
           value={service.startCommand.value}
           width="300px"
           setValue={(e) => { editService({ ...service, startCommand: { readOnly: false, value: e } }) }}
+          disabledTooltip={"You may only edit this field in your porter.yaml."}
         />
         <Spacer y={1} />
         <Input
@@ -40,6 +41,7 @@ const JobTabs: React.FC<Props> = ({
           disabled={service.cronSchedule.readOnly}
           width="300px"
           setValue={(e) => { editService({ ...service, cronSchedule: { readOnly: false, value: e } }) }}
+          disabledTooltip={"You may only edit this field in your porter.yaml."}
         />
       </>
     )
@@ -56,6 +58,7 @@ const JobTabs: React.FC<Props> = ({
           disabled={service.cpu.readOnly}
           width="300px"
           setValue={(e) => { editService({ ...service, cpu: { readOnly: false, value: e } }) }}
+          disabledTooltip={"You may only edit this field in your porter.yaml."}
         />
         <Spacer y={1} />
         <Input
@@ -65,6 +68,7 @@ const JobTabs: React.FC<Props> = ({
           disabled={service.ram.readOnly}
           width="300px"
           setValue={(e) => { editService({ ...service, ram: { readOnly: false, value: e } }) }}
+          disabledTooltip={"You may only edit this field in your porter.yaml."}
         />
       </>
     )

+ 11 - 0
dashboard/src/main/home/app-dashboard/new-app-flow/WebTabs.tsx

@@ -6,6 +6,7 @@ import TabSelector from "components/TabSelector";
 import Checkbox from "components/porter/Checkbox";
 import { WebService } from "./serviceTypes";
 import { Height } from "react-animate-height";
+import Tooltip from "components/porter/Tooltip";
 
 interface Props {
   service: WebService
@@ -31,6 +32,7 @@ const WebTabs: React.FC<Props> = ({
           width="300px"
           disabled={service.startCommand.readOnly}
           setValue={(e) => { editService({ ...service, startCommand: { readOnly: false, value: e } }) }}
+          disabledTooltip={"You may only edit this field in your porter.yaml."}
         />
         <Spacer y={1} />
         <Input
@@ -40,6 +42,7 @@ const WebTabs: React.FC<Props> = ({
           disabled={service.port.readOnly}
           width="300px"
           setValue={(e) => { editService({ ...service, port: { readOnly: false, value: e } }) }}
+          disabledTooltip={"You may only edit this field in your porter.yaml."}
         />
         <Spacer y={1} />
         <Checkbox
@@ -64,6 +67,7 @@ const WebTabs: React.FC<Props> = ({
           disabled={service.cpu.readOnly}
           width="300px"
           setValue={(e) => { editService({ ...service, cpu: { readOnly: false, value: e } }) }}
+          disabledTooltip={"You may only edit this field in your porter.yaml."}
         />
         <Spacer y={1} />
         <Input
@@ -73,6 +77,7 @@ const WebTabs: React.FC<Props> = ({
           disabled={service.ram.readOnly}
           width="300px"
           setValue={(e) => { editService({ ...service, ram: { readOnly: false, value: e } }) }}
+          disabledTooltip={"You may only edit this field in your porter.yaml."}
         />
         <Spacer y={1} />
         <Input
@@ -82,6 +87,7 @@ const WebTabs: React.FC<Props> = ({
           disabled={service.replicas.readOnly}
           width="300px"
           setValue={(e) => { editService({ ...service, replicas: { readOnly: false, value: e } }) }}
+          disabledTooltip={"You may only edit this field in your porter.yaml."}
         />
         <Spacer y={1} />
         <Checkbox
@@ -98,6 +104,7 @@ const WebTabs: React.FC<Props> = ({
           disabled={service.minReplicas.readOnly}
           width="300px"
           setValue={(e) => { editService({ ...service, minReplicas: { readOnly: false, value: e } }) }}
+          disabledTooltip={"You may only edit this field in your porter.yaml."}
         />
         <Spacer y={1} />
         <Input
@@ -107,6 +114,7 @@ const WebTabs: React.FC<Props> = ({
           disabled={service.maxReplicas.readOnly}
           width="300px"
           setValue={(e) => { editService({ ...service, maxReplicas: { readOnly: false, value: e } }) }}
+          disabledTooltip={"You may only edit this field in your porter.yaml."}
         />
         <Spacer y={1} />
         <Input
@@ -116,6 +124,7 @@ const WebTabs: React.FC<Props> = ({
           disabled={service.targetCPUUtilizationPercentage.readOnly}
           width="300px"
           setValue={(e) => { editService({ ...service, targetCPUUtilizationPercentage: { readOnly: false, value: e } }) }}
+          disabledTooltip={"You may only edit this field in your porter.yaml."}
         />
         <Spacer y={1} />
         <Input
@@ -125,6 +134,7 @@ const WebTabs: React.FC<Props> = ({
           disabled={service.targetRAMUtilizationPercentage.readOnly}
           width="300px"
           setValue={(e) => { editService({ ...service, targetRAMUtilizationPercentage: { readOnly: false, value: e } }) }}
+          disabledTooltip={"You may only edit this field in your porter.yaml."}
         />
       </>
     )
@@ -141,6 +151,7 @@ const WebTabs: React.FC<Props> = ({
           disabled={service.customDomain.readOnly}
           width="300px"
           setValue={(e) => { editService({ ...service, customDomain: { readOnly: false, value: e } }) }}
+          disabledTooltip={"You may only edit this field in your porter.yaml."}
         />
       </>
     );

+ 8 - 0
dashboard/src/main/home/app-dashboard/new-app-flow/WorkerTabs.tsx

@@ -31,6 +31,7 @@ const WorkerTabs: React.FC<Props> = ({
           value={service.startCommand.value}
           width="300px"
           setValue={(e) => { editService({ ...service, startCommand: { readOnly: false, value: e } }) }}
+          disabledTooltip={"You may only edit this field in your porter.yaml."}
         />
       </>
     )
@@ -47,6 +48,7 @@ const WorkerTabs: React.FC<Props> = ({
           disabled={service.cpu.readOnly}
           width="300px"
           setValue={(e) => { editService({ ...service, cpu: { readOnly: false, value: e } }) }}
+          disabledTooltip={"You may only edit this field in your porter.yaml."}
         />
         <Spacer y={1} />
         <Input
@@ -56,6 +58,7 @@ const WorkerTabs: React.FC<Props> = ({
           disabled={service.ram.readOnly}
           width="300px"
           setValue={(e) => { editService({ ...service, ram: { readOnly: false, value: e } }) }}
+          disabledTooltip={"You may only edit this field in your porter.yaml."}
         />
         <Spacer y={1} />
         <Input
@@ -65,6 +68,7 @@ const WorkerTabs: React.FC<Props> = ({
           disabled={service.replicas.readOnly}
           width="300px"
           setValue={(e) => { editService({ ...service, replicas: { readOnly: false, value: e } }) }}
+          disabledTooltip={"You may only edit this field in your porter.yaml."}
         />
         <Spacer y={1} />
         <Checkbox
@@ -81,6 +85,7 @@ const WorkerTabs: React.FC<Props> = ({
           disabled={service.minReplicas.readOnly}
           width="300px"
           setValue={(e) => { editService({ ...service, minReplicas: { readOnly: false, value: e } }) }}
+          disabledTooltip={"You may only edit this field in your porter.yaml."}
         />
         <Spacer y={1} />
         <Input
@@ -90,6 +95,7 @@ const WorkerTabs: React.FC<Props> = ({
           disabled={service.maxReplicas.readOnly}
           width="300px"
           setValue={(e) => { editService({ ...service, maxReplicas: { readOnly: false, value: e } }) }}
+          disabledTooltip={"You may only edit this field in your porter.yaml."}
         />
         <Spacer y={1} />
         <Input
@@ -99,6 +105,7 @@ const WorkerTabs: React.FC<Props> = ({
           disabled={service.targetCPUUtilizationPercentage.readOnly}
           width="300px"
           setValue={(e) => { editService({ ...service, targetCPUUtilizationPercentage: { readOnly: false, value: e } }) }}
+          disabledTooltip={"You may only edit this field in your porter.yaml."}
         />
         <Spacer y={1} />
         <Input
@@ -108,6 +115,7 @@ const WorkerTabs: React.FC<Props> = ({
           disabled={service.targetRAMUtilizationPercentage.readOnly}
           width="300px"
           setValue={(e) => { editService({ ...service, targetRAMUtilizationPercentage: { readOnly: false, value: e } }) }}
+          disabledTooltip={"You may only edit this field in your porter.yaml."}
         />
       </>
     )

+ 22 - 0
dashboard/src/main/home/app-dashboard/new-app-flow/serviceTypes.ts

@@ -357,6 +357,28 @@ export const Service = {
             // TODO: handle error
             return [];
         }
+    },
+
+    retrieveSubdomainFromHelmValues: (services: Service[], helmValues: any): string => {
+        const webServices = services.filter(Service.isWeb);
+        if (webServices.length == 0) {
+            return "";
+        }
+
+        for (const web of webServices) {
+            const values = helmValues[Service.toHelmName(web)];
+            if (values == null || values.ingress == null || !values.ingress.enabled) {
+                continue;
+            }
+            if (values.ingress.custom_domain && values.ingress.hosts?.length > 0) {
+                return values.ingress.hosts[0];
+            }
+            if (values.ingress.porter_hosts?.length > 0) {
+                return values.ingress.porter_hosts[0];
+            }
+        }
+
+        return "";
     }
 }