@chakra-ui/react#Checkbox JavaScript Examples

The following examples show how to use @chakra-ui/react#Checkbox. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: select.js    From react-table-library with MIT License 5 votes vote down vote up
Component = () => {
  const data = { nodes };

  const chakraTheme = getTheme(DEFAULT_OPTIONS);
  const customTheme = {
    Table: `
      --data-table-library_grid-template-columns:  64px repeat(5, minmax(0, 1fr));
    `,
  };
  const theme = useTheme([chakraTheme, customTheme]);

  const select = useRowSelect(data, {
    onChange: onSelectChange,
  });

  function onSelectChange(action, state) {
    console.log(action, state);
  }

  const COLUMNS = [
    {
      label: 'Task',
      renderCell: (item) => item.name,
      select: {
        renderHeaderCellSelect: () => (
          <Checkbox
            colorScheme="teal"
            isChecked={select.state.all}
            isIndeterminate={!select.state.all && !select.state.none}
            onChange={select.fns.onToggleAll}
          />
        ),
        renderCellSelect: (item) => (
          <Checkbox
            colorScheme="teal"
            isChecked={select.state.ids.includes(item.id)}
            onChange={() => select.fns.onToggleById(item.id)}
          />
        ),
      },
    },
    {
      label: 'Deadline',
      renderCell: (item) =>
        item.deadline.toLocaleDateString('en-US', {
          year: 'numeric',
          month: '2-digit',
          day: '2-digit',
        }),
    },
    { label: 'Type', renderCell: (item) => item.type },
    {
      label: 'Complete',
      renderCell: (item) => item.isComplete.toString(),
    },
    { label: 'Tasks', renderCell: (item) => item.nodes?.length },
  ];

  return (
    <>
      <Box p={3} borderWidth="1px" borderRadius="lg">
        <CompactTable columns={COLUMNS} data={data} theme={theme} select={select} />
      </Box>

      <br />
      <DocumentationSee anchor={'Features/' + key} />
    </>
  );
}
Example #2
Source File: filter.js    From react-table-library with MIT License 5 votes vote down vote up
Component = () => {
  let data = { nodes };

  const chakraTheme = getTheme(DEFAULT_OPTIONS);
  const theme = useTheme(chakraTheme);

  const [isHide, setHide] = React.useState(false);

  data = {
    nodes: isHide ? data.nodes.filter((node) => !node.isComplete) : data.nodes,
  };

  const COLUMNS = [
    { label: 'Task', renderCell: (item) => item.name },
    {
      label: 'Deadline',
      renderCell: (item) =>
        item.deadline.toLocaleDateString('en-US', {
          year: 'numeric',
          month: '2-digit',
          day: '2-digit',
        }),
    },
    { label: 'Type', renderCell: (item) => item.type },
    {
      label: 'Complete',
      renderCell: (item) => item.isComplete.toString(),
    },
    { label: 'Tasks', renderCell: (item) => item.nodes?.length },
  ];

  return (
    <>
      <Stack spacing={10}>
        <Checkbox
          colorScheme="teal"
          isChecked={isHide}
          onChange={(event) => setHide(event.target.checked)}
        >
          Hide Complete
        </Checkbox>
      </Stack>
      <br />

      <Box p={3} borderWidth="1px" borderRadius="lg">
        <CompactTable columns={COLUMNS} data={data} theme={theme} />
      </Box>

      <br />
      <DocumentationSee anchor={'Features/' + key} />
    </>
  );
}
Example #3
Source File: DashboardPanels.js    From web-client with Apache License 2.0 5 votes 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 #4
Source File: Form.js    From web-client with Apache License 2.0 5 votes vote down vote up
UserForm = ({ isEdit = false, user, userSetter: setUser, onFormSubmit }) => {

    const [passwordGenerationMethod, setPasswordGenerationMethod] = useState('autogenerated');

    const onFormChange = ev => {
        const target = ev.target;
        const name = target.name;
        const value = target.type === 'checkbox' ? target.checked : target.value;
        setUser({ ...user, [name]: value });
    };

    const onPasswordGenerationMethodChange = ev => {
        setPasswordGenerationMethod(ev.target.value);
    }

    return <form onSubmit={onFormSubmit} className="crud">
        <fieldset>
            <legend>Basic information</legend>

            <label>Full name
                <Input type="text" name="full_name" value={user.full_name || ""} onChange={onFormChange} required />
            </label>
            <label>Short bio
                <Input type="text" name="short_bio" value={user.short_bio || ""} onChange={onFormChange}
                    placeholder="DevSecOps, or Project Manager" />
            </label>
            <label>Email
                <Input type="email" name="email" value={user.email || ""} onChange={onFormChange} required />
            </label>
            <label>Role
                <Select name="role" onChange={onFormChange} value={user.role} required>
                    {UserRoles.map(role => <option key={`role_${role.id}`} value={role.id}>{role.name}</option>)}
                </Select>
            </label>
            <label>Properties
                <div>
                    <Checkbox name="active" isChecked={user.active} onChange={onFormChange}>Active</Checkbox>
                    <Checkbox name="mfa_enabled" isChecked={user.mfa_enabled} onChange={onFormChange}>2FA enabled</Checkbox>
                </div>
            </label>
        </fieldset>

        <fieldset>
            <legend>Credentials</legend>
            <label>Username
                <Input type="text" name="username" value={user.username || ""} onChange={onFormChange} autoFocus required />
            </label>
            {!isEdit &&
                <>
                    <label htmlFor="passwordGenerationMethod">Password generation method
                        <Select name="passwordGenerationMethod" onChange={onPasswordGenerationMethodChange}>
                            <option value="auto">Auto-generated</option>
                            <option value="manual">Manual</option>
                        </Select>
                    </label>
                    {passwordGenerationMethod === 'manual' &&
                        <>
                            <label>Password
                                <Input type="password" name="unencryptedPassword" onChange={onFormChange} required />
                            </label>
                            <label>
                                Send email to user
                                <Checkbox name="sendEmailToUser" onChange={onFormChange} />
                            </label>
                        </>
                    }
                </>
            }
        </fieldset>

        <PrimaryButton type="submit">{isEdit ? "Update" : "Create"}</PrimaryButton>
    </form >
}
Example #5
Source File: AdvancedSearch.js    From web-client with Apache License 2.0 5 votes vote down vote up
AdvancedSearch = () => {
    const navigate = useNavigate();

    const entityList = {
        'commands': 'Commands',
        'tasks': 'Tasks',
        'vulnerabilities': 'Vulnerabilities',
        'vulnerability_templates': 'Vulnerability templates',
        'projects': 'Projects',
        'project_templates': 'Project templates'
    };

    const [keywords, setKeywords] = useState('');
    const [entities, setEntities] = useState(Object.keys(entityList));

    const onFormSubmit = (ev) => {
        ev.preventDefault();

        navigate(`/search/${keywords.trim()}?entities=` + entities.join(','));
    }

    const onKeywordsChange = ev => {
        setKeywords(ev.target.value);
    };

    const onFormInputChange = ev => {
        const target = ev.target;
        const value = target.value;

        setEntities(target.checked ? [...entities, value] : entities.filter(entity => entity !== value));
    };

    return <>
        <PageTitle value={`Advanced search`} />
        <div className='heading'>
            <Breadcrumb />
        </div>
        <Title type='Advanced search' title="Search form" icon={<IconSearch />} />

        <form onSubmit={onFormSubmit}>
            <Input type="search" name="keywords" value={keywords} onChange={onKeywordsChange} placeholder="Keywords" />

            {Object.keys(entityList).map((objectKey) =>
                <Checkbox isChecked={entities.includes(objectKey)} value={objectKey} onChange={onFormInputChange}>{entityList[objectKey]}</Checkbox>
            )}

            <Button type="submit" isDisabled={keywords.trim().length === 0 || entities.length === 0}>Search</Button>
        </form>
    </>
}
Example #6
Source File: VaultTab.js    From web-client with Apache License 2.0 4 votes vote down vote up
ProjectVaultTab = ({ project }) => {
    const [vault, refreshVault] = useFetch(`/vault/${project.id}`);
    const [vaultItem, setVaultItem] = useState(new Vault());

    const onVaultItemFormChange = ev => {
        const value = ev.target.type === 'checkbox' ? ev.target.checked : ev.target.value;
        setVaultItem({ ...vaultItem, [ev.target.name]: value });
    }

    const onVaultItemDelete = vaultItemId => {
        secureApiFetch(`/vault/${project.id}/${vaultItemId}`, { method: 'DELETE' })
            .then(() => {
                refreshVault();
                actionCompletedToast("The vault item has been deleted.");
            })
            .catch(err => console.error(err))
    }

    const onFormSubmit = ev => {
        ev.preventDefault();

        secureApiFetch(`/vault/${project.id}`, { method: 'POST', body: JSON.stringify(vaultItem) })
            .then(resp => {
                if (resp.status === 201) {
                    setVaultItem(new Vault());
                    refreshVault();
                    actionCompletedToast(`The vault item has been added.`);
                } else {
                    errorToast("The vault item could not be saved. Review the form data or check the application logs.")
                }
            })
    }

    return <section>
        <RestrictedComponent roles={['administrator', 'superuser', 'user']} message="(access restricted)">
            {vault && <>
                <Table>
                    <Thead>
                        <Tr>
                            <Th>Name</Th>
                            <Th>Note</Th>
                            <Th>Type</Th>
                            <Th>Reportable</Th>
                            <Th>&nbsp;</Th>
                        </Tr>
                    </Thead>
                    <Tbody>
                        {0 === vault.length && <NoResultsTableRow numColumns={3} />}
                        {vault.map(item => <>
                            <Tr key={item.id}>
                                <Td>{item.name}</Td>
                                <Td>{item.note}</Td>
                                <Td>{item.type}</Td>
                                <Td>{item.reportable}</Td>
                                <Td textAlign="right">
                                    <LinkButton href={`/vault/${project.id}/${item.id}/edit`}>Edit</LinkButton>
                                    <DeleteIconButton onClick={onVaultItemDelete.bind(this, item.id)} />
                                </Td>
                            </Tr>
                        </>)}
                    </Tbody>
                </Table>
                <form onSubmit={onFormSubmit}>
                    <h3>New vault item</h3>
                    <Table>
                        <Thead>
                            <Tr>
                                <Th>Type</Th>
                                <Th>Name</Th>
                                <Th>Note</Th>
                                <Th>Value</Th>
                                <Th>Password</Th>
                                <Th>Reportable</Th>
                                <Th>&nbsp;</Th>
                            </Tr>
                        </Thead>
                        <Tbody>
                            <Tr>
                                <Td>
                                    <Select name="type" onChange={onVaultItemFormChange} value={vaultItem.type || ""} isRequired>
                                        <option value="password">Password</option>
                                        <option value="note">Note</option>
                                        <option value="token">Token</option>
                                        <option value="key">Key</option>
                                    </Select>
                                </Td>
                                <Td>
                                    <Input type="text" name="name" onChange={onVaultItemFormChange} value={vaultItem.name || ""} isRequired />
                                </Td>
                                <Td>
                                    <Input type="text" name="note" onChange={onVaultItemFormChange} value={vaultItem.note || ""} />
                                </Td>
                                <Td>
                                    <Input type="text" name="value" onChange={onVaultItemFormChange} value={vaultItem.value || ""} isRequired />
                                </Td>
                                <Td>
                                    <Input type="password" name="password" onChange={onVaultItemFormChange} value={vaultItem.password || ""} isRequired />
                                </Td>
                                <Td>
                                    <Checkbox name="reportable" onChange={onVaultItemFormChange} isChecked={vaultItem.reportable} />
                                </Td>
                                <Td>
                                    <Button type="submit">Add</Button>
                                </Td>
                            </Tr>
                        </Tbody>
                    </Table>
                </form>
            </>}
        </RestrictedComponent>
    </section>;
}
Example #7
Source File: showreel.js    From react-table-library with MIT License 4 votes vote down vote up
Component = () => {
  const [data, setData] = React.useState({ nodes });

  //* Theme *//

  const chakraTheme = getTheme({
    ...DEFAULT_OPTIONS,
    striped: true,
  });
  const customTheme = {
    Table: `
      --data-table-library_grid-template-columns:  64px repeat(5, minmax(0, 1fr));

      margin: 16px 0px;
    `,
  };
  const theme = useTheme([chakraTheme, customTheme]);

  //* Resize *//

  const resize = { resizerHighlight: '#dee2e6' };

  //* Pagination *//

  const pagination = usePagination(data, {
    state: {
      page: 0,
      size: 4,
    },
    onChange: onPaginationChange,
  });

  function onPaginationChange(action, state) {
    console.log(action, state);
  }

  //* Search *//

  const [search, setSearch] = React.useState('');

  useCustom('search', data, {
    state: { search },
    onChange: onSearchChange,
  });

  function onSearchChange(action, state) {
    console.log(action, state);
    pagination.fns.onSetPage(0);
  }

  //* Filter *//

  const [isHide, setHide] = React.useState(false);

  useCustom('filter', data, {
    state: { isHide },
    onChange: onFilterChange,
  });

  function onFilterChange(action, state) {
    console.log(action, state);
    pagination.fns.onSetPage(0);
  }

  //* Select *//

  const select = useRowSelect(data, {
    onChange: onSelectChange,
  });

  function onSelectChange(action, state) {
    console.log(action, state);
  }

  //* Tree *//

  const tree = useTree(
    data,
    {
      onChange: onTreeChange,
    },
    {
      clickType: TreeExpandClickTypes.ButtonClick,
      treeYLevel: 1,
      treeIcon: {
        margin: '4px',
        iconDefault: null,
        iconRight: <FaChevronRight />,
        iconDown: <FaChevronDown />,
      },
    },
  );

  function onTreeChange(action, state) {
    console.log(action, state);
  }

  //* Sort *//

  const sort = useSort(
    data,
    {
      onChange: onSortChange,
    },
    {
      sortIcon: {
        iconDefault: null,
        iconUp: <FaChevronUp />,
        iconDown: <FaChevronDown />,
      },
      sortFns: {
        TASK: (array) => array.sort((a, b) => a.name.localeCompare(b.name)),
        DEADLINE: (array) => array.sort((a, b) => a.deadline - b.deadline),
        TYPE: (array) => array.sort((a, b) => a.type.localeCompare(b.type)),
        COMPLETE: (array) => array.sort((a, b) => a.isComplete - b.isComplete),
        TASKS: (array) => array.sort((a, b) => (a.nodes || []).length - (b.nodes || []).length),
      },
    },
  );

  function onSortChange(action, state) {
    console.log(action, state);
  }

  //* Drawer *//

  const [drawerId, setDrawerId] = React.useState(null);
  const [edited, setEdited] = React.useState('');

  const handleEdit = (event) => {
    setEdited(event.target.value);
  };

  const handleCancel = () => {
    setEdited('');
    setDrawerId(null);
  };

  const handleSave = () => {
    const node = findNodeById(data.nodes, drawerId);
    const editedNode = { ...node, name: edited };
    const nodes = insertNode(data.nodes, editedNode);

    setData({
      nodes,
    });

    setEdited('');
    setDrawerId(null);
  };

  //* Modal *//

  const [modalOpened, setModalOpened] = React.useState(false);

  //* Custom Modifiers *//

  let modifiedNodes = data.nodes;

  // search
  modifiedNodes = modifiedNodes.filter((node) =>
    node.name.toLowerCase().includes(search.toLowerCase()),
  );

  // filter
  modifiedNodes = isHide ? modifiedNodes.filter((node) => !node.isComplete) : modifiedNodes;

  //* Columns *//

  const COLUMNS = [
    {
      label: 'Task',
      renderCell: (item) => item.name,
      resize,
      sort: { sortKey: 'TASK' },
      select: {
        renderHeaderCellSelect: () => (
          <Checkbox
            colorScheme="teal"
            isChecked={select.state.all}
            isIndeterminate={!select.state.all && !select.state.none}
            onChange={select.fns.onToggleAll}
          />
        ),
        renderCellSelect: (item) => (
          <Checkbox
            colorScheme="teal"
            style={{ backgroundColor: '#ffffff' }}
            isChecked={select.state.ids.includes(item.id)}
            onChange={() => select.fns.onToggleById(item.id)}
          />
        ),
      },
      tree: true,
    },
    {
      label: 'Deadline',
      renderCell: (item) =>
        item.deadline.toLocaleDateString('en-US', {
          year: 'numeric',
          month: '2-digit',
          day: '2-digit',
        }),
      resize,
      sort: { sortKey: 'DEADLINE' },
    },
    { label: 'Type', renderCell: (item) => item.type, resize, sort: { sortKey: 'TYPE' } },
    {
      label: 'Complete',
      renderCell: (item) => item.isComplete.toString(),
      resize,
      sort: { sortKey: 'COMPLETE' },
    },
    {
      label: 'Tasks',
      renderCell: (item) => (
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
          <span>{item.nodes?.length}</span>
          <IconButton
            aria-label="edit"
            icon={<FaPen />}
            size="xs"
            variant="ghost"
            colorScheme="teal"
            onClick={() => setDrawerId(item.id)}
          />
        </div>
      ),
      resize,
      sort: { sortKey: 'TASKS' },
    },
  ];

  return (
    <>
      <Modal isOpen={modalOpened} onClose={() => setModalOpened(false)}>
        <ModalOverlay />
        <ModalContent>
          <ModalHeader>Not all features included here, but we got ...</ModalHeader>
          <ModalCloseButton />
          <ModalBody>
            <div>
              <Checkbox colorScheme="teal" isChecked>
                Resize
              </Checkbox>
            </div>
            <div>
              <Checkbox colorScheme="teal" isChecked>
                Sort
              </Checkbox>
            </div>
            <div>
              <Checkbox colorScheme="teal" isChecked>
                Search
              </Checkbox>
            </div>
            <div>
              <Checkbox colorScheme="teal" isChecked>
                Filter
              </Checkbox>
            </div>
            <div>
              <Checkbox colorScheme="teal" isChecked>
                Select
              </Checkbox>
            </div>
            <div>
              <Checkbox colorScheme="teal" isChecked>
                Tree
              </Checkbox>
            </div>
            <div>
              <Checkbox colorScheme="teal" isChecked>
                Drawer on Edit
              </Checkbox>
            </div>
            <div>
              <Checkbox colorScheme="teal" isChecked>
                Pagination
              </Checkbox>
            </div>
          </ModalBody>
        </ModalContent>
      </Modal>

      {/* Form */}

      <HStack m={3}>
        <Button colorScheme="teal" onClick={() => setModalOpened(true)}>
          Features?
        </Button>

        <InputGroup>
          <InputLeftElement
            pointerEvents="none"
            children={<FaSearch style={{ color: '#4a5568' }} />}
          />
          <Input
            placeholder="Search Task"
            value={search}
            onChange={(event) => setSearch(event.target.value)}
          />
        </InputGroup>

        <Checkbox
          style={{ whiteSpace: 'nowrap' }}
          colorScheme="teal"
          isChecked={isHide}
          onChange={(event) => setHide(event.target.checked)}
        >
          Hide Complete
        </Checkbox>
      </HStack>

      {/* Table */}

      <Box p={3} borderWidth="1px" borderRadius="lg">
        <CompactTable
          columns={COLUMNS}
          data={{ ...data, nodes: modifiedNodes }}
          theme={theme}
          layout={{ custom: true }}
          select={select}
          tree={tree}
          sort={sort}
          pagination={pagination}
        />
      </Box>

      <br />
      <HStack justify="flex-end">
        <IconButton
          aria-label="previous page"
          icon={<FaChevronLeft />}
          colorScheme="teal"
          variant="ghost"
          disabled={pagination.state.page === 0}
          onClick={() => pagination.fns.onSetPage(pagination.state.page - 1)}
        />

        {pagination.state.getPages(modifiedNodes).map((_, index) => (
          <Button
            key={index}
            colorScheme="teal"
            variant={pagination.state.page === index ? 'solid' : 'ghost'}
            onClick={() => pagination.fns.onSetPage(index)}
          >
            {index + 1}
          </Button>
        ))}
        <IconButton
          aria-label="next page"
          icon={<FaChevronRight />}
          colorScheme="teal"
          variant="ghost"
          disabled={pagination.state.page + 1 === pagination.state.getTotalPages(data.nodes)}
          onClick={() => pagination.fns.onSetPage(pagination.state.page + 1)}
        />
      </HStack>

      <Drawer isOpen={drawerId} onClose={handleCancel} placement="right">
        <DrawerOverlay />
        <DrawerContent>
          <DrawerCloseButton />
          <DrawerHeader>Create your account</DrawerHeader>

          <DrawerBody>
            <Text>Name: </Text>
            <Input
              autoFocus
              value={
                edited || fromTreeToList(data.nodes).find((node) => node.id === drawerId)?.name
              }
              onChange={handleEdit}
              data-autofocus
            />
          </DrawerBody>

          <DrawerFooter>
            <Button variant="outline" mr={3} onClick={handleCancel}>
              Cancel
            </Button>
            <Button onClick={handleSave} colorScheme="teal">
              Save
            </Button>
          </DrawerFooter>
        </DrawerContent>
      </Drawer>
    </>
  );
}
Example #8
Source File: column-hide.js    From react-table-library with MIT License 4 votes vote down vote up
Component = () => {
  const data = { nodes };

  const chakraTheme = getTheme(DEFAULT_OPTIONS);
  const theme = useTheme(chakraTheme);

  const [hiddenColumns, setHiddenColumns] = React.useState(['DEADLINE', 'COMPLETE']);

  const toggleColumn = (column) => {
    if (hiddenColumns.includes(column)) {
      setHiddenColumns(hiddenColumns.filter((v) => v !== column));
    } else {
      setHiddenColumns(hiddenColumns.concat(column));
    }
  };

  const COLUMNS = [
    { label: 'Task', renderCell: (item) => item.name, hide: hiddenColumns.includes('TASK') },
    {
      label: 'Deadline',
      renderCell: (item) =>
        item.deadline.toLocaleDateString('en-US', {
          year: 'numeric',
          month: '2-digit',
          day: '2-digit',
        }),
      hide: hiddenColumns.includes('DEADLINE'),
    },
    { label: 'Type', renderCell: (item) => item.type, hide: hiddenColumns.includes('TYPE') },
    {
      label: 'Complete',
      renderCell: (item) => item.isComplete.toString(),
      hide: hiddenColumns.includes('COMPLETE'),
    },
    {
      label: 'Tasks',
      renderCell: (item) => item.nodes?.length,
      hide: hiddenColumns.includes('TASKS'),
    },
  ];

  return (
    <>
      <HStack spacing={10}>
        <Checkbox
          colorScheme="teal"
          isChecked={!hiddenColumns.includes('NAME')}
          onChange={() => toggleColumn('NAME')}
        >
          Name
        </Checkbox>
        <Checkbox
          colorScheme="teal"
          isChecked={!hiddenColumns.includes('DEADLINE')}
          onChange={() => toggleColumn('DEADLINE')}
        >
          Deadline
        </Checkbox>
        <Checkbox
          colorScheme="teal"
          isChecked={!hiddenColumns.includes('TYPE')}
          onChange={() => toggleColumn('TYPE')}
        >
          Type
        </Checkbox>
        <Checkbox
          colorScheme="teal"
          isChecked={!hiddenColumns.includes('COMPLETE')}
          onChange={() => toggleColumn('COMPLETE')}
        >
          Complete
        </Checkbox>
        <Checkbox
          colorScheme="teal"
          isChecked={!hiddenColumns.includes('TASKS')}
          onChange={() => toggleColumn('TASKS')}
        >
          Tasks
        </Checkbox>
      </HStack>
      <br />

      <Box p={3} borderWidth="1px" borderRadius="lg">
        <CompactTable columns={COLUMNS} data={data} theme={theme} layout={{ hiddenColumns }} />
      </Box>

      <br />
      <DocumentationSee anchor={'Features/' + key} />
    </>
  );
}
Example #9
Source File: VulnerabilitiesTable.js    From web-client with Apache License 2.0 4 votes vote down vote up
VulnerabilitiesTable = ({ tableModel, tableModelSetter: setTableModel, reloadCallback, showSelection = true, showProjectColumn = true }) => {
    const onSortChange = (ev, column, order) => {
        ev.preventDefault();

        setTableModel({ ...tableModel, sortBy: { column: column, order: order } })
    }

    const onSelectionChange = ev => {
        const target = ev.target;
        const selectionId = parseInt(target.value);
        if (target.checked) {
            setTableModel({ ...tableModel, selection: [...tableModel.selection, selectionId] })
        } else {
            setTableModel({ ...tableModel, selection: tableModel.selection.filter(value => value !== selectionId) })
        }
    };

    const onHeaderCheckboxClick = ev => {
        if (ev.target.checked) {
            setTableModel({ ...tableModel, selection: tableModel.vulnerabilities.map(vulnerability => vulnerability.id) })
        } else {
            setTableModel({ ...tableModel, selection: [] })
        }
    }

    const numColumns = 6 + (showSelection ? 1 : 0) + (showProjectColumn ? 1 : 0);
    const vulnerabilitiesLength = null !== tableModel.vulnerabilities ? tableModel.vulnerabilities.length : 0;

    const deleteVulnerability = useDelete('/vulnerabilities/', reloadCallback, 'Do you really want to delete this vulnerability?', 'The vulnerability has been deleted.');

    return <Table>
        <Thead>
            <Tr>
                {showSelection && <Th style={{ width: "32px", textAlign: "left" }}><Checkbox onChange={onHeaderCheckboxClick} isChecked={tableModel.selection.length && tableModel.selection.length === vulnerabilitiesLength} isDisabled={tableModel.vulnerabilitiesLength === 0} /></Th>}
                <Th style={{ width: '190px' }}>Summary</Th>
                {showProjectColumn && <Th style={{ width: '190px' }}>Project</Th>}
                <Th style={{ width: '120px' }}><DescendingSortLink callback={onSortChange} property="status" /> Status <AscendingSortLink callback={onSortChange} property="status" /></Th>
                <Th style={{ width: '120px' }}><DescendingSortLink callback={onSortChange} property="risk" /> Risk <AscendingSortLink callback={onSortChange} property="risk" /></Th>
                <Th style={{ width: '120px' }}><DescendingSortLink callback={onSortChange} property="cvss_score" /> <abbr title="Common Vulnerability Scoring System">CVSS</abbr> score <AscendingSortLink callback={onSortChange} property="cvss_score" /></Th>
                <Th className='only-desktop' style={{ width: '20%' }}><DescendingSortLink callback={onSortChange} property="category_name" /> Category <AscendingSortLink callback={onSortChange} property="category_name" /></Th>
                <Th style={{ width: '15%', textAlign: 'right' }}><ReloadButton onClick={reloadCallback} /></Th>
            </Tr>
        </Thead>
        <Tbody>
            {null === tableModel.vulnerabilities &&
                <LoadingTableRow numColumns={numColumns} />}
            {null !== tableModel.vulnerabilities && 0 === tableModel.vulnerabilities.length &&
                <NoResultsTableRow numColumns={numColumns} />}
            {null !== tableModel.vulnerabilities && tableModel.vulnerabilities.length > 0 &&
                tableModel.vulnerabilities.map((vulnerability, index) => {
                    return <Tr key={index}>
                        {showSelection &&
                            <Td>
                                <Checkbox
                                    value={vulnerability.id}
                                    onChange={onSelectionChange}
                                    isChecked={tableModel.selection.includes(vulnerability.id)}
                                />
                            </Td>
                        }
                        <Td>
                            <Stack>
                                <VulnerabilityBadge vulnerability={vulnerability} />
                                <div><Tags values={vulnerability.tags} /></div>
                            </Stack>
                        </Td>
                        {showProjectColumn && <Td>{vulnerability.is_template ? <span title="Not applicable">(n/a)</span> : <ProjectBadge project={{ id: vulnerability.project_id, name: vulnerability.project_name }} />}</Td>}
                        <Td><VulnerabilityStatusBadge vulnerability={vulnerability} /></Td>
                        <Td><RiskBadge risk={vulnerability.risk} /></Td>
                        <Td><CvssScore score={vulnerability.cvss_score} /></Td>
                        <Td className='only-desktop'>
                            <VulnerabilityCategorySpan name={vulnerability.category_name} parentName={vulnerability.parent_category_name} />
                        </Td>
                        <Td textAlign="right">
                            <RestrictedComponent roles={['administrator', 'superuser', 'user']}>
                                <LinkButton href={`/vulnerabilities/${vulnerability.id}/edit`}>Edit</LinkButton>
                                {reloadCallback &&
                                    <DeleteIconButton onClick={() => deleteVulnerability(vulnerability.id)} />
                                }
                            </RestrictedComponent>
                        </Td>
                    </Tr>
                })}
        </Tbody>
    </Table>
}
Example #10
Source File: Form.js    From web-client with Apache License 2.0 4 votes vote down vote up
VulnerabilityForm = ({
    isEditForm = false,
    vulnerability,
    vulnerabilitySetter: setVulnerability,
    onFormSubmit
}) => {
    const [initialised, setInitialised] = useState(false);
    const [projects, setProjects] = useState(null);
    const [categories, setCategories] = useState(null);
    const [subCategories, setSubCategories] = useState(null);
    const [targets, setTargets] = useState(null);
    const [useOWASP, setMetrics] = useState(false);

    useEffect(() => {
        if (initialised) return;

        Promise.all([
            secureApiFetch(`/projects`, { method: 'GET' }),
            secureApiFetch(`/vulnerabilities/categories`, { method: 'GET' }),
        ])
            .then(resp => {
                const [respA, respB] = resp;
                return Promise.all([respA.json(), respB.json()]);
            })
            .then(([projects, categories]) => {
                const defaultProjectId = projects.length ? projects[0].id : 0;
                const projectId = isEditForm ? vulnerability.project_id : defaultProjectId;
                setMetrics(isOwaspProject(projects, projectId))

                var subcategories = null;
                if (vulnerability.parent_category_id) {
                    secureApiFetch(`/vulnerabilities/categories/${vulnerability.parent_category_id}`, { method: 'GET' })
                        .then(response => response.json())
                        .then(json => {
                            subcategories = json;
                        })
                }

                secureApiFetch(`/targets?projectId=${projectId}`, { method: 'GET' })
                    .then(resp => resp.json())
                    .then(targets => {
                        unstable_batchedUpdates(() => {
                            setProjects(projects);
                            setCategories(categories);
                            setTargets(targets);
                            setVulnerability(prevVulnerability => {
                                let updatedVulnerability = prevVulnerability;
                                if (!idExists(projects, prevVulnerability.project_id)) {
                                    updatedVulnerability.project_id = defaultProjectId;
                                }
                                if ((!idExists(categories, prevVulnerability.category_id)) && (!idExists(subcategories, prevVulnerability.category_id))) {
                                    updatedVulnerability.category_id = categories[0].id;
                                }
                                if (!idExists(targets, vulnerability.target_id)) {
                                    updatedVulnerability.target_id = null;
                                }
                                return updatedVulnerability;
                            })
                            setInitialised(true);
                        });
                    })
            });
    }, [initialised, isEditForm, setProjects, setCategories, setTargets, setMetrics, setVulnerability, vulnerability.target_id, vulnerability.project_id, vulnerability.parent_category_id, subCategories, setSubCategories]);

    useEffect(() => {
        if (!initialised) return;

        if (vulnerability.parent_category_id) {
            secureApiFetch(`/vulnerabilities/categories/${vulnerability.parent_category_id}`, { method: 'GET' })
                .then(response => response.json())
                .then(json => {
                    setSubCategories(json);
                })
        }

        const projectId = vulnerability.project_id;
        secureApiFetch(`/targets?projectId=${projectId}`, { method: 'GET' })
            .then(resp => resp.json())
            .then(targets => {
                unstable_batchedUpdates(() => {
                    setTargets(targets);
                    if (isEditForm) { // Edit
                        if (!idExists(targets, vulnerability.target_id)) {
                            setVulnerability(prevVulnerability => {
                                return { ...prevVulnerability, target_id: 0 }
                            });
                        }
                    }
                });
            })
    }, [initialised, isEditForm, setTargets, setVulnerability, vulnerability.target_id, vulnerability.project_id, vulnerability.parent_category_id]);

    const idExists = (elements, id) => {
        if (!elements) return false;
        for (const el of elements) {
            if (el.id === parseInt(id)) return true;
        }
        return false;
    }

    const isOwaspProject = (elements, id) => {
        let metrics = ProjectVulnerabilityMetrics[0].id;
        for (const el of elements) {
            if (el.id === parseInt(id)) {
                metrics = el.vulnerability_metrics;
            }
        }
        return (ProjectVulnerabilityMetrics[1].id === metrics);
    }

    const onFormChange = ev => {
        const target = ev.target;
        const name = target.name;
        let value = target.type === 'checkbox' ? target.checked : target.value;

        if ('tags' === name) {
            value = JSON.stringify(value.split(','));
        }

        if ('category_id' === name) {
            if (value !== '(none)') {
                secureApiFetch(`/vulnerabilities/categories/${value}`, { method: 'GET' })
                    .then(response => response.json())
                    .then(json => {
                        setSubCategories(json);
                    })
                setVulnerability({ ...vulnerability, 'parent_category_id': value, [name]: value });
            } else {
                setVulnerability({ ...vulnerability, 'category_id': null });
            }
        } else if ('subcategory_id' === name) {
            setVulnerability({ ...vulnerability, 'category_id': value });
        } else {
            setVulnerability({ ...vulnerability, [name]: value });
        }
    };

    return <form onSubmit={onFormSubmit} className="crud">
        <Accordion defaultIndex={0} allowToggle allowMultiple>
            <AccordionItem index={0}>
                <h2>
                    <AccordionButton>
                        <Box flex="1" textAlign="left">
                            Basic information
                        </Box>
                        <AccordionIcon />
                    </AccordionButton>
                </h2>
                <AccordionPanel pb={4}>
                    <label>Properties
                        <div>
                            <Checkbox name="is_template" onChange={onFormChange} isChecked={vulnerability.is_template}>Is template</Checkbox>
                        </div>
                    </label>
                    <label>External ID
                        <Input type="text" name="external_id" value={vulnerability.external_id || ""} onChange={onFormChange} />
                    </label>
                    <label>Summary
                        <Input type="text" name="summary" value={vulnerability.summary || ""} onChange={onFormChange} required autoFocus />
                    </label>
                    <label>Description
                        <MarkdownEditor name="description" value={vulnerability.description || ""} onChange={onFormChange} />
                    </label>
                    <label>External references
                        <MarkdownEditor name="external_refs" value={vulnerability.external_refs || ""} onChange={onFormChange} />
                    </label>
                    <label>Category
                        <Select name="category_id" value={vulnerability.parent_category_id || ""} onChange={onFormChange} required>
                            <option>(none)</option>
                            {categories && categories.map(cat =>
                                <option key={cat.id} value={cat.id}>{cat.name}</option>
                            )}
                        </Select>
                    </label>
                    <label>Subcategory
                        <Select name="subcategory_id" value={vulnerability.category_id || ""} onChange={onFormChange} required>
                            <option>(none)</option>
                            {subCategories && subCategories.map(subcat =>
                                <option key={subcat.id} value={subcat.id}>{subcat.name}</option>
                            )}
                        </Select>
                    </label>
                    <FormControl id="visibility" isRequired>
                        <FormLabel>Visibility</FormLabel>
                        <Select name="visibility" value={vulnerability.visibility || ""} onChange={onFormChange}>
                            <option value="public">Public</option>
                            <option value="private">Private</option>
                        </Select>
                        <FormHelperText>Private makes this vulnerability not visible to the client.</FormHelperText>
                    </FormControl>
                    <label>Risk
                        <Select name="risk" value={vulnerability.risk || ""} onChange={onFormChange} required>
                            {Risks.map(risk =>
                                <option key={risk.id} value={risk.id}>{risk.name}</option>
                            )}
                        </Select>
                    </label>
                    <label>Tags
                        <Input type="text" name="tags" onChange={onFormChange} value={vulnerability.tags ? JSON.parse(vulnerability.tags).join(',') : ''} />
                    </label>
                    <label>Proof of concept
                        <MarkdownEditor name="proof_of_concept" value={vulnerability.proof_of_concept || ""} onChange={onFormChange} />
                    </label>
                    <label>Impact
                        <MarkdownEditor name="impact" value={vulnerability.impact || ""} onChange={onFormChange} />
                    </label>
                    {
                        !useOWASP && <>
                            <label>CVSS score
                                <Input type="number" step="0.1" min="0" max="10" name="cvss_score" value={vulnerability.cvss_score || ""}
                                    onChange={onFormChange} />
                            </label>
                            <label><span><CvssAbbr /> vector</span>
                                <Input type="text" name="cvss_vector" value={vulnerability.cvss_vector || ""} onChange={onFormChange} placeholder="eg: AV:N/AC:L/Au:S/C:P/I:P/A:N" />
                            </label>
                        </>
                    }
                </AccordionPanel>
            </AccordionItem>
            {useOWASP &&
                <AccordionItem>
                    <h2>
                        <AccordionButton>
                            <Box flex="1" textAlign="left">
                                Owasp Risk Rating calculator
                            </Box>
                            <AccordionIcon />
                        </AccordionButton>
                    </h2>
                    <AccordionPanel pb={4}>
                        <label>Owasp Risk Rating</label>
                        <OwaspRR vulnerability={vulnerability} vulnerabilitySetter={setVulnerability} />
                    </AccordionPanel>
                </AccordionItem>
            }
            <AccordionItem>
                <h2>
                    <AccordionButton>
                        <Box flex="1" textAlign="left">
                            Remediation
                        </Box>
                        <AccordionIcon />
                    </AccordionButton>
                </h2>
                <AccordionPanel pb={4}>

                    <label>Remediation instructions
                        <MarkdownEditor name="remediation" value={vulnerability.remediation || ""} onChange={onFormChange} />
                    </label>
                    <label>Remediation complexity
                        <Select name="remediation_complexity" value={vulnerability.remediation_complexity || ""} onChange={onFormChange} required>
                            {RemediationComplexity.map(complexity =>
                                <option key={complexity.id} value={complexity.id}>{complexity.name}</option>
                            )}
                        </Select>
                    </label>
                    <label>Remediation priority
                        <Select name="remediation_priority" value={vulnerability.remediation_priority || ""} onChange={onFormChange} required>
                            {RemediationPriority.map(priority =>
                                <option key={priority.id} value={priority.id}>{priority.name}</option>
                            )}
                        </Select>
                    </label>
                </AccordionPanel>
            </AccordionItem>

            {
                !vulnerability.is_template && <AccordionItem>
                    <h2>
                        <AccordionButton>
                            <Box flex="1" textAlign="left">
                                Relations
                            </Box>
                            <AccordionIcon />
                        </AccordionButton>
                    </h2>
                    <AccordionPanel pb={4}>

                        <label>Project
                            <Select name="project_id" value={vulnerability.project_id || ""} onChange={onFormChange} required>
                                {projects && projects.map((project, index) =>
                                    <option key={index} value={project.id}>{project.name}</option>
                                )}
                            </Select>
                        </label>

                        <label>Affected target
                            <Select name="target_id" value={vulnerability.target_id || ""} onChange={onFormChange}>
                                <option value="0">(none)</option>
                                {targets && targets.map((target, index) =>
                                    <option key={index} value={target.id}>{target.name}</option>
                                )}
                            </Select>
                        </label>
                    </AccordionPanel>
                </AccordionItem>
            }
        </Accordion>

        <Primary type="submit">{isEditForm ? "Save" : "Add"}</Primary>
    </form >
}
Example #11
Source File: create.js    From idena-web with MIT License 4 votes vote down vote up
export default function CreateKey() {
  const {t} = useTranslation()
  const size = useBreakpointValue(['lg', 'md'])
  const variant = useBreakpointValue(['mobile', 'initial'])
  const buttonVariant = useBreakpointValue(['primaryFlat', 'secondary'])
  const successToast = useSuccessToast()

  const router = useRouter()
  const [state, setState] = useState({
    step: steps.AVATAR,
  })
  const [error, setError] = useState()
  const {onCopy, hasCopied} = useClipboard(state.encryptedPrivateKey)

  const setStep = s => setState(prevState => ({...prevState, step: s}))

  const generateNewAddress = () => {
    const key = generatePrivateKey()
    setState(prevState => ({
      ...prevState,
      privateKey: key,
      address: privateKeyToAddress(key),
    }))
  }

  const setPassword = () => {
    if (state.password !== state.passwordConfirm) {
      setError(t("Passwords don't match. Try again."))
    } else {
      const encryptedKey = encryptPrivateKey(state.privateKey, state.password)
      setState(prevState => ({
        ...prevState,
        encryptedPrivateKey: encryptedKey,
        step: steps.BACKUP,
      }))
      setError(null)
    }
  }

  useEffect(() => {
    generateNewAddress()
  }, [])

  return (
    <>
      {state.step === steps.AVATAR && (
        <AuthLayout>
          <AuthLayout.Small>
            <Flex width="100%" direction="column">
              <Flex justifyContent="center">
                <div style={{position: 'relative'}}>
                  <Avatar address={state.address} />
                  <Box
                    color={['xblack.016', 'xwhite.500']}
                    opacity={[1, '0.8']}
                    position="absolute"
                    w={8}
                    h={8}
                    bottom={['28px', '5px']}
                    right={['-40px', '5px']}
                    borderRadius="6px"
                    background="gray.500"
                    padding="3px 2px 2px 5px"
                    cursor="pointer"
                    onClick={() => generateNewAddress()}
                  >
                    <RefreshIcon
                      color={['xwhite.500', 'inherit']}
                      boxSize={5}
                      fill="white"
                      style={{
                        opacity: 0.8,
                        transform: 'scaleX(-1) rotate(90deg)',
                      }}
                    ></RefreshIcon>
                  </Box>
                </div>
              </Flex>

              <Flex mt={[5, 0]} justify="center">
                <SubHeading color="white">{t('Your address')}</SubHeading>
              </Flex>

              <Flex
                mt="5px"
                mb="45px"
                fontSize="mdx"
                style={{
                  opacity: 0.5,
                  textAlign: 'center',
                  wordBreak: 'break-all',
                }}
              >
                {state.address}
              </Flex>
              <PrimaryButton
                size={size}
                onClick={() => setStep(steps.PASSWORD)}
              >
                {t('Proceed')}
              </PrimaryButton>

              <Flex justifyContent="center">
                <FlatButton onClick={() => router.push('/')} mt={5}>
                  {t('Cancel')}
                </FlatButton>
              </Flex>
            </Flex>
          </AuthLayout.Small>
        </AuthLayout>
      )}
      {state.step === steps.PASSWORD && (
        <AuthLayout>
          <Box
            w="100%"
            h={6}
            position="absolute"
            top="40px"
            display={['block', 'none']}
          >
            <ArrowBackIcon
              fill="#fff"
              boxSize={6}
              ml={4}
              onClick={() => setStep(steps.AVATAR)}
            ></ArrowBackIcon>
          </Box>
          <AuthLayout.Normal>
            <Flex
              direction={['column', 'initial']}
              align={['center', 'initial']}
              width="100%"
            >
              <Avatar address={state.address} />
              <Flex
                direction="column"
                align={['center', 'initial']}
                justify="center"
                flex="1"
                w={['75%', '100%']}
                mt={[5, 0]}
                ml={[0, 5]}
              >
                <Box>
                  <SubHeading color="white">
                    {t('Create password to encrypt your account')}
                  </SubHeading>
                </Box>

                <Flex justify="space-between">
                  <Text
                    wordBreak={['break-all', 'initial']}
                    color="xwhite.050"
                    fontSize="mdx"
                  >
                    {state.address}
                  </Text>
                </Flex>
              </Flex>
            </Flex>
            <Flex width="100%" mt={6}>
              <form
                onSubmit={e => {
                  e.preventDefault()
                  setPassword()
                }}
                style={{width: '100%'}}
              >
                <FormLabel
                  display={['none', 'inherit']}
                  htmlFor="key"
                  style={{color: 'white', fontSize: '13px'}}
                >
                  {t('Password')}
                </FormLabel>
                <Flex width="100%" mb={[3, 5]} style={{position: 'relative'}}>
                  <PasswordInput
                    id="password"
                    size={size}
                    value={state.password}
                    width="100%"
                    borderColor="xblack.008"
                    backgroundColor="xblack.016"
                    onChange={e =>
                      setState({
                        ...state,
                        password: e.target.value,
                      })
                    }
                    placeholder={t('Enter password')}
                  />
                </Flex>
                <FormLabel
                  display={['none', 'inherit']}
                  htmlFor="key"
                  style={{
                    color: 'white',
                    fontSize: '13px',
                  }}
                >
                  {t('Confirm password')}
                </FormLabel>
                <Flex width="100%" style={{position: 'relative'}}>
                  <PasswordInput
                    id="passwordConfirm"
                    size={size}
                    value={state.passwordConfirm}
                    width="100%"
                    borderColor="xblack.008"
                    backgroundColor="xblack.016"
                    onChange={e =>
                      setState({
                        ...state,
                        passwordConfirm: e.target.value,
                      })
                    }
                    placeholder={t('Enter password again')}
                  />
                </Flex>
                <Flex mt={[4, 8]} justify="space-between">
                  <FlatButton
                    display={['none', 'inherit']}
                    color="white"
                    _hover={{color: 'xwhite.080'}}
                    onClick={() => setStep(steps.AVATAR)}
                  >
                    <ArrowUpIcon
                      boxSize={5}
                      style={{transform: 'rotate(-90deg)', marginTop: -3}}
                    ></ArrowUpIcon>
                    {t('Back')}
                  </FlatButton>
                  <PrimaryButton
                    size={size}
                    w={['100%', 'initial']}
                    type="submit"
                  >
                    {t('Next')}
                  </PrimaryButton>
                </Flex>
                {error && (
                  <Flex
                    mt="30px"
                    background="rgb(255, 102, 102)"
                    borderRadius="9px"
                    fontSize="mdx"
                    p="18px 24px"
                  >
                    {error}
                  </Flex>
                )}
              </form>
            </Flex>
          </AuthLayout.Normal>
        </AuthLayout>
      )}
      {state.step === steps.BACKUP && (
        <AuthLayout>
          <Box
            w="100%"
            h={6}
            position="absolute"
            top="40px"
            display={['block', 'none']}
          >
            <ArrowBackIcon
              fill="#fff"
              boxSize={6}
              ml={4}
              onClick={() => setStep(steps.PASSWORD)}
            ></ArrowBackIcon>
          </Box>
          <AuthLayout.Normal>
            <Flex
              direction={['column', 'initial']}
              align={['center', 'initial']}
              width="100%"
            >
              <Avatar address={state.address} />
              <Flex
                direction="column"
                justify="center"
                flex="1"
                mt={[4, 0]}
                ml={[0, 5]}
              >
                <SubHeading color="white">
                  {t('Backup your private key')}
                </SubHeading>

                <Flex justify="space-between">
                  <Text color="xwhite.050" fontSize="mdx">
                    {t(
                      'Make a photo of QR code or save your encrypted private key.'
                    )}
                  </Text>
                </Flex>
              </Flex>
            </Flex>
            <Flex width="100%" mt={6}>
              <form
                onSubmit={e => {
                  e.preventDefault()
                  if (!state.understand1 || !state.understand2) {
                    setError(t('Please confirm you understand risks'))
                  } else {
                    sendSignUp(state.address)
                    setError('')
                    setStep(steps.SUCCESS)
                  }
                }}
                style={{width: '100%'}}
              >
                <Flex display={['none', 'flex']} justify="space-between">
                  <FormLabel style={{color: 'white', fontSize: 'md'}}>
                    {t('Your encrypted private key')}
                  </FormLabel>
                  {hasCopied ? (
                    <FormLabel style={{color: 'white', fontSize: 'md'}}>
                      {t('Copied!')}
                    </FormLabel>
                  ) : (
                    <FlatButton onClick={onCopy} marginBottom="10px">
                      {t('Copy')}
                    </FlatButton>
                  )}
                </Flex>
                <Flex width="100%" mb={[0, 5]} style={{position: 'relative'}}>
                  <Input
                    size={size}
                    variant={variant}
                    value={state.encryptedPrivateKey}
                    borderColor="xblack.008"
                    backgroundColor={['gray.500', 'xblack.016']}
                    width="100%"
                    pr={[10, 3]}
                    disabled
                  />
                  <Box
                    display={['initial', 'none']}
                    position="absolute"
                    top={3}
                    right={3}
                  >
                    <CopyIcon
                      boxSize={6}
                      fill="#E8EAED"
                      opacity="0.16"
                      onClick={() => {
                        onCopy()
                        successToast({
                          title: 'Private key copied!',
                          duration: '5000',
                        })
                      }}
                    />
                  </Box>
                </Flex>
                <Flex direction="column">
                  <Checkbox
                    order={[2, 1]}
                    mt={[9, 0]}
                    variant={variant}
                    textAlign={['left', 'initial']}
                    value={state.understand1}
                    isChecked={state.understand1}
                    onChange={e =>
                      setState({...state, understand1: e.target.checked})
                    }
                    style={{fontWeight: 300}}
                  >
                    {t(
                      'I understand that Idena cannot recover the private key for me.'
                    )}
                  </Checkbox>
                  <Checkbox
                    order={[3, 2]}
                    mt={2}
                    variant={variant}
                    textAlign={['left', 'initial']}
                    value={state.understand2}
                    isChecked={state.understand2}
                    onChange={e =>
                      setState({...state, understand2: e.target.checked})
                    }
                    style={{fontWeight: 300}}
                  >
                    {t(
                      'I understand the risk of compromising my private key backup.'
                    )}
                  </Checkbox>
                  <Flex order={[1, 3]} mt={[4, 8]} justify="space-between">
                    <FlatButton
                      display={['none', 'inherit']}
                      color="white"
                      _hover={{color: 'xwhite.080'}}
                      onClick={() => {
                        setError('')
                        setStep(steps.PASSWORD)
                      }}
                    >
                      <ArrowUpIcon
                        boxSize={5}
                        style={{transform: 'rotate(-90deg)', marginTop: -3}}
                      ></ArrowUpIcon>
                      {t('Back')}
                    </FlatButton>
                    <Flex
                      w={['100%', 'initial']}
                      direction={['column', 'initial']}
                    >
                      <Button
                        order={[2, 1]}
                        size={size}
                        variant={buttonVariant}
                        w={['100%', 'initial']}
                        type="button"
                        mt={[4, 0]}
                        mr={[0, 2.5]}
                        fontSize={['15px', '13px']}
                        onClick={() => setState({...state, showQrDialog: true})}
                      >
                        {t('Show QR code')}
                      </Button>
                      <PrimaryButton
                        order={[1, 2]}
                        w={['100%', 'initial']}
                        size={size}
                        type="submit"
                      >
                        {t('Next')}
                      </PrimaryButton>
                    </Flex>
                  </Flex>
                </Flex>
                {error && (
                  <Flex
                    mt="30px"
                    p="18px 24px"
                    background="rgb(255, 102, 102)"
                    borderRadius="9px"
                    fontSyze="mdx"
                    style={{
                      fontSize: '14px',
                    }}
                  >
                    {error}
                  </Flex>
                )}
              </form>
            </Flex>
          </AuthLayout.Normal>
          <Dialog
            key="qr"
            isOpen={state.showQrDialog}
            onClose={() => setState({...state, showQrDialog: false})}
          >
            <DialogHeader>{t('Encrypted private key')}</DialogHeader>
            <DialogBody>
              {t('Scan QR by your mobile phone.')}
              <Flex justify="center" mx="auto" my={8}>
                <QRCode value={state.encryptedPrivateKey} />
              </Flex>
            </DialogBody>
            <DialogFooter>
              <SecondaryButton
                onClick={() => setState({...state, showQrDialog: false})}
              >
                {t('Close')}
              </SecondaryButton>
              <PrimaryButton
                onClick={() => {
                  const blob = new Blob([state.encryptedPrivateKey], {
                    type: 'text/plain;charset=utf-8',
                  })
                  saveAs(blob, 'idena-encrypted-key.txt')
                }}
              >
                {t('Save to file')}
              </PrimaryButton>
            </DialogFooter>
          </Dialog>
        </AuthLayout>
      )}
      {state.step === steps.SUCCESS && (
        <AuthLayout>
          <AuthLayout.Small>
            <Flex width="100%" direction="column">
              <Flex justifyContent="center">
                <div style={{position: 'relative'}}>
                  <Avatar address={state.address} />
                </div>
              </Flex>
              <Flex justify="center" marginTop={7.5}>
                <SubHeading color="white">
                  {t('Successfully created!')}
                </SubHeading>
              </Flex>

              <Flex
                mt="5px"
                mb="45px"
                fontSize="mdx"
                style={{
                  opacity: 0.5,
                  textAlign: 'center',
                  wordBreak: 'break-all',
                }}
              >
                {state.address}
              </Flex>
              <PrimaryButton
                size={size}
                onClick={() => router.push('/key/import')}
              >
                {t('Sign in')}
              </PrimaryButton>
              <Flex display={['none', 'flex']} justifyContent="center">
                <FlatButton onClick={() => setStep(steps.BACKUP)} mt={5}>
                  {t('Back')}
                </FlatButton>
              </Flex>
            </Flex>
          </AuthLayout.Small>
        </AuthLayout>
      )}
    </>
  )
}
Example #12
Source File: VaultItemEdit.js    From web-client with Apache License 2.0 4 votes vote down vote up
VaultItemEdit = () => {
    const { projectId, vaultItemId } = useParams();
    const navigate = useNavigate();

    const [item, setVaultItem] = useState(new Vault());
    const [password, setPassword] = useState(null);

    const onVaultItemFormChange = ev => {
        const value = ev.target.type === 'checkbox' ? ev.target.checked : ev.target.value;
        setVaultItem({ ...item, [ev.target.name]: value });
    }

    const onFormSubmit = ev => {
        ev.preventDefault();

        item.password = password;

        secureApiFetch(`/vault/${projectId}/${vaultItemId}`, { method: 'PUT', body: JSON.stringify(item) })
            .then(resp => {
                if (resp.status === 201) {
                    setVaultItem(new Vault());
                    setPassword(null);
                    actionCompletedToast(`The vault item has been modified.`);
                    navigate(`/projects/${projectId}`);
                } else {
                    errorToast("The vault item could not be saved. Review the form data or check the application logs.")
                }
            })
    }

    const onPasswordProvided = ev => {
        ev.preventDefault();

        secureApiFetch(`/vault/${projectId}/${vaultItemId}`, { method: 'POST', body: JSON.stringify({ 'password': password }) })
            .then(response => response.json())
            .then(json => {
                if (json['success'] === false) {
                    errorToast("Seems like a wrong password.");
                    setPassword(null);
                }
                else {
                    var newItem = new Vault();
                    newItem.name = json['name'];
                    newItem.note = json['note'];
                    newItem.value = json['value'];
                    newItem.type = json['type'];
                    newItem.reportable = json['reportable'];
                    setVaultItem(newItem);
                    actionCompletedToast(`The vault item "${newItem.name}" has been loaded.`);
                }
            })
            .catch(err => {
                errorToast(err);
                setPassword(null);
            })
    }

    const onPasswordFormChanged = ev => {
        setPassword(ev.target.value);
    }

    return <div>
        {item.name !== "" && <>
            <form onSubmit={onFormSubmit}>
                <h3>Vault item</h3>
                <Table>
                    <Thead>
                        <Tr>
                            <Th>Type</Th>
                            <Th>Name</Th>
                            <Th>Note</Th>
                            <Th>Value</Th>
                            <Th>Reportable</Th>
                            <Th>&nbsp;</Th>
                        </Tr>
                    </Thead>
                    <Tbody>
                        <Tr>
                            <Td>
                                <Select name="type" onChange={onVaultItemFormChange} value={item.type || ""} isRequired>
                                    <option value="password">Password</option>
                                    <option value="note">Note</option>
                                    <option value="token">Token</option>
                                    <option value="key">Key</option>
                                </Select>
                            </Td>
                            <Td>
                                <Input type="text" name="name" onChange={onVaultItemFormChange} value={item.name || ""} isRequired />
                            </Td>
                            <Td>
                                <Input type="text" name="note" onChange={onVaultItemFormChange} value={item.note || ""} />
                            </Td>
                            <Td>
                                <Input type="text" name="value" onChange={onVaultItemFormChange} value={item.value || ""} isRequired />
                            </Td>
                            <Td>
                                <Checkbox name="reportable" onChange={onVaultItemFormChange} isChecked={item.reportable} />
                            </Td>
                            <Td>
                                <Button type="submit">Update</Button>
                            </Td>
                        </Tr>
                    </Tbody>
                </Table>
            </form>
        </>}
        {item.name === "" && <>
            <h3>Please provide password</h3>
            <form onSubmit={onPasswordProvided}>
                <Input type="password" name="password" onChange={onPasswordFormChanged} value={password || ""} isRequired />
                <Button type="submit">Send</Button>
            </form>
        </>}
    </div>
}
Example #13
Source File: Form.js    From web-client with Apache License 2.0 4 votes vote down vote up
ProjectForm = ({ isEdit = false, project, projectSetter: setProject, onFormSubmit }) => {

    const [clients] = useFetch('/clients');
    const [categories] = useFetch('/project/categories');

    const handleFormChange = ev => {
        const value = ev.target.type === 'checkbox' ? ev.target.checked : ev.target.value;
        setProject({ ...project, [ev.target.name]: value });
    };

    useEffect(() => {
        if (clients && clients.length && (project.client_id === null || project.client_id === 0)) {
            setProject({ ...project, client_id: clients[0].id });
        }
    }, [project, clients, setProject]);

    if (!project && !clients) return <Loading />

    return <form onSubmit={onFormSubmit} className="crud">

        <fieldset>
            <legend>Basic information</legend>

            <label>Is template?
                <Checkbox name="is_template" onChange={handleFormChange} isChecked={project.is_template} />
            </label>

            <label>
                Category
                <Select name="category_id" value={project.category_id || ""} onChange={handleFormChange} required>
                    {categories && <>
                        <option value="">(undefined)</option>
                        {categories.map(category => <option key={`category_${category.id}`} value={category.id}>{category.name}</option>)}
                    </>}
                </Select>
            </label>

            {!project.is_template && <>
                <label>Visibility
                    <Select name="visibility" onChange={handleFormChange} value={project.visibility}>
                        <option value="public">Public</option>
                        <option value="private">Private</option>
                    </Select>
                </label>

                <label>Client
                    <Select name="client_id" onChange={handleFormChange} value={project.client_id || ""}>
                        {clients && clients.map((client, index) =>
                            <option key={index} value={client.id}>{client.name}</option>
                        )}
                    </Select>
                </label>

                <label>External ID
                    <Input type="text" name="external_id" onChange={handleFormChange} value={project.external_id || ""} />
                </label>
            </>}

            <label>Name
                <Input type="text" name="name" onChange={handleFormChange} value={project.name || ""} required autoFocus />
            </label>
            <label>Description
                <MarkdownEditor name="description" onChange={handleFormChange} value={project.description || ""} required />
            </label>
        </fieldset>

        <fieldset>
            <legend>Rules of engagement</legend>

            <label>
                Vulnerability metrics
                <Select name="vulnerability_metrics" value={project.vulnerability_metrics || ""} onChange={handleFormChange}>
                    <option value="">(undefined)</option>
                    {ProjectVulnerabilityMetrics.map(type => <option key={`metrics_${type.id}`} value={type.id}>{type.name}</option>)}
                </Select>
            </label>

            {!project.is_template && <>
                <label>Start date
                    <Input type="date" name="engagement_start_date" value={project.engagement_start_date}
                        onChange={handleFormChange} />
                </label>

                <label>End date
                    <Input type="date" name="engagement_end_date" value={project.engagement_end_date}
                        onChange={handleFormChange} />
                </label>
            </>}
        </fieldset>

        <fieldset>
            <legend>Vulnerabilities summary</legend>

            <label>Management summary
                <MarkdownEditor name="management_summary" onChange={handleFormChange} value={project.management_summary || ""} required />
            </label>

            <label>Conclusion
                <MarkdownEditor name="management_conclusion" onChange={handleFormChange} value={project.management_conclusion || ""} required />
            </label>
        </fieldset>

        <PrimaryButton type="submit">{isEdit ? "Update" : "Create"}</PrimaryButton>
    </form>
}
Example #14
Source File: components.js    From idena-web with MIT License 4 votes vote down vote up
export function MyIdenaBotAlert({onConnect, onSkip}) {
  const {t} = useTranslation()

  const [{state}] = useIdentity()

  const myIdenaBotDisclosure = useDisclosure()

  const [doNotShowAgain, setDoNotShowAgain] = React.useState()

  const connectButtonRef = React.useRef()

  // eslint-disable-next-line no-shadow
  const eitherState = (...states) => states.some(s => s === state)

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

  const isDesktop = useIsDesktop()

  return (
    <>
      <Alert
        variant="solid"
        justifyContent="center"
        flexShrink={0}
        boxShadow="0 3px 12px 0 rgb(255 163 102 /0.1), 0 2px 3px 0 rgb(255 163 102 /0.2)"
        color="white"
        cursor="pointer"
        fontWeight={500}
        rounded="md"
        mt={2}
        mx={2}
        w="auto"
        onClick={myIdenaBotDisclosure.onOpen}
      >
        <Flex flexGrow={1} justifyContent="center" position="relative">
          <Box mr={[5, 0]}>
            <TelegramIcon boxSize={6} mr={1} display={['none', 'initial']} />
            {t(`Subscribe to @MyIdenaBot to get personalized notifications based on
        your status`)}
          </Box>
          {isDesktop ? (
            <FlatButton
              p={2}
              position="absolute"
              right={0}
              top={0}
              height="100%"
              color="white"
              onClick={e => {
                e.stopPropagation()
                onSkip()
              }}
              _hover={{color: 'white'}}
            >
              {t('Close')}
            </FlatButton>
          ) : (
            <CloseButton
              position="absolute"
              right={-3}
              top={-2}
              onClick={e => {
                e.stopPropagation()
                onSkip()
              }}
            />
          )}
        </Flex>
      </Alert>
      <Dialog
        title="Subscribe to @MyIdenaBot"
        size={size}
        initialFocusRef={connectButtonRef}
        {...myIdenaBotDisclosure}
      >
        <DialogBody>
          <Stack>
            <Text>
              {t(
                `MyIdenaBot reminds you about important actions based on your
              identity status:`,
                {nsSeparator: '!!'}
              )}
            </Text>

            {eitherState(IdentityStatus.Undefined) && (
              <IdenaBotFeatureList
                features={[
                  'next validation reminder',
                  'notification when you get an invite',
                  'reminder to activate your invite',
                  'your validation results when validation consensus is reached',
                ]}
              />
            )}

            {eitherState(IdentityStatus.Invite, IdentityStatus.Candidate) && (
              <IdenaBotFeatureList
                features={[
                  'next validation reminder',
                  'your validation results when validation consensus is reached',
                ]}
              />
            )}

            {eitherState(IdentityStatus.Newbie) && (
              <IdenaBotFeatureList
                features={[
                  'next validation reminder',
                  'reminder to create flips if you haven’t done it yet and the validation is coming',
                  'your validation results when validation consensus is reached',
                ]}
              />
            )}

            {eitherState(IdentityStatus.Verified, IdentityStatus.Human) && (
              <IdenaBotFeatureList
                features={[
                  'next validation reminder',
                  'reminder to create flips',
                  'your validation results when validation consensus is reached',
                  'reminder to share your remaining invites',
                  'reminder to submit extra flips to get more rewards',
                  'status update of all your invitees to check if they are ready for the validation (activated invites, submitted flips)',
                ]}
              />
            )}

            {eitherState(IdentityStatus.Zombie, IdentityStatus.Suspended) && (
              <IdenaBotFeatureList
                features={[
                  'next validation reminder',
                  'your validation results when validation consensus is reached',
                  'reminder to share your remaining invites',
                  'reminder to submit extra flips to get more rewards',
                  'status update of all your invitees to check if they are ready for the validation (activated invites, submitted flips)',
                ]}
              />
            )}
          </Stack>
        </DialogBody>
        <DialogFooter align="center">
          <Checkbox
            borderColor="gray.100"
            isChecked={doNotShowAgain}
            onChange={e => {
              setDoNotShowAgain(e.target.checked)
            }}
          >
            {t('Do not show again')}
          </Checkbox>
          <SecondaryButton
            onClick={() => {
              myIdenaBotDisclosure.onClose()
              if (doNotShowAgain) onConnect()
            }}
          >
            {t('Not now')}
          </SecondaryButton>
          <PrimaryButton
            ref={connectButtonRef}
            onClick={() => {
              openExternalUrl('https://t.me/MyIdenaBot')
              onConnect()
            }}
          >
            {t('Connect')}
          </PrimaryButton>
        </DialogFooter>
      </Dialog>
    </>
  )
}
Example #15
Source File: new.js    From idena-web with MIT License 4 votes vote down vote up
function NewVotingPage() {
  const {t, i18n} = useTranslation()

  const router = useRouter()

  const toast = useToast()

  const {isOpen: isOpenAdvanced, onToggle: onToggleAdvanced} = useDisclosure()

  const epochData = useEpoch()
  const {coinbase, privateKey} = useAuthState()
  const {
    data: {balance},
  } = useBalance()

  const [current, send, service] = useMachine(newVotingMachine, {
    actions: {
      onDone: () => {
        router.push(viewVotingHref(current.context.contractHash))
      },
      onError: (context, {data: {message}}) => {
        toast({
          // eslint-disable-next-line react/display-name
          render: () => (
            <Toast title={humanError(message, context)} status="error" />
          ),
        })
      },
      onInvalidForm: () => {
        toast({
          // eslint-disable-next-line react/display-name
          render: () => (
            <Toast title={t('Please correct form fields')} status="error" />
          ),
        })
      },
    },
  })

  React.useEffect(() => {
    if (epochData && coinbase) send('START', {epoch: epochData.epoch, coinbase})
  }, [coinbase, epochData, privateKey, send])

  const {
    options,
    startDate,
    votingDuration,
    publicVotingDuration,
    shouldStartImmediately,
    isFreeVoting,
    committeeSize,
    quorum = 1,
    winnerThreshold = '66',
    feePerGas,
    oracleReward,
    isWholeNetwork,
    oracleRewardsEstimates,
    ownerFee = 0,
    minOracleReward,
    votingMinPayment,
    dirtyBag,
  } = current.context

  const isInvalid = (field, cond = current.context[field]) =>
    dirtyBag[field] && !cond

  const isInvalidOptions = isInvalid('options', hasValuableOptions(options))
  const hasLinksInOptions = isInvalid('options', hasLinklessOptions(options))

  const handleChange = ({target: {id, value}}) => send('CHANGE', {id, value})
  const dna = toLocaleDna(i18n)

  return (
    <Layout showHamburger={false}>
      <Page px={0} py={0}>
        <Box px={20} py={6} w="full" overflowY="auto">
          <Flex justify="space-between" align="center">
            <PageTitle mb={0}>{t('New voting')}</PageTitle>
            <CloseButton
              ml="auto"
              onClick={() => router.push('/oracles/list')}
            />
          </Flex>
          <SuccessAlert my={8}>
            {t(
              'After publishing or launching, you will not be able to edit the voting parameters.'
            )}
          </SuccessAlert>

          {current.matches('preload.late') && <NewVotingFormSkeleton />}

          {!current.matches('preload') && (
            <Stack spacing={3}>
              <VotingInlineFormControl
                htmlFor="title"
                label={t('Title')}
                isInvalid={isInvalid('title')}
              >
                <Input id="title" onChange={handleChange} />
                {isInvalid('title') && (
                  <FormErrorMessage fontSize="md" mt={1}>
                    {t('You must provide title')}
                  </FormErrorMessage>
                )}
              </VotingInlineFormControl>

              <VotingInlineFormControl
                htmlFor="desc"
                label={t('Description')}
                isInvalid={isInvalid('desc')}
              >
                <Textarea id="desc" w="md" h={32} onChange={handleChange} />
                {isInvalid('desc') && (
                  <FormErrorMessage fontSize="md" mt={1}>
                    {t('You must provide description')}
                  </FormErrorMessage>
                )}
              </VotingInlineFormControl>

              <VotingInlineFormControl
                label={t('Voting options')}
                isInvalid={isInvalidOptions || hasLinksInOptions}
              >
                <Box
                  borderWidth={
                    isInvalidOptions || hasLinksInOptions ? '2px' : 1
                  }
                  borderColor={
                    isInvalidOptions || hasLinksInOptions
                      ? 'red.500'
                      : 'gray.100'
                  }
                  borderRadius="md"
                  p={1}
                  w="md"
                >
                  {options.map(({id, value}, idx) => (
                    <VotingOptionInput
                      key={id}
                      value={value}
                      placeholder={`${t('Option')} ${idx + 1}...`}
                      isLast={idx === options.length - 1}
                      isDisabled={[0, 1].includes(idx)}
                      onChange={({target}) => {
                        send('SET_OPTIONS', {id, value: target.value})
                      }}
                      onAddOption={() => {
                        send('ADD_OPTION')
                      }}
                      onRemoveOption={() => {
                        send('REMOVE_OPTION', {id})
                      }}
                      _invalid={null}
                    />
                  ))}
                </Box>
                {isInvalidOptions && (
                  <FormErrorMessage fontSize="md" mt={1}>
                    {t('You must provide at least 2 options')}
                  </FormErrorMessage>
                )}
                {hasLinksInOptions && (
                  <FormErrorMessage fontSize="md" mt={1}>
                    {t(
                      'Links are not allowed in voting options. Please use Description for links.'
                    )}
                  </FormErrorMessage>
                )}
              </VotingInlineFormControl>

              <VotingInlineFormControl
                htmlFor="startDate"
                label={t('Start date')}
                isDisabled={shouldStartImmediately}
                isInvalid={isInvalid(
                  'startDate',
                  startDate || shouldStartImmediately
                )}
                mt={4}
              >
                <Stack spacing={3} flex={1}>
                  <Input
                    id="startDate"
                    type="datetime-local"
                    onChange={handleChange}
                  />
                  {isInvalid(
                    'startDate',
                    startDate || shouldStartImmediately
                  ) && (
                    <FormErrorMessage fontSize="md" mt={-2}>
                      {t('You must either choose start date or start now')}
                    </FormErrorMessage>
                  )}
                  <Checkbox
                    id="shouldStartImmediately"
                    isChecked={shouldStartImmediately}
                    onChange={({target: {id, checked}}) => {
                      send('CHANGE', {id, value: checked})
                    }}
                  >
                    {t('Start now')}
                  </Checkbox>
                </Stack>
              </VotingInlineFormControl>

              <VotingDurationInput
                id="votingDuration"
                label={t('Voting duration')}
                value={votingDuration}
                tooltip={t('Secret voting period')}
                presets={[
                  durationPreset({hours: 12}),
                  durationPreset({days: 1}),
                  durationPreset({days: 2}),
                  durationPreset({days: 5}),
                  durationPreset({weeks: 1}),
                ]}
                service={service}
                mt={2}
              />

              <NewVotingFormSubtitle>
                {t('Oracles requirements')}
              </NewVotingFormSubtitle>

              <VotingInlineFormControl
                htmlFor="committeeSize"
                label={t('Committee size, oracles')}
                isInvalid={committeeSize < 1}
                tooltip={t(
                  'The number of randomly selected oracles allowed to vote'
                )}
                mt={2}
              >
                <Stack spacing={3} flex={1}>
                  <NumberInput
                    id="committeeSize"
                    value={committeeSize}
                    min={1}
                    step={1}
                    preventInvalidInput
                    isDisabled={isWholeNetwork}
                    onChange={({target: {id, value}}) => {
                      send('CHANGE_COMMITTEE', {id, value})
                    }}
                  />
                  <Checkbox
                    id="isWholeNetwork"
                    onChange={({target: {checked}}) => {
                      send('SET_WHOLE_NETWORK', {checked})
                    }}
                  >
                    {t('Whole network')}
                  </Checkbox>
                </Stack>
              </VotingInlineFormControl>

              <VotingInlineFormControl
                htmlFor="quorum"
                label={t('Quorum')}
                tooltip={t(
                  'The share of Oracle committee sufficient to determine the voting outcome'
                )}
                mt={2}
              >
                <Stack spacing={0} flex={1}>
                  <PercentInput
                    id="quorum"
                    value={quorum}
                    onChange={handleChange}
                  />
                  <NewOracleFormHelperText textAlign="right">
                    {t('{{count}} votes are required', {
                      count: quorumVotesCount({quorum, committeeSize}),
                    })}
                  </NewOracleFormHelperText>
                </Stack>
              </VotingInlineFormControl>

              <VotingInlineFormControl
                htmlFor="votingMinPayment"
                label={t('Voting deposit')}
                tooltip={t(
                  'Refunded when voting in majority and lost when voting in minority'
                )}
                isDisabled={isFreeVoting}
                mt={2}
              >
                <Stack spacing={3} flex={1}>
                  <DnaInput
                    id="votingMinPayment"
                    value={votingMinPayment}
                    isDisabled={isFreeVoting}
                    onChange={handleChange}
                  />
                  <Checkbox
                    id="isFreeVoting"
                    isChecked={isFreeVoting}
                    onChange={({target: {id, checked}}) => {
                      send('CHANGE', {id, value: checked})
                    }}
                  >
                    {t('No voting deposit for oracles')}
                  </Checkbox>
                </Stack>
              </VotingInlineFormControl>

              <NewVotingFormSubtitle>
                {t('Cost of voting')}
              </NewVotingFormSubtitle>

              <PresetFormControl
                label={t('Total funds')}
                tooltip={t(
                  'Total funds locked during the voting and paid to oracles and owner afterwards'
                )}
              >
                <PresetFormControlOptionList
                  value={String(oracleReward)}
                  onChange={value => {
                    send('CHANGE', {
                      id: 'oracleReward',
                      value,
                    })
                  }}
                >
                  {oracleRewardsEstimates.map(({label, value}) => (
                    <PresetFormControlOption key={value} value={String(value)}>
                      {label}
                    </PresetFormControlOption>
                  ))}
                </PresetFormControlOptionList>

                <PresetFormControlInputBox>
                  <DnaInput
                    id="oracleReward"
                    value={oracleReward * committeeSize || 0}
                    min={minOracleReward * committeeSize || 0}
                    onChange={({target: {id, value}}) => {
                      send('CHANGE', {
                        id,
                        value: (value || 0) / Math.max(1, committeeSize),
                      })
                    }}
                  />
                  <NewOracleFormHelperText textAlign="right">
                    {t('Min reward per oracle: {{amount}}', {
                      amount: dna(
                        rewardPerOracle({fundPerOracle: oracleReward, ownerFee})
                      ),
                      nsSeparator: '!',
                    })}
                  </NewOracleFormHelperText>
                </PresetFormControlInputBox>
              </PresetFormControl>

              <VotingInlineFormControl
                htmlFor="ownerFee"
                label={t('Owner fee')}
                tooltip={t('% of the Total funds you receive')}
              >
                <PercentInput
                  id="ownerFee"
                  value={ownerFee}
                  onChange={handleChange}
                />

                <NewOracleFormHelperText textAlign="right">
                  {t('Paid to owner: {{amount}}', {
                    amount: dna(
                      (oracleReward * committeeSize * Math.min(100, ownerFee)) /
                        100 || 0
                    ),
                    nsSeparator: '!',
                  })}
                </NewOracleFormHelperText>
              </VotingInlineFormControl>

              <NewVotingFormSubtitle
                cursor="pointer"
                onClick={onToggleAdvanced}
              >
                {t('Advanced settings')}
                <ChevronDownIcon
                  boxSize={5}
                  color="muted"
                  ml={1}
                  transform={isOpenAdvanced ? 'rotate(180deg)' : ''}
                  transition="all 0.2s ease-in-out"
                />
              </NewVotingFormSubtitle>

              <Collapse in={isOpenAdvanced} mt={2}>
                <Stack spacing={3}>
                  <VotingDurationInput
                    id="publicVotingDuration"
                    value={publicVotingDuration}
                    label={t('Counting duration')}
                    tooltip={t(
                      'Period when secret votes are getting published and results are counted'
                    )}
                    presets={[
                      durationPreset({hours: 12}),
                      durationPreset({days: 1}),
                      durationPreset({days: 2}),
                      durationPreset({days: 5}),
                      durationPreset({weeks: 1}),
                    ]}
                    service={service}
                  />

                  <PresetFormControl
                    label={t('Majority threshold')}
                    tooltip={t(
                      'The minimum share of the votes which an option requires to achieve before it becomes the voting outcome'
                    )}
                  >
                    <PresetFormControlOptionList
                      value={winnerThreshold}
                      onChange={value => {
                        send('CHANGE', {
                          id: 'winnerThreshold',
                          value,
                        })
                      }}
                    >
                      <PresetFormControlOption value="51">
                        {t('Simple majority')}
                      </PresetFormControlOption>
                      <PresetFormControlOption value="66">
                        {t('Super majority')}
                      </PresetFormControlOption>
                      <PresetFormControlOption value="100">
                        {t('N/A (polls)')}
                      </PresetFormControlOption>
                    </PresetFormControlOptionList>

                    <PresetFormControlInputBox>
                      <PercentInput
                        id="winnerThreshold"
                        value={winnerThreshold}
                        onChange={handleChange}
                      />
                    </PresetFormControlInputBox>
                  </PresetFormControl>
                </Stack>
              </Collapse>
            </Stack>
          )}
        </Box>

        <Stack
          isInline
          mt="auto"
          alignSelf="stretch"
          justify="flex-end"
          borderTop="1px"
          borderTopColor="gray.100"
          py={3}
          px={4}
        >
          <PrimaryButton
            isLoading={current.matches('publishing')}
            loadingText={t('Publishing')}
            onClick={() => send('PUBLISH')}
          >
            {t('Publish')}
          </PrimaryButton>
        </Stack>

        <ReviewVotingDrawer
          isOpen={current.matches('publishing')}
          onClose={() => send('CANCEL')}
          from={coinbase}
          available={balance}
          balance={votingMinBalance(oracleReward, committeeSize)}
          minStake={votingMinStake(feePerGas)}
          votingDuration={votingDuration}
          publicVotingDuration={publicVotingDuration}
          ownerFee={ownerFee}
          isLoading={eitherState(
            current,
            'publishing.deploy',
            `publishing.${VotingStatus.Starting}`
          )}
          // eslint-disable-next-line no-shadow
          onConfirm={({balance, stake}) =>
            send('CONFIRM', {privateKey, balance, stake})
          }
        />

        <NewOraclePresetDialog
          isOpen={eitherState(current, 'choosingPreset')}
          onChoosePreset={preset => send('CHOOSE_PRESET', {preset})}
          onCancel={() => send('CANCEL')}
        />
      </Page>
    </Layout>
  )
}
Example #16
Source File: restricted.js    From idena-web with MIT License 4 votes vote down vote up
export default function Restricted() {
  const [{apiKeyState, apiKeyData, apiKey}] = useSettings()
  const {saveConnection} = useSettingsDispatch()
  const {coinbase, privateKey} = useAuthState()
  const [{state: identityState}] = useIdentity()
  const auth = useAuthState()
  const router = useRouter()
  const {t} = useTranslation()

  const [, {updateRestrictedNotNow}] = useAppContext()

  const [step, setStep] = useState(steps.INITIAL)

  const [state, setState] = useState(options.PROLONG)
  const [dontShow, setDontShow] = useState(false)

  const buySharedNodeDisclosure = useDisclosure()

  const [submitting, setSubmitting] = useState(false)

  const failToast = useFailToast()

  const {isPurchasing, savePurchase} = useApikeyPurchasing()

  const [savedApiKey, setSavedApiKey] = useState()

  const size = useBreakpointValue(['lg', 'md'])
  const variantRadio = useBreakpointValue(['mobileDark', 'dark'])
  const variantSecondary = useBreakpointValue(['primaryFlat', 'secondary'])

  const notNow = persist => {
    if (persist) {
      updateRestrictedNotNow(dontShow)
    }
    router.back()
  }

  const getKeyForCandidate = async () => {
    setSubmitting(true)

    try {
      const providers = await getAvailableProviders()
      const signature = signMessage(hexToUint8Array(coinbase), privateKey)
      const result = await getCandidateKey(
        coinbase,
        toHexString(signature, true),
        providers
      )
      savePurchase(result.id, result.provider)
    } catch (e) {
      failToast(
        `Failed to get API key for Candidate: ${
          e.response ? e.response.data : 'unknown error'
        }`
      )
    } finally {
      setSubmitting(false)
    }
  }

  const process = async () => {
    if (state === options.PROLONG) {
      buySharedNodeDisclosure.onOpen()
    } else if (state === options.ENTER_KEY) {
      return router.push('/settings/node')
    } else if (state === options.CANDIDATE) {
      return getKeyForCandidate()
    } else if (state === options.RESTORE) {
      return saveConnection(savedApiKey.url, savedApiKey.key, false)
    } else return router.push('/node/rent')
  }

  const {data: provider, isError} = useQuery(
    ['get-provider-by-id', apiKeyData && apiKeyData.provider],
    () => getProvider(apiKeyData && apiKeyData.provider),
    {
      enabled: !!apiKeyData && !!apiKeyData.provider,
      retry: false,
      refetchOnWindowFocus: false,
    }
  )

  useEffect(() => {
    async function checkSaved() {
      try {
        const signature = signMessage(hexToUint8Array(coinbase), privateKey)
        const savedKey = await checkSavedKey(
          coinbase,
          toHexString(signature, true)
        )
        setSavedApiKey(savedKey)
        // eslint-disable-next-line no-empty
      } catch (e) {}
    }
    checkSaved()
  }, [apiKey, coinbase, privateKey])

  useEffect(() => {
    if (
      apiKeyState === ApiKeyStates.ONLINE ||
      apiKeyState === ApiKeyStates.EXTERNAL
    )
      router.push('/home')
  }, [apiKeyState, router])

  useEffect(() => {
    if (identityState === IdentityStatus.Candidate) {
      setState(options.CANDIDATE)
    } else if (savedApiKey) {
      setState(options.RESTORE)
    } else if ((provider && !provider.slots) || isError) {
      setState(options.BUY)
    }
  }, [identityState, isError, provider, savedApiKey])

  const waiting = submitting || isPurchasing

  const canProlong = provider && provider.slots && !waiting

  return (
    <Layout canRedirect={false}>
      <Flex
        bg={['gray.500', 'graphite.500']}
        alignItems="center"
        justifyContent="center"
        height="100%"
        direction="column"
        justify="center"
        flex="1"
      >
        <Flex
          flexGrow={1}
          align="center"
          justify={['flex-start', 'center']}
          mt="44px"
          mx={[3, 0]}
          direction="column"
        >
          <Flex
            direction="column"
            align={['center', 'initial']}
            maxWidth={['100%', '480px']}
          >
            <Flex
              direction={['column', 'row']}
              align="center"
              textAlign={['center', 'initial']}
              w={['60%', 'auto']}
            >
              <Avatar address={coinbase} />
              <Flex
                direction="column"
                justify="center"
                flex="1"
                ml={[0, 5]}
                mt={[5, 0]}
              >
                <SubHeading
                  fontSize={['mdx', 'lg']}
                  fontWeight={[400, 500]}
                  color={['muted', 'white']}
                  wordBreak="break-word"
                >
                  {auth.coinbase}
                </SubHeading>
              </Flex>
            </Flex>
            <Flex
              direction="column"
              mt={6}
              bg="gray.500"
              borderRadius="lg"
              px={[6, 10]}
              py={7}
              w={['100%', 'auto']}
            >
              {step === steps.INITIAL && (
                <Flex direction="column" alignItems="center" mt={6}>
                  <Flex>
                    <Text color="white" fontSize="lg">
                      {t('Restricted access')}
                    </Text>
                  </Flex>

                  <Flex mt={4}>
                    <Text fontSize="mdx" color="muted" textAlign="center">
                      {t(
                        'You can use all functions of the app except validation. Please connect to a shared node if you want to participate in the upcoming validation using the web app. '
                      )}
                    </Text>
                  </Flex>
                  <Flex justifyContent="center" mt={4}>
                    <PrimaryButton onClick={() => setStep(steps.CONNECT)}>
                      {t('Connect')}
                    </PrimaryButton>
                  </Flex>
                  <Flex
                    mt={10}
                    justifyContent="space-between"
                    alignSelf="normal"
                  >
                    <Flex>
                      <Checkbox
                        textAlign={['left', 'initial']}
                        value={dontShow}
                        isChecked={dontShow}
                        onChange={e => setDontShow(e.target.checked)}
                        color="white"
                      >
                        {t('Don’t show again')}
                      </Checkbox>
                    </Flex>
                    <Flex>
                      <SecondaryButton onClick={() => notNow(true)}>
                        {t('Not now')}
                      </SecondaryButton>
                    </Flex>
                  </Flex>
                </Flex>
              )}
              {step === steps.CONNECT && (
                <>
                  <Flex justify={['center', ' flex-start']}>
                    <Text color="white" fontSize="lg">
                      {t('Connect to a shared node')}
                    </Text>
                  </Flex>

                  <Flex mt={7}>
                    <Text color="muted" fontSize="sm">
                      {t('Choose an option')}
                    </Text>
                  </Flex>
                  <Flex mt={[2, 4]}>
                    <RadioGroup w={['100%', 'auto']}>
                      <Stack direction="column" spacing={[1, 3]}>
                        {savedApiKey && savedApiKey.url !== apiKey.url && (
                          <ChooseItemRadio
                            variant={variantRadio}
                            px={[4, 0]}
                            isChecked={state === options.RESTORE}
                            onChange={() => setState(options.RESTORE)}
                            alignItems={['center', 'flex-start']}
                          >
                            <Flex direction="column" mt={['auto', '-2px']}>
                              <Text color="white">
                                {t('Restore connection')}
                              </Text>
                              <Text color="muted" fontSize="sm">
                                {savedApiKey.url}
                              </Text>
                            </Flex>
                          </ChooseItemRadio>
                        )}
                        {identityState === IdentityStatus.Candidate && (
                          <ChooseItemRadio
                            variant={variantRadio}
                            px={[4, 0]}
                            isChecked={state === options.CANDIDATE}
                            onChange={() => setState(options.CANDIDATE)}
                          >
                            <Text color="white">{t('Get free access')}</Text>
                          </ChooseItemRadio>
                        )}
                        {canProlong && (
                          <ChooseItemRadio
                            variant={variantRadio}
                            px={[4, 0]}
                            isChecked={state === options.PROLONG}
                            onChange={() => setState(options.PROLONG)}
                            alignItems={['center', 'flex-start']}
                          >
                            <Flex direction="column" mt={['auto', '-2px']}>
                              <Text color="white">
                                {t('Prolong node access')}{' '}
                                {`(${GetProviderPrice(
                                  provider.data,
                                  identityState
                                )} iDNA)`}
                              </Text>
                              <Text color="muted" fontSize="sm">
                                {provider.data.url}
                              </Text>
                            </Flex>
                          </ChooseItemRadio>
                        )}
                        <ChooseItemRadio
                          variant={variantRadio}
                          px={[4, 0]}
                          isChecked={state === options.BUY}
                          onChange={() => setState(options.BUY)}
                        >
                          <Text color="white">
                            {canProlong
                              ? t('Rent another shared node')
                              : t('Rent a shared node')}
                          </Text>
                        </ChooseItemRadio>
                        <ChooseItemRadio
                          variant={variantRadio}
                          px={[4, 0]}
                          isChecked={state === options.ENTER_KEY}
                          onChange={() => setState(options.ENTER_KEY)}
                        >
                          <Text color="white">
                            {t('Enter shared node API key')}
                          </Text>
                        </ChooseItemRadio>
                      </Stack>
                    </RadioGroup>
                  </Flex>
                  <Flex mt={[4, 10]} justifyContent="space-between">
                    <Flex
                      direction={['column', 'row']}
                      ml="auto"
                      w={['100%', 'auto']}
                    >
                      <Button
                        variant={variantSecondary}
                        order={[2, 1]}
                        size={size}
                        w={['100%', 'auto']}
                        onClick={() => notNow(false)}
                        mr={[0, 2]}
                        mt={[2, 0]}
                      >
                        {t('Not now')}
                      </Button>
                      <PrimaryButton
                        order={[1, 2]}
                        size={size}
                        w={['100%', 'auto']}
                        onClick={process}
                        isDisabled={waiting}
                        isLoading={waiting}
                        loadingText="Waiting..."
                      >
                        {t('Continue')}
                      </PrimaryButton>
                    </Flex>
                  </Flex>
                </>
              )}
            </Flex>
          </Flex>
        </Flex>
        <Flex
          justify="center"
          mb={8}
          direction="column"
          justifyContent="center"
        >
          <Text color="white" fontSize="mdx" opacity="0.5" mb={1}>
            {t('You can run your own node at your desktop computer.')}
          </Text>
          <TextLink
            href="https://idena.io/download"
            target="_blank"
            color="white"
            textAlign="center"
          >
            <DownloadIcon boxSize={4} mx={2} />
            {t('Download Idena')}
          </TextLink>
        </Flex>
      </Flex>
      {provider && (
        <BuySharedNodeForm
          {...buySharedNodeDisclosure}
          providerId={provider.id}
          url={provider.data.url}
          from={coinbase}
          amount={GetProviderPrice(provider.data, identityState)}
          to={provider.data.address}
        />
      )}
    </Layout>
  )
}
Example #17
Source File: import.js    From idena-web with MIT License 4 votes vote down vote up
export default function ImportKey() {
  const size = useBreakpointValue(['lg', 'md'])
  const logoSize = useBreakpointValue(['88px', '80px'])
  const variant = useBreakpointValue(['mobile', 'initial'])
  const {t} = useTranslation()
  const [state, setState] = useState({
    key: '',
    password: '',
    saveKey: true,
  })
  const {apiKey} = useSettingsState()
  const {setNewKey, decryptKey} = useAuthDispatch()
  const [error, setError] = useState()
  const [isScanningQr, setIsScanningQr] = useState(false)
  const router = useRouter()
  const {setRestrictedKey} = useApikeyPurchasing()
  const [, {resetRestrictedModal}] = useAppContext()

  const addKey = () => {
    const key = decryptKey(state.key, state.password)
    if (key) {
      setError(null)
      setNewKey(state.key, state.password, state.saveKey)
      if (!apiKey) {
        setRestrictedKey()
      }
      sendSignIn(privateKeyToAddress(key))
      router.push('/home')
      resetRestrictedModal()
    } else {
      setError(t('Key or password is invalid. Try again.'))
    }
  }

  return (
    <AuthLayout>
      <AuthLayout.Normal>
        <Flex
          direction={['column', 'initial']}
          align={['center', 'initial']}
          width="100%"
        >
          <img
            src="/static/idena-logo-circle.svg"
            alt="logo"
            width={logoSize}
            height={logoSize}
          />
          <Flex
            direction="column"
            justify="center"
            flex="1"
            w={['85%', '100%']}
            m={['48px 0 0 0', '0 0 0 20px']}
          >
            <SubHeading color="white">
              {t('Import your private key backup to sign in')}
            </SubHeading>
            <Flex justify="space-between">
              <Text color="xwhite.050" fontSize="mdx">
                {t(
                  'Enter your private key backup. You can export your private key from Idena app (see Settings page).'
                )}
              </Text>
            </Flex>
          </Flex>
        </Flex>
        <Flex w="100%" mt="24px">
          <form
            onSubmit={async e => {
              e.preventDefault()
              addKey()
            }}
            style={{width: '100%'}}
          >
            <FormLabel
              display={['none', 'inherit']}
              htmlFor="key"
              style={{color: 'white', fontSize: 'md'}}
            >
              {t('Encrypted private key')}
            </FormLabel>
            <Flex w="100%" mb={[3, 5]} style={{position: 'relative'}}>
              <Input
                id="key"
                opacity={[0.8, 1]}
                size={size}
                value={state.key}
                borderColor="xblack.008"
                backgroundColor="xblack.016"
                onChange={e => setState({...state, key: e.target.value})}
                placeholder={t('Enter your private key backup')}
              />
              <Box
                display={['initial', 'none']}
                style={{
                  cursor: 'pointer',
                  position: 'absolute',
                  top: '10px',
                  right: '6px',
                  zIndex: 5,
                }}
                onClick={() => {}}
              >
                <QrScanIcon
                  boxSize="28px"
                  onClick={() => {
                    setIsScanningQr(true)
                  }}
                ></QrScanIcon>
              </Box>
            </Flex>
            <FormLabel
              display={['none', 'inherit']}
              htmlFor="key"
              style={{
                color: 'white',
                fontSize: 'md',
              }}
            >
              {t('Password')}
            </FormLabel>
            <Flex width="100%">
              <PasswordInput
                size={size}
                value={state.password}
                width="100%"
                borderColor="xblack.008"
                backgroundColor="xblack.016"
                onChange={e =>
                  setState({
                    ...state,
                    password: e.target.value,
                  })
                }
                placeholder={t('Enter your password')}
              />
            </Flex>
            <Flex
              mt={[4, 8]}
              direction={['column', 'initial']}
              justify="space-between"
            >
              <Checkbox
                pt={[7, 0]}
                order={[2, 1]}
                variant={variant}
                value={state.saveKey}
                isChecked={state.saveKey}
                onChange={e => setState({...state, saveKey: e.target.checked})}
                style={{fontWeight: 300}}
              >
                {t('Save the encrypted key on this device')}
              </Checkbox>
              <Flex order={[1, 2]}>
                <SecondaryButton
                  isFullWidth={[true, false]}
                  display={['none', 'initial']}
                  variant="secondary"
                  css={{marginRight: '10px'}}
                  onClick={() => router.push('/')}
                >
                  {t('Cancel')}
                </SecondaryButton>
                <PrimaryButton
                  size={size}
                  isFullWidth={[true, false]}
                  type="submit"
                  disabled={!state.key}
                >
                  {t('Import')}
                </PrimaryButton>
              </Flex>
            </Flex>
            {error && (
              <Flex
                mt="30px"
                fontSize="mdx"
                style={{
                  backgroundColor: theme.colors.danger,
                  borderRadius: '9px',
                  padding: `18px 24px`,
                }}
              >
                {error}
              </Flex>
            )}
          </form>
        </Flex>
      </AuthLayout.Normal>
      {isScanningQr && (
        <QrScanner
          isOpen={isScanningQr}
          onScan={key => {
            if (key) {
              setState({key})
              setIsScanningQr(false)
            }
          }}
          onClose={() => setIsScanningQr(false)}
        />
      )}
    </AuthLayout>
  )
}