Skip to content

Commit

Permalink
feat(pci.ai.notebook): update guide, fix console error and wording (#…
Browse files Browse the repository at this point in the history
…15076)

* feat(pci.ai.notebook): update guide, fix console error and wording
* feat(pci.ai.notebook): fix pr comments
Signed-off-by: Arthur Bullet <[email protected]>
  • Loading branch information
abullet33 authored Jan 29, 2025
1 parent 6e9b90b commit 78104d4
Show file tree
Hide file tree
Showing 27 changed files with 227 additions and 152 deletions.
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
{
"containerTitle": "Datastore S3, Datastore Git ou Object Storage OVHcloud",
"containerTitle": "Conteneur S3, Dépots Git privés et Object Storage OVHcloud",
"containerFieldLabel": "Conteneurs",
"containerDescription": "Datastore S3, Datastore Git ou Object Storage OVHcloud",
"noContainerDescription": "Vous n'avez pas configurés de Datastore S3 ou Git ni d'Object Storage OVHcloud.",
"datastoreLinkLabel": "Configurer un Datastore.",
"objectStorageLinkLabel": "Configurer un Object Storage OVHcloud.",
"containerFieldPlaceholder": "Séléctionner un conteneur",
"gitBranchFieldLabel": "Branch Git",
"mountDirectoryFieldLabel": "Répertoire de montage",
Expand All @@ -18,7 +15,7 @@
"duplicateMountPathError": "Ce répertoire de montage existe déjà",
"mountPathError": "Ce répertoire de montage est réservé",
"mountPathErrorFormat": "Format incorrect (ex : /files/test)",
"publicGitRepoTitle": "Dépots GIT public",
"publicGitRepoTitle": "Dépots GIT publics",
"publicGitUrlFieldLabel": "URL",
"gitUrlErrorFormat": "Format incorrect (ex: https://publicRepoGit.git)",
"numberOfConfiguredVolumes_zero": "{{count}} volumes configurés",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,10 @@
"formButtonAdvancedConfiguration": "Configuration avancée",
"fieldVolumesLabel": "Volumes",
"summaryFieldVolumesLabel": "Volumes:",
"fieldVolumeDescription": "Vous pouvez attacher des conteneurs S3 ou GIT, Object Storage OVHcloud ainsi que des des dépôts Git public à votre notebook. Une fois attachés, ceux-ci seront temporairement chargés et mis en cache près de votre instance afin de réduire la latence et d’améliorer les performances. Une bonne pratique est d’attacher un conteneur avec vos données entrantes et un autre avec vos données sortantes.",
"fieldVolumeLink": "En savoir plus le stockage de données.",
"fieldVolumeDescription1": "Si vous le souhaitez, vous pouvez attacher des conteneurs Swift, S3 ainsi que des dépôt Git privés ou publics à votre notebook que nous vous recommandons de configurer préalablement via AI Dashboard.",
"fieldVolumeDashboardLink": "Configurer un datastore",
"fieldVolumeDescription2": "Une fois attachés, ceux-ci seront temporairement chargés et mis en cache près de votre instance afin de réduire la latence et d’améliorer les performances. Une bonne pratique est d’attacher un conteneur avec vos données entrantes et un autre avec vos données sortantes.",
"fieldVolumeLink": "En savoir plus le stockage de données",
"summaryFieldVolumes_one": "{{count}} volume configuré",
"summaryFieldVolumes_other": "{{count}} volumes configurés",
"fieldConfigurationLabelsLabel": "Labels",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"breadcrumb": "Backups",
"title": "Sauvegardes",
"description": "Vous trouverez ci-dessous la liste de vos sauvegardes. Vous pouvez créer un nouveau notebook à partir du chacune d'entre elles",
"description": "Vous trouverez ci-dessous la liste des sauvegardes de vos notebooks. Il est possible de créer un nouveau notebook à partir de chacune d'entre elles.",
"tableHeaderId": "Id",
"tableHeaderCreationDate": "Date de création",
"tableHeaderUpdateDate": "Date de modification",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
"tableActionSyncData": "Synchroniser manuellement les données",
"tableWithCache": "Actif",
"tableWithoutCache": "Inactif",
"synchDataButtonHelper": "La synchronisation des données est possible seulement lorsque le notebook est en statut \"Echec de synchronisation\" (seulement pour le type push) ou \"En service\"",
"synchDataButtonHelper1": "La synchronisation des données (push et pull) n'est disponible que lorsque le notebook est en statut",
"synchDataButtonHelper2": "Il est également possible de lancer une synchronisation de type push lorsque le notebook affiche le statut",
"permission_RO": "Lecture Seule",
"permission_RW": "Lecture & Ecriture",
"permission_RWD": "Lecture & Ecriture & Suppression",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"breadcrumb": "Logs",
"title": "Logs",
"description": "Pour vous aider à suivre et à piloter votre notebook, vous trouverez les derniers événements (logs) ci-dessous, quasiment en direct.",
"description": "Vous trouverez ici l'ensemble des logs de votre notebook afin de vous aider à suivre et monitorer son évolution.",
"autoRefreshInputLabel": "Auto-Refresh"
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,12 @@
"description3": "Vous êtes data scientist ou développeur et souhaitez lancer un notebook en quelques minutes? Accédez rapidement à Jupyter ou VS Code et démarrez-le instantanément avec les ressources nécessaires, grâce à notre solution AI Notebooks. Pour développer votre activité, vous bénéficiez également d’un accès utilisateur sécurisé, de l’utilisation simplifiée de vos données et des plus grands frameworks d’intelligence artificielle (TensorFlow, PyTorch, Hugging Face ou encore Scikit-learn).",
"createNotebookButton": "Créer un Notebook",
"cardTutotitle": "Tutoriels",
"cardGuidetitle": "Guides",
"cardLink": "En savoir plus",
"cardTuto1Description": "Documentation complète AI Notebooks",
"cardTuto1Content": "Retrouvez toute la documentation d'AI Notebooks.",
"cardTuto2Description": "Définition AI Notebooks",
"cardTuto2Description": "Caractéristiques, capacités et limites",
"cardTuto2Content": "Découvrez ce qu'est un AI Notebook chez OVHcloud.",
"cardTuto3Description": "Démarrer avec AI Notebooks",
"cardTuto3Content": "Apprenez comment démarrer votre Notebook rapidement dans votre espace client.",
"cardTuto4Description": "Partager un Notebook",
"cardTuto4Content": "Apprenez comment partager un Notebook avec d'autres développeurs.",
"cardTuto5Description": "Accéder à vos datas depuis votre object storage",
"cardTuto5Content": "Découvrez comment accéder à vos datas de Notebook avec votre object storage."
"cardTuto3Content": "Apprenez comment démarrer votre Notebook rapidement depuis votre espace client, ligne de commande ou API."
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,32 @@ export const mockedSuggestion: Suggestions[] = [
unsecureHttp: false,
},
];

