@mui/material#Accordion TypeScript Examples
The following examples show how to use
@mui/material#Accordion.
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: SidebarLink.tsx From Cromwell with MIT License | 6 votes |
ExpansionPanel = withStyles({
root: {
padding: 0,
boxShadow: 'none',
'&:before': {
display: 'none',
},
'&$expanded': {
margin: 'auto',
},
},
expanded: {},
})(Accordion)
Example #2
Source File: index.tsx From genshin-optimizer with MIT License | 6 votes |
function FormulaCalc({ sectionKey, displayNs }: { displayNs: DisplaySub<NodeDisplay>, sectionKey: string }) {
const { data } = useContext(DataContext)
const header = usePromise(getDisplayHeader(data, sectionKey), [data, sectionKey])
if (!header) return null
if (Object.entries(displayNs).every(([_, node]) => node.isEmpty)) return null
const { title, icon, action } = header
return <CardDark sx={{ mb: 1 }}>
<CardHeader avatar={icon && <ImgIcon size={2} sx={{ m: -1 }} src={icon} />} title={title} action={action} titleTypographyProps={{ variant: "subtitle1" }} />
<Divider />
<CardContent>
{Object.entries(displayNs).map(([key, node]) =>
!node.isEmpty && <Accordion sx={{ bgcolor: "contentLight.main" }} key={key}>
<AccordionSummary expandIcon={<ExpandMore />}>
<Typography><ColorText color={node.info.variant}>{KeyMap.get(node.info.key ?? "")}</ColorText> <strong>{valueString(node.value, node.unit)}</strong></Typography>
</AccordionSummary>
<AccordionDetails>
{node.formulas.map((subform, i) => <Typography key={i}>{subform}</Typography>)}
</AccordionDetails>
</Accordion>)}
</CardContent>
</CardDark>
}
Example #3
Source File: itemAccordion.tsx From Search-Next with GNU General Public License v3.0 | 5 votes |
ItemAccordion: React.FC<ItemAccordionProps> = ({
title,
desc,
action,
expanded,
onChange,
children,
disableDetailPadding = false,
}) => {
return (
<Accordion
expanded={expanded}
onChange={onChange}
className={classNames(
'rounded border shadow-none bg-white my-0',
css`
&::before {
background-color: transparent !important;
}
`,
)}
>
<AccordionSummary
className=" transition hover:bg-gray-100"
expandIcon={<ExpandMore />}
>
<div className="flex items-center justify-between w-full mr-2">
<div>
{title && <p className="mb-0 text-sm">{title}</p>}
{desc && <p className="mb-0 text-xs text-gray-700">{desc}</p>}
</div>
<div className="flex items-center">{action}</div>
</div>
</AccordionSummary>
<AccordionDetails className={classNames({ 'p-0': disableDetailPadding })}>
{children}
</AccordionDetails>
</Accordion>
);
}
Example #4
Source File: AddLifecycleModal.tsx From console with GNU Affero General Public License v3.0 | 4 votes |
AddLifecycleModal = ({
open,
closeModalAndRefresh,
classes,
bucketName,
}: IReplicationModal) => {
const dispatch = useDispatch();
const distributedSetup = useSelector(selDistSet);
const [loadingTiers, setLoadingTiers] = useState<boolean>(true);
const [tiersList, setTiersList] = useState<ITiersDropDown[]>([]);
const [addLoading, setAddLoading] = useState(false);
const [isVersioned, setIsVersioned] = useState<boolean>(false);
const [prefix, setPrefix] = useState("");
const [tags, setTags] = useState<string>("");
const [storageClass, setStorageClass] = useState("");
const [ilmType, setIlmType] = useState<string>("expiry");
const [targetVersion, setTargetVersion] = useState<"current" | "noncurrent">(
"current"
);
const [lifecycleDays, setLifecycleDays] = useState<string>("");
const [isFormValid, setIsFormValid] = useState<boolean>(false);
const [expiredObjectDM, setExpiredObjectDM] = useState<boolean>(false);
const [loadingVersioning, setLoadingVersioning] = useState<boolean>(true);
useEffect(() => {
if (loadingTiers) {
api
.invoke("GET", `/api/v1/admin/tiers`)
.then((res: ITierResponse) => {
const tiersList: ITierElement[] | null = get(res, "items", []);
if (tiersList !== null && tiersList.length >= 1) {
const objList = tiersList.map((tier: ITierElement) => {
const tierType = tier.type;
const value = get(tier, `${tierType}.name`, "");
return { label: value, value: value };
});
setTiersList(objList);
if (objList.length > 0) {
setStorageClass(objList[0].value);
}
}
setLoadingTiers(false);
})
.catch((err: ErrorResponseHandler) => {
setLoadingTiers(false);
});
}
}, [loadingTiers]);
useEffect(() => {
let valid = true;
if (ilmType !== "expiry") {
if (storageClass === "") {
valid = false;
}
}
setIsFormValid(valid);
}, [ilmType, lifecycleDays, storageClass]);
useEffect(() => {
if (loadingVersioning && distributedSetup) {
api
.invoke("GET", `/api/v1/buckets/${bucketName}/versioning`)
.then((res: BucketVersioning) => {
setIsVersioned(res.is_versioned);
setLoadingVersioning(false);
})
.catch((err: ErrorResponseHandler) => {
dispatch(setModalErrorSnackMessage(err));
setLoadingVersioning(false);
});
}
}, [loadingVersioning, dispatch, bucketName, distributedSetup]);
const addRecord = () => {
let rules = {};
if (ilmType === "expiry") {
let expiry: { [key: string]: number } = {};
if (targetVersion === "current") {
expiry["expiry_days"] = parseInt(lifecycleDays);
} else {
expiry["noncurrentversion_expiration_days"] = parseInt(lifecycleDays);
}
rules = {
...expiry,
};
} else {
let transition: { [key: string]: number | string } = {};
if (targetVersion === "current") {
transition["transition_days"] = parseInt(lifecycleDays);
transition["storage_class"] = storageClass;
} else {
transition["noncurrentversion_transition_days"] =
parseInt(lifecycleDays);
transition["noncurrentversion_transition_storage_class"] = storageClass;
}
rules = {
...transition,
};
}
const lifecycleInsert = {
type: ilmType,
prefix,
tags,
expired_object_delete_marker: expiredObjectDM,
...rules,
};
api
.invoke(
"POST",
`/api/v1/buckets/${bucketName}/lifecycle`,
lifecycleInsert
)
.then(() => {
setAddLoading(false);
closeModalAndRefresh(true);
})
.catch((err: ErrorResponseHandler) => {
setAddLoading(false);
dispatch(setModalErrorSnackMessage(err));
});
};
return (
<ModalWrapper
modalOpen={open}
onClose={() => {
closeModalAndRefresh(false);
}}
title="Add Lifecycle Rule"
titleIcon={<LifecycleConfigIcon />}
>
{loadingTiers && (
<Grid container className={classes.loadingBox}>
<Grid item xs={12}>
<LinearProgress />
</Grid>
</Grid>
)}
{!loadingTiers && (
<form
noValidate
autoComplete="off"
onSubmit={(e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
setAddLoading(true);
addRecord();
}}
>
<Grid container>
<Grid item xs={12} className={classes.formScrollable}>
<Grid item xs={12}>
<Grid container spacing={1}>
<Grid item xs={12}>
<RadioGroupSelector
currentSelection={ilmType}
id="ilm_type"
name="ilm_type"
label="Type of lifecycle"
onChange={(e: React.ChangeEvent<{ value: unknown }>) => {
setIlmType(e.target.value as string);
}}
selectorOptions={[
{ value: "expiry", label: "Expiry" },
{ value: "transition", label: "Transition" },
]}
/>
</Grid>
{isVersioned && (
<Grid item xs={12}>
<SelectWrapper
value={targetVersion}
id="object_version"
name="object_version"
label="Object Version"
onChange={(e) => {
setTargetVersion(
e.target.value as "current" | "noncurrent"
);
}}
options={[
{ value: "current", label: "Current Version" },
{ value: "noncurrent", label: "Non-Current Version" },
]}
/>
</Grid>
)}
<Grid item xs={12}>
<InputBoxWrapper
id="expiry_days"
name="expiry_days"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
if (e.target.validity.valid) {
setLifecycleDays(e.target.value);
}
}}
pattern={"[0-9]*"}
label="After"
value={lifecycleDays}
overlayObject={
<InputUnitMenu
id={"expire-current-unit"}
unitSelected={"days"}
unitsList={[{ label: "Days", value: "days" }]}
disabled={true}
/>
}
/>
</Grid>
{ilmType === "expiry" ? (
<Fragment></Fragment>
) : (
<Fragment>
<Grid item xs={12}>
<SelectWrapper
label="To Tier"
id="storage_class"
name="storage_class"
value={storageClass}
onChange={(e: SelectChangeEvent<string>) => {
setStorageClass(e.target.value as string);
}}
options={tiersList}
/>
</Grid>
</Fragment>
)}
<Grid item xs={12} className={classes.formFieldRowFilter}>
<Accordion>
<AccordionSummary>
<Typography>Filters</Typography>
</AccordionSummary>
<AccordionDetails>
<Grid item xs={12}>
<InputBoxWrapper
id="prefix"
name="prefix"
onChange={(
e: React.ChangeEvent<HTMLInputElement>
) => {
setPrefix(e.target.value);
}}
label="Prefix"
value={prefix}
/>
</Grid>
<Grid item xs={12}>
<QueryMultiSelector
name="tags"
label="Tags"
elements={""}
onChange={(vl: string) => {
setTags(vl);
}}
keyPlaceholder="Tag Key"
valuePlaceholder="Tag Value"
withBorder
/>
</Grid>
</AccordionDetails>
</Accordion>
</Grid>
{ilmType === "expiry" && targetVersion === "noncurrent" && (
<Grid item xs={12} className={classes.formFieldRowFilter}>
<Accordion>
<AccordionSummary>
<Typography>Advanced</Typography>
</AccordionSummary>
<AccordionDetails>
<Grid item xs={12}>
<FormSwitchWrapper
value="expired_delete_marker"
id="expired_delete_marker"
name="expired_delete_marker"
checked={expiredObjectDM}
onChange={(
event: React.ChangeEvent<HTMLInputElement>
) => {
setExpiredObjectDM(event.target.checked);
}}
label={"Expire Delete Marker"}
description={
"Remove the reference to the object if no versions are left"
}
/>
</Grid>
</AccordionDetails>
</Accordion>
</Grid>
)}
</Grid>
</Grid>
</Grid>
<Grid item xs={12} className={classes.modalButtonBar}>
<Button
type="button"
variant="outlined"
color="primary"
disabled={addLoading}
onClick={() => {
closeModalAndRefresh(false);
}}
>
Cancel
</Button>
<Button
type="submit"
variant="contained"
color="primary"
disabled={addLoading || !isFormValid}
>
Save
</Button>
</Grid>
{addLoading && (
<Grid item xs={12}>
<LinearProgress />
</Grid>
)}
</Grid>
</form>
)}
</ModalWrapper>
);
}
Example #5
Source File: EditLifecycleConfiguration.tsx From console with GNU Affero General Public License v3.0 | 4 votes |
EditLifecycleConfiguration = ({
classes,
closeModalAndRefresh,
selectedBucket,
lifecycleRule,
open,
}: IAddUserContentProps) => {
const dispatch = useDispatch();
const [loadingTiers, setLoadingTiers] = useState<boolean>(true);
const [addLoading, setAddLoading] = useState<boolean>(false);
const [tags, setTags] = useState<string>("");
const [enabled, setEnabled] = useState<boolean>(false);
const [tiersList, setTiersList] = useState<ITiersDropDown[]>([]);
const [prefix, setPrefix] = useState("");
const [storageClass, setStorageClass] = useState("");
const [NCTransitionSC, setNCTransitionSC] = useState("");
const [expiredObjectDM, setExpiredObjectDM] = useState<boolean>(false);
const [NCExpirationDays, setNCExpirationDays] = useState<string>("0");
const [NCTransitionDays, setNCTransitionDays] = useState<string>("0");
const [ilmType, setIlmType] = useState<string>("expiry");
const [expiryDays, setExpiryDays] = useState<string>("0");
const [transitionDays, setTransitionDays] = useState<string>("0");
const [isFormValid, setIsFormValid] = useState<boolean>(false);
useEffect(() => {
if (loadingTiers) {
api
.invoke("GET", `/api/v1/admin/tiers`)
.then((res: ITierResponse) => {
const tiersList: ITierElement[] | null = get(res, "items", []);
if (tiersList !== null && tiersList.length >= 1) {
const objList = tiersList.map((tier: ITierElement) => {
const tierType = tier.type;
const value = get(tier, `${tierType}.name`, "");
return { label: value, value: value };
});
setTiersList(objList);
if (objList.length > 0) {
setStorageClass(objList[0].value);
}
}
setLoadingTiers(false);
})
.catch((err: ErrorResponseHandler) => {
setLoadingTiers(false);
});
}
}, [loadingTiers]);
useEffect(() => {
let valid = true;
if (ilmType !== "expiry") {
if (storageClass === "") {
valid = false;
}
}
setIsFormValid(valid);
}, [ilmType, expiryDays, transitionDays, storageClass]);
useEffect(() => {
if (lifecycleRule.status === "Enabled") {
setEnabled(true);
}
let transitionMode = false;
if (lifecycleRule.transition) {
if (
lifecycleRule.transition.days &&
lifecycleRule.transition.days !== 0
) {
setTransitionDays(lifecycleRule.transition.days.toString());
setIlmType("transition");
transitionMode = true;
}
if (
lifecycleRule.transition.noncurrent_transition_days &&
lifecycleRule.transition.noncurrent_transition_days !== 0
) {
setNCTransitionDays(
lifecycleRule.transition.noncurrent_transition_days.toString()
);
setIlmType("transition");
transitionMode = true;
}
// Fallback to old rules by date
if (
lifecycleRule.transition.date &&
lifecycleRule.transition.date !== "0001-01-01T00:00:00Z"
) {
setIlmType("transition");
transitionMode = true;
}
}
if (lifecycleRule.expiration) {
if (
lifecycleRule.expiration.days &&
lifecycleRule.expiration.days !== 0
) {
setExpiryDays(lifecycleRule.expiration.days.toString());
setIlmType("expiry");
transitionMode = false;
}
if (
lifecycleRule.expiration.noncurrent_expiration_days &&
lifecycleRule.expiration.noncurrent_expiration_days !== 0
) {
setNCExpirationDays(
lifecycleRule.expiration.noncurrent_expiration_days.toString()
);
setIlmType("expiry");
transitionMode = false;
}
// Fallback to old rules by date
if (
lifecycleRule.expiration.date &&
lifecycleRule.expiration.date !== "0001-01-01T00:00:00Z"
) {
setIlmType("expiry");
transitionMode = false;
}
}
// Transition fields
if (transitionMode) {
setStorageClass(lifecycleRule.transition?.storage_class || "");
setNCTransitionDays(
lifecycleRule.transition?.noncurrent_transition_days?.toString() || "0"
);
setNCTransitionSC(
lifecycleRule.transition?.noncurrent_storage_class || ""
);
} else {
// Expiry fields
setNCExpirationDays(
lifecycleRule.expiration?.noncurrent_expiration_days?.toString() || "0"
);
}
setExpiredObjectDM(!!lifecycleRule.expiration?.delete_marker);
setPrefix(lifecycleRule.prefix || "");
if (lifecycleRule.tags) {
const tgs = lifecycleRule.tags.reduce(
(stringLab: string, currItem: any, index: number) => {
return `${stringLab}${index !== 0 ? "&" : ""}${currItem.key}=${
currItem.value
}`;
},
""
);
setTags(tgs);
}
}, [lifecycleRule]);
const saveRecord = (event: React.FormEvent) => {
event.preventDefault();
if (addLoading) {
return;
}
setAddLoading(true);
if (selectedBucket !== null && lifecycleRule !== null) {
let rules = {};
if (ilmType === "expiry") {
let expiry: { [key: string]: number } = {};
if (
lifecycleRule.expiration?.days &&
lifecycleRule.expiration?.days > 0
) {
expiry["expiry_days"] = parseInt(expiryDays);
}
if (lifecycleRule.expiration?.noncurrent_expiration_days) {
expiry["noncurrentversion_expiration_days"] =
parseInt(NCExpirationDays);
}
rules = {
...expiry,
};
} else {
let transition: { [key: string]: number | string } = {};
if (
lifecycleRule.expiration?.days &&
lifecycleRule.expiration?.days > 0
) {
transition["transition_days"] = parseInt(expiryDays);
transition["storage_class"] = storageClass;
}
if (lifecycleRule.expiration?.noncurrent_expiration_days) {
transition["noncurrentversion_transition_days"] =
parseInt(NCExpirationDays);
transition["noncurrentversion_transition_storage_class"] =
NCTransitionSC;
}
rules = {
...transition,
};
}
const lifecycleUpdate = {
type: ilmType,
disable: !enabled,
prefix,
tags,
expired_object_delete_marker: expiredObjectDM,
...rules,
};
api
.invoke(
"PUT",
`/api/v1/buckets/${selectedBucket}/lifecycle/${lifecycleRule.id}`,
lifecycleUpdate
)
.then((res) => {
setAddLoading(false);
closeModalAndRefresh(true);
})
.catch((err: ErrorResponseHandler) => {
setAddLoading(false);
dispatch(setModalErrorSnackMessage(err));
});
}
};
return (
<ModalWrapper
onClose={() => {
closeModalAndRefresh(false);
}}
modalOpen={open}
title={"Edit Lifecycle Configuration"}
titleIcon={<LifecycleConfigIcon />}
>
<form
noValidate
autoComplete="off"
onSubmit={(e: React.FormEvent<HTMLFormElement>) => {
saveRecord(e);
}}
>
<Grid container>
<Grid item xs={12} className={classes.formScrollable}>
<Grid container spacing={1}>
<Grid item xs={12}>
<InputBoxWrapper
id="id"
name="id"
label="Id"
value={lifecycleRule.id}
onChange={() => {}}
disabled
/>
</Grid>
<Grid item xs={12}>
<FormSwitchWrapper
label="Status"
indicatorLabels={["Enabled", "Disabled"]}
checked={enabled}
value={"user_enabled"}
id="rule_status"
name="rule_status"
onChange={(e) => {
setEnabled(e.target.checked);
}}
/>
</Grid>
<Grid item xs={12}>
<RadioGroupSelector
currentSelection={ilmType}
id="rule_type"
name="rule_type"
label="Rule Type"
selectorOptions={[
{ value: "expiry", label: "Expiry" },
{ value: "transition", label: "Transition" },
]}
onChange={() => {}}
disableOptions
/>
</Grid>
{ilmType === "expiry" && lifecycleRule.expiration?.days && (
<Grid item xs={12}>
<InputBoxWrapper
type="number"
id="expiry_days"
name="expiry_days"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setExpiryDays(e.target.value);
}}
label="Expiry Days"
value={expiryDays}
min="0"
/>
</Grid>
)}
{ilmType === "expiry" &&
lifecycleRule.expiration?.noncurrent_expiration_days && (
<Grid item xs={12}>
<InputBoxWrapper
type="number"
id="noncurrentversion_expiration_days"
name="noncurrentversion_expiration_days"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setNCExpirationDays(e.target.value);
}}
label="Non-current Expiration Days"
value={NCExpirationDays}
min="0"
/>
</Grid>
)}
{ilmType === "transition" && lifecycleRule.transition?.days && (
<Fragment>
<Grid item xs={12}>
<InputBoxWrapper
type="number"
id="transition_days"
name="transition_days"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setTransitionDays(e.target.value);
}}
label="Transition Days"
value={transitionDays}
min="0"
/>
</Grid>
<Grid item xs={12}>
<SelectWrapper
label="Storage Class"
id="storage_class"
name="storage_class"
value={storageClass}
onChange={(e: SelectChangeEvent<string>) => {
setStorageClass(e.target.value as string);
}}
options={tiersList}
/>
</Grid>
</Fragment>
)}
{ilmType === "transition" &&
lifecycleRule.transition?.noncurrent_transition_days && (
<Fragment>
<Grid item xs={12}>
<InputBoxWrapper
type="number"
id="noncurrentversion_transition_days"
name="noncurrentversion_transition_days"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setNCTransitionDays(e.target.value);
}}
label="Non-current Transition Days"
value={NCTransitionDays}
min="0"
/>
</Grid>
<Grid item xs={12}>
<InputBoxWrapper
id="noncurrentversion_t_SC"
name="noncurrentversion_t_SC"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setNCTransitionSC(e.target.value);
}}
placeholder="Set Non-current Version Transition Storage Class"
label="Non-current Version Transition Storage Class"
value={NCTransitionSC}
/>
</Grid>
</Fragment>
)}
<Grid item xs={12} className={classes.formFieldRowAccordion}>
<Accordion>
<AccordionSummary>
<Typography>Filters</Typography>
</AccordionSummary>
<AccordionDetails>
<Grid item xs={12}>
<InputBoxWrapper
id="prefix"
name="prefix"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setPrefix(e.target.value);
}}
label="Prefix"
value={prefix}
/>
</Grid>
<Grid item xs={12}>
<QueryMultiSelector
name="tags"
label="Tags"
elements={tags}
onChange={(vl: string) => {
setTags(vl);
}}
keyPlaceholder="Tag Key"
valuePlaceholder="Tag Value"
withBorder
/>
</Grid>
</AccordionDetails>
</Accordion>
</Grid>
{ilmType === "expiry" &&
lifecycleRule.expiration?.noncurrent_expiration_days && (
<Grid item xs={12} className={classes.formFieldRowAccordion}>
<Accordion>
<AccordionSummary>
<Typography>Advanced</Typography>
</AccordionSummary>
<AccordionDetails>
<Grid item xs={12}>
<FormSwitchWrapper
value="expired_delete_marker"
id="expired_delete_marker"
name="expired_delete_marker"
checked={expiredObjectDM}
onChange={(
event: React.ChangeEvent<HTMLInputElement>
) => {
setExpiredObjectDM(event.target.checked);
}}
label={"Expired Object Delete Marker"}
/>
</Grid>
</AccordionDetails>
</Accordion>
</Grid>
)}
</Grid>
</Grid>
<Grid item xs={12} className={classes.modalButtonBar}>
<Button
type="button"
variant="outlined"
color="primary"
disabled={addLoading}
onClick={() => {
closeModalAndRefresh(false);
}}
>
Cancel
</Button>
<Button
type="submit"
variant="contained"
color="primary"
disabled={addLoading || !isFormValid}
>
Save
</Button>
</Grid>
{addLoading && (
<Grid item xs={12}>
<LinearProgress />
</Grid>
)}
</Grid>
</form>
</ModalWrapper>
);
}
Example #6
Source File: BlockEditor.tsx From NekoMaid with MIT License | 4 votes |
BlockEditor: React.FC = () => {
const theme = useTheme()
const plugin = usePlugin()
const his = useHistory()
const loc = useLocation()
const globalData = useGlobalData()
const drawerWidth = useDrawerWidth()
const [block, setBlock] = useState<Block>()
const [types, setTypes] = useState<string[]>([])
const [worlds, setWorlds] = useState<string[]>([])
const params = { world: '', x: 0, y: 0, z: 0 }
if (loc.pathname.startsWith('/NekoMaid/block/')) {
const arr = loc.pathname.split('/')
if (arr.length > 6) {
params.world = arr[3]
params.x = +arr[4]
params.y = +arr[5]
params.z = +arr[6]
} else his.push('/NekoMaid/block')
}
useEffect(() => {
const off = plugin.emit('item:blocks', (types: string[], worlds: string[]) => {
setTypes(types)
setWorlds(worlds)
})
.on('block:select', (world, x, y, z) => his.push(`/NekoMaid/block/${world}/${x}/${y}/${z}`))
return () => void off()
}, [])
const update = () => {
if (params.world) {
plugin.emit('block:fetch', (block: Block) => {
if (!block) {
failed()
his.push('/NekoMaid/block')
return
}
if (globalData.hasNBTAPI && block.nbt) block.nbt = stringify(parse(block.nbt), { pretty: true })
setBlock(block)
}, params.world, params.x, params.y, params.z)
}
}
const updateWithAction = (res: boolean) => {
action(res)
update()
}
useEffect(update, [params.world, params.x, params.y, params.z])
return <Box sx={{ minHeight: '100%', py: 3 }}>
<Toolbar />
<Container maxWidth={false}>
<Grid container spacing={3} sx={{ width: { sm: `calc(100vw - ${drawerWidth}px - ${theme.spacing(3)})` } }}>
<Grid item lg={6} md={12} xl={6} xs={12}>
<Card sx={{ '& .CodeMirror-dialog, .CodeMirror-scrollbar-filler': { backgroundColor: theme.palette.background.paper + '!important' } }}>
<CardHeader
title={lang.blockEditor.title}
sx={{ position: 'relative' }}
action={<Box sx={cardActionStyles}>
<IconButton
size='small'
disabled={!block || (!block.data && !block.nbt)}
onClick={() => block && plugin.emit('block:save', (res: boolean) => {
action(res)
update()
}, params.world, params.x, params.y, params.z, block.nbt || null, block.data || null)}
><Save /></IconButton>
<IconButton
size='small'
disabled={!block}
onClick={() => {
update()
success()
}}
><Refresh /></IconButton>
</Box>}
/>
<Divider />
{block
? <>
<CardContent sx={{ display: 'flex', width: '100%', justifyContent: 'center' }}>
<ItemViewer item={{ type: block.type }} />
<Autocomplete
options={types}
sx={{ maxWidth: 300, marginLeft: 1, flexGrow: 1 }}
value={block.type}
onChange={(_, it) => it && plugin.emit('block:type', (res: boolean) => {
action(res)
update()
}, params.world, params.x, params.y, params.z, (block.type = it))}
getOptionLabel={it => {
const locatedName = getName(it.toLowerCase())
return (locatedName ? locatedName + ' ' : '') + it
}}
renderInput={(params) => <TextField {...params} label={lang.itemEditor.itemType} size='small' variant='standard' />}
/>
</CardContent>
{block.data != null && <Accordion sx={{ '&::before': { opacity: '1!important' } }} disableGutters>
<AccordionSummary expandIcon={<ExpandMore />}><Typography>{lang.data}</Typography></AccordionSummary>
<AccordionDetails sx={{ padding: 0, '& .CodeMirror': { width: '100%', height: 350 } }}>
<UnControlled
value={block.data}
options={{
mode: 'javascript',
phrases: lang.codeMirrorPhrases,
theme: theme.palette.mode === 'dark' ? 'material' : 'one-light'
}}
onChange={(_: any, __: any, data: string) => (block.data = data)}
/>
</AccordionDetails>
</Accordion>}
{block.nbt != null && <Accordion sx={{ '&::before': { opacity: '1!important', display: '!important' } }} disableGutters>
<AccordionSummary expandIcon={<ExpandMore />}><Typography>NBT</Typography></AccordionSummary>
<AccordionDetails sx={{ padding: 0, '& .CodeMirror': { width: '100%', height: 350 } }}>
<UnControlled
value={block.nbt}
options={{
mode: 'javascript',
phrases: lang.codeMirrorPhrases,
theme: theme.palette.mode === 'dark' ? 'material' : 'one-light'
}}
onChange={(_: any, __: any, data: string) => (block.nbt = data)}
/>
</AccordionDetails>
</Accordion>}
</>
: <CardContent>{worlds.length ? <BlockSelector worlds={worlds} /> : <Empty />}</CardContent>}
</Card>
</Grid>
{block?.inventory?.length
? <Grid item lg={6} md={12} xl={6} xs={12}>
<Card>
<CardHeader
title={minecraft[('container.' + block.inventoryType || '').toLowerCase()] || lang.blockEditor.container}
sx={{ position: 'relative' }}
/>
<Divider />
<CardContent sx={{ whiteSpace: 'nowrap', overflowX: 'auto', textAlign: 'center' }}>
{block.inventory.map((it, i) => <React.Fragment key={i}><ItemViewer
item={it}
data={{ type: InvType.BLOCK, solt: i, ...params }}
onDrag={() => plugin.emit('block:setItem', update, params.world, params.x, params.y, params.z, i, null, -1)}
onDrop={(item, obj) => plugin.emit('block:setItem', update, params.world, params.x, params.y, params.z, i,
JSON.stringify(item), compare(obj, params) ? obj.solt : -1)}
onEdit={item => item !== false && plugin.emit('block:setItem', updateWithAction, params.world, params.x, params.y,
params.z, i, item && JSON.stringify(item), -1)}
/>{!((i + 1) % 9) && <br />}</React.Fragment>)}
</CardContent>
</Card>
</Grid>
: undefined}
</Grid>
</Container>
</Box>
}
Example #7
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 #8
Source File: EntityEditor.tsx From NekoMaid with MIT License | 4 votes |
EntityEditor: React.FC = () => {
const theme = useTheme()
const plugin = usePlugin()
const his = useHistory()
const loc = useLocation()
const globalData = useGlobalData()
const drawerWidth = useDrawerWidth()
const [customName, setCustomName] = useState('')
const [entity, setEntity] = useState<Entity>()
let id: string | null = null
if (loc.pathname.startsWith('/NekoMaid/entity/')) {
const arr = loc.pathname.split('/')
if (arr.length > 3) id = arr[3]
}
useEffect(() => {
const off = plugin.on('entity:select', id => his.push('/NekoMaid/entity/' + id))
return () => void off()
}, [])
const update = () => {
if (id) {
plugin.emit('entity:fetch', (entity: Entity) => {
if (!entity) {
failed()
his.push('/NekoMaid/entity')
return
}
if (globalData.hasNBTAPI && entity.nbt) entity.nbt = stringify(parse(entity.nbt), { pretty: true })
setCustomName(entity.customName || '')
setEntity(entity)
}, id)
}
}
const updateWithAction = (res: boolean) => {
action(res)
update()
}
useEffect(update, [id])
return <Box sx={{ minHeight: '100%', py: 3 }}>
<Toolbar />
<Container maxWidth={false}>
<Grid container spacing={3} sx={{ width: { sm: `calc(100vw - ${drawerWidth}px - ${theme.spacing(3)})` } }}>
<Grid item lg={6} md={12} xl={6} xs={12}>
<Card>
<CardHeader
title={(entity && minecraft['entity.minecraft.' + entity.type.toLowerCase()]) || lang.entityEditor.title}
sx={{ position: 'relative' }}
action={<Box sx={cardActionStyles}>
<IconButton
size='small'
disabled={!entity}
onClick={() => entity && plugin.emit('entity:save', (res: boolean) => {
action(res)
update()
}, id, entity.nbt || null, customName || null)}
><Save /></IconButton>
<IconButton
size='small'
disabled={!entity}
onClick={() => {
update()
success()
}}
><Refresh /></IconButton>
</Box>}
/>
<Divider />
{entity
? <>
<CardContent>
<Grid container>
<Grid item lg={6} md={6} xl={6} xs={12}>
<TextField
size='small'
label={lang.entityEditor.customName}
value={customName}
sx={{ width: '90%' }}
onChange={e => setCustomName(e.target.value)}
/>
</Grid>
{values.map(it => <Grid item lg={6} md={6} xl={6} xs={12} key={it}>
<FormControlLabel
control={<Switch checked={(entity as any)[it]} />}
label={(lang.entityEditor as any)[it]}
onChange={(e: any) => plugin.emit('entity:set', (res: boolean) => {
action(res)
update()
}, id, it, e.target.checked)}
/>
</Grid>)}
</Grid>
</CardContent>
{entity.nbt != null && <Accordion sx={{ '&::before': { opacity: '1!important' } }} disableGutters>
<AccordionSummary expandIcon={<ExpandMore />}><Typography>NBT</Typography></AccordionSummary>
<AccordionDetails sx={{
padding: 0,
'& .CodeMirror': { width: '100%', height: 350 },
'& .CodeMirror-dialog, .CodeMirror-scrollbar-filler': { backgroundColor: theme.palette.background.paper + '!important' }
}}>
<UnControlled
value={entity.nbt}
options={{
mode: 'javascript',
phrases: lang.codeMirrorPhrases,
theme: theme.palette.mode === 'dark' ? 'material' : 'one-light'
}}
onChange={(_: any, __: any, data: string) => (entity.nbt = data)}
/>
</AccordionDetails>
</Accordion>}
</>
: <CardContent><EntitySelector /></CardContent>}
</Card>
</Grid>
{entity?.inventory?.length
? <Grid item lg={6} md={12} xl={6} xs={12}>
<Card>
<CardHeader
title={lang.entityEditor.container}
sx={{ position: 'relative' }}
/>
<Divider />
<CardContent sx={{ whiteSpace: 'nowrap', overflowX: 'auto', textAlign: 'center' }}>
{entity.inventory.map((it, i) => <React.Fragment key={i}><ItemViewer
item={it}
data={{ type: InvType.ENTITY, solt: i, id }}
onDrag={() => plugin.emit('entity:setItem', update, id, i, null, -1)}
onDrop={(item, obj) => plugin.emit('entity:setItem', update, id, i, JSON.stringify(item),
obj?.type === InvType.ENTITY && obj.id === id ? obj.solt : -1)}
onEdit={item => item !== false && plugin.emit('entity:setItem', updateWithAction, id, i, item && JSON.stringify(item), -1)}
/>{!((i + 1) % 9) && <br />}</React.Fragment>)}
</CardContent>
</Card>
</Grid>
: undefined}
</Grid>
</Container>
</Box>
}