Skip to content

Commit 9b5933d

Browse files
feat(pci-instances): add image section with helper drawer
ref: #TAPC-4614, #TAPC-4652 Signed-off-by: tsiorifamonjena <[email protected]>
1 parent 37eddd2 commit 9b5933d

File tree

8 files changed

+190
-16
lines changed

8 files changed

+190
-16
lines changed

packages/manager/apps/pci-instances/public/translations/common/Messages_fr_FR.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,6 @@
2525
"pci_instances_common_instance_continent_north_africa": "Afrique du Nord",
2626
"pci_instances_common_instance_continent_south_east_asia": "Asie du Sud Est",
2727
"pci_instances_common_instance_continent_oceania": "Océanie",
28-
"pci_instances_common_instance_continent_all": "Tous"
28+
"pci_instances_common_instance_continent_all": "Tous",
29+
"pci_instances_common_more_info": "Plus d'informations"
2930
}

packages/manager/apps/pci-instances/public/translations/creation/Messages_fr_FR.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,5 +56,9 @@
5656
"pci_instance_creation_select_new_region_title": "Choisir une nouvelle région",
5757
"pci_instance_creation_select_new_region_label": "Selectionner une région",
5858
"pci_instance_creation_select_new_region_for_flavor": "Ce modèle <strong>({{ flavor }})</strong> n'est pas disponible dans votre <strong>région selectionnée</strong>. Vous pouvez toutefois le sélectionner mais vous devrez choisir une autre région disponible pour ce modèle.",
59-
"pci_instance_creation_select_new_region": "Choisissez une région"
59+
"pci_instance_creation_select_new_region": "Choisissez une région",
60+
"pci_instance_creation_select_image_title": "Sélectionnez une image",
61+
"pci_instance_creation_select_image_help_title": "Images",
62+
"pci_instance_creation_select_image_help_text": "Les images disponibles à cette étape dépendent des choix opérés lors des étapes précédentes, c'est-à-dire de la compatibilité avec le modèle d'instance et de la disponibilité régionale. Par exemple, si vous souhaitez sélectionner un système d'exploitation Windows et qu'il n'y a pas de distributions Windows disponibles, vous devez modifier vos choix des étapes précédentes.",
63+
"pci_instance_creation_select_image_life_cycle_help_label": "Cycle de vie d'une distribution chez OVH"
6064
}

packages/manager/apps/pci-instances/src/hooks/url/useGuideLink.constant.ts

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,40 @@ import { Subsidiary } from '@ovh-ux/manager-config';
22

33
const HELP_ROOT = 'https://www.ovhcloud.com';
44

5+
const HELP_URL = 'https://help.ovhcloud.com/csm';
6+
57
type TGuideLinkGroup = {
68
DEFAULT: string;
79
} & {
810
[key in Subsidiary]?: string;
911
};
1012

11-
type TGuideKey = 'LOCATION' | 'FLAVOR' | 'AVAILABILITY_ZONES';
13+
export type TGuideKey =
14+
| 'LOCATION'
15+
| 'FLAVOR'
16+
| 'AVAILABILITY_ZONES'
17+
| 'DISTRIBUTION_IMAGE'
18+
| 'DISTRIBUTION_IMAGE_LIFE_CYCLE';
1219