export const mockedTempSuggestionForOrderFunnel: Suggestions[] = [
{
region: 'GRA',
ressources: {
nb: 1,
flavor: 'ai1-1-cpu',
},
framework: {
id: 'one-for-all',
version: 'v98-ovh.beta.1',
},
editorId: 'jupyterlab',
unsecureHttp: false,
},
{
region: 'BHS',
ressources: {
nb: 1,
flavor: 'ai1-le-1-gpu',
},
framework: {
id: 'one-for-all',
version: 'v98-ovh.beta.1',
},
editorId: 'jupyterlab',
unsecureHttp: false,
},
];
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { useGetGuides } from '@/hooks/api/ai/guide/useGetGuides.hook';
import { useLocale } from '@/hooks/useLocale';

interface GuidesProps {
section?: string;
section?: string[];
onGuideClick?: (guide: ai.Guide) => void;
}
const Guides = ({ section, onGuideClick }: GuidesProps) => {
Expand All @@ -32,6 +32,7 @@ const Guides = ({ section, onGuideClick }: GuidesProps) => {
section,
locale.toLocaleLowerCase().replace('_', '-'),
);

// open the menu on cmd + j
useEffect(() => {
const down = (e: KeyboardEvent) => {
Expand All @@ -44,6 +45,7 @@ const Guides = ({ section, onGuideClick }: GuidesProps) => {
document.addEventListener('keydown', down);
return () => document.removeEventListener('keydown', down);
}, []);

// open a guide in a new tab
const openGuide = (guide: ai.Guide) => {
if (onGuideClick) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const RegionsSelect = React.forwardRef<HTMLInputElement, RegionsSelectProps>(
<RadioTile
data-testid={`region-tile-radio-tile-${region.id}`}
name="region-select"
key={`region-selet-${region.id}`}
onChange={() => onChange(region.id)}
value={region.id}
checked={region.id === value}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import React from 'react';
import { useParams } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { DataStoresWithContainers } from '@/hooks/api/ai/datastore/useGetDatastoresWithContainers.hook';
import { OrderVolumes } from '@/types/orderFunnel';
import OvhLink from '@/components/links/OvhLink.component';
import PublicGitForm from './PublicGitForm.component';
import ContainerForm from './ContainerForm.component';

Expand All @@ -15,48 +13,27 @@ interface VolumesFormProps {
}

const VolumeForm = React.forwardRef<HTMLInputElement, VolumesFormProps>(
({ configuredVolumesList, selectedVolumesList, onChange }) => {
({ configuredVolumesList, selectedVolumesList, onChange }, ref) => {
const { t } = useTranslation('pci-ai-notebooks/components/volumes');
const { projectId } = useParams();

return (
<>
<h5>{t('containerTitle')}</h5>
{configuredVolumesList.length > 0 ? (
<ContainerForm
configuredVolumesList={configuredVolumesList}
selectedVolumesList={selectedVolumesList}
onChange={(newVolumeList) => {
onChange(newVolumeList);
}}
/>
) : (
<div data-testid="no-datastore-info-container">
<p>{t('noContainerDescription')}</p>
<div className="flex flex-col gap-2 mt-2">
<OvhLink
data-testid="dashboard-datastore-link"
application="public-cloud"
path={`#/pci/projects/${projectId}/ai-dashboard`}
target="_blank"
rel="noopener noreferrer"
>
{t('datastoreLinkLabel')}
</OvhLink>
<OvhLink
data-testid="object-storage-link"
application="public-cloud"
path={`#/pci/projects/${projectId}/storages/objects`}
target="_blank"
rel="noopener noreferrer"
>
{t('objectStorageLinkLabel')}
</OvhLink>
</div>
</div>
{configuredVolumesList.length > 0 && (
<>
<h5>{t('containerTitle')}</h5>
<ContainerForm
ref={ref}
configuredVolumesList={configuredVolumesList}
selectedVolumesList={selectedVolumesList}
onChange={(newVolumeList) => {
onChange(newVolumeList);
}}
/>
</>
)}
<h5>{t('publicGitRepoTitle')}</h5>
<PublicGitForm
ref={ref}
selectedVolumesList={selectedVolumesList}
onChange={(newVolumeList) => {
onChange(newVolumeList);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,42 +43,6 @@ describe('Volume Form component', () => {
});

const onChange = vi.fn();
it('renders volume form should display dashboard, object storage link and public git form', async () => {
render(
<VolumeForm
configuredVolumesList={[]}
selectedVolumesList={[]}
onChange={onChange}
/>,
);
await waitFor(() => {
// should not be in the DOM as not Datastore configured
expect(
screen.queryByTestId('datastore-form-container'),
).not.toBeInTheDocument();
expect(
screen.queryByTestId('datastore-add-button'),
).not.toBeInTheDocument();
expect(screen.queryByTestId('datastore-list')).not.toBeInTheDocument();
// should be in the DOM
expect(
screen.getByTestId('no-datastore-info-container'),
).toBeInTheDocument();
expect(
screen.getByTestId('dashboard-datastore-link'),
).toBeInTheDocument();
expect(screen.getByTestId('object-storage-link')).toBeInTheDocument();
expect(
screen.getByTestId('public-git-form-container'),
).toBeInTheDocument();
expect(screen.getByTestId('public-git-add-button')).toBeInTheDocument();
expect(screen.getByTestId('public-git-list')).toBeInTheDocument();
expect(
screen.getByTestId('volumes-configured-labels'),
).toBeInTheDocument();
});
});

it('renders volume form should display datastore form and public git form', async () => {
render(
<VolumeForm
Expand Down
56 changes: 56 additions & 0 deletions packages/manager/apps/pci-ai-notebooks/src/configuration/guide.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
export enum GuideSections {
'cli' = 'cli',
'ovhaiCli' = 'ovhai-cli',
'users' = 'utilisateurs',
'data' = 'donnees',
'faq' = 'faq',
'registres' = 'registres',
'products' = 'produits-ia',
'notebooks' = 'ai-notebooks',
}

export const allGuidesSections: GuideSections[] = [
GuideSections.cli,
GuideSections.data,
GuideSections.faq,
GuideSections.notebooks,
GuideSections.ovhaiCli,
GuideSections.products,
GuideSections.notebooks,
];

export const GUIDES = {
GLOBAL_AI: {
fr_FR: 'https://docs.ovh.com/fr/publiccloud/ai/',
fr_CA: 'https://docs.ovh.com/fr/publiccloud/ai/',
default: 'https://docs.ovh.com/gb/en/publiccloud/ai/',
},
ONBOARDING_TUTO_1: {
fr_FR:
'https://help.ovhcloud.com/csm/fr-public-cloud-ai-notebooks-capabilities?id=kb_article_view&sysparm_article=KB0048247',
fr_CA:
'https://help.ovhcloud.com/csm/fr-public-cloud-ai-notebooks-capabilities?id=kb_article_view&sysparm_article=KB0048247',
default:
'https://help.ovhcloud.com/csm/en-gb-public-cloud-ai-notebooks-capabilities?id=kb_article_view&sysparm_article=KB0048238',
},
ONBOARDING_TUTO_2: {
fr_FR:
'https://help.ovhcloud.com/csm/fr-public-cloud-ai-notebooks-definition?id=kb_article_view&sysparm_article=KB0048274',
fr_CA:
'https://help.ovhcloud.com/csm/fr-public-cloud-ai-notebooks-definition?id=kb_article_view&sysparm_article=KB0048274',
default:
'https://help.ovhcloud.com/csm/en-gb-public-cloud-ai-notebooks-definition?id=kb_article_view&sysparm_article=KB0048269',
},
HOW_TO_MANAGE_DATA: {
fr_FR: 'https://docs.ovh.com/fr/publiccloud/ai/data/',
fr_CA: 'https://docs.ovh.com/fr/publiccloud/ai/data/',
default: 'https://docs.ovh.com/gb/en/publiccloud/ai/data/',
},
};

export function getGuideUrl(
guide: typeof GUIDES[keyof typeof GUIDES],
locale: string,
): string {
return guide[locale as keyof typeof guide] || guide.default;
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import * as ai from '@/types/cloud/project/ai';
import { PCIAi } from '..';

export interface GetGuidesProps extends PCIAi {
section?: string;
section?: string[];
lang?: string;
}
export const getGuides = async ({
Expand All @@ -16,12 +16,19 @@ export const getGuides = async ({
'X-Pagination-Size': '50000',
};
const filters = [];
if (section) {
filters.push(`section:eq=${section}`);

if (section && section.length > 0) {
filters.push(
section.length === 1
? `section:eq=${section[0]}`
: `section:in=${section.join(',')}`,
);
}

if (lang) {
filters.push(`lang:eq=${lang}`);
}

if (filters.length > 0) {
headers['X-Pagination-Filter'] = filters.join('&');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,13 @@ describe('Guides functions', () => {
expect(apiClient.v6.get).not.toHaveBeenCalled();
await getGuides({
projectId: 'projectId',
lang: 'fr-FR',
});
expect(apiClient.v6.get).toHaveBeenCalledWith(
'/cloud/project/projectId/ai/guides',
{
headers: {
'X-Pagination-Filter': 'lang:eq=fr-FR',
'X-Pagination-Mode': 'CachedObjectList-Pages',
'X-Pagination-Size': '50000',
},
Expand All @@ -40,7 +42,7 @@ describe('Guides functions', () => {
expect(apiClient.v6.get).not.toHaveBeenCalled();
await getGuides({
projectId: 'projectId',
section: 'cli',
section: ['cli'],
lang: 'fr-FR',
});
expect(apiClient.v6.get).toHaveBeenCalledWith(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { apiClient } from '@ovh-ux/manager-core-api';
import { PCIAi } from '../..';
import { Suggestions } from '@/types/orderFunnel';
import { mockedSuggestion } from '@/__tests__/helpers/mocks/suggestion';
// import { apiClient } from '@ovh-ux/manager-core-api';
// import { PCIAi } from '../..';
// import { Suggestions } from '@/types/orderFunnel';
import { mockedTempSuggestionForOrderFunnel } from '@/__tests__/helpers/mocks/suggestion';

export const getSuggestions = async ({ projectId }: PCIAi) => {
export const getSuggestions = async (/* { projectId }: PCIAi */) => {
/*
apiClient.v6
.get(`/cloud/project/${projectId}/ai/notebook/suggestions`)
.then((res) => res.data as Suggestions[]);
*/
return mockedSuggestion;
return mockedTempSuggestionForOrderFunnel;
};
Loading

0 comments on commit 78104d4

Please sign in to comment.