@mui/icons-material#Check TypeScript Examples
The following examples show how to use
@mui/icons-material#Check.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: RadioButton.tsx From frontend with MIT License | 6 votes |
function RadioButton({ checked, label, muiRadioButtonProps, value }: RadioButtonProps) {
return (
<StyledRadioButton>
<FormControlLabel
value={value}
className={`${classes.radioWrapper} ${checked ? classes.checked : null}`}
sx={checked ? {} : undefined}
label={<Typography className={classes.label}>{label}</Typography>}
control={
<Radio
icon={<div className={classes.circle} />}
checkedIcon={
<Check
color="primary"
sx={
checked
? {
width: 30,
height: 30,
border: `1px solid ${theme.palette.primary.main}`,
backgroundColor: theme.palette.primary.main,
borderRadius: theme.borders.round,
color: theme.palette.common.white,
}
: undefined
}
/>
}
{...muiRadioButtonProps}
/>
}
/>
</StyledRadioButton>
)
}
Example #2
Source File: SupportersGrid.tsx From frontend with MIT License | 5 votes |
renderCell = (params: GridRenderCellParams) =>
params.value ? <Check color="primary" /> : <Clear color="action" />
Example #3
Source File: EditableField.tsx From abrechnung with GNU Affero General Public License v3.0 | 4 votes |
export default function EditableField({
value,
onChange,
validate = undefined,
helperText = undefined,
onStopEdit = undefined,
canEdit = true,
...props
}) {
const [currentValue, setValue] = useState("");
const [editing, setEditing] = useState(false);
const [error, setError] = useState(false);
const classes = useStyles();
useEffect(() => {
setValue(value);
}, [value]);
const onSave = () => {
if (!error) {
onChange(currentValue);
setValue("");
setEditing(false);
}
};
const startEditing = () => {
setValue(value);
setEditing(true);
};
const stopEditing = () => {
setValue(value);
setEditing(false);
if (onStopEdit) {
onStopEdit();
}
};
const onValueChange = (event) => {
setValue(event.target.value);
if (validate) {
setError(!validate(event.target.value));
}
};
const onKeyUp = (key) => {
if (key.keyCode === 13) {
onSave();
}
};
return (
<div className={classes.root}>
<DisabledTextField
error={error}
value={currentValue}
disabled={!editing}
onChange={onValueChange}
className={classes.input}
helperText={error ? helperText : null}
onKeyUp={onKeyUp}
{...props}
/>
{canEdit &&
(editing ? (
<>
<IconButton color="primary" onClick={onSave}>
<Check />
</IconButton>
<IconButton color="secondary" onClick={stopEditing}>
<Close />
</IconButton>
</>
) : (
<IconButton color="primary" onClick={startEditing}>
<Edit />
</IconButton>
))}
</div>
);
}
Example #4
Source File: SessionList.tsx From abrechnung with GNU Affero General Public License v3.0 | 4 votes |
export default function SessionList() {
// TODO: fix editing functions
const [editedSessions, setEditedSessions] = useState({});
const [sessionToDelete, setSessionToDelete] = useState({
show: false,
toDelete: null,
});
const user = useRecoilValue(userData);
const sessions = user.sessions;
useTitle("Abrechnung - Sessions");
const editSession = (id) => {
if (!editedSessions.hasOwnProperty(id)) {
const newSessions = {
...editedSessions,
[id]: sessions.find((session) => session.id === id)?.name,
};
setEditedSessions(newSessions);
}
};
const stopEditSession = (id) => {
if (editedSessions.hasOwnProperty(id)) {
let newEditedSessions = { ...editedSessions };
delete newEditedSessions[id];
setEditedSessions(newEditedSessions);
}
};
const closeDeleteSessionModal = () => {
setSessionToDelete({ show: false, toDelete: null });
};
const performRename = (id) => {
if (editedSessions.hasOwnProperty(id)) {
renameSession({
sessionID: id,
name: editedSessions[id],
}).catch((err) => {
toast.error(err);
});
stopEditSession(id);
}
};
const openDeleteSessionModal = (id) => {
setSessionToDelete({ show: true, toDelete: id });
};
const confirmDeleteSession = () => {
if (sessionToDelete.toDelete !== null) {
deleteSession({ sessionID: sessionToDelete.toDelete }).catch((err) => {
toast.error(err);
});
setSessionToDelete({ show: false, toDelete: null });
}
};
const handleEditChange = (id, value) => {
const newEditedSessions = { ...editedSessions, [id]: value };
setEditedSessions(newEditedSessions);
};
const onKeyUp = (id) => (key) => {
if (key.keyCode === 13) {
performRename(id);
}
};
return (
<MobilePaper>
<Typography component="h3" variant="h5">
Login Sessions
</Typography>
<List>
{sessions.map((session) => {
if (editedSessions.hasOwnProperty(session.id)) {
return (
<ListItem key={session.id}>
<TextField
margin="normal"
variant="standard"
fullWidth
onKeyUp={onKeyUp(session.id)}
value={editedSessions[session.id]}
onChange={(event) => handleEditChange(session.id, event.target.value)}
/>
<ListItemSecondaryAction>
<Button onClick={() => performRename(session.id)}>
<Check />
</Button>
<Button onClick={() => stopEditSession(session.id)}>
<Close />
</Button>
</ListItemSecondaryAction>
</ListItem>
);
} else {
return (
<ListItem key={session.id}>
<ListItemText
primary={session.name}
secondary={
<>
<span>
Valid until{" "}
{DateTime.fromISO(session.valid_until).toLocaleString(
DateTime.DATETIME_FULL
) && "indefinitely"}
,{" "}
</span>
<span>
Last seen on{" "}
{DateTime.fromISO(session.last_seen).toLocaleString(
DateTime.DATETIME_FULL
)}
</span>
</>
}
/>
<ListItemSecondaryAction>
<IconButton onClick={() => editSession(session.id)}>
<Edit />
</IconButton>
<IconButton onClick={() => openDeleteSessionModal(session.id)}>
<Delete />
</IconButton>
</ListItemSecondaryAction>
</ListItem>
);
}
})}
</List>
<Dialog open={sessionToDelete.show} onClose={closeDeleteSessionModal}>
<DialogTitle>Delete Session?</DialogTitle>
<DialogContent>
<DialogContentText>
{sessionToDelete.toDelete !== null
? `Are you sure you want to delete session ${
sessions.find((session) => session.id === sessionToDelete.toDelete)?.name
}`
: null}
</DialogContentText>
</DialogContent>
<DialogActions>
<Button color="secondary" onClick={confirmDeleteSession}>
Yes pls
</Button>
<Button color="primary" onClick={closeDeleteSessionModal}>
No
</Button>
</DialogActions>
</Dialog>
</MobilePaper>
);
}
Example #5
Source File: AuthButton.tsx From multi-downloader-nx with MIT License | 4 votes |
AuthButton: React.FC = () => {
const snackbar = useSnackbar();
const [open, setOpen] = React.useState(false);
const [username, setUsername] = React.useState('');
const [password, setPassword] = React.useState('');
const [usernameError, setUsernameError] = React.useState(false);
const [passwordError, setPasswordError] = React.useState(false);
const messageChannel = React.useContext(messageChannelContext);
const [loading, setLoading] = React.useState(false);
const [error, setError] = React.useState<Error|undefined>(undefined);
const [authed, setAuthed] = React.useState(false);
const checkAuth = async () => {
console.log(await messageChannel?.checkToken());
setAuthed((await messageChannel?.checkToken())?.isOk ?? false);
}
React.useEffect(() => { checkAuth() }, []);
const handleSubmit = async () => {
if (!messageChannel)
throw new Error('Invalid state'); //The components to confirm only render if the messageChannel is not undefinded
if (username.trim().length === 0)
return setUsernameError(true);
if (password.trim().length === 0)
return setPasswordError(true);
setUsernameError(false);
setPasswordError(false);
setLoading(true);
const res = await messageChannel.auth({ username, password });
if (res.isOk) {
setOpen(false);
snackbar.enqueueSnackbar('Logged in', {
variant: 'success'
});
setUsername('');
setPassword('');
} else {
setError(res.reason);
}
await checkAuth();
setLoading(false);
}
return <Require value={messageChannel}>
<Dialog open={open}>
<Dialog open={!!error}>
<DialogTitle>Error during Authentication</DialogTitle>
<DialogContentText>
{error?.name}
{error?.message}
</DialogContentText>
<DialogActions>
<Button onClick={() => setError(undefined)}>Close</Button>
</DialogActions>
</Dialog>
<DialogTitle sx={{ flexGrow: 1 }}>Authentication</DialogTitle>
<DialogContent>
<DialogContentText>
Here, you need to enter your username (most likely your Email) and your password.<br />
These information are not stored anywhere and are only used to authenticate with the service once.
</DialogContentText>
<TextField
error={usernameError}
helperText={usernameError ? 'Please enter something before submiting' : undefined}
margin="dense"
id="username"
label="Username"
type="text"
fullWidth
variant="standard"
value={username}
onChange={(e) => setUsername(e.target.value)}
disabled={loading}
/>
<TextField
error={passwordError}
helperText={passwordError ? 'Please enter something before submiting' : undefined}
margin="dense"
id="password"
label="Password"
type="password"
fullWidth
variant="standard"
value={password}
onChange={(e) => setPassword(e.target.value)}
disabled={loading}
/>
</DialogContent>
<DialogActions>
{loading && <CircularProgress size={30}/>}
<Button disabled={loading} onClick={() => setOpen(false)}>Close</Button>
<Button disabled={loading} onClick={() => handleSubmit()}>Authenticate</Button>
</DialogActions>
</Dialog>
<Button startIcon={authed ? <Check />: <Close />} variant="contained" onClick={() => setOpen(true)}>Authenticate</Button>
</Require>
}
Example #6
Source File: EXPCalc.tsx From genshin-optimizer with MIT License | 4 votes |
export default function EXPCalc() {
const [{ mora, level, curExp, goUnder, books, books: { advice, experience, wit } }, setState] = useDBState("ToolDisplayExpCalc", initExpCalc)
let milestoneLvl = milestone.find(lvl => lvl > level)!
let expReq = -curExp
for (let i = level; i < Math.min(milestoneLvl, levelExp.length); i++) expReq += levelExp[i]
let bookResult = calculateBooks(wit, experience, advice, expReq, goUnder) || []
let [numWit = 0, numExperience = 0, numAdvice = 0] = bookResult
let bookResultObj = { advice: numAdvice, experience: numExperience, wit: numWit }
let expFromBooks = numWit * 20000 + numExperience * 5000 + numAdvice * 1000
let moraCost = expFromBooks / 5
let expDiff = expReq - expFromBooks
let finalMora = mora - moraCost
let finalExp = expFromBooks + curExp
let finalLvl = level
for (; finalLvl < Math.min(milestoneLvl, levelExp.length); finalLvl++) {
if (levelExp[finalLvl] <= finalExp) finalExp -= levelExp[finalLvl]
else break;
}
if (finalLvl === milestoneLvl) finalExp = 0
let invalidText: Displayable = ""
if (finalMora < 0)
invalidText = <span>You don't have enough <b>Mora</b> for this operation.</span>
else if (bookResult.length === 0)
invalidText = <span>You don't have enough <b>EXP. books</b> to level to the next milestone.</span>
else if (level === 90)
invalidText = "You are at the maximum level."
return <CardDark>
<Grid container sx={{ px: 2, py: 1 }} spacing={2} >
<Grid item>
<ImgIcon src={booksData.wit.img} sx={{ fontSize: "2em" }} />
</Grid>
<Grid item flexGrow={1}>
<Typography variant="h6">Experience Calculator</Typography>
</Grid>
<Grid item>
<ButtonGroup>
<Button color="primary" disabled={!goUnder} onClick={() => setState({ goUnder: false })}>Full Level</Button>
<Button color="primary" disabled={goUnder} onClick={() => setState({ goUnder: true })}>Don't fully level</Button>
</ButtonGroup>
</Grid>
</Grid>
<Divider />
<CardContent>
<Grid container spacing={1}>
<Grid item>
<Typography>
<span>This calculator tries to calculate the amount of exp books required to get to the next milestone level. </span>
{goUnder ? "It will try to get as close to the milestone level as possible, so you can grind the rest of the exp without any waste." :
"It will try to calculate the amount of books needed to minimize as much exp loss as possible."}
</Typography>
</Grid>
<Grid item xs={6} md={3} >
<ButtonGroup sx={{ display: "flex" }}>
<TextButton>Current Level</TextButton>
<CustomNumberInputButtonGroupWrapper sx={{ flexBasis: 30, flexGrow: 1 }}>
<CustomNumberInput
value={level}
onChange={(val) => setState({ level: clamp(val, 0, 90) })}
sx={{ px: 2 }}
/>
</CustomNumberInputButtonGroupWrapper >
</ButtonGroup>
</Grid>
<Grid item xs={6} md={3} >
<ButtonGroup sx={{ display: "flex" }}>
<TextButton>Current EXP.</TextButton>
<CustomNumberInputButtonGroupWrapper sx={{ flexBasis: 30, flexGrow: 1 }}>
<CustomNumberInput
value={curExp}
onChange={(val) => setState({ curExp: clamp(val, 0, (levelExp[level] || 1) - 1) })}
endAdornment={`/${levelExp[level] || 0}`}
sx={{ px: 2 }}
/>
</CustomNumberInputButtonGroupWrapper>
</ButtonGroup>
</Grid>
<Grid item xs={6} md={3} ><CardLight>
<Box sx={{ p: 1, display: "flex", justifyContent: "space-between" }}>
<Typography>
Next Milestone Level:
</Typography>
<Typography>
<b>{milestoneLvl}</b>
</Typography>
</Box>
</CardLight></Grid>
<Grid item xs={6} md={3} ><CardLight>
<Box sx={{ p: 1, display: "flex", justifyContent: "space-between" }}>
<Typography>
EXP. to milestone:
</Typography>
<Typography>
<span><strong>{expFromBooks}</strong> / <strong>{expReq}</strong></span>
</Typography>
</Box>
</CardLight></Grid>
{Object.entries(books).map(([bookKey]) => {
return <Grid item xs={12} md={4} key={bookKey}>
<BookDisplay bookKey={bookKey} value={books[bookKey]} setValue={b => setState({ books: { ...books, [bookKey]: b } })} required={bookResultObj[bookKey]} />
</Grid>
})}
<Grid item xs={12} md={4} >
<ButtonGroup sx={{ display: "flex" }}>
<TextButton>Current Mora</TextButton>
<CustomNumberInputButtonGroupWrapper sx={{ flexBasis: 30, flexGrow: 1 }}>
<CustomNumberInput
value={mora}
onChange={(val) => setState({ mora: Math.max(val ?? 0, 0) })}
sx={{ px: 2 }}
/>
</CustomNumberInputButtonGroupWrapper>
</ButtonGroup>
</Grid>
<Grid item xs={12} md={4} ><CardLight>
<Box sx={{ p: 1, display: "flex", justifyContent: "space-between" }}>
<Typography>Mora Cost: </Typography>
<Typography><b>{moraCost}</b></Typography>
</Box>
</CardLight></Grid>
<Grid item xs={12} md={4} ><CardLight>
<Box sx={{ p: 1, display: "flex", justifyContent: "space-between" }}>
<Typography>EXP {!goUnder ? "Waste" : "Diff"}: </Typography>
<Typography><b><ColorText color={expDiff < 0 ? `error` : `success`}>{expDiff}</ColorText></b></Typography>
</Box>
</CardLight></Grid>
<Grid item xs={12} md={4} ><CardLight>
<Box sx={{ p: 1, display: "flex", justifyContent: "space-between" }}>
<Typography>Final Mora: </Typography>
<Typography><b><ColorText color={finalMora < 0 ? `error` : `success`}>{finalMora}</ColorText></b></Typography>
</Box>
</CardLight></Grid>
<Grid item xs={12} md={4} ><CardLight>
<Box sx={{ p: 1, display: "flex", justifyContent: "space-between" }}>
<Typography>Final Level: </Typography>
<Typography><b><ColorText color="success">{finalLvl}</ColorText></b></Typography>
</Box>
</CardLight></Grid>
<Grid item xs={12} md={4} ><CardLight>
<Box sx={{ p: 1, display: "flex", justifyContent: "space-between" }}>
<Typography>Final EXP: </Typography>
<Typography><b><ColorText color={finalExp < 0 ? `error` : `success`}>{finalExp}</ColorText></b></Typography>
</Box>
</CardLight></Grid>
</Grid>
</CardContent>
<Divider />
<CardContent sx={{ py: 1 }}>
<Grid container spacing={2}>
<Grid item flexGrow={1}>
{!!invalidText && <Alert variant="filled" severity="error" >{invalidText}</Alert>}
</Grid>
<Grid item xs="auto"><Button disabled={!!invalidText}
onClick={() => setState({
level: finalLvl,
curExp: finalExp,
books: objectMap(bookResultObj, (val, bookKey) => books[bookKey] - val) as any,
mora: finalMora
})}
color="success"
startIcon={<Check />}
sx={{ height: "100%" }}
>Apply</Button>
</Grid>
</Grid>
</CardContent>
</CardDark >
}
Example #7
Source File: Config.tsx From NekoMaid with MIT License | 4 votes |
configs.push({
title: lang.config.serverConfig,
component () {
const plugin = usePlugin()
const globalData = useGlobalData()
const [flag, update] = useState(0)
const [info, setInfo] = useState<Record<string, string>>({ })
const [open, setOpen] = useState(false)
const [canGetData, setCanGetData] = useState(true)
const [loading, setLoading] = useState(false)
const setValue = (field: string, value: any, isGlobal = true) => {
plugin.emit('server:set', field, value)
success()
if (isGlobal) {
(globalData as any)[field] = value
update(flag + 1)
location.reload()
}
}
const createEditButtom = (field: string, isGlobal?: boolean, isInt = true) => <IconButton
onClick={() => dialog(
{
content: lang.inputValue,
input: isInt
? {
error: true,
type: 'number',
helperText: lang.invalidValue,
validator: (it: string) => /^\d+$/.test(it) && +it >= 0
}
: { }
}).then(res => res != null && setValue(field, isInt ? parseInt(res as any) : (res || null), isGlobal))}
><Edit /></IconButton>
const infoElm: JSX.Element[] = []
for (const key in info) {
const name = (lang.config as any)[key]
infoElm.push(<ListItem key={key} sx={{ pl: 4 }}>
<ListItemText
primary={key === 'isAikarFlags' ? <Link href='https://mcflags.emc.gs' target='_blank' rel='noopener'>{name}</Link> : name}
secondary={info[key].toString()}
/>
</ListItem>)
}
return <List>
<CircularLoading loading={loading} />
<ListItem secondaryAction={globalData.canSetMaxPlayers
? createEditButtom('maxPlayers')
: undefined}>
<ListItemText primary={lang.config.maxPlayers + ': ' + globalData.maxPlayers} />
</ListItem>
<ListItem secondaryAction={createEditButtom('spawnRadius')}>
<ListItemText primary={lang.config.spawnRadius + ': ' + globalData.spawnRadius} />
</ListItem>
<ListItem secondaryAction={createEditButtom('motd', false, false)}>
<ListItemText primary={lang.config.motd} />
</ListItem>
<ListItem secondaryAction={<Switch checked={globalData.hasWhitelist} onChange={e => setValue('hasWhitelist', e.target.checked)} />}>
<ListItemText primary={lang.config.whitelist} />
</ListItem>
{canGetData && <>
<ListItemButton onClick={() => {
if (infoElm.length) setOpen(!open)
else {
setLoading(true)
plugin.emit('server:fetchInfo', (data: any) => {
setLoading(false)
if (!data) {
failed(lang.unsupported)
setCanGetData(false)
return
}
setInfo(data)
setOpen(true)
})
}
}}>
<ListItemIcon><Equalizer /></ListItemIcon>
<ListItemText primary={lang.info} />
{open ? <ExpandLess /> : <ExpandMore />}
</ListItemButton>
<Collapse in={open} timeout='auto' unmountOnExit>
<List component='div' dense disablePadding>{infoElm}</List>
</Collapse>
</>}
</List>
}
},
{
title: lang.history,
component () {
const [cur, update] = useState(0)
const list: ServerRecord[] = JSON.parse(localStorage.getItem('NekoMaid:servers') || '[]')
return <List>
{list.sort((a, b) => b.time - a.time).map(it => {
const i = it.address.indexOf('?')
return <ListItem
disablePadding
key={it.address}
secondaryAction={<IconButton edge='end' size='small' onClick={() => {
localStorage.setItem('NekoMaid:servers', JSON.stringify(list.filter(s => s.address !== it.address)))
success()
update(cur + 1)
}}><Delete /></IconButton>}
>
<ListItemButton onClick={() => {
location.hash = ''
location.search = it.address
}} dense>
<ListItemAvatar><Avatar src={it.icon} variant='rounded'><HelpOutline /></Avatar></ListItemAvatar>
<ListItemText primary={<Tooltip title={it.address.slice(i + 1)}>
<span>{it.address.slice(0, i)}</span></Tooltip>} secondary={dayjs(it.time).fromNow()} />
</ListItemButton>
</ListItem>
})}
</List>
}
},
{
title: lang.config.theme,
component () {
const color = localStorage.getItem('NekoMaid:color') || 'blue'
return <CardContent sx={{ textAlign: 'center' }}>
<Box>
<ToggleButtonGroup exclusive value={localStorage.getItem('NekoMaid:colorMode') || ''} onChange={(_, it) => {
localStorage.setItem('NekoMaid:colorMode', it)
location.reload()
}}>
<ToggleButton value='light'><Brightness7 /> {lang.config.light}</ToggleButton>
<ToggleButton value=''><SettingsBrightness /> {lang.config.system}</ToggleButton>
<ToggleButton value='dark'><Brightness4 /> {lang.config.dark}</ToggleButton>
</ToggleButtonGroup>
</Box>
<Paper sx={{ marginTop: 2, width: '176px', overflow: 'hidden', display: 'inline-block' }}>
{Object.keys(colors).slice(1, 17).map((key, i) => {
const checked = color === key
const elm = <Box
key={key}
onClick={() => {
localStorage.setItem('NekoMaid:color', key)
location.reload()
}}
sx={{
backgroundColor: (colors as any)[key][600],
width: '44px',
height: '44px',
display: 'inline-block',
cursor: 'pointer'
}}
><Check htmlColor='white' sx={{ top: '10px', position: 'relative', opacity: checked ? 1 : 0 }} /></Box>
return (i + 1) % 4 === 0 ? <React.Fragment key={key}>{elm}<br /></React.Fragment> : elm
})}
</Paper>
</CardContent>
}
})
Example #8
Source File: Dashboard.tsx From NekoMaid with MIT License | 4 votes |
Dashboard: React.FC = () => {
const plugin = usePlugin()
const { version, hasGeoIP } = useGlobalData()
const [status, setStatus] = useState<Status[]>([])
const [current, setCurrent] = useState<CurrentStatus | undefined>()
useEffect(() => {
const offSetStatus = plugin.once('dashboard:info', setStatus)
const offCurrent = plugin.on('dashboard:current', (data: CurrentStatus) => setCurrent(old => {
if (old && isEqual(old.players, data.players)) data.players = old.players
return data
}))
plugin.switchPage('dashboard')
return () => {
offSetStatus()
offCurrent()
}
}, [])
const playerCount = current?.players?.length || 0
const prev = status[status.length - 1]?.players || 0
const percent = (prev ? playerCount / prev - 1 : playerCount) * 100
const tpsColor = !current || current.tps >= 18 ? green : current.tps >= 15 ? yellow : red
return <Box sx={{ minHeight: '100%', py: 3 }}>
<Toolbar />
<Container maxWidth={false}>
<Grid container spacing={3}>
<Grid item lg={3} sm={6} xl={3} xs={12}>
<TopCard
title={lang.dashboard.version}
content={current ? version : <Skeleton animation='wave' width={150} />}
icon={<Handyman />}
color={orange[600]}
>
<Box sx={{ pt: 2, display: 'flex', alignItems: 'flex-end' }}>
{!current || current.behinds < 0
? <Refresh htmlColor={blue[900]} />
: current?.behinds === 0
? <Check htmlColor={green[900]} />
: <Update htmlColor={yellow[900]} />}
<Typography color='textSecondary' variant='caption'> {!current || current.behinds === -3
? lang.dashboard.updateChecking
: current.behinds < 0
? <Link underline='hover' color='inherit' sx={{ cursor: 'pointer' }} onClick={() => {
toast(lang.dashboard.updateChecking)
plugin.emit('dashboard:checkUpdate')
}}>{lang.dashboard.updateFailed}</Link>
: current.behinds === 0 ? lang.dashboard.updated : lang.dashboard.behinds(current.behinds)}</Typography>
</Box>
</TopCard>
</Grid>
<Grid item lg={3} sm={6} xl={3} xs={12}>
<TopCard
title={lang.dashboard.onlinePlayers}
content={current ? playerCount : <Skeleton animation='wave' width={150} />}
icon={<People />}
color={deepPurple[600]}
>
<Box sx={{ pt: 2, display: 'flex', alignItems: 'flex-end' }}>
{percent === 0 ? <Remove color='primary' /> : percent < 0 ? <ArrowDownward color='error' /> : <ArrowUpward color='success' />}
<Typography
sx={{ color: (percent === 0 ? blue : percent < 0 ? red : green)[900], mr: 1 }}
variant='body2'
>{Math.abs(percent).toFixed(0)}%</Typography>
<Typography color='textSecondary' variant='caption'>{lang.dashboard.lastHour}</Typography>
</Box>
</TopCard>
</Grid>
<Grid item lg={3} sm={6} xl={3} xs={12}>
<TopCard
title='TPS'
content={current ? (current.tps === -1 ? '?' : current.tps.toFixed(2)) : <Skeleton animation='wave' width={150} />}
icon={!current || current.tps >= 18 || current.tps === -1
? <SentimentVerySatisfied />
: current.tps >= 15 ? <SentimentSatisfied /> : <SentimentDissatisfied />}
color={tpsColor[600]}
>
<Box sx={{ pt: 2.1, display: 'flex', alignItems: 'flex-end' }}>
<Typography
sx={{ color: tpsColor[900], mr: 1 }}
variant='body2'
>{!current || current.mspt === -1 ? '?' : current.mspt.toFixed(2) + 'ms'}</Typography>
<Typography color='textSecondary' variant='caption'>{lang.dashboard.mspt}</Typography>
</Box>
</TopCard>
</Grid>
<Grid item lg={3} sm={6} xl={3} xs={12}>
<TopCard
title={lang.dashboard.uptime}
content={current ? <Uptime time={current.time} /> : <Skeleton animation='wave' width={150} />}
icon={<AccessTime />}
color={blue[600]}
>
<Box sx={{ pt: 2.7, display: 'flex', alignItems: 'center' }}>
<Typography color='textSecondary' variant='caption' sx={{ marginRight: 1 }}>{lang.dashboard.memory}</Typography>
<Tooltip title={current?.totalMemory ? prettyBytes(current.memory) + ' / ' + prettyBytes(current.totalMemory) : ''}>
<LinearProgress
variant='determinate'
value={current?.totalMemory ? current.memory / current.totalMemory * 100 : 0}
sx={{ flex: '1' }}
/>
</Tooltip>
</Box>
</TopCard>
</Grid>
<Grid item lg={8} md={12} xl={9} xs={12}>{useMemo(() => <Charts data={status} />, [status])}</Grid>
<Grid item lg={4} md={12} xl={3} xs={12}><Players players={current?.players} /></Grid>
{hasGeoIP && current?.players && typeof current.players[0] !== 'string' && <Grid item xs={12}>
<Accordion TransitionProps={{ unmountOnExit: true }} disableGutters>
<AccordionSummary expandIcon={<ExpandMore />}>
<Typography>{lang.dashboard.playersDistribution}</Typography>
</AccordionSummary>
<Divider />
<WorldMap players={current.players as Player[]} />
</Accordion>
</Grid>}
</Grid>
</Container>
</Box>
}
Example #9
Source File: DetailsModal.tsx From frontend with MIT License | 4 votes |
function DetailsModal() {
const { getDialogs } = DialogStore
const handleClose = () => DialogStore.hide()
const { t } = useTranslation()
return (
<>
{getDialogs.map(({ id, show, title, row }) => {
return (
<Dialog
key={id}
onClose={handleClose}
open={show}
maxWidth="md"
PaperProps={{ elevation: 5 }}
BackdropProps={{ style: { opacity: 0.3 } }}>
{title && <DialogTitle>{title}</DialogTitle>}
<DialogContent dividers>
{/* TODO: Extract concrete implementation and use generic one */}
<Grid item xs={12}>
<List>
<ListItem>
<ListItemText
primary={`${row.getValue(row.id, 'name')}`}
secondary={row.row.person.company}
/>
</ListItem>
<ListItem>
<ListItemText primary={row.row.person.email} secondary={row.row.person.phone} />
</ListItem>
<ListItem>{dateFormatter(row.row.createdAt)}</ListItem>
<ListItem>
<Typography variant="body2">{row.row.message || row.row.comment}</Typography>
</ListItem>
<ListItem>
<Typography variant="caption">{row.row.person.id}</Typography>
</ListItem>
{'associationMember' in row.row &&
[
'associationMember',
'benefactorCampaign',
'benefactorPlatform',
'companyOtherText',
'companySponsor',
'companyVolunteer',
'partnerBussiness',
'partnerNpo',
'partnerOtherText',
'roleAssociationMember',
'roleBenefactor',
'roleCompany',
'rolePartner',
'roleVolunteer',
'volunteerBackend',
'volunteerDesigner',
'volunteerDevOps',
'volunteerFinancesAndAccounts',
'volunteerFrontend',
'volunteerLawyer',
'volunteerMarketing',
'volunteerProjectManager',
'volunteerQa',
'volunteerSecurity',
].map((k, i) => (
<ListItem key={i}>
<ListItemText
primary={k}
secondary={row.row[k] ? <Check color="primary" /> : <Clear />}
/>
</ListItem>
))}
</List>
</Grid>
{/* */}
</DialogContent>
<DialogActions>
<Button autoFocus onClick={handleClose} color="primary">
{t('common:close')}
</Button>
</DialogActions>
</Dialog>
)
})}
</>
)
}
Example #10
Source File: Vault.tsx From NekoMaid with MIT License | 1 votes |
PermissionDialog: React.FC<{ plugin: Plugin, id: string | undefined, isGroup: boolean, onClose: () => void }> = ({ plugin, id, onClose, isGroup }) => {
const [value, setValue] = useState('')
const [status, setStatus] = useState<boolean | undefined>(false)
const [options, setOptions] = useState<string[]>([])
useEffect(() => {
if (!id) return
setValue('')
setStatus(false)
plugin.emit('vault:getAllPermissions', (it: any) => setOptions(it.sort()))
}, [id])
const queryStatus = useMemo(() => throttle((value: string) => plugin.emit('vault:permission', setStatus, id, value, 0, isGroup), 500), [id, isGroup])
return <Dialog open={!!id} onClose={onClose}>
<DialogTitle>{lang.vault.editorTitle}</DialogTitle>
<DialogContent sx={{ overflow: 'hidden' }}>
<DialogContentText>{lang.vault.permissionInput}: <span className='bold' style={{ }}>
({isGroup ? lang.vault.permissionGroup : minecraft['entity.minecraft.player']}: {id})</span></DialogContentText>
<Autocomplete
freeSolo
options={options}
sx={{ marginTop: 1 }}
inputValue={value}
renderInput={params => <TextField {...params as any} label={lang.vault.permission} />}
onInputChange={(_, it) => {
setValue(it)
setStatus(undefined)
queryStatus(it)
}}
/>
<Box sx={{ display: 'flex', alignItems: 'center', marginTop: 1 }}>
{lang.status}:{status == null
? <CircularProgress size={20} sx={{ margin: '5px' }}/>
: status ? <Check color='success' /> : <Close color='error' />}
{status != null && <Button
disabled={!value}
variant='outlined'
size='small'
onClick={() => plugin.emit('vault:permission', (res: boolean) => {
action(res)
setStatus(undefined)
queryStatus(value)
}, id, value, status ? 2 : 1, isGroup)}
>{lang.vault[status ? 'removePermission' : 'addPermission']}</Button>}
</Box>
</DialogContent>
<DialogActions><Button onClick={onClose}>{minecraft['gui.back']}</Button></DialogActions>
</Dialog>
}