@chakra-ui/react#Table JavaScript Examples
The following examples show how to use
@chakra-ui/react#Table.
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: Table.js From web-client with Apache License 2.0 | 6 votes |
CommandsTable = ({ commands, onDeleteCallback = null }) => {
return <Table>
<Thead>
<Tr>
<Th style={{ width: '190px' }}>Name</Th>
<Th className='only-desktop'>Description</Th>
<Th>Execution environment</Th>
<Th>Output parser</Th>
<Th> </Th>
</Tr>
</Thead>
<Tbody>
{null === commands && <LoadingTableRow numColumns={5} />}
{null !== commands && 0 === commands.length && <NoResultsTableRow numColumns={5} />}
{null !== commands && 0 !== commands.length && commands.map(command =>
<Tr key={command.id}>
<Td><CommandBadge command={command} /></Td>
<Td className="only-desktop">
{command.description}<br />
<Tags values={command.tags} />
</Td>
<Td>{command.executable_type === 'custom' ? 'Host' : 'Container'}</Td>
<Td>{command.output_parser ?? '-'}</Td>
<Td textAlign="right">
<LinkButton href={`/commands/${command.id}/edit`}>Edit</LinkButton>
{onDeleteCallback && <DeleteIconButton onClick={() => onDeleteCallback(command.id)} />}
</Td>
</Tr>
)}
</Tbody>
</Table>
}
Example #2
Source File: Integrations.js From web-client with Apache License 2.0 | 6 votes |
SystemIntegrationsPage = () => {
const [integrations] = useFetch('/system/integrations')
return <div>
<PageTitle value="Integrations" />
<div className='heading'>
<Breadcrumb>
<div>System</div>
</Breadcrumb>
</div>
<Title title="Integrations" icon={<IconExtensions />} />
<Table>
<Thead>
<Tr>
<Th>Name</Th>
<Th>Description</Th>
<Th>External URL</Th>
<Th>Configured?</Th>
<Th> </Th>
</Tr>
</Thead>
<Tbody>
{null === integrations && <LoadingTableRow numColumns={5} />}
{null !== integrations && 0 === integrations.length && <NoResultsTableRow numColumns={5} />}
{null !== integrations && 0 !== integrations.length && integrations.map((integration, index) =>
<Tr key={index}>
<Td>{integration.name}</Td>
<Td>{integration.description}</Td>
<Td><ExternalLink href={integration.externalUrl}>{integration.externalUrl}</ExternalLink></Td>
<Td>{integration.configured ? 'Yes' : 'No'}</Td>
<Td>-</Td>
</Tr>
)}
</Tbody>
</Table>
</div>
}
Example #3
Source File: Licenses.js From web-client with Apache License 2.0 | 6 votes |
LicensesPage = () => {
return <div>
<PageTitle value="Licenses" />
<div className='heading'>
<Breadcrumb />
</div>
<Title title="Licenses" icon={<IconQuestionCircle />} />
<Table>
<Thead>
<Th>Dependency</Th>
<Th>License</Th>
<Th>Url</Th>
</Thead>
<Tbody>
{Object.entries(Licenses).map(entry => <Tr>
<Td>{entry[0]}</Td>
<Td>{entry[1].licenses}</Td>
<Td>{entry[1].url}</Td>
</Tr>)}
</Tbody>
</Table>
</div>
}
Example #4
Source File: Table.js From web-client with Apache License 2.0 | 6 votes |
DocumentsTable = ({ documents, onDeleteButtonClick }) => {
return <Table>
<Thead>
<Tr>
<Th>Title</Th>
<Th style={{ width: '200px' }}>Creation time</Th>
<Th style={{ width: '140px' }}>Author</Th>
<Th style={{ width: '140px' }}>Visibility</Th>
<Th> </Th>
</Tr>
</Thead>
<Tbody>
{null === documents && <LoadingTableRow numColumns={6} />}
{null !== documents && documents.length === 0 && <NoResultsTableRow numColumns={6} />}
{null !== documents && documents.map((document, index) =>
<Tr key={`doc_${index}`}>
<Td><DocumentBadge document={document} /></Td>
<Td><RelativeDateFormatter date={document.insert_ts} /></Td>
<Td><UserLink userId={document.user_id}>{document.user_name}</UserLink></Td>
<Td><VisibilityLegend visibility={document.visibility} /></Td>
<Td style={{ textAlign: "right" }}>
<LinkButton href={`/documents/${document.id}/edit`}>Edit</LinkButton>
<DeleteIconButton onClick={ev => onDeleteButtonClick(document.id)} />
</Td>
</Tr>
)}
</Tbody>
</Table>
}
Example #5
Source File: RecentActivityWidget.js From web-client with Apache License 2.0 | 6 votes |
RecentActivityWidget = () => {
const [auditLog] = useFetch('/auditlog?limit=5');
return <DashboardWidget title="Recent activity">
{auditLog && auditLog.length > 0 ?
<Table>
<Thead>
<Tr>
<Th>Action</Th>
<Th>User</Th>
<Th>Date/Time</Th>
</Tr>
</Thead>
<Tbody>
{auditLog.map(log => <Tr key={log.id}>
<Td><Badge>{log.action}</Badge></Td>
<Td>{log.user_name ?
<UserLink userId={log.user_id}>{log.user_name}</UserLink> : '-'}</Td>
<Td>{log.insert_ts}</Td>
</Tr>)}
</Tbody>
</Table> :
<p>No activity to show.</p>
}
</DashboardWidget>
}
Example #6
Source File: BuilderListSkeleton.jsx From scaffold-directory with MIT License | 6 votes |
BuilderListSkeleton = () => (
<Box overflowX="auto">
<Center mb={5}>
<chakra.strong mr={2}>Total builders:</chakra.strong> <SkeletonText noOfLines={1} w={5} />
</Center>
<Table>
<Thead>
<Tr>
<Th>Builder</Th>
<Th>Challenges</Th>
<Th>Socials</Th>
<Th>Last Activity</Th>
</Tr>
</Thead>
<Tbody>
{[1, 2].map(lineNumber => {
return (
<Tr key={lineNumber}>
<Td>
<SkeletonAddress w="12.5" fontSize="16" />
</Td>
<Td>
<SkeletonText noOfLines={1} py={2} />
</Td>
<Td>
<SkeletonText noOfLines={1} py={2} />
</Td>
<Td>
<SkeletonText noOfLines={1} py={2} />
</Td>
</Tr>
);
})}
</Tbody>
</Table>
</Box>
)
Example #7
Source File: RecentDocumentsWidget.js From web-client with Apache License 2.0 | 6 votes |
RecentDocumentsWidget = () => {
const [documents] = useFetch(`/documents?limit=5`)
if (!documents) return <Loading />
return <DashboardWidget title="Recent documents">
{documents.length === 0 ?
<p>No documents to show.</p>
:
<Table>
<Thead>
<Tr>
<Th>Title</Th>
<Th>Created</Th>
</Tr>
</Thead>
<Tbody>
{documents.map(doc => <Tr key={doc.id}>
<Td><DocumentBadge key={doc.id} document={doc} /></Td>
<Td><RelativeDateFormatter date={doc.insert_ts} /></Td>
</Tr>)}
</Tbody>
</Table>
}
</DashboardWidget>
}
Example #8
Source File: Table.js From web-client with Apache License 2.0 | 6 votes |
NotesTable = ({ notes, onDeleteButtonClick }) => {
return <Table>
<Thead>
<Tr>
<Th>Content</Th>
<Th style={{ width: '200px' }}>Creation time</Th>
<Th style={{ width: '140px' }}>Author</Th>
<Th style={{ width: '140px' }}>Visibility</Th>
<Th> </Th>
</Tr>
</Thead>
<Tbody>
{notes.length === 0 && <NoResultsTableRow numColumns={5} />}
{notes.map((note, index) =>
<Tr>
<Td><ReactMarkdown>{note.content}</ReactMarkdown></Td>
<Td><ReactTimeAgo date={note.insert_ts} /></Td>
<Td><UserLink userId={note.user_id}>{note.user_name}</UserLink></Td>
<Td><VisibilityLegend visibility={note.visibility} /></Td>
<Td>
<RestrictedComponent roles={['administrator', 'superuser', 'user']}>
<DeleteIconButton onClick={ev => onDeleteButtonClick(ev, note)} />
</RestrictedComponent>
</Td>
</Tr>
)}
</Tbody>
</Table>
}
Example #9
Source File: RecentVulnerabilitiesWidget.js From web-client with Apache License 2.0 | 6 votes |
RecentVulnerabilitiesWidget = () => {
const [vulnerabilities] = useFetch(`/vulnerabilities?limit=5&orderColumn=insert_ts&orderDirection=desc`)
if (!vulnerabilities) return <Loading />
return <DashboardWidget title="Recent vulnerabilities">
{vulnerabilities.length === 0 ?
<p>No vulnerabilities to show.</p>
:
<Table>
<Thead>
<Tr>
<Th>Summary</Th>
<Th>Created</Th>
</Tr>
</Thead>
<Tbody>
{vulnerabilities.map(vulnerability => <Tr key={vulnerability.id}>
<Td><VulnerabilityBadge key={vulnerability.id} vulnerability={vulnerability} /></Td>
<Td><RelativeDateFormatter date={vulnerability.insert_ts} /></Td>
</Tr>)}
</Tbody>
</Table>
}
</DashboardWidget>
}
Example #10
Source File: List.js From web-client with Apache License 2.0 | 5 votes |
NotificationsList = () => {
const [notifications, fetchNotifications] = useFetch('/notifications')
const markNotificationAsRead = notification => {
secureApiFetch(`/notifications/${notification.id}`, {
method: 'PUT',
body: JSON.stringify({ status: 'read' })
}).then(() => {
fetchNotifications();
})
}
const deleteNotification = useDelete('/notifications/', fetchNotifications);
return <>
<PageTitle value="Notifications" />
<div className='heading'>
<Breadcrumb />
</div>
<Title title='Notifications' icon={<BellIcon />} />
<Table>
<Thead>
<Tr>
<Th w={50}> </Th>
<Th w={200}>Date/time</Th>
<Th>Content</Th>
<Th> </Th>
</Tr>
</Thead>
<Tbody>
{null === notifications && <LoadingTableRow numColumns={3} />}
{null !== notifications && notifications.length === 0 && <NoResultsTableRow numColumns={3} />}
{null !== notifications && notifications.length > 0 &&
notifications.map(notification =>
<Tr key={notification.id}>
<Th>{notification.status === 'read' ? <FontAwesomeIcon icon={faCheck} /> : <> </>}</Th>
<Td><RelativeDateFormatter date={notification.insert_ts} /></Td>
<Td>
<strong>{notification.title}</strong>
<div>{notification.content}</div>
</Td>
<Td textAlign="right">
<ButtonGroup>
{notification.status === 'unread' && <Button onClick={() => markNotificationAsRead(notification)} leftIcon={<FontAwesomeIcon icon={faCheck} />}>Mark as read</Button>}
<DeleteIconButton onClick={() => deleteNotification(notification.id)} />
</ButtonGroup>
</Td>
</Tr>
)
}
</Tbody>
</Table>
</>
}
Example #11
Source File: AuditLogsTable.js From web-client with Apache License 2.0 | 5 votes |
AuditLogsTable = ({ auditLog, hideUserColumns = false }) => {
const numColumns = hideUserColumns ? 4 : 6;
return <Table>
<Thead>
<Tr>
<Th>Event</Th>
<Th>IP address</Th>
<Th>User agent</Th>
<Th>Date/Time</Th>
{!hideUserColumns &&
<>
<Th>User</Th>
<Th>Role</Th>
</>
}
<Th>Data</Th>
</Tr>
</Thead>
<Tbody>
{auditLog !== null && auditLog.length === 0 && <NoResultsTableRow numColumns={numColumns} />}
{auditLog !== null && auditLog.map(entry => {
return <Tr key={entry.id}>
<Td>
<Badge>{entry.action}</Badge>
</Td>
<Td><Ipv4Link value={entry.client_ip} /></Td>
<Td>{entry.user_agent ? <UserAgentLabel userAgent={entry.user_agent} /> : '-'}</Td>
<Td>{entry.insert_ts}</Td>
{!hideUserColumns &&
<>
<Td>{entry.user_name ?
<UserLink userId={entry.user_id}>{entry.user_name}</UserLink> : '-'}</Td>
<Td><UserRoleBadge role={entry.user_role} /></Td>
</>
}
<Td>{entry.object}</Td>
</Tr>
})}
</Tbody>
</Table>
}
Example #12
Source File: Mdx.js From codeursenseine.com with MIT License | 5 votes |
TABLE = (props) => <Table variant="striped" type="md" colorScheme="gray" mb="1em" {...props} />
Example #13
Source File: List.js From web-client with Apache License 2.0 | 5 votes |
ClientsList = () => {
const navigate = useNavigate();
const [clients, updateTasks] = useFetch('/clients')
const destroy = useDelete('/clients/', updateTasks);
const handleCreateClient = () => {
navigate(`/clients/create`)
}
return <>
<PageTitle value="Clients" />
<div className='heading'>
<Breadcrumb />
<ButtonGroup isAttached>
<CreateButton onClick={handleCreateClient}>Add client</CreateButton>
<Menu>
<MenuButton as={IconButton} aria-label='Options' icon={<FontAwesomeIcon icon={faEllipsis} />} variant='outline' />
<MenuList>
<ExportMenuItem entity="clients" />
</MenuList>
</Menu>
</ButtonGroup>
</div>
<Title title='Clients' icon={<IconBriefcase />} />
<Table>
<Thead>
<Tr>
<Th>Name</Th>
<Th>Address</Th>
<Th>URL</Th>
<Th>Number of contacts</Th>
<Th> </Th>
</Tr>
</Thead>
<Tbody>
{null === clients && <LoadingTableRow numColumns={5} />}
{null !== clients && 0 === clients.length && <NoResultsTableRow numColumns={5} />}
{null !== clients && 0 < clients.length && clients.map(client =>
<Tr key={client.id}>
<Td><ClientLink clientId={client.id}>{client.name}</ClientLink></Td>
<Td>{client.address || '-'}</Td>
<Td>{client.url ? <ExternalLink href={client.url}>{client.url}</ExternalLink> : '-'}</Td>
<Td>{client.num_contacts}</Td>
<Td textAlign="right">
<LinkButton href={`/clients/${client.id}/edit`}>Edit</LinkButton>
<DeleteIconButton onClick={() => destroy(client.id)} />
</Td>
</Tr>
)
}
</Tbody>
</Table>
</>
}
Example #14
Source File: Table.js From web-client with Apache License 2.0 | 5 votes |
ProjectsTable = ({ projects, destroy = null, showClientColumn = true }) => {
const numColumns = showClientColumn ? 7 : 6;
return <Table>
<Thead>
<Tr>
<Th>Name</Th>
{showClientColumn && <Th>Client</Th>}
<Th className="only-desktop">Description</Th>
<Th>Category</Th>
<Th>Vulnerability Metrics</Th>
<Th>Status</Th>
<Th> </Th>
</Tr>
</Thead>
<Tbody>
{null === projects && <LoadingTableRow numColumns={numColumns} />}
{null !== projects && 0 === projects.length && <NoResultsTableRow numColumns={numColumns} />}
{null !== projects && 0 !== projects.length && projects.map(project =>
<Tr key={project.id}>
<Td>
<ProjectBadge project={project} />
</Td>
{showClientColumn &&
<Td>{project.is_template ?
<span title="Not applicable">(n/a)</span> :
<ClientLink clientId={project.client_id}>{project.client_name}</ClientLink>}
</Td>
}
<Td className="only-desktop">{project.description}</Td>
<Td>{project.category_id !== null ? project.category_name : '(undefined)'}</Td>
<Td>{project.vulnerability_metrics ? project.vulnerability_metrics : '(undefined)'}</Td>
<Td>{project.archived ? 'Archived' : 'Active'}</Td>
<Td textAlign="right">
<RestrictedComponent roles={['administrator', 'superuser', 'user']}>
<LinkButton href={`/projects/${project.id}/edit`}>Edit</LinkButton>
{destroy &&
<DeleteIconButton onClick={() => destroy(project.id)} />
}
</RestrictedComponent>
</Td>
</Tr>
)}
</Tbody>
</Table>
}
Example #15
Source File: List.js From web-client with Apache License 2.0 | 5 votes |
TemplatesList = () => {
const navigate = useNavigate();
const [templates, updateTemplates] = useFetch('/projects?isTemplate=1')
const cloneProject = (ev, templateId) => {
ev.stopPropagation();
secureApiFetch(`/projects/${templateId}/clone`, { method: 'POST' })
.then(resp => resp.json())
.then(data => {
navigate(`/projects/${data.projectId}/edit`);
});
}
const viewProject = (templateId) => {
navigate(`/projects/templates/${templateId}`);
}
const destroy = useDelete('/projects/', updateTemplates);
const deleteTemplate = (ev, templateId) => {
ev.stopPropagation();
destroy(templateId);
}
const onAddProjectTemplateClick = () => {
navigate(`/projects/create?isTemplate=true`)
}
return <>
<PageTitle value="Project templates" />
<div className='heading'>
<Breadcrumb>
<Link to="/projects">Projects</Link>
</Breadcrumb>
<CreateButton onClick={onAddProjectTemplateClick}>Add project template</CreateButton>
</div>
<Title title='Project templates' icon={<IconDocumentDuplicate />} />
{!templates ? <Loading /> :
<Table>
<Thead>
<Tr>
<Th style={{ width: '190px' }}>Name</Th>
<Th>Description</Th>
<Th style={{ width: '16ch' }}>Number of tasks</Th>
<Th> </Th>
</Tr>
</Thead>
<Tbody>
{templates.length === 0 ?
<Td colSpan={4}><NoResults /></Td>
:
templates.map((template) =>
<Tr key={template.id} onClick={() => viewProject(template.id)}>
<Td><ProjectBadge project={template} /></Td>
<Td>{template.description}</Td>
<Td><BadgeOutline>{template.num_tasks}</BadgeOutline></Td>
<Td textAlign="right">
<PrimaryButton onClick={ev => cloneProject(ev, template.id)} key={template.id}
title="Clone" leftIcon={<IconPlus />}>Clone and edit</PrimaryButton>
<LinkButton href={`/projects/${template.id}/edit`}>Edit</LinkButton>
<DeleteIconButton onClick={ev => deleteTemplate(ev, template.id)} />
</Td>
</Tr>
)
}
</Tbody>
</Table>
}
</>
}
Example #16
Source File: Table.js From web-client with Apache License 2.0 | 5 votes |
ReportsTable = ({ reports, updateReports, includeProjectColumn = false }) => {
const navigate = useNavigate();
const deleteReport = useDelete('/reports/', updateReports);
const handleDownload = (reportId) => {
secureApiFetch(`/attachments/${reportId}`, { method: 'GET', headers: {} })
.then(resp => {
const contentDispositionHeader = resp.headers.get('Content-Disposition');
const filenameRe = new RegExp(/filename="(.*)";/)
const filename = filenameRe.exec(contentDispositionHeader)[1]
return Promise.all([resp.blob(), filename]);
})
.then((values) => {
const blob = values[0];
const filename = values[1];
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = filename;
a.click();
})
}
const handleSendByEmail = (projectId) => {
navigate(`/projects/${projectId}/report/send`);
}
return <Table>
<Thead>
<Tr>
<Th>Name (Description)</Th>
{includeProjectColumn && <Th>Project</Th>}
<Th>Datetime</Th>
<Th>Downloads</Th>
<Th> </Th>
</Tr>
</Thead>
<Tbody>
{reports.length === 0 && <NoResultsTableRow numColumns={4} />}
{reports.map((report, index) =>
<Tr key={index}>
<Td>{report.version_name} ({report.version_description})</Td>
{includeProjectColumn && <Td><ProjectBadge project={{ id: report.project_id, name: report.project_name }} /></Td>}
<Td><RelativeDateFormatter date={report.insert_ts} /></Td>
<Td>
<SecondaryButton onClick={() => handleDownload(report.docx_attachment_id)}>
<IconDocument /> DOCX
</SecondaryButton>
</Td>
<Td textAlign="right">
<SecondaryButton onClick={() => handleSendByEmail(report.project_id)}>Send by email</SecondaryButton>
<DeleteIconButton onClick={() => deleteReport(report.id)} />
</Td>
</Tr>
)}
</Tbody>
</Table>
}
Example #17
Source File: TasksTable.js From web-client with Apache License 2.0 | 5 votes |
TasksTable = ({ tableModel, tableModelSetter: setTableModel, destroy, reloadCallback = null }) => {
const showSelection = tableModel.columnsVisibility.selection;
const showProjectColumn = tableModel.columnsVisibility.project;
const numColumns = 6 + (showSelection ? 1 : 0) + (showProjectColumn ? 1 : 0);
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) })
}
};
return <Table>
<Thead>
<Tr>
{showSelection && <Th style={{ width: "32px" }}> </Th>}
<Th>Summary</Th>
<Th className='only-desktop'>Description</Th>
{showProjectColumn && <Th>Project</Th>}
<Th>Priority</Th>
<Th>Assignee</Th>
<Th style={{ width: '100px' }}>Status</Th>
<Th colSpan={reloadCallback ? 1 : 2}>Command</Th>
{reloadCallback && <Th style={{ width: '15%', textAlign: 'right' }}><ReloadButton onClick={reloadCallback} /></Th>}
</Tr>
</Thead>
<Tbody>
{null === tableModel.tasks && <LoadingTableRow numColumns={numColumns} />}
{null !== tableModel.tasks && 0 === tableModel.tasks.length && <NoResultsTableRow numColumns={numColumns} />}
{null !== tableModel.tasks && tableModel.tasks.map(task =>
<Tr key={task.id}>
{showSelection &&
<Td>
<input
type="checkbox"
value={task.id}
onChange={onSelectionChange}
checked={tableModel.selection.includes(task.id)}
/>
</Td>
}
<Td><TaskBadge task={task} /></Td>
<Td className="only-desktop">{task.description ? task.description.substring(0, 100) + "..." : "-"}</Td>
{showProjectColumn && <Td><ProjectBadge project={{ id: task.project_id, name: task.project_name }} /></Td>}
<Td>{task.priority}</Td>
<Td >{task.assignee_uid ?
<UserLink userId={task.assignee_uid}>{task.assignee_full_name}</UserLink> : '(nobody)'}</Td>
<Td><TaskStatusFormatter task={task} /></Td>
<Td>{task.command_name ? <BadgeOutline>{task.command_name}</BadgeOutline> : '-'}</Td>
<Td textAlign="right">
<RestrictedComponent roles={['administrator', 'superuser', 'user']}>
<LinkButton href={`/tasks/${task.id}/edit`}>Edit</LinkButton>
{destroy && <DeleteIconButton onClick={() => destroy(task.id)} />}
</RestrictedComponent>
</Td>
</Tr>
)}
</Tbody>
</Table>
}
Example #18
Source File: List.js From web-client with Apache License 2.0 | 5 votes |
VulnerabilityCategoriesPage = () => {
const [categories, fetchParentCategories] = useFetch('/vulnerabilities/categories?parentsOnly=0')
const destroy = useDelete('/vulnerabilities/categories/', fetchParentCategories);
const [editCategory, setEditCategory] = useState({});
const { isOpen: isAddCategoryDialogOpen, onOpen: openAddCategoryDialog, onClose: closeAddCategoryDialog } = useDisclosure();
const { isOpen: isEditCategoryDialogOpen, onOpen: openEditCategoryDialog, onClose: closeEditCategoryDialog } = useDisclosure();
const onCategoryDialogClosed = () => {
fetchParentCategories();
closeAddCategoryDialog();
closeEditCategoryDialog();
}
const onAddClick = ev => {
ev.preventDefault();
openAddCategoryDialog();
}
const onEditClick = (ev, ccategory) => {
ev.preventDefault();
setEditCategory(ccategory);
openEditCategoryDialog();
}
const onDeleteClick = (ev, templateId) => {
ev.stopPropagation();
destroy(templateId);
}
return <>
<PageTitle value="Vulnerability categories" />
<div className='heading'>
<Breadcrumb>
<Link to="/vulnerabilities">Vulnerabilities</Link>
</Breadcrumb>
<VulnerabilityCategoryAddModalDialog isOpen={isAddCategoryDialogOpen} onClose={onCategoryDialogClosed} onCancel={closeAddCategoryDialog} />
{isEditCategoryDialogOpen && <VulnerabilityCategoryEditModalDialog category={editCategory} isOpen={isEditCategoryDialogOpen} onClose={onCategoryDialogClosed} onCancel={closeEditCategoryDialog} />}
<CreateButton onClick={onAddClick}>Add vulnerability category...</CreateButton>
</div>
<Title title='Vulnerability categories' icon={<IconDocumentDuplicate />} />
{!categories ? <Loading /> :
<Table>
<Thead>
<Tr>
<Th style={{ width: '190px' }}>Name</Th>
<Th>Parent category</Th>
<Th colSpan={2}>Description</Th>
</Tr>
</Thead>
<Tbody>
{categories.length === 0 ?
<Tr><Td colSpan={3}><NoResults /></Td></Tr>
:
categories.map(category =>
<Tr key={category.id}>
<Td><strong>{category.name}</strong></Td>
<Td>{category.parent_name ?? '-'}</Td>
<Td>{category.description}</Td>
<Td textAlign="right">
<LinkButton href="#" onClick={ev => onEditClick(ev, category)}>Edit</LinkButton>
<DeleteIconButton onClick={ev => onDeleteClick(ev, category.id)} />
</Td>
</Tr>
)
}
</Tbody>
</Table>
}
</>
}
Example #19
Source File: List.js From web-client with Apache License 2.0 | 5 votes |
VulnerabilityTemplatesList = () => {
const navigate = useNavigate();
const [sortBy, setSortBy] = useState({ column: 'insert_ts', order: 'DESC' })
const [templates, updateTemplates] = useFetch(`/vulnerabilities?isTemplate=1&orderColumn=${sortBy.column}&orderDirection=${sortBy.order}`)
const cloneVulnerability = (ev, templateId) => {
ev.stopPropagation();
secureApiFetch(`/vulnerabilities/${templateId}/clone`, { method: 'POST' })
.then(resp => resp.json())
.then(data => {
navigate(`/vulnerabilities/${data.vulnerabilityId}/edit`);
});
}
const onSortChange = (ev, column, order) => {
ev.preventDefault();
setSortBy({ column: column, order: order });
}
const viewTemplate = (templateId) => {
navigate(`/vulnerabilities/templates/${templateId}`);
}
const destroy = useDelete('/vulnerabilities/', updateTemplates);
const deleteTemplate = (ev, templateId) => {
ev.stopPropagation();
destroy(templateId);
}
const onAddVulnerabilityTemplateClick = () => {
navigate(`/vulnerabilities/create?isTemplate=true`)
}
return (
<>
<PageTitle value="Vulnerability templates" />
<div className='heading'>
<Breadcrumb>
<Link to="/vulnerabilities">Vulnerabilities</Link>
</Breadcrumb>
<CreateButton onClick={onAddVulnerabilityTemplateClick}>Add vulnerability template</CreateButton>
</div>
<Title title='Vulnerability templates' icon={<IconDocumentDuplicate />} />
{!templates ? <Loading /> :
<Table>
<Thead>
<Tr>
<Th>Summary</Th>
<Th colSpan={2}><DescendingSortLink callback={onSortChange} property="category_name" /> Category <AscendingSortLink callback={onSortChange} property="category_name" /></Th>
</Tr>
</Thead>
<Tbody>
{templates.length === 0 ?
<Tr><Td colSpan={3}><NoResults /></Td></Tr>
:
templates.map((template) =>
<Tr key={template.id} onClick={() => viewTemplate(template.id)}>
<Td><VulnerabilityBadge vulnerability={template} /></Td>
<Td><VulnerabilityCategorySpan name={template.category_name} parentName={template.parent_category_name} /></Td>
<Td textAlign="right">
<PrimaryButton onClick={ev => cloneVulnerability(ev, template.id)} key={template.id}
title="Clone" leftIcon={<IconPlus />}>Clone and edit</PrimaryButton>
<LinkButton href={`/vulnerabilities/${template.id}/edit`}>Edit</LinkButton>
<DeleteIconButton onClick={ev => deleteTemplate(ev, template.id)} />
</Td>
</Tr>
)
}
</Tbody>
</Table>
}
</>
)
}
Example #20
Source File: ActivityView.jsx From scaffold-directory with MIT License | 5 votes |
export default function ActivityView() {
const [eventsFeed, setEventFeeds] = useState([]);
const [isLoadingEvents, setIsLoadingEvents] = useState(false);
const { secondaryFontColor } = useCustomColorModes();
useEffect(() => {
const updateEvents = async () => {
setIsLoadingEvents(true);
const events = await getAllEvents(25);
setEventFeeds(events);
setIsLoadingEvents(false);
};
updateEvents();
}, []);
return (
<Container maxW="container.md" centerContent>
<Heading as="h1" mb="4">
Activity feed
</Heading>
<Text color={secondaryFontColor} textAlign="center" mb={10}>
Last 25 things happening at SRE.
</Text>
{isLoadingEvents ? (
<Box w="100%" maxW="500px">
<SkeletonText mt="4" noOfLines={10} spacing="4" />
</Box>
) : (
<Table>
<Thead>
<Tr>
<Th>Builder</Th>
<Th>Time</Th>
<Th>Action</Th>
</Tr>
</Thead>
<Tbody>
{eventsFeed.map(event => (
<EventRow key={`${event.timestamp}_${event.payload.userAddress}`} event={event} />
))}
</Tbody>
</Table>
)}
</Container>
);
}
Example #21
Source File: TechStack.js From benjamincarlson.io with MIT License | 5 votes |
TechStack = () => {
const { colorMode } = useColorMode()
const colorSecondary = {
light: 'gray.600',
dark: 'gray.400'
}
const linkColor = {
light: 'blue.400',
dark: 'blue.600'
}
return (
<Box as="section" w="100%" mt={10} mb={20}>
<Heading letterSpacing="tight" size="lg" fontWeight={700} as="h2" mb={4}>
Tech Stack ⚙️
</Heading>
<Text color={colorSecondary[colorMode]} mb={4}>Each piece of technology used in this website is carefully thought out. I believe this is one of the best stacks there is to build websites of any size and domain.</Text>
<Box flexDir="column" overflowX="auto">
<Table variant="simple">
<Thead>
<Tr>
<Th>Type</Th>
<Th>Name</Th>
<Th>Route</Th>
<Th>Description</Th>
</Tr>
</Thead>
<Tbody>
<Tr>
<Td>JS Framework</Td>
<Td><Link href="https://nextjs.org" color={linkColor[colorMode]} isExternal>Next JS</Link></Td>
<Td>n/a</Td>
<Td>Next.js was an easy choice given its large community and ability for rapid development.</Td>
</Tr>
<Tr>
<Td>CSS Framework</Td>
<Td><Link href="https://chakra-ui.com" color={linkColor[colorMode]} isExternal>Chakra UI</Link></Td>
<Td>n/a</Td>
<Td>I use Chakra UI because its components make a beautiful UI out of the box and are highly customizable.</Td>
</Tr>
<Tr>
<Td>Blog</Td>
<Td><Code>next-mdx-remote</Code></Td>
<Td>/blog/[slug].js</Td>
<Td>I use <Link href="https://github.com/hashicorp/next-mdx-remote" color={linkColor[colorMode]} isExternal>next-mdx-remote</Link> for my blog. Posts are stored in <Code>mdx</Code> files and pre-rendered.</Td>
</Tr>
<Tr>
<Td>Real-Time Statistics</Td>
<Td>Next.js api routes</Td>
<Td>/api/[].js</Td>
<Td>Multiple api routes that interact with the GitHub, YouTube, and Strava api to fetch my real-time social media data using Next.JS <Link href="https://nextjs.org/docs/api-routes/introduction" color={linkColor[colorMode]} isExternal>serverless functions</Link>.</Td>
</Tr>
<Tr>
<Td>Realtime Blog Post View/Like Count</Td>
<Td>Firebase Realtime Db</Td>
<Td>/api</Td>
<Td>I use <Link href="https://firebase.google.com" color={linkColor[colorMode]} isExternal>Google's Firebase</Link> to store view and like counts for my blog posts.</Td>
</Tr>
<Tr>
<Td>Deployment</Td>
<Td>Vercel</Td>
<Td>n/a</Td>
<Td>I use <Link href="https://vercel.com" color={linkColor[colorMode]} isExternal>Vercel</Link> to deploy my app. It's free, fast, integrates with GitHub, and overall a great experience.</Td>
</Tr>
<Tr>
<Td>Domain</Td>
<Td>Namecheap</Td>
<Td>n/a</Td>
<Td>My domain name is bought and stored through <Link color="blue.500" href="https://www.namecheap.com/" isExternal>Namecheap</Link>.</Td>
</Tr>
</Tbody>
</Table>
</Box>
</Box>
)
}
Example #22
Source File: SubmissionReviewTableSkeleton.jsx From scaffold-directory with MIT License | 5 votes |
ChallengesTableSkeleton = () => (
<Box overflowX="auto">
<Table mb={4}>
<Thead>
<Tr>
<Th>Builder</Th>
<Th>Challenge</Th>
<Th>Contract</Th>
<Th>Live demo</Th>
<Th>Submitted time</Th>
<Th>Actions</Th>
</Tr>
</Thead>
<Tbody>
{[1, 2].map(lineNumber => {
return (
<Tr key={lineNumber}>
<Td>
<SkeletonAddress w="12.5" fontSize="16" />
</Td>
<Td>
<SkeletonText noOfLines={1} py={4} />
</Td>
<Td>
<SkeletonText noOfLines={1} py={4} />
</Td>
<Td>
<SkeletonText noOfLines={1} py={4} />
</Td>
<Td>
<SkeletonText noOfLines={1} py={4} />
</Td>
<Td>
<Skeleton startColor="blue.100" endColor="blue.500">
<Button type="button" size="xs">
Review
</Button>
</Skeleton>
</Td>
</Tr>
);
})}
</Tbody>
</Table>
</Box>
)
Example #23
Source File: SubmissionReviewTableSkeleton.jsx From scaffold-directory with MIT License | 5 votes |
BuildsTableSkeleton = () => (
<Box overflowX="auto">
<Table mb={4}>
<Thead>
<Tr>
<Th>Builder</Th>
<Th>Build Name</Th>
<Th>Description</Th>
<Th>Branch URL</Th>
<Th>Submitted time</Th>
<Th>Actions</Th>
</Tr>
</Thead>
<Tbody>
{[1, 2].map(lineNumber => {
return (
<Tr key={lineNumber}>
<Td>
<SkeletonAddress w="12.5" fontSize="16" />
</Td>
<Td>
<SkeletonText noOfLines={1} py={4} />
</Td>
<Td>
<SkeletonText noOfLines={1} py={4} />
</Td>
<Td>
<SkeletonText noOfLines={1} py={4} />
</Td>
<Td>
<SkeletonText noOfLines={1} py={4} />
</Td>
<Td>
<HStack spacing={3}>
<Skeleton startColor="red.100" endColor="red.500">
<Button type="button" size="xs">
Reject
</Button>
</Skeleton>
<Skeleton startColor="green.100" endColor="green.500">
<Button type="button" style={{ marginRight: 10 }} size="xs">
Approve
</Button>
</Skeleton>
</HStack>
</Td>
</Tr>
);
})}
</Tbody>
</Table>
</Box>
)
Example #24
Source File: BuilderProfileChallengesTableSkeleton.jsx From scaffold-directory with MIT License | 5 votes |
BuilderProfileChallengesTableSkeleton = () => (
<Box overflowX="auto">
<Table>
<Thead>
<Tr>
<Th w="30%">Name</Th>
<Th>Contract</Th>
<Th>Live Demo</Th>
<Th>Updated</Th>
<Th>Status</Th>
</Tr>
</Thead>
<Tbody>
{[1, 2].map(lineNumber => {
return (
<Tr key={lineNumber}>
<Td>
<SkeletonText noOfLines={1} py={2} />
</Td>
<Td>
<SkeletonText noOfLines={1} w="50%" />
</Td>
<Td>
<SkeletonText noOfLines={1} w="50%" />
</Td>
<Td>
<SkeletonText noOfLines={1} />
</Td>
<Td>
<Skeleton h={6} w={20} borderRadius="full">
Submitted
</Skeleton>
</Td>
</Tr>
);
})}
</Tbody>
</Table>
</Box>
)
Example #25
Source File: Cart.js From react-sample-projects with MIT License | 5 votes |
Cart = () => {
const dispatch = useDispatch();
const navigate = useNavigate();
const cartItems = useSelector(state => state.cart.cartItems);
const viewProductDetails = (e, item) => {
navigate(`/product/${item.id}`);
};
const deleteItem = (e, item) => {
e.stopPropagation();
e.preventDefault();
dispatch(deleteItemFromCart(item));
};
if (cartItems.length === 0) {
return (
<Flex>
<Box
m={4}
w="100%"
fontWeight="semibold"
letterSpacing="wide"
textAlign="center"
>
You cart empty :(
</Box>
</Flex>
);
}
return (
<Box m={3} p={3}>
<Table variant="simple">
<Thead>
<Tr>
<Th>#</Th>
<Th>Image</Th>
<Th>Title</Th>
<Th isNumeric>Price</Th>
<Th isNumeric>Quantity</Th>
<Th>Action</Th>
</Tr>
</Thead>
<Tbody>
{cartItems.map((item, index) => (
<Tr key={item.id} onClick={e => viewProductDetails(e, item)}>
<Td>{index + 1}</Td>
<Td>
<Avatar size={'sm'} src={item.image} alt={item.title} />
</Td>
<Td>{item.title}</Td>
<Td isNumeric>
${parseFloat(item.price * item.quantity).toFixed(2)}
</Td>
<Td isNumeric>{item.quantity}</Td>
<Td>
<Button onClick={e => deleteItem(e, item)}>Delete</Button>
</Td>
</Tr>
))}
</Tbody>
</Table>
</Box>
);
}
Example #26
Source File: offers.js From idena-web with MIT License | 5 votes |
export default function AdOfferList() {
const {t} = useTranslation()
const queryClient = useQueryClient()
const {data: burntCoins, status: burntCoinsStatus} = useApprovedBurntCoins()
const isFetched = burntCoinsStatus === 'success'
const isEmpty = isFetched && burntCoins.length === 0
const [selectedAd, setSelectedAd] = React.useState({})
const burnDisclosure = useDisclosure()
const {
onOpen: onOpenBurnDisclosure,
onClose: onCloseBurnDisclosure,
} = burnDisclosure
const handlePreviewBurn = React.useCallback(
ad => {
setSelectedAd(ad)
onOpenBurnDisclosure()
},
[onOpenBurnDisclosure]
)
const handleBurn = React.useCallback(() => {
onCloseBurnDisclosure()
queryClient.invalidateQueries(['bcn_burntCoins', []])
}, [onCloseBurnDisclosure, queryClient])
return (
<Layout skipBanner>
<Page>
<PageHeader>
<PageTitle mb={4}>{t('All offers')}</PageTitle>
<PageCloseButton href="/adn/list" />
</PageHeader>
<Table>
<Thead>
<Tr>
<RoundedTh isLeft>{t('Banner/author')}</RoundedTh>
<RoundedTh>{t('Website')}</RoundedTh>
<RoundedTh>{t('Target')}</RoundedTh>
<RoundedTh>{t('Burn')}</RoundedTh>
<RoundedTh isRight />
</Tr>
</Thead>
<Tbody>
{isFetched &&
burntCoins.map(burn => (
<AdOfferListItem
key={burn.key}
burn={burn}
onBurn={handlePreviewBurn}
/>
))}
</Tbody>
</Table>
{isEmpty && (
<Center color="muted" mt="4" w="full">
{t('No active offers')}
</Center>
)}
<BurnDrawer ad={selectedAd} onBurn={handleBurn} {...burnDisclosure} />
</Page>
</Layout>
)
}
Example #27
Source File: view.js From idena-web with MIT License | 4 votes |
export default function ViewVotingPage() {
const {t, i18n} = useTranslation()
const [, {addVote}] = useDeferredVotes()
const toast = useToast()
const {
query: {id},
push: redirect,
} = useRouter()
const {epoch} = useEpoch() ?? {epoch: -1}
const {coinbase, privateKey} = useAuthState()
const {
data: {balance: identityBalance},
} = useBalance()
const [current, send, service] = useMachine(viewVotingMachine, {
actions: {
onError: (context, {data: {message}}) => {
toast({
status: 'error',
// eslint-disable-next-line react/display-name
render: () => (
<Toast title={humanError(message, context)} status="error" />
),
})
},
addVote: (_, {data: {vote}}) => addVote(vote),
},
})
React.useEffect(() => {
send('RELOAD', {id, epoch, address: coinbase})
}, [coinbase, epoch, id, send])
const toDna = toLocaleDna(i18n.language)
const {
title,
desc,
contractHash,
status,
balance = 0,
contractBalance = Number(balance),
votingMinPayment = 0,
publicVotingDuration = 0,
quorum = 20,
committeeSize,
options = [],
votes = [],
voteProofsCount,
finishDate,
finishCountingDate,
selectedOption,
winnerThreshold = 50,
balanceUpdates,
ownerFee,
totalReward,
estimatedOracleReward,
estimatedMaxOracleReward = estimatedOracleReward,
isOracle,
minOracleReward,
estimatedTotalReward,
pendingVote,
adCid,
issuer,
} = current.context
const [
{canProlong, canFinish, canTerminate, isFetching: actionsIsFetching},
refetchActions,
] = useOracleActions(id)
const isLoaded = !current.matches('loading')
const sameString = a => b => areSameCaseInsensitive(a, b)
const eitherIdleState = (...states) =>
eitherState(current, ...states.map(s => `idle.${s}`.toLowerCase())) ||
states.some(sameString(status))
const isClosed = eitherIdleState(
VotingStatus.Archived,
VotingStatus.Terminated
)
const didDetermineWinner = hasWinner({
votes,
votesCount: voteProofsCount,
winnerThreshold,
quorum,
committeeSize,
finishCountingDate,
})
const isMaxWinnerThreshold = winnerThreshold === 100
const accountableVoteCount = sumAccountableVotes(votes)
const {data: ad} = useIpfsAd(adCid)
const adPreviewDisclosure = useDisclosure()
const isValidAdVoting = React.useMemo(
() => validateAdVoting({ad, voting: current.context}) === false,
[ad, current.context]
)
const isMaliciousAdVoting = ad && isValidAdVoting
return (
<>
<Layout showHamburger={false}>
<Page pt={8}>
<Stack spacing={10}>
<VotingSkeleton isLoaded={isLoaded} h={6}>
<Stack isInline spacing={2} align="center">
<VotingStatusBadge status={status} fontSize="md">
{t(mapVotingStatus(status))}
</VotingStatusBadge>
<Box
as={VotingBadge}
bg="gray.100"
color="muted"
fontSize="md"
cursor="pointer"
pl="1/2"
transition="color 0.2s ease"
_hover={{
color: 'brandGray.500',
}}
onClick={() => {
openExternalUrl(
`https://scan.idena.io/contract/${contractHash}`
)
}}
>
<Stack isInline spacing={1} align="center">
<Avatar size={5} address={contractHash} />
<Text>{contractHash}</Text>
</Stack>
</Box>
<CloseButton
sx={{
'&': {
marginLeft: 'auto!important',
},
}}
onClick={() => redirect('/oracles/list')}
/>
</Stack>
</VotingSkeleton>
<Stack isInline spacing={10} w="full">
<Box minWidth="lg" maxW="lg">
<Stack spacing={6}>
<VotingSkeleton isLoaded={isLoaded}>
<Stack
spacing={8}
borderRadius="md"
bg="gray.50"
py={8}
px={10}
>
<Stack spacing={4}>
<Heading
overflow="hidden"
fontSize={21}
fontWeight={500}
display="-webkit-box"
sx={{
'&': {
WebkitBoxOrient: 'vertical',
WebkitLineClamp: '2',
},
}}
>
{isMaliciousAdVoting
? t('Please reject malicious ad')
: title}
</Heading>
{ad ? (
<>
{isMaliciousAdVoting ? (
<MaliciousAdOverlay>
<OracleAdDescription ad={ad} />
</MaliciousAdOverlay>
) : (
<OracleAdDescription ad={ad} />
)}
</>
) : (
<Text
isTruncated
lineHeight="tall"
whiteSpace="pre-wrap"
>
<Linkify
onClick={url => {
send('FOLLOW_LINK', {url})
}}
>
{desc}
</Linkify>
</Text>
)}
</Stack>
<Flex>
{adCid && (
<IconButton
icon={<ViewIcon boxSize={4} />}
_hover={{background: 'transparent'}}
onClick={adPreviewDisclosure.onOpen}
>
{t('Preview')}
</IconButton>
)}
<GoogleTranslateButton
phrases={[
title,
desc &&
encodeURIComponent(desc?.replace(/%/g, '%25')),
options.map(({value}) => value).join('\n'),
]}
locale={i18n.language}
alignSelf="start"
/>
</Flex>
<Divider orientation="horizontal" />
{isLoaded && <VotingPhase service={service} />}
</Stack>
</VotingSkeleton>
{eitherIdleState(
VotingStatus.Pending,
VotingStatus.Starting,
VotingStatus.Open,
VotingStatus.Voting,
VotingStatus.Voted,
VotingStatus.Prolonging
) && (
<VotingSkeleton isLoaded={isLoaded}>
{isMaliciousAdVoting ? (
<>
{eitherIdleState(VotingStatus.Voted) ? (
<Box>
<Text color="muted" fontSize="sm" mb={3}>
{t('Choose an option to vote')}
</Text>
<Stack spacing={3}>
{/* eslint-disable-next-line no-shadow */}
{options.map(({id, value}) => {
const isMine = id === selectedOption
return (
<Stack
isInline
spacing={2}
align="center"
bg={isMine ? 'blue.012' : 'gray.50'}
borderRadius="md"
minH={8}
px={3}
py={2}
zIndex={1}
>
<Flex
align="center"
justify="center"
bg={
isMine
? 'brandBlue.500'
: 'transparent'
}
borderRadius="full"
borderWidth={isMine ? 0 : '4px'}
borderColor="gray.100"
color="white"
w={4}
h={4}
>
{isMine && <OkIcon boxSize={3} />}
</Flex>
<Text
isTruncated
maxW="sm"
title={value.length > 50 ? value : ''}
>
{value}
</Text>
</Stack>
)
})}
</Stack>
</Box>
) : null}
</>
) : (
<Box>
<Text color="muted" fontSize="sm" mb={3}>
{t('Choose an option to vote')}
</Text>
{eitherIdleState(VotingStatus.Voted) ? (
<Stack spacing={3}>
{/* eslint-disable-next-line no-shadow */}
{options.map(({id, value}) => {
const isMine = id === selectedOption
return (
<Stack
isInline
spacing={2}
align="center"
bg={isMine ? 'blue.012' : 'gray.50'}
borderRadius="md"
minH={8}
px={3}
py={2}
zIndex={1}
>
<Flex
align="center"
justify="center"
bg={
isMine ? 'brandBlue.500' : 'transparent'
}
borderRadius="full"
borderWidth={isMine ? 0 : '4px'}
borderColor="gray.100"
color="white"
w={4}
h={4}
>
{isMine && <OkIcon boxSize={3} />}
</Flex>
<Text
isTruncated
maxW="sm"
title={value.length > 50 ? value : ''}
>
{value}
</Text>
</Stack>
)
})}
</Stack>
) : (
<RadioGroup
value={String(selectedOption)}
onChange={value => {
send('SELECT_OPTION', {
option: Number(value),
})
}}
>
<Stack spacing={2}>
{/* eslint-disable-next-line no-shadow */}
{options.map(({id, value}) => (
<VotingOption
key={id}
value={String(id)}
isDisabled={eitherIdleState(
VotingStatus.Pending,
VotingStatus.Starting,
VotingStatus.Voted
)}
annotation={
isMaxWinnerThreshold
? null
: t('{{count}} min. votes required', {
count: toPercent(
winnerThreshold / 100
),
})
}
>
{value}
</VotingOption>
))}
</Stack>
</RadioGroup>
)}
</Box>
)}
</VotingSkeleton>
)}
{eitherIdleState(
VotingStatus.Counting,
VotingStatus.Finishing,
VotingStatus.Archived,
VotingStatus.Terminating,
VotingStatus.Terminated
) && (
<VotingSkeleton isLoaded={isLoaded}>
<Stack spacing={3}>
<Text color="muted" fontSize="sm">
{t('Voting results')}
</Text>
<VotingResult votingService={service} spacing={3} />
</Stack>
</VotingSkeleton>
)}
<VotingSkeleton isLoaded={!actionsIsFetching}>
<Flex justify="space-between" align="center">
<Stack isInline spacing={2}>
{eitherIdleState(VotingStatus.Pending) && (
<PrimaryButton
loadingText={t('Launching')}
onClick={() => {
send('REVIEW_START_VOTING', {
from: coinbase,
})
}}
>
{t('Launch')}
</PrimaryButton>
)}
{eitherIdleState(VotingStatus.Open) &&
(isOracle ? (
<PrimaryButton
onClick={() => {
if (isMaliciousAdVoting) {
send('FORCE_REJECT')
}
send('REVIEW')
}}
>
{isMaliciousAdVoting ? t('Reject') : t('Vote')}
</PrimaryButton>
) : (
<Box>
<Tooltip
label={t(
'This vote is not available to you. Only validated identities randomly selected to the committee can vote.'
)}
placement="top"
zIndex="tooltip"
>
<PrimaryButton isDisabled>
{t('Vote')}
</PrimaryButton>
</Tooltip>
</Box>
))}
{eitherIdleState(VotingStatus.Counting) && canFinish && (
<PrimaryButton
isLoading={current.matches(
`mining.${VotingStatus.Finishing}`
)}
loadingText={t('Finishing')}
onClick={() => send('FINISH', {from: coinbase})}
>
{didDetermineWinner
? t('Finish voting')
: t('Claim refunds')}
</PrimaryButton>
)}
{eitherIdleState(
VotingStatus.Open,
VotingStatus.Voting,
VotingStatus.Voted,
VotingStatus.Counting
) &&
canProlong && (
<PrimaryButton
onClick={() => send('REVIEW_PROLONG_VOTING')}
>
{t('Prolong voting')}
</PrimaryButton>
)}
{(eitherIdleState(
VotingStatus.Voted,
VotingStatus.Voting
) ||
(eitherIdleState(VotingStatus.Counting) &&
!canProlong &&
!canFinish)) && (
<PrimaryButton as={Box} isDisabled>
{t('Vote')}
</PrimaryButton>
)}
{!eitherIdleState(
VotingStatus.Terminated,
VotingStatus.Terminating
) &&
canTerminate && (
<PrimaryButton
colorScheme="red"
variant="solid"
_active={{}}
onClick={() => send('TERMINATE')}
>
{t('Terminate')}
</PrimaryButton>
)}
</Stack>
<Stack isInline spacing={3} align="center">
{eitherIdleState(
VotingStatus.Archived,
VotingStatus.Terminated
) &&
!didDetermineWinner && (
<Text color="red.500">
{t('No winner selected')}
</Text>
)}
<VDivider />
<Stack isInline spacing={2} align="center">
{didDetermineWinner ? (
<UserTickIcon color="muted" boxSize={4} />
) : (
<UserIcon color="muted" boxSize={4} />
)}
<Text as="span">
{/* eslint-disable-next-line no-nested-ternary */}
{eitherIdleState(VotingStatus.Counting) ? (
<>
{t('{{count}} published votes', {
count: accountableVoteCount,
})}{' '}
{t('out of {{count}}', {
count: voteProofsCount,
})}
</>
) : eitherIdleState(
VotingStatus.Pending,
VotingStatus.Open,
VotingStatus.Voting,
VotingStatus.Voted
) ? (
t('{{count}} votes', {
count: voteProofsCount,
})
) : (
t('{{count}} published votes', {
count: accountableVoteCount,
})
)}
</Text>
</Stack>
</Stack>
</Flex>
</VotingSkeleton>
<VotingSkeleton isLoaded={isLoaded}>
<Stack spacing={5}>
<Box>
<Text fontWeight={500}>{t('Recent transactions')}</Text>
</Box>
<Table style={{tableLayout: 'fixed', fontWeight: 500}}>
<Thead>
<Tr>
<RoundedTh isLeft>{t('Transaction')}</RoundedTh>
<RoundedTh>{t('Date and time')}</RoundedTh>
<RoundedTh isRight textAlign="right">
{t('Amount')}
</RoundedTh>
</Tr>
</Thead>
<Tbody>
{balanceUpdates.map(
({
hash,
type,
timestamp,
from,
amount,
fee,
tips,
balanceChange = 0,
contractCallMethod,
}) => {
const isSender = areSameCaseInsensitive(
from,
coinbase
)
const txCost =
(isSender ? -amount : 0) + balanceChange
const totalTxCost =
txCost - ((isSender ? fee : 0) + tips)
const isCredit = totalTxCost > 0
const color =
// eslint-disable-next-line no-nested-ternary
totalTxCost === 0
? 'brandGray.500'
: isCredit
? 'blue.500'
: 'red.500'
return (
<Tr key={hash}>
<OraclesTxsValueTd>
<Stack isInline>
<Flex
align="center"
justify="center"
bg={isCredit ? 'blue.012' : 'red.012'}
color={color}
borderRadius="lg"
minH={8}
minW={8}
>
{isSender ? (
<ArrowUpIcon boxSize={5} />
) : (
<ArrowDownIcon boxSize={5} />
)}
</Flex>
<Box isTruncated>
{contractCallMethod ? (
<Text>
{
ContractCallMethod[
contractCallMethod
]
}
</Text>
) : (
<Text>
{ContractTransactionType[type]}
</Text>
)}
<SmallText isTruncated title={from}>
{hash}
</SmallText>
</Box>
</Stack>
</OraclesTxsValueTd>
<OraclesTxsValueTd>
<Text>
{new Date(timestamp).toLocaleString()}
</Text>
</OraclesTxsValueTd>
<OraclesTxsValueTd textAlign="right">
<Text
color={color}
overflowWrap="break-word"
>
{toLocaleDna(i18n.language, {
signDisplay: 'exceptZero',
})(txCost)}
</Text>
{isSender && (
<SmallText>
{t('Fee')} {toDna(fee + tips)}
</SmallText>
)}
</OraclesTxsValueTd>
</Tr>
)
}
)}
{balanceUpdates.length === 0 && (
<Tr>
<OraclesTxsValueTd colSpan={3}>
<FillCenter py={12}>
<Stack spacing={4} align="center">
<CoinsLgIcon
boxSize={20}
color="gray.100"
/>
<Text color="muted">
{t('No transactions')}
</Text>
</Stack>
</FillCenter>
</OraclesTxsValueTd>
</Tr>
)}
</Tbody>
</Table>
</Stack>
</VotingSkeleton>
</Stack>
</Box>
<VotingSkeleton isLoaded={isLoaded} h={isLoaded ? 'auto' : 'lg'}>
<Box mt={3}>
<Box mt={-2} mb={4}>
<IconButton
icon={<RefreshIcon boxSize={5} />}
px={1}
pr={3}
_focus={null}
onClick={() => {
send('REFRESH')
refetchActions()
}}
>
{t('Refresh')}
</IconButton>
</Box>
{!isClosed && (
<Stat mb={8}>
<StatLabel as="div" color="muted" fontSize="md">
<Stack isInline spacing={2} align="center">
<StarIcon boxSize={4} color="white" />
<Text fontWeight={500}>{t('Prize pool')}</Text>
</Stack>
</StatLabel>
<StatNumber fontSize="base" fontWeight={500}>
{toDna(estimatedTotalReward)}
</StatNumber>
<Box mt={1}>
<IconButton
icon={<AddFundIcon boxSize={5} />}
onClick={() => {
send('ADD_FUND')
}}
>
{t('Add funds')}
</IconButton>
</Box>
</Stat>
)}
<Stack spacing={6}>
{!isClosed && (
<Stat>
<StatLabel color="muted" fontSize="md">
<Tooltip
label={
// eslint-disable-next-line no-nested-ternary
Number(votingMinPayment) > 0
? isMaxWinnerThreshold
? t('Deposit will be refunded')
: t(
'Deposit will be refunded if your vote matches the majority'
)
: t('Free voting')
}
placement="top"
>
<Text
as="span"
borderBottom="dotted 1px"
borderBottomColor="muted"
cursor="help"
>
{t('Voting deposit')}
</Text>
</Tooltip>
</StatLabel>
<StatNumber fontSize="base" fontWeight={500}>
{toDna(votingMinPayment)}
</StatNumber>
</Stat>
)}
{!isClosed && (
<Stat>
<StatLabel color="muted" fontSize="md">
<Tooltip
label={t('Including your Voting deposit')}
placement="top"
>
<Text
as="span"
borderBottom="dotted 1px"
borderBottomColor="muted"
cursor="help"
>
{t('Min reward')}
</Text>
</Tooltip>
</StatLabel>
<StatNumber fontSize="base" fontWeight={500}>
{toDna(estimatedOracleReward)}
</StatNumber>
</Stat>
)}
{!isClosed && (
<Stat>
<StatLabel color="muted" fontSize="md">
{isMaxWinnerThreshold ? (
<Text as="span">{t('Your max reward')}</Text>
) : (
<Tooltip
label={t(
`Including a share of minority voters' deposit`
)}
placement="top"
>
<Text
as="span"
borderBottom="dotted 1px"
borderBottomColor="muted"
cursor="help"
>
{t('Max reward')}
</Text>
</Tooltip>
)}
</StatLabel>
<StatNumber fontSize="base" fontWeight={500}>
{toDna(estimatedMaxOracleReward)}
</StatNumber>
</Stat>
)}
<AsideStat
label={t('Committee size')}
value={t('{{committeeSize}} oracles', {committeeSize})}
/>
<AsideStat
label={t('Quorum required')}
value={t('{{count}} votes', {
count: quorumVotesCount({quorum, committeeSize}),
})}
/>
<AsideStat
label={t('Majority threshold')}
value={
isMaxWinnerThreshold
? t('N/A')
: toPercent(winnerThreshold / 100)
}
/>
{isClosed && totalReward && (
<AsideStat
label={t('Prize paid')}
value={toDna(totalReward)}
/>
)}
</Stack>
</Box>
</VotingSkeleton>
</Stack>
</Stack>
</Page>
</Layout>
<VoteDrawer
isOpen={
eitherState(current, 'review', `mining.${VotingStatus.Voting}`) &&
!eitherState(
current,
`mining.${VotingStatus.Voting}.reviewPendingVote`
)
}
onClose={() => {
send('CANCEL')
}}
// eslint-disable-next-line no-shadow
option={options.find(({id}) => id === selectedOption)?.value}
from={coinbase}
to={contractHash}
deposit={votingMinPayment}
publicVotingDuration={publicVotingDuration}
finishDate={finishDate}
finishCountingDate={finishCountingDate}
isLoading={current.matches(`mining.${VotingStatus.Voting}`)}
onVote={() => {
send('VOTE', {privateKey})
}}
/>
<AddFundDrawer
isOpen={eitherState(
current,
'funding',
`mining.${VotingStatus.Funding}`
)}
onClose={() => {
send('CANCEL')
}}
from={coinbase}
to={contractHash}
available={identityBalance}
ownerFee={ownerFee}
isLoading={current.matches(`mining.${VotingStatus.Funding}`)}
onAddFund={({amount}) => {
send('ADD_FUND', {amount, privateKey})
}}
/>
<LaunchDrawer
isOpen={eitherState(
current,
`idle.${VotingStatus.Pending}.review`,
`mining.${VotingStatus.Starting}`
)}
onClose={() => {
send('CANCEL')
}}
balance={contractBalance}
requiredBalance={votingMinBalance(minOracleReward, committeeSize)}
ownerFee={ownerFee}
from={coinbase}
available={identityBalance}
isLoading={current.matches(`mining.${VotingStatus.Starting}`)}
onLaunch={({amount}) => {
send('START_VOTING', {amount, privateKey})
}}
/>
<FinishDrawer
isOpen={eitherState(
current,
`idle.${VotingStatus.Counting}.finish`,
`mining.${VotingStatus.Finishing}`
)}
onClose={() => {
send('CANCEL')
}}
from={coinbase}
available={identityBalance}
isLoading={current.matches(`mining.${VotingStatus.Finishing}`)}
onFinish={() => {
send('FINISH', {privateKey})
}}
hasWinner={didDetermineWinner}
/>
<ProlongDrawer
isOpen={eitherState(
current,
'prolong',
`mining.${VotingStatus.Prolonging}`
)}
onClose={() => {
send('CANCEL')
}}
from={coinbase}
available={identityBalance}
isLoading={current.matches(`mining.${VotingStatus.Prolonging}`)}
onProlong={() => {
send('PROLONG_VOTING', {privateKey})
}}
/>
<TerminateDrawer
isOpen={eitherState(
current,
`idle.terminating`,
`mining.${VotingStatus.Terminating}`
)}
onClose={() => {
send('CANCEL')
}}
contractAddress={contractHash}
isLoading={current.matches(`mining.${VotingStatus.Terminating}`)}
onTerminate={() => {
send('TERMINATE', {privateKey})
}}
/>
{pendingVote && (
<ReviewNewPendingVoteDialog
isOpen={eitherState(
current,
`mining.${VotingStatus.Voting}.reviewPendingVote`
)}
onClose={() => {
send('GOT_IT')
}}
vote={pendingVote}
startCounting={finishDate}
finishCounting={finishCountingDate}
/>
)}
{adCid && (
<AdPreview
ad={{...ad, author: issuer}}
isMalicious={isMaliciousAdVoting}
{...adPreviewDisclosure}
/>
)}
<Dialog
isOpen={eitherIdleState('redirecting')}
onClose={() => send('CANCEL')}
>
<DialogHeader>{t('Leaving Idena')}</DialogHeader>
<DialogBody>
<Text>{t(`You're about to leave Idena.`)}</Text>
<Text>{t(`Are you sure?`)}</Text>
</DialogBody>
<DialogFooter>
<SecondaryButton onClick={() => send('CANCEL')}>
{t('Cancel')}
</SecondaryButton>
<PrimaryButton onClick={() => send('CONTINUE')}>
{t('Continue')}
</PrimaryButton>
</DialogFooter>
</Dialog>
</>
)
}
Example #28
Source File: Membership.js From web-client with Apache License 2.0 | 4 votes |
ProjectMembership = () => {
const { projectId } = useParams();
const [users] = useFetch(`/users`)
const [members, updateMembers] = useFetch(`/projects/${projectId}/users`)
const [savedProject] = useFetch(`/projects/${projectId}`);
const [availableUsers, setAvailableUsers] = useState([]);
const handleOnClick = ev => {
ev.preventDefault();
const userId = document.getElementById('userId').value;
const userData = { userId: userId };
secureApiFetch(`/projects/${projectId}/users`, {
method: 'POST',
body: JSON.stringify(userData)
}).then(() => {
updateMembers()
})
}
const handleDelete = (member) => {
secureApiFetch(`/projects/${projectId}/users/${member.membership_id}`, {
method: 'DELETE'
}).then(() => {
updateMembers()
})
}
useEffect(() => {
if (members && users && users.length > 0) {
const memberIds = members.reduce((list, user) => [...list, user.id], []);
setAvailableUsers(users.filter(user => !memberIds.includes(user.id)));
}
}, [members, users]);
return <div>
<PageTitle value="Project membership" />
<div className="heading">
<Breadcrumb>
<Link to="/projects">Projects</Link>
{savedProject && <Link to={`/projects/${savedProject.id}`}>{savedProject.name}</Link>}
</Breadcrumb>
</div>
<Title title='Members' />
{availableUsers.length > 0 ?
<form>
<label>
Select user
<Select id="userId">
{availableUsers && availableUsers.map((user, index) =>
<option key={index} value={user.id}>{user.full_name}</option>
)}
</Select>
</label>
<PrimaryButton onClick={handleOnClick} leftIcon={<IconPlus />}>Add as member</PrimaryButton>
</form> :
<Alert status="info">
<AlertIcon />
All users have been added to the project.
</Alert>
}
<Table>
<Thead>
<Tr>
<Th style={{ width: '80px' }}> </Th>
<Th>Name</Th>
<Th>Role</Th>
<Th> </Th>
</Tr>
</Thead>
<Tbody>
{null === members &&
<LoadingTableRow numColumns={4} />}
{null !== members && 0 === members.length &&
<NoResultsTableRow numColumns={4} />}
{members && members.map((member, index) =>
<Tr key={index}>
<Td><UserAvatar email={member.email} /></Td>
<Td><UserLink userId={member.id}>{member.full_name}</UserLink></Td>
<Td><UserRoleBadge role={member.role} /></Td>
<Td textAlign="right">
<DeleteIconButton onClick={() => handleDelete(member)} />
</Td>
</Tr>
)
}
</Tbody>
</Table>
</div>
}
Example #29
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>
}