0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-02-17 22:04:19 -05:00

fix(console): add missing loading state for confirm modals (#3610)

This commit is contained in:
Xiao Yijun 2023-03-28 17:54:44 +08:00 committed by GitHub
parent a33173d9c9
commit 5f1c9a579b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 76 additions and 43 deletions

View file

@ -9,11 +9,19 @@ type Props = {
data: ConnectorResponse; data: ConnectorResponse;
isOpen: boolean; isOpen: boolean;
isInUse: boolean; isInUse: boolean;
isLoading: boolean;
onCancel: () => void; onCancel: () => void;
onConfirm: () => void; onConfirm: () => void;
}; };
function DeleteConnectorConfirmModal({ data, isOpen, isInUse, onCancel, onConfirm }: Props) { function DeleteConnectorConfirmModal({
data,
isOpen,
isInUse,
isLoading,
onCancel,
onConfirm,
}: Props) {
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' }); const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
const isSocial = data.type === ConnectorType.Social; const isSocial = data.type === ConnectorType.Social;
@ -21,6 +29,7 @@ function DeleteConnectorConfirmModal({ data, isOpen, isInUse, onCancel, onConfir
<ConfirmModal <ConfirmModal
isOpen={isOpen} isOpen={isOpen}
confirmButtonText="general.delete" confirmButtonText="general.delete"
isLoading={isLoading}
onCancel={onCancel} onCancel={onCancel}
onConfirm={onConfirm} onConfirm={onConfirm}
> >

View file

@ -68,36 +68,32 @@ function ConnectorDetails() {
const navigate = useNavigate(); const navigate = useNavigate();
const isSocial = data?.type === ConnectorType.Social; const isSocial = data?.type === ConnectorType.Social;
const [isDeleteAlertOpen, setIsDeleteAlertOpen] = useState(false); const [isDeleteAlertOpen, setIsDeleteAlertOpen] = useState(false);
const [isDeleting, setIsDeleting] = useState(false);
useEffect(() => { useEffect(() => {
setIsDeleteAlertOpen(false); setIsDeleteAlertOpen(false);
}, [pathname]); }, [pathname]);
const onDeleteClick = async () => {
if (!inUse) {
await handleDelete();
return;
}
setIsDeleteAlertOpen(true);
};
const handleDelete = async () => { const handleDelete = async () => {
if (!connectorId) { if (!connectorId || isDeleting) {
return; return;
} }
setIsDeleting(true);
await api.delete(`api/connectors/${connectorId}`).json<ConnectorResponse>(); try {
await api.delete(`api/connectors/${connectorId}`).json<ConnectorResponse>();
setIsDeleted(true); setIsDeleted(true);
toast.success(t('connector_details.connector_deleted')); toast.success(t('connector_details.connector_deleted'));
await mutateGlobal('api/connectors'); await mutateGlobal('api/connectors');
navigate(getConnectorsPathname(isSocial), { navigate(getConnectorsPathname(isSocial), {
replace: true, replace: true,
}); });
} finally {
setIsDeleting(false);
}
}; };
if (!connectorId) { if (!connectorId) {
@ -225,6 +221,7 @@ function ConnectorDetails() {
data={data} data={data}
isInUse={inUse} isInUse={inUse}
isOpen={isDeleteAlertOpen} isOpen={isDeleteAlertOpen}
isLoading={isDeleting}
onCancel={() => { onCancel={() => {
setIsDeleteAlertOpen(false); setIsDeleteAlertOpen(false);
}} }}

View file

@ -26,24 +26,30 @@ function ConnectorDeleteButton({ connectorGroup }: Props) {
const inUse = isConnectorInUse(firstConnector); const inUse = isConnectorInUse(firstConnector);
const [isDeleteAlertOpen, setIsDeleteAlertOpen] = useState(false); const [isDeleteAlertOpen, setIsDeleteAlertOpen] = useState(false);
const [isDeleting, setIsDeleting] = useState(false);
const api = useApi(); const api = useApi();
const handleDelete = async () => { const handleDelete = async () => {
if (!firstConnector) { if (!firstConnector || isDeleting) {
return; return;
} }
setIsDeleting(true);
const { connectors } = connectorGroup; const { connectors } = connectorGroup;
await Promise.all( try {
connectors.map(async (connector) => { await Promise.all(
await api.delete(`api/connectors/${connector.id}`).json<ConnectorResponse>(); connectors.map(async (connector) => {
}) await api.delete(`api/connectors/${connector.id}`).json<ConnectorResponse>();
); })
);
toast.success(t('connector_details.connector_deleted')); toast.success(t('connector_details.connector_deleted'));
await mutateGlobal('api/connectors'); await mutateGlobal('api/connectors');
} finally {
setIsDeleting(false);
}
}; };
if (!firstConnector) { if (!firstConnector) {
@ -65,6 +71,7 @@ function ConnectorDeleteButton({ connectorGroup }: Props) {
data={firstConnector} data={firstConnector}
isInUse={inUse} isInUse={inUse}
isOpen={isDeleteAlertOpen} isOpen={isDeleteAlertOpen}
isLoading={isDeleting}
onCancel={() => { onCancel={() => {
setIsDeleteAlertOpen(false); setIsDeleteAlertOpen(false);
}} }}

View file

@ -20,11 +20,21 @@ function GetStarted() {
const { data, isLoading } = useGetStartedMetadata(); const { data, isLoading } = useGetStartedMetadata();
const { update } = useUserPreferences(); const { update } = useUserPreferences();
const [showConfirmModal, setShowConfirmModal] = useState(false); const [showConfirmModal, setShowConfirmModal] = useState(false);
const [isUpdating, setIsUpdating] = useState(false);
const hideGetStarted = () => { const hideGetStarted = async () => {
void update({ getStartedHidden: true }); if (isUpdating) {
// Navigate to next menu item return;
navigate('/dashboard'); }
setIsUpdating(true);
try {
await update({ getStartedHidden: true });
// Navigate to next menu item
navigate('/dashboard');
} finally {
setIsUpdating(false);
}
}; };
const showConfirmModalHandler = () => { const showConfirmModalHandler = () => {
@ -77,6 +87,7 @@ function GetStarted() {
isOpen={showConfirmModal} isOpen={showConfirmModal}
confirmButtonType="primary" confirmButtonType="primary"
confirmButtonText="get_started.hide_this" confirmButtonText="get_started.hide_this"
isLoading={isUpdating}
onConfirm={hideGetStarted} onConfirm={hideGetStarted}
onCancel={hideConfirmModalHandler} onCancel={hideConfirmModalHandler}
> >

View file

@ -65,6 +65,7 @@ function SignInExperience() {
const { data, error, mutate } = useSWR<SignInExperienceType, RequestError>('api/sign-in-exp'); const { data, error, mutate } = useSWR<SignInExperienceType, RequestError>('api/sign-in-exp');
const isLoadingSignInExperience = !data && !error; const isLoadingSignInExperience = !data && !error;
const { isLoading: isUserAssetsServiceLoading } = useUserAssetsService(); const { isLoading: isUserAssetsServiceLoading } = useUserAssetsService();
const [isSaving, setIsSaving] = useState(false);
const { const {
configs, configs,
@ -93,7 +94,7 @@ function SignInExperience() {
handleSubmit, handleSubmit,
getValues, getValues,
watch, watch,
formState: { isSubmitting, isDirty, errors }, formState: { isDirty, errors },
} = methods; } = methods;
const api = useApi(); const api = useApi();
const formData = watch(); const formData = watch();
@ -115,19 +116,25 @@ function SignInExperience() {
}, [reset, defaultFormData]); }, [reset, defaultFormData]);
const saveData = async () => { const saveData = async () => {
const updatedData = await api setIsSaving(true);
.patch('api/sign-in-exp', {
json: signInExperienceParser.toRemoteModel(getValues()), try {
}) const updatedData = await api
.json<SignInExperienceType>(); .patch('api/sign-in-exp', {
void mutate(updatedData); json: signInExperienceParser.toRemoteModel(getValues()),
setDataToCompare(undefined); })
await updateConfigs({ signInExperienceCustomized: true }); .json<SignInExperienceType>();
toast.success(t('general.saved')); void mutate(updatedData);
setDataToCompare(undefined);
await updateConfigs({ signInExperienceCustomized: true });
toast.success(t('general.saved'));
} finally {
setIsSaving(false);
}
}; };
const onSubmit = handleSubmit(async (formData: SignInExperienceForm) => { const onSubmit = handleSubmit(async (formData: SignInExperienceForm) => {
if (!data || isSubmitting) { if (!data || isSaving) {
return; return;
} }
@ -217,7 +224,7 @@ function SignInExperience() {
</div> </div>
<SubmitFormChangesActionBar <SubmitFormChangesActionBar
isOpen={isDirty} isOpen={isDirty}
isSubmitting={isSubmitting} isSubmitting={isSaving}
onDiscard={reset} onDiscard={reset}
onSubmit={onSubmit} onSubmit={onSubmit}
/> />
@ -226,6 +233,7 @@ function SignInExperience() {
{data && ( {data && (
<ConfirmModal <ConfirmModal
isOpen={Boolean(dataToCompare)} isOpen={Boolean(dataToCompare)}
isLoading={isSaving}
onCancel={() => { onCancel={() => {
setDataToCompare(undefined); setDataToCompare(undefined);
}} }}

View file

@ -136,6 +136,7 @@ function UserSocialIdentities({ userId, identities, onDelete }: Props) {
)} )}
<DeleteConfirmModal <DeleteConfirmModal
isOpen={deletingConnector !== undefined} isOpen={deletingConnector !== undefined}
isLoading={isSubmitting}
onCancel={() => { onCancel={() => {
setDeletingConnector(undefined); setDeletingConnector(undefined);
}} }}