Merge pull request #1837 from RafaelTaranto/chore/update-mui-v6

LAM-1414 chore: update mui to v7
This commit is contained in:
Rafael Taranto 2025-05-12 09:46:25 +01:00 committed by GitHub
commit 8b3f93d8f0
357 changed files with 7823 additions and 14059 deletions

View file

@ -1,4 +0,0 @@
SKIP_PREFLIGHT_CHECK=true
HTTPS=true
REACT_APP_TYPE_CHECK_SANCTUARY=false
PORT=3001

View file

@ -1,28 +0,0 @@
server {
listen 80;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri /index.html;
}
location /graphql {
proxy_pass https://lamassu-admin-server/graphql;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 300;
proxy_connect_timeout 300;
proxy_send_timeout 300;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}

File diff suppressed because it is too large Load diff

View file

@ -5,12 +5,9 @@
"type": "module",
"dependencies": {
"@apollo/client": "^3.13.7",
"@emotion/react": "^11.14.0",
"@emotion/styled": "^11.14.0",
"@lamassu/coins": "v1.6.1",
"@mui/icons-material": "^5.17.1",
"@mui/material": "^5.17.1",
"@mui/styles": "^5.17.1",
"@mui/icons-material": "^7.1.0",
"@mui/material": "^7.1.0",
"@simplewebauthn/browser": "^3.0.0",
"apollo-upload-client": "^18.0.0",
"bignumber.js": "9.0.0",
@ -33,7 +30,6 @@
"react-copy-to-clipboard": "^5.0.2",
"react-dom": "17.0.2",
"react-dropzone": "^11.4.2",
"react-material-ui-carousel": "^3.4.2",
"react-number-format": "^4.4.1",
"react-otp-input": "3.1.1",
"react-router-dom": "5.1.2",
@ -44,6 +40,7 @@
},
"devDependencies": {
"@eslint/js": "^9.16.0",
"@tailwindcss/vite": "^4.1.4",
"@vitejs/plugin-react-swc": "^3.7.2",
"esbuild-plugin-react-virtualized": "^1.0.4",
"eslint": "^9.16.0",
@ -53,6 +50,7 @@
"globals": "^15.13.0",
"lint-staged": "^15.2.10",
"prettier": "3.4.1",
"tailwindcss": "^4.1.4",
"vite": "^6.0.1",
"vite-plugin-svgr": "^4.3.0"
},

View file

@ -1,12 +0,0 @@
diff --git a/node_modules/react-scripts/config/webpack.config.js b/node_modules/react-scripts/config/webpack.config.js
index 80c6ac2..3420936 100644
--- a/node_modules/react-scripts/config/webpack.config.js
+++ b/node_modules/react-scripts/config/webpack.config.js
@@ -752,6 +752,7 @@ module.exports = function (webpackEnv) {
formatter: require.resolve('react-dev-utils/eslintFormatter'),
eslintPath: require.resolve('eslint'),
context: paths.appSrc,
+ cache: true,
// ESLint class options
cwd: paths.appPath,
resolvePluginsRelativeTo: __dirname,

View file

@ -1,137 +1,14 @@
import { useQuery, gql } from "@apollo/client";
import CssBaseline from '@mui/material/CssBaseline'
import Grid from '@mui/material/Grid'
import Slide from '@mui/material/Slide'
import { StylesProvider, jssPreset, makeStyles } from '@mui/styles';
import { ThemeProvider, StyledEngineProvider } from '@mui/material/styles';
import { create } from 'jss'
import extendJss from 'jss-plugin-extend'
import React, { useContext, useState } from 'react'
import {
useLocation,
useHistory,
BrowserRouter as Router
} from 'react-router-dom'
import Header from 'src/components/layout/Header'
import Sidebar from 'src/components/layout/Sidebar'
import TitleSection from 'src/components/layout/TitleSection'
import { tree, hasSidebar, Routes, getParent } from 'src/routing/routes'
import { ThemeProvider, StyledEngineProvider } from '@mui/material/styles'
import React, { useState } from 'react'
import { BrowserRouter as Router } from 'react-router-dom'
import ApolloProvider from 'src/utils/apollo'
import AppContext from 'src/AppContext'
import global from 'src/styling/global'
import theme from 'src/styling/theme'
import { backgroundColor, mainWidth } from 'src/styling/variables'
const jss = create({
plugins: [extendJss(), ...jssPreset().plugins]
})
const fill = '100%'
const flexDirection = 'column'
const useStyles = makeStyles({
...global,
root: {
backgroundColor,
width: fill,
minHeight: fill,
display: 'flex',
flexDirection
},
wrapper: {
width: mainWidth,
height: fill,
margin: '0 auto',
flex: 1,
display: 'flex',
flexDirection
},
grid: {
flex: 1,
height: '100%'
},
contentWithSidebar: {
flex: 1,
marginLeft: 48,
paddingTop: 15
},
contentWithoutSidebar: {
width: mainWidth
}
})
const GET_USER_DATA = gql`
query userData {
userData {
id
username
role
enabled
last_accessed
last_accessed_from
last_accessed_address
}
}
`
const Main = () => {
const classes = useStyles()
const location = useLocation()
const history = useHistory()
const { wizardTested, userData, setUserData } = useContext(AppContext)
const { loading } = useQuery(GET_USER_DATA, {
onCompleted: userResponse => {
if (!userData && userResponse?.userData)
setUserData(userResponse.userData)
}
})
const route = location.pathname
const sidebar = hasSidebar(route)
const parent = sidebar ? getParent(route) : {}
const is404 = location.pathname === '/404'
const isSelected = it => location.pathname === it.route
const onClick = it => history.push(it.route)
const contentClassName = sidebar
? classes.contentWithSidebar
: classes.contentWithoutSidebar
return (
<div className={classes.root}>
{!is404 && wizardTested && userData && (
<Header tree={tree} user={userData} />
)}
<main className={classes.wrapper}>
{sidebar && !is404 && wizardTested && (
<Slide direction="left" in={true} mountOnEnter unmountOnExit>
<div>
<TitleSection title={parent.title}></TitleSection>
</div>
</Slide>
)}
<Grid container className={classes.grid}>
{sidebar && !is404 && wizardTested && (
<Sidebar
data={parent.children}
isSelected={isSelected}
displayName={it => it.label}
onClick={onClick}
/>
)}
<div className={contentClassName}>{!loading && <Routes />}</div>
</Grid>
</main>
</div>
)
}
import Main from './Main'
import './styling/global/global.css'
const App = () => {
const [wizardTested, setWizardTested] = useState(false)
@ -148,18 +25,16 @@ const App = () => {
value={{ wizardTested, setWizardTested, userData, setUserData, setRole }}>
<Router>
<ApolloProvider>
<StylesProvider jss={jss}>
<StyledEngineProvider injectFirst>
<ThemeProvider theme={theme}>
<CssBaseline />
<Main />
</ThemeProvider>
</StyledEngineProvider>
</StylesProvider>
<StyledEngineProvider enableCssLayer>
<ThemeProvider theme={theme}>
<CssBaseline />
<Main />
</ThemeProvider>
</StyledEngineProvider>
</ApolloProvider>
</Router>
</AppContext.Provider>
);
)
}
export default App

View file

@ -0,0 +1,83 @@
import { useHistory, useLocation } from 'react-router-dom'
import React, { useContext } from 'react'
import { gql, useQuery } from '@apollo/client'
import Slide from '@mui/material/Slide'
import Grid from '@mui/material/Grid'
import Header from './components/layout/Header.jsx'
import Sidebar from './components/layout/Sidebar.jsx'
import TitleSection from './components/layout/TitleSection.jsx'
import { getParent, hasSidebar, Routes, tree } from './routing/routes.jsx'
import AppContext from './AppContext.js'
const GET_USER_DATA = gql`
query userData {
userData {
id
username
role
enabled
last_accessed
last_accessed_from
last_accessed_address
}
}
`
const Main = () => {
const location = useLocation()
const history = useHistory()
const { wizardTested, userData, setUserData } = useContext(AppContext)
const { loading } = useQuery(GET_USER_DATA, {
onCompleted: userResponse => {
if (!userData && userResponse?.userData)
setUserData(userResponse.userData)
}
})
const route = location.pathname
const sidebar = hasSidebar(route)
const parent = sidebar ? getParent(route) : {}
const is404 = location.pathname === '/404'
const isSelected = it => location.pathname === it.route
const onClick = it => history.push(it.route)
const contentClassName = sidebar ? 'flex-1 ml-12 pt-4' : 'w-[1200px]'
return (
<div className="flex flex-col w-full min-h-full">
{!is404 && wizardTested && userData && (
<Header tree={tree} user={userData} />
)}
<main className="flex flex-1 flex-col my-0 mx-auto h-full w-[1200px]">
{sidebar && !is404 && wizardTested && (
<Slide direction="left" in={true} mountOnEnter unmountOnExit>
<div>
<TitleSection title={parent.title}></TitleSection>
</div>
</Slide>
)}
<Grid sx={{ flex: 1, height: 1 }} container>
{sidebar && !is404 && wizardTested && (
<Sidebar
data={parent.children}
isSelected={isSelected}
displayName={it => it.label}
onClick={onClick}
/>
)}
<div className={contentClassName}>{!loading && <Routes />}</div>
</Grid>
</main>
</div>
)
}
export default Main

View file

@ -1,63 +1,48 @@
import { makeStyles } from '@mui/styles'
import React, { memo } from 'react'
import ReactCarousel from 'react-material-ui-carousel'
import React, { memo, useState } from 'react'
import styles from './Carousel.module.css'
import LeftArrow from 'src/styling/icons/arrow/carousel-left-arrow.svg?react'
import RightArrow from 'src/styling/icons/arrow/carousel-right-arrow.svg?react'
const useStyles = makeStyles({
imgWrapper: {
alignItems: 'center',
justifyContent: 'center',
display: 'flex'
},
imgInner: {
objectFit: 'contain',
objectPosition: 'center',
width: 500,
height: 400,
marginBottom: 40
}
})
export const Carousel = memo(({ photosData, slidePhoto }) => {
const classes = useStyles()
const [activeIndex, setActiveIndex] = useState(0)
const handlePrev = () => {
const newIndex = activeIndex === 0 ? photosData.length - 1 : activeIndex - 1
setActiveIndex(newIndex)
slidePhoto(newIndex)
}
const handleNext = () => {
const newIndex = activeIndex === photosData.length - 1 ? 0 : activeIndex + 1
setActiveIndex(newIndex)
slidePhoto(newIndex)
}
if (!photosData || photosData.length === 0) {
return null
}
return (
<>
<ReactCarousel
PrevIcon={<LeftArrow />}
NextIcon={<RightArrow />}
navButtonsProps={{
style: {
backgroundColor: 'transparent',
borderRadius: 0,
color: 'transparent',
opacity: 1
}
}}
navButtonsWrapperProps={{
style: {
marginLeft: -22,
marginRight: -22
}
}}
autoPlay={false}
indicators={false}
navButtonsAlwaysVisible={true}
next={activeIndex => slidePhoto(activeIndex)}
prev={activeIndex => slidePhoto(activeIndex)}>
{photosData.map((item, i) => (
<div key={i}>
<div className={classes.imgWrapper}>
<img
className={classes.imgInner}
src={`/${item?.photoDir}/${item?.path}`}
alt=""
/>
</div>
</div>
))}
</ReactCarousel>
</>
<div className={styles.carouselContainer}>
{photosData.length > 1 && (
<button onClick={handlePrev} className={styles.navButton}>
<LeftArrow />
</button>
)}
<div className={styles.imageContainer}>
<img
className={styles.image}
src={`/${photosData[activeIndex]?.photoDir}/${photosData[activeIndex]?.path}`}
alt=""
/>
</div>
{photosData.length > 1 && (
<button onClick={handleNext} className={styles.navButton}>
<RightArrow />
</button>
)}
</div>
)
})

View file

@ -0,0 +1,45 @@
.carouselContainer {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
height: 100%;
box-sizing: border-box;
}
.imageContainer {
display: flex;
align-items: center;
justify-content: center;
flex: 1;
height: 100%;
overflow: hidden;
max-width: 80%;
}
.image {
object-fit: contain;
object-position: center;
width: 100%;
height: 100%;
margin-bottom: 40px;
}
.navButton {
background-color: transparent;
border: none;
border-radius: 0;
color: transparent;
opacity: 1;
cursor: pointer;
padding: 8px;
min-width: 44px;
min-height: 44px;
display: flex;
align-items: center;
justify-content: center;
}
.navButton:hover {
background-color: rgba(0, 0, 0, 0.04);
}

View file

@ -1,34 +0,0 @@
import Chip from '@mui/material/Chip'
import { withStyles } from '@mui/styles'
import React, { memo } from 'react'
import {
fontColor,
inputFontWeight,
subheaderColor,
smallestFontSize,
inputFontFamily
} from 'src/styling/variables'
const styles = theme => ({
root: {
backgroundColor: subheaderColor,
borderRadius: 4,
margin: theme.spacing(0.5, 0.25),
height: 18
},
label: {
fontSize: smallestFontSize,
color: fontColor,
fontWeight: inputFontWeight,
fontFamily: inputFontFamily,
paddingRight: 4,
paddingLeft: 4
}
})
const LsChip = memo(({ classes, ...props }) => (
<Chip size="small" classes={classes} {...props} />
))
export default withStyles(styles)(LsChip)

View file

