Translation support completed

This commit is contained in:
Colin Dawson 2026-01-31 19:32:45 +00:00
parent 83cf83b6fc
commit 6181fe48aa
62 changed files with 589 additions and 898 deletions

47
Translate-Locale.ps1 Normal file
View File

@ -0,0 +1,47 @@
#You will need Microsoft Copilot CLI installed to run this script use this to install the command line tool:
# winget install Microsoft.Copilot
# pwsh ./Translate-Locale.ps1 `
# -SourceFile "./public/locales/en-GB/common.json" `
# -TargetLocale "fr-FR" `
# -OutputFile "./public/locales/fr-FR/common.json"
# pwsh ./Translate-Locale.ps1 `
# -SourceFile "./public/locales/en-GB/common.json" `
# -TargetLocale "en-US" `
# -OutputFile "./public/locales/en-US/common.json"
# pwsh ./Translate-Locale.ps1 `
# -SourceFile "./public/locales/en-GB/common.json" `
# -TargetLocale "fr-CA" `
# -OutputFile "./public/locales/fr-CA/common.json"
param(
[Parameter(Mandatory=$true)]
[string]$SourceFile, # en-GB.json
[Parameter(Mandatory=$true)]
[string]$TargetLocale, # fr-FR, fr-CA, en-US, etc.
[Parameter(Mandatory=$true)]
[string]$OutputFile # output JSON file
)
# Load the source JSON
$sourceJson = Get-Content $SourceFile -Raw
# Build the translation prompt
$prompt = @"
Translate the following JSON values into $TargetLocale.
Keep the keys exactly the same.
Return valid JSON only.
$sourceJson
"@
# Call Copilot CLI
$translated = copilot $prompt
# Save the result
$translated | Out-File $OutputFile -Encoding UTF8
Write-Host "Generated $TargetLocale translation: $OutputFile"

View File

@ -1,4 +1,10 @@
{ {
"AuthorizationEndpoint": "Authorization Endpoint",
"ConfirmEmailResent": "Confirmation email resent", "ConfirmEmailResent": "Confirmation email resent",
"OccuredAt": "Occurred At" "OccuredAt": "Occurred At",
"Organisation": "Organization",
"OrganisationEdited": "Organization edited",
"Mail": "Email",
"MailTemplates": "Email Templates",
"LoggingOut": "Signing out"
} }

View File

@ -1,5 +1,6 @@
{ {
"Activate": "Activate", "Activate": "Activate",
"Active": "Active",
"Add": "Add", "Add": "Add",
"AddDomain": "Add Domain", "AddDomain": "Add Domain",
"Address": "Address", "Address": "Address",
@ -10,92 +11,185 @@
"AnErrorOccurred": "An error occurred", "AnErrorOccurred": "An error occurred",
"Application": "Application", "Application": "Application",
"Applications": "Applications", "Applications": "Applications",
"AuthorizationEndpoint": "Authorisation Endpoint",
"AuditLog": "Audit Logs", "AuditLog": "Audit Logs",
"AuditLogs": "Audit Logs", "AuditLogs": "Audit Logs",
"Authenticate": "Authenticate",
"AuthenticationCode": "Authentication code",
"BlockedIPAddresses": "Blocked IP addresses", "BlockedIPAddresses": "Blocked IP addresses",
"BlockedIPs": "Blocked IPs", "BlockedIPs": "Blocked IPs",
"Blocked": "Blocked",
"Cancel": "Cancel", "Cancel": "Cancel",
"Changes": "Changes", "Changes": "Changes",
"ClientDomainManager": "Client Domain Manager", "ClientDomainManager": "Client Domain Manager",
"ClientDomains": "Client Domains", "ClientDomains": "Client Domains",
"Close": "Close", "Close": "Close",
"ClientId": "Client Id",
"ClientSecret": "Client Secret",
"Comment": "Comment", "Comment": "Comment",
"Confirm": "Confirm", "Confirm": "Confirm",
"ConfirmEmailResent": "Confirm e-mail resent", "ConfirmEmailResent": "Confirm e-mail resent",
"ConfirmPassword": "Confirm Password", "ConfirmPassword": "Confirm Password",
"Continuous": "Continuous",
"Created": "Created", "Created": "Created",
"CustomField": "Custom Field",
"CustomFieldEdited": "Custom Field edited",
"CustomFieldForChildEntries": "Custom field for child entries",
"CustomFieldManager": "Custom Field Manager", "CustomFieldManager": "Custom Field Manager",
"CustomFields": "Custom Fields", "CustomFields": "Custom Fields",
"Day": "Day",
"DefaultValue": "Default Value",
"DefaultMustBeGreaterThanOrEqualToMinimumValue": "\"Default Value\" must be greater than or equal to \"Minimum Value\"",
"DefaultMustBeLessThanOrEqualToMaximumValue": "\"Default Value\" must be less than or equal to \"Maximum Value\"",
"Definition": "Definition",
"DisableAuthenticator": "Disable Authenticator", "DisableAuthenticator": "Disable Authenticator",
"DisplayName": "Display Name", "DisplayName": "Display Name",
"Domain": "Domain", "Domain": "Domain",
"DomainEdited": "Domain edited",
"Disabled": "Disabled",
"Enabled": "Enabled",
"e-print": "e-print", "e-print": "e-print",
"e-suite": "e-suite", "e-suite": "e-suite",
"e-suiteLogo": "e-suite logo", "e-suiteLogo": "e-suite logo",
"Edit": "Edit", "Edit": "Edit",
"EditDomain": "Edit Domain", "EditDomain": "Edit Domain",
"EditUser": "Edit User", "EditUser": "Edit User",
"EFlowAppId": "e-flow AppId",
"EFlowCategoryId": "e-flow CategoryId",
"EFlowHostname": "e-flow hostname",
"Email": "Email", "Email": "Email",
"EmailTemplateSaved": "Email Template saved",
"EntityDisplayName": "Entity Display Name", "EntityDisplayName": "Entity Display Name",
"ErrorLogs": "Error Logs", "ErrorLogs": "Error Logs",
"ExceptionJson": "Exception JSON", "ExceptionJson": "Exception JSON",
"ExceptionLogs": "Exception Logs", "ExceptionLogs": "Exception Logs",
"FailedToDisableAuthenticator": "Failed to disable authenticator:", "FailedToDisableAuthenticator": "Failed to disable authenticator:",
"Field": "Field",
"FailedToSaveFormInstance": "Failed to save form instance",
"FieldType": "Field Type", "FieldType": "Field Type",
"ForgottenPassword": "Forgotten Password",
"FirstName": "First name",
"Form": "Form",
"Forms": "Forms", "Forms": "Forms",
"FormTemplate": "Form Template",
"FormTemplateEdited": "Form template edited",
"FormTemplateManager": "Form Template Manager", "FormTemplateManager": "Form Template Manager",
"General": "General", "General": "General",
"Glossaries": "Glossaries", "Glossaries": "Glossaries",
"Glossary": "Glossary",
"GlossaryItem": "Glossary Item",
"GlossaryItemEdited": "Glossary Item edited",
"GlossaryManager": "Glossary Manager", "GlossaryManager": "Glossary Manager",
"Group": "Group", "Group": "Group",
"Home": "Home", "Home": "Home",
"Id": "Id", "Id": "Id",
"Increment": "Increment",
"IsPublic": "Is Public",
"IPAddress": "IP Address", "IPAddress": "IP Address",
"IPAddressUnblocked": "IP Address '{{ip}}' unblocked.", "IPAddressUnblocked": "IP Address '{{ip}}' unblocked.",
"Items": "Items", "Items": "Items",
"LastUpdated": "Last Updated", "LastUpdated": "Last Updated",
"Loading": "Loading", "Loading": "Loading",
"LoggingOut": "Logging out", "LoggingOut": "Logging out",
"LastName": "Last name",
"Mail": "Mail",
"MailTemplates": "Mail Templates", "MailTemplates": "Mail Templates",
"MaxEntriesEmptyUnlimited": "Max Entries (empty=unlimited)",
"MaximumValue": "Maximum Value",
"Message": "Message", "Message": "Message",
"MinEntries": "Min Entries",
"MinimumValue": "Minimum Value",
"MiddleNames": "Middle names",
"Month": "Month",
"MultiLine": "Multi-line",
"Name": "Name", "Name": "Name",
"NewCustomFieldAdded": "New Custom Field added",
"NewDomainAdded": "New Domain added",
"NewFormTemplateAdded": "New Form Template added",
"NewGlossaryItemAdded": "New Glossary Item added",
"NewOrganisationAdded": "New Organisation added",
"NewPassword": "New Password", "NewPassword": "New Password",
"NewRoleAdded": "New Role added",
"NewSequenceAdded": "New sequence added",
"NewSpecificationsAdded": "New Specifications added",
"NewSiteAdded": "New site added",
"NewSsoProviderAdded": "New Sso Provider added",
"NewUserAdded": "New User added",
"NewValue": "New Value", "NewValue": "New Value",
"NotFound": "Not found", "NotFound": "Not found",
"Number": "Number",
"NumberOfAttempts": "Number Of Attempts", "NumberOfAttempts": "Number Of Attempts",
"OccuredAt": "Occured At", "OccuredAt": "Occured At",
"OldValue": "Old Value", "OldValue": "Old Value",
"Organisation": "Organisation",
"OrganisationEdited": "Organisation edited",
"Password": "Password", "Password": "Password",
"PasswordIsRequired": "Password is required", "PasswordIsRequired": "Password is required",
"PasswordMinLength": "Password must be at least {{minPasswordLength}} characters", "PasswordMinLength": "Password must be at least {{minPasswordLength}} characters",
"PasswordsMustMatch": "You need to confirm by typing exactly the same as the new password", "PasswordsMustMatch": "You need to confirm by typing exactly the same as the new password",
"Pattern": "Pattern",
"Pending": "Pending",
"PressAgainToDelete": "Press again to delete", "PressAgainToDelete": "Press again to delete",
"PressAgainToUnblock": "Press again to unblock", "PressAgainToUnblock": "Press again to unblock",
"PrintSpecification": "Print Specification",
"Profile": "Profile",
"ResendConfirm": "Resend Confirm", "ResendConfirm": "Resend Confirm",
"Required": "Required",
"ResetPassword": "Reset Password", "ResetPassword": "Reset Password",
"RolloverType": "Rollover Type",
"Role": "Role",
"RoleAccess": "Role Access", "RoleAccess": "Role Access",
"RoleAccessUpdated": "Role access updated successfully.", "RoleAccessUpdated": "Role access updated successfully.",
"RoleEdited": "Role edited",
"Save": "Save", "Save": "Save",
"SaveAndClose": "Save and close",
"SecurityRoles": "Security Roles", "SecurityRoles": "Security Roles",
"Seed": "Seed",
"Sequence": "Sequence", "Sequence": "Sequence",
"SequenceEdited": "Sequence edited",
"SequenceFormGlossary": "Sequence/Form/Glossary",
"SequenceManager": "Sequence Manager", "SequenceManager": "Sequence Manager",
"ShowJSON": "Show JSON", "ShowJSON": "Show JSON",
"ShowStackTrace": "Show stack trace", "ShowStackTrace": "Show stack trace",
"SigmaId": "Sigma Id",
"Site": "Site",
"SiteEdited": "Site edited",
"SiteManager": "Site Manager", "SiteManager": "Site Manager",
"SpecificationManager": "Specification Manager", "SpecificationManager": "Specification Manager",
"Specifications": "Specifications",
"SpecificationsEdited": "Specifications edited",
"SsoManager": "Sso Manager", "SsoManager": "Sso Manager",
"SsoProvider": "Sso Provider",
"SsoProviderEdited": "Sso Provider edited",
"StackTrace": "Stack Trace", "StackTrace": "Stack Trace",
"Status": "Status", "Status": "Status",
"Step": "Step",
"Subject": "Subject",
"Support": "Support", "Support": "Support",
"SupportingData": "Supporting Data", "SupportingData": "Supporting Data",
"TemplateIdCannotBeNull": "Template Id cannot be null",
"TemplateUnknown": "Template unknown",
"Text": "Text",
"TheDetailsBelowAreLoadedFromMasterTemplate": "The details below are loaded from the master template. Saving this template will mean that any changes to the master template will not automatically appear here.",
"ThereAreErrorsOnTheForm": "There are errors on the form",
"ThisTemplateIsCustomForThisDomainOnly": "This template is custom for this domain only",
"Timing": "Timing", "Timing": "Timing",
"TokenEndpoint": "Token Endpoint",
"TwoFactorAuthentication": "2 Factor Authentication",
"Type": "Type", "Type": "Type",
"UnblockedInMinutes": "Unblocked In (Minutes)", "UnblockedInMinutes": "Unblocked In (Minutes)",
"Up": "Up", "Up": "Up",
"User": "User",
"UserAddedToRole": "User added to role",
"UserManager": "User Manager", "UserManager": "User Manager",
"UserName": "User Name", "UserName": "User Name",
"UsernameIsRequired": "Username is required", "UsernameIsRequired": "Username is required",
"UsernameMustBeValidEmail": "Username must be a valid email", "UsernameMustBeValidEmail": "Username must be a valid email",
"Users": "Users", "Users": "Users",
"Version": "Version" "UserEdited": "User edited",
"ValidIssuer": "Valid Issuer",
"Version": "Version",
"VersionCannotBeNull": "Version cannot be null",
"Year": "Year",
"YourProfileSettingsHaveBeenSaved": "Your profile settings have been saved"
} }

View File

@ -1,7 +1,11 @@
{ {
"Email": "Courriel", "AnEmailWithPasswordResetLinkHasBeenSent": "Un courriel contenant un lien pour réinitialiser le mot de passe a été envoyé.",
"ConfirmEmailResent": "Courriel de confirmation renvoyé", "ConfirmEmailResent": "Courriel de confirmation renvoyé",
"Email": "Courriel",
"EmailTemplateSaved": "Modèle de courriel enregistré",
"LoggingOut": "Fermeture de session",
"Mail": "Courriel",
"MailTemplates": "Modèles de courriels", "MailTemplates": "Modèles de courriels",
"Support": "Soutien", "PressAgainToDelete": "Appuyer de nouveau pour supprimer",
"LoggingOut": "Fermeture de session" "PressAgainToUnblock": "Appuyer de nouveau pour débloquer"
} }

View File

