@mui/material#InputLabel TypeScript Examples
The following examples show how to use
@mui/material#InputLabel.
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: BlockEditor.tsx From NekoMaid with MIT License | 6 votes |
BlockSelector: React.FC<{ worlds: string[] }> = ({ worlds }) => {
const his = useHistory()
const [world, setWorld] = useState(worlds[0])
const [x, setX] = useState('0')
const [y, setY] = useState('0')
const [z, setZ] = useState('0')
return <Grid container>
<Grid item xs={6}>
<FormControl variant='standard' fullWidth>
<InputLabel id='nekomaid-block-editor-world'>{lang.world}</InputLabel>
<Select
labelId='nekomaid-block-editor-world'
value={world}
label={lang.world}
onChange={e => setWorld(e.target.value)}
>
{worlds.map(it => <MenuItem key={it} value={it}>{it}</MenuItem>)}
</Select>
</FormControl>
</Grid>
<Grid item xs={2}><TextField variant='standard' label='X' type='number' fullWidth value={x} onChange={e => setX(e.target.value)} /></Grid>
<Grid item xs={2}><TextField variant='standard' label='Y' type='number' fullWidth value={y} onChange={e => setY(e.target.value)} /></Grid>
<Grid item xs={2}><TextField variant='standard' label='Z' type='number' fullWidth value={z} onChange={e => setZ(e.target.value)} /></Grid>
<Grid item xs={12} sx={{ marginTop: 3, textAlign: 'center' }}>
<Button
variant='contained'
onClick={() => his.push(`/NekoMaid/block/${world}/${parseFloat(x) | 0}/${parseFloat(y) | 0}/${parseFloat(z) | 0}`)}
>{minecraft['gui.done']}</Button>
</Grid>
</Grid>
}
Example #2
Source File: CampaignTypeSelect.tsx From frontend with MIT License | 6 votes |
export default function CampaignTypeSelect({ name = 'campaignTypeId' }) {
const { t } = useTranslation()
const { data } = useCampaignTypesList()
const [field, meta] = useField(name)
const helperText = meta.touched ? translateError(meta.error as TranslatableField, t) : ''
return (
<FormControl
fullWidth
size="small"
variant="outlined"
error={Boolean(meta.error) && Boolean(meta.touched)}>
<InputLabel>{t('campaigns:campaign.type')}</InputLabel>
<Select fullWidth defaultValue="" label={t('campaigns:campaign.type')} {...field}>
<MenuItem value="" disabled>
{t('campaigns:campaign.type')}
</MenuItem>
{data?.map((campaignType, index) => (
<MenuItem key={index} value={campaignType.id}>
{campaignType.name}
</MenuItem>
))}
</Select>
{helperText && <FormHelperText error>{helperText}</FormHelperText>}
</FormControl>
)
}
Example #3
Source File: Select.tsx From Cromwell with MIT License | 6 votes |
/** @internal */
export function Select(props: TSelectProps & MuiSelectProps<string | number>) {
const { className, style, variant = 'filled' } = props;
return (
<FormControl
fullWidth={props.fullWidth}
style={props.style}
className={props.className}
>
{props.label && (
<InputLabel style={{
marginTop: '8px',
}}>{props.label}</InputLabel>
)}
<MuiSelect
{...props}
variant={variant}
className={className}
style={style}
>
{props.options?.map((option) => {
const label = typeof option === 'object' ? option.label : option;
const value = typeof option === 'object' ? option.value : option;
return (
<MenuItem value={value} key={value + ''}>{label}</MenuItem>
)
})}
</MuiSelect>
</FormControl>
)
}
Example #4
Source File: SelectCountry.tsx From frontend with MIT License | 6 votes |
export default function SelectCountry({ name = 'countryId' }) {
const { t } = useTranslation()
const { data } = useCountriesList()
const [field, meta] = useField(name)
const helperText = meta.touched ? translateError(meta.error as TranslatableField, t) : ''
return (
<FormControl
fullWidth
size="small"
variant="outlined"
error={Boolean(meta.error) && Boolean(meta.touched)}>
<InputLabel>Държава</InputLabel>
<Select fullWidth defaultValue="" label="Държава" {...field}>
<MenuItem value="" disabled>
Избери държава
</MenuItem>
{data?.map((country) => (
<MenuItem key={country.id} value={country.id}>
{country.name}
</MenuItem>
))}
</Select>
{helperText && <FormHelperText error>{helperText}</FormHelperText>}
</FormControl>
)
}
Example #5
Source File: TextFilter.tsx From Tachidesk-WebUI with Mozilla Public License 2.0 | 5 votes |
export default function TextFilter(props: Props) {
const {
state,
name,
position,
group,
updateFilterValue,
update,
} = props;
const [Search, setsearch] = React.useState(state || '');
let typingTimer: NodeJS.Timeout;
function doneTyping(e: React.ChangeEvent<HTMLInputElement>) {
const upd = update.filter((el: {
position: number; group: number | undefined;
}) => !(position === el.position && group === el.group));
updateFilterValue([...upd, { position, state: e.target.value, group }]);
}
function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
setsearch(e.target.value);
clearTimeout(typingTimer);
typingTimer = setTimeout(() => { doneTyping(e); }, 2500);
}
if (state !== undefined) {
return (
<Box key={`${name}`} sx={{ display: 'flex', flexDirection: 'row', minWidth: 120 }}>
<>
<SearchIcon
sx={{
margin: 'auto',
}}
/>
<FormControl fullWidth>
<InputLabel sx={{ margin: '10px 0 10px 0' }}>
{name}
</InputLabel>
<Input
name={name}
value={Search || ''}
onChange={handleChange}
sx={{ margin: '10px 0 10px 0' }}
/>
</FormControl>
</>
</Box>
);
}
return (<></>);
}
Example #6
Source File: RadioGroupSelector.tsx From console with GNU Affero General Public License v3.0 | 5 votes |
RadioGroupSelector = ({
selectorOptions = [],
currentSelection,
label,
id,
name,
onChange,
tooltip = "",
disableOptions = false,
classes,
displayInColumn = false,
}: RadioGroupProps) => {
return (
<Grid container alignItems={"center"}>
<Grid item xs>
<InputLabel htmlFor={id} className={classes.inputLabel}>
<span>{label}</span>
{tooltip !== "" && (
<div className={classes.tooltipContainer}>
<Tooltip title={tooltip} placement="top-start">
<div>
<HelpIcon />
</div>
</Tooltip>
</div>
)}
</InputLabel>
</Grid>
<Grid item xs className={classes.radioOptionsLayout}>
<RadioGroup
aria-label={id}
id={id}
name={name}
value={currentSelection}
onChange={onChange}
row={!displayInColumn}
style={{ display: "block", textAlign: "right" }}
>
{selectorOptions.map((selectorOption) => {
return (
<FormControlLabel
key={`rd-${name}-${selectorOption.value}`}
value={selectorOption.value}
control={<RadioButton />}
label={selectorOption.label}
disabled={disableOptions}
className={clsx(classes.optionLabel, {
[classes.checkedOption]:
selectorOption.value === currentSelection,
})}
/>
);
})}
</RadioGroup>
</Grid>
</Grid>
);
}
Example #7
Source File: Sort.tsx From cli with Apache License 2.0 | 5 votes |
SortRenderer: FunctionComponent<SortProps> = (props) => {
const {controller, criteria} = props;
const [state, setState] = React.useState(controller.state);
useEffect(
() => controller.subscribe(() => setState(controller.state)),
[controller]
);
const getCurrentCriterion = () =>
criteria.find(
([, criterion]) =>
state.sortCriteria === buildCriterionExpression(criterion)
)!;
const getCriterionFromName = (name: string) =>
criteria.find(([criterionName]) => criterionName === name)!;
return (
<Box>
<FormControl>
<InputLabel id="sort-by-label">Sort by</InputLabel>
<Select
labelId="sort-by-label"
label="Sort by"
id="sort-by"
onChange={(e) =>
controller.sortBy(getCriterionFromName(e.target.value as string)[1])
}
defaultValue={getCurrentCriterion()[0]}
>
{criteria.map(([criterionName]) => (
<MenuItem key={criterionName} value={criterionName}>
{criterionName}
</MenuItem>
))}
</Select>
</FormControl>
</Box>
);
}
Example #8
Source File: MultiSelect.tsx From multi-downloader-nx with MIT License | 5 votes |
MultiSelect: React.FC<MultiSelectProps> = (props) => {
const theme = useTheme();
return <div>
<FormControl sx={{ m: 1, width: 300 }}>
<InputLabel id="multi-select-label">{props.title}</InputLabel>
<Select
labelId="multi-select-label"
id="multi-select"
multiple
value={(props.selected ?? [])}
onChange={e => {
const val = typeof e.target.value === "string" ? e.target.value.split(",") : e.target.value;
if (props.allOption && val.includes('all')) {
if (props.values.length === val.length - 1)
props.onChange([]);
else
props.onChange(props.values);
} else {
props.onChange(val);
}
}}
input={<OutlinedInput id="select-multiple-chip" label={props.title} />}
renderValue={(selected) => (
selected.join(', ')
)}
MenuProps={MenuProps}
>
{props.values.concat(props.allOption ? 'all' : []).map((name) => (
<MenuItem
key={`${props.title}_${name}`}
value={name}
style={getStyles(name, props.selected, theme)}
>
{name}
</MenuItem>
))}
</Select>
</FormControl>
</div>
}
Example #9
Source File: Importer.tsx From your_spotify with GNU General Public License v3.0 | 5 votes |
export default function Importer() {
const dispatch = useAppDispatch();
const imports = useSelector(selectImportStates);
const [importType, setImportType] = useState<ImporterStateTypes>(ImporterStateTypes.privacy);
const fetch = useCallback(
async (force = false) => {
dispatch(getImports(force));
},
[dispatch],
);
useEffect(() => {
fetch();
}, [fetch]);
const running = useMemo(() => imports?.find((st) => st.status === 'progress'), [imports]);
const Component = useMemo(
() => (importType ? ImportTypeToComponent[importType] : null),
[importType],
);
if (!imports) {
return <CircularProgress />;
}
return (
<div>
<div>
{running && (
<div>
<Text>Importing...</Text>
<div className={s.progress}>
<Text>
{running.current} / {running.total}
</Text>
</div>
<LinearProgress
style={{ width: '100%' }}
variant="determinate"
value={(running.current / running.total) * 100}
/>
</div>
)}
</div>
{!running && (
<div>
<FormControl className={s.selectimport}>
<InputLabel id="import-type-select">Import type</InputLabel>
<Select
labelId="import-type-select"
value={importType}
label="Import type"
onChange={(ev) => setImportType(ev.target.value as ImporterStateTypes)}>
{Object.values(ImporterStateTypes).map((typ) => (
<MenuItem value={typ} key={typ}>
{typ}
</MenuItem>
))}
</Select>
</FormControl>
{Component && <Component />}
</div>
)}
{imports.length > 0 && <ImportHistory />}
</div>
);
}
Example #10
Source File: CategorySelect.tsx From mojito_pdm with Creative Commons Attribution Share Alike 4.0 International | 5 votes |
CategorySelect: React.FC = () => {
const theme = useTheme()
const [category, setCategory] = useRecoilState(CarState.categorySearch)
const handleChange = (event: SelectChangeEvent) => {
setCategory(event.target.value)
};
return (
<>
<div>
<FormControl variant="outlined" sx={{margin: theme.spacing(1), minWidth: 240}} color="error">
<InputLabel sx={{color: "white"}}>Category</InputLabel>
<Select sx={{color: "white"}}
labelId="demo-simple-select-outlined-label"
id="demo-simple-select-outlined"
value={category}
onChange={handleChange}
label="Category"
>
<MenuItem value="">
<em>All</em>
</MenuItem>
<MenuItem value={"Sports"}>Sports</MenuItem>
<MenuItem value={"Compacts"}>Compacts</MenuItem>
<MenuItem value={"Muscle"}>Muscle</MenuItem>
<MenuItem value={"Sedan"}>Sedan</MenuItem>
<MenuItem value={"Coupe"}>Coupé</MenuItem>
<MenuItem value={"Super"}>Super</MenuItem>
<MenuItem value={"SUV"}>SUV</MenuItem>
<MenuItem value={"Vans"}>Vans</MenuItem>
<MenuItem value={"Offroad"}>Offroad</MenuItem>
<MenuItem value={"Sports Classics"}>Sports Classics</MenuItem>
<MenuItem value={"Motorcycles"}>Motorcycles</MenuItem>
</Select>
</FormControl>
</div>
</>
)
}
Example #11
Source File: FileList.tsx From frontend with MIT License | 5 votes |
function FileList({ files, onDelete, onSetFileRole, filesRole = [] }: Props) {
const setFileRole = (file: File) => {
return (event: SelectChangeEvent<CampaignFileRole>) => {
if (Object.values(CampaignFileRole).includes(event.target.value as CampaignFileRole)) {
onSetFileRole(file, event.target.value as CampaignFileRole)
}
}
}
return (
<List dense>
{files.map((file, key) => (
<ListItem
key={key}
secondaryAction={
<IconButton edge="end" aria-label="delete" onClick={() => onDelete && onDelete(file)}>
<Delete />
</IconButton>
}>
<ListItemAvatar>
<Avatar>
<UploadFile />
</Avatar>
</ListItemAvatar>
<ListItemText primary={file.type} />
<ListItemText primary={file.name} />
<FormControl>
<InputLabel id="choose-type-label">{'Избери роля'}</InputLabel>
<Select<CampaignFileRole>
id="choose-type"
label="Избери роля"
labelId="choose-type-label"
value={
filesRole.find((f) => f.file === file.name)?.role ?? CampaignFileRole.background
}
onChange={setFileRole(file)}>
{Object.values(CampaignFileRole).map((role) => (
<MenuItem key={role} value={role}>
{role}
</MenuItem>
))}
</Select>
</FormControl>
</ListItem>
))}
</List>
)
}
Example #12
Source File: StyleField.tsx From Cromwell with MIT License | 5 votes |
export function StyleField(props: { dataType: 'px' | 'string' | 'color' | 'select'; handleStyleChange: (name: keyof React.CSSProperties, value: any) => void; data: TCromwellBlockData; name: keyof React.CSSProperties; label: string; className?: string; style?: React.CSSProperties; options?: string[]; }) { let val = props.data?.style?.[props.name]; if (props.dataType === 'px') { if (val) val = parseFloat(val); if (isNaN(val)) val = undefined; } let noWrapper = true; let Field: React.ComponentType<any> = TextField; if (props.dataType === 'color') { Field = ColorPicker; } if (props.dataType === 'select') { Field = Select; noWrapper = false; } let content = ( <Field onChange={e => { let value: any = e?.target?.value ?? e; if (props.dataType === 'px') { if (value) value = parseFloat(value); if (isNaN(value) || value === '' || value === null) value = undefined; if (value !== undefined) value += 'px'; } props.handleStyleChange(props.name, value); }} variant="standard" value={val ?? ''} type={props.dataType === 'px' ? 'number' : 'string'} label={noWrapper ? props.label : undefined} className={noWrapper ? props.className : undefined} style={noWrapper ? props.style : undefined} >{props.options?.map(opt => <MenuItem value={opt} key={opt}>{opt}</MenuItem>)}</Field> ); if (props.dataType === 'select') { content = ( <FormControl className={props.className} style={props.style} > <InputLabel>{props.label}</InputLabel> {content} </FormControl> ) } return content; }
Example #13
Source File: SettingsView.tsx From react-flight-tracker with MIT License | 4 votes |
SettingsView: React.FC<Props> = (props) => {
// Fields
const contextName: string = ViewKeys.SettingsView;
// Contexts
const systemContext = useContext(SystemContext);
const appContext = useContext(AppContext);
const getSetting = (key: string, type: string) => {
const value = systemContext.getSetting(key)
if (typeof (value) === type)
return value;
return false;
};
const handleChange = (e: SelectChangeEvent) => {
appContext.changeTheme(e.target.value);
};
const handleSettingsChange = (e: React.ChangeEvent<HTMLInputElement>) => {
systemContext.storeSetting(e.target.name, e.target.checked);
};
const renderAppSettings = () => {
return (
<Card>
<CardContent>
<Typography
variant={'h6'}
gutterBottom={true}>
{'App settings'}
</Typography>
<FormGroup>
<FormControl
color='secondary'
variant="filled"
sx={{ m: 1, minWidth: 120 }}>
<InputLabel
id="demo-simple-select-filled-label">
Theme change
</InputLabel>
<Select
labelId="demo-simple-select-filled-label"
id="demo-simple-select-filled"
value={appContext.activeThemeName}
onChange={handleChange}>
<MenuItem
value={ThemeKeys.DarkTheme}>
{ThemeKeys.DarkTheme}
</MenuItem>
<MenuItem
value={ThemeKeys.LightTheme}>
{ThemeKeys.LightTheme}
</MenuItem>
<MenuItem
value={ThemeKeys.PineappleTheme}>
{ThemeKeys.PineappleTheme}
</MenuItem>
</Select>
</FormControl>
</FormGroup>
</CardContent>
</Card>
);
};
const renderMapSettings = () => {
return (
<Card>
<CardContent>
<Typography
variant={'h6'}
gutterBottom={true}>
{'Map settings'}
</Typography>
<FormGroup>
<FormControlLabel
control={
<Switch
color='secondary'
name={SettingKeys.ShowDataOverlayOnMap}
checked={getSetting(SettingKeys.ShowDataOverlayOnMap, 'boolean')}
onChange={handleSettingsChange} />
}
label="Show data overlay on map"
/>
<FormControlLabel
control={
<Switch
color='secondary'
name={SettingKeys.ShowLogOverlayOnMap}
checked={getSetting(SettingKeys.ShowLogOverlayOnMap, 'boolean')}
onChange={handleSettingsChange} />
}
label="Show log overlay on map"
/>
</FormGroup>
</CardContent>
</Card>
);
};
return (
<ViewContainer
isScrollLocked={true}>
{renderAppSettings()}
<Box sx={{ height: (theme) => theme.spacing(1) }} />
{renderMapSettings()}
</ViewContainer>
);
}
Example #14
Source File: select.tsx From Search-Next with GNU General Public License v3.0 | 4 votes |
Select: React.FC<SelectProps> = ({
label,
size = 'small',
options,
optionsConfig,
helperText,
error,
inputRef,
...props
}) => {
const theme = createTheme();
return (
<Box sx={{ minWidth: 120 }}>
<FormControl fullWidth>
<InputLabel
id={`mui-select-label-${label}`}
className={css`
&.MuiFormLabel-root {
transform: translate(14px, 9px) scale(1);
}
&.Mui-focused,
&.MuiFormLabel-filled {
transform: translate(14px, -9px) scale(0.75);
}
`}
>
{label}
</InputLabel>
<StyledSelect
{...props}
labelId={`mui-select-label-${label}`}
id={`mui-select-${label}`}
inputRef={inputRef}
label={label}
size={size}
error={error}
onClose={(e) => e.stopPropagation()}
MenuProps={{
sx: {
'& .MuiPaper-root': {
backgroundColor: 'rgba(253, 253, 253, 0.8)',
backdropFilter: 'blur(8px)',
borderRadius: '4px',
marginTop: theme.spacing(1),
minWidth: 140,
color:
theme.palette.mode === 'light'
? 'rgb(55, 65, 81)'
: theme.palette.grey[300],
boxShadow:
'rgb(255, 255, 255) 0px 0px 0px 0px, rgba(0, 0, 0, 0.05) 0px 0px 0px 1px, rgba(0, 0, 0, 0.1) 0px 10px 15px -3px, rgba(0, 0, 0, 0.05) 0px 4px 6px -2px',
'& .MuiMenu-list': {
padding: '0 4px',
},
'& .MuiMenuItem-root': {
borderRadius: '4px',
padding: '4px 8px',
margin: '4px 0',
fontSize: '14px',
transition: 'all 0.3s',
'& .MuiSvgIcon-root': {
fontSize: '14px',
},
'&:active': {
backgroundColor: alpha(
theme.palette.primary.main,
theme.palette.action.selectedOpacity,
),
},
},
},
},
}}
>
{options.map((i) => {
const label =
optionsConfig && optionsConfig.label
? i[optionsConfig.label]
: i.label;
const value =
optionsConfig && optionsConfig.value
? i[optionsConfig.value]
: i.value;
return (
<MenuItem key={value} value={value}>
{label}
</MenuItem>
);
})}
</StyledSelect>
<FormHelperText error={error}>{helperText}</FormHelperText>
</FormControl>
</Box>
);
}
Example #15
Source File: RegionSelectWrapper.tsx From console with GNU Affero General Public License v3.0 | 4 votes |
RegionSelectWrapper = ({
label,
onChange,
id,
name,
type,
tooltip = "",
index = 0,
error = "",
required = false,
overlayId,
overlayIcon = null,
overlayObject = null,
extraInputProps = {},
overlayAction,
noLabelMinWidth = false,
classes,
className = "",
}: RegionSelectBoxProps) => {
const inputClasses = inputStyles();
let inputProps: any = {
"data-index": index,
...extraInputProps,
name: name,
id: id,
classes: inputClasses,
};
return (
<React.Fragment>
<Grid
container
className={clsx(
className !== "" ? className : "",
error !== "" ? classes.errorInField : classes.inputBoxContainer
)}
>
{label !== "" && (
<InputLabel
htmlFor={id}
className={
noLabelMinWidth ? classes.noMinWidthLabel : classes.inputLabel
}
>
<span>
{label}
{required ? "*" : ""}
</span>
{tooltip !== "" && (
<div className={classes.tooltipContainer}>
<Tooltip title={tooltip} placement="top-start">
<div className={classes.tooltip}>
<HelpIcon />
</div>
</Tooltip>
</div>
)}
</InputLabel>
)}
<div className={classes.textBoxContainer}>
<RegionSelect
type={type}
inputProps={inputProps}
onChange={onChange}
/>
{overlayIcon && (
<div
className={`${classes.overlayAction} ${
label !== "" ? "withLabel" : ""
}`}
>
<IconButton
onClick={
overlayAction
? () => {
overlayAction();
}
: () => null
}
id={overlayId}
size={"small"}
disableFocusRipple={false}
disableRipple={false}
disableTouchRipple={false}
>
{overlayIcon}
</IconButton>
</div>
)}
{overlayObject && (
<div
className={`${classes.overlayAction} ${
label !== "" ? "withLabel" : ""
}`}
>
{overlayObject}
</div>
)}
</div>
</Grid>
</React.Fragment>
);
}
Example #16
Source File: ItemViewer.tsx From NekoMaid with MIT License | 4 votes |
ItemEditor: React.FC = () => {
const plugin = usePlugin()
const theme = useTheme()
const [item, setItem] = useState<Item | undefined>()
const [types, setTypes] = useState<string[]>([])
const [tab, setTab] = useState(0)
const [level, setLevel] = useState(1)
const [enchantment, setEnchantment] = useState<string | undefined>()
const [nbtText, setNBTText] = useState('')
const nbt: NBT = item?.nbt ? parse(item.nbt) : { id: 'minecraft:' + (item?.type || 'air').toLowerCase(), Count: new Byte(1) } as any
useEffect(() => {
if (!item || types.length) return
plugin.emit('item:fetch', (a: string[], b: string[]) => {
setTypes(a)
enchantments = b
})
}, [item])
useEffect(() => {
_setItem = (it: any) => {
setItem(it)
setNBTText(it.nbt ? stringify(parse(it.nbt), { pretty: true }) : '')
}
return () => { _setItem = null }
}, [])
const cancel = () => {
setItem(undefined)
if (_resolve) {
_resolve(false)
_resolve = null
}
}
const update = () => {
const newItem: any = { ...item }
if (nbt) {
newItem.nbt = stringify(nbt as any)
setNBTText(stringify(nbt, { pretty: true }))
}
setItem(newItem)
}
const isAir = item?.type === 'AIR'
const name = nbt?.tag?.display?.Name
const enchantmentMap: Record<string, true> = { }
return <Dialog open={!!item} onClose={cancel}>
<DialogTitle>{lang.itemEditor.title}</DialogTitle>
<DialogContent sx={{ display: 'flex', flexWrap: 'wrap', justifyContent: 'center' }}>
{item && <Box sx={{ display: 'flex', width: '100%', justifyContent: 'center' }}>
<ItemViewer item={item} />
<Autocomplete
options={types}
sx={{ maxWidth: 300, marginLeft: 1, flexGrow: 1 }}
value={item?.type}
onChange={(_, it) => {
item.type = it || 'AIR'
if (nbt) nbt.id = 'minecraft:' + (it ? it.toLowerCase() : 'air')
update()
}}
getOptionLabel={it => {
const locatedName = getName(it.toLowerCase())
return (locatedName ? locatedName + ' ' : '') + it
}}
renderInput={(params) => <TextField {...params} label={lang.itemEditor.itemType} size='small' variant='standard' />}
/>
</Box>}
<Tabs centered value={tab} onChange={(_, it) => setTab(it)} sx={{ marginBottom: 2 }}>
<Tab label={lang.itemEditor.baseAttribute} disabled={isAir} />
<Tab label={minecraft['container.enchant']} disabled={isAir} />
<Tab label='NBT' disabled={isAir} />
</Tabs>
{nbt && tab === 0 && <Grid container spacing={1} rowSpacing={1}>
<Grid item xs={12} md={6}><TextField
fullWidth
label={lang.itemEditor.count}
type='number'
variant='standard'
value={nbt.Count}
disabled={isAir}
onChange={e => {
nbt.Count = new Byte(item!.amount = parseInt(e.target.value))
update()
}}
/></Grid>
<Grid item xs={12} md={6}><TextField
fullWidth
label={lang.itemEditor.damage}
type='number'
variant='standard'
value={nbt.tag?.Damage}
disabled={isAir}
onChange={e => {
set(nbt, 'tag.Damage', parseInt(e.target.value))
update()
}}
/></Grid>
<Grid item xs={12} md={6}>
<TextField
fullWidth
label={lang.itemEditor.displayName}
variant='standard'
disabled={isAir}
value={name ? stringifyTextComponent(JSON.parse(name)) : ''}
onChange={e => {
set(nbt, 'tag.display.Name', JSON.stringify(item!.name = e.target.value))
update()
}}
/>
<FormControlLabel
label={minecraft['item.unbreakable']}
disabled={isAir}
checked={nbt.tag?.Unbreakable?.value === 1}
control={<Checkbox
checked={nbt.tag?.Unbreakable?.value === 1}
onChange={e => {
set(nbt, 'tag.Unbreakable', new Byte(+e.target.checked))
update()
}} />
}
/>
</Grid>
<Grid item xs={12} md={6}><TextField
fullWidth
multiline
label={lang.itemEditor.lore}
variant='standard'
maxRows={5}
disabled={isAir}
value={nbt.tag?.display?.Lore?.map(l => stringifyTextComponent(JSON.parse(l)))?.join('\n') || ''}
onChange={e => {
set(nbt, 'tag.display.Lore', e.target.value.split('\n').map(text => JSON.stringify(text)))
update()
}}
/></Grid>
</Grid>}
{nbt && tab === 1 && <Grid container spacing={1} sx={{ width: '100%' }}>
{nbt.tag?.Enchantments?.map((it, i) => {
enchantmentMap[it.id] = true
return <Grid item key={i}><Chip label={getEnchantmentName(it)} onDelete={() => {
nbt?.tag?.Enchantments?.splice(i, 1)
update()
}} /></Grid>
})}
<Grid item><Chip label={lang.itemEditor.newEnchantment} color='primary' onClick={() => {
setEnchantment('')
setLevel(1)
}} /></Grid>
<Dialog onClose={() => setEnchantment(undefined)} open={enchantment != null}>
<DialogTitle>{lang.itemEditor.newEnchantmentTitle}</DialogTitle>
<DialogContent>
<Box component='form' sx={{ display: 'flex', flexWrap: 'wrap' }}>
<FormControl variant='standard' sx={{ m: 1, minWidth: 120 }}>
<InputLabel htmlFor='item-editor-enchantment-selector'>{minecraft['container.enchant']}</InputLabel>
<Select
id='item-editor-enchantment-selector'
label={minecraft['container.enchant']}
value={enchantment || ''}
onChange={e => setEnchantment(e.target.value)}
>{enchantments
.filter(e => !(e in enchantmentMap))
.map(it => <MenuItem key={it} value={it}>{getEnchantmentName(it)}</MenuItem>)}
</Select>
</FormControl>
<FormControl sx={{ m: 1, minWidth: 120 }}>
<TextField
label={lang.itemEditor.level}
type='number'
variant='standard'
value={level}
onChange={e => setLevel(parseInt(e.target.value))}
/>
</FormControl>
</Box>
</DialogContent>
<DialogActions>
<Button onClick={() => setEnchantment(undefined)}>{minecraft['gui.cancel']}</Button>
<Button disabled={!enchantment || isNaN(level)} onClick={() => {
if (nbt) {
if (!nbt.tag) nbt.tag = { Damage: new Int(0) }
;(nbt.tag.Enchantments || (nbt.tag.Enchantments = [])).push({ id: enchantment!, lvl: new Short(level) })
}
setEnchantment(undefined)
update()
}}>{minecraft['gui.ok']}</Button>
</DialogActions>
</Dialog>
</Grid>}
</DialogContent>
{nbt && tab === 2 && <Box sx={{
'& .CodeMirror': { width: '100%' },
'& .CodeMirror-dialog, .CodeMirror-scrollbar-filler': { backgroundColor: theme.palette.background.paper + '!important' }
}}>
<UnControlled
value={nbtText}
options={{
mode: 'javascript',
phrases: lang.codeMirrorPhrases,
theme: theme.palette.mode === 'dark' ? 'material' : 'one-light'
}}
onChange={(_: any, __: any, nbt: string) => {
const n = parse(nbt) as any as NBT
const newItem: any = { ...item, nbt }
if (n.Count?.value != null) newItem.amount = n.Count.value
setItem(newItem)
}}
/>
</Box>}
<DialogActions>
<Button onClick={cancel}>{minecraft['gui.cancel']}</Button>
<Button onClick={() => {
setItem(undefined)
if (_resolve) {
_resolve(!item || item.type === 'AIR' ? null : item)
_resolve = null
}
}}>{minecraft['gui.ok']}</Button>
</DialogActions>
</Dialog>
}
Example #17
Source File: Withdraw.tsx From wrap.scrt.network with MIT License | 4 votes |
export default function Withdraw({
token,
secretjs,
secretAddress,
balances,
onSuccess,
onFailure,
}: {
token: Token;
secretjs: SecretNetworkClient | null;
secretAddress: string;
balances: Map<string, string>;
onSuccess: (txhash: string) => any;
onFailure: (error: any) => any;
}) {
const [targetAddress, setTargetAddress] = useState<string>("");
const [loadingTx, setLoading] = useState<boolean>(false);
const [selectedChainIndex, setSelectedChainIndex] = useState<number>(0);
const inputRef = useRef<any>();
const maxButtonRef = useRef<any>();
const sourceChain = chains["Secret Network"];
const targetChain =
chains[token.withdrawals[selectedChainIndex].target_chain_name];
const availableBalance =
balances.get(token.withdrawals[selectedChainIndex].from_denom) || "";
useEffect(() => {
(async () => {
while (!window.keplr || !window.getOfflineSignerOnlyAmino) {
await sleep(100);
}
// Find address on target chain
const { chain_id: targetChainId } =
chains[token.withdrawals[selectedChainIndex].target_chain_name];
if (token.withdrawals[selectedChainIndex].target_chain_name === "Terra") {
await suggestTerraToKeplr(window.keplr);
}
await window.keplr.enable(targetChainId);
const targetOfflineSigner =
window.getOfflineSignerOnlyAmino(targetChainId);
const targetFromAccounts = await targetOfflineSigner.getAccounts();
setTargetAddress(targetFromAccounts[0].address);
})();
}, [selectedChainIndex]);
return (
<>
<div style={{ padding: "1.5em" }}>
<div
style={{
display: "flex",
placeItems: "center",
gap: "0.5em",
}}
>
<Typography>
Withdraw <strong>{token.name}</strong> from{" "}
<strong>Secret Network</strong> to
</Typography>
<If condition={token.withdrawals.length === 1}>
<Then>
<Typography sx={{ marginLeft: "-0.2em" }}>
<strong>
{token.withdrawals[selectedChainIndex].target_chain_name}
</strong>
</Typography>
</Then>
<Else>
<FormControl>
<Select
value={selectedChainIndex}
onChange={(e) =>
setSelectedChainIndex(Number(e.target.value))
}
>
{token.withdrawals.map((chain, index) => (
<MenuItem value={index} key={index}>
<div
style={{
display: "flex",
gap: "0.5em",
placeItems: "center",
}}
>
<Avatar
src={chains[chain.target_chain_name].chain_image}
sx={{
marginLeft: "0.3em",
width: "1em",
height: "1em",
boxShadow: "rgba(0, 0, 0, 0.15) 0px 6px 10px",
}}
/>
<strong>{chain.target_chain_name}</strong>
</div>
</MenuItem>
))}
</Select>
</FormControl>
</Else>
</If>
</div>
<br />
<div
style={{
display: "flex",
placeContent: "space-between",
placeItems: "center",
gap: "1em",
}}
>
<Typography sx={{ fontWeight: "bold" }}>From:</Typography>
<CopyableAddress
address={secretAddress}
explorerPrefix={sourceChain.explorer_account}
/>
</div>
<div
style={{
display: "flex",
placeContent: "space-between",
placeItems: "center",
gap: "1em",
}}
>
<Typography sx={{ fontWeight: "bold" }}>To:</Typography>
<CopyableAddress
address={targetAddress}
explorerPrefix={targetChain.explorer_account}
/>
</div>
<br />
<div
style={{
display: "flex",
placeItems: "center",
gap: "0.3em",
marginBottom: "0.8em",
}}
>
<Typography sx={{ fontSize: "0.8em", fontWeight: "bold" }}>
Available to Withdraw:
</Typography>
<Typography
sx={{
fontSize: "0.8em",
opacity: 0.8,
cursor: "pointer",
}}
onClick={() => {
maxButtonRef.current.click();
}}
>
{(() => {
if (availableBalance === "") {
return <CircularProgress size="0.6em" />;
}
const prettyBalance = new BigNumber(availableBalance)
.dividedBy(`1e${token.decimals}`)
.toFormat();
if (prettyBalance === "NaN") {
return "Error";
}
return `${prettyBalance} ${token.name}`;
})()}
</Typography>
</div>
<FormControl sx={{ width: "100%" }} variant="standard">
<InputLabel htmlFor="Amount to Withdraw">
Amount to Withdraw
</InputLabel>
<Input
autoFocus
id="Amount to Withdraw"
fullWidth
type="text"
inputRef={inputRef}
startAdornment={
<InputAdornment position="start">
<Avatar
src={token.image}
sx={{
width: "1em",
height: "1em",
boxShadow: "rgba(0, 0, 0, 0.15) 0px 6px 10px",
}}
/>
</InputAdornment>
}
endAdornment={
<InputAdornment position="end">
<Button
ref={maxButtonRef}
style={{
padding: "0.1em 0.5em",
minWidth: 0,
}}
onClick={() => {
if (availableBalance === "") {
return;
}
const prettyBalance = new BigNumber(availableBalance)
.dividedBy(`1e${token.decimals}`)
.toFormat();
if (prettyBalance === "NaN") {
return;
}
inputRef.current.value = prettyBalance;
}}
>
MAX
</Button>
</InputAdornment>
}
/>
</FormControl>
</div>
<div
style={{
display: "flex",
placeContent: "center",
marginBottom: "0.4em",
}}
>
<LoadingButton
variant="contained"
sx={{
padding: "0.5em 0",
width: "10em",
fontWeight: "bold",
fontSize: "1.2em",
}}
loading={loadingTx}
onClick={async () => {
if (!secretjs) {
console.error("No secretjs");
return;
}
if (!inputRef?.current?.value) {
console.error("Empty withdraw");
return;
}
const normalizedAmount = (inputRef.current.value as string).replace(
/,/g,
""
);
if (!(Number(normalizedAmount) > 0)) {
console.error(`${normalizedAmount} not bigger than 0`);
return;
}
setLoading(true);
const amount = new BigNumber(normalizedAmount)
.multipliedBy(`1e${token.decimals}`)
.toFixed(0, BigNumber.ROUND_DOWN);
const { withdraw_channel_id, withdraw_gas } =
chains[token.withdrawals[selectedChainIndex].target_chain_name];
try {
const tx = await secretjs.tx.broadcast(
[
new MsgTransfer({
sender: secretAddress,
receiver: targetAddress,
sourceChannel: withdraw_channel_id,
sourcePort: "transfer",
token: {
amount,
denom: token.withdrawals[selectedChainIndex].from_denom,
},
timeoutTimestampSec: String(
Math.floor(Date.now() / 1000) + 15 * 60
), // 15 minute timeout
}),
],
{
gasLimit: withdraw_gas,
gasPriceInFeeDenom: 0.25,
feeDenom: "uscrt",
}
);
if (tx.code === 0) {
inputRef.current.value = "";
onSuccess(tx.transactionHash);
} else {
onFailure(tx.rawLog);
}
} catch (e) {
onFailure(e);
} finally {
setLoading(false);
}
}}
>
Withdraw
</LoadingButton>
</div>
</>
);
}
Example #18
Source File: Form.tsx From frontend with MIT License | 4 votes |
export default function Form() {
const router = useRouter()
const { t } = useTranslation()
let id = router.query.id
const [beneficiaryType, setBeneficiaryType] = useState<string>('')
const [personId, setPersonId] = useState<string>('')
const [companyId, setCompanyId] = useState<string>('')
const [coordinatorId, setCoordinatorId] = useState<string>('')
const [cityId, setCityId] = useState<string>('')
const [countryCode, setCountryCode] = useState<string>('')
const people = usePeopleList().data
const companies = useCompaniesList().data
const coordinators = useCoordinatorsList().data
const coordinatorRelations = Object.values(PersonRelation)
const cities = useCitiesList().data
const countries = useCountriesList().data
let initialValues: BeneficiaryFormData = {
type: beneficiaryType,
personId: personId,
companyId: companyId,
coordinatorId: coordinatorId,
countryCode: countryCode,
cityId: cityId,
description: '',
publicData: '',
privateData: '',
coordinatorRelation: 'none',
campaigns: [],
}
if (id) {
id = String(id)
const { data }: UseQueryResult<BeneficiaryListResponse> = useViewBeneficiary(id)
initialValues = {
type: data?.type,
cityId: data?.cityId || '',
companyId: data?.companyId || '',
coordinatorId: data?.coordinatorId || '',
countryCode: data?.countryCode || '',
description: data?.description || '',
personId: data?.personId || '',
privateData: data?.privateData || '',
publicData: data?.publicData || '',
coordinatorRelation: data?.coordinatorRelation || '',
campaigns: data?.campaigns || [],
}
}
const mutationFn = id ? useEditBeneficiary(id) : useCreateBeneficiary()
const mutation = useMutation<
AxiosResponse<BeneficiaryListResponse>,
AxiosError<ApiErrors>,
BeneficiaryFormData
>({
mutationFn,
onError: () => AlertStore.show(t('documents:alerts:error'), 'error'),
onSuccess: () => {
AlertStore.show(id ? t('documents:alerts:edit') : t('documents:alerts:create'), 'success')
router.push(routes.admin.beneficiary.index)
},
})
async function onSubmit(data: BeneficiaryFormData) {
mutation.mutateAsync(data)
}
return (
<GenericForm
onSubmit={onSubmit}
initialValues={initialValues}
validationSchema={validationSchema}>
<Box sx={{ height: '62.6vh', marginBottom: '9%' }}>
<Typography variant="h5" component="h2" sx={{ textAlign: 'center' }}>
{id ? t('beneficiary:forms:edit-heading') : t('beneficiary:forms:add-heading')}
</Typography>
<Grid container spacing={2}>
<Grid item xs={12}>
<InputLabel>{t('beneficiary:grid:type')}</InputLabel>
<Select
fullWidth
sx={{ height: '55%' }}
name="type"
defaultValue={initialValues.type}
onChange={(e: SelectChangeEvent) => {
setBeneficiaryType(e.target.value)
}}>
<MenuItem value="">
<em>None</em>
</MenuItem>
{Object.values(LegalEntityType)?.map((type) => {
return (
<MenuItem key={type} value={type}>
{t('beneficiary:grid:' + type)}
</MenuItem>
)
})}
</Select>
</Grid>
<Grid item xs={6}>
<InputLabel>{t('beneficiary:grid:individual')}</InputLabel>
<Select
fullWidth
sx={{ height: '55%' }}
name="personId"
defaultValue={initialValues.personId}
onChange={(e: SelectChangeEvent) => {
setPersonId(e.target.value)
}}>
<MenuItem value="">
<em>None</em>
</MenuItem>
{people?.map((person) => {
return (
<MenuItem key={person.id} value={person.id}>
{person.firstName + ' ' + person.lastName}
</MenuItem>
)
})}
</Select>
</Grid>
<Grid item xs={6}>
<InputLabel>{t('beneficiary:grid:company')}</InputLabel>
<Select
fullWidth
sx={{ height: '55%' }}
name="companyId"
defaultValue={initialValues.personId}
onChange={(e: SelectChangeEvent) => {
setCompanyId(e.target.value)
}}>
<MenuItem value="">
<em>None</em>
</MenuItem>
{companies?.map((company) => {
return (
<MenuItem key={company.id} value={company.id}>
{company.companyName}
</MenuItem>
)
})}
</Select>
</Grid>
<Grid item xs={6}>
<InputLabel>{t('beneficiary:grid:coordinatorRelation')}</InputLabel>
<Select
fullWidth
sx={{ height: '55%' }}
name="coordinatorRelation"
defaultValue={initialValues.coordinatorRelation}
onChange={(e: SelectChangeEvent) => {
setPersonId(e.target.value)
}}>
<MenuItem value="">
<em>None</em>
</MenuItem>
{coordinatorRelations?.map((relation) => {
return (
<MenuItem key={relation} value={relation}>
{relation}
</MenuItem>
)
})}
</Select>
</Grid>
<Grid item xs={6}>
<InputLabel>{t('beneficiary:grid:coordinator')}</InputLabel>
<Select
fullWidth
sx={{ height: '55%' }}
name="coordinatorId"
defaultValue={initialValues.coordinatorId}
onChange={(e: SelectChangeEvent) => {
setCoordinatorId(e.target.value)
}}>
<MenuItem value="">
<em>None</em>
</MenuItem>
{coordinators?.map((coordinator) => {
return (
<MenuItem key={coordinator.id} value={coordinator.id}>
{coordinator.person.firstName} {coordinator.person.lastName}
</MenuItem>
)
})}
</Select>
</Grid>
<Grid item xs={6}>
<InputLabel>{t('beneficiary:grid:countryCode')}</InputLabel>
<Select
fullWidth
sx={{ height: '55%' }}
name="countryCode"
defaultValue={initialValues.countryCode}
onChange={(e: SelectChangeEvent) => {
setCountryCode(e.target.value)
}}>
<MenuItem value="">
<em>None</em>
</MenuItem>
{countries?.map((country) => {
return (
<MenuItem key={country.id} value={country.countryCode}>
{country.countryCode} - {country.name}
</MenuItem>
)
})}
</Select>
</Grid>
<Grid item xs={6}>
<InputLabel>{t('beneficiary:grid:city')}</InputLabel>
<Select
fullWidth
sx={{ height: '55%' }}
name="cityId"
defaultValue={initialValues.cityId}
onChange={(e: SelectChangeEvent) => {
setCityId(e.target.value)
}}>
<MenuItem value="">
<em>None</em>
</MenuItem>
{cities?.map((city) => {
return (
<MenuItem key={city.id} value={city.id}>
{city.name}
</MenuItem>
)
})}
</Select>
</Grid>
<Grid item xs={6}>
<FormTextField
type="text"
name="description"
autoComplete="target-amount"
label={t('beneficiary:grid:description')}
multiline
rows={1.5}
defaultValue={initialValues.description}
/>
</Grid>
<Grid item xs={6}>
<SubmitButton fullWidth label={t('documents:cta:submit')} />
</Grid>
<Grid item xs={6}>
<Link href={routes.admin.beneficiary.index} passHref>
<Button>{t('documents:cta:cancel')}</Button>
</Link>
</Grid>
</Grid>
</Box>
</GenericForm>
)
}
Example #19
Source File: Deposit.tsx From wrap.scrt.network with MIT License | 4 votes |
export default function Deposit({
token,
secretAddress,
onSuccess,
onFailure,
}: {
token: Token;
secretAddress: string;
onSuccess: (txhash: string) => any;
onFailure: (error: any) => any;
}) {
const [sourceAddress, setSourceAddress] = useState<string>("");
const [availableBalance, setAvailableBalance] = useState<string>("");
const [loadingTx, setLoading] = useState<boolean>(false);
const [sourceCosmJs, setSourceCosmJs] =
useState<SigningStargateClient | null>(null);
const [selectedChainIndex, setSelectedChainIndex] = useState<number>(0);
const [fetchBalanceInterval, setFetchBalanceInterval] = useState<any>(null);
const inputRef = useRef<any>();
const maxButtonRef = useRef<any>();
const sourceChain =
chains[token.deposits[selectedChainIndex].source_chain_name];
const targetChain = chains["Secret Network"];
const fetchSourceBalance = async (sourceAddress: string) => {
const url = `${
chains[token.deposits[selectedChainIndex].source_chain_name].lcd
}/bank/balances/${sourceAddress}`;
try {
const response = await fetch(url);
const result: {
height: string;
result: Array<{ denom: string; amount: string }>;
} = await response.json();
const balance =
result.result.find(
(c) => c.denom === token.deposits[selectedChainIndex].from_denom
)?.amount || "0";
setAvailableBalance(balance);
} catch (e) {
console.error(`Error while trying to query ${url}:`, e);
setAvailableBalance("Error");
}
};
useEffect(() => {
setAvailableBalance("");
if (!sourceAddress) {
return;
}
if (fetchBalanceInterval) {
clearInterval(fetchBalanceInterval);
}
fetchSourceBalance(sourceAddress);
const interval = setInterval(
() => fetchSourceBalance(sourceAddress),
10_000
);
setFetchBalanceInterval(interval);
return () => clearInterval(interval);
}, [sourceAddress]);
useEffect(() => {
(async () => {
while (!window.keplr || !window.getOfflineSignerOnlyAmino) {
await sleep(100);
}
if (["LUNA", "UST"].includes(token.name.toUpperCase())) {
await suggestTerraToKeplr(window.keplr);
}
// Initialize cosmjs on the target chain, because it has sendIbcTokens()
const { chain_id, rpc, bech32_prefix } =
chains[token.deposits[selectedChainIndex].source_chain_name];
await window.keplr.enable(chain_id);
const sourceOfflineSigner = window.getOfflineSignerOnlyAmino(chain_id);
const depositFromAccounts = await sourceOfflineSigner.getAccounts();
setSourceAddress(depositFromAccounts[0].address);
const cosmjs = await SigningStargateClient.connectWithSigner(
rpc,
sourceOfflineSigner,
{ prefix: bech32_prefix, broadcastPollIntervalMs: 10_000 }
);
setSourceCosmJs(cosmjs);
})();
}, [selectedChainIndex]);
return (
<>
<div style={{ padding: "1.5em" }}>
<div
style={{
display: "flex",
placeItems: "center",
gap: token.deposits.length === 1 ? "0.3em" : "0.5em",
}}
>
<Typography>
Deposit <strong>{token.name}</strong> from
</Typography>
<If condition={token.deposits.length === 1}>
<Then>
<Typography>
<strong>
{token.deposits[selectedChainIndex].source_chain_name}
</strong>
</Typography>
</Then>
<Else>
<FormControl>
<Select
value={selectedChainIndex}
onChange={(e) =>
setSelectedChainIndex(Number(e.target.value))
}
>
{token.deposits.map((chain, index) => (
<MenuItem value={index} key={index}>
<div
style={{
display: "flex",
gap: "0.5em",
placeItems: "center",
}}
>
<Avatar
src={chains[chain.source_chain_name].chain_image}
sx={{
marginLeft: "0.3em",
width: "1em",
height: "1em",
boxShadow: "rgba(0, 0, 0, 0.15) 0px 6px 10px",
}}
/>
<strong>{chain.source_chain_name}</strong>
</div>
</MenuItem>
))}
</Select>
</FormControl>
</Else>
</If>
<Typography>
to <strong>Secret Network</strong>
</Typography>
</div>
<br />
<div
style={{
display: "flex",
placeContent: "space-between",
placeItems: "center",
gap: "1em",
}}
>
<Typography sx={{ fontWeight: "bold" }}>From:</Typography>
<CopyableAddress
address={sourceAddress}
explorerPrefix={sourceChain.explorer_account}
/>
</div>
<div
style={{
display: "flex",
placeContent: "space-between",
placeItems: "center",
gap: "1em",
}}
>
<Typography sx={{ fontWeight: "bold" }}>To:</Typography>
<CopyableAddress
address={secretAddress}
explorerPrefix={targetChain.explorer_account}
/>
</div>
<br />
<div
style={{
display: "flex",
placeItems: "center",
gap: "0.3em",
marginBottom: "0.8em",
}}
>
<Typography sx={{ fontSize: "0.8em", fontWeight: "bold" }}>
Available to Deposit:
</Typography>
<Typography
sx={{
fontSize: "0.8em",
opacity: 0.8,
cursor: "pointer",
}}
onClick={() => {
maxButtonRef.current.click();
}}
>
{(() => {
if (availableBalance === "") {
return <CircularProgress size="0.6em" />;
}
const prettyBalance = new BigNumber(availableBalance)
.dividedBy(`1e${token.decimals}`)
.toFormat();
if (prettyBalance === "NaN") {
return "Error";
}
return `${prettyBalance} ${token.name}`;
})()}
</Typography>
</div>
<FormControl sx={{ width: "100%" }} variant="standard">
<InputLabel htmlFor="Amount to Deposit">Amount to Deposit</InputLabel>
<Input
autoFocus
id="Amount to Deposit"
fullWidth
type="text"
inputRef={inputRef}
startAdornment={
<InputAdornment position="start">
<Avatar
src={token.image}
sx={{
width: "1em",
height: "1em",
boxShadow: "rgba(0, 0, 0, 0.15) 0px 6px 10px",
}}
/>
</InputAdornment>
}
endAdornment={
<InputAdornment position="end">
<Button
ref={maxButtonRef}
style={{
padding: "0.1em 0.5em",
minWidth: 0,
}}
onClick={() => {
if (availableBalance === "") {
return;
}
const prettyBalance = new BigNumber(availableBalance)
.dividedBy(`1e${token.decimals}`)
.toFormat();
if (prettyBalance === "NaN") {
return;
}
inputRef.current.value = prettyBalance;
}}
>
MAX
</Button>
</InputAdornment>
}
/>
</FormControl>
</div>
<div
style={{
display: "flex",
placeContent: "center",
marginBottom: "0.4em",
}}
>
<LoadingButton
variant="contained"
sx={{
padding: "0.5em 0",
width: "10em",
fontWeight: "bold",
fontSize: "1.2em",
}}
loading={loadingTx}
onClick={async () => {
if (!sourceCosmJs) {
console.error("No cosmjs");
return;
}
if (!inputRef?.current?.value) {
console.error("Empty deposit");
return;
}
const normalizedAmount = (inputRef.current.value as string).replace(
/,/g,
""
);
if (!(Number(normalizedAmount) > 0)) {
console.error(`${normalizedAmount} not bigger than 0`);
return;
}
setLoading(true);
const amount = new BigNumber(normalizedAmount)
.multipliedBy(`1e${token.decimals}`)
.toFixed(0, BigNumber.ROUND_DOWN);
const { deposit_channel_id, deposit_gas } =
chains[token.deposits[selectedChainIndex].source_chain_name];
try {
const { transactionHash } = await sourceCosmJs.sendIbcTokens(
sourceAddress,
secretAddress,
{
amount,
denom: token.deposits[selectedChainIndex].from_denom,
},
"transfer",
deposit_channel_id,
undefined,
Math.floor(Date.now() / 1000) + 15 * 60, // 15 minute timeout
gasToFee(deposit_gas)
);
inputRef.current.value = "";
onSuccess(transactionHash);
} catch (e) {
onFailure(e);
} finally {
setLoading(false);
}
}}
>
Deposit
</LoadingButton>
</div>
</>
);
}
Example #20
Source File: PSBTDetail.tsx From sapio-studio with Mozilla Public License 2.0 | 4 votes |
export function PSBTDetail(props: IProps) {
const psbt_selection_form = React.useRef<HTMLSelectElement>(null);
const [psbt, setPSBT] = React.useState<Bitcoin.Psbt>(props.psbts[0]!);
const [flash, setFlash] = React.useState<JSX.Element | null>(null);
if (props.psbts.length === 0) return null;
function show_flash(
msg: string | JSX.Element,
color: string,
onclick?: () => void
) {
const click = onclick ?? (() => null);
const elt = (
<h3 style={{ color: color }} onClick={click}>
{msg}
</h3>
);
setFlash(elt);
setTimeout(() => setFlash(<div></div>), 2000);
}
const psbt_handler = new PSBTHandler(show_flash);
const selectable_psbts = props.psbts.map((w, i) => (
<MenuItem key={i} value={i}>
{i} -- {w.toBase64().substr(0, 16)}...
</MenuItem>
));
const [idx, set_idx] = React.useState(0);
React.useEffect(() => {
if (idx < props.psbts.length && idx >= 0) {
setPSBT(props.psbts[idx]!);
}
}, [idx, props.psbts]);
// missing horizontal
return (
<div className="PSBTDetail">
<InputLabel id="label-select-psbt">PSBT Selection</InputLabel>
<Select
labelId="label-select-psbt"
label="PSBT Selection"
variant="outlined"
ref={psbt_selection_form}
onChange={() => {
const idx: number =
parseInt(psbt_selection_form.current?.value ?? '0') ??
0;
set_idx(idx);
}}
>
{selectable_psbts}
</Select>
{flash}
<Hex
className="txhex"
value={psbt.toBase64()}
label="Selected PSBT"
></Hex>
<div className="PSBTActions">
<Tooltip title="Save PSBT to Disk">
<IconButton
aria-label="save-psbt-disk"
onClick={() => psbt_handler.save_psbt(psbt.toBase64())}
>
<SaveIcon style={{ color: red[500] }} />
</IconButton>
</Tooltip>
<Tooltip title="Sign PSBT using Node">
<IconButton
aria-label="sign-psbt-node"
onClick={async () => {
const new_psbt = await psbt_handler.sign_psbt(
psbt.toBase64()
);
// TODO: Confirm this saves to model?
psbt.combine(new_psbt);
setPSBT(psbt);
}}
>
<VpnKeyIcon style={{ color: yellow[500] }} />
</IconButton>
</Tooltip>
<Tooltip title="Combine PSBT from File">
<IconButton
aria-label="combine-psbt-file"
onClick={async () => {
// TODO: Confirm this saves to model?
await psbt_handler.combine_psbt(psbt);
setPSBT(psbt);
}}
>
<MergeTypeIcon style={{ color: purple[500] }} />
</IconButton>
</Tooltip>
<Tooltip title="Finalize and Broadcast PSBT with Node">
<IconButton
aria-label="combine-psbt-file"
onClick={async () => {
await psbt_handler.finalize_psbt(psbt.toBase64());
setPSBT(psbt);
}}
>
<SendIcon style={{ color: orange[500] }} />
</IconButton>
</Tooltip>
<div></div>
</div>
</div>
);
}
Example #21
Source File: EditForm.tsx From frontend with MIT License | 4 votes |
export default function EditForm() {
const queryClient = useQueryClient()
const router = useRouter()
const id = router.query.id
const { data }: UseQueryResult<WithdrawalEditResponse> = useWithdrawal(String(id))
const { data: bankAccounts } = useBankAccountsList()
const { data: campaigns } = useCampaignList()
const { data: personList } = usePersonList()
const { data: vaults } = useVaultsList()
const [bankAccountId, setBankAccountId] = useState(data?.bankAccountId)
const [vaultId, setVaultId] = useState(data?.sourceVaultId)
const [campaignId, setCampaignId] = useState(data?.sourceCampaignId)
const [approvedById, setApprovedById] = useState(data?.approvedById)
const { t } = useTranslation()
const mutationFn = useEditWithdrawal(String(id))
const initialValues: WithdrawalInput = {
status: WithdrawalStatus.initial,
currency: data?.currency,
amount: data?.amount,
reason: data?.reason,
sourceVaultId: vaultId,
sourceCampaignId: campaignId,
bankAccountId: bankAccountId,
documentId: '',
approvedById: approvedById,
}
const mutation = useMutation<
AxiosResponse<WithdrawalResponse>,
AxiosError<ApiErrors>,
WithdrawalInput
>({
mutationFn,
onError: () => AlertStore.show(t('withdrawals:alerts:error'), 'error'),
onSuccess: () => {
queryClient.invalidateQueries(endpoints.withdrawals.getWithdrawal(String(id)).url)
AlertStore.show(t('withdrawals:alerts:edit'), 'success')
router.push(routes.admin.withdrawals.index)
},
})
function handleSubmit(values: WithdrawalInput) {
const data: WithdrawalInput = {
status: WithdrawalStatus.initial,
currency: values.currency,
amount: values.amount,
reason: values.reason,
sourceVaultId: vaultId,
sourceCampaignId: campaignId,
bankAccountId: bankAccountId,
documentId: 'ff89a831-34da-4b2d-91bc-742247efd9b8',
approvedById: approvedById,
}
mutation.mutate(data)
}
return (
<GenericForm
onSubmit={handleSubmit}
initialValues={initialValues}
validationSchema={validationSchema}>
<Box>
<Typography variant="h5" component="h2" sx={{ marginBottom: 2, textAlign: 'center' }}>
{t('withdrawals:form-heading')}
</Typography>
<Grid container spacing={2} sx={{ width: 600, margin: '0 auto' }}>
<Grid item xs={12}>
<FormTextField
type="number"
label="wihdrawals:Сума"
name="amount"
autoComplete="amount"
/>
</Grid>
<Grid item xs={12}>
<FormTextField
type="string"
label="wihdrawals:Причина"
name="reason"
autoComplete="reason"
/>
</Grid>
<Grid item xs={12}>
<CurrencySelect />
</Grid>
<Grid item xs={12}>
<InputLabel htmlFor="my-input">Банков акаунт</InputLabel>
<Select
fullWidth
id="bankAccountId"
name="bankAccountId"
value={bankAccountId}
onChange={(event) => setBankAccountId(event.target.value)}>
{bankAccounts?.map((acc) => {
return (
<MenuItem key={acc.id} value={acc.id}>
{acc.accountHolderName}
</MenuItem>
)
})}
</Select>
</Grid>
<Grid item xs={12}>
<InputLabel htmlFor="my-input">Кампании</InputLabel>
<Select
fullWidth
id="campaignId"
name="campaignId"
value={campaignId}
onChange={(event) => setCampaignId(event.target.value)}>
{campaigns?.map((camp) => {
return (
<MenuItem key={camp.id} value={camp.id}>
{camp.title}
</MenuItem>
)
})}
</Select>
</Grid>
<Grid item xs={12}>
<InputLabel htmlFor="my-input">Трезор</InputLabel>
<Select
fullWidth
id="vaultId"
name="vaultId"
value={vaultId}
onChange={(event) => setVaultId(event.target.value)}>
{vaults?.map((acc) => {
return (
<MenuItem key={acc.id} value={acc.id}>
{acc.name}
</MenuItem>
)
})}
</Select>
</Grid>
<Grid item xs={12}>
<InputLabel htmlFor="my-input">Одобрен от</InputLabel>
<Select
fullWidth
id="approvedById"
name="approvedById"
value={approvedById}
onChange={(event) => setApprovedById(event.target.value)}>
{personList?.map((acc) => {
return (
<MenuItem key={acc.id} value={acc.id}>
{acc.firstName} {acc.lastName}
</MenuItem>
)
})}
</Select>
</Grid>
<Grid item xs={6}>
<SubmitButton fullWidth label={t('withdrawals:cta:submit')} />
</Grid>
<Grid item xs={6}>
<Link href={routes.admin.withdrawals.index} passHref>
<Button fullWidth={true}>{t('withdrawals:cta:cancel')}</Button>
</Link>
</Grid>
</Grid>
</Box>
</GenericForm>
)
}
Example #22
Source File: ArrayEnumSelect.tsx From firecms with MIT License | 4 votes |
/**
* This fields renders a dropdown with multiple selection.
*
* This is one of the internal components that get mapped natively inside forms
* and tables to the specified properties.
* @category Form fields
*/
export function ArrayEnumSelect({
name,
value,
setValue,
error,
showError,
disabled,
property,
includeDescription,
autoFocus
}: FieldProps<EnumType[]>) {
const classes = formStyles();
if (!property.of) {
throw Error("Using wrong component ArrayEnumSelect");
}
if (property.of.dataType !== "string" && property.of.dataType !== "number") {
throw Error("Field misconfiguration: array field of type string or number");
}
const enumValues = property.of.config?.enumValues;
if (!enumValues) {
console.error(property);
throw Error("Field misconfiguration: array field of type string or number needs to have enumValues");
}
useClearRestoreValue({
property,
value,
setValue
});
const validValue = !!value && Array.isArray(value);
return (
<FormControl
variant="filled"
fullWidth
required={property.validation?.required}
error={showError}
>
<InputLabel id={`${name}-multiselect-label`}
classes={{
root: classes.inputLabel,
shrink: classes.shrinkInputLabel
}}>
<LabelWithIcon property={property}/>
</InputLabel>
<MuiSelect
multiple
sx={{
minHeight: "64px"
}}
variant={"filled"}
labelId={`${name}-multiselect-label`}
value={validValue ? value.map(v => v.toString()) : []}
autoFocus={autoFocus}
disabled={disabled}
onChange={(evt: any) => {
let newValue;
if (property.of?.dataType === "number")
newValue = evt.target.value ? evt.target.value.map((e: any) => parseFloat(e)) : [];
else
newValue = evt.target.value;
return setValue(
newValue
);
}}
renderValue={(selected: any) => (
<ArrayEnumPreview value={selected}
name={name}
enumValues={enumValues}
size={"regular"}/>
)}>
{enumToObjectEntries(enumValues)
.map(([enumKey, labelOrConfig]) => {
const checked = validValue && value.map(v => v.toString()).includes(enumKey.toString());
return (
<MenuItem key={`form-select-${name}-${enumKey}`}
value={enumKey}
disabled={isEnumValueDisabled(labelOrConfig)}
dense={true}>
<Checkbox checked={checked}/>
<ListItemText primary={
<EnumValuesChip
enumKey={enumKey}
enumValues={enumValues}
small={true}/>
}/>
</MenuItem>
);
})}
</MuiSelect>
{includeDescription &&
<FieldDescription property={property}/>}
{showError && <FormHelperText>{error}</FormHelperText>}
</FormControl>
);
}
Example #23
Source File: Form.tsx From frontend with MIT License | 4 votes |
export default function EditForm() {
const [type, setType] = useState('donation')
const [status, setStatus] = useState('initial')
const [provider, setProvider] = useState('none')
const [currency, setCurrency] = useState('')
const [vault, setVault] = useState('')
const router = useRouter()
const { t } = useTranslation()
let id = router.query.id
const vaults = useVaultsList().data
let initialValues: DonationInput = {
type: 'donation',
status: 'initial',
provider: 'none',
currency: '',
amount: 0,
targetVaultId: '',
extCustomerId: '',
extPaymentIntentId: '',
extPaymentMethodId: '',
}
if (id) {
id = String(id)
const { data }: UseQueryResult<DonationResponse> = useDonation(id)
if (data) {
initialValues = {
type: data?.type.toString(),
status: data?.status.toString(),
provider: data?.provider.toString(),
currency: data?.currency.toString(),
amount: data?.amount,
targetVaultId: data?.targetVaultId,
extCustomerId: data?.extCustomerId,
extPaymentIntentId: data?.extPaymentIntentId,
extPaymentMethodId: data?.extPaymentMethodId,
}
}
}
const mutationFn = id ? useEditDonation(id) : useCreateDonation()
const mutation = useMutation<
AxiosResponse<DonationResponse>,
AxiosError<ApiErrors>,
DonationInput
>({
mutationFn,
onError: () => AlertStore.show(t('donations:alerts:error'), 'error'),
onSuccess: () => {
AlertStore.show(id ? t('donations:alerts:edit') : t('donations:alerts:create'), 'success')
router.push(routes.admin.donations.index)
},
})
async function onSubmit(data: DonationInput) {
type ? (data.type = type) : ''
status ? (data.status = status) : ''
provider ? (data.provider = provider) : ''
currency ? (data.currency = currency) : ''
vault ? (data.targetVaultId = vault) : ''
mutation.mutate(data)
}
return (
<GenericForm
onSubmit={onSubmit}
initialValues={initialValues}
validationSchema={validationSchema}>
<Box sx={{ marginTop: '5%', height: '62.6vh' }}>
<Typography variant="h5" component="h2" sx={{ marginBottom: 2, textAlign: 'center' }}>
{id ? t('donations:edit-form-heading') : t('donations:form-heading')}
</Typography>
<Grid container spacing={2} sx={{ width: 600, margin: '0 auto' }}>
<Grid item xs={6}>
<FormControl fullWidth size="small">
<InputLabel id="labelType">{t('donations:type')}</InputLabel>
<Select
labelId="labelType"
label={t('donations:type')}
id="type"
name="type"
value={initialValues.type}
onChange={(e) => setType(e.target.value)}
disabled={id ? true : false}>
{validDonationTypes.map((type) => {
return (
<MenuItem key={type} value={type}>
{type}
</MenuItem>
)
})}
</Select>
</FormControl>
</Grid>
<Grid item xs={6}>
<FormControl fullWidth size="small">
<InputLabel id="labelStatus">{t('donations:status')}</InputLabel>
<Select
labelId="labelStatus"
label={t('donations:status')}
id="status"
name="status"
value={initialValues.status}
onChange={(e) => {
setStatus(e.target.value)
console.log(e.target.value)
}}>
{validDonationStatuses.map((stat) => {
return (
<MenuItem key={stat} value={stat}>
{stat}
</MenuItem>
)
})}
</Select>
</FormControl>
</Grid>
<Grid item xs={6}>
<FormControl fullWidth size="small">
<InputLabel id="labelProvider">{t('donations:provider')}</InputLabel>
<Select
labelId="labelProvider"
label={t('donations:provider')}
id="provider"
name="provider"
value={initialValues.provider}
onChange={(e) => setProvider(e.target.value)}
disabled={id ? true : false}>
{validProviders.map((prov) => {
return (
<MenuItem key={prov} value={prov}>
{prov}
</MenuItem>
)
})}
</Select>
</FormControl>
</Grid>
<Grid item xs={6}>
<FormControl fullWidth size="small">
<InputLabel id="labelVault">{t('donations:vault')}</InputLabel>
<Select
labelId="labelVault"
label={t('donations:vault')}
id="targetVaultId"
name="targetVaultId"
value={initialValues.targetVaultId}
onChange={(e) => setVault(e.target.value)}
disabled={id ? true : false}>
{vaults?.map((vault) => {
return (
<MenuItem key={vault.id} value={vault.id}>
{vault.name}
</MenuItem>
)
})}
</Select>
</FormControl>
</Grid>
<Grid item xs={12}>
<FormTextField
type="text"
label={t('donations:ext-customer-id')}
name="extCustomerId"
disabled={id ? true : false}
/>
</Grid>
<Grid item xs={6}>
<FormTextField
type="text"
label={t('donations:ext-payment-intent-id')}
name="extPaymentIntentId"
disabled={id ? true : false}
/>
</Grid>
<Grid item xs={6}>
<FormTextField
type="text"
label={t('donations:ext-payment-method-id')}
name="extPaymentMethodId"
disabled={id ? true : false}
/>
</Grid>
<Grid item xs={6}>
<FormTextField
type="number"
label={t('donations:amount')}
name="amount"
disabled={id ? true : false}
/>
</Grid>
<Grid item xs={6}>
<FormControl fullWidth size="small">
<InputLabel id="labelCurrency">{t('donations:currency')}</InputLabel>
<Select
labelId="labelCurrency"
label={t('donations:currency')}
id="currency"
name="currency"
value={initialValues.currency}
onChange={(e) => setCurrency(e.target.value)}
disabled={id ? true : false}>
{validCurrencies.map((currency) => {
return (
<MenuItem key={currency} value={currency}>
{currency}
</MenuItem>
)
})}
</Select>
</FormControl>
</Grid>
<Grid item xs={6}>
<SubmitButton fullWidth label={t('donations:cta:submit')} />
</Grid>
<Grid item xs={6}>
<Link passHref href={routes.admin.donations.index}>
<Button>{t('donations:cta:cancel')}</Button>
</Link>
</Grid>
</Grid>
</Box>
</GenericForm>
)
}
Example #24
Source File: TransactionList.tsx From abrechnung with GNU Affero General Public License v3.0 | 4 votes |
export default function TransactionList({ group }) {
const [speedDialOpen, setSpeedDialOpen] = useState(false);
const toggleSpeedDial = () => setSpeedDialOpen((currValue) => !currValue);
const [showTransferCreateDialog, setShowTransferCreateDialog] = useState(false);
const [showPurchaseCreateDialog, setShowPurchaseCreateDialog] = useState(false);
const transactions = useRecoilValue(transactionsSeenByUser(group.id));
const currentUser = useRecoilValue(userData);
const userPermissions = useRecoilValue(currUserPermissions(group.id));
const userAccounts = useRecoilValue(accountsOwnedByUser({ groupID: group.id, userID: currentUser.id }));
const groupAccountMap = useRecoilValue(accountIDsToName(group.id));
const theme: Theme = useTheme();
const isSmallScreen = useMediaQuery(theme.breakpoints.down("md"));
const [filteredTransactions, setFilteredTransactions] = useState([]);
const [searchValue, setSearchValue] = useState("");
const [sortMode, setSortMode] = useState("last_changed"); // last_changed, description, value, billed_at
useEffect(() => {
let filtered = transactions;
if (searchValue != null && searchValue !== "") {
filtered = transactions.filter((t) => t.filter(searchValue, groupAccountMap));
}
filtered = [...filtered].sort(getTransactionSortFunc(sortMode));
setFilteredTransactions(filtered);
}, [searchValue, setFilteredTransactions, sortMode, transactions, userAccounts]);
useTitle(`${group.name} - Transactions`);
const openPurchaseCreateDialog = () => {
setShowPurchaseCreateDialog(true);
};
const openTransferCreateDialog = () => {
setShowTransferCreateDialog(true);
};
return (
<>
<MobilePaper>
<Box
sx={{
display: "flex",
flexDirection: { xs: "column", sm: "column", md: "row", lg: "row" },
alignItems: { md: "flex-end" },
pl: "16px",
justifyContent: "space-between",
}}
>
<Box sx={{ display: "flex-item" }}>
<Box sx={{ minWidth: "56px", pt: "16px" }}>
<SearchIcon sx={{ color: "action.active" }} />
</Box>
<Input
value={searchValue}
onChange={(e) => setSearchValue(e.target.value)}
placeholder="Search…"
inputProps={{
"aria-label": "search",
}}
sx={{ pt: "16px" }}
endAdornment={
<InputAdornment position="end">
<IconButton
aria-label="clear search input"
onClick={(e) => setSearchValue("")}
edge="end"
>
<Clear />
</IconButton>
</InputAdornment>
}
/>
<FormControl variant="standard" sx={{ minWidth: 120, ml: 3 }}>
<InputLabel id="select-sort-by-label">Sort by</InputLabel>
<Select
labelId="select-sort-by-label"
id="select-sort-by"
label="Sort by"
onChange={(evt) => setSortMode(evt.target.value)}
value={sortMode}
>
<MenuItem value="last_changed">Last changed</MenuItem>
<MenuItem value="description">Description</MenuItem>
<MenuItem value="value">Value</MenuItem>
<MenuItem value="billed_at">Date</MenuItem>
</Select>
</FormControl>
</Box>
{!isSmallScreen && (
<Box sx={{ display: "flex-item" }}>
<div style={{ padding: "8px" }}>
<Add color="primary" />
</div>
<Tooltip title="Create Purchase">
<IconButton color="primary" onClick={openPurchaseCreateDialog}>
<PurchaseIcon />
</IconButton>
</Tooltip>
<Tooltip title="Create Transfer">
<IconButton color="primary" onClick={openTransferCreateDialog}>
<TransferIcon />
</IconButton>
</Tooltip>
</Box>
)}
</Box>
<Divider sx={{ mt: 1 }} />
<List>
{transactions.length === 0 ? (
<Alert severity="info">No Transactions</Alert>
) : (
filteredTransactions.map((transaction) => (
<TransactionListEntry key={transaction.id} group={group} transaction={transaction} />
))
)}
</List>
<TransferCreateModal
group={group}
show={showTransferCreateDialog}
onClose={(evt, reason) => {
if (reason !== "backdropClick") {
setShowTransferCreateDialog(false);
}
}}
/>
<PurchaseCreateModal
group={group}
show={showPurchaseCreateDialog}
onClose={(evt, reason) => {
if (reason !== "backdropClick") {
setShowPurchaseCreateDialog(false);
}
}}
/>
</MobilePaper>
{userPermissions.can_write && (
<SpeedDial
ariaLabel="Create Account"
sx={{ position: "fixed", bottom: 20, right: 20 }}
icon={<SpeedDialIcon />}
// onClose={() => setSpeedDialOpen(false)}
// onOpen={() => setSpeedDialOpen(true)}
onClick={toggleSpeedDial}
open={speedDialOpen}
>
<SpeedDialAction
icon={<PurchaseIcon />}
tooltipTitle="Purchase"
tooltipOpen
onClick={openPurchaseCreateDialog}
/>
<SpeedDialAction
icon={<TransferIcon />}
tooltipTitle="Transfer"
tooltipOpen
onClick={openTransferCreateDialog}
/>
</SpeedDial>
)}
</>
);
}
Example #25
Source File: CustomIdField.tsx From firecms with MIT License | 4 votes |
export function CustomIdField<M, UserType>
({ schema, status, onChange, error, entity }: {
schema: EntitySchema<M>,
status: EntityStatus,
onChange: Function,
error: boolean,
entity: Entity<M> | undefined
}) {
const classes = formStyles();
const disabled = status === "existing" || !schema.customId;
const idSetAutomatically = status !== "existing" && !schema.customId;
const hasEnumValues = typeof schema.customId === "object";
const snackbarContext = useSnackbarController();
const { copy } = useClipboard({
onSuccess: (text) => snackbarContext.open({
type: "success",
message: `Copied ${text}`
})
});
const appConfig: FireCMSContext<UserType> | undefined = useFireCMSContext();
const inputProps = {
className: classes.input,
endAdornment: entity
? (
<InputAdornment position="end">
<IconButton onClick={(e) => copy(entity.id)}
aria-label="copy-id"
size="large">
<Tooltip title={"Copy"}>
<svg
className={"MuiSvgIcon-root MuiSvgIcon-fontSizeSmall"}
fill={"currentColor"}
width="20" height="20" viewBox="0 0 24 24">
<path
d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"/>
</svg>
</Tooltip>
</IconButton>
{appConfig?.entityLinkBuilder &&
<a href={appConfig.entityLinkBuilder({ entity })}
rel="noopener noreferrer"
target="_blank">
<IconButton onClick={(e) => e.stopPropagation()}
aria-label="go-to-datasource" size="large">
<Tooltip title={"Open in the console"}>
<OpenInNewIcon fontSize={"small"}/>
</Tooltip>
</IconButton>
</a>}
</InputAdornment>
)
: undefined
};
const fieldProps: any = {
label: idSetAutomatically ? "ID is set automatically" : "ID",
disabled: disabled,
name: "id",
type: null,
value: entity && status === "existing" ? entity.id : undefined,
variant: "filled"
};
return (
<FormControl fullWidth
error={error}
{...fieldProps}
key={"custom-id-field"}>
{hasEnumValues && schema.customId &&
<>
<InputLabel id={"id-label"}>{fieldProps.label}</InputLabel>
<MuiSelect
labelId={"id-label"}
className={classes.select}
error={error}
{...fieldProps}
onChange={(event: any) => onChange(event.target.value)}>
{Object.entries(schema.customId).map(([key, label]) =>
<MenuItem
key={`custom-id-item-${key}`}
value={key}>
{`${key} - ${label}`}
</MenuItem>)}
</MuiSelect>
</>}
{!hasEnumValues &&
<MuiTextField {...fieldProps}
error={error}
InputProps={inputProps}
helperText={schema.customId === "optional" ? "Leave this blank to autogenerate an ID" : "ID of the new document"}
onChange={(event) => {
let value = event.target.value;
if (value) value = value.trim();
return onChange(value.length ? value : undefined);
}}/>}
<ErrorMessage name={"id"}
component="div">
{(_) => "You need to specify an ID"}
</ErrorMessage>
</FormControl>
);
}
Example #26
Source File: search.tsx From Cromwell with MIT License | 4 votes |
SearchPage: TPageWithLayout<SearchPageProps> = (props) => {
const filterInput = useRef<TPostFilter>({});
const listId = 'Blog_list_01';
const publishSort = useRef<"ASC" | "DESC">('DESC');
const forceUpdate = useForceUpdate();
const titleSearchId = "post-filter-search";
const updateList = () => {
const list = getBlockInstance<TCList>(listId)?.getContentInstance();
list?.clearState();
list?.init();
list?.updateData();
}
const handleChangeTags = (event: any, newValue?: (TTag | undefined | string)[]) => {
filterInput.current.tagIds = newValue?.map(tag => (tag as TTag)?.id);
forceUpdate();
updateList();
}
const handleGetPosts = (params: TPagedParams<TPost>) => {
params.orderBy = 'publishDate';
params.order = publishSort.current;
return handleGetFilteredPosts(params, filterInput.current);
}
const handleChangeSort = (event: SelectChangeEvent<unknown>) => {
if (event.target.value === 'Newest') publishSort.current = 'DESC';
if (event.target.value === 'Oldest') publishSort.current = 'ASC';
updateList();
}
const handleTagClick = (tag?: TTag) => {
if (!tag) return;
if (filterInput.current.tagIds?.length === 1 &&
filterInput.current.tagIds[0] === tag.id) return;
handleChangeTags(null, [tag]);
forceUpdate();
}
const handleTitleInput = debounce(400, () => {
filterInput.current.titleSearch = (document.getElementById(titleSearchId) as HTMLInputElement)?.value ?? undefined;
updateList();
});
return (
<CContainer className={commonStyles.content} id="search_01">
<CContainer className={styles.filter} id="search_02">
<div className={styles.filterLeft}>
<TextField
className={styles.filterItem}
placeholder="Search by title"
id={titleSearchId}
variant="standard"
onChange={handleTitleInput}
/>
<Autocomplete
multiple
freeSolo
value={filterInput.current.tagIds?.map(id => props.tags?.find(tag => tag.id === id)) ?? []}
className={styles.filterItem}
options={props.tags ?? []}
getOptionLabel={(option: any) => option?.name ?? ''}
style={{ width: 300 }}
onChange={handleChangeTags}
renderInput={(params) => (
<TextField
{...params}
variant="standard"
placeholder="Tags"
/>
)}
/>
</div>
<FormControl className={styles.filterItem}>
<InputLabel className={styles.sortLabel}>Sort</InputLabel>
<Select
style={{ width: '100px' }}
onChange={handleChangeSort}
variant="standard"
defaultValue='Newest'
>
{['Newest', 'Oldest'].map(sort => (
<MenuItem value={sort} key={sort}>{sort}</MenuItem>
))}
</Select>
</FormControl>
</CContainer>
<CContainer style={{ marginBottom: '20px' }} id="search_03">
<CList<TPost>
id={listId}
ListItem={(props) => (
<div className={styles.postWrapper}>
<PostCard onTagClick={handleTagClick} data={props.data} key={props.data?.id} />
</div>
)}
usePagination
useShowMoreButton
useQueryPagination
disableCaching
pageSize={20}
scrollContainerSelector={`.${layoutStyles.Layout}`}
firstBatch={props.posts}
loader={handleGetPosts}
cssClasses={{
page: styles.postList
}}
elements={{
pagination: Pagination
}}
/>
</CContainer>
</CContainer>
);
}
Example #27
Source File: Language.tsx From GTAV-NativeDB with MIT License | 4 votes |
export function CodeGenOptionComponent<TSettings>(props:CodeGenOptionComponentProps<TSettings>) {
const { type, label, prop, value, onChange } = props
switch (type) {
case 'boolean':
return (
<FormControlLabel
control={
<Checkbox
name={prop}
checked={value}
onChange={onChange}
/>
}
sx={{ userSelect: 'none' }}
label={label}
/>
)
case 'combo':
const options = props.options
return (
<FormControl fullWidth>
<InputLabel id={`${prop}-label`}>{label}</InputLabel>
<Select
id={`${prop}-select`}
labelId={`${prop}-label`}
name={prop}
value={value}
onChange={onChange}
label={label}
>
{options.map(({ label, value }) => (
<MenuItem key={value} value={value}>
{label}
</MenuItem>
))}
</Select>
</FormControl>
)
case 'string':
return (
<TextField
label={label}
name={prop}
onChange={(onChange as unknown as ChangeEventHandler<HTMLInputElement | HTMLTextAreaElement>)}
value={value}
/>
)
}
}
Example #28
Source File: QueryMultiSelector.tsx From console with GNU Affero General Public License v3.0 | 4 votes |
QueryMultiSelector = ({
elements,
name,
label,
tooltip = "",
keyPlaceholder = "",
valuePlaceholder = "",
onChange,
withBorder = false,
classes,
}: IQueryMultiSelector) => {
const [currentKeys, setCurrentKeys] = useState<string[]>([""]);
const [currentValues, setCurrentValues] = useState<string[]>([""]);
const bottomList = createRef<HTMLDivElement>();
// Use effect to get the initial values from props
useEffect(() => {
if (
currentKeys.length === 1 &&
currentKeys[0] === "" &&
currentValues.length === 1 &&
currentValues[0] === "" &&
elements &&
elements !== ""
) {
const elementsSplit = elements.split("&");
let keys = [];
let values = [];
elementsSplit.forEach((element: string) => {
const splittedVals = element.split("=");
if (splittedVals.length === 2) {
keys.push(splittedVals[0]);
values.push(splittedVals[1]);
}
});
keys.push("");
values.push("");
setCurrentKeys(keys);
setCurrentValues(values);
}
}, [currentKeys, currentValues, elements]);
// Use effect to send new values to onChange
useEffect(() => {
const refScroll = bottomList.current;
if (refScroll && currentKeys.length > 1) {
refScroll.scrollIntoView(false);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [currentKeys]);
// We avoid multiple re-renders / hang issue typing too fast
const firstUpdate = useRef(true);
useLayoutEffect(() => {
if (firstUpdate.current) {
firstUpdate.current = false;
return;
}
debouncedOnChange();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [currentKeys, currentValues]);
// If the last input is not empty, we add a new one
const addEmptyLine = () => {
if (
currentKeys[currentKeys.length - 1].trim() !== "" &&
currentValues[currentValues.length - 1].trim() !== ""
) {
const keysList = [...currentKeys];
const valuesList = [...currentValues];
keysList.push("");
valuesList.push("");
setCurrentKeys(keysList);
setCurrentValues(valuesList);
}
};
// Onchange function for input box, we get the dataset-index & only update that value in the array
const onChangeKey = (e: ChangeEvent<HTMLInputElement>) => {
e.persist();
let updatedElement = [...currentKeys];
const index = get(e.target, "dataset.index", 0);
updatedElement[index] = e.target.value;
setCurrentKeys(updatedElement);
};
const onChangeValue = (e: ChangeEvent<HTMLInputElement>) => {
e.persist();
let updatedElement = [...currentValues];
const index = get(e.target, "dataset.index", 0);
updatedElement[index] = e.target.value;
setCurrentValues(updatedElement);
};
// Debounce for On Change
const debouncedOnChange = debounce(() => {
let queryString = "";
currentKeys.forEach((keyVal, index) => {
if (currentKeys[index] && currentValues[index]) {
let insertString = `${keyVal}=${currentValues[index]}`;
if (index !== 0) {
insertString = `&${insertString}`;
}
queryString = `${queryString}${insertString}`;
}
});
onChange(queryString);
}, 500);
const inputs = currentValues.map((element, index) => {
return (
<Grid
item
xs={12}
className={classes.lineInputBoxes}
key={`query-pair-${name}-${index.toString()}`}
>
<InputBoxWrapper
id={`${name}-key-${index.toString()}`}
label={""}
name={`${name}-${index.toString()}`}
value={currentKeys[index]}
onChange={onChangeKey}
index={index}
placeholder={keyPlaceholder}
/>
<span className={classes.queryDiv}>:</span>
<InputBoxWrapper
id={`${name}-value-${index.toString()}`}
label={""}
name={`${name}-${index.toString()}`}
value={currentValues[index]}
onChange={onChangeValue}
index={index}
placeholder={valuePlaceholder}
overlayIcon={index === currentValues.length - 1 ? <AddIcon /> : null}
overlayAction={() => {
addEmptyLine();
}}
/>
</Grid>
);
});
return (
<React.Fragment>
<Grid item xs={12} className={classes.fieldContainer}>
<InputLabel className={classes.inputLabel}>
<span>{label}</span>
{tooltip !== "" && (
<div className={classes.tooltipContainer}>
<Tooltip title={tooltip} placement="top-start">
<HelpIcon className={classes.tooltip} />
</Tooltip>
</div>
)}
</InputLabel>
<Grid
item
xs={12}
className={`${withBorder ? classes.inputWithBorder : ""}`}
>
{inputs}
<div ref={bottomList} />
</Grid>
</Grid>
</React.Fragment>
);
}
Example #29
Source File: EpisodeListing.tsx From multi-downloader-nx with MIT License | 4 votes |
EpisodeListing: React.FC = () => {
const [store, dispatch] = useStore();
const [season, setSeason] = React.useState<'all'|string>('all');
const seasons = React.useMemo(() => {
const s: string[] = [];
for (const {season} of store.episodeListing) {
if (s.includes(season))
continue;
s.push(season);
}
return s;
}, [ store.episodeListing ])
const [selected, setSelected] = React.useState<string[]>([]);
React.useEffect(() => {
setSelected(parseSelect(store.downloadOptions.e));
}, [ store.episodeListing ])
const close = () => {
dispatch({
type: 'episodeListing',
payload: []
});
dispatch({
type: 'downloadOptions',
payload: {
...store.downloadOptions,
e: `${([...new Set([...parseSelect(store.downloadOptions.e), ...selected])]).join(',')}`
}
})
}
return <Dialog open={store.episodeListing.length > 0} onClose={close} scroll='paper' maxWidth='xl' sx={{ p: 2 }}>
<Box sx={{ display: 'grid', gridTemplateColumns: '1fr 200px 20px' }}>
<Typography color='text.primary' variant="h5" sx={{ textAlign: 'center', alignItems: 'center', justifyContent: 'center', display: 'flex' }}>
Episodes
</Typography>
<FormControl sx={{ mr: 2, mt: 2 }}>
<InputLabel id='seasonSelectLabel'>Season</InputLabel>
<Select labelId="seasonSelectLabel" label='Season' value={season} onChange={(e) => setSeason(e.target.value)}>
<MenuItem value='all'>Show all Epsiodes</MenuItem>
{seasons.map((a, index) => {
return <MenuItem value={a} key={`MenuItem_SeasonSelect_${index}`}>
{a}
</MenuItem>
})}
</Select>
</FormControl>
</Box>
<List>
<ListItem sx={{ display: 'grid', gridTemplateColumns: '25px 1fr 5fr' }}>
<Checkbox
indeterminate={store.episodeListing.some(a => selected.includes(a.e)) && !store.episodeListing.every(a => selected.includes(a.e))}
checked={store.episodeListing.every(a => selected.includes(a.e))}
onChange={() => {
if (selected.length > 0) {
setSelected([]);
} else {
setSelected(store.episodeListing.map(a => a.e));
}
}}
/>
</ListItem>
{store.episodeListing.filter((a) => season === 'all' ? true : a.season === season).map((item, index, { length }) => {
const e = isNaN(parseInt(item.e)) ? item.e : parseInt(item.e);
const isSelected = selected.includes(e.toString());
return <Box {...{ mouseData: isSelected }} key={`Episode_List_Item_${index}`} sx={{
backdropFilter: isSelected ? 'brightness(1.5)' : '',
'&:hover': {
backdropFilter: 'brightness(1.5)'
}
}}
onClick={() => {
let arr: string[] = [];
if (isSelected) {
arr = [...selected.filter(a => a !== e.toString())];
} else {
arr = [...selected, e.toString()];
}
setSelected(arr.filter(a => a.length > 0));
}}>
<ListItem sx={{ display: 'grid', gridTemplateColumns: '25px 50px 1fr 5fr' }}>
{ isSelected ? <CheckBox /> : <CheckBoxOutlineBlank /> }
<Typography color='text.primary' sx={{ textAlign: 'center' }}>
{e}
</Typography>
<img style={{ width: 'inherit', maxHeight: '200px', minWidth: '150px' }} src={item.img}></img>
<Box sx={{ display: 'flex', flexDirection: 'column', pl: 1 }}>
<Box sx={{ display: 'grid', gridTemplateColumns: '1fr min-content' }}>
<Typography color='text.primary' variant="h5">
{item.name}
</Typography>
<Typography color='text.primary'>
{item.time.startsWith('00:') ? item.time.slice(3) : item.time}
</Typography>
</Box>
<Typography color='text.primary'>
{item.description}
</Typography>
</Box>
</ListItem>
{index < length - 1 && <Divider />}
</Box>
})}
</List>
</Dialog>
}