|
@@ -1,20 +1,24 @@
|
|
|
-import React, { useState, useMemo } from "react";
|
|
|
|
|
|
|
+import React, { useMemo, useState } from "react";
|
|
|
|
|
+import { useLocation } from "react-router";
|
|
|
|
|
+import { type Column } from "react-table";
|
|
|
import styled from "styled-components";
|
|
import styled from "styled-components";
|
|
|
|
|
+import { match } from "ts-pattern";
|
|
|
|
|
|
|
|
-import history from "assets/history.png";
|
|
|
|
|
-import Text from "components/porter/Text";
|
|
|
|
|
-import Container from "components/porter/Container";
|
|
|
|
|
-import Spacer from "components/porter/Spacer";
|
|
|
|
|
-import { type JobRun, useJobs } from "lib/hooks/useJobs";
|
|
|
|
|
-import Table from "components/OldTable";
|
|
|
|
|
-import { type CellProps, type Column } from "react-table";
|
|
|
|
|
-import { relativeDate, timeFrom } from "shared/string_utils";
|
|
|
|
|
-import { useLocation } from "react-router";
|
|
|
|
|
import SelectRow from "components/form-components/SelectRow";
|
|
import SelectRow from "components/form-components/SelectRow";
|
|
|
|
|
+import Table from "components/OldTable";
|
|
|
|
|
+import Container from "components/porter/Container";
|
|
|
import Link from "components/porter/Link";
|
|
import Link from "components/porter/Link";
|
|
|
-import { ranFor } from "./utils";
|
|
|
|
|
|
|
+import Spacer from "components/porter/Spacer";
|
|
|
|
|
+import Text from "components/porter/Text";
|
|
|
|
|
+import { useJobs, type JobRun } from "lib/hooks/useJobs";
|
|
|
|
|
+
|
|
|
|
|
+import { relativeDate } from "shared/string_utils";
|
|
|
|
|
+import history from "assets/history.png";
|
|
|
|
|
+
|
|
|
|
|
+import { useLatestRevision } from "../../app-view/LatestRevisionContext";
|
|
|
import JobRunDetails from "./JobRunDetails";
|
|
import JobRunDetails from "./JobRunDetails";
|
|
|
import TriggerJobButton from "./TriggerJobButton";
|
|
import TriggerJobButton from "./TriggerJobButton";
|
|
|
|
|
+import { ranFor } from "./utils";
|
|
|
|
|
|
|
|
type Props = {
|
|
type Props = {
|
|
|
appName: string;
|
|
appName: string;
|
|
@@ -34,18 +38,24 @@ const JobsSection: React.FC<Props> = ({
|
|
|
const { search } = useLocation();
|
|
const { search } = useLocation();
|
|
|
const queryParams = new URLSearchParams(search);
|
|
const queryParams = new URLSearchParams(search);
|
|
|
const serviceFromQueryParams = queryParams.get("service");
|
|
const serviceFromQueryParams = queryParams.get("service");
|
|
|
- const jobRunId = queryParams.get("job_run_id");
|
|
|
|
|
|
|
+ const jobRunName = queryParams.get("job_run_name");
|
|
|
const [selectedJobName, setSelectedJobName] = useState<string>(
|
|
const [selectedJobName, setSelectedJobName] = useState<string>(
|
|
|
- serviceFromQueryParams != null && jobNames.includes(serviceFromQueryParams) ? serviceFromQueryParams : "all"
|
|
|
|
|
|
|
+ serviceFromQueryParams != null && jobNames.includes(serviceFromQueryParams)
|
|
|
|
|
+ ? serviceFromQueryParams
|
|
|
|
|
+ : "all"
|
|
|
);
|
|
);
|
|
|
|
|
+ const { deploymentTarget } = useLatestRevision();
|
|
|
|
|
|
|
|
const jobOptions = useMemo(() => {
|
|
const jobOptions = useMemo(() => {
|
|
|
- return [{ label: "All jobs", value: "all" }, ...jobNames.map((name) => {
|
|
|
|
|
- return {
|
|
|
|
|
- label: name,
|
|
|
|
|
- value: name,
|
|
|
|
|
- };
|
|
|
|
|
- })];
|
|
|
|
|
|
|
+ return [
|
|
|
|
|
+ { label: "All jobs", value: "all" },
|
|
|
|
|
+ ...jobNames.map((name) => {
|
|
|
|
|
+ return {
|
|
|
|
|
+ label: name,
|
|
|
|
|
+ value: name,
|
|
|
|
|
+ };
|
|
|
|
|
+ }),
|
|
|
|
|
+ ];
|
|
|
}, [jobNames]);
|
|
}, [jobNames]);
|
|
|
|
|
|
|
|
const { jobRuns, isLoadingJobRuns } = useJobs({
|
|
const { jobRuns, isLoadingJobRuns } = useJobs({
|
|
@@ -57,29 +67,25 @@ const JobsSection: React.FC<Props> = ({
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
const selectedJobRun = useMemo(() => {
|
|
const selectedJobRun = useMemo(() => {
|
|
|
- return jobRuns.find((jr) => jr.metadata.uid === jobRunId);
|
|
|
|
|
- }, [jobRuns, jobRunId]);
|
|
|
|
|
|
|
+ return jobRuns.find((jr) => jr.name === jobRunName);
|
|
|
|
|
+ }, [jobRuns, jobRunName]);
|
|
|
|
|
|
|
|
const columns = useMemo<Array<Column<JobRun>>>(
|
|
const columns = useMemo<Array<Column<JobRun>>>(
|
|
|
() => [
|
|
() => [
|
|
|
{
|
|
{
|
|
|
Header: "Started",
|
|
Header: "Started",
|
|
|
- accessor: (originalRow) => relativeDate(originalRow?.status.startTime ?? ''),
|
|
|
|
|
|
|
+ accessor: (originalRow) => relativeDate(originalRow.created_at),
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
Header: "Run for",
|
|
Header: "Run for",
|
|
|
- Cell: ({ row }) => {
|
|
|
|
|
|
|
+ Cell: (cell) => {
|
|
|
|
|
+ const { original: row } = cell.row;
|
|
|
let ranForString = "Still running...";
|
|
let ranForString = "Still running...";
|
|
|
- if (row.original.status.completionTime) {
|
|
|
|
|
- ranForString = ranFor(
|
|
|
|
|
- row.original.status.startTime ?? row.original.metadata.creationTimestamp,
|
|
|
|
|
- row.original.status.completionTime
|
|
|
|
|
- );
|
|
|
|
|
- } else if (row.original.status.conditions.length > 0 && row.original.status.conditions[0].lastTransitionTime) {
|
|
|
|
|
- ranForString = ranFor(
|
|
|
|
|
- row.original.status.startTime ?? row.original.metadata.creationTimestamp,
|
|
|
|
|
- row.original?.status?.conditions[0]?.lastTransitionTime
|
|
|
|
|
- );
|
|
|
|
|
|
|
+ const startedTime = new Date(row.created_at);
|
|
|
|
|
+ const finishedTime = new Date(row.finished_at);
|
|
|
|
|
+
|
|
|
|
|
+ if (finishedTime > startedTime) {
|
|
|
|
|
+ ranForString = ranFor(row.created_at, row.finished_at);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
return <div>{ranForString}</div>;
|
|
return <div>{ranForString}</div>;
|
|
@@ -88,43 +94,54 @@ const JobsSection: React.FC<Props> = ({
|
|
|
{
|
|
{
|
|
|
Header: "Name",
|
|
Header: "Name",
|
|
|
id: "job_name",
|
|
id: "job_name",
|
|
|
- Cell: ({ row }: CellProps<JobRun>) => {
|
|
|
|
|
- return <div>{row.original.jobName}</div>;
|
|
|
|
|
|
|
+ Cell: (cell) => {
|
|
|
|
|
+ const { original: row } = cell.row;
|
|
|
|
|
+
|
|
|
|
|
+ return <div>{row.service_name}</div>;
|
|
|
},
|
|
},
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
Header: "Version",
|
|
Header: "Version",
|
|
|
id: "version_number",
|
|
id: "version_number",
|
|
|
- Cell: ({ row }: CellProps<JobRun>) => {
|
|
|
|
|
- return <div>{row.original.revisionNumber}</div>;
|
|
|
|
|
|
|
+ Cell: (cell) => {
|
|
|
|
|
+ const { original: row } = cell.row;
|
|
|
|
|
+
|
|
|
|
|
+ return <div>{row.revisionNumber}</div>;
|
|
|
},
|
|
},
|
|
|
maxWidth: 100,
|
|
maxWidth: 100,
|
|
|
styles: {
|
|
styles: {
|
|
|
padding: "10px",
|
|
padding: "10px",
|
|
|
- }
|
|
|
|
|
|
|
+ },
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
Header: "Status",
|
|
Header: "Status",
|
|
|
id: "status",
|
|
id: "status",
|
|
|
- Cell: ({ row }: CellProps<JobRun>) => {
|
|
|
|
|
- if (row.original.status.succeeded != null && row.original.status.succeeded >= 1) {
|
|
|
|
|
- return <Status color="#38a88a">Succeeded</Status>;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (row.original.status.failed != null && row.original.status.failed >= 1) {
|
|
|
|
|
- return <Status color="#cc3d42">Failed</Status>;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return <Status color="#ffffff11">Running</Status>;
|
|
|
|
|
|
|
+ Cell: (cell) => {
|
|
|
|
|
+ const { original: row } = cell.row;
|
|
|
|
|
+
|
|
|
|
|
+ return match(row.status)
|
|
|
|
|
+ .with("SUCCESSFUL", () => (
|
|
|
|
|
+ <Status color="#38a88a">Succeeded</Status>
|
|
|
|
|
+ ))
|
|
|
|
|
+ .with("FAILED", () => <Status color="#cc3d42">Failed</Status>)
|
|
|
|
|
+ .otherwise(() => <Status color="#ffffff11">Running</Status>);
|
|
|
},
|
|
},
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
{
|
|
{
|
|
|
Header: "Details",
|
|
Header: "Details",
|
|
|
id: "expand",
|
|
id: "expand",
|
|
|
- Cell: ({ row }: CellProps<JobRun>) => {
|
|
|
|
|
|
|
+ Cell: (cell) => {
|
|
|
|
|
+ const { original: row } = cell.row;
|
|
|
|
|
+
|
|
|
return (
|
|
return (
|
|
|
- <Link to={`/apps/${appName}/job-history?job_run_id=${row.original.metadata.uid}&service=${row.original.jobName}`}>
|
|
|
|
|
|
|
+ <Link
|
|
|
|
|
+ to={
|
|
|
|
|
+ deploymentTarget.is_preview
|
|
|
|
|
+ ? `/preview-environments/apps/${appName}/job-history?job_run_name=${row.name}&service=${row.service_name}&target=${deploymentTargetId}`
|
|
|
|
|
+ : `/apps/${appName}/job-history?job_run_name=${row.name}&service=${row.service_name}`
|
|
|
|
|
+ }
|
|
|
|
|
+ >
|
|
|
<ExpandButton>
|
|
<ExpandButton>
|
|
|
<i className="material-icons">open_in_new</i>
|
|
<i className="material-icons">open_in_new</i>
|
|
|
</ExpandButton>
|
|
</ExpandButton>
|
|
@@ -139,28 +156,32 @@ const JobsSection: React.FC<Props> = ({
|
|
|
|
|
|
|
|
return (
|
|
return (
|
|
|
<>
|
|
<>
|
|
|
- {selectedJobRun && (
|
|
|
|
|
- <JobRunDetails
|
|
|
|
|
- jobRun={selectedJobRun}
|
|
|
|
|
- />
|
|
|
|
|
- )}
|
|
|
|
|
|
|
+ {selectedJobRun && <JobRunDetails jobRun={selectedJobRun} />}
|
|
|
{!selectedJobRun && (
|
|
{!selectedJobRun && (
|
|
|
<StyledExpandedApp>
|
|
<StyledExpandedApp>
|
|
|
<Container row spaced>
|
|
<Container row spaced>
|
|
|
- <Container row>
|
|
|
|
|
- <Icon src={history} />
|
|
|
|
|
- <Text size={21}>Run history for</Text>
|
|
|
|
|
- <SelectRow
|
|
|
|
|
- displayFlex={true}
|
|
|
|
|
- label=""
|
|
|
|
|
- value={selectedJobName}
|
|
|
|
|
- setActiveValue={(x: string) => { setSelectedJobName(x); }}
|
|
|
|
|
- options={jobOptions}
|
|
|
|
|
- width="200px"
|
|
|
|
|
- />
|
|
|
|
|
- </Container>
|
|
|
|
|
|
|
+ <Container row>
|
|
|
|
|
+ <Icon src={history} />
|
|
|
|
|
+ <Text size={21}>Run history for</Text>
|
|
|
|
|
+ <SelectRow
|
|
|
|
|
+ displayFlex={true}
|
|
|
|
|
+ label=""
|
|
|
|
|
+ value={selectedJobName}
|
|
|
|
|
+ setActiveValue={(x: string) => {
|
|
|
|
|
+ setSelectedJobName(x);
|
|
|
|
|
+ }}
|
|
|
|
|
+ options={jobOptions}
|
|
|
|
|
+ width="200px"
|
|
|
|
|
+ />
|
|
|
|
|
+ </Container>
|
|
|
{selectedJobName !== "all" && (
|
|
{selectedJobName !== "all" && (
|
|
|
- <TriggerJobButton projectId={projectId} clusterId={clusterId} appName={appName} jobName={selectedJobName} deploymentTargetId={deploymentTargetId}/>
|
|
|
|
|
|
|
+ <TriggerJobButton
|
|
|
|
|
+ projectId={projectId}
|
|
|
|
|
+ clusterId={clusterId}
|
|
|
|
|
+ appName={appName}
|
|
|
|
|
+ jobName={selectedJobName}
|
|
|
|
|
+ deploymentTargetId={deploymentTargetId}
|
|
|
|
|
+ />
|
|
|
)}
|
|
)}
|
|
|
</Container>
|
|
</Container>
|
|
|
<Spacer y={1} />
|
|
<Spacer y={1} />
|
|
@@ -168,8 +189,7 @@ const JobsSection: React.FC<Props> = ({
|
|
|
columns={columns}
|
|
columns={columns}
|
|
|
disableGlobalFilter
|
|
disableGlobalFilter
|
|
|
data={jobRuns.sort((a, b) => {
|
|
data={jobRuns.sort((a, b) => {
|
|
|
- return Date.parse(a?.metadata?.creationTimestamp) >
|
|
|
|
|
- Date.parse(b?.metadata?.creationTimestamp)
|
|
|
|
|
|
|
+ return Date.parse(a.created_at) > Date.parse(b.created_at)
|
|
|
? -1
|
|
? -1
|
|
|
: 1;
|
|
: 1;
|
|
|
})}
|
|
})}
|