@ -1,5 +1,6 @@
{ {
"Activate": "Activer", "Activate": "Activer",
"Active": "Actif",
"Add": "Ajouter", "Add": "Ajouter",
"AddDomain": "Ajouter un domaine", "AddDomain": "Ajouter un domaine",
"Address": "Adresse", "Address": "Adresse",
@ -10,92 +11,185 @@
"AnErrorOccurred": "Une erreur s'est produite", "AnErrorOccurred": "Une erreur s'est produite",
"Application": "Application", "Application": "Application",
"Applications": "Applications", "Applications": "Applications",
"AuthorizationEndpoint": "Point de terminaison dautorisation",
"AuditLog": "Journaux daudit", "AuditLog": "Journaux daudit",
"AuditLogs": "Journaux daudit", "AuditLogs": "Journaux daudit",
"Authenticate": "Authentifier",
"AuthenticationCode": "Code dauthentification",
"BlockedIPAddresses": "Adresses IP bloquées", "BlockedIPAddresses": "Adresses IP bloquées",
"BlockedIPs": "IPs bloquées", "BlockedIPs": "IPs bloquées",
"Blocked": "Bloqué",
"Cancel": "Annuler", "Cancel": "Annuler",
"Changes": "Modifications", "Changes": "Modifications",
"ClientDomainManager": "Gestionnaire de domaines clients", "ClientDomainManager": "Gestionnaire de domaines clients",
"ClientDomains": "Domaines clients", "ClientDomains": "Domaines clients",
"Close": "Fermer", "Close": "Fermer",
"ClientId": "Identifiant client",
"ClientSecret": "Secret client",
"Comment": "Commentaire", "Comment": "Commentaire",
"Confirm": "Confirmer", "Confirm": "Confirmer",
"ConfirmEmailResent": "E-mail de confirmation renvoyé", "ConfirmEmailResent": "E-mail de confirmation renvoyé",
"ConfirmPassword": "Confirmer le mot de passe", "ConfirmPassword": "Confirmer le mot de passe",
"Continuous": "Continu",
"Created": "Créé", "Created": "Créé",
"CustomField": "Champ personnalisé",
"CustomFieldEdited": "Champ personnalisé modifié",
"CustomFieldForChildEntries": "Champ personnalisé pour les entrées enfants",
"CustomFieldManager": "Gestionnaire de champs personnalisés", "CustomFieldManager": "Gestionnaire de champs personnalisés",
"CustomFields": "Champs personnalisés", "CustomFields": "Champs personnalisés",
"Day": "Jour",
"DefaultValue": "Valeur par défaut",
"DefaultMustBeGreaterThanOrEqualToMinimumValue": "\"Valeur par défaut\" doit être supérieure ou égale à \"Valeur minimale\"",
"DefaultMustBeLessThanOrEqualToMaximumValue": "\"Valeur par défaut\" doit être inférieure ou égale à \"Valeur maximale\"",
"Definition": "Définition",
"DisableAuthenticator": "Désactiver lauthentificateur", "DisableAuthenticator": "Désactiver lauthentificateur",
"DisplayName": "Nom daffichage", "DisplayName": "Nom daffichage",
"Domain": "Domaine", "Domain": "Domaine",
"DomainEdited": "Domaine modifié",
"Disabled": "Désactivé",
"Enabled": "Activé",
"e-print": "e-print", "e-print": "e-print",
"e-suite": "e-suite", "e-suite": "e-suite",
"e-suiteLogo": "Logo e-suite", "e-suiteLogo": "Logo e-suite",
"Edit": "Modifier", "Edit": "Modifier",
"EditDomain": "Modifier le domaine", "EditDomain": "Modifier le domaine",
"EditUser": "Modifier lutilisateur", "EditUser": "Modifier lutilisateur",
"EFlowAppId": "ID dapplication e-flow",
"EFlowCategoryId": "ID de catégorie e-flow",
"EFlowHostname": "Nom dhôte e-flow",
"Email": "E-mail", "Email": "E-mail",
"EmailTemplateSaved": "Modèle de-mail enregistré",
"EntityDisplayName": "Nom daffichage de lentité", "EntityDisplayName": "Nom daffichage de lentité",
"ErrorLogs": "Journaux derreurs", "ErrorLogs": "Journaux derreurs",
"ExceptionJson": "Exception JSON", "ExceptionJson": "Exception JSON",
"ExceptionLogs": "Journaux dexceptions", "ExceptionLogs": "Journaux dexceptions",
"FailedToDisableAuthenticator": "Échec de la désactivation de lauthentificateur :", "FailedToDisableAuthenticator": "Échec de la désactivation de lauthentificateur :",
"Field": "Champ",
"FailedToSaveFormInstance": "Échec de lenregistrement de linstance du formulaire",
"FieldType": "Type de champ", "FieldType": "Type de champ",
"ForgottenPassword": "Mot de passe oublié",
"FirstName": "Prénom",
"Form": "Formulaire",
"Forms": "Formulaires", "Forms": "Formulaires",
"FormTemplate": "Modèle de formulaire",
"FormTemplateEdited": "Modèle de formulaire modifié",
"FormTemplateManager": "Gestionnaire de modèles de formulaires", "FormTemplateManager": "Gestionnaire de modèles de formulaires",
"General": "Général", "General": "Général",
"Glossaries": "Glossaires", "Glossaries": "Glossaires",
"Glossary": "Glossaire",
"GlossaryItem": "Élément de glossaire",
"GlossaryItemEdited": "Élément de glossaire modifié",
"GlossaryManager": "Gestionnaire de glossaires", "GlossaryManager": "Gestionnaire de glossaires",
"Group": "Groupe", "Group": "Groupe",
"Home": "Accueil", "Home": "Accueil",
"Id": "Id", "Id": "Id",
"Increment": "Incrément",
"IsPublic": "Public",
"IPAddress": "Adresse IP", "IPAddress": "Adresse IP",
"IPAddressUnblocked": "Adresse IP '{{ip}}' débloquée.", "IPAddressUnblocked": "Adresse IP '{{ip}}' débloquée.",
"Items": "Éléments", "Items": "Éléments",
"LastUpdated": "Dernière mise à jour", "LastUpdated": "Dernière mise à jour",
"Loading": "Chargement", "Loading": "Chargement",
"LoggingOut": "Déconnexion", "LoggingOut": "Déconnexion",
"LastName": "Nom de famille",
"Mail": "Courrier",
"MailTemplates": "Modèles de-mails", "MailTemplates": "Modèles de-mails",
"MaxEntriesEmptyUnlimited": "Entrées max (vide = illimité)",
"MaximumValue": "Valeur maximale",
"Message": "Message", "Message": "Message",
"MinEntries": "Entrées min",
"MinimumValue": "Valeur minimale",
"MiddleNames": "Deuxième prénom",
"Month": "Mois",
"MultiLine": "Multiligne",
"Name": "Nom", "Name": "Nom",
"NewCustomFieldAdded": "Nouveau champ personnalisé ajouté",
"NewDomainAdded": "Nouveau domaine ajouté",
"NewFormTemplateAdded": "Nouveau modèle de formulaire ajouté",
"NewGlossaryItemAdded": "Nouvel élément de glossaire ajouté",
"NewOrganisationAdded": "Nouvelle organisation ajoutée",
"NewPassword": "Nouveau mot de passe", "NewPassword": "Nouveau mot de passe",
"NewRoleAdded": "Nouveau rôle ajouté",
"NewSequenceAdded": "Nouvelle séquence ajoutée",
"NewSpecificationsAdded": "Nouvelles spécifications ajoutées",
"NewSiteAdded": "Nouveau site ajouté",
"NewSsoProviderAdded": "Nouveau fournisseur SSO ajouté",
"NewUserAdded": "Nouvel utilisateur ajouté",
"NewValue": "Nouvelle valeur", "NewValue": "Nouvelle valeur",
"NotFound": "Introuvable", "NotFound": "Introuvable",
"Number": "Nombre",
"NumberOfAttempts": "Nombre de tentatives", "NumberOfAttempts": "Nombre de tentatives",
"OccuredAt": "Survenu à", "OccuredAt": "Survenu à",
"OldValue": "Ancienne valeur", "OldValue": "Ancienne valeur",
"Organisation": "Organisation",
"OrganisationEdited": "Organisation modifiée",
"Password": "Mot de passe", "Password": "Mot de passe",
"PasswordIsRequired": "Le mot de passe est requis", "PasswordIsRequired": "Le mot de passe est requis",
"PasswordMinLength": "Le mot de passe doit contenir au moins {{minPasswordLength}} caractères", "PasswordMinLength": "Le mot de passe doit contenir au moins {{minPasswordLength}} caractères",
"PasswordsMustMatch": "Vous devez confirmer en saisissant exactement le même nouveau mot de passe", "PasswordsMustMatch": "Vous devez confirmer en saisissant exactement le même nouveau mot de passe",
"Pattern": "Motif",
"Pending": "En attente",
"PressAgainToDelete": "Appuyez de nouveau pour supprimer", "PressAgainToDelete": "Appuyez de nouveau pour supprimer",
"PressAgainToUnblock": "Appuyez de nouveau pour débloquer", "PressAgainToUnblock": "Appuyez de nouveau pour débloquer",
"PrintSpecification": "Imprimer la spécification",
"Profile": "Profil",
"ResendConfirm": "Renvoyer la confirmation", "ResendConfirm": "Renvoyer la confirmation",
"Required": "Requis",
"ResetPassword": "Réinitialiser le mot de passe", "ResetPassword": "Réinitialiser le mot de passe",
"RolloverType": "Type de report",
"Role": "Rôle",
"RoleAccess": "Accès par rôle", "RoleAccess": "Accès par rôle",
"RoleAccessUpdated": "Accès par rôle mis à jour avec succès.", "RoleAccessUpdated": "Accès par rôle mis à jour avec succès.",
"RoleEdited": "Rôle modifié",
"Save": "Enregistrer", "Save": "Enregistrer",
"SaveAndClose": "Enregistrer et fermer",
"SecurityRoles": "Rôles de sécurité", "SecurityRoles": "Rôles de sécurité",
"Seed": "Graine",
"Sequence": "Séquence", "Sequence": "Séquence",
"SequenceEdited": "Séquence modifiée",
"SequenceFormGlossary": "Séquence/Formulaire/Glossaire",
"SequenceManager": "Gestionnaire de séquences", "SequenceManager": "Gestionnaire de séquences",
"ShowJSON": "Afficher le JSON", "ShowJSON": "Afficher le JSON",
"ShowStackTrace": "Afficher la trace de pile", "ShowStackTrace": "Afficher la trace de pile",
"SiteManager": "Gestionnaire de site", "SigmaId": "ID Sigma",
"Site": "Site",
"SiteEdited": "Site modifié",
"SiteManager": "Gestionnaire de sites",
"SpecificationManager": "Gestionnaire de spécifications", "SpecificationManager": "Gestionnaire de spécifications",
"Specifications": "Spécifications",
"SpecificationsEdited": "Spécifications modifiées",
"SsoManager": "Gestionnaire SSO", "SsoManager": "Gestionnaire SSO",
"SsoProvider": "Fournisseur SSO",
"SsoProviderEdited": "Fournisseur SSO modifié",
"StackTrace": "Trace de pile", "StackTrace": "Trace de pile",
"Status": "Statut", "Status": "Statut",
"Step": "Étape",
"Subject": "Sujet",
"Support": "Support", "Support": "Support",
"SupportingData": "Données de support", "SupportingData": "Données de support",
"TemplateIdCannotBeNull": "LID du modèle ne peut pas être nul",
"TemplateUnknown": "Modèle inconnu",
"Text": "Texte",
"TheDetailsBelowAreLoadedFromMasterTemplate": "Les détails ci-dessous sont chargés depuis le modèle maître. Enregistrer ce modèle signifie que les modifications du modèle maître napparaîtront plus automatiquement ici.",
"ThereAreErrorsOnTheForm": "Il y a des erreurs dans le formulaire",
"ThisTemplateIsCustomForThisDomainOnly": "Ce modèle est personnalisé uniquement pour ce domaine",
"Timing": "Timing", "Timing": "Timing",
"TokenEndpoint": "Point de terminaison du jeton",
"TwoFactorAuthentication": "Authentification à deux facteurs",
"Type": "Type", "Type": "Type",
"UnblockedInMinutes": "Débloqué dans (minutes)", "UnblockedInMinutes": "Débloqué dans (minutes)",
"Up": "Haut", "Up": "Haut",
"User": "Utilisateur",
"UserAddedToRole": "Utilisateur ajouté au rôle",
"UserManager": "Gestionnaire dutilisateurs", "UserManager": "Gestionnaire dutilisateurs",
"UserName": "Nom dutilisateur", "UserName": "Nom dutilisateur",
"UsernameIsRequired": "Le nom dutilisateur est requis", "UsernameIsRequired": "Le nom dutilisateur est requis",
"UsernameMustBeValidEmail": "Le nom dutilisateur doit être une adresse e-mail valide", "UsernameMustBeValidEmail": "Le nom dutilisateur doit être une adresse e-mail valide",
"Users": "Utilisateurs", "Users": "Utilisateurs",
"Version": "Version" "UserEdited": "Utilisateur modifié",
"ValidIssuer": "Émetteur valide",
"Version": "Version",
"VersionCannotBeNull": "La version ne peut pas être nulle",
"Year": "Année",
"YourProfileSettingsHaveBeenSaved": "Vos paramètres de profil ont été enregistrés"
} }

View File

