View | Details | Raw Unified | Return to bug 23269
Collapse All | Expand All

(-)a/Koha/REST/V1/Holds.pm (-3 / +3 lines)
Lines 265-273 sub edit { Link Here
265
        }
265
        }
266
266
267
        $pickup_library_id //= $hold->branchcode;
267
        $pickup_library_id //= $hold->branchcode;
268
        my $priority        = $body->{priority}        // $hold->priority;
268
        my $priority        = $body->{priority} // $hold->priority;
269
        my $hold_date       = $body->{hold_date}       // $hold->reservedate;
269
        my $hold_date       = exists $body->{hold_date}       ? $body->{hold_date}       : $hold->reservedate;
270
        my $expiration_date = $body->{expiration_date} // $hold->expirationdate;
270
        my $expiration_date = exists $body->{expiration_date} ? $body->{expiration_date} : $hold->expirationdate;
271
271
272
        # suspended_until can also be set to undef
272
        # suspended_until can also be set to undef
273
        my $suspended_until = $body->{suspended_until} || $hold->suspend_until;
273
        my $suspended_until = $body->{suspended_until} || $hold->suspend_until;
(-)a/api/v1/swagger/definitions/hold.yaml (-1 / +11 lines)
Lines 123-132 properties: Link Here
123
      - object
123
      - object
124
      - "null"
124
      - "null"
125
    description: The item
125
    description: The item
126
  item_group:
127
    type:
128
      - object
129
      - "null"
130
    description: The item group
131
  patron:
132
    type:
133
      - object
134
      - "null"
135
    description: The patron
126
  pickup_library:
136
  pickup_library:
127
    type:
137
    type:
128
      - object
138
      - object
129
      - "null"
139
      - "null"
130
    description: Pickup library
140
    description: Pickup library
131
141
132
additionalProperties: false
142
additionalProperties: false
(-)a/api/v1/swagger/paths/holds.yaml (-2 / +9 lines)
Lines 104-109 Link Here
104
            - cancellation_requested
104
            - cancellation_requested
105
            - biblio
105
            - biblio
106
            - pickup_library
106
            - pickup_library
107
            - patron
108
            - item
109
            - item_group
107
        collectionFormat: csv
110
        collectionFormat: csv
108
    produces:
111
    produces:
109
      - application/json
112
      - application/json
Lines 289-299 Link Here
289
              format: date-time
292
              format: date-time
290
            hold_date:
293
            hold_date:
291
              description: Hold date
294
              description: Hold date
292
              type: string
295
              type:
296
                - string
297
                - "null"
293
              format: date
298
              format: date
294
            expiration_date:
299
            expiration_date:
295
              description: Hold's expiration date
300
              description: Hold's expiration date
296
              type: string
301
              type:
302
                - string
303
                - "null"
297
              format: date
304
              format: date
298
          additionalProperties: false
305
          additionalProperties: false
299
    consumes:
306
    consumes:
