0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2024-12-16 20:26:19 -05:00

Merge pull request #2462 from logto-io/feature/ac-layout

refactor(console): ac layout
This commit is contained in:
Xiao Yijun 2022-11-18 14:32:25 +08:00 committed by GitHub
commit b35d422e1d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 115 additions and 128 deletions

View file

@ -21,7 +21,7 @@
.main {
flex-grow: 1;
padding-right: _.unit(6);
padding: 0 _.unit(3) 0 _.unit(2);
overflow-y: scroll;
> * {

View file

@ -21,10 +21,6 @@
}
}
.table {
margin-top: _.unit(4);
flex: 1;
}
.pagination {
margin-top: _.unit(4);

View file

@ -13,6 +13,7 @@ import TableError from '@/components/Table/TableError';
import TableLoading from '@/components/Table/TableLoading';
import UserName from '@/components/UserName';
import type { RequestError } from '@/hooks/use-api';
import * as resourcesStyles from '@/scss/resources.module.scss';
import * as tableStyles from '@/scss/table.module.scss';
import ApplicationSelector from './components/ApplicationSelector';
@ -85,7 +86,7 @@ const AuditLogTable = ({ userId }: Props) => {
/>
</div>
</div>
<div className={classNames(styles.table, tableStyles.scrollable)}>
<div className={classNames(resourcesStyles.table, tableStyles.scrollable)}>
<table className={classNames(logs?.length === 0 && tableStyles.empty)}>
<colgroup>
<col className={styles.eventName} />
@ -141,8 +142,9 @@ const AuditLogTable = ({ userId }: Props) => {
<div className={styles.pagination}>
{!!totalCount && (
<Pagination
pageCount={Math.ceil(totalCount / pageSize)}
pageIndex={pageIndex}
totalCount={totalCount}
pageSize={pageSize}
onChange={(page) => {
updateQuery('page', String(page));
}}

View file

@ -1,9 +1,21 @@
@use '@/scss/underscore' as _;
.container {
display: flex;
justify-content: flex-end;
}
.positionInfo {
align-self: flex-end;
font: var(--font-body-medium);
color: var(--color-text-secondary);
}
.pagination {
display: flex;
justify-content: right;
margin: 0;
padding-inline-start: _.unit(4);
li {
list-style: none;

View file

@ -1,4 +1,5 @@
import classNames from 'classnames';
import { useTranslation } from 'react-i18next';
import ReactPaginate from 'react-paginate';
import Button from '../Button';
@ -9,34 +10,46 @@ import * as styles from './index.module.scss';
type Props = {
pageIndex: number;
pageCount: number;
totalCount: number;
pageSize: number;
onChange?: (pageIndex: number) => void;
};
const Pagination = ({ pageIndex, pageCount, onChange }: Props) => {
const Pagination = ({ pageIndex, totalCount, pageSize, onChange }: Props) => {
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
const pageCount = Math.ceil(totalCount / pageSize);
const min = (pageIndex - 1) * pageSize + 1;
const max = pageIndex * pageSize;
return (
<ReactPaginate
className={styles.pagination}
pageCount={pageCount}
forcePage={pageIndex - 1}
pageLabelBuilder={(page: number) => (
<Button
type={page === pageIndex ? 'outline' : 'default'}
className={classNames(styles.button, page === pageIndex && styles.active)}
size="small"
title={<DangerousRaw>{page}</DangerousRaw>}
/>
)}
previousLabel={<Button className={styles.button} size="small" icon={<Previous />} />}
nextLabel={<Button className={styles.button} size="small" icon={<Next />} />}
breakLabel={
<Button className={styles.button} size="small" title={<DangerousRaw>...</DangerousRaw>} />
}
disabledClassName={styles.disabled}
onPageChange={({ selected }) => {
onChange?.(selected + 1);
}}
/>
<div className={styles.container}>
<div className={styles.positionInfo}>
{t('general.page_info', { min, max, total: totalCount })}
</div>
<ReactPaginate
className={styles.pagination}
pageCount={pageCount}
forcePage={pageIndex - 1}
pageLabelBuilder={(page: number) => (
<Button
type={page === pageIndex ? 'outline' : 'default'}
className={classNames(styles.button, page === pageIndex && styles.active)}
size="small"
title={<DangerousRaw>{page}</DangerousRaw>}
/>
)}
previousLabel={<Button className={styles.button} size="small" icon={<Previous />} />}
nextLabel={<Button className={styles.button} size="small" icon={<Next />} />}
breakLabel={
<Button className={styles.button} size="small" title={<DangerousRaw>...</DangerousRaw>} />
}
disabledClassName={styles.disabled}
onPageChange={({ selected }) => {
onChange?.(selected + 1);
}}
/>
</div>
);
};

View file

@ -1,19 +1,5 @@
@use '@/scss/underscore' as _;
.card {
@include _.flex-column;
}
.headline {
display: flex;
justify-content: space-between;
}
.table {
margin-top: _.unit(4);
flex: 1;
}
.icon {
flex-shrink: 0;
}

View file

@ -12,7 +12,6 @@ import ApiResourceDark from '@/assets/images/api-resource-dark.svg';
import ApiResource from '@/assets/images/api-resource.svg';
import Plus from '@/assets/images/plus.svg';
import Button from '@/components/Button';
import Card from '@/components/Card';
import CardTitle from '@/components/CardTitle';
import CopyToClipboard from '@/components/CopyToClipboard';
import ItemPreview from '@/components/ItemPreview';
@ -23,6 +22,7 @@ import TableLoading from '@/components/Table/TableLoading';
import type { RequestError } from '@/hooks/use-api';
import { useTheme } from '@/hooks/use-theme';
import * as modalStyles from '@/scss/modal.module.scss';
import * as resourcesStyles from '@/scss/resources.module.scss';
import * as tableStyles from '@/scss/table.module.scss';
import CreateForm from './components/CreateForm';
@ -46,8 +46,8 @@ const ApiResources = () => {
const [apiResources, totalCount] = data ?? [];
return (
<Card className={styles.card}>
<div className={styles.headline}>
<div className={resourcesStyles.container}>
<div className={resourcesStyles.headline}>
<CardTitle title="api_resources.title" subtitle="api_resources.subtitle" />
<Button
title="api_resources.create"
@ -77,7 +77,7 @@ const ApiResources = () => {
/>
</Modal>
</div>
<div className={classNames(styles.table, tableStyles.scrollable)}>
<div className={classNames(resourcesStyles.table, tableStyles.scrollable)}>
<table className={classNames(!data && tableStyles.empty)}>
<colgroup>
<col className={styles.apiResourceName} />
@ -140,15 +140,16 @@ const ApiResources = () => {
<div className={styles.pagination}>
{!!totalCount && (
<Pagination
pageCount={Math.ceil(totalCount / pageSize)}
pageIndex={pageIndex}
totalCount={totalCount}
pageSize={pageSize}
onChange={(page) => {
setQuery({ page: String(page) });
}}
/>
)}
</div>
</Card>
</div>
);
};

View file

@ -1,19 +1,5 @@
@use '@/scss/underscore' as _;
.card {
@include _.flex-column;
}
.headline {
display: flex;
justify-content: space-between;
}
.table {
margin-top: _.unit(4);
flex: 1;
}
.icon {
flex-shrink: 0;
}

View file

@ -9,7 +9,6 @@ import useSWR from 'swr';
import Plus from '@/assets/images/plus.svg';
import ApplicationIcon from '@/components/ApplicationIcon';
import Button from '@/components/Button';
import Card from '@/components/Card';
import CardTitle from '@/components/CardTitle';
import CopyToClipboard from '@/components/CopyToClipboard';
import ItemPreview from '@/components/ItemPreview';
@ -19,6 +18,7 @@ import TableError from '@/components/Table/TableError';
import TableLoading from '@/components/Table/TableLoading';
import type { RequestError } from '@/hooks/use-api';
import * as modalStyles from '@/scss/modal.module.scss';
import * as resourcesStyles from '@/scss/resources.module.scss';
import * as tableStyles from '@/scss/table.module.scss';
import { applicationTypeI18nKey } from '@/types/applications';
@ -41,8 +41,8 @@ const Applications = () => {
const [applications, totalCount] = data ?? [];
return (
<Card className={styles.card}>
<div className={styles.headline}>
<div className={resourcesStyles.container}>
<div className={resourcesStyles.headline}>
<CardTitle title="applications.title" subtitle="applications.subtitle" />
<Button
icon={<Plus />}
@ -69,19 +69,21 @@ const Applications = () => {
}}
/>
</Modal>
</div>
<div className={classNames(styles.table, tableStyles.scrollable)}>
</div>{' '}
<div className={classNames(resourcesStyles.table, tableStyles.scrollable)}>
<table className={classNames(!data && tableStyles.empty)}>
<colgroup>
<col className={styles.applicationName} />
<col />
</colgroup>
<thead>
<tr>
<th>{t('applications.application_name')}</th>
<th>{t('applications.app_id')}</th>
</tr>
</thead>
<tbody>
{!data && error && (
<TableError
@ -129,15 +131,16 @@ const Applications = () => {
<div className={styles.pagination}>
{!!totalCount && (
<Pagination
pageCount={Math.ceil(totalCount / pageSize)}
pageIndex={pageIndex}
totalCount={totalCount}
pageSize={pageSize}
onChange={(page) => {
setQuery({ page: String(page) });
}}
/>
)}
</div>
</Card>
</div>
);
};

View file

@ -1,10 +0,0 @@
@use '@/scss/underscore' as _;
.card {
@include _.flex-column;
}
.headline {
display: flex;
justify-content: space-between;
}

View file

@ -1,17 +1,15 @@
import AuditLogTable from '@/components/AuditLogTable';
import Card from '@/components/Card';
import CardTitle from '@/components/CardTitle';
import * as styles from './index.module.scss';
import * as resourcesStyles from '@/scss/resources.module.scss';
const AuditLogs = () => {
return (
<Card className={styles.card}>
<div className={styles.headline}>
<div className={resourcesStyles.container}>
<div className={resourcesStyles.headline}>
<CardTitle title="logs.title" subtitle="logs.subtitle" />
</div>
<AuditLogTable />
</Card>
</div>
);
};

View file

@ -1,24 +1,9 @@
@use '@/scss/underscore' as _;
.card {
@include _.flex-column;
}
.headline {
display: flex;
justify-content: space-between;
align-items: center;
}
.tabs {
margin-top: _.unit(4);
}
.table {
margin-top: _.unit(4);
flex: 1;
}
.connectorName {
width: 360px;
}

View file

@ -8,7 +8,6 @@ import Plus from '@/assets/images/plus.svg';
import SocialConnectorEmptyDark from '@/assets/images/social-connector-empty-dark.svg';
import SocialConnectorEmpty from '@/assets/images/social-connector-empty.svg';
import Button from '@/components/Button';
import Card from '@/components/Card';
import CardTitle from '@/components/CardTitle';
import TabNav, { TabNavItem } from '@/components/TabNav';
import TableEmpty from '@/components/Table/TableEmpty';
@ -16,6 +15,7 @@ import TableError from '@/components/Table/TableError';
import TableLoading from '@/components/Table/TableLoading';
import useConnectorGroups from '@/hooks/use-connector-groups';
import { useTheme } from '@/hooks/use-theme';
import * as resourcesStyles from '@/scss/resources.module.scss';
import * as tableStyles from '@/scss/table.module.scss';
import ConnectorRow from './components/ConnectorRow';
@ -60,8 +60,8 @@ const Connectors = () => {
return (
<>
<Card className={styles.card}>
<div className={styles.headline}>
<div className={resourcesStyles.container}>
<div className={resourcesStyles.headline}>
<CardTitle title="connectors.title" subtitle="connectors.subtitle" />
{isSocial && (
<Button
@ -80,7 +80,7 @@ const Connectors = () => {
<TabNavItem href="/connectors">{t('connectors.tab_email_sms')}</TabNavItem>
<TabNavItem href="/connectors/social">{t('connectors.tab_social')}</TabNavItem>
</TabNav>
<div className={classNames(styles.table, tableStyles.scrollable)}>
<div className={classNames(resourcesStyles.table, tableStyles.scrollable)}>
<table className={classNames(!data && tableStyles.empty)}>
<colgroup>
<col className={styles.connectorName} />
@ -145,7 +145,7 @@ const Connectors = () => {
</tbody>
</table>
</div>
</Card>
</div>
<CreateForm
isOpen={Boolean(createType)}
type={createType}

View file

@ -1,25 +1,17 @@
@use '@/scss/underscore' as _;
.card {
@include _.flex-column;
}
.headline {
display: flex;
justify-content: space-between;
}
.filter {
margin: _.unit(4) 0;
}
.tableContainer {
flex: 1;
background-color: var(--color-layer-1);
>table {
>tbody {
>tr {
>td {
> table {
> tbody {
> tr {
> td {
padding-top: 10px;
padding-bottom: 10px;
}

View file

@ -10,7 +10,6 @@ import useSWR from 'swr';
import Plus from '@/assets/images/plus.svg';
import ApplicationName from '@/components/ApplicationName';
import Button from '@/components/Button';
import Card from '@/components/Card';
import CardTitle from '@/components/CardTitle';
import DateTime from '@/components/DateTime';
import ItemPreview from '@/components/ItemPreview';
@ -23,6 +22,7 @@ import { generatedPasswordStorageKey } from '@/consts';
import { generateAvatarPlaceHolderById } from '@/consts/avatars';
import type { RequestError } from '@/hooks/use-api';
import * as modalStyles from '@/scss/modal.module.scss';
import * as resourcesStyles from '@/scss/resources.module.scss';
import * as tableStyles from '@/scss/table.module.scss';
import CreateForm from './components/CreateForm';
@ -46,8 +46,8 @@ const Users = () => {
const [users, totalCount] = data ?? [];
return (
<Card className={styles.card}>
<div className={styles.headline}>
<div className={resourcesStyles.container}>
<div className={resourcesStyles.headline}>
<CardTitle title="users.title" subtitle="users.subtitle" />
<Button
title="users.create"
@ -156,15 +156,16 @@ const Users = () => {
<div className={styles.pagination}>
{!!totalCount && (
<Pagination
pageCount={Math.ceil(totalCount / pageSize)}
pageIndex={pageIndex}
totalCount={totalCount}
pageSize={pageSize}
onChange={(page) => {
setQuery({ page: String(page), ...conditional(keyword && { search: keyword }) });
}}
/>
)}
</div>
</Card>
</div>
);
};

View file

@ -5,9 +5,7 @@
}
@mixin main-content-width {
max-width: 1168px;
min-width: 604px;
margin: 0 auto;
}
@mixin flex-column {

View file

@ -0,0 +1,17 @@
@use '@/scss/underscore' as _;
.container {
width: 100%;
@include _.flex-column;
.headline {
display: flex;
justify-content: space-between;
}
.table {
flex: 1;
margin-top: _.unit(4);
background-color: var(--color-layer-1);
}
}

View file

@ -38,6 +38,7 @@ const general = {
stay_on_page: 'Auf Seite bleiben',
type_to_search: 'Tippe um zu suchen',
got_it: 'Got it', // UNTRANSLATED
page_info: '{{min, number}}-{{max, number}} of {{total, number}}', // UNTRANSLATED
};
export default general;

View file

@ -37,6 +37,7 @@ const general = {
stay_on_page: 'Stay on Page',
type_to_search: 'Type to search',
got_it: 'Got it',
page_info: '{{min, number}}-{{max, number}} of {{total, number}}',
};
export default general;

View file

@ -38,6 +38,7 @@ const general = {
stay_on_page: 'Rester sur la page',
type_to_search: 'Type to search', // UNTRANSLATED
got_it: 'Got it', // UNTRANSLATED
page_info: '{{min, number}}-{{max, number}} of {{total, number}}', // UNTRANSLATED
};
export default general;

View file

@ -37,6 +37,7 @@ const general = {
stay_on_page: '페이지 유지하기',
type_to_search: 'Type to search', // UNTRANSLATED
got_it: 'Got it', // UNTRANSLATED
page_info: '{{min, number}}-{{max, number}} of {{total, number}}', // UNTRANSLATED
};
export default general;

View file

@ -37,6 +37,7 @@ const general = {
stay_on_page: 'Ficar na página',
type_to_search: 'Type to search', // UNTRANSLATED
got_it: 'Got it', // UNTRANSLATED
page_info: '{{min, number}}-{{max, number}} of {{total, number}}', // UNTRANSLATED
};
export default general;

View file

@ -38,6 +38,7 @@ const general = {
stay_on_page: 'Bu sayfada kal',
type_to_search: 'Type to search', // UNTRANSLATED
got_it: 'Got it', // UNTRANSLATED
page_info: '{{min, number}}-{{max, number}} of {{total, number}}', // UNTRANSLATED
};
export default general;

View file

@ -37,6 +37,7 @@ const general = {
stay_on_page: '留在此页',
type_to_search: '输入搜索',
got_it: 'Got it', // UNTRANSLATED
page_info: '{{min, number}}-{{max, number}} 共 {{total, number}} 条', // UNTRANSLATED
};
export default general;