diff --git a/cds_ils/config.py b/cds_ils/config.py
index 07911d740..a3e120da7 100644
--- a/cds_ils/config.py
+++ b/cds_ils/config.py
@@ -540,6 +540,7 @@ def _parse_env_bool(var_name, default=None):
"series_url_access_restriction",
"tag",
"item_identifier_scheme",
+ "shelf_number",
]
###############################################################################
diff --git a/cds_ils/vocabularies/data/shelf_numbers.json b/cds_ils/vocabularies/data/shelf_numbers.json
new file mode 100644
index 000000000..d7c441882
--- /dev/null
+++ b/cds_ils/vocabularies/data/shelf_numbers.json
@@ -0,0 +1,127 @@
+[
+ { "type": "shelf_number", "key": "01", "text": "SHELF 01" },
+ { "type": "shelf_number", "key": "02", "text": "SHELF 02" },
+ { "type": "shelf_number", "key": "03", "text": "SHELF 03" },
+ { "type": "shelf_number", "key": "04", "text": "SHELF 04" },
+ { "type": "shelf_number", "key": "05", "text": "SHELF 05" },
+ { "type": "shelf_number", "key": "06", "text": "SHELF 06" },
+ { "type": "shelf_number", "key": "07", "text": "SHELF 07" },
+ { "type": "shelf_number", "key": "08", "text": "SHELF 08" },
+ { "type": "shelf_number", "key": "09", "text": "SHELF 09" },
+ { "type": "shelf_number", "key": "10", "text": "SHELF 10" },
+ { "type": "shelf_number", "key": "11", "text": "SHELF 11" },
+ { "type": "shelf_number", "key": "12", "text": "SHELF 12" },
+ { "type": "shelf_number", "key": "13", "text": "SHELF 13" },
+ { "type": "shelf_number", "key": "14", "text": "SHELF 14" },
+ { "type": "shelf_number", "key": "15", "text": "SHELF 15" },
+ { "type": "shelf_number", "key": "16", "text": "SHELF 16" },
+ { "type": "shelf_number", "key": "17", "text": "SHELF 17" },
+ { "type": "shelf_number", "key": "18", "text": "SHELF 18" },
+ { "type": "shelf_number", "key": "19", "text": "SHELF 19" },
+ { "type": "shelf_number", "key": "20", "text": "SHELF 20" },
+ { "type": "shelf_number", "key": "21", "text": "SHELF 21" },
+ { "type": "shelf_number", "key": "22", "text": "SHELF 22" },
+ { "type": "shelf_number", "key": "23", "text": "SHELF 23" },
+ { "type": "shelf_number", "key": "24", "text": "SHELF 24" },
+ { "type": "shelf_number", "key": "25", "text": "SHELF 25" },
+ { "type": "shelf_number", "key": "26", "text": "SHELF 26" },
+ { "type": "shelf_number", "key": "27", "text": "SHELF 27" },
+ { "type": "shelf_number", "key": "28", "text": "SHELF 28" },
+ { "type": "shelf_number", "key": "29", "text": "SHELF 29" },
+ { "type": "shelf_number", "key": "30", "text": "SHELF 30" },
+ { "type": "shelf_number", "key": "31", "text": "SHELF 31" },
+ { "type": "shelf_number", "key": "32", "text": "SHELF 32" },
+ { "type": "shelf_number", "key": "33", "text": "SHELF 33" },
+ { "type": "shelf_number", "key": "34", "text": "SHELF 34" },
+ { "type": "shelf_number", "key": "35", "text": "SHELF 35" },
+ { "type": "shelf_number", "key": "36", "text": "SHELF 36" },
+ { "type": "shelf_number", "key": "37", "text": "SHELF 37" },
+ { "type": "shelf_number", "key": "38", "text": "SHELF 38" },
+ { "type": "shelf_number", "key": "39", "text": "SHELF 39" },
+ { "type": "shelf_number", "key": "40", "text": "SHELF 40" },
+ { "type": "shelf_number", "key": "41", "text": "SHELF 41" },
+ { "type": "shelf_number", "key": "42", "text": "SHELF 42" },
+ { "type": "shelf_number", "key": "43", "text": "SHELF 43" },
+ { "type": "shelf_number", "key": "44", "text": "SHELF 44" },
+ { "type": "shelf_number", "key": "45", "text": "SHELF 45" },
+ { "type": "shelf_number", "key": "46", "text": "SHELF 46" },
+ { "type": "shelf_number", "key": "47", "text": "SHELF 47" },
+ { "type": "shelf_number", "key": "48", "text": "SHELF 48" },
+ { "type": "shelf_number", "key": "49", "text": "SHELF 49" },
+ { "type": "shelf_number", "key": "50", "text": "SHELF 50" },
+ { "type": "shelf_number", "key": "51", "text": "SHELF 51" },
+ { "type": "shelf_number", "key": "52", "text": "SHELF 52" },
+ { "type": "shelf_number", "key": "53", "text": "SHELF 53" },
+ { "type": "shelf_number", "key": "54", "text": "SHELF 54" },
+ { "type": "shelf_number", "key": "55", "text": "SHELF 55" },
+ { "type": "shelf_number", "key": "56", "text": "SHELF 56" },
+ { "type": "shelf_number", "key": "57", "text": "SHELF 57" },
+ { "type": "shelf_number", "key": "58", "text": "SHELF 58" },
+ { "type": "shelf_number", "key": "59", "text": "SHELF 59" },
+ { "type": "shelf_number", "key": "60", "text": "SHELF 60" },
+ { "type": "shelf_number", "key": "61", "text": "SHELF 61" },
+ { "type": "shelf_number", "key": "62", "text": "SHELF 62" },
+ { "type": "shelf_number", "key": "63", "text": "SHELF 63" },
+ { "type": "shelf_number", "key": "64", "text": "SHELF 64" },
+ { "type": "shelf_number", "key": "65", "text": "SHELF 65" },
+ { "type": "shelf_number", "key": "66", "text": "SHELF 66" },
+ { "type": "shelf_number", "key": "67", "text": "SHELF 67" },
+ { "type": "shelf_number", "key": "68", "text": "SHELF 68" },
+ { "type": "shelf_number", "key": "69", "text": "SHELF 69" },
+ { "type": "shelf_number", "key": "70", "text": "SHELF 70" },
+ { "type": "shelf_number", "key": "71", "text": "SHELF 71" },
+ { "type": "shelf_number", "key": "72", "text": "SHELF 72" },
+ { "type": "shelf_number", "key": "73", "text": "SHELF 73" },
+ { "type": "shelf_number", "key": "74", "text": "SHELF 74" },
+ { "type": "shelf_number", "key": "75", "text": "SHELF 75" },
+ { "type": "shelf_number", "key": "77", "text": "SHELF 77" },
+ { "type": "shelf_number", "key": "78", "text": "SHELF 78" },
+ { "type": "shelf_number", "key": "79", "text": "SHELF 79" },
+ { "type": "shelf_number", "key": "80", "text": "SHELF 80" },
+ { "type": "shelf_number", "key": "81", "text": "SHELF 81" },
+ { "type": "shelf_number", "key": "82", "text": "SHELF 82" },
+ { "type": "shelf_number", "key": "83", "text": "SHELF 83" },
+ { "type": "shelf_number", "key": "84", "text": "SHELF 84" },
+ { "type": "shelf_number", "key": "85", "text": "SHELF 85" },
+ { "type": "shelf_number", "key": "86", "text": "SHELF 86" },
+ { "type": "shelf_number", "key": "87", "text": "SHELF 87" },
+ { "type": "shelf_number", "key": "88", "text": "SHELF 88" },
+ { "type": "shelf_number", "key": "89", "text": "SHELF 89" },
+ { "type": "shelf_number", "key": "90", "text": "SHELF 90" },
+ { "type": "shelf_number", "key": "91", "text": "SHELF 91" },
+ { "type": "shelf_number", "key": "92", "text": "SHELF 92" },
+ { "type": "shelf_number", "key": "93", "text": "SHELF 93" },
+ { "type": "shelf_number", "key": "94", "text": "SHELF 94" },
+ { "type": "shelf_number", "key": "95", "text": "SHELF 95" },
+ { "type": "shelf_number", "key": "96", "text": "SHELF 96" },
+ { "type": "shelf_number", "key": "97", "text": "SHELF 97" },
+ { "type": "shelf_number", "key": "98", "text": "SHELF 98" },
+ { "type": "shelf_number", "key": "99", "text": "SHELF 99" },
+ { "type": "shelf_number", "key": "100", "text": "SHELF 100" },
+ { "type": "shelf_number", "key": "101", "text": "SHELF 101" },
+ { "type": "shelf_number", "key": "102", "text": "SHELF 102" },
+ { "type": "shelf_number", "key": "103", "text": "SHELF 103" },
+ { "type": "shelf_number", "key": "104", "text": "SHELF 104" },
+ { "type": "shelf_number", "key": "105", "text": "SHELF 105" },
+ { "type": "shelf_number", "key": "106", "text": "SHELF 106" },
+ { "type": "shelf_number", "key": "107", "text": "SHELF 107" },
+ { "type": "shelf_number", "key": "108", "text": "SHELF 108" },
+ { "type": "shelf_number", "key": "109", "text": "SHELF 109" },
+ { "type": "shelf_number", "key": "110", "text": "SHELF 110" },
+ { "type": "shelf_number", "key": "111", "text": "SHELF 111" },
+ { "type": "shelf_number", "key": "112", "text": "SHELF 112" },
+ { "type": "shelf_number", "key": "113", "text": "SHELF 113" },
+ { "type": "shelf_number", "key": "114", "text": "SHELF 114" },
+ { "type": "shelf_number", "key": "115", "text": "SHELF 115" },
+ { "type": "shelf_number", "key": "116", "text": "SHELF 116" },
+ { "type": "shelf_number", "key": "117", "text": "SHELF 117" },
+ { "type": "shelf_number", "key": "118", "text": "SHELF 118" },
+ { "type": "shelf_number", "key": "119", "text": "SHELF 119" },
+ { "type": "shelf_number", "key": "120", "text": "SHELF 120" },
+ { "type": "shelf_number", "key": "121", "text": "SHELF 121" },
+ { "type": "shelf_number", "key": "122", "text": "SHELF 122" },
+ { "type": "shelf_number", "key": "123", "text": "SHELF 123" },
+ { "type": "shelf_number", "key": "124", "text": "SHELF 124" },
+ { "type": "shelf_number", "key": "125", "text": "SHELF 125" },
+ { "type": "shelf_number", "key": "126", "text": "SHELF 126" }
+]
diff --git a/ui/src/config.js b/ui/src/config.js
index 59447401c..809e2f975 100644
--- a/ui/src/config.js
+++ b/ui/src/config.js
@@ -71,6 +71,11 @@ export const config = {
doc_req_payment_method: "doc_req_payment_method",
doc_req_medium: "doc_req_medium",
},
+ item: {
+ identifier: {
+ scheme: "item_identifier_scheme",
+ },
+ },
},
DOCUMENTS: {
extensions: {
@@ -205,88 +210,15 @@ export const config = {
"circulation_restriction",
"medium",
],
- properties: {
- identifiers: {
- items: {
- properties: {
- scheme: {
- title: "Scheme name",
- type: "string",
- },
- value: {
- title: "Value",
- type: "string",
- },
- },
- required: ["scheme", "value"],
- title: "Identifier",
- type: "object",
- },
- title: "Identifiers",
- type: "array",
- },
- },
},
editorUiSchema: {
- "identifiers": {
+ shelf: {
+ "ui:widget": "vocabulary",
"ui:options": {
- orderable: false,
- },
- "items": {
- "scheme": {
- "ui:widget": "vocabulary",
- "ui:options": {
- vocabularyType: "item_identifier_scheme",
- },
- },
- "custom:grid": [
- {
- scheme: 8,
- value: 8,
- },
- ],
+ size: 125, // Make sure to update size when adding new shelfs
+ vocabularyType: "shelf_number",
},
},
- "custom:grid": [
- {
- barcode: 4,
- medium: 4,
- document_pid: 8,
- },
- {
- status: 4,
- circulation_restriction: 4,
- number_of_pages: 2,
- description: 6,
- },
- {
- "custom:divider": 16,
- },
- {
- isbns: 10,
- internal_notes: 6,
- },
- {
- "custom:divider": 16,
- },
- {
- internal_location_pid: 8,
- shelf: 8,
- },
- {
- "custom:divider": 16,
- },
- {
- acquisition_pid: 6,
- price: 10,
- },
- {
- "custom:divider": 16,
- },
- {
- identifiers: 10,
- },
- ],
},
mediums: [
{
diff --git a/ui/src/overridableMapping.js b/ui/src/overridableMapping.js
index 729989847..b6c6d1ae0 100644
--- a/ui/src/overridableMapping.js
+++ b/ui/src/overridableMapping.js
@@ -36,7 +36,7 @@ import { DocumentCirculationExtras } from "./overridden/frontsite/Document/Docum
import { OpeningHoursDetails } from "./overridden/frontsite/OpeningHours/OpeningHoursDetails";
import { PaymentInformationGrid } from "./overridden/backoffice/PaymentInformation/PaymentInformation";
import { OrderDetailsLine } from "./overridden/backoffice/Acquisition/OrderDetails";
-import { ItemDetailsMetadata } from "./overridden/backoffice/Items/ItemDetailsMetadata";
+import { ItemCirculationShelf } from "./overridden/backoffice/Items/ItemCirculationShelf";
export const overriddenCmps = {
"Backoffice.PatronDetails.Metadata": PatronMetadata,
@@ -70,5 +70,5 @@ export const overriddenCmps = {
"Backoffice.PaymentInformation": PaymentInformationGrid,
"Acquisition.OrderLine": OrderDetailsLine,
"DocumentCirculation.Extras": DocumentCirculationExtras,
- "ItemMetadata": ItemDetailsMetadata,
+ "ItemCirculation.backoffice.shelf": ItemCirculationShelf,
};
diff --git a/ui/src/overridden/backoffice/Items/ItemCirculationShelf.js b/ui/src/overridden/backoffice/Items/ItemCirculationShelf.js
new file mode 100644
index 000000000..132c9ff2e
--- /dev/null
+++ b/ui/src/overridden/backoffice/Items/ItemCirculationShelf.js
@@ -0,0 +1,37 @@
+import React from "react";
+import { Grid, Embed, Button, Icon } from "semantic-ui-react";
+import PropTypes from "prop-types";
+import { shelfLink } from "../../utils";
+
+export const ItemCirculationShelf = ({ metadata }) => {
+ return (
+
- {itemIdentifiers.map((entry) => (
-
- ),
- });
- }
- return leftColumn;
-}
-
-export const ItemDetailsMetadata = parametrize(ItemMetadata, {
- rightMetadataColumn: rightMetadata,
-});
diff --git a/ui/src/overridden/frontsite/Document/DocumentDetails/DocumentCirculationExtras.js b/ui/src/overridden/frontsite/Document/DocumentDetails/DocumentCirculationExtras.js
index 2714ef409..90ffbfd30 100644
--- a/ui/src/overridden/frontsite/Document/DocumentDetails/DocumentCirculationExtras.js
+++ b/ui/src/overridden/frontsite/Document/DocumentDetails/DocumentCirculationExtras.js
@@ -1,27 +1,84 @@
import React from "react";
-import { Embed, Header, Button } from "semantic-ui-react";
+import _get from "lodash/get";
+import _isEmpty from "lodash/isEmpty";
+import { invenioConfig } from "@inveniosoftware/react-invenio-app-ils";
+import { Embed, Header, Button, Divider } from "semantic-ui-react";
+import PropTypes from "prop-types";
import { shelfLink } from "../../../utils";
+function canCirculateItem(item) {
+ return invenioConfig.ITEMS.canCirculateStatuses.includes(item.status);
+}
+
+function isItemForReference(item) {
+ return invenioConfig.ITEMS.referenceStatuses.includes(item.status);
+}
+
+function getLoanableItemShelf(locations) {
+ const locationEntries = Object.entries(locations);
+ if (_isEmpty(locationEntries)) return {};
+
+ var allRelevantItems = [];
+
+ locationEntries.forEach(([locationName, internalLocations]) => {
+ const internalLocationEntries = Object.entries(internalLocations);
+
+ internalLocationEntries.forEach(([internalLocationName, items]) => {
+ if (internalLocationName === "total") return;
+
+ const relevantItems = items.filter(
+ (item) => canCirculateItem(item) || isItemForReference(item)
+ );
+ allRelevantItems = allRelevantItems.concat(relevantItems);
+ });
+ });
+
+ for (const item of allRelevantItems) {
+ const itemStatus = _get(item, "circulation.state");
+ // If item is not on loan, return item's shelf value
+ if (!invenioConfig.CIRCULATION.loanActiveStates.includes(itemStatus)) {
+ return item.shelf;
+ }
+ }
+ return null;
+}
+
export class DocumentCirculationExtras extends React.Component {
render() {
+ const {
+ documentDetails: {
+ metadata: {
+ items: { on_shelf: onShelf },
+ circulation: { available_items_for_loan_count: availableItems },
+ },
+ },
+ } = this.props;
+ if (_isEmpty(onShelf) || availableItems === 0) {
+ return null;
+ }
+
+ const shelfNumber = getLoanableItemShelf(onShelf);
+ if (shelfNumber === null || shelfNumber === undefined) {
+ // If no item can be loaned, don't display the cernmaps iframe
+ return null;
+ }
+
return (
-