diff --git a/packages/console/src/consts/page-tabs.ts b/packages/console/src/consts/page-tabs.ts index d7b883d37..0b9d90847 100644 --- a/packages/console/src/consts/page-tabs.ts +++ b/packages/console/src/consts/page-tabs.ts @@ -2,6 +2,7 @@ export enum ApplicationDetailsTabs { Settings = 'settings', Roles = 'roles', Logs = 'logs', + Branding = 'branding', } export enum ApiResourceDetailsTabs { diff --git a/packages/console/src/pages/ApplicationDetails/components/Branding/LogoUploader.tsx b/packages/console/src/pages/ApplicationDetails/components/Branding/LogoUploader.tsx new file mode 100644 index 000000000..69f6a1bf8 --- /dev/null +++ b/packages/console/src/pages/ApplicationDetails/components/Branding/LogoUploader.tsx @@ -0,0 +1,79 @@ +import { type ApplicationSignInExperience } from '@logto/schemas'; +import classNames from 'classnames'; +import { useState } from 'react'; +import { Controller, useFormContext } from 'react-hook-form'; +import { useTranslation } from 'react-i18next'; + +import ImageUploader from '@/ds-components/Uploader/ImageUploader'; +import useImageMimeTypes from '@/hooks/use-image-mime-types'; + +import * as styles from './index.module.scss'; + +type Props = { + isDarkModeEnabled?: boolean; +}; + +function LogoUploader({ isDarkModeEnabled }: Props) { + const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' }); + const [uploadLogoError, setUploadLogoError] = useState(); + const [uploadDarkLogoError, setUploadDarkLogoError] = useState(); + const { description } = useImageMimeTypes(); + const { control } = useFormContext(); + + return ( +
+
+ ( + { + onChange(''); + }} + /> + )} + /> + {/* Show the dark mode logto uploader only if dark mode is enabled in the global sign-in-experience */} + {isDarkModeEnabled && ( + ( + { + onChange(''); + }} + /> + )} + /> + )} +
+ {uploadLogoError && ( +
+ {t('sign_in_exp.branding.logo_image_error', { error: uploadLogoError })} +
+ )} + {uploadDarkLogoError && ( +
+ {t('sign_in_exp.branding.logo_image_error', { error: uploadDarkLogoError })} +
+ )} +
{description}
+
+ ); +} + +export default LogoUploader; diff --git a/packages/console/src/pages/ApplicationDetails/components/Branding/index.module.scss b/packages/console/src/pages/ApplicationDetails/components/Branding/index.module.scss new file mode 100644 index 000000000..94c997849 --- /dev/null +++ b/packages/console/src/pages/ApplicationDetails/components/Branding/index.module.scss @@ -0,0 +1,33 @@ +@use '@/scss/underscore' as _; + +.container { + display: flex; + + > * { + flex: 1; + + &:last-child { + border-top-left-radius: 0; + border-bottom-left-radius: 0; + } + + &.darkMode { + background-color: #000; + } + } + + .multiColumn { + border-top-right-radius: 0; + border-bottom-right-radius: 0; + } +} + +.description { + font: var(--font-body-2); + color: var(--color-text-secondary); + margin-top: _.unit(1); +} + +.error { + color: var(--color-error); +} diff --git a/packages/console/src/pages/ApplicationDetails/components/Branding/index.tsx b/packages/console/src/pages/ApplicationDetails/components/Branding/index.tsx new file mode 100644 index 000000000..cf01cd26c --- /dev/null +++ b/packages/console/src/pages/ApplicationDetails/components/Branding/index.tsx @@ -0,0 +1,171 @@ +import { type Application, type ApplicationSignInExperience } from '@logto/schemas'; +import { useCallback, useEffect } from 'react'; +import { useForm, FormProvider } from 'react-hook-form'; +import { toast } from 'react-hot-toast'; +import { useTranslation } from 'react-i18next'; + +import DetailsForm from '@/components/DetailsForm'; +import FormCard, { FormCardSkeleton } from '@/components/FormCard'; +import RequestDataError from '@/components/RequestDataError'; +import FormField from '@/ds-components/FormField'; +import TextInput from '@/ds-components/TextInput'; +import useApi from '@/hooks/use-api'; +import useUserAssetsService from '@/hooks/use-user-assets-service'; +import { trySubmitSafe } from '@/utils/form'; +import { uriValidator } from '@/utils/validator'; + +import LogoUploader from './LogoUploader'; +import useApplicationSignInExperienceSWR from './use-application-sign-in-experience-swr'; +import useSignInExperienceSWR from './use-sign-in-experience-swr'; +import { formatFormToSubmitData, formatResponseDataToForm } from './utils'; + +type Props = { + application: Application; +}; + +function Branding({ application }: Props) { + const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' }); + + const formMethods = useForm({ + defaultValues: { + tenantId: application.tenantId, + applicationId: application.id, + branding: {}, + }, + }); + + const { + handleSubmit, + register, + reset, + formState: { isDirty, isSubmitting, errors }, + } = formMethods; + + const api = useApi(); + + const { data, error, mutate } = useApplicationSignInExperienceSWR(application.id); + const { data: sieData, error: sieError, mutate: sieMutate } = useSignInExperienceSWR(); + const { isReady: isUserAssetsServiceReady, isLoading: isUserAssetsServiceLoading } = + useUserAssetsService(); + + const isApplicationSieLoading = !data && !error; + const isSieLoading = !sieData && !sieError; + const isLoading = isApplicationSieLoading || isSieLoading || isUserAssetsServiceLoading; + + const onSubmit = handleSubmit( + trySubmitSafe(async (data) => { + if (isSubmitting) { + return; + } + + const response = await api + .put(`api/applications/${application.id}/sign-in-experience`, { + json: formatFormToSubmitData(data), + }) + .json(); + + void mutate(response); + toast.success(t('general.saved')); + }) + ); + + const onRetryFetch = useCallback(() => { + void mutate(); + void sieMutate(); + }, [mutate, sieMutate]); + + useEffect(() => { + if (!data) { + return; + } + + reset(formatResponseDataToForm(data)); + }, [data, reset]); + + if (isLoading) { + return ; + } + + // Show error details if the error is not 404 + if (error && error.status !== 404) { + return ; + } + + const isDarkModeEnabled = sieData?.color.isDarkModeEnabled; + + return ( + + + + + + + {isUserAssetsServiceReady && ( + + + + )} + {/* Display the TextInput field if image upload service is not available */} + {!isUserAssetsServiceReady && ( + + + !value || uriValidator(value) || t('errors.invalid_uri_format'), + })} + error={errors.branding?.logoUrl?.message} + /> + + )} + {/* Display the Dark logo field only if the dark mode is enabled in the global sign-in-experience */} + {!isUserAssetsServiceReady && isDarkModeEnabled && ( + + + !value || uriValidator(value) || t('errors.invalid_uri_format'), + })} + error={errors.branding?.darkLogoUrl?.message} + /> + + )} + + + + + !value || uriValidator(value) || t('errors.invalid_uri_format'), + })} + error={errors.termsOfUseUrl?.message} + placeholder="https://" + /> + + + + !value || uriValidator(value) || t('errors.invalid_uri_format'), + })} + error={errors.privacyPolicyUrl?.message} + placeholder="https://" + /> + + + + + ); +} + +export default Branding; diff --git a/packages/console/src/pages/ApplicationDetails/components/Branding/use-application-sign-in-experience-swr.ts b/packages/console/src/pages/ApplicationDetails/components/Branding/use-application-sign-in-experience-swr.ts new file mode 100644 index 000000000..89fc17a82 --- /dev/null +++ b/packages/console/src/pages/ApplicationDetails/components/Branding/use-application-sign-in-experience-swr.ts @@ -0,0 +1,32 @@ +import { type ApplicationSignInExperience } from '@logto/schemas'; +import useSWR from 'swr'; + +import useApi, { RequestError } from '@/hooks/use-api'; +import useSwrFetcher from '@/hooks/use-swr-fetcher'; + +/** + * SWR fetcher for application sign-in experience + * + * hide error toast, because we will handle the error in the component + * allow 404 error, if the sign-in experience is not set + */ +const useApplicationSignInExperienceSWR = (applicationId: string) => { + const fetchApi = useApi({ hideErrorToast: true }); + const fetcher = useSwrFetcher(fetchApi); + + return useSWR( + `api/applications/${applicationId}/sign-in-experience`, + { + fetcher, + shouldRetryOnError: (error: unknown) => { + if (error instanceof RequestError) { + return error.status !== 404; + } + + return true; + }, + } + ); +}; + +export default useApplicationSignInExperienceSWR; diff --git a/packages/console/src/pages/ApplicationDetails/components/Branding/use-sign-in-experience-swr.ts b/packages/console/src/pages/ApplicationDetails/components/Branding/use-sign-in-experience-swr.ts new file mode 100644 index 000000000..9b9389fbf --- /dev/null +++ b/packages/console/src/pages/ApplicationDetails/components/Branding/use-sign-in-experience-swr.ts @@ -0,0 +1,13 @@ +import { type SignInExperience } from '@logto/schemas'; +import useSWR from 'swr'; + +import { type RequestError } from '@/hooks/use-api'; + +/** + * We need SIE isDarkModeEnabled to determine if we should show the dark mode logo forms + */ +const useSignInExperienceSWR = () => { + return useSWR('api/sign-in-exp'); +}; + +export default useSignInExperienceSWR; diff --git a/packages/console/src/pages/ApplicationDetails/components/Branding/utils.ts b/packages/console/src/pages/ApplicationDetails/components/Branding/utils.ts new file mode 100644 index 000000000..ff4607ca4 --- /dev/null +++ b/packages/console/src/pages/ApplicationDetails/components/Branding/utils.ts @@ -0,0 +1,41 @@ +import { type ApplicationSignInExperience } from '@logto/schemas'; +import { conditional } from '@silverhand/essentials'; + +/** + * Format the form data to match the API request body + * - Omit `applicationId` and `tenantId` from the request body + * - Remove the empty `logoUrl` and `darkLogoUrl` fields in the `branding` object + **/ +export const formatFormToSubmitData = ( + data: ApplicationSignInExperience +): Omit => { + const { branding, applicationId, tenantId, ...rest } = data; + + return { + ...rest, + branding: { + ...conditional(branding.logoUrl && { logoUrl: branding.logoUrl }), + ...conditional(branding.darkLogoUrl && { darkLogoUrl: branding.darkLogoUrl }), + }, + }; +}; + +/** + * Format the response data to match the form data + * + * Fulfill the branding object with empty string if the `logoUrl` or `darkLogoUrl` is not set. + * Otherwise, the RHF won't update the branding fields properly with the undefined value. + */ +export const formatResponseDataToForm = ( + data: ApplicationSignInExperience +): ApplicationSignInExperience => { + const { branding, ...rest } = data; + + return { + ...rest, + branding: { + logoUrl: branding.logoUrl ?? '', + darkLogoUrl: branding.darkLogoUrl ?? '', + }, + }; +}; diff --git a/packages/console/src/pages/ApplicationDetails/components/EndpointsAndCredentials.tsx b/packages/console/src/pages/ApplicationDetails/components/EndpointsAndCredentials.tsx index 8d1346fa4..0dbbe7e1a 100644 --- a/packages/console/src/pages/ApplicationDetails/components/EndpointsAndCredentials.tsx +++ b/packages/console/src/pages/ApplicationDetails/components/EndpointsAndCredentials.tsx @@ -11,6 +11,7 @@ import { Trans, useTranslation } from 'react-i18next'; import CaretDown from '@/assets/icons/caret-down.svg'; import CaretUp from '@/assets/icons/caret-up.svg'; import FormCard from '@/components/FormCard'; +import { isDevFeaturesEnabled } from '@/consts/env'; import { openIdProviderConfigPath } from '@/consts/oidc'; import { AppDataContext } from '@/contexts/AppDataProvider'; import Button from '@/ds-components/Button'; @@ -27,7 +28,7 @@ type Props = { oidcConfig: SnakeCaseOidcConfig; }; -function EndpointsAndCredentials({ app: { type, secret, id }, oidcConfig }: Props) { +function EndpointsAndCredentials({ app: { type, secret, id, isThirdParty }, oidcConfig }: Props) { const { tenantEndpoint } = useContext(AppDataContext); const [showMoreEndpoints, setShowMoreEndpoints] = useState(false); @@ -50,7 +51,8 @@ function EndpointsAndCredentials({ app: { type, secret, id }, oidcConfig }: Prop targetBlank: true, }} > - {tenantEndpoint && ( + {/* Hide logto endpoint field in third-party application's form. @simeng-li FIXME: remove isDevFeatureEnabled flag */} + {tenantEndpoint && (!isDevFeaturesEnabled || !isThirdParty) && ( (); - const { type: applicationType } = data; + const { type: applicationType, isThirdParty } = data; const isNativeApp = applicationType === ApplicationType.Native; const uriPatternRules: MultiTextInputRule = { @@ -55,12 +56,16 @@ function Settings({ data }: Props) { placeholder={t('application_details.application_name_placeholder')} /> - - - + {/* Hide description field in third-party application's form. @simeng-li FIXME: remove isDevFeatureEnabled flag */} + {(!isDevFeaturesEnabled || !isThirdParty) && ( + + + + )} + {applicationType !== ApplicationType.MachineToMachine && ( ( id && `api/applications/${id}` ); + const { data: oidcConfig, error: fetchOidcConfigError, mutate: mutateOidcConfig, } = useSWR(openIdProviderConfigPath); + const isLoading = (!data && !error) || (!oidcConfig && !fetchOidcConfigError); const requestError = error ?? fetchOidcConfigError; const [isReadmeOpen, setIsReadmeOpen] = useState(false); @@ -227,6 +231,11 @@ function ApplicationDetails() { )} + {isDevFeaturesEnabled && data.isThirdParty && ( + + {t('application_details.branding.branding')} + + )} )} + + {isDevFeaturesEnabled && data.isThirdParty && ( + + + + )} )} diff --git a/packages/console/src/pages/Applications/hooks/use-application-data.ts b/packages/console/src/pages/Applications/hooks/use-application-data.ts index f11bf30cb..e1d333e02 100644 --- a/packages/console/src/pages/Applications/hooks/use-application-data.ts +++ b/packages/console/src/pages/Applications/hooks/use-application-data.ts @@ -88,7 +88,7 @@ const useApplicationsData = (isThirdParty = false) => { const { data } = thirdPartyApplicationsData; const [_, totalCount] = data ?? []; - const hasThirdPartyApplications = totalCount && totalCount > 0; + const hasThirdPartyApplications = Boolean(totalCount && totalCount > 0); return { ...(isThirdParty ? thirdPartyApplicationsData : firstPartyApplicationsData), diff --git a/packages/phrases/src/locales/de/translation/admin-console/application-details.ts b/packages/phrases/src/locales/de/translation/admin-console/application-details.ts index dc9c279cd..37e4c0991 100644 --- a/packages/phrases/src/locales/de/translation/admin-console/application-details.ts +++ b/packages/phrases/src/locales/de/translation/admin-console/application-details.ts @@ -67,6 +67,27 @@ const application_details = { enter_your_application_name: 'Gib einen Anwendungsnamen ein', application_deleted: 'Anwendung {{name}} wurde erfolgreich gelöscht', redirect_uri_required: 'Gib mindestens eine Umleitungs-URI an', + branding: { + /** UNTRANSLATED */ + branding: 'Branding', + /** UNTRANSLATED */ + branding_description: + "Customize your application's display name and logo on the consent screen.", + /** UNTRANSLATED */ + more_info: 'More info', + /** UNTRANSLATED */ + more_info_description: 'Offer users more details about your application on the consent screen.', + /** UNTRANSLATED */ + display_name: 'Display name', + /** UNTRANSLATED */ + display_logo: 'Display logo', + /** UNTRANSLATED */ + display_logo_dark: 'Display logo (dark)', + /** UNTRANSLATED */ + terms_of_use_url: 'Application terms of use URL', + /** UNTRANSLATED */ + privacy_policy_url: 'Application privacy policy URL', + }, roles: { name_column: 'Rolle', description_column: 'Beschreibung', diff --git a/packages/phrases/src/locales/en/translation/admin-console/application-details.ts b/packages/phrases/src/locales/en/translation/admin-console/application-details.ts index c2cfa05a7..971aa88b9 100644 --- a/packages/phrases/src/locales/en/translation/admin-console/application-details.ts +++ b/packages/phrases/src/locales/en/translation/admin-console/application-details.ts @@ -61,6 +61,18 @@ const application_details = { enter_your_application_name: 'Enter your application name', application_deleted: 'Application {{name}} has been successfully deleted', redirect_uri_required: 'You must enter at least one redirect URI', + branding: { + branding: 'Branding', + branding_description: + "Customize your application's display name and logo on the consent screen.", + more_info: 'More info', + more_info_description: 'Offer users more details about your application on the consent screen.', + display_name: 'Display name', + display_logo: 'Display logo', + display_logo_dark: 'Display logo (dark)', + terms_of_use_url: 'Application terms of use URL', + privacy_policy_url: 'Application privacy policy URL', + }, roles: { name_column: 'Role', description_column: 'Description', diff --git a/packages/phrases/src/locales/es/translation/admin-console/application-details.ts b/packages/phrases/src/locales/es/translation/admin-console/application-details.ts index a83ccb0a6..4a8bd457a 100644 --- a/packages/phrases/src/locales/es/translation/admin-console/application-details.ts +++ b/packages/phrases/src/locales/es/translation/admin-console/application-details.ts @@ -67,6 +67,27 @@ const application_details = { enter_your_application_name: 'Ingresa el nombre de tu aplicación', application_deleted: 'Se ha eliminado exitosamente la aplicación {{name}}', redirect_uri_required: 'Debes ingresar al menos un URI de Redireccionamiento', + branding: { + /** UNTRANSLATED */ + branding: 'Branding', + /** UNTRANSLATED */ + branding_description: + "Customize your application's display name and logo on the consent screen.", + /** UNTRANSLATED */ + more_info: 'More info', + /** UNTRANSLATED */ + more_info_description: 'Offer users more details about your application on the consent screen.', + /** UNTRANSLATED */ + display_name: 'Display name', + /** UNTRANSLATED */ + display_logo: 'Display logo', + /** UNTRANSLATED */ + display_logo_dark: 'Display logo (dark)', + /** UNTRANSLATED */ + terms_of_use_url: 'Application terms of use URL', + /** UNTRANSLATED */ + privacy_policy_url: 'Application privacy policy URL', + }, roles: { name_column: 'Rol', description_column: 'Descripción', diff --git a/packages/phrases/src/locales/fr/translation/admin-console/application-details.ts b/packages/phrases/src/locales/fr/translation/admin-console/application-details.ts index ed7a28287..753a8fe77 100644 --- a/packages/phrases/src/locales/fr/translation/admin-console/application-details.ts +++ b/packages/phrases/src/locales/fr/translation/admin-console/application-details.ts @@ -67,6 +67,27 @@ const application_details = { enter_your_application_name: 'Entrez le nom de votre application', application_deleted: "L'application {{name}} a été supprimée avec succès.", redirect_uri_required: 'Vous devez entrer au moins un URI de redirection.', + branding: { + /** UNTRANSLATED */ + branding: 'Branding', + /** UNTRANSLATED */ + branding_description: + "Customize your application's display name and logo on the consent screen.", + /** UNTRANSLATED */ + more_info: 'More info', + /** UNTRANSLATED */ + more_info_description: 'Offer users more details about your application on the consent screen.', + /** UNTRANSLATED */ + display_name: 'Display name', + /** UNTRANSLATED */ + display_logo: 'Display logo', + /** UNTRANSLATED */ + display_logo_dark: 'Display logo (dark)', + /** UNTRANSLATED */ + terms_of_use_url: 'Application terms of use URL', + /** UNTRANSLATED */ + privacy_policy_url: 'Application privacy policy URL', + }, roles: { name_column: 'Rôle', description_column: 'Description', diff --git a/packages/phrases/src/locales/it/translation/admin-console/application-details.ts b/packages/phrases/src/locales/it/translation/admin-console/application-details.ts index c6af8721d..6d609fedd 100644 --- a/packages/phrases/src/locales/it/translation/admin-console/application-details.ts +++ b/packages/phrases/src/locales/it/translation/admin-console/application-details.ts @@ -67,6 +67,27 @@ const application_details = { enter_your_application_name: 'Inserisci il nome della tua applicazione', application_deleted: "L'applicazione {{name}} è stata eliminata con successo", redirect_uri_required: 'Devi inserire almeno un URI di reindirizzamento', + branding: { + /** UNTRANSLATED */ + branding: 'Branding', + /** UNTRANSLATED */ + branding_description: + "Customize your application's display name and logo on the consent screen.", + /** UNTRANSLATED */ + more_info: 'More info', + /** UNTRANSLATED */ + more_info_description: 'Offer users more details about your application on the consent screen.', + /** UNTRANSLATED */ + display_name: 'Display name', + /** UNTRANSLATED */ + display_logo: 'Display logo', + /** UNTRANSLATED */ + display_logo_dark: 'Display logo (dark)', + /** UNTRANSLATED */ + terms_of_use_url: 'Application terms of use URL', + /** UNTRANSLATED */ + privacy_policy_url: 'Application privacy policy URL', + }, roles: { name_column: 'Ruolo', description_column: 'Descrizione', diff --git a/packages/phrases/src/locales/ja/translation/admin-console/application-details.ts b/packages/phrases/src/locales/ja/translation/admin-console/application-details.ts index f80c7dcd5..1666a3bb8 100644 --- a/packages/phrases/src/locales/ja/translation/admin-console/application-details.ts +++ b/packages/phrases/src/locales/ja/translation/admin-console/application-details.ts @@ -67,6 +67,27 @@ const application_details = { enter_your_application_name: 'アプリケーション名を入力してください', application_deleted: 'アプリケーション{{name}}が正常に削除されました', redirect_uri_required: 'リダイレクトURIを少なくとも1つ入力する必要があります', + branding: { + /** UNTRANSLATED */ + branding: 'Branding', + /** UNTRANSLATED */ + branding_description: + "Customize your application's display name and logo on the consent screen.", + /** UNTRANSLATED */ + more_info: 'More info', + /** UNTRANSLATED */ + more_info_description: 'Offer users more details about your application on the consent screen.', + /** UNTRANSLATED */ + display_name: 'Display name', + /** UNTRANSLATED */ + display_logo: 'Display logo', + /** UNTRANSLATED */ + display_logo_dark: 'Display logo (dark)', + /** UNTRANSLATED */ + terms_of_use_url: 'Application terms of use URL', + /** UNTRANSLATED */ + privacy_policy_url: 'Application privacy policy URL', + }, roles: { name_column: '役割', description_column: '説明', diff --git a/packages/phrases/src/locales/ko/translation/admin-console/application-details.ts b/packages/phrases/src/locales/ko/translation/admin-console/application-details.ts index a15e2caf9..f66b2423b 100644 --- a/packages/phrases/src/locales/ko/translation/admin-console/application-details.ts +++ b/packages/phrases/src/locales/ko/translation/admin-console/application-details.ts @@ -67,6 +67,27 @@ const application_details = { enter_your_application_name: '어플리케이션 이름을 입력해 주세요.', application_deleted: '{{name}} 어플리케이션이 성공적으로 삭제되었어요.', redirect_uri_required: '반드시 최소 하나의 Redirect URI 를 입력해야 해요.', + branding: { + /** UNTRANSLATED */ + branding: 'Branding', + /** UNTRANSLATED */ + branding_description: + "Customize your application's display name and logo on the consent screen.", + /** UNTRANSLATED */ + more_info: 'More info', + /** UNTRANSLATED */ + more_info_description: 'Offer users more details about your application on the consent screen.', + /** UNTRANSLATED */ + display_name: 'Display name', + /** UNTRANSLATED */ + display_logo: 'Display logo', + /** UNTRANSLATED */ + display_logo_dark: 'Display logo (dark)', + /** UNTRANSLATED */ + terms_of_use_url: 'Application terms of use URL', + /** UNTRANSLATED */ + privacy_policy_url: 'Application privacy policy URL', + }, roles: { name_column: '역할', description_column: '설명', diff --git a/packages/phrases/src/locales/pl-pl/translation/admin-console/application-details.ts b/packages/phrases/src/locales/pl-pl/translation/admin-console/application-details.ts index a9d3a5e30..4586486cb 100644 --- a/packages/phrases/src/locales/pl-pl/translation/admin-console/application-details.ts +++ b/packages/phrases/src/locales/pl-pl/translation/admin-console/application-details.ts @@ -67,6 +67,27 @@ const application_details = { enter_your_application_name: 'Wpisz nazwę swojej aplikacji', application_deleted: 'Aplikacja {{name}} została pomyślnie usunięta', redirect_uri_required: 'Musisz wpisać co najmniej jeden adres URL przekierowania', + branding: { + /** UNTRANSLATED */ + branding: 'Branding', + /** UNTRANSLATED */ + branding_description: + "Customize your application's display name and logo on the consent screen.", + /** UNTRANSLATED */ + more_info: 'More info', + /** UNTRANSLATED */ + more_info_description: 'Offer users more details about your application on the consent screen.', + /** UNTRANSLATED */ + display_name: 'Display name', + /** UNTRANSLATED */ + display_logo: 'Display logo', + /** UNTRANSLATED */ + display_logo_dark: 'Display logo (dark)', + /** UNTRANSLATED */ + terms_of_use_url: 'Application terms of use URL', + /** UNTRANSLATED */ + privacy_policy_url: 'Application privacy policy URL', + }, roles: { name_column: 'Role', description_column: 'Opis', diff --git a/packages/phrases/src/locales/pt-br/translation/admin-console/application-details.ts b/packages/phrases/src/locales/pt-br/translation/admin-console/application-details.ts index b20302269..35df17048 100644 --- a/packages/phrases/src/locales/pt-br/translation/admin-console/application-details.ts +++ b/packages/phrases/src/locales/pt-br/translation/admin-console/application-details.ts @@ -67,6 +67,27 @@ const application_details = { enter_your_application_name: 'Digite o nome do seu aplicativo', application_deleted: 'O aplicativo {{name}} foi excluído com sucesso', redirect_uri_required: 'Você deve inserir pelo menos um URI de redirecionamento', + branding: { + /** UNTRANSLATED */ + branding: 'Branding', + /** UNTRANSLATED */ + branding_description: + "Customize your application's display name and logo on the consent screen.", + /** UNTRANSLATED */ + more_info: 'More info', + /** UNTRANSLATED */ + more_info_description: 'Offer users more details about your application on the consent screen.', + /** UNTRANSLATED */ + display_name: 'Display name', + /** UNTRANSLATED */ + display_logo: 'Display logo', + /** UNTRANSLATED */ + display_logo_dark: 'Display logo (dark)', + /** UNTRANSLATED */ + terms_of_use_url: 'Application terms of use URL', + /** UNTRANSLATED */ + privacy_policy_url: 'Application privacy policy URL', + }, roles: { name_column: 'Função', description_column: 'Descrição', diff --git a/packages/phrases/src/locales/pt-pt/translation/admin-console/application-details.ts b/packages/phrases/src/locales/pt-pt/translation/admin-console/application-details.ts index 0b7ad5353..11f1e73c1 100644 --- a/packages/phrases/src/locales/pt-pt/translation/admin-console/application-details.ts +++ b/packages/phrases/src/locales/pt-pt/translation/admin-console/application-details.ts @@ -67,6 +67,27 @@ const application_details = { enter_your_application_name: 'Insira o nome da aplicação', application_deleted: 'Aplicação {{name}} eliminada com sucesso', redirect_uri_required: 'Deve inserir pelo menos um URI de redirecionamento', + branding: { + /** UNTRANSLATED */ + branding: 'Branding', + /** UNTRANSLATED */ + branding_description: + "Customize your application's display name and logo on the consent screen.", + /** UNTRANSLATED */ + more_info: 'More info', + /** UNTRANSLATED */ + more_info_description: 'Offer users more details about your application on the consent screen.', + /** UNTRANSLATED */ + display_name: 'Display name', + /** UNTRANSLATED */ + display_logo: 'Display logo', + /** UNTRANSLATED */ + display_logo_dark: 'Display logo (dark)', + /** UNTRANSLATED */ + terms_of_use_url: 'Application terms of use URL', + /** UNTRANSLATED */ + privacy_policy_url: 'Application privacy policy URL', + }, roles: { name_column: 'Nome da função', description_column: 'Descrição', diff --git a/packages/phrases/src/locales/ru/translation/admin-console/application-details.ts b/packages/phrases/src/locales/ru/translation/admin-console/application-details.ts index 9f8dcabbd..2088ce3ea 100644 --- a/packages/phrases/src/locales/ru/translation/admin-console/application-details.ts +++ b/packages/phrases/src/locales/ru/translation/admin-console/application-details.ts @@ -67,6 +67,27 @@ const application_details = { enter_your_application_name: 'Введите название своего приложения', application_deleted: 'Приложение {{name}} успешно удалено', redirect_uri_required: 'Вы должны ввести по крайней мере один URI перенаправления', + branding: { + /** UNTRANSLATED */ + branding: 'Branding', + /** UNTRANSLATED */ + branding_description: + "Customize your application's display name and logo on the consent screen.", + /** UNTRANSLATED */ + more_info: 'More info', + /** UNTRANSLATED */ + more_info_description: 'Offer users more details about your application on the consent screen.', + /** UNTRANSLATED */ + display_name: 'Display name', + /** UNTRANSLATED */ + display_logo: 'Display logo', + /** UNTRANSLATED */ + display_logo_dark: 'Display logo (dark)', + /** UNTRANSLATED */ + terms_of_use_url: 'Application terms of use URL', + /** UNTRANSLATED */ + privacy_policy_url: 'Application privacy policy URL', + }, roles: { name_column: 'Роль', description_column: 'Описание', diff --git a/packages/phrases/src/locales/tr-tr/translation/admin-console/application-details.ts b/packages/phrases/src/locales/tr-tr/translation/admin-console/application-details.ts index a2c8ae76e..52398f695 100644 --- a/packages/phrases/src/locales/tr-tr/translation/admin-console/application-details.ts +++ b/packages/phrases/src/locales/tr-tr/translation/admin-console/application-details.ts @@ -67,6 +67,27 @@ const application_details = { enter_your_application_name: 'Uygulama adı giriniz', application_deleted: '{{name}} Uygulaması başarıyla silindi', redirect_uri_required: 'En az 1 yönlendirme URIı girmelisiniz', + branding: { + /** UNTRANSLATED */ + branding: 'Branding', + /** UNTRANSLATED */ + branding_description: + "Customize your application's display name and logo on the consent screen.", + /** UNTRANSLATED */ + more_info: 'More info', + /** UNTRANSLATED */ + more_info_description: 'Offer users more details about your application on the consent screen.', + /** UNTRANSLATED */ + display_name: 'Display name', + /** UNTRANSLATED */ + display_logo: 'Display logo', + /** UNTRANSLATED */ + display_logo_dark: 'Display logo (dark)', + /** UNTRANSLATED */ + terms_of_use_url: 'Application terms of use URL', + /** UNTRANSLATED */ + privacy_policy_url: 'Application privacy policy URL', + }, roles: { name_column: 'Rol', description_column: 'Açıklama', diff --git a/packages/phrases/src/locales/zh-cn/translation/admin-console/application-details.ts b/packages/phrases/src/locales/zh-cn/translation/admin-console/application-details.ts index fb5f96bfb..d9018ac8f 100644 --- a/packages/phrases/src/locales/zh-cn/translation/admin-console/application-details.ts +++ b/packages/phrases/src/locales/zh-cn/translation/admin-console/application-details.ts @@ -64,6 +64,27 @@ const application_details = { enter_your_application_name: '输入你的应用名称', application_deleted: '应用 {{name}} 成功删除。', redirect_uri_required: '至少需要输入一个重定向 URI。', + branding: { + /** UNTRANSLATED */ + branding: 'Branding', + /** UNTRANSLATED */ + branding_description: + "Customize your application's display name and logo on the consent screen.", + /** UNTRANSLATED */ + more_info: 'More info', + /** UNTRANSLATED */ + more_info_description: 'Offer users more details about your application on the consent screen.', + /** UNTRANSLATED */ + display_name: 'Display name', + /** UNTRANSLATED */ + display_logo: 'Display logo', + /** UNTRANSLATED */ + display_logo_dark: 'Display logo (dark)', + /** UNTRANSLATED */ + terms_of_use_url: 'Application terms of use URL', + /** UNTRANSLATED */ + privacy_policy_url: 'Application privacy policy URL', + }, roles: { name_column: '角色', description_column: '描述', diff --git a/packages/phrases/src/locales/zh-hk/translation/admin-console/application-details.ts b/packages/phrases/src/locales/zh-hk/translation/admin-console/application-details.ts index dd46d20af..860988461 100644 --- a/packages/phrases/src/locales/zh-hk/translation/admin-console/application-details.ts +++ b/packages/phrases/src/locales/zh-hk/translation/admin-console/application-details.ts @@ -64,6 +64,27 @@ const application_details = { enter_your_application_name: '輸入你的應用程式名稱', application_deleted: '應用 {{name}} 成功刪除。', redirect_uri_required: '至少需要輸入一個重定向 URL。', + branding: { + /** UNTRANSLATED */ + branding: 'Branding', + /** UNTRANSLATED */ + branding_description: + "Customize your application's display name and logo on the consent screen.", + /** UNTRANSLATED */ + more_info: 'More info', + /** UNTRANSLATED */ + more_info_description: 'Offer users more details about your application on the consent screen.', + /** UNTRANSLATED */ + display_name: 'Display name', + /** UNTRANSLATED */ + display_logo: 'Display logo', + /** UNTRANSLATED */ + display_logo_dark: 'Display logo (dark)', + /** UNTRANSLATED */ + terms_of_use_url: 'Application terms of use URL', + /** UNTRANSLATED */ + privacy_policy_url: 'Application privacy policy URL', + }, roles: { name_column: '角色', description_column: '描述', diff --git a/packages/phrases/src/locales/zh-tw/translation/admin-console/application-details.ts b/packages/phrases/src/locales/zh-tw/translation/admin-console/application-details.ts index 7d5980833..915b6ce4a 100644 --- a/packages/phrases/src/locales/zh-tw/translation/admin-console/application-details.ts +++ b/packages/phrases/src/locales/zh-tw/translation/admin-console/application-details.ts @@ -65,6 +65,27 @@ const application_details = { enter_your_application_name: '輸入你的應用程式姓名', application_deleted: '應用 {{name}} 成功刪除。', redirect_uri_required: '至少需要輸入一個重定向 URL。', + branding: { + /** UNTRANSLATED */ + branding: 'Branding', + /** UNTRANSLATED */ + branding_description: + "Customize your application's display name and logo on the consent screen.", + /** UNTRANSLATED */ + more_info: 'More info', + /** UNTRANSLATED */ + more_info_description: 'Offer users more details about your application on the consent screen.', + /** UNTRANSLATED */ + display_name: 'Display name', + /** UNTRANSLATED */ + display_logo: 'Display logo', + /** UNTRANSLATED */ + display_logo_dark: 'Display logo (dark)', + /** UNTRANSLATED */ + terms_of_use_url: 'Application terms of use URL', + /** UNTRANSLATED */ + privacy_policy_url: 'Application privacy policy URL', + }, roles: { name_column: '角色', description_column: '描述',