From 8007e2dc00e350a6d3eeaa76a55223078189b1de Mon Sep 17 00:00:00 2001 From: tsiorifamonjena Date: Thu, 19 Dec 2024 18:41:05 +0100 Subject: [PATCH 1/2] feat(pci.load-balancer): use regionselector for 3az feature ref: TAPC-2270 Signed-off-by: tsiorifamonjena --- .../apps/pci-load-balancer/package.json | 2 +- .../load-balancer/create/Messages_fr_FR.json | 5 +- .../src/api/hook/useFlavors.ts | 1 - .../src/api/hook/useFloatingIps.ts | 1 - .../src/api/hook/useNetwork.tsx | 2 - .../src/api/hook/useRegions.ts | 2 + .../src/pages/create/Create.page.tsx | 3 - .../create/steps/region/RegionStep.spec.tsx | 268 ++---------------- .../pages/create/steps/region/RegionStep.tsx | 256 ++++++++++------- .../components/GroupLabel.component.tsx | 31 -- .../components/StackLabel.component.tsx | 22 -- .../components/StackTitle.component.tsx | 19 -- yarn.lock | 10 + 13 files changed, 181 insertions(+), 441 deletions(-) delete mode 100644 packages/manager/apps/pci-load-balancer/src/pages/create/steps/region/components/GroupLabel.component.tsx delete mode 100644 packages/manager/apps/pci-load-balancer/src/pages/create/steps/region/components/StackLabel.component.tsx delete mode 100644 packages/manager/apps/pci-load-balancer/src/pages/create/steps/region/components/StackTitle.component.tsx diff --git a/packages/manager/apps/pci-load-balancer/package.json b/packages/manager/apps/pci-load-balancer/package.json index 965efd91ecd5..7ae019650246 100644 --- a/packages/manager/apps/pci-load-balancer/package.json +++ b/packages/manager/apps/pci-load-balancer/package.json @@ -21,7 +21,7 @@ "@ovh-ux/manager-config": "^8.0.2", "@ovh-ux/manager-core-api": "^0.9.0", "@ovh-ux/manager-core-utils": "^0.3.0", - "@ovh-ux/manager-pci-common": "^0.14.4", + "@ovh-ux/manager-pci-common": "^0.15.0", "@ovh-ux/manager-react-components": "^1.43.1", "@ovh-ux/manager-react-core-application": "^0.11.5", "@ovh-ux/manager-react-shell-client": "^0.8.5", diff --git a/packages/manager/apps/pci-load-balancer/public/translations/load-balancer/create/Messages_fr_FR.json b/packages/manager/apps/pci-load-balancer/public/translations/load-balancer/create/Messages_fr_FR.json index 47e5dc1994e8..d70c2a4ffd62 100644 --- a/packages/manager/apps/pci-load-balancer/public/translations/load-balancer/create/Messages_fr_FR.json +++ b/packages/manager/apps/pci-load-balancer/public/translations/load-balancer/create/Messages_fr_FR.json @@ -41,5 +41,8 @@ "octavia_load_balancer_create_name_field_label": "Nom du Load Balancer", "octavia_load_balancer_create_name_field_help": "Doit uniquement contenir des nombres, lettres, underscores, tirets ou points.", "octavia_load_balancer_create_submit": "Créer un Load Balancer", - "octavia_load_balancer_create_banner": "Votre Load Balancer est en cours de création. Cela ne prendra que quelques minutes." + "octavia_load_balancer_create_banner": "Votre Load Balancer est en cours de création. Cela ne prendra que quelques minutes.", + "octavia_load_balancer_create_private_network": "Il n'existe aucun réseau privé dans la région sélectionnée. Assurez-vous de avant la création du Load Balancer.", + "octavia_load_balancer_create_private_network_label": "créer un réseau privé", + "octavia_load_balancer_create_region_3az_price": "Load Balancer est actuellement en phase Beta dans la zone Paris (EU-WEST-PAR) et est donc gratuite durant cette période." } diff --git a/packages/manager/apps/pci-load-balancer/src/api/hook/useFlavors.ts b/packages/manager/apps/pci-load-balancer/src/api/hook/useFlavors.ts index 4652ab31ab44..e7443da75ae7 100644 --- a/packages/manager/apps/pci-load-balancer/src/api/hook/useFlavors.ts +++ b/packages/manager/apps/pci-load-balancer/src/api/hook/useFlavors.ts @@ -19,5 +19,4 @@ export const useGetFlavor = ( ], queryFn: () => getFlavor(projectId, regionName, addon), enabled: !!projectId && !!regionName && !!addon, - throwOnError: true, }); diff --git a/packages/manager/apps/pci-load-balancer/src/api/hook/useFloatingIps.ts b/packages/manager/apps/pci-load-balancer/src/api/hook/useFloatingIps.ts index bd052974633b..706bf221ffa8 100644 --- a/packages/manager/apps/pci-load-balancer/src/api/hook/useFloatingIps.ts +++ b/packages/manager/apps/pci-load-balancer/src/api/hook/useFloatingIps.ts @@ -36,7 +36,6 @@ export const useGetFloatingIps = (projectId: string, region: string) => { queryKey: ['project', projectId, 'region', region, 'floating-ips'], queryFn: () => getFloatingIps(projectId, region), enabled: !!projectId && !!region, - throwOnError: true, }); const defaultFloatingIp = useDefaultFloatingIp(); diff --git a/packages/manager/apps/pci-load-balancer/src/api/hook/useNetwork.tsx b/packages/manager/apps/pci-load-balancer/src/api/hook/useNetwork.tsx index b2d969842fc3..b2ed29c503f3 100644 --- a/packages/manager/apps/pci-load-balancer/src/api/hook/useNetwork.tsx +++ b/packages/manager/apps/pci-load-balancer/src/api/hook/useNetwork.tsx @@ -80,7 +80,6 @@ export const useGetPrivateNetworkSubnets = ( ], queryFn: () => getPrivateNetworkSubnets(projectId, region, networkId), enabled: !!projectId && !!region && !!networkId, - throwOnError: true, }); const list = useMemo(() => { @@ -106,7 +105,6 @@ export const useGetRegionPrivateNetworks = ( queryKey: ['project', projectId, 'region', region, 'networks'], queryFn: () => getRegionPrivateNetworks(projectId, region), enabled: !!projectId && !!region, - throwOnError: true, }); const list = useMemo( diff --git a/packages/manager/apps/pci-load-balancer/src/api/hook/useRegions.ts b/packages/manager/apps/pci-load-balancer/src/api/hook/useRegions.ts index 56c1a05d99dc..c33ffd404b7e 100644 --- a/packages/manager/apps/pci-load-balancer/src/api/hook/useRegions.ts +++ b/packages/manager/apps/pci-load-balancer/src/api/hook/useRegions.ts @@ -12,6 +12,7 @@ export type TRegion = { macroName: string; microName: string; continent: string; + type: string; }; // @TODO this part looks similar to what have been created in the region selector @@ -61,6 +62,7 @@ export const useGetRegions = ( region.name, )}`, ), + type: region.type, }); }); } diff --git a/packages/manager/apps/pci-load-balancer/src/pages/create/Create.page.tsx b/packages/manager/apps/pci-load-balancer/src/pages/create/Create.page.tsx index 46eeeb150a39..5144a99d79a2 100644 --- a/packages/manager/apps/pci-load-balancer/src/pages/create/Create.page.tsx +++ b/packages/manager/apps/pci-load-balancer/src/pages/create/Create.page.tsx @@ -11,7 +11,6 @@ import { useTranslation } from 'react-i18next'; import { ODS_TEXT_LEVEL, ODS_TEXT_SIZE } from '@ovhcloud/ods-components'; import { ODS_THEME_COLOR_INTENT } from '@ovhcloud/ods-common-theming'; import { useEffect } from 'react'; -import { useMedia } from 'react-use'; import { useCreateStore } from './store'; import { useGetPrivateNetworkSubnets, @@ -32,7 +31,6 @@ import { useGetFloatingIps } from '@/api/hook/useFloatingIps'; export default function CreatePage(): JSX.Element { const { me } = useMe(); const { data: addons, isPending: isAddonsPending } = useGetAddons(); - const isMobile = useMedia(`(max-width: 768px)`); const projectHref = useProjectUrl('public-cloud'); @@ -161,7 +159,6 @@ export default function CreatePage(): JSX.Element { isLoading={isRegionsPending} regions={regions} ovhSubsidiary={me?.ovhSubsidiary} - isMobile={isMobile} /> ({ + useProject: vi.fn().mockReturnValue({ data: { project_id: 'project_id' } }), + RegionSelector: () =>
, + usePCICommonContextFactory: vi.fn(), + PCICommonContext: { + Provider: () => <>, + }, +})); vi.mock('react-i18next', async () => { const { ...rest } = await vi.importActual('react-i18next'); @@ -63,35 +62,20 @@ vi.mock('@ovh-ux/manager-react-components', async () => { ); return { ...rest, + useProjectUrl: vi.fn(), StepComponent: vi .fn() .mockImplementation(ActualStepComponent as typeof StepComponent), }; }); -vi.mock('@ovh-ux/manager-pci-common', async () => { - const { - ShapesInputComponent: ActualShapesInputComponent, - ...rest - } = await vi.importActual('@ovh-ux/manager-pci-common'); - return { - ...rest, - ShapesInputComponent: vi - .fn() - .mockImplementation( - ActualShapesInputComponent as typeof ShapesInputComponent, - ), - }; -}); const renderStep = ( { isLoading = false, - isMobile = false, regions = undefined, ovhSubsidiary = undefined, }: Partial = { isLoading: false, - isMobile: false, regions: undefined, ovhSubsidiary: undefined, }, @@ -99,7 +83,6 @@ const renderStep = ( render( , @@ -128,7 +111,7 @@ describe('RegionStep', () => { const call = calls[calls.length - 1][0] as TStepProps; expect(call.title).toBe( - 'load-balancer/create | octavia_load_balancer_create_region_title', + 'load-balancer/create,pci-common | octavia_load_balancer_create_region_title', ); expect(call.isOpen).toBe(true); @@ -140,12 +123,12 @@ describe('RegionStep', () => { expect(call.order).toBe(2); expect(call.next.label).toBe( - 'pci-common | common_stepper_next_button_label', + 'load-balancer/create,pci-common | pci-common:common_stepper_next_button_label', ); expect(call.next.isDisabled).toBe(true); expect(call.edit.label).toBe( - 'pci-common | common_stepper_modify_this_step', + 'load-balancer/create,pci-common | pci-common:common_stepper_modify_this_step', ); }); @@ -153,12 +136,12 @@ describe('RegionStep', () => { const { getByText } = renderStep(); expect( getByText( - 'load-balancer/create | octavia_load_balancer_create_region_intro', + 'load-balancer/create,pci-common | octavia_load_balancer_create_region_intro', ), ).toBeInTheDocument(); expect( getByText( - 'load-balancer/create | octavia_load_balancer_create_region_link', + 'load-balancer/create,pci-common | octavia_load_balancer_create_region_link', ), ).toBeInTheDocument(); }); @@ -199,225 +182,6 @@ describe('RegionStep', () => { expect(getByTestId('spinner')).toBeInTheDocument(); }); - - describe('isLoading is false', () => { - beforeAll(() => { - ((ShapesInputComponent as unknown) as Mock).mockImplementationOnce( - () =>
, - ); - }); - it('should show input if regions are not pending and data is defined', () => { - const regions: TRegion[] = [ - { name: 'test', isEnabled: true, continent: 'Europe' }, - { name: 'test2', isEnabled: true, continent: 'Asia' }, - ] as Array; - - const { result } = renderStore(); - - act(() => result.current.set.addon({ code: 's' } as TAddon)); - - renderStep({ regions: new Map([['s', regions]]) }); - - const { calls } = (ShapesInputComponent as Mock).mock; - const call = calls[calls.length - 1][0] as TShapesInputProps; - - expect(call.items).toEqual(regions); - expect(call.value).toBe(null); - - expect(call.item.LabelComponent).toEqual(LabelComponent); - expect(call.item.getId({ name: 'test' } as TRegion)).toBe('test'); - expect(call.item.isDisabled({ isEnabled: true } as TRegion)).toBe( - false, - ); - - expect(call.stack.by({ macroName: 'test' } as TRegion)).toBe('test'); - expect(call.stack.by({} as TRegion)).toBe(''); - expect(call.stack.LabelComponent).toEqual(StackLabelComponent); - expect(call.stack.TitleComponent).toEqual(StackTitleComponent); - - expect(call.group.by({ continent: 'Europe' } as TRegion)).toBe( - 'Europe', - ); - expect(call.group.LabelComponent).toEqual(GroupLabelComponent); - }); - }); - }); - }); - - describe('Actions', () => { - beforeAll(() => { - (ShapesInputComponent as Mock).mockImplementationOnce(() => ( -
- )); - }); - - describe('next', () => { - describe('render', () => { - test('Next button should be disabled if region is not set', () => { - const { getByText } = renderStep(); - - const nextButton = getByText( - 'pci-common | common_stepper_next_button_label', - ); - expect( - nextButton.attributes.getNamedItem('disabled').value, - ).toBeTruthy(); - }); - - test('Next button should be enabled if region is set', () => { - (ShapesInputComponent as Mock).mockImplementationOnce(() => ( -
- )); - - const { result } = renderStore(); - act(() => result.current.set.region({} as TRegion)); - - const { getByText } = renderStep(); - const nextButton = getByText( - 'pci-common | common_stepper_next_button_label', - ); - expect( - nextButton.attributes.getNamedItem('disabled')?.value, - ).toBeFalsy(); - }); - }); - describe('click', () => { - beforeEach(() => { - const { result } = renderStore(); - act(() => { - result.current.set.region({} as TRegion); - }); - }); - it('Should track on next click', async () => { - (ShapesInputComponent as Mock).mockImplementationOnce(() => ( -
- )); - const trackStepSpy = vi.fn(); - - (useTracking as Mock).mockImplementationOnce(() => ({ - trackStep: trackStepSpy, - })); - - const { result } = renderStore(); - - act(() => { - result.current.set.region({} as TRegion); - }); - - const { getByText } = renderStep(); - - const nextButton = getByText( - 'pci-common | common_stepper_next_button_label', - ); - - act(() => nextButton.click()); - - expect(trackStepSpy).toHaveBeenCalledWith(2); - }); - - it('Should prepare next step on next click', async () => { - (ShapesInputComponent as Mock).mockImplementationOnce(() => ( -
- )); - - const { result } = renderStore(); - - act(() => { - result.current.set.region({} as TRegion); - }); - - const { getByText } = renderStep(); - - const nextButton = getByText( - 'pci-common | common_stepper_next_button_label', - ); - - const { check, lock, open } = { ...result.current }; - - result.current.check = vi.fn(); - result.current.lock = vi.fn(); - result.current.open = vi.fn(); - - act(() => nextButton.click()); - - expect(result.current.check).toHaveBeenCalledWith(StepsEnum.REGION); - expect(result.current.lock).toHaveBeenCalledWith(StepsEnum.REGION); - expect(result.current.open).toHaveBeenCalledWith(StepsEnum.IP); - - result.current.check = check; - result.current.lock = lock; - result.current.open = open; - }); - }); - }); - - describe('edit', () => { - describe('render', () => { - it('should not display if step is not checked', () => { - const { queryByText } = renderStep(); - - const editButton = queryByText( - 'pci-common | common_stepper_modify_this_step', - ); - expect(editButton).not.toBeInTheDocument(); - }); - it('should have the right label', () => { - const { result } = renderStore(); - act(() => result.current.lock(StepsEnum.REGION)); - - ((OsdsLink as unknown) as Mock).mockImplementation( - ({ href, ...props }) => ( - - ), - ); - - const { queryByText } = renderStep(); - - const editButton = queryByText( - 'pci-common | common_stepper_modify_this_step', - ); - - expect(editButton).toBeInTheDocument(); - }); - }); - - describe('click', () => { - it('should prepare steps on click', () => { - const { result } = renderStore(); - - const { unlock, uncheck, open, reset } = { ...result.current }; - - act(() => result.current.lock(StepsEnum.REGION)); - - result.current.unlock = vi.fn(); - result.current.uncheck = vi.fn(); - result.current.open = vi.fn(); - result.current.reset = vi.fn(); - - const { getByText } = renderStep(); - - const editButton = getByText( - 'pci-common | common_stepper_modify_this_step', - ); - - act(() => editButton.click()); - - expect(result.current.unlock).toHaveBeenCalledWith(StepsEnum.REGION); - expect(result.current.uncheck).toHaveBeenCalledWith(StepsEnum.REGION); - expect(result.current.open).toHaveBeenCalledWith(StepsEnum.REGION); - expect(result.current.reset).toHaveBeenCalledWith( - StepsEnum.IP, - StepsEnum.NETWORK, - StepsEnum.INSTANCE, - StepsEnum.NAME, - ); - - result.current.unlock = unlock; - result.current.uncheck = uncheck; - result.current.open = open; - result.current.reset = reset; - }); - }); }); }); }); diff --git a/packages/manager/apps/pci-load-balancer/src/pages/create/steps/region/RegionStep.tsx b/packages/manager/apps/pci-load-balancer/src/pages/create/steps/region/RegionStep.tsx index a5b858275145..3761fabc43f8 100644 --- a/packages/manager/apps/pci-load-balancer/src/pages/create/steps/region/RegionStep.tsx +++ b/packages/manager/apps/pci-load-balancer/src/pages/create/steps/region/RegionStep.tsx @@ -1,145 +1,185 @@ +import { useMemo } from 'react'; import { OsdsLink, + OsdsMessage, OsdsSpinner, OsdsText, } from '@ovhcloud/ods-components/react'; -import { ODS_TEXT_LEVEL, ODS_TEXT_SIZE } from '@ovhcloud/ods-components'; +import { + ODS_ICON_NAME, + ODS_TEXT_LEVEL, + ODS_TEXT_SIZE, +} from '@ovhcloud/ods-components'; import { ODS_THEME_COLOR_INTENT } from '@ovhcloud/ods-common-theming'; -import { StepComponent } from '@ovh-ux/manager-react-components'; -import { useTranslation } from 'react-i18next'; -import { ShapesInputComponent } from '@ovh-ux/manager-pci-common'; -import { useEffect, useRef } from 'react'; +import { + StepComponent, + Links, + useProjectUrl, +} from '@ovh-ux/manager-react-components'; +import { Trans, useTranslation } from 'react-i18next'; +import { + RegionSelector, + useProject, + usePCICommonContextFactory, + PCICommonContext, +} from '@ovh-ux/manager-pci-common'; import { TRegion } from '@/api/hook/useRegions'; import { REGION_AVAILABILITY_LINK } from '@/constants'; import { StepsEnum, useCreateStore } from '@/pages/create/store'; import { useTracking } from '@/pages/create/hooks/useTracking'; -import { LabelComponent } from './components/Label.component'; -import { StackLabelComponent } from './components/StackLabel.component'; -import { GroupLabelComponent } from './components/GroupLabel.component'; -import { StackTitleComponent } from '@/pages/create/steps/region/components/StackTitle.component'; -import { useColumnsCount } from '@/pages/create/hooks/useColumnsCount'; export type TRegionStepProps = { isLoading: boolean; - isMobile: boolean; - regions: Map; + regions?: Map; ovhSubsidiary: string; }; + +const isRegionWith3AZ = (regions: TRegion[]) => + regions.some((region) => region.type === 'region-3-az'); + export const RegionStep = ({ isLoading, - isMobile, regions, ovhSubsidiary, }: Readonly): JSX.Element => { - const { t: tCommon } = useTranslation('pci-common'); - const { t: tCreate } = useTranslation('load-balancer/create'); - - const columnsCount = useColumnsCount(); + const { t } = useTranslation(['load-balancer/create', 'pci-common']); + const { data: project } = useProject(); + const projectUrl = useProjectUrl('public-cloud'); const { trackStep } = useTracking(); const store = useCreateStore(); - // TODO: remove this once the class is added to step component directly in manager-react-components - useEffect(() => { - const refEl = document.getElementById('ref'); - if (refEl) { - const stepEl = refEl.nextSibling; - if (stepEl) { - const targetEl = stepEl.childNodes.item(1); - - if (targetEl.nodeName === 'DIV') { - const target = targetEl as HTMLDivElement; - if (!target.classList.contains('max-w-[calc(100%-76px)]')) { - target.classList.add('max-w-[calc(100%-76px)]'); - } - } - } - } - }, []); + const has3AZ = useMemo(() => { + const allRegions = regions + ? Array.from(regions, ([, values]) => values) + : []; + return isRegionWith3AZ(allRegions.flat()); + }, [regions]); + const pciCommonProperties = usePCICommonContextFactory({ has3AZ }); return ( - <> -
- { - trackStep(2); + { + trackStep(2); - store.check(StepsEnum.REGION); - store.lock(StepsEnum.REGION); + store.check(StepsEnum.REGION); + store.lock(StepsEnum.REGION); - store.open(StepsEnum.IP); - }, - label: tCommon('common_stepper_next_button_label'), - isDisabled: store.region === null, - }} - edit={{ - action: () => { - store.unlock(StepsEnum.REGION); - store.uncheck(StepsEnum.REGION); - store.open(StepsEnum.REGION); - store.reset( - StepsEnum.IP, - StepsEnum.NETWORK, - StepsEnum.INSTANCE, - StepsEnum.NAME, - ); - }, - label: tCommon('common_stepper_modify_this_step'), - }} - > -
+ store.open(StepsEnum.IP); + }, + label: t('pci-common:common_stepper_next_button_label'), + isDisabled: !store.region?.isEnabled, + }} + edit={{ + action: () => { + store.unlock(StepsEnum.REGION); + store.uncheck(StepsEnum.REGION); + store.open(StepsEnum.REGION); + store.reset( + StepsEnum.IP, + StepsEnum.NETWORK, + StepsEnum.INSTANCE, + StepsEnum.NAME, + ); + }, + label: t('pci-common:common_stepper_modify_this_step'), + }} + > +
+ + {t('octavia_load_balancer_create_region_intro')} + + {t('octavia_load_balancer_create_region_link')} + + +
+ {isLoading ? ( +
+ +
+ ) : ( + + { + store.set.region(undefined); + if (selectedRegion) { + const region = regions + ?.get(store.addon?.code) + ?.find(({ name }) => selectedRegion.name === name); + + store.set.region(region); + } + }} + regionFilter={(region) => + region.isMacro || + regions + ?.get(store.addon?.code) + ?.some(({ name }) => name === region.name) + } + /> + + )} + {store.region?.type === 'region-3-az' && ( + + {t('octavia_load_balancer_create_region_3az_price')} + + + )} + {store.region && !store.region.isEnabled && ( + + - {tCreate('octavia_load_balancer_create_region_intro')}{' '} - - {tCreate('octavia_load_balancer_create_region_link')} - + + ), + }} + /> -
- {isLoading ? ( -
- -
- ) : ( - - items={regions?.get(store.addon?.code) || []} - onInput={(region) => store.set.region(region)} - value={store.region} - columnsCount={columnsCount} - item={{ - LabelComponent, - getId: (item) => item.name, - isDisabled: (item) => !item.isEnabled, - }} - stack={{ - by: (item) => item?.macroName || '', - LabelComponent: StackLabelComponent, - TitleComponent: StackTitleComponent, - }} - group={{ - by: (item) => item.continent, - LabelComponent: GroupLabelComponent, - }} - isMobile={isMobile} - /> - )} -
- + + )} +
); }; diff --git a/packages/manager/apps/pci-load-balancer/src/pages/create/steps/region/components/GroupLabel.component.tsx b/packages/manager/apps/pci-load-balancer/src/pages/create/steps/region/components/GroupLabel.component.tsx deleted file mode 100644 index 4bd3a41ab907..000000000000 --- a/packages/manager/apps/pci-load-balancer/src/pages/create/steps/region/components/GroupLabel.component.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import { OsdsText } from '@ovhcloud/ods-components/react'; -import { ODS_TEXT_LEVEL, ODS_TEXT_SIZE } from '@ovhcloud/ods-components'; -import { ODS_THEME_COLOR_INTENT } from '@ovhcloud/ods-common-theming'; -import { useTranslation } from 'react-i18next'; - -export const GroupLabelComponent = ({ - groupName, - isGroupSelected, - isMobile, -}: { - groupName: string; - isGroupSelected: boolean; - isMobile: boolean; -}) => { - const { t: tRegionsList } = useTranslation('regions-list'); - - const shouldBeBold = isMobile || (isGroupSelected && !isMobile); - - return ( -
- - {groupName || tRegionsList('pci_project_regions_list_continent_all')} - -
- ); -}; diff --git a/packages/manager/apps/pci-load-balancer/src/pages/create/steps/region/components/StackLabel.component.tsx b/packages/manager/apps/pci-load-balancer/src/pages/create/steps/region/components/StackLabel.component.tsx deleted file mode 100644 index ed26951a7bb5..000000000000 --- a/packages/manager/apps/pci-load-balancer/src/pages/create/steps/region/components/StackLabel.component.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import { OsdsText } from '@ovhcloud/ods-components/react'; -import { ODS_TEXT_LEVEL, ODS_TEXT_SIZE } from '@ovhcloud/ods-components'; -import { ODS_THEME_COLOR_INTENT } from '@ovhcloud/ods-common-theming'; -import { TRegion } from '@/api/hook/useRegions'; - -export const StackLabelComponent = ({ - isStackSelected, - stackItems, -}: { - isStackSelected: boolean; - stackItems: TRegion[]; -}) => ( -
- - {stackItems[0].macroName} - -
-); diff --git a/packages/manager/apps/pci-load-balancer/src/pages/create/steps/region/components/StackTitle.component.tsx b/packages/manager/apps/pci-load-balancer/src/pages/create/steps/region/components/StackTitle.component.tsx deleted file mode 100644 index 0ded4a14cd97..000000000000 --- a/packages/manager/apps/pci-load-balancer/src/pages/create/steps/region/components/StackTitle.component.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import { OsdsText } from '@ovhcloud/ods-components/react'; -import { ODS_TEXT_LEVEL, ODS_TEXT_SIZE } from '@ovhcloud/ods-components'; -import { ODS_THEME_COLOR_INTENT } from '@ovhcloud/ods-common-theming'; -import { useTranslation } from 'react-i18next'; - -export const StackTitleComponent = () => { - const { t: tRegionsList } = useTranslation('regions-list'); - return ( -
- - {tRegionsList('pci_project_regions_list_region')} - -
- ); -}; diff --git a/yarn.lock b/yarn.lock index 5f6dfae4a8a8..551cf35cc408 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5792,6 +5792,16 @@ date-fns "^3.6.0" lodash.isequal "^4.5.0" +"@ovh-ux/manager-pci-common@^0.15.0": + version "0.15.0" + resolved "https://registry.yarnpkg.com/@ovh-ux/manager-pci-common/-/manager-pci-common-0.15.0.tgz#4710e8a17c16b4951844ef82c4cbcccfb275c818" + integrity sha512-+ESEiQXhGKu5Es+ozf5feaVawlKqECzsjNwr9coxNZ31/rH8UQ5YA8xOUUtzJz5huZTfOg6kheySv7UlKQRyKw== + dependencies: + "@ovh-ux/manager-tailwind-config" "^0.2.1" + clsx "2.1.1" + date-fns "^3.6.0" + lodash.isequal "^4.5.0" + "@ovh-ux/manager-react-components@^1.41.1", "@ovh-ux/manager-react-components@^1.41.2": version "1.41.2" resolved "https://registry.yarnpkg.com/@ovh-ux/manager-react-components/-/manager-react-components-1.41.2.tgz#087cacbbff37c594201851f5f27d2a0c524545b5" From 4026ce284454f99caf851000cb484212118c3347 Mon Sep 17 00:00:00 2001 From: CDS Translator Agent Date: Wed, 15 Jan 2025 11:07:30 +0000 Subject: [PATCH 2/2] fix(i18n): add missing translations [CDS 177] Signed-off-by: CDS Translator Agent --- .../load-balancer/create/Messages_de_DE.json | 5 ++- .../load-balancer/create/Messages_en_GB.json | 5 ++- .../load-balancer/create/Messages_es_ES.json | 5 ++- .../load-balancer/create/Messages_fr_CA.json | 5 ++- .../load-balancer/create/Messages_it_IT.json | 5 ++- .../load-balancer/create/Messages_pl_PL.json | 5 ++- .../load-balancer/create/Messages_pt_PT.json | 5 ++- .../create/steps/region/RegionStep.spec.tsx | 19 ++++++----- .../pages/create/steps/region/RegionStep.tsx | 32 ++++++++++--------- 9 files changed, 56 insertions(+), 30 deletions(-) diff --git a/packages/manager/apps/pci-load-balancer/public/translations/load-balancer/create/Messages_de_DE.json b/packages/manager/apps/pci-load-balancer/public/translations/load-balancer/create/Messages_de_DE.json index 05ea5aa22ecd..0e2f3baf0257 100644 --- a/packages/manager/apps/pci-load-balancer/public/translations/load-balancer/create/Messages_de_DE.json +++ b/packages/manager/apps/pci-load-balancer/public/translations/load-balancer/create/Messages_de_DE.json @@ -41,5 +41,8 @@ "octavia_load_balancer_create_name_field_help": "Darf ausschließlich Zahlen, Buchstaben, Unterstriche, Gedankenstriche und Punkte enthalten.", "octavia_load_balancer_create_size_flavour_description_xl": "Ideal für Anwendungen mit hohem Traffic, die eine größere Bandbreite erfordern, um eine hohe Leistung aufrechtzuerhalten.", "octavia_load_balancer_create_size_flavour_description_2xl": "Perfekt für trafficintensive Projekte. Bietet eine hohe Bandbreitenkapazität für starke Leistung.", - "octavia_load_balancer_create_size_flavour_description_3xl": "Konzipiert für kritische Umgebungen mit hohem Traffic. Gewährleistet maximale Leistung dank großer Bandbreite." + "octavia_load_balancer_create_size_flavour_description_3xl": "Konzipiert für kritische Umgebungen mit hohem Traffic. Gewährleistet maximale Leistung dank großer Bandbreite.", + "octavia_load_balancer_create_private_network": "In der ausgewählten Region ist kein privates Netzwerk vorhanden. Stellen Sie sicher, dass vor der Erstellung des Loadbalancers.", + "octavia_load_balancer_create_private_network_label": "Ein privates Netzwerk erstellen", + "octavia_load_balancer_create_region_3az_price": "Loadbalancer befindet sich derzeit in der Beta-Phase in der Pariser Zone (EU-WEST-PAR) und ist daher in dieser Zeit kostenlos." } diff --git a/packages/manager/apps/pci-load-balancer/public/translations/load-balancer/create/Messages_en_GB.json b/packages/manager/apps/pci-load-balancer/public/translations/load-balancer/create/Messages_en_GB.json index 10c9738c2332..d89c2e32287e 100644 --- a/packages/manager/apps/pci-load-balancer/public/translations/load-balancer/create/Messages_en_GB.json +++ b/packages/manager/apps/pci-load-balancer/public/translations/load-balancer/create/Messages_en_GB.json @@ -41,5 +41,8 @@ "octavia_load_balancer_create_name_field_help": "May contain numbers, letters, underscores, dashes and full stops only.", "octavia_load_balancer_create_size_flavour_description_xl": "An excellent choice for high traffic applications requiring extra bandwidth for optimal performance.", "octavia_load_balancer_create_size_flavour_description_2xl": "Ideal for projects with high traffic volume, as it provides ample bandwidth for consistent performance.", - "octavia_load_balancer_create_size_flavour_description_3xl": "Built for critical systems with heavy traffic, it maximises performance through its high bandwidth capabilities." + "octavia_load_balancer_create_size_flavour_description_3xl": "Built for critical systems with heavy traffic, it maximises performance through its high bandwidth capabilities.", + "octavia_load_balancer_create_private_network": "There are no private networks in the selected region. Make sure before the Load Balancer is created.", + "octavia_load_balancer_create_private_network_label": "create a private network", + "octavia_load_balancer_create_region_3az_price": "Load Balancer is currently in beta phase in the Paris zone (EU-WEST-PAR) and is therefore free during this period." } diff --git a/packages/manager/apps/pci-load-balancer/public/translations/load-balancer/create/Messages_es_ES.json b/packages/manager/apps/pci-load-balancer/public/translations/load-balancer/create/Messages_es_ES.json index a87d79690003..979053c2133b 100644 --- a/packages/manager/apps/pci-load-balancer/public/translations/load-balancer/create/Messages_es_ES.json +++ b/packages/manager/apps/pci-load-balancer/public/translations/load-balancer/create/Messages_es_ES.json @@ -41,5 +41,8 @@ "octavia_load_balancer_create_name_field_help": "Solo debe contener números, letras, guiones, guiones bajos o puntos.", "octavia_load_balancer_create_size_flavour_description_xl": "Perfecto para aplicaciones con mucho tráfico que requieren un ancho de banda superior para mantener un alto rendimiento.", "octavia_load_balancer_create_size_flavour_description_2xl": "Perfecto para proyectos de tráfico muy exigentes. Ofrecen una gran capacidad de ancho de banda para un rendimiento constante.", - "octavia_load_balancer_create_size_flavour_description_3xl": "Diseñado para entornos críticos con mucho tráfico. Ofrece el máximo rendimiento gracias al ancho de banda ampliado." + "octavia_load_balancer_create_size_flavour_description_3xl": "Diseñado para entornos críticos con mucho tráfico. Ofrece el máximo rendimiento gracias al ancho de banda ampliado.", + "octavia_load_balancer_create_private_network": "No hay ninguna red privada en la región seleccionada. Asegúrese de antes de crear el Load Balancer.", + "octavia_load_balancer_create_private_network_label": "crear una red privada", + "octavia_load_balancer_create_region_3az_price": "Load Balancer está actualmente en fase beta en la zona de París (EU-WEST-PAR) y, por lo tanto, es gratuito durante este período." } diff --git a/packages/manager/apps/pci-load-balancer/public/translations/load-balancer/create/Messages_fr_CA.json b/packages/manager/apps/pci-load-balancer/public/translations/load-balancer/create/Messages_fr_CA.json index 47e5dc1994e8..d70c2a4ffd62 100644 --- a/packages/manager/apps/pci-load-balancer/public/translations/load-balancer/create/Messages_fr_CA.json +++ b/packages/manager/apps/pci-load-balancer/public/translations/load-balancer/create/Messages_fr_CA.json @@ -41,5 +41,8 @@ "octavia_load_balancer_create_name_field_label": "Nom du Load Balancer", "octavia_load_balancer_create_name_field_help": "Doit uniquement contenir des nombres, lettres, underscores, tirets ou points.", "octavia_load_balancer_create_submit": "Créer un Load Balancer", - "octavia_load_balancer_create_banner": "Votre Load Balancer est en cours de création. Cela ne prendra que quelques minutes." + "octavia_load_balancer_create_banner": "Votre Load Balancer est en cours de création. Cela ne prendra que quelques minutes.", + "octavia_load_balancer_create_private_network": "Il n'existe aucun réseau privé dans la région sélectionnée. Assurez-vous de avant la création du Load Balancer.", + "octavia_load_balancer_create_private_network_label": "créer un réseau privé", + "octavia_load_balancer_create_region_3az_price": "Load Balancer est actuellement en phase Beta dans la zone Paris (EU-WEST-PAR) et est donc gratuite durant cette période." } diff --git a/packages/manager/apps/pci-load-balancer/public/translations/load-balancer/create/Messages_it_IT.json b/packages/manager/apps/pci-load-balancer/public/translations/load-balancer/create/Messages_it_IT.json index ca51aa7da16a..9280ab5a6135 100644 --- a/packages/manager/apps/pci-load-balancer/public/translations/load-balancer/create/Messages_it_IT.json +++ b/packages/manager/apps/pci-load-balancer/public/translations/load-balancer/create/Messages_it_IT.json @@ -41,5 +41,8 @@ "octavia_load_balancer_create_name_field_help": "Può contenere esclusivamente numeri, lettere, underscore, trattini o punti.", "octavia_load_balancer_create_size_flavour_description_xl": "Ideale per applicazioni a forte traffico che richiedono una banda passante superiore per mantenere prestazioni elevate.", "octavia_load_balancer_create_size_flavour_description_2xl": "Perfetto per progetti esigenti in termini di traffico, grazie a un’elevata capacità di banda passante che permette di ottenere prestazioni costanti.", - "octavia_load_balancer_create_size_flavour_description_3xl": "Progettato per ambienti critici con traffico massivo, grazie a una banda passante estesa che permette di garantire prestazioni massime." + "octavia_load_balancer_create_size_flavour_description_3xl": "Progettato per ambienti critici con traffico massivo, grazie a una banda passante estesa che permette di garantire prestazioni massime.", + "octavia_load_balancer_create_private_network": "Nella Region selezionata non sono presenti reti private. Assicurati di prima della creazione del Load Balancer.", + "octavia_load_balancer_create_private_network_label": "creare una rete privata", + "octavia_load_balancer_create_region_3az_price": "Load Balancer è attualmente in fase Beta nella zona di Parigi (EU-WEST-PAR) ed è quindi gratuito durante questo periodo." } diff --git a/packages/manager/apps/pci-load-balancer/public/translations/load-balancer/create/Messages_pl_PL.json b/packages/manager/apps/pci-load-balancer/public/translations/load-balancer/create/Messages_pl_PL.json index 9b524d6da0f1..8d184c5bc24f 100644 --- a/packages/manager/apps/pci-load-balancer/public/translations/load-balancer/create/Messages_pl_PL.json +++ b/packages/manager/apps/pci-load-balancer/public/translations/load-balancer/create/Messages_pl_PL.json @@ -41,5 +41,8 @@ "octavia_load_balancer_create_name_field_help": "Może zawierać jedynie cyfry, litery, podkreślenia, myślniki lub kropki.", "octavia_load_balancer_create_size_flavour_description_xl": "Idealna dla aplikacji generujących duży ruch, które potrzebują zwiększonej przepustowości, aby utrzymać wysoką wydajność.", "octavia_load_balancer_create_size_flavour_description_2xl": "Idealna do realizacji projektów generujących bardzo duży ruch, zapewnia wysoką przepustowość i stałą wydajność.", - "octavia_load_balancer_create_size_flavour_description_3xl": "Zaprojektowana dla środowisk o krytycznym znaczeniu generujących duży ruch, gwarantuje maksymalną wydajność dzięki zwiększonej przepustowości." + "octavia_load_balancer_create_size_flavour_description_3xl": "Zaprojektowana dla środowisk o krytycznym znaczeniu generujących duży ruch, gwarantuje maksymalną wydajność dzięki zwiększonej przepustowości.", + "octavia_load_balancer_create_private_network": "Brak prywatnej sieci w wybranym regionie. Upewnij się, że przed utworzeniem Load Balancera.", + "octavia_load_balancer_create_private_network_label": "Utwórz prywatną sieć", + "octavia_load_balancer_create_region_3az_price": "Load Balancer znajduje się obecnie w fazie beta w strefie paryskiej (EU-WEST-PAR) i w tym czasie jest bezpłatny." } diff --git a/packages/manager/apps/pci-load-balancer/public/translations/load-balancer/create/Messages_pt_PT.json b/packages/manager/apps/pci-load-balancer/public/translations/load-balancer/create/Messages_pt_PT.json index c7f758f092e3..6af210cef5a5 100644 --- a/packages/manager/apps/pci-load-balancer/public/translations/load-balancer/create/Messages_pt_PT.json +++ b/packages/manager/apps/pci-load-balancer/public/translations/load-balancer/create/Messages_pt_PT.json @@ -41,5 +41,8 @@ "octavia_load_balancer_create_name_field_help": "Deve apenas conter algarismos, letras, underscores, traços ou pontos.", "octavia_load_balancer_create_size_flavour_description_xl": "Ideal para aplicações de elevado tráfego que requerem uma largura de banda acrescida para manter um desempenho elevado.", "octavia_load_balancer_create_size_flavour_description_2xl": "Perfeito para projetos que exigem um elevado nível de tráfego, proporcionando uma elevada capacidade de largura de banda para um desempenho robusto.", - "octavia_load_balancer_create_size_flavour_description_3xl": "Concebido para ambientes críticos com grande tráfego, assegurando o máximo desempenho graças a uma elevada largura de banda." + "octavia_load_balancer_create_size_flavour_description_3xl": "Concebido para ambientes críticos com grande tráfego, assegurando o máximo desempenho graças a uma elevada largura de banda.", + "octavia_load_balancer_create_private_network": "Não existe nenhuma rede privada na região selecionada. Certifique-se de que antes de o Load Balancer ser criado.", + "octavia_load_balancer_create_private_network_label": "criar uma rede privada", + "octavia_load_balancer_create_region_3az_price": "O Load Balancer está atualmente em fase Beta na zona de Paris (EU-WEST-PAR) e é, portanto, gratuito durante esse período." } diff --git a/packages/manager/apps/pci-load-balancer/src/pages/create/steps/region/RegionStep.spec.tsx b/packages/manager/apps/pci-load-balancer/src/pages/create/steps/region/RegionStep.spec.tsx index 6ebfd43be3b4..4b5623294068 100644 --- a/packages/manager/apps/pci-load-balancer/src/pages/create/steps/region/RegionStep.spec.tsx +++ b/packages/manager/apps/pci-load-balancer/src/pages/create/steps/region/RegionStep.spec.tsx @@ -1,4 +1,10 @@ import { describe, Mock, vi } from 'vitest'; +import { + ResponseAPIError, + TProject, + useProject, +} from '@ovh-ux/manager-pci-common'; +import { UseQueryResult } from '@tanstack/react-query'; import { StepComponent, TStepProps } from '@ovh-ux/manager-react-components'; import { render, renderHook } from '@testing-library/react'; import { act } from 'react-dom/test-utils'; @@ -8,14 +14,11 @@ import { RegionStep, TRegionStepProps } from './RegionStep'; import { StepsEnum, useCreateStore } from '@/pages/create/store'; import { REGION_AVAILABILITY_LINK } from '@/constants'; -vi.mock('@ovh-ux/manager-pci-common', () => ({ - useProject: vi.fn().mockReturnValue({ data: { project_id: 'project_id' } }), - RegionSelector: () =>
, - usePCICommonContextFactory: vi.fn(), - PCICommonContext: { - Provider: () => <>, - }, -})); +vi.mock('@ovh-ux/manager-pci-common'); + +vi.mocked(useProject).mockReturnValue({ + data: { project_id: 'project_id' }, +} as UseQueryResult); vi.mock('react-i18next', async () => { const { ...rest } = await vi.importActual('react-i18next'); diff --git a/packages/manager/apps/pci-load-balancer/src/pages/create/steps/region/RegionStep.tsx b/packages/manager/apps/pci-load-balancer/src/pages/create/steps/region/RegionStep.tsx index 3761fabc43f8..c96c266adde5 100644 --- a/packages/manager/apps/pci-load-balancer/src/pages/create/steps/region/RegionStep.tsx +++ b/packages/manager/apps/pci-load-balancer/src/pages/create/steps/region/RegionStep.tsx @@ -22,6 +22,7 @@ import { useProject, usePCICommonContextFactory, PCICommonContext, + TLocalisation, } from '@ovh-ux/manager-pci-common'; import { TRegion } from '@/api/hook/useRegions'; import { REGION_AVAILABILITY_LINK } from '@/constants'; @@ -51,12 +52,22 @@ export const RegionStep = ({ const store = useCreateStore(); const has3AZ = useMemo(() => { - const allRegions = regions - ? Array.from(regions, ([, values]) => values) - : []; + const allRegions = regions ? [...regions.values()] : []; return isRegionWith3AZ(allRegions.flat()); }, [regions]); - const pciCommonProperties = usePCICommonContextFactory({ has3AZ }); + + const metaProps = usePCICommonContextFactory({ has3AZ }); + + const handleSelectRegion = (selectedRegion: TLocalisation) => { + store.set.region(null); + if (selectedRegion) { + const region = regions + ?.get(store.addon?.code) + ?.find(({ name }) => selectedRegion.name === name); + + store.set.region(region); + } + }; return (
) : ( - + { - store.set.region(undefined); - if (selectedRegion) { - const region = regions - ?.get(store.addon?.code) - ?.find(({ name }) => selectedRegion.name === name); - - store.set.region(region); - } - }} + onSelectRegion={handleSelectRegion} regionFilter={(region) => region.isMacro || regions