@inveniosoftware/react-invenio-app-ils 1.0.0 → 1.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/CHANGES.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changes
2
2
 
3
+ Version 1.2.0 (released 2024-11-19)
4
+
5
+ - self-checkout: integrate new dedicate endpoints
6
+
7
+ Version 1.1.0 (released 2024-11-04)
8
+
9
+ - self-checkout: uppercase barcode when input by the user
10
+
3
11
  Version 1.0.0 (released 2024-10-22)
4
12
 
5
13
  - upgrade axios and react-searchkit dependencies
package/README.md CHANGED
@@ -10,8 +10,7 @@ To update dependencies you need to run `npm install` in the target deployment
10
10
  environment:
11
11
 
12
12
  ```shell
13
- $ rm -rf package-lock.json && rm -rf node_modules
14
-
13
+ $ rm -rf package-lock.json node_modules
15
14
  # Run the container with x86_64 architecture and install packages
16
15
  $ docker run -it --platform="linux/amd64" --rm -v $(pwd):/app -w /app node:14-alpine sh -c "npm install"
17
16
  ```
package/dist/cjs/index.js CHANGED
@@ -440,6 +440,12 @@ const RECORDS_CONFIG = {
440
440
  iconClass: 'dolly'
441
441
  }
442
442
  },
443
+ deliveryMethodSelfCheckout: {
444
+ 'SELF-CHECKOUT': {
445
+ text: 'SELF-CHECKOUT',
446
+ iconClass: 'shopping basket'
447
+ }
448
+ },
443
449
  extensionsMaxCount: 3,
444
450
  loanWillExpireDays: 7,
445
451
  loanActiveStates: ['ITEM_AT_DESK', 'ITEM_ON_LOAN', 'ITEM_IN_TRANSIT_FOR_PICKUP', 'ITEM_IN_TRANSIT_TO_HOUSE'],
