0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-04-07 23:01:25 -05:00

fix(console): add UnsavedChangesAlert (#5277)

fix(console): add unsafe alert modal on the application branding page

add unsafe alert modal on the application branding page
This commit is contained in:
simeng-li 2024-01-25 12:38:22 +08:00 committed by GitHub
parent 3026413c23
commit 94344e1423
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 70 additions and 62 deletions

View file

@ -7,6 +7,7 @@ import { useTranslation } from 'react-i18next';
import DetailsForm from '@/components/DetailsForm';
import FormCard, { FormCardSkeleton } from '@/components/FormCard';
import RequestDataError from '@/components/RequestDataError';
import UnsavedChangesAlertModal from '@/components/UnsavedChangesAlertModal';
import FormField from '@/ds-components/FormField';
import TextInput from '@/ds-components/TextInput';
import useApi from '@/hooks/use-api';
@ -21,9 +22,10 @@ import { formatFormToSubmitData, formatResponseDataToForm } from './utils';
type Props = {
application: Application;
isActive: boolean; // Support for conditional render UnsavedChangesAlertModal component
};
function Branding({ application }: Props) {
function Branding({ application, isActive }: Props) {
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
const formMethods = useForm<ApplicationSignInExperience>({
@ -94,79 +96,82 @@ function Branding({ application }: Props) {
const isDarkModeEnabled = sieData?.color.isDarkModeEnabled;
return (
<FormProvider {...formMethods}>
<DetailsForm
isDirty={isDirty}
isSubmitting={isSubmitting}
onDiscard={reset}
onSubmit={onSubmit}
>
<FormCard
title="application_details.branding.name"
description="application_details.branding.description"
<>
<FormProvider {...formMethods}>
<DetailsForm
isDirty={isDirty}
isSubmitting={isSubmitting}
onDiscard={reset}
onSubmit={onSubmit}
>
<FormField title="application_details.branding.display_name">
<TextInput {...register('displayName')} placeholder={application.name} />
</FormField>
{isUserAssetsServiceReady && (
<FormField title="application_details.branding.display_logo">
<LogoUploader isDarkModeEnabled={isDarkModeEnabled} />
<FormCard
title="application_details.branding.name"
description="application_details.branding.description"
>
<FormField title="application_details.branding.display_name">
<TextInput {...register('displayName')} placeholder={application.name} />
</FormField>
)}
{/* Display the TextInput field if image upload service is not available */}
{!isUserAssetsServiceReady && (
<FormField title="application_details.branding.display_logo">
{isUserAssetsServiceReady && (
<FormField title="application_details.branding.display_logo">
<LogoUploader isDarkModeEnabled={isDarkModeEnabled} />
</FormField>
)}
{/* Display the TextInput field if image upload service is not available */}
{!isUserAssetsServiceReady && (
<FormField title="application_details.branding.display_logo">
<TextInput
{...register('branding.logoUrl', {
validate: (value) =>
!value || uriValidator(value) || t('errors.invalid_uri_format'),
})}
placeholder={t('sign_in_exp.branding.logo_image_url_placeholder')}
error={errors.branding?.logoUrl?.message}
/>
</FormField>
)}
{/* Display the Dark logo field only if the dark mode is enabled in the global sign-in-experience */}
{!isUserAssetsServiceReady && isDarkModeEnabled && (
<FormField title="application_details.branding.display_logo_dark">
<TextInput
{...register('branding.darkLogoUrl', {
validate: (value) =>
!value || uriValidator(value) || t('errors.invalid_uri_format'),
})}
placeholder={t('sign_in_exp.branding.dark_logo_image_url_placeholder')}
error={errors.branding?.darkLogoUrl?.message}
/>
</FormField>
)}
</FormCard>
<FormCard
title="application_details.branding.more_info"
description="application_details.branding.more_info_description"
>
<FormField title="application_details.branding.terms_of_use_url">
<TextInput
{...register('branding.logoUrl', {
{...register('termsOfUseUrl', {
validate: (value) =>
!value || uriValidator(value) || t('errors.invalid_uri_format'),
})}
placeholder={t('sign_in_exp.branding.logo_image_url_placeholder')}
error={errors.branding?.logoUrl?.message}
error={errors.termsOfUseUrl?.message}
placeholder="https://"
/>
</FormField>
)}
{/* Display the Dark logo field only if the dark mode is enabled in the global sign-in-experience */}
{!isUserAssetsServiceReady && isDarkModeEnabled && (
<FormField title="application_details.branding.display_logo_dark">
<FormField title="application_details.branding.privacy_policy_url">
<TextInput
{...register('branding.darkLogoUrl', {
{...register('privacyPolicyUrl', {
validate: (value) =>
!value || uriValidator(value) || t('errors.invalid_uri_format'),
})}
placeholder={t('sign_in_exp.branding.dark_logo_image_url_placeholder')}
error={errors.branding?.darkLogoUrl?.message}
error={errors.privacyPolicyUrl?.message}
placeholder="https://"
/>
</FormField>
)}
</FormCard>
<FormCard
title="application_details.branding.more_info"
description="application_details.branding.more_info_description"
>
<FormField title="application_details.branding.terms_of_use_url">
<TextInput
{...register('termsOfUseUrl', {
validate: (value) =>
!value || uriValidator(value) || t('errors.invalid_uri_format'),
})}
error={errors.termsOfUseUrl?.message}
placeholder="https://"
/>
</FormField>
<FormField title="application_details.branding.privacy_policy_url">
<TextInput
{...register('privacyPolicyUrl', {
validate: (value) =>
!value || uriValidator(value) || t('errors.invalid_uri_format'),
})}
error={errors.privacyPolicyUrl?.message}
placeholder="https://"
/>
</FormField>
</FormCard>
</DetailsForm>
</FormProvider>
</FormCard>
</DetailsForm>
</FormProvider>
{isActive && <UnsavedChangesAlertModal hasUnsavedChanges={isDirty} onConfirm={reset} />}
</>
);
}

View file

@ -200,6 +200,9 @@ function ApplicationDetailsContent({ data, oidcConfig, onApplicationUpdated }: P
)}
</DetailsForm>
</FormProvider>
{tab === ApplicationDetailsTabs.Settings && (
<UnsavedChangesAlertModal hasUnsavedChanges={!isDeleted && isDirty} onConfirm={reset} />
)}
</TabWrapper>
{data.type === ApplicationType.MachineToMachine && (
@ -230,11 +233,11 @@ function ApplicationDetailsContent({ data, oidcConfig, onApplicationUpdated }: P
isActive={tab === ApplicationDetailsTabs.Branding}
className={styles.tabContainer}
>
<Branding application={data} />
{/* isActive is needed to support conditional render UnsavedChangesAlertModal */}
<Branding application={data} isActive={tab === ApplicationDetailsTabs.Branding} />
</TabWrapper>
</>
)}
<UnsavedChangesAlertModal hasUnsavedChanges={!isDeleted && isDirty} onConfirm={reset} />
</>
);
}