mirror of
https://github.com/logto-io/logto.git
synced 2025-02-03 21:48:55 -05:00
fix(console): adjust styles on table (#476)
This commit is contained in:
parent
36cfdf4b16
commit
039f3d0cbb
17 changed files with 246 additions and 231 deletions
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
.container {
|
.container {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: _.unit(3);
|
padding: _.unit(2) _.unit(3);
|
||||||
border-radius: _.unit(2);
|
border-radius: _.unit(2);
|
||||||
background: var(--color-inverse-on-surface);
|
background: var(--color-inverse-on-surface);
|
||||||
color: var(--color-on-secondary-container);
|
color: var(--color-on-secondary-container);
|
||||||
|
|
|
@ -10,12 +10,16 @@ type Props = {
|
||||||
borderRadius?: number;
|
borderRadius?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
const ImagePlaceholder = ({ size = 50, borderRadius = 8 }: Props) => {
|
const ImagePlaceholder = ({ size = 40, borderRadius = 8 }: Props) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.container} style={{ width: size, height: size, borderRadius }}>
|
<div className={styles.container} style={{ width: size, height: size, borderRadius }}>
|
||||||
<img alt={t('general.placeholder')} src={defaultPlaceholder} />
|
<img
|
||||||
|
alt={t('general.placeholder')}
|
||||||
|
src={defaultPlaceholder}
|
||||||
|
style={{ width: size, height: size }}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -23,4 +23,15 @@
|
||||||
font: var(--font-body-small);
|
font: var(--font-body-small);
|
||||||
color: var(--color-outline);
|
color: var(--color-outline);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.compact {
|
||||||
|
.content {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
margin-right: _.unit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import classNames from 'classnames';
|
||||||
import React, { ReactNode } from 'react';
|
import React, { ReactNode } from 'react';
|
||||||
import { Link, To } from 'react-router-dom';
|
import { Link, To } from 'react-router-dom';
|
||||||
|
|
||||||
|
@ -8,13 +9,14 @@ type Props = {
|
||||||
subtitle?: string;
|
subtitle?: string;
|
||||||
icon?: ReactNode;
|
icon?: ReactNode;
|
||||||
to?: To;
|
to?: To;
|
||||||
|
size?: 'default' | 'compact';
|
||||||
};
|
};
|
||||||
|
|
||||||
const ItemPreview = ({ title, subtitle, icon, to }: Props) => {
|
const ItemPreview = ({ title, subtitle, icon, to, size = 'default' }: Props) => {
|
||||||
return (
|
return (
|
||||||
<div className={styles.item}>
|
<div className={classNames(styles.item, styles[size])}>
|
||||||
{icon && <div className={styles.icon}>{icon}</div>}
|
{icon && <div className={styles.icon}>{icon}</div>}
|
||||||
<div>
|
<div className={styles.content}>
|
||||||
{to && (
|
{to && (
|
||||||
<Link
|
<Link
|
||||||
className={styles.title}
|
className={styles.title}
|
||||||
|
|
|
@ -3,12 +3,12 @@
|
||||||
td > div.loading {
|
td > div.loading {
|
||||||
display: flex;
|
display: flex;
|
||||||
background: none;
|
background: none;
|
||||||
height: 50px;
|
height: 40px;
|
||||||
border-radius: unset;
|
border-radius: unset;
|
||||||
|
|
||||||
.avatar {
|
.avatar {
|
||||||
width: 50px;
|
width: 40px;
|
||||||
height: 50px;
|
height: 40px;
|
||||||
border-radius: _.unit(2);
|
border-radius: _.unit(2);
|
||||||
margin-right: _.unit(4);
|
margin-right: _.unit(4);
|
||||||
background: var(--color-neutral-95);
|
background: var(--color-neutral-95);
|
||||||
|
@ -20,14 +20,15 @@ td > div.loading {
|
||||||
.title {
|
.title {
|
||||||
background: var(--color-neutral-95);
|
background: var(--color-neutral-95);
|
||||||
border-radius: _.unit(2);
|
border-radius: _.unit(2);
|
||||||
height: 16px;
|
height: 14px;
|
||||||
margin: _.unit(2) 0;
|
margin: _.unit(1) 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.subTitle {
|
.subTitle {
|
||||||
background: var(--color-neutral-95);
|
background: var(--color-neutral-95);
|
||||||
border-radius: _.unit(2);
|
border-radius: _.unit(2);
|
||||||
height: 12px;
|
height: 12px;
|
||||||
|
margin-top: _.unit(2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
@use '@/scss/underscore' as _;
|
@use '@/scss/underscore' as _;
|
||||||
|
|
||||||
|
.card {
|
||||||
|
@include _.flex-column;
|
||||||
|
}
|
||||||
|
|
||||||
.headline {
|
.headline {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
@ -7,18 +11,7 @@
|
||||||
|
|
||||||
.table {
|
.table {
|
||||||
margin-top: _.unit(4);
|
margin-top: _.unit(4);
|
||||||
|
flex: 1;
|
||||||
tbody {
|
|
||||||
max-height: calc(100vh - _.unit(64));
|
|
||||||
|
|
||||||
tr.clickable {
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: var(--color-table-row-selected);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.apiResourceName {
|
.apiResourceName {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { Resource } from '@logto/schemas';
|
import { Resource } from '@logto/schemas';
|
||||||
import { conditional } from '@silverhand/essentials/lib/utilities/conditional.js';
|
import { conditional } from '@silverhand/essentials/lib/utilities/conditional.js';
|
||||||
|
import classNames from 'classnames';
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { toast } from 'react-hot-toast';
|
import { toast } from 'react-hot-toast';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
@ -18,6 +19,7 @@ import TableError from '@/components/Table/TableError';
|
||||||
import TableLoading from '@/components/Table/TableLoading';
|
import TableLoading from '@/components/Table/TableLoading';
|
||||||
import { RequestError } from '@/hooks/use-api';
|
import { RequestError } from '@/hooks/use-api';
|
||||||
import * as modalStyles from '@/scss/modal.module.scss';
|
import * as modalStyles from '@/scss/modal.module.scss';
|
||||||
|
import * as tableStyles from '@/scss/table.module.scss';
|
||||||
|
|
||||||
import CreateForm from './components/CreateForm';
|
import CreateForm from './components/CreateForm';
|
||||||
import * as styles from './index.module.scss';
|
import * as styles from './index.module.scss';
|
||||||
|
@ -32,7 +34,7 @@ const ApiResources = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card>
|
<Card className={styles.card}>
|
||||||
<div className={styles.headline}>
|
<div className={styles.headline}>
|
||||||
<CardTitle title="api_resources.title" subtitle="api_resources.subtitle" />
|
<CardTitle title="api_resources.title" subtitle="api_resources.subtitle" />
|
||||||
<Button
|
<Button
|
||||||
|
@ -62,55 +64,57 @@ const ApiResources = () => {
|
||||||
/>
|
/>
|
||||||
</Modal>
|
</Modal>
|
||||||
</div>
|
</div>
|
||||||
<table className={styles.table}>
|
<div className={classNames(styles.table, tableStyles.scrollable)}>
|
||||||
<colgroup>
|
<table>
|
||||||
<col className={styles.apiResourceName} />
|
<colgroup>
|
||||||
<col />
|
<col className={styles.apiResourceName} />
|
||||||
</colgroup>
|
<col />
|
||||||
<thead>
|
</colgroup>
|
||||||
<tr>
|
<thead>
|
||||||
<th>{t('api_resources.api_name')}</th>
|
<tr>
|
||||||
<th>{t('api_resources.api_identifier')}</th>
|
<th>{t('api_resources.api_name')}</th>
|
||||||
</tr>
|
<th>{t('api_resources.api_identifier')}</th>
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{error && (
|
|
||||||
<TableError
|
|
||||||
columns={2}
|
|
||||||
content={error.body.message}
|
|
||||||
onRetry={async () => mutate(undefined, true)}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{isLoading && <TableLoading columns={2} />}
|
|
||||||
{data?.length === 0 && (
|
|
||||||
<TableEmpty columns={2}>
|
|
||||||
<Button
|
|
||||||
title="admin_console.api_resources.create"
|
|
||||||
type="outline"
|
|
||||||
onClick={() => {
|
|
||||||
setIsCreateFormOpen(true);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</TableEmpty>
|
|
||||||
)}
|
|
||||||
{data?.map(({ id, name, indicator }) => (
|
|
||||||
<tr
|
|
||||||
key={id}
|
|
||||||
className={styles.clickable}
|
|
||||||
onClick={() => {
|
|
||||||
navigate(buildDetailsLink(id));
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<td>
|
|
||||||
<ItemPreview title={name} icon={<ImagePlaceholder />} to={buildDetailsLink(id)} />
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<CopyToClipboard value={indicator} />
|
|
||||||
</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
))}
|
</thead>
|
||||||
</tbody>
|
<tbody>
|
||||||
</table>
|
{error && (
|
||||||
|
<TableError
|
||||||
|
columns={2}
|
||||||
|
content={error.body.message}
|
||||||
|
onRetry={async () => mutate(undefined, true)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{isLoading && <TableLoading columns={2} />}
|
||||||
|
{data?.length === 0 && (
|
||||||
|
<TableEmpty columns={2}>
|
||||||
|
<Button
|
||||||
|
title="admin_console.api_resources.create"
|
||||||
|
type="outline"
|
||||||
|
onClick={() => {
|
||||||
|
setIsCreateFormOpen(true);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</TableEmpty>
|
||||||
|
)}
|
||||||
|
{data?.map(({ id, name, indicator }) => (
|
||||||
|
<tr
|
||||||
|
key={id}
|
||||||
|
className={tableStyles.clickable}
|
||||||
|
onClick={() => {
|
||||||
|
navigate(buildDetailsLink(id));
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<td>
|
||||||
|
<ItemPreview title={name} icon={<ImagePlaceholder />} to={buildDetailsLink(id)} />
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<CopyToClipboard value={indicator} />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
@use '@/scss/underscore' as _;
|
@use '@/scss/underscore' as _;
|
||||||
|
|
||||||
|
.card {
|
||||||
|
@include _.flex-column;
|
||||||
|
}
|
||||||
|
|
||||||
.headline {
|
.headline {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
@ -7,18 +11,7 @@
|
||||||
|
|
||||||
.table {
|
.table {
|
||||||
margin-top: _.unit(4);
|
margin-top: _.unit(4);
|
||||||
|
flex: 1;
|
||||||
tbody {
|
|
||||||
max-height: calc(100vh - _.unit(64));
|
|
||||||
|
|
||||||
tr.clickable {
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: var(--color-table-row-selected);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.applicationName {
|
.applicationName {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { Application } from '@logto/schemas';
|
import { Application } from '@logto/schemas';
|
||||||
import { conditional } from '@silverhand/essentials/lib/utilities/conditional.js';
|
import { conditional } from '@silverhand/essentials/lib/utilities/conditional.js';
|
||||||
|
import classNames from 'classnames';
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { toast } from 'react-hot-toast';
|
import { toast } from 'react-hot-toast';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
@ -18,6 +19,7 @@ import TableError from '@/components/Table/TableError';
|
||||||
import TableLoading from '@/components/Table/TableLoading';
|
import TableLoading from '@/components/Table/TableLoading';
|
||||||
import { RequestError } from '@/hooks/use-api';
|
import { RequestError } from '@/hooks/use-api';
|
||||||
import * as modalStyles from '@/scss/modal.module.scss';
|
import * as modalStyles from '@/scss/modal.module.scss';
|
||||||
|
import * as tableStyles from '@/scss/table.module.scss';
|
||||||
import { applicationTypeI18nKey } from '@/types/applications';
|
import { applicationTypeI18nKey } from '@/types/applications';
|
||||||
|
|
||||||
import CreateForm from './components/CreateForm';
|
import CreateForm from './components/CreateForm';
|
||||||
|
@ -31,7 +33,7 @@ const Applications = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card>
|
<Card className={styles.card}>
|
||||||
<div className={styles.headline}>
|
<div className={styles.headline}>
|
||||||
<CardTitle title="applications.title" subtitle="applications.subtitle" />
|
<CardTitle title="applications.title" subtitle="applications.subtitle" />
|
||||||
<Button
|
<Button
|
||||||
|
@ -60,60 +62,62 @@ const Applications = () => {
|
||||||
/>
|
/>
|
||||||
</Modal>
|
</Modal>
|
||||||
</div>
|
</div>
|
||||||
<table className={styles.table}>
|
<div className={classNames(styles.table, tableStyles.scrollable)}>
|
||||||
<colgroup>
|
<table>
|
||||||
<col className={styles.applicationName} />
|
<colgroup>
|
||||||
<col />
|
<col className={styles.applicationName} />
|
||||||
</colgroup>
|
<col />
|
||||||
<thead>
|
</colgroup>
|
||||||
<tr>
|
<thead>
|
||||||
<th>{t('applications.application_name')}</th>
|
<tr>
|
||||||
<th>{t('applications.client_id')}</th>
|
<th>{t('applications.application_name')}</th>
|
||||||
</tr>
|
<th>{t('applications.client_id')}</th>
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{error && (
|
|
||||||
<TableError
|
|
||||||
columns={2}
|
|
||||||
content={error.body.message}
|
|
||||||
onRetry={async () => mutate(undefined, true)}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{isLoading && <TableLoading columns={2} />}
|
|
||||||
{data?.length === 0 && (
|
|
||||||
<TableEmpty columns={2}>
|
|
||||||
<Button
|
|
||||||
title="admin_console.applications.create"
|
|
||||||
type="outline"
|
|
||||||
onClick={() => {
|
|
||||||
setIsCreateFormOpen(true);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</TableEmpty>
|
|
||||||
)}
|
|
||||||
{data?.map(({ id, name, type }) => (
|
|
||||||
<tr
|
|
||||||
key={id}
|
|
||||||
className={styles.clickable}
|
|
||||||
onClick={() => {
|
|
||||||
navigate(`/applications/${id}`);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<td>
|
|
||||||
<ItemPreview
|
|
||||||
title={name}
|
|
||||||
subtitle={t(`${applicationTypeI18nKey[type]}.title`)}
|
|
||||||
icon={<ImagePlaceholder />}
|
|
||||||
to={`/applications/${id}`}
|
|
||||||
/>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<CopyToClipboard value={id} />
|
|
||||||
</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
))}
|
</thead>
|
||||||
</tbody>
|
<tbody>
|
||||||
</table>
|
{error && (
|
||||||
|
<TableError
|
||||||
|
columns={2}
|
||||||
|
content={error.body.message}
|
||||||
|
onRetry={async () => mutate(undefined, true)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{isLoading && <TableLoading columns={2} />}
|
||||||
|
{data?.length === 0 && (
|
||||||
|
<TableEmpty columns={2}>
|
||||||
|
<Button
|
||||||
|
title="admin_console.applications.create"
|
||||||
|
type="outline"
|
||||||
|
onClick={() => {
|
||||||
|
setIsCreateFormOpen(true);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</TableEmpty>
|
||||||
|
)}
|
||||||
|
{data?.map(({ id, name, type }) => (
|
||||||
|
<tr
|
||||||
|
key={id}
|
||||||
|
className={tableStyles.clickable}
|
||||||
|
onClick={() => {
|
||||||
|
navigate(`/applications/${id}`);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<td>
|
||||||
|
<ItemPreview
|
||||||
|
title={name}
|
||||||
|
subtitle={t(`${applicationTypeI18nKey[type]}.title`)}
|
||||||
|
icon={<ImagePlaceholder />}
|
||||||
|
to={`/applications/${id}`}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<CopyToClipboard value={id} />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
@use '@/scss/underscore' as _;
|
@use '@/scss/underscore' as _;
|
||||||
|
|
||||||
|
.card {
|
||||||
|
@include _.flex-column;
|
||||||
|
}
|
||||||
|
|
||||||
.headline {
|
.headline {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
@ -11,18 +15,7 @@
|
||||||
|
|
||||||
.table {
|
.table {
|
||||||
margin-top: _.unit(4);
|
margin-top: _.unit(4);
|
||||||
|
flex: 1;
|
||||||
tbody {
|
|
||||||
max-height: calc(100vh - _.unit(74));
|
|
||||||
|
|
||||||
tr.clickable {
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: var(--color-table-row-selected);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.connectorName {
|
.connectorName {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { ConnectorDTO, ConnectorType } from '@logto/schemas';
|
import { ConnectorDTO, ConnectorType } from '@logto/schemas';
|
||||||
|
import classNames from 'classnames';
|
||||||
import React, { useMemo, useState } from 'react';
|
import React, { useMemo, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useLocation } from 'react-router-dom';
|
import { useLocation } from 'react-router-dom';
|
||||||
|
@ -12,6 +13,7 @@ import TableEmpty from '@/components/Table/TableEmpty';
|
||||||
import TableError from '@/components/Table/TableError';
|
import TableError from '@/components/Table/TableError';
|
||||||
import TableLoading from '@/components/Table/TableLoading';
|
import TableLoading from '@/components/Table/TableLoading';
|
||||||
import { RequestError } from '@/hooks/use-api';
|
import { RequestError } from '@/hooks/use-api';
|
||||||
|
import * as tableStyles from '@/scss/table.module.scss';
|
||||||
|
|
||||||
import ConnectorRow from './components/ConnectorRow';
|
import ConnectorRow from './components/ConnectorRow';
|
||||||
import SetupModal from './components/SetupModal';
|
import SetupModal from './components/SetupModal';
|
||||||
|
@ -49,7 +51,7 @@ const Connectors = () => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Card>
|
<Card className={styles.card}>
|
||||||
<div className={styles.headline}>
|
<div className={styles.headline}>
|
||||||
<CardTitle title="connectors.title" subtitle="connectors.subtitle" />
|
<CardTitle title="connectors.title" subtitle="connectors.subtitle" />
|
||||||
{isSocial && (
|
{isSocial && (
|
||||||
|
@ -66,54 +68,60 @@ const Connectors = () => {
|
||||||
<TabNavLink href="/connectors">{t('connectors.tab_email_sms')}</TabNavLink>
|
<TabNavLink href="/connectors">{t('connectors.tab_email_sms')}</TabNavLink>
|
||||||
<TabNavLink href="/connectors/social">{t('connectors.tab_social')}</TabNavLink>
|
<TabNavLink href="/connectors/social">{t('connectors.tab_social')}</TabNavLink>
|
||||||
</TabNav>
|
</TabNav>
|
||||||
<table className={styles.table}>
|
<div className={classNames(styles.table, tableStyles.scrollable)}>
|
||||||
<colgroup>
|
<table>
|
||||||
<col className={styles.connectorName} />
|
<colgroup>
|
||||||
<col />
|
<col className={styles.connectorName} />
|
||||||
<col />
|
<col />
|
||||||
</colgroup>
|
<col />
|
||||||
<thead>
|
</colgroup>
|
||||||
<tr>
|
<thead>
|
||||||
<th>{t('connectors.connector_name')}</th>
|
<tr>
|
||||||
<th>{t('connectors.connector_type')}</th>
|
<th>{t('connectors.connector_name')}</th>
|
||||||
<th>{t('connectors.connector_status')}</th>
|
<th>{t('connectors.connector_type')}</th>
|
||||||
</tr>
|
<th>{t('connectors.connector_status')}</th>
|
||||||
</thead>
|
</tr>
|
||||||
<tbody>
|
</thead>
|
||||||
{error && (
|
<tbody>
|
||||||
<TableError
|
{error && (
|
||||||
columns={3}
|
<TableError
|
||||||
content={error.body.message}
|
columns={3}
|
||||||
onRetry={async () => mutate(undefined, true)}
|
content={error.body.message}
|
||||||
/>
|
onRetry={async () => mutate(undefined, true)}
|
||||||
)}
|
/>
|
||||||
{isLoading && <TableLoading columns={3} />}
|
)}
|
||||||
{socialConnectors?.length === 0 && (
|
{isLoading && <TableLoading columns={3} />}
|
||||||
<TableEmpty
|
{socialConnectors?.length === 0 && (
|
||||||
columns={3}
|
<TableEmpty
|
||||||
title={t('connectors.type.social')}
|
columns={3}
|
||||||
content={t('connectors.social_connector_eg')}
|
title={t('connectors.type.social')}
|
||||||
>
|
content={t('connectors.social_connector_eg')}
|
||||||
<Button title="admin_console.connectors.create" type="outline" />
|
>
|
||||||
</TableEmpty>
|
<Button title="admin_console.connectors.create" type="outline" />
|
||||||
)}
|
</TableEmpty>
|
||||||
{!isLoading && !isSocial && (
|
)}
|
||||||
<ConnectorRow
|
{!isLoading && !isSocial && (
|
||||||
connector={emailConnector}
|
<ConnectorRow
|
||||||
type={ConnectorType.Email}
|
connector={emailConnector}
|
||||||
onClickSetup={() => {
|
type={ConnectorType.Email}
|
||||||
setCreateType(ConnectorType.Email);
|
onClickSetup={() => {
|
||||||
}}
|
setCreateType(ConnectorType.Email);
|
||||||
/>
|
}}
|
||||||
)}
|
/>
|
||||||
{!isLoading && !isSocial && (
|
)}
|
||||||
<ConnectorRow connector={smsConnector} type={ConnectorType.SMS} />
|
{!isLoading && !isSocial && (
|
||||||
)}
|
<ConnectorRow connector={smsConnector} type={ConnectorType.SMS} />
|
||||||
{socialConnectors?.map((connector) => (
|
)}
|
||||||
<ConnectorRow key={connector.id} connector={connector} type={ConnectorType.Social} />
|
{socialConnectors?.map((connector) => (
|
||||||
))}
|
<ConnectorRow
|
||||||
</tbody>
|
key={connector.id}
|
||||||
</table>
|
connector={connector}
|
||||||
|
type={ConnectorType.Social}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
{data && (
|
{data && (
|
||||||
<SetupModal
|
<SetupModal
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
@use '@/scss/underscore' as _;
|
@use '@/scss/underscore' as _;
|
||||||
|
|
||||||
.card {
|
.card {
|
||||||
display: flex;
|
@include _.flex-column;
|
||||||
flex-direction: column;
|
|
||||||
height: 100%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.headline {
|
.headline {
|
||||||
|
@ -17,14 +15,6 @@
|
||||||
|
|
||||||
.table {
|
.table {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
|
||||||
tr.clickable {
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: var(--color-table-row-selected);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.pagination {
|
.pagination {
|
||||||
|
|
|
@ -107,7 +107,7 @@ const Users = () => {
|
||||||
{users?.map(({ id, name, username }) => (
|
{users?.map(({ id, name, username }) => (
|
||||||
<tr
|
<tr
|
||||||
key={id}
|
key={id}
|
||||||
className={styles.clickable}
|
className={tableStyles.clickable}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
navigate(`/users/${id}`);
|
navigate(`/users/${id}`);
|
||||||
}}
|
}}
|
||||||
|
@ -116,8 +116,9 @@ const Users = () => {
|
||||||
<ItemPreview
|
<ItemPreview
|
||||||
title={name ?? '-'}
|
title={name ?? '-'}
|
||||||
subtitle={username ?? '-'}
|
subtitle={username ?? '-'}
|
||||||
icon={<ImagePlaceholder />}
|
icon={<ImagePlaceholder size={24} />}
|
||||||
to={`/users/${id}`}
|
to={`/users/${id}`}
|
||||||
|
size="compact"
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
<td>Application</td>
|
<td>Application</td>
|
||||||
|
|
|
@ -83,6 +83,7 @@
|
||||||
--color-code-comment: #66bb6a;
|
--color-code-comment: #66bb6a;
|
||||||
--color-surface-3: #e3dff5;
|
--color-surface-3: #e3dff5;
|
||||||
--color-surface-5: #dfd9f5;
|
--color-surface-5: #dfd9f5;
|
||||||
|
--shadow-light-s1: 0 2px 8px rgba(0, 0, 0, 8%);
|
||||||
--shadow-light-s2: 0 4px 12px rgba(0, 0, 0, 12%);
|
--shadow-light-s2: 0 4px 12px rgba(0, 0, 0, 12%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
@mixin flex-column {
|
@mixin flex-column {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin text-ellipsis {
|
@mixin text-ellipsis {
|
||||||
|
|
|
@ -30,30 +30,27 @@ table {
|
||||||
th {
|
th {
|
||||||
font: var(--font-subhead-2);
|
font: var(--font-subhead-2);
|
||||||
color: var(--color-component-caption);
|
color: var(--color-component-caption);
|
||||||
padding: _.unit(3) _.unit(4);
|
padding: _.unit(2);
|
||||||
border-bottom: 1px solid var(--color-neutral-90);
|
border-bottom: 1px solid var(--color-neutral-90);
|
||||||
text-align: left;
|
text-align: left;
|
||||||
|
|
||||||
|
&:first-child,
|
||||||
|
&:last-child {
|
||||||
|
padding: _.unit(2) _.unit(8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tbody {
|
||||||
|
td {
|
||||||
|
font: var(--font-body-medium);
|
||||||
|
border-bottom: 1px solid var(--color-neutral-90);
|
||||||
|
padding: _.unit(3) _.unit(2);
|
||||||
|
|
||||||
&:first-child,
|
&:first-child,
|
||||||
&:last-child {
|
&:last-child {
|
||||||
padding: _.unit(3) _.unit(8);
|
padding: _.unit(3) _.unit(8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tbody {
|
|
||||||
td {
|
|
||||||
border-bottom: 1px solid var(--color-neutral-90);
|
|
||||||
padding: _.unit(5) _.unit(4);
|
|
||||||
|
|
||||||
&:first-child,
|
|
||||||
&:last-child {
|
|
||||||
padding: _.unit(5) _.unit(8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tr:last-child td {
|
|
||||||
border-bottom: none;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,26 @@
|
||||||
@use '@/scss/underscore' as _;
|
@use '@/scss/underscore' as _;
|
||||||
|
|
||||||
|
.base {
|
||||||
|
box-shadow: var(--shadow-light-s1);
|
||||||
|
}
|
||||||
|
|
||||||
|
tr.clickable {
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: var(--color-table-row-selected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.scrollable {
|
.scrollable {
|
||||||
margin-top: _.unit(4);
|
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
border: 1px solid var(--color-neutral-90);
|
border: 1px solid var(--color-neutral-90);
|
||||||
border-radius: _.unit(2);
|
border-radius: _.unit(2);
|
||||||
|
box-shadow: var(--shadow-light-s1);
|
||||||
|
|
||||||
table {
|
table {
|
||||||
border: none;
|
border: none;
|
||||||
|
box-shadow: none;
|
||||||
|
|
||||||
thead tr {
|
thead tr {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
|
|
Loading…
Add table
Reference in a new issue