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-icons": "^4.0.0",
"joyent-ui-toolkit": "^4.5.0", "joyent-ui-toolkit": "^4.5.0",
"lodash.chunk": "^4.2.0", "lodash.chunk": "^4.2.0",
"lodash.keys": "^4.2.0",
"outy": "^0.1.2", "outy": "^0.1.2",
"param-case": "^2.1.1", "param-case": "^2.1.1",
"pascal-case": "^2.0.1", "pascal-case": "^2.0.1",

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -117,92 +117,6 @@ export default {
name: 'Help & Support', name: 'Help & Support',
__typename: 'Category' __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'
}
]) ])
} }
}; };