-
Notifications
You must be signed in to change notification settings - Fork 903
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor(core/delivery): Convert ExecutionDetails to react (#4282)
- Loading branch information
Justin Reynolds
authored
Oct 20, 2017
1 parent
5ab83af
commit 5ca919a
Showing
51 changed files
with
758 additions
and
656 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
193 changes: 191 additions & 2 deletions
193
app/scripts/modules/core/src/delivery/details/ExecutionDetails.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,197 @@ | ||
import * as React from 'react'; | ||
import { Subscription } from 'rxjs'; | ||
|
||
import { Application } from 'core/application/application.model'; | ||
import { IExecution } from 'core/domain'; | ||
import { IExecution, IExecutionStage, IExecutionStageSummary, IStageTypeConfig } from 'core/domain'; | ||
import { ReactInjector } from 'core/reactShims'; | ||
import { StageDetails } from './StageDetails'; | ||
import { StageSummary } from './StageSummary'; | ||
|
||
import './executionDetails.less'; | ||
|
||
export interface IExecutionDetailsProps { | ||
application: Application; | ||
execution: IExecution; | ||
standalone: boolean; | ||
standalone?: boolean; | ||
} | ||
|
||
export interface IExecutionDetailsState { | ||
detailsStageConfig: IStageTypeConfig; | ||
stageSummary: IExecutionStageSummary; | ||
stage: IExecutionStage; | ||
summaryStageConfig: IStageTypeConfig; | ||
} | ||
|
||
export interface IExecutionStateParams { | ||
stage?: number; | ||
subStage?: number; | ||
step?: number; | ||
stageId?: string; | ||
refId?: string; | ||
} | ||
|
||
export class ExecutionDetails extends React.Component<IExecutionDetailsProps, IExecutionDetailsState> { | ||
public static defaultProps: Partial<IExecutionDetailsProps> = { | ||
standalone: false | ||
}; | ||
|
||
private groupsUpdatedSubscription: Subscription; | ||
private locationChangeUnsubscribe: Function; | ||
|
||
constructor(props: IExecutionDetailsProps) { | ||
super(props); | ||
this.state = this.getUpdatedState(); | ||
} | ||
|
||
private getStageParamsFromStageId(stageId: string, summaries: IExecutionStageSummary[]): IExecutionStateParams { | ||
let stage, subStage, step; | ||
summaries.some((summary, index) => { | ||
let stepIndex = (summary.stages || []).findIndex(s2 => s2.id === stageId); | ||
if (stepIndex !== -1) { | ||
step = stepIndex; | ||
stage = index; | ||
return true; | ||
} | ||
if (summary.type === 'group' && summary.groupStages) { | ||
summary.groupStages.some((groupStage, subIndex) => { | ||
stepIndex = (groupStage.stages || []).findIndex((gs) => gs.id === stageId); | ||
if (stepIndex !== -1) { | ||
step = stepIndex; | ||
stage = index; | ||
subStage = subIndex; | ||
return true; | ||
} | ||
return false; | ||
}); | ||
} | ||
return false; | ||
}); | ||
|
||
if (stage) { | ||
return { stage, subStage, step, stageId: null }; | ||
} | ||
return null; | ||
} | ||
|
||
private getStageParamsFromRefId(refId: string, summaries: IExecutionStageSummary[]): IExecutionStateParams { | ||
let stage, subStage; | ||
|
||
const stageIndex = summaries.findIndex((summary) => summary.refId === refId); | ||
if (stageIndex !== -1) { | ||
return { stage: stageIndex, refId: null }; | ||
} | ||
|
||
summaries.some((summary, index) => { | ||
if (summary.type === 'group' && summary.groupStages) { | ||
const subStageIndex = summary.groupStages.findIndex(s2 => s2.refId === refId); | ||
if (subStageIndex !== -1) { | ||
stage = index; | ||
subStage = subStageIndex; | ||
return true; | ||
} | ||
} | ||
return false; | ||
}); | ||
if (stage && subStage !== undefined) { | ||
return { stage, subStage, refId: null }; | ||
} | ||
|
||
return { refId: null }; | ||
} | ||
|
||
private getCurrentStage(summaries: IExecutionStageSummary[]): { stage: number, subStage: number } { | ||
const { $state, $stateParams } = ReactInjector; | ||
if ($stateParams.stageId) { | ||
const params = this.getStageParamsFromStageId($stateParams.stageId, summaries); | ||
if (params) { | ||
$state.go('.', params, { location: 'replace' }); | ||
return { stage: params.stage, subStage: params.subStage }; | ||
} | ||
} | ||
if ($stateParams.refId) { | ||
const params = this.getStageParamsFromRefId($stateParams.refId, summaries); | ||
if (params) { | ||
$state.go('.', params, { location: 'replace' }); | ||
return { stage: params.stage, subStage: params.subStage }; | ||
} | ||
} | ||
|
||
return { stage: parseInt($stateParams.stage, 10), subStage: parseInt($stateParams.subStage, 10) }; | ||
} | ||
|
||
private getCurrentStep() { | ||
return parseInt(ReactInjector.$stateParams.step, 10); | ||
} | ||
|
||
private getStageSummary() { | ||
const stages = this.props.execution.stageSummaries || []; | ||
const { stage, subStage } = this.getCurrentStage(stages); | ||
let currentStage = null; | ||
if (stage !== undefined) { | ||
currentStage = stages[stage]; | ||
if (currentStage && subStage !== undefined && currentStage.groupStages) { | ||
currentStage = currentStage.groupStages[subStage]; | ||
} | ||
} | ||
return currentStage; | ||
} | ||
|
||
private getDetailsStageConfig(stageSummary: IExecutionStageSummary): IStageTypeConfig { | ||
if (stageSummary && ReactInjector.$stateParams.step !== undefined) { | ||
const step = stageSummary.stages[this.getCurrentStep()] || stageSummary.masterStage; | ||
return ReactInjector.pipelineConfig.getStageConfig(step); | ||
} | ||
return null; | ||
} | ||
|
||
private getSummaryStageConfig(stageSummary: IExecutionStageSummary): IStageTypeConfig { | ||
if (stageSummary && ReactInjector.$stateParams.stage !== undefined) { | ||
return ReactInjector.pipelineConfig.getStageConfig(stageSummary); | ||
} | ||
return {} as IStageTypeConfig; | ||
} | ||
|
||
public getUpdatedState(): IExecutionDetailsState { | ||
const stageSummary = this.getStageSummary(); | ||
if (stageSummary) { | ||
const stage = stageSummary.stages[this.getCurrentStep()] || stageSummary.masterStage; | ||
const summaryStageConfig = this.getSummaryStageConfig(stageSummary); | ||
const detailsStageConfig = this.getDetailsStageConfig(stageSummary); | ||
return { stageSummary, stage, summaryStageConfig, detailsStageConfig }; | ||
} | ||
return {} as IExecutionDetailsState; | ||
} | ||
|
||
public updateStage() { | ||
this.setState(this.getUpdatedState()); | ||
} | ||
|
||
public componentDidMount(): void { | ||
this.locationChangeUnsubscribe = ReactInjector.$uiRouter.transitionService.onSuccess({}, () => this.updateStage()); | ||
// Since stages and tasks can get updated without the reference to the execution changing, subscribe to the execution updated stream here too | ||
this.groupsUpdatedSubscription = ReactInjector.executionFilterService.groupsUpdatedStream.subscribe(() => this.updateStage()); | ||
|
||
this.updateStage(); | ||
} | ||
|
||
public componentWillReceiveProps() { | ||
this.updateStage(); | ||
} | ||
|
||
public componentWillUnmount(): void { | ||
this.groupsUpdatedSubscription.unsubscribe(); | ||
this.locationChangeUnsubscribe(); | ||
} | ||
|
||
public render() { | ||
const { application, execution } = this.props; | ||
const { detailsStageConfig, stage, stageSummary, summaryStageConfig } = this.state; | ||
|
||
return ( | ||
<div className="execution-details"> | ||
<StageSummary application={application} execution={execution} config={summaryStageConfig} stage={stage} stageSummary={stageSummary} /> | ||
<StageDetails application={application} execution={execution} stage={stage} config={detailsStageConfig} /> | ||
</div> | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
70 changes: 70 additions & 0 deletions
70
app/scripts/modules/core/src/delivery/details/StageDetails.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import * as React from 'react'; | ||
import { BindAll } from 'lodash-decorators'; | ||
|
||
import { Application } from 'core/application'; | ||
import { IExecution, IExecutionStage, IStageTypeConfig } from 'core/domain'; | ||
import { NgReact } from 'core/reactShims'; | ||
import { StatusGlyph } from 'core/task/StatusGlyph'; | ||
import { robotToHuman } from 'core/presentation/robotToHumanFilter/robotToHuman.filter'; | ||
|
||
export interface IStageDetailsProps { | ||
application: Application; | ||
config: IStageTypeConfig; | ||
execution: IExecution; | ||
stage: IExecutionStage; | ||
} | ||
|
||
export interface IStageDetailsState { | ||
sourceUrl?: string; | ||
configSections?: string[]; | ||
} | ||
|
||
@BindAll() | ||
export class StageDetails extends React.Component<IStageDetailsProps, IStageDetailsState> { | ||
constructor(props: IStageDetailsProps) { | ||
super(props); | ||
this.state = this.getState(); | ||
} | ||
|
||
private getState(): IStageDetailsState { | ||
let configSections: string[] = []; | ||
let sourceUrl = require('./defaultExecutionDetails.html'); | ||
|
||
const stageConfig = this.props.config; | ||
if (stageConfig) { | ||
if (stageConfig.executionConfigSections) { | ||
configSections = stageConfig.executionConfigSections; | ||
} | ||
if (stageConfig.executionDetailsUrl) { | ||
sourceUrl = stageConfig.executionDetailsUrl; | ||
} | ||
} | ||
return { configSections, sourceUrl }; | ||
} | ||
|
||
public componentWillReceiveProps() { | ||
this.setState(this.getState()); | ||
} | ||
|
||
public render(): React.ReactElement<StageDetails> { | ||
const { application, execution, stage } = this.props; | ||
const { sourceUrl, configSections } = this.state; | ||
|
||
const { StageDetailsWrapper } = NgReact; | ||
|
||
if ( sourceUrl ) { | ||
return ( | ||
<div className="stage-details"> | ||
<div className="stage-details-heading"> | ||
<h5> | ||
<StatusGlyph item={stage} /> | ||
{robotToHuman(stage.name || stage.type)} | ||
</h5> | ||
</div> | ||
<StageDetailsWrapper application={application} execution={execution} sourceUrl={sourceUrl} configSections={configSections} stage={stage} /> | ||
</div> | ||
); | ||
} | ||
return null; | ||
} | ||
} |
10 changes: 10 additions & 0 deletions
10
app/scripts/modules/core/src/delivery/details/StageDetailsWrapper.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import { Application } from 'core/application'; | ||
import { IExecution, IExecutionStage } from 'core/domain'; | ||
|
||
export interface IStageDetailsWrapperProps { | ||
application: Application; | ||
configSections: string[]; | ||
execution: IExecution; | ||
stage: IExecutionStage; | ||
sourceUrl: string; | ||
} |
39 changes: 39 additions & 0 deletions
39
app/scripts/modules/core/src/delivery/details/StageSummary.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import * as React from 'react'; | ||
import { BindAll } from 'lodash-decorators'; | ||
|
||
import { Application } from 'core/application'; | ||
import { IExecution, IExecutionStage, IExecutionStageSummary, IStageTypeConfig } from 'core/domain'; | ||
import { NgReact } from 'core/reactShims'; | ||
|
||
export interface IStageSummaryProps { | ||
application: Application; | ||
execution: IExecution; | ||
config: IStageTypeConfig; | ||
stage: IExecutionStage; | ||
stageSummary: IExecutionStageSummary; | ||
} | ||
|
||
export interface IStageSummaryState { | ||
} | ||
|
||
@BindAll() | ||
export class StageSummary extends React.Component<IStageSummaryProps, IStageSummaryState> { | ||
|
||
private getSourceUrl(): string { | ||
return this.props.config.executionSummaryUrl || require('../../pipeline/config/stages/core/executionSummary.html'); | ||
} | ||
|
||
public render(): React.ReactElement<StageSummary> { | ||
const sourceUrl = this.getSourceUrl(); | ||
if (sourceUrl) { | ||
const { application, execution, stage, stageSummary } = this.props; | ||
const { StageSummaryWrapper } = NgReact; | ||
return ( | ||
<div className="stage-summary"> | ||
<StageSummaryWrapper application={application} execution={execution} sourceUrl={sourceUrl} stage={stage} stageSummary={stageSummary} /> | ||
</div> | ||
); | ||
} | ||
return null; | ||
} | ||
} |
10 changes: 10 additions & 0 deletions
10
app/scripts/modules/core/src/delivery/details/StageSummaryWrapper.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import { Application } from 'core/application'; | ||
import { IExecution, IExecutionStage, IExecutionStageSummary } from 'core/domain'; | ||
|
||
export interface IStageSummaryWrapperProps { | ||
application: Application; | ||
execution: IExecution; | ||
sourceUrl: string; | ||
stage: IExecutionStage; | ||
stageSummary: IExecutionStageSummary; | ||
} |
21 changes: 0 additions & 21 deletions
21
app/scripts/modules/core/src/delivery/details/executionDetails.component.ts
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.