Skip to content

Commit

Permalink
refactor(core/delivery): Convert waitExecutionDetails to react (#4297)
Browse files Browse the repository at this point in the history
  • Loading branch information
Justin Reynolds authored Oct 21, 2017
1 parent 26aad5e commit 9dcc554
Show file tree
Hide file tree
Showing 15 changed files with 186 additions and 109 deletions.
46 changes: 25 additions & 21 deletions app/scripts/modules/core/src/delivery/details/StageDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as React from 'react';
import { BindAll } from 'lodash-decorators';

import { Application } from 'core/application';
import { IExecution, IExecutionStage, IStageTypeConfig } from 'core/domain';
import { IExecution, IExecutionDetailsComponentProps, IExecutionStage, IStageTypeConfig } from 'core/domain';
import { NgReact } from 'core/reactShims';
import { StatusGlyph } from 'core/task/StatusGlyph';
import { robotToHuman } from 'core/presentation/robotToHumanFilter/robotToHuman.filter';
Expand All @@ -15,8 +15,9 @@ export interface IStageDetailsProps {
}

export interface IStageDetailsState {
sourceUrl?: string;
configSections?: string[];
ReactComponent?: React.ComponentClass<IExecutionDetailsComponentProps>;
sourceUrl?: string;
}

@BindAll()
Expand All @@ -28,18 +29,23 @@ export class StageDetails extends React.Component<IStageDetailsProps, IStageDeta

private getState(): IStageDetailsState {
let configSections: string[] = [];
let sourceUrl = require('./defaultExecutionDetails.html');
let sourceUrl: string;
let ReactComponent: React.ComponentClass<IExecutionDetailsComponentProps>;

const stageConfig = this.props.config;
if (stageConfig) {
if (stageConfig.executionConfigSections) {
configSections = stageConfig.executionConfigSections;
}
if (stageConfig.executionDetailsUrl) {
sourceUrl = stageConfig.executionDetailsUrl;
if (stageConfig.executionDetailsComponent) {
// React execution details
ReactComponent = stageConfig.executionDetailsComponent;
} else {
// Angular execution details
sourceUrl = stageConfig.executionDetailsUrl || require('./defaultExecutionDetails.html');
}
}
return { configSections, sourceUrl };
return { configSections, ReactComponent, sourceUrl };
}

public componentWillReceiveProps() {
Expand All @@ -48,23 +54,21 @@ export class StageDetails extends React.Component<IStageDetailsProps, IStageDeta

public render(): React.ReactElement<StageDetails> {
const { application, execution, stage } = this.props;
const { sourceUrl, configSections } = this.state;

const { ReactComponent, sourceUrl, configSections } = this.state;
const { StageDetailsWrapper } = NgReact;
const detailsProps = { application, execution, stage, configSections };

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} />
return (
<div className="stage-details">
<div className="stage-details-heading">
<h5>
<StatusGlyph item={stage} />
{robotToHuman(stage.name || stage.type)}
</h5>
</div>
);
}
return null;
{sourceUrl && <StageDetailsWrapper {...detailsProps} sourceUrl={sourceUrl} />}
{ReactComponent && <ReactComponent {...detailsProps} />}
</div>
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import * as React from 'react';
import { isEqual } from 'lodash';

import { IExecutionDetailsComponentProps, IExecutionDetailsComponentState } from 'core/domain';
import { ReactInjector } from 'core/reactShims';

export function stageExecutionDetails(WrappedStageExecutionDetails: React.ComponentClass<IExecutionDetailsComponentProps>): React.ComponentClass<IExecutionDetailsComponentProps> {
return class extends React.Component<IExecutionDetailsComponentProps, IExecutionDetailsComponentState> {
constructor(props: IExecutionDetailsComponentProps) {
super(props);
this.state = {
detailsSection: null,
}
}

public updateDetailsSection(): void {
const detailsSection = ReactInjector.$stateParams.details;
if (this.state.detailsSection !== detailsSection) {
this.setState({detailsSection});
}
}

public syncDetails(props: IExecutionDetailsComponentProps): void {
ReactInjector.executionDetailsSectionService.synchronizeSection(props.configSections, () => this.updateDetailsSection());
}

public componentDidMount(): void {
this.syncDetails(this.props);
}

public componentWillReceiveProps(nextProps: IExecutionDetailsComponentProps): void {
if (!isEqual(nextProps.configSections, this.props.configSections)) {
this.syncDetails(nextProps);
}
}

public render() {
return (
<WrappedStageExecutionDetails detailsSection={this.state.detailsSection} {...this.props} />
);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import * as React from 'react';
import { get } from 'lodash';

import { IStage } from 'core/domain';

export const StageExecutionLogs = (props: { stage: IStage }): JSX.Element => {
const logs = get<string>(props.stage, 'context.execution.logs');
if (!logs) { return null; }

return (
<div className="row">
<div className="col-md-12">
<div className="well alert alert-info">
<a target="_blank" href={logs}>
View Execution Logs
</a>
</div>
</div>
</div>
);
}
4 changes: 4 additions & 0 deletions app/scripts/modules/core/src/delivery/details/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export * from './ExecutionDetailsSectionNav';
export * from './StageExecutionDetails';
export * from './StageExecutionLogs';
export * from './StageFailureMessage';
12 changes: 12 additions & 0 deletions app/scripts/modules/core/src/domain/IExecutionStage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,18 @@ export interface IExecutionStageLabelComponentProps {
stage: IExecutionStageSummary;
}

export interface IExecutionDetailsComponentProps {
application: Application;
configSections: string[];
detailsSection?: string;
execution: IExecution;
stage: IExecutionStage;
}

export interface IExecutionDetailsComponentState {
detailsSection: string;
}

export interface IExecutionStageSummary extends IOrchestratedItem {
activeStageType?: string,
after: IExecutionStage[];
Expand Down
3 changes: 2 additions & 1 deletion app/scripts/modules/core/src/domain/IStageTypeConfig.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { IStage } from './IStage';
import { IExecutionStageLabelComponentProps, IExecutionStageSummary } from './IExecutionStage';
import { IExecutionDetailsComponentProps, IExecutionStageLabelComponentProps, IExecutionStageSummary } from './IExecutionStage';
import { IStageOrTriggerTypeConfig } from './IStageOrTriggerTypeConfig';

export interface IStageTypeConfig extends IStageOrTriggerTypeConfig {
Expand All @@ -12,6 +12,7 @@ export interface IStageTypeConfig extends IStageOrTriggerTypeConfig {
configuration?: any;
defaultTimeoutMs?: number;
executionConfigSections?: string[];
executionDetailsComponent?: React.ComponentClass<IExecutionDetailsComponentProps>;
executionDetailsUrl?: string;
executionLabelComponent?: React.ComponentClass<IExecutionStageLabelComponentProps>;
executionStepLabelUrl?: string;
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import * as React from 'react';

import { IExecutionDetailsComponentProps } from 'core/domain';
import { ExecutionDetailsSectionNav, StageExecutionLogs, StageFailureMessage } from 'core/delivery/details';
import { ExecutionStepDetails } from 'core/pipeline/config/stages/core/ExecutionStepDetails';
import { SkipWait } from './SkipWait';
import { stageExecutionDetails } from 'core/delivery/details';

class ExecutionDetails extends React.Component<IExecutionDetailsComponentProps> {
public render() {
const { application, configSections, detailsSection, execution, stage } = this.props;
return (
<div>
<ExecutionDetailsSectionNav sections={configSections} />
{detailsSection === 'waitConfig' && (
<div className="step-section-details">
<SkipWait application={application} execution={execution} stage={stage} />
<StageFailureMessage stage={stage} message={stage.failureMessage} />
<StageExecutionLogs stage={stage} />
</div>
)}

{detailsSection === 'taskStatus' && (
<div className="step-section-details">
<div className="row">
<ExecutionStepDetails item={stage} />
</div>
</div>
)}
</div>
);
}
}

export const WaitExecutionDetails = stageExecutionDetails(ExecutionDetails);

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { module } from 'angular';

import { WAIT_STAGE } from './waitStage';

export const WAIT_STAGE_MODULE = 'spinnaker.core.pipeline.stage.wait';
module(WAIT_STAGE_MODULE, [
WAIT_STAGE,
]);
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { module } from 'angular';

import { IStage } from 'core/domain';
import { PIPELINE_CONFIG_PROVIDER, PipelineConfigProvider } from 'core/pipeline/config/pipelineConfigProvider';

import { SKIP_WAIT_COMPONENT } from './skipWait.component';
import { WaitExecutionDetails } from './WaitExecutionDetails';
import { WaitExecutionLabel } from './WaitExecutionLabel';

export const WAIT_STAGE = 'spinnaker.core.pipeline.stage.waitStage';

module(WAIT_STAGE, [
PIPELINE_CONFIG_PROVIDER,
SKIP_WAIT_COMPONENT,
])
.config((pipelineConfigProvider: PipelineConfigProvider) => {
pipelineConfigProvider.registerStage({
label: 'Wait',
description: 'Waits a specified period of time',
key: 'wait',
templateUrl: require('./waitStage.html'),
executionDetailsComponent: WaitExecutionDetails,
executionConfigSections: ['waitConfig', 'taskStatus'],
executionLabelComponent: WaitExecutionLabel,
useCustomTooltip: true,
strategy: true,
controller: 'WaitStageCtrl',
validators: [
{ type: 'requiredField', fieldName: 'waitTime' },
],
});
}).controller('WaitStageCtrl', (stage: IStage) => stage.waitTime = stage.waitTime || 30);
3 changes: 2 additions & 1 deletion app/scripts/modules/core/src/pipeline/pipelines.module.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { GROUP_STAGE_MODULE } from './config/stages/group/groupStage.module';
import { STAGE_CORE_MODULE } from './config/stages/core/stage.core.module';
import { TRAVIS_STAGE_MODULE } from './config/stages/travis/travisStage.module';
import { UNMATCHED_STAGE_TYPE_STAGE } from './config/stages/unmatchedStageTypeStage/unmatchedStageTypeStage';
import { WAIT_STAGE_MODULE } from './config/stages/wait/waitStage.module';
import { WEBHOOK_STAGE_MODULE } from './config/stages/webhook/webhookStage.module';

import './pipelines.less';
Expand Down Expand Up @@ -48,7 +49,7 @@ module.exports = angular.module('spinnaker.core.pipeline', [
require('./config/stages/scaleDownCluster/scaleDownClusterStage.module').name,
require('./config/stages/script/scriptStage.module').name,
require('./config/stages/shrinkCluster/shrinkClusterStage.module').name,
require('./config/stages/wait/waitStage.module').name,
WAIT_STAGE_MODULE,
require('./config/stages/waitForParentTasks/waitForParentTasks').name,
CREATE_LOAD_BALANCER_STAGE,
APPLY_SOURCE_SERVER_GROUP_CAPACITY_STAGE,
Expand Down
2 changes: 2 additions & 0 deletions app/scripts/modules/core/src/reactShims/react.injector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { ClusterFilterService } from '../cluster/filter/clusterFilter.service';
import { CollapsibleSectionStateCache } from '../cache/collapsibleSectionStateCache';
import { ConfirmationModalService } from '../confirmationModal/confirmationModal.service';
import { EntityTagWriter} from '../entityTag';
import { ExecutionDetailsSectionService } from 'core/delivery/details/executionDetailsSection.service';
import { ExecutionFilterModel } from '../delivery/filter/executionFilter.model';
import { ExecutionFilterService } from '../delivery/filter/executionFilter.service';
import { ExecutionService } from '../delivery/service/execution.service';
Expand Down Expand Up @@ -80,6 +81,7 @@ export class CoreReactInject extends ReactInject {
public get collapsibleSectionStateCache() { return this.$injector.get('collapsibleSectionStateCache') as CollapsibleSectionStateCache; }
public get confirmationModalService() { return this.$injector.get('confirmationModalService') as ConfirmationModalService; }
public get entityTagWriter() { return this.$injector.get('entityTagWriter') as EntityTagWriter; }
public get executionDetailsSectionService() { return this.$injector.get('executionDetailsSectionService') as ExecutionDetailsSectionService; }
public get executionFilterModel() { return this.$injector.get('executionFilterModel') as ExecutionFilterModel; }
public get executionFilterService() { return this.$injector.get('executionFilterService') as ExecutionFilterService; }
public get executionService() { return this.$injector.get('executionService') as ExecutionService; }
Expand Down

0 comments on commit 9dcc554

Please sign in to comment.