diff --git a/packages/console/src/components/CustomUiAssetsUploader/index.tsx b/packages/console/src/components/CustomUiAssetsUploader/index.tsx index 498721dd2b7b..eabb1c9571c4 100644 --- a/packages/console/src/components/CustomUiAssetsUploader/index.tsx +++ b/packages/console/src/components/CustomUiAssetsUploader/index.tsx @@ -1,12 +1,14 @@ import { type CustomUiAssets, maxUploadFileSize, type AllowedUploadMimeType } from '@logto/schemas'; import { type Nullable } from '@silverhand/essentials'; import { format } from 'date-fns/fp'; -import { useCallback, useState } from 'react'; +import { useCallback, useContext, useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import DeleteIcon from '@/assets/icons/delete.svg?react'; +import { SignInExperienceContext } from '@/contexts/SignInExperienceContextProvider'; import IconButton from '@/ds-components/IconButton'; import FileUploader from '@/ds-components/Uploader/FileUploader'; +import useApi from '@/hooks/use-api'; import { formatBytes } from '@/utils/uploader'; import FileIcon from '../FileIcon'; @@ -28,7 +30,19 @@ function CustomUiAssetsUploader({ disabled, value, onChange }: Props) { const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' }); const [file, setFile] = useState(); const [error, setError] = useState(); + const [abortController, setAbortController] = useState(new AbortController()); const showUploader = !value?.id && !file && !error; + const { setIsUploading, setCancelUpload } = useContext(SignInExperienceContext); + + const api = useApi({ timeout: requestTimeout, signal: abortController.signal }); + + useEffect(() => { + setCancelUpload(() => { + abortController.abort(); + setIsUploading(false); + setAbortController(new AbortController()); + }); + }, [abortController, setCancelUpload, setIsUploading]); const onComplete = useCallback( (id: string) => { @@ -53,13 +67,17 @@ function CustomUiAssetsUploader({ disabled, value, onChange }: Props) { if (showUploader) { return ( - defaultApiInstanceTimeout={requestTimeout} + apiInstance={api} disabled={disabled} allowedMimeTypes={allowedMimeTypes} maxSize={maxUploadFileSize} uploadUrl="api/sign-in-exp/default/custom-ui-assets" - onCompleted={({ customUiAssetId }) => { + onUploadStart={() => { + setIsUploading(true); + }} + onUploadComplete={({ customUiAssetId }) => { onComplete(customUiAssetId); + setIsUploading(false); }} onUploadErrorChange={onErrorChange} /> diff --git a/packages/console/src/components/ImageInputs/index.tsx b/packages/console/src/components/ImageInputs/index.tsx index 29a028199650..6dea4890cbae 100644 --- a/packages/console/src/components/ImageInputs/index.tsx +++ b/packages/console/src/components/ImageInputs/index.tsx @@ -137,7 +137,7 @@ function ImageInputs({ actionDescription={t(`sign_in_exp.branding.with_${field.theme}`, { value: t(`sign_in_exp.branding_uploads.${field.type}.title`), })} - onCompleted={({ url }) => { + onUploadComplete={({ url }) => { onChange(url); }} // Noop fallback should not be necessary, but for TypeScript to be happy diff --git a/packages/console/src/components/SubmitFormChangesActionBar/index.tsx b/packages/console/src/components/SubmitFormChangesActionBar/index.tsx index e1eeed147b12..fa0755ea6794 100644 --- a/packages/console/src/components/SubmitFormChangesActionBar/index.tsx +++ b/packages/console/src/components/SubmitFormChangesActionBar/index.tsx @@ -8,6 +8,7 @@ import styles from './index.module.scss'; type Props = { readonly isOpen: boolean; readonly isSubmitting: boolean; + readonly isSubmitDisabled?: boolean; readonly onSubmit: () => Promise; readonly onDiscard: () => void; readonly confirmText?: AdminConsoleKey; @@ -17,6 +18,7 @@ type Props = { function SubmitFormChangesActionBar({ isOpen, isSubmitting, + isSubmitDisabled = false, confirmText = 'general.save_changes', onSubmit, onDiscard, @@ -34,6 +36,7 @@ function SubmitFormChangesActionBar({ }} />