@inveniosoftware/react-invenio-app-ils 2.0.2 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.js +331 -89
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/index.js +331 -89
- package/dist/esm/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cjs/index.js
CHANGED
|
@@ -739,7 +739,7 @@ const RECORDS_CONFIG = {
|
|
|
739
739
|
}
|
|
740
740
|
},
|
|
741
741
|
ITEMS: {
|
|
742
|
-
|
|
742
|
+
identifiersToDisplay: [],
|
|
743
743
|
circulationRestrictions: [{
|
|
744
744
|
value: 'NO_RESTRICTION',
|
|
745
745
|
text: 'No restriction (4 weeks)'
|
|
@@ -4287,6 +4287,26 @@ const vocabularyApi = {
|
|
|
4287
4287
|
serializer: serializer$1
|
|
4288
4288
|
};
|
|
4289
4289
|
|
|
4290
|
+
/**
|
|
4291
|
+
* Resolves identifier scheme keys (e.g. "CALL_NUMBER") to their
|
|
4292
|
+
* human-readable titles from the vocabulary API.
|
|
4293
|
+
*
|
|
4294
|
+
* @param {Array<string>} identifiers
|
|
4295
|
+
* @param {string} identifierScheme
|
|
4296
|
+
* @returns {Promise<Array<{key: string, text: string}>>}
|
|
4297
|
+
*/
|
|
4298
|
+
const fetchIdentifierTitles = async (identifiers, identifierScheme) => {
|
|
4299
|
+
const query = vocabularyApi.query().withType(identifierScheme);
|
|
4300
|
+
const response = await vocabularyApi.list(query.qs());
|
|
4301
|
+
return identifiers.map(scheme => {
|
|
4302
|
+
const vocabEntry = response.data.hits.find(entry => entry.metadata.key === scheme);
|
|
4303
|
+
return {
|
|
4304
|
+
key: scheme,
|
|
4305
|
+
text: vocabEntry ? vocabEntry.metadata.text : scheme
|
|
4306
|
+
};
|
|
4307
|
+
});
|
|
4308
|
+
};
|
|
4309
|
+
|
|
4290
4310
|
class ScrollingMenuItem$1 extends React.Component {
|
|
4291
4311
|
constructor(props) {
|
|
4292
4312
|
super(props);
|
|
@@ -4359,6 +4379,14 @@ const prettyPrintBooleanValue = value => {
|
|
|
4359
4379
|
const screenIsWiderThan = pixels => {
|
|
4360
4380
|
return window.matchMedia(`(max-width: ${pixels}px)`).matches ? false : true;
|
|
4361
4381
|
};
|
|
4382
|
+
const isPrivilegedUser = () => {
|
|
4383
|
+
const roles = _get__default["default"](sessionManager, 'user.roles', []);
|
|
4384
|
+
return roles.includes('admin') || roles.includes('librarian');
|
|
4385
|
+
};
|
|
4386
|
+
const isDocumentOverbooked = async documentPid => {
|
|
4387
|
+
const response = await documentApi.get(documentPid);
|
|
4388
|
+
return _get__default["default"](response, 'data.metadata.circulation.overbooked', false);
|
|
4389
|
+
};
|
|
4362
4390
|
|
|
4363
4391
|
class MetadataTable extends React.Component {
|
|
4364
4392
|
renderRows() {
|
|
@@ -6224,32 +6252,36 @@ class DocumentItemBody extends React.Component {
|
|
|
6224
6252
|
items,
|
|
6225
6253
|
shelfLink,
|
|
6226
6254
|
documentDetails,
|
|
6227
|
-
|
|
6228
|
-
} = this.props;
|
|
6229
|
-
return items.map(item =>
|
|
6230
|
-
|
|
6231
|
-
|
|
6232
|
-
|
|
6233
|
-
|
|
6234
|
-
|
|
6235
|
-
|
|
6236
|
-
|
|
6237
|
-
|
|
6238
|
-
|
|
6239
|
-
return /*#__PURE__*/React__default["default"].createElement(semanticUiReact.Table.Cell, {
|
|
6240
|
-
key: identifier,
|
|
6241
|
-
"data-label": identifier.text,
|
|
6255
|
+
identifiersToDisplay
|
|
6256
|
+
} = this.props;
|
|
6257
|
+
return items.map(item => {
|
|
6258
|
+
const itemIsAccessible = !_get__default["default"](item, 'internal_location.restricted');
|
|
6259
|
+
const shelfValue = shelfLink ? shelfLink(item, documentDetails) : _get__default["default"](item, 'shelf');
|
|
6260
|
+
return /*#__PURE__*/React__default["default"].createElement(semanticUiReact.Table.Row, {
|
|
6261
|
+
key: item.pid
|
|
6262
|
+
}, /*#__PURE__*/React__default["default"].createElement(semanticUiReact.Table.Cell, {
|
|
6263
|
+
"data-label": "Barcode",
|
|
6264
|
+
className: "document-item-table-itemCell"
|
|
6265
|
+
}, item.barcode), /*#__PURE__*/React__default["default"].createElement(semanticUiReact.Table.Cell, {
|
|
6266
|
+
"data-label": "Shelf",
|
|
6242
6267
|
className: "document-item-table-itemCell"
|
|
6243
|
-
},
|
|
6244
|
-
|
|
6245
|
-
|
|
6246
|
-
|
|
6247
|
-
|
|
6248
|
-
|
|
6249
|
-
|
|
6250
|
-
|
|
6251
|
-
|
|
6252
|
-
|
|
6268
|
+
}, itemIsAccessible ? shelfValue : /*#__PURE__*/React__default["default"].createElement("p", null, "Available on Request")), identifiersToDisplay.map(identifier => {
|
|
6269
|
+
var _item$identifiers, _item$identifiers$fin;
|
|
6270
|
+
return /*#__PURE__*/React__default["default"].createElement(semanticUiReact.Table.Cell, {
|
|
6271
|
+
key: identifier,
|
|
6272
|
+
"data-label": identifier.text,
|
|
6273
|
+
className: "document-item-table-itemCell"
|
|
6274
|
+
}, itemIsAccessible && ((_item$identifiers = item.identifiers) === null || _item$identifiers === void 0 ? void 0 : (_item$identifiers$fin = _item$identifiers.find(entry => {
|
|
6275
|
+
return entry.scheme === identifier.key;
|
|
6276
|
+
})) === null || _item$identifiers$fin === void 0 ? void 0 : _item$identifiers$fin.value));
|
|
6277
|
+
}), /*#__PURE__*/React__default["default"].createElement(semanticUiReact.Table.Cell, {
|
|
6278
|
+
"data-label": "Status"
|
|
6279
|
+
}, this.statusLabel(item)), /*#__PURE__*/React__default["default"].createElement(semanticUiReact.Table.Cell, {
|
|
6280
|
+
"data-label": "Medium"
|
|
6281
|
+
}, getDisplayVal('ITEMS.mediums', item.medium)), /*#__PURE__*/React__default["default"].createElement(semanticUiReact.Table.Cell, {
|
|
6282
|
+
"data-label": "Restrictions"
|
|
6283
|
+
}, getDisplayVal('ITEMS.circulationRestrictions', item.circulation_restriction)));
|
|
6284
|
+
});
|
|
6253
6285
|
}
|
|
6254
6286
|
}
|
|
6255
6287
|
DocumentItemBody.defaultProps = {
|
|
@@ -27050,7 +27082,11 @@ class AvailableItems$1 extends React.Component {
|
|
|
27050
27082
|
query: '',
|
|
27051
27083
|
filteredData: null,
|
|
27052
27084
|
modalOpen: false,
|
|
27053
|
-
checkoutItem: null
|
|
27085
|
+
checkoutItem: null,
|
|
27086
|
+
identifiersToDisplay: invenioConfig.ITEMS.identifiersToDisplay.map(s => ({
|
|
27087
|
+
key: s,
|
|
27088
|
+
text: s
|
|
27089
|
+
}))
|
|
27054
27090
|
};
|
|
27055
27091
|
}
|
|
27056
27092
|
componentDidMount() {
|
|
@@ -27059,6 +27095,25 @@ class AvailableItems$1 extends React.Component {
|
|
|
27059
27095
|
loan
|
|
27060
27096
|
} = this.props;
|
|
27061
27097
|
fetchAvailableItems(loan.metadata.document_pid);
|
|
27098
|
+
this.loadIdentifierTitles();
|
|
27099
|
+
}
|
|
27100
|
+
componentWillUnmount() {
|
|
27101
|
+
if (this.cancellableFetchIdentifierTitles) {
|
|
27102
|
+
this.cancellableFetchIdentifierTitles.cancel();
|
|
27103
|
+
}
|
|
27104
|
+
}
|
|
27105
|
+
async loadIdentifierTitles() {
|
|
27106
|
+
this.cancellableFetchIdentifierTitles = withCancel(fetchIdentifierTitles(invenioConfig.ITEMS.identifiersToDisplay, invenioConfig.VOCABULARIES.item.identifier.scheme));
|
|
27107
|
+
try {
|
|
27108
|
+
let result = await this.cancellableFetchIdentifierTitles.promise;
|
|
27109
|
+
this.setState({
|
|
27110
|
+
identifiersToDisplay: result
|
|
27111
|
+
});
|
|
27112
|
+
} catch (error) {
|
|
27113
|
+
if (error !== 'UNMOUNTED') {
|
|
27114
|
+
console.error('Error fetching identifier titles for items.', error);
|
|
27115
|
+
}
|
|
27116
|
+
}
|
|
27062
27117
|
}
|
|
27063
27118
|
assignItemButton(item) {
|
|
27064
27119
|
const {
|
|
@@ -27129,18 +27184,31 @@ class AvailableItems$1 extends React.Component {
|
|
|
27129
27184
|
data
|
|
27130
27185
|
} = this.props;
|
|
27131
27186
|
const {
|
|
27132
|
-
filteredData
|
|
27187
|
+
filteredData,
|
|
27188
|
+
identifiersToDisplay
|
|
27133
27189
|
} = this.state;
|
|
27190
|
+
const identifierColumns = identifiersToDisplay.map(identifier => ({
|
|
27191
|
+
title: identifier.text,
|
|
27192
|
+
field: `metadata.identifiers`,
|
|
27193
|
+
formatter: _ref2 => {
|
|
27194
|
+
var _row$metadata$identif;
|
|
27195
|
+
let {
|
|
27196
|
+
row
|
|
27197
|
+
} = _ref2;
|
|
27198
|
+
const entry = (_row$metadata$identif = row.metadata.identifiers) === null || _row$metadata$identif === void 0 ? void 0 : _row$metadata$identif.find(id => id.scheme === identifier.key);
|
|
27199
|
+
return entry === null || entry === void 0 ? void 0 : entry.value;
|
|
27200
|
+
}
|
|
27201
|
+
}));
|
|
27134
27202
|
const columns = [{
|
|
27135
27203
|
title: 'PID',
|
|
27136
27204
|
field: 'metadata.pid'
|
|
27137
27205
|
}, {
|
|
27138
27206
|
title: 'Barcode',
|
|
27139
27207
|
field: 'metadata.barcode',
|
|
27140
|
-
formatter:
|
|
27208
|
+
formatter: _ref3 => {
|
|
27141
27209
|
let {
|
|
27142
27210
|
row
|
|
27143
|
-
} =
|
|
27211
|
+
} = _ref3;
|
|
27144
27212
|
return /*#__PURE__*/React__default["default"].createElement(reactRouterDom.Link, {
|
|
27145
27213
|
to: BackOfficeRoutes.itemDetailsFor(row.metadata.pid)
|
|
27146
27214
|
}, row.metadata.barcode);
|
|
@@ -27157,7 +27225,7 @@ class AvailableItems$1 extends React.Component {
|
|
|
27157
27225
|
}, {
|
|
27158
27226
|
title: 'Shelf',
|
|
27159
27227
|
field: 'metadata.shelf'
|
|
27160
|
-
}, {
|
|
27228
|
+
}, ...identifierColumns, {
|
|
27161
27229
|
title: 'Actions',
|
|
27162
27230
|
field: '',
|
|
27163
27231
|
formatter: this.rowActionButton
|
|
@@ -28146,15 +28214,20 @@ const LoanDetails = reactRedux.connect(mapStateToProps$K, mapDispatchToProps$z)(
|
|
|
28146
28214
|
class _SearchDateRange extends React.Component {
|
|
28147
28215
|
constructor() {
|
|
28148
28216
|
super(...arguments);
|
|
28149
|
-
this.onDateChange =
|
|
28217
|
+
this.onDateChange = (field, value) => {
|
|
28150
28218
|
const {
|
|
28151
28219
|
currentQueryState,
|
|
28152
28220
|
updateQueryState
|
|
28153
28221
|
} = this.props;
|
|
28154
|
-
const
|
|
28155
|
-
|
|
28222
|
+
const updatedFilters = currentQueryState.filters.filter(_ref => {
|
|
28223
|
+
let [name] = _ref;
|
|
28224
|
+
return name !== field;
|
|
28225
|
+
});
|
|
28226
|
+
if (value !== '') {
|
|
28227
|
+
updatedFilters.push([field, value]);
|
|
28228
|
+
}
|
|
28156
28229
|
return updateQueryState({
|
|
28157
|
-
filters:
|
|
28230
|
+
filters: updatedFilters
|
|
28158
28231
|
});
|
|
28159
28232
|
};
|
|
28160
28233
|
}
|
|
@@ -28166,8 +28239,8 @@ class _SearchDateRange extends React.Component {
|
|
|
28166
28239
|
} = this.props;
|
|
28167
28240
|
let fromDate = '';
|
|
28168
28241
|
let toDate = '';
|
|
28169
|
-
filters.forEach(
|
|
28170
|
-
let [name, value] =
|
|
28242
|
+
filters.forEach(_ref2 => {
|
|
28243
|
+
let [name, value] = _ref2;
|
|
28171
28244
|
if (name === 'loans_from_date') fromDate = value;
|
|
28172
28245
|
if (name === 'loans_to_date') toDate = value;
|
|
28173
28246
|
});
|
|
@@ -28179,12 +28252,12 @@ class _SearchDateRange extends React.Component {
|
|
|
28179
28252
|
maxDate: toDate,
|
|
28180
28253
|
defaultValue: fromDate,
|
|
28181
28254
|
placeholder: "From",
|
|
28182
|
-
handleDateChange: value => this.onDateChange(
|
|
28255
|
+
handleDateChange: value => this.onDateChange('loans_from_date', value)
|
|
28183
28256
|
})), /*#__PURE__*/React__default["default"].createElement(semanticUiReact.Card.Content, null, /*#__PURE__*/React__default["default"].createElement(DatePicker$1, {
|
|
28184
28257
|
minDate: fromDate,
|
|
28185
28258
|
defaultValue: toDate,
|
|
28186
28259
|
placeholder: "To",
|
|
28187
|
-
handleDateChange: value => this.onDateChange(
|
|
28260
|
+
handleDateChange: value => this.onDateChange('loans_to_date', value)
|
|
28188
28261
|
})));
|
|
28189
28262
|
}
|
|
28190
28263
|
}
|
|
@@ -28295,6 +28368,11 @@ const schema$3 = () => {
|
|
|
28295
28368
|
physical_location: {
|
|
28296
28369
|
type: 'string',
|
|
28297
28370
|
title: 'Physical location'
|
|
28371
|
+
},
|
|
28372
|
+
restricted: {
|
|
28373
|
+
type: 'boolean',
|
|
28374
|
+
title: 'Restricted access (not accessible to patrons)',
|
|
28375
|
+
default: false
|
|
28298
28376
|
}
|
|
28299
28377
|
}
|
|
28300
28378
|
};
|
|
@@ -28315,6 +28393,8 @@ const uiSchema$3 = title => {
|
|
|
28315
28393
|
}, {
|
|
28316
28394
|
physical_location: 8,
|
|
28317
28395
|
notes: 8
|
|
28396
|
+
}, {
|
|
28397
|
+
restricted: 8
|
|
28318
28398
|
}],
|
|
28319
28399
|
'custom:root': {
|
|
28320
28400
|
'custom:formTitle': title
|
|
@@ -29384,6 +29464,16 @@ class InternalLocationList$1 extends React.Component {
|
|
|
29384
29464
|
}, {
|
|
29385
29465
|
title: 'Location e-mail',
|
|
29386
29466
|
field: 'metadata.location.email'
|
|
29467
|
+
}, {
|
|
29468
|
+
title: 'Restricted access',
|
|
29469
|
+
formatter: _ref2 => {
|
|
29470
|
+
let {
|
|
29471
|
+
row
|
|
29472
|
+
} = _ref2;
|
|
29473
|
+
return row.metadata.restricted ? /*#__PURE__*/React__default["default"].createElement("i", {
|
|
29474
|
+
className: "check icon"
|
|
29475
|
+
}) : null;
|
|
29476
|
+
}
|
|
29387
29477
|
}, {
|
|
29388
29478
|
title: 'Actions',
|
|
29389
29479
|
field: '',
|
|
@@ -29547,19 +29637,108 @@ const mapDispatchToProps$v = dispatch => ({
|
|
|
29547
29637
|
});
|
|
29548
29638
|
const LocationList = reactRedux.connect(mapStateToProps$G, mapDispatchToProps$v)(LocationList$1);
|
|
29549
29639
|
|
|
29640
|
+
const OverbookedConfirmModal = _ref => {
|
|
29641
|
+
let {
|
|
29642
|
+
open,
|
|
29643
|
+
onClose,
|
|
29644
|
+
onConfirm,
|
|
29645
|
+
overbookedDocuments
|
|
29646
|
+
} = _ref;
|
|
29647
|
+
const isMultiple = overbookedDocuments.length > 1;
|
|
29648
|
+
return /*#__PURE__*/React__default["default"].createElement(semanticUiReact.Modal, {
|
|
29649
|
+
size: "small",
|
|
29650
|
+
open: open,
|
|
29651
|
+
onClose: onClose
|
|
29652
|
+
}, /*#__PURE__*/React__default["default"].createElement(semanticUiReact.Modal.Header, null, "Item in high demand!"), /*#__PURE__*/React__default["default"].createElement(semanticUiReact.Modal.Content, null, overbookedDocuments.map((doc, index) => /*#__PURE__*/React__default["default"].createElement("p", {
|
|
29653
|
+
key: doc.loanRequestId || doc.title || index
|
|
29654
|
+
}, "There is another patron waiting for \"", /*#__PURE__*/React__default["default"].createElement("strong", null, doc.title), "\"", ' ', doc.loanRequestId && /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, "(", /*#__PURE__*/React__default["default"].createElement("a", {
|
|
29655
|
+
href: `/backoffice/loans/${doc.loanRequestId}`
|
|
29656
|
+
}, "See loan request"), ")"), ".")), /*#__PURE__*/React__default["default"].createElement("p", null, /*#__PURE__*/React__default["default"].createElement("strong", null, "Do you still want to extend your ", isMultiple ? 'loans' : 'loan', "?"))), /*#__PURE__*/React__default["default"].createElement(semanticUiReact.Modal.Actions, null, /*#__PURE__*/React__default["default"].createElement(semanticUiReact.Button, {
|
|
29657
|
+
secondary: true,
|
|
29658
|
+
onClick: onClose
|
|
29659
|
+
}, "Cancel"), /*#__PURE__*/React__default["default"].createElement(semanticUiReact.Button, {
|
|
29660
|
+
primary: true,
|
|
29661
|
+
onClick: onConfirm
|
|
29662
|
+
}, "Extend")));
|
|
29663
|
+
};
|
|
29664
|
+
|
|
29550
29665
|
class PatronBulkExtendLoans$1 extends React.Component {
|
|
29551
29666
|
constructor() {
|
|
29552
29667
|
super(...arguments);
|
|
29553
29668
|
this.state = {
|
|
29554
|
-
open: false
|
|
29669
|
+
open: false,
|
|
29670
|
+
showOverbookedConfirm: false,
|
|
29671
|
+
overbookedDocuments: [],
|
|
29672
|
+
isChecking: false
|
|
29673
|
+
};
|
|
29674
|
+
this.open = async () => {
|
|
29675
|
+
this.setState({
|
|
29676
|
+
open: true
|
|
29677
|
+
});
|
|
29678
|
+
if (!isPrivilegedUser()) return;
|
|
29679
|
+
this.setState({
|
|
29680
|
+
isChecking: true
|
|
29681
|
+
});
|
|
29682
|
+
try {
|
|
29683
|
+
const {
|
|
29684
|
+
patronPid
|
|
29685
|
+
} = this.props;
|
|
29686
|
+
// Get all active loans for the patron
|
|
29687
|
+
const query = loanApi.query().withPatronPid(patronPid).withState(invenioConfig.CIRCULATION.loanActiveStates).withSize(invenioConfig.APP.PATRON_PROFILE_MAX_RESULTS_SIZE).sortByNewest().qs();
|
|
29688
|
+
const response = await loanApi.list(query);
|
|
29689
|
+
const loans = response.data.hits;
|
|
29690
|
+
const checks = loans.map(async loan => {
|
|
29691
|
+
const documentPid = _get__default["default"](loan, 'metadata.document.pid');
|
|
29692
|
+
const isOverbooked = await isDocumentOverbooked(documentPid);
|
|
29693
|
+
if (isOverbooked) {
|
|
29694
|
+
return {
|
|
29695
|
+
title: loan.metadata.document.title,
|
|
29696
|
+
loanRequestId: loan.id
|
|
29697
|
+
};
|
|
29698
|
+
}
|
|
29699
|
+
return null;
|
|
29700
|
+
});
|
|
29701
|
+
const results = await Promise.all(checks);
|
|
29702
|
+
const overbookedDocuments = results.filter(Boolean);
|
|
29703
|
+
this.setState({
|
|
29704
|
+
overbookedDocuments,
|
|
29705
|
+
isChecking: false
|
|
29706
|
+
});
|
|
29707
|
+
} catch (error) {
|
|
29708
|
+
console.error('Failed to fetch overbooked documents', error);
|
|
29709
|
+
this.setState({
|
|
29710
|
+
isChecking: false
|
|
29711
|
+
});
|
|
29712
|
+
}
|
|
29713
|
+
};
|
|
29714
|
+
this.close = () => {
|
|
29715
|
+
this.setState({
|
|
29716
|
+
open: false,
|
|
29717
|
+
showOverbookedConfirm: false,
|
|
29718
|
+
overbookedDocuments: []
|
|
29719
|
+
});
|
|
29555
29720
|
};
|
|
29556
|
-
this.open = () => this.setState({
|
|
29557
|
-
open: true
|
|
29558
|
-
});
|
|
29559
|
-
this.close = () => this.setState({
|
|
29560
|
-
open: false
|
|
29561
|
-
});
|
|
29562
29721
|
this.handleSubmitExtend = () => {
|
|
29722
|
+
const {
|
|
29723
|
+
bulkLoanExtension,
|
|
29724
|
+
patronPid
|
|
29725
|
+
} = this.props;
|
|
29726
|
+
const {
|
|
29727
|
+
overbookedDocuments
|
|
29728
|
+
} = this.state;
|
|
29729
|
+
|
|
29730
|
+
// If the user is privileged and there are overbooked docs
|
|
29731
|
+
if (isPrivilegedUser() && overbookedDocuments.length > 0) {
|
|
29732
|
+
this.setState({
|
|
29733
|
+
showOverbookedConfirm: true
|
|
29734
|
+
});
|
|
29735
|
+
return;
|
|
29736
|
+
}
|
|
29737
|
+
// Otherwise extend directly
|
|
29738
|
+
bulkLoanExtension(patronPid);
|
|
29739
|
+
this.close();
|
|
29740
|
+
};
|
|
29741
|
+
this.confirmBulkExtension = () => {
|
|
29563
29742
|
const {
|
|
29564
29743
|
bulkLoanExtension,
|
|
29565
29744
|
patronPid
|
|
@@ -29570,16 +29749,26 @@ class PatronBulkExtendLoans$1 extends React.Component {
|
|
|
29570
29749
|
}
|
|
29571
29750
|
render() {
|
|
29572
29751
|
const {
|
|
29573
|
-
patronPid,
|
|
29574
|
-
bulkLoanExtension,
|
|
29575
29752
|
isLoading,
|
|
29576
29753
|
disabled,
|
|
29754
|
+
patronPid,
|
|
29755
|
+
bulkLoanExtension,
|
|
29577
29756
|
...uiProps
|
|
29578
29757
|
} = this.props;
|
|
29579
29758
|
const {
|
|
29580
|
-
open
|
|
29759
|
+
open,
|
|
29760
|
+
showOverbookedConfirm,
|
|
29761
|
+
overbookedDocuments,
|
|
29762
|
+
isChecking
|
|
29581
29763
|
} = this.state;
|
|
29582
|
-
return /*#__PURE__*/React__default["default"].createElement(
|
|
29764
|
+
return /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, /*#__PURE__*/React__default["default"].createElement(OverbookedConfirmModal, {
|
|
29765
|
+
open: showOverbookedConfirm,
|
|
29766
|
+
onClose: () => this.setState({
|
|
29767
|
+
showOverbookedConfirm: false
|
|
29768
|
+
}),
|
|
29769
|
+
onConfirm: this.confirmBulkExtension,
|
|
29770
|
+
overbookedDocuments: overbookedDocuments
|
|
29771
|
+
}), /*#__PURE__*/React__default["default"].createElement(semanticUiReact.Modal, {
|
|
29583
29772
|
open: open,
|
|
29584
29773
|
onClose: this.close,
|
|
29585
29774
|
onOpen: this.open,
|
|
@@ -29599,8 +29788,9 @@ class PatronBulkExtendLoans$1 extends React.Component {
|
|
|
29599
29788
|
onClick: this.close
|
|
29600
29789
|
}, "Cancel"), /*#__PURE__*/React__default["default"].createElement(semanticUiReact.Button, {
|
|
29601
29790
|
onClick: this.handleSubmitExtend,
|
|
29602
|
-
primary: true
|
|
29603
|
-
|
|
29791
|
+
primary: true,
|
|
29792
|
+
loading: isChecking
|
|
29793
|
+
}, "Extend the loans"))));
|
|
29604
29794
|
}
|
|
29605
29795
|
}
|
|
29606
29796
|
PatronBulkExtendLoans$1.defaultProps = {
|
|
@@ -35320,21 +35510,6 @@ class DocumentStats extends React.Component {
|
|
|
35320
35510
|
class DocumentItem extends React.Component {
|
|
35321
35511
|
constructor(props) {
|
|
35322
35512
|
super(props);
|
|
35323
|
-
this.fetchIdentifiersToDisplayInFrontsideTitles = () => {
|
|
35324
|
-
const query = vocabularyApi.query().withType(invenioConfig.VOCABULARIES.item.identifier.scheme);
|
|
35325
|
-
vocabularyApi.list(query.qs()).then(response => {
|
|
35326
|
-
const identifiersToDisplayInFrontside = this.state.identifiersToDisplayInFrontside.map(identifier => {
|
|
35327
|
-
const vocabEntry = response.data.hits.find(entry => entry.metadata.key === identifier.key);
|
|
35328
|
-
return {
|
|
35329
|
-
...identifier,
|
|
35330
|
-
text: vocabEntry ? vocabEntry.metadata.text : identifier.text
|
|
35331
|
-
};
|
|
35332
|
-
});
|
|
35333
|
-
this.setState({
|
|
35334
|
-
identifiersToDisplayInFrontside
|
|
35335
|
-
});
|
|
35336
|
-
});
|
|
35337
|
-
};
|
|
35338
35513
|
this.toggleItems = () => {
|
|
35339
35514
|
const {
|
|
35340
35515
|
isShowingAll
|
|
@@ -35343,18 +35518,10 @@ class DocumentItem extends React.Component {
|
|
|
35343
35518
|
isShowingAll: !isShowingAll
|
|
35344
35519
|
});
|
|
35345
35520
|
};
|
|
35346
|
-
const _identifiersToDisplayInFrontside = invenioConfig.ITEMS.identifiersToDisplayInFrontside.map(identifier => ({
|
|
35347
|
-
key: identifier,
|
|
35348
|
-
text: identifier
|
|
35349
|
-
}));
|
|
35350
35521
|
this.state = {
|
|
35351
35522
|
isShowingAll: false,
|
|
35352
|
-
itemAmountLimit: 5
|
|
35353
|
-
identifiersToDisplayInFrontside: _identifiersToDisplayInFrontside
|
|
35523
|
+
itemAmountLimit: 5
|
|
35354
35524
|
};
|
|
35355
|
-
if (_identifiersToDisplayInFrontside.length > 0) {
|
|
35356
|
-
this.fetchIdentifiersToDisplayInFrontsideTitles();
|
|
35357
|
-
}
|
|
35358
35525
|
}
|
|
35359
35526
|
get moreItemsToLoad() {
|
|
35360
35527
|
const {
|
|
@@ -35370,12 +35537,12 @@ class DocumentItem extends React.Component {
|
|
|
35370
35537
|
internalLocationName,
|
|
35371
35538
|
items,
|
|
35372
35539
|
documentDetails,
|
|
35373
|
-
showTitle
|
|
35540
|
+
showTitle,
|
|
35541
|
+
identifiersToDisplay
|
|
35374
35542
|
} = this.props;
|
|
35375
35543
|
const {
|
|
35376
35544
|
isShowingAll,
|
|
35377
|
-
itemAmountLimit
|
|
35378
|
-
identifiersToDisplayInFrontside
|
|
35545
|
+
itemAmountLimit
|
|
35379
35546
|
} = this.state;
|
|
35380
35547
|
const previewArrayOfItems = items.slice(0, itemAmountLimit);
|
|
35381
35548
|
const completeArrayOfItems = items;
|
|
@@ -35393,14 +35560,14 @@ class DocumentItem extends React.Component {
|
|
|
35393
35560
|
id: "DocumentDetails.DocumentItem.TableHeader"
|
|
35394
35561
|
}, /*#__PURE__*/React__default["default"].createElement(semanticUiReact.Table.Row, {
|
|
35395
35562
|
"data-test": "header"
|
|
35396
|
-
}, /*#__PURE__*/React__default["default"].createElement(semanticUiReact.Table.HeaderCell, null, "Barcode"), /*#__PURE__*/React__default["default"].createElement(semanticUiReact.Table.HeaderCell, null, "Shelf"),
|
|
35563
|
+
}, /*#__PURE__*/React__default["default"].createElement(semanticUiReact.Table.HeaderCell, null, "Barcode"), /*#__PURE__*/React__default["default"].createElement(semanticUiReact.Table.HeaderCell, null, "Shelf"), identifiersToDisplay.map(identifier => /*#__PURE__*/React__default["default"].createElement(semanticUiReact.Table.HeaderCell, {
|
|
35397
35564
|
key: identifier.key
|
|
35398
35565
|
}, identifier.text)), /*#__PURE__*/React__default["default"].createElement(semanticUiReact.Table.HeaderCell, null, "Status"), /*#__PURE__*/React__default["default"].createElement(semanticUiReact.Table.HeaderCell, null, "Medium"), /*#__PURE__*/React__default["default"].createElement(semanticUiReact.Table.HeaderCell, null, "Loan restriction")))), /*#__PURE__*/React__default["default"].createElement(semanticUiReact.Table.Body, null, /*#__PURE__*/React__default["default"].createElement(Overridable__default["default"], {
|
|
35399
35566
|
id: "DocumentDetails.DocumentItemTableBody"
|
|
35400
35567
|
}, /*#__PURE__*/React__default["default"].createElement(DocumentItemBody, {
|
|
35401
35568
|
items: itemsToShow,
|
|
35402
35569
|
documentDetails: documentDetails,
|
|
35403
|
-
|
|
35570
|
+
identifiersToDisplay: identifiersToDisplay
|
|
35404
35571
|
}))), this.moreItemsToLoad && /*#__PURE__*/React__default["default"].createElement(semanticUiReact.Table.Footer, {
|
|
35405
35572
|
fullWidth: true,
|
|
35406
35573
|
"data-test": "footer",
|
|
@@ -35492,7 +35659,8 @@ class DocumentTabs extends React.Component {
|
|
|
35492
35659
|
};
|
|
35493
35660
|
this.createInternalLocationTables = locationsObject => {
|
|
35494
35661
|
const {
|
|
35495
|
-
activeInternalLocation
|
|
35662
|
+
activeInternalLocation,
|
|
35663
|
+
identifiersToDisplay
|
|
35496
35664
|
} = this.state;
|
|
35497
35665
|
const sortedInternalLocationEntries = this.sortedLocationEntries(Object.entries(locationsObject));
|
|
35498
35666
|
if (activeInternalLocation) {
|
|
@@ -35506,7 +35674,8 @@ class DocumentTabs extends React.Component {
|
|
|
35506
35674
|
internalLocationName: internalLocationName,
|
|
35507
35675
|
items: items,
|
|
35508
35676
|
documentDetails: this.documentDetails,
|
|
35509
|
-
showTitle: activeInternalLocation !== internalLocationName
|
|
35677
|
+
showTitle: activeInternalLocation !== internalLocationName,
|
|
35678
|
+
identifiersToDisplay: identifiersToDisplay
|
|
35510
35679
|
});
|
|
35511
35680
|
}
|
|
35512
35681
|
return sortedInternalLocationEntries.map(_ref6 => {
|
|
@@ -35517,7 +35686,8 @@ class DocumentTabs extends React.Component {
|
|
|
35517
35686
|
internalLocationName: internalLocationName,
|
|
35518
35687
|
items: items,
|
|
35519
35688
|
documentDetails: this.documentDetails,
|
|
35520
|
-
showTitle: activeInternalLocation !== internalLocationName
|
|
35689
|
+
showTitle: activeInternalLocation !== internalLocationName,
|
|
35690
|
+
identifiersToDisplay: identifiersToDisplay
|
|
35521
35691
|
});
|
|
35522
35692
|
});
|
|
35523
35693
|
};
|
|
@@ -35541,9 +35711,34 @@ class DocumentTabs extends React.Component {
|
|
|
35541
35711
|
const [firstLocationName] = this.locationEntries[0];
|
|
35542
35712
|
const [_firstInternalLocationName] = this.firstInternalLocationEntry(firstLocationName);
|
|
35543
35713
|
this.state = {
|
|
35544
|
-
activeInternalLocation: _firstInternalLocationName
|
|
35714
|
+
activeInternalLocation: _firstInternalLocationName,
|
|
35715
|
+
identifiersToDisplay: invenioConfig.ITEMS.identifiersToDisplay.map(s => ({
|
|
35716
|
+
key: s,
|
|
35717
|
+
text: s
|
|
35718
|
+
}))
|
|
35545
35719
|
};
|
|
35546
35720
|
}
|
|
35721
|
+
componentDidMount() {
|
|
35722
|
+
this.loadIdentifierTitles();
|
|
35723
|
+
}
|
|
35724
|
+
componentWillUnmount() {
|
|
35725
|
+
if (this.cancellableFetchIdentifierTitles) {
|
|
35726
|
+
this.cancellableFetchIdentifierTitles.cancel();
|
|
35727
|
+
}
|
|
35728
|
+
}
|
|
35729
|
+
async loadIdentifierTitles() {
|
|
35730
|
+
this.cancellableFetchIdentifierTitles = withCancel(fetchIdentifierTitles(invenioConfig.ITEMS.identifiersToDisplay, invenioConfig.VOCABULARIES.item.identifier.scheme));
|
|
35731
|
+
try {
|
|
35732
|
+
let result = await this.cancellableFetchIdentifierTitles.promise;
|
|
35733
|
+
this.setState({
|
|
35734
|
+
identifiersToDisplay: result
|
|
35735
|
+
});
|
|
35736
|
+
} catch (error) {
|
|
35737
|
+
if (error !== 'UNMOUNTED') {
|
|
35738
|
+
console.error('Error fetching identifier titles for items.', error);
|
|
35739
|
+
}
|
|
35740
|
+
}
|
|
35741
|
+
}
|
|
35547
35742
|
get locations() {
|
|
35548
35743
|
const {
|
|
35549
35744
|
locationsObject
|
|
@@ -38948,6 +39143,36 @@ class LoanExtendButton extends React.Component {
|
|
|
38948
39143
|
constructor(props) {
|
|
38949
39144
|
super(props);
|
|
38950
39145
|
this.triggerExtension = async () => {
|
|
39146
|
+
const {
|
|
39147
|
+
loan,
|
|
39148
|
+
onError
|
|
39149
|
+
} = this.props;
|
|
39150
|
+
const isUserPrivileged = isPrivilegedUser();
|
|
39151
|
+
if (isUserPrivileged) {
|
|
39152
|
+
this.setState({
|
|
39153
|
+
isLoading: true
|
|
39154
|
+
});
|
|
39155
|
+
try {
|
|
39156
|
+
const documentPid = _get__default["default"](loan, 'metadata.document.pid');
|
|
39157
|
+
const isOverbooked = await isDocumentOverbooked(documentPid);
|
|
39158
|
+
if (isOverbooked) {
|
|
39159
|
+
this.setState({
|
|
39160
|
+
isLoading: false,
|
|
39161
|
+
showOverbookedConfirm: true
|
|
39162
|
+
});
|
|
39163
|
+
return;
|
|
39164
|
+
}
|
|
39165
|
+
} catch (error) {
|
|
39166
|
+
onError('Something went wrong while checking if the literature is overbooked.', error);
|
|
39167
|
+
this.setState({
|
|
39168
|
+
isLoading: false
|
|
39169
|
+
});
|
|
39170
|
+
return;
|
|
39171
|
+
}
|
|
39172
|
+
}
|
|
39173
|
+
await this.performExtension();
|
|
39174
|
+
};
|
|
39175
|
+
this.performExtension = async () => {
|
|
38951
39176
|
const {
|
|
38952
39177
|
loan,
|
|
38953
39178
|
onSuccess,
|
|
@@ -38965,7 +39190,8 @@ class LoanExtendButton extends React.Component {
|
|
|
38965
39190
|
this.cancellableExtendLoan = withCancel(this.extendLoan(extendUrl, document.pid, patronPid));
|
|
38966
39191
|
const response = await this.cancellableExtendLoan.promise;
|
|
38967
39192
|
this.setState({
|
|
38968
|
-
isLoading: false
|
|
39193
|
+
isLoading: false,
|
|
39194
|
+
showOverbookedConfirm: false
|
|
38969
39195
|
});
|
|
38970
39196
|
const documentTitle = document.title;
|
|
38971
39197
|
onSuccess(INFO_MESSAGES.SUCCESS(documentTitle, luxon.DateTime.fromISO(response.data.metadata.end_date)));
|
|
@@ -38976,6 +39202,11 @@ class LoanExtendButton extends React.Component {
|
|
|
38976
39202
|
onError(error.response.data.message);
|
|
38977
39203
|
}
|
|
38978
39204
|
};
|
|
39205
|
+
this.hideOverbookedConfirm = () => {
|
|
39206
|
+
this.setState({
|
|
39207
|
+
showOverbookedConfirm: false
|
|
39208
|
+
});
|
|
39209
|
+
};
|
|
38979
39210
|
this.validate = loan => {
|
|
38980
39211
|
const hasExtendAction = _has__default["default"](loan, 'availableActions.extend');
|
|
38981
39212
|
if (!hasExtendAction) return {
|
|
@@ -39003,7 +39234,8 @@ class LoanExtendButton extends React.Component {
|
|
|
39003
39234
|
};
|
|
39004
39235
|
};
|
|
39005
39236
|
this.state = {
|
|
39006
|
-
isLoading: false
|
|
39237
|
+
isLoading: false,
|
|
39238
|
+
showOverbookedConfirm: false
|
|
39007
39239
|
};
|
|
39008
39240
|
}
|
|
39009
39241
|
componentWillUnmount() {
|
|
@@ -39022,11 +39254,21 @@ class LoanExtendButton extends React.Component {
|
|
|
39022
39254
|
loan
|
|
39023
39255
|
} = this.props;
|
|
39024
39256
|
const {
|
|
39025
|
-
isLoading
|
|
39257
|
+
isLoading,
|
|
39258
|
+
showOverbookedConfirm
|
|
39026
39259
|
} = this.state;
|
|
39027
39260
|
const validation = this.validate(loan);
|
|
39028
39261
|
const isDisabled = !validation.isValid;
|
|
39029
|
-
|
|
39262
|
+
const overbookedDocuments = [{
|
|
39263
|
+
title: _get__default["default"](loan, 'metadata.document.title', 'Unknown title'),
|
|
39264
|
+
loanRequestId: loan.id
|
|
39265
|
+
}];
|
|
39266
|
+
return /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, showOverbookedConfirm && /*#__PURE__*/React__default["default"].createElement(OverbookedConfirmModal, {
|
|
39267
|
+
open: showOverbookedConfirm,
|
|
39268
|
+
onClose: this.hideOverbookedConfirm,
|
|
39269
|
+
onConfirm: this.performExtension,
|
|
39270
|
+
overbookedDocuments: overbookedDocuments
|
|
39271
|
+
}), isDisabled && /*#__PURE__*/React__default["default"].createElement(semanticUiReact.Popup, {
|
|
39030
39272
|
content: validation.msg,
|
|
39031
39273
|
trigger: /*#__PURE__*/React__default["default"].createElement(semanticUiReact.Icon, {
|
|
39032
39274
|
name: "info"
|