From d526b07078cd7a6aa60fad3676a339ee1dcb1b92 Mon Sep 17 00:00:00 2001 From: Charles Bochet Date: Mon, 24 Nov 2025 17:34:10 +0100 Subject: [PATCH] Add ability to discard Information Banner (#16019) Fixes https://github.com/twentyhq/twenty/issues/14028 image --- .../src/generated-metadata/graphql.ts | 6 ++ .../twenty-front/src/generated/graphql.ts | 6 ++ .../components/InformationBanner.tsx | 75 +++++++++++++++---- ...rmationBannerBillingSubscriptionPaused.tsx | 1 + .../InformationBannerEndTrialPeriod.tsx | 1 + .../InformationBannerFailPaymentInfo.tsx | 1 + ...InformationBannerNoBillingSubscription.tsx | 1 + .../InformationBannerDeletedRecord.tsx | 1 + .../InformationBannerIsImpersonating.tsx | 1 + ...tionBannerReconnectAccountEmailAliases.tsx | 13 ++++ ...econnectAccountInsufficientPermissions.tsx | 13 ++++ .../dismissReconnectAccountBanner.ts | 7 ++ .../hooks/useDismissReconnectAccountBanner.ts | 45 +++++++++++ ...formationBannerComponentInstanceContext.ts | 4 + .../informationBannerIsOpenComponentState.ts | 9 +++ .../hooks/useLazyFindOneRecord.ts | 9 ++- .../dismiss-reconnect-account-banner.input.ts | 13 ++++ .../messaging/timeline-messaging.module.ts | 4 +- .../messaging/timeline-messaging.resolver.ts | 28 ++++++- 19 files changed, 219 insertions(+), 19 deletions(-) create mode 100644 packages/twenty-front/src/modules/information-banner/graphql/mutations/dismissReconnectAccountBanner.ts create mode 100644 packages/twenty-front/src/modules/information-banner/hooks/useDismissReconnectAccountBanner.ts create mode 100644 packages/twenty-front/src/modules/information-banner/states/contexts/InformationBannerComponentInstanceContext.ts create mode 100644 packages/twenty-front/src/modules/information-banner/states/informationBannerIsOpenComponentState.ts create mode 100644 packages/twenty-server/src/engine/core-modules/messaging/dtos/dismiss-reconnect-account-banner.input.ts diff --git a/packages/twenty-front/src/generated-metadata/graphql.ts b/packages/twenty-front/src/generated-metadata/graphql.ts index b972a5ed51..3c31003a88 100644 --- a/packages/twenty-front/src/generated-metadata/graphql.ts +++ b/packages/twenty-front/src/generated-metadata/graphql.ts @@ -1834,6 +1834,7 @@ export type Mutation = { destroyPageLayoutTab: Scalars['Boolean']; destroyPageLayoutWidget: Scalars['Boolean']; disablePostgresProxy: PostgresCredentials; + dismissReconnectAccountBanner: Scalars['Boolean']; duplicateWorkflow: WorkflowVersionDto; duplicateWorkflowVersionStep: WorkflowVersionStepChanges; editSSOIdentityProvider: EditSsoOutput; @@ -2370,6 +2371,11 @@ export type MutationDestroyPageLayoutWidgetArgs = { }; +export type MutationDismissReconnectAccountBannerArgs = { + connectedAccountId: Scalars['UUID']; +}; + + export type MutationDuplicateWorkflowArgs = { input: DuplicateWorkflowInput; }; diff --git a/packages/twenty-front/src/generated/graphql.ts b/packages/twenty-front/src/generated/graphql.ts index 4e1694ad96..21833292ac 100644 --- a/packages/twenty-front/src/generated/graphql.ts +++ b/packages/twenty-front/src/generated/graphql.ts @@ -1808,6 +1808,7 @@ export type Mutation = { destroyPageLayoutTab: Scalars['Boolean']; destroyPageLayoutWidget: Scalars['Boolean']; disablePostgresProxy: PostgresCredentials; + dismissReconnectAccountBanner: Scalars['Boolean']; duplicateWorkflow: WorkflowVersionDto; duplicateWorkflowVersionStep: WorkflowVersionStepChanges; editSSOIdentityProvider: EditSsoOutput; @@ -2325,6 +2326,11 @@ export type MutationDestroyPageLayoutWidgetArgs = { }; +export type MutationDismissReconnectAccountBannerArgs = { + connectedAccountId: Scalars['UUID']; +}; + + export type MutationDuplicateWorkflowArgs = { input: DuplicateWorkflowInput; }; diff --git a/packages/twenty-front/src/modules/information-banner/components/InformationBanner.tsx b/packages/twenty-front/src/modules/information-banner/components/InformationBanner.tsx index cc66353e21..cdd8aabac9 100644 --- a/packages/twenty-front/src/modules/information-banner/components/InformationBanner.tsx +++ b/packages/twenty-front/src/modules/information-banner/components/InformationBanner.tsx @@ -1,10 +1,15 @@ +import { InformationBannerComponentInstanceContext } from '@/information-banner/states/contexts/InformationBannerComponentInstanceContext'; +import { informationBannerIsOpenComponentState } from '@/information-banner/states/informationBannerIsOpenComponentState'; +import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue'; import styled from '@emotion/styled'; import { Banner, type BannerVariant, type IconComponent, + IconX, } from 'twenty-ui/display'; -import { Button } from 'twenty-ui/input'; +import { Button, IconButton } from 'twenty-ui/input'; +import { GRAY_SCALE_LIGHT } from 'twenty-ui/theme'; const StyledText = styled.div` overflow: hidden; @@ -12,6 +17,20 @@ const StyledText = styled.div` white-space: nowrap; `; +const StyledCloseButton = styled(IconButton)` + color: ${GRAY_SCALE_LIGHT.gray1}; + display: flex; +`; + +const StyledContent = styled.div<{ hasCloseButton: boolean }>` + align-items: center; + justify-content: center; + display: flex; + flex: 1; + margin-left: ${({ hasCloseButton }) => (hasCloseButton ? '24px' : '0')}; + gap: ${({ theme }) => theme.spacing(3)}; +`; + export const InformationBanner = ({ message, variant = 'default', @@ -19,6 +38,8 @@ export const InformationBanner = ({ buttonIcon, buttonOnClick, isButtonDisabled = false, + onClose, + componentInstanceId, }: { message: string; variant?: BannerVariant; @@ -26,21 +47,47 @@ export const InformationBanner = ({ buttonIcon?: IconComponent; buttonOnClick?: () => void; isButtonDisabled?: boolean; + onClose?: () => void; + componentInstanceId: string; }) => { + const informationBannerIsOpenComponent = useRecoilComponentValue( + informationBannerIsOpenComponentState, + componentInstanceId, + ); + return ( - - {message} - {buttonTitle && buttonOnClick && ( -