Revert "Make subdomain minimum length configurable via env var" (#23871)
Instead, reduce the subdomain minimum length to 1 char <!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/twentyhq/twenty/pull/23871?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. -->
This commit is contained in:
@@ -993,6 +993,7 @@ export type ClientConfig = {
|
||||
publicFunctionDomain?: Maybe<Scalars['String']['output']>;
|
||||
sentry: Sentry;
|
||||
signInPrefilled: Scalars['Boolean']['output'];
|
||||
/** @deprecated Subdomain minimum length is no longer configurable; kept one release for API compatibility, no longer read by the frontend. */
|
||||
subdomainMinLength: Scalars['Float']['output'];
|
||||
support: Support;
|
||||
};
|
||||
|
||||
+1
-7
@@ -1,6 +1,4 @@
|
||||
import { domainConfigurationState } from '@/domain-manager/states/domainConfigurationState';
|
||||
import { getSubdomainValidationSchema } from '@/settings/domains/utils/getSubdomainValidationSchema';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { useApolloClient, useLazyQuery } from '@apollo/client/react';
|
||||
import { useMemo, useState } from 'react';
|
||||
import {
|
||||
@@ -27,11 +25,7 @@ export const useWorkspaceSubdomainField = ({
|
||||
isSubdomainEnabled = true,
|
||||
}: { isSubdomainEnabled?: boolean } = {}) => {
|
||||
const apolloClient = useApolloClient();
|
||||
const { subdomainMinLength } = useAtomStateValue(domainConfigurationState);
|
||||
const subdomainSchema = useMemo(
|
||||
() => getSubdomainValidationSchema(subdomainMinLength),
|
||||
[subdomainMinLength],
|
||||
);
|
||||
const subdomainSchema = getSubdomainValidationSchema();
|
||||
|
||||
const defaults = useMemo(
|
||||
() =>
|
||||
|
||||
@@ -208,7 +208,6 @@ export const useClientConfig = (): UseClientConfigResult => {
|
||||
defaultSubdomain: clientConfig?.defaultSubdomain,
|
||||
frontDomain: clientConfig?.frontDomain,
|
||||
publicFunctionDomain: clientConfig?.publicFunctionDomain,
|
||||
subdomainMinLength: clientConfig?.subdomainMinLength,
|
||||
});
|
||||
setCanManageFeatureFlags(clientConfig?.canManageFeatureFlags);
|
||||
setLabPublicFeatureFlags(clientConfig?.publicFeatureFlags);
|
||||
|
||||
@@ -25,7 +25,6 @@ export type ClientConfig = {
|
||||
canManageFeatureFlags: boolean;
|
||||
captcha: Captcha;
|
||||
defaultSubdomain?: string;
|
||||
subdomainMinLength: number;
|
||||
frontDomain: string;
|
||||
publicFunctionDomain?: string | null;
|
||||
isAttachmentPreviewEnabled: boolean;
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
import { type ClientConfig } from '@/client-config/types/ClientConfig';
|
||||
import { createAtomState } from '@/ui/utilities/state/jotai/utils/createAtomState';
|
||||
import { DEFAULT_SUBDOMAIN_MIN_LENGTH } from 'twenty-shared/constants';
|
||||
|
||||
export const domainConfigurationState = createAtomState<
|
||||
Pick<
|
||||
ClientConfig,
|
||||
| 'frontDomain'
|
||||
| 'defaultSubdomain'
|
||||
| 'publicFunctionDomain'
|
||||
| 'subdomainMinLength'
|
||||
'frontDomain' | 'defaultSubdomain' | 'publicFunctionDomain'
|
||||
>
|
||||
>({
|
||||
key: 'domainConfiguration',
|
||||
@@ -16,6 +12,5 @@ export const domainConfigurationState = createAtomState<
|
||||
frontDomain: '',
|
||||
defaultSubdomain: undefined,
|
||||
publicFunctionDomain: undefined,
|
||||
subdomainMinLength: DEFAULT_SUBDOMAIN_MIN_LENGTH,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
||||
import { useRedirectToWorkspaceDomain } from '@/domain-manager/hooks/useRedirectToWorkspaceDomain';
|
||||
import { domainConfigurationState } from '@/domain-manager/states/domainConfigurationState';
|
||||
import { getSubdomainValidationSchema } from '@/settings/domains/utils/getSubdomainValidationSchema';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { useModal } from '@/ui/layout/modal/hooks/useModal';
|
||||
import { useAtomState } from '@/ui/utilities/state/jotai/hooks/useAtomState';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { CombinedGraphQLErrors } from '@apollo/client/errors';
|
||||
import { useMutation } from '@apollo/client/react';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
@@ -18,8 +16,7 @@ export const SUBDOMAIN_CHANGE_CONFIRMATION_MODAL_ID =
|
||||
|
||||
export const useSettingsSubdomain = () => {
|
||||
const { t } = useLingui();
|
||||
const { subdomainMinLength } = useAtomStateValue(domainConfigurationState);
|
||||
const subdomainSchema = getSubdomainValidationSchema(subdomainMinLength);
|
||||
const subdomainSchema = getSubdomainValidationSchema();
|
||||
|
||||
const { enqueueSuccessSnackBar, enqueueErrorSnackBar } = useSnackBar();
|
||||
const [updateWorkspace] = useMutation(UpdateWorkspaceDocument);
|
||||
|
||||
+3
-8
@@ -1,20 +1,15 @@
|
||||
import { t } from '@lingui/core/macro';
|
||||
import {
|
||||
DEFAULT_SUBDOMAIN_MIN_LENGTH,
|
||||
RESERVED_SUBDOMAINS,
|
||||
SUBDOMAIN_PATTERN,
|
||||
} from 'twenty-shared/constants';
|
||||
import { z } from 'zod';
|
||||
|
||||
export const getSubdomainValidationSchema = (
|
||||
minLength = DEFAULT_SUBDOMAIN_MIN_LENGTH,
|
||||
) =>
|
||||
export const getSubdomainValidationSchema = () =>
|
||||
z
|
||||
.string()
|
||||
.min(minLength, {
|
||||
message: t`Subdomain cannot be shorter than ${minLength} characters`,
|
||||
})
|
||||
.max(30, { message: t`Subdomain can not be longer than 30 characters` })
|
||||
.min(1, { message: t`Subdomain cannot be empty` })
|
||||
.max(30, { message: t`Subdomain cannot be longer than 30 characters` })
|
||||
.regex(SUBDOMAIN_PATTERN, {
|
||||
message: t`Use letter, number and dash only. Start and finish with a letter or a number`,
|
||||
})
|
||||
|
||||
+14
-7
@@ -1,11 +1,14 @@
|
||||
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
||||
import { expect, userEvent, within } from 'storybook/test';
|
||||
|
||||
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
||||
import { jotaiStore } from '@/ui/utilities/state/jotai/jotaiStore';
|
||||
import {
|
||||
PageDecorator,
|
||||
type PageDecoratorArgs,
|
||||
} from '~/testing/decorators/PageDecorator';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
import { mockCurrentWorkspace } from '~/testing/mock-data/users';
|
||||
|
||||
import { SettingsSubdomainPage } from '~/pages/settings/domains/SettingsSubdomainPage';
|
||||
|
||||
@@ -14,6 +17,13 @@ const meta: Meta<PageDecoratorArgs> = {
|
||||
component: SettingsSubdomainPage,
|
||||
decorators: [PageDecorator],
|
||||
args: { routePath: '/settings/domains/subdomain' },
|
||||
beforeEach: () => {
|
||||
jotaiStore.set(currentWorkspaceState.atom, mockCurrentWorkspace);
|
||||
|
||||
return () => {
|
||||
jotaiStore.set(currentWorkspaceState.atom, null);
|
||||
};
|
||||
},
|
||||
parameters: {
|
||||
msw: graphqlMocks,
|
||||
},
|
||||
@@ -25,20 +35,17 @@ export type Story = StoryObj<typeof SettingsSubdomainPage>;
|
||||
|
||||
export const Default: Story = {};
|
||||
|
||||
export const TooShortSubdomain: Story = {
|
||||
export const EmptySubdomain: Story = {
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
|
||||
const input = await canvas.findByRole('textbox', {}, { timeout: 5000 });
|
||||
|
||||
await expect(input).toHaveValue(mockCurrentWorkspace.subdomain);
|
||||
|
||||
await userEvent.clear(input);
|
||||
await userEvent.type(input, 'ab');
|
||||
|
||||
const errorMessage = await canvas.findByText(
|
||||
'Subdomain cannot be shorter than 3 characters',
|
||||
);
|
||||
|
||||
await expect(errorMessage).toBeVisible();
|
||||
await canvas.findByText('Subdomain cannot be empty');
|
||||
|
||||
const saveButton = canvas.getByText('Save');
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ export const mockedClientConfig: ClientConfig = {
|
||||
},
|
||||
frontDomain: 'localhost',
|
||||
defaultSubdomain: 'app',
|
||||
subdomainMinLength: 3,
|
||||
analyticsEnabled: true,
|
||||
support: {
|
||||
supportDriver: SupportDriver.FRONT,
|
||||
|
||||
Reference in New Issue
Block a user