diff --git a/packages/manager-react-components/src/hooks/services/services.type.ts b/packages/manager-react-components/src/hooks/services/services.type.ts index 4e35a725fe2a..9b3f00f70a03 100644 --- a/packages/manager-react-components/src/hooks/services/services.type.ts +++ b/packages/manager-react-components/src/hooks/services/services.type.ts @@ -80,7 +80,7 @@ export type ServiceDetails = { actions: LifecycleAction[]; }; current: { - createDate: string; + creationDate: string; pendingActions: LifecycleAction[]; state: LifecycleState; terminationDate: string; diff --git a/packages/manager/apps/container/src/assets/images/sidebar/hycu-logo.svg b/packages/manager/apps/container/src/assets/images/sidebar/hycu-logo.svg new file mode 100644 index 000000000000..e3856dac5f9e --- /dev/null +++ b/packages/manager/apps/container/src/assets/images/sidebar/hycu-logo.svg @@ -0,0 +1,12 @@ + + + + + + + diff --git a/packages/manager/apps/container/src/assets/images/sidebar/infinity-cloud.png b/packages/manager/apps/container/src/assets/images/sidebar/infinity-cloud.png new file mode 100644 index 000000000000..79586e21da7b Binary files /dev/null and b/packages/manager/apps/container/src/assets/images/sidebar/infinity-cloud.png differ diff --git a/packages/manager/apps/container/src/container/legacy/index.tsx b/packages/manager/apps/container/src/container/legacy/index.tsx index 215688246aa1..1401de2b586c 100644 --- a/packages/manager/apps/container/src/container/legacy/index.tsx +++ b/packages/manager/apps/container/src/container/legacy/index.tsx @@ -1,4 +1,4 @@ -import React, { +import { Suspense, useContext, useEffect, diff --git a/packages/manager/apps/container/src/container/legacy/server-sidebar/SidebarVirtual.tsx b/packages/manager/apps/container/src/container/legacy/server-sidebar/SidebarVirtual.tsx index 378e65d1b9f6..ffeb89736e57 100644 --- a/packages/manager/apps/container/src/container/legacy/server-sidebar/SidebarVirtual.tsx +++ b/packages/manager/apps/container/src/container/legacy/server-sidebar/SidebarVirtual.tsx @@ -73,7 +73,7 @@ export default function ServerSidebarVirtual({ style={{ height: `${rowVirtualizer.getTotalSize()}px`, width: '100%', - position: 'relative', + position: 'relative' }} aria-label={t('sidebar_description')} > diff --git a/packages/manager/apps/container/src/container/legacy/server-sidebar/universe/GetIcon.tsx b/packages/manager/apps/container/src/container/legacy/server-sidebar/universe/GetIcon.tsx index b56e62ca5a57..d0dae552d056 100644 --- a/packages/manager/apps/container/src/container/legacy/server-sidebar/universe/GetIcon.tsx +++ b/packages/manager/apps/container/src/container/legacy/server-sidebar/universe/GetIcon.tsx @@ -1,5 +1,3 @@ -import React from "react"; - const getIcon = (iconClass:string ): JSX.Element => { return ;} diff --git a/packages/manager/apps/container/src/container/legacy/server-sidebar/universe/HostedPrivateCloudSidebar.tsx b/packages/manager/apps/container/src/container/legacy/server-sidebar/universe/HostedPrivateCloudSidebar.tsx index 94b0456f39bb..4343c9e16373 100644 --- a/packages/manager/apps/container/src/container/legacy/server-sidebar/universe/HostedPrivateCloudSidebar.tsx +++ b/packages/manager/apps/container/src/container/legacy/server-sidebar/universe/HostedPrivateCloudSidebar.tsx @@ -12,6 +12,8 @@ import { OsdsIcon } from '@ovhcloud/ods-components/react'; import { ODS_ICON_NAME, ODS_ICON_SIZE } from '@ovhcloud/ods-components'; import { ODS_THEME_COLOR_INTENT } from '@ovhcloud/ods-common-theming'; import { useFeatureAvailability } from '@ovh-ux/manager-react-components'; +import infinityCLoud from '@/assets/images/sidebar/infinity-cloud.png'; +import hycuLogo from '@/assets/images/sidebar/hycu-logo.svg'; const features = [ 'dedicated-cloud', @@ -33,6 +35,7 @@ const features = [ 'dedicated-nasha', 'veeam-cloud-connect:order', 'veeam-enterprise:order', + 'hycu', 'vrack:bare-metal-cloud', 'vrack:order', 'vrack-services', @@ -236,6 +239,42 @@ export default function HostedPrivateCloudSidebar() { ], }); } + if (feature['hycu']) { + menu.push({ + id: 'hpc-storage-backup', + label: t('sidebar_storage_backup'), + icon: , + pathMatcher: new RegExp('^/hycu'), + badge: 'new', + subItems: [ + (feature['hycu']) && { + id: 'hpc-hycu', + label: t('sidebar_hycu'), + icon: , + pathMatcher: new RegExp('^/hycu'), + badge: "new", + async loader() { + const appId = 'hycu'; + const items = await loadServices('/license/hycu'); + + return [ + { + id: 'hycu-all', + label: t('sidebar_all_hycu'), + href: navigation.getURL(appId, '#/'), + ignoreSearch: true, + }, + ...items.map((service) => ({ + ...service, + href: navigation.getURL(appId, `#/${service.serviceName}`), + })) + ]; + }, + } + ] + }) + } + if (feature['key-management-service']) { const keyIcon = menu.push({ diff --git a/packages/manager/apps/container/src/container/nav-reshuffle/sidebar/navigation-tree/services/hostedPrivateCloud.ts b/packages/manager/apps/container/src/container/nav-reshuffle/sidebar/navigation-tree/services/hostedPrivateCloud.ts index aaa94a5853bd..2fc27b1ed24a 100644 --- a/packages/manager/apps/container/src/container/nav-reshuffle/sidebar/navigation-tree/services/hostedPrivateCloud.ts +++ b/packages/manager/apps/container/src/container/nav-reshuffle/sidebar/navigation-tree/services/hostedPrivateCloud.ts @@ -1,5 +1,5 @@ import illustration from '@/assets/images/sidebar/hosted-private-cloud.png'; -import { Node } from '../node'; +import { Node, NodeTag } from '../node'; import OvhProductName from '@ovh-ux/ovh-product-icons/utils/OvhProductNameEnum'; const hostedPrivateCloudUniverse: Node = { @@ -89,6 +89,19 @@ hostedPrivateCloudUniverse.children = [ }, features: ['veeam-cloud-connect'], }, + { + id: 'hycu', + idAttr: 'hycu-link', + universe: hostedPrivateCloudUniverse.id, + translation: 'sidebar_hycu', + serviceType: 'HYCU', + tag: NodeTag.NEW, + routing: { + application: 'hycu', + hash: '', + }, + features: ['hycu'], + }, ], }, ]; diff --git a/packages/manager/apps/container/src/public/translations/sidebar/Messages_de_DE.json b/packages/manager/apps/container/src/public/translations/sidebar/Messages_de_DE.json index aed3cb4d7436..ae4b68cefbe7 100644 --- a/packages/manager/apps/container/src/public/translations/sidebar/Messages_de_DE.json +++ b/packages/manager/apps/container/src/public/translations/sidebar/Messages_de_DE.json @@ -199,5 +199,7 @@ "sidebar_security_operations": "Abläufe", "sidebar_security_identity": "Identität und Sicherheit", "sidebar_zimbra": "Zimbra Mail", - "sidebar_pci_savings_plan": "Savings Plans" + "sidebar_pci_savings_plan": "Savings Plans", + "sidebar_hycu": "HYCU", + "sidebar_all_hycu": "Alle meine Lizenzen" } diff --git a/packages/manager/apps/container/src/public/translations/sidebar/Messages_en_GB.json b/packages/manager/apps/container/src/public/translations/sidebar/Messages_en_GB.json index 2cd1687d57a1..91ff6555990f 100644 --- a/packages/manager/apps/container/src/public/translations/sidebar/Messages_en_GB.json +++ b/packages/manager/apps/container/src/public/translations/sidebar/Messages_en_GB.json @@ -199,5 +199,7 @@ "sidebar_security_operations": "Operations", "sidebar_security_identity": "Identity and Security", "sidebar_reduce": "Minimise", - "sidebar_pci_savings_plan": "Savings Plan" + "sidebar_pci_savings_plan": "Savings Plan", + "sidebar_hycu": "HYCU", + "sidebar_all_hycu": "All my licenses" } diff --git a/packages/manager/apps/container/src/public/translations/sidebar/Messages_es_ES.json b/packages/manager/apps/container/src/public/translations/sidebar/Messages_es_ES.json index 05c3648f1b06..f189d885b9e7 100644 --- a/packages/manager/apps/container/src/public/translations/sidebar/Messages_es_ES.json +++ b/packages/manager/apps/container/src/public/translations/sidebar/Messages_es_ES.json @@ -199,5 +199,7 @@ "sidebar_security_operations": "Operaciones", "sidebar_security_identity": "Identidad y seguridad", "sidebar_reduce": "Minimizar", - "sidebar_pci_savings_plan": "Savings Plans" + "sidebar_pci_savings_plan": "Savings Plans", + "sidebar_hycu": "HYCU", + "sidebar_all_hycu": "Todas mis licencias" } diff --git a/packages/manager/apps/container/src/public/translations/sidebar/Messages_fr_CA.json b/packages/manager/apps/container/src/public/translations/sidebar/Messages_fr_CA.json index 6956e976b04c..c711ddc497b5 100644 --- a/packages/manager/apps/container/src/public/translations/sidebar/Messages_fr_CA.json +++ b/packages/manager/apps/container/src/public/translations/sidebar/Messages_fr_CA.json @@ -37,6 +37,8 @@ "sidebar_platforms": "Plateformes", "sidebar_platforms_services": "Plateformes et services", "sidebar_veeam_enterprise": "Veeam Enterprise", + "sidebar_hycu": "HYCU", + "sidebar_all_hycu": "Toutes mes licenses", "sidebar_pci": "Public Cloud", "sidebar_pci_short": "PCP", "sidebar_pci_new": "Créer un projet", diff --git a/packages/manager/apps/container/src/public/translations/sidebar/Messages_fr_FR.json b/packages/manager/apps/container/src/public/translations/sidebar/Messages_fr_FR.json index 6956e976b04c..c711ddc497b5 100644 --- a/packages/manager/apps/container/src/public/translations/sidebar/Messages_fr_FR.json +++ b/packages/manager/apps/container/src/public/translations/sidebar/Messages_fr_FR.json @@ -37,6 +37,8 @@ "sidebar_platforms": "Plateformes", "sidebar_platforms_services": "Plateformes et services", "sidebar_veeam_enterprise": "Veeam Enterprise", + "sidebar_hycu": "HYCU", + "sidebar_all_hycu": "Toutes mes licenses", "sidebar_pci": "Public Cloud", "sidebar_pci_short": "PCP", "sidebar_pci_new": "Créer un projet", diff --git a/packages/manager/apps/container/src/public/translations/sidebar/Messages_it_IT.json b/packages/manager/apps/container/src/public/translations/sidebar/Messages_it_IT.json index fff8219e4b21..dcb5b3b9a688 100644 --- a/packages/manager/apps/container/src/public/translations/sidebar/Messages_it_IT.json +++ b/packages/manager/apps/container/src/public/translations/sidebar/Messages_it_IT.json @@ -199,5 +199,7 @@ "sidebar_security_operations": "Operazioni", "sidebar_security_identity": "Identità e sicurezza", "sidebar_reduce": "Riduci", - "sidebar_pci_savings_plan": "Savings Plan" + "sidebar_pci_savings_plan": "Savings Plan", + "sidebar_hycu": "HYCU", + "sidebar_all_hycu": "Tutte le mie licenze" } diff --git a/packages/manager/apps/container/src/public/translations/sidebar/Messages_pl_PL.json b/packages/manager/apps/container/src/public/translations/sidebar/Messages_pl_PL.json index 7b5157a6f3e5..f655eb19997e 100644 --- a/packages/manager/apps/container/src/public/translations/sidebar/Messages_pl_PL.json +++ b/packages/manager/apps/container/src/public/translations/sidebar/Messages_pl_PL.json @@ -199,5 +199,7 @@ "sidebar_security_operations": "Operacje", "sidebar_security_identity": "Tożsamość i bezpieczeństwo", "sidebar_reduce": "Zmniejsz", - "sidebar_pci_savings_plan": "Savings Plans" + "sidebar_pci_savings_plan": "Savings Plans", + "sidebar_hycu": "HYCU", + "sidebar_all_hycu": "Wszystkie moje licencje" } diff --git a/packages/manager/apps/container/src/public/translations/sidebar/Messages_pt_PT.json b/packages/manager/apps/container/src/public/translations/sidebar/Messages_pt_PT.json index a729a77a2810..82d614d3820a 100644 --- a/packages/manager/apps/container/src/public/translations/sidebar/Messages_pt_PT.json +++ b/packages/manager/apps/container/src/public/translations/sidebar/Messages_pt_PT.json @@ -199,5 +199,7 @@ "sidebar_security_operations": "Operações", "sidebar_security_identity": "Identidade e Segurança", "sidebar_reduce": "Reduzir", - "sidebar_pci_savings_plan": "Savings Plans" + "sidebar_pci_savings_plan": "Savings Plans", + "sidebar_hycu": "HYCU", + "sidebar_all_hycu": "Todas as minhas licenças" } diff --git a/packages/manager/apps/hycu/.gitignore b/packages/manager/apps/hycu/.gitignore new file mode 100644 index 000000000000..e06831cfdeb4 --- /dev/null +++ b/packages/manager/apps/hycu/.gitignore @@ -0,0 +1,2 @@ +e2e/reports +e2e/coverage diff --git a/packages/manager/apps/hycu/README.md b/packages/manager/apps/hycu/README.md new file mode 100644 index 000000000000..f6efb1b4becf --- /dev/null +++ b/packages/manager/apps/hycu/README.md @@ -0,0 +1,3 @@ +# @ovh-ux/manager-hycu-app + +> Backup HYCU for OVHcloud diff --git a/packages/manager/apps/hycu/cucumber.js b/packages/manager/apps/hycu/cucumber.js new file mode 100644 index 000000000000..8e6abbfbca8f --- /dev/null +++ b/packages/manager/apps/hycu/cucumber.js @@ -0,0 +1,20 @@ +const isCI = process.env.CI; + +module.exports = { + default: { + paths: ['e2e/features/**/*.feature'], + require: [ + '../../../../playwright-helpers/bdd-setup.ts', + 'e2e/**/*.step.ts', + ], + requireModule: ['ts-node/register'], + format: [ + 'summary', + isCI ? 'progress' : 'progress-bar', + !isCI && ['html', 'e2e/reports/cucumber-results-report.html'], + !isCI && ['usage-json', 'e2e/reports/cucumber-usage-report.json'], + ].filter(Boolean), + formatOptions: { snippetInterface: 'async-await' }, + retry: 1, + }, +}; diff --git a/packages/manager/apps/hycu/index.html b/packages/manager/apps/hycu/index.html new file mode 100644 index 000000000000..ec4e92d05007 --- /dev/null +++ b/packages/manager/apps/hycu/index.html @@ -0,0 +1,22 @@ + + + + + + + + OVHcloud + + + + + + + We're sorry but this application doesn't work properly without + JavaScript enabled. Please enable it to continue. + + + + + + diff --git a/packages/manager/apps/hycu/mocks/example/example-data.json b/packages/manager/apps/hycu/mocks/example/example-data.json new file mode 100644 index 000000000000..16b09c4e47fd --- /dev/null +++ b/packages/manager/apps/hycu/mocks/example/example-data.json @@ -0,0 +1,11 @@ +[ + { + "id": 20374 + }, + { + "id": 20375 + }, + { + "id": 20379 + } +] diff --git a/packages/manager/apps/hycu/mocks/example/example.ts b/packages/manager/apps/hycu/mocks/example/example.ts new file mode 100644 index 000000000000..77c033e7b392 --- /dev/null +++ b/packages/manager/apps/hycu/mocks/example/example.ts @@ -0,0 +1,30 @@ +import { Handler } from '../../../../../../playwright-helpers'; +import exampleList from './example-data.json'; + +export type GetExampleMocksParams = { isKo?: boolean; nb?: number }; + +export const getExampleMocks = ({ + isKo, + nb = Number.POSITIVE_INFINITY, +}: GetExampleMocksParams): Handler[] => [ + { + url: '*', + response: isKo + ? { + message: 'Example error', + } + : exampleList.slice(0, nb), + status: isKo ? 500 : 200, + api: 'v6', + }, + { + url: '*', + response: isKo + ? { + message: 'Example error', + } + : exampleList.slice(0, nb), + status: isKo ? 500 : 200, + api: 'v2', + }, +]; diff --git a/packages/manager/apps/hycu/mocks/index.ts b/packages/manager/apps/hycu/mocks/index.ts new file mode 100644 index 000000000000..4356d0ac05ac --- /dev/null +++ b/packages/manager/apps/hycu/mocks/index.ts @@ -0,0 +1 @@ +export * from './example/example'; diff --git a/packages/manager/apps/hycu/package.json b/packages/manager/apps/hycu/package.json new file mode 100644 index 000000000000..6c027e737c9e --- /dev/null +++ b/packages/manager/apps/hycu/package.json @@ -0,0 +1,66 @@ +{ + "name": "@ovh-ux/manager-hycu-app", + "version": "0.0.0", + "private": true, + "description": "Backup HYCU for OVHcloud", + "repository": { + "type": "git", + "url": "git+https://github.com/ovh/manager.git", + "directory": "packages/manager/apps/hycu" + }, + "license": "BSD-3-Clause", + "author": "OVH SAS", + "scripts": { + "build": "tsc && vite build", + "dev": "tsc && vite", + "start": "lerna exec --stream --scope='@ovh-ux/manager-hycu-app' --include-dependencies -- npm run build --if-present", + "start:dev": "lerna exec --stream --scope='@ovh-ux/manager-hycu-app' --include-dependencies -- npm run dev --if-present", + "start:watch": "lerna exec --stream --parallel --scope='@ovh-ux/manager-hycu-app' --include-dependencies -- npm run dev:watch --if-present", + "test": "vitest run" + }, + "dependencies": { + "@ovh-ux/manager-config": "*", + "@ovh-ux/manager-core-api": "*", + "@ovh-ux/manager-core-utils": "*", + "@ovh-ux/manager-react-components": "*", + "@ovh-ux/manager-react-core-application": "*", + "@ovh-ux/manager-react-shell-client": "*", + "@ovh-ux/manager-tailwind-config": "*", + "@ovh-ux/request-tagger": "*", + "@ovhcloud/ods-common-core": "17.2.1", + "@ovhcloud/ods-common-theming": "17.2.1", + "@ovhcloud/ods-components": "17.2.1", + "@ovhcloud/ods-theme-blue-jeans": "17.2.1", + "@tanstack/react-query": "^5.51.21", + "@tanstack/react-query-devtools": "^5.51.21", + "axios": "^1.1.2", + "clsx": "^1.2.1", + "i18next": "^23.8.2", + "i18next-http-backend": "^2.4.2", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-i18next": "^14.0.5", + "react-router-dom": "^6.3.0", + "tailwindcss": "^3.4.4" + }, + "devDependencies": { + "@cucumber/cucumber": "^10.3.1", + "@ovh-ux/manager-vite-config": "*", + "@testing-library/jest-dom": "^6.5.0", + "@testing-library/react": "^16.0.1", + "@testing-library/user-event": "^14.5.2", + "@types/jest": "^29.5.13", + "@vitejs/plugin-react": "^4.3.2", + "element-internals-polyfill": "^1.3.12", + "eslint-plugin-prettier": "^5.2.1", + "msw": "2.1.7", + "typescript": "^5.1.6", + "vite": "^5.2.13", + "vitest": "^2.1.2" + }, + "regions": [ + "CA", + "EU", + "US" + ] +} diff --git a/packages/manager/apps/hycu/postcss.config.js b/packages/manager/apps/hycu/postcss.config.js new file mode 100644 index 000000000000..12a703d900da --- /dev/null +++ b/packages/manager/apps/hycu/postcss.config.js @@ -0,0 +1,6 @@ +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; diff --git a/packages/manager/apps/hycu/public/translations/dashboard/Messages_de_DE.json b/packages/manager/apps/hycu/public/translations/dashboard/Messages_de_DE.json new file mode 100644 index 000000000000..c63e4746c09a --- /dev/null +++ b/packages/manager/apps/hycu/public/translations/dashboard/Messages_de_DE.json @@ -0,0 +1,7 @@ +{ + "title": "Dashboard-Seite", + "error_service": "Unsere Info-Dienstleistungen", + "general_informations": "Allgemeine Informationen", + "tab2": "TAB 2", + "back_link": "Zurück zur Liste" +} diff --git a/packages/manager/apps/hycu/public/translations/dashboard/Messages_en_GB.json b/packages/manager/apps/hycu/public/translations/dashboard/Messages_en_GB.json new file mode 100644 index 000000000000..50112d71927a --- /dev/null +++ b/packages/manager/apps/hycu/public/translations/dashboard/Messages_en_GB.json @@ -0,0 +1,7 @@ +{ + "title": "Dashboard page", + "error_service": "Our info services", + "general_informations": "General information", + "tab2": "Tab 2", + "back_link": "Back to list" +} diff --git a/packages/manager/apps/hycu/public/translations/dashboard/Messages_es_ES.json b/packages/manager/apps/hycu/public/translations/dashboard/Messages_es_ES.json new file mode 100644 index 000000000000..d840c6ca437b --- /dev/null +++ b/packages/manager/apps/hycu/public/translations/dashboard/Messages_es_ES.json @@ -0,0 +1,7 @@ +{ + "title": "Dashboard page", + "error_service": "No services info", + "general_informations": "Datos generales", + "tab2": "Tabulador 2", + "back_link": "Volver a la lista" +} diff --git a/packages/manager/apps/hycu/public/translations/dashboard/Messages_fr_CA.json b/packages/manager/apps/hycu/public/translations/dashboard/Messages_fr_CA.json new file mode 100644 index 000000000000..f42a27b3366a --- /dev/null +++ b/packages/manager/apps/hycu/public/translations/dashboard/Messages_fr_CA.json @@ -0,0 +1,7 @@ +{ + "title": "Dashboard page", + "error_service": "No services info", + "general_informations": "Informations générales", + "tab2": "Tab 2", + "back_link": "Retour à la liste" +} diff --git a/packages/manager/apps/hycu/public/translations/dashboard/Messages_fr_FR.json b/packages/manager/apps/hycu/public/translations/dashboard/Messages_fr_FR.json new file mode 100644 index 000000000000..f42a27b3366a --- /dev/null +++ b/packages/manager/apps/hycu/public/translations/dashboard/Messages_fr_FR.json @@ -0,0 +1,7 @@ +{ + "title": "Dashboard page", + "error_service": "No services info", + "general_informations": "Informations générales", + "tab2": "Tab 2", + "back_link": "Retour à la liste" +} diff --git a/packages/manager/apps/hycu/public/translations/dashboard/Messages_it_IT.json b/packages/manager/apps/hycu/public/translations/dashboard/Messages_it_IT.json new file mode 100644 index 000000000000..dfab484de070 --- /dev/null +++ b/packages/manager/apps/hycu/public/translations/dashboard/Messages_it_IT.json @@ -0,0 +1,7 @@ +{ + "title": "Dashboard page", + "error_service": "I nostri servizi info", + "general_informations": "Informazioni generali", + "tab2": "Tab 2", + "back_link": "Torna alla lista" +} diff --git a/packages/manager/apps/hycu/public/translations/dashboard/Messages_pl_PL.json b/packages/manager/apps/hycu/public/translations/dashboard/Messages_pl_PL.json new file mode 100644 index 000000000000..91e02f3720bf --- /dev/null +++ b/packages/manager/apps/hycu/public/translations/dashboard/Messages_pl_PL.json @@ -0,0 +1,7 @@ +{ + "title": "Strona z dashboardem", + "error_service": "Nasze usługi info", + "general_informations": "Informacje ogólne", + "tab2": "Tab 2", + "back_link": "Powrót do listy" +} diff --git a/packages/manager/apps/hycu/public/translations/dashboard/Messages_pt_PT.json b/packages/manager/apps/hycu/public/translations/dashboard/Messages_pt_PT.json new file mode 100644 index 000000000000..aee82bf86b3a --- /dev/null +++ b/packages/manager/apps/hycu/public/translations/dashboard/Messages_pt_PT.json @@ -0,0 +1,7 @@ +{ + "title": "Página de painel", + "error_service": "Os nossos serviços info", + "general_informations": "Informações gerais", + "tab2": "Tab 2", + "back_link": "Voltar à lista" +} diff --git a/packages/manager/apps/hycu/public/translations/hycu/Messages_de_DE.json b/packages/manager/apps/hycu/public/translations/hycu/Messages_de_DE.json new file mode 100644 index 000000000000..fef0cbce28fd --- /dev/null +++ b/packages/manager/apps/hycu/public/translations/hycu/Messages_de_DE.json @@ -0,0 +1,6 @@ +{ + "hycu_crumb": "HYCU", + "tabs_2": "Tabs 2", + "hycu_description": "Vereinfachen Sie Backups, Notfall-Wiederherstellungspläne und Migrationen Ihrer Nutanix-Infrastruktur. Dieser Dienst bietet verschiedene Hycu Hybrid Cloud Lizenzpakete zum Schutz Ihrer Nutanix-Workloads.", + "hycu_cloud_vm_pack_unknown": "Unbekanntes Paket" +} diff --git a/packages/manager/apps/hycu/public/translations/hycu/Messages_en_GB.json b/packages/manager/apps/hycu/public/translations/hycu/Messages_en_GB.json new file mode 100644 index 000000000000..ddcfb95c418c --- /dev/null +++ b/packages/manager/apps/hycu/public/translations/hycu/Messages_en_GB.json @@ -0,0 +1,6 @@ +{ + "hycu_crumb": "HYCU", + "tabs_2": "Table 2", + "hycu_description": "Simplify your backups, disaster recovery plans, and migrations for your Nutanix infrastructure. This service offers different Hybrid Cloud HYCU license packs to protect your Nutanix workloads.", + "hycu_cloud_vm_pack_unknown": "Unknown pack" +} diff --git a/packages/manager/apps/hycu/public/translations/hycu/Messages_es_ES.json b/packages/manager/apps/hycu/public/translations/hycu/Messages_es_ES.json new file mode 100644 index 000000000000..477cf50f2cad --- /dev/null +++ b/packages/manager/apps/hycu/public/translations/hycu/Messages_es_ES.json @@ -0,0 +1,6 @@ +{ + "hycu_crumb": "HYCU", + "tabs_2": "Tabs 2", + "hycu_description": "Simplifique sus backups, planes de recuperación ante desastres y migraciones de su infraestructura Nutanix. Este servicio le ofrece diferentes packs de licencias HYCU Hybrid Cloud para proteger sus cargas de trabajo Nutanix.", + "hycu_cloud_vm_pack_unknown": "Pack desconocido" +} diff --git a/packages/manager/apps/hycu/public/translations/hycu/Messages_fr_CA.json b/packages/manager/apps/hycu/public/translations/hycu/Messages_fr_CA.json new file mode 100644 index 000000000000..36d8b913e6d9 --- /dev/null +++ b/packages/manager/apps/hycu/public/translations/hycu/Messages_fr_CA.json @@ -0,0 +1,6 @@ +{ + "hycu_crumb": "HYCU", + "tabs_2": "Tabs 2", + "hycu_description": "Simplifiez vos sauvegardes, plans de reprise après sinistre et migrations de votre infrastructure Nutanix. Ce service vous propose différents packs de licences HYCU Hybrid Cloud pour protéger vos charges de travail Nutanix.", + "hycu_cloud_vm_pack_unknown": "Pack inconnu" +} diff --git a/packages/manager/apps/hycu/public/translations/hycu/Messages_fr_FR.json b/packages/manager/apps/hycu/public/translations/hycu/Messages_fr_FR.json new file mode 100644 index 000000000000..36d8b913e6d9 --- /dev/null +++ b/packages/manager/apps/hycu/public/translations/hycu/Messages_fr_FR.json @@ -0,0 +1,6 @@ +{ + "hycu_crumb": "HYCU", + "tabs_2": "Tabs 2", + "hycu_description": "Simplifiez vos sauvegardes, plans de reprise après sinistre et migrations de votre infrastructure Nutanix. Ce service vous propose différents packs de licences HYCU Hybrid Cloud pour protéger vos charges de travail Nutanix.", + "hycu_cloud_vm_pack_unknown": "Pack inconnu" +} diff --git a/packages/manager/apps/hycu/public/translations/hycu/Messages_it_IT.json b/packages/manager/apps/hycu/public/translations/hycu/Messages_it_IT.json new file mode 100644 index 000000000000..cec002eab61d --- /dev/null +++ b/packages/manager/apps/hycu/public/translations/hycu/Messages_it_IT.json @@ -0,0 +1,6 @@ +{ + "hycu_crumb": "HYCU", + "tabs_2": "Tabs 2", + "hycu_description": "Backup più semplici, piani di ripristino di emergenza e migrazioni dell'infrastruttura Nutanix. Questo servizio propone diversi pack di licenze Hybrid Cloud per proteggere i carichi di lavoro Nutanix.", + "hycu_cloud_vm_pack_unknown": "Pack sconosciuto" +} diff --git a/packages/manager/apps/hycu/public/translations/hycu/Messages_pl_PL.json b/packages/manager/apps/hycu/public/translations/hycu/Messages_pl_PL.json new file mode 100644 index 000000000000..7b577a19fedc --- /dev/null +++ b/packages/manager/apps/hycu/public/translations/hycu/Messages_pl_PL.json @@ -0,0 +1,6 @@ +{ + "hycu_crumb": "HYCU", + "tabs_2": "Tabela 2", + "hycu_description": "Uprość tworzenie kopii zapasowych, odzyskiwanie danych po awarii i migrację infrastruktury Nutanix. Usługa ta zawiera różne pakiety licencji Hybrid Cloud Hybrid Cloud, które chronią Twoje obciążenia Nutanix.", + "hycu_cloud_vm_pack_unknown": "Nieznany pakiet" +} diff --git a/packages/manager/apps/hycu/public/translations/hycu/Messages_pt_PT.json b/packages/manager/apps/hycu/public/translations/hycu/Messages_pt_PT.json new file mode 100644 index 000000000000..e145e32af790 --- /dev/null +++ b/packages/manager/apps/hycu/public/translations/hycu/Messages_pt_PT.json @@ -0,0 +1,6 @@ +{ + "hycu_crumb": "HYCU", + "tabs_2": "Quadro 2", + "hycu_description": "Simplifique os seus backups, planos de recuperação após desastres e migrações da sua infraestrutura Nutanix. Este serviço propõe-lhe diferentes pacotes de licenças HYCU Hybrid Cloud para proteger as suas cargas de trabalho Nutanix.", + "hycu_cloud_vm_pack_unknown": "Pack desconhecido" +} diff --git a/packages/manager/apps/hycu/public/translations/hycu/error/Messages_de_DE.json b/packages/manager/apps/hycu/public/translations/hycu/error/Messages_de_DE.json new file mode 100644 index 000000000000..bf0fba32976b --- /dev/null +++ b/packages/manager/apps/hycu/public/translations/hycu/error/Messages_de_DE.json @@ -0,0 +1,8 @@ +{ + "manager_error_page_title": "Oops...!", + "manager_error_page_button_cancel": "Abbrechen", + "manager_error_page_detail_code": "Fehlercode: ", + "manager_error_page_action_reload_label": "Erneut versuchen", + "manager_error_page_action_home_label": "Zurück zur Startseite", + "manager_error_page_default": "Beim Laden der Seite ist ein Fehler aufgetreten." +} diff --git a/packages/manager/apps/hycu/public/translations/hycu/error/Messages_en_GB.json b/packages/manager/apps/hycu/public/translations/hycu/error/Messages_en_GB.json new file mode 100644 index 000000000000..b17691e2bc6d --- /dev/null +++ b/packages/manager/apps/hycu/public/translations/hycu/error/Messages_en_GB.json @@ -0,0 +1,8 @@ +{ + "manager_error_page_title": "Oops!", + "manager_error_page_button_cancel": "Cancel", + "manager_error_page_detail_code": "Error code: ", + "manager_error_page_action_reload_label": "Try again", + "manager_error_page_action_home_label": "Back to homepage", + "manager_error_page_default": "An error has occurred loading the page." +} diff --git a/packages/manager/apps/hycu/public/translations/hycu/error/Messages_es_ES.json b/packages/manager/apps/hycu/public/translations/hycu/error/Messages_es_ES.json new file mode 100644 index 000000000000..02cb3fbb1a80 --- /dev/null +++ b/packages/manager/apps/hycu/public/translations/hycu/error/Messages_es_ES.json @@ -0,0 +1,8 @@ +{ + "manager_error_page_title": "¡Vaya!", + "manager_error_page_button_cancel": "Cancelar", + "manager_error_page_detail_code": "Código de error: ", + "manager_error_page_action_reload_label": "Volver a intentarlo", + "manager_error_page_action_home_label": "Volver a la página de inicio", + "manager_error_page_default": "Se ha producido un error al cargar la página" +} diff --git a/packages/manager/apps/hycu/public/translations/hycu/error/Messages_fr_CA.json b/packages/manager/apps/hycu/public/translations/hycu/error/Messages_fr_CA.json new file mode 100644 index 000000000000..2c575c63588e --- /dev/null +++ b/packages/manager/apps/hycu/public/translations/hycu/error/Messages_fr_CA.json @@ -0,0 +1,8 @@ +{ + "manager_error_page_title": "Oops …!", + "manager_error_page_button_cancel": "Annuler", + "manager_error_page_detail_code": "Code d'erreur : ", + "manager_error_page_action_reload_label": "Réessayer", + "manager_error_page_action_home_label": "Retour à la page d'accueil", + "manager_error_page_default": "Une erreur est survenue lors du chargement de la page." +} diff --git a/packages/manager/apps/hycu/public/translations/hycu/error/Messages_fr_FR.json b/packages/manager/apps/hycu/public/translations/hycu/error/Messages_fr_FR.json new file mode 100644 index 000000000000..2c575c63588e --- /dev/null +++ b/packages/manager/apps/hycu/public/translations/hycu/error/Messages_fr_FR.json @@ -0,0 +1,8 @@ +{ + "manager_error_page_title": "Oops …!", + "manager_error_page_button_cancel": "Annuler", + "manager_error_page_detail_code": "Code d'erreur : ", + "manager_error_page_action_reload_label": "Réessayer", + "manager_error_page_action_home_label": "Retour à la page d'accueil", + "manager_error_page_default": "Une erreur est survenue lors du chargement de la page." +} diff --git a/packages/manager/apps/hycu/public/translations/hycu/error/Messages_it_IT.json b/packages/manager/apps/hycu/public/translations/hycu/error/Messages_it_IT.json new file mode 100644 index 000000000000..ce0517c42dde --- /dev/null +++ b/packages/manager/apps/hycu/public/translations/hycu/error/Messages_it_IT.json @@ -0,0 +1,8 @@ +{ + "manager_error_page_title": "Ops!", + "manager_error_page_button_cancel": "Annulla", + "manager_error_page_detail_code": "Codice di errore: ", + "manager_error_page_action_reload_label": "Riprova", + "manager_error_page_action_home_label": "Torna alla home page", + "manager_error_page_default": "Si è verificato un errore durante il caricamento della pagina." +} diff --git a/packages/manager/apps/hycu/public/translations/hycu/error/Messages_pl_PL.json b/packages/manager/apps/hycu/public/translations/hycu/error/Messages_pl_PL.json new file mode 100644 index 000000000000..6fc5dc1b135d --- /dev/null +++ b/packages/manager/apps/hycu/public/translations/hycu/error/Messages_pl_PL.json @@ -0,0 +1,8 @@ +{ + "manager_error_page_title": "Ups ...!", + "manager_error_page_button_cancel": "Anuluj", + "manager_error_page_detail_code": "Kod błędu: ", + "manager_error_page_action_reload_label": "Spróbuj ponownie", + "manager_error_page_action_home_label": "Powrót do strony głównej", + "manager_error_page_default": "Wystąpił błąd podczas ładowania strony." +} diff --git a/packages/manager/apps/hycu/public/translations/hycu/error/Messages_pt_PT.json b/packages/manager/apps/hycu/public/translations/hycu/error/Messages_pt_PT.json new file mode 100644 index 000000000000..1edd72c0f09a --- /dev/null +++ b/packages/manager/apps/hycu/public/translations/hycu/error/Messages_pt_PT.json @@ -0,0 +1,8 @@ +{ + "manager_error_page_title": "Oops!", + "manager_error_page_button_cancel": "Anular", + "manager_error_page_detail_code": "Código de erro: ", + "manager_error_page_action_reload_label": "Tentar novamente", + "manager_error_page_action_home_label": "Voltar à página inicial", + "manager_error_page_default": "Ocorreu um erro aquando do carregamento da página." +} diff --git a/packages/manager/apps/hycu/public/translations/hycu/listing/Messages_de_DE.json b/packages/manager/apps/hycu/public/translations/hycu/listing/Messages_de_DE.json new file mode 100644 index 000000000000..44a928fa9ff5 --- /dev/null +++ b/packages/manager/apps/hycu/public/translations/hycu/listing/Messages_de_DE.json @@ -0,0 +1,14 @@ +{ + "hycu_status_activated": "Aktiv", + "hycu_status_toActivate": "Zu aktivieren", + "hycu_status_pending": "Wird aktiviert", + "hycu_status_error": "Aktivierungsfehler", + "hycu_cloud_vm_pack_unknown": "Unbekanntes Paket", + "hycu_name": "Name", + "hycu_controller_id": "Controller-ID", + "hycu_status": "Status", + "hycu_commercial_name": "Pakettyp", + "hycu_subscribed_date": "Anmeldungsdatum", + "hycu_order": "Bestellen", + "hycu_service_listing_terminate": "kündigen" +} diff --git a/packages/manager/apps/hycu/public/translations/hycu/listing/Messages_en_GB.json b/packages/manager/apps/hycu/public/translations/hycu/listing/Messages_en_GB.json new file mode 100644 index 000000000000..7d8ec29cb2df --- /dev/null +++ b/packages/manager/apps/hycu/public/translations/hycu/listing/Messages_en_GB.json @@ -0,0 +1,14 @@ +{ + "hycu_status_activated": "Active", + "hycu_status_toActivate": "To activate", + "hycu_status_pending": "Enabling", + "hycu_status_error": "Activation error", + "hycu_cloud_vm_pack_unknown": "Unknown pack", + "hycu_name": "Name", + "hycu_controller_id": "Controller ID", + "hycu_status": "Status", + "hycu_commercial_name": "Pack type", + "hycu_subscribed_date": "Subscription date", + "hycu_order": "Order now", + "hycu_service_listing_terminate": "Cancel" +} diff --git a/packages/manager/apps/hycu/public/translations/hycu/listing/Messages_es_ES.json b/packages/manager/apps/hycu/public/translations/hycu/listing/Messages_es_ES.json new file mode 100644 index 000000000000..1e022f7e9b9c --- /dev/null +++ b/packages/manager/apps/hycu/public/translations/hycu/listing/Messages_es_ES.json @@ -0,0 +1,14 @@ +{ + "hycu_status_activated": "Activo", + "hycu_status_toActivate": "Por activar", + "hycu_status_pending": "En proceso de activación", + "hycu_status_error": "Error de activación", + "hycu_cloud_vm_pack_unknown": "Pack desconocido", + "hycu_name": "Nombre", + "hycu_controller_id": "Controller ID", + "hycu_status": "Estado", + "hycu_commercial_name": "Tipo de pack", + "hycu_subscribed_date": "Fecha de contratación", + "hycu_order": "Contratar", + "hycu_service_listing_terminate": "Dar de baja" +} diff --git a/packages/manager/apps/hycu/public/translations/hycu/listing/Messages_fr_CA.json b/packages/manager/apps/hycu/public/translations/hycu/listing/Messages_fr_CA.json new file mode 100644 index 000000000000..ea668aab4db9 --- /dev/null +++ b/packages/manager/apps/hycu/public/translations/hycu/listing/Messages_fr_CA.json @@ -0,0 +1,14 @@ +{ + "hycu_status_activated": "Active", + "hycu_status_toActivate": "À activer", + "hycu_status_pending": "En cours d'activation", + "hycu_status_error": "Erreur d'activation", + "hycu_cloud_vm_pack_unknown": "Pack inconnu", + "hycu_name": "Nom", + "hycu_controller_id": "Controller ID", + "hycu_status": "Statut", + "hycu_commercial_name": "Type de pack", + "hycu_subscribed_date": "Date de souscription", + "hycu_order": "Commander", + "hycu_service_listing_terminate": "Résilier" +} diff --git a/packages/manager/apps/hycu/public/translations/hycu/listing/Messages_fr_FR.json b/packages/manager/apps/hycu/public/translations/hycu/listing/Messages_fr_FR.json new file mode 100644 index 000000000000..ea668aab4db9 --- /dev/null +++ b/packages/manager/apps/hycu/public/translations/hycu/listing/Messages_fr_FR.json @@ -0,0 +1,14 @@ +{ + "hycu_status_activated": "Active", + "hycu_status_toActivate": "À activer", + "hycu_status_pending": "En cours d'activation", + "hycu_status_error": "Erreur d'activation", + "hycu_cloud_vm_pack_unknown": "Pack inconnu", + "hycu_name": "Nom", + "hycu_controller_id": "Controller ID", + "hycu_status": "Statut", + "hycu_commercial_name": "Type de pack", + "hycu_subscribed_date": "Date de souscription", + "hycu_order": "Commander", + "hycu_service_listing_terminate": "Résilier" +} diff --git a/packages/manager/apps/hycu/public/translations/hycu/listing/Messages_it_IT.json b/packages/manager/apps/hycu/public/translations/hycu/listing/Messages_it_IT.json new file mode 100644 index 000000000000..89cae0de4909 --- /dev/null +++ b/packages/manager/apps/hycu/public/translations/hycu/listing/Messages_it_IT.json @@ -0,0 +1,14 @@ +{ + "hycu_status_activated": "Attivo", + "hycu_status_toActivate": "Da attivare", + "hycu_status_pending": "Attivazione in corso", + "hycu_status_error": "Errore di attivazione", + "hycu_cloud_vm_pack_unknown": "Pack sconosciuto", + "hycu_name": "Cognome", + "hycu_controller_id": "Controller ID", + "hycu_status": "Status", + "hycu_commercial_name": "Tipo di pack", + "hycu_subscribed_date": "Data di sottoscrizione", + "hycu_order": "Ordina", + "hycu_service_listing_terminate": "Disattiva" +} diff --git a/packages/manager/apps/hycu/public/translations/hycu/listing/Messages_pl_PL.json b/packages/manager/apps/hycu/public/translations/hycu/listing/Messages_pl_PL.json new file mode 100644 index 000000000000..f64ed5b645c4 --- /dev/null +++ b/packages/manager/apps/hycu/public/translations/hycu/listing/Messages_pl_PL.json @@ -0,0 +1,14 @@ +{ + "hycu_status_activated": "Aktywny", + "hycu_status_toActivate": "Do aktywacji", + "hycu_status_pending": "W trakcie aktywacji", + "hycu_status_error": "Błąd aktywacji", + "hycu_cloud_vm_pack_unknown": "Nieznany pakiet", + "hycu_name": "Nazwisko", + "hycu_controller_id": "Controller ID", + "hycu_status": "Status", + "hycu_commercial_name": "Rodzaj pakietu", + "hycu_subscribed_date": "Data subskrypcji", + "hycu_order": "Zamów", + "hycu_service_listing_terminate": "Rezygnacja" +} diff --git a/packages/manager/apps/hycu/public/translations/hycu/listing/Messages_pt_PT.json b/packages/manager/apps/hycu/public/translations/hycu/listing/Messages_pt_PT.json new file mode 100644 index 000000000000..f5117b73140e --- /dev/null +++ b/packages/manager/apps/hycu/public/translations/hycu/listing/Messages_pt_PT.json @@ -0,0 +1,14 @@ +{ + "hycu_status_activated": "Ativado", + "hycu_status_toActivate": "A ativar", + "hycu_status_pending": "Ativação em curso", + "hycu_status_error": "Erro de ativação", + "hycu_cloud_vm_pack_unknown": "Pack desconhecido", + "hycu_name": "Nome", + "hycu_controller_id": "Controller ID", + "hycu_status": "Estado", + "hycu_commercial_name": "Tipo de pack", + "hycu_subscribed_date": "Data de subscrição", + "hycu_order": "Encomendar", + "hycu_service_listing_terminate": "Rescindir" +} diff --git a/packages/manager/apps/hycu/public/translations/hycu/onboarding/Messages_de_DE.json b/packages/manager/apps/hycu/public/translations/hycu/onboarding/Messages_de_DE.json new file mode 100644 index 000000000000..24b93a47ae87 --- /dev/null +++ b/packages/manager/apps/hycu/public/translations/hycu/onboarding/Messages_de_DE.json @@ -0,0 +1,11 @@ +{ + "orderButtonLabel": "Jetzt anfragen", + "moreInfoButtonLabel": "Mehr erfahren", + "hycu_onboarding_category_tutorial": "Anleitung", + "hycu_onboarding_guide1_title": "Guides und Dokumentation", + "hycu_onboarding_guide1_description": "Entdecken Sie unsere detaillierten Anleitungen und Dokumentationen, um Sie bei Ihrem Projekt zu unterstützen.", + "hycu_onboarding_guide2_title": "Nutanix on OVHcloud", + "hycu_onboarding_guide2_description": "Entdecken Sie unsere hyperkonvergente Plattform (HCI), die nicht nur skalierbar, sondern auch innerhalb weniger Stunden einsatzbereit ist. Diese Lösung ist als Paket- oder BYOL-Lösung (Bring Your Own Licence) verfügbar und kombiniert die Software-Lizenzen der Nutanix Cloud Platform (NCP) mit den dedizierten und für Nutanix qualifizierten Hosted Private Cloud Infrastrukturen von OVHcloud.", + "hycu_onboarding_guide3_title": "Disaster-Recovery-Plan (DRP)", + "hycu_onboarding_guide3_description": "Nutzen Sie HYCU für OVHcloud für eine kontrollierte und performante Disaster Recovery zu kontrollierten Kosten und ohne Überraschungen." +} diff --git a/packages/manager/apps/hycu/public/translations/hycu/onboarding/Messages_en_GB.json b/packages/manager/apps/hycu/public/translations/hycu/onboarding/Messages_en_GB.json new file mode 100644 index 000000000000..07c6020b3f09 --- /dev/null +++ b/packages/manager/apps/hycu/public/translations/hycu/onboarding/Messages_en_GB.json @@ -0,0 +1,11 @@ +{ + "orderButtonLabel": "Get started", + "moreInfoButtonLabel": "Find out more", + "hycu_onboarding_category_tutorial": "Tutorial", + "hycu_onboarding_guide1_title": "Guides and documentation", + "hycu_onboarding_guide1_description": "Explore our guides and detailed documentation to help you with your project.", + "hycu_onboarding_guide2_title": "Nutanix on OVHcloud", + "hycu_onboarding_guide2_description": "Discover our scalable, hyperconverged platform (HCI), ready to use in just a few hours Available as a pack or as a BYOL (Bring Your Own License) solution, it combines Nutanix Cloud Platform (NCP) software licenses with dedicated, Nutanix-qualified OVHcloud Hosted Private Cloud infrastructure.", + "hycu_onboarding_guide3_title": "Disaster Recovery Plan (DRP)", + "hycu_onboarding_guide3_description": "Rely on the HYCU for OVHcloud service for a controlled, high-performance disaster recovery, with a controlled cost, and no surprises." +} diff --git a/packages/manager/apps/hycu/public/translations/hycu/onboarding/Messages_es_ES.json b/packages/manager/apps/hycu/public/translations/hycu/onboarding/Messages_es_ES.json new file mode 100644 index 000000000000..9514b2bc6f8d --- /dev/null +++ b/packages/manager/apps/hycu/public/translations/hycu/onboarding/Messages_es_ES.json @@ -0,0 +1,11 @@ +{ + "orderButtonLabel": "Solicitar llamada", + "moreInfoButtonLabel": "Más información", + "hycu_onboarding_category_tutorial": "Tutorial", + "hycu_onboarding_guide1_title": "Guías y documentación", + "hycu_onboarding_guide1_description": "Descubra nuestras guías y documentación detalladas para ayudarle en su proyecto.", + "hycu_onboarding_guide2_title": "Nutanix on OVHcloud", + "hycu_onboarding_guide2_description": "Descubra nuestra plataforma hiperconvergente (HCI) escalable y lista para usar en solo unas horas. Disponible como solución en forma de pack o como solución BYOL (Bring Your Own Licence), combina las licencias de software de Nutanix Cloud Platform (NCP) con las infraestructuras Hosted Private Cloud de OVHcloud dedicadas y certificadas por Nutanix.", + "hycu_onboarding_guide3_title": "Plan de recuperación ante desastres (DRP)", + "hycu_onboarding_guide3_description": "Utilice HYCU for OVHcloud para disfrutar de una recuperación de la actividad controlada y potente, con un coste controlado y sin sorpresas." +} diff --git a/packages/manager/apps/hycu/public/translations/hycu/onboarding/Messages_fr_CA.json b/packages/manager/apps/hycu/public/translations/hycu/onboarding/Messages_fr_CA.json new file mode 100644 index 000000000000..150d27c36cf5 --- /dev/null +++ b/packages/manager/apps/hycu/public/translations/hycu/onboarding/Messages_fr_CA.json @@ -0,0 +1,11 @@ +{ + "orderButtonLabel": "Commencer", + "moreInfoButtonLabel": "En savoir plus", + "hycu_onboarding_category_tutorial": "Tutoriel", + "hycu_onboarding_guide1_title": "Guides et documentations", + "hycu_onboarding_guide1_description": "Découvrez nos guides et documentations détaillés pour vous accompagner dans votre projet.", + "hycu_onboarding_guide2_title": "Nutanix on OVHcloud", + "hycu_onboarding_guide2_description": "Découvrez notre plateforme hyperconvergée (HCI) évolutive et prête à l'emploi en quelques heures. Disponible en offre packagée ou offre BYOL (Bring Your Own Licence), elle associe les licences logicielles de la Nutanix Cloud Platform (NCP) et les infrastructures Hosted Private Cloud d'OVHcloud dédiées et qualifiées Nutanix.", + "hycu_onboarding_guide3_title": "Plan de Reprise d'Activité (PRA)", + "hycu_onboarding_guide3_description": "Appuyez-vous sur le service HYCU for OVHcloud pour une reprise d'activité contrôlée et performante, avec un coût maîtrisé et sans surprise." +} diff --git a/packages/manager/apps/hycu/public/translations/hycu/onboarding/Messages_fr_FR.json b/packages/manager/apps/hycu/public/translations/hycu/onboarding/Messages_fr_FR.json new file mode 100644 index 000000000000..150d27c36cf5 --- /dev/null +++ b/packages/manager/apps/hycu/public/translations/hycu/onboarding/Messages_fr_FR.json @@ -0,0 +1,11 @@ +{ + "orderButtonLabel": "Commencer", + "moreInfoButtonLabel": "En savoir plus", + "hycu_onboarding_category_tutorial": "Tutoriel", + "hycu_onboarding_guide1_title": "Guides et documentations", + "hycu_onboarding_guide1_description": "Découvrez nos guides et documentations détaillés pour vous accompagner dans votre projet.", + "hycu_onboarding_guide2_title": "Nutanix on OVHcloud", + "hycu_onboarding_guide2_description": "Découvrez notre plateforme hyperconvergée (HCI) évolutive et prête à l'emploi en quelques heures. Disponible en offre packagée ou offre BYOL (Bring Your Own Licence), elle associe les licences logicielles de la Nutanix Cloud Platform (NCP) et les infrastructures Hosted Private Cloud d'OVHcloud dédiées et qualifiées Nutanix.", + "hycu_onboarding_guide3_title": "Plan de Reprise d'Activité (PRA)", + "hycu_onboarding_guide3_description": "Appuyez-vous sur le service HYCU for OVHcloud pour une reprise d'activité contrôlée et performante, avec un coût maîtrisé et sans surprise." +} diff --git a/packages/manager/apps/hycu/public/translations/hycu/onboarding/Messages_it_IT.json b/packages/manager/apps/hycu/public/translations/hycu/onboarding/Messages_it_IT.json new file mode 100644 index 000000000000..ac111d7122aa --- /dev/null +++ b/packages/manager/apps/hycu/public/translations/hycu/onboarding/Messages_it_IT.json @@ -0,0 +1,11 @@ +{ + "orderButtonLabel": "Inizia ora", + "moreInfoButtonLabel": "Scopri di più", + "hycu_onboarding_category_tutorial": "Tutorial", + "hycu_onboarding_guide1_title": "Guide e documentazione", + "hycu_onboarding_guide1_description": "Scopri le nostre guide e la documentazione dettagliata per accompagnarti nel tuo progetto.", + "hycu_onboarding_guide2_title": "Nutanix on OVHcloud", + "hycu_onboarding_guide2_description": "Scopri la nostra piattaforma iperconvergente (HCI) scalabile e pronta all'uso in poche ore. Disponibile in pacchetti o BYOL (Bring Your Own Licence), questa soluzione combina le licenze software della Nutanix Cloud Platform (NCP) e le infrastrutture Hosted Private Cloud di OVHcloud dedicate e certificate Nutanix.", + "hycu_onboarding_guide3_title": "Disaster Recovery Plan (DRP)", + "hycu_onboarding_guide3_description": "Affidati al servizio HYCU per OVHcloud per una ripresa di attività controllata e performante, con un costo controllato e senza sorprese." +} diff --git a/packages/manager/apps/hycu/public/translations/hycu/onboarding/Messages_pl_PL.json b/packages/manager/apps/hycu/public/translations/hycu/onboarding/Messages_pl_PL.json new file mode 100644 index 000000000000..a29818b473e1 --- /dev/null +++ b/packages/manager/apps/hycu/public/translations/hycu/onboarding/Messages_pl_PL.json @@ -0,0 +1,11 @@ +{ + "orderButtonLabel": "Zapytaj", + "moreInfoButtonLabel": "Dowiedz się więcej", + "hycu_onboarding_category_tutorial": "Tutoriale", + "hycu_onboarding_guide1_title": "Przewodniki i dokumentacja", + "hycu_onboarding_guide1_description": "Poznaj nasze przewodniki i szczegółową dokumentację, które pomogą Ci zrealizować Twój projekt.", + "hycu_onboarding_guide2_title": "Nutanix on OVHcloud", + "hycu_onboarding_guide2_description": "Sprawdź naszą skalowalną, hiperkonwergentną platformę (HCI) gotową do użytku w ciągu kilku godzin. Rozwiązanie to, dostępne w pakietach lub w ramach oferty BYOL (Bring Your Own Licence), łączy w sobie licencje oprogramowania Nutanix Cloud Platform (NCP) oraz dedykowaną infrastrukturę Hosted Private Cloud z klasyfikacją Nutanix.", + "hycu_onboarding_guide3_title": "Plan Disaster Recovery (DRP)", + "hycu_onboarding_guide3_description": "Korzystaj z usługi HYCU dla OVHcloud do kontrolowanego i wydajnego przywracania usług, przy zachowaniu niskich kosztów i bez niespodzianek." +} diff --git a/packages/manager/apps/hycu/public/translations/hycu/onboarding/Messages_pt_PT.json b/packages/manager/apps/hycu/public/translations/hycu/onboarding/Messages_pt_PT.json new file mode 100644 index 000000000000..081e2b2a46d1 --- /dev/null +++ b/packages/manager/apps/hycu/public/translations/hycu/onboarding/Messages_pt_PT.json @@ -0,0 +1,11 @@ +{ + "orderButtonLabel": "Começar", + "moreInfoButtonLabel": "Saber mais", + "hycu_onboarding_category_tutorial": "Tutorial", + "hycu_onboarding_guide1_title": "Manuais e documentação", + "hycu_onboarding_guide1_description": "Descubra os nossos guias e documentação detalhados para o acompanhar no seu projeto.", + "hycu_onboarding_guide2_title": "Nutanix on OVHcloud", + "hycu_onboarding_guide2_description": "Descubra a nossa plataforma hiperconvergente (HCI) evolutiva e pronta a usar em apenas algumas horas. Disponível em oferta em pacote ou oferta BYOL (Bring Your Own Licence), associa as licenças de software da Nutanix Cloud Platform (NCP) às infraestruturas Hosted Private Cloud da OVHcloud dedicadas com certificação Nutanix.", + "hycu_onboarding_guide3_title": "Plano de recuperação de desastres (DRP)", + "hycu_onboarding_guide3_description": "Confie no serviço HYCU for OVHcloud para uma retoma de atividade controlada e com boa performance, a um custo controlado e sem surpresas." +} diff --git a/packages/manager/apps/hycu/src/App.tsx b/packages/manager/apps/hycu/src/App.tsx new file mode 100644 index 000000000000..9bedb39c2cae --- /dev/null +++ b/packages/manager/apps/hycu/src/App.tsx @@ -0,0 +1,35 @@ +import React, { useEffect, useContext } from 'react'; +import { QueryClientProvider, QueryClient } from '@tanstack/react-query'; +import { ReactQueryDevtools } from '@tanstack/react-query-devtools'; +import { odsSetup } from '@ovhcloud/ods-common-core'; +import { ShellContext } from '@ovh-ux/manager-react-shell-client'; +import { RouterProvider, createHashRouter } from 'react-router-dom'; +import { Routes } from './routes/routes'; + +odsSetup(); + +const queryClient = new QueryClient({ + defaultOptions: { + queries: { + staleTime: 300_000, + }, + }, +}); + +function App() { + const { shell } = useContext(ShellContext); + const router = createHashRouter(Routes); + + useEffect(() => { + shell.ux.hidePreloader(); + }, []); + + return ( + + + + + ); +} + +export default App; diff --git a/packages/manager/apps/hycu/src/assets/error-banner-oops.png b/packages/manager/apps/hycu/src/assets/error-banner-oops.png new file mode 100644 index 000000000000..413028afad19 Binary files /dev/null and b/packages/manager/apps/hycu/src/assets/error-banner-oops.png differ diff --git a/packages/manager/apps/hycu/src/components/Breadcrumb/Breadcrumb.component.tsx b/packages/manager/apps/hycu/src/components/Breadcrumb/Breadcrumb.component.tsx new file mode 100644 index 000000000000..0260f73b7499 --- /dev/null +++ b/packages/manager/apps/hycu/src/components/Breadcrumb/Breadcrumb.component.tsx @@ -0,0 +1,25 @@ +import React from 'react'; +import { OsdsBreadcrumb } from '@ovhcloud/ods-components/react'; +import { + useBreadcrumb, + BreadcrumbItem, +} from '@/hooks/breadcrumb/useBreadcrumb'; +import appConfig from '@/hycu.config'; + +export interface BreadcrumbProps { + customRootLabel?: string; + appName?: string; + items?: BreadcrumbItem[]; +} + +function Breadcrumb({ customRootLabel }: BreadcrumbProps): JSX.Element { + const label = customRootLabel || appConfig.rootLabel; + + const breadcrumbItems = useBreadcrumb({ + rootLabel: label, + appName: 'hycu', + }); + return ; +} + +export default Breadcrumb; diff --git a/packages/manager/apps/hycu/src/components/Error/Error.scss b/packages/manager/apps/hycu/src/components/Error/Error.scss new file mode 100644 index 000000000000..c73220cd3be3 --- /dev/null +++ b/packages/manager/apps/hycu/src/components/Error/Error.scss @@ -0,0 +1,18 @@ +.manager-error-page { + margin-left: auto; + margin-right: auto; + max-width: 600px; + width: 100%; + display: grid; + height: 100%; + overflow: hidden; + .manager-error-page-image { + img { + width: 100%; + } + } + .manager-error-page-footer { + text-align: right; + overflow: hidden; + } +} diff --git a/packages/manager/apps/hycu/src/components/Error/Error.tsx b/packages/manager/apps/hycu/src/components/Error/Error.tsx new file mode 100644 index 000000000000..66f2a411a7fa --- /dev/null +++ b/packages/manager/apps/hycu/src/components/Error/Error.tsx @@ -0,0 +1,52 @@ +import React from 'react'; +import { useLocation, useNavigate } from 'react-router-dom'; +import { ShellContext } from '@ovh-ux/manager-react-shell-client'; +import { + ErrorMessage, + TRACKING_LABELS, +} from '@ovh-ux/manager-react-components/src/components/'; +import { ErrorBanner } from '@ovh-ux/manager-react-components'; + +interface ErrorObject { + [key: string]: any; +} + +function getTrackingTypology(error: ErrorMessage) { + if (error?.detail?.status && Math.floor(error.detail.status / 100) === 4) { + return [401, 403].includes(error.detail.status) + ? TRACKING_LABELS.UNAUTHORIZED + : TRACKING_LABELS.SERVICE_NOT_FOUND; + } + return TRACKING_LABELS.PAGE_LOAD; +} + +const Errors: React.FC = ({ error }) => { + const navigate = useNavigate(); + const location = useLocation(); + const { shell } = React.useContext(ShellContext); + const { tracking, environment } = shell; + const env = environment.getEnvironment(); + + React.useEffect(() => { + env.then((response) => { + const { applicationName } = response; + const name = `errors::${getTrackingTypology(error)}::${applicationName}`; + tracking.trackPage({ + name, + level2: '81', + type: 'navigation', + page_category: location.pathname, + }); + }); + }, []); + + return ( + navigate(location.pathname, { replace: true })} + onRedirectHome={() => navigate('/', { replace: true })} + /> + ); +}; + +export default Errors; diff --git a/packages/manager/apps/hycu/src/components/Loading/Loading.component.tsx b/packages/manager/apps/hycu/src/components/Loading/Loading.component.tsx new file mode 100644 index 000000000000..bb74a4fa8e15 --- /dev/null +++ b/packages/manager/apps/hycu/src/components/Loading/Loading.component.tsx @@ -0,0 +1,10 @@ +import React from 'react'; +import { OsdsSpinner } from '@ovhcloud/ods-components/react'; + +export default function Loading() { + return ( + + + + ); +} diff --git a/packages/manager/apps/hycu/src/constants.ts b/packages/manager/apps/hycu/src/constants.ts new file mode 100644 index 000000000000..b519834748ef --- /dev/null +++ b/packages/manager/apps/hycu/src/constants.ts @@ -0,0 +1,9 @@ +export const packTypeLabel = { + 'hycu-cloud-vm-pack-25': '25 VMs', + 'hycu-cloud-vm-pack-50': '50 VMs', + 'hycu-cloud-vm-pack-100': '100 VMs', + 'hycu-cloud-vm-pack-150': '150 VMs', + 'hycu-cloud-vm-pack-200': '200 VMs', + 'hycu-cloud-vm-pack-250': '250 VMs', + 'hycu-cloud-vm-pack-500': '500 VMs', +} as const; diff --git a/packages/manager/apps/hycu/src/data/api/hycu.ts b/packages/manager/apps/hycu/src/data/api/hycu.ts new file mode 100644 index 000000000000..7068dc242d81 --- /dev/null +++ b/packages/manager/apps/hycu/src/data/api/hycu.ts @@ -0,0 +1,52 @@ +import { fetchIcebergV6, apiClient } from '@ovh-ux/manager-core-api'; + +export type GetlicenseHycuListParams = { + /** Filter resources on IAM tags */ + iamTags: any; +}; + +export const getlicenseHycuListQueryKey = ['get/license/hycu']; + +/** + * Manage HYCU licenses : Get list of owned HYCU licenses + */ +export const getlicenseHycuList = async ( + params: GetlicenseHycuListParams, +): Promise => apiClient.v6.get('/license/hycu', { data: params }); + +export type GetlicenseHycuServiceParams = { + /** Service name */ + serviceName?: string; +}; + +export const getlicenseHycuServiceQueryKey = ( + params: GetlicenseHycuServiceParams, +) => [`get/license/hycu/${params.serviceName}`]; + +/** + * Manage HYCU licenses : Get HYCU license info + */ +export const getlicenseHycuService = async ( + params: GetlicenseHycuServiceParams, +): Promise => apiClient.v6.get(`/license/hycu/${params.serviceName}`); + +/** + * Get listing with iceberg V6 + */ +export const getListingIcebergV6 = async ({ + pageSize, + page, +}: { + pageSize: number; + page: number; +}) => { + const { data, status, totalCount } = await fetchIcebergV6({ + route: `/license/hycu`, + pageSize, + page, + }); + if (status > 400) { + throw new Error(); + } + return { data, status, totalCount }; +}; diff --git a/packages/manager/apps/hycu/src/hooks/breadcrumb/useBreadcrumb.tsx b/packages/manager/apps/hycu/src/hooks/breadcrumb/useBreadcrumb.tsx new file mode 100644 index 000000000000..d61852b056a4 --- /dev/null +++ b/packages/manager/apps/hycu/src/hooks/breadcrumb/useBreadcrumb.tsx @@ -0,0 +1,49 @@ +import { useEffect, useState, useContext } from 'react'; +import { useLocation } from 'react-router-dom'; +import { ShellContext } from '@ovh-ux/manager-react-shell-client'; + +export type BreadcrumbItem = { + label: string | undefined; + href?: string; +}; + +export interface BreadcrumbProps { + rootLabel?: string; + appName?: string; + projectId?: string; + items?: BreadcrumbItem[]; +} + +export const useBreadcrumb = ({ rootLabel, appName }: BreadcrumbProps) => { + const { shell } = useContext(ShellContext); + const [root, setRoot] = useState([]); + const [paths, setPaths] = useState([]); + const location = useLocation(); + const pathnames = location.pathname.split('/').filter((x) => x); + + useEffect(() => { + const fetchRoot = async () => { + try { + const response = await shell?.navigation.getURL(appName, '#/', {}); + const rootItem = { + label: rootLabel, + href: String(response), + }; + setRoot([rootItem]); + } catch { + // Fetch navigation error + } + }; + fetchRoot(); + }, [rootLabel, appName, shell?.navigation]); + + useEffect(() => { + const pathsTab = pathnames.map((value) => ({ + label: value, + href: `/#/${appName}/${value}`, + })); + setPaths(pathsTab); + }, [location]); + + return [...root, ...paths]; +}; diff --git a/packages/manager/apps/hycu/src/hooks/guide/useGuideUtils.tsx b/packages/manager/apps/hycu/src/hooks/guide/useGuideUtils.tsx new file mode 100644 index 000000000000..e7ba1e87acfd --- /dev/null +++ b/packages/manager/apps/hycu/src/hooks/guide/useGuideUtils.tsx @@ -0,0 +1,170 @@ +import { useContext, useEffect, useState } from 'react'; +import { CountryCode } from '@ovh-ux/manager-config'; +import { ShellContext } from '@ovh-ux/manager-react-shell-client'; + +type TGuideLinks = { [key in CountryCode]: string }; + +const GUIDE_LIST: { [guideName: string]: Partial } = { + main: { + ASIA: 'https://www.ovhcloud.com/asia/storage-solutions/hycu/', + DE: 'https://www.ovhcloud.com/de/storage-solutions/hycu/', + ES: 'https://www.ovhcloud.com/es-es/storage-solutions/hycu/', + WS: 'https://www.ovhcloud.com/es/storage-solutions/hycu/', + IE: 'https://www.ovhcloud.com/en-ie/storage-solutions/hycu/', + IT: 'https://www.ovhcloud.com/it/storage-solutions/hycu/', + PL: 'https://www.ovhcloud.com/pl/storage-solutions/hycu/', + PT: 'https://www.ovhcloud.com/pt/storage-solutions/hycu/', + FR: 'https://www.ovhcloud.com/fr/storage-solutions/hycu/', + GB: 'https://www.ovhcloud.com/en-gb/storage-solutions/hycu/', + CA: 'https://www.ovhcloud.com/en-ca/storage-solutions/hycu/', + QC: 'https://www.ovhcloud.com/fr-ca/storage-solutions/hycu/', + US: 'https://www.ovhcloud.com/en/storage-solutions/hycu/', + AU: 'https://www.ovhcloud.com/en-au/storage-solutions/hycu/', + SG: 'https://www.ovhcloud.com/en-sg/storage-solutions/hycu/', + MA: 'https://www.ovhcloud.com/fr-ma/storage-solutions/hycu/', + SN: 'https://www.ovhcloud.com/fr-sn/storage-solutions/hycu/', + TN: 'https://www.ovhcloud.com/fr-tn/storage-solutions/hycu/', + NL: 'https://www.ovhcloud.com/nl/storage-solutions/hycu/', + IN: 'https://www.ovhcloud.com/en-in/storage-solutions/hycu/', + WE: 'https://www.ovhcloud.com/en/storage-solutions/hycu/', + }, + guideLink1: { + DE: + 'https://help.ovhcloud.com/csm/de-nutanix-hycu-backup?id=kb_article_view&sysparm_article=KB0045099', + ES: + 'https://help.ovhcloud.com/csm/es-es-nutanix-hycu-backup?id=kb_article_view&sysparm_article=KB0045102', + WS: + 'https://help.ovhcloud.com/csm/es-nutanix-hycu-backup?id=kb_article_view&sysparm_article=KB0045108', + IE: + 'https://help.ovhcloud.com/csm/en-ie-nutanix-hycu-backup?id=kb_article_view&sysparm_article=KB0045115', + IT: + 'https://help.ovhcloud.com/csm/it-nutanix-hycu-backup?id=kb_article_view&sysparm_article=KB0045120', + PL: + 'https://help.ovhcloud.com/csm/pl-nutanix-hycu-backup?id=kb_article_view&sysparm_article=KB0045111', + PT: + 'https://help.ovhcloud.com/csm/pt-nutanix-hycu-backup?id=kb_article_view&sysparm_article=KB0045112', + FR: + 'https://help.ovhcloud.com/csm/fr-nutanix-hycu-backup?id=kb_article_view&sysparm_article=KB0045116', + GB: + 'https://help.ovhcloud.com/csm/en-gb-nutanix-hycu-backup?id=kb_article_view&sysparm_article=KB0045103', + CA: + 'https://help.ovhcloud.com/csm/en-ca-nutanix-hycu-backup?id=kb_article_view&sysparm_article=KB0045101', + QC: + 'https://help.ovhcloud.com/csm/fr-ca-nutanix-hycu-backup?id=kb_article_view&sysparm_article=KB0045109', + WE: + 'https://help.ovhcloud.com/csm/en-nutanix-hycu-backup?id=kb_article_view&sysparm_article=KB0032260', + US: + 'https://support.us.ovhcloud.com/hc/en-us/articles/18912619822099-How-to-Configure-HYCU-Backup-on-Nutanix', + MA: + 'https://help.ovhcloud.com/csm/fr-nutanix-hycu-backup?id=kb_article_view&sysparm_article=KB0045116', + SN: + 'https://help.ovhcloud.com/csm/fr-nutanix-hycu-backup?id=kb_article_view&sysparm_article=KB0045116', + TN: + 'https://help.ovhcloud.com/csm/fr-nutanix-hycu-backup?id=kb_article_view&sysparm_article=KB0045116', + }, + guideLink2: { + FR: 'https://www.ovhcloud.com/fr/hosted-private-cloud/nutanix/', + US: 'https://us.ovhcloud.com/hosted-private-cloud/nutanix/', + DE: 'https://www.ovhcloud.com/de/hosted-private-cloud/nutanix/', + ES: 'https://www.ovhcloud.com/es-es/hosted-private-cloud/nutanix/', + GB: 'https://www.ovhcloud.com/en-gb/hosted-private-cloud/nutanix/', + IE: 'https://www.ovhcloud.com/en-ie/hosted-private-cloud/nutanix/', + IT: 'https://www.ovhcloud.com/it/hosted-private-cloud/nutanix/', + MA: 'https://www.ovhcloud.com/fr-ma/hosted-private-cloud/nutanix/', + NL: 'https://www.ovhcloud.com/nl/hosted-private-cloud/nutanix/', + PL: 'https://www.ovhcloud.com/pl/hosted-private-cloud/nutanix/', + PT: 'https://www.ovhcloud.com/pt/hosted-private-cloud/nutanix/', + SN: 'https://www.ovhcloud.com/fr-sn/hosted-private-cloud/nutanix/', + TN: 'https://www.ovhcloud.com/fr-tn/hosted-private-cloud/nutanix/', + CA: 'https://www.ovhcloud.com/en-ca/hosted-private-cloud/nutanix/', + QC: 'https://www.ovhcloud.com/fr-ca/hosted-private-cloud/nutanix/', + ASIA: 'https://www.ovhcloud.com/asia/hosted-private-cloud/nutanix/', + AU: 'https://www.ovhcloud.com/en-au/hosted-private-cloud/nutanix/', + SG: 'https://www.ovhcloud.com/en-sg/hosted-private-cloud/nutanix/', + WS: 'https://www.ovhcloud.com/es/hosted-private-cloud/nutanix/', + WE: 'https://www.ovhcloud.com/en/hosted-private-cloud/nutanix/', + }, + guideLink3: { + FR: + 'https://www.ovhcloud.com/fr/hosted-private-cloud/nutanix/uc-disaster-recovery-plan/', + GB: + 'https://www.ovhcloud.com/en-gb/hosted-private-cloud/nutanix/uc-disaster-recovery-plan/', + US: + 'https://us.ovhcloud.com/hosted-private-cloud/nutanix/uc-disaster-recovery-plan/', + DE: + 'https://www.ovhcloud.com/de/hosted-private-cloud/nutanix/uc-disaster-recovery-plan/', + ES: + 'https://www.ovhcloud.com/es-es/hosted-private-cloud/nutanix/uc-disaster-recovery-plan/', + IE: + 'https://www.ovhcloud.com/en-ie/hosted-private-cloud/nutanix/uc-disaster-recovery-plan/', + IT: + 'https://www.ovhcloud.com/it/hosted-private-cloud/nutanix/uc-disaster-recovery-plan/', + MA: + 'https://www.ovhcloud.com/fr-ma/hosted-private-cloud/nutanix/uc-disaster-recovery-plan/', + NL: + 'https://www.ovhcloud.com/nl/hosted-private-cloud/nutanix/uc-disaster-recovery-plan/', + PL: + 'https://www.ovhcloud.com/pl/hosted-private-cloud/nutanix/uc-disaster-recovery-plan/', + PT: + 'https://www.ovhcloud.com/pt/hosted-private-cloud/nutanix/uc-disaster-recovery-plan/', + SN: + 'https://www.ovhcloud.com/fr-sn/hosted-private-cloud/nutanix/uc-disaster-recovery-plan/', + TN: + 'https://www.ovhcloud.com/fr-tn/hosted-private-cloud/nutanix/uc-disaster-recovery-plan/', + CA: + 'https://www.ovhcloud.com/en-ca/hosted-private-cloud/nutanix/uc-disaster-recovery-plan/', + QC: + 'https://www.ovhcloud.com/fr-ca/hosted-private-cloud/nutanix/uc-disaster-recovery-plan/', + ASIA: + 'https://www.ovhcloud.com/asia/hosted-private-cloud/nutanix/uc-disaster-recovery-plan/', + AU: + 'https://www.ovhcloud.com/en-au/hosted-private-cloud/nutanix/uc-disaster-recovery-plan/', + SG: + 'https://www.ovhcloud.com/en-sg/hosted-private-cloud/nutanix/uc-disaster-recovery-plan/', + WS: + 'https://www.ovhcloud.com/es/hosted-private-cloud/nutanix/uc-disaster-recovery-plan/', + WE: + 'https://www.ovhcloud.com/en/hosted-private-cloud/nutanix/uc-disaster-recovery-plan/', + }, +}; + +type TGetGuideLinkProps = { + name?: string; + subsidiary: CountryCode | string; +}; + +interface IGuideLinkProps { + [guideName: string]: string; +} + +const DEFAULT_SUB_PAGE = 'GB'; + +function getGuideListLink({ subsidiary }: TGetGuideLinkProps) { + const list: IGuideLinkProps = {}; + const keys = Object.entries(GUIDE_LIST); + keys.forEach((key) => { + list[key[0]] = + GUIDE_LIST[key[0]][subsidiary as CountryCode] ?? + GUIDE_LIST[key[0]][DEFAULT_SUB_PAGE]; + }); + return list; +} + +function useGuideUtils() { + const { shell } = useContext(ShellContext); + const { environment } = shell; + const [list, setList] = useState({}); + + useEffect(() => { + const getSubSidiary = async () => { + const env = await environment.getEnvironment(); + const { ovhSubsidiary } = env.getUser(); + const guideList = getGuideListLink({ subsidiary: ovhSubsidiary }); + setList(guideList); + }; + getSubSidiary(); + }, []); + return list as IGuideLinkProps; +} + +export default useGuideUtils; diff --git a/packages/manager/apps/hycu/src/hooks/service/usePackLabel.spec.ts b/packages/manager/apps/hycu/src/hooks/service/usePackLabel.spec.ts new file mode 100644 index 000000000000..bcee312401b5 --- /dev/null +++ b/packages/manager/apps/hycu/src/hooks/service/usePackLabel.spec.ts @@ -0,0 +1,47 @@ +import { describe, expect, it, test, vi } from 'vitest'; +import { usePackTypeLabel } from './usePackLabel'; + +vi.mock('react-i18next', () => ({ + useTranslation: () => ({ + t: (translationKey: string) => `${translationKey}_translated`, + i18n: { + // eslint-disable-next-line @typescript-eslint/no-empty-function + changeLanguage: () => new Promise(() => {}), + }, + }), +})); + +describe('get service key type translation ', () => { + const useCases: { + type: string; + label: string; + }[] = [ + { + type: 'hycu-cloud-vm-pack-25', + label: '25 VMs', + }, + { + type: 'hycu-cloud-vm-pack-250', + label: '250 VMs', + }, + ]; + test.each(useCases)( + 'should return the right translation key for $type', + ({ type, label }) => { + // given type and translationKey + // when + const result = usePackTypeLabel(type); + // then + expect(result).toBe(label); + }, + ); + it('should return type if unexpected value', () => { + // given + const type = 'hycu-cloud-vm-pack-123'; + // when + const result = usePackTypeLabel(type); + + // then + expect(result).toBe('hycu_cloud_vm_pack_unknown_translated'); + }); +}); diff --git a/packages/manager/apps/hycu/src/hooks/service/usePackLabel.ts b/packages/manager/apps/hycu/src/hooks/service/usePackLabel.ts new file mode 100644 index 000000000000..617f8386e151 --- /dev/null +++ b/packages/manager/apps/hycu/src/hooks/service/usePackLabel.ts @@ -0,0 +1,11 @@ +import { useTranslation } from 'react-i18next'; +import { packTypeLabel } from '@/constants'; + +export const usePackTypeLabel = (packType: string) => { + const { t } = useTranslation('common'); + + return ( + packTypeLabel[packType as keyof typeof packTypeLabel] ?? + t('hycu_cloud_vm_pack_unknown') + ); +}; diff --git a/packages/manager/apps/hycu/src/hycu.config.ts b/packages/manager/apps/hycu/src/hycu.config.ts new file mode 100644 index 000000000000..a27a328f3525 --- /dev/null +++ b/packages/manager/apps/hycu/src/hycu.config.ts @@ -0,0 +1,8 @@ +export default { + listing: { + datagrid: { + serviceKey: 'hycu', + }, + }, + rootLabel: 'HYCU for OVHcloud', +}; diff --git a/packages/manager/apps/hycu/src/index.scss b/packages/manager/apps/hycu/src/index.scss new file mode 100644 index 000000000000..65dd5f63a7df --- /dev/null +++ b/packages/manager/apps/hycu/src/index.scss @@ -0,0 +1 @@ +@tailwind utilities; diff --git a/packages/manager/apps/hycu/src/index.tsx b/packages/manager/apps/hycu/src/index.tsx new file mode 100644 index 000000000000..f99c98002fcd --- /dev/null +++ b/packages/manager/apps/hycu/src/index.tsx @@ -0,0 +1,51 @@ +import React from 'react'; +import ReactDOM from 'react-dom/client'; +import { + ShellContext, + initShellContext, + initI18n, +} from '@ovh-ux/manager-react-shell-client'; +import App from './App'; +import '@ovhcloud/ods-theme-blue-jeans/dist/index.css'; +import './index.scss'; +import './vite-hmr'; + +import { UNIVERSE, SUB_UNIVERSE, APP_NAME, LEVEL2 } from './tracking.constant'; + +const trackingContext = { + chapter1: UNIVERSE, + chapter2: SUB_UNIVERSE, + chapter3: APP_NAME, + appName: APP_NAME, + pageTheme: UNIVERSE, + level2Config: LEVEL2, +}; + +const init = async (appName: string) => { + const context = await initShellContext(appName, trackingContext); + + await initI18n({ + context, + reloadOnLocaleChange: true, + defaultNS: appName, + ns: ['listing', 'dashboard', 'onboarding'], + }); + + const region = context.environment.getRegion(); + context.shell.tracking.setConfig(region, LEVEL2); + try { + await import(`./config-${region}.js`); + } catch (error) { + // nothing to do + } + + ReactDOM.createRoot(document.getElementById('root')!).render( + + + + + , + ); +}; + +init('hycu'); diff --git a/packages/manager/apps/hycu/src/mocks/index.ts b/packages/manager/apps/hycu/src/mocks/index.ts new file mode 100644 index 000000000000..202f88045626 --- /dev/null +++ b/packages/manager/apps/hycu/src/mocks/index.ts @@ -0,0 +1 @@ +export * from './licenseHycu/licenseHycu'; diff --git a/packages/manager/apps/hycu/src/mocks/licenseHycu/licenseHycu.data.ts b/packages/manager/apps/hycu/src/mocks/licenseHycu/licenseHycu.data.ts new file mode 100644 index 000000000000..260accd6ab47 --- /dev/null +++ b/packages/manager/apps/hycu/src/mocks/licenseHycu/licenseHycu.data.ts @@ -0,0 +1,28 @@ +import { IHycuDetails, LicenseStatus } from '@/type/hycu.details.interface'; + +export const licensesHycu: IHycuDetails[] = [ + { + iam: { + id: '4a26ef55-d46b-4b71-88c8-76ad71b154b4', + urn: + 'urn:v1:eu:resource:licenseHycu:425802fa-fb70-4b2a-9d5b-ec4de86bb40c', + }, + comment: '', + serviceName: '425802fa-fb70-4b2a-9d5b-ec4de86bb40c', + controllerId: '', + licenseStatus: LicenseStatus.TO_ACTIVATE, + expirationDate: '0001-01-01T00:00:00Z', + }, + { + iam: { + id: '06a89efa-cf14-431b-ab84-af5b3913e2ef', + urn: + 'urn:v1:eu:resource:licenseHycu:c1b7cb4f-6b63-45da-9a8a-f731f1a67b2c', + }, + comment: '', + serviceName: 'c1b7cb4f-6b63-45da-9a8a-f731f1a67b2c', + controllerId: '', + licenseStatus: LicenseStatus.ACTIVATED, + expirationDate: '0001-01-01T00:00:00Z', + }, +]; diff --git a/packages/manager/apps/hycu/src/mocks/licenseHycu/licenseHycu.ts b/packages/manager/apps/hycu/src/mocks/licenseHycu/licenseHycu.ts new file mode 100644 index 000000000000..664d5fb4e95f --- /dev/null +++ b/packages/manager/apps/hycu/src/mocks/licenseHycu/licenseHycu.ts @@ -0,0 +1,25 @@ +import { Handler } from '../../../../../../../playwright-helpers'; +import { licensesHycu } from './licenseHycu.data'; + +export type GetLicenseHycuMocksParams = { + isGetLicenseHycuKo?: boolean; + nbLicenseHycu?: number; +}; + +export const getLicenseHycuMocks = ({ + isGetLicenseHycuKo, + nbLicenseHycu = Number.POSITIVE_INFINITY, +}: GetLicenseHycuMocksParams): Handler[] => { + return [ + { + url: 'license/hycu', + response: isGetLicenseHycuKo + ? { + message: 'Backup error', + } + : licensesHycu.slice(0, nbLicenseHycu), + status: isGetLicenseHycuKo ? 500 : 200, + api: 'v6', + }, + ]; +}; diff --git a/packages/manager/apps/hycu/src/pages/404.tsx b/packages/manager/apps/hycu/src/pages/404.tsx new file mode 100644 index 000000000000..d052f1ebcbbf --- /dev/null +++ b/packages/manager/apps/hycu/src/pages/404.tsx @@ -0,0 +1,7 @@ +import React from 'react'; + +export default function NotFound() { + // @TODO: add a redirection here in order to catch /:serviceName given from iframe + + return 404 - route not found; +} diff --git a/packages/manager/apps/hycu/src/pages/dashboard/Dashboard.page.tsx b/packages/manager/apps/hycu/src/pages/dashboard/Dashboard.page.tsx new file mode 100644 index 000000000000..665a301e9a95 --- /dev/null +++ b/packages/manager/apps/hycu/src/pages/dashboard/Dashboard.page.tsx @@ -0,0 +1,89 @@ +import React, { useState, useEffect } from 'react'; +import { useTranslation } from 'react-i18next'; +import { + Outlet, + NavLink, + useLocation, + useNavigate, + useParams, + useResolvedPath, +} from 'react-router-dom'; +import { + OsdsTabs, + OsdsTabBar, + OsdsTabBarItem, +} from '@ovhcloud/ods-components/react'; + +import { BaseLayout } from '@ovh-ux/manager-react-components'; + +import Breadcrumb from '@/components/Breadcrumb/Breadcrumb.component'; + +export type DashboardTabItemProps = { + name: string; + title: string; + to: string; +}; + +export type DashboardLayoutProps = { + tabs: DashboardTabItemProps[]; +}; + +export default function DashboardPage() { + const [panel, setActivePanel] = useState(''); + const location = useLocation(); + const navigate = useNavigate(); + const { t } = useTranslation('dashboard'); + + const tabsList = [ + { + name: 'general_informations', + title: 'Informations générales', + to: useResolvedPath('').pathname, + }, + { + name: 'Tab 2', + title: 'Tab 2', + to: useResolvedPath('Tab2').pathname, + }, + ] as const; + + useEffect(() => { + const activeTab = tabsList.find((tab) => tab.to === location.pathname); + if (activeTab) { + setActivePanel(activeTab.name); + } else { + setActivePanel(tabsList[0].name); + navigate(`${tabsList[0].to}`); + } + }, [location.pathname]); + + const header = { + title: t('title'), + }; + + return ( + } + header={header} + description="Description du hycu" + tabs={ + + + {tabsList.map((tab: DashboardTabItemProps) => ( + + + {tab.title} + + + ))} + + + } + > + + + ); +} diff --git a/packages/manager/apps/hycu/src/pages/dashboard/general-information/DashboardGeneralInformation.page.tsx b/packages/manager/apps/hycu/src/pages/dashboard/general-information/DashboardGeneralInformation.page.tsx new file mode 100644 index 000000000000..a785e6d2ff0f --- /dev/null +++ b/packages/manager/apps/hycu/src/pages/dashboard/general-information/DashboardGeneralInformation.page.tsx @@ -0,0 +1,7 @@ +import React from 'react'; + +function GeneralInfos() { + return Information Générales Tab; +} + +export default GeneralInfos; diff --git a/packages/manager/apps/hycu/src/pages/dashboard/tab2/index.tsx b/packages/manager/apps/hycu/src/pages/dashboard/tab2/index.tsx new file mode 100644 index 000000000000..9cb100623734 --- /dev/null +++ b/packages/manager/apps/hycu/src/pages/dashboard/tab2/index.tsx @@ -0,0 +1,7 @@ +import React from 'react'; + +function Tab2() { + return Tab 2; +} + +export default Tab2; diff --git a/packages/manager/apps/hycu/src/pages/index.tsx b/packages/manager/apps/hycu/src/pages/index.tsx new file mode 100644 index 000000000000..5e7124b938c9 --- /dev/null +++ b/packages/manager/apps/hycu/src/pages/index.tsx @@ -0,0 +1,13 @@ +import React from 'react'; +import { useTranslation } from 'react-i18next'; + +export default function Hycu() { + const { t } = useTranslation('hycu'); + + return ( + + {t('title')} + Start your application + + ); +} diff --git a/packages/manager/apps/hycu/src/pages/layout.tsx b/packages/manager/apps/hycu/src/pages/layout.tsx new file mode 100644 index 000000000000..913e7665b627 --- /dev/null +++ b/packages/manager/apps/hycu/src/pages/layout.tsx @@ -0,0 +1,31 @@ +import React, { useEffect, useContext } from 'react'; +import { defineCurrentPage } from '@ovh-ux/request-tagger'; +import { Outlet, useLocation, useMatches } from 'react-router-dom'; +import { + useOvhTracking, + useRouteSynchro, + ShellContext, +} from '@ovh-ux/manager-react-shell-client'; + +export default function Layout() { + const location = useLocation(); + const { shell } = useContext(ShellContext); + const matches = useMatches(); + const { trackCurrentPage } = useOvhTracking(); + useRouteSynchro(); + + useEffect(() => { + const match = matches.slice(-1); + defineCurrentPage(`app.hycu-${match[0]?.id}`); + }, [location]); + + useEffect(() => { + trackCurrentPage(); + }, [location]); + + useEffect(() => { + shell.ux.hidePreloader(); + }, []); + + return ; +} diff --git a/packages/manager/apps/hycu/src/pages/listing/Listing.page.tsx b/packages/manager/apps/hycu/src/pages/listing/Listing.page.tsx new file mode 100644 index 000000000000..89ffb56d055f --- /dev/null +++ b/packages/manager/apps/hycu/src/pages/listing/Listing.page.tsx @@ -0,0 +1,229 @@ +import React, { useMemo } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useNavigate } from 'react-router-dom'; + +import { + OsdsButton, + OsdsChip, + OsdsMessage, + OsdsSkeleton, +} from '@ovhcloud/ods-components/react'; +import { + Datagrid, + DataGridTextCell, + useResourcesIcebergV6, + RedirectionGuard, + BaseLayout, + Links, + useServiceDetails, +} from '@ovh-ux/manager-react-components'; + +import { ODS_THEME_COLOR_INTENT } from '@ovhcloud/ods-common-theming'; +import { + ODS_BUTTON_VARIANT, + ODS_CHIP_SIZE, + ODS_MESSAGE_TYPE, + ODS_BUTTON_SIZE, +} from '@ovhcloud/ods-components'; +import { + DateFormat, + useFormattedDate, +} from '@ovh-ux/manager-react-components/src/hooks/date/useFormattedDate'; +import HYCU_CONFIG from '@/hycu.config'; +import { IHycuDetails } from '@/type/hycu.details.interface'; + +import { urls, subRoutes } from '@/routes/routes.constant'; +import { usePackTypeLabel } from '@/hooks/service/usePackLabel'; +import HycuActionMenu from './menu/HycuActionMenu.component'; +import { getStatusColor } from '@/utils/statusColor'; + +const dateFormat: Intl.DateTimeFormatOptions = { + day: '2-digit', + month: '2-digit', + year: 'numeric', +}; + +/* ========= datagrid cells ========= */ +const DatagridIdCell = (hycuDetail: IHycuDetails) => { + const navigate = useNavigate(); + + return ( + + + navigate( + urls.dashboard.replace( + subRoutes.serviceName, + hycuDetail.serviceName, + ), + ) + } + label={hycuDetail.serviceName} + > + + ); +}; + +const DatagridControllerIdCell = (hycuDetail: IHycuDetails) => { + return {hycuDetail.controllerId}; +}; + +const DatagridStatusCell = (hycuDetail: IHycuDetails) => { + const { t } = useTranslation('hycu/listing'); + + return ( + + + {t([`hycu_status_${hycuDetail.licenseStatus}`, 'hycu_status_error'])} + + + ); +}; + +const DatagridCommercialNameCell = (hycuDetail: IHycuDetails) => { + const { data: serviceDetails, isLoading } = useServiceDetails({ + resourceName: hycuDetail.serviceName, + }); + + const productName = usePackTypeLabel( + serviceDetails?.data.resource.product.name, + ); + + return ( + + {isLoading ? : productName} + + ); +}; + +const DatagridCreatedDateCell = (hycuDetail: IHycuDetails) => { + const { data: serviceDetails, isLoading } = useServiceDetails({ + resourceName: hycuDetail.serviceName, + }); + const creationDate = + serviceDetails?.data.billing.lifecycle.current.creationDate; + const formattedDate = useFormattedDate({ + dateString: creationDate as string, + format: DateFormat.compact, + }); + + return ( + + {isLoading ? : formattedDate} + + ); +}; + +const DatagridActionCell = (hycuDetail: IHycuDetails) => { + return ( + + + + ); +}; + +export default function Listing() { + const { t } = useTranslation('hycu/listing'); + const { t: tCommon } = useTranslation('hycu'); + const { t: tError } = useTranslation('hycu/error'); + const { + flattenData, + isError, + totalCount, + hasNextPage, + fetchNextPage, + isLoading, + status, + sorting, + setSorting, + } = useResourcesIcebergV6({ + route: '/license/hycu', + queryKey: ['hycu', '/license/hycu'], + }); + + const columns = useMemo(() => { + return [ + { + id: 'name', + label: t('hycu_name'), + cell: DatagridIdCell, + }, + { + id: 'controller_id', + label: t('hycu_controller_id'), + cell: DatagridControllerIdCell, + }, + { + id: 'status', + label: t('hycu_status'), + cell: DatagridStatusCell, + }, + { + id: 'commercial_name', + label: t('hycu_commercial_name'), + cell: DatagridCommercialNameCell, + }, + { + id: 'subscribed_date', + label: t('hycu_subscribed_date'), + cell: DatagridCreatedDateCell, + }, + { + id: 'action', + label: '', + cell: DatagridActionCell, + }, + ]; + }, []); + + const header = { + title: HYCU_CONFIG.rootLabel, + description: tCommon('hycu_description'), + }; + + return ( + + {tError('manager_error_page_default')} + + } + > + + + + + + {t('hycu_order')} + + + {columns && flattenData && ( + + )} + + + + + ); +} diff --git a/packages/manager/apps/hycu/src/pages/listing/Listing.spec.tsx b/packages/manager/apps/hycu/src/pages/listing/Listing.spec.tsx new file mode 100644 index 000000000000..396747dc0831 --- /dev/null +++ b/packages/manager/apps/hycu/src/pages/listing/Listing.spec.tsx @@ -0,0 +1,48 @@ +import { act, screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { renderTestApp } from '@/utils/tests/renderTestApp'; +import '@testing-library/jest-dom'; +import { labels } from '@/utils/tests/init.i18n'; +import { licensesHycu } from '@/mocks/licenseHycu/licenseHycu.data'; +import HYCU_CONFIG from '@/hycu.config'; + +describe('License Hycu listing test suite', () => { + it('should redirect to the onboarding page when the license hycu list is empty', async () => { + await renderTestApp({ nbLicenseHycu: 0 }); + + expect(screen.getByText(HYCU_CONFIG.rootLabel)).toBeVisible(); + expect( + screen.getByText(labels.onboarding.hycu_onboarding_guide1_title), + ).toBeInTheDocument(); + + expect( + screen.queryByText(labels.listing.hycu_name), + ).not.toBeInTheDocument(); + }); + + it('should display the hycu listing page', async () => { + await renderTestApp(); + + expect(screen.getByText(labels.listing.hycu_order)).toBeVisible(); + + expect( + screen.queryByText(labels.onboarding.hycu_onboarding_guide1_title), + ).not.toBeInTheDocument(); + }); + + it('should navigate to a hycu dashboard on click on license hycu name', async () => { + await renderTestApp(); + + await act(() => + userEvent.click(screen.getByText(licensesHycu[0].serviceName)), + ); + + await waitFor( + () => + expect( + screen.getByText(labels.dashboard.general_informations), + ).toBeVisible(), + { timeout: 30_000 }, + ); + }); +}); diff --git a/packages/manager/apps/hycu/src/pages/listing/menu/HycuActionMenu.component.tsx b/packages/manager/apps/hycu/src/pages/listing/menu/HycuActionMenu.component.tsx new file mode 100644 index 000000000000..24d7466a0bbc --- /dev/null +++ b/packages/manager/apps/hycu/src/pages/listing/menu/HycuActionMenu.component.tsx @@ -0,0 +1,31 @@ +import { ActionMenu, ActionMenuItem } from '@ovh-ux/manager-react-components'; +import { ODS_THEME_COLOR_INTENT } from '@ovhcloud/ods-common-theming'; +import React from 'react'; +import { ODS_ICON_NAME } from '@ovhcloud/ods-components'; +import { useTranslation } from 'react-i18next'; +import { IHycuDetails } from '@/type/hycu.details.interface'; + +const HycuActionMenu = ({ + serviceName: _serviceName, +}: Pick) => { + const { t } = useTranslation('hycu/listing'); + + const items: ActionMenuItem[] = [ + { + id: 1, + label: t('hycu_service_listing_terminate'), + color: ODS_THEME_COLOR_INTENT.error, + onClick: () => {}, + }, + ]; + + return ( + + ); +}; + +export default HycuActionMenu; diff --git a/packages/manager/apps/hycu/src/pages/onboarding/Onboarding.page.tsx b/packages/manager/apps/hycu/src/pages/onboarding/Onboarding.page.tsx new file mode 100644 index 000000000000..3e8b8641a796 --- /dev/null +++ b/packages/manager/apps/hycu/src/pages/onboarding/Onboarding.page.tsx @@ -0,0 +1,65 @@ +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import { Card, OnboardingLayout } from '@ovh-ux/manager-react-components'; +import useGuideUtils from '@/hooks/guide/useGuideUtils'; +import onboardingImgSrc from './hycu-x-ovhcloud.svg'; +import HYCU_CONFIG from '@/hycu.config'; + +export default function Onboarding() { + const { t } = useTranslation('hycu/onboarding'); + const { t: tCommon } = useTranslation('hycu'); + const link = useGuideUtils(); + + const tileList = [ + { + id: 1, + texts: { + title: t('hycu_onboarding_guide1_title'), + description: t('hycu_onboarding_guide1_description'), + category: t('hycu_onboarding_category_tutorial'), + }, + href: link?.guideLink1, + }, + { + id: 2, + texts: { + title: t('hycu_onboarding_guide2_title'), + description: t('hycu_onboarding_guide2_description'), + category: t('hycu_onboarding_category_tutorial'), + }, + href: link?.guideLink2, + }, + { + id: 3, + texts: { + title: t('hycu_onboarding_guide3_title'), + description: t('hycu_onboarding_guide3_description'), + category: t('hycu_onboarding_category_tutorial'), + }, + href: link?.guideLink3, + }, + ]; + + const title: string = HYCU_CONFIG.rootLabel; + const description: string = tCommon('hycu_description'); + const imgSrc: React.ComponentProps<'img'> = { + src: onboardingImgSrc, + className: 'max-h-36 w-max-w-9/12', + }; + + return ( + + {tileList.map((tile) => ( + + ))} + + ); +} diff --git a/packages/manager/apps/hycu/src/pages/onboarding/hycu-x-ovhcloud.svg b/packages/manager/apps/hycu/src/pages/onboarding/hycu-x-ovhcloud.svg new file mode 100644 index 000000000000..ba7f6ad856f6 --- /dev/null +++ b/packages/manager/apps/hycu/src/pages/onboarding/hycu-x-ovhcloud.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/manager/apps/hycu/src/pages/onboarding/index.scss b/packages/manager/apps/hycu/src/pages/onboarding/index.scss new file mode 100644 index 000000000000..995e5c3b0be6 --- /dev/null +++ b/packages/manager/apps/hycu/src/pages/onboarding/index.scss @@ -0,0 +1,10 @@ +.tile-grid { + display: grid; + grid-template-columns: repeat(2, 1fr); + grid-gap: 30px; + padding-top: 3rem; + + @media (min-width: 1024px) { + grid-template-columns: repeat(3, 1fr); + } +} diff --git a/packages/manager/apps/hycu/src/routes/routes.constant.ts b/packages/manager/apps/hycu/src/routes/routes.constant.ts new file mode 100644 index 000000000000..61e0fa44744f --- /dev/null +++ b/packages/manager/apps/hycu/src/routes/routes.constant.ts @@ -0,0 +1,12 @@ +export const subRoutes = { + onboarding: 'onboarding', + serviceName: ':serviceName', +}; + +export const urls = { + root: '/', + onboarding: `/${subRoutes.onboarding}`, + listing: '/', + dashboard: `/${subRoutes.serviceName}`, + tab2: 'Tab2', +} as const; diff --git a/packages/manager/apps/hycu/src/routes/routes.tsx b/packages/manager/apps/hycu/src/routes/routes.tsx new file mode 100644 index 000000000000..0fa1bc776da3 --- /dev/null +++ b/packages/manager/apps/hycu/src/routes/routes.tsx @@ -0,0 +1,84 @@ +import React from 'react'; +import { RouteObject } from 'react-router-dom'; +import { PageType } from '@ovh-ux/manager-react-shell-client'; +import NotFound from '@/pages/404'; +import { urls } from '@/routes/routes.constant'; + +const lazyRouteConfig = (importFn: CallableFunction): Partial => { + return { + lazy: async () => { + const { default: moduleDefault, ...moduleExports } = await importFn(); + return { + Component: moduleDefault, + ...moduleExports, + }; + }, + }; +}; + +export const Routes: any = [ + { + path: urls.root, + ...lazyRouteConfig(() => import('@/pages/layout')), + children: [ + { + id: 'listing', + path: urls.listing, + ...lazyRouteConfig(() => import('@/pages/listing/Listing.page')), + handle: { + tracking: { + pageName: 'listing', + pageType: PageType.listing, + }, + }, + }, + { + path: urls.dashboard, + ...lazyRouteConfig(() => import('@/pages/dashboard/Dashboard.page')), + children: [ + { + id: 'dashboard', + path: '', + ...lazyRouteConfig(() => + import( + '@/pages/dashboard/general-information/DashboardGeneralInformation.page' + ), + ), + handle: { + tracking: { + pageName: 'dashboard', + pageType: PageType.dashboard, + }, + }, + }, + { + id: 'dashboard.tab2', + path: 'Tab2', + ...lazyRouteConfig(() => import('@/pages/dashboard/tab2')), + handle: { + tracking: { + pageName: 'tab2', + pageType: PageType.dashboard, + }, + }, + }, + ], + }, + { + id: 'onboarding', + path: urls.onboarding, + ...lazyRouteConfig(() => import('@/pages/onboarding/Onboarding.page')), + handle: { + tracking: { + pageName: 'onboarding', + pageType: PageType.onboarding, + }, + }, + }, + ], + }, + { + path: '*', + element: , + }, +]; diff --git a/packages/manager/apps/hycu/src/setupTests.tsx b/packages/manager/apps/hycu/src/setupTests.tsx new file mode 100644 index 000000000000..141b5063ffb0 --- /dev/null +++ b/packages/manager/apps/hycu/src/setupTests.tsx @@ -0,0 +1,39 @@ +import { odsSetup } from '@ovhcloud/ods-common-core'; +import { SetupServer, setupServer } from 'msw/node'; +import { toMswHandlers } from '../../../../../playwright-helpers'; +import { getAuthenticationMocks } from '../../../../../playwright-helpers/mocks/auth'; +import '@testing-library/jest-dom'; +import 'element-internals-polyfill'; + +odsSetup(); + +declare global { + // eslint-disable-next-line vars-on-top, no-var + var server: SetupServer; + // eslint-disable-next-line vars-on-top, no-var, @typescript-eslint/naming-convention + var __VERSION__: string; +} + +const server = setupServer( + ...toMswHandlers([ + ...getAuthenticationMocks({ isAuthMocked: true, region: 'EU' }), + ]), +); + +beforeAll(() => { + server.listen({ onUnhandledRequest: 'warn' }); + + delete global.server; + global.__VERSION__ = null; + global.server = server; +}); + +afterAll(() => { + server.close(); + + delete global.__VERSION__; +}); + +afterEach(() => { + server.resetHandlers(); +}); diff --git a/packages/manager/apps/hycu/src/tracking.constant.ts b/packages/manager/apps/hycu/src/tracking.constant.ts new file mode 100644 index 000000000000..e18081d08218 --- /dev/null +++ b/packages/manager/apps/hycu/src/tracking.constant.ts @@ -0,0 +1,20 @@ +export const LEVEL2 = { + EU: { + config: { + level2: '98', + }, + }, + CA: { + config: { + level2: '98', + }, + }, + US: { + config: { + level2: '98', + }, + }, +} as const; +export const UNIVERSE = 'HostedPrivatedCloud'; +export const SUB_UNIVERSE = 'HostedPrivatedCloud'; +export const APP_NAME = 'hycu'; diff --git a/packages/manager/apps/hycu/src/type/hycu.details.interface.ts b/packages/manager/apps/hycu/src/type/hycu.details.interface.ts new file mode 100644 index 000000000000..64b1af7066ff --- /dev/null +++ b/packages/manager/apps/hycu/src/type/hycu.details.interface.ts @@ -0,0 +1,42 @@ +export enum LicenseStatus { + ACTIVATED = 'activated', + TO_ACTIVATE = 'toActivate', + PENDING = 'pending', + ERROR = 'error', +} + +export interface IamDetails { + id: string; + urn: string; + serviceName?: string; +} + +export interface IHycuDetails { + controllerId: string; + comment: string; + expirationDate: string; + iam: IamDetails; + licenseStatus: LicenseStatus; + serviceName: string; +} +export interface IHycuServiceInfo { + canDeleteAtExpiration: false; + contactAdmin: string; + contactBilling: string; + contactTech: string; + creation: string; + domain: string; + engagedUpTo: string; + expiration: string; + possibleRenewPeriod: number[]; + renew: { + automatic: boolean; + deleteAtExpiration: boolean; + forced: boolean; + manualPayment: boolean; + period: number; + }; + renewalType: 'automaticForcedProduct'; + serviceId: number; + status: 'expired'; +} diff --git a/packages/manager/apps/hycu/src/utils/statusColor.ts b/packages/manager/apps/hycu/src/utils/statusColor.ts new file mode 100644 index 000000000000..1aedb85a5ad8 --- /dev/null +++ b/packages/manager/apps/hycu/src/utils/statusColor.ts @@ -0,0 +1,18 @@ +import { ODS_THEME_COLOR_INTENT } from '@ovhcloud/ods-common-theming'; +import { LicenseStatus } from '@/type/hycu.details.interface'; + +export const getStatusColor = ( + licenseStatus: LicenseStatus, +): ODS_THEME_COLOR_INTENT => { + switch (licenseStatus) { + case LicenseStatus.ACTIVATED: + return ODS_THEME_COLOR_INTENT.success; + case LicenseStatus.TO_ACTIVATE: + return ODS_THEME_COLOR_INTENT.warning; + case LicenseStatus.PENDING: + return ODS_THEME_COLOR_INTENT.primary; + case LicenseStatus.ERROR: + default: + return ODS_THEME_COLOR_INTENT.error; + } +}; diff --git a/packages/manager/apps/hycu/src/utils/tests/TestApp.tsx b/packages/manager/apps/hycu/src/utils/tests/TestApp.tsx new file mode 100644 index 000000000000..b016f4d6ec24 --- /dev/null +++ b/packages/manager/apps/hycu/src/utils/tests/TestApp.tsx @@ -0,0 +1,21 @@ +import React from 'react'; +import { QueryClientProvider, QueryClient } from '@tanstack/react-query'; +import { createMemoryRouter, RouterProvider } from 'react-router-dom'; +import { Routes } from '../../routes/routes'; + +export function TestApp() { + const router = createMemoryRouter(Routes, { + initialEntries: ['/'], + initialIndex: 0, + }); + + const queryClient = new QueryClient({ + defaultOptions: { queries: { retry: false }, mutations: { retry: false } }, + }); + + return ( + + + + ); +} diff --git a/packages/manager/apps/hycu/src/utils/tests/init.i18n.ts b/packages/manager/apps/hycu/src/utils/tests/init.i18n.ts new file mode 100644 index 000000000000..9af278be892c --- /dev/null +++ b/packages/manager/apps/hycu/src/utils/tests/init.i18n.ts @@ -0,0 +1,52 @@ +import i18next, { i18n } from 'i18next'; +import common from '../../../public/translations/hycu/Messages_fr_FR.json'; +import dashboard from '../../../public/translations/dashboard/Messages_fr_FR.json'; +import listing from '../../../public/translations/hycu/listing/Messages_fr_FR.json'; +import onboarding from '../../../public/translations/hycu/onboarding/Messages_fr_FR.json'; + +export const defaultLocale = 'fr_FR'; +export const defaultAvailableLocales = [defaultLocale]; + +function addTranslations() { + i18next + .addResources(defaultLocale, 'hycu', common) + .addResources(defaultLocale, 'dashboard', dashboard) + .addResources(defaultLocale, 'hycu/listing', listing) + .addResources(defaultLocale, 'hycu/onboarding', onboarding) + .use({ + type: 'postProcessor', + name: 'normalize', + process: (value: string) => + value ? value.replace(/&/g, '&') : value, + }); +} + +export const initTestI18n = () => + new Promise((resolve) => { + i18next.init({ + lng: defaultLocale, + defaultNS: 'hycu', + ns: [], + supportedLngs: defaultAvailableLocales, + postProcess: 'normalize', + interpolation: { + escapeValue: false, + }, + }); + + if (i18next.isInitialized) { + addTranslations(); + } else { + i18next.on('initialized', () => { + addTranslations(); + resolve(i18next); + }); + } + }); + +export const labels = { + common, + dashboard, + listing, + onboarding, +}; diff --git a/packages/manager/apps/hycu/src/utils/tests/renderTestApp.tsx b/packages/manager/apps/hycu/src/utils/tests/renderTestApp.tsx new file mode 100644 index 000000000000..fb0e6a88d311 --- /dev/null +++ b/packages/manager/apps/hycu/src/utils/tests/renderTestApp.tsx @@ -0,0 +1,59 @@ +import React from 'react'; +import { + initShellContext, + ShellContext, + ShellContextType, +} from '@ovh-ux/manager-react-shell-client'; +import { i18n } from 'i18next'; +import { I18nextProvider } from 'react-i18next'; +import { render, waitFor, screen } from '@testing-library/react'; +import { + getServicesMocks, + GetServicesMocksParams, +} from '@ovh-ux/manager-react-components/src/hooks/services/mocks/services.mock'; +import { TestApp } from './TestApp'; +import { initTestI18n } from './init.i18n'; +import { toMswHandlers } from '../../../../../../../playwright-helpers'; +import { getAuthenticationMocks } from '../../../../../../../playwright-helpers/mocks/auth'; +import { getLicenseHycuMocks, GetLicenseHycuMocksParams } from '@/mocks'; + +let context: ShellContextType; +let i18nValue: i18n; + +export const renderTestApp = async ( + mockParams: GetServicesMocksParams & GetLicenseHycuMocksParams = {}, +) => { + global.server?.resetHandlers( + ...toMswHandlers([ + ...getAuthenticationMocks({ isAuthMocked: true }), + ...getServicesMocks(mockParams), + ...getLicenseHycuMocks(mockParams), + ]), + ); + + if (!context) { + context = await initShellContext('hycu'); + } + + if (!i18nValue) { + i18nValue = await initTestI18n(); + } + + const result = render( + + + + + , + ); + + await waitFor( + () => + expect( + screen.getAllByText('HYCU', { exact: false }).length, + ).toBeGreaterThan(0), + { timeout: 30000 }, + ); + + return result; +}; diff --git a/packages/manager/apps/hycu/src/vite-hmr.ts b/packages/manager/apps/hycu/src/vite-hmr.ts new file mode 100644 index 000000000000..473d87630039 --- /dev/null +++ b/packages/manager/apps/hycu/src/vite-hmr.ts @@ -0,0 +1,5 @@ +if (import.meta.hot) { + import.meta.hot.on('iframe-reload', () => { + window.location.reload(); + }); +} diff --git a/packages/manager/apps/hycu/tailwind.config.js b/packages/manager/apps/hycu/tailwind.config.js new file mode 100644 index 000000000000..657ab11bb87d --- /dev/null +++ b/packages/manager/apps/hycu/tailwind.config.js @@ -0,0 +1,14 @@ +import path from 'path'; +import config from '@ovh-ux/manager-tailwind-config'; + +/** @type {import('tailwindcss').Config} */ +module.exports = { + ...config, + content: [ + './src/**/*.{js,jsx,ts,tsx}', + path.join( + path.dirname(require.resolve('@ovh-ux/manager-react-components')), + '**/*.{js,jsx,ts,tsx}', + ), + ], +}; diff --git a/packages/manager/apps/hycu/tsconfig.json b/packages/manager/apps/hycu/tsconfig.json new file mode 100644 index 000000000000..e2104f471575 --- /dev/null +++ b/packages/manager/apps/hycu/tsconfig.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + "lib": ["dom", "es2020"], + "noEmit": true, + "target": "es2020", + "types": ["vite/client", "node"], + "module": "ES2020", + "moduleResolution": "node", + "removeComments": true, + "outDir": "dist", + "esModuleInterop": true, + "isolatedModules": true, + "allowSyntheticDefaultImports": true, + "skipLibCheck": true, + "noImplicitAny": true, + "declaration": true, + "resolveJsonModule": true, + "allowJs": true, + "jsx": "react", + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + }, + "include": ["src"], + "exclude": ["node_modules", "dist", "types", "src/__tests__"] +} diff --git a/packages/manager/apps/hycu/tsconfig.test.json b/packages/manager/apps/hycu/tsconfig.test.json new file mode 100644 index 000000000000..7048c297c8f6 --- /dev/null +++ b/packages/manager/apps/hycu/tsconfig.test.json @@ -0,0 +1,6 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "module": "CommonJS" + } +} diff --git a/packages/manager/apps/hycu/vite.config.mjs b/packages/manager/apps/hycu/vite.config.mjs new file mode 100644 index 000000000000..f33ab6dc98cd --- /dev/null +++ b/packages/manager/apps/hycu/vite.config.mjs @@ -0,0 +1,8 @@ +import { defineConfig } from 'vite'; +import { getBaseConfig } from '@ovh-ux/manager-vite-config'; +import { resolve } from 'path'; + +export default defineConfig({ + ...getBaseConfig(), + root: resolve(process.cwd()), +}); diff --git a/packages/manager/apps/hycu/vitest.config.js b/packages/manager/apps/hycu/vitest.config.js new file mode 100644 index 000000000000..5ad6ce3dccf7 --- /dev/null +++ b/packages/manager/apps/hycu/vitest.config.js @@ -0,0 +1,39 @@ +import path from 'path'; +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [react()], + test: { + globals: true, + environment: 'jsdom', + setupFiles: ['./src/setupTests.tsx'], + coverage: { + include: ['src'], + exclude: [ + 'src/App.tsx', + 'src/index.tsx', + 'src/tracking.constant.ts', + 'src/vite-hmr.ts', + ], + }, + testTimeout: 60000, + fileParallelism: false, + maxWorkers: 1, + pollOptions: { + forks: { + singleFork: true, + }, + threads: { + singleThread: true, + }, + }, + }, + resolve: { + alias: { + '@': path.resolve(__dirname, 'src'), + }, + mainFields: ['module'], + }, +}); diff --git a/packages/manager/modules/config/src/locale/country-code.enum.ts b/packages/manager/modules/config/src/locale/country-code.enum.ts index 5026cbc2fe35..012054d9dfe8 100644 --- a/packages/manager/modules/config/src/locale/country-code.enum.ts +++ b/packages/manager/modules/config/src/locale/country-code.enum.ts @@ -9,10 +9,14 @@ export enum CountryCode { IE = 'IE', IN = 'IN', IT = 'IT', + MA = 'MA', + NL = 'NL', PL = 'PL', PT = 'PT', QC = 'QC', SG = 'SG', + SN = 'SN', + TN = 'TN', US = 'US', WE = 'WE', WS = 'WS', diff --git a/yarn.lock b/yarn.lock index 732763a5d257..7a6cdd742d94 100644 --- a/yarn.lock +++ b/yarn.lock @@ -214,6 +214,14 @@ "@babel/highlight" "^7.24.7" picocolors "^1.0.0" +"@babel/code-frame@^7.25.7": + version "7.25.7" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.25.7.tgz#438f2c524071531d643c6f0188e1e28f130cebc7" + integrity sha512-0xZJFNE5XMpENsgfHYTw8FbX4kv53mFLn2i3XPoq69LyhYSCBJtitaHx9QnsVTrsogI4Z3+HtEfZ2/GFPOtf5g== + dependencies: + "@babel/highlight" "^7.25.7" + picocolors "^1.0.0" + "@babel/compat-data@^7.22.6", "@babel/compat-data@^7.23.5": version "7.24.1" resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.24.1.tgz#31c1f66435f2a9c329bb5716a6d6186c516c3742" @@ -234,6 +242,11 @@ resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.24.7.tgz#d23bbea508c3883ba8251fb4164982c36ea577ed" integrity sha512-qJzAIcv03PyaWqxRgO4mSU3lihncDT296vnyuE2O8uA4w3UHWI4S3hgeZd1L8W1Bft40w9JxJ2b412iDUFFRhw== +"@babel/compat-data@^7.25.7": + version "7.25.7" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.25.7.tgz#b8479fe0018ef0ac87b6b7a5c6916fcd67ae2c9c" + integrity sha512-9ickoLz+hcXCeh7jrcin+/SLWm+GkxE2kTvoYyp38p4WkdFXfQJxDFGWp/YHjiKLPx06z2A7W8XKuqbReXDzsw== + "@babel/core@7.22.10": version "7.22.10" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.22.10.tgz#aad442c7bcd1582252cb4576747ace35bc122f35" @@ -297,6 +310,27 @@ json5 "^2.2.3" semver "^6.3.1" +"@babel/core@^7.25.2": + version "7.25.7" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.25.7.tgz#1b3d144157575daf132a3bc80b2b18e6e3ca6ece" + integrity sha512-yJ474Zv3cwiSOO9nXJuqzvwEeM+chDuQ8GJirw+pZ91sCGCyOZ3dJkVE09fTV0VEVzXyLWhh3G/AolYTPX7Mow== + dependencies: + "@ampproject/remapping" "^2.2.0" + "@babel/code-frame" "^7.25.7" + "@babel/generator" "^7.25.7" + "@babel/helper-compilation-targets" "^7.25.7" + "@babel/helper-module-transforms" "^7.25.7" + "@babel/helpers" "^7.25.7" + "@babel/parser" "^7.25.7" + "@babel/template" "^7.25.7" + "@babel/traverse" "^7.25.7" + "@babel/types" "^7.25.7" + convert-source-map "^2.0.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.3" + semver "^6.3.1" + "@babel/generator@^7.20.3", "@babel/generator@^7.22.15", "@babel/generator@^7.22.9", "@babel/generator@^7.7.2": version "7.22.15" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.22.15.tgz#1564189c7ec94cb8f77b5e8a90c4d200d21b2339" @@ -347,6 +381,16 @@ "@jridgewell/trace-mapping" "^0.3.25" jsesc "^2.5.1" +"@babel/generator@^7.25.7": + version "7.25.7" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.25.7.tgz#de86acbeb975a3e11ee92dd52223e6b03b479c56" + integrity sha512-5Dqpl5fyV9pIAD62yK9P7fcA768uVPUyrQmqpqstHWgMma4feF1x/oFysBCVZLY5wJ2GkMUCdsNDnGZrPoR6rA== + dependencies: + "@babel/types" "^7.25.7" + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.25" + jsesc "^3.0.2" + "@babel/helper-annotate-as-pure@^7.18.6", "@babel/helper-annotate-as-pure@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz#e7f06737b197d580a01edf75d97e2c8be99d3882" @@ -401,6 +445,17 @@ lru-cache "^5.1.1" semver "^6.3.1" +"@babel/helper-compilation-targets@^7.25.7": + version "7.25.7" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.7.tgz#11260ac3322dda0ef53edfae6e97b961449f5fa4" + integrity sha512-DniTEax0sv6isaw6qSQSfV4gVRNtw2rte8HHM45t9ZR0xILaufBRNkpMifCRiAPyvL4ACD6v0gfCwCmtOQaV4A== + dependencies: + "@babel/compat-data" "^7.25.7" + "@babel/helper-validator-option" "^7.25.7" + browserslist "^4.24.0" + lru-cache "^5.1.1" + semver "^6.3.1" + "@babel/helper-create-class-features-plugin@^7.18.6": version "7.22.15" resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.15.tgz#97a61b385e57fe458496fad19f8e63b63c867de4" @@ -553,6 +608,14 @@ "@babel/traverse" "^7.24.7" "@babel/types" "^7.24.7" +"@babel/helper-module-imports@^7.25.7": + version "7.25.7" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.25.7.tgz#dba00d9523539152906ba49263e36d7261040472" + integrity sha512-o0xCgpNmRohmnoWKQ0Ij8IdddjyBFE4T2kagL/x6M3+4zUgc+4qTOUBoNe4XxDskt1HPKO007ZPiMgLDq2s7Kw== + dependencies: + "@babel/traverse" "^7.25.7" + "@babel/types" "^7.25.7" + "@babel/helper-module-transforms@^7.22.9": version "7.22.20" resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.22.20.tgz#da9edc14794babbe7386df438f3768067132f59e" @@ -586,6 +649,16 @@ "@babel/helper-split-export-declaration" "^7.24.7" "@babel/helper-validator-identifier" "^7.24.7" +"@babel/helper-module-transforms@^7.25.7": + version "7.25.7" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.25.7.tgz#2ac9372c5e001b19bc62f1fe7d96a18cb0901d1a" + integrity sha512-k/6f8dKG3yDz/qCwSM+RKovjMix563SLxQFo0UhRNo239SP6n9u5/eLtKD6EAjwta2JHJ49CsD8pms2HdNiMMQ== + dependencies: + "@babel/helper-module-imports" "^7.25.7" + "@babel/helper-simple-access" "^7.25.7" + "@babel/helper-validator-identifier" "^7.25.7" + "@babel/traverse" "^7.25.7" + "@babel/helper-optimise-call-expression@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz#f21531a9ccbff644fdd156b4077c16ff0c3f609e" @@ -610,6 +683,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.7.tgz#98c84fe6fe3d0d3ae7bfc3a5e166a46844feb2a0" integrity sha512-Rq76wjt7yz9AAc1KnlRKNAi/dMSVWgDRx43FHoJEbcYU6xOWaE2dVPwcdTukJrjxS65GITyfbvEYHvkirZ6uEg== +"@babel/helper-plugin-utils@^7.25.7": + version "7.25.7" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.7.tgz#8ec5b21812d992e1ef88a9b068260537b6f0e36c" + integrity sha512-eaPZai0PiqCi09pPs3pAFfl/zYgGaE6IdXtYvmf0qlcDTd3WCtO7JWCcRd64e0EQrcYgiHibEZnOGsSY4QSgaw== + "@babel/helper-remap-async-to-generator@^7.22.20": version "7.22.20" resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz#7b68e1cb4fa964d2996fd063723fb48eca8498e0" @@ -652,6 +730,14 @@ "@babel/traverse" "^7.24.7" "@babel/types" "^7.24.7" +"@babel/helper-simple-access@^7.25.7": + version "7.25.7" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.25.7.tgz#5eb9f6a60c5d6b2e0f76057004f8dacbddfae1c0" + integrity sha512-FPGAkJmyoChQeM+ruBGIDyrT2tKfZJO8NcxdC+CWNJi7N8/rZpSxK7yvBJ5O/nF1gfu5KzN7VKG3YVSLFfRSxQ== + dependencies: + "@babel/traverse" "^7.25.7" + "@babel/types" "^7.25.7" + "@babel/helper-skip-transparent-expression-wrappers@^7.20.0", "@babel/helper-skip-transparent-expression-wrappers@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz#007f15240b5751c537c40e77abb4e89eeaaa8847" @@ -736,6 +822,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.24.7.tgz#24c3bb77c7a425d1742eec8fb433b5a1b38e62f6" integrity sha512-yy1/KvjhV/ZCL+SM7hBrvnZJ3ZuT9OuZgIJAGpPEToANvc3iM6iDvBnRjtElWibHU6n8/LPR/EjX9EtIEYO3pw== +"@babel/helper-validator-option@^7.25.7": + version "7.25.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.25.7.tgz#97d1d684448228b30b506d90cace495d6f492729" + integrity sha512-ytbPLsm+GjArDYXJ8Ydr1c/KJuutjF2besPNbIZnZ6MKUxi/uTA22t2ymmA4WFjZFpjiAMO0xuuJPqK2nvDVfQ== + "@babel/helper-wrap-function@^7.22.20": version "7.22.20" resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz#15352b0b9bfb10fc9c76f79f6342c00e3411a569" @@ -762,6 +853,14 @@ "@babel/template" "^7.24.7" "@babel/types" "^7.24.7" +"@babel/helpers@^7.25.7": + version "7.25.7" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.25.7.tgz#091b52cb697a171fe0136ab62e54e407211f09c2" + integrity sha512-Sv6pASx7Esm38KQpF/U/OXLwPPrdGHNKoeblRxgZRLXnAtnkEe4ptJPDtAZM7fBLadbc1Q07kQpSiGQ0Jg6tRA== + dependencies: + "@babel/template" "^7.25.7" + "@babel/types" "^7.25.7" + "@babel/highlight@^7.24.2", "@babel/highlight@^7.24.7": version "7.24.7" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.7.tgz#a05ab1df134b286558aae0ed41e6c5f731bf409d" @@ -772,6 +871,16 @@ js-tokens "^4.0.0" picocolors "^1.0.0" +"@babel/highlight@^7.25.7": + version "7.25.7" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.25.7.tgz#20383b5f442aa606e7b5e3043b0b1aafe9f37de5" + integrity sha512-iYyACpW3iW8Fw+ZybQK+drQre+ns/tKpXbNESfrhNnPLIklLbXr7MYJ6gPEd0iETGLOK+SxMjVvKb/ffmk+FEw== + dependencies: + "@babel/helper-validator-identifier" "^7.25.7" + chalk "^2.4.2" + js-tokens "^4.0.0" + picocolors "^1.0.0" + "@babel/parser@^7.1.0", "@babel/parser@^7.14.7": version "7.17.0" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.17.0.tgz#f0ac33eddbe214e4105363bb17c3341c5ffcc43c" @@ -829,12 +938,12 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.7.tgz#9a5226f92f0c5c8ead550b750f5608e766c8ce85" integrity sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw== -"@babel/parser@^7.25.4": - version "7.25.8" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.25.8.tgz#f6aaf38e80c36129460c1657c0762db584c9d5e2" - integrity sha512-HcttkxzdPucv3nNFmfOOMfFf64KgdJVqm1KaCm25dPGMLElo9nsLvXeJECQg8UzPuBGLyTSA0ZzqCtDSzKTEoQ== +"@babel/parser@^7.25.7": + version "7.25.7" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.25.7.tgz#99b927720f4ddbfeb8cd195a363ed4532f87c590" + integrity sha512-aZn7ETtQsjjGG5HruveUK06cU3Hljuhd9Iojm4M8WWv3wLE6OkE5PWbDUkItmMgegmccaITudyuW5RPYrYlgWw== dependencies: - "@babel/types" "^7.25.8" + "@babel/types" "^7.25.7" "@babel/parser@^7.7.0": version "7.10.3" @@ -1455,6 +1564,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.24.7" +"@babel/plugin-transform-react-jsx-self@^7.24.7": + version "7.25.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.25.7.tgz#3d11df143131fd8f5486a1f7d3839890f88f8c85" + integrity sha512-JD9MUnLbPL0WdVK8AWC7F7tTG2OS6u/AKKnsK+NdRhUiVdnzyR1S3kKQCaRLOiaULvUiqK6Z4JQE635VgtCFeg== + dependencies: + "@babel/helper-plugin-utils" "^7.25.7" + "@babel/plugin-transform-react-jsx-source@^7.14.5", "@babel/plugin-transform-react-jsx-source@^7.19.6": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.22.5.tgz#49af1615bfdf6ed9d3e9e43e425e0b2b65d15b6c" @@ -1476,6 +1592,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.24.7" +"@babel/plugin-transform-react-jsx-source@^7.24.7": + version "7.25.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.25.7.tgz#a0d8372310d5ea5b0447dfa03a8485f960eff7be" + integrity sha512-S/JXG/KrbIY06iyJPKfxr0qRxnhNOdkNXYBl/rmwgDd72cQLH9tEGkDm/yJPGvcSIUoikzfjMios9i+xT/uv9w== + dependencies: + "@babel/helper-plugin-utils" "^7.25.7" + "@babel/plugin-transform-react-jsx@^7.19.0", "@babel/plugin-transform-react-jsx@^7.22.5": version "7.23.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.23.4.tgz#393f99185110cea87184ea47bcb4a7b0c2e39312" @@ -1801,6 +1924,15 @@ "@babel/parser" "^7.25.0" "@babel/types" "^7.25.0" +"@babel/template@^7.25.7": + version "7.25.7" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.25.7.tgz#27f69ce382855d915b14ab0fe5fb4cbf88fa0769" + integrity sha512-wRwtAgI3bAS+JGU2upWNL9lSlDcRCqD05BZ1n3X2ONLH1WilFP6O1otQjeMK/1g0pvYcXC7b/qVUB1keofjtZA== + dependencies: + "@babel/code-frame" "^7.25.7" + "@babel/parser" "^7.25.7" + "@babel/types" "^7.25.7" + "@babel/traverse@^7.1.0", "@babel/traverse@^7.22.8", "@babel/traverse@^7.7.0", "@babel/traverse@^7.7.2": version "7.22.20" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.22.20.tgz#db572d9cb5c79e02d83e5618b82f6991c07584c9" @@ -1878,6 +2010,19 @@ debug "^4.3.1" globals "^11.1.0" +"@babel/traverse@^7.25.7": + version "7.25.7" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.25.7.tgz#83e367619be1cab8e4f2892ef30ba04c26a40fa8" + integrity sha512-jatJPT1Zjqvh/1FyJs6qAHL+Dzb7sTb+xr7Q+gM1b+1oBsMsQQ4FkVKb6dFlJvLlVssqkRzV05Jzervt9yhnzg== + dependencies: + "@babel/code-frame" "^7.25.7" + "@babel/generator" "^7.25.7" + "@babel/parser" "^7.25.7" + "@babel/template" "^7.25.7" + "@babel/types" "^7.25.7" + debug "^4.3.1" + globals "^11.1.0" + "@babel/types@^7.0.0", "@babel/types@^7.2.0", "@babel/types@^7.20.7", "@babel/types@^7.22.15", "@babel/types@^7.22.19", "@babel/types@^7.22.5", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.7.0": version "7.22.19" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.22.19.tgz#7425343253556916e440e662bb221a93ddb75684" @@ -1941,10 +2086,10 @@ "@babel/helper-validator-identifier" "^7.24.7" to-fast-properties "^2.0.0" -"@babel/types@^7.25.4", "@babel/types@^7.25.8": - version "7.25.8" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.25.8.tgz#5cf6037258e8a9bcad533f4979025140cb9993e1" - integrity sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg== +"@babel/types@^7.25.7": + version "7.25.7" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.25.7.tgz#1b7725c1d3a59f328cb700ce704c46371e6eef9b" + integrity sha512-vwIVdXG+j+FOpkwqHRcBgHLYNL7XMkufrlaFvL9o6Ai9sJn9+PdyIL5qa0XzTZw084c+u9LOls53eoZWP/W5WQ== dependencies: "@babel/helper-string-parser" "^7.25.7" "@babel/helper-validator-identifier" "^7.25.7" @@ -5194,6 +5339,11 @@ resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== +"@pkgr/core@^0.1.0": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.1.1.tgz#1ec17e2edbec25c8306d424ecfbf13c7de1aaa31" + integrity sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA== + "@playwright/test@^1.34.3", "@playwright/test@^1.41.2": version "1.43.0" resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.43.0.tgz#5d90f247b26d404dd5d81c60f9c7c5e5159eb664" @@ -8361,6 +8511,19 @@ lodash "^4.17.21" redent "^3.0.0" +"@testing-library/jest-dom@^6.5.0": + version "6.5.0" + resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-6.5.0.tgz#50484da3f80fb222a853479f618a9ce5c47bfe54" + integrity sha512-xGGHpBXYSHUUr6XsKBfs85TWlYKpTc37cSBBVrXcib2MkHLboWlkClhWF37JKlDb9KEq3dHs+f2xR7XJEWGBxA== + dependencies: + "@adobe/css-tools" "^4.4.0" + aria-query "^5.0.0" + chalk "^3.0.0" + css.escape "^1.5.1" + dom-accessibility-api "^0.6.3" + lodash "^4.17.21" + redent "^3.0.0" + "@testing-library/react@14.0.0": version "14.0.0" resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-14.0.0.tgz#59030392a6792450b9ab8e67aea5f3cc18d6347c" @@ -8395,6 +8558,13 @@ dependencies: "@babel/runtime" "^7.12.5" +"@testing-library/react@^16.0.1": + version "16.0.1" + resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-16.0.1.tgz#29c0ee878d672703f5e7579f239005e4e0faa875" + integrity sha512-dSmwJVtJXmku+iocRhWOUFbrERC76TX2Mnf0ATODz8brzAZrMBbzLwQixlBSanZxR6LddK3eiwpSFZgDET1URg== + dependencies: + "@babel/runtime" "^7.12.5" + "@testing-library/user-event@^13.2.1": version "13.5.0" resolved "https://registry.yarnpkg.com/@testing-library/user-event/-/user-event-13.5.0.tgz#69d77007f1e124d55314a2b73fd204b333b13295" @@ -8754,6 +8924,14 @@ expect "^28.0.0" pretty-format "^28.0.0" +"@types/jest@^29.5.13": + version "29.5.13" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.13.tgz#8bc571659f401e6a719a7bf0dbcb8b78c71a8adc" + integrity sha512-wd+MVEZCHt23V0/L642O5APvspWply/rGY5BcW4SUETo2UzPU3Z26qr8jC2qxpimI2jjx9h7+2cj2FwIr01bXg== + dependencies: + expect "^29.0.0" + pretty-format "^29.0.0" + "@types/js-cookie@^2.2.6": version "2.2.7" resolved "https://registry.yarnpkg.com/@types/js-cookie/-/js-cookie-2.2.7.tgz#226a9e31680835a6188e887f3988e60c04d3f6a3" @@ -9411,6 +9589,17 @@ "@types/babel__core" "^7.20.5" react-refresh "^0.14.2" +"@vitejs/plugin-react@^4.3.2": + version "4.3.2" + resolved "https://registry.yarnpkg.com/@vitejs/plugin-react/-/plugin-react-4.3.2.tgz#1e13f666fe3135b477220d3c13b783704636b6e4" + integrity sha512-hieu+o05v4glEBucTcKMK3dlES0OeJlD9YVOAPraVMOInBCwzumaIFiUjr4bHK7NPgnAHgiskUoceKercrN8vg== + dependencies: + "@babel/core" "^7.25.2" + "@babel/plugin-transform-react-jsx-self" "^7.24.7" + "@babel/plugin-transform-react-jsx-source" "^7.24.7" + "@types/babel__core" "^7.20.5" + react-refresh "^0.14.2" + "@vitejs/plugin-vue@^5.0.4": version "5.1.0" resolved "https://registry.yarnpkg.com/@vitejs/plugin-vue/-/plugin-vue-5.1.0.tgz#d29f2aad9127c73b578e7a463e76249e89256e0b" @@ -9635,7 +9824,9 @@ resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-1.3.1.tgz#814245d46d011b99edd1c7528f5725c64e85a88b" integrity sha512-xAcW+S099ylC9VLU7eZfdT9myV67Nor9w9zhf0mGCYJSO+zM2839tOeROTdikOi/8Qeusffvxb/MyBSOja1Uig== dependencies: - tinyspy "^2.2.0" + "@vitest/pretty-format" "2.1.2" + magic-string "^0.30.11" + pathe "^1.1.2" "@vitest/spy@1.4.0": version "1.4.0" @@ -11648,6 +11839,16 @@ browserslist@^4.23.0: node-releases "^2.0.14" update-browserslist-db "^1.0.16" +browserslist@^4.24.0: + version "4.24.0" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.24.0.tgz#a1325fe4bc80b64fda169629fc01b3d6cecd38d4" + integrity sha512-Rmb62sR1Zpjql25eSanFGEhAxcFwfA1K0GuQcLoaJBAcENegrQut3hYdhXFF1obQfiDyqIW/cLM5HSJ/9k884A== + dependencies: + caniuse-lite "^1.0.30001663" + electron-to-chromium "^1.5.28" + node-releases "^2.0.18" + update-browserslist-db "^1.1.0" + bs-logger@0.x: version "0.2.6" resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" @@ -11880,6 +12081,11 @@ caniuse-lite@^1.0.30001640: resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001643.tgz#9c004caef315de9452ab970c3da71085f8241dbd" integrity sha512-ERgWGNleEilSrHM6iUz/zJNSQTP8Mr21wDWpdgvRwcTXGAq6jMtOUPP4dqFPTdKqZ2wKTdtB+uucZ3MRpAUSmg== +caniuse-lite@^1.0.30001663: + version "1.0.30001667" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001667.tgz#99fc5ea0d9c6e96897a104a8352604378377f949" + integrity sha512-7LTwJjcRkzKFmtqGsibMeuXmvFDfZq/nzIjnmgCGzKKRVzjD72selLDK1oPF/Oxzmt4fNcPvTDvGqSDG4tCALw== + capital-case@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/capital-case/-/capital-case-1.0.4.tgz#9d130292353c9249f6b00fa5852bee38a717e669" @@ -14301,6 +14507,11 @@ electron-to-chromium@^1.4.820: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.1.tgz#24640bd4dcfaccb6d82bb4c3f4c7311503241581" integrity sha512-FKbOCOQ5QRB3VlIbl1LZQefWIYwszlBloaXcY2rbfpu9ioJnNh3TK03YtIDKDo3WKBi8u+YV4+Fn2CkEozgf4w== +electron-to-chromium@^1.5.28: + version "1.5.33" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.33.tgz#8f64698661240e70fdbc4b032e6085e391f05e09" + integrity sha512-+cYTcFB1QqD4j4LegwLfpCNxifb6dDFUAwk6RsLusCwIaZI6or2f+q8rs5tTB2YC53HhOlIbEaqHMAAC8IOIwA== + element-internals-polyfill@^1.3.10: version "1.3.10" resolved "https://registry.yarnpkg.com/element-internals-polyfill/-/element-internals-polyfill-1.3.10.tgz#799dfe5104a7dab39cb11f91af1b94740ff73394" @@ -14311,6 +14522,11 @@ element-internals-polyfill@^1.3.11: resolved "https://registry.yarnpkg.com/element-internals-polyfill/-/element-internals-polyfill-1.3.11.tgz#fc0c0894a61a1c0b182d9b2aceeab4b4e4f66bb2" integrity sha512-SQLQNVY4wMdpnP/F/HtalJbpEenQd46Avtjm5hvUdeTs3QU0zHFNX5/AmtQIPPcfzePb0ipCkQGY4GwYJIhLJA== +element-internals-polyfill@^1.3.12: + version "1.3.12" + resolved "https://registry.yarnpkg.com/element-internals-polyfill/-/element-internals-polyfill-1.3.12.tgz#4a9464a15f2d50a36c7e21e0c40aeed30fb8efb0" + integrity sha512-KW1k+cMGwXlx3X9nqhgmuElAfR/c/ccFt0pG4KpwK++Mx9Y+mPExxJW+jgQnqux/NQrJejgOxxg4Naf3f6y67Q== + email-addresses@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/email-addresses/-/email-addresses-5.0.0.tgz#7ae9e7f58eef7d5e3e2c2c2d3ea49b78dc854fa6" @@ -14994,6 +15210,14 @@ eslint-plugin-prettier@^3.1.1: dependencies: prettier-linter-helpers "^1.0.0" +eslint-plugin-prettier@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz#d1c8f972d8f60e414c25465c163d16f209411f95" + integrity sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw== + dependencies: + prettier-linter-helpers "^1.0.0" + synckit "^0.9.1" + eslint-plugin-promise@6.1.1: version "6.1.1" resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-6.1.1.tgz#269a3e2772f62875661220631bd4dafcb4083816" @@ -19963,6 +20187,11 @@ jsesc@^2.5.1: resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== +jsesc@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.0.2.tgz#bb8b09a6597ba426425f2e4a07245c3d00b9343e" + integrity sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g== + jsesc@~0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" @@ -20816,7 +21045,7 @@ magic-string@^0.30.0, magic-string@^0.30.1, magic-string@^0.30.5, magic-string@^ dependencies: "@jridgewell/sourcemap-codec" "^1.4.15" -magic-string@^0.30.10: +magic-string@^0.30.10, magic-string@^0.30.11: version "0.30.11" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.11.tgz#301a6f93b3e8c2cb13ac1a7a673492c0dfd12954" integrity sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A== @@ -21885,6 +22114,11 @@ node-releases@^2.0.14: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== +node-releases@^2.0.18: + version "2.0.18" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.18.tgz#f010e8d35e2fe8d6b2944f03f70213ecedc4ca3f" + integrity sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g== + nopt@1.0.10: version "1.0.10" resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee" @@ -26780,6 +27014,14 @@ synchronous-promise@^2.0.15: resolved "https://registry.yarnpkg.com/synchronous-promise/-/synchronous-promise-2.0.17.tgz#38901319632f946c982152586f2caf8ddc25c032" integrity sha512-AsS729u2RHUfEra9xJrE39peJcc2stq2+poBXX8bcM08Y6g9j/i/PUzwNQqkaJde7Ntg1TO7bSREbR5sdosQ+g== +synckit@^0.9.1: + version "0.9.2" + resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.9.2.tgz#a3a935eca7922d48b9e7d6c61822ee6c3ae4ec62" + integrity sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw== + dependencies: + "@pkgr/core" "^0.1.0" + tslib "^2.6.2" + systemjs@^6.12.1: version "6.14.3" resolved "https://registry.yarnpkg.com/systemjs/-/systemjs-6.14.3.tgz#c1d6e4ff5f9ff7106e5bb3d451360b1a066bde8a" @@ -27463,6 +27705,11 @@ tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.0, tslib@^2.3 resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== +tslib@^2.6.2: + version "2.7.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.7.0.tgz#d9b40c5c40ab59e8738f297df3087bf1a2690c01" + integrity sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA== + tsutils@^3.21.0: version "3.21.0" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623"