diff --git a/CHANGELOG.md b/CHANGELOG.md index ca3b20810..5b60dddc6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,14 @@ * Leverage API supported sorting of columns on pre-registrations records list. Refs UIU-3249. * Fix issue with `Proxy borrower` field value. Refs UIU-3290. * Remove duplicates from the keyboard shortcut modal. Refs UIU-3026. -* Create/Edit a Patron Block - HTML page title. Refs UIU-3302. +* React v19: refactor away from default props for functional components. Refs. UIU-3141. +* Hide Create block button for user without permission. Refs UIU-3300. +* Add HTML page title to add/edit patron block page. Refs UIU-3302. + +## [11.0.10](https://github.com/folio-org/ui-users/tree/v11.0.10) (2025-01-10) +[Full Changelog](https://github.com/folio-org/ui-users/compare/v11.0.9...v11.0.10) + +* Add sub permission `manual-block-templates.collection.get` to permission `Users: Can create, edit and remove patron blocks`. Refs UIU-3305. ## [11.0.9](https://github.com/folio-org/ui-users/tree/v11.0.9) (2024-12-13) [Full Changelog](https://github.com/folio-org/ui-users/compare/v11.0.8...v11.0.9) @@ -13,6 +20,7 @@ * Add permission to access users-keycloak delete method. Refs UIU-3282. * Check if userId is present in withUserRoles HOC. Refs UIU-3273. * Add missed permissions for endpoints used in withUserRoles HOC. UIU-3294. +* Add view/manage roles permissions. Refs UIU-3301. ## [11.0.8](https://github.com/folio-org/ui-users/tree/v11.0.8) (2024-12-10) [Full Changelog](https://github.com/folio-org/ui-users/compare/v11.0.7...v11.0.8) diff --git a/package.json b/package.json index 0985a1e43..99fcc93c5 100644 --- a/package.json +++ b/package.json @@ -86,9 +86,7 @@ "departments.collection.get", "departments.item.get", "users.configurations.item.get", - "roles.users.collection.get", - "users-keycloak.auth-users.item.get", - "roles.collection.get" + "users-keycloak.auth-users.item.get" ], "visible": true }, @@ -106,7 +104,6 @@ "tags.item.post", "circulation-storage.request-preferences.item.post", "circulation-storage.request-preferences.item.put", - "roles.users.item.put", "users-keycloak.auth-users.item.post" ], "visible": true @@ -173,6 +170,24 @@ ], "visible": true }, + { + "permissionName": "ui-users.roles.view", + "displayName": "Users: Can view user/role assignments", + "description": "Also includes basic permissions to view roles, users, patron groups", + "subPermissions": [ + "ui-authorization-roles.users.settings.view" + ], + "visible": true + }, + { + "permissionName": "ui-users.roles.manage", + "displayName": "Users: Can manage user/role assignments", + "description": "", + "subPermissions": [ + "ui-authorization-roles.users.settings.manage" + ], + "visible": true + }, { "permissionName": "ui-users.user-service-points.view", "displayName": "Users: Can view service points assigned to users", @@ -598,6 +613,7 @@ "replaces": ["ui-users.patron_blocks"], "subPermissions": [ "manualblocks.collection.get", + "manual-block-templates.collection.get", "manualblocks.item.delete", "manualblocks.item.get", "manualblocks.item.post", diff --git a/src/components/AffiliationsManager/AffiliationsManager.js b/src/components/AffiliationsManager/AffiliationsManager.js index 257609f4a..b0bb0368d 100644 --- a/src/components/AffiliationsManager/AffiliationsManager.js +++ b/src/components/AffiliationsManager/AffiliationsManager.js @@ -5,11 +5,11 @@ import { AffiliationsManagerModal } from './AffiliationsManagerModal'; import AffiliationsManagerTrigger from './AffiliationsManagerTrigger'; const AffiliationsManager = ({ - disabled, + disabled = false, onUpdateAffiliations, - renderTrigger, + renderTrigger = AffiliationsManagerTrigger, userId, - withTrigger, + withTrigger = true, }) => { const [isModalOpen, toggleModal] = useToggle(!withTrigger); @@ -36,10 +36,4 @@ AffiliationsManager.propTypes = { withTrigger: PropTypes.bool, }; -AffiliationsManager.defaultProps = { - disabled: false, - renderTrigger: AffiliationsManagerTrigger, - withTrigger: true, -}; - export default AffiliationsManager; diff --git a/src/components/AffiliationsSelect/AffiliationsSelect.js b/src/components/AffiliationsSelect/AffiliationsSelect.js index 18faab0b1..6dcde943f 100644 --- a/src/components/AffiliationsSelect/AffiliationsSelect.js +++ b/src/components/AffiliationsSelect/AffiliationsSelect.js @@ -13,7 +13,7 @@ import { Selection } from '@folio/stripes/components'; import { affiliationsShape } from '../../shapes'; const AffiliationsSelect = ({ - id, + id = 'user-assigned', affiliations, value, onChange, @@ -53,10 +53,6 @@ const AffiliationsSelect = ({ ); }; -AffiliationsSelect.defaultProps = { - id: 'user-assigned', -}; - AffiliationsSelect.propTypes = { affiliations: affiliationsShape, onChange: PropTypes.func.isRequired, diff --git a/src/components/AssignedUsers/AssignedUsersContainer.js b/src/components/AssignedUsers/AssignedUsersContainer.js index 996a33385..54da168b6 100644 --- a/src/components/AssignedUsers/AssignedUsersContainer.js +++ b/src/components/AssignedUsers/AssignedUsersContainer.js @@ -24,7 +24,12 @@ import AssignUsers from './AssignUsers'; import AssignedUsersList from './AssignedUsersList'; import { getUpdatedUsersList } from './utils'; -const AssignedUsersContainer = ({ permissionSetId, expanded, onToggle, tenantId }) => { +const AssignedUsersContainer = ({ + permissionSetId, + expanded = true, + onToggle, + tenantId +}) => { const callout = useCallout(); const intl = useIntl(); @@ -123,8 +128,4 @@ AssignedUsersContainer.propTypes = { tenantId: PropTypes.string, }; -AssignedUsersContainer.defaultProps = { - expanded: true, -}; - export default AssignedUsersContainer; diff --git a/src/components/AssignedUsers/AssignedUsersList.js b/src/components/AssignedUsers/AssignedUsersList.js index b4c7234a3..7e3b14d8f 100644 --- a/src/components/AssignedUsers/AssignedUsersList.js +++ b/src/components/AssignedUsers/AssignedUsersList.js @@ -12,7 +12,7 @@ import { VISIBLE_COLUMNS, } from './constants'; -const AssignedUsersList = ({ users, isFetching }) => ( +const AssignedUsersList = ({ users = [], isFetching = false }) => ( { const { failedRenewals, successRenewals, - height, + height = 300, errorMessages, requestCounts, loanPolicies, @@ -126,7 +122,6 @@ const BulkRenewedLoansList = (props) => { ); }; -BulkRenewedLoansList.defaultProps = defaultProps; BulkRenewedLoansList.propTypes = propTypes; export default BulkRenewedLoansList; diff --git a/src/components/EditSections/EditUserInfo/components/ChangeUserTypeModal/ChangeUserTypeModal.js b/src/components/EditSections/EditUserInfo/components/ChangeUserTypeModal/ChangeUserTypeModal.js index dece42bc5..863d4e517 100644 --- a/src/components/EditSections/EditUserInfo/components/ChangeUserTypeModal/ChangeUserTypeModal.js +++ b/src/components/EditSections/EditUserInfo/components/ChangeUserTypeModal/ChangeUserTypeModal.js @@ -9,7 +9,7 @@ import { import { USER_TYPES } from '../../../../../constants'; -const ChangeUserTypeModal = ({ onChange, initialUserType, open }) => { +const ChangeUserTypeModal = ({ onChange, initialUserType, open = false }) => { const userTypeModalFooter = ( + + + ); }; @@ -90,41 +93,45 @@ function EditUserRoles({ accordionId, form:{ change }, setAssignedRoleIds, assig } return ( -
- } - id={accordionId} - displayWhenClosed={{assignedRoleIds.length}} - > - - {renderUserRoles()} - - - - - setIsOpen(false)} - initialRoleIds={assignedRoleIds} - changeUserRoles={changeUserRoles} - /> - } - message={unassignAllMessage} - onConfirm={handleUnassignAllRoles} - onCancel={() => setUnassignModalOpen(false)} - cancelLabel={} - confirmLabel={} - /> - - {(userAssignedRoleIds) => { - const userRoleIds = isEmpty(userAssignedRoleIds) ? [] : userAssignedRoleIds; - setAssignedRoleIds(userRoleIds); - }} - -
+ +
+ } + id={accordionId} + displayWhenClosed={{assignedRoleIds.length}} + > + + {renderUserRoles()} + + + + + + + setIsOpen(false)} + initialRoleIds={assignedRoleIds} + changeUserRoles={changeUserRoles} + /> + } + message={unassignAllMessage} + onConfirm={handleUnassignAllRoles} + onCancel={() => setUnassignModalOpen(false)} + cancelLabel={} + confirmLabel={} + /> + + {(userAssignedRoleIds) => { + const userRoleIds = isEmpty(userAssignedRoleIds) ? [] : userAssignedRoleIds; + setAssignedRoleIds(userRoleIds); + }} + +
+
); } diff --git a/src/components/EditSections/EditUserRoles/EditUserRoles.test.js b/src/components/EditSections/EditUserRoles/EditUserRoles.test.js index 3dfa5bc7b..563762049 100644 --- a/src/components/EditSections/EditUserRoles/EditUserRoles.test.js +++ b/src/components/EditSections/EditUserRoles/EditUserRoles.test.js @@ -4,6 +4,7 @@ import { cleanup, waitFor } from '@folio/jest-config-stripes/testing-library/rea import userEvent from '@folio/jest-config-stripes/testing-library/user-event'; import renderWithRouter from 'helpers/renderWithRouter'; import { + IfPermission, useStripes, } from '@folio/stripes/core'; import { Form } from 'react-final-form'; @@ -19,6 +20,7 @@ jest.mock('../../../hooks', () => ({ jest.mock('@folio/stripes/core', () => ({ ...jest.requireActual('@folio/stripes/core'), useStripes: jest.fn(), + IfPermission: jest.fn() })); jest.unmock('@folio/stripes/components'); @@ -95,6 +97,7 @@ describe('EditUserRoles Component', () => { beforeEach(() => { useStripes.mockClear().mockReturnValue(STRIPES); useAllRolesData.mockClear().mockReturnValue(mockAllRolesData); + IfPermission.mockImplementation(({ children }) => children); }); afterEach(cleanup); @@ -106,6 +109,22 @@ describe('EditUserRoles Component', () => { expect(queryByText('simple role')).not.toBeInTheDocument(); }); + it('hides the roles accordion when user doesn\'t have view roles permission', () => { + IfPermission.mockImplementation(({ perm, children }) => (perm !== 'ui-authorization-roles.users.settings.view' ? children : null)); + const { queryByText } = renderEditRolesAccordion(propsData); + + expect(queryByText('ui-users.roles.userRoles')).not.toBeInTheDocument(); + }); + + it('hides the add role button when user doesn\'t have manage roles permission', () => { + IfPermission.mockImplementation(({ perm, children }) => (perm !== 'ui-authorization-roles.users.settings.manage' ? children : null)); + const { getByText, queryByText } = renderEditRolesAccordion(propsData); + + expect(getByText('test role')).toBeInTheDocument(); + expect(getByText('admin role')).toBeInTheDocument(); + expect(queryByText('ui-users.roles.addRoles')).not.toBeInTheDocument(); + }); + it('calls delete user role function', async () => { const id = `clickable-remove-user-role-${mockAllRolesData.data.roles[0].id}`; renderEditRolesAccordion(propsData); diff --git a/src/components/EditSections/EditUserRoles/components/CheckboxColumn/CheckboxColumn.js b/src/components/EditSections/EditUserRoles/components/CheckboxColumn/CheckboxColumn.js index 7863ee63b..442006136 100644 --- a/src/components/EditSections/EditUserRoles/components/CheckboxColumn/CheckboxColumn.js +++ b/src/components/EditSections/EditUserRoles/components/CheckboxColumn/CheckboxColumn.js @@ -9,9 +9,9 @@ import css from './CheckboxColumn.css'; const CheckboxColumn = memo(props => { const { value, - checked, + checked = false, roleName, - onChange, + onChange = noop, } = props; return ( @@ -39,9 +39,4 @@ CheckboxColumn.propTypes = { onChange: PropTypes.func, }; -CheckboxColumn.defaultProps = { - checked: false, - onChange: noop, -}; - export default CheckboxColumn; diff --git a/src/components/Loans/components/ActionsBar/ActionsBar.js b/src/components/Loans/components/ActionsBar/ActionsBar.js index c522f4d02..ca17e1311 100644 --- a/src/components/Loans/components/ActionsBar/ActionsBar.js +++ b/src/components/Loans/components/ActionsBar/ActionsBar.js @@ -12,11 +12,7 @@ const propTypes = { contentEnd: PropTypes.oneOfType([PropTypes.element, PropTypes.func]), }; -const defaultProps = { - show: true, -}; - -const ActionsBar = ({ show, contentStart, contentEnd }) => { +const ActionsBar = ({ show = true, contentStart, contentEnd }) => { if (!show) { return null; } @@ -30,6 +26,5 @@ const ActionsBar = ({ show, contentStart, contentEnd }) => { }; ActionsBar.propTypes = propTypes; -ActionsBar.defaultProps = defaultProps; export default ActionsBar; diff --git a/src/components/PermissionsAccordion/PermissionsAccordion.js b/src/components/PermissionsAccordion/PermissionsAccordion.js index 8c673cdc4..fa76a26b9 100644 --- a/src/components/PermissionsAccordion/PermissionsAccordion.js +++ b/src/components/PermissionsAccordion/PermissionsAccordion.js @@ -33,9 +33,9 @@ const PermissionsAccordion = (props) => { const { accordionId, affiliations, - disabled, + disabled = false, expanded, - onChangeAffiliation, + onChangeAffiliation = noop, onToggle, permToModify, permToDelete, @@ -43,9 +43,9 @@ const PermissionsAccordion = (props) => { filtersConfig, visibleColumns, headlineContent, - excludePermissionSets, - initialValues: { personal }, - isLoading, + excludePermissionSets = false, + initialValues: { personal } = {}, + isLoading = false, form: { change }, setButtonRef, tenantId, @@ -310,12 +310,4 @@ PermissionsAccordion.propTypes = { setButtonRef: PropTypes.func }; -PermissionsAccordion.defaultProps = { - disabled: false, - excludePermissionSets: false, - initialValues: {}, - isLoading: false, - onChangeAffiliation: noop, -}; - export default stripesConnect(injectIntl(PermissionsAccordion)); diff --git a/src/components/PermissionsAccordion/components/CheckboxColumn/CheckboxColumn.js b/src/components/PermissionsAccordion/components/CheckboxColumn/CheckboxColumn.js index bfb1dab4c..b1c0b7b0f 100644 --- a/src/components/PermissionsAccordion/components/CheckboxColumn/CheckboxColumn.js +++ b/src/components/PermissionsAccordion/components/CheckboxColumn/CheckboxColumn.js @@ -9,9 +9,9 @@ import css from './CheckboxColumn.css'; const CheckboxColumn = memo(props => { const { value, - checked, + checked = false, permissionName, - onChange, + onChange = noop, } = props; return ( @@ -39,9 +39,4 @@ CheckboxColumn.propTypes = { onChange: PropTypes.func, }; -CheckboxColumn.defaultProps = { - checked: false, - onChange: noop, -}; - export default CheckboxColumn; diff --git a/src/components/UserDetailSections/PatronBlock/PatronBlock.js b/src/components/UserDetailSections/PatronBlock/PatronBlock.js index e9a16b9f9..2831cbb95 100644 --- a/src/components/UserDetailSections/PatronBlock/PatronBlock.js +++ b/src/components/UserDetailSections/PatronBlock/PatronBlock.js @@ -14,7 +14,10 @@ import { Button, Headline } from '@folio/stripes/components'; -import { stripesConnect } from '@folio/stripes/core'; +import { + IfPermission, + stripesConnect, +} from '@folio/stripes/core'; import { isDcbUser } from '../../util'; import css from './PatronBlock.css'; @@ -176,18 +179,18 @@ class PatronBlock extends React.Component { sortDirection, } = this.state; - const buttonDisabled = this.props.stripes.hasPerm('ui-users.patron-blocks.all'); const displayWhenOpen = - ; + + + ; const items = {items} - ); } } diff --git a/src/components/UserDetailSections/UserRoles/UserRoles.js b/src/components/UserDetailSections/UserRoles/UserRoles.js index cedcf2002..920e447d3 100644 --- a/src/components/UserDetailSections/UserRoles/UserRoles.js +++ b/src/components/UserDetailSections/UserRoles/UserRoles.js @@ -41,7 +41,7 @@ const UserRoles = (props) => { return (} - permToRead="roles.users.collection.get" + permToRead="ui-authorization-roles.users.settings.view" affiliations={affiliations} selectedAffiliation={tenantId} isLoading={isLoading} diff --git a/src/views/LostItems/LostItemsListContainer/components/LostItemsList/components/InstanceDetails/components/ShowLongContentInPopover/ShowLongContentInPopover.js b/src/views/LostItems/LostItemsListContainer/components/LostItemsList/components/InstanceDetails/components/ShowLongContentInPopover/ShowLongContentInPopover.js index c04f3674d..6da93ff52 100644 --- a/src/views/LostItems/LostItemsListContainer/components/LostItemsList/components/InstanceDetails/components/ShowLongContentInPopover/ShowLongContentInPopover.js +++ b/src/views/LostItems/LostItemsListContainer/components/LostItemsList/components/InstanceDetails/components/ShowLongContentInPopover/ShowLongContentInPopover.js @@ -34,8 +34,8 @@ export const getComponentText = (text, additionalText = defaultAdditionalText, c const ShowLongContentInPopover = ({ text, - additionalText, - contentLength, + additionalText = defaultAdditionalText, + contentLength = defaultContentLength, }) => { const { contentText, @@ -61,9 +61,4 @@ ShowLongContentInPopover.propTypes = { contentLength: PropTypes.number, }; -ShowLongContentInPopover.defaultProps = { - additionalText: defaultAdditionalText, - contentLength: defaultContentLength, -}; - export default ShowLongContentInPopover; diff --git a/translations/ui-users/pt_BR.json b/translations/ui-users/pt_BR.json index 90a870ac2..56bcb7c4f 100644 --- a/translations/ui-users/pt_BR.json +++ b/translations/ui-users/pt_BR.json @@ -1210,7 +1210,7 @@ "permission.fee-fine-actions.all": "Detalhes de taxas/multas: Pode criar, editar e remover ações de taxa/multa", "permission.loans-anonymize.execute": "Usuários: Anomnimizar empréstimos de usuário", "permission.loans-due-date.edit": "Usuários: Empréstimos de usuários - alterar a data de vencimento", - "permission.loans-claim-item-returned.execute": "Usuários: Reivindicação de empréstimos de usuários devolvida", + "permission.loans-claim-item-returned.execute": "Usuários: Reclamação de empréstimos de usuários devolvida", "permission.loans-declare-claimed-returned-item-as-missing.execute": "Usuários: Empréstimos de usuários - marcados como reivindicados, devolvidos como desaparecidos", "permission.loans-declare-item-lost.execute": "Usuários: declarar como perdido empréstimos de usuários", "permission.loans-renew-override.create": "Usuários: Renovação de empréstimos de usuários por meio de sobreposição", diff --git a/translations/ui-users/zh_TW.json b/translations/ui-users/zh_TW.json index f3f7b2df6..37bb64d52 100644 --- a/translations/ui-users/zh_TW.json +++ b/translations/ui-users/zh_TW.json @@ -1,6 +1,6 @@ { "data.contactTypes.email": "電子郵件", - "data.contactTypes.mail": "郵件(主要地址)", + "data.contactTypes.mail": "郵件地址 ( 主要 )", "data.contactTypes.textMessage": "文字訊息", "data.loanActionMap.checkedOut": "已借出", "data.loanActionMap.checkedIn": "已歸還", @@ -43,8 +43,8 @@ "permissions.addPermission": "新增權限", "permissions.availablePermissions": "可用權限", "permissions.userPermissions": "使用者權限", - "permissions.isProxyFor": "保證人({name} 可以代表保證人進行借閱)", - "permissions.isSponsorOf": "代理人(代理人可以代表 {name} 進行借用)", + "permissions.isProxyFor": "保證人 ( {name} 可以代表保證人進行借閱 )", + "permissions.isSponsorOf": "代理人 ( 代理人可以代表 {name} 進行借閱 )", "permissions.assignedPermissions": "已指派的權限", "permissions.untitledPermissionSet": "未命名的權限組合", "permissions.closePermissionSetDialog": "關閉權限組合對話框", @@ -251,7 +251,7 @@ "details.field.location": "館藏地", "details.field.duedate": "到期日", "details.field.returnedate": "已歸還日期", - "accounts.history.columns.title": "實例(資料類型)", + "accounts.history.columns.title": "實例 ( 資料類型 )", "accounts.history.columns.amount": "帳款", "accounts.history.columns.remaining": "剩餘金額", "accounts.history.columns.barcode": "條碼", @@ -303,7 +303,7 @@ "systemReturnDate": "系統歸還日期", "item.barcode": "條碼", "item.contributors": "貢獻者姓名", - "item.holdingsRecordId": "館藏記錄ID", + "item.holdingsRecordId": "館藏紀錄 ID", "item.instanceId": "實例ID", "item.status.name": "館藏狀態", "item.title": "館藏題名", @@ -351,12 +351,12 @@ "blocks.form.label.staff": "資訊僅限館員閱讀", "blocks.form.label.message": "給讀者的訊息", "blocks.form.label.date": "有效期限", - "blocks.form.label.block": "凍結操作 * (選擇所有適用選項)", + "blocks.form.label.block": "凍結操作 * ( 選擇所有適用選項 )", "blocks.form.label.borrowing": "外借中", "blocks.form.label.renewals": "續借", - "blocks.form.placeholder.desc": "輸入簡短描述(必填)", - "blocks.form.placeholder.information": "輸入附加資訊(選填)", - "blocks.form.placeholder.message": "輸入給讀者的訊息(選填)", + "blocks.form.placeholder.desc": "輸入簡短描述 ( 必填 )", + "blocks.form.placeholder.information": "輸入附加資訊 ( 選填 )", + "blocks.form.placeholder.message": "輸入給讀者的訊息 ( 選填 )", "blocks.form.validate.desc": "描述為必填", "blocks.form.validate.any": "選擇任一選項", "blocks.form.validate.date": "到期日為必填", @@ -408,7 +408,7 @@ "cddd.dateRequired": "日期 *", "cddd.timeRequired": "時間 *", "additionalInfo.label": "附加資訊", - "additionalInfo.placeholder": "輸入有關越權的更多訊息(必填)", + "additionalInfo.placeholder": "輸入有關越權的更多資訊 ( 必填 )", "button.override": "越權", "override.emptyNewDueDate": "選擇上方的到期日", "loans.feeFineDetails": "費用 / 罰款 詳細資料", @@ -428,7 +428,7 @@ "override.autoNewDueDate": "到期日將自動計算", "blocks.form.button.close": "關閉讀者凍結對話框", "blocks.layer.newBlockTitle": "新凍結", - "accounts.totalOpenAccounts": "(總計: {amount} )", + "accounts.totalOpenAccounts": "( 總計 : {amount} )", "accounts.status.outstanding": "未結", "feefines.defaultChargeNotice": "預設收費通知", "feefines.defaultActionNotice": "預設操作通知", @@ -463,7 +463,7 @@ "accounts.viewAllFeesFines": "檢視所有費用/罰款", "save": "儲存", "reports.overdue.item.contributors": "貢獻者", - "reports.overdue.label": "逾期借閱報告(CSV)", + "reports.overdue.label": "逾期借閱報告 ( CSV )", "accounts.transfer.error.amount": "轉帳金額必須大於零", "accounts.transfer.error.exceeds": "轉帳金額超過所選金額", "accounts.transfer.modalLabel": "轉移費用 / 罰款", @@ -480,7 +480,7 @@ "accounts.commentStaff": "給館員的附加資訊", "accounts.notifyPatron": "通知讀者", "accounts.infoPatron": "給讀者的附加資訊", - "accounts.optional": "可選擇", + "accounts.optional": "選填", "accounts.required": "必填", "accounts.summary": "{type} {count} {count, plural, one {費用/罰款} other {費用/罰款}}總金額為 {amount} ", "accounts.payment.modalLabel": "支付費用 / 罰款", @@ -547,13 +547,13 @@ "requests.selectDeliveryAddress": "選擇收件地址", "addAddressError": "請在“地址”部分增加至少一處地址", "requests.defaultPickupServicePoint": "預設取書服務據點", - "errors.currentUser.expired": "當前使用者記錄已過期", + "errors.currentUser.expired": "當前使用者紀錄已過期", "data.loanActionMap.declaredLost": "宣告遺失", "confirm": "確認", "loans.declareLost": "宣告遺失", "loans.declareLostDialogBody": " {title} ( {materialType} ) (條碼: {barcode} ) 將宣告為遺失 。 {countIndex, plural, =-1 {可能有對該館藏的開放預約。 } =0 {} one {此館藏有{openRequestValue} 。 } other {這個館藏有{openRequestValue} 。 }}", "loans.confirmLostState": "確認宣告遺失狀態", - "loans.declareLost.additionalInfoPlaceholder": "輸入有關遺失館藏的更多資訊(必填)", + "loans.declareLost.additionalInfoPlaceholder": "輸入有關遺失館藏的更多資訊 ( 必填 )", "userSearch": "使用者搜尋", "userSearchResults": "使用者查詢結果", "feefines.ownerLabel": "所有者", @@ -574,9 +574,9 @@ "item.volume": "卷", "loans.details.effectiveCallNumber": "有效的索書號字串", "settings.customFields": "自訂欄位", - "details.field.instance.type": "實例(資料類型)", - "accounts.history.columns.instance": "實例(資料類型)", - "feefines.errors.reservedName": "費用/罰款類型已作為自動費用/罰款存在", + "details.field.instance.type": "實例 ( 資料類型 )", + "accounts.history.columns.instance": "實例 ( 資料類型 )", + "feefines.errors.reservedName": "費用 / 罰款類型已做為自動費用 / 罰款存在", "accounts.payment.error.select": "費用/罰款所有者不存在付款方式", "accounts.waive.error.select": "未填寫免除理由", "accounts.transfer.error.select": "費用/罰款所有者不存在轉帳帳戶", @@ -595,10 +595,10 @@ "permission.loans.all": "使用者:使用者借閱檢視,更改到期日,續借", "permission.loans.view": "使用者:使用者借閱檢視", "permission.requests.all": "使用者:檢視預約", - "permission.settings.customfields.all": "設定(使用者):可建立、編輯、檢視和刪除自訂欄位", - "permission.settings.customfields.edit": "設定(使用者):可新增、編輯、檢視自訂欄位", - "permission.settings.customfields.view": "設定(使用者):可檢視自訂欄位", - "permission.settings.feefine": "設定(使用者):可新增、編輯和移除費用/罰款設定", + "permission.settings.customfields.all": "設定 ( 使用者 ) : 可建立、編輯、檢視和刪除自訂欄位", + "permission.settings.customfields.edit": "設定 ( 使用者 ) : 可新增、編輯、檢視自訂欄位", + "permission.settings.customfields.view": "設定 ( 使用者 ) : 可檢視自訂欄位", + "permission.settings.feefine": "設定 ( 使用者 ) : 可新增、編輯和移除費用 / 罰款設定", "permission.view": "使用者:可以檢視使用者設定文件", "loans.history": "借閱歷史", "accounts.loading": "帳戶載入中", @@ -611,8 +611,8 @@ "loans.confirmAsMissing": "確認館藏遺失", "data.loanActionMap.closedLoan": "已關閉借閱", "loans.numClaimedReturnedLoans": "( {count, number} {count, plural, one {聲稱歸還} other {聲稱歸還}} )", - "data.loanActionMap.checkedInReturnedByPatron": "已歸還(由讀者歸還)", - "data.loanActionMap.checkedInFoundByLibrary": "已歸還(由圖書館尋獲)", + "data.loanActionMap.checkedInReturnedByPatron": "已歸還 ( 由讀者歸還 )", + "data.loanActionMap.checkedInFoundByLibrary": "已歸還 ( 由圖書館尋獲 )", "bulkClaimReturned.item.title": "題名", "bulkClaimReturned.preConfirm": "確認宣稱已還", "bulkClaimReturned.postConfirm": "宣稱已歸還確認", @@ -622,9 +622,9 @@ "bulkClaimReturned.status.notOk": "館藏無法申請歸還:館藏已宣稱歸還", "bulkClaimReturned.items.ok": "{numItems}館藏成功宣稱歸還。", "bulkClaimReturned.items.notOk": "{numItems}館藏宣稱已歸還。", - "bulkClaimReturned.moreInfoPlaceholder": "輸入有關賠償的更多資訊(必填)", + "bulkClaimReturned.moreInfoPlaceholder": "輸入有關賠償的更多資訊 ( 必填 )", "loans.resolveClaim": "解決聲稱", - "blocks.columns.automated.type": "自動(無法編輯)", + "blocks.columns.automated.type": "自動 ( 無法編輯 )", "permission.reset.password": "使用者:建立/重設密碼", "errors.proxies.duplicateUserMessage": "已輸入重複的代理人。", "errors.sponsors.duplicateUserMessage": "已輸入重複的保證人。", @@ -650,12 +650,12 @@ "extended.department.add": "新增系所", "extended.department.default": "選擇系所", "item.copyNumber": "複本號", - "permission.settings.departments.view": "設定(使用者):檢視系所", - "permission.settings.departments.edit": "設定(使用者):編輯系所", - "permission.settings.departments.create": "設定(使用者):建立系所", - "permission.settings.departments.delete": "設定(使用者):刪除系所", - "permission.settings.departments.create.edit.view": "設定(使用者):建立、編輯、檢視系所", - "permission.settings.departments.all": "設定(使用者):建立、編輯、檢視和刪除系所", + "permission.settings.departments.view": "設定 ( 使用者 ) : 檢視系所", + "permission.settings.departments.edit": "設定 ( 使用者 ) : 編輯系所", + "permission.settings.departments.create": "設定 ( 使用者 ) : 建立系所", + "permission.settings.departments.delete": "設定 ( 使用者 ) : 刪除系所", + "permission.settings.departments.create.edit.view": "設定( 使用者 ) : 建立、編輯、檢視系所", + "permission.settings.departments.all": "設定 ( 使用者 ) : 建立、編輯、檢視和刪除系所", "loans.action.source.system": "系统", "accounts.otherOwed": "所欠的其他費用/罰款", "accounts.totalPaid": "總支付金額", @@ -671,7 +671,7 @@ "accounts.actions.warning.refundAction": "已退款", "accounts.actions.refund": "退款", "reports.noItemsFound": "沒有找到館藏", - "reports.claimReturned.label": "宣稱已歸還報表(CSV)", + "reports.claimReturned.label": "宣稱已歸還報表 ( CSV )", "reports.borrower.name": "借閱者姓名", "reports.borrower.barcode": "借閱者條碼", "reports.borrowerId": "借閱者編號", @@ -705,7 +705,7 @@ "loans.confirmDeclaredLost": "確認館藏狀態:申報遺失", "loans.confirmClaimedReturned": "確認館藏狀態: 宣稱歸還", "loans.confirmMissing": "確認館藏狀態: 遺失", - "information.patronGroup.expirationOffset": "到期日期偏移設定(天)", + "information.patronGroup.expirationOffset": "到期日偏移設定 ( 天 )", "reports.item.contributors": "貢獻者", "information.patronGroup.expirationOffset.error": "必須為空白或整數> 0", "settings.manualBlockTemplates": "範本", @@ -724,7 +724,7 @@ "loan404": "無法檢索到預約借閱", "actions": "操作", "showColumns": "顯示欄位", - "reports.refunds.label": "手動退款報告(CSV)", + "reports.refunds.label": "人工退款報告 ( CSV )", "reports.refunds.modal.label": "人工處理退款", "reports.refunds.modal.message": "指定日期退款輸入範圍", "reports.refunds.modal.startDate": "起始日期", @@ -818,7 +818,7 @@ "loans.columns.feefineIncurred": "產生的費用 / 罰款", "loans.details.fineIncurred": "產生的費用 / 罰款", "errors.userNotFound": "未找到使用者", - "reports.cashDrawer.label": "現金對帳報告(CSV, PDF)", + "reports.cashDrawer.label": "現金對帳報告 ( CSV, PDF )", "reports.financialTransaction.label": "財務交易明細報告 (CSV)", "shortcut.openShortcutModal": "開啟鍵盤快捷鍵模組", "accounts.outstanding.total": "未結餘額總額: {amount}", @@ -833,7 +833,7 @@ "reports.cash.drawer.sources.placeholder": "選擇資源", "reports.cash.drawer.report.format": "報表格式", "reports.cash.drawer.report.format.csv": "CSV", - "reports.cash.drawer.report.format.pdf": "PDF(唯讀)", + "reports.cash.drawer.report.format.pdf": "PDF ( 唯讀 )", "reports.cash.drawer.report.format.both": "兩個都", "reports.cash.drawer.report.startDate.error": "“開始日期”為必填項", "reports.cash.drawer.report.endDateWithoutStart.error": "如果輸入“結束日期”,也需要輸入“開始日期”", @@ -865,7 +865,7 @@ "settings.transferCriteria": "匯款條件", "settings.transferCriteria.notAvailable": "沒有可使用的外掛程式!", "details.label.loanAnonymized": "匿名", - "accounts.history.button.loanAnonymized": "借閱詳細資訊(匿名)", + "accounts.history.button.loanAnonymized": "借閱詳細資訊 ( 匿名 )", "details.checkDelete": "檢查未結交易/刪除 使用者", "details.checkDelete.confirmation": "使用者 {name} 沒有未結交易。

您確定要刪除該使用者嗎?

", "details.openTransactions": "未结交易", @@ -996,7 +996,7 @@ "lostItems.modal.button.keepEditing": "繼續編輯", "lostItems.modal.button.confirm": "確認", "errorModal.currentUserServicePointAbsentee.label": "存取被拒絕", - "errorModal.currentUserServicePointAbsentee.message": "您必須選擇一個服務據點才能建立和檢視讀者費用/罰款 。請在使用者應用程式中將一個或多個服務地點新增至您的使用者記錄。如果您無法將服務據點新增至您的記錄中,請聯絡系統管理員。", + "errorModal.currentUserServicePointAbsentee.message": "您必須選擇一個服務據點才能建立和檢視 讀者費用 / 罰款 。請在 使用者 紀錄應用程式中將一個或多個服務地點新增至您的使用者紀錄。如果您無法將服務據點新增至您的紀錄中,請聯絡系統管理員。", "errorModal.currentUserServicePointAbsentee.confirmButtonText": "返回", "lostItems.feeFineAmount.error": "向讀者開立帳單的實際費用必須大於 0.00 且小於 9999.99", "lostItems.notification.serverError": "系統發生錯誤 - 請稍後重試或聯絡您的 FOLIO 支援人員", @@ -1028,7 +1028,7 @@ "affiliations.manager.modal.aria.assignAll": "分配所有隸屬關係", "affiliations.manager.modal.aria.search": "搜尋隸屬關係", "affiliations.manager.modal.totalSelected": "已選擇總數: {count}", - "affiliations.manager.modal.warning.unassigned": "取消指派隸屬關係將刪除與此使用者記錄的該隸屬關係關聯的所有權限。", + "affiliations.manager.modal.warning.unassigned": "取消指派隸屬關係將刪除與此使用者紀錄的該隸屬關係關聯的所有權限。", "affiliations.manager.result.title": "隸屬關係", "affiliations.manager.result.subTitle": "{amount, plural, one {# affiliation found} other {# affiliations found}}", "affiliations.section.action.edit": "分配 / 取消分配", @@ -1049,45 +1049,45 @@ "data.loanActionMap.staffInfo.superseded": "館員資訊 ( 已取代 )", "loans.newPatronInfo": "新讀者資訊", "loans.newStaffInfo": "新館員資訊", - "loans.patronInfoDialogBody": "為 {title} ( {materialType} ) 新增新讀者資訊(條碼: {barcode} )。這將取代之前新增的任何讀者資訊。", - "loans.staffInfoDialogBody": "為 {title} ( {materialType} ) 新增新的員工資訊(條碼: {barcode} )。", + "loans.patronInfoDialogBody": "為 {title} ( {materialType} ) 新增新讀者資訊 ( 條碼 : {barcode} )。這將取代之前新增的任何讀者資訊。", + "loans.staffInfoDialogBody": "為 {title} ( {materialType} ) 新增新的員工資訊 ( 條碼 : {barcode} )。", "loans.addInfo.patron": "新增新讀者訊息", "loans.addInfo.staff": "新增新職員資訊", "errors.affiliationsLoadFailed": " {tenantId} 租用戶中使用者 {user} 的隸屬關係載入失敗。", "errors.permissionsLoadFailed": " {tenantId} 租用戶中的使用者 {user} 權限載入失敗。", "affiliations.select.label": "隸屬關係", - "permission.settings.view": "設定(使用者):檢視所有設定", - "permission.settings.addresstypes.view": "設定(使用者):可以檢視地址類型", - "permission.settings.addresstypes.all": "設定(使用者):可以建立、編輯和移除地址類型", - "permission.settings.comments.view": "設定(使用者):如果需要評論可以檢視", - "permission.settings.comments.all": "設定(使用者):如果需要評論可以編輯", - "permission.settings.conditions.view": "設定(使用者):可以檢視讀者區塊條件", - "permission.settings.conditions.edit": "設定(使用者):可以檢視和編輯讀者限制條件", - "permission.settings.limits.view": "設定(使用者):可以檢視讀者區塊限制", - "permission.settings.limits.all": "設定(使用者):可以建立、編輯和移除讀者限制", - "permission.settings.manual-charges.view": "設定(使用者):可以檢視人工收費", - "permission.settings.manual-charges.all": "設定(使用者):可以建立、編輯和移除手動費用", - "permission.settings.owners.view": "設定(使用者):可以檢視所有者", - "permission.settings.owners.all": "設定(使用者):可以建立、編輯和移除所有者", - "permission.settings.patron-block-templates.view": "設定(使用者):可以檢視讀者區塊模板", - "permission.settings.patron-block-templates.all": "設定(使用者):可以建立、編輯和移除讀者區塊模板", - "permission.settings.payments.view": "設定(使用者):可以檢視付款方式", - "permission.settings.payments.all": "設定(使用者):可以建立、編輯和移除付款方式", - "permission.settings.permsets.view": "設定(使用者):可以檢視權限集", - "permission.settings.permsets.all": "設定(使用者):可以建立、編輯和移除權限集", - "permission.settings.refunds.view": "設定(使用者):可以檢視退款原因", - "permission.settings.refunds.all": "設定(使用者):可以建立、編輯和移除退款原因", - "permission.settings.transfers.view": "設定(使用者):可以檢視轉帳帳戶 ", - "permission.settings.transfers.all": "設定(使用者):可建立、編輯和移除轉帳帳戶 ", - "permission.settings.transfertypes.view": "設定(使用者):可以檢視轉帳條件", - "permission.settings.transfertypes.all": "設定(使用者):可建立、編輯和移除轉帳標準", - "permission.settings.usergroups.view": "設定(使用者):可以檢視讀者群組", - "permission.settings.usergroups.all": "設定(使用者):可建立、編輯和移除讀者群組", - "permission.settings.waives.view": "設定(使用者):可以檢視免除原因", - "permission.settings.waives.all": "設定(使用者):可以建立、編輯和移除免除原因", - "permission.settings.general.view": "設定(使用者):可以檢視常規條目", - "permission.settings.patron-blocks.view": "設定(使用者):可以檢視所有讀者區塊條目", - "permission.settings.feefines.view": "設定(使用者):可以檢視與費用相關的條目", + "permission.settings.view": "設定 ( 使用者 ) : 檢視所有設定", + "permission.settings.addresstypes.view": "設定 ( 使用者 ) : 可以檢視地址類型", + "permission.settings.addresstypes.all": "設定 ( 使用者 ) : 可以建立、編輯和移除地址類型", + "permission.settings.comments.view": "設定 ( 使用者 ) : 如果需要評論可以檢視", + "permission.settings.comments.all": "設定 ( 使用者 ) : 如果需要評論可以編輯", + "permission.settings.conditions.view": "設定 ( 使用者 ) : 可以檢視讀者區塊條件", + "permission.settings.conditions.edit": "設定 ( 使用者 ) : 可以檢視和編輯讀者限制條件", + "permission.settings.limits.view": "設定 ( 使用者 ) : 可以檢視讀者區塊限制", + "permission.settings.limits.all": "設定 ( 使用者 ) : 可以建立、編輯和移除讀者凍結限制", + "permission.settings.manual-charges.view": "設定 ( 使用者 ) : 可以檢視人工收費", + "permission.settings.manual-charges.all": "設定 ( 使用者 ) : 可以建立、編輯和移除人工收費", + "permission.settings.owners.view": "設定 ( 使用者 ) : 可以檢視所有者", + "permission.settings.owners.all": "設定 ( 使用者 ) : 可以建立、編輯和移除所有者", + "permission.settings.patron-block-templates.view": "設定 ( 使用者 ) : 可以檢視讀者區塊模板", + "permission.settings.patron-block-templates.all": "設定 ( 使用者 ) : 可以建立、編輯和移除讀者區塊模板", + "permission.settings.payments.view": "設定 ( 使用者 ) : 可以檢視付款方式", + "permission.settings.payments.all": "設定 ( 使用者 ) : 可以建立、編輯和移除付款方式", + "permission.settings.permsets.view": "設定 ( 使用者 ) : 可以檢視權限集", + "permission.settings.permsets.all": "設定 ( 使用者 ) : 可以建立、編輯和移除權限集", + "permission.settings.refunds.view": "設定 ( 使用者 ) : 可以檢視退款原因", + "permission.settings.refunds.all": "設定 ( 使用者 ) : 可以建立、編輯和移除退款原因", + "permission.settings.transfers.view": "設定 ( 使用者 ) : 可以檢視轉帳帳戶", + "permission.settings.transfers.all": "設定 ( 使用者 ) : 可建立、編輯和移除轉帳帳戶", + "permission.settings.transfertypes.view": "設定 ( 使用者 ) : 可以檢視轉帳條件", + "permission.settings.transfertypes.all": "設定 ( 使用者 ) : 可建立、編輯和移除轉帳標準", + "permission.settings.usergroups.view": "設定 ( 使用者 ) : 可以檢視讀者群組", + "permission.settings.usergroups.all": "設定 ( 使用者 ) : 可建立、編輯和移除讀者群組", + "permission.settings.waives.view": "設定 ( 使用者 ) : 可以檢視免除罰款的理由", + "permission.settings.waives.all": "設定 ( 使用者 ) : 可以建立、編輯和移除免除罰款的理由", + "permission.settings.general.view": "設定 ( 使用者 ) : 可以檢視常規條目", + "permission.settings.patron-blocks.view": "設定 ( 使用者 ) : 可以檢視所有讀者區塊條目", + "permission.settings.feefines.view": "設定 ( 使用者 ) : 可以檢視與費用相關的條目", "loans.lastReminderNumber": "{count, number} {count, plural, one {提醒費用} other {提醒費用}}已計費", "reports.feeFineExplanation": "費用/罰款 說明", "reports.includesReminderFees": "包含提醒費",