From 0043ba8551f6b7ebb65f797173ca4b5ae2b09d17 Mon Sep 17 00:00:00 2001 From: richardwang98 Date: Tue, 28 Feb 2023 12:18:39 -0500 Subject: [PATCH] log viewer --- .../components/workflow/WorkFlowDetail.tsx | 35 ++++++++++++++-- .../components/workflow/WorkFlowLogViewer.tsx | 21 +--------- .../workflow/topology/PipelineLayout.tsx | 16 +++++--- .../workflow/topology/TopologyComponent.css | 4 -- .../workflow/topology/WorkFlowStepper.tsx | 40 ++++++++++--------- .../workflow/topology/mock/mockLog.ts | 16 ++++++++ .../workflow/topology/mock/mockTasks.ts | 27 +++++++++++++ .../topology/useDemoPipelineNodes.tsx | 29 ++++---------- 8 files changed, 116 insertions(+), 72 deletions(-) delete mode 100644 plugins/orion/src/components/workflow/topology/TopologyComponent.css create mode 100644 plugins/orion/src/components/workflow/topology/mock/mockLog.ts diff --git a/plugins/orion/src/components/workflow/WorkFlowDetail.tsx b/plugins/orion/src/components/workflow/WorkFlowDetail.tsx index 49ecb947ac..29202abda3 100644 --- a/plugins/orion/src/components/workflow/WorkFlowDetail.tsx +++ b/plugins/orion/src/components/workflow/WorkFlowDetail.tsx @@ -2,12 +2,39 @@ import { ParodosPage } from '../ParodosPage'; import { ContentHeader, SupportButton } from '@backstage/core-components'; import { Chip, Typography } from '@material-ui/core'; import { WorkFlowLogViewer } from './WorkFlowLogViewer'; -import React from 'react'; +import React, { useEffect, useState } from 'react'; import { WorkFlowStepper } from './topology/WorkFlowStepper'; import { useParams } from 'react-router-dom'; +import { WorkFlowTask } from './topology/type/WorkFlowTask'; +import { mockTasks } from './topology/mock/mockTasks'; +import { mockLog } from './topology/mock/mockLog'; export const WorkFlowDetail = ({ isNew }: { isNew: boolean }) => { const { executionId } = useParams(); + const [selectedTask, setSelectedTask] = useState(''); + const [allTasks, setAllTasks] = useState([]); + const [log, setLog] = useState(``); + + useEffect(() => { + setAllTasks([]); + const getWholeWorkflowExecutionInfo = () => { + // TODO api call to get subsequent execution CHAIN detail + setAllTasks(mockTasks); + }; + getWholeWorkflowExecutionInfo(); + }, [executionId]); + + useEffect(() => { + const getSelectedTaskLog = () => { + // TODO api call to get a task log from Workflow Execution Id + if (selectedTask !== '') + setLog( + `checking logs for ${selectedTask?.toUpperCase()} in execution: ${executionId}\n${mockLog}`, + ); + }; + getSelectedTaskLog(); + }, [executionId, selectedTask]); + return ( {isNew && } @@ -17,8 +44,10 @@ export const WorkFlowDetail = ({ isNew }: { isNew: boolean }) => { You are onboarding: org-name/new-project. Execution Id is {executionId} - - + {allTasks.length > 0 && ( + + )} + {log !== '' && } ); }; diff --git a/plugins/orion/src/components/workflow/WorkFlowLogViewer.tsx b/plugins/orion/src/components/workflow/WorkFlowLogViewer.tsx index a28754b533..1038d26ddd 100644 --- a/plugins/orion/src/components/workflow/WorkFlowLogViewer.tsx +++ b/plugins/orion/src/components/workflow/WorkFlowLogViewer.tsx @@ -2,23 +2,6 @@ import { LogViewer } from '@backstage/core-components'; import React from 'react'; import { withStyles } from '@material-ui/core'; -const exampleLog = `Starting up task with following steps -info: green 1 -info: green 2 -info: green 3 -error: red 1 -error: red 2 -error: red 3 -error: yellow 1 -error: yellow 2 -error: yellow 3 -error: blue 1 -error: blue 2 -error: blue 3 -error: purple 1 -error: cyan 1 -`; - const ParodosLogViewer = withStyles(theme => ({ root: { background: theme.palette.background.paper, @@ -30,8 +13,8 @@ const ParodosLogViewer = withStyles(theme => ({ }, }))(LogViewer); -export const WorkFlowLogViewer = () => ( +export const WorkFlowLogViewer = ({ log }: { log: string }) => (
- +
); diff --git a/plugins/orion/src/components/workflow/topology/PipelineLayout.tsx b/plugins/orion/src/components/workflow/topology/PipelineLayout.tsx index 322c440a23..ab91080b05 100644 --- a/plugins/orion/src/components/workflow/topology/PipelineLayout.tsx +++ b/plugins/orion/src/components/workflow/topology/PipelineLayout.tsx @@ -22,6 +22,7 @@ import '@patternfly/react-styles/css/components/Topology/topology-components.css import pipelineComponentFactory from './pipelineComponentFactory'; import { useDemoPipelineNodes } from './useDemoPipelineNodes'; import { GROUPED_PIPELINE_NODE_SEPARATION_HORIZONTAL } from './DemoTaskGroupEdge'; +import { WorkFlowTask } from './type/WorkFlowTask'; export const PIPELINE_NODE_SEPARATION_VERTICAL = 10; @@ -30,11 +31,16 @@ export const LAYOUT_TITLE = 'Layout'; const PIPELINE_LAYOUT = 'PipelineLayout'; const GROUPED_PIPELINE_LAYOUT = 'GroupedPipelineLayout'; -const TopologyPipelineLayout: React.FC = () => { +type Props = { + tasks: WorkFlowTask[]; + setSelectedTask: (selectedTask: string) => void; +}; + +const TopologyPipelineLayout = (props: Props) => { const [selectedIds, setSelectedIds] = React.useState(); const controller = useVisualizationController(); - const pipelineNodes = useDemoPipelineNodes(false, false, false, false); + const pipelineNodes = useDemoPipelineNodes(props.tasks); React.useEffect(() => { const spacerNodes = getSpacerNodes(pipelineNodes); @@ -68,6 +74,7 @@ const TopologyPipelineLayout: React.FC = () => { useEventListener(SELECTION_EVENT, ids => { setSelectedIds(ids); + props.setSelectedTask(ids.toString()); }); return ( @@ -79,7 +86,7 @@ const TopologyPipelineLayout: React.FC = () => { TopologyPipelineLayout.displayName = 'TopologyPipelineLayout'; -export const PipelineLayout = React.memo(() => { +export const PipelineLayout = React.memo((props: Props) => { const controller = new Visualization(); controller.setFitToScreenOnLayout(true); controller.registerComponentFactory(pipelineComponentFactory); @@ -92,7 +99,6 @@ export const PipelineLayout = React.memo(() => { ? GROUPED_PIPELINE_NODE_SEPARATION_HORIZONTAL : GROUPED_PIPELINE_NODE_SEPARATION_HORIZONTAL, ignoreGroups: true, - // nodeDistance: -20, }), ); controller.fromModel( @@ -113,7 +119,7 @@ export const PipelineLayout = React.memo(() => { return ( - + ); }); diff --git a/plugins/orion/src/components/workflow/topology/TopologyComponent.css b/plugins/orion/src/components/workflow/topology/TopologyComponent.css deleted file mode 100644 index 5100d648b6..0000000000 --- a/plugins/orion/src/components/workflow/topology/TopologyComponent.css +++ /dev/null @@ -1,4 +0,0 @@ -.pf-ri__topology-demo { - width: 100%; - height: 35%; -} diff --git a/plugins/orion/src/components/workflow/topology/WorkFlowStepper.tsx b/plugins/orion/src/components/workflow/topology/WorkFlowStepper.tsx index d6a3423f05..f7bbf26b4b 100644 --- a/plugins/orion/src/components/workflow/topology/WorkFlowStepper.tsx +++ b/plugins/orion/src/components/workflow/topology/WorkFlowStepper.tsx @@ -2,27 +2,29 @@ import React from 'react'; import '@patternfly/react-core/dist/styles/base.css'; import { PipelineLayout } from './PipelineLayout'; -import './TopologyComponent.css'; +import { makeStyles } from '@material-ui/core'; +import { WorkFlowTask } from './type/WorkFlowTask'; -export const WorkFlowStepper = () => { +const useStyles = makeStyles(theme => ({ + pfRi__topologyDemo: { + width: '100%', + height: '35%', + '& .pf-topology-visualization-surface__svg': { + background: theme.palette.background.default, + }, + }, +})); + +type Props = { + tasks: WorkFlowTask[]; + setSelectedTask: (selectedTask: string) => void; +}; + +export const WorkFlowStepper = (props: Props) => { + const classes = useStyles(); return ( -
- +
+
); }; - -// export const WorkFlowStepper = () => { -// return ( -// -// -// Lorem Ipsum -// -// -// You are onboarding: org-name/new-project -// -// -// -// -// ); -// }; diff --git a/plugins/orion/src/components/workflow/topology/mock/mockLog.ts b/plugins/orion/src/components/workflow/topology/mock/mockLog.ts new file mode 100644 index 0000000000..34c6edf350 --- /dev/null +++ b/plugins/orion/src/components/workflow/topology/mock/mockLog.ts @@ -0,0 +1,16 @@ +export const mockLog = `Starting up task with following steps +info: green 1 +info: green 2 +info: green 3 +error: red 1 +error: red 2 +error: red 3 +warning: yellow 1 +warning: yellow 2 +warning: yellow 3 +error: blue 1 +error: blue 2 +error: blue 3 +error: purple 1 +error: cyan 1 +`; diff --git a/plugins/orion/src/components/workflow/topology/mock/mockTasks.ts b/plugins/orion/src/components/workflow/topology/mock/mockTasks.ts index 3cc2fc37f6..45ae12512e 100644 --- a/plugins/orion/src/components/workflow/topology/mock/mockTasks.ts +++ b/plugins/orion/src/components/workflow/topology/mock/mockTasks.ts @@ -62,3 +62,30 @@ export const mockTasks: WorkFlowTask[] = [ runAfterTasks: [], }, ]; + +export const mockTasks2: WorkFlowTask[] = [ + { + id: `project-information`, + type: DEFAULT_TASK_NODE_TYPE, + label: `Project Information`, + status: 'completed', + locked: false, + runAfterTasks: [], + }, + { + id: `SSL Certification`, + type: DEFAULT_TASK_NODE_TYPE, + label: `SSL Certification`, + status: 'in_progress', + locked: false, + runAfterTasks: [`project-information`], + }, + { + id: `AD Groups`, + type: DEFAULT_TASK_NODE_TYPE, + label: `AD Groups`, + status: 'completed', + locked: false, + runAfterTasks: [`project-information`], + }, +]; diff --git a/plugins/orion/src/components/workflow/topology/useDemoPipelineNodes.tsx b/plugins/orion/src/components/workflow/topology/useDemoPipelineNodes.tsx index 787fe98749..69e47bde9e 100644 --- a/plugins/orion/src/components/workflow/topology/useDemoPipelineNodes.tsx +++ b/plugins/orion/src/components/workflow/topology/useDemoPipelineNodes.tsx @@ -5,9 +5,8 @@ import { WhenStatus, } from '@patternfly/react-topology'; import '@patternfly/react-styles/css/components/Topology/topology-components.css'; -import { mockTasks } from './mock/mockTasks'; import LockIcon from '@material-ui/icons/Lock'; -import './TopologyComponent.css'; +import { WorkFlowTask } from './type/WorkFlowTask'; export const NODE_PADDING_VERTICAL = 15; export const NODE_PADDING_HORIZONTAL = 10; @@ -16,10 +15,7 @@ export const DEFAULT_TASK_WIDTH = 200; export const DEFAULT_TASK_HEIGHT = 30; export const useDemoPipelineNodes = ( - showContextMenu: boolean, - showBadges: boolean, - showIcons: boolean, - badgeTooltips: boolean, + workflowTasks: WorkFlowTask[], ): PipelineNodeModel[] => React.useMemo(() => { const getStatus: any = (status: string) => { @@ -35,22 +31,16 @@ export const useDemoPipelineNodes = ( }; // Create a task node for each task status - const tasks = mockTasks.map(workFlowTask => { + const tasks = workflowTasks.map(workFlowTask => { // Set all the standard fields const task: PipelineNodeModel = { id: workFlowTask.id, type: workFlowTask.type, label: workFlowTask.label, - width: - DEFAULT_TASK_WIDTH + - (showContextMenu ? 10 : 0) + - (showBadges ? 40 : 0), + width: DEFAULT_TASK_WIDTH, height: DEFAULT_TASK_HEIGHT, style: { - padding: [ - NODE_PADDING_VERTICAL, - NODE_PADDING_HORIZONTAL + (showIcons ? 25 : 0), - ], + padding: [NODE_PADDING_VERTICAL, NODE_PADDING_HORIZONTAL + 25], }, runAfterTasks: workFlowTask.runAfterTasks, }; @@ -58,12 +48,7 @@ export const useDemoPipelineNodes = ( // put options in data, our DEMO task node will pass them along to the TaskNode task.data = { status: getStatus(workFlowTask.status), - badge: showBadges ? '3/4' : undefined, - badgeTooltips, taskIcon: workFlowTask.locked ? : null, - taskIconTooltip: showIcons ? 'Environment' : undefined, - showContextMenu, - // columnGroup: index % STATUS_PER_ROW }; return task; @@ -75,5 +60,5 @@ export const useDemoPipelineNodes = ( task.data.whenStatus = getConditionMet(task.data.status); }); - return [...tasks]; // , ...finallyNodes, finallyGroup]; - }, [badgeTooltips, showBadges, showContextMenu, showIcons]); + return tasks; + }, [workflowTasks]);