1320
export const GUIDE_LINKS: Record<TGuideKey, TGuideLinkGroup> = {
1421
LOCATION: {
15-
DEFAULT:
16-
'https://help.ovhcloud.com/csm/fr-public-cloud-deployments-modes?id=kb_article_view&sysparm_article=KB0066031',
17-
FR:
18-
'https://help.ovhcloud.com/csm/fr-public-cloud-deployments-modes?id=kb_article_view&sysparm_article=KB0066031',
22+
DEFAULT: `${HELP_URL}/fr-public-cloud-deployments-modes?id=kb_article_view&sysparm_article=KB0066031`,
23+
FR: `${HELP_URL}/fr-public-cloud-deployments-modes?id=kb_article_view&sysparm_article=KB0066031`,
1924
},
2025
AVAILABILITY_ZONES: {
21-
DEFAULT:
22-
' https://help.ovhcloud.com/csm/fr-public-cloud-deployments-modes?id=kb_article_view&sysparm_article=KB0066031',
23-
FR:
24-
' https://help.ovhcloud.com/csm/fr-public-cloud-deployments-modes?id=kb_article_view&sysparm_article=KB0066031',
26+
DEFAULT: `${HELP_URL}/fr-public-cloud-deployments-modes?id=kb_article_view&sysparm_article=KB0066031`,
27+
FR: `${HELP_URL}/fr-public-cloud-deployments-modes?id=kb_article_view&sysparm_article=KB0066031`,
2528
},
2629
FLAVOR: {
2730
DEFAULT: `${HELP_ROOT}/fr/public-cloud/virtual-instances/`,
2831
FR: `${HELP_ROOT}/fr/public-cloud/virtual-instances/`,
2932
},
33+
DISTRIBUTION_IMAGE: {
34+
DEFAULT: `${HELP_URL}/fr-public-cloud-compute-getting-started?id=kb_article_view&sysparm_article=KB0051011`,
35+
FR: `${HELP_URL}/fr-public-cloud-compute-getting-started?id=kb_article_view&sysparm_article=KB0051011`,
36+
},
37+
DISTRIBUTION_IMAGE_LIFE_CYCLE: {
38+
DEFAULT: `${HELP_URL}/fr-public-cloud-compute-vps-image-life-cycle?id=kb_article_view&sysparm_article=KB0050802`,
39+
FR: `${HELP_URL}/fr-public-cloud-compute-vps-image-life-cycle?id=kb_article_view&sysparm_article=KB0050802`,
40+
},
3041
};
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import { createContext } from 'react';
2+
import { describe, it, expect, vi } from 'vitest';
3+
import { renderHook, waitFor } from '@testing-library/react';
4+
import { useGuideLink } from './useGuideLink';
5+
import { GUIDE_LINKS, TGuideKey } from './useGuideLink.constant';
6+
7+
const mockGetOvhSubsidiary = vi.hoisted(() => vi.fn());
8+
9+
vi.mock('@ovh-ux/manager-react-shell-client', () => ({
10+
ShellContext: createContext({
11+
environment: {
12+
getUser: mockGetOvhSubsidiary,
13+
},
14+
}),
15+
}));
16+
17+
describe('useGuideLink', () => {
18+
const testCasesSingleKey = [
19+
{
20+
ovhSubsidiary: 'FR',
21+
key: 'FLAVOR' as TGuideKey,
22+
expected: GUIDE_LINKS.FLAVOR.FR,
23+
description: 'returns guide link for valid subsidiary',
24+
},
25+
{
26+
ovhSubsidiary: 'fakeSubsidiary',
27+
key: 'FLAVOR' as TGuideKey,
28+
expected: GUIDE_LINKS.FLAVOR.DEFAULT,
29+
description: 'returns default guide link for unknown subsidiary',
30+
},
31+
];
32+
33+
it.each(testCasesSingleKey)(
34+
'should $description',
35+
async ({ ovhSubsidiary, key, expected }) => {
36+
mockGetOvhSubsidiary.mockReturnValue({ ovhSubsidiary });
37+
38+
const { result } = renderHook(() => useGuideLink(key));
39+
40+
await waitFor(() => {
41+
expect(result.current).toStrictEqual(expected);
42+
});
43+
},
44+
);
45+
46+
const testCasesMultipleKey = [
47+
{
48+
ovhSubsidiary: 'FR',
49+
key: ['FLAVOR', 'DISTRIBUTION_IMAGE'] as TGuideKey[],
50+
expected: {
51+
FLAVOR: GUIDE_LINKS.FLAVOR.FR,
52+
DISTRIBUTION_IMAGE: GUIDE_LINKS.DISTRIBUTION_IMAGE.FR,
53+
},
54+
description: 'returns guide links for valid subsidiary',
55+
},
56+
{
57+
ovhSubsidiary: 'fakeSubsidiary',
58+
key: ['FLAVOR', 'DISTRIBUTION_IMAGE'] as TGuideKey[],
59+
expected: {
60+
FLAVOR: GUIDE_LINKS.FLAVOR.DEFAULT,
61+
DISTRIBUTION_IMAGE: GUIDE_LINKS.DISTRIBUTION_IMAGE.DEFAULT,
62+
},
63+
description: 'returns default guide links for unknown subsidiary',
64+
},
65+
];
66+
67+
it.each(testCasesMultipleKey)(
68+
'should $description',
69+
async ({ ovhSubsidiary, key, expected }) => {
70+
mockGetOvhSubsidiary.mockReturnValue({ ovhSubsidiary });
71+
72+
const { result } = renderHook(() => useGuideLink(key));
73+
74+
await waitFor(() => {
75+
expect(result.current).toStrictEqual(expected);
76+
});
77+
},
78+
);
79+
});
Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,23 @@
11
import { ShellContext } from '@ovh-ux/manager-react-shell-client';
22
import { useContext } from 'react';
3-
import { GUIDE_LINKS } from './useGuideLink.constant';
3+
import { GUIDE_LINKS, TGuideKey } from './useGuideLink.constant';
4+
import { Subsidiary } from '@ovh-ux/manager-config';
45

