0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-03-31 22:51:25 -05:00

refactor(console): display loading when user assets service is loading (#3523)

This commit is contained in:
Xiao Yijun 2023-03-22 07:28:36 +08:00 committed by GitHub
parent 11e302b2fa
commit 1b303edfee
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 182 additions and 8 deletions

View file

@ -1,11 +1,16 @@
import type { UserAssetsServiceStatus } from '@logto/schemas';
import useSWRImmutable from 'swr/immutable';
import type { RequestError } from './use-api';
const useUserAssetsService = () => {
const { data } = useSWRImmutable<UserAssetsServiceStatus>('api/user-assets/service-status');
const { data, error } = useSWRImmutable<UserAssetsServiceStatus, RequestError>(
'api/user-assets/service-status'
);
return {
isReady: data?.status === 'ready',
isLoading: !error && !data,
};
};

View file

@ -0,0 +1,107 @@
@use '@/scss/underscore' as _;
.fieldWrapper {
padding: _.unit(2);
>:not(:first-child) {
margin-top: _.unit(6);
}
.title {
@include _.shimmering-animation;
width: 80px;
height: 16px;
}
.field {
@include _.shimmering-animation;
width: 100%;
height: 44px;
}
&:not(:first-child) {
margin-top: _.unit(3);
}
}
.preview {
background: var(--color-surface-variant);
padding: _.unit(6);
border-radius: 12px;
overflow: hidden;
.header {
padding: _.unit(2);
margin-bottom: _.unit(6);
display: flex;
justify-content: space-between;
.actions {
display: flex;
gap: _.unit(3);
}
.smallButton {
width: 30px;
height: 30px;
margin-left: _.unit(2.5);
@include _.shimmering-animation;
}
.button {
width: 104px;
height: 30px;
margin-left: _.unit(2.5);
@include _.shimmering-animation;
}
}
.mobile {
display: flex;
flex-direction: column;
align-items: center;
width: 375px;
height: 667px;
background: var(--color-surface);
margin: 0 auto;
padding: _.unit(6);
border-radius: 16px;
transform: scale(0.6);
transform-origin: top;
.logo {
width: 64px;
height: 64px;
margin-top: _.unit(16);
@include _.shimmering-animation;
}
.slogan {
width: 177px;
height: 16px;
margin: _.unit(3) 0 _.unit(10);
@include _.shimmering-animation;
}
.field {
width: 100%;
height: 36px;
margin-top: _.unit(3);
@include _.shimmering-animation;
}
.button {
width: 100%;
height: 36px;
margin-top: _.unit(10);
@include _.shimmering-animation;
}
.social {
width: 180px;
height: 24px;
margin-top: _.unit(3);
@include _.shimmering-animation;
}
}
}

View file

@ -0,0 +1,44 @@
import * as pageLayout from '@/onboarding/scss/layout.module.scss';
import * as sieLayout from '../../index.module.scss';
import * as styles from './index.module.scss';
const Skeleton = () => {
return (
<div className={pageLayout.page}>
<div className={pageLayout.contentContainer}>
<div className={sieLayout.content}>
<div className={sieLayout.config}>
{Array.from({ length: 3 }).map((_, index) => (
// eslint-disable-next-line react/no-array-index-key
<div key={index} className={styles.fieldWrapper}>
<div className={styles.title} />
<div className={styles.field} />
<div className={styles.field} />
</div>
))}
</div>
<div className={styles.preview}>
<div className={styles.header}>
<div className={styles.button} />
<div className={styles.actions}>
<div className={styles.smallButton} />
<div className={styles.button} />
</div>
</div>
<div className={styles.mobile}>
<div className={styles.logo} />
<div className={styles.slogan} />
<div className={styles.field} />
<div className={styles.field} />
<div className={styles.button} />
<div className={styles.social} />
</div>
</div>
</div>
</div>
</div>
);
};
export default Skeleton;

View file

@ -17,7 +17,6 @@
border-radius: 8px;
padding: _.unit(12);
margin-right: _.unit(6);
min-width: 500px;
.title {
margin-top: _.unit(6);

View file

@ -29,6 +29,7 @@ import { uriValidator } from '@/utils/validator';
import InspireMe from './components/InspireMe';
import Preview from './components/Preview';
import Skeleton from './components/Skeleton';
import SocialSelector from './components/SocialSelector';
import * as styles from './index.module.scss';
import { authenticationOptions, identifierOptions } from './options';
@ -39,10 +40,14 @@ import { parser } from './utils';
function SignInExperience() {
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
const navigate = useNavigate();
const { data: signInExperience, mutate } = useSWR<SignInExperienceType, RequestError>(
'api/sign-in-exp'
);
const {
data: signInExperience,
error,
mutate,
} = useSWR<SignInExperienceType, RequestError>('api/sign-in-exp');
const isSignInExperienceDataLoading = !error && !signInExperience;
const { isLoading: isUserAssetsServiceLoading } = useUserAssetsService();
const isLoading = isSignInExperienceDataLoading || isUserAssetsServiceLoading;
const api = useApi();
const { isReady: isUserAssetsServiceReady } = useUserAssetsService();
@ -96,6 +101,10 @@ function SignInExperience() {
onSuccess();
};
if (isLoading) {
return <Skeleton />;
}
return (
<div className={pageLayout.page}>
<OverlayScrollbar className={pageLayout.contentContainer}>

View file

@ -10,6 +10,7 @@ import { adminTenantEndpoint, meApi } from '@/consts';
import { isCloud } from '@/consts/cloud';
import { useStaticApi } from '@/hooks/use-api';
import useCurrentUser from '@/hooks/use-current-user';
import useUserAssetsService from '@/hooks/use-user-assets-service';
import * as resourcesStyles from '@/scss/resources.module.scss';
import { withAppInsights } from '@/utils/app-insights';
@ -27,12 +28,13 @@ function Profile() {
const navigate = useNavigate();
const api = useStaticApi({ prefixUrl: adminTenantEndpoint, resourceIndicator: meApi.indicator });
const { user, reload, isLoading: isLoadingUser } = useCurrentUser();
const { isLoading: isUserAssetServiceLoading } = useUserAssetsService();
const [connectors, setConnectors] = useState<ConnectorResponse[]>();
const [isLoadingConnectors, setIsLoadingConnectors] = useState(false);
const [showDeleteAccountModal, setShowDeleteAccountModal] = useState(false);
const showLoadingSkeleton = isLoadingUser || isLoadingConnectors;
const showLoadingSkeleton = isLoadingUser || isLoadingConnectors || isUserAssetServiceLoading;
useEffect(() => {
void reload();

View file

@ -21,6 +21,7 @@ import type { RequestError } from '@/hooks/use-api';
import useApi from '@/hooks/use-api';
import useConfigs from '@/hooks/use-configs';
import useUiLanguages from '@/hooks/use-ui-languages';
import useUserAssetsService from '@/hooks/use-user-assets-service';
import { withAppInsights } from '@/utils/app-insights';
import Preview from './components/Preview';
@ -62,6 +63,7 @@ function SignInExperience() {
const { tab } = useParams();
const { data, error, mutate } = useSWR<SignInExperienceType, RequestError>('api/sign-in-exp');
const isLoadingSignInExperience = !data && !error;
const { isLoading: isUserAssetsServiceLoading } = useUserAssetsService();
const {
configs,
@ -78,6 +80,12 @@ function SignInExperience() {
const requestError = error ?? configsError ?? languageError;
const isLoading =
isLoadingSignInExperience ||
isLoadingConfig ||
isLoadingLanguages ||
isUserAssetsServiceLoading;
const methods = useForm<SignInExperienceForm>();
const {
reset,
@ -134,7 +142,7 @@ function SignInExperience() {
await saveData();
});
if (isLoadingSignInExperience || isLoadingConfig || isLoadingLanguages) {
if (isLoading) {
return <Skeleton />;
}