@chakra-ui/react#Checkbox JavaScript Examples
The following examples show how to use
@chakra-ui/react#Checkbox.
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: select.js From react-table-library with MIT License | 5 votes |
Component = () => {
const data = { nodes };
const chakraTheme = getTheme(DEFAULT_OPTIONS);
const customTheme = {
Table: `
--data-table-library_grid-template-columns: 64px repeat(5, minmax(0, 1fr));
`,
};
const theme = useTheme([chakraTheme, customTheme]);
const select = useRowSelect(data, {
onChange: onSelectChange,
});
function onSelectChange(action, state) {
console.log(action, state);
}
const COLUMNS = [
{
label: 'Task',
renderCell: (item) => item.name,
select: {
renderHeaderCellSelect: () => (
<Checkbox
colorScheme="teal"
isChecked={select.state.all}
isIndeterminate={!select.state.all && !select.state.none}
onChange={select.fns.onToggleAll}
/>
),
renderCellSelect: (item) => (
<Checkbox
colorScheme="teal"
isChecked={select.state.ids.includes(item.id)}
onChange={() => select.fns.onToggleById(item.id)}
/>
),
},
},
{
label: 'Deadline',
renderCell: (item) =>
item.deadline.toLocaleDateString('en-US', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
}),
},
{ label: 'Type', renderCell: (item) => item.type },
{
label: 'Complete',
renderCell: (item) => item.isComplete.toString(),
},
{ label: 'Tasks', renderCell: (item) => item.nodes?.length },
];
return (
<>
<Box p={3} borderWidth="1px" borderRadius="lg">
<CompactTable columns={COLUMNS} data={data} theme={theme} select={select} />
</Box>
<br />
<DocumentationSee anchor={'Features/' + key} />
</>
);
}
Example #2
Source File: filter.js From react-table-library with MIT License | 5 votes |
Component = () => {
let data = { nodes };
const chakraTheme = getTheme(DEFAULT_OPTIONS);
const theme = useTheme(chakraTheme);
const [isHide, setHide] = React.useState(false);
data = {
nodes: isHide ? data.nodes.filter((node) => !node.isComplete) : data.nodes,
};
const COLUMNS = [
{ label: 'Task', renderCell: (item) => item.name },
{
label: 'Deadline',
renderCell: (item) =>
item.deadline.toLocaleDateString('en-US', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
}),
},
{ label: 'Type', renderCell: (item) => item.type },
{
label: 'Complete',
renderCell: (item) => item.isComplete.toString(),
},
{ label: 'Tasks', renderCell: (item) => item.nodes?.length },
];
return (
<>
<Stack spacing={10}>
<Checkbox
colorScheme="teal"
isChecked={isHide}
onChange={(event) => setHide(event.target.checked)}
>
Hide Complete
</Checkbox>
</Stack>
<br />
<Box p={3} borderWidth="1px" borderRadius="lg">
<CompactTable columns={COLUMNS} data={data} theme={theme} />
</Box>
<br />
<DocumentationSee anchor={'Features/' + key} />
</>
);
}
Example #3
Source File: DashboardPanels.js From web-client with Apache License 2.0 | 5 votes |
DashboardPanels = () => {
const user = Auth.getLoggedInUser();
user.preferences = initialiseUserPreferences(user);
const [dashboardConfig, setDashboardConfig] = useState(user?.preferences?.['web-client.widgets'] || InitialiseWidgetConfig());
const [visibleWidgets, setVisibleWidgets] = useState(filterWidgets(user));
const onWidgetChange = ev => {
setDashboardConfig(prev => ({ ...prev, [ev.target.name]: { ...prev[ev.target.name], visible: ev.target.checked } }));
}
const onSave = () => {
const user = Auth.getLoggedInUser();
user.preferences = initialiseUserPreferences(user);
user.preferences['web-client.widgets'] = dashboardConfig;
secureApiFetch(`/users/${user.id}`, {
method: 'PATCH',
body: JSON.stringify({ preferences: user.preferences })
})
.then(() => {
localStorage.setItem('user', JSON.stringify(user));
setVisibleWidgets(filterWidgets(user));
actionCompletedToast("Your preferences have been saved.");
})
.catch(err => console.error(err));
}
if (dashboardConfig === null) return <Loading />
return <section>
<Title type="Home" title="Dashboard" icon={<IconChartBar />} />
<PageTitle value="Dashboard" />
<Tabs>
<TabList>
<Tab>View</Tab>
<Tab>Configure</Tab>
</TabList>
<TabPanels>
<TabPanel>
<SimpleGrid gap="3" columns={{ base: "1", md: "2", xl: "3" }}>
{visibleWidgets.length === 0 ? <WelcomeWidget /> : visibleWidgets}
</SimpleGrid>
</TabPanel>
<TabPanel>
<h4>Select which widgets to present in your dashboard</h4>
<br />
<Stack>
{Object.keys(Widgets).map(widgetKey => {
const widget = Widgets[widgetKey];
if (!widget.hasOwnProperty("permissions") || PermissionsService.isAllowed(widget.permissions, user.permissions)) {
return <Checkbox key={widgetKey} name={widgetKey} isChecked={dashboardConfig.hasOwnProperty(widgetKey) && dashboardConfig[widgetKey].visible} onChange={onWidgetChange}>{Widgets[widgetKey].title}. <em>{Widgets[widgetKey].description}</em></Checkbox>
} else {
return <></>
}
})}
</Stack>
<Button onClick={onSave}>Save</Button>
</TabPanel>
</TabPanels>
</Tabs>
</section>
}
Example #4
Source File: Form.js From web-client with Apache License 2.0 | 5 votes |
UserForm = ({ isEdit = false, user, userSetter: setUser, onFormSubmit }) => {
const [passwordGenerationMethod, setPasswordGenerationMethod] = useState('autogenerated');
const onFormChange = ev => {
const target = ev.target;
const name = target.name;
const value = target.type === 'checkbox' ? target.checked : target.value;
setUser({ ...user, [name]: value });
};
const onPasswordGenerationMethodChange = ev => {
setPasswordGenerationMethod(ev.target.value);
}
return <form onSubmit={onFormSubmit} className="crud">
<fieldset>
<legend>Basic information</legend>
<label>Full name
<Input type="text" name="full_name" value={user.full_name || ""} onChange={onFormChange} required />
</label>
<label>Short bio
<Input type="text" name="short_bio" value={user.short_bio || ""} onChange={onFormChange}
placeholder="DevSecOps, or Project Manager" />
</label>
<label>Email
<Input type="email" name="email" value={user.email || ""} onChange={onFormChange} required />
</label>
<label>Role
<Select name="role" onChange={onFormChange} value={user.role} required>
{UserRoles.map(role => <option key={`role_${role.id}`} value={role.id}>{role.name}</option>)}
</Select>
</label>
<label>Properties
<div>
<Checkbox name="active" isChecked={user.active} onChange={onFormChange}>Active</Checkbox>
<Checkbox name="mfa_enabled" isChecked={user.mfa_enabled} onChange={onFormChange}>2FA enabled</Checkbox>
</div>
</label>
</fieldset>
<fieldset>
<legend>Credentials</legend>
<label>Username
<Input type="text" name="username" value={user.username || ""} onChange={onFormChange} autoFocus required />
</label>
{!isEdit &&
<>
<label htmlFor="passwordGenerationMethod">Password generation method
<Select name="passwordGenerationMethod" onChange={onPasswordGenerationMethodChange}>
<option value="auto">Auto-generated</option>
<option value="manual">Manual</option>
</Select>
</label>
{passwordGenerationMethod === 'manual' &&
<>
<label>Password
<Input type="password" name="unencryptedPassword" onChange={onFormChange} required />
</label>
<label>
Send email to user
<Checkbox name="sendEmailToUser" onChange={onFormChange} />
</label>
</>
}
</>
}
</fieldset>
<PrimaryButton type="submit">{isEdit ? "Update" : "Create"}</PrimaryButton>
</form >
}
Example #5
Source File: AdvancedSearch.js From web-client with Apache License 2.0 | 5 votes |
AdvancedSearch = () => {
const navigate = useNavigate();
const entityList = {
'commands': 'Commands',
'tasks': 'Tasks',
'vulnerabilities': 'Vulnerabilities',
'vulnerability_templates': 'Vulnerability templates',
'projects': 'Projects',
'project_templates': 'Project templates'
};
const [keywords, setKeywords] = useState('');
const [entities, setEntities] = useState(Object.keys(entityList));
const onFormSubmit = (ev) => {
ev.preventDefault();
navigate(`/search/${keywords.trim()}?entities=` + entities.join(','));
}
const onKeywordsChange = ev => {
setKeywords(ev.target.value);
};
const onFormInputChange = ev => {
const target = ev.target;
const value = target.value;
setEntities(target.checked ? [...entities, value] : entities.filter(entity => entity !== value));
};
return <>
<PageTitle value={`Advanced search`} />
<div className='heading'>
<Breadcrumb />
</div>
<Title type='Advanced search' title="Search form" icon={<IconSearch />} />
<form onSubmit={onFormSubmit}>
<Input type="search" name="keywords" value={keywords} onChange={onKeywordsChange} placeholder="Keywords" />
{Object.keys(entityList).map((objectKey) =>
<Checkbox isChecked={entities.includes(objectKey)} value={objectKey} onChange={onFormInputChange}>{entityList[objectKey]}</Checkbox>
)}
<Button type="submit" isDisabled={keywords.trim().length === 0 || entities.length === 0}>Search</Button>
</form>
</>
}
Example #6
Source File: VaultTab.js From web-client with Apache License 2.0 | 4 votes |
ProjectVaultTab = ({ project }) => {
const [vault, refreshVault] = useFetch(`/vault/${project.id}`);
const [vaultItem, setVaultItem] = useState(new Vault());
const onVaultItemFormChange = ev => {
const value = ev.target.type === 'checkbox' ? ev.target.checked : ev.target.value;
setVaultItem({ ...vaultItem, [ev.target.name]: value });
}
const onVaultItemDelete = vaultItemId => {
secureApiFetch(`/vault/${project.id}/${vaultItemId}`, { method: 'DELETE' })
.then(() => {
refreshVault();
actionCompletedToast("The vault item has been deleted.");
})
.catch(err => console.error(err))
}
const onFormSubmit = ev => {
ev.preventDefault();
secureApiFetch(`/vault/${project.id}`, { method: 'POST', body: JSON.stringify(vaultItem) })
.then(resp => {
if (resp.status === 201) {
setVaultItem(new Vault());
refreshVault();
actionCompletedToast(`The vault item has been added.`);
} else {
errorToast("The vault item could not be saved. Review the form data or check the application logs.")
}
})
}
return <section>
<RestrictedComponent roles={['administrator', 'superuser', 'user']} message="(access restricted)">
{vault && <>
<Table>
<Thead>
<Tr>
<Th>Name</Th>
<Th>Note</Th>
<Th>Type</Th>
<Th>Reportable</Th>
<Th> </Th>
</Tr>
</Thead>
<Tbody>
{0 === vault.length && <NoResultsTableRow numColumns={3} />}
{vault.map(item => <>
<Tr key={item.id}>
<Td>{item.name}</Td>
<Td>{item.note}</Td>
<Td>{item.type}</Td>
<Td>{item.reportable}</Td>
<Td textAlign="right">
<LinkButton href={`/vault/${project.id}/${item.id}/edit`}>Edit</LinkButton>
<DeleteIconButton onClick={onVaultItemDelete.bind(this, item.id)} />
</Td>
</Tr>
</>)}
</Tbody>
</Table>
<form onSubmit={onFormSubmit}>
<h3>New vault item</h3>
<Table>
<Thead>
<Tr>
<Th>Type</Th>
<Th>Name</Th>
<Th>Note</Th>
<Th>Value</Th>
<Th>Password</Th>
<Th>Reportable</Th>
<Th> </Th>
</Tr>
</Thead>
<Tbody>
<Tr>
<Td>
<Select name="type" onChange={onVaultItemFormChange} value={vaultItem.type || ""} isRequired>
<option value="password">Password</option>
<option value="note">Note</option>
<option value="token">Token</option>
<option value="key">Key</option>
</Select>
</Td>
<Td>
<Input type="text" name="name" onChange={onVaultItemFormChange} value={vaultItem.name || ""} isRequired />
</Td>
<Td>
<Input type="text" name="note" onChange={onVaultItemFormChange} value={vaultItem.note || ""} />
</Td>
<Td>
<Input type="text" name="value" onChange={onVaultItemFormChange} value={vaultItem.value || ""} isRequired />
</Td>
<Td>
<Input type="password" name="password" onChange={onVaultItemFormChange} value={vaultItem.password || ""} isRequired />
</Td>
<Td>
<Checkbox name="reportable" onChange={onVaultItemFormChange} isChecked={vaultItem.reportable} />
</Td>
<Td>
<Button type="submit">Add</Button>
</Td>
</Tr>
</Tbody>
</Table>
</form>
</>}
</RestrictedComponent>
</section>;
}
Example #7
Source File: showreel.js From react-table-library with MIT License | 4 votes |
Component = () => {
const [data, setData] = React.useState({ nodes });
//* Theme *//
const chakraTheme = getTheme({
...DEFAULT_OPTIONS,
striped: true,
});
const customTheme = {
Table: `
--data-table-library_grid-template-columns: 64px repeat(5, minmax(0, 1fr));
margin: 16px 0px;
`,
};
const theme = useTheme([chakraTheme, customTheme]);
//* Resize *//
const resize = { resizerHighlight: '#dee2e6' };
//* Pagination *//
const pagination = usePagination(data, {
state: {
page: 0,
size: 4,
},
onChange: onPaginationChange,
});
function onPaginationChange(action, state) {
console.log(action, state);
}
//* Search *//
const [search, setSearch] = React.useState('');
useCustom('search', data, {
state: { search },
onChange: onSearchChange,
});
function onSearchChange(action, state) {
console.log(action, state);
pagination.fns.onSetPage(0);
}
//* Filter *//
const [isHide, setHide] = React.useState(false);
useCustom('filter', data, {
state: { isHide },
onChange: onFilterChange,
});
function onFilterChange(action, state) {
console.log(action, state);
pagination.fns.onSetPage(0);
}
//* Select *//
const select = useRowSelect(data, {
onChange: onSelectChange,
});
function onSelectChange(action, state) {
console.log(action, state);
}
//* Tree *//
const tree = useTree(
data,
{
onChange: onTreeChange,
},
{
clickType: TreeExpandClickTypes.ButtonClick,
treeYLevel: 1,
treeIcon: {
margin: '4px',
iconDefault: null,
iconRight: <FaChevronRight />,
iconDown: <FaChevronDown />,
},
},
);
function onTreeChange(action, state) {
console.log(action, state);
}
//* Sort *//
const sort = useSort(
data,
{
onChange: onSortChange,
},
{
sortIcon: {
iconDefault: null,
iconUp: <FaChevronUp />,
iconDown: <FaChevronDown />,
},
sortFns: {
TASK: (array) => array.sort((a, b) => a.name.localeCompare(b.name)),
DEADLINE: (array) => array.sort((a, b) => a.deadline - b.deadline),
TYPE: (array) => array.sort((a, b) => a.type.localeCompare(b.type)),
COMPLETE: (array) => array.sort((a, b) => a.isComplete - b.isComplete),
TASKS: (array) => array.sort((a, b) => (a.nodes || []).length - (b.nodes || []).length),
},
},
);
function onSortChange(action, state) {
console.log(action, state);
}
//* Drawer *//
const [drawerId, setDrawerId] = React.useState(null);
const [edited, setEdited] = React.useState('');
const handleEdit = (event) => {
setEdited(event.target.value);
};
const handleCancel = () => {
setEdited('');
setDrawerId(null);
};
const handleSave = () => {
const node = findNodeById(data.nodes, drawerId);
const editedNode = { ...node, name: edited };
const nodes = insertNode(data.nodes, editedNode);
setData({
nodes,
});
setEdited('');
setDrawerId(null);
};
//* Modal *//
const [modalOpened, setModalOpened] = React.useState(false);
//* Custom Modifiers *//
let modifiedNodes = data.nodes;
// search
modifiedNodes = modifiedNodes.filter((node) =>
node.name.toLowerCase().includes(search.toLowerCase()),
);
// filter
modifiedNodes = isHide ? modifiedNodes.filter((node) => !node.isComplete) : modifiedNodes;
//* Columns *//
const COLUMNS = [
{
label: 'Task',
renderCell: (item) => item.name,
resize,
sort: { sortKey: 'TASK' },
select: {
renderHeaderCellSelect: () => (
<Checkbox
colorScheme="teal"
isChecked={select.state.all}
isIndeterminate={!select.state.all && !select.state.none}
onChange={select.fns.onToggleAll}
/>
),
renderCellSelect: (item) => (
<Checkbox
colorScheme="teal"
style={{ backgroundColor: '#ffffff' }}
isChecked={select.state.ids.includes(item.id)}
onChange={() => select.fns.onToggleById(item.id)}
/>
),
},
tree: true,
},
{
label: 'Deadline',
renderCell: (item) =>
item.deadline.toLocaleDateString('en-US', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
}),
resize,
sort: { sortKey: 'DEADLINE' },
},
{ label: 'Type', renderCell: (item) => item.type, resize, sort: { sortKey: 'TYPE' } },
{
label: 'Complete',
renderCell: (item) => item.isComplete.toString(),
resize,
sort: { sortKey: 'COMPLETE' },
},
{
label: 'Tasks',
renderCell: (item) => (
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<span>{item.nodes?.length}</span>
<IconButton
aria-label="edit"
icon={<FaPen />}
size="xs"
variant="ghost"
colorScheme="teal"
onClick={() => setDrawerId(item.id)}
/>
</div>
),
resize,
sort: { sortKey: 'TASKS' },
},
];
return (
<>
<Modal isOpen={modalOpened} onClose={() => setModalOpened(false)}>
<ModalOverlay />
<ModalContent>
<ModalHeader>Not all features included here, but we got ...</ModalHeader>
<ModalCloseButton />
<ModalBody>
<div>
<Checkbox colorScheme="teal" isChecked>
Resize
</Checkbox>
</div>
<div>
<Checkbox colorScheme="teal" isChecked>
Sort
</Checkbox>
</div>
<div>
<Checkbox colorScheme="teal" isChecked>
Search
</Checkbox>
</div>
<div>
<Checkbox colorScheme="teal" isChecked>
Filter
</Checkbox>
</div>
<div>
<Checkbox colorScheme="teal" isChecked>
Select
</Checkbox>
</div>
<div>
<Checkbox colorScheme="teal" isChecked>
Tree
</Checkbox>
</div>
<div>
<Checkbox colorScheme="teal" isChecked>
Drawer on Edit
</Checkbox>
</div>
<div>
<Checkbox colorScheme="teal" isChecked>
Pagination
</Checkbox>
</div>
</ModalBody>
</ModalContent>
</Modal>
{/* Form */}
<HStack m={3}>
<Button colorScheme="teal" onClick={() => setModalOpened(true)}>
Features?
</Button>
<InputGroup>
<InputLeftElement
pointerEvents="none"
children={<FaSearch style={{ color: '#4a5568' }} />}
/>
<Input
placeholder="Search Task"
value={search}
onChange={(event) => setSearch(event.target.value)}
/>
</InputGroup>
<Checkbox
style={{ whiteSpace: 'nowrap' }}
colorScheme="teal"
isChecked={isHide}
onChange={(event) => setHide(event.target.checked)}
>
Hide Complete
</Checkbox>
</HStack>
{/* Table */}
<Box p={3} borderWidth="1px" borderRadius="lg">
<CompactTable
columns={COLUMNS}
data={{ ...data, nodes: modifiedNodes }}
theme={theme}
layout={{ custom: true }}
select={select}
tree={tree}
sort={sort}
pagination={pagination}
/>
</Box>
<br />
<HStack justify="flex-end">
<IconButton
aria-label="previous page"
icon={<FaChevronLeft />}
colorScheme="teal"
variant="ghost"
disabled={pagination.state.page === 0}
onClick={() => pagination.fns.onSetPage(pagination.state.page - 1)}
/>
{pagination.state.getPages(modifiedNodes).map((_, index) => (
<Button
key={index}
colorScheme="teal"
variant={pagination.state.page === index ? 'solid' : 'ghost'}
onClick={() => pagination.fns.onSetPage(index)}
>
{index + 1}
</Button>
))}
<IconButton
aria-label="next page"
icon={<FaChevronRight />}
colorScheme="teal"
variant="ghost"
disabled={pagination.state.page + 1 === pagination.state.getTotalPages(data.nodes)}
onClick={() => pagination.fns.onSetPage(pagination.state.page + 1)}
/>
</HStack>
<Drawer isOpen={drawerId} onClose={handleCancel} placement="right">
<DrawerOverlay />
<DrawerContent>
<DrawerCloseButton />
<DrawerHeader>Create your account</DrawerHeader>
<DrawerBody>
<Text>Name: </Text>
<Input
autoFocus
value={
edited || fromTreeToList(data.nodes).find((node) => node.id === drawerId)?.name
}
onChange={handleEdit}
data-autofocus
/>
</DrawerBody>
<DrawerFooter>
<Button variant="outline" mr={3} onClick={handleCancel}>
Cancel
</Button>
<Button onClick={handleSave} colorScheme="teal">
Save
</Button>
</DrawerFooter>
</DrawerContent>
</Drawer>
</>
);
}
Example #8
Source File: column-hide.js From react-table-library with MIT License | 4 votes |
Component = () => {
const data = { nodes };
const chakraTheme = getTheme(DEFAULT_OPTIONS);
const theme = useTheme(chakraTheme);
const [hiddenColumns, setHiddenColumns] = React.useState(['DEADLINE', 'COMPLETE']);
const toggleColumn = (column) => {
if (hiddenColumns.includes(column)) {
setHiddenColumns(hiddenColumns.filter((v) => v !== column));
} else {
setHiddenColumns(hiddenColumns.concat(column));
}
};
const COLUMNS = [
{ label: 'Task', renderCell: (item) => item.name, hide: hiddenColumns.includes('TASK') },
{
label: 'Deadline',
renderCell: (item) =>
item.deadline.toLocaleDateString('en-US', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
}),
hide: hiddenColumns.includes('DEADLINE'),
},
{ label: 'Type', renderCell: (item) => item.type, hide: hiddenColumns.includes('TYPE') },
{
label: 'Complete',
renderCell: (item) => item.isComplete.toString(),
hide: hiddenColumns.includes('COMPLETE'),
},
{
label: 'Tasks',
renderCell: (item) => item.nodes?.length,
hide: hiddenColumns.includes('TASKS'),
},
];
return (
<>
<HStack spacing={10}>
<Checkbox
colorScheme="teal"
isChecked={!hiddenColumns.includes('NAME')}
onChange={() => toggleColumn('NAME')}
>
Name
</Checkbox>
<Checkbox
colorScheme="teal"
isChecked={!hiddenColumns.includes('DEADLINE')}
onChange={() => toggleColumn('DEADLINE')}
>
Deadline
</Checkbox>
<Checkbox
colorScheme="teal"
isChecked={!hiddenColumns.includes('TYPE')}
onChange={() => toggleColumn('TYPE')}
>
Type
</Checkbox>
<Checkbox
colorScheme="teal"
isChecked={!hiddenColumns.includes('COMPLETE')}
onChange={() => toggleColumn('COMPLETE')}
>
Complete
</Checkbox>
<Checkbox
colorScheme="teal"
isChecked={!hiddenColumns.includes('TASKS')}
onChange={() => toggleColumn('TASKS')}
>
Tasks
</Checkbox>
</HStack>
<br />
<Box p={3} borderWidth="1px" borderRadius="lg">
<CompactTable columns={COLUMNS} data={data} theme={theme} layout={{ hiddenColumns }} />
</Box>
<br />
<DocumentationSee anchor={'Features/' + key} />
</>
);
}
Example #9
Source File: VulnerabilitiesTable.js From web-client with Apache License 2.0 | 4 votes |
VulnerabilitiesTable = ({ tableModel, tableModelSetter: setTableModel, reloadCallback, showSelection = true, showProjectColumn = true }) => {
const onSortChange = (ev, column, order) => {
ev.preventDefault();
setTableModel({ ...tableModel, sortBy: { column: column, order: order } })
}
const onSelectionChange = ev => {
const target = ev.target;
const selectionId = parseInt(target.value);
if (target.checked) {
setTableModel({ ...tableModel, selection: [...tableModel.selection, selectionId] })
} else {
setTableModel({ ...tableModel, selection: tableModel.selection.filter(value => value !== selectionId) })
}
};
const onHeaderCheckboxClick = ev => {
if (ev.target.checked) {
setTableModel({ ...tableModel, selection: tableModel.vulnerabilities.map(vulnerability => vulnerability.id) })
} else {
setTableModel({ ...tableModel, selection: [] })
}
}
const numColumns = 6 + (showSelection ? 1 : 0) + (showProjectColumn ? 1 : 0);
const vulnerabilitiesLength = null !== tableModel.vulnerabilities ? tableModel.vulnerabilities.length : 0;
const deleteVulnerability = useDelete('/vulnerabilities/', reloadCallback, 'Do you really want to delete this vulnerability?', 'The vulnerability has been deleted.');
return <Table>
<Thead>
<Tr>
{showSelection && <Th style={{ width: "32px", textAlign: "left" }}><Checkbox onChange={onHeaderCheckboxClick} isChecked={tableModel.selection.length && tableModel.selection.length === vulnerabilitiesLength} isDisabled={tableModel.vulnerabilitiesLength === 0} /></Th>}
<Th style={{ width: '190px' }}>Summary</Th>
{showProjectColumn && <Th style={{ width: '190px' }}>Project</Th>}
<Th style={{ width: '120px' }}><DescendingSortLink callback={onSortChange} property="status" /> Status <AscendingSortLink callback={onSortChange} property="status" /></Th>
<Th style={{ width: '120px' }}><DescendingSortLink callback={onSortChange} property="risk" /> Risk <AscendingSortLink callback={onSortChange} property="risk" /></Th>
<Th style={{ width: '120px' }}><DescendingSortLink callback={onSortChange} property="cvss_score" /> <abbr title="Common Vulnerability Scoring System">CVSS</abbr> score <AscendingSortLink callback={onSortChange} property="cvss_score" /></Th>
<Th className='only-desktop' style={{ width: '20%' }}><DescendingSortLink callback={onSortChange} property="category_name" /> Category <AscendingSortLink callback={onSortChange} property="category_name" /></Th>
<Th style={{ width: '15%', textAlign: 'right' }}><ReloadButton onClick={reloadCallback} /></Th>
</Tr>
</Thead>
<Tbody>
{null === tableModel.vulnerabilities &&
<LoadingTableRow numColumns={numColumns} />}
{null !== tableModel.vulnerabilities && 0 === tableModel.vulnerabilities.length &&
<NoResultsTableRow numColumns={numColumns} />}
{null !== tableModel.vulnerabilities && tableModel.vulnerabilities.length > 0 &&
tableModel.vulnerabilities.map((vulnerability, index) => {
return <Tr key={index}>
{showSelection &&
<Td>
<Checkbox
value={vulnerability.id}
onChange={onSelectionChange}
isChecked={tableModel.selection.includes(vulnerability.id)}
/>
</Td>
}
<Td>
<Stack>
<VulnerabilityBadge vulnerability={vulnerability} />
<div><Tags values={vulnerability.tags} /></div>
</Stack>
</Td>
{showProjectColumn && <Td>{vulnerability.is_template ? <span title="Not applicable">(n/a)</span> : <ProjectBadge project={{ id: vulnerability.project_id, name: vulnerability.project_name }} />}</Td>}
<Td><VulnerabilityStatusBadge vulnerability={vulnerability} /></Td>
<Td><RiskBadge risk={vulnerability.risk} /></Td>
<Td><CvssScore score={vulnerability.cvss_score} /></Td>
<Td className='only-desktop'>
<VulnerabilityCategorySpan name={vulnerability.category_name} parentName={vulnerability.parent_category_name} />
</Td>
<Td textAlign="right">
<RestrictedComponent roles={['administrator', 'superuser', 'user']}>
<LinkButton href={`/vulnerabilities/${vulnerability.id}/edit`}>Edit</LinkButton>
{reloadCallback &&
<DeleteIconButton onClick={() => deleteVulnerability(vulnerability.id)} />
}
</RestrictedComponent>
</Td>
</Tr>
})}
</Tbody>
</Table>
}
Example #10
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 #11
Source File: create.js From idena-web with MIT License | 4 votes |
export default function CreateKey() {
const {t} = useTranslation()
const size = useBreakpointValue(['lg', 'md'])
const variant = useBreakpointValue(['mobile', 'initial'])
const buttonVariant = useBreakpointValue(['primaryFlat', 'secondary'])
const successToast = useSuccessToast()
const router = useRouter()
const [state, setState] = useState({
step: steps.AVATAR,
})
const [error, setError] = useState()
const {onCopy, hasCopied} = useClipboard(state.encryptedPrivateKey)
const setStep = s => setState(prevState => ({...prevState, step: s}))
const generateNewAddress = () => {
const key = generatePrivateKey()
setState(prevState => ({
...prevState,
privateKey: key,
address: privateKeyToAddress(key),
}))
}
const setPassword = () => {
if (state.password !== state.passwordConfirm) {
setError(t("Passwords don't match. Try again."))
} else {
const encryptedKey = encryptPrivateKey(state.privateKey, state.password)
setState(prevState => ({
...prevState,
encryptedPrivateKey: encryptedKey,
step: steps.BACKUP,
}))
setError(null)
}
}
useEffect(() => {
generateNewAddress()
}, [])
return (
<>
{state.step === steps.AVATAR && (
<AuthLayout>
<AuthLayout.Small>
<Flex width="100%" direction="column">
<Flex justifyContent="center">
<div style={{position: 'relative'}}>
<Avatar address={state.address} />
<Box
color={['xblack.016', 'xwhite.500']}
opacity={[1, '0.8']}
position="absolute"
w={8}
h={8}
bottom={['28px', '5px']}
right={['-40px', '5px']}
borderRadius="6px"
background="gray.500"
padding="3px 2px 2px 5px"
cursor="pointer"
onClick={() => generateNewAddress()}
>
<RefreshIcon
color={['xwhite.500', 'inherit']}
boxSize={5}
fill="white"
style={{
opacity: 0.8,
transform: 'scaleX(-1) rotate(90deg)',
}}
></RefreshIcon>
</Box>
</div>
</Flex>
<Flex mt={[5, 0]} justify="center">
<SubHeading color="white">{t('Your address')}</SubHeading>
</Flex>
<Flex
mt="5px"
mb="45px"
fontSize="mdx"
style={{
opacity: 0.5,
textAlign: 'center',
wordBreak: 'break-all',
}}
>
{state.address}
</Flex>
<PrimaryButton
size={size}
onClick={() => setStep(steps.PASSWORD)}
>
{t('Proceed')}
</PrimaryButton>
<Flex justifyContent="center">
<FlatButton onClick={() => router.push('/')} mt={5}>
{t('Cancel')}
</FlatButton>
</Flex>
</Flex>
</AuthLayout.Small>
</AuthLayout>
)}
{state.step === steps.PASSWORD && (
<AuthLayout>
<Box
w="100%"
h={6}
position="absolute"
top="40px"
display={['block', 'none']}
>
<ArrowBackIcon
fill="#fff"
boxSize={6}
ml={4}
onClick={() => setStep(steps.AVATAR)}
></ArrowBackIcon>
</Box>
<AuthLayout.Normal>
<Flex
direction={['column', 'initial']}
align={['center', 'initial']}
width="100%"
>
<Avatar address={state.address} />
<Flex
direction="column"
align={['center', 'initial']}
justify="center"
flex="1"
w={['75%', '100%']}
mt={[5, 0]}
ml={[0, 5]}
>
<Box>
<SubHeading color="white">
{t('Create password to encrypt your account')}
</SubHeading>
</Box>
<Flex justify="space-between">
<Text
wordBreak={['break-all', 'initial']}
color="xwhite.050"
fontSize="mdx"
>
{state.address}
</Text>
</Flex>
</Flex>
</Flex>
<Flex width="100%" mt={6}>
<form
onSubmit={e => {
e.preventDefault()
setPassword()
}}
style={{width: '100%'}}
>
<FormLabel
display={['none', 'inherit']}
htmlFor="key"
style={{color: 'white', fontSize: '13px'}}
>
{t('Password')}
</FormLabel>
<Flex width="100%" mb={[3, 5]} style={{position: 'relative'}}>
<PasswordInput
id="password"
size={size}
value={state.password}
width="100%"
borderColor="xblack.008"
backgroundColor="xblack.016"
onChange={e =>
setState({
...state,
password: e.target.value,
})
}
placeholder={t('Enter password')}
/>
</Flex>
<FormLabel
display={['none', 'inherit']}
htmlFor="key"
style={{
color: 'white',
fontSize: '13px',
}}
>
{t('Confirm password')}
</FormLabel>
<Flex width="100%" style={{position: 'relative'}}>
<PasswordInput
id="passwordConfirm"
size={size}
value={state.passwordConfirm}
width="100%"
borderColor="xblack.008"
backgroundColor="xblack.016"
onChange={e =>
setState({
...state,
passwordConfirm: e.target.value,
})
}
placeholder={t('Enter password again')}
/>
</Flex>
<Flex mt={[4, 8]} justify="space-between">
<FlatButton
display={['none', 'inherit']}
color="white"
_hover={{color: 'xwhite.080'}}
onClick={() => setStep(steps.AVATAR)}
>
<ArrowUpIcon
boxSize={5}
style={{transform: 'rotate(-90deg)', marginTop: -3}}
></ArrowUpIcon>
{t('Back')}
</FlatButton>
<PrimaryButton
size={size}
w={['100%', 'initial']}
type="submit"
>
{t('Next')}
</PrimaryButton>
</Flex>
{error && (
<Flex
mt="30px"
background="rgb(255, 102, 102)"
borderRadius="9px"
fontSize="mdx"
p="18px 24px"
>
{error}
</Flex>
)}
</form>
</Flex>
</AuthLayout.Normal>
</AuthLayout>
)}
{state.step === steps.BACKUP && (
<AuthLayout>
<Box
w="100%"
h={6}
position="absolute"
top="40px"
display={['block', 'none']}
>
<ArrowBackIcon
fill="#fff"
boxSize={6}
ml={4}
onClick={() => setStep(steps.PASSWORD)}
></ArrowBackIcon>
</Box>
<AuthLayout.Normal>
<Flex
direction={['column', 'initial']}
align={['center', 'initial']}
width="100%"
>
<Avatar address={state.address} />
<Flex
direction="column"
justify="center"
flex="1"
mt={[4, 0]}
ml={[0, 5]}
>
<SubHeading color="white">
{t('Backup your private key')}
</SubHeading>
<Flex justify="space-between">
<Text color="xwhite.050" fontSize="mdx">
{t(
'Make a photo of QR code or save your encrypted private key.'
)}
</Text>
</Flex>
</Flex>
</Flex>
<Flex width="100%" mt={6}>
<form
onSubmit={e => {
e.preventDefault()
if (!state.understand1 || !state.understand2) {
setError(t('Please confirm you understand risks'))
} else {
sendSignUp(state.address)
setError('')
setStep(steps.SUCCESS)
}
}}
style={{width: '100%'}}
>
<Flex display={['none', 'flex']} justify="space-between">
<FormLabel style={{color: 'white', fontSize: 'md'}}>
{t('Your encrypted private key')}
</FormLabel>
{hasCopied ? (
<FormLabel style={{color: 'white', fontSize: 'md'}}>
{t('Copied!')}
</FormLabel>
) : (
<FlatButton onClick={onCopy} marginBottom="10px">
{t('Copy')}
</FlatButton>
)}
</Flex>
<Flex width="100%" mb={[0, 5]} style={{position: 'relative'}}>
<Input
size={size}
variant={variant}
value={state.encryptedPrivateKey}
borderColor="xblack.008"
backgroundColor={['gray.500', 'xblack.016']}
width="100%"
pr={[10, 3]}
disabled
/>
<Box
display={['initial', 'none']}
position="absolute"
top={3}
right={3}
>
<CopyIcon
boxSize={6}
fill="#E8EAED"
opacity="0.16"
onClick={() => {
onCopy()
successToast({
title: 'Private key copied!',
duration: '5000',
})
}}
/>
</Box>
</Flex>
<Flex direction="column">
<Checkbox
order={[2, 1]}
mt={[9, 0]}
variant={variant}
textAlign={['left', 'initial']}
value={state.understand1}
isChecked={state.understand1}
onChange={e =>
setState({...state, understand1: e.target.checked})
}
style={{fontWeight: 300}}
>
{t(
'I understand that Idena cannot recover the private key for me.'
)}
</Checkbox>
<Checkbox
order={[3, 2]}
mt={2}
variant={variant}
textAlign={['left', 'initial']}
value={state.understand2}
isChecked={state.understand2}
onChange={e =>
setState({...state, understand2: e.target.checked})
}
style={{fontWeight: 300}}
>
{t(
'I understand the risk of compromising my private key backup.'
)}
</Checkbox>
<Flex order={[1, 3]} mt={[4, 8]} justify="space-between">
<FlatButton
display={['none', 'inherit']}
color="white"
_hover={{color: 'xwhite.080'}}
onClick={() => {
setError('')
setStep(steps.PASSWORD)
}}
>
<ArrowUpIcon
boxSize={5}
style={{transform: 'rotate(-90deg)', marginTop: -3}}
></ArrowUpIcon>
{t('Back')}
</FlatButton>
<Flex
w={['100%', 'initial']}
direction={['column', 'initial']}
>
<Button
order={[2, 1]}
size={size}
variant={buttonVariant}
w={['100%', 'initial']}
type="button"
mt={[4, 0]}
mr={[0, 2.5]}
fontSize={['15px', '13px']}
onClick={() => setState({...state, showQrDialog: true})}
>
{t('Show QR code')}
</Button>
<PrimaryButton
order={[1, 2]}
w={['100%', 'initial']}
size={size}
type="submit"
>
{t('Next')}
</PrimaryButton>
</Flex>
</Flex>
</Flex>
{error && (
<Flex
mt="30px"
p="18px 24px"
background="rgb(255, 102, 102)"
borderRadius="9px"
fontSyze="mdx"
style={{
fontSize: '14px',
}}
>
{error}
</Flex>
)}
</form>
</Flex>
</AuthLayout.Normal>
<Dialog
key="qr"
isOpen={state.showQrDialog}
onClose={() => setState({...state, showQrDialog: false})}
>
<DialogHeader>{t('Encrypted private key')}</DialogHeader>
<DialogBody>
{t('Scan QR by your mobile phone.')}
<Flex justify="center" mx="auto" my={8}>
<QRCode value={state.encryptedPrivateKey} />
</Flex>
</DialogBody>
<DialogFooter>
<SecondaryButton
onClick={() => setState({...state, showQrDialog: false})}
>
{t('Close')}
</SecondaryButton>
<PrimaryButton
onClick={() => {
const blob = new Blob([state.encryptedPrivateKey], {
type: 'text/plain;charset=utf-8',
})
saveAs(blob, 'idena-encrypted-key.txt')
}}
>
{t('Save to file')}
</PrimaryButton>
</DialogFooter>
</Dialog>
</AuthLayout>
)}
{state.step === steps.SUCCESS && (
<AuthLayout>
<AuthLayout.Small>
<Flex width="100%" direction="column">
<Flex justifyContent="center">
<div style={{position: 'relative'}}>
<Avatar address={state.address} />
</div>
</Flex>
<Flex justify="center" marginTop={7.5}>
<SubHeading color="white">
{t('Successfully created!')}
</SubHeading>
</Flex>
<Flex
mt="5px"
mb="45px"
fontSize="mdx"
style={{
opacity: 0.5,
textAlign: 'center',
wordBreak: 'break-all',
}}
>
{state.address}
</Flex>
<PrimaryButton
size={size}
onClick={() => router.push('/key/import')}
>
{t('Sign in')}
</PrimaryButton>
<Flex display={['none', 'flex']} justifyContent="center">
<FlatButton onClick={() => setStep(steps.BACKUP)} mt={5}>
{t('Back')}
</FlatButton>
</Flex>
</Flex>
</AuthLayout.Small>
</AuthLayout>
)}
</>
)
}
Example #12
Source File: VaultItemEdit.js From web-client with Apache License 2.0 | 4 votes |
VaultItemEdit = () => {
const { projectId, vaultItemId } = useParams();
const navigate = useNavigate();
const [item, setVaultItem] = useState(new Vault());
const [password, setPassword] = useState(null);
const onVaultItemFormChange = ev => {
const value = ev.target.type === 'checkbox' ? ev.target.checked : ev.target.value;
setVaultItem({ ...item, [ev.target.name]: value });
}
const onFormSubmit = ev => {
ev.preventDefault();
item.password = password;
secureApiFetch(`/vault/${projectId}/${vaultItemId}`, { method: 'PUT', body: JSON.stringify(item) })
.then(resp => {
if (resp.status === 201) {
setVaultItem(new Vault());
setPassword(null);
actionCompletedToast(`The vault item has been modified.`);
navigate(`/projects/${projectId}`);
} else {
errorToast("The vault item could not be saved. Review the form data or check the application logs.")
}
})
}
const onPasswordProvided = ev => {
ev.preventDefault();
secureApiFetch(`/vault/${projectId}/${vaultItemId}`, { method: 'POST', body: JSON.stringify({ 'password': password }) })
.then(response => response.json())
.then(json => {
if (json['success'] === false) {
errorToast("Seems like a wrong password.");
setPassword(null);
}
else {
var newItem = new Vault();
newItem.name = json['name'];
newItem.note = json['note'];
newItem.value = json['value'];
newItem.type = json['type'];
newItem.reportable = json['reportable'];
setVaultItem(newItem);
actionCompletedToast(`The vault item "${newItem.name}" has been loaded.`);
}
})
.catch(err => {
errorToast(err);
setPassword(null);
})
}
const onPasswordFormChanged = ev => {
setPassword(ev.target.value);
}
return <div>
{item.name !== "" && <>
<form onSubmit={onFormSubmit}>
<h3>Vault item</h3>
<Table>
<Thead>
<Tr>
<Th>Type</Th>
<Th>Name</Th>
<Th>Note</Th>
<Th>Value</Th>
<Th>Reportable</Th>
<Th> </Th>
</Tr>
</Thead>
<Tbody>
<Tr>
<Td>
<Select name="type" onChange={onVaultItemFormChange} value={item.type || ""} isRequired>
<option value="password">Password</option>
<option value="note">Note</option>
<option value="token">Token</option>
<option value="key">Key</option>
</Select>
</Td>
<Td>
<Input type="text" name="name" onChange={onVaultItemFormChange} value={item.name || ""} isRequired />
</Td>
<Td>
<Input type="text" name="note" onChange={onVaultItemFormChange} value={item.note || ""} />
</Td>
<Td>
<Input type="text" name="value" onChange={onVaultItemFormChange} value={item.value || ""} isRequired />
</Td>
<Td>
<Checkbox name="reportable" onChange={onVaultItemFormChange} isChecked={item.reportable} />
</Td>
<Td>
<Button type="submit">Update</Button>
</Td>
</Tr>
</Tbody>
</Table>
</form>
</>}
{item.name === "" && <>
<h3>Please provide password</h3>
<form onSubmit={onPasswordProvided}>
<Input type="password" name="password" onChange={onPasswordFormChanged} value={password || ""} isRequired />
<Button type="submit">Send</Button>
</form>
</>}
</div>
}
Example #13
Source File: Form.js From web-client with Apache License 2.0 | 4 votes |
ProjectForm = ({ isEdit = false, project, projectSetter: setProject, onFormSubmit }) => {
const [clients] = useFetch('/clients');
const [categories] = useFetch('/project/categories');
const handleFormChange = ev => {
const value = ev.target.type === 'checkbox' ? ev.target.checked : ev.target.value;
setProject({ ...project, [ev.target.name]: value });
};
useEffect(() => {
if (clients && clients.length && (project.client_id === null || project.client_id === 0)) {
setProject({ ...project, client_id: clients[0].id });
}
}, [project, clients, setProject]);
if (!project && !clients) return <Loading />
return <form onSubmit={onFormSubmit} className="crud">
<fieldset>
<legend>Basic information</legend>
<label>Is template?
<Checkbox name="is_template" onChange={handleFormChange} isChecked={project.is_template} />
</label>
<label>
Category
<Select name="category_id" value={project.category_id || ""} onChange={handleFormChange} required>
{categories && <>
<option value="">(undefined)</option>
{categories.map(category => <option key={`category_${category.id}`} value={category.id}>{category.name}</option>)}
</>}
</Select>
</label>
{!project.is_template && <>
<label>Visibility
<Select name="visibility" onChange={handleFormChange} value={project.visibility}>
<option value="public">Public</option>
<option value="private">Private</option>
</Select>
</label>
<label>Client
<Select name="client_id" onChange={handleFormChange} value={project.client_id || ""}>
{clients && clients.map((client, index) =>
<option key={index} value={client.id}>{client.name}</option>
)}
</Select>
</label>
<label>External ID
<Input type="text" name="external_id" onChange={handleFormChange} value={project.external_id || ""} />
</label>
</>}
<label>Name
<Input type="text" name="name" onChange={handleFormChange} value={project.name || ""} required autoFocus />
</label>
<label>Description
<MarkdownEditor name="description" onChange={handleFormChange} value={project.description || ""} required />
</label>
</fieldset>
<fieldset>
<legend>Rules of engagement</legend>
<label>
Vulnerability metrics
<Select name="vulnerability_metrics" value={project.vulnerability_metrics || ""} onChange={handleFormChange}>
<option value="">(undefined)</option>
{ProjectVulnerabilityMetrics.map(type => <option key={`metrics_${type.id}`} value={type.id}>{type.name}</option>)}
</Select>
</label>
{!project.is_template && <>
<label>Start date
<Input type="date" name="engagement_start_date" value={project.engagement_start_date}
onChange={handleFormChange} />
</label>
<label>End date
<Input type="date" name="engagement_end_date" value={project.engagement_end_date}
onChange={handleFormChange} />
</label>
</>}
</fieldset>
<fieldset>
<legend>Vulnerabilities summary</legend>
<label>Management summary
<MarkdownEditor name="management_summary" onChange={handleFormChange} value={project.management_summary || ""} required />
</label>
<label>Conclusion
<MarkdownEditor name="management_conclusion" onChange={handleFormChange} value={project.management_conclusion || ""} required />
</label>
</fieldset>
<PrimaryButton type="submit">{isEdit ? "Update" : "Create"}</PrimaryButton>
</form>
}
Example #14
Source File: components.js From idena-web with MIT License | 4 votes |
export function MyIdenaBotAlert({onConnect, onSkip}) {
const {t} = useTranslation()
const [{state}] = useIdentity()
const myIdenaBotDisclosure = useDisclosure()
const [doNotShowAgain, setDoNotShowAgain] = React.useState()
const connectButtonRef = React.useRef()
// eslint-disable-next-line no-shadow
const eitherState = (...states) => states.some(s => s === state)
const size = useBreakpointValue(['sm', 'md'])
const isDesktop = useIsDesktop()
return (
<>
<Alert
variant="solid"
justifyContent="center"
flexShrink={0}
boxShadow="0 3px 12px 0 rgb(255 163 102 /0.1), 0 2px 3px 0 rgb(255 163 102 /0.2)"
color="white"
cursor="pointer"
fontWeight={500}
rounded="md"
mt={2}
mx={2}
w="auto"
onClick={myIdenaBotDisclosure.onOpen}
>
<Flex flexGrow={1} justifyContent="center" position="relative">
<Box mr={[5, 0]}>
<TelegramIcon boxSize={6} mr={1} display={['none', 'initial']} />
{t(`Subscribe to @MyIdenaBot to get personalized notifications based on
your status`)}
</Box>
{isDesktop ? (
<FlatButton
p={2}
position="absolute"
right={0}
top={0}
height="100%"
color="white"
onClick={e => {
e.stopPropagation()
onSkip()
}}
_hover={{color: 'white'}}
>
{t('Close')}
</FlatButton>
) : (
<CloseButton
position="absolute"
right={-3}
top={-2}
onClick={e => {
e.stopPropagation()
onSkip()
}}
/>
)}
</Flex>
</Alert>
<Dialog
title="Subscribe to @MyIdenaBot"
size={size}
initialFocusRef={connectButtonRef}
{...myIdenaBotDisclosure}
>
<DialogBody>
<Stack>
<Text>
{t(
`MyIdenaBot reminds you about important actions based on your
identity status:`,
{nsSeparator: '!!'}
)}
</Text>
{eitherState(IdentityStatus.Undefined) && (
<IdenaBotFeatureList
features={[
'next validation reminder',
'notification when you get an invite',
'reminder to activate your invite',
'your validation results when validation consensus is reached',
]}
/>
)}
{eitherState(IdentityStatus.Invite, IdentityStatus.Candidate) && (
<IdenaBotFeatureList
features={[
'next validation reminder',
'your validation results when validation consensus is reached',
]}
/>
)}
{eitherState(IdentityStatus.Newbie) && (
<IdenaBotFeatureList
features={[
'next validation reminder',
'reminder to create flips if you haven’t done it yet and the validation is coming',
'your validation results when validation consensus is reached',
]}
/>
)}
{eitherState(IdentityStatus.Verified, IdentityStatus.Human) && (
<IdenaBotFeatureList
features={[
'next validation reminder',
'reminder to create flips',
'your validation results when validation consensus is reached',
'reminder to share your remaining invites',
'reminder to submit extra flips to get more rewards',
'status update of all your invitees to check if they are ready for the validation (activated invites, submitted flips)',
]}
/>
)}
{eitherState(IdentityStatus.Zombie, IdentityStatus.Suspended) && (
<IdenaBotFeatureList
features={[
'next validation reminder',
'your validation results when validation consensus is reached',
'reminder to share your remaining invites',
'reminder to submit extra flips to get more rewards',
'status update of all your invitees to check if they are ready for the validation (activated invites, submitted flips)',
]}
/>
)}
</Stack>
</DialogBody>
<DialogFooter align="center">
<Checkbox
borderColor="gray.100"
isChecked={doNotShowAgain}
onChange={e => {
setDoNotShowAgain(e.target.checked)
}}
>
{t('Do not show again')}
</Checkbox>
<SecondaryButton
onClick={() => {
myIdenaBotDisclosure.onClose()
if (doNotShowAgain) onConnect()
}}
>
{t('Not now')}
</SecondaryButton>
<PrimaryButton
ref={connectButtonRef}
onClick={() => {
openExternalUrl('https://t.me/MyIdenaBot')
onConnect()
}}
>
{t('Connect')}
</PrimaryButton>
</DialogFooter>
</Dialog>
</>
)
}
Example #15
Source File: new.js From idena-web with MIT License | 4 votes |
function NewVotingPage() {
const {t, i18n} = useTranslation()
const router = useRouter()
const toast = useToast()
const {isOpen: isOpenAdvanced, onToggle: onToggleAdvanced} = useDisclosure()
const epochData = useEpoch()
const {coinbase, privateKey} = useAuthState()
const {
data: {balance},
} = useBalance()
const [current, send, service] = useMachine(newVotingMachine, {
actions: {
onDone: () => {
router.push(viewVotingHref(current.context.contractHash))
},
onError: (context, {data: {message}}) => {
toast({
// eslint-disable-next-line react/display-name
render: () => (
<Toast title={humanError(message, context)} status="error" />
),
})
},
onInvalidForm: () => {
toast({
// eslint-disable-next-line react/display-name
render: () => (
<Toast title={t('Please correct form fields')} status="error" />
),
})
},
},
})
React.useEffect(() => {
if (epochData && coinbase) send('START', {epoch: epochData.epoch, coinbase})
}, [coinbase, epochData, privateKey, send])
const {
options,
startDate,
votingDuration,
publicVotingDuration,
shouldStartImmediately,
isFreeVoting,
committeeSize,
quorum = 1,
winnerThreshold = '66',
feePerGas,
oracleReward,
isWholeNetwork,
oracleRewardsEstimates,
ownerFee = 0,
minOracleReward,
votingMinPayment,
dirtyBag,
} = current.context
const isInvalid = (field, cond = current.context[field]) =>
dirtyBag[field] && !cond
const isInvalidOptions = isInvalid('options', hasValuableOptions(options))
const hasLinksInOptions = isInvalid('options', hasLinklessOptions(options))
const handleChange = ({target: {id, value}}) => send('CHANGE', {id, value})
const dna = toLocaleDna(i18n)
return (
<Layout showHamburger={false}>
<Page px={0} py={0}>
<Box px={20} py={6} w="full" overflowY="auto">
<Flex justify="space-between" align="center">
<PageTitle mb={0}>{t('New voting')}</PageTitle>
<CloseButton
ml="auto"
onClick={() => router.push('/oracles/list')}
/>
</Flex>
<SuccessAlert my={8}>
{t(
'After publishing or launching, you will not be able to edit the voting parameters.'
)}
</SuccessAlert>
{current.matches('preload.late') && <NewVotingFormSkeleton />}
{!current.matches('preload') && (
<Stack spacing={3}>
<VotingInlineFormControl
htmlFor="title"
label={t('Title')}
isInvalid={isInvalid('title')}
>
<Input id="title" onChange={handleChange} />
{isInvalid('title') && (
<FormErrorMessage fontSize="md" mt={1}>
{t('You must provide title')}
</FormErrorMessage>
)}
</VotingInlineFormControl>
<VotingInlineFormControl
htmlFor="desc"
label={t('Description')}
isInvalid={isInvalid('desc')}
>
<Textarea id="desc" w="md" h={32} onChange={handleChange} />
{isInvalid('desc') && (
<FormErrorMessage fontSize="md" mt={1}>
{t('You must provide description')}
</FormErrorMessage>
)}
</VotingInlineFormControl>
<VotingInlineFormControl
label={t('Voting options')}
isInvalid={isInvalidOptions || hasLinksInOptions}
>
<Box
borderWidth={
isInvalidOptions || hasLinksInOptions ? '2px' : 1
}
borderColor={
isInvalidOptions || hasLinksInOptions
? 'red.500'
: 'gray.100'
}
borderRadius="md"
p={1}
w="md"
>
{options.map(({id, value}, idx) => (
<VotingOptionInput
key={id}
value={value}
placeholder={`${t('Option')} ${idx + 1}...`}
isLast={idx === options.length - 1}
isDisabled={[0, 1].includes(idx)}
onChange={({target}) => {
send('SET_OPTIONS', {id, value: target.value})
}}
onAddOption={() => {
send('ADD_OPTION')
}}
onRemoveOption={() => {
send('REMOVE_OPTION', {id})
}}
_invalid={null}
/>
))}
</Box>
{isInvalidOptions && (
<FormErrorMessage fontSize="md" mt={1}>
{t('You must provide at least 2 options')}
</FormErrorMessage>
)}
{hasLinksInOptions && (
<FormErrorMessage fontSize="md" mt={1}>
{t(
'Links are not allowed in voting options. Please use Description for links.'
)}
</FormErrorMessage>
)}
</VotingInlineFormControl>
<VotingInlineFormControl
htmlFor="startDate"
label={t('Start date')}
isDisabled={shouldStartImmediately}
isInvalid={isInvalid(
'startDate',
startDate || shouldStartImmediately
)}
mt={4}
>
<Stack spacing={3} flex={1}>
<Input
id="startDate"
type="datetime-local"
onChange={handleChange}
/>
{isInvalid(
'startDate',
startDate || shouldStartImmediately
) && (
<FormErrorMessage fontSize="md" mt={-2}>
{t('You must either choose start date or start now')}
</FormErrorMessage>
)}
<Checkbox
id="shouldStartImmediately"
isChecked={shouldStartImmediately}
onChange={({target: {id, checked}}) => {
send('CHANGE', {id, value: checked})
}}
>
{t('Start now')}
</Checkbox>
</Stack>
</VotingInlineFormControl>
<VotingDurationInput
id="votingDuration"
label={t('Voting duration')}
value={votingDuration}
tooltip={t('Secret voting period')}
presets={[
durationPreset({hours: 12}),
durationPreset({days: 1}),
durationPreset({days: 2}),
durationPreset({days: 5}),
durationPreset({weeks: 1}),
]}
service={service}
mt={2}
/>
<NewVotingFormSubtitle>
{t('Oracles requirements')}
</NewVotingFormSubtitle>
<VotingInlineFormControl
htmlFor="committeeSize"
label={t('Committee size, oracles')}
isInvalid={committeeSize < 1}
tooltip={t(
'The number of randomly selected oracles allowed to vote'
)}
mt={2}
>
<Stack spacing={3} flex={1}>
<NumberInput
id="committeeSize"
value={committeeSize}
min={1}
step={1}
preventInvalidInput
isDisabled={isWholeNetwork}
onChange={({target: {id, value}}) => {
send('CHANGE_COMMITTEE', {id, value})
}}
/>
<Checkbox
id="isWholeNetwork"
onChange={({target: {checked}}) => {
send('SET_WHOLE_NETWORK', {checked})
}}
>
{t('Whole network')}
</Checkbox>
</Stack>
</VotingInlineFormControl>
<VotingInlineFormControl
htmlFor="quorum"
label={t('Quorum')}
tooltip={t(
'The share of Oracle committee sufficient to determine the voting outcome'
)}
mt={2}
>
<Stack spacing={0} flex={1}>
<PercentInput
id="quorum"
value={quorum}
onChange={handleChange}
/>
<NewOracleFormHelperText textAlign="right">
{t('{{count}} votes are required', {
count: quorumVotesCount({quorum, committeeSize}),
})}
</NewOracleFormHelperText>
</Stack>
</VotingInlineFormControl>
<VotingInlineFormControl
htmlFor="votingMinPayment"
label={t('Voting deposit')}
tooltip={t(
'Refunded when voting in majority and lost when voting in minority'
)}
isDisabled={isFreeVoting}
mt={2}
>
<Stack spacing={3} flex={1}>
<DnaInput
id="votingMinPayment"
value={votingMinPayment}
isDisabled={isFreeVoting}
onChange={handleChange}
/>
<Checkbox
id="isFreeVoting"
isChecked={isFreeVoting}
onChange={({target: {id, checked}}) => {
send('CHANGE', {id, value: checked})
}}
>
{t('No voting deposit for oracles')}
</Checkbox>
</Stack>
</VotingInlineFormControl>
<NewVotingFormSubtitle>
{t('Cost of voting')}
</NewVotingFormSubtitle>
<PresetFormControl
label={t('Total funds')}
tooltip={t(
'Total funds locked during the voting and paid to oracles and owner afterwards'
)}
>
<PresetFormControlOptionList
value={String(oracleReward)}
onChange={value => {
send('CHANGE', {
id: 'oracleReward',
value,
})
}}
>
{oracleRewardsEstimates.map(({label, value}) => (
<PresetFormControlOption key={value} value={String(value)}>
{label}
</PresetFormControlOption>
))}
</PresetFormControlOptionList>
<PresetFormControlInputBox>
<DnaInput
id="oracleReward"
value={oracleReward * committeeSize || 0}
min={minOracleReward * committeeSize || 0}
onChange={({target: {id, value}}) => {
send('CHANGE', {
id,
value: (value || 0) / Math.max(1, committeeSize),
})
}}
/>
<NewOracleFormHelperText textAlign="right">
{t('Min reward per oracle: {{amount}}', {
amount: dna(
rewardPerOracle({fundPerOracle: oracleReward, ownerFee})
),
nsSeparator: '!',
})}
</NewOracleFormHelperText>
</PresetFormControlInputBox>
</PresetFormControl>
<VotingInlineFormControl
htmlFor="ownerFee"
label={t('Owner fee')}
tooltip={t('% of the Total funds you receive')}
>
<PercentInput
id="ownerFee"
value={ownerFee}
onChange={handleChange}
/>
<NewOracleFormHelperText textAlign="right">
{t('Paid to owner: {{amount}}', {
amount: dna(
(oracleReward * committeeSize * Math.min(100, ownerFee)) /
100 || 0
),
nsSeparator: '!',
})}
</NewOracleFormHelperText>
</VotingInlineFormControl>
<NewVotingFormSubtitle
cursor="pointer"
onClick={onToggleAdvanced}
>
{t('Advanced settings')}
<ChevronDownIcon
boxSize={5}
color="muted"
ml={1}
transform={isOpenAdvanced ? 'rotate(180deg)' : ''}
transition="all 0.2s ease-in-out"
/>
</NewVotingFormSubtitle>
<Collapse in={isOpenAdvanced} mt={2}>
<Stack spacing={3}>
<VotingDurationInput
id="publicVotingDuration"
value={publicVotingDuration}
label={t('Counting duration')}
tooltip={t(
'Period when secret votes are getting published and results are counted'
)}
presets={[
durationPreset({hours: 12}),
durationPreset({days: 1}),
durationPreset({days: 2}),
durationPreset({days: 5}),
durationPreset({weeks: 1}),
]}
service={service}
/>
<PresetFormControl
label={t('Majority threshold')}
tooltip={t(
'The minimum share of the votes which an option requires to achieve before it becomes the voting outcome'
)}
>
<PresetFormControlOptionList
value={winnerThreshold}
onChange={value => {
send('CHANGE', {
id: 'winnerThreshold',
value,
})
}}
>
<PresetFormControlOption value="51">
{t('Simple majority')}
</PresetFormControlOption>
<PresetFormControlOption value="66">
{t('Super majority')}
</PresetFormControlOption>
<PresetFormControlOption value="100">
{t('N/A (polls)')}
</PresetFormControlOption>
</PresetFormControlOptionList>
<PresetFormControlInputBox>
<PercentInput
id="winnerThreshold"
value={winnerThreshold}
onChange={handleChange}
/>
</PresetFormControlInputBox>
</PresetFormControl>
</Stack>
</Collapse>
</Stack>
)}
</Box>
<Stack
isInline
mt="auto"
alignSelf="stretch"
justify="flex-end"
borderTop="1px"
borderTopColor="gray.100"
py={3}
px={4}
>
<PrimaryButton
isLoading={current.matches('publishing')}
loadingText={t('Publishing')}
onClick={() => send('PUBLISH')}
>
{t('Publish')}
</PrimaryButton>
</Stack>
<ReviewVotingDrawer
isOpen={current.matches('publishing')}
onClose={() => send('CANCEL')}
from={coinbase}
available={balance}
balance={votingMinBalance(oracleReward, committeeSize)}
minStake={votingMinStake(feePerGas)}
votingDuration={votingDuration}
publicVotingDuration={publicVotingDuration}
ownerFee={ownerFee}
isLoading={eitherState(
current,
'publishing.deploy',
`publishing.${VotingStatus.Starting}`
)}
// eslint-disable-next-line no-shadow
onConfirm={({balance, stake}) =>
send('CONFIRM', {privateKey, balance, stake})
}
/>
<NewOraclePresetDialog
isOpen={eitherState(current, 'choosingPreset')}
onChoosePreset={preset => send('CHOOSE_PRESET', {preset})}
onCancel={() => send('CANCEL')}
/>
</Page>
</Layout>
)
}
Example #16
Source File: restricted.js From idena-web with MIT License | 4 votes |
export default function Restricted() {
const [{apiKeyState, apiKeyData, apiKey}] = useSettings()
const {saveConnection} = useSettingsDispatch()
const {coinbase, privateKey} = useAuthState()
const [{state: identityState}] = useIdentity()
const auth = useAuthState()
const router = useRouter()
const {t} = useTranslation()
const [, {updateRestrictedNotNow}] = useAppContext()
const [step, setStep] = useState(steps.INITIAL)
const [state, setState] = useState(options.PROLONG)
const [dontShow, setDontShow] = useState(false)
const buySharedNodeDisclosure = useDisclosure()
const [submitting, setSubmitting] = useState(false)
const failToast = useFailToast()
const {isPurchasing, savePurchase} = useApikeyPurchasing()
const [savedApiKey, setSavedApiKey] = useState()
const size = useBreakpointValue(['lg', 'md'])
const variantRadio = useBreakpointValue(['mobileDark', 'dark'])
const variantSecondary = useBreakpointValue(['primaryFlat', 'secondary'])
const notNow = persist => {
if (persist) {
updateRestrictedNotNow(dontShow)
}
router.back()
}
const getKeyForCandidate = async () => {
setSubmitting(true)
try {
const providers = await getAvailableProviders()
const signature = signMessage(hexToUint8Array(coinbase), privateKey)
const result = await getCandidateKey(
coinbase,
toHexString(signature, true),
providers
)
savePurchase(result.id, result.provider)
} catch (e) {
failToast(
`Failed to get API key for Candidate: ${
e.response ? e.response.data : 'unknown error'
}`
)
} finally {
setSubmitting(false)
}
}
const process = async () => {
if (state === options.PROLONG) {
buySharedNodeDisclosure.onOpen()
} else if (state === options.ENTER_KEY) {
return router.push('/settings/node')
} else if (state === options.CANDIDATE) {
return getKeyForCandidate()
} else if (state === options.RESTORE) {
return saveConnection(savedApiKey.url, savedApiKey.key, false)
} else return router.push('/node/rent')
}
const {data: provider, isError} = useQuery(
['get-provider-by-id', apiKeyData && apiKeyData.provider],
() => getProvider(apiKeyData && apiKeyData.provider),
{
enabled: !!apiKeyData && !!apiKeyData.provider,
retry: false,
refetchOnWindowFocus: false,
}
)
useEffect(() => {
async function checkSaved() {
try {
const signature = signMessage(hexToUint8Array(coinbase), privateKey)
const savedKey = await checkSavedKey(
coinbase,
toHexString(signature, true)
)
setSavedApiKey(savedKey)
// eslint-disable-next-line no-empty
} catch (e) {}
}
checkSaved()
}, [apiKey, coinbase, privateKey])
useEffect(() => {
if (
apiKeyState === ApiKeyStates.ONLINE ||
apiKeyState === ApiKeyStates.EXTERNAL
)
router.push('/home')
}, [apiKeyState, router])
useEffect(() => {
if (identityState === IdentityStatus.Candidate) {
setState(options.CANDIDATE)
} else if (savedApiKey) {
setState(options.RESTORE)
} else if ((provider && !provider.slots) || isError) {
setState(options.BUY)
}
}, [identityState, isError, provider, savedApiKey])
const waiting = submitting || isPurchasing
const canProlong = provider && provider.slots && !waiting
return (
<Layout canRedirect={false}>
<Flex
bg={['gray.500', 'graphite.500']}
alignItems="center"
justifyContent="center"
height="100%"
direction="column"
justify="center"
flex="1"
>
<Flex
flexGrow={1}
align="center"
justify={['flex-start', 'center']}
mt="44px"
mx={[3, 0]}
direction="column"
>
<Flex
direction="column"
align={['center', 'initial']}
maxWidth={['100%', '480px']}
>
<Flex
direction={['column', 'row']}
align="center"
textAlign={['center', 'initial']}
w={['60%', 'auto']}
>
<Avatar address={coinbase} />
<Flex
direction="column"
justify="center"
flex="1"
ml={[0, 5]}
mt={[5, 0]}
>
<SubHeading
fontSize={['mdx', 'lg']}
fontWeight={[400, 500]}
color={['muted', 'white']}
wordBreak="break-word"
>
{auth.coinbase}
</SubHeading>
</Flex>
</Flex>
<Flex
direction="column"
mt={6}
bg="gray.500"
borderRadius="lg"
px={[6, 10]}
py={7}
w={['100%', 'auto']}
>
{step === steps.INITIAL && (
<Flex direction="column" alignItems="center" mt={6}>
<Flex>
<Text color="white" fontSize="lg">
{t('Restricted access')}
</Text>
</Flex>
<Flex mt={4}>
<Text fontSize="mdx" color="muted" textAlign="center">
{t(
'You can use all functions of the app except validation. Please connect to a shared node if you want to participate in the upcoming validation using the web app. '
)}
</Text>
</Flex>
<Flex justifyContent="center" mt={4}>
<PrimaryButton onClick={() => setStep(steps.CONNECT)}>
{t('Connect')}
</PrimaryButton>
</Flex>
<Flex
mt={10}
justifyContent="space-between"
alignSelf="normal"
>
<Flex>
<Checkbox
textAlign={['left', 'initial']}
value={dontShow}
isChecked={dontShow}
onChange={e => setDontShow(e.target.checked)}
color="white"
>
{t('Don’t show again')}
</Checkbox>
</Flex>
<Flex>
<SecondaryButton onClick={() => notNow(true)}>
{t('Not now')}
</SecondaryButton>
</Flex>
</Flex>
</Flex>
)}
{step === steps.CONNECT && (
<>
<Flex justify={['center', ' flex-start']}>
<Text color="white" fontSize="lg">
{t('Connect to a shared node')}
</Text>
</Flex>
<Flex mt={7}>
<Text color="muted" fontSize="sm">
{t('Choose an option')}
</Text>
</Flex>
<Flex mt={[2, 4]}>
<RadioGroup w={['100%', 'auto']}>
<Stack direction="column" spacing={[1, 3]}>
{savedApiKey && savedApiKey.url !== apiKey.url && (
<ChooseItemRadio
variant={variantRadio}
px={[4, 0]}
isChecked={state === options.RESTORE}
onChange={() => setState(options.RESTORE)}
alignItems={['center', 'flex-start']}
>
<Flex direction="column" mt={['auto', '-2px']}>
<Text color="white">
{t('Restore connection')}
</Text>
<Text color="muted" fontSize="sm">
{savedApiKey.url}
</Text>
</Flex>
</ChooseItemRadio>
)}
{identityState === IdentityStatus.Candidate && (
<ChooseItemRadio
variant={variantRadio}
px={[4, 0]}
isChecked={state === options.CANDIDATE}
onChange={() => setState(options.CANDIDATE)}
>
<Text color="white">{t('Get free access')}</Text>
</ChooseItemRadio>
)}
{canProlong && (
<ChooseItemRadio
variant={variantRadio}
px={[4, 0]}
isChecked={state === options.PROLONG}
onChange={() => setState(options.PROLONG)}
alignItems={['center', 'flex-start']}
>
<Flex direction="column" mt={['auto', '-2px']}>
<Text color="white">
{t('Prolong node access')}{' '}
{`(${GetProviderPrice(
provider.data,
identityState
)} iDNA)`}
</Text>
<Text color="muted" fontSize="sm">
{provider.data.url}
</Text>
</Flex>
</ChooseItemRadio>
)}
<ChooseItemRadio
variant={variantRadio}
px={[4, 0]}
isChecked={state === options.BUY}
onChange={() => setState(options.BUY)}
>
<Text color="white">
{canProlong
? t('Rent another shared node')
: t('Rent a shared node')}
</Text>
</ChooseItemRadio>
<ChooseItemRadio
variant={variantRadio}
px={[4, 0]}
isChecked={state === options.ENTER_KEY}
onChange={() => setState(options.ENTER_KEY)}
>
<Text color="white">
{t('Enter shared node API key')}
</Text>
</ChooseItemRadio>
</Stack>
</RadioGroup>
</Flex>
<Flex mt={[4, 10]} justifyContent="space-between">
<Flex
direction={['column', 'row']}
ml="auto"
w={['100%', 'auto']}
>
<Button
variant={variantSecondary}
order={[2, 1]}
size={size}
w={['100%', 'auto']}
onClick={() => notNow(false)}
mr={[0, 2]}
mt={[2, 0]}
>
{t('Not now')}
</Button>
<PrimaryButton
order={[1, 2]}
size={size}
w={['100%', 'auto']}
onClick={process}
isDisabled={waiting}
isLoading={waiting}
loadingText="Waiting..."
>
{t('Continue')}
</PrimaryButton>
</Flex>
</Flex>
</>
)}
</Flex>
</Flex>
</Flex>
<Flex
justify="center"
mb={8}
direction="column"
justifyContent="center"
>
<Text color="white" fontSize="mdx" opacity="0.5" mb={1}>
{t('You can run your own node at your desktop computer.')}
</Text>
<TextLink
href="https://idena.io/download"
target="_blank"
color="white"
textAlign="center"
>
<DownloadIcon boxSize={4} mx={2} />
{t('Download Idena')}
</TextLink>
</Flex>
</Flex>
{provider && (
<BuySharedNodeForm
{...buySharedNodeDisclosure}
providerId={provider.id}
url={provider.data.url}
from={coinbase}
amount={GetProviderPrice(provider.data, identityState)}
to={provider.data.address}
/>
)}
</Layout>
)
}
Example #17
Source File: import.js From idena-web with MIT License | 4 votes |
export default function ImportKey() {
const size = useBreakpointValue(['lg', 'md'])
const logoSize = useBreakpointValue(['88px', '80px'])
const variant = useBreakpointValue(['mobile', 'initial'])
const {t} = useTranslation()
const [state, setState] = useState({
key: '',
password: '',
saveKey: true,
})
const {apiKey} = useSettingsState()
const {setNewKey, decryptKey} = useAuthDispatch()
const [error, setError] = useState()
const [isScanningQr, setIsScanningQr] = useState(false)
const router = useRouter()
const {setRestrictedKey} = useApikeyPurchasing()
const [, {resetRestrictedModal}] = useAppContext()
const addKey = () => {
const key = decryptKey(state.key, state.password)
if (key) {
setError(null)
setNewKey(state.key, state.password, state.saveKey)
if (!apiKey) {
setRestrictedKey()
}
sendSignIn(privateKeyToAddress(key))
router.push('/home')
resetRestrictedModal()
} else {
setError(t('Key or password is invalid. Try again.'))
}
}
return (
<AuthLayout>
<AuthLayout.Normal>
<Flex
direction={['column', 'initial']}
align={['center', 'initial']}
width="100%"
>
<img
src="/static/idena-logo-circle.svg"
alt="logo"
width={logoSize}
height={logoSize}
/>
<Flex
direction="column"
justify="center"
flex="1"
w={['85%', '100%']}
m={['48px 0 0 0', '0 0 0 20px']}
>
<SubHeading color="white">
{t('Import your private key backup to sign in')}
</SubHeading>
<Flex justify="space-between">
<Text color="xwhite.050" fontSize="mdx">
{t(
'Enter your private key backup. You can export your private key from Idena app (see Settings page).'
)}
</Text>
</Flex>
</Flex>
</Flex>
<Flex w="100%" mt="24px">
<form
onSubmit={async e => {
e.preventDefault()
addKey()
}}
style={{width: '100%'}}
>
<FormLabel
display={['none', 'inherit']}
htmlFor="key"
style={{color: 'white', fontSize: 'md'}}
>
{t('Encrypted private key')}
</FormLabel>
<Flex w="100%" mb={[3, 5]} style={{position: 'relative'}}>
<Input
id="key"
opacity={[0.8, 1]}
size={size}
value={state.key}
borderColor="xblack.008"
backgroundColor="xblack.016"
onChange={e => setState({...state, key: e.target.value})}
placeholder={t('Enter your private key backup')}
/>
<Box
display={['initial', 'none']}
style={{
cursor: 'pointer',
position: 'absolute',
top: '10px',
right: '6px',
zIndex: 5,
}}
onClick={() => {}}
>
<QrScanIcon
boxSize="28px"
onClick={() => {
setIsScanningQr(true)
}}
></QrScanIcon>
</Box>
</Flex>
<FormLabel
display={['none', 'inherit']}
htmlFor="key"
style={{
color: 'white',
fontSize: 'md',
}}
>
{t('Password')}
</FormLabel>
<Flex width="100%">
<PasswordInput
size={size}
value={state.password}
width="100%"
borderColor="xblack.008"
backgroundColor="xblack.016"
onChange={e =>
setState({
...state,
password: e.target.value,
})
}
placeholder={t('Enter your password')}
/>
</Flex>
<Flex
mt={[4, 8]}
direction={['column', 'initial']}
justify="space-between"
>
<Checkbox
pt={[7, 0]}
order={[2, 1]}
variant={variant}
value={state.saveKey}
isChecked={state.saveKey}
onChange={e => setState({...state, saveKey: e.target.checked})}
style={{fontWeight: 300}}
>
{t('Save the encrypted key on this device')}
</Checkbox>
<Flex order={[1, 2]}>
<SecondaryButton
isFullWidth={[true, false]}
display={['none', 'initial']}
variant="secondary"
css={{marginRight: '10px'}}
onClick={() => router.push('/')}
>
{t('Cancel')}
</SecondaryButton>
<PrimaryButton
size={size}
isFullWidth={[true, false]}
type="submit"
disabled={!state.key}
>
{t('Import')}
</PrimaryButton>
</Flex>
</Flex>
{error && (
<Flex
mt="30px"
fontSize="mdx"
style={{
backgroundColor: theme.colors.danger,
borderRadius: '9px',
padding: `18px 24px`,
}}
>
{error}
</Flex>
)}
</form>
</Flex>
</AuthLayout.Normal>
{isScanningQr && (
<QrScanner
isOpen={isScanningQr}
onScan={key => {
if (key) {
setState({key})
setIsScanningQr(false)
}
}}
onClose={() => setIsScanningQr(false)}
/>
)}
</AuthLayout>
)
}