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:
parent
a33173d9c9
commit
5f1c9a579b
6 changed files with 76 additions and 43 deletions
|
@ -9,11 +9,19 @@ type Props = {
|
|||
data: ConnectorResponse;
|
||||
isOpen: boolean;
|
||||
isInUse: boolean;
|
||||
isLoading: boolean;
|
||||
onCancel: () => 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 isSocial = data.type === ConnectorType.Social;
|
||||
|
||||
|
@ -21,6 +29,7 @@ function DeleteConnectorConfirmModal({ data, isOpen, isInUse, onCancel, onConfir
|
|||
<ConfirmModal
|
||||
isOpen={isOpen}
|
||||
confirmButtonText="general.delete"
|
||||
isLoading={isLoading}
|
||||
onCancel={onCancel}
|
||||
onConfirm={onConfirm}
|
||||
>
|
||||
|
|
|
@ -68,26 +68,19 @@ function ConnectorDetails() {
|
|||
const navigate = useNavigate();
|
||||
const isSocial = data?.type === ConnectorType.Social;
|
||||
const [isDeleteAlertOpen, setIsDeleteAlertOpen] = useState(false);
|
||||
const [isDeleting, setIsDeleting] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
setIsDeleteAlertOpen(false);
|
||||
}, [pathname]);
|
||||
|
||||
const onDeleteClick = async () => {
|
||||
if (!inUse) {
|
||||
await handleDelete();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
setIsDeleteAlertOpen(true);
|
||||
};
|
||||
|
||||
const handleDelete = async () => {
|
||||
if (!connectorId) {
|
||||
if (!connectorId || isDeleting) {
|
||||
return;
|
||||
}
|
||||
setIsDeleting(true);
|
||||
|
||||
try {
|
||||
await api.delete(`api/connectors/${connectorId}`).json<ConnectorResponse>();
|
||||
|
||||
setIsDeleted(true);
|
||||
|
@ -98,6 +91,9 @@ function ConnectorDetails() {
|
|||
navigate(getConnectorsPathname(isSocial), {
|
||||
replace: true,
|
||||
});
|
||||
} finally {
|
||||
setIsDeleting(false);
|
||||
}
|
||||
};
|
||||
|
||||
if (!connectorId) {
|
||||
|
@ -225,6 +221,7 @@ function ConnectorDetails() {
|
|||
data={data}
|
||||
isInUse={inUse}
|
||||
isOpen={isDeleteAlertOpen}
|
||||
isLoading={isDeleting}
|
||||
onCancel={() => {
|
||||
setIsDeleteAlertOpen(false);
|
||||
}}
|
||||
|
|
|
@ -26,16 +26,19 @@ function ConnectorDeleteButton({ connectorGroup }: Props) {
|
|||
const inUse = isConnectorInUse(firstConnector);
|
||||
|
||||
const [isDeleteAlertOpen, setIsDeleteAlertOpen] = useState(false);
|
||||
const [isDeleting, setIsDeleting] = useState(false);
|
||||
|
||||
const api = useApi();
|
||||
|
||||
const handleDelete = async () => {
|
||||
if (!firstConnector) {
|
||||
if (!firstConnector || isDeleting) {
|
||||
return;
|
||||
}
|
||||
setIsDeleting(true);
|
||||
|
||||
const { connectors } = connectorGroup;
|
||||
|
||||
try {
|
||||
await Promise.all(
|
||||
connectors.map(async (connector) => {
|
||||
await api.delete(`api/connectors/${connector.id}`).json<ConnectorResponse>();
|
||||
|
@ -44,6 +47,9 @@ function ConnectorDeleteButton({ connectorGroup }: Props) {
|
|||
|
||||
toast.success(t('connector_details.connector_deleted'));
|
||||
await mutateGlobal('api/connectors');
|
||||
} finally {
|
||||
setIsDeleting(false);
|
||||
}
|
||||
};
|
||||
|
||||
if (!firstConnector) {
|
||||
|
@ -65,6 +71,7 @@ function ConnectorDeleteButton({ connectorGroup }: Props) {
|
|||
data={firstConnector}
|
||||
isInUse={inUse}
|
||||
isOpen={isDeleteAlertOpen}
|
||||
isLoading={isDeleting}
|
||||
onCancel={() => {
|
||||
setIsDeleteAlertOpen(false);
|
||||
}}
|
||||
|
|
|
@ -20,11 +20,21 @@ function GetStarted() {
|
|||
const { data, isLoading } = useGetStartedMetadata();
|
||||
const { update } = useUserPreferences();
|
||||
const [showConfirmModal, setShowConfirmModal] = useState(false);
|
||||
const [isUpdating, setIsUpdating] = useState(false);
|
||||
|
||||
const hideGetStarted = () => {
|
||||
void update({ getStartedHidden: true });
|
||||
const hideGetStarted = async () => {
|
||||
if (isUpdating) {
|
||||
return;
|
||||
}
|
||||
setIsUpdating(true);
|
||||
|
||||
try {
|
||||
await update({ getStartedHidden: true });
|
||||
// Navigate to next menu item
|
||||
navigate('/dashboard');
|
||||
} finally {
|
||||
setIsUpdating(false);
|
||||
}
|
||||
};
|
||||
|
||||
const showConfirmModalHandler = () => {
|
||||
|
@ -77,6 +87,7 @@ function GetStarted() {
|
|||
isOpen={showConfirmModal}
|
||||
confirmButtonType="primary"
|
||||
confirmButtonText="get_started.hide_this"
|
||||
isLoading={isUpdating}
|
||||
onConfirm={hideGetStarted}
|
||||
onCancel={hideConfirmModalHandler}
|
||||
>
|
||||
|
|
|
@ -65,6 +65,7 @@ function SignInExperience() {
|
|||
const { data, error, mutate } = useSWR<SignInExperienceType, RequestError>('api/sign-in-exp');
|
||||
const isLoadingSignInExperience = !data && !error;
|
||||
const { isLoading: isUserAssetsServiceLoading } = useUserAssetsService();
|
||||
const [isSaving, setIsSaving] = useState(false);
|
||||
|
||||
const {
|
||||
configs,
|
||||
|
@ -93,7 +94,7 @@ function SignInExperience() {
|
|||
handleSubmit,
|
||||
getValues,
|
||||
watch,
|
||||
formState: { isSubmitting, isDirty, errors },
|
||||
formState: { isDirty, errors },
|
||||
} = methods;
|
||||
const api = useApi();
|
||||
const formData = watch();
|
||||
|
@ -115,6 +116,9 @@ function SignInExperience() {
|
|||
}, [reset, defaultFormData]);
|
||||
|
||||
const saveData = async () => {
|
||||
setIsSaving(true);
|
||||
|
||||
try {
|
||||
const updatedData = await api
|
||||
.patch('api/sign-in-exp', {
|
||||
json: signInExperienceParser.toRemoteModel(getValues()),
|
||||
|
@ -124,10 +128,13 @@ function SignInExperience() {
|
|||
setDataToCompare(undefined);
|
||||
await updateConfigs({ signInExperienceCustomized: true });
|
||||
toast.success(t('general.saved'));
|
||||
} finally {
|
||||
setIsSaving(false);
|
||||
}
|
||||
};
|
||||
|
||||
const onSubmit = handleSubmit(async (formData: SignInExperienceForm) => {
|
||||
if (!data || isSubmitting) {
|
||||
if (!data || isSaving) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -217,7 +224,7 @@ function SignInExperience() {
|
|||
</div>
|
||||
<SubmitFormChangesActionBar
|
||||
isOpen={isDirty}
|
||||
isSubmitting={isSubmitting}
|
||||
isSubmitting={isSaving}
|
||||
onDiscard={reset}
|
||||
onSubmit={onSubmit}
|
||||
/>
|
||||
|
@ -226,6 +233,7 @@ function SignInExperience() {
|
|||
{data && (
|
||||
<ConfirmModal
|
||||
isOpen={Boolean(dataToCompare)}
|
||||
isLoading={isSaving}
|
||||
onCancel={() => {
|
||||
setDataToCompare(undefined);
|
||||
}}
|
||||
|
|
|
@ -136,6 +136,7 @@ function UserSocialIdentities({ userId, identities, onDelete }: Props) {
|
|||
)}
|
||||
<DeleteConfirmModal
|
||||
isOpen={deletingConnector !== undefined}
|
||||
isLoading={isSubmitting}
|
||||
onCancel={() => {
|
||||
setDeletingConnector(undefined);
|
||||
}}
|
||||
|
|
Loading…
Add table
Reference in a new issue