|
Lines 105-110
Link Here
|
| 105 |
</div> |
105 |
</div> |
| 106 |
</div> |
106 |
</div> |
| 107 |
|
107 |
|
|
|
108 |
<!-- Modal for biblio restoration with items --> |
| 109 |
<div class="modal" id="restoreBiblioModal" tabindex="-1" role="dialog" aria-labelledby="restoreBiblioModalLabel"> |
| 110 |
<div class="modal-dialog modal-lg" role="document"> |
| 111 |
<div class="modal-content"> |
| 112 |
<div class="modal-header"> |
| 113 |
<h4 class="modal-title" id="restoreBiblioModalLabel">Restore bibliographic record with items</h4> |
| 114 |
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> |
| 115 |
</div> |
| 116 |
<div class="modal-body"> |
| 117 |
<p>Restore bibliographic record:</p> |
| 118 |
<dl> |
| 119 |
<dt>Biblio ID:</dt> |
| 120 |
<dd id="restore-modal-biblio-id"></dd> |
| 121 |
<dt>Title:</dt> |
| 122 |
<dd id="restore-modal-biblio-title"></dd> |
| 123 |
<dt>Author:</dt> |
| 124 |
<dd id="restore-modal-biblio-author"></dd> |
| 125 |
</dl> |
| 126 |
<div id="items-section"> |
| 127 |
<hr /> |
| 128 |
<p><strong>This bibliographic record has deleted items. Select items to restore:</strong></p> |
| 129 |
<table class="table table-sm table-bordered" id="deleted-items-list"> |
| 130 |
<thead> |
| 131 |
<tr> |
| 132 |
<th class="NoSort"><input type="checkbox" id="select-all-items" /></th> |
| 133 |
<th>Item ID</th> |
| 134 |
<th>Barcode</th> |
| 135 |
<th>Call number</th> |
| 136 |
<th>Home library</th> |
| 137 |
</tr> |
| 138 |
</thead> |
| 139 |
<tbody></tbody> |
| 140 |
</table> |
| 141 |
</div> |
| 142 |
</div> |
| 143 |
<div class="modal-footer"> |
| 144 |
<button type="button" class="btn btn-default" data-bs-dismiss="modal">Cancel</button> |
| 145 |
<button type="button" class="btn btn-primary" id="restore-biblio-with-items-button">Restore</button> |
| 146 |
</div> |
| 147 |
</div> |
| 148 |
</div> |
| 149 |
</div> |
| 150 |
|
| 108 |
[% MACRO jsinclude BLOCK %] |
151 |
[% MACRO jsinclude BLOCK %] |
| 109 |
[% Asset.js("js/tools-menu.js") | $raw %] |
152 |
[% Asset.js("js/tools-menu.js") | $raw %] |
| 110 |
[% INCLUDE 'datatables.inc' %] |
153 |
[% INCLUDE 'datatables.inc' %] |
|
Lines 126-131
Link Here
|
| 126 |
ajax: { |
169 |
ajax: { |
| 127 |
url: "/api/v1/deleted/biblios", |
170 |
url: "/api/v1/deleted/biblios", |
| 128 |
}, |
171 |
}, |
|
|
172 |
embed: "items", |
| 129 |
order: [[3, "desc"]], |
173 |
order: [[3, "desc"]], |
| 130 |
columns: [ |
174 |
columns: [ |
| 131 |
{ |
175 |
{ |
|
Lines 274-314
Link Here
|
| 274 |
}); |
318 |
}); |
| 275 |
var items_table_api = items_table.DataTable(); |
319 |
var items_table_api = items_table.DataTable(); |
| 276 |
|
320 |
|
|
|
321 |
// Initialize the modal items table as kohaTable |
| 322 |
var modal_items_table = null; |
| 323 |
var modal_items_table_api = null; |
| 324 |
|
| 277 |
// Restore biblio handler |
325 |
// Restore biblio handler |
| 278 |
$("#deleted_biblios_table").on("click", ".restore-biblio", function (e) { |
326 |
$("#deleted_biblios_table").on("click", ".restore-biblio", function (e) { |
| 279 |
e.preventDefault(); |
327 |
e.preventDefault(); |
| 280 |
var button = $(this); |
328 |
var button = $(this); |
| 281 |
var biblio_id = button.data("biblio-id"); |
329 |
var biblio_id = button.data("biblio-id"); |
| 282 |
var title = button.data("title"); |
330 |
var title = button.data("title"); |
|
|
331 |
var row = biblios_table_api.row(button.closest("tr")).data(); |
| 283 |
|
332 |
|
| 284 |
if (!confirm(_("Are you sure you want to restore bibliographic record %s '%s'?").format(biblio_id, title))) { |
333 |
// Populate modal with biblio info |
| 285 |
return; |
334 |
$("#restore-modal-biblio-id").text(biblio_id); |
|
|
335 |
$("#restore-modal-biblio-title").text(title || _("(No title)")); |
| 336 |
$("#restore-modal-biblio-author").text(row.author || _("(No author)")); |
| 337 |
|
| 338 |
// Check if there are deleted items |
| 339 |
var items = row.items || []; |
| 340 |
if (items.length > 0) { |
| 341 |
$("#items-section").show(); |
| 342 |
|
| 343 |
// Destroy existing DataTable if it exists |
| 344 |
if (modal_items_table_api) { |
| 345 |
modal_items_table_api.destroy(); |
| 346 |
} |
| 347 |
|
| 348 |
// Initialize kohaTable with the items data |
| 349 |
modal_items_table = $("#deleted-items-list").kohaTable({ |
| 350 |
data: items, |
| 351 |
paging: false, |
| 352 |
info: false, |
| 353 |
columns: [ |
| 354 |
{ |
| 355 |
data: function (row, type) { |
| 356 |
if (type === "display") { |
| 357 |
return '<input type="checkbox" class="item-checkbox" data-item-id="' + row.item_id + '">'; |
| 358 |
} |
| 359 |
return ""; |
| 360 |
}, |
| 361 |
searchable: false, |
| 362 |
orderable: false, |
| 363 |
}, |
| 364 |
{ |
| 365 |
data: "item_id", |
| 366 |
searchable: true, |
| 367 |
orderable: true, |
| 368 |
}, |
| 369 |
{ |
| 370 |
data: "external_id", |
| 371 |
searchable: true, |
| 372 |
orderable: true, |
| 373 |
render: function (data, type, row) { |
| 374 |
if (type === "display") { |
| 375 |
return data ? $("<div/>").text(data).html() : _("(No barcode)"); |
| 376 |
} |
| 377 |
return data || ""; |
| 378 |
}, |
| 379 |
}, |
| 380 |
{ |
| 381 |
data: "callnumber", |
| 382 |
searchable: true, |
| 383 |
orderable: true, |
| 384 |
render: function (data, type, row) { |
| 385 |
if (type === "display") { |
| 386 |
return data ? $("<div/>").text(data).html() : ""; |
| 387 |
} |
| 388 |
return data || ""; |
| 389 |
}, |
| 390 |
}, |
| 391 |
{ |
| 392 |
data: "home_library_id", |
| 393 |
searchable: true, |
| 394 |
orderable: true, |
| 395 |
render: function (data, type, row) { |
| 396 |
if (type === "display") { |
| 397 |
return data ? $("<div/>").text(data).html() : ""; |
| 398 |
} |
| 399 |
return data || ""; |
| 400 |
}, |
| 401 |
}, |
| 402 |
], |
| 403 |
}); |
| 404 |
modal_items_table_api = modal_items_table.DataTable(); |
| 405 |
} else { |
| 406 |
$("#items-section").hide(); |
| 286 |
} |
407 |
} |
| 287 |
|
408 |
|
| 288 |
button.prop("disabled", true); |
409 |
// Store biblio data |
|
|
410 |
$("#restore-biblio-with-items-button").data("biblio-id", biblio_id); |
| 411 |
$("#restore-biblio-with-items-button").data("restore-button", button); |
| 289 |
|
412 |
|
| 290 |
$.ajax({ |
413 |
var modal = new bootstrap.Modal(document.getElementById("restoreBiblioModal")); |
| 291 |
url: "/api/v1/deleted/biblios/" + biblio_id, |
414 |
modal.show(); |
| 292 |
type: "POST", |
|
|
| 293 |
headers: { |
| 294 |
"x-koha-request-id": Math.random(), |
| 295 |
}, |
| 296 |
success: function (data) { |
| 297 |
$("#messages").append( |
| 298 |
'<div class="alert alert-success">' + '<button type="button" class="close" data-dismiss="alert">×</button>' + _("Bibliographic record %s restored successfully").format(biblio_id) + "</div>" |
| 299 |
); |
| 300 |
biblios_table_api.ajax.reload(); |
| 301 |
items_table_api.ajax.reload(); |
| 302 |
}, |
| 303 |
error: function (xhr) { |
| 304 |
var error_msg = _("Error restoring bibliographic record %s").format(biblio_id); |
| 305 |
if (xhr.responseJSON && xhr.responseJSON.error) { |
| 306 |
error_msg += ": " + xhr.responseJSON.error; |
| 307 |
} |
| 308 |
$("#messages").append('<div class="alert alert-danger">' + '<button type="button" class="close" data-dismiss="alert">×</button>' + error_msg + "</div>"); |
| 309 |
button.prop("disabled", false); |
| 310 |
}, |
| 311 |
}); |
| 312 |
}); |
415 |
}); |
| 313 |
|
416 |
|
| 314 |
// Restore item handler |
417 |
// Restore item handler |
|
Lines 395-400
Link Here
|
| 395 |
}, |
498 |
}, |
| 396 |
}); |
499 |
}); |
| 397 |
}); |
500 |
}); |
|
|
501 |
|
| 502 |
// Select all items checkbox |
| 503 |
$("#select-all-items").on("change", function () { |
| 504 |
var checked = $(this).prop("checked"); |
| 505 |
$(".item-checkbox").prop("checked", checked); |
| 506 |
}); |
| 507 |
|
| 508 |
// Restore biblio with items |
| 509 |
$("#restore-biblio-with-items-button").on("click", function () { |
| 510 |
var button = $(this); |
| 511 |
var biblio_id = button.data("biblio-id"); |
| 512 |
var restore_button = button.data("restore-button"); |
| 513 |
|
| 514 |
button.prop("disabled", true); |
| 515 |
|
| 516 |
$.ajax({ |
| 517 |
url: "/api/v1/deleted/biblios/" + biblio_id, |
| 518 |
type: "PUT", |
| 519 |
headers: { |
| 520 |
"x-koha-request-id": Math.random(), |
| 521 |
}, |
| 522 |
success: function (data) { |
| 523 |
showMessage(_("Bibliographic record %s restored successfully").format(biblio_id), "success"); |
| 524 |
|
| 525 |
var selected_items = []; |
| 526 |
$(".item-checkbox:checked").each(function () { |
| 527 |
selected_items.push($(this).data("item-id")); |
| 528 |
}); |
| 529 |
|
| 530 |
if (selected_items.length > 0) { |
| 531 |
var items_restored = 0; |
| 532 |
var items_failed = 0; |
| 533 |
|
| 534 |
selected_items.forEach(function (item_id) { |
| 535 |
$.ajax({ |
| 536 |
url: "/api/v1/deleted/items/" + item_id, |
| 537 |
type: "PUT", |
| 538 |
headers: { |
| 539 |
"x-koha-request-id": Math.random(), |
| 540 |
}, |
| 541 |
success: function (data) { |
| 542 |
items_restored++; |
| 543 |
if (items_restored + items_failed === selected_items.length) { |
| 544 |
if (items_restored > 0) { |
| 545 |
showMessage(_("%s item(s) restored successfully").format(items_restored), "success"); |
| 546 |
} |
| 547 |
if (items_failed > 0) { |
| 548 |
showMessage(_("%s item(s) failed to restore").format(items_failed), "danger"); |
| 549 |
} |
| 550 |
items_table_api.ajax.reload(); |
| 551 |
} |
| 552 |
}, |
| 553 |
error: function (xhr) { |
| 554 |
items_failed++; |
| 555 |
if (items_restored + items_failed === selected_items.length) { |
| 556 |
if (items_restored > 0) { |
| 557 |
showMessage(_("%s item(s) restored successfully").format(items_restored), "success"); |
| 558 |
} |
| 559 |
if (items_failed > 0) { |
| 560 |
showMessage(_("%s item(s) failed to restore").format(items_failed), "danger"); |
| 561 |
} |
| 562 |
items_table_api.ajax.reload(); |
| 563 |
} |
| 564 |
}, |
| 565 |
}); |
| 566 |
}); |
| 567 |
} |
| 568 |
|
| 569 |
bootstrap.Modal.getInstance(document.getElementById("restoreBiblioModal")).hide(); |
| 570 |
biblios_table_api.ajax.reload(); |
| 571 |
button.prop("disabled", false); |
| 572 |
}, |
| 573 |
error: function (xhr) { |
| 574 |
var error_msg = _("Error restoring bibliographic record %s").format(biblio_id); |
| 575 |
if (xhr.responseJSON && xhr.responseJSON.error) { |
| 576 |
error_msg += ": " + xhr.responseJSON.error; |
| 577 |
} |
| 578 |
showMessage(error_msg, "danger"); |
| 579 |
button.prop("disabled", false); |
| 580 |
}, |
| 581 |
}); |
| 582 |
}); |
| 398 |
}); |
583 |
}); |
| 399 |
</script> |
584 |
</script> |
| 400 |
[% END %] |
585 |
[% END %] |
| 401 |
- |
|
|