Bladeren bron

refactor: sanitize branch deploys

Soham Parekh 3 jaren geleden
bovenliggende
commit
76e852375b

+ 185 - 37
dashboard/src/main/home/cluster-dashboard/preview-environments/environments/CreateBranchEnvironment.tsx

@@ -1,32 +1,38 @@
-import React, { useContext, useState } from "react";
+import React, { useContext, useMemo, useState } from "react";
 import styled from "styled-components";
 import { Context } from "shared/Context";
 import { Environment } from "../types";
 import Helper from "components/form-components/Helper";
 import api from "shared/api";
-import { useMutation, useQuery } from "@tanstack/react-query";
+import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
 import { validatePorterYAML } from "../utils";
 import Banner from "components/Banner";
 import { useRouting } from "shared/routing";
 import PorterYAMLErrorsModal from "../components/PorterYAMLErrorsModal";
 import Placeholder from "components/Placeholder";
-import BranchFilterSelector from "../components/BranchFilterSelector";
 import _ from "lodash";
 import Loading from "components/Loading";
+import { EllipsisTextWrapper } from "../components/styled";
+import pr_icon from "assets/pull_request_icon.svg";
+import { search } from "shared/search";
+import RadioFilter from "components/RadioFilter";
+import sort from "assets/sort.svg";
 
 interface Props {
   environmentID: string;
 }
 
 const CreateBranchEnvironment = ({ environmentID }: Props) => {
+  const queryClient = useQueryClient();
   const router = useRouting();
+  const [searchValue, setSearchValue] = useState("");
+  const [sortOrder, setSortOrder] = useState("Newest");
   const [loading, setLoading] = useState<boolean>(false);
   const [showErrorsModal, setShowErrorsModal] = useState<boolean>(false);
   const {
     currentProject,
     currentCluster,
     setCurrentError,
-    setCurrentModal,
   } = useContext(Context);
 
   const {
@@ -78,13 +84,11 @@ const CreateBranchEnvironment = ({ environmentID }: Props) => {
   );
 
   const environmentGitDeployBranches = environment?.git_deploy_branches ?? [];
-  const [selectedBranches, setSelectedBranches] = useState<string[]>(
-    environmentGitDeployBranches
-  );
+  const [selectedBranch, setSelectedBranch] = useState<string>(null);
   const [porterYAMLErrors, setPorterYAMLErrors] = useState<string[]>([]);
 
   const handleRowItemClick = async (branch: string) => {
-    //setSelectedBranch(branch);
+    setSelectedBranch(branch);
     setLoading(true);
 
     const res = await validatePorterYAML({
@@ -99,6 +103,28 @@ const CreateBranchEnvironment = ({ environmentID }: Props) => {
     setLoading(false);
   };
 
+  const handleRefresh = () => {
+    queryClient.invalidateQueries({
+      queryKey: ["branches"],
+    });
+  };
+
+  const filteredBranches = useMemo(() => {
+    const filteredBySearch = search<string>(
+      branches ?? [],
+      searchValue,
+      {
+        isCaseSensitive: false,
+      }
+    );
+
+    switch (sortOrder) {
+      case "Alphabetical":
+      default:
+        return _.sortBy(filteredBySearch);
+    }
+  }, [branches, searchValue, sortOrder]);
+
   const updateDeployBranchesMutation = useMutation({
     mutationFn: () => {
       return api.updateEnvironment(
@@ -106,7 +132,12 @@ const CreateBranchEnvironment = ({ environmentID }: Props) => {
         {
           disable_new_comments: environment.new_comments_disabled,
           ...environment,
-          git_deploy_branches: selectedBranches,
+          git_deploy_branches: _.uniq(
+            [
+              ...environmentGitDeployBranches,
+              selectedBranch,
+            ]
+          ),
         },
         {
           project_id: currentProject.id,
@@ -150,23 +181,66 @@ const CreateBranchEnvironment = ({ environmentID }: Props) => {
         Select a branch to preview. Branches must contain a{" "}
         <Code>porter.yaml</Code> file.
       </Helper>
+      <FlexRow>
+        <Flex>
+          <SearchRowWrapper>
+            <SearchBarWrapper>
+              <i className="material-icons">search</i>
+              <SearchInput
+                value={searchValue}
+                onChange={(e: any) => {
+                  setSelectedBranch(undefined);
+                  setPorterYAMLErrors([]);
+                  setSearchValue(e.target.value);
+                }}
+                placeholder="Search"
+              />
+            </SearchBarWrapper>
+          </SearchRowWrapper>
+        </Flex>
+        <Flex>
+          <RefreshButton color={"#7d7d81"} onClick={handleRefresh}>
+            <i className="material-icons">refresh</i>
+          </RefreshButton>
+          <RadioFilter
+            icon={sort}
+            selected={sortOrder}
+            setSelected={setSortOrder}
+            options={[
+              { label: "Alphabetical", value: "Alphabetical" },
+            ]}
+            name="Sort"
+          />
+        </Flex>
+      </FlexRow>
       <Br height="10px" />
-      <BranchFilterSelector
-        onChange={(branches) => setSelectedBranches(branches)}
-        options={branches}
-        value={selectedBranches}
-        showLoading={branchesLoading}
-        multiSelect={false}
-      />
-      {/* {showErrorsModal && selectedBranch ? (
+      <BranchList>
+      {
+        (filteredBranches ?? []).map((branch, i) => (
+          <BranchRow
+            onClick={() => handleRowItemClick(branch)}
+            isLast={i === filteredBranches.length - 1}
+            isSelected={branch === selectedBranch}
+          >
+            <BranchName>
+              <BranchIcon src={pr_icon} alt="branch icon" />
+                <EllipsisTextWrapper tooltipText={branch}>
+                  {branch}
+                </EllipsisTextWrapper>
+            </BranchName>
+          </BranchRow>
+        ))
+      }
+      </BranchList>
+      {showErrorsModal && selectedBranch ? (
         <PorterYAMLErrorsModal
           errors={porterYAMLErrors}
           onClose={() => setShowErrorsModal(false)}
           repo={environment.git_repo_name + "/" + environment.git_repo_owner}
           branch={selectedBranch}
         />
-      ) : null} */}
-      {/* {selectedBranch && porterYAMLErrors.length ? (
+      ) : null}
+      {selectedBranch && porterYAMLErrors.length ? (
         <ValidationErrorBannerWrapper>
           <Banner type="warning">
             We found some errors in the porter.yaml file in the&nbsp;
@@ -176,18 +250,20 @@ const CreateBranchEnvironment = ({ environmentID }: Props) => {
             </LearnMoreButton>
           </Banner>
         </ValidationErrorBannerWrapper>
-      ) : null} */}
+      ) : null}
       <CreatePreviewDeploymentWrapper>
         <SubmitButton
           onClick={() => updateDeployBranchesMutation.mutate()}
           disabled={
             updateDeployBranchesMutation.isLoading || loading
-            //|| porterYAMLErrors.length > 0
+            || porterYAMLErrors.length > 0 || !selectedBranch
           }
         >
-          Update branch deployments
+          {
+            updateDeployBranchesMutation.isLoading ? 'Creating...' : 'Create Preview Deployment'
+          }
         </SubmitButton>
-        {/* {selectedBranch && porterYAMLErrors.length ? (
+        {selectedBranch && porterYAMLErrors.length ? (
           <RevalidatePorterYAMLSpanWrapper>
             Please fix your porter.yaml file to continue.{" "}
             <RevalidateSpan
@@ -205,7 +281,7 @@ const CreateBranchEnvironment = ({ environmentID }: Props) => {
               Refresh
             </RevalidateSpan>
           </RevalidatePorterYAMLSpanWrapper>
-        ) : null} */}
+        ) : null}
       </CreatePreviewDeploymentWrapper>
     </>
   );
@@ -213,7 +289,14 @@ const CreateBranchEnvironment = ({ environmentID }: Props) => {
 
 export default CreateBranchEnvironment;
 
-const PullRequestRow = styled.div<{ isLast?: boolean; isSelected?: boolean }>`
+const BranchList = styled.div`
+  border: 1px solid #494b4f;
+  border-radius: 5px;
+  overflow: hidden;
+  margin-top: 33px;
+`;
+
+const BranchRow = styled.div<{ isLast?: boolean; isSelected?: boolean }>`
   width: 100%;
   padding: 15px;
   cursor: pointer;
@@ -224,6 +307,41 @@ const PullRequestRow = styled.div<{ isLast?: boolean; isSelected?: boolean }>`
   }
 `;
 
+const SearchRowWrapper = styled.div`
+  display: flex;
+  align-items: center;
+  height: 30px;
+  margin-right: 10px;
+  background: #26292e;
+  border-radius: 5px;
+  border: 1px solid #aaaabb33;
+  border-radius: 5px;
+  width: 250px;
+`;
+
+const SearchBarWrapper = styled.div`
+  display: flex;
+  flex: 1;
+
+  > i {
+    color: #aaaabb;
+    padding-top: 1px;
+    margin-left: 8px;
+    font-size: 16px;
+    margin-right: 8px;
+  }
+`;
+
+const BranchName = styled.div`
+  font-family: "Work Sans", sans-serif;
+  font-weight: 500;
+  color: #ffffff;
+  display: flex;
+  font-size: 14px;
+  align-items: center;
+  margin-bottom: 10px;
+`;
+
 const Code = styled.span`
   font-family: monospace; ;
 `;
@@ -233,6 +351,14 @@ const Flex = styled.div`
   align-items: center;
 `;
 
+const FlexRow = styled.div`
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  flex-wrap: wrap;
+  gap: 10px;
+`;
+
 const DeploymentImageContainer = styled.div`
   height: 20px;
   font-size: 13px;
@@ -279,7 +405,7 @@ const MergeInfo = styled.div`
   }
 `;
 
-const PRIcon = styled.img`
+const BranchIcon = styled.img`
   font-size: 20px;
   height: 16px;
   margin-right: 10px;
@@ -287,16 +413,6 @@ const PRIcon = styled.img`
   opacity: 50%;
 `;
 
-const PRName = styled.div`
-  font-family: "Work Sans", sans-serif;
-  font-weight: 500;
-  color: #ffffff;
-  display: flex;
-  font-size: 14px;
-  align-items: center;
-  margin-bottom: 10px;
-`;
-
 const SubmitButton = styled.div`
   display: flex;
   flex-direction: row;
@@ -338,6 +454,16 @@ const SubmitButton = styled.div`
   }
 `;
 
+const SearchInput = styled.input`
+  outline: none;
+  border: none;
+  font-size: 13px;
+  background: none;
+  width: 100%;
+  color: white;
+  height: 100%;
+`;
+
 const Br = styled.div<{ height: string }>`
   width: 100%;
   height: ${(props) => props.height || "2px"};
@@ -349,7 +475,7 @@ const ValidationErrorBannerWrapper = styled.div`
 
 const LearnMoreButton = styled.div`
   text-decoration: underline;
-  fontweight: bold;
+  font-weight: bold;
   cursor: pointer;
 `;
 
@@ -371,3 +497,25 @@ const RevalidateSpan = styled.span`
   text-decoration: underline;
   cursor: pointer;
 `;
+
+const RefreshButton = styled.button`
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  color: ${(props: { color: string }) => props.color};
+  cursor: pointer;
+  border: none;
+  width: 30px;
+  height: 30px;
+  margin-right: 15px;
+  background: none;
+  border-radius: 50%;
+  margin-left: 10px;
+  > i {
+    font-size: 20px;
+  }
+  :hover {
+    background-color: rgb(97 98 102 / 44%);
+    color: white;
+  }
+`;

+ 1 - 1
dashboard/src/main/home/cluster-dashboard/preview-environments/environments/CreatePREnvironment.tsx

@@ -457,7 +457,7 @@ const ValidationErrorBannerWrapper = styled.div`
 
 const LearnMoreButton = styled.div`
   text-decoration: underline;
-  fontweight: bold;
+  font-weight: bold;
   cursor: pointer;
 `;