diff --git a/.eslintignore b/.eslintignore index f5c69691a2a8..af55cf13f700 100644 --- a/.eslintignore +++ b/.eslintignore @@ -16,3 +16,4 @@ vue/src packages/manager/core/generator packages/components/ovh-at-internet/src/ovh-at-internet.ts packages/manager/apps/container +packages/manager/apps/pci-ai-notebooks/src/components/ui \ No newline at end of file diff --git a/.prettierignore b/.prettierignore index c26c9f17c5b7..aedc62fde2e4 100644 --- a/.prettierignore +++ b/.prettierignore @@ -5,3 +5,5 @@ custom-elements loader react vue +packages/manager/apps/pci-ai-notebooks/src/components/ui +packages/manager/apps/pci-ai-notebooks/src/lib/utils.ts \ No newline at end of file diff --git a/packages/manager/apps/container/src/container/legacy/server-sidebar/universe/public-cloud/pci-menu.ts b/packages/manager/apps/container/src/container/legacy/server-sidebar/universe/public-cloud/pci-menu.ts index e8637959e018..01e23d3d9cf1 100644 --- a/packages/manager/apps/container/src/container/legacy/server-sidebar/universe/public-cloud/pci-menu.ts +++ b/packages/manager/apps/container/src/container/legacy/server-sidebar/universe/public-cloud/pci-menu.ts @@ -44,7 +44,8 @@ export const features = [ 'public-cloud:project-settings', 'ai-dashboard', 'data-platform', - 'ai-endpoints' + 'ai-endpoints', + 'pci-ai-notebooks' ]; export function getPciProjectMenu( @@ -297,8 +298,8 @@ export function getPciProjectMenu( { id: 'notebooks', title: 'AI Notebooks', - feature: 'notebooks', - href: getURL('public-cloud', `#/pci/projects/${projectId}/notebooks`), + feature: 'pci-ai-notebooks', + href: getURL('public-cloud', `#/pci/projects/${projectId}/ai/notebooks`), }, { id: 'training', diff --git a/packages/manager/apps/pci-ai-notebooks/.gitignore b/packages/manager/apps/pci-ai-notebooks/.gitignore new file mode 100644 index 000000000000..32ef74fe6562 --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/.gitignore @@ -0,0 +1,2 @@ +coverage +yarn-error.log \ No newline at end of file diff --git a/packages/manager/apps/pci-ai-notebooks/README.md b/packages/manager/apps/pci-ai-notebooks/README.md new file mode 100644 index 000000000000..1c5efd0baccd --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/README.md @@ -0,0 +1,3 @@ +# @ovh-ux/manager-pci-ai-notebooks-app + +> pci-ai-notebooks project diff --git a/packages/manager/apps/pci-ai-notebooks/components.json b/packages/manager/apps/pci-ai-notebooks/components.json new file mode 100644 index 000000000000..5fa88201dfd4 --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/components.json @@ -0,0 +1,17 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "default", + "rsc": false, + "tsx": true, + "tailwind": { + "config": "tailwind.config.ts", + "css": "src/global.css", + "baseColor": "neutral", + "cssVariables": true, + "prefix": "" + }, + "aliases": { + "components": "@/components", + "utils": "@/lib/utils" + } +} diff --git a/packages/manager/apps/pci-ai-notebooks/package.json b/packages/manager/apps/pci-ai-notebooks/package.json new file mode 100644 index 000000000000..9564db61118b --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/package.json @@ -0,0 +1,127 @@ +{ + "name": "@ovh-ux/manager-pci-ai-notebooks-app", + "version": "1.0.0", + "private": true, + "description": "pci-ai-notebooks", + "repository": { + "type": "git", + "url": "git+https://github.com/ovh/manager.git", + "directory": "packages/manager/apps/pci-ai-notebooks" + }, + "license": "BSD-3-Clause", + "author": "OVH SAS", + "type": "module", + "scripts": { + "build": "tsc --project tsconfig.build.json && vite build", + "coverage": "vitest run --coverage", + "dev": "tsc && vite", + "start": "lerna exec --stream --scope='@ovh-ux/manager-pci-ai-notebooks-app' --include-dependencies -- npm run build --if-present", + "start:dev": "lerna exec --stream --scope='@ovh-ux/manager-pci-ai-notebooks-app' --include-dependencies -- npm run dev --if-present", + "start:watch": "lerna exec --stream --parallel --scope='@ovh-ux/manager-pci-ai-notebooks-app' --include-dependencies -- npm run dev:watch --if-present", + "test": "vitest", + "test-ui": "vitest --ui --coverage.enabled=true" + }, + "dependencies": { + "@emotion/react": "^11.11.4", + "@emotion/styled": "^11.11.0", + "@hookform/resolvers": "^3.3.4", + "@ovh-ux/manager-config": "*", + "@ovh-ux/manager-core-api": "*", + "@ovh-ux/manager-react-core-application": "*", + "@ovh-ux/manager-react-shell-client": "*", + "@ovh-ux/shell": "*", + "@ovhcloud/manager-components": "^1.3.0", + "@ovhcloud/ods-common-core": "^17.1.0", + "@ovhcloud/ods-common-theming": "^17.1.0", + "@ovhcloud/ods-components": "^17.1.0", + "@ovhcloud/ods-theme-blue-jeans": "^17.1.0", + "@radix-ui/react-accordion": "^1.1.2", + "@radix-ui/react-alert-dialog": "^1.0.5", + "@radix-ui/react-collapsible": "^1.0.3", + "@radix-ui/react-dialog": "^1.0.5", + "@radix-ui/react-dropdown-menu": "^2.0.6", + "@radix-ui/react-label": "^2.0.2", + "@radix-ui/react-popover": "^1.0.7", + "@radix-ui/react-progress": "^1.0.3", + "@radix-ui/react-radio-group": "^1.1.3", + "@radix-ui/react-scroll-area": "^1.0.5", + "@radix-ui/react-select": "^2.0.0", + "@radix-ui/react-slider": "^1.1.2", + "@radix-ui/react-slot": "^1.0.2", + "@radix-ui/react-switch": "^1.0.3", + "@radix-ui/react-tabs": "^1.0.4", + "@radix-ui/react-toast": "^1.1.5", + "@radix-ui/react-tooltip": "^1.0.7", + "@tanstack/react-query": "^5.8.3", + "@tanstack/react-table": "^8.12.0", + "@testing-library/dom": "^9.3.4", + "@testing-library/jest-dom": "^6.4.2", + "@testing-library/react": "^14.2.2", + "@testing-library/user-event": "^14.5.2", + "@types/node": "^18.0.0", + "chart.js": "^4.4.2", + "chartjs-adapter-date-fns": "^3.0.0", + "chartjs-plugin-zoom": "^2.0.1", + "class-variance-authority": "^0.7.0", + "clsx": "^2.1.0", + "cmdk": "^0.2.1", + "date-fns": "^3.4.0", + "duration-fns": "^3.0.2", + "i18next": "^23.10.0", + "i18next-http-backend": "^2.4.2", + "lucide-react": "^0.334.0", + "next-themes": "^0.2.1", + "qs": "^6.11.2", + "react": "^18.2.0", + "react-chartjs-2": "^5.2.0", + "react-day-picker": "^8.10.0", + "react-dom": "^18.2.0", + "react-hook-form": "^7.50.1", + "react-i18next": "^14.0.5", + "react-router": "^6.21.3", + "react-router-dom": "^6.3.0", + "sonner": "^1.4.0", + "tailwind-merge": "^2.2.1", + "tailwindcss": "^3.4.1", + "tailwindcss-animate": "^1.0.7", + "turbo": "^1.4.3", + "zod": "^3.22.4" + }, + "devDependencies": { + "@babel/plugin-proposal-private-property-in-object": "^7.21.11", + "@jest/globals": "^29.7.0", + "@ovh-ux/manager-vite-config": "*", + "@tanstack/react-query-devtools": "^5.8.3", + "@testing-library/dom": "^9.3.3", + "@testing-library/jest-dom": "^6.1.5", + "@testing-library/react": "^14.1.2", + "@testing-library/user-event": "^13.2.1", + "@types/jest": "^29.5.11", + "@types/node": "^20.10.6", + "@types/react": "^18.2.45", + "@types/react-dom": "^18.2.18", + "@typescript-eslint/eslint-plugin": "^6.16.0", + "@typescript-eslint/parser": "^6.16.0", + "@vitejs/plugin-react": "^4.2.1", + "@vitest/coverage-v8": "^1.2.0", + "@vitest/ui": "^1.4.0", + "autoprefixer": "^10.4.16", + "babel-plugin-transform-import-meta": "^2.2.1", + "element-internals-polyfill": "^1.3.10", + "eslint": "^8.56.0", + "jest-environment-jsdom": "^29.7.0", + "knip": "^3.10.0", + "postcss": "^8.4.32", + "rollup": "^4.4.0", + "tailwindcss": "^3.4.0", + "ts-jest": "^29.1.1", + "ts-node": "^10.9.2", + "typescript": "^5.3.3", + "vite": "4.3.1", + "vitest": "^1.4.0" + }, + "regions": [ + "CA", + "EU" + ] +} diff --git a/packages/manager/apps/pci-ai-notebooks/postcss.config.cjs b/packages/manager/apps/pci-ai-notebooks/postcss.config.cjs new file mode 100644 index 000000000000..12a703d900da --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/postcss.config.cjs @@ -0,0 +1,6 @@ +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; diff --git a/packages/manager/apps/pci-ai-notebooks/public/assets/oops.png b/packages/manager/apps/pci-ai-notebooks/public/assets/oops.png new file mode 100644 index 000000000000..413028afad19 Binary files /dev/null and b/packages/manager/apps/pci-ai-notebooks/public/assets/oops.png differ diff --git a/packages/manager/apps/pci-ai-notebooks/public/translations/bytes/Messages_de_DE.json b/packages/manager/apps/pci-ai-notebooks/public/translations/bytes/Messages_de_DE.json new file mode 100644 index 000000000000..5928e33d7bbe --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/public/translations/bytes/Messages_de_DE.json @@ -0,0 +1,20 @@ +{ + "unitShort-B": "B", + "unitShort-KB": "KB", + "unitShort-MB": "MB", + "unitShort-GB": "GB", + "unitShort-TB": "TB", + "unitShort-PB": "PB", + "unitLong-B_one": "Byte", + "unitLong-B_other": "Byte", + "unitLong-KB_one": "Kilobyte", + "unitLong-KB_other": "Kilobyte", + "unitLong-MB_one": "Megabyte", + "unitLong-MB_other": "Megabyte", + "unitLong-GB_one": "Gigabyte", + "unitLong-GB_other": "Gigabyte", + "unitLong-TB_one": "Terabyte", + "unitLong-TB_other": "Terabyte", + "unitLong-PB_one": "Petabyte", + "unitLong-PB_other": "Petabyte" +} diff --git a/packages/manager/apps/pci-ai-notebooks/public/translations/bytes/Messages_en_GB.json b/packages/manager/apps/pci-ai-notebooks/public/translations/bytes/Messages_en_GB.json new file mode 100644 index 000000000000..ff5ca5c4de65 --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/public/translations/bytes/Messages_en_GB.json @@ -0,0 +1,20 @@ +{ + "unitShort-B": "B", + "unitShort-KB": "KB", + "unitShort-MB": "MB", + "unitShort-GB": "GB", + "unitShort-TB": "TB", + "unitShort-PB": "PB", + "unitLong-B_one": "byte", + "unitLong-B_other": "bytes", + "unitLong-KB_one": "kilobyte", + "unitLong-KB_other": "kilobytes", + "unitLong-MB_one": "megabyte", + "unitLong-MB_other": "megabytes", + "unitLong-GB_one": "gigabyte", + "unitLong-GB_other": "gigabytes", + "unitLong-TB_one": "terabyte", + "unitLong-TB_other": "terabytes", + "unitLong-PB_one": "petabyte", + "unitLong-PB_other": "petabytes" +} diff --git a/packages/manager/apps/pci-ai-notebooks/public/translations/bytes/Messages_es_ES.json b/packages/manager/apps/pci-ai-notebooks/public/translations/bytes/Messages_es_ES.json new file mode 100644 index 000000000000..ff5ca5c4de65 --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/public/translations/bytes/Messages_es_ES.json @@ -0,0 +1,20 @@ +{ + "unitShort-B": "B", + "unitShort-KB": "KB", + "unitShort-MB": "MB", + "unitShort-GB": "GB", + "unitShort-TB": "TB", + "unitShort-PB": "PB", + "unitLong-B_one": "byte", + "unitLong-B_other": "bytes", + "unitLong-KB_one": "kilobyte", + "unitLong-KB_other": "kilobytes", + "unitLong-MB_one": "megabyte", + "unitLong-MB_other": "megabytes", + "unitLong-GB_one": "gigabyte", + "unitLong-GB_other": "gigabytes", + "unitLong-TB_one": "terabyte", + "unitLong-TB_other": "terabytes", + "unitLong-PB_one": "petabyte", + "unitLong-PB_other": "petabytes" +} diff --git a/packages/manager/apps/pci-ai-notebooks/public/translations/bytes/Messages_fr_CA.json b/packages/manager/apps/pci-ai-notebooks/public/translations/bytes/Messages_fr_CA.json new file mode 100644 index 000000000000..21953a45b499 --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/public/translations/bytes/Messages_fr_CA.json @@ -0,0 +1,20 @@ +{ + "unitShort-B": "o", + "unitShort-KB": "Ko", + "unitShort-MB": "Mo", + "unitShort-GB": "Go", + "unitShort-TB": "To", + "unitShort-PB": "Po", + "unitLong-B_one": "octet", + "unitLong-B_other": "octets", + "unitLong-KB_one": "kilooctet", + "unitLong-KB_other": "kilooctets", + "unitLong-MB_one": "mégaoctet", + "unitLong-MB_other": "mégaoctets", + "unitLong-GB_one": "gigaoctet", + "unitLong-GB_other": "gigaoctets", + "unitLong-TB_one": "téraoctet", + "unitLong-TB_other": "téraoctets", + "unitLong-PB_one": "pétaoctet", + "unitLong-PB_other": "pétaoctets" +} diff --git a/packages/manager/apps/pci-ai-notebooks/public/translations/bytes/Messages_fr_FR.json b/packages/manager/apps/pci-ai-notebooks/public/translations/bytes/Messages_fr_FR.json new file mode 100644 index 000000000000..21953a45b499 --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/public/translations/bytes/Messages_fr_FR.json @@ -0,0 +1,20 @@ +{ + "unitShort-B": "o", + "unitShort-KB": "Ko", + "unitShort-MB": "Mo", + "unitShort-GB": "Go", + "unitShort-TB": "To", + "unitShort-PB": "Po", + "unitLong-B_one": "octet", + "unitLong-B_other": "octets", + "unitLong-KB_one": "kilooctet", + "unitLong-KB_other": "kilooctets", + "unitLong-MB_one": "mégaoctet", + "unitLong-MB_other": "mégaoctets", + "unitLong-GB_one": "gigaoctet", + "unitLong-GB_other": "gigaoctets", + "unitLong-TB_one": "téraoctet", + "unitLong-TB_other": "téraoctets", + "unitLong-PB_one": "pétaoctet", + "unitLong-PB_other": "pétaoctets" +} diff --git a/packages/manager/apps/pci-ai-notebooks/public/translations/bytes/Messages_it_IT.json b/packages/manager/apps/pci-ai-notebooks/public/translations/bytes/Messages_it_IT.json new file mode 100644 index 000000000000..375d7b8399d5 --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/public/translations/bytes/Messages_it_IT.json @@ -0,0 +1,20 @@ +{ + "unitShort-B": "b", + "unitShort-KB": "KB", + "unitShort-MB": "MB", + "unitShort-GB": "GB", + "unitShort-TB": "TB", + "unitShort-PB": "PB", + "unitLong-B_one": "byte", + "unitLong-B_other": "byte", + "unitLong-KB_one": "kilobyte", + "unitLong-KB_other": "kilobyte", + "unitLong-MB_one": "megabyte", + "unitLong-MB_other": "megabyte", + "unitLong-GB_one": "gigabyte", + "unitLong-GB_other": "gigabyte", + "unitLong-TB_one": "terabyte", + "unitLong-TB_other": "terabyte", + "unitLong-PB_one": "petabyte", + "unitLong-PB_other": "petabyte" +} diff --git a/packages/manager/apps/pci-ai-notebooks/public/translations/bytes/Messages_pl_PL.json b/packages/manager/apps/pci-ai-notebooks/public/translations/bytes/Messages_pl_PL.json new file mode 100644 index 000000000000..1511808fc990 --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/public/translations/bytes/Messages_pl_PL.json @@ -0,0 +1,20 @@ +{ + "unitShort-B": "B", + "unitShort-KB": "KB", + "unitShort-MB": "MB", + "unitShort-GB": "GB", + "unitShort-TB": "TB", + "unitShort-PB": "PB", + "unitLong-B_one": "bajt", + "unitLong-B_other": "bajty", + "unitLong-KB_one": "kilobajt", + "unitLong-KB_other": "kilobajty", + "unitLong-MB_one": "megabajt", + "unitLong-MB_other": "megabajty", + "unitLong-GB_one": "gigabajt", + "unitLong-GB_other": "gigabajty", + "unitLong-TB_one": "terabajt", + "unitLong-TB_other": "terabajty", + "unitLong-PB_one": "petabajt", + "unitLong-PB_other": "petabajty" +} diff --git a/packages/manager/apps/pci-ai-notebooks/public/translations/bytes/Messages_pt_PT.json b/packages/manager/apps/pci-ai-notebooks/public/translations/bytes/Messages_pt_PT.json new file mode 100644 index 000000000000..ff5ca5c4de65 --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/public/translations/bytes/Messages_pt_PT.json @@ -0,0 +1,20 @@ +{ + "unitShort-B": "B", + "unitShort-KB": "KB", + "unitShort-MB": "MB", + "unitShort-GB": "GB", + "unitShort-TB": "TB", + "unitShort-PB": "PB", + "unitLong-B_one": "byte", + "unitLong-B_other": "bytes", + "unitLong-KB_one": "kilobyte", + "unitLong-KB_other": "kilobytes", + "unitLong-MB_one": "megabyte", + "unitLong-MB_other": "megabytes", + "unitLong-GB_one": "gigabyte", + "unitLong-GB_other": "gigabytes", + "unitLong-TB_one": "terabyte", + "unitLong-TB_other": "terabytes", + "unitLong-PB_one": "petabyte", + "unitLong-PB_other": "petabytes" +} diff --git a/packages/manager/apps/pci-ai-notebooks/public/translations/error/Messages_de_DE.json b/packages/manager/apps/pci-ai-notebooks/public/translations/error/Messages_de_DE.json new file mode 100644 index 000000000000..8e10000b4500 --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/public/translations/error/Messages_de_DE.json @@ -0,0 +1,8 @@ +{ + "manager_error_page_title": "Hoppla!", + "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/pci-ai-notebooks/public/translations/error/Messages_en_GB.json b/packages/manager/apps/pci-ai-notebooks/public/translations/error/Messages_en_GB.json new file mode 100644 index 000000000000..b17691e2bc6d --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/public/translations/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/pci-ai-notebooks/public/translations/error/Messages_es_ES.json b/packages/manager/apps/pci-ai-notebooks/public/translations/error/Messages_es_ES.json new file mode 100644 index 000000000000..15fc5f79256d --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/public/translations/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/pci-ai-notebooks/public/translations/error/Messages_fr_CA.json b/packages/manager/apps/pci-ai-notebooks/public/translations/error/Messages_fr_CA.json new file mode 100644 index 000000000000..2c575c63588e --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/public/translations/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/pci-ai-notebooks/public/translations/error/Messages_fr_FR.json b/packages/manager/apps/pci-ai-notebooks/public/translations/error/Messages_fr_FR.json new file mode 100644 index 000000000000..2c575c63588e --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/public/translations/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/pci-ai-notebooks/public/translations/error/Messages_it_IT.json b/packages/manager/apps/pci-ai-notebooks/public/translations/error/Messages_it_IT.json new file mode 100644 index 000000000000..fa5055b8cec5 --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/public/translations/error/Messages_it_IT.json @@ -0,0 +1,8 @@ +{ + "manager_error_page_title": "Ops!", + "manager_error_page_button_cancel": "Annullare", + "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/pci-ai-notebooks/public/translations/error/Messages_pl_PL.json b/packages/manager/apps/pci-ai-notebooks/public/translations/error/Messages_pl_PL.json new file mode 100644 index 000000000000..eceb9bcca2ca --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/public/translations/error/Messages_pl_PL.json @@ -0,0 +1,8 @@ +{ + "manager_error_page_title": "Ojej...", + "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/pci-ai-notebooks/public/translations/error/Messages_pt_PT.json b/packages/manager/apps/pci-ai-notebooks/public/translations/error/Messages_pt_PT.json new file mode 100644 index 000000000000..25fac9551c86 --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/public/translations/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 para a página inicial", + "manager_error_page_default": "Ocorreu um erro ao carregar a página." +} diff --git a/packages/manager/apps/pci-ai-notebooks/public/translations/pci-ai-notebooks/Messages_fr_FR.json b/packages/manager/apps/pci-ai-notebooks/public/translations/pci-ai-notebooks/Messages_fr_FR.json new file mode 100644 index 000000000000..63af51e824fb --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/public/translations/pci-ai-notebooks/Messages_fr_FR.json @@ -0,0 +1,3 @@ +{ + "title": "AI Notebooks" +} diff --git a/packages/manager/apps/pci-ai-notebooks/public/translations/regions/Messages_de_DE.json b/packages/manager/apps/pci-ai-notebooks/public/translations/regions/Messages_de_DE.json new file mode 100644 index 000000000000..24b6c3bde262 --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/public/translations/regions/Messages_de_DE.json @@ -0,0 +1,67 @@ +{ + "region_SBG1": "Straßburg (SBG1)", + "region_BHS1": "Beauharnois (BHS1)", + "region_GRA1": "Gravelines (GRA1)", + "region_SBG": "Straßburg", + "region_SBG_micro": "Straßburg ({{ micro }})", + "region_BHS": "Beauharnois", + "region_BHS_micro": "Beauharnois ({{ micro }})", + "region_ERI": "London", + "region_ERI_micro": "London ({{ micro }})", + "region_GRA": "Gravelines", + "region_GRA_micro": "Gravelines ({{ micro }})", + "region_LIM": "Limburg", + "region_LIM_micro": "Limburg ({{ micro }})", + "region_RBX": "Roubaix", + "region_RBX_micro": "Roubaix ({{ micro }})", + "region_WAW": "Warschau", + "region_WAW_micro": "Warschau ({{ micro }})", + "region_DE": "Frankfurt", + "region_DE_micro": "Frankfurt ({{ micro }})", + "region_UK": "London", + "region_UK_micro": "London ({{ micro }})", + "region_SGP": "Singapur", + "region_SGP_micro": "Singapur ({{ micro }})", + "region_SYD": "Sydney", + "region_SYD_micro": "Sydney ({{ micro }})", + "region_US": "USA", + "region_US_micro": "USA ({{ micro }})", + "region_GS": "GS", + "region_MAD": "Madrid", + "region_BRU": "Brüssel", + "region_SHA_micro": "Gravelines (SHADOW-EU-1)", + "region_GS_micro": "Gridscale ({{ micro }})", + "region_MAD_micro": "Madrid ({{ micro }})", + "region_BRU_micro": "Brüssel ({{ micro }})", + "region_localize": "Lokalisieren", + "region_location_SBG": "Mitteleuropa (Frankreich)", + "region_location_WAW": "Mitteleuropa (Polen)", + "region_location_BHS": "Nordamerika (Kanada)", + "region_location_ERI": "Westeuropa (Vereinigtes Königreich)", + "region_location_GRA": "Westeuropa (Frankreich)", + "region_location_GS": "Westeuropa", + "region_location_MAD": "Westeuropa", + "region_location_BRU": "Westeuropa", + "region_location_LIM": "Mitteleuropa (Deutschland)", + "region_location_RBX": "Westeuropa (Frankreich)", + "region_location_DE": "Mitteleuropa (Deutschland)", + "region_location_UK": "Westeuropa (Vereinigtes Königreich)", + "region_location_SGP": "Südostasien (Singapur)", + "region_location_SYD": "Ozeanien (Australien)", + "region_location_US": "USA", + "region_continent_SBG": "Mitteleuropa", + "region_continent_WAW": "Mitteleuropa", + "region_continent_BHS": "Nordamerika", + "region_continent_GRA": "Westeuropa", + "region_continent_RBX": "Westeuropa", + "region_continent_GS": "Westeuropa", + "region_continent_MAD": "Westeuropa", + "region_continent_BRU": "Westeuropa", + "region_continent_DE": "Mitteleuropa", + "region_continent_UK": "Westeuropa", + "region_continent_SGP": "Südostasien", + "region_continent_SYD": "Ozeanien", + "region_continent_US": "USA", + "region_continent_SHA": "Westeuropa", + "region_continent_all": "Alle Standorte" +} diff --git a/packages/manager/apps/pci-ai-notebooks/public/translations/regions/Messages_en_GB.json b/packages/manager/apps/pci-ai-notebooks/public/translations/regions/Messages_en_GB.json new file mode 100644 index 000000000000..f91fd8920068 --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/public/translations/regions/Messages_en_GB.json @@ -0,0 +1,67 @@ +{ + "region_SBG1": "Strasbourg (SBG1)", + "region_BHS1": "Beauharnois (BHS1)", + "region_GRA1": "Gravelines (GRA1)", + "region_SBG": "Strasbourg", + "region_SBG_micro": "Strasbourg ({{ micro }})", + "region_BHS": "Beauharnois", + "region_BHS_micro": "Beauharnois ({{ micro }})", + "region_ERI": "London", + "region_ERI_micro": "London ({{ micro }})", + "region_GRA": "Gravelines", + "region_GRA_micro": "Gravelines ({{ micro }})", + "region_LIM": "Limburg", + "region_LIM_micro": "Limburg ({{ micro }})", + "region_RBX": "Roubaix", + "region_RBX_micro": "Roubaix ({{ micro }})", + "region_WAW": "Warsaw", + "region_WAW_micro": "Warsaw ({{ micro }})", + "region_DE": "Frankfurt", + "region_DE_micro": "Frankfurt ({{ micro }})", + "region_UK": "London", + "region_UK_micro": "London ({{ micro }})", + "region_SGP": "Singapore", + "region_SGP_micro": "Singapore ({{ micro }})", + "region_SYD": "Sydney", + "region_SYD_micro": "Sydney ({{ micro }})", + "region_US": "United States of America", + "region_US_micro": "United States ({{ micro }})", + "region_GS": "GS", + "region_MAD": "Madrid", + "region_BRU": "Brussels", + "region_SHA_micro": "Gravelines (SHADOW-EU-1)", + "region_GS_micro": "Gridscale ({{ micro }})", + "region_MAD_micro": "Madrid ({{ micro }})", + "region_BRU_micro": "Brussels ({{ micro }})", + "region_localize": "Locate", + "region_location_SBG": "Central Europe (France)", + "region_location_WAW": "Central Europe (Poland)", + "region_location_BHS": "North America (Canada)", + "region_location_ERI": "Western Europe (United Kingdom)", + "region_location_GRA": "Western Europe (France)", + "region_location_GS": "Western Europe", + "region_location_MAD": "Western Europe", + "region_location_BRU": "Western Europe", + "region_location_LIM": "Central Europe (Germany)", + "region_location_RBX": "Western Europe (France)", + "region_location_DE": "Central Europe (Germany)", + "region_location_UK": "Western Europe (United Kingdom)", + "region_location_SGP": "South-East Asia (Singapore)", + "region_location_SYD": "Oceania (Australia)", + "region_location_US": "United States of America", + "region_continent_SBG": "Central Europe", + "region_continent_WAW": "Central Europe", + "region_continent_BHS": "North America", + "region_continent_GRA": "Western Europe", + "region_continent_RBX": "Western Europe", + "region_continent_GS": "Western Europe", + "region_continent_MAD": "Western Europe", + "region_continent_BRU": "Western Europe", + "region_continent_DE": "Central Europe", + "region_continent_UK": "Western Europe", + "region_continent_SGP": "South-East Asia", + "region_continent_SYD": "Oceania", + "region_continent_US": "United States of America", + "region_continent_SHA": "Western Europe", + "region_continent_all": "All locations" +} diff --git a/packages/manager/apps/pci-ai-notebooks/public/translations/regions/Messages_es_ES.json b/packages/manager/apps/pci-ai-notebooks/public/translations/regions/Messages_es_ES.json new file mode 100644 index 000000000000..d78d3808005d --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/public/translations/regions/Messages_es_ES.json @@ -0,0 +1,67 @@ +{ + "region_SBG1": "Estrasburgo (SBG1)", + "region_BHS1": "Beauharnois (BHS1)", + "region_GRA1": "Gravelines (GRA1)", + "region_SBG": "Estrasburgo", + "region_SBG_micro": "Estrasburgo ({{ micro }})", + "region_BHS": "Beauharnois", + "region_BHS_micro": "Beauharnois ({{ micro }})", + "region_ERI": "Londres", + "region_ERI_micro": "Londres ({{ micro }})", + "region_GRA": "Gravelines", + "region_GRA_micro": "Gravelines ({{ micro }})", + "region_LIM": "Limburgo", + "region_LIM_micro": "Limburgo ({{ micro }})", + "region_RBX": "Roubaix", + "region_RBX_micro": "Roubaix ({{ micro }})", + "region_WAW": "Varsovia", + "region_WAW_micro": "Varsovia ({{ micro }})", + "region_DE": "Fráncfort", + "region_DE_micro": "Fráncfort ({{ micro }})", + "region_UK": "Londres", + "region_UK_micro": "Londres ({{ micro }})", + "region_SGP": "Singapur", + "region_SGP_micro": "Singapur ({{ micro }})", + "region_SYD": "Sídney", + "region_SYD_micro": "Sídney ({{ micro }})", + "region_US": "Estados Unidos", + "region_US_micro": "Estados Unidos ({{ micro }})", + "region_GS": "GS", + "region_MAD": "Madrid", + "region_BRU": "Bruselas", + "region_SHA_micro": "Gravelines (SHADOW-EU-1)", + "region_GS_micro": "Gridscale ({{ micro }})", + "region_MAD_micro": "Madrid ({{ micro }})", + "region_BRU_micro": "Bruselas ({{ micro }})", + "region_localize": "Localizar", + "region_location_SBG": "Europa Central (Francia)", + "region_location_WAW": "Europa Central (Polonia)", + "region_location_BHS": "Norteamérica (Canadá)", + "region_location_ERI": "Europa Occidental (Reino Unido)", + "region_location_GRA": "Europa Occidental (Francia)", + "region_location_GS": "Western Europe", + "region_location_MAD": "Western Europe", + "region_location_BRU": "Western Europe", + "region_location_LIM": "Europa Central (Alemania)", + "region_location_RBX": "Europa Occidental (Francia)", + "region_location_DE": "Europa Central (Alemania)", + "region_location_UK": "Europa Occidental (Reino Unido)", + "region_location_SGP": "Sudeste asiático (Singapur)", + "region_location_SYD": "Oceanía (Australia)", + "region_location_US": "Estados Unidos", + "region_continent_SBG": "Europa Central", + "region_continent_WAW": "Europa Central", + "region_continent_BHS": "Norteamérica", + "region_continent_GRA": "Europa Occidental", + "region_continent_RBX": "Europa Occidental", + "region_continent_GS": "Western Europe", + "region_continent_MAD": "Western Europe", + "region_continent_BRU": "Western Europe", + "region_continent_DE": "Europa Central", + "region_continent_UK": "Europa Occidental", + "region_continent_SGP": "Sudeste Asiático", + "region_continent_SYD": "Oceanía", + "region_continent_US": "Estados Unidos", + "region_continent_SHA": "Europa Occidental", + "region_continent_all": "Todas las localizaciones" +} diff --git a/packages/manager/apps/pci-ai-notebooks/public/translations/regions/Messages_fr_CA.json b/packages/manager/apps/pci-ai-notebooks/public/translations/regions/Messages_fr_CA.json new file mode 100644 index 000000000000..8d6147ad82fb --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/public/translations/regions/Messages_fr_CA.json @@ -0,0 +1,67 @@ +{ + "region_SBG1": "Strasbourg (SBG1)", + "region_BHS1": "Beauharnois (BHS1)", + "region_GRA1": "Gravelines (GRA1)", + "region_SBG": "Strasbourg", + "region_SBG_micro": "Strasbourg ({{ micro }})", + "region_BHS": "Beauharnois", + "region_BHS_micro": "Beauharnois ({{ micro }})", + "region_ERI": "Londres", + "region_ERI_micro": "Londres ({{ micro }})", + "region_GRA": "Gravelines", + "region_GRA_micro": "Gravelines ({{ micro }})", + "region_LIM": "Limburg", + "region_LIM_micro": "Limburg ({{ micro }})", + "region_RBX": "Roubaix", + "region_RBX_micro": "Roubaix ({{ micro }})", + "region_WAW": "Varsovie", + "region_WAW_micro": "Varsovie ({{ micro }})", + "region_DE": "Francfort", + "region_DE_micro": "Francfort ({{ micro }})", + "region_UK": "Londres", + "region_UK_micro": "Londres ({{ micro }})", + "region_SGP": "Singapour", + "region_SGP_micro": "Singapour ({{ micro }})", + "region_SYD": "Sydney", + "region_SYD_micro": "Sydney ({{ micro }})", + "region_US": "États-Unis", + "region_US_micro": "États-Unis ({{ micro }})", + "region_GS": "GS", + "region_MAD": "Madrid", + "region_BRU": "Bruxelles", + "region_SHA_micro": "Gravelines (SHADOW-EU-1)", + "region_GS_micro": "Gridscale ({{ micro }})", + "region_MAD_micro": "Madrid ({{ micro }})", + "region_BRU_micro": "Bruxelles ({{ micro }})", + "region_localize": "Localiser", + "region_location_SBG": "Europe centrale (France)", + "region_location_WAW": "Europe centrale (Pologne)", + "region_location_BHS": "Amérique du Nord (Canada)", + "region_location_ERI": "Europe de l'Ouest (Grande-Bretagne)", + "region_location_GRA": "Europe de l'Ouest (France)", + "region_location_GS": "Western Europe", + "region_location_MAD": "Western Europe", + "region_location_BRU": "Western Europe", + "region_location_LIM": "Europe centrale (Allemagne)", + "region_location_RBX": "Europe de l'Ouest (France)", + "region_location_DE": "Europe centrale (Allemagne)", + "region_location_UK": "Europe de l'Ouest (Grande-Bretagne)", + "region_location_SGP": "Asie du Sud-Est (Singapour)", + "region_location_SYD": "Océanie (Australie)", + "region_location_US": "États-Unis", + "region_continent_SBG": "Europe centrale", + "region_continent_WAW": "Europe centrale", + "region_continent_BHS": "Amérique du Nord", + "region_continent_GRA": "Europe de l'Ouest", + "region_continent_RBX": "Europe de l'Ouest", + "region_continent_GS": "Western Europe", + "region_continent_MAD": "Western Europe", + "region_continent_BRU": "Western Europe", + "region_continent_DE": "Europe centrale", + "region_continent_UK": "Europe de l'Ouest", + "region_continent_SGP": "Asie du Sud-Est", + "region_continent_SYD": "Océanie", + "region_continent_US": "États-Unis", + "region_continent_SHA": "Europe de l'Ouest", + "region_continent_all": "Toutes les localisations" +} diff --git a/packages/manager/apps/pci-ai-notebooks/public/translations/regions/Messages_fr_FR.json b/packages/manager/apps/pci-ai-notebooks/public/translations/regions/Messages_fr_FR.json new file mode 100644 index 000000000000..8d6147ad82fb --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/public/translations/regions/Messages_fr_FR.json @@ -0,0 +1,67 @@ +{ + "region_SBG1": "Strasbourg (SBG1)", + "region_BHS1": "Beauharnois (BHS1)", + "region_GRA1": "Gravelines (GRA1)", + "region_SBG": "Strasbourg", + "region_SBG_micro": "Strasbourg ({{ micro }})", + "region_BHS": "Beauharnois", + "region_BHS_micro": "Beauharnois ({{ micro }})", + "region_ERI": "Londres", + "region_ERI_micro": "Londres ({{ micro }})", + "region_GRA": "Gravelines", + "region_GRA_micro": "Gravelines ({{ micro }})", + "region_LIM": "Limburg", + "region_LIM_micro": "Limburg ({{ micro }})", + "region_RBX": "Roubaix", + "region_RBX_micro": "Roubaix ({{ micro }})", + "region_WAW": "Varsovie", + "region_WAW_micro": "Varsovie ({{ micro }})", + "region_DE": "Francfort", + "region_DE_micro": "Francfort ({{ micro }})", + "region_UK": "Londres", + "region_UK_micro": "Londres ({{ micro }})", + "region_SGP": "Singapour", + "region_SGP_micro": "Singapour ({{ micro }})", + "region_SYD": "Sydney", + "region_SYD_micro": "Sydney ({{ micro }})", + "region_US": "États-Unis", + "region_US_micro": "États-Unis ({{ micro }})", + "region_GS": "GS", + "region_MAD": "Madrid", + "region_BRU": "Bruxelles", + "region_SHA_micro": "Gravelines (SHADOW-EU-1)", + "region_GS_micro": "Gridscale ({{ micro }})", + "region_MAD_micro": "Madrid ({{ micro }})", + "region_BRU_micro": "Bruxelles ({{ micro }})", + "region_localize": "Localiser", + "region_location_SBG": "Europe centrale (France)", + "region_location_WAW": "Europe centrale (Pologne)", + "region_location_BHS": "Amérique du Nord (Canada)", + "region_location_ERI": "Europe de l'Ouest (Grande-Bretagne)", + "region_location_GRA": "Europe de l'Ouest (France)", + "region_location_GS": "Western Europe", + "region_location_MAD": "Western Europe", + "region_location_BRU": "Western Europe", + "region_location_LIM": "Europe centrale (Allemagne)", + "region_location_RBX": "Europe de l'Ouest (France)", + "region_location_DE": "Europe centrale (Allemagne)", + "region_location_UK": "Europe de l'Ouest (Grande-Bretagne)", + "region_location_SGP": "Asie du Sud-Est (Singapour)", + "region_location_SYD": "Océanie (Australie)", + "region_location_US": "États-Unis", + "region_continent_SBG": "Europe centrale", + "region_continent_WAW": "Europe centrale", + "region_continent_BHS": "Amérique du Nord", + "region_continent_GRA": "Europe de l'Ouest", + "region_continent_RBX": "Europe de l'Ouest", + "region_continent_GS": "Western Europe", + "region_continent_MAD": "Western Europe", + "region_continent_BRU": "Western Europe", + "region_continent_DE": "Europe centrale", + "region_continent_UK": "Europe de l'Ouest", + "region_continent_SGP": "Asie du Sud-Est", + "region_continent_SYD": "Océanie", + "region_continent_US": "États-Unis", + "region_continent_SHA": "Europe de l'Ouest", + "region_continent_all": "Toutes les localisations" +} diff --git a/packages/manager/apps/pci-ai-notebooks/public/translations/regions/Messages_it_IT.json b/packages/manager/apps/pci-ai-notebooks/public/translations/regions/Messages_it_IT.json new file mode 100644 index 000000000000..2d2b67b9b45d --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/public/translations/regions/Messages_it_IT.json @@ -0,0 +1,67 @@ +{ + "region_SBG1": "Strasburgo (SBG1)", + "region_BHS1": "Beauharnois (BHS1)", + "region_GRA1": "Gravelines (GRA1)", + "region_SBG": "Strasburgo", + "region_SBG_micro": "Strasburgo ({{ micro }})", + "region_BHS": "Beauharnois", + "region_BHS_micro": "Beauharnois ({{ micro }})", + "region_ERI": "Londra", + "region_ERI_micro": "Londra ({{ micro }})", + "region_GRA": "Gravelines", + "region_GRA_micro": "Gravelines ({{ micro }})", + "region_LIM": "Limburgo", + "region_LIM_micro": "Limburgo ({{ micro }})", + "region_RBX": "Roubaix", + "region_RBX_micro": "Roubaix ({{ micro }})", + "region_WAW": "Varsavia", + "region_WAW_micro": "Varsavia ({{ micro }})", + "region_DE": "Francoforte", + "region_DE_micro": "Francoforte ({{ micro }})", + "region_UK": "Londra", + "region_UK_micro": "Londra ({{ micro }})", + "region_SGP": "Singapore", + "region_SGP_micro": "Singapore ({{ micro }})", + "region_SYD": "Sydney", + "region_SYD_micro": "Sydney ({{ micro }})", + "region_US": "Stati Uniti", + "region_US_micro": "Stati Uniti ({{ micro }})", + "region_GS": "GS", + "region_MAD": "Madrid", + "region_BRU": "Bruxelles", + "region_SHA_micro": "Gravelines (SHADOW-EU-1)", + "region_GS_micro": "Gridscale ({{ micro }})", + "region_MAD_micro": "Madrid ({{ micro }})", + "region_BRU_micro": "Bruxelles ({{ micro }})", + "region_localize": "Localizza", + "region_location_SBG": "Europa centrale (Francia)", + "region_location_WAW": "Europa centrale (Polonia)", + "region_location_BHS": "Nord America (Canada)", + "region_location_ERI": "Europa Occidentale (Gran Bretagna)", + "region_location_GRA": "Europa Occidentale (Francia)", + "region_location_GS": "Europa Occidentale", + "region_location_MAD": "Europa Occidentale", + "region_location_BRU": "Europa Occidentale", + "region_location_LIM": "Europa centrale (Germania)", + "region_location_RBX": "Europa Occidentale (Francia)", + "region_location_DE": "Europa centrale (Germania)", + "region_location_UK": "Europa Occidentale (Gran Bretagna)", + "region_location_SGP": "Sud-est asiatico (Singapore)", + "region_location_SYD": "Oceania (Australia)", + "region_location_US": "Stati Uniti", + "region_continent_SBG": "Europa centrale", + "region_continent_WAW": "Europa centrale", + "region_continent_BHS": "Nord America ", + "region_continent_GRA": "Europa Occidentale", + "region_continent_RBX": "Europa Occidentale", + "region_continent_GS": "Europa Occidentale", + "region_continent_MAD": "Europa Occidentale", + "region_continent_BRU": "Europa Occidentale", + "region_continent_DE": "Europa centrale", + "region_continent_UK": "Europa Occidentale", + "region_continent_SGP": "Asia Pacifica", + "region_continent_SYD": "Oceania", + "region_continent_US": "Stati Uniti", + "region_continent_SHA": "Europa Occidentale", + "region_continent_all": "Tutte le Region" +} diff --git a/packages/manager/apps/pci-ai-notebooks/public/translations/regions/Messages_pl_PL.json b/packages/manager/apps/pci-ai-notebooks/public/translations/regions/Messages_pl_PL.json new file mode 100644 index 000000000000..6f3791ace50e --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/public/translations/regions/Messages_pl_PL.json @@ -0,0 +1,67 @@ +{ + "region_SBG1": "Strasburg (SBG1)", + "region_BHS1": "Beauharnois (BHS1)", + "region_GRA1": "Gravelines (GRA1)", + "region_SBG": "Strasburg", + "region_SBG_micro": "Strasburg ({{ micro }})", + "region_BHS": "Beauharnois", + "region_BHS_micro": "Beauharnois ({{ micro }})", + "region_ERI": "Londyn", + "region_ERI_micro": "Londyn ({{ micro }})", + "region_GRA": "Gravelines", + "region_GRA_micro": "Gravelines ({{ micro }})", + "region_LIM": "Limburg", + "region_LIM_micro": "Limburg ({{ micro }})", + "region_RBX": "Roubaix", + "region_RBX_micro": "Roubaix ({{ micro }})", + "region_WAW": "Warszawa", + "region_WAW_micro": "Warszawa ({{ micro }})", + "region_DE": "Frankfurt", + "region_DE_micro": "Frankfurt ({{ micro }})", + "region_UK": "Londyn", + "region_UK_micro": "Londyn ({{ micro }})", + "region_SGP": "Singapur", + "region_SGP_micro": "Singapur ({{ micro }})", + "region_SYD": "Sydney", + "region_SYD_micro": "Sydney ({{ micro }})", + "region_US": "Stany Zjednoczone", + "region_US_micro": "Stany Zjednoczone ({{ micro }})", + "region_GS": "GS", + "region_MAD": "Madryt", + "region_BRU": "Bruksela", + "region_SHA_micro": "Gravelines (SHADOW-EU-1)", + "region_GS_micro": "Gridscale ({{micro}})", + "region_MAD_micro": "Madryt ({{micro}})", + "region_BRU_micro": "Bruksela ({{micro}})", + "region_localize": "Lokalizacja", + "region_location_SBG": "Europa Środkowa (Francja)", + "region_location_WAW": "Europa Środkowa (Polska)", + "region_location_BHS": "Ameryka Północna (Kanada)", + "region_location_ERI": "Europa Zachodnia (Wielka Brytania)", + "region_location_GRA": "Europa Zachodnia (Francja)", + "region_location_GS": "Europa Zachodnia", + "region_location_MAD": "Europa Zachodnia", + "region_location_BRU": "Europa Zachodnia", + "region_location_LIM": "Europa Środkowa (Niemcy)", + "region_location_RBX": "Europa Zachodnia (Francja)", + "region_location_DE": "Europa Środkowa (Niemcy)", + "region_location_UK": "Europa Zachodnia (Wielka Brytania)", + "region_location_SGP": "Azja Południowo-Wschodnia (Singapur)", + "region_location_SYD": "Oceania (Australia)", + "region_location_US": "Stany Zjednoczone", + "region_continent_SBG": "Europa Środkowa", + "region_continent_WAW": "Europa Środkowa", + "region_continent_BHS": "Ameryka Północna", + "region_continent_GRA": "Europa Zachodnia", + "region_continent_RBX": "Europa Zachodnia", + "region_continent_GS": "Europa Zachodnia", + "region_continent_MAD": "Europa Zachodnia", + "region_continent_BRU": "Europa Zachodnia", + "region_continent_DE": "Europa Środkowa", + "region_continent_UK": "Europa Zachodnia", + "region_continent_SGP": "Azja Południowo-Wschodnia", + "region_continent_SYD": "Oceania", + "region_continent_US": "Stany Zjednoczone", + "region_continent_SHA": "Europa Zachodnia", + "region_continent_all": "Wszystkie lokalizacje" +} diff --git a/packages/manager/apps/pci-ai-notebooks/public/translations/regions/Messages_pt_PT.json b/packages/manager/apps/pci-ai-notebooks/public/translations/regions/Messages_pt_PT.json new file mode 100644 index 000000000000..365abdb1cdac --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/public/translations/regions/Messages_pt_PT.json @@ -0,0 +1,67 @@ +{ + "region_SBG1": "Estrasburgo (SBG1)", + "region_BHS1": "Beauharnois (BHS1)", + "region_GRA1": "Gravelines (GRA1)", + "region_SBG": "Estrasburgo", + "region_SBG_micro": "Estrasburgo ({{ micro }})", + "region_BHS": "Beauharnois", + "region_BHS_micro": "Beauharnois ({{ micro }})", + "region_ERI": "Londres", + "region_ERI_micro": "Londres ({{ micro }})", + "region_GRA": "Gravelines", + "region_GRA_micro": "Gravelines ({{ micro }})", + "region_LIM": "Limburgo", + "region_LIM_micro": "Limburgo ({{ micro }})", + "region_RBX": "Roubaix", + "region_RBX_micro": "Roubaix ({{ micro }})", + "region_WAW": "Varsóvia", + "region_WAW_micro": "Varsóvia ({{ micro }})", + "region_DE": "Frankfurt ", + "region_DE_micro": "Frankfurt ({{ micro }})", + "region_UK": "Londres", + "region_UK_micro": "Londres ({{ micro }})", + "region_SGP": "Singapura", + "region_SGP_micro": "Singapura ({{ micro }})", + "region_SYD": "Sydney", + "region_SYD_micro": "Sydney ({{ micro }})", + "region_US": "Estados Unidos", + "region_US_micro": "Estados Unidos ({{ micro }})", + "region_GS": "GS", + "region_MAD": "Madrid", + "region_BRU": "Bruxelas", + "region_SHA_micro": "Gravelines (SHADOW-EU-1)", + "region_GS_micro": "Gridscale ({{ micro }})", + "region_MAD_micro": "Madrid ({{ micro }})", + "region_BRU_micro": "Bruxelas ({{ micro }})", + "region_localize": "Localizar", + "region_location_SBG": "Europa Central (França)", + "region_location_WAW": "Europa Central (Polónia)", + "region_location_BHS": "América do Norte (Canadá)", + "region_location_ERI": "Europa Ocidental (Reino Unido)", + "region_location_GRA": "Europa Ocidental (França)", + "region_location_GS": "Western Europe", + "region_location_MAD": "Western Europe", + "region_location_BRU": "Western Europe", + "region_location_LIM": "Europa Central (Alemanha)", + "region_location_RBX": "Europa Ocidental (França)", + "region_location_DE": "Europa Central (Alemanha)", + "region_location_UK": "Europa Ocidental (Reino Unido)", + "region_location_SGP": "Sudeste Asiático (Singapura)", + "region_location_SYD": "Oceânia (Austrália)", + "region_location_US": "Estados Unidos", + "region_continent_SBG": "Europa Central", + "region_continent_WAW": "Europa Central", + "region_continent_BHS": "América do Norte", + "region_continent_GRA": "Europa Ocidental", + "region_continent_RBX": "Europa Ocidental", + "region_continent_GS": "Western Europe", + "region_continent_MAD": "Western Europe", + "region_continent_BRU": "Western Europe", + "region_continent_DE": "Europa Central", + "region_continent_UK": "Europa Ocidental", + "region_continent_SGP": "Sudeste Asiático", + "region_continent_SYD": "Oceânia", + "region_continent_US": "Estados Unidos", + "region_continent_SHA": "Europa Ocidental", + "region_continent_all": "Todas as localizações" +} diff --git a/packages/manager/apps/pci-ai-notebooks/src/App.tsx b/packages/manager/apps/pci-ai-notebooks/src/App.tsx new file mode 100644 index 000000000000..8b9a4cd48b07 --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/src/App.tsx @@ -0,0 +1,34 @@ +import React, { useEffect } from 'react'; +import { QueryClientProvider } from '@tanstack/react-query'; +import { odsSetup } from '@ovhcloud/ods-common-core'; +import { useShell } from '@ovh-ux/manager-react-shell-client'; + +import '@ovhcloud/ods-theme-blue-jeans'; +import './global.css'; + +import queryClient from './query.client'; +import Router from '@/routes/Router'; +import Loading from './components/Loading/Loading'; +import { useLoadingIndicatorContext } from './contexts/loadingIndicatorContext'; +import ProgressLoader from './components/Loading/ProgressLoader'; + +odsSetup(); + +function App() { + const { loading } = useLoadingIndicatorContext(); + const shell = useShell(); + useEffect(() => { + shell.ux.hidePreloader(); + }, []); + + return ( + + {loading && } + }> + + + + ); +} + +export default App; diff --git a/packages/manager/apps/pci-ai-notebooks/src/__tests__/helpers/pointerEvent.ts b/packages/manager/apps/pci-ai-notebooks/src/__tests__/helpers/pointerEvent.ts new file mode 100644 index 000000000000..a27898956a04 --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/src/__tests__/helpers/pointerEvent.ts @@ -0,0 +1,19 @@ +interface PointerEventProps extends EventInit { + button: number; + ctrlKey: boolean; +} +export class PointerEvent extends Event { + button: number; + + ctrlKey: boolean; + + constructor(type: string, props: PointerEventProps) { + super(type, props); + if (props.button != null) { + this.button = props.button; + } + if (props.ctrlKey != null) { + this.ctrlKey = props.ctrlKey; + } + } +} diff --git a/packages/manager/apps/pci-ai-notebooks/src/__tests__/helpers/selectHelper.ts b/packages/manager/apps/pci-ai-notebooks/src/__tests__/helpers/selectHelper.ts new file mode 100644 index 000000000000..9941ec5ee168 --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/src/__tests__/helpers/selectHelper.ts @@ -0,0 +1,39 @@ +import { act, fireEvent, screen, waitFor } from '@testing-library/react'; + +/** + * Open a Select component and select the correct option + * @param triggerId testId of the trigger select + * @param options labels of the options that should be in the select + * @param optionToSelect the option to select + */ +export async function handleSelectOption( + triggerId: string, + options: string[], + optionToSelect: string, +) { + // Open select + act(() => { + const trigger = screen.getByTestId(triggerId); + fireEvent.focus(trigger); + fireEvent.keyDown(trigger, { key: 'Enter', code: 13 }); + }); + + // Check if select has the options + await waitFor(() => { + expect(screen.getByTestId(triggerId)).not.toHaveAttribute( + 'data-state', + 'closed', + ); + options.forEach((optionLabel) => { + expect(screen.getByText(optionLabel)).toBeInTheDocument(); + }); + }); + // Select the option + act(() => { + const optionsElements = screen.getAllByRole('option'); + const elem = optionsElements.find((e) => + e.innerHTML.includes(optionToSelect), + ); + fireEvent.keyDown(elem, { key: 'Enter', code: 13 }); + }); +} diff --git a/packages/manager/apps/pci-ai-notebooks/src/__tests__/helpers/wrappers/QueryClientWrapper.tsx b/packages/manager/apps/pci-ai-notebooks/src/__tests__/helpers/wrappers/QueryClientWrapper.tsx new file mode 100644 index 000000000000..1b9e387c9f5a --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/src/__tests__/helpers/wrappers/QueryClientWrapper.tsx @@ -0,0 +1,10 @@ +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; + +const queryClient = new QueryClient(); +export const QueryClientWrapper = ({ + children, +}: { + children: React.ReactNode; +}) => ( + {children} +); diff --git a/packages/manager/apps/pci-ai-notebooks/src/__tests__/helpers/wrappers/RouterWithLocationWrapper.tsx b/packages/manager/apps/pci-ai-notebooks/src/__tests__/helpers/wrappers/RouterWithLocationWrapper.tsx new file mode 100644 index 000000000000..0d310dca93fb --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/src/__tests__/helpers/wrappers/RouterWithLocationWrapper.tsx @@ -0,0 +1,57 @@ +import React from 'react'; +import { + RouterProvider, + createHashRouter, + MemoryRouter, + useLocation, +} from 'react-router-dom'; +import * as useLoadingIndicator from '@/contexts/loadingIndicatorContext'; + +/** + * Displays the current location in order to test the syncing between the state of the hook and the url + */ +export const LocationDisplay = () => { + const location = useLocation(); + return ( +
{`${location.pathname}${location.search}`}
+ ); +}; + +export const RouterWithLocationWrapper = ({ + children, + initialEntries = ['/test'], +}: { + children: React.ReactNode; + initialEntries: string[]; +}) => { + return ( + + {children} + + + ); +}; + +export const HashRouterWithLocationWrapper = ({ + children, +}: { + children: React.ReactNode; +}) => { + const element = ( + <> + {children} + + + ); + const router = createHashRouter([ + { + path: '/', + element, + }, + ]); + return ( + + + + ); +}; diff --git a/packages/manager/apps/pci-ai-notebooks/src/__tests__/setupTest.ts b/packages/manager/apps/pci-ai-notebooks/src/__tests__/setupTest.ts new file mode 100644 index 000000000000..8cd2e90548c9 --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/src/__tests__/setupTest.ts @@ -0,0 +1,7 @@ +import '@testing-library/jest-dom'; +import { PointerEvent } from './helpers/pointerEvent'; + +// use a custom pointerEvent as jest does not implement it. +// it is requiered for DropdownMenus +// source: https://github.com/radix-ui/primitives/issues/856#issuecomment-928704064 +window.PointerEvent = PointerEvent as any; diff --git a/packages/manager/apps/pci-ai-notebooks/src/components/Breadcrumb/Breadcrumb.tsx b/packages/manager/apps/pci-ai-notebooks/src/components/Breadcrumb/Breadcrumb.tsx new file mode 100644 index 000000000000..c790aff8ff7c --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/src/components/Breadcrumb/Breadcrumb.tsx @@ -0,0 +1,82 @@ +import React, { useState } from 'react'; +import { Params, useParams, useLocation, useMatches } from 'react-router-dom'; +import { useNavigation } from '@ovh-ux/manager-react-shell-client'; +import usePciProject from '@/data/hooks/pciProjects.api.hooks'; +import { Skeleton } from '../ui/skeleton'; +import { Link, A } from '../links'; + +export type BreadcrumbHandleParams = { + data: unknown; + params: Params; +}; + +export interface MatchWithBreadcrumb { + id: string; + pathname: string; + params: Params; + data: unknown; + handle: { + breadcrumb?: (breadcrumbParams: { + params: Params; + data: unknown; + }) => React.ReactElement | null; + }; +} + +function Breadcrumb(): JSX.Element { + const { projectId } = useParams(); + const { data: project } = usePciProject(); + + const location = useLocation(); + + const navigation = useNavigation(); + const [baseUrl, setBaseUrl] = useState(''); + const matches = useMatches() as MatchWithBreadcrumb[]; + const [breadcrumbData, setBreadcrumbData] = React.useState([]); + + React.useEffect(() => { + const breadcrumbArray = matches + .filter((match) => Boolean(match.handle?.breadcrumb)) + .map((match) => { + return { + path: match.pathname, + label: match.handle.breadcrumb(match), + }; + }); + setBreadcrumbData(breadcrumbArray); + }, [location.pathname]); + + React.useEffect(() => { + const updateNav = async () => { + const url = await navigation.getURL('public-cloud', ``, {}); + setBaseUrl(url as string); + }; + updateNav(); + }, [navigation]); + + return ( + <> + + {project?.description ?? ( + + )} + + {breadcrumbData.map((bc, index) => ( + + | + {index < breadcrumbData.length - 1 ? ( + + {bc.label} + + ) : ( + + {bc.label} + + )} + + ))} + + ); +} + +export default Breadcrumb; diff --git a/packages/manager/apps/pci-ai-notebooks/src/components/Breadcrumb/BreadcrumbItem.tsx b/packages/manager/apps/pci-ai-notebooks/src/components/Breadcrumb/BreadcrumbItem.tsx new file mode 100644 index 000000000000..9d7164f1b24d --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/src/components/Breadcrumb/BreadcrumbItem.tsx @@ -0,0 +1,12 @@ +import { useTranslation } from 'react-i18next'; + +interface BreadcrumbItemProps { + translationKey: string; + namespace: string; +} +const BreadcrumbItem = ({ translationKey, namespace }: BreadcrumbItemProps) => { + const { t } = useTranslation(namespace); + return t(translationKey); +}; + +export default BreadcrumbItem; diff --git a/packages/manager/apps/pci-ai-notebooks/src/components/Loading/Loading.tsx b/packages/manager/apps/pci-ai-notebooks/src/components/Loading/Loading.tsx new file mode 100644 index 000000000000..d534bff440af --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/src/components/Loading/Loading.tsx @@ -0,0 +1,11 @@ +import { OsdsSpinner } from '@ovhcloud/ods-components/react'; + +export default function Loading() { + return ( +
+
+ +
+
+ ); +} diff --git a/packages/manager/apps/pci-ai-notebooks/src/components/Loading/ProgressLoader.tsx b/packages/manager/apps/pci-ai-notebooks/src/components/Loading/ProgressLoader.tsx new file mode 100644 index 000000000000..7e0cca660f09 --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/src/components/Loading/ProgressLoader.tsx @@ -0,0 +1,35 @@ +import { useEffect, useState } from 'react'; + +export default function ProgressLoader() { + const [progress, setProgress] = useState(0); + + useEffect(() => { + const interval = setInterval(() => { + setProgress((prevProgress) => { + // Increment progress in a non-linear fashion for a more dynamic feel + const increment = Math.random() * 20; + const nextProgress = prevProgress + increment; + if (nextProgress < 95) { + return nextProgress; + } + clearInterval(interval); // Stop incrementing near 100% to mimic NProgress behavior + return prevProgress; + }); + }, 500); // Increase progress more frequently + + return () => clearInterval(interval); // Cleanup on component unmount + }, []); + + return ( +
+
+
+ ); +} diff --git a/packages/manager/apps/pci-ai-notebooks/src/components/PageLayout/PageLayout.tsx b/packages/manager/apps/pci-ai-notebooks/src/components/PageLayout/PageLayout.tsx new file mode 100644 index 000000000000..df32d00961fc --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/src/components/PageLayout/PageLayout.tsx @@ -0,0 +1,11 @@ +import React from 'react'; + +const PageLayout: React.FC = ({ children }) => { + return ( +
+ {children} +
+ ); +}; + +export default PageLayout; diff --git a/packages/manager/apps/pci-ai-notebooks/src/components/errorBoundary.tsx b/packages/manager/apps/pci-ai-notebooks/src/components/errorBoundary.tsx new file mode 100644 index 000000000000..66832b01741f --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/src/components/errorBoundary.tsx @@ -0,0 +1,74 @@ +import { useNavigation } from '@ovh-ux/manager-react-shell-client'; +import { useRouteError } from 'react-router-dom'; +import { useTranslation } from 'react-i18next'; +import errorImgSrc from '@/public/assets/oops.png'; +import { Alert, AlertDescription } from './ui/alert'; +import { Button } from './ui/button'; + +const ErrorBoundary = () => { + const error = useRouteError(); + const { t } = useTranslation('error'); + const nav = useNavigation(); + + const navigateToHomepage = () => { + nav.navigateTo('public-cloud', '', {}); + }; + const reloadPage = () => { + nav.reload(); + }; + + if (error instanceof Error) { + return ( +
+
+
+ +
+

{t('manager_error_page_title')}

+ + +

{t('manager_error_page_default')}

+

{error.message}

+ {'xOvhQueryId' in error && ( +

+ {t('manager_error_page_detail_code', { + code: error.xOvhQueryId, + })} +

+ )} +
+
+ +
+ + +
+
+
+ ); + } + return <>; +}; + +export default ErrorBoundary; diff --git a/packages/manager/apps/pci-ai-notebooks/src/components/links.tsx b/packages/manager/apps/pci-ai-notebooks/src/components/links.tsx new file mode 100644 index 000000000000..edca85019d07 --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/src/components/links.tsx @@ -0,0 +1,154 @@ +import * as React from 'react'; +import { useNavigation } from '@ovh-ux/manager-react-shell-client'; +import { + LinkProps, + NavLink as RouterNavLink, + Link as RouterLink, + NavLinkProps, +} from 'react-router-dom'; +import { cn } from '@/lib/utils'; +import { useLoadingIndicatorContext } from '@/contexts/loadingIndicatorContext'; + +function A({ + className, + children, + disabled, + ...props +}: React.AnchorHTMLAttributes & { disabled?: boolean }) { + const baseClassName = + 'text-primary-500 font-semibold outiline-none cursor-pointer no-underline hover:text-primary-700 hover:underline'; + const disabledClass = 'opacity-50 cursor-not-allowed hover:text-primary-500'; + const combinedClassName = cn( + baseClassName, + className, + disabled && disabledClass, + ); + if (disabled) { + // eslint-disable-next-line no-unused-vars + const { href, onClick, tabIndex, ...otherProps } = props; + return ( + + {children} + + ); + } + + return ( + + {children} + + ); +} + +function Link({ + className, + disabled, + children, + to, + ...props +}: LinkProps & { disabled?: boolean }) { + const { setLoading } = useLoadingIndicatorContext(); + const baseClassName = + 'text-primary-500 font-semibold outiline-none cursor-pointer no-underline hover:text-primary-700 hover:underline'; + const disabledClass = 'opacity-50 cursor-not-allowed hover:text-primary-500'; + const combinedClassName = cn( + baseClassName, + className, + disabled && disabledClass, + ); + return ( + { + if (disabled) { + e.preventDefault(); + } else { + setLoading(true); + } + }} + > + {children} + + ); +} + +function NavLink({ + className, + disabled, + children, + to, + end, + ...props +}: NavLinkProps & { disabled?: boolean }) { + const { setLoading } = useLoadingIndicatorContext(); + const baseClassName = + 'whitespace-nowrap w-fit text-primary-500 text-base font-semibold m-0 py-2 hover:text-primary-700'; + const activeClass = 'border-b-2 border-primary-500'; + const disabledClass = 'cursor-not-allowed opacity-50 hover:text-primary-500'; + + return ( + + cn( + baseClassName, + isActive && activeClass, + className, + disabled && disabledClass, + ) + } + onClick={(e) => { + if (disabled) { + e.preventDefault(); + } else { + setLoading(true); + } + }} + {...props} + > + {children} + + ); +} + +interface OvhLinkProps { + application: string; + path: string; + params?: Record; +} +function OvhLink({ + application, + path, + params = {}, + children, + ...props +}: React.AnchorHTMLAttributes & + OvhLinkProps & { disabled?: boolean }) { + const navigation = useNavigation(); + const [url, setUrl] = React.useState(''); + React.useEffect(() => { + const fetchUrl = async (urlParams: OvhLinkProps) => { + const goTo = (await navigation.getURL( + urlParams.application, + urlParams.path, + urlParams.params, + )) as string; + setUrl(goTo); + }; + fetchUrl({ application, path, params }); + }, [application, path, params, navigation]); + return ( + + {children} + + ); +} +export { A, Link, NavLink, OvhLink }; diff --git a/packages/manager/apps/pci-ai-notebooks/src/components/table-date.tsx b/packages/manager/apps/pci-ai-notebooks/src/components/table-date.tsx new file mode 100644 index 000000000000..703bd2fe396c --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/src/components/table-date.tsx @@ -0,0 +1,17 @@ +import { useMemo } from 'react'; +import { useLocale } from '@/hooks/useLocale'; + +interface TableDateCellProps { + date: Date; + options?: Intl.DateTimeFormatOptions; +} + +const FormattedDate = ({ date, options }: TableDateCellProps) => { + const locale = useLocale(); + const formater = useMemo( + () => new Intl.DateTimeFormat(locale.replace('_', '-'), options), + [locale], + ); + return formater.format(date); +}; +export default FormattedDate; diff --git a/packages/manager/apps/pci-ai-notebooks/src/components/tabs-menu.tsx b/packages/manager/apps/pci-ai-notebooks/src/components/tabs-menu.tsx new file mode 100644 index 000000000000..90ecea26b442 --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/src/components/tabs-menu.tsx @@ -0,0 +1,85 @@ +import { useRef } from 'react'; +import { Skeleton } from './ui/skeleton'; +import { ScrollArea, ScrollBar } from './ui/scroll-area'; +import { NavLink } from './links'; +import { Badge } from './ui/badge'; + +export interface Tab { + href: string; + label: string; + count?: number; + end?: boolean; + disabled?: boolean; +} +interface TabsMenuProps { + tabs: Tab[]; +} +const TabsMenu = ({ tabs }: TabsMenuProps) => { + const s = useRef(null); + return ( + { + s.current.children[1].scrollLeft += e.deltaY; + }} + > +
+ {tabs.map((tab, index) => ( + + {({ isActive }) => ( + { + if (node && isActive) + node?.scrollIntoView({ + behavior: 'smooth', + block: 'center', + }); + }} + > + {tab.label} + {tab.count > 0 && ( + + {tab.count} + + )} + + )} + + ))} +
+ +
+ ); +}; + +TabsMenu.Skeleton = function TabsMenuSkeleton() { + return ( +
+
+ + + + + + + + + + + + +
+
+ ); +}; + +export default TabsMenu; diff --git a/packages/manager/apps/pci-ai-notebooks/src/components/ui/accordion.tsx b/packages/manager/apps/pci-ai-notebooks/src/components/ui/accordion.tsx new file mode 100644 index 000000000000..e6a723d06574 --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/src/components/ui/accordion.tsx @@ -0,0 +1,56 @@ +import * as React from "react" +import * as AccordionPrimitive from "@radix-ui/react-accordion" +import { ChevronDown } from "lucide-react" + +import { cn } from "@/lib/utils" + +const Accordion = AccordionPrimitive.Root + +const AccordionItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AccordionItem.displayName = "AccordionItem" + +const AccordionTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + svg]:rotate-180", + className + )} + {...props} + > + {children} + + + +)) +AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName + +const AccordionContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + +
{children}
+
+)) + +AccordionContent.displayName = AccordionPrimitive.Content.displayName + +export { Accordion, AccordionItem, AccordionTrigger, AccordionContent } diff --git a/packages/manager/apps/pci-ai-notebooks/src/components/ui/alert-dialog.tsx b/packages/manager/apps/pci-ai-notebooks/src/components/ui/alert-dialog.tsx new file mode 100644 index 000000000000..8722561cf6bd --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/src/components/ui/alert-dialog.tsx @@ -0,0 +1,139 @@ +import * as React from "react" +import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog" + +import { cn } from "@/lib/utils" +import { buttonVariants } from "@/components/ui/button" + +const AlertDialog = AlertDialogPrimitive.Root + +const AlertDialogTrigger = AlertDialogPrimitive.Trigger + +const AlertDialogPortal = AlertDialogPrimitive.Portal + +const AlertDialogOverlay = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName + +const AlertDialogContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + + +)) +AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName + +const AlertDialogHeader = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +AlertDialogHeader.displayName = "AlertDialogHeader" + +const AlertDialogFooter = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +AlertDialogFooter.displayName = "AlertDialogFooter" + +const AlertDialogTitle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName + +const AlertDialogDescription = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AlertDialogDescription.displayName = + AlertDialogPrimitive.Description.displayName + +const AlertDialogAction = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName + +const AlertDialogCancel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName + +export { + AlertDialog, + AlertDialogPortal, + AlertDialogOverlay, + AlertDialogTrigger, + AlertDialogContent, + AlertDialogHeader, + AlertDialogFooter, + AlertDialogTitle, + AlertDialogDescription, + AlertDialogAction, + AlertDialogCancel, +} diff --git a/packages/manager/apps/pci-ai-notebooks/src/components/ui/alert.tsx b/packages/manager/apps/pci-ai-notebooks/src/components/ui/alert.tsx new file mode 100644 index 000000000000..924b130c73e3 --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/src/components/ui/alert.tsx @@ -0,0 +1,69 @@ +import * as React from "react" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" + +const alertVariants = cva( + "relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground", + { + variants: { + variant: { + default: "bg-background text-foreground", + destructive: + "border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive", + info: + "border-transparent bg-blue-100 text-blue-700 [&>svg]:text-blue-700", + success: + "border-transparent bg-green-100 text-green-700 [&>svg]:text-green-700", + warning: + "border-transparent bg-yellow-200 text-yellow-800 [&>svg]:text-green-800", + error: + "border-transparent bg-red-100 text-red-700 [&>svg]:text-red-700", + }, + }, + defaultVariants: { + variant: "default", + }, + } +) + +const Alert = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes & VariantProps +>(({ className, variant, ...props }, ref) => ( +
+)) +Alert.displayName = "Alert" + +const AlertTitle = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes +>(({ className, children, ...props }, ref) => ( +
+ {children} +
+)) +AlertTitle.displayName = "AlertTitle" + +const AlertDescription = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +AlertDescription.displayName = "AlertDescription" + +export { Alert, AlertTitle, AlertDescription } diff --git a/packages/manager/apps/pci-ai-notebooks/src/components/ui/badge.tsx b/packages/manager/apps/pci-ai-notebooks/src/components/ui/badge.tsx new file mode 100644 index 000000000000..c2ed15071965 --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/src/components/ui/badge.tsx @@ -0,0 +1,44 @@ +import * as React from "react" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" + +const badgeVariants = cva( + "inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2", + { + variants: { + variant: { + default: + "border-transparent bg-primary text-primary-foreground hover:bg-primary/80", + success: + "border-transparent bg-green-100 text-green-700 hover:bg-green-100/80", + info: + "border-transparent bg-blue-100 text-blue-700 hover:bg-blue-100/80", + warning: + "border-transparent bg-yellow-300 text-yellow-800 hover:bg-yellow-100/80", + error: + "border-transparent bg-red-100 text-red-700 hover:bg-red-100/80", + secondary: + "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80", + destructive: + "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80", + outline: "text-foreground", + }, + }, + defaultVariants: { + variant: "default", + }, + } +) + +export interface BadgeProps + extends React.HTMLAttributes, + VariantProps {} + +function Badge({ className, variant, ...props }: BadgeProps) { + return ( +
+ ) +} + +export { Badge, badgeVariants } diff --git a/packages/manager/apps/pci-ai-notebooks/src/components/ui/button.tsx b/packages/manager/apps/pci-ai-notebooks/src/components/ui/button.tsx new file mode 100644 index 000000000000..57f4a373a512 --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/src/components/ui/button.tsx @@ -0,0 +1,64 @@ +import * as React from "react" +import { Slot } from "@radix-ui/react-slot" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" + +const buttonVariants = cva( + "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", + { + variants: { + variant: { + default: "bg-primary text-primary-foreground hover:bg-primary-600", + destructive: + "bg-destructive text-destructive-foreground hover:bg-destructive/90", + outline: + "border text-primary border-primary border-2 bg-background font-semibold hover:bg-primary-100", + menu: + "border text-primary border-primary border-2 bg-background font-semibold hover:bg-primary-100 rounded-full", + secondary: + "bg-secondary text-secondary-foreground hover:bg-secondary/80", + ghost: "hover:bg-accent hover:text-accent-foreground", + table: "hover:bg-primary-100 hover:text-primary-700 hover:font-semibold", + link: "text-primary underline-offset-4 hover:underline", + input: "border border-input bg-background", + }, + size: { + default: "h-10 px-4 py-2 text-base", + sm: "h-9 rounded-md px-3 text-sm", + lg: "h-11 rounded-md px-8", + icon: "h-10 w-10", + link: "text-base", + table: "h-4 w-4 my-auto", + menu: 'size-8 p-0', + input: "h-10 w-full rounded-md px-3 py-2 text-sm" + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, + } +) + +export interface ButtonProps + extends React.ButtonHTMLAttributes, + VariantProps { + asChild?: boolean +} + +const Button = React.forwardRef( + ({ className, variant, size, asChild = false, ...props }, ref) => { + const Comp = asChild ? Slot : "button" + return ( + + ) + } +) +Button.displayName = "Button" + +export { Button, buttonVariants } diff --git a/packages/manager/apps/pci-ai-notebooks/src/components/ui/calendar.tsx b/packages/manager/apps/pci-ai-notebooks/src/components/ui/calendar.tsx new file mode 100644 index 000000000000..b065f8e0cd2b --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/src/components/ui/calendar.tsx @@ -0,0 +1,64 @@ +import * as React from "react" +import { ChevronLeft, ChevronRight } from "lucide-react" +import { DayPicker } from "react-day-picker" + +import { cn } from "@/lib/utils" +import { buttonVariants } from "@/components/ui/button" + +export type CalendarProps = React.ComponentProps + +function Calendar({ + className, + classNames, + showOutsideDays = true, + ...props +}: CalendarProps) { + return ( + , + IconRight: ({ ...props }) => , + }} + {...props} + /> + ) +} +Calendar.displayName = "Calendar" + +export { Calendar } diff --git a/packages/manager/apps/pci-ai-notebooks/src/components/ui/card.tsx b/packages/manager/apps/pci-ai-notebooks/src/components/ui/card.tsx new file mode 100644 index 000000000000..60b8cbe52fa1 --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/src/components/ui/card.tsx @@ -0,0 +1,79 @@ +import * as React from "react" + +import { cn } from "@/lib/utils" + +const Card = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +Card.displayName = "Card" + +const CardHeader = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +CardHeader.displayName = "CardHeader" + +const CardTitle = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes +>(({ className, children, ...props }, ref) => ( +

