Bugzilla – Attachment 99123 Details for
Bug 18433
Allow to select results to export in item search
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 18433: Allow to select results to export in item search
Bug-18433-Allow-to-select-results-to-export-in-ite.patch (text/plain), 19.17 KB, created by
David Nind
on 2020-02-17 19:01:24 UTC
(
hide
)
Description:
Bug 18433: Allow to select results to export in item search
Filename:
MIME Type:
Creator:
David Nind
Created:
2020-02-17 19:01:24 UTC
Size:
19.17 KB
patch
obsolete
>From 236c49ddcd40f71d7a56c81ce3f446347091d0fe Mon Sep 17 00:00:00 2001 >From: Julian Maurice <julian.maurice@biblibre.com> >Date: Fri, 14 Apr 2017 15:45:04 +0200 >Subject: [PATCH] Bug 18433: Allow to select results to export in item search >MIME-Version: 1.0 >Content-Type: text/plain; charset=UTF-8 >Content-Transfer-Encoding: 8bit > >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 > >Followed test plan, works as expected. >Signed-off-by: Marc Véron <veron@veron.ch> > >Signed-off-by: David Nind <david@davidnind.com> >--- > catalogue/item-export.pl | 64 +++++++++++++ > catalogue/itemsearch.pl | 66 +------------ > .../en/includes/catalogue/itemsearch_item.csv.inc | 4 +- > .../en/includes/catalogue/itemsearch_item.json.inc | 9 +- > .../prog/en/modules/catalogue/itemsearch.tt | 104 +++++++++++++++++---- > 5 files changed, 163 insertions(+), 84 deletions(-) > create mode 100755 catalogue/item-export.pl > >diff --git a/catalogue/item-export.pl b/catalogue/item-export.pl >new file mode 100755 >index 0000000000..ef6aaa4b9f >--- /dev/null >+++ b/catalogue/item-export.pl >@@ -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*$|; >+} >diff --git a/catalogue/itemsearch.pl b/catalogue/itemsearch.pl >index a145149277..7acde61802 100755 >--- a/catalogue/itemsearch.pl >+++ b/catalogue/itemsearch.pl >@@ -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, >diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/catalogue/itemsearch_item.csv.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/catalogue/itemsearch_item.csv.inc >index f52e3a6934..63aaee8874 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/includes/catalogue/itemsearch_item.csv.inc >+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/catalogue/itemsearch_item.csv.inc >@@ -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 %]" >diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/catalogue/itemsearch_item.json.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/catalogue/itemsearch_item.json.inc >index 88ba5487cf..6b17cd62ea 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/includes/catalogue/itemsearch_item.json.inc >+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/catalogue/itemsearch_item.json.inc >@@ -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 %]", >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/itemsearch.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/itemsearch.tt >index ee1b43ea74..a9ad87d0c5 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/itemsearch.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/itemsearch.tt >@@ -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 () { >-- >2.11.0
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 18433
:
62170
|
62181
|
62358
|
62388
|
62389
|
62390
|
62415
|
62416
|
62417
|
62449
|
62472
|
95380
|
97479
|
99123
|
99124
|
99159
|
99160
|
99161
|
99162