Skip to content

Commit

Permalink
feat(core/managed): Add StatusBubble to denote resource status (#8214)
Browse files Browse the repository at this point in the history
* refactor(core/managed): Adjust spacing in ObjectRow component for including status bubble

* feat(core/managed): Update StatusBubble to include a pill

* feat(core/managed): Add StatsBubble to show the current resource status

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
  • Loading branch information
vigneshm and mergify[bot] committed May 1, 2020
1 parent 04f60bd commit c6c3fa8
Show file tree
Hide file tree
Showing 7 changed files with 149 additions and 37 deletions.
19 changes: 19 additions & 0 deletions app/scripts/modules/core/src/managed/ManagedResourceObject.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { getKindName } from './ManagedReader';
import { ObjectRow } from './ObjectRow';
import { AnimatingPill, Pill } from './Pill';
import { getResourceName, getArtifactVersionDisplayName } from './displayNames';
import { IStatusBubbleProps, StatusBubble } from './StatusBubble';

export interface IManagedResourceObjectProps {
resource: IManagedResourceSummary;
Expand Down Expand Up @@ -56,6 +57,20 @@ const getResourceRoutingInfo = (
return null;
};

const resourceStatusConfig: {
[status: string]: Pick<IStatusBubbleProps, 'appearance' | 'iconName'>;
} = {
ACTUATING: { appearance: 'progress', iconName: 'mdActuating' },
CREATED: { appearance: 'info', iconName: 'mdCreated' },
DIFF: { appearance: 'info', iconName: 'mdDiff' },
CURRENTLY_UNRESOLVABLE: { appearance: 'warning', iconName: 'mdError' },
ERROR: { appearance: 'error', iconName: 'mdError' },
PAUSED: { appearance: 'warning', iconName: 'mdPaused' },
RESUMED: { appearance: 'info', iconName: 'mdResumed' },
UNHAPPY: { appearance: 'error', iconName: 'mdUnhappy' },
UNKNOWN: { appearance: 'warning', iconName: 'mdUnknown' },
};

export const ManagedResourceObject = memo(
({ resource, artifactVersionsByState, artifactDetails, depth }: IManagedResourceObjectProps) => {
const { kind } = resource;
Expand All @@ -78,11 +93,15 @@ export const ManagedResourceObject = memo(
</>
);

const resourceStatusProps = resourceStatusConfig[resource.status];
const resourceStatus = resourceStatusProps && <StatusBubble {...resourceStatusProps} size="small" />;

return (
<ObjectRow
icon={getIconTypeFromKind(kind)}
title={route ? <a {...route}>{resourceName}</a> : resourceName}
depth={depth}
content={resourceStatus}
metadata={
<>
{currentPill}
Expand Down
31 changes: 16 additions & 15 deletions app/scripts/modules/core/src/managed/ObjectRow.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
align-items: center;
flex: auto;
box-shadow: inset 0 -1px 0 0 #cccccc;
height: 40px;
height: 44px;
font-size: 14px;
}

Expand All @@ -17,6 +17,7 @@

.clickableArea {
display: flex;
justify-content: space-between;
width: 100%;
height: 100%;
padding-left: 8px;
Expand All @@ -27,15 +28,24 @@
background-image: linear-gradient(to bottom, rgba(160, 180, 220, 0.15), rgba(160, 180, 220, 0.15));
}

.leftCol {
flex: 5 0 1px;
display: flex;
.col {
align-items: center;
display: flex;
margin-right: 8px;
pointer-events: none;
}

.titleCol {
flex-basis: 50%;
overflow: hidden;
pointer-events: auto;
text-overflow: ellipsis;
white-space: nowrap;
margin-right: 16px;
/* background-color: rgba(255, 0, 0, 0.1); */
}

.metaDataCol {
flex-basis: 110px;
justify-content: flex-end;
}

.rowTitle {
Expand All @@ -45,15 +55,6 @@
flex: 1 1 auto;
}

.centerCol {
flex: 0 0 100px;
display: flex;
align-items: center;

pointer-events: none;
/* background-color: rgba(0, 255, 0, 0.1); */
}

.ObjectRow:hover .select,
.ObjectRow:hover .expand {
visibility: visible;
Expand Down
13 changes: 7 additions & 6 deletions app/scripts/modules/core/src/managed/ObjectRow.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,28 @@
import React from 'react';
import classNames from 'classnames';

import { Icon, IconNames } from '../presentation';

import styles from './ObjectRow.module.css';

interface IObjectRowProps {
content?: JSX.Element;
icon: IconNames;
title: JSX.Element | string;
metadata?: JSX.Element;
depth?: number;
}

export const ObjectRow = ({ icon, title, metadata, depth = 1 }: IObjectRowProps) => {
export const ObjectRow = ({ content, icon, title, metadata, depth = 1 }: IObjectRowProps) => {
return (
<div className={styles.ObjectRow} style={getStylesFromDepth(depth)}>
<span className="clickableArea">
<div className={styles.leftCol}>
<span className={styles.clickableArea}>
<div className={classNames([styles.col, styles.titleCol])}>
<Icon name={icon} size="medium" appearance="dark" className="sp-margin-s-right" />
<span className={styles.rowTitle}>{title}</span>
</div>
<div className={styles.centerCol} style={{ flex: `0 0 ${200 + depth * 16}px` }}>
{metadata}
</div>
<div className={styles.col}>{content}</div>
<div className={classNames([styles.col, styles.metaDataCol])}>{metadata}</div>
</span>
</div>
);
Expand Down
78 changes: 69 additions & 9 deletions app/scripts/modules/core/src/managed/StatusBubble.less
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,98 @@
display: grid;
grid-template-columns: 1fr;
grid-template-rows: 1fr;
border-radius: 50%;

.status-bubble-icon-container {
.status-bubble-content {
display: flex;
flex-direction: row;
grid-column: 1;
grid-row: 1;
}

&.status-bubble-inactive {
.icon-wrapper {
border-radius: 50%;
display: grid;
grid-template-columns: 1fr;
grid-template-rows: 1fr;

&.with-quantity {
border-bottom-right-radius: 0%;
}
}

.icon-container {
align-items: center;
display: flex;
flex-flow: row nowrap;
grid-column: 1;
grid-row: 1;
justify-content: center;
}

.status-inactive {
background-color: var(--color-status-inactive);
}

&.status-bubble-neutral {
.status-neutral {
background-color: var(--color-status-neutral);
}

&.status-bubble-info {
.status-info {
background-color: var(--color-status-info);
}

&.status-bubble-progress {
.status-progress {
background-color: var(--color-status-progress);
}

&.status-bubble-success {
.status-success {
background-color: var(--color-status-success);
}

&.status-bubble-warning {
.status-warning {
background-color: var(--color-status-warning);
}

&.status-bubble-error {
.status-error {
background-color: var(--color-status-error);
}

.quantity-pill {
align-self: flex-end;
color: var(--color-icon-light);
display: inline-block;
z-index: -1;

&.small {
border-radius: 0 16px 16px 0;
font-size: 11px;
line-height: 13px;
margin-left: -10px;
padding: 2px 6px 2px 10px;
}

&.medium {
border-radius: 0 16px 16px 0;
font-size: 13px;
line-height: 16px;
margin-left: -10px;
padding: 2px 6px 2px 10px;
}

&.large {
border-radius: 0 18px 18px 0;
font-size: 17px;
line-height: 20px;
margin-left: -10px;
padding: 3px 6px 3px 10px;
}

&.extraLarge {
border-radius: 0 20px 20px 0;
font-size: 20px;
line-height: 23px;
margin-left: -10px;
padding: 4px 6px 4px 10px;
}
}
}
41 changes: 36 additions & 5 deletions app/scripts/modules/core/src/managed/StatusBubble.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import React, { memo } from 'react';
import React, { ReactNode, memo } from 'react';
import { useTransition, animated } from 'react-spring';
import classNames from 'classnames';

import { Icon, IconNames } from '../presentation';

import './StatusBubble.less';

const QUANITITY_SIZES = ['small', 'medium', 'large', 'extraLarge'];

export interface IStatusBubbleProps {
iconName: IconNames;
appearance: 'inactive' | 'neutral' | 'info' | 'progress' | 'success' | 'warning' | 'error';
size: 'extraSmall' | 'small' | 'medium' | 'large' | 'extraLarge';
quantity?: string | number;
}

const paddingBySize = {
Expand Down Expand Up @@ -36,14 +40,41 @@ const transitionConfig = {
config: { mass: 1, tension: 400, friction: 30 },
};

export const StatusBubble = memo(({ iconName, appearance, size }: IStatusBubbleProps) => {
function getQuantityPill({
appearance,
size,
quantity,
}: Pick<IStatusBubbleProps, 'appearance' | 'size' | 'quantity'>): ReactNode {
// Render quantity text only for size >= small.
if (quantity && QUANITITY_SIZES.includes(size)) {
return <span className={classNames(['quantity-pill', 'text-bold', size, `status-${appearance}`])}>{quantity}</span>;
}

return null;
}

export const StatusBubble = memo(({ appearance, iconName, size, quantity }: IStatusBubbleProps) => {
const transitions = useTransition(iconName, null, transitionConfig);
const quantityPill: ReactNode = getQuantityPill({ appearance, size, quantity });

return (
<div className={`StatusBubble status-bubble-${appearance} sp-padding-${paddingBySize[size]}`}>
<div className="StatusBubble">
{transitions.map(({ item, key, props }) => (
<animated.div key={key} className="status-bubble-icon-container flex-container-h center middle" style={props}>
<Icon name={item} appearance="light" size={size} />
<animated.div className="status-bubble-content" key={key} style={props}>
<div
className={classNames([
'icon-wrapper',
`sp-padding-${paddingBySize[size]}`,
`status-${appearance}`,
{ 'with-quantity': !!quantityPill },
])}
>
<div className="icon-container">
<Icon appearance="light" name={item} size={size} />
</div>
</div>

{quantityPill}
</animated.div>
))}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ import { ReactComponent as mdDeltaDetected } from './vectors/mdDeltaDetected.svg
import { ReactComponent as mdDeltaResolved } from './vectors/mdDeltaResolved.svg';
import { ReactComponent as mdDiff } from './vectors/mdDiff.svg';
import { ReactComponent as mdError } from './vectors/mdError.svg';
import { ReactComponent as mdFlapping } from './vectors/mdFlapping.svg';
import { ReactComponent as mdUnhappy } from './vectors/mdUnhappy.svg';
import { ReactComponent as mdPaused } from './vectors/mdPaused.svg';
import { ReactComponent as mdResumed } from './vectors/mdResumed.svg';
import { ReactComponent as mdUnknown } from './vectors/mdUnknown.svg';
Expand Down Expand Up @@ -130,7 +130,7 @@ export const iconsByName = {
mdDeltaResolved,
mdDiff,
mdError,
mdFlapping,
mdUnhappy,
mdPaused,
mdResumed,
mdUnknown,
Expand Down

0 comments on commit c6c3fa8

Please sign in to comment.