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 { InstancesIcon, HealthyIcon, P } from 'joyent-ui-toolkit';
|
||||||
|
|
||||||
import InstanceStatuses from './instance-statuses';
|
import Status from './status';
|
||||||
|
|
||||||
const StyledCardHeader = styled(CardHeader)`
|
const StyledCardHeader = styled(CardHeader)`
|
||||||
position: relative;
|
position: relative;
|
||||||
@ -105,7 +105,7 @@ const ServiceListItem = ({
|
|||||||
{isChild && title}
|
{isChild && title}
|
||||||
{isChild && subtitle}
|
{isChild && subtitle}
|
||||||
<CardDescription>
|
<CardDescription>
|
||||||
<InstanceStatuses instanceStatuses={service.instanceStatuses} />
|
<Status service={service} />
|
||||||
<CardInfo
|
<CardInfo
|
||||||
icon={<HealthyIcon />}
|
icon={<HealthyIcon />}
|
||||||
iconPosition="left"
|
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]!) {
|
mutation DeleteServices($ids: [ID]!) {
|
||||||
deleteServices(ids: $ids) {
|
deleteServices(ids: $ids) {
|
||||||
id
|
...ServiceInfo
|
||||||
slug
|
|
||||||
instances {
|
instances {
|
||||||
id
|
id
|
||||||
status
|
status
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
|
#import "./ServiceInfo.gql"
|
||||||
|
|
||||||
mutation RestartServices($ids: [ID]!) {
|
mutation RestartServices($ids: [ID]!) {
|
||||||
restartServices(ids: $ids) {
|
restartServices(ids: $ids) {
|
||||||
id
|
...ServiceInfo
|
||||||
slug
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
|
#import "./ServiceInfo.gql"
|
||||||
|
|
||||||
mutation StartServices($ids: [ID]!) {
|
mutation StartServices($ids: [ID]!) {
|
||||||
startServices(ids: $ids) {
|
startServices(ids: $ids) {
|
||||||
id
|
...ServiceInfo
|
||||||
slug
|
|
||||||
instances {
|
instances {
|
||||||
id
|
id
|
||||||
status
|
status
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
|
#import "./ServiceInfo.gql"
|
||||||
|
|
||||||
mutation StopServices($ids: [ID]!) {
|
mutation StopServices($ids: [ID]!) {
|
||||||
stopServices(ids: $ids) {
|
stopServices(ids: $ids) {
|
||||||
id
|
...ServiceInfo
|
||||||
slug
|
|
||||||
instances {
|
instances {
|
||||||
id
|
id
|
||||||
status
|
status
|
||||||
|
@ -68,7 +68,16 @@ const activeInstanceStatuses = [
|
|||||||
'INCOMPLETE'
|
'INCOMPLETE'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const transitionalServiceStatuses = [
|
||||||
|
'PROVISIONING',
|
||||||
|
'SCALING',
|
||||||
|
'STOPPING',
|
||||||
|
'DELETING',
|
||||||
|
'RESTARTING'
|
||||||
|
];
|
||||||
|
|
||||||
const getInstanceStatuses = service => {
|
const getInstanceStatuses = service => {
|
||||||
|
|
||||||
const instanceStatuses = service.instances.reduce((statuses, instance) => {
|
const instanceStatuses = service.instances.reduce((statuses, instance) => {
|
||||||
// if (instance.status !== 'RUNNING') {
|
// if (instance.status !== 'RUNNING') {
|
||||||
if (statuses[instance.status]) {
|
if (statuses[instance.status]) {
|
||||||
@ -97,19 +106,18 @@ const getInstancesActive = instanceStatuses => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const getService = (service, index) => {
|
const getService = (service, index) => {
|
||||||
const statuses = getInstanceStatuses(service);
|
|
||||||
const instancesActive = getInstancesActive(statuses);
|
const instanceStatuses = getInstanceStatuses(service);
|
||||||
const instanceStatuses = statuses.length === 1 &&
|
const instancesActive = getInstancesActive(instanceStatuses);
|
||||||
statuses[0].status === 'RUNNING'
|
const transitionalStatus = transitionalServiceStatuses.indexOf(service.status) !== -1;
|
||||||
? []
|
return ({
|
||||||
: statuses;
|
index,
|
||||||
return {
|
...service,
|
||||||
index,
|
instanceStatuses,
|
||||||
...service,
|
instancesActive,
|
||||||
instanceStatuses,
|
transitionalStatus,
|
||||||
instancesActive,
|
isConsul: service.slug === 'consul'
|
||||||
isConsul: service.slug === 'consul'
|
});
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const processServices = services => {
|
const processServices = services => {
|
||||||
|
@ -17,6 +17,7 @@ export { default as CloseButton } from './close-button';
|
|||||||
export { default as IconButton } from './icon-button';
|
export { default as IconButton } from './icon-button';
|
||||||
export { Tooltip, TooltipButton, TooltipDivider } from './tooltip';
|
export { Tooltip, TooltipButton, TooltipDivider } from './tooltip';
|
||||||
export { Dropdown } from './dropdown';
|
export { Dropdown } from './dropdown';
|
||||||
|
export { default as StatusLoader } from './status-loader';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
default as Progressbar,
|
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