From 11b006656f8c087369fce30a40d93f65f23ff5fa Mon Sep 17 00:00:00 2001 From: Simon Chaumet Date: Fri, 20 Dec 2024 16:45:20 +0100 Subject: [PATCH] feat(pci-block-storage): add deploy zone ref: TAPC-2112 Signed-off-by: Simon Chaumet --- .../translations/add/Messages_fr_FR.json | 11 ++- .../pci-block-storage/src/api/data/catalog.ts | 95 +++++++++++++++++++ .../src/api/hooks/useCatalog.ts | 10 ++ .../api/hooks/useConsumptionVolumesAddon.ts | 47 --------- .../new/components/CapacityStep.component.tsx | 4 +- .../new/components/DeploymentModeStep.tsx | 77 +++++++++++++++ .../pages/new/components/HighSpeedV2Infos.tsx | 11 ++- .../new/components/LocationStep.component.tsx | 75 ++++++++++++--- .../pages/new/components/PriceEstimate.tsx | 4 +- .../components/ValidationStep.component.tsx | 5 +- .../components/VolumeTypeStep.component.tsx | 43 ++++----- .../src/pages/new/form.type.ts | 4 +- .../src/pages/new/hooks/useVolumeStepper.ts | 5 +- .../src/website/ovhWebsiteMapper.ts | 36 +++++++ .../images-list/images-list.controller.js | 2 + .../instance/edit/edit.controller.js | 6 ++ 16 files changed, 334 insertions(+), 101 deletions(-) delete mode 100644 packages/manager/apps/pci-block-storage/src/api/hooks/useConsumptionVolumesAddon.ts create mode 100644 packages/manager/apps/pci-block-storage/src/pages/new/components/DeploymentModeStep.tsx create mode 100644 packages/manager/apps/pci-block-storage/src/website/ovhWebsiteMapper.ts diff --git a/packages/manager/apps/pci-block-storage/public/translations/add/Messages_fr_FR.json b/packages/manager/apps/pci-block-storage/public/translations/add/Messages_fr_FR.json index 2bdfa71cbe03..8aeb33d3b72f 100644 --- a/packages/manager/apps/pci-block-storage/public/translations/add/Messages_fr_FR.json +++ b/packages/manager/apps/pci-block-storage/public/translations/add/Messages_fr_FR.json @@ -25,5 +25,14 @@ "pci_projects_project_storages_blocks_add_save_form": "Création du volume en cours", "pci_projects_project_storages_blocks_add_error_query": "Une erreur est survenue lors de la récupération des régions : {{ message }}", "pci_projects_project_storages_blocks_add_success_message": "Le volume {{volume}} a été ajouté", - "pci_projects_project_storages_blocks_add_error_post": "Une erreur est survenue lors de l'ajout du volume {{ volume }} : {{ message }}" + "pci_projects_project_storages_blocks_add_error_post": "Une erreur est survenue lors de l'ajout du volume {{ volume }} : {{ message }}", + "pci_projects_project_storages_blocks_add_deployment_mode_title": "Sélectionnez un mode de déploiement", + "pci_projects_project_storages_blocks_add_deployment_mode_description": "Sélectionnez la configuration optimale pour garantir la disponibilité, la résilience et la latence appropriée de vos données en fonction de vos cas d'usage. En savoir plus", + "pci_projects_project_storages_blocks_add_deployment_mode_title_1AZ": "Région 1-AZ", + "pci_projects_project_storages_blocks_add_deployment_mode_description_1AZ": "Déploiement résilient et économique sur 1 zone de disponibilité.", + "pci_projects_project_storages_blocks_add_deployment_mode_title_3AZ": "Région 3-AZ", + "pci_projects_project_storages_blocks_add_deployment_mode_description_3AZ": "Déploiement haute résilience/haute disponibilité pour vos applications critiques sur 3 zones de disponibilité.", + "pci_projects_project_storages_blocks_add_deployment_mode_title_LZ": "Local Zone", + "pci_projects_project_storages_blocks_add_deployment_mode_description_LZ": "Déploiement de vos applications au plus près de vos utilisatrices et utilisateurs pour une faible latence et la résidence des données.", + "pci_projects_project_storages_blocks_add_deployment_mode_price_from": "A partir de {{price}} HT/Go/heure" } diff --git a/packages/manager/apps/pci-block-storage/src/api/data/catalog.ts b/packages/manager/apps/pci-block-storage/src/api/data/catalog.ts index 192f6048ebd2..21e8bfd50398 100644 --- a/packages/manager/apps/pci-block-storage/src/api/data/catalog.ts +++ b/packages/manager/apps/pci-block-storage/src/api/data/catalog.ts @@ -1,3 +1,6 @@ +import { TAddon } from '@ovh-ux/manager-pci-common'; +import { v6 } from '@ovh-ux/manager-core-api'; + export type TPricing = { capacities: string[]; mode: string; @@ -26,3 +29,95 @@ export type TPricing = { promotions: unknown[]; engagementConfiguration?: unknown; }; + +export type TRegionGroup = { + name: string; + tags: string[]; +}; + +export type TModelGroup = { + name: string; + type: string; + tags: string[]; +}; + +export type TRegion = { + name: string; + type: '3-az' | 'region' | 'localzone'; + availabilityZone: string[]; + isInMaintenance: boolean; + isUp: boolean; + isActivated: boolean; + country: string; + regionGroup: string; + datacenter: string; +}; + +export type TVolumePricing = Omit< + TAddon['pricings'][number], + 'interval' | 'intervalUnit' +> & { + regions: TRegion['name'][]; + interval: 'day' | 'hour' | 'month' | 'none'; +}; + +export type TVolumeAddon = Omit & { + groups: TRegionGroup['name'][]; + pricings: TVolumePricing[]; + pricingType: 'consumption' | string; +}; + +export type TVolumeCatalog = { + modelsGroups: TModelGroup[]; + regionsGroups: TRegionGroup[]; + regions: TRegion[]; + models: TVolumeAddon[]; +}; + +export const getVolumeCatalog = async ( + projectId: string, +): Promise => + (await v6.get(`/cloud/project/${projectId}/catalog/volume`)) + .data; + +export function getLeastPrice(pricings: TVolumePricing[]) { + return pricings.reduce( + (leastPrice, p) => + leastPrice === null ? p.price : Math.min(p.price, leastPrice), + null, + ); +} + +export function mapPricesToGroups( + groups: TRegionGroup[], + regions: TRegion[], + models: TVolumeAddon[], +): (TRegionGroup & { leastPrice: number })[] { + return groups.map((group) => { + const groupRegions = regions + .filter((r) => r.type === group.name) + .map((r) => r.name); + + return { + ...group, + leastPrice: models + .filter((m) => m.pricingType === 'consumption') + .map((m) => + getLeastPrice( + m.pricings.filter( + (p) => + p.capacities.includes('consumption') && + p.regions.some((r) => groupRegions.includes(r)), + ), + ), + ) + .reduce( + (leastPrice, modelLeastPrice) => + leastPrice === null + ? modelLeastPrice + : Math.min(modelLeastPrice, leastPrice), + null, + ), + }; + }); +} diff --git a/packages/manager/apps/pci-block-storage/src/api/hooks/useCatalog.ts b/packages/manager/apps/pci-block-storage/src/api/hooks/useCatalog.ts index f71c5d1cafad..7b6c2488d34f 100644 --- a/packages/manager/apps/pci-block-storage/src/api/hooks/useCatalog.ts +++ b/packages/manager/apps/pci-block-storage/src/api/hooks/useCatalog.ts @@ -1,12 +1,16 @@ import { useQuery } from '@tanstack/react-query'; import { useMe } from '@ovh-ux/manager-react-components'; import { getCatalog } from '@ovh-ux/manager-pci-common'; +import { getVolumeCatalog } from '@/api/data/catalog'; export const getCatalogQuery = (ovhSubsidiary: string) => ({ queryKey: ['catalog'], queryFn: () => getCatalog(ovhSubsidiary), }); +/** + * @deprecated use {@link useVolumeCatalog} instead + */ export const useCatalog = () => { const { me } = useMe(); return useQuery({ @@ -14,3 +18,9 @@ export const useCatalog = () => { enabled: !!me, }); }; + +export const useVolumeCatalog = (projectId: string) => + useQuery({ + queryKey: ['projects', projectId, 'catalog', 'volume'], + queryFn: () => getVolumeCatalog(projectId), + }); diff --git a/packages/manager/apps/pci-block-storage/src/api/hooks/useConsumptionVolumesAddon.ts b/packages/manager/apps/pci-block-storage/src/api/hooks/useConsumptionVolumesAddon.ts deleted file mode 100644 index 9e041a711423..000000000000 --- a/packages/manager/apps/pci-block-storage/src/api/hooks/useConsumptionVolumesAddon.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { useEffect, useState } from 'react'; -import { TCatalog } from '@ovh-ux/manager-pci-common'; -import { TRegion } from '@/api/data/regions'; -import { useCatalog } from '@/api/hooks/useCatalog'; -import { useProjectsAvailableVolumes } from '@/api/hooks/useProjectsAvailableVolumes'; - -export const useConsumptionVolumesAddon = ( - projectId: string, - region: TRegion, -) => { - const [state, setState] = useState(undefined); - - const { data: catalog, isPending: isCatalogPending } = useCatalog(); - const { - data: availableVolumes, - isPending: isVolumesPending, - } = useProjectsAvailableVolumes(projectId); - const isPending = isCatalogPending || isVolumesPending; - - useEffect(() => { - if (catalog && availableVolumes && region) { - // Get volumes addons ids - const volumeAddonsIds = catalog.plans - .find((plan) => plan.planCode === 'project') - .addonFamilies.find(({ name }) => name === 'volume').addons; - - // Get volumes addons details - const totalConsumptionVolumeAddons = catalog.addons.filter( - (addon) => - volumeAddonsIds.includes(addon.planCode) && - addon.planCode.includes('consumption'), - ); - - const volumeAddonsIdss = availableVolumes.plans?.filter(({ regions }) => - regions.some(({ name }) => name === region.name), - ); - - setState( - totalConsumptionVolumeAddons.filter(({ planCode }) => - volumeAddonsIdss?.some(({ code }) => code === planCode), - ), - ); - } - }, [catalog, region, availableVolumes]); - - return { volumeTypes: state, isPending }; -}; diff --git a/packages/manager/apps/pci-block-storage/src/pages/new/components/CapacityStep.component.tsx b/packages/manager/apps/pci-block-storage/src/pages/new/components/CapacityStep.component.tsx index 0b4a2d059a92..caa8ddf36ca6 100644 --- a/packages/manager/apps/pci-block-storage/src/pages/new/components/CapacityStep.component.tsx +++ b/packages/manager/apps/pci-block-storage/src/pages/new/components/CapacityStep.component.tsx @@ -22,13 +22,13 @@ import { } from '@ovhcloud/ods-components'; import { useTranslation } from 'react-i18next'; -import { TAddon } from '@ovh-ux/manager-pci-common'; import { PriceEstimate } from '@/pages/new/components/PriceEstimate'; import { HighSpeedV2Infos } from '@/pages/new/components/HighSpeedV2Infos'; import { TLocalisation } from '@/api/hooks/useRegions'; import { StepState } from '@/pages/new/hooks/useStep'; import { useRegionsQuota } from '@/api/hooks/useQuota'; import { useVolumeMaxSize } from '@/api/data/quota'; +import { TVolumeAddon } from '@/api/data/catalog'; export const VOLUME_MIN_SIZE = 10; // 10 Gio export const VOLUME_UNLIMITED_QUOTA = -1; // Should be 10 * 1024 (but API is wrong) @@ -36,7 +36,7 @@ export const VOLUME_UNLIMITED_QUOTA = -1; // Should be 10 * 1024 (but API is wro interface CapacityStepProps { projectId: string; region: TLocalisation; - volumeType: TAddon; + volumeType: TVolumeAddon; step: StepState; onSubmit: (volumeCapacity: number) => void; } diff --git a/packages/manager/apps/pci-block-storage/src/pages/new/components/DeploymentModeStep.tsx b/packages/manager/apps/pci-block-storage/src/pages/new/components/DeploymentModeStep.tsx new file mode 100644 index 000000000000..1dd365639e05 --- /dev/null +++ b/packages/manager/apps/pci-block-storage/src/pages/new/components/DeploymentModeStep.tsx @@ -0,0 +1,77 @@ +import { useParams } from 'react-router-dom'; +import { + OsdsChip, + OsdsSpinner, + OsdsText, +} from '@ovhcloud/ods-components/react'; +import { useTranslation } from 'react-i18next'; +import { ODS_CHIP_SIZE, ODS_SPINNER_SIZE } from '@ovhcloud/ods-components'; +import { useMemo, useState } from 'react'; +import { TilesInputComponent } from '@ovh-ux/manager-react-components'; +import { ODS_THEME_COLOR_INTENT } from '@ovhcloud/ods-common-theming'; +import { mapPricesToGroups, TRegionGroup } from '@/api/data/catalog'; +import { useVolumeCatalog } from '@/api/hooks/useCatalog'; + +export const DeploymentModeStep = () => { + const { t } = useTranslation(['add', 'common']); + const { projectId } = useParams(); + + const { data, isPending } = useVolumeCatalog(projectId); + + const mappedGroups = useMemo( + () => + data + ? mapPricesToGroups(data.regionsGroups, data.regions, data.models) + : [], + [data], + ); + + const [selectedRegionGroup, setSelectedRegionGroup] = useState< + null | ReturnType[number] + >(null); + + // if (isPending) return ; + return ; + + return ( +
+ [number]> + items={mappedGroups} + value={selectedRegionGroup} + onInput={setSelectedRegionGroup} + label={(group) => ( +
+
+ + {t( + `pci_projects_project_storages_blocks_add_deployment_mode_title_${group.name}`, + )} + +
+
+ {group.tags.includes('is_new') ? ( +
+ + {t('common:pci_projects_project_storages_blocks_new')} + + Gratuit +
+ ) : ( + group.leastPrice !== null && + t( + 'pci_projects_project_storages_blocks_add_deployment_mode_price_from', + { price: group.leastPrice }, + ) + )} +
+
+ )} + /> +
+ ); +}; diff --git a/packages/manager/apps/pci-block-storage/src/pages/new/components/HighSpeedV2Infos.tsx b/packages/manager/apps/pci-block-storage/src/pages/new/components/HighSpeedV2Infos.tsx index 9fc2281229b0..fe62528e81ef 100644 --- a/packages/manager/apps/pci-block-storage/src/pages/new/components/HighSpeedV2Infos.tsx +++ b/packages/manager/apps/pci-block-storage/src/pages/new/components/HighSpeedV2Infos.tsx @@ -5,7 +5,7 @@ import { ODS_THEME_TYPOGRAPHY_SIZE, } from '@ovhcloud/ods-common-theming'; import { useTranslation } from 'react-i18next'; -import { TAddon } from '@ovh-ux/manager-pci-common'; +import { TVolumeAddon } from '@/api/data/catalog'; export const HIGHSPEED_V2_PLANCODE = 'volume.high-speed-gen2.consumption'; @@ -17,7 +17,10 @@ export function getDisplayUnit(unit: string) { return unit; } -export function computeBandwidthToAllocate(capacity: number, addon: TAddon) { +export function computeBandwidthToAllocate( + capacity: number, + addon: TVolumeAddon, +) { const { bandwidth } = addon.blobs.technical; const allocatedBandwidth = capacity * bandwidth.level; const maxBandwidthInMb = bandwidth.max * 1000; @@ -27,7 +30,7 @@ export function computeBandwidthToAllocate(capacity: number, addon: TAddon) { : `${maxBandwidthInMb} ${getDisplayUnit(bandwidth.unit)}`; } -export function computeIopsToAllocate(capacity: number, addon: TAddon) { +export function computeIopsToAllocate(capacity: number, addon: TVolumeAddon) { const { volume } = addon.blobs.technical; const allocatedIops = capacity * volume.iops.level; @@ -38,7 +41,7 @@ export function computeIopsToAllocate(capacity: number, addon: TAddon) { export interface HighSpeedV2InfosProps { volumeCapacity: number; - volumeType: TAddon; + volumeType: TVolumeAddon; } export function HighSpeedV2Infos({ diff --git a/packages/manager/apps/pci-block-storage/src/pages/new/components/LocationStep.component.tsx b/packages/manager/apps/pci-block-storage/src/pages/new/components/LocationStep.component.tsx index ddca42059db0..e3014f5cab85 100644 --- a/packages/manager/apps/pci-block-storage/src/pages/new/components/LocationStep.component.tsx +++ b/packages/manager/apps/pci-block-storage/src/pages/new/components/LocationStep.component.tsx @@ -1,16 +1,24 @@ -import { useState } from 'react'; -import { OsdsButton } from '@ovhcloud/ods-components/react'; -import { ODS_BUTTON_SIZE } from '@ovhcloud/ods-components'; +import { useContext, useState } from 'react'; +import { OsdsButton, OsdsLink, OsdsText } from '@ovhcloud/ods-components/react'; +import { + ODS_BUTTON_SIZE, + 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'; +import { Trans, useTranslation } from 'react-i18next'; import { isDiscoveryProject, useProject, RegionSelector, RegionSummary, } from '@ovh-ux/manager-pci-common'; +import { OvhSubsidiary, Subtitle } from '@ovh-ux/manager-react-components'; +import { ShellContext } from '@ovh-ux/manager-react-shell-client'; import { TLocalisation } from '@/api/hooks/useRegions'; import { StepState } from '@/pages/new/hooks/useStep'; +import { DeploymentModeStep } from '@/pages/new/components/DeploymentModeStep'; +import { getBaseUrl } from '@/website/ovhWebsiteMapper'; interface LocationProps { projectId: string; @@ -23,23 +31,62 @@ export function LocationStep({ step, onSubmit, }: Readonly) { - const { t: tStepper } = useTranslation('stepper'); + const { t } = useTranslation(['stepper', 'add']); + const context = useContext(ShellContext); + const { ovhSubsidiary } = context.environment.getUser(); + const [region, setRegion] = useState(undefined); const { data: project } = useProject(); const isDiscovery = isDiscoveryProject(project); const hasRegion = !!region; + return ( <> {hasRegion && step.isLocked && } {(!step.isLocked || isDiscovery) && ( - - r.isMacro || - r.services.some((s) => s.name === 'volume' && s.status === 'UP') - } - /> +
+
+ + {t( + 'add:pci_projects_project_storages_blocks_add_deployment_mode_title', + )} + +
+ + + ), + }} + /> + +
+
+ {/* */} + +
+ + {t('add:pci_projects_project_storages_blocks_add_region_title')} + +
+ + r.isMacro || + r.services.some((s) => s.name === 'volume' && s.status === 'UP') + } + /> +
)} {hasRegion && !step.isLocked && ( onSubmit(region)} > - {tStepper('common_stepper_next_button_label')} + {t('common_stepper_next_button_label')} )} diff --git a/packages/manager/apps/pci-block-storage/src/pages/new/components/PriceEstimate.tsx b/packages/manager/apps/pci-block-storage/src/pages/new/components/PriceEstimate.tsx index 34efc4a64694..5b10326d9aca 100644 --- a/packages/manager/apps/pci-block-storage/src/pages/new/components/PriceEstimate.tsx +++ b/packages/manager/apps/pci-block-storage/src/pages/new/components/PriceEstimate.tsx @@ -6,11 +6,11 @@ import { ODS_THEME_TYPOGRAPHY_SIZE, } from '@ovhcloud/ods-common-theming'; import { useCatalogPrice } from '@ovh-ux/manager-react-components'; -import { TAddon } from '@ovh-ux/manager-pci-common'; +import { TVolumeAddon } from '@/api/data/catalog'; export interface PriceEstimateProps { volumeCapacity: number; - volumeType: TAddon; + volumeType: TVolumeAddon; } const ESTIMATE_MONTHLY_HOURS = 24 * 30; diff --git a/packages/manager/apps/pci-block-storage/src/pages/new/components/ValidationStep.component.tsx b/packages/manager/apps/pci-block-storage/src/pages/new/components/ValidationStep.component.tsx index c5034859a708..2875f3e87fc3 100644 --- a/packages/manager/apps/pci-block-storage/src/pages/new/components/ValidationStep.component.tsx +++ b/packages/manager/apps/pci-block-storage/src/pages/new/components/ValidationStep.component.tsx @@ -4,12 +4,13 @@ import { ODS_THEME_COLOR_INTENT } from '@ovhcloud/ods-common-theming'; import { useNotifications } from '@ovh-ux/manager-react-components'; import { useTranslation } from 'react-i18next'; import { useNavigate } from 'react-router-dom'; -import { PciTrustedZoneBanner, TAddon } from '@ovh-ux/manager-pci-common'; +import { PciTrustedZoneBanner } from '@ovh-ux/manager-pci-common'; import { PriceEstimate } from '@/pages/new/components/PriceEstimate'; +import { TVolumeAddon } from '@/api/data/catalog'; interface ValidationStepProps { volumeCapacity: number; - volumeType: TAddon; + volumeType: TVolumeAddon; onSubmit: () => void; } diff --git a/packages/manager/apps/pci-block-storage/src/pages/new/components/VolumeTypeStep.component.tsx b/packages/manager/apps/pci-block-storage/src/pages/new/components/VolumeTypeStep.component.tsx index 0b9a11cb0b18..1f2841b07b08 100644 --- a/packages/manager/apps/pci-block-storage/src/pages/new/components/VolumeTypeStep.component.tsx +++ b/packages/manager/apps/pci-block-storage/src/pages/new/components/VolumeTypeStep.component.tsx @@ -1,37 +1,28 @@ -import { - OsdsButton, - OsdsSpinner, - OsdsText, - OsdsChip, -} from '@ovhcloud/ods-components/react'; +import { OsdsButton, OsdsText, OsdsChip } from '@ovhcloud/ods-components/react'; import { ODS_THEME_COLOR_INTENT, ODS_THEME_TYPOGRAPHY_LEVEL, ODS_THEME_TYPOGRAPHY_SIZE, } from '@ovhcloud/ods-common-theming'; -import { - ODS_CHIP_SIZE, - ODS_BUTTON_SIZE, - ODS_SPINNER_SIZE, -} from '@ovhcloud/ods-components'; +import { ODS_CHIP_SIZE, ODS_BUTTON_SIZE } from '@ovhcloud/ods-components'; import { TilesInputComponent, useCatalogPrice, } from '@ovh-ux/manager-react-components'; import { useTranslation } from 'react-i18next'; -import { useState } from 'react'; -import { TAddon, TCatalog } from '@ovh-ux/manager-pci-common'; +import { useMemo, useState } from 'react'; import { useTranslateBytes } from '@/pages/new/hooks/useTranslateBytes'; -import { useConsumptionVolumesAddon } from '@/api/hooks/useConsumptionVolumesAddon'; import { StepState } from '@/pages/new/hooks/useStep'; import { TLocalisation } from '@/api/hooks/useRegions'; +import { useVolumeCatalog } from '@/api/hooks/useCatalog'; +import { TVolumeAddon } from '@/api/data/catalog'; export interface VolumeTypeStepProps { projectId: string; region: TLocalisation; step: StepState; - onSubmit: (volumeType: TAddon) => void; + onSubmit: (volumeType: TVolumeAddon) => void; } export function VolumeTypeStep({ @@ -43,30 +34,32 @@ export function VolumeTypeStep({ const { t } = useTranslation('add'); const { t: tStepper } = useTranslation('stepper'); const { t: tCommon } = useTranslation('common'); - const [volumeType, setVolumeType] = useState(undefined); + const [volumeType, setVolumeType] = useState(undefined); const tBytes = useTranslateBytes(); const { getFormattedCatalogPrice } = useCatalogPrice(6, { hideTaxLabel: true, }); - const { volumeTypes, isPending } = useConsumptionVolumesAddon( - projectId, - region, + const { data } = useVolumeCatalog(projectId); + const volumeTypes = useMemo( + () => + data?.models.filter( + (m) => + m.pricingType === 'consumption' && + m.pricings.flatMap((p) => p.regions).includes(region.name), + ) || [], + [data, region], ); const displayedTypes = volumeType && step.isLocked ? [volumeType] : volumeTypes; - if (isPending) { - return ; - } - return ( <> - + value={volumeType} items={displayedTypes || []} - label={(vType: TCatalog['addons'][0]) => ( + label={(vType) => (
({ region: f.region })); }, - submit: (volumeType: TAddon) => { + submit: (volumeType: TVolumeAddon) => { volumeTypeStep.check(); volumeTypeStep.lock(); if ( diff --git a/packages/manager/apps/pci-block-storage/src/website/ovhWebsiteMapper.ts b/packages/manager/apps/pci-block-storage/src/website/ovhWebsiteMapper.ts new file mode 100644 index 000000000000..e0bf36eeca6b --- /dev/null +++ b/packages/manager/apps/pci-block-storage/src/website/ovhWebsiteMapper.ts @@ -0,0 +1,36 @@ +import { OvhSubsidiary } from '@ovh-ux/manager-react-components'; + +export function getBaseUrl(ovhSubsidiary: OvhSubsidiary): string { + switch (ovhSubsidiary) { + case OvhSubsidiary.ASIA: + case OvhSubsidiary.DE: + case OvhSubsidiary.FR: + case OvhSubsidiary.IT: + case OvhSubsidiary.NL: + case OvhSubsidiary.PL: + case OvhSubsidiary.PT: + return `https://www.ovhcloud.com/${ovhSubsidiary.toLowerCase()}`; + case OvhSubsidiary.AU: + case OvhSubsidiary.CA: + case OvhSubsidiary.GB: + case OvhSubsidiary.IE: + case OvhSubsidiary.IN: + case OvhSubsidiary.SG: + return `https://www.ovhcloud.com/en-${ovhSubsidiary.toLowerCase()}`; + case OvhSubsidiary.ES: + return 'https://www.ovhcloud.com/es-es'; + case OvhSubsidiary.MA: + case OvhSubsidiary.SN: + case OvhSubsidiary.TN: + return `https://www.ovhcloud.com/fr-${ovhSubsidiary.toLowerCase()}`; + case OvhSubsidiary.QC: + return 'https://www.ovhcloud.com/fr-ca'; + case OvhSubsidiary.US: + return 'https://us.ovhcloud.com'; + case OvhSubsidiary.WS: + return 'https://www.ovhcloud.com/es'; + case OvhSubsidiary.DEFAULT: + default: + return 'https://www.ovhcloud.com/en'; + } +} diff --git a/packages/manager/modules/pci/src/components/project/images-list/images-list.controller.js b/packages/manager/modules/pci/src/components/project/images-list/images-list.controller.js index 0bfd1361e51f..89d92f0d3527 100644 --- a/packages/manager/modules/pci/src/components/project/images-list/images-list.controller.js +++ b/packages/manager/modules/pci/src/components/project/images-list/images-list.controller.js @@ -182,6 +182,7 @@ export default class ImagesListController { } onImageChange(image, distribution) { + console.log('images list - calling image change in', image, distribution); if (distribution) { this.distribution = distribution; } @@ -195,6 +196,7 @@ export default class ImagesListController { this.selectedImage = image; if (this.onChange) { this.onChange({ image: this.selectedImage }); + console.log('images list - calling parent onChange'); } } diff --git a/packages/manager/modules/pci/src/projects/project/instances/instance/edit/edit.controller.js b/packages/manager/modules/pci/src/projects/project/instances/instance/edit/edit.controller.js index af5c9997035e..337107a6232c 100644 --- a/packages/manager/modules/pci/src/projects/project/instances/instance/edit/edit.controller.js +++ b/packages/manager/modules/pci/src/projects/project/instances/instance/edit/edit.controller.js @@ -91,6 +91,12 @@ export default class PciInstanceEditController { } onImageChange(image) { + console.log( + 'edit - calling onImageChange', + image, + this.defaultImage, + image ? image.isBackup() : null, + ); if (image) { if (!this.defaultImage) { this.defaultImage = image;