Soham Dessai vor 3 Jahren
Ursprung
Commit
59769f7e09

+ 28 - 14
dashboard/src/main/home/app-dashboard/new-app-flow/NewAppFlow.tsx

@@ -80,6 +80,7 @@ const NewAppFlow: React.FC<Props> = ({ ...props }) => {
   const { currentCluster, currentProject } = useContext(Context);
   const [isLoading, setIsLoading] = useState<boolean>(true);
   const [currentStep, setCurrentStep] = useState<number>(0);
+  const [existingStep, setExistingStep] = useState<number>(0);
   const [formState, setFormState] = useState<FormState>(INITIAL_STATE);
   const [actionConfig, setActionConfig] = useState<GithubActionConfigType>({
     ...defaultActionConfig,
@@ -111,9 +112,30 @@ const NewAppFlow: React.FC<Props> = ({ ...props }) => {
   const [showGHAModal, setShowGHAModal] = useState<boolean>(false);
 
   // Deploys a Helm chart and writes build settings to the DB
+  const isAppNameValid = (name: string) => {
+    const regex = /^[a-z0-9-]+$/;
+    return regex.test(name);
+  };
+
+  const handleAppNameChange = (name: string) => {
+    setCurrentStep(currentStep);
+    setFormState({ ...formState, applicationName: name });
+    if (isAppNameValid(name) && Validators.applicationName(name)) {
+      setCurrentStep(Math.max(Math.max(currentStep, 1), existingStep));
+    } else {
+      setExistingStep(Math.max(currentStep, existingStep));
+      setCurrentStep(0);
+    }
+  };
+
+  const shouldHighlightAppNameInput = () => {
+    return (
+      formState.applicationName !== "" &&
+      !isAppNameValid(formState.applicationName)
+    );
+  };
   const deployPorterApp = async () => {
     try {
-
       // Write build settings to the DB
       const res = await api.createPorterApp(
         "<token>",
@@ -125,7 +147,7 @@ const NewAppFlow: React.FC<Props> = ({ ...props }) => {
           project_id: currentProject.id,
         }
       );
-      alert("ok")
+      alert("ok");
     } catch (err) {
       console.log(err);
     }
@@ -137,14 +159,7 @@ const NewAppFlow: React.FC<Props> = ({ ...props }) => {
     <CenterWrapper>
       <Div>
         <StyledConfigureTemplate>
-          <Back to="/apps" />
-          <DashboardHeader
-            prefix={<Icon src={web} />}
-            title="Deploy a new application"
-            capitalize={false}
-            disableLineBreak
-          />
-          <DarkMatter />
+          {/* ... */}
           <VerticalSteps
             currentStep={currentStep}
             steps={[
@@ -159,13 +174,12 @@ const NewAppFlow: React.FC<Props> = ({ ...props }) => {
                   placeholder="ex: academic-sophon"
                   value={formState.applicationName}
                   width="300px"
+                  error={shouldHighlightAppNameInput() && "Invalid App Name"}
                   setValue={(e) => {
-                    setFormState({ ...formState, applicationName: e });
-                    if (Validators.applicationName(e)) {
-                      setCurrentStep(Math.max(currentStep, 1));
-                    }
+                    handleAppNameChange(e);
                   }}
                 />
+                {shouldHighlightAppNameInput()}
               </>,
               <>
                 <Text size={16}>Deployment method</Text>

+ 47 - 32
dashboard/src/main/home/app-dashboard/new-app-flow/Services.tsx

@@ -1,4 +1,4 @@
-import React, { useState } from "react"
+import React, { useState } from "react";
 import ServiceContainer from "./ServiceContainer";
 import styled from "styled-components";
 import Spacer from "components/porter/Spacer";
@@ -19,32 +19,41 @@ interface ServicesProps {
   setServices: (services: Service[]) => void;
 }
 
-const Services: React.FC<ServicesProps> = ({
-  services,
-  setServices,
-}) => {
-  const [showAddServiceModal, setShowAddServiceModal] = useState<boolean>(false);
-  const [serviceName, setServiceName] = useState<string>('');
-  const [serviceType, setServiceType] = useState<ServiceType>('web');
+const Services: React.FC<ServicesProps> = ({ services, setServices }) => {
+  const [showAddServiceModal, setShowAddServiceModal] = useState<boolean>(
+    false
+  );
+  const [serviceName, setServiceName] = useState<string>("");
+  const [serviceType, setServiceType] = useState<ServiceType>("web");
+  const isServiceNameValid = (name: string) => {
+    const regex = /^[a-z0-9-]+$/;
+    return regex.test(name);
+  };
 
   return (
     <>
-      {services.length > 0 &&
+      {services.length > 0 && (
         <>
           <ServicesContainer>
             {services.map((service, index) => {
               return (
                 <ServiceContainer
                   service={service}
-                  editService={(newService: Service) => setServices(services.map((s, i) => i === index ? newService : s))}
-                  deleteService={() => setServices(services.filter((_, i) => i !== index))}
+                  editService={(newService: Service) =>
+                    setServices(
+                      services.map((s, i) => (i === index ? newService : s))
+                    )
+                  }
+                  deleteService={() =>
+                    setServices(services.filter((_, i) => i !== index))
+                  }
                 />
-              )
+              );
             })}
           </ServicesContainer>
           <Spacer y={0.5} />
         </>
-      }
+      )}
       <AddServiceButton onClick={() => setShowAddServiceModal(true)}>
         <i className="material-icons add-icon">add_icon</i>
         Add a new service
@@ -57,18 +66,18 @@ const Services: React.FC<ServicesProps> = ({
           <Spacer y={0.5} />
           <Container row>
             <ServiceIcon>
-              {serviceType === 'web' && <img src={web} />}
-              {serviceType === 'worker' && <img src={worker} />}
-              {serviceType === 'job' && <img src={job} />}
+              {serviceType === "web" && <img src={web} />}
+              {serviceType === "worker" && <img src={worker} />}
+              {serviceType === "job" && <img src={job} />}
             </ServiceIcon>
             <Select
               value={serviceType}
               // this is ugly
               setValue={(value: string) => setServiceType(value as ServiceType)}
               options={[
-                { label: 'Web', value: 'web' },
-                { label: 'Worker', value: 'worker' },
-                { label: 'Job', value: 'job' }
+                { label: "Web", value: "web" },
+                { label: "Worker", value: "worker" },
+                { label: "Job", value: "job" },
               ]}
             />
           </Container>
@@ -79,24 +88,31 @@ const Services: React.FC<ServicesProps> = ({
             placeholder="ex: my-service"
             width="300px"
             value={serviceName}
+            error={!isServiceNameValid(serviceName) && "Invalid Name"}
             setValue={setServiceName}
           />
           <Spacer y={1} />
-          <Button onClick={() => {
-            setServices([...services, createDefaultService(serviceName, serviceType)]);
-            setShowAddServiceModal(false);
-            setServiceName('');
-            setServiceType('web');
-          }}>
+          <Button
+            onClick={() => {
+              setServices([
+                ...services,
+                createDefaultService(serviceName, serviceType),
+              ]);
+              setShowAddServiceModal(false);
+              setServiceName("");
+              setServiceType("web");
+            }}
+            disabled={!isServiceNameValid(serviceName)}
+          >
             <I className="material-icons">add</I> Add service
           </Button>
         </Modal>
       )}
     </>
-  )
-}
+  );
+};
 
-export default Services
+export default Services;
 
 const ServiceIcon = styled.div`
   border: 1px solid #494b4f;
@@ -133,11 +149,10 @@ const I = styled.i`
   justify-content: center;
 `;
 
-const ServicesContainer = styled.div`
-`;
+const ServicesContainer = styled.div``;
 
 const AddServiceButton = styled.div`
-  color:  #aaaabb;
+  color: #aaaabb;
   background: #26292e;
   border: 1px solid #494b4f;
   :hover {
@@ -156,4 +171,4 @@ const AddServiceButton = styled.div`
     width: 30px;
     font-size: 20px;
   }
-`;
+`;