Skip to content

Commit

Permalink
feat(managed): Add status popovers, new props for HoverablePopover
Browse files Browse the repository at this point in the history
  • Loading branch information
Erik Munson authored and erikmunson committed Nov 5, 2019
1 parent 88b8e6c commit 5acb0d0
Show file tree
Hide file tree
Showing 2 changed files with 155 additions and 10 deletions.
Original file line number Diff line number Diff line change
@@ -1,63 +1,189 @@
import * as React from 'react';
import * as ReactGA from 'react-ga';
import * as classNames from 'classnames';
import { UISref } from '@uirouter/react';

import { HoverablePopover } from 'core/presentation';
import { IManagedResourceSummary } from 'core/managed';

import './ManagedResourceStatusIndicator.less';

const resourceStatusToClassNames = {
const viewConfigurationByStatus = {
ACTUATING: {
iconClass: 'icon-md-actuating',
colorClass: 'info',
popoverContents: (id: string) => (
<>
<p>
<b>Action is being taken to resolve a drift from the declarative configuration.</b>
</p>
<p>
Check the{' '}
<UISref to="home.applications.application.tasks">
<a>tasks view</a>
</UISref>{' '}
to see work that's in progress. <LearnMoreLink id={id} />
</p>
</>
),
},
CREATED: {
iconClass: 'icon-md-created',
colorClass: 'info',
popoverContents: (id: string) => (
<>
<p>
<b>Spinnaker has started continuously managing this resource.</b>
</p>
<p>
If its actual configuration drifts from the declarative configuration, Spinnaker will automatically correct
it. Changes made in the UI will be stomped in favor of the declarative configuration.{' '}
<LearnMoreLink id={id} />
</p>
</>
),
},
DIFF: {
iconClass: 'icon-md-diff',
colorClass: 'info',
popoverContents: (id: string) => (
<>
<p>
<b>A drift from the declarative configuration was detected.</b>
</p>
<p>
Spinnaker will automatically take action to bring this resource back to its desired state.{' '}
<LearnMoreLink id={id} />
</p>
</>
),
},
ERROR: {
iconClass: 'icon-md-error',
colorClass: 'error',
popoverContents: (id: string) => (
<>
<p>
<b>Something went wrong.</b>
</p>
<p>
Spinnaker is configured to continuously manage this resource, but something went wrong trying to check its
current state. Automatic action can't be taken right now, and manual intervention might be required.{' '}
<LearnMoreLink id={id} />
</p>
</>
),
},
HAPPY: {
iconClass: 'icon-md',
colorClass: 'info',
popoverContents: (id: string) => (
<>
<p>
<b>Spinnaker is continuously managing this resource.</b>
</p>
<p>
Changes made in the UI will be stomped in favor of the declarative configuration. <LearnMoreLink id={id} />
</p>
</>
),
},
PAUSED: {
iconClass: 'icon-md-paused',
colorClass: 'warning',
popoverContents: (id: string) => (
<>
<p>
<b>Continuous management is paused.</b>
</p>
<p>
Spinnaker is configured to continuously manage this resource, but management is temporarily paused. You can
resume management on the{' '}
<UISref to="home.applications.application.config" params={{ section: 'managed-resources' }}>
<a>config view</a>
</UISref>
. <LearnMoreLink id={id} />
</p>
</>
),
},
UNHAPPY: {
iconClass: 'icon-md-flapping',
colorClass: 'error',
popoverContents: (id: string) => (
<>
<p>
<b>A drift from the declarative configuration was detected, but Spinnaker hasn't been able to correct it.</b>
</p>
<p>
Spinnaker has been trying to correct a detected drift, but taking automatic action hasn't helped. Manual
intervention might be required.
</p>
<p>
You can temporarily pause management on the{' '}
<UISref to="home.applications.application.config" params={{ section: 'managed-resources' }}>
<a>config view</a>
</UISref>{' '}
to troubleshoot or make manual changes. <LearnMoreLink id={id} />
</p>
</>
),
},
UNKNOWN: {
iconClass: 'icon-md-unknown',
colorClass: 'warning',
popoverContents: (id: string) => (
<>
<p>
<b>Unable to determine resource status.</b>
</p>
<p>
Spinnaker is configured to continuously manage this resource, but its current status can't be calculated right
now. <LearnMoreLink id={id} />
</p>
</>
),
},
};

const logClick = (label: string, resourceId: string) =>
ReactGA.event({
category: 'Managed Resource Status Indicator',
action: `${label} clicked`,
label: resourceId,
});

const LearnMoreLink = ({ id }: { id: string }) => (
<a
target="_blank"
onClick={() => logClick('Learn More', id)}
href="https://www.spinnaker.io/reference/managed-delivery"
>
Learn More
</a>
);

export interface IManagedResourceStatusIndicatorProps {
shape: 'square' | 'circle';
resourceSummary: IManagedResourceSummary;
}

export const ManagedResourceStatusIndicator = ({
shape,
resourceSummary: { status },
resourceSummary: { id, status },
}: IManagedResourceStatusIndicatorProps) => {
return (
<div
className={classNames(
<HoverablePopover
template={viewConfigurationByStatus[status].popoverContents(id)}
placement="left"
style={{ display: 'flex' }}
wrapperClassName={classNames(
'flex-container-h middle ManagedResourceStatusIndicator',
shape,
resourceStatusToClassNames[status].colorClass,
viewConfigurationByStatus[status].colorClass,
)}
>
<i className={classNames('fa', resourceStatusToClassNames[status].iconClass)} />
</div>
<i className={classNames('fa', viewConfigurationByStatus[status].iconClass)} />
</HoverablePopover>
);
};
25 changes: 22 additions & 3 deletions app/scripts/modules/core/src/presentation/HoverablePopover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@ export interface IHoverablePopoverProps extends React.HTMLProps<any> {
hOffsetPercent?: string;
/** class to put on the popover content */
className?: string;

/** class to put on the outermost element */
wrapperClassName?: string;
/** custom style attributes */
style?: React.CSSProperties;
/** Rendered on the top of the popover content */
title?: string;
id?: string;
Expand Down Expand Up @@ -146,7 +149,18 @@ export class HoverablePopover extends React.Component<IHoverablePopoverProps, IH
};

public render() {
const { Component, template, placement, container, hOffsetPercent, id, title, className } = this.props;
const {
Component,
template,
placement,
container,
hOffsetPercent,
id,
title,
className,
wrapperClassName,
style,
} = this.props;
const { popoverIsOpen, animation, placementOverride } = this.state;
const { Wrapper } = this;

Expand All @@ -157,7 +171,12 @@ export class HoverablePopover extends React.Component<IHoverablePopoverProps, IH
);

return (
<Wrapper style={{ display: 'inline' }} onMouseEnter={this.handleMouseEvent} onMouseLeave={this.handleMouseEvent}>
<Wrapper
className={wrapperClassName}
style={{ display: 'inline', ...style }}
onMouseEnter={this.handleMouseEvent}
onMouseLeave={this.handleMouseEvent}
>
{this.props.children}
<Overlay
show={popoverIsOpen}
Expand Down

0 comments on commit 5acb0d0

Please sign in to comment.