0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2024-12-30 20:33:54 -05:00

refactor: update per review

This commit is contained in:
Gao Sun 2024-07-29 17:47:26 +08:00
parent 01df8f46a2
commit e67187126d
No known key found for this signature in database
GPG key ID: 13EBE123E4773688
11 changed files with 43 additions and 35 deletions

View file

@ -1,18 +1,30 @@
import type { Nullable } from '@silverhand/essentials';
import { type Nullable } from '@silverhand/essentials';
import { isValid } from 'date-fns';
type Props = {
readonly children: Nullable<string | number>;
};
function DateTime({ children }: Props) {
const date = children && new Date(children);
if (!date || !isValid(date)) {
return <span>-</span>;
const parseDate = (date: Nullable<string | number | Date>) => {
if (!date) {
return;
}
return <span>{date.toLocaleDateString()}</span>;
const parsed = new Date(date);
return isValid(parsed) ? parsed : undefined;
};
type Props = {
readonly children: Nullable<string | number | Date>;
};
/**
* Safely display a date in the user's locale. If the date is invalid, it will display a dash.
*/
export function LocaleDate({ children }: Props) {
return <span>{parseDate(children)?.toLocaleDateString() ?? '-'}</span>;
}
export default DateTime;
/**
* Safely display a date and time in the user's locale. If the date is invalid, it will display a
* dash.
*/
export function LocaleDateTime({ children }: Props) {
return <span>{parseDate(children)?.toLocaleString() ?? '-'}</span>;
}

View file

@ -7,6 +7,7 @@ import { type GuideMetadata } from '@/assets/docs/guides/types';
import Button from '@/ds-components/Button';
import OverlayScrollbar from '@/ds-components/OverlayScrollbar';
import MdxProvider from '@/mdx-components/MdxProvider';
import { type ApplicationSecretRow } from '@/pages/ApplicationDetails/ApplicationDetailsContent/EndpointsAndCredentials';
import NotFound from '@/pages/NotFound';
import StepsSkeleton from './StepsSkeleton';
@ -19,6 +20,7 @@ export type GuideContextType = {
| ((props: { readonly className?: string }) => JSX.Element);
isCompact: boolean;
app?: ApplicationResponse;
secrets?: ApplicationSecretRow[];
endpoint?: string;
redirectUris?: string[];
postLogoutRedirectUris?: string[];
@ -40,6 +42,7 @@ export const GuideContext = createContext<GuideContextType>({
metadata: {} as GuideMetadata,
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions, no-restricted-syntax
app: {} as ApplicationResponse,
secrets: [],
endpoint: '',
redirectUris: [],
postLogoutRedirectUris: [],

View file

@ -72,11 +72,6 @@
}
.dot {
flex-shrink: 0;
display: inline-block;
width: 6px;
height: 6px;
border-radius: 50%;
background: var(--color-text-secondary);
-webkit-text-stroke: 1px var(--color-text);
}
}

View file

@ -60,10 +60,7 @@ function CopyToClipboard(
return value;
}
return Array.from({ length: Math.max(Math.floor((value.length / 5) * 3), 1) }).map(
// eslint-disable-next-line react/no-array-index-key -- No need to persist the key
(_, index) => <span key={index} className={styles.dot} />
);
return <span className={styles.dot}>{'•'.repeat(value.length)}</span>;
}, [hasVisibilityToggle, showHiddenContent, value]);
useEffect(() => {

View file

@ -9,8 +9,8 @@ import TextLink from '@/ds-components/TextLink';
import styles from './index.module.scss';
function ApplicationCredentials() {
const { app } = useContext(GuideContext);
const { id, secret } = app ?? {};
const { app, secrets } = useContext(GuideContext);
const { id } = app ?? {};
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
return (
@ -37,12 +37,12 @@ function ApplicationCredentials() {
<CopyToClipboard displayType="block" value={id} variant="border" />
</FormField>
)}
{secret && (
{secrets?.[0] && (
<FormField title="application_details.application_secret">
<CopyToClipboard
hasVisibilityToggle
displayType="block"
value={secret}
value={secrets[0].value}
variant="border"
/>
</FormField>

View file

@ -31,7 +31,7 @@ button.add {
}
.expired {
color: var(--color-text-secondary);
color: var(--color-placeholder);
}
.copyToClipboard {

View file

@ -4,6 +4,7 @@ import { useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import ActionsButton from '@/components/ActionsButton';
import { LocaleDateTime } from '@/components/DateTime';
import CopyToClipboard from '@/ds-components/CopyToClipboard';
import { type Column } from '@/ds-components/Table/types';
import { Tooltip } from '@/ds-components/Tip';
@ -68,7 +69,7 @@ export const useSecretTableColumns = ({ appId, onUpdated }: UseSecretTableColumn
compareDesc(expiresAt, new Date()) === 1 ? (
<Expired expiresAt={new Date(expiresAt)} />
) : (
new Date(expiresAt).toLocaleString()
<LocaleDateTime>{expiresAt}</LocaleDateTime>
)
) : (
t('application_details.secrets.never')

View file

@ -6,7 +6,7 @@ import useSWR from 'swr';
import Plus from '@/assets/icons/plus.svg?react';
import ActionsButton from '@/components/ActionsButton';
import DateTime from '@/components/DateTime';
import { LocaleDate } from '@/components/DateTime';
import EmptyDataPlaceholder from '@/components/EmptyDataPlaceholder';
import UserPreview from '@/components/ItemPreview/UserPreview';
import { RoleOption } from '@/components/OrganizationRolesSelect';
@ -96,7 +96,7 @@ function Members() {
dataIndex: 'lastSignInAt',
title: t('users.latest_sign_in'),
colSpan: 5,
render: ({ lastSignInAt }) => <DateTime>{lastSignInAt}</DateTime>,
render: ({ lastSignInAt }) => <LocaleDate>{lastSignInAt}</LocaleDate>,
},
{
dataIndex: 'actions',

View file

@ -9,7 +9,7 @@ import useSWR from 'swr';
import Delete from '@/assets/icons/delete.svg?react';
import Plus from '@/assets/icons/plus.svg?react';
import ApplicationName from '@/components/ApplicationName';
import DateTime from '@/components/DateTime';
import { LocaleDate } from '@/components/DateTime';
import EmptyDataPlaceholder from '@/components/EmptyDataPlaceholder';
import UserPreview from '@/components/ItemPreview/UserPreview';
import { defaultPageSize } from '@/consts';
@ -103,7 +103,7 @@ function RoleUsers() {
title: t('role_details.users.latest_sign_in_column'),
dataIndex: 'latestSignIn',
colSpan: 5,
render: ({ lastSignInAt }) => <DateTime>{lastSignInAt}</DateTime>,
render: ({ lastSignInAt }) => <LocaleDate>{lastSignInAt}</LocaleDate>,
},
{
title: null,

View file

@ -8,7 +8,7 @@ import Plus from '@/assets/icons/plus.svg?react';
import UsersEmptyDark from '@/assets/images/users-empty-dark.svg?react';
import UsersEmpty from '@/assets/images/users-empty.svg?react';
import ApplicationName from '@/components/ApplicationName';
import DateTime from '@/components/DateTime';
import { LocaleDate } from '@/components/DateTime';
import EmptyDataPlaceholder from '@/components/EmptyDataPlaceholder';
import ItemPreview from '@/components/ItemPreview';
import ListPage from '@/components/ListPage';
@ -104,7 +104,7 @@ function Users() {
title: t('users.latest_sign_in'),
dataIndex: 'lastSignInAt',
colSpan: 5,
render: ({ lastSignInAt }) => <DateTime>{lastSignInAt}</DateTime>,
render: ({ lastSignInAt }) => <LocaleDate>{lastSignInAt}</LocaleDate>,
},
],
filter: (

View file

@ -179,7 +179,7 @@ const application_details = {
expiration: 'Expiration',
expiration_description: 'The secret will expire at {{date}}.',
expiration_description_never:
'The secret will never expire. We recommend setting an expiration date for better security.',
'The secret will never expire. We recommend setting an expiration date for enhanced security.',
days: '{{count}} day',
days_other: '{{count}} days',
},