diff --git a/packages/cp-frontend/src/components/services/instance-statuses.js b/packages/cp-frontend/src/components/services/instance-statuses.js
deleted file mode 100644
index a517d58e..00000000
--- a/packages/cp-frontend/src/components/services/instance-statuses.js
+++ /dev/null
@@ -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 (
-
- {`${count}
- ${count > 1 ? 'instances' : 'instance'}
- ${status.toLowerCase()}`}
-
- );
- });
-
- return (
-
- {statuses}
-
- );
-};
-
-InstanceStatuses.propTypes = {
- instanceStatuses: PropTypes.array.isRequired
-};
-
-export default InstanceStatuses;
diff --git a/packages/cp-frontend/src/components/services/list-item.js b/packages/cp-frontend/src/components/services/list-item.js
index 088c1ab8..1c4dba0c 100644
--- a/packages/cp-frontend/src/components/services/list-item.js
+++ b/packages/cp-frontend/src/components/services/list-item.js
@@ -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}
-
+
}
iconPosition="left"
diff --git a/packages/cp-frontend/src/components/services/status.js b/packages/cp-frontend/src/components/services/status.js
new file mode 100644
index 00000000..fc713ea7
--- /dev/null
+++ b/packages/cp-frontend/src/components/services/status.js
@@ -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 (
+
+ {`${count}
+ ${count > 1 ? 'instances' : 'instance'}
+ ${status.toLowerCase()}`}
+
+ );
+ });
+
+ return service.transitionalStatus
+ ? (
+
+
+
+ { service.status ? service.status.toLowerCase() : '' }
+
+
+ )
+ : (
+
+ {getInstanceStatuses(service.instanceStatuses)}
+
+ );
+};
+
+ServiceStatus.propTypes = {
+ service: PropTypes.object.isRequired
+};
+
+export default ServiceStatus;
diff --git a/packages/cp-frontend/src/graphql/ServicesDeleteMutation.gql b/packages/cp-frontend/src/graphql/ServicesDeleteMutation.gql
index b4ef3a26..6e62f6a3 100644
--- a/packages/cp-frontend/src/graphql/ServicesDeleteMutation.gql
+++ b/packages/cp-frontend/src/graphql/ServicesDeleteMutation.gql
@@ -1,7 +1,8 @@
+#import "./ServiceInfo.gql"
+
mutation DeleteServices($ids: [ID]!) {
deleteServices(ids: $ids) {
- id
- slug
+ ...ServiceInfo
instances {
id
status
diff --git a/packages/cp-frontend/src/graphql/ServicesRestartMutation.gql b/packages/cp-frontend/src/graphql/ServicesRestartMutation.gql
index a1d0a662..f47e2c8d 100644
--- a/packages/cp-frontend/src/graphql/ServicesRestartMutation.gql
+++ b/packages/cp-frontend/src/graphql/ServicesRestartMutation.gql
@@ -1,6 +1,7 @@
+#import "./ServiceInfo.gql"
+
mutation RestartServices($ids: [ID]!) {
restartServices(ids: $ids) {
- id
- slug
+ ...ServiceInfo
}
}
diff --git a/packages/cp-frontend/src/graphql/ServicesStartMutation.gql b/packages/cp-frontend/src/graphql/ServicesStartMutation.gql
index e854e34e..31ae80a9 100644
--- a/packages/cp-frontend/src/graphql/ServicesStartMutation.gql
+++ b/packages/cp-frontend/src/graphql/ServicesStartMutation.gql
@@ -1,7 +1,8 @@
+#import "./ServiceInfo.gql"
+
mutation StartServices($ids: [ID]!) {
startServices(ids: $ids) {
- id
- slug
+ ...ServiceInfo
instances {
id
status
diff --git a/packages/cp-frontend/src/graphql/ServicesStopMutation.gql b/packages/cp-frontend/src/graphql/ServicesStopMutation.gql
index f2778ba7..9f4149ca 100644
--- a/packages/cp-frontend/src/graphql/ServicesStopMutation.gql
+++ b/packages/cp-frontend/src/graphql/ServicesStopMutation.gql
@@ -1,7 +1,8 @@
+#import "./ServiceInfo.gql"
+
mutation StopServices($ids: [ID]!) {
stopServices(ids: $ids) {
- id
- slug
+ ...ServiceInfo
instances {
id
status
diff --git a/packages/cp-frontend/src/state/selectors.js b/packages/cp-frontend/src/state/selectors.js
index 8e04b1e4..8c5c9b98 100644
--- a/packages/cp-frontend/src/state/selectors.js
+++ b/packages/cp-frontend/src/state/selectors.js
@@ -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 => {
diff --git a/packages/ui-toolkit/src/index.js b/packages/ui-toolkit/src/index.js
index 33aeab97..d939556a 100644
--- a/packages/ui-toolkit/src/index.js
+++ b/packages/ui-toolkit/src/index.js
@@ -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,
diff --git a/packages/ui-toolkit/src/status-loader/index.js b/packages/ui-toolkit/src/status-loader/index.js
new file mode 100644
index 00000000..2b4a0ea7
--- /dev/null
+++ b/packages/ui-toolkit/src/status-loader/index.js
@@ -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 () => (
+
+);
diff --git a/packages/ui-toolkit/src/status-loader/usage.md b/packages/ui-toolkit/src/status-loader/usage.md
new file mode 100644
index 00000000..0a2a087e
--- /dev/null
+++ b/packages/ui-toolkit/src/status-loader/usage.md
@@ -0,0 +1,5 @@
+```
+const SectionLoader = require('./index').default
+
+
+```