@ -1,10 +1,8 @@
import Grid from '@mui/material/Grid'
import { makeStyles } from '@mui/styles'
import classnames from 'classnames'
import PropTypes from 'prop-types'
import React from 'react'
import { white } from 'src/styling/variables'
import Paper from '@mui/material/Paper'
import classnames from 'classnames'
const cardState = Object.freeze({
DEFAULT: 'default',
@ -12,24 +10,11 @@ const cardState = Object.freeze({
EXPANDED: 'expanded'
})
const styles = {
card: {
wordWrap: 'break-word',
boxShadow: '0 0 4px 0 rgba(0, 0, 0, 0.08)',
borderRadius: 12,
padding: 24,
backgroundColor: white
}
}
const useStyles = makeStyles(styles)
const CollapsibleCard = ({ className, state, shrunkComponent, children }) => {
const classes = useStyles()
return (
<Grid item className={classnames(className, classes.card)}>
<Paper className={classnames('p-6', className)}>
{state === cardState.SHRUNK ? shrunkComponent : children}
</Grid>
</Paper>
)
}

View file

@ -1,51 +1,27 @@
import Dialog from '@mui/material/Dialog'
import DialogActions from '@mui/material/DialogActions'
import DialogContent from '@mui/material/DialogContent'
import IconButton from '@mui/material/IconButton'
import InputLabel from '@mui/material/InputLabel'
import { makeStyles } from '@mui/styles'
import React, { memo, useState } from 'react'
import { H4, P } from 'src/components/typography'
import CloseIcon from 'src/styling/icons/action/close/zodiac.svg?react'
import { Button, IconButton } from 'src/components/buttons'
import { Button } from 'src/components/buttons'
import { TextInput } from 'src/components/inputs'
import { spacer } from 'src/styling/variables'
import ErrorMessage from './ErrorMessage'
const useStyles = makeStyles({
dialogContent: {
width: 434,
padding: spacer * 2,
paddingRight: spacer * 3.5
},
dialogTitle: {
padding: spacer * 2,
paddingRight: spacer * 1.5,
display: 'flex',
'justify-content': 'space-between',
'& > h4': {
margin: 0
},
'& > button': {
padding: 0,
marginTop: -(spacer / 2)
}
},
dialogActions: {
padding: spacer * 4,
paddingTop: spacer * 2
}
})
import SvgIcon from '@mui/material/SvgIcon'
export const DialogTitle = ({ children, onClose }) => {
const classes = useStyles()
return (
<div className={classes.dialogTitle}>
<div className="p-4 pr-3 flex justify-between">
{children}
{onClose && (
<IconButton size={16} aria-label="close" onClick={onClose}>
<CloseIcon />
<IconButton aria-label="close" onClick={onClose} className="p-0 -mt-1">
<SvgIcon fontSize="small">
<CloseIcon />
</SvgIcon>
</IconButton>
)}
</div>
@ -67,7 +43,6 @@ export const ConfirmDialog = memo(
disabled = false,
...props
}) => {
const classes = useStyles()
const [value, setValue] = useState(initialValue)
const [error, setError] = useState(false)
const handleChange = event => setValue(event.target.value)
@ -84,7 +59,7 @@ export const ConfirmDialog = memo(
return (
<Dialog open={open} aria-labelledby="form-dialog-title" {...props}>
<DialogTitle id="customized-dialog-title" onClose={innerOnClose}>
<H4>{title}</H4>
<H4 noMargin>{title}</H4>
</DialogTitle>
{errorMessage && (
<DialogTitle>
@ -98,7 +73,7 @@ export const ConfirmDialog = memo(
</ErrorMessage>
</DialogTitle>
)}
<DialogContent className={classes.dialogContent}>
<DialogContent className="w-108 p-4 pr-7">
{message && <P>{message}</P>}
<InputLabel htmlFor="confirm-input">{confirmationMessage}</InputLabel>
<TextInput
@ -116,7 +91,7 @@ export const ConfirmDialog = memo(
onChange={handleChange}
/>
</DialogContent>
<DialogActions className={classes.dialogActions}>
<DialogActions className="p-8 pt-4">
<Button
color="green"
disabled={isOnErrorState}

View file

@ -1,24 +1,20 @@
import { makeStyles } from '@mui/styles'
import classnames from 'classnames'
import * as R from 'ramda'
import React, { useState, useEffect } from 'react'
import { CopyToClipboard as ReactCopyToClipboard } from 'react-copy-to-clipboard'
import Popover from 'src/components/Popper'
import Popover from 'src/components/Popper.jsx'
import CopyIcon from 'src/styling/icons/action/copy/copy.svg?react'
import { comet } from 'src/styling/variables'
import { comet } from 'src/styling/variables.js'
import { cpcStyles } from './Transactions.styles'
const useStyles = makeStyles(cpcStyles)
import { Label1, Mono } from './typography/index.jsx'
const CopyToClipboard = ({
className,
buttonClassname,
children,
wrapperClassname,
removeSpace = true,
...props
removeSpace = true
}) => {
const [anchorEl, setAnchorEl] = useState(null)
@ -26,8 +22,6 @@ const CopyToClipboard = ({
if (anchorEl) setTimeout(() => setAnchorEl(null), 3000)
}, [anchorEl])
const classes = useStyles()
const handleClick = event => {
setAnchorEl(anchorEl ? null : event.currentTarget)
}
@ -40,16 +34,19 @@ const CopyToClipboard = ({
const id = open ? 'simple-popper' : undefined
return (
<div className={classnames(classes.wrapper, wrapperClassname)}>
<div className={classnames('flex items-center', wrapperClassname)}>
{children && (
<>
<div className={classnames(classes.address, className)}>
<Mono
noMargin
className={classnames('linebreak-anywhere', className)}>
{children}
</div>
<div className={classnames(classes.buttonWrapper, buttonClassname)}>
</Mono>
<div className={buttonClassname}>
<ReactCopyToClipboard
text={removeSpace ? R.replace(/\s/g, '')(children) : children}>
<button
className="border-0 bg-transparent cursor-pointer"
aria-describedby={id}
onClick={event => handleClick(event)}>
<CopyIcon />
@ -61,12 +58,12 @@ const CopyToClipboard = ({
open={open}
anchorEl={anchorEl}
onClose={handleClose}
arrowSize={3}
bgColor={comet}
className="py-1 px-2"
placement="top">
<div className={classes.popoverContent}>
<div>Copied to clipboard!</div>
</div>
<Label1 noMargin className="text-white rounded-sm">
Copied to clipboard!
</Label1>
</Popover>
</>
)}

View file

@ -1,54 +1,25 @@
import Dialog from '@mui/material/Dialog'
import DialogActions from '@mui/material/DialogActions'
import DialogContent from '@mui/material/DialogContent'
import { makeStyles } from '@mui/styles'
import IconButton from '@mui/material/IconButton'
import React from 'react'
import { H4, P } from 'src/components/typography'
import CloseIcon from 'src/styling/icons/action/close/zodiac.svg?react'
import { Button, IconButton } from 'src/components/buttons'
import { spacer } from 'src/styling/variables'
import { Button } from 'src/components/buttons'
import ErrorMessage from './ErrorMessage'
const useStyles = makeStyles({
content: {
width: 434,
padding: spacer * 2,
paddingRight: spacer * 3.5
},
titleSection: {
padding: spacer * 2,
paddingRight: spacer * 1.5,
display: 'flex',
justifyContent: 'space-between',
margin: 0
},
actions: {
padding: spacer * 4,
paddingTop: spacer * 2
},
title: {
margin: 0
},
closeButton: {
padding: 0,
marginTop: -(spacer / 2)
}
})
import SvgIcon from '@mui/material/SvgIcon'
export const DialogTitle = ({ children, close }) => {
const classes = useStyles()
return (
<div className={classes.titleSection}>
<div className="p-4 pr-3 flex justify-between m-0">
{children}
{close && (
<IconButton
size={16}
aria-label="close"
onClick={close}
className={classes.closeButton}>
<CloseIcon />
<IconButton aria-label="close" onClick={close} className="p-0 -mt-1">
<SvgIcon fontSize="small">
<CloseIcon />
</SvgIcon>
</IconButton>
)}
</div>
@ -65,12 +36,10 @@ export const DeleteDialog = ({
extraMessage,
errorMessage = ''
}) => {
const classes = useStyles()
return (
<Dialog open={open} aria-labelledby="form-dialog-title">
<DialogTitle close={() => onDismissed()}>
<H4 className={classes.title}>{title}</H4>
<H4 className="m-0">{title}</H4>
</DialogTitle>
{errorMessage && (
<DialogTitle>
@ -84,11 +53,11 @@ export const DeleteDialog = ({
</ErrorMessage>
</DialogTitle>
)}
<DialogContent className={classes.content}>
<DialogContent className="w-108 p-4 pr-7">
{confirmationMessage && <P>{confirmationMessage}</P>}
{extraMessage}
</DialogContent>
<DialogActions className={classes.actions}>
<DialogActions className="p-8 pt-4">
<Button onClick={onConfirmed}>Confirm</Button>
</DialogActions>
</Dialog>

View file

@ -1,38 +1,16 @@
import { makeStyles } from '@mui/styles'
import classnames from 'classnames'
import React from 'react'
import ErrorIcon from 'src/styling/icons/warning-icon/tomato.svg?react'
import { errorColor } from 'src/styling/variables'
import { Info3 } from './typography'
const styles = {
wrapper: {
display: 'flex',
alignItems: 'center',
'& > svg': {
marginRight: 10
}
},
message: {
display: 'flex',
alignItems: 'center',
color: errorColor,
margin: 0,
whiteSpace: 'break-spaces'
}
}
const useStyles = makeStyles(styles)
const ErrorMessage = ({ className, children, ...props }) => {
const classes = useStyles()
const ErrorMessage = ({ className, children }) => {
return (
<div className={classnames(classes.wrapper, className)}>
<ErrorIcon />
<Info3 className={classes.message}>{children}</Info3>
<div className={classnames('flex items-center', className)}>
<ErrorIcon className="mr-3" />
<Info3 className="flex items-center text-tomato m-0 whitespace-break-spaces">
{children}
</Info3>
</div>
)
}

View file

@ -1,5 +1,4 @@
import ClickAwayListener from '@mui/material/ClickAwayListener'
import { makeStyles } from '@mui/styles'
import classnames from 'classnames'
import React, { memo, useState } from 'react'
import Popper from 'src/components/Popper'
@ -8,18 +7,8 @@ import ZoomIcon from 'src/styling/icons/circle buttons/search/zodiac.svg?react'
import { FeatureButton } from 'src/components/buttons'
import imagePopperStyles from './ImagePopper.styles'
const useStyles = makeStyles(imagePopperStyles)
const ImagePopper = memo(
({ className, width, height, popupWidth, popupHeight, src }) => {
const classes = useStyles({
width,
height,
popupWidth,
popupHeight
})
const [popperAnchorEl, setPopperAnchorEl] = useState(null)
const handleOpenPopper = event => {
@ -32,23 +21,30 @@ const ImagePopper = memo(
const popperOpen = Boolean(popperAnchorEl)
const Image = ({ className }) => (
<img className={classnames(className)} src={src} alt="" />
const Image = ({ className, style }) => (
<img className={classnames(className)} style={style} src={src} alt="" />
)
return (
<ClickAwayListener onClickAway={handleClosePopper}>
<div className={classnames(classes.row, className)}>
<Image className={classes.image} />
<div className={classnames('flex flex-row', className)}>
<Image
className="object-cover rounded-tl-lg"
style={{ width, height }}
/>
<FeatureButton
Icon={ZoomIcon}
InverseIcon={ZoomIconInverse}
className={classes.button}
className="rounded-none rounded-tr-lg rounded-br-lg"
style={{ height }}
onClick={handleOpenPopper}
/>
<Popper open={popperOpen} anchorEl={popperAnchorEl} placement="top">
<div className={classes.popoverContent}>
<Image className={classes.popupImage} />
<div className="py-2 px-4">
<Image
className="object-cover"
style={{ width: popupWidth, height: popupHeight }}
/>
</div>
</Popper>
</div>

View file

@ -1,25 +0,0 @@
export default {
row: {
display: 'flex',
flexDirection: 'row'
},
image: ({ width, height }) => ({
objectFit: 'cover',
borderRadius: '8px 0px 0px 8px',
width,
height
}),
popupImage: ({ popupWidth, popupHeight }) => ({
objectFit: 'cover',
width: popupWidth,
height: popupHeight
}),
button: ({ height }) => ({
borderRadius: '0px 8px 8px 0px',
height
}),
popoverContent: {
display: 'block',
padding: [[10, 15]]
}
}

View file

@ -1,26 +0,0 @@
import Box from '@mui/material/Box'
import { makeStyles } from '@mui/styles'
import React from 'react'
import { Label1 } from 'src/components/typography'
import WarningIcon from 'src/styling/icons/warning-icon/comet.svg?react'
const useStyles = makeStyles({
message: ({ width }) => ({
width,
marginTop: 4,
marginLeft: 16
})
})
const InfoMessage = ({ children, width = 330, className }) => {
const classes = useStyles({ width })
return (
<Box display="flex" className={className}>
<WarningIcon />
<Label1 className={classes.message}>{children}</Label1>
</Box>
)
}
export default InfoMessage

View file

@ -1,43 +1,13 @@
import Dialog from '@mui/material/Dialog'
import DialogContent from '@mui/material/DialogContent'
import { makeStyles } from '@mui/styles'
import SvgIcon from '@mui/material/SvgIcon'
import IconButton from '@mui/material/IconButton'
import React, { memo } from 'react'
import { H1 } from 'src/components/typography'
import CloseIcon from 'src/styling/icons/action/close/zodiac.svg?react'
import { IconButton } from 'src/components/buttons'
import { spacer } from 'src/styling/variables'
const useStyles = makeStyles({
closeButton: {
display: 'flex',
padding: [[spacer * 2, spacer * 2, 0, spacer * 2]],
paddingRight: spacer * 1.5,
justifyContent: 'end'
},
title: {
margin: [[0, spacer * 2, spacer, spacer * 2 + 4]]
}
})
export const DialogTitle = ({ children, onClose }) => {
const classes = useStyles()
return (
<div className={classes.dialogTitle}>
{children}
{onClose && (
<IconButton size={16} aria-label="close" onClick={onClose}>
<CloseIcon />
</IconButton>
)}
</div>
)
}
export const InformativeDialog = memo(
({ title = '', open, onDissmised, disabled = false, data, ...props }) => {
const classes = useStyles()
const innerOnClose = () => {
onDissmised()
}
@ -53,13 +23,16 @@ export const InformativeDialog = memo(
open={open}
aria-labelledby="form-dialog-title"
{...props}>
<div className={classes.closeButton}>
<IconButton size={16} aria-label="close" onClick={innerOnClose}>
<div className="flex justify-end pt-4 pr-3 pb-0 pl-4">
<IconButton aria-label="close" onClick={innerOnClose}>
<SvgIcon fontSize="small">
<CloseIcon />
</SvgIcon>
<CloseIcon />
</IconButton>
</div>
<H1 className={classes.title}>{title}</H1>
<DialogContent className={classes.dialogContent}>{data}</DialogContent>
<H1 className="mt-0 mr-4 mb-2 ml-5">{title}</H1>
<DialogContent>{data}</DialogContent>
</Dialog>
)
}

View file

@ -1,6 +1,5 @@
import { useLazyQuery } from "@apollo/client";
import { useLazyQuery } from '@apollo/client'
import ClickAwayListener from '@mui/material/ClickAwayListener'
import { makeStyles } from '@mui/styles'
import classnames from 'classnames'
import { format, set } from 'date-fns/fp'
import FileSaver from 'file-saver'
@ -11,68 +10,32 @@ import DownloadInverseIcon from 'src/styling/icons/button/download/white.svg?rea
import Download from 'src/styling/icons/button/download/zodiac.svg?react'
import { FeatureButton, Link } from 'src/components/buttons'
import { primaryColor, offColor, zircon } from 'src/styling/variables'
import { formatDate } from 'src/utils/timezones'
import Popper from './Popper'
import DateRangePicker from './date-range-picker/DateRangePicker'
import { RadioGroup } from './inputs'
import typographyStyles from './typography/styles'
import { H4, Info1, Label1, Label2 } from './typography/index.jsx'
const { info1, label1, label2, h4 } = typographyStyles
const dateContainerStyles = {
wrapper: {
height: 46,
width: 99
},
container: {
display: 'flex'
},
monthWeekDayContainer: {
display: 'flex',
flexDirection: 'column'
},
label: {
extend: label1,
lineHeight: 1.33,
color: primaryColor
},
bigNumber: {
extend: info1,
lineHeight: 1,
marginRight: 7
},
monthYear: {
extend: label2,
lineHeight: 1.17,
color: primaryColor
},
weekDay: {
extend: label1,
lineHeight: 1.33,
color: offColor
}
}
const dateContainerUseStyles = makeStyles(dateContainerStyles)
const DateContainer = ({ date, children, ...props }) => {
const classes = dateContainerUseStyles()
const DateContainer = ({ date, children }) => {
return (
<div className={classes.wrapper}>
<div className={classes.label}>{children}</div>
<div className="h-11 w-25">
<Label1 noMargin>{children}</Label1>
{date && (
<>
<div className={classes.container}>
<div className={classes.bigNumber}>{format('d', date)}</div>
<div className={classes.monthWeekDayContainer}>
<span className={classes.monthYear}>{`${format(
<div className="flex">
<Info1 noMargin className="mr-2">
{format('d', date)}
</Info1>
<div className="flex flex-col">
<Label2 noMargin>{`${format(
'MMM',
date
)} ${format('yyyy', date)}`}</span>
<span className={classes.weekDay}>{format('EEEE', date)}</span>
)} ${format('yyyy', date)}`}</Label2>
<Label1 noMargin className="text-comet">
{format('EEEE', date)}
</Label1>
</div>
</div>
</>
@ -81,54 +44,6 @@ const DateContainer = ({ date, children, ...props }) => {
)
}
const styles = {
popoverContent: {
width: 280
},
popoverHeader: {
extend: h4,
padding: [[15, 15, 0, 15]]
},
radioButtonsContainer: {
padding: [[5, 15, 5, 15]]
},
radioButtons: {
display: 'flex',
justifyContent: 'space-between',
flexDirection: 'row',
color: primaryColor
},
dateRangePickerShowing: {
display: 'block',
height: '100%'
},
dateRangePickerHidden: {
display: 'none',
height: 0
},
download: {
padding: [[10, 15]]
},
dateContainerWrapper: {
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
position: 'relative',
backgroundColor: zircon,
padding: [[0, 15]],
minHeight: 70
},
arrowContainer: {
position: 'absolute',
left: 125,
top: 26
},
arrow: {
margin: 'auto'
}
}
const useStyles = makeStyles(styles)
const ALL = 'all'
const RANGE = 'range'
const ADVANCED = 'advanced'
@ -153,11 +68,9 @@ const LogsDownloaderPopover = ({
onCompleted: data => createLogsFile(getLogs(data), range)
})
const classes = useStyles()
const dateRangePickerClasses = {
[classes.dateRangePickerShowing]: selectedRadio === RANGE,
[classes.dateRangePickerHidden]: selectedRadio === ALL
'block h-full': selectedRadio === RANGE,
hidden: selectedRadio === ALL
}
const handleRadioButtons = evt => {
@ -255,26 +168,28 @@ const LogsDownloaderPopover = ({
variant="contained"
/>
<Popper id={id} open={open} anchorEl={anchorEl} placement="bottom">
<div className={classes.popoverContent}>
<div className={classes.popoverHeader}>{title}</div>
<div className={classes.radioButtonsContainer}>
<div className="w-70">
<H4 noMargin className="p-4 pb-0">
{title}
</H4>
<div className="py-1 px-4">
<RadioGroup
name="logs-select"
value={selectedRadio}
options={radioButtonOptions}
ariaLabel="logs-select"
onChange={handleRadioButtons}
className={classes.radioButtons}
className="flex flex-row justify-between text-zodiac"
/>
</div>
{selectedRadio === RANGE && (
<div className={classnames(dateRangePickerClasses)}>
<div className={classes.dateContainerWrapper}>
<div className="flex justify-between items-center py-0 px-4 bg-zircon relative min-h-20">
{range && (
<>
<DateContainer date={range.from}>From</DateContainer>
<div className={classes.arrowContainer}>
<Arrow className={classes.arrow} />
<div className="absolute left-31 top-6">
<Arrow className="m-auto" />
</div>
<DateContainer date={range.until}>To</DateContainer>
</>
@ -295,18 +210,18 @@ const LogsDownloaderPopover = ({
</div>
)}
{simplified && (
<div className={classes.radioButtonsContainer}>
<div className="py-1 px-4">
<RadioGroup
name="simplified-tx-logs"
value={selectedAdvancedRadio}
options={advancedRadioButtonOptions}
ariaLabel="simplified-tx-logs"
onChange={handleAdvancedRadioButtons}
className={classes.radioButtons}
className="flex flex-row justify-between text-zodiac"
/>
</div>
)}
<div className={classes.download}>
<div className="py-3 px-4">
<Link color="primary" onClick={() => downloadLogs(range, args)}>
Download
</Link>

View file

@ -1,75 +1,12 @@
import MaterialModal from '@mui/material/Modal'
import IconButton from '@mui/material/IconButton'
import SvgIcon from '@mui/material/SvgIcon'
import Paper from '@mui/material/Paper'
import { makeStyles } from '@mui/styles'
import classnames from 'classnames'
import React from 'react'
import { H1, H4 } from 'src/components/typography'
import CloseIcon from 'src/styling/icons/action/close/zodiac.svg?react'
import { IconButton } from 'src/components/buttons'
const styles = {
modal: {
display: 'flex',
justifyContent: 'center',
flexDirection: 'column',
alignItems: 'center'
},
wrapper: ({ width, height }) => ({
width,
height,
display: 'flex',
flexDirection: 'column',
minHeight: height ?? 400,
maxHeight: '90vh',
overflowY: 'auto',
borderRadius: 8,
outline: 0
}),
infoPanelWrapper: ({ width, infoPanelHeight }) => ({
width,
height: infoPanelHeight,
marginTop: 16,
display: 'flex',
flexDirection: 'column',
minHeight: infoPanelHeight ?? 200,
maxHeight: '90vh',
overflowY: 'auto',
borderRadius: 8,
outline: 0
}),
panelContent: {
width: '100%',
display: 'flex',
flexDirection: 'column',
flex: 1,
padding: [[0, 24]]
},
content: ({ small, xl }) => ({
width: '100%',
display: 'flex',
flexDirection: 'column',
flex: 1,
padding: xl ? [[0, 60 + 28]] : small ? [[0, 16]] : [[0, 32]]
}),
button: ({ small, xl }) => ({
padding: [[0, 0, xl ? 26 : 0, 0]],
margin: xl
? [[0, 0, 'auto', 'auto']]
: small
? [[12, 12, 'auto', 'auto']]
: [[16, 16, 'auto', 'auto']]
}),
header: {
display: 'flex'
},
title: ({ small }) => ({
margin: small ? [[20, 0, 8, 16]] : [[28, 0, 8, 32]]
})
}
const useStyles = makeStyles(styles)
const Modal = ({
width,
height,
@ -86,7 +23,6 @@ const Modal = ({
closeOnBackdropClick,
...props
}) => {
const classes = useStyles({ width, height, small, infoPanelHeight, xl })
const TitleCase = small ? H4 : H1
const closeSize = xl ? 28 : small ? 16 : 20
@ -96,24 +32,61 @@ const Modal = ({
handleClose()
}
const marginBySize = xl ? 0 : small ? 12 : 16
const paddingBySize = xl ? 88 : small ? 16 : 32
return (
<MaterialModal onClose={innerClose} className={classes.modal} {...props}>
<MaterialModal
onClose={innerClose}
className="flex justify-center flex-col items-center"
{...props}>
<>
<Paper className={classnames(classes.wrapper, className)}>
<div className={classes.header}>
{title && <TitleCase className={classes.title}>{title}</TitleCase>}
<IconButton
size={closeSize}
className={classes.button}
onClick={() => handleClose()}>
<CloseIcon />
</IconButton>
<Paper
style={{ width, height, minHeight: height ?? 400 }}
className={classnames(
'flex flex-col max-h-[90vh] rounded-lg outline-0',
className
)}>
<div className="flex">
{title && (
<TitleCase
className={
small ? 'mt-5 mr-0 mb-2 ml-4' : 'mt-7 mr-0 mb-2 ml-8'
}>
{title}
</TitleCase>
)}
<div
className="ml-auto"
style={{ marginRight: marginBySize, marginTop: marginBySize }}>
<IconButton
className="p-0 mb-auto ml-auto"
onClick={() => handleClose()}>
<SvgIcon fontSize={xl ? 'large' : 'small'}>
<CloseIcon />
</SvgIcon>
</IconButton>
</div>
</div>
<div
className="w-full flex flex-col flex-1"
style={{ paddingRight: paddingBySize, paddingLeft: paddingBySize }}>
{children}
</div>
<div className={classes.content}>{children}</div>
</Paper>
{infoPanel && (
<Paper className={classnames(classes.infoPanelWrapper, className)}>
<div className={classes.panelContent}>{infoPanel}</div>
<Paper
style={{
width,
height: infoPanelHeight,
minHeight: infoPanelHeight ?? 200
}}
className={classnames(
'mt-4 flex flex-col max-h-[90vh] overflow-y-auto rounded-lg outline-0',
className
)}>
<div className="w-full flex flex-col flex-1 py-0 px-6">
{infoPanel}
</div>
</Paper>
)}
</>

View file

@ -1,5 +1,4 @@
import { useQuery, useMutation, gql } from "@apollo/client";
import { makeStyles } from '@mui/styles'
import { useQuery, useMutation, gql } from '@apollo/client'
import * as R from 'ramda'
import React, { useState, useEffect } from 'react'
import ActionButton from 'src/components/buttons/ActionButton'
@ -9,10 +8,8 @@ import ClearAllIconInverse from 'src/styling/icons/stage/spring/empty.svg?react'
import ClearAllIcon from 'src/styling/icons/stage/zodiac/empty.svg?react'
import ShowUnreadIcon from 'src/styling/icons/stage/zodiac/full.svg?react'
import styles from './NotificationCenter.styles'
import NotificationRow from './NotificationRow'
const useStyles = makeStyles(styles)
import classes from './NotificationCenter.module.css'
const GET_NOTIFICATIONS = gql`
query getNotifications {
@ -63,7 +60,6 @@ const NotificationCenter = ({
const [xOffset, setXoffset] = useState(300)
const [showingUnread, setShowingUnread] = useState(false)
const classes = useStyles({ buttonCoords, xOffset })
const machines = R.compose(
R.map(R.prop('name')),
R.indexBy(R.prop('deviceId'))
@ -120,7 +116,13 @@ const NotificationCenter = ({
<div className={classes.container}>
<div className={classes.header}>
<H5 className={classes.headerText}>Notifications</H5>
<button onClick={close} className={classes.notificationIcon}>
<button
onClick={close}
className={classes.notificationIcon}
style={{
top: buttonCoords?.y ?? 0,
left: buttonCoords?.x ? buttonCoords.x - xOffset : 0
}}>
<NotificationIconZodiac />
{hasUnread && <div className={classes.hasUnread} />}
</button>

View file

@ -0,0 +1,145 @@
.container {
width: 40vw;
height: 110vh;
right: 0;
background-color: white;
box-shadow: 0 0 14px 0 rgba(0, 0, 0, 0.24);
}
.container @media only screen and (max-width: 1920px) {
width: 30vw;
}
.header {
display: flex;
justify-content: space-between;
}
.headerText {
margin-top: 20px;
margin-left: 12px;
}
.actionButtons {
display: flex;
margin-left: 16px;
height: 0;
}
.notificationIcon {
position: absolute;
cursor: pointer;
background: transparent;
box-shadow: 0 0 0 transparent;
border: 0 solid transparent;
text-shadow: 0 0 0 transparent;
outline: none;
}
.clearAllButton {
margin-top: -16px;
margin-left: 8px;
background-color: var(--zircon);
}
.notificationsList {
height: 90vh;
max-height: 100vh;
margin-top: 24px;
margin-left: 0;
overflow-y: auto;
overflow-x: hidden;
background-color: white;
z-index: 10;
}
.notificationRow {
display: flex;
flex-direction: row;
justify-content: flex-start;
position: relative;
margin-bottom: 16px;
padding-top: 12px;
gap: 10px;
}
.notificationRow > *:first-child {
margin-right: 24px;
}
.notificationContent {
display: flex;
flex-direction: column;
justify-content: center;
width: 300px;
}
.unread {
background-color: var(--spring3)
}
.notificationRowIcon {
align-self: center;
}
.notificationRowIcon > * {
margin-left: 24px
}
.readIconWrapper {
flex-grow: 1
}
.unreadIcon {
margin-top: 5px;
margin-left: 8px;
width: 12px;
height: 12px;
background-color: var(--spring);
border-radius: 50%;
cursor: pointer;
z-index: 1;
}
.readIcon {
margin-left: 8px;
margin-top: 5px;
width: 12px;
height: 12px;
border: 1px solid var(--comet);
border-radius: 50%;
cursor: pointer;
z-index: 1;
}
.notificationTitle {
margin: 0;
color: var(--comet);
}
.notificationBody {
margin: 0
}
.notificationSubtitle {
margin: 0;
margin-bottom: 8px;
color: var(--comet);
}
.stripes {
position: absolute;
height: 100%;
top: 0;
opacity: 60%;
}
.hasUnread {
position: absolute;
top: 0;
left: 16px;
width: 9px;
height: 9px;
background-color: var(--spring);
border-radius: 50%;
}

View file

@ -1,143 +0,0 @@
import {
spacer,
white,
zircon,
secondaryColor,
spring3,
comet
} from 'src/styling/variables'
const styles = {
container: {
'@media only screen and (max-width: 1920px)': {
width: '30vw'
},
width: '40vw',
height: '110vh',
right: 0,
backgroundColor: white,
boxShadow: '0 0 14px 0 rgba(0, 0, 0, 0.24)'
},
header: {
display: 'flex',
justifyContent: 'space-between'
},
headerText: {
marginTop: spacer * 2.5,
marginLeft: spacer * 3
},
actionButtons: {
display: 'flex',
marginLeft: spacer * 2,
height: 0
},
notificationIcon: ({ buttonCoords, xOffset }) => ({
position: 'absolute',
top: buttonCoords ? buttonCoords.y : 0,
left: buttonCoords ? buttonCoords.x - xOffset : 0,
cursor: 'pointer',
background: 'transparent',
boxShadow: '0px 0px 0px transparent',
border: '0px solid transparent',
textShadow: '0px 0px 0px transparent',
outline: 'none'
}),
clearAllButton: {
marginTop: -spacer * 2,
marginLeft: spacer,
backgroundColor: zircon
},
notificationsList: {
height: '90vh',
maxHeight: '100vh',
marginTop: spacer * 3,
marginLeft: 0,
overflowY: 'auto',
overflowX: 'hidden',
backgroundColor: white,
zIndex: 10
},
notificationRow: {
display: 'flex',
flexDirection: 'row',
justifyContent: 'flex-start',
position: 'relative',
marginBottom: spacer / 2,
paddingTop: spacer * 1.5,
'& > *:first-child': {
marginRight: 24
},
'& > *': {
marginRight: 10
},
'& > *:last-child': {
marginRight: 0
}
},
notificationContent: {
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
width: 300
},
unread: {
backgroundColor: spring3
},
notificationRowIcon: {
alignSelf: 'center',
'& > *': {
marginLeft: spacer * 3
}
},
readIconWrapper: {
flexGrow: 1
},
unreadIcon: {
marginTop: 2,
width: '12px',
height: '12px',
backgroundColor: secondaryColor,
borderRadius: '50%',
cursor: 'pointer',
zIndex: 1
},
readIcon: {
marginLeft: spacer,
marginTop: 5,
width: '12px',
height: '12px',
border: [[1, 'solid', comet]],
borderRadius: '50%',
cursor: 'pointer',
zIndex: 1
},
notificationTitle: {
margin: 0,
color: comet
},
notificationBody: {
margin: 0
},
notificationSubtitle: {
margin: 0,
marginBottom: spacer,
color: comet
},
stripes: {
position: 'absolute',
height: '100%',
top: '0px',
opacity: '60%'
},
hasUnread: {
position: 'absolute',
top: 0,
left: 16,
width: '9px',
height: '9px',
backgroundColor: secondaryColor,
borderRadius: '50%'
}
}
export default styles

View file

@ -1,4 +1,3 @@
import { makeStyles } from '@mui/styles'
import classnames from 'classnames'
import prettyMs from 'pretty-ms'
import * as R from 'ramda'
@ -8,8 +7,7 @@ import Wrench from 'src/styling/icons/action/wrench/zodiac.svg?react'
import Transaction from 'src/styling/icons/arrow/transaction.svg?react'
import WarningIcon from 'src/styling/icons/warning-icon/tomato.svg?react'
import styles from './NotificationCenter.styles'
const useStyles = makeStyles(styles)
import classes from './NotificationCenter.module.css'
const types = {
transaction: {
@ -46,8 +44,6 @@ const NotificationRow = ({
valid,
toggleClear
}) => {
const classes = useStyles()
const typeDisplay = R.path([type, 'display'])(types) ?? null
const icon = R.path([type, 'icon'])(types) ?? (
<Wrench height={16} width={16} />

View file

@ -1,120 +1,15 @@
import MaterialPopper from '@mui/material/Popper'
import Paper from '@mui/material/Paper'
import { makeStyles } from '@mui/styles'
import classnames from 'classnames'
import * as R from 'ramda'
import React, { useState } from 'react'
import { white } from 'src/styling/variables'
import classes from './Popper.module.css'
const Popover = ({
children,
bgColor = white,
arrowSize = 6,
className,
...props
}) => {
const Popover = ({ children, bgColor = white, className, ...props }) => {
const [arrowRef, setArrowRef] = useState(null)
const styles = {
popover: {
zIndex: 3000,
backgroundColor: bgColor,
borderRadius: 4
},
arrow: {
position: 'absolute',
fontSize: arrowSize,
width: '3em',
height: '3em'
},
arrowBottom: {
top: 0,
width: 0,
height: 0,
borderLeft: [['2em', 'solid', 'transparent']],
borderRight: [['2em', 'solid', 'transparent']],
borderBottom: [['2em', 'solid', bgColor]],
marginTop: '-1.9em',
'&:after': {
zIndex: -10,
content: '""',
position: 'absolute',
width: arrowSize * 3,
height: arrowSize * 3,
marginLeft: 0,
bottom: 0,
top: 'calc(50% - 0px)',
left: 0,
border: '5px solid #fff',
borderColor: 'transparent transparent #fff #fff',
transformOrigin: '0 0',
transform: 'rotate(45deg)',
boxShadow:
'0px 2px 1px -1px rgba(0,0,0,0.2),0px 1px 1px 0px rgba(0,0,0,0.14),0px 1px 3px 0px rgba(0,0,0,0.12)'
}
},
arrowTop: {
bottom: 0,
width: 0,
height: 0,
borderLeft: [['2em', 'solid', 'transparent']],
borderRight: [['2em', 'solid', 'transparent']],
borderTop: [['2em', 'solid', bgColor]],
marginBottom: '-1.9em',
'&:after': {
zIndex: -10,
content: '""',
position: 'absolute',
width: arrowSize * 3,
height: arrowSize * 3,
marginLeft: 0,
bottom: 0,
top: -(arrowSize * 4 + 2),
left: 0,
border: '5px solid #fff',
borderColor: 'transparent transparent #fff #fff',
transformOrigin: '0 0',
transform: 'rotate(45deg)',
boxShadow:
'0px 2px 1px -1px rgba(0,0,0,0.2),0px 1px 1px 0px rgba(0,0,0,0.14),0px 1px 3px 0px rgba(0,0,0,0.12)'
}
},
arrowRight: {
left: 0,
width: 0,
height: 0,
borderTop: [['2em', 'solid', 'transparent']],
borderBottom: [['2em', 'solid', 'transparent']],
borderRight: [['2em', 'solid', bgColor]],
marginLeft: '-1.9em'
},
arrowLeft: {
right: 0,
width: 0,
height: 0,
borderTop: [['2em', 'solid', 'transparent']],
borderBottom: [['2em', 'solid', 'transparent']],
borderLeft: [['2em', 'solid', bgColor]],
marginRight: '-1.9em'
},
root: {
backgroundColor: bgColor
}
}
const useStyles = makeStyles(styles)
const classes = useStyles()
const getArrowClasses = placement => ({
[classes.arrow]: true,
[classes.arrowBottom]: placement === 'bottom',
[classes.arrowTop]: placement === 'top',
[classes.arrowRight]: placement === 'right',
[classes.arrowLeft]: placement === 'left'
})
const flipPlacements = {
top: ['bottom'],
bottom: ['top'],
@ -164,17 +59,16 @@ const Popover = ({
<MaterialPopper
disablePortal={false}
modifiers={modifiers}
className={classes.popover}
className={classnames(classes.tooltip, 'z-3000 rounded-sm')}
{...props}>
{({ placement }) => (
<Paper className={classnames(classes.root, className)}>
<span
className={classnames(getArrowClasses(placement))}
ref={setArrowRef}
/>
{children}
</Paper>
)}
<Paper style={{ backgroundColor: bgColor }} className={className}>
<span
className={classes.newArrow}
data-popper-arrow
ref={setArrowRef}
/>
{children}
</Paper>
</MaterialPopper>
</>
)

View file

@ -0,0 +1,33 @@
.newArrow,
.newArrow::before {
position: absolute;
width: 8px;
height: 8px;
background: inherit;
}
.newArrow {
visibility: hidden;
}
.newArrow::before {
visibility: visible;
content: '';
transform: rotate(45deg);
}
.tooltip[data-popper-placement^='top'] > div > span {
bottom: -4px;
}
.tooltip[data-popper-placement^='bottom'] > div > span {
top: -4px;
}
.tooltip[data-popper-placement^='left'] > div > span {
right: -4px;
}
.tooltip[data-popper-placement^='right'] > div > span {
left: -4px;
}

View file

@ -1,16 +1,11 @@
import InputBase from '@mui/material/InputBase'
import Paper from '@mui/material/Paper'
import { makeStyles } from '@mui/styles'
import MAutocomplete from '@mui/material/Autocomplete'
import classnames from 'classnames'
import React, { memo, useState } from 'react'
import { P } from 'src/components/typography'
import SearchIcon from 'src/styling/icons/circle buttons/search/zodiac.svg?react'
import styles from './SearchBox.styles'
const useStyles = makeStyles(styles)
const SearchBox = memo(
({
loading = false,
@ -21,13 +16,11 @@ const SearchBox = memo(
onChange,
...props
}) => {
const classes = useStyles({ size })
const [popupOpen, setPopupOpen] = useState(false)
const inputClasses = {
[classes.input]: true,
[classes.inputWithPopup]: popupOpen
'flex flex-1 h-8 px-2 py-2 font-md items-center rounded-2xl bg-zircon text-comet': true,
'rounded-b-none': popupOpen
}
const innerOnChange = filters => onChange(filters)
@ -35,15 +28,16 @@ const SearchBox = memo(
return (
<MAutocomplete
loading={loading}
classes={{ option: classes.autocomplete }}
value={filters}
options={options}
getOptionLabel={it => it.label || it.value}
renderOption={(props, it) => (
<li {...props}>
<div className={classes.item}>
<P className={classes.itemLabel}>{it.label || it.value}</P>
<P className={classes.itemType}>{it.type}</P>
<div className="flex flex-row w-full h-8">
<P className="m-0 whitespace-nowrap overflow-hidden text-ellipsis">
{it.label || it.value}
</P>
<P className="m-0 ml-auto text-sm text-come">{it.type}</P>
</div>
</li>
)}
@ -53,25 +47,16 @@ const SearchBox = memo(
multiple
filterSelectedOptions
isOptionEqualToValue={(option, value) => option.type === value.type}
PaperComponent={({ children }) => (
<Paper elevation={0} className={classes.popup}>
<div className={classes.separator} />
{children}
</Paper>
)}
renderInput={params => {
return (
<InputBase
ref={params.InputProps.ref}
{...params}
className={classnames(inputClasses)}
startAdornment={<SearchIcon className={classes.iconButton} />}
startAdornment={<SearchIcon className="mr-3" />}
placeholder={inputPlaceholder}
inputProps={{
className: classes.bold,
classes: {
root: classes.size
},
className: 'font-bold',
...params.inputProps
}}
/>
@ -81,8 +66,17 @@ const SearchBox = memo(
onClose={() => setPopupOpen(false)}
onChange={(_, filters) => innerOnChange(filters)}
{...props}
/>
)
slots={{
paper: ({ children }) => (
<Paper
elevation={0}
className="flex flex-col rounded-b-xl bg-zircon shadow-2xl">
<div className="w-[88%] h-[1px] my-p mx-auto border-1 border-comet" />
{children}
</Paper>
)
}} />
);
}
)

View file

@ -1,78 +0,0 @@
import baseButtonStyles from 'src/components/buttons/BaseButton.styles'
import { bySize, bold } from 'src/styling/helpers'
import { zircon, comet, primaryColor } from 'src/styling/variables'
const { baseButton } = baseButtonStyles
const searchBoxBorderRadius = baseButton.height / 2
const searchBoxHeight = 32
const popupBorderRadiusFocus = baseButton.height / 4
const hoverColor = 'rgba(0, 0, 0, 0.08)'
const boxShadow = `0 4px 4px 0 ${hoverColor}`
const styles = {
size: ({ size }) => ({
marginTop: size === 'lg' ? 0 : 2,
...bySize(size)
}),
bold,
autocomplete: {
'&[data-focus="true"]': {
backgroundColor: hoverColor
}
},
popup: {
display: 'flex',
flexDirection: 'column',
borderRadius: [[0, 0, popupBorderRadiusFocus, popupBorderRadiusFocus]],
backgroundColor: zircon,
boxShadow
},
separator: {
width: '88%',
height: 1,
margin: '0 auto',
border: 'solid 0.5px',
borderColor: comet
},
item: {
display: 'flex',
flexDirection: 'row',
width: '100%',
height: 36,
alignItems: 'center'
},
itemLabel: {
margin: [0],
whiteSpace: 'nowrap',
overflow: 'hidden',
textOverflow: 'ellipsis'
},
itemType: {
marginLeft: 'auto',
fontSize: 12,
color: comet,
margin: [0]
},
input: {
display: 'flex',
flex: 1,
width: 273,
padding: [[8, 12]],
alignItems: 'center',
height: searchBoxHeight,
borderRadius: searchBoxBorderRadius,
backgroundColor: zircon,
color: primaryColor
},
inputWithPopup: {
borderRadius: [[popupBorderRadiusFocus, popupBorderRadiusFocus, 0, 0]],
boxShadow
},
iconButton: {
marginRight: 12
}
}
export default styles

View file

@ -1,6 +1,5 @@
import { makeStyles } from '@mui/styles'
import Chip from '@mui/material/Chip'
import React from 'react'
import Chip from 'src/components/Chip'
import { P, Label3 } from 'src/components/typography'
import CloseIcon from 'src/styling/icons/action/close/zodiac.svg?react'
import FilterIcon from 'src/styling/icons/button/filter/white.svg?react'
@ -9,48 +8,39 @@ import ReverseFilterIcon from 'src/styling/icons/button/filter/zodiac.svg?react'
import { ActionButton } from 'src/components/buttons'
import { onlyFirstToUpper, singularOrPlural } from 'src/utils/string'
import { chipStyles, styles } from './SearchFilter.styles'
const useChipStyles = makeStyles(chipStyles)
const useStyles = makeStyles(styles)
const SearchFilter = ({
filters,
onFilterDelete,
deleteAllFilters,
entries = 0
}) => {
const chipClasses = useChipStyles()
const classes = useStyles()
return (
<>
<P className={classes.text}>{'Filters:'}</P>
<div className={classes.filters}>
<div className={classes.chips}>
<P className="mx-0">{'Filters:'}</P>
<div className="flex mb-4">
<div className="mt-auto">
{filters.map((f, idx) => (
<Chip
key={idx}
classes={chipClasses}
label={`${onlyFirstToUpper(f.type)}: ${f.label || f.value}`}
onDelete={() => onFilterDelete(f)}
deleteIcon={<CloseIcon className={classes.button} />}
deleteIcon={<CloseIcon className="w-2 h-2 mx-2" />}
/>
))}
</div>
<div className={classes.deleteWrapper}>
<div className="flex ml-auto justify-end flex-row">
{
<Label3 className={classes.entries}>{`${entries} ${singularOrPlural(
<Label3 className="text-comet m-auto mr-3">{`${entries} ${singularOrPlural(
entries,
`entry`,
`entries`
)}`}</Label3>
}
<ActionButton
altTextColor
color="secondary"
Icon={ReverseFilterIcon}
InverseIcon={FilterIcon}
className={classes.deleteButton}
onClick={deleteAllFilters}>
Delete filters
</ActionButton>

View file

@ -1,62 +0,0 @@
import {
primaryColor,
zircon,
smallestFontSize,
inputFontFamily,
inputFontWeight,
spacer,
offColor
} from 'src/styling/variables'
const chipStyles = {
root: {
marginLeft: 0,
height: 20,
backgroundColor: zircon,
'&:hover, &:focus, &:active': {
backgroundColor: zircon
},
marginBottom: 'auto'
},
label: {
fontSize: smallestFontSize,
fontWeight: inputFontWeight,
fontFamily: inputFontFamily,
paddingRight: 0,
paddingLeft: spacer,
color: primaryColor
}
}
const styles = {
button: {
width: 8,
height: 8,
marginLeft: 8,
marginRight: 8
},
text: {
marginTop: 0,
marginBottom: 0
},
filters: {
display: 'flex',
marginBottom: 16
},
deleteWrapper: {
display: 'flex',
marginLeft: 'auto',
justifyContent: 'flex-end',
flexDirection: 'row'
},
entries: {
color: offColor,
margin: 'auto',
marginRight: 12
},
chips: {
marginTop: 'auto'
}
}
export { chipStyles, styles }

View file

@ -1,112 +0,0 @@
import { makeStyles } from '@mui/styles'
import classnames from 'classnames'
import * as R from 'ramda'
import React, { memo } from 'react'
import CompleteStageIconSpring from 'src/styling/icons/stage/spring/complete.svg?react'
import CurrentStageIconSpring from 'src/styling/icons/stage/spring/current.svg?react'
import EmptyStageIconSpring from 'src/styling/icons/stage/spring/empty.svg?react'
import CompleteStageIconZodiac from 'src/styling/icons/stage/zodiac/complete.svg?react'
import CurrentStageIconZodiac from 'src/styling/icons/stage/zodiac/current.svg?react'
import EmptyStageIconZodiac from 'src/styling/icons/stage/zodiac/empty.svg?react'
import {
primaryColor,
secondaryColor,
offColor,
disabledColor
} from 'src/styling/variables'
const styles = {
stages: {
display: 'flex',
alignItems: 'center'
},
wrapper: {
display: 'flex',
alignItems: 'center',
margin: 0
},
stage: {
display: 'flex',
height: 28,
width: 28,
zIndex: 2,
'& > svg': {
height: '100%',
width: '100%',
overflow: 'visible'
}
},
separator: {
width: 28,
height: 2,
border: [[2, 'solid']],
zIndex: 1
},
separatorSpring: {
borderColor: secondaryColor
},
separatorZodiac: {
borderColor: primaryColor
},
separatorSpringEmpty: {
borderColor: disabledColor
},
separatorZodiacEmpty: {
borderColor: offColor
}
}
const useStyles = makeStyles(styles)
const Stage = memo(({ stages, currentStage, color = 'spring', className }) => {
if (currentStage < 1 || currentStage > stages)
throw Error('Value of currentStage is invalid')
if (stages < 1) throw Error('Value of stages is invalid')
const classes = useStyles()
const separatorClasses = {
[classes.separator]: true,
[classes.separatorSpring]: color === 'spring',
[classes.separatorZodiac]: color === 'zodiac'
}
const separatorEmptyClasses = {
[classes.separator]: true,
[classes.separatorSpringEmpty]: color === 'spring',
[classes.separatorZodiacEmpty]: color === 'zodiac'
}
return (
<div className={classnames(className, classes.stages)}>
{R.range(1, currentStage).map(idx => (
<div key={idx} className={classes.wrapper}>
{idx > 1 && <div className={classnames(separatorClasses)} />}
<div className={classes.stage}>
{color === 'spring' && <CompleteStageIconSpring />}
{color === 'zodiac' && <CompleteStageIconZodiac />}
</div>
</div>
))}
<div className={classes.wrapper}>
{currentStage > 1 && <div className={classnames(separatorClasses)} />}
<div className={classes.stage}>
{color === 'spring' && <CurrentStageIconSpring />}
{color === 'zodiac' && <CurrentStageIconZodiac />}
</div>
</div>
{R.range(currentStage + 1, stages + 1).map(idx => (
<div key={idx} className={classes.wrapper}>
<div className={classnames(separatorEmptyClasses)} />
<div className={classes.stage}>
{color === 'spring' && <EmptyStageIconSpring />}
{color === 'zodiac' && <EmptyStageIconZodiac />}
</div>
</div>
))}
</div>
)
})
export default Stage

View file

@ -1,59 +1,8 @@
import Chip from '@mui/material/Chip'
import { makeStyles } from '@mui/styles'
import React from 'react'
import {
tomato,
mistyRose,
pumpkin,
secondaryColorDarker as spring4,
inputFontWeight,
spring3,
zircon,
primaryColor,
smallestFontSize,
inputFontFamily,
spacer,
linen
} from '../styling/variables'
const colors = {
error: tomato,
warning: pumpkin,
success: spring4,
neutral: primaryColor
}
const backgroundColors = {
error: mistyRose,
warning: linen,
success: spring3,
neutral: zircon
}
const useStyles = makeStyles({
root: {
borderRadius: spacer / 2,
marginTop: spacer / 2,
marginRight: spacer / 4,
marginBottom: spacer / 2,
marginLeft: spacer / 4,
height: spacer * 3,
backgroundColor: ({ type }) => backgroundColors[type]
},
label: {
fontSize: smallestFontSize,
fontWeight: inputFontWeight,
fontFamily: inputFontFamily,
paddingRight: spacer / 2,
paddingLeft: spacer / 2,
color: ({ type }) => colors[type]
}
})
const Status = ({ status }) => {
const classes = useStyles({ type: status.type })
return <Chip type={status.type} label={status.label} classes={classes} />
return <Chip color={status.type} label={status.label} />
}
const MainStatus = ({ statuses }) => {

View file

@ -1,4 +1,3 @@
import { makeStyles } from '@mui/styles'
import classnames from 'classnames'
import * as R from 'ramda'
import React, { memo } from 'react'
@ -9,79 +8,29 @@ import CompleteStageIconZodiac from 'src/styling/icons/stage/zodiac/complete.svg
import CurrentStageIconZodiac from 'src/styling/icons/stage/zodiac/current.svg?react'
import EmptyStageIconZodiac from 'src/styling/icons/stage/zodiac/empty.svg?react'
import {
primaryColor,
secondaryColor,
offColor,
disabledColor
} from 'src/styling/variables'
const styles = {
stages: {
display: 'flex',
alignItems: 'center'
},
wrapper: {
display: 'flex',
alignItems: 'center',
margin: 0
},
stage: {
display: 'flex',
height: 28,
width: 28,
zIndex: 2,
'& > svg': {
height: '100%',
width: '100%',
overflow: 'visible'
}
},
separator: {
width: 28,
height: 2,
border: [[2, 'solid']],
zIndex: 1
},
separatorSpring: {
borderColor: secondaryColor
},
separatorZodiac: {
borderColor: primaryColor
},
separatorSpringEmpty: {
borderColor: disabledColor
},
separatorZodiacEmpty: {
borderColor: offColor
}
}
const useStyles = makeStyles(styles)
import classes from './Stepper.module.css'
const Stepper = memo(({ steps, currentStep, color = 'spring', className }) => {
if (currentStep < 1 || currentStep > steps)
throw Error('Value of currentStage is invalid')
if (steps < 1) throw Error('Value of stages is invalid')
const classes = useStyles()
const separatorClasses = {
[classes.separator]: true,
[classes.separatorSpring]: color === 'spring',
[classes.separatorZodiac]: color === 'zodiac'
'w-7 h-[2px] border-2 z-1': true,
'border-spring': color === 'spring',
'border-zodiac': color === 'zodiac'
}
const separatorEmptyClasses = {
[classes.separator]: true,
[classes.separatorSpringEmpty]: color === 'spring',
[classes.separatorZodiacEmpty]: color === 'zodiac'
'w-7 h-[2px] border-2 z-1': true,
'border-dust': color === 'spring',
'border-comet': color === 'zodiac'
}
return (
<div className={classnames(className, classes.stages)}>
<div className={classnames(className, 'flex items-center')}>
{R.range(1, currentStep).map(idx => (
<div key={idx} className={classes.wrapper}>
<div key={idx} className="flex items-center m-0">
{idx > 1 && <div className={classnames(separatorClasses)} />}
<div className={classes.stage}>
{color === 'spring' && <CompleteStageIconSpring />}
@ -89,7 +38,7 @@ const Stepper = memo(({ steps, currentStep, color = 'spring', className }) => {
</div>
</div>
))}
<div className={classes.wrapper}>
<div className="flex items-center m-0">
{currentStep > 1 && <div className={classnames(separatorClasses)} />}
<div className={classes.stage}>
{color === 'spring' && <CurrentStageIconSpring />}
@ -97,7 +46,7 @@ const Stepper = memo(({ steps, currentStep, color = 'spring', className }) => {
</div>
</div>
{R.range(currentStep + 1, steps + 1).map(idx => (
<div key={idx} className={classes.wrapper}>
<div key={idx} className="flex items-center m-0">
<div className={classnames(separatorEmptyClasses)} />
<div className={classes.stage}>
{color === 'spring' && <EmptyStageIconSpring />}

View file

@ -0,0 +1,12 @@
.stage {
display: flex;
height: 28px;
width: 28px;
z-index: 2;
}
.stage > svg {
height: 100%;
width: 100%;
overflow: visible;
}

View file

@ -1,27 +1,12 @@
import { makeStyles } from '@mui/styles'
import classnames from 'classnames'
import React, { memo } from 'react'
import { spacer, offColor } from 'src/styling/variables'
import { TL1 } from './typography'
const useStyles = makeStyles({
subtitle: {
color: offColor,
marginTop: spacer * 2,
marginBottom: spacer * 2
},
extraMarginTop: {
marginTop: spacer * 9
}
})
const Subtitle = memo(({ children, className, extraMarginTop }) => {
const classes = useStyles()
const classNames = {
[classes.subtitle]: true,
[classes.extraMarginTop]: extraMarginTop
'text-comet my-4': true,
'mt-18': extraMarginTop
}
return <TL1 className={classnames(classNames, className)}>{children}</TL1>

View file

@ -1,35 +0,0 @@
import { makeStyles } from '@mui/styles'
import classnames from 'classnames'
import React from 'react'
import { Label1 } from './typography'
const useStyles = makeStyles({
wrapper: {
display: 'flex',
alignItems: 'center'
},
colorIndicator: {
borderRadius: 3,
height: 12,
width: 12,
marginRight: 8
}
})
const TableLabel = ({ className, label, color, ...props }) => {
const classes = useStyles()
return (
<div className={classnames(classes.wrapper, className)} {...props}>
{color && (
<div
className={classes.colorIndicator}
style={{ backgroundColor: color }}
/>
)}
<Label1 {...props}>{label}</Label1>
</div>
)
}
export default TableLabel

View file

@ -1,20 +1,9 @@
import { makeStyles } from '@mui/styles'
import React, { memo } from 'react'
import { spacer } from 'src/styling/variables'
import { H1 } from './typography'
const useStyles = makeStyles({
title: {
marginTop: spacer * 3,
marginBottom: spacer * 3
}
})
const Title = memo(({ children }) => {
const classes = useStyles()
return <H1 className={classes.title}>{children}</H1>
return <H1 className="my-6">{children}</H1>
})
export default Title

View file

@ -1,11 +1,10 @@
import ClickAwayListener from '@mui/material/ClickAwayListener'
import { makeStyles } from '@mui/styles'
import * as R from 'ramda'
import React, { useState, memo } from 'react'
import Popper from 'src/components/Popper'
import HelpIcon from 'src/styling/icons/action/help/zodiac.svg?react'
const useStyles = makeStyles({
const useStyles = {
transparentButton: {
border: 'none',
backgroundColor: 'transparent',
@ -27,10 +26,9 @@ const useStyles = makeStyles({
width,
padding: [[10, 15]]
})
})
}
const usePopperHandler = width => {
const classes = useStyles({ width })
const usePopperHandler = () => {
const [helpPopperAnchorEl, setHelpPopperAnchorEl] = useState(null)
const handleOpenHelpPopper = event => {
@ -48,7 +46,6 @@ const usePopperHandler = width => {
const helpPopperOpen = Boolean(helpPopperAnchorEl)
return {
classes,
helpPopperAnchorEl,
helpPopperOpen,
handleOpenHelpPopper,
@ -62,15 +59,13 @@ const HelpTooltip = memo(({ children, width }) => {
return (
<ClickAwayListener onClickAway={handler.handleCloseHelpPopper}>
<div
className={handler.classes.relativelyPositioned}
onMouseLeave={handler.handleCloseHelpPopper}>
<div className="relative" onMouseLeave={handler.handleCloseHelpPopper}>
{handler.helpPopperOpen && (
<div className={handler.classes.safeSpace}></div>
<div className="absolute bg-transparent h-10 -left-1/2 w-[200%]"></div>
)}
<button
type="button"
className={handler.classes.transparentButton}
className="border-0 bg-transparent outline-0 cursor-pointer mt-1"
onMouseEnter={handler.openHelpPopper}>
<HelpIcon />
</button>
@ -79,7 +74,9 @@ const HelpTooltip = memo(({ children, width }) => {
anchorEl={handler.helpPopperAnchorEl}
arrowEnabled={true}
placement="bottom">
<div className={handler.classes.popoverContent}>{children}</div>
<div className="py-2 px-4" style={{ width }}>
{children}
</div>
</Popper>
</div>
</ClickAwayListener>
@ -104,7 +101,7 @@ const HoverableTooltip = memo(({ parentElements, children, width }) => {
type="button"
onMouseEnter={handler.handleOpenHelpPopper}
onMouseLeave={handler.handleCloseHelpPopper}
className={handler.classes.transparentButton}>
className="border-0 bg-transparent outline-0 cursor-pointer mt-1">
<HelpIcon />
</button>
)}
@ -112,7 +109,9 @@ const HoverableTooltip = memo(({ parentElements, children, width }) => {
open={handler.helpPopperOpen}
anchorEl={handler.helpPopperAnchorEl}
placement="bottom">
<div className={handler.classes.popoverContent}>{children}</div>
<div className="py-2 px-4" style={{ width }}>
{children}
</div>
</Popper>
</div>
</ClickAwayListener>

View file

@ -1,93 +0,0 @@
import { makeStyles } from '@mui/styles'
import Chip from '@mui/material/Chip'
import * as R from 'ramda'
import React from 'react'
import {
secondaryColorLighter,
secondaryColorDarker,
offErrorColor,
errorColor,
offColor,
inputFontWeight,
smallestFontSize,
inputFontFamily,
spacer
} from 'src/styling/variables'
import { onlyFirstToUpper } from 'src/utils/string'
import typographyStyles from './typography/styles'
const { label1 } = typographyStyles
const colors = {
running: secondaryColorDarker,
notRunning: offErrorColor
}
const backgroundColors = {
running: secondaryColorLighter,
notRunning: errorColor
}
const styles = {
uptimeContainer: {
display: 'inline-block',
minWidth: 104,
margin: [[0, 20]]
},
name: {
extend: label1,
paddingLeft: 4,
color: offColor
}
}
const useStyles = makeStyles(styles)
const useChipStyles = makeStyles({
root: {
borderRadius: spacer / 2,
marginTop: spacer / 2,
marginRight: spacer / 4,
marginBottom: spacer / 2,
marginLeft: spacer / 4,
height: spacer * 3,
backgroundColor: ({ type }) => backgroundColors[type]
},
label: {
fontSize: smallestFontSize,
fontWeight: inputFontWeight,
fontFamily: inputFontFamily,
padding: [[spacer / 2, spacer]],
color: ({ type }) => colors[type]
}
})
const Uptime = ({ process, ...props }) => {
const classes = useStyles()
const uptime = time => {
if (time < 60) return `${time}s`
if (time < 3600) return `${Math.floor(time / 60)}m`
if (time < 86400) return `${Math.floor(time / 60 / 60)}h`
return `${Math.floor(time / 60 / 60 / 24)}d`
}
return (
<div className={classes.uptimeContainer}>
<div className={classes.name}>{R.toLower(process.name)}</div>
<Chip
label={
process.state === 'RUNNING'
? `Running for ${uptime(process.uptime)}`
: onlyFirstToUpper(process.state)
}
classes={useChipStyles({
type: process.state === 'RUNNING' ? 'running' : 'notRunning'
})}
/>
</div>
)
}
export default Uptime

View file

@ -1,5 +1,4 @@
import { makeStyles } from '@mui/styles'
import classnames from 'classnames'
import IconButton from '@mui/material/IconButton'
import { useFormikContext, Form, Formik, Field as FormikField } from 'formik'
import * as R from 'ramda'
import React, { useState, memo } from 'react'
@ -11,13 +10,10 @@ import FalseIcon from 'src/styling/icons/table/false.svg?react'
import TrueIcon from 'src/styling/icons/table/true.svg?react'
import * as Yup from 'yup'
import { Link, IconButton } from 'src/components/buttons'
import { Link } from 'src/components/buttons'
import { RadioGroup } from 'src/components/inputs/formik'
import { Table, TableBody, TableRow, TableCell } from 'src/components/table'
import { booleanPropertiesTableStyles } from './BooleanPropertiesTable.styles'
const useStyles = makeStyles(booleanPropertiesTableStyles)
import SvgIcon from '@mui/material/SvgIcon'
const BooleanCell = ({ name }) => {
const { values } = useFormikContext()
@ -26,6 +22,8 @@ const BooleanCell = ({ name }) => {
const BooleanPropertiesTable = memo(
({ title, disabled, data, elements, save, forcedEditing = false }) => {
const [editing, setEditing] = useState(forcedEditing)
const initialValues = R.fromPairs(
elements.map(it => [it.name, data[it.name]?.toString() ?? 'false'])
)
@ -39,10 +37,6 @@ const BooleanPropertiesTable = memo(
)
)
const [editing, setEditing] = useState(forcedEditing)
const classes = useStyles()
const innerSave = async values => {
const toBoolean = (num, _) => R.equals(num, 'true')
save(R.mapObjIndexed(toBoolean, R.filter(R.complement(R.isNil))(values)))
@ -54,7 +48,7 @@ const BooleanPropertiesTable = memo(
{ display: 'No', code: 'false' }
]
return (
<div className={classes.booleanPropertiesTableWrapper}>
<div className="flex w-sm flex-col ">
<Formik
validateOnBlur={false}
validateOnChange={false}
@ -65,16 +59,16 @@ const BooleanPropertiesTable = memo(
{({ resetForm }) => {
return (
<Form>
<div className={classes.rowWrapper}>
<div className="flex items-center">
<H4>{title}</H4>
{editing ? (
<div className={classes.rightAligned}>
<div className="ml-auto">
<Link type="submit" color="primary">
Save
</Link>
<Link
type="reset"
className={classes.rightLink}
className="ml-5"
onClick={() => {
resetForm()
setEditing(false)
@ -85,34 +79,30 @@ const BooleanPropertiesTable = memo(
</div>
) : (
<IconButton
className={classes.transparentButton}
onClick={() => setEditing(true)}
size="large">
{disabled ? <EditIconDisabled /> : <EditIcon />}
className="my-auto mx-3"
onClick={() => setEditing(true)}>
<SvgIcon fontSize="small">
{disabled ? <EditIconDisabled /> : <EditIcon />}
</SvgIcon>
</IconButton>
)}
</div>
<PromptWhenDirty />
<Table className={classes.fillColumn}>
<TableBody className={classes.fillColumn}>
<Table className="w-full">
<TableBody className="w-full">
{elements.map((it, idx) => (
<TableRow
key={idx}
size="sm"
className={classes.tableRow}>
<TableCell className={classes.leftTableCell}>
{it.display}
</TableCell>
<TableCell className={classes.rightTableCell}>
className="h-auto py-2 px-4 flex items-center justify-between min-h-8 even:bg-transparent odd:bg-zircon">
<TableCell className="p-0 w-50">{it.display}</TableCell>
<TableCell className="p-0 flex">
{editing && (
<FormikField
component={RadioGroup}
name={it.name}
options={radioButtonOptions}
className={classnames(
classes.radioButtons,
classes.rightTableCell
)}
className="flex flex-row m-[-15px] p-0"
/>
)}
{!editing && <BooleanCell name={it.name} />}
@ -122,11 +112,11 @@ const BooleanPropertiesTable = memo(
</TableBody>
</Table>
</Form>
);
)
}}
</Formik>
</div>
);
)
}
)

View file

@ -1,74 +0,0 @@
import baseStyles from 'src/pages/Logs.styles'
import { backgroundColor, zircon } from 'src/styling/variables'
const { fillColumn } = baseStyles
const booleanPropertiesTableStyles = {
booleanPropertiesTableWrapper: {
display: 'flex',
flexDirection: 'column',
width: 396
},
tableRow: {
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
'&:nth-child(even)': {
backgroundColor: backgroundColor
},
'&:nth-child(odd)': {
backgroundColor: zircon
},
minHeight: 32,
height: 'auto',
padding: [[8, 16, 8, 24]],
boxShadow: '0 0 0 0 rgba(0, 0, 0, 0)'
},
leftTableCell: {
display: 'flex',
alignItems: 'center',
justifyContent: 'left',
width: 200,
padding: [0]
},
rightTableCell: {
display: 'flex',
alignItems: 'center',
justifyContent: 'right',
padding: [0]
},
transparentButton: {
'& > *': {
margin: 'auto 12px'
},
'& button': {
border: 'none',
backgroundColor: 'transparent',
cursor: 'pointer'
}
},
rowWrapper: {
display: 'flex',
alignItems: 'center',
position: 'relative',
flex: 'wrap'
},
rightAligned: {
marginLeft: 'auto'
},
radioButtons: {
display: 'flex',
flexDirection: 'row',
margin: [-15]
},
rightLink: {
marginLeft: '20px'
},
fillColumn,
popoverContent: {
width: 272,
padding: [[10, 15]]
}
}
export { booleanPropertiesTableStyles }

View file

@ -1,34 +1,41 @@
import { makeStyles } from '@mui/styles'
import classnames from 'classnames'
import React, { memo } from 'react'
import styles from './ActionButton.styles'
const useStyles = makeStyles(styles)
import moduleStyles from './ActionButton.module.css'
const ActionButton = memo(
({ className, Icon, InverseIcon, color, children, ...props }) => {
const classes = useStyles()
({
className,
altTextColor,
Icon,
InverseIcon,
color,
center,
children,
...props
}) => {
const classNames = {
[classes.actionButton]: true,
[classes.primary]: color === 'primary',
[classes.secondary]: color === 'secondary',
[classes.spring]: color === 'spring',
[classes.tomato]: color === 'tomato'
[moduleStyles.actionButton]: true,
[moduleStyles.altText]: altTextColor || color !== 'primary',
[moduleStyles.primary]: color === 'primary',
[moduleStyles.secondary]: color === 'secondary',
[moduleStyles.spring]: color === 'spring',
[moduleStyles.tomato]: color === 'tomato',
[moduleStyles.center]: center
}
return (
<button className={classnames(classNames, className)} {...props}>
{Icon && (
<div className={classes.actionButtonIcon}>
<div className={moduleStyles.actionButtonIcon}>
<Icon />
</div>
)}
{InverseIcon && (
<div
className={classnames(
classes.actionButtonIcon,
classes.actionButtonIconActive
moduleStyles.actionButtonIcon,
moduleStyles.actionButtonIconActive
)}>
<InverseIcon />
</div>

View file

@ -0,0 +1,145 @@
.actionButton {
composes: p from '../typography/typography.module.css';
cursor: pointer;
border: none;
height: 28px;
outline: 0;
border-radius: 6px;
padding: 0 8px;
display: flex;
align-items: center;
}
.actionButton.altText {
color: white;
}
.primary {
background-color: var(--zircon);
}
.primary:hover {
background-color: var(--zircon2);
}
.primary:active {
background-color: var(--comet);
color: white;
}
.primary .actionButtonIconActive {
display: none;
}
.primary:active .actionButtonIcon {
display: none;
}
.primary:active .actionButtonIconActive {
display: flex;
}
.secondary {
background-color: var(--comet);
color: white;
}
.secondary:hover {
background-color: var(--comet2);
}
.secondary:active {
background-color: var(--comet3);
}
.secondary .actionButtonIcon {
display: none;
}
.secondary .actionButtonIconActive {
display: flex;
}
.secondary:active .actionButtonIcon {
display: flex;
}
.secondary:active .actionButtonIconActive {
display: none;
}
.spring {
background-color: var(--spring2);
color: white;
}
.spring:hover {
background-color: var(--spring);
}
.spring:active {
background-color: var(--spring4);
}
.spring .actionButtonIcon {
display: none;
}
.spring .actionButtonIconActive {
display: flex;
}
.spring:active .actionButtonIcon {
display: flex;
}
.spring:active .actionButtonIconActive {
display: none;
}
.tomato {
background-color: var(--tomato);
color: white;
}
.tomato:hover {
background-color: var(--tomato);
}
.tomato:active {
background-color: var(--tomato);
}
.tomato .actionButtonIcon {
display: none;
}
.tomato .actionButtonIconActive {
display: flex;
}
.tomato:active .actionButtonIcon {
display: flex;
}
.tomato:active .actionButtonIconActive {
display: none;
}
.actionButtonIcon {
display: flex;
padding-right: 7px;
}
.actionButtonIcon svg {
width: 14px;
height: 14px;
}
.center {
align-items: center;
justify-content: center;
}
.actionButtonIconActive {
}

View file

@ -1,123 +0,0 @@
import typographyStyles from 'src/components/typography/styles'
import {
white,
subheaderColor,
subheaderDarkColor,
offColor,
offDarkColor,
offDarkerColor,
secondaryColor,
secondaryColorDark,
secondaryColorDarker,
errorColor,
errorColorDark,
errorColorDarker
} from 'src/styling/variables'
const { p } = typographyStyles
const colors = (color1, color2, color3) => {
return {
backgroundColor: color1,
'&:hover': {
backgroundColor: color2
},
'&:active': {
backgroundColor: color3
}
}
}
export default {
actionButton: {
extend: p,
cursor: 'pointer',
border: 'none',
height: 28,
outline: 0,
borderRadius: 6,
padding: '0 8px',
display: 'flex',
alignItems: 'center'
},
primary: {
extend: colors(subheaderColor, subheaderDarkColor, offColor),
'&:active': {
color: white,
'& $actionButtonIcon': {
display: 'none'
},
'& $actionButtonIconActive': {
display: 'flex'
}
},
'& $actionButtonIconActive': {
display: 'none'
}
},
secondary: {
extend: colors(offColor, offDarkColor, offDarkerColor),
color: white,
'&:active': {
'& $actionButtonIcon': {
display: 'flex'
},
'& $actionButtonIconActive': {
display: 'none'
}
},
'& $actionButtonIcon': {
display: 'none'
},
'& $actionButtonIconActive': {
display: 'flex'
}
},
spring: {
extend: colors(secondaryColorDark, secondaryColor, secondaryColorDarker),
color: white,
'&:active': {
'& $actionButtonIcon': {
display: 'flex'
},
'& $actionButtonIconActive': {
display: 'none'
}
},
'& $actionButtonIcon': {
display: 'none'
},
'& $actionButtonIconActive': {
display: 'flex'
}
},
tomato: {
extend: colors(errorColorDark, errorColor, errorColorDarker),
color: white,
'&:active': {
'& $actionButtonIcon': {
display: 'flex'
},
'& $actionButtonIconActive': {
display: 'none'
}
},
'& $actionButtonIcon': {
display: 'none'
},
'& $actionButtonIconActive': {
display: 'flex'
}
},
actionButtonIcon: {
display: 'flex',
paddingRight: 7,
'@global': {
svg: {
width: 14,
height: 14
}
}
},
actionButtonIconActive: {}
}

View file

@ -1,47 +1,10 @@
import { makeStyles } from '@mui/styles'
import classnames from 'classnames'
import React, { memo } from 'react'
import AddIcon from 'src/styling/icons/button/add/zodiac.svg?react'
import typographyStyles from 'src/components/typography/styles'
import { zircon, zircon2, comet, fontColor, white } from 'src/styling/variables'
const { p } = typographyStyles
const styles = {
button: {
extend: p,
border: 'none',
backgroundColor: zircon,
cursor: 'pointer',
outline: 0,
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
width: 167,
height: 48,
color: fontColor,
'&:hover': {
backgroundColor: zircon2
},
'&:active': {
backgroundColor: comet,
color: white,
'& svg g *': {
stroke: white
}
},
'& svg': {
marginRight: 8
}
}
}
const useStyles = makeStyles(styles)
import classes from './AddButton.module.css'
const SimpleButton = memo(({ className, children, ...props }) => {
const classes = useStyles()
return (
<button className={classnames(classes.button, className)} {...props}>
<AddIcon />

View file

@ -0,0 +1,30 @@
.button {
composes: p from '../typography/typography.module.css';
border: none;
background-color: var(--zircon);
cursor: pointer;
outline: 0;
display: flex;
justify-content: center;
align-items: center;
width: 167px;
height: 48px;
color: var(--zodiac);
}
.button:hover {
background-color: var(--zircon2);
}
.button:active {
background-color: var(--comet);
color: white;
}
.button:active svg g * {
stroke: white;
}
.button svg {
margin-right: 8px;
}

View file

@ -1,25 +1,37 @@
import { makeStyles } from '@mui/styles'
import classnames from 'classnames'
import React, { memo } from 'react'
import styles from './Button.styles'
import moduleStyles from './Button.module.css'
import { spacer } from '../../styling/variables.js'
const useStyles = makeStyles(styles)
const pickSize = size => {
switch (size) {
case 'xl':
return spacer * 7.625
case 'sm':
return spacer * 4
case 'lg':
default:
return spacer * 5
}
}
const ActionButton = memo(
({
size = 'lg',
children,
className,
buttonClassName,
backgroundColor,
...props
}) => {
const classes = useStyles({ size, backgroundColor })
({ size = 'lg', children, className, buttonClassName, ...props }) => {
const height = pickSize(size)
return (
<div className={classnames(className, classes.wrapper)}>
<div className={className} style={{ height: height + height / 12 }}>
<button
className={classnames(buttonClassName, classes.button)}
className={classnames(
buttonClassName,
moduleStyles.button,
'text-white',
{
[moduleStyles.buttonSm]: size === 'sm',
[moduleStyles.buttonXl]: size === 'xl'
}
)}
{...props}>
{children}
</button>

View file

@ -0,0 +1,49 @@
.button {
composes: h3 from '../typography/typography.module.css';
border: none;
cursor: pointer;
outline: 0;
font-weight: 900;
background-color: var(--spring);
height: 40px;
padding: 0 20px;
border-radius: 10px;
box-shadow: 0 3px var(--spring4);
}
.buttonXl {
composes: h1 from '../typography/typography.module.css';
height: 61px;
border-radius: 15px
}
.buttonSm {
height: 32px;
padding: 0 16px;
border-radius: 8px
}
.button:disabled {
background-color: var(--dust);
box-shadow: none;
}
.button:disabled:hover {
background-color: var(--dust);
box-shadow: none;
}
.button:disabled:active {
margin-top: 0;
}
.button:hover {
background-color: var(--spring2);
box-shadow: 0 3px var(--spring4);
}
.button:active {
margin-top: 2px;
background-color: var(--spring2);
box-shadow: 0 2px var(--spring4);
}

View file

@ -1,79 +0,0 @@
import typographyStyles from 'src/components/typography/styles'
import {
white,
disabledColor,
secondaryColor,
secondaryColorDark,
secondaryColorDarker,
offColor,
offDarkColor,
offDarkerColor,
spacer
} from 'src/styling/variables'
const { h1, h3 } = typographyStyles
const pickSize = size => {
switch (size) {
case 'xl':
return spacer * 7.625
case 'sm':
return spacer * 4
case 'lg':
default:
return spacer * 5
}
}
export default {
wrapper: ({ size }) => {
const height = pickSize(size)
const shadowSize = height / 12
return { height: height + shadowSize / 2 }
},
button: ({ size, backgroundColor }) => {
const height = pickSize(size)
const shadowSize = size === 'xl' ? 3 : height / 12
const padding = size === 'xl' ? 20 : height / 2
const isGrey = backgroundColor === 'grey'
return {
extend: size === 'xl' ? h1 : h3,
border: 'none',
color: white,
cursor: 'pointer',
fontWeight: 900,
outline: 0,
backgroundColor: isGrey ? offDarkColor : secondaryColor,
'&:disabled': {
backgroundColor: disabledColor,
boxShadow: 'none',
'&:hover': {
backgroundColor: disabledColor,
boxShadow: 'none'
},
'&:active': {
marginTop: 0
}
},
shadowSize,
height,
padding: `0 ${padding}px`,
borderRadius: height / 4,
boxShadow: `0 ${shadowSize}px ${isGrey ? offColor : secondaryColorDark}`,
'&:hover': {
backgroundColor: isGrey ? offColor : secondaryColorDark,
boxShadow: `0 ${shadowSize}px ${
isGrey ? offDarkerColor : secondaryColorDarker
}`
},
'&:active': {
marginTop: shadowSize / 2,
backgroundColor: isGrey ? offDarkColor : secondaryColorDark,
boxShadow: `0 ${shadowSize / 2}px ${
isGrey ? offDarkerColor : secondaryColorDarker
}`
}
}
}
}

View file

@ -1,53 +0,0 @@
import { makeStyles } from '@mui/styles'
import classnames from 'classnames'
import React, { memo } from 'react'
import DeleteIcon from 'src/styling/icons/button/cancel/zodiac.svg?react'
import typographyStyles from 'src/components/typography/styles'
import { zircon, zircon2, comet, fontColor, white } from 'src/styling/variables'
const { p } = typographyStyles
const styles = {
button: {
extend: p,
border: 'none',
backgroundColor: zircon,
cursor: 'pointer',
outline: 0,
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
width: 167,
height: 48,
color: fontColor,
'&:hover': {
backgroundColor: zircon2
},
'&:active': {
backgroundColor: comet,
color: white,
'& svg g *': {
stroke: white
}
},
'& svg': {
marginRight: 8
}
}
}
const useStyles = makeStyles(styles)
const SimpleButton = memo(({ className, children, ...props }) => {
const classes = useStyles()
return (
<button className={classnames(classes.button, className)} {...props}>
<DeleteIcon />
{children}
</button>
)
})
export default SimpleButton

View file

@ -1,47 +1,19 @@
import { makeStyles } from '@mui/styles'
import classnames from 'classnames'
import React, { memo } from 'react'
import baseButtonStyles from './BaseButton.styles'
const { baseButton, primary } = baseButtonStyles
const styles = {
featureButton: {
extend: baseButton,
width: baseButton.height,
borderRadius: baseButton.height / 2,
display: 'flex',
padding: 0
},
primary,
buttonIcon: {
margin: 'auto',
'& svg': {
width: 16,
height: 16,
overflow: 'visible',
'& g': {
strokeWidth: 1.8
}
}
},
buttonIconActive: {} // required to extend primary
}
const useStyles = makeStyles(styles)
import classes from './FeatureButton.module.css'
const FeatureButton = memo(
({ className, Icon, InverseIcon, children, ...props }) => {
const classes = useStyles()
const classNames = {
[classes.featureButton]: true,
[classes.primary]: true
}
return (
<button className={classnames(classNames, className)} {...props}>
<button
className={classnames(
classes.baseButton,
classes.roundButton,
classes.primary,
className
)}
{...props}>
{Icon && (
<div className={classes.buttonIcon}>
<Icon />

View file

@ -0,0 +1,87 @@
.baseButton {
cursor: pointer;
border: none;
outline: 0;
height: 32px;
color: var(--zodiac);
}
.roundButton {
width: 32px;
border-radius: 16px;
display: flex;
padding: 0;
}
.roundButton .buttonIcon {
margin: auto;
}
.roundButton .buttonIcon svg {
width: 16px;
height: 16px;
overflow: visible;
}
.roundButton .buttonIcon svg g {
stroke-width: 2px;
}
.baseButton:active {
color: white;
}
.primary {
background-color: var(--zircon);
}
.primary:hover {
background-color: var(--zircon2);
}
.primary:active {
background-color: var(--comet);
color: white;
}
.primary .buttonIconActive {
display: none;
}
.primary:active .buttonIcon {
display: none;
}
.primary:active .buttonIconActive {
display: block;
}
.secondary {
background-color: var(--comet);
color: white;
}
.secondary:hover {
background-color: var(--comet2);
}
.secondary:active {
background-color: white;
color: var(--zodiac);
}
.secondary .buttonIcon {
display: none;
}
.secondary .buttonIconActive {
display: flex;
}
.secondary:active .buttonIcon {
display: flex;
}
.secondary:active .buttonIconActive {
display: none;
}

View file

@ -1,68 +1,9 @@
import ClickAwayListener from '@mui/material/ClickAwayListener'
import { makeStyles } from '@mui/styles'
import classnames from 'classnames'
import React, { useState, memo } from 'react'
import Popover from 'src/components/Popper'
import typographyStyles from 'src/components/typography/styles'
import {
subheaderColor,
subheaderDarkColor,
offColor
} from 'src/styling/variables'
const { info2 } = typographyStyles
const colors = (color1, color2, color3) => {
return {
backgroundColor: color1,
'&:hover': {
backgroundColor: color2
},
'&:active': {
backgroundColor: color3
}
}
}
const styles = {
idButton: {
width: 34,
height: 28,
display: 'flex',
borderRadius: 4,
padding: 0,
border: 'none',
cursor: 'pointer'
},
buttonIcon: {
margin: 'auto',
lineHeight: 1,
'& svg': {
overflow: 'visible'
}
},
closed: {
extend: colors(subheaderColor, subheaderDarkColor, offColor)
},
open: {
extend: colors(offColor, offColor, offColor)
},
popoverContent: {
extend: info2,
padding: 8,
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
borderRadius: 4,
'& img': {
height: 145,
minWidth: 200
}
}
}
const useStyles = makeStyles(styles)
import classes from './IDButton.module.css'
const IDButton = memo(
({
@ -77,8 +18,6 @@ const IDButton = memo(
}) => {
const [anchorEl, setAnchorEl] = useState(null)
const classes = useStyles()
const open = Boolean(anchorEl)
const id = open ? `simple-popper-${name}` : undefined
@ -127,7 +66,6 @@ const IDButton = memo(
open={open}
anchorEl={anchorEl}
onClose={handleClose}
arrowSize={3}
placement="top"
flip>
<div className={classes.popoverContent}>

View file

@ -0,0 +1,58 @@
.idButton {
width: 34px;
height: 28px;
display: flex;
border-radius: 4px;
padding: 0;
border: none;
cursor: pointer;
}
.buttonIcon {
margin: auto;
line-height: 1px;
}
.buttonIcon svg {
overflow: visible;
}
.closed {
background-color: var(--zircon);
}
.closed:hover {
background-color: var(--zircon2);
}
.closed:active {
background-color: var(--comet);
color: white;
}
.open {
background-color: var(--comet);
color: white;
}
.open:hover {
background-color: var(--comet2);
}
.open:active {
background-color: var(--comet3);
}
.popoverContent {
composes: info2 from '../typography/typography.module.css';
padding: 8px;
display: flex;
justify-content: center;
align-items: center;
border-radius: 4px;
}
.popoverContent img {
height: 145px;
min-width: 200px;
}

View file

@ -1,45 +0,0 @@
import IconB from '@mui/material/IconButton'
import { makeStyles } from '@mui/styles'
import React from 'react'
import { comet } from 'src/styling/variables'
const styles = {
root: ({ size }) => ({
width: size,
height: size,
'& svg': {
flex: 1
},
'&:hover': {
backgroundColor: 'inherit'
},
'&:hover rect': {
stroke: comet
},
'&:hover polygon': {
stroke: comet
},
'&:hover path': {
stroke: comet
}
})
}
const useStyles = makeStyles(styles)
const IconButton = ({ size, children, onClick, ...props }) => {
const classes = useStyles({ size })
return (
<IconB
{...props}
size="small"
classes={{ root: classes.root }}
disableRipple
onClick={onClick}>
{children}
</IconB>
)
}
export default IconButton

View file

@ -1,14 +1,10 @@
import { makeStyles } from '@mui/styles'
import classnames from 'classnames'
import React, { memo } from 'react'
import styles from './Link.styles'
const useStyles = makeStyles(styles)
import classes from './Link.module.css'
const Link = memo(
({ submit, className, children, color = 'primary', ...props }) => {
const classes = useStyles()
const classNames = {
[classes.link]: true,
[classes.primary]: color === 'primary',

View file

@ -0,0 +1,47 @@
.link {
composes: h4 from '../typography/typography.module.css';
text-decoration: none;
border: none;
background-color: transparent;
cursor: pointer;
padding: 0;
height: 100%;
}
.primary {
box-shadow: inset 0 -4px 0 0 rgba(72, 246, 148, 0.8);
}
.primary:hover {
box-shadow: none;
background-color: rgba(72, 246, 148, 0.8);
}
.secondary {
box-shadow: inset 0 -4px 0 0 rgba(255, 88, 74, 0.8);
}
.secondary:hover {
box-shadow: none;
background-color: rgba(255, 88, 74, 0.8);
color: white;
}
.noColor {
box-shadow: inset 0 -4px 0 0 rgba(255, 255, 255, 0.8);
}
.noColor:hover {
box-shadow: none;
background-color: rgba(255, 255, 255, 0.8);
}
.action {
box-shadow: inset 0 -4px 0 0 rgba(72, 246, 148, 0.8);
color: var(--zircon);
}
.action:hover {
box-shadow: none;
background-color: rgba(72, 246, 148, 0.8);
}

View file

@ -1,47 +0,0 @@
import { alpha } from '@mui/material/styles'
import typographyStyles from 'src/components/typography/styles'
import {
white,
linkPrimaryColor,
linkSecondaryColor,
zircon
} from 'src/styling/variables'
const { h4 } = typographyStyles
const color = color => ({
boxShadow: `inset 0 -4px 0 0 ${alpha(color, 0.8)}`,
'&:hover': {
boxShadow: 'none',
backgroundColor: alpha(color, 0.8)
}
})
export default {
link: {
extend: h4,
textDecoration: 'none',
border: 'none',
backgroundColor: 'transparent',
cursor: 'pointer',
padding: '0',
height: '100%'
},
primary: {
extend: color(linkPrimaryColor)
},
secondary: {
extend: color(linkSecondaryColor),
'&:hover': {
color: white
}
},
noColor: {
extend: color(white)
},
action: {
extend: color(linkPrimaryColor),
color: zircon
}
}

View file

@ -1,12 +1,9 @@
import { makeStyles } from '@mui/styles'
import classnames from 'classnames'
import React, { memo, useState } from 'react'
import { H4 } from 'src/components/typography'
import CancelIconInverse from 'src/styling/icons/button/cancel/white.svg?react'
import subpageButtonStyles from './SubpageButton.styles'
const useStyles = makeStyles(subpageButtonStyles)
import classes from './SubpageButton.module.css'
const SubpageButton = memo(
({
@ -19,11 +16,10 @@ const SubpageButton = memo(
}) => {
const [active, setActive] = useState(false)
const isActive = forceDisable ? false : active
const classes = useStyles()
const classNames = {
[classes.button]: true,
[classes.normalButton]: !isActive,
[classes.activeButton]: isActive
[classes.normal]: !isActive,
[classes.active]: isActive
}
const normalButton = <Icon className={classes.buttonIcon} />
@ -36,7 +32,7 @@ const SubpageButton = memo(
classes.buttonIconActiveLeft
)}
/>
<H4 className={classes.white}>{children}</H4>
<H4 className="text-white">{children}</H4>
<CancelIconInverse
className={classnames(
classes.buttonIcon,

View file

@ -0,0 +1,51 @@
.button {
cursor: pointer;
border: none;
outline: 0;
height: 32px;
padding: 0;
color: white;
border-radius: 16px;
background-color: var(--zircon);
}
.button:hover {
background-color: var(--zircon2);
}
.normal {
width: 32px;
}
.active {
display: flex;
flex-direction: row;
align-items: center;
background-color: var(--comet);
font-weight: bold;
padding: 0 5px;
}
.active:hover {
background-color: var(--comet);
}
.buttonIcon {
width: 16px;
height: 16px;
overflow: visible;
}
.buttonIcon g {
stroke-width: 1.8px;
}
.buttonIconActiveLeft {
margin-right: 12px;
margin-left: 4px;
}
.buttonIconActiveRight {
margin-right: 5px;
margin-left: 20px;
}

View file

@ -1,31 +1,18 @@
import { makeStyles } from '@mui/styles'
import React from 'react'
import InverseLinkIcon from 'src/styling/icons/action/external link/white.svg?react'
import LinkIcon from 'src/styling/icons/action/external link/zodiac.svg?react'
import { ActionButton } from 'src/components/buttons'
import { spacer, primaryColor } from 'src/styling/variables'
const useStyles = makeStyles({
actionButton: {
marginBottom: spacer * 4
},
actionButtonLink: {
textDecoration: 'none',
color: primaryColor
}
})
const SupportLinkButton = ({ link, label }) => {
const classes = useStyles()
return (
<a
className={classes.actionButtonLink}
className="no-underline text-zodiac"
target="_blank"
rel="noopener noreferrer"
href={link}>
<ActionButton
className={classes.actionButton}
className="mb-8"
color="primary"
Icon={LinkIcon}
InverseIcon={InverseLinkIcon}>

View file

@ -1,10 +1,8 @@
import ActionButton from './ActionButton'
import AddButton from './AddButton'
import Button from './Button'
import DeleteButton from './DeleteButton'
import FeatureButton from './FeatureButton'
import IDButton from './IDButton'
import IconButton from './IconButton'
import Link from './Link'
import SubpageButton from './SubpageButton'
import SupportLinkButton from './SupportLinkButton'
@ -14,10 +12,8 @@ export {
Link,
ActionButton,
FeatureButton,
IconButton,
IDButton,
AddButton,
SupportLinkButton,
SubpageButton,
DeleteButton
SubpageButton
}

View file

@ -1,4 +1,3 @@
import { makeStyles } from '@mui/styles'
import {
add,
differenceInMonths,
@ -18,77 +17,12 @@ import React, { useState } from 'react'
import Arrow from 'src/styling/icons/arrow/month_change.svg?react'
import RightArrow from 'src/styling/icons/arrow/month_change_right.svg?react'
import typographyStyles from 'src/components/typography/styles'
import { primaryColor, zircon } from 'src/styling/variables'
import Tile from './Tile'
const { p, label2 } = typographyStyles
const styles = {
wrapper: {
display: 'flex',
flexDirection: 'column',
alignItems: 'center'
},
button: {
outline: 'none'
},
navbar: {
extend: p,
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
width: '100%',
padding: [[15, 15]],
color: primaryColor,
'& button': {
display: 'flex',
alignItems: 'center',
padding: 0,
border: 'none',
backgroundColor: zircon,
cursor: 'pointer',
borderRadius: '50%',
width: 20,
height: 20,
position: 'relative',
overflow: 'hidden',
'& svg': {
position: 'absolute',
left: 0
}
}
},
table: {
borderCollapse: 'collapse',
width: '100%',
color: primaryColor,
'& tr': {
'&:first-child': {
paddingLeft: 5
},
'&:last-child': {
paddingRight: 5
}
},
'& th, & td': {
margin: 0,
padding: [[3, 0, 3, 0]]
},
'& th': {
extend: label2
}
}
}
const useStyles = makeStyles(styles)
import classes from './Calendar.module.css'
const Calendar = ({ minDate, maxDate, handleSelect, ...props }) => {
const [currentDisplayedMonth, setCurrentDisplayedMonth] = useState(new Date())
const classes = useStyles()
const weekdays = Array.from(Array(7)).map((_, i) =>
format('EEEEE', add({ days: i }, startOfWeek(new Date())))
)

View file

@ -0,0 +1,66 @@
.wrapper {
display: flex;
flex-direction: column;
align-items: center;
}
.button {
outline: none;
}
.navbar {
font-size: 14px;
font-family: var(--museo);
font-weight: 500;
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
padding: 15px 15px;
color: var(--zodiac);
}
.navbar button {
display: flex;
align-items: center;
padding: 0;
border: none;
background-color: var(--zircon);
cursor: pointer;
border-radius: 50%;
width: 20px;
height: 20px;
position: relative;
overflow: hidden;
}
.navbar button svg {
position: absolute;
left: 0;
}
.table {
border-collapse: collapse;
width: 100%;
color: var(--zodiac);
}
.table tr:first-child {
padding-left: 5px;
}
.table tr:last-child {
padding-right: 5px;
}
.table th,
.table td {
margin: 0;
padding: 3px 0 3px 0;
}
.table th {
font-size: 13px;
font-family: var(--museo);
font-weight: 700;
}

View file

@ -1,4 +1,3 @@
import { makeStyles } from '@mui/styles'
import classnames from 'classnames'
import { compareAsc, differenceInDays, set } from 'date-fns/fp'
import * as R from 'ramda'
@ -6,15 +5,6 @@ import React, { useState, useEffect } from 'react'
import Calendar from './Calendar'
const styles = {
wrapper: {
backgroundColor: 'white',
borderRadius: 10
}
}
const useStyles = makeStyles(styles)
const DateRangePicker = ({ minDate, maxDate, className, onRangeChange }) => {
const [from, setFrom] = useState(null)
const [to, setTo] = useState(null)
@ -23,8 +13,6 @@ const DateRangePicker = ({ minDate, maxDate, className, onRangeChange }) => {
onRangeChange(from, to)
}, [from, onRangeChange, to])
const classes = useStyles()
const handleSelect = day => {
if (
(maxDate && compareAsc(maxDate, day) > 0) ||
@ -55,7 +43,7 @@ const DateRangePicker = ({ minDate, maxDate, className, onRangeChange }) => {
return (
<>
<div className={classnames(classes.wrapper, className)}>
<div className={classnames('bg-white rounded-xl', className)}>
<Calendar
from={from}
to={to}

View file

@ -1,76 +1,15 @@
import { makeStyles } from '@mui/styles'
import classnames from 'classnames'
import React from 'react'
import typographyStyles from 'src/components/typography/styles'
import {
primaryColor,
spring2,
spring3,
disabledColor
} from 'src/styling/variables'
const { label1 } = typographyStyles
const styles = {
wrapper: {
height: 26,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
position: 'relative',
overflow: 'hidden'
},
button: {
outline: 'none',
extend: label1,
border: 'none',
cursor: 'pointer',
backgroundColor: 'transparent',
color: primaryColor,
zIndex: 2
},
lowerBound: {
left: '50%'
},
upperBound: {
right: '50%'
},
selected: {
width: 26,
height: 26,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: spring2,
borderRadius: '50%',
position: 'absolute',
zIndex: 1
},
between: {
position: 'absolute',
width: '100%',
height: '100%',
zIndex: 0,
backgroundColor: spring3
},
disabled: {
color: disabledColor,
cursor: 'default'
}
}
const useStyles = makeStyles(styles)
import classes from './Tile.module.css'
const Tile = ({
isLowerBound,
isUpperBound,
isBetween,
isDisabled,
children,
...props
children
}) => {
const classes = useStyles()
const selected = isLowerBound || isUpperBound
const rangeClasses = {

View file

@ -0,0 +1,53 @@
.wrapper {
height: 26px;
display: flex;
align-items: center;
justify-content: center;
position: relative;
overflow: hidden;
}
.button {
outline: none;
font-size: 13px;
font-family: var(--museo);
font-weight: 500;
border: none;
cursor: pointer;
background-color: transparent;
color: var(--zodiac);
z-index: 2;
}
.lowerBound {
left: 50%;
}
.upperBound {
right: 50%;
}
.selected {
width: 26px;
height: 26px;
display: flex;
align-items: center;
justify-content: center;
background-color: var(--spring2);
border-radius: 50%;
position: absolute;
z-index: 1;
}
.between {
position: absolute;
width: 100%;
height: 100%;
z-index: 0;
background-color: var(--spring3);
}
.disabled {
color: var(--dust);
cursor: default;
}

View file

@ -1,74 +0,0 @@
import { makeStyles } from '@mui/styles'
import React, { useState, memo } from 'react'
import { H4, P } from 'src/components/typography'
import EditIconDisabled from 'src/styling/icons/action/edit/disabled.svg?react'
import EditIcon from 'src/styling/icons/action/edit/enabled.svg?react'
import { Link } from 'src/components/buttons'
import { RadioGroup } from 'src/components/inputs'
import { editablePropertyStyles } from './EditableProperty.styles'
const useStyles = makeStyles(editablePropertyStyles)
const EditableProperty = memo(
({ title, prefixText, disabled, options, code, save }) => {
const [editing, setEditing] = useState(false)
const [currentCode, setCurrentCode] = useState(code)
const classes = useStyles()
const innerSave = () => {
save(currentCode)
setEditing(false)
}
const innerCancel = () => setEditing(false)
return (
<>
<div className={classes.rowWrapper}>
<H4>{title}</H4>
{editing ? (
<div className={classes.leftSpace}>
<Link
className={classes.leftSpace}
onClick={innerCancel}
color="secondary">
Cancel
</Link>
<Link
className={classes.leftSpace}
onClick={innerSave}
color="primary">
Save
</Link>
</div>
) : (
<div className={classes.transparentButton}>
<button disabled={disabled} onClick={() => setEditing(true)}>
{disabled ? <EditIconDisabled /> : <EditIcon />}
</button>
</div>
)}
</div>
{editing ? (
<RadioGroup
options={options}
value={currentCode}
onChange={event => setCurrentCode(event.target.value)}
className={classes.radioButtons}
/>
) : (
<P>
{`${prefixText} ${options
.find(it => it.code === currentCode)
.display.toLowerCase()}`}
</P>
)}
</>
)
}
)
export default EditableProperty

View file

@ -1,36 +0,0 @@
const optionsRowHeigth = 43
const editablePropertyStyles = {
transparentButton: {
'& > *': {
margin: 'auto 12px'
},
'& button': {
border: 'none',
backgroundColor: 'transparent',
cursor: 'pointer'
}
},
rowWrapper: {
display: 'flex',
alignItems: 'center',
position: 'relative',
flex: 'wrap',
height: optionsRowHeigth
},
rightAligned: {
display: 'flex',
position: 'absolute',
right: 0
},
radioButtons: {
display: 'flex',
flexDirection: 'row',
height: optionsRowHeigth
},
leftSpace: {
marginLeft: '20px'
}
}
export { editablePropertyStyles }

View file

@ -1,3 +0,0 @@
import EditableProperty from './EditableProperty'
export { EditableProperty }

View file

@ -1,4 +1,3 @@
import { makeStyles } from '@mui/styles'
import classnames from 'classnames'
import * as R from 'ramda'
import React, { useContext } from 'react'
@ -13,14 +12,6 @@ import { sentenceCase } from 'src/utils/string'
import TableCtx from './Context'
const styles = {
orderedBySpan: {
whiteSpace: 'nowrap'
}
}
const useStyles = makeStyles(styles)
const groupSecondHeader = elements => {
const doubleHeader = R.prop('doubleHeader')
const sameDoubleHeader = (a, b) => doubleHeader(a) === doubleHeader(b)
@ -46,7 +37,6 @@ const groupSecondHeader = elements => {
}
const Header = () => {
const classes = useStyles()
const {
elements,
enableEdit,
@ -79,7 +69,7 @@ const Header = () => {
idx
) => {
const orderClasses = classnames({
[classes.orderedBySpan]:
'whitespace-nowrap':
R.isNil(header) && !R.isNil(orderedBy) && R.equals(name, orderedBy.code)
})

View file

@ -1,5 +1,6 @@
import { makeStyles } from '@mui/styles'
import Switch from '@mui/material/Switch'
import IconButton from '@mui/material/IconButton'
import SvgIcon from '@mui/material/SvgIcon'
import classnames from 'classnames'
import { Field, useFormikContext } from 'formik'
import * as R from 'ramda'
@ -13,15 +14,12 @@ import DisabledEditIcon from 'src/styling/icons/action/edit/disabled.svg?react'
import EditIcon from 'src/styling/icons/action/edit/enabled.svg?react'
import StripesSvg from 'src/styling/icons/stripes.svg?react'
import { Link, IconButton } from 'src/components/buttons'
import { Link } from 'src/components/buttons'
import TableCtx from './Context'
import styles from './Row.styles'
const useStyles = makeStyles(styles)
import moduleStyles from './Row.module.css'
const ActionCol = ({ disabled, editing }) => {
const classes = useStyles()
const { values, submitForm, resetForm } = useFormikContext()
const {
editWidth,
@ -59,7 +57,7 @@ const ActionCol = ({ disabled, editing }) => {
{editing && (
<Td textAlign="center" width={actionColSize}>
<Link
className={classes.saveButton}
className={moduleStyles.saveButton}
type="submit"
color="primary"
onClick={submitForm}>
@ -76,10 +74,11 @@ const ActionCol = ({ disabled, editing }) => {
<Td textAlign="center" width={editWidth}>
<IconButton
disabled={disableEdit}
className={classes.editButton}
onClick={() => onEdit && onEdit(values.id)}
size="large">
{disableEdit ? <DisabledEditIcon /> : <EditIcon />}
size="small">
<SvgIcon>
{disableEdit ? <DisabledEditIcon /> : <EditIcon />}
</SvgIcon>
</IconButton>
</Td>
)}
@ -90,8 +89,10 @@ const ActionCol = ({ disabled, editing }) => {
onClick={() => {
setDeleteDialog(true)
}}
size="large">
{disabled ? <DisabledDeleteIcon /> : <DeleteIcon />}
size="small">
<SvgIcon>
{disabled ? <DisabledDeleteIcon /> : <DeleteIcon />}
</SvgIcon>
</IconButton>
<DeleteDialog
open={deleteDialog}
@ -116,7 +117,7 @@ const ActionCol = ({ disabled, editing }) => {
</Td>
)}
</>
);
)
}
const ECol = ({ editing, focus, config, extraPaddingRight, extraPadding }) => {
@ -151,11 +152,6 @@ const ECol = ({ editing, focus, config, extraPaddingRight, extraPadding }) => {
const isEditing = editing && isEditable(editable)
const isField = !bypassField
const classes = useStyles({
textAlign: isEditing ? editingAlign : textAlign,
size
})
const innerProps = {
fullWidth: true,
autoFocus: focus,
@ -165,16 +161,20 @@ const ECol = ({ editing, focus, config, extraPaddingRight, extraPadding }) => {
...inputProps
}
const newAlign = isEditing ? editingAlign : textAlign
const justifyContent = newAlign === 'right' ? 'flex-end' : newAlign
const style = suffix || prefix ? { justifyContent } : {}
return (
<div className={classes.fields}>
<div className={moduleStyles.fields}>
{fields.map((f, idx) => (
<Td
style={style}
key={idx}
className={{
[classes.extraPaddingRight]: extraPaddingRight,
[classes.extraPadding]: extraPadding,
[classes.withSuffix]: suffix,
[classes.withPrefix]: prefix
[moduleStyles.extraPaddingRight]: extraPaddingRight,
[moduleStyles.extraPadding]: extraPadding,
'flex items-center': suffix || prefix
}}
width={width}
size={size}
@ -182,7 +182,7 @@ const ECol = ({ editing, focus, config, extraPaddingRight, extraPadding }) => {
textAlign={textAlign}>
{prefix && !isHidden(values) && (
<PrefixComponent
className={classes.prefix}
className={moduleStyles.prefix}
style={isEditing ? {} : textStyle(values, isEditing)}>
{typeof prefix === 'function' ? prefix(f) : prefix}
</PrefixComponent>
@ -200,7 +200,7 @@ const ECol = ({ editing, focus, config, extraPaddingRight, extraPadding }) => {
)}
{suffix && !isHidden(values) && (
<SuffixComponent
className={classes.suffix}
className={moduleStyles.suffix}
style={isEditing ? {} : textStyle(values, isEditing)}>
{suffix}
</SuffixComponent>
@ -241,8 +241,6 @@ const ERow = ({ editing, disabled, lastOfGroup, newRow }) => {
stripeWhen
} = useContext(TableCtx)
const classes = useStyles()
const shouldStripe = !editing && stripeWhen && stripeWhen(values)
const innerElements = shouldStripe ? groupStriped(elements) : elements
@ -261,7 +259,7 @@ const ERow = ({ editing, disabled, lastOfGroup, newRow }) => {
)
const classNames = {
[classes.lastOfGroup]: lastOfGroup
[moduleStyles.lastOfGroup]: lastOfGroup
}
const touchedErrors = R.pick(R.keys(touched), errors)

View file

@ -0,0 +1,29 @@
.saveButton {
margin-right: 20px;
}
.lastOfGroup {
margin-bottom: 24px;
}
.extraPadding {
padding-left: 35px;
padding-right: 30px;
}
.extraPaddingRight {
padding-right: 39px;
}
.suffix {
margin: 0 0 0 7px;
}
.prefix {
margin: 0 7px 0 0;
}
.fields {
display: flex;
flex-direction: column;
}

View file

@ -1,45 +0,0 @@
import { bySize, bold } from 'src/styling/helpers'
export default {
saveButton: {
marginRight: 20
},
lastOfGroup: {
marginBottom: 24
},
extraPadding: {
paddingLeft: 35,
paddingRight: 30
},
extraPaddingRight: {
paddingRight: 39
},
withSuffix: ({ textAlign }) => {
const justifyContent = textAlign === 'right' ? 'flex-end' : textAlign
return {
display: 'flex',
alignItems: 'center',
justifyContent
}
},
suffix: {
margin: [[0, 0, 0, 7]]
},
withPrefix: ({ textAlign }) => {
const justifyContent = textAlign === 'right' ? 'flex-end' : textAlign
return {
display: 'flex',
alignItems: 'center',
justifyContent
}
},
prefix: {
margin: [[0, 7, 0, 0]]
},
size: ({ size }) => bySize(size),
bold,
fields: {
display: 'flex',
flexDirection: 'column'
}
}

View file

@ -1,4 +1,3 @@
import { makeStyles } from '@mui/styles'
import { Form, Formik } from 'formik'
import * as R from 'ramda'
import React, { useState, useEffect } from 'react'
@ -13,13 +12,11 @@ import { AddButton } from 'src/components/buttons/index'
import TableCtx from './Context'
import Header from './Header'
import ERow from './Row'
import styles from './Table.styles'
import classes from './Table.module.css'
const ACTION_COL_SIZE = 87
const DEFAULT_COL_SIZE = 100
const useStyles = makeStyles(styles)
const getWidth = R.compose(
R.reduce(R.add)(0),
R.map(it => it.width ?? DEFAULT_COL_SIZE)
@ -129,8 +126,6 @@ const ETable = ({
const width = getWidth(elements) + actionColSize
const classes = useStyles({ width })
const showButtonOnEmpty = !data.length && enableCreate && !adding
const canAdd = !forceDisable && !editingId && !disableAdd && !adding
const showTable = adding || data.length !== 0
@ -162,7 +157,7 @@ const ETable = ({
return (
<TableCtx.Provider value={ctxValue}>
<div className={classes.wrapper}>
<div style={{ width }}>
{showButtonOnEmpty && canAdd && (
<AddButton onClick={addField}>{createText}</AddButton>
)}

View file

@ -0,0 +1,16 @@
.addLink {
margin-left: auto;
}
.title {
margin: 0;
color: var(--comet);
}
.outerHeader {
min-height: 16px;
margin-bottom: 24px;
display: flex;
justify-content: space-between;
align-items: center;
}

View file

@ -1,21 +0,0 @@
import { offColor } from 'src/styling/variables'
export default {
wrapper: ({ width }) => ({
width: width
}),
addLink: {
marginLeft: 'auto'
},
title: {
margin: 0,
color: offColor
},
outerHeader: {
minHeight: 16,
marginBottom: 24,
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center'
}
}

View file

@ -1,14 +1,10 @@
import Card from '@mui/material/Card'
import CardContent from '@mui/material/CardContent'
import { makeStyles } from '@mui/styles'
import classnames from 'classnames'
import React from 'react'
import { Link } from 'src/components/buttons'
import styles from './Table.styles'
const useStyles = makeStyles(styles)
import styles from './Table.module.css'
const Table = ({ children, className, ...props }) => (
<div className={classnames(className)} {...props}>
@ -17,17 +13,12 @@ const Table = ({ children, className, ...props }) => (
)
const THead = ({ children, className }) => {
const classes = useStyles()
return <div className={classnames(className, classes.header)}>{children}</div>
return <div className={classnames(className, styles.header)}>{children}</div>
}
const TDoubleLevelHead = ({ children, className }) => {
const classes = useStyles()
return (
<div className={classnames(className, classes.doubleHeader)}>
{children}
</div>
<div className={classnames(className, styles.doubleHeader)}>{children}</div>
)
}
@ -36,6 +27,7 @@ const TBody = ({ children, className }) => {
}
const Td = ({
style = {},
children,
header,
className,
@ -45,15 +37,28 @@ const Td = ({
textAlign,
action
}) => {
const classes = useStyles({ textAlign, width, size })
const classNames = {
[classes.td]: true,
[classes.tdHeader]: header,
[classes.actionCol]: action,
[classes.size]: !header,
[classes.bold]: !header && bold
const inlineStyle = {
...style,
width,
textAlign,
fontSize: size === 'sm' ? '14px' : size === 'lg' ? '24px' : ''
}
return <div data-cy={`td-${header}`} className={classnames(className, classNames)}>{children}</div>
const cssClasses = {
[styles.td]: !header,
[styles.tdHeader]: header,
'font-bold': !header && (bold || size === 'lg'),
[styles.actionCol]: action
}
return (
<div
data-cy={`td-${header}`}
className={classnames(className, cssClasses)}
style={inlineStyle}>
{children}
</div>
)
}
const Th = ({ children, ...props }) => {
@ -65,11 +70,11 @@ const Th = ({ children, ...props }) => {
}
const ThDoubleLevel = ({ title, children, className, width }) => {
const classes = useStyles({ width })
return (
<div className={classnames(className, classes.thDoubleLevel)}>
<div>{title}</div>
<div
className={classnames(className, styles.thDoubleLevel)}
style={{ width }}>
<div className={styles.thDoubleLevelFirst}>{title}</div>
<div>{children}</div>
</div>
)
@ -85,23 +90,30 @@ const Tr = ({
size,
newRow
}) => {
const classes = useStyles({ size })
const cardClasses = { root: classes.cardContentRoot }
const classNames = {
[classes.tr]: true,
[classes.trError]: error,
[classes.card]: true,
[classes.trAdding]: newRow,
className
const inlineStyle = {
minHeight: size === 'sm' ? '34px' : size === 'lg' ? '68px' : '48px'
}
const cardClasses = {
[styles.card]: true,
[styles.trError]: error,
[styles.trAdding]: newRow
}
const mainContentClasses = {
[styles.mainContent]: true,
[styles.sizeSm]: size === 'sm',
[styles.sizeLg]: size === 'lg'
}
return (
<>
<Card className={classnames(classNames, className)} onClick={onClick}>
<CardContent classes={cardClasses}>
<div className={classes.mainContent}>{children}</div>
<Card className={classnames(className, cardClasses)} onClick={onClick}>
<CardContent className={styles.cardContentRoot}>
<div className={classnames(mainContentClasses)} style={inlineStyle}>
{children}
</div>
{error && shouldShowError && (
<div className={classes.errorContent}>{errorMessage}</div>
<div className={styles.errorContent}>{errorMessage}</div>
)}
</CardContent>
</Card>

View file

@ -0,0 +1,106 @@
.header {
composes: tl2 from '../typography/typography.module.css';
background-color: var(--zodiac);
height: 32px;
text-align: left;
color: white;
display: flex;
align-items: center;
}
.doubleHeader {
composes: tl2 from '../typography/typography.module.css';
background-color: var(--zodiac);
height: 64px;
color: white;
display: table-row;
}
.thDoubleLevel {
display: table-cell;
}
.thDoubleLevelFirst {
composes: label1 from '../typography/typography.module.css';
margin: 0 10px;
font-weight: 700;
display: flex;
justify-content: center;
align-items: center;
background-color: var(--comet);
color: white;
border-radius: 0 0 8px 8px;
height: 28px;
}
.thDoubleLevel > :last-child {
padding: 0 11px;
display: table-cell;
vertical-align: middle;
height: 36px;
}
.cellDoubleLevel {
display: flex;
padding: 0 16px;
}
.td {
padding: 1px 24px 0 24px;
}
.tdHeader {
vertical-align: middle;
display: table-cell;
padding: 0 24px;
}
.trError {
background-color: var(--misty-rose);
}
.trAdding {
background-color: var(--spring3);
}
.mainContent {
display: flex;
align-items: center;
}
.cardContentRoot {
margin: 0;
padding: 0;
}
.cardContentRoot:last-child {
padding: 0;
}
.card {
composes: p from '../typography/typography.module.css';
margin: 4px 0 0 0;
width: 100%;
box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.08);
}
.card:before {
height: 0;
}
.actionCol {
margin-left: auto;
}
.errorContent {
padding: 12px 0 12px 24px;
color: var(--tomato);
}
.sizeSm {
min-height: 34px;
}
.sizeLg {
min-height: 68px;
}

View file

@ -1,114 +0,0 @@
import typographyStyles from 'src/components/typography/styles'
import { bySize, bold } from 'src/styling/helpers'
import {
tableHeaderColor,
tableHeaderHeight,
tableErrorColor,
tableSuccessColor,
spacer,
white,
tableDoubleHeaderHeight,
offColor,
errorColor
} from 'src/styling/variables'
const { tl2, p, label1 } = typographyStyles
export default {
size: ({ size }) => bySize(size),
bold,
header: {
extend: tl2,
backgroundColor: tableHeaderColor,
height: tableHeaderHeight,
textAlign: 'left',
color: white,
display: 'flex',
alignItems: 'center'
},
doubleHeader: {
extend: tl2,
backgroundColor: tableHeaderColor,
height: tableDoubleHeaderHeight,
color: white,
display: 'table-row'
},
thDoubleLevel: ({ width }) => ({
width,
display: 'table-cell',
'& > :first-child': {
margin: [[0, 10]],
extend: label1,
fontWeight: 700,
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: offColor,
color: white,
borderRadius: [[0, 0, 8, 8]],
height: 28
},
'& > :last-child': {
padding: [[0, 11]],
display: 'table-cell',
verticalAlign: 'middle',
height: tableDoubleHeaderHeight - 28
}
}),
cellDoubleLevel: {
display: 'flex',
padding: [[0, spacer * 2]]
},
td: ({ textAlign, width }) => ({
width,
padding: [[1, spacer * 3, 0, spacer * 3]],
textAlign
}),
tdHeader: {
verticalAlign: 'middle',
display: 'table-cell',
padding: [[0, spacer * 3]]
},
trError: {
backgroundColor: tableErrorColor
},
trAdding: {
backgroundColor: tableSuccessColor
},
mainContent: ({ size }) => {
const sizes = {
sm: 34,
lg: 68
}
const minHeight = sizes[size] || 48
return {
display: 'flex',
alignItems: 'center',
minHeight
}
},
// mui-overrides
cardContentRoot: {
margin: 0,
padding: 0,
'&:last-child': {
padding: 0
}
},
card: {
extend: p,
'&:before': {
height: 0
},
margin: [[4, 0, 0, 0]],
width: '100%',
boxShadow: [[0, 0, 4, 0, 'rgba(0, 0, 0, 0.08)']]
},
actionCol: {
marginLeft: 'auto'
},
errorContent: {
padding: [[12, 0, 12, 24]],
color: errorColor
}
}

View file

@ -1,13 +1,11 @@
import Box from '@mui/material/Box'
import MAutocomplete from '@mui/material/Autocomplete'
import classnames from 'classnames'
import sort from 'match-sorter'
import * as R from 'ramda'
import React from 'react'
import { HoverableTooltip } from 'src/components/Tooltip'
import { P } from 'src/components/typography'
import { errorColor, orangeYellow, spring4 } from 'src/styling/variables'
import TextInput from './TextInput'
const Autocomplete = ({
@ -82,7 +80,6 @@ const Autocomplete = ({
openOnFocus
autoHighlight
disableClearable
ChipProps={{ onDelete: null }}
clearOnEscape
isOptionEqualToValue={R.eqProps(valueProp)}
{...props}
@ -104,39 +101,30 @@ const Autocomplete = ({
if (!props.warning && !props.warningMessage)
return <li {...iprops}>{R.path([labelProp])(props)}</li>
const warningColors = {
clean: spring4,
partial: orangeYellow,
important: errorColor
const className = {
'flex w-4 h-4 rounded-md': true,
'bg-spring4': props.warning === 'clean',
'bg-orange-yellow': props.warning === 'partial',
'bg-tomato': props.warning === 'important'
}
const hoverableElement = (
<Box
width={18}
height={18}
borderRadius="6px"
bgcolor={warningColors[props.warning]}
/>
)
const hoverableElement = <div className={classnames(className)} />
return (
<li {...iprops}>
<Box
width="100%"
display="flex"
flexDirection="row"
justifyContent="space-between"
alignItems="center">
<Box>{R.path([labelProp])(props)}</Box>
<div className="flex flex-row justify-between items-center w-full">
<div className="flex">{R.path([labelProp])(props)}</div>
<HoverableTooltip parentElements={hoverableElement} width={250}>
<P>{props.warningMessage}</P>
</HoverableTooltip>
</Box>
</div>
</li>
)
}}
/>
)
slotProps={{
chip: { onDelete: null }
}} />
);
}
export default Autocomplete

View file

@ -1,60 +1,22 @@
import Checkbox from '@mui/material/Checkbox'
import { makeStyles } from '@mui/styles'
import CheckBoxIcon from '@mui/icons-material/CheckBox'
import CheckBoxOutlineBlankIcon from '@mui/icons-material/CheckBoxOutlineBlank'
import React from 'react'
import { Label2, Info3 } from 'src/components/typography'
import WarningIcon from 'src/styling/icons/warning-icon/comet.svg?react'
import {
fontSize2,
fontSize3,
secondaryColor,
offColor
} from 'src/styling/variables'
const useStyles = makeStyles({
root: {
color: secondaryColor,
'&.Mui-checked': {
color: secondaryColor
}
},
checked: {},
checkBoxLabel: {
display: 'flex'
},
wrapper: {
display: 'flex',
alignItems: 'center',
'& > svg': {
marginRight: 10
}
},
message: {
display: 'flex',
alignItems: 'center',
color: offColor,
margin: 0,
whiteSpace: 'break-spaces'
}
})
import { fontSize2, fontSize3 } from 'src/styling/variables'
const CheckboxInput = ({ name, onChange, value, settings, ...props }) => {
const { enabled, label, disabledMessage, rightSideLabel } = settings
const classes = useStyles()
return (
<>
{enabled ? (
<div className={classes.checkBoxLabel}>
<div className="flex">
{!rightSideLabel && <Label2>{label}</Label2>}
<Checkbox
id={name}
classes={{
root: classes.root,
checked: classes.checked
}}
onChange={onChange}
value={value}
checked={value}
@ -70,9 +32,11 @@ const CheckboxInput = ({ name, onChange, value, settings, ...props }) => {
{rightSideLabel && <Label2>{label}</Label2>}
</div>
) : (
<div className={classes.wrapper}>
<div className="flex items-center gap-2">
<WarningIcon />
<Info3 className={classes.message}>{disabledMessage}</Info3>
<Info3 className="flex items-center text-comet m-0 whitespace-break-spaces">
{disabledMessage}
</Info3>
</div>
)}
</>

View file

@ -1,14 +1,8 @@
import { makeStyles } from '@mui/styles'
import classnames from 'classnames'
import React from 'react'
import OtpInput from 'react-otp-input'
import typographyStyles from 'src/components/typography/styles'
import styles from './CodeInput.styles'
const useStyles = makeStyles(styles)
const useTypographyStyles = makeStyles(typographyStyles)
import classes from './CodeInput.module.css'
const CodeInput = ({
name,
@ -19,9 +13,6 @@ const CodeInput = ({
inputStyle,
containerStyle
}) => {
const classes = useStyles()
const typographyClasses = useTypographyStyles()
return (
<OtpInput
id={name}
@ -30,19 +21,15 @@ const CodeInput = ({
numInputs={numInputs}
renderSeparator={<span> </span>}
shouldAutoFocus
containerStyle={classnames(containerStyle, classes.container)}
containerStyle={classnames(containerStyle, 'justify-evenly')}
inputStyle={classnames(
inputStyle,
classes.input,
typographyClasses.confirmationCode,
error && classes.error
'font-museo font-black text-4xl',
error && 'border-tomato'
)}
inputType={'tel'}
renderInput={(props) => (
<input
{...props}
/>
)}
renderInput={props => <input {...props} />}
/>
)
}

View file

@ -0,0 +1,14 @@
.input {
width: 3.5rem !important;
height: 5rem;
border: 2px solid;
border-color: var(--zircon);
border-radius: 4px;
}
.input:focus {
border: 2px solid;
border-color: var(--zodiac);
border-radius: 4px;
outline: none;
}

View file

@ -1,27 +0,0 @@
import { primaryColor, zircon, errorColor } from 'src/styling/variables'
const styles = {
input: {
width: '3.5rem !important',
height: '5rem',
border: '2px solid',
borderColor: zircon,
borderRadius: '4px',
'&:focus': {
border: '2px solid',
borderColor: primaryColor,
borderRadius: '4px',
'&:focus': {
outline: 'none'
}
},
},
error: {
borderColor: errorColor
},
container: {
justifyContent: 'space-evenly'
}
}
export default styles

View file

@ -1,31 +1,10 @@
import Radio from '@mui/material/Radio'
import MRadioGroup from '@mui/material/RadioGroup'
import FormControlLabel from '@mui/material/FormControlLabel'
import { makeStyles } from '@mui/styles'
import classnames from 'classnames'
import React from 'react'
import { Label1 } from 'src/components/typography'
import { offColor, secondaryColor } from 'src/styling/variables'
const styles = {
label: {
height: 16,
lineHeight: '16px',
margin: [[0, 0, 4, 0]],
paddingLeft: 3
},
subtitle: {
marginTop: -8,
marginLeft: 32,
color: offColor
},
radio: {
color: secondaryColor
}
}
const useStyles = makeStyles(styles)
const RadioGroup = ({
name,
label,
@ -36,10 +15,11 @@ const RadioGroup = ({
labelClassName,
radioClassName
}) => {
const classes = useStyles()
return (
<>
{label && <Label1 className={classes.label}>{label}</Label1>}
{label && (
<Label1 className="h-4 leading-4 m-0 mb-1 pl-1">{label}</Label1>
)}
<MRadioGroup
name={name}
value={value}
@ -51,12 +31,16 @@ const RadioGroup = ({
<FormControlLabel
disabled={option.disabled}
value={option.code}
control={<Radio className={classnames(classes.radio, radioClassName)} />}
control={
<Radio
className={classnames('text-spring', radioClassName)}
/>
}
label={option.display}
className={classnames(labelClassName)}
/>
{option.subtitle && (
<Label1 className={classes.subtitle}>{option.subtitle}</Label1>
<Label1 className="-mt-2 ml-8">{option.subtitle}</Label1>
)}
</div>
</React.Fragment>

View file

@ -1,16 +1,12 @@
import { makeStyles } from '@mui/styles'
import classnames from 'classnames'
import { useSelect } from 'downshift'
import * as R from 'ramda'
import React from 'react'
import Arrowdown from 'src/styling/icons/action/arrow/regular.svg?react'
import styles from './Select.styles'
const useStyles = makeStyles(styles)
import styles from './Select.module.css'
function Select({ className, label, items, ...props }) {
const classes = useStyles()
const {
isOpen,
@ -28,18 +24,18 @@ function Select({ className, label, items, ...props }) {
})
const selectClassNames = {
[classes.select]: true,
[classes.selectFiltered]: props.defaultAsFilter
[styles.select]: true,
[styles.selectFiltered]: props.defaultAsFilter
? true
: !R.equals(selectedItem, props.default),
[classes.open]: isOpen
[styles.open]: isOpen
}
return (
<div className={classnames(selectClassNames, className)}>
<label {...getLabelProps()}>{label}</label>
<button {...getToggleButtonProps()}>
<span className={classes.selectedItem}>{selectedItem.display}</span>
<span className={styles.selectedItem}>{selectedItem.display}</span>
<Arrowdown />
</button>
<ul {...getMenuProps()}>

View file

@ -0,0 +1,100 @@
.selectedItem {
width: 111px;
display: block;
white-space: nowrap;
overflow: hidden;
}
.select {
width: 152px;
z-index: 1;
}
.select label {
font-size: 13px;
font-family: var(--museo);
font-weight: 500;
color: var(--comet);
padding-left: 10px;
}
.select button {
font-size: 14px;
font-family: var(--museo);
font-weight: 500;
position: relative;
border: 0;
background-color: var(--zircon);
width: 152px;
padding: 6px 0 6px 12px;
border-radius: 20px;
line-height: 1.14;
text-align: left;
color: var(--comet);
cursor: pointer;
outline: 0 none;
}
.select ul {
max-height: 200px;
width: 152px;
overflow-y: auto;
position: absolute;
margin: 0;
border-top: 0;
padding: 0;
border-radius: 0 0 8px 8px;
background-color: var(--zircon);
outline: 0 none;
}
.select ul li {
font-size: 14px;
font-family: var(--museo);
font-weight: 500;
list-style-type: none;
padding: 6px 12px;
cursor: pointer;
}
.select ul li span {
width: 100%;
display: block;
overflow: hidden;
white-space: nowrap;
}
.select ul li:hover {
background-color: var(--comet);
color: white;
}
.select svg {
position: absolute;
top: 12px;
right: 14px;
fill: var(--comet);
}
.selectFiltered button {
background-color: var(--comet);
color: white;
}
.selectFiltered ul li {
background-color: var(--comet);
color: white;
}
.selectFiltered ul li:hover {
background-color: var(--zircon);
color: var(--comet);
}
.selectFiltered svg {
fill: white !important;
}
.open button {
border-radius: 8px 8px 0 0;
}

View file

@ -1,96 +0,0 @@
import { subheaderColor, offColor, white } from '../../../styling/variables'
import typographyStyles from '../../typography/styles'
const { p, label1 } = typographyStyles
const WIDTH = 152
export default {
selectedItem: {
width: WIDTH - 41,
display: 'block',
whiteSpace: 'nowrap',
overflow: 'hidden'
},
select: {
width: WIDTH,
zIndex: 1,
'& label': {
extend: label1,
color: offColor,
paddingLeft: 10
},
'& button': {
extend: p,
position: 'relative',
border: 0,
backgroundColor: subheaderColor,
width: WIDTH,
padding: [[6, 0, 6, 12]],
borderRadius: 20,
lineHeight: '1.14',
textAlign: 'left',
color: offColor,
cursor: 'pointer',
outline: '0 none'
},
'& ul': {
maxHeight: '200px',
width: WIDTH,
overflowY: 'auto',
position: 'absolute',
margin: 0,
borderTop: 0,
padding: 0,
borderRadius: [[0, 0, 8, 8]],
backgroundColor: subheaderColor,
outline: '0 none',
'& li': {
extend: p,
listStyleType: 'none',
padding: [[6, 12]],
cursor: 'pointer',
'& span': {
width: '100%',
display: 'block',
overflow: 'hidden',
whiteSpace: 'nowrap'
}
},
'& li:hover': {
backgroundColor: offColor,
color: white
}
},
'& svg': {
position: 'absolute',
top: 12,
right: 14,
fill: offColor
}
},
selectFiltered: {
'& button': {
backgroundColor: offColor,
color: white
},
'& ul': {
'& li': {
backgroundColor: offColor,
color: white
},
'& li:hover': {
backgroundColor: subheaderColor,
color: offColor
}
},
'& svg': {
fill: [[white], '!important']
}
},
open: {
'& button': {
borderRadius: [[8, 8, 0, 0]]
}
}
}

View file

@ -1,12 +1,9 @@
import { makeStyles } from '@mui/styles'
import TextField from '@mui/material/TextField'
import classnames from 'classnames'
import * as R from 'ramda'
import React, { memo } from 'react'
import styles from './TextInput.styles'
const useStyles = makeStyles(styles)
import styles from './TextInput.module.css'
const TextInput = memo(
({
@ -19,6 +16,7 @@ const TextInput = memo(
suffix,
textAlign,
width,
inputClasses,
// lg or sm
size,
bold,
@ -26,11 +24,23 @@ const TextInput = memo(
InputProps,
...props
}) => {
const classes = useStyles({ textAlign, width, size })
const isTextFilled = !error && !R.isNil(value) && !R.isEmpty(value)
const filled = isPasswordFilled || isTextFilled
const inputClasses = {
[classes.bold]: bold
const style = {
width: width,
textAlign: textAlign
}
const sizeClass =
size === 'sm'
? styles.sizeSm
: size === 'lg'
? styles.sizeLg
: styles.size
const divClass = {
[styles.bold]: bold
}
return (
@ -41,17 +51,22 @@ const TextInput = memo(
onBlur={onBlur}
error={error}
value={value}
classes={{ root: classes.root }}
className={className}
InputProps={{
className: classnames(inputClasses),
classes: {
root: classes.size,
underline: filled ? classes.underline : null
style={style}
{...props}
slotProps={{
input: {
className: classnames(divClass),
classes: {
root: sizeClass,
underline: filled ? styles.underline : null,
input: inputClasses
},
...InputProps
},
...InputProps
}}
{...props} />
htmlInput: { style: { textAlign } }
}} />
);
}
)

View file

@ -0,0 +1,24 @@
.size {
font-size: 16px;
}
.sizeSm {
font-size: 14px;
}
.sizeLg {
font-size: 24px;
font-weight: 700;
}
.bold {
font-weight: 700;
}
.underline:before {
border-bottom-color: var(--spring);
}
.underline:hover:not(.Mui-disabled)::before {
border-bottom-color: var(--spring);
}

View file

@ -1,24 +0,0 @@
import { bySize, bold } from 'src/styling/helpers'
import { secondaryColor } from 'src/styling/variables'
export default {
size: ({ size }) => ({
marginTop: size === 'lg' ? 0 : 2,
...bySize(size)
}),
bold,
root: ({ width, textAlign }) => ({
width,
'& input': {
textAlign
}
}),
underline: {
'&:before': {
borderBottomColor: secondaryColor
},
'&:hover:not(.Mui-disabled)::before': {
borderBottomColor: secondaryColor
}
}
}

View file

@ -1,38 +1,8 @@
import { makeStyles } from '@mui/styles'
import MUIToggleButtonGroup from '@mui/material/ToggleButtonGroup'
import ToggleButton from '@mui/material/ToggleButton'
import React from 'react'
import { H4, P } from 'src/components/typography'
import { backgroundColor, comet } from 'src/styling/variables'
const styles = {
noTextTransform: {
textTransform: 'none'
},
flex: {
display: 'flex',
alignItems: 'center',
justifyContent: 'start',
width: '90%',
overflow: 'hidden',
maxHeight: 80
},
buttonTextContent: {
marginLeft: 32,
textTransform: 'none',
textAlign: 'left'
},
button: {
backgroundColor: backgroundColor,
marginBottom: 16
},
paragraph: {
color: comet,
marginTop: -10
}
}
const useStyles = makeStyles(styles)
const ToggleButtonGroup = ({
name,
orientation = 'vertical',
@ -42,7 +12,6 @@ const ToggleButtonGroup = ({
size = 'small',
...props
}) => {
const classes = useStyles()
return (
<MUIToggleButtonGroup
size={size}
@ -54,15 +23,15 @@ const ToggleButtonGroup = ({
{props.options.map(option => {
return (
<ToggleButton
className={classes.button}
className="bg-ghost"
value={option.value}
aria-label={option.value}
key={option.value}>
<div className={classes.flex}>
<div className="flex items-center justify-start w-9/10 overflow-hidden max-h-20">
<option.icon />
<div className={classes.buttonTextContent}>
<div className="ml-8 normal-case text-left">
<H4>{option.title}</H4>
<P className={classes.paragraph}> {option.description}</P>
<P className="text-comet -mt-2"> {option.description}</P>
</div>
</div>
</ToggleButton>

View file

@ -1,54 +1,59 @@
import { makeStyles } from '@mui/styles'
import Chip from '@mui/material/Chip'
import classnames from 'classnames'
import React from 'react'
import Chip from 'src/components/Chip'
import { Info2, Label1, Label2 } from 'src/components/typography'
import { numberToFiatAmount } from 'src/utils/number'
import { cashboxStyles, gridStyles } from './Cashbox.styles'
import classes from './Cashbox.module.css'
import { primaryColor as zodiac, tomato } from '../../../styling/variables.js'
const cashboxClasses = makeStyles(cashboxStyles)
const gridClasses = makeStyles(gridStyles)
const colors = {
cashOut: {
empty: tomato,
full: zodiac
},
cashIn: {
empty: zodiac,
full: tomato
}
}
const Cashbox = ({
percent = 0,
cashOut = false,
width,
height,
width = 80,
height = 118,
className,
emptyPartClassName,
labelClassName,
applyColorVariant,
applyFiatBalanceAlertsStyling,
omitInnerPercentage,
isLow
}) => {
const classes = cashboxClasses({
percent,
cashOut,
width,
height,
applyColorVariant,
isLow
})
const ltHalf = percent <= 51
const showCashBox = {
[classes.fiatBalanceAlertCashbox]: applyFiatBalanceAlertsStyling,
[classes.cashbox]: !applyFiatBalanceAlertsStyling
}
const color =
colors[cashOut ? 'cashOut' : 'cashIn'][!isLow ? 'full' : 'empty']
return (
<div className={classnames(className, showCashBox)}>
<div className={classnames(emptyPartClassName, classes.emptyPart)}>
<div
style={{ height, width, backgroundColor: color, borderColor: color }}
className={classnames(className, classes.cashbox)}>
<div
className={classnames(emptyPartClassName, classes.emptyPart)}
style={{ height: `${100 - percent}%` }}>
{!omitInnerPercentage && ltHalf && (
<Label2 className={labelClassName}>{percent.toFixed(0)}%</Label2>
<Label2
style={{ color }}
className={classnames(labelClassName, classes.emptyPartP)}>
{percent.toFixed(0)}%
</Label2>
)}
</div>
<div className={classes.fullPart}>
<div style={{ backgroundColor: color }}>
{!omitInnerPercentage && !ltHalf && (
<Label2 className={labelClassName}>{percent.toFixed(0)}%</Label2>
<Label2 className={classnames(classes.fullPartP, labelClassName)}>
{percent.toFixed(0)}%
</Label2>
)}
</div>
</div>
@ -71,7 +76,6 @@ const CashIn = ({
}) => {
const percent = (100 * notes) / capacity
const isLow = percent < threshold
const classes = gridClasses()
return (
<>
<div className={classes.row}>
@ -117,7 +121,6 @@ const CashOut = ({
}) => {
const percent = (100 * notes) / capacity
const isLow = percent < threshold
const classes = gridClasses()
return (
<>
<div className={classes.row}>
@ -136,10 +139,7 @@ const CashOut = ({
<div className={classes.col2}>
<div className={classes.innerRow}>
<Info2 className={classes.noMarginText}>{notes}</Info2>
<Chip
className={classes.chip}
label={`${denomination} ${currency.code}`}
/>
<Chip label={`${denomination} ${currency.code}`} />
</div>
<div className={classes.innerRow}>
<Label1 className={classes.noMarginText}>
@ -163,7 +163,6 @@ const CashOutLite = ({
}) => {
const percent = (100 * notes) / capacity
const isLow = percent < threshold
const classes = gridClasses()
return (
<div className={classes.col}>
<Cashbox

View file

@ -0,0 +1,52 @@
.row {
display: flex;
align-items: center;
}
.col {
display: flex;
flex-direction: column;
align-items: center;
}
.innerRow {
display: flex;
justify-content: flex-start;
}
.col2 {
margin-left: 14px;
}
.noMarginText {
margin-top: 0;
margin-bottom: 0;
}
.link {
margin-top: 8px;
}
.fullPartP {
color: white;
display: inline;
}
.emptyPart {
background-color: var(--ghost);
position: relative;
}
.emptyPartP {
display: inline-block;
position: absolute;
margin: 0;
bottom: 0;
right: 0;
}
.cashbox {
border: 2px solid;
text-align: end;
display: inline-block;
}

View file

@ -1,88 +0,0 @@
import { spacer, tomato, primaryColor as zodiac } from 'src/styling/variables'
const colors = {
cashOut: {
empty: tomato,
full: zodiac
},
cashIn: {
empty: zodiac,
full: tomato
}
}
const colorPicker = ({ cashOut, applyColorVariant, isLow }) => {
return colors[cashOut ? 'cashOut' : 'cashIn'][
applyColorVariant || !isLow ? 'full' : 'empty'
]
}
const cashboxStyles = {
cashbox: {
borderColor: colorPicker,
backgroundColor: colorPicker,
height: ({ height }) => height ?? 118,
width: ({ width }) => width ?? 80,
border: '2px solid',
textAlign: 'end',
display: 'inline-block'
},
fiatBalanceAlertCashbox: {
borderColor: colorPicker,
backgroundColor: colorPicker,
height: 118,
width: 80,
border: '4px solid'
},
emptyPart: {
backgroundColor: 'white',
height: ({ percent }) => `${100 - percent}%`,
position: 'relative',
'& > p': {
color: colorPicker,
display: 'inline-block',
position: 'absolute',
margin: 0,
bottom: 0,
right: 0
}
},
fullPart: {
backgroundColor: colorPicker,
'& > p': {
color: 'white',
display: 'inline'
}
}
}
const gridStyles = {
row: {
display: 'flex',
alignItems: 'center'
},
col: {
display: 'flex',
flexDirection: 'column',
alignItems: 'center'
},
innerRow: {
display: 'flex',
justifyContent: 'flex-start'
},
col2: {
marginLeft: 14
},
noMarginText: {
marginTop: 0,
marginBottom: 0
},
link: {
marginTop: spacer
},
chip: {
margin: [[0, 0, 0, 7]]
}
}
export { cashboxStyles, gridStyles }

View file

@ -1,30 +1,19 @@
import { makeStyles } from '@mui/styles'
import classNames from 'classnames'
import React, { memo, useState } from 'react'
import { CashOut } from 'src/components/inputs/cashbox/Cashbox'
import { NumberInput } from '../base'
const useStyles = makeStyles({
flex: {
display: 'flex'
},
cashCassette: {
height: 36,
marginRight: 14
}
})
const CashCassetteInput = memo(
({ decimalPlaces, width, threshold, inputClassName, ...props }) => {
const classes = useStyles()
const { name, onChange, onBlur, value } = props.field
const { touched, errors } = props.form
const [notes, setNotes] = useState(value)
const error = !!(touched[name] && errors[name])
return (
<div className={classes.flex}>
<div className="flex">
<CashOut
className={classNames(classes.cashCassette, inputClassName)}
className={classNames('h-9 mr-4', inputClassName)}
notes={notes}
editingMode={true}
width={width}

View file

@ -1,36 +0,0 @@
import typographyStyles from 'src/components/typography/styles'
import {
fontColor,
offColor,
inputFontSize,
inputFontWeight
} from 'src/styling/variables'
const { info3 } = typographyStyles
const styles = {
masked: {
position: 'absolute',
bottom: 5,
left: 4,
color: fontColor,
fontSize: inputFontSize,
fontWeight: inputFontWeight
},
secretSpan: {
extend: info3,
color: offColor
},
hideSpan: {
display: 'none'
},
maskedInput: {
'& input': {
pointerEvents: 'none',
backgroundColor: 'transparent',
zIndex: -1
}
}
}
export { styles }

View file

@ -1,7 +1,6 @@
import { useQuery, gql } from "@apollo/client";
import { useQuery, gql } from '@apollo/client'
import ClickAwayListener from '@mui/material/ClickAwayListener'
import Popper from '@mui/material/Popper'
import { makeStyles } from '@mui/styles'
import classnames from 'classnames'
import * as R from 'ramda'
import React, { memo, useState, useEffect, useRef } from 'react'
@ -16,9 +15,7 @@ import NotificationIcon from 'src/styling/icons/menu/notification.svg?react'
import NotificationCenter from 'src/components/NotificationCenter'
import AddMachine from 'src/pages/AddMachine'
import styles from './Header.styles'
const useStyles = makeStyles(styles)
import styles from './Header.module.css'
const HAS_UNREAD = gql`
query getUnread {
@ -26,22 +23,22 @@ const HAS_UNREAD = gql`
}
`
const Subheader = ({ item, classes, user }) => {
const Subheader = ({ item, user }) => {
const [prev, setPrev] = useState(null)
return (
<div className={classes.subheader}>
<div className={classes.content}>
<div className={styles.subheader}>
<div className={styles.content}>
<nav>
<ul className={classes.subheaderUl}>
<ul className={styles.subheaderUl}>
{item.children.map((it, idx) => {
if (!R.includes(user.role, it.allowedRoles)) return <></>
return (
<li key={idx} className={classes.subheaderLi}>
<li key={idx} className={styles.subheaderLi}>
<NavLink
to={{ pathname: it.route, state: { prev } }}
className={classes.subheaderLink}
activeClassName={classes.activeSubheaderLink}
className={styles.subheaderLink}
activeClassName={styles.activeSubheaderLink}
isActive={match => {
if (!match) return false
setPrev(it.route)
@ -72,7 +69,6 @@ const Header = memo(({ tree, user }) => {
const notifCenterButtonRef = useRef()
const popperRef = useRef()
const history = useHistory()
const classes = useStyles()
useEffect(() => {
if (data?.hasUnreadNotifications) return setHasUnread(true)
@ -112,20 +108,20 @@ const Header = memo(({ tree, user }) => {
const popperOpen = Boolean(anchorEl)
const id = popperOpen ? 'notifications-popper' : undefined
return (
<header className={classes.headerContainer}>
<div className={classes.header}>
<div className={classes.content}>
<header className={styles.headerContainer}>
<div className={styles.header}>
<div className={styles.content}>
<div
onClick={() => {
setActive(false)
history.push('/dashboard')
}}
className={classnames(classes.logo, classes.logoLink)}>
className={classnames(styles.logo, styles.logoLink)}>
<Logo />
<H4 className={classes.white}>Lamassu Admin</H4>
<H4 className="text-white">Lamassu Admin</H4>
</div>
<nav className={classes.nav}>
<ul className={classes.ul}>
<nav className={styles.nav}>
<ul className={styles.ul}>
{tree.map((it, idx) => {
if (!R.includes(user.role, it.allowedRoles)) return <></>
return (
@ -137,11 +133,11 @@ const Header = memo(({ tree, user }) => {
setActive(it)
return true
}}
className={classnames(classes.link, classes.whiteLink)}
activeClassName={classes.activeLink}>
<li className={classes.li}>
className={classnames(styles.link)}
activeClassName={styles.activeLink}>
<li className={styles.li}>
<span
className={classes.forceSize}
className={styles.forceSize}
data-forcesize={it.label}>
{it.label}
</span>
@ -151,8 +147,9 @@ const Header = memo(({ tree, user }) => {
})}
</ul>
</nav>
<div className={classes.actionButtonsContainer}>
<div className={styles.actionButtonsContainer}>
<ActionButton
altTextColor
color="secondary"
Icon={AddIcon}
InverseIcon={AddIconReverse}
@ -163,16 +160,16 @@ const Header = memo(({ tree, user }) => {
<div ref={notifCenterButtonRef}>
<button
onClick={handleClick}
className={classes.notificationIcon}>
className={styles.notificationIcon}>
<NotificationIcon />
{hasUnread && <div className={classes.hasUnread} />}
{hasUnread && <div className={styles.hasUnread} />}
</button>
<Popper
ref={popperRef}
id={id}
open={popperOpen}
anchorEl={anchorEl}
className={classes.popper}
className={styles.popper}
disablePortal={false}
placement="bottom-end"
modifiers={[
@ -187,8 +184,8 @@ const Header = memo(({ tree, user }) => {
name: 'preventOverflow',
enabled: true,
options: {
rootBoundary: 'viewport',
},
rootBoundary: 'viewport'
}
}
]}>
<NotificationCenter
@ -204,9 +201,7 @@ const Header = memo(({ tree, user }) => {
</div>
</div>
</div>
{active && active.children && (
<Subheader item={active} classes={classes} user={user} />
)}
{active && active.children && <Subheader item={active} user={user} />}
{open && <AddMachine close={() => setOpen(false)} onPaired={onPaired} />}
</header>
)

Some files were not shown because too many files have changed in this diff Show more