|
@@ -13,6 +13,9 @@ import { useRouting } from "shared/routing";
|
|
|
import { useHistory, useLocation, useParams } from "react-router";
|
|
import { useHistory, useLocation, useParams } from "react-router";
|
|
|
import { deployments, pull_requests } from "../mocks";
|
|
import { deployments, pull_requests } from "../mocks";
|
|
|
import PullRequestCard from "./PullRequestCard";
|
|
import PullRequestCard from "./PullRequestCard";
|
|
|
|
|
+import DynamicLink from "components/DynamicLink";
|
|
|
|
|
+import { PreviewEnvironmentsHeader } from "../components/PreviewEnvironmentsHeader";
|
|
|
|
|
+import SearchBar from "components/SearchBar";
|
|
|
|
|
|
|
|
const AvailableStatusFilters = [
|
|
const AvailableStatusFilters = [
|
|
|
"all",
|
|
"all",
|
|
@@ -30,6 +33,7 @@ const DeploymentList = () => {
|
|
|
const [hasError, setHasError] = useState(false);
|
|
const [hasError, setHasError] = useState(false);
|
|
|
const [deploymentList, setDeploymentList] = useState<PRDeployment[]>([]);
|
|
const [deploymentList, setDeploymentList] = useState<PRDeployment[]>([]);
|
|
|
const [pullRequests, setPullRequests] = useState<PullRequest[]>([]);
|
|
const [pullRequests, setPullRequests] = useState<PullRequest[]>([]);
|
|
|
|
|
+ const [searchValue, setSearchValue] = useState("");
|
|
|
|
|
|
|
|
const [
|
|
const [
|
|
|
statusSelectorVal,
|
|
statusSelectorVal,
|
|
@@ -130,30 +134,46 @@ const DeploymentList = () => {
|
|
|
handleRefresh();
|
|
handleRefresh();
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
+ const searchFilter = (value: string | number) => {
|
|
|
|
|
+ const val = String(value);
|
|
|
|
|
+
|
|
|
|
|
+ return val.toLowerCase().includes(searchValue);
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
const filteredDeployments = useMemo(() => {
|
|
const filteredDeployments = useMemo(() => {
|
|
|
// Only filter out inactive when status filter is "active"
|
|
// Only filter out inactive when status filter is "active"
|
|
|
if (statusSelectorVal === "active") {
|
|
if (statusSelectorVal === "active") {
|
|
|
- return deploymentList.filter((d) => {
|
|
|
|
|
- return d.status !== "inactive";
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ return deploymentList
|
|
|
|
|
+ .filter((d) => {
|
|
|
|
|
+ return d.status !== "inactive";
|
|
|
|
|
+ })
|
|
|
|
|
+ .filter((d) => {
|
|
|
|
|
+ return Boolean(Object.values(d).find(searchFilter));
|
|
|
|
|
+ });
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (statusSelectorVal === "inactive") {
|
|
if (statusSelectorVal === "inactive") {
|
|
|
- return deploymentList.filter((d) => {
|
|
|
|
|
- return d.status === "inactive";
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ return deploymentList
|
|
|
|
|
+ .filter((d) => {
|
|
|
|
|
+ return d.status === "inactive";
|
|
|
|
|
+ })
|
|
|
|
|
+ .filter((d) => {
|
|
|
|
|
+ return Boolean(Object.values(d).find(searchFilter));
|
|
|
|
|
+ });
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
return deploymentList;
|
|
return deploymentList;
|
|
|
- }, [statusSelectorVal, deploymentList]);
|
|
|
|
|
|
|
+ }, [statusSelectorVal, deploymentList, searchValue]);
|
|
|
|
|
|
|
|
const filteredPullRequests = useMemo(() => {
|
|
const filteredPullRequests = useMemo(() => {
|
|
|
if (statusSelectorVal !== "inactive") {
|
|
if (statusSelectorVal !== "inactive") {
|
|
|
return [];
|
|
return [];
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- return pullRequests;
|
|
|
|
|
- }, [pullRequests, statusSelectorVal]);
|
|
|
|
|
|
|
+ return pullRequests.filter((pr) => {
|
|
|
|
|
+ return Boolean(Object.values(pr).find(searchFilter));
|
|
|
|
|
+ });
|
|
|
|
|
+ }, [pullRequests, statusSelectorVal, searchValue]);
|
|
|
|
|
|
|
|
const renderDeploymentList = () => {
|
|
const renderDeploymentList = () => {
|
|
|
if (isLoading) {
|
|
if (isLoading) {
|
|
@@ -213,13 +233,12 @@ const DeploymentList = () => {
|
|
|
|
|
|
|
|
return (
|
|
return (
|
|
|
<>
|
|
<>
|
|
|
|
|
+ <PreviewEnvironmentsHeader />
|
|
|
<Flex>
|
|
<Flex>
|
|
|
- <i
|
|
|
|
|
- className="material-icons"
|
|
|
|
|
- onClick={() => pushQueryParams({}, ["status_filter", "repository"])}
|
|
|
|
|
- >
|
|
|
|
|
|
|
+ <BackButton to={"/preview-environments"} className="material-icons">
|
|
|
keyboard_backspace
|
|
keyboard_backspace
|
|
|
- </i>
|
|
|
|
|
|
|
+ </BackButton>
|
|
|
|
|
+
|
|
|
<Icon
|
|
<Icon
|
|
|
src="https://git-scm.com/images/logos/downloads/Git-Icon-1788C.png"
|
|
src="https://git-scm.com/images/logos/downloads/Git-Icon-1788C.png"
|
|
|
alt="git repository icon"
|
|
alt="git repository icon"
|
|
@@ -231,6 +250,16 @@ const DeploymentList = () => {
|
|
|
<RefreshButton color={"#7d7d81"} onClick={handleRefresh}>
|
|
<RefreshButton color={"#7d7d81"} onClick={handleRefresh}>
|
|
|
<i className="material-icons">refresh</i>
|
|
<i className="material-icons">refresh</i>
|
|
|
</RefreshButton>
|
|
</RefreshButton>
|
|
|
|
|
+ <SearchRow>
|
|
|
|
|
+ <i className="material-icons">search</i>
|
|
|
|
|
+ <SearchInput
|
|
|
|
|
+ value={searchValue}
|
|
|
|
|
+ onChange={(e: any) => {
|
|
|
|
|
+ setSearchValue(e.target.value);
|
|
|
|
|
+ }}
|
|
|
|
|
+ placeholder="Search"
|
|
|
|
|
+ />
|
|
|
|
|
+ </SearchRow>
|
|
|
<Selector
|
|
<Selector
|
|
|
activeValue={statusSelectorVal}
|
|
activeValue={statusSelectorVal}
|
|
|
setActiveValue={handleStatusFilterChange}
|
|
setActiveValue={handleStatusFilterChange}
|
|
@@ -275,16 +304,16 @@ const mockRequest = () =>
|
|
|
const Flex = styled.div`
|
|
const Flex = styled.div`
|
|
|
display: flex;
|
|
display: flex;
|
|
|
align-items: center;
|
|
align-items: center;
|
|
|
|
|
+`;
|
|
|
|
|
|
|
|
- > i {
|
|
|
|
|
- cursor: pointer;
|
|
|
|
|
- font-size: 24px;
|
|
|
|
|
- color: #969fbbaa;
|
|
|
|
|
- padding: 3px;
|
|
|
|
|
- border-radius: 100px;
|
|
|
|
|
- :hover {
|
|
|
|
|
- background: #ffffff11;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+const BackButton = styled(DynamicLink)`
|
|
|
|
|
+ cursor: pointer;
|
|
|
|
|
+ font-size: 24px;
|
|
|
|
|
+ color: #969fbbaa;
|
|
|
|
|
+ padding: 3px;
|
|
|
|
|
+ border-radius: 100px;
|
|
|
|
|
+ :hover {
|
|
|
|
|
+ background: #ffffff11;
|
|
|
}
|
|
}
|
|
|
`;
|
|
`;
|
|
|
|
|
|
|
@@ -356,15 +385,6 @@ const Container = styled.div`
|
|
|
padding-bottom: 120px;
|
|
padding-bottom: 120px;
|
|
|
`;
|
|
`;
|
|
|
|
|
|
|
|
-const ControlRow = styled.div`
|
|
|
|
|
- display: flex;
|
|
|
|
|
- margin-left: auto;
|
|
|
|
|
- justify-content: space-between;
|
|
|
|
|
- align-items: center;
|
|
|
|
|
- margin-bottom: 35px;
|
|
|
|
|
- padding-left: 0px;
|
|
|
|
|
-`;
|
|
|
|
|
-
|
|
|
|
|
const EventsGrid = styled.div`
|
|
const EventsGrid = styled.div`
|
|
|
display: grid;
|
|
display: grid;
|
|
|
grid-row-gap: 20px;
|
|
grid-row-gap: 20px;
|
|
@@ -380,25 +400,37 @@ const StyledStatusSelector = styled.div`
|
|
|
}
|
|
}
|
|
|
`;
|
|
`;
|
|
|
|
|
|
|
|
-const Header = styled.div`
|
|
|
|
|
- font-weight: 500;
|
|
|
|
|
- color: #aaaabb;
|
|
|
|
|
- font-size: 16px;
|
|
|
|
|
- margin-bottom: 15px;
|
|
|
|
|
- width: 50%;
|
|
|
|
|
-`;
|
|
|
|
|
-
|
|
|
|
|
-const Subheader = styled.div`
|
|
|
|
|
- width: 50%;
|
|
|
|
|
|
|
+const SearchInput = styled.input`
|
|
|
|
|
+ outline: none;
|
|
|
|
|
+ border: none;
|
|
|
|
|
+ font-size: 13px;
|
|
|
|
|
+ background: none;
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ color: white;
|
|
|
|
|
+ padding: 0;
|
|
|
|
|
+ height: 20px;
|
|
|
`;
|
|
`;
|
|
|
|
|
|
|
|
-const Label = styled.div`
|
|
|
|
|
|
|
+const SearchRow = styled.div`
|
|
|
display: flex;
|
|
display: flex;
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ font-size: 13px;
|
|
|
|
|
+ color: #ffffff55;
|
|
|
|
|
+ border-radius: 4px;
|
|
|
|
|
+ user-select: none;
|
|
|
align-items: center;
|
|
align-items: center;
|
|
|
- margin-right: 12px;
|
|
|
|
|
|
|
+ padding: 10px 0px;
|
|
|
|
|
+ min-width: 300px;
|
|
|
|
|
+ max-width: min-content;
|
|
|
|
|
+ max-height: 35px;
|
|
|
|
|
+ background: #ffffff11;
|
|
|
|
|
+ margin-right: 15px;
|
|
|
|
|
|
|
|
- > i {
|
|
|
|
|
- margin-right: 8px;
|
|
|
|
|
- font-size: 18px;
|
|
|
|
|
|
|
+ i {
|
|
|
|
|
+ width: 18px;
|
|
|
|
|
+ height: 18px;
|
|
|
|
|
+ margin-left: 12px;
|
|
|
|
|
+ margin-right: 12px;
|
|
|
|
|
+ font-size: 20px;
|
|
|
}
|
|
}
|
|
|
`;
|
|
`;
|