@chakra-ui/react#Tab JavaScript Examples
The following examples show how to use
@chakra-ui/react#Tab.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: components.js From idena-web with MIT License | 6 votes |
AdFormTab = forwardRef(({isSelected, ...props}, ref) => (
<Tab
ref={ref}
isSelected={isSelected}
color="muted"
fontWeight={500}
py={2}
px={4}
rounded="md"
_selected={{bg: 'brandBlue.50', color: 'brandBlue.500'}}
{...props}
/>
))
Example #2
Source File: components.js From idena-web with MIT License | 6 votes |
GetInvitationTab = React.forwardRef(
({iconSelected, icon, title, ...props}, ref) => {
const isMobile = useBreakpointValue([true, false])
const tabProps = useTab({...props, ref})
const isSelected = !!tabProps['aria-selected']
return (
<Tab
color="gray.300"
fontWeight="500"
_selected={{
color: 'blue.500',
bg: ['gray.500', 'gray.50'],
borderRadius: 'md',
}}
mr={[0, 2]}
w={['25%', null]}
{...tabProps}
py={3 / 2}
>
{isMobile
? React.cloneElement(isSelected ? iconSelected : icon, {
boxSize: 6,
color: isSelected ? 'white' : 'gray.500',
})
: title}
</Tab>
)
}
)
Example #3
Source File: components.js From idena-web with MIT License | 6 votes |
export function TransactionsTab(props) {
return (
<Tab
color={['gray.500', 'muted']}
fontWeight="500"
fontSize={['mobile', 'md']}
_selected={{
color: ['white', 'blue.500'],
bg: ['gray.500', 'gray.50'],
borderRadius: 'md',
}}
mr={[0, 2]}
w={['50%', 'auto']}
py={3 / 2}
{...props}
/>
)
}
Example #4
Source File: ouput.js From GitMarkonics with MIT License | 6 votes |
Output = (file) => {
// const getMarkdownText = () => {
// var rawMarkup = marked("_Nothing_ to show ");
// if (file.file) {
// rawMarkup = marked(file.file);
// // console.log("file is", file);
// } else {
// rawMarkup = marked("_Nothing_ to show ");
// }
// return { __html: rawMarkup };
// };
return (
<Box flex="1" bg="white" border="1px" borderColor="gray.10" p={5}>
<Tabs>
<TabList>
<Tab>Output</Tab>
{/* <Tab>Preview</Tab> */}
</TabList>
<TabPanels>
<TabPanel>
<Text whiteSpace="pre-line">{file.file}</Text>
</TabPanel>
{/* <TabPanel>
<div dangerouslySetInnerHTML={getMarkdownText()} />
</TabPanel> */}
</TabPanels>
</Tabs>
</Box>
);
}
Example #5
Source File: Details.js From web-client with Apache License 2.0 | 5 votes |
VulnerabilityTemplateDetails = () => {
const navigate = useNavigate();
const { templateId } = useParams();
const [vulnerability] = useFetch(`/vulnerabilities/${templateId}`)
const cloneProject = async (templateId) => {
secureApiFetch(`/vulnerabilities/${templateId}/clone`, { method: 'POST' })
.then(resp => resp.json())
.then(data => {
navigate(`/vulnerabilities/${data.vulnerabilityId}/edit`);
});
}
const destroy = useDelete('/vulnerabilities/', () => {
navigate('/vulnerabilities/templates');
});
if (!vulnerability) return <Loading />
if (vulnerability && !vulnerability.is_template) {
return <Navigate to={`/vulnerabilities/${vulnerability.id}`} />
}
return (
<>
<div>
<div className='heading'>
<Breadcrumb>
<Link to="/vulnerabilities">Vulnerabilities</Link>
<Link to="/vulnerabilities/templates">Templates</Link>
</Breadcrumb>
<ButtonGroup>
<PrimaryButton onClick={() => cloneProject(vulnerability.id)} leftIcon={<IconPlusCircle />}>Clone and edit</PrimaryButton>
<RestrictedComponent roles={['administrator', 'superuser', 'user']}>
<LinkButton href={`/vulnerabilities/${vulnerability.id}/edit`}>Edit</LinkButton>
<DeleteButton onClick={() => destroy(vulnerability.id)} />
</RestrictedComponent>
</ButtonGroup>
</div>
<article>
<PageTitle value={`${vulnerability.summary} vulnerability template`} />
<Title type='Vulnerability template' title={vulnerability.summary} icon={<IconFlag />} />
<Tabs>
<TabList>
<Tab>Description</Tab>
<Tab>Remediation</Tab>
</TabList>
<TabPanels>
<TabPanel>
<VulnerabilityDescriptionPanel vulnerability={vulnerability} />
</TabPanel>
<TabPanel>
<VulnerabilityRemediationPanel vulnerability={vulnerability} />
</TabPanel>
</TabPanels>
</Tabs>
</article>
</div>
</>
)
}
Example #6
Source File: Profile.js From web-client with Apache License 2.0 | 5 votes |
UserProfile = () => {
const navigate = useNavigate();
const { userId } = useParams();
const [user] = useFetch(`/users/${userId}`)
const [auditLog] = useFetch(`/users/${userId}/activity`)
const deleteUser = useDelete('/users/');
const onDeleteButtonClick = ev => {
ev.preventDefault();
deleteUser(userId).then(() => {
navigate('/users');
})
}
if (!user) return <Loading />
return <>
<div className='heading'>
<Breadcrumb>
<Link to="/users">Users</Link>
</Breadcrumb>
<ButtonGroup>
<RestrictedComponent roles={['administrator', 'superuser', 'user']}>
<LinkButton href={`/users/${user.id}/edit`}>Edit</LinkButton>
<DeleteButton onClick={onDeleteButtonClick} />
</RestrictedComponent>
</ButtonGroup>
</div>
<div>
<PageTitle value={`${user.full_name} user`} />
<Title type='User profile' title={user.full_name}
icon={<UserAvatar email={user.email} />} />
<Tabs isLazy>
<TabList>
<Tab>Details</Tab>
<Tab>Activity</Tab>
</TabList>
<TabPanels>
<TabPanel>
<div className="grid grid-two">
<div>
<h4>Properties</h4>
<dl>
<dt>Short bio</dt>
<dd>{user.short_bio ? user.short_bio : <EmptyField />}</dd>
<dt>Role</dt>
<dd><UserRoleBadge role={user.role} /><br /></dd>
<dt>Timezone</dt>
<dd>{user.timezone}</dd>
<dt>Active?</dt>
<dd><BooleanText value={user.active} /></dd>
<dt>2FA enabled?</dt>
<dd><BooleanText value={user.mfa_enabled} /></dd>
</dl>
</div>
<div>
<TimestampsSection entity={user} />
</div>
</div>
</TabPanel>
<TabPanel>
<h4>Activity (<Link to="/auditlog">view full audit log</Link>)</h4>
{auditLog ? <AuditLogsTable auditLog={auditLog} hideUserColumns="true" /> : <Loading />}
</TabPanel>
</TabPanels>
</Tabs>
</div>
</>
}
Example #7
Source File: Details.js From web-client with Apache License 2.0 | 5 votes |
ReportTemplateDetails = () => {
const navigate = useNavigate();
const { templateId } = useParams();
const [vulnerability] = useFetch(`/vulnerabilities/${templateId}`)
const cloneProject = async (templateId) => {
secureApiFetch(`/vulnerabilities/${templateId}/clone`, { method: 'POST' })
.then(resp => resp.json())
.then(data => {
navigate(`/vulnerabilities/${data.vulnerabilityId}/edit`);
});
}
const destroy = useDelete('/vulnerabilities/', () => {
navigate('/vulnerabilities/templates');
});
if (!vulnerability) return <Loading />
if (vulnerability && !vulnerability.is_template) {
return <Navigate to={`/vulnerabilities/${vulnerability.id}`} />
}
return (
<>
<div>
<div className='heading'>
<Breadcrumb>
<Link to="/vulnerabilities">Vulnerabilities</Link>
<Link to="/vulnerabilities/templates">Templates</Link>
</Breadcrumb>
<ButtonGroup>
<PrimaryButton onClick={() => cloneProject(vulnerability.id)} leftIcon={<IconPlusCircle />}>Clone and edit</PrimaryButton>
<RestrictedComponent roles={['administrator', 'superuser', 'user']}>
<LinkButton href={`/vulnerabilities/${vulnerability.id}/edit`}>Edit</LinkButton>
<DeleteButton onClick={() => destroy(vulnerability.id)} />
</RestrictedComponent>
</ButtonGroup>
</div>
<article>
<PageTitle value={`${vulnerability.summary} vulnerability template`} />
<Title type='Vulnerability template' title={vulnerability.summary} icon={<IconFlag />} />
<Tabs>
<TabList>
<Tab>Description</Tab>
<Tab>Remediation</Tab>
</TabList>
<TabPanels>
<TabPanel>
</TabPanel>
<TabPanel>
</TabPanel>
</TabPanels>
</Tabs>
</article>
</div>
</>
)
}
Example #8
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 #9
Source File: Details.js From web-client with Apache License 2.0 | 5 votes |
TemplateDetails = () => {
const navigate = useNavigate();
const { templateId } = useParams();
const [template] = useFetch(`/projects/${templateId}`)
const cloneProject = async (templateId) => {
secureApiFetch(`/projects/${templateId}/clone`, { method: 'POST' })
.then(resp => resp.json())
.then(data => {
navigate(`/projects/${data.projectId}/edit`);
});
}
const destroy = useDelete('/projects/', () => {
navigate('/projects/templates');
});
if (template && !template.is_template) {
return <Navigate to={`/projects/${template.id}`} />
}
return <>
<div className='heading'>
<Breadcrumb>
<Link to="/projects">Projects</Link>
<Link to="/projects/templates">Templates</Link>
</Breadcrumb>
{template &&
<ButtonGroup>
<PrimaryButton onClick={() => cloneProject(template.id)} leftIcon={<IconPlusCircle />}>Create project from template</PrimaryButton>
<LinkButton href={`/projects/${template.id}/edit`}>Edit</LinkButton>
<DeleteButton onClick={() => destroy(template.id)} />
</ButtonGroup>
}
</div>
{!template ?
<Loading /> :
<article>
<PageTitle value={`${template.name} project template`} />
<Title title={template.name} type='Project template' icon={<IconFolder />} />
<Tabs>
<TabList>
<Tab>Details</Tab>
<Tab>Tasks</Tab>
</TabList>
<TabPanels>
<TabPanel><ProjectDetailsTab project={template} /></TabPanel>
<TabPanel><ProjectTasks project={template} /></TabPanel>
</TabPanels>
</Tabs>
</article>}
</>
}
Example #10
Source File: Report.js From web-client with Apache License 2.0 | 5 votes |
ProjectReport = () => {
const { projectId } = useParams();
const [project, setProject] = useState(null);
useEffect(() => {
secureApiFetch(`/projects/${projectId}`, {
method: 'GET',
})
.then(resp => resp.json())
.then(json => {
setProject(json);
});
}, [projectId, setProject]);
if (!project) {
return <Loading />
}
return (
<>
<PageTitle value={`Report ${project.name}`} />
<div className='heading'>
<Breadcrumb>
<Link to="/projects">Projects</Link>
<Link to={`/projects/${project.id}`}>{project.name}</Link>
</Breadcrumb>
</div>
<Title type="Project reporting" title="Project report"
icon={<IconReport />} />
<Tabs>
<TabList>
<Tab>Preview</Tab>
<Tab>Revisions</Tab>
{false && <Tab>Configuration</Tab>}
</TabList>
<TabPanels>
<TabPanel>
<ReportPreview projectId={projectId} />
</TabPanel>
<TabPanel>
<ReportRevisions projectId={projectId} />
</TabPanel>
{false &&
<TabPanel>
<ReportConfigurationForm projectId={projectId} />
</TabPanel>
}
</TabPanels>
</Tabs>
</>
)
}
Example #11
Source File: Details.js From web-client with Apache License 2.0 | 4 votes |
CommandDetails = () => {
const { commandId } = useParams();
const navigate = useNavigate();
const [command] = useFetch(`/commands/${commandId}`)
const deleteClient = useDelete(`/commands/`)
const handleDelete = async () => {
const confirmed = await deleteClient(commandId);
if (confirmed)
navigate('/commands');
}
if (!command) {
return <Loading />
}
return <div>
<div className='heading'>
<Breadcrumb>
<Link to="/commands">Commands</Link>
</Breadcrumb>
<ButtonGroup>
<RestrictedComponent roles={['administrator', 'superuser', 'user']}>
<EditButton onClick={(ev) => {
ev.preventDefault();
navigate(`/commands/${command.id}/edit`)
}}>Edit</EditButton>
<DeleteButton onClick={handleDelete} />
</RestrictedComponent>
</ButtonGroup>
</div>
<article>
<div>
<PageTitle value={`${command.name} command`} />
<Title type='Command' title={command.name} icon={<IconBriefcase />} />
<Tags values={command.tags} />
</div>
<Tabs>
<TabList>
<Tab>Details</Tab>
<Tab>Run instructions</Tab>
<Tab>Command outputs</Tab>
<Tab>Terminal</Tab>
</TabList>
<TabPanels>
<TabPanel>
<div className="grid grid-two">
<div>
<dl>
<dt>Description</dt>
<dd>{command.description ? <ReactMarkdown>{command.description}</ReactMarkdown> : <EmptyField />}</dd>
{command.output_parser && <>
<dt>Output parser support</dt>
<dl>Yes ({command.output_parser})</dl>
</>}
{command.more_info_url && <>
<dt>More information URL</dt>
<dl>{command.more_info_url ? <ExternalLink href={command.more_info_url}>{command.more_info_url}</ExternalLink> : <EmptyField />}</dl>
</>}
{CommandService.hasCommand(command) && <>
{CommandService.isHost(command) && <>
<dt>Command line example</dt>
<dd>
<ShellCommand>{HostCommandLineGenerator.generateEntryPoint(command)} {HostCommandLineGenerator.renderArguments(command)}</ShellCommand>
</dd>
</>}
<dt>Command line example using rmap CLI</dt>
<dd>
<ShellCommand>{CommandService.generateEntryPoint(command)} {CommandService.renderArguments(command)}</ShellCommand>
</dd>
</>}
</dl>
</div>
<div>
<h4>Relations</h4>
<dl>
<dt>Created by</dt>
<dd><UserLink userId={command.creator_uid}>{command.creator_full_name}</UserLink></dd>
</dl>
<TimestampsSection entity={command} />
</div>
</div>
</TabPanel>
<TabPanel>
<CommandInstructions command={command} />
</TabPanel>
<TabPanel>
<CommandOutputs command={command} />
</TabPanel>
<TabPanel>
<CommandTerminal commands={[]} />
</TabPanel>
</TabPanels>
</Tabs>
</article>
</div >
}
Example #12
Source File: Details.js From web-client with Apache License 2.0 | 4 votes |
VulnerabilityDetails = () => {
const navigate = useNavigate();
const { vulnerabilityId } = useParams();
const [vulnerability, updateVulnerability] = useFetch(`/vulnerabilities/${vulnerabilityId}`)
const deleteVulnerability = useDelete(`/vulnerabilities/`)
const parentType = 'vulnerability';
const parentId = vulnerabilityId;
const [attachments, reloadAttachments] = useFetch(`/attachments?parentType=${parentType}&parentId=${parentId}`)
const handleDelete = async () => {
const confirmed = await deleteVulnerability(vulnerabilityId);
if (confirmed)
navigate('/vulnerabilities')
}
const onStatusChange = ev => {
const [status, substatus] = ev.target.value.split('-');
secureApiFetch(`/vulnerabilities/${vulnerability.id}`, {
method: 'PATCH',
body: JSON.stringify({ status, substatus })
})
.then(() => {
actionCompletedToast("The status has been transitioned.");
updateVulnerability()
})
.catch(err => console.error(err))
}
if (!vulnerability) return <Loading />
if (vulnerability && vulnerability.is_template) {
return <Navigate to={`/vulnerabilities/templates/${vulnerability.id}`} />
}
return <div>
<div className='heading'>
<Breadcrumb>
<Link to="/vulnerabilities">Vulnerabilities</Link>
</Breadcrumb>
<HStack alignItems='flex-end'>
<RestrictedComponent roles={['administrator', 'superuser', 'user']}>
<EditButton onClick={(ev) => {
ev.preventDefault();
navigate(`/vulnerabilities/${vulnerability.id}/edit`)
}}>Edit</EditButton>
<label>Transition to
<Select onChange={onStatusChange} value={vulnerability.status + '-' + vulnerability.substatus}>
{VulnerabilityStatuses.map(status =>
<option key={`vulnstatus_${status.id}`} value={status.id}>{status.name}</option>
)}
</Select>
</label>
<DeleteButton onClick={handleDelete} />
</RestrictedComponent>
</HStack>
</div>
<article>
<PageTitle value={`${vulnerability.summary} vulnerability`} />
<Title type='Vulnerability' title={vulnerability.external_id ? <><strong>{vulnerability.external_id.toUpperCase()}</strong> {vulnerability.summary}</> : vulnerability.summary} icon={<IconFlag />} />
<Tag size="sm" colorScheme="blue">{vulnerability.visibility}</Tag> <Tags values={vulnerability.tags} />
<Tabs>
<TabList>
<Tab>Description</Tab>
<Tab>Remediation</Tab>
<Tab>Notes</Tab>
<Tab>Attachments</Tab>
</TabList>
<TabPanels>
<TabPanel>
<VulnerabilityDescriptionPanel vulnerability={vulnerability} />
</TabPanel>
<TabPanel>
<VulnerabilityRemediationPanel vulnerability={vulnerability} />
</TabPanel>
<TabPanel>
<VulnerabilitiesNotesTab vulnerability={vulnerability} />
</TabPanel>
<TabPanel>
<AttachmentsDropzone parentType={parentType} parentId={parentId} onUploadFinished={reloadAttachments} />
<h4><IconDocument />Attachment list</h4>
<AttachmentsTable attachments={attachments} reloadAttachments={reloadAttachments} />
</TabPanel>
</TabPanels>
</Tabs>
</article>
</div >
}
Example #13
Source File: Details.js From web-client with Apache License 2.0 | 4 votes |
TaskDetails = () => {
const loggedInUser = Auth.getLoggedInUser();
const navigate = useNavigate();
const { taskId } = useParams();
const [task, fetchTask] = useFetch(`/tasks/${taskId}`)
const [users] = useFetch(`/users`)
const [project, setProject] = useState(null);
const [command, setCommand] = useState(null);
const parentType = 'task';
const parentId = taskId;
const [attachments, reloadAttachments] = useFetch(`/attachments?parentType=${parentType}&parentId=${parentId}`)
const destroy = useDelete('/tasks/', fetchTask);
const handleDelete = () => {
destroy(task.id);
navigate('/tasks');
}
const onAssigneeChange = ev => {
const assigneeUid = ev.target.value;
secureApiFetch(`/tasks/${task.id}`, {
method: 'PATCH',
body: JSON.stringify({ assignee_uid: '' === assigneeUid ? null : assigneeUid })
})
.then(() => {
actionCompletedToast("The assignee has been updated.");
fetchTask()
})
.catch(err => console.error(err))
}
const onStatusChange = ev => {
const status = ev.target.value;
secureApiFetch(`/tasks/${task.id}`, {
method: 'PATCH',
body: JSON.stringify({ status: status })
})
.then(() => {
actionCompletedToast("The status has been transitioned.");
fetchTask()
})
.catch(err => console.error(err))
}
useEffect(() => {
if (task) {
if (task.command_id) {
secureApiFetch(`/commands/${task.command_id}`, { method: 'GET' })
.then(resp => resp.json())
.then(command => setCommand(command))
.catch(err => console.error(err))
}
secureApiFetch(`/projects/${task.project_id}`, { method: 'GET' })
.then(resp => resp.json())
.then(project => setProject(project))
.catch(err => console.error(err))
}
}, [task])
return <div>
<div className="heading">
<Breadcrumb>
<Link to="/tasks">Tasks</Link>
{project && <Link to={`/projects/${project.id}`}>{project.name}</Link>}
</Breadcrumb>
{task && users &&
<HStack alignItems='flex-end'>
<RestrictedComponent roles={['administrator', 'superuser', 'user']}>
<Link to={`/tasks/${task.id}/edit`}>Edit</Link>
<label>Transition to
<Select onChange={onStatusChange} value={task.status}>
{TaskStatuses.map((status, index) =>
<option key={index} value={status.id}>{status.name}</option>
)}
</Select>
</label>
<DeleteButton onClick={() => handleDelete(task.id)} />
</RestrictedComponent>
</HStack>
}
</div>
{!task ? <Loading /> :
<article>
<PageTitle value={`${task.summary} task`} />
<Title title={task.summary} type='Task' icon={<IconClipboard />} />
<Tabs>
<TabList>
<Tab>Details</Tab>
{null !== command && <Tab>Command instructions</Tab>}
<Tab>Attachments</Tab>
</TabList>
<TabPanels>
<TabPanel>
<div className="grid grid-two">
<div>
<h4>Description</h4>
{task.description ? <ReactMarkdown>{task.description}</ReactMarkdown> : <EmptyField />}
<h4>Priority</h4>
<p>{task.priority}</p>
<h4>Status</h4>
<p style={{ display: 'flex', alignItems: 'center', columnGap: 'var(--margin)' }}>
<TaskStatusFormatter task={task} />
</p>
{task.command_id && <>
<h4>Command</h4>
<CommandBadge command={{ id: task.command_id, name: task.command_name }} />
</>}
</div>
<div>
<h4>People</h4>
<dl>
<dt>Created by</dt>
<dd><UserLink userId={task.creator_uid}>{task.creator_full_name}</UserLink></dd>
<dt>Assigned to</dt>
<dd>
{users &&
<Select onChange={onAssigneeChange} defaultValue={task.assignee_uid}>
<option value="">(nobody)</option>
{users.map((user, index) =>
<option key={index} value={user.id}>{user.full_name}{user.id === loggedInUser.id ? " (You)" : ""}</option>
)}
</Select>}
</dd>
</dl>
<TimestampsSection entity={task} />
{task.due_date &&
<dl>
<dt>Due date</dt>
<dd><RelativeDateFormatter date={task.due_date} /></dd>
</dl>
}
</div>
</div>
</TabPanel>
{null !== command && <TabPanel>
<CommandInstructions command={command} task={task} />
</TabPanel>}
<TabPanel>
<AttachmentsDropzone parentType={parentType} parentId={parentId} onUploadFinished={reloadAttachments} />
<h4><IconDocument />Attachment list</h4>
<AttachmentsTable attachments={attachments} reloadAttachments={reloadAttachments} />
</TabPanel>
</TabPanels>
</Tabs>
</article>
}
</div>
}
Example #14
Source File: Details.js From web-client with Apache License 2.0 | 4 votes |
ProjectDetails = () => {
const navigate = useNavigate();
const { projectId } = useParams();
const { colorMode } = useColorMode()
const [project, updateProject] = useFetch(`/projects/${projectId}`)
const [users] = useFetch(`/projects/${projectId}/users`)
const destroy = useDelete(`/projects/`, updateProject);
const handleGenerateReport = () => {
navigate(`/projects/${project.id}/report`)
}
const handleManageTeam = () => {
navigate(`/projects/${project.id}/membership`)
}
const onArchiveButtonClick = (project) => {
secureApiFetch(`/projects/${project.id}`, {
method: 'PATCH',
body: JSON.stringify({ archived: !project.archived })
})
.then(() => {
updateProject();
actionCompletedToast('The project has been updated.');
})
.catch(err => console.error(err))
}
if (project && project.is_template) {
return <Navigate to={`/projects/templates/${project.id}`} />
}
return <>
<div className='heading'>
<Breadcrumb>
<Link to="/projects">Projects</Link>
</Breadcrumb>
{project && <>
<PageTitle value={`${project.name} project`} />
<ProjectTeam project={project} users={users} />
<ButtonGroup isAttached>
<RestrictedComponent roles={['administrator', 'superuser', 'user']}>
{!project.archived && <>
<LinkButton href={`/projects/${project.id}/edit`}>Edit</LinkButton>
<SecondaryButton onClick={handleGenerateReport} leftIcon={<IconClipboardCheck />}>Report</SecondaryButton>
<SecondaryButton onClick={handleManageTeam} leftIcon={<IconUserGroup />}>Membership</SecondaryButton>
</>}
<Menu>
<MenuButton as={IconButton} aria-label='Options' icon={<FontAwesomeIcon icon={faEllipsis} />} variant='outline' />
<MenuList>
<MenuItem onClick={() => onArchiveButtonClick(project)}>{project.archived ? 'Unarchive' : 'Archive'}</MenuItem>
<MenuItem icon={<FontAwesomeIcon icon={faTrash} />} color={colorMode === "light" ? "red.500" : "red.400"} onClick={() => destroy(project.id)}>Delete</MenuItem>
</MenuList>
</Menu>
</RestrictedComponent>
</ButtonGroup>
</>}
</div>
{!project ? <Loading /> :
<>
<Title title={project.name} type="Project" icon={<IconFolder />} />
<Tabs>
<TabList>
<Tab>Details</Tab>
<Tab>Targets</Tab>
<Tab>Tasks</Tab>
<Tab>Vulnerabilities</Tab>
<Tab>Notes</Tab>
<Tab>Attachments</Tab>
<Tab>Vault</Tab>
</TabList>
<TabPanels>
<TabPanel><ProjectDetailsTab project={project} /></TabPanel>
<TabPanel><ProjectTargets project={project} /></TabPanel>
<TabPanel><ProjectTasks project={project} /></TabPanel>
<TabPanel><ProjectVulnerabilities project={project} /></TabPanel>
<TabPanel><ProjectNotesTab project={project} /></TabPanel>
<TabPanel><ProjectAttachmentsTab project={project} /></TabPanel>
<TabPanel><ProjectVaultTab project={project} /></TabPanel>
</TabPanels>
</Tabs>
</>
}
</>
}
Example #15
Source File: Details.js From web-client with Apache License 2.0 | 4 votes |
ClientDetails = () => {
const { clientId } = useParams();
const navigate = useNavigate();
const [client] = useFetch(`/clients/${clientId}`);
const [contacts, fetchContacts] = useFetch(`/clients/${clientId}/contacts`);
const [contact, setContact] = useState(new Contact());
const onContactFormChange = ev => {
setContact({ ...contact, [ev.target.name]: ev.target.value });
}
const deleteClient = useDelete(`/clients/`)
const [logo, setLogo] = useState(null);
const [smallLogo, setSmallLogo] = useState(null);
const handleDelete = async () => {
const confirmed = await deleteClient(clientId);
if (confirmed)
navigate('/clients');
}
const onFormSubmit = ev => {
ev.preventDefault();
secureApiFetch(`/clients/${clientId}/contacts`, { method: 'POST', body: JSON.stringify(contact) })
.then(resp => {
if (resp.status === 201) {
setContact(new Contact());
fetchContacts();
actionCompletedToast(`The contact has been added.`);
} else {
errorToast("The contact could not be saved. Review the form data or check the application logs.")
}
})
}
const onContactDelete = contactId => {
secureApiFetch(`/contacts/${contactId}`, { method: 'DELETE' })
.then(() => {
fetchContacts();
actionCompletedToast("The contact has been deleted.");
})
.catch(err => console.error(err))
}
useEffect(() => {
if (client) {
if (client.small_logo_attachment_id) {
downloadAndDisplayLogo(client.small_logo_attachment_id, 'small_logo');
}
if (client.logo_attachment_id) {
downloadAndDisplayLogo(client.logo_attachment_id, 'logo');
}
}
}, [client]);
const downloadAndDisplayLogo = (logoId, type) => {
secureApiFetch(`/attachments/${logoId}`, { method: 'GET' })
.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 url = URL.createObjectURL(blob);
if (type === 'small_logo') {
setSmallLogo(url);
} else {
setLogo(url);
}
})
}
if (!client) {
return <Loading />
}
return <div>
<div className='heading'>
<Breadcrumb>
<Link to="/clients">Clients</Link>
</Breadcrumb>
<ButtonGroup>
<RestrictedComponent roles={['administrator', 'superuser', 'user']}>
<EditButton onClick={(ev) => {
ev.preventDefault();
navigate(`/clients/${client.id}/edit`)
}}>Edit</EditButton>
<DeleteButton onClick={handleDelete} />
</RestrictedComponent>
</ButtonGroup>
</div>
<article>
<div>
<PageTitle value={`${client.name} client`} />
<Title type='Client' title={client.name} icon={<IconBriefcase />} />
</div>
<Tabs isLazy>
<TabList>
<Tab>Details</Tab>
<Tab>Contacts</Tab>
<Tab>Projects</Tab>
</TabList>
<TabPanels>
<TabPanel>
<div className="grid grid-two">
<div>
<h4>Properties</h4>
<dl>
<dt>Address</dt>
<dd>{client.address ?? '-'}</dd>
<dt>URL</dt>
<dd><ExternalLink href={client.url}>{client.url}</ExternalLink></dd>
</dl>
<h4>Branding</h4>
<dl>
<dt>Main logo</dt>
<dd>{logo ? <img src={logo} alt="The main logo" /> : <EmptyField />}</dd>
<dt>Small logo</dt>
<dd>{smallLogo ? <img src={smallLogo} alt="The smaller version of the logo" /> : <EmptyField />}</dd>
</dl>
</div>
<div>
<h4>Relations</h4>
<dl>
<dt>Created by</dt>
<dd><UserLink userId={client.creator_uid}>{client.creator_full_name}</UserLink></dd>
</dl>
<TimestampsSection entity={client} />
</div>
</div>
</TabPanel>
<TabPanel>
<h4>Contacts</h4>
{contacts && <>
<form onSubmit={onFormSubmit}>
<Table>
<Thead>
<Tr>
<Th>Kind</Th>
<Th>Name</Th>
<Th>Role</Th>
<Th>Email</Th>
<Th>Phone</Th>
<Th> </Th>
</Tr>
</Thead>
<Tbody>
<Tr>
<Td>
<Select name="kind" onChange={onContactFormChange} value={contact.kind || ""} isRequired>
<option value="general">General</option>
<option value="technical">Technical</option>
<option value="billing">Billing</option>
</Select>
</Td>
<Td>
<Input type="text" name="name" onChange={onContactFormChange} value={contact.name || ""} isRequired />
</Td>
<Td>
<Input type="text" name="role" onChange={onContactFormChange} value={contact.role || ""} />
</Td>
<Td>
<Input type="email" name="email" onChange={onContactFormChange} value={contact.email || ""} isRequired />
</Td>
<Td>
<Input type="tel" name="phone" onChange={onContactFormChange} value={contact.phone || ""} />
</Td>
<Td>
<Button type="submit">Add</Button>
</Td>
</Tr>
{0 === contacts.length && <NoResultsTableRow numColumns={6} />}
{contacts.map(contact => <>
<Tr key={contact.id}>
<Td>{contact.kind}</Td>
<Td>{contact.name}</Td>
<Td>{contact.role}</Td>
<Td><MailLink email={contact.email} /></Td>
<Td><TelephoneLink number={contact.phone} /></Td>
<Td><DeleteIconButton onClick={onContactDelete.bind(this, contact.id)} /></Td>
</Tr>
</>)}
</Tbody>
</Table>
</form>
</>}
</TabPanel>
<TabPanel>
<ClientProjectsTab clientId={clientId} />
</TabPanel>
</TabPanels>
</Tabs>
</article>
</div>
}
Example #16
Source File: ChallengeDetailView.jsx From scaffold-directory with MIT License | 4 votes |
export default function ChallengeDetailView({ serverUrl, address, userProvider, userRole, loadWeb3Modal }) {
const [descriptionJs, setDescriptionJs] = useState(null);
const [descriptionTs, setDescriptionTs] = useState(null);
const { challengeId } = useParams();
const history = useHistory();
const { isOpen, onOpen, onClose } = useDisclosure();
const [openModalOnLoad, setOpenModalOnLoad] = useState(false);
const challenge = challengeInfo[challengeId];
const isWalletConnected = !!userRole;
const isAnonymous = userRole && USER_ROLES.anonymous === userRole;
// Fetch challenge description from local files.
// In the future, this might be a fetch to the repos/branchs README
// (Ideally fetched at build time)
useEffect(() => {
getChallengeReadme(challengeId, "js")
.then(text => setDescriptionJs(parseGithubReadme(text)))
.catch(() => setDescriptionJs(challenge.description));
getChallengeReadme(challengeId, "ts")
.then(text => setDescriptionTs(parseGithubReadme(text)))
.catch(() => setDescriptionTs(challenge.description));
}, [challengeId, challenge]);
useEffect(() => {
if (!isWalletConnected || isAnonymous) return;
if (openModalOnLoad) {
onOpen();
setOpenModalOnLoad(false);
}
}, [isAnonymous, isWalletConnected, onOpen, userRole, openModalOnLoad, setOpenModalOnLoad]);
if (!challenge) {
// TODO implement a 404 page
// this looks good: https://ant.design/components/result/#components-result-demo-404
history.push("/404");
}
const handleSubmitChallengeModal = async () => {
if (isWalletConnected && !isAnonymous) {
return onOpen();
}
if (!isWalletConnected) {
await loadWeb3Modal();
setOpenModalOnLoad(true);
}
};
const challengeActionButtons = (type = "JS") => {
const repo = type === "JS" ? JS_CHALLENGE_REPO : TS_CHALLENGE_REPO;
return (
<Box>
<Button
as="a"
colorScheme="gray"
variant="outline"
href={`${repo}/tree/${challenge.branchName}`}
target="_blank"
rel="noopener noreferrer"
>
View it on Github <ExternalLinkIcon ml={1} />
</Button>
<Box pos="fixed" bottom={0} p={6} left={0} right={0}>
<Tooltip label={isAnonymous ? "You need to register as a builder" : "Submit Challenge"} shouldWrapChildren>
<Button colorScheme="blue" boxShadow="dark-lg" onClick={handleSubmitChallengeModal} disabled={isAnonymous}>
Submit challenge
</Button>
</Tooltip>
</Box>
</Box>
);
};
return (
// Magic number for maxW to match GitHub
<Container maxW="894px" mb="60px">
<Box textAlign="center" mb={6}>
<Heading as="h1" mb={4}>
{challenge.label}
</Heading>
</Box>
<Tabs variant="enclosed-colored" align="center">
<TabList>
<Tab>Javascript</Tab>
<Tab>Typescript</Tab>
</TabList>
<TabPanels align="left">
<TabPanel>
<SkeletonText mt="4" noOfLines={4} spacing="4" isLoaded={descriptionJs} />
<ReactMarkdown components={ChakraUIRenderer(chakraMarkdownComponents)}>{descriptionJs}</ReactMarkdown>
<Box textAlign="center" my={6}>
{challengeActionButtons("JS")}
</Box>
</TabPanel>
<TabPanel>
<SkeletonText mt="4" noOfLines={4} spacing="4" isLoaded={descriptionTs} />
<ReactMarkdown components={ChakraUIRenderer(chakraMarkdownComponents)}>{descriptionTs}</ReactMarkdown>
<Box textAlign="center" my={6}>
{challengeActionButtons("TS")}
</Box>
</TabPanel>
</TabPanels>
</Tabs>
<Modal isOpen={isOpen} onClose={onClose}>
<ModalOverlay />
<ModalContent>
<ModalHeader>Submit Challenge</ModalHeader>
<ModalCloseButton />
<ModalBody px={6} pb={8}>
<ChallengeSubmission
challenge={challenge}
serverUrl={serverUrl}
address={address}
userProvider={userProvider}
loadWeb3Modal={loadWeb3Modal}
/>
</ModalBody>
</ModalContent>
</Modal>
</Container>
);
}
Example #17
Source File: ChallengeReviewRow.jsx From scaffold-directory with MIT License | 4 votes |
export default function ChallengeReviewRow({ challenge, isLoading, approveClick, rejectClick, userProvider }) {
const [comment, setComment] = useState(challenge.reviewComment ?? "");
const [testPassed, setTestPassed] = useState(null);
const [isRunningTests, setIsRunningTests] = useState(false);
const { isOpen, onOpen, onClose } = useDisclosure();
const address = useUserAddress(userProvider);
if (!challengeInfo[challenge.id]) {
return null;
}
// We asume that rejected challenges will always have review Comments.
const isAutograded = challenge.autograding;
// ToDo. Use the stored events.
const isResubmitted = !isAutograded && !!challenge.reviewComment;
const runTests = async () => {
try {
console.log("Testing challenge with the auto-grader");
setIsRunningTests(true);
setTestPassed(null);
const result = await runAutograderTest(challenge.id, challenge.contractUrl, address);
const resultData = result.data;
console.log("Testing results", resultData);
setTestPassed(resultData.success);
setComment(resultData.feedback ?? resultData.error);
} catch (e) {
console.log("Error calling the auto-grader", e);
} finally {
setIsRunningTests(false);
}
};
const challengeReviewDisplay = (
<Link as={RouteLink} to={`/challenge/${challenge.id}`}>
{challengeInfo[challenge.id].label}
{isResubmitted && (
<>
<br />
<Text fontSize="xs">(Resubmitted)</Text>
</>
)}
{isAutograded && (
<>
<br />
<Text fontSize="xs" color="orange.500">
(Autograded)
</Text>
</>
)}
</Link>
);
const submittedMoment = moment(challenge.submittedTimestamp);
const reviewRow = (
<>
<Td>
<Link as={RouteLink} to={`/builders/${challenge.userAddress}`} pos="relative">
<Address address={challenge.userAddress} w="12.5" fontSize="16" />
</Link>
</Td>
<Td>{challengeReviewDisplay}</Td>
<Td>
<DateWithTooltip timestamp={challenge.submittedTimestamp} />
</Td>
</>
);
return (
<Tr>
{reviewRow}
<Td>
<Button type="button" colorScheme="blue" disabled={isLoading} className="danger" onClick={onOpen} size="xs">
Review
</Button>
</Td>
<Modal isOpen={isOpen} onClose={onClose} size="xl">
<ModalOverlay />
<ModalContent maxW="56rem">
<ModalHeader>Review Challenge</ModalHeader>
<ModalCloseButton />
<Table mb={4}>
<Thead>
<Tr>
<Th>Builder</Th>
<Th>Challenge & Links</Th>
</Tr>
</Thead>
<Tbody>
<Tr>
<Td>
<Link as={RouteLink} to={`/builders/${challenge.userAddress}`} pos="relative">
<Address address={challenge.userAddress} w="12.5" fontSize="16" />
</Link>
</Td>
<Td>
{challengeReviewDisplay}
<UnorderedList>
<ListItem>
<Link
// Legacy branchUrl
href={challenge.contractUrl || challenge.branchUrl}
color="teal.500"
target="_blank"
rel="noopener noreferrer"
>
Contract
</Link>
</ListItem>
<ListItem>
<Link href={challenge.deployedUrl} color="teal.500" target="_blank" rel="noopener noreferrer">
Demo
</Link>
</ListItem>
<ListItem>
Submitted{" "}
<Tooltip label={submittedMoment.format("YYYY-MM-DD, HH:mm")}>
<chakra.span cursor="pointer">{submittedMoment.fromNow()}</chakra.span>
</Tooltip>
</ListItem>
<ListItem listStyleType="none" mt={2}>
<Flex align="center">
<Button onClick={runTests} isLoading={isRunningTests} mr={2}>
Run tests
</Button>
{isBoolean(testPassed) && (
<Badge colorScheme={testPassed ? "green" : "red"}>
{testPassed ? "Accepted" : "Rejected"}
</Badge>
)}
</Flex>
</ListItem>
</UnorderedList>
</Td>
</Tr>
</Tbody>
</Table>
<ModalBody px={6} pb={0}>
<Tabs variant="enclosed-colored">
<TabList>
<Tab>Write</Tab>
<Tab>Preview</Tab>
</TabList>
<TabPanels align="left">
<TabPanel p={0}>
<Textarea
onChange={e => {
const value = e.target.value;
setComment(value);
}}
placeholder="Comment"
style={{ marginBottom: 10 }}
rows={10}
value={comment}
borderTopRadius={0}
/>
</TabPanel>
<TabPanel>
<ReactMarkdown components={ChakraUIRenderer(chakraMarkdownComponents)}>{comment}</ReactMarkdown>
</TabPanel>
</TabPanels>
</Tabs>
</ModalBody>
<ModalFooter>
<Button
type="button"
colorScheme="red"
disabled={isLoading}
className="danger"
onClick={() => rejectClick(challenge.userAddress, challenge.id, comment)}
size="sm"
isFullWidth
>
Reject
</Button>
<Button
type="button"
colorScheme="green"
disabled={isLoading}
ml={3}
onClick={() => approveClick(challenge.userAddress, challenge.id, comment)}
size="sm"
isFullWidth
>
Approve
</Button>
</ModalFooter>
</ModalContent>
</Modal>
</Tr>
);
}
Example #18
Source File: Profile.js From DAOInsure with MIT License | 4 votes |
function Profile() {
const web3Context = useContext(Web3Context);
const {
signerAddress,
userDaoTokenBalance,
fetchProposals,
fetchVotedProposals,
proposalsArray,
votedProposalsArray,
} = web3Context;
const [daoTokenBalance, setDaoTokenBalance] = useState(0);
const [stable, setStable] = useState(false);
useEffect(() => {
setInterval(async () => {
setDaoTokenBalance(await userDaoTokenBalance());
}, 10000);
}, []);
useEffect(() => {
fetchProposals();
fetchVotedProposals();
}, [stable]);
function con() {
console.log(proposalsArray);
}
return (
<VStack
alignItems='flex-start'
height='calc(100vh - 64px)'
px='250px'
py='20px'
width='100%'>
<HStack width='100%' alignItems='flex-start'>
<Box
borderWidth='2px'
borderRadius='full'
borderColor='whatsapp.500'
padding='2px'>
<Avatar
size='md'
icon={
<Jazzicon
diameter='48'
address={`${signerAddress}`}
/>
}
/>
</Box>
<VStack alignItems='flex-start'>
<Heading fontSize='20px'>{signerAddress}</Heading>
<Tag>10DAIx / month</Tag>
</VStack>
<Spacer />
<VStack>
<Tag>INSURE Tokens : {daoTokenBalance}</Tag>
</VStack>
</HStack>
<Grid
width='100%'
mt='30px !important'
templateColumns='3fr 2fr'
gridGap={5}
alignItems='flex-start'>
<Tabs
colorScheme='whatsapp'
variant='soft-rounded'
width='100%'>
<TabList>
<Tab onClick={con}>
Claims{" "}
<Tag ml={2} borderRadius='20px'>
{proposalsArray.length}
</Tag>
</Tab>
<Tab>
Voted For
<Tag ml={2} borderRadius='20px'>
{votedProposalsArray.length}
</Tag>
</Tab>
</TabList>
<TabPanels>
<TabPanel mt={3} padding={0}>
<Card cardTitle='Claims'>
<Table>
<Tbody>
{proposalsArray.map(function (
element,
id
) {
return (
<Tr key={id}>
<Th>
{" "}
{element[0].toNumber()}{" "}
</Th>
<Th>{element[2]}</Th>
<Th>
{element[7] ? (
<span>
{" "}
Passed{" "}
</span>
) : (
<span>
{" "}
Failed{" "}
</span>
)}
</Th>
</Tr>
);
})}
</Tbody>
</Table>
</Card>
</TabPanel>
<TabPanel mt={3} padding={0}>
<Card cardTitle='Claims'>
<Table>
<Tbody>
{votedProposalsArray.map(function (
element,
id
) {
return (
<Tr key={id}>
<Th>
{" "}
{element[0].toNumber()}{" "}
</Th>
<Th>{element[2]}</Th>
<Th>
{element[7] ? (
<span>
{" "}
Passed{" "}
</span>
) : (
<span>
{" "}
Failed{" "}
</span>
)}
</Th>
</Tr>
);
})}
</Tbody>
</Table>
</Card>
</TabPanel>
</TabPanels>
</Tabs>
</Grid>
</VStack>
);
}
Example #19
Source File: ClaimsPage.js From DAOInsure with MIT License | 4 votes |
function ClaimsPage() {
const { textileClient } = useContext(AppContext);
const [openClaims, setOpenClaims] = useState();
const [isLoadingOpenClaims, setIsLoadingOpenClaims] = useState(true);
const web3Context = useContext(Web3Context);
const {
fetchAllProposals,
allProposalsArray,
openProposalsArray,
acceptedProposalsArray,
rejectedProposalsArray,
daoMemberCount,
setDaoMemberCount,
} = web3Context;
useEffect(() => {
async function init() {
console.log(textileClient);
if (textileClient) {
// textile database querying the thread using threadId and collection where claims are present.
let openClaims = await queryThread(
textileClient,
"bafkyspsyykcninhqn4ht6d6jeqmzq4cepy344akmkhjk75dmw36wq4q",
"claimsData",
{}
);
console.log(openClaims);
setOpenClaims(openClaims);
setIsLoadingOpenClaims(false);
}
}
init();
}, [textileClient]);
useEffect(() => {
fetchAllProposals();
console.log(openProposalsArray);
}, []);
return (
<Grid
height='calc(100vh - 64px)'
px='250px'
py='20px'
width='100%'
templateColumns='3fr 1fr'
gridGap={5}
alignItems='flex-start'>
<Tabs variant='soft-rounded' colorScheme='whatsapp'>
<TabList justifyContent='space-between'>
<HStack>
<Tab>
Open Claims{" "}
<GreenTag>{openProposalsArray.length}</GreenTag>
</Tab>
<Tab variant='solid'>
Accepted Claims{" "}
<GreenTag>{acceptedProposalsArray.length}</GreenTag>
</Tab>
<Tab variant='solid'>
Rejected Claims{" "}
<GreenTag>{rejectedProposalsArray.length}</GreenTag>
</Tab>
</HStack>
<Link to='/makeClaim'>
<Button colorScheme='whatsapp'>+ Make a Claim</Button>
</Link>
</TabList>
<TabPanels>
<TabPanel py={4} px={0}>
<ClaimsList claims={openProposalsArray} />
</TabPanel>
<TabPanel py={4} px={0}>
<ClaimsList claims={acceptedProposalsArray} />
</TabPanel>
<TabPanel py={4} px={0}>
<ClaimsList claims={rejectedProposalsArray} />
</TabPanel>
</TabPanels>
</Tabs>
<Stats
claims={
acceptedProposalsArray.length +
rejectedProposalsArray.length
}
daoMemberCount={daoMemberCount}
/>
</Grid>
);
}