From 957546e305b1051a47cbde7942bd8ad43ef7f5a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nuno=20G=C3=B3is?= Date: Thu, 19 Oct 2023 13:18:25 +0100 Subject: [PATCH] refactor: rename message banners to banners (#5098) https://linear.app/unleash/issue/2-1531/rename-message-banners-to-banners This renames "message banners" to "banners". I also added support for external banners coming from a `banner` flag instead of only `messageBanner` flag, so we can eventually migrate to the new one in the future if we want. --- frontend/src/component/App.tsx | 8 ++-- .../Banner/Banner.tsx} | 18 ++++---- .../Banner/BannerDialog/BannerDialog.tsx} | 6 +-- .../externalBanners/ExternalBanners.tsx | 30 +++++++++++++ .../internalBanners/InternalBanners.tsx | 14 ++++++ .../ExternalMessageBanners.tsx | 28 ------------ .../InternalMessageBanners.tsx | 17 -------- .../useMessageBannersApi.ts | 43 ++++++++----------- .../useBanners.ts} | 17 ++++---- frontend/src/hooks/usePlausibleTracker.ts | 2 +- .../{messageBanner.ts => banner.ts} | 4 +- frontend/src/interfaces/uiConfig.ts | 3 +- .../__snapshots__/create-config.test.ts.snap | 4 +- src/lib/types/experimental.ts | 7 ++- ...rename-message-banners-table-to-banners.js | 9 ++++ 15 files changed, 106 insertions(+), 104 deletions(-) rename frontend/src/component/{messageBanners/MessageBanner/MessageBanner.tsx => banners/Banner/Banner.tsx} (89%) rename frontend/src/component/{messageBanners/MessageBanner/MessageBannerDialog/MessageBannerDialog.tsx => banners/Banner/BannerDialog/BannerDialog.tsx} (87%) create mode 100644 frontend/src/component/banners/externalBanners/ExternalBanners.tsx create mode 100644 frontend/src/component/banners/internalBanners/InternalBanners.tsx delete mode 100644 frontend/src/component/messageBanners/externalMessageBanners/ExternalMessageBanners.tsx delete mode 100644 frontend/src/component/messageBanners/internalMessageBanners/InternalMessageBanners.tsx rename frontend/src/hooks/api/getters/{useMessageBanners/useMessageBanners.ts => useBanners/useBanners.ts} (62%) rename frontend/src/interfaces/{messageBanner.ts => banner.ts} (77%) create mode 100644 src/migrations/20231019110154-rename-message-banners-table-to-banners.js diff --git a/frontend/src/component/App.tsx b/frontend/src/component/App.tsx index ede602779a0e..778ca85f065c 100644 --- a/frontend/src/component/App.tsx +++ b/frontend/src/component/App.tsx @@ -20,8 +20,8 @@ import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig'; import MaintenanceBanner from './maintenance/MaintenanceBanner'; import { styled } from '@mui/material'; import { InitialRedirect } from './InitialRedirect'; -import { InternalMessageBanners } from './messageBanners/internalMessageBanners/InternalMessageBanners'; -import { ExternalMessageBanners } from './messageBanners/externalMessageBanners/ExternalMessageBanners'; +import { InternalBanners } from './banners/internalBanners/InternalBanners'; +import { ExternalBanners } from './banners/externalBanners/ExternalBanners'; const StyledContainer = styled('div')(() => ({ '& ul': { @@ -65,8 +65,8 @@ export const App = () => { )} show={} /> - - + + diff --git a/frontend/src/component/messageBanners/MessageBanner/MessageBanner.tsx b/frontend/src/component/banners/Banner/Banner.tsx similarity index 89% rename from frontend/src/component/messageBanners/MessageBanner/MessageBanner.tsx rename to frontend/src/component/banners/Banner/Banner.tsx index 2e7a3783291b..757d97f04724 100644 --- a/frontend/src/component/messageBanners/MessageBanner/MessageBanner.tsx +++ b/frontend/src/component/banners/Banner/Banner.tsx @@ -7,10 +7,10 @@ import { import { styled, Icon, Link } from '@mui/material'; import { usePlausibleTracker } from 'hooks/usePlausibleTracker'; import { useNavigate } from 'react-router-dom'; -import { MessageBannerDialog } from './MessageBannerDialog/MessageBannerDialog'; +import { BannerDialog } from './BannerDialog/BannerDialog'; import { useState } from 'react'; import ReactMarkdown from 'react-markdown'; -import { BannerVariant, IMessageBanner } from 'interfaces/messageBanner'; +import { BannerVariant, IBanner } from 'interfaces/banner'; const StyledBar = styled('aside', { shouldForwardProp: (prop) => prop !== 'variant' && prop !== 'sticky', @@ -43,11 +43,11 @@ const StyledIcon = styled('div', { color: theme.palette[variant].main, })); -interface IMessageBannerProps { - messageBanner: IMessageBanner; +interface IBannerProps { + banner: IBanner; } -export const MessageBanner = ({ messageBanner }: IMessageBannerProps) => { +export const Banner = ({ banner }: IBannerProps) => { const [open, setOpen] = useState(false); const { @@ -60,7 +60,7 @@ export const MessageBanner = ({ messageBanner }: IMessageBannerProps) => { plausibleEvent, dialogTitle, dialog, - } = messageBanner; + } = banner; return ( @@ -75,13 +75,13 @@ export const MessageBanner = ({ messageBanner }: IMessageBannerProps) => { > {linkText} - {dialog!} - + ); }; @@ -127,7 +127,7 @@ const BannerButton = ({ const trackEvent = () => { if (!plausibleEvent) return; - tracker.trackEvent('message_banner', { + tracker.trackEvent('banner', { props: { event: plausibleEvent }, }); }; diff --git a/frontend/src/component/messageBanners/MessageBanner/MessageBannerDialog/MessageBannerDialog.tsx b/frontend/src/component/banners/Banner/BannerDialog/BannerDialog.tsx similarity index 87% rename from frontend/src/component/messageBanners/MessageBanner/MessageBannerDialog/MessageBannerDialog.tsx rename to frontend/src/component/banners/Banner/BannerDialog/BannerDialog.tsx index 49a32e6b6c84..8d92557cb0cf 100644 --- a/frontend/src/component/messageBanners/MessageBanner/MessageBannerDialog/MessageBannerDialog.tsx +++ b/frontend/src/component/banners/Banner/BannerDialog/BannerDialog.tsx @@ -8,19 +8,19 @@ const StyledReactMarkdown = styled(ReactMarkdown)(({ theme }) => ({ }, })); -interface IMessageBannerDialogProps { +interface IBannerDialogProps { title: string; open: boolean; setOpen: React.Dispatch>; children: string; } -export const MessageBannerDialog = ({ +export const BannerDialog = ({ open, setOpen, title, children, -}: IMessageBannerDialogProps) => { +}: IBannerDialogProps) => { return ( { + const { uiConfig } = useUiConfig(); + + const bannerVariantFromMessageBannerFlag = useVariant( + uiConfig.flags.messageBanner, + ); + const bannerVariantFromBannerFlag = useVariant( + uiConfig.flags.banner, + ); + + const bannerVariant = + bannerVariantFromMessageBannerFlag || bannerVariantFromBannerFlag || []; + + const banners: IBanner[] = Array.isArray(bannerVariant) + ? bannerVariant + : [bannerVariant]; + + return ( + <> + {banners.map((banner) => ( + + ))} + + ); +}; diff --git a/frontend/src/component/banners/internalBanners/InternalBanners.tsx b/frontend/src/component/banners/internalBanners/InternalBanners.tsx new file mode 100644 index 000000000000..3db8dbd90aa1 --- /dev/null +++ b/frontend/src/component/banners/internalBanners/InternalBanners.tsx @@ -0,0 +1,14 @@ +import { Banner } from 'component/banners/Banner/Banner'; +import { useBanners } from 'hooks/api/getters/useBanners/useBanners'; + +export const InternalBanners = () => { + const { banners } = useBanners(); + + return ( + <> + {banners.map((banner) => ( + + ))} + + ); +}; diff --git a/frontend/src/component/messageBanners/externalMessageBanners/ExternalMessageBanners.tsx b/frontend/src/component/messageBanners/externalMessageBanners/ExternalMessageBanners.tsx deleted file mode 100644 index ee991ca89c96..000000000000 --- a/frontend/src/component/messageBanners/externalMessageBanners/ExternalMessageBanners.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import { MessageBanner } from 'component/messageBanners/MessageBanner/MessageBanner'; -import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig'; -import { useVariant } from 'hooks/useVariant'; -import { IMessageBanner } from 'interfaces/messageBanner'; - -export const ExternalMessageBanners = () => { - const { uiConfig } = useUiConfig(); - - const messageBannerVariant = - useVariant( - uiConfig.flags.messageBanner, - ) || []; - - const messageBanners: IMessageBanner[] = Array.isArray(messageBannerVariant) - ? messageBannerVariant - : [messageBannerVariant]; - - return ( - <> - {messageBanners.map((messageBanner) => ( - - ))} - - ); -}; diff --git a/frontend/src/component/messageBanners/internalMessageBanners/InternalMessageBanners.tsx b/frontend/src/component/messageBanners/internalMessageBanners/InternalMessageBanners.tsx deleted file mode 100644 index f84d17c597fa..000000000000 --- a/frontend/src/component/messageBanners/internalMessageBanners/InternalMessageBanners.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { MessageBanner } from 'component/messageBanners/MessageBanner/MessageBanner'; -import { useMessageBanners } from 'hooks/api/getters/useMessageBanners/useMessageBanners'; - -export const InternalMessageBanners = () => { - const { messageBanners } = useMessageBanners(); - - return ( - <> - {messageBanners.map((messageBanner) => ( - - ))} - - ); -}; diff --git a/frontend/src/hooks/api/actions/useMessageBannersApi/useMessageBannersApi.ts b/frontend/src/hooks/api/actions/useMessageBannersApi/useMessageBannersApi.ts index 384cba240269..c65e93cbb998 100644 --- a/frontend/src/hooks/api/actions/useMessageBannersApi/useMessageBannersApi.ts +++ b/frontend/src/hooks/api/actions/useMessageBannersApi/useMessageBannersApi.ts @@ -1,27 +1,22 @@ -import { IInternalMessageBanner } from 'interfaces/messageBanner'; +import { IInternalBanner } from 'interfaces/banner'; import useAPI from '../useApi/useApi'; -const ENDPOINT = 'api/admin/message-banners'; +const ENDPOINT = 'api/admin/banners'; -type AddOrUpdateMessageBanner = Omit< - IInternalMessageBanner, - 'id' | 'createdAt' ->; +type AddOrUpdateBanner = Omit; -export const useMessageBannersApi = () => { +export const useBannersApi = () => { const { loading, makeRequest, createRequest, errors } = useAPI({ propagateErrors: true, }); - const addMessageBanner = async ( - messageBanner: AddOrUpdateMessageBanner, - ) => { - const requestId = 'addMessageBanner'; + const addBanner = async (banner: AddOrUpdateBanner) => { + const requestId = 'addBanner'; const req = createRequest( ENDPOINT, { method: 'POST', - body: JSON.stringify(messageBanner), + body: JSON.stringify(banner), }, requestId, ); @@ -30,16 +25,16 @@ export const useMessageBannersApi = () => { return response.json(); }; - const updateMessageBanner = async ( - messageBannerId: number, - messageBanner: AddOrUpdateMessageBanner, + const updateBanner = async ( + bannerId: number, + banner: AddOrUpdateBanner, ) => { - const requestId = 'updateMessageBanner'; + const requestId = 'updateBanner'; const req = createRequest( - `${ENDPOINT}/${messageBannerId}`, + `${ENDPOINT}/${bannerId}`, { method: 'PUT', - body: JSON.stringify(messageBanner), + body: JSON.stringify(banner), }, requestId, ); @@ -47,10 +42,10 @@ export const useMessageBannersApi = () => { await makeRequest(req.caller, req.id); }; - const removeMessageBanner = async (messageBannerId: number) => { - const requestId = 'removeMessageBanner'; + const removeBanner = async (bannerId: number) => { + const requestId = 'removeBanner'; const req = createRequest( - `${ENDPOINT}/${messageBannerId}`, + `${ENDPOINT}/${bannerId}`, { method: 'DELETE' }, requestId, ); @@ -59,9 +54,9 @@ export const useMessageBannersApi = () => { }; return { - addMessageBanner, - updateMessageBanner, - removeMessageBanner, + addBanner, + updateBanner, + removeBanner, errors, loading, }; diff --git a/frontend/src/hooks/api/getters/useMessageBanners/useMessageBanners.ts b/frontend/src/hooks/api/getters/useBanners/useBanners.ts similarity index 62% rename from frontend/src/hooks/api/getters/useMessageBanners/useMessageBanners.ts rename to frontend/src/hooks/api/getters/useBanners/useBanners.ts index 0bfdbd92fa6e..f6e6399fb649 100644 --- a/frontend/src/hooks/api/getters/useMessageBanners/useMessageBanners.ts +++ b/frontend/src/hooks/api/getters/useBanners/useBanners.ts @@ -4,25 +4,24 @@ import handleErrorResponses from '../httpErrorResponseHandler'; import { useConditionalSWR } from '../useConditionalSWR/useConditionalSWR'; import useUiConfig from '../useUiConfig/useUiConfig'; import { useUiFlag } from 'hooks/useUiFlag'; -import { IInternalMessageBanner } from 'interfaces/messageBanner'; +import { IInternalBanner } from 'interfaces/banner'; -const ENDPOINT = 'api/admin/message-banners'; +const ENDPOINT = 'api/admin/banners'; -export const useMessageBanners = () => { +export const useBanners = () => { const { isEnterprise } = useUiConfig(); - const internalMessageBanners = useUiFlag('internalMessageBanners'); + const bannersEnabled = useUiFlag('banners'); const { data, error, mutate } = useConditionalSWR( - isEnterprise() && internalMessageBanners, - { messageBanners: [] }, + isEnterprise() && bannersEnabled, + { banners: [] }, formatApiPath(ENDPOINT), fetcher, ); return useMemo( () => ({ - messageBanners: (data?.messageBanners ?? - []) as IInternalMessageBanner[], + banners: (data?.banners ?? []) as IInternalBanner[], loading: !error && !data, refetch: () => mutate(), error, @@ -33,6 +32,6 @@ export const useMessageBanners = () => { const fetcher = (path: string) => { return fetch(path) - .then(handleErrorResponses('Message Banners')) + .then(handleErrorResponses('Banners')) .then((res) => res.json()); }; diff --git a/frontend/src/hooks/usePlausibleTracker.ts b/frontend/src/hooks/usePlausibleTracker.ts index 97a80cd18fd6..00f1a60a000a 100644 --- a/frontend/src/hooks/usePlausibleTracker.ts +++ b/frontend/src/hooks/usePlausibleTracker.ts @@ -15,7 +15,7 @@ export type CustomEvents = | 'change_request' | 'favorite' | 'maintenance' - | 'message_banner' + | 'banner' | 'hidden_environment' | 'project_overview' | 'suggest_tags' diff --git a/frontend/src/interfaces/messageBanner.ts b/frontend/src/interfaces/banner.ts similarity index 77% rename from frontend/src/interfaces/messageBanner.ts rename to frontend/src/interfaces/banner.ts index 4cd168c88a24..c7bbb8a38f6e 100644 --- a/frontend/src/interfaces/messageBanner.ts +++ b/frontend/src/interfaces/banner.ts @@ -1,6 +1,6 @@ export type BannerVariant = 'warning' | 'info' | 'error' | 'success'; -export interface IMessageBanner { +export interface IBanner { message: string; variant?: BannerVariant; sticky?: boolean; @@ -12,7 +12,7 @@ export interface IMessageBanner { dialog?: string; } -export interface IInternalMessageBanner extends IMessageBanner { +export interface IInternalBanner extends IBanner { id: number; enabled: boolean; createdAt: string; diff --git a/frontend/src/interfaces/uiConfig.ts b/frontend/src/interfaces/uiConfig.ts index e227653e3d65..2d825365c1e3 100644 --- a/frontend/src/interfaces/uiConfig.ts +++ b/frontend/src/interfaces/uiConfig.ts @@ -47,6 +47,7 @@ export type UiFlags = { embedProxyFrontend?: boolean; maintenanceMode?: boolean; messageBanner?: Variant; + banner?: Variant; featuresExportImport?: boolean; caseInsensitiveInOperators?: boolean; proPlanAutoCharge?: boolean; @@ -69,7 +70,7 @@ export type UiFlags = { accessOverview?: boolean; datadogJsonTemplate?: boolean; dependentFeatures?: boolean; - internalMessageBanners?: boolean; + banners?: boolean; disableEnvsOnRevive?: boolean; playgroundImprovements?: boolean; }; diff --git a/src/lib/__snapshots__/create-config.test.ts.snap b/src/lib/__snapshots__/create-config.test.ts.snap index a2a9656ca223..8475acd9645f 100644 --- a/src/lib/__snapshots__/create-config.test.ts.snap +++ b/src/lib/__snapshots__/create-config.test.ts.snap @@ -77,6 +77,7 @@ exports[`should create default config 1`] = ` "flags": { "accessOverview": false, "anonymiseEventLog": false, + "banners": false, "caseInsensitiveInOperators": false, "customRootRolesKillSwitch": false, "datadogJsonTemplate": false, @@ -93,7 +94,6 @@ exports[`should create default config 1`] = ` "featuresExportImport": true, "filterInvalidClientMetrics": false, "googleAuthEnabled": false, - "internalMessageBanners": false, "lastSeenByEnvironment": false, "maintenanceMode": false, "messageBanner": { @@ -122,6 +122,7 @@ exports[`should create default config 1`] = ` "experiments": { "accessOverview": false, "anonymiseEventLog": false, + "banners": false, "caseInsensitiveInOperators": false, "customRootRolesKillSwitch": false, "datadogJsonTemplate": false, @@ -138,7 +139,6 @@ exports[`should create default config 1`] = ` "featuresExportImport": true, "filterInvalidClientMetrics": false, "googleAuthEnabled": false, - "internalMessageBanners": false, "lastSeenByEnvironment": false, "maintenanceMode": false, "messageBanner": { diff --git a/src/lib/types/experimental.ts b/src/lib/types/experimental.ts index e663acb27071..afbeb9b91fa7 100644 --- a/src/lib/types/experimental.ts +++ b/src/lib/types/experimental.ts @@ -34,8 +34,7 @@ export type IFlagKey = | 'datadogJsonTemplate' | 'disableMetrics' | 'useLastSeenRefactor' - | 'internalMessageBanners' - | 'internalMessageBanner' + | 'banners' | 'separateAdminClientApi' | 'disableEnvsOnRevive' | 'playgroundImprovements'; @@ -162,8 +161,8 @@ const flags: IFlags = { process.env.UNLEASH_EXPERIMENTAL_USE_LAST_SEEN_REFACTOR, false, ), - internalMessageBanners: parseEnvVarBoolean( - process.env.UNLEASH_EXPERIMENTAL_INTERNAL_MESSAGE_BANNERS, + banners: parseEnvVarBoolean( + process.env.UNLEASH_EXPERIMENTAL_BANNERS, false, ), separateAdminClientApi: parseEnvVarBoolean( diff --git a/src/migrations/20231019110154-rename-message-banners-table-to-banners.js b/src/migrations/20231019110154-rename-message-banners-table-to-banners.js new file mode 100644 index 000000000000..460877c56b65 --- /dev/null +++ b/src/migrations/20231019110154-rename-message-banners-table-to-banners.js @@ -0,0 +1,9 @@ +'use strict'; + +exports.up = function (db, cb) { + db.runSql(`ALTER TABLE message_banners RENAME TO banners`, cb); +}; + +exports.down = function (db, cb) { + db.runSql(`ALTER TABLE banners RENAME TO message_banners`, cb); +};