Bug 18433: Allow to select results to export in item search
This adds a column of checkboxes in the results table to be able to select the items to be exported Test plan: 1. Go to item search and click 'Search' 2. Without checking any checkbox, verify that the export still works (it should export all results) 3. Tick some checkboxes and re-export, verify that only selected items are exported Signed-off-by: Marc Véron <veron@veron.ch> Signed-off-by: David Nind <david@davidnind.com> Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org> Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>
This commit is contained in:
parent
2dbcc0303a
commit
40219cf2a6
|
|
@ -0,0 +1,64 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
# Copyright 2017 BibLibre
|
||||
#
|
||||
# This file is part of Koha
|
||||
#
|
||||
# Koha is free software; you can redistribute it and/or modify it under the
|
||||
# terms of the GNU General Public License as published by the Free Software
|
||||
# Foundation; either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with Koha; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
use Modern::Perl;
|
||||
|
||||
use CGI;
|
||||
|
||||
use C4::Auth;
|
||||
use C4::Output;
|
||||
|
||||
my $cgi = new CGI;
|
||||
|
||||
my ($template, $borrowernumber, $cookie) = get_template_and_user({
|
||||
template_name => 'catalogue/itemsearch_csv.tt',
|
||||
query => $cgi,
|
||||
type => 'intranet',
|
||||
authnotrequired => 0,
|
||||
flagsrequired => { catalogue => 1 },
|
||||
});
|
||||
|
||||
my @itemnumbers = $cgi->multi_param('itemnumber');
|
||||
my $format = $cgi->param('format') // 'csv';
|
||||
|
||||
my @items = Koha::Items->search({ itemnumber => { -in => \@itemnumbers } });
|
||||
|
||||
if ($format eq 'barcodes') {
|
||||
print $cgi->header({
|
||||
type => 'text/plain',
|
||||
attachment => 'barcodes.txt',
|
||||
});
|
||||
|
||||
foreach my $item (@items) {
|
||||
print $item->barcode . "\n";
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
$template->param(
|
||||
results => \@items,
|
||||
);
|
||||
|
||||
print $cgi->header({
|
||||
type => 'text/csv',
|
||||
attachment => 'items.csv',
|
||||
});
|
||||
for my $line ( split '\n', $template->output ) {
|
||||
print "$line\n" unless $line =~ m|^\s*$|;
|
||||
}
|
||||
|
|
@ -97,13 +97,7 @@ my ($template, $borrowernumber, $cookie) = get_template_and_user({
|
|||
flagsrequired => { catalogue => 1 },
|
||||
});
|
||||
|
||||
my $mss = Koha::MarcSubfieldStructures->search({ frameworkcode => '', kohafield => 'items.notforloan', authorised_value => [ -and => {'!=' => undef }, {'!=' => ''}] });
|
||||
my $notforloan_values = $mss->count ? GetAuthorisedValues($mss->next->authorised_value) : [];
|
||||
|
||||
$mss = Koha::MarcSubfieldStructures->search({ frameworkcode => '', kohafield => 'items.location', authorised_value => [ -and => {'!=' => undef }, {'!=' => ''}] });
|
||||
my $location_values = $mss->count ? GetAuthorisedValues($mss->next->authorised_value) : [];
|
||||
|
||||
$mss = Koha::MarcSubfieldStructures->search({ frameworkcode => '', kohafield => 'items.itemlost', authorised_value => [ -and => {'!=' => undef }, {'!=' => ''}] });
|
||||
my $mss = Koha::MarcSubfieldStructures->search({ frameworkcode => '', kohafield => 'items.itemlost', authorised_value => [ -and => {'!=' => undef }, {'!=' => ''}] });
|
||||
my $itemlost_values = $mss->count ? GetAuthorisedValues($mss->next->authorised_value) : [];
|
||||
|
||||
$mss = Koha::MarcSubfieldStructures->search({ frameworkcode => '', kohafield => 'items.withdrawn', authorised_value => [ -and => {'!=' => undef }, {'!=' => ''}] });
|
||||
|
|
@ -227,38 +221,10 @@ if (scalar keys %params > 0) {
|
|||
}
|
||||
|
||||
if ($results) {
|
||||
# Get notforloan labels
|
||||
my $notforloan_map = {};
|
||||
foreach my $nfl_value (@$notforloan_values) {
|
||||
$notforloan_map->{$nfl_value->{authorised_value}} = $nfl_value->{lib};
|
||||
}
|
||||
|
||||
# Get location labels
|
||||
my $location_map = {};
|
||||
foreach my $loc_value (@$location_values) {
|
||||
$location_map->{$loc_value->{authorised_value}} = $loc_value->{lib};
|
||||
}
|
||||
|
||||
# Get itemlost labels
|
||||
my $itemlost_map = {};
|
||||
foreach my $il_value (@$itemlost_values) {
|
||||
$itemlost_map->{$il_value->{authorised_value}} = $il_value->{lib};
|
||||
}
|
||||
|
||||
# Get withdrawn labels
|
||||
my $withdrawn_map = {};
|
||||
foreach my $wd_value (@$withdrawn_values) {
|
||||
$withdrawn_map->{$wd_value->{authorised_value}} = $wd_value->{lib};
|
||||
}
|
||||
|
||||
foreach my $item (@$results) {
|
||||
my $biblio = Koha::Biblios->find( $item->{biblionumber} );
|
||||
$item->{biblio} = $biblio;
|
||||
$item->{biblioitem} = $biblio->biblioitem->unblessed;
|
||||
$item->{status} = $notforloan_map->{$item->{notforloan}};
|
||||
if (defined $item->{location}) {
|
||||
$item->{location} = $location_map->{$item->{location}};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -289,13 +255,6 @@ if (scalar keys %params > 0) {
|
|||
# Display the search form
|
||||
|
||||
my @branches = map { value => $_->branchcode, label => $_->branchname }, Koha::Libraries->search( {}, { order_by => 'branchname' } );
|
||||
my @locations;
|
||||
foreach my $location (@$location_values) {
|
||||
push @locations, {
|
||||
value => $location->{authorised_value},
|
||||
label => $location->{lib} // $location->{authorised_value},
|
||||
};
|
||||
}
|
||||
my @itemtypes;
|
||||
foreach my $itemtype ( Koha::ItemTypes->search ) {
|
||||
push @itemtypes, {
|
||||
|
|
@ -304,23 +263,10 @@ foreach my $itemtype ( Koha::ItemTypes->search ) {
|
|||
};
|
||||
}
|
||||
|
||||
$mss = Koha::MarcSubfieldStructures->search({ frameworkcode => '', kohafield => 'items.ccode', authorised_value => [ -and => {'!=' => undef }, {'!=' => ''}] });
|
||||
my $ccode_avcode = $mss->count ? $mss->next->authorised_value : 'CCODE';
|
||||
my $ccodes = GetAuthorisedValues($ccode_avcode);
|
||||
my @ccodes;
|
||||
foreach my $ccode (@$ccodes) {
|
||||
push @ccodes, {
|
||||
value => $ccode->{authorised_value},
|
||||
label => $ccode->{lib},
|
||||
};
|
||||
}
|
||||
|
||||
my @notforloans;
|
||||
foreach my $value (@$notforloan_values) {
|
||||
push @notforloans, {
|
||||
value => $value->{authorised_value},
|
||||
label => $value->{lib},
|
||||
};
|
||||
my @ccodes = Koha::AuthorisedValues->get_descriptions_by_koha_field({ kohafield => 'items.ccode' });
|
||||
foreach my $ccode (@ccodes) {
|
||||
$ccode->{value} = $ccode->{authorised_value},
|
||||
$ccode->{label} = $ccode->{lib},
|
||||
}
|
||||
|
||||
my @itemlosts;
|
||||
|
|
@ -350,10 +296,8 @@ foreach my $field (@items_search_fields) {
|
|||
|
||||
$template->param(
|
||||
branches => \@branches,
|
||||
locations => \@locations,
|
||||
itemtypes => \@itemtypes,
|
||||
ccodes => \@ccodes,
|
||||
notforloans => \@notforloans,
|
||||
itemlosts => \@itemlosts,
|
||||
withdrawns => \@withdrawns,
|
||||
items_search_fields => \@items_search_fields,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
[%- USE Branches -%]
|
||||
[%- USE Koha -%]
|
||||
[%- USE ItemTypes -%]
|
||||
[% USE AuthorisedValues %]
|
||||
[%- USE AuthorisedValues -%]
|
||||
[%- SET biblio = item.biblio -%]
|
||||
[%- SET biblioitem = item.biblioitem -%]
|
||||
"[% biblio.title | html %] [% IF ( Koha.Preference( 'marcflavour' ) == 'UNIMARC' && biblio.author ) %]by [% END %][% biblio.author | html %]", "[% (biblioitem.publicationyear || biblio.copyrightdate) | html %]", "[% biblioitem.publishercode | html %]", "[% AuthorisedValues.GetByCode( 'CCODE', item.ccode ) | html %]", "[% item.barcode | html %]", "[% item.itemcallnumber | html %]", "[% Branches.GetName(item.homebranch) | html %]", "[% Branches.GetName(item.holdingbranch) | html %]", "[% item.location | html %]", "[% ItemTypes.GetDescription(item.itype) | html %]", "[% item.stocknumber | html %]", "[% item.status | html %]","[% AuthorisedValues.GetByCode( 'LOST', item.itemlost ) || "" | html %]","[% AuthorisedValues.GetByCode( 'WITHDRAWN', item.withdrawn ) || "" | html %]", "[% (item.issues || 0) | html %]"
|
||||
"[% biblio.title | html %] [% IF ( Koha.Preference( 'marcflavour' ) == 'UNIMARC' && biblio.author ) %]by [% END %][% biblio.author | html %]", "[% (biblioitem.publicationyear || biblio.copyrightdate) | html %]", "[% biblioitem.publishercode | html %]", "[% AuthorisedValues.GetByCode( 'CCODE', item.ccode ) | html %]", "[% item.barcode | html %]", "[% item.itemcallnumber | html %]", "[% Branches.GetName(item.homebranch) | html %]", "[% Branches.GetName(item.holdingbranch) | html %]", "[% AuthorisedValues.GetDescriptionByKohaField(frameworkcode => biblio.frameworkcode, kohafield => 'items.location', authorised_value => item.location) | html %]", "[% ItemTypes.GetDescription(item.itype) | html %]", "[% item.stocknumber | html %]", "[% AuthorisedValues.GetDescriptionByKohaField(frameworkcode => biblio.frameworkcode, kohafield => 'items.notforloan', authorised_value => item.notforloan) | html %]","[% AuthorisedValues.GetByCode( 'LOST', item.itemlost ) || "" | html %]","[% AuthorisedValues.GetByCode( 'WITHDRAWN', item.withdrawn ) || "" | html %]", "[% (item.issues || 0) | html %]"
|
||||
|
|
|
|||
|
|
@ -2,11 +2,14 @@
|
|||
[%- USE Koha -%]
|
||||
[%- USE To -%]
|
||||
[%- USE ItemTypes -%]
|
||||
[% USE AuthorisedValues %]
|
||||
[%- USE AuthorisedValues -%]
|
||||
[%- biblio = item.biblio -%]
|
||||
[%- biblioitem = item.biblioitem -%]
|
||||
[
|
||||
"[% FILTER escape_quotes = replace('"', '\"') ~%]
|
||||
<input type="checkbox" name="itemnumber" value="[% item.itemnumber %]"/>
|
||||
[%~ END %]",
|
||||
"[% FILTER escape_quotes ~%]
|
||||
<a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% biblio.biblionumber | uri %]" title="Go to record detail page">[% biblio.title | html %]</a>[% IF ( Koha.Preference( 'marcflavour' ) == 'UNIMARC' && biblio.author ) %] by[% END %] [% biblio.author | html %]
|
||||
[%~ END %]",
|
||||
"[% (biblioitem.publicationyear || biblio.copyrightdate) | html %]",
|
||||
|
|
@ -18,10 +21,10 @@
|
|||
"[% item.itemcallnumber | html %]",
|
||||
"[% Branches.GetName(item.homebranch) | html %]",
|
||||
"[% Branches.GetName(item.holdingbranch) | html %]",
|
||||
"[% item.location | html %]",
|
||||
"[% AuthorisedValues.GetDescriptionByKohaField( frameworkcode => biblio.frameworkcode, kohafield => 'items.location', authorised_value => item.location) | html %]",
|
||||
"[% ItemTypes.GetDescription(item.itype) | html %]",
|
||||
"[% item.stocknumber | html %]",
|
||||
"[% item.status | html %]",
|
||||
"[% AuthorisedValues.GetDescriptionByKohaField( frameworkcode => biblio.frameworkcode, kohafield => 'items.notforloan', authorised_value => item.notforloan) | html %]",
|
||||
"[% AuthorisedValues.GetByCode( 'LOST', item.itemlost ) || "" | html %]",
|
||||
"[% AuthorisedValues.GetByCode( 'WITHDRAWN', item.withdrawn ) || "" | html %]",
|
||||
"[% (item.issues || 0) | html %]",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
[% USE raw %]
|
||||
[% USE To %]
|
||||
[% USE Asset %]
|
||||
[% USE AuthorisedValues %]
|
||||
|
||||
[% BLOCK form_label %]
|
||||
[% SWITCH label %]
|
||||
|
|
@ -110,6 +111,18 @@
|
|||
[%- To.json(escaped) | $raw -%]
|
||||
[%- END -%]
|
||||
|
||||
[% notforloans = AuthorisedValues.GetDescriptionsByKohaField({ kohafield = 'items.notforloan' }) %]
|
||||
[% FOREACH nfl IN notforloans %]
|
||||
[% nfl.value = nfl.authorised_value %]
|
||||
[% nfl.label = nfl.lib %]
|
||||
[% END %]
|
||||
|
||||
[% locations = AuthorisedValues.GetDescriptionsByKohaField({ kohafield = 'items.location' }) %]
|
||||
[% FOREACH loc IN locations %]
|
||||
[% loc.value = loc.authorised_value %]
|
||||
[% loc.label = loc.lib %]
|
||||
[% END %]
|
||||
|
||||
[%# Page starts here %]
|
||||
|
||||
[% SET footerjs = 1 %]
|
||||
|
|
@ -266,6 +279,7 @@
|
|||
function submitForm($form) {
|
||||
var tr = ''
|
||||
+ ' <tr>'
|
||||
+ ' <th id="items_checkbox"></th>'
|
||||
+ ' <th id="items_title">' + _("Title") + '</th>'
|
||||
+ ' <th id="items_pubdate">' + _("Publication date") + '</th>'
|
||||
+ ' <th id="items_publisher">' + _("Publisher") + '</th>'
|
||||
|
|
@ -301,38 +315,79 @@
|
|||
$('#item-search-block').show();
|
||||
});
|
||||
|
||||
function exportItems(format) {
|
||||
var itemnumbers = [];
|
||||
$('#results').find('input[name="itemnumber"]:checked').each(function() {
|
||||
itemnumbers.push($(this).val());
|
||||
});
|
||||
if (itemnumbers.length) {
|
||||
var href = '/cgi-bin/koha/catalogue/item-export.pl?format=' + format;
|
||||
href += '&itemnumber=' + itemnumbers.join('&itemnumber=');
|
||||
location = href;
|
||||
} else {
|
||||
$('#format-' + format).prop('checked', true);
|
||||
$('#itemsearchform').submit();
|
||||
$('#format-html').prop('checked', true);
|
||||
}
|
||||
}
|
||||
|
||||
var csvExportLink = $('<a>')
|
||||
.attr('href', '#')
|
||||
.html(_("Export results to CSV"))
|
||||
.addClass('btn btn-default btn-xs')
|
||||
.html("CSV")
|
||||
.on('click', function(e) {
|
||||
e.preventDefault();
|
||||
$('#format-csv').prop('checked', true);
|
||||
$('#itemsearchform').submit();
|
||||
$('#format-html').prop('checked', true);
|
||||
exportItems('csv');
|
||||
});
|
||||
var barcodesExportLink = $('<a>')
|
||||
.attr('href', '#')
|
||||
.html(_("Export results to barcodes file"))
|
||||
.addClass('btn btn-default btn-xs')
|
||||
.html(_("Barcodes file"))
|
||||
.on('click', function(e) {
|
||||
e.preventDefault();
|
||||
$('#format-barcodes').prop('checked', true);
|
||||
$('#itemsearchform').submit();
|
||||
$('#format-html').prop('checked', true);
|
||||
exportItems('barcodes');
|
||||
});
|
||||
|
||||
var editSearchAndExportLinks = $('<p>')
|
||||
.append(editSearchLink)
|
||||
.append(' | ')
|
||||
.append(csvExportLink)
|
||||
.append(' ')
|
||||
.append(barcodesExportLink);
|
||||
var exportButton = $('<div>')
|
||||
.addClass('btn-group')
|
||||
.append($('<button>')
|
||||
.addClass('btn btn-default btn-xs dropdown-toggle')
|
||||
.attr('id', 'export-button')
|
||||
.attr('data-toggle', 'dropdown')
|
||||
.attr('aria-haspopup', 'true')
|
||||
.attr('aria-expanded', 'false')
|
||||
.html(_("Export all results to") + ' <span class="caret"></span>'))
|
||||
.append($('<ul>')
|
||||
.addClass('dropdown-menu')
|
||||
.append($('<li>').append(csvExportLink))
|
||||
.append($('<li>').append(barcodesExportLink)));
|
||||
|
||||
var selectVisibleRows = $('<a>')
|
||||
.attr('href', '#')
|
||||
.append('<i class="fa fa-check"></i> ')
|
||||
.append(_("Select visible rows"))
|
||||
.on('click', function(e) {
|
||||
e.preventDefault();
|
||||
$('#results input[type="checkbox"]').prop('checked', true).change();
|
||||
});
|
||||
var clearSelection = $('<a>')
|
||||
.attr('href', '#')
|
||||
.append('<i class="fa fa-remove"></i> ')
|
||||
.append(_("Clear selection"))
|
||||
.on('click', function(e) {
|
||||
e.preventDefault();
|
||||
$('#results input[type="checkbox"]').prop('checked', false).change();
|
||||
});
|
||||
var exportLinks = $('<p>')
|
||||
.append(selectVisibleRows)
|
||||
.append(' ')
|
||||
.append(clearSelection)
|
||||
.append(' | ')
|
||||
.append(exportButton);
|
||||
|
||||
var results_heading = $('<div>').addClass('results-heading')
|
||||
.append("<h1>" + _("Item search results") + "</h1>")
|
||||
.append($('<p>').append(advSearchLink))
|
||||
.append(editSearchAndExportLinks);
|
||||
.append($('<p>').append(editSearchLink))
|
||||
.append(exportLinks);
|
||||
$('#results-wrapper').empty()
|
||||
.append(results_heading)
|
||||
.append(table);
|
||||
|
|
@ -369,7 +424,9 @@
|
|||
});
|
||||
},
|
||||
'sDom': '<"top pager"ilp>t<"bottom pager"ip>r',
|
||||
'aaSorting': [[1, 'asc']],
|
||||
'aoColumns': [
|
||||
{ 'sName': 'checkbox', 'bSortable': false },
|
||||
{ 'sName': 'title' },
|
||||
{ 'sName': 'publicationyear' },
|
||||
{ 'sName': 'publishercode' },
|
||||
|
|
@ -385,12 +442,13 @@
|
|||
{ 'sName': 'itemlost' },
|
||||
{ 'sName': 'withdrawn' },
|
||||
{ 'sName': 'issues' },
|
||||
{ 'sName': 'checkbox', 'bSortable': false }
|
||||
{ 'sName': 'actions', 'bSortable': false }
|
||||
],
|
||||
"sPaginationType": "full_numbers"
|
||||
})).columnFilter({
|
||||
'sPlaceHolder': 'head:after',
|
||||
'aoColumns': [
|
||||
null,
|
||||
{ 'type': 'text' },
|
||||
{ 'type': 'text' },
|
||||
{ 'type': 'text' },
|
||||
|
|
@ -433,6 +491,16 @@
|
|||
null
|
||||
]
|
||||
});
|
||||
|
||||
$('#results').on('change', 'input[type="checkbox"]', function() {
|
||||
var countSelected = $(this).parents('table').find('input:checked').length;
|
||||
var caret = ' <span class="caret">';
|
||||
if (countSelected > 0) {
|
||||
$('#export-button').html(_("Export selected results to") + caret);
|
||||
} else {
|
||||
$('#export-button').html(_("Export all results to") + caret);
|
||||
}
|
||||
});
|
||||
}
|
||||
var Sticky;
|
||||
$(document).ready(function () {
|
||||
|
|
|
|||
Loading…
Reference in New Issue