Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(pci.ai.notebook): update guide, fix console error and wording #15076

Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
45 changes: 45 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,45 @@
import { Locale } from '@/hooks/useLocale';

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 function getGlobalAIGuideLink(local: string) {
return local === Locale.fr_FR || local === Locale.fr_CA
? 'https://docs.ovh.com/fr/publiccloud/ai/'
: 'https://docs.ovh.com/gb/en/publiccloud/ai/';
}

export function getOnbordingTuto1Link(local: string) {
return local === Locale.fr_FR || local === Locale.fr_CA
? 'https://help.ovhcloud.com/csm/fr-public-cloud-ai-notebooks-capabilities?id=kb_article_view&sysparm_article=KB0048247'
: 'https://help.ovhcloud.com/csm/en-gb-public-cloud-ai-notebooks-capabilities?id=kb_article_view&sysparm_article=KB0048238';
}
export function getOnbordingTuto2Link(local: string) {
return local === Locale.fr_FR || local === Locale.fr_CA
? 'https://help.ovhcloud.com/csm/fr-public-cloud-ai-notebooks-definition?id=kb_article_view&sysparm_article=KB0048274'
: 'https://help.ovhcloud.com/csm/en-gb-public-cloud-ai-notebooks-definition?id=kb_article_view&sysparm_article=KB0048269';
}

export function getHowToManageDataInAIDocLink(local: string) {
return local === Locale.fr_FR || local === Locale.fr_CA
? 'https://help.ovhcloud.com/csm/fr-public-cloud-ai-notebooks-definition?id=kb_article_view&sysparm_article=KB0048274'
: 'https://help.ovhcloud.com/csm/en-gb-public-cloud-ai-notebooks-definition?id=kb_article_view&sysparm_article=KB0048269';
}
abullet33 marked this conversation as resolved.
Show resolved Hide resolved
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;
};
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import { useQueryImmediateRefetch } from '../../useImmediateRefetch';

export function useGetGuides(
projectId: string,
section?: string,
section?: string[],
lang?: string,
options: Omit<QueryObserverOptions, 'queryKey'> = {},
) {
const queryKey = [projectId, 'ai', 'guides', section];
const queryKey = [projectId, 'ai', 'guides', section, lang];
return useQueryImmediateRefetch({
queryKey,
queryFn: () =>
Expand Down
Loading
Loading