diff --git a/packages/ui-toolkit/src/button/index.js b/packages/ui-toolkit/src/button/index.js index 54368412..b5d34c82 100644 --- a/packages/ui-toolkit/src/button/index.js +++ b/packages/ui-toolkit/src/button/index.js @@ -173,7 +173,7 @@ const style = css` `}; ${is('bold')` - font-weight: bold; + font-weight: 500; `}; `; diff --git a/packages/ui-toolkit/src/index.js b/packages/ui-toolkit/src/index.js index 41da873e..d2522340 100644 --- a/packages/ui-toolkit/src/index.js +++ b/packages/ui-toolkit/src/index.js @@ -134,6 +134,7 @@ export { export { default as Table, Thead as TableThead, + ThFooter as TableThFooter, Tr as TableTr, Th as TableTh, Tbody as TableTbody, diff --git a/packages/ui-toolkit/src/table/index.js b/packages/ui-toolkit/src/table/index.js index f4951866..6d729319 100644 --- a/packages/ui-toolkit/src/table/index.js +++ b/packages/ui-toolkit/src/table/index.js @@ -2,7 +2,7 @@ import React from 'react'; import { Broadcast, Subscriber } from 'joy-react-broadcast'; import isBoolean from 'lodash.isboolean'; import styled, { css } from 'styled-components'; -import is from 'styled-is'; +import is, { isNot } from 'styled-is'; import remcalc from 'remcalc'; import Baseline from '../baseline'; @@ -45,7 +45,7 @@ const Column = css` white-space: nowrap; box-sizing: border-box; - padding: 0 ${remcalc(18)}; + padding: 0 ${remcalc(24)}; height: ${remcalc(60)}; ${handleBreakpoint('xs')}; @@ -124,22 +124,53 @@ const BaseTable = styled.table` max-width: 100%; `; -const BaseThead = styled.thead` +const BaseThFooter = styled.tfoot` width: 100%; th:first-child { - border-top-left-radius: ${remcalc(4)}; + border-bottom-left-radius: ${remcalc(4)}; } th:last-child { - border-top-right-radius: ${remcalc(4)}; + border-bottom-right-radius: ${remcalc(4)}; } th { - border-bottom-width: 0; + border-top-width: 0; } `; +const BaseThead = styled.thead` + width: 100%; + + ${is('footer')` + th:first-child { + border-bottom-left-radius: ${remcalc(4)}; + } + + th:last-child { + border-bottom-right-radius: ${remcalc(4)}; + } + + th { + border-top-width: 0; + } + `}; + ${isNot('footer')` + th:first-child { + border-top-left-radius: ${remcalc(4)}; + } + + th:last-child { + border-top-right-radius: ${remcalc(4)}; + } + + th { + border-bottom-width: 0; + } + `}; +`; + const BaseTbody = styled.tbody` width: 100%; @@ -167,6 +198,7 @@ const BaseTh = styled.th` ${is('selected')` color: ${props => props.theme.text}; + font-weight: bold; `}; &:not(:first-child) { @@ -186,7 +218,6 @@ const BaseTh = styled.th` const BaseTd = styled.td` ${Column}; - transition: all 200ms ease; border-bottom-width: 0; vertical-align: middle; @@ -279,6 +310,16 @@ export const Thead = Baseline(({ children, ...rest }) => ( )); +export const ThFooter = Baseline(({ children, ...rest }) => ( + + {value => ( + + {children} + + )} + +)); + export const Tr = Baseline(({ children, ...rest }) => ( {value => ( diff --git a/prototypes/create-instance-icons/src/components/affinity/index.js b/prototypes/create-instance-icons/src/components/affinity/index.js index 3e535961..4a53db4e 100644 --- a/prototypes/create-instance-icons/src/components/affinity/index.js +++ b/prototypes/create-instance-icons/src/components/affinity/index.js @@ -104,7 +104,7 @@ class Affinity extends Component {

Affinity rules control the location of instances, to help reduce traffic across networks and keep the workload balanced. With strict - rules, instances are only provisioned when the criteria is met.{' '} + rules, instances are only provisioned when the criteria is met. {' '} Read the docs @@ -122,85 +122,82 @@ class Affinity extends Component { , - {this.state.showRuleCreation ? ( - - - - - - -

Create an affinity rule

- - - - - -
-

The instance

-
-
- + + + +
+
+

be on

+
+
+ +
+
+

node as the instance(s) identified by the

+
+
+ + -
-
-

be on

-
-
- + + + + + -
-
-

node as the instance(s) identified by the

-
-
- - - - - - - -
-
- - -
-
- - - ) : ( - - - - )} + + + +
+ + +
+ + + + ) : ( + + + + )} ]; diff --git a/prototypes/create-instance-icons/src/components/filters/filters.js b/prototypes/create-instance-icons/src/components/filters/filters.js index f000cc13..0e30ea2a 100644 --- a/prototypes/create-instance-icons/src/components/filters/filters.js +++ b/prototypes/create-instance-icons/src/components/filters/filters.js @@ -17,8 +17,7 @@ import { Label, H2, H4, - P, - ViewContainer + P } from 'joyent-ui-toolkit'; const FullWidth = styled(Margin)` @@ -38,7 +37,8 @@ class Filters extends Component { ram, cpu, disk, - cost + cost, + reset: 0 }; } @@ -56,7 +56,8 @@ class Filters extends Component { ram, cpu, disk, - cost + cost, + reset: this.state.reset + 1 }); }; @@ -122,7 +123,8 @@ class Filters extends Component { costChange={value => costChange(value)} filters={filters} disabled={isEqual(filters, defaultState.filters)} - onClick={this.handleResetClick} + onResetClick={this.handleResetClick} + reset={this.state.reset} /> ]; diff --git a/prototypes/create-instance-icons/src/components/filters/inputs.js b/prototypes/create-instance-icons/src/components/filters/inputs.js index bc1670db..3c236a30 100644 --- a/prototypes/create-instance-icons/src/components/filters/inputs.js +++ b/prototypes/create-instance-icons/src/components/filters/inputs.js @@ -1,5 +1,6 @@ import React, { Component } from 'react'; import styled from 'styled-components'; +import remcalc from 'remcalc'; import { FormGroup, FormLabel, @@ -9,52 +10,92 @@ import { InputDropdown } from 'joyent-ui-toolkit'; import { Row, Col } from 'react-styled-flexboxgrid'; -import { Padding } from 'styled-components-spacing'; +import { Padding, Margin } from 'styled-components-spacing'; const RowFullWidth = styled(Row)` width: 100%; `; -const InputDropdownBorder = styled(InputDropdown)` - border-right: 1px solid ${props => props.theme.grey}; - margin-right: 24px; - padding-right: 24px; + +const Divider = styled.div` + width: ${remcalc(1)}; + background: ${props => props.theme.grey}; + height: ${remcalc(66)}; + margin: 0 ${remcalc(14)}; + margin-bottom: ${remcalc(9)}; + display: flex; + align-self: flex-end; `; -const valuesToSend = (changed, target, value, name) => ({ +const isToBeMultiplied = (name, state, target) => + (name === 'ram' && state[name][`${target}Selected`] === 'MB') || + (name === 'disk' && state[name][`${target}Selected`] === 'GB'); + +const valuesToSend = (changed, target, value) => ({ min: !isNaN(parseFloat(changed.min)) ? parseFloat(changed.min) : 0, max: !isNaN(parseFloat(changed.max)) ? parseFloat(changed.max) : 0, [target]: parseFloat(value) }); +const ramLogic = ram => ({ + min: ram.min > 1 ? ram.min : ram.min * 1000, + minSelected: 'MB', + max: ram.max > 1 ? ram.max : ram.max * 1000, + maxSelected: 'GB' +}); + +const diskLogic = disk => ({ + min: disk.min > 1 ? disk.min : disk.min * 1000, + minSelected: 'GB', + max: disk.max > 1 ? disk.max : disk.max * 1000, + maxSelected: 'TB' +}); + class Inputs extends Component { constructor(props) { super(props); - const { filters: { cpu, cost, ram, disk } } = this.props; + const { filters: { cpu, cost, ram, disk }, reset } = this.props; this.state = { - ram: { - min: ram.min > 1 ? ram.min : ram.min * 1000, - minSelected: 'MB', - max: ram.max > 1 ? ram.max : ram.max * 1000, - maxSelected: 'GB' - }, + ram: ramLogic(ram), cpu, - disk: { - min: disk.min > 1 ? disk.min : disk.min * 1000, - minSelected: 'GB', - max: disk.max > 1 ? disk.max : disk.max * 1000, - maxSelected: 'TB' - }, - cost + disk: diskLogic(disk), + cost, + reset }; } + componentWillReceiveProps = nextProps => { + const { filters: { cpu, cost, ram, disk }, reset } = nextProps; + if (reset !== this.state.reset) { + this.setState({ + ram: ramLogic(ram), + cpu, + disk: diskLogic(disk), + cost, + reset + }); + } + }; + handleChange = (e, name, target) => { const changed = this.state[name]; const value = (e.target || {}).value; setTimeout(() => { - this.props[`${name}Change`](valuesToSend(changed, target, value, name)); + this.props[`${name}Change`]( + valuesToSend( + { + min: isToBeMultiplied(name, this.state, 'min') + ? changed.min / 1000 + : changed.min, + max: isToBeMultiplied(name, this.state, 'max') + ? changed.max / 1000 + : changed.max + }, + target, + isToBeMultiplied(name, this.state, target) ? value / 1000 : value + ) + ); }, 1000); this.setState({ @@ -68,6 +109,8 @@ class Inputs extends Component { handleSelectChange = (e, name, target, valueTarget) => { const value = (e.target || {}).value; + const isToBeMultiplied = + (name === 'ram' && value === 'MB') || (name === 'disk' && value === 'GB'); this.setState({ ...this.state, [name]: { @@ -75,13 +118,36 @@ class Inputs extends Component { [target]: value } }); + + this.props[`${name}Change`]( + valuesToSend( + this.state[name], + valueTarget, + isToBeMultiplied + ? this.state[name][valueTarget] / 1000 + : this.state[name][valueTarget] + ) + ); }; handleBlur = (e, name, target) => { const changed = this.state[name]; const value = (e.target || {}).value; - this.props[`${name}Change`](valuesToSend(changed, target, value, name)); + this.props[`${name}Change`]( + valuesToSend( + { + min: isToBeMultiplied(name, this.state, 'min') + ? changed.min / 1000 + : changed.min, + max: isToBeMultiplied(name, this.state, 'max') + ? changed.max / 1000 + : changed.max + }, + target, + isToBeMultiplied(name, this.state, target) ? value / 1000 : value + ) + ); this.setState({ ...this.state, @@ -94,7 +160,7 @@ class Inputs extends Component { render() { const { cpu, cost, ram, disk } = this.state; - const { onClick, disabled } = this.props; + const { onResetClick, disabled } = this.props; return [ @@ -124,7 +190,7 @@ class Inputs extends Component { to - + MB - + + Disk @@ -218,6 +285,7 @@ class Inputs extends Component { /> + $/hour @@ -243,9 +311,17 @@ class Inputs extends Component { , - + + + ]; diff --git a/prototypes/create-instance-icons/src/components/home/home.js b/prototypes/create-instance-icons/src/components/home/home.js index 715500a5..ac9d3e6d 100644 --- a/prototypes/create-instance-icons/src/components/home/home.js +++ b/prototypes/create-instance-icons/src/components/home/home.js @@ -9,7 +9,9 @@ import { BreadcrumbItem, Anchor, Button, - Divider + Divider, + MessageTitle, + MessageDescription } from 'joyent-ui-toolkit'; class Home extends Component { @@ -47,7 +49,6 @@ class Home extends Component { selected: values[key] ? values[key] : false })); - console.table(groups); onFilterChange({ ...filters, groups @@ -60,9 +61,12 @@ class Home extends Component { const { filters, onFilterReset, packages } = this.props; const _msg = showMessage ? ( - Not all data centres have all configurations of instances available. - Make sure that you choose the data center that suits your requirements.{' '} - Learn More + Choosing deployment data center + + Not all data centres have all configurations of instances available. + Make sure that you choose the data center that suits your + requirements. Learn More + ) : null; @@ -103,10 +107,12 @@ class Home extends Component { , - + + + , - + ]; diff --git a/prototypes/create-instance-icons/src/components/icons/index.js b/prototypes/create-instance-icons/src/components/icons/index.js index 272a1ad1..8fa98639 100644 --- a/prototypes/create-instance-icons/src/components/icons/index.js +++ b/prototypes/create-instance-icons/src/components/icons/index.js @@ -40,7 +40,7 @@ export const returnIcon = group => { - + {icon} diff --git a/prototypes/create-instance-icons/src/components/navigation/header.js b/prototypes/create-instance-icons/src/components/navigation/header.js index b1606542..d3a2ba4c 100644 --- a/prototypes/create-instance-icons/src/components/navigation/header.js +++ b/prototypes/create-instance-icons/src/components/navigation/header.js @@ -1,5 +1,7 @@ import React from 'react'; import { Link } from 'react-router-dom'; +import styled from 'styled-components'; +import remcalc from 'remcalc'; import { Header, @@ -11,11 +13,15 @@ import { UserIconLight } from 'joyent-ui-toolkit'; +const HeaderBrandStyled = styled(HeaderBrand)` + margin-top: ${remcalc(6)}; +`; + const NavHeader = () => (
- + - +
  • diff --git a/prototypes/create-instance-icons/src/components/package/index.js b/prototypes/create-instance-icons/src/components/package/index.js index 08437400..52197605 100644 --- a/prototypes/create-instance-icons/src/components/package/index.js +++ b/prototypes/create-instance-icons/src/components/package/index.js @@ -1,10 +1,18 @@ import React from 'react'; import { reduxForm } from 'redux-form'; +import styled from 'styled-components'; +import remcalc from 'remcalc'; import { returnIcon } from '../icons'; import { TableTr, TableTd, H4, Radio, FormGroup } from 'joyent-ui-toolkit'; +const FormGroupStyled = styled(FormGroup)` + float: left; + margin-right: ${remcalc(24)}; + margin-top: ${remcalc(3)}; +`; + const Package = ({ pack: { price, memory, vcpus, disk, group, ssd, name }, selected, @@ -12,20 +20,18 @@ const Package = ({ }) => ( - + - - - + {returnIcon(group)}

    {name}

    - + {memory > 1 ? `${parseInt(memory, 10)} GB` : `${memory * 1000} MB`} - {disk > 1 ? `${disk} TB` : `${disk * 1000} GB`} - {vcpus} - {price.toFixed(3)} + {disk > 1 ? `${disk} TB` : `${disk * 1000} GB`} + {vcpus} + {price.toFixed(3)}
    ); diff --git a/prototypes/create-instance-icons/src/components/packages/list.js b/prototypes/create-instance-icons/src/components/packages/list.js index 05110d9c..7d6915ed 100644 --- a/prototypes/create-instance-icons/src/components/packages/list.js +++ b/prototypes/create-instance-icons/src/components/packages/list.js @@ -12,6 +12,7 @@ import { Table, TableThead, TableTbody, + TableThFooter, TableTr, TableTh, ArrowIcon @@ -21,18 +22,15 @@ const ArrowIconStyled = styled(ArrowIcon)` margin-left: ${remcalc(6)}; cursor: pointer; position: relative; - top: ${remcalc(-1)}; + top: ${remcalc(-3)}; transition: transform 200ms ease; path { - fill: ${props => props.theme.grey}; + fill: ${props => props.theme.text}; } ${is('selected', 'down')` transform: rotate(180deg); - path { - fill: ${props => props.theme.text}; - } `}; `; @@ -46,8 +44,10 @@ class Packages extends Component { super(props); this.state = { - packages: props.packages, - selected: null + packages: props.packages.sort((a, b) => (a.price > b.price ? 1 : -1)), + selected: null, + price: true, + ordered: 'price' }; } @@ -84,56 +84,65 @@ class Packages extends Component { - this.order('name')}> Name{' '} - this.order('name')} - /> + {ordered === 'name' && ( + this.order('name')} + /> + )} this.order('memory')}> RAM{' '} - this.order('memory')} - /> + {ordered === 'memory' && ( + this.order('memory')} + /> + )} this.order('disk')}> Disk{' '} - this.order('disk')} - /> + {ordered === 'disk' && ( + this.order('disk')} + /> + )} this.order('vcpus')}> vCPU{' '} - this.order('vcpus')} - /> + {ordered === 'vcpus' && ( + this.order('vcpus')} + /> + )} this.order('price')}> $/hour{' '} - this.order('price')} - /> + {ordered === 'price' && ( + this.order('price')} + /> + )} @@ -147,12 +156,76 @@ class Packages extends Component { /> ))} + + + + this.order('name')}> + Name{' '} + + {ordered === 'name' && ( + this.order('name')} + /> + )} + + + this.order('memory')}> + RAM{' '} + + {ordered === 'memory' && ( + this.order('memory')} + /> + )} + + + this.order('disk')}> + Disk{' '} + + {ordered === 'disk' && ( + this.order('disk')} + /> + )} + + + this.order('vcpus')}> + vCPU{' '} + + {ordered === 'vcpus' && ( + this.order('vcpus')} + /> + )} + + + this.order('price')}> + $/hour{' '} + + {ordered === 'price' && ( + this.order('price')} + /> + )} + + +
    ) : ( - + diff --git a/prototypes/create-instance-icons/src/state/store.js b/prototypes/create-instance-icons/src/state/store.js index 4d224526..3885601d 100644 --- a/prototypes/create-instance-icons/src/state/store.js +++ b/prototypes/create-instance-icons/src/state/store.js @@ -50,11 +50,11 @@ export const store = createStore( }), state, // Initial state compose( - applyMiddleware(client.middleware()) + applyMiddleware(client.middleware()), // If you are using the devToolsExtension, you can add it here also // eslint-disable-next-line no-negated-condition - // typeof GLOBAL.__REDUX_DEVTOOLS_EXTENSION__ !== 'undefined' - // ? GLOBAL.__REDUX_DEVTOOLS_EXTENSION__() - // : f => f + typeof GLOBAL.__REDUX_DEVTOOLS_EXTENSION__ !== 'undefined' + ? GLOBAL.__REDUX_DEVTOOLS_EXTENSION__() + : f => f ) );