feat(joyent-ui-toolkit, joyent-cp-frontend): Display transitional service statuses
This commit is contained in:
parent
5ccd873a54
commit
06ab07a966
@ -1,42 +0,0 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import styled from 'styled-components';
|
||||
import remcalc from 'remcalc';
|
||||
import { P } from 'joyent-ui-toolkit';
|
||||
|
||||
const StyledStatus = P.extend`
|
||||
margin: 0;
|
||||
font-size: ${remcalc(13)};
|
||||
line-height: ${remcalc(13)};
|
||||
`;
|
||||
|
||||
const StyledStatusContainer = styled.div`
|
||||
margin: ${remcalc(6)} 0 ${remcalc(12)} 0;
|
||||
height: ${remcalc(54)}
|
||||
`;
|
||||
|
||||
const InstanceStatuses = ({ instanceStatuses }) => {
|
||||
const statuses = instanceStatuses.map(instanceStatus => {
|
||||
const { status, count } = instanceStatus;
|
||||
|
||||
return (
|
||||
<StyledStatus>
|
||||
{`${count}
|
||||
${count > 1 ? 'instances' : 'instance'}
|
||||
${status.toLowerCase()}`}
|
||||
</StyledStatus>
|
||||
);
|
||||
});
|
||||
|
||||
return (
|
||||
<StyledStatusContainer>
|
||||
{statuses}
|
||||
</StyledStatusContainer>
|
||||
);
|
||||
};
|
||||
|
||||
InstanceStatuses.propTypes = {
|
||||
instanceStatuses: PropTypes.array.isRequired
|
||||
};
|
||||
|
||||
export default InstanceStatuses;
|
@ -18,7 +18,7 @@ import {
|
||||
|
||||
import { InstancesIcon, HealthyIcon, P } from 'joyent-ui-toolkit';
|
||||
|
||||
import InstanceStatuses from './instance-statuses';
|
||||
import Status from './status';
|
||||
|
||||
const StyledCardHeader = styled(CardHeader)`
|
||||
position: relative;
|
||||
@ -105,7 +105,7 @@ const ServiceListItem = ({
|
||||
{isChild && title}
|
||||
{isChild && subtitle}
|
||||
<CardDescription>
|
||||
<InstanceStatuses instanceStatuses={service.instanceStatuses} />
|
||||
<Status service={service} />
|
||||
<CardInfo
|
||||
icon={<HealthyIcon />}
|
||||
iconPosition="left"
|
||||
|
61
packages/cp-frontend/src/components/services/status.js
Normal file
61
packages/cp-frontend/src/components/services/status.js
Normal file
@ -0,0 +1,61 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import styled from 'styled-components';
|
||||
import remcalc from 'remcalc';
|
||||
import { StatusLoader, P } from 'joyent-ui-toolkit';
|
||||
|
||||
const StyledStatusContainer = styled.div`
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
height: ${remcalc(54)};
|
||||
width: ${remcalc(200)};
|
||||
`;
|
||||
|
||||
const StyledStatus = P.extend`
|
||||
margin: 0;
|
||||
font-size: ${remcalc(13)};
|
||||
line-height: ${remcalc(13)};
|
||||
`;
|
||||
|
||||
const StyledTransitionalStatus = StyledStatus.extend`
|
||||
display: inline-block;
|
||||
margin-left: ${remcalc(6)};
|
||||
text-transform: capitalize;
|
||||
`;
|
||||
|
||||
const ServiceStatus = ({ service }) => {
|
||||
|
||||
const getInstanceStatuses = (instanceStatuses) =>
|
||||
instanceStatuses.map((instanceStatus, index) => {
|
||||
const { status, count } = instanceStatus;
|
||||
|
||||
return (
|
||||
<StyledStatus key={index}>
|
||||
{`${count}
|
||||
${count > 1 ? 'instances' : 'instance'}
|
||||
${status.toLowerCase()}`}
|
||||
</StyledStatus>
|
||||
);
|
||||
});
|
||||
|
||||
return service.transitionalStatus
|
||||
? (
|
||||
<StyledStatusContainer>
|
||||
<StatusLoader />
|
||||
<StyledTransitionalStatus>
|
||||
{ service.status ? service.status.toLowerCase() : '' }
|
||||
</StyledTransitionalStatus>
|
||||
</StyledStatusContainer>
|
||||
)
|
||||
: (
|
||||
<StyledStatusContainer>
|
||||
{getInstanceStatuses(service.instanceStatuses)}
|
||||
</StyledStatusContainer>
|
||||
);
|
||||
};
|
||||
|
||||
ServiceStatus.propTypes = {
|
||||
service: PropTypes.object.isRequired
|
||||
};
|
||||
|
||||
export default ServiceStatus;
|
@ -1,7 +1,8 @@
|
||||
#import "./ServiceInfo.gql"
|
||||
|
||||
mutation DeleteServices($ids: [ID]!) {
|
||||
deleteServices(ids: $ids) {
|
||||
id
|
||||
slug
|
||||
...ServiceInfo
|
||||
instances {
|
||||
id
|
||||
status
|
||||
|
@ -1,6 +1,7 @@
|
||||
#import "./ServiceInfo.gql"
|
||||
|
||||
mutation RestartServices($ids: [ID]!) {
|
||||
restartServices(ids: $ids) {
|
||||
id
|
||||
slug
|
||||
...ServiceInfo
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,8 @@
|
||||
#import "./ServiceInfo.gql"
|
||||
|
||||
mutation StartServices($ids: [ID]!) {
|
||||
startServices(ids: $ids) {
|
||||
id
|
||||
slug
|
||||
...ServiceInfo
|
||||
instances {
|
||||
id
|
||||
status
|
||||
|
@ -1,7 +1,8 @@
|
||||
#import "./ServiceInfo.gql"
|
||||
|
||||
mutation StopServices($ids: [ID]!) {
|
||||
stopServices(ids: $ids) {
|
||||
id
|
||||
slug
|
||||
...ServiceInfo
|
||||
instances {
|
||||
id
|
||||
status
|
||||
|
@ -68,7 +68,16 @@ const activeInstanceStatuses = [
|
||||
'INCOMPLETE'
|
||||
];
|
||||
|
||||
const transitionalServiceStatuses = [
|
||||
'PROVISIONING',
|
||||
'SCALING',
|
||||
'STOPPING',
|
||||
'DELETING',
|
||||
'RESTARTING'
|
||||
];
|
||||
|
||||
const getInstanceStatuses = service => {
|
||||
|
||||
const instanceStatuses = service.instances.reduce((statuses, instance) => {
|
||||
// if (instance.status !== 'RUNNING') {
|
||||
if (statuses[instance.status]) {
|
||||
@ -97,19 +106,18 @@ const getInstancesActive = instanceStatuses => {
|
||||
};
|
||||
|
||||
const getService = (service, index) => {
|
||||
const statuses = getInstanceStatuses(service);
|
||||
const instancesActive = getInstancesActive(statuses);
|
||||
const instanceStatuses = statuses.length === 1 &&
|
||||
statuses[0].status === 'RUNNING'
|
||||
? []
|
||||
: statuses;
|
||||
return {
|
||||
index,
|
||||
...service,
|
||||
instanceStatuses,
|
||||
instancesActive,
|
||||
isConsul: service.slug === 'consul'
|
||||
};
|
||||
|
||||
const instanceStatuses = getInstanceStatuses(service);
|
||||
const instancesActive = getInstancesActive(instanceStatuses);
|
||||
const transitionalStatus = transitionalServiceStatuses.indexOf(service.status) !== -1;
|
||||
return ({
|
||||
index,
|
||||
...service,
|
||||
instanceStatuses,
|
||||
instancesActive,
|
||||
transitionalStatus,
|
||||
isConsul: service.slug === 'consul'
|
||||
});
|
||||
};
|
||||
|
||||
const processServices = services => {
|
||||
|
@ -17,6 +17,7 @@ export { default as CloseButton } from './close-button';
|
||||
export { default as IconButton } from './icon-button';
|
||||
export { Tooltip, TooltipButton, TooltipDivider } from './tooltip';
|
||||
export { Dropdown } from './dropdown';
|
||||
export { default as StatusLoader } from './status-loader';
|
||||
|
||||
export {
|
||||
default as Progressbar,
|
||||
|
35
packages/ui-toolkit/src/status-loader/index.js
Normal file
35
packages/ui-toolkit/src/status-loader/index.js
Normal file
@ -0,0 +1,35 @@
|
||||
import React, { Component } from 'react';
|
||||
import styled, { keyframes } from 'styled-components';
|
||||
|
||||
const animationName = keyframes`
|
||||
0% {
|
||||
opacity: 1;
|
||||
stroke-width: 2;
|
||||
}
|
||||
100% {
|
||||
opacity: 0.25;
|
||||
stroke-width: 0;
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledFirstRect = styled.rect`
|
||||
fill: ${props => props.theme.primary};
|
||||
stroke: ${props => props.theme.primary};
|
||||
animation: ${animationName} 1.5s ease-out 0s infinite;
|
||||
`;
|
||||
|
||||
const StyledSecondRect = StyledFirstRect.extend`
|
||||
animation-delay: 0.5s;
|
||||
`;
|
||||
|
||||
const StyledThirdRect = StyledFirstRect.extend`
|
||||
animation-delay: 1s;
|
||||
`;
|
||||
|
||||
export default () => (
|
||||
<svg width='28' height='10'>
|
||||
<StyledFirstRect x='2' y='2' width='6' height='6' />
|
||||
<StyledSecondRect x='11' y='2' width='6' height='6' />
|
||||
<StyledThirdRect x='20' y='2' width='6' height='6' />
|
||||
</svg>
|
||||
);
|
5
packages/ui-toolkit/src/status-loader/usage.md
Normal file
5
packages/ui-toolkit/src/status-loader/usage.md
Normal file
@ -0,0 +1,5 @@
|
||||
```
|
||||
const SectionLoader = require('./index').default
|
||||
|
||||
<SectionLoader />
|
||||
```
|
Loading…
Reference in New Issue
Block a user