@material-ui/core#TableHead TypeScript Examples

The following examples show how to use @material-ui/core#TableHead. 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: OpenOrdersDialog.tsx    From swap-ui with Apache License 2.0 6 votes vote down vote up
function OpenOrdersAccounts() {
  const styles = useStyles();
  const openOrders = useOpenOrders();
  const openOrdersEntries: Array<[PublicKey, OpenOrders[]]> = useMemo(() => {
    return Array.from(openOrders.entries()).map(([market, oo]) => [
      new PublicKey(market),
      oo,
    ]);
  }, [openOrders]);
  return (
    <TableContainer component={Paper} elevation={0}>
      <Table className={styles.table} aria-label="simple table">
        <TableHead>
          <TableRow>
            <TableCell>Market</TableCell>
            <TableCell align="center">Open Orders Account</TableCell>
            <TableCell align="center">Base Used</TableCell>
            <TableCell align="center">Base Free</TableCell>
            <TableCell align="center">Quote Used</TableCell>
            <TableCell align="center">Quote Free</TableCell>
            <TableCell align="center">Settle</TableCell>
            <TableCell align="center">Close</TableCell>
          </TableRow>
        </TableHead>
        <TableBody>
          {openOrdersEntries.map(([market, oos]) => {
            return (
              <OpenOrdersRow
                key={market.toString()}
                market={market}
                openOrders={oos}
              />
            );
          })}
        </TableBody>
      </Table>
    </TableContainer>
  );
}
Example #2
Source File: PricingPage.tsx    From clearflask with Apache License 2.0 6 votes vote down vote up
FeatureList = withStyles(styles, { withTheme: true })((props: WithStyles<typeof styles, true> & {
  planNames: string[],
  name: string,
  children?: any,
}) => {
  const theme = useTheme();
  const mdUp = useMediaQuery(theme.breakpoints.up('sm'));
  return (
    <div className={props.classes.box}>
      <Table
        size={mdUp ? 'medium' : 'small'}
      >
        <TableHead>
          <TableRow>
            <TableCell key='feature'><Typography variant='h6'>{props.name}</Typography></TableCell>
            {props.planNames.map(planName => (
              <TableCell key={planName}>{planName}</TableCell>
            ))}
          </TableRow>
        </TableHead>
        <TableBody>
          {props.children}
        </TableBody>
      </Table>
    </div>
  );
})
Example #3
Source File: TableDetails.tsx    From SeeQR with MIT License 6 votes vote down vote up
TableDetails = ({ table }: TableDetailsProps) => (
  <>
    <Typography variant="h3">{`${table?.table_name}`}</Typography>
    <br />
    <TableContainer component={StyledPaper}>
      <Table>
        <TableHead>
          <TableRow>
            <TableCell>
              <strong>Column</strong>
            </TableCell>
            <TableCell align="right">
              <strong>Type</strong>
            </TableCell>
            <TableCell align="right">
              <strong>Is Nullable?</strong>
            </TableCell>
          </TableRow>
        </TableHead>
        <TableBody>
          {table?.columns.map((row) => (
            <TableRow key={row.column_name}>
              <StyledCell key={row?.column_name}>{row?.column_name}</StyledCell>
              <StyledCell align="right">
                {`${row?.data_type}${
                  row?.character_maximum_length
                    ? `(${row.character_maximum_length})`
                    : ''
                }`}
              </StyledCell>
              <StyledCell align="right">{row?.is_nullable}</StyledCell>
            </TableRow>
          ))}
        </TableBody>
      </Table>
    </TableContainer>
  </>
)
Example #4
Source File: Header.tsx    From postgres-nest-react-typescript-boilerplate with GNU General Public License v3.0 6 votes vote down vote up
TableHeader: FC<{
  data: TodosTableHeader[];
  headerStyle?: HeaderStyle;
}> = ({ data, headerStyle = {} }) => {
  return (
    <TableHead>
      <TableRow>
        {data.map((column, i) => (
          <TableCell
            key={i}
            align="left"
            style={{
              minWidth: column.minWidth,
              fontSize: '1.5rem',
              fontWeight: 600,
              height: '48px',
              background: 'black',
              color: 'white',
              ...headerStyle
            }}
          >
            {column.label}
          </TableCell>
        ))}
      </TableRow>
    </TableHead>
  );
}
Example #5
Source File: VotesTable.tsx    From homebase-app with MIT License 6 votes vote down vote up
VotesTable: React.FC<{ data: RowData[] }> = ({data}) => {
  const theme = useTheme();
  const isSmall = useMediaQuery(theme.breakpoints.down("sm"))

  return (
    <>
      <Table>
        <TableHead>
          <TableRow>
            {titles.map((title, i) => (
              <TableCell key={`votestitle-${i}`}>{title}</TableCell>
            ))}
          </TableRow>
        </TableHead>
        <TableBody>
          {data.map((row, i) => (
            <TableRow key={`votesrow-${i}`}>
              <TableCell>{isSmall ? toShortAddress(row.address) : row.address}</TableCell>
              <TableCell>{row.votes}</TableCell>
            </TableRow>
          ))}
        </TableBody>
      </Table>
    </>
  );
}
Example #6
Source File: RecentGames.tsx    From planning-poker with MIT License 5 votes vote down vote up
RecentGames = () => {
  const history = useHistory();
  const [recentGames, setRecentGames] = useState<Game[] | undefined>(undefined);

  useEffect(() => {
    async function fetchData() {
      const games = await getPlayerRecentGames();
      if (games) {
        setRecentGames(games);
      }
    }
    fetchData();
  }, []);

  const isEmptyRecentGames = (): boolean => {
    if (!recentGames) {
      return true;
    }
    if (recentGames && recentGames.length === 0) {
      return true;
    }
    return false;
  };

  return (
    <Card variant='outlined' className='RecentGamesCard'>
      <CardHeader
        className='RecentGamesCardTitle'
        title='Recent Session'
        titleTypographyProps={{ variant: 'h6', noWrap: true }}
      />
      <CardContent className='RecentGamesCardContent'>
        {isEmptyRecentGames() && (
          <Typography variant='body2'>No recent sessions found</Typography>
        )}
        {recentGames && recentGames.length > 0 && (
          <TableContainer className='RecentGamesTableContainer'>
            <Table stickyHeader>
              <TableHead>
                <TableRow>
                  <TableCell>Name</TableCell>
                  <TableCell>Created By</TableCell>
                  <TableCell></TableCell>
                </TableRow>
              </TableHead>
              <TableBody>
                {recentGames.map((recentGame) => (
                  <TableRow
                    hover
                    key={recentGame.id}
                    className='RecentGamesTableRow'
                    onClick={() => history.push(`/game/${recentGame.id}`)}
                  >
                    <TableCell>{recentGame.name}</TableCell>
                    <TableCell align='left'>{recentGame.createdBy}</TableCell>
                    <TableCell align='left'></TableCell>
                  </TableRow>
                ))}
              </TableBody>
            </Table>
          </TableContainer>
        )}
      </CardContent>
    </Card>
  );
}
Example #7
Source File: MTable.tsx    From crossfeed with Creative Commons Zero v1.0 Universal 5 votes vote down vote up
MTable = <T extends object>(props: Props<T>) => {
  const { instance, footerRows, ...rest } = props;
  const classes = useStyles();

  return (
    <Table {...instance.getTableProps} {...rest}>
      <TableHead classes={{ root: classes.head }}>
        {instance.headerGroups.map((group) => (
          <TableRow {...group.getHeaderGroupProps()} key={group.id}>
            {group.headers.map((column) => (
              <TableCell
                {...column.getHeaderProps()}
                key={column.id}
                classes={{ root: classes.cell }}
              >
                {column.render('Header')}
              </TableCell>
            ))}
          </TableRow>
        ))}
      </TableHead>
      <TableBody {...instance.getTableBodyProps()}>
        {instance.rows.map((row) => {
          instance.prepareRow(row);
          const { key, ...rest } = row.getRowProps();
          return (
            <React.Fragment key={key}>
              <TableRow {...rest}>
                {row.cells.map((cell) => (
                  <TableCell
                    {...cell.getCellProps()}
                    key={`${cell.row},${cell.column}`}
                    classes={{ root: classes.cell }}
                  >
                    {cell.render('Cell')}
                  </TableCell>
                ))}
              </TableRow>
            </React.Fragment>
          );
        })}
      </TableBody>
      {footerRows && <TableFooter>{footerRows}</TableFooter>}
    </Table>
  );
}
Example #8
Source File: TransactionList.tsx    From clearflask with Apache License 2.0 5 votes vote down vote up
render() {
    if (!this.props.isLoggedIn) {
      return (<ErrorMsg msg='You need to log in to see your balance' variant='info' />);
    }

    if (!this.props.transactions?.length) return null;

    var cumulativeBalance = this.props.balance || 0;
    return (
      <div className={this.props.className}>
        <PanelTitle text='Transaction history' />
        <div className={this.props.classes.transactionsTable}>
          <Table>
            <TableHead>
              <TableRow>
                <TableCell key='date'>Date</TableCell>
                <TableCell key='type'>Type</TableCell>
                <TableCell key='description'>Description</TableCell>
                <TableCell key='amount' align='right'>Amount</TableCell>
                <TableCell key='balance' align='right'>Account balance</TableCell>
              </TableRow>
            </TableHead>
            <TableBody>
              {this.props.credits !== undefined && this.props.balance !== undefined && this.props.transactions !== undefined && this.props.transactions.map(transaction => {
                const transactionBalance = cumulativeBalance;
                cumulativeBalance += transaction.amount;
                return (
                  <TableRow key={transaction.transactionId}>
                    <TableCell key='date'>
                      <Typography><TimeAgo date={transaction.created} /></Typography>
                    </TableCell>
                    <TableCell key='type'>
                      <Typography>{transaction.transactionType}</Typography>
                    </TableCell>
                    <TableCell key='description'>
                      {transaction.summary}
                      {transaction.transactionType === Client.TransactionType.Vote && transaction.targetId && (
                        <Button
                          component={Link}
                          to={preserveEmbed(`/post/${transaction.targetId}`)}
                        >
                          View
                        </Button>
                      )}
                    </TableCell>
                    <TableCell key='amount'>
                      <CreditView val={transaction.amount} credits={this.props.credits!} />
                    </TableCell>
                    <TableCell key='balance'>
                      <CreditView val={transactionBalance} credits={this.props.credits!} />
                    </TableCell>
                  </TableRow>
                )
              })}
            </TableBody>
          </Table>
        </div>
        {this.props.getNextTransactions && (
          <Button style={{ margin: 'auto', display: 'block' }} onClick={() => this.props.getNextTransactions && this.props.getNextTransactions()}>
            Show more
          </Button>
        )}
      </div>
    );
  }
