From d67cf86be9df86dcd8706b66475aacbca4a27650 Mon Sep 17 00:00:00 2001 From: FOLIO Translations Bot <38661258+folio-translations@users.noreply.github.com> Date: Mon, 30 Oct 2023 17:10:56 -0400 Subject: [PATCH 01/14] Lokalise: updates --- translations/ui-organizations/cs_CZ.json | 4 +- translations/ui-organizations/es_ES.json | 16 +- translations/ui-organizations/ko.json | 8 +- translations/ui-organizations/sk.json | 422 +++++++++++++++++++++++ translations/ui-organizations/zh_CN.json | 2 +- 5 files changed, 437 insertions(+), 15 deletions(-) create mode 100644 translations/ui-organizations/sk.json diff --git a/translations/ui-organizations/cs_CZ.json b/translations/ui-organizations/cs_CZ.json index 4c738d8c..ccd29ae2 100644 --- a/translations/ui-organizations/cs_CZ.json +++ b/translations/ui-organizations/cs_CZ.json @@ -417,6 +417,6 @@ "settings.types.termWillBeDeleted": "Typ {term} bude smazán.", "save.success": "Organizace - \"{organizationName}\" byla úspěšně uložena", "permission.settings.view": "Nastavení (Organizace): Zobrazení nastavení", - "comingSoon": "Coming in a future release.", - "summary.isDonor": "Donor" + "comingSoon": "Přijde v budoucím vydání.", + "summary.isDonor": "Dárce" } \ No newline at end of file diff --git a/translations/ui-organizations/es_ES.json b/translations/ui-organizations/es_ES.json index 2ef0bc30..8339db80 100644 --- a/translations/ui-organizations/es_ES.json +++ b/translations/ui-organizations/es_ES.json @@ -341,7 +341,7 @@ "integration.ftp.ftpMode": "FTP mode", "integration.ftp.serverAddress": "Server address", "integration.ftp.ftpConnectionMode": "FTP connection mode", - "integration.ftp.ftpConnectionMode.Active": "Active", + "integration.ftp.ftpConnectionMode.Active": "Activo", "integration.ftp.ftpConnectionMode.Passive": "Passive", "integration.ftp.username": "Username", "integration.ftp.password": "Password", @@ -384,15 +384,15 @@ "view.duplicateAccounts": "An organization can not have duplicate account numbers. Before editing this organization in any way you will need to change or remove any duplicate account numbers", "save.error.accountNumberMustBeUnique": "Una organización no puede tener números de cuenta duplicados", "integration.edi.ediNamingConvention.info": "When defining your naming convention you can use text or one of the following tokens. Tokens will be replace by the corresponding information from the export job. Possible tokens are {tokens}", - "linkedAgreements.section": "Agreements", - "linkedAgreements.agreement.name": "Agreement Name", + "linkedAgreements.section": "Acuerdos", + "linkedAgreements.agreement.name": "Nombre del acuerdo", "linkedAgreements.agreement.startDate": "Period start", "linkedAgreements.agreement.endDate": "Period End", - "linkedAgreements.agreement.agreementStatus": "Agreement status", - "linkedAgreements.agreement.agreementStatus.active": "Active", + "linkedAgreements.agreement.agreementStatus": "Estado del Acuerdo", + "linkedAgreements.agreement.agreementStatus.active": "Activo", "linkedAgreements.agreement.agreementStatus.closed": "Cerrado", - "linkedAgreements.agreement.agreementStatus.draft": "Draft", - "linkedAgreements.agreement.agreementStatus.in_negotiation": "In negotiation", + "linkedAgreements.agreement.agreementStatus.draft": "Borrador", + "linkedAgreements.agreement.agreementStatus.in_negotiation": "En negociación", "linkedAgreements.agreement.agreementStatus.requested": "Solicitado", "filterConfig.types": "Types", "summary.type": "Type", @@ -418,5 +418,5 @@ "save.success": "The Organization - \"{organizationName}\" has been successfully saved", "permission.settings.view": "Settings (Organizations): View settings", "comingSoon": "Coming in a future release.", - "summary.isDonor": "Donor" + "summary.isDonor": "Donante" } \ No newline at end of file diff --git a/translations/ui-organizations/ko.json b/translations/ui-organizations/ko.json index ce9bc1e0..b5e322c3 100644 --- a/translations/ui-organizations/ko.json +++ b/translations/ui-organizations/ko.json @@ -415,8 +415,8 @@ "settings.types.deleteEntry": "유형 삭제", "settings.types.termDeleted": " {term} 유형이 성공적으로 삭제되었습니다 ", "settings.types.termWillBeDeleted": " {term} 유형이 삭제됩니다. ", - "save.success": "The Organization - \"{organizationName}\" has been successfully saved", - "permission.settings.view": "Settings (Organizations): View settings", - "comingSoon": "Coming in a future release.", - "summary.isDonor": "Donor" + "save.success": "공급사 - \"{organizationName}\"이(가) 성공적으로 저장되었습니다.", + "permission.settings.view": "설정 (공급사): 설정 보기", + "comingSoon": "향후 릴리스에서 제공될 예정입니다.", + "summary.isDonor": "기증자" } \ No newline at end of file diff --git a/translations/ui-organizations/sk.json b/translations/ui-organizations/sk.json new file mode 100644 index 00000000..c2e6879e --- /dev/null +++ b/translations/ui-organizations/sk.json @@ -0,0 +1,422 @@ +{ + "meta.title": "Organizations", + "search": "Search", + "resultCount": "{count, number} {count, plural, one {Record found} other {Records found}}", + "data.contactTypes.email": "Email", + "data.contactTypes.mail": "Mail (primary address)", + "data.contactTypes.textMessage": "Text message", + "data.contactTypes.addressLine1": "Address 1", + "data.contactTypes.addressLine2": "Address 2", + "data.contactTypes.stateProviceOrRegion": "State/Province/Region", + "data.contactTypes.zipOrPostalCode": "Zip/Postal code", + "data.contactTypes.addressType": "Address type", + "data.contactTypes.city": "City", + "data.contactTypes.country": "Country", + "data.contactTypes.editThisAddress": "Edit address", + "data.contactTypes.primaryAddress": "Primary address", + "data.contactTypes.alternateAddress": "Alternate address", + "data.contactTypes.address": "Address", + "data.contactTypes.categories": "Categories", + "data.contactTypes.remove": "Remove", + "data.contactTypes.noAddressInfo": "Please add address info", + "data.contactTypes.language": "Language", + "filterConfig.vendorStatus": "Organizations status", + "filterConfig.addressCategory": "Address category", + "filterConfig.contactPeopleCategory": "Contact people category", + "filterConfig.country": "Country", + "filterConfig.languages": "Languages", + "filterConfig.paymentMethod": "Payment method", + "filterConfig.statsAvailable": "Stats available", + "view.edit": "Edit", + "view.editVendorDialog": "Edit vendor dialog", + "view.details": "Details", + "edit.delete": "Delete", + "edit.requiredFields": "Required fields!", + "edit.password": "Password", + "edit.show": "Show", + "edit.hide": "Hide", + "summary": "Summary", + "contactInformation": "Contact information", + "contactPeople": "Contact people", + "agreements": "Agreements", + "vendorInformation": "Vendor information", + "ediInformation": "EDI information", + "interface": "Interface", + "accounts": "Accounts", + "main.name": "Name", + "main.code": "Code", + "main.description": "Description", + "main.vendorStatus": "Organizations status", + "summary.name": "Name", + "summary.code": "Code", + "summary.description": "Description", + "summary.accountingCode": "Accounting code", + "summary.defaultLanguage": "Default language", + "summary.alternativeNames": "Alternative names", + "summary.alias": "Alias", + "summary.remove": "Remove", + "summary.add": "Add alternative names", + "summary.pleaseAddAltNames": "Please add alternative names", + "contactInfo.phoneNumbers": "Phone numbers", + "contactInfo.phoneNumber": "Phone number", + "contactInfo.type": "Type", + "contactInfo.language": "Language", + "contactInfo.categories": "Categories", + "contactInfo.description": "Description", + "contactInfo.email": "Email", + "contactInfo.emailAddress": "Email address", + "contactInfo.url": "URL", + "contactInfo.urls": "URLs", + "contactInfo.remove": "Remove", + "contactInfo.addURL": "Add URL", + "contactInfo.pleaseAddEmail": "Please add email", + "contactInfo.pleaseAddPhoneNumber": "Please add phone number", + "contactInfo.pleaseAddURL": "Please add URL", + "contactPeople.phoneNumbers": "Phone numbers", + "contactPeople.phoneNumber": "Phone number", + "contactPeople.type": "Type", + "contactPeople.language": "Language", + "contactPeople.categories": "Categories", + "contactPeople.email": "Email", + "contactPeople.emails": "Emails", + "contactPeople.emailAddress": "Email address", + "contactPeople.additionalEmail": "Additional email", + "contactPeople.url": "URL", + "contactPeople.urls": "URLs", + "contactPeople.name": "Name", + "contactPeople.inactive": "Inactive", + "contactPeople.description": "Description", + "contactPeople.noContactAvailable": "No contact available", + "contactPeople.remove": "Remove", + "contactPeople.removeContact": "Remove contact", + "contactPeople.prefix": "Prefix", + "contactPeople.add": "Add", + "contactPeople.addAddress": "Add address", + "contactPeople.addEmail": "Add email", + "contactPeople.addPhoneNumber": "Add phone number", + "contactPeople.addUrl": "Add URL", + "contactPeople.pleaseAddAddress": "Please add address", + "contactPeople.pleaseAddEmail": "Please add email", + "contactPeople.pleaseAddPhoneNumbers": "Please add phone number", + "contactPeople.pleaseAddUrl": "Please add URL", + "agreement.name": "Name", + "agreement.discount": "Discount", + "agreement.discountSym": "Discount %", + "agreement.referenceUrl": "Reference URL", + "agreement.notes": "Notes", + "agreement.noAgreementsAvailable": "No agreements available", + "agreement.remove": "Remove", + "agreement.add": "Add", + "agreement.pleaseAddAgreements": "Please add agreements", + "vendorInfo.paymentMethod": "Payment method", + "vendorInfo.vendorCurrencies": "Vendor currencies", + "vendorInfo.claimingInterval": "Claiming interval", + "vendorInfo.discountPercent": "Discount percent", + "vendorInfo.expectedActivationInterval": "Expected activation interval", + "vendorInfo.expectedInvoiceInterval": "Expected invoice interval", + "vendorInfo.expectedReceiptInterval": "Expected receipt interval", + "vendorInfo.renewalActivationInterval": "Renewal activation interval", + "vendorInfo.subscriptionInterval": "Subscription interval", + "vendorInfo.tax": "Tax", + "vendorInfo.taxID": "Tax ID", + "vendorInfo.taxPercentage": "Tax percentage", + "vendorInfo.liableForVAT": "Liable for VAT", + "interface.name": "Name", + "interface.uri": "URI", + "interface.username": "Username", + "interface.password": "Password", + "interface.notes": "Notes", + "interface.statistics": "Statistics", + "interface.available": "Available", + "interface.deliveryMethod": "Delivery method", + "interface.statisticsFormat": "Statistics format", + "interface.locallyStored": "Locally stored", + "interface.onlineLocation": "Online location", + "interface.statisticsNotes": "Statistics notes", + "interface.noInterfaceAvail": "No interface data available", + "interface.remove": "Remove", + "interface.add": "Add", + "interface.pleaseAddInterface": "Please add interface", + "accounts.name": "Name", + "accounts.accountNumber": "Account number", + "accounts.description": "Description", + "accounts.payable": "Accounting code", + "accounts.paymentMethod": "Payment method", + "accounts.accountStatus": "Account status", + "accounts.libraryCode": "Library code", + "accounts.libraryEDICode": "Library EDI code", + "accounts.notes": "Notes", + "accounts.noAccountsAvail": "No accounts available", + "accounts.add": "Add", + "accounts.pleaseAddAccount": "Please add account", + "settings.categories": "Categories", + "settings.name": "name", + "settings.action": "actions", + "settings.vendorSettings": "Organizations settings", + "summary.organizationStatus": "Organization status", + "summary.isVendor": "Vendor", + "createOrg.title": "Create organization", + "vendorTerms": "Vendor terms", + "editOrg.title": "Edit - {name}", + "accounts.account.accountStatus": "Account status", + "contactInfo.actions.addAddress": "Add address", + "contactInfo.actions.addPhoneNumber": "Add phone number", + "contactInfo.actions.addEmail": "Add email", + "accounts.account.contactInfo": "Contact info", + "organizationStatus.active": "Active", + "organizationStatus.inactive": "Inactive", + "organizationStatus.pending": "Pending", + "accounts.remove": "Remove", + "primaryItem": "Primary", + "alternateItem": "Alternate", + "contactPeople.status": "Status", + "contactPeople.status.inactive": "Inactive", + "contactPeople.status.active": "Active", + "contactPeople.addresses": "Addresses", + "contactPeople.addressLine1": "Address 1", + "contactPeople.addressLine2": "Address 2", + "contactPeople.city": "City", + "contactPeople.zipCode": "Zip code", + "contactPeople.country": "Country", + "contactPeople.showMoreAddresses": "Show more addresses", + "contactPeople.showMorePhones": "Show more phone numbers", + "contactPeople.showMoreEmails": "Show more emails", + "contactPeople.showMoreURLs": "Show more URLs", + "contactPeople.details.lastName": "Last name", + "contactPeople.details.firstName": "First name", + "contactPeople.addContact": "Add contact", + "contacts.edit.paneTitle": "Edit contact - {name}", + "contacts.create.paneTitle": "Create contact", + "contacts.view.paneTitle": "Contact - {name}", + "contacts.button.edit": "Edit", + "contacts.button.copy": "Copy", + "contacts.button.unassign": "Unassign", + "contacts.button.delete": "Delete", + "contactPeople.noFindContactPlugin": "no find-contact plugin", + "contactPeople.address": "Address", + "contactPeople.stateRegion": "State / Prov. / Region", + "contactPeople.primaryAddress": "Use as primary address", + "contactPeople.addresses.address": "Address", + "contactPeople.addresses.addressLine1": "Address 1", + "contactPeople.addresses.addressLine2": "Address 2", + "contactPeople.addresses.city": "City", + "contactPeople.addresses.stateRegion": "State/Prov./Region", + "contactPeople.addresses.zipCode": "Zip code", + "contactPeople.addresses.country": "Country", + "contactPeople.addresses.language": "Language", + "contactPeople.addresses.categories": "Categories", + "contactPeople.phoneNumbers.phoneNumber": "Phone number", + "contactPeople.phoneNumbers.language": "Language", + "contactPeople.phoneNumbers.categories": "Categories", + "contactPeople.phoneNumbers.type": "Type", + "contactPeople.phone": "Phone", + "contactPeople.primaryPhone": "Use as primary phone", + "contactPeople.primaryEmail": "Use as primary email", + "contactPeople.urls.value": "URL", + "contactPeople.urls.description": "Description", + "contactPeople.urls.language": "Language", + "contactPeople.urls.categories": "Categories", + "contactPeople.primaryUrl": "Use as primary URL", + "contactPeople.emails.value": "Email", + "contactPeople.emails.description": "Description", + "contactPeople.emails.language": "Language", + "contactPeople.emails.categories": "Categories", + "contacts.message.unassigned.fail": "The contact was not unassigned", + "contacts.message.unassigned.success": "The contact was unassigned", + "contacts.confirmUnassign.confirmLabel": "Confirm", + "contacts.confirmUnassign.heading": "Unassign from organization", + "contacts.confirmDelete.confirmLabel": "Confirm", + "contacts.confirmDelete.heading": "Delete contact", + "contacts.confirmDelete.message": "Are you sure you want to delete the contact?", + "contacts.message.deleted.fail": "The contact was not deleted", + "contacts.message.deleted.success": "The contact was deleted", + "contactPeople.newContact": "New", + "contacts.button.save": "Save", + "contacts.message.saved.fail": "The contact was not saved", + "contacts.message.saved.success": "The contact was saved", + "contacts.confirmUnassign.message1": "Are you sure you want to unassign the contact from this organization?", + "interface.addInterface": "Add interface", + "interface.noFindInterfacePlugin": "no find-interface plugin", + "interface.newInterface": "New", + "interface.button.edit": "Edit", + "interface.button.copy": "Copy", + "interface.button.unassign": "Unassign", + "interface.button.delete": "Delete", + "interface.button.save": "Save", + "interface.create.paneTitle": "Create interface", + "interface.edit.paneTitle": "Edit interface - {name}", + "interface.message.saved.fail": "The interface was not saved", + "interface.message.saved.success": "The interface was saved", + "contactPeople.note": "Note", + "interface.confirmUnassign.confirmLabel": "Confirm", + "interface.confirmUnassign.heading": "Unassign from organization", + "interface.confirmUnassign.message1": "Are you sure you want to unassign the interface from this organization?", + "interface.confirmDelete.confirmLabel": "Confirm", + "interface.confirmDelete.heading": "Delete interface", + "interface.confirmDelete.message": "Are you sure you want to delete the interface?", + "interface.message.unassigned.fail": "The interface was not unassigned", + "interface.message.delete.fail": "The interface was not deleted", + "filterConfig.isVendor": "Is vendor", + "main.isVendor.no": "No", + "main.isVendor.yes": "Yes", + "main.isVendor": "Vendor", + "filterConfig.boolean.true": "Yes", + "filterConfig.boolean.false": "No", + "search.name": "Name", + "search.contacts": "Contacts", + "search.code": "Code", + "search.language": "Language", + "search.aliases": "Alias", + "search.erpCode": "Accounting code", + "search.taxId": "Tax ID", + "search.interfaces": "Interfaces", + "organization.delete.heading": "Delete {organizationName}?", + "organization.delete.confirmLabel": "Delete", + "organization.delete.success": "The organization {organizationName} was successfully deleted", + "view.delete": "Delete", + "view.delete.message": "Delete organization?", + "vendor.confirmation.heading": "Confirm vendor data deletion", + "vendor.confirmation.confirm": "Confirm", + "vendor.confirmation.message": "Warning. All vendor information, vendor terms, EDI information, and accounts will be deleted from this record.", + "edit.showCredentials": "Show credentials", + "showMore": "Show more", + "showTags": "Show tags", + "search.keyword": "All", + "button.cancel": "Cancel", + "button.saveAndClose": "Save & close", + "interface.url": "URL", + "interface.type": "Type", + "edit.hideCredentials": "Hide credentials", + "contactInfo.vendorCategory.uncategorized": "Uncategorized", + "contacts.actions.load.error": "Failed to load contacts data", + "save.error.genericError": "Organization could not be saved", + "filterConfig.acqUnits": "Acquisition unit", + "save.error.codeInUse": "Code is already in use", + "search.placeholder.language": "Search with language code", + "vendorInfo.exportToAccounting": "Export to accounting", + "notes.entity": "Organization", + "notes.entityPlural": "Organizations", + "contactInfo.vendorCategory.customerService": "Customer Service", + "contactInfo.vendorCategory.payments": "Payment", + "contactInfo.vendorCategory.returns": "Returns", + "contactInfo.vendorCategory.shipments": "Shipments", + "save.error.creds": "Error while saving credentials", + "save.error.assignInterface": "Error while assigning interface to the organization", + "contactPeople.errors.noPrimaryRecord": "No primary record selected", + "contactPeople.removedContact": "Removed contact", + "permission.view": "Organizations: View", + "permission.edit": "Organizations: View, edit", + "permission.create": "Organizations: View, edit, create", + "permission.delete": "Organizations: View, edit, delete", + "permission.creds.view": "Organizations: Interface usernames and passwords: view", + "permission.creds.manage": "Organizations: Interface usernames and passwords: view, edit, create, delete", + "permission.acqUnits.assign": "Organizations: Assign acquisition units to new organization", + "permission.acqUnits.manage": "Organizations: Manage acquisition units", + "permission.settings": "Settings (Organizations): Can view and edit settings", + "appMenu.organizationsAppSearch": "Organizations app Search", + "view.exportLog": "View export log", + "integrationDetails": "Integration details", + "integration.create": "Add integration", + "integration.create.paneTitle": "Create integration", + "integration.edit.paneTitle": "Edit integration - {name}", + "integration.info": "Integration information", + "integration.info.configName": "Integration name", + "integration.info.configDescription": "Description", + "integration.info.isDefaultConfig": "Default integration", + "integration.edi": "EDI configuration", + "integration.edi.accountNumbers": "Account numbers", + "integration.edi.defaultAcquisitionMethods": "Automate order export for acquisition methods", + "integration.edi.vendorEDICode": "Vendor EDI code", + "integration.edi.vendorEDIType": "Vendor EDI type", + "integration.edi.libraryEDICode": "Library EDI code", + "integration.edi.libraryEDIType": "Library EDI type", + "integration.edi.ediNamingConvention": "EDI naming convention", + "integration.edi.sendAccountNumber": "Send account number", + "integration.edi.receiveNotifications": "What messages are expected for this vendor?", + "integration.edi.orders": "Orders", + "integration.edi.invoices": "Invoices", + "integration.edi.notes": "Notes", + "integration.ftp": "FTP details", + "integration.ftp.ftpFormat": "EDI FTP", + "integration.ftp.ftpMode": "FTP mode", + "integration.ftp.serverAddress": "Server address", + "integration.ftp.ftpConnectionMode": "FTP connection mode", + "integration.ftp.ftpConnectionMode.Active": "Active", + "integration.ftp.ftpConnectionMode.Passive": "Passive", + "integration.ftp.username": "Username", + "integration.ftp.password": "Password", + "integration.ftp.ftpPort": "FTP port", + "integration.ftp.orderDirectory": "Order directory", + "integration.ftp.invoiceDirectory": "Invoice directory", + "integration.ftp.notes": "Notes", + "integration.scheduling": "Scheduling", + "integration.scheduling.scheduleEDI": "Schedule EDI", + "integration.scheduling.schedulePeriod": "Schedule period", + "integration.scheduling.schedulePeriod.hours": "Hourly", + "integration.scheduling.schedulePeriod.days": "Daily", + "integration.scheduling.schedulePeriod.weeks": "Weekly", + "integration.scheduling.schedulePeriod.months": "Monthly", + "integration.scheduling.scheduleTime": "Time", + "integration.scheduling.scheduleFrequency": "Schedule frequency", + "integration.scheduling.scheduleDate": "Date", + "integration.scheduling.scheduleDay": "Day", + "integration.scheduling.scheduleWeekdays.FRIDAY": "F", + "integration.scheduling.scheduleWeekdays.MONDAY": "M", + "integration.scheduling.scheduleWeekdays.SATURDAY": "S", + "integration.scheduling.scheduleWeekdays.SUNDAY": "S", + "integration.scheduling.scheduleWeekdays.THURSDAY": "T", + "integration.scheduling.scheduleWeekdays.TUESDAY": "T", + "integration.scheduling.scheduleWeekdays.WEDNESDAY": "W", + "integration.scheduling.scheduleWeekdaysView.FRIDAY": "Friday", + "integration.scheduling.scheduleWeekdaysView.MONDAY": "Monday", + "integration.scheduling.scheduleWeekdaysView.SATURDAY": "Saturday", + "integration.scheduling.scheduleWeekdaysView.SUNDAY": "Sunday", + "integration.scheduling.scheduleWeekdaysView.THURSDAY": "Thursday", + "integration.scheduling.scheduleWeekdaysView.TUESDAY": "Tuesday", + "integration.scheduling.scheduleWeekdaysView.WEDNESDAY": "Wednesday", + "integration.message.save.success": "Integration was saved", + "integration.message.save.error": "Integration could not be saved", + "integration.confirmation.heading": "Confirm integration deletion", + "integration.confirmation.confirm": "Confirm", + "integration.confirmation.message": "Are you sure you want to delete the integration?", + "integration.message.delete.error": "The integration was not deleted", + "integration.message.delete.success": "The integration was successfully deleted", + "view.duplicateAccounts": "An organization can not have duplicate account numbers. Before editing this organization in any way you will need to change or remove any duplicate account numbers", + "save.error.accountNumberMustBeUnique": "An organization can not have duplicate account numbers", + "integration.edi.ediNamingConvention.info": "When defining your naming convention you can use text or one of the following tokens. Tokens will be replace by the corresponding information from the export job. Possible tokens are {tokens}", + "linkedAgreements.section": "Agreements", + "linkedAgreements.agreement.name": "Agreement Name", + "linkedAgreements.agreement.startDate": "Period start", + "linkedAgreements.agreement.endDate": "Period End", + "linkedAgreements.agreement.agreementStatus": "Agreement status", + "linkedAgreements.agreement.agreementStatus.active": "Active", + "linkedAgreements.agreement.agreementStatus.closed": "Closed", + "linkedAgreements.agreement.agreementStatus.draft": "Draft", + "linkedAgreements.agreement.agreementStatus.in_negotiation": "In negotiation", + "linkedAgreements.agreement.agreementStatus.requested": "Requested", + "filterConfig.types": "Types", + "summary.type": "Type", + "settings.type.name": "Name", + "settings.type.status": "Status", + "settings.types": "Types", + "settings.type": "Type", + "settings.typeStatus.Active": "Active", + "settings.typeStatus.Inactive": "Inactive", + "permission.integrations.creds.view": "Organizations: Integration usernames and passwords: view", + "permission.integrations.creds.edit": "Organizations: Integration usernames and passwords: view, edit", + "integration.scheduling.schedulePeriod.none": "Please select schedule period", + "settings.categories.cannotDeleteTermHeader": "Cannot delete category", + "settings.categories.cannotDeleteTermMessage": "This category cannot be deleted, as it is in use by one or more records.", + "settings.categories.deleteEntry": "Delete category", + "settings.categories.termDeleted": "The category {term} was successfully deleted", + "settings.categories.termWillBeDeleted": "The category {term} will be deleted.", + "settings.types.cannotDeleteTermHeader": "Cannot delete type", + "settings.types.cannotDeleteTermMessage": "This type cannot be deleted, as it is in use by one or more records.", + "settings.types.deleteEntry": "Delete type", + "settings.types.termDeleted": "The type {term} was successfully deleted", + "settings.types.termWillBeDeleted": "The type {term} will be deleted.", + "save.success": "The Organization - \"{organizationName}\" has been successfully saved", + "permission.settings.view": "Settings (Organizations): View settings", + "comingSoon": "Coming in a future release.", + "summary.isDonor": "Donor" +} \ No newline at end of file diff --git a/translations/ui-organizations/zh_CN.json b/translations/ui-organizations/zh_CN.json index 906bee6f..c6ec832d 100644 --- a/translations/ui-organizations/zh_CN.json +++ b/translations/ui-organizations/zh_CN.json @@ -418,5 +418,5 @@ "save.success": "组织 -“ {organizationName} ” 已成功保存", "permission.settings.view": "设置(组织):查看设置", "comingSoon": "将在未来版本中推出。", - "summary.isDonor": "Donor" + "summary.isDonor": "捐赠者" } \ No newline at end of file From 797cca867b525ccfc3bf0f6ed87e555e7f49dc9c Mon Sep 17 00:00:00 2001 From: Alisher Musurmonov Date: Wed, 1 Nov 2023 20:42:57 +0500 Subject: [PATCH 02/14] UIORGS-391 - Settings for banking information (#577) * UIORGS-391: add initial routing config and components * UIORGS-404 bump optional plugins to compatible versions (#572) Use plugins compatible with the requested version of stripes (v9). Refs UIORGS-404 * Release v5.0.0 (#573) * UIORGS-383: add donor info for organization summary (#574) * UIORGS-383: add donor info for organization summary * tests: fix failing tests * tests: remove failing snapshots * tests: generate snapshot tests * tests: update snapshot tests * improve: bump package.json, fix organizations summary layout, remove checkbox handler * feat: add CRUD for banking account types * UIORGS-391: integrate with backend. * tests: add test coverages * remove failing test * tests: add test cases * tests: add test coverages * tests: add test coverage * tests: add test coverages * refactor: code based on comments * test: fix failing tests * update package.json interfaces * update: refactor code and component * test: add test coverage * update: permissions for organization settings * update: permissions for organizations settings * refactor: query key and checkbox component * remove unnecessary permissions * update: permissions for banking-account-types * refactor: change the order of imports * refactor: fix column naming issues * optimize: add settings version for optimistic locking issue * tests: fix failing tests --------- Co-authored-by: Zak Burke --- CHANGELOG.md | 1 + package.json | 13 ++- .../BankingAccountTypeSettings.js | 60 +++++++++++++ .../BankingAccountTypeSettings.test.js | 66 +++++++++++++++ .../BankingAccountTypeSettings/index.js | 1 + .../BankingInformationSettings.js | 53 ++++++++++++ .../BankingInformationSettings.test.js | 84 +++++++++++++++++++ .../BankingInformationSettingsForm.js | 73 ++++++++++++++++ .../BankingInformationSettingsForm.test.js | 46 ++++++++++ .../BankingInformationSettings/index.js | 1 + src/Settings/SettingsPage.js | 44 ++++++++-- src/Settings/SettingsPage.test.js | 75 +++++++++++++++++ src/Settings/constants.js | 8 ++ src/Settings/hooks/index.js | 1 + src/Settings/hooks/useBankingInformation.js | 35 ++++++++ .../hooks/useBankingInformation.test.js | 53 ++++++++++++ translations/ui-organizations/en.json | 16 ++++ 17 files changed, 620 insertions(+), 10 deletions(-) create mode 100644 src/Settings/BankingAccountTypeSettings/BankingAccountTypeSettings.js create mode 100644 src/Settings/BankingAccountTypeSettings/BankingAccountTypeSettings.test.js create mode 100644 src/Settings/BankingAccountTypeSettings/index.js create mode 100644 src/Settings/BankingInformationSettings/BankingInformationSettings.js create mode 100644 src/Settings/BankingInformationSettings/BankingInformationSettings.test.js create mode 100644 src/Settings/BankingInformationSettings/BankingInformationSettingsForm.js create mode 100644 src/Settings/BankingInformationSettings/BankingInformationSettingsForm.test.js create mode 100644 src/Settings/BankingInformationSettings/index.js create mode 100644 src/Settings/SettingsPage.test.js create mode 100644 src/Settings/constants.js create mode 100644 src/Settings/hooks/index.js create mode 100644 src/Settings/hooks/useBankingInformation.js create mode 100644 src/Settings/hooks/useBankingInformation.test.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 07078bfc..c3326e45 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## 5.1.0 (IN PROGRESS) * Designate Organization as donor. Refs UIORGS-383. +* Settings for banking information. Refs UIORGS-391. ## [5.0.0](https://github.com/folio-org/ui-organizations/tree/v5.0.0) (2023-10-12) [Full Changelog](https://github.com/folio-org/ui-organizations/compare/v4.0.0...v5.0.0) diff --git a/package.json b/package.json index 4d765cd7..158442d4 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "organizations-storage.emails": "1.1", "organizations-storage.interfaces": "2.1", "organizations-storage.phone-numbers": "2.0", + "organizations-storage.settings": "1.0", "organizations-storage.urls": "1.1", "tags": "1.0", "users": "15.1 16.0" @@ -207,7 +208,11 @@ "settings.organizations.enabled", "organizations-storage.organization-types.collection.get", "organizations-storage.organization-types.item.get", - "organizations-storage.categories.collection.get" + "organizations-storage.categories.collection.get", + "organizations-storage.settings.collection.get", + "organizations-storage.settings.item.get", + "organizations-storage.banking-account-types.collection.get", + "organizations-storage.banking-account-types.item.get" ] }, { @@ -221,7 +226,11 @@ "organizations-storage.organization-types.item.delete", "organizations-storage.categories.item.delete", "organizations-storage.categories.item.post", - "organizations-storage.categories.item.put" + "organizations-storage.categories.item.put", + "organizations-storage.settings.item.put", + "organizations-storage.banking-account-types.item.post", + "organizations-storage.banking-account-types.item.put", + "organizations-storage.banking-account-types.item.delete" ] } ] diff --git a/src/Settings/BankingAccountTypeSettings/BankingAccountTypeSettings.js b/src/Settings/BankingAccountTypeSettings/BankingAccountTypeSettings.js new file mode 100644 index 00000000..0ffb2568 --- /dev/null +++ b/src/Settings/BankingAccountTypeSettings/BankingAccountTypeSettings.js @@ -0,0 +1,60 @@ +import React from 'react'; +import { FormattedMessage } from 'react-intl'; + +import { getControlledVocabTranslations } from '@folio/stripes-acq-components'; +import { useStripes } from '@folio/stripes/core'; +import { ControlledVocab } from '@folio/stripes/smart-components'; + +import { BANKING_ACCOUNT_TYPES_API } from '../constants'; + +const setUniqValidation = (value, index, items) => { + const errors = {}; + + const isBankingAccountTypeExist = items.some(({ id, name }) => { + return name?.toLowerCase() === value?.name?.toLowerCase() && id !== value?.id; + }); + + if (isBankingAccountTypeExist) { + errors.name = ; + } + + return errors; +}; + +const BankingAccountTypeSettings = () => { + const stripes = useStripes(); + const ConnectedComponent = stripes.connect(ControlledVocab); + + const columnMapping = { + name: , + action: , + }; + + const hasEditPerms = stripes.hasPerm('ui-organizations.settings'); + const actionSuppressor = { + edit: () => !hasEditPerms, + delete: () => !hasEditPerms, + }; + + return ( + } + translations={getControlledVocabTranslations('ui-organizations.settings.bankingAccountTypes')} + objectLabel="BankingAccountTypes" + visibleFields={['name']} + columnMapping={columnMapping} + hiddenFields={['lastUpdated', 'numberOfObjects']} + nameKey="bankingAccountTypes" + id="bankingAccountTypes" + validate={setUniqValidation} + sortby="name" + /> + ); +}; + +export default BankingAccountTypeSettings; diff --git a/src/Settings/BankingAccountTypeSettings/BankingAccountTypeSettings.test.js b/src/Settings/BankingAccountTypeSettings/BankingAccountTypeSettings.test.js new file mode 100644 index 00000000..fec7b865 --- /dev/null +++ b/src/Settings/BankingAccountTypeSettings/BankingAccountTypeSettings.test.js @@ -0,0 +1,66 @@ +import { + render, + screen, +} from '@folio/jest-config-stripes/testing-library/react'; +import { useStripes } from '@folio/stripes/core'; +import { ControlledVocab } from '@folio/stripes/smart-components'; + +import BankingAccountTypeSettings from './BankingAccountTypeSettings'; + +jest.mock('@folio/stripes/core', () => ({ + ...jest.requireActual('@folio/stripes/core'), + useStripes: jest.fn(), +})); + +jest.mock('@folio/stripes-smart-components/lib/ControlledVocab', () => jest.fn(({ + rowFilter, + label, + rowFilterFunction, + preCreateHook, + listSuppressor, +}) => ( + <> + {label} +
{rowFilter}
+ + +))); + +const stripesMock = { + connect: component => component, + hasPerm: jest.fn(() => true), + clone: jest.fn(), +}; + +const renderCategorySettings = () => render(); + +describe('BankingAccountTypeSettings', () => { + beforeEach(() => { + useStripes.mockReturnValue(stripesMock); + }); + + it('should render component', () => { + renderCategorySettings(); + + expect(screen.getByText('New')); + expect(screen.getByText('ui-organizations.settings.bankingAccountTypes')); + }); + + it('should check action suppression', () => { + renderCategorySettings(); + + const { actionSuppressor } = ControlledVocab.mock.calls[0][0]; + + expect(actionSuppressor.edit()).toBeFalsy(); + expect(actionSuppressor.delete()).toBeFalsy(); + }); +}); diff --git a/src/Settings/BankingAccountTypeSettings/index.js b/src/Settings/BankingAccountTypeSettings/index.js new file mode 100644 index 00000000..52570c07 --- /dev/null +++ b/src/Settings/BankingAccountTypeSettings/index.js @@ -0,0 +1 @@ +export { default as BankingAccountTypeSettings } from './BankingAccountTypeSettings'; diff --git a/src/Settings/BankingInformationSettings/BankingInformationSettings.js b/src/Settings/BankingInformationSettings/BankingInformationSettings.js new file mode 100644 index 00000000..5c45c571 --- /dev/null +++ b/src/Settings/BankingInformationSettings/BankingInformationSettings.js @@ -0,0 +1,53 @@ +import { FormattedMessage } from 'react-intl'; + +import { useShowCallout } from '@folio/stripes-acq-components'; +import { Loading } from '@folio/stripes/components'; +import { useOkapiKy } from '@folio/stripes/core'; + +import { SETTINGS_API } from '../constants'; +import { useBankingInformation } from '../hooks'; +import BankingInformationSettingsForm from './BankingInformationSettingsForm'; + +const BankingInformationSettings = () => { + const { + enabled, + key, + id: bankingInformationId, + version, + isLoading, + refetch, + } = useBankingInformation(); + const ky = useOkapiKy(); + const sendCallout = useShowCallout(); + + const onSubmit = async ({ value }) => { + try { + await ky.put(`${SETTINGS_API}/${bankingInformationId}`, { + json: { value, key, _version: version }, + }); + + refetch(); + sendCallout({ + message: , + }); + } catch (error) { + sendCallout({ + type: 'error', + message: , + }); + } + }; + + if (isLoading) { + return ; + } + + return ( + + ); +}; + +export default BankingInformationSettings; diff --git a/src/Settings/BankingInformationSettings/BankingInformationSettings.test.js b/src/Settings/BankingInformationSettings/BankingInformationSettings.test.js new file mode 100644 index 00000000..4bacedac --- /dev/null +++ b/src/Settings/BankingInformationSettings/BankingInformationSettings.test.js @@ -0,0 +1,84 @@ +import { MemoryRouter } from 'react-router-dom'; + +import { + act, + render, + screen, +} from '@folio/jest-config-stripes/testing-library/react'; +import user from '@folio/jest-config-stripes/testing-library/user-event'; +import { useOkapiKy } from '@folio/stripes/core'; + +import { useBankingInformation } from '../hooks'; +import BankingInformationSettings from './BankingInformationSettings'; + +const mockRefetch = jest.fn(); + +jest.mock('@folio/stripes/components', () => ({ + ...jest.requireActual('@folio/stripes/components'), + Loading: () =>
Loading
, +})); + +jest.mock('../hooks', () => ({ + useBankingInformation: jest.fn(() => ({ + isLoading: false, + enabled: false, + refetch: mockRefetch, + })), +})); + +const renderBankingInformationSettings = () => render( + , + { wrapper: MemoryRouter }, +); + +describe('BankingInformationSettings component', () => { + it('should display pane headings', () => { + renderBankingInformationSettings(); + + const paneTitle = screen.getByText('ui-organizations.settings.bankingInformation'); + const checkboxLabel = screen.getByText('ui-organizations.settings.bankingInformation.enable'); + + expect(paneTitle).toBeInTheDocument(); + expect(checkboxLabel).toBeInTheDocument(); + }); + + it('should render Loading component', () => { + useBankingInformation.mockReturnValue({ + isLoading: true, + enabled: false, + }); + + renderBankingInformationSettings(); + + expect(screen.getByText('Loading')).toBeInTheDocument(); + }); + + it('should save banking options', async () => { + useBankingInformation.mockClear().mockReturnValue({ + isLoading: false, + enabled: true, + refetch: mockRefetch, + }); + const mockPutMethod = jest.fn(() => ({ + json: () => Promise.resolve('ok'), + })); + + useOkapiKy + .mockClear() + .mockReturnValue({ + put: mockPutMethod, + }); + + renderBankingInformationSettings(); + + const checkbox = screen.getByRole('checkbox', { name: 'ui-organizations.settings.bankingInformation.enable' }); + const saveButton = screen.getByText('ui-organizations.settings.accountTypes.save.button'); + + await act(async () => { + await user.click(checkbox); + await user.click(saveButton); + }); + + expect(mockPutMethod).toHaveBeenCalled(); + }); +}); diff --git a/src/Settings/BankingInformationSettings/BankingInformationSettingsForm.js b/src/Settings/BankingInformationSettings/BankingInformationSettingsForm.js new file mode 100644 index 00000000..96d21441 --- /dev/null +++ b/src/Settings/BankingInformationSettings/BankingInformationSettingsForm.js @@ -0,0 +1,73 @@ +import { useMemo } from 'react'; +import PropTypes from 'prop-types'; +import { Field } from 'react-final-form'; +import { FormattedMessage } from 'react-intl'; + +import { + Button, + Checkbox, + Col, + Pane, + PaneFooter, + PaneHeader, + Row, +} from '@folio/stripes/components'; +import stripesForm from '@folio/stripes/final-form'; + +const BankingInformationSettingsForm = ({ + handleSubmit, + pristine, + submitting, +}) => { + const paneFooter = useMemo(() => { + const end = ( + + ); + + return ; + }, [handleSubmit, pristine, submitting]); + + const paneTitle = ; + + return ( + } + footer={paneFooter} + > + + + } + name="value" + type="checkbox" + /> + + + + ); +}; + +BankingInformationSettingsForm.propTypes = { + handleSubmit: PropTypes.func.isRequired, + pristine: PropTypes.bool.isRequired, + submitting: PropTypes.bool.isRequired, + renderHeader: PropTypes.func, +}; + +export default stripesForm({ + enableReinitialize: true, + keepDirtyOnReinitialize: true, + navigationCheck: true, + subscription: { values: true }, +})(BankingInformationSettingsForm); diff --git a/src/Settings/BankingInformationSettings/BankingInformationSettingsForm.test.js b/src/Settings/BankingInformationSettings/BankingInformationSettingsForm.test.js new file mode 100644 index 00000000..30b76e28 --- /dev/null +++ b/src/Settings/BankingInformationSettings/BankingInformationSettingsForm.test.js @@ -0,0 +1,46 @@ +import { MemoryRouter } from 'react-router-dom'; + +import { + act, + render, + screen, +} from '@folio/jest-config-stripes/testing-library/react'; +import user from '@folio/jest-config-stripes/testing-library/user-event'; + +import BankingInformationSettingsForm from './BankingInformationSettingsForm'; + +const mockOnSubmit = jest.fn(); + +const DEFAULT_PROPS = { + onSubmit: mockOnSubmit, + initialValues: { + value: true, + }, +}; + +const renderBankingInformationSettingsForm = (props = DEFAULT_PROPS) => render( + , + { wrapper: MemoryRouter }, +); + +describe('BankingInformationSettingsForm component', () => { + it('should render component', async () => { + renderBankingInformationSettingsForm(); + + expect(screen.getByLabelText('ui-organizations.settings.bankingInformation')).toBeInTheDocument(); + }); + + it('should save banking options', async () => { + renderBankingInformationSettingsForm(); + + const checkbox = screen.getByRole('checkbox', { name: 'ui-organizations.settings.bankingInformation.enable' }); + const saveButton = screen.getByText('ui-organizations.settings.accountTypes.save.button'); + + await act(async () => { + await user.click(checkbox); + await user.click(saveButton); + }); + + expect(mockOnSubmit).toHaveBeenCalled(); + }); +}); diff --git a/src/Settings/BankingInformationSettings/index.js b/src/Settings/BankingInformationSettings/index.js new file mode 100644 index 00000000..6fe1ba6f --- /dev/null +++ b/src/Settings/BankingInformationSettings/index.js @@ -0,0 +1 @@ +export { default as BankingInformationSettings } from './BankingInformationSettings'; diff --git a/src/Settings/SettingsPage.js b/src/Settings/SettingsPage.js index 65d7c8d4..e422f927 100644 --- a/src/Settings/SettingsPage.js +++ b/src/Settings/SettingsPage.js @@ -1,10 +1,14 @@ -import React from 'react'; +import React, { useMemo } from 'react'; import { FormattedMessage } from 'react-intl'; import { Settings } from '@folio/stripes/smart-components'; +import { Loading } from '@folio/stripes/components'; +import { useBankingInformation } from './hooks'; import { CategorySettings } from './CategorySettings'; import { TypeSettings } from './TypeSettings'; +import { BankingInformationSettings } from './BankingInformationSettings'; +import { BankingAccountTypeSettings } from './BankingAccountTypeSettings'; const pages = [ { @@ -19,14 +23,38 @@ const pages = [ perm: 'settings.organizations.enabled', route: 'type', }, + { + component: BankingInformationSettings, + label: , + perm: 'settings.organizations.enabled', + route: 'banking-information', + }, ]; -const SettingsPage = (props) => ( - } - /> -); +const bankingAccountTypesPage = { + component: BankingAccountTypeSettings, + label: , + perm: 'settings.organizations.enabled', + route: 'banking-account-types', +}; + +const SettingsPage = (props) => { + const { enabled, isLoading } = useBankingInformation(); + + const settingsPages = useMemo(() => (enabled ? pages.concat(bankingAccountTypesPage) : pages), [enabled]); + + if (isLoading) { + return ; + } + + return ( + } + /> + ); +}; export default SettingsPage; diff --git a/src/Settings/SettingsPage.test.js b/src/Settings/SettingsPage.test.js new file mode 100644 index 00000000..d4b2e8a0 --- /dev/null +++ b/src/Settings/SettingsPage.test.js @@ -0,0 +1,75 @@ +import React from 'react'; +import { MemoryRouter } from 'react-router-dom'; + +import { screen, render } from '@folio/jest-config-stripes/testing-library/react'; + +import SettingsPage from './SettingsPage'; +import { useBankingInformation } from './hooks'; + +jest.mock('@folio/stripes/core'); +jest.mock('@folio/stripes/smart-components'); + +jest.mock('@folio/stripes/components', () => ({ + ...jest.requireActual('@folio/stripes/components'), + Loading: () =>
Loading
, +})); +jest.mock('./hooks', () => ({ + useBankingInformation: jest.fn(() => ({ + isLoading: false, + enabled: false, + })), +})); + +const stripesMock = { + connect: component => component, + hasPerm: jest.fn(() => true), +}; + +const defaultProps = { + stripes: stripesMock, + match: { + path: 'url', + }, + location: { + search: '?name=test', + pathname: '', + }, +}; + +const renderSettingsPage = (props) => render( + + + , +); + +describe('SettingsPage', () => { + it('should return categories, types and banking information links', async () => { + renderSettingsPage(); + + expect(screen.getByText('ui-organizations.settings.categories')).toBeInTheDocument(); + expect(screen.getByText('ui-organizations.settings.types')).toBeInTheDocument(); + expect(screen.getByText('ui-organizations.settings.bankingInformation')).toBeInTheDocument(); + }); + + it('should return banking account types link', async () => { + useBankingInformation.mockReturnValue({ + isLoading: false, + enabled: true, + }); + + renderSettingsPage(); + + expect(screen.getByText('ui-organizations.settings.bankingAccountTypes')).toBeInTheDocument(); + }); + + it('should display loading on fetching useBankingInformation', async () => { + useBankingInformation.mockReturnValue({ + isLoading: true, + enabled: false, + }); + + renderSettingsPage(); + + expect(screen.getByText('Loading')).toBeInTheDocument(); + }); +}); diff --git a/src/Settings/constants.js b/src/Settings/constants.js new file mode 100644 index 00000000..56157dab --- /dev/null +++ b/src/Settings/constants.js @@ -0,0 +1,8 @@ +export const SETTINGS_API = 'organizations-storage/settings'; +export const BANKING_ACCOUNT_TYPES_API = 'organizations-storage/banking-account-types'; + +export const BANKING_INFORMATION_ENABLED_QUERY_KEY = 'BANKING_INFORMATION_ENABLED'; +export const BANKING_INFORMATION_SEARCH_PARAMS = { + query: `key=${BANKING_INFORMATION_ENABLED_QUERY_KEY}`, + limit: 1, +}; diff --git a/src/Settings/hooks/index.js b/src/Settings/hooks/index.js new file mode 100644 index 00000000..2144f705 --- /dev/null +++ b/src/Settings/hooks/index.js @@ -0,0 +1 @@ +export { useBankingInformation } from './useBankingInformation'; diff --git a/src/Settings/hooks/useBankingInformation.js b/src/Settings/hooks/useBankingInformation.js new file mode 100644 index 00000000..23dce38d --- /dev/null +++ b/src/Settings/hooks/useBankingInformation.js @@ -0,0 +1,35 @@ +import { get } from 'lodash'; +import { useQuery } from 'react-query'; + +import { + useNamespace, + useOkapiKy, +} from '@folio/stripes/core'; + +import { + BANKING_INFORMATION_SEARCH_PARAMS, + SETTINGS_API, +} from '../constants'; + +export const useBankingInformation = () => { + const ky = useOkapiKy(); + const [namespace] = useNamespace({ key: 'banking-information-settings' }); + + const { isLoading, data, refetch } = useQuery( + [namespace], + () => ky.get(SETTINGS_API, { + searchParams: BANKING_INFORMATION_SEARCH_PARAMS, + }).json(), + ); + + const bankingInformation = get(data, 'settings[0]', {}); + + return ({ + id: bankingInformation.id, + enabled: bankingInformation.value === 'true', + key: bankingInformation.key, + version: bankingInformation._version, + isLoading, + refetch, + }); +}; diff --git a/src/Settings/hooks/useBankingInformation.test.js b/src/Settings/hooks/useBankingInformation.test.js new file mode 100644 index 00000000..03046dfe --- /dev/null +++ b/src/Settings/hooks/useBankingInformation.test.js @@ -0,0 +1,53 @@ +import { + QueryClient, + QueryClientProvider, +} from 'react-query'; + +import { + renderHook, + waitFor, +} from '@folio/jest-config-stripes/testing-library/react'; +import { useOkapiKy } from '@folio/stripes/core'; + +import { useBankingInformation } from './useBankingInformation'; + +const queryClient = new QueryClient(); + +const MOCK_BANKING_INFORMATION = { + 'id': 'cb007def-4b68-496c-ad78-ea8e039e819d', + 'key': 'BANKING_INFORMATION_ENABLED', + 'value': 'true', + refetch: jest.fn(), +}; + +// eslint-disable-next-line react/prop-types +const wrapper = ({ children }) => ( + + {children} + +); + +describe('useBankingInformation', () => { + beforeEach(() => { + useOkapiKy + .mockClear() + .mockReturnValue({ + get: () => ({ + json: () => Promise.resolve({ settings: [MOCK_BANKING_INFORMATION] }), + }), + }); + }); + + it('should fetch all organization types', async () => { + const { result } = renderHook(() => useBankingInformation(), { wrapper }); + + await waitFor(() => expect(result.current.isLoading).toBeFalsy()); + + expect(result.current).toEqual(expect.objectContaining({ + enabled: true, + isLoading: false, + id: MOCK_BANKING_INFORMATION.id, + key: MOCK_BANKING_INFORMATION.key, + })); + }); +}); diff --git a/translations/ui-organizations/en.json b/translations/ui-organizations/en.json index c591d8b2..ec12c26e 100644 --- a/translations/ui-organizations/en.json +++ b/translations/ui-organizations/en.json @@ -36,6 +36,7 @@ "filterConfig.contactPeopleCategory": "Contact people category", "filterConfig.country": "Country", "filterConfig.isVendor": "Is vendor", + "filterConfig.isDonor": "Is donor", "filterConfig.languages": "Languages", "filterConfig.paymentMethod": "Payment method", "filterConfig.statsAvailable": "Stats available", @@ -442,6 +443,21 @@ "settings.type": "Type", "settings.typeStatus.Active": "Active", "settings.typeStatus.Inactive": "Inactive", + "settings.bankingInformation": "Banking information", + "settings.bankingInformation.enable": "Enable banking information", + "settings.bankingAccountTypes": "Account types", + "settings.bankingAccountTypes.cannotDeleteTermHeader": "Cannot delete account type", + "settings.bankingAccountTypes.cannotDeleteTermMessage": "This account type cannot be deleted, as it is in use by one or more records.", + "settings.bankingAccountTypes.deleteEntry": "Delete account type", + "settings.bankingAccountTypes.termDeleted": "The account type {term} was successfully deleted", + "settings.bankingAccountTypes.termWillBeDeleted": "The account type {term} will be deleted.", + "settings.accountTypes.save.error.accountTypeMustBeUnique": "Account type must be unique.", + "settings.accountTypes.save.button": "Save", + "settings.accountTypes.save.success.message": "Setting was successfully updated.", + "settings.accountTypes.save.error.generic.message": "Something went wrong.", + "settings.accountTypes.name": "Name", + "settings.accountTypes.action": "Action", + "permission.view": "Organizations: View", "permission.edit": "Organizations: View, edit", "permission.create": "Organizations: View, edit, create", From 19700d9a31a29f8bba5c89e97cc8af9b0b22e919 Mon Sep 17 00:00:00 2001 From: FOLIO Translations Bot <38661258+folio-translations@users.noreply.github.com> Date: Mon, 6 Nov 2023 16:26:43 -0500 Subject: [PATCH 03/14] Lokalise: updates --- translations/ui-organizations/ar.json | 17 ++++++++++++++++- translations/ui-organizations/ber.json | 17 ++++++++++++++++- translations/ui-organizations/ca.json | 17 ++++++++++++++++- translations/ui-organizations/cs_CZ.json | 17 ++++++++++++++++- translations/ui-organizations/da.json | 17 ++++++++++++++++- translations/ui-organizations/de.json | 17 ++++++++++++++++- translations/ui-organizations/en_GB.json | 17 ++++++++++++++++- translations/ui-organizations/en_SE.json | 17 ++++++++++++++++- translations/ui-organizations/en_US.json | 17 ++++++++++++++++- translations/ui-organizations/es.json | 17 ++++++++++++++++- translations/ui-organizations/es_419.json | 17 ++++++++++++++++- translations/ui-organizations/es_ES.json | 17 ++++++++++++++++- translations/ui-organizations/fr.json | 17 ++++++++++++++++- translations/ui-organizations/fr_FR.json | 17 ++++++++++++++++- translations/ui-organizations/he.json | 17 ++++++++++++++++- translations/ui-organizations/hi_IN.json | 17 ++++++++++++++++- translations/ui-organizations/hu.json | 17 ++++++++++++++++- translations/ui-organizations/it_IT.json | 17 ++++++++++++++++- translations/ui-organizations/ja.json | 17 ++++++++++++++++- translations/ui-organizations/ko.json | 17 ++++++++++++++++- translations/ui-organizations/nb.json | 17 ++++++++++++++++- translations/ui-organizations/nn.json | 17 ++++++++++++++++- translations/ui-organizations/pl.json | 17 ++++++++++++++++- translations/ui-organizations/pt_BR.json | 17 ++++++++++++++++- translations/ui-organizations/pt_PT.json | 17 ++++++++++++++++- translations/ui-organizations/ru.json | 17 ++++++++++++++++- translations/ui-organizations/sk.json | 17 ++++++++++++++++- translations/ui-organizations/sv.json | 17 ++++++++++++++++- translations/ui-organizations/ur.json | 17 ++++++++++++++++- translations/ui-organizations/zh_CN.json | 17 ++++++++++++++++- translations/ui-organizations/zh_TW.json | 17 ++++++++++++++++- 31 files changed, 496 insertions(+), 31 deletions(-) diff --git a/translations/ui-organizations/ar.json b/translations/ui-organizations/ar.json index 958d8d63..85e46d70 100644 --- a/translations/ui-organizations/ar.json +++ b/translations/ui-organizations/ar.json @@ -418,5 +418,20 @@ "save.success": "The Organization - \"{organizationName}\" has been successfully saved", "permission.settings.view": "Settings (Organizations): View settings", "comingSoon": "Coming in a future release.", - "summary.isDonor": "Donor" + "summary.isDonor": "Donor", + "filterConfig.isDonor": "Is donor", + "settings.bankingInformation": "Banking information", + "settings.bankingInformation.enable": "Enable banking information", + "settings.bankingAccountTypes": "Account types", + "settings.bankingAccountTypes.cannotDeleteTermHeader": "Cannot delete account type", + "settings.bankingAccountTypes.cannotDeleteTermMessage": "This account type cannot be deleted, as it is in use by one or more records.", + "settings.bankingAccountTypes.deleteEntry": "Delete account type", + "settings.bankingAccountTypes.termDeleted": "The account type {term} was successfully deleted", + "settings.bankingAccountTypes.termWillBeDeleted": "The account type {term} will be deleted.", + "settings.accountTypes.save.error.accountTypeMustBeUnique": "Account type must be unique.", + "settings.accountTypes.save.button": "Save", + "settings.accountTypes.save.success.message": "Setting was successfully updated.", + "settings.accountTypes.save.error.generic.message": "Something went wrong.", + "settings.accountTypes.name": "Name", + "settings.accountTypes.action": "Action" } \ No newline at end of file diff --git a/translations/ui-organizations/ber.json b/translations/ui-organizations/ber.json index c2e6879e..d1cb0d90 100644 --- a/translations/ui-organizations/ber.json +++ b/translations/ui-organizations/ber.json @@ -418,5 +418,20 @@ "save.success": "The Organization - \"{organizationName}\" has been successfully saved", "permission.settings.view": "Settings (Organizations): View settings", "comingSoon": "Coming in a future release.", - "summary.isDonor": "Donor" + "summary.isDonor": "Donor", + "filterConfig.isDonor": "Is donor", + "settings.bankingInformation": "Banking information", + "settings.bankingInformation.enable": "Enable banking information", + "settings.bankingAccountTypes": "Account types", + "settings.bankingAccountTypes.cannotDeleteTermHeader": "Cannot delete account type", + "settings.bankingAccountTypes.cannotDeleteTermMessage": "This account type cannot be deleted, as it is in use by one or more records.", + "settings.bankingAccountTypes.deleteEntry": "Delete account type", + "settings.bankingAccountTypes.termDeleted": "The account type {term} was successfully deleted", + "settings.bankingAccountTypes.termWillBeDeleted": "The account type {term} will be deleted.", + "settings.accountTypes.save.error.accountTypeMustBeUnique": "Account type must be unique.", + "settings.accountTypes.save.button": "Save", + "settings.accountTypes.save.success.message": "Setting was successfully updated.", + "settings.accountTypes.save.error.generic.message": "Something went wrong.", + "settings.accountTypes.name": "Name", + "settings.accountTypes.action": "Action" } \ No newline at end of file diff --git a/translations/ui-organizations/ca.json b/translations/ui-organizations/ca.json index 045d355b..007e224f 100644 --- a/translations/ui-organizations/ca.json +++ b/translations/ui-organizations/ca.json @@ -418,5 +418,20 @@ "save.success": "The Organization - \"{organizationName}\" has been successfully saved", "permission.settings.view": "Settings (Organizations): View settings", "comingSoon": "Coming in a future release.", - "summary.isDonor": "Donor" + "summary.isDonor": "Donor", + "filterConfig.isDonor": "Is donor", + "settings.bankingInformation": "Banking information", + "settings.bankingInformation.enable": "Enable banking information", + "settings.bankingAccountTypes": "Account types", + "settings.bankingAccountTypes.cannotDeleteTermHeader": "Cannot delete account type", + "settings.bankingAccountTypes.cannotDeleteTermMessage": "This account type cannot be deleted, as it is in use by one or more records.", + "settings.bankingAccountTypes.deleteEntry": "Delete account type", + "settings.bankingAccountTypes.termDeleted": "The account type {term} was successfully deleted", + "settings.bankingAccountTypes.termWillBeDeleted": "The account type {term} will be deleted.", + "settings.accountTypes.save.error.accountTypeMustBeUnique": "Account type must be unique.", + "settings.accountTypes.save.button": "Save", + "settings.accountTypes.save.success.message": "Setting was successfully updated.", + "settings.accountTypes.save.error.generic.message": "Something went wrong.", + "settings.accountTypes.name": "Name", + "settings.accountTypes.action": "Action" } \ No newline at end of file diff --git a/translations/ui-organizations/cs_CZ.json b/translations/ui-organizations/cs_CZ.json index ccd29ae2..14309b74 100644 --- a/translations/ui-organizations/cs_CZ.json +++ b/translations/ui-organizations/cs_CZ.json @@ -418,5 +418,20 @@ "save.success": "Organizace - \"{organizationName}\" byla úspěšně uložena", "permission.settings.view": "Nastavení (Organizace): Zobrazení nastavení", "comingSoon": "Přijde v budoucím vydání.", - "summary.isDonor": "Dárce" + "summary.isDonor": "Dárce", + "filterConfig.isDonor": "Is donor", + "settings.bankingInformation": "Banking information", + "settings.bankingInformation.enable": "Enable banking information", + "settings.bankingAccountTypes": "Account types", + "settings.bankingAccountTypes.cannotDeleteTermHeader": "Cannot delete account type", + "settings.bankingAccountTypes.cannotDeleteTermMessage": "This account type cannot be deleted, as it is in use by one or more records.", + "settings.bankingAccountTypes.deleteEntry": "Delete account type", + "settings.bankingAccountTypes.termDeleted": "The account type {term} was successfully deleted", + "settings.bankingAccountTypes.termWillBeDeleted": "The account type {term} will be deleted.", + "settings.accountTypes.save.error.accountTypeMustBeUnique": "Account type must be unique.", + "settings.accountTypes.save.button": "Save", + "settings.accountTypes.save.success.message": "Setting was successfully updated.", + "settings.accountTypes.save.error.generic.message": "Something went wrong.", + "settings.accountTypes.name": "Name", + "settings.accountTypes.action": "Action" } \ No newline at end of file diff --git a/translations/ui-organizations/da.json b/translations/ui-organizations/da.json index 7827308b..c6a04897 100644 --- a/translations/ui-organizations/da.json +++ b/translations/ui-organizations/da.json @@ -418,5 +418,20 @@ "save.success": "The Organization - \"{organizationName}\" has been successfully saved", "permission.settings.view": "Settings (Organizations): View settings", "comingSoon": "Coming in a future release.", - "summary.isDonor": "Donor" + "summary.isDonor": "Donor", + "filterConfig.isDonor": "Is donor", + "settings.bankingInformation": "Banking information", + "settings.bankingInformation.enable": "Enable banking information", + "settings.bankingAccountTypes": "Account types", + "settings.bankingAccountTypes.cannotDeleteTermHeader": "Cannot delete account type", + "settings.bankingAccountTypes.cannotDeleteTermMessage": "This account type cannot be deleted, as it is in use by one or more records.", + "settings.bankingAccountTypes.deleteEntry": "Delete account type", + "settings.bankingAccountTypes.termDeleted": "The account type {term} was successfully deleted", + "settings.bankingAccountTypes.termWillBeDeleted": "The account type {term} will be deleted.", + "settings.accountTypes.save.error.accountTypeMustBeUnique": "Account type must be unique.", + "settings.accountTypes.save.button": "Save", + "settings.accountTypes.save.success.message": "Setting was successfully updated.", + "settings.accountTypes.save.error.generic.message": "Something went wrong.", + "settings.accountTypes.name": "Name", + "settings.accountTypes.action": "Action" } \ No newline at end of file diff --git a/translations/ui-organizations/de.json b/translations/ui-organizations/de.json index d41a9efd..23b7c2bb 100644 --- a/translations/ui-organizations/de.json +++ b/translations/ui-organizations/de.json @@ -418,5 +418,20 @@ "save.success": "DieOrganisation -\"{organizationName}\" wurde erfolgreich gespeichert", "permission.settings.view": "Settings (Organizations): View settings", "comingSoon": "Coming in a future release.", - "summary.isDonor": "Donor" + "summary.isDonor": "Donor", + "filterConfig.isDonor": "Is donor", + "settings.bankingInformation": "Banking information", + "settings.bankingInformation.enable": "Enable banking information", + "settings.bankingAccountTypes": "Account types", + "settings.bankingAccountTypes.cannotDeleteTermHeader": "Cannot delete account type", + "settings.bankingAccountTypes.cannotDeleteTermMessage": "This account type cannot be deleted, as it is in use by one or more records.", + "settings.bankingAccountTypes.deleteEntry": "Delete account type", + "settings.bankingAccountTypes.termDeleted": "The account type {term} was successfully deleted", + "settings.bankingAccountTypes.termWillBeDeleted": "The account type {term} will be deleted.", + "settings.accountTypes.save.error.accountTypeMustBeUnique": "Account type must be unique.", + "settings.accountTypes.save.button": "Save", + "settings.accountTypes.save.success.message": "Setting was successfully updated.", + "settings.accountTypes.save.error.generic.message": "Something went wrong.", + "settings.accountTypes.name": "Name", + "settings.accountTypes.action": "Action" } \ No newline at end of file diff --git a/translations/ui-organizations/en_GB.json b/translations/ui-organizations/en_GB.json index c2e6879e..d1cb0d90 100644 --- a/translations/ui-organizations/en_GB.json +++ b/translations/ui-organizations/en_GB.json @@ -418,5 +418,20 @@ "save.success": "The Organization - \"{organizationName}\" has been successfully saved", "permission.settings.view": "Settings (Organizations): View settings", "comingSoon": "Coming in a future release.", - "summary.isDonor": "Donor" + "summary.isDonor": "Donor", + "filterConfig.isDonor": "Is donor", + "settings.bankingInformation": "Banking information", + "settings.bankingInformation.enable": "Enable banking information", + "settings.bankingAccountTypes": "Account types", + "settings.bankingAccountTypes.cannotDeleteTermHeader": "Cannot delete account type", + "settings.bankingAccountTypes.cannotDeleteTermMessage": "This account type cannot be deleted, as it is in use by one or more records.", + "settings.bankingAccountTypes.deleteEntry": "Delete account type", + "settings.bankingAccountTypes.termDeleted": "The account type {term} was successfully deleted", + "settings.bankingAccountTypes.termWillBeDeleted": "The account type {term} will be deleted.", + "settings.accountTypes.save.error.accountTypeMustBeUnique": "Account type must be unique.", + "settings.accountTypes.save.button": "Save", + "settings.accountTypes.save.success.message": "Setting was successfully updated.", + "settings.accountTypes.save.error.generic.message": "Something went wrong.", + "settings.accountTypes.name": "Name", + "settings.accountTypes.action": "Action" } \ No newline at end of file diff --git a/translations/ui-organizations/en_SE.json b/translations/ui-organizations/en_SE.json index c2e6879e..d1cb0d90 100644 --- a/translations/ui-organizations/en_SE.json +++ b/translations/ui-organizations/en_SE.json @@ -418,5 +418,20 @@ "save.success": "The Organization - \"{organizationName}\" has been successfully saved", "permission.settings.view": "Settings (Organizations): View settings", "comingSoon": "Coming in a future release.", - "summary.isDonor": "Donor" + "summary.isDonor": "Donor", + "filterConfig.isDonor": "Is donor", + "settings.bankingInformation": "Banking information", + "settings.bankingInformation.enable": "Enable banking information", + "settings.bankingAccountTypes": "Account types", + "settings.bankingAccountTypes.cannotDeleteTermHeader": "Cannot delete account type", + "settings.bankingAccountTypes.cannotDeleteTermMessage": "This account type cannot be deleted, as it is in use by one or more records.", + "settings.bankingAccountTypes.deleteEntry": "Delete account type", + "settings.bankingAccountTypes.termDeleted": "The account type {term} was successfully deleted", + "settings.bankingAccountTypes.termWillBeDeleted": "The account type {term} will be deleted.", + "settings.accountTypes.save.error.accountTypeMustBeUnique": "Account type must be unique.", + "settings.accountTypes.save.button": "Save", + "settings.accountTypes.save.success.message": "Setting was successfully updated.", + "settings.accountTypes.save.error.generic.message": "Something went wrong.", + "settings.accountTypes.name": "Name", + "settings.accountTypes.action": "Action" } \ No newline at end of file diff --git a/translations/ui-organizations/en_US.json b/translations/ui-organizations/en_US.json index c2e6879e..d1cb0d90 100644 --- a/translations/ui-organizations/en_US.json +++ b/translations/ui-organizations/en_US.json @@ -418,5 +418,20 @@ "save.success": "The Organization - \"{organizationName}\" has been successfully saved", "permission.settings.view": "Settings (Organizations): View settings", "comingSoon": "Coming in a future release.", - "summary.isDonor": "Donor" + "summary.isDonor": "Donor", + "filterConfig.isDonor": "Is donor", + "settings.bankingInformation": "Banking information", + "settings.bankingInformation.enable": "Enable banking information", + "settings.bankingAccountTypes": "Account types", + "settings.bankingAccountTypes.cannotDeleteTermHeader": "Cannot delete account type", + "settings.bankingAccountTypes.cannotDeleteTermMessage": "This account type cannot be deleted, as it is in use by one or more records.", + "settings.bankingAccountTypes.deleteEntry": "Delete account type", + "settings.bankingAccountTypes.termDeleted": "The account type {term} was successfully deleted", + "settings.bankingAccountTypes.termWillBeDeleted": "The account type {term} will be deleted.", + "settings.accountTypes.save.error.accountTypeMustBeUnique": "Account type must be unique.", + "settings.accountTypes.save.button": "Save", + "settings.accountTypes.save.success.message": "Setting was successfully updated.", + "settings.accountTypes.save.error.generic.message": "Something went wrong.", + "settings.accountTypes.name": "Name", + "settings.accountTypes.action": "Action" } \ No newline at end of file diff --git a/translations/ui-organizations/es.json b/translations/ui-organizations/es.json index 64f3862b..4459148d 100644 --- a/translations/ui-organizations/es.json +++ b/translations/ui-organizations/es.json @@ -418,5 +418,20 @@ "save.success": "The Organization - \"{organizationName}\" has been successfully saved", "permission.settings.view": "Settings (Organizations): View settings", "comingSoon": "Coming in a future release.", - "summary.isDonor": "Donor" + "summary.isDonor": "Donor", + "filterConfig.isDonor": "Is donor", + "settings.bankingInformation": "Banking information", + "settings.bankingInformation.enable": "Enable banking information", + "settings.bankingAccountTypes": "Account types", + "settings.bankingAccountTypes.cannotDeleteTermHeader": "Cannot delete account type", + "settings.bankingAccountTypes.cannotDeleteTermMessage": "This account type cannot be deleted, as it is in use by one or more records.", + "settings.bankingAccountTypes.deleteEntry": "Delete account type", + "settings.bankingAccountTypes.termDeleted": "The account type {term} was successfully deleted", + "settings.bankingAccountTypes.termWillBeDeleted": "The account type {term} will be deleted.", + "settings.accountTypes.save.error.accountTypeMustBeUnique": "Account type must be unique.", + "settings.accountTypes.save.button": "Save", + "settings.accountTypes.save.success.message": "Setting was successfully updated.", + "settings.accountTypes.save.error.generic.message": "Something went wrong.", + "settings.accountTypes.name": "Name", + "settings.accountTypes.action": "Action" } \ No newline at end of file diff --git a/translations/ui-organizations/es_419.json b/translations/ui-organizations/es_419.json index 6c70cacf..83f8948b 100644 --- a/translations/ui-organizations/es_419.json +++ b/translations/ui-organizations/es_419.json @@ -418,5 +418,20 @@ "save.success": "La Organización - \"{organizationName}\" se ha guardado correctamente", "permission.settings.view": "Ajustes (Organizaciones): Ver configuración", "comingSoon": "Coming in a future release.", - "summary.isDonor": "Donor" + "summary.isDonor": "Donor", + "filterConfig.isDonor": "Is donor", + "settings.bankingInformation": "Banking information", + "settings.bankingInformation.enable": "Enable banking information", + "settings.bankingAccountTypes": "Account types", + "settings.bankingAccountTypes.cannotDeleteTermHeader": "Cannot delete account type", + "settings.bankingAccountTypes.cannotDeleteTermMessage": "This account type cannot be deleted, as it is in use by one or more records.", + "settings.bankingAccountTypes.deleteEntry": "Delete account type", + "settings.bankingAccountTypes.termDeleted": "The account type {term} was successfully deleted", + "settings.bankingAccountTypes.termWillBeDeleted": "The account type {term} will be deleted.", + "settings.accountTypes.save.error.accountTypeMustBeUnique": "Account type must be unique.", + "settings.accountTypes.save.button": "Save", + "settings.accountTypes.save.success.message": "Setting was successfully updated.", + "settings.accountTypes.save.error.generic.message": "Something went wrong.", + "settings.accountTypes.name": "Name", + "settings.accountTypes.action": "Action" } \ No newline at end of file diff --git a/translations/ui-organizations/es_ES.json b/translations/ui-organizations/es_ES.json index 8339db80..a04991f5 100644 --- a/translations/ui-organizations/es_ES.json +++ b/translations/ui-organizations/es_ES.json @@ -418,5 +418,20 @@ "save.success": "The Organization - \"{organizationName}\" has been successfully saved", "permission.settings.view": "Settings (Organizations): View settings", "comingSoon": "Coming in a future release.", - "summary.isDonor": "Donante" + "summary.isDonor": "Donante", + "filterConfig.isDonor": "Is donor", + "settings.bankingInformation": "Banking information", + "settings.bankingInformation.enable": "Enable banking information", + "settings.bankingAccountTypes": "Account types", + "settings.bankingAccountTypes.cannotDeleteTermHeader": "Cannot delete account type", + "settings.bankingAccountTypes.cannotDeleteTermMessage": "This account type cannot be deleted, as it is in use by one or more records.", + "settings.bankingAccountTypes.deleteEntry": "Delete account type", + "settings.bankingAccountTypes.termDeleted": "The account type {term} was successfully deleted", + "settings.bankingAccountTypes.termWillBeDeleted": "The account type {term} will be deleted.", + "settings.accountTypes.save.error.accountTypeMustBeUnique": "Account type must be unique.", + "settings.accountTypes.save.button": "Save", + "settings.accountTypes.save.success.message": "Setting was successfully updated.", + "settings.accountTypes.save.error.generic.message": "Something went wrong.", + "settings.accountTypes.name": "Name", + "settings.accountTypes.action": "Action" } \ No newline at end of file diff --git a/translations/ui-organizations/fr.json b/translations/ui-organizations/fr.json index 6a67988e..46d95332 100644 --- a/translations/ui-organizations/fr.json +++ b/translations/ui-organizations/fr.json @@ -418,5 +418,20 @@ "save.success": "The Organization - \"{organizationName}\" has been successfully saved", "permission.settings.view": "Settings (Organizations): View settings", "comingSoon": "Coming in a future release.", - "summary.isDonor": "Donor" + "summary.isDonor": "Donor", + "filterConfig.isDonor": "Is donor", + "settings.bankingInformation": "Banking information", + "settings.bankingInformation.enable": "Enable banking information", + "settings.bankingAccountTypes": "Account types", + "settings.bankingAccountTypes.cannotDeleteTermHeader": "Cannot delete account type", + "settings.bankingAccountTypes.cannotDeleteTermMessage": "This account type cannot be deleted, as it is in use by one or more records.", + "settings.bankingAccountTypes.deleteEntry": "Delete account type", + "settings.bankingAccountTypes.termDeleted": "The account type {term} was successfully deleted", + "settings.bankingAccountTypes.termWillBeDeleted": "The account type {term} will be deleted.", + "settings.accountTypes.save.error.accountTypeMustBeUnique": "Account type must be unique.", + "settings.accountTypes.save.button": "Save", + "settings.accountTypes.save.success.message": "Setting was successfully updated.", + "settings.accountTypes.save.error.generic.message": "Something went wrong.", + "settings.accountTypes.name": "Name", + "settings.accountTypes.action": "Action" } \ No newline at end of file diff --git a/translations/ui-organizations/fr_FR.json b/translations/ui-organizations/fr_FR.json index a8d96f31..e0147ff2 100644 --- a/translations/ui-organizations/fr_FR.json +++ b/translations/ui-organizations/fr_FR.json @@ -418,5 +418,20 @@ "save.success": "The Organization - \"{organizationName}\" has been successfully saved", "permission.settings.view": "Settings (Organizations): View settings", "comingSoon": "Coming in a future release.", - "summary.isDonor": "Donor" + "summary.isDonor": "Donor", + "filterConfig.isDonor": "Is donor", + "settings.bankingInformation": "Banking information", + "settings.bankingInformation.enable": "Enable banking information", + "settings.bankingAccountTypes": "Account types", + "settings.bankingAccountTypes.cannotDeleteTermHeader": "Cannot delete account type", + "settings.bankingAccountTypes.cannotDeleteTermMessage": "This account type cannot be deleted, as it is in use by one or more records.", + "settings.bankingAccountTypes.deleteEntry": "Delete account type", + "settings.bankingAccountTypes.termDeleted": "The account type {term} was successfully deleted", + "settings.bankingAccountTypes.termWillBeDeleted": "The account type {term} will be deleted.", + "settings.accountTypes.save.error.accountTypeMustBeUnique": "Account type must be unique.", + "settings.accountTypes.save.button": "Save", + "settings.accountTypes.save.success.message": "Setting was successfully updated.", + "settings.accountTypes.save.error.generic.message": "Something went wrong.", + "settings.accountTypes.name": "Name", + "settings.accountTypes.action": "Action" } \ No newline at end of file diff --git a/translations/ui-organizations/he.json b/translations/ui-organizations/he.json index c2e6879e..d1cb0d90 100644 --- a/translations/ui-organizations/he.json +++ b/translations/ui-organizations/he.json @@ -418,5 +418,20 @@ "save.success": "The Organization - \"{organizationName}\" has been successfully saved", "permission.settings.view": "Settings (Organizations): View settings", "comingSoon": "Coming in a future release.", - "summary.isDonor": "Donor" + "summary.isDonor": "Donor", + "filterConfig.isDonor": "Is donor", + "settings.bankingInformation": "Banking information", + "settings.bankingInformation.enable": "Enable banking information", + "settings.bankingAccountTypes": "Account types", + "settings.bankingAccountTypes.cannotDeleteTermHeader": "Cannot delete account type", + "settings.bankingAccountTypes.cannotDeleteTermMessage": "This account type cannot be deleted, as it is in use by one or more records.", + "settings.bankingAccountTypes.deleteEntry": "Delete account type", + "settings.bankingAccountTypes.termDeleted": "The account type {term} was successfully deleted", + "settings.bankingAccountTypes.termWillBeDeleted": "The account type {term} will be deleted.", + "settings.accountTypes.save.error.accountTypeMustBeUnique": "Account type must be unique.", + "settings.accountTypes.save.button": "Save", + "settings.accountTypes.save.success.message": "Setting was successfully updated.", + "settings.accountTypes.save.error.generic.message": "Something went wrong.", + "settings.accountTypes.name": "Name", + "settings.accountTypes.action": "Action" } \ No newline at end of file diff --git a/translations/ui-organizations/hi_IN.json b/translations/ui-organizations/hi_IN.json index c2e6879e..d1cb0d90 100644 --- a/translations/ui-organizations/hi_IN.json +++ b/translations/ui-organizations/hi_IN.json @@ -418,5 +418,20 @@ "save.success": "The Organization - \"{organizationName}\" has been successfully saved", "permission.settings.view": "Settings (Organizations): View settings", "comingSoon": "Coming in a future release.", - "summary.isDonor": "Donor" + "summary.isDonor": "Donor", + "filterConfig.isDonor": "Is donor", + "settings.bankingInformation": "Banking information", + "settings.bankingInformation.enable": "Enable banking information", + "settings.bankingAccountTypes": "Account types", + "settings.bankingAccountTypes.cannotDeleteTermHeader": "Cannot delete account type", + "settings.bankingAccountTypes.cannotDeleteTermMessage": "This account type cannot be deleted, as it is in use by one or more records.", + "settings.bankingAccountTypes.deleteEntry": "Delete account type", + "settings.bankingAccountTypes.termDeleted": "The account type {term} was successfully deleted", + "settings.bankingAccountTypes.termWillBeDeleted": "The account type {term} will be deleted.", + "settings.accountTypes.save.error.accountTypeMustBeUnique": "Account type must be unique.", + "settings.accountTypes.save.button": "Save", + "settings.accountTypes.save.success.message": "Setting was successfully updated.", + "settings.accountTypes.save.error.generic.message": "Something went wrong.", + "settings.accountTypes.name": "Name", + "settings.accountTypes.action": "Action" } \ No newline at end of file diff --git a/translations/ui-organizations/hu.json b/translations/ui-organizations/hu.json index a583de46..50c0920a 100644 --- a/translations/ui-organizations/hu.json +++ b/translations/ui-organizations/hu.json @@ -418,5 +418,20 @@ "save.success": "The Organization - \"{organizationName}\" has been successfully saved", "permission.settings.view": "Settings (Organizations): View settings", "comingSoon": "Coming in a future release.", - "summary.isDonor": "Donor" + "summary.isDonor": "Donor", + "filterConfig.isDonor": "Is donor", + "settings.bankingInformation": "Banking information", + "settings.bankingInformation.enable": "Enable banking information", + "settings.bankingAccountTypes": "Account types", + "settings.bankingAccountTypes.cannotDeleteTermHeader": "Cannot delete account type", + "settings.bankingAccountTypes.cannotDeleteTermMessage": "This account type cannot be deleted, as it is in use by one or more records.", + "settings.bankingAccountTypes.deleteEntry": "Delete account type", + "settings.bankingAccountTypes.termDeleted": "The account type {term} was successfully deleted", + "settings.bankingAccountTypes.termWillBeDeleted": "The account type {term} will be deleted.", + "settings.accountTypes.save.error.accountTypeMustBeUnique": "Account type must be unique.", + "settings.accountTypes.save.button": "Save", + "settings.accountTypes.save.success.message": "Setting was successfully updated.", + "settings.accountTypes.save.error.generic.message": "Something went wrong.", + "settings.accountTypes.name": "Name", + "settings.accountTypes.action": "Action" } \ No newline at end of file diff --git a/translations/ui-organizations/it_IT.json b/translations/ui-organizations/it_IT.json index 3ebd5ede..4ff6b9a7 100644 --- a/translations/ui-organizations/it_IT.json +++ b/translations/ui-organizations/it_IT.json @@ -418,5 +418,20 @@ "save.success": "The Organization - \"{organizationName}\" has been successfully saved", "permission.settings.view": "Settings (Organizations): View settings", "comingSoon": "Coming in a future release.", - "summary.isDonor": "Donor" + "summary.isDonor": "Donor", + "filterConfig.isDonor": "Is donor", + "settings.bankingInformation": "Banking information", + "settings.bankingInformation.enable": "Enable banking information", + "settings.bankingAccountTypes": "Account types", + "settings.bankingAccountTypes.cannotDeleteTermHeader": "Cannot delete account type", + "settings.bankingAccountTypes.cannotDeleteTermMessage": "This account type cannot be deleted, as it is in use by one or more records.", + "settings.bankingAccountTypes.deleteEntry": "Delete account type", + "settings.bankingAccountTypes.termDeleted": "The account type {term} was successfully deleted", + "settings.bankingAccountTypes.termWillBeDeleted": "The account type {term} will be deleted.", + "settings.accountTypes.save.error.accountTypeMustBeUnique": "Account type must be unique.", + "settings.accountTypes.save.button": "Save", + "settings.accountTypes.save.success.message": "Setting was successfully updated.", + "settings.accountTypes.save.error.generic.message": "Something went wrong.", + "settings.accountTypes.name": "Name", + "settings.accountTypes.action": "Action" } \ No newline at end of file diff --git a/translations/ui-organizations/ja.json b/translations/ui-organizations/ja.json index 722db646..fc392730 100644 --- a/translations/ui-organizations/ja.json +++ b/translations/ui-organizations/ja.json @@ -418,5 +418,20 @@ "save.success": "The Organization - \"{organizationName}\" has been successfully saved", "permission.settings.view": "Settings (Organizations): View settings", "comingSoon": "Coming in a future release.", - "summary.isDonor": "Donor" + "summary.isDonor": "Donor", + "filterConfig.isDonor": "Is donor", + "settings.bankingInformation": "Banking information", + "settings.bankingInformation.enable": "Enable banking information", + "settings.bankingAccountTypes": "Account types", + "settings.bankingAccountTypes.cannotDeleteTermHeader": "Cannot delete account type", + "settings.bankingAccountTypes.cannotDeleteTermMessage": "This account type cannot be deleted, as it is in use by one or more records.", + "settings.bankingAccountTypes.deleteEntry": "Delete account type", + "settings.bankingAccountTypes.termDeleted": "The account type {term} was successfully deleted", + "settings.bankingAccountTypes.termWillBeDeleted": "The account type {term} will be deleted.", + "settings.accountTypes.save.error.accountTypeMustBeUnique": "Account type must be unique.", + "settings.accountTypes.save.button": "Save", + "settings.accountTypes.save.success.message": "Setting was successfully updated.", + "settings.accountTypes.save.error.generic.message": "Something went wrong.", + "settings.accountTypes.name": "Name", + "settings.accountTypes.action": "Action" } \ No newline at end of file diff --git a/translations/ui-organizations/ko.json b/translations/ui-organizations/ko.json index b5e322c3..e1cbbcc6 100644 --- a/translations/ui-organizations/ko.json +++ b/translations/ui-organizations/ko.json @@ -418,5 +418,20 @@ "save.success": "공급사 - \"{organizationName}\"이(가) 성공적으로 저장되었습니다.", "permission.settings.view": "설정 (공급사): 설정 보기", "comingSoon": "향후 릴리스에서 제공될 예정입니다.", - "summary.isDonor": "기증자" + "summary.isDonor": "기증자", + "filterConfig.isDonor": "Is donor", + "settings.bankingInformation": "Banking information", + "settings.bankingInformation.enable": "Enable banking information", + "settings.bankingAccountTypes": "Account types", + "settings.bankingAccountTypes.cannotDeleteTermHeader": "Cannot delete account type", + "settings.bankingAccountTypes.cannotDeleteTermMessage": "This account type cannot be deleted, as it is in use by one or more records.", + "settings.bankingAccountTypes.deleteEntry": "Delete account type", + "settings.bankingAccountTypes.termDeleted": "The account type {term} was successfully deleted", + "settings.bankingAccountTypes.termWillBeDeleted": "The account type {term} will be deleted.", + "settings.accountTypes.save.error.accountTypeMustBeUnique": "Account type must be unique.", + "settings.accountTypes.save.button": "Save", + "settings.accountTypes.save.success.message": "Setting was successfully updated.", + "settings.accountTypes.save.error.generic.message": "Something went wrong.", + "settings.accountTypes.name": "Name", + "settings.accountTypes.action": "Action" } \ No newline at end of file diff --git a/translations/ui-organizations/nb.json b/translations/ui-organizations/nb.json index c2e6879e..d1cb0d90 100644 --- a/translations/ui-organizations/nb.json +++ b/translations/ui-organizations/nb.json @@ -418,5 +418,20 @@ "save.success": "The Organization - \"{organizationName}\" has been successfully saved", "permission.settings.view": "Settings (Organizations): View settings", "comingSoon": "Coming in a future release.", - "summary.isDonor": "Donor" + "summary.isDonor": "Donor", + "filterConfig.isDonor": "Is donor", + "settings.bankingInformation": "Banking information", + "settings.bankingInformation.enable": "Enable banking information", + "settings.bankingAccountTypes": "Account types", + "settings.bankingAccountTypes.cannotDeleteTermHeader": "Cannot delete account type", + "settings.bankingAccountTypes.cannotDeleteTermMessage": "This account type cannot be deleted, as it is in use by one or more records.", + "settings.bankingAccountTypes.deleteEntry": "Delete account type", + "settings.bankingAccountTypes.termDeleted": "The account type {term} was successfully deleted", + "settings.bankingAccountTypes.termWillBeDeleted": "The account type {term} will be deleted.", + "settings.accountTypes.save.error.accountTypeMustBeUnique": "Account type must be unique.", + "settings.accountTypes.save.button": "Save", + "settings.accountTypes.save.success.message": "Setting was successfully updated.", + "settings.accountTypes.save.error.generic.message": "Something went wrong.", + "settings.accountTypes.name": "Name", + "settings.accountTypes.action": "Action" } \ No newline at end of file diff --git a/translations/ui-organizations/nn.json b/translations/ui-organizations/nn.json index c2e6879e..d1cb0d90 100644 --- a/translations/ui-organizations/nn.json +++ b/translations/ui-organizations/nn.json @@ -418,5 +418,20 @@ "save.success": "The Organization - \"{organizationName}\" has been successfully saved", "permission.settings.view": "Settings (Organizations): View settings", "comingSoon": "Coming in a future release.", - "summary.isDonor": "Donor" + "summary.isDonor": "Donor", + "filterConfig.isDonor": "Is donor", + "settings.bankingInformation": "Banking information", + "settings.bankingInformation.enable": "Enable banking information", + "settings.bankingAccountTypes": "Account types", + "settings.bankingAccountTypes.cannotDeleteTermHeader": "Cannot delete account type", + "settings.bankingAccountTypes.cannotDeleteTermMessage": "This account type cannot be deleted, as it is in use by one or more records.", + "settings.bankingAccountTypes.deleteEntry": "Delete account type", + "settings.bankingAccountTypes.termDeleted": "The account type {term} was successfully deleted", + "settings.bankingAccountTypes.termWillBeDeleted": "The account type {term} will be deleted.", + "settings.accountTypes.save.error.accountTypeMustBeUnique": "Account type must be unique.", + "settings.accountTypes.save.button": "Save", + "settings.accountTypes.save.success.message": "Setting was successfully updated.", + "settings.accountTypes.save.error.generic.message": "Something went wrong.", + "settings.accountTypes.name": "Name", + "settings.accountTypes.action": "Action" } \ No newline at end of file diff --git a/translations/ui-organizations/pl.json b/translations/ui-organizations/pl.json index 0466c1d6..847dc340 100644 --- a/translations/ui-organizations/pl.json +++ b/translations/ui-organizations/pl.json @@ -418,5 +418,20 @@ "save.success": "The Organization - \"{organizationName}\" has been successfully saved", "permission.settings.view": "Settings (Organizations): View settings", "comingSoon": "Coming in a future release.", - "summary.isDonor": "Donor" + "summary.isDonor": "Donor", + "filterConfig.isDonor": "Is donor", + "settings.bankingInformation": "Banking information", + "settings.bankingInformation.enable": "Enable banking information", + "settings.bankingAccountTypes": "Account types", + "settings.bankingAccountTypes.cannotDeleteTermHeader": "Cannot delete account type", + "settings.bankingAccountTypes.cannotDeleteTermMessage": "This account type cannot be deleted, as it is in use by one or more records.", + "settings.bankingAccountTypes.deleteEntry": "Delete account type", + "settings.bankingAccountTypes.termDeleted": "The account type {term} was successfully deleted", + "settings.bankingAccountTypes.termWillBeDeleted": "The account type {term} will be deleted.", + "settings.accountTypes.save.error.accountTypeMustBeUnique": "Account type must be unique.", + "settings.accountTypes.save.button": "Save", + "settings.accountTypes.save.success.message": "Setting was successfully updated.", + "settings.accountTypes.save.error.generic.message": "Something went wrong.", + "settings.accountTypes.name": "Name", + "settings.accountTypes.action": "Action" } \ No newline at end of file diff --git a/translations/ui-organizations/pt_BR.json b/translations/ui-organizations/pt_BR.json index 0007d405..bfbf7af4 100644 --- a/translations/ui-organizations/pt_BR.json +++ b/translations/ui-organizations/pt_BR.json @@ -418,5 +418,20 @@ "save.success": "A Organização - \" {organizationName} \" foi salva com sucesso", "permission.settings.view": "Configurações (Organizações): Exibir configurações", "comingSoon": "Vindo em uma versão futura.", - "summary.isDonor": "Doador" + "summary.isDonor": "Doador", + "filterConfig.isDonor": "É doador", + "settings.bankingInformation": "Informações bancárias", + "settings.bankingInformation.enable": "Habilitar informações bancárias", + "settings.bankingAccountTypes": "Tipos de conta", + "settings.bankingAccountTypes.cannotDeleteTermHeader": "Não é possível excluir o tipo de conta", + "settings.bankingAccountTypes.cannotDeleteTermMessage": "Este tipo de conta não pode ser excluído, pois está em uso por um ou mais registros.", + "settings.bankingAccountTypes.deleteEntry": "Excluir tipo de conta", + "settings.bankingAccountTypes.termDeleted": "O tipo de conta {term} foi excluído com sucesso", + "settings.bankingAccountTypes.termWillBeDeleted": "O tipo de conta {term} será excluído.", + "settings.accountTypes.save.error.accountTypeMustBeUnique": "O tipo de conta deve ser exclusivo.", + "settings.accountTypes.save.button": "Salvar", + "settings.accountTypes.save.success.message": "A configuração foi atualizada com sucesso.", + "settings.accountTypes.save.error.generic.message": "Algo deu errado.", + "settings.accountTypes.name": "Nome", + "settings.accountTypes.action": "Ação" } \ No newline at end of file diff --git a/translations/ui-organizations/pt_PT.json b/translations/ui-organizations/pt_PT.json index d29a1e06..1b45fa1f 100644 --- a/translations/ui-organizations/pt_PT.json +++ b/translations/ui-organizations/pt_PT.json @@ -418,5 +418,20 @@ "save.success": "The Organization - \"{organizationName}\" has been successfully saved", "permission.settings.view": "Settings (Organizations): View settings", "comingSoon": "Coming in a future release.", - "summary.isDonor": "Donor" + "summary.isDonor": "Donor", + "filterConfig.isDonor": "Is donor", + "settings.bankingInformation": "Banking information", + "settings.bankingInformation.enable": "Enable banking information", + "settings.bankingAccountTypes": "Account types", + "settings.bankingAccountTypes.cannotDeleteTermHeader": "Cannot delete account type", + "settings.bankingAccountTypes.cannotDeleteTermMessage": "This account type cannot be deleted, as it is in use by one or more records.", + "settings.bankingAccountTypes.deleteEntry": "Delete account type", + "settings.bankingAccountTypes.termDeleted": "The account type {term} was successfully deleted", + "settings.bankingAccountTypes.termWillBeDeleted": "The account type {term} will be deleted.", + "settings.accountTypes.save.error.accountTypeMustBeUnique": "Account type must be unique.", + "settings.accountTypes.save.button": "Save", + "settings.accountTypes.save.success.message": "Setting was successfully updated.", + "settings.accountTypes.save.error.generic.message": "Something went wrong.", + "settings.accountTypes.name": "Name", + "settings.accountTypes.action": "Action" } \ No newline at end of file diff --git a/translations/ui-organizations/ru.json b/translations/ui-organizations/ru.json index 0180c06a..9fe9a2be 100644 --- a/translations/ui-organizations/ru.json +++ b/translations/ui-organizations/ru.json @@ -418,5 +418,20 @@ "save.success": "The Organization - \"{organizationName}\" has been successfully saved", "permission.settings.view": "Settings (Organizations): View settings", "comingSoon": "Coming in a future release.", - "summary.isDonor": "Donor" + "summary.isDonor": "Donor", + "filterConfig.isDonor": "Is donor", + "settings.bankingInformation": "Banking information", + "settings.bankingInformation.enable": "Enable banking information", + "settings.bankingAccountTypes": "Account types", + "settings.bankingAccountTypes.cannotDeleteTermHeader": "Cannot delete account type", + "settings.bankingAccountTypes.cannotDeleteTermMessage": "This account type cannot be deleted, as it is in use by one or more records.", + "settings.bankingAccountTypes.deleteEntry": "Delete account type", + "settings.bankingAccountTypes.termDeleted": "The account type {term} was successfully deleted", + "settings.bankingAccountTypes.termWillBeDeleted": "The account type {term} will be deleted.", + "settings.accountTypes.save.error.accountTypeMustBeUnique": "Account type must be unique.", + "settings.accountTypes.save.button": "Save", + "settings.accountTypes.save.success.message": "Setting was successfully updated.", + "settings.accountTypes.save.error.generic.message": "Something went wrong.", + "settings.accountTypes.name": "Name", + "settings.accountTypes.action": "Action" } \ No newline at end of file diff --git a/translations/ui-organizations/sk.json b/translations/ui-organizations/sk.json index c2e6879e..d1cb0d90 100644 --- a/translations/ui-organizations/sk.json +++ b/translations/ui-organizations/sk.json @@ -418,5 +418,20 @@ "save.success": "The Organization - \"{organizationName}\" has been successfully saved", "permission.settings.view": "Settings (Organizations): View settings", "comingSoon": "Coming in a future release.", - "summary.isDonor": "Donor" + "summary.isDonor": "Donor", + "filterConfig.isDonor": "Is donor", + "settings.bankingInformation": "Banking information", + "settings.bankingInformation.enable": "Enable banking information", + "settings.bankingAccountTypes": "Account types", + "settings.bankingAccountTypes.cannotDeleteTermHeader": "Cannot delete account type", + "settings.bankingAccountTypes.cannotDeleteTermMessage": "This account type cannot be deleted, as it is in use by one or more records.", + "settings.bankingAccountTypes.deleteEntry": "Delete account type", + "settings.bankingAccountTypes.termDeleted": "The account type {term} was successfully deleted", + "settings.bankingAccountTypes.termWillBeDeleted": "The account type {term} will be deleted.", + "settings.accountTypes.save.error.accountTypeMustBeUnique": "Account type must be unique.", + "settings.accountTypes.save.button": "Save", + "settings.accountTypes.save.success.message": "Setting was successfully updated.", + "settings.accountTypes.save.error.generic.message": "Something went wrong.", + "settings.accountTypes.name": "Name", + "settings.accountTypes.action": "Action" } \ No newline at end of file diff --git a/translations/ui-organizations/sv.json b/translations/ui-organizations/sv.json index c2e6879e..d1cb0d90 100644 --- a/translations/ui-organizations/sv.json +++ b/translations/ui-organizations/sv.json @@ -418,5 +418,20 @@ "save.success": "The Organization - \"{organizationName}\" has been successfully saved", "permission.settings.view": "Settings (Organizations): View settings", "comingSoon": "Coming in a future release.", - "summary.isDonor": "Donor" + "summary.isDonor": "Donor", + "filterConfig.isDonor": "Is donor", + "settings.bankingInformation": "Banking information", + "settings.bankingInformation.enable": "Enable banking information", + "settings.bankingAccountTypes": "Account types", + "settings.bankingAccountTypes.cannotDeleteTermHeader": "Cannot delete account type", + "settings.bankingAccountTypes.cannotDeleteTermMessage": "This account type cannot be deleted, as it is in use by one or more records.", + "settings.bankingAccountTypes.deleteEntry": "Delete account type", + "settings.bankingAccountTypes.termDeleted": "The account type {term} was successfully deleted", + "settings.bankingAccountTypes.termWillBeDeleted": "The account type {term} will be deleted.", + "settings.accountTypes.save.error.accountTypeMustBeUnique": "Account type must be unique.", + "settings.accountTypes.save.button": "Save", + "settings.accountTypes.save.success.message": "Setting was successfully updated.", + "settings.accountTypes.save.error.generic.message": "Something went wrong.", + "settings.accountTypes.name": "Name", + "settings.accountTypes.action": "Action" } \ No newline at end of file diff --git a/translations/ui-organizations/ur.json b/translations/ui-organizations/ur.json index 56a241ec..a7ab6c59 100644 --- a/translations/ui-organizations/ur.json +++ b/translations/ui-organizations/ur.json @@ -418,5 +418,20 @@ "save.success": "The Organization - \"{organizationName}\" has been successfully saved", "permission.settings.view": "Settings (Organizations): View settings", "comingSoon": "Coming in a future release.", - "summary.isDonor": "Donor" + "summary.isDonor": "Donor", + "filterConfig.isDonor": "Is donor", + "settings.bankingInformation": "Banking information", + "settings.bankingInformation.enable": "Enable banking information", + "settings.bankingAccountTypes": "Account types", + "settings.bankingAccountTypes.cannotDeleteTermHeader": "Cannot delete account type", + "settings.bankingAccountTypes.cannotDeleteTermMessage": "This account type cannot be deleted, as it is in use by one or more records.", + "settings.bankingAccountTypes.deleteEntry": "Delete account type", + "settings.bankingAccountTypes.termDeleted": "The account type {term} was successfully deleted", + "settings.bankingAccountTypes.termWillBeDeleted": "The account type {term} will be deleted.", + "settings.accountTypes.save.error.accountTypeMustBeUnique": "Account type must be unique.", + "settings.accountTypes.save.button": "Save", + "settings.accountTypes.save.success.message": "Setting was successfully updated.", + "settings.accountTypes.save.error.generic.message": "Something went wrong.", + "settings.accountTypes.name": "Name", + "settings.accountTypes.action": "Action" } \ No newline at end of file diff --git a/translations/ui-organizations/zh_CN.json b/translations/ui-organizations/zh_CN.json index c6ec832d..ca2caa3d 100644 --- a/translations/ui-organizations/zh_CN.json +++ b/translations/ui-organizations/zh_CN.json @@ -418,5 +418,20 @@ "save.success": "组织 -“ {organizationName} ” 已成功保存", "permission.settings.view": "设置(组织):查看设置", "comingSoon": "将在未来版本中推出。", - "summary.isDonor": "捐赠者" + "summary.isDonor": "捐赠者", + "filterConfig.isDonor": "Is donor", + "settings.bankingInformation": "Banking information", + "settings.bankingInformation.enable": "Enable banking information", + "settings.bankingAccountTypes": "Account types", + "settings.bankingAccountTypes.cannotDeleteTermHeader": "Cannot delete account type", + "settings.bankingAccountTypes.cannotDeleteTermMessage": "This account type cannot be deleted, as it is in use by one or more records.", + "settings.bankingAccountTypes.deleteEntry": "Delete account type", + "settings.bankingAccountTypes.termDeleted": "The account type {term} was successfully deleted", + "settings.bankingAccountTypes.termWillBeDeleted": "The account type {term} will be deleted.", + "settings.accountTypes.save.error.accountTypeMustBeUnique": "Account type must be unique.", + "settings.accountTypes.save.button": "Save", + "settings.accountTypes.save.success.message": "Setting was successfully updated.", + "settings.accountTypes.save.error.generic.message": "Something went wrong.", + "settings.accountTypes.name": "Name", + "settings.accountTypes.action": "Action" } \ No newline at end of file diff --git a/translations/ui-organizations/zh_TW.json b/translations/ui-organizations/zh_TW.json index f54933ed..04bc7331 100644 --- a/translations/ui-organizations/zh_TW.json +++ b/translations/ui-organizations/zh_TW.json @@ -418,5 +418,20 @@ "save.success": "The Organization - \"{organizationName}\" has been successfully saved", "permission.settings.view": "Settings (Organizations): View settings", "comingSoon": "Coming in a future release.", - "summary.isDonor": "Donor" + "summary.isDonor": "Donor", + "filterConfig.isDonor": "Is donor", + "settings.bankingInformation": "Banking information", + "settings.bankingInformation.enable": "Enable banking information", + "settings.bankingAccountTypes": "Account types", + "settings.bankingAccountTypes.cannotDeleteTermHeader": "Cannot delete account type", + "settings.bankingAccountTypes.cannotDeleteTermMessage": "This account type cannot be deleted, as it is in use by one or more records.", + "settings.bankingAccountTypes.deleteEntry": "Delete account type", + "settings.bankingAccountTypes.termDeleted": "The account type {term} was successfully deleted", + "settings.bankingAccountTypes.termWillBeDeleted": "The account type {term} will be deleted.", + "settings.accountTypes.save.error.accountTypeMustBeUnique": "Account type must be unique.", + "settings.accountTypes.save.button": "Save", + "settings.accountTypes.save.success.message": "Setting was successfully updated.", + "settings.accountTypes.save.error.generic.message": "Something went wrong.", + "settings.accountTypes.name": "Name", + "settings.accountTypes.action": "Action" } \ No newline at end of file From 56a9c97c8b026d90dca87e04631a97a8d73a20d5 Mon Sep 17 00:00:00 2001 From: FOLIO Translations Bot <38661258+folio-translations@users.noreply.github.com> Date: Tue, 14 Nov 2023 17:39:39 -0500 Subject: [PATCH 04/14] Lokalise: updates --- translations/ui-organizations/cs_CZ.json | 32 ++++++++++++------------ 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/translations/ui-organizations/cs_CZ.json b/translations/ui-organizations/cs_CZ.json index 14309b74..7358b6f3 100644 --- a/translations/ui-organizations/cs_CZ.json +++ b/translations/ui-organizations/cs_CZ.json @@ -89,7 +89,7 @@ "contactPeople.noContactAvailable": "Není k dispozici žádný kontakt", "contactPeople.remove": "Odstranit", "contactPeople.removeContact": "Odstranit kontakt", - "contactPeople.prefix": "Prefixy", + "contactPeople.prefix": "Prefix", "contactPeople.add": "Přidat", "contactPeople.addAddress": "Přidat adresu", "contactPeople.addEmail": "Přidat e-mail", @@ -419,19 +419,19 @@ "permission.settings.view": "Nastavení (Organizace): Zobrazení nastavení", "comingSoon": "Přijde v budoucím vydání.", "summary.isDonor": "Dárce", - "filterConfig.isDonor": "Is donor", - "settings.bankingInformation": "Banking information", - "settings.bankingInformation.enable": "Enable banking information", - "settings.bankingAccountTypes": "Account types", - "settings.bankingAccountTypes.cannotDeleteTermHeader": "Cannot delete account type", - "settings.bankingAccountTypes.cannotDeleteTermMessage": "This account type cannot be deleted, as it is in use by one or more records.", - "settings.bankingAccountTypes.deleteEntry": "Delete account type", - "settings.bankingAccountTypes.termDeleted": "The account type {term} was successfully deleted", - "settings.bankingAccountTypes.termWillBeDeleted": "The account type {term} will be deleted.", - "settings.accountTypes.save.error.accountTypeMustBeUnique": "Account type must be unique.", - "settings.accountTypes.save.button": "Save", - "settings.accountTypes.save.success.message": "Setting was successfully updated.", - "settings.accountTypes.save.error.generic.message": "Something went wrong.", - "settings.accountTypes.name": "Name", - "settings.accountTypes.action": "Action" + "filterConfig.isDonor": "Je dárce", + "settings.bankingInformation": "Bankovní informace", + "settings.bankingInformation.enable": "Povolit bankovní informace", + "settings.bankingAccountTypes": "Typy účtů", + "settings.bankingAccountTypes.cannotDeleteTermHeader": "Nelze smazat typ účtu", + "settings.bankingAccountTypes.cannotDeleteTermMessage": "Tento typ účtu nelze odstranit, protože je používán jedním nebo více záznamy.", + "settings.bankingAccountTypes.deleteEntry": "Smazat typ účtu", + "settings.bankingAccountTypes.termDeleted": "Typ účtu {term} byl úspěšně smazán", + "settings.bankingAccountTypes.termWillBeDeleted": "Typ účtu {term} bude smazán.", + "settings.accountTypes.save.error.accountTypeMustBeUnique": "Typ účtu musí být jedinečný.", + "settings.accountTypes.save.button": "Uložit", + "settings.accountTypes.save.success.message": "Nastavení bylo úspěšně aktualizováno.", + "settings.accountTypes.save.error.generic.message": "Něco se pokazilo.", + "settings.accountTypes.name": "Jméno", + "settings.accountTypes.action": "Akce" } \ No newline at end of file From e780e54d1b76edba306e035af2661ad358adee4e Mon Sep 17 00:00:00 2001 From: Yury Saukou Date: Thu, 16 Nov 2023 22:08:23 +0400 Subject: [PATCH 05/14] UIORGS-390 Implement organization's banking information form (#580) * UIORGS-390 Move reusable constants and hooks to appropriate places * UIORGS-390 rename hook useBankingInformation to useBankingInformationSettings: to not confuse domens * UIORGS-390 Implement base components and hooks for banking information (no logic) * UIORGS-390 Implement logic for banking information management * UIORGS-390 add hook to get categories * UIORGS-390 Add categories options to the form; fix issues * UIORGS-390 Update label for address category * UIORGS-390 use translated categories * UIORGS-390 Implement event emmiter to handle address categories change * UIORGS-390 Update changelog * Fix countries sorting * update tests * fix code smells * UIORGS-390 Add unit tests * add more test * UIORGS-390 add tests to cover categories assignement logic * UIORGS-390 Temporarily include banking info perms into common sets --- CHANGELOG.md | 1 + package.json | 6 + .../OrganizationCreate/OrganizationCreate.js | 39 +- .../OrganizationCreate.test.js | 42 +- .../OrganizationEdit/OrganizationEdit.js | 43 +- .../OrganizationEdit/OrganizationEdit.test.js | 55 +- .../BankingInformationField.js | 128 +++ .../BankingInformationField.test.js | 42 + .../BankingInformationField/index.js | 1 + .../BankingInformationFieldArray.js | 47 + .../BankingInformationFieldArray.test.js | 39 + .../BankingInformationFieldArray/index.js | 1 + .../OrganizationBankingInfoForm.js | 68 ++ .../OrganizationBankingInfoForm.test.js | 126 +++ .../OrganizationBankingInfoForm/index.js | 1 + .../OrganizationContactInfoForm.test.js.snap | 972 +++++++++--------- .../OrganizationForm/OrganizationForm.js | 16 +- .../OrganizationForm/OrganizationForm.test.js | 35 +- .../getAddressCategoryIdsSet.js | 9 + .../getAddressCategoryIdsSet.test.js | 13 + src/Organizations/constants.js | 5 +- .../useBankingInformationManager.js | 70 ++ .../useBankingInformationManager.test.js | 103 ++ .../BankingAccountTypeSettings.js | 3 +- .../BankingInformationSettings.js | 14 +- .../BankingInformationSettings.test.js | 46 +- src/Settings/SettingsPage.js | 13 +- src/Settings/SettingsPage.test.js | 21 +- src/Settings/constants.js | 8 - src/Settings/hooks/index.js | 1 - src/Settings/hooks/useBankingInformation.js | 35 - .../CategoryDropdown/CategoryDropdown.js | 23 +- .../CategoryDropdown/CategoryDropdown.test.js | 27 +- .../components/AddressInfo/AddressInfo.js | 25 +- src/common/constants/api.js | 5 +- src/common/constants/events.js | 3 + src/common/constants/index.js | 1 + src/common/constants/organization.js | 1 + src/common/hooks/index.js | 6 + .../hooks/useBankingAccountTypes/index.js | 1 + .../useBankingAccountTypes.js | 40 + .../useBankingAccountTypes.test.js | 37 + .../useBankingInformationMutation/index.js | 1 + .../useBankingInformationMutation.js | 52 + .../useBankingInformationMutation.test.js | 83 ++ .../useBankingInformationSettings/index.js | 1 + .../useBankingInformationSettings.js | 46 + .../useBankingInformationSettings.test.js} | 19 +- src/common/hooks/useCategories/index.js | 1 + .../hooks/useCategories/useCategories.js | 41 + .../hooks/useCategories/useCategories.test.js | 37 + src/common/hooks/useEventEmitter/index.js | 1 + .../hooks/useEventEmitter/useEventEmitter.js | 7 + .../useEventEmitter/useEventEmitter.test.js | 12 + .../index.js | 1 + .../useOrganizationBankingInformation.js | 47 + .../useOrganizationBankingInformation.test.js | 43 + src/common/utils/EventEmitter/EventEmitter.js | 19 + .../utils/EventEmitter/EventEmitter.test.js | 36 + src/common/utils/EventEmitter/index.js | 1 + src/common/utils/createAddNewItem.js | 1 - .../getArrayItemsChanges.js | 39 + .../getArrayItemsChanges.test.js | 122 +++ .../utils/getArrayItemsChanges/index.js | 1 + src/common/utils/index.js | 2 + .../__snapshots__/EditContact.test.js.snap | 972 +++++++++--------- .../ViewContact/ViewContactContainer.test.js | 7 +- translations/ui-organizations/en.json | 10 + 68 files changed, 2635 insertions(+), 1139 deletions(-) create mode 100644 src/Organizations/OrganizationForm/OrganizationBankingInfoForm/BankingInformationField/BankingInformationField.js create mode 100644 src/Organizations/OrganizationForm/OrganizationBankingInfoForm/BankingInformationField/BankingInformationField.test.js create mode 100644 src/Organizations/OrganizationForm/OrganizationBankingInfoForm/BankingInformationField/index.js create mode 100644 src/Organizations/OrganizationForm/OrganizationBankingInfoForm/BankingInformationFieldArray/BankingInformationFieldArray.js create mode 100644 src/Organizations/OrganizationForm/OrganizationBankingInfoForm/BankingInformationFieldArray/BankingInformationFieldArray.test.js create mode 100644 src/Organizations/OrganizationForm/OrganizationBankingInfoForm/BankingInformationFieldArray/index.js create mode 100644 src/Organizations/OrganizationForm/OrganizationBankingInfoForm/OrganizationBankingInfoForm.js create mode 100644 src/Organizations/OrganizationForm/OrganizationBankingInfoForm/OrganizationBankingInfoForm.test.js create mode 100644 src/Organizations/OrganizationForm/OrganizationBankingInfoForm/index.js create mode 100644 src/Organizations/OrganizationForm/getAddressCategoryIdsSet.js create mode 100644 src/Organizations/OrganizationForm/getAddressCategoryIdsSet.test.js create mode 100644 src/Organizations/useBankingInformationManager.js create mode 100644 src/Organizations/useBankingInformationManager.test.js delete mode 100644 src/Settings/constants.js delete mode 100644 src/Settings/hooks/index.js delete mode 100644 src/Settings/hooks/useBankingInformation.js create mode 100644 src/common/constants/events.js create mode 100644 src/common/hooks/useBankingAccountTypes/index.js create mode 100644 src/common/hooks/useBankingAccountTypes/useBankingAccountTypes.js create mode 100644 src/common/hooks/useBankingAccountTypes/useBankingAccountTypes.test.js create mode 100644 src/common/hooks/useBankingInformationMutation/index.js create mode 100644 src/common/hooks/useBankingInformationMutation/useBankingInformationMutation.js create mode 100644 src/common/hooks/useBankingInformationMutation/useBankingInformationMutation.test.js create mode 100644 src/common/hooks/useBankingInformationSettings/index.js create mode 100644 src/common/hooks/useBankingInformationSettings/useBankingInformationSettings.js rename src/{Settings/hooks/useBankingInformation.test.js => common/hooks/useBankingInformationSettings/useBankingInformationSettings.test.js} (62%) create mode 100644 src/common/hooks/useCategories/index.js create mode 100644 src/common/hooks/useCategories/useCategories.js create mode 100644 src/common/hooks/useCategories/useCategories.test.js create mode 100644 src/common/hooks/useEventEmitter/index.js create mode 100644 src/common/hooks/useEventEmitter/useEventEmitter.js create mode 100644 src/common/hooks/useEventEmitter/useEventEmitter.test.js create mode 100644 src/common/hooks/useOrganizationBankingInformation/index.js create mode 100644 src/common/hooks/useOrganizationBankingInformation/useOrganizationBankingInformation.js create mode 100644 src/common/hooks/useOrganizationBankingInformation/useOrganizationBankingInformation.test.js create mode 100644 src/common/utils/EventEmitter/EventEmitter.js create mode 100644 src/common/utils/EventEmitter/EventEmitter.test.js create mode 100644 src/common/utils/EventEmitter/index.js create mode 100644 src/common/utils/getArrayItemsChanges/getArrayItemsChanges.js create mode 100644 src/common/utils/getArrayItemsChanges/getArrayItemsChanges.test.js create mode 100644 src/common/utils/getArrayItemsChanges/index.js diff --git a/CHANGELOG.md b/CHANGELOG.md index c3326e45..f7e5b9f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ * Designate Organization as donor. Refs UIORGS-383. * Settings for banking information. Refs UIORGS-391. +* Implement organization's banking information form. Refs UIORGS-390. ## [5.0.0](https://github.com/folio-org/ui-organizations/tree/v5.0.0) (2023-10-12) [Full Changelog](https://github.com/folio-org/ui-organizations/compare/v4.0.0...v5.0.0) diff --git a/package.json b/package.json index 158442d4..e2fbba66 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "home": "/organizations", "okapiInterfaces": { "acquisition-methods": "1.0", + "banking-information": "1.0", "data-export-spring": "1.0", "configuration": "2.0", "organizations.organizations": "1.0", @@ -80,6 +81,8 @@ "data-export.config.item.get", "orders.acquisition-methods.collection.get", "orders.acquisition-method.item.get", + "organizations.banking-information.collection.get", + "organizations.banking-information.item.get", "organizations.organizations.collection.get", "organizations.organizations.item.get", "organizations-storage.addresses.collection.get", @@ -108,6 +111,7 @@ "data-export.config.item.delete", "data-export.config.item.post", "data-export.config.item.put", + "organizations.banking-information.item.put", "organizations.organizations.item.put", "organizations-storage.addresses.item.put", "organizations-storage.emails.item.put", @@ -127,6 +131,7 @@ "displayName": "Organizations: View, edit, create", "visible": true, "subPermissions": [ + "organizations.banking-information.item.post", "organizations.organizations.item.post", "organizations-storage.addresses.item.post", "organizations-storage.emails.item.post", @@ -140,6 +145,7 @@ "displayName": "Organizations: View, edit, delete", "visible": true, "subPermissions": [ + "organizations.banking-information.item.delete", "organizations.organizations.item.delete", "organizations-storage.addresses.item.delete", "organizations-storage.emails.item.delete", diff --git a/src/Organizations/OrganizationCreate/OrganizationCreate.js b/src/Organizations/OrganizationCreate/OrganizationCreate.js index 24f5d6de..9d39c782 100644 --- a/src/Organizations/OrganizationCreate/OrganizationCreate.js +++ b/src/Organizations/OrganizationCreate/OrganizationCreate.js @@ -1,19 +1,17 @@ -import React, { useCallback } from 'react'; import PropTypes from 'prop-types'; -import { withRouter } from 'react-router-dom'; +import { useCallback, useMemo } from 'react'; import { useIntl } from 'react-intl'; +import { withRouter } from 'react-router-dom'; -import { - stripesConnect, -} from '@folio/stripes/core'; +import { stripesConnect } from '@folio/stripes/core'; import { useShowCallout } from '@folio/stripes-acq-components'; import { VIEW_ORG_DETAILS } from '../../common/constants'; import { organizationsResource } from '../../common/resources'; -import { - OrganizationForm, -} from '../OrganizationForm'; +import { BANKING_INFORMATION_FIELD_NAME } from '../constants'; import { handleSaveErrorResponse } from '../handleSaveErrorResponse'; +import { OrganizationForm } from '../OrganizationForm'; +import { useBankingInformationManager } from '../useBankingInformationManager'; const INITIAL_VALUES = { interfaces: [], @@ -32,6 +30,8 @@ const INITIAL_VALUES = { }; export const OrganizationCreate = ({ history, location, mutator }) => { + const { manageBankingInformation } = useBankingInformationManager(); + const cancelForm = useCallback( (id) => { history.push({ @@ -45,9 +45,21 @@ export const OrganizationCreate = ({ history, location, mutator }) => { const showCallout = useShowCallout(); const intl = useIntl(); + const createOrganization = useCallback( - (data) => { + (values, { getFieldState }) => { + const { [BANKING_INFORMATION_FIELD_NAME]: bankingInformation, ...data } = values; + return mutator.createOrganizationOrg.POST(data) + .then(async organization => { + await manageBankingInformation({ + initBankingInformation: getFieldState(BANKING_INFORMATION_FIELD_NAME)?.initial, + bankingInformation, + organization, + }); + + return organization; + }) .then(organization => { setTimeout(() => cancelForm(organization.id)); showCallout({ @@ -60,12 +72,17 @@ export const OrganizationCreate = ({ history, location, mutator }) => { }); }, // eslint-disable-next-line react-hooks/exhaustive-deps - [cancelForm, intl, showCallout], + [cancelForm, intl, manageBankingInformation, showCallout], ); + const initialValues = useMemo(() => ({ + [BANKING_INFORMATION_FIELD_NAME]: [], + ...INITIAL_VALUES, + }), []); + return ( diff --git a/src/Organizations/OrganizationCreate/OrganizationCreate.test.js b/src/Organizations/OrganizationCreate/OrganizationCreate.test.js index 1651446c..2ee3202c 100644 --- a/src/Organizations/OrganizationCreate/OrganizationCreate.test.js +++ b/src/Organizations/OrganizationCreate/OrganizationCreate.test.js @@ -1,13 +1,16 @@ -import React from 'react'; +import { QueryClient, QueryClientProvider } from 'react-query'; import { render, screen } from '@folio/jest-config-stripes/testing-library/react'; import { OrganizationForm } from '../OrganizationForm'; - +import { useBankingInformationManager } from '../useBankingInformationManager'; import { OrganizationCreate } from './OrganizationCreate'; jest.mock('../OrganizationForm', () => ({ OrganizationForm: jest.fn().mockReturnValue('OrganizationForm'), })); +jest.mock('../useBankingInformationManager', () => ({ + useBankingInformationManager: jest.fn(), +})); const mutatorMock = { createOrganizationOrg: { @@ -17,6 +20,18 @@ const mutatorMock = { const historyMock = { push: jest.fn(), }; + +const getFieldState = jest.fn(); +const manageBankingInformation = jest.fn(); + +const queryClient = new QueryClient(); + +const wrapper = ({ children }) => ( + + {children} + +); + const renderOrganizationCreate = (props) => render( render( mutator={mutatorMock} {...props} />, + { wrapper }, ); describe('OrganizationCreate', () => { beforeEach(() => { OrganizationForm.mockClear(); + getFieldState.mockClear(); historyMock.push.mockClear(); + manageBankingInformation.mockClear(); mutatorMock.createOrganizationOrg.POST.mockClear(); + + useBankingInformationManager + .mockClear() + .mockReturnValue({ manageBankingInformation }); }); it('should display organization form', () => { @@ -56,11 +78,23 @@ describe('OrganizationCreate', () => { expect(historyMock.push.mock.calls[0][0].pathname).toBe('/organizations/view/orgUid'); }); - it('should save organization', () => { + it('should save organization', async () => { mutatorMock.createOrganizationOrg.POST.mockReturnValue(Promise.resolve({ id: 'orgUid' })); renderOrganizationCreate(); - OrganizationForm.mock.calls[0][0].onSubmit({}); + await OrganizationForm.mock.calls[0][0].onSubmit({}, { getFieldState }); + + expect(mutatorMock.createOrganizationOrg.POST).toHaveBeenCalled(); + }); + + it('should handle banking information on form submit', async () => { + mutatorMock.createOrganizationOrg.POST.mockReturnValue(Promise.resolve({ id: 'orgUid' })); + + renderOrganizationCreate(); + + await OrganizationForm.mock.calls[0][0].onSubmit({}, { getFieldState }); + + expect(manageBankingInformation).toHaveBeenCalled(); }); }); diff --git a/src/Organizations/OrganizationEdit/OrganizationEdit.js b/src/Organizations/OrganizationEdit/OrganizationEdit.js index 326bef8a..ea531813 100644 --- a/src/Organizations/OrganizationEdit/OrganizationEdit.js +++ b/src/Organizations/OrganizationEdit/OrganizationEdit.js @@ -1,6 +1,7 @@ -import React, { +import { useCallback, useEffect, + useMemo, useState, } from 'react'; import { FormattedMessage, useIntl } from 'react-intl'; @@ -19,27 +20,35 @@ import { } from '@folio/stripes-acq-components'; import { VIEW_ORG_DETAILS } from '../../common/constants'; +import { useOrganizationBankingInformation } from '../../common/hooks'; import { organizationResourceByUrl } from '../../common/resources'; -import { - OrganizationForm, -} from '../OrganizationForm'; +import { BANKING_INFORMATION_FIELD_NAME } from '../constants'; +import { OrganizationForm } from '../OrganizationForm'; import { handleSaveErrorResponse } from '../handleSaveErrorResponse'; +import { useBankingInformationManager } from '../useBankingInformationManager'; export const OrganizationEdit = ({ match, history, location, mutator }) => { const organizationId = match.params.id; const [organization, setOrganization] = useState({}); - const [isLoading, setIsLoading] = useState(true); + const [isOrganizationLoading, setIsOrganizationLoading] = useState(true); const showCallout = useShowCallout(); const intl = useIntl(); + const { manageBankingInformation } = useBankingInformationManager(); + + const { + bankingInformation: bankingInformationData, + isLoading: isBankingInformationLoading, + } = useOrganizationBankingInformation(organizationId); + useEffect( () => { mutator.editOrganizationOrg.GET() .then(organizationsResponse => { setOrganization(organizationsResponse); }) - .finally(() => setIsLoading(false)); + .finally(() => setIsOrganizationLoading(false)); }, // eslint-disable-next-line react-hooks/exhaustive-deps [], @@ -58,8 +67,17 @@ export const OrganizationEdit = ({ match, history, location, mutator }) => { ); const updateOrganization = useCallback( - (data) => { + (values, { getFieldState }) => { + const { [BANKING_INFORMATION_FIELD_NAME]: bankingInformation, ...data } = values; + return mutator.editOrganizationOrg.PUT(data) + .then(() => { + return manageBankingInformation({ + initBankingInformation: getFieldState(BANKING_INFORMATION_FIELD_NAME)?.initial, + bankingInformation, + organization: values, + }); + }) .then(() => { setTimeout(cancelForm); showCallout({ @@ -72,9 +90,16 @@ export const OrganizationEdit = ({ match, history, location, mutator }) => { }); }, // eslint-disable-next-line react-hooks/exhaustive-deps - [cancelForm, intl, showCallout], + [cancelForm, intl, manageBankingInformation, showCallout], ); + const initialValues = useMemo(() => ({ + [BANKING_INFORMATION_FIELD_NAME]: bankingInformationData, + ...organization, + }), [organization, bankingInformationData]); + + const isLoading = isOrganizationLoading || isBankingInformationLoading; + if (isLoading) { return ( @@ -85,7 +110,7 @@ export const OrganizationEdit = ({ match, history, location, mutator }) => { return ( } diff --git a/src/Organizations/OrganizationEdit/OrganizationEdit.test.js b/src/Organizations/OrganizationEdit/OrganizationEdit.test.js index 5b7bd0cd..c5a9e576 100644 --- a/src/Organizations/OrganizationEdit/OrganizationEdit.test.js +++ b/src/Organizations/OrganizationEdit/OrganizationEdit.test.js @@ -1,18 +1,34 @@ -import React from 'react'; +import { QueryClient, QueryClientProvider } from 'react-query'; + import { render, screen } from '@folio/jest-config-stripes/testing-library/react'; +import { useOrganizationBankingInformation } from '../../common/hooks'; import { OrganizationForm } from '../OrganizationForm'; - +import { useBankingInformationManager } from '../useBankingInformationManager'; import { OrganizationEdit } from './OrganizationEdit'; +jest.mock('../../common/hooks', () => ({ + ...jest.requireActual('../../common/hooks'), + useOrganizationBankingInformation: jest.fn(), +})); jest.mock('../OrganizationForm', () => ({ OrganizationForm: jest.fn().mockReturnValue('OrganizationForm'), })); +jest.mock('../useBankingInformationManager', () => ({ + useBankingInformationManager: jest.fn(), +})); const organization = { name: 'Amazon', id: 'orgUid', }; + +const bankingInformation = [{ + id: 'banking-information-id', + bankName: 'bankName', + isPrimary: true, +}]; + const mutatorMock = { editOrganizationOrg: { GET: jest.fn(), @@ -27,6 +43,18 @@ const matchMock = { id: organization.id, }, }; + +const getFieldState = jest.fn(); +const manageBankingInformation = jest.fn(); + +const queryClient = new QueryClient(); + +const wrapper = ({ children }) => ( + + {children} + +); + const renderOrganizationEdit = (props) => render( render( mutator={mutatorMock} {...props} />, + { wrapper }, ); describe('OrganizationEdit', () => { beforeEach(() => { OrganizationForm.mockClear(); + getFieldState.mockClear(); historyMock.push.mockClear(); mutatorMock.editOrganizationOrg.GET.mockClear().mockReturnValue(Promise.resolve(organization)); mutatorMock.editOrganizationOrg.PUT.mockClear(); + + useOrganizationBankingInformation + .mockClear() + .mockReturnValue({ bankingInformation, isLoading: false }); + useBankingInformationManager + .mockClear() + .mockReturnValue({ manageBankingInformation }); }); it('should display organization form', async () => { @@ -70,7 +107,19 @@ describe('OrganizationEdit', () => { renderOrganizationEdit(); await screen.findByText('OrganizationForm'); + await OrganizationForm.mock.calls[0][0].onSubmit({}, { getFieldState }); + + expect(mutatorMock.editOrganizationOrg.PUT).toHaveBeenCalled(); + }); + + it('should handle banking information on form submit', async () => { + mutatorMock.editOrganizationOrg.PUT.mockReturnValue(Promise.resolve({ id: 'orgUid' })); + + renderOrganizationEdit(); + + await screen.findByText('OrganizationForm'); + await OrganizationForm.mock.calls[0][0].onSubmit({}, { getFieldState }); - OrganizationForm.mock.calls[0][0].onSubmit({}); + expect(manageBankingInformation).toHaveBeenCalled(); }); }); diff --git a/src/Organizations/OrganizationForm/OrganizationBankingInfoForm/BankingInformationField/BankingInformationField.js b/src/Organizations/OrganizationForm/OrganizationBankingInfoForm/BankingInformationField/BankingInformationField.js new file mode 100644 index 00000000..128113cd --- /dev/null +++ b/src/Organizations/OrganizationForm/OrganizationBankingInfoForm/BankingInformationField/BankingInformationField.js @@ -0,0 +1,128 @@ +import PropTypes from 'prop-types'; +import { useMemo } from 'react'; +import { Field, useForm } from 'react-final-form'; +import { FormattedMessage } from 'react-intl'; + +import { + Card, + Col, + Row, + TextField, +} from '@folio/stripes/components'; +import { FieldSelectionFinal } from '@folio/stripes-acq-components'; + +import { FieldIsPrimary } from '../../../../common/components'; +import { getAddressCategoryIdsSet } from '../../getAddressCategoryIdsSet'; + +export const BankingInformationField = ({ + bankingAccountTypeOptions, + categories, + fields, + index, + name, +}) => { + const { getFieldState } = useForm(); + + const initCategoryId = getFieldState(`${name}.categoryId`)?.initial; + const addresses = getFieldState('addresses')?.value; + const addressCategoryIdsSet = useMemo(() => { + return getAddressCategoryIdsSet(addresses); + }, [addresses]); + + const cardHeader = ( + + ); + + const categoriesOptions = useMemo(() => { + return categories.reduce((acc, { id, value }) => { + if (addressCategoryIdsSet.has(id) || id === initCategoryId) { + acc.push({ label: value, value: id }); + } + + return acc; + }, []); + }, [addressCategoryIdsSet, categories, initCategoryId]); + + return ( + + + + } + name={`${name}.bankName`} + component={TextField} + fullWidth + validateFields={[]} + /> + + + } + name={`${name}.bankAccountNumber`} + component={TextField} + fullWidth + validateFields={[]} + /> + + + } + name={`${name}.transitNumber`} + component={TextField} + fullWidth + validateFields={[]} + /> + + + } + name={`${name}.categoryId`} + dataOptions={categoriesOptions} + validateFields={[]} + /> + + + } + name={`${name}.accountTypeId`} + dataOptions={bankingAccountTypeOptions} + fullWidth + validateFields={[]} + /> + + + } + name={`${name}.notes`} + id={`${name}.notes`} + component={TextField} + fullWidth + validateFields={[]} + /> + + + + ); +}; + +BankingInformationField.propTypes = { + bankingAccountTypeOptions: PropTypes.arrayOf(PropTypes.shape({ + label: PropTypes.string, + value: PropTypes.string, + })).isRequired, + categories: PropTypes.arrayOf(PropTypes.shape({ + id: PropTypes.string, + value: PropTypes.string, + })).isRequired, + fields: PropTypes.object.isRequired, + index: PropTypes.number.isRequired, + name: PropTypes.string.isRequired, +}; diff --git a/src/Organizations/OrganizationForm/OrganizationBankingInfoForm/BankingInformationField/BankingInformationField.test.js b/src/Organizations/OrganizationForm/OrganizationBankingInfoForm/BankingInformationField/BankingInformationField.test.js new file mode 100644 index 00000000..32af4dea --- /dev/null +++ b/src/Organizations/OrganizationForm/OrganizationBankingInfoForm/BankingInformationField/BankingInformationField.test.js @@ -0,0 +1,42 @@ +import { Form } from 'react-final-form'; + +import { render, screen } from '@folio/jest-config-stripes/testing-library/react'; + +import { BankingInformationField } from './BankingInformationField'; + +const defaultProps = { + bankingAccountTypeOptions: [], + categories: [], + fields: { forEach: jest.fn }, + index: 3, + name: 'bankingInfo[3]', +}; + +const wrapper = ({ children }) => ( +
children} + /> +); + +const renderBankingInformationField = (props = {}) => render( + , + { wrapper }, +); + +describe('BankingInformationField', () => { + it('should render banking information item fields', () => { + renderBankingInformationField(); + + expect(screen.getByText('ui-organizations.data.bankingInformation.isPrimary')).toBeInTheDocument(); + expect(screen.getByText('ui-organizations.data.bankingInformation.bankName')).toBeInTheDocument(); + expect(screen.getByText('ui-organizations.data.bankingInformation.bankAccountNumber')).toBeInTheDocument(); + expect(screen.getByText('ui-organizations.data.bankingInformation.transitNumber')).toBeInTheDocument(); + expect(screen.getByText('ui-organizations.data.bankingInformation.addressCategory')).toBeInTheDocument(); + expect(screen.getByText('ui-organizations.data.bankingInformation.accountType')).toBeInTheDocument(); + expect(screen.getByText('ui-organizations.data.bankingInformation.notes')).toBeInTheDocument(); + }); +}); diff --git a/src/Organizations/OrganizationForm/OrganizationBankingInfoForm/BankingInformationField/index.js b/src/Organizations/OrganizationForm/OrganizationBankingInfoForm/BankingInformationField/index.js new file mode 100644 index 00000000..70a06bd3 --- /dev/null +++ b/src/Organizations/OrganizationForm/OrganizationBankingInfoForm/BankingInformationField/index.js @@ -0,0 +1 @@ +export { BankingInformationField } from './BankingInformationField'; diff --git a/src/Organizations/OrganizationForm/OrganizationBankingInfoForm/BankingInformationFieldArray/BankingInformationFieldArray.js b/src/Organizations/OrganizationForm/OrganizationBankingInfoForm/BankingInformationFieldArray/BankingInformationFieldArray.js new file mode 100644 index 00000000..641f9189 --- /dev/null +++ b/src/Organizations/OrganizationForm/OrganizationBankingInfoForm/BankingInformationFieldArray/BankingInformationFieldArray.js @@ -0,0 +1,47 @@ +import PropTypes from 'prop-types'; +import { useEffect } from 'react'; +import { useForm } from 'react-final-form'; + +import { RepeatableFieldWithValidation } from '@folio/stripes-acq-components'; + +import { EVENT_EMITTER_EVENTS } from '../../../../common/constants'; +import { useEventEmitter } from '../../../../common/hooks'; +import { getAddressCategoryIdsSet } from '../../getAddressCategoryIdsSet'; + +export const BankingInformationFieldArray = (props) => { + const { fields } = props; + const eventEmitter = useEventEmitter(); + const { change, getFieldState } = useForm(); + + /* + Handles organization addresses categories change. + Resets banking information address category fields without initial value. + */ + useEffect(() => { + const eventType = EVENT_EMITTER_EVENTS.ADDRESS_CATEGORY_CHANGED; + const callback = () => { + const addressesCategoriesIdsMap = getAddressCategoryIdsSet(getFieldState('addresses').value); + + fields.forEach(field => { + const fieldName = `${field}.categoryId`; + const { initial, value } = getFieldState(fieldName); + + if (!addressesCategoriesIdsMap.has(value) && value !== initial) { + change(fieldName, undefined); + } + }); + }; + + eventEmitter.on(eventType, callback); + + return () => { + eventEmitter.off(eventType, callback); + }; + }, [change, eventEmitter, fields, getFieldState]); + + return ; +}; + +BankingInformationFieldArray.propTypes = { + fields: PropTypes.object.isRequired, +}; diff --git a/src/Organizations/OrganizationForm/OrganizationBankingInfoForm/BankingInformationFieldArray/BankingInformationFieldArray.test.js b/src/Organizations/OrganizationForm/OrganizationBankingInfoForm/BankingInformationFieldArray/BankingInformationFieldArray.test.js new file mode 100644 index 00000000..d58854d0 --- /dev/null +++ b/src/Organizations/OrganizationForm/OrganizationBankingInfoForm/BankingInformationFieldArray/BankingInformationFieldArray.test.js @@ -0,0 +1,39 @@ +import { MemoryRouter } from 'react-router-dom'; + +import { render, screen } from '@folio/jest-config-stripes/testing-library/react'; +import stripesFinalForm from '@folio/stripes/final-form'; + +import { BankingInformationFieldArray } from './BankingInformationFieldArray'; + +jest.mock('@folio/stripes-acq-components', () => ({ + ...jest.requireActual('@folio/stripes-acq-components'), + RepeatableFieldWithValidation: jest.fn(() => 'RepeatableFieldWithValidation'), +})); + +const FormWrapper = stripesFinalForm({ + keepDirtyOnReinitialize: true, + navigationCheck: true, + subscription: { values: true }, + validateOnBlur: true, +})(({ children }) => {children}); + +const wrapper = ({ children }) => ( + + + {children} + + +); + +const renderBankingInformationFieldArray = (props = {}) => render( + , + { wrapper }, +); + +describe('OrganizationBankingInfoForm', () => { + it('should render RepeatableFieldWithValidation', async () => { + renderBankingInformationFieldArray(); + + expect(screen.getByText('RepeatableFieldWithValidation')).toBeInTheDocument(); + }); +}); diff --git a/src/Organizations/OrganizationForm/OrganizationBankingInfoForm/BankingInformationFieldArray/index.js b/src/Organizations/OrganizationForm/OrganizationBankingInfoForm/BankingInformationFieldArray/index.js new file mode 100644 index 00000000..84e0f493 --- /dev/null +++ b/src/Organizations/OrganizationForm/OrganizationBankingInfoForm/BankingInformationFieldArray/index.js @@ -0,0 +1 @@ +export { BankingInformationFieldArray } from './BankingInformationFieldArray'; diff --git a/src/Organizations/OrganizationForm/OrganizationBankingInfoForm/OrganizationBankingInfoForm.js b/src/Organizations/OrganizationForm/OrganizationBankingInfoForm/OrganizationBankingInfoForm.js new file mode 100644 index 00000000..62e253ca --- /dev/null +++ b/src/Organizations/OrganizationForm/OrganizationBankingInfoForm/OrganizationBankingInfoForm.js @@ -0,0 +1,68 @@ +import { useMemo } from 'react'; +import { FieldArray } from 'react-final-form-arrays'; +import { FormattedMessage } from 'react-intl'; + +import { Loading } from '@folio/stripes/components'; + +import { + useBankingAccountTypes, + useCategories, +} from '../../../common/hooks'; +import { + createAddNewItem, + removeItem, +} from '../../../common/utils'; +import { validatePrimary } from '../../../common/validation'; +import { BANKING_INFORMATION_FIELD_NAME } from '../../constants'; +import { BankingInformationField } from './BankingInformationField'; +import { BankingInformationFieldArray } from './BankingInformationFieldArray'; + +const renderField = (props) => (name, index, fields) => ( + +); + +export const OrganizationBankingInfoForm = () => { + const { + bankingAccountTypes, + isFetching: isBankingAccountTypesFetching, + } = useBankingAccountTypes(); + + const { + categories, + isFetching: isCategoriesFetching, + } = useCategories(); + + const bankingAccountTypeOptions = useMemo(() => { + return bankingAccountTypes.map(({ id, name }) => ({ + label: name, + value: id, + })); + }, [bankingAccountTypes]); + + const isLoading = isBankingAccountTypesFetching || isCategoriesFetching; + + if (isLoading) { + return ; + } + + return ( + } + component={BankingInformationFieldArray} + id="bankingInformation" + name={BANKING_INFORMATION_FIELD_NAME} + onAdd={createAddNewItem()} + onRemove={removeItem} + renderField={renderField({ + bankingAccountTypeOptions, + categories, + })} + validate={validatePrimary} + /> + ); +}; diff --git a/src/Organizations/OrganizationForm/OrganizationBankingInfoForm/OrganizationBankingInfoForm.test.js b/src/Organizations/OrganizationForm/OrganizationBankingInfoForm/OrganizationBankingInfoForm.test.js new file mode 100644 index 00000000..c3a5d269 --- /dev/null +++ b/src/Organizations/OrganizationForm/OrganizationBankingInfoForm/OrganizationBankingInfoForm.test.js @@ -0,0 +1,126 @@ +import { FieldArray } from 'react-final-form-arrays'; +import { MemoryRouter } from 'react-router-dom'; + +import user from '@folio/jest-config-stripes/testing-library/user-event'; +import { + act, + render, + renderHook, + screen, + within, +} from '@folio/jest-config-stripes/testing-library/react'; +import stripesFinalForm from '@folio/stripes/final-form'; +import { RepeatableFieldWithValidation } from '@folio/stripes-acq-components'; + +import { EVENT_EMITTER_EVENTS } from '../../../common/constants'; +import { + useBankingAccountTypes, + useCategories, + useEventEmitter, +} from '../../../common/hooks'; +import CategoryDropdown from '../../../Utils/CategoryDropdown'; +import { OrganizationBankingInfoForm } from './OrganizationBankingInfoForm'; + +jest.mock('../../../common/hooks', () => ({ + ...jest.requireActual('../../../common/hooks'), + useBankingAccountTypes: jest.fn(), + useCategories: jest.fn(), +})); + +let form; + +const bankingAccountTypes = [ + { id: '1', name: 'First banking account type' }, + { id: '2', name: 'Second banking account type' }, +]; +const categories = [ + { id: '1', value: 'First category' }, + { id: '2', value: 'Second category' }, +]; +const addresses = [{ id: 'address-id', categories: categories.map(({ id }) => id) }]; +const initialFormValues = { addresses }; + +const FormWrapper = stripesFinalForm({ + keepDirtyOnReinitialize: true, + navigationCheck: true, + subscription: { values: true }, + validateOnBlur: true, +})(({ children, ...props }) => { + form = props.form; + + return
{children}
; +}); + +const renderOrganizationBankingInfoForm = (props = {}, initialValues = initialFormValues) => render( + + <> + ( + + )} + /> + + + , + { wrapper: MemoryRouter }, +); + +const addField = async () => user.click(await screen.findByRole('button', { name: 'ui-organizations.button.bankingInformation.add' })); + +describe('OrganizationBankingInfoForm', () => { + beforeEach(() => { + useBankingAccountTypes + .mockClear() + .mockReturnValue({ isFetching: false, bankingAccountTypes }); + useCategories + .mockClear() + .mockReturnValue({ isFetching: false, categories }); + }); + + it('should provide banking account types options for the related field', async () => { + renderOrganizationBankingInfoForm(); + + await addField(); + + bankingAccountTypes.forEach(({ name }) => { + expect(screen.getByText(name)).toBeInTheDocument(); + }); + }); + + describe('Interaction with \'Addresses\' categories fields', () => { + it('should render categories options based on selected address categories', async () => { + renderOrganizationBankingInfoForm(); + + await addField(); + + categories.forEach(({ value }) => { + expect(within(screen.getByTestId('banking-information-card')).getByText(value)).toBeInTheDocument(); + }); + }); + + it('should handle change address categories event', async () => { + const { result } = renderHook(() => useEventEmitter()); + + renderOrganizationBankingInfoForm(); + + act(() => { + form.change('addresses[0].categories', []); + result.current.emit(EVENT_EMITTER_EVENTS.ADDRESS_CATEGORY_CHANGED); + }); + + await addField(); + + categories.forEach(({ value }) => { + expect(within(screen.getByTestId('banking-information-card')).queryByText(value)).not.toBeInTheDocument(); + }); + }); + }); +}); diff --git a/src/Organizations/OrganizationForm/OrganizationBankingInfoForm/index.js b/src/Organizations/OrganizationForm/OrganizationBankingInfoForm/index.js new file mode 100644 index 00000000..0538aaeb --- /dev/null +++ b/src/Organizations/OrganizationForm/OrganizationBankingInfoForm/index.js @@ -0,0 +1 @@ +export { OrganizationBankingInfoForm } from './OrganizationBankingInfoForm'; diff --git a/src/Organizations/OrganizationForm/OrganizationContactInfoForm/__snapshots__/OrganizationContactInfoForm.test.js.snap b/src/Organizations/OrganizationForm/OrganizationContactInfoForm/__snapshots__/OrganizationContactInfoForm.test.js.snap index 387065b3..b527f1b4 100644 --- a/src/Organizations/OrganizationForm/OrganizationContactInfoForm/__snapshots__/OrganizationContactInfoForm.test.js.snap +++ b/src/Organizations/OrganizationForm/OrganizationContactInfoForm/__snapshots__/OrganizationContactInfoForm.test.js.snap @@ -299,7 +299,7 @@ exports[`OrganizationContactInfoForm should render correct structure with define class="optionSegment" data-test-selection-option-segment="true" > - stripes-components.countries.US + US @@ -332,7 +332,7 @@ exports[`OrganizationContactInfoForm should render correct structure with define class="selectionFilterContainer" > - stripes-components.countries.AF + AD
  • - stripes-components.countries.AX + AE
  • - stripes-components.countries.AL + AF
  • - stripes-components.countries.DZ + AG
  • - stripes-components.countries.AS + AI
  • - stripes-components.countries.AD + AL
  • - stripes-components.countries.AO + AM
  • - stripes-components.countries.AI + AN
  • - stripes-components.countries.AQ + AO
  • - stripes-components.countries.AG + AQ
  • - stripes-components.countries.AR + AR
  • - stripes-components.countries.AM + AS
  • - stripes-components.countries.AW + AT
  • - stripes-components.countries.AU + AU
  • - stripes-components.countries.AT + AW
  • - stripes-components.countries.AZ + AX
  • - stripes-components.countries.BS + AZ
  • - stripes-components.countries.BH + BA
  • - stripes-components.countries.BD + BB
  • - stripes-components.countries.BB + BD
  • - stripes-components.countries.BY + BE
  • - stripes-components.countries.BE + BF
  • - stripes-components.countries.BZ + BG
  • - stripes-components.countries.BJ + BH
  • - stripes-components.countries.BM + BI
  • - stripes-components.countries.BT + BJ
  • - stripes-components.countries.BO + BL
  • - stripes-components.countries.BA + BM
  • - stripes-components.countries.BW + BN
  • - stripes-components.countries.BV + BO
  • - stripes-components.countries.BR + BR
  • - stripes-components.countries.VG + BS
  • - stripes-components.countries.IO + BT
  • - stripes-components.countries.BN + BV
  • - stripes-components.countries.BG + BW
  • - stripes-components.countries.BF + BY
  • - stripes-components.countries.BI + BZ
  • - stripes-components.countries.KH + CA
  • - stripes-components.countries.CM + CC
  • - stripes-components.countries.CA + CD
  • - stripes-components.countries.CV + CF
  • - stripes-components.countries.KY + CG
  • - stripes-components.countries.CF + CH
  • - stripes-components.countries.TD + CI
  • - stripes-components.countries.CL + CK
  • - stripes-components.countries.CN + CL
  • - stripes-components.countries.HK + CM
  • - stripes-components.countries.MO + CN
  • - stripes-components.countries.CX + CO
  • - stripes-components.countries.CC + CR
  • - stripes-components.countries.CO + CU
  • - stripes-components.countries.KM + CV
  • - stripes-components.countries.CG + CX
  • - stripes-components.countries.CD + CY
  • - stripes-components.countries.CK + CZ
  • - stripes-components.countries.CR + DE
  • - stripes-components.countries.CI + DJ
  • - stripes-components.countries.HR + DK
  • - stripes-components.countries.CU + DM
  • - stripes-components.countries.CY + DO
  • - stripes-components.countries.CZ + DZ
  • - stripes-components.countries.DK + EC
  • - stripes-components.countries.DJ + EE
  • - stripes-components.countries.DM + EG
  • - stripes-components.countries.DO + EH
  • - stripes-components.countries.EC + ER
  • - stripes-components.countries.EG + ES
  • - stripes-components.countries.SV + ET
  • - stripes-components.countries.GQ + FI
  • - stripes-components.countries.ER + FJ
  • - stripes-components.countries.EE + FK
  • - stripes-components.countries.ET + FM
  • - stripes-components.countries.FK + FO
  • - stripes-components.countries.FO + FR
  • - stripes-components.countries.FJ + GA
  • - stripes-components.countries.FI + GB
  • - stripes-components.countries.FR + GD
  • - stripes-components.countries.GF + GE
  • - stripes-components.countries.PF + GF
  • - stripes-components.countries.TF + GG
  • - stripes-components.countries.GA + GH
  • - stripes-components.countries.GM + GI
  • - stripes-components.countries.GE + GL
  • - stripes-components.countries.DE + GM
  • - stripes-components.countries.GH + GN
  • - stripes-components.countries.GI + GP
  • - stripes-components.countries.GR + GQ
  • - stripes-components.countries.GL + GR
  • - stripes-components.countries.GD + GS
  • - stripes-components.countries.GP + GT
  • - stripes-components.countries.GU + GU
  • - stripes-components.countries.GT + GW
  • - stripes-components.countries.GG + GY
  • - stripes-components.countries.GN + HK
  • - stripes-components.countries.GW + HM
  • - stripes-components.countries.GY + HN
  • - stripes-components.countries.HT + HR
  • - stripes-components.countries.HM + HT
  • - stripes-components.countries.VA + HU
  • - stripes-components.countries.HN + ID
  • - stripes-components.countries.HU + IE
  • - stripes-components.countries.IS + IL
  • - stripes-components.countries.IN + IM
  • - stripes-components.countries.ID + IN
  • - stripes-components.countries.IR + IO
  • - stripes-components.countries.IQ + IQ
  • - stripes-components.countries.IE + IR
  • - stripes-components.countries.IM + IS
  • - stripes-components.countries.IL + IT
  • - stripes-components.countries.IT + JE
  • - stripes-components.countries.JM + JM
  • - stripes-components.countries.JP + JO
  • - stripes-components.countries.JE + JP
  • - stripes-components.countries.JO + KE
  • - stripes-components.countries.KZ + KG
  • - stripes-components.countries.KE + KH
  • - stripes-components.countries.KI + KI
  • - stripes-components.countries.KP + KM
  • - stripes-components.countries.KR + KN
  • - stripes-components.countries.KW + KP
  • - stripes-components.countries.KG + KR
  • - stripes-components.countries.LA + KW
  • - stripes-components.countries.LV + KY
  • - stripes-components.countries.LB + KZ
  • - stripes-components.countries.LS + LA
  • - stripes-components.countries.LR + LB
  • - stripes-components.countries.LY + LC
  • - stripes-components.countries.LI + LI
  • - stripes-components.countries.LT + LK
  • - stripes-components.countries.LU + LR
  • - stripes-components.countries.MK + LS
  • - stripes-components.countries.MG + LT
  • - stripes-components.countries.MW + LU
  • - stripes-components.countries.MY + LV
  • - stripes-components.countries.MV + LY
  • - stripes-components.countries.ML + MA
  • - stripes-components.countries.MT + MC
  • - stripes-components.countries.MH + MD
  • - stripes-components.countries.MQ + ME
  • - stripes-components.countries.MR + MF
  • - stripes-components.countries.MU + MG
  • - stripes-components.countries.YT + MH
  • - stripes-components.countries.MX + MK
  • - stripes-components.countries.FM + ML
  • - stripes-components.countries.MD + MM
  • - stripes-components.countries.MC + MN
  • - stripes-components.countries.MN + MO
  • - stripes-components.countries.ME + MP
  • - stripes-components.countries.MS + MQ
  • - stripes-components.countries.MA + MR
  • - stripes-components.countries.MZ + MS
  • - stripes-components.countries.MM + MT
  • - stripes-components.countries.NA + MU
  • - stripes-components.countries.NR + MV
  • - stripes-components.countries.NP + MW
  • - stripes-components.countries.NL + MX
  • - stripes-components.countries.AN + MY
  • - stripes-components.countries.NC + MZ
  • - stripes-components.countries.NZ + NA
  • - stripes-components.countries.NI + NC
  • - stripes-components.countries.NE + NE
  • - stripes-components.countries.NG + NF
  • - stripes-components.countries.NU + NG
  • - stripes-components.countries.NF + NI
  • - stripes-components.countries.MP + NL
  • - stripes-components.countries.NO + NO
  • - stripes-components.countries.OM + NP
  • - stripes-components.countries.PK + NR
  • - stripes-components.countries.PW + NU
  • - stripes-components.countries.PS + NZ
  • - stripes-components.countries.PA + OM
  • - stripes-components.countries.PG + PA
  • - stripes-components.countries.PY + PE
  • - stripes-components.countries.PE + PF
  • - stripes-components.countries.PH + PG
  • - stripes-components.countries.PN + PH
  • - stripes-components.countries.PL + PK
  • - stripes-components.countries.PT + PL
  • - stripes-components.countries.PR + PM
  • - stripes-components.countries.QA + PN
  • - stripes-components.countries.RE + PR
  • - stripes-components.countries.RO + PS
  • - stripes-components.countries.RU + PT
  • - stripes-components.countries.RW + PW
  • - stripes-components.countries.BL + PY
  • - stripes-components.countries.SH + QA
  • - stripes-components.countries.KN + RE
  • - stripes-components.countries.LC + RO
  • - stripes-components.countries.MF + RS
  • - stripes-components.countries.PM + RU
  • - stripes-components.countries.VC + RW
  • - stripes-components.countries.WS + SA
  • - stripes-components.countries.SM + SB
  • - stripes-components.countries.ST + SC
  • - stripes-components.countries.SA + SD
  • - stripes-components.countries.SN + SE
  • - stripes-components.countries.RS + SG
  • - stripes-components.countries.SC + SH
  • - stripes-components.countries.SL + SI
  • - stripes-components.countries.SG + SJ
  • - stripes-components.countries.SK + SK
  • - stripes-components.countries.SI + SL
  • - stripes-components.countries.SB + SM
  • - stripes-components.countries.SO + SN
  • - stripes-components.countries.ZA + SO
  • - stripes-components.countries.GS + SR
  • - stripes-components.countries.SS + SS
  • - stripes-components.countries.ES + ST
  • - stripes-components.countries.LK + SV
  • - stripes-components.countries.SD + SY
  • - stripes-components.countries.SR + SZ
  • - stripes-components.countries.SJ + TC
  • - stripes-components.countries.SZ + TD
  • - stripes-components.countries.SE + TF
  • - stripes-components.countries.CH + TG
  • - stripes-components.countries.SY + TH
  • - stripes-components.countries.TW + TJ
  • - stripes-components.countries.TJ + TK
  • - stripes-components.countries.TZ + TL
  • - stripes-components.countries.TH + TM
  • - stripes-components.countries.TL + TN
  • - stripes-components.countries.TG + TO
  • - stripes-components.countries.TK + TR
  • - stripes-components.countries.TO + TT
  • - stripes-components.countries.TT + TV
  • - stripes-components.countries.TN + TW
  • - stripes-components.countries.TR + TZ
  • - stripes-components.countries.TM + UA
  • - stripes-components.countries.TC + UG
  • - stripes-components.countries.TV + UM
  • - stripes-components.countries.UG + US
  • - stripes-components.countries.UA + UY
  • - stripes-components.countries.AE + UZ
  • - stripes-components.countries.GB + VA
  • - stripes-components.countries.US + VC
  • - stripes-components.countries.UM + VE
  • - stripes-components.countries.UY + VG
  • - stripes-components.countries.UZ + VI
  • - stripes-components.countries.VU + VN
  • - stripes-components.countries.VE + VU
  • - stripes-components.countries.VN + WF
  • - stripes-components.countries.VI + WS
  • - stripes-components.countries.WF + YE
  • - stripes-components.countries.EH + YT
  • - stripes-components.countries.YE + ZA
  • - stripes-components.countries.ZM + ZM
  • - stripes-components.countries.ZW + ZW
  • diff --git a/src/Organizations/OrganizationForm/OrganizationForm.js b/src/Organizations/OrganizationForm/OrganizationForm.js index e1d6bd4d..11826ddb 100644 --- a/src/Organizations/OrganizationForm/OrganizationForm.js +++ b/src/Organizations/OrganizationForm/OrganizationForm.js @@ -1,4 +1,3 @@ -import React from 'react'; import PropTypes from 'prop-types'; import { FormattedMessage } from 'react-intl'; import { useHistory } from 'react-router'; @@ -24,6 +23,8 @@ import { } from '@folio/stripes-acq-components'; import { ORGANIZATIONS_ROUTE } from '../../common/constants'; +import { useBankingInformationSettings } from '../../common/hooks'; +import { OrganizationBankingInfoForm } from './OrganizationBankingInfoForm'; import { OrganizationSummaryForm } from './OrganizationSummaryForm'; import { OrganizationContactInfoFormContainer } from './OrganizationContactInfoForm'; import { OrganizationContactPeopleForm } from './OrganizationContactPeopleForm'; @@ -54,6 +55,7 @@ const OrganizationForm = ({ [ORGANIZATION_SECTIONS.contactPeopleSection]: false, [ORGANIZATION_SECTIONS.interfacesSection]: false, [ORGANIZATION_SECTIONS.vendorInformationSection]: false, + [ORGANIZATION_SECTIONS.bankingInformationSection]: false, [ORGANIZATION_SECTIONS.vendorTermsSection]: false, [ORGANIZATION_SECTIONS.accountsSection]: false, }; @@ -69,6 +71,9 @@ const OrganizationForm = ({ : stateSections; const history = useHistory(); const { id, interfaces, contacts, metadata } = initialValues; + + const { enabled: isBankingInformationEnabled } = useBankingInformationSettings(); + const shortcuts = [ { name: 'cancel', @@ -216,6 +221,15 @@ const OrganizationForm = ({ accountFormValues={formValues.accounts} /> + + {isBankingInformationEnabled && ( + + + + )} ) } diff --git a/src/Organizations/OrganizationForm/OrganizationForm.test.js b/src/Organizations/OrganizationForm/OrganizationForm.test.js index 71c527bd..5a031cbf 100644 --- a/src/Organizations/OrganizationForm/OrganizationForm.test.js +++ b/src/Organizations/OrganizationForm/OrganizationForm.test.js @@ -1,3 +1,4 @@ +import { QueryClient, QueryClientProvider } from 'react-query'; import { MemoryRouter } from 'react-router-dom'; import { useHistory } from 'react-router'; @@ -16,6 +17,7 @@ import user from '@folio/jest-config-stripes/testing-library/user-event'; import { organizationTypes } from 'fixtures'; import { ORGANIZATIONS_ROUTE } from '../../common/constants'; +import { useBankingInformationSettings } from '../../common/hooks'; import OrganizationForm from './OrganizationForm'; jest.mock('react-router', () => ({ @@ -27,6 +29,10 @@ jest.mock('@folio/stripes-components/lib/Commander', () => ({ expandAllSections: jest.fn(), collapseAllSections: jest.fn(), })); +jest.mock('../../common/hooks', () => ({ + ...jest.requireActual('../../common/hooks'), + useBankingInformationSettings: jest.fn(), +})); jest.mock( './OrganizationSummaryForm', () => ({ OrganizationSummaryForm: () => 'OrganizationSummaryForm' }), @@ -55,6 +61,9 @@ jest.mock( './OrganizationAccountsForm', () => ({ OrganizationAccountsForm: () => 'OrganizationAccountsForm' }), ); +jest.mock('./OrganizationBankingInfoForm', () => ({ + OrganizationBankingInfoForm: () => 'OrganizationBankingInfoForm', +})); const queryAllByClass = queryHelpers.queryAllByAttribute.bind(null, 'class'); @@ -68,14 +77,27 @@ const defaultProps = { organizationTypes: organizationTypesMock, cancelForm: jest.fn(), }; + +const queryClient = new QueryClient(); + +const wrapper = ({ children }) => ( + + + {children} + + +); + const renderOrganizationForm = (props = defaultProps) => render( , - { wrapper: MemoryRouter }, + { wrapper }, ); describe('OrganizationForm', () => { beforeEach(() => { global.document.createRange = global.document.originalCreateRange; + + useBankingInformationSettings.mockClear().mockReturnValue({ enabled: false }); }); afterEach(() => { @@ -155,6 +177,17 @@ describe('OrganizationForm', () => { .length, ).toBe(sections.length); }); + + it('should render banking information form', () => { + useBankingInformationSettings.mockReturnValue({ enabled: true }); + + renderOrganizationForm({ + ...defaultProps, + initialValues: { isVendor: true }, + }); + + expect(screen.getByText('OrganizationBankingInfoForm')).toBeInTheDocument(); + }); }); describe('Shortcuts', () => { diff --git a/src/Organizations/OrganizationForm/getAddressCategoryIdsSet.js b/src/Organizations/OrganizationForm/getAddressCategoryIdsSet.js new file mode 100644 index 00000000..d10209e6 --- /dev/null +++ b/src/Organizations/OrganizationForm/getAddressCategoryIdsSet.js @@ -0,0 +1,9 @@ +import memoize from 'lodash/memoize'; + +export const getAddressCategoryIdsSet = memoize((addresses = []) => { + return addresses.reduce((acc, address) => { + address.categories?.forEach(categoryId => acc.add(categoryId)); + + return acc; + }, new Set()); +}); diff --git a/src/Organizations/OrganizationForm/getAddressCategoryIdsSet.test.js b/src/Organizations/OrganizationForm/getAddressCategoryIdsSet.test.js new file mode 100644 index 00000000..3f5b157b --- /dev/null +++ b/src/Organizations/OrganizationForm/getAddressCategoryIdsSet.test.js @@ -0,0 +1,13 @@ +import { getAddressCategoryIdsSet } from './getAddressCategoryIdsSet'; + +describe('getAddressCategoryIdsSet', () => { + it('should return a set of addresses categories', () => { + const addresses = [ + { categories: [1, 2, 3] }, + { categories: [2, 3, 4] }, + { categories: [1, 4, 5] }, + ]; + + expect(getAddressCategoryIdsSet(addresses).size).toEqual(5); + }); +}); diff --git a/src/Organizations/constants.js b/src/Organizations/constants.js index 457a9a5d..717e9b55 100644 --- a/src/Organizations/constants.js +++ b/src/Organizations/constants.js @@ -1,8 +1,8 @@ -import React from 'react'; import { FormattedMessage } from 'react-intl'; export const ORGANIZATION_SECTIONS = { summarySection: 'summarySection', + bankingInformationSection: 'bankingInformationSection', contactInformationSection: 'contactInformationSection', contactPeopleSection: 'contactPeopleSection', interfacesSection: 'interfacesSection', @@ -16,6 +16,7 @@ export const ORGANIZATION_SECTIONS = { export const ORGANIZATION_SECTION_LABELS = { [ORGANIZATION_SECTIONS.summarySection]: , + [ORGANIZATION_SECTIONS.bankingInformationSection]: , [ORGANIZATION_SECTIONS.contactInformationSection]: , [ORGANIZATION_SECTIONS.contactPeopleSection]: , [ORGANIZATION_SECTIONS.interfacesSection]: , @@ -41,3 +42,5 @@ export const MAP_FIELD_ACCORDION = { agreements: ORGANIZATION_SECTIONS.vendorTermsSection, accounts: ORGANIZATION_SECTIONS.accountsSection, }; + +export const BANKING_INFORMATION_FIELD_NAME = 'bankingInformation'; diff --git a/src/Organizations/useBankingInformationManager.js b/src/Organizations/useBankingInformationManager.js new file mode 100644 index 00000000..78a8ee85 --- /dev/null +++ b/src/Organizations/useBankingInformationManager.js @@ -0,0 +1,70 @@ +import chunk from 'lodash/chunk'; +import { useCallback } from 'react'; + +import { useShowCallout } from '@folio/stripes-acq-components'; + +import { + useBankingInformationMutation, + useBankingInformationSettings, +} from '../common/hooks'; +import { getArrayItemsChanges } from '../common/utils'; + +const executeSequentially = (fn, arr) => arr.reduce((acc, curr) => { + return acc.then(() => fn({ bankingInformation: curr })); +}, Promise.resolve()); + +const executeParallel = (fn, arr) => chunk(arr, 5).reduce((acc, chunked) => { + return acc.then(() => Promise.all(chunked.map((bankingInformation) => fn({ bankingInformation })))); +}, Promise.resolve()); + +export const useBankingInformationManager = () => { + const showCallout = useShowCallout(); + + const { enabled: isBankingInformationEnabled } = useBankingInformationSettings(); + + const { + createBankingInformation, + updateBankingInformation, + deleteBankingInformation, + isLoading, + } = useBankingInformationMutation(); + + const manageBankingInformation = useCallback(({ + initBankingInformation, + bankingInformation, + organization, + }) => { + if (!(organization.isVendor && isBankingInformationEnabled)) return Promise.resolve(); + + const { + created, + updated, + deleted, + } = getArrayItemsChanges(initBankingInformation, bankingInformation); + + return Promise.all([ + executeSequentially(createBankingInformation, created.map((item) => ({ + organizationId: organization.id, + ...item, + }))), + executeParallel(updateBankingInformation, updated), + executeParallel(deleteBankingInformation, deleted), + ]).catch(() => { + showCallout({ + type: 'error', + messageId: 'ui-organizations.bankingInformation.save.error', + }); + }); + }, [ + createBankingInformation, + deleteBankingInformation, + isBankingInformationEnabled, + showCallout, + updateBankingInformation, + ]); + + return { + manageBankingInformation, + isLoading, + }; +}; diff --git a/src/Organizations/useBankingInformationManager.test.js b/src/Organizations/useBankingInformationManager.test.js new file mode 100644 index 00000000..d88aa39b --- /dev/null +++ b/src/Organizations/useBankingInformationManager.test.js @@ -0,0 +1,103 @@ +import { renderHook } from '@folio/jest-config-stripes/testing-library/react'; + +import { organization } from 'fixtures'; +import { + useBankingInformationMutation, + useBankingInformationSettings, +} from '../common/hooks'; +import { useBankingInformationManager } from './useBankingInformationManager'; + +const mutationsMock = { + createBankingInformation: jest.fn(), + updateBankingInformation: jest.fn(), + deleteBankingInformation: jest.fn(), +}; + +jest.mock('../common/hooks', () => ({ + ...jest.requireActual('../common/hooks'), + useBankingInformationMutation: jest.fn(), + useBankingInformationSettings: jest.fn(), +})); + +const organizationId = organization.id; +const initBankingInformation = [ + { id: 1, bankName: 'Bank name 1', organizationId }, + { id: 2, bankName: 'Bank name 2', organizationId }, +]; +const bankingInformation = [ + { id: 1, bankName: 'Bank name 1 (Edited)', organizationId }, + { id: 3, bankName: 'Bank name 3' }, +]; + +describe('useBankingAccountTypes', () => { + beforeEach(() => { + Object + .values(mutationsMock) + .forEach(fn => fn.mockClear()); + useBankingInformationMutation + .mockClear() + .mockReturnValue(mutationsMock); + useBankingInformationSettings + .mockClear() + .mockReturnValue({ enabled: true }); + }); + + it('should handle banking information fields change', async () => { + const { result } = renderHook(() => useBankingInformationManager()); + const { manageBankingInformation } = result.current; + + await manageBankingInformation({ + initBankingInformation, + bankingInformation, + organization, + }); + + expect(mutationsMock.createBankingInformation).toHaveBeenCalledWith({ + bankingInformation: { + organizationId, + ...bankingInformation[1], + }, + }); + expect(mutationsMock.updateBankingInformation).toHaveBeenCalledWith({ + bankingInformation: bankingInformation[0], + }); + expect(mutationsMock.deleteBankingInformation).toHaveBeenCalledWith({ + bankingInformation: initBankingInformation[1], + }); + }); + + it('should return a resolved promise immediately if an organization is not a vendor', async () => { + const { result } = renderHook(() => useBankingInformationManager()); + const { manageBankingInformation } = result.current; + + await manageBankingInformation({ + initBankingInformation, + bankingInformation, + organization: { + ...organization, + isVendor: false, + }, + }); + + expect(mutationsMock.createBankingInformation).not.toHaveBeenCalled(); + expect(mutationsMock.deleteBankingInformation).not.toHaveBeenCalled(); + expect(mutationsMock.updateBankingInformation).not.toHaveBeenCalled(); + }); + + it('should return a resolved promise immediately if the banking information settings are disabled', async () => { + useBankingInformationSettings.mockReturnValue({ enabled: false }); + + const { result } = renderHook(() => useBankingInformationManager()); + const { manageBankingInformation } = result.current; + + await manageBankingInformation({ + initBankingInformation, + bankingInformation, + organization, + }); + + expect(mutationsMock.createBankingInformation).not.toHaveBeenCalled(); + expect(mutationsMock.deleteBankingInformation).not.toHaveBeenCalled(); + expect(mutationsMock.updateBankingInformation).not.toHaveBeenCalled(); + }); +}); diff --git a/src/Settings/BankingAccountTypeSettings/BankingAccountTypeSettings.js b/src/Settings/BankingAccountTypeSettings/BankingAccountTypeSettings.js index 0ffb2568..14b78f0b 100644 --- a/src/Settings/BankingAccountTypeSettings/BankingAccountTypeSettings.js +++ b/src/Settings/BankingAccountTypeSettings/BankingAccountTypeSettings.js @@ -1,11 +1,10 @@ -import React from 'react'; import { FormattedMessage } from 'react-intl'; import { getControlledVocabTranslations } from '@folio/stripes-acq-components'; import { useStripes } from '@folio/stripes/core'; import { ControlledVocab } from '@folio/stripes/smart-components'; -import { BANKING_ACCOUNT_TYPES_API } from '../constants'; +import { BANKING_ACCOUNT_TYPES_API } from '../../common/constants'; const setUniqValidation = (value, index, items) => { const errors = {}; diff --git a/src/Settings/BankingInformationSettings/BankingInformationSettings.js b/src/Settings/BankingInformationSettings/BankingInformationSettings.js index 5c45c571..614124ac 100644 --- a/src/Settings/BankingInformationSettings/BankingInformationSettings.js +++ b/src/Settings/BankingInformationSettings/BankingInformationSettings.js @@ -4,26 +4,24 @@ import { useShowCallout } from '@folio/stripes-acq-components'; import { Loading } from '@folio/stripes/components'; import { useOkapiKy } from '@folio/stripes/core'; -import { SETTINGS_API } from '../constants'; -import { useBankingInformation } from '../hooks'; +import { SETTINGS_API } from '../../common/constants'; +import { useBankingInformationSettings } from '../../common/hooks'; import BankingInformationSettingsForm from './BankingInformationSettingsForm'; const BankingInformationSettings = () => { const { enabled, - key, - id: bankingInformationId, - version, + bankingInformation, isLoading, refetch, - } = useBankingInformation(); + } = useBankingInformationSettings(); const ky = useOkapiKy(); const sendCallout = useShowCallout(); const onSubmit = async ({ value }) => { try { - await ky.put(`${SETTINGS_API}/${bankingInformationId}`, { - json: { value, key, _version: version }, + await ky.put(`${SETTINGS_API}/${bankingInformation.id}`, { + json: { ...bankingInformation, value }, }); refetch(); diff --git a/src/Settings/BankingInformationSettings/BankingInformationSettings.test.js b/src/Settings/BankingInformationSettings/BankingInformationSettings.test.js index 4bacedac..60d4d71b 100644 --- a/src/Settings/BankingInformationSettings/BankingInformationSettings.test.js +++ b/src/Settings/BankingInformationSettings/BankingInformationSettings.test.js @@ -1,29 +1,20 @@ import { MemoryRouter } from 'react-router-dom'; -import { - act, - render, - screen, -} from '@folio/jest-config-stripes/testing-library/react'; +import { render, screen } from '@folio/jest-config-stripes/testing-library/react'; import user from '@folio/jest-config-stripes/testing-library/user-event'; import { useOkapiKy } from '@folio/stripes/core'; -import { useBankingInformation } from '../hooks'; +import { useBankingInformationSettings } from '../../common/hooks'; import BankingInformationSettings from './BankingInformationSettings'; -const mockRefetch = jest.fn(); - jest.mock('@folio/stripes/components', () => ({ ...jest.requireActual('@folio/stripes/components'), Loading: () =>
    Loading
    , })); -jest.mock('../hooks', () => ({ - useBankingInformation: jest.fn(() => ({ - isLoading: false, - enabled: false, - refetch: mockRefetch, - })), +jest.mock('../../common/hooks', () => ({ + ...jest.requireActual('../../common/hooks'), + useBankingInformationSettings: jest.fn(), })); const renderBankingInformationSettings = () => render( @@ -31,7 +22,20 @@ const renderBankingInformationSettings = () => render( { wrapper: MemoryRouter }, ); +const mockRefetch = jest.fn(); +const bankingInformation = { id: 'banking-information-id' }; + describe('BankingInformationSettings component', () => { + beforeEach(() => { + useBankingInformationSettings + .mockClear() + .mockReturnValue({ + isLoading: false, + enabled: false, + refetch: mockRefetch, + }); + }); + it('should display pane headings', () => { renderBankingInformationSettings(); @@ -43,7 +47,7 @@ describe('BankingInformationSettings component', () => { }); it('should render Loading component', () => { - useBankingInformation.mockReturnValue({ + useBankingInformationSettings.mockReturnValue({ isLoading: true, enabled: false, }); @@ -54,7 +58,8 @@ describe('BankingInformationSettings component', () => { }); it('should save banking options', async () => { - useBankingInformation.mockClear().mockReturnValue({ + useBankingInformationSettings.mockClear().mockReturnValue({ + bankingInformation, isLoading: false, enabled: true, refetch: mockRefetch, @@ -71,13 +76,8 @@ describe('BankingInformationSettings component', () => { renderBankingInformationSettings(); - const checkbox = screen.getByRole('checkbox', { name: 'ui-organizations.settings.bankingInformation.enable' }); - const saveButton = screen.getByText('ui-organizations.settings.accountTypes.save.button'); - - await act(async () => { - await user.click(checkbox); - await user.click(saveButton); - }); + await user.click(await screen.findByRole('checkbox', { name: 'ui-organizations.settings.bankingInformation.enable' })); + await user.click(await screen.findByRole('button', { name: 'ui-organizations.settings.accountTypes.save.button' })); expect(mockPutMethod).toHaveBeenCalled(); }); diff --git a/src/Settings/SettingsPage.js b/src/Settings/SettingsPage.js index e422f927..5dd8ba63 100644 --- a/src/Settings/SettingsPage.js +++ b/src/Settings/SettingsPage.js @@ -1,14 +1,13 @@ -import React, { useMemo } from 'react'; +import { useMemo } from 'react'; import { FormattedMessage } from 'react-intl'; import { Settings } from '@folio/stripes/smart-components'; -import { Loading } from '@folio/stripes/components'; -import { useBankingInformation } from './hooks'; +import { useBankingInformationSettings } from '../common/hooks'; import { CategorySettings } from './CategorySettings'; import { TypeSettings } from './TypeSettings'; -import { BankingInformationSettings } from './BankingInformationSettings'; import { BankingAccountTypeSettings } from './BankingAccountTypeSettings'; +import { BankingInformationSettings } from './BankingInformationSettings'; const pages = [ { @@ -39,14 +38,10 @@ const bankingAccountTypesPage = { }; const SettingsPage = (props) => { - const { enabled, isLoading } = useBankingInformation(); + const { enabled } = useBankingInformationSettings(); const settingsPages = useMemo(() => (enabled ? pages.concat(bankingAccountTypesPage) : pages), [enabled]); - if (isLoading) { - return ; - } - return ( ({ ...jest.requireActual('@folio/stripes/components'), Loading: () =>
    Loading
    , })); -jest.mock('./hooks', () => ({ - useBankingInformation: jest.fn(() => ({ +jest.mock('../common/hooks', () => ({ + ...jest.requireActual('../common/hooks'), + useBankingInformationSettings: jest.fn(() => ({ isLoading: false, enabled: false, })), @@ -52,7 +52,7 @@ describe('SettingsPage', () => { }); it('should return banking account types link', async () => { - useBankingInformation.mockReturnValue({ + useBankingInformationSettings.mockReturnValue({ isLoading: false, enabled: true, }); @@ -61,15 +61,4 @@ describe('SettingsPage', () => { expect(screen.getByText('ui-organizations.settings.bankingAccountTypes')).toBeInTheDocument(); }); - - it('should display loading on fetching useBankingInformation', async () => { - useBankingInformation.mockReturnValue({ - isLoading: true, - enabled: false, - }); - - renderSettingsPage(); - - expect(screen.getByText('Loading')).toBeInTheDocument(); - }); }); diff --git a/src/Settings/constants.js b/src/Settings/constants.js deleted file mode 100644 index 56157dab..00000000 --- a/src/Settings/constants.js +++ /dev/null @@ -1,8 +0,0 @@ -export const SETTINGS_API = 'organizations-storage/settings'; -export const BANKING_ACCOUNT_TYPES_API = 'organizations-storage/banking-account-types'; - -export const BANKING_INFORMATION_ENABLED_QUERY_KEY = 'BANKING_INFORMATION_ENABLED'; -export const BANKING_INFORMATION_SEARCH_PARAMS = { - query: `key=${BANKING_INFORMATION_ENABLED_QUERY_KEY}`, - limit: 1, -}; diff --git a/src/Settings/hooks/index.js b/src/Settings/hooks/index.js deleted file mode 100644 index 2144f705..00000000 --- a/src/Settings/hooks/index.js +++ /dev/null @@ -1 +0,0 @@ -export { useBankingInformation } from './useBankingInformation'; diff --git a/src/Settings/hooks/useBankingInformation.js b/src/Settings/hooks/useBankingInformation.js deleted file mode 100644 index 23dce38d..00000000 --- a/src/Settings/hooks/useBankingInformation.js +++ /dev/null @@ -1,35 +0,0 @@ -import { get } from 'lodash'; -import { useQuery } from 'react-query'; - -import { - useNamespace, - useOkapiKy, -} from '@folio/stripes/core'; - -import { - BANKING_INFORMATION_SEARCH_PARAMS, - SETTINGS_API, -} from '../constants'; - -export const useBankingInformation = () => { - const ky = useOkapiKy(); - const [namespace] = useNamespace({ key: 'banking-information-settings' }); - - const { isLoading, data, refetch } = useQuery( - [namespace], - () => ky.get(SETTINGS_API, { - searchParams: BANKING_INFORMATION_SEARCH_PARAMS, - }).json(), - ); - - const bankingInformation = get(data, 'settings[0]', {}); - - return ({ - id: bankingInformation.id, - enabled: bankingInformation.value === 'true', - key: bankingInformation.key, - version: bankingInformation._version, - isLoading, - refetch, - }); -}; diff --git a/src/Utils/CategoryDropdown/CategoryDropdown.js b/src/Utils/CategoryDropdown/CategoryDropdown.js index 43c73a2a..ba5b7803 100644 --- a/src/Utils/CategoryDropdown/CategoryDropdown.js +++ b/src/Utils/CategoryDropdown/CategoryDropdown.js @@ -1,6 +1,7 @@ -import React, { useCallback, useMemo } from 'react'; +import find from 'lodash/find'; import PropTypes from 'prop-types'; -import { find } from 'lodash'; +import { useCallback, useMemo } from 'react'; +import { useForm } from 'react-final-form'; import { FormattedMessage } from 'react-intl'; import { OptionSegment } from '@folio/stripes/components'; @@ -8,7 +9,15 @@ import { FieldMultiSelectionFinal } from '@folio/stripes-acq-components'; import { filterCategories } from './utils'; -function CategoryDropdown({ dropdownVendorCategories, name, withLabel, ariaLabelledBy }) { +function CategoryDropdown({ + dropdownVendorCategories, + name, + withLabel, + ariaLabelledBy, + onChange: onChangeProp, +}) { + const { change } = useForm(); + const fieldName = name ? `${name}.categories` : 'categories'; const toString = useCallback((option) => ( option ? `${fieldName}-${option}` : option @@ -35,6 +44,12 @@ function CategoryDropdown({ dropdownVendorCategories, name, withLabel, ariaLabel return dropdownVendorCategories.map(item => item.id) || []; }, [dropdownVendorCategories]); + const onChange = useCallback((value) => { + change(fieldName, value); + + if (onChangeProp) onChangeProp(value); + }, [change, fieldName, onChangeProp]); + return ( : undefined} @@ -44,6 +59,7 @@ function CategoryDropdown({ dropdownVendorCategories, name, withLabel, ariaLabel itemToString={toString} formatter={formatter} filter={filterItems} + onChange={onChange} /> ); } @@ -53,6 +69,7 @@ CategoryDropdown.propTypes = { name: PropTypes.string, withLabel: PropTypes.bool, ariaLabelledBy: PropTypes.string, + onChange: PropTypes.func, }; CategoryDropdown.defaultProps = { diff --git a/src/Utils/CategoryDropdown/CategoryDropdown.test.js b/src/Utils/CategoryDropdown/CategoryDropdown.test.js index 6a401d64..bed45aee 100644 --- a/src/Utils/CategoryDropdown/CategoryDropdown.test.js +++ b/src/Utils/CategoryDropdown/CategoryDropdown.test.js @@ -1,23 +1,28 @@ -import React from 'react'; +import { Form } from 'react-final-form'; +import { MemoryRouter } from 'react-router-dom'; + import { render, screen } from '@folio/jest-config-stripes/testing-library/react'; import CategoryDropdown from './CategoryDropdown'; -jest.mock('react-final-form', () => ({ - // eslint-disable-next-line - Field: ({ component, ...rest }) => { - const Component = component; - - return ; - }, -})); - const categories = [ { id: 'category1', value: 'Main' }, { id: 'category2', value: 'Uncategorize' }, ]; -const renderCategoryDropdown = (props = {}) => render(); +const wrapper = ({ children }) => ( + +
    children} + /> + +); + +const renderCategoryDropdown = (props = {}) => render( + , + { wrapper }, +); describe('CategoryDropdown', () => { it('should display passed categories as options', () => { diff --git a/src/common/components/AddressInfo/AddressInfo.js b/src/common/components/AddressInfo/AddressInfo.js index 625956dd..edcd9ab2 100644 --- a/src/common/components/AddressInfo/AddressInfo.js +++ b/src/common/components/AddressInfo/AddressInfo.js @@ -1,9 +1,9 @@ -import React from 'react'; +import PropTypes from 'prop-types'; +import { useCallback, useMemo } from 'react'; import { FormattedMessage, injectIntl, } from 'react-intl'; -import PropTypes from 'prop-types'; import { Field } from 'react-final-form'; import { FieldArray } from 'react-final-form-arrays'; @@ -21,6 +21,8 @@ import { } from '@folio/stripes-acq-components'; import CategoryDropdown from '../../../Utils/CategoryDropdown'; +import { EVENT_EMITTER_EVENTS } from '../../constants'; +import { useEventEmitter } from '../../hooks'; import { createAddNewItem, removeItem, @@ -36,10 +38,20 @@ const AddressInfo = ({ dropdownVendorCategories, intl, }) => { - const countriesOptions = countries.map(c => ({ - label: intl.formatMessage({ id: `stripes-components.countries.${c.alpha2}` }), - value: c.alpha3, - })); + const eventEmitter = useEventEmitter(); + + const onCategoryChange = useCallback(() => { + eventEmitter.emit(EVENT_EMITTER_EVENTS.ADDRESS_CATEGORY_CHANGED); + }, [eventEmitter]); + + const countriesOptions = useMemo(() => ( + countries + .map(c => ({ + label: intl.formatDisplayName(c.alpha2, { type: 'region' }), + value: c.alpha3, + })) + .sort((a, b) => a.label.localeCompare(b.label)) + ), [intl]); // eslint-disable-next-line react/prop-types const Address = (name, index, fields) => { @@ -161,6 +173,7 @@ const AddressInfo = ({ ariaLabelledBy="addressFormCategoriesLabel" dropdownVendorCategories={dropdownVendorCategories} name={name} + onChange={onCategoryChange} /> diff --git a/src/common/constants/api.js b/src/common/constants/api.js index e4d3413e..a9055baa 100644 --- a/src/common/constants/api.js +++ b/src/common/constants/api.js @@ -1,7 +1,10 @@ +export const AGREEMENTS_API = 'erm/sas'; +export const BANKING_ACCOUNT_TYPES_API = 'organizations-storage/banking-account-types'; +export const BANKING_INFORMATION_API = 'organizations/banking-information'; export const CATEGORIES_API = 'organizations-storage/categories'; export const CONTACTS_API = 'organizations-storage/contacts'; export const INTERFACES_API = 'organizations-storage/interfaces'; +export const SETTINGS_API = 'organizations-storage/settings'; export const TYPES_API = 'organizations-storage/organization-types'; -export const AGREEMENTS_API = 'erm/sas'; export const MAX_LIMIT = 2147483647; diff --git a/src/common/constants/events.js b/src/common/constants/events.js new file mode 100644 index 00000000..78bbb388 --- /dev/null +++ b/src/common/constants/events.js @@ -0,0 +1,3 @@ +export const EVENT_EMITTER_EVENTS = { + ADDRESS_CATEGORY_CHANGED: 'ADDRESS_CATEGORY_CHANGED', +}; diff --git a/src/common/constants/index.js b/src/common/constants/index.js index 25a381e2..52453f15 100644 --- a/src/common/constants/index.js +++ b/src/common/constants/index.js @@ -1,5 +1,6 @@ export * from './api'; export * from './categories'; +export * from './events'; export * from './interfaces'; export * from './organization'; export * from './organizationTypes'; diff --git a/src/common/constants/organization.js b/src/common/constants/organization.js index 97e7a7d5..d20894e1 100644 --- a/src/common/constants/organization.js +++ b/src/common/constants/organization.js @@ -1,3 +1,4 @@ export { ORGANIZATION_STATUS } from '@folio/plugin-find-organization'; +export const BANKING_INFORMATION_ENABLED_KEY = 'BANKING_INFORMATION_ENABLED'; export const DICT_CATEGORIES = 'vendorCategories'; diff --git a/src/common/hooks/index.js b/src/common/hooks/index.js index 393e24a9..9b6c0fd4 100644 --- a/src/common/hooks/index.js +++ b/src/common/hooks/index.js @@ -1,6 +1,12 @@ export * from './useAcqMethods'; +export * from './useBankingAccountTypes'; +export * from './useBankingInformationMutation'; +export * from './useBankingInformationSettings'; +export * from './useCategories'; +export * from './useEventEmitter'; export * from './useIntegrationConfig'; export * from './useIntegrationConfigMutation'; export * from './useLinkedAgreements'; +export * from './useOrganizationBankingInformation'; export * from './useTranslatedCategories'; export * from './useTypes'; diff --git a/src/common/hooks/useBankingAccountTypes/index.js b/src/common/hooks/useBankingAccountTypes/index.js new file mode 100644 index 00000000..c1574cdd --- /dev/null +++ b/src/common/hooks/useBankingAccountTypes/index.js @@ -0,0 +1 @@ +export { useBankingAccountTypes } from './useBankingAccountTypes'; diff --git a/src/common/hooks/useBankingAccountTypes/useBankingAccountTypes.js b/src/common/hooks/useBankingAccountTypes/useBankingAccountTypes.js new file mode 100644 index 00000000..aec118d8 --- /dev/null +++ b/src/common/hooks/useBankingAccountTypes/useBankingAccountTypes.js @@ -0,0 +1,40 @@ +import { useQuery } from 'react-query'; + +import { + useNamespace, + useOkapiKy, +} from '@folio/stripes/core'; +import { LIMIT_MAX } from '@folio/stripes-acq-components'; + +import { BANKING_ACCOUNT_TYPES_API } from '../../constants'; + +const DEFAULT_DATA = []; + +export const useBankingAccountTypes = () => { + const ky = useOkapiKy(); + const [namespace] = useNamespace({ key: 'banking-account-types' }); + + const { + data, + isFetching, + isLoading, + refetch, + } = useQuery( + [namespace], + () => { + const searchParams = { + limit: LIMIT_MAX, + }; + + return ky.get(BANKING_ACCOUNT_TYPES_API, { searchParams }).json(); + }, + ); + + return ({ + bankingAccountTypes: data?.bankingAccountTypes || DEFAULT_DATA, + totalRecords: data?.totalRecords, + isFetching, + isLoading, + refetch, + }); +}; diff --git a/src/common/hooks/useBankingAccountTypes/useBankingAccountTypes.test.js b/src/common/hooks/useBankingAccountTypes/useBankingAccountTypes.test.js new file mode 100644 index 00000000..cb7eb2c6 --- /dev/null +++ b/src/common/hooks/useBankingAccountTypes/useBankingAccountTypes.test.js @@ -0,0 +1,37 @@ +import { QueryClient, QueryClientProvider } from 'react-query'; + +import { renderHook, waitFor } from '@folio/jest-config-stripes/testing-library/react'; +import { useOkapiKy } from '@folio/stripes/core'; + +import { useBankingAccountTypes } from './useBankingAccountTypes'; + +const bankingAccountTypes = [{ id: 'banking-account-type-id' }]; + +const queryClient = new QueryClient(); + +const wrapper = ({ children }) => ( + + {children} + +); + +const kyMock = { + get: jest.fn(() => ({ + json: () => Promise.resolve({ bankingAccountTypes }), + })), +}; + +describe('useBankingAccountTypes', () => { + beforeEach(() => { + kyMock.get.mockClear(); + useOkapiKy.mockClear().mockReturnValue(kyMock); + }); + + it('should fetch all banking account types', async () => { + const { result } = renderHook(() => useBankingAccountTypes(), { wrapper }); + + await waitFor(() => expect(result.current.isLoading).toBeFalsy()); + + expect(result.current.bankingAccountTypes).toEqual(bankingAccountTypes); + }); +}); diff --git a/src/common/hooks/useBankingInformationMutation/index.js b/src/common/hooks/useBankingInformationMutation/index.js new file mode 100644 index 00000000..5700e6a6 --- /dev/null +++ b/src/common/hooks/useBankingInformationMutation/index.js @@ -0,0 +1 @@ +export { useBankingInformationMutation } from './useBankingInformationMutation'; diff --git a/src/common/hooks/useBankingInformationMutation/useBankingInformationMutation.js b/src/common/hooks/useBankingInformationMutation/useBankingInformationMutation.js new file mode 100644 index 00000000..111e51fc --- /dev/null +++ b/src/common/hooks/useBankingInformationMutation/useBankingInformationMutation.js @@ -0,0 +1,52 @@ +import { useMutation } from 'react-query'; + +import { useOkapiKy } from '@folio/stripes/core'; + +import { BANKING_INFORMATION_API } from '../../constants'; + +export const useBankingInformationMutation = () => { + const ky = useOkapiKy(); + + const { + mutateAsync: createBankingInformation, + isLoading: isBankingInformationCreateLoading, + } = useMutation({ + mutationFn: ({ bankingInformation }) => { + return ky.post(BANKING_INFORMATION_API, { json: bankingInformation }).json(); + }, + }); + + const { + mutateAsync: updateBankingInformation, + isLoading: isBankingInformationUpdateLoading, + } = useMutation({ + mutationFn: ({ bankingInformation }) => { + return ky.put( + `${BANKING_INFORMATION_API}/${bankingInformation.id}`, + { json: bankingInformation }, + ).json(); + }, + }); + + const { + mutateAsync: deleteBankingInformation, + isLoading: isBankingInformationDeleteLoading, + } = useMutation({ + mutationFn: ({ bankingInformation }) => { + return ky.delete(`${BANKING_INFORMATION_API}/${bankingInformation.id}`).json(); + }, + }); + + const isLoading = ( + isBankingInformationCreateLoading + || isBankingInformationDeleteLoading + || isBankingInformationUpdateLoading + ); + + return { + createBankingInformation, + updateBankingInformation, + deleteBankingInformation, + isLoading, + }; +}; diff --git a/src/common/hooks/useBankingInformationMutation/useBankingInformationMutation.test.js b/src/common/hooks/useBankingInformationMutation/useBankingInformationMutation.test.js new file mode 100644 index 00000000..a135fed3 --- /dev/null +++ b/src/common/hooks/useBankingInformationMutation/useBankingInformationMutation.test.js @@ -0,0 +1,83 @@ +import { QueryClient, QueryClientProvider } from 'react-query'; +import { renderHook } from '@folio/jest-config-stripes/testing-library/react'; + +import { useOkapiKy } from '@folio/stripes/core'; + +import { BANKING_INFORMATION_API } from '../../constants'; +import { useBankingInformationMutation } from './useBankingInformationMutation'; + +const bankingInformationBase = { + isPrimary: true, + organizationId: 'organizationId', + bankName: 'Bank name', +}; + +const queryClient = new QueryClient(); + +const wrapper = ({ children }) => ( + + {children} + +); + +const buildMockRequest = (response) => () => ({ + json: () => Promise.resolve(response), +}); + +const kyMock = { + post: jest.fn((_, { json }) => buildMockRequest(json)()), + put: jest.fn(buildMockRequest()), + delete: jest.fn(buildMockRequest()), +}; + +const bankingInformationId = 'banking-information-id'; + +describe('useBankingInformationMutation', () => { + beforeEach(() => { + Object + .values(kyMock) + .forEach(fn => fn.mockClear()); + useOkapiKy + .mockClear() + .mockReturnValue(kyMock); + }); + + it('should make POST request to create a new banking information', async () => { + const { result } = renderHook( + () => useBankingInformationMutation(), + { wrapper }, + ); + + await result.current.createBankingInformation({ bankingInformation: bankingInformationBase }); + + expect(kyMock.post).toHaveBeenCalledWith(BANKING_INFORMATION_API, { json: bankingInformationBase }); + }); + + it('should make PUT request to update an banking information', async () => { + const bankingInformation = { + ...bankingInformationBase, + id: bankingInformationId, + bankName: 'New bank name', + }; + + const { result } = renderHook( + () => useBankingInformationMutation(), + { wrapper }, + ); + + await result.current.updateBankingInformation({ bankingInformation }); + + expect(kyMock.put).toHaveBeenCalledWith(`${BANKING_INFORMATION_API}/${bankingInformationId}`, { json: bankingInformation }); + }); + + it('should make DELETE request to delete banking information by id', async () => { + const { result } = renderHook( + () => useBankingInformationMutation(), + { wrapper }, + ); + + await result.current.deleteBankingInformation({ bankingInformation: { id: bankingInformationId } }); + + expect(kyMock.delete).toHaveBeenCalledWith(`${BANKING_INFORMATION_API}/${bankingInformationId}`); + }); +}); diff --git a/src/common/hooks/useBankingInformationSettings/index.js b/src/common/hooks/useBankingInformationSettings/index.js new file mode 100644 index 00000000..b63dfa7c --- /dev/null +++ b/src/common/hooks/useBankingInformationSettings/index.js @@ -0,0 +1 @@ +export { useBankingInformationSettings } from './useBankingInformationSettings'; diff --git a/src/common/hooks/useBankingInformationSettings/useBankingInformationSettings.js b/src/common/hooks/useBankingInformationSettings/useBankingInformationSettings.js new file mode 100644 index 00000000..ab11faa6 --- /dev/null +++ b/src/common/hooks/useBankingInformationSettings/useBankingInformationSettings.js @@ -0,0 +1,46 @@ +import { get } from 'lodash'; +import { useQuery } from 'react-query'; + +import { + useNamespace, + useOkapiKy, +} from '@folio/stripes/core'; + +import { + BANKING_INFORMATION_ENABLED_KEY, + SETTINGS_API, +} from '../../constants'; + +const DEFAULT_DATA = {}; + +export const useBankingInformationSettings = () => { + const ky = useOkapiKy(); + const [namespace] = useNamespace({ key: 'banking-information-settings' }); + + const { + data: bankingInformation = DEFAULT_DATA, + isFetching, + isLoading, + refetch, + } = useQuery( + [namespace], + async () => { + const response = await ky.get(SETTINGS_API, { + searchParams: { + query: `key=${BANKING_INFORMATION_ENABLED_KEY}`, + limit: 1, + }, + }).json(); + + return get(response, 'settings[0]', DEFAULT_DATA); + }, + ); + + return ({ + bankingInformation, + enabled: bankingInformation.value === 'true', + isFetching, + isLoading, + refetch, + }); +}; diff --git a/src/Settings/hooks/useBankingInformation.test.js b/src/common/hooks/useBankingInformationSettings/useBankingInformationSettings.test.js similarity index 62% rename from src/Settings/hooks/useBankingInformation.test.js rename to src/common/hooks/useBankingInformationSettings/useBankingInformationSettings.test.js index 03046dfe..482b85cf 100644 --- a/src/Settings/hooks/useBankingInformation.test.js +++ b/src/common/hooks/useBankingInformationSettings/useBankingInformationSettings.test.js @@ -9,25 +9,25 @@ import { } from '@folio/jest-config-stripes/testing-library/react'; import { useOkapiKy } from '@folio/stripes/core'; -import { useBankingInformation } from './useBankingInformation'; +import { BANKING_INFORMATION_ENABLED_KEY } from '../../constants'; +import { useBankingInformationSettings } from './useBankingInformationSettings'; const queryClient = new QueryClient(); const MOCK_BANKING_INFORMATION = { - 'id': 'cb007def-4b68-496c-ad78-ea8e039e819d', - 'key': 'BANKING_INFORMATION_ENABLED', - 'value': 'true', + id: 'cb007def-4b68-496c-ad78-ea8e039e819d', + key: BANKING_INFORMATION_ENABLED_KEY, + value: 'true', refetch: jest.fn(), }; -// eslint-disable-next-line react/prop-types const wrapper = ({ children }) => ( {children} ); -describe('useBankingInformation', () => { +describe('useBankingInformationSettings', () => { beforeEach(() => { useOkapiKy .mockClear() @@ -38,16 +38,15 @@ describe('useBankingInformation', () => { }); }); - it('should fetch all organization types', async () => { - const { result } = renderHook(() => useBankingInformation(), { wrapper }); + it('should fetch banking information settings', async () => { + const { result } = renderHook(() => useBankingInformationSettings(), { wrapper }); await waitFor(() => expect(result.current.isLoading).toBeFalsy()); expect(result.current).toEqual(expect.objectContaining({ enabled: true, isLoading: false, - id: MOCK_BANKING_INFORMATION.id, - key: MOCK_BANKING_INFORMATION.key, + bankingInformation: MOCK_BANKING_INFORMATION, })); }); }); diff --git a/src/common/hooks/useCategories/index.js b/src/common/hooks/useCategories/index.js new file mode 100644 index 00000000..8fa49339 --- /dev/null +++ b/src/common/hooks/useCategories/index.js @@ -0,0 +1 @@ +export { useCategories } from './useCategories'; diff --git a/src/common/hooks/useCategories/useCategories.js b/src/common/hooks/useCategories/useCategories.js new file mode 100644 index 00000000..8cd3878b --- /dev/null +++ b/src/common/hooks/useCategories/useCategories.js @@ -0,0 +1,41 @@ +import { useQuery } from 'react-query'; + +import { + useNamespace, + useOkapiKy, +} from '@folio/stripes/core'; +import { LIMIT_MAX } from '@folio/stripes-acq-components'; + +import { CATEGORIES_API } from '../../constants'; +import { useTranslatedCategories } from '../useTranslatedCategories'; + +const DEFAULT_DATA = []; + +export const useCategories = (options = {}) => { + const ky = useOkapiKy(); + const [namespace] = useNamespace('categories'); + + const searchParams = { + limit: LIMIT_MAX, + query: 'cql.allRecords=1', + }; + + const { + data, + isFetching, + isLoading, + } = useQuery( + [namespace], + () => ky.get(CATEGORIES_API, { searchParams }).json(), + options, + ); + + const [translatedCategories] = useTranslatedCategories(data?.categories); + + return ({ + categories: translatedCategories || DEFAULT_DATA, + totalRecords: data?.totalRecords, + isFetching, + isLoading, + }); +}; diff --git a/src/common/hooks/useCategories/useCategories.test.js b/src/common/hooks/useCategories/useCategories.test.js new file mode 100644 index 00000000..530ce269 --- /dev/null +++ b/src/common/hooks/useCategories/useCategories.test.js @@ -0,0 +1,37 @@ +import { QueryClient, QueryClientProvider } from 'react-query'; + +import { renderHook, waitFor } from '@folio/jest-config-stripes/testing-library/react'; +import { useOkapiKy } from '@folio/stripes/core'; + +import { useCategories } from './useCategories'; + +const categories = [{ id: 'categoryId' }]; + +const queryClient = new QueryClient(); + +const wrapper = ({ children }) => ( + + {children} + +); + +const kyMock = { + get: jest.fn(() => ({ + json: () => Promise.resolve({ categories }), + })), +}; + +describe('useCategories', () => { + beforeEach(() => { + kyMock.get.mockClear(); + useOkapiKy.mockClear().mockReturnValue(kyMock); + }); + + it('should fetch all categories', async () => { + const { result } = renderHook(() => useCategories(), { wrapper }); + + await waitFor(() => expect(result.current.isLoading).toBeFalsy()); + + expect(result.current.categories).toEqual(categories); + }); +}); diff --git a/src/common/hooks/useEventEmitter/index.js b/src/common/hooks/useEventEmitter/index.js new file mode 100644 index 00000000..2e7b4b78 --- /dev/null +++ b/src/common/hooks/useEventEmitter/index.js @@ -0,0 +1 @@ +export { useEventEmitter } from './useEventEmitter'; diff --git a/src/common/hooks/useEventEmitter/useEventEmitter.js b/src/common/hooks/useEventEmitter/useEventEmitter.js new file mode 100644 index 00000000..6c699778 --- /dev/null +++ b/src/common/hooks/useEventEmitter/useEventEmitter.js @@ -0,0 +1,7 @@ +import { EventEmitter } from '../../utils'; + +const eventEmitter = new EventEmitter(); + +export const useEventEmitter = () => { + return eventEmitter; +}; diff --git a/src/common/hooks/useEventEmitter/useEventEmitter.test.js b/src/common/hooks/useEventEmitter/useEventEmitter.test.js new file mode 100644 index 00000000..475b9de6 --- /dev/null +++ b/src/common/hooks/useEventEmitter/useEventEmitter.test.js @@ -0,0 +1,12 @@ +import { renderHook } from '@folio/jest-config-stripes/testing-library/react'; + +import { EventEmitter } from '../../utils'; +import { useEventEmitter } from './useEventEmitter'; + +describe('useEventEmitter', () => { + it('should return event emitter instance', async () => { + const { result } = renderHook(() => useEventEmitter()); + + expect(result.current).toBeInstanceOf(EventEmitter); + }); +}); diff --git a/src/common/hooks/useOrganizationBankingInformation/index.js b/src/common/hooks/useOrganizationBankingInformation/index.js new file mode 100644 index 00000000..b97f1380 --- /dev/null +++ b/src/common/hooks/useOrganizationBankingInformation/index.js @@ -0,0 +1 @@ +export { useOrganizationBankingInformation } from './useOrganizationBankingInformation'; diff --git a/src/common/hooks/useOrganizationBankingInformation/useOrganizationBankingInformation.js b/src/common/hooks/useOrganizationBankingInformation/useOrganizationBankingInformation.js new file mode 100644 index 00000000..132f90c8 --- /dev/null +++ b/src/common/hooks/useOrganizationBankingInformation/useOrganizationBankingInformation.js @@ -0,0 +1,47 @@ +import { useQuery } from 'react-query'; + +import { + useNamespace, + useOkapiKy, +} from '@folio/stripes/core'; +import { LIMIT_MAX } from '@folio/stripes-acq-components'; + +import { BANKING_INFORMATION_API } from '../../constants'; + +const DEFAULT_DATA = []; + +export const useOrganizationBankingInformation = (organizationId, options = {}) => { + const ky = useOkapiKy(); + const [namespace] = useNamespace({ key: 'organization-banking-information' }); + + const queryOptions = { + ...options, + enabled: options.enabled && Boolean(organizationId), + }; + + const { + data, + isFetching, + isLoading, + refetch, + } = useQuery( + [namespace], + () => { + const searchParams = { + query: `organizationId==${organizationId} sortby metadata.createdDate/sort.ascending`, + limit: LIMIT_MAX, + }; + + return ky.get(BANKING_INFORMATION_API, { searchParams }).json(); + }, + queryOptions, + ); + + return ({ + bankingInformation: data?.bankingInformation || DEFAULT_DATA, + totalRecords: data?.totalRecords, + isFetching, + isLoading, + refetch, + }); +}; diff --git a/src/common/hooks/useOrganizationBankingInformation/useOrganizationBankingInformation.test.js b/src/common/hooks/useOrganizationBankingInformation/useOrganizationBankingInformation.test.js new file mode 100644 index 00000000..43e629e8 --- /dev/null +++ b/src/common/hooks/useOrganizationBankingInformation/useOrganizationBankingInformation.test.js @@ -0,0 +1,43 @@ +import { QueryClient, QueryClientProvider } from 'react-query'; + +import { renderHook, waitFor } from '@folio/jest-config-stripes/testing-library/react'; +import { useOkapiKy } from '@folio/stripes/core'; + +import { organization } from 'fixtures'; +import { useOrganizationBankingInformation } from './useOrganizationBankingInformation'; + +const queryClient = new QueryClient(); + +const wrapper = ({ children }) => ( + + {children} + +); + +const organizationId = organization.id; +const bankingInformation = [ + { id: 'id', organizationId }, +]; + +const kyMock = { + get: jest.fn(() => ({ + json: () => Promise.resolve({ bankingInformation }), + })), +}; + +describe('useOrganizationBankingInformation', () => { + beforeEach(() => { + kyMock.get.mockClear(); + useOkapiKy + .mockClear() + .mockReturnValue(kyMock); + }); + + it('should fetch organization banking information', async () => { + const { result } = renderHook(() => useOrganizationBankingInformation(organizationId), { wrapper }); + + await waitFor(() => expect(result.current.isLoading).toBeFalsy()); + + expect(result.current.bankingInformation).toEqual(bankingInformation); + }); +}); diff --git a/src/common/utils/EventEmitter/EventEmitter.js b/src/common/utils/EventEmitter/EventEmitter.js new file mode 100644 index 00000000..3cffc881 --- /dev/null +++ b/src/common/utils/EventEmitter/EventEmitter.js @@ -0,0 +1,19 @@ +export class EventEmitter { + constructor() { + this.eventTarget = new EventTarget(); + } + + on(eventName, callback) { + this.eventTarget.addEventListener(eventName, callback); + } + + off(eventName, callback) { + this.eventTarget.removeEventListener(eventName, callback); + } + + emit(eventName, data) { + const event = new CustomEvent(eventName, { detail: data }); + + this.eventTarget.dispatchEvent(event); + } +} diff --git a/src/common/utils/EventEmitter/EventEmitter.test.js b/src/common/utils/EventEmitter/EventEmitter.test.js new file mode 100644 index 00000000..ffcd0b9f --- /dev/null +++ b/src/common/utils/EventEmitter/EventEmitter.test.js @@ -0,0 +1,36 @@ +import { EventEmitter } from './EventEmitter'; + +const EVENT_TYPE = 'test-event-type'; +const callback = jest.fn(); +const payload = 'Test payload'; + +describe('EventEmitter', () => { + let emitter; + + beforeEach(() => { + emitter = new EventEmitter(); + callback.mockClear(); + }); + + it('should add and invoke event listeners', () => { + emitter.on(EVENT_TYPE, callback); + emitter.emit(EVENT_TYPE, payload); + + expect(callback).toHaveBeenCalledWith(expect.objectContaining({ detail: payload })); + }); + + it('should remove event listeners', () => { + emitter.on(EVENT_TYPE, callback); + emitter.off(EVENT_TYPE, callback); + emitter.emit(EVENT_TYPE, payload); + + expect(callback).not.toHaveBeenCalled(); + }); + + it('should emit events with the correct data', () => { + emitter.on(EVENT_TYPE, callback); + emitter.emit(EVENT_TYPE, payload); + + expect(callback).toHaveBeenCalledWith(expect.objectContaining({ detail: payload })); + }); +}); diff --git a/src/common/utils/EventEmitter/index.js b/src/common/utils/EventEmitter/index.js new file mode 100644 index 00000000..4f497da0 --- /dev/null +++ b/src/common/utils/EventEmitter/index.js @@ -0,0 +1 @@ +export { EventEmitter } from './EventEmitter'; diff --git a/src/common/utils/createAddNewItem.js b/src/common/utils/createAddNewItem.js index 9431000b..2b59ec9b 100644 --- a/src/common/utils/createAddNewItem.js +++ b/src/common/utils/createAddNewItem.js @@ -1,4 +1,3 @@ -// eslint-disable-next-line import/prefer-default-export export function createAddNewItem(defaultLanguage) { return fields => { const newItem = {}; diff --git a/src/common/utils/getArrayItemsChanges/getArrayItemsChanges.js b/src/common/utils/getArrayItemsChanges/getArrayItemsChanges.js new file mode 100644 index 00000000..78c0828d --- /dev/null +++ b/src/common/utils/getArrayItemsChanges/getArrayItemsChanges.js @@ -0,0 +1,39 @@ +import isEqual from 'lodash/isEqual'; +import keyBy from 'lodash/keyBy'; + +/** + * Detects added, modified and deleted items in an array. + * The function assumes that each element of the array is an object structure. +*/ +export const getArrayItemsChanges = (initialValues = [], values = []) => { + const initialValuesMap = keyBy(initialValues, 'id'); + const valuesMap = keyBy(values, 'id'); + + const { created, updated } = values.reduce((acc, item) => { + const initItem = initialValuesMap[item.id]; + + if (!initItem) { + acc.created.push(item); + } else if (!isEqual(initItem, item)) { + acc.updated.push(item); + } + + return acc; + }, { created: [], updated: [] }); + + const deleted = initialValues.reduce((acc, initItem) => { + const item = valuesMap[initItem.id]; + + if (!item) { + acc.push(initItem); + } + + return acc; + }, []); + + return { + created, + updated, + deleted, + }; +}; diff --git a/src/common/utils/getArrayItemsChanges/getArrayItemsChanges.test.js b/src/common/utils/getArrayItemsChanges/getArrayItemsChanges.test.js new file mode 100644 index 00000000..3da99314 --- /dev/null +++ b/src/common/utils/getArrayItemsChanges/getArrayItemsChanges.test.js @@ -0,0 +1,122 @@ +import cloneDeep from 'lodash/cloneDeep'; + +import { getArrayItemsChanges } from './getArrayItemsChanges'; + +const initialArray = [ + { id: 1, foo: 'a' }, + { id: 2, foo: 'b' }, + { id: 3, foo: 'c' }, + { id: 4, foo: 'd' }, + { id: 5, foo: 'e' }, +]; + +describe('getArrayItemsChanges', () => { + it('should return a list of created (added) items', () => { + const newItems = [ + { id: 6, foo: 'f' }, + { id: 7, foo: 'g' }, + { id: 8, foo: 'e' }, + ]; + const currArray = [ + ...initialArray, + ...newItems, + ]; + + const { + created, + deleted, + updated, + } = getArrayItemsChanges(initialArray, currArray); + + expect(created).toHaveLength(3); + expect(created).toEqual(newItems); + expect(deleted).toHaveLength(0); + expect(updated).toHaveLength(0); + }); + + it('should return a list of updated items', () => { + const updatedItems = [ + { id: 2, foo: 'bb' }, + { id: 3, foo: 'cc' }, + ]; + + const currArray = cloneDeep(initialArray).map(el => { + const updatedItem = updatedItems.find(item => item.id === el.id); + + return updatedItem || el; + }); + + const { + created, + deleted, + updated, + } = getArrayItemsChanges(initialArray, currArray); + + expect(created).toHaveLength(0); + expect(deleted).toHaveLength(0); + expect(updated).toHaveLength(2); + expect(updated).toEqual(updatedItems); + }); + + it('should return a list of deleted items', () => { + const deletedItems = initialArray.slice(0, 3); + + const currArray = cloneDeep(initialArray).filter(el => { + const deletedItem = deletedItems.find(item => item.id === el.id); + + return !deletedItem; + }); + + const { + created, + deleted, + updated, + } = getArrayItemsChanges(initialArray, currArray); + + expect(created).toHaveLength(0); + expect(deleted).toHaveLength(3); + expect(deleted).toEqual(deletedItems); + expect(updated).toHaveLength(0); + }); + + it('should return a list with all changes in the array made at once', () => { + const newItems = [ + { id: 6, foo: 'f' }, + { id: 7, foo: 'g' }, + ]; + const updatedItems = [ + { id: 1, foo: 'aa' }, + { id: 2, foo: 'bb' }, + { id: 3, foo: 'cc' }, + ]; + const deletedItems = initialArray.slice(3, 4); + + const currArray = [ + ...cloneDeep(initialArray), + ...newItems, + ] + .map(el => { + const updatedItem = updatedItems.find(item => item.id === el.id); + + return updatedItem || el; + }) + .filter(el => { + const deletedItem = deletedItems.find(item => item.id === el.id); + + return !deletedItem; + }); + + const { + created, + deleted, + updated, + } = getArrayItemsChanges(initialArray, currArray); + + expect(created).toHaveLength(2); + expect(created).toEqual(newItems); + expect(deleted).toHaveLength(1); + expect(deleted).toEqual(deletedItems); + expect(updated).toHaveLength(3); + expect(updated).toEqual(updatedItems); + }); +}); diff --git a/src/common/utils/getArrayItemsChanges/index.js b/src/common/utils/getArrayItemsChanges/index.js new file mode 100644 index 00000000..c4deb405 --- /dev/null +++ b/src/common/utils/getArrayItemsChanges/index.js @@ -0,0 +1 @@ +export { getArrayItemsChanges } from './getArrayItemsChanges'; diff --git a/src/common/utils/index.js b/src/common/utils/index.js index 5db960aa..8e662bd0 100644 --- a/src/common/utils/index.js +++ b/src/common/utils/index.js @@ -1,5 +1,7 @@ export * from './category'; export * from './createItem'; +export * from './EventEmitter'; +export * from './getArrayItemsChanges'; export * from './getResourceData'; export * from './hydrateContactInfo'; export * from './createAddNewItem'; diff --git a/src/contacts/EditContact/__snapshots__/EditContact.test.js.snap b/src/contacts/EditContact/__snapshots__/EditContact.test.js.snap index 8952df91..57812565 100644 --- a/src/contacts/EditContact/__snapshots__/EditContact.test.js.snap +++ b/src/contacts/EditContact/__snapshots__/EditContact.test.js.snap @@ -31869,7 +31869,7 @@ exports[`EditContact should render correct form structure 1`] = ` class="optionSegment" data-test-selection-option-segment="true" > - stripes-components.countries.US + US @@ -31902,7 +31902,7 @@ exports[`EditContact should render correct form structure 1`] = ` class="selectionFilterContainer" > - stripes-components.countries.AF + AD
  • - stripes-components.countries.AX + AE
  • - stripes-components.countries.AL + AF
  • - stripes-components.countries.DZ + AG
  • - stripes-components.countries.AS + AI
  • - stripes-components.countries.AD + AL
  • - stripes-components.countries.AO + AM
  • - stripes-components.countries.AI + AN
  • - stripes-components.countries.AQ + AO
  • - stripes-components.countries.AG + AQ
  • - stripes-components.countries.AR + AR
  • - stripes-components.countries.AM + AS
  • - stripes-components.countries.AW + AT
  • - stripes-components.countries.AU + AU
  • - stripes-components.countries.AT + AW
  • - stripes-components.countries.AZ + AX
  • - stripes-components.countries.BS + AZ
  • - stripes-components.countries.BH + BA
  • - stripes-components.countries.BD + BB
  • - stripes-components.countries.BB + BD
  • - stripes-components.countries.BY + BE
  • - stripes-components.countries.BE + BF
  • - stripes-components.countries.BZ + BG
  • - stripes-components.countries.BJ + BH
  • - stripes-components.countries.BM + BI
  • - stripes-components.countries.BT + BJ
  • - stripes-components.countries.BO + BL
  • - stripes-components.countries.BA + BM
  • - stripes-components.countries.BW + BN
  • - stripes-components.countries.BV + BO
  • - stripes-components.countries.BR + BR
  • - stripes-components.countries.VG + BS
  • - stripes-components.countries.IO + BT
  • - stripes-components.countries.BN + BV
  • - stripes-components.countries.BG + BW
  • - stripes-components.countries.BF + BY
  • - stripes-components.countries.BI + BZ
  • - stripes-components.countries.KH + CA
  • - stripes-components.countries.CM + CC
  • - stripes-components.countries.CA + CD
  • - stripes-components.countries.CV + CF
  • - stripes-components.countries.KY + CG
  • - stripes-components.countries.CF + CH
  • - stripes-components.countries.TD + CI
  • - stripes-components.countries.CL + CK
  • - stripes-components.countries.CN + CL
  • - stripes-components.countries.HK + CM
  • - stripes-components.countries.MO + CN
  • - stripes-components.countries.CX + CO
  • - stripes-components.countries.CC + CR
  • - stripes-components.countries.CO + CU
  • - stripes-components.countries.KM + CV
  • - stripes-components.countries.CG + CX
  • - stripes-components.countries.CD + CY
  • - stripes-components.countries.CK + CZ
  • - stripes-components.countries.CR + DE
  • - stripes-components.countries.CI + DJ
  • - stripes-components.countries.HR + DK
  • - stripes-components.countries.CU + DM
  • - stripes-components.countries.CY + DO
  • - stripes-components.countries.CZ + DZ
  • - stripes-components.countries.DK + EC
  • - stripes-components.countries.DJ + EE
  • - stripes-components.countries.DM + EG
  • - stripes-components.countries.DO + EH
  • - stripes-components.countries.EC + ER
  • - stripes-components.countries.EG + ES
  • - stripes-components.countries.SV + ET
  • - stripes-components.countries.GQ + FI
  • - stripes-components.countries.ER + FJ
  • - stripes-components.countries.EE + FK
  • - stripes-components.countries.ET + FM
  • - stripes-components.countries.FK + FO
  • - stripes-components.countries.FO + FR
  • - stripes-components.countries.FJ + GA
  • - stripes-components.countries.FI + GB
  • - stripes-components.countries.FR + GD
  • - stripes-components.countries.GF + GE
  • - stripes-components.countries.PF + GF
  • - stripes-components.countries.TF + GG
  • - stripes-components.countries.GA + GH
  • - stripes-components.countries.GM + GI
  • - stripes-components.countries.GE + GL
  • - stripes-components.countries.DE + GM
  • - stripes-components.countries.GH + GN
  • - stripes-components.countries.GI + GP
  • - stripes-components.countries.GR + GQ
  • - stripes-components.countries.GL + GR
  • - stripes-components.countries.GD + GS
  • - stripes-components.countries.GP + GT
  • - stripes-components.countries.GU + GU
  • - stripes-components.countries.GT + GW
  • - stripes-components.countries.GG + GY
  • - stripes-components.countries.GN + HK
  • - stripes-components.countries.GW + HM
  • - stripes-components.countries.GY + HN
  • - stripes-components.countries.HT + HR
  • - stripes-components.countries.HM + HT
  • - stripes-components.countries.VA + HU
  • - stripes-components.countries.HN + ID
  • - stripes-components.countries.HU + IE
  • - stripes-components.countries.IS + IL
  • - stripes-components.countries.IN + IM
  • - stripes-components.countries.ID + IN
  • - stripes-components.countries.IR + IO
  • - stripes-components.countries.IQ + IQ
  • - stripes-components.countries.IE + IR
  • - stripes-components.countries.IM + IS
  • - stripes-components.countries.IL + IT
  • - stripes-components.countries.IT + JE
  • - stripes-components.countries.JM + JM
  • - stripes-components.countries.JP + JO
  • - stripes-components.countries.JE + JP
  • - stripes-components.countries.JO + KE
  • - stripes-components.countries.KZ + KG
  • - stripes-components.countries.KE + KH
  • - stripes-components.countries.KI + KI
  • - stripes-components.countries.KP + KM
  • - stripes-components.countries.KR + KN
  • - stripes-components.countries.KW + KP
  • - stripes-components.countries.KG + KR
  • - stripes-components.countries.LA + KW
  • - stripes-components.countries.LV + KY
  • - stripes-components.countries.LB + KZ
  • - stripes-components.countries.LS + LA
  • - stripes-components.countries.LR + LB
  • - stripes-components.countries.LY + LC
  • - stripes-components.countries.LI + LI
  • - stripes-components.countries.LT + LK
  • - stripes-components.countries.LU + LR
  • - stripes-components.countries.MK + LS
  • - stripes-components.countries.MG + LT
  • - stripes-components.countries.MW + LU
  • - stripes-components.countries.MY + LV
  • - stripes-components.countries.MV + LY
  • - stripes-components.countries.ML + MA
  • - stripes-components.countries.MT + MC
  • - stripes-components.countries.MH + MD
  • - stripes-components.countries.MQ + ME
  • - stripes-components.countries.MR + MF
  • - stripes-components.countries.MU + MG
  • - stripes-components.countries.YT + MH
  • - stripes-components.countries.MX + MK
  • - stripes-components.countries.FM + ML
  • - stripes-components.countries.MD + MM
  • - stripes-components.countries.MC + MN
  • - stripes-components.countries.MN + MO
  • - stripes-components.countries.ME + MP
  • - stripes-components.countries.MS + MQ
  • - stripes-components.countries.MA + MR
  • - stripes-components.countries.MZ + MS
  • - stripes-components.countries.MM + MT
  • - stripes-components.countries.NA + MU
  • - stripes-components.countries.NR + MV
  • - stripes-components.countries.NP + MW
  • - stripes-components.countries.NL + MX
  • - stripes-components.countries.AN + MY
  • - stripes-components.countries.NC + MZ
  • - stripes-components.countries.NZ + NA
  • - stripes-components.countries.NI + NC
  • - stripes-components.countries.NE + NE
  • - stripes-components.countries.NG + NF
  • - stripes-components.countries.NU + NG
  • - stripes-components.countries.NF + NI
  • - stripes-components.countries.MP + NL
  • - stripes-components.countries.NO + NO
  • - stripes-components.countries.OM + NP
  • - stripes-components.countries.PK + NR
  • - stripes-components.countries.PW + NU
  • - stripes-components.countries.PS + NZ
  • - stripes-components.countries.PA + OM
  • - stripes-components.countries.PG + PA
  • - stripes-components.countries.PY + PE
  • - stripes-components.countries.PE + PF
  • - stripes-components.countries.PH + PG
  • - stripes-components.countries.PN + PH
  • - stripes-components.countries.PL + PK
  • - stripes-components.countries.PT + PL
  • - stripes-components.countries.PR + PM
  • - stripes-components.countries.QA + PN
  • - stripes-components.countries.RE + PR
  • - stripes-components.countries.RO + PS
  • - stripes-components.countries.RU + PT
  • - stripes-components.countries.RW + PW
  • - stripes-components.countries.BL + PY
  • - stripes-components.countries.SH + QA
  • - stripes-components.countries.KN + RE
  • - stripes-components.countries.LC + RO
  • - stripes-components.countries.MF + RS
  • - stripes-components.countries.PM + RU
  • - stripes-components.countries.VC + RW
  • - stripes-components.countries.WS + SA
  • - stripes-components.countries.SM + SB
  • - stripes-components.countries.ST + SC
  • - stripes-components.countries.SA + SD
  • - stripes-components.countries.SN + SE
  • - stripes-components.countries.RS + SG
  • - stripes-components.countries.SC + SH
  • - stripes-components.countries.SL + SI
  • - stripes-components.countries.SG + SJ
  • - stripes-components.countries.SK + SK
  • - stripes-components.countries.SI + SL
  • - stripes-components.countries.SB + SM
  • - stripes-components.countries.SO + SN
  • - stripes-components.countries.ZA + SO
  • - stripes-components.countries.GS + SR
  • - stripes-components.countries.SS + SS
  • - stripes-components.countries.ES + ST
  • - stripes-components.countries.LK + SV
  • - stripes-components.countries.SD + SY
  • - stripes-components.countries.SR + SZ
  • - stripes-components.countries.SJ + TC
  • - stripes-components.countries.SZ + TD
  • - stripes-components.countries.SE + TF
  • - stripes-components.countries.CH + TG
  • - stripes-components.countries.SY + TH
  • - stripes-components.countries.TW + TJ
  • - stripes-components.countries.TJ + TK
  • - stripes-components.countries.TZ + TL
  • - stripes-components.countries.TH + TM
  • - stripes-components.countries.TL + TN
  • - stripes-components.countries.TG + TO
  • - stripes-components.countries.TK + TR
  • - stripes-components.countries.TO + TT
  • - stripes-components.countries.TT + TV
  • - stripes-components.countries.TN + TW
  • - stripes-components.countries.TR + TZ
  • - stripes-components.countries.TM + UA
  • - stripes-components.countries.TC + UG
  • - stripes-components.countries.TV + UM
  • - stripes-components.countries.UG + US
  • - stripes-components.countries.UA + UY
  • - stripes-components.countries.AE + UZ
  • - stripes-components.countries.GB + VA
  • - stripes-components.countries.US + VC
  • - stripes-components.countries.UM + VE
  • - stripes-components.countries.UY + VG
  • - stripes-components.countries.UZ + VI
  • - stripes-components.countries.VU + VN
  • - stripes-components.countries.VE + VU
  • - stripes-components.countries.VN + WF
  • - stripes-components.countries.VI + WS
  • - stripes-components.countries.WF + YE
  • - stripes-components.countries.EH + YT
  • - stripes-components.countries.YE + ZA
  • - stripes-components.countries.ZM + ZM
  • - stripes-components.countries.ZW + ZW
  • diff --git a/src/contacts/ViewContact/ViewContactContainer.test.js b/src/contacts/ViewContact/ViewContactContainer.test.js index 17e93a41..618963e0 100644 --- a/src/contacts/ViewContact/ViewContactContainer.test.js +++ b/src/contacts/ViewContact/ViewContactContainer.test.js @@ -1,13 +1,14 @@ -import React from 'react'; import { render, screen } from '@folio/jest-config-stripes/testing-library/react'; import { match, history } from '../../../test/jest/routerMocks'; - import { DICT_CATEGORIES } from '../../common/constants'; import ViewContact from './ViewContact'; import { ViewContactContainer } from './ViewContactContainer'; -jest.mock('../../common/utils', () => ({ getResourceDataItem: jest.fn() })); +jest.mock('../../common/utils', () => ({ + ...jest.requireActual('../../common/utils'), + getResourceDataItem: jest.fn(), +})); jest.mock('./ViewContact', () => jest.fn(() => 'ViewContact')); const historyMock = { diff --git a/translations/ui-organizations/en.json b/translations/ui-organizations/en.json index ec12c26e..66596301 100644 --- a/translations/ui-organizations/en.json +++ b/translations/ui-organizations/en.json @@ -12,6 +12,13 @@ "comingSoon": "Coming in a future release.", + "data.bankingInformation.accountType": "Account type", + "data.bankingInformation.addressCategory": "Address category", + "data.bankingInformation.bankAccountNumber": "Bank account number", + "data.bankingInformation.bankName": "Bank name", + "data.bankingInformation.isPrimary": "Use as primary banking information", + "data.bankingInformation.notes": "Notes", + "data.bankingInformation.transitNumber": "Transit number", "data.contactTypes.address": "Address", "data.contactTypes.addressLine1": "Address 1", "data.contactTypes.addressLine2": "Address 2", @@ -84,6 +91,8 @@ "vendor.confirmation.message": "Warning. All vendor information, vendor terms, EDI information, and accounts will be deleted from this record.", "summary": "Summary", + "bankingInformation": "Banking information", + "bankingInformation.save.error": "Failed to save banking information.", "contactInformation": "Contact information", "contactPeople": "Contact people", "agreements": "Agreements", @@ -120,6 +129,7 @@ "summary.add": "Add alternative names", "summary.pleaseAddAltNames": "Please add alternative names", + "button.bankingInformation.add": "Add banking information", "button.cancel": "Cancel", "button.saveAndClose": "Save & close", From e7ceac480c394405d65e1fa792fa7fdb102e829c Mon Sep 17 00:00:00 2001 From: Yury Saukou Date: Fri, 17 Nov 2023 18:57:03 +0400 Subject: [PATCH 06/14] UIORGS-389 Implement organization's banking information details view (#582) * UIORGS-389 Implement organization's banking information details view * UIORGS-389 Add unit tests * reorder imports --- CHANGELOG.md | 1 + .../BankingInformationCard.js | 94 +++++++++++++++++++ .../BankingInformationCard.test.js | 46 +++++++++ .../BankingInformationCard/index.js | 1 + .../OrganizationBankingInfo.js | 53 +++++++++++ .../OrganizationBankingInfo.test.js | 86 +++++++++++++++++ .../OrganizationBankingInfo/index.js | 1 + .../OrganizationDetails.js | 35 +++++-- .../OrganizationDetails.test.js | 16 +++- .../OrganizationDetailsContainer.js | 39 +++++--- .../OrganizationDetailsContainer.test.js | 11 ++- 11 files changed, 354 insertions(+), 29 deletions(-) create mode 100644 src/Organizations/OrganizationDetails/OrganizationBankingInfo/BankingInformationCard/BankingInformationCard.js create mode 100644 src/Organizations/OrganizationDetails/OrganizationBankingInfo/BankingInformationCard/BankingInformationCard.test.js create mode 100644 src/Organizations/OrganizationDetails/OrganizationBankingInfo/BankingInformationCard/index.js create mode 100644 src/Organizations/OrganizationDetails/OrganizationBankingInfo/OrganizationBankingInfo.js create mode 100644 src/Organizations/OrganizationDetails/OrganizationBankingInfo/OrganizationBankingInfo.test.js create mode 100644 src/Organizations/OrganizationDetails/OrganizationBankingInfo/index.js diff --git a/CHANGELOG.md b/CHANGELOG.md index f7e5b9f8..24aef053 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * Designate Organization as donor. Refs UIORGS-383. * Settings for banking information. Refs UIORGS-391. * Implement organization's banking information form. Refs UIORGS-390. +* Implement organization's banking information details view. Refs UIORGS-389. ## [5.0.0](https://github.com/folio-org/ui-organizations/tree/v5.0.0) (2023-10-12) [Full Changelog](https://github.com/folio-org/ui-organizations/compare/v4.0.0...v5.0.0) diff --git a/src/Organizations/OrganizationDetails/OrganizationBankingInfo/BankingInformationCard/BankingInformationCard.js b/src/Organizations/OrganizationDetails/OrganizationBankingInfo/BankingInformationCard/BankingInformationCard.js new file mode 100644 index 00000000..49b74a93 --- /dev/null +++ b/src/Organizations/OrganizationDetails/OrganizationBankingInfo/BankingInformationCard/BankingInformationCard.js @@ -0,0 +1,94 @@ +import PropTypes from 'prop-types'; +import { useCallback } from 'react'; +import { FormattedMessage } from 'react-intl'; + +import { + Card, + Col, + KeyValue, + LayoutHeader, + Row, +} from '@folio/stripes/components'; + +const invalidReference = ; + +export const BankingInformationCard = ({ + bankingAccountTypesMap, + bankingInformation, + categoriesMap, +}) => { + const { + isPrimary, + bankName, + bankAccountNumber, + transitNumber, + categoryId, + accountTypeId, + notes, + } = bankingInformation; + + const renderHeader = useCallback(() => ( + } + noActions + /> + ), [isPrimary]); + + return ( + + + + } + value={bankName} + /> + + + } + value={bankAccountNumber} + /> + + + } + value={transitNumber} + /> + + + } + value={categoryId && (categoriesMap[categoryId]?.value ?? invalidReference)} + /> + + + } + value={accountTypeId && (bankingAccountTypesMap[accountTypeId]?.name ?? invalidReference)} + /> + + + } + value={notes} + /> + + + + ); +}; + +BankingInformationCard.propTypes = { + bankingAccountTypesMap: PropTypes.object.isRequired, + bankingInformation: PropTypes.shape({ + isPrimary: PropTypes.bool, + bankName: PropTypes.string, + bankAccountNumber: PropTypes.string, + transitNumber: PropTypes.string, + categoryId: PropTypes.string, + accountTypeId: PropTypes.string, + notes: PropTypes.string, + }).isRequired, + categoriesMap: PropTypes.object.isRequired, +}; diff --git a/src/Organizations/OrganizationDetails/OrganizationBankingInfo/BankingInformationCard/BankingInformationCard.test.js b/src/Organizations/OrganizationDetails/OrganizationBankingInfo/BankingInformationCard/BankingInformationCard.test.js new file mode 100644 index 00000000..b8844209 --- /dev/null +++ b/src/Organizations/OrganizationDetails/OrganizationBankingInfo/BankingInformationCard/BankingInformationCard.test.js @@ -0,0 +1,46 @@ +import { render, screen } from '@folio/jest-config-stripes/testing-library/react'; + +import { BankingInformationCard } from './BankingInformationCard'; + +const bankingInformation = { + isPrimary: true, + bankName: 'Bank name', + bankAccountNumber: 'Acc No', + transitNumber: 't-123', + categoryId: 'category-id', + accountTypeId: 'acc-type-id', + notes: 'Notes', +}; + +const defaultProps = { + bankingAccountTypesMap: { + [bankingInformation.accountTypeId]: { name: 'Acc type' }, + }, + bankingInformation, + categoriesMap: { + [bankingInformation.categoryId]: { value: 'Category' }, + }, +}; + +const renderBankingInformationCard = (props = {}) => render( + , +); + +describe('BankingInformationCard', () => { + it('should render banking information item values', () => { + renderBankingInformationCard(); + + expect(screen.getByText('ui-organizations.primaryItem')).toBeInTheDocument(); + expect(screen.getByText(defaultProps.categoriesMap[bankingInformation.categoryId].value)).toBeInTheDocument(); + expect( + screen.getByText(defaultProps.bankingAccountTypesMap[bankingInformation.accountTypeId].name), + ).toBeInTheDocument(); + expect(screen.getByText(bankingInformation.bankAccountNumber)).toBeInTheDocument(); + expect(screen.getByText(bankingInformation.bankName)).toBeInTheDocument(); + expect(screen.getByText(bankingInformation.notes)).toBeInTheDocument(); + expect(screen.getByText(bankingInformation.transitNumber)).toBeInTheDocument(); + }); +}); diff --git a/src/Organizations/OrganizationDetails/OrganizationBankingInfo/BankingInformationCard/index.js b/src/Organizations/OrganizationDetails/OrganizationBankingInfo/BankingInformationCard/index.js new file mode 100644 index 00000000..56f2d8cb --- /dev/null +++ b/src/Organizations/OrganizationDetails/OrganizationBankingInfo/BankingInformationCard/index.js @@ -0,0 +1 @@ +export { BankingInformationCard } from './BankingInformationCard'; diff --git a/src/Organizations/OrganizationDetails/OrganizationBankingInfo/OrganizationBankingInfo.js b/src/Organizations/OrganizationDetails/OrganizationBankingInfo/OrganizationBankingInfo.js new file mode 100644 index 00000000..c34e93b6 --- /dev/null +++ b/src/Organizations/OrganizationDetails/OrganizationBankingInfo/OrganizationBankingInfo.js @@ -0,0 +1,53 @@ +import keyBy from 'lodash/keyBy'; +import PropTypes from 'prop-types'; +import { useMemo } from 'react'; + +import { Loading } from '@folio/stripes/components'; + +import { + useBankingAccountTypes, + useCategories, + useOrganizationBankingInformation, +} from '../../../common/hooks'; +import { BankingInformationCard } from './BankingInformationCard'; + +export const OrganizationBankingInfo = ({ organization }) => { + const { + bankingInformation, + isFetching: isBankingInformationFetching, + } = useOrganizationBankingInformation(organization.id); + + const { + categories, + isFetching: isCategoriesFetching, + } = useCategories(); + + const { + bankingAccountTypes, + isFetching: isBankingAccountTypesFetching, + } = useBankingAccountTypes(); + + const categoriesMap = useMemo(() => keyBy(categories, 'id'), [categories]); + const bankingAccountTypesMap = useMemo(() => keyBy(bankingAccountTypes, 'id'), [bankingAccountTypes]); + + const isFetching = ( + isBankingInformationFetching + || isCategoriesFetching + || isBankingAccountTypesFetching + ); + + if (isFetching) return ; + + return bankingInformation.map(info => ( + + )); +}; + +OrganizationBankingInfo.propTypes = { + organization: PropTypes.object.isRequired, +}; diff --git a/src/Organizations/OrganizationDetails/OrganizationBankingInfo/OrganizationBankingInfo.test.js b/src/Organizations/OrganizationDetails/OrganizationBankingInfo/OrganizationBankingInfo.test.js new file mode 100644 index 00000000..4115c777 --- /dev/null +++ b/src/Organizations/OrganizationDetails/OrganizationBankingInfo/OrganizationBankingInfo.test.js @@ -0,0 +1,86 @@ +import { render, screen } from '@folio/jest-config-stripes/testing-library/react'; + +import { organization } from 'fixtures'; +import { + useBankingAccountTypes, + useCategories, + useOrganizationBankingInformation, +} from '../../../common/hooks'; +import { OrganizationBankingInfo } from './OrganizationBankingInfo'; + +jest.mock('../../../common/hooks', () => ({ + ...jest.requireActual('../../../common/hooks'), + useBankingAccountTypes: jest.fn(), + useCategories: jest.fn(), + useOrganizationBankingInformation: jest.fn(), +})); + +const defaultProps = { + organization, +}; + +const bankingAccountTypes = [ + { id: 'bank-acc-type-id-1', name: 'Acc type 1' }, + { id: 'bank-acc-type-id-2', name: 'Acc type 2' }, +]; + +const categories = [ + { id: 'category-id-1', value: 'Category 1' }, + { id: 'category-id-2', value: 'Category 2' }, +]; + +const bankingInformation = [ + { + id: 'bank-info-id-1', + isPrimary: true, + bankName: 'Bank name 1', + bankAccountNumber: 'Bank acc No 1', + transitNumber: 't-1', + accountTypeId: bankingAccountTypes[0].id, + categoryId: categories[0].id, + notes: 'Notes', + }, + { + id: 'bank-info-id-2', + bankName: 'Bank name 2', + accountTypeId: bankingAccountTypes[1].id, + categoryId: categories[1].id, + }, + { + id: 'bank-info-id-3', + bankName: 'Bank name 3', + accountTypeId: 'deleted-acc-type-id', + categoryId: 'deleted-category-id', + }, + { + id: 'bank-info-id-4', + bankName: 'Bank name 4', + }, +]; + +const renderOrganizationBankingInfo = (props = {}) => render( + , +); + +describe('OrganizationBankingInfo', () => { + beforeEach(() => { + useBankingAccountTypes + .mockClear() + .mockReturnValue({ bankingAccountTypes, isFetching: false }); + useCategories + .mockClear() + .mockReturnValue({ categories, isFetching: false }); + useOrganizationBankingInformation + .mockClear() + .mockReturnValue({ bankingInformation, isFetching: false }); + }); + + it('should render card for each of banking information items', () => { + renderOrganizationBankingInfo(); + + expect(screen.getAllByText(/^Bank name.*/)).toHaveLength(bankingInformation.length); + }); +}); diff --git a/src/Organizations/OrganizationDetails/OrganizationBankingInfo/index.js b/src/Organizations/OrganizationDetails/OrganizationBankingInfo/index.js new file mode 100644 index 00000000..27b08a52 --- /dev/null +++ b/src/Organizations/OrganizationDetails/OrganizationBankingInfo/index.js @@ -0,0 +1 @@ +export { OrganizationBankingInfo } from './OrganizationBankingInfo'; diff --git a/src/Organizations/OrganizationDetails/OrganizationDetails.js b/src/Organizations/OrganizationDetails/OrganizationDetails.js index 6c6a71d1..82f67910 100644 --- a/src/Organizations/OrganizationDetails/OrganizationDetails.js +++ b/src/Organizations/OrganizationDetails/OrganizationDetails.js @@ -1,7 +1,7 @@ -import React, { useCallback, useEffect, useRef } from 'react'; +import get from 'lodash/get'; import PropTypes from 'prop-types'; +import { useCallback, useEffect, useRef } from 'react'; import { FormattedMessage } from 'react-intl'; -import { get } from 'lodash'; import { useLocation, useHistory, @@ -43,23 +43,24 @@ import { NOTES_ROUTE, ORGANIZATIONS_ROUTE, } from '../../common/constants'; -import { - ORG_DOMAIN, - ORG_NOTE_TYPE, -} from '../Notes/const'; import { ORGANIZATION_SECTIONS, ORGANIZATION_SECTION_LABELS, } from '../constants'; +import { + ORG_DOMAIN, + ORG_NOTE_TYPE, +} from '../Notes/const'; +import { IntegrationDetails } from './IntegrationDetails'; import { LinkedAgreements } from './LinkedAgreements'; -import { OrganizationSummary } from './OrganizationSummary'; +import { OrganizationAccounts } from './OrganizationAccounts'; +import { OrganizationAgreements } from './OrganizationAgreements'; +import { OrganizationBankingInfo } from './OrganizationBankingInfo'; import { OrganizationContactInfo } from './OrganizationContactInfo'; import { OrganizationContactPeopleContainer } from './OrganizationContactPeople'; import { OrganizationInterfacesContainer } from './OrganizationInterfaces'; +import { OrganizationSummary } from './OrganizationSummary'; import { OrganizationVendorInfo } from './OrganizationVendorInfo'; -import { OrganizationAgreements } from './OrganizationAgreements'; -import { OrganizationAccounts } from './OrganizationAccounts'; -import { IntegrationDetails } from './IntegrationDetails'; const OrganizationDetails = ({ onClose, @@ -70,6 +71,7 @@ const OrganizationDetails = ({ organization, organizationCategories, integrationConfigs, + isBankingInformationEnabled, organizationTypes, }) => { const stripes = useStripes(); @@ -83,6 +85,7 @@ const OrganizationDetails = ({ [ORGANIZATION_SECTIONS.vendorTermsSection]: false, [ORGANIZATION_SECTIONS.integrationDetailsSection]: false, [ORGANIZATION_SECTIONS.accountsSection]: false, + [ORGANIZATION_SECTIONS.bankingInformationSection]: false, [ORGANIZATION_SECTIONS.notesSection]: false, [ORGANIZATION_SECTIONS.agreements]: false, }; @@ -95,6 +98,7 @@ const OrganizationDetails = ({ const { restrictions, isLoading: isRestrictionsLoading } = useAcqRestrictions( organization.id, organization.acqUnitIds, ); + const accountNumbers = (organization.isVendor && organization.accounts?.map(({ accountNo }) => accountNo)) || []; const hasDuplicateAccountNumbers = [...new Set(accountNumbers)].length !== accountNumbers.length; @@ -370,6 +374,15 @@ const OrganizationDetails = ({ accounts={organization.accounts} /> + + {isBankingInformationEnabled && ( + + + + )} ) } @@ -420,11 +433,13 @@ OrganizationDetails.propTypes = { value: PropTypes.string, })), integrationConfigs: PropTypes.arrayOf(PropTypes.object), + isBankingInformationEnabled: PropTypes.bool, organizationTypes: PropTypes.arrayOf(PropTypes.object), }; OrganizationDetails.defaultProps = { organizationCategories: [], + isBankingInformationEnabled: false, }; export default OrganizationDetails; diff --git a/src/Organizations/OrganizationDetails/OrganizationDetails.test.js b/src/Organizations/OrganizationDetails/OrganizationDetails.test.js index c10ae483..50f6b9e7 100644 --- a/src/Organizations/OrganizationDetails/OrganizationDetails.test.js +++ b/src/Organizations/OrganizationDetails/OrganizationDetails.test.js @@ -1,14 +1,13 @@ -import React from 'react'; import { QueryClient, QueryClientProvider, } from 'react-query'; +import { MemoryRouter } from 'react-router-dom'; + import { render, screen } from '@folio/jest-config-stripes/testing-library/react'; import user from '@folio/jest-config-stripes/testing-library/user-event'; -import { MemoryRouter } from 'react-router-dom'; import { organizationTypes as organizationTypesMock } from 'fixtures'; - import OrganizationDetails from './OrganizationDetails'; jest.mock('@folio/stripes-acq-components', () => ({ @@ -18,6 +17,7 @@ jest.mock('@folio/stripes-acq-components', () => ({ })); jest.mock('@folio/stripes-smart-components/lib/Notes/NotesSmartAccordion', () => () => 'NotesSmartAccordion'); jest.mock('./OrganizationAccounts', () => ({ OrganizationAccounts: () => 'OrganizationAccounts' })); +jest.mock('./OrganizationBankingInfo', () => ({ OrganizationBankingInfo: () => 'OrganizationBankingInfo' })); jest.mock('./IntegrationDetails', () => ({ IntegrationDetails: () => 'IntegrationDetails' })); jest.mock('./OrganizationAgreements', () => ({ OrganizationAgreements: () => 'OrganizationAgreements' })); jest.mock('./OrganizationVendorInfo', () => ({ OrganizationVendorInfo: () => 'OrganizationVendorInfo' })); @@ -140,6 +140,16 @@ describe('OrganizationDetails', () => { expect(screen.getByText('ui-organizations.view.duplicateAccounts')).toBeDefined(); }); + it('should display banking information accordion when org is vendor and related settings are enabled', () => { + renderOrganizationDetails({ + ...defaultProps, + isBankingInformationEnabled: true, + organization: { name: 'Amazon', isVendor: true }, + }); + + expect(screen.getByText('OrganizationBankingInfo')).toBeInTheDocument(); + }); + describe('Actions', () => { it('should call onEdit when edit action is pressed', async () => { const onEdit = jest.fn(); diff --git a/src/Organizations/OrganizationDetails/OrganizationDetailsContainer.js b/src/Organizations/OrganizationDetails/OrganizationDetailsContainer.js index 26f451a8..655fcf9d 100644 --- a/src/Organizations/OrganizationDetails/OrganizationDetailsContainer.js +++ b/src/Organizations/OrganizationDetails/OrganizationDetailsContainer.js @@ -1,12 +1,12 @@ -import React, { +import PropTypes from 'prop-types'; +import { useCallback, useEffect, useState, } from 'react'; -import PropTypes from 'prop-types'; -import ReactRouterPropTypes from 'react-router-prop-types'; -import { withRouter } from 'react-router-dom'; import { useIntl } from 'react-intl'; +import { withRouter } from 'react-router-dom'; +import ReactRouterPropTypes from 'react-router-prop-types'; import { stripesConnect } from '@folio/stripes/core'; import { @@ -16,13 +16,14 @@ import { } from '@folio/stripes-acq-components'; import { - organizationResourceByUrl, - categoriesResource, -} from '../../common/resources'; -import { + useBankingInformationSettings, useTranslatedCategories, useTypes, } from '../../common/hooks'; +import { + organizationResourceByUrl, + categoriesResource, +} from '../../common/resources'; import { handleSaveErrorResponse } from '../handleSaveErrorResponse'; import OrganizationDetails from './OrganizationDetails'; @@ -35,14 +36,19 @@ export const OrganizationDetailsContainer = ({ }) => { const organizationId = match.params.id; + const intl = useIntl(); const showCallout = useShowCallout(); + const [organization, setOrganization] = useState({}); - const [isLoading, setIsLoading] = useState(true); + const [isOrganizationLoading, setIsOrganizationLoading] = useState(true); const [organizationCategories, setOrganizationCategories] = useState([]); const [translatedCategories] = useTranslatedCategories(organizationCategories); const { organizationTypes, isLoading: isOrgTypesLoading } = useTypes(); - const intl = useIntl(); const { integrationConfigs } = useIntegrationConfigs({ organizationId }); + const { + enabled: isBankingInformationEnabled, + isLoading: isBankingInformationSettingsLoading, + } = useBankingInformationSettings(); useEffect( () => { @@ -57,14 +63,14 @@ export const OrganizationDetailsContainer = ({ useEffect( () => { - setIsLoading(true); + setIsOrganizationLoading(true); setOrganization({}); mutator.organizationDetailsOrg.GET() .then(organizationResponse => { setOrganization(organizationResponse); }) - .finally(() => setIsLoading(false)); + .finally(() => setIsOrganizationLoading(false)); }, // eslint-disable-next-line react-hooks/exhaustive-deps [organizationId], @@ -133,7 +139,13 @@ export const OrganizationDetailsContainer = ({ [intl, showCallout, organizationId], ); - if (isLoading || isOrgTypesLoading) { + const isLoading = ( + isOrganizationLoading + || isOrgTypesLoading + || isBankingInformationSettingsLoading + ); + + if (isLoading) { return ( ); diff --git a/src/Organizations/OrganizationDetails/OrganizationDetailsContainer.test.js b/src/Organizations/OrganizationDetails/OrganizationDetailsContainer.test.js index 85f2e6b2..6736b846 100644 --- a/src/Organizations/OrganizationDetails/OrganizationDetailsContainer.test.js +++ b/src/Organizations/OrganizationDetails/OrganizationDetailsContainer.test.js @@ -1,10 +1,11 @@ -import React from 'react'; import { render, screen } from '@folio/jest-config-stripes/testing-library/react'; import { organizationTypes } from 'fixtures'; - import { match, location, history } from '../../../test/jest/routerMocks'; -import { useTypes } from '../../common/hooks'; +import { + useBankingInformationSettings, + useTypes, +} from '../../common/hooks'; import OrganizationDetails from './OrganizationDetails'; import { OrganizationDetailsContainer } from './OrganizationDetailsContainer'; @@ -14,6 +15,7 @@ jest.mock('@folio/stripes-acq-components', () => ({ })); jest.mock('../../common/hooks', () => ({ ...jest.requireActual('../../common/hooks'), + useBankingInformationSettings: jest.fn(), useTypes: jest.fn(), })); jest.mock('./OrganizationDetails', () => jest.fn(() => 'OrganizationDetails')); @@ -49,6 +51,9 @@ const renderOrganizationDetailsContainer = () => render( describe('OrganizationDetailsContainer', () => { beforeEach(() => { mutatorMock.organizationDetailsOrg.GET.mockClear().mockReturnValue(Promise.resolve(organization)); + useBankingInformationSettings + .mockClear() + .mockReturnValue({ enabled: true, isLoading: false }); useTypes .mockClear() .mockReturnValue({ orgTypes: { organizationTypes, totalRecords: organizationTypes.length } }); From 914862dd72320ad660dbf212f92899fb53c051c9 Mon Sep 17 00:00:00 2001 From: Alisher Musurmonov Date: Tue, 21 Nov 2023 16:51:29 +0500 Subject: [PATCH 07/14] UIORGS-398: modify summary display in organization view mode (#575) * UIORGS-398: modify summary display in organization view mode * tests: add test case for improving test coverage * refactor: update boolean check for accordion visibility * update changelog file * update todo comment --- CHANGELOG.md | 1 + .../OrganizationDetails.js | 89 ++++++++++++------- .../OrganizationDetails.test.js | 13 +++ .../OrganizationSummary.js | 77 +++++++--------- src/Organizations/constants.js | 2 + translations/ui-organizations/en.json | 1 + 6 files changed, 108 insertions(+), 75 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 24aef053..04f7ee24 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ * Settings for banking information. Refs UIORGS-391. * Implement organization's banking information form. Refs UIORGS-390. * Implement organization's banking information details view. Refs UIORGS-389. +* Modify summary display in organization view mode. Refs UIORGS-398. ## [5.0.0](https://github.com/folio-org/ui-organizations/tree/v5.0.0) (2023-10-12) [Full Changelog](https://github.com/folio-org/ui-organizations/compare/v4.0.0...v5.0.0) diff --git a/src/Organizations/OrganizationDetails/OrganizationDetails.js b/src/Organizations/OrganizationDetails/OrganizationDetails.js index 82f67910..0c9f37b4 100644 --- a/src/Organizations/OrganizationDetails/OrganizationDetails.js +++ b/src/Organizations/OrganizationDetails/OrganizationDetails.js @@ -62,6 +62,21 @@ import { OrganizationInterfacesContainer } from './OrganizationInterfaces'; import { OrganizationSummary } from './OrganizationSummary'; import { OrganizationVendorInfo } from './OrganizationVendorInfo'; +const { + accountsSection, + agreements, + bankingInformationSection, + contactInformationSection, + contactPeopleSection, + donorContacts, + integrationDetailsSection, + interfacesSection, + notesSection, + summarySection, + vendorInformationSection, + vendorTermsSection, +} = ORGANIZATION_SECTIONS; + const OrganizationDetails = ({ onClose, onEdit, @@ -77,17 +92,17 @@ const OrganizationDetails = ({ const stripes = useStripes(); const [isRemoveModalOpened, toggleRemoveModal] = useModalToggle(); const initialAccordionStatus = { - [ORGANIZATION_SECTIONS.summarySection]: true, - [ORGANIZATION_SECTIONS.contactInformationSection]: false, - [ORGANIZATION_SECTIONS.contactPeopleSection]: true, - [ORGANIZATION_SECTIONS.interfacesSection]: false, - [ORGANIZATION_SECTIONS.vendorInformationSection]: false, - [ORGANIZATION_SECTIONS.vendorTermsSection]: false, - [ORGANIZATION_SECTIONS.integrationDetailsSection]: false, - [ORGANIZATION_SECTIONS.accountsSection]: false, - [ORGANIZATION_SECTIONS.bankingInformationSection]: false, - [ORGANIZATION_SECTIONS.notesSection]: false, - [ORGANIZATION_SECTIONS.agreements]: false, + [summarySection]: true, + [contactInformationSection]: false, + [contactPeopleSection]: true, + [interfacesSection]: false, + [vendorInformationSection]: false, + [vendorTermsSection]: false, + [integrationDetailsSection]: false, + [accountsSection]: false, + [bankingInformationSection]: false, + [notesSection]: false, + [agreements]: false, }; const [isTagsOpened, toggleTagsPane] = useModalToggle(); const paneTitleRef = useRef(); @@ -95,6 +110,7 @@ const OrganizationDetails = ({ const history = useHistory(); const accordionStatusRef = useRef(); const isDetailsPaneInFocus = location.state?.isDetailsPaneInFocus; + const isDonorVisible = organization?.isVendor && organization?.isDonor; const { restrictions, isLoading: isRestrictionsLoading } = useAcqRestrictions( organization.id, organization.acqUnitIds, ); @@ -263,8 +279,8 @@ const OrganizationDetails = ({ + { + isDonorVisible && ( + + {/* + TODO: add Privileged donor information component https://issues.folio.org/browse/UIORGS-397 + */} + + ) + } + { organization.isVendor && ( <> diff --git a/src/Organizations/OrganizationDetails/OrganizationDetails.test.js b/src/Organizations/OrganizationDetails/OrganizationDetails.test.js index 50f6b9e7..b5990634 100644 --- a/src/Organizations/OrganizationDetails/OrganizationDetails.test.js +++ b/src/Organizations/OrganizationDetails/OrganizationDetails.test.js @@ -127,6 +127,19 @@ describe('OrganizationDetails', () => { expect(screen.getByText('OrganizationAccounts')).toBeDefined(); }); + it('should display Donor Contacts accordion when both vendor and donor have been checked', () => { + renderOrganizationDetails({ + ...defaultProps, + organization: { + name: 'Amazon', + isVendor: true, + isDonor: true, + }, + }); + + expect(screen.getByText('ui-organizations.donorContacts')).toBeDefined(); + }); + it('should display warning message if vendor has not unique account numbers', () => { renderOrganizationDetails({ ...defaultProps, diff --git a/src/Organizations/OrganizationDetails/OrganizationSummary/OrganizationSummary.js b/src/Organizations/OrganizationDetails/OrganizationSummary/OrganizationSummary.js index ae5cb36a..ee57a036 100644 --- a/src/Organizations/OrganizationDetails/OrganizationSummary/OrganizationSummary.js +++ b/src/Organizations/OrganizationDetails/OrganizationSummary/OrganizationSummary.js @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useMemo } from 'react'; import { FormattedMessage } from 'react-intl'; import PropTypes from 'prop-types'; @@ -6,7 +6,6 @@ import { Checkbox, Col, KeyValue, - MultiColumnList, NoValue, Row, } from '@folio/stripes/components'; @@ -18,12 +17,6 @@ import { import { ORGANIZATION_SECTIONS } from '../../constants'; -const aliasesColumnMapping = { - value: , - description: , -}; -const aliasesVisibleColumns = ['value', 'description']; - const OrganizationSummary = ({ acqUnitIds, aliases, @@ -39,6 +32,7 @@ const OrganizationSummary = ({ organizationTypes, }) => { const defaultLanguageValue = LANG_LABEL_BY_CODE[language] || language; + const alternativeNames = useMemo(() => aliases.map(({ value }) => value).join(', '), [aliases]); return ( <> @@ -54,7 +48,7 @@ const OrganizationSummary = ({ - + } @@ -62,14 +56,14 @@ const OrganizationSummary = ({ /> - + } value={code} /> - + } @@ -77,7 +71,7 @@ const OrganizationSummary = ({ /> - + } > @@ -85,7 +79,7 @@ const OrganizationSummary = ({ - + } @@ -93,25 +87,7 @@ const OrganizationSummary = ({ /> - - } - vertical - /> - - - - } - vertical - /> - - - + } @@ -119,31 +95,42 @@ const OrganizationSummary = ({ /> - + - + } value={description || } /> - - - + + } + vertical + /> + + + + } + vertical + /> + + + } - > - - + value={alternativeNames || } + /> diff --git a/src/Organizations/constants.js b/src/Organizations/constants.js index 717e9b55..1b6b2beb 100644 --- a/src/Organizations/constants.js +++ b/src/Organizations/constants.js @@ -12,6 +12,7 @@ export const ORGANIZATION_SECTIONS = { notesSection: 'notesSection', integrationDetailsSection: 'integrationDetailsSection', agreements: 'linkedAgreements', + donorContacts: 'donorContacts', }; export const ORGANIZATION_SECTION_LABELS = { @@ -25,6 +26,7 @@ export const ORGANIZATION_SECTION_LABELS = { [ORGANIZATION_SECTIONS.accountsSection]: , [ORGANIZATION_SECTIONS.integrationDetailsSection]: , [ORGANIZATION_SECTIONS.agreements]: , + [ORGANIZATION_SECTIONS.donorContacts]: , }; export const CREATE_UNITS_PERM = 'organizations.acquisitions-units-assignments.assign'; diff --git a/translations/ui-organizations/en.json b/translations/ui-organizations/en.json index 66596301..23bd186a 100644 --- a/translations/ui-organizations/en.json +++ b/translations/ui-organizations/en.json @@ -97,6 +97,7 @@ "contactPeople": "Contact people", "agreements": "Agreements", "vendorInformation": "Vendor information", + "donorContacts": "Donor contacts", "ediInformation": "EDI information", "interface": "Interface", "accounts": "Accounts", From 221acf6b06030903b8ff6303390aa93e09a73ccd Mon Sep 17 00:00:00 2001 From: FOLIO Translations Bot <38661258+folio-translations@users.noreply.github.com> Date: Tue, 21 Nov 2023 17:11:15 -0500 Subject: [PATCH 08/14] Lokalise: updates --- translations/ui-organizations/ar.json | 13 ++++++++++++- translations/ui-organizations/ber.json | 13 ++++++++++++- translations/ui-organizations/ca.json | 13 ++++++++++++- translations/ui-organizations/cs_CZ.json | 13 ++++++++++++- translations/ui-organizations/da.json | 13 ++++++++++++- translations/ui-organizations/de.json | 13 ++++++++++++- translations/ui-organizations/en_GB.json | 13 ++++++++++++- translations/ui-organizations/en_SE.json | 13 ++++++++++++- translations/ui-organizations/en_US.json | 13 ++++++++++++- translations/ui-organizations/es.json | 13 ++++++++++++- translations/ui-organizations/es_419.json | 13 ++++++++++++- translations/ui-organizations/es_ES.json | 13 ++++++++++++- translations/ui-organizations/fr.json | 13 ++++++++++++- translations/ui-organizations/fr_FR.json | 13 ++++++++++++- translations/ui-organizations/he.json | 13 ++++++++++++- translations/ui-organizations/hi_IN.json | 13 ++++++++++++- translations/ui-organizations/hu.json | 13 ++++++++++++- translations/ui-organizations/it_IT.json | 13 ++++++++++++- translations/ui-organizations/ja.json | 13 ++++++++++++- translations/ui-organizations/ko.json | 13 ++++++++++++- translations/ui-organizations/nb.json | 13 ++++++++++++- translations/ui-organizations/nn.json | 13 ++++++++++++- translations/ui-organizations/pl.json | 13 ++++++++++++- translations/ui-organizations/pt_BR.json | 13 ++++++++++++- translations/ui-organizations/pt_PT.json | 13 ++++++++++++- translations/ui-organizations/ru.json | 13 ++++++++++++- translations/ui-organizations/sk.json | 13 ++++++++++++- translations/ui-organizations/sv.json | 13 ++++++++++++- translations/ui-organizations/ur.json | 13 ++++++++++++- translations/ui-organizations/zh_CN.json | 13 ++++++++++++- translations/ui-organizations/zh_TW.json | 13 ++++++++++++- 31 files changed, 372 insertions(+), 31 deletions(-) diff --git a/translations/ui-organizations/ar.json b/translations/ui-organizations/ar.json index 85e46d70..52d810c0 100644 --- a/translations/ui-organizations/ar.json +++ b/translations/ui-organizations/ar.json @@ -433,5 +433,16 @@ "settings.accountTypes.save.success.message": "Setting was successfully updated.", "settings.accountTypes.save.error.generic.message": "Something went wrong.", "settings.accountTypes.name": "Name", - "settings.accountTypes.action": "Action" + "settings.accountTypes.action": "Action", + "data.bankingInformation.accountType": "Account type", + "data.bankingInformation.addressCategory": "Address category", + "data.bankingInformation.bankAccountNumber": "Bank account number", + "data.bankingInformation.bankName": "Bank name", + "data.bankingInformation.isPrimary": "Use as primary banking information", + "data.bankingInformation.notes": "Notes", + "data.bankingInformation.transitNumber": "Transit number", + "bankingInformation": "Banking information", + "bankingInformation.save.error": "Failed to save banking information.", + "button.bankingInformation.add": "Add banking information", + "donorContacts": "Donor contacts" } \ No newline at end of file diff --git a/translations/ui-organizations/ber.json b/translations/ui-organizations/ber.json index d1cb0d90..b34af686 100644 --- a/translations/ui-organizations/ber.json +++ b/translations/ui-organizations/ber.json @@ -433,5 +433,16 @@ "settings.accountTypes.save.success.message": "Setting was successfully updated.", "settings.accountTypes.save.error.generic.message": "Something went wrong.", "settings.accountTypes.name": "Name", - "settings.accountTypes.action": "Action" + "settings.accountTypes.action": "Action", + "data.bankingInformation.accountType": "Account type", + "data.bankingInformation.addressCategory": "Address category", + "data.bankingInformation.bankAccountNumber": "Bank account number", + "data.bankingInformation.bankName": "Bank name", + "data.bankingInformation.isPrimary": "Use as primary banking information", + "data.bankingInformation.notes": "Notes", + "data.bankingInformation.transitNumber": "Transit number", + "bankingInformation": "Banking information", + "bankingInformation.save.error": "Failed to save banking information.", + "button.bankingInformation.add": "Add banking information", + "donorContacts": "Donor contacts" } \ No newline at end of file diff --git a/translations/ui-organizations/ca.json b/translations/ui-organizations/ca.json index 007e224f..0f151b8e 100644 --- a/translations/ui-organizations/ca.json +++ b/translations/ui-organizations/ca.json @@ -433,5 +433,16 @@ "settings.accountTypes.save.success.message": "Setting was successfully updated.", "settings.accountTypes.save.error.generic.message": "Something went wrong.", "settings.accountTypes.name": "Name", - "settings.accountTypes.action": "Action" + "settings.accountTypes.action": "Action", + "data.bankingInformation.accountType": "Account type", + "data.bankingInformation.addressCategory": "Address category", + "data.bankingInformation.bankAccountNumber": "Bank account number", + "data.bankingInformation.bankName": "Bank name", + "data.bankingInformation.isPrimary": "Use as primary banking information", + "data.bankingInformation.notes": "Notes", + "data.bankingInformation.transitNumber": "Transit number", + "bankingInformation": "Banking information", + "bankingInformation.save.error": "Failed to save banking information.", + "button.bankingInformation.add": "Add banking information", + "donorContacts": "Donor contacts" } \ No newline at end of file diff --git a/translations/ui-organizations/cs_CZ.json b/translations/ui-organizations/cs_CZ.json index 7358b6f3..186b8110 100644 --- a/translations/ui-organizations/cs_CZ.json +++ b/translations/ui-organizations/cs_CZ.json @@ -433,5 +433,16 @@ "settings.accountTypes.save.success.message": "Nastavení bylo úspěšně aktualizováno.", "settings.accountTypes.save.error.generic.message": "Něco se pokazilo.", "settings.accountTypes.name": "Jméno", - "settings.accountTypes.action": "Akce" + "settings.accountTypes.action": "Akce", + "data.bankingInformation.accountType": "Typ účtu", + "data.bankingInformation.addressCategory": "Kategorie adresy", + "data.bankingInformation.bankAccountNumber": "Číslo bankovního účtu", + "data.bankingInformation.bankName": "Název banky", + "data.bankingInformation.isPrimary": "Použít jako primární bankovní informace", + "data.bankingInformation.notes": "Poznámky", + "data.bankingInformation.transitNumber": "Tranzitní číslo", + "bankingInformation": "Bankovní informace", + "bankingInformation.save.error": "Nepodařilo se uložit bankovní informace.", + "button.bankingInformation.add": "Přidat bankovní informace", + "donorContacts": "Kontakty na dárce" } \ No newline at end of file diff --git a/translations/ui-organizations/da.json b/translations/ui-organizations/da.json index c6a04897..fa5ae44e 100644 --- a/translations/ui-organizations/da.json +++ b/translations/ui-organizations/da.json @@ -433,5 +433,16 @@ "settings.accountTypes.save.success.message": "Setting was successfully updated.", "settings.accountTypes.save.error.generic.message": "Something went wrong.", "settings.accountTypes.name": "Name", - "settings.accountTypes.action": "Action" + "settings.accountTypes.action": "Action", + "data.bankingInformation.accountType": "Account type", + "data.bankingInformation.addressCategory": "Address category", + "data.bankingInformation.bankAccountNumber": "Bank account number", + "data.bankingInformation.bankName": "Bank name", + "data.bankingInformation.isPrimary": "Use as primary banking information", + "data.bankingInformation.notes": "Notes", + "data.bankingInformation.transitNumber": "Transit number", + "bankingInformation": "Banking information", + "bankingInformation.save.error": "Failed to save banking information.", + "button.bankingInformation.add": "Add banking information", + "donorContacts": "Donor contacts" } \ No newline at end of file diff --git a/translations/ui-organizations/de.json b/translations/ui-organizations/de.json index 23b7c2bb..b0c0e09d 100644 --- a/translations/ui-organizations/de.json +++ b/translations/ui-organizations/de.json @@ -433,5 +433,16 @@ "settings.accountTypes.save.success.message": "Setting was successfully updated.", "settings.accountTypes.save.error.generic.message": "Something went wrong.", "settings.accountTypes.name": "Name", - "settings.accountTypes.action": "Action" + "settings.accountTypes.action": "Action", + "data.bankingInformation.accountType": "Account type", + "data.bankingInformation.addressCategory": "Address category", + "data.bankingInformation.bankAccountNumber": "Bank account number", + "data.bankingInformation.bankName": "Bank name", + "data.bankingInformation.isPrimary": "Use as primary banking information", + "data.bankingInformation.notes": "Notes", + "data.bankingInformation.transitNumber": "Transit number", + "bankingInformation": "Banking information", + "bankingInformation.save.error": "Failed to save banking information.", + "button.bankingInformation.add": "Add banking information", + "donorContacts": "Donor contacts" } \ No newline at end of file diff --git a/translations/ui-organizations/en_GB.json b/translations/ui-organizations/en_GB.json index d1cb0d90..b34af686 100644 --- a/translations/ui-organizations/en_GB.json +++ b/translations/ui-organizations/en_GB.json @@ -433,5 +433,16 @@ "settings.accountTypes.save.success.message": "Setting was successfully updated.", "settings.accountTypes.save.error.generic.message": "Something went wrong.", "settings.accountTypes.name": "Name", - "settings.accountTypes.action": "Action" + "settings.accountTypes.action": "Action", + "data.bankingInformation.accountType": "Account type", + "data.bankingInformation.addressCategory": "Address category", + "data.bankingInformation.bankAccountNumber": "Bank account number", + "data.bankingInformation.bankName": "Bank name", + "data.bankingInformation.isPrimary": "Use as primary banking information", + "data.bankingInformation.notes": "Notes", + "data.bankingInformation.transitNumber": "Transit number", + "bankingInformation": "Banking information", + "bankingInformation.save.error": "Failed to save banking information.", + "button.bankingInformation.add": "Add banking information", + "donorContacts": "Donor contacts" } \ No newline at end of file diff --git a/translations/ui-organizations/en_SE.json b/translations/ui-organizations/en_SE.json index d1cb0d90..b34af686 100644 --- a/translations/ui-organizations/en_SE.json +++ b/translations/ui-organizations/en_SE.json @@ -433,5 +433,16 @@ "settings.accountTypes.save.success.message": "Setting was successfully updated.", "settings.accountTypes.save.error.generic.message": "Something went wrong.", "settings.accountTypes.name": "Name", - "settings.accountTypes.action": "Action" + "settings.accountTypes.action": "Action", + "data.bankingInformation.accountType": "Account type", + "data.bankingInformation.addressCategory": "Address category", + "data.bankingInformation.bankAccountNumber": "Bank account number", + "data.bankingInformation.bankName": "Bank name", + "data.bankingInformation.isPrimary": "Use as primary banking information", + "data.bankingInformation.notes": "Notes", + "data.bankingInformation.transitNumber": "Transit number", + "bankingInformation": "Banking information", + "bankingInformation.save.error": "Failed to save banking information.", + "button.bankingInformation.add": "Add banking information", + "donorContacts": "Donor contacts" } \ No newline at end of file diff --git a/translations/ui-organizations/en_US.json b/translations/ui-organizations/en_US.json index d1cb0d90..b34af686 100644 --- a/translations/ui-organizations/en_US.json +++ b/translations/ui-organizations/en_US.json @@ -433,5 +433,16 @@ "settings.accountTypes.save.success.message": "Setting was successfully updated.", "settings.accountTypes.save.error.generic.message": "Something went wrong.", "settings.accountTypes.name": "Name", - "settings.accountTypes.action": "Action" + "settings.accountTypes.action": "Action", + "data.bankingInformation.accountType": "Account type", + "data.bankingInformation.addressCategory": "Address category", + "data.bankingInformation.bankAccountNumber": "Bank account number", + "data.bankingInformation.bankName": "Bank name", + "data.bankingInformation.isPrimary": "Use as primary banking information", + "data.bankingInformation.notes": "Notes", + "data.bankingInformation.transitNumber": "Transit number", + "bankingInformation": "Banking information", + "bankingInformation.save.error": "Failed to save banking information.", + "button.bankingInformation.add": "Add banking information", + "donorContacts": "Donor contacts" } \ No newline at end of file diff --git a/translations/ui-organizations/es.json b/translations/ui-organizations/es.json index 4459148d..1a3f0dc6 100644 --- a/translations/ui-organizations/es.json +++ b/translations/ui-organizations/es.json @@ -433,5 +433,16 @@ "settings.accountTypes.save.success.message": "Setting was successfully updated.", "settings.accountTypes.save.error.generic.message": "Something went wrong.", "settings.accountTypes.name": "Name", - "settings.accountTypes.action": "Action" + "settings.accountTypes.action": "Action", + "data.bankingInformation.accountType": "Account type", + "data.bankingInformation.addressCategory": "Address category", + "data.bankingInformation.bankAccountNumber": "Bank account number", + "data.bankingInformation.bankName": "Bank name", + "data.bankingInformation.isPrimary": "Use as primary banking information", + "data.bankingInformation.notes": "Notes", + "data.bankingInformation.transitNumber": "Transit number", + "bankingInformation": "Banking information", + "bankingInformation.save.error": "Failed to save banking information.", + "button.bankingInformation.add": "Add banking information", + "donorContacts": "Donor contacts" } \ No newline at end of file diff --git a/translations/ui-organizations/es_419.json b/translations/ui-organizations/es_419.json index 83f8948b..f6de3073 100644 --- a/translations/ui-organizations/es_419.json +++ b/translations/ui-organizations/es_419.json @@ -433,5 +433,16 @@ "settings.accountTypes.save.success.message": "Setting was successfully updated.", "settings.accountTypes.save.error.generic.message": "Something went wrong.", "settings.accountTypes.name": "Name", - "settings.accountTypes.action": "Action" + "settings.accountTypes.action": "Action", + "data.bankingInformation.accountType": "Account type", + "data.bankingInformation.addressCategory": "Address category", + "data.bankingInformation.bankAccountNumber": "Bank account number", + "data.bankingInformation.bankName": "Bank name", + "data.bankingInformation.isPrimary": "Use as primary banking information", + "data.bankingInformation.notes": "Notes", + "data.bankingInformation.transitNumber": "Transit number", + "bankingInformation": "Banking information", + "bankingInformation.save.error": "Failed to save banking information.", + "button.bankingInformation.add": "Add banking information", + "donorContacts": "Donor contacts" } \ No newline at end of file diff --git a/translations/ui-organizations/es_ES.json b/translations/ui-organizations/es_ES.json index a04991f5..310f8b5a 100644 --- a/translations/ui-organizations/es_ES.json +++ b/translations/ui-organizations/es_ES.json @@ -433,5 +433,16 @@ "settings.accountTypes.save.success.message": "Setting was successfully updated.", "settings.accountTypes.save.error.generic.message": "Something went wrong.", "settings.accountTypes.name": "Name", - "settings.accountTypes.action": "Action" + "settings.accountTypes.action": "Action", + "data.bankingInformation.accountType": "Account type", + "data.bankingInformation.addressCategory": "Address category", + "data.bankingInformation.bankAccountNumber": "Bank account number", + "data.bankingInformation.bankName": "Bank name", + "data.bankingInformation.isPrimary": "Use as primary banking information", + "data.bankingInformation.notes": "Notes", + "data.bankingInformation.transitNumber": "Transit number", + "bankingInformation": "Banking information", + "bankingInformation.save.error": "Failed to save banking information.", + "button.bankingInformation.add": "Add banking information", + "donorContacts": "Donor contacts" } \ No newline at end of file diff --git a/translations/ui-organizations/fr.json b/translations/ui-organizations/fr.json index 46d95332..a63c0c66 100644 --- a/translations/ui-organizations/fr.json +++ b/translations/ui-organizations/fr.json @@ -433,5 +433,16 @@ "settings.accountTypes.save.success.message": "Setting was successfully updated.", "settings.accountTypes.save.error.generic.message": "Something went wrong.", "settings.accountTypes.name": "Name", - "settings.accountTypes.action": "Action" + "settings.accountTypes.action": "Action", + "data.bankingInformation.accountType": "Account type", + "data.bankingInformation.addressCategory": "Address category", + "data.bankingInformation.bankAccountNumber": "Bank account number", + "data.bankingInformation.bankName": "Bank name", + "data.bankingInformation.isPrimary": "Use as primary banking information", + "data.bankingInformation.notes": "Notes", + "data.bankingInformation.transitNumber": "Transit number", + "bankingInformation": "Banking information", + "bankingInformation.save.error": "Failed to save banking information.", + "button.bankingInformation.add": "Add banking information", + "donorContacts": "Donor contacts" } \ No newline at end of file diff --git a/translations/ui-organizations/fr_FR.json b/translations/ui-organizations/fr_FR.json index e0147ff2..b6681dd7 100644 --- a/translations/ui-organizations/fr_FR.json +++ b/translations/ui-organizations/fr_FR.json @@ -433,5 +433,16 @@ "settings.accountTypes.save.success.message": "Setting was successfully updated.", "settings.accountTypes.save.error.generic.message": "Something went wrong.", "settings.accountTypes.name": "Name", - "settings.accountTypes.action": "Action" + "settings.accountTypes.action": "Action", + "data.bankingInformation.accountType": "Account type", + "data.bankingInformation.addressCategory": "Address category", + "data.bankingInformation.bankAccountNumber": "Bank account number", + "data.bankingInformation.bankName": "Bank name", + "data.bankingInformation.isPrimary": "Use as primary banking information", + "data.bankingInformation.notes": "Notes", + "data.bankingInformation.transitNumber": "Transit number", + "bankingInformation": "Banking information", + "bankingInformation.save.error": "Failed to save banking information.", + "button.bankingInformation.add": "Add banking information", + "donorContacts": "Donor contacts" } \ No newline at end of file diff --git a/translations/ui-organizations/he.json b/translations/ui-organizations/he.json index d1cb0d90..b34af686 100644 --- a/translations/ui-organizations/he.json +++ b/translations/ui-organizations/he.json @@ -433,5 +433,16 @@ "settings.accountTypes.save.success.message": "Setting was successfully updated.", "settings.accountTypes.save.error.generic.message": "Something went wrong.", "settings.accountTypes.name": "Name", - "settings.accountTypes.action": "Action" + "settings.accountTypes.action": "Action", + "data.bankingInformation.accountType": "Account type", + "data.bankingInformation.addressCategory": "Address category", + "data.bankingInformation.bankAccountNumber": "Bank account number", + "data.bankingInformation.bankName": "Bank name", + "data.bankingInformation.isPrimary": "Use as primary banking information", + "data.bankingInformation.notes": "Notes", + "data.bankingInformation.transitNumber": "Transit number", + "bankingInformation": "Banking information", + "bankingInformation.save.error": "Failed to save banking information.", + "button.bankingInformation.add": "Add banking information", + "donorContacts": "Donor contacts" } \ No newline at end of file diff --git a/translations/ui-organizations/hi_IN.json b/translations/ui-organizations/hi_IN.json index d1cb0d90..b34af686 100644 --- a/translations/ui-organizations/hi_IN.json +++ b/translations/ui-organizations/hi_IN.json @@ -433,5 +433,16 @@ "settings.accountTypes.save.success.message": "Setting was successfully updated.", "settings.accountTypes.save.error.generic.message": "Something went wrong.", "settings.accountTypes.name": "Name", - "settings.accountTypes.action": "Action" + "settings.accountTypes.action": "Action", + "data.bankingInformation.accountType": "Account type", + "data.bankingInformation.addressCategory": "Address category", + "data.bankingInformation.bankAccountNumber": "Bank account number", + "data.bankingInformation.bankName": "Bank name", + "data.bankingInformation.isPrimary": "Use as primary banking information", + "data.bankingInformation.notes": "Notes", + "data.bankingInformation.transitNumber": "Transit number", + "bankingInformation": "Banking information", + "bankingInformation.save.error": "Failed to save banking information.", + "button.bankingInformation.add": "Add banking information", + "donorContacts": "Donor contacts" } \ No newline at end of file diff --git a/translations/ui-organizations/hu.json b/translations/ui-organizations/hu.json index 50c0920a..fab9382e 100644 --- a/translations/ui-organizations/hu.json +++ b/translations/ui-organizations/hu.json @@ -433,5 +433,16 @@ "settings.accountTypes.save.success.message": "Setting was successfully updated.", "settings.accountTypes.save.error.generic.message": "Something went wrong.", "settings.accountTypes.name": "Name", - "settings.accountTypes.action": "Action" + "settings.accountTypes.action": "Action", + "data.bankingInformation.accountType": "Account type", + "data.bankingInformation.addressCategory": "Address category", + "data.bankingInformation.bankAccountNumber": "Bank account number", + "data.bankingInformation.bankName": "Bank name", + "data.bankingInformation.isPrimary": "Use as primary banking information", + "data.bankingInformation.notes": "Notes", + "data.bankingInformation.transitNumber": "Transit number", + "bankingInformation": "Banking information", + "bankingInformation.save.error": "Failed to save banking information.", + "button.bankingInformation.add": "Add banking information", + "donorContacts": "Donor contacts" } \ No newline at end of file diff --git a/translations/ui-organizations/it_IT.json b/translations/ui-organizations/it_IT.json index 4ff6b9a7..483ab7e2 100644 --- a/translations/ui-organizations/it_IT.json +++ b/translations/ui-organizations/it_IT.json @@ -433,5 +433,16 @@ "settings.accountTypes.save.success.message": "Setting was successfully updated.", "settings.accountTypes.save.error.generic.message": "Something went wrong.", "settings.accountTypes.name": "Name", - "settings.accountTypes.action": "Action" + "settings.accountTypes.action": "Action", + "data.bankingInformation.accountType": "Account type", + "data.bankingInformation.addressCategory": "Address category", + "data.bankingInformation.bankAccountNumber": "Bank account number", + "data.bankingInformation.bankName": "Bank name", + "data.bankingInformation.isPrimary": "Use as primary banking information", + "data.bankingInformation.notes": "Notes", + "data.bankingInformation.transitNumber": "Transit number", + "bankingInformation": "Banking information", + "bankingInformation.save.error": "Failed to save banking information.", + "button.bankingInformation.add": "Add banking information", + "donorContacts": "Donor contacts" } \ No newline at end of file diff --git a/translations/ui-organizations/ja.json b/translations/ui-organizations/ja.json index fc392730..9f84099e 100644 --- a/translations/ui-organizations/ja.json +++ b/translations/ui-organizations/ja.json @@ -433,5 +433,16 @@ "settings.accountTypes.save.success.message": "Setting was successfully updated.", "settings.accountTypes.save.error.generic.message": "Something went wrong.", "settings.accountTypes.name": "Name", - "settings.accountTypes.action": "Action" + "settings.accountTypes.action": "Action", + "data.bankingInformation.accountType": "Account type", + "data.bankingInformation.addressCategory": "Address category", + "data.bankingInformation.bankAccountNumber": "Bank account number", + "data.bankingInformation.bankName": "Bank name", + "data.bankingInformation.isPrimary": "Use as primary banking information", + "data.bankingInformation.notes": "Notes", + "data.bankingInformation.transitNumber": "Transit number", + "bankingInformation": "Banking information", + "bankingInformation.save.error": "Failed to save banking information.", + "button.bankingInformation.add": "Add banking information", + "donorContacts": "Donor contacts" } \ No newline at end of file diff --git a/translations/ui-organizations/ko.json b/translations/ui-organizations/ko.json index e1cbbcc6..e3ef31d7 100644 --- a/translations/ui-organizations/ko.json +++ b/translations/ui-organizations/ko.json @@ -433,5 +433,16 @@ "settings.accountTypes.save.success.message": "Setting was successfully updated.", "settings.accountTypes.save.error.generic.message": "Something went wrong.", "settings.accountTypes.name": "Name", - "settings.accountTypes.action": "Action" + "settings.accountTypes.action": "Action", + "data.bankingInformation.accountType": "Account type", + "data.bankingInformation.addressCategory": "Address category", + "data.bankingInformation.bankAccountNumber": "Bank account number", + "data.bankingInformation.bankName": "Bank name", + "data.bankingInformation.isPrimary": "Use as primary banking information", + "data.bankingInformation.notes": "Notes", + "data.bankingInformation.transitNumber": "Transit number", + "bankingInformation": "Banking information", + "bankingInformation.save.error": "Failed to save banking information.", + "button.bankingInformation.add": "Add banking information", + "donorContacts": "Donor contacts" } \ No newline at end of file diff --git a/translations/ui-organizations/nb.json b/translations/ui-organizations/nb.json index d1cb0d90..b34af686 100644 --- a/translations/ui-organizations/nb.json +++ b/translations/ui-organizations/nb.json @@ -433,5 +433,16 @@ "settings.accountTypes.save.success.message": "Setting was successfully updated.", "settings.accountTypes.save.error.generic.message": "Something went wrong.", "settings.accountTypes.name": "Name", - "settings.accountTypes.action": "Action" + "settings.accountTypes.action": "Action", + "data.bankingInformation.accountType": "Account type", + "data.bankingInformation.addressCategory": "Address category", + "data.bankingInformation.bankAccountNumber": "Bank account number", + "data.bankingInformation.bankName": "Bank name", + "data.bankingInformation.isPrimary": "Use as primary banking information", + "data.bankingInformation.notes": "Notes", + "data.bankingInformation.transitNumber": "Transit number", + "bankingInformation": "Banking information", + "bankingInformation.save.error": "Failed to save banking information.", + "button.bankingInformation.add": "Add banking information", + "donorContacts": "Donor contacts" } \ No newline at end of file diff --git a/translations/ui-organizations/nn.json b/translations/ui-organizations/nn.json index d1cb0d90..b34af686 100644 --- a/translations/ui-organizations/nn.json +++ b/translations/ui-organizations/nn.json @@ -433,5 +433,16 @@ "settings.accountTypes.save.success.message": "Setting was successfully updated.", "settings.accountTypes.save.error.generic.message": "Something went wrong.", "settings.accountTypes.name": "Name", - "settings.accountTypes.action": "Action" + "settings.accountTypes.action": "Action", + "data.bankingInformation.accountType": "Account type", + "data.bankingInformation.addressCategory": "Address category", + "data.bankingInformation.bankAccountNumber": "Bank account number", + "data.bankingInformation.bankName": "Bank name", + "data.bankingInformation.isPrimary": "Use as primary banking information", + "data.bankingInformation.notes": "Notes", + "data.bankingInformation.transitNumber": "Transit number", + "bankingInformation": "Banking information", + "bankingInformation.save.error": "Failed to save banking information.", + "button.bankingInformation.add": "Add banking information", + "donorContacts": "Donor contacts" } \ No newline at end of file diff --git a/translations/ui-organizations/pl.json b/translations/ui-organizations/pl.json index 847dc340..45ec02cb 100644 --- a/translations/ui-organizations/pl.json +++ b/translations/ui-organizations/pl.json @@ -433,5 +433,16 @@ "settings.accountTypes.save.success.message": "Setting was successfully updated.", "settings.accountTypes.save.error.generic.message": "Something went wrong.", "settings.accountTypes.name": "Name", - "settings.accountTypes.action": "Action" + "settings.accountTypes.action": "Action", + "data.bankingInformation.accountType": "Account type", + "data.bankingInformation.addressCategory": "Address category", + "data.bankingInformation.bankAccountNumber": "Bank account number", + "data.bankingInformation.bankName": "Bank name", + "data.bankingInformation.isPrimary": "Use as primary banking information", + "data.bankingInformation.notes": "Notes", + "data.bankingInformation.transitNumber": "Transit number", + "bankingInformation": "Banking information", + "bankingInformation.save.error": "Failed to save banking information.", + "button.bankingInformation.add": "Add banking information", + "donorContacts": "Donor contacts" } \ No newline at end of file diff --git a/translations/ui-organizations/pt_BR.json b/translations/ui-organizations/pt_BR.json index bfbf7af4..e2b6eb6e 100644 --- a/translations/ui-organizations/pt_BR.json +++ b/translations/ui-organizations/pt_BR.json @@ -433,5 +433,16 @@ "settings.accountTypes.save.success.message": "A configuração foi atualizada com sucesso.", "settings.accountTypes.save.error.generic.message": "Algo deu errado.", "settings.accountTypes.name": "Nome", - "settings.accountTypes.action": "Ação" + "settings.accountTypes.action": "Ação", + "data.bankingInformation.accountType": "Tipo de conta", + "data.bankingInformation.addressCategory": "Categoria de endereço", + "data.bankingInformation.bankAccountNumber": "Número da conta bancária", + "data.bankingInformation.bankName": "Nome do banco", + "data.bankingInformation.isPrimary": "Usar como informação bancária principal", + "data.bankingInformation.notes": "Notas", + "data.bankingInformation.transitNumber": "Número de trânsito", + "bankingInformation": "Informações bancárias", + "bankingInformation.save.error": "Falha ao salvar informações bancárias.", + "button.bankingInformation.add": "Adicionar informações bancárias", + "donorContacts": "Contatos do(s) doador(es)" } \ No newline at end of file diff --git a/translations/ui-organizations/pt_PT.json b/translations/ui-organizations/pt_PT.json index 1b45fa1f..fb552f29 100644 --- a/translations/ui-organizations/pt_PT.json +++ b/translations/ui-organizations/pt_PT.json @@ -433,5 +433,16 @@ "settings.accountTypes.save.success.message": "Setting was successfully updated.", "settings.accountTypes.save.error.generic.message": "Something went wrong.", "settings.accountTypes.name": "Name", - "settings.accountTypes.action": "Action" + "settings.accountTypes.action": "Action", + "data.bankingInformation.accountType": "Account type", + "data.bankingInformation.addressCategory": "Address category", + "data.bankingInformation.bankAccountNumber": "Bank account number", + "data.bankingInformation.bankName": "Bank name", + "data.bankingInformation.isPrimary": "Use as primary banking information", + "data.bankingInformation.notes": "Notes", + "data.bankingInformation.transitNumber": "Transit number", + "bankingInformation": "Banking information", + "bankingInformation.save.error": "Failed to save banking information.", + "button.bankingInformation.add": "Add banking information", + "donorContacts": "Donor contacts" } \ No newline at end of file diff --git a/translations/ui-organizations/ru.json b/translations/ui-organizations/ru.json index 9fe9a2be..b88475a4 100644 --- a/translations/ui-organizations/ru.json +++ b/translations/ui-organizations/ru.json @@ -433,5 +433,16 @@ "settings.accountTypes.save.success.message": "Setting was successfully updated.", "settings.accountTypes.save.error.generic.message": "Something went wrong.", "settings.accountTypes.name": "Name", - "settings.accountTypes.action": "Action" + "settings.accountTypes.action": "Action", + "data.bankingInformation.accountType": "Account type", + "data.bankingInformation.addressCategory": "Address category", + "data.bankingInformation.bankAccountNumber": "Bank account number", + "data.bankingInformation.bankName": "Bank name", + "data.bankingInformation.isPrimary": "Use as primary banking information", + "data.bankingInformation.notes": "Notes", + "data.bankingInformation.transitNumber": "Transit number", + "bankingInformation": "Banking information", + "bankingInformation.save.error": "Failed to save banking information.", + "button.bankingInformation.add": "Add banking information", + "donorContacts": "Donor contacts" } \ No newline at end of file diff --git a/translations/ui-organizations/sk.json b/translations/ui-organizations/sk.json index d1cb0d90..b34af686 100644 --- a/translations/ui-organizations/sk.json +++ b/translations/ui-organizations/sk.json @@ -433,5 +433,16 @@ "settings.accountTypes.save.success.message": "Setting was successfully updated.", "settings.accountTypes.save.error.generic.message": "Something went wrong.", "settings.accountTypes.name": "Name", - "settings.accountTypes.action": "Action" + "settings.accountTypes.action": "Action", + "data.bankingInformation.accountType": "Account type", + "data.bankingInformation.addressCategory": "Address category", + "data.bankingInformation.bankAccountNumber": "Bank account number", + "data.bankingInformation.bankName": "Bank name", + "data.bankingInformation.isPrimary": "Use as primary banking information", + "data.bankingInformation.notes": "Notes", + "data.bankingInformation.transitNumber": "Transit number", + "bankingInformation": "Banking information", + "bankingInformation.save.error": "Failed to save banking information.", + "button.bankingInformation.add": "Add banking information", + "donorContacts": "Donor contacts" } \ No newline at end of file diff --git a/translations/ui-organizations/sv.json b/translations/ui-organizations/sv.json index d1cb0d90..b34af686 100644 --- a/translations/ui-organizations/sv.json +++ b/translations/ui-organizations/sv.json @@ -433,5 +433,16 @@ "settings.accountTypes.save.success.message": "Setting was successfully updated.", "settings.accountTypes.save.error.generic.message": "Something went wrong.", "settings.accountTypes.name": "Name", - "settings.accountTypes.action": "Action" + "settings.accountTypes.action": "Action", + "data.bankingInformation.accountType": "Account type", + "data.bankingInformation.addressCategory": "Address category", + "data.bankingInformation.bankAccountNumber": "Bank account number", + "data.bankingInformation.bankName": "Bank name", + "data.bankingInformation.isPrimary": "Use as primary banking information", + "data.bankingInformation.notes": "Notes", + "data.bankingInformation.transitNumber": "Transit number", + "bankingInformation": "Banking information", + "bankingInformation.save.error": "Failed to save banking information.", + "button.bankingInformation.add": "Add banking information", + "donorContacts": "Donor contacts" } \ No newline at end of file diff --git a/translations/ui-organizations/ur.json b/translations/ui-organizations/ur.json index a7ab6c59..8785da80 100644 --- a/translations/ui-organizations/ur.json +++ b/translations/ui-organizations/ur.json @@ -433,5 +433,16 @@ "settings.accountTypes.save.success.message": "Setting was successfully updated.", "settings.accountTypes.save.error.generic.message": "Something went wrong.", "settings.accountTypes.name": "Name", - "settings.accountTypes.action": "Action" + "settings.accountTypes.action": "Action", + "data.bankingInformation.accountType": "Account type", + "data.bankingInformation.addressCategory": "Address category", + "data.bankingInformation.bankAccountNumber": "Bank account number", + "data.bankingInformation.bankName": "Bank name", + "data.bankingInformation.isPrimary": "Use as primary banking information", + "data.bankingInformation.notes": "Notes", + "data.bankingInformation.transitNumber": "Transit number", + "bankingInformation": "Banking information", + "bankingInformation.save.error": "Failed to save banking information.", + "button.bankingInformation.add": "Add banking information", + "donorContacts": "Donor contacts" } \ No newline at end of file diff --git a/translations/ui-organizations/zh_CN.json b/translations/ui-organizations/zh_CN.json index ca2caa3d..95df8200 100644 --- a/translations/ui-organizations/zh_CN.json +++ b/translations/ui-organizations/zh_CN.json @@ -433,5 +433,16 @@ "settings.accountTypes.save.success.message": "Setting was successfully updated.", "settings.accountTypes.save.error.generic.message": "Something went wrong.", "settings.accountTypes.name": "Name", - "settings.accountTypes.action": "Action" + "settings.accountTypes.action": "Action", + "data.bankingInformation.accountType": "Account type", + "data.bankingInformation.addressCategory": "Address category", + "data.bankingInformation.bankAccountNumber": "Bank account number", + "data.bankingInformation.bankName": "Bank name", + "data.bankingInformation.isPrimary": "Use as primary banking information", + "data.bankingInformation.notes": "Notes", + "data.bankingInformation.transitNumber": "Transit number", + "bankingInformation": "Banking information", + "bankingInformation.save.error": "Failed to save banking information.", + "button.bankingInformation.add": "Add banking information", + "donorContacts": "Donor contacts" } \ No newline at end of file diff --git a/translations/ui-organizations/zh_TW.json b/translations/ui-organizations/zh_TW.json index 04bc7331..92114d08 100644 --- a/translations/ui-organizations/zh_TW.json +++ b/translations/ui-organizations/zh_TW.json @@ -433,5 +433,16 @@ "settings.accountTypes.save.success.message": "Setting was successfully updated.", "settings.accountTypes.save.error.generic.message": "Something went wrong.", "settings.accountTypes.name": "Name", - "settings.accountTypes.action": "Action" + "settings.accountTypes.action": "Action", + "data.bankingInformation.accountType": "Account type", + "data.bankingInformation.addressCategory": "Address category", + "data.bankingInformation.bankAccountNumber": "Bank account number", + "data.bankingInformation.bankName": "Bank name", + "data.bankingInformation.isPrimary": "Use as primary banking information", + "data.bankingInformation.notes": "Notes", + "data.bankingInformation.transitNumber": "Transit number", + "bankingInformation": "Banking information", + "bankingInformation.save.error": "Failed to save banking information.", + "button.bankingInformation.add": "Add banking information", + "donorContacts": "Donor contacts" } \ No newline at end of file From d156c4bc90b6d3007d44d70492c9754b37f7de22 Mon Sep 17 00:00:00 2001 From: Yury Saukou Date: Thu, 23 Nov 2023 11:55:25 +0400 Subject: [PATCH 09/14] UIORGS-388 Protection of viewing and changes of banking information by permissions (#583) * UIORGS-388 Protection of viewing and changes of banking information by permissions * UIORGS-388 Update perms hierarchy for repeatable fields usage --- CHANGELOG.md | 1 + package.json | 41 ++++++++++++++++--- .../OrganizationDetails.js | 14 ++++--- .../OrganizationBankingInfoForm.js | 5 +++ .../OrganizationForm/OrganizationForm.js | 15 ++++--- translations/ui-organizations/en.json | 4 ++ 6 files changed, 63 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 04f7ee24..9859bea2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ * Implement organization's banking information form. Refs UIORGS-390. * Implement organization's banking information details view. Refs UIORGS-389. * Modify summary display in organization view mode. Refs UIORGS-398. +* Protection of viewing and changes of banking information by permissions. Refs UIORGS-388. ## [5.0.0](https://github.com/folio-org/ui-organizations/tree/v5.0.0) (2023-10-12) [Full Changelog](https://github.com/folio-org/ui-organizations/compare/v4.0.0...v5.0.0) diff --git a/package.json b/package.json index e2fbba66..2ffc7a08 100644 --- a/package.json +++ b/package.json @@ -81,8 +81,6 @@ "data-export.config.item.get", "orders.acquisition-methods.collection.get", "orders.acquisition-method.item.get", - "organizations.banking-information.collection.get", - "organizations.banking-information.item.get", "organizations.organizations.collection.get", "organizations.organizations.item.get", "organizations-storage.addresses.collection.get", @@ -111,7 +109,6 @@ "data-export.config.item.delete", "data-export.config.item.post", "data-export.config.item.put", - "organizations.banking-information.item.put", "organizations.organizations.item.put", "organizations-storage.addresses.item.put", "organizations-storage.emails.item.put", @@ -131,7 +128,6 @@ "displayName": "Organizations: View, edit, create", "visible": true, "subPermissions": [ - "organizations.banking-information.item.post", "organizations.organizations.item.post", "organizations-storage.addresses.item.post", "organizations-storage.emails.item.post", @@ -145,7 +141,6 @@ "displayName": "Organizations: View, edit, delete", "visible": true, "subPermissions": [ - "organizations.banking-information.item.delete", "organizations.organizations.item.delete", "organizations-storage.addresses.item.delete", "organizations-storage.emails.item.delete", @@ -154,6 +149,42 @@ "ui-organizations.edit" ] }, + { + "permissionName": "ui-organizations.banking-information.view", + "displayName": "Organizations: View banking information", + "visible": true, + "subPermissions": [ + "organizations.banking-information.collection.get", + "organizations.banking-information.item.get" + ] + }, + { + "permissionName": "ui-organizations.banking-information.edit", + "displayName": "Organizations: View and edit banking information", + "visible": true, + "subPermissions": [ + "ui-organizations.banking-information.view", + "organizations.banking-information.item.put" + ] + }, + { + "permissionName": "ui-organizations.banking-information.create", + "displayName": "Organizations: View, edit and create banking information", + "visible": true, + "subPermissions": [ + "ui-organizations.banking-information.edit", + "organizations.banking-information.item.post" + ] + }, + { + "permissionName": "ui-organizations.banking-information.delete", + "displayName": "Organizations: View, edit, create and delete banking information", + "visible": true, + "subPermissions": [ + "ui-organizations.banking-information.create", + "organizations.banking-information.item.delete" + ] + }, { "permissionName": "ui-organizations.creds.view", "displayName": "Organizations: Interface usernames and passwords: view", diff --git a/src/Organizations/OrganizationDetails/OrganizationDetails.js b/src/Organizations/OrganizationDetails/OrganizationDetails.js index 0c9f37b4..13710cf8 100644 --- a/src/Organizations/OrganizationDetails/OrganizationDetails.js +++ b/src/Organizations/OrganizationDetails/OrganizationDetails.js @@ -405,12 +405,14 @@ const OrganizationDetails = ({ {isBankingInformationEnabled && ( - - - + + + + + )} ) diff --git a/src/Organizations/OrganizationForm/OrganizationBankingInfoForm/OrganizationBankingInfoForm.js b/src/Organizations/OrganizationForm/OrganizationBankingInfoForm/OrganizationBankingInfoForm.js index 62e253ca..157d5377 100644 --- a/src/Organizations/OrganizationForm/OrganizationBankingInfoForm/OrganizationBankingInfoForm.js +++ b/src/Organizations/OrganizationForm/OrganizationBankingInfoForm/OrganizationBankingInfoForm.js @@ -3,6 +3,7 @@ import { FieldArray } from 'react-final-form-arrays'; import { FormattedMessage } from 'react-intl'; import { Loading } from '@folio/stripes/components'; +import { useStripes } from '@folio/stripes/core'; import { useBankingAccountTypes, @@ -27,6 +28,8 @@ const renderField = (props) => (name, index, fields) => ( ); export const OrganizationBankingInfoForm = () => { + const stripes = useStripes(); + const { bankingAccountTypes, isFetching: isBankingAccountTypesFetching, @@ -54,6 +57,8 @@ export const OrganizationBankingInfoForm = () => { } component={BankingInformationFieldArray} + canAdd={stripes.hasPerm('ui-organizations.banking-information.create')} + canRemove={stripes.hasPerm('ui-organizations.banking-information.delete')} id="bankingInformation" name={BANKING_INFORMATION_FIELD_NAME} onAdd={createAddNewItem()} diff --git a/src/Organizations/OrganizationForm/OrganizationForm.js b/src/Organizations/OrganizationForm/OrganizationForm.js index 11826ddb..2e3785c6 100644 --- a/src/Organizations/OrganizationForm/OrganizationForm.js +++ b/src/Organizations/OrganizationForm/OrganizationForm.js @@ -3,6 +3,7 @@ import { FormattedMessage } from 'react-intl'; import { useHistory } from 'react-router'; import { mapValues } from 'lodash'; +import { IfPermission } from '@folio/stripes/core'; import stripesForm from '@folio/stripes/final-form'; import { Accordion, @@ -223,12 +224,14 @@ const OrganizationForm = ({ {isBankingInformationEnabled && ( - - - + + + + + )} ) diff --git a/translations/ui-organizations/en.json b/translations/ui-organizations/en.json index 23bd186a..9434d9ae 100644 --- a/translations/ui-organizations/en.json +++ b/translations/ui-organizations/en.json @@ -479,6 +479,10 @@ "permission.creds.manage": "Organizations: Interface usernames and passwords: view, edit, create, delete", "permission.acqUnits.assign": "Organizations: Assign acquisition units to new organization", "permission.acqUnits.manage": "Organizations: Manage acquisition units", + "permission.banking-information.view": "Organizations: View banking information", + "permission.banking-information.edit": "Organizations: View and edit banking information", + "permission.banking-information.create": "Organizations: View, edit and create banking information", + "permission.banking-information.delete": "Organizations: View, edit, create and delete banking information", "permission.settings.view": "Settings (Organizations): View settings", "permission.settings": "Settings (Organizations): Can view and edit settings" } From e9f6f1b007a2c04b04c25f232a40cc225da6fcc1 Mon Sep 17 00:00:00 2001 From: FOLIO Translations Bot <38661258+folio-translations@users.noreply.github.com> Date: Fri, 24 Nov 2023 17:41:20 -0500 Subject: [PATCH 10/14] Lokalise: updates --- translations/ui-organizations/ar.json | 6 +++++- translations/ui-organizations/ber.json | 6 +++++- translations/ui-organizations/ca.json | 6 +++++- translations/ui-organizations/cs_CZ.json | 6 +++++- translations/ui-organizations/da.json | 6 +++++- translations/ui-organizations/de.json | 6 +++++- translations/ui-organizations/en_GB.json | 6 +++++- translations/ui-organizations/en_SE.json | 6 +++++- translations/ui-organizations/en_US.json | 6 +++++- translations/ui-organizations/es.json | 6 +++++- translations/ui-organizations/es_419.json | 6 +++++- translations/ui-organizations/es_ES.json | 6 +++++- translations/ui-organizations/fr.json | 6 +++++- translations/ui-organizations/fr_FR.json | 6 +++++- translations/ui-organizations/he.json | 6 +++++- translations/ui-organizations/hi_IN.json | 6 +++++- translations/ui-organizations/hu.json | 6 +++++- translations/ui-organizations/it_IT.json | 6 +++++- translations/ui-organizations/ja.json | 6 +++++- translations/ui-organizations/ko.json | 6 +++++- translations/ui-organizations/nb.json | 6 +++++- translations/ui-organizations/nn.json | 6 +++++- translations/ui-organizations/pl.json | 6 +++++- translations/ui-organizations/pt_BR.json | 6 +++++- translations/ui-organizations/pt_PT.json | 6 +++++- translations/ui-organizations/ru.json | 6 +++++- translations/ui-organizations/sk.json | 6 +++++- translations/ui-organizations/sv.json | 6 +++++- translations/ui-organizations/ur.json | 6 +++++- translations/ui-organizations/zh_CN.json | 6 +++++- translations/ui-organizations/zh_TW.json | 6 +++++- 31 files changed, 155 insertions(+), 31 deletions(-) diff --git a/translations/ui-organizations/ar.json b/translations/ui-organizations/ar.json index 52d810c0..fef221b7 100644 --- a/translations/ui-organizations/ar.json +++ b/translations/ui-organizations/ar.json @@ -444,5 +444,9 @@ "bankingInformation": "Banking information", "bankingInformation.save.error": "Failed to save banking information.", "button.bankingInformation.add": "Add banking information", - "donorContacts": "Donor contacts" + "donorContacts": "Donor contacts", + "permission.banking-information.view": "Organizations: View banking information", + "permission.banking-information.edit": "Organizations: View and edit banking information", + "permission.banking-information.create": "Organizations: View, edit and create banking information", + "permission.banking-information.delete": "Organizations: View, edit, create and delete banking information" } \ No newline at end of file diff --git a/translations/ui-organizations/ber.json b/translations/ui-organizations/ber.json index b34af686..b783379c 100644 --- a/translations/ui-organizations/ber.json +++ b/translations/ui-organizations/ber.json @@ -444,5 +444,9 @@ "bankingInformation": "Banking information", "bankingInformation.save.error": "Failed to save banking information.", "button.bankingInformation.add": "Add banking information", - "donorContacts": "Donor contacts" + "donorContacts": "Donor contacts", + "permission.banking-information.view": "Organizations: View banking information", + "permission.banking-information.edit": "Organizations: View and edit banking information", + "permission.banking-information.create": "Organizations: View, edit and create banking information", + "permission.banking-information.delete": "Organizations: View, edit, create and delete banking information" } \ No newline at end of file diff --git a/translations/ui-organizations/ca.json b/translations/ui-organizations/ca.json index 0f151b8e..a87e8523 100644 --- a/translations/ui-organizations/ca.json +++ b/translations/ui-organizations/ca.json @@ -444,5 +444,9 @@ "bankingInformation": "Banking information", "bankingInformation.save.error": "Failed to save banking information.", "button.bankingInformation.add": "Add banking information", - "donorContacts": "Donor contacts" + "donorContacts": "Donor contacts", + "permission.banking-information.view": "Organizations: View banking information", + "permission.banking-information.edit": "Organizations: View and edit banking information", + "permission.banking-information.create": "Organizations: View, edit and create banking information", + "permission.banking-information.delete": "Organizations: View, edit, create and delete banking information" } \ No newline at end of file diff --git a/translations/ui-organizations/cs_CZ.json b/translations/ui-organizations/cs_CZ.json index 186b8110..25d4544e 100644 --- a/translations/ui-organizations/cs_CZ.json +++ b/translations/ui-organizations/cs_CZ.json @@ -444,5 +444,9 @@ "bankingInformation": "Bankovní informace", "bankingInformation.save.error": "Nepodařilo se uložit bankovní informace.", "button.bankingInformation.add": "Přidat bankovní informace", - "donorContacts": "Kontakty na dárce" + "donorContacts": "Kontakty na dárce", + "permission.banking-information.view": "Organizations: View banking information", + "permission.banking-information.edit": "Organizations: View and edit banking information", + "permission.banking-information.create": "Organizations: View, edit and create banking information", + "permission.banking-information.delete": "Organizations: View, edit, create and delete banking information" } \ No newline at end of file diff --git a/translations/ui-organizations/da.json b/translations/ui-organizations/da.json index fa5ae44e..d0beb22d 100644 --- a/translations/ui-organizations/da.json +++ b/translations/ui-organizations/da.json @@ -444,5 +444,9 @@ "bankingInformation": "Banking information", "bankingInformation.save.error": "Failed to save banking information.", "button.bankingInformation.add": "Add banking information", - "donorContacts": "Donor contacts" + "donorContacts": "Donor contacts", + "permission.banking-information.view": "Organizations: View banking information", + "permission.banking-information.edit": "Organizations: View and edit banking information", + "permission.banking-information.create": "Organizations: View, edit and create banking information", + "permission.banking-information.delete": "Organizations: View, edit, create and delete banking information" } \ No newline at end of file diff --git a/translations/ui-organizations/de.json b/translations/ui-organizations/de.json index b0c0e09d..05615e3d 100644 --- a/translations/ui-organizations/de.json +++ b/translations/ui-organizations/de.json @@ -444,5 +444,9 @@ "bankingInformation": "Banking information", "bankingInformation.save.error": "Failed to save banking information.", "button.bankingInformation.add": "Add banking information", - "donorContacts": "Donor contacts" + "donorContacts": "Donor contacts", + "permission.banking-information.view": "Organizations: View banking information", + "permission.banking-information.edit": "Organizations: View and edit banking information", + "permission.banking-information.create": "Organizations: View, edit and create banking information", + "permission.banking-information.delete": "Organizations: View, edit, create and delete banking information" } \ No newline at end of file diff --git a/translations/ui-organizations/en_GB.json b/translations/ui-organizations/en_GB.json index b34af686..b783379c 100644 --- a/translations/ui-organizations/en_GB.json +++ b/translations/ui-organizations/en_GB.json @@ -444,5 +444,9 @@ "bankingInformation": "Banking information", "bankingInformation.save.error": "Failed to save banking information.", "button.bankingInformation.add": "Add banking information", - "donorContacts": "Donor contacts" + "donorContacts": "Donor contacts", + "permission.banking-information.view": "Organizations: View banking information", + "permission.banking-information.edit": "Organizations: View and edit banking information", + "permission.banking-information.create": "Organizations: View, edit and create banking information", + "permission.banking-information.delete": "Organizations: View, edit, create and delete banking information" } \ No newline at end of file diff --git a/translations/ui-organizations/en_SE.json b/translations/ui-organizations/en_SE.json index b34af686..b783379c 100644 --- a/translations/ui-organizations/en_SE.json +++ b/translations/ui-organizations/en_SE.json @@ -444,5 +444,9 @@ "bankingInformation": "Banking information", "bankingInformation.save.error": "Failed to save banking information.", "button.bankingInformation.add": "Add banking information", - "donorContacts": "Donor contacts" + "donorContacts": "Donor contacts", + "permission.banking-information.view": "Organizations: View banking information", + "permission.banking-information.edit": "Organizations: View and edit banking information", + "permission.banking-information.create": "Organizations: View, edit and create banking information", + "permission.banking-information.delete": "Organizations: View, edit, create and delete banking information" } \ No newline at end of file diff --git a/translations/ui-organizations/en_US.json b/translations/ui-organizations/en_US.json index b34af686..b783379c 100644 --- a/translations/ui-organizations/en_US.json +++ b/translations/ui-organizations/en_US.json @@ -444,5 +444,9 @@ "bankingInformation": "Banking information", "bankingInformation.save.error": "Failed to save banking information.", "button.bankingInformation.add": "Add banking information", - "donorContacts": "Donor contacts" + "donorContacts": "Donor contacts", + "permission.banking-information.view": "Organizations: View banking information", + "permission.banking-information.edit": "Organizations: View and edit banking information", + "permission.banking-information.create": "Organizations: View, edit and create banking information", + "permission.banking-information.delete": "Organizations: View, edit, create and delete banking information" } \ No newline at end of file diff --git a/translations/ui-organizations/es.json b/translations/ui-organizations/es.json index 1a3f0dc6..91828c3b 100644 --- a/translations/ui-organizations/es.json +++ b/translations/ui-organizations/es.json @@ -444,5 +444,9 @@ "bankingInformation": "Banking information", "bankingInformation.save.error": "Failed to save banking information.", "button.bankingInformation.add": "Add banking information", - "donorContacts": "Donor contacts" + "donorContacts": "Donor contacts", + "permission.banking-information.view": "Organizations: View banking information", + "permission.banking-information.edit": "Organizations: View and edit banking information", + "permission.banking-information.create": "Organizations: View, edit and create banking information", + "permission.banking-information.delete": "Organizations: View, edit, create and delete banking information" } \ No newline at end of file diff --git a/translations/ui-organizations/es_419.json b/translations/ui-organizations/es_419.json index f6de3073..02888b1c 100644 --- a/translations/ui-organizations/es_419.json +++ b/translations/ui-organizations/es_419.json @@ -444,5 +444,9 @@ "bankingInformation": "Banking information", "bankingInformation.save.error": "Failed to save banking information.", "button.bankingInformation.add": "Add banking information", - "donorContacts": "Donor contacts" + "donorContacts": "Donor contacts", + "permission.banking-information.view": "Organizations: View banking information", + "permission.banking-information.edit": "Organizations: View and edit banking information", + "permission.banking-information.create": "Organizations: View, edit and create banking information", + "permission.banking-information.delete": "Organizations: View, edit, create and delete banking information" } \ No newline at end of file diff --git a/translations/ui-organizations/es_ES.json b/translations/ui-organizations/es_ES.json index 310f8b5a..566f18a9 100644 --- a/translations/ui-organizations/es_ES.json +++ b/translations/ui-organizations/es_ES.json @@ -444,5 +444,9 @@ "bankingInformation": "Banking information", "bankingInformation.save.error": "Failed to save banking information.", "button.bankingInformation.add": "Add banking information", - "donorContacts": "Donor contacts" + "donorContacts": "Donor contacts", + "permission.banking-information.view": "Organizations: View banking information", + "permission.banking-information.edit": "Organizations: View and edit banking information", + "permission.banking-information.create": "Organizations: View, edit and create banking information", + "permission.banking-information.delete": "Organizations: View, edit, create and delete banking information" } \ No newline at end of file diff --git a/translations/ui-organizations/fr.json b/translations/ui-organizations/fr.json index a63c0c66..a1af22c9 100644 --- a/translations/ui-organizations/fr.json +++ b/translations/ui-organizations/fr.json @@ -444,5 +444,9 @@ "bankingInformation": "Banking information", "bankingInformation.save.error": "Failed to save banking information.", "button.bankingInformation.add": "Add banking information", - "donorContacts": "Donor contacts" + "donorContacts": "Donor contacts", + "permission.banking-information.view": "Organizations: View banking information", + "permission.banking-information.edit": "Organizations: View and edit banking information", + "permission.banking-information.create": "Organizations: View, edit and create banking information", + "permission.banking-information.delete": "Organizations: View, edit, create and delete banking information" } \ No newline at end of file diff --git a/translations/ui-organizations/fr_FR.json b/translations/ui-organizations/fr_FR.json index b6681dd7..48ad51ed 100644 --- a/translations/ui-organizations/fr_FR.json +++ b/translations/ui-organizations/fr_FR.json @@ -444,5 +444,9 @@ "bankingInformation": "Banking information", "bankingInformation.save.error": "Failed to save banking information.", "button.bankingInformation.add": "Add banking information", - "donorContacts": "Donor contacts" + "donorContacts": "Donor contacts", + "permission.banking-information.view": "Organizations: View banking information", + "permission.banking-information.edit": "Organizations: View and edit banking information", + "permission.banking-information.create": "Organizations: View, edit and create banking information", + "permission.banking-information.delete": "Organizations: View, edit, create and delete banking information" } \ No newline at end of file diff --git a/translations/ui-organizations/he.json b/translations/ui-organizations/he.json index b34af686..b783379c 100644 --- a/translations/ui-organizations/he.json +++ b/translations/ui-organizations/he.json @@ -444,5 +444,9 @@ "bankingInformation": "Banking information", "bankingInformation.save.error": "Failed to save banking information.", "button.bankingInformation.add": "Add banking information", - "donorContacts": "Donor contacts" + "donorContacts": "Donor contacts", + "permission.banking-information.view": "Organizations: View banking information", + "permission.banking-information.edit": "Organizations: View and edit banking information", + "permission.banking-information.create": "Organizations: View, edit and create banking information", + "permission.banking-information.delete": "Organizations: View, edit, create and delete banking information" } \ No newline at end of file diff --git a/translations/ui-organizations/hi_IN.json b/translations/ui-organizations/hi_IN.json index b34af686..b783379c 100644 --- a/translations/ui-organizations/hi_IN.json +++ b/translations/ui-organizations/hi_IN.json @@ -444,5 +444,9 @@ "bankingInformation": "Banking information", "bankingInformation.save.error": "Failed to save banking information.", "button.bankingInformation.add": "Add banking information", - "donorContacts": "Donor contacts" + "donorContacts": "Donor contacts", + "permission.banking-information.view": "Organizations: View banking information", + "permission.banking-information.edit": "Organizations: View and edit banking information", + "permission.banking-information.create": "Organizations: View, edit and create banking information", + "permission.banking-information.delete": "Organizations: View, edit, create and delete banking information" } \ No newline at end of file diff --git a/translations/ui-organizations/hu.json b/translations/ui-organizations/hu.json index fab9382e..c990fbd8 100644 --- a/translations/ui-organizations/hu.json +++ b/translations/ui-organizations/hu.json @@ -444,5 +444,9 @@ "bankingInformation": "Banking information", "bankingInformation.save.error": "Failed to save banking information.", "button.bankingInformation.add": "Add banking information", - "donorContacts": "Donor contacts" + "donorContacts": "Donor contacts", + "permission.banking-information.view": "Organizations: View banking information", + "permission.banking-information.edit": "Organizations: View and edit banking information", + "permission.banking-information.create": "Organizations: View, edit and create banking information", + "permission.banking-information.delete": "Organizations: View, edit, create and delete banking information" } \ No newline at end of file diff --git a/translations/ui-organizations/it_IT.json b/translations/ui-organizations/it_IT.json index 483ab7e2..7ee77817 100644 --- a/translations/ui-organizations/it_IT.json +++ b/translations/ui-organizations/it_IT.json @@ -444,5 +444,9 @@ "bankingInformation": "Banking information", "bankingInformation.save.error": "Failed to save banking information.", "button.bankingInformation.add": "Add banking information", - "donorContacts": "Donor contacts" + "donorContacts": "Donor contacts", + "permission.banking-information.view": "Organizations: View banking information", + "permission.banking-information.edit": "Organizations: View and edit banking information", + "permission.banking-information.create": "Organizations: View, edit and create banking information", + "permission.banking-information.delete": "Organizations: View, edit, create and delete banking information" } \ No newline at end of file diff --git a/translations/ui-organizations/ja.json b/translations/ui-organizations/ja.json index 9f84099e..963b5618 100644 --- a/translations/ui-organizations/ja.json +++ b/translations/ui-organizations/ja.json @@ -444,5 +444,9 @@ "bankingInformation": "Banking information", "bankingInformation.save.error": "Failed to save banking information.", "button.bankingInformation.add": "Add banking information", - "donorContacts": "Donor contacts" + "donorContacts": "Donor contacts", + "permission.banking-information.view": "Organizations: View banking information", + "permission.banking-information.edit": "Organizations: View and edit banking information", + "permission.banking-information.create": "Organizations: View, edit and create banking information", + "permission.banking-information.delete": "Organizations: View, edit, create and delete banking information" } \ No newline at end of file diff --git a/translations/ui-organizations/ko.json b/translations/ui-organizations/ko.json index e3ef31d7..a665182a 100644 --- a/translations/ui-organizations/ko.json +++ b/translations/ui-organizations/ko.json @@ -444,5 +444,9 @@ "bankingInformation": "Banking information", "bankingInformation.save.error": "Failed to save banking information.", "button.bankingInformation.add": "Add banking information", - "donorContacts": "Donor contacts" + "donorContacts": "Donor contacts", + "permission.banking-information.view": "Organizations: View banking information", + "permission.banking-information.edit": "Organizations: View and edit banking information", + "permission.banking-information.create": "Organizations: View, edit and create banking information", + "permission.banking-information.delete": "Organizations: View, edit, create and delete banking information" } \ No newline at end of file diff --git a/translations/ui-organizations/nb.json b/translations/ui-organizations/nb.json index b34af686..b783379c 100644 --- a/translations/ui-organizations/nb.json +++ b/translations/ui-organizations/nb.json @@ -444,5 +444,9 @@ "bankingInformation": "Banking information", "bankingInformation.save.error": "Failed to save banking information.", "button.bankingInformation.add": "Add banking information", - "donorContacts": "Donor contacts" + "donorContacts": "Donor contacts", + "permission.banking-information.view": "Organizations: View banking information", + "permission.banking-information.edit": "Organizations: View and edit banking information", + "permission.banking-information.create": "Organizations: View, edit and create banking information", + "permission.banking-information.delete": "Organizations: View, edit, create and delete banking information" } \ No newline at end of file diff --git a/translations/ui-organizations/nn.json b/translations/ui-organizations/nn.json index b34af686..b783379c 100644 --- a/translations/ui-organizations/nn.json +++ b/translations/ui-organizations/nn.json @@ -444,5 +444,9 @@ "bankingInformation": "Banking information", "bankingInformation.save.error": "Failed to save banking information.", "button.bankingInformation.add": "Add banking information", - "donorContacts": "Donor contacts" + "donorContacts": "Donor contacts", + "permission.banking-information.view": "Organizations: View banking information", + "permission.banking-information.edit": "Organizations: View and edit banking information", + "permission.banking-information.create": "Organizations: View, edit and create banking information", + "permission.banking-information.delete": "Organizations: View, edit, create and delete banking information" } \ No newline at end of file diff --git a/translations/ui-organizations/pl.json b/translations/ui-organizations/pl.json index 45ec02cb..94a25e09 100644 --- a/translations/ui-organizations/pl.json +++ b/translations/ui-organizations/pl.json @@ -444,5 +444,9 @@ "bankingInformation": "Banking information", "bankingInformation.save.error": "Failed to save banking information.", "button.bankingInformation.add": "Add banking information", - "donorContacts": "Donor contacts" + "donorContacts": "Donor contacts", + "permission.banking-information.view": "Organizations: View banking information", + "permission.banking-information.edit": "Organizations: View and edit banking information", + "permission.banking-information.create": "Organizations: View, edit and create banking information", + "permission.banking-information.delete": "Organizations: View, edit, create and delete banking information" } \ No newline at end of file diff --git a/translations/ui-organizations/pt_BR.json b/translations/ui-organizations/pt_BR.json index e2b6eb6e..f95ce3c4 100644 --- a/translations/ui-organizations/pt_BR.json +++ b/translations/ui-organizations/pt_BR.json @@ -444,5 +444,9 @@ "bankingInformation": "Informações bancárias", "bankingInformation.save.error": "Falha ao salvar informações bancárias.", "button.bankingInformation.add": "Adicionar informações bancárias", - "donorContacts": "Contatos do(s) doador(es)" + "donorContacts": "Contatos do(s) doador(es)", + "permission.banking-information.view": "Organizações: Visualizar informações bancárias", + "permission.banking-information.edit": "Organizações: visualizar e editar informações bancárias", + "permission.banking-information.create": "Organizações: Visualizar, editar e criar informações bancárias", + "permission.banking-information.delete": "Organizações: Visualizar, editar, criar e excluir informações bancárias" } \ No newline at end of file diff --git a/translations/ui-organizations/pt_PT.json b/translations/ui-organizations/pt_PT.json index fb552f29..7bebc70d 100644 --- a/translations/ui-organizations/pt_PT.json +++ b/translations/ui-organizations/pt_PT.json @@ -444,5 +444,9 @@ "bankingInformation": "Banking information", "bankingInformation.save.error": "Failed to save banking information.", "button.bankingInformation.add": "Add banking information", - "donorContacts": "Donor contacts" + "donorContacts": "Donor contacts", + "permission.banking-information.view": "Organizations: View banking information", + "permission.banking-information.edit": "Organizations: View and edit banking information", + "permission.banking-information.create": "Organizations: View, edit and create banking information", + "permission.banking-information.delete": "Organizations: View, edit, create and delete banking information" } \ No newline at end of file diff --git a/translations/ui-organizations/ru.json b/translations/ui-organizations/ru.json index b88475a4..5b68d15b 100644 --- a/translations/ui-organizations/ru.json +++ b/translations/ui-organizations/ru.json @@ -444,5 +444,9 @@ "bankingInformation": "Banking information", "bankingInformation.save.error": "Failed to save banking information.", "button.bankingInformation.add": "Add banking information", - "donorContacts": "Donor contacts" + "donorContacts": "Donor contacts", + "permission.banking-information.view": "Organizations: View banking information", + "permission.banking-information.edit": "Organizations: View and edit banking information", + "permission.banking-information.create": "Organizations: View, edit and create banking information", + "permission.banking-information.delete": "Organizations: View, edit, create and delete banking information" } \ No newline at end of file diff --git a/translations/ui-organizations/sk.json b/translations/ui-organizations/sk.json index b34af686..b783379c 100644 --- a/translations/ui-organizations/sk.json +++ b/translations/ui-organizations/sk.json @@ -444,5 +444,9 @@ "bankingInformation": "Banking information", "bankingInformation.save.error": "Failed to save banking information.", "button.bankingInformation.add": "Add banking information", - "donorContacts": "Donor contacts" + "donorContacts": "Donor contacts", + "permission.banking-information.view": "Organizations: View banking information", + "permission.banking-information.edit": "Organizations: View and edit banking information", + "permission.banking-information.create": "Organizations: View, edit and create banking information", + "permission.banking-information.delete": "Organizations: View, edit, create and delete banking information" } \ No newline at end of file diff --git a/translations/ui-organizations/sv.json b/translations/ui-organizations/sv.json index b34af686..b783379c 100644 --- a/translations/ui-organizations/sv.json +++ b/translations/ui-organizations/sv.json @@ -444,5 +444,9 @@ "bankingInformation": "Banking information", "bankingInformation.save.error": "Failed to save banking information.", "button.bankingInformation.add": "Add banking information", - "donorContacts": "Donor contacts" + "donorContacts": "Donor contacts", + "permission.banking-information.view": "Organizations: View banking information", + "permission.banking-information.edit": "Organizations: View and edit banking information", + "permission.banking-information.create": "Organizations: View, edit and create banking information", + "permission.banking-information.delete": "Organizations: View, edit, create and delete banking information" } \ No newline at end of file diff --git a/translations/ui-organizations/ur.json b/translations/ui-organizations/ur.json index 8785da80..bba7e67b 100644 --- a/translations/ui-organizations/ur.json +++ b/translations/ui-organizations/ur.json @@ -444,5 +444,9 @@ "bankingInformation": "Banking information", "bankingInformation.save.error": "Failed to save banking information.", "button.bankingInformation.add": "Add banking information", - "donorContacts": "Donor contacts" + "donorContacts": "Donor contacts", + "permission.banking-information.view": "Organizations: View banking information", + "permission.banking-information.edit": "Organizations: View and edit banking information", + "permission.banking-information.create": "Organizations: View, edit and create banking information", + "permission.banking-information.delete": "Organizations: View, edit, create and delete banking information" } \ No newline at end of file diff --git a/translations/ui-organizations/zh_CN.json b/translations/ui-organizations/zh_CN.json index 95df8200..0632fef9 100644 --- a/translations/ui-organizations/zh_CN.json +++ b/translations/ui-organizations/zh_CN.json @@ -444,5 +444,9 @@ "bankingInformation": "Banking information", "bankingInformation.save.error": "Failed to save banking information.", "button.bankingInformation.add": "Add banking information", - "donorContacts": "Donor contacts" + "donorContacts": "Donor contacts", + "permission.banking-information.view": "Organizations: View banking information", + "permission.banking-information.edit": "Organizations: View and edit banking information", + "permission.banking-information.create": "Organizations: View, edit and create banking information", + "permission.banking-information.delete": "Organizations: View, edit, create and delete banking information" } \ No newline at end of file diff --git a/translations/ui-organizations/zh_TW.json b/translations/ui-organizations/zh_TW.json index 92114d08..cb1d5fdb 100644 --- a/translations/ui-organizations/zh_TW.json +++ b/translations/ui-organizations/zh_TW.json @@ -444,5 +444,9 @@ "bankingInformation": "Banking information", "bankingInformation.save.error": "Failed to save banking information.", "button.bankingInformation.add": "Add banking information", - "donorContacts": "Donor contacts" + "donorContacts": "Donor contacts", + "permission.banking-information.view": "Organizations: View banking information", + "permission.banking-information.edit": "Organizations: View and edit banking information", + "permission.banking-information.create": "Organizations: View, edit and create banking information", + "permission.banking-information.delete": "Organizations: View, edit, create and delete banking information" } \ No newline at end of file From cf2c36cd1d5bc839e611fa7a78258957c5d160a9 Mon Sep 17 00:00:00 2001 From: Yury Saukou Date: Mon, 27 Nov 2023 15:48:52 +0400 Subject: [PATCH 11/14] UIORGS-392 Search organization on bank account number (#585) * UIORGS-392 Search organization on bank account number * add tests * fix lint issue * comment --- CHANGELOG.md | 1 + .../OrganizationsList/OrganizationsList.js | 6 ++- .../hooks/useBuildQuery/useBuildQuery.js | 9 ++-- .../hooks/useBuildQuery/useBuildQuery.test.js | 48 ++++++++++++++++++- translations/ui-organizations/en.json | 1 + 5 files changed, 58 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9859bea2..6119fd95 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ * Implement organization's banking information details view. Refs UIORGS-389. * Modify summary display in organization view mode. Refs UIORGS-398. * Protection of viewing and changes of banking information by permissions. Refs UIORGS-388. +* Search organization on bank account number. Refs UIORGS-392. ## [5.0.0](https://github.com/folio-org/ui-organizations/tree/v5.0.0) (2023-10-12) [Full Changelog](https://github.com/folio-org/ui-organizations/compare/v4.0.0...v5.0.0) diff --git a/src/Organizations/OrganizationsList/OrganizationsList.js b/src/Organizations/OrganizationsList/OrganizationsList.js index c71377cb..da5a063b 100644 --- a/src/Organizations/OrganizationsList/OrganizationsList.js +++ b/src/Organizations/OrganizationsList/OrganizationsList.js @@ -32,8 +32,8 @@ import { useLocationSorting, } from '@folio/stripes-acq-components'; import { + getSearchableIndexes, OrganizationsListFilter, - searchableIndexes, } from '@folio/plugin-find-organization'; import { @@ -105,6 +105,10 @@ const OrganizationsList = ({ const { isFiltersOpened, toggleFilters } = useFiltersToogle('ui-organizations/filters'); + const searchableIndexes = useMemo(() => ( + getSearchableIndexes(stripes) + ), [stripes]); + const urlParams = useMemo(() => ( matchPath(location.pathname, { path: `${VIEW_ORG_DETAILS}:id` }) ), [location.pathname]); diff --git a/src/Organizations/OrganizationsList/hooks/useBuildQuery/useBuildQuery.js b/src/Organizations/OrganizationsList/hooks/useBuildQuery/useBuildQuery.js index 1948d180..cfaf483f 100644 --- a/src/Organizations/OrganizationsList/hooks/useBuildQuery/useBuildQuery.js +++ b/src/Organizations/OrganizationsList/hooks/useBuildQuery/useBuildQuery.js @@ -1,8 +1,7 @@ import { useCallback } from 'react'; -import { - makeQueryBuilder, -} from '@folio/stripes-acq-components'; +import { useStripes } from '@folio/stripes/core'; +import { makeQueryBuilder } from '@folio/stripes-acq-components'; import { filterMap, getKeywordQuery, @@ -16,6 +15,8 @@ const CUSTOM_SORT_MAP = { }; export const useBuildQuery = () => { + const stripes = useStripes(); + return useCallback(makeQueryBuilder( 'cql.allRecords=1', (query, qindex) => { @@ -23,7 +24,7 @@ export const useBuildQuery = () => { return `(${qindex}=${query}*)`; } - return getKeywordQuery(query); + return getKeywordQuery(query, stripes); }, 'sortby name/sort.ascending', filterMap, diff --git a/src/Organizations/OrganizationsList/hooks/useBuildQuery/useBuildQuery.test.js b/src/Organizations/OrganizationsList/hooks/useBuildQuery/useBuildQuery.test.js index 7f0ed07a..ac745998 100644 --- a/src/Organizations/OrganizationsList/hooks/useBuildQuery/useBuildQuery.test.js +++ b/src/Organizations/OrganizationsList/hooks/useBuildQuery/useBuildQuery.test.js @@ -1,12 +1,56 @@ -import queryString from 'query-string'; import { renderHook } from '@folio/jest-config-stripes/testing-library/react'; +import { useStripes } from '@folio/stripes/core'; +import { + SEARCH_INDEX_PARAMETER, + SEARCH_PARAMETER, +} from '@folio/stripes-acq-components'; import { useBuildQuery } from './useBuildQuery'; +jest.mock('@folio/stripes/core', () => ({ + ...jest.requireActual('@folio/stripes/core'), + useStripes: jest.fn(), +})); + +const stripesStub = { + hasPerm: jest.fn(() => true), +}; + describe('useBuildQuery', () => { + beforeEach(() => { + stripesStub.hasPerm.mockClear(); + + useStripes + .mockClear() + .mockReturnValue(stripesStub); + }); + it('should return function, that return query', () => { const { result } = renderHook(() => useBuildQuery()); - expect(result.current(queryString.parse('?foo=bar'))).toBe('(foo=="bar") sortby name/sort.ascending'); + expect(result.current({ + [SEARCH_PARAMETER]: 'bar', + [SEARCH_INDEX_PARAMETER]: 'foo', + })).toBe('(((foo=bar*))) sortby name/sort.ascending'); + }); + + describe('Banking information', () => { + const params = { + [SEARCH_PARAMETER]: 'qwerty', + }; + + it('should include banking information index in the query if a user has the appropriate permission', () => { + const { result } = renderHook(() => useBuildQuery()); + + expect(result.current(params)).toContain('bankingInformation.bankAccountNumber="qwerty*"'); + }); + + it('should NOT include banking information index in the query if a user does not have the appropriate permission', async () => { + stripesStub.hasPerm.mockReturnValue(false); + + const { result } = renderHook(() => useBuildQuery()); + + expect(result.current(params)).not.toContain('bankingInformation.bankAccountNumber="qwerty*"'); + }); }); }); diff --git a/translations/ui-organizations/en.json b/translations/ui-organizations/en.json index 9434d9ae..55ea98f8 100644 --- a/translations/ui-organizations/en.json +++ b/translations/ui-organizations/en.json @@ -61,6 +61,7 @@ "search.erpCode": "Accounting code", "search.taxId": "Tax ID", "search.interfaces": "Interfaces", + "search.bankingInformation.bankAccountNumber": "Bank account number", "search.placeholder.language": "Search with language code", "organization.delete.heading": "Delete {organizationName}?", From d0fdfefd1ff78304315979a4fa1593667cc2fa2f Mon Sep 17 00:00:00 2001 From: Yury Saukou Date: Mon, 4 Dec 2023 17:03:05 +0400 Subject: [PATCH 12/14] UIORGS-388 Add permission to retrieve organizations settings (#587) --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 2ffc7a08..f4f2d581 100644 --- a/package.json +++ b/package.json @@ -96,6 +96,7 @@ "organizations-storage.interfaces.collection.get", "organizations-storage.phone-numbers.collection.get", "organizations-storage.phone-numbers.item.get", + "organizations-storage.settings.collection.get", "organizations-storage.urls.collection.get", "organizations-storage.urls.item.get", "ui-organizations.third-party-services" From 90194458499190f4c7a27545be6fa46dc68d8249 Mon Sep 17 00:00:00 2001 From: Yury Saukou Date: Thu, 7 Dec 2023 12:02:38 +0400 Subject: [PATCH 13/14] UIORGS-415 Enable 'Hourly' and 'Monthly' EDI export scheduling frequency options (#588) --- CHANGELOG.md | 1 + .../SchedulingForm/SchedulingForm.js | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6119fd95..7260cc70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ * Modify summary display in organization view mode. Refs UIORGS-398. * Protection of viewing and changes of banking information by permissions. Refs UIORGS-388. * Search organization on bank account number. Refs UIORGS-392. +* Enable "Hourly" and "Monthly" EDI export scheduling frequency options. Refs UIORGS-415. ## [5.0.0](https://github.com/folio-org/ui-organizations/tree/v5.0.0) (2023-10-12) [Full Changelog](https://github.com/folio-org/ui-organizations/compare/v4.0.0...v5.0.0) diff --git a/src/OrganizationIntegration/OrganizationIntegrationForm/SchedulingForm/SchedulingForm.js b/src/OrganizationIntegration/OrganizationIntegrationForm/SchedulingForm/SchedulingForm.js index ad86fb7c..03de00ca 100644 --- a/src/OrganizationIntegration/OrganizationIntegrationForm/SchedulingForm/SchedulingForm.js +++ b/src/OrganizationIntegration/OrganizationIntegrationForm/SchedulingForm/SchedulingForm.js @@ -23,7 +23,13 @@ import { WEEKDAYS, } from '../../constants'; -const ALLOWED_SCHEDULE_PERIODS = [SCHEDULE_PERIODS.days, SCHEDULE_PERIODS.weeks, SCHEDULE_PERIODS.none]; +const ALLOWED_SCHEDULE_PERIODS = [ + SCHEDULE_PERIODS.none, + SCHEDULE_PERIODS.hours, + SCHEDULE_PERIODS.days, + SCHEDULE_PERIODS.weeks, + SCHEDULE_PERIODS.months, +]; const normalizeNumber = value => { if (!value && value !== 0) return value; From 2580943043fea6e4a15aba9a04c5a3f178c36654 Mon Sep 17 00:00:00 2001 From: Alisher Musurmonov Date: Thu, 7 Dec 2023 23:28:44 +0500 Subject: [PATCH 14/14] UIORGS-397: add privileged donor contacts list (#590) * UIORGS-397: add privileged donor contacts and crud operation for privileged contacts * tests: add test cases * tests: fix failing tests * tests: add test cases * tests: add test case * add permissions for privileged contacts * fix accidentally removed permission name --- CHANGELOG.md | 1 + index.js | 20 ++--- package.json | 6 ++ .../OrganizationDetails.js | 13 ++-- .../OrganizationDetails.test.js | 3 +- .../OrganizationForm/OrganizationForm.js | 16 ++++ .../OrganizationForm/OrganizationForm.test.js | 18 +++++ src/Organizations/constants.js | 4 +- src/common/constants/api.js | 1 + src/common/resources/contacts.js | 15 +++- src/contacts/ContactsContainer.js | 8 +- .../EditContact/EditContactContainer.js | 27 ++++--- .../EditContact/EditContactContainer.test.js | 35 +++++++++ src/contacts/EditContact/util.js | 5 +- src/contacts/EditContact/util.test.js | 75 +++++++++++-------- src/contacts/ViewContact/ViewContact.js | 5 +- src/contacts/ViewContact/ViewContact.test.js | 19 ++--- .../ViewContact/ViewContactContainer.js | 18 ++++- .../ViewContact/ViewContactContainer.test.js | 23 ++++++ src/contacts/constants.js | 2 + translations/ui-organizations/en.json | 2 +- 21 files changed, 231 insertions(+), 85 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7260cc70..a0b3650f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ * Protection of viewing and changes of banking information by permissions. Refs UIORGS-388. * Search organization on bank account number. Refs UIORGS-392. * Enable "Hourly" and "Monthly" EDI export scheduling frequency options. Refs UIORGS-415. +* Create Privileged donor information accordion in organization record. Refs UIORGS-397. ## [5.0.0](https://github.com/folio-org/ui-organizations/tree/v5.0.0) (2023-10-12) [Full Changelog](https://github.com/folio-org/ui-organizations/compare/v4.0.0...v5.0.0) diff --git a/index.js b/index.js index f2d26fda..1810b9c4 100644 --- a/index.js +++ b/index.js @@ -31,19 +31,19 @@ class Organizations extends Component { - - - {/* - TODO: add Privileged donor information component https://issues.folio.org/browse/UIORGS-397 - */} + ) } diff --git a/src/Organizations/OrganizationDetails/OrganizationDetails.test.js b/src/Organizations/OrganizationDetails/OrganizationDetails.test.js index b5990634..5d907ea9 100644 --- a/src/Organizations/OrganizationDetails/OrganizationDetails.test.js +++ b/src/Organizations/OrganizationDetails/OrganizationDetails.test.js @@ -13,6 +13,7 @@ import OrganizationDetails from './OrganizationDetails'; jest.mock('@folio/stripes-acq-components', () => ({ ...jest.requireActual('@folio/stripes-acq-components'), useAcqRestrictions: jest.fn().mockReturnValue({ restrictions: {} }), + PrivilegedDonorsListContainer: jest.fn(() => 'PrivilegedDonorsListContainer'), TagsPane: jest.fn(() => 'TagsPane'), })); jest.mock('@folio/stripes-smart-components/lib/Notes/NotesSmartAccordion', () => () => 'NotesSmartAccordion'); @@ -137,7 +138,7 @@ describe('OrganizationDetails', () => { }, }); - expect(screen.getByText('ui-organizations.donorContacts')).toBeDefined(); + expect(screen.getByText('ui-organizations.privilegedDonorInformation')).toBeDefined(); }); it('should display warning message if vendor has not unique account numbers', () => { diff --git a/src/Organizations/OrganizationForm/OrganizationForm.js b/src/Organizations/OrganizationForm/OrganizationForm.js index 2e3785c6..f569e41f 100644 --- a/src/Organizations/OrganizationForm/OrganizationForm.js +++ b/src/Organizations/OrganizationForm/OrganizationForm.js @@ -19,6 +19,7 @@ import { import { ViewMetaData } from '@folio/stripes/smart-components'; import { FormFooter, + PrivilegedDonorContacts, handleKeyCommand, useAccordionToggle, } from '@folio/stripes-acq-components'; @@ -55,6 +56,7 @@ const OrganizationForm = ({ [ORGANIZATION_SECTIONS.contactInformationSection]: false, [ORGANIZATION_SECTIONS.contactPeopleSection]: false, [ORGANIZATION_SECTIONS.interfacesSection]: false, + [ORGANIZATION_SECTIONS.privilegedDonorInformation]: false, [ORGANIZATION_SECTIONS.vendorInformationSection]: false, [ORGANIZATION_SECTIONS.bankingInformationSection]: false, [ORGANIZATION_SECTIONS.vendorTermsSection]: false, @@ -199,6 +201,20 @@ const OrganizationForm = ({ { formValues.isVendor && ( <> + { + formValues.isDonor && ( + + + + ) + } ({ ...jest.requireActual('react-router'), useHistory: jest.fn(), })); +jest.mock('@folio/stripes-acq-components', () => ({ + ...jest.requireActual('@folio/stripes-acq-components'), + PrivilegedDonorContacts: jest.fn(() => 'PrivilegedDonorContacts'), +})); jest.mock('@folio/stripes-components/lib/Commander', () => ({ HasCommand: jest.fn(({ children }) =>
    {children}
    ), expandAllSections: jest.fn(), @@ -188,6 +192,20 @@ describe('OrganizationForm', () => { expect(screen.getByText('OrganizationBankingInfoForm')).toBeInTheDocument(); }); + + it('should render privileged donor contacts form', () => { + useBankingInformationSettings.mockReturnValue({ enabled: true }); + + renderOrganizationForm({ + ...defaultProps, + initialValues: { + isDonor: true, + isVendor: true, + }, + }); + + expect(screen.getByText('PrivilegedDonorContacts')).toBeInTheDocument(); + }); }); describe('Shortcuts', () => { diff --git a/src/Organizations/constants.js b/src/Organizations/constants.js index 1b6b2beb..9f59e372 100644 --- a/src/Organizations/constants.js +++ b/src/Organizations/constants.js @@ -12,7 +12,7 @@ export const ORGANIZATION_SECTIONS = { notesSection: 'notesSection', integrationDetailsSection: 'integrationDetailsSection', agreements: 'linkedAgreements', - donorContacts: 'donorContacts', + privilegedDonorInformation: 'privilegedDonorInformation', }; export const ORGANIZATION_SECTION_LABELS = { @@ -26,7 +26,7 @@ export const ORGANIZATION_SECTION_LABELS = { [ORGANIZATION_SECTIONS.accountsSection]: , [ORGANIZATION_SECTIONS.integrationDetailsSection]: , [ORGANIZATION_SECTIONS.agreements]: , - [ORGANIZATION_SECTIONS.donorContacts]: , + [ORGANIZATION_SECTIONS.privilegedDonorInformation]: , }; export const CREATE_UNITS_PERM = 'organizations.acquisitions-units-assignments.assign'; diff --git a/src/common/constants/api.js b/src/common/constants/api.js index a9055baa..75237d36 100644 --- a/src/common/constants/api.js +++ b/src/common/constants/api.js @@ -4,6 +4,7 @@ export const BANKING_INFORMATION_API = 'organizations/banking-information'; export const CATEGORIES_API = 'organizations-storage/categories'; export const CONTACTS_API = 'organizations-storage/contacts'; export const INTERFACES_API = 'organizations-storage/interfaces'; +export const PRIVILEGED_CONTACTS_API = 'organizations-storage/privileged-contacts'; export const SETTINGS_API = 'organizations-storage/settings'; export const TYPES_API = 'organizations-storage/organization-types'; diff --git a/src/common/resources/contacts.js b/src/common/resources/contacts.js index 54a942b4..636f588b 100644 --- a/src/common/resources/contacts.js +++ b/src/common/resources/contacts.js @@ -1,4 +1,8 @@ -import { CONTACTS_API, MAX_LIMIT } from '../constants'; +import { + CONTACTS_API, + MAX_LIMIT, + PRIVILEGED_CONTACTS_API, +} from '../constants'; export const contactResource = { throwErrors: false, @@ -9,6 +13,15 @@ export const contactResource = { }, }; +export const privilegedContactResource = { + throwErrors: false, + type: 'okapi', + path: `${PRIVILEGED_CONTACTS_API}/:{id}`, + POST: { + path: PRIVILEGED_CONTACTS_API, + }, +}; + export const baseContactsResource = { throwErrors: false, type: 'okapi', diff --git a/src/contacts/ContactsContainer.js b/src/contacts/ContactsContainer.js index 3ba87518..5b0a5034 100644 --- a/src/contacts/ContactsContainer.js +++ b/src/contacts/ContactsContainer.js @@ -16,11 +16,13 @@ import { } from '@folio/stripes-acq-components'; import { VIEW_ORG_DETAILS } from '../common/constants'; -import ViewContact from './ViewContact'; +import { PRIVILEGED_CONTACT_URL_PATH } from './constants'; import EditContact from './EditContact'; +import ViewContact from './ViewContact'; function ContactsContainer({ history, match: { params, url } }) { const sendCallout = useShowCallout(); + const contactsUrlPath = url.includes(PRIVILEGED_CONTACT_URL_PATH) ? PRIVILEGED_CONTACT_URL_PATH : 'contacts'; const showMessage = useCallback((messageKey, messageType = 'success') => { sendCallout({ type: messageType, @@ -32,9 +34,9 @@ function ContactsContainer({ history, match: { params, url } }) { if (!contactId) { history.push(`${VIEW_ORG_DETAILS}${orgId}`); } else { - history.push(`/organizations/${orgId}/contacts/details/${contactId}/view`); + history.push(`/organizations/${orgId}/${contactsUrlPath}/details/${contactId}/view`); } - }, [history]); + }, [contactsUrlPath, history]); const goToEdit = useCallback((props) => ( { const isNew = !match.params.id; - const loadedContact = resources?.contact?.records?.[0]; + const isPrivilegedContactUrl = match.path.includes(PRIVILEGED_CONTACT_URL_PATH); + const contactResources = isPrivilegedContactUrl ? 'privilegedContact' : 'contact'; + const loadedContact = get(resources[contactResources], 'records[0]'); const categories = resources?.[DICT_CATEGORIES]?.records; const [translatedCategories] = useTranslatedCategories(categories); const contactsOrganization = resources?.contactsOrg?.records?.[0]; @@ -36,12 +41,12 @@ export const EditContactContainer = ({ if (onClose) { onClose(orgId, contactId); } else { - history.push(getBackPath(orgId, contactId, 'contacts')); + history.push(getBackPath(orgId, contactId, isPrivilegedContactUrl ? PRIVILEGED_CONTACT_URL_PATH : 'contacts')); } - }, [match.params.id, onClose, history, orgId]); + }, [match.params.id, onClose, orgId, history, isPrivilegedContactUrl]); const onSubmit = useCallback(contactValues => { - saveContact(mutator, contactValues, contactsOrganization) + saveContact(mutator, contactValues, contactsOrganization, isPrivilegedContactUrl) .then(({ id }) => { showMessage('ui-organizations.contacts.message.saved.success', 'success'); onCloseForm(id); @@ -63,6 +68,7 @@ export const EditContactContainer = ({ const contact = isNew ? {} : loadedContact; const { firstName, lastName } = contact; const name = `${lastName}, ${firstName}`; + const paneTitle = isNew ? : ; @@ -82,6 +88,7 @@ EditContactContainer.manifest = Object.freeze({ contact: contactResource, [DICT_CATEGORIES]: categoriesResource, contactsOrg: organizationResource, + privilegedContact: privilegedContactResource, }); EditContactContainer.propTypes = { diff --git a/src/contacts/EditContact/EditContactContainer.test.js b/src/contacts/EditContact/EditContactContainer.test.js index 8d986dc7..0ed34708 100644 --- a/src/contacts/EditContact/EditContactContainer.test.js +++ b/src/contacts/EditContact/EditContactContainer.test.js @@ -9,6 +9,7 @@ import { DICT_CATEGORIES } from '../../common/constants'; import { saveContact } from './util'; import EditContact from './EditContact'; import { EditContactContainer } from './EditContactContainer'; +import { PRIVILEGED_CONTACT_URL_PATH } from '../constants'; jest.mock('./util', () => ({ saveContact: jest.fn(), @@ -29,6 +30,7 @@ const defaultProps = { [DICT_CATEGORIES]: { records: [{ value: 'Customer Service', id: 'f52ceea4-8e35' }], }, + privilegedContact: { records: [contact] }, }, showMessage: jest.fn(), onClose: jest.fn(), @@ -80,4 +82,37 @@ describe('EditContactContainer', () => { expect(saveContact).toHaveBeenCalled(); }); + + describe('Privileged contact actions', () => { + const props = { + ...defaultProps, + match: { + ...defaultProps.match, + path: `/contacts/view/:id/${PRIVILEGED_CONTACT_URL_PATH}`, + }, + onClose: undefined, + }; + + it('should save privileged contacts', async () => { + saveContact.mockClear().mockReturnValue(Promise.resolve()); + + renderEditContactContainer(props); + + await screen.findByText('EditContact'); + + EditContact.mock.calls[0][0].onSubmit({}); + + expect(saveContact).toHaveBeenCalled(); + }); + + it('should redirect to org details when form is closed', async () => { + renderEditContactContainer(props); + + await screen.findByText('EditContact'); + + EditContact.mock.calls[0][0].onClose(); + + expect(historyMock.push).toHaveBeenCalledWith('/organizations/orgId/privileged-contacts/id/view'); + }); + }); }); diff --git a/src/contacts/EditContact/util.js b/src/contacts/EditContact/util.js index 0b236b0c..2689bbab 100644 --- a/src/contacts/EditContact/util.js +++ b/src/contacts/EditContact/util.js @@ -1,7 +1,8 @@ // eslint-disable-next-line import/prefer-default-export -export const saveContact = (mutator, contact, org) => { +export const saveContact = (mutator, contact, org, isPrivilegedContactUrl = false) => { const isNew = !contact.id; - const httpMethod = isNew ? mutator.contact.POST : mutator.contact.PUT; + const currentMutator = isPrivilegedContactUrl ? mutator.privilegedContact : mutator.contact; + const httpMethod = isNew ? currentMutator.POST : currentMutator.PUT; return httpMethod(contact) .then(savedContact => { diff --git a/src/contacts/EditContact/util.test.js b/src/contacts/EditContact/util.test.js index 0775f6f8..d3eeb1a9 100644 --- a/src/contacts/EditContact/util.test.js +++ b/src/contacts/EditContact/util.test.js @@ -1,47 +1,56 @@ import { saveContact } from './util'; +const contactId = 'contactId'; +const contact = { name: 'Mark' }; +const contactWithId = { id: contactId, name: 'Mark' }; +const org = { id: 'org1', name: 'Amazon', contacts: [] }; + +const contactMutator = { + contact: { + POST: jest.fn().mockReturnValue(Promise.resolve({ ...contact, id: contactId })), + PUT: jest.fn().mockReturnValue(Promise.resolve()), + }, + privilegedContact: { + PUT: jest.fn().mockReturnValue(Promise.resolve()), + POST: jest.fn().mockReturnValue(Promise.resolve({ ...contact, id: contactId })), + }, + contactsOrg: { + PUT: jest.fn().mockReturnValue(Promise.resolve()), + }, +}; + describe('EditContact utils', () => { it('should create contact when contact without id', async () => { - const contact = { name: 'Mark' }; - const mutator = { - contact: { - POST: jest.fn().mockReturnValue(Promise.resolve()), - }, - }; - - await saveContact(mutator, contact); + await saveContact(contactMutator, contact); - expect(mutator.contact.POST).toHaveBeenCalledWith(contact); + expect(contactMutator.contact.POST).toHaveBeenCalledWith(contact); }); it('should update contact when contact with id', async () => { - const contact = { id: 'contactId', name: 'Mark' }; - const mutator = { - contact: { - PUT: jest.fn().mockReturnValue(Promise.resolve()), - }, - }; - - await saveContact(mutator, contact); + await saveContact(contactMutator, contactWithId); - expect(mutator.contact.PUT).toHaveBeenCalledWith(contact); + expect(contactMutator.contact.PUT).toHaveBeenCalledWith(contactWithId); }); it('should assign contact to org when contact is saved successfully and org is provided', async () => { - const contactId = 'contactId'; - const contact = { name: 'Mark' }; - const org = { id: 'org1', name: 'Amazon', contacts: [] }; - const mutator = { - contact: { - POST: jest.fn().mockReturnValue(Promise.resolve({ ...contact, id: contactId })), - }, - contactsOrg: { - PUT: jest.fn().mockReturnValue(Promise.resolve()), - }, - }; - - await saveContact(mutator, contact, org); - - expect(mutator.contactsOrg.PUT).toHaveBeenCalledWith({ ...org, contacts: [contactId] }); + await saveContact(contactMutator, contact, org); + + expect(contactMutator.contactsOrg.PUT).toHaveBeenCalledWith({ ...org, contacts: [contactId] }); + }); + + it('should create privileged contact', async () => { + const isPrivilegedContactUrl = true; + + await saveContact(contactMutator, contact, org, isPrivilegedContactUrl); + + expect(contactMutator.privilegedContact.POST).toHaveBeenCalledWith(contact); + }); + + it('should update privileged contact when with id', async () => { + const isPrivilegedContactUrl = true; + + await saveContact(contactMutator, contactWithId, org, isPrivilegedContactUrl); + + expect(contactMutator.privilegedContact.PUT).toHaveBeenCalledWith(contactWithId); }); }); diff --git a/src/contacts/ViewContact/ViewContact.js b/src/contacts/ViewContact/ViewContact.js index 59fad6a2..3d56a84e 100644 --- a/src/contacts/ViewContact/ViewContact.js +++ b/src/contacts/ViewContact/ViewContact.js @@ -34,6 +34,7 @@ import { ORGANIZATIONS_ROUTE } from '../../common/constants'; import { CONTACT_PERSON_ACCORDIONS, CONTACT_PERSON_ACCORDION_LABELS, + PRIVILEGED_CONTACT_URL_PATH, } from '../constants'; import ContactDetails from './ContactDetails'; import ContactAddresses from './ContactAddresses'; @@ -51,6 +52,7 @@ const ViewContact = ({ }) => { const history = useHistory(); const accordionStatusRef = useRef(); + const isPrivilegedContactUrl = history.location?.pathname?.includes(PRIVILEGED_CONTACT_URL_PATH); const stripes = useStripes(); @@ -81,6 +83,7 @@ const ViewContact = ({ // eslint-disable-next-line react/prop-types const getActionMenu = ({ onToggle }) => { const contactId = contact.id; + const isUnassignVisible = contactId && !isPrivilegedContactUrl; return (
    @@ -95,7 +98,7 @@ const ViewContact = ({ - {contactId && ( + {isUnassignVisible && (