|
|
@@ -5,21 +5,12 @@ import api from "shared/api";
|
|
|
import { useHistory, useLocation, useRouteMatch } from "react-router";
|
|
|
import { getQueryParam } from "shared/routing";
|
|
|
import styled from "styled-components";
|
|
|
-import SortSelector from "../../SortSelector";
|
|
|
+import { integrationList } from "shared/common";
|
|
|
import ButtonEnablePREnvironments from "./components/ButtonEnablePREnvironments";
|
|
|
import ConnectNewRepo from "./components/ConnectNewRepo";
|
|
|
import Loading from "components/Loading";
|
|
|
import pr_icon from "assets/pull_request_icon.svg";
|
|
|
|
|
|
-export type Environment = {
|
|
|
- id: number;
|
|
|
- url: string;
|
|
|
- pr_link: string;
|
|
|
- status: string;
|
|
|
- namespace: string;
|
|
|
- actions_link: string;
|
|
|
-};
|
|
|
-
|
|
|
export type PRDeployment = {
|
|
|
id: number,
|
|
|
subdomain: string,
|
|
|
@@ -27,6 +18,20 @@ export type PRDeployment = {
|
|
|
environment_id: number,
|
|
|
pull_request_id: number,
|
|
|
namespace: string,
|
|
|
+ gh_pr_name: string,
|
|
|
+ gh_repo_owner: string,
|
|
|
+ gh_repo_name: string,
|
|
|
+ gh_commit_sha: string,
|
|
|
+}
|
|
|
+
|
|
|
+export type Environment = {
|
|
|
+ id: Number,
|
|
|
+ project_id: number,
|
|
|
+ cluster_id: number,
|
|
|
+ git_installation_id: number,
|
|
|
+ name: string,
|
|
|
+ git_repo_owner: string,
|
|
|
+ git_repo_name: string,
|
|
|
}
|
|
|
|
|
|
export const capitalize = (s: string) => {
|
|
|
@@ -36,7 +41,9 @@ export const capitalize = (s: string) => {
|
|
|
const EnvironmentList = () => {
|
|
|
const [isLoading, setIsLoading] = useState(true);
|
|
|
const [hasError, setHasError] = useState(false);
|
|
|
- const [environmentList, setEnvironmentList] = useState<PRDeployment[]>([]);
|
|
|
+ const [environmentList, setEnvironmentList] = useState<Environment[]>([]);
|
|
|
+ const [deploymentList, setDeploymentList] = useState<PRDeployment[]>([]);
|
|
|
+ const [showRepoTooltip, setShowRepoTooltip] = useState(false);
|
|
|
const [showConnectRepoFlow, setShowConnectRepoFlow] = useState(false);
|
|
|
const { currentProject, currentCluster, setCurrentError } = useContext(
|
|
|
Context
|
|
|
@@ -48,6 +55,39 @@ const EnvironmentList = () => {
|
|
|
const location = useLocation();
|
|
|
const history = useHistory();
|
|
|
|
|
|
+ useEffect(() => {
|
|
|
+ let isSubscribed = true;
|
|
|
+ api
|
|
|
+ .listEnvironments(
|
|
|
+ "<token>",
|
|
|
+ {},
|
|
|
+ {
|
|
|
+ project_id: currentProject.id,
|
|
|
+ cluster_id: currentCluster.id,
|
|
|
+ }
|
|
|
+ ).then(({ data }) => {
|
|
|
+ if (!isSubscribed) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!Array.isArray(data)) {
|
|
|
+ throw Error("Data is not an array");
|
|
|
+ }
|
|
|
+
|
|
|
+ setEnvironmentList(data);
|
|
|
+ })
|
|
|
+ .catch((err) => {
|
|
|
+ console.error(err);
|
|
|
+ if (isSubscribed) {
|
|
|
+ setHasError(true);
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ return () => {
|
|
|
+ isSubscribed = false;
|
|
|
+ };
|
|
|
+ }, []);
|
|
|
+
|
|
|
useEffect(() => {
|
|
|
let isSubscribed = true;
|
|
|
// TODO: Replace get mock data by endpoint
|
|
|
@@ -68,15 +108,13 @@ const EnvironmentList = () => {
|
|
|
throw Error("Data is not an array");
|
|
|
}
|
|
|
|
|
|
- console.log('retrieved', data)
|
|
|
-
|
|
|
- setEnvironmentList(data);
|
|
|
+ setDeploymentList(data);
|
|
|
})
|
|
|
.catch((err) => {
|
|
|
console.error(err);
|
|
|
if (isSubscribed) {
|
|
|
setHasError(true);
|
|
|
- setEnvironmentList([]);
|
|
|
+ setDeploymentList([]);
|
|
|
}
|
|
|
})
|
|
|
.finally(() => {
|
|
|
@@ -116,7 +154,11 @@ const EnvironmentList = () => {
|
|
|
}
|
|
|
|
|
|
if (hasError) {
|
|
|
- return <>Unexpected error occured, please try again later</>;
|
|
|
+ return(
|
|
|
+ <Placeholder>
|
|
|
+ Error
|
|
|
+ </Placeholder>
|
|
|
+ )
|
|
|
}
|
|
|
|
|
|
if (!environmentList.length) {
|
|
|
@@ -127,6 +169,74 @@ const EnvironmentList = () => {
|
|
|
);
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+
|
|
|
+ let renderDeploymentList = () => {
|
|
|
+ if (!deploymentList.length) {
|
|
|
+ return (
|
|
|
+ <Placeholder>
|
|
|
+ No preview apps have been found. Open a PR to create a new preview app.
|
|
|
+ </Placeholder>
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ return deploymentList.map((d) => {
|
|
|
+ let repository = `${d.gh_repo_owner}/${d.gh_repo_name}`
|
|
|
+ return (
|
|
|
+ <EnvironmentCard key={d.id}>
|
|
|
+ <DataContainer>
|
|
|
+ <PRName>
|
|
|
+ <PRIcon src={pr_icon} alt="pull request icon" />
|
|
|
+ {d.gh_pr_name}
|
|
|
+ </PRName>
|
|
|
+
|
|
|
+ <PRWrapper>
|
|
|
+ <StatusContainer>
|
|
|
+ <Status>
|
|
|
+ <StatusDot status={d.status} />
|
|
|
+ {capitalize(d.status)}
|
|
|
+ </Status>
|
|
|
+ </StatusContainer>
|
|
|
+ <DeploymentImageContainer>
|
|
|
+ <DeploymentTypeIcon src={integrationList.repo.icon} />
|
|
|
+ <RepositoryName
|
|
|
+ onMouseOver={() => {
|
|
|
+ setShowRepoTooltip(true);
|
|
|
+ }}
|
|
|
+ onMouseOut={() => {
|
|
|
+ setShowRepoTooltip(false);
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ {repository}
|
|
|
+ </RepositoryName>
|
|
|
+ {showRepoTooltip && <Tooltip>{repository}</Tooltip>}
|
|
|
+ </DeploymentImageContainer>
|
|
|
+ </PRWrapper>
|
|
|
+
|
|
|
+
|
|
|
+ </DataContainer>
|
|
|
+ <Flex>
|
|
|
+ <RowButton
|
|
|
+ to={`${currentUrl}/pr-env-detail/${d.namespace}`}
|
|
|
+ key={d.id}
|
|
|
+ >
|
|
|
+ <i className="material-icons-outlined">info</i>
|
|
|
+ Details
|
|
|
+ </RowButton>
|
|
|
+ <RowButton
|
|
|
+ to={d.subdomain}
|
|
|
+ key={d.subdomain}
|
|
|
+ target="_blank"
|
|
|
+ >
|
|
|
+ <i className="material-icons">open_in_new</i>
|
|
|
+ View Live
|
|
|
+ </RowButton>
|
|
|
+ </Flex>
|
|
|
+ </EnvironmentCard>
|
|
|
+ );
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
return (
|
|
|
<Container>
|
|
|
<ControlRow>
|
|
|
@@ -144,52 +254,38 @@ const EnvironmentList = () => {
|
|
|
</SortFilterWrapper>
|
|
|
</ControlRow>
|
|
|
<EventsGrid>
|
|
|
- {environmentList.map((env) => {
|
|
|
- return (
|
|
|
- <EnvironmentCard key={env.id}>
|
|
|
- <DataContainer>
|
|
|
- <PRName>
|
|
|
- <PRIcon src={pr_icon} alt="pull request icon" />
|
|
|
- {env.subdomain}
|
|
|
- </PRName>
|
|
|
- <StatusContainer>
|
|
|
- <Status>
|
|
|
- <StatusDot status={env.status} />
|
|
|
- {capitalize(env.status)}
|
|
|
- </Status>
|
|
|
- </StatusContainer>
|
|
|
- </DataContainer>
|
|
|
- <Flex>
|
|
|
- <RowButton
|
|
|
- to={`${currentUrl}/pr-env-detail/${env.namespace}`}
|
|
|
- key={env.id}
|
|
|
- >
|
|
|
- <i className="material-icons-outlined">info</i>
|
|
|
- Details
|
|
|
- </RowButton>
|
|
|
- <RowButton
|
|
|
- to={env.subdomain}
|
|
|
- key={env.subdomain}
|
|
|
- target="_blank"
|
|
|
- >
|
|
|
- <i className="material-icons">open_in_new</i>
|
|
|
- View Live
|
|
|
- </RowButton>
|
|
|
- </Flex>
|
|
|
- </EnvironmentCard>
|
|
|
- );
|
|
|
- })}
|
|
|
+ {renderDeploymentList()}
|
|
|
</EventsGrid>
|
|
|
</Container>
|
|
|
);
|
|
|
};
|
|
|
|
|
|
export default EnvironmentList;
|
|
|
+const PRWrapper = styled.div`
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+`
|
|
|
|
|
|
const Placeholder = styled.div`
|
|
|
- height: 300px;
|
|
|
-`;
|
|
|
+ width: 100%;
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ color: #ffffff44;
|
|
|
+ background: #26282f;
|
|
|
+ border-radius: 5px;
|
|
|
+ height: 370px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ color: #ffffff44;
|
|
|
+ font-size: 13px;
|
|
|
|
|
|
+ > i {
|
|
|
+ font-size: 16px;
|
|
|
+ margin-right: 12px;
|
|
|
+ }
|
|
|
+`;
|
|
|
const Flex = styled.div`
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
@@ -376,3 +472,60 @@ const StatusDot = styled.div`
|
|
|
border-radius: 20px;
|
|
|
margin-left: 3px;
|
|
|
`;
|
|
|
+
|
|
|
+const DeploymentImageContainer = styled.div`
|
|
|
+ height: 20px;
|
|
|
+ font-size: 13px;
|
|
|
+ position: relative;
|
|
|
+ display: flex;
|
|
|
+ margin-left: 15px;
|
|
|
+ align-items: center;
|
|
|
+ font-weight: 400;
|
|
|
+ justify-content: center;
|
|
|
+ color: #ffffff66;
|
|
|
+ padding-left: 5px;
|
|
|
+`;
|
|
|
+
|
|
|
+const Icon = styled.img`
|
|
|
+ width: 100%;
|
|
|
+`;
|
|
|
+
|
|
|
+const DeploymentTypeIcon = styled(Icon)`
|
|
|
+ width: 20px;
|
|
|
+ margin-right: 10px;
|
|
|
+`;
|
|
|
+
|
|
|
+const RepositoryName = styled.div`
|
|
|
+ white-space: nowrap;
|
|
|
+ overflow: hidden;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ max-width: 390px;
|
|
|
+ position: relative;
|
|
|
+ margin-right: 3px;
|
|
|
+`;
|
|
|
+
|
|
|
+const Tooltip = styled.div`
|
|
|
+ position: absolute;
|
|
|
+ left: -20px;
|
|
|
+ top: 10px;
|
|
|
+ min-height: 18px;
|
|
|
+ max-width: calc(700px);
|
|
|
+ padding: 5px 7px;
|
|
|
+ background: #272731;
|
|
|
+ z-index: 999;
|
|
|
+ color: white;
|
|
|
+ font-size: 12px;
|
|
|
+ font-family: "Work Sans", sans-serif;
|
|
|
+ outline: 1px solid #ffffff55;
|
|
|
+ opacity: 0;
|
|
|
+ animation: faded-in 0.2s 0.15s;
|
|
|
+ animation-fill-mode: forwards;
|
|
|
+ @keyframes faded-in {
|
|
|
+ from {
|
|
|
+ opacity: 0;
|
|
|
+ }
|
|
|
+ to {
|
|
|
+ opacity: 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+`;
|