From ddd97b8ad011e10038a57427c957e15f79fb7d2f Mon Sep 17 00:00:00 2001
From: Priyanka Terala <104053200+Terala-Priyanka@users.noreply.github.com>
Date: Thu, 30 May 2024 14:56:49 +0530
Subject: [PATCH 01/11] UITEN-290 - Make dependency on mod-reading-rooms
optional. (#407)
---
CHANGELOG.md | 5 +++--
package.json | 8 ++++----
src/settings/index.js | 3 ++-
3 files changed, 9 insertions(+), 7 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6845b214..d93aca6a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,16 +1,17 @@
# Change history for ui-tenant-settings
-## 9.0.0 (IN PROGRESS)
+## 8.2.0 (IN PROGRESS)
* [UITEN-274](https://folio-org.atlassian.net/browse/UITEN-274) Use Save & close button label stripes-component translation key.
* [UITEN-280](https://folio-org.atlassian.net/browse/UITEN-280) Conditionally include SSO Settings based on login-saml interface.
-* [UITEN-286](https://folio-org.atlassian.net/browse/UITEN-286) *BREAKING* Add new interface. Add new permission to view reading room access in tenant settings.
+* [UITEN-286](https://folio-org.atlassian.net/browse/UITEN-286) Add new interface. Add new permission to view reading room access in tenant settings.
* [UITEN-287](https://folio-org.atlassian.net/browse/UITEN-287) Add new permission to create, edit and remove reading room access in tenant settings.
* [UITEN-277](https://issues.folio.org/browse/UITEN-277) Ensure Reading Room Access settings page is wrapped by `Title Manager`.
* [UITEN-276](https://issues.folio.org/browse/UITEN-276) Reading Room Access (settings): Basic Layout.
* [UITEN-278] (https://issues.folio.org/browse/UITEN-278) Reading Room Access (settings): Create new reading room.
* [UITEN-282] (https://issues.folio.org/browse/UITEN-282) Reading Room Access (settings): Update reading room.
* [UITEN-283] (https://issues.folio.org/browse/UITEN-283) Reading Room Access (settings): Delete reading room.
+* [UITEN-290] (https://issues.folio.org/browse/UITEN-290) Make dependency on mod-reading-rooms optional.
## [8.1.0](https://github.com/folio-org/ui-tenant-settings/tree/v8.1.0)(2024-03-19)
[Full Changelog](https://github.com/folio-org/ui-tenant-settings/compare/v8.0.0...v8.1.0)
diff --git a/package.json b/package.json
index 484d7ed7..c1ce21e0 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@folio/tenant-settings",
- "version": "9.0.0",
+ "version": "8.1.0",
"description": "Tenant settings",
"main": "src/index.js",
"repository": "folio-org/ui-tenant-settings",
@@ -17,8 +17,7 @@
"route": "/tenant-settings",
"okapiInterfaces": {
"configuration": "2.0",
- "users": "15.0 16.0",
- "reading-room": "1.0"
+ "users": "15.0 16.0"
},
"optionalOkapiInterfaces": {
"location-units": "2.0",
@@ -26,7 +25,8 @@
"login-saml": "2.0",
"remote-storage-configurations": "1.0",
"remote-storage-mappings": "1.0 2.0",
- "service-points": "3.0"
+ "service-points": "3.0",
+ "reading-room": "1.0"
},
"permissionSets": [
{
diff --git a/src/settings/index.js b/src/settings/index.js
index 57875c2e..51800ac1 100644
--- a/src/settings/index.js
+++ b/src/settings/index.js
@@ -62,7 +62,8 @@ class Organization extends React.Component {
route: 'reading-room',
label: ,
component: ReadingRoomAccess,
- perm: 'ui-tenant-settings.settings.reading-room-access.view'
+ perm: 'ui-tenant-settings.settings.reading-room-access.view',
+ iface: 'reading-room'
},
{
route: 'servicePoints',
From 5382d67ab55742a332354254e5dd028189ee1915 Mon Sep 17 00:00:00 2001
From: FOLIO Translations Bot
<38661258+folio-translations@users.noreply.github.com>
Date: Thu, 20 Jun 2024 09:44:30 -0400
Subject: [PATCH 02/11] Lokalise: updates
---
translations/ui-tenant-settings/fr_FR.json | 22 +++++++++++-----------
translations/ui-tenant-settings/pt_BR.json | 4 ++--
2 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/translations/ui-tenant-settings/fr_FR.json b/translations/ui-tenant-settings/fr_FR.json
index 5413340d..f8b03c98 100644
--- a/translations/ui-tenant-settings/fr_FR.json
+++ b/translations/ui-tenant-settings/fr_FR.json
@@ -111,20 +111,20 @@
"settings.locale.localeWarning": "Les paramètres de cette page modifieront de manière PERMANENTE les paramètres régionaux (y compris l'affichage de la langue, le format de la date et le format des nombres) pour tous les utilisateurs. Il est fortement déconseillé de modifier les paramètres régionaux ici, sauf si vous êtes absolument certain que c'est la bonne action. Pour modifier TEMPORAIREMENT les paramètres régionaux de votre session uniquement, cliquez sur le bouton \" {label} \" à la place.",
"settings.locale.changeSessionLocale": "Changer langue et les paramètres régionaux de la session",
"settings.pluginNames.create-inventory-records": "Créer des enregistrements d'inventaire / de catalogue",
- "settings.pluginNames.find-user": "Trouver un utilisateur",
+ "settings.pluginNames.find-user": "Rechercher un utilisateur",
"settings.pluginNames.find-instance": "Rechercher une instance",
"settings.pluginNames.find-import-profile": "Rechercher un profil d'importation",
- "settings.pluginNames.find-eresource": "Trouver une ressource électronique",
- "settings.pluginNames.find-contact": "Trouver un contact",
- "settings.pluginNames.find-organization": "Trouver une organisation",
+ "settings.pluginNames.find-eresource": "Rechercher une ressource électronique",
+ "settings.pluginNames.find-contact": "Rechercher un contact",
+ "settings.pluginNames.find-organization": "Rechercher une organisation",
"settings.pluginNames.create-item": "Créer un exemplaire",
- "settings.pluginNames.find-interface": "Trouver une interface",
- "settings.pluginNames.find-license": "Trouver une licence",
- "settings.pluginNames.find-agreement": "Trouver un accord",
- "settings.pluginNames.find-po-line": "Trouver la ligne de commande",
+ "settings.pluginNames.find-interface": "Rechercher une interface",
+ "settings.pluginNames.find-license": "Rechercher une licence",
+ "settings.pluginNames.find-agreement": "Rechercher un accord",
+ "settings.pluginNames.find-po-line": "Rechercher la ligne de commande",
"settings.pluginNames.find-package-title": "Rechercher le titre du bouquet",
"settings.pluginNames.find-finc-metadata-collection": "Find finance metadata collection",
- "settings.pluginNames.find-erm-usage-data-provider": "Trouver un fournisseur de métadonnées d'utilisation ERM",
+ "settings.pluginNames.find-erm-usage-data-provider": "Rechercher un fournisseur de métadonnées d'utilisation ERM",
"settings.pluginNames.find-finc-metadata-source": "Rechercher une source de métadonnées financières",
"permission.module.enabled": "UI: Tenant-settings module is enabled",
"permission.settings.addresses": "Paramètres (tenant) : peut gérer l'adresse des tenants",
@@ -172,8 +172,8 @@
"settings.addresses.cannotDeleteTermHeader": "Impossible de supprimer l'adresse",
"settings.addresses.cannotDeleteTermMessage": "This address cannot be deleted, as it is in use by one or more records.",
"settings.addresses.deleteEntry": "Supprimer l'adresse",
- "settings.addresses.termDeleted": "L'adresse {term} a été supprimée avec succès ",
- "settings.addresses.termWillBeDeleted": "L'adresse {term} sera supprimée. ",
+ "settings.addresses.termDeleted": "L'adresse {term} a été supprimée avec succès",
+ "settings.addresses.termWillBeDeleted": "L'adresse {term} sera supprimée.",
"settings.confirmPickupLocationChangeModal.title": "Confirm Pickup location change",
"settings.confirmPickupLocationChangeModal.message": "Changing this Pickup location from \"Yes\" to \"No\" will remove it from existing Request policies and affect all Circulation rules using the policies.",
"settings.confirmPickupLocationChangeModal.button.confirm": "Confirm",
diff --git a/translations/ui-tenant-settings/pt_BR.json b/translations/ui-tenant-settings/pt_BR.json
index 215e3646..b49ec421 100644
--- a/translations/ui-tenant-settings/pt_BR.json
+++ b/translations/ui-tenant-settings/pt_BR.json
@@ -15,8 +15,8 @@
"settings.saml.validate.userProperty": "Por favor, selecione uma propriedade de usuário",
"settings.saml.validate.idpUrl": "Este não é um URL válido do Provedor de identidade",
"settings.saml.idpUrl": "URL do provedor de identidade",
- "settings.saml.downloadMetadata": "Download de metadados",
- "settings.saml.idpUrlChanged": "O URL do IdP foi alterado desde o último download. Faça o download dos metadados do ponto de serviço e faça o upload novamente para o IdP.",
+ "settings.saml.downloadMetadata": "Baixar metadados",
+ "settings.saml.idpUrlChanged": "A URL do IdP foi alterado desde o último download. Faça o download dos metadados do ponto de serviço e recarregue novamente para o IdP.",
"settings.saml.binding": "Ligação SAML",
"settings.saml.attribute": "Atributo SAML",
"settings.saml.userProperty": "Propriedade do usuário",
From 777efda08b1d2534f417f5a65de289878092a009 Mon Sep 17 00:00:00 2001
From: FOLIO Translations Bot
<38661258+folio-translations@users.noreply.github.com>
Date: Tue, 2 Jul 2024 18:42:56 -0400
Subject: [PATCH 03/11] Lokalise: updates
---
translations/ui-tenant-settings/pt_BR.json | 6 +++---
translations/ui-tenant-settings/zh_CN.json | 24 +++++++++++-----------
2 files changed, 15 insertions(+), 15 deletions(-)
diff --git a/translations/ui-tenant-settings/pt_BR.json b/translations/ui-tenant-settings/pt_BR.json
index b49ec421..4c4bc844 100644
--- a/translations/ui-tenant-settings/pt_BR.json
+++ b/translations/ui-tenant-settings/pt_BR.json
@@ -35,7 +35,7 @@
"settings.location.locations.location": "Localização",
"settings.location.locations.generalInformation": "Informação geral",
"settings.location.locations.name": "Nome do FOLIO",
- "settings.location.locations.discoveryDisplayName": "Nome de exibição no serviço de descoberta",
+ "settings.location.locations.discoveryDisplayName": "Nome de exibição na descoberta",
"settings.location.locations.status": "Status",
"settings.location.locations.active": "Ativo",
"settings.location.locations.inactive": "Inativo",
@@ -58,7 +58,7 @@
"settings.servicePoints.new": "Novo ponto de serviço",
"settings.servicePoints.generalInformation": "Informação geral",
"settings.servicePoints.code": "Código",
- "settings.servicePoints.discoveryDisplayName": "Nome de exibição no serviço de descoberta",
+ "settings.servicePoints.discoveryDisplayName": "Nome de exibição na descoberta",
"settings.servicePoints.description": "Descrição",
"settings.servicePoints.shelvingLagTime": "Tempo de atraso para guarda na estante de exemplar devolvido (em minutos)",
"settings.servicePoints.pickupLocation": "Localização de retirada",
@@ -110,7 +110,7 @@
"settings.save.error.network": "Registro não foi salvo",
"settings.locale.localeWarning": "As configurações nesta página alterarão PERMANENTEMENTE o código de idioma (incluindo exibição de idioma, formato de data e formato de número) para todos os usuários. Você é fortemente desencorajado de alterar o código de idioma aqui, a menos que tenha certeza absoluta de que é a ação correta. Para alterar temporariamente o código de idioma da sua sessão, clique no botão \"{label}\".",
"settings.locale.changeSessionLocale": "Alterar idioma da sessão",
- "settings.pluginNames.create-inventory-records": "Criar registros de inventário",
+ "settings.pluginNames.create-inventory-records": "Criar registros de catalogação",
"settings.pluginNames.find-user": "Encontrar usuário",
"settings.pluginNames.find-instance": "Encontrar instância",
"settings.pluginNames.find-import-profile": "Encontrar perfil de importação",
diff --git a/translations/ui-tenant-settings/zh_CN.json b/translations/ui-tenant-settings/zh_CN.json
index ce892b01..8e046b9e 100644
--- a/translations/ui-tenant-settings/zh_CN.json
+++ b/translations/ui-tenant-settings/zh_CN.json
@@ -199,16 +199,16 @@
"settings.items.title": "租户设置 - {item}",
"settings.location.createNew.title": "租户设置 - 新位置",
"settings.items.edit.title": "租户设置 - 编辑: {item}",
- "permission.settings.reading-room-access.view": "Settings (tenant): Can view reading room access",
- "permission.settings.reading-room-access.all": "Settings (tenant): Can create, edit and remove reading room access",
- "settings.reading-room.title": "Tenant settings - Reading room access",
- "settings.reading-room-access.label": "Reading room access",
- "settings.reading-room-access.name": "Room name",
- "settings.reading-room-access.public": "Public",
- "settings.reading-room-access.asp": "Associated service points",
- "settings.reading-room-access.cannotDeleteTermHeader": "Cannot delete reading room access",
- "settings.reading-room-access.cannotDeleteTermMessage": "This reading room access cannot be deleted, as it is in use by one or more records.",
- "settings.reading-room-access.deleteEntry": "Delete reading room access",
- "settings.reading-room-access.termDeleted": "The reading room access {term} was successfully deleted",
- "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted"
+ "permission.settings.reading-room-access.view": "设置(租户):可查看阅览室访问",
+ "permission.settings.reading-room-access.all": "设置(租户):可以创建、编辑和删除阅览室访问",
+ "settings.reading-room.title": "租户设置 - 阅览室访问",
+ "settings.reading-room-access.label": "阅览室访问",
+ "settings.reading-room-access.name": "房间名称",
+ "settings.reading-room-access.public": "公开",
+ "settings.reading-room-access.asp": "相关服务点",
+ "settings.reading-room-access.cannotDeleteTermHeader": "无法删除阅览室访问",
+ "settings.reading-room-access.cannotDeleteTermMessage": "无法删除此阅览室访问,因为它正在被一条或多条记录使用。",
+ "settings.reading-room-access.deleteEntry": "删除阅览室访问",
+ "settings.reading-room-access.termDeleted": "阅览室访问 {term} 已成功删除",
+ "settings.reading-room-access.termWillBeDeleted": "阅览室 {term} 将被删除"
}
\ No newline at end of file
From c70e491aa6feaef0058698c7039386e2ca7c19cf Mon Sep 17 00:00:00 2001
From: Priyanka Terala <104053200+Terala-Priyanka@users.noreply.github.com>
Date: Thu, 4 Jul 2024 16:57:24 +0530
Subject: [PATCH 04/11] UITEN-298 - supply correct translation ids (#410)
---
CHANGELOG.md | 1 +
src/settings/ReadingRoomAccess/ReadingRoomAccess.js | 4 ++--
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d93aca6a..d7106c25 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,6 +12,7 @@
* [UITEN-282] (https://issues.folio.org/browse/UITEN-282) Reading Room Access (settings): Update reading room.
* [UITEN-283] (https://issues.folio.org/browse/UITEN-283) Reading Room Access (settings): Delete reading room.
* [UITEN-290] (https://issues.folio.org/browse/UITEN-290) Make dependency on mod-reading-rooms optional.
+* [UITEN-298] (https://issues.folio.org/browse/UITEN-298) Update translation ids for reading room.
## [8.1.0](https://github.com/folio-org/ui-tenant-settings/tree/v8.1.0)(2024-03-19)
[Full Changelog](https://github.com/folio-org/ui-tenant-settings/compare/v8.0.0...v8.1.0)
diff --git a/src/settings/ReadingRoomAccess/ReadingRoomAccess.js b/src/settings/ReadingRoomAccess/ReadingRoomAccess.js
index ef5b9a2b..8dc0e697 100644
--- a/src/settings/ReadingRoomAccess/ReadingRoomAccess.js
+++ b/src/settings/ReadingRoomAccess/ReadingRoomAccess.js
@@ -18,8 +18,8 @@ import { getValidators } from './getValidators';
const hiddenFields = ['numberOfObjects', 'lastUpdated'];
const translations = {
- cannotDeleteTermHeader: 'ui-tenant-settings.settings.addresses.cannotDeleteTermHeader',
- cannotDeleteTermMessage: 'ui-tenant-settings.settings.addresses.cannotDeleteTermMessage',
+ cannotDeleteTermHeader: 'ui-tenant-settings.settings.reading-room-access.cannotDeleteTermHeader',
+ cannotDeleteTermMessage: 'ui-tenant-settings.settings.reading-room-access.cannotDeleteTermMessage',
deleteEntry: 'ui-tenant-settings.settings.reading-room-access.deleteEntry',
termDeleted: 'ui-tenant-settings.settings.reading-room-access.termDeleted',
termWillBeDeleted: 'ui-tenant-settings.settings.reading-room-access.termWillBeDeleted',
From 1e77ab650a9c89c7086737d3706f4b6abc656dbd Mon Sep 17 00:00:00 2001
From: FOLIO Translations Bot
<38661258+folio-translations@users.noreply.github.com>
Date: Tue, 9 Jul 2024 18:13:17 -0400
Subject: [PATCH 05/11] Lokalise: updates
---
translations/ui-tenant-settings/fr_FR.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/translations/ui-tenant-settings/fr_FR.json b/translations/ui-tenant-settings/fr_FR.json
index f8b03c98..79b057fc 100644
--- a/translations/ui-tenant-settings/fr_FR.json
+++ b/translations/ui-tenant-settings/fr_FR.json
@@ -110,7 +110,7 @@
"settings.save.error.network": "Enregistrement non sauvegardé",
"settings.locale.localeWarning": "Les paramètres de cette page modifieront de manière PERMANENTE les paramètres régionaux (y compris l'affichage de la langue, le format de la date et le format des nombres) pour tous les utilisateurs. Il est fortement déconseillé de modifier les paramètres régionaux ici, sauf si vous êtes absolument certain que c'est la bonne action. Pour modifier TEMPORAIREMENT les paramètres régionaux de votre session uniquement, cliquez sur le bouton \" {label} \" à la place.",
"settings.locale.changeSessionLocale": "Changer langue et les paramètres régionaux de la session",
- "settings.pluginNames.create-inventory-records": "Créer des enregistrements d'inventaire / de catalogue",
+ "settings.pluginNames.create-inventory-records": "Créer des notices de catalogue",
"settings.pluginNames.find-user": "Rechercher un utilisateur",
"settings.pluginNames.find-instance": "Rechercher une instance",
"settings.pluginNames.find-import-profile": "Rechercher un profil d'importation",
From f7339b615c2a1e9fac1178f09c0c6d015b8f3c9f Mon Sep 17 00:00:00 2001
From: Priyanka Terala <104053200+Terala-Priyanka@users.noreply.github.com>
Date: Wed, 10 Jul 2024 18:17:30 +0530
Subject: [PATCH 06/11] UITEN-301 - Display Reading room access in alphabetical
order on settings page. (#412)
* UITEN-301 - Display Reading room access in alphabetical order on settings page.
* UITEN-301 - add unit tests
---
CHANGELOG.md | 1 +
src/settings/index.js | 14 +++++++-------
src/settings/index.test.js | 21 +++++++++++++++++++++
test/jest/__new_mocks__/stripesCore.mock.js | 2 +-
4 files changed, 30 insertions(+), 8 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d7106c25..dcc1f8e2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,6 +13,7 @@
* [UITEN-283] (https://issues.folio.org/browse/UITEN-283) Reading Room Access (settings): Delete reading room.
* [UITEN-290] (https://issues.folio.org/browse/UITEN-290) Make dependency on mod-reading-rooms optional.
* [UITEN-298] (https://issues.folio.org/browse/UITEN-298) Update translation ids for reading room.
+* [UITEN-301] (https://issues.folio.org/browse/UITEN-301) Display Reading room access in alphabetical order on settings page.
## [8.1.0](https://github.com/folio-org/ui-tenant-settings/tree/v8.1.0)(2024-03-19)
[Full Changelog](https://github.com/folio-org/ui-tenant-settings/compare/v8.0.0...v8.1.0)
diff --git a/src/settings/index.js b/src/settings/index.js
index 51800ac1..323ed55f 100644
--- a/src/settings/index.js
+++ b/src/settings/index.js
@@ -51,13 +51,6 @@ class Organization extends React.Component {
component: Plugins,
perm: 'ui-tenant-settings.settings.plugins.view',
},
- {
- route: 'ssosettings',
- label: ,
- component: SSOSettings,
- perm: 'ui-tenant-settings.settings.sso.view',
- iface: 'login-saml'
- },
{
route: 'reading-room',
label: ,
@@ -65,6 +58,13 @@ class Organization extends React.Component {
perm: 'ui-tenant-settings.settings.reading-room-access.view',
iface: 'reading-room'
},
+ {
+ route: 'ssosettings',
+ label: ,
+ component: SSOSettings,
+ perm: 'ui-tenant-settings.settings.sso.view',
+ iface: 'login-saml'
+ },
{
route: 'servicePoints',
label: ,
diff --git a/src/settings/index.test.js b/src/settings/index.test.js
index d9778acd..d77e36c7 100644
--- a/src/settings/index.test.js
+++ b/src/settings/index.test.js
@@ -36,10 +36,12 @@ describe('Organization', () => {
};
stripes.setIsAuthenticated = jest.fn();
stripes.hasInterface = jest.fn().mockReturnValue(false);
+ stripes.hasPerm = jest.fn().mockReturnValue(false);
});
it('should render SSO Settings when login-saml interface is present', () => {
stripes.hasInterface = jest.fn().mockReturnValue(true);
+ stripes.hasPerm = jest.fn().mockReturnValue(true);
const { queryByText } = renderWithRouter();
expect(queryByText('ui-tenant-settings.settings.ssoSettings.label')).toBeTruthy();
});
@@ -48,4 +50,23 @@ describe('Organization', () => {
const { queryByText } = renderWithRouter();
expect(queryByText('ui-tenant-settings.settings.ssoSettings.label')).toBeNull();
});
+
+ it('should render Reading room access when associated permission and interface are present', () => {
+ stripes.hasInterface = jest.fn().mockReturnValue(true);
+ stripes.hasPerm = jest.fn().mockReturnValue(true);
+ const { queryByText } = renderWithRouter();
+ expect(queryByText('ui-tenant-settings.settings.reading-room-access.label')).toBeTruthy();
+ });
+
+ it('should not render Reading room access when ui-tenant-settings.settings.reading-room-access.view permission is not present', () => {
+ stripes.hasInterface = jest.fn().mockReturnValue(true);
+ const { queryByText } = renderWithRouter();
+ expect(queryByText('ui-tenant-settings.settings.reading-room-access.label')).toBeNull();
+ });
+
+ it('should not render Reading room access when reading-room interface is not present', () => {
+ stripes.hasPerm = jest.fn().mockReturnValue(true);
+ const { queryByText } = renderWithRouter();
+ expect(queryByText('ui-tenant-settings.settings.reading-room-access.label')).toBeNull();
+ });
});
diff --git a/test/jest/__new_mocks__/stripesCore.mock.js b/test/jest/__new_mocks__/stripesCore.mock.js
index 2b1d3773..9fb3bd2b 100644
--- a/test/jest/__new_mocks__/stripesCore.mock.js
+++ b/test/jest/__new_mocks__/stripesCore.mock.js
@@ -10,7 +10,7 @@ const buildStripes = (otherProperties = {}) => ({
},
currency: 'USD',
hasInterface: () => true,
- hasPerm: jest.fn(() => true),
+ hasPerm: () => true,
locale: 'en-US',
logger: {
log: () => { },
From f0a79f53e2f5b2c2ced0e6589b40fd78ee0c5cfc Mon Sep 17 00:00:00 2001
From: FOLIO Translations Bot
<38661258+folio-translations@users.noreply.github.com>
Date: Sat, 13 Jul 2024 13:56:50 -0400
Subject: [PATCH 07/11] Lokalise: updates
---
translations/ui-tenant-settings/fr_FR.json | 2 +-
translations/ui-tenant-settings/pt_BR.json | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/translations/ui-tenant-settings/fr_FR.json b/translations/ui-tenant-settings/fr_FR.json
index 79b057fc..f6e0073b 100644
--- a/translations/ui-tenant-settings/fr_FR.json
+++ b/translations/ui-tenant-settings/fr_FR.json
@@ -175,7 +175,7 @@
"settings.addresses.termDeleted": "L'adresse {term} a été supprimée avec succès",
"settings.addresses.termWillBeDeleted": "L'adresse {term} sera supprimée.",
"settings.confirmPickupLocationChangeModal.title": "Confirm Pickup location change",
- "settings.confirmPickupLocationChangeModal.message": "Changing this Pickup location from \"Yes\" to \"No\" will remove it from existing Request policies and affect all Circulation rules using the policies.",
+ "settings.confirmPickupLocationChangeModal.message": "Changer ce point de retrait de \"Oui\" à \"Non\" le supprimera des politiques de réservations existantes et s'appliquera à toutes les règles de circulation utilisant ces politiques.",
"settings.confirmPickupLocationChangeModal.button.confirm": "Confirm",
"settings.confirmPickupLocationChangeModal.button.cancel": "Back",
"permission.settings.tenant-settings.view": "Settings (tenant): View",
diff --git a/translations/ui-tenant-settings/pt_BR.json b/translations/ui-tenant-settings/pt_BR.json
index 4c4bc844..77662b8b 100644
--- a/translations/ui-tenant-settings/pt_BR.json
+++ b/translations/ui-tenant-settings/pt_BR.json
@@ -60,7 +60,7 @@
"settings.servicePoints.code": "Código",
"settings.servicePoints.discoveryDisplayName": "Nome de exibição na descoberta",
"settings.servicePoints.description": "Descrição",
- "settings.servicePoints.shelvingLagTime": "Tempo de atraso para guarda na estante de exemplar devolvido (em minutos)",
+ "settings.servicePoints.shelvingLagTime": "Tempo de atraso para guarda na estante de exemplar devolvido (em minutos)",
"settings.servicePoints.pickupLocation": "Localização de retirada",
"settings.servicePoints.feeFineOwner": "Dono da taxa/multa",
"settings.servicePoints.deleteServicePoint": "Excluir ponto de serviço",
From 3b4ee2fea104ece73c5ae5016d9ab02a2ba26d4b Mon Sep 17 00:00:00 2001
From: UladzislauKutarkin
<72550466+UladzislauKutarkin@users.noreply.github.com>
Date: Fri, 26 Jul 2024 12:56:27 +0400
Subject: [PATCH 08/11] UITEN-212: Permission changes for service point
management (#414)
---
CHANGELOG.md | 1 +
package.json | 5 ++---
translations/ui-tenant-settings/en.json | 2 +-
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index dcc1f8e2..d889c0ca 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,6 +14,7 @@
* [UITEN-290] (https://issues.folio.org/browse/UITEN-290) Make dependency on mod-reading-rooms optional.
* [UITEN-298] (https://issues.folio.org/browse/UITEN-298) Update translation ids for reading room.
* [UITEN-301] (https://issues.folio.org/browse/UITEN-301) Display Reading room access in alphabetical order on settings page.
+* [UITEN-212](https://folio-org.atlassian.net/browse/UITEN-212) Permission changes for service point management.
## [8.1.0](https://github.com/folio-org/ui-tenant-settings/tree/v8.1.0)(2024-03-19)
[Full Changelog](https://github.com/folio-org/ui-tenant-settings/compare/v8.0.0...v8.1.0)
diff --git a/package.json b/package.json
index c1ce21e0..3098caaa 100644
--- a/package.json
+++ b/package.json
@@ -200,12 +200,11 @@
},
{
"permissionName": "ui-tenant-settings.settings.servicepoints",
- "displayName": "Settings (tenant): Can create, edit and remove service points",
+ "displayName": "Settings (tenant): Can create and edit service points",
"subPermissions": [
"ui-tenant-settings.settings.servicepoints.view",
"inventory-storage.service-points.item.post",
- "inventory-storage.service-points.item.put",
- "inventory-storage.service-points.item.delete"
+ "inventory-storage.service-points.item.put"
],
"visible": true
},
diff --git a/translations/ui-tenant-settings/en.json b/translations/ui-tenant-settings/en.json
index a7512009..300476e6 100644
--- a/translations/ui-tenant-settings/en.json
+++ b/translations/ui-tenant-settings/en.json
@@ -223,7 +223,7 @@
"permission.settings.sso.view": "Settings (tenant): Can view SSO settings",
"permission.settings.location": "Settings (tenant): Can create, edit and remove locations",
"permission.settings.location.view": "Settings (Tenant): View locations",
- "permission.settings.servicepoints": "Settings (tenant): Can create, edit and remove service points",
+ "permission.settings.servicepoints": "Settings (tenant): Can create and edit service points",
"permission.settings.servicepoints.view": "Settings (tenant): Can view service points",
"permission.settings.bursar-exports": "Settings (tenant): Bursar admin",
"permission.settings.reading-room-access.view": "Settings (tenant): Can view reading room access",
From de327163d7cfb319ba25d4449be5a391cf6f5525 Mon Sep 17 00:00:00 2001
From: FOLIO Translations Bot
<38661258+folio-translations@users.noreply.github.com>
Date: Sat, 27 Jul 2024 14:37:33 -0400
Subject: [PATCH 09/11] Lokalise: updates
---
translations/ui-tenant-settings/ber.json | 2 +-
translations/ui-tenant-settings/ca.json | 2 +-
translations/ui-tenant-settings/cs_CZ.json | 2 +-
translations/ui-tenant-settings/en_GB.json | 2 +-
translations/ui-tenant-settings/en_SE.json | 2 +-
translations/ui-tenant-settings/en_US.json | 2 +-
translations/ui-tenant-settings/es.json | 2 +-
translations/ui-tenant-settings/es_ES.json | 2 +-
translations/ui-tenant-settings/fr.json | 2 +-
translations/ui-tenant-settings/fr_FR.json | 84 +++++++++++-----------
translations/ui-tenant-settings/he.json | 2 +-
translations/ui-tenant-settings/hi_IN.json | 2 +-
translations/ui-tenant-settings/hu.json | 2 +-
translations/ui-tenant-settings/nb.json | 2 +-
translations/ui-tenant-settings/nl.json | 2 +-
translations/ui-tenant-settings/nn.json | 2 +-
translations/ui-tenant-settings/pt_BR.json | 2 +-
translations/ui-tenant-settings/pt_PT.json | 2 +-
translations/ui-tenant-settings/ru.json | 2 +-
translations/ui-tenant-settings/sk.json | 2 +-
translations/ui-tenant-settings/sv.json | 2 +-
translations/ui-tenant-settings/ur.json | 2 +-
22 files changed, 63 insertions(+), 63 deletions(-)
diff --git a/translations/ui-tenant-settings/ber.json b/translations/ui-tenant-settings/ber.json
index c06141e0..a98803e2 100644
--- a/translations/ui-tenant-settings/ber.json
+++ b/translations/ui-tenant-settings/ber.json
@@ -133,7 +133,7 @@
"permission.settings.plugins": "Settings (tenant): Can maintain preferred plugins",
"permission.settings.sso": "Settings (tenant): Can maintain SSO settings",
"permission.settings.location": "Settings (tenant): Can create, edit and remove locations",
- "permission.settings.servicepoints": "Settings (tenant): Can create, edit and remove service points",
+ "permission.settings.servicepoints": "Settings (tenant): Can create and edit service points",
"settings.location.remotes.remote": "Remote storage",
"settings.location.remotes.no": "No (default)",
"settings.location.remotes.loading": "loading...",
diff --git a/translations/ui-tenant-settings/ca.json b/translations/ui-tenant-settings/ca.json
index c06141e0..a98803e2 100644
--- a/translations/ui-tenant-settings/ca.json
+++ b/translations/ui-tenant-settings/ca.json
@@ -133,7 +133,7 @@
"permission.settings.plugins": "Settings (tenant): Can maintain preferred plugins",
"permission.settings.sso": "Settings (tenant): Can maintain SSO settings",
"permission.settings.location": "Settings (tenant): Can create, edit and remove locations",
- "permission.settings.servicepoints": "Settings (tenant): Can create, edit and remove service points",
+ "permission.settings.servicepoints": "Settings (tenant): Can create and edit service points",
"settings.location.remotes.remote": "Remote storage",
"settings.location.remotes.no": "No (default)",
"settings.location.remotes.loading": "loading...",
diff --git a/translations/ui-tenant-settings/cs_CZ.json b/translations/ui-tenant-settings/cs_CZ.json
index a0de6399..22b553ef 100644
--- a/translations/ui-tenant-settings/cs_CZ.json
+++ b/translations/ui-tenant-settings/cs_CZ.json
@@ -133,7 +133,7 @@
"permission.settings.plugins": "Nastavení (nájemce): Může udržovat preferované pluginy",
"permission.settings.sso": "Nastavení (nájemce): Může udržovat nastavení SSO",
"permission.settings.location": "Nastavení (nájemce): Může vytvářet, upravovat a odstraňovat lokace",
- "permission.settings.servicepoints": "Nastavení (nájemce): Může vytvářet, upravovat a odebírat pulty služeb",
+ "permission.settings.servicepoints": "Nastavení (nájemce): Může vytvářet a upravovat pulty služeb",
"settings.location.remotes.remote": "Vzdálené úložiště",
"settings.location.remotes.no": "Ne (výchozí)",
"settings.location.remotes.loading": "načítání...",
diff --git a/translations/ui-tenant-settings/en_GB.json b/translations/ui-tenant-settings/en_GB.json
index c06141e0..a98803e2 100644
--- a/translations/ui-tenant-settings/en_GB.json
+++ b/translations/ui-tenant-settings/en_GB.json
@@ -133,7 +133,7 @@
"permission.settings.plugins": "Settings (tenant): Can maintain preferred plugins",
"permission.settings.sso": "Settings (tenant): Can maintain SSO settings",
"permission.settings.location": "Settings (tenant): Can create, edit and remove locations",
- "permission.settings.servicepoints": "Settings (tenant): Can create, edit and remove service points",
+ "permission.settings.servicepoints": "Settings (tenant): Can create and edit service points",
"settings.location.remotes.remote": "Remote storage",
"settings.location.remotes.no": "No (default)",
"settings.location.remotes.loading": "loading...",
diff --git a/translations/ui-tenant-settings/en_SE.json b/translations/ui-tenant-settings/en_SE.json
index c06141e0..a98803e2 100644
--- a/translations/ui-tenant-settings/en_SE.json
+++ b/translations/ui-tenant-settings/en_SE.json
@@ -133,7 +133,7 @@
"permission.settings.plugins": "Settings (tenant): Can maintain preferred plugins",
"permission.settings.sso": "Settings (tenant): Can maintain SSO settings",
"permission.settings.location": "Settings (tenant): Can create, edit and remove locations",
- "permission.settings.servicepoints": "Settings (tenant): Can create, edit and remove service points",
+ "permission.settings.servicepoints": "Settings (tenant): Can create and edit service points",
"settings.location.remotes.remote": "Remote storage",
"settings.location.remotes.no": "No (default)",
"settings.location.remotes.loading": "loading...",
diff --git a/translations/ui-tenant-settings/en_US.json b/translations/ui-tenant-settings/en_US.json
index c06141e0..a98803e2 100644
--- a/translations/ui-tenant-settings/en_US.json
+++ b/translations/ui-tenant-settings/en_US.json
@@ -133,7 +133,7 @@
"permission.settings.plugins": "Settings (tenant): Can maintain preferred plugins",
"permission.settings.sso": "Settings (tenant): Can maintain SSO settings",
"permission.settings.location": "Settings (tenant): Can create, edit and remove locations",
- "permission.settings.servicepoints": "Settings (tenant): Can create, edit and remove service points",
+ "permission.settings.servicepoints": "Settings (tenant): Can create and edit service points",
"settings.location.remotes.remote": "Remote storage",
"settings.location.remotes.no": "No (default)",
"settings.location.remotes.loading": "loading...",
diff --git a/translations/ui-tenant-settings/es.json b/translations/ui-tenant-settings/es.json
index 0133f790..64ed6ed3 100644
--- a/translations/ui-tenant-settings/es.json
+++ b/translations/ui-tenant-settings/es.json
@@ -133,7 +133,7 @@
"permission.settings.plugins": "Settings (tenant): Can maintain preferred plugins",
"permission.settings.sso": "Settings (tenant): Can maintain SSO settings",
"permission.settings.location": "Settings (tenant): Can create, edit and remove locations",
- "permission.settings.servicepoints": "Settings (tenant): Can create, edit and remove service points",
+ "permission.settings.servicepoints": "Settings (tenant): Can create and edit service points",
"settings.location.remotes.remote": "Remote storage",
"settings.location.remotes.no": "No (default)",
"settings.location.remotes.loading": "loading...",
diff --git a/translations/ui-tenant-settings/es_ES.json b/translations/ui-tenant-settings/es_ES.json
index b1d91c96..70c4bc44 100644
--- a/translations/ui-tenant-settings/es_ES.json
+++ b/translations/ui-tenant-settings/es_ES.json
@@ -133,7 +133,7 @@
"permission.settings.plugins": "Settings (tenant): Can maintain preferred plugins",
"permission.settings.sso": "Settings (tenant): Can maintain SSO settings",
"permission.settings.location": "Settings (tenant): Can create, edit and remove locations",
- "permission.settings.servicepoints": "Settings (tenant): Can create, edit and remove service points",
+ "permission.settings.servicepoints": "Settings (tenant): Can create and edit service points",
"settings.location.remotes.remote": "Remote storage",
"settings.location.remotes.no": "No (default)",
"settings.location.remotes.loading": "loading...",
diff --git a/translations/ui-tenant-settings/fr.json b/translations/ui-tenant-settings/fr.json
index c06141e0..a98803e2 100644
--- a/translations/ui-tenant-settings/fr.json
+++ b/translations/ui-tenant-settings/fr.json
@@ -133,7 +133,7 @@
"permission.settings.plugins": "Settings (tenant): Can maintain preferred plugins",
"permission.settings.sso": "Settings (tenant): Can maintain SSO settings",
"permission.settings.location": "Settings (tenant): Can create, edit and remove locations",
- "permission.settings.servicepoints": "Settings (tenant): Can create, edit and remove service points",
+ "permission.settings.servicepoints": "Settings (tenant): Can create and edit service points",
"settings.location.remotes.remote": "Remote storage",
"settings.location.remotes.no": "No (default)",
"settings.location.remotes.loading": "loading...",
diff --git a/translations/ui-tenant-settings/fr_FR.json b/translations/ui-tenant-settings/fr_FR.json
index f6e0073b..649c4b44 100644
--- a/translations/ui-tenant-settings/fr_FR.json
+++ b/translations/ui-tenant-settings/fr_FR.json
@@ -61,7 +61,7 @@
"settings.servicePoints.discoveryDisplayName": "Nom d'affichage",
"settings.servicePoints.description": "Description",
"settings.servicePoints.shelvingLagTime": "Temps de latence du rayonnage (minutes)",
- "settings.servicePoints.pickupLocation": "Emplacement du point de retrait",
+ "settings.servicePoints.pickupLocation": "Point de retrait",
"settings.servicePoints.feeFineOwner": "Propriétaire des frais/amendes",
"settings.servicePoints.deleteServicePoint": "Supprimer l'unité de services",
"settings.servicePoints.delete": "Supprimer",
@@ -108,11 +108,11 @@
"settings.servicePoints.pickupLocation.yes": "Oui",
"settings.servicePoints.pickupLocation.no": "Non",
"settings.save.error.network": "Enregistrement non sauvegardé",
- "settings.locale.localeWarning": "Les paramètres de cette page modifieront de manière PERMANENTE les paramètres régionaux (y compris l'affichage de la langue, le format de la date et le format des nombres) pour tous les utilisateurs. Il est fortement déconseillé de modifier les paramètres régionaux ici, sauf si vous êtes absolument certain que c'est la bonne action. Pour modifier TEMPORAIREMENT les paramètres régionaux de votre session uniquement, cliquez sur le bouton \" {label} \" à la place.",
- "settings.locale.changeSessionLocale": "Changer langue et les paramètres régionaux de la session",
+ "settings.locale.localeWarning": "Les paramètres de cette page modifieront de manière PERMANENTE les paramètres régionaux (y compris l'affichage de la langue, le format de la date et le format des nombres) pour tous les utilisateurs. Il est fortement déconseillé de modifier les paramètres régionaux ici, sauf si vous êtes absolument certain que c'est la bonne action. Pour modifier TEMPORAIREMENT les paramètres régionaux de votre session uniquement, cliquez sur le bouton \"{label}\" à la place.",
+ "settings.locale.changeSessionLocale": "Changer la langue et les paramètres régionaux de la session",
"settings.pluginNames.create-inventory-records": "Créer des notices de catalogue",
"settings.pluginNames.find-user": "Rechercher un utilisateur",
- "settings.pluginNames.find-instance": "Rechercher une instance",
+ "settings.pluginNames.find-instance": "Rechercher une notice bibliographique",
"settings.pluginNames.find-import-profile": "Rechercher un profil d'importation",
"settings.pluginNames.find-eresource": "Rechercher une ressource électronique",
"settings.pluginNames.find-contact": "Rechercher un contact",
@@ -127,67 +127,67 @@
"settings.pluginNames.find-erm-usage-data-provider": "Rechercher un fournisseur de métadonnées d'utilisation ERM",
"settings.pluginNames.find-finc-metadata-source": "Rechercher une source de métadonnées financières",
"permission.module.enabled": "UI: Tenant-settings module is enabled",
- "permission.settings.addresses": "Paramètres (tenant) : peut gérer l'adresse des tenants",
+ "permission.settings.addresses": "Paramètres (Gestion/administration) : peut gérer l'adresse des tenants",
"permission.settings.key-bindings": "Settings (tenant): Can maintain key bindings",
- "permission.settings.locale": "Paramètres (tenant) : peut maintenir la langue, la localisation et la devise",
- "permission.settings.plugins": "Paramètres (tenant) : peut maintenir les plugins préférés",
- "permission.settings.sso": "Paramètres (tenant) : peut maintenir la configuration SSO",
- "permission.settings.location": "Paramètres (tenant) : peut créer, modifier et supprimer des localisations",
- "permission.settings.servicepoints": "Paramètres (tenant) : Peut créer, modifier et supprimer des \"service points\"",
+ "permission.settings.locale": "Paramètres (gestion/administration) : peut modifier la langue, la localisation et la devise",
+ "permission.settings.plugins": "Paramètres (Gestion/administration) : peut maintenir les plugins préférés",
+ "permission.settings.sso": "Paramètres (Gestion/administration) : peut maintenir la configuration SSO",
+ "permission.settings.location": "Paramètres (Gestion/administration) : peut créer, modifier et supprimer des localisations",
+ "permission.settings.servicepoints": "Paramètres (Gestion/administration) : Peut créer, modifier et supprimer des points de service",
"settings.location.remotes.remote": "Stockage à distance",
"settings.location.remotes.no": "Non (par défaut)",
"settings.location.remotes.loading": "Chargement...",
"settings.location.remotes.readonly": "ne peut être modifié que s'il n'y a pas de collections ou d'exemplaires permanents associés à cet emplacement",
"settings.location.remotes.failed": "Échec du chargement",
- "permission.settings.bursar-exports": "Paramètres: intendant (administration",
+ "permission.settings.bursar-exports": "Paramètres (Gestion/administration) : intendant",
"settings.location.locations.remoteStorage": "Stockage à distance",
"settings.location.locations.returning-workflow.title": "Returning workflow preference",
"settings.location.locations.returning-workflow.Scanned to folio": "Items received at remote storage scanned into FOLIO",
"settings.location.locations.returning-workflow.Scanned to CaiaSoft": "Items received at remote storage scanned into CaiaSoft",
"settings.numberingSystem": "Numbering system",
"settings.servicePoints.holdShelfClosedLibraryDateManagement": "Closed library date management for hold shelf expiration date calculation",
- "settings.servicePoints.holdShelfClosedLibraryDateManagement.keepTheOriginalDate": "Keep the original date",
- "settings.servicePoints.holdShelfClosedLibraryDateManagement.moveToTheEndOfThePreviousOpenDay": "Move to the end of the previous open day",
- "settings.servicePoints.holdShelfClosedLibraryDateManagement.moveToTheEndOfTheNextOpenDay": "Move to the end of the next open day",
- "settings.servicePoints.holdShelfClosedLibraryDateManagement.keepTheOriginalDateTime": "Keep the original date/time",
- "settings.servicePoints.holdShelfClosedLibraryDateManagement.moveToTheEndOfTheCurrentServicePointHours": "Move to the end of the current service point hours",
- "settings.servicePoints.holdShelfClosedLibraryDateManagement.MoveToTheBeginningOfTheNextOpenServicePointHours": "Move to the beginning of the next open service point hours",
+ "settings.servicePoints.holdShelfClosedLibraryDateManagement.keepTheOriginalDate": "Garder la date d'origine",
+ "settings.servicePoints.holdShelfClosedLibraryDateManagement.moveToTheEndOfThePreviousOpenDay": "Déplacer à la fin de la journée d'ouverture précédente",
+ "settings.servicePoints.holdShelfClosedLibraryDateManagement.moveToTheEndOfTheNextOpenDay": "Déplacer à la fin de la prochaine journée d'ouverture",
+ "settings.servicePoints.holdShelfClosedLibraryDateManagement.keepTheOriginalDateTime": "Garder la date/heure d'origine",
+ "settings.servicePoints.holdShelfClosedLibraryDateManagement.moveToTheEndOfTheCurrentServicePointHours": "Déplacer à la fin de la plage horaire actuelle du point de service",
+ "settings.servicePoints.holdShelfClosedLibraryDateManagement.MoveToTheBeginningOfTheNextOpenServicePointHours": "Déplacer au début de la prochaine plage horaire d'ouverture du point de service",
"settings.servicePoints.expirationPeriod": "Hold shelf expiration period",
"settings.servicePoints.selectInterval": "Select interval",
- "settings.location.institutions.cannotDeleteTermHeader": "Cannot delete institution",
- "settings.location.institutions.cannotDeleteTermMessage": "This institution cannot be deleted, as it is in use by one or more records.",
- "settings.location.institutions.deleteEntry": "Delete institution",
- "settings.location.institutions.termDeleted": "The institution {term} was successfully deleted",
- "settings.location.institutions.termWillBeDeleted": "The institution {term} will be deleted.",
- "settings.location.campuses.cannotDeleteTermHeader": "Cannot delete campus",
- "settings.location.campuses.cannotDeleteTermMessage": "This campus cannot be deleted, as it is in use by one or more records.",
- "settings.location.campuses.deleteEntry": "Delete campus",
- "settings.location.campuses.termDeleted": "The campus {term} was successfully deleted",
- "settings.location.campuses.termWillBeDeleted": "The campus {term} will be deleted.",
- "settings.location.libraries.cannotDeleteTermHeader": "Cannot delete library",
- "settings.location.libraries.cannotDeleteTermMessage": "This library cannot be deleted, as it is in use by one or more records.",
- "settings.location.libraries.deleteEntry": "Delete library",
- "settings.location.libraries.termDeleted": "The library {term} was successfully deleted",
- "settings.location.libraries.termWillBeDeleted": "The library {term} will be deleted.",
+ "settings.location.institutions.cannotDeleteTermHeader": "Impossible de supprimer l'institution",
+ "settings.location.institutions.cannotDeleteTermMessage": "Cette institution ne peut être supprimée car elle est utilisée par une ou plusieurs notices",
+ "settings.location.institutions.deleteEntry": "Supprimer l'institution",
+ "settings.location.institutions.termDeleted": "L'institution {term} a été supprimée avec succès",
+ "settings.location.institutions.termWillBeDeleted": "L'institution {term} sera supprimée.",
+ "settings.location.campuses.cannotDeleteTermHeader": "Impossible de supprimer le campus",
+ "settings.location.campuses.cannotDeleteTermMessage": "Ce campus ne peut être supprimé car il est utilisé par une ou plusieurs notices.",
+ "settings.location.campuses.deleteEntry": "Supprimer le campus",
+ "settings.location.campuses.termDeleted": "Le campus {term} a été supprimé avec succès",
+ "settings.location.campuses.termWillBeDeleted": "Le campus {term} sera supprimé.",
+ "settings.location.libraries.cannotDeleteTermHeader": "Impossible de supprimer la bibliothèque",
+ "settings.location.libraries.cannotDeleteTermMessage": "Cette bibliothèque ne peut être supprimée car elle est utilisée par une ou plusieurs notices.",
+ "settings.location.libraries.deleteEntry": "Supprimer la bibliothèque",
+ "settings.location.libraries.termDeleted": "La bibliothèque {term} a été supprimée avec succès",
+ "settings.location.libraries.termWillBeDeleted": "La bibliothèque {term} sera supprimée.",
"settings.addresses.cannotDeleteTermHeader": "Impossible de supprimer l'adresse",
"settings.addresses.cannotDeleteTermMessage": "This address cannot be deleted, as it is in use by one or more records.",
"settings.addresses.deleteEntry": "Supprimer l'adresse",
"settings.addresses.termDeleted": "L'adresse {term} a été supprimée avec succès",
"settings.addresses.termWillBeDeleted": "L'adresse {term} sera supprimée.",
- "settings.confirmPickupLocationChangeModal.title": "Confirm Pickup location change",
+ "settings.confirmPickupLocationChangeModal.title": "Confirmer le changement de point de retrait",
"settings.confirmPickupLocationChangeModal.message": "Changer ce point de retrait de \"Oui\" à \"Non\" le supprimera des politiques de réservations existantes et s'appliquera à toutes les règles de circulation utilisant ces politiques.",
- "settings.confirmPickupLocationChangeModal.button.confirm": "Confirm",
- "settings.confirmPickupLocationChangeModal.button.cancel": "Back",
+ "settings.confirmPickupLocationChangeModal.button.confirm": "Confirmer",
+ "settings.confirmPickupLocationChangeModal.button.cancel": "Retour",
"permission.settings.tenant-settings.view": "Settings (tenant): View",
"permission.settings.addresses.view": "Settings (tenant): Can view tenant addresses",
- "permission.settings.locale.view": "Settings (tenant): Can view language, localization, and currency",
- "permission.settings.plugins.view": "Settings (tenant): Can view preferred plugins",
- "permission.settings.sso.view": "Settings (tenant): Can view SSO settings",
+ "permission.settings.locale.view": "Paramètres (Gestion/administration) : peut voir la langue, la localisation et la devise",
+ "permission.settings.plugins.view": "Paramètres (Gestion/administration) : peut voir les plugins préférés",
+ "permission.settings.sso.view": "Paramètres (Gestion/administration) : peut voir les paramètres SSO",
"permission.settings.location.view": "Settings (Tenant): View locations",
- "permission.settings.servicepoints.view": "Settings (tenant): Can view service points",
+ "permission.settings.servicepoints.view": "Paramètres (Gestion/administration) : peut voir les points de services",
"settings.title": "Tenant settings",
"settings.address.title": "Tenant settings - Addresses",
- "settings.locale.title": "Tenant settings - Language and localization",
+ "settings.locale.title": "Paramètres locaux - Langue et localisation",
"settings.plugins.title": "Tenant settings - Preferred plugins",
"settings.sso.title": "Tenant settings - SSO settings",
"settings.service.title": "Tenant settings - Service points",
@@ -199,8 +199,8 @@
"settings.items.title": "Tenant settings - {item}",
"settings.location.createNew.title": "Tenant settings - New location",
"settings.items.edit.title": "Tenant settings - Edit: {item}",
- "permission.settings.reading-room-access.view": "Settings (tenant): Can view reading room access",
- "permission.settings.reading-room-access.all": "Settings (tenant): Can create, edit and remove reading room access",
+ "permission.settings.reading-room-access.view": "Paramètres (Gestion/administration) : peut voir l'accès aux salles de lecture",
+ "permission.settings.reading-room-access.all": "Paramètres (Gestion/administration) : peut créer, modifier et supprimer les accès aux salles de lecture",
"settings.reading-room.title": "Tenant settings - Reading room access",
"settings.reading-room-access.label": "Reading room access",
"settings.reading-room-access.name": "Nom de la salle",
diff --git a/translations/ui-tenant-settings/he.json b/translations/ui-tenant-settings/he.json
index c06141e0..a98803e2 100644
--- a/translations/ui-tenant-settings/he.json
+++ b/translations/ui-tenant-settings/he.json
@@ -133,7 +133,7 @@
"permission.settings.plugins": "Settings (tenant): Can maintain preferred plugins",
"permission.settings.sso": "Settings (tenant): Can maintain SSO settings",
"permission.settings.location": "Settings (tenant): Can create, edit and remove locations",
- "permission.settings.servicepoints": "Settings (tenant): Can create, edit and remove service points",
+ "permission.settings.servicepoints": "Settings (tenant): Can create and edit service points",
"settings.location.remotes.remote": "Remote storage",
"settings.location.remotes.no": "No (default)",
"settings.location.remotes.loading": "loading...",
diff --git a/translations/ui-tenant-settings/hi_IN.json b/translations/ui-tenant-settings/hi_IN.json
index c06141e0..a98803e2 100644
--- a/translations/ui-tenant-settings/hi_IN.json
+++ b/translations/ui-tenant-settings/hi_IN.json
@@ -133,7 +133,7 @@
"permission.settings.plugins": "Settings (tenant): Can maintain preferred plugins",
"permission.settings.sso": "Settings (tenant): Can maintain SSO settings",
"permission.settings.location": "Settings (tenant): Can create, edit and remove locations",
- "permission.settings.servicepoints": "Settings (tenant): Can create, edit and remove service points",
+ "permission.settings.servicepoints": "Settings (tenant): Can create and edit service points",
"settings.location.remotes.remote": "Remote storage",
"settings.location.remotes.no": "No (default)",
"settings.location.remotes.loading": "loading...",
diff --git a/translations/ui-tenant-settings/hu.json b/translations/ui-tenant-settings/hu.json
index f92d4fd6..0c87829f 100644
--- a/translations/ui-tenant-settings/hu.json
+++ b/translations/ui-tenant-settings/hu.json
@@ -133,7 +133,7 @@
"permission.settings.plugins": "Settings (tenant): Can maintain preferred plugins",
"permission.settings.sso": "Settings (tenant): Can maintain SSO settings",
"permission.settings.location": "Settings (tenant): Can create, edit and remove locations",
- "permission.settings.servicepoints": "Settings (tenant): Can create, edit and remove service points",
+ "permission.settings.servicepoints": "Settings (tenant): Can create and edit service points",
"settings.location.remotes.remote": "Remote storage",
"settings.location.remotes.no": "No (default)",
"settings.location.remotes.loading": "loading...",
diff --git a/translations/ui-tenant-settings/nb.json b/translations/ui-tenant-settings/nb.json
index c06141e0..a98803e2 100644
--- a/translations/ui-tenant-settings/nb.json
+++ b/translations/ui-tenant-settings/nb.json
@@ -133,7 +133,7 @@
"permission.settings.plugins": "Settings (tenant): Can maintain preferred plugins",
"permission.settings.sso": "Settings (tenant): Can maintain SSO settings",
"permission.settings.location": "Settings (tenant): Can create, edit and remove locations",
- "permission.settings.servicepoints": "Settings (tenant): Can create, edit and remove service points",
+ "permission.settings.servicepoints": "Settings (tenant): Can create and edit service points",
"settings.location.remotes.remote": "Remote storage",
"settings.location.remotes.no": "No (default)",
"settings.location.remotes.loading": "loading...",
diff --git a/translations/ui-tenant-settings/nl.json b/translations/ui-tenant-settings/nl.json
index c06141e0..a98803e2 100644
--- a/translations/ui-tenant-settings/nl.json
+++ b/translations/ui-tenant-settings/nl.json
@@ -133,7 +133,7 @@
"permission.settings.plugins": "Settings (tenant): Can maintain preferred plugins",
"permission.settings.sso": "Settings (tenant): Can maintain SSO settings",
"permission.settings.location": "Settings (tenant): Can create, edit and remove locations",
- "permission.settings.servicepoints": "Settings (tenant): Can create, edit and remove service points",
+ "permission.settings.servicepoints": "Settings (tenant): Can create and edit service points",
"settings.location.remotes.remote": "Remote storage",
"settings.location.remotes.no": "No (default)",
"settings.location.remotes.loading": "loading...",
diff --git a/translations/ui-tenant-settings/nn.json b/translations/ui-tenant-settings/nn.json
index c06141e0..a98803e2 100644
--- a/translations/ui-tenant-settings/nn.json
+++ b/translations/ui-tenant-settings/nn.json
@@ -133,7 +133,7 @@
"permission.settings.plugins": "Settings (tenant): Can maintain preferred plugins",
"permission.settings.sso": "Settings (tenant): Can maintain SSO settings",
"permission.settings.location": "Settings (tenant): Can create, edit and remove locations",
- "permission.settings.servicepoints": "Settings (tenant): Can create, edit and remove service points",
+ "permission.settings.servicepoints": "Settings (tenant): Can create and edit service points",
"settings.location.remotes.remote": "Remote storage",
"settings.location.remotes.no": "No (default)",
"settings.location.remotes.loading": "loading...",
diff --git a/translations/ui-tenant-settings/pt_BR.json b/translations/ui-tenant-settings/pt_BR.json
index 77662b8b..35f14e7e 100644
--- a/translations/ui-tenant-settings/pt_BR.json
+++ b/translations/ui-tenant-settings/pt_BR.json
@@ -133,7 +133,7 @@
"permission.settings.plugins": "Configurações (locatário): Pode manter os plugins preferidos",
"permission.settings.sso": "Configurações (locatário): Pode manter as configurações de SSO",
"permission.settings.location": "Configurações (locatário): Pode criar, editar e remover locais",
- "permission.settings.servicepoints": "Configurações (locatário): Pode criar, editar e remover pontos de serviço",
+ "permission.settings.servicepoints": "Configurações (locatário): Pode criar e editar pontos de serviço",
"settings.location.remotes.remote": "Armazenamento externo",
"settings.location.remotes.no": "Não (padrão)",
"settings.location.remotes.loading": "carregando...",
diff --git a/translations/ui-tenant-settings/pt_PT.json b/translations/ui-tenant-settings/pt_PT.json
index 9427740c..b6723c63 100644
--- a/translations/ui-tenant-settings/pt_PT.json
+++ b/translations/ui-tenant-settings/pt_PT.json
@@ -133,7 +133,7 @@
"permission.settings.plugins": "Settings (tenant): Can maintain preferred plugins",
"permission.settings.sso": "Settings (tenant): Can maintain SSO settings",
"permission.settings.location": "Settings (tenant): Can create, edit and remove locations",
- "permission.settings.servicepoints": "Settings (tenant): Can create, edit and remove service points",
+ "permission.settings.servicepoints": "Settings (tenant): Can create and edit service points",
"settings.location.remotes.remote": "Remote storage",
"settings.location.remotes.no": "No (default)",
"settings.location.remotes.loading": "loading...",
diff --git a/translations/ui-tenant-settings/ru.json b/translations/ui-tenant-settings/ru.json
index 65b80c83..e75b8b60 100644
--- a/translations/ui-tenant-settings/ru.json
+++ b/translations/ui-tenant-settings/ru.json
@@ -133,7 +133,7 @@
"permission.settings.plugins": "Settings (tenant): Can maintain preferred plugins",
"permission.settings.sso": "Settings (tenant): Can maintain SSO settings",
"permission.settings.location": "Settings (tenant): Can create, edit and remove locations",
- "permission.settings.servicepoints": "Settings (tenant): Can create, edit and remove service points",
+ "permission.settings.servicepoints": "Settings (tenant): Can create and edit service points",
"settings.location.remotes.remote": "Remote storage",
"settings.location.remotes.no": "No (default)",
"settings.location.remotes.loading": "loading...",
diff --git a/translations/ui-tenant-settings/sk.json b/translations/ui-tenant-settings/sk.json
index c06141e0..a98803e2 100644
--- a/translations/ui-tenant-settings/sk.json
+++ b/translations/ui-tenant-settings/sk.json
@@ -133,7 +133,7 @@
"permission.settings.plugins": "Settings (tenant): Can maintain preferred plugins",
"permission.settings.sso": "Settings (tenant): Can maintain SSO settings",
"permission.settings.location": "Settings (tenant): Can create, edit and remove locations",
- "permission.settings.servicepoints": "Settings (tenant): Can create, edit and remove service points",
+ "permission.settings.servicepoints": "Settings (tenant): Can create and edit service points",
"settings.location.remotes.remote": "Remote storage",
"settings.location.remotes.no": "No (default)",
"settings.location.remotes.loading": "loading...",
diff --git a/translations/ui-tenant-settings/sv.json b/translations/ui-tenant-settings/sv.json
index c06141e0..a98803e2 100644
--- a/translations/ui-tenant-settings/sv.json
+++ b/translations/ui-tenant-settings/sv.json
@@ -133,7 +133,7 @@
"permission.settings.plugins": "Settings (tenant): Can maintain preferred plugins",
"permission.settings.sso": "Settings (tenant): Can maintain SSO settings",
"permission.settings.location": "Settings (tenant): Can create, edit and remove locations",
- "permission.settings.servicepoints": "Settings (tenant): Can create, edit and remove service points",
+ "permission.settings.servicepoints": "Settings (tenant): Can create and edit service points",
"settings.location.remotes.remote": "Remote storage",
"settings.location.remotes.no": "No (default)",
"settings.location.remotes.loading": "loading...",
diff --git a/translations/ui-tenant-settings/ur.json b/translations/ui-tenant-settings/ur.json
index c06141e0..a98803e2 100644
--- a/translations/ui-tenant-settings/ur.json
+++ b/translations/ui-tenant-settings/ur.json
@@ -133,7 +133,7 @@
"permission.settings.plugins": "Settings (tenant): Can maintain preferred plugins",
"permission.settings.sso": "Settings (tenant): Can maintain SSO settings",
"permission.settings.location": "Settings (tenant): Can create, edit and remove locations",
- "permission.settings.servicepoints": "Settings (tenant): Can create, edit and remove service points",
+ "permission.settings.servicepoints": "Settings (tenant): Can create and edit service points",
"settings.location.remotes.remote": "Remote storage",
"settings.location.remotes.no": "No (default)",
"settings.location.remotes.loading": "loading...",
From 1a04912916987f72baaed905a5e880cbfb31844e Mon Sep 17 00:00:00 2001
From: Vadym Shchekotilin <86330150+vashjs@users.noreply.github.com>
Date: Wed, 7 Aug 2024 11:54:34 +0200
Subject: [PATCH 10/11] UITEN-299 Rewrite class components to functional ones
(ui-tenant-settings module) (#416)
UITEN-299 Rewrite all class components to functional ones (ui-tenant-settings module)
---
CHANGELOG.md | 1 +
package.json | 1 +
src/components/Period/Period.js | 190 ++---
src/hooks/useCampusDetails.js | 20 +
src/hooks/useCampuses.js | 19 +
src/hooks/useConfigurations.js | 19 +
src/hooks/useConfigurationsCreate.js | 16 +
src/hooks/useConfigurationsUpdate.js | 16 +
src/hooks/useInstitutionDetails.js | 20 +
src/hooks/useInstitutions.js | 19 +
src/hooks/useLibraries.js | 19 +
src/hooks/useLibraryDetails.js | 20 +
src/hooks/useLocationCreate.js | 16 +
src/hooks/useLocationDelete.js | 16 +
src/hooks/useLocationUpdate.js | 16 +
src/hooks/useLocations.js | 20 +
src/hooks/useRemoteStorageConfigurations.js | 21 +
src/hooks/useRemoteStorageMappingDelete.js | 16 +
src/hooks/useRemoteStorageMappingUpdate.js | 16 +
src/hooks/useRemoteStorageMappings.js | 21 +
src/hooks/useSamlConfiguration.js | 19 +
src/hooks/useSamlConfigurationUpdate.js | 16 +
src/hooks/useSamlDownload.js | 24 +
src/hooks/useServicePoints.js | 19 +
src/settings/Addresses.js | 192 ++---
src/settings/Bindings/Bindings.js | 52 +-
src/settings/Bindings/BindingsForm.js | 139 ++--
src/settings/Locale.js | 79 +-
src/settings/LocaleForm.js | 263 +++---
src/settings/LocationCampuses.js | 255 +++---
src/settings/LocationCampuses.test.js | 115 ++-
src/settings/LocationInstitutions.js | 141 ++--
src/settings/LocationInstitutions.test.js | 63 +-
src/settings/LocationLibraries.js | 327 +++-----
src/settings/LocationLibraries.test.js | 111 ++-
.../LocationLocations/LocationDetail.js | 112 +--
.../LocationForm/DetailsField.js | 99 +--
.../LocationForm/DetailsField.test.js | 9 +-
.../LocationForm/LocationForm.js | 586 ++++++-------
.../LocationForm/LocationFormContainer.js | 52 +-
.../LocationFormContainer.test.js | 270 +++---
.../LocationForm/RemoteStorageField.js | 13 +-
.../LocationForm/ServicePointsFields.js | 14 +-
.../LocationLocations/LocationManager.js | 786 +++++++-----------
.../LocationLocations/LocationManager.test.js | 233 ++----
.../RemoteStorage/Control.js | 17 +-
.../RemoteStorage/Control.test.js | 26 +-
.../RemoteStorage/Provider.js | 100 +--
.../LocationLocations/RemoteStorageDetails.js | 3 +-
.../LocationLocations/locationDetail.test.js | 76 +-
.../remoteStorageDetails.test.js | 23 +-
src/settings/LocationLocations/utils.js | 8 +-
src/settings/Plugins/PluginForm.js | 126 ++-
src/settings/Plugins/Plugins.js | 162 ++--
src/settings/Plugins/Plugins.test.js | 67 +-
.../ReadingRoomAccess/ReadingRoomAccess.js | 16 +-
.../ReadingRoomAccess.test.js | 13 +-
src/settings/SSOSettings/SSOSettings.js | 177 ++--
src/settings/SSOSettings/SSOSettings.test.js | 63 +-
src/settings/SSOSettings/SamlForm.js | 292 +++----
src/settings/ServicePoints/LocationList.js | 6 +-
.../ServicePoints/StaffSlipEditList.js | 36 +-
src/settings/ServicePoints/StaffSlipList.js | 49 +-
src/settings/ServicePoints/constants.js | 1 -
src/settings/index.js | 228 +++--
src/settings/index.test.js | 47 +-
test/jest/__mocks__/stripesCore.mock.js | 160 ++--
translations/ui-tenant-settings/en.json | 1 +
68 files changed, 2828 insertions(+), 3360 deletions(-)
create mode 100644 src/hooks/useCampusDetails.js
create mode 100644 src/hooks/useCampuses.js
create mode 100644 src/hooks/useConfigurations.js
create mode 100644 src/hooks/useConfigurationsCreate.js
create mode 100644 src/hooks/useConfigurationsUpdate.js
create mode 100644 src/hooks/useInstitutionDetails.js
create mode 100644 src/hooks/useInstitutions.js
create mode 100644 src/hooks/useLibraries.js
create mode 100644 src/hooks/useLibraryDetails.js
create mode 100644 src/hooks/useLocationCreate.js
create mode 100644 src/hooks/useLocationDelete.js
create mode 100644 src/hooks/useLocationUpdate.js
create mode 100644 src/hooks/useLocations.js
create mode 100644 src/hooks/useRemoteStorageConfigurations.js
create mode 100644 src/hooks/useRemoteStorageMappingDelete.js
create mode 100644 src/hooks/useRemoteStorageMappingUpdate.js
create mode 100644 src/hooks/useRemoteStorageMappings.js
create mode 100644 src/hooks/useSamlConfiguration.js
create mode 100644 src/hooks/useSamlConfigurationUpdate.js
create mode 100644 src/hooks/useSamlDownload.js
create mode 100644 src/hooks/useServicePoints.js
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d889c0ca..0cae5387 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,6 +15,7 @@
* [UITEN-298] (https://issues.folio.org/browse/UITEN-298) Update translation ids for reading room.
* [UITEN-301] (https://issues.folio.org/browse/UITEN-301) Display Reading room access in alphabetical order on settings page.
* [UITEN-212](https://folio-org.atlassian.net/browse/UITEN-212) Permission changes for service point management.
+* [UITEN-299](https://folio-org.atlassian.net/browse/UITEN-299) Rewrite class components to functional ones (ui-tenant-settings module).
## [8.1.0](https://github.com/folio-org/ui-tenant-settings/tree/v8.1.0)(2024-03-19)
[Full Changelog](https://github.com/folio-org/ui-tenant-settings/compare/v8.0.0...v8.1.0)
diff --git a/package.json b/package.json
index 3098caaa..dda50338 100644
--- a/package.json
+++ b/package.json
@@ -304,6 +304,7 @@
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-intl": "^6.4.4",
+ "react-query": "^3.6.0",
"react-router-dom": "^5.2.0"
}
}
diff --git a/src/components/Period/Period.js b/src/components/Period/Period.js
index 9f999028..65d6b441 100644
--- a/src/components/Period/Period.js
+++ b/src/components/Period/Period.js
@@ -1,31 +1,24 @@
-import React from 'react';
+import React, { useRef } from 'react';
import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl';
-
-import {
- Field,
-} from 'react-final-form';
-
-import {
- get,
- isEmpty,
- isNumber,
-} from 'lodash';
+import { Field } from 'react-final-form';
+import { get, isEmpty, isNumber } from 'lodash';
import {
Col,
Row,
Select,
TextField,
- Label,
+ Label
} from '@folio/stripes/components';
-import css from './Period.css';
import {
shortTermExpiryPeriod,
shortTermClosedDateManagementMenu,
longTermClosedDateManagementMenu
} from '../../settings/ServicePoints/constants';
+import css from './Period.css';
+
const validateDuration = value => {
if (typeof value !== 'number') {
@@ -39,32 +32,19 @@ const validateDuration = value => {
return undefined;
};
-class Period extends React.Component {
- static propTypes = {
- fieldLabel: PropTypes.string.isRequired,
- selectPlaceholder: PropTypes.string.isRequired,
- dependentValuePath: PropTypes.string.isRequired,
- inputValuePath: PropTypes.string.isRequired,
- selectValuePath: PropTypes.string.isRequired,
- entity: PropTypes.object.isRequired,
- intervalPeriods: PropTypes.arrayOf(PropTypes.object),
- changeFormValue: PropTypes.func.isRequired,
- };
-
- constructor(props) {
- super(props);
-
- this.inputRef = React.createRef();
- }
-
- onInputBlur = () => {
- const {
- inputValuePath,
- selectValuePath,
- entity,
- changeFormValue,
- } = this.props;
-
+const Period = ({
+ fieldLabel,
+ selectPlaceholder,
+ dependentValuePath,
+ inputValuePath,
+ selectValuePath,
+ entity,
+ intervalPeriods,
+ changeFormValue
+}) => {
+ const inputRef = useRef(null);
+
+ const onInputBlur = () => {
const inputValue = get(entity, inputValuePath);
if (isNumber(inputValue)) {
@@ -74,22 +54,11 @@ class Period extends React.Component {
changeFormValue(selectValuePath, '');
};
- onInputClear = () => {
- const {
- inputValuePath,
- changeFormValue,
- } = this.props;
-
+ const onInputClear = () => {
changeFormValue(inputValuePath, '');
};
- onSelectChange = (e) => {
- const {
- selectValuePath,
- changeFormValue,
- dependentValuePath,
- } = this.props;
-
+ const onSelectChange = (e) => {
changeFormValue(selectValuePath, e.target.value);
const holdShelfClosedLibraryDateManagementValue =
shortTermExpiryPeriod.findIndex(item => item === e.target.value) > -1
@@ -97,10 +66,10 @@ class Period extends React.Component {
: longTermClosedDateManagementMenu[0].value;
changeFormValue(dependentValuePath, holdShelfClosedLibraryDateManagementValue);
- this.inputRef.current.focus();
+ inputRef.current.focus();
};
- transformInputValue = (value) => {
+ const transformInputValue = (value) => {
if (isEmpty(value)) {
return '';
}
@@ -108,12 +77,7 @@ class Period extends React.Component {
return Number(value);
};
- generateOptions = () => {
- const {
- intervalPeriods,
- selectValuePath,
- } = this.props;
-
+ const generateOptions = () => {
return intervalPeriods.map(({ value, label }) => (
+
+ [example]
+
+
+
+
+
+
+
+ );
+};
BindingsForm.propTypes = {
handleSubmit: PropTypes.func.isRequired,
pristine: PropTypes.bool,
- stripes: stripesShape.isRequired,
submitting: PropTypes.bool,
label: PropTypes.node,
};
@@ -114,4 +109,4 @@ BindingsForm.propTypes = {
export default stripesFinalForm({
validate,
navigationCheck: true,
-})(withStripes(BindingsForm));
+})(BindingsForm);
diff --git a/src/settings/Locale.js b/src/settings/Locale.js
index 6a2505b7..18d75407 100644
--- a/src/settings/Locale.js
+++ b/src/settings/Locale.js
@@ -1,56 +1,49 @@
import React from 'react';
import PropTypes from 'prop-types';
+import { useIntl } from 'react-intl';
+
import { ConfigManager } from '@folio/stripes/smart-components';
+import { TitleManager, useStripes } from '@folio/stripes/core';
-import { injectIntl } from 'react-intl';
-import { TitleManager } from '@folio/stripes/core';
import LocaleForm from './LocaleForm';
import { parseSerializedLocale, serializeLocale } from './localeHelpers';
-class Locale extends React.Component {
- static propTypes = {
- stripes: PropTypes.shape({
- setCurrency: PropTypes.func.isRequired,
- setLocale: PropTypes.func.isRequired,
- setTimezone: PropTypes.func.isRequired,
- connect: PropTypes.func.isRequired,
- }).isRequired,
- label: PropTypes.node.isRequired,
- intl: PropTypes.object,
- };
- constructor(props) {
- super(props);
- this.configManager = props.stripes.connect(ConfigManager);
- this.afterSave = this.afterSave.bind(this);
- }
+const Locale = ({ label, ...rest }) => {
+ const intl = useIntl();
+ const stripes = useStripes();
- afterSave(setting) {
+ const ConnectedConfigManager = stripes.connect(ConfigManager);
+
+ const afterSave = (setting) => {
const localeValues = JSON.parse(setting.value);
const { locale, timezone, currency } = localeValues;
setTimeout(() => {
- if (locale) this.props.stripes.setLocale(locale);
- if (timezone) this.props.stripes.setTimezone(timezone);
- if (currency) this.props.stripes.setCurrency(currency);
- }, 500);
- }
-
- render() {
- return (
-
-
-
- );
- }
-}
-
-export default injectIntl(Locale);
+ if (locale) stripes.setLocale(locale);
+ if (timezone) stripes.setTimezone(timezone);
+ if (currency) stripes.setCurrency(currency);
+ }, 2000);
+ };
+
+ return (
+
+
+
+ );
+};
+
+Locale.propTypes = {
+ label: PropTypes.node.isRequired,
+};
+
+export default Locale;
diff --git a/src/settings/LocaleForm.js b/src/settings/LocaleForm.js
index c5d263e0..5660e7a5 100644
--- a/src/settings/LocaleForm.js
+++ b/src/settings/LocaleForm.js
@@ -1,10 +1,9 @@
-import React from 'react';
+import React, { useMemo } from 'react';
import PropTypes from 'prop-types';
import {
createIntl,
createIntlCache,
- FormattedMessage,
- injectIntl,
+ FormattedMessage, useIntl,
} from 'react-intl';
import { Field } from 'react-final-form';
@@ -24,49 +23,24 @@ import {
IfPermission,
supportedLocales,
supportedNumberingSystems,
- withStripes,
+ useStripes,
} from '@folio/stripes/core';
import styles from './Locale.css';
-const timezoneOptions = timezones.map(timezone => (
- {
- value: timezone.value,
- label: timezone.value,
- }
-));
-
-/**
- * localesList: list of available locales suitable for a Select
- * label contains language in context's locale and in iteree's locale
- * e.g. given the context's locale is `en` and the keys `ar` and `zh-CN` show:
- * Arabic / العربية
- * Chinese (China) / 中文(中国)
- * e.g. given the context's locale is `ar` and the keys `ar` and `zh-CN` show:
- * العربية / العربية
- * الصينية (الصين) / 中文(中国)
- *
- * @param {object} intl react-intl object in the current context's locale
- * @returns {array} array of {value, label} suitable for a Select
- */
+
+const timezoneOptions = timezones.map(timezone => ({
+ value: timezone.value,
+ label: timezone.value,
+}));
+
const localesList = (intl) => {
- // This is optional but highly recommended
- // since it prevents memory leak
const cache = createIntlCache();
- // error handler if an intl context cannot be created,
- // i.e. if the browser is missing support for the requested locale
- const logLocaleError = (e) => {
- console.warn(e); // eslint-disable-line
- };
-
- // iterate through the locales list to build an array of { value, label } objects
const locales = supportedLocales.map(l => {
- // intl instance with locale of current iteree
const lIntl = createIntl({
locale: l,
messages: {},
- onError: logLocaleError,
},
cache);
@@ -79,24 +53,10 @@ const localesList = (intl) => {
return locales.sort((a, b) => a.label.localeCompare(b.label));
};
-/**
- * numberingSystemsList: list of available systems, suitable for a Select
- * label contains the name and the digits zero-nine in the given system
- * e.g. given the system is `latn` show:
- * latn (0 1 2 3 4 5 6 7 8 9)
- * e.g. given the system is `arab` show:
- * arab (٠ ١ ٢ ٣ ٤ ٥ ٦ ٧ ٨ ٩)
- * More info on numbering systems:
- * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale/numberingSystem
-
- * @returns {array} array of {value, label} suitable for a Select
- */
const numberingSystemsList = () => {
- // This is optional but highly recommended
- // since it prevents memory leak
const cache = createIntlCache();
- const formats = supportedNumberingSystems.map(f => {
+ return supportedNumberingSystems.map(f => {
const lIntl = createIntl({
locale: `en-u-nu-${f}`,
messages: {},
@@ -108,136 +68,123 @@ const numberingSystemsList = () => {
label: `${f} (${Array.from(Array(10).keys()).map(i => lIntl.formatNumber(i)).join(' ')})`,
};
});
-
- return formats;
};
-class LocaleForm extends React.Component {
- constructor(props) {
- super(props);
-
- this.isReadOnly = !props.stripes.hasPerm('ui-tenant-settings.settings.locale');
- this.localesOptions = localesList(props.intl);
- this.numberingSystemOptions = [
- { value: '', label: '---' },
- ...numberingSystemsList()
- ];
- }
-
- getFooter() {
- const { pristine, submitting } = this.props;
-
- return !this.isReadOnly && (
+
+const LocaleForm = ({ handleSubmit, pristine, submitting, label }) => {
+ const intl = useIntl();
+ const stripes = useStripes();
+
+ const isReadOnly = !stripes.hasPerm('ui-tenant-settings.settings.locale');
+ const localesOptions = useMemo(() => localesList(intl), [intl]);
+ const numberingSystemOptions = useMemo(() => [
+ { value: '', label: '---' },
+ ...numberingSystemsList(),
+ ], []);
+
+ const getFooter = () => (
+ !isReadOnly && (
)}
/>
- );
- }
-
- render() {
- const { handleSubmit, label, intl: { formatMessage } } = this.props;
-
- return (
-
- );
- }
-}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
LocaleForm.propTypes = {
handleSubmit: PropTypes.func.isRequired,
pristine: PropTypes.bool,
submitting: PropTypes.bool,
label: PropTypes.node,
- intl: PropTypes.object,
- stripes: PropTypes.shape({
- hasPerm: PropTypes.func.isRequired,
- })
};
export default stripesFinalForm({
navigationCheck: true,
-})(withStripes(injectIntl(LocaleForm)));
+})(LocaleForm);
diff --git a/src/settings/LocationCampuses.js b/src/settings/LocationCampuses.js
index e8ba0f27..edd4f4fb 100644
--- a/src/settings/LocationCampuses.js
+++ b/src/settings/LocationCampuses.js
@@ -1,20 +1,17 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import {
- FormattedMessage,
- injectIntl,
-} from 'react-intl';
+import React, { useState, useCallback } from 'react';
+import { FormattedMessage, useIntl } from 'react-intl';
+
import { ControlledVocab } from '@folio/stripes/smart-components';
-import {
- Select,
- TextLink,
-} from '@folio/stripes/components';
+import { Select, TextLink } from '@folio/stripes/components';
+import { TitleManager, useStripes } from '@folio/stripes/core';
-import { TitleManager } from '@folio/stripes/core';
import locationCodeValidator from './locationCodeValidator';
import composeValidators from '../util/composeValidators';
-import css from './LocationInstitutions.css';
import { CAMPUS_ID_LIBRARIES, INSTITUTION_ID_CAMPUS, INSTITUTION_ID_LIBRARIES } from '../constants';
+import { useLibraries } from '../hooks/useLibraries';
+import { useInstitutions } from '../hooks/useInstitutions';
+import css from './LocationInstitutions.css';
+
const translations = {
cannotDeleteTermHeader: 'ui-tenant-settings.settings.location.campuses.cannotDeleteTermHeader',
@@ -24,89 +21,32 @@ const translations = {
termWillBeDeleted: 'ui-tenant-settings.settings.location.campuses.termWillBeDeleted',
};
-class LocationCampuses extends React.Component {
- static manifest = {
- institutions: {
- type: 'okapi',
- records: 'locinsts',
- path: 'location-units/institutions?query=cql.allRecords=1 sortby name&limit=100',
- accumulate: true,
- },
- libraries: {
- type: 'okapi',
- path: 'location-units/libraries',
- params: {
- query: 'cql.allRecords=1 sortby name',
- limit: '1000',
- },
- records: 'loclibs',
- accumulate: true,
+
+const LocationCampuses = (props) => {
+ const stripes = useStripes();
+ const { formatMessage } = useIntl();
+ const [institutionId, setInstitutionId] = useState(sessionStorage.getItem(INSTITUTION_ID_CAMPUS) || null);
+
+ const hasAllLocationPerms = stripes.hasPerm('ui-tenant-settings.settings.location');
+ const ConnectedControlledVocab = stripes.connect(ControlledVocab);
+
+ const { institutions } = useInstitutions({
+ searchParams: {
+ limit: 100,
+ query: 'cql.allRecords=1 sortby name',
},
- };
-
- static propTypes = {
- stripes: PropTypes.shape({
- connect: PropTypes.func.isRequired,
- hasPerm: PropTypes.func.isRequired
- }).isRequired,
- resources: PropTypes.shape({
- institutions: PropTypes.shape({
- records: PropTypes.arrayOf(PropTypes.object),
- }),
- locationsPerCampus: PropTypes.shape({
- records: PropTypes.arrayOf(PropTypes.object),
- }),
- libraries: PropTypes.shape({
- records: PropTypes.arrayOf(PropTypes.object),
- })
- }),
- intl: PropTypes.object,
- mutator: PropTypes.shape({
- institutions: PropTypes.shape({
- GET: PropTypes.func.isRequired,
- reset: PropTypes.func.isRequired,
- }),
- locationsPerCampus: PropTypes.shape({
- GET: PropTypes.func.isRequired,
- reset: PropTypes.func.isRequired,
- }),
- }),
- };
-
- constructor(props) {
- super(props);
- this.connectedControlledVocab = props.stripes.connect(ControlledVocab);
- this.hasAllLocationPerms = props.stripes.hasPerm('ui-tenant-settings.settings.location');
- this.numberOfObjectsFormatter = this.numberOfObjectsFormatter.bind(this);
-
- this.state = {
- institutionId: null,
- };
- }
+ });
- /**
- * Refresh lookup tables when the component mounts. Fetches in the manifest
- * will only run once (in the constructor) but because this object may be
- * unmounted/remounted without being destroyed/recreated, the lookup tables
- * will be stale if they change between unmounting/remounting.
- */
- componentDidMount() {
- const institutionId = sessionStorage.getItem(INSTITUTION_ID_CAMPUS);
- this.setState({ institutionId });
- ['institutions', 'libraries'].forEach(i => {
- this.props.mutator[i].reset();
- this.props.mutator[i].GET();
- });
- }
+ const { libraries } = useLibraries({ searchParams: {
+ limit: 1000,
+ query: 'cql.allRecords=1 sortby name',
+ } });
- numberOfObjectsFormatter = (item) => {
- const records = (this.props.resources.libraries || {}).records || [];
- const numberOfObjects = records.reduce((count, loc) => {
- return loc.campusId === item.id ? count + 1 : count;
- }, 0);
+ const numberOfObjectsFormatter = useCallback((item) => {
+ const numberOfObjects = libraries.reduce((count, loc) => (loc.campusId === item.id ? count + 1 : count), 0);
const onNumberOfObjectsClick = () => {
- sessionStorage.setItem(INSTITUTION_ID_LIBRARIES, this.state.institutionId);
+ sessionStorage.setItem(INSTITUTION_ID_LIBRARIES, institutionId);
sessionStorage.setItem(CAMPUS_ID_LIBRARIES, item.id);
};
@@ -118,81 +58,74 @@ class LocationCampuses extends React.Component {
to="./location-libraries"
>
{numberOfObjects}
- );
- }
+
+ );
+ }, [libraries, institutionId]);
- onChangeInstitution = (e) => {
+ const onChangeInstitution = useCallback((e) => {
const value = e.target.value;
- this.setState({ institutionId: value });
-
+ setInstitutionId(value);
sessionStorage.setItem(INSTITUTION_ID_CAMPUS, value);
- }
+ }, []);
- render() {
- const institutions = [];
- (((this.props.resources.institutions || {}).records || []).forEach(i => {
- institutions.push(
-
- );
- }));
-
- if (!institutions.length) {
- return ;
- }
-
- const rowFilter = (
- }
- id="institutionSelect"
- name="institutionSelect"
- onChange={this.onChangeInstitution}
- value={this.state.institutionId}
- >
-
- {selectText => (
-
- )}
-
- {institutions}
-
- );
+ const institutionOptions = institutions.map(i => (
+
+ ));
- return (
-
- from being overwritten by the props.resources here.
- dataKey={undefined}
- baseUrl="location-units/campuses"
- records="loccamps"
- rowFilter={rowFilter}
- rowFilterFunction={(row) => row.institutionId === this.state.institutionId}
- label={this.props.intl.formatMessage({ id: 'ui-tenant-settings.settings.location.campuses' })}
- translations={translations}
- objectLabel={}
- visibleFields={['name', 'code']}
- columnMapping={{
- name: ,
- code: ,
- }}
- formatter={{ numberOfObjects: this.numberOfObjectsFormatter }}
- nameKey="group"
- id="campuses"
- preCreateHook={(item) => ({ ...item, institutionId: this.state.institutionId })}
- listSuppressor={() => !this.state.institutionId}
- listSuppressorText={}
- sortby="name"
- validate={composeValidators(locationCodeValidator.validate)}
- editable={this.hasAllLocationPerms}
- canCreate={this.hasAllLocationPerms}
- />
-
- );
+ if (!institutionOptions.length) {
+ return ;
}
-}
-export default injectIntl(LocationCampuses);
+ const rowFilter = (
+ }
+ id="institutionSelect"
+ name="institutionSelect"
+ onChange={onChangeInstitution}
+ value={institutionId}
+ >
+
+ {selectText => (
+
+ )}
+
+ {institutionOptions}
+
+ );
+
+ return (
+
+ row.institutionId === institutionId}
+ label={formatMessage({ id: 'ui-tenant-settings.settings.location.campuses' })}
+ translations={translations}
+ objectLabel={}
+ visibleFields={['name', 'code']}
+ columnMapping={{
+ name: ,
+ code: ,
+ }}
+ formatter={{ numberOfObjects: numberOfObjectsFormatter }}
+ nameKey="group"
+ id="campuses"
+ preCreateHook={(item) => ({ ...item, institutionId })}
+ listSuppressor={() => !institutionId}
+ listSuppressorText={}
+ sortby="name"
+ validate={composeValidators(locationCodeValidator.validate)}
+ editable={hasAllLocationPerms}
+ canCreate={hasAllLocationPerms}
+ />
+
+ );
+};
+
+export default LocationCampuses;
diff --git a/src/settings/LocationCampuses.test.js b/src/settings/LocationCampuses.test.js
index 58905add..ca8727d2 100644
--- a/src/settings/LocationCampuses.test.js
+++ b/src/settings/LocationCampuses.test.js
@@ -1,14 +1,16 @@
import React from 'react';
-
+import { QueryClient, QueryClientProvider } from 'react-query';
import { screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
-import '../../test/jest/__mocks__';
-import buildStripes from '../../test/jest/__new_mocks__/stripesCore.mock';
import { renderWithRouter } from '../../test/jest/helpers';
-
import LocationCampuses from './LocationCampuses';
+import '../../test/jest/__mocks__';
+import { useInstitutions } from '../hooks/useInstitutions';
+import { useLibraries } from '../hooks/useLibraries';
+
+
jest.mock('@folio/stripes-smart-components/lib/ControlledVocab', () => jest.fn(({
rowFilter,
label,
@@ -40,78 +42,69 @@ jest.mock('@folio/stripes-smart-components/lib/ControlledVocab', () => jest.fn((
>
)));
-const STRIPES = buildStripes();
-
-const resourcesMock = {
- institutions: {
- records: [
- { code: 'KU',
+jest.mock('../hooks/useInstitutions', () => ({
+ useInstitutions: jest.fn(() => ({
+ institutions: [
+ {
+ code: 'KU',
id: '40ee00ca-a518-4b49-be01-0638d0a4ac57',
- name: 'Københavns Universitet' }
+ name: 'Københavns Universitet'
+ }
+ ],
+ })),
+}));
+
+jest.mock('../hooks/useLibraries', () => ({
+ useLibraries: jest.fn(() => ({
+ libraries: [
+ {
+ 'id': '5d78803e-ca04-4b4a-aeae-2c63b924518b',
+ 'name': 'Datalogisk Institut',
+ 'code': 'DI',
+ 'campusId': '62cf76b7-cca5-4d33-9217-edf42ce1a848',
+ 'metadata': {
+ 'createdDate': '2023-06-23T02:10:45.756+00:00',
+ 'updatedDate': '2023-06-23T02:10:45.756+00:00'
+ }
+ },
+ {
+ 'id': 'c2549bb4-19c7-4fcc-8b52-39e612fb7dbe',
+ 'name': 'Online',
+ 'code': 'E',
+ 'campusId': '470ff1dd-937a-4195-bf9e-06bcfcd135df',
+ 'metadata': {
+ 'createdDate': '2023-06-23T02:10:45.756+00:00',
+ 'updatedDate': '2023-06-23T02:10:45.756+00:00'
+ }
+ }
]
- },
- libraries: {
- records:
- [
- {
- 'id': '5d78803e-ca04-4b4a-aeae-2c63b924518b',
- 'name': 'Datalogisk Institut',
- 'code': 'DI',
- 'campusId': '62cf76b7-cca5-4d33-9217-edf42ce1a848',
- 'metadata': {
- 'createdDate': '2023-06-23T02:10:45.756+00:00',
- 'updatedDate': '2023-06-23T02:10:45.756+00:00'
- }
- },
- {
- 'id': 'c2549bb4-19c7-4fcc-8b52-39e612fb7dbe',
- 'name': 'Online',
- 'code': 'E',
- 'campusId': '470ff1dd-937a-4195-bf9e-06bcfcd135df',
- 'metadata': {
- 'createdDate': '2023-06-23T02:10:45.756+00:00',
- 'updatedDate': '2023-06-23T02:10:45.756+00:00'
- }
- }
-
- ]
- }
-};
-
-const mutatorMock = {
- libraries: {
- GET: jest.fn(() => Promise.resolve()),
- reset: jest.fn(() => Promise.resolve()),
- },
- institutions: {
- GET: jest.fn(() => Promise.resolve()),
- reset: jest.fn(() => Promise.resolve()),
- },
-};
-
-const renderLocationCampuses = (resources = {}) => renderWithRouter(
-
+ })),
+}));
+
+const renderLocationCampuses = () => renderWithRouter(
+
+
+
);
describe('LocationCampuses', () => {
it('should render LocationCampuses with empty resources', async () => {
+ useInstitutions.mockImplementationOnce(() => ({ institutions: [] }));
+ useLibraries.mockImplementationOnce(() => ({ libraries: [] }));
+
renderLocationCampuses();
- expect(screen.getByTestId('institutuins-empty')).toBeVisible();
+ expect(screen.getByTestId('institutions-empty')).toBeVisible();
});
it('should render LocationCampuses', async () => {
- renderLocationCampuses(resourcesMock);
+ renderLocationCampuses();
expect(renderLocationCampuses).toBeDefined();
});
it('should render LocationCampuses changed option value', async () => {
- renderLocationCampuses(resourcesMock);
+ renderLocationCampuses();
const checkboxInstitution = screen.getByRole('combobox');
@@ -123,7 +116,7 @@ describe('LocationCampuses', () => {
});
it('should render LocationCampuses changed option value and call click', async () => {
- renderLocationCampuses(resourcesMock);
+ renderLocationCampuses();
const checkboxInstitution = screen.getByRole('combobox');
diff --git a/src/settings/LocationInstitutions.js b/src/settings/LocationInstitutions.js
index 7f081385..aa609aaf 100644
--- a/src/settings/LocationInstitutions.js
+++ b/src/settings/LocationInstitutions.js
@@ -1,18 +1,15 @@
import React from 'react';
-import PropTypes from 'prop-types';
-import {
- FormattedMessage,
- injectIntl,
-} from 'react-intl';
+import { FormattedMessage, useIntl } from 'react-intl';
import { ControlledVocab } from '@folio/stripes/smart-components';
-
import { TextLink } from '@folio/stripes/components';
-import { TitleManager } from '@folio/stripes/core';
+import { TitleManager, useStripes } from '@folio/stripes/core';
+
import composeValidators from '../util/composeValidators';
import locationCodeValidator from './locationCodeValidator';
-import css from './LocationInstitutions.css';
import { INSTITUTION_ID_CAMPUS } from '../constants';
+import { useCampuses } from '../hooks/useCampuses';
+import css from './LocationInstitutions.css';
const translations = {
cannotDeleteTermHeader: 'ui-tenant-settings.settings.location.institutions.cannotDeleteTermHeader',
@@ -22,54 +19,20 @@ const translations = {
termWillBeDeleted: 'ui-tenant-settings.settings.location.institutions.termWillBeDeleted',
};
-class LocationInstitutions extends React.Component {
- static manifest = Object.freeze({
- campuses: {
- type: 'okapi',
- records: 'loccamps',
- path: 'location-units/campuses?query=cql.allRecords=1 sortby name&limit=2000',
- accumulate: true,
- },
- });
- static propTypes = {
- intl: PropTypes.object,
- stripes: PropTypes.shape({
- connect: PropTypes.func.isRequired,
- hasPerm: PropTypes.func.isRequired,
- }).isRequired,
- resources: PropTypes.shape({
- campuses: PropTypes.object,
- }).isRequired,
- mutator: PropTypes.shape({
- campuses: PropTypes.shape({
- GET: PropTypes.func.isRequired,
- reset: PropTypes.func.isRequired,
- }),
- }),
- };
-
- constructor(props) {
- super(props);
- this.hasAllLocationPerms = props.stripes.hasPerm('ui-tenant-settings.settings.location');
- this.connectedControlledVocab = props.stripes.connect(ControlledVocab);
- this.numberOfObjectsFormatter = this.numberOfObjectsFormatter.bind(this);
- }
+const LocationInstitutions = (props) => {
+ const stripes = useStripes();
+ const { formatMessage } = useIntl();
+ const hasAllLocationPerms = stripes.hasPerm('ui-tenant-settings.settings.location');
+ const ConnectedControlledVocab = stripes.connect(ControlledVocab);
- /**
- * Refresh lookup tables when the component mounts. Fetches in the manifest
- * will only run once (in the constructor) but because this object may be
- * unmounted/remounted without being destroyed/recreated, the lookup tables
- * will be stale if they change between unmounting/remounting.
- */
- componentDidMount() {
- this.props.mutator.campuses.reset();
- this.props.mutator.campuses.GET();
- }
+ const { campuses } = useCampuses({ searchParams: {
+ limit: 1000,
+ query: 'cql.allRecords=1 sortby name',
+ } });
- numberOfObjectsFormatter = (item) => {
- const records = (this.props.resources.campuses || {}).records || [];
- const numberOfObjects = records.reduce((count, loc) => {
+ const numberOfObjectsFormatter = (item) => {
+ const numberOfObjects = campuses.reduce((count, loc) => {
return loc.institutionId === item.id ? count + 1 : count;
}, 0);
@@ -84,42 +47,42 @@ class LocationInstitutions extends React.Component {
to="./location-campuses"
>
{numberOfObjects}
- );
- }
+
+ );
+ };
- render() {
- const formatter = {
- numberOfObjects: this.numberOfObjectsFormatter,
- };
+ const formatter = {
+ numberOfObjects: numberOfObjectsFormatter,
+ };
- return (
-
- from being overwritten by the props.resources here.
- dataKey={undefined}
- baseUrl="location-units/institutions"
- records="locinsts"
- label={this.props.intl.formatMessage({ id: 'ui-tenant-settings.settings.location.institutions' })}
- translations={translations}
- objectLabel={}
- visibleFields={['name', 'code']}
- columnMapping={{
- name: ,
- code: ,
- }}
- formatter={formatter}
- nameKey="name"
- id="institutions"
- sortby="name"
- validate={composeValidators(locationCodeValidator.validate)}
- editable={this.hasAllLocationPerms}
- canCreate={this.hasAllLocationPerms}
- />
-
- );
- }
-}
+ return (
+
+ }
+ visibleFields={['name', 'code']}
+ columnMapping={{
+ name: ,
+ code: ,
+ }}
+ formatter={formatter}
+ nameKey="name"
+ id="institutions"
+ sortby="name"
+ validate={composeValidators(locationCodeValidator.validate)}
+ editable={hasAllLocationPerms}
+ canCreate={hasAllLocationPerms}
+ />
+
+ );
+};
-export default injectIntl(LocationInstitutions);
+export default LocationInstitutions;
diff --git a/src/settings/LocationInstitutions.test.js b/src/settings/LocationInstitutions.test.js
index 3a1c2402..696fb3c7 100644
--- a/src/settings/LocationInstitutions.test.js
+++ b/src/settings/LocationInstitutions.test.js
@@ -1,9 +1,19 @@
import React from 'react';
import { screen } from '@testing-library/react';
+import { QueryClient, QueryClientProvider } from 'react-query';
import LocationInstitutions from './LocationInstitutions';
import { renderWithRouter } from '../../test/jest/helpers';
+
+const mockCampuses = [
+ {
+ 'id' : '1',
+ 'name' : 'Københavns Universitet',
+ 'code' : 'KU',
+ }
+];
+
jest.mock('@folio/stripes-smart-components/lib/ControlledVocab', () => jest.fn(({
formatter,
label
@@ -11,17 +21,17 @@ jest.mock('@folio/stripes-smart-components/lib/ControlledVocab', () => jest.fn((
<>
{label}
- {formatter.numberOfObjects(
- {
- 'id' : '1',
- 'name' : 'Københavns Universitet',
- 'code' : 'KU',
- }
- )}
+ {formatter.numberOfObjects(mockCampuses[0])}
>
)));
+jest.mock('../hooks/useCampuses', () => ({
+ useCampuses: jest.fn(() => ({
+ campuses: mockCampuses,
+ })),
+}));
+
const stripesMock = {
connect: component => component,
hasPerm: jest.fn().mockResolvedValue(true),
@@ -30,39 +40,14 @@ const stripesMock = {
},
};
-const resourcesMock = {
- locationsPerInstitution: {
- records: [
- {
- 'id' : '1',
- 'name' : 'Annex',
- 'code' : 'KU/CC/DI/A',
- 'isActive' : true,
- 'institutionId' : '1',
- 'campusId' : '1',
- 'libraryId' : '1',
- 'primaryServicePoint' : '1',
- 'servicePointIds' : ['1'],
- 'servicePoints' : [],
- },
- ]
- },
-};
-
-const mutatorMock = {
- campuses: {
- GET: jest.fn(),
- reset: jest.fn(),
- }
-};
-
const renderLocationInstitutions = () => (
renderWithRouter(
-
+
+
+
+
)
);
@@ -71,8 +56,6 @@ describe('LocationInstitutions', () => {
renderLocationInstitutions();
const numbersOfObjectsCells = screen.getAllByText('ui-tenant-settings.settings.location.institutions');
- expect(mutatorMock.campuses.GET).toBeCalled();
- expect(mutatorMock.campuses.reset).toBeCalled();
numbersOfObjectsCells.forEach((el) => {
expect(el).toBeVisible();
});
diff --git a/src/settings/LocationLibraries.js b/src/settings/LocationLibraries.js
index 5c656976..aeeaefda 100644
--- a/src/settings/LocationLibraries.js
+++ b/src/settings/LocationLibraries.js
@@ -1,18 +1,10 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import {
- FormattedMessage,
- injectIntl,
-} from 'react-intl';
-import { get } from 'lodash';
+import React, { useState, useEffect, useCallback } from 'react';
+import { FormattedMessage, useIntl } from 'react-intl';
import { ControlledVocab } from '@folio/stripes/smart-components';
-import {
- Select,
- TextLink
-} from '@folio/stripes/components';
+import { Select, TextLink } from '@folio/stripes/components';
+import { TitleManager, useStripes } from '@folio/stripes/core';
-import { TitleManager } from '@folio/stripes/core';
import composeValidators from '../util/composeValidators';
import locationCodeValidator from './locationCodeValidator';
import {
@@ -23,6 +15,9 @@ import {
LOCATION_LIBRARY_ID_KEY
} from '../constants';
import css from './LocationInstitutions.css';
+import { useInstitutions } from '../hooks/useInstitutions';
+import { useCampuses } from '../hooks/useCampuses';
+import { useLocations } from '../hooks/useLocations';
const translations = {
cannotDeleteTermHeader: 'ui-tenant-settings.settings.location.libraries.cannotDeleteTermHeader',
@@ -32,97 +27,43 @@ const translations = {
termWillBeDeleted: 'ui-tenant-settings.settings.location.libraries.termWillBeDeleted',
};
-class LocationLibraries extends React.Component {
- static manifest = Object.freeze({
- institutions: {
- type: 'okapi',
- records: 'locinsts',
- path: 'location-units/institutions?query=cql.allRecords=1 sortby name&limit=100',
- accumulate: true,
- },
- campuses: {
- type: 'okapi',
- records: 'loccamps',
- path: 'location-units/campuses?query=cql.allRecords=1 sortby name&limit=100',
- accumulate: true,
- },
- locationsPerLibrary: {
- type: 'okapi',
- records: 'locations',
- path: 'locations',
- params: {
- query: 'cql.allRecords=1 sortby name',
- limit: '10000',
- },
- accumulate: true,
- },
- });
- static propTypes = {
- intl: PropTypes.object,
- stripes: PropTypes.shape({
- connect: PropTypes.func.isRequired,
- hasPerm: PropTypes.func.isRequired,
- }).isRequired,
- resources: PropTypes.shape({
- institutions: PropTypes.object,
- campuses: PropTypes.object,
- locationsPerLibrary: PropTypes.object,
- }).isRequired,
- mutator: PropTypes.shape({
- institutions: PropTypes.shape({
- GET: PropTypes.func.isRequired,
- reset: PropTypes.func.isRequired,
- }),
- campuses: PropTypes.shape({
- GET: PropTypes.func.isRequired,
- reset: PropTypes.func.isRequired,
- }),
- locationsPerLibrary: PropTypes.shape({
- GET: PropTypes.func.isRequired,
- reset: PropTypes.func.isRequired,
- }),
- }),
- };
+const LocationLibraries = (props) => {
+ const stripes = useStripes();
+ const { formatMessage } = useIntl();
+ const [institutionId, setInstitutionId] = useState(sessionStorage.getItem(INSTITUTION_ID_LIBRARIES) || null);
+ const [campusId, setCampusId] = useState(sessionStorage.getItem(CAMPUS_ID_LIBRARIES) || null);
- constructor(props) {
- super(props);
- this.connectedControlledVocab = props.stripes.connect(ControlledVocab);
- this.hasAllLocationPerms = props.stripes.hasPerm('ui-tenant-settings.settings.location');
- this.numberOfObjectsFormatter = this.numberOfObjectsFormatter.bind(this);
+ const hasAllLocationPerms = stripes.hasPerm('ui-tenant-settings.settings.location');
+ const ConnectedControlledVocab = stripes.connect(ControlledVocab);
- this.state = {
- institutionId: null,
- campusId: null,
- };
- }
+ const { institutions } = useInstitutions({ searchParams: {
+ limit: 100,
+ query: 'cql.allRecords=1 sortby name',
+ } });
- /**
- * Refresh lookup tables when the component mounts. Fetches in the manifest
- * will only run once (in the constructor) but because this object may be
- * unmounted/remounted without being destroyed/recreated, the lookup tables
- * will be stale if they change between unmounting/remounting.
- */
- componentDidMount() {
- const institutionId = sessionStorage.getItem(INSTITUTION_ID_LIBRARIES);
- const campusId = sessionStorage.getItem(CAMPUS_ID_LIBRARIES);
- this.setState({ institutionId, campusId });
- ['institutions', 'campuses', 'locationsPerLibrary'].forEach(i => {
- this.props.mutator[i].reset();
- this.props.mutator[i].GET();
- });
- }
+ const { campuses } = useCampuses({ searchParams: {
+ limit: 100,
+ query: 'cql.allRecords=1 sortby name',
+ } });
+
+ const { locations } = useLocations({ searchParams: {
+ limit: 10000,
+ query: 'cql.allRecords=1 sortby name',
+ } });
+
+ useEffect(() => {
+ sessionStorage.setItem(INSTITUTION_ID_LIBRARIES, institutionId);
+ sessionStorage.setItem(CAMPUS_ID_LIBRARIES, campusId);
+ }, [institutionId, campusId]);
- numberOfObjectsFormatter = (item) => {
- const records = (this.props.resources.locationsPerLibrary || {}).records || [];
- const numberOfObjects = records.reduce((count, loc) => {
- return loc.libraryId === item.id ? count + 1 : count;
- }, 0);
+ const numberOfObjectsFormatter = useCallback((item) => {
+ const numberOfObjects = locations.reduce((count, loc) => (loc.libraryId === item.id ? count + 1 : count), 0);
const onNumberOfObjectsClick = () => {
sessionStorage.setItem(LOCATION_LIBRARY_ID_KEY, item.id);
- sessionStorage.setItem(LOCATION_INSTITUTION_ID_KEY, this.state.institutionId);
- sessionStorage.setItem(LOCATION_CAMPUS_ID_KEY, this.state.campusId);
+ sessionStorage.setItem(LOCATION_INSTITUTION_ID_KEY, institutionId);
+ sessionStorage.setItem(LOCATION_CAMPUS_ID_KEY, campusId);
};
return (
@@ -133,124 +74,104 @@ class LocationLibraries extends React.Component {
to="./location-locations"
>
{numberOfObjects}
- );
- }
+
+ );
+ }, [locations, institutionId, campusId]);
- onChangeInstitution = (e) => {
+ const onChangeInstitution = useCallback((e) => {
const value = e.target.value;
- this.setState({ institutionId: value, campusId: null });
-
- sessionStorage.setItem(INSTITUTION_ID_LIBRARIES, value);
- sessionStorage.setItem(CAMPUS_ID_LIBRARIES, '');
- }
+ setInstitutionId(value);
+ setCampusId(null);
+ }, []);
- onChangeCampus = (e) => {
+ const onChangeCampus = useCallback((e) => {
const value = e.target.value;
- this.setState({ campusId: value });
-
- sessionStorage.setItem(CAMPUS_ID_LIBRARIES, value);
+ setCampusId(value);
+ }, []);
+
+ const institutionOptions = institutions.map(i => (
+
+ ));
+
+ const campusOptions = campuses.filter(c => c.institutionId === institutionId).map(c => (
+
+ ));
+
+ if (!institutionOptions.length) {
+ return ;
}
- render() {
- const { institutionId, campusId } = this.state;
- const { resources } = this.props;
-
- const institutions = get(resources, 'institutions.records', []).map(i => (
-
- ));
-
- if (!institutions.length) {
- return ;
- }
-
- const campuses = [];
-
- get(resources, 'campuses.records', []).forEach(c => {
- if (c.institutionId === institutionId) {
- campuses.push(
-
- );
- }
- });
-
- const formatter = {
- numberOfObjects: this.numberOfObjectsFormatter,
- };
-
- const filterBlock = (
- <>
+ const filterBlock = (
+ <>
+ }
+ id="institutionSelect"
+ name="institutionSelect"
+ onChange={onChangeInstitution}
+ value={institutionId}
+ >
+
+ {selectText => (
+
+ )}
+
+ {institutionOptions}
+
+ {institutionId && (
}
- id="institutionSelect"
- name="institutionSelect"
- onChange={this.onChangeInstitution}
- value={this.state.institutionId}
+ label={}
+ id="campusSelect"
+ name="campusSelect"
+ onChange={onChangeCampus}
+ value={campusId}
>
-
+
{selectText => (
-
+
)}
- {institutions}
+ {campusOptions}
- {institutionId &&
- }
- id="campusSelect"
- name="campusSelect"
- onChange={this.onChangeCampus}
- value={this.state.campusId}
- >
-
- {selectText => (
-
- )}
-
- {campuses}
-
- }
- >
- );
-
- return (
-
- from being overwritten by the props.resources here.
- dataKey={undefined}
- baseUrl="location-units/libraries"
- records="loclibs"
- rowFilter={filterBlock}
- rowFilterFunction={(row) => row.campusId === campusId}
- label={this.props.intl.formatMessage({ id: 'ui-tenant-settings.settings.location.libraries' })}
- translations={translations}
- objectLabel={}
- visibleFields={['name', 'code']}
- columnMapping={{
- name: ,
- code: ,
- }}
- formatter={formatter}
- nameKey="group"
- id="libraries"
- preCreateHook={(item) => ({ ...item, campusId })}
- listSuppressor={() => !(institutionId && campusId)}
- listSuppressorText={}
- sortby="name"
- validate={composeValidators(locationCodeValidator.validate)}
- editable={this.hasAllLocationPerms}
- canCreate={this.hasAllLocationPerms}
- />
-
- );
- }
-}
+ )}
+ >
+ );
+
+ return (
+
+ row.campusId === campusId}
+ label={formatMessage({ id: 'ui-tenant-settings.settings.location.libraries' })}
+ translations={translations}
+ objectLabel={}
+ visibleFields={['name', 'code']}
+ columnMapping={{
+ name: ,
+ code: ,
+ }}
+ formatter={{ numberOfObjects: numberOfObjectsFormatter }}
+ nameKey="group"
+ id="libraries"
+ preCreateHook={(item) => ({ ...item, campusId })}
+ listSuppressor={() => !(institutionId && campusId)}
+ listSuppressorText={}
+ sortby="name"
+ validate={composeValidators(locationCodeValidator.validate)}
+ editable={hasAllLocationPerms}
+ canCreate={hasAllLocationPerms}
+ />
+
+ );
+};
-export default injectIntl(LocationLibraries);
+export default LocationLibraries;
diff --git a/src/settings/LocationLibraries.test.js b/src/settings/LocationLibraries.test.js
index faf18275..de698ca5 100644
--- a/src/settings/LocationLibraries.test.js
+++ b/src/settings/LocationLibraries.test.js
@@ -1,9 +1,12 @@
import React from 'react';
import { screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
+import { QueryClient, QueryClientProvider } from 'react-query';
-import LocacationLibraries from './LocationLibraries';
+import LocationLibraries from './LocationLibraries';
import { renderWithRouter } from '../../test/jest/helpers';
+import { useInstitutions } from '../hooks/useInstitutions';
+
jest.mock('@folio/stripes-smart-components/lib/ControlledVocab', () => jest.fn(({
rowFilter,
@@ -36,39 +39,40 @@ jest.mock('@folio/stripes-smart-components/lib/ControlledVocab', () => jest.fn((
>
)));
-const stripesMock = {
- connect: component => component,
- hasPerm: jest.fn().mockResolvedValue(true),
- config: {
- platform: 'tenant-settings'
- },
-};
-
-const mutatorMock = {
- locationsPerLibrary: {
- GET: jest.fn(() => Promise.resolve()),
- reset: jest.fn(() => Promise.resolve()),
- },
- institutions: {
- GET: jest.fn(() => Promise.resolve()),
- reset: jest.fn(() => Promise.resolve()),
- },
- campuses: {
- GET: jest.fn(() => Promise.resolve()),
- reset: jest.fn(() => Promise.resolve()),
- },
-};
-
-const resourcesMock = {
- institutions: {
- records: [
- { code: 'KU',
+jest.mock('../hooks/useCampuses', () => ({
+ useCampuses: jest.fn(() => ({
+ campuses: [
+ {
+ code: 'CC',
+ id: '62cf76b7-cca5-4d33-9217-edf42ce1a848',
+ institutionId: '40ee00ca-a518-4b49-be01-0638d0a4ac57',
+ name: 'City Campus',
+ },
+ {
+ code: 'E',
+ id: '470ff1dd-937a-4195-bf9e-06bcfcd135df',
+ institutionId: '40ee00ca-a518-4b49-be01-0638d0a4ac57',
+ name: 'Online'
+ }
+ ],
+ })),
+}));
+
+jest.mock('../hooks/useInstitutions', () => ({
+ useInstitutions: jest.fn(() => ({
+ institutions: [
+ {
+ code: 'KU',
id: '40ee00ca-a518-4b49-be01-0638d0a4ac57',
- name: 'Københavns Universitet' }
+ name: 'Københavns Universitet'
+ }
]
- },
- locationsPerLibrary: {
- records: [
+ })),
+}));
+
+jest.mock('../hooks/useLocations', () => ({
+ useLocations: jest.fn(() => ({
+ locations: [
{
campusId: '62cf76b7-cca5-4d33-9217-edf42ce1a848',
code: 'KU/CC/DI/A',
@@ -87,49 +91,36 @@ const resourcesMock = {
name: 'Dematic',
}
]
- },
- campuses: {
- records: [{
- code: 'CC',
- id: '62cf76b7-cca5-4d33-9217-edf42ce1a848',
- institutionId: '40ee00ca-a518-4b49-be01-0638d0a4ac57',
- name: 'City Campus',
- },
- {
- code: 'E',
- id: '470ff1dd-937a-4195-bf9e-06bcfcd135df',
- institutionId: '40ee00ca-a518-4b49-be01-0638d0a4ac57',
- name: 'Online'
- }
- ]
- },
-};
-
-const renderLocationLibaries = (resources = {}) => renderWithRouter(
-
+ })),
+}));
+
+
+const renderLocationLibaries = () => renderWithRouter(
+
+
+
);
describe('LocationLibraries', () => {
it('should render LocationLibraries with empty resources', async () => {
+ useInstitutions.mockImplementationOnce(() => ({ institutions: [] }));
+
renderLocationLibaries();
expect(screen.getByTestId('libraries-empty')).toBeVisible();
});
+
it('should render LocationLibraries with resourses', async () => {
- renderLocationLibaries(resourcesMock);
+ renderLocationLibaries();
expect(renderLocationLibaries).toBeDefined();
});
it('should render LocationLibraries changed option value', async () => {
- renderLocationLibaries(resourcesMock);
+ renderLocationLibaries();
- const checkboxInstitution = screen.getByRole('combobox');
+ const checkboxInstitution = screen.getAllByRole('combobox')[0];
await userEvent.selectOptions(checkboxInstitution, 'Københavns Universitet (KU)');
@@ -139,7 +130,7 @@ describe('LocationLibraries', () => {
});
it('should render LocationLibraries with filled form', async () => {
- renderLocationLibaries(resourcesMock);
+ renderLocationLibaries();
const checkboxInstitution = screen.getByRole('combobox', { name: 'ui-tenant-settings.settings.location.institutions.institution' });
diff --git a/src/settings/LocationLocations/LocationDetail.js b/src/settings/LocationLocations/LocationDetail.js
index d54ee7b0..e248e85b 100644
--- a/src/settings/LocationLocations/LocationDetail.js
+++ b/src/settings/LocationLocations/LocationDetail.js
@@ -1,4 +1,4 @@
-import React, { useState, useCallback } from 'react';
+import React, { useState } from 'react';
import { FormattedMessage, useIntl } from 'react-intl';
import PropTypes from 'prop-types';
import {
@@ -20,21 +20,21 @@ import {
} from '@folio/stripes/components';
import { ViewMetaData } from '@folio/stripes/smart-components';
import {
- stripesConnect,
- IfPermission, useStripes, TitleManager,
+ IfPermission,
+ useStripes,
+ TitleManager,
} from '@folio/stripes/core';
import LocationInUseModal from './LocationInUseModal';
import { useRemoteStorageApi } from './RemoteStorage';
import RemoteStorageDetails from './RemoteStorageDetails';
+import { useCampusDetails } from '../../hooks/useCampusDetails';
+import { useInstitutionDetails } from '../../hooks/useInstitutionDetails';
+import { useLibraryDetails } from '../../hooks/useLibraryDetails';
+
const LocationDetail = ({
initialValues: loc,
- resources: {
- institutions,
- campuses,
- libraries,
- },
servicePointsById,
onEdit,
onClone,
@@ -51,11 +51,16 @@ const LocationDetail = ({
const [isDeleteLocationModalOpened, setIsDeleteLocationModalOpened] = useState(false);
const [isLocationInUseModalOpened, setIsLocationInUseModalOpened] = useState(false);
+ const { campus } = useCampusDetails({ id: loc.campusId });
+ const { institution } = useInstitutionDetails({ id: loc.institutionId });
+ const { library } = useLibraryDetails({ id: loc.libraryId });
const { setMapping } = useRemoteStorageApi();
- const handleExpandAll = setSections;
+ const handleExpandAll = (newSections) => {
+ setSections(newSections);
+ };
- const renderServicePoint = useCallback((sp, index) => {
+ const renderServicePoint = (sp, index) => {
return (
index === 0 ?
@@ -65,9 +70,9 @@ const LocationDetail = ({
{sp}
);
- }, []);
+ };
- const renderServicePoints = useCallback(() => {
+ const renderServicePoints = () => {
const itemsList = [];
// as primary servicePoint surely exists and servicePointsById shouldn't be empty, its index would be at the 0th position of itemsList array
if (!isEmpty(servicePointsById) && loc.servicePointIds.length !== 0) {
@@ -85,19 +90,19 @@ const LocationDetail = ({
isEmptyMessage="No servicePoints found"
/>
);
- }, [loc, renderServicePoint, servicePointsById]);
+ };
- const handleSectionToggle = useCallback(({ id }) => {
+ const handleSectionToggle = ({ id }) => {
setSections(prevSections => ({ ...prevSections, [id]: !prevSections[id] }));
- }, []);
+ };
- const toggleDeleteLocationConfirmation = useCallback(() => {
+ const toggleDeleteLocationConfirmation = () => {
setIsDeleteLocationModalOpened(prevState => !prevState);
- }, []);
+ };
- const toggleLocationInUseModal = useCallback(() => {
+ const toggleLocationInUseModal = () => {
setIsLocationInUseModalOpened(prevState => !prevState);
- }, []);
+ };
const removeLocation = () => {
toggleDeleteLocationConfirmation();
@@ -112,6 +117,7 @@ const LocationDetail = ({
});
};
+ // eslint-disable-next-line react/prop-types
const renderActionMenu = item => ({ onToggle }) => {
if (!hasAllLocationPerms) return null;
@@ -162,15 +168,6 @@ const LocationDetail = ({
);
};
- const institutionList = institutions?.records || [];
- const institution = institutionList.length === 1 ? institutionList[0] : null;
-
- const campusList = campuses?.records || [];
- const campus = campusList.length === 1 ? campusList[0] : null;
-
- const libraryList = libraries?.records || [];
- const library = libraryList.length === 1 ? libraryList[0] : null;
-
// massage the "details" property which is represented in the API as
// an object but displayed on the details page as an array of
// key-value pairs sorted by key.
@@ -222,7 +219,7 @@ const LocationDetail = ({
- }
+ }
{
- isDeleteLocationModalOpened && (
- }
- message={confirmationMessage}
- onConfirm={removeLocation}
- onCancel={toggleDeleteLocationConfirmation}
- confirmLabel={}
- />
- )
- }
+ isDeleteLocationModalOpened && (
+ }
+ message={confirmationMessage}
+ onConfirm={removeLocation}
+ onCancel={toggleDeleteLocationConfirmation}
+ confirmLabel={}
+ />
+ )
+ }
{
- isLocationInUseModalOpened && (
-
- )
- }
+ isLocationInUseModalOpened && (
+
+ )
+ }
);
};
-LocationDetail.manifest = Object.freeze({
- institutions: {
- type: 'okapi',
- path: 'location-units/institutions/!{initialValues.institutionId}',
- },
- campuses: {
- type: 'okapi',
- path: 'location-units/campuses/!{initialValues.campusId}',
- },
- libraries: {
- type: 'okapi',
- path: 'location-units/libraries/!{initialValues.libraryId}',
- },
-});
-
LocationDetail.propTypes = {
- stripes: PropTypes.shape({
- connect: PropTypes.func.isRequired,
- }).isRequired,
initialValues: PropTypes.object,
- resources: PropTypes.shape({
- institutions: PropTypes.object,
- campuses: PropTypes.object,
- libraries: PropTypes.object,
- }).isRequired,
servicePointsById: PropTypes.object,
onEdit: PropTypes.func.isRequired,
onClone: PropTypes.func.isRequired,
@@ -363,4 +337,4 @@ LocationDetail.propTypes = {
onRemove: PropTypes.func.isRequired,
};
-export default stripesConnect(LocationDetail);
+export default LocationDetail;
diff --git a/src/settings/LocationLocations/LocationForm/DetailsField.js b/src/settings/LocationLocations/LocationForm/DetailsField.js
index 1628701e..1c2f3622 100644
--- a/src/settings/LocationLocations/LocationForm/DetailsField.js
+++ b/src/settings/LocationLocations/LocationForm/DetailsField.js
@@ -1,6 +1,5 @@
-import React from 'react';
+import React, { useMemo } from 'react';
import { FormattedMessage } from 'react-intl';
-import PropTypes from 'prop-types';
import {
AutoSuggest,
@@ -9,31 +8,16 @@ import {
} from '@folio/stripes/components';
import RepeatableField from '../../../components/RepeatableField';
+import { useLocations } from '../../../hooks/useLocations';
-class DetailsField extends React.Component {
- static manifest = {
- locations: {
- type: 'okapi',
- path: 'locations?query=(details=*)',
- },
- };
-
- static propTypes = {
- resources: PropTypes.shape({
- locations: PropTypes.shape({
- records: PropTypes.arrayOf(PropTypes.object),
- }),
- }).isRequired,
- };
- constructor(props) {
- super(props);
- this.getSuggestedTerms = this.getSuggestedTerms.bind(this);
- }
+const DetailsField = () => {
+ const { locations } = useLocations({ searchParams: {
+ query: '(details=*)'
+ } });
- getSuggestedTerms(locationsArray) {
+ const getSuggestedTerms = (locationsArray) => {
const terms = [];
- // eslint-disable-next-line no-unused-vars
for (const item of locationsArray) {
if (item.details) {
Object.keys(item.details).forEach(name => {
@@ -44,44 +28,39 @@ class DetailsField extends React.Component {
}
}
return terms;
- }
-
- render() {
- const { locations } = this.props.resources;
- const locationsArray = locations ? locations.records[0] ? locations.records[0].locations : [] : [];
- const suggestedTerms = this.getSuggestedTerms(locationsArray);
- const detailNames = suggestedTerms.length > 0 ? suggestedTerms.map(locationName => (
- { value: locationName })) : [];
+ };
- return (
-
-
-
- }
- addButtonId="clickable-add-location-details"
- template={[
- {
- name: 'name',
- label: ,
- component: AutoSuggest,
- items: detailNames,
- renderValue: item => item || '',
- withFinalForm: true,
- },
- {
- name: 'value',
- label: ,
- component: TextField,
- },
- ]}
- newItemTemplate={{ name: '', value: '' }}
- />
- );
- }
-}
+ const suggestedTerms = getSuggestedTerms(locations);
+ const detailNames = useMemo(() => (suggestedTerms.length > 0 ? suggestedTerms.map(locationName => (
+ { value: locationName })) : []), [suggestedTerms]);
+ return (
+
+
+
+ }
+ addButtonId="clickable-add-location-details"
+ template={[
+ {
+ name: 'name',
+ label: ,
+ component: AutoSuggest,
+ items: detailNames,
+ renderValue: item => item || '',
+ withFinalForm: true,
+ },
+ {
+ name: 'value',
+ label: ,
+ component: TextField,
+ },
+ ]}
+ newItemTemplate={{ name: '', value: '' }}
+ />
+ );
+};
export default DetailsField;
diff --git a/src/settings/LocationLocations/LocationForm/DetailsField.test.js b/src/settings/LocationLocations/LocationForm/DetailsField.test.js
index 943fbba6..90da0c3b 100644
--- a/src/settings/LocationLocations/LocationForm/DetailsField.test.js
+++ b/src/settings/LocationLocations/LocationForm/DetailsField.test.js
@@ -1,4 +1,5 @@
import React from 'react';
+import { QueryClientProvider, QueryClient } from 'react-query';
import { render } from '@testing-library/react';
@@ -64,9 +65,11 @@ const renderDetailsField = () => render(
onSubmit={() => {}}
mutators={{ ...arrayMutators }}
render={() => (
-
+
+
+
)}
/>
);
diff --git a/src/settings/LocationLocations/LocationForm/LocationForm.js b/src/settings/LocationLocations/LocationForm/LocationForm.js
index e41e2960..f8412ea0 100644
--- a/src/settings/LocationLocations/LocationForm/LocationForm.js
+++ b/src/settings/LocationLocations/LocationForm/LocationForm.js
@@ -1,12 +1,13 @@
-import React from 'react';
+import React, { useState } from 'react';
import PropTypes from 'prop-types';
import { cloneDeep, sortBy } from 'lodash';
import { Field } from 'react-final-form';
-import { FormattedMessage, injectIntl } from 'react-intl';
+import { FormattedMessage, useIntl } from 'react-intl';
import {
TitleManager,
- withStripes,
+ useOkapiKy,
+ useStripes,
} from '@folio/stripes/core';
import {
Accordion,
@@ -32,65 +33,67 @@ import ServicePointsFields from './ServicePointsFields';
import DetailsField from './DetailsField';
import { RemoteStorageField } from './RemoteStorageField';
-class LocationForm extends React.Component {
- static propTypes = {
- stripes: PropTypes.shape({
- hasPerm: PropTypes.func.isRequired,
- connect: PropTypes.func.isRequired,
- }).isRequired,
- locationResources: PropTypes.shape({
- institutions: PropTypes.object,
- campuses: PropTypes.object,
- libraries: PropTypes.object,
- servicePoints: PropTypes.object,
- }),
- parentMutator: PropTypes.object.isRequired,
- initialValues: PropTypes.object,
- intl: PropTypes.object,
- handleSubmit: PropTypes.func.isRequired,
- onCancel: PropTypes.func,
- pristine: PropTypes.bool,
- submitting: PropTypes.bool,
- cloning: PropTypes.bool,
- form: PropTypes.object.isRequired,
- };
- constructor(props) {
- super(props);
+const LocationForm = ({
+ handleSubmit,
+ initialValues,
+ form,
+ onCancel,
+ pristine,
+ submitting,
+ cloning,
+ institutions,
+ campuses,
+ libraries,
+ servicePoints,
+ checkLocationHasHoldingsOrItems,
+}) => {
+ const stripes = useStripes();
+ const ky = useOkapiKy();
+ const { formatMessage } = useIntl();
- this.handleExpandAll = this.handleExpandAll.bind(this);
- this.handleSectionToggle = this.handleSectionToggle.bind(this);
- this.cViewMetaData = props.stripes.connect(ViewMetaData);
- this.cDetailsField = props.stripes.connect(DetailsField);
+ const [sections, setSections] = useState({
+ generalSection: true,
+ detailsSection: true,
+ });
- this.state = {
- sections: {
- generalSection: true,
- detailsSection: true,
- },
- };
- }
+ const mappedInstitutions = institutions.map(i => {
+ let label = i.name;
+ if (i.code) {
+ label += ` (${i.code})`;
+ }
+ return { value: i.id, label };
+ });
+ const mappedServicePoints = sortBy(servicePoints, ['name']).map(i => ({ label: `${i.name}` }));
- addFirstMenu() {
- return (
-
-
- {ariaLabel => (
-
- )}
-
-
- );
- }
+ const handleExpandAll = (newSections) => {
+ setSections(newSections);
+ };
- renderFooter() {
- const { pristine, submitting, cloning, onCancel } = this.props;
+ const handleSectionToggle = ({ id }) => {
+ setSections((curState) => {
+ const newState = cloneDeep(curState);
+ newState[id] = !newState[id];
+ return newState;
+ });
+ };
+ const addFirstMenu = () => (
+
+
+ {ariaLabel => (
+
+ )}
+
+
+ );
+
+ const renderFooter = () => {
const closeButton = (
);
- }
-
- handleSectionToggle({ id }) {
- this.setState((curState) => {
- const newState = cloneDeep(curState);
- newState.sections[id] = !newState.sections[id];
- return newState;
- });
- }
-
- handleExpandAll(sections) {
- this.setState((curState) => {
- const newState = cloneDeep(curState);
- newState.sections = sections;
- return newState;
- });
- }
+ };
- renderPaneTitle() {
- const { initialValues } = this.props;
+ const renderPaneTitle = () => {
const loc = initialValues || {};
if (loc.id) {
@@ -151,258 +137,222 @@ class LocationForm extends React.Component {
}
return ;
- }
-
- render() {
- const {
- stripes,
- handleSubmit,
- initialValues,
- locationResources,
- intl: { formatMessage },
- form,
- parentMutator
- } = this.props;
- const loc = initialValues || {};
- const { sections } = this.state;
- const disabled = !stripes.hasPerm('settings.tenant-settings.enabled');
-
- const institutions = [];
- ((locationResources.institutions || {}).records || []).forEach(i => {
- institutions.push({ value: i.id, label: `${i.name} ${i.code ? `(${i.code})` : ''}` });
- });
-
- const servicePoints = [];
- const entryList = sortBy((locationResources.servicePoints || {}).records || [], ['name']);
- entryList.forEach(i => {
- servicePoints.push({ label: `${i.name}` });
- });
+ };
- const formValues = form.getState().values;
+ const formValues = form.getState().values;
- const titleManagerLabel = initialValues?.name && initialValues?.id ? formatMessage({ id:'ui-tenant-settings.settings.items.edit.title' }, { item: initialValues?.name })
- :
- formatMessage({ id:'ui-tenant-settings.settings.location.createNew.title' });
+ const titleManagerLabel = initialValues?.name && initialValues?.id
+ ? formatMessage({ id:'ui-tenant-settings.settings.items.edit.title' }, { item: initialValues?.name })
+ : formatMessage({ id:'ui-tenant-settings.settings.location.createNew.title' });
- return (
-
-
- );
- }
-}
+
+ { label => (
+
+ )}
+
+
+ { label => (
+
+ )}
+
+
+
+
+
+
+ }
+ name="description"
+ id="input-location-description"
+ component={TextArea}
+ fullWidth
+ disabled={!stripes.hasPerm('settings.tenant-settings.enabled')}
+ />
+
+
+
+ }
+ >
+
+
+
+
+
+
+ );
+};
+LocationForm.propTypes = {
+ institutions: PropTypes.arrayOf(PropTypes.object),
+ campuses: PropTypes.arrayOf(PropTypes.object),
+ libraries: PropTypes.arrayOf(PropTypes.object),
+ servicePoints: PropTypes.arrayOf(PropTypes.object),
+ initialValues: PropTypes.object,
+ handleSubmit: PropTypes.func.isRequired,
+ onCancel: PropTypes.func,
+ pristine: PropTypes.bool,
+ submitting: PropTypes.bool,
+ cloning: PropTypes.bool,
+ form: PropTypes.object.isRequired,
+ checkLocationHasHoldingsOrItems: PropTypes.func
+};
export default stripesFinalForm({
navigationCheck: true,
@@ -425,4 +375,4 @@ export default stripesFinalForm({
},
validate,
validateOnBlur: true,
-})(withStripes(injectIntl(LocationForm)));
+})(LocationForm);
diff --git a/src/settings/LocationLocations/LocationForm/LocationFormContainer.js b/src/settings/LocationLocations/LocationForm/LocationFormContainer.js
index e1d0adfd..23aeba41 100644
--- a/src/settings/LocationLocations/LocationForm/LocationFormContainer.js
+++ b/src/settings/LocationLocations/LocationForm/LocationFormContainer.js
@@ -1,42 +1,46 @@
-import React, {
- useState,
- useEffect,
- useCallback,
- useContext,
-} from 'react';
+import React, { useContext } from 'react';
import { cloneDeep } from 'lodash';
import { FormattedMessage } from 'react-intl';
+import PropTypes from 'prop-types';
+import { useQueryClient } from 'react-query';
import { CalloutContext } from '@folio/stripes/core';
-import PropTypes from 'prop-types';
import LocationForm from './LocationForm';
import { useRemoteStorageApi } from '../RemoteStorage';
+import { useLocationCreate } from '../../../hooks/useLocationCreate';
+import { useLocationUpdate } from '../../../hooks/useLocationUpdate';
+import { LOCATIONS } from '../../../hooks/useLocations';
+import { SERVICE_POINTS } from '../../../hooks/useServicePoints';
const LocationFormContainer = ({
onSave,
servicePointsByName,
initialValues: location,
- parentMutator,
...rest
}) => {
- const [initialValues, setInitialValues] = useState(location);
-
- useEffect(() => {
- setInitialValues(location);
- }, [location?.id]);
+ const queryClient = useQueryClient();
const callout = useContext(CalloutContext);
- function showSubmitErrorCallout(error) {
+ const showSubmitErrorCallout = (error) => {
callout.sendCallout({
type: 'error',
message: error.message || error.statusText || ,
});
- }
+ };
const { setMapping } = useRemoteStorageApi();
+ const sharedOptions = {
+ onSuccess: () => {
+ queryClient.invalidateQueries(SERVICE_POINTS);
+ queryClient.invalidateQueries(LOCATIONS);
+ },
+ };
+
+ const { createLocation } = useLocationCreate(sharedOptions);
+ const { updateLocation } = useLocationUpdate(sharedOptions);
const initiateSetMapping = (...args) => setMapping(...args).catch(showSubmitErrorCallout);
@@ -44,7 +48,7 @@ const LocationFormContainer = ({
const { remoteId: configurationId, ...locationData } = formData;
if (locationData.id === undefined) {
- const newLocation = await parentMutator.entries.POST(locationData);
+ const newLocation = await createLocation({ data: locationData });
initiateSetMapping({ folioLocationId: newLocation?.id, configurationId });
return newLocation;
@@ -52,10 +56,11 @@ const LocationFormContainer = ({
initiateSetMapping({ folioLocationId: locationData.id, configurationId });
- return parentMutator.entries.PUT(locationData);
+ return updateLocation({ locationId: locationData.id, data: locationData })
+ .then(() => locationData);
};
- const saveLocation = useCallback((updatedLocation) => {
+ const saveLocation = (updatedLocation) => {
const data = cloneDeep(updatedLocation);
const servicePointsObject = {};
@@ -83,13 +88,12 @@ const LocationFormContainer = ({
saveData(data)
.then(onSave)
.catch(showSubmitErrorCallout);
- }, [onSave, servicePointsByName, saveData]);
+ };
return (
);
@@ -101,12 +105,6 @@ LocationFormContainer.propTypes = {
initialValues: PropTypes.shape({
id: PropTypes.string,
}),
- parentMutator: PropTypes.shape({
- entries: PropTypes.shape({
- POST: PropTypes.func,
- PUT: PropTypes.func,
- })
- }),
};
export default LocationFormContainer;
diff --git a/src/settings/LocationLocations/LocationForm/LocationFormContainer.test.js b/src/settings/LocationLocations/LocationForm/LocationFormContainer.test.js
index 6d9dcd06..47f766dd 100644
--- a/src/settings/LocationLocations/LocationForm/LocationFormContainer.test.js
+++ b/src/settings/LocationLocations/LocationForm/LocationFormContainer.test.js
@@ -1,13 +1,92 @@
import React from 'react';
-
+import { QueryClient, QueryClientProvider } from 'react-query';
import { screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import '../../../../test/jest/__mocks__';
-import buildStripes from '../../../../test/jest/__new_mocks__/stripesCore.mock';
import { renderWithRouter } from '../../../../test/jest/helpers';
import LocationFormContainer from './LocationFormContainer';
+import { mockUseOkapiKy } from '../../../../test/jest/__mocks__/stripesCore.mock';
+
+
+const mockCreateLocation = jest.fn(() => Promise.resolve());
+const mockUpdateLocation = jest.fn(() => Promise.resolve());
+
+
+jest.mock('../../../hooks/useLocationCreate', () => ({
+ useLocationCreate: jest.fn(() => ({
+ createLocation: mockCreateLocation,
+ isCreatingLocation: false,
+ })),
+}));
+
+jest.mock('../../../hooks/useLocationUpdate', () => ({
+ useLocationUpdate: jest.fn(() => ({
+ updateLocation: mockUpdateLocation,
+ isUpdatingLocation: false,
+ })),
+}));
+
+
+const institutions = [
+ {
+ code: 'KU',
+ id: '40ee00ca-a518-4b49-be01-0638d0a4ac57',
+ metadata: { createdDate: '2021-11-08T03:24:13.021+00:00', updatedDate: '2021-11-08T03:24:13.021+00:00' },
+ name: 'Københavns Universitet',
+ }
+];
+
+const campuses = [
+ {
+ code: 'DI',
+ id: '62cf76b7-cca5-4d33-9217-edf42ce1a848',
+ institutionId: '40ee00ca-a518-4b49-be01-0638d0a4ac57',
+ name: 'City Campus',
+ },
+ {
+ code: 'E',
+ id: '470ff1dd-937a-4195-bf9e-06bcfcd135df',
+ institutionId: '40ee00ca-a518-4b49-be01-0638d0a4ac57',
+ name: 'Online',
+ }
+];
+
+const libraries = [
+ {
+ campusId: '62cf76b7-cca5-4d33-9217-edf42ce1a848',
+ code: 'DI',
+ id: '5d78803e-ca04-4b4a-aeae-2c63b924518b',
+ name: 'Datalogisk Institut'
+ }
+];
+
+const servicePoints = [
+ {
+ code: 'cd1',
+ discoveryDisplayName: 'Circulation Desk -- Hallway',
+ holdShelfExpiryPeriod: { duration: 3, intervalId: 'Weeks' },
+ id: '3a40852d-49fd-4df2-a1f9-6e2641a6e91f',
+ name: 'Circ Desk 1',
+ pickupLocation: true,
+ staffSlips: [],
+ },
+ {
+ code: 'cd2',
+ discoveryDisplayName: 'Circulation Desk -- Back Entrance',
+ holdShelfExpiryPeriod: {
+ duration: 5,
+ intervalId: 'Days',
+ },
+
+ id: 'c4c90014-c8c9-4ade-8f24-b5e313319f4b',
+ name: 'Circ Desk 2',
+ pickupLocation: true,
+ staffSlips: []
+ }
+];
+
jest.mock('./DetailsField', () => {
return () => DetaolsField;
@@ -18,29 +97,18 @@ const mockSetMapping = jest.fn().mockResolvedValue(true);
jest.mock('../RemoteStorage/Provider', () => ({
...jest.requireActual('../RemoteStorage/Provider'),
useRemoteStorageApi: () => ({
- remoteMap: {
- },
- mappings: {
- failed: false,
- hasLoaded: true,
- isPending: false,
- records: [
- {
- configurationId: 'de17bad7-2a30-4f1c-bee5-f653ded15629',
- folioLocationId: '53cf956f-c1df-410b-8bea-27f712cca7c0'
- },
- {
- configurationId: 'de17bad7-2a30-4f1c-bee5-f653ded15629',
- folioLocationId: 'c0762159-8fe3-4cbc-ae64-fa274f7acc47'
- }
- ],
- },
- configurations: {
- failed: false,
- hasLoaded: true,
- isPending: false,
- records: [],
- },
+ remoteMap: {},
+ mappings: [
+ {
+ configurationId: 'de17bad7-2a30-4f1c-bee5-f653ded15629',
+ folioLocationId: '53cf956f-c1df-410b-8bea-27f712cca7c0'
+ },
+ {
+ configurationId: 'de17bad7-2a30-4f1c-bee5-f653ded15629',
+ folioLocationId: 'c0762159-8fe3-4cbc-ae64-fa274f7acc47'
+ }
+ ],
+ configurations: [],
translate: () => 'str',
setMapping: mockSetMapping
})
@@ -48,8 +116,6 @@ jest.mock('../RemoteStorage/Provider', () => ({
const onSaveMock = jest.fn();
-const STRIPES = buildStripes();
-
const initialValuesMock = {
id: '1',
name: 'Initial Value',
@@ -69,6 +135,7 @@ const initialValuesMock = {
}
]
};
+
const servicePointsByNameMock = {
CircDesk1: '3a40852d-49fd-4df2-a1f9-6e2641a6e91f',
CircDesk2: 'c4c90014-c8c9-4ade-8f24-b5e313319f4b',
@@ -80,145 +147,28 @@ const restPropsMock = {
pristine: false,
submitting: false,
cloning: true,
- stripes: STRIPES,
- locationResources: {
- campuses: {
- records: [
- {
- code: 'DI',
- id: '62cf76b7-cca5-4d33-9217-edf42ce1a848',
- institutionId: '40ee00ca-a518-4b49-be01-0638d0a4ac57',
- name: 'City Campus',
- },
- {
- code: 'E',
- id: '470ff1dd-937a-4195-bf9e-06bcfcd135df',
- institutionId: '40ee00ca-a518-4b49-be01-0638d0a4ac57',
- name: 'Online',
- }
- ]
- },
- entries: {
- records: [{
- campusId: '62cf76b7-cca5-4d33-9217-edf42ce1a848',
- code: 'KU/CC/DI/A',
- id: '53cf956f-c1df-410b-8bea-27f712cca7c0',
- institutionId: '40ee00ca-a518-4b49-be01-0638d0a4ac57',
- isActive: true,
- libraryId: '5d78803e-ca04-4b4a-aeae-2c63b924518b',
- name: 'Annex',
- primaryServicePoint: '3a40852d-49fd-4df2-a1f9-6e2641a6e91f',
- servicePointIds: ['3a40852d-49fd-4df2-a1f9-6e2641a6e91f'],
- servicePoints: [],
- }
- ]
- },
- institutions: {
- records: [
- {
- code: 'KU',
- id: '40ee00ca-a518-4b49-be01-0638d0a4ac57',
- metadata: { createdDate: '2021-11-08T03:24:13.021+00:00', updatedDate: '2021-11-08T03:24:13.021+00:00' },
- name: 'Københavns Universitet',
- }
- ]
- },
- libraries: {
- dataKey: 'location-locations',
- hasLoaded: true,
- records: [
- {
- campusId: '62cf76b7-cca5-4d33-9217-edf42ce1a848',
- code: 'DI',
- id: '5d78803e-ca04-4b4a-aeae-2c63b924518b',
- name: 'Datalogisk Institut'
- }
- ]
- },
- servicePoints: {
- records: [
- {
- code: 'cd1',
- discoveryDisplayName: 'Circulation Desk -- Hallway',
- holdShelfExpiryPeriod: { duration: 3, intervalId: 'Weeks' },
- id: '3a40852d-49fd-4df2-a1f9-6e2641a6e91f',
- name: 'Circ Desk 1',
- pickupLocation: true,
- staffSlips: [],
- },
- {
- code: 'cd2',
- discoveryDisplayName: 'Circulation Desk -- Back Entrance',
- holdShelfExpiryPeriod: {
- duration: 5,
- intervalId: 'Days',
- },
-
- id: 'c4c90014-c8c9-4ade-8f24-b5e313319f4b',
- name: 'Circ Desk 2',
- pickupLocation: true,
- staffSlips: []
- }
- ]
- },
- locations: {
- records: []
- }
- }
-};
-
-const mutatorMock = {
- servicePoints: {
- POST: jest.fn(() => Promise.resolve()),
- PUT: jest.fn(() => Promise.resolve()),
- DELETE: jest.fn(() => Promise.resolve()),
- },
- institutions: {
- GET: jest.fn(() => Promise.resolve()),
- reset: jest.fn(() => Promise.resolve()),
- },
- campuses: {
- GET: jest.fn(() => Promise.resolve()),
- reset: jest.fn(() => Promise.resolve()),
- },
- libraries: {
- GET: jest.fn(() => Promise.resolve()),
- reset: jest.fn(() => Promise.resolve()),
- },
- holdingsEntries: {
- GET: jest.fn(() => Promise.resolve()),
- reset: jest.fn(() => Promise.resolve()),
- },
- itemEntries: {
- GET: jest.fn(() => Promise.resolve()),
- reset: jest.fn(() => Promise.resolve()),
- },
- entries: {
- DELETE: jest.fn(() => Promise.resolve()),
- POST: jest.fn(() => Promise.resolve()),
- PUT: jest.fn(() => Promise.resolve()),
- },
- uniquenessValidator: {
- DELETE: jest.fn(() => Promise.resolve()),
- GET: jest.fn(() => Promise.resolve()),
- POST: jest.fn(() => Promise.resolve()),
- PUT: jest.fn(() => Promise.resolve()),
- cancel: jest.fn(() => Promise.resolve()),
- reset: jest.fn(() => Promise.resolve()),
- }
};
const renderLocationFormContainer = () => renderWithRouter(
-
+
+
+
);
describe('LocationFormContainer', () => {
+ mockUseOkapiKy.mockImplementation(() => ({
+ get: jest.fn(() => ({ json: jest.fn().mockResolvedValue(Promise.resolve()) })),
+ }));
+
it('should render ServicePointManager titles', () => {
renderLocationFormContainer();
diff --git a/src/settings/LocationLocations/LocationForm/RemoteStorageField.js b/src/settings/LocationLocations/LocationForm/RemoteStorageField.js
index 143d06fa..2a03c3f8 100644
--- a/src/settings/LocationLocations/LocationForm/RemoteStorageField.js
+++ b/src/settings/LocationLocations/LocationForm/RemoteStorageField.js
@@ -1,11 +1,12 @@
import React, { useState, useEffect, useMemo } from 'react';
+import PropTypes from 'prop-types';
import { useField } from 'react-final-form';
import { useStripes } from '@folio/stripes/core';
-import PropTypes from 'prop-types';
import { Control, useRemoteStorageApi } from '../RemoteStorage';
+
export const RemoteStorageField = ({ initialValues, checkLocationHasHoldingsOrItems }) => {
const stripes = useStripes();
const noInterfaces = useMemo(
@@ -13,7 +14,7 @@ export const RemoteStorageField = ({ initialValues, checkLocationHasHoldingsOrIt
[stripes]
);
- const { remoteMap, mappings, translate: t } = useRemoteStorageApi();
+ const { remoteMap, isMappingsError, isMappingsLoading, translate: t } = useRemoteStorageApi();
const [isReadOnly, setIsReadOnly] = useState(true);
@@ -40,16 +41,14 @@ export const RemoteStorageField = ({ initialValues, checkLocationHasHoldingsOrIt
if (noInterfaces) return null;
- const message = (mappings.failed && t('failed')) || (mappings.isPending && t('loading')) || (isReadOnly && t('readonly'));
-
- const isDisabled = !mappings.hasLoaded;
+ const message = (isMappingsError && t('failed')) || (isMappingsLoading && t('loading')) || (isReadOnly && t('readonly'));
return (
diff --git a/src/settings/LocationLocations/LocationForm/ServicePointsFields.js b/src/settings/LocationLocations/LocationForm/ServicePointsFields.js
index 14bf5568..7745c1e2 100644
--- a/src/settings/LocationLocations/LocationForm/ServicePointsFields.js
+++ b/src/settings/LocationLocations/LocationForm/ServicePointsFields.js
@@ -1,5 +1,5 @@
import React from 'react';
-import { FormattedMessage } from 'react-intl';
+import { FormattedMessage, injectIntl } from 'react-intl';
import { Field } from 'react-final-form';
import { FieldArray } from 'react-final-form-arrays';
import PropTypes from 'prop-types';
@@ -35,6 +35,7 @@ class ServicePointsFields extends React.Component {
servicePoints: PropTypes.arrayOf(PropTypes.object),
changePrimary: PropTypes.func.isRequired,
formValues: PropTypes.object.isRequired,
+ intl: PropTypes.object,
};
constructor(props) {
@@ -74,7 +75,10 @@ class ServicePointsFields extends React.Component {
this.list = omitUsedOptions(this.props.servicePoints, formValues.servicePointIds, 'selectSP', index);
const sortedList = sortBy(this.list, ['label']);
- const options = [{ label: 'Select service point', value: '' }, ...sortedList];
+ const options = [{
+ label: this.props.intl.formatMessage({ id: 'ui-tenant-settings.settings.servicePoints.placeholder' }),
+ value: ''
+ }, ...sortedList];
return (
@@ -108,7 +112,9 @@ class ServicePointsFields extends React.Component {
const { formValues } = this.props;
// make the last existing service point to be the primary one
- if (formValues.servicePointIds && formValues.servicePointIds.length === 1 && !formValues.servicePointIds[0].primary) {
+ const isPrimary = formValues.servicePointIds && formValues.servicePointIds.length === 1 && !formValues.servicePointIds[0].primary;
+
+ if (isPrimary) {
this.singlePrimary(0);
}
@@ -143,4 +149,4 @@ class ServicePointsFields extends React.Component {
}
}
-export default ServicePointsFields;
+export default injectIntl(ServicePointsFields);
diff --git a/src/settings/LocationLocations/LocationManager.js b/src/settings/LocationLocations/LocationManager.js
index 310f35a9..31de12b0 100644
--- a/src/settings/LocationLocations/LocationManager.js
+++ b/src/settings/LocationLocations/LocationManager.js
@@ -1,20 +1,24 @@
-import React from 'react';
+import React, { useState, useRef } from 'react';
import PropTypes from 'prop-types';
-import { Route } from 'react-router-dom';
-
+import {
+ Route,
+ useHistory,
+ useLocation,
+ useRouteMatch
+} from 'react-router-dom';
import {
FormattedMessage,
- injectIntl,
+ useIntl,
} from 'react-intl';
import {
cloneDeep,
find,
isEmpty,
omit,
- get,
forEach,
} from 'lodash';
import queryString from 'query-string';
+import { useQueryClient } from 'react-query';
import {
SearchAndSortQuery,
@@ -32,8 +36,12 @@ import {
Layer,
Callout,
} from '@folio/stripes/components';
+import {
+ TitleManager,
+ useOkapiKy,
+ useStripes
+} from '@folio/stripes/core';
-import { TitleManager } from '@folio/stripes/core';
import {
LOCATION_CAMPUS_ID_KEY,
LOCATION_INSTITUTION_ID_KEY,
@@ -43,327 +51,192 @@ import {
import LocationDetail from './LocationDetail';
import EditForm from './LocationForm';
import { RemoteStorageApiProvider } from './RemoteStorage';
+import { useInstitutions } from '../../hooks/useInstitutions';
+import { useLibraries } from '../../hooks/useLibraries';
+import { useCampuses } from '../../hooks/useCampuses';
+import { SERVICE_POINTS, useServicePoints } from '../../hooks/useServicePoints';
+import { LOCATIONS, useLocations } from '../../hooks/useLocations';
+import { useLocationDelete } from '../../hooks/useLocationDelete';
+
+
+const initialSelectedLocationId = (location) => {
+ const idFromPathnameRe = '/([^/]+)$';
+ const reMatches = new RegExp(idFromPathnameRe).exec(location.pathname);
+ return reMatches ? reMatches[1] : null;
+};
+
+const initialSort = (location) => {
+ const { sort = 'name', sortDir = SORT_TYPES.ASCENDING } = queryString.parse(location.search.slice(1));
+ return { sort, sortDir };
+};
+
+const locationListVisibleColumns = ['isActive', 'name', 'code'];
+
+const locationListColumnMapping = {
+ isActive: ,
+ name: ,
+ code: ,
+};
+
+const locationListFormatter = {
+ isActive: item => {
+ const locationId = item.isActive ? 'active' : 'inactive';
+ return ;
+ }
+};
+
+const LocationManager = ({ label }) => {
+ const intl = useIntl();
+ const stripes = useStripes();
+ const queryClient = useQueryClient();
+ const ky = useOkapiKy();
+ const callout = useRef(null);
+ const location = useLocation();
+ const history = useHistory();
+ const match = useRouteMatch();
+
+ const entryLabel = intl.formatMessage({ id: 'ui-tenant-settings.settings.location.locations.location' });
+ const hasAllLocationPerms = stripes.hasPerm('ui-tenant-settings.settings.location');
+
+ const showCalloutMessage = (name) => {
+ if (!callout.current) return;
+ const message = (
+
+ );
+ callout.current.sendCallout({ message });
+ };
-class LocationManager extends React.Component {
- static manifest = Object.freeze({
- entries: {
- type: 'okapi',
- records: 'locations',
- path: 'locations',
- params: {
- query: 'cql.allRecords=1 sortby name',
- limit: '3000',
- },
- },
- uniquenessValidator: {
- type: 'okapi',
- records: 'locations',
- accumulate: 'true',
- path: 'locations',
- fetch: false,
- },
- institutions: {
- type: 'okapi',
- path: 'location-units/institutions',
- params: {
- query: 'cql.allRecords=1 sortby name',
- limit: '1000',
- },
- records: 'locinsts',
- accumulate: true,
- },
- campuses: {
- type: 'okapi',
- path: 'location-units/campuses',
- params: {
- query: 'cql.allRecords=1 sortby name',
- limit: '1000',
- },
- records: 'loccamps',
- accumulate: true,
- },
- libraries: {
- type: 'okapi',
- path: 'location-units/libraries',
- params: {
- query: 'cql.allRecords=1 sortby name',
- limit: '1000',
- },
- records: 'loclibs',
- accumulate: true,
- },
- servicePoints: {
- type: 'okapi',
- records: 'servicepoints',
- path: 'service-points',
- params: {
- query: 'cql.allRecords=1 sortby name',
- limit: '1000',
- },
- resourceShouldRefresh: true,
- },
- holdingsEntries: {
- type: 'okapi',
- path: 'holdings-storage/holdings',
- records: 'holdingsRecords',
- accumulate: true,
- },
- itemEntries: {
- type: 'okapi',
- path: 'inventory/items',
- records: 'items',
- accumulate: true,
+ const [institutionId, setInstitutionId] = useState(sessionStorage.getItem(LOCATION_INSTITUTION_ID_KEY) || '');
+ const [campusId, setCampusId] = useState(sessionStorage.getItem(LOCATION_CAMPUS_ID_KEY) || '');
+ const [libraryId, setLibraryId] = useState(sessionStorage.getItem(LOCATION_LIBRARY_ID_KEY) || '');
+ const [selectedId, setSelectedId] = useState(initialSelectedLocationId(location));
+ const [sortState, setSortState] = useState(initialSort(location));
+
+ const { institutions } = useInstitutions({ searchParams: {
+ limit: 100,
+ query: 'cql.allRecords=1 sortby name',
+ } });
+
+ const { libraries } = useLibraries({ searchParams: {
+ limit: 1000,
+ query: 'cql.allRecords=1 sortby name',
+ } });
+
+ const { campuses } = useCampuses({ searchParams: {
+ limit: 1000,
+ query: 'cql.allRecords=1 sortby name',
+ } });
+
+ const { servicePoints } = useServicePoints({ searchParams: {
+ limit: 1000,
+ query: 'cql.allRecords=1 sortby name',
+ } });
+
+ const { locations: locationEntries, refetch: refetchLocationEntries } = useLocations({
+ searchParams: {
+ limit: 3000,
+ query: 'cql.allRecords=1 sortby name'
},
});
- static propTypes = {
- intl: PropTypes.object,
- label: PropTypes.node.isRequired,
- location: PropTypes.shape({
- search: PropTypes.string,
- pathname: PropTypes.string,
- }).isRequired,
- history: PropTypes.shape({ push: PropTypes.func.isRequired }).isRequired,
- match: PropTypes.shape({ path: PropTypes.string.isRequired }).isRequired,
- resources: PropTypes.shape({
- entries: PropTypes.shape({ records: PropTypes.arrayOf(PropTypes.object) }),
- servicePoints: PropTypes.shape({ records: PropTypes.arrayOf(PropTypes.object),
- hasLoaded: PropTypes.bool }),
- institutions: PropTypes.shape({ records: PropTypes.arrayOf(PropTypes.object) }),
- campuses: PropTypes.shape({ records: PropTypes.arrayOf(PropTypes.object) }),
- libraries: PropTypes.shape({ records: PropTypes.arrayOf(PropTypes.object) }),
- }).isRequired,
- mutator: PropTypes.shape({
- entries: PropTypes.shape({
- POST: PropTypes.func,
- PUT: PropTypes.func,
- DELETE: PropTypes.func,
- }),
- servicePoints: PropTypes.shape({
- POST: PropTypes.func,
- PUT: PropTypes.func,
- DELETE: PropTypes.func,
- }),
- institutions: PropTypes.shape({
- GET: PropTypes.func.isRequired,
- reset: PropTypes.func.isRequired,
- }),
- campuses: PropTypes.shape({
- GET: PropTypes.func.isRequired,
- reset: PropTypes.func.isRequired,
- }),
- libraries: PropTypes.shape({
- GET: PropTypes.func.isRequired,
- reset: PropTypes.func.isRequired,
- }),
- holdingsEntries: PropTypes.shape({
- GET: PropTypes.func.isRequired,
- reset: PropTypes.func.isRequired,
- }),
- itemEntries: PropTypes.shape({
- GET: PropTypes.func.isRequired,
- reset: PropTypes.func.isRequired,
- }),
- uniquenessValidator: PropTypes.object,
- }).isRequired,
- stripes: PropTypes.shape({
- hasPerm: PropTypes.func.isRequired,
- connect: PropTypes.func.isRequired,
- hasInterface: PropTypes.func.isRequired,
- }),
- };
-
- constructor(props) {
- super(props);
-
- this.state = {
- institutionId: sessionStorage.getItem(LOCATION_INSTITUTION_ID_KEY) || '',
- campusId: sessionStorage.getItem(LOCATION_CAMPUS_ID_KEY) || '',
- libraryId: sessionStorage.getItem(LOCATION_LIBRARY_ID_KEY) || '',
- servicePointsById: {},
- servicePointsByName: {},
- selectedId: this.initialSelectedLocationId,
- ...this.initialSort,
- };
-
- this.callout = React.createRef();
-
- const { formatMessage } = props.intl;
-
- this.entryLabel = formatMessage({ id: 'ui-tenant-settings.settings.location.locations.location' });
- this.locationListVisibleColumns = ['isActive', 'name', 'code'];
- this.locationListColumnMapping = {
- isActive: formatMessage({ id: 'ui-tenant-settings.settings.location.locations.status' }),
- name: formatMessage({ id: 'ui-tenant-settings.settings.location.locations.detailsName' }),
- code: formatMessage({ id: 'ui-tenant-settings.settings.location.code' }),
- };
- this.locationListFormatter = {
- isActive: item => {
- const locationId = item.isActive ? 'active' : 'inactive';
-
- return formatMessage({ id: `ui-tenant-settings.settings.location.locations.${locationId}` });
- }
- };
- this.hasAllLocationPerms = props.stripes.hasPerm('ui-tenant-settings.settings.location');
- }
-
- static getDerivedStateFromProps(nextProps) {
- const { resources } = nextProps;
- const servicePointsByName = {};
- if (resources.servicePoints && resources.servicePoints.hasLoaded) {
- const servicePointsById = ((resources.servicePoints || {}).records || []).reduce((map, item) => {
- map[item.id] = item.name;
- servicePointsByName[item.name] = item.id;
- return map;
- }, {});
- return { servicePointsById, servicePointsByName };
+ const { deleteLocation } = useLocationDelete({
+ onSuccess: () => {
+ queryClient.invalidateQueries(SERVICE_POINTS);
+ queryClient.invalidateQueries(LOCATIONS);
}
- return null;
- }
-
- /**
- * Refresh lookup tables when the component mounts. Fetches in the manifest
- * will only run once (in the constructor) but because this object may be
- * unmounted/remounted without being destroyed/recreated, the lookup tables
- * will be stale if they change between unmounting/remounting.
- */
- componentDidMount() {
- ['institutions', 'campuses', 'libraries'].forEach(i => {
- this.props.mutator[i].reset();
- this.props.mutator[i].GET();
- });
- }
-
- get initialSelectedLocationId() {
- const { location } = this.props;
+ });
- const idFromPathnameRe = '/([^/]+)$';
- const reMatches = new RegExp(idFromPathnameRe).exec(location.pathname);
+ const { servicePointsById, servicePointsByName } = servicePoints.reduce((acc, item) => {
+ acc.servicePointsById[item.id] = item.name;
+ acc.servicePointsByName[item.name] = item.id;
- return reMatches ? reMatches[1] : null;
- }
+ return acc;
+ }, { servicePointsById: {}, servicePointsByName: {} });
- get initialSort() {
- const { location: { search } } = this.props;
+ const transitionToParams = (values) => {
+ const url = buildUrl(location, values);
+ history.push(url);
+ };
- const {
- sort = 'name',
- sortDir = SORT_TYPES.ASCENDING,
- } = queryString.parse(search.slice(1));
+ const formatLocationDisplayName = (loc) => {
+ let lbl = loc.name;
- return {
- sort,
- sortDir,
- };
- }
+ if (loc.code) {
+ lbl += ` (${loc.code})`;
+ }
- onSort = (e, { name: fieldName }) => {
- const {
- sort,
- sortDir,
- } = this.state;
+ return lbl;
+ };
+ const onSort = (e, { name: fieldName }) => {
+ const { sort, sortDir } = sortState;
const isSameField = sort === fieldName;
let newSortDir = SORT_TYPES.ASCENDING;
-
if (isSameField) {
newSortDir = newSortDir === sortDir ? SORT_TYPES.DESCENDING : newSortDir;
}
-
- const sortState = {
- sort: fieldName,
- sortDir: newSortDir,
- };
-
- this.setState(sortState);
- this.transitionToParams(sortState);
+ const newSortState = { sort: fieldName, sortDir: newSortDir };
+ setSortState(newSortState);
+ transitionToParams(newSortState);
};
- onSelectRow = (e, meta) => {
- const { match: { path } } = this.props;
-
- this.transitionToParams({ _path: `${path}/${meta.id}` });
- this.setState({ selectedId: meta.id });
+ const onSelectRow = (e, meta) => {
+ transitionToParams({ _path: `${match.path}/${meta.id}` });
+ setSelectedId(meta.id);
};
- transitionToParams(values) {
- const {
- location,
- history,
- } = this.props;
-
- const url = buildUrl(location, values);
-
- history.push(url);
- }
-
- onChangeInstitution = (e) => {
- const institutionId = e.target.value;
-
- sessionStorage.setItem(LOCATION_INSTITUTION_ID_KEY, institutionId);
+ const onChangeInstitution = (e) => {
+ const newInstitutionId = e.target.value;
+ sessionStorage.setItem(LOCATION_INSTITUTION_ID_KEY, newInstitutionId);
sessionStorage.setItem(LOCATION_CAMPUS_ID_KEY, '');
sessionStorage.setItem(LOCATION_LIBRARY_ID_KEY, '');
-
- this.setState({
- institutionId,
- campusId: '',
- libraryId: '',
- });
+ setInstitutionId(newInstitutionId);
+ setCampusId('');
+ setLibraryId('');
};
- onChangeCampus = (e) => {
- const campusId = e.target.value;
-
- sessionStorage.setItem(LOCATION_CAMPUS_ID_KEY, campusId);
-
- this.setState({
- campusId,
- libraryId: '',
- });
+ const onChangeCampus = (e) => {
+ const newCampusId = e.target.value;
+ sessionStorage.setItem(LOCATION_CAMPUS_ID_KEY, newCampusId);
+ setCampusId(newCampusId);
+ setLibraryId('');
};
- onChangeLibrary = (e) => {
- const libraryId = e.target.value;
-
- sessionStorage.setItem(LOCATION_LIBRARY_ID_KEY, libraryId);
-
- this.setState({ libraryId });
+ const onChangeLibrary = (e) => {
+ const newLibraryId = e.target.value;
+ sessionStorage.setItem(LOCATION_LIBRARY_ID_KEY, newLibraryId);
+ setLibraryId(newLibraryId);
};
- renderFilter() {
- const {
- resources,
- location,
- intl: { formatMessage },
- } = this.props;
- const {
- institutionId,
- campusId,
- libraryId,
- } = this.state;
-
- const institutions = get(resources.institutions, 'records', [])
+ const renderFilter = () => {
+ const formattedInstitutions = institutions
.map(institution => ({
value: institution.id,
- label: this.formatLocationDisplayName(institution),
+ label: formatLocationDisplayName(institution),
}));
- if (isEmpty(institutions)) {
+ if (isEmpty(formattedInstitutions)) {
return ;
}
- const campuses = get(resources.campuses, 'records', [])
+ const formattedCampuses = campuses
.filter(campus => campus.institutionId === institutionId)
.map(campus => ({
value: campus.id,
- label: this.formatLocationDisplayName(campus),
+ label: formatLocationDisplayName(campus),
}));
- const libraries = get(resources.libraries, 'records', [])
+ const formattedLibraries = libraries
.filter(library => library.campusId === campusId)
.map(library => ({
value: library.id,
- label: this.formatLocationDisplayName(library),
+ label: formatLocationDisplayName(library),
}));
return (
@@ -374,8 +247,8 @@ class LocationManager extends React.Component {
id="institutionSelect"
name="institutionSelect"
value={institutionId}
- dataOptions={[{ label: formatMessage({ id: 'ui-tenant-settings.settings.location.institutions.selectInstitution' }), value: '' }, ...institutions]}
- onChange={this.onChangeInstitution}
+ dataOptions={[{ label: intl.formatMessage({ id: 'ui-tenant-settings.settings.location.institutions.selectInstitution' }), value: '' }, ...formattedInstitutions]}
+ onChange={onChangeInstitution}
/>
@@ -384,25 +257,25 @@ class LocationManager extends React.Component {
id="campusSelect"
name="campusSelect"
value={campusId}
- dataOptions={[{ label: formatMessage({ id: 'ui-tenant-settings.settings.location.campuses.selectCampus' }), value: '' }, ...campuses]}
- onChange={this.onChangeCampus}
+ dataOptions={[{ label: intl.formatMessage({ id: 'ui-tenant-settings.settings.location.campuses.selectCampus' }), value: '' }, ...formattedCampuses]}
+ onChange={onChangeCampus}
/>}
{campusId && }
id="librarySelect"
- name="campusSelect"
+ name="librarySelect"
value={libraryId}
- dataOptions={[{ label: formatMessage({ id: 'ui-tenant-settings.settings.location.libraries.selectLibrary' }), value: '' }, ...libraries]}
- onChange={this.onChangeLibrary}
+ dataOptions={[{ label: intl.formatMessage({ id: 'ui-tenant-settings.settings.location.libraries.selectLibrary' }), value: '' }, ...formattedLibraries]}
+ onChange={onChangeLibrary}
/>}
- {this.hasAllLocationPerms && (
+ {hasAllLocationPerms && (
@@ -426,249 +299,188 @@ class LocationManager extends React.Component {
}
);
- }
-
- formatLocationDisplayName(location) {
- return `${location.name}${location.code ? ` (${location.code})` : ''}`;
- }
+ };
- parseInitialValues(loc, cloning = false) {
+ const parseInitialValues = (loc, cloning = false) => {
if (!loc) return loc;
-
- loc.detailsArray = Object.keys(loc.details || []).map(name => {
- return { name, value: loc.details[name] };
- }).sort();
-
+ loc.detailsArray = Object.keys(loc.details || []).map(name => ({ name, value: loc.details[name] }))
+ .sort((a, b) => a.name.localeCompare(b.name));
return cloning ? omit(loc, 'id') : loc;
- }
-
- handleDetailClose = () => {
- this.transitionToParams({ _path: this.props.match.path });
- this.setState({ selectedId: null });
};
- prepareLocationsData() {
- const { resources } = this.props;
- const {
- sort,
- sortDir,
- } = this.state;
+ const handleDetailClose = () => {
+ transitionToParams({ _path: match.path });
+ setSelectedId(null);
+ refetchLocationEntries();
+ };
+ const prepareLocationsData = () => {
+ const { sort, sortDir } = sortState;
const sortDirValue = sortDir === SORT_TYPES.ASCENDING ? 1 : -1;
-
- return cloneDeep((resources.entries || {}).records || []).map(location => {
- location.servicePointIds = (location.servicePointIds || []).map(id => ({
- selectSP: this.state.servicePointsById[id],
- primary: (location.primaryServicePoint === id),
+ return cloneDeep((locationEntries)).map(loc => {
+ loc.servicePointIds = (loc.servicePointIds || []).map(id => ({
+ selectSP: servicePointsById[id],
+ primary: (loc.primaryServicePoint === id),
}));
- return location;
+ return loc;
}).sort((a, b) => sortDirValue * `${a[sort]}`.localeCompare(`${b[sort]}`));
- }
+ };
- onCancel = (e) => {
+ const onCancel = (e) => {
if (e) {
e.preventDefault();
}
-
- this.transitionToParams({ layer: null });
+ transitionToParams({ layer: null });
};
- handleDetailEdit = location => {
- this.setState({ selectedId: location.id });
- this.transitionToParams({ layer: 'edit' });
+ const handleDetailEdit = loc => {
+ setSelectedId(loc.id);
+ transitionToParams({ layer: 'edit' });
};
- handleDetailClone = location => {
- this.setState({ selectedId: location.id });
- this.transitionToParams({ layer: 'clone' });
+ const handleDetailClone = loc => {
+ setSelectedId(loc.id);
+ transitionToParams({ layer: 'clone' });
};
- checkLocationHasHoldingsOrItems = async (locationId) => {
- const { mutator } = this.props;
+ const checkLocationHasHoldingsOrItems = async (locationId) => {
const query = `permanentLocationId=="${locationId}" or temporaryLocationId=="${locationId}"`;
- mutator.holdingsEntries.reset();
- mutator.itemEntries.reset();
-
const results = await Promise.all([
- mutator.holdingsEntries.GET({ params: { query } }),
- mutator.itemEntries.GET({ params: { query } }),
+ ky.get('inventory/items', { searchParams: { query } }).json(),
+ ky.get('holdings-storage/holdings', { searchParams: { query } }).json(),
]);
return results.some(records => records.length > 0);
};
- onRemove = location => {
- const {
- match,
- mutator,
- } = this.props;
-
- return this.checkLocationHasHoldingsOrItems(location.id)
- .then(hasSomething => !hasSomething && mutator.entries.DELETE(location))
+ const onRemove = loc => {
+ return checkLocationHasHoldingsOrItems(loc.id)
+ .then(hasSomething => !hasSomething && deleteLocation({ locationId: loc.id }))
.then(result => {
const isRemoved = (result !== false);
-
if (isRemoved) {
- this.showCalloutMessage(location.name);
- this.transitionToParams({
+ showCalloutMessage(loc.name);
+ transitionToParams({
_path: `${match.path}`,
layer: null
});
}
-
return isRemoved;
});
};
- updateSelected = location => {
- this.transitionToParams({
- _path: `${this.props.match.path}/${location.id}`,
+ const updateSelected = loc => {
+ transitionToParams({
+ _path: `${match.path}/${loc.id}`,
layer: null,
});
- this.setState({ selectedId: location.id });
+ setSelectedId(loc.id);
};
- showCalloutMessage(name) {
- if (!this.callout.current) return;
-
- const message = (
-
- );
-
- this.callout.current.sendCallout({ message });
- }
-
- render() {
- const {
- match,
- label,
- location: { search },
- mutator,
- } = this.props;
- const {
- institutionId,
- campusId,
- libraryId,
- sort,
- sortDir,
- selectedId,
- servicePointsById,
- servicePointsByName,
- } = this.state;
-
- const locations = this.prepareLocationsData();
- const contentData = locations.filter(row => row.libraryId === libraryId);
- const query = queryString.parse(search);
- const defaultEntry = { isActive: true, institutionId, campusId, libraryId, servicePointIds: [{ selectSP: '', primary: true }] };
- const adding = search.match('layer=add');
- const cloning = search.match('layer=clone');
-
- // Providing default 'isActive' value is used here when the 'isActive' property is missing in the 'locations' loaded via the API.
- forEach(contentData, location => {
- if (location.isActive === undefined) {
- location.isActive = false;
- }
- });
-
- const selectedItem = (selectedId && !adding)
- ? find(contentData, entry => entry.id === selectedId) : defaultEntry;
+ const locations = prepareLocationsData();
+ const contentData = locations.filter(row => row.libraryId === libraryId);
+ const query = queryString.parse(location.search);
+ const defaultEntry = { isActive: true, institutionId, campusId, libraryId, servicePointIds: [{ selectSP: '', primary: true }] };
+ const adding = location.search.match('layer=add');
+ const cloning = location.search.match('layer=clone');
- const initialValues = this.parseInitialValues(selectedItem, cloning);
+ forEach(contentData, loc => {
+ if (loc.isActive === undefined) {
+ loc.isActive = false;
+ }
+ });
- const container = document.getElementById('ModuleContainer');
+ const selectedItem = (selectedId && !adding) ? find(contentData, entry => entry.id === selectedId) : defaultEntry;
+ const initialValues = parseInitialValues(selectedItem, cloning);
- if (!container) return ();
+ const container = document.getElementById('ModuleContainer');
+ if (!container) return ();
- return (
-
+
-
-
- {() => (
- <>
-
- {this.renderFilter()}
-
-
- >
- )}
-
-
- {
- if (!selectedItem) return null;
-
- return (
-
-
-
- );
- }
- }
- />
-
-
- {contentLabelChunks => (
-
-
+ {() => (
+ <>
+
+ {renderFilter()}
+
-
- )}
-
-
-
-
- );
- }
-}
-
-export default injectIntl(LocationManager);
-// export default LocationManager;
+
+ >
+ )}
+
+
+ {
+ if (!selectedItem) return null;
+ return (
+
+
+
+ );
+ }}
+ />
+
+
+ {contentLabelChunks => (
+
+
+
+ )}
+
+
+
+
+ );
+};
+
+LocationManager.propTypes = {
+ label: PropTypes.node.isRequired,
+};
+
+export default LocationManager;
diff --git a/src/settings/LocationLocations/LocationManager.test.js b/src/settings/LocationLocations/LocationManager.test.js
index ad106c6a..8f1a0b0e 100644
--- a/src/settings/LocationLocations/LocationManager.test.js
+++ b/src/settings/LocationLocations/LocationManager.test.js
@@ -1,51 +1,30 @@
import React from 'react';
import { screen } from '@testing-library/react';
import { createMemoryHistory } from 'history';
-
-import '../../../test/jest/__mocks__';
+import { QueryClient, QueryClientProvider } from 'react-query';
import userEvent from '@testing-library/user-event';
-import buildStripes from '../../../test/jest/__new_mocks__/stripesCore.mock';
+
import {
renderWithRouter
} from '../../../test/jest/helpers';
-
import LocationManager from './LocationManager';
+import '../../../test/jest/__mocks__';
+
+
jest.mock('./RemoteStorage/Provider', () => ({
...jest.requireActual('./RemoteStorage/Provider'),
useRemoteStorageApi: () => ({
remoteMap: {},
- mappings: {
- failed: false,
- hasLoaded: true,
- isPending: false
- },
- configurations: {
- failed: false,
- hasLoaded: true,
- isPending: false,
- records: []
- },
+ mappings: [],
+ configurations: [],
translate: () => 'str'
})
}));
-const STRIPES = buildStripes();
-
-const history = createMemoryHistory();
-
-const locationMock = {
- pathname: '/settings/tenant-settings/location-locations',
- search: '',
- hash: '',
- key: '00ee83',
-};
-
-const resourcesMock = {
- campuses: { hasLoaded: true,
- resource: 'campuses',
- dataKey: 'location-locations',
- records:[
+jest.mock('../../hooks/useCampuses', () => ({
+ useCampuses: jest.fn(() => ({
+ campuses: [
{ code: 'DI',
id: '40ee00ca-a518-4b49-be01-0638d0a4ac57ff',
institutionId: '40ee00ca-a518-4b49-be01-0638d0a4ac57',
@@ -56,10 +35,38 @@ const resourcesMock = {
institutionId: '40ee00ca-a518-4b49-be01-0638d0a4ac57',
name: 'Online'
}
- ] },
- entries:{
- hasLoaded: true,
- records:[
+ ],
+ })),
+}));
+
+jest.mock('../../hooks/useInstitutions', () => ({
+ useInstitutions: jest.fn(() => ({
+ institutions: [
+ {
+ code: 'KU',
+ id: '40ee00ca-a518-4b49-be01-0638d0a4ac57',
+ name: 'Københavns Universitet',
+ }
+ ],
+ })),
+}));
+
+jest.mock('../../hooks/useLibraries', () => ({
+ useLibraries: jest.fn(() => ({
+ libraries: [
+ {
+ campusId: '40ee00ca-a518-4b49-be01-0638d0a4ac57ff',
+ code: 'DI',
+ id: '5d78803e-ca04-4b4a-aeae-2c63b924518b',
+ name: 'Datalogisk Institut'
+ }
+ ],
+ })),
+}));
+
+jest.mock('../../hooks/useLocations', () => ({
+ useLocations: jest.fn(() => ({
+ locations: [
{
campusId: '62cf76b7-cca5-4d33-9217-edf42ce1a848',
code: 'KU/CC/DI/2',
@@ -86,113 +93,59 @@ const resourcesMock = {
servicePointIds: ['3a40852d-49fd-4df2-a1f9-6e2641a6e91f'],
servicePoints: []
}
- ],
- resource: 'entries'
- },
- institutions: {
- hasLoaded: true,
- records: [
- {
- code: 'KU',
- id: '40ee00ca-a518-4b49-be01-0638d0a4ac57',
- name: 'Københavns Universitet',
- }
]
- },
- libraries:{
- dataKey: 'location-locations',
- hasLoaded: true,
- records: [
+ })),
+}));
+
+jest.mock('../../hooks/useServicePoints', () => ({
+ useServicePoints: jest.fn(() => ({
+ servicePoints: [
{
- campusId: '40ee00ca-a518-4b49-be01-0638d0a4ac57ff',
- code: 'DI',
- id: '5d78803e-ca04-4b4a-aeae-2c63b924518b',
- name: 'Datalogisk Institut'
+ code: 'cd1',
+ discoveryDisplayName: 'Circulation Desk -- Hallway',
+ holdShelfExpiryPeriod: { duration: 3, intervalId: 'Weeks' },
+ id: '3a40852d-49fd-4df2-a1f9-6e2641a6e91f',
+ name: 'Circ Desk 1',
+ pickupLocation: true,
+ staffSlips: [],
+ },
+ {
+ code: 'Online',
+ discoveryDisplayName: 'Online',
+ id: '7c5abc9f-f3d7-4856-b8d7-6712462ca007',
+ metadata: { createdDate: '2021-11-04T03:24:42.555+00:00', updatedDate: '2021-11-04T03:24:42.555+00:00' },
+ name: 'Online',
+ pickupLocation: false,
+ shelvingLagTime: 0,
+ staffSlips: [],
}
]
- },
- servicePoints: {
- hasLoaded: true,
- records: [{
- code: 'cd1',
- discoveryDisplayName: 'Circulation Desk -- Hallway',
- holdShelfExpiryPeriod: { duration: 3, intervalId: 'Weeks' },
- id: '3a40852d-49fd-4df2-a1f9-6e2641a6e91f',
- name: 'Circ Desk 1',
- pickupLocation: true,
- staffSlips: [],
- },
- {
- code: 'Online',
- discoveryDisplayName: 'Online',
- id: '7c5abc9f-f3d7-4856-b8d7-6712462ca007',
- metadata: { createdDate: '2021-11-04T03:24:42.555+00:00', updatedDate: '2021-11-04T03:24:42.555+00:00' },
- name: 'Online',
- pickupLocation: false,
- shelvingLagTime: 0,
- staffSlips: [],
- }
- ]
- }
-};
-
-const mutatorMock = {
- servicePoints: {
- POST: jest.fn(() => Promise.resolve()),
- PUT: jest.fn(() => Promise.resolve()),
- DELETE: jest.fn(() => Promise.resolve()),
- },
- institutions: {
- GET: jest.fn(() => Promise.resolve()),
- reset: jest.fn(() => Promise.resolve()),
- },
- campuses: {
- GET: jest.fn(() => Promise.resolve()),
- reset: jest.fn(() => Promise.resolve()),
- },
- libraries: {
- GET: jest.fn(() => Promise.resolve()),
- reset: jest.fn(() => Promise.resolve()),
- },
- holdingsEntries: {
- GET: jest.fn(() => Promise.resolve()),
- reset: jest.fn(() => Promise.resolve()),
- },
- itemEntries: {
- GET: jest.fn(() => Promise.resolve()),
- reset: jest.fn(() => Promise.resolve()),
- },
- entries: {
- DELETE: jest.fn(() => Promise.resolve()),
- POST: jest.fn(() => Promise.resolve()),
- PUT: jest.fn(() => Promise.resolve()),
- },
- uniquenessValidator: {
- DELETE: jest.fn(() => Promise.resolve()),
- GET: jest.fn(() => Promise.resolve()),
- POST: jest.fn(() => Promise.resolve()),
- PUT: jest.fn(() => Promise.resolve()),
- cancel: jest.fn(() => Promise.resolve()),
- reset: jest.fn(() => Promise.resolve()),
- }
-};
-
-const matchMock = {
- path: '/settings/tenant-settings/location-locations',
- isExact: true,
- params: {}
-};
-
-const renderLocationManager = (match = matchMock) => renderWithRouter(
- ServicePointManager}
- location={locationMock}
- history={history}
- match={match}
- />
+ })),
+}));
+
+jest.mock('../../hooks/useLocationCreate', () => ({
+ useLocationCreate: jest.fn(() => ({
+ createLocation: jest.fn(),
+ isCreatingLocation: false,
+ })),
+}));
+
+jest.mock('../../hooks/useLocationUpdate', () => ({
+ useLocationUpdate: jest.fn(() => ({
+ updateLocation: jest.fn(),
+ isUpdatingLocation: false,
+ })),
+}));
+
+
+const history = createMemoryHistory();
+
+const renderLocationManager = () => renderWithRouter(
+
+ ServicePointManager}
+ />
+
);
describe('LocationManager', () => {
@@ -254,10 +207,6 @@ describe('LocationManager', () => {
));
libraryOption.forEach((el) => expect(el.selected).toBe(true));
- const rowButtons = screen.getAllByRole('button', { name: 'row button' });
- const headerButton = screen.getByRole('cell', { name: 'ui-tenant-settings.settings.location.locations.status' });
- userEvent.click(headerButton);
- userEvent.click(rowButtons[0]);
});
it('should render select Service points', () => {
diff --git a/src/settings/LocationLocations/RemoteStorage/Control.js b/src/settings/LocationLocations/RemoteStorage/Control.js
index d335d9f3..18daf5b3 100644
--- a/src/settings/LocationLocations/RemoteStorage/Control.js
+++ b/src/settings/LocationLocations/RemoteStorage/Control.js
@@ -30,15 +30,20 @@ const CustomSelect = ({ message, ...rest }) => (
);
export const Control = ({ disabled, readOnly, message, ...rest }) => {
- const { configurations, translate: t } = useRemoteStorageApi();
+ const {
+ configurations,
+ isConfigurationsLoading,
+ isConfigurationsError,
+ translate: t
+ } = useRemoteStorageApi();
- const errorMessage = configurations.failed && t('failed');
- const loadingMessage = configurations.isPending && t('loading');
- const isDisabled = disabled || !configurations.hasLoaded;
+ const errorMessage = isConfigurationsError && t('failed');
+ const loadingMessage = isConfigurationsLoading && t('loading');
+ const isDisabled = disabled || isConfigurationsLoading;
- const configurationOptions = configurations.records.map(c => ({ label: c.name, value: c.id }));
+ const configurationOptions = configurations.map(c => ({ label: c.name, value: c.id }));
const defaultOption = { label: t('no'), value: '' };
- const options = configurations.hasLoaded ? [defaultOption, ...configurationOptions] : undefined;
+ const options = !isConfigurationsLoading ? [defaultOption, ...configurationOptions] : undefined;
return (
render(
-
- Control}
- sub={SubControl}
- dataOptions={dataOptionsMock}
- />
-
+
+
+ Control}
+ sub={SubControl}
+ dataOptions={dataOptionsMock}
+ />
+
+
);
describe('Control', () => {
diff --git a/src/settings/LocationLocations/RemoteStorage/Provider.js b/src/settings/LocationLocations/RemoteStorage/Provider.js
index 64c1c094..cc55377e 100644
--- a/src/settings/LocationLocations/RemoteStorage/Provider.js
+++ b/src/settings/LocationLocations/RemoteStorage/Provider.js
@@ -1,37 +1,62 @@
import React, {
- useEffect,
- useState,
useContext,
createContext,
useMemo,
} from 'react';
-import PropTypes from 'prop-types';
import { useIntl } from 'react-intl';
-import { stripesConnect } from '@folio/stripes/core';
+import { useStripes } from '@folio/stripes/core';
+
+import { useRemoteStorageConfigurations } from '../../../hooks/useRemoteStorageConfigurations';
+import { useRemoteStorageMappingUpdate } from '../../../hooks/useRemoteStorageMappingUpdate';
+import { useRemoteStorageMappingDelete } from '../../../hooks/useRemoteStorageMappingDelete';
+import { useRemoteStorageMappings } from '../../../hooks/useRemoteStorageMappings';
+
const Context = createContext({});
export const useRemoteStorageApi = () => useContext(Context);
-const Provider = ({ resources, mutator, stripes, ...rest }) => {
- const [persistentMutator] = useState(mutator);
+export const RemoteStorageApiProvider = (props) => {
+ const stripes = useStripes();
- useEffect(() => {
- if (stripes.hasInterface('remote-storage-configurations')) {
- persistentMutator.configurations.reset();
- persistentMutator.configurations.GET();
+ const {
+ configurations,
+ isConfigurationsLoading,
+ isConfigurationsError
+ } = useRemoteStorageConfigurations({
+ searchParams: {
+ limit: 10000
+ },
+ options: {
+ enabled: stripes.hasInterface('remote-storage-configurations'),
}
- }, [persistentMutator.configurations, stripes]);
+ });
+
+ const {
+ mappings,
+ isMappingsLoading,
+ isMappingsError
+ } = useRemoteStorageMappings({
+ searchParams: {
+ limit: 10000
+ },
+ options: {
+ enabled: stripes.hasInterface('remote-storage-mappings'),
+ }
+ });
+
+ const { updateMapping } = useRemoteStorageMappingUpdate();
+ const { deleteMapping } = useRemoteStorageMappingDelete();
const { formatMessage } = useIntl();
const translate = key => formatMessage({ id: `ui-tenant-settings.settings.location.remotes.${key}` });
const remoteMap = useMemo(
- () => Object.fromEntries(resources.mappings.records.map(
+ () => Object.fromEntries(mappings.map(
({ folioLocationId, configurationId }) => [folioLocationId, configurationId]
)),
- [resources.mappings.records]
+ [mappings]
);
const setMapping = ({ folioLocationId, configurationId }) => {
@@ -39,49 +64,26 @@ const Provider = ({ resources, mutator, stripes, ...rest }) => {
return Promise.resolve();
}
- if (configurationId) return persistentMutator.mappings.POST({ folioLocationId, configurationId });
+ if (configurationId) {
+ return updateMapping({
+ data: { folioLocationId, configurationId }
+ });
+ }
- return persistentMutator.mappings.DELETE({ folioLocationId });
+ return deleteMapping({ folioLocationId });
};
const context = {
- ...resources,
remoteMap,
+ mappings,
+ isMappingsLoading,
+ isMappingsError,
+ configurations,
+ isConfigurationsLoading,
+ isConfigurationsError,
setMapping,
translate,
};
- return ;
-};
-
-Provider.manifest = Object.freeze({
- configurations: {
- type: 'okapi',
- path: 'remote-storage/configurations?limit=10000',
- accumulate: true,
- records: 'configurations',
- throwErrors: false,
- },
- mappings: {
- type: 'okapi',
- path: 'remote-storage/mappings',
- perRequest: 10000,
- records: 'mappings',
- pk: 'folioLocationId',
- clientGeneratePk: false, // because we use POST instead of PUT for modification here (there's no PUT)
- throwErrors: false,
- fetch: ({ stripes }) => stripes.hasInterface('remote-storage-mappings'),
- },
-});
-
-Provider.propTypes = {
- mutator: PropTypes.object.isRequired,
- stripes: PropTypes.object,
- resources: PropTypes.shape({
- mappings: PropTypes.shape({
- records: PropTypes.arrayOf(PropTypes.object)
- })
- })
+ return ;
};
-
-export const RemoteStorageApiProvider = stripesConnect(Provider);
diff --git a/src/settings/LocationLocations/RemoteStorageDetails.js b/src/settings/LocationLocations/RemoteStorageDetails.js
index 900d5191..dc074ca5 100644
--- a/src/settings/LocationLocations/RemoteStorageDetails.js
+++ b/src/settings/LocationLocations/RemoteStorageDetails.js
@@ -10,10 +10,11 @@ import {
import { useRemoteStorageApi } from './RemoteStorage';
+
const RemoteStorageDetails = ({ locationId }) => {
const { remoteMap, configurations } = useRemoteStorageApi();
- const currentConfig = configurations?.records.find(config => remoteMap[locationId] === config.id);
+ const currentConfig = configurations.find(config => remoteMap[locationId] === config.id);
return (
<>
diff --git a/src/settings/LocationLocations/locationDetail.test.js b/src/settings/LocationLocations/locationDetail.test.js
index d1385d08..671b1fa7 100644
--- a/src/settings/LocationLocations/locationDetail.test.js
+++ b/src/settings/LocationLocations/locationDetail.test.js
@@ -1,10 +1,14 @@
import React from 'react';
+import { QueryClient, QueryClientProvider } from 'react-query';
import { render, screen, within } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
import user from '@testing-library/user-event';
import LocationDetail from './LocationDetail';
+import '../../../test/jest/__mocks__';
+
+
const mockInitialValues = {
id: '1',
servicePointIds: [
@@ -15,21 +19,31 @@ const mockInitialValues = {
],
};
-const mockSetMapping = jest.fn();
-
-jest.mock(
- '@folio/stripes/core',
- () => ({
- stripesConnect: Component => props => ,
- IfPermission : ({ children }) => <>{children}>,
- useStripes: () => ({
- hasPerm: () => true
- }),
- TitleManager: jest.fn(({ children, ...rest }) => (
- {children}
- ))
+jest.mock('../../hooks/useCampusDetails', () => ({
+ useCampusDetails: jest.fn(() => ({
+ campus: {},
+ })),
+}));
+
+jest.mock('../../hooks/useLibraryDetails', () => ({
+ useLibraryDetails: jest.fn(() => ({
+ library: {},
+ })),
+}));
+
+jest.mock('../../hooks/useInstitutionDetails', () => ({
+ useInstitutionDetails: jest.fn(() => ({
+ institution: {},
+ })),
+}));
+
+jest.mock('./RemoteStorage', () => ({
+ useRemoteStorageApi: () => ({
+ remoteMap: {},
+ configurations: [],
+ setMapping: jest.fn(),
}),
-);
+}));
jest.mock(
'@folio/stripes-components/lib/Icon',
@@ -38,20 +52,8 @@ jest.mock(
},
);
-jest.mock(
- './RemoteStorage',
- () => ({
- useRemoteStorageApi: () => ({ setMapping: mockSetMapping }),
- }),
-);
-
const renderLocationDetail = ({
initialValues = mockInitialValues,
- resources = {
- institutions: {},
- campuses: {},
- libraries: {},
- },
servicePointsById = {
'1': 'Circ Desk 1'
},
@@ -64,16 +66,17 @@ const renderLocationDetail = ({
},
} = {}) => (render(
-
+
+
+
));
@@ -127,7 +130,6 @@ describe('LocationDetail', () => {
user.click(editButton);
expect(onEdit).toHaveBeenCalled();
- expect(mockSetMapping).toHaveBeenCalled();
});
it('should call onClone when duplicate button in action menu clicked', () => {
diff --git a/src/settings/LocationLocations/remoteStorageDetails.test.js b/src/settings/LocationLocations/remoteStorageDetails.test.js
index acf27445..682ef81d 100644
--- a/src/settings/LocationLocations/remoteStorageDetails.test.js
+++ b/src/settings/LocationLocations/remoteStorageDetails.test.js
@@ -1,26 +1,31 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
+import { QueryClient, QueryClientProvider } from 'react-query';
+
import { useRemoteStorageApi } from './RemoteStorage';
import RemoteStorageDetails from './RemoteStorageDetails';
-const mockConfigurations = {
- records: [
- { name: 'RS1', id: 1 },
- { name: 'RS2', id: 2, returningWorkflowDetails: 'Scanned to folio' }
- ]
-};
+
+const mockConfigurations = [
+ { name: 'RS1', id: 1 },
+ { name: 'RS2', id: 2, returningWorkflowDetails: 'Scanned to folio' }
+];
const mockRemoteMap = {
locationWithoutDetails: 1,
locationWithDetails: 2,
};
-jest.mock('./RemoteStorage');
+jest.mock('./RemoteStorage', () => ({
+ useRemoteStorageApi: jest.fn(),
+}));
const renderRemoteStorageDetails = ({
locationId
}) => (render(
-
+
+
+
));
describe('RemoteStorageDetails', () => {
@@ -47,7 +52,7 @@ describe('RemoteStorageDetails', () => {
expect(screen.getByText('RS2')).toBeVisible();
- useRemoteStorageApi.mockImplementation(() => ({ remoteMap: mockRemoteMap, configurations: undefined }));
+ useRemoteStorageApi.mockImplementation(() => ({ remoteMap: mockRemoteMap, configurations: [] }));
sut.rerender();
expect(screen.queryByText('RS2')).not.toBeInTheDocument();
diff --git a/src/settings/LocationLocations/utils.js b/src/settings/LocationLocations/utils.js
index e8ac5c9d..6c188ee5 100644
--- a/src/settings/LocationLocations/utils.js
+++ b/src/settings/LocationLocations/utils.js
@@ -57,18 +57,16 @@ export const validate = values => {
return errors;
};
-export const getUniquenessValidation = (field, mutator, id) => {
+export const getUniquenessValidation = (field, ky, id) => {
return (value, allValues, meta) => {
if (!value) return Promise.resolve();
if (id && !meta.dirty) return Promise.resolve();
- mutator.reset();
-
const query = `(${field}=="${value.replace(/"/gi, '\\"')}")`;
- return mutator.GET({ params: { query } })
- .then((locations) => {
+ return ky.get('locations', { searchParams: { query } }).json()
+ .then(({ locations }) => {
if (locations.length !== 0) return Promise.reject();
return undefined;
diff --git a/src/settings/Plugins/PluginForm.js b/src/settings/Plugins/PluginForm.js
index 7af6b959..8edfb919 100644
--- a/src/settings/Plugins/PluginForm.js
+++ b/src/settings/Plugins/PluginForm.js
@@ -17,32 +17,27 @@ import stripesFinalForm from '@folio/stripes/final-form';
import styles from './Plugins.css';
-class PluginForm extends React.Component {
- static propTypes = {
- handleSubmit: PropTypes.func.isRequired,
- pristine: PropTypes.bool,
- submitting: PropTypes.bool,
- label: PropTypes.node,
- pluginTypes: PropTypes.object,
- readOnly: PropTypes.bool,
- };
-
- constructor(props) {
- super(props);
- this.renderPlugins = this.renderPlugins.bind(this);
- }
- renderPlugin(field, plugin) {
- const intl = useIntl();
- const { pluginTypes, readOnly } = this.props;
+const PluginForm = ({
+ handleSubmit,
+ pristine,
+ submitting,
+ label,
+ pluginTypes,
+ readOnly,
+}) => {
+ const intl = useIntl();
+ const renderPlugin = (field, plugin) => {
const pluginType = pluginTypes[plugin.configName];
const options = [{ value: '@@', label: '(none)' }].concat(pluginType.map(p => ({
value: p.module,
- label: intl.formatMessage({ id: `ui-tenant-settings.settings.pluginNames.${p.pluginType}` }) + ` ${p.version}`,
+ label: intl.formatMessage({ id: `ui-tenant-settings.settings.pluginNames.${p.pluginType}` }) + ' ' + p.version,
})));
- const label = ;
+
+ const lbl = ;
+
return (
@@ -50,7 +45,7 @@ class PluginForm extends React.Component {
readOnly={readOnly}
id={plugin.configName}
data-testid={plugin.configName}
- label={label}
+ label={lbl}
name={`${field}.value`}
placeholder="---"
component={Select}
@@ -59,59 +54,54 @@ class PluginForm extends React.Component {
);
- }
-
- renderPlugins({ fields }) {
- const plugins = fields.map((field, index) => (
- this.renderPlugin(field, fields.value[index])
- ));
+ };
- return (
- {plugins}
- );
- }
+ const renderPlugins = ({ fields }) => {
+ const plugins = fields.map((field, index) => renderPlugin(field, fields.value[index]));
- render() {
- const {
- handleSubmit,
- pristine,
- submitting,
- label,
- readOnly,
- } = this.props;
+ return {plugins}
;
+ };
- const footer = !readOnly && (
-
-
-
- )}
- />
- );
+ const footer = !readOnly && (
+
+
+
+ )}
+ />
+ );
- return (
-
- );
- }
-}
+
+
+
+ );
+};
+
+PluginForm.propTypes = {
+ handleSubmit: PropTypes.func.isRequired,
+ pristine: PropTypes.bool,
+ submitting: PropTypes.bool,
+ label: PropTypes.node,
+ pluginTypes: PropTypes.object,
+ readOnly: PropTypes.bool,
+};
export default stripesFinalForm({
navigationCheck: true,
diff --git a/src/settings/Plugins/Plugins.js b/src/settings/Plugins/Plugins.js
index 62673216..f14061d4 100644
--- a/src/settings/Plugins/Plugins.js
+++ b/src/settings/Plugins/Plugins.js
@@ -1,131 +1,113 @@
-import React from 'react';
+import React, { useRef } from 'react';
import PropTypes from 'prop-types';
-import { FormattedMessage, injectIntl } from 'react-intl';
+import { FormattedMessage, useIntl } from 'react-intl';
import { map, omit } from 'lodash';
+import { useQueryClient } from 'react-query';
import { modules } from 'stripes-config'; // eslint-disable-line import/no-unresolved, import/no-extraneous-dependencies
import {
Callout,
Layout,
} from '@folio/stripes/components';
+import { TitleManager, useStripes } from '@folio/stripes/core';
-import { TitleManager } from '@folio/stripes/core';
import PluginForm from './PluginForm';
+import { useConfigurationsCreate } from '../../hooks/useConfigurationsCreate';
+import { useConfigurationsUpdate } from '../../hooks/useConfigurationsUpdate';
+import { CONFIGURATIONS, useConfigurations } from '../../hooks/useConfigurations';
-class Plugins extends React.Component {
- static manifest = Object.freeze({
- recordId: {},
- settings: {
- type: 'okapi',
- records: 'configs',
- path: 'configurations/entries?query=(module==PLUGINS) sortby configName&limit=1000',
- POST: {
- path: 'configurations/entries',
- },
- PUT: {
- path: 'configurations/entries/%{recordId}',
- },
+
+const Plugins = ({ label }) => {
+ const intl = useIntl();
+ const stripes = useStripes();
+ const queryClient = useQueryClient();
+ const callout = useRef(null);
+
+ const { configs } = useConfigurations({
+ searchParams: {
+ query: '(module==PLUGINS) sortby configName',
+ limit: '1000',
},
});
- static propTypes = {
- label: PropTypes.node.isRequired,
- stripes: PropTypes.shape({
- logger: PropTypes.shape({
- log: PropTypes.func.isRequired,
- }).isRequired,
- setSinglePlugin: PropTypes.func.isRequired,
- hasPerm: PropTypes.func.isRequired,
- }).isRequired,
- resources: PropTypes.shape({
- settings: PropTypes.shape({
- records: PropTypes.arrayOf(PropTypes.object),
- }),
- }).isRequired,
- mutator: PropTypes.shape({
- recordId: PropTypes.shape({
- replace: PropTypes.func,
- }),
- settings: PropTypes.shape({
- POST: PropTypes.func.isRequired,
- PUT: PropTypes.func.isRequired,
- }),
- }).isRequired,
- intl: PropTypes.object,
+ const sharedOptions = {
+ onSuccess: () => {
+ queryClient.invalidateQueries(CONFIGURATIONS);
+ },
};
- constructor(props) {
- super(props);
+ const { createConfiguration } = useConfigurationsCreate(sharedOptions);
+ const { updateConfiguration } = useConfigurationsUpdate(sharedOptions);
+ const pluginTypes = (() => {
const plugins = modules.plugin || [];
- this.pluginTypes = plugins.reduce((pt, plugin) => {
+ return plugins.reduce((pt, plugin) => {
const type = plugin.pluginType;
- // eslint-disable-next-line no-param-reassign
pt[type] = pt[type] || [];
pt[type].push(plugin);
return pt;
}, {});
+ })();
- this.save = this.save.bind(this);
- }
-
- getPlugins() {
- const settings = ((this.props.resources.settings || {}).records || []);
+ const getPlugins = (settings) => {
const pluginsByType = settings.reduce((memo, setting) => {
- // eslint-disable-next-line no-param-reassign
memo[setting.configName] = setting;
return memo;
}, {});
- return map(this.pluginTypes, (types, key) => {
+ return map(pluginTypes, (types, key) => {
const plugin = pluginsByType[key];
return plugin || { configName: key };
});
- }
+ };
- savePlugin(plugin) {
+ const savePlugin = (plugin) => {
const value = plugin.value;
if (plugin.id) {
- // Setting has been set previously: replace it
- this.props.mutator.recordId.replace(plugin.id);
- this.props.mutator.settings.PUT(omit(plugin, ['metadata']));
+ updateConfiguration({
+ id: plugin.id,
+ data: omit(plugin, ['metadata']),
+ });
} else {
- // No setting: create a new one
- this.props.mutator.settings.POST({
- module: 'PLUGINS',
- configName: plugin.configName,
- value,
+ createConfiguration({
+ data: {
+ module: 'PLUGINS',
+ configName: plugin.configName,
+ value,
+ },
});
}
- this.props.stripes.setSinglePlugin(plugin.configName, value);
- }
+ stripes.setSinglePlugin(plugin.configName, value);
+ };
- save(data) {
- data.plugins.forEach(p => this.savePlugin(p));
+ const save = (data) => {
+ data.plugins.forEach(p => savePlugin(p));
const updateMsg = ;
- this.callout.sendCallout({ message: updateMsg });
- }
-
- render() {
- const plugins = this.getPlugins();
- const isReadOnly = !this.props.stripes.hasPerm('ui-tenant-settings.settings.plugins');
-
- return (
-
-
-
-
- { this.callout = ref; }} />
-
- );
- }
-}
-
-export default injectIntl(Plugins);
+ callout.current.sendCallout({ message: updateMsg });
+ };
+
+ const plugins = getPlugins(configs);
+ const isReadOnly = !stripes.hasPerm('ui-tenant-settings.settings.plugins');
+
+ return (
+
+
+
+
+
+
+ );
+};
+
+Plugins.propTypes = {
+ label: PropTypes.node.isRequired,
+};
+
+export default Plugins;
diff --git a/src/settings/Plugins/Plugins.test.js b/src/settings/Plugins/Plugins.test.js
index a7f3ab2b..655cb227 100644
--- a/src/settings/Plugins/Plugins.test.js
+++ b/src/settings/Plugins/Plugins.test.js
@@ -1,72 +1,53 @@
import React from 'react';
-
+import { QueryClient, QueryClientProvider } from 'react-query';
import { screen } from '@testing-library/react';
import user from '@testing-library/user-event';
-import '../../../test/jest/__mocks__';
import { renderWithRouter } from '../../../test/jest/helpers';
-
import Plugins from './Plugins';
-const setSinglePlugin = jest.fn();
-const hasPermMock = jest.fn().mockReturnValue(true);
+import '../../../test/jest/__mocks__';
+import { mockHasPerm } from '../../../test/jest/__mocks__/stripesCore.mock';
-const renderPlugins = (props) => renderWithRouter();
+const mockCreateConfiguration = jest.fn(() => Promise.resolve());
+
+jest.mock('../../hooks/useConfigurationsCreate', () => ({
+ useConfigurationsCreate: jest.fn(() => ({
+ createConfiguration: mockCreateConfiguration,
+ isCreatingConfiguration: false,
+ })),
+}));
+
+const renderPlugins = (props) => renderWithRouter(
+
+
+
+);
describe('Plugins', () => {
afterEach(() => {
- setSinglePlugin.mockClear();
- hasPermMock.mockClear();
+ mockHasPerm.mockClear();
});
it('should render plugins', async () => {
- const { findAllByText } = await renderPlugins({ label: 'plugins',
- stripes: {
- setSinglePlugin,
- hasPerm: hasPermMock,
- logger: {
- log: jest.fn(),
- },
- },
- resources: {} });
+ const { findAllByText } = await renderPlugins({ label: 'plugins' });
+
expect(await findAllByText('plugins')).toBeDefined();
});
it('should choose and save plugin', async () => {
- renderPlugins({ label: 'plugins',
- stripes: {
- setSinglePlugin,
- hasPerm: hasPermMock,
- logger: {
- log: jest.fn(),
- },
- },
- resources: {},
- mutator: {
- settings: { POST: jest.fn() }
- } });
+ renderPlugins({ label: 'plugins' });
user.selectOptions(screen.getByTestId('find-instance'), ['@folio/plugin-find-instance']);
user.click(screen.getByRole('button', { type: /submit/i }));
- expect(setSinglePlugin).toHaveBeenCalledTimes(1);
+ expect(mockCreateConfiguration).toHaveBeenCalledTimes(1);
});
it('submit button should not be present without permissions', async () => {
- hasPermMock.mockReturnValueOnce(false);
+ mockHasPerm.mockReturnValueOnce(false);
- renderPlugins({ label: 'plugins',
- stripes: {
- setSinglePlugin,
- hasPerm: hasPermMock,
- logger: {
- log: jest.fn(),
- },
- },
- resources: {},
- mutator: {
- settings: { POST: jest.fn() }
- } });
+ renderPlugins({ label: 'plugins' });
expect(screen.queryByRole('button', { type: /submit/i })).toBeNull();
});
diff --git a/src/settings/ReadingRoomAccess/ReadingRoomAccess.js b/src/settings/ReadingRoomAccess/ReadingRoomAccess.js
index 8dc0e697..8ce07e89 100644
--- a/src/settings/ReadingRoomAccess/ReadingRoomAccess.js
+++ b/src/settings/ReadingRoomAccess/ReadingRoomAccess.js
@@ -5,8 +5,7 @@ import _ from 'lodash';
import {
TitleManager,
- withStripes,
- stripesShape
+ useStripes
} from '@folio/stripes/core';
import { Label } from '@folio/stripes/components';
import { ControlledVocab } from '@folio/stripes/smart-components';
@@ -16,6 +15,7 @@ import { getFormatter } from './getFormatter';
import { getFieldComponents } from './getFieldComponents';
import { getValidators } from './getValidators';
+
const hiddenFields = ['numberOfObjects', 'lastUpdated'];
const translations = {
cannotDeleteTermHeader: 'ui-tenant-settings.settings.reading-room-access.cannotDeleteTermHeader',
@@ -27,14 +27,15 @@ const translations = {
const ReadingRoomAccess = (props) => {
const intl = useIntl();
- const { resources, stripes } = props;
+ const stripes = useStripes();
+ const { resources } = props;
// service points defined in the tenant
const servicePoints = _.get(resources, ['RRAServicePoints', 'records', 0, 'servicepoints'], []);
/**
* A reading room can have more than one service points assigned to it.
* but a servicepoint cannot be mapped to more than one reading room
- */
+ */
const sps = [];
const rrs = _.get(resources, ['values', 'records']);
rrs.forEach(rr => {
@@ -78,7 +79,7 @@ const ReadingRoomAccess = (props) => {
const formatter = useMemo(() => getFormatter({ fieldLabels }), [fieldLabels]);
const validateItem = useCallback((item, items) => {
- const errors = Object.values(readingRoomAccessColumns).reduce((acc, field) => {
+ return Object.values(readingRoomAccessColumns).reduce((acc, field) => {
const error = getValidators(field)?.(item, items);
if (error) {
@@ -87,8 +88,6 @@ const ReadingRoomAccess = (props) => {
return acc;
}, {});
-
- return errors;
}, []);
const validate = (item, index, items) => validateItem(item, items) || {};
@@ -140,7 +139,6 @@ ReadingRoomAccess.manifest = Object.freeze({
ReadingRoomAccess.propTypes = {
resources: PropTypes.object,
mutator: PropTypes.object,
- stripes: stripesShape.isRequired,
};
-export default withStripes(ReadingRoomAccess);
+export default ReadingRoomAccess;
diff --git a/src/settings/ReadingRoomAccess/ReadingRoomAccess.test.js b/src/settings/ReadingRoomAccess/ReadingRoomAccess.test.js
index 8b000d8d..f05c8e47 100644
--- a/src/settings/ReadingRoomAccess/ReadingRoomAccess.test.js
+++ b/src/settings/ReadingRoomAccess/ReadingRoomAccess.test.js
@@ -4,14 +4,11 @@ import { Form } from 'react-final-form';
import { runAxeTest } from '@folio/stripes-testing';
-import '../../../test/jest/__mocks__';
-import buildStripes from '../../../test/jest/__new_mocks__/stripesCore.mock';
-
import { renderWithRouter } from '../../../test/jest/helpers';
-
import ReadingRoomAccess from './ReadingRoomAccess';
-const stripes = buildStripes();
+import '../../../test/jest/__mocks__';
+import { mockHasPerm } from '../../../test/jest/__mocks__/stripesCore.mock';
const mutatorPutMock = jest.fn(() => Promise.resolve());
const mutatorMock = {
@@ -28,7 +25,6 @@ const mutatorMock = {
replace: jest.fn()
},
};
-
const resourcesMock = {
values: {
dataKey: 'reading-room',
@@ -179,12 +175,11 @@ describe('Reading Room Access', () => {
const props = {
mutator: mutatorMock,
resources: resourcesMock,
- stripes,
};
describe('when all permissions are available', () => {
beforeEach(() => {
- stripes.hasPerm = jest.fn().mockReturnValue(true);
+ mockHasPerm.mockReturnValue(true);
renderReadingRoomAccess(props);
});
@@ -253,7 +248,7 @@ describe('Reading Room Access', () => {
describe('when permissions are not available', () => {
beforeEach(() => {
- stripes.hasPerm = jest.fn().mockReturnValue(false);
+ mockHasPerm.mockReturnValue(false);
renderReadingRoomAccess(props);
});
diff --git a/src/settings/SSOSettings/SSOSettings.js b/src/settings/SSOSettings/SSOSettings.js
index 4bf532a8..934652ad 100644
--- a/src/settings/SSOSettings/SSOSettings.js
+++ b/src/settings/SSOSettings/SSOSettings.js
@@ -1,103 +1,56 @@
-import _ from 'lodash';
-import React from 'react';
+import React, { useRef } from 'react';
import PropTypes from 'prop-types';
-import { FormattedMessage, injectIntl } from 'react-intl';
-import { stripesShape, TitleManager } from '@folio/stripes/core';
+import { FormattedMessage, useIntl } from 'react-intl';
+import { useQueryClient } from 'react-query';
+
+import { TitleManager, useOkapiKy, useStripes } from '@folio/stripes/core';
import {
Callout,
Layout,
} from '@folio/stripes/components';
import { patronIdentifierTypes, samlBindingTypes } from '../../constants';
-
import SamlForm from './SamlForm';
-
-class SSOSettings extends React.Component {
- static manifest = Object.freeze({
- recordId: {},
- samlconfig: {
- type: 'okapi',
- path: 'saml/configuration',
- PUT: {
- path: 'saml/configuration',
- },
- },
- downloadFile: {
- accumulate: true,
- type: 'okapi',
- path: 'saml/regenerate',
- },
- urlValidator: {
- type: 'okapi',
- accumulate: 'true',
- path: 'saml/validate',
- fetch: false,
- throwErrors: false,
- },
+import { SAML_CONFIGURATION, useSamlConfiguration } from '../../hooks/useSamlConfiguration';
+import { useSamlConfigurationUpdate } from '../../hooks/useSamlConfigurationUpdate';
+
+
+const SSOSettings = ({ label }) => {
+ const intl = useIntl();
+ const stripes = useStripes();
+ const queryClient = useQueryClient();
+ const ky = useOkapiKy();
+ const callout = useRef(null);
+ const downloadButton = useRef(null);
+ const isReadOnly = !stripes.hasPerm('ui-tenant-settings.settings.sso');
+
+ const { samlConfig } = useSamlConfiguration();
+ const { updateSamlConfiguration } = useSamlConfigurationUpdate({
+ onSuccess: () => {
+ callout.current.sendCallout({ message: });
+ queryClient.invalidateQueries(SAML_CONFIGURATION);
+ }
});
- static propTypes = {
- label: PropTypes.node.isRequired,
- stripes: stripesShape.isRequired,
- resources: PropTypes.shape({
- samlconfig: PropTypes.object,
- }).isRequired,
- mutator: PropTypes.shape({
- recordId: PropTypes.shape({
- replace: PropTypes.func,
- }),
- samlconfig: PropTypes.shape({
- PUT: PropTypes.func.isRequired,
- }),
- downloadFile: PropTypes.shape({
- GET: PropTypes.func.isRequired,
- reset: PropTypes.func.isRequired,
- }),
- urlValidator: PropTypes.shape({
- GET: PropTypes.func.isRequired,
- reset: PropTypes.func.isRequired,
- }),
- }).isRequired,
- intl: PropTypes.object
- };
-
- constructor(props) {
- super(props);
-
- this.validateIdpUrl = this.validateIdpUrl.bind(this);
- this.updateSettings = this.updateSettings.bind(this);
- }
-
- getConfig() {
- const { resources } = this.props;
- const config = (resources.samlconfig || {}).records || [];
- const configValue = (config.length === 0) ? {} : config[0];
- const configData = configValue ? _.cloneDeep(configValue) : configValue;
- return configData;
- }
-
- updateSettings(settings) {
- const updateMsg = ;
- settings.okapiUrl = this.props.stripes.okapi.url;
- this.props.mutator.samlconfig.PUT(settings).then(() => {
- this.callout.sendCallout({ message: updateMsg });
+ const updateSettings = (settings) => {
+ updateSamlConfiguration({
+ data: {
+ ...settings,
+ okapiUrl: stripes.okapi.url,
+ }
});
- }
-
- async validateIdpUrl(value) {
- const { mutator: { urlValidator } } = this.props;
+ };
+ const validateIdpUrl = async (value) => {
if (!value) {
return ;
}
const error = ;
- const params = { type: 'idpurl', value };
-
- urlValidator.reset();
+ const searchParams = { type: 'idpurl', value };
try {
- const result = await urlValidator.GET({ params });
+ const result = await ky.get('saml/validate', { searchParams }).json();
if (!result?.valid) {
return error;
@@ -107,36 +60,34 @@ class SSOSettings extends React.Component {
}
return '';
- }
-
- render() {
- const samlFormData = this.getConfig();
- const isReadOnly = !this.props.stripes.hasPerm('ui-tenant-settings.settings.sso');
-
- return (
-
-
- { this.updateSettings(record); }}
- optionLists={{ identifierOptions: patronIdentifierTypes, samlBindingOptions: samlBindingTypes }}
- parentMutator={this.props.mutator}
- validateIdpUrl={this.validateIdpUrl}
- stripes={this.props.stripes}
- readOnly={isReadOnly}
- />
- { this.downloadButton = reference; return reference; }}
- >
-
-
- { this.callout = ref; }} />
-
-
- );
- }
-}
+ };
-export default injectIntl(SSOSettings);
+ return (
+
+
+ { updateSettings(record); }}
+ optionLists={{ identifierOptions: patronIdentifierTypes, samlBindingOptions: samlBindingTypes }}
+ validateIdpUrl={validateIdpUrl}
+ stripes={stripes}
+ readOnly={isReadOnly}
+ />
+
+
+
+
+
+
+ );
+};
+
+SSOSettings.propTypes = {
+ label: PropTypes.node.isRequired,
+};
+
+export default SSOSettings;
diff --git a/src/settings/SSOSettings/SSOSettings.test.js b/src/settings/SSOSettings/SSOSettings.test.js
index 78c9553c..b4b44a2b 100644
--- a/src/settings/SSOSettings/SSOSettings.test.js
+++ b/src/settings/SSOSettings/SSOSettings.test.js
@@ -1,70 +1,27 @@
import React from 'react';
import { act, screen, fireEvent, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
+import { QueryClient, QueryClientProvider } from 'react-query';
+
import SSOSettings from './SSOSettings';
-import buildStripes from '../../../test/jest/__new_mocks__/stripesCore.mock';
import { renderWithRouter } from '../../../test/jest/helpers';
-
-const hasPermMock = jest.fn().mockReturnValue(true);
-
-const STRIPES = {
- ...buildStripes(),
- hasPerm: hasPermMock,
- config: {
- platform: 'tenant-settings'
- },
-};
-
-const resourcesMock = {
- values: {
- failed: false,
- hasLoaded: true,
- httpStatus: 200,
- isPending: false,
- module: '@folio/tenant-settings',
- },
-};
-
-const samlconfigCallback = jest.fn(() => Promise.resolve());
-const urlValidatorCallback = jest.fn(() => Promise.resolve({ valid: true }));
-
-const mutatorMock = {
- recordId: {
- replace: jest.fn(() => Promise.resolve()),
- },
- samlconfig: {
- PUT: samlconfigCallback,
- },
- downloadFile: {
- GET: jest.fn(() => Promise.resolve()),
- reset: jest.fn(() => Promise.resolve()),
- },
- urlValidator: {
- GET: urlValidatorCallback,
- reset: jest.fn(() => Promise.resolve()),
- }
-};
-
+import '../../../test/jest/__mocks__';
+import { mockHasPerm } from '../../../test/jest/__mocks__/stripesCore.mock';
const SSOSettingsLabel = 'SSOSettings label';
const renderSSOSettings = () => {
renderWithRouter(
- {SSOSettingsLabel}}
- stripes={STRIPES}
- resources={resourcesMock}
- mutator={mutatorMock}
- />
+
+ {SSOSettingsLabel}}
+ />
+
);
};
describe('SSOSettings', () => {
- afterEach(() => {
- hasPermMock.mockClear();
- });
-
it('should render SSOSettings label', () => {
renderSSOSettings();
@@ -152,7 +109,7 @@ describe('SSOSettings', () => {
});
it('should render SSOSettings form elements "read-only mode"', async () => {
- hasPermMock.mockReturnValue(false);
+ mockHasPerm.mockReturnValue(false);
renderSSOSettings();
diff --git a/src/settings/SSOSettings/SamlForm.js b/src/settings/SSOSettings/SamlForm.js
index 89c46004..ca0215a1 100644
--- a/src/settings/SSOSettings/SamlForm.js
+++ b/src/settings/SSOSettings/SamlForm.js
@@ -16,6 +16,8 @@ import stripesFinalForm from '@folio/stripes/final-form';
import { IfPermission } from '@folio/stripes/core';
import styles from './SSOSettings.css';
+import { useSamlDownload } from '../../hooks/useSamlDownload';
+
const validate = (values) => {
const errors = {};
@@ -32,169 +34,151 @@ const validate = (values) => {
return errors;
};
-class SamlForm extends React.Component {
- static propTypes = {
- validateIdpUrl: PropTypes.func.isRequired,
- handleSubmit: PropTypes.func.isRequired,
- reset: PropTypes.func,
- pristine: PropTypes.bool,
- submitting: PropTypes.bool,
- initialValues: PropTypes.object.isRequired, // eslint-disable-line react/no-unused-prop-types
- values: PropTypes.object,
- optionLists: PropTypes.shape({
- identifierOptions: PropTypes.arrayOf(PropTypes.object),
- samlBindingOptions: PropTypes.arrayOf(PropTypes.object),
- }),
- parentMutator: PropTypes.shape({ // eslint-disable-line react/no-unused-prop-types
- urlValidator: PropTypes.shape({
- reset: PropTypes.func.isRequired,
- GET: PropTypes.func.isRequired,
- }).isRequired,
- downloadFile: PropTypes.shape({
- GET: PropTypes.func.isRequired,
- reset: PropTypes.func.isRequired,
- }),
- }),
- label: PropTypes.node,
- readOnly: PropTypes.bool,
- };
-
- updateMetadataInvalidated = () => {
- this.props.initialValues.metadataInvalidated = false;
- this.forceUpdate();
- }
- downloadMetadata = () => {
- this.props.parentMutator.downloadFile.reset();
- this.props.parentMutator.downloadFile.GET().then((result) => {
+const SamlForm = ({
+ validateIdpUrl,
+ handleSubmit,
+ pristine,
+ submitting,
+ initialValues,
+ optionLists,
+ label,
+ values,
+ readOnly,
+}) => {
+ const { downloadFile } = useSamlDownload({
+ onSuccess: (result) => {
const anchor = document.createElement('a');
- anchor.href = `data:text/plain;base64,${result.fileContent}`;
+ anchor.href = `data:text/plain;base64,${result?.fileContent}`;
anchor.download = 'sp-metadata.xml';
anchor.click();
- this.updateMetadataInvalidated();
- });
- }
- render() {
- const {
- handleSubmit,
- pristine,
- submitting,
- initialValues,
- optionLists,
- label,
- validateIdpUrl,
- values,
- readOnly,
- } = this.props;
+ initialValues.metadataInvalidated = false;
+ },
+ });
- const identifierOptions = (optionLists.identifierOptions || []).map(i => (
- { id: i.key, label: i.label, value: i.key, selected: initialValues.userProperty === i.key }
- ));
- const samlBindingOptions = optionLists.samlBindingOptions.map(i => (
- { id: i.key, label: i.label, value: i.key, selected: initialValues.samlBinding === i.key }
- ));
+ const identifierOptions = (optionLists.identifierOptions || []).map(i => (
+ { id: i.key, label: i.label, value: i.key, selected: initialValues.userProperty === i.key }
+ ));
- const footer = !readOnly && (
-
-
-
- )}
- />
- );
+ const samlBindingOptions = optionLists.samlBindingOptions.map(i => (
+ { id: i.key, label: i.label, value: i.key, selected: initialValues.samlBinding === i.key }
+ ));
- return (
-
- );
- }
-}
+
+
+ )}
+ />
+ );
+
+ return (
+
+ );
+};
+
+SamlForm.propTypes = {
+ validateIdpUrl: PropTypes.func.isRequired,
+ handleSubmit: PropTypes.func.isRequired,
+ pristine: PropTypes.bool,
+ submitting: PropTypes.bool,
+ initialValues: PropTypes.object.isRequired, // eslint-disable-line react/no-unused-prop-types
+ values: PropTypes.object,
+ optionLists: PropTypes.shape({
+ identifierOptions: PropTypes.arrayOf(PropTypes.object),
+ samlBindingOptions: PropTypes.arrayOf(PropTypes.object),
+ }),
+ label: PropTypes.node,
+ readOnly: PropTypes.bool,
+};
export default stripesFinalForm({
validate,
diff --git a/src/settings/ServicePoints/LocationList.js b/src/settings/ServicePoints/LocationList.js
index effdb065..f1ba799e 100644
--- a/src/settings/ServicePoints/LocationList.js
+++ b/src/settings/ServicePoints/LocationList.js
@@ -8,7 +8,7 @@ import {
const LocationList = ({ locations, expanded, servicePoint, onToggle }) => {
const intl = useIntl();
- const renderLocation = (location) => {
+ const renderLocation = (location, index) => {
if (!location) return ();
const { name, code, primaryServicePoint } = location;
@@ -16,14 +16,14 @@ const LocationList = ({ locations, expanded, servicePoint, onToggle }) => {
? intl.formatMessage({ id: 'ui-tenant-settings.settings.servicePoints.primary' }) :
'';
const title = `${name} - ${code} ${primary}`;
- return ({title});
+ return ({title});
};
const renderLocations = () => {
return (
renderLocation(location)}
+ itemFormatter={renderLocation}
isEmptyMessage={}
/>
);
diff --git a/src/settings/ServicePoints/StaffSlipEditList.js b/src/settings/ServicePoints/StaffSlipEditList.js
index 03890df5..6d9e7512 100644
--- a/src/settings/ServicePoints/StaffSlipEditList.js
+++ b/src/settings/ServicePoints/StaffSlipEditList.js
@@ -6,13 +6,9 @@ import { FieldArray } from 'react-final-form-arrays';
import { Col, Row, Checkbox } from '@folio/stripes/components';
-class StaffSlipEditList extends React.Component {
- static propTypes = {
- staffSlips: PropTypes.arrayOf(PropTypes.object),
- };
- renderList = () => {
- const { staffSlips } = this.props;
+const StaffSlipEditList = ({ staffSlips }) => {
+ const renderList = () => {
const items = staffSlips.map((staffSlip, index) => (
@@ -30,24 +26,24 @@ class StaffSlipEditList extends React.Component {
return (
<>
-
+
{items}
>
);
- }
+ };
- render() {
- return (
-
- );
- }
-}
+ return (
+
+ );
+};
+
+StaffSlipEditList.propTypes = {
+ staffSlips: PropTypes.arrayOf(PropTypes.object),
+};
export default StaffSlipEditList;
diff --git a/src/settings/ServicePoints/StaffSlipList.js b/src/settings/ServicePoints/StaffSlipList.js
index 20bcb51a..ef70a0cc 100644
--- a/src/settings/ServicePoints/StaffSlipList.js
+++ b/src/settings/ServicePoints/StaffSlipList.js
@@ -2,15 +2,12 @@ import { keyBy, isUndefined } from 'lodash';
import React from 'react';
import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl';
+
import { List, KeyValue } from '@folio/stripes/components';
-class StaffSlipList extends React.Component {
- static propTypes = {
- staffSlips: PropTypes.arrayOf(PropTypes.object),
- servicePoint: PropTypes.object,
- };
- renderItem = (staffSlip, slipMap) => {
+const StaffSlipList = ({ staffSlips, servicePoint }) => {
+ const renderItem = (staffSlip, slipMap) => {
const { id, name } = staffSlip;
const { printByDefault } = (slipMap[id] || {});
const yesNo = (printByDefault || isUndefined(printByDefault)) ? 'yes' : 'no';
@@ -23,27 +20,29 @@ class StaffSlipList extends React.Component {
/>
);
- }
+ };
- render() {
- const { staffSlips, servicePoint } = this.props;
- const slipMap = keyBy(servicePoint.staffSlips, 'id');
+ const slipMap = keyBy(servicePoint.staffSlips, 'id');
- if (!staffSlips.length) return null;
+ if (!staffSlips.length) return null;
- return (
- }
- >
-
- this.renderItem(staffSlip, slipMap)}
- />
-
-
- );
- }
-}
+ return (
+ }
+ >
+
+ renderItem(staffSlip, slipMap)}
+ />
+
+
+ );
+};
+
+StaffSlipList.propTypes = {
+ staffSlips: PropTypes.arrayOf(PropTypes.object),
+ servicePoint: PropTypes.object,
+};
export default StaffSlipList;
diff --git a/src/settings/ServicePoints/constants.js b/src/settings/ServicePoints/constants.js
index d0b1b2a5..f69fd268 100644
--- a/src/settings/ServicePoints/constants.js
+++ b/src/settings/ServicePoints/constants.js
@@ -1,5 +1,4 @@
export const shortTermExpiryPeriod = ['Hours', 'Minutes'];
-export const longTermExpiryPeriod = ['Months', 'Weeks', 'Days'];
export const closedLibraryDateManagementMapping = {
Keep_the_current_due_date_time: 'keepTheOriginalDateTime',
diff --git a/src/settings/index.js b/src/settings/index.js
index 323ed55f..53107ec4 100644
--- a/src/settings/index.js
+++ b/src/settings/index.js
@@ -1,9 +1,9 @@
import React from 'react';
-import { FormattedMessage, injectIntl } from 'react-intl';
+import { FormattedMessage, useIntl } from 'react-intl';
+
import { Settings } from '@folio/stripes/smart-components';
-import { stripesShape, TitleManager } from '@folio/stripes/core';
+import { TitleManager, useStripes } from '@folio/stripes/core';
-import PropTypes from 'prop-types';
import Addresses from './Addresses';
import Locale from './Locale';
import Plugins from './Plugins';
@@ -15,130 +15,108 @@ import LocationLibraries from './LocationLibraries';
import LocationLocations from './LocationLocations';
import ServicePoints from './ServicePoints';
-class Organization extends React.Component {
- static propTypes = {
- stripes: stripesShape.isRequired,
- intl: PropTypes.object,
- }
-
- constructor(props) {
- super(props);
- this.sections = [
- {
- label:
- (
-
-
-
- ),
- pages: [
- {
- route: 'addresses',
- label: ,
- component: Addresses,
- perm: 'ui-tenant-settings.settings.addresses.view',
- },
- {
- route: 'locale',
- label: ,
- component: Locale,
- perm: 'ui-tenant-settings.settings.locale.view',
- },
- {
- route: 'plugins',
- label: ,
- component: Plugins,
- perm: 'ui-tenant-settings.settings.plugins.view',
- },
- {
- route: 'reading-room',
- label: ,
- component: ReadingRoomAccess,
- perm: 'ui-tenant-settings.settings.reading-room-access.view',
- iface: 'reading-room'
- },
- {
- route: 'ssosettings',
- label: ,
- component: SSOSettings,
- perm: 'ui-tenant-settings.settings.sso.view',
- iface: 'login-saml'
- },
- {
- route: 'servicePoints',
- label: ,
- component: ServicePoints,
- perm: 'ui-tenant-settings.settings.servicepoints.view',
- iface: 'service-points',
- },
- ],
- },
- {
- label: ,
- pages: [
- {
- route: 'location-institutions',
- label: ,
- component: LocationInstitutions,
- perm: 'ui-tenant-settings.settings.location.view',
- iface: 'location-units',
- },
- {
- route: 'location-campuses',
- label: ,
- component: LocationCampuses,
- perm: 'ui-tenant-settings.settings.location.view',
- iface: 'location-units',
- },
- {
- route: 'location-libraries',
- label: ,
- component: LocationLibraries,
- perm: 'ui-tenant-settings.settings.location.view',
- iface: 'location-units',
- },
- {
- route: 'location-locations',
- label: ,
- component: LocationLocations,
- perm: 'ui-tenant-settings.settings.location.view',
- iface: 'location-units',
- },
- ],
- }
- ];
- }
- /*
-
-
- {navLinks}
-
-
-
-
-
-
+const Organization = (props) => {
+ const intl = useIntl();
+ const stripes = useStripes();
- */
+ const sections = [
+ {
+ label: (
+
+
+
+ ),
+ pages: [
+ {
+ route: 'addresses',
+ label: ,
+ component: Addresses,
+ perm: 'ui-tenant-settings.settings.addresses.view',
+ },
+ {
+ route: 'locale',
+ label: ,
+ component: Locale,
+ perm: 'ui-tenant-settings.settings.locale.view',
+ },
+ {
+ route: 'plugins',
+ label: ,
+ component: Plugins,
+ perm: 'ui-tenant-settings.settings.plugins.view',
+ },
+ {
+ route: 'reading-room',
+ label: ,
+ component: ReadingRoomAccess,
+ perm: 'ui-tenant-settings.settings.reading-room-access.view',
+ iface: 'reading-room'
+ },
+ {
+ route: 'ssosettings',
+ label: ,
+ component: SSOSettings,
+ perm: 'ui-tenant-settings.settings.sso.view',
+ iface: 'login-saml'
+ },
+ {
+ route: 'servicePoints',
+ label: ,
+ component: ServicePoints,
+ perm: 'ui-tenant-settings.settings.servicepoints.view',
+ iface: 'service-points',
+ },
+ ],
+ },
+ {
+ label: ,
+ pages: [
+ {
+ route: 'location-institutions',
+ label: ,
+ component: LocationInstitutions,
+ perm: 'ui-tenant-settings.settings.location.view',
+ iface: 'location-units',
+ },
+ {
+ route: 'location-campuses',
+ label: ,
+ component: LocationCampuses,
+ perm: 'ui-tenant-settings.settings.location.view',
+ iface: 'location-units',
+ },
+ {
+ route: 'location-libraries',
+ label: ,
+ component: LocationLibraries,
+ perm: 'ui-tenant-settings.settings.location.view',
+ iface: 'location-units',
+ },
+ {
+ route: 'location-locations',
+ label: ,
+ component: LocationLocations,
+ perm: 'ui-tenant-settings.settings.location.view',
+ iface: 'location-units',
+ },
+ ],
+ }
+ ];
- render() {
- // If this PR is accepted, we will not need to do this filtering by hand:
- // https://github.com/folio-org/stripes-smart-components/pull/1401#issuecomment-1771334495
- // But for now ...
- const sections = this.sections.map(section => ({
- label: section.label,
- pages: section.pages.filter(page => !page.iface || this.props.stripes.hasInterface(page.iface)),
- }));
+ const filteredSections = sections.map(section => ({
+ label: section.label,
+ pages: section.pages.filter(page => !page.iface || stripes.hasInterface(page.iface)),
+ }));
- return (
- }
- />
- );
- }
-}
+ return (
+ }
+ />
+ );
+};
-export default injectIntl(Organization);
+export default Organization;
diff --git a/src/settings/index.test.js b/src/settings/index.test.js
index d77e36c7..546f1236 100644
--- a/src/settings/index.test.js
+++ b/src/settings/index.test.js
@@ -1,22 +1,12 @@
import React from 'react';
-import '../../test/jest/__mocks__';
-import {
- renderWithRouter
-} from '../../test/jest/helpers';
-import buildStripes from '../../test/jest/__new_mocks__/stripesCore.mock';
-
+import { renderWithRouter } from '../../test/jest/helpers';
import Organization from './index';
-const stripes = buildStripes();
-
-const intl = {
- formatMessage: jest.fn()
-};
+import '../../test/jest/__mocks__';
+import { mockHasInterface, mockHasPerm } from '../../test/jest/__mocks__/stripesCore.mock';
const props = {
- stripes,
- intl,
history: {},
location: {
pathname: '/tenant-settings'
@@ -30,43 +20,34 @@ const props = {
};
describe('Organization', () => {
- beforeEach(() => {
- stripes.discovery = {
- interfaces: {}
- };
- stripes.setIsAuthenticated = jest.fn();
- stripes.hasInterface = jest.fn().mockReturnValue(false);
- stripes.hasPerm = jest.fn().mockReturnValue(false);
- });
-
it('should render SSO Settings when login-saml interface is present', () => {
- stripes.hasInterface = jest.fn().mockReturnValue(true);
- stripes.hasPerm = jest.fn().mockReturnValue(true);
const { queryByText } = renderWithRouter();
expect(queryByText('ui-tenant-settings.settings.ssoSettings.label')).toBeTruthy();
});
it('should not render SSO Settings when login-saml interface is not present', () => {
- const { queryByText } = renderWithRouter();
- expect(queryByText('ui-tenant-settings.settings.ssoSettings.label')).toBeNull();
- });
+ mockHasInterface.mockReturnValue(false);
+ mockHasPerm.mockReturnValue(false);
- it('should render Reading room access when associated permission and interface are present', () => {
- stripes.hasInterface = jest.fn().mockReturnValue(true);
- stripes.hasPerm = jest.fn().mockReturnValue(true);
const { queryByText } = renderWithRouter();
- expect(queryByText('ui-tenant-settings.settings.reading-room-access.label')).toBeTruthy();
+ expect(queryByText('ui-tenant-settings.settings.ssoSettings.label')).toBeNull();
});
it('should not render Reading room access when ui-tenant-settings.settings.reading-room-access.view permission is not present', () => {
- stripes.hasInterface = jest.fn().mockReturnValue(true);
const { queryByText } = renderWithRouter();
expect(queryByText('ui-tenant-settings.settings.reading-room-access.label')).toBeNull();
});
it('should not render Reading room access when reading-room interface is not present', () => {
- stripes.hasPerm = jest.fn().mockReturnValue(true);
const { queryByText } = renderWithRouter();
expect(queryByText('ui-tenant-settings.settings.reading-room-access.label')).toBeNull();
});
+
+ it('should render Reading room access when associated permission and interface are present', () => {
+ mockHasInterface.mockReturnValue(true);
+ mockHasPerm.mockReturnValue(true);
+
+ const { queryByText } = renderWithRouter();
+ expect(queryByText('ui-tenant-settings.settings.reading-room-access.label')).toBeTruthy();
+ });
});
diff --git a/test/jest/__mocks__/stripesCore.mock.js b/test/jest/__mocks__/stripesCore.mock.js
index 096eb1ce..8dd4b970 100644
--- a/test/jest/__mocks__/stripesCore.mock.js
+++ b/test/jest/__mocks__/stripesCore.mock.js
@@ -1,47 +1,57 @@
-import React from 'react';
-
-jest.mock('@folio/stripes/core', () => {
- const STRIPES = {
- actionNames: [],
- clone: () => ({ ...STRIPES }),
- connect: (Component) => Component,
- config: {},
- currency: 'USD',
- hasInterface: () => true,
- hasPerm: jest.fn().mockReturnValue(true),
- locale: 'en-US',
- logger: {
- log: () => { },
- },
- okapi: {
- tenant: 'diku',
- url: 'https://folio-testing-okapi.dev.folio.org',
- },
- plugins: {},
- setBindings: () => { },
- setCurrency: () => { },
- setLocale: () => { },
- setSinglePlugin: () => { },
- setTimezone: () => { },
- setToken: () => { },
- store: {
- getState: () => { },
- dispatch: () => { },
- subscribe: () => { },
- replaceReducer: () => { },
- },
- timezone: 'UTC',
+export const mockHasPerm = jest.fn(() => true);
+export const mockHasInterface = jest.fn().mockReturnValue(true);
+export const mockUseOkapiKy = jest.fn();
+
+export const buildStripes = (otherProperties = {}) => ({
+ actionNames: [],
+ clone: buildStripes,
+ connect: Comp => Comp,
+ config: {
+ platformName: 'bulk-edit'
+ },
+ currency: 'USD',
+ hasInterface: jest.fn().mockReturnValue(true),
+ hasPerm: mockHasPerm,
+ locale: 'en-US',
+ logger: {
+ log: () => { },
+ },
+ okapi: {
+ tenant: 'diku',
+ url: 'https://folio-testing-okapi.dev.folio.org',
+ },
+ plugins: {},
+ setBindings: () => { },
+ setCurrency: () => { },
+ setLocale: () => { },
+ setSinglePlugin: () => { },
+ setTimezone: () => { },
+ setToken: () => { },
+ store: {
+ getState: () => { },
+ dispatch: () => { },
+ subscribe: () => { },
+ replaceReducer: () => { },
+ },
+ timezone: 'UTC',
+ user: {
+ perms: {},
user: {
- perms: {},
- user: {
- id: 'b1add99d-530b-5912-94f3-4091b4d87e2c',
- username: 'diku_admin',
+ id: 'b1add99d-530b-5912-94f3-4091b4d87e2c',
+ username: 'diku_admin',
+ consortium: {
+ centralTenantId: 'consortia',
},
},
- withOkapi: true,
- };
+ },
+ withOkapi: true,
+ ...otherProperties,
+});
- const stripesConnect = (Component, options) => ({ mutator, resources, stripes, ...rest }) => {
+const STRIPES = buildStripes();
+
+const mockStripesCore = {
+ stripesConnect: Component => ({ mutator, resources, stripes, ...rest }) => {
const fakeMutator = mutator || Object.keys(Component.manifest).reduce((acc, mutatorName) => {
const returnValue = Component.manifest[mutatorName].records ? [] : {};
@@ -51,59 +61,53 @@ jest.mock('@folio/stripes/core', () => {
POST: jest.fn().mockReturnValue(Promise.resolve()),
DELETE: jest.fn().mockReturnValue(Promise.resolve()),
reset: jest.fn(),
+ update: jest.fn(),
+ replace: jest.fn(),
};
return acc;
}, {});
const fakeResources = resources || Object.keys(Component.manifest).reduce((acc, resourceName) => {
- if (options?.resources?.[resourceName]) {
- acc[resourceName] = options.resources[resourceName];
- } else {
- acc[resourceName] = {
- records: [],
- };
- }
+ acc[resourceName] = {
+ records: [],
+ };
return acc;
}, {});
const fakeStripes = stripes || STRIPES;
- if (options?.stripes) {
- Object.assign(fakeStripes, options.stripes);
- }
-
return ;
- };
+ },
- const withStripes = (Component, options) => ({ stripes, ...rest }) => {
- const fakeStripes = stripes || STRIPES;
+ useOkapiKy: mockUseOkapiKy,
- fakeStripes.connect = Comp => stripesConnect(Comp, options);
+ useStripes: () => STRIPES,
- if (options?.stripes) {
- Object.assign(fakeStripes, options.stripes);
- }
+ withStripes: Component => ({ stripes, ...rest }) => {
+ const fakeStripes = stripes || STRIPES;
return ;
- };
-
- const useStripes = ({ ...STRIPES, connect: Component => stripesConnect(Component) });
- const TitleManager = jest.fn(({ children, ...rest }) => (
- {children}
- ));
-
- return {
- ...jest.requireActual('@folio/stripes/core'),
- stripesConnect,
- useStripes,
- withStripes,
- // eslint-disable-next-line react/prop-types
- Pluggable: props => <>{props.children}>,
- IfPermission: ({ children }) => <>{children}>,
- TitleManager,
- supportedLocales: ['ar', 'en', 'fr-FR'],
- supportedNumberingSystems: ['latn', 'arab'],
- };
-}, { virtual: true });
+ },
+
+ // eslint-disable-next-line react/prop-types
+ Pluggable: props => <>
+
+ >,
+
+ // eslint-disable-next-line react/prop-types
+ IfPermission: jest.fn(props => <>{props.children}>),
+
+ // eslint-disable-next-line react/prop-types
+ IfInterface: jest.fn(props => <>{props.children}>),
+
+ useNamespace: ({ key }) => [`@folio/bulk-edit:${key}`],
+ TitleManager: ({ children }) => <>{children}>,
+ checkIfUserInMemberTenant: () => true,
+};
+
+jest.mock('@folio/stripes/core', () => ({
+ ...jest.requireActual('@folio/stripes/core'),
+ ...mockStripesCore
+}), { virtual: true });
diff --git a/translations/ui-tenant-settings/en.json b/translations/ui-tenant-settings/en.json
index 300476e6..3e456438 100644
--- a/translations/ui-tenant-settings/en.json
+++ b/translations/ui-tenant-settings/en.json
@@ -154,6 +154,7 @@
"settings.servicePoints.assignedLocations": "Assigned locations",
"settings.servicePoints.location": "Location",
"settings.servicePoints.selectLocation": "Select location name or code",
+ "settings.servicePoints.placeholder": "Select service point",
"settings.servicePoints.addLocation": "Add location",
"settings.servicePoints.noLocationsFound": "No locations found",
"settings.servicePoints.validation.required": "Please fill this in to continue",
From 7aee23e16374d83ec7d2896763c411dea76c3084 Mon Sep 17 00:00:00 2001
From: FOLIO Translations Bot
<38661258+folio-translations@users.noreply.github.com>
Date: Fri, 16 Aug 2024 18:18:55 -0400
Subject: [PATCH 11/11] Lokalise: updates
---
translations/ui-tenant-settings/ar.json | 3 +-
translations/ui-tenant-settings/ber.json | 3 +-
translations/ui-tenant-settings/ca.json | 3 +-
translations/ui-tenant-settings/cs_CZ.json | 5 +-
translations/ui-tenant-settings/da.json | 3 +-
translations/ui-tenant-settings/de.json | 3 +-
translations/ui-tenant-settings/en_GB.json | 3 +-
translations/ui-tenant-settings/en_SE.json | 3 +-
translations/ui-tenant-settings/en_US.json | 3 +-
translations/ui-tenant-settings/es.json | 3 +-
translations/ui-tenant-settings/es_419.json | 3 +-
translations/ui-tenant-settings/es_ES.json | 3 +-
translations/ui-tenant-settings/fr.json | 3 +-
translations/ui-tenant-settings/fr_FR.json | 3 +-
translations/ui-tenant-settings/he.json | 3 +-
translations/ui-tenant-settings/hi_IN.json | 3 +-
translations/ui-tenant-settings/hu.json | 3 +-
translations/ui-tenant-settings/it_IT.json | 3 +-
translations/ui-tenant-settings/ja.json | 65 +++++++++++----------
translations/ui-tenant-settings/ko.json | 3 +-
translations/ui-tenant-settings/nb.json | 3 +-
translations/ui-tenant-settings/nl.json | 3 +-
translations/ui-tenant-settings/nn.json | 3 +-
translations/ui-tenant-settings/pl.json | 3 +-
translations/ui-tenant-settings/pt_BR.json | 3 +-
translations/ui-tenant-settings/pt_PT.json | 3 +-
translations/ui-tenant-settings/ru.json | 3 +-
translations/ui-tenant-settings/sk.json | 3 +-
translations/ui-tenant-settings/sv.json | 3 +-
translations/ui-tenant-settings/ur.json | 3 +-
translations/ui-tenant-settings/zh_CN.json | 5 +-
translations/ui-tenant-settings/zh_TW.json | 3 +-
32 files changed, 97 insertions(+), 65 deletions(-)
diff --git a/translations/ui-tenant-settings/ar.json b/translations/ui-tenant-settings/ar.json
index 20a72f19..cb3b0069 100644
--- a/translations/ui-tenant-settings/ar.json
+++ b/translations/ui-tenant-settings/ar.json
@@ -210,5 +210,6 @@
"settings.reading-room-access.cannotDeleteTermMessage": "This reading room access cannot be deleted, as it is in use by one or more records.",
"settings.reading-room-access.deleteEntry": "Delete reading room access",
"settings.reading-room-access.termDeleted": "The reading room access {term} was successfully deleted",
- "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted"
+ "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted",
+ "settings.servicePoints.placeholder": "Select service point"
}
\ No newline at end of file
diff --git a/translations/ui-tenant-settings/ber.json b/translations/ui-tenant-settings/ber.json
index a98803e2..ab875854 100644
--- a/translations/ui-tenant-settings/ber.json
+++ b/translations/ui-tenant-settings/ber.json
@@ -210,5 +210,6 @@
"settings.reading-room-access.cannotDeleteTermMessage": "This reading room access cannot be deleted, as it is in use by one or more records.",
"settings.reading-room-access.deleteEntry": "Delete reading room access",
"settings.reading-room-access.termDeleted": "The reading room access {term} was successfully deleted",
- "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted"
+ "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted",
+ "settings.servicePoints.placeholder": "Select service point"
}
\ No newline at end of file
diff --git a/translations/ui-tenant-settings/ca.json b/translations/ui-tenant-settings/ca.json
index a98803e2..ab875854 100644
--- a/translations/ui-tenant-settings/ca.json
+++ b/translations/ui-tenant-settings/ca.json
@@ -210,5 +210,6 @@
"settings.reading-room-access.cannotDeleteTermMessage": "This reading room access cannot be deleted, as it is in use by one or more records.",
"settings.reading-room-access.deleteEntry": "Delete reading room access",
"settings.reading-room-access.termDeleted": "The reading room access {term} was successfully deleted",
- "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted"
+ "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted",
+ "settings.servicePoints.placeholder": "Select service point"
}
\ No newline at end of file
diff --git a/translations/ui-tenant-settings/cs_CZ.json b/translations/ui-tenant-settings/cs_CZ.json
index 22b553ef..794a9348 100644
--- a/translations/ui-tenant-settings/cs_CZ.json
+++ b/translations/ui-tenant-settings/cs_CZ.json
@@ -90,7 +90,7 @@
"settings.servicePoints.disallowDeleteServicePoint": "Pult služeb nelze smazat",
"settings.servicePoints.disallowDeleteServicePointMessage": "Tento pult služeb nelze smazat, protože je hlavním pultem služeb pro jedno nebo více lokací.",
"settings.servicePoints.ok": "Dobře",
- "settings.servicePoints.deleteServicePointWithLocsMessage": "{name} je přidružen k jednomu nebo více místům. Opravdu chcete odebrat {name}?",
+ "settings.servicePoints.deleteServicePointWithLocsMessage": "{name} je spojený s jedním nebo více lokací. Opravdu chcete odebrat {name}?",
"settings.servicePoints.primary": "hlavní",
"settings.servicePoints.printByDefault": "Výchozí nastavení pro tisk lístků",
"settings.servicePoints.printSlip.yes": "{name} - ano",
@@ -210,5 +210,6 @@
"settings.reading-room-access.cannotDeleteTermMessage": "Tento přístup do čítárny nelze smazat, protože jej využívá jeden nebo více záznamů.",
"settings.reading-room-access.deleteEntry": "Smazat přístup do čítárny",
"settings.reading-room-access.termDeleted": "Přístup do čítárny {term} byl úspěšně smazán",
- "settings.reading-room-access.termWillBeDeleted": "Čítárna {term} bude smazána"
+ "settings.reading-room-access.termWillBeDeleted": "Čítárna {term} bude smazána",
+ "settings.servicePoints.placeholder": "Výběr pultu služeb"
}
\ No newline at end of file
diff --git a/translations/ui-tenant-settings/da.json b/translations/ui-tenant-settings/da.json
index 3ada6978..29a8a0d7 100644
--- a/translations/ui-tenant-settings/da.json
+++ b/translations/ui-tenant-settings/da.json
@@ -210,5 +210,6 @@
"settings.reading-room-access.cannotDeleteTermMessage": "This reading room access cannot be deleted, as it is in use by one or more records.",
"settings.reading-room-access.deleteEntry": "Delete reading room access",
"settings.reading-room-access.termDeleted": "The reading room access {term} was successfully deleted",
- "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted"
+ "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted",
+ "settings.servicePoints.placeholder": "Select service point"
}
\ No newline at end of file
diff --git a/translations/ui-tenant-settings/de.json b/translations/ui-tenant-settings/de.json
index 884d515b..ca1027a4 100644
--- a/translations/ui-tenant-settings/de.json
+++ b/translations/ui-tenant-settings/de.json
@@ -210,5 +210,6 @@
"settings.reading-room-access.cannotDeleteTermMessage": "This reading room access cannot be deleted, as it is in use by one or more records.",
"settings.reading-room-access.deleteEntry": "Delete reading room access",
"settings.reading-room-access.termDeleted": "The reading room access {term} was successfully deleted",
- "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted"
+ "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted",
+ "settings.servicePoints.placeholder": "Select service point"
}
\ No newline at end of file
diff --git a/translations/ui-tenant-settings/en_GB.json b/translations/ui-tenant-settings/en_GB.json
index a98803e2..ab875854 100644
--- a/translations/ui-tenant-settings/en_GB.json
+++ b/translations/ui-tenant-settings/en_GB.json
@@ -210,5 +210,6 @@
"settings.reading-room-access.cannotDeleteTermMessage": "This reading room access cannot be deleted, as it is in use by one or more records.",
"settings.reading-room-access.deleteEntry": "Delete reading room access",
"settings.reading-room-access.termDeleted": "The reading room access {term} was successfully deleted",
- "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted"
+ "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted",
+ "settings.servicePoints.placeholder": "Select service point"
}
\ No newline at end of file
diff --git a/translations/ui-tenant-settings/en_SE.json b/translations/ui-tenant-settings/en_SE.json
index a98803e2..ab875854 100644
--- a/translations/ui-tenant-settings/en_SE.json
+++ b/translations/ui-tenant-settings/en_SE.json
@@ -210,5 +210,6 @@
"settings.reading-room-access.cannotDeleteTermMessage": "This reading room access cannot be deleted, as it is in use by one or more records.",
"settings.reading-room-access.deleteEntry": "Delete reading room access",
"settings.reading-room-access.termDeleted": "The reading room access {term} was successfully deleted",
- "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted"
+ "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted",
+ "settings.servicePoints.placeholder": "Select service point"
}
\ No newline at end of file
diff --git a/translations/ui-tenant-settings/en_US.json b/translations/ui-tenant-settings/en_US.json
index a98803e2..ab875854 100644
--- a/translations/ui-tenant-settings/en_US.json
+++ b/translations/ui-tenant-settings/en_US.json
@@ -210,5 +210,6 @@
"settings.reading-room-access.cannotDeleteTermMessage": "This reading room access cannot be deleted, as it is in use by one or more records.",
"settings.reading-room-access.deleteEntry": "Delete reading room access",
"settings.reading-room-access.termDeleted": "The reading room access {term} was successfully deleted",
- "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted"
+ "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted",
+ "settings.servicePoints.placeholder": "Select service point"
}
\ No newline at end of file
diff --git a/translations/ui-tenant-settings/es.json b/translations/ui-tenant-settings/es.json
index 64ed6ed3..62bbf6d1 100644
--- a/translations/ui-tenant-settings/es.json
+++ b/translations/ui-tenant-settings/es.json
@@ -210,5 +210,6 @@
"settings.reading-room-access.cannotDeleteTermMessage": "This reading room access cannot be deleted, as it is in use by one or more records.",
"settings.reading-room-access.deleteEntry": "Delete reading room access",
"settings.reading-room-access.termDeleted": "The reading room access {term} was successfully deleted",
- "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted"
+ "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted",
+ "settings.servicePoints.placeholder": "Select service point"
}
\ No newline at end of file
diff --git a/translations/ui-tenant-settings/es_419.json b/translations/ui-tenant-settings/es_419.json
index 3f2f14ef..584f8210 100644
--- a/translations/ui-tenant-settings/es_419.json
+++ b/translations/ui-tenant-settings/es_419.json
@@ -210,5 +210,6 @@
"settings.reading-room-access.cannotDeleteTermMessage": "This reading room access cannot be deleted, as it is in use by one or more records.",
"settings.reading-room-access.deleteEntry": "Delete reading room access",
"settings.reading-room-access.termDeleted": "The reading room access {term} was successfully deleted",
- "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted"
+ "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted",
+ "settings.servicePoints.placeholder": "Select service point"
}
\ No newline at end of file
diff --git a/translations/ui-tenant-settings/es_ES.json b/translations/ui-tenant-settings/es_ES.json
index 70c4bc44..8ba8601b 100644
--- a/translations/ui-tenant-settings/es_ES.json
+++ b/translations/ui-tenant-settings/es_ES.json
@@ -210,5 +210,6 @@
"settings.reading-room-access.cannotDeleteTermMessage": "This reading room access cannot be deleted, as it is in use by one or more records.",
"settings.reading-room-access.deleteEntry": "Delete reading room access",
"settings.reading-room-access.termDeleted": "The reading room access {term} was successfully deleted",
- "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted"
+ "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted",
+ "settings.servicePoints.placeholder": "Select service point"
}
\ No newline at end of file
diff --git a/translations/ui-tenant-settings/fr.json b/translations/ui-tenant-settings/fr.json
index a98803e2..ab875854 100644
--- a/translations/ui-tenant-settings/fr.json
+++ b/translations/ui-tenant-settings/fr.json
@@ -210,5 +210,6 @@
"settings.reading-room-access.cannotDeleteTermMessage": "This reading room access cannot be deleted, as it is in use by one or more records.",
"settings.reading-room-access.deleteEntry": "Delete reading room access",
"settings.reading-room-access.termDeleted": "The reading room access {term} was successfully deleted",
- "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted"
+ "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted",
+ "settings.servicePoints.placeholder": "Select service point"
}
\ No newline at end of file
diff --git a/translations/ui-tenant-settings/fr_FR.json b/translations/ui-tenant-settings/fr_FR.json
index 649c4b44..2518f572 100644
--- a/translations/ui-tenant-settings/fr_FR.json
+++ b/translations/ui-tenant-settings/fr_FR.json
@@ -210,5 +210,6 @@
"settings.reading-room-access.cannotDeleteTermMessage": "This reading room access cannot be deleted, as it is in use by one or more records.",
"settings.reading-room-access.deleteEntry": "Delete reading room access",
"settings.reading-room-access.termDeleted": "The reading room access {term} was successfully deleted",
- "settings.reading-room-access.termWillBeDeleted": "Le {type} {term} sera supprimé. "
+ "settings.reading-room-access.termWillBeDeleted": "Le {type} {term} sera supprimé. ",
+ "settings.servicePoints.placeholder": "Select service point"
}
\ No newline at end of file
diff --git a/translations/ui-tenant-settings/he.json b/translations/ui-tenant-settings/he.json
index a98803e2..ab875854 100644
--- a/translations/ui-tenant-settings/he.json
+++ b/translations/ui-tenant-settings/he.json
@@ -210,5 +210,6 @@
"settings.reading-room-access.cannotDeleteTermMessage": "This reading room access cannot be deleted, as it is in use by one or more records.",
"settings.reading-room-access.deleteEntry": "Delete reading room access",
"settings.reading-room-access.termDeleted": "The reading room access {term} was successfully deleted",
- "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted"
+ "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted",
+ "settings.servicePoints.placeholder": "Select service point"
}
\ No newline at end of file
diff --git a/translations/ui-tenant-settings/hi_IN.json b/translations/ui-tenant-settings/hi_IN.json
index a98803e2..ab875854 100644
--- a/translations/ui-tenant-settings/hi_IN.json
+++ b/translations/ui-tenant-settings/hi_IN.json
@@ -210,5 +210,6 @@
"settings.reading-room-access.cannotDeleteTermMessage": "This reading room access cannot be deleted, as it is in use by one or more records.",
"settings.reading-room-access.deleteEntry": "Delete reading room access",
"settings.reading-room-access.termDeleted": "The reading room access {term} was successfully deleted",
- "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted"
+ "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted",
+ "settings.servicePoints.placeholder": "Select service point"
}
\ No newline at end of file
diff --git a/translations/ui-tenant-settings/hu.json b/translations/ui-tenant-settings/hu.json
index 0c87829f..5d05667b 100644
--- a/translations/ui-tenant-settings/hu.json
+++ b/translations/ui-tenant-settings/hu.json
@@ -210,5 +210,6 @@
"settings.reading-room-access.cannotDeleteTermMessage": "This reading room access cannot be deleted, as it is in use by one or more records.",
"settings.reading-room-access.deleteEntry": "Delete reading room access",
"settings.reading-room-access.termDeleted": "The reading room access {term} was successfully deleted",
- "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted"
+ "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted",
+ "settings.servicePoints.placeholder": "Select service point"
}
\ No newline at end of file
diff --git a/translations/ui-tenant-settings/it_IT.json b/translations/ui-tenant-settings/it_IT.json
index dd98f42d..7c5fb6fb 100644
--- a/translations/ui-tenant-settings/it_IT.json
+++ b/translations/ui-tenant-settings/it_IT.json
@@ -210,5 +210,6 @@
"settings.reading-room-access.cannotDeleteTermMessage": "This reading room access cannot be deleted, as it is in use by one or more records.",
"settings.reading-room-access.deleteEntry": "Delete reading room access",
"settings.reading-room-access.termDeleted": "The reading room access {term} was successfully deleted",
- "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted"
+ "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted",
+ "settings.servicePoints.placeholder": "Select service point"
}
\ No newline at end of file
diff --git a/translations/ui-tenant-settings/ja.json b/translations/ui-tenant-settings/ja.json
index 51e7ba78..21d3efc8 100644
--- a/translations/ui-tenant-settings/ja.json
+++ b/translations/ui-tenant-settings/ja.json
@@ -9,7 +9,7 @@
"settings.keyBindings": "Edit key bindings as JSON.",
"settings.localization": "ロケール(言語表示、日付形式など)",
"settings.timeZonePicker": "タイムゾーン(日付時刻情報を表示する際に使用する時間帯)",
- "settings.updated": "Settings were successfully updated.",
+ "settings.updated": "設定が正常に更新されました",
"settings.saml.validate.fillIn": "続行するには入力してください",
"settings.saml.validate.binding": "Please select SAML binding type",
"settings.saml.validate.userProperty": "Please select a user property",
@@ -20,34 +20,34 @@
"settings.saml.binding": "SAML binding",
"settings.saml.attribute": "SAML attribute",
"settings.saml.userProperty": "User property",
- "settings.location.label": "場所の設定",
+ "settings.location.label": "所在設定",
"settings.location.code": "コード",
"settings.location.institutions": "機関",
"settings.location.institutions.institution": "機関",
- "settings.location.institutions.selectInstitution": "機関を選択",
+ "settings.location.institutions.selectInstitution": "機関の選択",
"settings.location.campuses": "キャンパス",
"settings.location.campuses.campus": "キャンパス",
- "settings.location.campuses.selectCampus": "キャンパスを選択",
+ "settings.location.campuses.selectCampus": "キャンパスの選択",
"settings.location.libraries": "図書館",
"settings.location.libraries.library": "図書館",
- "settings.location.libraries.selectLibrary": "図書館を選択",
- "settings.location.locations": "場所",
- "settings.location.locations.location": "場所",
+ "settings.location.libraries.selectLibrary": "図書館の選択",
+ "settings.location.locations": "所在",
+ "settings.location.locations.location": "所在",
"settings.location.locations.generalInformation": "一般情報",
- "settings.location.locations.name": "FOLIO名",
+ "settings.location.locations.name": "FOLIO名称",
"settings.location.locations.discoveryDisplayName": "ディスカバリー表示名",
"settings.location.locations.status": "ステータス",
"settings.location.locations.active": "有効",
- "settings.location.locations.inactive": "非アクティブ",
+ "settings.location.locations.inactive": "無効",
"settings.location.locations.description": "説明",
"settings.location.locations.locationDetails": "Location details",
- "settings.location.locations.createLocation": "場所の作成",
- "settings.location.locations.deleteLocation": "位置情報を削除しますか?",
+ "settings.location.locations.createLocation": "所在の作成",
+ "settings.location.locations.deleteLocation": "所在を削除しますか?",
"settings.location.locations.deleteLocationMessage": "{name}は 削除されます",
"settings.location.locations.untitledLocation": "Untitled location",
"settings.location.locations.addDetails": "新規",
- "settings.location.locations.validation.name.unique": "場所の名前は一意である必要があります",
- "settings.location.locations.validation.code.unique": "場所コードは一意である必要があります",
+ "settings.location.locations.validation.name.unique": "所在名称は一意である必要があります",
+ "settings.location.locations.validation.code.unique": "所在コードは一意である必要があります",
"settings.hiddenDownloadLink": "非表示のダウンロードリンク",
"settings.servicePoints.label": "サービスポイント",
"settings.servicePoints.name": "名称",
@@ -61,8 +61,8 @@
"settings.servicePoints.discoveryDisplayName": "ディスカバリー表示名",
"settings.servicePoints.description": "説明",
"settings.servicePoints.shelvingLagTime": "Shelving lag time (minutes)",
- "settings.servicePoints.pickupLocation": "Pickup location",
- "settings.servicePoints.feeFineOwner": "Fee fine owner",
+ "settings.servicePoints.pickupLocation": "受取所在",
+ "settings.servicePoints.feeFineOwner": "手数料/罰金 所有者",
"settings.servicePoints.deleteServicePoint": "サービスポイントを削除",
"settings.servicePoints.delete": "削除",
"settings.servicePoints.untitledServicePoint": "サービスポイント名称",
@@ -73,14 +73,14 @@
"settings.servicePoints.validation.code.unique": "コードは一意である必要があります",
"settings.location.campuses.missingSelection": "続行する機関を選択してください。",
"settings.location.libraries.missingSelection": "続行するには、機関とキャンパスを選択してください。",
- "settings.location.locations.new": "新しい場所",
+ "settings.location.locations.new": "新規所在",
"settings.location.locations.detailsName": "名称",
"settings.location.locations.detailsValue": "値",
"settings.servicePoints.stripes-core.button.cancel": "キャンセル",
- "settings.servicePoints.assignedLocations": "割り当てられた場所",
- "settings.servicePoints.location": "場所",
- "settings.servicePoints.selectLocation": "場所の名前またはコードを選択してください",
- "settings.servicePoints.addLocation": "場所の追加",
+ "settings.servicePoints.assignedLocations": "所在の割当",
+ "settings.servicePoints.location": "所在",
+ "settings.servicePoints.selectLocation": "所在名称またはコードを選択してください",
+ "settings.servicePoints.addLocation": "所在の追加",
"settings.servicePoints.noLocationsFound": "No locations found",
"meta.title": "テナント",
"settings.index.paneTitle": "テナント",
@@ -107,10 +107,10 @@
"settings.primaryCurrency": "主要通貨(通貨記号の表示用)",
"settings.servicePoints.pickupLocation.yes": "はい",
"settings.servicePoints.pickupLocation.no": "いいえ",
- "settings.save.error.network": "Record not saved",
+ "settings.save.error.network": "レコードは保存されませんでした",
"settings.locale.localeWarning": "このページの設定により、すべてのユーザーのロケール(言語表示、日付形式、数値形式を含む)が**恒久的に**変更されます。ここでのロケール変更が絶対に正しい場合以外、ここでロケールを変更しないでください。セッションのみのロケールを一時的に変更するには、代わりに「{label} 」ボタンをクリックします。",
"settings.locale.changeSessionLocale": "セッションロケールを変更する",
- "settings.pluginNames.create-inventory-records": "Create inventory records",
+ "settings.pluginNames.create-inventory-records": "インベントリレコードの作成",
"settings.pluginNames.find-user": "Find user",
"settings.pluginNames.find-instance": "Find instance",
"settings.pluginNames.find-import-profile": "Find import profile",
@@ -132,7 +132,7 @@
"permission.settings.locale": "設定(テナント):言語、ローカライズ、通貨の編集が可能",
"permission.settings.plugins": "設定(テナント):優先プラグインを管理できます",
"permission.settings.sso": "設定(テナント):SSO設定を管理できます",
- "permission.settings.location": "Settings (tenant): Can create, edit and remove locations",
+ "permission.settings.location": "設定(テナント): 所在の作成、編集、削除が可能",
"permission.settings.servicepoints": "設定(テナント):サービスポイントを作成、編集、削除できます",
"settings.location.remotes.remote": "Remote storage",
"settings.location.remotes.no": "No (default)",
@@ -164,17 +164,17 @@
"settings.location.campuses.deleteEntry": "キャンパスの削除",
"settings.location.campuses.termDeleted": "キャンパス {term} が正常に削除されました",
"settings.location.campuses.termWillBeDeleted": "キャンパス {term} は、削除されます。",
- "settings.location.libraries.cannotDeleteTermHeader": "ライブラリを削除できません",
- "settings.location.libraries.cannotDeleteTermMessage": "このライブラリは、1 つ以上のレコードで使用されているため、削除できません。",
- "settings.location.libraries.deleteEntry": "ライブラリの削除",
- "settings.location.libraries.termDeleted": "ライブラリ {term} が正常に削除されました",
+ "settings.location.libraries.cannotDeleteTermHeader": "図書館を削除できません",
+ "settings.location.libraries.cannotDeleteTermMessage": "この図書館は、1 つ以上のレコードで使用されているため、削除できません。",
+ "settings.location.libraries.deleteEntry": "図書館の削除",
+ "settings.location.libraries.termDeleted": "図書館 {term} が正常に削除されました",
"settings.location.libraries.termWillBeDeleted": "ライブラリ {term} は、削除されます。",
"settings.addresses.cannotDeleteTermHeader": "アドレスを削除できません",
"settings.addresses.cannotDeleteTermMessage": "このアドレスは、1 つ以上のレコードで使用されているため、削除できません。",
"settings.addresses.deleteEntry": "アドレスの削除",
"settings.addresses.termDeleted": "アドレス{term} は正常に削除されました",
"settings.addresses.termWillBeDeleted": "アドレス {term} は、削除されます。 ",
- "settings.confirmPickupLocationChangeModal.title": "ピックアップ場所の変更を確認する",
+ "settings.confirmPickupLocationChangeModal.title": "受取所在の変更を確認する",
"settings.confirmPickupLocationChangeModal.message": "Changing this Pickup location from \"Yes\" to \"No\" will remove it from existing Request policies and affect all Circulation rules using the policies.",
"settings.confirmPickupLocationChangeModal.button.confirm": "確認する",
"settings.confirmPickupLocationChangeModal.button.cancel": "戻る",
@@ -183,7 +183,7 @@
"permission.settings.locale.view": "設定(テナント):言語、ローカライズ、通貨を表示できます。",
"permission.settings.plugins.view": "設定(テナント):優先プラグインを表示できます",
"permission.settings.sso.view": "設定(テナント):SSO(シングルサインオン)設定を表示できます",
- "permission.settings.location.view": "設定(テナント):場所の表示",
+ "permission.settings.location.view": "設定(テナント):所在の表示",
"permission.settings.servicepoints.view": "設定(テナント):サービスポイントを表示できます",
"settings.title": "テナント設定",
"settings.address.title": "テナント設定 - アドレス",
@@ -194,10 +194,10 @@
"settings.location.institutions.title": "テナント設定 - 機関",
"settings.location.libraries.title": "テナント設定 - 図書館",
"settings.location.campuses.title": "テナント設定 - キャンパス",
- "settings.location.locations.title": "テナント設定 - 場所",
+ "settings.location.locations.title": "テナント設定 - 所在",
"settings.newService.title": "テナント設定 - 新しいサービス ポイント",
"settings.items.title": "テナント設定 - {item}",
- "settings.location.createNew.title": "テナント設定 - 新しい場所",
+ "settings.location.createNew.title": "テナント設定 - 新規所在",
"settings.items.edit.title": "テナント設定 - 編集: {item}",
"permission.settings.reading-room-access.view": "Settings (tenant): Can view reading room access",
"permission.settings.reading-room-access.all": "Settings (tenant): Can create, edit and remove reading room access",
@@ -210,5 +210,6 @@
"settings.reading-room-access.cannotDeleteTermMessage": "This reading room access cannot be deleted, as it is in use by one or more records.",
"settings.reading-room-access.deleteEntry": "Delete reading room access",
"settings.reading-room-access.termDeleted": "The reading room access {term} was successfully deleted",
- "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted"
+ "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted",
+ "settings.servicePoints.placeholder": "サービスポイントの選択"
}
\ No newline at end of file
diff --git a/translations/ui-tenant-settings/ko.json b/translations/ui-tenant-settings/ko.json
index 1735f883..e73e28c6 100644
--- a/translations/ui-tenant-settings/ko.json
+++ b/translations/ui-tenant-settings/ko.json
@@ -210,5 +210,6 @@
"settings.reading-room-access.cannotDeleteTermMessage": "This reading room access cannot be deleted, as it is in use by one or more records.",
"settings.reading-room-access.deleteEntry": "Delete reading room access",
"settings.reading-room-access.termDeleted": "The reading room access {term} was successfully deleted",
- "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted"
+ "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted",
+ "settings.servicePoints.placeholder": "Select service point"
}
\ No newline at end of file
diff --git a/translations/ui-tenant-settings/nb.json b/translations/ui-tenant-settings/nb.json
index a98803e2..ab875854 100644
--- a/translations/ui-tenant-settings/nb.json
+++ b/translations/ui-tenant-settings/nb.json
@@ -210,5 +210,6 @@
"settings.reading-room-access.cannotDeleteTermMessage": "This reading room access cannot be deleted, as it is in use by one or more records.",
"settings.reading-room-access.deleteEntry": "Delete reading room access",
"settings.reading-room-access.termDeleted": "The reading room access {term} was successfully deleted",
- "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted"
+ "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted",
+ "settings.servicePoints.placeholder": "Select service point"
}
\ No newline at end of file
diff --git a/translations/ui-tenant-settings/nl.json b/translations/ui-tenant-settings/nl.json
index a98803e2..ab875854 100644
--- a/translations/ui-tenant-settings/nl.json
+++ b/translations/ui-tenant-settings/nl.json
@@ -210,5 +210,6 @@
"settings.reading-room-access.cannotDeleteTermMessage": "This reading room access cannot be deleted, as it is in use by one or more records.",
"settings.reading-room-access.deleteEntry": "Delete reading room access",
"settings.reading-room-access.termDeleted": "The reading room access {term} was successfully deleted",
- "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted"
+ "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted",
+ "settings.servicePoints.placeholder": "Select service point"
}
\ No newline at end of file
diff --git a/translations/ui-tenant-settings/nn.json b/translations/ui-tenant-settings/nn.json
index a98803e2..ab875854 100644
--- a/translations/ui-tenant-settings/nn.json
+++ b/translations/ui-tenant-settings/nn.json
@@ -210,5 +210,6 @@
"settings.reading-room-access.cannotDeleteTermMessage": "This reading room access cannot be deleted, as it is in use by one or more records.",
"settings.reading-room-access.deleteEntry": "Delete reading room access",
"settings.reading-room-access.termDeleted": "The reading room access {term} was successfully deleted",
- "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted"
+ "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted",
+ "settings.servicePoints.placeholder": "Select service point"
}
\ No newline at end of file
diff --git a/translations/ui-tenant-settings/pl.json b/translations/ui-tenant-settings/pl.json
index 82791f24..b7175c45 100644
--- a/translations/ui-tenant-settings/pl.json
+++ b/translations/ui-tenant-settings/pl.json
@@ -210,5 +210,6 @@
"settings.reading-room-access.cannotDeleteTermMessage": "This reading room access cannot be deleted, as it is in use by one or more records.",
"settings.reading-room-access.deleteEntry": "Delete reading room access",
"settings.reading-room-access.termDeleted": "The reading room access {term} was successfully deleted",
- "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted"
+ "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted",
+ "settings.servicePoints.placeholder": "Select service point"
}
\ No newline at end of file
diff --git a/translations/ui-tenant-settings/pt_BR.json b/translations/ui-tenant-settings/pt_BR.json
index 35f14e7e..fc5aa277 100644
--- a/translations/ui-tenant-settings/pt_BR.json
+++ b/translations/ui-tenant-settings/pt_BR.json
@@ -210,5 +210,6 @@
"settings.reading-room-access.cannotDeleteTermMessage": "Este acesso à sala de leitura não pode ser excluído, pois está em uso por um ou mais registros.",
"settings.reading-room-access.deleteEntry": "Excluir o acesso à sala de leitura",
"settings.reading-room-access.termDeleted": "O acesso à sala de leitura {term} foi excluído com sucesso",
- "settings.reading-room-access.termWillBeDeleted": "A sala de leitura {term} será excluída"
+ "settings.reading-room-access.termWillBeDeleted": "A sala de leitura {term} será excluída",
+ "settings.servicePoints.placeholder": "Selecione o ponto de serviço"
}
\ No newline at end of file
diff --git a/translations/ui-tenant-settings/pt_PT.json b/translations/ui-tenant-settings/pt_PT.json
index b6723c63..5f6a15a0 100644
--- a/translations/ui-tenant-settings/pt_PT.json
+++ b/translations/ui-tenant-settings/pt_PT.json
@@ -210,5 +210,6 @@
"settings.reading-room-access.cannotDeleteTermMessage": "This reading room access cannot be deleted, as it is in use by one or more records.",
"settings.reading-room-access.deleteEntry": "Delete reading room access",
"settings.reading-room-access.termDeleted": "The reading room access {term} was successfully deleted",
- "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted"
+ "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted",
+ "settings.servicePoints.placeholder": "Select service point"
}
\ No newline at end of file
diff --git a/translations/ui-tenant-settings/ru.json b/translations/ui-tenant-settings/ru.json
index e75b8b60..700824d5 100644
--- a/translations/ui-tenant-settings/ru.json
+++ b/translations/ui-tenant-settings/ru.json
@@ -210,5 +210,6 @@
"settings.reading-room-access.cannotDeleteTermMessage": "This reading room access cannot be deleted, as it is in use by one or more records.",
"settings.reading-room-access.deleteEntry": "Delete reading room access",
"settings.reading-room-access.termDeleted": "The reading room access {term} was successfully deleted",
- "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted"
+ "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted",
+ "settings.servicePoints.placeholder": "Select service point"
}
\ No newline at end of file
diff --git a/translations/ui-tenant-settings/sk.json b/translations/ui-tenant-settings/sk.json
index a98803e2..ab875854 100644
--- a/translations/ui-tenant-settings/sk.json
+++ b/translations/ui-tenant-settings/sk.json
@@ -210,5 +210,6 @@
"settings.reading-room-access.cannotDeleteTermMessage": "This reading room access cannot be deleted, as it is in use by one or more records.",
"settings.reading-room-access.deleteEntry": "Delete reading room access",
"settings.reading-room-access.termDeleted": "The reading room access {term} was successfully deleted",
- "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted"
+ "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted",
+ "settings.servicePoints.placeholder": "Select service point"
}
\ No newline at end of file
diff --git a/translations/ui-tenant-settings/sv.json b/translations/ui-tenant-settings/sv.json
index a98803e2..ab875854 100644
--- a/translations/ui-tenant-settings/sv.json
+++ b/translations/ui-tenant-settings/sv.json
@@ -210,5 +210,6 @@
"settings.reading-room-access.cannotDeleteTermMessage": "This reading room access cannot be deleted, as it is in use by one or more records.",
"settings.reading-room-access.deleteEntry": "Delete reading room access",
"settings.reading-room-access.termDeleted": "The reading room access {term} was successfully deleted",
- "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted"
+ "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted",
+ "settings.servicePoints.placeholder": "Select service point"
}
\ No newline at end of file
diff --git a/translations/ui-tenant-settings/ur.json b/translations/ui-tenant-settings/ur.json
index a98803e2..ab875854 100644
--- a/translations/ui-tenant-settings/ur.json
+++ b/translations/ui-tenant-settings/ur.json
@@ -210,5 +210,6 @@
"settings.reading-room-access.cannotDeleteTermMessage": "This reading room access cannot be deleted, as it is in use by one or more records.",
"settings.reading-room-access.deleteEntry": "Delete reading room access",
"settings.reading-room-access.termDeleted": "The reading room access {term} was successfully deleted",
- "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted"
+ "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted",
+ "settings.servicePoints.placeholder": "Select service point"
}
\ No newline at end of file
diff --git a/translations/ui-tenant-settings/zh_CN.json b/translations/ui-tenant-settings/zh_CN.json
index 8e046b9e..7d9a7ae6 100644
--- a/translations/ui-tenant-settings/zh_CN.json
+++ b/translations/ui-tenant-settings/zh_CN.json
@@ -133,7 +133,7 @@
"permission.settings.plugins": "设置(租户):可以维护首选插件",
"permission.settings.sso": "设置(租户):可以维护SSO设置",
"permission.settings.location": "设置(租户):可以创建、编辑和移除馆藏地",
- "permission.settings.servicepoints": "设置(租户):可以创建、编辑和移除服务点",
+ "permission.settings.servicepoints": "设置(租户):可以创建和编辑服务点",
"settings.location.remotes.remote": "远程存储",
"settings.location.remotes.no": "否(默认)",
"settings.location.remotes.loading": "载入中...",
@@ -210,5 +210,6 @@
"settings.reading-room-access.cannotDeleteTermMessage": "无法删除此阅览室访问,因为它正在被一条或多条记录使用。",
"settings.reading-room-access.deleteEntry": "删除阅览室访问",
"settings.reading-room-access.termDeleted": "阅览室访问 {term} 已成功删除",
- "settings.reading-room-access.termWillBeDeleted": "阅览室 {term} 将被删除"
+ "settings.reading-room-access.termWillBeDeleted": "阅览室 {term} 将被删除",
+ "settings.servicePoints.placeholder": "Select service point"
}
\ No newline at end of file
diff --git a/translations/ui-tenant-settings/zh_TW.json b/translations/ui-tenant-settings/zh_TW.json
index ab50a299..f25e1188 100644
--- a/translations/ui-tenant-settings/zh_TW.json
+++ b/translations/ui-tenant-settings/zh_TW.json
@@ -210,5 +210,6 @@
"settings.reading-room-access.cannotDeleteTermMessage": "This reading room access cannot be deleted, as it is in use by one or more records.",
"settings.reading-room-access.deleteEntry": "Delete reading room access",
"settings.reading-room-access.termDeleted": "The reading room access {term} was successfully deleted",
- "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted"
+ "settings.reading-room-access.termWillBeDeleted": "The reading room {term} will be deleted",
+ "settings.servicePoints.placeholder": "Select service point"
}
\ No newline at end of file