@chakra-ui/react#FormControl JavaScript Examples
The following examples show how to use
@chakra-ui/react#FormControl.
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: components.js From idena-web with MIT License | 6 votes |
function CustomFormControl({label, labelFontSize = 'md', children, ...props}) {
return (
<FormControl {...props}>
<FormLabel fontSize={labelFontSize} color="brandGray.500" mb={2}>
{label}
</FormLabel>
{children}
</FormControl>
)
}
Example #2
Source File: Form.js From web-client with Apache License 2.0 | 6 votes |
VulnerabilityCategoryForm = ({ category, onFormSubmit, categorySetter: setCategory }) => {
const [categories] = useFetch('/vulnerabilities/categories?parentsOnly=true');
const onFormInputChange = ev => {
const target = ev.target;
const name = target.name;
const value = target.value === "" ? null : target.value;
setCategory({ ...category, [name]: value });
};
return <form id="vulnerability_category_form" onSubmit={onFormSubmit}>
<FormControl id="parent_id" isRequired>
<FormLabel>Parent category</FormLabel>
{categories && <Select name="parent_id" value={category.parent_id} onChange={onFormInputChange}>
<option>(none)</option>
{categories.filter(category => category.parent_id === null).map(category => <option key={category.id} value={category.id}>{category.name}</option>)}
</Select>}
</FormControl>
<FormControl id="name" isRequired>
<FormLabel>Name</FormLabel>
<Input name="name" autoFocus value={category.name} onChange={onFormInputChange} />
</FormControl>
<FormControl id="description">
<FormLabel>Description</FormLabel>
<Input name="description" value={category.description} onChange={onFormInputChange} />
</FormControl>
</form>
}
Example #3
Source File: Form.js From web-client with Apache License 2.0 | 6 votes |
TargetForm = ({ newTarget, onFormSubmit, targetSetter: setTarget }) => {
const onFormChange = ev => {
const target = ev.target;
const name = target.name;
let value = target.value;
if ('tags' === name) {
value = JSON.stringify(value.split(','));
}
setTarget({ ...newTarget, [name]: value });
};
return <div>
<form onSubmit={onFormSubmit}>
<FormControl id="name" isRequired>
<FormLabel>Name</FormLabel>
<Input name="name" placeholder="e.g. 127.0.0.1" onChange={onFormChange} isRequired autoFocus />
</FormControl>
<FormControl id="tags">
<FormLabel>Tags</FormLabel>
<Input name="tags" placeholder="e.g. linux,production" onChange={onFormChange} />
</FormControl>
<FormControl id="kind" isRequired>
<FormLabel>Kind</FormLabel>
<Select name="kind" onChange={onFormChange}>
{TargetKinds.map((targetKind, index) =>
<option key={index} value={targetKind.value}>{targetKind.description}</option>
)}
</Select>
</FormControl>
</form>
</div>
}
Example #4
Source File: Form.js From web-client with Apache License 2.0 | 6 votes |
NotesForm = ({ note, onFormSubmit, noteSetter: setNote }) => {
const onFormInputChange = ev => {
const target = ev.target;
const name = target.name;
const value = target.value;
setNote({ ...note, [name]: value });
};
return <form onSubmit={onFormSubmit}>
<FormControl id="content" isRequired>
<FormLabel>Content</FormLabel>
<Textarea name="content" style={{ width: '100%' }} value={note.content}
onChange={onFormInputChange} autoFocus /><br />
</FormControl>
<FormControl id="visibility" isRequired>
<FormLabel>Visibility</FormLabel>
<Select name="visibility" value={note.visibility} onChange={onFormInputChange}>
<option value="private">Private</option>
<option value="public">Public</option>
</Select>
</FormControl>
</form>
}
Example #5
Source File: Form.js From web-client with Apache License 2.0 | 6 votes |
DocumentForm = ({ document, onFormSubmit, documentSetter: setNote, isEditForm = false }) => {
const onFormInputChange = ev => {
const target = ev.target;
const name = target.name;
const value = target.value;
setNote({
...document, [name]: value
});
};
return <form onSubmit={onFormSubmit}>
<FormControl isRequired>
<FormLabel htmlFor="title">Title</FormLabel>
<Input type="text" name="title" id="title" value={document.title || ""} onChange={onFormInputChange} autoFocus />
</FormControl>
<FormControl isRequired>
<FormLabel htmlFor="content">Content (markdown supported)</FormLabel>
<MarkdownEditor name="content" style={{ width: '100%' }} required value={document.content || ""}
onChange={onFormInputChange} /><br />
</FormControl>
<FormControl>
<FormLabel htmlFor="visibility">Visibility</FormLabel>
<Select name="visibility" id="visibility" value={document.visibility} onChange={onFormInputChange} required>
<option value="private">Private</option>
<option value="public">Public</option>
</Select>
</FormControl>
<PrimaryButton type="submit">{isEditForm ? "Update" : "Create"}</PrimaryButton>
</form>
}
Example #6
Source File: podcasts.js From grandcast.fm with Apache License 2.0 | 6 votes |
Podcasts = () => {
const [getPodcasts, { data }] = useLazyQuery(PodcastSearchQuery)
const { isSignedIn } = useAuth()
const [searchString, setSearchString] = useState('')
return (
<Container>
{!isSignedIn() && <SignIn />}
{isSignedIn() && (
<div>
<FormControl id="podcastsearch">
<FormLabel>Search podcasts</FormLabel>
<Flex>
<Input onChange={(e) => setSearchString(e.target.value)} />
<Button
ml={4}
onClick={() =>
getPodcasts({ variables: { searchTerm: searchString } })
}
>
Search
</Button>
</Flex>
</FormControl>
<VStack>
{data?.podcastSearch.map((p) => {
return <Podcast podcast={p} />
})}
</VStack>
</div>
)}
</Container>
)
}
Example #7
Source File: SignIn.js From grandcast.fm with Apache License 2.0 | 6 votes |
SignIn = () => {
const [username, setUsername] = useState('')
const [password, setPassword] = useState('')
const { signIn } = useAuth()
function onSubmit(e) {
e.preventDefault()
signIn({ username, password })
}
return (
<div>
<FormControl b="1px" id="signin">
<FormLabel m={4}>Sign In</FormLabel>
<Input
m={4}
type="text"
placeholder="username"
onChange={(e) => setUsername(e.target.value)}
></Input>
<Input
m={4}
type="password"
placeholder="password"
onChange={(e) => setPassword(e.target.value)}
></Input>
<Button m={4} w="100%" onClick={onSubmit} type="submit">
Log In
</Button>
</FormControl>
</div>
)
}
Example #8
Source File: components.js From idena-web with MIT License | 6 votes |
export function FormControlWithLabel({
label,
labelFontSize = 'md',
children,
...props
}) {
return (
<FormControl {...props}>
<FormLabel fontSize={labelFontSize} color="brandGray.500" mb={2}>
{label}
</FormLabel>
{children}
</FormControl>
)
}
Example #9
Source File: components.js From idena-web with MIT License | 6 votes |
export function VotingInlineFormControl({
htmlFor,
label,
tooltip,
children,
...props
}) {
return (
<FormControl display="inline-flex" {...props}>
{tooltip ? (
<FormLabel htmlFor={htmlFor} color="muted" py={2} minW={32} w={32}>
<Tooltip label={tooltip} placement="top" zIndex="tooltip">
<Text
as="span"
borderBottomStyle="dotted"
borderBottomWidth="1px"
borderBottomColor="muted"
cursor="help"
>
{label}
</Text>
</Tooltip>
</FormLabel>
) : (
<FormLabel htmlFor={htmlFor} color="muted" py={2} minW={32} w={32}>
{label}
</FormLabel>
)}
<Box w="md">{children}</Box>
</FormControl>
)
}
Example #10
Source File: components.js From idena-web with MIT License | 6 votes |
export function OracleFormControl({label, children, ...props}) {
return (
<FormControl {...props}>
<FormLabel color="brandGray.500" mb={2}>
{label}
</FormLabel>
{children}
</FormControl>
)
}
Example #11
Source File: components.js From idena-web with MIT License | 6 votes |
export function AdFormField({label, children, maybeError, ...props}) {
return (
<FormControl isInvalid={Boolean(maybeError)} {...props}>
<Flex>
<FormLabel color="muted" w="32" pt={2}>
{label}
</FormLabel>
<Box w="sm">
{children}
<AdFormError>{maybeError}</AdFormError>
</Box>
</Flex>
</FormControl>
)
}
Example #12
Source File: Send.js From web-client with Apache License 2.0 | 5 votes |
SendReport = () => {
const navigate = useNavigate();
const { projectId } = useParams();
const [project] = useFetch(`/projects/${projectId}`)
const [revisions] = useFetch(`/reports?projectId=${projectId}`)
const [deliverySettings, setDeliverySettings] = useState({
report_id: null,
recipients: null,
subject: "[CONFIDENTIAL] Security report attached",
body: "Please review attachment containing a security report."
})
const handleSend = async (ev) => {
ev.preventDefault();
secureApiFetch(`/reports/${deliverySettings.report_id}/send`, { method: 'POST', body: JSON.stringify(deliverySettings) })
.then(() => {
navigate(`/projects/${project.id}/report`);
})
.catch(err => {
console.error(err);
})
}
const handleFormChange = ev => {
const target = ev.target;
const name = target.name;
const value = target.value;
setDeliverySettings({ ...deliverySettings, [name]: value });
};
useEffect(() => {
if (revisions && deliverySettings.report_id === null)
setDeliverySettings({ ...deliverySettings, report_id: revisions[0].id })
}, [revisions, deliverySettings]);
if (!project) return <Loading />
return <div>
<PageTitle value="Send report" />
<div className='heading'>
<Breadcrumb>
<Link to="/projects">Projects</Link>
{project && <Link to={`/projects/${project.id}`}>{project.name}</Link>}
{project && <Link to={`/projects/${project.id}/report`}>Report</Link>}
</Breadcrumb>
</div>
<form onSubmit={handleSend}>
<Title title='Send report' />
<FormControl isRequired>
<FormLabel for="reportId">Revision</FormLabel>
<Select id="reportId" name="report_id" onChange={handleFormChange}>
{revisions && revisions.map(revision => <option value={revision.id}>{revision.version_name}</option>)}
</Select>
</FormControl>
<FormControl isRequired>
<FormLabel>Recipients</FormLabel>
<Input type="text" name="recipients" onChange={handleFormChange} autoFocus
placeholder="[email protected]" />
<FormHelperText>Comma separated list of email addresses.</FormHelperText>
</FormControl>
<FormControl isRequired>
<FormLabel>Subject</FormLabel>
<Input type="text" name="subject" onChange={handleFormChange}
value={deliverySettings.subject} />
</FormControl>
<FormControl isRequired>
<FormLabel>Body</FormLabel>
<Textarea name="body" onChange={handleFormChange} value={deliverySettings.body} />
</FormControl>
<PrimaryButton type="submit">Send</PrimaryButton>
</form>
</div>
}
Example #13
Source File: containers.js From idena-web with MIT License | 5 votes |
export function AdMediaInput({
name,
value,
label,
description,
fallbackSrc,
maybeError,
onChange,
...props
}) {
const src = React.useMemo(
() =>
isValidImage(value) ? URL.createObjectURL(value) : value ?? adFallbackSrc,
[value]
)
return (
<FormControl isInvalid={Boolean(maybeError)}>
<FormLabel htmlFor={name} m={0} p={0}>
<VisuallyHiddenInput
id={name}
name={name}
type="file"
accept="image/png,image/jpg,image/jpeg"
onChange={async e => {
if (onChange) {
const {files} = e.target
if (files.length) {
const [file] = files
if (hasImageType(file)) {
onChange(file)
}
}
}
}}
{...props}
/>
<HStack spacing={4} align="center" cursor="pointer">
<Box flexShrink={0}>
{src !== adFallbackSrc ? (
<AdImage src={src} width={70} />
) : (
<Center
bg="gray.50"
borderWidth={1}
borderColor="gray.016"
rounded="lg"
p="3"
>
<Image src={fallbackSrc} ignoreFallback boxSize="44px" />
</Center>
)}
</Box>
<Stack>
<HStack>
<LaptopIcon boxSize="5" color="blue.500" />
<Text color="blue.500" fontWeight={500}>
{label}
</Text>
</HStack>
<SmallText>{description}</SmallText>
</Stack>
</HStack>
<AdFormError>{maybeError}</AdFormError>
</FormLabel>
</FormControl>
)
}
Example #14
Source File: containers.js From idena-web with MIT License | 5 votes |
export function EditContactDrawer({contact, onRename, ...props}) {
const {t} = useTranslation()
const {updateInvite} = useInviteDispatch()
const [isSubmitting, setIsSubmitting] = React.useState()
const {id, firstName, lastName, receiver} = contact
const contactName = `${firstName} ${lastName}`.trim() || receiver
return (
<Drawer {...props}>
<DrawerHeader>
<ContactDrawerHeader address={receiver} name={contactName} />
</DrawerHeader>
<Flex
as="form"
direction="column"
flex={1}
onSubmit={async e => {
e.preventDefault()
const {
firstName: {value: firstNameValue},
lastName: {value: lastNameValue},
} = e.target.elements
setIsSubmitting(true)
await updateInvite(id, firstNameValue, lastNameValue)
setIsSubmitting(false)
onRename({firstName: firstNameValue, lastName: lastNameValue})
}}
>
<DrawerBody>
<Stack isInline spacing={4} mt={5}>
<FormControl>
<FormLabel>{t('First name')}</FormLabel>
<Input id="firstName" defaultValue={firstName} />
</FormControl>
<FormControl>
<FormLabel>{t('Last name')}</FormLabel>
<Input id="lastName" defaultValue={lastName} />
</FormControl>
</Stack>
</DrawerBody>
<DrawerFooter>
<PrimaryButton type="submit" ml="auto" isLoading={isSubmitting}>
{t('Save')}
</PrimaryButton>
</DrawerFooter>
</Flex>
</Drawer>
)
}
Example #15
Source File: components.js From idena-web with MIT License | 5 votes |
export function ReceiveDrawer({isOpen, onClose, address}) {
const {t} = useTranslation()
const {onCopy, hasCopied} = useClipboard(address)
const size = useBreakpointValue(['lg', 'md'])
const qrSize = useBreakpointValue(['170px', '128px'])
const variant = useBreakpointValue(['outlineMobile', 'outline'])
return (
<Drawer isOpen={isOpen} onClose={onClose}>
<DrawerHeader mb={[12, 8]}>
<Flex direction="column" textAlign={['center', 'start']}>
<Flex
order={[2, 1]}
align="center"
justify="center"
mt={[8, 0]}
h={12}
w={12}
rounded="xl"
bg="blue.012"
>
<ReceiveIcon boxSize={6} color="blue.500" />
</Flex>
<Heading
order={[1, 2]}
color="brandGray.500"
fontSize={['base', 'lg']}
fontWeight={[['bold', 500]]}
lineHeight="base"
mt={[0, 4]}
>
{t(`Receive iDNA`)}
</Heading>
</Flex>
</DrawerHeader>
<DrawerBody>
<Stack spacing={[12, 5]}>
<QRCode
value={address}
style={{height: qrSize, width: qrSize, margin: '0 auto'}}
/>
<FormControl>
<Flex justify="space-between">
<FormLabel fontSize={['base', 'md']}>{t('Address')}</FormLabel>
{hasCopied ? (
<FormLabel fontSize={['base', 'md']}>{t('Copied!')}</FormLabel>
) : (
<FlatButton onClick={onCopy} mb={2.5}>
{t('Copy')}
</FlatButton>
)}
</Flex>
<Input value={address} size={size} variant={variant} isDisabled />
</FormControl>
</Stack>
</DrawerBody>
</Drawer>
)
}
Example #16
Source File: ModalDialog.js From web-client with Apache License 2.0 | 5 votes |
ReportModalDialog = ({ isOpen, onSubmit, onCancel }) => {
const fileRef = useRef();
const emptyReportTemplate = {
version_name: "",
version_description: null,
resultFile: null,
}
const [reportTemplate, setReportTemplate] = useState(emptyReportTemplate)
const onCreateReportFormSubmit = ev => {
ev.preventDefault();
const formData = new FormData();
formData.append('version_name', reportTemplate.version_name);
formData.append('version_description', reportTemplate.version_description);
formData.append('resultFile', fileRef.current.files[0]);
secureApiFetch(`/reports/templates`, { method: 'POST', body: formData })
.then(() => {
onSubmit();
actionCompletedToast(`The report template "${reportTemplate.version_name}" has been added.`);
})
.catch(err => {
errorToast(err);
})
.finally(() => {
setReportTemplate(emptyReportTemplate)
})
}
const onFormChange = ev => {
setReportTemplate({ ...reportTemplate, [ev.target.name]: ev.target.value })
}
return <Modal size="xl" isOpen={isOpen} onClose={onCancel}>
<ModalOverlay />
<ModalContent>
<ModalHeader><h4>New report template details</h4></ModalHeader>
<ModalCloseButton />
<ModalBody>
<form id="reportTemplateForm" onSubmit={onCreateReportFormSubmit}>
<FormControl isRequired>
<FormLabel>Version name</FormLabel>
<Input type="text" name="version_name" onChange={onFormChange} autoFocus />
</FormControl>
<FormControl>
<FormLabel>Version description</FormLabel>
<Input type="text" name="version_description" onChange={onFormChange} />
</FormControl>
<FormControl isRequired>
<FormLabel>File</FormLabel>
<Input type="file" ref={fileRef} name="resultFile" onChange={onFormChange} />
</FormControl>
</form>
</ModalBody>
<ModalFooter>
<Button onClick={onCancel} mr={3}>Cancel</Button>
<Button form="reportTemplateForm" type="submit" colorScheme="blue">Save</Button>
</ModalFooter>
</ModalContent>
</Modal>
}
Example #17
Source File: components.js From idena-web with MIT License | 5 votes |
export function SpoilInviteDrawer({onSuccess, onFail, ...props}) {
const {t} = useTranslation()
return (
<Drawer {...props}>
<DrawerHeader mb={0}>
<Center flexDirection="column">
<Avatar address={dummyAddress} />
<Heading
fontSize="lg"
fontWeight={500}
color="gray.500"
mt="4"
mb={0}
>
{t('Spoil invitation code')}
</Heading>
</Center>
</DrawerHeader>
<DrawerBody mt="6">
<Text fontSize="md" mb={6}>
{t(
`Spoil invitations that are shared publicly. This will encourage people to share invitations privately and prevent bots from collecting invitation codes.`
)}
</Text>
<Stack spacing="6">
<form
id="spoilInvite"
onSubmit={async e => {
e.preventDefault()
const code = new FormData(e.target).get('code').trim()
const randomPrivateKey = generatePrivateKey()
try {
const hash = await sendRawTx(
new Transaction()
.fromHex(
await getRawTx(
TxType.ActivationTx,
privateKeyToAddress(code),
privateKeyToAddress(randomPrivateKey),
0,
0,
privateKeyToPublicKey(randomPrivateKey)
)
)
.sign(code)
.toHex(true)
)
// eslint-disable-next-line no-unused-expressions
onSuccess?.(hash)
} catch (error) {
// eslint-disable-next-line no-unused-expressions
onFail?.(error)
}
}}
>
<FormControl>
<FormLabel>{t('Invitation code')}</FormLabel>
<Input name="code" placeholder={t('Invitation code to spoil')} />
</FormControl>
</form>
<Text fontSize="md">
{t(
`When you click 'Spoil' the invitation code will be activated by a random address and wasted.`
)}
</Text>
</Stack>
</DrawerBody>
<DrawerFooter>
<PrimaryButton type="submit" form="spoilInvite">
{t('Spoil invite')}
</PrimaryButton>
</DrawerFooter>
</Drawer>
)
}
Example #18
Source File: components.js From idena-web with MIT License | 5 votes |
export function ActivateInvitationDialog({onClose, ...props}) {
const {t} = useTranslation()
const [code, setCode] = useState('')
const [{isMining, isSuccess}, {activateInvite}] = useInviteActivation()
const size = useBreakpointValue(['lg', 'md'])
useEffect(() => {
if (!isMining && isSuccess) onClose()
}, [isMining, isSuccess, onClose])
return (
<Dialog title={t('Invite activation')} onClose={onClose} {...props}>
<DialogBody mb={0}>
<Box
mt={4}
as="form"
onSubmit={async e => {
e.preventDefault()
await activateInvite(code)
}}
>
<FormControl>
<Stack spacing={[2, 3]}>
<Flex justify="space-between" align="center">
<FormLabel htmlFor="code" p={0} m={0} fontSize={['base', 'md']}>
{t('Enter invitation code')}
</FormLabel>
<PasteButton
isDisabled={isMining}
onClick={() =>
navigator.clipboard.readText().then(text => setCode(text))
}
/>
</Flex>
<Input
size={size}
value={code}
isDisabled={isMining}
onChange={e => setCode(e.target.value)}
/>
</Stack>
</FormControl>
<Flex mt={4} align="center" justifyContent="flex-end">
<SecondaryButton
display={['none', 'initial']}
onClick={onClose}
mr={2}
>
{t('Cancel')}
</SecondaryButton>
<PrimaryButton
size={size}
w={['100%', 'auto']}
type="submit"
isLoading={isMining}
loadingText={t('Mining...')}
>
{t('Activate invitation')}
</PrimaryButton>
</Flex>
</Box>
</DialogBody>
</Dialog>
)
}
Example #19
Source File: Preferences.js From web-client with Apache License 2.0 | 5 votes |
UserPreferences = () => {
const user = Auth.getLoggedInUser();
user.preferences = initialiseUserPreferences(user);
const timezones = CountriesTimezones.getAllTimezones();
const timezoneKeys = Object.keys(timezones).sort();
const { setTheme } = useContext(ThemeContext);
const { setColorMode } = useColorMode();
const [formValues, setFormValues] = useState({
timezone: user.timezone,
theme: user.preferences["web-client.theme"]
});
const updateFormValues = ev => {
setFormValues({ ...formValues, [ev.target.name]: ev.target.value });
}
const onFormSubmit = ev => {
ev.preventDefault();
user.timezone = formValues.timezone;
user.preferences = { ...initialiseUserPreferences(user), "web-client.theme": formValues.theme };
secureApiFetch(`/users/${user.id}`, {
method: 'PATCH',
body: JSON.stringify({ timezone: formValues.timezone, preferences: user.preferences })
})
.then(() => {
setTheme(theme => {
setThemeColors(formValues.theme);
setColorMode(formValues.theme);
return formValues.theme;
});
localStorage.setItem('user', JSON.stringify(user));
actionCompletedToast("Your preferences have been saved.");
})
.catch(err => console.error(err));
}
return <>
<PageTitle value="Preferences" />
<div className='heading'>
<Breadcrumb />
</div>
<Title type='User' title='Preferences' icon={<IconPreferences />} />
<form onSubmit={onFormSubmit}>
<FormControl>
<FormLabel>Theme</FormLabel>
<Select name="theme" onChange={updateFormValues} defaultValue={formValues.theme || "dark"}>
<option value="dark">Dark</option>
<option value="light">Light</option>
</Select>
</FormControl>
<FormControl>
<FormLabel>Timezone</FormLabel>
<Select name="timezone" onChange={updateFormValues} defaultValue={user.timezone}>
{timezoneKeys.map((key, index) =>
<option key={index} value={timezones[key].name}>{timezones[key].name}</option>
)}
</Select>
</FormControl>
<Primary type="submit">Save</Primary>
</form>
</>
}
Example #20
Source File: components.js From idena-web with MIT License | 5 votes |
export function DeleteFlipDrawer({hash, cover, onDelete, ...props}) {
const {t} = useTranslation()
return (
<Drawer {...props}>
<DrawerHeader>
<Flex
align="center"
justify="center"
bg="red.012"
h={12}
w={12}
rounded="xl"
>
<DeleteIcon boxSize={6} color="red.500" />
</Flex>
<Heading fontSize="lg" fontWeight={500} color="brandGray.500" mt={4}>
{t('Delete flip')}
</Heading>
</DrawerHeader>
<DrawerBody>
<Text color="brandGray.500" fontSize="md">
{t('Deleted flip will be moved to the drafts.')}
</Text>
<FlipImage
src={cover}
size={160}
objectFit="cover"
mx="auto"
mt={8}
mb={38}
rounded="lg"
/>
<FormControl mb={6}>
<FormLabel htmlFor="hashInput" mb={2}>
{t('Flip hash')}
</FormLabel>
<Input
id="hashInput"
h={8}
borderColor="gray.100"
lineHeight={rem(18)}
px={3}
pt={1.5}
pb={2}
mb={2}
value={hash}
isReadOnly
_readOnly={{
bg: 'gray.50',
borderColor: 'gray.100',
color: 'muted',
}}
/>
</FormControl>
<PrimaryButton
colorScheme="red"
display="flex"
ml="auto"
_hover={{
bg: 'rgb(227 60 60)',
}}
onClick={onDelete}
>
{t('Delete')}
</PrimaryButton>
</DrawerBody>
</Drawer>
)
}
Example #21
Source File: ProductAddEdit.js From react-sample-projects with MIT License | 4 votes |
ProductAddEdit = () => {
const categories = useSelector(state => state.product.categories);
const dispatch = useDispatch();
const navigate = useNavigate();
const initialValues = {
title: '',
price: '',
category: '',
description: '',
image: '',
};
const validationSchema = yup.object({
title: yup.string().required(),
price: yup.number().required(),
category: yup.string().required(),
description: yup.string().required(),
image: yup.string().url().required(),
});
const onFormSubmit = (values, actions) => {
actions.setSubmitting(false);
dispatch(addNewProduct(values));
navigate('/');
};
useEffect(() => {
dispatch(fetchCategories());
return () => {};
}, [dispatch]);
return (
<Box boxShadow="base" m={'auto'} width="clamp(300px, 60%, 100%)">
<Formik
initialValues={initialValues}
onSubmit={onFormSubmit}
validationSchema={validationSchema}
>
{props => (
<Form noValidate>
<VStack p={3} m="3">
<Box fontWeight="semibold" mt="1" as="h2" textAlign="left">
Add Product
</Box>
<Field name="title">
{({ field, form }) => (
<FormControl
isRequired
isInvalid={form.errors.title && form.touched.title}
>
<FormLabel htmlFor="title">Enter Title</FormLabel>
<Input
{...field}
type="text"
id="title"
placeholder="Enter Title"
/>
<ErrorMessage
name="title"
component={FormErrorMessage}
></ErrorMessage>
</FormControl>
)}
</Field>
<Field name="price">
{({ field, form }) => (
<FormControl
isRequired
isInvalid={form.errors.price && form.touched.price}
>
<FormLabel>Enter price</FormLabel>
<Input type="number" placeholder="Enter price" {...field} />
<ErrorMessage
name="price"
component={FormErrorMessage}
></ErrorMessage>
</FormControl>
)}
</Field>
<Field name="category">
{({ field, form }) => (
<FormControl
name="category"
isRequired
isInvalid={form.errors.category && form.touched.category}
>
<FormLabel>Enter category</FormLabel>
<Select placeholder="Select category" {...field}>
{categories.map((category, index) => (
<option key={index}>{category}</option>
))}
</Select>
<ErrorMessage
name="category"
component={FormErrorMessage}
></ErrorMessage>
</FormControl>
)}
</Field>
<Field name="description">
{({ field, form }) => (
<FormControl
name="description"
isRequired
isInvalid={
form.errors.description && form.touched.description
}
>
<FormLabel>Enter description</FormLabel>
<Textarea
{...field}
id="description"
placeholder="Enter description"
></Textarea>
<ErrorMessage
name="description"
component={FormErrorMessage}
></ErrorMessage>
</FormControl>
)}
</Field>
<Field name="image">
{({ field, form }) => (
<FormControl
name="image"
isRequired
isInvalid={form.errors.image && form.touched.image}
>
<FormLabel>Enter image</FormLabel>
<Input
type="url"
placeholder="Enter image url"
{...field}
/>
<ErrorMessage
name="image"
component={FormErrorMessage}
></ErrorMessage>
</FormControl>
)}
</Field>
<Button
mt={4}
colorScheme="teal"
type="submit"
isLoading={props.isSubmitting}
>
Add Product
</Button>
</VStack>
</Form>
)}
</Formik>
</Box>
);
}
Example #22
Source File: containers.js From idena-web with MIT License | 4 votes |
export function BurnDrawer({ad, onBurn, ...props}) {
const {t} = useTranslation()
const [{address}] = useIdentity()
const balance = useBalance(address)
const failToast = useFailToast()
const [isPending, {on: setIsPendingOn, off: setIsPendingOff}] = useBoolean()
const {submit} = useBurnAd({
onMined: React.useCallback(() => {
onBurn()
setIsPendingOff()
}, [onBurn, setIsPendingOff]),
onError: React.useCallback(
error => {
failToast(error)
setIsPendingOff()
},
[failToast, setIsPendingOff]
),
})
const formatDna = useFormatDna()
const competingAds = useCompetingAds(ad.cid, new AdTarget(ad))
const competitorCount = competingAds?.length
const maxCompetitor = competingAds?.sort((a, b) => b.amount - a.amount)[0]
return (
<AdDrawer isMining={isPending} {...props}>
<DrawerHeader>
<Stack spacing={4}>
<FillCenter
alignSelf="flex-start"
bg="blue.012"
w={12}
minH={12}
rounded="xl"
>
<AdsIcon boxSize={6} color="blue.500" />
</FillCenter>
<Heading fontSize="lg" fontWeight={500}>
{t('Burn')}
</Heading>
</Stack>
</DrawerHeader>
<DrawerBody overflowY="auto" mx={-6} mb={10}>
<Stack spacing="6" color="brandGray.500" fontSize="md" p={6} pt={0}>
<Stack spacing="3">
<Text>{t('Burn iDNA to make your ad visible.')}</Text>
</Stack>
<Stack spacing="6" bg="gray.50" p={6} rounded="lg">
<Stack isInline spacing={5} align="flex-start">
<AdImage src={adImageThumbSrc(ad)} w="10" />
<Box>
<Text fontWeight={500}>{ad.title}</Text>
<ExternalLink href={ad.url} maxW="48">
{ad.url}
</ExternalLink>
</Box>
</Stack>
<Stack spacing={3}>
<HDivider />
<InlineAdStatGroup labelWidth="24">
<InlineAdStat
label={t('Competitors')}
value={String(competitorCount)}
/>
<InlineAdStat
label={t('Max bid')}
value={maxCompetitor ? formatDna(maxCompetitor.amount) : '--'}
/>
</InlineAdStatGroup>
<HDivider />
<InlineAdStatGroup labelWidth="20">
<SmallInlineAdStat label={t('Language')} value={ad.language} />
<SmallInlineAdStat label={t('Min stake')} value={ad.stake} />
<SmallInlineAdStat label={t('Min age')} value={ad.age} />
<SmallInlineAdStat label={t('OS')} value={ad.os} />
</InlineAdStatGroup>
</Stack>
</Stack>
<form
id="burnForm"
onSubmit={e => {
e.preventDefault()
const amount = Number(new FormData(e.target).get('amount'))
if (amount > 0 && amount < balance) {
setIsPendingOn()
submit({ad, amount})
} else {
failToast(
amount > 0
? t('Insufficient funds to burn {{amount}}', {
amount: formatDna(amount),
})
: t('Invalid amount')
)
}
}}
>
<FormControl>
<Stack spacing={3}>
<FormLabel htmlFor="amount" mb={0}>
{t('Amount, iDNA')}
</FormLabel>
<AdNumberInput
name="amount"
min={0}
max={Number.MAX_SAFE_INTEGER}
addon={t('iDNA')}
/>
</Stack>
</FormControl>
</form>
</Stack>
</DrawerBody>
<DrawerFooter>
<PrimaryButton
type="submit"
form="burnForm"
isLoading={isPending}
loadingText={t('Mining...')}
>
{t('Burn')}
</PrimaryButton>
</DrawerFooter>
</AdDrawer>
)
}
Example #23
Source File: ModalDialog.js From web-client with Apache License 2.0 | 4 votes |
ReportVersionModalDialog = ({ projectId, isOpen, onSubmit, onCancel }) => {
const defaultFormValues = { reportTemplateId: 0, name: "", description: "" };
const [formValues, setFormValues] = useState(defaultFormValues);
const [templates] = useFetch('/reports/templates');
const onFormValueChange = ev => {
ev.preventDefault();
setFormValues({ ...formValues, [ev.target.name]: ev.target.value });
};
const beforeCancelCallback = ev => {
setFormValues(defaultFormValues);
onCancel(ev);
}
const onFormSubmit = ev => {
ev.preventDefault();
const params = {
projectId: projectId,
reportTemplateId: formValues.reportTemplateId,
name: formValues.name,
description: formValues.description
};
secureApiFetch(`/reports`, { method: 'POST', body: JSON.stringify(params) })
.then(() => {
onSubmit();
actionCompletedToast(`The report version "${formValues.name}" has been added.`);
})
.catch(err => {
console.error(err);
})
.finally(() => {
setFormValues(defaultFormValues)
})
}
useEffect(() => {
if (templates !== null && templates.length > 0) {
setFormValues((prev) => ({ ...prev, reportTemplateId: templates[0].id }))
}
}, [templates]);
return <Modal size="xl" isOpen={isOpen} onClose={beforeCancelCallback}>
<ModalOverlay />
<ModalContent>
<ModalHeader><HStack><TargetIcon style={{ width: '24px' }} /> <h4>New report version details</h4></HStack></ModalHeader>
<ModalCloseButton />
<ModalBody>
<form id="reportVersionReportForm" onSubmit={onFormSubmit} className="crud" style={{ marginTop: '20px' }}>
<FormControl isRequired>
<FormLabel>Template</FormLabel>
{templates && <Select name="reportTemplateId" value={formValues.reportTemplateId} onChange={onFormValueChange}>
{templates.map(template => <option key={template.id} value={template.id}>{template.version_name}</option>)}
</Select>}
</FormControl>
<FormControl isRequired>
<FormLabel>Name</FormLabel>
<Input type="text" name="name" value={formValues.name} onChange={onFormValueChange}
placeholder="eg 1.0, 202103" autoFocus />
</FormControl>
<FormControl isRequired>
<FormLabel>Description</FormLabel>
<Input type="text" name="description" value={formValues.description}
onChange={onFormValueChange}
placeholder="eg Initial version, Draft"
/>
</FormControl>
</form>
</ModalBody>
<ModalFooter>
<Button onClick={beforeCancelCallback} mr={3}>Cancel</Button>
<Button form="reportVersionReportForm" type="submit" colorScheme="blue">Save</Button>
</ModalFooter>
</ModalContent>
</Modal>
}
Example #24
Source File: node.js From idena-web with MIT License | 4 votes |
function Settings() {
const {t} = useTranslation()
const {addNotification} = useNotificationDispatch()
const settingsState = useSettingsState()
const {saveConnection} = useSettingsDispatch()
const size = useBreakpointValue(['lg', 'md'])
const flexDirection = useBreakpointValue(['column', 'row'])
const flexJustify = useBreakpointValue(['flex-start', 'space-between'])
const [state, setState] = useState({
url: settingsState.url || '',
apiKey: settingsState.apiKey || '',
})
const [nodeProvider, setNodeProvider] = useState('')
useEffect(() => {
setState({url: settingsState.url, apiKey: settingsState.apiKey})
}, [settingsState])
const notify = () =>
addNotification({
title: 'Settings updated',
body: `Connected to url ${state.url}`,
})
useEffect(() => {
async function check() {
try {
const result = await checkKey(settingsState.apiKey)
const provider = await getProvider(result.provider)
setNodeProvider(provider.data.ownerName)
} catch (e) {}
}
if (settingsState.apiKeyState === ApiKeyStates.OFFLINE) check()
}, [settingsState.apiKeyState, settingsState.url, settingsState.apiKey])
return (
<SettingsLayout title={t('Node')}>
<Stack
spacing={5}
mt={[3, 8]}
width={['100%', '480px']}
position="relative"
>
{settingsState.apiKeyState === ApiKeyStates.RESTRICTED && (
<Alert
status="error"
bg="red.010"
borderWidth="1px"
borderColor="red.050"
fontWeight={500}
rounded="md"
px={3}
py={2}
>
<AlertIcon name="info" color="red.500" size={5} mr={3}></AlertIcon>
{t(
'The shared node access is restricted. You cannot use the node for the upcoming validation ceremony.'
)}
</Alert>
)}
{settingsState.apiKeyState === ApiKeyStates.OFFLINE &&
!!settingsState.url &&
!!settingsState.apiKey && (
<Alert
status="error"
bg="red.010"
borderWidth="1px"
borderColor="red.050"
fontWeight={500}
rounded="md"
px={3}
py={2}
>
<AlertIcon name="info" color="red.500" size={5} mr={3} />
<Text>
{nodeProvider
? t(
'This node is unavailable. Please contact the node owner:',
{
nsSeparator: 'null',
}
)
: t('Node is unavailable.')}{' '}
{nodeProvider && (
<Link
color="#578fff"
href={`https://t.me/${nodeProvider}`}
target="_blank"
ml={1}
>
{nodeProvider}
</Link>
)}
</Text>
</Alert>
)}
<Flex display={['none', 'flex']} justify="space-between">
<Heading as="h1" fontSize="lg" fontWeight={500} textAlign="start">
{t('Node settings')}
</Heading>
<Box mt="3px">
<Link
color="#578fff"
fontSize="13px"
fontWeight="500"
height="17px"
href="/node/rent"
>
{t('Rent a new node')}
<ChevronDownIcon boxSize={4} transform="rotate(-90deg)" />
</Link>
</Box>
</Flex>
<FormControl
as={Flex}
direction={flexDirection}
justify={flexJustify}
mt={[0, 5]}
>
<Flex justify="space-between">
<FormLabel
fontSize={['base', 'md']}
color={['brandGray.500', 'muted']}
fontWeight={[500, 400]}
mb={[2, 0]}
lineHeight={[6, 8]}
>
{t('Shared node URL')}
</FormLabel>
<Box display={['block', 'none']}>
<Link
fontSize="16px"
fontWeight="500"
color="#578fff"
href="/node/rent"
>
{t('Rent a new node')}
</Link>
</Box>
</Flex>
<Input
id="url"
w={['100%', '360px']}
size={size}
value={state.url}
onChange={e => setState({...state, url: e.target.value})}
/>
</FormControl>
<FormControl as={Flex} direction={flexDirection} justify={flexJustify}>
<FormLabel
fontSize={['base', 'md']}
color={['brandGray.500', 'muted']}
fontWeight={[500, 400]}
mb={[2, 0]}
lineHeight={[6, 8]}
>
{t('Node API key')}
</FormLabel>
<PasswordInput
id="key"
w={['100%', '360px']}
size={size}
value={state.apiKey}
onChange={e => setState({...state, apiKey: e.target.value})}
/>
</FormControl>
{settingsState.apiKeyState === ApiKeyStates.ONLINE && (
<Alert
status="warning"
bg="warning.020"
borderWidth="1px"
borderColor="warning.100"
fontWeight={500}
rounded="md"
px={3}
py={2}
>
<AlertIcon size={5} mr={3} colo="warning.500"></AlertIcon>
{t(
'Please do not use the API key on multiple devices at the same time as this will cause the validation failure.'
)}
</Alert>
)}
<Flex justify="space-between">
<PrimaryButton
size={size}
w={['100%', 'auto']}
onClick={() => {
saveConnection(state.url, state.apiKey, true)
notify()
}}
ml="auto"
>
{t('Save')}
</PrimaryButton>
</Flex>
</Stack>
</SettingsLayout>
)
}
Example #25
Source File: Form.js From web-client with Apache License 2.0 | 4 votes |
VulnerabilityForm = ({
isEditForm = false,
vulnerability,
vulnerabilitySetter: setVulnerability,
onFormSubmit
}) => {
const [initialised, setInitialised] = useState(false);
const [projects, setProjects] = useState(null);
const [categories, setCategories] = useState(null);
const [subCategories, setSubCategories] = useState(null);
const [targets, setTargets] = useState(null);
const [useOWASP, setMetrics] = useState(false);
useEffect(() => {
if (initialised) return;
Promise.all([
secureApiFetch(`/projects`, { method: 'GET' }),
secureApiFetch(`/vulnerabilities/categories`, { method: 'GET' }),
])
.then(resp => {
const [respA, respB] = resp;
return Promise.all([respA.json(), respB.json()]);
})
.then(([projects, categories]) => {
const defaultProjectId = projects.length ? projects[0].id : 0;
const projectId = isEditForm ? vulnerability.project_id : defaultProjectId;
setMetrics(isOwaspProject(projects, projectId))
var subcategories = null;
if (vulnerability.parent_category_id) {
secureApiFetch(`/vulnerabilities/categories/${vulnerability.parent_category_id}`, { method: 'GET' })
.then(response => response.json())
.then(json => {
subcategories = json;
})
}
secureApiFetch(`/targets?projectId=${projectId}`, { method: 'GET' })
.then(resp => resp.json())
.then(targets => {
unstable_batchedUpdates(() => {
setProjects(projects);
setCategories(categories);
setTargets(targets);
setVulnerability(prevVulnerability => {
let updatedVulnerability = prevVulnerability;
if (!idExists(projects, prevVulnerability.project_id)) {
updatedVulnerability.project_id = defaultProjectId;
}
if ((!idExists(categories, prevVulnerability.category_id)) && (!idExists(subcategories, prevVulnerability.category_id))) {
updatedVulnerability.category_id = categories[0].id;
}
if (!idExists(targets, vulnerability.target_id)) {
updatedVulnerability.target_id = null;
}
return updatedVulnerability;
})
setInitialised(true);
});
})
});
}, [initialised, isEditForm, setProjects, setCategories, setTargets, setMetrics, setVulnerability, vulnerability.target_id, vulnerability.project_id, vulnerability.parent_category_id, subCategories, setSubCategories]);
useEffect(() => {
if (!initialised) return;
if (vulnerability.parent_category_id) {
secureApiFetch(`/vulnerabilities/categories/${vulnerability.parent_category_id}`, { method: 'GET' })
.then(response => response.json())
.then(json => {
setSubCategories(json);
})
}
const projectId = vulnerability.project_id;
secureApiFetch(`/targets?projectId=${projectId}`, { method: 'GET' })
.then(resp => resp.json())
.then(targets => {
unstable_batchedUpdates(() => {
setTargets(targets);
if (isEditForm) { // Edit
if (!idExists(targets, vulnerability.target_id)) {
setVulnerability(prevVulnerability => {
return { ...prevVulnerability, target_id: 0 }
});
}
}
});
})
}, [initialised, isEditForm, setTargets, setVulnerability, vulnerability.target_id, vulnerability.project_id, vulnerability.parent_category_id]);
const idExists = (elements, id) => {
if (!elements) return false;
for (const el of elements) {
if (el.id === parseInt(id)) return true;
}
return false;
}
const isOwaspProject = (elements, id) => {
let metrics = ProjectVulnerabilityMetrics[0].id;
for (const el of elements) {
if (el.id === parseInt(id)) {
metrics = el.vulnerability_metrics;
}
}
return (ProjectVulnerabilityMetrics[1].id === metrics);
}
const onFormChange = ev => {
const target = ev.target;
const name = target.name;
let value = target.type === 'checkbox' ? target.checked : target.value;
if ('tags' === name) {
value = JSON.stringify(value.split(','));
}
if ('category_id' === name) {
if (value !== '(none)') {
secureApiFetch(`/vulnerabilities/categories/${value}`, { method: 'GET' })
.then(response => response.json())
.then(json => {
setSubCategories(json);
})
setVulnerability({ ...vulnerability, 'parent_category_id': value, [name]: value });
} else {
setVulnerability({ ...vulnerability, 'category_id': null });
}
} else if ('subcategory_id' === name) {
setVulnerability({ ...vulnerability, 'category_id': value });
} else {
setVulnerability({ ...vulnerability, [name]: value });
}
};
return <form onSubmit={onFormSubmit} className="crud">
<Accordion defaultIndex={0} allowToggle allowMultiple>
<AccordionItem index={0}>
<h2>
<AccordionButton>
<Box flex="1" textAlign="left">
Basic information
</Box>
<AccordionIcon />
</AccordionButton>
</h2>
<AccordionPanel pb={4}>
<label>Properties
<div>
<Checkbox name="is_template" onChange={onFormChange} isChecked={vulnerability.is_template}>Is template</Checkbox>
</div>
</label>
<label>External ID
<Input type="text" name="external_id" value={vulnerability.external_id || ""} onChange={onFormChange} />
</label>
<label>Summary
<Input type="text" name="summary" value={vulnerability.summary || ""} onChange={onFormChange} required autoFocus />
</label>
<label>Description
<MarkdownEditor name="description" value={vulnerability.description || ""} onChange={onFormChange} />
</label>
<label>External references
<MarkdownEditor name="external_refs" value={vulnerability.external_refs || ""} onChange={onFormChange} />
</label>
<label>Category
<Select name="category_id" value={vulnerability.parent_category_id || ""} onChange={onFormChange} required>
<option>(none)</option>
{categories && categories.map(cat =>
<option key={cat.id} value={cat.id}>{cat.name}</option>
)}
</Select>
</label>
<label>Subcategory
<Select name="subcategory_id" value={vulnerability.category_id || ""} onChange={onFormChange} required>
<option>(none)</option>
{subCategories && subCategories.map(subcat =>
<option key={subcat.id} value={subcat.id}>{subcat.name}</option>
)}
</Select>
</label>
<FormControl id="visibility" isRequired>
<FormLabel>Visibility</FormLabel>
<Select name="visibility" value={vulnerability.visibility || ""} onChange={onFormChange}>
<option value="public">Public</option>
<option value="private">Private</option>
</Select>
<FormHelperText>Private makes this vulnerability not visible to the client.</FormHelperText>
</FormControl>
<label>Risk
<Select name="risk" value={vulnerability.risk || ""} onChange={onFormChange} required>
{Risks.map(risk =>
<option key={risk.id} value={risk.id}>{risk.name}</option>
)}
</Select>
</label>
<label>Tags
<Input type="text" name="tags" onChange={onFormChange} value={vulnerability.tags ? JSON.parse(vulnerability.tags).join(',') : ''} />
</label>
<label>Proof of concept
<MarkdownEditor name="proof_of_concept" value={vulnerability.proof_of_concept || ""} onChange={onFormChange} />
</label>
<label>Impact
<MarkdownEditor name="impact" value={vulnerability.impact || ""} onChange={onFormChange} />
</label>
{
!useOWASP && <>
<label>CVSS score
<Input type="number" step="0.1" min="0" max="10" name="cvss_score" value={vulnerability.cvss_score || ""}
onChange={onFormChange} />
</label>
<label><span><CvssAbbr /> vector</span>
<Input type="text" name="cvss_vector" value={vulnerability.cvss_vector || ""} onChange={onFormChange} placeholder="eg: AV:N/AC:L/Au:S/C:P/I:P/A:N" />
</label>
</>
}
</AccordionPanel>
</AccordionItem>
{useOWASP &&
<AccordionItem>
<h2>
<AccordionButton>
<Box flex="1" textAlign="left">
Owasp Risk Rating calculator
</Box>
<AccordionIcon />
</AccordionButton>
</h2>
<AccordionPanel pb={4}>
<label>Owasp Risk Rating</label>
<OwaspRR vulnerability={vulnerability} vulnerabilitySetter={setVulnerability} />
</AccordionPanel>
</AccordionItem>
}
<AccordionItem>
<h2>
<AccordionButton>
<Box flex="1" textAlign="left">
Remediation
</Box>
<AccordionIcon />
</AccordionButton>
</h2>
<AccordionPanel pb={4}>
<label>Remediation instructions
<MarkdownEditor name="remediation" value={vulnerability.remediation || ""} onChange={onFormChange} />
</label>
<label>Remediation complexity
<Select name="remediation_complexity" value={vulnerability.remediation_complexity || ""} onChange={onFormChange} required>
{RemediationComplexity.map(complexity =>
<option key={complexity.id} value={complexity.id}>{complexity.name}</option>
)}
</Select>
</label>
<label>Remediation priority
<Select name="remediation_priority" value={vulnerability.remediation_priority || ""} onChange={onFormChange} required>
{RemediationPriority.map(priority =>
<option key={priority.id} value={priority.id}>{priority.name}</option>
)}
</Select>
</label>
</AccordionPanel>
</AccordionItem>
{
!vulnerability.is_template && <AccordionItem>
<h2>
<AccordionButton>
<Box flex="1" textAlign="left">
Relations
</Box>
<AccordionIcon />
</AccordionButton>
</h2>
<AccordionPanel pb={4}>
<label>Project
<Select name="project_id" value={vulnerability.project_id || ""} onChange={onFormChange} required>
{projects && projects.map((project, index) =>
<option key={index} value={project.id}>{project.name}</option>
)}
</Select>
</label>
<label>Affected target
<Select name="target_id" value={vulnerability.target_id || ""} onChange={onFormChange}>
<option value="0">(none)</option>
{targets && targets.map((target, index) =>
<option key={index} value={target.id}>{target.name}</option>
)}
</Select>
</label>
</AccordionPanel>
</AccordionItem>
}
</Accordion>
<Primary type="submit">{isEditForm ? "Save" : "Add"}</Primary>
</form >
}
Example #26
Source File: ChallengeSubmission.jsx From scaffold-directory with MIT License | 4 votes |
// ToDo. on-line form validation
export default function ChallengeSubmission({ challenge, serverUrl, address, userProvider }) {
const { challengeId } = useParams();
const history = useHistory();
const toast = useToast({ position: "top", isClosable: true });
const [isSubmitting, setIsSubmitting] = useState(false);
const [deployedUrl, setDeployedUrl] = useState("");
const [contractUrl, setContractUrl] = useState("");
const [hasErrorField, setHasErrorField] = useState({ deployedUrl: false, contractUrl: false });
const onFinish = async () => {
if (!deployedUrl || !contractUrl) {
toast({
status: "error",
description: "Both fields are required",
});
return;
}
if (!isValidUrl(deployedUrl) || !isValidUrl(contractUrl)) {
toast({
status: "error",
title: "Please provide a valid URL",
description: "Valid URLs start with http:// or https://",
});
setHasErrorField({
deployedUrl: !isValidUrl(deployedUrl),
contractUrl: !isValidUrl(contractUrl),
});
return;
}
setIsSubmitting(true);
let signMessage;
try {
const signMessageResponse = await axios.get(serverUrl + `/sign-message`, {
params: {
messageId: "challengeSubmit",
address,
challengeId,
},
});
signMessage = JSON.stringify(signMessageResponse.data);
} catch (error) {
toast({
description: "Can't get the message to sign. Please try again",
status: "error",
});
setIsSubmitting(false);
return;
}
let signature;
try {
signature = await userProvider.send("personal_sign", [signMessage, address]);
} catch (error) {
toast({
status: "error",
description: "The signature was cancelled",
});
console.error(error);
setIsSubmitting(false);
return;
}
try {
await axios.post(
serverUrl + serverPath,
{
challengeId,
deployedUrl,
contractUrl,
signature,
},
{
headers: {
address,
},
},
);
} catch (error) {
toast({
status: "error",
description: "Submission Error. Please try again.",
});
console.error(error);
setIsSubmitting(false);
return;
}
toast({
status: "success",
description: "Challenge submitted!",
});
setIsSubmitting(false);
history.push("/portfolio");
};
if (!address) {
return (
<Text color="orange.400" className="warning" align="center">
Connect your wallet to submit this Challenge.
</Text>
);
}
return (
<div>
<Heading as="h2" size="md" mb={4}>
{challenge.label}
</Heading>
{challenge.isDisabled ? (
<Text color="orange.400" className="warning">
This challenge is disabled.
</Text>
) : (
<form name="basic" autoComplete="off">
<FormControl id="deployedUrl" isRequired>
<FormLabel>
Deployed URL{" "}
<Tooltip label="Your deployed challenge URL on surge / s3 / ipfs ">
<QuestionOutlineIcon ml="2px" />
</Tooltip>
</FormLabel>
<Input
type="text"
name="deployedUrl"
value={deployedUrl}
placeholder="https://your-site.surge.sh"
onChange={e => {
setDeployedUrl(e.target.value);
if (hasErrorField.deployedUrl) {
setHasErrorField(prevErrorsFields => ({
...prevErrorsFields,
deployedUrl: false,
}));
}
}}
borderColor={hasErrorField.deployedUrl && "red.500"}
/>
</FormControl>
<FormControl id="contractUrl" isRequired mt={4}>
<FormLabel>
Etherscan Contract URL{" "}
<Tooltip label="Your verified contract URL on Etherscan">
<QuestionOutlineIcon ml="2px" />
</Tooltip>
</FormLabel>
<Input
type="text"
name="contractUrl"
value={contractUrl}
placeholder="https://etherscan.io/address/your-contract-address"
onChange={e => {
setContractUrl(e.target.value);
if (hasErrorField.contractUrl) {
setHasErrorField(prevErrorsFields => ({
...prevErrorsFields,
contractUrl: false,
}));
}
}}
borderColor={hasErrorField.contractUrl && "red.500"}
/>
</FormControl>
<div className="form-item">
<Button colorScheme="blue" onClick={onFinish} isLoading={isSubmitting} mt={4} isFullWidth>
Submit
</Button>
</div>
</form>
)}
</div>
);
}
Example #27
Source File: BuilderProfileCard.jsx From scaffold-directory with MIT License | 4 votes |
BuilderProfileCard = ({ builder, mainnetProvider, isMyProfile, userProvider, fetchBuilder, userRole }) => {
const address = useUserAddress(userProvider);
const ens = useDisplayAddress(mainnetProvider, builder?.id);
const [updatedSocials, setUpdatedSocials] = useState({});
const [isUpdatingReachedOutFlag, setIsUpdatingReachedOutFlag] = useState(false);
const [isUpdatingSocials, setIsUpdatingSocials] = useState(false);
const { isOpen, onOpen, onClose } = useDisclosure();
const { hasCopied, onCopy } = useClipboard(builder?.id);
const { borderColor, secondaryFontColor } = useCustomColorModes();
const shortAddress = ellipsizedAddress(builder?.id);
const hasEns = ens !== shortAddress;
const toast = useToast({ position: "top", isClosable: true });
const toastVariant = useColorModeValue("subtle", "solid");
const joinedDate = new Date(builder?.creationTimestamp);
const joinedDateDisplay = joinedDate.toLocaleString("default", { month: "long" }) + " " + joinedDate.getFullYear();
// INFO: conditional chaining and coalescing didn't work when also checking the length
const hasProfileLinks = builder?.socialLinks ? Object.keys(builder.socialLinks).length !== 0 : false;
const isAdmin = userRole === USER_ROLES.admin;
useEffect(() => {
if (builder) {
setUpdatedSocials(builder.socialLinks ?? {});
}
}, [builder]);
const handleUpdateSocials = async () => {
setIsUpdatingSocials(true);
// Avoid sending socials with empty strings.
const socialLinkCleaned = Object.fromEntries(Object.entries(updatedSocials).filter(([_, value]) => !!value));
const invalidSocials = validateSocials(socialLinkCleaned);
if (invalidSocials.length !== 0) {
toast({
description: `The usernames for the following socials are not correct: ${invalidSocials
.map(([social]) => social)
.join(", ")}`,
status: "error",
variant: toastVariant,
});
setIsUpdatingSocials(false);
return;
}
let signMessage;
try {
signMessage = await getUpdateSocialsSignMessage(address);
} catch (error) {
toast({
description: " Sorry, the server is overloaded. ???",
status: "error",
variant: toastVariant,
});
setIsUpdatingSocials(false);
return;
}
let signature;
try {
signature = await userProvider.send("personal_sign", [signMessage, address]);
} catch (error) {
toast({
description: "Couldn't get a signature from the Wallet",
status: "error",
variant: toastVariant,
});
setIsUpdatingSocials(false);
return;
}
try {
await postUpdateSocials(address, signature, socialLinkCleaned);
} catch (error) {
if (error.status === 401) {
toast({
status: "error",
description: "Access error",
variant: toastVariant,
});
setIsUpdatingSocials(false);
return;
}
toast({
status: "error",
description: "Can't update your socials. Please try again.",
variant: toastVariant,
});
setIsUpdatingSocials(false);
return;
}
toast({
description: "Your social links have been updated",
status: "success",
variant: toastVariant,
});
fetchBuilder();
setIsUpdatingSocials(false);
onClose();
};
const handleUpdateReachedOutFlag = async reachedOut => {
setIsUpdatingReachedOutFlag(true);
let signMessage;
try {
signMessage = await getUpdateReachedOutFlagSignMessage(builder.id, reachedOut);
} catch (error) {
toast({
description: " Sorry, the server is overloaded. ???",
status: "error",
variant: toastVariant,
});
setIsUpdatingReachedOutFlag(false);
return;
}
let signature;
try {
signature = await userProvider.send("personal_sign", [signMessage, address]);
} catch (error) {
toast({
description: "Couldn't get a signature from the Wallet",
status: "error",
variant: toastVariant,
});
setIsUpdatingReachedOutFlag(false);
return;
}
try {
await postUpdateReachedOutFlag(address, builder.id, reachedOut, signature);
} catch (error) {
if (error.status === 401) {
toast({
status: "error",
description: "Access error",
variant: toastVariant,
});
setIsUpdatingReachedOutFlag(false);
return;
}
toast({
status: "error",
description: "Can't update the reached out flag. Please try again.",
variant: toastVariant,
});
setIsUpdatingReachedOutFlag(false);
return;
}
toast({
description: 'Updated "reached out" flag successfully',
status: "success",
variant: toastVariant,
});
fetchBuilder();
setIsUpdatingReachedOutFlag(false);
};
return (
<>
<BuilderProfileCardSkeleton isLoaded={!!builder}>
{() => (
/* delay execution */
<Flex
borderRadius="lg"
borderColor={borderColor}
borderWidth={1}
justify={{ base: "space-around", xl: "center" }}
direction={{ base: "row", xl: "column" }}
p={4}
pb={6}
maxW={{ base: "full", lg: "50%", xl: 60 }}
margin="auto"
>
<Link as={RouteLink} to={`/builders/${builder.id}`}>
<QRPunkBlockie
withQr={false}
address={builder.id?.toLowerCase()}
w={52}
borderRadius="lg"
margin="auto"
/>
</Link>
<Flex alignContent="center" direction="column" mt={4}>
{hasEns ? (
<>
<Text fontSize="2xl" fontWeight="bold" textAlign="center">
{ens}
</Text>
<Text textAlign="center" mb={4} color={secondaryFontColor}>
{shortAddress}{" "}
<Tooltip label={hasCopied ? "Copied!" : "Copy"} closeOnClick={false}>
<CopyIcon cursor="pointer" onClick={onCopy} />
</Tooltip>
</Text>
</>
) : (
<Text fontSize="2xl" fontWeight="bold" textAlign="center" mb={8}>
{shortAddress}{" "}
<Tooltip label={hasCopied ? "Copied!" : "Copy"} closeOnClick={false}>
<CopyIcon cursor="pointer" onClick={onCopy} />
</Tooltip>
</Text>
)}
{isAdmin && (
<Center mb={4}>
{builder.reachedOut ? (
<Badge variant="outline" colorScheme="green" alignSelf="center">
Reached Out
</Badge>
) : (
<Button
colorScheme="green"
size="xs"
onClick={() => handleUpdateReachedOutFlag(true)}
isLoading={isUpdatingReachedOutFlag}
alignSelf="center"
>
Mark as reached out
</Button>
)}
</Center>
)}
<Divider mb={6} />
{hasProfileLinks ? (
<Flex mb={4} justifyContent="space-evenly" alignItems="center">
{Object.entries(builder.socialLinks)
.sort(bySocialWeight)
.map(([socialId, socialValue]) => (
<SocialLink id={socialId} value={socialValue} />
))}
</Flex>
) : (
isMyProfile && (
<Alert mb={3} status="warning">
<Text style={{ fontSize: 11 }}>
You haven't set your socials{" "}
<Tooltip label="It's our way of reaching out to you. We could sponsor you an ENS, offer to be part of a build or set up an ETH stream for you.">
<QuestionOutlineIcon />
</Tooltip>
</Text>
</Alert>
)
)}
{isMyProfile && (
<Button mb={3} size="xs" variant="outline" onClick={onOpen}>
Update socials
</Button>
)}
<Text textAlign="center" color={secondaryFontColor}>
Joined {joinedDateDisplay}
</Text>
</Flex>
</Flex>
)}
</BuilderProfileCardSkeleton>
<Modal isOpen={isOpen} onClose={onClose}>
<ModalOverlay />
<ModalContent>
<ModalHeader>Update your socials</ModalHeader>
<ModalCloseButton />
<ModalBody p={6}>
{Object.entries(socials).map(([socialId, socialData]) => (
<FormControl id="socialId" key={socialId} mb={3}>
<FormLabel htmlFor={socialId} mb={0}>
<strong>{socialData.label}:</strong>
</FormLabel>
<Input
type="text"
name={socialId}
value={updatedSocials[socialId] ?? ""}
placeholder={socialData.placeholder}
onChange={e => {
const value = e.target.value;
setUpdatedSocials(prevSocials => ({
...prevSocials,
[socialId]: value,
}));
}}
/>
</FormControl>
))}
<Button colorScheme="blue" onClick={handleUpdateSocials} isLoading={isUpdatingSocials} isFullWidth mt={4}>
Update
</Button>
</ModalBody>
</ModalContent>
</Modal>
</>
);
}
Example #28
Source File: index.js From UpStats with MIT License | 4 votes |
export default function Home({ status, systems, config }) {
console.log(status);
console.log(systems);
const [email, setEmail] = useState("");
const toast = useToast();
const handleSubmit = async (email) => {
try {
await http.post("/subs", { email: email });
toast({
title: "Success",
description: "Successfully Subscribed ",
status: "success",
duration: 9000,
isClosable: true,
});
} catch (ex) {
toast({
title: "Error",
description: "Submit Unsuccessful",
status: "error",
duration: 9000,
isClosable: true,
});
}
};
return (
<>
<Head>
<meta charSet="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, viewport-fit=cover"
/>
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" />
<link rel="icon" href="/favicon.ico" type="image/x-icon" />
<title>UP Stats</title>
<link rel="stylesheet" href="/main.css" />
</Head>
<main className="root">
<header className="top-0">
<nav>
<div className="content-center p-4">
{/* Nav Bar Logo */}
<img className="nav-brand" src="assets/img/logo.jpg" />
</div>
</nav>
</header>
<section>
<Center mt="5">
<Box bg="blue" w="90%" p={4} color="white" borderRadius="md">
{status.operational
? "All Systems Operational"
: `${status.outageCount} Systems Outage`}
</Box>
</Center>
<br />
<VStack>
{systems.map((system) => (
<Flex
id={system._id}
borderRadius="md"
boxShadow="lg"
w="90%"
p={3}
bg="white"
>
<Text pl={3}>{system.name}</Text>
<Spacer />
{system.status === "up" && (
<CheckCircleIcon mr={5} mt="1" color="green" />
)}
{system.status === "down" && (
<WarningIcon mr={5} mt="1" color="red" />
)}
</Flex>
))}
</VStack>
</section>
{config.mailing ? (
<VStack p={10} m={10} borderWidth={1} borderRadius="lg">
<h1 className="font-sans text-xl">Want to see Back in action?</h1>
<p className="font-sans">
Subscribe via Email and <br />
Get notified about the System Status
</p>
<Center>
<FormControl id="email" width="90%">
<FormLabel>Email address</FormLabel>
<Input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<Box
width="8em"
mt="3"
height="3em"
border="1px"
color="white"
bg="blue"
borderRadius="lg"
p="3"
onClick={() => handleSubmit(email)}
>
<EmailIcon mr={3} />
Subscribe
</Box>
</FormControl>
</Center>
</VStack>
) : (
""
)}
<footer className="px-4 py-16 mx-auto max-w-7xl">
<nav className="grid grid-cols-2 gap-12 mb-12 md:grid-cols-3 lg:grid-cols-5">
<div>
<p className="mb-4 text-sm font-medium text-primary">
Handy Links
</p>
<a
className="flex mb-3 text-sm font-medium text-gray-700 transition md:mb-2 hover:text-primary"
href="https://github.com/ToolsHD/UPStats"
>
Opensource
</a>
<a
className="flex mb-3 text-sm font-medium text-gray-700 transition md:mb-2 hover:text-primary"
href="#"
>
Features
</a>
<a
className="flex mb-3 text-sm font-medium text-gray-700 transition md:mb-2 hover:text-primary"
href="#"
>
Pricing
</a>
</div>
</nav>
<div className="flex flex-col items-center justify-between md:flex-row">
<a href="/" className="mb-4 md:mb-0">
<img id="footer-img" src="assets/img/footer.jpg" />
<span className="sr-only">UpStats</span>
</a>
<p className="text-sm text-center text-gray-600 md:text-left">
© 2021 <a href="#">UP Stats</a>
</p>
</div>
</footer>
<div>
<button onClick="topFunction()" id="scroll-to-top">
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-6 w-6"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M5 10l7-7m0 0l7 7m-7-7v18"
/>
</svg>
</button>
</div>
</main>
</>
);
}
Example #29
Source File: playlists.js From grandcast.fm with Apache License 2.0 | 4 votes |
export default function Playlists() {
const { isSignedIn } = useAuth()
const [selectedPlaylist, setSelectedPlaylist] = useState('')
const [newPlaylist, setNewPlaylist] = useState('')
const { data } = useQuery(GET_PLAYLISTS)
const [createPlaylist] = useMutation(CREATE_PLAYLIST)
const filteredPlaylist = data?.playlists?.filter((p) => {
return p.name === selectedPlaylist
})[0]
return (
<Container>
{!isSignedIn() && <SignIn />}
{isSignedIn() && (
<div>
<FormControl id="playlists">
<Flex>
<Select
placeholder="Select playlist"
onChange={(e) => setSelectedPlaylist(e.target.value)}
>
{data?.playlists?.map((p) => {
return (
<option key={p.name} value={p.value}>
{p.name}
</option>
)
})}
</Select>
<Popover>
<PopoverTrigger>
<Button ml={4}>
<AddIcon />
</Button>
</PopoverTrigger>
<PopoverContent>
<PopoverArrow />
<PopoverCloseButton />
<PopoverHeader>Create new playlist</PopoverHeader>
<PopoverBody>
<FormControl id="newplaylist">
<Input
type="text"
onChange={(e) => setNewPlaylist(e.target.value)}
/>
<Button
mt={4}
onClick={() =>
createPlaylist({
variables: { playlistName: newPlaylist },
update: (proxy) => {
const data = proxy.readQuery({
query: GET_PLAYLISTS,
})
proxy.writeQuery({
query: GET_PLAYLISTS,
data: {
playlists: [
...data.playlists,
{
__typename: 'Playlist',
name: newPlaylist,
},
],
},
})
},
})
}
>
Create
</Button>
</FormControl>
</PopoverBody>
</PopoverContent>
</Popover>
</Flex>
</FormControl>
<VStack mt={4} spacing={4}>
{filteredPlaylist?.episodes?.map((e) => {
return (
<Episode key={e.id} episode={e} playlists={data.playlists} />
)
})}
</VStack>
</div>
)}
</Container>
)
}