Feat: New styleguide, table component and screen
This commit is contained in:
parent
c100c11a2f
commit
8b4a1ff23f
20 changed files with 309 additions and 287 deletions
46
new-lamassu-admin/package-lock.json
generated
46
new-lamassu-admin/package-lock.json
generated
|
|
@ -4737,7 +4737,8 @@
|
|||
"asap": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
|
||||
"integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY="
|
||||
"integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=",
|
||||
"dev": true
|
||||
},
|
||||
"asn1": {
|
||||
"version": "0.2.4",
|
||||
|
|
@ -7705,6 +7706,7 @@
|
|||
"version": "0.2.3",
|
||||
"resolved": "https://registry.npmjs.org/create-react-context/-/create-react-context-0.2.3.tgz",
|
||||
"integrity": "sha512-CQBmD0+QGgTaxDL3OX1IDXYqjkp2It4RIbcb99jS6AEg27Ga+a9G3JtK6SIu0HBwPLZlmwt9F7UwWA4Bn92Rag==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fbjs": "^0.8.0",
|
||||
"gud": "^1.0.0"
|
||||
|
|
@ -8800,6 +8802,7 @@
|
|||
"version": "0.1.12",
|
||||
"resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz",
|
||||
"integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"iconv-lite": "~0.4.13"
|
||||
}
|
||||
|
|
@ -10278,6 +10281,7 @@
|
|||
"version": "0.8.17",
|
||||
"resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.17.tgz",
|
||||
"integrity": "sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"core-js": "^1.0.0",
|
||||
"isomorphic-fetch": "^2.1.1",
|
||||
|
|
@ -10291,12 +10295,14 @@
|
|||
"core-js": {
|
||||
"version": "1.2.7",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz",
|
||||
"integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY="
|
||||
"integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=",
|
||||
"dev": true
|
||||
},
|
||||
"promise": {
|
||||
"version": "7.3.1",
|
||||
"resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
|
||||
"integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"asap": "~2.0.3"
|
||||
}
|
||||
|
|
@ -10618,17 +10624,16 @@
|
|||
"dev": true
|
||||
},
|
||||
"formik": {
|
||||
"version": "1.5.8",
|
||||
"resolved": "https://registry.npmjs.org/formik/-/formik-1.5.8.tgz",
|
||||
"integrity": "sha512-fNvPe+ddbh+7xiByT25vuso2p2hseG/Yvuj211fV1DbCjljUEG9OpgRpcb7g7O3kxHX/q31cbZDzMxJXPWSNwA==",
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/formik/-/formik-2.0.3.tgz",
|
||||
"integrity": "sha512-kYBvcxlsYSncY8OiJHD49C0UmoWXbgmIc9V1g3N1WwBJ7SMLk34QpcJDgroYd42K1cH+mSJlXhB7PlgTXTzlWg==",
|
||||
"requires": {
|
||||
"create-react-context": "^0.2.2",
|
||||
"deepmerge": "^2.1.1",
|
||||
"hoist-non-react-statics": "^3.3.0",
|
||||
"lodash": "^4.17.14",
|
||||
"lodash-es": "^4.17.14",
|
||||
"prop-types": "^15.6.1",
|
||||
"react-fast-compare": "^2.0.1",
|
||||
"scheduler": "^0.14.0",
|
||||
"tiny-warning": "^1.0.2",
|
||||
"tslib": "^1.9.3"
|
||||
},
|
||||
|
|
@ -10637,6 +10642,15 @@
|
|||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz",
|
||||
"integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA=="
|
||||
},
|
||||
"scheduler": {
|
||||
"version": "0.14.0",
|
||||
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.14.0.tgz",
|
||||
"integrity": "sha512-9CgbS06Kki2f4R9FjLSITjZo5BZxPsryiRNyL3LpvrM9WxcVmhlqAOc9E+KQbeI2nqej4JIIbOsfdL51cNb4Iw==",
|
||||
"requires": {
|
||||
"loose-envify": "^1.1.0",
|
||||
"object-assign": "^4.1.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -11476,6 +11490,7 @@
|
|||
"version": "0.4.24",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
||||
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"safer-buffer": ">= 2.1.2 < 3"
|
||||
}
|
||||
|
|
@ -11975,7 +11990,8 @@
|
|||
"is-stream": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
|
||||
"integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ="
|
||||
"integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
|
||||
"dev": true
|
||||
},
|
||||
"is-svg": {
|
||||
"version": "3.0.0",
|
||||
|
|
@ -12041,6 +12057,7 @@
|
|||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz",
|
||||
"integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"node-fetch": "^1.0.1",
|
||||
"whatwg-fetch": ">=0.10.0"
|
||||
|
|
@ -14856,6 +14873,7 @@
|
|||
"version": "1.7.3",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz",
|
||||
"integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"encoding": "^0.1.11",
|
||||
"is-stream": "^1.0.1"
|
||||
|
|
@ -19994,7 +20012,8 @@
|
|||
"safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
|
||||
"dev": true
|
||||
},
|
||||
"sane": {
|
||||
"version": "4.1.0",
|
||||
|
|
@ -20318,7 +20337,8 @@
|
|||
"setimmediate": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
|
||||
"integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU="
|
||||
"integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=",
|
||||
"dev": true
|
||||
},
|
||||
"setprototypeof": {
|
||||
"version": "1.1.1",
|
||||
|
|
@ -22019,7 +22039,8 @@
|
|||
"ua-parser-js": {
|
||||
"version": "0.7.20",
|
||||
"resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.20.tgz",
|
||||
"integrity": "sha512-8OaIKfzL5cpx8eCMAhhvTlft8GYF8b2eQr6JkCyVdrgjcytyOmPCXrqXFcUnhonRpLlh5yxEZVohm6mzaowUOw=="
|
||||
"integrity": "sha512-8OaIKfzL5cpx8eCMAhhvTlft8GYF8b2eQr6JkCyVdrgjcytyOmPCXrqXFcUnhonRpLlh5yxEZVohm6mzaowUOw==",
|
||||
"dev": true
|
||||
},
|
||||
"uglify-js": {
|
||||
"version": "3.4.9",
|
||||
|
|
@ -22849,7 +22870,8 @@
|
|||
"whatwg-fetch": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz",
|
||||
"integrity": "sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q=="
|
||||
"integrity": "sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q==",
|
||||
"dev": true
|
||||
},
|
||||
"whatwg-mimetype": {
|
||||
"version": "2.3.0",
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
"classnames": "2.2.6",
|
||||
"downshift": "3.3.4",
|
||||
"file-saver": "2.0.2",
|
||||
"formik": "1.5.8",
|
||||
"formik": "2.0.3",
|
||||
"jss-plugin-extend": "^10.0.0",
|
||||
"lodash": "4.17.15",
|
||||
"moment": "2.24.0",
|
||||
|
|
|
|||
|
|
@ -62,7 +62,9 @@ const Header = memo(({ tree }) => {
|
|||
className={classnames(classes.link, classes.whiteLink)}
|
||||
activeClassName={classes.activeLink}
|
||||
>
|
||||
<span className={classes.forceSize} forcesize={it.label}>
|
||||
{it.label}
|
||||
</span>
|
||||
</NavLink>
|
||||
</li>
|
||||
))}
|
||||
|
|
|
|||
|
|
@ -11,10 +11,10 @@ import {
|
|||
|
||||
import typographyStyles from './typography/styles'
|
||||
|
||||
const { tl2 } = typographyStyles
|
||||
const { tl2, p } = typographyStyles
|
||||
|
||||
let headerHeight = spacer * 7
|
||||
let subheaderHeight = spacer * 6
|
||||
let subheaderHeight = spacer * 5
|
||||
|
||||
if (version === 8) {
|
||||
headerHeight = spacer * 8
|
||||
|
|
@ -51,11 +51,15 @@ export default {
|
|||
padding: `0 ${spacer * 2.5}px`
|
||||
},
|
||||
link: {
|
||||
extend: tl2,
|
||||
extend: p,
|
||||
textDecoration: 'none',
|
||||
border: 'none',
|
||||
color: white,
|
||||
backgroundColor: 'transparent',
|
||||
'&:hover': {
|
||||
extend: tl2,
|
||||
color: white
|
||||
},
|
||||
'&:hover::after': {
|
||||
width: '50%',
|
||||
marginLeft: '-25%'
|
||||
|
|
@ -75,7 +79,21 @@ export default {
|
|||
transition: 'all 0.2s cubic-bezier(0.95, 0.1, 0.45, 0.94)'
|
||||
}
|
||||
},
|
||||
forceSize: {
|
||||
display: 'inline-block',
|
||||
textAlign: 'center',
|
||||
'&:after': {
|
||||
display: 'block',
|
||||
content: 'attr(forcesize)',
|
||||
fontWeight: 700,
|
||||
height: 0,
|
||||
overflow: 'hidden',
|
||||
visibility: 'hidden'
|
||||
}
|
||||
},
|
||||
activeLink: {
|
||||
extend: tl2,
|
||||
color: white,
|
||||
'&::after': {
|
||||
width: '50%',
|
||||
marginLeft: '-25%'
|
||||
|
|
|
|||
|
|
@ -6,19 +6,25 @@ import styles from './Sidebar.styles'
|
|||
|
||||
const useStyles = makeStyles(styles)
|
||||
|
||||
const Logs = ({ data, displayName, isSelected, onClick, children }) => {
|
||||
const Logs = ({ data, displayName, isSelected, onClick, children, itemRender }) => {
|
||||
const classes = useStyles()
|
||||
|
||||
return (
|
||||
<div className={classes.sidebar}>
|
||||
{data &&
|
||||
data.map((it, idx) => (
|
||||
<p
|
||||
<div
|
||||
key={idx}
|
||||
className={classnames(isSelected(it) ? classes.activeLink : '', classes.link)}
|
||||
className={classnames({
|
||||
[classes.activeLink]: isSelected(it),
|
||||
[classes.customRenderActiveLink]: itemRender && isSelected(it),
|
||||
[classes.customRenderLink]: itemRender,
|
||||
[classes.link]: true
|
||||
})}
|
||||
onClick={() => onClick(it)}
|
||||
>
|
||||
{displayName(it)}
|
||||
</p>
|
||||
{itemRender ? itemRender(it) : displayName(it)}
|
||||
</div>
|
||||
))}
|
||||
{children}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
import { respondTo } from '../styling/helpers'
|
||||
import { primaryColor, spacer, placeholderColor, zircon, xxl } from '../styling/variables'
|
||||
|
||||
import typographyStyles from './typography/styles'
|
||||
|
||||
const { tl2 } = typographyStyles
|
||||
|
||||
const sidebarColor = zircon
|
||||
|
||||
export default {
|
||||
|
|
@ -12,7 +16,7 @@ export default {
|
|||
boxShadow: `-500px 0px 0px 0px ${sidebarColor}`,
|
||||
borderRadius: '0 20px 0 0',
|
||||
alignItems: 'flex-end',
|
||||
padding: spacer * 2.5,
|
||||
padding: spacer * 3,
|
||||
flexDirection: 'column',
|
||||
[respondTo(xxl)]: {
|
||||
width: 'auto',
|
||||
|
|
@ -23,9 +27,10 @@ export default {
|
|||
},
|
||||
|
||||
link: {
|
||||
extend: tl2,
|
||||
position: 'relative',
|
||||
color: placeholderColor,
|
||||
marginRight: 24,
|
||||
margin: '12px 24px 12px 0',
|
||||
cursor: 'pointer',
|
||||
'&:hover::after': {
|
||||
height: '140%'
|
||||
|
|
@ -50,5 +55,18 @@ export default {
|
|||
'&::after': {
|
||||
height: '140%'
|
||||
}
|
||||
},
|
||||
customRenderLink: {
|
||||
'&:hover::after': {
|
||||
height: '100%'
|
||||
},
|
||||
'&:after': {
|
||||
bottom: 0
|
||||
}
|
||||
},
|
||||
customRenderActiveLink: {
|
||||
'&::after': {
|
||||
height: '100%'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import {
|
|||
|
||||
import typographyStyles from '../typography/styles'
|
||||
|
||||
const { label } = typographyStyles
|
||||
const { p } = typographyStyles
|
||||
|
||||
const colors = (color1, color2, color3) => {
|
||||
return {
|
||||
|
|
@ -25,7 +25,7 @@ const colors = (color1, color2, color3) => {
|
|||
|
||||
export default {
|
||||
actionButton: {
|
||||
extend: label,
|
||||
extend: p,
|
||||
cursor: 'pointer',
|
||||
border: 'none',
|
||||
height: 24,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import React, { useState } from 'react'
|
||||
import { identity } from 'lodash/fp'
|
||||
import { FastField } from 'formik'
|
||||
import React, { useState, memo } from 'react'
|
||||
import { identity, isEmpty } from 'lodash/fp'
|
||||
import { Form, Formik, FastField, useFormikContext } from 'formik'
|
||||
|
||||
import {
|
||||
Td,
|
||||
|
|
@ -13,18 +13,24 @@ const getField = (name, component, props = {}) => (
|
|||
<FastField name={name} component={component} {...props} />
|
||||
)
|
||||
|
||||
const ERow = ({ elements, cancel, save, value }) => {
|
||||
const ERow = memo(({ elements }) => {
|
||||
const { values, submitForm, resetForm, errors } = useFormikContext()
|
||||
const [editing, setEditing] = useState(false)
|
||||
|
||||
const innerSave = () => {
|
||||
submitForm()
|
||||
}
|
||||
|
||||
const innerCancel = () => {
|
||||
setEditing(false)
|
||||
cancel()
|
||||
resetForm()
|
||||
}
|
||||
|
||||
return (
|
||||
<Tr>
|
||||
{elements.map(({ name, input, size, view = identity, inputProps }, idx) => (
|
||||
<Td key={idx} size={size}>
|
||||
{editing ? getField(name, input, inputProps) : view(value[name])}
|
||||
<Tr error={!isEmpty(errors)} errorMessage={errors && errors.toString()}>
|
||||
{elements.map(({ name, input, size, textAlign, view = identity, inputProps }, idx) => (
|
||||
<Td key={idx} size={size} textAlign={textAlign}>
|
||||
{editing ? getField(name, input, inputProps) : view(values[name])}
|
||||
</Td>
|
||||
))}
|
||||
<Td size={175}>
|
||||
|
|
@ -33,7 +39,7 @@ const ERow = ({ elements, cancel, save, value }) => {
|
|||
<Link style={{ marginRight: '20px' }} color='secondary' onClick={innerCancel}>
|
||||
Cancel
|
||||
</Link>
|
||||
<Link color='primary' onClick={save}>
|
||||
<Link color='primary' onClick={innerSave}>
|
||||
Save
|
||||
</Link>
|
||||
</>
|
||||
|
|
@ -45,6 +51,21 @@ const ERow = ({ elements, cancel, save, value }) => {
|
|||
</Td>
|
||||
</Tr>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
export default ERow
|
||||
const ERowWithFormik = memo(({ value, validationSchema, save, elements }) => {
|
||||
return (
|
||||
<Formik
|
||||
enableReinitialize
|
||||
initialValues={value}
|
||||
validationSchema={validationSchema}
|
||||
onSubmit={save}
|
||||
>
|
||||
<Form>
|
||||
<ERow elements={elements} />
|
||||
</Form>
|
||||
</Formik>
|
||||
)
|
||||
})
|
||||
|
||||
export default ERowWithFormik
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import React from 'react'
|
||||
import React, { memo } from 'react'
|
||||
import { startCase } from 'lodash/fp'
|
||||
|
||||
import {
|
||||
|
|
@ -10,23 +10,20 @@ import {
|
|||
|
||||
import ERow from './Row'
|
||||
|
||||
const ETable = ({ elements = [], data = [], cancel, save, components = {} }) => {
|
||||
const { row } = components
|
||||
const Row = row || ERow
|
||||
|
||||
const ETable = memo(({ elements = [], data = [], save, validationSchema }) => {
|
||||
return (
|
||||
<Table>
|
||||
<THead>
|
||||
{elements.map(({ name, size, header }, idx) => (
|
||||
<Td header key={idx} size={size}>{header || startCase(name)}</Td>
|
||||
{elements.map(({ name, size, header, textAlign }, idx) => (
|
||||
<Td header key={idx} size={size} textAlign={textAlign}>{header || startCase(name)}</Td>
|
||||
))}
|
||||
<Td header size={175} />
|
||||
</THead>
|
||||
<TBody>
|
||||
{data.map((it, idx) => <Row key={idx} value={it} elements={elements} cancel={cancel} save={save} />)}
|
||||
{data.map((it, idx) => <ERow key={idx} value={it} elements={elements} save={save} validationSchema={validationSchema} />)}
|
||||
</TBody>
|
||||
</Table>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
export default ETable
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import React from 'react'
|
||||
import classnames from 'classnames'
|
||||
import ExpansionPanel from '@material-ui/core/ExpansionPanel'
|
||||
import ExpansionPanelSummary from '@material-ui/core/ExpansionPanelSummary'
|
||||
import Card from '@material-ui/core/Card'
|
||||
import CardContent from '@material-ui/core/CardContent'
|
||||
|
||||
import { makeStyles } from '@material-ui/core/styles'
|
||||
|
||||
|
|
@ -10,20 +10,21 @@ import { Link } from '../../components/buttons'
|
|||
import {
|
||||
tableHeaderColor,
|
||||
tableHeaderHeight,
|
||||
tableErrorColor,
|
||||
spacer,
|
||||
white
|
||||
} from '../../styling/variables'
|
||||
|
||||
import typographyStyles from '../typography/styles'
|
||||
|
||||
const { label2, p } = typographyStyles
|
||||
const { tl2, p } = typographyStyles
|
||||
|
||||
const useStyles = makeStyles({
|
||||
body: {
|
||||
borderSpacing: '0 4px'
|
||||
},
|
||||
header: {
|
||||
extend: label2,
|
||||
extend: tl2,
|
||||
backgroundColor: tableHeaderColor,
|
||||
height: tableHeaderHeight,
|
||||
textAlign: 'left',
|
||||
|
|
@ -39,39 +40,31 @@ const useStyles = makeStyles({
|
|||
display: 'table-cell',
|
||||
padding: `0 ${spacer * 3}px`
|
||||
},
|
||||
summary: {
|
||||
cursor: 'auto'
|
||||
trError: {
|
||||
backgroundColor: tableErrorColor
|
||||
},
|
||||
mainContent: {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
minHeight: 54
|
||||
},
|
||||
// mui-overrides
|
||||
panelRoot: {
|
||||
cardContentRoot: {
|
||||
// display: 'flex',
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
'&:last-child': {
|
||||
padding: 0
|
||||
}
|
||||
},
|
||||
card: {
|
||||
extend: p,
|
||||
display: 'table-row',
|
||||
'&:before': {
|
||||
height: 0
|
||||
},
|
||||
margin: '4px 0',
|
||||
width: 'min-content',
|
||||
boxShadow: '0 0 4px 0 rgba(0, 0, 0, 0.08)'
|
||||
},
|
||||
panelExpanded: {
|
||||
'&:first-child': {
|
||||
marginTop: '4px !important'
|
||||
}
|
||||
},
|
||||
summaryRoot: {
|
||||
userSelect: 'auto',
|
||||
'&:hover:not(.Mui-disabled)': {
|
||||
cursor: 'auto'
|
||||
},
|
||||
cursor: 'auto',
|
||||
padding: 0
|
||||
},
|
||||
summaryContent: {
|
||||
margin: 0,
|
||||
height: 54,
|
||||
alignItems: 'center'
|
||||
},
|
||||
summaryFocused: {
|
||||
backgroundColor: 'inherit !important'
|
||||
}
|
||||
})
|
||||
|
||||
|
|
@ -99,7 +92,7 @@ const TBody = ({ children, className }) => {
|
|||
)
|
||||
}
|
||||
|
||||
const Td = ({ children, header, className, size = 100 }) => {
|
||||
const Td = ({ children, header, className, size = 100, textAlign }) => {
|
||||
const classes = useStyles()
|
||||
const classNames = {
|
||||
[classes.td]: true,
|
||||
|
|
@ -107,23 +100,28 @@ const Td = ({ children, header, className, size = 100 }) => {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className={classnames(className, classNames)} style={{ width: size }}>
|
||||
<div className={classnames(className, classNames)} style={{ width: size, textAlign }}>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const Tr = ({ children }) => {
|
||||
const Tr = ({ error, errorMessage, children }) => {
|
||||
const classes = useStyles()
|
||||
const epClasses = { root: classes.panelRoot, expanded: classes.panelExpanded }
|
||||
const summaryClasses = { root: classes.summaryRoot, content: classes.summaryContent, focused: classes.summaryFocused }
|
||||
const cardClasses = { root: classes.cardContentRoot }
|
||||
const classNames = {
|
||||
[classes.trError]: error
|
||||
}
|
||||
|
||||
return (
|
||||
<ExpansionPanel expanded={false} classes={epClasses} square>
|
||||
<ExpansionPanelSummary tabIndex={null} classes={summaryClasses} className={classes.summary}>
|
||||
{children}
|
||||
</ExpansionPanelSummary>
|
||||
</ExpansionPanel>
|
||||
<>
|
||||
<Card className={classnames(classNames, classes.card)}>
|
||||
<CardContent classes={cardClasses}>
|
||||
<div className={classes.mainContent}>{children}</div>
|
||||
{error && <div className={classes.errorContent}>{errorMessage}</div>}
|
||||
</CardContent>
|
||||
</Card>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,13 +35,15 @@ const Autocomplete = memo(({ suggestions, classes, placeholder, label, itemToStr
|
|||
}) => (
|
||||
<div className={classes.container}>
|
||||
{renderInput({
|
||||
id: name,
|
||||
fullWidth: true,
|
||||
classes,
|
||||
onBlur,
|
||||
error: touched[name] && errors[name],
|
||||
error: (touched[`${name}-input`] || touched[name]) && errors[name],
|
||||
success: (touched[`${name}-input`] || touched[name] || value) && !errors[name],
|
||||
InputProps: getInputProps({
|
||||
value: inputValue2 || '',
|
||||
placeholder,
|
||||
onBlur,
|
||||
onClick: () => toggleMenu(),
|
||||
onChange: it => {
|
||||
if (it.target.value === '') {
|
||||
|
|
|
|||
|
|
@ -60,10 +60,11 @@ const AutocompleteMultiple = memo(
|
|||
}) => (
|
||||
<div className={classes.container}>
|
||||
{renderInput({
|
||||
id: name,
|
||||
fullWidth: true,
|
||||
classes,
|
||||
onBlur,
|
||||
error: touched[name] && errors[name],
|
||||
error: (touched[`${name}-input`] || touched[name]) && errors[name],
|
||||
success: (touched[`${name}-input`] || touched[name] || value) && !errors[name],
|
||||
InputProps: getInputProps({
|
||||
startAdornment: (value || []).map(item => (
|
||||
<Chip
|
||||
|
|
@ -72,6 +73,7 @@ const AutocompleteMultiple = memo(
|
|||
label={item.code}
|
||||
/>
|
||||
)),
|
||||
onBlur,
|
||||
onChange: it => setInputValue(it.target.value),
|
||||
onClick: () => toggleMenu(),
|
||||
onKeyDown: handleKeyDown,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import MenuItem from '@material-ui/core/MenuItem'
|
|||
import { fontColor, inputFontSize, inputFontWeight } from '../../../styling/variables'
|
||||
|
||||
function renderInput (inputProps) {
|
||||
const { InputProps, classes, ref, ...other } = inputProps
|
||||
const { onBlur, success, InputProps, classes, ref, ...other } = inputProps
|
||||
|
||||
return (
|
||||
<TextField
|
||||
|
|
@ -14,7 +14,8 @@ function renderInput (inputProps) {
|
|||
inputRef: ref,
|
||||
classes: {
|
||||
root: classes.inputRoot,
|
||||
input: classes.inputInput
|
||||
input: classes.inputInput,
|
||||
underline: success ? classes.success : ''
|
||||
},
|
||||
...InputProps
|
||||
}}
|
||||
|
|
@ -88,6 +89,11 @@ const styles = theme => ({
|
|||
inputInput: {
|
||||
flex: 1
|
||||
},
|
||||
success: {
|
||||
'&:after': {
|
||||
transform: 'scaleX(1)'
|
||||
}
|
||||
},
|
||||
divider: {
|
||||
height: theme.spacing(2)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,22 +25,25 @@ function H4 ({ children, className, ...props }) {
|
|||
return <h4 className={classnames(classes.h3, className)} {...props}>{children}</h4>
|
||||
}
|
||||
|
||||
const P = pBuilder()
|
||||
const P = pBuilder('p')
|
||||
const Info1 = pBuilder('info1')
|
||||
const Info2 = pBuilder('info2')
|
||||
const Info3 = pBuilder('info3')
|
||||
const Info4 = pBuilder('info4')
|
||||
const Mono = pBuilder('mono')
|
||||
const TL1 = pBuilder('tl1')
|
||||
const TL2 = pBuilder('tl2')
|
||||
const Label1 = pBuilder('label1')
|
||||
const Label2 = pBuilder('label2')
|
||||
const Label3 = pBuilder('label3')
|
||||
|
||||
function pBuilder (elementClass) {
|
||||
return ({ inline, className, children, ...props }) => {
|
||||
return ({ inline, noMargin, className, children, ...props }) => {
|
||||
const classes = useStyles()
|
||||
const classNames = {
|
||||
[classes[elementClass]]: elementClass,
|
||||
className: true,
|
||||
[classes.inline]: inline
|
||||
[classes.inline]: inline,
|
||||
[classes.noMarginP]: noMargin
|
||||
}
|
||||
return (
|
||||
<p className={classnames(classNames, className)} {...props}>
|
||||
|
|
@ -50,4 +53,4 @@ function pBuilder (elementClass) {
|
|||
}
|
||||
}
|
||||
|
||||
export { H1, H2, H3, H4, TL1, TL2, P, Info1, Info2, Info3, Info4, Mono }
|
||||
export { H1, H2, H3, H4, TL1, TL2, P, Info1, Info2, Info3, Mono, Label1, Label2, Label3 }
|
||||
|
|
|
|||
|
|
@ -70,6 +70,12 @@ export default {
|
|||
fontFamily: fontSecondary,
|
||||
fontWeight: 700
|
||||
},
|
||||
info3: {
|
||||
extend: base,
|
||||
fontSize: fontSize3,
|
||||
fontFamily: fontSecondary,
|
||||
fontWeight: 500
|
||||
},
|
||||
mono: {
|
||||
extend: base,
|
||||
fontSize: fontSize4,
|
||||
|
|
@ -95,7 +101,7 @@ export default {
|
|||
fontWeight: 500,
|
||||
lineHeight: '110%'
|
||||
},
|
||||
label: {
|
||||
label1: {
|
||||
fontSize: fontSize5,
|
||||
fontFamily: fontSecondary,
|
||||
fontWeight: 500
|
||||
|
|
@ -105,6 +111,12 @@ export default {
|
|||
fontFamily: fontSecondary,
|
||||
fontWeight: 700
|
||||
},
|
||||
label3: {
|
||||
fontSize: fontSize4,
|
||||
fontFamily: fontSecondary,
|
||||
fontWeight: 500,
|
||||
color: fontColor
|
||||
},
|
||||
select: {
|
||||
fontSize: fontSize3,
|
||||
fontFamily: fontSecondary,
|
||||
|
|
@ -112,5 +124,8 @@ export default {
|
|||
},
|
||||
inline: {
|
||||
display: 'inline'
|
||||
},
|
||||
noMarginP: {
|
||||
margin: 0
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import BigNumber from 'bignumber.js'
|
|||
import useAxios from '@use-hooks/axios'
|
||||
import { makeStyles } from '@material-ui/core/styles'
|
||||
|
||||
import { H3, Info1, Info3, Info4, Mono } from '../components/typography'
|
||||
import { H3, Info1, Info2, Info3, Mono, Label1, Label3, TL2 } from '../components/typography'
|
||||
import Title from '../components/Title'
|
||||
import Sidebar from '../components/Sidebar'
|
||||
import { primaryColor } from '../styling/variables'
|
||||
|
|
@ -58,6 +58,16 @@ const Funding = () => {
|
|||
}
|
||||
})
|
||||
|
||||
const itemRender = (it) => {
|
||||
return (
|
||||
<div className={classes.itemWrapper}>
|
||||
<div className={classes.firstItem}>{it.display}</div>
|
||||
<div className={classes.item}>{it.fiatConfirmedBalance} {it.fiatCode}</div>
|
||||
<div className={classes.item}>{it.confirmedBalance} {it.cryptoCode}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Title>Funding</Title>
|
||||
|
|
@ -67,14 +77,15 @@ const Funding = () => {
|
|||
isSelected={isSelected}
|
||||
onClick={setSelected}
|
||||
displayName={it => it.display}
|
||||
itemRender={itemRender}
|
||||
>
|
||||
{data && data.length && (
|
||||
<div className={classes.total}>
|
||||
<Info3 className={classes.totalTitle}>Total Crypto Balance</Info3>
|
||||
<Label1 className={classes.totalTitle}>Total Crypto Balance</Label1>
|
||||
<Info1 className={classes.noMargin}>
|
||||
{getConfirmedTotal(data)} {data[0].fiatCode}
|
||||
</Info1>
|
||||
<Info4>(+{getPendingTotal(data)} pending)</Info4>
|
||||
<Label1 className={classes.totalPending}>(+{getPendingTotal(data)} pending)</Label1>
|
||||
</div>
|
||||
)}
|
||||
</Sidebar>
|
||||
|
|
@ -83,21 +94,21 @@ const Funding = () => {
|
|||
<div className={classes.firstSide}>
|
||||
<H3>Balance ({selected.display})</H3>
|
||||
<div className={classes.coinTotal}>
|
||||
<span className='info1'>
|
||||
<Info1 inline noMargin>
|
||||
{`${selected.confirmedBalance} ${selected.cryptoCode}`}
|
||||
</span>
|
||||
<span className={classnames('tl2', classes.leftSpacer)}>
|
||||
{` (+ ${selected.pending} pending)`}
|
||||
</span>
|
||||
</Info1>
|
||||
<Info2 inline noMargin className={classes.leftSpacer}>
|
||||
{`(+ ${selected.pending} pending)`}
|
||||
</Info2>
|
||||
</div>
|
||||
|
||||
<div className={classes.coinTotal}>
|
||||
<span className={classnames('info3', classes.noMarginTop)}>
|
||||
<Info3 inline noMargin>
|
||||
{`= ${formatNumber(selected.fiatConfirmedBalance)} ${selected.fiatCode}`}
|
||||
</span>
|
||||
<span className={classnames('info4', classes.leftSpacer)}>
|
||||
</Info3>
|
||||
<Label3 inline noMargin className={classes.leftSpacer}>
|
||||
{`(+${formatNumber(selected.fiatPending)} pending)`}
|
||||
</span>
|
||||
</Label3>
|
||||
</div>
|
||||
|
||||
<H3 className={classes.topSpacer}>Address</H3>
|
||||
|
|
@ -109,7 +120,7 @@ const Funding = () => {
|
|||
</div>
|
||||
|
||||
<div className={classes.secondSide}>
|
||||
<Info3>Scan to send {selected.display}</Info3>
|
||||
<Label1>Scan to send {selected.display}</Label1>
|
||||
<QRCode size={240} fgColor={primaryColor} value={selected.fundingAddressUrl} />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,8 @@
|
|||
import { spacer, subheaderColor, placeholderColor } from '../styling/variables'
|
||||
import { spacer, subheaderColor, placeholderColor, fontColor } from '../styling/variables'
|
||||
|
||||
import typographyStyles from '../components/typography/styles'
|
||||
|
||||
const { label1 } = typographyStyles
|
||||
|
||||
export default {
|
||||
wrapper: {
|
||||
|
|
@ -38,12 +42,27 @@ export default {
|
|||
width: 375,
|
||||
margin: `${spacer * 1.5}px ${spacer * 3}px`
|
||||
},
|
||||
itemWrapper: {
|
||||
textAlign: 'end'
|
||||
},
|
||||
item: {
|
||||
extend: label1,
|
||||
margin: 2
|
||||
},
|
||||
firstItem: {
|
||||
margin: 2
|
||||
},
|
||||
total: {
|
||||
marginTop: 'auto',
|
||||
textAlign: 'right',
|
||||
marginRight: 20
|
||||
marginRight: 24
|
||||
},
|
||||
totalPending: {
|
||||
color: fontColor,
|
||||
marginTop: 2
|
||||
},
|
||||
totalTitle: {
|
||||
color: placeholderColor
|
||||
color: placeholderColor,
|
||||
marginBottom: 2
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import React, { memo, useState } from 'react'
|
||||
import { withFormik } from 'formik'
|
||||
import * as Yup from 'yup'
|
||||
import useAxios from '@use-hooks/axios'
|
||||
|
||||
|
|
@ -24,7 +23,6 @@ const initialValues = {
|
|||
|
||||
const Locales = memo(() => {
|
||||
const [locale, setLocale] = useState(initialValues)
|
||||
const [editing, setEditing] = useState(false)
|
||||
const [data, setData] = useState(null)
|
||||
|
||||
useAxios({
|
||||
|
|
@ -48,21 +46,16 @@ const Locales = memo(() => {
|
|||
}
|
||||
})
|
||||
|
||||
const MainFormFormik = withFormik({
|
||||
mapPropsToValues: () => locale,
|
||||
validationSchema: LocaleSchema,
|
||||
handleSubmit: it => {
|
||||
setEditing(false)
|
||||
const save = (it) => {
|
||||
setLocale(it)
|
||||
reFetch()
|
||||
}
|
||||
})(MainForm)
|
||||
|
||||
return (
|
||||
<>
|
||||
<Title>Locales</Title>
|
||||
<Subtitle>Default settings</Subtitle>
|
||||
<MainFormFormik editing={editing} setEditing={setEditing} data={data} />
|
||||
<MainForm validationSchema={LocaleSchema} value={locale} save={save} auxData={data} />
|
||||
<Subtitle extraMarginTop>Overrides</Subtitle>
|
||||
</>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,143 +1,32 @@
|
|||
import React, { useState, memo } from 'react'
|
||||
import { Form, FastField } from 'formik'
|
||||
import { __, compose, join, map, get, isEmpty } from 'lodash/fp'
|
||||
import React, { memo } from 'react'
|
||||
import { __, compose, join, map, get } from 'lodash/fp'
|
||||
|
||||
import { Link } from '../../components/buttons'
|
||||
import { Autocomplete, AutocompleteMultiple } from '../../components/inputs'
|
||||
|
||||
import { Checkbox } from '../../components/inputs/formik'
|
||||
|
||||
import {
|
||||
EditCell,
|
||||
Table,
|
||||
TableHead,
|
||||
TableRow,
|
||||
TableHeader,
|
||||
TableBody,
|
||||
TableCell as Td
|
||||
} from '../../components/table'
|
||||
|
||||
// import styles from './MainForm.module.scss'
|
||||
import { Table as EditableTable } from '../../components/editableTable'
|
||||
|
||||
const styles = {}
|
||||
|
||||
const sizes = {
|
||||
country: 200,
|
||||
fiatCurrency: 150,
|
||||
languages: 240,
|
||||
cryptoCurrencies: 280,
|
||||
cryptoCurrencies: 270,
|
||||
showRates: 125,
|
||||
action: 175
|
||||
}
|
||||
|
||||
const MainForm = memo(
|
||||
({ values, resetForm, submitForm, errors, editing, setEditing, data }) => {
|
||||
const [submitted, setSubmitted] = useState(false)
|
||||
|
||||
const getData = get(__, data)
|
||||
({ value, save, auxData, validationSchema }) => {
|
||||
const getData = get(__, auxData)
|
||||
const displayCodeArray = compose(join(', '), map(get('code')))
|
||||
|
||||
const save = () => {
|
||||
setSubmitted(true)
|
||||
submitForm()
|
||||
}
|
||||
|
||||
const cancel = () => {
|
||||
resetForm()
|
||||
setSubmitted(false)
|
||||
setEditing(false)
|
||||
}
|
||||
|
||||
const ViewFields = (
|
||||
<>
|
||||
<Td>{values.country && values.country.display}</Td>
|
||||
<Td>{values.fiatCurrency && values.fiatCurrency.code}</Td>
|
||||
<Td>
|
||||
{values.languages && values.languages.map(it => it.code).join(', ')}
|
||||
</Td>
|
||||
<Td>
|
||||
{values.cryptoCurrencies &&
|
||||
values.cryptoCurrencies.map(it => it.code).join(', ')}
|
||||
</Td>
|
||||
<Td>{values.showRates ? 'true' : 'false'}</Td>
|
||||
<Td rightAlign>
|
||||
<Link color='primary' onClick={() => setEditing(true)}>
|
||||
Edit
|
||||
</Link>
|
||||
</Td>
|
||||
</>
|
||||
)
|
||||
|
||||
const EditFields = (
|
||||
<>
|
||||
<Td>
|
||||
<FastField
|
||||
name='country'
|
||||
component={Autocomplete}
|
||||
suggestions={data && data.countries}
|
||||
/>
|
||||
</Td>
|
||||
<Td>
|
||||
<FastField
|
||||
name='fiatCurrency'
|
||||
component={Autocomplete}
|
||||
suggestions={data && data.currencies}
|
||||
/>
|
||||
</Td>
|
||||
<Td>
|
||||
<FastField
|
||||
name='languages'
|
||||
component={AutocompleteMultiple}
|
||||
suggestions={data && data.languages}
|
||||
/>
|
||||
</Td>
|
||||
<Td>
|
||||
<FastField
|
||||
name='cryptoCurrencies'
|
||||
component={AutocompleteMultiple}
|
||||
suggestions={data && data.cryptoCurrencies}
|
||||
/>
|
||||
</Td>
|
||||
<Td>
|
||||
<FastField name='showRates' component={Checkbox} />
|
||||
</Td>
|
||||
<EditCell save={save} cancel={cancel} />
|
||||
</>
|
||||
)
|
||||
|
||||
return (
|
||||
<Form>
|
||||
<Table>
|
||||
<colgroup>
|
||||
<col className={styles.bigColumn} />
|
||||
<col className={styles.mediumColumn} />
|
||||
<col className={styles.mediumColumn} />
|
||||
<col className={styles.bigColumn} />
|
||||
<col className={styles.showRates} />
|
||||
<col className={styles.actionColumn} />
|
||||
</colgroup>
|
||||
<TableHead>
|
||||
<TableRow header>
|
||||
<TableHeader>Country</TableHeader>
|
||||
<TableHeader>Fiat Currency</TableHeader>
|
||||
<TableHeader>Languages</TableHeader>
|
||||
<TableHeader>Crypto Currencies</TableHeader>
|
||||
<TableHeader>Show Rates</TableHeader>
|
||||
<TableHeader />
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
<TableRow error={submitted && !isEmpty(errors)}>
|
||||
{editing ? EditFields : ViewFields}
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
|
||||
<EditableTable
|
||||
cancel={cancel}
|
||||
save={save}
|
||||
data={[values]}
|
||||
validationSchema={validationSchema}
|
||||
data={[value]}
|
||||
elements={[
|
||||
{
|
||||
name: 'country',
|
||||
|
|
@ -156,26 +45,26 @@ const MainForm = memo(
|
|||
{
|
||||
name: 'languages',
|
||||
size: sizes.languages,
|
||||
input: AutocompleteMultiple,
|
||||
view: displayCodeArray,
|
||||
input: AutocompleteMultiple,
|
||||
inputProps: { suggestions: getData('languages') }
|
||||
},
|
||||
{
|
||||
name: 'cryptoCurrencies',
|
||||
size: sizes.languages,
|
||||
input: AutocompleteMultiple,
|
||||
size: sizes.cryptoCurrencies,
|
||||
view: displayCodeArray,
|
||||
input: AutocompleteMultiple,
|
||||
inputProps: { suggestions: getData('cryptoCurrencies') }
|
||||
},
|
||||
{
|
||||
name: 'showRates',
|
||||
size: sizes.showRates,
|
||||
input: Checkbox,
|
||||
view: it => it ? 'true' : 'false'
|
||||
textAlign: 'center',
|
||||
view: it => it ? 'true' : 'false',
|
||||
input: Checkbox
|
||||
}
|
||||
]}
|
||||
/>
|
||||
</Form>
|
||||
)
|
||||
}
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
const version = 8
|
||||
const version = 9
|
||||
|
||||
// Primary
|
||||
const zodiac = '#1b2559'
|
||||
|
|
@ -8,8 +8,8 @@ const spring = '#48f694'
|
|||
const comet = '#5f668a'
|
||||
const comet2 = '#72799d'
|
||||
const spring2 = '#44e188'
|
||||
const spring4 = '#3fd07e'
|
||||
const spring3 = '#ecfbef'
|
||||
const spring4 = '#3fd07e'
|
||||
const zircon = '#ebefff'
|
||||
const zircon2 = '#dbdfed'
|
||||
|
||||
|
|
@ -75,7 +75,7 @@ if (version === 8) {
|
|||
fontSize5 = 14
|
||||
}
|
||||
|
||||
const smallestFontSize = fontSize5 - 1
|
||||
const smallestFontSize = fontSize5
|
||||
const inputFontSize = fontSize4
|
||||
const inputFontSizeLg = fontSize1
|
||||
const inputFontWeight = 500
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue