From 5f36c3823f5148e2419fe17ab5a9310db38f314c Mon Sep 17 00:00:00 2001 From: Yoann Fievez Date: Thu, 28 Nov 2024 16:00:07 +0100 Subject: [PATCH] feat(pci-object-storage): add import policy nodal ref: DTCORE-2879 Signed-off-by: Yoann Fievez --- .../apps/pci-object-storage/package.json | 1 + .../users/import-policy/Messages_de_DE.json | 9 ++ .../users/import-policy/Messages_en_GB.json | 9 ++ .../users/import-policy/Messages_es_ES.json | 9 ++ .../users/import-policy/Messages_fr_CA.json | 10 ++ .../users/import-policy/Messages_fr_FR.json | 10 ++ .../users/import-policy/Messages_it_IT.json | 9 ++ .../users/import-policy/Messages_pl_PL.json | 9 ++ .../users/import-policy/Messages_pt_PT.json | 9 ++ .../pci-object-storage/src/api/data/user.ts | 14 ++ .../src/api/hooks/{useUser.ts => useUser.tsx} | 62 ++++++++- .../src/components/Actions.component.tsx | 2 + .../src/components/FileInput.component.tsx | 122 ++++++++++++++++++ .../src/components/Label.component.spec.tsx | 37 ++++++ .../src/components/Label.component.tsx | 57 ++++++++ .../pci-object-storage/src/helpers/index.ts | 9 ++ .../objects/container/users/Listing.page.tsx | 11 +- .../users/import-policy/ImportPolicy.page.tsx | 106 +++++++++++++++ .../apps/pci-object-storage/src/routes.tsx | 8 ++ 19 files changed, 493 insertions(+), 10 deletions(-) create mode 100644 packages/manager/apps/pci-object-storage/public/translations/objects/users/import-policy/Messages_de_DE.json create mode 100644 packages/manager/apps/pci-object-storage/public/translations/objects/users/import-policy/Messages_en_GB.json create mode 100644 packages/manager/apps/pci-object-storage/public/translations/objects/users/import-policy/Messages_es_ES.json create mode 100644 packages/manager/apps/pci-object-storage/public/translations/objects/users/import-policy/Messages_fr_CA.json create mode 100644 packages/manager/apps/pci-object-storage/public/translations/objects/users/import-policy/Messages_fr_FR.json create mode 100644 packages/manager/apps/pci-object-storage/public/translations/objects/users/import-policy/Messages_it_IT.json create mode 100644 packages/manager/apps/pci-object-storage/public/translations/objects/users/import-policy/Messages_pl_PL.json create mode 100644 packages/manager/apps/pci-object-storage/public/translations/objects/users/import-policy/Messages_pt_PT.json rename packages/manager/apps/pci-object-storage/src/api/hooks/{useUser.ts => useUser.tsx} (66%) create mode 100644 packages/manager/apps/pci-object-storage/src/components/FileInput.component.tsx create mode 100644 packages/manager/apps/pci-object-storage/src/components/Label.component.spec.tsx create mode 100644 packages/manager/apps/pci-object-storage/src/components/Label.component.tsx create mode 100644 packages/manager/apps/pci-object-storage/src/pages/objects/container/users/import-policy/ImportPolicy.page.tsx diff --git a/packages/manager/apps/pci-object-storage/package.json b/packages/manager/apps/pci-object-storage/package.json index 84a3dd2925c0..35438ff2c752 100644 --- a/packages/manager/apps/pci-object-storage/package.json +++ b/packages/manager/apps/pci-object-storage/package.json @@ -31,6 +31,7 @@ "@tanstack/react-query": "^5.51.21", "@tanstack/react-table": "^8.20.1", "element-internals-polyfill": "^1.3.12", + "file-saver": "^2.0.5", "i18next": "^23.8.2", "i18next-http-backend": "^2.5.2", "react": "^18.2.0", diff --git a/packages/manager/apps/pci-object-storage/public/translations/objects/users/import-policy/Messages_de_DE.json b/packages/manager/apps/pci-object-storage/public/translations/objects/users/import-policy/Messages_de_DE.json new file mode 100644 index 000000000000..b76f7c91e32b --- /dev/null +++ b/packages/manager/apps/pci-object-storage/public/translations/objects/users/import-policy/Messages_de_DE.json @@ -0,0 +1,9 @@ +{ + "pci_projects_project_storages_containers_users_import_title": "Datei importieren", + "pci_projects_project_storages_containers_users_import_submit_label": "Importieren", + "pci_projects_project_storages_containers_users_import_add_files_label": "Dateien importieren", + "pci_projects_project_storages_containers_users_import_description": "Sie können eine JSON-Datei importieren und damit die Rechte des Nutzers verwalten.", + "pci_projects_project_storages_containers_users_import_success": "Die JSON-Datei für den Nutzer {{ username }} wurde vollständig importiert.", + "pci_projects_project_storages_containers_users_import_error": "Die JSON-Datei für den Nutzer {{ username }} wurde nicht korrekt importiert: {{ message }}", + "pci_projects_project_storages_containers_users_import_read_page_error": "Beim Download der Datei ist ein Fehler aufgetreten." +} diff --git a/packages/manager/apps/pci-object-storage/public/translations/objects/users/import-policy/Messages_en_GB.json b/packages/manager/apps/pci-object-storage/public/translations/objects/users/import-policy/Messages_en_GB.json new file mode 100644 index 000000000000..aecb37171db3 --- /dev/null +++ b/packages/manager/apps/pci-object-storage/public/translations/objects/users/import-policy/Messages_en_GB.json @@ -0,0 +1,9 @@ +{ + "pci_projects_project_storages_containers_users_import_title": "Import file", + "pci_projects_project_storages_containers_users_import_submit_label": "Import", + "pci_projects_project_storages_containers_users_import_add_files_label": "Import files", + "pci_projects_project_storages_containers_users_import_description": "You can import a JSON file to manage your user's rights.", + "pci_projects_project_storages_containers_users_import_success": "The JSON file linked to the user {{username}} has been imported.", + "pci_projects_project_storages_containers_users_import_error": "The JSON file linked to the user {{username}} was not imported correctly: {{message}}", + "pci_projects_project_storages_containers_users_import_read_page_error": "An error has occurred attempting to download the file." +} diff --git a/packages/manager/apps/pci-object-storage/public/translations/objects/users/import-policy/Messages_es_ES.json b/packages/manager/apps/pci-object-storage/public/translations/objects/users/import-policy/Messages_es_ES.json new file mode 100644 index 000000000000..712fa3be7767 --- /dev/null +++ b/packages/manager/apps/pci-object-storage/public/translations/objects/users/import-policy/Messages_es_ES.json @@ -0,0 +1,9 @@ +{ + "pci_projects_project_storages_containers_users_import_title": "Importar un archivo", + "pci_projects_project_storages_containers_users_import_submit_label": "Importar", + "pci_projects_project_storages_containers_users_import_add_files_label": "Importar archivos", + "pci_projects_project_storages_containers_users_import_description": "Puede importar un archivo JSON para administrar los permisos de su usuario.", + "pci_projects_project_storages_containers_users_import_success": "El archivo JSON asociado al usuario {{ username }} se ha importado correctamente.", + "pci_projects_project_storages_containers_users_import_error": "El archivo JSON asociado al usuario {{ username }} no se ha importado correctamente: {{ message }}", + "pci_projects_project_storages_containers_users_import_read_page_error": "Se ha producido un error al intentar descargar el archivo." +} diff --git a/packages/manager/apps/pci-object-storage/public/translations/objects/users/import-policy/Messages_fr_CA.json b/packages/manager/apps/pci-object-storage/public/translations/objects/users/import-policy/Messages_fr_CA.json new file mode 100644 index 000000000000..41d3ebebae71 --- /dev/null +++ b/packages/manager/apps/pci-object-storage/public/translations/objects/users/import-policy/Messages_fr_CA.json @@ -0,0 +1,10 @@ +{ + "pci_projects_project_storages_containers_users_import_title": "Importer un fichier", + "pci_projects_project_storages_containers_users_import_submit_label": "Importer", + "pci_projects_project_storages_containers_users_import_add_files_label": "Importer des fichiers", + "pci_projects_project_storages_containers_users_import_description": "Vous pouvez importer un fichier JSON pour gérer les droits de votre utilisateur.", + + "pci_projects_project_storages_containers_users_import_success": "Le fichier JSON lié à l’utilisateur {{ username }} a été importé avec succès.", + "pci_projects_project_storages_containers_users_import_error": "Le fichier JSON lié à l’utilisateur {{ username }} n’a pas été correctement importé : {{ message }}", + "pci_projects_project_storages_containers_users_import_read_page_error": "Une erreur s'est produite lors de la tentative de téléchargement du fichier." +} diff --git a/packages/manager/apps/pci-object-storage/public/translations/objects/users/import-policy/Messages_fr_FR.json b/packages/manager/apps/pci-object-storage/public/translations/objects/users/import-policy/Messages_fr_FR.json new file mode 100644 index 000000000000..41d3ebebae71 --- /dev/null +++ b/packages/manager/apps/pci-object-storage/public/translations/objects/users/import-policy/Messages_fr_FR.json @@ -0,0 +1,10 @@ +{ + "pci_projects_project_storages_containers_users_import_title": "Importer un fichier", + "pci_projects_project_storages_containers_users_import_submit_label": "Importer", + "pci_projects_project_storages_containers_users_import_add_files_label": "Importer des fichiers", + "pci_projects_project_storages_containers_users_import_description": "Vous pouvez importer un fichier JSON pour gérer les droits de votre utilisateur.", + + "pci_projects_project_storages_containers_users_import_success": "Le fichier JSON lié à l’utilisateur {{ username }} a été importé avec succès.", + "pci_projects_project_storages_containers_users_import_error": "Le fichier JSON lié à l’utilisateur {{ username }} n’a pas été correctement importé : {{ message }}", + "pci_projects_project_storages_containers_users_import_read_page_error": "Une erreur s'est produite lors de la tentative de téléchargement du fichier." +} diff --git a/packages/manager/apps/pci-object-storage/public/translations/objects/users/import-policy/Messages_it_IT.json b/packages/manager/apps/pci-object-storage/public/translations/objects/users/import-policy/Messages_it_IT.json new file mode 100644 index 000000000000..3c99abbe8467 --- /dev/null +++ b/packages/manager/apps/pci-object-storage/public/translations/objects/users/import-policy/Messages_it_IT.json @@ -0,0 +1,9 @@ +{ + "pci_projects_project_storages_containers_users_import_title": "Importa un file", + "pci_projects_project_storages_containers_users_import_submit_label": "Importa", + "pci_projects_project_storages_containers_users_import_add_files_label": "Importa file", + "pci_projects_project_storages_containers_users_import_description": "Puoi importare un file JSON per gestire i diritti di un utente.", + "pci_projects_project_storages_containers_users_import_success": "Il file JSON associato all'utente {{ username }} è stato importato correttamente.", + "pci_projects_project_storages_containers_users_import_error": "Il file JSON associato all'utente {{ username }} non è stato importato correttamente: {{ message }}", + "pci_projects_project_storages_containers_users_import_read_page_error": "Si è verificato un errore durante il tentativo di scaricare il file." +} diff --git a/packages/manager/apps/pci-object-storage/public/translations/objects/users/import-policy/Messages_pl_PL.json b/packages/manager/apps/pci-object-storage/public/translations/objects/users/import-policy/Messages_pl_PL.json new file mode 100644 index 000000000000..79c9df2949f1 --- /dev/null +++ b/packages/manager/apps/pci-object-storage/public/translations/objects/users/import-policy/Messages_pl_PL.json @@ -0,0 +1,9 @@ +{ + "pci_projects_project_storages_containers_users_import_title": "Zaimportuj plik", + "pci_projects_project_storages_containers_users_import_submit_label": "Importuj", + "pci_projects_project_storages_containers_users_import_add_files_label": "Importuj pliki", + "pci_projects_project_storages_containers_users_import_description": "Możesz zaimportować plik JSON, aby zarządzać uprawnieniami użytkownika.", + "pci_projects_project_storages_containers_users_import_success": "Plik JSON powiązany z użytkownikiem {{username}} został zaimportowany.", + "pci_projects_project_storages_containers_users_import_error": "Plik JSON powiązany z użytkownikiem {{username}} nie został poprawnie zaimportowany: {{message}}", + "pci_projects_project_storages_containers_users_import_read_page_error": "Wystąpił błąd podczas próby pobrania pliku." +} diff --git a/packages/manager/apps/pci-object-storage/public/translations/objects/users/import-policy/Messages_pt_PT.json b/packages/manager/apps/pci-object-storage/public/translations/objects/users/import-policy/Messages_pt_PT.json new file mode 100644 index 000000000000..a6db6ca5cb17 --- /dev/null +++ b/packages/manager/apps/pci-object-storage/public/translations/objects/users/import-policy/Messages_pt_PT.json @@ -0,0 +1,9 @@ +{ + "pci_projects_project_storages_containers_users_import_title": "Importar ficheiro", + "pci_projects_project_storages_containers_users_import_submit_label": "Importar", + "pci_projects_project_storages_containers_users_import_add_files_label": "Importar ficheiros", + "pci_projects_project_storages_containers_users_import_description": "Pode importar um ficheiro JSON para gerir os direitos do seu utilizador.", + "pci_projects_project_storages_containers_users_import_success": "O ficheiro JSON associado ao utilizador {{ username }} foi importado com êxito.", + "pci_projects_project_storages_containers_users_import_error": "O ficheiro JSON associado ao utilizador {{ username }} não foi corretamente importado: {{ message }}", + "pci_projects_project_storages_containers_users_import_read_page_error": "Ocorreu um erro durante a tentativa de carregamento do ficheiro." +} diff --git a/packages/manager/apps/pci-object-storage/src/api/data/user.ts b/packages/manager/apps/pci-object-storage/src/api/data/user.ts index a968d297ca8a..52dacd9c13dc 100644 --- a/packages/manager/apps/pci-object-storage/src/api/data/user.ts +++ b/packages/manager/apps/pci-object-storage/src/api/data/user.ts @@ -51,3 +51,17 @@ export const deleteUser = async ( `/cloud/project/${projectId}/user/${userId}/s3Credentials/${accessKey}`, ); }; + +export const importUserPolicy = async ( + projectId: string, + userId: string, + policy: string, +) => { + const { data } = await v6.post( + `/cloud/project/${projectId}/user/${userId}/policy`, + { + policy, + }, + ); + return data; +}; diff --git a/packages/manager/apps/pci-object-storage/src/api/hooks/useUser.ts b/packages/manager/apps/pci-object-storage/src/api/hooks/useUser.tsx similarity index 66% rename from packages/manager/apps/pci-object-storage/src/api/hooks/useUser.ts rename to packages/manager/apps/pci-object-storage/src/api/hooks/useUser.tsx index c5f3010d6612..35d73738def3 100644 --- a/packages/manager/apps/pci-object-storage/src/api/hooks/useUser.ts +++ b/packages/manager/apps/pci-object-storage/src/api/hooks/useUser.tsx @@ -1,12 +1,14 @@ import { useMutation, useQueries, useQuery } from '@tanstack/react-query'; import { ColumnSort, PaginationState } from '@ovh-ux/manager-react-components'; import { applyFilters, Filter } from '@ovh-ux/manager-core-api'; -import { useMemo } from 'react'; -import { paginateResults, sortResults } from '@/helpers'; +import { useMemo, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { isJson, paginateResults, sortResults } from '@/helpers'; import { deleteUser, getAllUsers, getS3Credentials, + importUserPolicy, TS3Credentials, TUser, } from '@/api/data/user'; @@ -105,3 +107,59 @@ export const useDeleteUser = ({ ...mutation, }; }; + +type ImportPolicyProps = { + projectId: string; + userId: string; + files: File[]; + onError: (cause: Error) => void; + onSuccess: () => void; +}; + +const readFileAsJSON = (file: File, t): Promise => { + return new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.onloadend = () => { + if (isJson(reader.result.toString())) { + resolve(reader.result.toString()); + } else { + reject( + new Error( + t( + 'pci_projects_project_storages_containers_users_import_read_page_error', + ), + ), + ); + } + }; + + reader.readAsText(file); + }); +}; + +export const useImportPolicy = ({ + projectId, + userId, + files, + onError, + onSuccess, +}: ImportPolicyProps) => { + const [isPending, setIsPending] = useState(false); + const { t } = useTranslation('objects/users/import-policy'); + const importPolicy = async () => { + try { + setIsPending(true); + const policy = await readFileAsJSON(files[0], t); + importUserPolicy(projectId, userId, policy); + onSuccess(); + } catch (e) { + onError(e as Error); + } finally { + setIsPending(false); + } + }; + return { + isPending, + importPolicy, + }; +}; diff --git a/packages/manager/apps/pci-object-storage/src/components/Actions.component.tsx b/packages/manager/apps/pci-object-storage/src/components/Actions.component.tsx index 439391ae9bfd..ad1ab0e7340d 100644 --- a/packages/manager/apps/pci-object-storage/src/components/Actions.component.tsx +++ b/packages/manager/apps/pci-object-storage/src/components/Actions.component.tsx @@ -16,10 +16,12 @@ export default function ActionsComponent({ ); const deleteHref = useHref(`./${user.id}/delete`); + const importHref = useHref(`./import-policy?userId=${user.id}`); const items = [ { id: 0, label: t('pci_projects_project_storages_containers_users_import_json'), + href: importHref, }, { id: 1, diff --git a/packages/manager/apps/pci-object-storage/src/components/FileInput.component.tsx b/packages/manager/apps/pci-object-storage/src/components/FileInput.component.tsx new file mode 100644 index 000000000000..36faebe2148f --- /dev/null +++ b/packages/manager/apps/pci-object-storage/src/components/FileInput.component.tsx @@ -0,0 +1,122 @@ +import { useBytes } from '@ovh-ux/manager-pci-common'; +import { + ODS_THEME_COLOR_INTENT, + ODS_THEME_SIZE, + ODS_THEME_TYPOGRAPHY_LEVEL, +} from '@ovhcloud/ods-common-theming'; +import { + ODS_BUTTON_SIZE, + ODS_BUTTON_VARIANT, + ODS_ICON_NAME, + ODS_ICON_SIZE, + ODS_TEXT_SIZE, +} from '@ovhcloud/ods-components'; +import { OsdsButton, OsdsIcon, OsdsText } from '@ovhcloud/ods-components/react'; +import { ChangeEvent, useRef, useState } from 'react'; +import { useTranslation } from 'react-i18next'; + +type FileInputComponentProps = { + onFilesSelected: (files: File[]) => void; +}; + +export default function FileInputComponent({ + onFilesSelected, +}: Readonly) { + const { t } = useTranslation('pci-common'); + const { formatBytes } = useBytes(); + const [selectedFiles, setSelectedFiles] = useState([]); + const fileInputRef = useRef(null); + + // Gérer la sélection des fichiers + const handleFileChange = (event: ChangeEvent) => { + const newFiles = Array.from(event.target.files); + + const updatedFiles = [...selectedFiles, ...newFiles]; + setSelectedFiles(updatedFiles); + onFilesSelected(updatedFiles); // Met à jour la liste des fichiers dans le parent + }; + + // Supprimer un fichier de la liste + const handleRemoveFile = (index: number) => { + const updatedFiles = selectedFiles.filter((_, i) => i !== index); + setSelectedFiles(updatedFiles); + onFilesSelected(updatedFiles); // Met à jour la liste des fichiers dans le parent + }; + + // Ouvrir la boîte de dialogue de fichiers + const handleOpenFileDialog = () => { + fileInputRef.current.click(); + }; + + return ( +
+ + + {t('common_file_filesSelector')} + + + + + {selectedFiles.length > 0 && ( +
+ + {t('common_file_attachmentsHeading')} + + {selectedFiles.map((file, index) => ( +
+
+ + + {file.name} ({formatBytes(file.size)}) + +
+ handleRemoveFile(index)} + variant={ODS_BUTTON_VARIANT.ghost} + size={ODS_BUTTON_SIZE.sm} + className="text-red-600 hover:text-red-800" + > + + +
+ ))} +
+ )} +
+ ); +} diff --git a/packages/manager/apps/pci-object-storage/src/components/Label.component.spec.tsx b/packages/manager/apps/pci-object-storage/src/components/Label.component.spec.tsx new file mode 100644 index 000000000000..c8cde8d8e6f0 --- /dev/null +++ b/packages/manager/apps/pci-object-storage/src/components/Label.component.spec.tsx @@ -0,0 +1,37 @@ +import { render } from '@testing-library/react'; +import { describe, it, expect } from 'vitest'; +import LabelComponent from './Label.component'; + +describe('LabelComponent', () => { + it('renders the label text', () => { + const { getByText } = render(); + expect(getByText('Test Label')).toBeInTheDocument(); + }); + + it('renders the help text when provided', () => { + const { getByText } = render( + , + ); + expect(getByText('Help Text')).toBeInTheDocument(); + }); + + it('does not render the help text when not provided', () => { + const { queryByText } = render(); + expect(queryByText('Help Text')).not.toBeInTheDocument(); + }); + + it('applies error color when hasError is true', () => { + const { getByText } = render(); + const label = getByText('Test Label'); + expect(label).toHaveAttribute('color', 'error'); + }); + + it('applies custom className when provided', () => { + const { getByText } = render( + , + ); + + const { parentElement } = getByText('Test Label'); + expect(parentElement).toHaveClass('custom-class'); + }); +}); diff --git a/packages/manager/apps/pci-object-storage/src/components/Label.component.tsx b/packages/manager/apps/pci-object-storage/src/components/Label.component.tsx new file mode 100644 index 000000000000..8e5c656aea53 --- /dev/null +++ b/packages/manager/apps/pci-object-storage/src/components/Label.component.tsx @@ -0,0 +1,57 @@ +import { + OsdsIcon, + OsdsPopover, + OsdsPopoverContent, + OsdsText, +} from '@ovhcloud/ods-components/react'; +import { ODS_THEME_COLOR_INTENT } from '@ovhcloud/ods-common-theming'; +import { + ODS_ICON_NAME, + ODS_ICON_SIZE, + ODS_TEXT_LEVEL, + ODS_TEXT_SIZE, +} from '@ovhcloud/ods-components'; + +type TLabelProps = { + text: string; + helpText?: string; + hasError?: boolean; + slot?: string; + className?: string; +}; + +export default function LabelComponent({ + text, + helpText, + hasError, + slot = 'label', + className = '', +}: Readonly): JSX.Element { + return ( +
+ + {text} + + + {!!helpText && ( + + + {helpText} + + )} +
+ ); +} diff --git a/packages/manager/apps/pci-object-storage/src/helpers/index.ts b/packages/manager/apps/pci-object-storage/src/helpers/index.ts index e85225741e2e..af1814fd2e20 100644 --- a/packages/manager/apps/pci-object-storage/src/helpers/index.ts +++ b/packages/manager/apps/pci-object-storage/src/helpers/index.ts @@ -41,3 +41,12 @@ export const sortResults = (items: T[], sorting: ColumnSort): T[] => { export const isSwiftType = (storage: TStorage) => !storage.archive && !storage.s3StorageType; + +export const isJson = (str: string) => { + try { + JSON.parse(str); + } catch (e) { + return false; + } + return true; +}; diff --git a/packages/manager/apps/pci-object-storage/src/pages/objects/container/users/Listing.page.tsx b/packages/manager/apps/pci-object-storage/src/pages/objects/container/users/Listing.page.tsx index 7a678864a0e7..7b38d147b7fc 100644 --- a/packages/manager/apps/pci-object-storage/src/pages/objects/container/users/Listing.page.tsx +++ b/packages/manager/apps/pci-object-storage/src/pages/objects/container/users/Listing.page.tsx @@ -3,7 +3,6 @@ import { FilterAdd, FilterList, Notifications, - RedirectionGuard, useColumnFilters, useDataGrid, useFeatureAvailability, @@ -55,7 +54,7 @@ export default function Listing() { const [searchQueries, setSearchQueries] = useState([]); const filterPopoverRef = useRef(undefined); - const { allUsers, paginatedUsers, isPending } = usePaginatedUsers( + const { paginatedUsers, isPending } = usePaginatedUsers( projectId, pagination, sorting, @@ -75,11 +74,7 @@ export default function Listing() { }; return ( - + <>
@@ -246,6 +241,6 @@ export default function Listing() { -
+ ); } diff --git a/packages/manager/apps/pci-object-storage/src/pages/objects/container/users/import-policy/ImportPolicy.page.tsx b/packages/manager/apps/pci-object-storage/src/pages/objects/container/users/import-policy/ImportPolicy.page.tsx new file mode 100644 index 000000000000..a1b1398f3dbc --- /dev/null +++ b/packages/manager/apps/pci-object-storage/src/pages/objects/container/users/import-policy/ImportPolicy.page.tsx @@ -0,0 +1,106 @@ +import { PciModal } from '@ovh-ux/manager-pci-common'; +import { useNotifications } from '@ovh-ux/manager-react-components'; +import { ODS_THEME_COLOR_INTENT } from '@ovhcloud/ods-common-theming'; +import { ODS_TEXT_LEVEL, ODS_TEXT_SIZE } from '@ovhcloud/ods-components'; +import { OsdsFormField, OsdsText } from '@ovhcloud/ods-components/react'; +import { Translation, useTranslation } from 'react-i18next'; +import { useNavigate, useParams, useSearchParams } from 'react-router-dom'; +import { useEffect, useState } from 'react'; +import { ApiError } from '@ovh-ux/manager-core-api'; +import LabelComponent from '@/components/Label.component'; +import FileInputComponent from '@/components/FileInput.component'; +import { useImportPolicy, useUsers } from '@/api/hooks/useUser'; +import { TUser } from '@/api/data/user'; + +export default function ImportPolicyPage() { + const { addSuccess, addError } = useNotifications(); + const { projectId } = useParams(); + const [searchParams] = useSearchParams(); + const userId = searchParams.get('userId'); + const [user, setUser] = useState(undefined); + const { data: listUsers, isPending: isPendingUsers } = useUsers(projectId); + const { t } = useTranslation('objects/users/import-policy'); + const [filesToUpload, setFilesToUpload] = useState([]); + const navigate = useNavigate(); + const onCancel = () => navigate(`..`); + const onClose = () => navigate(`..`); + + const { importPolicy, isPending: isPendingImport } = useImportPolicy({ + projectId, + userId, + files: filesToUpload, + onError(error: ApiError) { + addError( + + {(_t) => + _t('pci_projects_project_storages_containers_users_import_error', { + message: error?.response?.data?.message || error?.message || null, + username: 'username', + }) + } + , + true, + ); + onClose(); + }, + onSuccess() { + addSuccess( + + {(_t) => + _t( + 'pci_projects_project_storages_containers_users_import_success', + { + username: user.username, + }, + ) + } + , + true, + ); + navigate('..'); + }, + }); + + const onConfirm = () => { + importPolicy(); + navigate('..'); + }; + + useEffect(() => { + if (listUsers) { + setUser(listUsers.find((u) => `${u.id}` === userId)); + } + }, [listUsers]); + + const isPending = isPendingUsers || isPendingImport; + + return ( + + + {t('pci_projects_project_storages_containers_users_import_description')} + + + + + + + ); +} diff --git a/packages/manager/apps/pci-object-storage/src/routes.tsx b/packages/manager/apps/pci-object-storage/src/routes.tsx index 827ae5a1884d..6e7c25c94d4b 100644 --- a/packages/manager/apps/pci-object-storage/src/routes.tsx +++ b/packages/manager/apps/pci-object-storage/src/routes.tsx @@ -6,6 +6,7 @@ export const ROUTE_PATHS = { OBJECTS: '', USER_LIST: 'users', USER_DELETE: ':userId/delete', + USER_IMPORT_POLICY: 'import-policy', }; const LayoutPage = lazy(() => import('@/pages/Layout')); @@ -19,6 +20,9 @@ const UserListPage = lazy(() => const DeletePage = lazy(() => import('@/pages/objects/container/users/delete/Delete.page'), ); +const ImportPolicyPage = lazy(() => + import('@/pages/objects/container/users/import-policy/ImportPolicy.page'), +); const RoutesComponent = () => ( @@ -27,6 +31,10 @@ const RoutesComponent = () => ( +