{children}

+)) +CardTitle.displayName = "CardTitle" + +const CardDescription = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +

+)) +CardDescription.displayName = "CardDescription" + +const CardContent = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +

+)) +CardContent.displayName = "CardContent" + +const CardFooter = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +CardFooter.displayName = "CardFooter" + +export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent } diff --git a/packages/manager/apps/pci-ai-notebooks/src/components/ui/collapsible.tsx b/packages/manager/apps/pci-ai-notebooks/src/components/ui/collapsible.tsx new file mode 100644 index 000000000000..a23e7a281287 --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/src/components/ui/collapsible.tsx @@ -0,0 +1,9 @@ +import * as CollapsiblePrimitive from "@radix-ui/react-collapsible" + +const Collapsible = CollapsiblePrimitive.Root + +const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger + +const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent + +export { Collapsible, CollapsibleTrigger, CollapsibleContent } diff --git a/packages/manager/apps/pci-ai-notebooks/src/components/ui/command.tsx b/packages/manager/apps/pci-ai-notebooks/src/components/ui/command.tsx new file mode 100644 index 000000000000..d4a5338a3d59 --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/src/components/ui/command.tsx @@ -0,0 +1,154 @@ +/* eslint-disable react/no-unknown-property */ +import * as React from "react" +import { type DialogProps } from "@radix-ui/react-dialog" +import { Command as CommandPrimitive } from "cmdk" +import { Search } from "lucide-react" + +import { cn } from "@/lib/utils" +import { Dialog, DialogContent } from "@/components/ui/dialog" + +const Command = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +Command.displayName = CommandPrimitive.displayName + +interface CommandDialogProps extends DialogProps {} + +const CommandDialog = ({ children, ...props }: CommandDialogProps) => { + return ( + + + + {children} + + + + ) +} + +const CommandInput = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( +
+ + +
+)) + +CommandInput.displayName = CommandPrimitive.Input.displayName + +const CommandList = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) + +CommandList.displayName = CommandPrimitive.List.displayName + +const CommandEmpty = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>((props, ref) => ( + +)) + +CommandEmpty.displayName = CommandPrimitive.Empty.displayName + +const CommandGroup = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) + +CommandGroup.displayName = CommandPrimitive.Group.displayName + +const CommandSeparator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +CommandSeparator.displayName = CommandPrimitive.Separator.displayName + +const CommandItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) + +CommandItem.displayName = CommandPrimitive.Item.displayName + +const CommandShortcut = ({ + className, + ...props +}: React.HTMLAttributes) => { + return ( + + ) +} +CommandShortcut.displayName = "CommandShortcut" + +export { + Command, + CommandDialog, + CommandInput, + CommandList, + CommandEmpty, + CommandGroup, + CommandItem, + CommandShortcut, + CommandSeparator, +} diff --git a/packages/manager/apps/pci-ai-notebooks/src/components/ui/data-table.tsx b/packages/manager/apps/pci-ai-notebooks/src/components/ui/data-table.tsx new file mode 100644 index 000000000000..a71a1c699516 --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/src/components/ui/data-table.tsx @@ -0,0 +1,262 @@ +import { useState } from 'react'; +import { ChevronDown, ChevronUp, ChevronsUpDown, ChevronLeft, ChevronRight, ChevronFirst, ChevronLast } from 'lucide-react'; +import { + ColumnDef, + SortingColumn, + SortingState, + flexRender, + Table as TanStackTable, + getCoreRowModel, + getPaginationRowModel, + getSortedRowModel, + useReactTable, +} from '@tanstack/react-table'; +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from '@/components/ui/table'; +import { Button } from '@/components/ui/button'; +import { Skeleton } from './skeleton'; +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from './select'; + +interface DataTablePaginationProps { + table: TanStackTable +} +export function DataTablePagination({ + table, +}: DataTablePaginationProps) { + return ( +
+
+
+ +
+
+ Page {table.getState().pagination.pageIndex + 1} of{" "} + {table.getPageCount()} +
+
+ + + + +
+
+
+ ); +} + +interface DataTableProps { + columns: ColumnDef[]; + data: TData[]; + pageSize?: number; +} + +export function DataTable({ + columns, + data, + pageSize, +}: DataTableProps) { + const [sorting, setSorting] = useState([]); + const table = useReactTable({ + data, + columns, + getCoreRowModel: getCoreRowModel(), + getPaginationRowModel: getPaginationRowModel(), + onSortingChange: setSorting, + getSortedRowModel: getSortedRowModel(), + state: { + sorting, + }, + initialState: { + pagination: { pageSize: pageSize ?? 5 }, + }, + }); + + return ( + <> +
+ + + {table.getHeaderGroups().map((headerGroup) => ( + + {headerGroup.headers.map((header) => { + return ( + + {header.isPlaceholder + ? null + : flexRender( + header.column.columnDef.header, + header.getContext(), + )} + + ); + })} + + ))} + + + {table.getRowModel().rows?.length ? ( + table.getRowModel().rows.map((row) => ( + + {row.getVisibleCells().map((cell) => ( + + {flexRender( + cell.column.columnDef.cell, + cell.getContext(), + )} + + ))} + + )) + ) : ( + + + No results. + + + )} + +
+
+ + + ); +} + +interface SortableHeaderProps { + column: SortingColumn; + children: React.ReactNode; +} +export function SortableHeader({ + column, + children, +}: SortableHeaderProps) { + const sort = column.getIsSorted(); + let icon = ; + if (sort === 'asc') { + icon = ; + } else if (sort === 'desc') { + icon = ; + } + + const buttonClass = `px-0 font-bold hover:bg-primary-100 ${ + sort + ? 'text-primary-500 hover:text-primary-500' + : 'text-primary-700 hover:text-primary-500' + }`; + return ( + + ); +} + +interface DataTableSkeletonProps { + columns?: number; + rows?: number; + height?: number; + width?: number; +} +DataTable.Skeleton = function DataTableSkeleton({ + columns = 5, + rows = 5, + height = 16, + width = 80, +}: DataTableSkeletonProps) { + return ( + + + + {Array.from({ length: columns }).map((colHead, iColHead) => ( + + + + ))} + + + + {Array.from({ length: rows }).map((row, iRow) => ( + + {Array.from({ length: columns }).map((col, iCol) => ( + + + + ))} + + ))} + +
+ ); +}; \ No newline at end of file diff --git a/packages/manager/apps/pci-ai-notebooks/src/components/ui/dialog.tsx b/packages/manager/apps/pci-ai-notebooks/src/components/ui/dialog.tsx new file mode 100644 index 000000000000..c23630eb8415 --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/src/components/ui/dialog.tsx @@ -0,0 +1,120 @@ +import * as React from "react" +import * as DialogPrimitive from "@radix-ui/react-dialog" +import { X } from "lucide-react" + +import { cn } from "@/lib/utils" + +const Dialog = DialogPrimitive.Root + +const DialogTrigger = DialogPrimitive.Trigger + +const DialogPortal = DialogPrimitive.Portal + +const DialogClose = DialogPrimitive.Close + +const DialogOverlay = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DialogOverlay.displayName = DialogPrimitive.Overlay.displayName + +const DialogContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + {children} + + + Close + + + +)) +DialogContent.displayName = DialogPrimitive.Content.displayName + +const DialogHeader = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +DialogHeader.displayName = "DialogHeader" + +const DialogFooter = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +DialogFooter.displayName = "DialogFooter" + +const DialogTitle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DialogTitle.displayName = DialogPrimitive.Title.displayName + +const DialogDescription = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DialogDescription.displayName = DialogPrimitive.Description.displayName + +export { + Dialog, + DialogPortal, + DialogOverlay, + DialogClose, + DialogTrigger, + DialogContent, + DialogHeader, + DialogFooter, + DialogTitle, + DialogDescription, +} diff --git a/packages/manager/apps/pci-ai-notebooks/src/components/ui/dropdown-menu.tsx b/packages/manager/apps/pci-ai-notebooks/src/components/ui/dropdown-menu.tsx new file mode 100644 index 000000000000..f3b4e7e4aad4 --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/src/components/ui/dropdown-menu.tsx @@ -0,0 +1,218 @@ +import * as React from "react" +import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu" +import { Check, ChevronRight, Circle } from "lucide-react" + +import { cn } from "@/lib/utils" +import { VariantProps, cva } from "class-variance-authority" + +const DropdownMenu = DropdownMenuPrimitive.Root + +const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger + +const DropdownMenuGroup = DropdownMenuPrimitive.Group + +const DropdownMenuPortal = DropdownMenuPrimitive.Portal + +const DropdownMenuSub = DropdownMenuPrimitive.Sub + +const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup + +const DropdownMenuSubTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, children, ...props }, ref) => ( + + {children} + + +)) +DropdownMenuSubTrigger.displayName = + DropdownMenuPrimitive.SubTrigger.displayName + +const DropdownMenuSubContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DropdownMenuSubContent.displayName = + DropdownMenuPrimitive.SubContent.displayName + +const DropdownMenuContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, sideOffset = 4, ...props }, ref) => ( + + + +)) +DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName + +const dropdownMenuItemVariant = cva( + "relative flex cursor-pointer select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors data-[disabled]:pointer-events-none data-[disabled]:opacity-50", + { + variants: { + variant: { + default: "focus:bg-accent focus:text-accent-foreground", + primary: "text-primary-500 focus:text-primary-500 focus:bg-primary-100 font-semibold", + destructive: + "text-red-500 focus:text-red-500 focus:bg-red-100 font-semibold", + }, + }, + defaultVariants: { + variant: "default", + }, + } +) +export interface DropdownMenuItemProps + extends React.ComponentPropsWithoutRef, + VariantProps { + inset?: boolean; + } + +const DropdownMenuItem = React.forwardRef< + React.ElementRef, + DropdownMenuItemProps +>(({ className, variant, inset, ...props }, ref) => ( +
+ +
+)) +DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName + +const DropdownMenuCheckboxItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, checked, ...props }, ref) => ( + + + + + + + {children} + +)) +DropdownMenuCheckboxItem.displayName = + DropdownMenuPrimitive.CheckboxItem.displayName + +const DropdownMenuRadioItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + + + + {children} + +)) +DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName + +const DropdownMenuLabel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, ...props }, ref) => ( + +)) +DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName + +const DropdownMenuSeparator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName + +const DropdownMenuShortcut = ({ + className, + ...props +}: React.HTMLAttributes) => { + return ( + + ) +} +DropdownMenuShortcut.displayName = "DropdownMenuShortcut" + +export { + DropdownMenu, + DropdownMenuTrigger, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuCheckboxItem, + DropdownMenuRadioItem, + DropdownMenuLabel, + DropdownMenuSeparator, + DropdownMenuShortcut, + DropdownMenuGroup, + DropdownMenuPortal, + DropdownMenuSub, + DropdownMenuSubContent, + DropdownMenuSubTrigger, + DropdownMenuRadioGroup, + dropdownMenuItemVariant, +} diff --git a/packages/manager/apps/pci-ai-notebooks/src/components/ui/form.tsx b/packages/manager/apps/pci-ai-notebooks/src/components/ui/form.tsx new file mode 100644 index 000000000000..4603f8b3d5ee --- /dev/null +++ b/packages/manager/apps/pci-ai-notebooks/src/components/ui/form.tsx @@ -0,0 +1,176 @@ +import * as React from "react" +import * as LabelPrimitive from "@radix-ui/react-label" +import { Slot } from "@radix-ui/react-slot" +import { + Controller, + ControllerProps, + FieldPath, + FieldValues, + FormProvider, + useFormContext, +} from "react-hook-form" + +import { cn } from "@/lib/utils" +import { Label } from "@/components/ui/label" + +const Form = FormProvider + +type FormFieldContextValue< + TFieldValues extends FieldValues = FieldValues, + TName extends FieldPath = FieldPath +> = { + name: TName +} + +const FormFieldContext = React.createContext( + {} as FormFieldContextValue +) + +const FormField = < + TFieldValues extends FieldValues = FieldValues, + TName extends FieldPath = FieldPath +>({ + ...props +}: ControllerProps) => { + return ( + + + + ) +} + +const useFormField = () => { + const fieldContext = React.useContext(FormFieldContext) + const itemContext = React.useContext(FormItemContext) + const { getFieldState, formState } = useFormContext() + + const fieldState = getFieldState(fieldContext.name, formState) + + if (!fieldContext) { + throw new Error("useFormField should be used within ") + } + + const { id } = itemContext + + return { + id, + name: fieldContext.name, + formItemId: `${id}-form-item`, + formDescriptionId: `${id}-form-item-description`, + formMessageId: `${id}-form-item-message`, + ...fieldState, + } +} + +type FormItemContextValue = { + id: string +} + +const FormItemContext = React.createContext( + {} as FormItemContextValue +) + +const FormItem = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => { + const id = React.useId() + + return ( + +
+ + ) +}) +FormItem.displayName = "FormItem" + +const FormLabel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => { + const { error, formItemId } = useFormField() + + return ( +