diff --git a/packages/connectors/connector-logto-email/package.json b/packages/connectors/connector-logto-email/package.json index 37cc54450..a8d12fdf7 100644 --- a/packages/connectors/connector-logto-email/package.json +++ b/packages/connectors/connector-logto-email/package.json @@ -52,7 +52,7 @@ "access": "public" }, "devDependencies": { - "@logto/cloud": "0.2.5-582d792", + "@logto/cloud": "0.2.5-1661979", "@silverhand/eslint-config": "6.0.1", "@silverhand/ts-config": "6.0.0", "@types/node": "^20.11.20", diff --git a/packages/console/package.json b/packages/console/package.json index 9116a9314..c8c4abe2a 100644 --- a/packages/console/package.json +++ b/packages/console/package.json @@ -27,7 +27,7 @@ "devDependencies": { "@fontsource/roboto-mono": "^5.0.0", "@jest/types": "^29.5.0", - "@logto/cloud": "0.2.5-91ab76c", + "@logto/cloud": "0.2.5-1661979", "@logto/connector-kit": "workspace:^4.0.0", "@logto/core-kit": "workspace:^2.5.0", "@logto/elements": "workspace:^0.0.1", diff --git a/packages/console/src/components/CreateTenantModal/index.tsx b/packages/console/src/components/CreateTenantModal/index.tsx index 3dc2fd678..2f40cb0cd 100644 --- a/packages/console/src/components/CreateTenantModal/index.tsx +++ b/packages/console/src/components/CreateTenantModal/index.tsx @@ -10,6 +10,7 @@ import CreateTenantHeaderIcon from '@/assets/icons/create-tenant-header.svg?reac import { useCloudApi } from '@/cloud/hooks/use-cloud-api'; import { type TenantResponse } from '@/cloud/types/router'; import Region, { RegionName } from '@/components/Region'; +import { isDevFeaturesEnabled } from '@/consts/env'; import Button from '@/ds-components/Button'; import DangerousRaw from '@/ds-components/DangerousRaw'; import FormField from '@/ds-components/FormField'; @@ -18,6 +19,7 @@ import RadioGroup, { Radio } from '@/ds-components/RadioGroup'; import TextInput from '@/ds-components/TextInput'; import useTheme from '@/hooks/use-theme'; import modalStyles from '@/scss/modal.module.scss'; +import { trySubmitSafe } from '@/utils/form'; import EnvTagOptionContent from './EnvTagOptionContent'; import SelectTenantPlanModal from './SelectTenantPlanModal'; @@ -56,16 +58,18 @@ function CreateTenantModal({ isOpen, onClose }: Props) { }; const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' }); - const onCreateClick = handleSubmit(async (data: CreateTenantData) => { - const { tag } = data; - if (tag === TenantTag.Development) { - await createTenant(data); - toast.success(t('tenants.create_modal.tenant_created')); - return; - } + const onCreateClick = handleSubmit( + trySubmitSafe(async (data: CreateTenantData) => { + const { tag } = data; + if (tag === TenantTag.Development) { + await createTenant(data); + toast.success(t('tenants.create_modal.tenant_created')); + return; + } - setTenantData(data); - }); + setTenantData(data); + }) + ); return ( ( {/* Manually maintaining the list of regions to avoid unexpected changes. We may consider using an API in the future. */} - {[RegionName.EU, RegionName.US].map((region) => ( - - - - } - value={region} - isDisabled={isSubmitting} - /> - ))} + {[RegionName.EU, RegionName.US, RegionName.AU].map( + (region) => + (isDevFeaturesEnabled || region !== RegionName.AU) && ( + + + + } + value={region} + isDisabled={isSubmitting} + /> + ) + )} )} /> diff --git a/packages/console/src/components/Region/assets/au.svg b/packages/console/src/components/Region/assets/au.svg new file mode 100644 index 000000000..a237b779f --- /dev/null +++ b/packages/console/src/components/Region/assets/au.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + diff --git a/packages/console/src/components/Region/assets/eu.svg b/packages/console/src/components/Region/assets/eu.svg new file mode 100644 index 000000000..e030582cb --- /dev/null +++ b/packages/console/src/components/Region/assets/eu.svg @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/console/src/components/Region/assets/us.svg b/packages/console/src/components/Region/assets/us.svg new file mode 100644 index 000000000..d59265a34 --- /dev/null +++ b/packages/console/src/components/Region/assets/us.svg @@ -0,0 +1,161 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/console/src/components/Region/index.module.scss b/packages/console/src/components/Region/index.module.scss index 73727b5e2..8b4b82ab6 100644 --- a/packages/console/src/components/Region/index.module.scss +++ b/packages/console/src/components/Region/index.module.scss @@ -1,6 +1,10 @@ @use '@/scss/underscore' as _; -.regionText { +.wrapper { + display: flex; + align-items: center; + justify-content: center; + gap: _.unit(2); font: var(--font-label-2); .comingSoon { diff --git a/packages/console/src/components/Region/index.tsx b/packages/console/src/components/Region/index.tsx index ff4164aa8..50f2dd8cb 100644 --- a/packages/console/src/components/Region/index.tsx +++ b/packages/console/src/components/Region/index.tsx @@ -1,19 +1,31 @@ import classNames from 'classnames'; +import { type ComponentType } from 'react'; import { useTranslation } from 'react-i18next'; +import auFlag from './assets/au.svg?react'; +import euFlag from './assets/eu.svg?react'; +import usFlag from './assets/us.svg?react'; import styles from './index.module.scss'; // TODO: This is a copy from `@logto/cloud-models`, make a SSoT for this later export enum RegionName { EU = 'EU', US = 'US', + AU = 'AU', } -const regionFlagMap = Object.freeze({ - [RegionName.EU]: 'πŸ‡ͺπŸ‡Ί', - [RegionName.US]: 'πŸ‡ΊπŸ‡Έ', +const regionDisplayNameMap = Object.freeze({ + [RegionName.EU]: 'Europe', + [RegionName.US]: 'West US', + [RegionName.AU]: 'Australia', } satisfies Record); +const regionFlagMap = Object.freeze({ + [RegionName.EU]: euFlag, + [RegionName.US]: usFlag, + [RegionName.AU]: auFlag, +} satisfies Record); + type Props = { readonly regionName: RegionName; readonly isComingSoon?: boolean; @@ -22,10 +34,12 @@ type Props = { function Region({ isComingSoon = false, regionName, className }: Props) { const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' }); + const Flag = regionFlagMap[regionName]; return ( - - {regionFlagMap[regionName]} {regionName} + + + {regionDisplayNameMap[regionName]} {isComingSoon && {`(${t('general.coming_soon')})`}} ); diff --git a/packages/console/src/utils/form.ts b/packages/console/src/utils/form.ts index 7fc1f624f..288f28142 100644 --- a/packages/console/src/utils/form.ts +++ b/packages/console/src/utils/form.ts @@ -1,3 +1,4 @@ +import { ResponseError } from '@withtyped/client'; import { HTTPError, TimeoutError } from 'ky'; import { type FieldValues, type SubmitHandler } from 'react-hook-form'; import { toast } from 'react-hot-toast'; @@ -16,7 +17,10 @@ export const trySubmitSafe = try { await handler(formData, event); } catch (error) { - if (error instanceof HTTPError && error.response.status !== 401) { + if ( + (error instanceof HTTPError || error instanceof ResponseError) && + error.response.status !== 401 + ) { // Returned directly, since the error has been handled by the `use-api` hook. return; } diff --git a/packages/core/package.json b/packages/core/package.json index 805aa7b02..de9077dde 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -97,7 +97,7 @@ "zod": "^3.23.8" }, "devDependencies": { - "@logto/cloud": "0.2.5-91ab76c", + "@logto/cloud": "0.2.5-1661979", "@silverhand/eslint-config": "6.0.1", "@silverhand/ts-config": "6.0.0", "@types/adm-zip": "^0.5.5", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 68dfa7d32..b41e4492c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1269,8 +1269,8 @@ importers: version: 3.23.8 devDependencies: '@logto/cloud': - specifier: 0.2.5-582d792 - version: 0.2.5-582d792(zod@3.23.8) + specifier: 0.2.5-1661979 + version: 0.2.5-1661979(zod@3.23.8) '@silverhand/eslint-config': specifier: 6.0.1 version: 6.0.1(eslint@8.57.0)(prettier@3.0.0)(typescript@5.5.3) @@ -2568,8 +2568,8 @@ importers: specifier: ^29.5.0 version: 29.5.0 '@logto/cloud': - specifier: 0.2.5-91ab76c - version: 0.2.5-91ab76c(zod@3.23.8) + specifier: 0.2.5-1661979 + version: 0.2.5-1661979(zod@3.23.8) '@logto/connector-kit': specifier: workspace:^4.0.0 version: link:../toolkit/connector-kit @@ -3064,8 +3064,8 @@ importers: version: 3.23.8 devDependencies: '@logto/cloud': - specifier: 0.2.5-91ab76c - version: 0.2.5-91ab76c(zod@3.23.8) + specifier: 0.2.5-1661979 + version: 0.2.5-1661979(zod@3.23.8) '@silverhand/eslint-config': specifier: 6.0.1 version: 6.0.1(eslint@8.57.0)(prettier@3.0.0)(typescript@5.5.3) @@ -5571,12 +5571,8 @@ packages: '@logto/client@2.7.2': resolution: {integrity: sha512-jsmuDl9QpXfR3uLEMPE67tvYoL5XcjJi+4yGqucYPjd4GH6SUHp3N9skk8C/OyygnKDPLY+ttwD0LaIbpGvn+Q==} - '@logto/cloud@0.2.5-582d792': - resolution: {integrity: sha512-0fIZzqwyjQguTS0a5+XbgVZlGEB/MXIf6pbuBDkHh6JHlMTJ/XH041rWX+e+nMk5N7/Xk2XXS+d2RJUWumnmpw==} - engines: {node: ^20.9.0} - - '@logto/cloud@0.2.5-91ab76c': - resolution: {integrity: sha512-t/ZVrFICVxtqw6zh6/OJ+0VYt+fl+waNz77CdAJkhxC91KFMfojm4hWNrx1qTNSTUzg+gc/2p8cbKC9cH1ngeA==} + '@logto/cloud@0.2.5-1661979': + resolution: {integrity: sha512-CiH6VxaR281cZLWQyI54XUiwSXEnW9rxci6ptz73rS4OWYfIweOWzP3Z30OVLiOslznBfTLuBML8eVelxpG1iQ==} engines: {node: ^20.9.0} '@logto/js@4.1.4': @@ -15244,14 +15240,7 @@ snapshots: camelcase-keys: 7.0.2 jose: 5.6.3 - '@logto/cloud@0.2.5-582d792(zod@3.23.8)': - dependencies: - '@silverhand/essentials': 2.9.1 - '@withtyped/server': 0.14.0(zod@3.23.8) - transitivePeerDependencies: - - zod - - '@logto/cloud@0.2.5-91ab76c(zod@3.23.8)': + '@logto/cloud@0.2.5-1661979(zod@3.23.8)': dependencies: '@silverhand/essentials': 2.9.1 '@withtyped/server': 0.14.0(zod@3.23.8)