mirror of
https://github.com/logto-io/logto.git
synced 2024-12-23 20:33:16 -05:00
feat(console): table scroll
This commit is contained in:
parent
6a61ea29f5
commit
7feafe8d21
4 changed files with 104 additions and 72 deletions
|
@ -1,5 +1,11 @@
|
|||
@use '@/scss/underscore' as _;
|
||||
|
||||
.card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.headline {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
@ -10,21 +16,21 @@
|
|||
}
|
||||
|
||||
.table {
|
||||
margin-top: _.unit(4);
|
||||
flex: 1;
|
||||
|
||||
tbody {
|
||||
max-height: calc(100vh - _.unit(64));
|
||||
tr.clickable {
|
||||
cursor: pointer;
|
||||
|
||||
tr.clickable {
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background: var(--color-table-row-selected);
|
||||
}
|
||||
&:hover {
|
||||
background: var(--color-table-row-selected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.pagination {
|
||||
min-height: 64px;
|
||||
}
|
||||
|
||||
.userName {
|
||||
width: 360px;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { User } from '@logto/schemas';
|
||||
import { conditionalString } from '@silverhand/essentials';
|
||||
import classNames from 'classnames';
|
||||
import React, { useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import Modal from 'react-modal';
|
||||
|
@ -18,6 +19,7 @@ import TableError from '@/components/Table/TableError';
|
|||
import TableLoading from '@/components/Table/TableLoading';
|
||||
import { RequestError } from '@/hooks/use-api';
|
||||
import * as modalStyles from '@/scss/modal.module.scss';
|
||||
import * as tableStyles from '@/scss/table.module.scss';
|
||||
|
||||
import CreateForm from './components/CreateForm';
|
||||
import * as styles from './index.module.scss';
|
||||
|
@ -39,7 +41,7 @@ const Users = () => {
|
|||
const [users, totalCount] = data ?? [];
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<Card className={styles.card}>
|
||||
<div className={styles.headline}>
|
||||
<CardTitle title="users.title" subtitle="users.subtitle" />
|
||||
<Button
|
||||
|
@ -68,68 +70,72 @@ const Users = () => {
|
|||
<div className={styles.filter}>
|
||||
<Search defaultValue={keyword} onSearch={setKeyword} />
|
||||
</div>
|
||||
<table className={styles.table}>
|
||||
<colgroup>
|
||||
<col className={styles.userName} />
|
||||
<col />
|
||||
<col />
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{t('users.user_name')}</th>
|
||||
<th>{t('users.application_name')}</th>
|
||||
<th>{t('users.latest_sign_in')}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{error && (
|
||||
<TableError
|
||||
columns={3}
|
||||
content={error.body.message}
|
||||
onRetry={async () => mutate(undefined, true)}
|
||||
/>
|
||||
)}
|
||||
{isLoading && <TableLoading columns={3} />}
|
||||
{users?.length === 0 && (
|
||||
<TableEmpty columns={3}>
|
||||
<Button
|
||||
title="admin_console.users.create"
|
||||
type="outline"
|
||||
onClick={() => {
|
||||
setIsCreateFormOpen(true);
|
||||
}}
|
||||
/>
|
||||
</TableEmpty>
|
||||
)}
|
||||
{users?.map(({ id, name, username }) => (
|
||||
<tr
|
||||
key={id}
|
||||
className={styles.clickable}
|
||||
onClick={() => {
|
||||
navigate(`/users/${id}`);
|
||||
}}
|
||||
>
|
||||
<td>
|
||||
<ItemPreview
|
||||
title={name ?? '-'}
|
||||
subtitle={username ?? '-'}
|
||||
icon={<ImagePlaceholder />}
|
||||
to={`/users/${id}`}
|
||||
/>
|
||||
</td>
|
||||
<td>Application</td>
|
||||
<td>Last sign in</td>
|
||||
<div className={classNames(styles.table, tableStyles.scrollable)}>
|
||||
<table>
|
||||
<colgroup>
|
||||
<col className={styles.userName} />
|
||||
<col />
|
||||
<col />
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{t('users.user_name')}</th>
|
||||
<th>{t('users.application_name')}</th>
|
||||
<th>{t('users.latest_sign_in')}</th>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
{totalCount !== undefined && totalCount > 0 && (
|
||||
<Pagination
|
||||
pageCount={Math.ceil(totalCount / pageSize)}
|
||||
pageIndex={pageIndex}
|
||||
onChange={setPageIndex}
|
||||
/>
|
||||
)}
|
||||
</thead>
|
||||
<tbody>
|
||||
{error && (
|
||||
<TableError
|
||||
columns={3}
|
||||
content={error.body.message}
|
||||
onRetry={async () => mutate(undefined, true)}
|
||||
/>
|
||||
)}
|
||||
{isLoading && <TableLoading columns={3} />}
|
||||
{users?.length === 0 && (
|
||||
<TableEmpty columns={3}>
|
||||
<Button
|
||||
title="admin_console.users.create"
|
||||
type="outline"
|
||||
onClick={() => {
|
||||
setIsCreateFormOpen(true);
|
||||
}}
|
||||
/>
|
||||
</TableEmpty>
|
||||
)}
|
||||
{users?.map(({ id, name, username }) => (
|
||||
<tr
|
||||
key={id}
|
||||
className={styles.clickable}
|
||||
onClick={() => {
|
||||
navigate(`/users/${id}`);
|
||||
}}
|
||||
>
|
||||
<td>
|
||||
<ItemPreview
|
||||
title={name ?? '-'}
|
||||
subtitle={username ?? '-'}
|
||||
icon={<ImagePlaceholder />}
|
||||
to={`/users/${id}`}
|
||||
/>
|
||||
</td>
|
||||
<td>Application</td>
|
||||
<td>Last sign in</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div className={styles.pagination}>
|
||||
{totalCount !== undefined && totalCount > 0 && (
|
||||
<Pagination
|
||||
pageCount={Math.ceil(totalCount / pageSize)}
|
||||
pageIndex={pageIndex}
|
||||
onChange={setPageIndex}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -25,7 +25,6 @@ table {
|
|||
border-spacing: 0;
|
||||
width: 100%;
|
||||
table-layout: fixed;
|
||||
overflow: hidden;
|
||||
|
||||
thead {
|
||||
th {
|
||||
|
|
21
packages/console/src/scss/table.module.scss
Normal file
21
packages/console/src/scss/table.module.scss
Normal file
|
@ -0,0 +1,21 @@
|
|||
@use '@/scss/underscore' as _;
|
||||
|
||||
.scrollable {
|
||||
margin-top: _.unit(4);
|
||||
overflow-y: auto;
|
||||
border: 1px solid var(--color-neutral-90);
|
||||
border-radius: _.unit(2);
|
||||
|
||||
table {
|
||||
border: none;
|
||||
|
||||
thead tr {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
|
||||
th {
|
||||
background: var(--color-on-primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue