diff --git a/packages/apps/esm-implementer-tools-app/translations/bn.json b/packages/apps/esm-implementer-tools-app/translations/bn.json new file mode 100644 index 000000000..84858b265 --- /dev/null +++ b/packages/apps/esm-implementer-tools-app/translations/bn.json @@ -0,0 +1,31 @@ +{ + "activeItemSourceText": "The current value comes from ", + "backendModules": "Backend modules", + "checkImplementerToolsMessage": "Check the Backend Modules tab in the Implementer Tools for more details", + "clearConfig": "Clear local config", + "close": "Close", + "configuration": "Configuration", + "description": "Description", + "downloadConfig": "Download config", + "edit": "Edit", + "editValueButtonText": "Edit", + "enabled": "Enabled", + "extensions": "Extensions", + "featureFlag": "Feature flag", + "featureFlags": "Feature flags", + "frontendModules": "Frontend modules", + "implementerTools": "Implementer Tools", + "installedVersion": "Installed version", + "itemDescriptionSourceDefaultText": "The current value is the default.", + "jsonEditor": "JSON editor", + "missing": "Missing", + "moduleName": "Module name", + "modulesWithMissingDependenciesWarning": "Some modules have unresolved backend dependencies", + "requiredVersion": "Required Version", + "resetToDefaultValueButtonText": "Reset to default", + "uiEditor": "UI editor", + "unknownVersion": "unknown", + "updateConfig": "Update config", + "value": "Value", + "viewModules": "View modules" +} diff --git a/packages/apps/esm-implementer-tools-app/translations/fr.json b/packages/apps/esm-implementer-tools-app/translations/fr.json index 88c20ca26..5ef520905 100644 --- a/packages/apps/esm-implementer-tools-app/translations/fr.json +++ b/packages/apps/esm-implementer-tools-app/translations/fr.json @@ -14,7 +14,7 @@ "featureFlag": "Fonctionnalité", "featureFlags": "Fonctionnalités", "frontendModules": "Modules du Frontend", - "implementerTools": "Implementer Tools", + "implementerTools": "Outils de mise en œuvre", "installedVersion": "Version Installée", "itemDescriptionSourceDefaultText": "Valeur courante est définié par défaut", "jsonEditor": "Editeur JSON", diff --git a/packages/apps/esm-implementer-tools-app/translations/lg.json b/packages/apps/esm-implementer-tools-app/translations/lg.json new file mode 100644 index 000000000..84858b265 --- /dev/null +++ b/packages/apps/esm-implementer-tools-app/translations/lg.json @@ -0,0 +1,31 @@ +{ + "activeItemSourceText": "The current value comes from ", + "backendModules": "Backend modules", + "checkImplementerToolsMessage": "Check the Backend Modules tab in the Implementer Tools for more details", + "clearConfig": "Clear local config", + "close": "Close", + "configuration": "Configuration", + "description": "Description", + "downloadConfig": "Download config", + "edit": "Edit", + "editValueButtonText": "Edit", + "enabled": "Enabled", + "extensions": "Extensions", + "featureFlag": "Feature flag", + "featureFlags": "Feature flags", + "frontendModules": "Frontend modules", + "implementerTools": "Implementer Tools", + "installedVersion": "Installed version", + "itemDescriptionSourceDefaultText": "The current value is the default.", + "jsonEditor": "JSON editor", + "missing": "Missing", + "moduleName": "Module name", + "modulesWithMissingDependenciesWarning": "Some modules have unresolved backend dependencies", + "requiredVersion": "Required Version", + "resetToDefaultValueButtonText": "Reset to default", + "uiEditor": "UI editor", + "unknownVersion": "unknown", + "updateConfig": "Update config", + "value": "Value", + "viewModules": "View modules" +} diff --git a/packages/apps/esm-implementer-tools-app/translations/pt_BR.json b/packages/apps/esm-implementer-tools-app/translations/pt_BR.json index 84858b265..f42002377 100644 --- a/packages/apps/esm-implementer-tools-app/translations/pt_BR.json +++ b/packages/apps/esm-implementer-tools-app/translations/pt_BR.json @@ -1,31 +1,31 @@ { - "activeItemSourceText": "The current value comes from ", - "backendModules": "Backend modules", - "checkImplementerToolsMessage": "Check the Backend Modules tab in the Implementer Tools for more details", - "clearConfig": "Clear local config", - "close": "Close", - "configuration": "Configuration", - "description": "Description", - "downloadConfig": "Download config", - "edit": "Edit", - "editValueButtonText": "Edit", - "enabled": "Enabled", - "extensions": "Extensions", - "featureFlag": "Feature flag", - "featureFlags": "Feature flags", - "frontendModules": "Frontend modules", - "implementerTools": "Implementer Tools", - "installedVersion": "Installed version", - "itemDescriptionSourceDefaultText": "The current value is the default.", - "jsonEditor": "JSON editor", - "missing": "Missing", - "moduleName": "Module name", - "modulesWithMissingDependenciesWarning": "Some modules have unresolved backend dependencies", - "requiredVersion": "Required Version", - "resetToDefaultValueButtonText": "Reset to default", - "uiEditor": "UI editor", - "unknownVersion": "unknown", - "updateConfig": "Update config", - "value": "Value", - "viewModules": "View modules" + "activeItemSourceText": "O valor atual vem de", + "backendModules": "Módulos de back-end", + "checkImplementerToolsMessage": "Verifique a guia Módulos de back-end nas Ferramentas do implementador para obter mais detalhes", + "clearConfig": "Limpar configuração local", + "close": "Fechar", + "configuration": "Configuração", + "description": "Descrição do módulo", + "downloadConfig": "Baixar configuração", + "edit": "Editar", + "editValueButtonText": "Editar", + "enabled": "Habilitado", + "extensions": "Extensões", + "featureFlag": "Alerta de recurso", + "featureFlags": "Alertas de recursos", + "frontendModules": "Módulos front-end", + "implementerTools": "Ferramentas do implementador", + "installedVersion": "Versão instalada", + "itemDescriptionSourceDefaultText": "O valor atual é o padrão.", + "jsonEditor": "Editor JSON", + "missing": "Faltando", + "moduleName": "Nome do módulo", + "modulesWithMissingDependenciesWarning": "Alguns módulos têm dependências de back-end não resolvidas", + "requiredVersion": "Versão necessária", + "resetToDefaultValueButtonText": "Redefinir para o padrão", + "uiEditor": "Editor de interface do usuário", + "unknownVersion": "desconhecido", + "updateConfig": "Atualizar configuração", + "value": "Valor", + "viewModules": "Exibir módulos" } diff --git a/packages/apps/esm-implementer-tools-app/translations/ru_RU.json b/packages/apps/esm-implementer-tools-app/translations/ru_RU.json new file mode 100644 index 000000000..84858b265 --- /dev/null +++ b/packages/apps/esm-implementer-tools-app/translations/ru_RU.json @@ -0,0 +1,31 @@ +{ + "activeItemSourceText": "The current value comes from ", + "backendModules": "Backend modules", + "checkImplementerToolsMessage": "Check the Backend Modules tab in the Implementer Tools for more details", + "clearConfig": "Clear local config", + "close": "Close", + "configuration": "Configuration", + "description": "Description", + "downloadConfig": "Download config", + "edit": "Edit", + "editValueButtonText": "Edit", + "enabled": "Enabled", + "extensions": "Extensions", + "featureFlag": "Feature flag", + "featureFlags": "Feature flags", + "frontendModules": "Frontend modules", + "implementerTools": "Implementer Tools", + "installedVersion": "Installed version", + "itemDescriptionSourceDefaultText": "The current value is the default.", + "jsonEditor": "JSON editor", + "missing": "Missing", + "moduleName": "Module name", + "modulesWithMissingDependenciesWarning": "Some modules have unresolved backend dependencies", + "requiredVersion": "Required Version", + "resetToDefaultValueButtonText": "Reset to default", + "uiEditor": "UI editor", + "unknownVersion": "unknown", + "updateConfig": "Update config", + "value": "Value", + "viewModules": "View modules" +} diff --git a/packages/apps/esm-implementer-tools-app/translations/uz.json b/packages/apps/esm-implementer-tools-app/translations/uz.json new file mode 100644 index 000000000..84858b265 --- /dev/null +++ b/packages/apps/esm-implementer-tools-app/translations/uz.json @@ -0,0 +1,31 @@ +{ + "activeItemSourceText": "The current value comes from ", + "backendModules": "Backend modules", + "checkImplementerToolsMessage": "Check the Backend Modules tab in the Implementer Tools for more details", + "clearConfig": "Clear local config", + "close": "Close", + "configuration": "Configuration", + "description": "Description", + "downloadConfig": "Download config", + "edit": "Edit", + "editValueButtonText": "Edit", + "enabled": "Enabled", + "extensions": "Extensions", + "featureFlag": "Feature flag", + "featureFlags": "Feature flags", + "frontendModules": "Frontend modules", + "implementerTools": "Implementer Tools", + "installedVersion": "Installed version", + "itemDescriptionSourceDefaultText": "The current value is the default.", + "jsonEditor": "JSON editor", + "missing": "Missing", + "moduleName": "Module name", + "modulesWithMissingDependenciesWarning": "Some modules have unresolved backend dependencies", + "requiredVersion": "Required Version", + "resetToDefaultValueButtonText": "Reset to default", + "uiEditor": "UI editor", + "unknownVersion": "unknown", + "updateConfig": "Update config", + "value": "Value", + "viewModules": "View modules" +} diff --git a/packages/apps/esm-implementer-tools-app/translations/zh_CN.json b/packages/apps/esm-implementer-tools-app/translations/zh_CN.json index 6a92323ed..d488f7956 100644 --- a/packages/apps/esm-implementer-tools-app/translations/zh_CN.json +++ b/packages/apps/esm-implementer-tools-app/translations/zh_CN.json @@ -3,7 +3,7 @@ "backendModules": "后端模块", "checkImplementerToolsMessage": "请查看Implementer 工具中的Backend模块选项卡,以获取更多详细信息。", "clearConfig": "清除本地配置", - "close": "Close", + "close": "关闭", "configuration": "配置", "description": "描述", "downloadConfig": "下载配置", @@ -11,10 +11,10 @@ "editValueButtonText": "编辑", "enabled": "启用", "extensions": "扩展", - "featureFlag": "Feature flag", - "featureFlags": "Feature flags", + "featureFlag": "功能标志", + "featureFlags": "功能标志", "frontendModules": "前端模块", - "implementerTools": "Implementer Tools", + "implementerTools": "实施者工具", "installedVersion": "已安装版本", "itemDescriptionSourceDefaultText": "当前值为默认值。", "jsonEditor": "JSON编辑器", @@ -25,7 +25,7 @@ "resetToDefaultValueButtonText": "恢复为默认值", "uiEditor": "UI编辑器", "unknownVersion": "未知", - "updateConfig": "Update config", + "updateConfig": "更新配置", "value": "值", "viewModules": "查看模块" } diff --git a/packages/apps/esm-login-app/translations/bn.json b/packages/apps/esm-login-app/translations/bn.json new file mode 100644 index 000000000..f70a740bb --- /dev/null +++ b/packages/apps/esm-login-app/translations/bn.json @@ -0,0 +1,40 @@ +{ + "builtWith": "Built with", + "cancel": "বাতিল", + "change": "পরিবর্তন", + "changePassword": "পাসওয়ার্ড পরিবর্তন", + "changingPassword": "পাসওয়ার্ড পরিবর্তন হচ্ছে", + "confirmPassword": "নতুন পাসওয়ার্ড নিশ্চিত করুন", + "continue": "এগিয়ে যান", + "errorChangingPassword": "পাসওয়ার্ড পরিবর্তনে ত্রুটি দেখা দিয়েছে", + "footerlogo": "Footer Logo", + "invalidCredentials": "ইউজারনেম অথবা পাসওয়ার্ড সঠিক নয়", + "learnMore": "আরো জানুন", + "locationPreferenceRemoved": "Login location preference removed", + "locationPreferenceRemovedMessage": "প্রতিবার লগইন এর সময় ঠিকানা বাছাই করতে হবে", + "locationSaved": "ঠিকানা জমা হয়েছে", + "locationSaveMessage": "আপনার পছন্দনীয় ঠিকানা ভবিষ্যৎ লগইনের জন্য সংরক্ষন করা হয়েছে", + "locationUpdated": "ঠিকানা হালনাগাদ হয়েছে", + "locationUpdateMessage": "Your preferred login location has been updated", + "loggingIn": "লগ ইন হচ্ছে", + "login": "লগ ইন", + "loginButtonIconDescription": "লগ ইন বাটন", + "Logout": "লগ আউট", + "newPassword": "নতুন পাসওয়ার্ড", + "newPasswordRequired": "নতুন পাসওয়ার্ড প্রয়োজনীয়", + "oldPassword": "পুরাতন পাসওয়ার্ড", + "oldPasswordRequired": "পুরাতন পাসওয়ার্ড প্রয়োজনীয়", + "openmrsLogo": "ওপেনএমআরএস এর প্রতীক", + "password": "পাসওয়ার্ড", + "passwordChangedSuccessfully": "পাসওয়ার্ড পরিবর্তন সফল", + "passwordConfirmationRequired": "পাসওয়ার্ড নিশ্চিতকরণ প্রয়োজন", + "passwordsDoNotMatch": "পাসওয়ার্ডসমূহ মিলছে না", + "poweredBySubtext": "একটি ওপেন-সোর্স মেডিক্যাল রেকর্ড সিস্টেম এবং বিশ্বব্যাপী সম্প্রদায়", + "rememberLocationForFutureLogins": "ভবিষ্যৎ লগইনের জন্য ঠিকানা সংরক্ষন করুন", + "selectYourLocation": "নিমোক্ত তালিকা থেকে ঠিকানা বাছাই করুন। ঠিকানা খুজতে হলে সার্চবার ব্যবহার করুন।", + "showPassword": "পাসওয়ার্ড প্রদর্শন করুন", + "submitting": "সাবমিট করা হচ্ছে", + "username": "ইউজারনেম", + "validValueRequired": "বৈধ মান প্রয়োজন", + "welcome": "স্বাগতম" +} diff --git a/packages/apps/esm-login-app/translations/lg.json b/packages/apps/esm-login-app/translations/lg.json new file mode 100644 index 000000000..397bb9628 --- /dev/null +++ b/packages/apps/esm-login-app/translations/lg.json @@ -0,0 +1,40 @@ +{ + "builtWith": "Built with", + "cancel": "Cancel", + "change": "Change", + "changePassword": "Change password", + "changingPassword": "Changing password", + "confirmPassword": "Confirm new password", + "continue": "Continue", + "errorChangingPassword": "Error changing password", + "footerlogo": "Footer Logo", + "invalidCredentials": "Invalid username or password", + "learnMore": "Learn more", + "locationPreferenceRemoved": "Login location preference removed", + "locationPreferenceRemovedMessage": "You will need to select a location on each login", + "locationSaved": "Location saved", + "locationSaveMessage": "Your preferred location has been saved for future logins", + "locationUpdated": "Location updated", + "locationUpdateMessage": "Your preferred login location has been updated", + "loggingIn": "Logging in", + "login": "Log in", + "loginButtonIconDescription": "Log in button", + "Logout": "Logout", + "newPassword": "New password", + "newPasswordRequired": "New password is required", + "oldPassword": "Old password", + "oldPasswordRequired": "Old password is required", + "openmrsLogo": "OpenMRS logo", + "password": "Password", + "passwordChangedSuccessfully": "Password changed successfully", + "passwordConfirmationRequired": "Password confirmation is required", + "passwordsDoNotMatch": "Passwords do not match", + "poweredBySubtext": "An open-source medical record system and global community", + "rememberLocationForFutureLogins": "Remember my location for future logins", + "selectYourLocation": "Select your location from the list below. Use the search bar to find your location.", + "showPassword": "Show password", + "submitting": "Submitting", + "username": "Username", + "validValueRequired": "A valid value is required", + "welcome": "Welcome" +} diff --git a/packages/apps/esm-login-app/translations/pt_BR.json b/packages/apps/esm-login-app/translations/pt_BR.json index 3b00af432..58082c26d 100644 --- a/packages/apps/esm-login-app/translations/pt_BR.json +++ b/packages/apps/esm-login-app/translations/pt_BR.json @@ -1,5 +1,5 @@ { - "builtWith": "Built with", + "builtWith": "Construído com", "cancel": "Cancelar", "change": "Alterar", "changePassword": "Mudar senha", @@ -9,7 +9,7 @@ "errorChangingPassword": "Erro ao alterar a senha", "footerlogo": "Logo do Rodapé", "invalidCredentials": "Usuário ou senha inválidos", - "learnMore": "Learn more", + "learnMore": "Aprender mais", "locationPreferenceRemoved": "Preferência de local de inicialização removida", "locationPreferenceRemovedMessage": "Você precisará selecionar um local em cada entrada no sistema", "locationSaved": "Local salvo", @@ -18,7 +18,7 @@ "locationUpdateMessage": "Seu local preferido de entrada foi atualizado", "loggingIn": "Autenticando", "login": "Entrar", - "loginButtonIconDescription": "Log in button", + "loginButtonIconDescription": "Botão de Entrar", "Logout": "Sair", "newPassword": "Nova senha", "newPasswordRequired": "Nova senha é obrigatória", @@ -29,7 +29,7 @@ "passwordChangedSuccessfully": "Senha alterada com sucesso", "passwordConfirmationRequired": "A confirmação da senha é obrigatória", "passwordsDoNotMatch": "As senhas não coincidem", - "poweredBySubtext": "An open-source medical record system and global community", + "poweredBySubtext": "Um sistema de registros médicos de código aberto e comunidade global", "rememberLocationForFutureLogins": "Lembrar o meu local para futuras entradas no sistema", "selectYourLocation": "Selecione seu local na lista abaixo. Use a barra de pesquisa para encontrar seu local.", "showPassword": "Mostrar senha", diff --git a/packages/apps/esm-login-app/translations/ru_RU.json b/packages/apps/esm-login-app/translations/ru_RU.json new file mode 100644 index 000000000..397bb9628 --- /dev/null +++ b/packages/apps/esm-login-app/translations/ru_RU.json @@ -0,0 +1,40 @@ +{ + "builtWith": "Built with", + "cancel": "Cancel", + "change": "Change", + "changePassword": "Change password", + "changingPassword": "Changing password", + "confirmPassword": "Confirm new password", + "continue": "Continue", + "errorChangingPassword": "Error changing password", + "footerlogo": "Footer Logo", + "invalidCredentials": "Invalid username or password", + "learnMore": "Learn more", + "locationPreferenceRemoved": "Login location preference removed", + "locationPreferenceRemovedMessage": "You will need to select a location on each login", + "locationSaved": "Location saved", + "locationSaveMessage": "Your preferred location has been saved for future logins", + "locationUpdated": "Location updated", + "locationUpdateMessage": "Your preferred login location has been updated", + "loggingIn": "Logging in", + "login": "Log in", + "loginButtonIconDescription": "Log in button", + "Logout": "Logout", + "newPassword": "New password", + "newPasswordRequired": "New password is required", + "oldPassword": "Old password", + "oldPasswordRequired": "Old password is required", + "openmrsLogo": "OpenMRS logo", + "password": "Password", + "passwordChangedSuccessfully": "Password changed successfully", + "passwordConfirmationRequired": "Password confirmation is required", + "passwordsDoNotMatch": "Passwords do not match", + "poweredBySubtext": "An open-source medical record system and global community", + "rememberLocationForFutureLogins": "Remember my location for future logins", + "selectYourLocation": "Select your location from the list below. Use the search bar to find your location.", + "showPassword": "Show password", + "submitting": "Submitting", + "username": "Username", + "validValueRequired": "A valid value is required", + "welcome": "Welcome" +} diff --git a/packages/apps/esm-login-app/translations/uz.json b/packages/apps/esm-login-app/translations/uz.json new file mode 100644 index 000000000..397bb9628 --- /dev/null +++ b/packages/apps/esm-login-app/translations/uz.json @@ -0,0 +1,40 @@ +{ + "builtWith": "Built with", + "cancel": "Cancel", + "change": "Change", + "changePassword": "Change password", + "changingPassword": "Changing password", + "confirmPassword": "Confirm new password", + "continue": "Continue", + "errorChangingPassword": "Error changing password", + "footerlogo": "Footer Logo", + "invalidCredentials": "Invalid username or password", + "learnMore": "Learn more", + "locationPreferenceRemoved": "Login location preference removed", + "locationPreferenceRemovedMessage": "You will need to select a location on each login", + "locationSaved": "Location saved", + "locationSaveMessage": "Your preferred location has been saved for future logins", + "locationUpdated": "Location updated", + "locationUpdateMessage": "Your preferred login location has been updated", + "loggingIn": "Logging in", + "login": "Log in", + "loginButtonIconDescription": "Log in button", + "Logout": "Logout", + "newPassword": "New password", + "newPasswordRequired": "New password is required", + "oldPassword": "Old password", + "oldPasswordRequired": "Old password is required", + "openmrsLogo": "OpenMRS logo", + "password": "Password", + "passwordChangedSuccessfully": "Password changed successfully", + "passwordConfirmationRequired": "Password confirmation is required", + "passwordsDoNotMatch": "Passwords do not match", + "poweredBySubtext": "An open-source medical record system and global community", + "rememberLocationForFutureLogins": "Remember my location for future logins", + "selectYourLocation": "Select your location from the list below. Use the search bar to find your location.", + "showPassword": "Show password", + "submitting": "Submitting", + "username": "Username", + "validValueRequired": "A valid value is required", + "welcome": "Welcome" +} diff --git a/packages/apps/esm-login-app/translations/zh_CN.json b/packages/apps/esm-login-app/translations/zh_CN.json index 466e0d5d7..b7c7ffeb8 100644 --- a/packages/apps/esm-login-app/translations/zh_CN.json +++ b/packages/apps/esm-login-app/translations/zh_CN.json @@ -1,15 +1,15 @@ { - "builtWith": "Built with", - "cancel": "Cancel", + "builtWith": "构建者", + "cancel": "取消", "change": "更改", - "changePassword": "Change password", - "changingPassword": "Changing password", - "confirmPassword": "Confirm new password", + "changePassword": "修改密码", + "changingPassword": "修改密码中", + "confirmPassword": "确认新密码", "continue": "继续", - "errorChangingPassword": "Error changing password", - "footerlogo": "Footer Logo", + "errorChangingPassword": "修改密码时出错", + "footerlogo": "页脚图标", "invalidCredentials": "用户名或密码无效", - "learnMore": "Learn more", + "learnMore": "学习更多", "locationPreferenceRemoved": "登录地点偏好已移除", "locationPreferenceRemovedMessage": "您需要在每次登录时选择一个地点", "locationSaved": "地点已保存", @@ -18,18 +18,18 @@ "locationUpdateMessage": "您的首选登录地点已更新", "loggingIn": "登录中", "login": "登录", - "loginButtonIconDescription": "Log in button", + "loginButtonIconDescription": "登入按钮", "Logout": "退出", - "newPassword": "New password", - "newPasswordRequired": "New password is required", - "oldPassword": "Old password", - "oldPasswordRequired": "Old password is required", - "openmrsLogo": "OpenMRS logo", + "newPassword": "新密码", + "newPasswordRequired": "需要新密码", + "oldPassword": "旧密码", + "oldPasswordRequired": "需要旧密码", + "openmrsLogo": "OpenMRS 图标", "password": "密码", - "passwordChangedSuccessfully": "Password changed successfully", - "passwordConfirmationRequired": "Password confirmation is required", - "passwordsDoNotMatch": "Passwords do not match", - "poweredBySubtext": "An open-source medical record system and global community", + "passwordChangedSuccessfully": "密码修改成功", + "passwordConfirmationRequired": "需要密码确认信息", + "passwordsDoNotMatch": "密码不匹配", + "poweredBySubtext": "开源病历系统和全球社区", "rememberLocationForFutureLogins": "记住我的地点以便将来登录", "selectYourLocation": "请从下面的列表中选择您的地点。可使用搜索栏进行搜索。", "showPassword": "显示密码", diff --git a/packages/apps/esm-offline-tools-app/translations/bn.json b/packages/apps/esm-offline-tools-app/translations/bn.json new file mode 100644 index 000000000..304df0615 --- /dev/null +++ b/packages/apps/esm-offline-tools-app/translations/bn.json @@ -0,0 +1,57 @@ +{ + "emptyStateText": "There are no {{displayText}} to display", + "home": "Home", + "homeHeader": "Offline home", + "homeOverviewCardOfflineActionsFailedToUpload": "Failed to upload", + "homeOverviewCardOfflineActionsHeader": "Offline Actions", + "homeOverviewCardOfflineActionsPendingUpload": "Pending upload", + "homeOverviewCardPatientsDownloaded": "Downloaded", + "homeOverviewCardPatientsHeader": "Patients", + "homeOverviewCardPatientsNewlyRegistered": "Newly registered", + "homeOverviewCardView": "View", + "offlineActions": "Offline Actions", + "offlineActionsDeleteConfirmationModalCancel": "Cancel", + "offlineActionsDeleteConfirmationModalConfirm": "Delete forever", + "offlineActionsDeleteConfirmationModalContent": "Are you sure that you want to delete all selected offline actions? This cannot be undone!", + "offlineActionsDeleteConfirmationModalTitle": "Delete offline actions", + "offlineActionsHeader": "Offline Actions", + "offlineActionsNoActionsEmptyStateContent": "All offline actions have been uploaded successfully,\nand merged with the online patient records.", + "offlineActionsNoActionsEmptyStateImageAlt": "No Pending Actions Image", + "offlineActionsNoActionsEmptyStateTitle": "No actions pending upload", + "offlineActionsTableAction": "Action", + "offlineActionsTableCreatedOn": "Date & Time", + "offlineActionsTableDeleteActions_one": "Delete action", + "offlineActionsTableDeleteActions_other": "Delete {{count}} actions", + "offlineActionsTableError": "Error", + "offlineActionsTablePatient": "Patient", + "offlineActionsUpdateOfflinePatients": "Update offline patients", + "offlinePatients": "Offline patients", + "offlinePatients_lower": "offline patients", + "offlinePatientsHeader": "Offline patients", + "offlinePatientsTableDeleteConfirmationModalCancel": "Cancel", + "offlinePatientsTableDeleteConfirmationModalConfirm": "Remove patients", + "offlinePatientsTableDeleteConfirmationModalContent": "Are you sure that you want to remove all selected patients from the offline list? Their charts will no longer be available in offline mode and any newly registered patient will be permanently deleted.", + "offlinePatientsTableDeleteConfirmationModalTitle": "Remove offline patients", + "offlinePatientsTableHeaderAge": "Age", + "offlinePatientsTableHeaderGender": "Gender", + "offlinePatientsTableHeaderLastUpdated": "Last updated", + "offlinePatientsTableHeaderName": "Name", + "offlinePatientsTableLastUpdatedDownloading": "Downloading...", + "offlinePatientsTableLastUpdatedError": "error", + "offlinePatientsTableLastUpdatedErrors": "errors", + "offlinePatientsTableLastUpdatedNotYetSynchronized": "Not synchronized", + "offlinePatientsTableLastUpdatedOutdatedData": "Outdated data", + "offlinePatientsTableNameNewlyRegistered": "New", + "offlinePatientsTableRemoveFromOfflineList": "Remove from list", + "offlinePatientsTableSearchLabel": "Search this list", + "offlinePatientsTableSearchPlaceholder": "Search this list", + "offlinePatientsTableTitle": "Offline patients", + "offlinePatientsTableUpdatePatient": "Update patient", + "offlinePatientsTableUpdatePatients": "Update patients", + "offlinePatientSyncDetailsDownloadedHeader": "Downloaded to this device", + "offlinePatientSyncDetailsFailedHeader": "There was an error downloading the following items", + "offlinePatientSyncDetailsFallbackErrorMessage": "Unknown error.", + "offlinePatientSyncDetailsHeader": "Offline patient details", + "offlineReady": "Offline Ready", + "offlineToolsAppMenuLink": "Offline tools" +} diff --git a/packages/apps/esm-offline-tools-app/translations/lg.json b/packages/apps/esm-offline-tools-app/translations/lg.json new file mode 100644 index 000000000..304df0615 --- /dev/null +++ b/packages/apps/esm-offline-tools-app/translations/lg.json @@ -0,0 +1,57 @@ +{ + "emptyStateText": "There are no {{displayText}} to display", + "home": "Home", + "homeHeader": "Offline home", + "homeOverviewCardOfflineActionsFailedToUpload": "Failed to upload", + "homeOverviewCardOfflineActionsHeader": "Offline Actions", + "homeOverviewCardOfflineActionsPendingUpload": "Pending upload", + "homeOverviewCardPatientsDownloaded": "Downloaded", + "homeOverviewCardPatientsHeader": "Patients", + "homeOverviewCardPatientsNewlyRegistered": "Newly registered", + "homeOverviewCardView": "View", + "offlineActions": "Offline Actions", + "offlineActionsDeleteConfirmationModalCancel": "Cancel", + "offlineActionsDeleteConfirmationModalConfirm": "Delete forever", + "offlineActionsDeleteConfirmationModalContent": "Are you sure that you want to delete all selected offline actions? This cannot be undone!", + "offlineActionsDeleteConfirmationModalTitle": "Delete offline actions", + "offlineActionsHeader": "Offline Actions", + "offlineActionsNoActionsEmptyStateContent": "All offline actions have been uploaded successfully,\nand merged with the online patient records.", + "offlineActionsNoActionsEmptyStateImageAlt": "No Pending Actions Image", + "offlineActionsNoActionsEmptyStateTitle": "No actions pending upload", + "offlineActionsTableAction": "Action", + "offlineActionsTableCreatedOn": "Date & Time", + "offlineActionsTableDeleteActions_one": "Delete action", + "offlineActionsTableDeleteActions_other": "Delete {{count}} actions", + "offlineActionsTableError": "Error", + "offlineActionsTablePatient": "Patient", + "offlineActionsUpdateOfflinePatients": "Update offline patients", + "offlinePatients": "Offline patients", + "offlinePatients_lower": "offline patients", + "offlinePatientsHeader": "Offline patients", + "offlinePatientsTableDeleteConfirmationModalCancel": "Cancel", + "offlinePatientsTableDeleteConfirmationModalConfirm": "Remove patients", + "offlinePatientsTableDeleteConfirmationModalContent": "Are you sure that you want to remove all selected patients from the offline list? Their charts will no longer be available in offline mode and any newly registered patient will be permanently deleted.", + "offlinePatientsTableDeleteConfirmationModalTitle": "Remove offline patients", + "offlinePatientsTableHeaderAge": "Age", + "offlinePatientsTableHeaderGender": "Gender", + "offlinePatientsTableHeaderLastUpdated": "Last updated", + "offlinePatientsTableHeaderName": "Name", + "offlinePatientsTableLastUpdatedDownloading": "Downloading...", + "offlinePatientsTableLastUpdatedError": "error", + "offlinePatientsTableLastUpdatedErrors": "errors", + "offlinePatientsTableLastUpdatedNotYetSynchronized": "Not synchronized", + "offlinePatientsTableLastUpdatedOutdatedData": "Outdated data", + "offlinePatientsTableNameNewlyRegistered": "New", + "offlinePatientsTableRemoveFromOfflineList": "Remove from list", + "offlinePatientsTableSearchLabel": "Search this list", + "offlinePatientsTableSearchPlaceholder": "Search this list", + "offlinePatientsTableTitle": "Offline patients", + "offlinePatientsTableUpdatePatient": "Update patient", + "offlinePatientsTableUpdatePatients": "Update patients", + "offlinePatientSyncDetailsDownloadedHeader": "Downloaded to this device", + "offlinePatientSyncDetailsFailedHeader": "There was an error downloading the following items", + "offlinePatientSyncDetailsFallbackErrorMessage": "Unknown error.", + "offlinePatientSyncDetailsHeader": "Offline patient details", + "offlineReady": "Offline Ready", + "offlineToolsAppMenuLink": "Offline tools" +} diff --git a/packages/apps/esm-offline-tools-app/translations/pt_BR.json b/packages/apps/esm-offline-tools-app/translations/pt_BR.json index 304df0615..212d652c1 100644 --- a/packages/apps/esm-offline-tools-app/translations/pt_BR.json +++ b/packages/apps/esm-offline-tools-app/translations/pt_BR.json @@ -1,57 +1,57 @@ { - "emptyStateText": "There are no {{displayText}} to display", - "home": "Home", - "homeHeader": "Offline home", - "homeOverviewCardOfflineActionsFailedToUpload": "Failed to upload", - "homeOverviewCardOfflineActionsHeader": "Offline Actions", - "homeOverviewCardOfflineActionsPendingUpload": "Pending upload", - "homeOverviewCardPatientsDownloaded": "Downloaded", - "homeOverviewCardPatientsHeader": "Patients", - "homeOverviewCardPatientsNewlyRegistered": "Newly registered", - "homeOverviewCardView": "View", - "offlineActions": "Offline Actions", - "offlineActionsDeleteConfirmationModalCancel": "Cancel", - "offlineActionsDeleteConfirmationModalConfirm": "Delete forever", - "offlineActionsDeleteConfirmationModalContent": "Are you sure that you want to delete all selected offline actions? This cannot be undone!", - "offlineActionsDeleteConfirmationModalTitle": "Delete offline actions", - "offlineActionsHeader": "Offline Actions", - "offlineActionsNoActionsEmptyStateContent": "All offline actions have been uploaded successfully,\nand merged with the online patient records.", - "offlineActionsNoActionsEmptyStateImageAlt": "No Pending Actions Image", - "offlineActionsNoActionsEmptyStateTitle": "No actions pending upload", - "offlineActionsTableAction": "Action", - "offlineActionsTableCreatedOn": "Date & Time", - "offlineActionsTableDeleteActions_one": "Delete action", - "offlineActionsTableDeleteActions_other": "Delete {{count}} actions", - "offlineActionsTableError": "Error", - "offlineActionsTablePatient": "Patient", - "offlineActionsUpdateOfflinePatients": "Update offline patients", - "offlinePatients": "Offline patients", - "offlinePatients_lower": "offline patients", - "offlinePatientsHeader": "Offline patients", - "offlinePatientsTableDeleteConfirmationModalCancel": "Cancel", - "offlinePatientsTableDeleteConfirmationModalConfirm": "Remove patients", - "offlinePatientsTableDeleteConfirmationModalContent": "Are you sure that you want to remove all selected patients from the offline list? Their charts will no longer be available in offline mode and any newly registered patient will be permanently deleted.", - "offlinePatientsTableDeleteConfirmationModalTitle": "Remove offline patients", - "offlinePatientsTableHeaderAge": "Age", - "offlinePatientsTableHeaderGender": "Gender", - "offlinePatientsTableHeaderLastUpdated": "Last updated", - "offlinePatientsTableHeaderName": "Name", - "offlinePatientsTableLastUpdatedDownloading": "Downloading...", - "offlinePatientsTableLastUpdatedError": "error", - "offlinePatientsTableLastUpdatedErrors": "errors", - "offlinePatientsTableLastUpdatedNotYetSynchronized": "Not synchronized", - "offlinePatientsTableLastUpdatedOutdatedData": "Outdated data", - "offlinePatientsTableNameNewlyRegistered": "New", - "offlinePatientsTableRemoveFromOfflineList": "Remove from list", - "offlinePatientsTableSearchLabel": "Search this list", - "offlinePatientsTableSearchPlaceholder": "Search this list", - "offlinePatientsTableTitle": "Offline patients", - "offlinePatientsTableUpdatePatient": "Update patient", - "offlinePatientsTableUpdatePatients": "Update patients", - "offlinePatientSyncDetailsDownloadedHeader": "Downloaded to this device", - "offlinePatientSyncDetailsFailedHeader": "There was an error downloading the following items", - "offlinePatientSyncDetailsFallbackErrorMessage": "Unknown error.", - "offlinePatientSyncDetailsHeader": "Offline patient details", - "offlineReady": "Offline Ready", - "offlineToolsAppMenuLink": "Offline tools" + "emptyStateText": "Não há {{displayText}} para exibir", + "home": "Página inicial", + "homeHeader": "Página inicial off-line", + "homeOverviewCardOfflineActionsFailedToUpload": "Falha no upload", + "homeOverviewCardOfflineActionsHeader": "Ações off-line", + "homeOverviewCardOfflineActionsPendingUpload": "Upload pendente", + "homeOverviewCardPatientsDownloaded": "Baixado", + "homeOverviewCardPatientsHeader": "Pacientes", + "homeOverviewCardPatientsNewlyRegistered": "Recém-registrados", + "homeOverviewCardView": "Exibir", + "offlineActions": "Ações off-line", + "offlineActionsDeleteConfirmationModalCancel": "Cancelar", + "offlineActionsDeleteConfirmationModalConfirm": "Excluir para sempre", + "offlineActionsDeleteConfirmationModalContent": "Tem certeza de que deseja excluir todas as ações off-line selecionadas? Isso não pode ser desfeito!", + "offlineActionsDeleteConfirmationModalTitle": "Excluir ações off-line", + "offlineActionsHeader": "Ações off-line", + "offlineActionsNoActionsEmptyStateContent": "Todas as ações off-line foram carregadas com sucesso,\ne mescladas com os registros on-line dos pacientes.", + "offlineActionsNoActionsEmptyStateImageAlt": "Nenhuma imagem de ações pendentes", + "offlineActionsNoActionsEmptyStateTitle": "Nenhuma ação pendente de upload", + "offlineActionsTableAction": "Ação", + "offlineActionsTableCreatedOn": "Data e hora", + "offlineActionsTableDeleteActions_one": "Excluir ação", + "offlineActionsTableDeleteActions_other": "Excluir {{count}} ações", + "offlineActionsTableError": "Erro", + "offlineActionsTablePatient": "Paciente", + "offlineActionsUpdateOfflinePatients": "Atualizar pacientes off-line", + "offlinePatients": "Pacientes off-line", + "offlinePatients_lower": "pacientes off-line", + "offlinePatientsHeader": "Pacientes off-line", + "offlinePatientsTableDeleteConfirmationModalCancel": "Cancelar", + "offlinePatientsTableDeleteConfirmationModalConfirm": "Remover pacientes", + "offlinePatientsTableDeleteConfirmationModalContent": "Tem certeza de que deseja remover todos os pacientes selecionados da lista off-line? Os prontuários deles não estarão mais disponíveis no modo off-line e qualquer paciente recém-registrado será excluído permanentemente.", + "offlinePatientsTableDeleteConfirmationModalTitle": "Remover pacientes off-line", + "offlinePatientsTableHeaderAge": "Idade", + "offlinePatientsTableHeaderGender": "Gênero", + "offlinePatientsTableHeaderLastUpdated": "Última atualização", + "offlinePatientsTableHeaderName": "Nome do módulo", + "offlinePatientsTableLastUpdatedDownloading": "Download...", + "offlinePatientsTableLastUpdatedError": "erro", + "offlinePatientsTableLastUpdatedErrors": "erros", + "offlinePatientsTableLastUpdatedNotYetSynchronized": "Não sincronizado", + "offlinePatientsTableLastUpdatedOutdatedData": "Dados desatualizados", + "offlinePatientsTableNameNewlyRegistered": "Novo", + "offlinePatientsTableRemoveFromOfflineList": "Remover da lista", + "offlinePatientsTableSearchLabel": "Pesquisar nesta lista", + "offlinePatientsTableSearchPlaceholder": "Pesquisar nesta lista", + "offlinePatientsTableTitle": "Pacientes off-line", + "offlinePatientsTableUpdatePatient": "Atualizar paciente", + "offlinePatientsTableUpdatePatients": "Atualizar pacientes", + "offlinePatientSyncDetailsDownloadedHeader": "Baixado para este dispositivo", + "offlinePatientSyncDetailsFailedHeader": "Ocorreu um erro ao fazer o download dos seguintes itens", + "offlinePatientSyncDetailsFallbackErrorMessage": "Erro desconhecido.", + "offlinePatientSyncDetailsHeader": "Detalhes do paciente off-line", + "offlineReady": "Pronto para uso off-line", + "offlineToolsAppMenuLink": "Ferramentas off-line" } diff --git a/packages/apps/esm-offline-tools-app/translations/ru_RU.json b/packages/apps/esm-offline-tools-app/translations/ru_RU.json new file mode 100644 index 000000000..304df0615 --- /dev/null +++ b/packages/apps/esm-offline-tools-app/translations/ru_RU.json @@ -0,0 +1,57 @@ +{ + "emptyStateText": "There are no {{displayText}} to display", + "home": "Home", + "homeHeader": "Offline home", + "homeOverviewCardOfflineActionsFailedToUpload": "Failed to upload", + "homeOverviewCardOfflineActionsHeader": "Offline Actions", + "homeOverviewCardOfflineActionsPendingUpload": "Pending upload", + "homeOverviewCardPatientsDownloaded": "Downloaded", + "homeOverviewCardPatientsHeader": "Patients", + "homeOverviewCardPatientsNewlyRegistered": "Newly registered", + "homeOverviewCardView": "View", + "offlineActions": "Offline Actions", + "offlineActionsDeleteConfirmationModalCancel": "Cancel", + "offlineActionsDeleteConfirmationModalConfirm": "Delete forever", + "offlineActionsDeleteConfirmationModalContent": "Are you sure that you want to delete all selected offline actions? This cannot be undone!", + "offlineActionsDeleteConfirmationModalTitle": "Delete offline actions", + "offlineActionsHeader": "Offline Actions", + "offlineActionsNoActionsEmptyStateContent": "All offline actions have been uploaded successfully,\nand merged with the online patient records.", + "offlineActionsNoActionsEmptyStateImageAlt": "No Pending Actions Image", + "offlineActionsNoActionsEmptyStateTitle": "No actions pending upload", + "offlineActionsTableAction": "Action", + "offlineActionsTableCreatedOn": "Date & Time", + "offlineActionsTableDeleteActions_one": "Delete action", + "offlineActionsTableDeleteActions_other": "Delete {{count}} actions", + "offlineActionsTableError": "Error", + "offlineActionsTablePatient": "Patient", + "offlineActionsUpdateOfflinePatients": "Update offline patients", + "offlinePatients": "Offline patients", + "offlinePatients_lower": "offline patients", + "offlinePatientsHeader": "Offline patients", + "offlinePatientsTableDeleteConfirmationModalCancel": "Cancel", + "offlinePatientsTableDeleteConfirmationModalConfirm": "Remove patients", + "offlinePatientsTableDeleteConfirmationModalContent": "Are you sure that you want to remove all selected patients from the offline list? Their charts will no longer be available in offline mode and any newly registered patient will be permanently deleted.", + "offlinePatientsTableDeleteConfirmationModalTitle": "Remove offline patients", + "offlinePatientsTableHeaderAge": "Age", + "offlinePatientsTableHeaderGender": "Gender", + "offlinePatientsTableHeaderLastUpdated": "Last updated", + "offlinePatientsTableHeaderName": "Name", + "offlinePatientsTableLastUpdatedDownloading": "Downloading...", + "offlinePatientsTableLastUpdatedError": "error", + "offlinePatientsTableLastUpdatedErrors": "errors", + "offlinePatientsTableLastUpdatedNotYetSynchronized": "Not synchronized", + "offlinePatientsTableLastUpdatedOutdatedData": "Outdated data", + "offlinePatientsTableNameNewlyRegistered": "New", + "offlinePatientsTableRemoveFromOfflineList": "Remove from list", + "offlinePatientsTableSearchLabel": "Search this list", + "offlinePatientsTableSearchPlaceholder": "Search this list", + "offlinePatientsTableTitle": "Offline patients", + "offlinePatientsTableUpdatePatient": "Update patient", + "offlinePatientsTableUpdatePatients": "Update patients", + "offlinePatientSyncDetailsDownloadedHeader": "Downloaded to this device", + "offlinePatientSyncDetailsFailedHeader": "There was an error downloading the following items", + "offlinePatientSyncDetailsFallbackErrorMessage": "Unknown error.", + "offlinePatientSyncDetailsHeader": "Offline patient details", + "offlineReady": "Offline Ready", + "offlineToolsAppMenuLink": "Offline tools" +} diff --git a/packages/apps/esm-offline-tools-app/translations/uz.json b/packages/apps/esm-offline-tools-app/translations/uz.json new file mode 100644 index 000000000..304df0615 --- /dev/null +++ b/packages/apps/esm-offline-tools-app/translations/uz.json @@ -0,0 +1,57 @@ +{ + "emptyStateText": "There are no {{displayText}} to display", + "home": "Home", + "homeHeader": "Offline home", + "homeOverviewCardOfflineActionsFailedToUpload": "Failed to upload", + "homeOverviewCardOfflineActionsHeader": "Offline Actions", + "homeOverviewCardOfflineActionsPendingUpload": "Pending upload", + "homeOverviewCardPatientsDownloaded": "Downloaded", + "homeOverviewCardPatientsHeader": "Patients", + "homeOverviewCardPatientsNewlyRegistered": "Newly registered", + "homeOverviewCardView": "View", + "offlineActions": "Offline Actions", + "offlineActionsDeleteConfirmationModalCancel": "Cancel", + "offlineActionsDeleteConfirmationModalConfirm": "Delete forever", + "offlineActionsDeleteConfirmationModalContent": "Are you sure that you want to delete all selected offline actions? This cannot be undone!", + "offlineActionsDeleteConfirmationModalTitle": "Delete offline actions", + "offlineActionsHeader": "Offline Actions", + "offlineActionsNoActionsEmptyStateContent": "All offline actions have been uploaded successfully,\nand merged with the online patient records.", + "offlineActionsNoActionsEmptyStateImageAlt": "No Pending Actions Image", + "offlineActionsNoActionsEmptyStateTitle": "No actions pending upload", + "offlineActionsTableAction": "Action", + "offlineActionsTableCreatedOn": "Date & Time", + "offlineActionsTableDeleteActions_one": "Delete action", + "offlineActionsTableDeleteActions_other": "Delete {{count}} actions", + "offlineActionsTableError": "Error", + "offlineActionsTablePatient": "Patient", + "offlineActionsUpdateOfflinePatients": "Update offline patients", + "offlinePatients": "Offline patients", + "offlinePatients_lower": "offline patients", + "offlinePatientsHeader": "Offline patients", + "offlinePatientsTableDeleteConfirmationModalCancel": "Cancel", + "offlinePatientsTableDeleteConfirmationModalConfirm": "Remove patients", + "offlinePatientsTableDeleteConfirmationModalContent": "Are you sure that you want to remove all selected patients from the offline list? Their charts will no longer be available in offline mode and any newly registered patient will be permanently deleted.", + "offlinePatientsTableDeleteConfirmationModalTitle": "Remove offline patients", + "offlinePatientsTableHeaderAge": "Age", + "offlinePatientsTableHeaderGender": "Gender", + "offlinePatientsTableHeaderLastUpdated": "Last updated", + "offlinePatientsTableHeaderName": "Name", + "offlinePatientsTableLastUpdatedDownloading": "Downloading...", + "offlinePatientsTableLastUpdatedError": "error", + "offlinePatientsTableLastUpdatedErrors": "errors", + "offlinePatientsTableLastUpdatedNotYetSynchronized": "Not synchronized", + "offlinePatientsTableLastUpdatedOutdatedData": "Outdated data", + "offlinePatientsTableNameNewlyRegistered": "New", + "offlinePatientsTableRemoveFromOfflineList": "Remove from list", + "offlinePatientsTableSearchLabel": "Search this list", + "offlinePatientsTableSearchPlaceholder": "Search this list", + "offlinePatientsTableTitle": "Offline patients", + "offlinePatientsTableUpdatePatient": "Update patient", + "offlinePatientsTableUpdatePatients": "Update patients", + "offlinePatientSyncDetailsDownloadedHeader": "Downloaded to this device", + "offlinePatientSyncDetailsFailedHeader": "There was an error downloading the following items", + "offlinePatientSyncDetailsFallbackErrorMessage": "Unknown error.", + "offlinePatientSyncDetailsHeader": "Offline patient details", + "offlineReady": "Offline Ready", + "offlineToolsAppMenuLink": "Offline tools" +} diff --git a/packages/apps/esm-primary-navigation-app/src/components/change-language/change-language.modal.tsx b/packages/apps/esm-primary-navigation-app/src/components/change-language/change-language.modal.tsx index ddfd3bae7..543b6b7a2 100644 --- a/packages/apps/esm-primary-navigation-app/src/components/change-language/change-language.modal.tsx +++ b/packages/apps/esm-primary-navigation-app/src/components/change-language/change-language.modal.tsx @@ -1,5 +1,6 @@ import React, { useCallback, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; +import { capitalize } from 'lodash-es'; import { Button, InlineLoading, @@ -69,7 +70,7 @@ export default function ChangeLanguageModal({ close }: ChangeLanguageModalProps) key={`locale-option-${locale}-${i}`} id={`locale-option-${locale}-${i}`} name={locale} - labelText={languageNames[locale]} + labelText={capitalize(languageNames[locale])} value={locale} /> ))} diff --git a/packages/apps/esm-primary-navigation-app/src/components/change-language/change-language.test.tsx b/packages/apps/esm-primary-navigation-app/src/components/change-language/change-language.test.tsx index 4097cbea8..abff02978 100644 --- a/packages/apps/esm-primary-navigation-app/src/components/change-language/change-language.test.tsx +++ b/packages/apps/esm-primary-navigation-app/src/components/change-language/change-language.test.tsx @@ -55,7 +55,7 @@ describe(`Change Language Modal`, () => { render(); - expect(screen.getByRole('radio', { name: /français/ })).toBeChecked(); + expect(screen.getByRole('radio', { name: /français/i })).toBeChecked(); await user.click(screen.getByRole('radio', { name: /english/i })); await user.click(screen.getByRole('button', { name: /change/i })); diff --git a/packages/apps/esm-primary-navigation-app/translations/bn.json b/packages/apps/esm-primary-navigation-app/translations/bn.json new file mode 100644 index 000000000..55ee990a3 --- /dev/null +++ b/packages/apps/esm-primary-navigation-app/translations/bn.json @@ -0,0 +1,9 @@ +{ + "AppMenuTooltip": "App Menu", + "cancel": "Cancel", + "change": "Change", + "changeLanguage": "Change language", + "changingLanguage": "Changing language", + "notifications": "Notifications", + "userMenuTooltip": "My Account" +} diff --git a/packages/apps/esm-primary-navigation-app/translations/fr.json b/packages/apps/esm-primary-navigation-app/translations/fr.json index 440dace8a..70df181ab 100644 --- a/packages/apps/esm-primary-navigation-app/translations/fr.json +++ b/packages/apps/esm-primary-navigation-app/translations/fr.json @@ -1,5 +1,5 @@ { - "AppMenuTooltip": "App Menu", + "AppMenuTooltip": "Menu des applications", "cancel": "Annuler", "change": "Modifier", "changeLanguage": "Modifier la langue", diff --git a/packages/apps/esm-primary-navigation-app/translations/lg.json b/packages/apps/esm-primary-navigation-app/translations/lg.json new file mode 100644 index 000000000..55ee990a3 --- /dev/null +++ b/packages/apps/esm-primary-navigation-app/translations/lg.json @@ -0,0 +1,9 @@ +{ + "AppMenuTooltip": "App Menu", + "cancel": "Cancel", + "change": "Change", + "changeLanguage": "Change language", + "changingLanguage": "Changing language", + "notifications": "Notifications", + "userMenuTooltip": "My Account" +} diff --git a/packages/apps/esm-primary-navigation-app/translations/pt_BR.json b/packages/apps/esm-primary-navigation-app/translations/pt_BR.json index 55ee990a3..34cdab753 100644 --- a/packages/apps/esm-primary-navigation-app/translations/pt_BR.json +++ b/packages/apps/esm-primary-navigation-app/translations/pt_BR.json @@ -1,9 +1,9 @@ { - "AppMenuTooltip": "App Menu", - "cancel": "Cancel", - "change": "Change", - "changeLanguage": "Change language", - "changingLanguage": "Changing language", - "notifications": "Notifications", - "userMenuTooltip": "My Account" + "AppMenuTooltip": "Menu do Aplicativo", + "cancel": "Cancelar", + "change": "Alterar", + "changeLanguage": "Alterar idioma", + "changingLanguage": "Alterando idioma", + "notifications": "Notificações", + "userMenuTooltip": "Minha Conta" } diff --git a/packages/apps/esm-primary-navigation-app/translations/ru_RU.json b/packages/apps/esm-primary-navigation-app/translations/ru_RU.json new file mode 100644 index 000000000..55ee990a3 --- /dev/null +++ b/packages/apps/esm-primary-navigation-app/translations/ru_RU.json @@ -0,0 +1,9 @@ +{ + "AppMenuTooltip": "App Menu", + "cancel": "Cancel", + "change": "Change", + "changeLanguage": "Change language", + "changingLanguage": "Changing language", + "notifications": "Notifications", + "userMenuTooltip": "My Account" +} diff --git a/packages/apps/esm-primary-navigation-app/translations/uz.json b/packages/apps/esm-primary-navigation-app/translations/uz.json new file mode 100644 index 000000000..55ee990a3 --- /dev/null +++ b/packages/apps/esm-primary-navigation-app/translations/uz.json @@ -0,0 +1,9 @@ +{ + "AppMenuTooltip": "App Menu", + "cancel": "Cancel", + "change": "Change", + "changeLanguage": "Change language", + "changingLanguage": "Changing language", + "notifications": "Notifications", + "userMenuTooltip": "My Account" +} diff --git a/packages/apps/esm-primary-navigation-app/translations/zh_CN.json b/packages/apps/esm-primary-navigation-app/translations/zh_CN.json index 4d32a84ec..58520b5c4 100644 --- a/packages/apps/esm-primary-navigation-app/translations/zh_CN.json +++ b/packages/apps/esm-primary-navigation-app/translations/zh_CN.json @@ -1,5 +1,5 @@ { - "AppMenuTooltip": "App Menu", + "AppMenuTooltip": "应用菜单", "cancel": "取消", "change": "更改", "changeLanguage": "更改语言", diff --git a/packages/framework/esm-api/src/types/attachments-types.ts b/packages/framework/esm-api/src/types/attachments-types.ts index cc5f76b41..a57ccb452 100644 --- a/packages/framework/esm-api/src/types/attachments-types.ts +++ b/packages/framework/esm-api/src/types/attachments-types.ts @@ -5,6 +5,7 @@ export interface UploadedFile { fileType: string; fileDescription: string; status?: 'uploading' | 'complete'; + capturedFromWebcam?: boolean; } export interface Attachment { diff --git a/packages/framework/esm-extensions/src/workspaces.ts b/packages/framework/esm-extensions/src/workspaces.ts index ba93fd993..d0f3b2614 100644 --- a/packages/framework/esm-extensions/src/workspaces.ts +++ b/packages/framework/esm-extensions/src/workspaces.ts @@ -1,6 +1,6 @@ import { type ReactNode } from 'react'; import { type LifeCycles } from 'single-spa'; -import { type WorkspaceWindowState } from '@openmrs/esm-globals'; +import { type WorkspaceGroupDefinition, type WorkspaceWindowState } from '@openmrs/esm-globals'; import { type ExtensionRegistration, getExtensionRegistration } from '.'; import { createGlobalStore } from '@openmrs/esm-state'; import { translateFrom } from '@openmrs/esm-translations'; @@ -17,9 +17,13 @@ export interface WorkspaceRegistration { preferredWindowSize: WorkspaceWindowState; load: () => Promise<{ default?: LifeCycles } & LifeCycles>; moduleName: string; - groups?: Array; + groups: Array; } +export type WorkspaceGroupRegistration = WorkspaceGroupDefinition & { + members: Array; +}; + interface WorkspaceRegistrationStore { workspaces: Record; } @@ -28,6 +32,14 @@ const workspaceRegistrationStore = createGlobalStore workspaces: {}, }); +interface WorkspaceGroupRegistrationStore { + workspaceGroups: Record }>; +} + +const workspaceGroupStore = createGlobalStore('workspaceGroups', { + workspaceGroups: {}, +}); + /** See [[WorkspaceDefinition]] for more information about these properties */ export interface RegisterWorkspaceOptions { name: string; @@ -64,6 +76,23 @@ export function registerWorkspace(workspace: RegisterWorkspaceOptions) { })); } +/** + * Tells the workspace system about a workspace group. This is used by the app shell + * to register workspace groups defined in the `routes.json` file. + * @internal + */ +export function registerWorkspaceGroup(workspaceGroup: WorkspaceGroupRegistration) { + workspaceGroupStore.setState((state) => ({ + workspaceGroups: { + ...state.workspaceGroups, + [workspaceGroup.name]: { + name: workspaceGroup.name, + members: workspaceGroup.members, + }, + }, + })); +} + const workspaceExtensionWarningsIssued = new Set(); /** * This exists for compatibility with the old way of registering @@ -94,7 +123,7 @@ export function getWorkspaceRegistration(name: string): WorkspaceRegistration { canHide: workspaceExtension.meta?.canHide ?? false, canMaximize: workspaceExtension.meta?.canMaximize ?? false, width: workspaceExtension.meta?.width ?? 'narrow', - groups: workspaceExtension?.meta?.groups ?? [], + groups: workspaceExtension.meta?.groups ?? [], }; } else { throw new Error(`No workspace named '${name}' has been registered.`); @@ -102,6 +131,21 @@ export function getWorkspaceRegistration(name: string): WorkspaceRegistration { } } +/** + * This provides the workspace group registration and is also compatibile with the + * old way of registering workspace groups (as extensions), but isn't recommended. + * + * @param name of the workspace + */ +export function getWorkspaceGroupRegistration(name: string): WorkspaceGroupRegistration { + const registeredWorkspaces = workspaceGroupStore.getState().workspaceGroups; + if (registeredWorkspaces[name]) { + return registeredWorkspaces[name]; + } else { + throw new Error(`No workspace group named '${name}' has been registered.`); + } +} + function getTitleFromExtension(ext: ExtensionRegistration) { const title = ext?.meta?.title; if (typeof title === 'string') { @@ -111,3 +155,37 @@ function getTitleFromExtension(ext: ExtensionRegistration) { } return ext.name; } + +function createNewWorkspaceGroupInfo(groupName: string): WorkspaceGroupRegistration { + return { + name: groupName, + members: [], + }; +} + +export function attachWorkspaceToGroup(workspaceName: string, groupName: string) { + workspaceGroupStore.setState((state) => { + const group = state.workspaceGroups[groupName]; + if (group) { + return { + workspaceGroups: { + ...state.workspaceGroups, + [groupName]: { + ...group, + members: [...group.members, workspaceName], + }, + }, + }; + } else { + return { + workspaceGroups: { + ...state.workspaceGroups, + [groupName]: { + ...createNewWorkspaceGroupInfo(groupName), + members: [workspaceName], + }, + }, + }; + } + }); +} diff --git a/packages/framework/esm-framework/docs/API.md b/packages/framework/esm-framework/docs/API.md index a460bc727..94c0e9665 100644 --- a/packages/framework/esm-framework/docs/API.md +++ b/packages/framework/esm-framework/docs/API.md @@ -610,7 +610,7 @@ ___ #### Defined in -[packages/framework/esm-globals/src/types.ts:409](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L409) +[packages/framework/esm-globals/src/types.ts:422](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L422) ___ @@ -623,7 +623,7 @@ Basically, this is the same as the app routes, with each routes definition keyed #### Defined in -[packages/framework/esm-globals/src/types.ts:400](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L400) +[packages/framework/esm-globals/src/types.ts:413](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L413) ___ @@ -8231,7 +8231,7 @@ Function to close an opened workspace #### Defined in -[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:425](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L425) +[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:433](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L433) ___ @@ -8282,7 +8282,7 @@ prop named `workspaceTitle` will override the title of the workspace. #### Defined in -[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:289](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L289) +[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:297](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L297) ___ @@ -8313,7 +8313,7 @@ launchWorkspaceGroup("myGroup", { #### Defined in -[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:205](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L205) +[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:211](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L211) ___ @@ -8339,7 +8339,7 @@ Use this function to navigate to a new page and launch a workspace on that page. #### Defined in -[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:382](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L382) +[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:390](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L390) ___ @@ -8353,4 +8353,4 @@ ___ #### Defined in -[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:536](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L536) +[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:544](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L544) diff --git a/packages/framework/esm-framework/docs/interfaces/Attachment.md b/packages/framework/esm-framework/docs/interfaces/Attachment.md index 97a52c7be..0252cbc04 100644 --- a/packages/framework/esm-framework/docs/interfaces/Attachment.md +++ b/packages/framework/esm-framework/docs/interfaces/Attachment.md @@ -22,7 +22,7 @@ #### Defined in -[packages/framework/esm-api/src/types/attachments-types.ts:16](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-api/src/types/attachments-types.ts#L16) +[packages/framework/esm-api/src/types/attachments-types.ts:17](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-api/src/types/attachments-types.ts#L17) ___ @@ -32,7 +32,7 @@ ___ #### Defined in -[packages/framework/esm-api/src/types/attachments-types.ts:15](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-api/src/types/attachments-types.ts#L15) +[packages/framework/esm-api/src/types/attachments-types.ts:16](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-api/src/types/attachments-types.ts#L16) ___ @@ -42,7 +42,7 @@ ___ #### Defined in -[packages/framework/esm-api/src/types/attachments-types.ts:14](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-api/src/types/attachments-types.ts#L14) +[packages/framework/esm-api/src/types/attachments-types.ts:15](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-api/src/types/attachments-types.ts#L15) ___ @@ -52,7 +52,7 @@ ___ #### Defined in -[packages/framework/esm-api/src/types/attachments-types.ts:17](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-api/src/types/attachments-types.ts#L17) +[packages/framework/esm-api/src/types/attachments-types.ts:18](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-api/src/types/attachments-types.ts#L18) ___ @@ -62,7 +62,7 @@ ___ #### Defined in -[packages/framework/esm-api/src/types/attachments-types.ts:13](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-api/src/types/attachments-types.ts#L13) +[packages/framework/esm-api/src/types/attachments-types.ts:14](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-api/src/types/attachments-types.ts#L14) ___ @@ -72,7 +72,7 @@ ___ #### Defined in -[packages/framework/esm-api/src/types/attachments-types.ts:11](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-api/src/types/attachments-types.ts#L11) +[packages/framework/esm-api/src/types/attachments-types.ts:12](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-api/src/types/attachments-types.ts#L12) ___ @@ -82,4 +82,4 @@ ___ #### Defined in -[packages/framework/esm-api/src/types/attachments-types.ts:12](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-api/src/types/attachments-types.ts#L12) +[packages/framework/esm-api/src/types/attachments-types.ts:13](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-api/src/types/attachments-types.ts#L13) diff --git a/packages/framework/esm-framework/docs/interfaces/AttachmentResponse.md b/packages/framework/esm-framework/docs/interfaces/AttachmentResponse.md index 0c5c3ac69..cf0501fa7 100644 --- a/packages/framework/esm-framework/docs/interfaces/AttachmentResponse.md +++ b/packages/framework/esm-framework/docs/interfaces/AttachmentResponse.md @@ -21,7 +21,7 @@ #### Defined in -[packages/framework/esm-api/src/types/attachments-types.ts:21](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-api/src/types/attachments-types.ts#L21) +[packages/framework/esm-api/src/types/attachments-types.ts:22](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-api/src/types/attachments-types.ts#L22) ___ @@ -31,7 +31,7 @@ ___ #### Defined in -[packages/framework/esm-api/src/types/attachments-types.ts:22](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-api/src/types/attachments-types.ts#L22) +[packages/framework/esm-api/src/types/attachments-types.ts:23](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-api/src/types/attachments-types.ts#L23) ___ @@ -41,7 +41,7 @@ ___ #### Defined in -[packages/framework/esm-api/src/types/attachments-types.ts:23](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-api/src/types/attachments-types.ts#L23) +[packages/framework/esm-api/src/types/attachments-types.ts:24](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-api/src/types/attachments-types.ts#L24) ___ @@ -51,7 +51,7 @@ ___ #### Defined in -[packages/framework/esm-api/src/types/attachments-types.ts:24](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-api/src/types/attachments-types.ts#L24) +[packages/framework/esm-api/src/types/attachments-types.ts:25](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-api/src/types/attachments-types.ts#L25) ___ @@ -61,7 +61,7 @@ ___ #### Defined in -[packages/framework/esm-api/src/types/attachments-types.ts:26](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-api/src/types/attachments-types.ts#L26) +[packages/framework/esm-api/src/types/attachments-types.ts:27](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-api/src/types/attachments-types.ts#L27) ___ @@ -71,4 +71,4 @@ ___ #### Defined in -[packages/framework/esm-api/src/types/attachments-types.ts:25](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-api/src/types/attachments-types.ts#L25) +[packages/framework/esm-api/src/types/attachments-types.ts:26](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-api/src/types/attachments-types.ts#L26) diff --git a/packages/framework/esm-framework/docs/interfaces/CloseWorkspaceOptions.md b/packages/framework/esm-framework/docs/interfaces/CloseWorkspaceOptions.md index 0b6851461..ac6f75b98 100644 --- a/packages/framework/esm-framework/docs/interfaces/CloseWorkspaceOptions.md +++ b/packages/framework/esm-framework/docs/interfaces/CloseWorkspaceOptions.md @@ -27,7 +27,7 @@ Defaults to true except when opening a new workspace of the same group. #### Defined in -[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:33](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L33) +[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:38](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L38) ___ @@ -42,7 +42,7 @@ even if the `testFcn` passed to `promptBeforeClosing` returns `true`. #### Defined in -[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:18](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L18) +[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:23](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L23) ## Workspace Methods @@ -62,4 +62,4 @@ void #### Defined in -[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:25](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L25) +[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:30](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L30) diff --git a/packages/framework/esm-framework/docs/interfaces/DefaultWorkspaceProps.md b/packages/framework/esm-framework/docs/interfaces/DefaultWorkspaceProps.md index 57d80a2b7..fdcb3effd 100644 --- a/packages/framework/esm-framework/docs/interfaces/DefaultWorkspaceProps.md +++ b/packages/framework/esm-framework/docs/interfaces/DefaultWorkspaceProps.md @@ -43,7 +43,7 @@ closed, given the user forcefully closes the workspace. #### Defined in -[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:45](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L45) +[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:50](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L50) ___ @@ -66,7 +66,7 @@ will directly close the workspace without any prompt #### Defined in -[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:55](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L55) +[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:60](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L60) ___ @@ -89,7 +89,7 @@ this workspace is closed; e.g. if there is unsaved data. #### Defined in -[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:50](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L50) +[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:55](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L55) ___ @@ -117,4 +117,4 @@ title needs to be set dynamically. #### Defined in -[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:70](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L70) +[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:75](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L75) diff --git a/packages/framework/esm-framework/docs/interfaces/FeatureFlagDefinition.md b/packages/framework/esm-framework/docs/interfaces/FeatureFlagDefinition.md index 4059543f4..ba39fda1b 100644 --- a/packages/framework/esm-framework/docs/interfaces/FeatureFlagDefinition.md +++ b/packages/framework/esm-framework/docs/interfaces/FeatureFlagDefinition.md @@ -22,7 +22,7 @@ An explanation of what the flag does, which will be displayed in the Implementer #### Defined in -[packages/framework/esm-globals/src/types.ts:363](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L363) +[packages/framework/esm-globals/src/types.ts:374](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L374) ___ @@ -34,7 +34,7 @@ A code-friendly name for the flag, which will be used to reference it in code #### Defined in -[packages/framework/esm-globals/src/types.ts:359](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L359) +[packages/framework/esm-globals/src/types.ts:370](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L370) ___ @@ -46,4 +46,4 @@ A human-friendly name which will be displayed in the Implementer Tools #### Defined in -[packages/framework/esm-globals/src/types.ts:361](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L361) +[packages/framework/esm-globals/src/types.ts:372](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L372) diff --git a/packages/framework/esm-framework/docs/interfaces/OpenWorkspace.md b/packages/framework/esm-framework/docs/interfaces/OpenWorkspace.md index 8aab4ab19..695167ac8 100644 --- a/packages/framework/esm-framework/docs/interfaces/OpenWorkspace.md +++ b/packages/framework/esm-framework/docs/interfaces/OpenWorkspace.md @@ -70,7 +70,7 @@ ___ ### groups -• `Optional` **groups**: `string`[] +• **groups**: `string`[] #### Inherited from @@ -188,7 +188,7 @@ ___ #### Defined in -[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:109](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L109) +[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:115](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L115) ___ @@ -198,7 +198,7 @@ ___ #### Defined in -[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:110](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L110) +[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:116](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L116) ## Methods @@ -228,7 +228,7 @@ closed, given the user forcefully closes the workspace. #### Defined in -[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:45](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L45) +[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:50](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L50) ___ @@ -255,7 +255,7 @@ will directly close the workspace without any prompt #### Defined in -[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:55](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L55) +[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:60](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L60) ___ @@ -300,7 +300,7 @@ this workspace is closed; e.g. if there is unsaved data. #### Defined in -[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:50](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L50) +[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:55](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L55) ___ @@ -332,4 +332,4 @@ title needs to be set dynamically. #### Defined in -[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:70](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L70) +[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:75](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L75) diff --git a/packages/framework/esm-framework/docs/interfaces/OpenmrsAppRoutes.md b/packages/framework/esm-framework/docs/interfaces/OpenmrsAppRoutes.md index 1080d7d7a..f56204f75 100644 --- a/packages/framework/esm-framework/docs/interfaces/OpenmrsAppRoutes.md +++ b/packages/framework/esm-framework/docs/interfaces/OpenmrsAppRoutes.md @@ -15,6 +15,7 @@ This interface describes the format of the routes provided by an app - [optionalBackendDependencies](OpenmrsAppRoutes.md#optionalbackenddependencies) - [pages](OpenmrsAppRoutes.md#pages) - [version](OpenmrsAppRoutes.md#version) +- [workspaceGroups](OpenmrsAppRoutes.md#workspacegroups) - [workspaces](OpenmrsAppRoutes.md#workspaces) ## Properties @@ -27,7 +28,7 @@ A list of backend modules necessary for this frontend module and the correspondi #### Defined in -[packages/framework/esm-globals/src/types.ts:371](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L371) +[packages/framework/esm-globals/src/types.ts:382](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L382) ___ @@ -39,7 +40,7 @@ An array of all extensions supported by this frontend module. Extensions can be #### Defined in -[packages/framework/esm-globals/src/types.ts:387](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L387) +[packages/framework/esm-globals/src/types.ts:398](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L398) ___ @@ -51,7 +52,7 @@ An array of all feature flags for any beta-stage features this module provides. #### Defined in -[packages/framework/esm-globals/src/types.ts:389](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L389) +[packages/framework/esm-globals/src/types.ts:400](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L400) ___ @@ -63,7 +64,7 @@ An array of all modals supported by this frontend module. Modals can be launched #### Defined in -[packages/framework/esm-globals/src/types.ts:391](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L391) +[packages/framework/esm-globals/src/types.ts:402](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L402) ___ @@ -81,7 +82,7 @@ The name of the backend dependency and either the required version or an object #### Defined in -[packages/framework/esm-globals/src/types.ts:373](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L373) +[packages/framework/esm-globals/src/types.ts:384](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L384) ___ @@ -93,7 +94,7 @@ An array of all pages supported by this frontend module. Pages are automatically #### Defined in -[packages/framework/esm-globals/src/types.ts:385](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L385) +[packages/framework/esm-globals/src/types.ts:396](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L396) ___ @@ -105,7 +106,19 @@ The version of this frontend module. #### Defined in -[packages/framework/esm-globals/src/types.ts:369](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L369) +[packages/framework/esm-globals/src/types.ts:380](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L380) + +___ + +### workspaceGroups + +• `Optional` **workspaceGroups**: [`WorkspaceGroupDefinition`](WorkspaceGroupDefinition.md)[] + +An array of all workspace groups supported by this frontend module. + +#### Defined in + +[packages/framework/esm-globals/src/types.ts:406](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L406) ___ @@ -117,4 +130,4 @@ An array of all workspaces supported by this frontend module. Workspaces can be #### Defined in -[packages/framework/esm-globals/src/types.ts:393](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L393) +[packages/framework/esm-globals/src/types.ts:404](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L404) diff --git a/packages/framework/esm-framework/docs/interfaces/Prompt.md b/packages/framework/esm-framework/docs/interfaces/Prompt.md index c9e509fb7..bd22dc022 100644 --- a/packages/framework/esm-framework/docs/interfaces/Prompt.md +++ b/packages/framework/esm-framework/docs/interfaces/Prompt.md @@ -23,7 +23,7 @@ #### Defined in -[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:89](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L89) +[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:94](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L94) ___ @@ -35,7 +35,7 @@ Defaults to "Cancel" #### Defined in -[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:94](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L94) +[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:99](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L99) ___ @@ -47,7 +47,7 @@ Defaults to "Confirm" #### Defined in -[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:91](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L91) +[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:96](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L96) ___ @@ -57,7 +57,7 @@ ___ #### Defined in -[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:88](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L88) +[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:93](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L93) ## Methods @@ -71,4 +71,4 @@ ___ #### Defined in -[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:92](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L92) +[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:97](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L97) diff --git a/packages/framework/esm-framework/docs/interfaces/ResourceLoader.md b/packages/framework/esm-framework/docs/interfaces/ResourceLoader.md index e4535a5ca..fd573e697 100644 --- a/packages/framework/esm-framework/docs/interfaces/ResourceLoader.md +++ b/packages/framework/esm-framework/docs/interfaces/ResourceLoader.md @@ -20,4 +20,4 @@ #### Defined in -[packages/framework/esm-globals/src/types.ts:403](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L403) +[packages/framework/esm-globals/src/types.ts:416](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L416) diff --git a/packages/framework/esm-framework/docs/interfaces/UploadedFile.md b/packages/framework/esm-framework/docs/interfaces/UploadedFile.md index c68875f7f..6e4fa0a7a 100644 --- a/packages/framework/esm-framework/docs/interfaces/UploadedFile.md +++ b/packages/framework/esm-framework/docs/interfaces/UploadedFile.md @@ -7,6 +7,7 @@ ### Properties - [base64Content](UploadedFile.md#base64content) +- [capturedFromWebcam](UploadedFile.md#capturedfromwebcam) - [file](UploadedFile.md#file) - [fileDescription](UploadedFile.md#filedescription) - [fileName](UploadedFile.md#filename) @@ -25,6 +26,16 @@ ___ +### capturedFromWebcam + +• `Optional` **capturedFromWebcam**: `boolean` + +#### Defined in + +[packages/framework/esm-api/src/types/attachments-types.ts:8](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-api/src/types/attachments-types.ts#L8) + +___ + ### file • `Optional` **file**: `File` diff --git a/packages/framework/esm-framework/docs/interfaces/WorkspaceGroupDefinition.md b/packages/framework/esm-framework/docs/interfaces/WorkspaceGroupDefinition.md new file mode 100644 index 000000000..655d377ba --- /dev/null +++ b/packages/framework/esm-framework/docs/interfaces/WorkspaceGroupDefinition.md @@ -0,0 +1,34 @@ +[@openmrs/esm-framework](../API.md) / WorkspaceGroupDefinition + +# Interface: WorkspaceGroupDefinition + +## Table of contents + +### Properties + +- [members](WorkspaceGroupDefinition.md#members) +- [name](WorkspaceGroupDefinition.md#name) + +## Properties + +### members + +• `Optional` **members**: `string`[] + +List of workspace names which are part of the workspace group. + +#### Defined in + +[packages/framework/esm-globals/src/types.ts:362](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L362) + +___ + +### name + +• **name**: `string` + +Name of the workspace group. This is used to launch the workspace group + +#### Defined in + +[packages/framework/esm-globals/src/types.ts:358](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L358) diff --git a/packages/framework/esm-framework/docs/interfaces/WorkspaceRegistration.md b/packages/framework/esm-framework/docs/interfaces/WorkspaceRegistration.md index ada48462f..9c9a97fe2 100644 --- a/packages/framework/esm-framework/docs/interfaces/WorkspaceRegistration.md +++ b/packages/framework/esm-framework/docs/interfaces/WorkspaceRegistration.md @@ -53,7 +53,7 @@ ___ ### groups -• `Optional` **groups**: `string`[] +• **groups**: `string`[] #### Defined in diff --git a/packages/framework/esm-framework/docs/interfaces/WorkspacesInfo.md b/packages/framework/esm-framework/docs/interfaces/WorkspacesInfo.md index 98149ebe4..8466d5d4f 100644 --- a/packages/framework/esm-framework/docs/interfaces/WorkspacesInfo.md +++ b/packages/framework/esm-framework/docs/interfaces/WorkspacesInfo.md @@ -20,7 +20,7 @@ #### Defined in -[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:529](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L529) +[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:537](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L537) ___ @@ -30,7 +30,7 @@ ___ #### Defined in -[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:530](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L530) +[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:538](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L538) ___ @@ -43,11 +43,12 @@ ___ | Name | Type | | :------ | :------ | | `cleanup?` | `Function` | +| `members` | `string`[] | | `name` | `string` | #### Defined in -[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:533](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L533) +[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:541](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L541) ___ @@ -57,7 +58,7 @@ ___ #### Defined in -[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:531](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L531) +[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:539](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L539) ___ @@ -67,4 +68,4 @@ ___ #### Defined in -[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:532](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L532) +[packages/framework/esm-styleguide/src/workspaces/workspaces.ts:540](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/workspaces.ts#L540) diff --git a/packages/framework/esm-globals/src/types.ts b/packages/framework/esm-globals/src/types.ts index 5675a6494..e1e6fe862 100644 --- a/packages/framework/esm-globals/src/types.ts +++ b/packages/framework/esm-globals/src/types.ts @@ -351,6 +351,17 @@ export type WorkspaceDefinition = { } ); +export interface WorkspaceGroupDefinition { + /** + * Name of the workspace group. This is used to launch the workspace group + */ + name: string; + /** + * List of workspace names which are part of the workspace group. + */ + members?: Array; +} + /** * A definition of a feature flag extracted from the routes.json */ @@ -391,6 +402,8 @@ export interface OpenmrsAppRoutes { modals?: Array; /** An array of all workspaces supported by this frontend module. Workspaces can be launched by name. */ workspaces?: Array; + /** An array of all workspace groups supported by this frontend module. */ + workspaceGroups?: Array; } /** diff --git a/packages/framework/esm-react-utils/src/openmrsComponentDecorator.tsx b/packages/framework/esm-react-utils/src/openmrsComponentDecorator.tsx index ab8f6212c..ea0c15d87 100644 --- a/packages/framework/esm-react-utils/src/openmrsComponentDecorator.tsx +++ b/packages/framework/esm-react-utils/src/openmrsComponentDecorator.tsx @@ -1,6 +1,6 @@ import React, { type ComponentType, type ErrorInfo, Suspense } from 'react'; import { I18nextProvider } from 'react-i18next'; -import { SWRConfig } from 'swr'; +import { SWRConfig, type SWRConfiguration } from 'swr'; import type {} from '@openmrs/esm-globals'; import { openmrsFetch } from '@openmrs/esm-api'; import { ComponentContext, type ComponentConfig, type ExtensionData } from './ComponentContext'; @@ -31,6 +31,7 @@ export interface ComponentDecoratorOptions { featureName: string; disableTranslations?: boolean; strictMode?: boolean; + swrConfig?: Partial>; } export interface OpenmrsReactComponentProps { @@ -98,9 +99,10 @@ export function openmrsComponentDecorator(userOpts: ComponentDecoratorOptions // TO-DO have a UX designed for when a catastrophic error occurs return
An error has occurred. Please try reloading the page.
; } else { + const swrConfig = { ...defaultSwrConfig, ...opts.swrConfig }; const content = ( - + {opts.disableTranslations ? ( @@ -120,7 +122,7 @@ export function openmrsComponentDecorator(userOpts: ComponentDecoratorOptions ); - + if (!opts.strictMode || !React.StrictMode) { return content; } else { diff --git a/packages/framework/esm-routes/src/loaders/components.ts b/packages/framework/esm-routes/src/loaders/components.ts index 3027946b2..e47ee810c 100644 --- a/packages/framework/esm-routes/src/loaders/components.ts +++ b/packages/framework/esm-routes/src/loaders/components.ts @@ -1,15 +1,18 @@ import { attach, + attachWorkspaceToGroup, type ExtensionRegistration, registerExtension, registerModal, registerWorkspace, + registerWorkspaceGroup, } from '@openmrs/esm-extensions'; import { type FeatureFlagDefinition, type ExtensionDefinition, type ModalDefinition, type WorkspaceDefinition, + type WorkspaceGroupDefinition, } from '@openmrs/esm-globals'; import { getLoader } from './app'; import { registerFeatureFlag } from '@openmrs/esm-feature-flags'; @@ -194,9 +197,36 @@ supported, so the workspace will not be loaded.`, canMaximize: workspace.canMaximize, width: workspace.width, preferredWindowSize: workspace.preferredWindowSize, - groups: workspace.groups ?? [], + groups: workspace.groups, }); } + + for (const group of workspace.groups || []) { + attachWorkspaceToGroup(name, group); + } +} + +/** + * This function registers a workspace group definition with the framework so that it can be launched. + * + * @param appName The name of the app defining this workspace + * @param workspace An object that describes the workspace, derived from `routes.json` + */ +export function tryRegisterWorkspaceGroup(appName: string, workspaceGroup: WorkspaceGroupDefinition) { + const name = workspaceGroup.name; + if (!name) { + console.error( + `A workspace group definition in ${appName} is missing a name and thus cannot be registered. +To fix this, ensure that you define the "name" field inside the workspace definition.`, + workspaceGroup, + ); + return; + } + + registerWorkspaceGroup({ + name, + members: workspaceGroup.members ?? [], + }); } /** diff --git a/packages/framework/esm-routes/src/loaders/pages.ts b/packages/framework/esm-routes/src/loaders/pages.ts index 9a13cb24f..18648c884 100644 --- a/packages/framework/esm-routes/src/loaders/pages.ts +++ b/packages/framework/esm-routes/src/loaders/pages.ts @@ -1,6 +1,7 @@ import { type ActivityFn, pathToActiveWhen, registerApplication } from 'single-spa'; import { registerModuleWithConfigSystem } from '@openmrs/esm-config'; import { + type WorkspaceGroupDefinition, type ExtensionDefinition, type FeatureFlagDefinition, type ModalDefinition, @@ -12,7 +13,13 @@ import { import { getFeatureFlag } from '@openmrs/esm-feature-flags'; import { routeRegex } from './helpers'; import { getLoader } from './app'; -import { tryRegisterExtension, tryRegisterFeatureFlag, tryRegisterModal, tryRegisterWorkspace } from './components'; +import { + tryRegisterExtension, + tryRegisterFeatureFlag, + tryRegisterModal, + tryRegisterWorkspace, + tryRegisterWorkspaceGroup, +} from './components'; // this is the global holder of all pages registered in the app const pages: Array = []; @@ -93,6 +100,7 @@ export function registerApp(appName: string, routes: OpenmrsAppRoutes) { const availableExtensions: Array = routes.extensions ?? []; const availableModals: Array = routes.modals ?? []; const availableWorkspaces: Array = routes.workspaces ?? []; + const availableWorkspaceGroups: Array = routes.workspaceGroups ?? []; const availableFeatureFlags: Array = routes.featureFlags ?? []; routes.pages?.forEach((p) => { @@ -153,6 +161,17 @@ export function registerApp(appName: string, routes: OpenmrsAppRoutes) { } }); + availableWorkspaceGroups.forEach((workspaceGroup) => { + if (workspaceGroup && typeof workspaceGroup === 'object' && Object.hasOwn(workspaceGroup, 'name')) { + tryRegisterWorkspaceGroup(appName, workspaceGroup); + } else { + console.warn( + `A workspace group for ${appName} could not be registered as it does not appear to have the required properties`, + workspaceGroup, + ); + } + }); + availableFeatureFlags.forEach((featureFlag) => { if (featureFlag && typeof featureFlag === 'object' && Object.hasOwn(featureFlag, 'flagName')) { tryRegisterFeatureFlag(appName, featureFlag); diff --git a/packages/framework/esm-styleguide/src/workspaces/workspaces.test.ts b/packages/framework/esm-styleguide/src/workspaces/workspaces.test.ts index 51052e473..e7d026d26 100644 --- a/packages/framework/esm-styleguide/src/workspaces/workspaces.test.ts +++ b/packages/framework/esm-styleguide/src/workspaces/workspaces.test.ts @@ -1,5 +1,5 @@ import { clearMockExtensionRegistry } from '@openmrs/esm-framework/mock'; -import { registerExtension, registerWorkspace } from '@openmrs/esm-extensions'; +import { registerExtension, registerWorkspace, registerWorkspaceGroup } from '@openmrs/esm-extensions'; import { type Prompt, cancelPrompt, @@ -555,7 +555,7 @@ describe('workspace system', () => { }); expect(workspaceGroupStore).toBeTruthy(); - expect(workspaceGroupStore?.getState()?.['foo']).toBe(true); + expect(workspaceGroupStore?.getState()['foo']).toBe(true); }); it('should update the store state with new additionalProps if workspaces with same workspaceGroup name calls the function', () => { @@ -564,15 +564,15 @@ describe('workspace system', () => { }); expect(workspaceGroupStore).toBeTruthy(); - expect(workspaceGroupStore?.getState()?.['foo']).toBe(true); + expect(workspaceGroupStore?.getState()['foo']).toBe(true); workspaceGroupStore = getWorkspaceGroupStore('ward-patient-store', { bar: true, }); expect(workspaceGroupStore).toBeTruthy(); - expect(workspaceGroupStore?.getState()?.['foo']).toBe(true); - expect(workspaceGroupStore?.getState()?.['bar']).toBe(true); + expect(workspaceGroupStore?.getState()['foo']).toBe(true); + expect(workspaceGroupStore?.getState()['bar']).toBe(true); }); }); @@ -590,7 +590,11 @@ describe('workspace system', () => { load: jest.fn(), type: 'ward-patient', moduleName: '@openmrs/esm-ward-app', - groups: ['ward-patient-store'], + }); + + registerWorkspaceGroup({ + name: 'ward-patient-store', + members: ['ward-patient-workspace'], }); launchWorkspaceGroup('ward-patient-store', { @@ -620,7 +624,10 @@ describe('workspace system', () => { load: jest.fn(), type: 'ward-patient', moduleName: '@openmrs/esm-ward-app', - groups: ['ward-patient-store'], + }); + registerWorkspaceGroup({ + name: 'ward-patient-store', + members: ['ward-patient-workspace'], }); launchWorkspaceGroup('ward-patient-store', { state: { @@ -647,7 +654,6 @@ describe('workspace system', () => { load: jest.fn(), type: 'ward-patient', moduleName: '@openmrs/esm-ward-app', - groups: [workspaceGroup], }); registerWorkspace({ name: 'transfer-patient-workspace', @@ -655,7 +661,10 @@ describe('workspace system', () => { load: jest.fn(), type: 'transfer-patient', moduleName: '@openmrs/esm-ward-app', - groups: [workspaceGroup], + }); + registerWorkspaceGroup({ + name: workspaceGroup, + members: ['ward-patient-workspace', 'transfer-patient-workspace'], }); launchWorkspaceGroup(workspaceGroup, { @@ -689,7 +698,6 @@ describe('workspace system', () => { load: jest.fn(), type: 'ward-patient', moduleName: '@openmrs/esm-ward-app', - groups: ['ward-patient-store'], }); registerWorkspace({ name: 'transfer-patient-workspace', @@ -697,7 +705,16 @@ describe('workspace system', () => { load: jest.fn(), type: 'transfer-patient', moduleName: '@openmrs/esm-ward-app', - groups: ['another-sidebar-group'], + }); + + registerWorkspaceGroup({ + name: 'ward-patient-store', + members: ['ward-patient-workspace'], + }); + + registerWorkspaceGroup({ + name: 'another-sidebar-group', + members: ['transfer-patient-workspace'], }); const workspaceStore = getWorkspaceStore(); @@ -737,7 +754,6 @@ describe('workspace system', () => { type: 'ward-patient', moduleName: '@openmrs/esm-ward-app', canHide: true, - groups: ['ward-patient-store'], }); registerWorkspace({ name: 'transfer-patient-workspace', @@ -745,7 +761,11 @@ describe('workspace system', () => { load: jest.fn(), type: 'transfer-patient', moduleName: '@openmrs/esm-ward-app', - groups: ['ward-patient-store'], + }); + + registerWorkspaceGroup({ + name: 'ward-patient-store', + members: ['ward-patient-workspace', 'transfer-patient-workspace'], }); const workspaceStore = getWorkspaceStore(); @@ -776,7 +796,10 @@ describe('workspace system', () => { load: jest.fn(), type: 'ward-patient', moduleName: '@openmrs/esm-ward-app', - groups: ['ward-patient-store'], + }); + registerWorkspaceGroup({ + name: 'ward-patient-store', + members: ['ward-patient-workspace'], }); launchWorkspaceGroup('ward-patient-store', { state: { foo: true }, diff --git a/packages/framework/esm-styleguide/src/workspaces/workspaces.ts b/packages/framework/esm-styleguide/src/workspaces/workspaces.ts index 3f3fd26b1..790da90c0 100644 --- a/packages/framework/esm-styleguide/src/workspaces/workspaces.ts +++ b/packages/framework/esm-styleguide/src/workspaces/workspaces.ts @@ -1,6 +1,11 @@ /** @module @category Workspace */ import { useMemo, type ReactNode } from 'react'; -import { getWorkspaceRegistration, type WorkspaceRegistration } from '@openmrs/esm-extensions'; +import { + getWorkspaceGroupRegistration, + getWorkspaceRegistration, + WorkspaceGroupRegistration, + type WorkspaceRegistration, +} from '@openmrs/esm-extensions'; import { type WorkspaceWindowState } from '@openmrs/esm-globals'; import { navigate } from '@openmrs/esm-navigation'; import { getGlobalStore, createGlobalStore } from '@openmrs/esm-state'; @@ -101,6 +106,7 @@ export interface WorkspaceStoreState { workspaceWindowState: WorkspaceWindowState; workspaceGroup?: { name: string; + members: Array; cleanup?: Function; }; } @@ -203,6 +209,7 @@ interface LaunchWorkspaceGroupArg { * }); */ export function launchWorkspaceGroup(groupName: string, args: LaunchWorkspaceGroupArg) { + const workspaceGroupRegistration = getWorkspaceGroupRegistration(groupName); const { state, onWorkspaceGroupLaunch, workspaceGroupCleanup, workspaceToLaunch } = args; const store = getWorkspaceStore(); if (store.getState().openWorkspaces.length) { @@ -221,6 +228,7 @@ export function launchWorkspaceGroup(groupName: string, args: LaunchWorkspaceGro ...prev, workspaceGroup: { name: groupName, + members: workspaceGroupRegistration.members, cleanup: workspaceGroupCleanup, }, })); @@ -293,7 +301,7 @@ export function launchWorkspace< const workspace = getWorkspaceRegistration(name); const currentWorkspaceGroup = store.getState().workspaceGroup; - if (currentWorkspaceGroup && !workspace.groups?.includes(currentWorkspaceGroup?.name)) { + if (currentWorkspaceGroup && !currentWorkspaceGroup.members?.includes(name)) { closeWorkspaceGroup(currentWorkspaceGroup.name, () => { launchWorkspace(name, additionalProps); }); diff --git a/packages/framework/esm-translations/translations/bn.json b/packages/framework/esm-translations/translations/bn.json new file mode 100644 index 000000000..6ae6e0fbe --- /dev/null +++ b/packages/framework/esm-translations/translations/bn.json @@ -0,0 +1,60 @@ +{ + "actions": "Actions", + "address": "Address", + "address1": "Address line 1", + "address2": "Address line 2", + "address3": "Address line 3", + "address4": "Address line 4", + "address5": "Address line 5", + "address6": "Address line 6", + "age": "Age", + "cancel": "Cancel", + "change": "Change", + "city": "City", + "cityVillage": "City", + "Clinic": "Clinic", + "close": "Close", + "closeAllOpenedWorkspaces": "Discard changes in {{count}} workspaces", + "closingAllWorkspacesPromptBody": "There are unsaved changes in the following workspaces. Do you want to discard changes in the following workspaces? {{workspaceNames}}", + "closingAllWorkspacesPromptTitle": "You have unsaved changes", + "confirm": "Confirm", + "contactAdministratorIfIssuePersists": "Contact your system administrator if the problem persists.", + "contactDetails": "Contact Details", + "country": "Country", + "countyDistrict": "District", + "discard": "Discard", + "district": "District", + "error": "Error", + "errorCopy": "Sorry, there was a problem displaying this information. You can try to reload this page, or contact the site administrator and quote the error code above.", + "female": "Female", + "hide": "Hide", + "loading": "Loading", + "male": "Male", + "maximize": "Maximize", + "minimize": "Minimize", + "openAnyway": "Open Anyway", + "other": "Other", + "patientIdentifierSticker": "Patient identifier sticker", + "patientLists": "Patient Lists", + "postalCode": "Postal code", + "print": "Print", + "printError": "Print error", + "printErrorExplainer": "An error occurred in {{errorLocation}}", + "printIdentifierSticker": "Print identifier sticker", + "printing": "Printing", + "relationships": "Relationships", + "resetOverrides": "Reset overrides", + "save": "Save", + "scriptLoadingError": "Failed to load overridden script from {{url}}. Please check that the bundled script is available at the expected URL. Click the button below to reset all import map overrides.", + "scriptLoadingFailed": "Error: Script failed to load", + "seeMoreLists": "See {{count}} more lists", + "sex": "Sex", + "showLess": "Show less", + "showMore": "Show more", + "state": "State", + "stateProvince": "State", + "unknown": "Unknown", + "unsavedChangesInWorkspace": "There are unsaved changes in {{workspaceName}}. Please save them before opening another workspace.", + "unsavedChangesTitleText": "Unsaved changes", + "workspaceHeader": "Workspace header" +} diff --git a/packages/framework/esm-translations/translations/lg.json b/packages/framework/esm-translations/translations/lg.json new file mode 100644 index 000000000..6ae6e0fbe --- /dev/null +++ b/packages/framework/esm-translations/translations/lg.json @@ -0,0 +1,60 @@ +{ + "actions": "Actions", + "address": "Address", + "address1": "Address line 1", + "address2": "Address line 2", + "address3": "Address line 3", + "address4": "Address line 4", + "address5": "Address line 5", + "address6": "Address line 6", + "age": "Age", + "cancel": "Cancel", + "change": "Change", + "city": "City", + "cityVillage": "City", + "Clinic": "Clinic", + "close": "Close", + "closeAllOpenedWorkspaces": "Discard changes in {{count}} workspaces", + "closingAllWorkspacesPromptBody": "There are unsaved changes in the following workspaces. Do you want to discard changes in the following workspaces? {{workspaceNames}}", + "closingAllWorkspacesPromptTitle": "You have unsaved changes", + "confirm": "Confirm", + "contactAdministratorIfIssuePersists": "Contact your system administrator if the problem persists.", + "contactDetails": "Contact Details", + "country": "Country", + "countyDistrict": "District", + "discard": "Discard", + "district": "District", + "error": "Error", + "errorCopy": "Sorry, there was a problem displaying this information. You can try to reload this page, or contact the site administrator and quote the error code above.", + "female": "Female", + "hide": "Hide", + "loading": "Loading", + "male": "Male", + "maximize": "Maximize", + "minimize": "Minimize", + "openAnyway": "Open Anyway", + "other": "Other", + "patientIdentifierSticker": "Patient identifier sticker", + "patientLists": "Patient Lists", + "postalCode": "Postal code", + "print": "Print", + "printError": "Print error", + "printErrorExplainer": "An error occurred in {{errorLocation}}", + "printIdentifierSticker": "Print identifier sticker", + "printing": "Printing", + "relationships": "Relationships", + "resetOverrides": "Reset overrides", + "save": "Save", + "scriptLoadingError": "Failed to load overridden script from {{url}}. Please check that the bundled script is available at the expected URL. Click the button below to reset all import map overrides.", + "scriptLoadingFailed": "Error: Script failed to load", + "seeMoreLists": "See {{count}} more lists", + "sex": "Sex", + "showLess": "Show less", + "showMore": "Show more", + "state": "State", + "stateProvince": "State", + "unknown": "Unknown", + "unsavedChangesInWorkspace": "There are unsaved changes in {{workspaceName}}. Please save them before opening another workspace.", + "unsavedChangesTitleText": "Unsaved changes", + "workspaceHeader": "Workspace header" +} diff --git a/packages/framework/esm-translations/translations/pt_BR.json b/packages/framework/esm-translations/translations/pt_BR.json index 6ae6e0fbe..a0a649911 100644 --- a/packages/framework/esm-translations/translations/pt_BR.json +++ b/packages/framework/esm-translations/translations/pt_BR.json @@ -1,60 +1,60 @@ { - "actions": "Actions", - "address": "Address", - "address1": "Address line 1", - "address2": "Address line 2", - "address3": "Address line 3", - "address4": "Address line 4", - "address5": "Address line 5", - "address6": "Address line 6", - "age": "Age", - "cancel": "Cancel", - "change": "Change", - "city": "City", - "cityVillage": "City", - "Clinic": "Clinic", - "close": "Close", - "closeAllOpenedWorkspaces": "Discard changes in {{count}} workspaces", - "closingAllWorkspacesPromptBody": "There are unsaved changes in the following workspaces. Do you want to discard changes in the following workspaces? {{workspaceNames}}", - "closingAllWorkspacesPromptTitle": "You have unsaved changes", - "confirm": "Confirm", - "contactAdministratorIfIssuePersists": "Contact your system administrator if the problem persists.", - "contactDetails": "Contact Details", - "country": "Country", - "countyDistrict": "District", - "discard": "Discard", - "district": "District", - "error": "Error", - "errorCopy": "Sorry, there was a problem displaying this information. You can try to reload this page, or contact the site administrator and quote the error code above.", - "female": "Female", - "hide": "Hide", - "loading": "Loading", - "male": "Male", - "maximize": "Maximize", - "minimize": "Minimize", - "openAnyway": "Open Anyway", - "other": "Other", - "patientIdentifierSticker": "Patient identifier sticker", - "patientLists": "Patient Lists", - "postalCode": "Postal code", - "print": "Print", - "printError": "Print error", - "printErrorExplainer": "An error occurred in {{errorLocation}}", - "printIdentifierSticker": "Print identifier sticker", - "printing": "Printing", - "relationships": "Relationships", - "resetOverrides": "Reset overrides", - "save": "Save", - "scriptLoadingError": "Failed to load overridden script from {{url}}. Please check that the bundled script is available at the expected URL. Click the button below to reset all import map overrides.", - "scriptLoadingFailed": "Error: Script failed to load", - "seeMoreLists": "See {{count}} more lists", - "sex": "Sex", - "showLess": "Show less", - "showMore": "Show more", - "state": "State", - "stateProvince": "State", - "unknown": "Unknown", - "unsavedChangesInWorkspace": "There are unsaved changes in {{workspaceName}}. Please save them before opening another workspace.", - "unsavedChangesTitleText": "Unsaved changes", - "workspaceHeader": "Workspace header" + "actions": "Ações", + "address": "Endereço", + "address1": "Linha de Endereço 1", + "address2": "Linha de Endereço 2", + "address3": "Linha de Endereço 3", + "address4": "Linha de endereço 4", + "address5": "Linha de Endereço 5", + "address6": "Linha de Endereço 6", + "age": "Idade", + "cancel": "Cancelar", + "change": "Alterar", + "city": "Cidade", + "cityVillage": "Cidade", + "Clinic": "Clínica", + "close": "Fechar", + "closeAllOpenedWorkspaces": "Descartar alterações em {{count}} espaços de trabalho ", + "closingAllWorkspacesPromptBody": "Há alterações não salvas nos seguintes espaços de trabalho. Deseja descartar as alterações nos seguintes espaços de trabalho? {{workspaceNames}}", + "closingAllWorkspacesPromptTitle": "Você tem alterações não salvas", + "confirm": "Confirmar", + "contactAdministratorIfIssuePersists": "Entre em contato com o administrador do sistema se o problema persistir.", + "contactDetails": "Detalhes de contato", + "country": "País", + "countyDistrict": "Distrito", + "discard": "Descarte", + "district": "Distrito", + "error": "Erro", + "errorCopy": "Desculpe, houve um problema ao exibir essas informações. Você pode tentar recarregar esta página ou entrar em contato com o administrador do site e informar o código de erro acima.", + "female": "Feminino", + "hide": "Esconder", + "loading": "Carregando", + "male": "Masculino", + "maximize": "Maximizar", + "minimize": "Minimizar", + "openAnyway": "Abrir de qualquer forma", + "other": "Outros", + "patientIdentifierSticker": "Adesivo de identificação do paciente", + "patientLists": "Listas de pacientes", + "postalCode": "Código postal", + "print": "Imprimir", + "printError": "Erro de impressão", + "printErrorExplainer": "Ocorreu um erro em {{errorLocation}}", + "printIdentifierSticker": "Imprimir adesivo identificador", + "printing": "Impressão", + "relationships": "Relacionamentos", + "resetOverrides": "Redefinir substituições", + "save": "Salvar", + "scriptLoadingError": "Falha ao carregar o script substituído de {{url}}. Verifique se o script empacotado está disponível no URL esperado. Clique no botão abaixo para redefinir todas as substituições do mapa de importação.", + "scriptLoadingFailed": "Erro: Falha ao carregar o script", + "seeMoreLists": "Veja mais {{count}} listas", + "sex": "Sexo", + "showLess": "Mostrar menos", + "showMore": "Mostrar mais", + "state": "Estado", + "stateProvince": "Estado", + "unknown": "Desconhecido", + "unsavedChangesInWorkspace": "Há alterações não salvas em {{workspaceName}}. Salve-as antes de abrir outro espaço de trabalho.", + "unsavedChangesTitleText": "Alterações não salvas", + "workspaceHeader": "Cabeçalho do espaço de trabalho" } diff --git a/packages/framework/esm-translations/translations/ru_RU.json b/packages/framework/esm-translations/translations/ru_RU.json new file mode 100644 index 000000000..6ae6e0fbe --- /dev/null +++ b/packages/framework/esm-translations/translations/ru_RU.json @@ -0,0 +1,60 @@ +{ + "actions": "Actions", + "address": "Address", + "address1": "Address line 1", + "address2": "Address line 2", + "address3": "Address line 3", + "address4": "Address line 4", + "address5": "Address line 5", + "address6": "Address line 6", + "age": "Age", + "cancel": "Cancel", + "change": "Change", + "city": "City", + "cityVillage": "City", + "Clinic": "Clinic", + "close": "Close", + "closeAllOpenedWorkspaces": "Discard changes in {{count}} workspaces", + "closingAllWorkspacesPromptBody": "There are unsaved changes in the following workspaces. Do you want to discard changes in the following workspaces? {{workspaceNames}}", + "closingAllWorkspacesPromptTitle": "You have unsaved changes", + "confirm": "Confirm", + "contactAdministratorIfIssuePersists": "Contact your system administrator if the problem persists.", + "contactDetails": "Contact Details", + "country": "Country", + "countyDistrict": "District", + "discard": "Discard", + "district": "District", + "error": "Error", + "errorCopy": "Sorry, there was a problem displaying this information. You can try to reload this page, or contact the site administrator and quote the error code above.", + "female": "Female", + "hide": "Hide", + "loading": "Loading", + "male": "Male", + "maximize": "Maximize", + "minimize": "Minimize", + "openAnyway": "Open Anyway", + "other": "Other", + "patientIdentifierSticker": "Patient identifier sticker", + "patientLists": "Patient Lists", + "postalCode": "Postal code", + "print": "Print", + "printError": "Print error", + "printErrorExplainer": "An error occurred in {{errorLocation}}", + "printIdentifierSticker": "Print identifier sticker", + "printing": "Printing", + "relationships": "Relationships", + "resetOverrides": "Reset overrides", + "save": "Save", + "scriptLoadingError": "Failed to load overridden script from {{url}}. Please check that the bundled script is available at the expected URL. Click the button below to reset all import map overrides.", + "scriptLoadingFailed": "Error: Script failed to load", + "seeMoreLists": "See {{count}} more lists", + "sex": "Sex", + "showLess": "Show less", + "showMore": "Show more", + "state": "State", + "stateProvince": "State", + "unknown": "Unknown", + "unsavedChangesInWorkspace": "There are unsaved changes in {{workspaceName}}. Please save them before opening another workspace.", + "unsavedChangesTitleText": "Unsaved changes", + "workspaceHeader": "Workspace header" +} diff --git a/packages/framework/esm-translations/translations/uz.json b/packages/framework/esm-translations/translations/uz.json new file mode 100644 index 000000000..6ae6e0fbe --- /dev/null +++ b/packages/framework/esm-translations/translations/uz.json @@ -0,0 +1,60 @@ +{ + "actions": "Actions", + "address": "Address", + "address1": "Address line 1", + "address2": "Address line 2", + "address3": "Address line 3", + "address4": "Address line 4", + "address5": "Address line 5", + "address6": "Address line 6", + "age": "Age", + "cancel": "Cancel", + "change": "Change", + "city": "City", + "cityVillage": "City", + "Clinic": "Clinic", + "close": "Close", + "closeAllOpenedWorkspaces": "Discard changes in {{count}} workspaces", + "closingAllWorkspacesPromptBody": "There are unsaved changes in the following workspaces. Do you want to discard changes in the following workspaces? {{workspaceNames}}", + "closingAllWorkspacesPromptTitle": "You have unsaved changes", + "confirm": "Confirm", + "contactAdministratorIfIssuePersists": "Contact your system administrator if the problem persists.", + "contactDetails": "Contact Details", + "country": "Country", + "countyDistrict": "District", + "discard": "Discard", + "district": "District", + "error": "Error", + "errorCopy": "Sorry, there was a problem displaying this information. You can try to reload this page, or contact the site administrator and quote the error code above.", + "female": "Female", + "hide": "Hide", + "loading": "Loading", + "male": "Male", + "maximize": "Maximize", + "minimize": "Minimize", + "openAnyway": "Open Anyway", + "other": "Other", + "patientIdentifierSticker": "Patient identifier sticker", + "patientLists": "Patient Lists", + "postalCode": "Postal code", + "print": "Print", + "printError": "Print error", + "printErrorExplainer": "An error occurred in {{errorLocation}}", + "printIdentifierSticker": "Print identifier sticker", + "printing": "Printing", + "relationships": "Relationships", + "resetOverrides": "Reset overrides", + "save": "Save", + "scriptLoadingError": "Failed to load overridden script from {{url}}. Please check that the bundled script is available at the expected URL. Click the button below to reset all import map overrides.", + "scriptLoadingFailed": "Error: Script failed to load", + "seeMoreLists": "See {{count}} more lists", + "sex": "Sex", + "showLess": "Show less", + "showMore": "Show more", + "state": "State", + "stateProvince": "State", + "unknown": "Unknown", + "unsavedChangesInWorkspace": "There are unsaved changes in {{workspaceName}}. Please save them before opening another workspace.", + "unsavedChangesTitleText": "Unsaved changes", + "workspaceHeader": "Workspace header" +} diff --git a/packages/framework/esm-translations/translations/zh_CN.json b/packages/framework/esm-translations/translations/zh_CN.json index 9613c43a4..e9a09c111 100644 --- a/packages/framework/esm-translations/translations/zh_CN.json +++ b/packages/framework/esm-translations/translations/zh_CN.json @@ -3,27 +3,27 @@ "address": "地址", "address1": "地址行1", "address2": "地址行2", - "address3": "Address line 3", - "address4": "Address line 4", - "address5": "Address line 5", - "address6": "Address line 6", - "age": "Age", + "address3": "地址行3", + "address4": "地址行4", + "address5": "地址行5", + "address6": "地址行6", + "age": "年龄", "cancel": "取消", "change": "更改", "city": "城市", "cityVillage": "城市", - "Clinic": "Clinic", + "Clinic": "临床", "close": "关闭", "closeAllOpenedWorkspaces": "放弃 {{count}} 个工作区中的更改", "closingAllWorkspacesPromptBody": "以下工作区中有未保存的更改。您是否要放弃这些工作区中的更改? {{workspaceNames}}", "closingAllWorkspacesPromptTitle": "您有未保存的更改", "confirm": "确认", - "contactAdministratorIfIssuePersists": "Contact your system administrator if the problem persists.", + "contactAdministratorIfIssuePersists": "如果问题仍然存在,请与系统管理员联系。", "contactDetails": "联系方式", "country": "国家", "countyDistrict": "区县", "discard": "放弃", - "district": "District", + "district": "区县", "error": "错误", "errorCopy": "抱歉,显示此信息时出现问题。您可以尝试重新加载此页面,或联系网站管理员并引用上面的错误代码。", "female": "女性", @@ -34,27 +34,27 @@ "minimize": "最小化", "openAnyway": "仍然打开", "other": "其他", - "patientIdentifierSticker": "Patient identifier sticker", + "patientIdentifierSticker": "患者标识符标签", "patientLists": "患者列表", "postalCode": "邮政编码", - "print": "Print", - "printError": "Print error", - "printErrorExplainer": "An error occurred in {{errorLocation}}", - "printIdentifierSticker": "Print identifier sticker", - "printing": "Printing", + "print": "打印", + "printError": "打印错误", + "printErrorExplainer": "{{errorLocation}}处发生一个错误", + "printIdentifierSticker": "打印标识标签", + "printing": "打印中", "relationships": "关系", "resetOverrides": "重置覆盖", - "save": "Save", + "save": "保存", "scriptLoadingError": "无法从{{url}}加载覆盖脚本。请检查捆绑脚本是否可在预期的URL上可用。点击下面的按钮重置所有导入的映射覆盖。", "scriptLoadingFailed": "错误:脚本加载失败", "seeMoreLists": "查看{{count}}个更多列表", - "sex": "Sex", - "showLess": "Show less", - "showMore": "Show more", + "sex": "性别", + "showLess": "显示较少", + "showMore": "显示更多", "state": "省份", "stateProvince": "省份", "unknown": "未知", "unsavedChangesInWorkspace": "{{workspaceName}} 中有未保存的更改。请在打开另一个工作区之前保存它们。", - "unsavedChangesTitleText": "Unsaved changes", - "workspaceHeader": "Workspace header" + "unsavedChangesTitleText": "未保存的更改", + "workspaceHeader": "工作区标题" } diff --git a/packages/framework/esm-utils/src/age-helpers.test.ts b/packages/framework/esm-utils/src/age-helpers.test.ts index 3d1ad83f9..135c901c4 100644 --- a/packages/framework/esm-utils/src/age-helpers.test.ts +++ b/packages/framework/esm-utils/src/age-helpers.test.ts @@ -9,6 +9,7 @@ describe('Age Helper', () => { // https://webarchive.nationalarchives.gov.uk/ukgwa/20160921162509mp_/http://systems.digital.nhs.uk/data/cui/uig/patben.pdf // (Table 8) const now = dayjs('2024-07-30'); + const test0 = now; const test1 = now.subtract(1, 'hour').subtract(30, 'minutes'); const test2 = now.subtract(1, 'day').subtract(2, 'hours').subtract(5, 'minutes'); const test3 = now.subtract(3, 'days').subtract(17, 'hours').subtract(30, 'minutes'); @@ -22,6 +23,7 @@ describe('Age Helper', () => { const test11 = now.subtract(18, 'year').subtract(39, 'day'); it('should render durations correctly', () => { + expect(age(test0, now)).toBe('0 min'); expect(age(test1, now)).toBe('90 min'); expect(age(test2, now)).toBe('26 hr'); expect(age(test3, now)).toBe('3 days'); diff --git a/packages/framework/esm-utils/src/age-helpers.ts b/packages/framework/esm-utils/src/age-helpers.ts index f0103a25b..a6ecf3535 100644 --- a/packages/framework/esm-utils/src/age-helpers.ts +++ b/packages/framework/esm-utils/src/age-helpers.ts @@ -2,7 +2,7 @@ import dayjs from 'dayjs'; import { getLocale } from './omrs-dates'; import { DurationFormat } from '@formatjs/intl-durationformat'; -import { type DurationInput } from '@formatjs/intl-durationformat/src/types'; +import { type DurationFormatOptions, type DurationInput } from '@formatjs/intl-durationformat/src/types'; /** * Gets a human readable and locale supported representation of a person's age, given their birthDate, @@ -32,9 +32,14 @@ export function age(birthDate: dayjs.ConfigType, currentDate: dayjs.ConfigType = const locale = getLocale(); + const options: DurationFormatOptions = { style: 'short', localeMatcher: 'lookup' }; + if (hourDiff < 2) { const minuteDiff = to.diff(from, 'minutes'); duration['minutes'] = minuteDiff; + if (minuteDiff == 0) { + options.minutesDisplay = 'always'; + } } else if (dayDiff < 2) { duration['hours'] = hourDiff; } else if (weekDiff < 4) { @@ -55,5 +60,5 @@ export function age(birthDate: dayjs.ConfigType, currentDate: dayjs.ConfigType = duration['years'] = yearDiff; } - return new DurationFormat(locale, { style: 'short', localeMatcher: 'lookup' }).format(duration); + return new DurationFormat(locale, options).format(duration); } diff --git a/packages/tooling/openmrs/src/cli.ts b/packages/tooling/openmrs/src/cli.ts index f0022aefd..931cb2e36 100644 --- a/packages/tooling/openmrs/src/cli.ts +++ b/packages/tooling/openmrs/src/cli.ts @@ -29,51 +29,79 @@ yargs.command( 'Starts a new debugging session of the OpenMRS app shell. This uses Webpack as a debug server with proxy middleware.', (argv) => argv - .number('port') - .default('port', 8080) - .describe('port', 'The port where the dev server should run.') - .number('host') - .default('host', 'localhost') - .describe('host', 'The host name or IP for the server to use.') - .string('backend') - .default('backend', 'https://dev3.openmrs.org/') - .describe('backend', 'The backend to proxy API requests to.') - .string('add-cookie') - .default('add-cookie', '') - .describe('add-cookie', 'Additional cookies to provide when proxying.') - .boolean('support-offline') - .describe('support-offline', 'Determines if a service worker should be installed for offline support.') - .default('support-offline', false) - .string('spa-path') - .default('spa-path', '/openmrs/spa/') - .describe('spa-path', 'The path of the application on the target server.') - .string('api-url') - .default('api-url', '/openmrs/') - .describe('api-url', 'The URL of the API. Can be a path if the API is on the same target server.') - .string('page-title') - .default('page-title', 'OpenMRS') - .describe('page-title', 'The title of the web app usually displayed in the browser tab.') - .array('config-url') - .default('config-url', []) - .describe('config-url', 'The URL to a valid frontend configuration. Can be used multiple times.') - .boolean('run-project') - .default('run-project', false) - .describe('run-project', 'Runs the project in the current directory fusing it with the specified import map.') - .array('sources') - .default('sources', ['.']) - .describe('sources', 'Runs the projects from the provided source directories. Can be used multiple times.') - .array('shared-dependencies') - .default('shared-dependencies', []) - .describe('shared-dependencies', 'The additional shared dependencies besides the ones from the app shell.') - .string('importmap') - .default('importmap', 'importmap.json') - .describe( - 'importmap', - 'The import map to use. Can be a path to a valid import map to be taken literally, an URL, or a fixed JSON object.', - ) - .string('routes') - .default('routes', 'routes.registry.json') - .describe('routes', 'The routes.registry.json file to use.'), + .option('port', { + default: 8080, + describe: 'The port where the dev server should run.', + type: 'number', + }) + .option('host', { + default: 'localhost', + describe: 'The host name or IP for the server to use.', + type: 'string', + }) + .option('backend', { + default: 'https://dev3.openmrs.org', + describe: 'The backend to proxy API requests to.', + type: 'string', + coerce: (arg) => (arg.endsWith('/') ? arg.slice(0, -1) : arg), + }) + .option('add-cookie', { + default: '', + describe: 'Additional cookies to provide when proxying.', + type: 'string', + }) + .option('spa-path', { + default: '/openmrs/spa/', + describe: 'The path of the application on the target server.', + type: 'string', + }) + .option('api-url', { + default: '/openmrs/', + describe: 'The URL of the API. Can be a path if the API is on the same target server.', + type: 'string', + }) + .option('open', { + default: true, + describe: 'Immediately opens the SPA page URL in the browser.', + type: 'boolean', + }) + .option('config-url', { + default: [], + describe: 'The URL to a valid frontend configuration. Can be used multiple times.', + type: 'array', + }) + .option('config-file', { + default: [], + describe: 'The path to a frontend configuration file. Can be used multiple times.', + type: 'array', + }) + .option('sources', { + default: ['.'], + describe: 'Runs the projects from the provided source directories. Can be used multiple times.', + type: 'array', + }) + .option('shared-dependencies', { + default: [], + describe: 'The additional shared dependencies besides the ones from the app shell.', + type: 'array', + }) + .option('importmap', { + default: 'importmap.json', + describe: + 'The import map to use. Can be a path to a valid import map to be taken literally, an URL, or a fixed JSON object.', + type: 'string', + }) + .option('routes', { + default: 'routes.registry.json', + describe: + 'The routes.registry.json file to use. Can be a path to a valid routes registry to be taken literally, an URL, or a fixed JSON object.', + type: 'string', + }) + .option('support-offline', { + default: false, + describe: 'Determines if a service worker should be installed for offline support.', + type: 'boolean', + }), async (args) => runCommand('runDebug', { configUrls: args['config-url'], @@ -81,11 +109,10 @@ yargs.command( ...proxyImportmapAndRoutes( await mergeImportmapAndRoutes( await getImportmapAndRoutes(args.importmap, args.routes, args.port), - (args['run-project'] || (args.runProject as boolean)) && (await runProject(args.port, args.sources)), + await runProject(args.port, args.sources), ), args.backend, - args.host, - args.port, + args.spaPath, ), }), ); @@ -95,51 +122,79 @@ yargs.command( 'Starts a new frontend module development session with the OpenMRS app shell.', (argv) => argv - .number('port') - .default('port', 8080) - .describe('port', 'The port where the dev server should run.') - .number('host') - .default('host', 'localhost') - .describe('host', 'The host name or IP for the server to use.') - .string('backend') - .default('backend', 'https://dev3.openmrs.org/') - .describe('backend', 'The backend to proxy API requests to.') - .string('add-cookie') - .default('add-cookie', '') - .describe('add-cookie', 'Additional cookies to provide when proxying.') - .string('spa-path') - .default('spa-path', '/openmrs/spa/') - .describe('spa-path', 'The path of the application on the target server.') - .string('api-url') - .default('api-url', '/openmrs/') - .describe('api-url', 'The URL of the API. Can be a path if the API is on the same target server.') - .boolean('open') - .default('open', true) - .describe('open', 'Immediately opens the SPA page URL in the browser.') - .array('config-url') - .default('config-url', []) - .describe('config-url', 'The URL to a valid frontend configuration. Can be used multiple times.') - .array('config-file') - .default('config-file', []) - .describe('config-file', 'The path to a frontend configuration file. Can be used multiple times.') - .array('sources') - .default('sources', ['.']) - .describe('sources', 'Runs the projects from the provided source directories. Can be used multiple times.') - .array('shared-dependencies') - .default('shared-dependencies', []) - .describe('shared-dependencies', 'The additional shared dependencies besides the ones from the app shell.') - .string('importmap') - .default('importmap', 'importmap.json') - .describe( - 'importmap', - 'The import map to use. Can be a path to a valid import map to be taken literally, an URL, or a fixed JSON object.', - ) - .string('routes') - .default('routes', 'routes.registry.json') - .describe('routes', 'The routes.registry.json file to use.') - .boolean('support-offline') - .default('support-offline', false) - .describe('support-offline', 'Determines if a service worker should be installed for offline support.'), + .option('port', { + default: 8080, + describe: 'The port where the dev server should run.', + type: 'number', + }) + .option('host', { + default: 'localhost', + describe: 'The host name or IP for the server to use.', + type: 'string', + }) + .option('backend', { + default: 'https://dev3.openmrs.org', + describe: 'The backend to proxy API requests to.', + type: 'string', + coerce: (arg) => (arg.endsWith('/') ? arg.slice(0, -1) : arg), + }) + .option('add-cookie', { + default: '', + describe: 'Additional cookies to provide when proxying.', + type: 'string', + }) + .option('spa-path', { + default: '/openmrs/spa/', + describe: 'The path of the application on the target server.', + type: 'string', + }) + .option('api-url', { + default: '/openmrs/', + describe: 'The URL of the API. Can be a path if the API is on the same target server.', + type: 'string', + }) + .option('open', { + default: true, + describe: 'Immediately opens the SPA page URL in the browser.', + type: 'boolean', + }) + .option('config-url', { + default: [], + describe: 'The URL to a valid frontend configuration. Can be used multiple times.', + type: 'array', + }) + .option('config-file', { + default: [], + describe: 'The path to a frontend configuration file. Can be used multiple times.', + type: 'array', + }) + .option('sources', { + default: ['.'], + describe: 'Runs the projects from the provided source directories. Can be used multiple times.', + type: 'array', + }) + .option('shared-dependencies', { + default: [], + describe: 'The additional shared dependencies besides the ones from the app shell.', + type: 'array', + }) + .option('importmap', { + default: 'importmap.json', + describe: + 'The import map to use. Can be a path to a valid import map to be taken literally, an URL, or a fixed JSON object.', + type: 'string', + }) + .option('routes', { + default: 'routes.registry.json', + describe: + 'The routes.registry.json file to use. Can be a path to a valid routes registry to be taken literally, an URL, or a fixed JSON object.', + type: 'string', + }) + .option('support-offline', { + default: false, + describe: 'Determines if a service worker should be installed for offline support.', + type: 'boolean', + }), async (args) => runCommand('runDevelop', { configUrls: args['config-url'], @@ -148,13 +203,12 @@ yargs.command( ...proxyImportmapAndRoutes( await mergeImportmapAndRoutes( await getImportmapAndRoutes(args.importmap, args.routes, args.port), - (args.sources[0] as string | boolean) !== false && (await runProject(args.port, args.sources)), + await runProject(args.port, args.sources), args.backend, args.spaPath, ), args.backend, - args.host, - args.port, + args.spaPath, ), }), ); diff --git a/packages/tooling/openmrs/src/commands/debug.ts b/packages/tooling/openmrs/src/commands/debug.ts index 2132f7a6b..abe30fa66 100644 --- a/packages/tooling/openmrs/src/commands/debug.ts +++ b/packages/tooling/openmrs/src/commands/debug.ts @@ -6,7 +6,6 @@ export interface DebugArgs { host: string; backend: string; importmap: ImportmapDeclaration; - pageTitle: string; supportOffline?: boolean; spaPath: string; apiUrl: string; diff --git a/packages/tooling/openmrs/src/utils/importmap.ts b/packages/tooling/openmrs/src/utils/importmap.ts index 9d4305df6..f27af51a6 100644 --- a/packages/tooling/openmrs/src/utils/importmap.ts +++ b/packages/tooling/openmrs/src/utils/importmap.ts @@ -226,8 +226,10 @@ export async function runProject( } /** - * @param decl The initial import map declaration - * @param additionalImports New imports to add + * @param importAndRoutes An ImportmapAndRoutes object that holds the current import map and routes registries + * @param additionalImportsAndRoutes An object containing any import map entries, routes, and watched route files to add to the setup + * @param backend The URL for the backend + * @param spaPath The spaPath for this instance * @returns The import map declaration with the new imports added in. If * there are new imports to add, and if the original import map declaration * had type "url", it is downloaded and resolved to one of type "inline". @@ -366,18 +368,15 @@ export async function getRoutes(routesPath: string): Promise } /** - * @param decl An import map declaration of type "inline" - * @param backend The backend which is being proxied by the dev server - * @param host The dev server host - * @param port The dev server port - * @returns The same import map declaration but with all imports from - * `backend` changed to import from `http://${host}:${port}`. + * @param importmapAndRoutes An ImportmapAndRoutes object that holds the import map and routes registry + * @param backend The URL for the backend + * @param spaPath The spaPath for this instance + * @returns The same import map declaration but with all imports changed to the appropriate path */ export function proxyImportmapAndRoutes( importmapAndRoutes: ImportmapAndRoutesWithWatches, backend: string, - host: string, - port: number, + spaPath: string, ) { const { importMap: importMapDecl, routes: routesDecl, watchedRoutesPaths } = importmapAndRoutes; if (importMapDecl.type != 'inline') { @@ -393,11 +392,14 @@ export function proxyImportmapAndRoutes( ); } + const backendUrl = new URL(backend); const importmap = JSON.parse(importMapDecl.value); + const spaPathRegEx = new RegExp('^' + spaPath.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&').replace(/-/g, '\\x2d')); + Object.keys(importmap.imports).forEach((key) => { - const url = importmap.imports[key]; - if (url.startsWith(backend)) { - importmap.imports[key] = url.replace(backend, ''); + const url = new URL(importmap.imports[key], backendUrl); + if (url.protocol === backendUrl.protocol && url.host === backendUrl.host) { + importmap.imports[key] = `./${url.pathname.replace(spaPathRegEx, '')}${url.search}${url.hash}`; } }); importMapDecl.value = JSON.stringify(importmap);