import { UISref } from '@uirouter/react'; import { isEmpty } from 'lodash'; import React from 'react'; import { ExecutionMarkerInformationModal } from './ExecutionMarkerInformationModal'; import { OrchestratedItemRunningTime } from './OrchestratedItemRunningTime'; import type { Application } from '../../../application/application.model'; import { SETTINGS } from '../../../config/settings'; import { ExecutionBarLabel } from '../../config/stages/common/ExecutionBarLabel'; import type { IExecution, IExecutionStageSummary, IStage } from '../../../domain'; import { logger } from '../../../utils'; import { duration } from '../../../utils/timeFormatters'; import './executionMarker.less'; export interface IExecutionMarkerProps { active?: boolean; application: Application; execution: IExecution; onClick: (stageIndex: number) => void; previousStageActive?: boolean; stage: IExecutionStageSummary; width: string; } export interface IExecutionMarkerState { duration: string; hydrated: boolean; showingExecutionMarkerInformationModal: boolean; } export class ExecutionMarker extends React.Component { private runningTime: OrchestratedItemRunningTime; constructor(props: IExecutionMarkerProps) { super(props); const { stage, execution } = props; this.state = { duration: duration(stage.runningTimeInMs), hydrated: execution.hydrated, showingExecutionMarkerInformationModal: false, }; } public componentDidMount() { this.runningTime = new OrchestratedItemRunningTime(this.props.stage, (time: number) => this.setState({ duration: duration(time) }), ); } public componentWillReceiveProps(nextProps: IExecutionMarkerProps) { this.runningTime.checkStatus(nextProps.stage); } public componentWillUnmount() { this.runningTime.reset(); } private handleStageClick = (): void => { logger.log({ category: 'Pipeline', action: 'Stage clicked (bar)' }); this.props.onClick(this.props.stage.index); }; private handleStageInformationClick = (event: any): void => { logger.log({ category: 'Pipeline', action: 'Stage show context menu (bar)' }); event.preventDefault(); event.stopPropagation(); this.showExecutionMarkerInformationModal(); }; private showExecutionMarkerInformationModal = () => { this.setState({ showingExecutionMarkerInformationModal: true, }); }; private hideExecutionMarkerInformationModal = () => { this.setState({ showingExecutionMarkerInformationModal: false, }); }; private stageStatus = (stageStatus: string) => { if (stageStatus === 'running') { const currentStatus = this.props.stage.stages.filter( (stage) => stage.status.toLowerCase() === 'running' && stage.type === 'pipeline' && !isEmpty(stage.others), ); if (!isEmpty(currentStatus)) return 'waiting'; } return stageStatus; }; public render() { const { stage, application, execution, active, previousStageActive, width } = this.props; let stageType = (stage.activeStageType || stage.type).toLowerCase(); // support groups if (SETTINGS.feature.manualJudgmentParentPipeline) { stage.stages.forEach((childStage: IStage) => { if ( childStage.type == 'pipeline' && application.executions != undefined && application.executions.data != undefined ) { const childPipeline = application.executions.data.find((p: any) => p.id === childStage.context.executionId); if (childPipeline != undefined) { childPipeline.stages.forEach((stageToCheck: IStage) => { if (stageToCheck.type == 'manualJudgment' && stageToCheck.status == 'RUNNING') { stageType = 'manualjudgment'; } }); } } }); } const pipelineStatus = this.stageStatus(stage.status.toLowerCase()); const markerClassName = [ stage.type !== 'group' ? 'clickable' : '', 'stage', 'execution-marker', `stage-type-${stageType}`, `execution-marker-${pipelineStatus}`, active ? 'active' : '', previousStageActive ? 'after-active' : '', stage.isRunning ? 'glowing' : '', stage.requiresAttention ? 'requires-attention' : '', ].join(' '); const TooltipComponent = stage.useCustomTooltip ? stage.labelComponent : ExecutionBarLabel; const MarkerIcon = stage.markerIcon; const showInfoIcon = SETTINGS.feature.executionMarkerInformationModal && stage.status.toLowerCase() === 'terminal' && stage.type === 'pipeline'; const stageContents = pipelineStatus === 'waiting' ? (
waiting {}
) : (
{this.state.duration} {showInfoIcon && }
); return ( {stageContents} {this.state.showingExecutionMarkerInformationModal && ( )} ); } }