Jonathan Druart
424aca3d56
Here we go! Disclaimer: this patch is huge and does many things, but splitting it in several chunks would be time consuming and painful to rebase. However it adds many tests and isolate/refactor code to make it way more reusable. This patchset will make the "batch item modification" and "batch item deletion" features use the task queue (reminder: Since bug 28158, and so 21.05.00, we do no longer use the old "background job" functionality and the user does not get any info about the progress of the job). More than that, more of the code to build an item form and a list of items is now isolated in module (.pm) and include files (.inc) We are reusing the changes made by bug 27526 that simplifies the way we edit/create items (no more unecessary serialization Koha > MARC > MARCXML > XML > HTML) New module: * Koha::BackgroundJob::BatchDeleteItem Subclass for process item deletion in batch * Koha::BackgroundJob::BatchUpdateItem Subclass for process item modification in batch * Koha::Item::Attributes We needed an object to represent item's attributes that are not mapped with a koha field (aka "more subfields xml") This module will help us to create the marcxml from a hashref and the reverse. * Koha::UI::Form::Builder::Item The code that was used to build the add/edit item form is centralised in this module. In conjunction with the subfields_for_item BLOCK (from html_helpers.inc) it will be really easy to reuse this code in other places where the item form is used (acquisition and serials modules) * Koha::UI::Table::Builder::Items Same as previously for the table. We are now using this table from 3 different places (batch item mod, batch item del, backgroung job detail view) and the code is only in one place. To use with items_table_batchmod BLOCK (still from html_helpers.inc) This patch is fixing some bugs about repeatable subfields and regex. A UI change will reflect the limitation: if you want to apply a regex on a subfield you cannot add several subfields for the same subfield code. Test plan: Prepare the ground: - Make sure you are always using a bibliographic/item record using the framework you are modifying! - Add some subfields for items that are not mapped with a koha field (note that you can use 'é' for more fun, don't try more funny characters) - Make some subfields (mapped and not mapped with a kohafield) repeatable - Add default values to some of your subfields There are 4 main screens to test: 1. Add/edit item form The behaviour should be the same before and after this patch. See test plan from bug 27526. Those 2 prefs must be tested: * SubfieldsToAllowForRestrictedEditing * SubfieldsToUseWhenPrefill 2. Batch modification a. Fill some values, play with repeatable and regex. Note that the behaviour in master was buggy, only the first value was modified by the regex: * With subfield = "a | b" 1 value added with "new" => "new | b" * With subfield = "a | b" 2 new fields "new1","new2" => "new2 | b" Important note: For repeatable subfields, a regex will apply on the subfields in the "concatenated form". To apply the regex on all the different subfields of a given subfield code you must use the "g" modifier. This could be improved later, but keep in mind that it's not a regression or behaviour change. b. Play with the "Populate fields with default values from default framework" checkbox c. Use this tool to modify items and play with the different sysprefs that interfer with it: * NewItemsDefaultLocation * SubfieldsToAllowForRestrictedBatchmod * MaxItemsToDisplayForBatchMod * MaxItemsToProcessForBatchMod 3. Batch deletion a. Batch delete some items b. Check items out and try to delete them c. Use the "Delete records if no items remain" checkbox to delete bibliographic records without remaining items. d. Play with the following sysprefs and confirm that it works as expected: * MaxItemsToDisplayForBatchDel e. Stress the tool: Go to the confirmation screen with items that can be deleted, don't request the job to be processed right away, but check the item out before. 4. Background job detail view You must have seen it already if you are curious and tested the above. When a new modification or deletion batch is requested, the confirmation screen will tell you that the job has enqueued. A link to the progress of the job can be followed. On this screen you will be able to see the result of the job once it's fully processed. QA notes: * There are some FIXME's that are not blocker in my opinion. Feel free to discuss them if you have suggestions. * Do we still need MaxItemsToProcessForBatchMod? * Prior to this patchset we had a "Return to the cataloging module" link if we went from the cataloguing module and that the biblio was deleted. We cannot longer know if the biblio will be deleted but we could display a "Go to the cataloging module" link on the "job has been enqueued" screen regardless from where we were coming from. Signed-off-by: Nick Clemens <nick@bywatersolutions.com> Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io> Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
215 lines
12 KiB
Text
215 lines
12 KiB
Text
[% USE raw %]
|
|
[% USE Asset %]
|
|
[% USE Koha %]
|
|
[% USE Branches %]
|
|
[% USE KohaDates %]
|
|
[% USE TablesSettings %]
|
|
[% INCLUDE 'doc-head-open.inc' %]
|
|
<title>Items › [% biblio.title | html %] [% IF ( biblio.author ) %] by [% biblio.author | html %][% END %] (Record #[% biblio.biblionumber | html %]) › Cataloging › Koha</title>
|
|
[% INCLUDE 'doc-head-close.inc' %]
|
|
[% Asset.css("css/addbiblio.css") | $raw %]
|
|
[% INCLUDE 'datatables.inc' %]
|
|
<script>
|
|
[% IF Koha.Preference('CreateAVFromCataloguing') && CAN_user_parameters_manage_auth_values %]
|
|
var auth_values_creation = 1;
|
|
[% ELSE %]
|
|
var auth_values_creation = 0;
|
|
[% END %]
|
|
</script>
|
|
[% INCLUDE 'select2.inc' %]
|
|
[% Asset.js("js/cataloging.js") | $raw %]
|
|
[% INCLUDE 'columns_settings.inc' %]
|
|
[% Asset.js("js/browser.js") | $raw %]
|
|
[% INCLUDE 'calendar.inc' %]
|
|
[% INCLUDE 'str/cataloging_additem.inc' %]
|
|
[% Asset.js("js/cataloging_additem.js") | $raw %]
|
|
</head>
|
|
|
|
<body id="cat_additem" class="cat">
|
|
[% INCLUDE 'header.inc' %]
|
|
[% INCLUDE 'cataloging-search.inc' %]
|
|
|
|
<nav id="breadcrumbs" aria-label="Breadcrumb" class="breadcrumb">
|
|
<ol>
|
|
<li>
|
|
<a href="/cgi-bin/koha/mainpage.pl">Home</a>
|
|
</li>
|
|
<li>
|
|
<a href="/cgi-bin/koha/cataloguing/addbooks.pl">Cataloging</a>
|
|
</li>
|
|
<li>
|
|
<a href="/cgi-bin/koha/cataloguing/addbiblio.pl?biblionumber=[% biblio.biblionumber | uri %]">Edit <em>[% biblio.title | html %] [% IF ( biblio.author ) %] by [% biblio.author | html %][% END %] (Record #[% biblio.biblionumber | html %])</em></a>
|
|
</li>
|
|
<li>
|
|
<a href="#" aria-current="page">
|
|
Items
|
|
</a>
|
|
</li>
|
|
</ol>
|
|
</nav>
|
|
|
|
<div class="main container-fluid">
|
|
<div class="row">
|
|
<div class="col-sm-12">
|
|
<main>
|
|
[% INCLUDE 'blocking_errors.inc' %]
|
|
<h1>Items for [% biblio.title | html %] [% IF ( biblio.author ) %] by [% biblio.author | html %][% END %] (Record #[% biblio.biblionumber | html %])</h1>
|
|
|
|
[% IF ( barcode_not_unique ) %]<div class="dialog alert"><strong>Error saving item</strong>: Barcode must be unique.</div>[% END %]
|
|
[% IF ( no_next_barcode ) %]<div class="dialog alert"><strong>Error saving items</strong>: Unable to automatically determine values for barcodes. No item has been inserted.</div>[% END %]
|
|
[% IF ( book_on_loan ) %]<div class="dialog alert"><strong>Cannot delete</strong>: item is checked out.</div>[% END %]
|
|
[% IF ( book_reserved ) %]<div class="dialogalert"><strong>Cannot delete</strong>: item has a waiting hold.</div>[% END %]
|
|
[% IF ( not_same_branch ) %]<div class="dialog alert"><strong>Cannot delete</strong>: The items do not belong to your library.</div>[% END %]
|
|
[% IF ( linked_analytics ) %]<div class="dialog alert"><strong>Cannot delete</strong>: item has linked <a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% biblio.biblionumber | uri %]&analyze=1">analytics.</a>.</div>[% END %]
|
|
[% IF last_item_for_hold %]<div class="dialog alert"><strong>Cannot delete</strong>: Last item for bibliographic record with biblio-level hold on it.</div>[% END %]
|
|
|
|
<div id="cataloguing_additem_itemlist">
|
|
[% IF items %]
|
|
[% SET date_fields = [ 'dateaccessioned', 'onloan', 'datelastseen', 'datelastborrowed', 'replacementpricedate' ] %]
|
|
<div>
|
|
<table id="itemst">
|
|
<thead>
|
|
<tr>
|
|
<th class="NoSort"> </th>
|
|
[% FOREACH item_header IN item_header_loop %]
|
|
[% IF item_header.column_name %]
|
|
<th data-colname="[% item_header.column_name | html %]">
|
|
[% ELSE %]
|
|
<th>
|
|
[% END %]
|
|
[% item_header.header_value | html %]
|
|
</th>
|
|
[% END %]
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
[% FOREACH item IN items %]
|
|
[% SET can_be_edited = ! ( Koha.Preference('IndependentBranches') && ! logged_in_user && item.homebranch != Branches.GetLoggedInBranchcode() ) %]
|
|
[% IF item.itemnumber == itemnumber%]
|
|
[% UNLESS can_be_edited %]
|
|
<tr id="row[% item.itemnumber | html %]" class="active">
|
|
[% ELSE %]
|
|
<tr id="row[% item.itemnumber | html %]" class="active editable">
|
|
[% END %]
|
|
[% ELSE %]
|
|
[% UNLESS can_be_edited %]
|
|
<tr id="row[% item.itemnumber | html %]">
|
|
[% ELSE %]
|
|
<tr id="row[% item.itemnumber | html %]" class="editable">
|
|
[% END %]
|
|
[% END %]
|
|
[% UNLESS can_be_edited %]
|
|
<td> </td>
|
|
[% ELSE %]
|
|
<td>
|
|
<div class="btn-group dropup">
|
|
<a class="btn btn-default btn-xs dropdown-toggle" id="itemactions[% item.itemnumber | html %]" role="button" data-toggle="dropdown" href="#">
|
|
Actions <b class="caret"></b>
|
|
</a>
|
|
<ul class="dropdown-menu" role="menu" aria-labelledby="itemactions[% item.itemnumber | html %]">
|
|
|
|
[% IF item.biblionumber != biblio.biblionumber %] [%# Host item %]
|
|
<li><a href="additem.pl?op=edititem&biblionumber=[% item.biblionumber | uri %]&itemnumber=[% item.itemnumber | uri %]#edititem">Edit in host</a> <a class="delete" href="/cgi-bin/koha/cataloguing/additem.pl?op=delinkitem&biblionumber=[% biblio.biblionumber | html %]&hostitemnumber=[% item.itemnumber | html %]&searchid=[% searchid | html %]">Delink</a></li>
|
|
[% ELSE %]
|
|
<li><a href="additem.pl?op=edititem&biblionumber=[% biblio.biblionumber | uri %]&itemnumber=[% item.itemnumber | uri %]&searchid=[% searchid | uri %]#edititem">Edit</a></li>
|
|
<li><a href="additem.pl?op=dupeitem&biblionumber=[% biblio.biblionumber | uri %]&itemnumber=[% item.itemnumber | uri %]&searchid=[% searchid | uri %]#additema">Duplicate</a></li>
|
|
<li class="print_label"><a href="/cgi-bin/koha/labels/label-edit-batch.pl?op=add&number_type=itemnumber&number_list=[% item.itemnumber | uri %]" target="_blank" >Print label</a></li>
|
|
<li><a class="delete" href="/cgi-bin/koha/cataloguing/additem.pl?op=delitem&biblionumber=[% item.biblionumber | html %]&itemnumber=[% item.itemnumber | html %]&searchid=[% searchid | html %]" onclick="return confirm_deletion();">Delete</a></li>
|
|
[% END %]
|
|
[% IF ( OPACBaseURL ) %]
|
|
<li class="view-in-opac"><a target="_blank" href="[% Koha.Preference('OPACBaseURL') | url %]/cgi-bin/koha/opac-detail.pl?biblionumber=[% item.biblionumber | uri %]">OPAC view</a></li>
|
|
[% END %]
|
|
</ul>
|
|
</div>
|
|
</td>
|
|
[% END %]
|
|
[% FOREACH header IN item_header_loop %]
|
|
[% SET attribute = header.attribute %]
|
|
[% IF header.attribute AND date_fields.grep('^' _ attribute _ '$').size %]
|
|
<td data-order="[% item.$attribute | html %]">[% item.$attribute | $KohaDates %]</td>
|
|
[% ELSE %]
|
|
<td>[% item.$attribute | html %]</td>
|
|
[% END %]
|
|
[% END %]
|
|
</tr>
|
|
[% END %]
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
[% END %]
|
|
|
|
<div class="row">
|
|
<div class="col-sm-2">
|
|
[% INCLUDE 'biblio-view-menu.inc' %]
|
|
</div>
|
|
<div class="col-sm-10">
|
|
|
|
<div id="cataloguing_additem_newitem">
|
|
<form id="f" method="post" action="/cgi-bin/koha/cataloguing/additem.pl?biblionumber=[% biblio.biblionumber | html %]" name="f">
|
|
<input type="hidden" name="op" value="[% op | html %]" />
|
|
[% IF (popup) %]
|
|
<input type="hidden" name="popup" value="1" />
|
|
[% END %]
|
|
<input type="hidden" name="biblionumber" value="[% biblio.biblionumber | html %]" />
|
|
[% IF op != 'saveitem' %]
|
|
<h2 id="additema">Add item [% IF (circborrowernumber) %]<em>(fast cataloging)</em>[% END %]</h2>
|
|
[% ELSE %]
|
|
<h2 id="edititem">Edit item #[% itemnumber | html %][% IF ( barcode ) %] / Barcode [% barcode | html %][% END %]</h2>
|
|
[% END %]
|
|
<fieldset class="rows">
|
|
[% PROCESS subfields_for_item subfields => subfields %]
|
|
</fieldset>
|
|
[% IF op != 'add_item' %]
|
|
<input type="hidden" name="itemnumber" value="[% itemnumber | html %]" />
|
|
[% END %]
|
|
|
|
<fieldset class="action"> [% IF op != 'saveitem' %]
|
|
<input type="submit" name="phony_submit" value="phony_submit" id="phony_submit" style="display:none;" onclick="return false;" />
|
|
<!-- Note : We use here a false submit button because we have several submit buttons and we don't want the user to believe they validated the adding of multiple items
|
|
when pressing the enter key, while in fact it is the first submit button that is validated, in our case the "add (single) item" button.
|
|
It is a bit tricky, but necessary in the sake of UI correctness.
|
|
-->
|
|
<span id="addsingle">
|
|
<input type="submit" name="add_submit" value="Add item" onclick="return Check(this.form)" />
|
|
<input type="submit" name="add_duplicate_submit" value="Add & duplicate" onclick="return Check(this.form)" />
|
|
</span>
|
|
<span id="addmultiple">
|
|
<input type="button" name="add_multiple_copies" id="add_multiple_copies" value="Add multiple copies of this item" />
|
|
</span>
|
|
<fieldset id="add_multiple_copies_span">
|
|
<label for="number_of_copies">Number of copies of this item to add: </label>
|
|
<input type="text" id="number_of_copies" name="number_of_copies" value="" size="2" />
|
|
<input type="submit" id="add_multiple_copies_submit" name="add_multiple_copies_submit" value="Add" onclick="javascript:return Check(this.form) && CheckMultipleAdd(this.form.number_of_copies.value);" /> <a href="#" id="cancel_add_multiple" class="cancel">Cancel</a>
|
|
<div class="hint"><p>The barcode you enter will be incremented for each additional item.</p></div>
|
|
</fieldset>
|
|
|
|
[% ELSE %]
|
|
[% IF op != 'add_item' %]
|
|
<input type="hidden" name="itemnumber" value="[% itemnumber | html %]" />
|
|
[% END %]
|
|
<input type="submit" value="Save changes" onclick="return Check(this.form)">
|
|
<input type="button" id="addnewitem" value="Add a new item">
|
|
<a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% biblio.biblionumber | uri %]">Cancel</a>
|
|
[% END %]</fieldset>
|
|
|
|
[%# Fields for fast cataloging %]
|
|
<input type="hidden" name="circborrowernumber" value="[% circborrowernumber | html %]" />
|
|
<input type="hidden" name="stickyduedate" value="[% stickyduedate | html %]" />
|
|
<input type="hidden" name="barcode" value="[% barcode | html %]" />
|
|
<input type="hidden" name="duedatespec" value="[% duedatespec | html %]" />
|
|
[%# End fields for fast cataloging %]
|
|
|
|
|
|
</form>
|
|
|
|
[% INCLUDE 'modals/cataloguing_create_av.inc' %]
|
|
|
|
</div> <!-- /#cataloguing_additem_newitem -->
|
|
</div> <!-- /.col-sm-10 -->
|
|
</div> <!-- /.row -->
|
|
</div> <!-- /#cataloguing_additem_itemlist -->
|
|
</main>
|
|
</div> <!-- /.col-sm-12 -->
|
|
</div> <!-- /.row -->
|
|
|
|
[% INCLUDE 'intranet-bottom.inc' %]
|