diff --git a/src/main/frontend/pipeline-console-view/pipeline-console/main/ConsoleLogCard.tsx b/src/main/frontend/pipeline-console-view/pipeline-console/main/ConsoleLogCard.tsx index 75fa461f..cf01ba17 100644 --- a/src/main/frontend/pipeline-console-view/pipeline-console/main/ConsoleLogCard.tsx +++ b/src/main/frontend/pipeline-console-view/pipeline-console/main/ConsoleLogCard.tsx @@ -1,24 +1,31 @@ import React from "react"; import { lazy, Suspense } from "react"; import { styled } from "@mui/material/styles"; -import Card from "@mui/material/Card"; -import CardContent from "@mui/material/CardContent"; +import { + Button, + Card, + CardContent, + CircularProgress, + Collapse, + Grid, + Typography, +} from "@mui/material"; import CardActionArea from "@mui/material/CardActions"; -import { CircularProgress } from "@mui/material"; -import Collapse from "@mui/material/Collapse"; import IconButton, { IconButtonProps } from "@mui/material/IconButton"; -import Typography from "@mui/material/Typography"; import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; -import { StepInfo, StepLogBufferInfo } from "./PipelineConsoleModel"; -import Grid from "@mui/material/Grid"; -import Button from "@mui/material/Button"; +import LinkIcon from "@mui/icons-material/Link"; import { Tooltip } from "react-tippy"; -import { LOG_FETCH_SIZE } from "./PipelineConsoleModel"; -import LinkIcon from "@mui/icons-material/Link"; +import { + LOG_FETCH_SIZE, + StepInfo, + StepLogBufferInfo, +} from "./PipelineConsoleModel"; import ConsoleLogModal from "./ConsoleLogModal"; import ResizeIcon from "./ResizeIcon"; +import { getStepStatus } from "../../../step-status/StepStatus"; + const ConsoleLogStream = lazy(() => import("./ConsoleLogStream")); interface ExpandMoreProps extends IconButtonProps { @@ -127,10 +134,32 @@ export class ConsoleLogCard extends React.Component< return `${(size / gib).toFixed(2)}GiB`; } + getStepHeaderTitle(stepTitle: string, stepId: string) { + if (stepTitle) { + return ( + + {stepTitle} + + ); + } else { + return null; + } + } + render() { const handleOpen = () => this.setState({ open: true }); const handleClose = () => this.setState({ open: false }); + const statusIcon = getStepStatus( + this.props.step.state, + this.props.step.completePercent, + 10 + ); + return ( + {statusIcon} - {this.props.step.name - .substring(0, this.props.step.name.lastIndexOf("-")) - .trimEnd()} - - - {this.props.step.name - .substring( - this.props.step.name.lastIndexOf("-") + 1, - this.props.step.name.length - ) - .trimStart()} + {this.props.step.name} + {this.getStepHeaderTitle( + this.props.step.title, + this.props.step.id + )} - + - +
+ +
@@ -218,11 +240,11 @@ export class ConsoleLogCard extends React.Component< } aria-label="View step as plain text" > - +
- + void; @@ -13,7 +12,7 @@ export interface ConsoleLogModelProps { open: boolean; } -import { Box, Modal } from "@mui/material"; +import { Box, Modal, Stack } from "@mui/material"; import Typography from "@mui/material/Typography"; import ConsoleLogStream from "./ConsoleLogStream"; @@ -36,6 +35,13 @@ const style = { export default function ConsoleLogModal(props: ConsoleLogModelProps) { const handleClose = () => props.setClose(); + const statusIcon = getStepStatus( + props.step.state, + props.step.completePercent, + 10 + ); + const stepDisplayName = props.step.name; + const stepTitle = props.step.title ? " - " + props.step.title : ""; return ( <> @@ -54,25 +60,17 @@ export default function ConsoleLogModal(props: ConsoleLogModelProps) { noWrap={true} key={`step-name-text-${props.step.id}`} > - {props.step.name - .substring(0, props.step.name.lastIndexOf("-")) - .trimEnd()} + + {statusIcon} + + + {stepDisplayName} + + {stepTitle} + + - - {props.step.name - .substring( - props.step.name.lastIndexOf("-") + 1, - props.step.name.length - ) - .trimStart()} - - diff --git a/src/main/frontend/pipeline-console-view/pipeline-console/main/pipeline-console.scss b/src/main/frontend/pipeline-console-view/pipeline-console/main/pipeline-console.scss index 4258841b..1643d588 100644 --- a/src/main/frontend/pipeline-console-view/pipeline-console/main/pipeline-console.scss +++ b/src/main/frontend/pipeline-console-view/pipeline-console/main/pipeline-console.scss @@ -2,13 +2,13 @@ :root { --card-background: hsl(212, 30%, 96%); - --step-bg-running: var(--accent-color); - --step-bg-success: var(--success-color); - --step-bg-unstable: var(--warning-color); - --step-bg-failure: var(--error-color); - --step-bg-aborted: var(--purple); - --step-bg-paused: var(--blue); - --step-text-color: rgb(233, 237, 237); + --step-bg-running: color-mix(in srgb, var(--accent-color) 50%, white); + --step-bg-success: color-mix(in srgb, var(--success-color) 50%, white); + --step-bg-unstable: color-mix(in srgb, var(--warning-color) 50%, white); + --step-bg-failure: color-mix(in srgb, var(--error-color) 50%, white); + --step-bg-aborted: color-mix(in srgb, var(--purple) 50%, white); + --step-bg-paused: color-mix(in srgb, var(--blue) 50%, white); + --step-text-color: var(--text-color); } .app-page-body--one-column { @@ -17,14 +17,25 @@ [data-theme="dark"] { --card-background: hsl(230deg 14% 23%); - --step-text-color: hsl(230deg 14% 23%); + --step-bg-running: color-mix(in srgb, var(--accent-color) 50%, black); + --step-bg-success: color-mix(in srgb, var(--success-color) 50%, black); + --step-bg-unstable: color-mix(in srgb, var(--warning-color) 50%, black); + --step-bg-failure: color-mix(in srgb, var(--error-color) 50%, black); + --step-bg-aborted: color-mix(in srgb, var(--purple) 50%, black); + --step-bg-paused: color-mix(in srgb, var(--blue) 50%, black); } @media (prefers-color-scheme: dark) { [data-theme="dark-system"], [data-theme="dark-system"] { --card-background: hsl(230deg 14% 23%); - --step-text-color: hsl(230deg 14% 23%); + //--step-text-color: hsl(230deg 14% 23%); + --step-bg-running: color-mix(in srgb, var(--accent-color) 50%, black); + --step-bg-success: color-mix(in srgb, var(--success-color) 50%, black); + --step-bg-unstable: color-mix(in srgb, var(--warning-color) 50%, black); + --step-bg-failure: color-mix(in srgb, var(--error-color) 50%, black); + --step-bg-aborted: color-mix(in srgb, var(--purple) 50%, black); + --step-bg-paused: color-mix(in srgb, var(--blue) 50%, black); } } @@ -222,6 +233,14 @@ g.build-status-icon__outer { color: var(--step-text-color); } +.svg-icon--link { + color: var(--step-text-color); +} + +.svg-icon--resize { + color: var(--step-text-color); +} + .svg-icon--step-card-status { color: var(--step-text-color) !important; } diff --git a/src/main/frontend/step-status/StepStatus.tsx b/src/main/frontend/step-status/StepStatus.tsx index 4cbe1581..1114949e 100644 --- a/src/main/frontend/step-status/StepStatus.tsx +++ b/src/main/frontend/step-status/StepStatus.tsx @@ -24,7 +24,11 @@ const Component: FunctionComponent = (props: Props) => { ); }; -function getStepStatus(status: Result, complete?: number, radius?: number) { +export function getStepStatus( + status: Result, + complete?: number, + radius?: number +) { const icon = getGroupForResult( decodeResultValue(status), complete ?? 100, diff --git a/src/main/java/io/jenkins/plugins/pipelinegraphview/utils/PipelineStepApi.java b/src/main/java/io/jenkins/plugins/pipelinegraphview/utils/PipelineStepApi.java index 325b46f4..126db46d 100644 --- a/src/main/java/io/jenkins/plugins/pipelinegraphview/utils/PipelineStepApi.java +++ b/src/main/java/io/jenkins/plugins/pipelinegraphview/utils/PipelineStepApi.java @@ -28,19 +28,22 @@ private List parseSteps(List stepNodes, String st if (flowNodeWrapper.getStatus().getState() != BlueRun.BlueRunState.FINISHED) { state = flowNodeWrapper.getStatus().getState().name().toLowerCase(Locale.ROOT); } - String displayName = flowNodeWrapper.getDisplayName(); + String displayName = flowNodeWrapper.getDisplayName(); + String title = ""; if (flowNodeWrapper.getType() == FlowNodeWrapper.NodeType.UNHANDLED_EXCEPTION) { displayName = "Pipeline error"; } else { String stepArguments = flowNodeWrapper.getArgumentsAsString(); if (stepArguments != null && !stepArguments.isEmpty()) { - displayName = stepArguments + " - " + displayName; + displayName = stepArguments; + title = flowNodeWrapper.getDisplayName(); } // Use the step label as the displayName if set String labelDisplayName = flowNodeWrapper.getLabelDisplayName(); if (labelDisplayName != null && !labelDisplayName.isEmpty()) { displayName = labelDisplayName; + title = ""; } } // Remove non-printable chars (e.g. ANSI color codes). @@ -54,7 +57,7 @@ private List parseSteps(List stepNodes, String st state, 50, // TODO how ??? flowNodeWrapper.getType().name(), - flowNodeWrapper.getDisplayName(), // TODO blue ocean uses timing information: "Passed in + title, // TODO blue ocean uses timing information: "Passed in // 0s" stageId, "Queued " diff --git a/src/test/java/io/jenkins/plugins/pipelinegraphview/utils/PipelineStepApiTest.java b/src/test/java/io/jenkins/plugins/pipelinegraphview/utils/PipelineStepApiTest.java index d415767a..a01a06a8 100644 --- a/src/test/java/io/jenkins/plugins/pipelinegraphview/utils/PipelineStepApiTest.java +++ b/src/test/java/io/jenkins/plugins/pipelinegraphview/utils/PipelineStepApiTest.java @@ -32,23 +32,31 @@ public void unstableSmokes() throws Exception { List steps = api.getSteps(unstableOneId).getSteps(); assertThat(steps, hasSize(3)); - assertThat(steps.get(0).getName(), is("foo - Print Message")); - assertThat(steps.get(1).getName(), is("oops-one - Set stage result to unstable")); - assertThat(steps.get(2).getName(), is("bar - Print Message")); + assertThat(steps.get(0).getName(), is("foo")); + assertThat(steps.get(0).getTitle(), is("Print Message")); + assertThat(steps.get(1).getName(), is("oops-one")); + assertThat(steps.get(1).getTitle(), is("Set stage result to unstable")); + assertThat(steps.get(2).getName(), is("bar")); + assertThat(steps.get(2).getTitle(), is("Print Message")); steps = api.getSteps(successId).getSteps(); assertThat(steps, hasSize(1)); - assertThat(steps.get(0).getName(), is("baz - Print Message")); + assertThat(steps.get(0).getName(), is("baz")); + assertThat(steps.get(0).getTitle(), is("Print Message")); steps = api.getSteps(unstableTwoId).getSteps(); assertThat(steps, hasSize(2)); - assertThat(steps.get(0).getName(), is("will-be-caught - Error signal")); - assertThat(steps.get(1).getName(), is("oops-two - Set stage result to unstable")); + assertThat(steps.get(0).getName(), is("will-be-caught")); + assertThat(steps.get(0).getTitle(), is("Error signal")); + assertThat(steps.get(1).getName(), is("oops-two")); + assertThat(steps.get(1).getTitle(), is("Set stage result to unstable")); steps = api.getSteps(failureID).getSteps(); assertThat(steps, hasSize(2)); - assertThat(steps.get(0).getName(), is("oops-masked - Set stage result to unstable")); - assertThat(steps.get(1).getName(), is("oops-failure - Error signal")); + assertThat(steps.get(0).getName(), is("oops-masked")); + assertThat(steps.get(0).getTitle(), is("Set stage result to unstable")); + assertThat(steps.get(1).getName(), is("oops-failure")); + assertThat(steps.get(1).getTitle(), is("Error signal")); } @Test @@ -78,20 +86,26 @@ public void complexParallelBranchesHaveCorrectSteps() throws Exception { PipelineStepApi api = new PipelineStepApi(run); List steps = api.getSteps(nonParallelId).getSteps(); assertThat(steps, hasSize(2)); - assertThat(steps.get(0).getName(), is("This stage will be executed first. - Print Message")); + assertThat(steps.get(0).getName(), is("This stage will be executed first.")); + assertThat(steps.get(0).getTitle(), is("Print Message")); assertThat(steps.get(1).getName(), is("Print Message")); + assertThat(steps.get(1).getTitle(), is("")); // Check 'Branch A' steps = api.getSteps(branchAId).getSteps(); assertThat(steps, hasSize(2)); - assertThat(steps.get(0).getName(), is("On Branch A - 1 - Print Message")); - assertThat(steps.get(1).getName(), is("On Branch A - 2 - Print Message")); + assertThat(steps.get(0).getName(), is("On Branch A - 1")); + assertThat(steps.get(0).getTitle(), is("Print Message")); + assertThat(steps.get(1).getName(), is("On Branch A - 2")); + assertThat(steps.get(1).getTitle(), is("Print Message")); // Check 'Branch B' steps = api.getSteps(branchBId).getSteps(); assertThat(steps, hasSize(2)); - assertThat(steps.get(0).getName(), is("On Branch B - 1 - Print Message")); - assertThat(steps.get(1).getName(), is("On Branch B - 2 - Print Message")); + assertThat(steps.get(0).getName(), is("On Branch B - 1")); + assertThat(steps.get(0).getTitle(), is("Print Message")); + assertThat(steps.get(1).getName(), is("On Branch B - 2")); + assertThat(steps.get(1).getTitle(), is("Print Message")); // Check 'Branch C' steps = api.getSteps(branchCId).getSteps(); @@ -100,14 +114,18 @@ public void complexParallelBranchesHaveCorrectSteps() throws Exception { // Check 'Nested 1' steps = api.getSteps(branchNested1Id).getSteps(); assertThat(steps, hasSize(2)); - assertThat(steps.get(0).getName(), is("In stage Nested 1 - 1 within Branch C - Print Message")); - assertThat(steps.get(1).getName(), is("In stage Nested 1 - 2 within Branch C - Print Message")); + assertThat(steps.get(0).getName(), is("In stage Nested 1 - 1 within Branch C")); + assertThat(steps.get(0).getTitle(), is("Print Message")); + assertThat(steps.get(1).getName(), is("In stage Nested 1 - 2 within Branch C")); + assertThat(steps.get(1).getTitle(), is("Print Message")); // Check 'Nested 2' steps = api.getSteps(branchNested2Id).getSteps(); assertThat(steps, hasSize(2)); - assertThat(steps.get(0).getName(), is("In stage Nested 2 - 1 within Branch C - Print Message")); - assertThat(steps.get(1).getName(), is("In stage Nested 2 - 2 within Branch C - Print Message")); + assertThat(steps.get(0).getName(), is("In stage Nested 2 - 1 within Branch C")); + assertThat(steps.get(0).getTitle(), is("Print Message")); + assertThat(steps.get(1).getName(), is("In stage Nested 2 - 2 within Branch C")); + assertThat(steps.get(1).getTitle(), is("Print Message")); } @Test @@ -132,7 +150,8 @@ public void nestedStagesHaveCorrectSteps() throws Exception { // Check 'Child A' List steps = api.getSteps(childAId).getSteps(); assertThat(steps, hasSize(1)); - assertThat(steps.get(0).getName(), is("In child A - Print Message")); + assertThat(steps.get(0).getName(), is("In child A")); + assertThat(steps.get(0).getTitle(), is("Print Message")); // Check 'Child A' steps = api.getSteps(childBId).getSteps(); @@ -141,7 +160,8 @@ public void nestedStagesHaveCorrectSteps() throws Exception { // Check 'Grandchild B' steps = api.getSteps(grandchildBId).getSteps(); assertThat(steps, hasSize(1)); - assertThat(steps.get(0).getName(), is("In grandchild B - Print Message")); + assertThat(steps.get(0).getName(), is("In grandchild B")); + assertThat(steps.get(0).getTitle(), is("Print Message")); // Check 'Child C' steps = api.getSteps(childCId).getSteps(); @@ -154,7 +174,8 @@ public void nestedStagesHaveCorrectSteps() throws Exception { // Check 'Great-Grandchild C' steps = api.getSteps(greatGrandchildCId).getSteps(); assertThat(steps, hasSize(1)); - assertThat(steps.get(0).getName(), is("In great-grandchild C - Print Message")); + assertThat(steps.get(0).getName(), is("In great-grandchild C")); + assertThat(steps.get(0).getTitle(), is("Print Message")); } @Test @@ -169,17 +190,27 @@ public void getAllStepsReturnsStepsForComplexParallelBranches() throws Exception List steps = api.getAllSteps().getSteps(); assertThat(steps, hasSize(10)); - assertThat(steps.get(0).getName(), is("This stage will be executed first. - Print Message")); + assertThat(steps.get(0).getName(), is("This stage will be executed first.")); + assertThat(steps.get(0).getTitle(), is("Print Message")); assertThat(steps.get(1).getName(), is("Print Message")); - assertThat(steps.get(2).getName(), is("On Branch A - 1 - Print Message")); - assertThat(steps.get(3).getName(), is("On Branch A - 2 - Print Message")); - assertThat(steps.get(4).getName(), is("On Branch B - 1 - Print Message")); - assertThat(steps.get(5).getName(), is("On Branch B - 2 - Print Message")); - - assertThat(steps.get(6).getName(), is("In stage Nested 1 - 1 within Branch C - Print Message")); - assertThat(steps.get(7).getName(), is("In stage Nested 1 - 2 within Branch C - Print Message")); - assertThat(steps.get(8).getName(), is("In stage Nested 2 - 1 within Branch C - Print Message")); - assertThat(steps.get(9).getName(), is("In stage Nested 2 - 2 within Branch C - Print Message")); + assertThat(steps.get(1).getTitle(), is("")); + assertThat(steps.get(2).getName(), is("On Branch A - 1")); + assertThat(steps.get(2).getTitle(), is("Print Message")); + assertThat(steps.get(3).getName(), is("On Branch A - 2")); + assertThat(steps.get(3).getTitle(), is("Print Message")); + assertThat(steps.get(4).getName(), is("On Branch B - 1")); + assertThat(steps.get(4).getTitle(), is("Print Message")); + assertThat(steps.get(5).getName(), is("On Branch B - 2")); + assertThat(steps.get(5).getTitle(), is("Print Message")); + + assertThat(steps.get(6).getName(), is("In stage Nested 1 - 1 within Branch C")); + assertThat(steps.get(6).getTitle(), is("Print Message")); + assertThat(steps.get(7).getName(), is("In stage Nested 1 - 2 within Branch C")); + assertThat(steps.get(7).getTitle(), is("Print Message")); + assertThat(steps.get(8).getName(), is("In stage Nested 2 - 1 within Branch C")); + assertThat(steps.get(8).getTitle(), is("Print Message")); + assertThat(steps.get(9).getName(), is("In stage Nested 2 - 2 within Branch C")); + assertThat(steps.get(9).getTitle(), is("Print Message")); } @Test @@ -192,9 +223,12 @@ public void getAllStepsReturnsStepsForNestedStages() throws Exception { List steps = api.getAllSteps().getSteps(); assertThat(steps, hasSize(3)); - assertThat(steps.get(0).getName(), is("In child A - Print Message")); - assertThat(steps.get(1).getName(), is("In grandchild B - Print Message")); - assertThat(steps.get(2).getName(), is("In great-grandchild C - Print Message")); + assertThat(steps.get(0).getName(), is("In child A")); + assertThat(steps.get(0).getTitle(), is("Print Message")); + assertThat(steps.get(1).getName(), is("In grandchild B")); + assertThat(steps.get(1).getTitle(), is("Print Message")); + assertThat(steps.get(2).getName(), is("In great-grandchild C")); + assertThat(steps.get(2).getTitle(), is("Print Message")); } @Issue("GH#92") @@ -230,31 +264,38 @@ public void githubIssue92RegressionTest() throws Exception { List steps = api.getSteps(linux8CheckoutId).getSteps(); assertThat(steps, hasSize(1)); - assertThat(steps.get(0).getName(), is("Checking out linux-8 - Print Message")); + assertThat(steps.get(0).getName(), is("Checking out linux-8")); + assertThat(steps.get(0).getTitle(), is("Print Message")); steps = api.getSteps(linux8BuildId).getSteps(); assertThat(steps, hasSize(1)); - assertThat(steps.get(0).getName(), is("Building linux-8 - Print Message")); + assertThat(steps.get(0).getName(), is("Building linux-8")); + assertThat(steps.get(0).getTitle(), is("Print Message")); steps = api.getSteps(linux8ArchiveId).getSteps(); assertThat(steps, hasSize(1)); - assertThat(steps.get(0).getName(), is("Archiving linux-8 - Print Message")); + assertThat(steps.get(0).getName(), is("Archiving linux-8")); + assertThat(steps.get(0).getTitle(), is("Print Message")); steps = api.getSteps(linux11CheckoutId).getSteps(); assertThat(steps, hasSize(1)); - assertThat(steps.get(0).getName(), is("Checking out linux-11 - Print Message")); + assertThat(steps.get(0).getName(), is("Checking out linux-11")); + assertThat(steps.get(0).getTitle(), is("Print Message")); steps = api.getSteps(linux11BuildId).getSteps(); assertThat(steps, hasSize(1)); - assertThat(steps.get(0).getName(), is("Building linux-11 - Print Message")); + assertThat(steps.get(0).getName(), is("Building linux-11")); + assertThat(steps.get(0).getTitle(), is("Print Message")); steps = api.getSteps(linux11ArchiveId).getSteps(); assertThat(steps, hasSize(1)); - assertThat(steps.get(0).getName(), is("Archiving linux-11 - Print Message")); + assertThat(steps.get(0).getName(), is("Archiving linux-11")); + assertThat(steps.get(0).getTitle(), is("Print Message")); steps = api.getSteps(deployStageId).getSteps(); assertThat(steps, hasSize(1)); - assertThat(steps.get(0).getName(), is("Deploying... - Print Message")); + assertThat(steps.get(0).getName(), is("Deploying...")); + assertThat(steps.get(0).getTitle(), is("Print Message")); } @Issue("GH#213") @@ -272,7 +313,8 @@ public void githubIssue213RegressionTest_scriptedError() throws Exception { List steps = api.getSteps(failureStage).getSteps(); assertThat(steps, hasSize(2)); PipelineStep errorStep = steps.get(1); - assertThat(errorStep.getName(), is("oops-failure - Error signal")); + assertThat(errorStep.getName(), is("oops-failure")); + assertThat(errorStep.getTitle(), is("Error signal")); FlowNode node = run.getExecution().getNode(String.valueOf(errorStep.getId())); String errorText = PipelineNodeUtil.getExceptionText(node); assertThat(errorText, is("oops-failure")); @@ -294,7 +336,8 @@ public void githubIssue213RegressionTest_errorStep() throws Exception { List steps = api.getSteps(failureStage).getSteps(); assertThat(steps, hasSize(2)); PipelineStep errorStep = steps.get(1); - assertThat(errorStep.getName(), is("oops-failure - Error signal")); + assertThat(errorStep.getName(), is("oops-failure")); + assertThat(errorStep.getTitle(), is("Error signal")); FlowNode node = run.getExecution().getNode(String.valueOf(errorStep.getId())); String errorText = PipelineNodeUtil.getExceptionText(node); assertThat(errorText, is("oops-failure"));