From cdb7eb3da955fe23bd1a449b2e5e0636045b3842 Mon Sep 17 00:00:00 2001 From: bourquecharles Date: Wed, 1 Dec 2021 12:07:50 -0500 Subject: [PATCH] Version 2.5.10 --- package-lock.json | 20 +- package.json | 4 +- public/locales/de/translation.json | 16 ++ public/locales/en/translation.json | 16 ++ public/locales/es/translation.json | 16 ++ public/locales/fr/translation.json | 16 ++ public/locales/pt/translation.json | 16 ++ src/layout/index.js | 77 +++--- src/pages/ProfilePage/index.js | 387 +---------------------------- 9 files changed, 139 insertions(+), 429 deletions(-) diff --git a/package-lock.json b/package-lock.json index bcabb62..96d2080 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "ucentral-client", - "version": "2.5.9", + "version": "2.5.10", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "ucentral-client", - "version": "2.5.9", + "version": "2.5.10", "dependencies": { "@coreui/coreui": "^3.4.0", "@coreui/icons": "^2.0.1", @@ -32,7 +32,7 @@ "react-tooltip": "^4.2.21", "react-widgets": "^5.1.1", "sass": "^1.35.1", - "ucentral-libs": "^1.0.45", + "ucentral-libs": "^1.0.51", "uuid": "^8.3.2" }, "devDependencies": { @@ -15046,9 +15046,9 @@ } }, "node_modules/ucentral-libs": { - "version": "1.0.45", - "resolved": "https://registry.npmjs.org/ucentral-libs/-/ucentral-libs-1.0.45.tgz", - "integrity": "sha512-CLLU0u9pKe9PsbkFIRx0VXmOqERhcI3EUUSQhGgdLefu6VyPbkt2jgwjL4ou/KBx+LcW7EixSq3CLmj3WlPlLQ==", + "version": "1.0.51", + "resolved": "https://registry.npmjs.org/ucentral-libs/-/ucentral-libs-1.0.51.tgz", + "integrity": "sha512-VcWWThbkM0wx5MJ9zlQIohQVnwFHzTy5hvcGnY8J9uIqR3EScA2S6JHnUyPWwQ1qo6G0svgmmDUKeFLW06fZcw==", "dependencies": { "@coreui/coreui": "^3.4.0", "@coreui/icons": "^2.0.1", @@ -15058,6 +15058,7 @@ "libphonenumber-js": "^1.9.37", "lodash": "^4.17.21", "react-flow-renderer": "^9.6.6", + "react-i18next": "^11.11.0", "react-paginate": "^7.1.3", "react-phone-input-2": "^2.14.0", "react-router-dom": "^5.2.0", @@ -28137,9 +28138,9 @@ } }, "ucentral-libs": { - "version": "1.0.45", - "resolved": "https://registry.npmjs.org/ucentral-libs/-/ucentral-libs-1.0.45.tgz", - "integrity": "sha512-CLLU0u9pKe9PsbkFIRx0VXmOqERhcI3EUUSQhGgdLefu6VyPbkt2jgwjL4ou/KBx+LcW7EixSq3CLmj3WlPlLQ==", + "version": "1.0.51", + "resolved": "https://registry.npmjs.org/ucentral-libs/-/ucentral-libs-1.0.51.tgz", + "integrity": "sha512-VcWWThbkM0wx5MJ9zlQIohQVnwFHzTy5hvcGnY8J9uIqR3EScA2S6JHnUyPWwQ1qo6G0svgmmDUKeFLW06fZcw==", "requires": { "@coreui/coreui": "^3.4.0", "@coreui/icons": "^2.0.1", @@ -28149,6 +28150,7 @@ "libphonenumber-js": "^1.9.37", "lodash": "^4.17.21", "react-flow-renderer": "^9.6.6", + "react-i18next": "^11.11.0", "react-paginate": "^7.1.3", "react-phone-input-2": "^2.14.0", "react-router-dom": "^5.2.0", diff --git a/package.json b/package.json index 25506c6..a33cf3e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ucentral-client", - "version": "2.5.9", + "version": "2.5.10", "dependencies": { "@coreui/coreui": "^3.4.0", "@coreui/icons": "^2.0.1", @@ -26,7 +26,7 @@ "react-tooltip": "^4.2.21", "react-widgets": "^5.1.1", "sass": "^1.35.1", - "ucentral-libs": "^1.0.45", + "ucentral-libs": "^1.0.51", "uuid": "^8.3.2" }, "main": "index.js", diff --git a/public/locales/de/translation.json b/public/locales/de/translation.json index 6ed39ac..3331d6b 100644 --- a/public/locales/de/translation.json +++ b/public/locales/de/translation.json @@ -272,6 +272,7 @@ "contact": { "access_pin": "Zugangs-PIN", "add_contact": "Kontakt hinzufügen", + "contact": "Kontakt", "create_contact": "Kontakt erstellen", "currently_selected_contact": "Aktuell ausgewählter Kontakt: {{contact}}", "delete": "Kontakt löschen?", @@ -347,7 +348,9 @@ "currently_selected_venue": "Aktuell ausgewählter Veranstaltungsort: {{config}}", "delete_success": "Entität erfolgreich gelöscht", "delete_warning": "Achtung: Dieser Vorgang kann nicht rückgängig gemacht werden", + "duplicate_from_node": "Mit einem bestimmten Root-Knoten duplizieren", "duplicate_map": "Karte duplizieren", + "duplicate_with_node": "Dupliziere {{mapName}} mit {{rootName}} als Root-Knoten", "edit_failure": "Aktualisierung fehlgeschlagen : {{error}}", "enter_here": "Geben Sie hier die IP(s) ein, die Sie hinzufügen möchten", "entire_tree": "Netzwerkkarte", @@ -664,6 +667,19 @@ "uptime": "Betriebszeit", "used_total_memory": "{{used}} verwendet / {{total}} insgesamt" }, + "subscriber": { + "create": "Abonnenten erstellen", + "edit": "Abonnent bearbeiten", + "error_create": "Fehler beim Erstellen des Abonnenten: {{error}}", + "error_delete": "Fehler beim Löschen des Abonnenten: {{error}}", + "error_fetching": "Fehler beim Abrufen von Abonnenten: {{error}}", + "error_fetching_single": "Fehler beim Abrufen des Abonnenten: {{error}}", + "error_update": "Fehler beim Aktualisieren des Abonnenten: {{error}}", + "subscribers": "Abonnenten", + "success_create": "Abonnent erfolgreich erstellt!", + "success_delete": "Abonnent erfolgreich gelöscht!", + "success_update": "Abonnent erfolgreich aktualisiert!" + }, "system": { "error_fetching": "Fehler beim Abrufen von Systeminformationen", "error_reloading": "Fehler beim Neuladen: {{error}}", diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index 512c0a1..b7ee227 100644 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -272,6 +272,7 @@ "contact": { "access_pin": "Access PIN", "add_contact": "Add Contact", + "contact": "Contact", "create_contact": "Create Contact", "currently_selected_contact": "Currently Selected Contact: {{contact}}", "delete": "Delete Contact?", @@ -347,7 +348,9 @@ "currently_selected_venue": "Currently Selected Venue: {{config}}", "delete_success": "Entity Successfully Deleted", "delete_warning": "Warning: this operation cannot be reverted", + "duplicate_from_node": "Duplicate with specific Root Node", "duplicate_map": "Duplicate Map", + "duplicate_with_node": "Duplicate {{mapName}} with {{rootName}} as root node", "edit_failure": "Update unsuccessful : {{error}}", "enter_here": "Enter the IP(s) you'd like to add here", "entire_tree": "Network Map", @@ -664,6 +667,19 @@ "uptime": "Uptime", "used_total_memory": "{{used}} used / {{total}} total " }, + "subscriber": { + "create": "Create Subscriber", + "edit": "Edit Subscriber", + "error_create": "Error creating subscriber: {{error}}", + "error_delete": "Error deleting subscriber: {{error}}", + "error_fetching": "Error fetching subscribers: {{error}}", + "error_fetching_single": "Error fetching subscriber: {{error}}", + "error_update": "Error updating subscriber: {{error}}", + "subscribers": "Subscribers", + "success_create": "Subscriber successfully created!", + "success_delete": "Subscriber successfully deleted!", + "success_update": "Successfully updated subscriber!" + }, "system": { "error_fetching": "Error while fetching system information", "error_reloading": "Error while reloading: {{error}}", diff --git a/public/locales/es/translation.json b/public/locales/es/translation.json index e0a44ef..fda68cb 100644 --- a/public/locales/es/translation.json +++ b/public/locales/es/translation.json @@ -272,6 +272,7 @@ "contact": { "access_pin": "PIN de acceso", "add_contact": "Agregar contacto", + "contact": "Contacto", "create_contact": "Crear contacto", "currently_selected_contact": "Contacto seleccionado actualmente: {{contact}}", "delete": "¿Borrar contacto?", @@ -347,7 +348,9 @@ "currently_selected_venue": "Lugar seleccionado actualmente: {{config}}", "delete_success": "Entidad eliminada correctamente", "delete_warning": "Advertencia: esta operación no se puede revertir", + "duplicate_from_node": "Duplicar con un nodo raíz específico", "duplicate_map": "Mapa duplicado", + "duplicate_with_node": "Duplicar {{mapName}} con {{rootName}} como nodo raíz", "edit_failure": "Actualización fallida: {{error}}", "enter_here": "Ingrese las IP que desea agregar aquí", "entire_tree": "Mapa de red", @@ -664,6 +667,19 @@ "uptime": "Tiempo de actividad", "used_total_memory": "{{used}} usado / {{total}} total" }, + "subscriber": { + "create": "Crear suscriptor", + "edit": "Editar suscriptor", + "error_create": "Error al crear el suscriptor: {{error}}", + "error_delete": "Error al eliminar el suscriptor: {{error}}", + "error_fetching": "Error al obtener suscriptores: {{error}}", + "error_fetching_single": "Error al obtener el suscriptor: {{error}}", + "error_update": "Error al actualizar el suscriptor: {{error}}", + "subscribers": "Suscriptores", + "success_create": "¡Suscriptor creado correctamente!", + "success_delete": "¡Suscriptor eliminado correctamente!", + "success_update": "Suscriptor actualizado con éxito!" + }, "system": { "error_fetching": "Error al obtener información del sistema", "error_reloading": "Error al recargar: {{error}}", diff --git a/public/locales/fr/translation.json b/public/locales/fr/translation.json index c29f718..4628954 100644 --- a/public/locales/fr/translation.json +++ b/public/locales/fr/translation.json @@ -272,6 +272,7 @@ "contact": { "access_pin": "NIP d'accès", "add_contact": "Ajouter le contact", + "contact": "Contact", "create_contact": "Créer un contact", "currently_selected_contact": "Contact actuellement sélectionné : {{contact}}", "delete": "Effacer le contact?", @@ -347,7 +348,9 @@ "currently_selected_venue": "Lieu actuellement sélectionné : {{config}}", "delete_success": "Entité supprimée avec succès", "delete_warning": "Attention : cette opération ne peut pas être annulée", + "duplicate_from_node": "Dupliquer avec un nœud racine spécifique", "duplicate_map": "Carte en double", + "duplicate_with_node": "Dupliquer {{mapName}} avec {{rootName}} comme nœud racine", "edit_failure": "Échec de la mise à jour : {{error}}", "enter_here": "Entrez les IP que vous souhaitez ajouter ici", "entire_tree": "Carte du réseau", @@ -664,6 +667,19 @@ "uptime": "La disponibilité", "used_total_memory": "{{used}} utilisé / {{total}} total" }, + "subscriber": { + "create": "Créer un abonné", + "edit": "Modifier l'abonné", + "error_create": "Erreur lors de la création de l'abonné : {{error}}", + "error_delete": "Erreur lors de la suppression de l'abonné : {{error}}", + "error_fetching": "Erreur lors de la récupération des abonnés : {{error}}", + "error_fetching_single": "Erreur lors de la récupération de l'abonné : {{error}}", + "error_update": "Erreur lors de la mise à jour de l'abonné : {{error}}", + "subscribers": "Les abonnés", + "success_create": "Abonné créé avec succès !", + "success_delete": "Abonné supprimé avec succès !", + "success_update": "Abonné mis à jour avec succès !" + }, "system": { "error_fetching": "Erreur lors de la récupération des informations système", "error_reloading": "Erreur lors du rechargement : {{error}}", diff --git a/public/locales/pt/translation.json b/public/locales/pt/translation.json index f80b501..ea4b411 100644 --- a/public/locales/pt/translation.json +++ b/public/locales/pt/translation.json @@ -272,6 +272,7 @@ "contact": { "access_pin": "PIN de acesso", "add_contact": "Adicionar contato", + "contact": "Contato", "create_contact": "Criar Contato", "currently_selected_contact": "Contato atualmente selecionado: {{contact}}", "delete": "Excluir contato?", @@ -347,7 +348,9 @@ "currently_selected_venue": "Local selecionado atualmente: {{config}}", "delete_success": "Entidade excluída com sucesso", "delete_warning": "Aviso: esta operação não pode ser revertida", + "duplicate_from_node": "Duplicar com nó raiz específico", "duplicate_map": "Mapa duplicado", + "duplicate_with_node": "Duplicar {{mapName}} com {{rootName}} como nó raiz", "edit_failure": "Atualização malsucedida: {{error}}", "enter_here": "Digite o (s) IP (s) que deseja adicionar aqui", "entire_tree": "Mapa de Rede", @@ -664,6 +667,19 @@ "uptime": "Tempo de atividade", "used_total_memory": "{{used}} usado / {{total}} total" }, + "subscriber": { + "create": "Criar assinante", + "edit": "Editar Assinante", + "error_create": "Erro ao criar assinante: {{error}}", + "error_delete": "Erro ao excluir assinante: {{error}}", + "error_fetching": "Erro ao buscar assinantes: {{error}}", + "error_fetching_single": "Erro ao buscar assinante: {{error}}", + "error_update": "Erro ao atualizar assinante: {{error}}", + "subscribers": "Inscritos", + "success_create": "Assinante criado com sucesso!", + "success_delete": "Assinante excluído com sucesso!", + "success_update": "Assinante atualizado com sucesso!" + }, "system": { "error_fetching": "Erro ao buscar informações do sistema", "error_reloading": "Erro ao recarregar: {{error}}", diff --git a/src/layout/index.js b/src/layout/index.js index cf264e6..ebacecb 100644 --- a/src/layout/index.js +++ b/src/layout/index.js @@ -1,6 +1,9 @@ import React, { useState } from 'react'; import { useTranslation } from 'react-i18next'; import routes from 'routes'; +import { CSidebarNavItem } from '@coreui/react'; +import { cilBarcode, cilRouter, cilSave, cilSettings, cilPeople } from '@coreui/icons'; +import CIcon from '@coreui/icons-react'; import { Header, Sidebar, Footer, PageContainer, ToastProvider, useAuth } from 'ucentral-libs'; const TheLayout = () => { @@ -8,46 +11,52 @@ const TheLayout = () => { const { endpoints, currentToken, user, avatar, logout } = useAuth(); const { t, i18n } = useTranslation(); - const navigation = [ - { - _tag: 'CSidebarNavItem', - name: t('common.devices'), - icon: 'cilRouter', - to: '/devices', - }, - { - _tag: 'CSidebarNavItem', - name: t('firmware.title'), - icon: 'cilSave', - to: '/firmware', - }, - { - _tag: 'CSidebarNavItem', - name: t('configuration.default_configs'), - icon: 'cilBarcode', - to: '/defaultconfigurations', - }, - { - _tag: 'CSidebarNavItem', - name: t('user.users'), - to: '/users', - icon: 'cilPeople', - }, - { - _tag: 'CSidebarNavItem', - name: t('common.system'), - to: '/system', - icon: 'cilSettings', - }, - ]; - return (
+ } + /> + } + /> + } + /> + } + /> + } + /> + } + /> + + } redirectTo="/devices" />
diff --git a/src/pages/ProfilePage/index.js b/src/pages/ProfilePage/index.js index 6c89a97..d2ceff1 100644 --- a/src/pages/ProfilePage/index.js +++ b/src/pages/ProfilePage/index.js @@ -1,392 +1,11 @@ -import React, { useState, useEffect } from 'react'; +import React from 'react'; import { useTranslation } from 'react-i18next'; -import { CCard, CCardBody, CCardHeader, CButton, CPopover, CButtonToolbar } from '@coreui/react'; -import { cilPencil, cilSave, cilSync, cilX } from '@coreui/icons'; -import CIcon from '@coreui/icons-react'; import axiosInstance from 'utils/axiosInstance'; -import { testRegex } from 'utils/helper'; -import { useUser, EditMyProfile, useAuth, useToast } from 'ucentral-libs'; - -const initialState = { - Id: { - value: '', - error: false, - editable: false, - }, - newPassword: { - value: '', - error: false, - editable: true, - ignore: true, - }, - confirmNewPassword: { - value: '', - error: false, - editable: true, - ignore: true, - }, - email: { - value: '', - error: false, - editable: false, - }, - description: { - value: '', - error: false, - editable: true, - }, - name: { - value: '', - error: false, - editable: true, - }, - notes: { - value: [], - editable: false, - }, - userTypeProprietaryInfo: { - value: {}, - error: false, - }, - mfaMethod: { - value: '', - error: false, - }, -}; +import { ProfilePage as Page } from 'ucentral-libs'; const ProfilePage = () => { const { t } = useTranslation(); - const { currentToken, endpoints, user, getAvatar, avatar } = useAuth(); - const { addToast } = useToast(); - const [editing, setEditing] = useState(false); - const [loading, setLoading] = useState(false); - const [userForm, updateWithId, updateWithKey, setUser] = useUser(initialState); - const [newAvatar, setNewAvatar] = useState(''); - const [newAvatarFile, setNewAvatarFile] = useState(null); - const [avatarDeleted, setAvatarDeleted] = useState(false); - const [fileInputKey, setFileInputKey] = useState(0); - const [policies, setPolicies] = useState({ - passwordPolicy: '', - passwordPattern: '', - accessPolicy: '', - }); - - const getPasswordPolicy = () => { - axiosInstance - .post(`${endpoints.owsec}/api/v1/oauth2?requirements=true`, {}) - .then((response) => { - const newPolicies = response.data; - newPolicies.accessPolicy = `${endpoints.owsec}${newPolicies.accessPolicy}`; - newPolicies.passwordPolicy = `${endpoints.owsec}${newPolicies.passwordPolicy}`; - setPolicies(response.data); - }) - .catch(() => {}); - }; - - const getUser = () => { - const options = { - headers: { - Accept: 'application/json', - Authorization: `Bearer ${currentToken}`, - }, - }; - - axiosInstance - .get(`${endpoints.owsec}/api/v1/user/${user.Id}`, options) - .then((response) => { - const newUser = {}; - - for (const key of Object.keys(response.data)) { - if (key in initialState && key !== 'currentPassword') { - newUser[key] = { - ...initialState[key], - value: response.data[key], - }; - } - } - - newUser.mfaMethod = { - value: response.data.userTypeProprietaryInfo.mfa.enabled - ? response.data.userTypeProprietaryInfo.mfa.method - : '', - error: false, - }; - - setUser({ ...initialState, ...newUser }); - }) - .catch((e) => { - addToast({ - title: t('common.error'), - body: t('user.error_fetching_users', { error: e }), - color: 'danger', - autohide: true, - }); - }); - }; - - const uploadAvatar = () => { - const options = { - headers: { - Accept: 'application/json', - Authorization: `Bearer ${currentToken}`, - }, - }; - - const data = new FormData(); - data.append('file', newAvatarFile); - - axiosInstance - .post(`${endpoints.owsec}/api/v1/avatar/${user.Id}`, data, options) - .then(() => { - addToast({ - title: t('user.update_success_title'), - body: t('user.update_success'), - color: 'success', - autohide: true, - }); - getAvatar(); - setNewAvatar(''); - setNewAvatarFile(null); - setFileInputKey(fileInputKey + 1); - }) - .catch(() => { - addToast({ - title: t('user.update_failure_title'), - body: t('user.update_failure'), - color: 'danger', - autohide: true, - }); - }); - }; - - const updateUser = () => { - setLoading(true); - - if (newAvatar !== '' && newAvatarFile !== null) { - uploadAvatar(); - } else if (avatarDeleted) { - const options = { - headers: { - Accept: 'application/json', - Authorization: `Bearer ${currentToken}`, - }, - }; - - axiosInstance - .delete(`${endpoints.owsec}/api/v1/avatar/${user.Id}`, options) - .then(() => { - getAvatar(); - }) - .catch(() => {}); - } - - if ( - userForm.newPassword.value !== '' && - (!testRegex(userForm.newPassword.value, policies.passwordPattern) || - userForm.newPassword.value !== userForm.confirmNewPassword.value) - ) { - updateWithKey('newPassword', { - error: true, - }); - setLoading(false); - } else { - const newNotes = []; - - for (let i = 0; i < userForm.notes.value.length; i += 1) { - if (userForm.notes.value[i].new) newNotes.push({ note: userForm.notes.value[i].note }); - } - - const propInfo = { ...userForm.userTypeProprietaryInfo.value }; - propInfo.mfa.method = userForm.mfaMethod.value === '' ? undefined : userForm.mfaMethod.value; - propInfo.mfa.enabled = userForm.mfaMethod.value !== ''; - - const parameters = { - id: user.Id, - description: userForm.description.value, - name: userForm.name.value, - notes: newNotes, - userTypeProprietaryInfo: propInfo, - currentPassword: userForm.newPassword.value !== '' ? userForm.newPassword.value : undefined, - }; - - const options = { - headers: { - Accept: 'application/json', - Authorization: `Bearer ${currentToken}`, - }, - }; - - axiosInstance - .put(`${endpoints.owsec}/api/v1/user/${user.Id}`, parameters, options) - .then(() => { - addToast({ - title: t('user.update_success_title'), - body: t('user.update_success'), - color: 'success', - autohide: true, - }); - // eslint-disable-next-line no-use-before-define - toggleEditing(); - }) - .catch((e) => { - addToast({ - title: t('user.update_failure_title'), - body: t('user.update_failure', { error: e.response?.data?.ErrorDescription }), - color: 'danger', - autohide: true, - }); - }) - .finally(() => { - getUser(); - setLoading(false); - }); - } - }; - - const addNote = (currentNote) => { - const newNotes = [...userForm.notes.value]; - newNotes.unshift({ - note: currentNote, - new: true, - created: new Date().getTime() / 1000, - createdBy: '', - }); - updateWithKey('notes', { value: newNotes }); - }; - - const showPreview = (e) => { - setAvatarDeleted(false); - const imageFile = e.target.files[0]; - setNewAvatar(URL.createObjectURL(imageFile)); - setNewAvatarFile(imageFile); - }; - - const deleteAvatar = () => { - setNewAvatar(''); - setAvatarDeleted(true); - }; - - const sendPhoneNumberTest = async (phoneNumber) => { - const options = { - headers: { - Accept: 'application/json', - Authorization: `Bearer ${currentToken}`, - }, - }; - - return axiosInstance - .post(`${endpoints.owsec}/api/v1/sms?validateNumber=true`, { to: phoneNumber }, options) - .then(() => true) - .catch(() => { - addToast({ - title: t('common.error'), - body: t('user.error_sending_code'), - color: 'danger', - autohide: true, - }); - return false; - }); - }; - - const testVerificationCode = async (phoneNumber, code) => { - const options = { - headers: { - Accept: 'application/json', - Authorization: `Bearer ${currentToken}`, - }, - }; - - return axiosInstance - .post( - `${endpoints.owsec}/api/v1/sms?completeValidation=true&validationCode=${code}`, - { to: phoneNumber }, - options, - ) - .then(() => true) - .catch(() => { - addToast({ - title: t('common.error'), - body: t('user.wrong_validation_code'), - color: 'danger', - autohide: true, - }); - return false; - }); - }; - - const toggleEditing = () => { - if (editing) { - setAvatarDeleted(false); - setNewAvatar(''); - getUser(); - getAvatar(); - } - setEditing(!editing); - }; - - useEffect(() => { - if (user.Id) { - getAvatar(); - getUser(); - } - if (policies.passwordPattern.length === 0) { - getPasswordPolicy(); - } - }, [user.Id]); - - return ( - - -
- {t('user.my_profile')} -
-
- - - - - - - - - - - - - - - - - - - - - - -
-
- - - -
- ); + return ; }; export default ProfilePage;