5-
export const useGuideLink = (name: keyof typeof GUIDE_LINKS) => {
6+
const getGuideLink = (key: TGuideKey, ovhSubsidiary: Subsidiary) =>
7+
GUIDE_LINKS[key][ovhSubsidiary] ?? GUIDE_LINKS[key].DEFAULT;
8+
9+
export function useGuideLink(key: TGuideKey): string;
10+
export function useGuideLink(keys: TGuideKey[]): Record<TGuideKey, string>;
11+
export function useGuideLink(keys: TGuideKey | TGuideKey[]) {
612
const { ovhSubsidiary } = useContext(ShellContext).environment.getUser();
7-
const guideLink = GUIDE_LINKS[name];
813

9-
return guideLink[ovhSubsidiary] ?? guideLink.DEFAULT;
10-
};
14+
return Array.isArray(keys)
15+
? keys.reduce(
16+
(prev, currentKey) => ({
17+
...prev,
18+
[currentKey]: getGuideLink(currentKey, ovhSubsidiary),
19+
}),
20+
{} as Record<TGuideKey, string>,
21+
)
22+
: getGuideLink(keys, ovhSubsidiary);
23+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { FC } from 'react';
2+
import { Divider, Text } from '@ovhcloud/ods-react';
3+
import { useTranslation } from 'react-i18next';
4+
import { ImageHelper } from './distributionImage/ImageHelper.component';
5+
6+
const DistributionImage: FC = () => {
7+
const { t } = useTranslation('creation');
8+
9+
return (
10+
<section>
11+
<Divider spacing="64" />
12+
<div className="flex items-center space-x-4">
13+
<Text preset="heading-3">
14+
{t('pci_instance_creation_select_image_title')}
15+
</Text>
16+
<ImageHelper />
17+
</div>
18+
</section>
19+
);
20+
};
21+
22+
export default DistributionImage;

packages/manager/apps/pci-instances/src/pages/instances/create/components/createInstanceForm/CreateInstanceForm.component.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { useTranslation } from 'react-i18next';
1717
import { selectAvailabilityZones } from '../../view-models/availabilityZonesViewModel';
1818
import { AvailabilityZoneSelection } from '../availabilityZoneSelection/AvailabilityZoneSelection.component';
1919
import { LocalizationSelection } from '../localisationSelection/LocalizationSelection.component';
20+
import DistributionImage from '../DistributionImage.component';
2021

2122
const quantityHintParams = {
2223
quota: 1,
@@ -70,6 +71,7 @@ export const CreateInstanceForm = () => {
7071
)}
7172
<Divider spacing="64" />
7273
<FlavorBlock />
74+
<DistributionImage />
7375
<AdvancedParameters />
7476
<PciCardShowcaseComponent />
7577
</section>
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { HelpDrawer } from '@/components/helpDrawer/HelpDrawer.component';
2+
import { FC } from 'react';
3+
import { useTranslation } from 'react-i18next';
4+
import { Link, Text } from '@ovhcloud/ods-react';
5+
import { useGuideLink } from '@/hooks/url/useGuideLink';
6+
7+
export const ImageHelper: FC = () => {
8+
const { t } = useTranslation(['creation', 'common']);
9+
const guide = useGuideLink([
10+
'DISTRIBUTION_IMAGE',
11+
'DISTRIBUTION_IMAGE_LIFE_CYCLE',
12+
]);
13+
14+
return (
15+
<HelpDrawer>
16+
<Text preset="heading-2">
17+
{t('creation:pci_instance_creation_select_image_help_title')}
18+
</Text>
19+
<Text preset="paragraph" className="py-4">
20+
{t('creation:pci_instance_creation_select_image_help_text')}
21+
</Text>
22+
<Link
23+
className="visited:text-[var(--ods-color-primary-500)]"
24+
href={guide.DISTRIBUTION_IMAGE}
25+
target="_blank"
26+
>
27+
{t('common:pci_instances_common_more_info')}
28+
</Link>
29+
<div className="mt-4">
30+
<Link
31+
className="visited:text-[var(--ods-color-primary-500)]"
32+
href={guide.DISTRIBUTION_IMAGE_LIFE_CYCLE}
33+
target="_blank"
34+
>
35+
{t(
36+
'creation:pci_instance_creation_select_image_life_cycle_help_label',
37+
)}
38+
</Link>
39+
</div>
40+
</HelpDrawer>
41+
);
42+
};

0 commit comments

Comments
 (0)