Example #9
Source File: UsersTable.tsx    From homebase-app with MIT License 5 votes vote down vote up
StyledTableHead = styled(TableHead)({
  minHeight: 34,
})
Example #10
Source File: Pager.tsx    From glific-frontend with GNU Affero General Public License v3.0 5 votes vote down vote up
Pager: React.SFC<PagerProps> = (props) => {
  const {
    data,
    columnStyles,
    showCheckbox,
    columnNames,
    tableVals,
    listItemName,
    handleTableChange,
    totalRows,
    collapseOpen,
    collapseRow,
    removeSortBy = [],
  } = props;

  const rows = createRows(data, columnStyles, showCheckbox, collapseRow, collapseOpen);
  const tableHead = tableHeadColumns(
    columnNames,
    columnStyles,
    tableVals,
    handleTableChange,
    showCheckbox,
    listItemName,
    removeSortBy
  );

  const tablePagination = pagination(columnNames, totalRows, handleTableChange, tableVals);

  return (
    <div className={styles.TableContainer}>
      <Table className={styles.Table} data-testid="table">
        <TableHead className={styles.TagListHeader} data-testid="tableHead">
          {tableHead}
        </TableHead>
        <TableBody data-testid="tableBody">{rows}</TableBody>
        <TableFooter className={styles.TableFooter} data-testid="tableFooter">
          <TableRow>{tablePagination}</TableRow>
        </TableFooter>
      </Table>
    </div>
  );
}
Example #11
Source File: HealthIndicatorTable.tsx    From abacus with GNU General Public License v2.0 5 votes vote down vote up
export default function HealthIndicatorTable({
  className,
  indicators,
}: {
  className?: string
  indicators: HealthIndicator[]
}): JSX.Element {
  const classes = useStyles()
  const decorationClasses = useDecorationStyles()
  return (
    <TableContainer className={className}>
      <Table className={classes.table} aria-label='simple table'>
        <TableHead>
          <TableRow>
            <TableCell>Name</TableCell>
            <TableCell>Unit</TableCell>
            <TableCell>Value</TableCell>
            <TableCell>{/* Indication Emoji */}</TableCell>
            <TableCell>Indication</TableCell>
            <TableCell>Reason</TableCell>
            <TableCell>Recommendation</TableCell>
          </TableRow>
        </TableHead>
        <TableBody>
          {indicators.map((indicator) => (
            <TableRow key={indicator.name}>
              <TableCell scope='row'>
                <Link href={indicator.link} target='_blank'>
                  {indicator.name}
                </Link>
              </TableCell>
              <TableCell scope='row' className={clsx(classes.monospace, classes.deemphasized, classes.nowrap)}>
                {indicator.unit === HealthIndicatorUnit.Pvalue ? (
                  <Tooltip title='The smaller the p-value the more likely there is an issue.'>
                    <span className={decorationClasses.tooltipped}>p-value</span>
                  </Tooltip>
                ) : (
                  <span>{indicator.unit}</span>
                )}
              </TableCell>
              <TableCell scope='row' className={clsx(classes.monospace, classes.deemphasized, classes.nowrap)}>
                {indicator.value.toFixed(4)}
              </TableCell>
              <TableCell scope='row'>
                <span>{severityEmoji[indicator.indication.severity]}</span>
              </TableCell>
              <TableCell
                scope='row'
                className={clsx(
                  classes.indication,
                  classes[indicationSeverityClassSymbol(indicator.indication.severity)],
                  classes.monospace,
                  classes.nowrap,
                )}
              >
                <span>{indicator.indication.code}</span>
              </TableCell>
              <TableCell scope='row' className={clsx(classes.monospace, classes.deemphasized, classes.nowrap)}>
                {indicator.indication.reason}
              </TableCell>
              <TableCell scope='row' className={clsx(classes.deemphasized, classes.recommendation)}>
                <Typography variant='body1'>{indicator.indication.recommendation}</Typography>
              </TableCell>
            </TableRow>
          ))}
        </TableBody>
      </Table>
    </TableContainer>
  )
}
Example #12
Source File: RouteTable.tsx    From dashboard with Apache License 2.0 5 votes vote down vote up
RoutesTable = ({ routes }: RoutesTableProps) => {
  return (
    <Card>
      <CardHeader
        title="Routes (List of Pods)"
        titleTypographyProps={{ variant: "subtitle1" }}
      />
      {routes && routes?.length && (
        <CardContent>
          <Table>
            <TableHead>
              <TableRow>
                <TableCell>Pod</TableCell>
                <TableCell>Pod Id</TableCell>
                <TableCell>Start time</TableCell>
                <TableCell>End time</TableCell>
                <TableCell>Elapsed Time</TableCell>
              </TableRow>
            </TableHead>
            <TableBody>
              {routes.map((route) => {
                const { pod_id, pod, start_time, end_time } = route
                return (
                  <TableRow key={pod_id}>
                    <TableCell> {pod} </TableCell>
                    <TableCell>{pod_id}</TableCell>
                    <TableCell>{start_time}</TableCell>
                    <TableCell>{end_time}</TableCell>
                    <TableCell>
                      {getElapsedTime(start_time, end_time)}
                    </TableCell>
                  </TableRow>
                )
              })}
            </TableBody>
          </Table>
        </CardContent>
      )}
    </Card>
  )
}
Example #13
Source File: object-parameters.tsx    From mtcute with GNU Lesser General Public License v3.0 5 votes vote down vote up
export function ObjectParameters({
    obj,
    diff,
    history,
}: {
    obj: ExtendedTlObject
    diff?: boolean
    history?: boolean
}): JSX.Element {
    const classes = useStyles()

    return (
        <Table className={classes.table}>
            <TableHead>
                <TableRow>
                    {diff && <TableCell>Change</TableCell>}
                    <TableCell>Name</TableCell>
                    <TableCell>Type</TableCell>
                    <TableCell>Description</TableCell>
                </TableRow>
            </TableHead>
            <TableBody>
                {obj.arguments.map((arg) => (
                    <TableRow key={arg.name} className={arg.className}>
                        {diff && (
                            <TableCell
                                className={clsx(
                                    classes.changed,
                                    classes[arg.changed!]
                                )}
                            >
                                {arg.changed}
                            </TableCell>
                        )}
                        <TableCell>
                            <code
                                className={
                                    !arg.optional &&
                                    arg.type !== '$FlagsBitField'
                                        ? classes.bold
                                        : undefined
                                }
                            >
                                {arg.name}
                            </code>
                        </TableCell>
                        <TableCell className={classes.mono}>
                            {arg.optional ? (
                                <span title={arg.predicate}>
                                    {LinkToTl(arg.type, history)}?
                                </span>
                            ) : (
                                LinkToTl(arg.type, history)
                            )}
                        </TableCell>
                        <Description
                            description={arg.description}
                            component={TableCell}
                        />
                    </TableRow>
                ))}
            </TableBody>
        </Table>
    )
}
Example #14
Source File: CompareTable.tsx    From SeeQR with MIT License 5 votes vote down vote up
CompareTable = ({ queries }: CompareTableProps) => {
  const comparedQueries = analyze(Object.values(queries));
  comparedQueries.sort(
    (a, b) =>
      // sort by group alphabetically
      a.group.localeCompare(b.group) ||
      // if same group, sort by speed ascending
      a.relativeSpeed - b.relativeSpeed
  );

  return (
    <TableBg>
      <Table>
        <TableHead>
          <TableRow>
            {tableInfo.map(([column, alignment]) => (
              <TableCell key={column} align={alignment}>
                {column}
              </TableCell>
            ))}
          </TableRow>
        </TableHead>
        <TableBody>
          {comparedQueries.map((query: AnalysedQuery) => (
            <TableRow key={query.label + query.db + query.group}>
              {tableInfo.map(([columnLabel, alignment, transformer]) => (
                <StyledCell
                  align={alignment}
                  key={`${query.label}_${query.db}_${query.group}_${columnLabel}`}
                  $isFastest={query.isFastest}
                  $isMarker={!columnLabel}
                >
                  {transformer(query)}
                </StyledCell>
              ))}
            </TableRow>
          ))}
        </TableBody>
      </Table>
    </TableBg>
  );
}
Example #15
Source File: CallStatusTable.tsx    From twilio-voice-notification-app with Apache License 2.0 5 votes vote down vote up
CallStatusTable: React.FC<CallStatusTableProps> = ({
  recipients,
  meta,
  loading,
  pageCount,
  rowsPerPage,
  setRowsPerPage,
  currentPage,
  setCurrentPage,
}) => {
  const rowsPerPageOptions = useRowsPerPageOptions(meta?.total);

  const onChangeRowsPerPage = useCallback(
    (event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
      const rows = parseInt(event.target.value, 10);
      setRowsPerPage(rows);
      setCurrentPage(0);
    },
    [setRowsPerPage, setCurrentPage]
  );

  const onChangePagination = useCallback(
    (event: unknown, value: number) => {
      setCurrentPage(value);
    },
    [setCurrentPage]
  );

  return (
    <>
      {recipients && recipients.length > 0 && (
        <>
          <TableContainer
            component={Paper}
            style={{
              marginBottom: loading ? '0' : '4px',
            }}
          >
            <Table
              aria-label="Notification recipients calls details and statuses"
              size="small"
              data-testid={RECIPIENTS_TABLE_TEST_ID}
            >
              <TableHead>
                <TableRow>
                  <TableCell>Number</TableCell>
                  <TableCell>Status</TableCell>
                </TableRow>
              </TableHead>
              <TableBody>
                {recipients?.map((recipient) => (
                  <TableRow key={recipient.callSid}>
                    <TableCell>{recipient.to}</TableCell>
                    <TableCell>{recipient.status}</TableCell>
                  </TableRow>
                ))}
              </TableBody>
            </Table>
          </TableContainer>
          {loading && <LinearProgress />}
        </>
      )}
      {pageCount > 0 && meta.total && (
        <TablePagination
          data-testid={PAGINATOR_TEST_ID}
          rowsPerPageOptions={rowsPerPageOptions}
          component="div"
          page={currentPage}
          count={meta.total}
          rowsPerPage={rowsPerPage}
          onChangePage={onChangePagination}
          onChangeRowsPerPage={onChangeRowsPerPage}
        />
      )}
    </>
  );
}
Example #16
Source File: DialogBody.tsx    From backstage with Apache License 2.0 5 votes vote down vote up
export function DialogBody() {
  const classes = useStyles();
  const { stats } = useGetStats();
  const { project } = useProjectContext();

  if (stats.error) {
    return (
      <Alert severity="error">Unexpected error: {stats.error.message}</Alert>
    );
  }

  if (stats.loading) {
    return <Progress />;
  }

  if (!stats.value) {
    return <Alert severity="error">Couldn't find any stats :(</Alert>;
  }

  const { allReleases, allTags } = stats.value;
  const { mappedReleases } = getMappedReleases({ allReleases, project });
  const { releaseStats } = getReleaseStats({
    mappedReleases,
    allTags,
    project,
  });

  return (
    <ReleaseStatsContext.Provider value={{ releaseStats }}>
      <Info />

      <TableContainer>
        <Table className={classes.table} size="small">
          <TableHead>
            <TableRow>
              <TableCell />
              <TableCell>Release</TableCell>
              <TableCell>Created at</TableCell>
              <TableCell># candidate patches</TableCell>
              <TableCell># release patches</TableCell>
            </TableRow>
          </TableHead>

          <TableBody>
            {Object.entries(releaseStats.releases).map(
              ([baseVersion, releaseStat], index) => {
                return (
                  <Row
                    key={`row-${index}`}
                    baseVersion={baseVersion}
                    releaseStat={releaseStat}
                  />
                );
              },
            )}
          </TableBody>
        </Table>

        {(releaseStats.unmappableTags.length > 0 ||
          releaseStats.unmatchedTags.length > 0 ||
          releaseStats.unmatchedReleases.length > 0) && <Warn />}
      </TableContainer>
    </ReleaseStatsContext.Provider>
  );
}
Example #17
Source File: CartTable.tsx    From storefront with MIT License 5 votes vote down vote up
CartTable: React.VFC<Props> = ({ cart, loading, onUpdate }) => {
  const styles = useStyles();

  return (
    <Table className={styles.root}>
      <TableHead sx={{ display: { xs: 'none', sm: 'table-header-group' } }}>
        <TableRow>
          <TableCell colSpan={2}>Product</TableCell>
          <TableCell>Price</TableCell>
          <TableCell>Quantity</TableCell>
          <TableCell colSpan={2}>Total Price</TableCell>
        </TableRow>
      </TableHead>
      <TableBody sx={{ display: { xs: 'block', sm: 'table-row-group' } }}>
        {cart.contents?.nodes?.map(
          (item) =>
            item != null && (
              <CartTableRow key={item.key} item={item} loading={loading} onUpdate={onUpdate} />
            ),
        )}
      </TableBody>
      <TableFooter className={styles.footer}>
        <TableRow>
          <TableCell colSpan={3} />
          <TableCell>
            <Typography>Subtotal</Typography>
          </TableCell>
          <TableCell colSpan={2}>
            <Price>{cart.subtotal}</Price>
          </TableCell>
        </TableRow>
        {(cart.appliedCoupons?.length ?? 0) > 0 && (
          <TableRow>
            <TableCell colSpan={3} />
            <TableCell>
              <Typography>Discount</Typography>
            </TableCell>
            <TableCell colSpan={2}>
              <Price color="error">{`-${cart.discountTotal}`}</Price>
            </TableCell>
          </TableRow>
        )}
      </TableFooter>
    </Table>
  );
}
Example #18
Source File: UserBookings.tsx    From office-booker with MIT License 4 votes vote down vote up
UserBookings: React.FC<RouteComponentProps<{ email: string }>> = (props) => {
  // Global state
  const { state, dispatch } = useContext(AppContext);
  const { user } = state;

  // Local state
  const [loading, setLoading] = useState(true);
  const [selectedUser, setSelectedUser] = useState<User | undefined>();
  const [bookings, setBookings] = useState<Booking[] | undefined>();
  const [bookingToCancel, setBookingToCancel] = useState<undefined | Booking>();
  const [sortedBookings, setSortedBookings] = useState<Booking[] | undefined>();

  const [sortBy, setSortBy] = useState<keyof Booking>('date');
  const [sortOrder, setSortOrder] = useState<SortOrder>('asc');

  // Theme
  const theme = useTheme();
  const fullScreen = useMediaQuery(theme.breakpoints.down('sm'));

  // Effects
  useEffect(() => {
    if (props.email) {
      getBookings({ user: props.email })
        .then((data) => {
          // Split for previous and upcoming
          setBookings(data);
        })
        .catch((err) => {
          // Handle errors
          setLoading(false);

          dispatch({
            type: 'SET_ALERT',
            payload: {
              message: formatError(err),
              color: 'error',
            },
          });
        });
    }
  }, [props.email, dispatch]);

  useEffect(() => {
    if (user && !user.permissions.canViewUsers) {
      // No permissions - Bounce to home page
      navigate('/');
    }
  }, [user]);

  useEffect(() => {
    if (user) {
      // Get selected user
      getUser(props.email || '')
        .then((selectedUser) => setSelectedUser(selectedUser))
        .catch((err) => {
          // Handle errors
          setLoading(false);

          dispatch({
            type: 'SET_ALERT',
            payload: {
              message: formatError(err),
              color: 'error',
            },
          });
        });
    }
  }, [user, props.email, dispatch]);

  useEffect(() => {
    if (bookings) {
      // Sort it!
      setSortedBookings(sortData([...bookings], sortBy, sortOrder));
    }
  }, [bookings, sortBy, sortOrder]);

  useEffect(() => {
    if (bookings) {
      // Wait for global state to be ready
      setLoading(false);
    }
  }, [bookings]);

  // Handlers
  const handleSort = (key: keyof Booking) => {
    if (key === sortBy) {
      setSortOrder(sortOrder === 'desc' ? 'asc' : 'desc');
    } else {
      setSortBy(key);
    }
  };

  const getAllBookings = useCallback(() => {
    if (state.user) {
      getBookings({ user: state.user.email })
        .then((data) => {
          // Split for previous and upcoming
          setBookings(data);
        })
        .catch((err) => {
          // Handle errors
          setLoading(false);

          dispatch({
            type: 'SET_ALERT',
            payload: {
              message: formatError(err),
              color: 'error',
            },
          });
        });
    }
  }, [state.user, dispatch]);

  const handleCancelBooking = (booking: Booking) => {
    cancelBooking(booking.id, booking.user)
      .then(() => {
        // Clear selected booking
        setBookingToCancel(undefined);

        // Retrieve updated bookings
        getAllBookings();

        // Show confirmation alert
        dispatch({
          type: 'SET_ALERT',
          payload: {
            message: 'Booking cancelled',
            color: 'success',
          },
        });
      })
      .catch((err) =>
        dispatch({
          type: 'SET_ALERT',
          payload: {
            message: formatError(err),
            color: 'error',
          },
        })
      );
  };

  // Render
  if (!user) {
    return null;
  }

  return (
    <AdminLayout currentRoute="users">
      <UserBookingsStyles>
        {loading || !selectedUser ? (
          <Loading />
        ) : (
          <>
            <h3>User Bookings</h3>

            <Paper square className="table-container">
              <h4>{selectedUser.email}</h4>
              <TableContainer className="table">
                <Table>
                  <TableHead>
                    <TableRow>
                      <TableCell className="table-header">
                        <TableSortLabel
                          active={sortBy === 'office'}
                          direction={sortOrder}
                          onClick={() => handleSort('office')}
                        >
                          Office
                        </TableSortLabel>
                      </TableCell>
                      <TableCell className="table-header">
                        <TableSortLabel
                          active={sortBy === 'date'}
                          direction={sortOrder}
                          onClick={() => handleSort('date')}
                        >
                          Date
                        </TableSortLabel>
                      </TableCell>
                      <TableCell className="table-header">
                        <TableSortLabel
                          active={sortBy === 'parking'}
                          direction={sortOrder}
                          onClick={() => handleSort('parking')}
                        >
                          Parking
                        </TableSortLabel>
                      </TableCell>
                      <TableCell />
                    </TableRow>
                  </TableHead>
                  <TableBody>
                    {sortedBookings && sortedBookings.length > 0 ? (
                      sortedBookings.map((booking, index) => {
                        const parsedDate = parseISO(booking.date);

                        return (
                          <TableRow key={index}>
                            <TableCell>{booking.office.name}</TableCell>
                            <TableCell>
                              {' '}
                              {format(
                                parse(booking.date, 'yyyy-MM-dd', new Date(), DATE_FNS_OPTIONS),
                                'do LLLL yyyy',
                                DATE_FNS_OPTIONS
                              )}
                            </TableCell>
                            <TableCell>{booking.parking ? 'Yes' : 'No'}</TableCell>
                            {isToday(parsedDate) || !isPast(parsedDate) ? (
                              <TableCell align="right">
                                <div className="btn-container">
                                  <OurButton
                                    type="submit"
                                    variant="contained"
                                    color="secondary"
                                    size="small"
                                    onClick={() => setBookingToCancel(booking)}
                                  >
                                    Cancel
                                  </OurButton>
                                </div>
                              </TableCell>
                            ) : (
                              <TableCell />
                            )}
                          </TableRow>
                        );
                      })
                    ) : (
                      <TableRow>
                        <TableCell>No bookings found</TableCell>
                        <TableCell />
                      </TableRow>
                    )}
                  </TableBody>
                </Table>
              </TableContainer>
            </Paper>
          </>
        )}

        {bookingToCancel && (
          <Dialog fullScreen={fullScreen} open={true} onClose={() => setBookingToCancel(undefined)}>
            <DialogTitle>{'Are you sure you want to cancel this booking?'}</DialogTitle>
            <DialogContent>
              <DialogContentText>
                Booking for <strong>{bookingToCancel.user}</strong> on{' '}
                <strong>{format(parseISO(bookingToCancel.date), 'do LLLL')}</strong> for{' '}
                <strong>{bookingToCancel.office.name}</strong>
              </DialogContentText>
            </DialogContent>
            <DialogActions>
              <Button onClick={() => setBookingToCancel(undefined)} color="primary" autoFocus>
                No
              </Button>
              <Button
                autoFocus
                onClick={() => handleCancelBooking(bookingToCancel)}
                color="primary"
              >
                Yes
              </Button>
            </DialogActions>
          </Dialog>
        )}
      </UserBookingsStyles>
    </AdminLayout>
  );
}
Example #19
Source File: LogsPage.tsx    From ow-mod-manager with MIT License 4 votes vote down vote up
OwmlLog: React.FunctionComponent = () => {
  const styles = useStyles();
  const [logLines, setLogLines] = useRecoilState(logLinesState);
  const {
    settings: { logLinesLimit },
  } = useSettings();

  const [paginatedLines, setPaginatedLines] = useState<LogLine[]>([]);
  const [selectedModName, setSelectedModName] = useState<string>('');
  const [filter, setFilter] = useState('');
  const [page, setPage] = useState<number>(0);

  const containerRef = useRef<HTMLDivElement>(null);
  const isPreviousPageVisible = useRef(false);
  const isNextPageVisible = page > 0;
  const isPaginated = useRef(false);
  const hasHiddenLines = useRef(false);

  useEffect(() => {
    if (!containerRef.current) {
      return;
    }
    debugConsole.log('useEffect: LogsPage scroll reset');
    containerRef.current.scrollTo(0, containerRef.current.scrollHeight);
  }, [paginatedLines]);

  useEffect(() => {
    debugConsole.log('useEffect: LogsPage filter');
    const lowerCaseFilter = filter.toLowerCase();
    const isFilteringByName = filter !== '';
    const isFilteringByMod = selectedModName !== '';

    let filteredLines: LogLine[] = [];
    if (isFilteringByName || isFilteringByMod) {
      filteredLines = logLines.filter((line) => {
        const isFromSelectedMod =
          !isFilteringByMod || line.modName === selectedModName;
        const isMatchWithFilter =
          !isFilteringByName ||
          line.text.toLowerCase().includes(lowerCaseFilter);
        return isMatchWithFilter && isFromSelectedMod;
      });
    } else {
      filteredLines = logLines;
    }

    let lines: LogLine[] = [];
    if (filteredLines.length <= logLinesLimit) {
      lines = filteredLines;
    }

    const end = filteredLines.length - page * logLinesLimit;
    const start = end > logLinesLimit ? end - logLinesLimit : 0;
    lines = filteredLines.slice(start, end);

    isPreviousPageVisible.current =
      page < Math.floor((filteredLines.length - 1) / logLinesLimit);
    isPaginated.current = filteredLines.length !== lines.length;
    hasHiddenLines.current = logLines.length !== lines.length;

    setPaginatedLines(lines);
  }, [filter, logLines, selectedModName, page, logLinesLimit]);

  useEffect(() => {
    debugConsole.log('useEffect: LogsPage pagination reset');
    setPage(0);
  }, [filter, selectedModName]);

  function handlePreviousPageClick() {
    setPage((prevPage) => prevPage + 1);
  }

  function handleNextPageClick() {
    setPage((prevPage) => prevPage - 1);
  }

  function handleClearClick() {
    setLogLines([]);
  }

  return (
    <PageContainer maxWidth={false}>
      <TableContainer
        component={Paper}
        className={styles.container}
        ref={containerRef}
      >
        <Table size="small" stickyHeader>
          <TableHead>
            <TableRow>
              <LogCell className={styles.nameHeader}>
                <FilterInput
                  onChange={setFilter}
                  value={filter}
                  label={logsText.filterLogsLabel}
                />
                {logLines.length > 1 && (
                  <Typography variant="subtitle2" color="textSecondary">
                    {hasHiddenLines.current &&
                      logsText.showingLines(paginatedLines.length)}
                    {logsText.entries(logLines.length)}
                    {isPaginated.current && logsText.page(page + 1)}
                  </Typography>
                )}
                <Tooltip title={logsText.clearLogs}>
                  <IconButton size="small" onClick={handleClearClick}>
                    <ClearLogsIcon />
                  </IconButton>
                </Tooltip>
              </LogCell>
              <LogCell className={styles.modSelectHeader}>
                <ModNameSelect
                  value={selectedModName}
                  onChange={setSelectedModName}
                  logLines={logLines}
                />
              </LogCell>
              <LogCell className={styles.logCountHeader}>#</LogCell>
            </TableRow>
          </TableHead>
          <TableBody>
            {isPreviousPageVisible.current && (
              <TableRow>
                <LogCell colSpan={3}>
                  <Button
                    onClick={handlePreviousPageClick}
                    fullWidth
                    variant="outlined"
                  >
                    {logsText.showPrevious(logLinesLimit)}
                  </Button>
                </LogCell>
              </TableRow>
            )}
            {paginatedLines.map((line: LogLine) => (
              <React.Fragment key={line.id}>
                <TableRow>
                  <LogCell className={styles[line.type]}>
                    {line.text.split('\n').map((text) => (
                      <div>{text}</div>
                    ))}
                  </LogCell>
                  <LogCell className={styles.modNameCell}>
                    {line.modName}
                  </LogCell>
                  <LogCell>{line.count > 1 ? line.count : ''}</LogCell>
                </TableRow>
              </React.Fragment>
            ))}
            {isNextPageVisible && (
              <TableRow>
                <LogCell colSpan={3}>
                  <Button
                    onClick={handleNextPageClick}
                    fullWidth
                    variant="outlined"
                  >
                    {logsText.showNext(logLinesLimit)}
                  </Button>
                </LogCell>
              </TableRow>
            )}
          </TableBody>
        </Table>
      </TableContainer>
    </PageContainer>
  );
}
Example #20
Source File: DataTable.tsx    From interface-v2 with GNU General Public License v3.0 4 votes vote down vote up
DataTable: React.FC<DataTableProps<any>> = ({
  headCells,
  data,
  renderRow,
  toolbar,
  sortUpIcon,
  sortDownIcon,
  caption,
  defaultOrderBy = headCells[0],
  defaultOrder = 'asc',
  loading = false,
  isSinglelineHeader = false,
  size = 0,
  rowPerPage = 10,
  emptyMesage = 'No results.',
  showEmptyRows = true,
  showPagination,
}) => {
  const classes = useStyles({ isSinglelineHeader });
  const [order, setOrder] = useState<SortOrder>(defaultOrder);
  const [orderBy, setOrderBy] = useState<HeadCell<any>>(defaultOrderBy);
  const [page, setPage] = useState(0);
  const [rowsPerPage, setRowsPerPage] = useState(rowPerPage);
  const count = size || data.length;

  const handleRequestSort = (
    event: React.MouseEvent<unknown>,
    property: HeadCell<any>,
  ) => {
    const isAsc = orderBy.id === property.id && order === 'asc';
    setOrder(isAsc && !property.sortDisabled ? 'desc' : 'asc');
    setOrderBy(property);
  };

  const handleChangePage = (event: unknown, newPage: number) => {
    setPage(newPage);
  };

  const handleChangeRowsPerPage = (
    event: React.ChangeEvent<HTMLInputElement>,
  ) => {
    setRowsPerPage(parseInt(event.target.value, 10));
    setPage(0);
  };

  const emptyRows =
    rowsPerPage - Math.min(rowsPerPage, data.length - page * rowsPerPage);

  return (
    <Box>
      {toolbar}

      <TableContainer>
        <Table
          className={classes.table}
          aria-labelledby='tableTitle'
          size='medium'
          aria-label='enhanced table'
        >
          <TableHead>
            <TableRow>
              {headCells.map((headCell, index) => (
                <TableCell
                  className={headCell.buttonCell ? 'buttonCell' : ''}
                  key={`${headCell.id}_${index}`}
                  align={headCell.align}
                  padding='normal'
                  sortDirection={orderBy.id === headCell.id ? order : false}
                >
                  {headCell.element}
                  {sortUpIcon && sortDownIcon ? (
                    <Grid
                      container
                      alignItems='center'
                      className={classes.label}
                      onClick={(event: any) =>
                        handleRequestSort(event, headCell)
                      }
                    >
                      <Box
                        className={cx(
                          classes.headCellLabel,
                          orderBy.id === headCell.id &&
                            classes.sortRequestedHeadLabel,
                        )}
                      >
                        {headCell.label}
                      </Box>
                      {!headCell.sortDisabled && (
                        <Box
                          className={cx(
                            classes.sortIcon,
                            orderBy.id === headCell.id &&
                              classes.sortRequestedIcon,
                          )}
                        >
                          {order === 'asc' && orderBy.id === headCell.id
                            ? sortUpIcon
                            : sortDownIcon}
                        </Box>
                      )}
                    </Grid>
                  ) : (
                    <TableSortLabel
                      className={classes.label}
                      active={orderBy.id === headCell.id}
                      direction={orderBy.id === headCell.id ? order : 'asc'}
                      onClick={(event: any) =>
                        handleRequestSort(event, headCell)
                      }
                    >
                      {headCell.label}
                      {orderBy.id === headCell.id ? (
                        <span className={classes.visuallyHidden}>
                          {order === 'desc'
                            ? 'sorted descending'
                            : 'sorted ascending'}
                        </span>
                      ) : null}
                    </TableSortLabel>
                  )}
                </TableCell>
              ))}
            </TableRow>
          </TableHead>

          <TableBody>
            {loading && (
              <TableRow style={{ height: 53 * emptyRows }}>
                <TableCell colSpan={headCells.length}>
                  <Grid container justifyContent='center' alignItems='center'>
                    <CircularProgress />
                  </Grid>
                </TableCell>
              </TableRow>
            )}

            {stableSort(data, getComparator(order, orderBy))
              .slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
              .map((item, index) => renderRow(item, index, page, rowsPerPage))}

            {!loading && data.length < 1 && (
              <TableRow style={{ height: 53 }}>
                <TableCell colSpan={headCells.length} align='center'>
                  {emptyMesage}
                </TableCell>
              </TableRow>
            )}

            {!loading && emptyRows > 0 && showEmptyRows && (
              <TableRow
                style={{
                  height: 53 * (data.length < 1 ? emptyRows - 1 : emptyRows),
                }}
              >
                <TableCell colSpan={headCells.length} />
              </TableRow>
            )}
          </TableBody>

          {/* Todo: show captions */}
          {caption === false && (
            <caption style={{ marginTop: 24 }}>{caption}</caption>
          )}
        </Table>
      </TableContainer>

      {showPagination && (
        <TablePagination
          rowsPerPageOptions={[5, 10, 25, 50]}
          className={classes.tablePagination}
          component='div'
          count={count}
          rowsPerPage={rowsPerPage}
          page={page}
          onPageChange={handleChangePage}
          onRowsPerPageChange={handleChangeRowsPerPage}
        />
      )}
    </Box>
  );
}
Example #21
Source File: TreasuryTable.tsx    From lobis-frontend with MIT License 4 votes vote down vote up
function TreasuryTable() {
    const isAppLoading = useSelector<IReduxState, boolean>(state => state.app.loading);
    const app = useSelector<IReduxState, IAppSlice>(state => state.app);
    const crvPerLobi = app.crvTreasuryBalance / (app.totalSupply - app.multisigLobiBalance);
    const crvUSDPerLobi = (app.crvTreasuryBalance * app.crvPrice) / (app.totalSupply - app.multisigLobiBalance);
    const fxsPerLobi = app.fraxTreasuryBalance / (app.totalSupply - app.multisigLobiBalance);
    const fxsUSDPerLobi = (app.fraxTreasuryBalance * app.fxsPrice) / (app.totalSupply - app.multisigLobiBalance);
    const tokePerLobi = app.tokeTreasuryBalance / (app.totalSupply - app.multisigLobiBalance);
    const tokeUSDPerLobi = (app.tokeTreasuryBalance * app.tokePrice) / (app.totalSupply - app.multisigLobiBalance);
    const sdtPerLobi = app.treasurySdtBalance / (app.totalSupply - app.multisigLobiBalance);
    const sdtUSDPerLobi = (app.treasurySdtBalance * app.sdtPrice) / (app.totalSupply - app.multisigLobiBalance);
    const anglePerLobi = app.angleTreasuryBalance / (app.totalSupply - app.multisigLobiBalance);
    const angleUSDPerLobi = (app.angleTreasuryBalance * app.anglePrice) / (app.totalSupply - app.multisigLobiBalance);
    const gOhmPerLobi = app.gOhmTreasuryBalance / (app.totalSupply - app.multisigLobiBalance);
    const gOhmUSDPerLobi = (app.gOhmTreasuryBalance * app.gOhmPrice) / (app.totalSupply - app.multisigLobiBalance);
    const totalUSDPerLobi = crvUSDPerLobi + fxsUSDPerLobi + tokeUSDPerLobi;

    return (
        <Grid container item>
            <TableContainer className="treasury-balance-view-card-table">
                <Table>
                    <TableHead>
                        <TableRow>
                            <TableCell align="left">
                                <p className="treasury-balance-view-card-table-title">Token</p>
                            </TableCell>
                            <TableCell align="center">
                                <p className="treasury-balance-view-card-table-title">Treasury</p>
                            </TableCell>
                            <TableCell align="center">
                                <p className="treasury-balance-view-card-table-title">Token Price (USD)</p>
                            </TableCell>
                            <TableCell align="center">
                                <p className="treasury-balance-view-card-table-title">Reserve Values (USD)</p>
                            </TableCell>
                            <TableCell align="center">
                                <p className="treasury-balance-view-card-table-title">Backing Per LOBI (votes)</p>
                            </TableCell>
                            <TableCell align="center">
                                <p className="treasury-balance-view-card-table-title">Backing Per LOBI (USD)</p>
                            </TableCell>
                            <TableCell align="right"></TableCell>
                        </TableRow>
                    </TableHead>
                    <TableBody>
                        <TableRow className="data-row">
                            <TableCell align="left" className="token-name-title">
                                CRV
                            </TableCell>
                            <TableCell align="center" className="token-name-title">
                                {`${new Intl.NumberFormat("en-US", {
                                    maximumFractionDigits: 0,
                                    minimumFractionDigits: 0,
                                }).format(app.crvTreasuryBalance)}`}
                            </TableCell>
                            <TableCell align="center" className="token-name-title">
                                {`${new Intl.NumberFormat("en-US", {
                                    maximumFractionDigits: 2,
                                    minimumFractionDigits: 0,
                                }).format(app.crvPrice)}`}
                            </TableCell>
                            <TableCell align="center" className="token-name-title">
                                {`${new Intl.NumberFormat("en-US", {
                                    maximumFractionDigits: 0,
                                    minimumFractionDigits: 0,
                                }).format(app.crvTreasuryBalance * app.crvPrice)}`}
                            </TableCell>
                            <TableCell align="center" className="token-name-title">
                                {`${new Intl.NumberFormat("en-US", {
                                    maximumFractionDigits: 2,
                                    minimumFractionDigits: 0,
                                }).format(crvPerLobi)}`}
                            </TableCell>
                            <TableCell align="center" className="token-name-title">
                                {`${new Intl.NumberFormat("en-US", {
                                    maximumFractionDigits: 2,
                                    minimumFractionDigits: 0,
                                }).format(crvUSDPerLobi)}`}
                            </TableCell>
                        </TableRow>
                        <TableRow>
                            <TableCell align="left" className="token-name-title">
                                FXS
                            </TableCell>
                            <TableCell align="center" className="token-name-title">
                                {`${new Intl.NumberFormat("en-US", {
                                    maximumFractionDigits: 0,
                                    minimumFractionDigits: 0,
                                }).format(app.fraxTreasuryBalance)}`}
                            </TableCell>
                            <TableCell align="center" className="token-name-title">
                                {`${new Intl.NumberFormat("en-US", {
                                    maximumFractionDigits: 2,
                                    minimumFractionDigits: 0,
                                }).format(app.fxsPrice)}`}
                            </TableCell>
                            <TableCell align="center" className="token-name-title">
                                {`${new Intl.NumberFormat("en-US", {
                                    maximumFractionDigits: 0,
                                    minimumFractionDigits: 0,
                                }).format(app.fraxTreasuryBalance * app.fxsPrice)}`}
                            </TableCell>
                            <TableCell align="center" className="token-name-title">
                                {`${new Intl.NumberFormat("en-US", {
                                    maximumFractionDigits: 2,
                                    minimumFractionDigits: 0,
                                }).format(fxsPerLobi)}`}
                            </TableCell>
                            <TableCell align="center" className="token-name-title">
                                {`${new Intl.NumberFormat("en-US", {
                                    maximumFractionDigits: 2,
                                    minimumFractionDigits: 0,
                                }).format(fxsUSDPerLobi)}`}
                            </TableCell>
                        </TableRow>
                        <TableRow>
                            <TableCell align="left" className="token-name-title">
                                TOKE
                            </TableCell>
                            <TableCell align="center" className="token-name-title">
                                {`${new Intl.NumberFormat("en-US", {
                                    maximumFractionDigits: 0,
                                    minimumFractionDigits: 0,
                                }).format(app.tokeTreasuryBalance)}`}
                            </TableCell>
                            <TableCell align="center" className="token-name-title">
                                {`${new Intl.NumberFormat("en-US", {
                                    maximumFractionDigits: 2,
                                    minimumFractionDigits: 0,
                                }).format(app.tokePrice)}`}
                            </TableCell>
                            <TableCell align="center" className="token-name-title">
                                {`${new Intl.NumberFormat("en-US", {
                                    maximumFractionDigits: 0,
                                    minimumFractionDigits: 0,
                                }).format(app.tokeTreasuryBalance * app.tokePrice)}`}
                            </TableCell>
                            <TableCell align="center" className="token-name-title">
                                {`${new Intl.NumberFormat("en-US", {
                                    maximumFractionDigits: 2,
                                    minimumFractionDigits: 0,
                                }).format(tokePerLobi)}`}
                            </TableCell>
                            <TableCell align="center" className="token-name-title">
                                {`${new Intl.NumberFormat("en-US", {
                                    maximumFractionDigits: 2,
                                    minimumFractionDigits: 0,
                                }).format(tokeUSDPerLobi)}`}
                            </TableCell>
                        </TableRow>
                        <TableRow>
                            <TableCell align="left" className="token-name-title">
                                SDT
                            </TableCell>
                            <TableCell align="center" className="token-name-title">
                                {`${new Intl.NumberFormat("en-US", {
                                    maximumFractionDigits: 0,
                                    minimumFractionDigits: 0,
                                }).format(app.treasurySdtBalance)}`}
                            </TableCell>
                            <TableCell align="center" className="token-name-title">
                                {`${new Intl.NumberFormat("en-US", {
                                    maximumFractionDigits: 2,
                                    minimumFractionDigits: 0,
                                }).format(app.sdtPrice)}`}
                            </TableCell>
                            <TableCell align="center" className="token-name-title">
                                {`${new Intl.NumberFormat("en-US", {
                                    maximumFractionDigits: 0,
                                    minimumFractionDigits: 0,
                                }).format(app.treasurySdtBalance * app.sdtPrice)}`}
                            </TableCell>
                            <TableCell align="center" className="token-name-title">
                                {`${new Intl.NumberFormat("en-US", {
                                    maximumFractionDigits: 2,
                                    minimumFractionDigits: 0,
                                }).format(sdtPerLobi)}`}
                            </TableCell>
                            <TableCell align="center" className="token-name-title">
                                {`${new Intl.NumberFormat("en-US", {
                                    maximumFractionDigits: 2,
                                    minimumFractionDigits: 0,
                                }).format(sdtUSDPerLobi)}`}
                            </TableCell>
                        </TableRow>
                        <TableRow>
                            <TableCell align="left" className="token-name-title">
                                ANGLE
                            </TableCell>
                            <TableCell align="center" className="token-name-title">
                                {`${new Intl.NumberFormat("en-US", {
                                    maximumFractionDigits: 0,
                                    minimumFractionDigits: 0,
                                }).format(app.angleTreasuryBalance)}`}
                            </TableCell>
                            <TableCell align="center" className="token-name-title">
                                {`${new Intl.NumberFormat("en-US", {
                                    maximumFractionDigits: 2,
                                    minimumFractionDigits: 0,
                                }).format(app.anglePrice)}`}
                            </TableCell>
                            <TableCell align="center" className="token-name-title">
                                {`${new Intl.NumberFormat("en-US", {
                                    maximumFractionDigits: 0,
                                    minimumFractionDigits: 0,
                                }).format(app.angleTreasuryBalance * app.anglePrice)}`}
                            </TableCell>
                            <TableCell align="center" className="token-name-title">
                                {`${new Intl.NumberFormat("en-US", {
                                    maximumFractionDigits: 2,
                                    minimumFractionDigits: 0,
                                }).format(anglePerLobi)}`}
                            </TableCell>
                            <TableCell align="center" className="token-name-title">
                                {`${new Intl.NumberFormat("en-US", {
                                    maximumFractionDigits: 2,
                                    minimumFractionDigits: 0,
                                }).format(angleUSDPerLobi)}`}
                            </TableCell>
                        </TableRow>
                        <TableRow>
                            <TableCell align="left" className="token-name-title">
                                gOHM
                            </TableCell>
                            <TableCell align="center" className="token-name-title">
                                {`${new Intl.NumberFormat("en-US", {
                                    maximumFractionDigits: 0,
                                    minimumFractionDigits: 0,
                                }).format(app.gOhmTreasuryBalance)}`}
                            </TableCell>
                            <TableCell align="center" className="token-name-title">
                                {`${new Intl.NumberFormat("en-US", {
                                    maximumFractionDigits: 2,
                                    minimumFractionDigits: 0,
                                }).format(app.gOhmPrice)}`}
                            </TableCell>
                            <TableCell align="center" className="token-name-title">
                                {`${new Intl.NumberFormat("en-US", {
                                    maximumFractionDigits: 0,
                                    minimumFractionDigits: 0,
                                }).format(app.gOhmTreasuryBalance * app.gOhmPrice)}`}
                            </TableCell>
                            <TableCell align="center" className="token-name-title">
                                {`${new Intl.NumberFormat("en-US", {
                                    maximumFractionDigits: 2,
                                    minimumFractionDigits: 0,
                                }).format(gOhmPerLobi)}`}
                            </TableCell>
                            <TableCell align="center" className="token-name-title">
                                {`${new Intl.NumberFormat("en-US", {
                                    maximumFractionDigits: 2,
                                    minimumFractionDigits: 0,
                                }).format(gOhmUSDPerLobi)}`}
                            </TableCell>
                        </TableRow>
                    </TableBody>
                    <TableFooter>
                        {" "}
                        <TableRow>
                            <TableCell align="left" className="treasury-balance-view-card-table-title-footer">
                                <p className="treasury-balance-view-card-table-title"></p>
                            </TableCell>
                            <TableCell align="center" className="treasury-balance-view-card-table-title-footer"></TableCell>
                            <TableCell align="center" className="treasury-balance-view-card-table-title-footer"></TableCell>
                            <TableCell align="center" className="treasury-balance-view-card-table-title-footer">
                                {`${new Intl.NumberFormat("en-US", {
                                    style: "currency",
                                    currency: "USD",
                                    maximumFractionDigits: 0,
                                    minimumFractionDigits: 0,
                                }).format(app.treasuryBalance)}`}
                            </TableCell>
                            <TableCell align="center" className="treasury-balance-view-card-table-title-footer"></TableCell>
                            <TableCell align="center" className="treasury-balance-view-card-table-title-footer">
                                {`${new Intl.NumberFormat("en-US", {
                                    style: "currency",
                                    currency: "USD",
                                    maximumFractionDigits: 2,
                                    minimumFractionDigits: 0,
                                }).format(totalUSDPerLobi)}`}
                            </TableCell>
                        </TableRow>
                    </TableFooter>
                </Table>
            </TableContainer>
        </Grid>
    );
}
Example #22
Source File: no-description.tsx    From mtcute with GNU Lesser General Public License v3.0 4 votes vote down vote up
export default function NoDescriptionPage({ data }: { data: Data }) {
    const classes = usePageStyles()

    // i dont care
    const args: any[] = []
    data.arguments.nodes.forEach((node) => {
        if (node.arguments) {
            node.arguments.forEach((arg) => {
                if (arg.description === null) {
                    ;(arg as any).node = node
                    args.push(arg)
                }
            })
        }
    })

    return (
        <Page
            toc={[
                { id: 'types', title: 'Types' },
                { id: 'arguments', title: 'Arguments' },
            ]}
        >
            <div className={classes.heading1}>
                <Typography variant="h3" id="tl-reference">
                    No description
                </Typography>
                <Typography variant="body2">
                    {data.classes.nodes.length} types, {args.length} arguments
                </Typography>
            </div>
            <Typography variant="body1" className={classes.paragraph}>
                This page lists all items (types and their arguments) from the
                schema that currently do not have a description, neither
                official nor unofficial. You can improve this reference by
                adding description to missing items in{' '}
                <MuiLink href="https://github.com/mtcute/mtcute/blob/master/packages/tl/descriptions.yaml">
                    descriptions.yaml
                </MuiLink>
                .
            </Typography>
            <Section id="types" title="Types">
                <Table>
                    <TableHead>
                        <TableRow>
                            <TableCell>Type</TableCell>
                            <TableCell>Name</TableCell>
                            <TableCell>
                                <MuiLink href="https://github.com/mtcute/mtcute/blob/master/packages/tl/descriptions.yaml">
                                    descriptions.yaml
                                </MuiLink>{' '}
                                key
                            </TableCell>
                        </TableRow>
                    </TableHead>
                    <TableBody>
                        {data.classes.nodes.map((node) => (
                            <TableRow key={node.id}>
                                <TableCell>
                                    {node.type === 'method'
                                        ? 'Method'
                                        : node.type === 'union'
                                        ? 'Union'
                                        : 'Class'}
                                </TableCell>
                                <TableCell>{LinkToTl(node)}</TableCell>
                                <TableCell>
                                    {(node.type === 'method'
                                        ? 'm_'
                                        : node.type === 'union'
                                        ? 'u_'
                                        : 'o_') +
                                        (node.prefix === 'mtproto/'
                                            ? 'mt_'
                                            : '') +
                                        (node.type === 'union'
                                            ? node.name
                                            : node.underscore)}
                                </TableCell>
                            </TableRow>
                        ))}
                    </TableBody>
                </Table>
            </Section>
            <Section id="arguments" title="Arguments">
                <Table>
                    <TableHead>
                        <TableRow>
                            <TableCell>Type</TableCell>
                            <TableCell>Name</TableCell>
                            <TableCell>
                                <MuiLink href="https://github.com/mtcute/mtcute/blob/master/packages/tl/descriptions.yaml">
                                    descriptions.yaml
                                </MuiLink>{' '}
                                key
                            </TableCell>
                            <TableCell>Argument</TableCell>
                        </TableRow>
                    </TableHead>
                    <TableBody>
                        {args.map((arg) => (
                            <TableRow key={arg.node.id + arg.name}>
                                <TableCell>
                                    {arg.node.type === 'method'
                                        ? 'Method'
                                        : arg.node.type === 'union'
                                        ? 'Union'
                                        : 'Class'}
                                </TableCell>
                                <TableCell>{LinkToTl(arg.node)}</TableCell>
                                <TableCell>
                                    {(arg.node.type === 'method'
                                        ? 'm_'
                                        : 'o_') +
                                        (arg.node.prefix === 'mtproto/'
                                            ? 'mt_'
                                            : '') +
                                        (arg.node.type === 'union'
                                            ? arg.node.name
                                            : arg.node.underscore)}
                                </TableCell>
                                <TableCell>
                                    <code>{arg.name}</code>
                                </TableCell>
                            </TableRow>
                        ))}
                    </TableBody>
                </Table>
            </Section>
        </Page>
    )
}
Example #23
Source File: KnownPlaintextAndKeyReuse.tsx    From DamnVulnerableCryptoApp with MIT License 4 votes vote down vote up
KnownPlaintextAndKeyReuse = (props: IChallengeProps) => {

  const [history, setHistory] = useState<IHistoryEntry[]>([]);
  const [plaintext, setPlaintext] = useState("");
  const layoutContext = useContext(LayoutContext);


  const onEncryptButtonPressed = () => {
    layoutContext.setLoading(true);

    KnownPlaintextAndKeyReuseService.encrypt(plaintext).then((res: IHistoryEntry) => {
      const c = Buffer.from(res.encryptedContent, "hex").toString();
      setHistory((hstry) => [res, ...hstry]);

      // TODO: This may be not be reliable. take a look at it and find a better way to validate it
      if (c.match(/\w{8}-\w{4}-\w{4}-\w{4}-\w{12}/))
        props.setFlag(c);

      layoutContext.setLoading(false);

    }).catch(() => layoutContext.setLoading(false));
  };

  const getHistory = () => {
    layoutContext.setLoading(true);

    KnownPlaintextAndKeyReuseService.history().then(res => {
      setHistory((hstry) => res);
      layoutContext.setLoading(false);
    }).catch(() => layoutContext.setLoading(false));
  };

  useEffect(() => {
    getHistory();
  }, []);


  const classes = useStyles();

  const onPlainTextChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => setPlaintext(e.target.value);

  return (
    <div>
      <Box mt={7}>
        <Box style={{ display: 'flex' }}>
          <Box>
            <LockIcon className={classes.lockIcon} />
          </Box>
          <Box mt={2}>
            <Typography gutterBottom variant="h5">Encrypt4Free</Typography>
            <Typography>We offer you an online and secure service to encrypt data for free.</Typography>
          </Box>
        </Box>
        <TextField fullWidth label="Text to encrypt" variant="outlined" multiline rows={4} onChange={onPlainTextChange} />
      </Box>
      <div className={classes.buttonContainer}>
        <Button variant="contained" color="primary" onClick={onEncryptButtonPressed}>Encrypt</Button>
      </div>

      <Typography gutterBottom variant="h5" component="h2">
        Other data encrypted with this service
      </Typography>
      <TableContainer>
        <Table aria-label="simple table">
          <TableHead>
            <TableRow>
              <TableCell>Date</TableCell>
              <TableCell>Encrypted Content</TableCell>
            </TableRow>
          </TableHead>
          <TableBody>
            {
              history.map((row: any, index: number) => (
                <TableRow key={index}>
                  <TableCell scope="row">{row.date}</TableCell>
                  <TableCell scope="row">{row.encryptedContent}</TableCell>
                </TableRow>
              ))
            }
          </TableBody>
        </Table>
      </TableContainer>
    </div>

  );
}
Example #24
Source File: index.tsx    From gatsby-theme-pristine with Apache License 2.0 4 votes vote down vote up
Layout: React.FC = ({ children }) => {
  const darkMode = useDarkMode();
  const theme = darkMode.value ? darkTheme : lightTheme;
  const components = {
    h1: (props: any) => <Typography variant={"h1"} {...props} gutterBottom={true} />,
    h2: (props: any) => <Typography variant={"h2"} {...props} gutterBottom={true} />,
    h3: (props: any) => <Typography variant={"h3"} {...props} gutterBottom={true} />,
    h4: (props: any) => <Typography variant={"h4"} {...props} gutterBottom={true} />,
    h5: (props: any) => <Typography variant={"h5"} {...props} gutterBottom={true} />,
    h6: (props: any) => <Typography variant={"h6"} {...props} gutterBottom={true} />,
    Demo: (props: any) => <h1>This is a demo component</h1>,
    code: (props: any) => <CodeBlock darkMode={darkMode.value} {...props} />,
    thematicBreak: (props: any) => <Divider  {...props} />,
    a: (props: any) => <Link {...props} />,
    table: (props: any) => <Table {...props} style={{ marginBottom: "15px", ...props.style }} />,
    thead: (props: any) => <TableHead {...props} />,
    tr: (props: any) => <TableRow {...props} />,
    tableBody: (props: any) => <TableBody {...props} />,
    td: (props: any) => {
      return (
        <TableCell>
          {props.children || ""}
        </TableCell>
      );
    },
  };
  const [open, setOpen] = useState();

  const data = useStaticQuery(graphql`
    query LayoutQuery {
      site {
        siteMetadata {
          title
          description
          logoUrl
          primaryColor
          secondaryColor
          footerLinks {
            name
            link
          }
        }
      }
    }
  `);

  return (
    <MDXProvider components={components}>
      <MuiThemeProvider theme={{
        ...theme,
        palette: {
          ...theme.palette,
          primary: {
            ...theme.palette.primary,
            main: data.site.siteMetadata.primaryColor,
          },
          secondary: {
            ...theme.palette.secondary,
            main: data.site.siteMetadata.secondaryColor,
          }
        }
      }}>
        <Sidebar open={open} onClose={() => setOpen(false)} />
        <AppBar position="fixed" color="default" elevation={0}>
          <Toolbar>
            <IconButton onClick={() => setOpen(true)}>
              <MenuIcon fontSize="small" />
            </IconButton>
            <Grid container alignContent="center" alignItems="center" justify="space-between">
              <Grid item container direction="row" xs={5}>
                <Grid style={{ paddingRight: "5px" }}>
                  <img
                    alt="logo"
                    height="30"
                    style={{
                      marginTop: "6px",
                    }}
                    src={data.site.siteMetadata.logoUrl} />
                </Grid>
                <Grid style={{ marginTop: "7px" }}>
                  <GatsbyLink to="/" style={{ textDecoration: "none" }}>
                    <Typography color="textSecondary" variant="h6">
                      {data.site.siteMetadata.title}
                    </Typography>
                  </GatsbyLink>
                </Grid>
              </Grid>
              <Grid item container direction="row" xs={7} justify="flex-end" alignItems="center">
                <Hidden only="xs">
                  <Search />
                </Hidden>
                <Tooltip title={"Toggle Dark Mode"}>
                  <IconButton onClick={darkMode.toggle}>
                    {darkMode.value ? <Brightness3Icon fontSize="small" /> : <WbSunnyIcon fontSize="small" />}
                  </IconButton>
                </Tooltip>
              </Grid>
            </Grid>
          </Toolbar>
        </AppBar>
        <Container>
          <CssBaseline />
          <div style={{ padding: "30px", paddingTop: "64px" }}>
            {children}
            <Footer footerLinks={data.site.siteMetadata.footerLinks} />
          </div>
        </Container>
      </MuiThemeProvider >
    </MDXProvider >
  );
}
Example #25
Source File: ByteAtATime.tsx    From DamnVulnerableCryptoApp with MIT License 4 votes vote down vote up
ByteAtATime = (props: IChallengeProps) => {
  const classes = useStyles();

  const [requests, setRequests] = useState<IRequest[]>([]);
  const [selectedTab, setSelectedTab] = useState(0);
  const [selectedRow, setSelectedRow] = useState(-1);
  const [editedRequest, setEditedRequest] = useState("");

  const layoutContext = useContext(LayoutContext);

  const onTableRowSelected = (i: number) => {
    return (e: React.MouseEvent) => {
      setSelectedRow(i);
    };
  };


  const onTabChange = (event: React.ChangeEvent<{}>, newValue: number) => setSelectedTab(newValue);
  const onEditRequestChange = (event: React.ChangeEvent<HTMLInputElement>) => setEditedRequest(event.target.value);


  const onSubmitClicked = async () => {
    layoutContext.setLoading(true);
    ByteAtATimeService.submitRequest(editedRequest).then(resp => {
      layoutContext.setLoading(false);

      setRequests([...requests, resp]);

      // TODO: find a better way of doing this...
      const m = resp.rawResponse.match(/\w{8}-\w{4}-\w{4}-\w{4}-\w{12}/);
      if (m) props.setFlag(m[0]);


    }).catch(err => {
      layoutContext.setLoading(false);
      // TODO: HANDLE ERROR
      // error parsing the request...
    });


  };

  useEffect(() => {
    setRequests(defaultRequests);
    setSelectedRow(0);

  }, []);

  useEffect(() => {
    setEditedRequest(requests[selectedRow]?.rawContent);
    setSelectedTab(0);
  }, [selectedRow]);




  return (
    <Box>
      <Box textAlign="center">
        <img src={faklerLogo} className={classes.logo} />
      </Box>

      <Box mt={2} mb={4}>
        <Alert severity="info">
          A Fakler capture was shared online with you, take a look and have fun :)
      </Alert>
      </Box>

      <Typography variant="h4">Captured Packages</Typography>
      <TableContainer component={Paper} className={classes.requestsTable}>
        <Table>
          <TableHead>
            <TableRow>
              <StyledTableCell>#</StyledTableCell>
              <StyledTableCell>Status</StyledTableCell>
              <StyledTableCell>Method</StyledTableCell>
              <StyledTableCell>Protocol</StyledTableCell>
              <StyledTableCell>Host</StyledTableCell>
              <StyledTableCell>Url</StyledTableCell>

            </TableRow>
          </TableHead>
          <TableBody>
            {
              requests.map((c, i) => (
                <StyledTableRow key={i} onClick={onTableRowSelected(i)} selected={i === selectedRow}>
                  <StyledTableCell>{i}</StyledTableCell>
                  <StyledTableCell>{c.status}</StyledTableCell>
                  <StyledTableCell>{c.method}</StyledTableCell>
                  <StyledTableCell>{c.protocol}</StyledTableCell>
                  <StyledTableCell>{c.host}</StyledTableCell>
                  <StyledTableCell>{c.url}</StyledTableCell>
                </StyledTableRow>
              ))
            }
          </TableBody>
        </Table>
      </TableContainer>


      <Box mt={3}>
        <Tabs value={selectedTab} onChange={onTabChange} className={classes.tabs}>
          <Tab label="Request" icon={<ArrowForwardIcon />} />
          <Tab label="Response" icon={<ArrowBackIcon />} />
          <Tab label="Edit Request" icon={<EditIcon />} />
        </Tabs>
        <TabPanel index={0} selectedTabIndex={selectedTab} className={classes.tabPanel}>
          {<pre>{requests[selectedRow]?.rawContent}</pre>}
        </TabPanel>
        <TabPanel index={1} selectedTabIndex={selectedTab} className={classes.tabPanel}>
          {<pre>{requests[selectedRow]?.rawResponse}</pre>}
        </TabPanel>
        <TabPanel index={2} selectedTabIndex={selectedTab} className={classes.tabPanel}>
          <Box textAlign="right">
            <Button color="primary" type="submit" onClick={onSubmitClicked}>
              Send
            <SendIcon />
            </Button>
          </Box>
          <TextField multiline rows={16} fullWidth value={editedRequest} onChange={onEditRequestChange} className={classes.editRequestInput} />
        </TabPanel>


      </Box>
    </Box>

  );
}
Example #26
Source File: App.tsx    From react-final-table with MIT License 4 votes vote down vote up
function App() {
  const [searchString, setSearchString] = useState('');

  const {
    headers,
    rows,
    selectRow,
    selectedRows,
    originalRows,
    toggleSort,
    toggleAll,
  } = useTable<DataType>(columns, data, {
    selectable: true,
    filter: useCallback(
      (rows: RowType<DataType>[]) => {
        return rows.filter(row => {
          return (
            row.cells.filter(cell => {
              if (cell.value.toLowerCase().includes(searchString)) {
                return true;
              }
              return false;
            }).length > 0
          );
        });
      },
      [searchString]
    ),
  });

  return (
    <Grid container>
      <Grid item>
        <TableContainer>
          <Table>
            <TableHead>
              <TableRow>
                <TableCell>
                  <Checkbox
                    indeterminate={
                      selectedRows.length > 0 &&
                      selectedRows.length !== rows.length
                    }
                    checked={selectedRows.length === rows.length}
                    onClick={() => toggleAll()}
                  />
                </TableCell>
                {headers.map(column => (
                  <TableCell onClick={() => toggleSort(column.name)}>
                    {column.render()}{' '}
                    {column.sorted.on ? (
                      <>
                        {column.sorted.asc ? (
                          <ArrowUpward />
                        ) : (
                          <ArrowDownward />
                        )}
                      </>
                    ) : null}
                  </TableCell>
                ))}
              </TableRow>
            </TableHead>
            <TableBody>
              {rows.map(row => (
                <TableRow>
                  <TableCell>
                    <Checkbox
                      checked={row.selected}
                      onChange={() => selectRow(row.id)}
                    />
                  </TableCell>
                  {row.cells.map(cell => (
                    <TableCell>{cell.render()}</TableCell>
                  ))}
                </TableRow>
              ))}
            </TableBody>
          </Table>
        </TableContainer>
        <TableContainer>
          <TableHead>
            <TableRow>
              {headers.map(column => (
                <TableCell>{column.label}</TableCell>
              ))}
            </TableRow>
          </TableHead>
          <TableBody>
            {selectedRows.map(row => {
              return (
                <TableRow>
                  <TableCell>
                    <Button onClick={() => selectRow(row.id)}>
                      Deselect Row
                    </Button>
                  </TableCell>
                  {row.cells.map(cell => {
                    return <TableCell>{cell.render()}</TableCell>;
                  })}
                </TableRow>
              );
            })}
          </TableBody>
        </TableContainer>
        <TextField
          variant="outlined"
          label="Search..."
          value={searchString}
          onChange={e => setSearchString(e.target.value)}
        />
        <pre>
          <code>
            {JSON.stringify({ selectedRows, originalRows, rows }, null, 2)}
          </code>
        </pre>
      </Grid>
    </Grid>
  );
}
Example #27
Source File: Metrics.tsx    From abacus with GNU General Public License v2.0 4 votes vote down vote up
Metrics = ({
  indexedMetrics,
  completionBag,
  formikProps,
}: {
  indexedMetrics: Record<number, Metric>
  completionBag: ExperimentFormCompletionBag
  formikProps: FormikProps<{ experiment: ExperimentFormData }>
}): JSX.Element => {
  const classes = useStyles()
  const metricEditorClasses = useMetricEditorStyles()
  const decorationClasses = useDecorationStyles()

  // Metric Assignments
  const [metricAssignmentsField, _metricAssignmentsFieldMetaProps, metricAssignmentsFieldHelperProps] =
    useField<MetricAssignment[]>('experiment.metricAssignments')
  const [selectedMetric, setSelectedMetric] = useState<Metric | null>(null)
  const onChangeSelectedMetricOption = (_event: unknown, value: Metric | null) => setSelectedMetric(value)

  const makeMetricAssignmentPrimary = (indexToSet: number) => {
    metricAssignmentsFieldHelperProps.setValue(
      metricAssignmentsField.value.map((metricAssignment, index) => ({
        ...metricAssignment,
        isPrimary: index === indexToSet,
      })),
    )
  }

  // This picks up the no metric assignments validation error
  const metricAssignmentsError =
    formikProps.touched.experiment?.metricAssignments &&
    _.isString(formikProps.errors.experiment?.metricAssignments) &&
    formikProps.errors.experiment?.metricAssignments

  // ### Exposure Events
  const [exposureEventsField, _exposureEventsFieldMetaProps, _exposureEventsFieldHelperProps] =
    useField<EventNew[]>('experiment.exposureEvents')

  return (
    <div className={classes.root}>
      <Typography variant='h4' gutterBottom>
        Assign Metrics
      </Typography>

      <FieldArray
        name='experiment.metricAssignments'
        render={(arrayHelpers) => {
          const onAddMetric = () => {
            if (selectedMetric) {
              const metricAssignment = createMetricAssignment(selectedMetric)
              arrayHelpers.push({
                ...metricAssignment,
                isPrimary: metricAssignmentsField.value.length === 0,
              })
            }
            setSelectedMetric(null)
          }

          return (
            <>
              <TableContainer>
                <Table>
                  <TableHead>
                    <TableRow>
                      <TableCell>Metric</TableCell>
                      <TableCell>Attribution Window</TableCell>
                      <TableCell>Change Expected?</TableCell>
                      <TableCell>Minimum Practical Difference</TableCell>
                      <TableCell />
                    </TableRow>
                  </TableHead>
                  <TableBody>
                    {metricAssignmentsField.value.map((metricAssignment, index) => {
                      const onRemoveMetricAssignment = () => {
                        arrayHelpers.remove(index)
                      }

                      const onMakePrimary = () => {
                        makeMetricAssignmentPrimary(index)
                      }

                      const attributionWindowError =
                        (_.get(
                          formikProps.touched,
                          `experiment.metricAssignments[${index}].attributionWindowSeconds`,
                        ) as boolean | undefined) &&
                        (_.get(
                          formikProps.errors,
                          `experiment.metricAssignments[${index}].attributionWindowSeconds`,
                        ) as string | undefined)

                      return (
                        <TableRow key={index}>
                          <TableCell className={classes.metricNameCell}>
                            <Tooltip arrow title={indexedMetrics[metricAssignment.metricId].description}>
                              <span className={clsx(classes.metricName, decorationClasses.tooltipped)}>
                                {indexedMetrics[metricAssignment.metricId].name}
                              </span>
                            </Tooltip>
                            <br />
                            {metricAssignment.isPrimary && <Attribute name='primary' className={classes.monospaced} />}
                          </TableCell>
                          <TableCell>
                            <Field
                              className={classes.attributionWindowSelect}
                              component={Select}
                              name={`experiment.metricAssignments[${index}].attributionWindowSeconds`}
                              labelId={`experiment.metricAssignments[${index}].attributionWindowSeconds`}
                              size='small'
                              variant='outlined'
                              autoWidth
                              displayEmpty
                              error={!!attributionWindowError}
                              SelectDisplayProps={{
                                'aria-label': 'Attribution Window',
                              }}
                            >
                              <MenuItem value=''>-</MenuItem>
                              {Object.entries(AttributionWindowSecondsToHuman).map(
                                ([attributionWindowSeconds, attributionWindowSecondsHuman]) => (
                                  <MenuItem value={attributionWindowSeconds} key={attributionWindowSeconds}>
                                    {attributionWindowSecondsHuman}
                                  </MenuItem>
                                ),
                              )}
                            </Field>
                            {_.isString(attributionWindowError) && (
                              <FormHelperText error>{attributionWindowError}</FormHelperText>
                            )}
                          </TableCell>
                          <TableCell className={classes.changeExpected}>
                            <Field
                              component={Switch}
                              name={`experiment.metricAssignments[${index}].changeExpected`}
                              id={`experiment.metricAssignments[${index}].changeExpected`}
                              type='checkbox'
                              aria-label='Change Expected'
                              variant='outlined'
                            />
                          </TableCell>
                          <TableCell>
                            <MetricDifferenceField
                              className={classes.minDifferenceField}
                              name={`experiment.metricAssignments[${index}].minDifference`}
                              id={`experiment.metricAssignments[${index}].minDifference`}
                              metricParameterType={indexedMetrics[metricAssignment.metricId].parameterType}
                            />
                          </TableCell>
                          <TableCell>
                            <MoreMenu>
                              <MenuItem onClick={onMakePrimary}>Set as Primary</MenuItem>
                              <MenuItem onClick={onRemoveMetricAssignment}>Remove</MenuItem>
                            </MoreMenu>
                          </TableCell>
                        </TableRow>
                      )
                    })}
                    {metricAssignmentsField.value.length === 0 && (
                      <TableRow>
                        <TableCell colSpan={5}>
                          <Typography variant='body1' align='center'>
                            You don&apos;t have any metric assignments yet.
                          </Typography>
                        </TableCell>
                      </TableRow>
                    )}
                  </TableBody>
                </Table>
              </TableContainer>
              <div className={metricEditorClasses.addMetric}>
                <Add className={metricEditorClasses.addMetricAddSymbol} />
                <FormControl className={classes.addMetricSelect}>
                  <MetricAutocomplete
                    id='add-metric-select'
                    value={selectedMetric}
                    onChange={onChangeSelectedMetricOption}
                    options={Object.values(indexedMetrics)}
                    error={metricAssignmentsError}
                    fullWidth
                  />
                </FormControl>
                <Button variant='contained' disableElevation size='small' onClick={onAddMetric} aria-label='Add metric'>
                  Assign
                </Button>
              </div>
            </>
          )
        }}
      />

      <Alert severity='info' className={classes.metricsInfo}>
        <Link
          underline='always'
          href="https://github.com/Automattic/experimentation-platform/wiki/Experimenter's-Guide#how-do-i-choose-a-primary-metric"
          target='_blank'
        >
          How do I choose a Primary Metric?
        </Link>
        &nbsp;
        <Link
          underline='always'
          href="https://github.com/Automattic/experimentation-platform/wiki/Experimenter's-Guide#what-does-change-expected-mean-for-a-metric"
          target='_blank'
        >
          What is Change Expected?
        </Link>
      </Alert>

      <CollapsibleAlert
        id='attr-window-panel'
        severity='info'
        className={classes.attributionWindowInfo}
        summary={'What is an Attribution Window?'}
      >
        <Link
          underline='always'
          href="https://github.com/Automattic/experimentation-platform/wiki/Experimenter's-Guide#what-is-an-attribution-window-for-a-metric"
          target='_blank'
        >
          An Attribution Window
        </Link>{' '}
        is the window of time after exposure to an experiment that we capture metric events for a participant (exposure
        can be from either assignment or specified exposure events). The refund window is the window of time after a
        purchase event. Revenue metrics will automatically deduct transactions that have been refunded within the
        metric’s refund window.
        <br />
        <div className={classes.attributionWindowDiagram}>
          <AttributionWindowDiagram />
          <RefundWindowDiagram />
        </div>
      </CollapsibleAlert>

      <CollapsibleAlert
        id='min-diff-panel'
        severity='info'
        className={classes.minDiffInfo}
        summary={'How do I choose a Minimum Difference?'}
      >
        <Link
          underline='always'
          href="https://github.com/Automattic/experimentation-platform/wiki/Experimenter's-Guide#how-do-i-choose-a-minimum-difference-practically-equivalent-value-for-my-metrics"
          target='_blank'
        >
          Minimum Practical Difference values
        </Link>{' '}
        are absolute differences from the baseline (not relative). For example, if the baseline conversion rate is 5%, a
        minimum difference of 0.5 pp is equivalent to a 10% relative change.
        <br />
        <div className={classes.minDiffDiagram}>
          <MinDiffDiagram />
        </div>
      </CollapsibleAlert>

      <Alert severity='info' className={classes.requestMetricInfo}>
        <Link underline='always' href='https://betterexperiments.wordpress.com/?start=metric-request' target='_blank'>
          {"Can't find a metric? Request one!"}
        </Link>
      </Alert>

      <Typography variant='h4' className={classes.exposureEventsTitle}>
        Exposure Events
      </Typography>

      <FieldArray
        name='experiment.exposureEvents'
        render={(arrayHelpers) => {
          const onAddExposureEvent = () => {
            arrayHelpers.push({
              event: '',
              props: [],
            })
          }
          return (
            <>
              <TableContainer>
                <Table>
                  <TableBody>
                    {exposureEventsField.value.map((exposureEvent, index) => (
                      <EventEditor
                        key={index}
                        {...{ arrayHelpers, index, classes, completionBag, exposureEvent }}
                        onRemoveExposureEvent={() => arrayHelpers.remove(index)}
                      />
                    ))}
                    {exposureEventsField.value.length === 0 && (
                      <TableRow>
                        <TableCell colSpan={1}>
                          <Typography variant='body1' align='center'>
                            You don&apos;t have any exposure events.
                            {}
                            <br />
                            {}
                            We strongly suggest considering adding one to improve the accuracy of your metrics.
                          </Typography>
                        </TableCell>
                      </TableRow>
                    )}
                  </TableBody>
                </Table>
              </TableContainer>
              <div className={metricEditorClasses.addMetric}>
                <Add className={metricEditorClasses.addMetricAddSymbol} />
                <Button
                  variant='contained'
                  disableElevation
                  size='small'
                  onClick={onAddExposureEvent}
                  aria-label='Add exposure event'
                >
                  Add Event
                </Button>
              </div>
            </>
          )
        }}
      />

      <Alert severity='info' className={classes.exposureEventsInfo}>
        <Link
          underline='always'
          href="https://github.com/Automattic/experimentation-platform/wiki/Experimenter's-Guide#what-is-an-exposure-event-and-when-do-i-need-it"
          target='_blank'
        >
          What is an Exposure Event? And when do I need it?
        </Link>
        <br />
        <span>Only validated events can be used as exposure events.</span>
      </Alert>

      <Alert severity='info' className={classes.multipleExposureEventsInfo}>
        If you have multiple exposure events, then participants will be considered exposed if they trigger{' '}
        <strong>any</strong> of the exposure events.
      </Alert>
    </div>
  )
}
Example #28
Source File: PriceCompare.tsx    From akashlytics with GNU General Public License v3.0 4 votes vote down vote up
PriceCompare: React.FunctionComponent<IPriceCompareProps> = ({}) => {
  const { data: dashboardData, status } = useDashboardData();
  const classes = useStyles();
  const [priceComparisons, setPriceComparisons] = useState(null);
  const marketData = dashboardData?.marketData;
  const intl = useIntl();

  useEffect(() => {
    async function getPriceCompare() {
      const res = await fetch("/data/price-comparisons.json");
      const data = await res.json();

      if (data) {
        setPriceComparisons(data);
      }
    }

    getPriceCompare();
  }, []);

  return (
    <div className={clsx(classes.root, "container")}>
      <Helmet title="Price comparison">
        <meta
          name="description"
          content="Compare Akash cost savings against the cloud giants like Amazon Web Services (aws), Google Cloud Platform (gcp) and Microsoft Azure."
        />
      </Helmet>
      <div className={clsx("row", classes.titleContainer)}>
        <div className="col-xs-12">
          <Typography variant="h3" className={classes.pageTitle}>
            Akash vs. Cloud giants
          </Typography>
          <Typography variant="h5">A simple price comparison</Typography>
          <Typography variant="caption">$USD price per month</Typography>
        </div>
      </div>

      <div className="row">
        <div className="col-xs-12">
          {!priceComparisons || !marketData ? (
            <Box textAlign="center">
              <CircularProgress size={80} />
            </Box>
          ) : (
            <TableContainer component={Paper}>
              <Table className={classes.table} aria-label="price comparisons">
                <TableHead className={classes.tableHeader}>
                  <TableRow>
                    <TableCell align="center" width="10%">
                      type
                    </TableCell>
                    {priceComparisons.providers.map((provider) => (
                      <TableCell key={provider.key} align="center">
                        {provider.title}
                      </TableCell>
                    ))}
                  </TableRow>
                </TableHead>
                <TableBody>
                  {priceComparisons.rows.map((row, rowIndex) => {
                    const akashCell = row.cells.filter((c) => c.provider === "akash")[0];
                    const akashPrice = akashCell.amount * 0.432 * marketData.price;

                    return (
                      <React.Fragment key={row.type}>
                        <TableRow>
                          <TableCell align="center" component="th" scope="row" className={classes.dataCell}>
                            {row.type}
                          </TableCell>
                          {row.cells.map((cell) => (
                            <ProviderCell key={`${cell.provider}_${cell.amount}_${cell.unit}`} cell={cell} marketData={marketData} />
                          ))}
                        </TableRow>

                        <TableRow className={classes.tableRow}>
                          <TableCell align="center" component="th" scope="row" className={classes.discountCell}></TableCell>
                          {row.cells.map((cell, i) => {
                            const isAkash = cell.provider === "akash";
                            const discount = +(akashPrice - cell.amount) / cell.amount;

                            return (
                              <TableCell
                                key={`discount_${rowIndex}_${i}_${cell.provider}_${cell.amount}_${cell.unit}`}
                                align="center"
                                className={classes.discountCell}
                              >
                                {!isAkash ? (
                                  <Chip
                                    className={clsx(classes.discountChip, {
                                      [classes.discountChipGreen]: discount < 0
                                    })}
                                    size="small"
                                    label={intl.formatNumber(discount, {
                                      style: "percent",
                                      maximumFractionDigits: 2
                                    })}
                                  />
                                ) : (
                                  <div className={classes.discountLabel}>Akash discount:</div>
                                )}
                              </TableCell>
                            );
                          })}
                        </TableRow>
                      </React.Fragment>
                    );
                  })}
                </TableBody>
              </Table>
            </TableContainer>
          )}
        </div>
      </div>

      <div className={clsx("row", classes.disclaimerRow)}>
        <div className="col-xs-12">
          <Typography variant="h4" className={classes.disclaimerTitle}>
            Disclaimer
          </Typography>

          <u className={classes.disclaimerList}>
            <li>These prices may vary. I strongly suggest that you do your own research as I might have miss-calculated some of the providers pricing.</li>
            <li>The specifications used for comparisons are mostly focused on CPU and RAM as storage is usually rather cheap.</li>
            <li>
              As of today, the minimum pricing for a lease on akash is 1uakt (.000001akt) per block at an average of 1 block per 6 second, which gives
              ~.423akt/month. To counter the rise of prices, Akash will introduce fractional pricing which will enable even lower prices. Please refer to this{" "}
              <a href="https://akash.network/blog/akash-mainnet-2-update-april-29-2021/" target="_blank" rel="noopener" className={classes.link}>
                article.
              </a>
            </li>
            <li>
              To calculate the pricing for Akash, I created a deployment with the given specifications and took the best available bid. This might change in the
              future.
            </li>
            <li>
              <a href="https://calculator.s3.amazonaws.com/index.html" target="_blank" rel="noopener" className={classes.link}>
                Amazon Web Service pricing calculator
              </a>
            </li>
            <li>
              <a href="https://cloud.google.com/products/calculator" target="_blank" rel="noopener" className={classes.link}>
                Google cloud platform pricing calculator
              </a>
            </li>
            <li>
              <a href="https://azure.microsoft.com/en-us/pricing/calculator/" target="_blank" rel="noopener" className={classes.link}>
                Microsoft Azure pricing calculator
              </a>
            </li>
          </u>
        </div>
      </div>
    </div>
  );
}
Example #29
Source File: ReleasesTableView.tsx    From github-deploy-center with MIT License 4 votes vote down vote up
ReleasesTableView = () => {
  const { selectedApplication, pendingDeployments } = useAppState()
  const repo = selectedApplication?.repo
  const { triggerDeployment, removeEnvironment } = useActions()
  const allReleaseResultsForTag = useFetchReleases()

  const releases = allReleaseResultsForTag.data || []

  const { mutate, error, isLoading } = useMutation(
    async ({
      release,
      environmentName,
    }: {
      release: string
      environmentName: string
    }) => {
      await triggerDeployment({ release, environmentName })
    }
  )

  if (
    !selectedApplication ||
    !DeployWorkflowCodec.is(selectedApplication.deploySettings) ||
    !selectedApplication.deploySettings.workflowId
  ) {
    return null
  }

  if (allReleaseResultsForTag.isLoading) {
    return <CircularProgress />
  }

  const releasesSorted = orderBy(
    releases
      .slice()
      .sort((a, b) =>
        b.tagName.localeCompare(a.tagName, undefined, { numeric: true })
      )
      .filter((r) =>
        r.name
          .toLowerCase()
          .startsWith(selectedApplication.releaseFilter.toLowerCase())
      ),
    (r) => r.createdAt,
    'desc'
  )

  const selectedEnvironments = values(
    selectedApplication.environmentSettingsByName
  )

  const releasesByEnvironment = selectedEnvironments.reduce<
    Record<string, ReleaseModel[]>
  >((record, environment) => {
    record[environment.name] = releasesSorted.filter((r) =>
      r.deployments.some((d) => d.environment === environment.name)
    )
    return record
  }, {})

  const createButton = (
    deployment: DeploymentModel | undefined,
    release: ReleaseModel,
    environment: EnvironmentSettings
  ) => {
    const latestRelease = releasesByEnvironment[environment.name]?.[0]
    const isAfterLatest =
      !latestRelease || release.createdAt.isAfter(latestRelease.createdAt)

    const deploymentId = getDeploymentId({
      release: release.tagName,
      environment: environment.name,
      repo: selectedApplication.repo.name,
      owner: selectedApplication.repo.owner,
    })
    const pendingDeployment = pendingDeployments[deploymentId]
    const modifiedAt = deployment?.modifiedAt
    const deploymentState =
      pendingDeployment &&
      (!modifiedAt || pendingDeployment.isAfter(modifiedAt))
        ? DeploymentState.Pending
        : deployment?.state

    const deployButtonVariant =
      (isAfterLatest && !deploymentState) ||
      deploymentState === DeploymentState.Active
        ? 'contained'
        : 'outlined'

    return (
      <Button
        disabled={isLoading}
        variant={deployButtonVariant}
        color={!deploymentState && isAfterLatest ? 'primary' : 'default'}
        style={getButtonStyle(deploymentState)}
        onClick={() =>
          mutate({
            release: release.tagName,
            environmentName: environment.name,
          })
        }>
        {deploymentState?.replaceAll('_', ' ') ?? 'Deploy'}
      </Button>
    )
  }

  return (
    <>
      {error instanceof Error && (
        <Alert severity="error">{error.message}</Alert>
      )}
      <Table>
        <TableHead>
          <TableRow>
            <TableCell>Release name</TableCell>
            {selectedEnvironments.map((environment) => (
              <TableCell key={environment.name}>
                <Link
                  href={`https://github.com/${repo?.owner}/${
                    repo?.name
                  }/deployments/activity_log?environment=${encodeURIComponent(
                    environment.name
                  )}`}
                  target="_blank"
                  color="inherit">
                  {environment.name}
                </Link>
                <IconButton onClick={() => removeEnvironment(environment.name)}>
                  <Icon>delete</Icon>
                </IconButton>
              </TableCell>
            ))}
          </TableRow>
        </TableHead>
        <TableBody>
          {releasesSorted.map((release) => (
            <TableRow key={release.id}>
              <TableCell style={{ width: '20%' }}>
                <Link
                  href={`https://github.com/${repo?.owner}/${repo?.name}/releases/tag/${release.tagName}`}
                  target="_blank"
                  color="inherit">
                  {release.name}
                </Link>
              </TableCell>
              {selectedEnvironments.map((environment) => {
                const deployment = release.deployments.find(
                  (d) => d.environment === environment.name
                )
                return (
                  <TableCell key={environment.name}>
                    {createButton(deployment, release, environment)}
                  </TableCell>
                )
              })}
            </TableRow>
          ))}
        </TableBody>
      </Table>
    </>
  )
}