Skip to content

Commit

Permalink
feat(core/serverGroup): Refactor to smaller components and make them …
Browse files Browse the repository at this point in the history
…Overridable (#4941)
  • Loading branch information
christopherthielen authored Mar 7, 2018
1 parent b1c112a commit 73e002c
Show file tree
Hide file tree
Showing 4 changed files with 192 additions and 127 deletions.
Original file line number Diff line number Diff line change
@@ -1,52 +1,50 @@
import * as React from 'react';
import { BindAll } from 'lodash-decorators';

import { CollapsibleSection, NgReact, ReactInjector } from '@spinnaker/core';
import { CollapsibleSection, NgReact, Overridable, ReactInjector, Application, IServerGroup } from '@spinnaker/core';

import { IAmazonServerGroupDetailsSectionProps } from './IAmazonServerGroupDetailsSectionProps';

@Overridable('amazon.serverGroup.CapacityDetailsSection')
@BindAll()
export class CapacityDetailsSection extends React.Component<IAmazonServerGroupDetailsSectionProps> {
private resizeServerGroup(): void {
public static resizeServerGroup(serverGroup: IServerGroup, application: Application): void {
ReactInjector.modalService.open({
templateUrl: ReactInjector.overrideRegistry.getTemplate('aws.resize.modal', require('../resize/resizeServerGroup.html')),
controller: 'awsResizeServerGroupCtrl as ctrl',
resolve: {
serverGroup: () => this.props.serverGroup,
application: () => this.props.app
serverGroup: () => serverGroup,
application: () => application,
}
});
}

public render(): JSX.Element {
const { serverGroup } = this.props;
const { serverGroup, app } = this.props;
const { ViewScalingActivitiesLink } = NgReact;
const simple = serverGroup.asg.minSize === serverGroup.asg.maxSize;

return (
<CollapsibleSection heading="Capacity" defaultExpanded={true}>
{serverGroup.asg.minSize === serverGroup.asg.maxSize && (
<dl className="dl-horizontal dl-flex">
<dt>Min/Max</dt>
<dd>{serverGroup.asg.desiredCapacity}</dd>
<dt>Current</dt>
<dd>{serverGroup.instances.length}</dd>
</dl>
)}
{serverGroup.asg.minSize !== serverGroup.asg.maxSize && (
<dl className="dl-horizontal dl-flex">
<dt>Min</dt>
<dd>{serverGroup.asg.minSize}</dd>
<dt>Desired</dt>
<dd>{serverGroup.asg.desiredCapacity}</dd>
<dt>Max</dt>
<dd>{serverGroup.asg.maxSize}</dd>
<dt>Current</dt>
<dd>{serverGroup.instances.length}</dd>
</dl>
)}
<dl className="dl-horizontal dl-flex">
{simple && <dt>Min/Max</dt>}
{simple && <dd>{serverGroup.asg.desiredCapacity}</dd>}

{!simple && <dt>Min</dt>}
{!simple && <dd>{serverGroup.asg.minSize}</dd>}
{!simple && <dt>Desired</dt>}
{!simple && <dd>{serverGroup.asg.desiredCapacity}</dd>}
{!simple && <dt>Max</dt>}
{!simple && <dd>{serverGroup.asg.maxSize}</dd>}

<dt>Current</dt>
<dd>{serverGroup.instances.length}</dd>
</dl>

<div>
<a className="clickable" onClick={this.resizeServerGroup}>Resize Server Group</a>
<a className="clickable" onClick={() => CapacityDetailsSection.resizeServerGroup(serverGroup, app)}>Resize Server Group</a>
</div>

<div>
<ViewScalingActivitiesLink serverGroup={serverGroup}/>
</div>
Expand Down
125 changes: 24 additions & 101 deletions app/scripts/modules/core/src/serverGroup/ServerGroup.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,19 @@
import * as React from 'react';
import * as ReactGA from 'react-ga';
import { has, get } from 'lodash';
import { has } from 'lodash';
import * as classNames from 'classnames';
import { BindAll } from 'lodash-decorators';
import { Subscription } from 'rxjs';

import { ReactInjector } from 'core/reactShims';
import { Application } from 'core/application';
import { CloudProviderLogo } from 'core/cloudProvider';
import { IInstance, IServerGroup } from 'core/domain';
import { EntityNotifications } from 'core/entityTag/notifications/EntityNotifications';
import { HealthCounts } from 'core/healthCounts';
import { InstanceList } from 'core/instance/InstanceList';
import { Instances } from 'core/instance/Instances';
import { LoadBalancersTagWrapper } from 'core/loadBalancer';
import { NamingService } from 'core/naming';
import { NgReact, ReactInjector } from 'core/reactShims';
import { ScrollToService } from 'core/utils';
import { ISortFilter } from 'core/filterModel';
import { ServerGroupManagerTag } from 'core/serverGroupManager/ServerGroupManagerTag';

import { ServerGroupHeader } from './ServerGroupHeader';

export interface JenkinsViewModel {
number: number;
Expand All @@ -34,18 +30,10 @@ export interface IServerGroupProps {
}

export interface IServerGroupState {
serverGroup: IServerGroup;
serverGroupSequence: string;
jenkins: JenkinsViewModel;
hasBuildInfo: boolean;
instances: IInstance[];
images?: string;

filter: string;
showAllInstances: boolean;
listInstances: boolean;

multiselect: boolean;
isSelected: boolean; // single select mode
isMultiSelected: boolean; // multiselect mode
}
Expand All @@ -62,12 +50,9 @@ export class ServerGroup extends React.Component<IServerGroupProps, IServerGroup

private getState(props: IServerGroupProps): IServerGroupState {
const { serverGroup } = props;
const { showAllInstances, listInstances, multiselect, filter } = props.sortFilter;
const instances = serverGroup.instances.filter(i => ReactInjector.clusterFilterService.shouldShowInstance(i));
const serverGroupSequence = new NamingService().getSequence(serverGroup.moniker.sequence);
const hasBuildInfo = !!serverGroup.buildInfo;
const isSelected = this.isSelected(serverGroup);
const isMultiSelected = this.isMultiSelected(multiselect, serverGroup);
const isMultiSelected = this.isMultiSelected(props.sortFilter.multiselect, serverGroup);
const jenkinsConfig = serverGroup.buildInfo && serverGroup.buildInfo.jenkins;

let jenkins: JenkinsViewModel = null;
Expand All @@ -80,23 +65,16 @@ export class ServerGroup extends React.Component<IServerGroupProps, IServerGroup

jenkins = {
number: jenkinsConfig.number,
href: fromBuildInfo || fromFullUrl || fromHost ,
href: fromBuildInfo || fromFullUrl || fromHost,
};
} else if (has(serverGroup, 'buildInfo.images')) {
images = serverGroup.buildInfo.images.join(', ');
}

return {
serverGroup,
serverGroupSequence,
jenkins,
hasBuildInfo,
instances,
images,
filter,
showAllInstances,
listInstances,
multiselect,
isSelected,
isMultiSelected,
};
Expand All @@ -118,14 +96,14 @@ export class ServerGroup extends React.Component<IServerGroupProps, IServerGroup
}

private onServerGroupsChanged() {
const isMultiSelected = this.isMultiSelected(this.state.multiselect, this.state.serverGroup);
const isMultiSelected = this.isMultiSelected(this.props.sortFilter.multiselect, this.props.serverGroup);
this.setState({ isMultiSelected });
// Enables the (angular) details pane to detect the changes
ReactInjector.$rootScope.$applyAsync(() => false);
}

private onStateChanged() {
this.setState({ isSelected: this.isSelected(this.state.serverGroup) });
this.setState({ isSelected: this.isSelected(this.props.serverGroup) });
}

public componentDidMount(): void {
Expand All @@ -145,15 +123,6 @@ export class ServerGroup extends React.Component<IServerGroupProps, IServerGroup
this.setState(this.getState(nextProps));
}

public headerIsSticky(): boolean {
const { showAllInstances, listInstances, instances } = this.state;
if (!showAllInstances) {
return false;
}

return listInstances ? instances.length > 1 : instances.length > 20;
}

public loadDetails(event: React.MouseEvent<any>): void {
event.persist();

Expand All @@ -172,17 +141,12 @@ export class ServerGroup extends React.Component<IServerGroupProps, IServerGroup
}

public render() {
const { RunningTasksTag } = NgReact;
const { filter, instances, images, jenkins, isSelected, multiselect, isMultiSelected, showAllInstances, listInstances } = this.state;
const { instances, images, jenkins, isSelected, isMultiSelected } = this.state;
const { serverGroup, application, sortFilter, hasDiscovery, hasLoadBalancers } = this.props;
const { account, region, name, type } = serverGroup;
const { account, region, name } = serverGroup;
const { showAllInstances, listInstances } = sortFilter;
const key = ScrollToService.toDomId(['serverGroup', account, region, name].join('-'));

const hasJenkins = !!jenkins;
const hasImages = !!images;
const hasRunningExecutions = !!serverGroup.runningExecutions.length || !!serverGroup.runningTasks.length;
const hasLoadBalancer = !!get(serverGroup, 'loadBalancers.length') || !!get(serverGroup, 'targetGroups.length');

const serverGroupClassName = classNames({
'server-group': true,
'rollup-pod-server-group': true,
Expand All @@ -192,74 +156,33 @@ export class ServerGroup extends React.Component<IServerGroupProps, IServerGroup
'active': isSelected,
});

const headerClassName = classNames({
'server-group-title': true,
'sticky-header-3': this.headerIsSticky(),
});

const col1ClassName = `col-md-${images ? 9 : 8 } col-sm-6 section-title horizontal bottom`;
const col2ClassName = `col-md-${images ? 3 : 4 } col-sm-6 text-right`;

return (
<div key={key} id={key} className={serverGroupClassName} onClick={this.handleServerGroupClicked}>
<div id={key} className={serverGroupClassName} onClick={this.handleServerGroupClicked}>
<div className="cluster-container">
<div className={headerClassName}>
<div className="container-fluid no-padding">
<div className="row">
<div className={col1ClassName}>
{multiselect && <input type="checkbox" checked={isMultiSelected}/>}

<CloudProviderLogo provider={type} height="16px" width="16px"/>

<span className="server-group-sequence"> {this.state.serverGroupSequence}</span>
{(hasJenkins || hasImages) && <span>: </span>}
{hasJenkins && <a className="build-link" href={jenkins.href} target="_blank">Build: #{jenkins.number}</a>}
{hasImages && <span>{images}</span>}

<EntityNotifications
entity={serverGroup}
application={application}
placement="top"
hOffsetPercent="20%"
entityType="serverGroup"
pageLocation="pod"
onUpdate={() => application.serverGroups.refresh()}
/>
</div>

<div className={col2ClassName}>
<HealthCounts container={serverGroup.instanceCounts}/>

{hasRunningExecutions && (
<RunningTasksTag
application={application}
tasks={serverGroup.runningTasks}
executions={serverGroup.runningExecutions}
/>
)}

{hasLoadBalancer && <LoadBalancersTagWrapper application={application} serverGroup={serverGroup}/>}
<ServerGroupManagerTag application={application} serverGroup={serverGroup}/>
</div>
</div>
</div>
</div>
<ServerGroupHeader
application={application}
images={images}
isMultiSelected={isMultiSelected}
jenkins={jenkins}
serverGroup={serverGroup}
sortFilter={sortFilter}
/>

{showAllInstances && (
<div className="instance-list">
{listInstances ? (
<div>
<InstanceList
serverGroup={serverGroup}
instances={instances}
sortFilter={sortFilter}
hasDiscovery={hasDiscovery}
hasLoadBalancers={hasLoadBalancers}
instances={instances}
serverGroup={serverGroup}
sortFilter={sortFilter}
/>
</div>
) : (
<div>
<Instances highlight={filter} instances={instances}/>
<Instances highlight={sortFilter.filter} instances={instances}/>
</div>
)}
</div>
Expand Down
Loading

0 comments on commit 73e002c

Please sign in to comment.