Explorar el Código

sort env groups and allow multi selects (#4487)

Co-authored-by: jusrhee <justin@porter.run>
d-g-town hace 2 años
padre
commit
3341471aca

+ 45 - 47
dashboard/src/main/home/app-dashboard/validate-apply/app-settings/EnvGroupModal.tsx

@@ -1,13 +1,12 @@
 import React, {
   useCallback,
-  useEffect,
   useMemo,
   useState,
   type Dispatch,
   type SetStateAction,
 } from "react";
-import { UseFieldArrayAppend, useFormContext } from "react-hook-form";
-import styled, { css } from "styled-components";
+import { useFormContext } from "react-hook-form";
+import styled from "styled-components";
 import { type IterableElement } from "type-fest";
 
 import Button from "components/porter/Button";
@@ -16,9 +15,6 @@ import Spacer from "components/porter/Spacer";
 import Text from "components/porter/Text";
 import { type PorterAppFormData } from "lib/porter-apps";
 
-import doppler from "assets/doppler.png";
-import sliders from "assets/sliders.svg";
-
 import EnvGroupRow from "./EnvGroupRow";
 import { type PopulatedEnvGroup } from "./types";
 
@@ -29,28 +25,54 @@ type Props = {
 };
 
 const EnvGroupModal: React.FC<Props> = ({ append, setOpen, baseEnvGroups }) => {
-  const [selectedEnvGroup, setSelectedEnvGroup] =
-    useState<PopulatedEnvGroup | null>(null);
+  const [selectedEnvGroups, setSelectedEnvGroups] = useState<
+    PopulatedEnvGroup[]
+  >([]);
 
   const { watch } = useFormContext<PorterAppFormData>();
   const envGroups = watch("app.envGroups", []);
 
   const onSubmit = useCallback(() => {
-    if (selectedEnvGroup) {
+    selectedEnvGroups.forEach((selectedEnvGroup): void => {
       append({
         name: selectedEnvGroup.name,
         version: selectedEnvGroup.latest_version,
       });
-      setOpen(false);
-    }
-  }, [selectedEnvGroup]);
+    });
+    setOpen(false);
+  }, [selectedEnvGroups]);
 
   const remainingEnvGroupOptions = useMemo(() => {
-    return baseEnvGroups.filter((eg) => {
-      return !envGroups.some((eg2) => eg2.name === eg.name);
-    });
+    return baseEnvGroups
+      .filter((eg) => {
+        return !envGroups.some((eg2) => eg2.name === eg.name);
+      })
+      .sort((a, b) => a.name.localeCompare(b.name));
   }, [envGroups, baseEnvGroups]);
 
+  const addToSelectedEnvGroups = (envGroup: PopulatedEnvGroup): void => {
+    if (isInSelectedEnvGroups(envGroup)) {
+      return;
+    }
+    setSelectedEnvGroups([...selectedEnvGroups, envGroup]);
+  };
+
+  const removeFromSelectedEnvGroups = (envGroup: PopulatedEnvGroup): void => {
+    if (isInSelectedEnvGroups(envGroup)) {
+      setSelectedEnvGroups(
+        selectedEnvGroups.filter((selected) => selected.name !== envGroup.name)
+      );
+    }
+  };
+
+  const isInSelectedEnvGroups = (envGroup: PopulatedEnvGroup): boolean => {
+    return (
+      selectedEnvGroups.findIndex(
+        (selected) => selected.name === envGroup.name
+      ) !== -1
+    );
+  };
+
   return (
     <Modal
       closeModal={() => {
@@ -72,15 +94,15 @@ const EnvGroupModal: React.FC<Props> = ({ append, setOpen, baseEnvGroups }) => {
                   <EnvGroupRow envGroup={eg} maxHeight="300px" noLink />
                   <SelectedIndicator
                     onClick={() => {
-                      setSelectedEnvGroup(eg);
+                      if (isInSelectedEnvGroups(eg)) {
+                        removeFromSelectedEnvGroups(eg);
+                      } else {
+                        addToSelectedEnvGroups(eg);
+                      }
                     }}
-                    isSelected={
-                      Boolean(selectedEnvGroup) &&
-                      selectedEnvGroup?.name === eg.name
-                    }
+                    isSelected={isInSelectedEnvGroups(eg)}
                   >
-                    {Boolean(selectedEnvGroup) &&
-                    selectedEnvGroup?.name === eg.name ? (
+                    {isInSelectedEnvGroups(eg) ? (
                       <Check className="material-icons">check</Check>
                     ) : (
                       <i className="material-icons">add</i>
@@ -95,7 +117,7 @@ const EnvGroupModal: React.FC<Props> = ({ append, setOpen, baseEnvGroups }) => {
         <Text>No selectable Env Groups</Text>
       )}
       <Spacer y={1} />
-      <Button onClick={onSubmit} disabled={!selectedEnvGroup}>
+      <Button onClick={onSubmit} disabled={!selectedEnvGroups}>
         Load env group
       </Button>
     </Modal>
@@ -151,30 +173,6 @@ const EnvGroupList = styled.div`
   gap: 15px;
 `;
 
-const SidebarSection = styled.section<{ $expanded?: boolean }>`
-  height: 100%;
-  overflow-y: auto;
-  ${(props) =>
-    props.$expanded &&
-    css`
-      grid-column: span 2;
-    `}
-`;
-
-const GroupEnvPreview = styled.pre`
-  font-family: monospace;
-  margin: 0 0 10px 0;
-  white-space: pre-line;
-  word-break: break-word;
-  user-select: text;
-  .key {
-    color: white;
-  }
-  .value {
-    color: #3a48ca;
-  }
-`;
-
 const ScrollableContainer = styled.div`
   flex: 1;
   overflow-y: auto;