Add icons to service list and tidy up
This commit is contained in:
parent
9a1a84510f
commit
c06bbf4e31
@ -1,20 +1,33 @@
|
||||
import React from 'react';
|
||||
|
||||
import { MetricGraph, MetricView } from '@ui/components/metric';
|
||||
import PropTypes from '@root/prop-types';
|
||||
import {
|
||||
MetricGraph,
|
||||
MetricView,
|
||||
MiniMetricMeta,
|
||||
MiniMetricTitle,
|
||||
MiniMetricSubtitle
|
||||
} from '@ui/components/metric';
|
||||
|
||||
const MetricItem = ({
|
||||
uuid,
|
||||
data
|
||||
}) => (
|
||||
<MetricView borderless mini>
|
||||
<MetricGraph data={data} />
|
||||
<MiniMetricMeta>
|
||||
<MiniMetricTitle>Memory: 54%</MiniMetricTitle>
|
||||
<MiniMetricSubtitle>(1280/3000 MB)</MiniMetricSubtitle>
|
||||
</MiniMetricMeta>
|
||||
<MetricGraph
|
||||
data={data}
|
||||
width={160}
|
||||
height={72}
|
||||
/>
|
||||
</MetricView>
|
||||
);
|
||||
|
||||
MetricItem.propTypes = {
|
||||
uuid: React.PropTypes.string,
|
||||
data: PropTypes.data
|
||||
data: React.PropTypes.data
|
||||
};
|
||||
|
||||
export default MetricItem;
|
||||
|
@ -5,6 +5,11 @@ import { Checkbox, FormGroup } from '@ui/components/form';
|
||||
import PropTypes from '@root/prop-types';
|
||||
import forceArray from 'force-array';
|
||||
import React from 'react';
|
||||
import {
|
||||
DataCentersIcon,
|
||||
HealthyIcon,
|
||||
InstancesMultipleIcon
|
||||
} from '@ui/components/icons';
|
||||
|
||||
import {
|
||||
ListItem,
|
||||
@ -15,7 +20,8 @@ import {
|
||||
ListItemDescription,
|
||||
ListItemGroupView,
|
||||
ListItemOptions,
|
||||
ListItemHeader
|
||||
ListItemHeader,
|
||||
ListItemInfo
|
||||
} from '@ui/components/list';
|
||||
|
||||
const StyledFormGroup = styled(FormGroup)`
|
||||
@ -36,7 +42,7 @@ const ServiceItem = ({
|
||||
service = {}
|
||||
}) => {
|
||||
const isChild = !!service.parent;
|
||||
|
||||
console.log('service = ', service);
|
||||
const childs = forceArray(service.services).map((service) => (
|
||||
<ServiceItem
|
||||
key={service.uuid}
|
||||
@ -69,10 +75,6 @@ const ServiceItem = ({
|
||||
<ListItemSubTitle>{service.instances} instances</ListItemSubTitle>
|
||||
);
|
||||
|
||||
const description = (
|
||||
<ListItemDescription>Flags</ListItemDescription>
|
||||
);
|
||||
|
||||
const onOptionsClick = (evt) => {
|
||||
onQuickActions(evt, service.uuid);
|
||||
};
|
||||
@ -81,12 +83,20 @@ const ServiceItem = ({
|
||||
<ListItemHeader>
|
||||
<ListItemMeta>
|
||||
{title}
|
||||
{subtitle}
|
||||
{description}
|
||||
<ListItemDescription>
|
||||
<ListItemInfo
|
||||
icon={<InstancesMultipleIcon />}
|
||||
iconPosition='top'
|
||||
label={`${service.instances} ${service.instances > 1 ?
|
||||
'instances' : 'instance' }`}
|
||||
/>
|
||||
<ListItemInfo
|
||||
icon={<DataCentersIcon />}
|
||||
label={service.datacenters[0].id}
|
||||
/>
|
||||
</ListItemDescription>
|
||||
</ListItemMeta>
|
||||
<ListItemOptions onClick={onOptionsClick}>
|
||||
…
|
||||
</ListItemOptions>
|
||||
<ListItemOptions onClick={onOptionsClick} />
|
||||
</ListItemHeader>
|
||||
);
|
||||
|
||||
@ -99,7 +109,12 @@ const ServiceItem = ({
|
||||
<ListItemMeta>
|
||||
{isChild && title}
|
||||
{isChild && subtitle}
|
||||
{description}
|
||||
<ListItemDescription>
|
||||
<ListItemInfo
|
||||
icon={<HealthyIcon />}
|
||||
label='Healthy'
|
||||
/>
|
||||
</ListItemDescription>
|
||||
</ListItemMeta>
|
||||
<ItemMetricGroup
|
||||
datasets={service.metrics}
|
||||
|
@ -9,6 +9,7 @@ import moment from 'moment';
|
||||
|
||||
const account = (state) => get(state, 'account.data', {});
|
||||
const accountUi = (state) => get(state, 'account.ui', {});
|
||||
const datacenters = (state) => get(state, 'datacenters.data', {});
|
||||
const orgUiSections = (state) => get(state, 'orgs.ui.sections', []);
|
||||
const projectUiSections = (state) => get(state, 'projects.ui.sections', []);
|
||||
const serviceUiTooltip = (state) => get(state, 'services.ui.tooltip', []);
|
||||
@ -267,8 +268,9 @@ const datasets = (
|
||||
});
|
||||
|
||||
const servicesByProjectId = (projectId, metricOptions) => createSelector(
|
||||
[services, projectById(projectId), collapsedServices, metricsData, metricsUI],
|
||||
(services, project, collapsed, metrics, metricsUI) =>
|
||||
[services, projectById(projectId), collapsedServices,
|
||||
instances, datacenters, metricsData, metricsUI],
|
||||
(services, project, collapsed, instances, datacenters, metrics, metricsUI) =>
|
||||
services.filter((s) => s.project === project.uuid)
|
||||
.map((service) => ({
|
||||
...service,
|
||||
@ -278,6 +280,14 @@ const servicesByProjectId = (projectId, metricOptions) => createSelector(
|
||||
.map((service) => ({
|
||||
...service,
|
||||
metrics: datasets(metrics, service.metrics, metricsUI, metricOptions),
|
||||
datacenters: instances.reduce((acc, instance) => {
|
||||
if(instance.service === service.uuid) {
|
||||
acc.push(instance);
|
||||
}
|
||||
return acc;
|
||||
}, []).map((instance) =>
|
||||
// TODO ensure uniqueness here
|
||||
find(datacenters, ['uuid', instance.datacenter])),
|
||||
collapsed: isCollapsed(collapsed, service.uuid),
|
||||
services: service.services.map((service) => ({
|
||||
...service,
|
||||
|
@ -9,6 +9,7 @@ const style = css`
|
||||
|
||||
${is('secondary')`
|
||||
color: ${colors.base.white};
|
||||
text-decoration: none;
|
||||
`}
|
||||
`;
|
||||
|
||||
|
9
ui/src/components/icons/data-centers.js
Normal file
9
ui/src/components/icons/data-centers.js
Normal file
@ -0,0 +1,9 @@
|
||||
import { Baseline } from '../../shared/composers';
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
import React from 'react';
|
||||
|
||||
import DataCentersIcon from './svg/data-centers.svg';
|
||||
|
||||
export default Baseline(
|
||||
DataCentersIcon
|
||||
);
|
@ -1,4 +1,5 @@
|
||||
export { default as CloseIcon } from './close';
|
||||
export { default as DataCentersIcon } from './data-centers';
|
||||
export { default as HealthyIcon } from './healthy';
|
||||
export { default as HeartIcon } from './heart';
|
||||
export { default as InputConfirmIcon } from './input-confirm';
|
||||
|
@ -8,6 +8,7 @@ import ListItemOutlet from './outlet';
|
||||
import ListItemSubTitle from './subtitle';
|
||||
import ListItemTitle from './title';
|
||||
import ListItemView from './view';
|
||||
import ListItemInfo from './info';
|
||||
|
||||
export {
|
||||
ListItemDescription,
|
||||
@ -19,5 +20,6 @@ export {
|
||||
ListItemOutlet,
|
||||
ListItemSubTitle,
|
||||
ListItemTitle,
|
||||
ListItemView
|
||||
ListItemView,
|
||||
ListItemInfo
|
||||
};
|
||||
|
43
ui/src/components/list/info.js
Normal file
43
ui/src/components/list/info.js
Normal file
@ -0,0 +1,43 @@
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { unitcalc } from '../../shared/functions';
|
||||
import { P } from '../base-elements';
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
display: inline-block;
|
||||
margin: 0 ${unitcalc(2)};
|
||||
`;
|
||||
|
||||
const StyledIcon = styled.div`
|
||||
display: inline-block;
|
||||
margin-right: ${unitcalc(1)};
|
||||
vertical-align: ${props =>
|
||||
props.iconPosition ?
|
||||
props.iconPosition : 'text-top'};
|
||||
`;
|
||||
|
||||
const StyledP = styled(P)`
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
`;
|
||||
|
||||
const Info = ({
|
||||
icon,
|
||||
iconPosition,
|
||||
label
|
||||
}) => (
|
||||
<StyledContainer>
|
||||
<StyledIcon iconPosition={iconPosition}>
|
||||
{icon}
|
||||
</StyledIcon>
|
||||
<StyledP>{label}</StyledP>
|
||||
</StyledContainer>
|
||||
);
|
||||
|
||||
Info.propTypes = {
|
||||
icon: React.PropTypes.node,
|
||||
iconPosition: React.PropTypes.string,
|
||||
label: React.PropTypes.string
|
||||
};
|
||||
|
||||
export default Info;
|
@ -12,11 +12,12 @@ const Nav = styled.nav`
|
||||
box-sizing: border-box;
|
||||
|
||||
${is('fromHeader')`
|
||||
border-left-color: ${colors.base.primary};
|
||||
border-left-color: ${colors.base.primaryDesaturatedActive};
|
||||
`};
|
||||
`;
|
||||
|
||||
const StyledButton = styled(Button)`
|
||||
position: relative;
|
||||
border-width: 0;
|
||||
box-shadow: none;
|
||||
width: 100%;
|
||||
@ -46,8 +47,20 @@ const StyledButton = styled(Button)`
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
`;
|
||||
|
||||
const StyledCircle = styled.div`
|
||||
margin: 0 0 2px -2px;
|
||||
border-radius: 50%;
|
||||
background-color: ${colors.base.white};
|
||||
width: 4px;
|
||||
height: 4px;
|
||||
`;
|
||||
|
||||
const Options = ({
|
||||
children,
|
||||
...props
|
||||
}) => {
|
||||
const render = ({
|
||||
@ -61,7 +74,11 @@ const Options = ({
|
||||
rect
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
<StyledContainer>
|
||||
<StyledCircle />
|
||||
<StyledCircle />
|
||||
<StyledCircle />
|
||||
</StyledContainer>
|
||||
</StyledButton>
|
||||
</Nav>
|
||||
);
|
||||
@ -74,7 +91,6 @@ const Options = ({
|
||||
};
|
||||
|
||||
Options.propTypes = {
|
||||
children: React.PropTypes.node,
|
||||
collapsed: React.PropTypes.bool,
|
||||
fromHeader: React.PropTypes.bool
|
||||
};
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Subscriber } from 'react-broadcast';
|
||||
import { is } from '../../shared/functions';
|
||||
import { is, remcalc } from '../../shared/functions';
|
||||
import { Baseline } from '../../shared/composers';
|
||||
import Column from '../column';
|
||||
import styled from 'styled-components';
|
||||
@ -7,6 +7,9 @@ import React from 'react';
|
||||
|
||||
const StyledColumn = styled(Column)`
|
||||
display: block;
|
||||
min-width: auto;
|
||||
max-width: ${remcalc(480)};
|
||||
margin-left: auto;
|
||||
|
||||
${is('collapsed')`
|
||||
display: none;
|
||||
|
@ -5,6 +5,7 @@ import styled from 'styled-components';
|
||||
import React from 'react';
|
||||
|
||||
const OuterBox = styled.div`
|
||||
box-sizing: border-box;
|
||||
height: ${remcalc(53)};
|
||||
padding: ${remcalc(8)} ${remcalc(12)};
|
||||
border-bottom: ${remcalc(1)} solid ${colors.seperator};
|
||||
|
Loading…
Reference in New Issue
Block a user