From 6a3281a18ddc1dca45e262d0c7225c74f970e13f Mon Sep 17 00:00:00 2001 From: Thomas Trompette Date: Thu, 12 Mar 2026 15:55:30 +0100 Subject: [PATCH] Bug fix batches (#18588) - clear sse state on logout - fix no record not selectable through keyboard - fix book a call design - fix error notif design --- .../src/modules/auth/hooks/useAuth.ts | 8 +++--- .../SingleRecordPickerMenuItems.tsx | 9 ++++--- .../sse-db-event/hooks/useClearSseClient.ts | 25 +++++++++++++++++++ .../auth/services/sign-in-up.service.ts | 4 +-- .../progress-bar/components/ProgressBar.tsx | 3 ++- .../link/components/ClickToActionLink.tsx | 1 + 6 files changed, 39 insertions(+), 11 deletions(-) create mode 100644 packages/twenty-front/src/modules/sse-db-event/hooks/useClearSseClient.ts diff --git a/packages/twenty-front/src/modules/auth/hooks/useAuth.ts b/packages/twenty-front/src/modules/auth/hooks/useAuth.ts index 5f6d4ded6c..ee6865ac7a 100644 --- a/packages/twenty-front/src/modules/auth/hooks/useAuth.ts +++ b/packages/twenty-front/src/modules/auth/hooks/useAuth.ts @@ -52,7 +52,7 @@ import { useOrigin } from '@/domain-manager/hooks/useOrigin'; import { useRedirect } from '@/domain-manager/hooks/useRedirect'; import { useRedirectToWorkspaceDomain } from '@/domain-manager/hooks/useRedirectToWorkspaceDomain'; import { domainConfigurationState } from '@/domain-manager/states/domainConfigurationState'; -import { sseClientState } from '@/sse-db-event/states/sseClientState'; +import { useClearSseClient } from '@/sse-db-event/hooks/useClearSseClient'; import { useLoadCurrentUser } from '@/users/hooks/useLoadCurrentUser'; import { workspaceAuthProvidersState } from '@/workspace/states/workspaceAuthProvidersState'; import { i18n } from '@lingui/core'; @@ -81,6 +81,7 @@ export const useAuth = () => { isEmailVerificationRequiredState, ); const { loadCurrentUser } = useLoadCurrentUser(); + const { clearSseClient } = useClearSseClient(); const { reloadWorkspaceMetadata, resetToMockedMetadata } = useReloadWorkspaceMetadata(); @@ -117,9 +118,7 @@ export const useAuth = () => { const navigate = useNavigate(); const clearSession = useCallback(async () => { - const sseClient = store.get(sseClientState.atom); - - sseClient?.dispose(); + clearSseClient(); const authProvidersValue = store.get(workspaceAuthProvidersState.atom); const domainConfigurationValue = store.get(domainConfigurationState.atom); @@ -162,6 +161,7 @@ export const useAuth = () => { navigate(AppPath.SignInUp); store.set(isAppEffectRedirectEnabledState.atom, true); }, [ + clearSseClient, client, setLastAuthenticateWorkspaceDomain, resetToMockedMetadata, diff --git a/packages/twenty-front/src/modules/object-record/record-picker/single-record-picker/components/SingleRecordPickerMenuItems.tsx b/packages/twenty-front/src/modules/object-record/record-picker/single-record-picker/components/SingleRecordPickerMenuItems.tsx index be2aa60bda..968c8766bd 100644 --- a/packages/twenty-front/src/modules/object-record/record-picker/single-record-picker/components/SingleRecordPickerMenuItems.tsx +++ b/packages/twenty-front/src/modules/object-record/record-picker/single-record-picker/components/SingleRecordPickerMenuItems.tsx @@ -55,8 +55,8 @@ export const SingleRecordPickerMenuItems = ({ const isSelectedItemId = useAtomComponentFamilyStateValue( isSelectedItemIdComponentFamilyState, - selectableListComponentInstanceId, 'select-none', + selectableListComponentInstanceId, ); useHotkeysOnFocusedElement({ @@ -69,9 +69,10 @@ export const SingleRecordPickerMenuItems = ({ dependencies: [onCancel, resetSelectedItem], }); - const selectableItemIds = pickableMorphItems.map( - (morphItem) => morphItem.recordId, - ); + const selectableItemIds = [ + ...(emptyLabel ? ['select-none'] : []), + ...pickableMorphItems.map((morphItem) => morphItem.recordId), + ]; const [singleRecordPickerSelectedId, setSingleRecordPickerSelectedId] = useAtomComponentState(singleRecordPickerSelectedIdComponentState); diff --git a/packages/twenty-front/src/modules/sse-db-event/hooks/useClearSseClient.ts b/packages/twenty-front/src/modules/sse-db-event/hooks/useClearSseClient.ts new file mode 100644 index 0000000000..b18fdb9e0b --- /dev/null +++ b/packages/twenty-front/src/modules/sse-db-event/hooks/useClearSseClient.ts @@ -0,0 +1,25 @@ +import { activeQueryListenersState } from '@/sse-db-event/states/activeQueryListenersState'; +import { requiredQueryListenersState } from '@/sse-db-event/states/requiredQueryListenersState'; +import { sseClientState } from '@/sse-db-event/states/sseClientState'; +import { sseEventStreamIdState } from '@/sse-db-event/states/sseEventStreamIdState'; +import { sseEventStreamReadyState } from '@/sse-db-event/states/sseEventStreamReadyState'; +import { useCallback } from 'react'; +import { useStore } from 'jotai'; + +export const useClearSseClient = () => { + const store = useStore(); + + const clearSseClient = useCallback(() => { + const sseClient = store.get(sseClientState.atom); + + store.set(sseClientState.atom, null); + store.set(sseEventStreamIdState.atom, null); + store.set(sseEventStreamReadyState.atom, false); + store.set(activeQueryListenersState.atom, []); + store.set(requiredQueryListenersState.atom, []); + + sseClient?.dispose(); + }, [store]); + + return { clearSseClient }; +}; diff --git a/packages/twenty-server/src/engine/core-modules/auth/services/sign-in-up.service.ts b/packages/twenty-server/src/engine/core-modules/auth/services/sign-in-up.service.ts index 9f0217d79d..29e7191531 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/services/sign-in-up.service.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/services/sign-in-up.service.ts @@ -20,6 +20,7 @@ import { compareHash, hashPassword, } from 'src/engine/core-modules/auth/auth.util'; +import { type AuthContextUser } from 'src/engine/core-modules/auth/types/auth-context.type'; import { type AuthProviderWithPasswordType, type ExistingUserOrPartialUserWithPicture, @@ -33,10 +34,10 @@ import { MetricsService } from 'src/engine/core-modules/metrics/metrics.service' import { MetricsKeys } from 'src/engine/core-modules/metrics/types/metrics-keys.type'; import { OnboardingService } from 'src/engine/core-modules/onboarding/onboarding.service'; import { SecureHttpClientService } from 'src/engine/core-modules/secure-http-client/secure-http-client.service'; +import { TelemetryEventType } from 'src/engine/core-modules/telemetry/telemetry-event.type'; import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service'; import { UserService } from 'src/engine/core-modules/user/services/user.service'; -import { type AuthContextUser } from 'src/engine/core-modules/auth/types/auth-context.type'; import { UserEntity } from 'src/engine/core-modules/user/user.entity'; import { WorkspaceInvitationService } from 'src/engine/core-modules/workspace-invitation/services/workspace-invitation.service'; import { AuthProviderEnum } from 'src/engine/core-modules/workspace/types/workspace.type'; @@ -45,7 +46,6 @@ import { WorkspaceCacheService } from 'src/engine/workspace-cache/services/works import { WorkspaceEventEmitter } from 'src/engine/workspace-event-emitter/workspace-event-emitter'; import { getDomainNameByEmail } from 'src/utils/get-domain-name-by-email'; import { isWorkEmail } from 'src/utils/is-work-email'; -import { TelemetryEventType } from 'src/engine/core-modules/telemetry/telemetry-event.type'; @Injectable() // oxlint-disable-next-line twenty/inject-workspace-repository diff --git a/packages/twenty-ui/src/feedback/progress-bar/components/ProgressBar.tsx b/packages/twenty-ui/src/feedback/progress-bar/components/ProgressBar.tsx index 0f550d44d4..8a7d566109 100644 --- a/packages/twenty-ui/src/feedback/progress-bar/components/ProgressBar.tsx +++ b/packages/twenty-ui/src/feedback/progress-bar/components/ProgressBar.tsx @@ -17,7 +17,8 @@ export type StyledBarProps = { }; const StyledBar = styled.div` - height: ${themeCssVariables.spacing[2]}; + height: 100%; + min-height: ${themeCssVariables.spacing[2]}; background-color: ${({ backgroundColor }) => backgroundColor ?? ''}; border-radius: ${({ withBorderRadius }) => withBorderRadius ? themeCssVariables.border.radius.xxl : '0'}; diff --git a/packages/twenty-ui/src/navigation/link/components/ClickToActionLink.tsx b/packages/twenty-ui/src/navigation/link/components/ClickToActionLink.tsx index 3c58b4c44c..f481f03a3f 100644 --- a/packages/twenty-ui/src/navigation/link/components/ClickToActionLink.tsx +++ b/packages/twenty-ui/src/navigation/link/components/ClickToActionLink.tsx @@ -12,6 +12,7 @@ const StyledButtonLink = styled.a` gap: ${themeCssVariables.spacing[1]}; padding: 0 ${themeCssVariables.spacing[1]}; text-decoration: none; + white-space: nowrap; &:hover { color: ${themeCssVariables.font.color.tertiary};