@@ -3447,6 +3453,7 @@ const serializer$4 = {
3447
3453
 
3448
3454
  const apiPaths$1 = {
3449
3455
  checkout: '/circulation/loans/checkout',
3456
+ selfCheckout: '/circulation/loans/self-checkout',
3450
3457
  notificationOverdue: '/circulation/loans/:loanPid/notification-overdue',
3451
3458
  item: '/circulation/loans/:loanPid',
3452
3459
  list: '/circulation/loans/',
@@ -3540,6 +3547,24 @@ const doCheckout = async function (documentPid, itemPid, patronPid) {
3540
3547
  response.data = serializer$4.fromJSON(response.data);
3541
3548
  return response;
3542
3549
  };
3550
+ const doSelfCheckoutSearchItem = async barcode => {
3551
+ const response = await http.get(`${apiPaths$1.selfCheckout}?barcode=${barcode}`);
3552
+ response.data = serializer$4.fromJSON(response.data);
3553
+ return response;
3554
+ };
3555
+ const doSelfCheckout = async (documentPid, itemPid, patronPid) => {
3556
+ const currentUser = sessionManager.user;
3557
+ const payload = {
3558
+ document_pid: documentPid,
3559
+ item_pid: itemPid,
3560
+ patron_pid: patronPid,
3561
+ transaction_location_pid: `${currentUser.locationPid}`,
3562
+ transaction_user_pid: `${currentUser.id}`
3563
+ };
3564
+ const response = await http.post(apiPaths$1.selfCheckout, payload);
3565
+ response.data = serializer$4.fromJSON(response.data);
3566
+ return response;
3567
+ };
3543
3568
  const assignItemToLoan$1 = async (itemPid, loanPid) => {
3544
3569
  const path = reactRouterDom.generatePath(apiPaths$1.replaceItem, {
3545
3570
  loanPid: loanPid
@@ -3720,6 +3745,8 @@ const loanApi = {
3720
3745
  doAction: doAction,
3721
3746
  doRequest: doRequest,
3722
3747
  doCheckout: doCheckout,
3748
+ doSelfCheckout: doSelfCheckout,
3749
+ doSelfCheckoutSearchItem: doSelfCheckoutSearchItem,
3723
3750
  sendOverdueLoansNotificationReminder: sendOverdueLoansNotificationReminder$1,
3724
3751
  serializer: serializer$4,
3725
3752
  updateDates: updateDates,
@@ -12163,6 +12190,7 @@ class LoanListEntry extends React.Component {
12163
12190
  const patronPid = loan.metadata.patron_pid;
12164
12191
  const delivery = _get__default["default"](loan.metadata.delivery, 'method');
12165
12192
  const deliveryMethod = delivery && loan.metadata.state === 'PENDING' ? invenioConfig.CIRCULATION.deliveryMethods[delivery] : '';
12193
+ const isSelfCheckout = delivery === 'SELF-CHECKOUT';
12166
12194
  return /*#__PURE__*/React__default["default"].createElement(semanticUiReact.Item, null, /*#__PURE__*/React__default["default"].createElement(semanticUiReact.Item.Content, null, loan.metadata.is_overdue && /*#__PURE__*/React__default["default"].createElement(semanticUiReact.Label, {
12167
12195
  color: "red"
12168
12196
  }, "Overdue"), /*#__PURE__*/React__default["default"].createElement(semanticUiReact.Item.Header, {
@@ -12197,8 +12225,10 @@ class LoanListEntry extends React.Component {
12197
12225
  }, loan.metadata.extension_count || '0'), /*#__PURE__*/React__default["default"].createElement(semanticUiReact.List.Content, null, /*#__PURE__*/React__default["default"].createElement("label", null, " Extensions"))))), /*#__PURE__*/React__default["default"].createElement(semanticUiReact.Grid.Column, {
12198
12226
  width: 2,
12199
12227
  textAlign: "center"
12200
- }, deliveryMethod && /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, delivery, ' ', deliveryMethod.iconClass && /*#__PURE__*/React__default["default"].createElement(semanticUiReact.Icon, {
12228
+ }, deliveryMethod ? /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, delivery, ' ', deliveryMethod.iconClass && /*#__PURE__*/React__default["default"].createElement(semanticUiReact.Icon, {
12201
12229
  className: deliveryMethod.iconClass
12230
+ })) : isSelfCheckout && /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, delivery, ' ', /*#__PURE__*/React__default["default"].createElement(semanticUiReact.Icon, {
12231
+ className: invenioConfig.CIRCULATION.deliveryMethodSelfCheckout[delivery].iconClass
12202
12232
  }))), /*#__PURE__*/React__default["default"].createElement(semanticUiReact.Grid.Column, {
12203
12233
  computer: 3,
12204
12234
  largeScreen: 3
@@ -24871,7 +24901,7 @@ const deleteItem = itemPid => {
24871
24901
  }
24872
24902
  };
24873
24903
  };
24874
- const checkoutItem$2 = function (documentPid, itemPid, patronPid) {
24904
+ const checkoutItem$1 = function (documentPid, itemPid, patronPid) {
24875
24905
  let force = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
24876
24906
  return async dispatch => {
24877
24907
  dispatch({
@@ -25071,7 +25101,7 @@ const mapDispatchToProps$J = dispatch => ({
25071
25101
  deleteItem: itemPid => dispatch(deleteItem(itemPid)),
25072
25102
  checkoutItem: function (documentPid, itemPid, patronPid) {
25073
25103
  let force = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
25074
- return dispatch(checkoutItem$2(documentPid, itemPid, patronPid, force));
25104
+ return dispatch(checkoutItem$1(documentPid, itemPid, patronPid, force));
25075
25105
  }
25076
25106
  });
25077
25107
  const ItemActionMenu = reactRedux.connect(mapStateToProps$W, mapDispatchToProps$J)(ItemActionMenu$1);
@@ -25452,7 +25482,7 @@ const mapDispatchToProps$I = dispatch => ({
25452
25482
  deleteItem: itemPid => dispatch(deleteItem(itemPid)),
25453
25483
  checkoutItem: function (documentPid, itemPid, patronPid) {
25454
25484
  let force = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
25455
- return dispatch(checkoutItem$2(documentPid, itemPid, patronPid, force));
25485
+ return dispatch(checkoutItem$1(documentPid, itemPid, patronPid, force));
25456
25486
  }
25457
25487
  });
25458
25488
  const ItemMetadata$1 = reactRedux.connect(mapStateToProps$U, mapDispatchToProps$I)(ItemMetadata$2);
@@ -26625,7 +26655,7 @@ class LoanMetadata$1 extends React.Component {
26625
26655
  getDelivery(_delivery) {
26626
26656
  const delivery = _get__default["default"](_delivery, 'method');
26627
26657
  if (delivery) {
26628
- const deliveryMethod = invenioConfig.CIRCULATION.deliveryMethods[delivery];
26658
+ const deliveryMethod = invenioConfig.CIRCULATION.deliveryMethods[delivery] || invenioConfig.CIRCULATION.deliveryMethodSelfCheckout[delivery];
26629
26659
  return /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, deliveryMethod.text, ' ', deliveryMethod.iconClass && /*#__PURE__*/React__default["default"].createElement(semanticUiReact.Icon, {
26630
26660
  className: deliveryMethod.iconClass
26631
26661
  }));
@@ -29571,7 +29601,7 @@ const CLEAR_SEARCH = 'itemsSearchBarcode/CLEAR_SEARCH';
29571
29601
  const IS_LOADING$h = 'patronItemCheckout/IS_LOADING';
29572
29602
  const SUCCESS$h = 'patronItemCheckout/SUCCESS';
29573
29603
  const HAS_ERROR$h = 'patronItemCheckout/ERROR';
29574
- const checkoutItem$1 = function (documentPid, itemPid, patronPid) {
29604
+ const checkoutItem = function (documentPid, itemPid, patronPid) {
29575
29605
  let force = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
29576
29606
  return async dispatch => {
29577
29607
  dispatch({
@@ -29612,7 +29642,7 @@ const checkoutItem$1 = function (documentPid, itemPid, patronPid) {
29612
29642
  const mapDispatchToProps$t = dispatch => ({
29613
29643
  checkoutItem: function (documentPid, itemPid, patronPid) {
29614
29644
  let force = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
29615
- return dispatch(checkoutItem$1(documentPid, itemPid, patronPid, force));
29645
+ return dispatch(checkoutItem(documentPid, itemPid, patronPid, force));
29616
29646
  }
29617
29647
  });
29618
29648
  const mapStateToProps$E = state => ({
@@ -29774,7 +29804,7 @@ const mapStateToProps$D = state => ({
29774
29804
  const mapDispatchToProps$s = dispatch => ({
29775
29805
  checkoutItem: function (documentPid, itemPid, patronPid) {
29776
29806
  let force = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
29777
- return dispatch(checkoutItem$1(documentPid, itemPid, patronPid, force));
29807
+ return dispatch(checkoutItem(documentPid, itemPid, patronPid, force));
29778
29808
  }
29779
29809
  });
29780
29810
  const ItemsResultsList = reactRedux.connect(mapStateToProps$D, mapDispatchToProps$s)(ItemsResultsList$1);
@@ -29900,7 +29930,7 @@ const fetchAndCheckoutIfOne = (barcode, patronPid, onSuccess) => {
29900
29930
  type: recordToPidType(itemToCheckout),
29901
29931
  value: itemToCheckout.metadata.pid
29902
29932
  };
29903
- dispatch(checkoutItem$1(documentPid, itemPid, patronPid, true));
29933
+ dispatch(checkoutItem(documentPid, itemPid, patronPid, true));
29904
29934
  onSuccess();
29905
29935
  }
29906
29936
  } catch (error) {
@@ -29935,7 +29965,7 @@ const mapDispatchToProps$r = dispatch => ({
29935
29965
  clearResults: () => dispatch(clearResults()),
29936
29966
  checkoutItem: function (documentPid, itemPid, patronPid) {
29937
29967
  let force = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
29938
- return dispatch(checkoutItem$1(documentPid, itemPid, patronPid, force));
29968
+ return dispatch(checkoutItem(documentPid, itemPid, patronPid, force));
29939
29969
  }
29940
29970
  });
29941
29971
  const mapStateToProps$C = state => ({
@@ -37659,7 +37689,7 @@ class ManualCheckout extends React__default["default"].Component {
37659
37689
  constructor(props) {
37660
37690
  super(props);
37661
37691
  this.state = {
37662
- manualBarcode: null
37692
+ manualBarcode: ''
37663
37693
  };
37664
37694
  this.inputRef = React__default["default"].createRef();
37665
37695
  }
@@ -37676,7 +37706,7 @@ class ManualCheckout extends React__default["default"].Component {
37676
37706
  render() {
37677
37707
  const {
37678
37708
  show,
37679
- onChange,
37709
+ onBarcodeInput,
37680
37710
  label
37681
37711
  } = this.props;
37682
37712
  const {
@@ -37690,17 +37720,22 @@ class ManualCheckout extends React__default["default"].Component {
37690
37720
  }, /*#__PURE__*/React__default["default"].createElement(semanticUiReact.Header, {
37691
37721
  className: "pb-1",
37692
37722
  as: "h5"
37693
- }, label, " Add the barcode manually:"), /*#__PURE__*/React__default["default"].createElement(semanticUiReact.Input, {
37723
+ }, label, " Insert the barcode manually:"), /*#__PURE__*/React__default["default"].createElement(semanticUiReact.Input, {
37694
37724
  id: "barcodeInput",
37695
37725
  type: "text",
37696
37726
  placeholder: "Barcode...",
37697
37727
  className: "pb-1",
37698
37728
  ref: this.inputRef,
37699
- onChange: e => this.setState({
37700
- manualBarcode: e.target.value
37701
- })
37729
+ value: manualBarcode,
37730
+ onChange: e => {
37731
+ var _e$target$value;
37732
+ return this.setState({
37733
+ manualBarcode: (_e$target$value = e.target.value) === null || _e$target$value === void 0 ? void 0 : _e$target$value.toUpperCase()
37734
+ });
37735
+ }
37702
37736
  }), /*#__PURE__*/React__default["default"].createElement(semanticUiReact.Button, {
37703
- onClick: () => onChange(manualBarcode),
37737
+ onClick: () => manualBarcode && onBarcodeInput(manualBarcode),
37738
+ disabled: !manualBarcode,
37704
37739
  className: "ml-10",
37705
37740
  type: "submit"
37706
37741
  }, "Search")));
@@ -37711,7 +37746,7 @@ class ManualCheckout extends React__default["default"].Component {
37711
37746
  }
37712
37747
  ManualCheckout.defaultProps = {
37713
37748
  show: false,
37714
- label: 'Can’t scan the barcode?',
37749
+ label: "Can't scan the barcode?",
37715
37750
  autofocus: false
37716
37751
  };
37717
37752
 
@@ -37761,14 +37796,14 @@ class SelfCheckoutModal$1 extends React__default["default"].Component {
37761
37796
  size: "large",
37762
37797
  centered: true,
37763
37798
  onClose: () => toggleModal(false)
37764
- }, /*#__PURE__*/React__default["default"].createElement(semanticUiReact.Modal.Header, null, `You are about to checkout a book with barcode:
37799
+ }, /*#__PURE__*/React__default["default"].createElement(semanticUiReact.Modal.Header, null, `You are about to checkout the literature with barcode:
37765
37800
  ${item === null || item === void 0 ? void 0 : item.metadata.barcode}`), /*#__PURE__*/React__default["default"].createElement(semanticUiReact.Modal.Content, null, /*#__PURE__*/React__default["default"].createElement(DocumentCard, {
37766
37801
  item: item
37767
37802
  }), /*#__PURE__*/React__default["default"].createElement(ManualCheckout, {
37768
- label: "Wrong book?",
37803
+ label: "Wrong literature?",
37769
37804
  autofocus: true,
37770
37805
  show: true,
37771
- onChange: onBarcodeDetected
37806
+ onBarcodeInput: onBarcodeDetected
37772
37807
  })), /*#__PURE__*/React__default["default"].createElement(semanticUiReact.Modal.Actions, null, /*#__PURE__*/React__default["default"].createElement(semanticUiReact.Button, {
37773
37808
  color: "black",
37774
37809
  onClick: () => toggleModal(false),
@@ -37803,21 +37838,19 @@ const notifyResultMessage = message => {
37803
37838
  dispatch(sendWarningNotification(message));
37804
37839
  };
37805
37840
  };
37806
- const searchItem = async (dispatch, term) => {
37807
- const response = await itemApi.list(itemApi.query().withBarcode(term).qs());
37808
- const item = _first__default["default"](response.data.hits) || null;
37809
- dispatch({
37810
- type: SEARCH_ITEM_SUCCESS,
37811
- payload: item
37812
- });
37813
- };
37814
37841
  const selfCheckOutSearch = term => {
37815
37842
  return async dispatch => {
37816
37843
  dispatch({
37817
37844
  type: SEARCH_IS_LOADING
37818
37845
  });
37819
37846
  try {
37820
- await searchItem(dispatch, term);
37847
+ const upperCasedTerm = term.toUpperCase();
37848
+ const response = await loanApi.doSelfCheckoutSearchItem(upperCasedTerm);
37849
+ const item = response.data || null;
37850
+ dispatch({
37851
+ type: SEARCH_ITEM_SUCCESS,
37852
+ payload: item
37853
+ });
37821
37854
  } catch (error) {
37822
37855
  dispatch({
37823
37856
  type: SEARCH_HAS_ERROR,
@@ -37827,16 +37860,13 @@ const selfCheckOutSearch = term => {
37827
37860
  }
37828
37861
  };
37829
37862
  };
37830
- const checkoutItem = (documentPid, itemPid, patronPid) => {
37863
+ const selfCheckOut = (documentPid, itemPid, patronPid) => {
37831
37864
  return async dispatch => {
37832
37865
  try {
37833
- const response = await loanApi.doCheckout(documentPid, itemPid, patronPid);
37834
- const {
37835
- pid
37836
- } = response.data.metadata;
37837
- const linkToLoan = /*#__PURE__*/React__default["default"].createElement("p", null, "The loan ", pid, " has been created by you!", ' ', /*#__PURE__*/React__default["default"].createElement(reactRouterDom.Link, {
37866
+ await loanApi.doSelfCheckout(documentPid, itemPid, patronPid);
37867
+ const linkToLoan = /*#__PURE__*/React__default["default"].createElement("p", null, "Self-checkout completed! You can view all your current loans on your", ' ', /*#__PURE__*/React__default["default"].createElement(reactRouterDom.Link, {
37838
37868
  to: FrontSiteRoutes.patronProfile
37839
- }, "You can now view the loan details."));
37869
+ }, "profile"), " page.");
37840
37870
  dispatch(sendSuccessNotification('Success!', linkToLoan));
37841
37871
  } catch (error) {
37842
37872
  dispatch(sendErrorNotification(error));
@@ -37845,7 +37875,7 @@ const checkoutItem = (documentPid, itemPid, patronPid) => {
37845
37875
  };
37846
37876
 
37847
37877
  const mapDispatchToProps$a = dispatch => ({
37848
- checkoutItem: (documentPid, itemPid, patronPid) => dispatch(checkoutItem(documentPid, itemPid, patronPid))
37878
+ checkoutItem: (documentPid, itemPid, patronPid) => dispatch(selfCheckOut(documentPid, itemPid, patronPid))
37849
37879
  });
37850
37880
  const mapStateToProps$b = state => ({
37851
37881
  user: state.authenticationManagement.data,
@@ -37879,48 +37909,8 @@ class SelfCheckout$1 extends React__default["default"].Component {
37879
37909
  selfCheckOutSearch
37880
37910
  } = this.props;
37881
37911
  await selfCheckOutSearch(detectedBarcode);
37882
-
37883
- // open modal if item is loanable
37884
- const shouldShowModal = this.isItemLoanable(detectedBarcode);
37885
- if (shouldShowModal) {
37886
- this.toggleModal(true);
37887
- } else {
37888
- this.toggleModal(false);
37889
- }
37890
- }
37891
- };
37892
- this.itemStatus = item => ({
37893
- canCirculate: () => invenioConfig.ITEMS.canCirculateStatuses.includes(item.metadata.status),
37894
- isOnShelf: () => !item.metadata.circulation.state // on shelf if circulation.state doesn't exist
37895
- });
37896
- this.isItemLoanable = itemBarcode => {
37897
- const {
37898
- user,
37899
- item,
37900
- notifyResultMessage
37901
- } = this.props;
37902
- var resultMessage = `Book with barcode: ${itemBarcode} doesn't exist.`;
37903
- if (!_isEmpty__default["default"](item)) {
37904
- if (this.itemStatus(item).canCirculate()) {
37905
- if (this.itemStatus(item).isOnShelf()) {
37906
- return true;
37907
- } else {
37908
- if (item.metadata.circulation.patron_pid === user.id.toString()) {
37909
- resultMessage = `You already loaned this book with barcode: ${itemBarcode}!`;
37910
- } else {
37911
- resultMessage = `Book with barcode: ${itemBarcode} is currently on loan!`;
37912
- }
37913
- }
37914
- } else {
37915
- var _item$metadata;
37916
- const status = _find__default["default"](invenioConfig.ITEMS.statuses, {
37917
- value: (_item$metadata = item.metadata) === null || _item$metadata === void 0 ? void 0 : _item$metadata.status
37918
- });
37919
- resultMessage = `Book with barcode: ${itemBarcode} is ${status === null || status === void 0 ? void 0 : status.text}!`;
37920
- }
37912
+ this.toggleModal(true);
37921
37913
  }
37922
- notifyResultMessage(resultMessage);
37923
- return false;
37924
37914
  };
37925
37915
  this.renderInstructions = () => {
37926
37916
  return /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, /*#__PURE__*/React__default["default"].createElement(semanticUiReact.Header, {
@@ -37960,24 +37950,24 @@ class SelfCheckout$1 extends React__default["default"].Component {
37960
37950
  onBarcodeDetected: this.onBarcodeDetected
37961
37951
  }), /*#__PURE__*/React__default["default"].createElement(ManualCheckout, {
37962
37952
  show: true,
37963
- onChange: this.onBarcodeDetected
37953
+ onBarcodeInput: this.onBarcodeDetected
37964
37954
  }), /*#__PURE__*/React__default["default"].createElement(semanticUiReact.Message, {
37965
37955
  warning: true,
37966
37956
  compact: true
37967
- }, "If your browser isn't able to scan the barcode, try", /*#__PURE__*/React__default["default"].createElement("br", null), "using another browser. (Recommended: Chrome)")), /*#__PURE__*/React__default["default"].createElement(SelfCheckoutModal, {
37957
+ }, "Barcode not detected while scanning?", /*#__PURE__*/React__default["default"].createElement("br", null), "Try using another browser. (Recommended:", ' ', /*#__PURE__*/React__default["default"].createElement("a", {
37958
+ href: "https://www.google.com/chrome/"
37959
+ }, "Google Chrome"), ")")), /*#__PURE__*/React__default["default"].createElement(SelfCheckoutModal, {
37968
37960
  modalOpened: showModal,
37969
37961
  toggleModal: this.toggleModal,
37970
37962
  onBarcodeDetected: this.onBarcodeDetected
37971
37963
  }), this.renderInstructions());
37972
37964
  }
37973
37965
  }
37974
- SelfCheckout$1.defaultProps = {
37975
- item: null
37976
- };
37977
37966
  var SelfCheckoutComponent = Overridable__default["default"].component('SelfCheckout', SelfCheckout$1);
37978
37967
 
37979
37968
  const mapDispatchToProps$9 = dispatch => ({
37980
37969
  selfCheckOutSearch: term => dispatch(selfCheckOutSearch(term)),
37970
+ selfCheckOut: term => dispatch(selfCheckOut(term)),
37981
37971
  notifyResultMessage: message => dispatch(notifyResultMessage(message))
37982
37972
  });
37983
37973
  const mapStateToProps$a = state => ({