(-)a/koha-tmpl/intranet-tmpl/prog/en/includes/holds_table.inc (-342 / +3 lines)
Lines 5-365 Link Here
5
[%#This include depends on the asset js/form-submit.js. Any template making use of this include must import form-submit.js as well. %]
5
[%#This include depends on the asset js/form-submit.js. Any template making use of this include must import form-submit.js as well. %]
6
[%#FIXME can form-submit.js be imported into this file directly? %]
6
[%#FIXME can form-submit.js be imported into this file directly? %]
7
7
8
<table id="patron_holds_table" class="holds_table">
8
<table id="patron_holds_table_[% biblio_id | html %]_[% split_data | html %]" class="holds_table" data-total-holds="[% total_holds | html %]">
9
    <thead>
9
    <thead>
10
        <tr>
10
        <tr>
11
            <th id="checkbox" data-colname="checkbox"><input type="checkbox" class="select_hold_all" /></th>
11
            <th id="checkbox" data-colname="checkbox"><input type="checkbox" class="select_hold_all" /></th>
12
            <th id="priority" data-colname="priority">Priority</th>
12
            <th id="priority" data-colname="priority">Priority</th>
13
            [% IF ( CAN_user_reserveforothers_modify_holds_priority ) %]
13
            <th id="change_priority" data-colname="change_priority">Change priority</th>
14
                <th id="change_priority" data-colname="change_priority">Change priority</th>
15
            [% END %]
16
            <th id="patron" data-colname="patron">Patron</th>
14
            <th id="patron" data-colname="patron">Patron</th>
17
            <th id="notes" data-colname="notes">Notes</th>
15
            <th id="notes" data-colname="notes">Notes</th>
18
            <th id="date" data-colname="date">Date</th>
16
            <th id="date" data-colname="date">Date</th>
19
            <th id="expiration" data-colname="expiration">Expiration</th>
17
            <th id="expiration" data-colname="expiration">Expiration</th>
20
            <th id="pickup_library" data-colname="pickup_library">Pickup library</th>
18
            <th id="pickup_library" data-colname="pickup_library">Pickup library</th>
21
            <th id="details" data-colname="details">Details</th>
19
            <th id="details" data-colname="details">Details</th>
22
            [% IF ( CAN_user_reserveforothers_modify_holds_priority ) %]
20
            <th id="set_lowest_priority" data-colname="set_lowest_priority"><span style="display:none;">Set lowest priority</span><i class="fa fa-lg fa-rotate-90 fa-fast-forward" title="Toggle set to lowest priority"></i></th>
23
                <th id="set_lowest_priority" data-colname="set_lowest_priority"><span style="display:none;">Set lowest priority</span><i class="fa fa-lg fa-rotate-90 fa-fast-forward" title="Toggle set to lowest priority"></i></th>
24
            [% END %]
25
            <th id="delete" data-colname="delete">Delete</th>
21
            <th id="delete" data-colname="delete">Delete</th>
26
            <th id="suspend" data-colname="suspend">Suspend</th>
22
            <th id="suspend" data-colname="suspend">Suspend</th>
27
            <th id="print_slip" data-colname="print_slip">Print hold/transfer slip</th>
23
            <th id="print_slip" data-colname="print_slip">Print hold/transfer slip</th>
28
        </tr>
24
        </tr>
29
    </thead>
25
    </thead>
30
    [%- SET first_priority = 0 -%]
31
    [%- SET found_holds = 0 -%]
32
    [%- SET last_priority  = holds.last.priority -%]
33
34
    [% SET all_priorities = [] %]
35
    [% FOREACH hold IN holds %]
36
        [% all_priorities.push( hold.priority ) %]
37
    [% END %]
38
39
    <tbody>
40
        [% FOREACH hold IN holds %]
41
            [%- IF !hold.found && first_priority == 0 -%]
42
                [%- first_priority = hold.priority -%]
43
                [%- found_holds = loop.index() -%]
44
            [%- END -%]
45
            [%- IF Koha.Preference('HoldsSplitQueueNumbering') == 'actual' -%]
46
                [%- this_priority = hold.priority -%]
47
            [%- ELSE -%]
48
                [%- this_priority = loop.count() - found_holds -%]
49
            [%- END -%]
50
            [% SET tr_class = hold.suspend ? 'suspend' : '' %]
51
            <tr class="[% tr_class | html %]">
52
                <td><input type="checkbox" class="select_hold" data-id="[% hold.reserve_id | html %]" /></td>
53
                <td>
54
                    <input type="hidden" name="reserve_id" value="[% hold.reserve_id | html %]" />
55
                    <input type="hidden" name="borrowernumber" value="[% hold.borrowernumber | html %]" />
56
                    <input type="hidden" name="biblionumber" value="[% hold.biblionumber | html %]" />
57
                    [% IF ( CAN_user_reserveforothers_modify_holds_priority ) %]
58
                        [% IF Koha.Preference('HoldsSplitQueue') == "nothing" && !hold.found %]
59
                            <select name="rank-request" class="rank-request" data-hold-id="[% hold.reserve_id | html %]">
60
                                [% IF ( CAN_user_reserveforothers_modify_holds_priority ) %]
61
                                    [% FOREACH priority IN all_priorities %]
62
                                        [% IF priority == this_priority %]
63
                                            <option value="[% priority | html %]" selected="selected">[% priority | html %]</option>
64
                                        [% ELSIF priority > 0 %]
65
                                            <option value="[% priority | html %]">[% priority | html %]</option>
66
                                        [% END %]
67
                                    [% END %]
68
                                [% ELSE %]
69
                                    <option value="[% hold.priority | html %]" selected="selected">[% this_priority | html %]</option>
70
                                [% END %]
71
                                <option value="del">del</option>
72
                            </select>
73
                        [% ELSE %]
74
                            <input type="hidden" name="rank-request" class="rank-request" value="[% hold.priority | html %]" data-hold-id="[% hold.reserve_id | html %]" />
75
                            <select name="rank-request" class="rank-request" disabled="disabled" data-hold-id="[% hold.reserve_id | html %]">
76
                                [% IF ( hold.found ) %]
77
                                    [% IF ( hold.intransit ) %]
78
                                        <option value="T" selected="selected">In transit</option>
79
                                    [% ELSIF (hold.inprocessing) %]
80
                                        <option value="P" selected="selected">In processing</option>
81
                                    [% ELSE %]
82
                                        <option value="W" selected="selected">Waiting</option>
83
                                    [% END %]
84
                                [% ELSE %]
85
                                    <option value="[% hold.priority | html %]" selected="selected">[% this_priority | html %]</option>
86
                                [% END %]
87
                            </select>
88
                        [% END %]
89
                    [% ELSE %]
90
                        <input type="hidden" name="rank-request" class="rank-request" value="[% hold.priority | html %]" data-hold-id="[% hold.reserve_id | html %]" />
91
                        [% hold.priority | html %]
92
                    [% END %]
93
                </td>
94
                [%- IF ( CAN_user_reserveforothers_modify_holds_priority ) -%]
95
                    [%- UNLESS hold.found -%]
96
                        [%- SET prev_priority  = loop.prev.priority -%]
97
                        [%- SET next_priority  = loop.next.priority -%]
98
                        <td style="white-space:nowrap;">
99
                            <a
100
                                class="hold-arrow"
101
                                title="Move hold up"
102
                                data-op="cud-move"
103
                                data-where="up"
104
                                data-first_priority="[% first_priority | html %]"
105
                                data-last_priority="[% last_priority | html %]"
106
                                data-prev_priority="[% prev_priority | html %]"
107
                                data-next_priority="[% next_priority | html %]"
108
                                data-borrowernumber="[% hold.borrowernumber | html %]"
109
                                data-biblionumber="[% hold.biblionumber | html %]"
110
                                data-reserve_id="[% hold.reserve_id | html %]"
111
                                data-date="[% hold.date | html %]"
112
                            >
113
                                <i class="fa fa-lg icon-move-hold-up" aria-hidden="true"></i>
114
                            </a>
115
116
                            <a
117
                                class="hold-arrow"
118
                                title="Move hold to top"
119
                                data-op="cud-move"
120
                                data-where="top"
121
                                data-first_priority="[% first_priority | html %]"
122
                                data-last_priority="[% last_priority | html %]"
123
                                data-prev_priority="[% prev_priority | html %]"
124
                                data-next_priority="[% next_priority | html %]"
125
                                data-borrowernumber="[% hold.borrowernumber | html %]"
126
                                data-biblionumber="[% hold.biblionumber | html %]"
127
                                data-reserve_id="[% hold.reserve_id | html %]"
128
                                data-date="[% hold.date | html %]"
129
                            >
130
                                <i class="fa fa-lg icon-move-hold-top" aria-hidden="true"></i>
131
                            </a>
132
133
                            <a
134
                                class="hold-arrow"
135
                                title="Move hold to bottom"
136
                                data-op="cud-move"
137
                                data-where="bottom"
138
                                data-first_priority="[% first_priority | html %]"
139
                                data-last_priority="[% last_priority | html %]"
140
                                data-prev_priority="[% prev_priority | html %]"
141
                                data-next_priority="[% next_priority | html %]"
142
                                data-borrowernumber="[% hold.borrowernumber | html %]"
143
                                data-biblionumber="[% hold.biblionumber | html %]"
144
                                data-reserve_id="[% hold.reserve_id | html %]"
145
                                data-date="[% hold.date | html %]"
146
                            >
147
                                <i class="fa fa-lg icon-move-hold-bottom" aria-hidden="true"></i>
148
                            </a>
149
150
                            <a
151
                                class="hold-arrow"
152
                                title="Move hold down"
153
                                data-op="cud-move"
154
                                data-where="down"
155
                                data-first_priority="[% first_priority | html %]"
156
                                data-last_priority="[% last_priority | html %]"
157
                                data-prev_priority="[% prev_priority | html %]"
158
                                data-next_priority="[% next_priority | html %]"
159
                                data-borrowernumber="[% hold.borrowernumber | html %]"
160
                                data-biblionumber="[% hold.biblionumber | html %]"
161
                                data-reserve_id="[% hold.reserve_id | html %]"
162
                                data-date="[% hold.date | html %]"
163
                            >
164
                                <i class="fa fa-lg icon-move-hold-down" aria-hidden="true"></i>
165
                            </a>
166
                        </td>
167
                    [%- ELSE -%]
168
                        <td></td>
169
                    [%- END -%]
170
                [%- END -%]
171
                <td> [% INCLUDE 'patron-title.inc' patron=hold.patron hide_patron_infos_if_needed=1 %] </td>
172
                <td>[% hold.notes | html | html_line_break %]</td>
173
                <td data-order="[% hold.date| html %]">
174
                    [% IF Koha.Preference('AllowHoldDateInFuture') %]
175
                        <input type="text" class="flatpickr" value="[% hold.date | html %]" required="required" size="10" name="reservedate" />
176
                    [% ELSE %]
177
                        [% hold.date | $KohaDates %]
178
                    [% END %]
179
                </td>
180
                <td>
181
                    <input type="text" class="flatpickr" data-flatpickr-futuredate="true" value="[% hold.expirationdate | html %]" size="10" name="expirationdate" />
182
                </td>
183
                <td>
184
                    [%- IF ( hold.found ) -%]
185
                        <input type="hidden" name="pickup" value="[% hold.wbrcode | html %]" />
186
                        [%- IF ( hold.atdestination ) -%]
187
                            Item waiting at <strong> [% hold.wbrname | html %]</strong>[% IF hold.desk_name %], [% hold.desk_name | html %],[% END %] since [% hold.waiting_date | $KohaDates %]
188
                        [%- ELSIF (hold.intransit) -%]
189
                            Item being transferred to <strong> [% hold.wbrname | html %]</strong>
190
                        [%- ELSIF (hold.inprocessing) -%]
191
                            Item being processed at <strong> [% hold.wbrname | html %]</strong>
192
                        [%- ELSE -%]
193
                            Hold expected at <strong>[% hold.wbrname | html %]</strong>, please checkin to verify status
194
                        [%- END -%]
195
                    [%- ELSE -%]
196
                        [%- IF Koha.Preference('IndependentBranches') && Branches.all().size == 1 -%]
197
                            [% Branches.GetName(hold.branchcode) | html %] <input type="hidden" name="pickup" value="[% hold.branchcode | html %]" />
198
                        [%- ELSE -%]
199
                            <select class="pickup_location_dropdown" data-selected="[% hold.branchcode | html %]" data-hold-id="[% hold.reserve_id | html %]" data-pickup-location-source="hold" name="pickup">
200
                                <option selected="selected" value="[% hold.branchcode | html %]">[% Branches.GetName(hold.branchcode) | html %]</option>
201
                                <option value="" disabled="disabled" class="loading">Loading...</option>
202
                            </select>
203
                            <img class="loading_[% hold.reserve_id | html %]" src="[% interface | html %]/[% theme | html %]/img/spinner-small.gif" alt="" style="display:none;" />
204
                        [%- END -%]
205
                    [%- END -%]
206
                </td>
207
                <td>
208
                    [%- IF ( hold.found ) -%]
209
                        <a href="/cgi-bin/koha/catalogue/moredetail.pl?biblionumber=[% hold.biblionumber | uri %]&amp;itemnumber=[% hold.itemnumber | uri %]#item[% hold.itemnumber | uri %]">
210
                            [%- IF ( hold.barcodenumber ) -%]
211
                                [%- hold.barcodenumber | html -%]
212
                            [%- ELSE -%]
213
                                <span>No barcode</span>
214
                            [%- END -%]
215
                            <input type="hidden" name="itemnumber" value="[% hold.itemnumber | html %]" />
216
                        </a>
217
                    [%- ELSE -%]
218
                        [%- IF ( hold.item_level_hold ) -%]
219
                            <em>
220
                                [%- IF ! hold.change_hold_type_allowed -%]
221
                                    <span>Only item</span>
222
                                    <a href="/cgi-bin/koha/catalogue/moredetail.pl?biblionumber=[% hold.biblionumber | uri %]&amp;itemnumber=[% hold.itemnumber | uri %]#item[% hold.itemnumber | uri %]">
223
                                        [%- IF ( hold.barcodenumber ) -%]
224
                                            [%- hold.barcodenumber | html -%]
225
                                        [%- ELSE -%]
226
                                            <span>No barcode</span>
227
                                        [%- END -%]
228
                                        <input type="hidden" name="itemnumber" value="[% hold.itemnumber | html %]" />
229
                                    </a>
230
                                [%- ELSE -%]
231
                                    <select name="change_hold_type_[% hold.reserve_id | html %]">
232
                                        <option selected="selected" value=""
233
                                            >Only item
234
                                            [%- IF ( hold.barcodenumber ) -%]
235
                                                [%- hold.barcodenumber | html -%]
236
                                            [%- ELSE -%]
237
                                                No barcode
238
                                            [%- END -%]
239
                                        </option>
240
                                        <option value="1">Next available</option>
241
                                    </select>
242
                                    [%- IF ( hold.itemnumber ) -%]
243
                                        <input type="hidden" name="itemnumber" value="[% hold.itemnumber | html %]" />
244
                                    [%- END -%]
245
                                    [%- IF hold.itemtype -%]
246
                                        <span style="display:none">Next available [% ItemTypes.GetDescription( hold.itemtype ) | html %] item</span>
247
                                    [%- ELSE -%]
248
                                        <span style="display:none">Next available</span>
249
                                    [%- END -%]
250
                                [%- END -%]
251
                            </em>
252
                        [%- ELSE -%]
253
                            [%- IF hold.itemtype -%]
254
                                <em>Next available [% ItemTypes.GetDescription( hold.itemtype ) | html %] item</em>
255
                            [%- ELSIF hold.object.item_group -%]
256
                                <em>Next available item from group <strong>[% hold.object.item_group.description | html %]</strong></em>
257
                            [%- ELSE -%]
258
                                <em>Next available</em>
259
                            [%- END -%]
260
261
                            <input type="hidden" name="itemnumber" value="" />
262
                        [%- END -%]
263
                    [%- END -%]
264
                    [%- IF hold.non_priority -%]
265
                        <br /><i>Non priority hold</i>
266
                    [%- END -%]
267
                </td>
268
                [%- IF ( CAN_user_reserveforothers_modify_holds_priority ) -%]
269
                    [%- UNLESS hold.found -%]
270
                        <td>
271
                            [% IF ( hold.lowestPriority ) %]
272
                                <a
273
                                    class="hold-arrow"
274
                                    title="Remove lowest priority"
275
                                    data-op="cud-setLowestPriority"
276
                                    data-borrowernumber="[% hold.borrowernumber | html %]"
277
                                    data-biblionumber="[% hold.biblionumber | html %]"
278
                                    data-reserve_id="[% hold.reserve_id | html %]"
279
                                    data-date="[% hold.date | html %]"
280
                                >
281
                                    <i class="fa fa-lg fa-rotate-90 icon-unset-lowest" aria-hidden="true"></i>
282
                                </a>
283
                            [% ELSE %]
284
                                <a
285
                                    class="hold-arrow"
286
                                    title="Set lowest priority"
287
                                    data-op="cud-setLowestPriority"
288
                                    data-borrowernumber="[% hold.borrowernumber | html %]"
289
                                    data-biblionumber="[% hold.biblionumber | html %]"
290
                                    data-reserve_id="[% hold.reserve_id | html %]"
291
                                    data-date="[% hold.date | html %]"
292
                                >
293
                                    <i class="fa fa-lg fa-rotate-90 icon-set-lowest" aria-hidden="true"></i>
294
                                </a>
295
                            [% END %]
296
                        </td>
297
                    [%- ELSE -%]
298
                        <td></td>
299
                    [%- END -%]
300
                [%- END -%]
301
                <td>
302
                    <a class="cancel-hold" title="Cancel hold" data-borrowernumber="[% hold.borrowernumber | html %]" data-biblionumber="[% hold.biblionumber | html %]" data-id="[% hold.reserve_id | html %]" href="#">
303
                        <i class="fa fa-trash" aria-label="Cancel hold"></i>
304
                    </a>
305
                </td>
306
                <td>
307
                    [% IF Koha.Preference('SuspendHoldsIntranet') %]
308
                        [% UNLESS ( hold.found ) %]
309
                            [% IF ( hold.suspend ) %]
310
                                <button class="btn btn-default btn-xs unsuspend-hold" data-reserve-id="[% hold.reserve_id | html %]" data-biblionumber="[% hold.biblionumber | html %]">
311
                                    <i class="fa fa-play" aria-hidden="true"></i> Unsuspend
312
                                </button>
313
                            [% ELSE %]
314
                                <button class="btn btn-default btn-xs suspend-hold" data-reserve-id="[% hold.reserve_id | html %]" data-biblionumber="[% hold.biblionumber | html %]">
315
                                    <i class="fa fa-pause" aria-hidden="true"></i> Suspend
316
                                </button>
317
                            [% END %]
318
319
                            [% IF Koha.Preference('AutoResumeSuspendedHolds') %]
320
                                <label for="suspend_until_[% hold.reserve_id | html %]">[% IF ( hold.suspend ) %]on[% ELSE %]until[% END %]</label>
321
                                <input
322
                                    type="text"
323
                                    name="suspend_until_[% hold.reserve_id | html %]"
324
                                    id="suspend_until_[% hold.reserve_id | html %]"
325
                                    size="10"
326
                                    value="[% hold.suspend_until | html %]"
327
                                    class="flatpickr"
328
                                    data-flatpickr-futuredate="true"
329
                                />
330
                            [%- ELSE -%]
331
                                <input type="hidden" name="suspend_until_[% hold.reserve_id | html %]" id="suspend_until_[% hold.reserve_id | html %]" value="" />
332
                            [%- END -%]
333
                        [%- END -%]
334
                    [%- END # IF SuspendHoldsIntranet -%]
335
                    [%- IF ( hold.found ) -%]
336
                        <a
337
                            class="btn btn-default  submit-form-link"
338
                            href="#"
339
                            id="revert_hold_[% hold.reserve_id | html %]"
340
                            data-op="cud-move"
341
                            data-where="down"
342
                            data-first_priority="[% first_priority | html %]"
343
                            data-last_priority="[% last_priority | html %]"
344
                            data-prev_priority="0"
345
                            data-next_priority="1"
346
                            data-borrowernumber="[% hold.borrowernumber | html %]"
347
                            data-biblionumber="[% hold.biblionumber | html %]"
348
                            data-itemnumber="[% hold.itemnumber | html %]"
349
                            data-reserve_id="[% hold.reserve_id | html %]"
350
                            data-date="[% hold.date | html %]"
351
                            data-action="request.pl"
352
                            data-method="post"
353
                            >[% IF hold.intransit %]Revert transit status[% ELSE %]Revert waiting status[% END %]</a
354
                        >
355
                    [%- END -%]
356
                </td>
357
                [% IF ( hold.intransit || hold.atdestination ) %]
358
                    <td><input class="printholdslip" type="button" name="printholdslip" value="Print slip" data-reserve_id="[% hold.reserve_id | html %]" /></td>
359
                [% ELSE %]
360
                    <td></td>
361
                [% END %]
362
            </tr>
363
        [% END %]
364
    </tbody>
365
</table>
26
</table>
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt (-249 / +91 lines)
Lines 1198-1204 Link Here
1198
                [% END %]
1198
                [% END %]
1199
            [% END %]
1199
            [% END %]
1200
        [% END %]
1200
        [% END %]
1201
        [% IF ( reserveloop ) %]
1201
        [% IF ( total_holds ) %]
1202
            <form id="existing_holds" name="T[% time | html %]" action="modrequest.pl" method="post" style="display:block">
1202
            <form id="existing_holds" name="T[% time | html %]" action="modrequest.pl" method="post" style="display:block">
1203
                [% INCLUDE 'csrf-token.inc' %]
1203
                [% INCLUDE 'csrf-token.inc' %]
1204
                [% IF ( multi_hold ) %]
1204
                [% IF ( multi_hold ) %]
Lines 1216-1225 Link Here
1216
1216
1217
                <h2>Existing holds</h2>
1217
                <h2>Existing holds</h2>
1218
                <div id="toolbar" class="btn-toolbar sticky">
1218
                <div id="toolbar" class="btn-toolbar sticky">
1219
                    <div class="btn-group">
1220
                        <input type="hidden" name="op" value="cud-modifyall" />
1221
                        <input type="submit" class="btn btn-primary" name="submit" value="Update hold(s)" />
1222
                    </div>
1223
                    <div class="btn-group">
1219
                    <div class="btn-group">
1224
                        <button class="btn cancel_selected_holds" data-bulk="true"></button>
1220
                        <button class="btn cancel_selected_holds" data-bulk="true"></button>
1225
                    </div>
1221
                    </div>
Lines 1238-1374 Link Here
1238
                </div>
1234
                </div>
1239
                <div class="page-section">
1235
                <div class="page-section">
1240
                    [% FOREACH biblioloo IN biblioloop %]
1236
                    [% FOREACH biblioloo IN biblioloop %]
1241
                        [% IF ( biblioloo.reserveloop ) %]
1237
                        [% IF ( biblioloo.total_holds ) %]
1242
                            <div class="hold_title" id="hold_title_[% biblioloo.biblionumber | html %]">
1238
                            <div class="hold_title" id="hold_title_[% biblioloo.biblionumber | html %]">
1243
                                [% IF ( multi_hold ) %]
1239
                                [% IF ( multi_hold ) %]
1244
                                    <h3>
1240
                                    <h3>
1245
                                        <a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% biblioloo.biblionumber | uri %]"> [% biblioloo.title | html %] </a>
1241
                                        <a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% biblioloo.biblionumber | uri %]"> [% biblioloo.title | html %] </a>
1246
                                        <span class="badge bg-info-subtle"><span>[% biblioloo.reserveloop.size | html %] [% tn('Hold', 'Holds', biblioloo.reserveloop.size) | $raw %]</span></span>
1242
                                        <span class="badge bg-info-subtle"><span>[% biblioloo.total_holds | html %] [% tn('Hold', 'Holds', biblioloo.total_holds) | $raw %]</span></span>
1247
                                    </h3>
1243
                                    </h3>
1248
                                [% END %]
1244
                                [% END %]
1249
1245
1250
                                [% IF Koha.Preference('HoldsSplitQueue') == 'branch' %]
1246
                                [% IF Koha.Preference('HoldsSplitQueue') == 'branch' %]
1251
1247
                                    [% IF biblioloo.hold_branches.empty %]
1252
                                    [% SET branchcodes = [] %]
1248
                                        <div class="holds_by_library">
1253
1249
                                            <h4>Any library</h4>
1254
                                    [% FOREACH h IN biblioloo.reserveloop %]
1250
                                            [% INCLUDE holds_table.inc biblio_id=biblioloo.biblionumber total_holds=biblioloo.total_holds split_data="any" %]
1255
                                        [% branchcodes.push( h.branchcode ) %]
1251
                                        </div>
1256
                                    [% END %]
1257
                                    [% branchcodes = branchcodes.unique %]
1258
                                    [% IF ( branchcodes.empty ) %]
1259
                                        <div class="alert alert-info"> There are no holds on this title. </div>
1260
                                    [% ELSE %]
1252
                                    [% ELSE %]
1261
1253
                                        [% FOREACH b IN biblioloo.hold_branches %]
1262
                                        [% FOREACH b IN branchcodes.sort %]
1263
                                            [% SET holds_by_branch = [] %]
1264
                                            [% FOREACH h IN biblioloo.reserveloop %]
1265
                                                [% IF h.branchcode == b %]
1266
                                                    [% holds_by_branch.push( h ) %]
1267
                                                [% END %]
1268
                                            [% END %]
1269
                                            <div class="holds_by_library">
1254
                                            <div class="holds_by_library">
1270
                                                <h4>[% Branches.GetName( b ) | html %]</h4>
1255
                                                <h4>[% Branches.GetName( b ) | html %]</h4>
1271
1256
1272
                                                [% INCLUDE holds_table.inc holds=holds_by_branch %]
1257
                                                [% INCLUDE holds_table.inc biblio_id=biblioloo.biblionumber total_holds=biblioloo.total_holds split_data=b %]
1273
                                            </div>
1258
                                            </div>
1274
                                        [% END # /FOREACh b %]
1259
                                        [% END %]
1275
                                    [% END # /IF ( branchcodes.empty ) %]
1260
                                    [% END # /IF hold_branches.empty %]
1276
                                [% ELSIF Koha.Preference('HoldsSplitQueue') == 'itemtype' %]
1261
                                [% ELSIF Koha.Preference('HoldsSplitQueue') == 'itemtype' %]
1277
1262
1278
                                    [% SET itemtypes = [] %]
1263
                                    [% IF biblioloo.hold_itemtypes.empty %]
1279
1264
                                        <div class="holds_by_itemtype">
1280
                                    [% FOREACH h IN biblioloo.reserveloop %]
1265
                                            <h4>Any item type</h4>
1281
                                        [% SET hold_itemtype = h.object.item.effective_itemtype || h.itemtype %]
1266
                                            [% INCLUDE holds_table.inc biblio_id=biblioloo.biblionumber total_holds=biblioloo.total_holds split_data="any" %]
1282
                                        [% itemtypes.push( hold_itemtype ) %]
1267
                                        </div>
1283
                                    [% END %]
1284
                                    [% itemtypes = itemtypes.unique %]
1285
                                    [% IF ( itemtypes.empty ) %]
1286
                                        <div class="alert alert-info"> There are no holds on this title. </div>
1287
                                    [% ELSE %]
1268
                                    [% ELSE %]
1288
1269
                                        [% FOREACH i IN biblioloo.hold_itemtypes %]
1289
                                        [% FOREACH i IN itemtypes.sort %]
1290
                                            [% SET holds_by_itemtype = [] %]
1291
                                            [% FOREACH h IN biblioloo.reserveloop %]
1292
                                                [% SET hold_itemtype = h.object.item.effective_itemtype || h.itemtype %]
1293
                                                [% IF hold_itemtype == i %]
1294
                                                    [% holds_by_itemtype.push( h ) %]
1295
                                                [% END %]
1296
                                            [% END %]
1297
1298
                                            <div class="holds_by_itemtype">
1270
                                            <div class="holds_by_itemtype">
1299
                                                [% IF i %]
1271
                                                [% IF i && i != 'any' %]
1300
                                                    <h4>[% ItemTypes.GetDescription( i ) | html %]</h4>
1272
                                                    <h4>[% ItemTypes.GetDescription( i ) | html %]</h4>
1301
                                                [% ELSE %]
1273
                                                [% ELSE %]
1302
                                                    <h4>Any item type</h4>
1274
                                                    <h4>Any item type</h4>
1303
                                                [% END %]
1275
                                                [% END %]
1304
                                                [% INCLUDE holds_table.inc holds=holds_by_itemtype %]
1276
                                                [% INCLUDE holds_table.inc biblio_id=biblioloo.biblionumber total_holds=biblioloo.total_holds split_data=i %]
1305
                                            </div>
1277
                                            </div>
1306
                                        [% END # /FOREACH i %]
1278
                                        [% END %]
1307
                                    [% END # /IF ( itemtypes.empty ) %]
1279
                                    [% END # /IF hold_split.empty %]
1308
                                [% ELSIF Koha.Preference('HoldsSplitQueue') == 'branch_itemtype' %]
1280
                                [% ELSIF Koha.Preference('HoldsSplitQueue') == 'branch_itemtype' %]
1309
                                    [% SET branchcodes = [] %]
1310
1281
1311
                                    [% FOREACH h IN biblioloo.reserveloop %]
1282
                                    [% FOREACH b IN biblioloo.hold_branches %]
1312
                                        [% branchcodes.push( h.branchcode ) %]
1283
                                        <div class="holds_by_library">
1313
                                    [% END %]
1284
                                            <h4>[% Branches.GetName( b ) | html %]</h4>
1314
                                    [% branchcodes = branchcodes.unique %]
1285
                                            [% FOREACH i IN biblioloo.hold_itemtypes %]
1315
                                    [% IF ( branchcodes.empty ) %]
1286
                                                <div class="holds_by_itemtype">
1316
                                        <div class="alert alert-info"> There are no holds on this title. </div>
1287
                                                    [% IF i && i != 'any' %]
1317
                                    [% ELSE %]
1288
                                                        <h4>[% ItemTypes.GetDescription( i ) | html %]</h4>
1318
1289
                                                    [% ELSE %]
1319
                                        [% FOREACH b IN branchcodes.sort %]
1290
                                                        <h4>Any item type</h4>
1320
                                            <div class="holds_by_library">
1321
                                                <h4 class="library_holds">[% Branches.GetName( b ) | html %]</h4>
1322
                                                [% SET holds_by_branch = [] %]
1323
                                                [% FOREACH h IN biblioloo.reserveloop %]
1324
                                                    [% IF h.branchcode == b %]
1325
                                                        [% holds_by_branch.push( h ) %]
1326
                                                    [% END %]
1291
                                                    [% END %]
1327
                                                [% END %]
1292
                                                    [% SET split_data = b _ "_" _ i %]
1328
1293
                                                    [% INCLUDE holds_table.inc biblio_id=biblioloo.biblionumber total_holds=biblioloo.total_holds split_data=split_data %]
1329
                                                [% SET itemtypes = [] %]
1294
                                                </div>
1330
                                                [% FOREACH h IN holds_by_branch %]
1295
                                            [% END %]
1331
                                                    [% SET hold_itemtype = h.object.item.effective_itemtype || h.itemtype %]
1296
                                        </div>
1332
                                                    [% itemtypes.push( hold_itemtype ) %]
1333
                                                [% END %]
1334
                                                [% itemtypes = itemtypes.unique %]
1335
1336
                                                [% FOREACH i IN itemtypes.sort %]
1337
                                                    <div class="holds_by_itemtype">
1338
                                                        <h5 class="itemtype_holds">
1339
                                                            [% IF i %]
1340
                                                                [% ItemTypes.GetDescription( i ) | html %]
1341
                                                            [% ELSE %]
1342
                                                                <span>Any item type</span>
1343
                                                            [% END %]
1344
                                                        </h5>
1345
1346
                                                        [% SET holds_by_itemtype = [] %]
1347
                                                        [% FOREACH h IN holds_by_branch %]
1348
                                                            [% SET hold_itemtype = h.object.item.effective_itemtype || h.itemtype %]
1349
                                                            [% IF hold_itemtype == i %]
1350
                                                                [% holds_by_itemtype.push( h ) %]
1351
                                                            [% END %]
1352
                                                        [% END %]
1353
                                                        [% INCLUDE holds_table.inc holds=holds_by_itemtype %]
1354
                                                    </div>
1355
                                                    <!-- /.holds_by_itemtype -->
1356
                                                [% END %]
1357
                                            </div>
1358
                                            <!-- /.holds_by_library -->
1359
                                        [% END # /FOREACH b %]
1360
                                    [% END # /IF ( branchcodes.empty ) %]
1361
                                [% ELSE %]
1362
1363
                                    [% IF ( biblioloo.reserveloop.size ) %]
1364
                                        [% INCLUDE holds_table.inc holds=biblioloo.reserveloop %]
1365
                                    [% ELSE %]
1366
                                        <div class="alert alert-info"> There are no holds on this title. </div>
1367
                                    [% END %]
1297
                                    [% END %]
1298
                                [% ELSE %]
1299
                                    [% INCLUDE holds_table.inc biblio_id=biblioloo.biblionumber total_holds=biblioloo.total_holds split_data="any" %]
1368
                                [% END # /IF HoldsSplitQueue %]
1300
                                [% END # /IF HoldsSplitQueue %]
1369
                            </div>
1301
                            </div>
1370
                            <!-- /hold_title -->
1302
                            <!-- /hold_title -->
1371
                        [% END # /IF biblioloo.reserveloop %]
1303
                        [% ELSE %]
1304
                            <div class="note"> There are no holds on this title. </div>
1305
                        [% END # /IF ( biblioloo.total_holds ) %]
1372
                    [% END # FOREACH biblioloo %]
1306
                    [% END # FOREACH biblioloo %]
1373
                </div>
1307
                </div>
1374
            </form>
1308
            </form>
Lines 1424-1429 Link Here
1424
    [% INCLUDE 'datatables.inc' %]
1358
    [% INCLUDE 'datatables.inc' %]
1425
    [% INCLUDE 'calendar.inc' %]
1359
    [% INCLUDE 'calendar.inc' %]
1426
    [% INCLUDE 'select2.inc' %]
1360
    [% INCLUDE 'select2.inc' %]
1361
    <script>
1362
        hold_table_settings = [% TablesSettings.GetTableSettings( 'circ', 'holds', 'patron_holds_table', 'json' ) | $raw %];
1363
    </script>
1427
    [% Asset.js("js/holds.js") | $raw %]
1364
    [% Asset.js("js/holds.js") | $raw %]
1428
    [% Asset.js("js/form-submit.js") | $raw %]
1365
    [% Asset.js("js/form-submit.js") | $raw %]
1429
1366
Lines 1432-1448 Link Here
1432
        [% SET url_biblio_params = url_biblio_params _ "&amp;multi_hold=1" %]
1369
        [% SET url_biblio_params = url_biblio_params _ "&amp;multi_hold=1" %]
1433
    [% END %]
1370
    [% END %]
1434
    <script>
1371
    <script>
1435
        $(document).ready(function () {
1436
            hold_table_settings = [% TablesSettings.GetTableSettings( 'circ', 'holds', 'patron_holds_table', 'json' ) | $raw %];
1437
            $("#patron_holds_table").kohaTable(
1438
                {
1439
                    paging: false,
1440
                    bKohaColumnsUseNames: true,
1441
                },
1442
                hold_table_settings
1443
            );
1444
        });
1445
        var biblionumbers = [[% biblionumbers.join(', ') | $raw %]];
1372
        var biblionumbers = [[% biblionumbers.join(', ') | $raw %]];
1373
        var hold_branches = {[% FOREACH biblio_info IN biblioloop %] [% biblio_info.biblionumber | html %]: ["[% biblio_info.hold_branches.join('", "') | $raw %]"], [% END %]};
1374
        var hold_itemtypes = {[% FOREACH biblio_info IN biblioloop %] [% biblio_info.biblionumber | html %]: ["[% biblio_info.hold_itemtypes.join('", "') | $raw %]"], [% END %]};
1375
        var HoldsSplitQueue = "[% Koha.Preference('HoldsSplitQueue') | html %]";
1376
        var HoldsSplitQueueNumbering = "[% Koha.Preference('HoldsSplitQueueNumbering') | html %]";
1377
        var SuspendHoldsIntranet = [% ( Koha.Preference('SuspendHoldsIntranet') ) ? 1 : 0 | html %];
1378
        var AutoResumeSuspendedHolds = [% ( Koha.Preference('AutoResumeSuspendedHolds') ) ? 1 : 0 | html %];
1379
        var AllowHoldDateInFuture = [% ( Koha.Preference('AllowHoldDateInFuture') ) ? 1 : 0 | html %];
1380
        var HidePatronName = [% ( Koha.Preference('HidePatronName') ) ? 1 : 0 | html %];
1381
        var CAN_user_reserveforothers_modify_holds_priority = [%CAN_user_reserveforothers_modify_holds_priority ? 1 : 0 | html %];
1446
        var borrowernumber = "[% patron.borrowernumber | $raw %]";
1382
        var borrowernumber = "[% patron.borrowernumber | $raw %]";
1447
        var patron_homebranch = "[% To.json( Branches.GetName( patron.branchcode ) ) | $raw %]";
1383
        var patron_homebranch = "[% To.json( Branches.GetName( patron.branchcode ) ) | $raw %]";
1448
        var override_items = {[% FOREACH biblio_info IN biblioloop %][% FOREACH itemloo IN biblio_info.itemloop %][% IF ( itemloo.override ) %]
1384
        var override_items = {[% FOREACH biblio_info IN biblioloop %][% FOREACH itemloo IN biblio_info.itemloop %][% IF ( itemloo.override ) %]
Lines 1472-1477 Link Here
1472
        $.fn.select2.defaults.set("dropdownAutoWidth", true );
1408
        $.fn.select2.defaults.set("dropdownAutoWidth", true );
1473
1409
1474
        $(document).ready(function() {
1410
        $(document).ready(function() {
1411
            biblionumbers.forEach(function(biblionumber) {
1412
                let branches = hold_branches[biblionumber];
1413
                let itemtypes = hold_itemtypes[biblionumber];
1414
                switch (HoldsSplitQueue) {
1415
                    case 'branch':
1416
                        branches.forEach(function(branch) {
1417
                            load_patron_holds_table(biblionumber, {name: HoldsSplitQueue, value: branch});
1418
                        });
1419
                        break;
1420
                    case 'itemtype':
1421
                        itemtypes.forEach(function(itemtype) {
1422
                            load_patron_holds_table(biblionumber, {name: HoldsSplitQueue, value: itemtype});
1423
                        });
1424
                        break;
1425
                    case 'branch_itemtype':
1426
                        branches.forEach(function(branch) {
1427
                            itemtypes.forEach(function(itemtype) {
1428
                                load_patron_holds_table(biblionumber, {name: HoldsSplitQueue, value: branch + '_' + itemtype});
1429
                            });
1430
                        });
1431
                        break;
1432
                    default:
1433
                        load_patron_holds_table(biblionumber, {name: 'any', value: 'any'});
1434
                }
1435
            });
1475
            $('#cancellation-reason-fieldset').hide();
1436
            $('#cancellation-reason-fieldset').hide();
1476
            $('.rank-request').on('change', function() {
1437
            $('.rank-request').on('change', function() {
1477
                if ( $(".rank-request option:selected[value='del']").length ) {
1438
                if ( $(".rank-request option:selected[value='del']").length ) {
Lines 1787-1805 Link Here
1787
            });
1748
            });
1788
1749
1789
            // Confirm cancellation of hold
1750
            // Confirm cancellation of hold
1790
            let cancel_link;
1751
            // let cancel_link;
1791
            $(".cancel-hold").on("click",function(e) {
1752
            // $(".cancel-hold").on("click",function(e) {
1792
                e.preventDefault;
1753
            //     e.preventDefault;
1793
                cancel_link = $(this);
1754
            //     cancel_link = $(this);
1794
                $("#cancel_modal_form #inputs").empty();
1755
            //     $("#cancel_modal_form #inputs").empty();
1795
                    let reserve_id = cancel_link.data('id');
1756
            //         let reserve_id = cancel_link.data('id');
1796
                    let biblionumber = cancel_link.data('biblionumber');
1757
            //         let biblionumber = cancel_link.data('biblionumber');
1797
                    $("#cancel_modal_form #inputs").append('<input type="hidden" name="reserve_id" value="' + reserve_id + '">');
1758
            //         $("#cancel_modal_form #inputs").append('<input type="hidden" name="reserve_id" value="' + reserve_id + '">');
1798
                    $("#cancel_modal_form #inputs").append('<input type="hidden" name="biblionumber" value="' + biblionumber + '">');
1759
            //         $("#cancel_modal_form #inputs").append('<input type="hidden" name="biblionumber" value="' + biblionumber + '">');
1799
                    $("#cancel_modal_form #inputs").append('<input type="hidden" name="op" value="cud-cancel">');
1760
            //         $("#cancel_modal_form #inputs").append('<input type="hidden" name="op" value="cud-cancel">');
1800
                $('#cancelModal').modal('show');
1761
            //     $('#cancelModal').modal('show');
1801
                return false;
1762
            //     return false;
1802
            });
1763
            // });
1803
1764
1804
            [% UNLESS ( patron || patron.borrowernumber || borrowers || noitems || nobiblio ) %]
1765
            [% UNLESS ( patron || patron.borrowernumber || borrowers || noitems || nobiblio ) %]
1805
                [% IF ( PatronAutoComplete ) %]
1766
                [% IF ( PatronAutoComplete ) %]
Lines 1821-1938 Link Here
1821
                localStorage.selectedHolds = [];
1782
                localStorage.selectedHolds = [];
1822
            }
1783
            }
1823
1784
1824
            $('.holds_table .select_hold').each(function() {
1825
                if(localStorage.selectedHolds.includes($(this).data('id'))) {
1826
                    $(this).prop('checked', true);
1827
                }
1828
            });
1829
1830
            $('.holds_table .select_hold_all').each(function() {
1831
                var table = $(this).parents('.holds_table');
1832
                var count = $('.select_hold:not(:checked)', table).length;
1833
                $('.select_hold_all', table).prop('checked', !count);
1834
            });
1835
1836
            $('.cancel_selected_holds').html(MSG_CANCEL_SELECTED.format($('.holds_table .select_hold:checked').length));
1837
1838
            $('.holds_table .select_hold_all').click(function() {
1839
                var table = $(this).parents('.holds_table');
1840
                var count = $('.select_hold:checked', table).length;
1841
                $('.select_hold', table).prop('checked', !count);
1842
                $(this).prop('checked', !count);
1843
                $('.cancel_selected_holds').html(MSG_CANCEL_SELECTED.format($('.holds_table .select_hold:checked').length));
1844
                $('#cancel_hold_alert').html( MSG_CANCEL_ALERT.format($('.holds_table .select_hold:checked').length));
1845
                $('#cancel_hold_alert').show();
1846
                localStorage.selectedHolds = $('.holds_table .select_hold:checked').toArray().map(el => $(el).data('id'));
1847
            });
1848
1849
            $('.holds_table .select_hold').click(function() {
1850
                var table = $(this).parents('.holds_table');
1851
                var count = $('.select_hold:not(:checked)', table).length;
1852
                $('.select_hold_all', table).prop('checked', !count);
1853
                $('.cancel_selected_holds').html(MSG_CANCEL_SELECTED.format($('.holds_table .select_hold:checked').length));
1854
                $('#cancel_hold_alert').html( MSG_CANCEL_ALERT.format($('.holds_table .select_hold:checked').length));
1855
                $('#cancel_hold_alert').show();
1856
                localStorage.selectedHolds = $('.holds_table .select_hold:checked').toArray().map(el => $(el).data('id'));
1857
            });
1858
1859
            $('.cancel_selected_holds').click(function(e) {
1860
                e.preventDefault();
1861
                if($('.holds_table .select_hold:checked').length) {
1862
                    cancel_link = $(this);
1863
                    $("#cancel_modal_form #inputs").empty();
1864
                    biblionumbers.forEach( function(biblionumber){
1865
                        $("#cancel_modal_form #inputs").append('<input type="hidden" name="biblionumber" value="'+biblionumber+'">');
1866
                    });
1867
                    $("#cancel_modal_form #inputs").append('<input type="hidden" name="op" value="cud-cancel_bulk">');
1868
                    let hold_ids= $('.holds_table .select_hold:checked').toArray().map(el => $(el).data('id')).join(',');
1869
                    $("#cancel_modal_form #inputs").append('<input type="hidden" name="ids" value="' + hold_ids + '">');
1870
                    delete localStorage.selectedHolds;
1871
                    $('#cancelModal').modal('show');
1872
                }
1873
                return false;
1874
            });
1875
1876
            $(".hold-arrow").click(function(e) {
1877
                e.preventDefault();
1878
                let arrowForm = $("#hold-actions-form").attr({
1879
                    action: 'request.pl',
1880
                    method: 'post'
1881
                });
1882
                let arrow_op = $("<input />").attr({
1883
                    name: 'op',
1884
                    type: 'hidden',
1885
                    value: $(this).data('op')
1886
                });
1887
                let arrow_where = $("<input />").attr({
1888
                    name: 'where',
1889
                    type: 'hidden',
1890
                    value: $(this).data('where')
1891
                });
1892
                let arrow_fp = $("<input />").attr({
1893
                    name: 'first_priority',
1894
                    type: 'hidden',
1895
                    value: $(this).data('first_priority')
1896
                });
1897
                let arrow_lp = $("<input />").attr({
1898
                    name: 'last_priority',
1899
                    type: 'hidden',
1900
                    value: $(this).data('last_priority')
1901
                });
1902
                let arrow_pp = $("<input />").attr({
1903
                    name: 'prev_priority',
1904
                    type: 'hidden',
1905
                    value: $(this).data('prev_priority')
1906
                });
1907
                let arrow_np = $("<input />").attr({
1908
                    name: 'next_priority',
1909
                    type: 'hidden',
1910
                    value: $(this).data('next_priority')
1911
                });
1912
                let arrow_bn = $("<input />").attr({
1913
                    name: 'borrowernumber',
1914
                    type: 'hidden',
1915
                    value: $(this).data('borrowernumber')
1916
                });
1917
                let arrow_bb = $("<input />").attr({
1918
                    name: 'biblionumber',
1919
                    type: 'hidden',
1920
                    value: $(this).data('biblionumber')
1921
                });
1922
                let arrow_ri = $("<input />").attr({
1923
                    name: 'reserve_id',
1924
                    type: 'hidden',
1925
                    value: $(this).data('reserve_id')
1926
                });
1927
                let arrow_date = $("<input />").attr({
1928
                    name: 'date',
1929
                    type: 'hidden',
1930
                    value: $(this).data('date')
1931
                });
1932
                arrowForm.append(arrow_op,arrow_where,arrow_fp,arrow_lp,arrow_pp,arrow_np,arrow_bn,arrow_bb,arrow_ri,arrow_date);
1933
                $("#hold-actions-form").submit();
1934
                return true;
1935
            })
1936
        });
1785
        });
1937
    </script>
1786
    </script>
1938
    <script>
1787
    <script>
Lines 1948-1960 Link Here
1948
            });
1797
            });
1949
        </script>
1798
        </script>
1950
    [% END %]
1799
    [% END %]
1951
    <script>
1952
        $(".printholdslip").click(function () {
1953
            var reserve_id = $(this).attr("data-reserve_id");
1954
            window.open("/cgi-bin/koha/circ/hold-transfer-slip.pl?reserve_id=" + reserve_id);
1955
            return false;
1956
        });
1957
    </script>
1958
[% END %]
1800
[% END %]
1959
1801
1960
[% INCLUDE 'intranet-bottom.inc' %]
1802
[% INCLUDE 'intranet-bottom.inc' %]
(-)a/koha-tmpl/intranet-tmpl/prog/js/holds.js (+851 lines)
Lines 698-700 $(document).ready(function () { Link Here
698
        return toggle_suspend(this, inputs);
698
        return toggle_suspend(this, inputs);
699
    });
699
    });
700
});
700
});
701
702
async function load_patron_holds_table(biblio_id, split_data) {
703
    const { name: split_name, value: split_value } = split_data;
704
    const table_id = `#patron_holds_table_${biblio_id}_${split_value}`;
705
    hold_table_settings.table = `patron_holds_table_${biblio_id}_${split_data.value}`;
706
    let url = `/api/v1/holds/?q={"me.biblio_id":${biblio_id}`;
707
708
    if (split_name === "branch" && split_value !== "any") {
709
        url += `, "me.pickup_library_id":"${split_value}"`;
710
    } else if (split_name === "itemtype" && split_value !== "any") {
711
        url += `, "me.itemtype":"${split_value}"`;
712
    } else if (split_name === "branch_itemtype") {
713
        const [branch, itemtype] = split_value.split("_");
714
        url +=
715
            itemtype === "any"
716
                ? `, "me.pickup_library_id":"${branch}"`
717
                : `, "me.pickup_library_id":"${branch}", "me.itemtype":"${itemtype}"`;
718
    }
719
720
    url += "}";
721
    const totalHolds = $(table_id).data("total-holds");
722
    const totalHoldsSelect = parseInt(totalHolds) + 1;
723
    let pageStart;
724
    var holdsQueueTable = $(table_id).kohaTable(
725
        {
726
            ajax: {
727
                url: url,
728
                data: function (params) {
729
                    pageStart = params.start;
730
                    var query = {
731
                        _per_page: params.length,
732
                        _page: params.start / params.length + 1,
733
                        _order_by: "priority",
734
                        _match: "exact",
735
                    };
736
                    return query;
737
                },
738
            },
739
            embed: ["patron", "item", "item_group"],
740
            columnDefs: [
741
                {
742
                    targets: [2, 3],
743
                    className: "dt-body-nowrap",
744
                },
745
                {
746
                    targets: [3, 9],
747
                    visible: CAN_user_reserveforothers_modify_holds_priority
748
                        ? true
749
                        : false,
750
                },
751
            ],
752
            columns: [
753
                {
754
                    data: "hold_id",
755
                    orderable: false,
756
                    searchable: false,
757
                    render: function (data, type, row, meta) {
758
                        return (
759
                            '<input type="checkbox" class="select_hold" data-id="' +
760
                            data +
761
                            '"/>'
762
                        );
763
                    },
764
                },
765
                {
766
                    data: "priority",
767
                    orderable: false,
768
                    searchable: false,
769
                    render: function (data, type, row, meta) {
770
                        let select =
771
                            '<select name="rank-request" class="rank-request" data-id="' +
772
                            row.hold_id;
773
                        if (
774
                            CAN_user_reserveforothers_modify_holds_priority &&
775
                            split_name == "any"
776
                        ) {
777
                            for (var i = 0; i < totalHoldsSelect; i++) {
778
                                let selected;
779
                                let value;
780
                                let desc;
781
                                if (data == i && row.status == "T") {
782
                                    select += '" disabled="disabled">';
783
                                    selected = " selected='selected' ";
784
                                    value = "T";
785
                                    desc = "In transit";
786
                                } else if (data == i && row.status == "P") {
787
                                    select += '" disabled="disabled">';
788
                                    selected = " selected='selected' ";
789
                                    value = "P";
790
                                    desc = "In processing";
791
                                } else if (data == i && row.status == "W") {
792
                                    select += '" disabled="disabled">';
793
                                    selected = " selected='selected' ";
794
                                    value = "W";
795
                                    desc = "Waiting";
796
                                } else if (data == i && !row.status) {
797
                                    select += '">';
798
                                    selected = " selected='selected' ";
799
                                    value = data;
800
                                    desc = data;
801
                                } else {
802
                                    if (i != 0) {
803
                                        select += '">';
804
                                        value = i;
805
                                        desc = i;
806
                                    } else {
807
                                        select += '">';
808
                                    }
809
                                }
810
                                if (value) {
811
                                    select +=
812
                                        '<option value="' +
813
                                        value +
814
                                        '"' +
815
                                        selected +
816
                                        ">" +
817
                                        desc +
818
                                        "</option>";
819
                                }
820
                            }
821
                        } else {
822
                            if (row.status == "T") {
823
                                select +=
824
                                    '" disabled="disabled"><option value="T" selected="selected">In transit</option></select>';
825
                            } else if (row.status == "P") {
826
                                select +=
827
                                    '" disabled="disabled"><option value="P" selected="selected">In processing</option></select>';
828
                            } else if (row.status == "W") {
829
                                select +=
830
                                    '" disabled="disabled"><option value="W" selected="selected">Waiting</option></select>';
831
                            } else {
832
                                if (
833
                                    HoldsSplitQueue !== "nothing" &&
834
                                    HoldsSplitQueueNumbering === "virtual"
835
                                ) {
836
                                    let virtualPriority =
837
                                        pageStart + meta.row + 1;
838
                                    select +=
839
                                        '" disabled="disabled"><option value="' +
840
                                        data +
841
                                        '" selected="selected">' +
842
                                        virtualPriority +
843
                                        "</option></select>";
844
                                } else {
845
                                    select +=
846
                                        '" disabled="disabled"><option value="' +
847
                                        data +
848
                                        '" selected="selected">' +
849
                                        data +
850
                                        "</option></select>";
851
                                }
852
                            }
853
                        }
854
                        select += "</select>";
855
                        return select;
856
                    },
857
                },
858
                {
859
                    data: "",
860
                    orderable: false,
861
                    searchable: false,
862
                    render: function (data, type, row, meta) {
863
                        if (row.status) {
864
                            return null;
865
                        }
866
                        let buttons =
867
                            '<a class="hold-arrow move-hold" title="Move hold up" href="#" data-move-hold="up" data-priority="' +
868
                            row.priority +
869
                            '" reserve_id="' +
870
                            row.hold_id +
871
                            '"><i class="fa fa-lg icon-move-hold-up" aria-hidden="true"></i></a>';
872
                        buttons +=
873
                            '<a class="hold-arrow move-hold" title="Move hold to top" href="#" data-move-hold="top" data-priority="' +
874
                            row.priority +
875
                            '" reserve_id="' +
876
                            row.hold_id +
877
                            '"><i class="fa fa-lg icon-move-hold-top" aria-hidden="true"></i></a>';
878
                        buttons +=
879
                            '<a class="hold-arrow move-hold" title="Move hold to bottom" href="#" data-move-hold="bottom" data-priority="' +
880
                            row.priority +
881
                            '" reserve_id="' +
882
                            row.hold_id +
883
                            '"><i class="fa fa-lg icon-move-hold-bottom" aria-hidden="true"></i></a>';
884
                        buttons +=
885
                            '<a class="hold-arrow move-hold" title="Move hold down" href="#" data-move-hold="down" data-priority="' +
886
                            row.priority +
887
                            '" reserve_id="' +
888
                            row.hold_id +
889
                            '"><i class="fa fa-lg icon-move-hold-down" aria-hidden="true"></i></a>';
890
                        return buttons;
891
                    },
892
                },
893
                {
894
                    data: "patron.cardnumber",
895
                    orderable: false,
896
                    searchable: true,
897
                    render: function (data, type, row, meta) {
898
                        if (data == null) {
899
                            let library = libraries.find(
900
                                library => library._id == row.pickup_library_id
901
                            );
902
                            return __("A patron from library %s").format(
903
                                library.name
904
                            );
905
                        } else {
906
                            return (
907
                                '<a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=' +
908
                                row.patron.patron_id +
909
                                '">' +
910
                                data +
911
                                "</a>"
912
                            );
913
                        }
914
                    },
915
                },
916
                {
917
                    data: "notes",
918
                    orderable: false,
919
                    searchable: false,
920
                    render: function (data, type, row, meta) {
921
                        return data;
922
                    },
923
                },
924
                {
925
                    data: "hold_date",
926
                    orderable: false,
927
                    searchable: false,
928
                    render: function (data, type, row, meta) {
929
                        if (AllowHoldDateInFuture) {
930
                            return (
931
                                '<input type="text" class="holddate" value="' +
932
                                $date(data, { dateformat: "rfc3339" }) +
933
                                '" size="10" name="hold_date" data-id="' +
934
                                row.hold_id +
935
                                '" data-current-date="' +
936
                                data +
937
                                '"/>'
938
                            );
939
                        } else {
940
                            return $date(data);
941
                        }
942
                    },
943
                },
944
                {
945
                    data: "expiration_date",
946
                    orderable: false,
947
                    searchable: false,
948
                    render: function (data, type, row, meta) {
949
                        return (
950
                            '<input type="text" class="expirationdate" value="' +
951
                            $date(data, { dateformat: "rfc3339" }) +
952
                            '" size="10" name="expiration_date" data-id="' +
953
                            row.hold_id +
954
                            '" data-current-date="' +
955
                            data +
956
                            '"/>'
957
                        );
958
                    },
959
                },
960
                {
961
                    data: "pickup_library_id",
962
                    orderable: false,
963
                    searchable: false,
964
                    render: function (data, type, row, meta) {
965
                        var branchSelect =
966
                            "<select priority=" +
967
                            row.priority +
968
                            ' class="hold_location_select" data-id="' +
969
                            row.hold_id +
970
                            '" reserve_id="' +
971
                            row.hold_id +
972
                            '" name="pick-location" data-pickup-location-source="hold">';
973
                        var libraryname;
974
                        for (var i = 0; i < libraries.length; i++) {
975
                            var selectedbranch;
976
                            var setbranch;
977
                            if (libraries[i]._id == data) {
978
                                selectedbranch = " selected='selected' ";
979
                                setbranch = __(" (current) ");
980
                                libraryname = libraries[i]._str;
981
                            } else if (libraries[i].pickup_location == false) {
982
                                continue;
983
                            } else {
984
                                selectedbranch = "";
985
                                setbranch = "";
986
                            }
987
                            branchSelect +=
988
                                '<option value="' +
989
                                libraries[i]._id.escapeHtml() +
990
                                '"' +
991
                                selectedbranch +
992
                                ">" +
993
                                libraries[i]._str.escapeHtml() +
994
                                setbranch +
995
                                "</option>";
996
                        }
997
                        branchSelect += "</select>";
998
                        if (row.status == "T") {
999
                            return __(
1000
                                "Item being transferred to <strong>%s</strong>"
1001
                            ).format(libraryname);
1002
                        } else if (row.status == "P") {
1003
                            return __(
1004
                                "Item being processed at <strong>%s</strong>"
1005
                            ).format(libraryname);
1006
                        } else if (row.status == "W") {
1007
                            return __(
1008
                                "Item waiting at <strong>%s</strong> since %s"
1009
                            ).format(libraryname, $date(row.waiting_date));
1010
                        } else {
1011
                            return branchSelect;
1012
                        }
1013
                    },
1014
                },
1015
                {
1016
                    data: "",
1017
                    orderable: false,
1018
                    searchable: false,
1019
                    render: function (data, type, row, meta) {
1020
                        if (row.item_id) {
1021
                            return (
1022
                                '<a href="/cgi-bin/koha/catalogue/moredetail.pl?biblionumber=' +
1023
                                row.biblio_id +
1024
                                "&itemnumber=" +
1025
                                row.item_id +
1026
                                '">' +
1027
                                row.item.external_id +
1028
                                "</a>"
1029
                            );
1030
                        } else if (row.item_group_id) {
1031
                            return __(
1032
                                "Next available item from group <strong>%s</strong>"
1033
                            ).format(row.item_group.description);
1034
                        } else {
1035
                            if (row.non_priority) {
1036
                                return (
1037
                                    "<em>" +
1038
                                    __("Next available") +
1039
                                    "</em><br/><i>" +
1040
                                    __("Non priority hold") +
1041
                                    "</i>"
1042
                                );
1043
                            } else {
1044
                                return "<em>" + __("Next available") + "</em>";
1045
                            }
1046
                        }
1047
                    },
1048
                },
1049
                {
1050
                    data: "",
1051
                    orderable: false,
1052
                    searchable: false,
1053
                    render: function (data, type, row, meta) {
1054
                        if (row.item_id) {
1055
                            return null;
1056
                        } else {
1057
                            if (row.lowest_priority) {
1058
                                return (
1059
                                    '<a class="hold-arrow toggle-lowest-priority" title="Remove lowest priority" href="#" data-op="cud-setLowestPriority" data-borrowernumber="' +
1060
                                    row.patron_id +
1061
                                    '" data-biblionumber="' +
1062
                                    biblio_id +
1063
                                    '" data-reserve_id="' +
1064
                                    row.hold_id +
1065
                                    '" data-date="' +
1066
                                    row.hold_date +
1067
                                    '"><i class="fa fa-lg fa-rotate-90 icon-unset-lowest" aria-hidden="true"></i></a>'
1068
                                );
1069
                            } else {
1070
                                return (
1071
                                    '<a class="hold-arrow toggle-lowest-priority" title="Set lowest priority" href="#" data-op="cud-setLowestPriority" data-borrowernumber="' +
1072
                                    row.patron_id +
1073
                                    '" data-biblionumber="' +
1074
                                    biblio_id +
1075
                                    '" data-reserve_id="' +
1076
                                    row.hold_id +
1077
                                    '" data-date="' +
1078
                                    row.hold_date +
1079
                                    '"><i class="fa fa-lg fa-rotate-90 icon-set-lowest" aria-hidden="true"></i></a>'
1080
                                );
1081
                            }
1082
                        }
1083
                    },
1084
                },
1085
                {
1086
                    data: "hold_id",
1087
                    orderable: false,
1088
                    searchable: false,
1089
                    render: function (data, type, row, meta) {
1090
                        return (
1091
                            '<a class="cancel-hold" title="Cancel hold" reserve_id="' +
1092
                            data +
1093
                            '" href="#"><i class="fa fa-trash" aria-label="Cancel hold"></i></a>'
1094
                        );
1095
                    },
1096
                },
1097
                {
1098
                    data: "hold_id",
1099
                    orderable: false,
1100
                    searchable: false,
1101
                    render: function (data, type, row, meta) {
1102
                        if (row.status) {
1103
                            var link_value =
1104
                                row.status == "T"
1105
                                    ? __("Revert transit status")
1106
                                    : __("Revert waiting status");
1107
                            return (
1108
                                '<a class="btn btn-default submit-form-link" href="#" id="revert_hold_' +
1109
                                data +
1110
                                '" data-op="cud-move" data-where="down" data-first_priority="1" data-last_priority="' +
1111
                                totalHolds +
1112
                                '" data-prev_priority="0" data-next_priority="1" data-borrowernumber="' +
1113
                                row.patron_id +
1114
                                '" data-biblionumber="' +
1115
                                biblio_id +
1116
                                '" data-itemnumber="' +
1117
                                row.item_id +
1118
                                '" data-reserve_id="' +
1119
                                row.hold_id +
1120
                                '" data-date="' +
1121
                                row.hold_date +
1122
                                '" data-action="request.pl" data-method="post">' +
1123
                                link_value +
1124
                                "</a>"
1125
                            );
1126
                        } else {
1127
                            let td = "";
1128
                            if (SuspendHoldsIntranet) {
1129
                                td +=
1130
                                    '<button class="btn btn-default btn-xs toggle-suspend" data-id="' +
1131
                                    data +
1132
                                    '" data-biblionumber="' +
1133
                                    biblio_id +
1134
                                    '" data-suspended="' +
1135
                                    row.suspended +
1136
                                    '">';
1137
                                if (row.suspended) {
1138
                                    td +=
1139
                                        '<i class="fa fa-play" aria-hidden="true"></i> ' +
1140
                                        __("Resume") +
1141
                                        "</button>";
1142
                                } else {
1143
                                    td +=
1144
                                        '<i class="fa fa-pause" aria-hidden="true"></i> ' +
1145
                                        __("Suspend") +
1146
                                        "</button>";
1147
                                }
1148
                                if (AutoResumeSuspendedHolds) {
1149
                                    if (row.suspended) {
1150
                                        td +=
1151
                                            '<label for="suspend_until_' +
1152
                                            data +
1153
                                            '">' +
1154
                                            __("Suspend on") +
1155
                                            " </label>";
1156
                                    } else {
1157
                                        td +=
1158
                                            '<label for="suspend_until_' +
1159
                                            data +
1160
                                            '">' +
1161
                                            __("Suspend until") +
1162
                                            " </label>";
1163
                                    }
1164
                                    td +=
1165
                                        '<input type="text" name="suspend_until_' +
1166
                                        data +
1167
                                        '" data-id="' +
1168
                                        data +
1169
                                        '" size="10" value="' +
1170
                                        $date(row.suspended_until, {
1171
                                            dateformat: "rfc3339",
1172
                                        }) +
1173
                                        '" class="suspenddate" data-flatpickr-futuredate="true" data-suspend-date="' +
1174
                                        row.suspended_until +
1175
                                        '" />';
1176
                                }
1177
                                return td;
1178
                            } else {
1179
                                return null;
1180
                            }
1181
                        }
1182
                    },
1183
                },
1184
                {
1185
                    data: "hold_id",
1186
                    orderable: false,
1187
                    searchable: false,
1188
                    render: function (data, type, row, meta) {
1189
                        if (row.status == "W" || row.status == "T") {
1190
                            return (
1191
                                '<a class="btn btn-default btn-xs printholdslip" data-reserve_id="' +
1192
                                data +
1193
                                '">' +
1194
                                __("Print slip") +
1195
                                "</a>"
1196
                            );
1197
                        } else {
1198
                            return "";
1199
                        }
1200
                    },
1201
                },
1202
            ],
1203
        },
1204
        hold_table_settings
1205
    );
1206
    $(table_id).on("draw.dt", function () {
1207
        // Remove the search box. Don't know why it isn't working in the table settings
1208
        $(this).parent().find(".pager .table_controls .dt-search").remove();
1209
        $(this)
1210
            .parent()
1211
            .find(".pager .table_controls .dt-buttons .dt_button_clear_filter")
1212
            .remove();
1213
        var MSG_CANCEL_SELECTED = _("Cancel selected (%s)");
1214
        $(".cancel_selected_holds").html(
1215
            MSG_CANCEL_SELECTED.format(
1216
                $(".holds_table .select_hold:checked").length
1217
            )
1218
        );
1219
        $(".holds_table .select_hold").each(function () {
1220
            if (
1221
                localStorage.selectedHolds &&
1222
                localStorage.selectedHolds.includes($(this).data("id"))
1223
            ) {
1224
                $(this).prop("checked", true);
1225
            }
1226
        });
1227
        $(".holds_table .select_hold_all").on("click", function () {
1228
            var table = $(this).parents(".holds_table");
1229
            var count = $(".select_hold:checked", table).length;
1230
            $(".select_hold", table).prop("checked", !count);
1231
            $(this).prop("checked", !count);
1232
            $(this).parent().parent().toggleClass("selected");
1233
            $(".cancel_selected_holds").html(
1234
                MSG_CANCEL_SELECTED.format(
1235
                    $(".holds_table .select_hold:checked").length
1236
                )
1237
            );
1238
            localStorage.selectedHolds = $(".holds_table .select_hold:checked")
1239
                .toArray()
1240
                .map(el => $(el).data("id"));
1241
        });
1242
        $(".holds_table .select_hold").on("click", function () {
1243
            var table = $(this).parents(".holds_table");
1244
            var count = $(".select_hold:not(:checked)", table).length;
1245
            $(".select_hold_all", table).prop("checked", !count);
1246
            $(this).parent().parent().toggleClass("selected");
1247
            $(".cancel_selected_holds").html(
1248
                MSG_CANCEL_SELECTED.format(
1249
                    $(".holds_table .select_hold:checked").length
1250
                )
1251
            );
1252
            localStorage.selectedHolds = $(".holds_table .select_hold:checked")
1253
                .toArray()
1254
                .map(el => $(el).data("id"));
1255
        });
1256
        $(".cancel-hold").on("click", function (e) {
1257
            e.preventDefault;
1258
            var res_id = $(this).attr("reserve_id");
1259
            $(".select_hold").prop("checked", false);
1260
            $(".select_hold_all").prop("checked", false);
1261
            $(".cancel_selected_holds").html(MSG_CANCEL_SELECTED.format(0));
1262
            $("#cancelModal")
1263
                .modal("show")
1264
                .find("#cancelModalConfirmBtn")
1265
                .attr("data-id", res_id);
1266
            delete localStorage.selectedHolds;
1267
        });
1268
        $(".cancel_selected_holds").on("click", function (e) {
1269
            e.preventDefault();
1270
            if ($(".holds_table .select_hold:checked").length) {
1271
                delete localStorage.selectedHolds;
1272
                $("#cancelModal").modal("show");
1273
            }
1274
            return false;
1275
        });
1276
        // Remove any previously attached handlers
1277
        $("#cancelModalConfirmBtn").off("click");
1278
        // Attach the handler to the button
1279
        $("#cancelModalConfirmBtn").one("click", function (e) {
1280
            e.preventDefault();
1281
            let hold_ids;
1282
            const hold_id = $("#cancelModal")
1283
                .modal("show")
1284
                .find("#cancelModalConfirmBtn")
1285
                .attr("data-id");
1286
            let reason = $("#modal-cancellation-reason").val();
1287
            if (hold_id) {
1288
                hold_ids = [hold_id];
1289
            } else {
1290
                hold_ids = $(".holds_table .select_hold:checked")
1291
                    .toArray()
1292
                    .map(el => $(el).data("id"));
1293
            }
1294
            $("#cancelModal")
1295
                .find(".modal-footer #cancelModalConfirmBtn")
1296
                .before(
1297
                    '<img src="/intranet-tmpl/prog/img/spinner-small.gif" alt="" style="padding-right: 10px;"/>'
1298
                );
1299
            deleteHolds(hold_ids, reason);
1300
            $("#cancelModal")
1301
                .modal("show")
1302
                .find("#cancelModalConfirmBtn")
1303
                .attr("data-id", "");
1304
        });
1305
        async function deleteHolds(hold_ids, reason) {
1306
            for (const hold_id of hold_ids) {
1307
                await deleteHold(hold_id, reason);
1308
                $("#cancelModal")
1309
                    .find(".modal-body")
1310
                    .append(
1311
                        '<p class="hold-cancelled">' +
1312
                            __("Hold") +
1313
                            " " +
1314
                            hold_id +
1315
                            " " +
1316
                            __("cancelled") +
1317
                            "</p>"
1318
                    );
1319
                await new Promise(resolve => setTimeout(resolve, 1000));
1320
            }
1321
1322
            holdsQueueTable.api().ajax.reload(null, false);
1323
            setTimeout(() => {
1324
                $("#cancelModal").modal("hide");
1325
                $("#cancelModal")
1326
                    .find(".modal-footer #cancelModalConfirmBtn")
1327
                    .prev("img")
1328
                    .remove();
1329
                $("#cancelModal")
1330
                    .find(".modal-body")
1331
                    .find(".hold-cancelled")
1332
                    .remove();
1333
            });
1334
        }
1335
        async function deleteHold(hold_id, reason) {
1336
            try {
1337
                await $.ajax({
1338
                    method: "DELETE",
1339
                    url: "/api/v1/holds/" + encodeURIComponent(hold_id),
1340
                    data: JSON.stringify(reason),
1341
                });
1342
            } catch (error) {
1343
                console.error("Error when deleting hold: " + hold_id);
1344
            }
1345
        }
1346
        $(".holddate, .expirationdate").flatpickr({
1347
            onReady: function (selectedDates, dateStr, instance) {
1348
                $(instance.altInput)
1349
                    .wrap("<span class='flatpickr_wrapper'></span>")
1350
                    .after(
1351
                        $("<a/>")
1352
                            .attr("href", "#")
1353
                            .addClass("clear_date")
1354
                            .addClass("fa fa-times")
1355
                            .addClass("ps-2")
1356
                            .on("click", function (e) {
1357
                                e.preventDefault();
1358
                                instance.clear();
1359
                            })
1360
                            .attr("aria-hidden", true)
1361
                    );
1362
            },
1363
            onChange: function (selectedDates, dateStr, instance) {
1364
                let hold_id = $(instance.input).attr("data-id");
1365
                let fieldname = $(instance.input).attr("name");
1366
                let current_date = $(instance.input).attr("data-current-date");
1367
                dateStr = dateStr ? dateStr : null;
1368
                let req =
1369
                    fieldname == "hold_date"
1370
                        ? { hold_date: dateStr }
1371
                        : { expiration_date: dateStr };
1372
                if (current_date != dateStr) {
1373
                    $.ajax({
1374
                        method: "PATCH",
1375
                        url: "/api/v1/holds/" + encodeURIComponent(hold_id),
1376
                        contentType: "application/json",
1377
                        data: JSON.stringify(req),
1378
                        success: function (data) {
1379
                            holdsQueueTable.api().ajax.reload(null, false);
1380
                        },
1381
                        error: function (jqXHR, textStatus, errorThrown) {
1382
                            holdsQueueTable.api().ajax.reload(null, false);
1383
                        },
1384
                    });
1385
                }
1386
            },
1387
        });
1388
        $(".suspenddate").flatpickr({
1389
            onReady: function (selectedDates, dateStr, instance) {
1390
                $(instance.altInput)
1391
                    .wrap("<span class='flatpickr_wrapper'></span>")
1392
                    .after(
1393
                        $("<a/>")
1394
                            .attr("href", "#")
1395
                            .addClass("clear_date")
1396
                            .addClass("fa fa-times")
1397
                            .addClass("ps-2")
1398
                            .on("click", function (e) {
1399
                                e.preventDefault();
1400
                                instance.clear();
1401
                            })
1402
                            .attr("aria-hidden", true)
1403
                    );
1404
            },
1405
        });
1406
        $(".toggle-suspend").one("click", function (e) {
1407
            e.preventDefault();
1408
            const hold_id = $(this).data("id");
1409
            const suspended = $(this).attr("data-suspended");
1410
            const input = $(`.suspenddate[data-id="${hold_id}"]`);
1411
            const method = suspended == "true" ? "DELETE" : "POST";
1412
            let end_date = input.val() && method == "POST" ? input.val() : null;
1413
            let params =
1414
                end_date !== null && end_date !== ""
1415
                    ? JSON.stringify({ end_date: end_date })
1416
                    : null;
1417
            $.ajax({
1418
                method: method,
1419
                url:
1420
                    "/api/v1/holds/" +
1421
                    encodeURIComponent(hold_id) +
1422
                    "/suspension",
1423
                contentType: "application/json",
1424
                data: params,
1425
                success: function (data) {
1426
                    holdsQueueTable.api().ajax.reload(null, false);
1427
                },
1428
                error: function (jqXHR, textStatus, errorThrown) {
1429
                    holdsQueueTable.api().ajax.reload(null, false);
1430
                    alert(
1431
                        "There was an error:" + textStatus + " " + errorThrown
1432
                    );
1433
                },
1434
            });
1435
        });
1436
        $(".rank-request").on("change", function (e) {
1437
            e.preventDefault();
1438
            const hold_id = $(this).data("id");
1439
            let priority = e.target.value;
1440
            $.ajax({
1441
                method: "PUT",
1442
                url:
1443
                    "/api/v1/holds/" +
1444
                    encodeURIComponent(hold_id) +
1445
                    "/priority",
1446
                data: JSON.stringify(priority),
1447
                success: function (data) {
1448
                    holdsQueueTable.api().ajax.reload(null, false);
1449
                },
1450
                error: function (jqXHR, textStatus, errorThrown) {
1451
                    alert(
1452
                        "There was an error:" + textStatus + " " + errorThrown
1453
                    );
1454
                },
1455
            });
1456
        });
1457
        $(".move-hold").one("click", function (e) {
1458
            e.preventDefault();
1459
            let toPosition = $(this).attr("data-move-hold");
1460
            let priority = $(this).attr("data-priority");
1461
            var res_id = $(this).attr("reserve_id");
1462
            var moveTo;
1463
            if (toPosition == "up") {
1464
                moveTo = parseInt(priority) - 1;
1465
            }
1466
            if (toPosition == "down") {
1467
                moveTo = parseInt(priority) + 1;
1468
            }
1469
            if (toPosition == "top") {
1470
                moveTo = 1;
1471
            }
1472
            if (toPosition == "bottom") {
1473
                moveTo = totalHolds;
1474
            }
1475
            $.ajax({
1476
                method: "PUT",
1477
                url:
1478
                    "/api/v1/holds/" + encodeURIComponent(res_id) + "/priority",
1479
                data: JSON.stringify(moveTo),
1480
                success: function (data) {
1481
                    holdsQueueTable.api().ajax.reload(null, false);
1482
                },
1483
                error: function (jqXHR, textStatus, errorThrown) {
1484
                    alert(
1485
                        "There was an error:" + textStatus + " " + errorThrown
1486
                    );
1487
                },
1488
            });
1489
        });
1490
        $(".toggle-lowest-priority").one("click", function (e) {
1491
            e.preventDefault();
1492
            var res_id = $(this).attr("data-reserve_id");
1493
            $.ajax({
1494
                method: "PUT",
1495
                url:
1496
                    "/api/v1/holds/" +
1497
                    encodeURIComponent(res_id) +
1498
                    "/lowest_priority",
1499
                success: function (data) {
1500
                    holdsQueueTable.api().ajax.reload(null, false);
1501
                },
1502
                error: function (jqXHR, textStatus, errorThrown) {
1503
                    alert(
1504
                        "There was an error:" + textStatus + " " + errorThrown
1505
                    );
1506
                },
1507
            });
1508
        });
1509
        $(".hold_location_select").on("change", function () {
1510
            $(this).prop("disabled", true);
1511
            var cur_select = $(this);
1512
            var res_id = $(this).attr("reserve_id");
1513
            $(this).after(
1514
                '<div id="updating_reserveno' +
1515
                    res_id +
1516
                    '" class="waiting"><img src="/intranet-tmpl/prog/img/spinner-small.gif" alt="" /><span class="waiting_msg"></span></div>'
1517
            );
1518
            let api_url =
1519
                "/api/v1/holds/" +
1520
                encodeURIComponent(res_id) +
1521
                "/pickup_location";
1522
            $.ajax({
1523
                method: "PUT",
1524
                url: api_url,
1525
                data: JSON.stringify({ pickup_library_id: $(this).val() }),
1526
                headers: { "x-koha-override": "any" },
1527
                success: function (data) {
1528
                    holdsQueueTable.api().ajax.reload(null, false);
1529
                },
1530
                error: function (jqXHR, textStatus, errorThrown) {
1531
                    alert(
1532
                        "There was an error:" + textStatus + " " + errorThrown
1533
                    );
1534
                    cur_select.prop("disabled", false);
1535
                    $("#updating_reserveno" + res_id).remove();
1536
                    cur_select.val(
1537
                        cur_select.children('option[selected="selected"]').val()
1538
                    );
1539
                },
1540
            });
1541
        });
1542
        $(".printholdslip").one("click", function () {
1543
            var reserve_id = $(this).attr("data-reserve_id");
1544
            window.open(
1545
                "/cgi-bin/koha/circ/hold-transfer-slip.pl?reserve_id=" +
1546
                    reserve_id
1547
            );
1548
            return false;
1549
        });
1550
    });
1551
}
(-)a/reserve/request.pl (-59 / +33 lines)
Lines 603-611 if ( ( $findborrower && $borrowernumber_hold || $findclub && $club_hold ) Link Here
603
603
604
        # existingreserves building
604
        # existingreserves building
605
        my @reserveloop;
605
        my @reserveloop;
606
        my $total_holds       = 0;
607
        my $hold_branches     = [];
608
        my $hold_itemtypes    = [];
606
        my $always_show_holds = $input->cookie('always_show_holds');
609
        my $always_show_holds = $input->cookie('always_show_holds');
607
        $template->param( always_show_holds => $always_show_holds );
610
        $template->param( always_show_holds => $always_show_holds );
608
        my $show_holds_now = $input->param('show_holds_now');
611
        my $show_holds_now = $input->param('show_holds_now');
612
609
        unless ( ( defined $always_show_holds && $always_show_holds eq 'DONT' ) && !$show_holds_now ) {
613
        unless ( ( defined $always_show_holds && $always_show_holds eq 'DONT' ) && !$show_holds_now ) {
610
            my $holds_count_per_patron = {
614
            my $holds_count_per_patron = {
611
                map { $_->{borrowernumber} => $_->{hold_count} } @{ Koha::Holds->search(
615
                map { $_->{borrowernumber} => $_->{hold_count} } @{ Koha::Holds->search(
Lines 618-678 if ( ( $findborrower && $borrowernumber_hold || $findclub && $club_hold ) Link Here
618
                    )->unblessed
622
                    )->unblessed
619
                }
623
                }
620
            };
624
            };
621
            my @reserves =
625
            $total_holds = Koha::Holds->search( { biblionumber => $biblionumber } )->count;
622
                Koha::Holds->search( { biblionumber => $biblionumber }, { order_by => 'priority' } )->as_list;
626
            my $branches = Koha::Holds->search(
623
            foreach my $res (
627
                {
624
                sort {
628
                    biblionumber => $biblionumber,
625
                    my $a_found = $a->found() || '';
629
                },
626
                    my $b_found = $a->found() || '';
630
                {
627
                    $a_found cmp $b_found;
631
                    select => [ { distinct => 'branchcode' } ],
628
                } @reserves
632
                    as     => [qw( branchcode )],
629
                )
630
            {
631
                my %reserve;
632
                if ( $res->is_found() ) {
633
                    $reserve{'holdingbranch'} = $res->item()->holdingbranch();
634
                    $reserve{'biblionumber'}  = $res->item()->biblionumber();
635
                    $reserve{'barcodenumber'} = $res->item()->barcode();
636
                    $reserve{'wbrcode'}       = $res->branchcode();
637
                    $reserve{'itemnumber'}    = $res->itemnumber();
638
                    $reserve{'wbrname'}       = $res->branch()->branchname();
639
                    $reserve{'atdestination'} = $res->is_at_destination();
640
                    $reserve{'desk_name'}     = ( $res->desk() ) ? $res->desk()->desk_name() : '';
641
                    $reserve{'found'}         = $res->is_found();
642
                    $reserve{'inprocessing'}  = $res->is_in_processing();
643
                    $reserve{'intransit'}     = $res->is_in_transit();
644
                } elsif ( $res->priority() > 0 ) {
645
                    if ( my $item = $res->item() ) {
646
                        $reserve{'itemnumber'}      = $item->id();
647
                        $reserve{'barcodenumber'}   = $item->barcode();
648
                        $reserve{'item_level_hold'} = 1;
649
                    }
650
                }
633
                }
651
                $reserve{'expirationdate'} = $res->expirationdate;
634
            )->unblessed;
652
                $reserve{'date'}           = $res->reservedate;
635
            $hold_branches = [ map { $_->{branchcode} } @$branches ];
653
                $reserve{'borrowernumber'} = $res->borrowernumber();
636
            my $itemtypes = Koha::Holds->search(
654
                $reserve{'biblionumber'}   = $res->biblionumber();
637
                {
655
                $reserve{'patron'}         = $res->borrower;
638
                    biblionumber => $biblionumber,
656
                $reserve{'notes'}          = $res->reservenotes();
639
                },
657
                $reserve{'waiting_date'}   = $res->waitingdate();
640
                {
658
                $reserve{'ccode'}          = $res->item() ? $res->item()->ccode()   : undef;
641
                    select => [ { distinct => 'itemtype' } ],
659
                $reserve{'barcode'}        = $res->item() ? $res->item()->barcode() : undef;
642
                    as     => [qw( itemtype )],
660
                $reserve{'priority'}       = $res->priority();
661
                $reserve{'lowestPriority'} = $res->lowestPriority();
662
                $reserve{'suspend'}        = $res->suspend();
663
                $reserve{'suspend_until'}  = $res->suspend_until();
664
                $reserve{'reserve_id'}     = $res->reserve_id();
665
                $reserve{itemtype}         = $res->itemtype();
666
                $reserve{branchcode}       = $res->branchcode();
667
                $reserve{non_priority}     = $res->non_priority();
668
                $reserve{object}           = $res;
669
670
                if ( $holds_count_per_patron->{ $reserve{'borrowernumber'} } == 1 ) {
671
                    $reserve{'change_hold_type_allowed'} = 1;
672
                }
643
                }
673
644
            )->unblessed;
674
                push( @reserveloop, \%reserve );
645
            $hold_itemtypes = [ map { $_->{itemtype} ? $_->{itemtype} : 'any' } @$itemtypes ];
675
            }
676
        }
646
        }
677
647
678
        # get the time for the form name...
648
        # get the time for the form name...
Lines 695-710 if ( ( $findborrower && $borrowernumber_hold || $findclub && $club_hold ) Link Here
695
            C4::Search::enabled_staff_search_views,
665
            C4::Search::enabled_staff_search_views,
696
        );
666
        );
697
667
698
        $biblioloopiter{biblionumber} = $biblionumber;
668
        $biblioloopiter{biblionumber}   = $biblionumber;
699
        $biblioloopiter{title}        = $biblio->title;
669
        $biblioloopiter{title}          = $biblio->title;
700
        $biblioloopiter{author}       = $biblio->author;
670
        $biblioloopiter{author}         = $biblio->author;
701
        $biblioloopiter{rank}         = $fixedRank;
671
        $biblioloopiter{rank}           = $fixedRank;
702
        $biblioloopiter{reserveloop}  = \@reserveloop;
672
        $biblioloopiter{reserveloop}    = \@reserveloop;
673
        $biblioloopiter{total_holds}    = $total_holds;
674
        $biblioloopiter{hold_branches}  = $hold_branches;
675
        $biblioloopiter{hold_itemtypes} = $hold_itemtypes;
703
676
704
        if (@reserveloop) {
677
        if (@reserveloop) {
705
            $template->param( reserveloop => \@reserveloop );
678
            $template->param( reserveloop => \@reserveloop );
706
        }
679
        }
707
680
681
        $template->param( total_holds => $total_holds );
682
708
        if ( $patron && $multi_hold ) {
683
        if ( $patron && $multi_hold ) {
709
684
710
            # Add the valid pickup locations
685
            # Add the valid pickup locations
711
- 

Return to bug 23269