@chakra-ui/react#TabPanels JavaScript Examples

The following examples show how to use @chakra-ui/react#TabPanels. 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: ouput.js    From GitMarkonics with MIT License 6 votes vote down vote up
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 #2
Source File: DashboardPanels.js    From web-client with Apache License 2.0 5 votes vote down vote up
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 #3
Source File: Details.js    From web-client with Apache License 2.0 5 votes vote down vote up
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 #4
Source File: Profile.js    From web-client with Apache License 2.0 5 votes vote down vote up
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 #5
Source File: Details.js    From web-client with Apache License 2.0 5 votes vote down vote up
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 #6
Source File: Details.js    From web-client with Apache License 2.0 5 votes vote down vote up
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 #7
Source File: Report.js    From web-client with Apache License 2.0 5 votes vote down vote up
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 #8
Source File: Details.js    From web-client with Apache License 2.0 4 votes vote down vote up
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>&nbsp;</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 #9
Source File: Details.js    From web-client with Apache License 2.0 4 votes vote down vote up
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 #10
Source File: ChallengeDetailView.jsx    From scaffold-directory with MIT License 4 votes vote down vote up
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 #11
Source File: Details.js    From web-client with Apache License 2.0 4 votes vote down vote up
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 #12
Source File: ChallengeReviewRow.jsx    From scaffold-directory with MIT License 4 votes vote down vote up
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 #13
Source File: wallets.js    From idena-web with MIT License 4 votes vote down vote up
export default function Index() {
  const {t} = useTranslation()

  const {coinbase} = useAuthState()

  const [{all}] = useDeferredVotes()

  const {
    data: {balance, stake},
    isLoading,
  } = useBalance()

  const receiveDrawerDisclosure = useDisclosure()

  const sendDrawerDisclosure = useDisclosure()

  return (
    <Layout>
      <Page pt={[4, 6]}>
        <MobileApiStatus left={4} />
        <PageTitleNew>{t('Wallets')}</PageTitleNew>
        <Flex w="100%" flexFlow="row wrap">
          <Flex flexBasis={['100%', '50%']} order={1}>
            <Avatar
              display={['block', 'none']}
              size="80px"
              mr={6}
              address={coinbase}
            />
            <TotalAmount
              amount={parseFloat(balance) + parseFloat(stake)}
              isLoading={isLoading}
              mt={[2, 0]}
            />
          </Flex>
          <Flex flexBasis={['100%', '50%']} order={[4, 2]} mt={1}>
            <HStack
              justifyContent={['space-around', 'flex-end']}
              h={6}
              alignItems="center"
              flexBasis="100%"
            >
              <VDivider display={['none', 'initial']} />
              <IconButton
                mx={[3, 0]}
                fontSize={['mobile', 'md']}
                color={['red.500', 'blue.500']}
                icon={
                  <SendOutIcon boxSize={5} color={['red.500', 'blue.500']} />
                }
                onClick={sendDrawerDisclosure.onOpen}
              >
                {t('Send')}
              </IconButton>
              <VDivider />
              <IconButton
                mx={[3, 0]}
                fontSize={['mobile', 'md']}
                icon={<ReceiveIcon boxSize={5} color="blue.500" />}
                onClick={receiveDrawerDisclosure.onOpen}
              >
                {t('Receive')}
              </IconButton>
            </HStack>
          </Flex>
          <Flex flexBasis="100%" order={[2, 3]} mt={[8, 2]}>
            <Link
              target="_blank"
              href={`https://scan.idena.io/address/${coinbase}`}
              color="blue.500"
              fontWeight={500}
              w={['100%', 'auto']}
            >
              <Flex
                fontSize={['base', 'md']}
                alignItems="center"
                w={['100%', 'auto']}
              >
                <Box
                  boxSize={8}
                  backgroundColor="brandBlue.10"
                  borderRadius="10px"
                  display={['inline-block', 'none']}
                >
                  <OpenExplorerIcon boxSize={5} mt={1} ml={3 / 2} />
                </Box>
                <Box
                  as="span"
                  ml={[3, 0]}
                  borderBottomWidth={['1px', 0]}
                  flex={[1, 'auto']}
                  pb={[1, 0]}
                >
                  {t('More details in explorer')}{' '}
                  <Icon display={['none', 'inline']} as={FiChevronRight} />
                </Box>
              </Flex>
            </Link>
          </Flex>
          <Flex
            flexBasis="100%"
            order={[3, 4]}
            overflowX={['auto', 'initial']}
            sx={{
              '&::-webkit-scrollbar': {
                display: 'none',
              },
            }}
            mt={8}
            mb={[6, 0]}
          >
            <WalletCard
              address={coinbase}
              wallet={{name: 'Main', balance, isStake: false}}
              isSelected
              onSend={sendDrawerDisclosure.onOpen}
              onReceive={receiveDrawerDisclosure.onOpen}
              isLoading={isLoading}
            />
            <WalletCard
              wallet={{name: 'Stake', balance: stake, isStake: true}}
              isLoading={isLoading}
            />
          </Flex>
        </Flex>

        <Heading
          fontSize="lg"
          color="brandGray.500"
          fontWeight={500}
          mb={0}
          mt={8}
          display={['none', 'block']}
        >
          {t('Transactions')}
        </Heading>

        {all.length > 0 ? (
          <Tabs variant="unstyled" w={['100%', 'auto']} mt={[8, 6]}>
            <TabList bg={['gray.50', 'white']} borderRadius="md" p={[1, 0]}>
              <TransactionsTab>
                {t('Scheduled')}
                {all.length > 0 && (
                  <>
                    <Badge ml={2} display={['none', 'inline-block']}>
                      {all.length}
                    </Badge>
                    <Box as="span" ml={1} display={['inline', 'none']}>
                      {all.length}
                    </Box>
                  </>
                )}
              </TransactionsTab>
              <TransactionsTab> {t('Recent')}</TransactionsTab>
            </TabList>
            <TabPanels mt={4}>
              <TabPanel p={0}>
                <WalletPendingTransactions />
              </TabPanel>
              <TabPanel p={0}>
                <WalletTransactions address={coinbase} />
              </TabPanel>
            </TabPanels>
          </Tabs>
        ) : (
          <Flex mt={4}>
            <WalletTransactions address={coinbase} />
          </Flex>
        )}

        <SendDrawer {...sendDrawerDisclosure} />

        <ReceiveDrawer address={coinbase} {...receiveDrawerDisclosure} />
      </Page>
    </Layout>
  )
}
Example #14
Source File: get-invitation.js    From idena-web with MIT License 4 votes vote down vote up
export default function GetInvitation() {
  const router = useRouter()
  const {t} = useTranslation()

  const [nickname, setNickname] = useState('')

  const failToast = useFailToast()
  const successToast = useSuccessToast()

  const [code, setCode] = useState()
  const [isWaiting, setIsWaiting] = useState(false)

  const size = useBreakpointValue(['lg', 'md'])

  const invitationCodeRef = useRef()

  const {scrollTo: scrollToCode} = useScroll(invitationCodeRef)

  const getCode = async () => {
    setIsWaiting(true)
    const name = nickname.startsWith('@') ? nickname.substring(1) : nickname

    try {
      const {invitation} = await getInvitationCode(name, cookie.get('refId'))
      setCode(invitation)
      successToast(t('Your invitation code has been generated successfully!'))
      scrollToCode()
    } catch (e) {
      failToast(e.message)
    } finally {
      setIsWaiting(false)
    }
  }

  return (
    <Layout showHamburger={false}>
      <Page>
        <Flex
          align="center"
          alignSelf="stretch"
          justify={['center', 'space-between']}
          mb={[8, 2]}
          w={['100%', null]}
        >
          <PageTitle
            fontSize={['base', 'xl']}
            fontWeight={['bold', 500]}
            mb={0}
          >
            {t('How to get an invitation')}
          </PageTitle>
          <CloseButton
            color={['blue.500', 'inherit']}
            size="lg"
            position={['absolute', 'inherit']}
            right={2}
            onClick={() => router.push('/home')}
          />
        </Flex>
        <Flex
          direction="column"
          maxW="480px"
          w={['100%', null]}
          fontSize={['mdx', 'md']}
        >
          <Text>
            {t(
              'To minimize the probability of a Sybil attack, the pace of network growth is restricted: Idena network participation is invitation-based. New invitations can be sent out only by validated users. The number of invitations is limited and increases as the network grows.',
              {nsSeparator: '|'}
            )}
          </Text>
          <Text mt={2}>
            {t(
              'Please choose the platform where you have the most active account:',
              {nsSeparator: '|'}
            )}
          </Text>

          <Tabs variant="unstyled" mt={8}>
            <TabList bg={['gray.50', 'white']} p={[1, 0]} borderRadius="md">
              <GetInvitationTab
                iconSelected={<TelegramInvertedIcon />}
                icon={<TelegramIcon />}
                title="Telegram"
              />
              <GetInvitationTab
                iconSelected={<DiscordInvertedIcon />}
                icon={<DiscordIcon />}
                title="Discord"
              />
              <GetInvitationTab
                iconSelected={<TwitterIcon />}
                icon={<TwitterIcon />}
                title="Twitter"
              />
              <GetInvitationTab
                iconSelected={<RedditInvertedIcon />}
                icon={<RedditIcon />}
                title="Reddit"
              />
            </TabList>
            <TabPanels>
              <GetInvitationTabPanel>
                <GetInvitationTabTitle>Telegram</GetInvitationTabTitle>
                <Text>
                  <Trans t={t} i18nKey="joinIdenaTelegram">
                    Join the official{' '}
                    <Link
                      href="https://t.me/IdenaNetworkPublic"
                      target="_blank"
                      color="blue.500"
                    >
                      Idena Telegram group
                    </Link>{' '}
                    and request an invitation code from the community.
                  </Trans>
                </Text>
              </GetInvitationTabPanel>
              <GetInvitationTabPanel>
                <GetInvitationTabTitle>Discord</GetInvitationTabTitle>
                <Text>
                  <Trans t={t} i18nKey="joinIdenaDiscord">
                    Join{' '}
                    <Link
                      href="https://discord.gg/8BusRj7"
                      target="_blank"
                      color="blue.500"
                    >
                      Idena Community Discord
                    </Link>{' '}
                    and request an invitation code from the community in
                    #invite-requests channel.
                  </Trans>
                </Text>
              </GetInvitationTabPanel>
              <GetInvitationTabPanel>
                <GetInvitationTabTitle>Twitter</GetInvitationTabTitle>
                <OrderedList spacing={2}>
                  <ListItem>
                    {t('Follow')}{' '}
                    <Link
                      href="https://twitter.com/IdenaNetwork"
                      target="_blank"
                      color="blue.500"
                    >
                      @IdenaNetwork
                    </Link>{' '}
                  </ListItem>
                  <ListItem>
                    <Stack spacing={4}>
                      <Text>
                        <Trans t={t} i18nKey="joinIdenaTwitterSendTweet">
                          <Link
                            target="_blank"
                            color="blue.500"
                            rel="noreferrer"
                            href="https://twitter.com/intent/tweet?text=I%20want%20to%20join%20%40IdenaNetwork%20to%20become%20a%20validator%20of%20the%20first%20Proof-of-Person%20blockchain%20%23IdenaInvite%0A%0Ahttps://www.idena.io"
                          >
                            Send a tweet
                          </Link>{' '}
                          with a hashtag #IdenaInvite from your account. To get
                          an invite, your account should be older than 1 year or
                          older than two months and have at least 50 followers.
                          The tweet should say:
                        </Trans>
                      </Text>
                      <Flex mt={4} p={[7, 10]} borderRadius="md" bg="gray.50">
                        <Flex direction={['column', 'row']}>
                          <Stack>
                            <Text color="gray.500">
                              I want to join @IdenaNetwork to become a validator
                              of the first Proof-of-Person blockchain
                              #IdenaInvite
                            </Text>
                            <Text>
                              <Link
                                href="https://www.idena.io"
                                target="_blank"
                                color="blue.500"
                              >
                                https://www.idena.io
                              </Link>
                            </Text>
                          </Stack>
                          <GetInvitationCopyButton
                            ml={[0, 10]}
                            value={
                              'I want to join @IdenaNetwork to become a validator of the first Proof-of-Person blockchain #IdenaInvite\n' +
                              '\n' +
                              'https://www.idena.io'
                            }
                          />
                        </Flex>
                      </Flex>
                    </Stack>
                  </ListItem>
                  <ListItem>
                    <Stack spacing={4} pt={2}>
                      <Text>
                        <Trans t={t} i18nKey="joinIdenaTwitterGetCode">
                          Enter your twitter name and click{' '}
                          <i>Get an invitation code</i> button. The code will be
                          shown automatically.
                        </Trans>
                      </Text>
                      <Stack>
                        <Text color="gray.500" fontWeight="500">
                          {t('Your nickname')}
                        </Text>
                        <GetInvitationTwitterInput
                          value={nickname}
                          onChange={value => setNickname(value)}
                        />
                      </Stack>

                      {code ? (
                        <Flex
                          boxShadow="0 3px 12px 0 rgba(83, 86, 92, 0.1), 0 2px 3px 0 rgba(83, 86, 92, 0.2)"
                          px={10}
                          py={8}
                          borderRadius="lg"
                          position="relative"
                        >
                          <Flex
                            direction={['column', 'row']}
                            justifyContent="space-between"
                            w="100%"
                          >
                            <Stack spacing={0}>
                              <Text color="muted">{t('Invitation code')}</Text>
                              <Text
                                color="gray.500"
                                fontWeight={500}
                                wordBreak="break-all"
                              >
                                {code}
                              </Text>
                            </Stack>
                            <GetInvitationCopyButton
                              value={code}
                              ml={[0, 10]}
                            />
                          </Flex>
                        </Flex>
                      ) : (
                        <Flex>
                          <PrimaryButton
                            ml="auto"
                            onClick={getCode}
                            isLoading={isWaiting}
                            loadingText=""
                            w={['100%', 'auto']}
                            size={size}
                          >
                            {t('Get an invitation code')}
                          </PrimaryButton>
                        </Flex>
                      )}
                      <Box ref={invitationCodeRef}></Box>
                    </Stack>
                  </ListItem>
                </OrderedList>
              </GetInvitationTabPanel>
              <GetInvitationTabPanel>
                <GetInvitationTabTitle>Reddit</GetInvitationTabTitle>
                <Text color="gray.500">
                  <Trans t={t} i18nKey="joinIdenaReddit">
                    Join{' '}
                    <Link
                      href="https://www.reddit.com/r/Idena/"
                      target="_blank"
                      color="blue.500"
                    >
                      Idena subreddit
                    </Link>{' '}
                    and request an invitation code from the community.
                  </Trans>
                </Text>
              </GetInvitationTabPanel>
            </TabPanels>
          </Tabs>
        </Flex>
      </Page>
    </Layout>
  )
}
Example #15
Source File: Details.js    From web-client with Apache License 2.0 4 votes vote down vote up
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&nbsp;
                            <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 #16
Source File: Profile.js    From DAOInsure with MIT License 4 votes vote down vote up
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 #17
Source File: Details.js    From web-client with Apache License 2.0 4 votes vote down vote up
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&nbsp;
                        <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>&nbsp;{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 #18
Source File: ClaimsPage.js    From DAOInsure with MIT License 4 votes vote down vote up
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>
	);
}