diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..b23d587 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,15 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "pwa-chrome", + "request": "launch", + "name": "Launch Chrome against localhost", + "url": "http://localhost:8080", + "webRoot": "${workspaceFolder}" + } + ] +} \ No newline at end of file diff --git a/web/package-lock.json b/web/package-lock.json index 8f08d96..2a4096b 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -3658,6 +3658,20 @@ "@types/node": "*" } }, + "@types/history": { + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.8.tgz", + "integrity": "sha512-S78QIYirQcUoo6UJZx9CSP0O2ix9IaeAXwQi26Rhr/+mg7qqPy8TzaxHSUut7eGjL8WmLccT7/MXf304WjqHcA==" + }, + "@types/hoist-non-react-statics": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz", + "integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==", + "requires": { + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0" + } + }, "@types/html-minifier-terser": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz", @@ -3684,6 +3698,16 @@ "@types/istanbul-lib-report": "*" } }, + "@types/javascript-time-ago": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@types/javascript-time-ago/-/javascript-time-ago-2.0.2.tgz", + "integrity": "sha512-uBUXwIG8YzPuWw5c6yV5RGvskkNOxnR+9hctOv8cptyMlB0IgfzeqFo0jkK+Ich8zGchvWghOT3Ryqr3bZmH3A==" + }, + "@types/json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-WW+0cfH3ovFN6ROV+p/Xfw36dT6s16hbXBYIG49PYw6+j6e+AkpqYccctgxwyicBmC8CZDBnPhOH94shFhXgHQ==" + }, "@types/json-schema": { "version": "7.0.7", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz", @@ -3751,6 +3775,25 @@ } } }, + "@types/react-router": { + "version": "5.1.14", + "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.14.tgz", + "integrity": "sha512-LAJpqYUaCTMT2anZheoidiIymt8MuX286zoVFPM3DVb23aQBH0mAkFvzpd4LKqiolV8bBtZWT5Qp7hClCNDENw==", + "requires": { + "@types/history": "*", + "@types/react": "*" + } + }, + "@types/react-router-dom": { + "version": "5.1.7", + "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.1.7.tgz", + "integrity": "sha512-D5mHD6TbdV/DNHYsnwBTv+y73ei+mMjrkGrla86HthE4/PVvL1J94Bu3qABU+COXzpL23T1EZapVVpwHuBXiUg==", + "requires": { + "@types/history": "*", + "@types/react": "*", + "@types/react-router": "*" + } + }, "@types/react-transition-group": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.1.tgz", @@ -3787,6 +3830,23 @@ "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.0.tgz", "integrity": "sha512-RJJrrySY7A8havqpGObOB4W92QXKJo63/jFLLgpvOtsGUqbQZ9Sbgl35KMm1DjC6j7AvmmU2bIno+3IyEaemaw==" }, + "@types/styled-components": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/@types/styled-components/-/styled-components-5.1.9.tgz", + "integrity": "sha512-kbEG6YlwK8rucITpKEr6pA4Ho9KSQHUUOzZ9lY3va1mtcjvS3D0wDciFyHEiNHKLL/npZCKDQJqm0x44sPO9oA==", + "requires": { + "@types/hoist-non-react-statics": "*", + "@types/react": "*", + "csstype": "^3.0.2" + }, + "dependencies": { + "csstype": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.8.tgz", + "integrity": "sha512-jXKhWqXPmlUeoQnF/EhTtTl4C9SnrxSH/jZUih3jmO6lBKr99rP3/+FmrMj4EFpOXzMtXHAZkd3x0E6h6Fgflw==" + } + } + }, "@types/tapable": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.7.tgz", @@ -5113,6 +5173,11 @@ "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==" }, + "bignumber.js": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.1.tgz", + "integrity": "sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA==" + }, "binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -10303,6 +10368,14 @@ "istanbul-lib-report": "^3.0.0" } }, + "javascript-time-ago": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/javascript-time-ago/-/javascript-time-ago-2.3.6.tgz", + "integrity": "sha512-OZLtmx+o+LyfLLi7oKsz7taNCx2uguf1qsdN3KCYDe89L7D1OT1BcR/E0HgK5EYqvXxpPEl0oiuypFC7ugyeJA==", + "requires": { + "relative-time-format": "^1.0.5" + } + }, "jerrypick": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/jerrypick/-/jerrypick-1.0.3.tgz", @@ -11826,6 +11899,14 @@ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" }, + "json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "requires": { + "bignumber.js": "^9.0.0" + } + }, "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", @@ -15553,6 +15634,11 @@ "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=" }, + "relative-time-format": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/relative-time-format/-/relative-time-format-1.0.5.tgz", + "integrity": "sha512-MAgx/YKcUQYJpIaWcfetPstElnWf26JxVis4PirdwVrrymFdbxyCSm6yENpfB1YuwFbtHSHksN3aBajVNxk10Q==" + }, "remove-array-items": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/remove-array-items/-/remove-array-items-1.1.1.tgz", @@ -17810,6 +17896,11 @@ "is-typedarray": "^1.0.0" } }, + "typescript": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.4.tgz", + "integrity": "sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg==" + }, "unbox-primitive": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", @@ -18640,7 +18731,8 @@ }, "ssri": { "version": "6.0.1", - "resolved": "", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", "requires": { "figgy-pudding": "^3.5.1" } diff --git a/web/package.json b/web/package.json index 84f417b..2d76081 100644 --- a/web/package.json +++ b/web/package.json @@ -7,11 +7,17 @@ "@material-ui/core": "^4.11.3", "@material-ui/icons": "^4.11.2", "@types/d3": "^5.16.4", + "@types/javascript-time-ago": "^2.0.2", + "@types/json-bigint": "^1.0.0", "@types/pixi.js": "^4.8.9", + "@types/react-router-dom": "^5.1.7", + "@types/styled-components": "^5.1.9", "@types/throttle-debounce": "^1.1.1", "axios": "^0.21.1", "d3": "^5.16.0", "fg-loadcss": "^2.1.0", + "javascript-time-ago": "^2.3.6", + "json-bigint": "^1.0.0", "konva": "^7.2.5", "pixi-filters": "^2.7.1", "pixi.js": "^4.8.9", @@ -29,7 +35,8 @@ "react-twitter-embed": "^3.0.3", "recharts": "^2.0.9", "styled-components": "^5.2.3", - "throttle-debounce": "^3.0.1" + "throttle-debounce": "^3.0.1", + "typescript": "^4.2.4" }, "scripts": { "start": "react-scripts start", diff --git a/web/src/App.js b/web/src/App.js index 8825aab..c7e8a99 100644 --- a/web/src/App.js +++ b/web/src/App.js @@ -19,6 +19,8 @@ import { duration, easing } from '@material-ui/core/styles/transitions'; import { GlobalStyle, themeLight, themeDark } from './theme/globalStyle'; import HomePage from './Components/HomePage/HomePage'; import DataCentersPage from './Components/DataCentersPage/DataCentersPage'; +import TransactionPage from './Components/TransactionPage/TransactionPage'; +import TransactionsPage from './Components/TransactionsPage/TransactionsPage'; import AboutPage from './Components/AboutPage/AboutPage'; import DEAppBar from './Components/DEAppBar/DEAppBar'; import Footer from './Components/Footer/Footer'; @@ -215,6 +217,15 @@ class App extends Component { /> } /> + + + } + /> @@ -226,6 +237,15 @@ class App extends Component { /> } /> + + + } + /> props.theme.colorAppBarDfinityText}; + ${({ breakpoint }) => + breakpoint === Breakpoints.XS && ` + margin-left: 8.4px; + letter-spacing: 3px; + ` + } + } +`; + +const TypographyExplorer = styled(TypographyAppName)` + && { + margin-left: 10px; + letter-spacing: 3px; + color: ${props => props.theme.colorAppBarExplorerText}; + ${({ breakpoint }) => + breakpoint === Breakpoints.XS && ` + margin-left: 9.8px; + letter-spacing: 3px; + ` + } + } +`; + +// INTERNET COMPUTER | EXPLORER +const TypographyDfinity = styled(TypographyAppName)` + && { + margin-left: 12px; + margin-right: 8px; + //letter-spacing: 1px; + color: ${props => props.theme.colorAppBarDfinityText}; + ${({ breakpoint }) => + breakpoint === Breakpoints.XS && ` + margin-left: 8.4px; + letter-spacing: 8.4px; + ` + } + } +`; + +const TypographyExplorer = styled(TypographyAppName)` + && { + margin-left: 10px; + //letter-spacing: 1px; + color: ${props => props.theme.colorAppBarExplorerText}; + ${({ breakpoint }) => + breakpoint === Breakpoints.XS && ` + margin-left: 9.8px; + letter-spacing: 5.25px; + ` + } + } +`; + +*/ + const StyledIconButton = styled(IconButton)` && { color: ${props => props.theme.colorAppBarTextButton}; @@ -521,7 +584,15 @@ class DEAppBar extends ResponsiveComponent { - + + + + + + + + + diff --git a/web/src/Components/Footer/Footer.js b/web/src/Components/Footer/Footer.js index a6656ab..bfd9969 100644 --- a/web/src/Components/Footer/Footer.js +++ b/web/src/Components/Footer/Footer.js @@ -260,11 +260,11 @@ class Footer extends ResponsiveComponent { const breakpoint = getBreakpoint(); switch (breakpoint) { case Breakpoints.XS: - return '© 2021 dfinityexplorer'; + return '© 2021 IC Explorer'; case Breakpoints.SM: - return '© 2021 dfinityexplorer contributors'; + return '© 2021 Internet Computer Explorer'; default: - return '© 2021 dfinityexplorer contributors | All rights reserved'; + return '© 2021 Internet Computer Explorer | All rights reserved'; } } diff --git a/web/src/Components/PagedTable/PagedTable.tsx b/web/src/Components/PagedTable/PagedTable.tsx new file mode 100644 index 0000000..3c69a13 --- /dev/null +++ b/web/src/Components/PagedTable/PagedTable.tsx @@ -0,0 +1,378 @@ +/** + * @file PagedTable + * @copyright Copyright (c) 2018-2021 Dylan Miller and dfinityexplorer contributors + * @license MIT License + */ + +import { Link } from 'react-router-dom'; +import styled from 'styled-components'; +import { + CircularProgress, + Fade, + Grid, + Paper, + Table, + TableBody, + TableCell, + TableContainer, + TableFooter, + TableHead, + TableRow, + Typography +} from '@material-ui/core'; +import { duration, easing } from '@material-ui/core/styles/transitions'; +import zIndex from '@material-ui/core/styles/zIndex'; +import TablePager from '../TablePager/TablePager'; +import { Breakpoints } from '../../utils/breakpoint'; +import Constants from '../../constants'; + +const StyledPaper = styled(Paper)` + && { + background: ${props => props.theme.colorTableBackgroundPrimary}; + } +`; + +const TypographyTitle = styled(Typography)` + && { + color: ${props => props.theme.colorBodyText}; + padding-top: 8px; + padding-bottom: 4px; + padding-left: 15px; + text-align: left; + font-family: ${Constants.FONT_PRIMARY}; + font-size: ${Constants.MATERIAL_FONT_SIZE_H6}; + font-weight: 300; + } +`; + +const DivCircularProgress = styled.div<{ breakpoint: number }>` + && { + position: absolute; + /* Set to modal z-index so that progress indicator is above table. */ + z-index: ${zIndex.modal}; + /* Add padding under the progress indicator for XS to compensate for the larger footer. */ + ${({ breakpoint }) => + breakpoint === Breakpoints.XS && ` + padding-bottom: 30px; + ` + } + } +`; + +const StyledCircularProgress = styled(CircularProgress)` + && { + color: ${props => props.theme.colorBodyButtonBackground}; + } +`; + +const StyledTable = styled(Table)<{ breakpoint: number, loading: number }>` + && { + /* Same easing as Material-UI . */ + transition: ${'opacity ' + duration.standard + 'ms ' + easing.easeInOut}; + opacity: ${props => props.loading ? 0.5 : 1.0}; + font-family: ${Constants.FONT_PRIMARY}; + ${({ breakpoint }) => + ((breakpoint !== Breakpoints.XS) && ` + min-width: 800px; + `) + } + } +`; + +const StyledTableRow = styled(TableRow)<{ breakpoint: number }>` + && { + height: ${Constants.TABLE_ROW_HEIGHT_SM_AND_UP + 'px'}; + ${({ breakpoint }) => + breakpoint === Breakpoints.XS && ` + height: ${Constants.TABLE_ROW_HEIGHT_XS + 'px'}; + ` + } + } +`; + +const TableRowFooter = styled(StyledTableRow)` + && { + border-top-color: ${props => props.theme.colorTableRowBorder}; + border-top-style: solid; + border-top-width: 2px; + } +`; + +const StyledTableCell = styled(TableCell)<{ breakpoint: number }>` + && { + border-color: ${props => props.theme.colorTableRowBorder}; + color: ${props => props.theme.colorBodyText}; + font-family: ${Constants.FONT_PRIMARY}; + font-size: ${Constants.MATERIAL_FONT_SIZE_BODY_2}; + white-space: nowrap; + ${({ breakpoint }) => + breakpoint === Breakpoints.XS && ` + font-size: ${Constants.FONT_SIZE_TABLE_XS}; + ` + } + } +`; + +const TableCellHeader = styled(StyledTableCell)` + && { + border-bottom-style: solid; + border-bottom-width: 2px; + color: ${props => props.theme.colorBodyTextDim}; + font-weight: 500; + } +`; + +const StyledLink = styled(Link)` + && { + color: ${props => props.theme.colorBodyTextLink}; + text-decoration: none; + &:hover { + text-decoration: underline; + } + } +`; + +/** + * Describes the cells of a PagedTable row. + */ +export interface PagedTableCell +{ + /** + * The value of the cell. + */ + value: string; + /** + * True if the cell contains a numeric value, false otherwise. + */ + isNumeric: boolean; + /** + * Optional string which provides a link for the cell (to= prop of Link). + */ + link?: string; +} + +/** + * Describes a body row of a PagedTable. + */ +export interface PagedTableBodyRow { + /** + * A unique key that identifies the row. + */ + mapKey: string; + /** + * An array of PagedTableCell objects that describe the cells of the row. + */ + cells: Array; +} + +interface PagedTableProps { + /** + * The current Breakpoint, taking the desktop drawer (large screens) width into account. + */ + breakpoint: number; + /** + * An array that specifies the column widths of the table. + */ + columnWidths: Array; + /** + * The total number of rows. + */ + count: number; + /** + * Return an array of PagedTableBodyRow objects that describe the body rows. + * @return {Array} An array of PagedTableBodyRow that describe the body rows. + */ + getBodyRows: () => Array; + /** + * An array of PagedTableCell objects that describe the cells of the header row. + */ + headerRow: Array; + /** + * Indicates whether the table is currently loading data. + */ + isLoading: boolean; + /** + * Callback fired when the page is changed. + * @param {number} pageIndex The index of the new page. + */ + onChangePage: (pageIndex: number) => void; + /** + * Callback fired when the number of rows per page is changed. + * @param {number} pageSize The number of rows per page. + */ + onChangePageSize: (pageSize: number) => void; + /** + * The current page index. + */ + pageIndex: number|null; + /** + * The page size of the table. + */ + pageSize: number; + /** + * The title of the table. + */ + title: string; +} + +/** + * This component displays a table that supports pagination. + */ +const PagedTable = ( + { + breakpoint, + columnWidths, + count, + getBodyRows, + headerRow, + isLoading, + onChangePage, + onChangePageSize, + pageIndex, + pageSize, + title + }: PagedTableProps) => { + + /** + * Return the elements for the table. + * @return {JSX.Element} The elements for the table. + * @private + */ + const getTableElements = (): JSX.Element => { + return ( + + + + + + + + + + {columnWidths.map((width, index) => { + // The column width settings seem to be ignored in many cases, depending on cell + // length. That is, when cell lengths are long, the widths are ignored. + return ( + + ); + })} + + + {getHeaderRowElement()} + + + {getBodyRowElements()} + + + {getFooterRowElement()} + + + + + ); + } + + /** + * Return the element for the header row. + * @return {JSX.Element} The element for the header row. + */ + const getHeaderRowElement = (): JSX.Element => { + return ( + + {headerRow.map((cell, index) => { + return ( + // Using index as the key is fine here and for cells in other rows, since we never add, + // remove, reorder, or filter items in the cell arrays. + + {cell.link ? + {cell.value} : + cell.value + } + + ); + })} + + ); + } + + /** + * Return the elements for all of the body rows. + * @return {Array} The elements for all of the body rows. + */ + const getBodyRowElements = (): Array => { + const rows: Array = getBodyRows(); + return rows.map((bodyRow: PagedTableBodyRow) => { + return getBodyRowElement(bodyRow); + }); + } + + /** + * Return the element for the specified body row. + * @param {PagedTableBodyRow} bodyRow Object that describes the body row. + * @return {JSX.Element} The element for the specified body row. + */ + const getBodyRowElement = (bodyRow: PagedTableBodyRow): JSX.Element => { + return ( + + {bodyRow.cells.map((cell, index) => { + return ( + + {cell.link ? + {cell.value} : + cell.value + } + + ); + })} + + ); + } + + /** + * Return the element for the footer row. + * @return {JSX.Element} The element for the footer row. + */ + const getFooterRowElement = (): JSX.Element => { + const show = count > 0; + return ( + + + + + + ); + } + + return ( + + {title} + {getTableElements()} + + ); +} + +export default PagedTable; diff --git a/web/src/Components/TablePager/TablePager.js b/web/src/Components/TablePager/TablePager.js new file mode 100644 index 0000000..0058ab3 --- /dev/null +++ b/web/src/Components/TablePager/TablePager.js @@ -0,0 +1,480 @@ +/** + * @file TablePager + * @copyright Copyright (c) 2018-2021 Dylan Miller and dfinityexplorer contributors + * @license MIT License + */ + +import React, { Component, Fragment } from 'react'; +import PropTypes from 'prop-types'; +import styled, { withTheme } from 'styled-components'; +import { + Grid, + IconButton, + InputBase, + MenuItem, + Select, + TableCell, + Toolbar, + Typography +} from '@material-ui/core'; +import { fade } from '@material-ui/core/styles/colorManipulator'; +import FirstPageIcon from '@material-ui/icons/FirstPage'; +import KeyboardArrowLeft from '@material-ui/icons/KeyboardArrowLeft'; +import KeyboardArrowRight from '@material-ui/icons/KeyboardArrowRight'; +import LastPageIcon from '@material-ui/icons/LastPage'; +import { Breakpoints } from '../../utils/breakpoint'; +import Constants from '../../constants'; + +const StyledTableCell = styled(TableCell)` + && { + &:last-child { + border-bottom: 0; + padding: 0px; + } + } +`; + +const StyledToolbar = styled(Toolbar)` + && { + color: ${props => props.theme.colorBodyTextDim}; + min-height: auto; + padding-left: 2px; + padding-right: 2px; + } +`; + +const TypographyCaption = styled(Typography)` + && { + font-family: ${Constants.FONT_PRIMARY}; + font-size: ${Constants.MATERIAL_FONT_SIZE_CAPTION}; + /* Padding to align rows text and count text with rows per page number for non-XS breakpoints. */ + padding-bottom: 1px; + ${({ breakpoint }) => + breakpoint === Breakpoints.XS && ` + padding-bottom: 0px; + ` + } + } +`; + +const TypographyRows = styled(TypographyCaption)` + && { + margin-top: -1px; + margin-left: 6px; + margin-right: 14px; + ${({ breakpoint }) => + (breakpoint === Breakpoints.SM || breakpoint === Breakpoints.XS) && ` + margin-right: 7px; + ` + } + } +`; + +const TypographyCount = styled(TypographyCaption)` + && { + margin-left: 41px; + margin-right: 2px; + ${({ breakpoint }) => + (breakpoint === Breakpoints.SM && ` + margin-left: 20px; + `) || + (breakpoint === Breakpoints.XS && ` + margin-left: 20px; + margin-right: 6px; + `) + } + } +`; + +const StyledSelect = styled(({ ...other }) => ( +