@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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
StyledTableHead = styled(TableHead)({ minHeight: 34, })
Example #10
Source File: Pager.tsx From glific-frontend with GNU Affero General Public License v3.0 | 5 votes |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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'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>
<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'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 |
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 |
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>
</>
)
}