Procházet zdrojové kódy

Implemented basic version of cron input

jnfrati před 4 roky
rodič
revize
4611134850

+ 4 - 2
dashboard/src/components/form-components/InputRow.tsx

@@ -15,6 +15,7 @@ type PropsType = {
   isRequired?: boolean;
   className?: string;
   maxLength?: number;
+  hasError?: boolean;
 };
 
 type StateType = {
@@ -65,7 +66,7 @@ export default class InputRow extends Component<PropsType, StateType> {
             {this.props.isRequired && <Required>{" *"}</Required>}
           </Label>
         )}
-        <InputWrapper>
+        <InputWrapper hasError={this.props.hasError}>
           <Input
             readOnly={this.state.readOnly}
             onFocus={() => this.setState({ readOnly: false })}
@@ -103,7 +104,8 @@ const InputWrapper = styled.div`
   display: flex;
   margin-bottom: -1px;
   align-items: center;
-  border: 1px solid #ffffff55;
+  border: 1px solid
+    ${(props: { hasError: boolean }) => (props.hasError ? "red" : "#ffffff55")};
   border-radius: 3px;
 `;
 

+ 4 - 0
dashboard/src/components/porter-form/PorterForm.tsx

@@ -2,6 +2,7 @@ import React, { useContext } from "react";
 import {
   ArrayInputField,
   CheckboxField,
+  CronField,
   FormField,
   InputField,
   KeyValueArrayField,
@@ -24,6 +25,7 @@ import Select from "./field-components/Select";
 import ServiceIPList from "./field-components/ServiceIPList";
 import ResourceList from "./field-components/ResourceList";
 import VeleroForm from "./field-components/VeleroForm";
+import CronInput from "./field-components/CronInput";
 
 interface Props {
   leftTabOptions?: TabOption[];
@@ -84,6 +86,8 @@ const PorterForm: React.FC<Props> = (props) => {
         return <ResourceList {...(bundledProps as ResourceListField)} />;
       case "velero-create-backup":
         return <VeleroForm />;
+      case "cron":
+        return <CronInput {...(bundledProps as CronField)} />;
     }
     return <p>Not Implemented: {(field as any).type}</p>;
   };

+ 64 - 0
dashboard/src/components/porter-form/field-components/CronInput.tsx

@@ -0,0 +1,64 @@
+import InputRow from "components/form-components/InputRow";
+import React from "react";
+import useFormField from "../hooks/useFormField";
+import { CronField } from "../types";
+import { hasSetValue } from "../utils";
+import { isValidCron } from "cron-validator";
+import CronParser from "cronstrue";
+import styled from "styled-components";
+
+const CronInput: React.FC<CronField> = (props) => {
+  const { id, variable } = props;
+
+  const { state, variables, setVars, setValidation, validation } = useFormField(
+    id,
+    {
+      initValidation: {
+        validated: hasSetValue(props),
+      },
+    }
+  );
+
+  console.log(validation[id]);
+
+  return (
+    <>
+      <InputRow
+        type="text"
+        value={variables[variable]}
+        setValue={(x: string) => {
+          setVars((vars) => {
+            return {
+              ...vars,
+              [variable]: x,
+            };
+          });
+          setValidation((prev) => {
+            return {
+              ...prev,
+              validated: isValidCron(x),
+            };
+          });
+        }}
+        width={"100%"}
+        hasError={!validation[id].validated}
+      />
+      <Label error={!validation[id].validated}>
+        {CronParser.toString(variables[variable], {
+          throwExceptionOnParseError: false,
+          verbose: true,
+        })}
+      </Label>
+    </>
+  );
+};
+
+const Label = styled.label`
+  ${(props: { error: boolean }) => {
+    if (props.error) {
+      return "color: red;";
+    }
+  }}
+`;
+
+export default CronInput;

+ 2 - 0
dashboard/src/components/porter-form/hooks/useFormField.tsx

@@ -9,6 +9,7 @@ import {
 interface FormFieldData<T> {
   state: T;
   variables: PorterFormVariableList;
+  validation: { [key: string]: PorterFormFieldValidationState };
   setState: (setFunc: (prev: T) => Partial<T>) => void;
   setVars: (
     setFunc: (vars: PorterFormVariableList) => PorterFormVariableList
@@ -89,6 +90,7 @@ const useFormField = <T extends PorterFormFieldFieldState>(
   return {
     state: formState.components[fieldId]?.state as T,
     variables: formState.variables,
+    validation: formState.validation,
     setState,
     setVars,
     setValidation,

+ 7 - 2
dashboard/src/components/porter-form/types.ts

@@ -85,7 +85,7 @@ export interface KeyValueArrayField extends GenericInputField {
   settings?: {
     options?: {
       enable_synced_env_groups: boolean;
-    },
+    };
     type: "env" | "normal";
   };
 }
@@ -119,6 +119,10 @@ export interface VariableField extends GenericInputField {
   };
 }
 
+export interface CronField extends GenericInputField {
+  type: "cron";
+}
+
 export type FormField =
   | HeadingField
   | SubtitleField
@@ -130,7 +134,8 @@ export type FormField =
   | ServiceIPListField
   | ResourceListField
   | VeleroBackupField
-  | VariableField;
+  | VariableField
+  | CronField;
 
 export interface ShowIfAnd {
   and: ShowIf[];

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

@@ -39,7 +39,7 @@ class Dashboard extends Component<PropsType, StateType> {
     infras: [] as InfraType[],
     pressingCtrl: false,
     pressingK: false,
-    showFormDebugger: false,
+    showFormDebugger: true,
   };
 
   refreshInfras = () => {