@ -288,7 +288,7 @@ function GetSecureRoutes() {
path="/domains/add" path="/domains/add"
element={ element={
<Mainframe title={t("ClientDomainManager")}> <Mainframe title={t("ClientDomainManager")}>
<DomainsDetails editMode={false} /> <DomainsDetails isEditMode={false} />
</Mainframe> </Mainframe>
} }
/> />
@ -296,7 +296,7 @@ function GetSecureRoutes() {
path="/domains/edit/:domainId/addRole" path="/domains/edit/:domainId/addRole"
element={ element={
<Mainframe title={t("ClientDomainManager")}> <Mainframe title={t("ClientDomainManager")}>
<RolesDetails editMode={false} /> <RolesDetails isEditMode={false} />
</Mainframe> </Mainframe>
} }
/> />
@ -304,7 +304,7 @@ function GetSecureRoutes() {
path="/domains/edit/:domainId/editRole/:roleId" path="/domains/edit/:domainId/editRole/:roleId"
element={ element={
<Mainframe title={t("ClientDomainManager")}> <Mainframe title={t("ClientDomainManager")}>
<RolesDetails editMode={true} /> <RolesDetails isEditMode={true} />
</Mainframe> </Mainframe>
} }
/> />
@ -312,7 +312,7 @@ function GetSecureRoutes() {
path="/domains/edit/:domainId/editRole/:roleId/addUserToRole" path="/domains/edit/:domainId/editRole/:roleId/addUserToRole"
element={ element={
<Mainframe title={t("ClientDomainManager")}> <Mainframe title={t("ClientDomainManager")}>
<AddUserToRole editMode={false} /> <AddUserToRole isEditMode={false} />
</Mainframe> </Mainframe>
} }
/> />
@ -320,7 +320,7 @@ function GetSecureRoutes() {
path="/domains/edit/:domainId" path="/domains/edit/:domainId"
element={ element={
<Mainframe title={t("ClientDomainManager")}> <Mainframe title={t("ClientDomainManager")}>
<DomainsDetails editMode={true} /> <DomainsDetails isEditMode={true} />
</Mainframe> </Mainframe>
} }
/> />

View File

@ -1,5 +1,6 @@
import React from "react"; import React from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Namespaces } from "../../i18n/i18n";
import deepFind from "../../utils/deepfind"; import deepFind from "../../utils/deepfind";
import Column from "./columns"; import Column from "./columns";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
@ -47,7 +48,7 @@ export default function TableBody<T>({
onSelectRow, onSelectRow,
showSecondaryAudit, showSecondaryAudit,
}: TableBodyProps<T>): JSX.Element { }: TableBodyProps<T>): JSX.Element {
const { t } = useTranslation(); const { t } = useTranslation<typeof Namespaces.Common>();
const resolvePath = (path: string, args: string[]) => { const resolvePath = (path: string, args: string[]) => {
let modifiedPath = path; let modifiedPath = path;
let index = 0; let index = 0;

View File

@ -17,6 +17,8 @@ import Loading from "./Loading";
import { useForm } from "./useForm"; import { useForm } from "./useForm";
import { renderCustomField } from "./formHelpers"; import { renderCustomField } from "./formHelpers";
import { CustomFieldValue } from "../../modules/manager/glossary/services/glossaryService"; import { CustomFieldValue } from "../../modules/manager/glossary/services/glossaryService";
import { useTranslation } from "react-i18next";
import { Namespaces } from "../../i18n/i18n";
interface TemplateFillerProps { interface TemplateFillerProps {
templateId?: GeneralIdRef; templateId?: GeneralIdRef;
@ -204,20 +206,22 @@ const TemplateFiller = forwardRef<TemplateFillerHandle, TemplateFillerProps>(
return Object.keys(form.state.errors).length > 0; return Object.keys(form.state.errors).length > 0;
}, [form.state.errors]); }, [form.state.errors]);
const { t } = useTranslation(Namespaces.Common);
const Save = useCallback(async () => { const Save = useCallback(async () => {
const { errors } = form.state; const { errors } = form.state;
if (Object.keys(errors).length > 0) { if (Object.keys(errors).length > 0) {
toast.error("There are errors on the form"); toast.error(t("ThereAreErrorsOnTheForm"));
throw new Error("There are errors on the form"); throw new Error(t("ThereAreErrorsOnTheForm") as string);
} }
const customFieldValues = form.CustomFieldValues(); const customFieldValues = form.CustomFieldValues();
if (formInstanceId !== undefined) { if (formInstanceId !== undefined) {
if (template.templateId === undefined) if (template.templateId === undefined)
throw Error("TemplateId cannot be null"); throw Error(t("TemplateIdCannotBeNull") as string);
if (template.version === undefined) if (template.version === undefined)
throw Error("Version cannot be null"); throw Error(t("VersionCannotBeNull") as string);
const editFormInstance: EditFormInstance = { const editFormInstance: EditFormInstance = {
formInstanceId, formInstanceId,
@ -238,9 +242,9 @@ const TemplateFiller = forwardRef<TemplateFillerHandle, TemplateFillerProps>(
}; };
return await formsService.postFormInstance(formInstance); return await formsService.postFormInstance(formInstance);
} }
throw new Error("template unknown"); throw new Error(t("TemplateUnknown") as string);
} }
}, [form, template, formInstanceId]); }, [form, template, formInstanceId, t]);
useImperativeHandle(ref, () => ({ useImperativeHandle(ref, () => ({
hasValidationErrors, hasValidationErrors,

View File

@ -1,644 +0,0 @@
export * from "./formHelpers.tsx";
/*
import React from "react";
import Input, { InputType } from "./Input";
import ToggleSlider from "./ToggleSlider";
import Select from "./Select";
import Option from "./option";
import { GeneralIdRef } from "../../utils/GeneralIdRef";
import SequencePicker from "../pickers/SequencePicker";
import GlossaryPicker from "../pickers/GlossaryPicker";
import CustomFieldsEditor, { CustomFieldEditorAdd, CustomFieldEditorDelete } from "./CustomFieldsEditor";
import { CustomField, numberParams, textParams } from "../../modules/manager/customfields/services/customFieldsService";
import FormTemplatePicker from "../pickers/FormTemplatePicker";
import { CustomFieldValue } from "../../modules/manager/glossary/services/glossaryService";
import TemplateEditor from "./TemplateEditor";
import DomainPicker from "../pickers/DomainPicker";
import UserPicker from "../pickers/UserPicker";
import Button, { ButtonType } from "./Button";
import Expando from "./expando";
import ErrorBlock from "./ErrorBlock";
import SsoProviderPicker from "../pickers/SsoProviderPicker";
import { FormData, FormError } from "./useForm";
export const renderButton = (
label: string,
errors: FormError,
name?: string,
onClick?: (keyValue: any) => void,
testid?: string,
enabled: boolean = true,
buttonType: ButtonType = ButtonType.primary,
overrideErrorChecking: boolean = false
) => {
let disabled = !enabled || Object.keys(errors).filter((x) => !x.startsWith("_")).length > 0;
if (overrideErrorChecking) disabled = !enabled;
return (
<Button testid={testid} disabled={disabled} name={name ?? label} buttonType={buttonType} onClick={onClick}>
{label}
</Button>
);
};
export const renderError = (name: string, errors: FormError) => {
return <ErrorBlock error={errors[name]} />;
};
export const renderInput = (
name: string,
label: string,
data: FormData,
errors: FormError,
type: InputType = InputType.text,
readOnly = false,
defaultValue: string = "",
placeHolder: string = "",
maxLength: number = 0,
visible: boolean = true,
autoComplete: string | undefined = undefined,
onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void
) => {
let value = data[name];
let cleanValue: string | undefined;
if (value === undefined) {
cleanValue = defaultValue;
} else if (typeof value === "string") {
cleanValue = value as string;
} else if (typeof value === "number") {
cleanValue = String(value);
} else if (typeof value === "boolean") {
cleanValue = String(value);
} else if (value as CustomFieldValue) {
cleanValue = (value as CustomFieldValue).displayValue ?? (value as CustomFieldValue).value.toString();
}
if (readOnly) {
return (
<Input
includeLabel={true}
type={type}
name={name}
label={label}
value={cleanValue}
error={errors[name]}
maxLength={maxLength}
readOnly
placeHolder={placeHolder}
hidden={!visible}
autoComplete={autoComplete}
/>
);
} else {
return (
<Input
includeLabel={true}
type={type}
name={name}
label={label}
value={cleanValue}
error={errors[name]}
maxLength={maxLength}
onChange={onChange}
placeHolder={placeHolder}
hidden={!visible}
autoComplete={autoComplete}
/>
);
}
};
export const renderInputWithChangeEvent = (
name: string,
label: string,
data: FormData,
errors: FormError,
type: InputType = InputType.text,
readOnly = false,
handleChangeEvent?: (e: React.ChangeEvent<HTMLInputElement>) => void,
defaultValue: string = "",
placeHolder: string = "",
maxLength: number = 0
) => {
let value = data[name];
let cleanValue: string | undefined;
if (value === undefined) {
cleanValue = defaultValue;
} else if (typeof value === "string") {
cleanValue = value as string;
} else if (typeof value === "number") {
cleanValue = String(value);
} else if (typeof value === "boolean") {
cleanValue = String(value);
} else if (value as CustomFieldValue) {
cleanValue = (value as CustomFieldValue).displayValue ?? (value as CustomFieldValue).value.toString();
}
if (readOnly) {
return (
<Input
includeLabel={true}
type={type}
name={name}
label={label}
value={cleanValue}
error={errors[name]}
maxLength={maxLength}
readOnly
placeHolder={placeHolder}
/>
);
} else {
return (
<Input
includeLabel={true}
type={type}
name={name}
label={label}
value={cleanValue}
error={errors[name]}
maxLength={maxLength}
onChange={handleChangeEvent}
placeHolder={placeHolder}
/>
);
}
};
export const renderInputNumber = (
name: string,
label: string,
data: FormData,
errors: FormError,
readOnly = false,
defaultValue: string = "",
min?: number,
max?: number,
step: number = 1,
onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void
) => {
let value = data[name];
let cleanValue: string | undefined;
if (value === undefined) {
cleanValue = defaultValue;
} else if (typeof value === "string") {
cleanValue = value as string;
} else if (typeof value === "number") {
cleanValue = String(value);
} else if (typeof value === "boolean") {
cleanValue = String(value);
} else if (value as CustomFieldValue) {
cleanValue = (value as CustomFieldValue).displayValue ?? (value as CustomFieldValue).value.toString();
}
if (readOnly) {
return <Input includeLabel={true} type={InputType.number} name={name} label={label} value={cleanValue} error={errors[name]} readOnly />;
} else {
return (
<Input
includeLabel={true}
type={InputType.number}
name={name}
label={label}
value={cleanValue}
error={errors[name]}
min={min}
max={max}
step={step}
onChange={onChange}
/>
);
}
};
export const renderInputTextarea = (
includeLabel: boolean,
name: string,
label: string,
data: FormData,
errors: FormError,
readOnly = false,
defaultValue: string = "",
onTextAreaChange?: (e: React.ChangeEvent<HTMLTextAreaElement>) => void
) => {
let value = data[name];
let cleanValue: string | undefined;
if (value === undefined) {
cleanValue = defaultValue;
} else if (typeof value === "string") {
cleanValue = value as string;
}
if (readOnly) {
return (
<Input
includeLabel={includeLabel}
type={InputType.textarea}
key={name}
name={name}
label={label}
value={cleanValue}
error={errors[name]}
readOnly
/>
);
} else {
return (
<Input
includeLabel={includeLabel}
type={InputType.textarea}
key={name}
name={name}
label={label}
value={cleanValue}
error={errors[name]}
onTextAreaChange={onTextAreaChange}
/>
);
}
};
export const renderCustomFieldInput = (
includeLabel: boolean,
name: string,
label: string,
data: FormData,
errors: FormError,
type: InputType = InputType.text,
readOnly = false,
defaultValue: string = "",
onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void
) => {
let value = data[name];
let cleanValue: string | undefined;
if (value === undefined) {
cleanValue = defaultValue;
} else if (typeof value === "string") {
cleanValue = value as string;
} else if (typeof value === "number") {
cleanValue = String(value);
} else if (typeof value === "boolean") {
cleanValue = String(value);
} else if (value as CustomFieldValue) {
const customFieldValue = value as CustomFieldValue[];
cleanValue = customFieldValue[0].displayValue ?? customFieldValue[0].value?.toString();
}
if (readOnly) {
return <Input includeLabel={includeLabel} type={type} name={name} label={label} value={cleanValue} error={errors[name]} readOnly />;
} else {
return (
<Input
includeLabel={includeLabel}
type={type}
name={name}
label={label}
value={cleanValue}
error={errors[name]}
onChange={onChange}
/>
);
}
};
export const renderCustomFieldNumber = (
includeLabel: boolean,
name: string,
label: string,
data: FormData,
errors: FormError,
readOnly = false,
defaultValue: string = "",
min?: number,
max?: number,
step: number = 1,
onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void
) => {
let values: CustomFieldValue[] = data[name] as CustomFieldValue[];
let value: CustomFieldValue | undefined = undefined;
if (values) {
if (values.length > 0) {
value = values[0];
}
}
let cleanValue: string | undefined;
if (value === undefined) {
cleanValue = defaultValue;
} else if (typeof value === "string") {
cleanValue = value as string;
} else if (typeof value === "number") {
cleanValue = String(value);
} else if (value as CustomFieldValue) {
cleanValue = (value as CustomFieldValue).displayValue ?? (value as CustomFieldValue).value?.toString();
}
if (readOnly) {
return <Input includeLabel={includeLabel} type={InputType.number} name={name} label={label} value={cleanValue} error={errors[name]} readOnly />;
} else {
return (
<Input
includeLabel={includeLabel}
type={InputType.number}
name={name}
label={label}
value={cleanValue}
error={errors[name]}
min={min}
max={max}
step={step}
onChange={onChange}
/>
);
}
};
export const renderTemplateEditor = (
className: string,
name: string,
label: string,
data: FormData,
allowCustomFields: boolean,
onChange?: (name: string, value: string) => void
) => {
let value = data[name] as string;
return (
<div>
<label htmlFor={name}>{label}</label>
<TemplateEditor className={className} name={name} data={value} onChange={onChange} showFields={allowCustomFields} />
</div>
);
};
export const renderSelect = (
name: string,
label: string,
data: FormData,
errors: FormError,
options: Option[],
onChange?: (e: React.ChangeEvent<HTMLSelectElement>) => void
) => {
return <Select name={name} label={label} value={data[name]} options={options} error={errors[name]} onChange={onChange} />;
};
export const renderToggle = (
name: string,
label: string,
data: FormData,
errors: FormError,
onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void
) => {
return <ToggleSlider name={name} label={label} defaultChecked={Boolean(data[name])} error={errors[name]} onChange={onChange} />;
};
export const renderSequencePicker = (
includeLabel: boolean,
name: string,
label: string,
data: FormData,
errors: FormError,
onChange?: (name: string, value: GeneralIdRef) => void
) => {
return (
<SequencePicker includeLabel={includeLabel} name={name} label={label} value={data[name]} error={errors[name]} onChange={onChange} />
);
};
export const renderGlossaryPicker = (
includeLabel: boolean,
name: string,
label: string,
data: FormData,
errors: FormError,
maxEntries?: number,
refElementId?: GeneralIdRef,
onChange?: (name: string, values: CustomFieldValue[]) => void
) => {
const glossaryValues: CustomFieldValue[] | undefined = data[name] as any as CustomFieldValue[];
return (
<GlossaryPicker
includeLabel={includeLabel}
name={name}
label={label}
maxEntries={maxEntries}
values={glossaryValues}
error={errors[name]}
rootItem={refElementId}
onChange={onChange}
/>
);
};
export const renderDomainPicker = (
includeLabel: boolean,
name: string,
label: string,
data: FormData,
errors: FormError,
minEntries: number,
maxEntries?: number,
onChange?: (name: string, values: CustomFieldValue[]) => void
) => {
const domainValues: CustomFieldValue[] | undefined = data[name] as any as CustomFieldValue[];
return (
<DomainPicker
includeLabel={includeLabel}
name={name}
label={label}
minEntries={minEntries}
maxEntries={maxEntries}
values={domainValues}
error={errors[name]}
onChange={onChange}
/>
);
};
export const renderTemplatePicker = (
includeLabel: boolean,
name: string,
label: string,
data: FormData,
errors: FormError,
onChange?: (name: string, value: GeneralIdRef) => void
) => {
const templateValue: GeneralIdRef = data[name] as any as GeneralIdRef;
return (
<FormTemplatePicker
includeLabel={includeLabel}
name={name}
label={label}
value={templateValue}
error={errors[name]}
onChange={onChange}
/>
);
};
export const renderUserPicker = (
name: string,
label: string,
data: FormData,
errors: FormError,
onChange?: (name: string, value: GeneralIdRef) => void
) => {
const glossaryValue: GeneralIdRef | undefined = data[name] as any as GeneralIdRef;
return <UserPicker name={name} label={label} value={glossaryValue} error={errors[name]} onChange={onChange} />;
};
export const renderSsoProviderPicker = (
name: string,
label: string,
data: FormData,
errors: FormError,
onChange?: (name: string, value: GeneralIdRef) => void
) => {
const glossaryValue: GeneralIdRef | undefined = data[name] as any as GeneralIdRef;
return <SsoProviderPicker name={name} label={label} value={glossaryValue} error={errors[name]} onChange={onChange} />;
};
export const renderCustomFieldsEditor = (
name: string,
label: string,
data: FormData,
errors: FormError,
selected: CustomField[],
onAdd: CustomFieldEditorAdd,
onDelete: CustomFieldEditorDelete
) => {
return (
<CustomFieldsEditor name={name} label={label} value={data[name] as []} error={errors[name]} exclude={selected} onAdd={onAdd} onDelete={onDelete} />
);
};
export const renderCustomField = (
customField: CustomField,
includeLabel: boolean,
data: FormData,
errors: FormError,
onChange: (e: React.ChangeEvent<HTMLInputElement> | React.ChangeEvent<HTMLTextAreaElement>) => void,
onPickerChange: (name: string, value: GeneralIdRef | CustomFieldValue[]) => void,
getCustomFieldType: (field: CustomFieldValue, customFields: CustomField[]) => string
) => {
switch (customField.fieldType.toLowerCase()) {
case "text":
const textParameters: textParams = JSON.parse(customField.parameters!);
if (textParameters.multiLine) {
return renderInputTextarea(
includeLabel,
"customfield_" + customField.id,
customField.name,
data,
errors,
false,
customField.defaultValue,
onChange as (e: React.ChangeEvent<HTMLTextAreaElement>) => void
);
} else {
return renderCustomFieldInput(
includeLabel,
"customfield_" + customField.id,
customField.name,
data,
errors,
InputType.text,
false,
customField.defaultValue,
onChange as (e: React.ChangeEvent<HTMLInputElement>) => void
);
}
case "sequence":
return renderCustomFieldInput(includeLabel, "customfield_" + customField.id, customField.name, data, errors, InputType.text, true);
case "formtemplate":
return renderTemplatePicker(
includeLabel,
"customfield_" + customField.id,
customField.name,
data,
errors,
(name, value) => onPickerChange(name, value)
);
case "glossary":
return renderGlossaryPicker(
includeLabel,
"customfield_" + customField.id,
customField.name,
data,
errors,
customField.maxEntries,
customField.refElementId,
(name, values) => onPickerChange(name, values)
);
case "number":
const numberParameters: numberParams = JSON.parse(customField.parameters!);
return renderCustomFieldNumber(
includeLabel,
"customfield_" + customField.id,
customField.name,
data,
errors,
false,
customField.defaultValue,
numberParameters.minValue ? Number(numberParameters.minValue) : undefined,
numberParameters.maxValue ? Number(numberParameters.maxValue) : undefined,
numberParameters.step ? Number(numberParameters.step) : undefined,
onChange as (e: React.ChangeEvent<HTMLInputElement>) => void
);
case "domain":
return renderDomainPicker(
includeLabel,
"customfield_" + customField.id,
customField.name,
data,
errors,
customField.minEntries,
customField.maxEntries,
(name, values) => onPickerChange(name, values)
);
default:
return <>{customField.name + " " + customField.fieldType}</>;
}
};
export const renderCustomFields = (
customFields: CustomField[] | undefined,
data: FormData,
errors: FormError,
onChange: (e: React.ChangeEvent<HTMLInputElement> | React.ChangeEvent<HTMLTextAreaElement>) => void,
onPickerChange: (name: string, value: GeneralIdRef | CustomFieldValue[]) => void,
getCustomFieldType: (field: CustomFieldValue, customFields: CustomField[]) => string
) => {
if (customFields === undefined) return <></>;
let customFieldsBlock: JSX.Element[] = [];
for (const customField of customFields) {
customFieldsBlock.push(
renderCustomField(customField, true, data, errors, onChange, onPickerChange, getCustomFieldType)
);
}
return <>{customFieldsBlock.map((x) => x)}</>;
};
export const renderDropSection = (name: string, title: JSX.Element, content: JSX.Element, errors: FormError) => {
return (
<Expando name={name} title={title} error={errors[name]}>
{content}
</Expando>
);
};
*/

View File

@ -5,6 +5,8 @@ import AuditTable from "./components/auditTable";
import auditService, { AuditLogEntry } from "./services/auditService"; import auditService, { AuditLogEntry } from "./services/auditService";
import Loading from "../../components/common/Loading"; import Loading from "../../components/common/Loading";
import { useLocation, useParams } from "react-router-dom"; import { useLocation, useParams } from "react-router-dom";
import { useTranslation } from "react-i18next";
import { Namespaces } from "../../i18n/i18n";
const useQuery = () => new URLSearchParams(useLocation().search); const useQuery = () => new URLSearchParams(useLocation().search);
@ -12,6 +14,7 @@ export default function Audit() {
const location = useLocation(); const location = useLocation();
const params = useParams(); const params = useParams();
const query = useQuery(); const query = useQuery();
const { t } = useTranslation<typeof Namespaces.Common>();
const [loaded, setLoaded] = useState(false); const [loaded, setLoaded] = useState(false);
const [pagedData, setPagedData] = useState<Paginated<AuditLogEntry>>({ const [pagedData, setPagedData] = useState<Paginated<AuditLogEntry>>({
@ -24,7 +27,7 @@ export default function Audit() {
const [sortColumn, setSortColumn] = useState<Column<AuditLogEntry>>({ const [sortColumn, setSortColumn] = useState<Column<AuditLogEntry>>({
key: "dateTime", key: "dateTime",
label: "Timing", label: t("Timing"),
order: "desc", order: "desc",
}); });
@ -95,12 +98,12 @@ export default function Audit() {
setSortColumn({ setSortColumn({
key: "dateTime", key: "dateTime",
label: "Timing", label: t("Timing"),
order: "desc", order: "desc",
}); });
setLoaded(false); setLoaded(false);
}, [location.search, params.auditId]); }, [location.search, params.auditId, t]);
return ( return (
<Loading loaded={loaded}> <Loading loaded={loaded}>

View File

@ -47,7 +47,7 @@ const ErrorLogs = (): JSX.Element => {
useEffect(() => { useEffect(() => {
loadErrorLogs(pagedData.page, pagedData.pageSize, sortColumn, filters); loadErrorLogs(pagedData.page, pagedData.pageSize, sortColumn, filters);
}, [loadErrorLogs]); }, [filters, loadErrorLogs, pagedData.page, pagedData.pageSize, sortColumn]);
const changePage = useCallback( const changePage = useCallback(
async (page: number, pageSize: number) => { async (page: number, pageSize: number) => {

View File

@ -5,7 +5,6 @@ import { InputType } from "../../../components/common/Input";
import Input from "../../../components/common/Input"; import Input from "../../../components/common/Input";
import Button, { ButtonType } from "../../../components/common/Button"; import Button, { ButtonType } from "../../../components/common/Button";
import ErrorBlock from "../../../components/common/ErrorBlock"; import ErrorBlock from "../../../components/common/ErrorBlock";
import { FormData } from "../../../components/common/Form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Namespaces } from "../../../i18n/i18n"; import { Namespaces } from "../../../i18n/i18n";

View File

@ -1,7 +1,6 @@
import React, { useState } from "react"; import React, { useState } from "react";
import authentication from "../services/authenticationService"; import authentication from "../services/authenticationService";
import { IEmailUserAction } from "../models/IEmailUserAction"; import { IEmailUserAction } from "../models/IEmailUserAction";
import { FormData } from "../../../components/common/Form";
import Button, { ButtonType } from "../../../components/common/Button"; import Button, { ButtonType } from "../../../components/common/Button";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Namespaces } from "../../../i18n/i18n"; import { Namespaces } from "../../../i18n/i18n";

View File

@ -2,7 +2,6 @@ import React, { useState } from "react";
import { InputType } from "../../../components/common/Input"; import { InputType } from "../../../components/common/Input";
import { IEmailUserAction } from "../models/IEmailUserAction"; import { IEmailUserAction } from "../models/IEmailUserAction";
import authentication from "../services/authenticationService"; import authentication from "../services/authenticationService";
import { FormData } from "../../../components/common/Form";
import Input from "../../../components/common/Input"; import Input from "../../../components/common/Input";
import Button, { ButtonType } from "../../../components/common/Button"; import Button, { ButtonType } from "../../../components/common/Button";
import ErrorBlock from "../../../components/common/ErrorBlock"; import ErrorBlock from "../../../components/common/ErrorBlock";

View File

@ -1,5 +1,4 @@
import React, { useState } from "react"; import React, { useState } from "react";
import { FormData } from "../../../components/common/Form";
import authentication from "../services/authenticationService"; import authentication from "../services/authenticationService";
import Input, { InputType } from "../../../components/common/Input"; import Input, { InputType } from "../../../components/common/Input";
import Button, { ButtonType } from "../../../components/common/Button"; import Button, { ButtonType } from "../../../components/common/Button";

View File

@ -10,8 +10,11 @@ import {
renderError, renderError,
renderInput, renderInput,
} from "../../../components/common/formHelpers"; } from "../../../components/common/formHelpers";
import { useTranslation } from "react-i18next";
import { Namespaces } from "../../../i18n/i18n";
const LoginForm: React.FC = () => { const LoginForm: React.FC = () => {
const { t } = useTranslation<typeof Namespaces.Common>();
const [isInNextStage, setIsInNextStage] = useState(false); const [isInNextStage, setIsInNextStage] = useState(false);
const [emailSent, setEmailSent] = useState(false); const [emailSent, setEmailSent] = useState(false);
const passwordMaxLength = 255; const passwordMaxLength = 255;
@ -33,11 +36,11 @@ const LoginForm: React.FC = () => {
username: Joi.string() username: Joi.string()
.required() .required()
.email({ tlds: { allow: false } }) .email({ tlds: { allow: false } })
.label("Email"), .label(t("Email")),
password: Joi.string().required().label("Password"), password: Joi.string().required().label(t("Password")),
tfaNeeded: Joi.boolean().required(), tfaNeeded: Joi.boolean().required(),
requestTfaRemoval: Joi.boolean().required(), requestTfaRemoval: Joi.boolean().required(),
securityCode: Joi.string().allow("").label("Authenticate"), securityCode: Joi.string().allow("").label(t("Authenticate")),
}; };
form.schema = schema; form.schema = schema;
@ -137,7 +140,7 @@ const LoginForm: React.FC = () => {
InputType.text, InputType.text,
isInNextStage, isInNextStage,
"", "",
"Email", t("Email") as string,
0, 0,
true, true,
"username", "username",
@ -151,7 +154,7 @@ const LoginForm: React.FC = () => {
InputType.password, InputType.password,
emailSent, emailSent,
"", "",
"Password", t("Password") as string,
passwordMaxLength, passwordMaxLength,
isInNextStage, isInNextStage,
"current-password", "current-password",
@ -159,7 +162,7 @@ const LoginForm: React.FC = () => {
)} )}
{!isInNextStage && {!isInNextStage &&
renderButton( renderButton(
"Next", t("Next"),
form.state.errors, form.state.errors,
"next", "next",
handleNextClick, handleNextClick,
@ -184,7 +187,7 @@ const LoginForm: React.FC = () => {
{isInNextStage && ( {isInNextStage && (
<div className="forgottenLink"> <div className="forgottenLink">
{renderButton( {renderButton(
"Forgotten Password", t("ForgottenPassword") as string,
form.state.errors, form.state.errors,
"forgot-password", "forgot-password",
handleForgetPassword, handleForgetPassword,
@ -209,7 +212,7 @@ const LoginForm: React.FC = () => {
{renderError("_general", form.state.errors)} {renderError("_general", form.state.errors)}
{renderInput( {renderInput(
"securityCode", "securityCode",
"Authenticate", t("Authenticate") as string,
form.state.data, form.state.data,
form.state.errors, form.state.errors,
InputType.text, InputType.text,
@ -221,7 +224,7 @@ const LoginForm: React.FC = () => {
undefined, undefined,
form.handleChange, form.handleChange,
)} )}
{renderButton("Authenticate", form.state.errors, "authenticate")} {renderButton(t("Authenticate"), form.state.errors, "authenticate")}
<Link to="#" onClick={authenticationWorkAround}> <Link to="#" onClick={authenticationWorkAround}>
My Authenticator is not working My Authenticator is not working
</Link> </Link>

View File

@ -1,9 +1,10 @@
import React, { useEffect } from "react"; import React, { useEffect } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Namespaces } from "../../../i18n/i18n";
import authentication from "../services/authenticationService"; import authentication from "../services/authenticationService";
const Logout: React.FC = () => { const Logout: React.FC = () => {
const { t } = useTranslation(); const { t } = useTranslation<typeof Namespaces.Common>();
useEffect(() => { useEffect(() => {
authentication.logout(); authentication.logout();

View File

@ -1,8 +1,9 @@
import React from "react"; import React from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Namespaces } from "../../../i18n/i18n";
const NotFound: React.FC = () => { const NotFound: React.FC = () => {
const { t } = useTranslation(); const { t } = useTranslation<typeof Namespaces.Common>();
return <h1>{t("NotFound")}</h1>; return <h1>{t("NotFound")}</h1>;
}; };

View File

@ -1,8 +1,9 @@
import React from "react"; import React from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Namespaces } from "../../i18n/i18n";
const HomePage: React.FC = () => { const HomePage: React.FC = () => {
const { t } = useTranslation(); const { t } = useTranslation<typeof Namespaces.Common>();
const redirect = () => { const redirect = () => {
window.location.href = "/organisations"; window.location.href = "/organisations";

View File

@ -1,5 +1,6 @@
import React from "react"; import React from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Namespaces } from "../../../../i18n/i18n";
import Column from "../../../../components/common/columns"; import Column from "../../../../components/common/columns";
import Table, { import Table, {
PublishedTableProps, PublishedTableProps,
@ -10,7 +11,7 @@ import { CustomField } from "../services/customFieldsService";
const CustomFieldsTable: React.FC<PublishedTableProps<CustomField>> = ( const CustomFieldsTable: React.FC<PublishedTableProps<CustomField>> = (
props, props,
) => { ) => {
const { t } = useTranslation(); const { t } = useTranslation<typeof Namespaces.Common>();
const columns: Column<CustomField>[] = [ const columns: Column<CustomField>[] = [
{ key: "name", label: t("Name"), order: "asc" }, { key: "name", label: t("Name"), order: "asc" },

View File

@ -2,6 +2,8 @@ import Joi from "joi";
import React, { useEffect } from "react"; import React, { useEffect } from "react";
import { Navigate, useParams } from "react-router-dom"; import { Navigate, useParams } from "react-router-dom";
import { toast } from "react-toastify"; import { toast } from "react-toastify";
import { useTranslation } from "react-i18next";
import { Namespaces } from "../../../i18n/i18n";
import { InputType } from "../../../components/common/Input"; import { InputType } from "../../../components/common/Input";
import { useForm } from "../../../components/common/useForm"; import { useForm } from "../../../components/common/useForm";
import { import {
@ -35,21 +37,22 @@ const CustomFieldDetails: React.FC<CustomFieldDetailsProps> = ({
editMode = false, editMode = false,
}) => { }) => {
const { customFieldId } = useParams<{ customFieldId: string }>(); const { customFieldId } = useParams<{ customFieldId: string }>();
const { t } = useTranslation<typeof Namespaces.Common>();
const labelName = "Name"; const labelName = t("Name");
const labelFieldType = "Field Type"; const labelFieldType = t("FieldType");
const labelMultiLine = "Multi-line"; const labelMultiLine = t("MultiLine");
const labelDefaultValue = "Default Value"; const labelDefaultValue = t("DefaultValue");
const labelMinValue = "Minimum Value"; const labelMinValue = t("MinimumValue");
const labelMaxValue = "Maximum Value"; const labelMaxValue = t("MaximumValue");
const labelStep = "Step"; const labelStep = t("Step");
const labelRequired = "Required"; const labelRequired = t("Required");
const labelMinEntries = "Min Entries"; const labelMinEntries = t("MinEntries");
const labelMaxEntries = "Max Entries (empty=unlimited)"; const labelMaxEntries = t("MaxEntriesEmptyUnlimited");
let labelRefElementId = "Sequence/Form/Glossary"; let labelRefElementId = t("SequenceFormGlossary");
const labelApply = "Save"; const labelApply = t("Save");
const labelSave = "Save and close"; const labelSave = t("SaveAndClose");
const form = useForm({ const form = useForm({
loaded: false, loaded: false,
@ -111,22 +114,14 @@ const CustomFieldDetails: React.FC<CustomFieldDetailsProps> = ({
then: Joi.number(), then: Joi.number(),
otherwise: Joi.number() otherwise: Joi.number()
.min(Joi.ref("minValue")) .min(Joi.ref("minValue"))
.message( .message(t("DefaultMustBeGreaterThanOrEqualToMinimumValue")),
'"Default Value" must be greater than or equal to "' +
labelMinValue +
'"',
),
}) })
.when("maxValue", { .when("maxValue", {
is: Joi.any().valid(null, ""), is: Joi.any().valid(null, ""),
then: Joi.number(), then: Joi.number(),
otherwise: Joi.number() otherwise: Joi.number()
.max(Joi.ref("maxValue")) .max(Joi.ref("maxValue"))
.message( .message(t("DefaultMustBeLessThanOrEqualToMaximumValue")),
'"Default Value" must be less than or equal to "' +
labelMaxValue +
'"',
),
}) })
.allow(""), .allow(""),
otherwise: Joi.string().allow(""), otherwise: Joi.string().allow(""),
@ -305,7 +300,7 @@ const CustomFieldDetails: React.FC<CustomFieldDetailsProps> = ({
params, params,
); );
if (response) { if (response) {
toast.info("Custom Field edited"); toast.info(t("CustomFieldEdited"));
} }
} else { } else {
const response = await customFieldsService.postField( const response = await customFieldsService.postField(
@ -318,7 +313,7 @@ const CustomFieldDetails: React.FC<CustomFieldDetailsProps> = ({
params, params,
); );
if (response) { if (response) {
toast.info("New Custom Field added"); toast.info(t("NewCustomFieldAdded"));
} }
} }
@ -337,33 +332,35 @@ const CustomFieldDetails: React.FC<CustomFieldDetailsProps> = ({
const { fieldType } = form.state.data; const { fieldType } = form.state.data;
const fieldTypeValue = typeof fieldType === "string" ? fieldType : ""; const fieldTypeValue = typeof fieldType === "string" ? fieldType : "";
let mode = "Add"; let mode = t("Add");
if (isEditMode()) mode = "Edit"; if (isEditMode()) mode = t("Edit");
const fieldTypeOptions: Option[] = [ const fieldTypeOptions: Option[] = [
{ _id: "Text", name: "Text" }, { _id: "Text", name: t("Text") },
{ _id: "Number", name: "Number" }, { _id: "Number", name: t("Number") },
{ _id: "Sequence", name: "Sequence" }, { _id: "Sequence", name: t("Sequence") },
{ _id: "FormTemplate", name: "Form Template" }, { _id: "FormTemplate", name: t("FormTemplate") },
{ _id: "Glossary", name: "Glossary" }, { _id: "Glossary", name: t("Glossary") },
{ _id: "Domain", name: "Domain" }, { _id: "Domain", name: t("Domain") },
]; ];
switch (fieldTypeValue) { switch (fieldTypeValue) {
case "Sequence": case "Sequence":
labelRefElementId = "Sequence"; labelRefElementId = t("Sequence");
break; break;
case "FormTemplate": case "FormTemplate":
labelRefElementId = "Form"; labelRefElementId = t("Form");
break; break;
case "Glossary": case "Glossary":
labelRefElementId = "Glossary"; labelRefElementId = t("Glossary");
break; break;
} }
return ( return (
<Loading loaded={form.state.loaded}> <Loading loaded={form.state.loaded}>
<h1>{mode} Custom Field</h1> <h1>
{mode} {t("CustomField")}
</h1>
<form onSubmit={handleSubmit}> <form onSubmit={handleSubmit}>
{renderError("_general", form.state.errors)} {renderError("_general", form.state.errors)}
{renderInput( {renderInput(

View File

@ -1,5 +1,6 @@
import React, { useEffect, useMemo, useState } from "react"; import React, { useEffect, useMemo, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Namespaces } from "../../../i18n/i18n";
import Column from "../../../components/common/columns"; import Column from "../../../components/common/columns";
import { Paginated } from "../../../services/Paginated"; import { Paginated } from "../../../services/Paginated";
import CustomFieldsTable from "./components/CustomFieldsTable"; import CustomFieldsTable from "./components/CustomFieldsTable";
@ -18,17 +19,18 @@ const initialPagedData: Paginated<CustomField> = {
data: [], data: [],
}; };
const initialSortColumn: Column<CustomField> = {
key: "name",
label: "Name",
order: "asc",
};
const CustomFields: React.FC = () => { const CustomFields: React.FC = () => {
const { t } = useTranslation(); const { t } = useTranslation<typeof Namespaces.Common>();
const [loaded, setLoaded] = useState(false); const [loaded, setLoaded] = useState(false);
const [pagedData, setPagedData] = const [pagedData, setPagedData] =
useState<Paginated<CustomField>>(initialPagedData); useState<Paginated<CustomField>>(initialPagedData);
const initialSortColumn: Column<CustomField> = {
key: "name",
label: t("Name"),
order: "asc",
};
const [sortColumn, setSortColumn] = const [sortColumn, setSortColumn] =
useState<Column<CustomField>>(initialSortColumn); useState<Column<CustomField>>(initialSortColumn);
const [filters, setFilters] = useState<Map<string, string>>( const [filters, setFilters] = useState<Map<string, string>>(
@ -53,7 +55,7 @@ const CustomFields: React.FC = () => {
}; };
void loadInitial(); void loadInitial();
}, []); }, [initialSortColumn.key, initialSortColumn.order]);
const changePage = async (page: number, pageSize: number) => { const changePage = async (page: number, pageSize: number) => {
const pagedDataResult = await customFieldsService.getFields( const pagedDataResult = await customFieldsService.getFields(

View File

@ -1,5 +1,6 @@
import React, { useCallback, useEffect, useState } from "react"; import React, { useCallback, useEffect, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Namespaces } from "../../../i18n/i18n";
import Column from "../../../components/common/columns"; import Column from "../../../components/common/columns";
import { Paginated } from "../../../services/Paginated"; import { Paginated } from "../../../services/Paginated";
import DomainsTable from "./components/domainsTable"; import DomainsTable from "./components/domainsTable";
@ -17,7 +18,7 @@ const initialPagedData: Paginated<GetDomain> = {
}; };
const Domains: React.FC = () => { const Domains: React.FC = () => {
const { t } = useTranslation(); const { t } = useTranslation<typeof Namespaces.Common>();
const [loaded, setLoaded] = useState(false); const [loaded, setLoaded] = useState(false);
const [pagedData, setPagedData] = const [pagedData, setPagedData] =
useState<Paginated<GetDomain>>(initialPagedData); useState<Paginated<GetDomain>>(initialPagedData);

View File

@ -1,5 +1,6 @@
import React from "react"; import React from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Namespaces } from "../../../i18n/i18n";
import { useSearchParams } from "react-router-dom"; import { useSearchParams } from "react-router-dom";
import HorizontalTabs from "../../../components/common/HorizionalTabs"; import HorizontalTabs from "../../../components/common/HorizionalTabs";
import Tab from "../../../components/common/Tab"; import Tab from "../../../components/common/Tab";
@ -9,17 +10,17 @@ import MailTemplatesTab from "./components/MailTemplatesTab";
import SecurityRolesTab from "./components/SecurityRolesTab"; import SecurityRolesTab from "./components/SecurityRolesTab";
interface DomainsDetailsProps { interface DomainsDetailsProps {
editMode: boolean; isEditMode: boolean;
} }
const DomainsDetails: React.FC<DomainsDetailsProps> = ({ editMode }) => { const DomainsDetails: React.FC<DomainsDetailsProps> = ({ isEditMode }) => {
const { t } = useTranslation(); const { t } = useTranslation<typeof Namespaces.Common>();
const [searchParams] = useSearchParams(); const [searchParams] = useSearchParams();
const canViewMailTemplates = authentication.hasAccess("ViewDomain"); const canViewMailTemplates = authentication.hasAccess("ViewDomain");
const canViewSecurityRoles = authentication.hasAccess("ViewRole"); const canViewSecurityRoles = authentication.hasAccess("ViewRole");
const heading = editMode ? t("EditDomain") : t("AddDomain"); const heading = isEditMode ? t("EditDomain") : t("AddDomain");
const initialTab = searchParams.get("tab") || undefined; const initialTab = searchParams.get("tab") || undefined;
const roleId = searchParams.get("roleId") || undefined; const roleId = searchParams.get("roleId") || undefined;
const innerTab = searchParams.get("innerTab") || undefined; const innerTab = searchParams.get("innerTab") || undefined;
@ -28,11 +29,11 @@ const DomainsDetails: React.FC<DomainsDetailsProps> = ({ editMode }) => {
tabs.push( tabs.push(
<Tab key={1} label={t("General")}> <Tab key={1} label={t("General")}>
<GeneralTab isEditMode={editMode} /> <GeneralTab isEditMode={isEditMode} />
</Tab>, </Tab>,
); );
if (editMode) { if (isEditMode) {
if (canViewMailTemplates) { if (canViewMailTemplates) {
tabs.push( tabs.push(
<Tab key={2} label={t("MailTemplates")}> <Tab key={2} label={t("MailTemplates")}>

View File

@ -2,6 +2,8 @@ import Joi from "joi";
import React from "react"; import React from "react";
import { Navigate, useParams } from "react-router-dom"; import { Navigate, useParams } from "react-router-dom";
import { toast } from "react-toastify"; import { toast } from "react-toastify";
import { useTranslation } from "react-i18next";
import { Namespaces } from "../../../../i18n/i18n";
import { useForm } from "../../../../components/common/useForm"; import { useForm } from "../../../../components/common/useForm";
import { MakeGeneralIdRef } from "../../../../utils/GeneralIdRef"; import { MakeGeneralIdRef } from "../../../../utils/GeneralIdRef";
import roleService from "../serrvices/rolesService"; import roleService from "../serrvices/rolesService";
@ -21,10 +23,11 @@ const AddUserToRole: React.FC<LocAddUserToRoleProps> = ({ isEditMode }) => {
domainId: string; domainId: string;
roleId: string; roleId: string;
}>(); }>();
const { t } = useTranslation<typeof Namespaces.Common>();
const labelUserId = "User"; const labelUserId = t("User");
const labelApply = "Save"; const labelApply = t("Save");
const labelSave = "Save and close"; const labelSave = t("SaveAndClose");
const form = useForm({ const form = useForm({
loaded: true, loaded: true,
@ -48,7 +51,7 @@ const AddUserToRole: React.FC<LocAddUserToRoleProps> = ({ isEditMode }) => {
MakeGeneralIdRef(BigInt(roleId!)), MakeGeneralIdRef(BigInt(roleId!)),
); );
if (response) { if (response) {
toast.info("User added to role"); toast.info(t("UserAddedToRole"));
if (buttonName === labelSave) if (buttonName === labelSave)
form.setState({ form.setState({

View File

@ -2,6 +2,8 @@ import Joi from "joi";
import React, { useEffect } from "react"; import React, { useEffect } from "react";
import { Navigate } from "react-router-dom"; import { Navigate } from "react-router-dom";
import { toast } from "react-toastify"; import { toast } from "react-toastify";
import { useTranslation } from "react-i18next";
import { Namespaces } from "../../../../i18n/i18n";
import { useForm } from "../../../../components/common/useForm"; import { useForm } from "../../../../components/common/useForm";
import { InputType } from "../../../../components/common/Input"; import { InputType } from "../../../../components/common/Input";
import { MakeGeneralIdRef } from "../../../../utils/GeneralIdRef"; import { MakeGeneralIdRef } from "../../../../utils/GeneralIdRef";
@ -22,10 +24,12 @@ const EmailTemplateEditor: React.FC<EmailTemplateEditorProps> = ({
domainId, domainId,
currentMailType, currentMailType,
}) => { }) => {
const labelName = "Subject"; const { t } = useTranslation<typeof Namespaces.Common>();
const labelDefinition = "Definition";
const labelApply = "Save"; const labelName = t("Subject");
const labelSave = "Save and close"; const labelDefinition = t("Definition");
const labelApply = t("Save");
const labelSave = t("SaveAndClose");
const form = useForm({ const form = useForm({
loaded: false, loaded: false,
@ -101,7 +105,7 @@ const EmailTemplateEditor: React.FC<EmailTemplateEditorProps> = ({
definitionStr, definitionStr,
); );
if (response) { if (response) {
toast.info("Email Template saved"); toast.info(t("EmailTemplateSaved"));
if (buttonName === labelSave) form.setState({ redirect: "/domains" }); if (buttonName === labelSave) form.setState({ redirect: "/domains" });
} }
} catch (ex: any) { } catch (ex: any) {
@ -122,14 +126,10 @@ const EmailTemplateEditor: React.FC<EmailTemplateEditorProps> = ({
<> <>
<div style={{ position: "relative" }}> <div style={{ position: "relative" }}>
{isOverriddenValue && ( {isOverriddenValue && (
<p>This template is custom for this domain only</p> <p>{t("ThisTemplateIsCustomForThisDomainOnly")}</p>
)} )}
{!isOverriddenValue && ( {!isOverriddenValue && (
<p> <p>{t("TheDetailsBelowAreLoadedFromMasterTemplate")}</p>
The details below are loaded from the master template. Saving this
template will mean that any changes to the master template will not
automatically appear here.
</p>
)} )}
<form <form

View File

@ -2,6 +2,8 @@ import Joi from "joi";
import React, { useEffect } from "react"; import React, { useEffect } from "react";
import { Navigate, useParams } from "react-router-dom"; import { Navigate, useParams } from "react-router-dom";
import { toast } from "react-toastify"; import { toast } from "react-toastify";
import { useTranslation } from "react-i18next";
import { Namespaces } from "../../../../i18n/i18n";
import { useForm } from "../../../../components/common/useForm"; import { useForm } from "../../../../components/common/useForm";
import { InputType } from "../../../../components/common/Input"; import { InputType } from "../../../../components/common/Input";
import { MakeGeneralIdRef } from "../../../../utils/GeneralIdRef"; import { MakeGeneralIdRef } from "../../../../utils/GeneralIdRef";
@ -20,16 +22,17 @@ interface GeneralTabProps {
const GeneralTab: React.FC<GeneralTabProps> = ({ isEditMode }) => { const GeneralTab: React.FC<GeneralTabProps> = ({ isEditMode }) => {
const { domainId } = useParams<{ domainId: string }>(); const { domainId } = useParams<{ domainId: string }>();
const { t } = useTranslation<typeof Namespaces.Common>();
const labelName = "Name"; const labelName = t("Name");
const labelSsoProvider = "Sso Provider"; const labelSsoProvider = t("SsoProvider");
const labelSunriseHostName = "e-flow hostname"; const labelSunriseHostName = t("EFlowHostname");
const labelSunriseAppId = "e-flow AppId"; const labelSunriseAppId = t("EFlowAppId");
const labelSunriseCategoryId = "e-flow CategoryId"; const labelSunriseCategoryId = t("EFlowCategoryId");
const labelSigmaId = "Sigma Id"; const labelSigmaId = t("SigmaId");
const labelApply = "Save"; const labelApply = t("Save");
const labelSave = "Save and close"; const labelSave = t("SaveAndClose");
const form = useForm({ const form = useForm({
loaded: false, loaded: false,
@ -97,7 +100,7 @@ const GeneralTab: React.FC<GeneralTabProps> = ({ isEditMode }) => {
sigmaIdValue, sigmaIdValue,
); );
if (response) { if (response) {
toast.info("Domain edited"); toast.info(t("DomainEdited"));
} }
} else { } else {
const response = await domainsService.postDomain( const response = await domainsService.postDomain(
@ -109,7 +112,7 @@ const GeneralTab: React.FC<GeneralTabProps> = ({ isEditMode }) => {
sigmaIdValue, sigmaIdValue,
); );
if (response) { if (response) {
toast.info("New Domain added"); toast.info(t("NewDomainAdded"));
} }
} }

View File

@ -1,5 +1,6 @@
import React, { useCallback, useEffect, useMemo, useState } from "react"; import React, { useCallback, useEffect, useMemo, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Namespaces } from "../../../../i18n/i18n";
import { toast } from "react-toastify"; import { toast } from "react-toastify";
import { Paginated } from "../../../../services/Paginated"; import { Paginated } from "../../../../services/Paginated";
import { MakeGeneralIdRef } from "../../../../utils/GeneralIdRef"; import { MakeGeneralIdRef } from "../../../../utils/GeneralIdRef";
@ -31,7 +32,7 @@ interface RoleAccessEditorProps {
} }
const RoleAccessEditor: React.FC<RoleAccessEditorProps> = ({ role }) => { const RoleAccessEditor: React.FC<RoleAccessEditorProps> = ({ role }) => {
const { t } = useTranslation(); const { t } = useTranslation<typeof Namespaces.Common>();
const [loaded, setLoaded] = useState(false); const [loaded, setLoaded] = useState(false);
const [accessList, setAccessList] = const [accessList, setAccessList] =
useState<Paginated<GetSecurityAccess>>(initialAccessList); useState<Paginated<GetSecurityAccess>>(initialAccessList);

View File

@ -2,6 +2,8 @@ import Joi from "joi";
import React, { useEffect } from "react"; import React, { useEffect } from "react";
import { Navigate, useParams } from "react-router-dom"; import { Navigate, useParams } from "react-router-dom";
import { toast } from "react-toastify"; import { toast } from "react-toastify";
import { useTranslation } from "react-i18next";
import { Namespaces } from "../../../../i18n/i18n";
import { useForm } from "../../../../components/common/useForm"; import { useForm } from "../../../../components/common/useForm";
import { InputType } from "../../../../components/common/Input"; import { InputType } from "../../../../components/common/Input";
import { MakeGeneralIdRef } from "../../../../utils/GeneralIdRef"; import { MakeGeneralIdRef } from "../../../../utils/GeneralIdRef";
@ -22,10 +24,11 @@ const RolesDetails: React.FC<RolesDetailsProps> = ({ isEditMode }) => {
domainId: string; domainId: string;
roleId: string; roleId: string;
}>(); }>();
const { t } = useTranslation<typeof Namespaces.Common>();
const labelName = "Name"; const labelName = t("Name");
const labelApply = "Save"; const labelApply = t("Save");
const labelSave = "Save and close"; const labelSave = t("SaveAndClose");
const form = useForm({ const form = useForm({
loaded: false, loaded: false,
@ -51,7 +54,7 @@ const RolesDetails: React.FC<RolesDetailsProps> = ({ isEditMode }) => {
var generalIdRef = MakeGeneralIdRef(BigInt(roleId!)); var generalIdRef = MakeGeneralIdRef(BigInt(roleId!));
const response = await roleService.putRole(generalIdRef, nameStr); const response = await roleService.putRole(generalIdRef, nameStr);
if (response) { if (response) {
toast.info("Role edited"); toast.info(t("RoleEdited"));
} }
} else { } else {
const response = await roleService.postRole( const response = await roleService.postRole(
@ -59,7 +62,7 @@ const RolesDetails: React.FC<RolesDetailsProps> = ({ isEditMode }) => {
nameStr, nameStr,
); );
if (response) { if (response) {
toast.info("New Role added"); toast.info(t("NewRoleAdded"));
} }
} }
@ -102,12 +105,14 @@ const RolesDetails: React.FC<RolesDetailsProps> = ({ isEditMode }) => {
const { loaded, redirect } = form.state; const { loaded, redirect } = form.state;
if (redirect) return <Navigate to={redirect} />; if (redirect) return <Navigate to={redirect} />;
let mode = "Add"; let mode = t("Add");
if (isEditMode) mode = "Edit"; if (isEditMode) mode = t("Edit");
return ( return (
<Loading loaded={loaded}> <Loading loaded={loaded}>
<h1>{mode} Role</h1> <h1>
{mode} {t("Role")}
</h1>
<form onSubmit={handleSubmit}> <form onSubmit={handleSubmit}>
{renderError("_general", form.state.errors)} {renderError("_general", form.state.errors)}
{renderInput( {renderInput(

View File

@ -1,5 +1,6 @@
import React, { useCallback, useEffect, useMemo, useState } from "react"; import React, { useCallback, useEffect, useMemo, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Namespaces } from "../../../../i18n/i18n";
import Column from "../../../../components/common/columns"; import Column from "../../../../components/common/columns";
import { Paginated } from "../../../../services/Paginated"; import { Paginated } from "../../../../services/Paginated";
import { MakeGeneralIdRef } from "../../../../utils/GeneralIdRef"; import { MakeGeneralIdRef } from "../../../../utils/GeneralIdRef";
@ -31,7 +32,7 @@ const RolesEditor: React.FC<RolesEditorProps> = ({
onUnselectRole, onUnselectRole,
initialRoleId, initialRoleId,
}) => { }) => {
const { t } = useTranslation(); const { t } = useTranslation<typeof Namespaces.Common>();
const [loaded, setLoaded] = useState(false); const [loaded, setLoaded] = useState(false);
const [pagedData, setPagedData] = const [pagedData, setPagedData] =
useState<Paginated<GetRoleResponse>>(initialPagedData); useState<Paginated<GetRoleResponse>>(initialPagedData);

View File

@ -1,5 +1,6 @@
import React from "react"; import React from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Namespaces } from "../../../../i18n/i18n";
import Column from "../../../../components/common/columns"; import Column from "../../../../components/common/columns";
import Table, { import Table, {
PublishedTableProps, PublishedTableProps,
@ -8,7 +9,7 @@ import authentication from "../../../frame/services/authenticationService";
import { GetRoleResponse } from "../serrvices/rolesService"; import { GetRoleResponse } from "../serrvices/rolesService";
const RolesTable: React.FC<PublishedTableProps<GetRoleResponse>> = (props) => { const RolesTable: React.FC<PublishedTableProps<GetRoleResponse>> = (props) => {
const { t } = useTranslation(); const { t } = useTranslation<typeof Namespaces.Common>();
const columns: Column<GetRoleResponse>[] = [ const columns: Column<GetRoleResponse>[] = [
{ key: "name", label: t("Name"), order: "asc" }, { key: "name", label: t("Name"), order: "asc" },

View File

@ -1,5 +1,6 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Namespaces } from "../../../../i18n/i18n";
import Column from "../../../../components/common/columns"; import Column from "../../../../components/common/columns";
import Table, { import Table, {
PublishedTableProps, PublishedTableProps,
@ -21,7 +22,7 @@ const RollAccessTable: React.FC<RollAccessTableProps> = ({
onSort, onSort,
data, data,
}) => { }) => {
const { t } = useTranslation(); const { t } = useTranslation<typeof Namespaces.Common>();
const [deltaAdditions, setDeltaAdditions] = useState<string[]>([]); const [deltaAdditions, setDeltaAdditions] = useState<string[]>([]);
const [deltaDeletions, setDeltaDeletions] = useState<string[]>([]); const [deltaDeletions, setDeltaDeletions] = useState<string[]>([]);

View File

@ -1,5 +1,6 @@
import React, { useState } from "react"; import React, { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Namespaces } from "../../../../i18n/i18n";
import HorizontalTabs from "../../../../components/common/HorizionalTabs"; import HorizontalTabs from "../../../../components/common/HorizionalTabs";
import Tab from "../../../../components/common/Tab"; import Tab from "../../../../components/common/Tab";
import RoleAccessEditor from "./RoleAccessEditor"; import RoleAccessEditor from "./RoleAccessEditor";
@ -17,7 +18,7 @@ const SecurityRolesTab: React.FC<SecurityRolesTabProps> = ({
initialRoleId, initialRoleId,
initialInnerTab, initialInnerTab,
}) => { }) => {
const { t } = useTranslation(); const { t } = useTranslation<typeof Namespaces.Common>();
const [selectedRole, setSelectedRole] = useState<GetRoleResponse | undefined>( const [selectedRole, setSelectedRole] = useState<GetRoleResponse | undefined>(
undefined, undefined,
); );

View File

@ -1,5 +1,6 @@
import React, { useCallback, useEffect, useMemo, useState } from "react"; import React, { useCallback, useEffect, useMemo, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Namespaces } from "../../../../i18n/i18n";
import Column from "../../../../components/common/columns"; import Column from "../../../../components/common/columns";
import { Paginated } from "../../../../services/Paginated"; import { Paginated } from "../../../../services/Paginated";
import { MakeGeneralIdRef } from "../../../../utils/GeneralIdRef"; import { MakeGeneralIdRef } from "../../../../utils/GeneralIdRef";
@ -22,7 +23,7 @@ interface UserRoleEditorProps {
} }
const UserRoleEditor: React.FC<UserRoleEditorProps> = ({ role }) => { const UserRoleEditor: React.FC<UserRoleEditorProps> = ({ role }) => {
const { t } = useTranslation(); const { t } = useTranslation<typeof Namespaces.Common>();
const [loaded, setLoaded] = useState(false); const [loaded, setLoaded] = useState(false);
const [pagedData, setPagedData] = const [pagedData, setPagedData] =
useState<Paginated<RoleUser>>(initialPagedData); useState<Paginated<RoleUser>>(initialPagedData);

View File

@ -1,5 +1,6 @@
import React from "react"; import React from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Namespaces } from "../../../../i18n/i18n";
import Column from "../../../../components/common/columns"; import Column from "../../../../components/common/columns";
import Table, { import Table, {
PublishedTableProps, PublishedTableProps,
@ -8,7 +9,7 @@ import authentication from "../../../frame/services/authenticationService";
import { RoleUser } from "../serrvices/rolesService"; import { RoleUser } from "../serrvices/rolesService";
const UserRolesTable: React.FC<PublishedTableProps<RoleUser>> = (props) => { const UserRolesTable: React.FC<PublishedTableProps<RoleUser>> = (props) => {
const { t } = useTranslation(); const { t } = useTranslation<typeof Namespaces.Common>();
const columns: Column<RoleUser>[] = [ const columns: Column<RoleUser>[] = [
{ key: "displayName", label: t("Name"), order: "asc" }, { key: "displayName", label: t("Name"), order: "asc" },

View File

@ -1,5 +1,6 @@
import React from "react"; import React from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Namespaces } from "../../../../i18n/i18n";
import Column from "../../../../components/common/columns"; import Column from "../../../../components/common/columns";
import Table, { import Table, {
PublishedTableProps, PublishedTableProps,
@ -8,7 +9,7 @@ import authentication from "../../../frame/services/authenticationService";
import { GetDomain } from "../serrvices/domainsService"; import { GetDomain } from "../serrvices/domainsService";
const DomainsTable: React.FC<PublishedTableProps<GetDomain>> = (props) => { const DomainsTable: React.FC<PublishedTableProps<GetDomain>> = (props) => {
const { t } = useTranslation(); const { t } = useTranslation<typeof Namespaces.Common>();
const columns: Column<GetDomain>[] = [ const columns: Column<GetDomain>[] = [
{ key: "name", label: t("Name"), order: "asc" }, { key: "name", label: t("Name"), order: "asc" },

View File

@ -1,5 +1,6 @@
import { useCallback, useEffect, useState } from "react"; import { useCallback, useEffect, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Namespaces } from "../../../i18n/i18n";
import Button, { ButtonType } from "../../../components/common/Button"; import Button, { ButtonType } from "../../../components/common/Button";
import Column from "../../../components/common/columns"; import Column from "../../../components/common/columns";
import Permission from "../../../components/common/Permission"; import Permission from "../../../components/common/Permission";
@ -9,7 +10,7 @@ import formsService, { GetFormResponse } from "./services/formsService";
import Loading from "../../../components/common/Loading"; import Loading from "../../../components/common/Loading";
const Forms: React.FC = () => { const Forms: React.FC = () => {
const { t } = useTranslation(); const { t } = useTranslation<typeof Namespaces.Common>();
const [loaded, setLoaded] = useState(false); const [loaded, setLoaded] = useState(false);
const [pagedData, setPagedData] = useState<Paginated<GetFormResponse>>({ const [pagedData, setPagedData] = useState<Paginated<GetFormResponse>>({

View File

@ -2,6 +2,8 @@ import Joi from "joi";
import React, { useEffect } from "react"; import React, { useEffect } from "react";
import { Navigate, useParams } from "react-router-dom"; import { Navigate, useParams } from "react-router-dom";
import { toast } from "react-toastify"; import { toast } from "react-toastify";
import { useTranslation } from "react-i18next";
import { Namespaces } from "../../../i18n/i18n";
import { useForm } from "../../../components/common/useForm"; import { useForm } from "../../../components/common/useForm";
import { InputType } from "../../../components/common/Input"; import { InputType } from "../../../components/common/Input";
import { MakeGeneralIdRef } from "../../../utils/GeneralIdRef"; import { MakeGeneralIdRef } from "../../../utils/GeneralIdRef";
@ -18,12 +20,13 @@ const FormsDetails: React.FC<{ editMode?: boolean }> = ({
editMode = false, editMode = false,
}) => { }) => {
const { formId } = useParams<{ formId: string }>(); const { formId } = useParams<{ formId: string }>();
const { t } = useTranslation<typeof Namespaces.Common>();
const labelName = "Name"; const labelName = t("Name");
const labelDefinition = "Definition"; const labelDefinition = t("Definition");
const labelApply = "Save"; const labelApply = t("Save");
const labelSave = "Save and close"; const labelSave = t("SaveAndClose");
const form = useForm({ const form = useForm({
loaded: false, loaded: false,
@ -80,12 +83,12 @@ const FormsDetails: React.FC<{ editMode?: boolean }> = ({
definitionStr, definitionStr,
); );
if (response) { if (response) {
toast.info("Form template edited"); toast.info(t("FormTemplateEdited"));
} }
} else { } else {
const response = await formsService.postForm(nameStr, definitionStr); const response = await formsService.postForm(nameStr, definitionStr);
if (response) { if (response) {
toast.info("New Form Template added"); toast.info(t("NewFormTemplateAdded"));
} }
} }
@ -102,12 +105,14 @@ const FormsDetails: React.FC<{ editMode?: boolean }> = ({
const { loaded, redirect } = form.state; const { loaded, redirect } = form.state;
if (redirect) return <Navigate to={redirect} />; if (redirect) return <Navigate to={redirect} />;
let mode = "Add"; let mode = t("Add");
if (editMode) mode = "Edit"; if (editMode) mode = t("Edit");
return ( return (
<Loading loaded={loaded}> <Loading loaded={loaded}>
<h1>{mode} Form Template</h1> <h1>
{mode} {t("FormTemplate")}
</h1>
<form onSubmit={handleSubmit}> <form onSubmit={handleSubmit}>
{renderError("_general", form.state.errors)} {renderError("_general", form.state.errors)}
{renderInput( {renderInput(

View File

@ -1,5 +1,6 @@
import React, { useMemo } from "react"; import React, { useMemo } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Namespaces } from "../../../../i18n/i18n";
import Column from "../../../../components/common/columns"; import Column from "../../../../components/common/columns";
import Table, { import Table, {
PublishedTableProps, PublishedTableProps,
@ -15,7 +16,7 @@ const FormsTable: React.FC<PublishedTableProps<GetFormResponse>> = ({
onDelete, onDelete,
onSort, onSort,
}) => { }) => {
const { t } = useTranslation(); const { t } = useTranslation<typeof Namespaces.Common>();
const columns: Column<GetFormResponse>[] = useMemo( const columns: Column<GetFormResponse>[] = useMemo(
() => [ () => [

View File

@ -2,6 +2,8 @@ import Joi from "joi";
import React, { useEffect } from "react"; import React, { useEffect } from "react";
import { Navigate, useParams } from "react-router-dom"; import { Navigate, useParams } from "react-router-dom";
import { toast } from "react-toastify"; import { toast } from "react-toastify";
import { useTranslation } from "react-i18next";
import { Namespaces } from "../../../i18n/i18n";
import { useForm } from "../../../components/common/useForm"; import { useForm } from "../../../components/common/useForm";
import { InputType } from "../../../components/common/Input"; import { InputType } from "../../../components/common/Input";
import { GeneralIdRef, MakeGeneralIdRef } from "../../../utils/GeneralIdRef"; import { GeneralIdRef, MakeGeneralIdRef } from "../../../utils/GeneralIdRef";
@ -28,12 +30,13 @@ const GlossariesDetails: React.FC<GlossariesDetailsProps> = ({
editMode = false, editMode = false,
}) => { }) => {
const { glossaryId } = useParams<{ glossaryId: string }>(); const { glossaryId } = useParams<{ glossaryId: string }>();
const { t } = useTranslation<typeof Namespaces.Common>();
const labelName = "Name"; const labelName = t("Name");
const labelChildCustomFieldDefinition = "Custom field for child entries"; const labelChildCustomFieldDefinition = t("CustomFieldForChildEntries");
const labelApply = "Save"; const labelApply = t("Save");
const labelSave = "Save and close"; const labelSave = t("SaveAndClose");
const form = useForm({ const form = useForm({
loaded: false, loaded: false,
@ -159,7 +162,7 @@ const GlossariesDetails: React.FC<GlossariesDetailsProps> = ({
customfieldValues, customfieldValues,
); );
if (response) { if (response) {
toast.info("Glossary Item edited"); toast.info(t("GlossaryItemEdited"));
} }
} else { } else {
const generalIdRef = parentGlossary const generalIdRef = parentGlossary
@ -172,7 +175,7 @@ const GlossariesDetails: React.FC<GlossariesDetailsProps> = ({
customfieldValues, customfieldValues,
); );
if (response) { if (response) {
toast.info("New Glossary Item added"); toast.info(t("NewGlossaryItemAdded"));
} }
} }
@ -191,8 +194,8 @@ const GlossariesDetails: React.FC<GlossariesDetailsProps> = ({
const { loaded, redirect, data } = form.state; const { loaded, redirect, data } = form.state;
if (redirect) return <Navigate to={redirect} />; if (redirect) return <Navigate to={redirect} />;
let mode = "Add"; let mode = t("Add");
if (editMode) mode = "Edit"; if (editMode) mode = t("Edit");
const parentGlossary = data.parent as Glossary | undefined; const parentGlossary = data.parent as Glossary | undefined;
const handleCustomFieldChange = ( const handleCustomFieldChange = (
@ -223,7 +226,9 @@ const GlossariesDetails: React.FC<GlossariesDetailsProps> = ({
return ( return (
<Loading loaded={loaded}> <Loading loaded={loaded}>
<h1>{mode} Glossary Item</h1> <h1>
{mode} {t("GlossaryItem")}
</h1>
<form onSubmit={handleSubmit}> <form onSubmit={handleSubmit}>
{renderError("_general", form.state.errors)} {renderError("_general", form.state.errors)}
{renderInput( {renderInput(

View File

@ -1,6 +1,7 @@
import React, { useCallback, useEffect, useState } from "react"; import React, { useCallback, useEffect, useState } from "react";
import { Link, useParams } from "react-router-dom"; import { Link, useParams } from "react-router-dom";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Namespaces } from "../../../i18n/i18n";
import { MakeGeneralIdRef } from "../../../utils/GeneralIdRef"; import { MakeGeneralIdRef } from "../../../utils/GeneralIdRef";
import GlossariesTable from "./components/GlossariesTable"; import GlossariesTable from "./components/GlossariesTable";
import glossariesService, { import glossariesService, {
@ -13,7 +14,7 @@ import Loading from "../../../components/common/Loading";
import Permission from "../../../components/common/Permission"; import Permission from "../../../components/common/Permission";
const Glossaries: React.FC = () => { const Glossaries: React.FC = () => {
const { t } = useTranslation(); const { t } = useTranslation<typeof Namespaces.Common>();
const { glossaryId } = useParams<{ glossaryId: string }>(); const { glossaryId } = useParams<{ glossaryId: string }>();
const [loaded, setLoaded] = useState(false); const [loaded, setLoaded] = useState(false);

View File

@ -1,5 +1,6 @@
import React, { useState, useEffect, useMemo } from "react"; import React, { useState, useEffect, useMemo } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Namespaces } from "../../../../i18n/i18n";
import Column from "../../../../components/common/columns"; import Column from "../../../../components/common/columns";
import Table from "../../../../components/common/Table"; import Table from "../../../../components/common/Table";
import { Glossary } from "../services/glossaryService"; import { Glossary } from "../services/glossaryService";
@ -22,7 +23,7 @@ const GlossariesTable: React.FC<GlossariesTableProps> = ({
data, data,
onDelete, onDelete,
}) => { }) => {
const { t } = useTranslation(); const { t } = useTranslation<typeof Namespaces.Common>();
const [columnsList, setColumnsList] = useState<CustomColumn[]>([]); const [columnsList, setColumnsList] = useState<CustomColumn[]>([]);

View File

@ -1,6 +1,5 @@
import { useCallback, useEffect, useState } from "react"; import { useCallback, useEffect, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";import { Namespaces } from "../../../i18n/i18n";import Button, { ButtonType } from "../../../components/common/Button";
import Button, { ButtonType } from "../../../components/common/Button";
import Column from "../../../components/common/columns"; import Column from "../../../components/common/columns";
import Permission from "../../../components/common/Permission"; import Permission from "../../../components/common/Permission";
import { Paginated } from "../../../services/Paginated"; import { Paginated } from "../../../services/Paginated";
@ -11,7 +10,7 @@ import organisationsService, {
import Loading from "../../../components/common/Loading"; import Loading from "../../../components/common/Loading";
const Organisations: React.FC = () => { const Organisations: React.FC = () => {
const { t } = useTranslation(); const { t } = useTranslation<typeof Namespaces.Common>();
const [loaded, setLoaded] = useState(false); const [loaded, setLoaded] = useState(false);
const [pagedData, setPagedData] = useState<Paginated<ReadOrganisation>>({ const [pagedData, setPagedData] = useState<Paginated<ReadOrganisation>>({
page: 1, page: 1,

View File

@ -2,6 +2,8 @@ import Joi from "joi";
import React, { useEffect } from "react"; import React, { useEffect } from "react";
import { Navigate, useParams } from "react-router-dom"; import { Navigate, useParams } from "react-router-dom";
import { toast } from "react-toastify"; import { toast } from "react-toastify";
import { useTranslation } from "react-i18next";
import { Namespaces } from "../../../i18n/i18n";
import { useForm } from "../../../components/common/useForm"; import { useForm } from "../../../components/common/useForm";
import { InputType } from "../../../components/common/Input"; import { InputType } from "../../../components/common/Input";
import { MakeGeneralIdRef } from "../../../utils/GeneralIdRef"; import { MakeGeneralIdRef } from "../../../utils/GeneralIdRef";
@ -19,18 +21,19 @@ const OrganisationsDetails: React.FC<{ editMode?: boolean }> = ({
editMode = false, editMode = false,
}) => { }) => {
const { organisationId } = useParams<{ organisationId: string }>(); const { organisationId } = useParams<{ organisationId: string }>();
const { t } = useTranslation<typeof Namespaces.Common>();
const labelName = "Name"; const labelName = t("Name");
const labelAddress = "Address"; const labelAddress = t("Address");
const labelStatus = "Status"; const labelStatus = t("Status");
const labelApply = "Save"; const labelApply = t("Save");
const labelSave = "Save and close"; const labelSave = t("SaveAndClose");
const organisationStatusOptions: Option[] = [ const organisationStatusOptions: Option[] = [
{ _id: "Active", name: "Active" }, { _id: "Active", name: t("Active") },
{ _id: "Pending", name: "Pending" }, { _id: "Pending", name: t("Pending") },
{ _id: "Blocked", name: "Blocked" }, { _id: "Blocked", name: t("Blocked") },
]; ];
const form = useForm({ const form = useForm({
@ -95,7 +98,7 @@ const OrganisationsDetails: React.FC<{ editMode?: boolean }> = ({
statusStr, statusStr,
); );
if (response) { if (response) {
toast.info("Organisation edited"); toast.info(t("OrganisationEdited"));
} }
} else { } else {
const response = await organisationsService.postOrganisation( const response = await organisationsService.postOrganisation(
@ -104,7 +107,7 @@ const OrganisationsDetails: React.FC<{ editMode?: boolean }> = ({
statusStr, statusStr,
); );
if (response) { if (response) {
toast.info("New Organisation added"); toast.info(t("NewOrganisationAdded"));
} }
} }
@ -121,12 +124,14 @@ const OrganisationsDetails: React.FC<{ editMode?: boolean }> = ({
const { loaded, redirect } = form.state; const { loaded, redirect } = form.state;
if (redirect) return <Navigate to={redirect} />; if (redirect) return <Navigate to={redirect} />;
let mode = "Add"; let mode = t("Add");
if (editMode) mode = "Edit"; if (editMode) mode = t("Edit");
return ( return (
<Loading loaded={loaded}> <Loading loaded={loaded}>
<h1>{mode} Organisation</h1> <h1>
{mode} {t("Organisation")}
</h1>
<form onSubmit={handleSubmit}> <form onSubmit={handleSubmit}>
{renderError("_general", form.state.errors)} {renderError("_general", form.state.errors)}
{renderInput( {renderInput(

View File

@ -1,5 +1,6 @@
import React, { useMemo } from "react"; import React, { useMemo } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Namespaces } from "../../../../i18n/i18n";
import Column from "../../../../components/common/columns"; import Column from "../../../../components/common/columns";
import Table, { import Table, {
PublishedTableProps, PublishedTableProps,
@ -15,7 +16,7 @@ const OrganisationsTable: React.FC<PublishedTableProps<ReadOrganisation>> = ({
onDelete, onDelete,
onSort, onSort,
}) => { }) => {
const { t } = useTranslation(); const { t } = useTranslation<typeof Namespaces.Common>();
const canViewSite = authentication.hasAccess("ViewSite"); const canViewSite = authentication.hasAccess("ViewSite");
const columns: Column<ReadOrganisation>[] = useMemo( const columns: Column<ReadOrganisation>[] = useMemo(

View File

@ -2,6 +2,8 @@ import Joi from "joi";
import React, { useEffect } from "react"; import React, { useEffect } from "react";
import { Navigate, useParams } from "react-router-dom"; import { Navigate, useParams } from "react-router-dom";
import { toast } from "react-toastify"; import { toast } from "react-toastify";
import { useTranslation } from "react-i18next";
import { Namespaces } from "../../../i18n/i18n";
import { useForm } from "../../../components/common/useForm"; import { useForm } from "../../../components/common/useForm";
import { InputType } from "../../../components/common/Input"; import { InputType } from "../../../components/common/Input";
import { import {
@ -24,15 +26,16 @@ const SequenceDetails: React.FC<SequenceDetailsProps> = ({
editMode = false, editMode = false,
}) => { }) => {
const { sequenceId } = useParams<{ sequenceId: string }>(); const { sequenceId } = useParams<{ sequenceId: string }>();
const { t } = useTranslation<typeof Namespaces.Common>();
const labelName = "Name"; const labelName = t("Name");
const labelSeed = "Seed"; const labelSeed = t("Seed");
const labelIncrement = "Increment"; const labelIncrement = t("Increment");
const labelPattern = "Pattern"; const labelPattern = t("Pattern");
const labelRolloverType = "Rollover Type"; const labelRolloverType = t("RolloverType");
const labelApply = "Save"; const labelApply = t("Save");
const labelSave = "Save and close"; const labelSave = t("SaveAndClose");
const form = useForm({ const form = useForm({
loaded: false, loaded: false,
@ -110,7 +113,7 @@ const SequenceDetails: React.FC<SequenceDetailsProps> = ({
rolloverTypeStr, rolloverTypeStr,
); );
if (response) { if (response) {
toast.info("Sequence edited"); toast.info(t("SequenceEdited"));
} }
} else { } else {
const response = await sequenceService.postSequence( const response = await sequenceService.postSequence(
@ -121,7 +124,7 @@ const SequenceDetails: React.FC<SequenceDetailsProps> = ({
rolloverTypeStr, rolloverTypeStr,
); );
if (response) { if (response) {
toast.info("New sequence added"); toast.info(t("NewSequenceAdded"));
} }
} }
@ -141,17 +144,19 @@ const SequenceDetails: React.FC<SequenceDetailsProps> = ({
if (redirect) return <Navigate to={redirect} />; if (redirect) return <Navigate to={redirect} />;
const rolloverOptions: Option[] = [ const rolloverOptions: Option[] = [
{ _id: "Continuous", name: "Continuous" }, { _id: "Continuous", name: t("Continuous") },
{ _id: "Day", name: "Day" }, { _id: "Day", name: t("Day") },
{ _id: "Month", name: "Month" }, { _id: "Month", name: t("Month") },
{ _id: "Year", name: "Year" }, { _id: "Year", name: t("Year") },
]; ];
const mode = editMode ? "Edit" : "Add"; const mode = editMode ? t("Edit") : t("Add");
return ( return (
<Loading loaded={loaded}> <Loading loaded={loaded}>
<h1>{mode} Sequence</h1> <h1>
{mode} {t("Sequence")}
</h1>
<form onSubmit={handleSubmit}> <form onSubmit={handleSubmit}>
{renderError("_general", form.state.errors)} {renderError("_general", form.state.errors)}
{renderInput( {renderInput(

View File

@ -1,5 +1,6 @@
import React, { useMemo } from "react"; import React, { useMemo } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Namespaces } from "../../../../i18n/i18n";
import Column from "../../../../components/common/columns"; import Column from "../../../../components/common/columns";
import Table, { import Table, {
PublishedTableProps, PublishedTableProps,
@ -15,7 +16,7 @@ const SequenceTable: React.FC<PublishedTableProps<ReadSequence>> = ({
onDelete, onDelete,
onSort, onSort,
}) => { }) => {
const { t } = useTranslation(); const { t } = useTranslation<typeof Namespaces.Common>();
const columns: Column<ReadSequence>[] = useMemo( const columns: Column<ReadSequence>[] = useMemo(
() => [{ key: "name", label: t("Name"), order: "asc" }], () => [{ key: "name", label: t("Name"), order: "asc" }],

View File

@ -1,5 +1,6 @@
import React, { useCallback, useEffect, useState } from "react"; import React, { useCallback, useEffect, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Namespaces } from "../../../i18n/i18n";
import sequenceService, { ReadSequence } from "./services/sequenceService"; import sequenceService, { ReadSequence } from "./services/sequenceService";
import SequenceTable from "./components/squenceTable"; import SequenceTable from "./components/squenceTable";
import Column from "../../../components/common/columns"; import Column from "../../../components/common/columns";
@ -9,7 +10,7 @@ import Loading from "../../../components/common/Loading";
import Permission from "../../../components/common/Permission"; import Permission from "../../../components/common/Permission";
const Sequence: React.FC = () => { const Sequence: React.FC = () => {
const { t } = useTranslation(); const { t } = useTranslation<typeof Namespaces.Common>();
const [loaded, setLoaded] = useState(false); const [loaded, setLoaded] = useState(false);
const [pagedData, setPagedData] = useState<Paginated<ReadSequence>>({ const [pagedData, setPagedData] = useState<Paginated<ReadSequence>>({
page: 1, page: 1,

View File

@ -2,6 +2,8 @@ import Joi from "joi";
import React, { useEffect } from "react"; import React, { useEffect } from "react";
import { Navigate, useParams } from "react-router-dom"; import { Navigate, useParams } from "react-router-dom";
import { toast } from "react-toastify"; import { toast } from "react-toastify";
import { useTranslation } from "react-i18next";
import { Namespaces } from "../../../i18n/i18n";
import { useForm } from "../../../components/common/useForm"; import { useForm } from "../../../components/common/useForm";
import { InputType } from "../../../components/common/Input"; import { InputType } from "../../../components/common/Input";
import { import {
@ -24,13 +26,14 @@ const SiteDetails: React.FC<SiteDetailsProps> = ({ editMode = false }) => {
organisationId: string; organisationId: string;
siteId?: string; siteId?: string;
}>(); }>();
const { t } = useTranslation<typeof Namespaces.Common>();
const labelName = "Name"; const labelName = t("Name");
const labelAddress = "Address"; const labelAddress = t("Address");
const labelStatus = "Status"; const labelStatus = t("Status");
const labelApply = "Save"; const labelApply = t("Save");
const labelSave = "Save and close"; const labelSave = t("SaveAndClose");
const form = useForm({ const form = useForm({
loaded: false, loaded: false,
@ -98,7 +101,7 @@ const SiteDetails: React.FC<SiteDetailsProps> = ({ editMode = false }) => {
organisationGeneralIdRef, organisationGeneralIdRef,
); );
if (response) { if (response) {
toast.info("Site edited"); toast.info(t("SiteEdited"));
} }
} else { } else {
const response = await siteService.postSite( const response = await siteService.postSite(
@ -108,7 +111,7 @@ const SiteDetails: React.FC<SiteDetailsProps> = ({ editMode = false }) => {
organisationGeneralIdRef, organisationGeneralIdRef,
); );
if (response) { if (response) {
toast.info("New site added"); toast.info(t("NewSiteAdded"));
} }
} }
@ -128,16 +131,18 @@ const SiteDetails: React.FC<SiteDetailsProps> = ({ editMode = false }) => {
if (redirect) return <Navigate to={redirect} />; if (redirect) return <Navigate to={redirect} />;
const organisationStatusOptions: Option[] = [ const organisationStatusOptions: Option[] = [
{ _id: "Active", name: "Active" }, { _id: "Active", name: t("Active") },
{ _id: "Pending", name: "Pending" }, { _id: "Pending", name: t("Pending") },
{ _id: "Blocked", name: "Blocked" }, { _id: "Blocked", name: t("Blocked") },
]; ];
const mode = editMode ? "Edit" : "Add"; const mode = editMode ? t("Edit") : t("Add");
return ( return (
<Loading loaded={loaded}> <Loading loaded={loaded}>
<h1>{mode} Site</h1> <h1>
{mode} {t("Site")}
</h1>
<form onSubmit={handleSubmit}> <form onSubmit={handleSubmit}>
{renderError("_general", form.state.errors)} {renderError("_general", form.state.errors)}
{renderInput( {renderInput(

View File

@ -1,5 +1,6 @@
import React, { useCallback, useEffect, useMemo, useState } from "react"; import React, { useCallback, useEffect, useMemo, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Namespaces } from "../../../i18n/i18n";
import { useParams } from "react-router-dom"; import { useParams } from "react-router-dom";
import Column from "../../../components/common/columns"; import Column from "../../../components/common/columns";
import { Paginated } from "../../../services/Paginated"; import { Paginated } from "../../../services/Paginated";
@ -18,7 +19,7 @@ const initialPagedData: Paginated<ReadSite> = {
}; };
const Sites: React.FC = () => { const Sites: React.FC = () => {
const { t } = useTranslation(); const { t } = useTranslation<typeof Namespaces.Common>();
const { organisationId } = useParams<{ organisationId: string }>(); const { organisationId } = useParams<{ organisationId: string }>();
const [loaded, setLoaded] = useState(false); const [loaded, setLoaded] = useState(false);

View File

@ -1,5 +1,6 @@
import React, { useMemo } from "react"; import React, { useMemo } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Namespaces } from "../../../../i18n/i18n";
import Column from "../../../../components/common/columns"; import Column from "../../../../components/common/columns";
import Table, { import Table, {
PublishedTableProps, PublishedTableProps,
@ -16,7 +17,7 @@ const SitesTable: React.FC<PublishedTableProps<ReadSite>> = ({
onDelete, onDelete,
onSort, onSort,
}) => { }) => {
const { t } = useTranslation(); const { t } = useTranslation<typeof Namespaces.Common>();
const columns: Column<ReadSite>[] = useMemo( const columns: Column<ReadSite>[] = useMemo(
() => [ () => [

View File

@ -1,5 +1,6 @@
import React, { useCallback, useEffect, useMemo, useState } from "react"; import React, { useCallback, useEffect, useMemo, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Namespaces } from "../../../i18n/i18n";
import { useParams } from "react-router-dom"; import { useParams } from "react-router-dom";
import Column from "../../../components/common/columns"; import Column from "../../../components/common/columns";
import { Paginated } from "../../../services/Paginated"; import { Paginated } from "../../../services/Paginated";
@ -20,7 +21,7 @@ const initialPagedData: Paginated<ReadSpecification> = {
}; };
const Specifications: React.FC = () => { const Specifications: React.FC = () => {
const { t } = useTranslation(); const { t } = useTranslation<typeof Namespaces.Common>();
const { siteId } = useParams<{ siteId: string }>(); const { siteId } = useParams<{ siteId: string }>();
const [loaded, setLoaded] = useState(false); const [loaded, setLoaded] = useState(false);

View File

@ -2,6 +2,8 @@ import Joi from "joi";
import React, { useEffect, useRef, useState, useCallback } from "react"; import React, { useEffect, useRef, useState, useCallback } from "react";
import { Navigate, useParams } from "react-router-dom"; import { Navigate, useParams } from "react-router-dom";
import { toast } from "react-toastify"; import { toast } from "react-toastify";
import { useTranslation } from "react-i18next";
import { Namespaces } from "../../../i18n/i18n";
import { useForm } from "../../../components/common/useForm"; import { useForm } from "../../../components/common/useForm";
import { InputType } from "../../../components/common/Input"; import { InputType } from "../../../components/common/Input";
import Loading from "../../../components/common/Loading"; import Loading from "../../../components/common/Loading";
@ -33,13 +35,14 @@ const SpecificationsDetails: React.FC<SpecificationsDetailsProps> = ({
siteId: string; siteId: string;
specificationId?: string; specificationId?: string;
}>(); }>();
const { t } = useTranslation<typeof Namespaces.Common>();
const TemplateFillerRef = useRef<TemplateFillerHandle>(null); const TemplateFillerRef = useRef<TemplateFillerHandle>(null);
const labelName = "Name"; const labelName = t("Name");
const labelPrintSpecification = "Print Specification"; const labelPrintSpecification = t("PrintSpecification");
const labelSigmaId = "SigmaId"; const labelSigmaId = t("SigmaId");
const labelApply = "Save"; const labelApply = t("Save");
const labelSave = "Save and close"; const labelSave = t("SaveAndClose");
const form = useForm({ const form = useForm({
loaded: false, loaded: false,
@ -173,12 +176,12 @@ const SpecificationsDetails: React.FC<SpecificationsDetailsProps> = ({
sigmaIdValue, sigmaIdValue,
); );
if (response) { if (response) {
toast.info("Specifications edited"); toast.info(t("SpecificationsEdited"));
} }
} else { } else {
const newFormInstanceId = await templateFiller.Save(); const newFormInstanceId = await templateFiller.Save();
if (!newFormInstanceId) { if (!newFormInstanceId) {
toast.error("Failed to save form instance"); toast.error(t("FailedToSaveFormInstance"));
return; return;
} }
@ -189,7 +192,7 @@ const SpecificationsDetails: React.FC<SpecificationsDetailsProps> = ({
sigmaIdValue, sigmaIdValue,
); );
if (response) { if (response) {
toast.info("New Specifications added"); toast.info(t("NewSpecificationsAdded"));
} }
} }
@ -210,11 +213,13 @@ const SpecificationsDetails: React.FC<SpecificationsDetailsProps> = ({
const { loaded, redirect } = form.state; const { loaded, redirect } = form.state;
if (redirect && redirect !== "") return <Navigate to={redirect} />; if (redirect && redirect !== "") return <Navigate to={redirect} />;
const mode = isEditMode() ? "Edit" : "Add"; const mode = isEditMode() ? t("Edit") : t("Add");
return ( return (
<Loading loaded={loaded}> <Loading loaded={loaded}>
<h1>{mode} Specifications</h1> <h1>
{mode} {t("Specifications")}
</h1>
<form onSubmit={handleSubmit}> <form onSubmit={handleSubmit}>
{renderError("_general", form.state.errors)} {renderError("_general", form.state.errors)}
{renderInput( {renderInput(

View File

@ -1,5 +1,6 @@
import React, { useMemo } from "react"; import React, { useMemo } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Namespaces } from "../../../../i18n/i18n";
import Column from "../../../../components/common/columns"; import Column from "../../../../components/common/columns";
import Table, { import Table, {
PublishedTableProps, PublishedTableProps,
@ -15,7 +16,7 @@ const SpecificationsTable: React.FC<PublishedTableProps<ReadSpecification>> = ({
onDelete, onDelete,
onSort, onSort,
}) => { }) => {
const { t } = useTranslation(); const { t } = useTranslation<typeof Namespaces.Common>();
const columns: Column<ReadSpecification>[] = useMemo( const columns: Column<ReadSpecification>[] = useMemo(
() => [{ key: "name", label: t("Name"), order: "asc" }], () => [{ key: "name", label: t("Name"), order: "asc" }],

View File

@ -2,6 +2,8 @@ import Joi from "joi";
import React, { useEffect } from "react"; import React, { useEffect } from "react";
import { Navigate, useParams, useLocation } from "react-router-dom"; import { Navigate, useParams, useLocation } from "react-router-dom";
import { toast } from "react-toastify"; import { toast } from "react-toastify";
import { useTranslation } from "react-i18next";
import { Namespaces } from "../../../i18n/i18n";
import { useForm } from "../../../components/common/useForm"; import { useForm } from "../../../components/common/useForm";
import { InputType } from "../../../components/common/Input"; import { InputType } from "../../../components/common/Input";
import { import {
@ -22,17 +24,18 @@ const SsoProviderDetails: React.FC<SsoProviderDetailsProps> = ({
}) => { }) => {
const { ssoProviderId } = useParams<{ ssoProviderId: string }>(); const { ssoProviderId } = useParams<{ ssoProviderId: string }>();
const location = useLocation(); const location = useLocation();
const { t } = useTranslation<typeof Namespaces.Common>();
const labelName = "Name"; const labelName = t("Name");
const labelClientId = "Client Id"; const labelClientId = t("ClientId");
const labelClientSecret = "Client Secret"; const labelClientSecret = t("ClientSecret");
const labelValidIssuer = "Valid Issuer"; const labelValidIssuer = t("ValidIssuer");
const labelAuthorizationEndpoint = "Authorisation Endpoint"; const labelAuthorizationEndpoint = t("AuthorizationEndpoint");
const labelTokenEndpoint = "Token Endpoint"; const labelTokenEndpoint = t("TokenEndpoint");
const labelIsPublic = "Is Public"; const labelIsPublic = t("IsPublic");
const labelApply = "Save"; const labelApply = t("Save");
const labelSave = "Save and close"; const labelSave = t("SaveAndClose");
const form = useForm({ const form = useForm({
loaded: false, loaded: false,
@ -132,7 +135,7 @@ const SsoProviderDetails: React.FC<SsoProviderDetailsProps> = ({
isPublicValue, isPublicValue,
); );
if (response) { if (response) {
toast.info("Sso Provider edited"); toast.info(t("SsoProviderEdited"));
} }
} else { } else {
const response = await ssoManagerService.postSsoProvider( const response = await ssoManagerService.postSsoProvider(
@ -145,7 +148,7 @@ const SsoProviderDetails: React.FC<SsoProviderDetailsProps> = ({
isPublicValue, isPublicValue,
); );
if (response) { if (response) {
toast.info("New Sso Provider added"); toast.info(t("NewSsoProviderAdded"));
} }
} }
@ -164,7 +167,7 @@ const SsoProviderDetails: React.FC<SsoProviderDetailsProps> = ({
const { loaded, redirect } = form.state; const { loaded, redirect } = form.state;
if (redirect) return <Navigate to={redirect} />; if (redirect) return <Navigate to={redirect} />;
const mode = editMode ? "Edit" : "Add"; const mode = editMode ? t("Edit") : t("Add");
const redirectUrl = const redirectUrl =
window.location.href.slice( window.location.href.slice(
0, 0,
@ -175,7 +178,9 @@ const SsoProviderDetails: React.FC<SsoProviderDetailsProps> = ({
return ( return (
<Loading loaded={loaded}> <Loading loaded={loaded}>
<h1>{mode} Sso Provider</h1> <h1>
{mode} {t("SsoProvider")}
</h1>
<form onSubmit={handleSubmit}> <form onSubmit={handleSubmit}>
{renderError("_general", form.state.errors)} {renderError("_general", form.state.errors)}
{renderInput( {renderInput(

View File

@ -1,5 +1,6 @@
import React, { useMemo } from "react"; import React, { useMemo } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Namespaces } from "../../../../i18n/i18n";
import Column from "../../../../components/common/columns"; import Column from "../../../../components/common/columns";
import Table, { import Table, {
PublishedTableProps, PublishedTableProps,
@ -15,7 +16,7 @@ const SsoManagerTable: React.FC<PublishedTableProps<GetSsoProvider>> = ({
onDelete, onDelete,
onSort, onSort,
}) => { }) => {
const { t } = useTranslation(); const { t } = useTranslation<typeof Namespaces.Common>();
const columns: Column<GetSsoProvider>[] = useMemo( const columns: Column<GetSsoProvider>[] = useMemo(
() => [{ key: "name", label: t("Name"), order: "asc" }], () => [{ key: "name", label: t("Name"), order: "asc" }],

View File

@ -1,5 +1,6 @@
import React, { useCallback, useEffect, useState } from "react"; import React, { useCallback, useEffect, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Namespaces } from "../../../i18n/i18n";
import Column from "../../../components/common/columns"; import Column from "../../../components/common/columns";
import { Paginated } from "../../../services/Paginated"; import { Paginated } from "../../../services/Paginated";
import SsoManagerTable from "./components/ssoManagerTable"; import SsoManagerTable from "./components/ssoManagerTable";
@ -11,7 +12,7 @@ import Loading from "../../../components/common/Loading";
import Permission from "../../../components/common/Permission"; import Permission from "../../../components/common/Permission";
const SsoManager: React.FC = () => { const SsoManager: React.FC = () => {
const { t } = useTranslation(); const { t } = useTranslation<typeof Namespaces.Common>();
const [loaded, setLoaded] = useState(false); const [loaded, setLoaded] = useState(false);
const [pagedData, setPagedData] = useState<Paginated<GetSsoProvider>>({ const [pagedData, setPagedData] = useState<Paginated<GetSsoProvider>>({
page: 1, page: 1,

View File

@ -1,5 +1,6 @@
import React from "react"; import React from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Namespaces } from "../../../i18n/i18n";
import HorizontalTabs from "../../../components/common/HorizionalTabs"; import HorizontalTabs from "../../../components/common/HorizionalTabs";
import Tab from "../../../components/common/Tab"; import Tab from "../../../components/common/Tab";
import GeneralTab from "./components/GeneralTab"; import GeneralTab from "./components/GeneralTab";
@ -9,7 +10,7 @@ interface UserDetailsProps {
} }
const UserDetails: React.FC<UserDetailsProps> = ({ editMode }) => { const UserDetails: React.FC<UserDetailsProps> = ({ editMode }) => {
const { t } = useTranslation(); const { t } = useTranslation<typeof Namespaces.Common>();
const heading = editMode ? t("EditUser") : t("AddUser"); const heading = editMode ? t("EditUser") : t("AddUser");

View File

@ -2,6 +2,8 @@ import Joi from "joi";
import React, { useEffect } from "react"; import React, { useEffect } from "react";
import { Navigate, useParams } from "react-router-dom"; import { Navigate, useParams } from "react-router-dom";
import { toast } from "react-toastify"; import { toast } from "react-toastify";
import { useTranslation } from "react-i18next";
import { Namespaces } from "../../../../i18n/i18n";
import { useForm } from "../../../../components/common/useForm"; import { useForm } from "../../../../components/common/useForm";
import { InputType } from "../../../../components/common/Input"; import { InputType } from "../../../../components/common/Input";
import { GeneralIdRef, MakeGeneralIdRef } from "../../../../utils/GeneralIdRef"; import { GeneralIdRef, MakeGeneralIdRef } from "../../../../utils/GeneralIdRef";
@ -22,15 +24,16 @@ interface GeneralTabProps {
const GeneralTab: React.FC<GeneralTabProps> = ({ isEditMode }) => { const GeneralTab: React.FC<GeneralTabProps> = ({ isEditMode }) => {
const { userId } = useParams<{ userId: string }>(); const { userId } = useParams<{ userId: string }>();
const { t } = useTranslation<typeof Namespaces.Common>();
const labelFirstName = "First name"; const labelFirstName = t("FirstName");
const labelMiddleNames = "Middle names"; const labelMiddleNames = t("MiddleNames");
const labelLastName = "Last name"; const labelLastName = t("LastName");
const labelEmail = "Mail"; const labelEmail = t("Mail");
const labelDomain = "Domain"; const labelDomain = t("Domain");
const labelApply = "Save"; const labelApply = t("Save");
const labelSave = "Save and close"; const labelSave = t("SaveAndClose");
const form = useForm({ const form = useForm({
loaded: false, loaded: false,
@ -110,7 +113,7 @@ const GeneralTab: React.FC<GeneralTabProps> = ({ isEditMode }) => {
domainValue, domainValue,
); );
if (response) { if (response) {
toast.info("User edited"); toast.info(t("UserEdited"));
} }
} else { } else {
const response = await userService.postUser( const response = await userService.postUser(
@ -121,7 +124,7 @@ const GeneralTab: React.FC<GeneralTabProps> = ({ isEditMode }) => {
domainValue, domainValue,
); );
if (response) { if (response) {
toast.info("New User added"); toast.info(t("NewUserAdded"));
} }
} }

View File

@ -1,5 +1,6 @@
import React, { useCallback, useMemo } from "react"; import React, { useCallback, useMemo } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Namespaces } from "../../../../i18n/i18n";
import Column from "../../../../components/common/columns"; import Column from "../../../../components/common/columns";
import Table, { import Table, {
PublishedTableProps, PublishedTableProps,
@ -23,7 +24,7 @@ const UsersTable: React.FC<UsersTableProps> = ({
onSort, onSort,
resendConfirmEmail, resendConfirmEmail,
}) => { }) => {
const { t } = useTranslation(); const { t } = useTranslation<typeof Namespaces.Common>();
const canResendConfirmMail = authentication.hasAccess("ResendConfirmMail"); const canResendConfirmMail = authentication.hasAccess("ResendConfirmMail");
const resendConfirmEmailHandler = useCallback( const resendConfirmEmailHandler = useCallback(

View File

@ -1,5 +1,6 @@
import React, { useCallback, useEffect, useState } from "react"; import React, { useCallback, useEffect, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Namespaces } from "../../../i18n/i18n";
import Column from "../../../components/common/columns"; import Column from "../../../components/common/columns";
import { Paginated } from "../../../services/Paginated"; import { Paginated } from "../../../services/Paginated";
import UsersTable from "./components/usersTable"; import UsersTable from "./components/usersTable";
@ -10,7 +11,7 @@ import Loading from "../../../components/common/Loading";
import Permission from "../../../components/common/Permission"; import Permission from "../../../components/common/Permission";
const Users: React.FC = () => { const Users: React.FC = () => {
const { t } = useTranslation(); const { t } = useTranslation<typeof Namespaces.Common>();
const [loaded, setLoaded] = useState(false); const [loaded, setLoaded] = useState(false);
const [pagedData, setPagedData] = useState<Paginated<GetUser>>({ const [pagedData, setPagedData] = useState<Paginated<GetUser>>({
page: 1, page: 1,

View File

@ -1,6 +1,8 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import Joi from "joi"; import Joi from "joi";
import { toast } from "react-toastify"; import { toast } from "react-toastify";
import { useTranslation } from "react-i18next";
import { Namespaces } from "../../i18n/i18n";
import { useForm } from "../../components/common/useForm"; import { useForm } from "../../components/common/useForm";
import profileService from "./services/profileService"; import profileService from "./services/profileService";
import { InputType } from "../../components/common/Input"; import { InputType } from "../../components/common/Input";
@ -15,15 +17,17 @@ import {
} from "../../components/common/formHelpers"; } from "../../components/common/formHelpers";
const Profile: React.FC = () => { const Profile: React.FC = () => {
const labelFirstName = "First Name"; const { t } = useTranslation<typeof Namespaces.Common>();
const labelMiddleNames = "Middle Name(s)";
const labelLastName = "Last Name"; const labelFirstName = t("FirstName");
const labelEmail = "E-Mail"; const labelMiddleNames = t("MiddleNames");
const labelNewPassword = "New Password"; const labelLastName = t("LastName");
const labelConfirmPassword = "Confirm Password"; const labelEmail = t("Email");
const labelUsingTwoFactorAuthentication = "2 Factor Authentication"; const labelNewPassword = t("NewPassword");
const labelTfaCode = "Authentication code"; const labelConfirmPassword = t("ConfirmPassword");
const labelApply = "Save"; const labelUsingTwoFactorAuthentication = t("TwoFactorAuthentication");
const labelTfaCode = t("AuthenticationCode");
const labelApply = t("Save");
const [twoFactorAuthenticationSettings, setTwoFactorAuthenticationSettings] = const [twoFactorAuthenticationSettings, setTwoFactorAuthenticationSettings] =
useState<TwoFactorAuthenticationSettings>({ useState<TwoFactorAuthenticationSettings>({
@ -157,7 +161,7 @@ const Profile: React.FC = () => {
); );
if (response) { if (response) {
await loadProfile(); await loadProfile();
toast.info("Your profile settings have been saved"); toast.info(t("YourProfileSettingsHaveBeenSaved"));
} }
} catch (ex: any) { } catch (ex: any) {
form.handleGeneralError(ex); form.handleGeneralError(ex);
@ -172,7 +176,9 @@ const Profile: React.FC = () => {
const { usingTwoFactorAuthentication, newPassword } = form.state.data; const { usingTwoFactorAuthentication, newPassword } = form.state.data;
const passwordMaxLength = 255; const passwordMaxLength = 255;
const tfaEnabled = usingTwoFactorAuthentication ? "Enabled" : "Disabled"; const tfaEnabled = usingTwoFactorAuthentication
? t("Enabled")
: t("Disabled");
let tfaImageBlock = null; let tfaImageBlock = null;
if (twoFactorAuthenticationSettings) if (twoFactorAuthenticationSettings)
@ -268,7 +274,7 @@ const Profile: React.FC = () => {
return ( return (
<Loading loaded={loaded}> <Loading loaded={loaded}>
<h1>Profile</h1> <h1>{t("Profile")}</h1>
<form onSubmit={handleSubmit}> <form onSubmit={handleSubmit}>
{renderError("_general", form.state.errors)} {renderError("_general", form.state.errors)}
{renderInput( {renderInput(