From 288d57b384f9167e556c20a99446ed6e06c1991d Mon Sep 17 00:00:00 2001 From: Eric Ciccotti Date: Thu, 9 Jan 2025 09:38:16 +0100 Subject: [PATCH] fix(pci.savings-plan): fix banner notifications management ref: TAPC-1861 Signed-off-by: Eric Ciccotti --- .../CreatePlanForm/CreatePlanForm.tsx | 27 +++- .../src/hooks/useSavingsPlan.tsx | 29 +++- .../src/pages/listing/edit-name/index.tsx | 17 ++- .../src/pages/listing/index.tsx | 129 +++--------------- .../src/pages/listing/renew-modal/index.tsx | 29 +++- .../src/types/CreatePlan.type.ts | 6 + .../pci-savings-plan/src/types/api.type.ts | 11 ++ .../apps/pci-savings-plan/vitest.config.js | 5 + 8 files changed, 120 insertions(+), 133 deletions(-) diff --git a/packages/manager/apps/pci-savings-plan/src/components/CreatePlanForm/CreatePlanForm.tsx b/packages/manager/apps/pci-savings-plan/src/components/CreatePlanForm/CreatePlanForm.tsx index 35b6cba2ee2d..6bdc50684608 100644 --- a/packages/manager/apps/pci-savings-plan/src/components/CreatePlanForm/CreatePlanForm.tsx +++ b/packages/manager/apps/pci-savings-plan/src/components/CreatePlanForm/CreatePlanForm.tsx @@ -1,5 +1,5 @@ import { usePciUrl } from '@ovh-ux/manager-pci-common'; -import { Subtitle } from '@ovh-ux/manager-react-components'; +import { Subtitle, useNotifications } from '@ovh-ux/manager-react-components'; import { ODS_BUTTON_VARIANT, ODS_ICON_NAME, @@ -20,12 +20,20 @@ import { OdsTabs, OdsText, } from '@ovhcloud/ods-components/react'; -import React, { FC, Suspense, useEffect, useMemo, useState } from 'react'; +import React, { + FC, + Suspense, + useContext, + useEffect, + useMemo, + useState, +} from 'react'; import { MutationStatus, useMutationState } from '@tanstack/react-query'; import { useTranslation } from 'react-i18next'; import { useNavigate } from 'react-router-dom'; +import { ShellContext } from '@ovh-ux/manager-react-shell-client'; import useTechnicalInfo, { usePricingInfo } from '@/hooks/useCatalogCommercial'; import { getMutationKeyCreateSavingsPlan, @@ -44,7 +52,7 @@ import { Resource, ResourceType, } from '../../types/CreatePlan.type'; -import { formatDate } from '../../utils/formatter/date'; +import { formatDate, toLocalDateUTC } from '../../utils/formatter/date'; import { isValidSavingsPlanName } from '../../utils/savingsPlan'; import Commitment from '../Commitment/Commitment'; import SimpleTile from '../SimpleTile/SimpleTile'; @@ -423,7 +431,12 @@ export const CreatePlanFormContainer = ({ }: { isDiscoveryProject: boolean; }) => { + const { environment } = useContext(ShellContext); + const locale = environment.getUserLocale(); + const { t } = useTranslation('create'); + const { addSuccess } = useNotifications(); + const { t: tListing } = useTranslation('listing'); const [instanceCategory, setInstanceCategory] = useState< InstanceTechnicalName @@ -452,7 +465,13 @@ export const CreatePlanFormContainer = ({ } }, [technicalList]); - const { mutate: onCreatePlan } = useSavingsPlanCreate(); + const { mutate: onCreatePlan } = useSavingsPlanCreate(async (data) => { + addSuccess( + tListing('banner_create_sp', { + startDate: toLocalDateUTC(data.startDate, locale), + }), + ); + }); const sortedPriceByDuration = [...pricingByDuration].sort( (a, b) => a.duration - b.duration, diff --git a/packages/manager/apps/pci-savings-plan/src/hooks/useSavingsPlan.tsx b/packages/manager/apps/pci-savings-plan/src/hooks/useSavingsPlan.tsx index be5afd48b063..033d9b3c3764 100644 --- a/packages/manager/apps/pci-savings-plan/src/hooks/useSavingsPlan.tsx +++ b/packages/manager/apps/pci-savings-plan/src/hooks/useSavingsPlan.tsx @@ -100,12 +100,18 @@ export const getMutationKeySPChangePeriod = ( serviceId: number, ) => ['savings-plan', serviceId, 'change-period', savingsPlanId]; -export const useSavingsPlanChangePeriod = (savingsPlanId: string) => { +export const useSavingsPlanChangePeriod = ( + savingsPlanId: string, + onSuccess?: () => void, +) => { const { refetch } = useSavingsPlan(); const serviceId = useServiceId(); return useMutation({ - onSuccess: () => refetch(), + onSuccess: async () => { + onSuccess?.(); + refetch(); + }, mutationKey: getMutationKeySPChangePeriod(savingsPlanId, serviceId), mutationFn: ({ periodEndAction, @@ -131,19 +137,27 @@ export const getMutationKeyCreateSavingsPlan = (serviceId: number) => [ 'create', ]; -export const useSavingsPlanEditName = (savingsPlanId: string) => { +export const useSavingsPlanEditName = ( + savingsPlanId: string, + onSuccess?: () => void, +) => { const { refetch } = useSavingsPlan(); const serviceId = useServiceId(); return useMutation({ - onSuccess: () => refetch(), mutationKey: getMutationKeySPEditName(savingsPlanId, serviceId), mutationFn: ({ displayName }: { displayName: string }) => putSubscribedSavingsPlanEditName(serviceId, savingsPlanId, displayName), + onSuccess: async () => { + onSuccess?.(); + refetch(); + }, }); }; -export const useSavingsPlanCreate = () => { +export const useSavingsPlanCreate = ( + onSuccess?: (data: SavingsPlanService) => void, +) => { const { refetch } = useSavingsPlan(); const serviceId = useServiceId(); const navigate = useNavigate(); @@ -151,8 +165,9 @@ export const useSavingsPlanCreate = () => { return useMutation({ onSuccess: async () => { - const { data } = await refetch(); - if (data?.length) { + const { data: refetchData } = await refetch(); + if (refetchData?.length) { + onSuccess?.(refetchData[0]); navigate(getSavingsPlansUrl(projectId)); } }, diff --git a/packages/manager/apps/pci-savings-plan/src/pages/listing/edit-name/index.tsx b/packages/manager/apps/pci-savings-plan/src/pages/listing/edit-name/index.tsx index 0867c753df63..231481f5990f 100644 --- a/packages/manager/apps/pci-savings-plan/src/pages/listing/edit-name/index.tsx +++ b/packages/manager/apps/pci-savings-plan/src/pages/listing/edit-name/index.tsx @@ -1,23 +1,30 @@ import React, { startTransition, Suspense } from 'react'; import { useNavigate, useParams, useSearchParams } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; -import { UpdateNameModal } from '@ovh-ux/manager-react-components'; +import { + UpdateNameModal, + useNotifications, +} from '@ovh-ux/manager-react-components'; import { useSavingsPlan, useSavingsPlanEditName } from '@/hooks/useSavingsPlan'; import { REGEX } from '@/utils/savingsPlan'; const EditNameChildren = () => { + const { t } = useTranslation('edit-name'); + const { t: tListing } = useTranslation('listing'); + const { t: tCreate } = useTranslation('create'); + const navigate = useNavigate(); const { savingsPlanId } = useParams(); + const { addSuccess } = useNotifications(); const { data: savingsPlan } = useSavingsPlan(); - const { mutate: editName } = useSavingsPlanEditName(savingsPlanId); + const { mutate: editName } = useSavingsPlanEditName(savingsPlanId, () => { + addSuccess(tListing('banner_edit_name')); + }); const [searchParams] = useSearchParams(); const currentPlan = savingsPlan?.find((plan) => plan.id === savingsPlanId); - const { t } = useTranslation('edit-name'); - const { t: tCreate } = useTranslation('create'); - return ( <> {currentPlan ? ( diff --git a/packages/manager/apps/pci-savings-plan/src/pages/listing/index.tsx b/packages/manager/apps/pci-savings-plan/src/pages/listing/index.tsx index ee76d6ab8e6c..c27da5ece2fe 100644 --- a/packages/manager/apps/pci-savings-plan/src/pages/listing/index.tsx +++ b/packages/manager/apps/pci-savings-plan/src/pages/listing/index.tsx @@ -1,22 +1,19 @@ -import React, { useContext, useEffect, useState } from 'react'; -import { MutationStatus, useMutationState } from '@tanstack/react-query'; +import React, { useEffect } from 'react'; import { useTranslation } from 'react-i18next'; -import { Outlet, useHref, useNavigate, useParams } from 'react-router-dom'; -import { ShellContext } from '@ovh-ux/manager-react-shell-client'; +import { Outlet, useNavigate, useParams } from 'react-router-dom'; import { ODS_BUTTON_SIZE, ODS_BUTTON_VARIANT } from '@ovhcloud/ods-components'; -import { OdsButton, OdsMessage, OdsText } from '@ovhcloud/ods-components/react'; +import { OdsButton, OdsText } from '@ovhcloud/ods-components/react'; -import { Title } from '@ovh-ux/manager-react-components'; +import { + Notifications, + Title, + useNotifications, +} from '@ovh-ux/manager-react-components'; import TableContainer from '@/components/Table/TableContainer'; -import { - getMutationKeyCreateSavingsPlan, - useSavingsPlan, - useServiceId, -} from '@/hooks/useSavingsPlan'; -import { SavingsPlanService } from '@/types'; -import { toLocalDateUTC } from '@/utils/formatter/date'; +import { useSavingsPlan } from '@/hooks/useSavingsPlan'; +import { ListingProps } from '@/types/CreatePlan.type'; export const formatDateString = (dateString: string, locale?: string) => { const date = new Date(dateString); @@ -31,42 +28,7 @@ export const formatDateString = (dateString: string, locale?: string) => { : '-'; }; -const Banner = ({ message }: { message: string }) => { - const [showBanner, setShowBanner] = useState(true); - - useEffect(() => { - if (message) { - setShowBanner(true); - } - }, [message]); - return ( - showBanner && ( - setShowBanner(false)} - > - {message} - - ) - ); -}; - -export interface ListingProps { - data: SavingsPlanService[]; - refetchSavingsPlans: () => void; -} - -type MutationInfo = { - submittedAt: number; - error?: { - code: string; - }; - status: MutationStatus; - data?: Data; -}; - -const getMutationFilters = (filters: (string | number)[]) => ({ +export const getMutationFilters = (filters: (string | number)[]) => ({ filters: { mutationKey: filters }, }); @@ -75,44 +37,9 @@ const ListingTablePage: React.FC = ({ refetchSavingsPlans, }) => { const { t } = useTranslation('listing'); - const { environment } = useContext(ShellContext); - const locale = environment.getUserLocale(); - const navigate = useNavigate(); - const hrefDashboard = useHref(''); - const serviceId = useServiceId(); const { projectId } = useParams(); - const mutationSPChangePeriod = useMutationState< - MutationInfo & { - variables: { - periodEndAction: 'REACTIVATE' | 'ACTIVATE'; - }; - } - >(getMutationFilters(['savings-plan', serviceId, 'change-period'])); - - const mutationSPEditName = useMutationState( - getMutationFilters(['savings-plan', serviceId, 'edit-name']), - ); - - const mutationSpCreate = useMutationState>( - getMutationFilters(getMutationKeyCreateSavingsPlan(serviceId)), - ); - - const lastMutationEditName = - mutationSPEditName[mutationSPEditName.length - 1]; - const lastMutationChangePeriod = - mutationSPChangePeriod[mutationSPChangePeriod.length - 1]; - const lastMutationSpCreate = mutationSpCreate[mutationSpCreate.length - 1]; - - const renewBannerMessage = t( - lastMutationChangePeriod?.variables.periodEndAction === 'REACTIVATE' - ? 'banner_renew_activate' - : 'banner_renew_deactivate', - { - planName: lastMutationChangePeriod?.data?.displayName, - endDate: lastMutationChangePeriod?.data?.endDate, - }, - ); + const { clearNotifications } = useNotifications(); return ( <> @@ -122,39 +49,17 @@ const ListingTablePage: React.FC = ({ icon="plus" size={ODS_BUTTON_SIZE.sm} variant={ODS_BUTTON_VARIANT.outline} - onClick={() => - navigate(`/pci/projects/${projectId}/savings-plan/new`) - } + onClick={() => { + clearNotifications(); + navigate(`/pci/projects/${projectId}/savings-plan/new`); + }} label={t('createSavingsPlan')} /> {t('informationMessage')} - {mutationSPChangePeriod.length > 0 && ( - - )} - {mutationSpCreate.length > 0 && !lastMutationSpCreate.error?.code && ( - - )} - - {mutationSPEditName.length > 0 && ( - - )} + ); diff --git a/packages/manager/apps/pci-savings-plan/src/pages/listing/renew-modal/index.tsx b/packages/manager/apps/pci-savings-plan/src/pages/listing/renew-modal/index.tsx index b44d327fbae5..7343098f56cf 100644 --- a/packages/manager/apps/pci-savings-plan/src/pages/listing/renew-modal/index.tsx +++ b/packages/manager/apps/pci-savings-plan/src/pages/listing/renew-modal/index.tsx @@ -1,5 +1,7 @@ import React from 'react'; import { useNavigate, useParams, useSearchParams } from 'react-router-dom'; +import { useNotifications } from '@ovh-ux/manager-react-components'; +import { useTranslation } from 'react-i18next'; import Errors from '@/components/Error/Error'; import RenewModal from '@/components/Modal/RenewModal'; import { @@ -11,18 +13,35 @@ import { SavingsPlanPlanedChangeStatus } from '@/types/api.type'; const RenewModalPage = () => { const navigate = useNavigate(); const { savingsPlanId } = useParams(); - const { data: savingsPlan, error, isError } = useSavingsPlan(); - const { mutate: changePeriod } = useSavingsPlanChangePeriod(savingsPlanId); + const { t: tListing } = useTranslation('listing'); + const { addSuccess } = useNotifications(); + + const currentPlan = savingsPlan?.find((plan) => plan.id === savingsPlanId); + const periodEndAction = currentPlan?.periodEndAction === 'REACTIVATE'; + + const { mutate: changePeriod } = useSavingsPlanChangePeriod( + savingsPlanId, + async () => { + addSuccess( + tListing( + currentPlan?.periodEndAction === 'REACTIVATE' + ? 'banner_renew_activate' + : 'banner_renew_deactivate', + { + planName: currentPlan.displayName, + endDate: currentPlan.endDate, + }, + ), + ); + }, + ); const [searchParams] = useSearchParams(); if (isError || error) { return ; } - const currentPlan = savingsPlan?.find((plan) => plan.id === savingsPlanId); - const periodEndAction = currentPlan?.periodEndAction === 'REACTIVATE'; - const goToPrevious = () => navigate({ pathname: '..', search: searchParams.toString() }); diff --git a/packages/manager/apps/pci-savings-plan/src/types/CreatePlan.type.ts b/packages/manager/apps/pci-savings-plan/src/types/CreatePlan.type.ts index d37a38715846..4549aaa0a864 100644 --- a/packages/manager/apps/pci-savings-plan/src/types/CreatePlan.type.ts +++ b/packages/manager/apps/pci-savings-plan/src/types/CreatePlan.type.ts @@ -1,4 +1,5 @@ import { formatTechnicalInfo } from '@/utils/formatter/formatter'; +import { SavingsPlanService } from './api.type'; export enum ResourceType { instance = 'instance', @@ -25,3 +26,8 @@ export type Resource = { label: string; img: string; }; + +export interface ListingProps { + data: SavingsPlanService[]; + refetchSavingsPlans: () => void; +} diff --git a/packages/manager/apps/pci-savings-plan/src/types/api.type.ts b/packages/manager/apps/pci-savings-plan/src/types/api.type.ts index 153fbad73b51..b22872c60815 100644 --- a/packages/manager/apps/pci-savings-plan/src/types/api.type.ts +++ b/packages/manager/apps/pci-savings-plan/src/types/api.type.ts @@ -1,3 +1,5 @@ +import { MutationStatus } from '@tanstack/react-query'; + export interface PciProject { project_id: string; projectName: string; @@ -65,3 +67,12 @@ export interface SavingsPlanService { startDate: string; status: SavingsPlanStatus; } + +export type MutationInfo = { + submittedAt: number; + error?: { + code: string; + }; + status: MutationStatus; + data?: Data; +}; diff --git a/packages/manager/apps/pci-savings-plan/vitest.config.js b/packages/manager/apps/pci-savings-plan/vitest.config.js index c8a1ca9993bb..0b1799e6e234 100644 --- a/packages/manager/apps/pci-savings-plan/vitest.config.js +++ b/packages/manager/apps/pci-savings-plan/vitest.config.js @@ -6,6 +6,11 @@ import react from '@vitejs/plugin-react'; export default defineConfig({ plugins: [react()], test: { + server: { + deps: { + inline: ['clsx'], + }, + }, globals: true, environment: 'jsdom', coverage: {