feat(navigation): add api
This commit is contained in:
parent
7f0658e246
commit
024bce06af
|
@ -5,7 +5,7 @@
|
|||
"license": "MPL-2.0",
|
||||
"main": "lib/index.js",
|
||||
"scripts": {
|
||||
"dev": "NODE_ENV=development PREACT=1 REACT_APP_GQL_PORT=4000 PORT=3000 joyent-react-scripts start",
|
||||
"dev": "NODE_ENV=development PREACT=1 REACT_APP_GQL_PORT=3068 PORT=3000 joyent-react-scripts start",
|
||||
"build:test": "echo 0",
|
||||
"build:lib": "echo 0",
|
||||
"build:bundle": "NODE_ENV=production redrun build",
|
||||
|
@ -29,9 +29,9 @@
|
|||
"joyent-icons": "^5.0.0",
|
||||
"joyent-ui-toolkit": "^5.0.0",
|
||||
"lodash.chunk": "^4.2.0",
|
||||
"lodash.groupby": "^4.6.0",
|
||||
"lodash.keys": "^4.2.0",
|
||||
"outy": "^0.1.2",
|
||||
"param-case": "^2.1.1",
|
||||
"pascal-case": "^2.0.1",
|
||||
"preact": "^8.2.7",
|
||||
"preact-compat": "^3.18.0",
|
||||
|
|
|
@ -7,8 +7,12 @@ import theme from 'joyent-ui-toolkit/dist/es/theme';
|
|||
import { client } from './state';
|
||||
import Header from './header';
|
||||
|
||||
console.log(theme);
|
||||
|
||||
const fullTheme = {
|
||||
...theme,
|
||||
headerbg: '#1e313b',
|
||||
overlay: 'rgba(0, 0, 0, 0.25)',
|
||||
flexboxgrid: {
|
||||
gridSize: 12, // rem
|
||||
gutterWidth: 1.25, // rem
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
import emotion from 'preact-emotion';
|
||||
|
||||
export default emotion('a')`
|
||||
font-weight: 600;
|
||||
line-height: 24px;
|
||||
font-size: 15px;
|
||||
text-decoration: none;
|
||||
color: ${props => props.theme.text};
|
||||
|
||||
&:hover {
|
||||
color: ${props => props.theme.primary}
|
||||
}
|
||||
`;
|
|
@ -30,7 +30,7 @@ export const Item = emotion('div')`
|
|||
${props =>
|
||||
props.active &&
|
||||
`
|
||||
height: ${remcalc(27)};
|
||||
margin-top: ${remcalc(3)};
|
||||
border-bottom: ${remcalc(3)} solid #E38200;
|
||||
background-color: rgba(0, 0, 0, 0.25);
|
||||
`};
|
||||
|
|
|
@ -32,3 +32,5 @@ export {
|
|||
} from './service';
|
||||
|
||||
export { default as Overlay } from './overlay';
|
||||
export { default as Anchor } from './anchor';
|
||||
export { default as Sup } from './sup';
|
||||
|
|
|
@ -31,5 +31,8 @@ export const Description = emotion('h6')`
|
|||
|
||||
export default emotion('a')`
|
||||
display: block;
|
||||
|
||||
&:not(:last-child) {
|
||||
margin-bottom: ${remcalc(22)};
|
||||
}
|
||||
`;
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
import emotion from 'preact-emotion';
|
||||
import remcalc from 'remcalc';
|
||||
|
||||
export default emotion('sup')`
|
||||
position: absolute;
|
||||
margin-left: ${remcalc(6)};
|
||||
font-weight: ${props => props.theme.font.weight.semibold};
|
||||
line-height: normal;
|
||||
font-size: ${remcalc(8)};
|
||||
color: ${props => (props.new ? props.theme.orange : props.theme.primary)};
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
`;
|
|
@ -3,21 +3,30 @@ import emotion from 'preact-emotion';
|
|||
import { graphql, compose } from 'react-apollo';
|
||||
import gql from 'graphql-tag';
|
||||
import remcalc from 'remcalc';
|
||||
import groupBy from 'lodash.groupby';
|
||||
|
||||
import { Grid, Row, Col } from 'preact-emotion-flexboxgrid';
|
||||
import {
|
||||
DatacenterPlace,
|
||||
DatacenterRegion,
|
||||
Datacenter,
|
||||
Overlay
|
||||
Overlay,
|
||||
Anchor
|
||||
} from '../components';
|
||||
|
||||
const fixContinentName = name =>
|
||||
name
|
||||
.toLowerCase()
|
||||
.split('_')
|
||||
.join(' ');
|
||||
|
||||
const Container = emotion('div')`
|
||||
background-color: #ffffff;
|
||||
`;
|
||||
|
||||
const TitleContainer = emotion('div')`
|
||||
background-color: ${props => props.theme.background};
|
||||
text-transform:capitalize;
|
||||
`;
|
||||
|
||||
const RegionContainer = emotion('div')`
|
||||
|
@ -27,19 +36,13 @@ const RegionContainer = emotion('div')`
|
|||
|
||||
const GetDatacenters = gql`
|
||||
{
|
||||
regions @client {
|
||||
regions {
|
||||
name
|
||||
slug
|
||||
}
|
||||
places @client {
|
||||
name
|
||||
slug
|
||||
region
|
||||
}
|
||||
datacenters @client {
|
||||
name
|
||||
slug
|
||||
place
|
||||
continent
|
||||
datacenters {
|
||||
name
|
||||
url
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
@ -47,13 +50,15 @@ const GetDatacenters = gql`
|
|||
const Datacenters = ({ expanded, regions = [] }) =>
|
||||
expanded ? (
|
||||
<Overlay>
|
||||
{regions.map(({ name, slug, places }) => (
|
||||
<div key={slug}>
|
||||
{Object.keys(regions).map(region => (
|
||||
<div key={region}>
|
||||
<TitleContainer>
|
||||
<Grid>
|
||||
<Row>
|
||||
<Col>
|
||||
<DatacenterRegion>{name}</DatacenterRegion>
|
||||
<DatacenterRegion>
|
||||
{fixContinentName(region)}
|
||||
</DatacenterRegion>
|
||||
</Col>
|
||||
</Row>
|
||||
</Grid>
|
||||
|
@ -62,11 +67,13 @@ const Datacenters = ({ expanded, regions = [] }) =>
|
|||
<Grid>
|
||||
<RegionContainer>
|
||||
<Row>
|
||||
{places.map(({ name, slug, datacenters }) => (
|
||||
<Col key={slug} xs={12} md={6} lg={3}>
|
||||
{regions[region].map(({ name, datacenters }) => (
|
||||
<Col key={name} xs={12} md={6} lg={3}>
|
||||
<DatacenterPlace>{name}</DatacenterPlace>
|
||||
{datacenters.map(({ name, slug }) => (
|
||||
<Datacenter key={slug}>{name}</Datacenter>
|
||||
{datacenters.map(({ name, url }) => (
|
||||
<Datacenter key={name}>
|
||||
<Anchor href={url}>{name}</Anchor>
|
||||
</Datacenter>
|
||||
))}
|
||||
</Col>
|
||||
))}
|
||||
|
@ -84,28 +91,10 @@ export default compose(
|
|||
options: () => ({
|
||||
ssr: false
|
||||
}),
|
||||
props: ({ data }) => {
|
||||
const {
|
||||
regions = [],
|
||||
places = [],
|
||||
datacenters = [],
|
||||
loading = false,
|
||||
error = null
|
||||
} = data;
|
||||
|
||||
const _regions = regions.map(({ slug, ...region }) => ({
|
||||
...region,
|
||||
places: places
|
||||
.filter(({ region }) => region === slug)
|
||||
.map(({ slug, ...place }) => ({
|
||||
...place,
|
||||
datacenters: datacenters.filter(({ place }) => place === slug),
|
||||
slug
|
||||
})),
|
||||
slug
|
||||
}));
|
||||
|
||||
return { regions: _regions, loading, error };
|
||||
}
|
||||
props: ({ data: { regions = [], loading = false, error = null } }) => ({
|
||||
regions: groupBy(regions, 'continent'),
|
||||
loading,
|
||||
error
|
||||
})
|
||||
})
|
||||
)(Datacenters);
|
||||
|
|
|
@ -2,7 +2,6 @@ import React from 'react';
|
|||
import emotion from 'preact-emotion';
|
||||
import { graphql, compose } from 'react-apollo';
|
||||
import gql from 'graphql-tag';
|
||||
import chunk from 'lodash.chunk';
|
||||
import remcalc from 'remcalc';
|
||||
|
||||
import { Grid, Row, Col } from 'preact-emotion-flexboxgrid';
|
||||
|
@ -12,7 +11,9 @@ import {
|
|||
ServiceName,
|
||||
ServiceDescription,
|
||||
Service,
|
||||
Overlay
|
||||
Overlay,
|
||||
Anchor,
|
||||
Sup
|
||||
} from '../components';
|
||||
|
||||
const Container = emotion('div')`
|
||||
|
@ -20,75 +21,81 @@ const Container = emotion('div')`
|
|||
background-color: #ffffff;
|
||||
`;
|
||||
|
||||
const GetCategories = gql`
|
||||
{
|
||||
categories @client {
|
||||
name
|
||||
slug
|
||||
}
|
||||
}
|
||||
const CategoryWrapper = emotion(Col)`
|
||||
margin-bottom: ${remcalc(48)};
|
||||
`;
|
||||
|
||||
const sliptTag = tag => tag.split('=').map(n => n.replace(/'/g, ''));
|
||||
|
||||
const isNew = tag => sliptTag(tag)[0] === 'is-new';
|
||||
|
||||
const formatTag = tag => {
|
||||
if (sliptTag(tag)[0] === 'note') {
|
||||
return sliptTag(tag)[1];
|
||||
}
|
||||
|
||||
if (sliptTag(tag)[0] === 'is-new') {
|
||||
return 'New!';
|
||||
}
|
||||
|
||||
return tag;
|
||||
};
|
||||
|
||||
const GetProducts = gql`
|
||||
{
|
||||
products {
|
||||
categories {
|
||||
name
|
||||
description
|
||||
category
|
||||
url
|
||||
services {
|
||||
name
|
||||
slug
|
||||
url
|
||||
tags
|
||||
description
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const Services = ({ expanded = false, categories = [], products = [] }) =>
|
||||
const Services = ({ expanded = false, categories = [], loading }) =>
|
||||
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}>
|
||||
<Row>
|
||||
{!loading &&
|
||||
categories.map(({ name, services }) => (
|
||||
<CategoryWrapper xs={12} sm={6} md={4}>
|
||||
<ServiceCategory>{name}</ServiceCategory>
|
||||
{services.map(({ name, description }) => (
|
||||
{services.map(({ name, description, url, tags }) => (
|
||||
<Service>
|
||||
<ServiceName>{name}</ServiceName>
|
||||
<ServiceName>
|
||||
<Anchor href={url}>{name}</Anchor>
|
||||
{tags
|
||||
? tags.map(tag => (
|
||||
<Sup new={isNew(tag)}>{formatTag(tag)}</Sup>
|
||||
))
|
||||
: null}
|
||||
</ServiceName>
|
||||
<ServiceDescription>{description}</ServiceDescription>
|
||||
</Service>
|
||||
))}
|
||||
</Col>
|
||||
</CategoryWrapper>
|
||||
))}
|
||||
</Row>
|
||||
))}
|
||||
</Row>
|
||||
</Grid>
|
||||
</Container>
|
||||
</Overlay>
|
||||
) : null;
|
||||
|
||||
export default compose(
|
||||
graphql(GetCategories, {
|
||||
options: () => ({
|
||||
ssr: false
|
||||
}),
|
||||
props: ({ data }) => {
|
||||
const { categories = [] } = data;
|
||||
return { categories };
|
||||
}
|
||||
}),
|
||||
graphql(GetProducts, {
|
||||
options: () => ({
|
||||
ssr: false
|
||||
}),
|
||||
props: ({ data }) => {
|
||||
const { products = [] } = data;
|
||||
return { products };
|
||||
}
|
||||
props: ({ data: { categories = [], loading = false, error = null } }) => ({
|
||||
categories,
|
||||
loading,
|
||||
error
|
||||
})
|
||||
})
|
||||
)(Services);
|
||||
|
|
|
@ -5,7 +5,6 @@ import pascalCase from 'pascal-case';
|
|||
import keys from 'lodash.keys';
|
||||
|
||||
import { DataCenterIcon, TritonIcon, ServicesIcon } from './components';
|
||||
// import { ServicesIcon } from './components';
|
||||
import * as Overlays from './containers';
|
||||
|
||||
import {
|
||||
|
@ -34,32 +33,21 @@ const GetHeader = gql`
|
|||
}
|
||||
`;
|
||||
|
||||
const GetAccount = gql`
|
||||
{
|
||||
datacenter {
|
||||
name
|
||||
}
|
||||
account {
|
||||
login
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
// <HeaderDividerItem />
|
||||
// <HeaderItem
|
||||
// onClick={() => toggleSectionOpen('services')}
|
||||
// active={isOpen && activePanel === 'services'}
|
||||
// >
|
||||
// <HeaderItemContent>Products & Services</HeaderItemContent>
|
||||
// <HeaderItemIcon>
|
||||
// <ServicesIcon light />
|
||||
// </HeaderItemIcon>
|
||||
// </HeaderItem>
|
||||
// <HeaderDividerItem />
|
||||
// Needs to be revised
|
||||
// const GetAccount = gql`
|
||||
// {
|
||||
// datacenter {
|
||||
// name
|
||||
// }
|
||||
// account {
|
||||
// login
|
||||
// }
|
||||
// }
|
||||
// `;
|
||||
|
||||
const Navigation = ({
|
||||
login,
|
||||
datacenter,
|
||||
datacenter = true,
|
||||
toggleSectionOpen,
|
||||
isOpen,
|
||||
activePanel
|
||||
|
@ -69,6 +57,17 @@ const Navigation = ({
|
|||
<HeaderItem>
|
||||
<TritonIcon light />
|
||||
</HeaderItem>
|
||||
<HeaderDividerItem />
|
||||
<HeaderItem
|
||||
onClick={() => toggleSectionOpen('services')}
|
||||
active={isOpen && activePanel === 'services'}
|
||||
>
|
||||
<HeaderItemContent>Products & Services</HeaderItemContent>
|
||||
<HeaderItemIcon>
|
||||
<ServicesIcon light />
|
||||
</HeaderItemIcon>
|
||||
</HeaderItem>
|
||||
<HeaderDividerItem />
|
||||
<HeaderFlexibleSpaceItem />
|
||||
<HeaderDividerItem />
|
||||
{datacenter ? (
|
||||
|
@ -79,7 +78,7 @@ const Navigation = ({
|
|||
<HeaderItemContent>
|
||||
<HeaderItemSubContent>Data Center:</HeaderItemSubContent>
|
||||
<HeaderSpace />
|
||||
<span>{datacenter}</span>
|
||||
<span>us-east-1</span>
|
||||
</HeaderItemContent>
|
||||
<HeaderItemIcon>
|
||||
<DataCenterIcon light />
|
||||
|
@ -87,18 +86,17 @@ const Navigation = ({
|
|||
</HeaderItem>
|
||||
) : null}
|
||||
{datacenter ? <HeaderDividerItem /> : null}
|
||||
{login ? (
|
||||
<HeaderItem>
|
||||
<HeaderItemContent>
|
||||
<HeaderItemSubContent>Account:</HeaderItemSubContent>
|
||||
<HeaderSpace />
|
||||
{login}
|
||||
</HeaderItemContent>
|
||||
<HeaderItemIcon>
|
||||
<Avatar />
|
||||
</HeaderItemIcon>
|
||||
</HeaderItem>
|
||||
) : null}
|
||||
<HeaderItem>
|
||||
<HeaderItemContent>
|
||||
<HeaderItemSubContent>Account:</HeaderItemSubContent>
|
||||
<HeaderSpace />
|
||||
Raul Millais
|
||||
</HeaderItemContent>
|
||||
<HeaderItemIcon>
|
||||
<Avatar />
|
||||
</HeaderItemIcon>
|
||||
</HeaderItem>
|
||||
)
|
||||
</HeaderRow>
|
||||
{keys(Overlays).map(panelName =>
|
||||
React.createElement(Overlays[panelName], {
|
||||
|
@ -109,23 +107,23 @@ const Navigation = ({
|
|||
);
|
||||
|
||||
export default compose(
|
||||
graphql(GetAccount, {
|
||||
options: () => ({
|
||||
ssr: false
|
||||
}),
|
||||
props: ({ data }) => {
|
||||
const {
|
||||
account = {},
|
||||
datacenter = {},
|
||||
loading = false,
|
||||
error = null
|
||||
} = data;
|
||||
const { login } = account;
|
||||
const { name } = datacenter;
|
||||
// graphql(GetAccount, {
|
||||
// options: () => ({
|
||||
// ssr: false
|
||||
// }),
|
||||
// props: ({ data }) => {
|
||||
// const {
|
||||
// account = {},
|
||||
// datacenter = {},
|
||||
// loading = false,
|
||||
// error = null
|
||||
// } = data;
|
||||
// const { login } = account;
|
||||
// const { name } = datacenter;
|
||||
|
||||
return { login, datacenter: name, loading, error };
|
||||
}
|
||||
}),
|
||||
// return { login, datacenter: name, loading, error };
|
||||
// }
|
||||
// }),
|
||||
graphql(GetHeader, {
|
||||
options: () => ({
|
||||
ssr: false
|
||||
|
|
|
@ -1,12 +1,3 @@
|
|||
import paramCase from 'param-case';
|
||||
|
||||
const dataSlugFromObjects = (arr = []) =>
|
||||
arr.map(({ name, ...obj }) => ({
|
||||
...obj,
|
||||
name,
|
||||
slug: paramCase(name)
|
||||
}));
|
||||
|
||||
export default {
|
||||
resolvers: {
|
||||
Mutation: {
|
||||
|
@ -17,106 +8,6 @@ export default {
|
|||
},
|
||||
defaults: {
|
||||
isOpen: false,
|
||||
activePanel: '',
|
||||
regions: dataSlugFromObjects([
|
||||
{
|
||||
name: 'Americas',
|
||||
__typename: 'Region'
|
||||
},
|
||||
{
|
||||
name: 'Europe',
|
||||
__typename: 'Region'
|
||||
},
|
||||
{
|
||||
name: 'Asia',
|
||||
__typename: 'Region'
|
||||
}
|
||||
]),
|
||||
places: dataSlugFromObjects([
|
||||
{
|
||||
name: 'Ashburn, Virginia, USA',
|
||||
region: 'americas',
|
||||
__typename: 'Place'
|
||||
},
|
||||
{
|
||||
name: 'Las Vegas, Nevada, USA',
|
||||
region: 'americas',
|
||||
__typename: 'Place'
|
||||
},
|
||||
{
|
||||
name: 'Emeryville, California, USA',
|
||||
region: 'americas',
|
||||
__typename: 'Place'
|
||||
},
|
||||
{
|
||||
name: 'Amsterdam, Netherlands',
|
||||
region: 'europe',
|
||||
__typename: 'Place'
|
||||
},
|
||||
{
|
||||
name: 'Singapore',
|
||||
region: 'asia',
|
||||
__typename: 'Place'
|
||||
},
|
||||
{
|
||||
name: 'Seoul, South Korea',
|
||||
region: 'asia',
|
||||
__typename: 'Place'
|
||||
}
|
||||
]),
|
||||
datacenters: dataSlugFromObjects([
|
||||
{
|
||||
name: 'us-east-1',
|
||||
place: 'ashburn-virginia-usa',
|
||||
__typename: 'Datacenter'
|
||||
},
|
||||
{
|
||||
name: 'us-east-2',
|
||||
place: 'ashburn-virginia-usa',
|
||||
__typename: 'Datacenter'
|
||||
},
|
||||
{
|
||||
name: 'us-east-3',
|
||||
place: 'ashburn-virginia-usa',
|
||||
__typename: 'Datacenter'
|
||||
},
|
||||
{
|
||||
name: 'us-west-1',
|
||||
place: 'emeryville-california-usa',
|
||||
__typename: 'Datacenter'
|
||||
},
|
||||
{
|
||||
name: 'us-sw-1',
|
||||
place: 'las-vegas-nevada-usa',
|
||||
__typename: 'Datacenter'
|
||||
},
|
||||
{
|
||||
name: 'eu-ams-1',
|
||||
place: 'amsterdam-netherlands',
|
||||
__typename: 'Datacenter'
|
||||
}
|
||||
]),
|
||||
categories: dataSlugFromObjects([
|
||||
{
|
||||
name: 'Compute',
|
||||
__typename: 'Category'
|
||||
},
|
||||
{
|
||||
name: 'Network',
|
||||
__typename: 'Category'
|
||||
},
|
||||
{
|
||||
name: 'Storage',
|
||||
__typename: 'Category'
|
||||
},
|
||||
{
|
||||
name: 'Access',
|
||||
__typename: 'Category'
|
||||
},
|
||||
{
|
||||
name: 'Help & Support',
|
||||
__typename: 'Category'
|
||||
}
|
||||
])
|
||||
activePanel: ''
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue