feat(navigation): fetch products from api

fixes #1101
This commit is contained in:
Sérgio Ramos 2018-01-25 16:23:30 +00:00 committed by Sérgio Ramos
parent 467edd24e2
commit c39536677b
7 changed files with 102 additions and 178 deletions

View File

@ -25,6 +25,7 @@
"joyent-icons": "^4.0.0",
"joyent-ui-toolkit": "^4.5.0",
"lodash.chunk": "^4.2.0",
"lodash.keys": "^4.2.0",
"outy": "^0.1.2",
"param-case": "^2.1.1",
"pascal-case": "^2.0.1",

View File

@ -91,6 +91,10 @@ export const Divider = emotion('div')`
height: ${remcalc(36)};
`;
export const Space = emotion('div')`
width: ${remcalc(6)};
`;
export const Row = emotion('div')`
display: flex;
align-items: center;

View File

@ -14,7 +14,8 @@ export {
Icon as HeaderItemIcon,
FlexibleSpace as HeaderFlexibleSpaceItem,
Divider as HeaderDividerItem,
SubContent as HeaderItemSubContent
SubContent as HeaderItemSubContent,
Space as HeaderSpace
} from './header';
export {

View File

@ -44,39 +44,40 @@ const getDatacenters = gql`
}
`;
const Datacenters = ({ regions = [] }) => (
<Overlay>
{regions.map(({ name, slug, places }) => (
<div key={slug}>
<TitleContainer>
<Grid>
<Row>
<Col>
<DatacenterRegion>{name}</DatacenterRegion>
</Col>
</Row>
</Grid>
</TitleContainer>
<Container>
<Grid>
<RegionContainer>
const Datacenters = ({ expanded, regions = [] }) =>
expanded ? (
<Overlay>
{regions.map(({ name, slug, places }) => (
<div key={slug}>
<TitleContainer>
<Grid>
<Row>
{places.map(({ name, slug, datacenters }) => (
<Col key={slug} xs={12} md={6} lg={3}>
<DatacenterPlace>{name}</DatacenterPlace>
{datacenters.map(({ name, slug }) => (
<Datacenter key={slug}>{name}</Datacenter>
))}
</Col>
))}
<Col>
<DatacenterRegion>{name}</DatacenterRegion>
</Col>
</Row>
</RegionContainer>
</Grid>
</Container>
</div>
))}
</Overlay>
);
</Grid>
</TitleContainer>
<Container>
<Grid>
<RegionContainer>
<Row>
{places.map(({ name, slug, datacenters }) => (
<Col key={slug} xs={12} md={6} lg={3}>
<DatacenterPlace>{name}</DatacenterPlace>
{datacenters.map(({ name, slug }) => (
<Datacenter key={slug}>{name}</Datacenter>
))}
</Col>
))}
</Row>
</RegionContainer>
</Grid>
</Container>
</div>
))}
</Overlay>
) : null;
export default compose(
graphql(getDatacenters, {

View File

@ -20,62 +20,69 @@ const Container = emotion('div')`
background-color: #ffffff;
`;
const getHeader = gql`
const GetCategories = gql`
{
categories @client {
name
slug
}
services @client {
}
`;
const GetProducts = gql`
{
products {
name
description
category
slug
url
}
}
`;
const Services = ({ categories = [] }) => (
<Overlay>
<Container>
<Grid>
{chunk(categories, 4).map(chunk => (
<Row>
{chunk.map(({ name, services }) => (
<Col xs={12} sm={6} md={4} lg={3}>
<ServiceCategory>{name}</ServiceCategory>
{services.map(({ name, description }) => (
<Service>
<ServiceName>{name}</ServiceName>
<ServiceDescription>{description}</ServiceDescription>
</Service>
))}
</Col>
))}
</Row>
))}
</Grid>
</Container>
</Overlay>
);
const Services = ({ expanded = false, categories = [], products }) =>
expanded ? (
<Overlay>
<Container>
<Grid>
{chunk(
categories.map(({ slug, ...category }) => ({
...category,
services: products.filter(({ category }) => category === slug),
slug
})),
4
).map(chunk => (
<Row>
{chunk.map(({ name, services }) => (
<Col xs={12} sm={6} md={4} lg={3}>
<ServiceCategory>{name}</ServiceCategory>
{services.map(({ name, description }) => (
<Service>
<ServiceName>{name}</ServiceName>
<ServiceDescription>{description}</ServiceDescription>
</Service>
))}
</Col>
))}
</Row>
))}
</Grid>
</Container>
</Overlay>
) : null;
export default compose(
graphql(getHeader, {
graphql(GetCategories, {
props: ({ data }) => {
const {
categories = [],
services = [],
loading = false,
error = null
} = data;
const _categories = categories.map(({ slug, ...category }) => ({
...category,
services: services.filter(({ category }) => category === slug),
slug
}));
return { categories: _categories, loading, error };
const { categories = [] } = data;
return { categories };
}
}),
graphql(GetProducts, {
props: ({ data }) => {
const { products = [] } = data;
return { products };
}
})
)(Services);

View File

@ -2,6 +2,7 @@ import React from 'react';
import { graphql, compose } from 'react-apollo';
import gql from 'graphql-tag';
import pascalCase from 'pascal-case';
import keys from 'lodash.keys';
import { DataCenterIcon, TritonIcon, ServicesIcon } from './components';
import * as Overlays from './containers';
@ -15,7 +16,8 @@ import {
HeaderItemSubContent,
HeaderItemIcon,
HeaderFlexibleSpaceItem,
HeaderDividerItem
HeaderDividerItem,
HeaderSpace
} from './components';
const updateHeaderMutation = gql`
@ -39,20 +41,6 @@ const getAccount = gql`
}
`;
const Panel = ({ name = '', expanded = false, children, ...rest }) => {
if (!expanded) {
return null;
}
const overlay = Overlays[pascalCase(name)];
if (!overlay) {
return null;
}
return React.createElement(overlay, rest, children);
};
const Navigation = ({ login, toggleSectionOpen, isOpen, activePanel }) => (
<Header onOutsideClick={() => toggleSectionOpen()}>
<HeaderRow>
@ -64,7 +52,7 @@ const Navigation = ({ login, toggleSectionOpen, isOpen, activePanel }) => (
onClick={() => toggleSectionOpen('services')}
active={isOpen && activePanel === 'services'}
>
<HeaderItemContent>Services</HeaderItemContent>
<HeaderItemContent>Products & Services</HeaderItemContent>
<HeaderItemIcon>
<ServicesIcon light />
</HeaderItemIcon>
@ -77,7 +65,9 @@ const Navigation = ({ login, toggleSectionOpen, isOpen, activePanel }) => (
active={isOpen && activePanel === 'datacenter'}
>
<HeaderItemContent>
<HeaderItemSubContent>Data Center:</HeaderItemSubContent> us-east-1
<HeaderItemSubContent>Data Center:</HeaderItemSubContent>
<HeaderSpace />
<span>us-east-1</span>
</HeaderItemContent>
<HeaderItemIcon>
<DataCenterIcon light />
@ -87,7 +77,9 @@ const Navigation = ({ login, toggleSectionOpen, isOpen, activePanel }) => (
{login ? (
<HeaderItem>
<HeaderItemContent>
<HeaderItemSubContent>Account:</HeaderItemSubContent> {login}
<HeaderItemSubContent>Account:</HeaderItemSubContent>
<HeaderSpace />
{login}
</HeaderItemContent>
<HeaderItemIcon>
<Avatar />
@ -95,7 +87,11 @@ const Navigation = ({ login, toggleSectionOpen, isOpen, activePanel }) => (
</HeaderItem>
) : null}
</HeaderRow>
<Panel expanded={isOpen} name={activePanel} />
{keys(Overlays).map(panelName =>
React.createElement(Overlays[panelName], {
expanded: isOpen && panelName === pascalCase(activePanel)
})
)}
</Header>
);

View File

@ -117,92 +117,6 @@ export default {
name: 'Help & Support',
__typename: 'Category'
}
]),
services: dataSlugFromObjects([
{
name: 'VMs & Containers',
description: 'Run VMs and bare metal containers',
category: 'compute',
__typename: 'Service'
},
{
name: 'Converged Analytics',
description: 'Map reduce and ETL on your objects',
category: 'compute',
__typename: 'Service'
},
{
name: 'VLANs',
description: 'Wire your appliction your way',
category: 'network',
__typename: 'Service'
},
{
name: 'Subnets',
description: 'A network for everything',
category: 'network',
__typename: 'Service'
},
{
name: 'Firewall Rules',
description: 'Control the bits coming and going',
category: 'network',
__typename: 'Service'
},
{
name: 'Service Status',
description: 'Write here about Service Status',
category: 'help-support',
__typename: 'Service'
},
{
name: 'Contact Support',
description: 'Chat to us via phone or email',
category: 'help-support',
__typename: 'Service'
},
{
name: 'Support Plans',
description: 'Write here about Support Plans',
category: 'help-support',
__typename: 'Service'
},
{
name: 'Getting Started',
description: 'Write here about Getting Started',
category: 'help-support',
__typename: 'Service'
},
{
name: 'Triton Object Storage',
description: 'Modern cloud object storage',
category: 'storage',
__typename: 'Service'
},
{
name: 'S3 Compatibility Bridge',
description: 'Modern storage, legacy compatibility',
category: 'storage',
__typename: 'Service'
},
{
name: 'Triton Volumes',
description: 'Network filesystems for your apps',
category: 'storage',
__typename: 'Service'
},
{
name: 'Role Based Access Control',
description: 'Manage users within your account',
category: 'access',
__typename: 'Service'
},
{
name: 'Firewall Rules',
description: 'Inspect all the bytes',
category: 'access',
__typename: 'Service'
}
])
}
};