From fbd7ac3a69c51ed5153b1764aa6b47df1a51bf8c Mon Sep 17 00:00:00 2001 From: Charles Zhao Date: Tue, 7 Jun 2022 11:51:26 +0800 Subject: [PATCH] refactor(console): hide check demo button if demo app is deleted --- packages/console/src/hooks/use-api.ts | 23 +++++----- packages/console/src/hooks/use-swr-fetcher.ts | 2 +- .../components/Skeleton/index.module.scss | 44 +++++++++++++++++++ .../GetStarted/components/Skeleton/index.tsx | 19 ++++++++ packages/console/src/pages/GetStarted/hook.ts | 17 +++++++ .../console/src/pages/GetStarted/index.tsx | 42 ++++++++++-------- 6 files changed, 116 insertions(+), 31 deletions(-) create mode 100644 packages/console/src/pages/GetStarted/components/Skeleton/index.module.scss create mode 100644 packages/console/src/pages/GetStarted/components/Skeleton/index.tsx diff --git a/packages/console/src/hooks/use-api.ts b/packages/console/src/hooks/use-api.ts index bc2bbaba4..967cdd47c 100644 --- a/packages/console/src/hooks/use-api.ts +++ b/packages/console/src/hooks/use-api.ts @@ -1,17 +1,18 @@ import { useLogto } from '@logto/react'; import { RequestErrorBody } from '@logto/schemas'; import { managementResource } from '@logto/schemas/lib/seeds'; -import { conditional } from '@silverhand/essentials'; import { t } from 'i18next'; import ky from 'ky'; import { useMemo } from 'react'; import { toast } from 'react-hot-toast'; export class RequestError extends Error { + status: number; body?: RequestErrorBody; - constructor(body: RequestErrorBody) { + constructor(status: number, body: RequestErrorBody) { super('Request error occurred.'); + this.status = status; this.body = body; } } @@ -36,17 +37,15 @@ const useApi = ({ hideErrorToast }: Props = {}) => { () => ky.create({ hooks: { - beforeError: conditional( - !hideErrorToast && [ - (error) => { - const { response } = error; + beforeError: hideErrorToast + ? [] + : [ + (error) => { + void toastError(error.response); - void toastError(response); - - return error; - }, - ] - ), + return error; + }, + ], beforeRequest: [ async (request) => { if (isAuthenticated) { diff --git a/packages/console/src/hooks/use-swr-fetcher.ts b/packages/console/src/hooks/use-swr-fetcher.ts index abf9382e3..b1247b7a2 100644 --- a/packages/console/src/hooks/use-swr-fetcher.ts +++ b/packages/console/src/hooks/use-swr-fetcher.ts @@ -41,7 +41,7 @@ const useSwrFetcher: useSwrFetcherHook = () => { if (error instanceof HTTPError) { const { response } = error; const metadata = await response.json(); - throw new RequestError(metadata); + throw new RequestError(response.status, metadata); } throw error; } diff --git a/packages/console/src/pages/GetStarted/components/Skeleton/index.module.scss b/packages/console/src/pages/GetStarted/components/Skeleton/index.module.scss new file mode 100644 index 000000000..6711a4ece --- /dev/null +++ b/packages/console/src/pages/GetStarted/components/Skeleton/index.module.scss @@ -0,0 +1,44 @@ +@use '@/scss/underscore' as _; + +.card { + display: flex; + padding: _.unit(6) _.unit(8); + background-color: var(--color-layer-1); + border-radius: 16px; + + .icon { + @include _.shimmering-animation; + width: 48px; + height: 48px; + margin-right: _.unit(6); + } + + .wrapper { + flex: 1; + display: flex; + flex-direction: column; + + .title { + @include _.shimmering-animation; + width: 113px; + height: 20px; + } + + .subtitle { + @include _.shimmering-animation; + width: 453px; + height: 20px; + margin-top: _.unit(1); + } + } + + .button { + @include _.shimmering-animation; + width: 129px; + height: 44px; + } +} + +.card + .card { + margin-top: _.unit(4); +} diff --git a/packages/console/src/pages/GetStarted/components/Skeleton/index.tsx b/packages/console/src/pages/GetStarted/components/Skeleton/index.tsx new file mode 100644 index 000000000..9b77ec18c --- /dev/null +++ b/packages/console/src/pages/GetStarted/components/Skeleton/index.tsx @@ -0,0 +1,19 @@ +import React from 'react'; + +import * as styles from './index.module.scss'; + +const Skeleton = () => ( + <> + {[...Array.from({ length: 5 }).keys()].map((key) => ( +
+
+
+
+
+
+
+ ))} + +); + +export default Skeleton; diff --git a/packages/console/src/pages/GetStarted/hook.ts b/packages/console/src/pages/GetStarted/hook.ts index 9542a0c99..9067cf85d 100644 --- a/packages/console/src/pages/GetStarted/hook.ts +++ b/packages/console/src/pages/GetStarted/hook.ts @@ -1,5 +1,7 @@ import { AdminConsoleKey, I18nKey } from '@logto/phrases'; +import { Application } from '@logto/schemas'; import { useNavigate } from 'react-router-dom'; +import useSWR from 'swr'; import checkDemoIcon from '@/assets/images/check-demo.svg'; import createAppIcon from '@/assets/images/create-app.svg'; @@ -7,6 +9,7 @@ import customizeIcon from '@/assets/images/customize.svg'; import furtherReadingsIcon from '@/assets/images/further-readings.svg'; import oneClickIcon from '@/assets/images/one-click.svg'; import passwordlessIcon from '@/assets/images/passwordless.svg'; +import { RequestError } from '@/hooks/use-api'; import useSettings from '@/hooks/use-settings'; type GetStartedMetadata = { @@ -16,12 +19,24 @@ type GetStartedMetadata = { icon: string; buttonText: I18nKey; isComplete?: boolean; + isHidden?: boolean; onClick: () => void; }; const useGetStartedMetadata = () => { const { settings, updateSettings } = useSettings(); + const { data: demoApp, error } = useSWR('/api/applications/demo_app', { + shouldRetryOnError: (error: unknown) => { + if (error instanceof RequestError) { + return error.status !== 404; + } + + return true; + }, + }); const navigate = useNavigate(); + const isLoadingDemoApp = !demoApp && !error; + const hideDemo = error?.status === 404; const data: GetStartedMetadata[] = [ { @@ -31,6 +46,7 @@ const useGetStartedMetadata = () => { icon: checkDemoIcon, buttonText: 'general.check_out', isComplete: settings?.checkDemo, + isHidden: hideDemo, onClick: async () => { void updateSettings({ checkDemo: true }); window.open('/demo-app', '_blank'); @@ -97,6 +113,7 @@ const useGetStartedMetadata = () => { data, completedCount: data.filter(({ isComplete }) => isComplete).length, totalCount: data.length, + isLoading: isLoadingDemoApp, }; }; diff --git a/packages/console/src/pages/GetStarted/index.tsx b/packages/console/src/pages/GetStarted/index.tsx index c1880f946..ebd612f04 100644 --- a/packages/console/src/pages/GetStarted/index.tsx +++ b/packages/console/src/pages/GetStarted/index.tsx @@ -9,13 +9,14 @@ import ConfirmModal from '@/components/ConfirmModal'; import Spacer from '@/components/Spacer'; import useUserPreferences from '@/hooks/use-user-preferences'; +import Skeleton from './components/Skeleton'; import useGetStartedMetadata from './hook'; import * as styles from './index.module.scss'; const GetStarted = () => { const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' }); const navigate = useNavigate(); - const { data } = useGetStartedMetadata(); + const { data, isLoading } = useGetStartedMetadata(); const { update } = useUserPreferences(); const [showConfirmModal, setShowConfirmModal] = useState(false); @@ -45,23 +46,28 @@ const GetStarted = () => {
- {data.map(({ id, title, subtitle, icon, isComplete, buttonText, onClick }) => ( - - - {isComplete && } -
-
{t(title)}
-
{t(subtitle)}
-
-