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

feat(console): connector details header (#348)

This commit is contained in:
Wang Sijie 2022-03-09 15:54:46 +08:00 committed by GitHub
parent 6fcc682f4f
commit dab3c12bea
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 158 additions and 49 deletions

View file

@ -12,8 +12,8 @@ import initI18n from './i18n/init';
import ApiResources from './pages/ApiResources'; import ApiResources from './pages/ApiResources';
import ApplicationDetails from './pages/ApplicationDetails'; import ApplicationDetails from './pages/ApplicationDetails';
import Applications from './pages/Applications'; import Applications from './pages/Applications';
import ConnectorDetails from './pages/ConnectorDetails';
import Connectors from './pages/Connectors'; import Connectors from './pages/Connectors';
import Connector from './pages/Connectors/Connector';
import { fetcher } from './swr'; import { fetcher } from './swr';
const isBasenameNeeded = process.env.NODE_ENV !== 'development' || process.env.PORT === '5002'; const isBasenameNeeded = process.env.NODE_ENV !== 'development' || process.env.PORT === '5002';
@ -46,7 +46,7 @@ const Main = () => {
<Route path="connectors"> <Route path="connectors">
<Route index element={<Connectors />} /> <Route index element={<Connectors />} />
<Route path="social" element={<Connectors />} /> <Route path="social" element={<Connectors />} />
<Route path=":connectorId" element={<Connector />} /> <Route path=":connectorId" element={<ConnectorDetails />} />
</Route> </Route>
</Routes> </Routes>
</Content> </Content>

View file

@ -0,0 +1,14 @@
@use '@/scss/underscore' as _;
.button {
padding-left: 0;
.body {
display: flex;
align-items: center;
> *:not(:first-child) {
margin-left: _.unit(1);
}
}
}

View file

@ -0,0 +1,24 @@
import classNames from 'classnames';
import React, { ReactNode } from 'react';
import { Link } from 'react-router-dom';
import * as buttonStyles from '@/components/TextButton/index.module.scss';
import Back from './Back';
import * as styles from './index.module.scss';
type Props = {
to: string;
children: ReactNode;
};
const BackLink = ({ to, children }: Props) => (
<Link to={to} className={classNames(buttonStyles.button, styles.button)}>
<div className={styles.body}>
<Back />
<div>{children}</div>
</div>
</Link>
);
export default BackLink;

View file

@ -6,19 +6,6 @@
} }
} }
.button {
padding-left: 0;
.body {
display: flex;
align-items: center;
> *:not(:first-child) {
margin-left: _.unit(1);
}
}
}
.container .header { .container .header {
padding: _.unit(8); padding: _.unit(8);
display: flex; display: flex;

View file

@ -1,18 +1,16 @@
import { Application } from '@logto/schemas'; import { Application } from '@logto/schemas';
import classNames from 'classnames';
import React from 'react'; import React from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { Link, useParams } from 'react-router-dom'; import { useParams } from 'react-router-dom';
import useSWR from 'swr'; import useSWR from 'swr';
import BackLink from '@/components/BackLink';
import Card from '@/components/Card'; import Card from '@/components/Card';
import CopyToClipboard from '@/components/CopyToClipboard'; import CopyToClipboard from '@/components/CopyToClipboard';
import ImagePlaceholder from '@/components/ImagePlaceholder'; import ImagePlaceholder from '@/components/ImagePlaceholder';
import * as buttonStyles from '@/components/TextButton/index.module.scss';
import { RequestError } from '@/swr'; import { RequestError } from '@/swr';
import { applicationTypeI18nKey } from '@/types/applications'; import { applicationTypeI18nKey } from '@/types/applications';
import Back from './icons/Back';
import * as styles from './index.module.scss'; import * as styles from './index.module.scss';
const ApplicationDetails = () => { const ApplicationDetails = () => {
@ -23,12 +21,7 @@ const ApplicationDetails = () => {
return ( return (
<div className={styles.container}> <div className={styles.container}>
<Link to="/applications" className={classNames(buttonStyles.button, styles.button)}> <BackLink to="/applications">{t('application_details.back_to_applications')}</BackLink>
<div className={styles.body}>
<Back />
<div>{t('application_details.back_to_applications')}</div>
</div>
</Link>
{isLoading && <div>loading</div>} {isLoading && <div>loading</div>}
{error && <div>{`error occurred: ${error.metadata.code}`}</div>} {error && <div>{`error occurred: ${error.metadata.code}`}</div>}
{data && ( {data && (

View file

@ -0,0 +1,51 @@
@use '@/scss/underscore' as _;
.container {
> *:not(:first-child) {
margin-top: _.unit(4);
}
}
.container .header {
padding: _.unit(8);
display: flex;
align-items: center;
justify-content: space-between;
> *:not(:first-child) {
margin-left: _.unit(6);
}
.logo {
width: _.unit(19);
height: _.unit(19);
border-radius: _.unit(4);
}
.metadata {
flex: 1;
> div {
display: flex;
align-items: center;
&:not(:first-child) {
margin-top: _.unit(2);
}
> *:not(:first-child) {
margin-left: _.unit(2);
}
}
.name {
font: var(--font-title-large);
color: var(--color-component-text);
}
.id {
font: var(--font-subhead-2);
color: var(--color-component-caption);
}
}
}

View file

@ -0,0 +1,58 @@
import { ConnectorDTO } from '@logto/schemas';
import React from 'react';
import { useTranslation } from 'react-i18next';
import { useParams } from 'react-router-dom';
import useSWR from 'swr';
import BackLink from '@/components/BackLink';
import Card from '@/components/Card';
import ImagePlaceholder from '@/components/ImagePlaceholder';
import Status from '@/components/Status';
import { RequestError } from '@/swr';
import * as styles from './index.module.scss';
const ConnectorDetails = () => {
const { connectorId } = useParams();
const {
t,
i18n: { language },
} = useTranslation(undefined, { keyPrefix: 'admin_console' });
const { data, error } = useSWR<ConnectorDTO, RequestError>(
connectorId && `/api/connectors/${connectorId}`
);
const isLoading = !data && !error;
return (
<div className={styles.container}>
<BackLink to="/connectors">{t('connector_details.back_to_connectors')}</BackLink>
{isLoading && <div>loading</div>}
{error && <div>{`error occurred: ${error.metadata.code}`}</div>}
{data && (
<Card className={styles.header}>
{data.metadata.logo.startsWith('http') ? (
<img src={data.metadata.logo} className={styles.logo} />
) : (
<ImagePlaceholder size={76} borderRadius={16} />
)}
<div className={styles.metadata}>
<div>
<div className={styles.name}>{data.metadata.name[language]}</div>
<div className={styles.id}>{data.id}</div>
</div>
<div>
<Status status={data.enabled ? 'operational' : 'offline'}>
{t('connectors.connector_status', {
context: data.enabled ? 'enabled' : 'disabled',
})}
</Status>
</div>
</div>
<div>action</div>
</Card>
)}
</div>
);
};
export default ConnectorDetails;

View file

@ -1,24 +0,0 @@
import { ConnectorDTO } from '@logto/schemas';
import React from 'react';
import { useParams } from 'react-router-dom';
import useSWR from 'swr';
import Card from '@/components/Card';
import { RequestError } from '@/swr';
const Connector = () => {
const { connectorId } = useParams();
const { data, error } = useSWR<ConnectorDTO, RequestError>(
connectorId && `/api/connectors/${connectorId}`
);
const isLoading = !data && !error;
return (
<Card>
{isLoading && 'loading'}
{error && error}
</Card>
);
};
export default Connector;

View file

@ -101,6 +101,9 @@ const translation = {
application_details: { application_details: {
back_to_applications: 'Back to Applications', back_to_applications: 'Back to Applications',
}, },
connector_details: {
back_to_connectors: 'Back to Connectors',
},
}, },
}; };

View file

@ -103,6 +103,9 @@ const translation = {
application_details: { application_details: {
back_to_applications: '返回应用集', back_to_applications: '返回应用集',
}, },
connector_details: {
back_to_connectors: '返回连接器',
},
}, },
}; };