'required' => '1',
'min_ver' => '0.03',
},
+ 'Template::Plugin::JSON::Escape' => {
+ 'usage' => 'Core',
+ 'required' => '1',
+ 'min_ver' => '0.02',
+ },
'DBD::Mock' => {
'usage' => 'Core',
'required' => '1',
use Data::Dumper; # used as part of logging item record changes, not just for
# debugging; so please don't remove this
use Koha::DateUtils qw/dt_from_string/;
+use C4::SQLHelper qw(GetColumns);
use vars qw($VERSION @ISA @EXPORT);
GetAnalyticsCount
GetItemHolds
+ SearchItemsByField
SearchItems
PrepareItemrecordDisplay
return $holds;
}
-# Return the list of the column names of items table
-sub _get_items_columns {
- my $dbh = C4::Context->dbh;
- my $sth = $dbh->column_info(undef, undef, 'items', '%');
- $sth->execute;
- my $results = $sth->fetchall_hashref('COLUMN_NAME');
- return keys %$results;
+=head2 SearchItemsByField
+
+ my $items = SearchItemsByField($field, $value);
+
+SearchItemsByField will search for items on a specific given field.
+For instance you can search all items with a specific stocknumber like this:
+
+ my $items = SearchItemsByField('stocknumber', $stocknumber);
+
+=cut
+
+sub SearchItemsByField {
+ my ($field, $value) = @_;
+
+ my $filters = [ {
+ field => $field,
+ query => $value,
+ } ];
+
+ my ($results) = SearchItems($filters);
+ return $results;
+}
+
+sub _SearchItems_build_where_fragment {
+ my ($filter) = @_;
+
+ my $where_fragment;
+ if (exists($filter->{conjunction})) {
+ my (@where_strs, @where_args);
+ foreach my $f (@{ $filter->{filters} }) {
+ my $fragment = _SearchItems_build_where_fragment($f);
+ if ($fragment) {
+ push @where_strs, $fragment->{str};
+ push @where_args, @{ $fragment->{args} };
+ }
+ }
+ my $where_str = '';
+ if (@where_strs) {
+ $where_str = '(' . join (' ' . $filter->{conjunction} . ' ', @where_strs) . ')';
+ $where_fragment = {
+ str => $where_str,
+ args => \@where_args,
+ };
+ }
+ } else {
+ my @columns = GetColumns('items');
+ push @columns, GetColumns('biblio');
+ push @columns, GetColumns('biblioitems');
+ my @operators = qw(= != > < >= <= like);
+ my $field = $filter->{field};
+ if ( (0 < grep /^$field$/, @columns) or (substr($field, 0, 5) eq 'marc:') ) {
+ my $op = $filter->{operator};
+ my $query = $filter->{query};
+
+ if (!$op or (0 == grep /^$op$/, @operators)) {
+ $op = '='; # default operator
+ }
+
+ my $column;
+ if ($field =~ /^marc:(\d{3})(?:\$(\w))?$/) {
+ my $marcfield = $1;
+ my $marcsubfield = $2;
+ my $xpath;
+ if ($marcfield < 10) {
+ $xpath = "//record/controlfield[\@tag=\"$marcfield\"]";
+ } else {
+ $xpath = "//record/datafield[\@tag=\"$marcfield\"]/subfield[\@code=\"$marcsubfield\"]";
+ }
+ $column = "ExtractValue(marcxml, '$xpath')";
+ } else {
+ $column = $field;
+ }
+
+ if (ref $query eq 'ARRAY') {
+ if ($op eq '=') {
+ $op = 'IN';
+ } elsif ($op eq '!=') {
+ $op = 'NOT IN';
+ }
+ $where_fragment = {
+ str => "$column $op (" . join (',', ('?') x @$query) . ")",
+ args => $query,
+ };
+ } else {
+ $where_fragment = {
+ str => "$column $op ?",
+ args => [ $query ],
+ };
+ }
+ }
+ }
+
+ return $where_fragment;
}
=head2 SearchItems
- my $items = SearchItems($field, $value);
+ my ($items, $total) = SearchItemsByField($filters, $params);
-SearchItems will search for items on a specific given field.
-For instance you can search all items with a specific stocknumber like this:
+Perform a search among items
- my $items = SearchItems('stocknumber', $stocknumber);
+$filters is a reference to an array of filters, where each filter is a hash with
+the following keys:
+
+=over 2
+
+=item * field: the name of a SQL column in table items
+
+=item * query: the value to search in this column
+
+=item * operator: comparison operator. Can be one of = != > < >= <= like
+
+=back
+
+A logical AND is used to combine filters.
+
+$params is a reference to a hash that can contain the following parameters:
+
+=over 2
+
+=item * rows: Number of items to return. 0 returns everything (default: 0)
+
+=item * page: Page to return (return items from (page-1)*rows to (page*rows)-1)
+ (default: 1)
+
+=item * sortby: A SQL column name in items table to sort on
+
+=item * sortorder: 'ASC' or 'DESC'
+
+=back
=cut
sub SearchItems {
- my ($field, $value) = @_;
+ my ($filter, $params) = @_;
+
+ $filter //= {};
+ $params //= {};
+ return unless ref $filter eq 'HASH';
+ return unless ref $params eq 'HASH';
+
+ # Default parameters
+ $params->{rows} ||= 0;
+ $params->{page} ||= 1;
+ $params->{sortby} ||= 'itemnumber';
+ $params->{sortorder} ||= 'ASC';
+
+ my ($where_str, @where_args);
+ my $where_fragment = _SearchItems_build_where_fragment($filter);
+ if ($where_fragment) {
+ $where_str = $where_fragment->{str};
+ @where_args = @{ $where_fragment->{args} };
+ }
my $dbh = C4::Context->dbh;
- my @columns = _get_items_columns;
- my $results = [];
- if(0 < grep /^$field$/, @columns) {
- my $query = "SELECT $field FROM items WHERE $field = ?";
- my $sth = $dbh->prepare( $query );
- $sth->execute( $value );
- $results = $sth->fetchall_arrayref({});
+ my $query = q{
+ SELECT SQL_CALC_FOUND_ROWS items.*
+ FROM items
+ LEFT JOIN biblio ON biblio.biblionumber = items.biblionumber
+ LEFT JOIN biblioitems ON biblioitems.biblioitemnumber = items.biblioitemnumber
+ };
+ if (defined $where_str and $where_str ne '') {
+ $query .= qq{ WHERE $where_str };
}
- return $results;
+
+ my @columns = GetColumns('items');
+ push @columns, GetColumns('biblio');
+ push @columns, GetColumns('biblioitems');
+ my $sortby = (0 < grep {$params->{sortby} eq $_} @columns)
+ ? $params->{sortby} : 'itemnumber';
+ my $sortorder = (uc($params->{sortorder}) eq 'ASC') ? 'ASC' : 'DESC';
+ $query .= qq{ ORDER BY $sortby $sortorder };
+
+ my $rows = $params->{rows};
+ my @limit_args;
+ if ($rows > 0) {
+ my $offset = $rows * ($params->{page}-1);
+ $query .= qq { LIMIT ?, ? };
+ push @limit_args, $offset, $rows;
+ }
+
+ my $sth = $dbh->prepare($query);
+ my $rv = $sth->execute(@where_args, @limit_args);
+
+ return unless ($rv);
+ my ($total_rows) = $dbh->selectrow_array(q{ SELECT FOUND_ROWS() });
+
+ return ($sth->fetchall_arrayref({}), $total_rows);
}
UpdateInTable
GetPrimaryKeys
clear_columns_cache
+ GetColumns
);
%EXPORT_TAGS = ( all =>[qw( InsertInTable DeleteInTable SearchInTable UpdateInTable GetPrimaryKeys)]
);
return $hashref->{$tablename};
}
+=head2 GetColumns
+
+ my @columns = GetColumns($tablename);
+
+Given a tablename, returns an array of columns names.
+
+=cut
+
+sub GetColumns {
+ my ($tablename) = @_;
+
+ return unless $tablename;
+ return unless $tablename =~ /^[a-zA-Z0-9_]+$/;
+
+ # Get the database handle.
+ my $dbh = C4::Context->dbh;
+
+ # Pure ANSI SQL goodness.
+ my $sql = "SELECT * FROM $tablename WHERE 1=0;";
+
+ # Run the SQL statement to load STH's readonly properties.
+ my $sth = $dbh->prepare($sql);
+ my $rv = $sth->execute();
+
+ my @data;
+ if ($rv) {
+ @data = @{$sth->{NAME}};
+ }
+
+ return @data;
+}
+
=head2 _filter_columns
=over 4
--- /dev/null
+package Koha::Item::Search::Field;
+
+use Modern::Perl;
+use base qw( Exporter );
+
+our @EXPORT_OK = qw(
+ AddItemSearchField
+ ModItemSearchField
+ DelItemSearchField
+ GetItemSearchField
+ GetItemSearchFields
+);
+
+use C4::Context;
+
+sub AddItemSearchField {
+ my ($field) = @_;
+
+ my ( $name, $label, $tagfield, $tagsubfield, $av_category ) =
+ @$field{qw(name label tagfield tagsubfield authorised_values_category)};
+
+ my $dbh = C4::Context->dbh;
+ my $query = q{
+ INSERT INTO items_search_fields (name, label, tagfield, tagsubfield, authorised_values_category)
+ VALUES (?, ?, ?, ?, ?)
+ };
+ my $sth = $dbh->prepare($query);
+ my $rv = $sth->execute($name, $label, $tagfield, $tagsubfield, $av_category);
+
+ return ($rv) ? $field : undef;
+}
+
+sub ModItemSearchField {
+ my ($field) = @_;
+
+ my ( $name, $label, $tagfield, $tagsubfield, $av_category ) =
+ @$field{qw(name label tagfield tagsubfield authorised_values_category)};
+
+ my $dbh = C4::Context->dbh;
+ my $query = q{
+ UPDATE items_search_fields
+ SET label = ?,
+ tagfield = ?,
+ tagsubfield = ?,
+ authorised_values_category = ?
+ WHERE name = ?
+ };
+ my $sth = $dbh->prepare($query);
+ my $rv = $sth->execute($label, $tagfield, $tagsubfield, $av_category, $name);
+
+ return ($rv) ? $field : undef;
+}
+
+sub DelItemSearchField {
+ my ($name) = @_;
+
+ my $dbh = C4::Context->dbh;
+ my $query = q{
+ DELETE FROM items_search_fields
+ WHERE name = ?
+ };
+ my $sth = $dbh->prepare($query);
+ my $rv = $sth->execute($name);
+
+ my $is_deleted = $rv ? int($rv) : 0;
+ if (!$is_deleted) {
+ warn "DelItemSearchField: Field '$name' doesn't exist";
+ }
+
+ return $is_deleted;
+}
+
+sub GetItemSearchField {
+ my ($name) = @_;
+
+ my $dbh = C4::Context->dbh;
+ my $query = q{
+ SELECT * FROM items_search_fields
+ WHERE name = ?
+ };
+ my $sth = $dbh->prepare($query);
+ my $rv = $sth->execute($name);
+
+ my $field;
+ if ($rv) {
+ $field = $sth->fetchrow_hashref;
+ }
+
+ return $field;
+}
+
+sub GetItemSearchFields {
+ my $dbh = C4::Context->dbh;
+ my $query = q{
+ SELECT * FROM items_search_fields
+ };
+ my $sth = $dbh->prepare($query);
+ my $rv = $sth->execute();
+
+ my @fields;
+ if ($rv) {
+ my $fields = $sth->fetchall_arrayref( {} );
+ @fields = @$fields;
+ }
+
+ return @fields;
+}
my $r = {};
my $i = 0;
for ( my $i=0; $i<@field; $i++ ) {
- my $items = C4::Items::SearchItems($field[$i], $value[$i]);
+ my $items = C4::Items::SearchItemsByField($field[$i], $value[$i]);
if ( @$items ) {
push @{ $r->{$field[$i]} }, $value[$i];
--- /dev/null
+#!/usr/bin/perl
+# Copyright 2013 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;
+use C4::Koha;
+
+use Koha::Item::Search::Field qw(GetItemSearchField ModItemSearchField);
+
+my $cgi = new CGI;
+
+my ($template, $borrowernumber, $cookie) = get_template_and_user({
+ template_name => 'admin/items_search_field.tt',
+ query => $cgi,
+ type => 'intranet',
+ authnotrequired => 0,
+ flagsrequired => { catalogue => 1 },
+});
+
+my $op = $cgi->param('op') || '';
+my $name = $cgi->param('name');
+
+if ($op eq 'mod') {
+ my %vars = $cgi->Vars;
+ my $field = { name => $name };
+ my @params = qw(label tagfield tagsubfield authorised_values_category);
+ @$field{@params} = @vars{@params};
+ if ( $field->{authorised_values_category} eq '' ) {
+ $field->{authorised_values_category} = undef;
+ }
+ $field = ModItemSearchField($field);
+ my $updated = ($field) ? 1 : 0;
+ print $cgi->redirect('/cgi-bin/koha/admin/items_search_fields.pl?updated=' . $updated);
+ exit;
+}
+
+my $field = GetItemSearchField($name);
+my $authorised_values_categories = C4::Koha::GetAuthorisedValueCategories();
+
+$template->param(
+ field => $field,
+ authorised_values_categories => $authorised_values_categories,
+);
+
+output_html_with_http_headers $cgi, $cookie, $template->output;
--- /dev/null
+#!/usr/bin/perl
+# Copyright 2013 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;
+use C4::Koha;
+
+use Koha::Item::Search::Field qw(AddItemSearchField GetItemSearchFields DelItemSearchField);
+
+my $cgi = new CGI;
+
+my ($template, $borrowernumber, $cookie) = get_template_and_user({
+ template_name => 'admin/items_search_fields.tt',
+ query => $cgi,
+ type => 'intranet',
+ authnotrequired => 0,
+ flagsrequired => { catalogue => 1 },
+});
+
+my $op = $cgi->param('op') || '';
+
+if ($op eq 'add') {
+ my %vars = $cgi->Vars;
+ my $field;
+ my @params = qw(name label tagfield tagsubfield authorised_values_category);
+ @$field{@params} = @vars{@params};
+ if ( $field->{authorised_values_category} eq '' ) {
+ $field->{authorised_values_category} = undef;
+ }
+ $field = AddItemSearchField($field);
+ if ($field) {
+ $template->param(field_added => $field);
+ } else {
+ $template->param(field_not_added => 1);
+ }
+} elsif ($op eq 'del') {
+ my $name = $cgi->param('name');
+ my $rv = DelItemSearchField($name);
+ if ($rv) {
+ $template->param(field_deleted => 1);
+ } else {
+ $template->param(field_not_deleted => 1);
+ }
+} else {
+ my $updated = $cgi->param('updated');
+ if (defined $updated) {
+ if ($updated) {
+ $template->param(field_updated => 1);
+ } else {
+ $template->param(field_not_updated => 1);
+ }
+ }
+}
+
+my @fields = GetItemSearchFields();
+my $authorised_values_categories = C4::Koha::GetAuthorisedValueCategories();
+
+$template->param(
+ fields => \@fields,
+ authorised_values_categories => $authorised_values_categories,
+);
+
+output_html_with_http_headers $cgi, $cookie, $template->output;
--- /dev/null
+#!/usr/bin/perl
+# Copyright 2013 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 JSON;
+
+use C4::Auth;
+use C4::Output;
+use C4::Items;
+use C4::Biblio;
+use C4::Branch;
+use C4::Koha;
+use C4::ItemType;
+
+use Koha::Item::Search::Field qw(GetItemSearchFields);
+
+my $cgi = new CGI;
+my %params = $cgi->Vars;
+
+my $format = $cgi->param('format');
+my ($template_name, $content_type);
+if (defined $format and $format eq 'json') {
+ $template_name = 'catalogue/itemsearch.json.tt';
+ $content_type = 'json';
+
+ # Map DataTables parameters with 'regular' parameters
+ $cgi->param('rows', $cgi->param('iDisplayLength'));
+ $cgi->param('page', ($cgi->param('iDisplayStart') / $cgi->param('iDisplayLength')) + 1);
+ my @columns = split /,/, $cgi->param('sColumns');
+ $cgi->param('sortby', $columns[ $cgi->param('iSortCol_0') ]);
+ $cgi->param('sortorder', $cgi->param('sSortDir_0'));
+
+ my @f = $cgi->param('f');
+ my @q = $cgi->param('q');
+ push @q, '' if @q == 0;
+ my @op = $cgi->param('op');
+ my @c = $cgi->param('c');
+ foreach my $i (0 .. ($cgi->param('iColumns') - 1)) {
+ my $sSearch = $cgi->param("sSearch_$i");
+ if ($sSearch) {
+ my @words = split /\s+/, $sSearch;
+ foreach my $word (@words) {
+ push @f, $columns[$i];
+ push @q, "%$word%";
+ push @op, 'like';
+ push @c, 'and';
+ }
+ }
+ }
+ $cgi->param('f', @f);
+ $cgi->param('q', @q);
+ $cgi->param('op', @op);
+ $cgi->param('c', @c);
+} elsif (defined $format and $format eq 'csv') {
+ $template_name = 'catalogue/itemsearch.csv.tt';
+
+ # Retrieve all results
+ $cgi->param('rows', 0);
+} else {
+ $format = 'html';
+ $template_name = 'catalogue/itemsearch.tt';
+ $content_type = 'html';
+}
+
+my ($template, $borrowernumber, $cookie) = get_template_and_user({
+ template_name => $template_name,
+ query => $cgi,
+ type => 'intranet',
+ authnotrequired => 0,
+ flagsrequired => { catalogue => 1 },
+});
+
+my $notforloan_avcode = GetAuthValCode('items.notforloan');
+my $notforloan_values = GetAuthorisedValues($notforloan_avcode);
+
+if (scalar keys %params > 0) {
+ # Parameters given, it's a search
+
+ my $filter = {
+ conjunction => 'AND',
+ filters => [],
+ };
+
+ foreach my $p (qw(homebranch location itype ccode issues datelastborrowed)) {
+ if (my @q = $cgi->param($p)) {
+ if ($q[0] ne '') {
+ my $f = {
+ field => $p,
+ query => \@q,
+ };
+ if (my $op = $cgi->param($p . '_op')) {
+ $f->{operator} = $op;
+ }
+ push @{ $filter->{filters} }, $f;
+ }
+ }
+ }
+
+ my @c = $cgi->param('c');
+ my @fields = $cgi->param('f');
+ my @q = $cgi->param('q');
+ my @op = $cgi->param('op');
+
+ my $f;
+ for (my $i = 0; $i < @fields; $i++) {
+ my $field = $fields[$i];
+ my $q = shift @q;
+ my $op = shift @op;
+ if (defined $q and $q ne '') {
+ if ($i == 0) {
+ $f = {
+ field => $field,
+ query => $q,
+ operator => $op,
+ };
+ } else {
+ my $c = shift @c;
+ $f = {
+ conjunction => $c,
+ filters => [
+ $f, {
+ field => $field,
+ query => $q,
+ operator => $op,
+ }
+ ],
+ };
+ }
+ }
+ }
+ push @{ $filter->{filters} }, $f;
+
+ # Yes/No parameters
+ foreach my $p (qw(damaged itemlost)) {
+ my $v = $cgi->param($p) // '';
+ my $f = {
+ field => $p,
+ query => 0,
+ };
+ if ($v eq 'yes') {
+ $f->{operator} = '!=';
+ push @{ $filter->{filters} }, $f;
+ } elsif ($v eq 'no') {
+ $f->{operator} = '=';
+ push @{ $filter->{filters} }, $f;
+ }
+ }
+
+ if (my $itemcallnumber_from = $cgi->param('itemcallnumber_from')) {
+ push @{ $filter->{filters} }, {
+ field => 'itemcallnumber',
+ query => $itemcallnumber_from,
+ operator => '>=',
+ };
+ }
+ if (my $itemcallnumber_to = $cgi->param('itemcallnumber_to')) {
+ push @{ $filter->{filters} }, {
+ field => 'itemcallnumber',
+ query => $itemcallnumber_to,
+ operator => '<=',
+ };
+ }
+
+ my $search_params = {
+ rows => $cgi->param('rows') // 20,
+ page => $cgi->param('page') || 1,
+ sortby => $cgi->param('sortby') || 'itemnumber',
+ sortorder => $cgi->param('sortorder') || 'asc',
+ };
+
+ my ($results, $total_rows) = SearchItems($filter, $search_params);
+ if ($results) {
+ # Get notforloan labels
+ my $notforloan_map = {};
+ foreach my $nfl_value (@$notforloan_values) {
+ $notforloan_map->{$nfl_value->{authorised_value}} = $nfl_value->{lib};
+ }
+
+ foreach my $item (@$results) {
+ $item->{biblio} = GetBiblio($item->{biblionumber});
+ ($item->{biblioitem}) = GetBiblioItemByBiblioNumber($item->{biblionumber});
+ $item->{status} = $notforloan_map->{$item->{notforloan}};
+ }
+ }
+
+ $template->param(
+ filter => $filter,
+ search_params => $search_params,
+ results => $results,
+ total_rows => $total_rows,
+ search_done => 1,
+ );
+
+ if ($format eq 'html') {
+ # Build pagination bar
+ my $url = $cgi->url(-absolute => 1);
+ my @params;
+ foreach my $p (keys %params) {
+ my @v = $cgi->param($p);
+ push @params, map { "$p=" . $_ } @v;
+ }
+ $url .= '?' . join ('&', @params);
+ my $nb_pages = 1 + int($total_rows / $search_params->{rows});
+ my $current_page = $search_params->{page};
+ my $pagination_bar = pagination_bar($url, $nb_pages, $current_page, 'page');
+
+ $template->param(pagination_bar => $pagination_bar);
+ }
+}
+
+if ($format eq 'html') {
+ # Retrieve data required for the form.
+
+ my $branches = GetBranches();
+ my @branches;
+ foreach my $branchcode (keys %$branches) {
+ push @branches, {
+ value => $branchcode,
+ label => $branches->{$branchcode}->{branchname},
+ };
+ }
+ my $locations = GetAuthorisedValues('LOC');
+ my @locations;
+ foreach my $location (@$locations) {
+ push @locations, {
+ value => $location->{authorised_value},
+ label => $location->{lib},
+ };
+ }
+ my @itemtypes = C4::ItemType->all();
+ foreach my $itemtype (@itemtypes) {
+ $itemtype->{value} = $itemtype->{itemtype};
+ $itemtype->{label} = $itemtype->{description};
+ }
+ my $ccode_avcode = GetAuthValCode('items.ccode') || '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 @items_search_fields = GetItemSearchFields();
+
+ my $authorised_values = {};
+ foreach my $field (@items_search_fields) {
+ if (my $category = ($field->{authorised_values_category})) {
+ $authorised_values->{$category} = GetAuthorisedValues($category);
+ }
+ }
+
+ $template->param(
+ branches => \@branches,
+ locations => \@locations,
+ itemtypes => \@itemtypes,
+ ccodes => \@ccodes,
+ notforloans => \@notforloans,
+ items_search_fields => \@items_search_fields,
+ authorised_values_json => to_json($authorised_values),
+ );
+}
+
+if ($format eq 'csv') {
+ print $cgi->header({
+ type => 'text/csv',
+ attachment => 'items.csv',
+ });
+ print $template->output;
+} else {
+ output_with_http_headers $cgi, $cookie, $template->output, $content_type;
+}
PRIMARY KEY(module, page, tablename, columnname)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+--
+-- Table structure for table 'items_search_fields'
+--
+
+DROP TABLE IF EXISTS items_search_fields;
+CREATE TABLE items_search_fields (
+ name VARCHAR(255) NOT NULL,
+ label VARCHAR(255) NOT NULL,
+ tagfield CHAR(3) NOT NULL,
+ tagsubfield CHAR(1) NULL DEFAULT NULL,
+ authorised_values_category VARCHAR(16) NULL DEFAULT NULL,
+ PRIMARY KEY(name),
+ CONSTRAINT items_search_fields_authorised_values_category
+ FOREIGN KEY (authorised_values_category) REFERENCES authorised_values (category)
+ ON DELETE SET NULL ON UPDATE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
SetVersion($DBversion);
}
+$DBversion = "3.17.00.XXX";
+if ( CheckVersion($DBversion) ) {
+ $dbh->do(q{
+ CREATE TABLE IF NOT EXISTS items_search_fields (
+ name VARCHAR(255) NOT NULL,
+ label VARCHAR(255) NOT NULL,
+ tagfield CHAR(3) NOT NULL,
+ tagsubfield CHAR(1) NULL DEFAULT NULL,
+ authorised_values_category VARCHAR(16) NULL DEFAULT NULL,
+ PRIMARY KEY(name),
+ CONSTRAINT items_search_fields_authorised_values_category
+ FOREIGN KEY (authorised_values_category) REFERENCES authorised_values (category)
+ ON DELETE SET NULL ON UPDATE CASCADE
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+ });
+ print "Upgrade to $DBversion done (Bug 11425: Add items_search_fields table)\n";
+ SetVersion($DBversion);
+}
+
=head1 FUNCTIONS
=head2 TableExists($table)
--- /dev/null
+.form-field {
+ margin: 5px 0;
+}
+
+.form-field > * {
+ vertical-align: middle;
+}
+
+.form-field-label {
+ display: inline-block;
+ text-align: right;
+ width: 10em;
+}
+
+.form-field-conjunction[disabled] {
+ visibility: hidden;
+}
+
+.form-field-radio > * {
+ vertical-align: middle;
+}
+
+.form-actions {
+ margin-top: 20px;
+}
+
+th.active {
+ padding-right: 21px;
+ background-repeat: no-repeat;
+ background-position: 100% 50%;
+}
+
+th.sort-asc {
+ background-image: url('../../img/asc.gif');
+}
+
+th.sort-desc {
+ background-image: url('../../img/desc.gif');
+}
+
+th select {
+ width: 100%;
+ font-weight: normal;
+}
--- /dev/null
+<ul>
+ <li>
+ <label for="name">Name</label>
+ [% IF field %]
+ <input type="text" name="name" value="[% field.name %]" disabled="disabled">
+ <input type="hidden" name="name" value="[% field.name %]">
+ [% ELSE %]
+ <input type="text" name="name" />
+ [% END %]
+ </li>
+ <li>
+ <label for="label">Label</label>
+ [% IF field %]
+ <input type="text" name="label" value="[% field.label %]" />
+ [% ELSE %]
+ <input type="text" name="label" />
+ [% END %]
+ </li>
+ <li>
+ <label for="tagfield">MARC field</label>
+ <select name="tagfield">
+ [% FOREACH tagfield IN ['001'..'999'] %]
+ [% IF field && field.tagfield == tagfield %]
+ <option value="[% tagfield %]" selected="selected">[% tagfield %]</option>
+ [% ELSE %]
+ <option value="[% tagfield %]">[% tagfield %]</option>
+ [% END %]
+ [% END %]
+ </select>
+ </li>
+ <li>
+ <label for="tagsubfield">MARC subfield</label>
+ <select name="tagsubfield">
+ [% codes = [''] %]
+ [% codes = codes.merge([0..9], ['a'..'z']) %]
+ [% FOREACH tagsubfield IN codes %]
+ [% IF field && field.tagsubfield == tagsubfield %]
+ <option value="[% tagsubfield %]" selected="selected">[% tagsubfield %]</option>
+ [% ELSE %]
+ <option value="[% tagsubfield %]">[% tagsubfield %]</option>
+ [% END %]
+ [% END %]
+ </select>
+ </li>
+ <li>
+ <label for="authorised_values_category">Authorised values category</label>
+ <select name="authorised_values_category">
+ <option value="">- None -</option>
+ [% FOREACH category IN authorised_values_categories %]
+ [% IF field && field.authorised_values_category == category %]
+ <option value="[% category %]" selected="selected">[% category %]</option>
+ [% ELSE %]
+ <option value="[% category %]">[% category %]</option>
+ [% END %]
+ [% END %]
+ </select>
+ </li>
+</ul>
<li><a href="/cgi-bin/koha/admin/classsources.pl">Classification sources</a></li>
<li><a href="/cgi-bin/koha/admin/matching-rules.pl">Record matching rules</a></li>
<li><a href="/cgi-bin/koha/admin/oai_sets.pl">OAI sets configuration</a></li>
+ <li><a href="/cgi-bin/koha/admin/items_search_fields.pl">Items search fields</a></li>
</ul>
<h5>Acquisition parameters</h5>
--- /dev/null
+[%- USE Branches -%]
+[%- biblio = item.biblio -%]
+[%- biblioitem = item.biblioitem -%]
+"[% biblio.title |html %] by [% biblio.author |html %]", "[% biblioitem.publicationyear |html %]", "[% biblioitem.publishercode |html %]", "[% biblioitem.collectiontitle |html %]", "[% item.barcode |html %]", "[% item.itemcallnumber |html %]", "[% Branches.GetName(item.homebranch) |html %]", "[% Branches.GetName(item.holdingbranch) |html %]", "[% item.location |html %]", "[% item.stocknumber |html %]", "[% item.status |html %]", "[% (item.issues || 0) |html %]"
--- /dev/null
+[%- USE Branches -%]
+[% biblio = item.biblio %]
+[% biblioitem = item.biblioitem %]
+<tr>
+ <td>
+ <a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% biblio.biblionumber %]" title="Go to record detail page">[% biblio.title %]</a>
+ by [% biblio.author %]
+ </td>
+ <td>[% biblioitem.publicationyear %]</td>
+ <td>[% biblioitem.publishercode %]</td>
+ <td>[% biblioitem.collectiontitle %]</td>
+ <td>
+ <a href="/cgi-bin/koha/catalogue/moredetail.pl?biblionumber=[% biblio.biblionumber %]#item[% item.itemnumber %]" title="Go to item details">[% item.barcode %]</a>
+ </td>
+ <td>[% item.itemcallnumber %]</td>
+ <td>[% Branches.GetName(item.homebranch) %]</td>
+ <td>[% Branches.GetName(item.holdingbranch) %]</td>
+ <td>[% item.location %]</td>
+ <td>[% item.stocknumber %]</td>
+ <td>[% item.status %]</td>
+ <td>[% item.issues || 0 %]</td>
+ <td><a href="/cgi-bin/koha/cataloguing/additem.pl?op=edititem&biblionumber=[% item.biblionumber %]&itemnumber=[% item.itemnumber %]">Modify</a></td>
+</tr>
--- /dev/null
+[%- USE Branches -%]
+[%- biblio = item.biblio -%]
+[%- biblioitem = item.biblioitem -%]
+[
+ "<a href='/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% biblio.biblionumber %]' title='Go to record detail page'>[% biblio.title |html %]</a> by [% biblio.author |html %]",
+ "[% biblioitem.publicationyear |html %]",
+ "[% biblioitem.publishercode |html %]",
+ "[% biblioitem.collectiontitle |html %]",
+ "<a href='/cgi-bin/koha/catalogue/moredetail.pl?biblionumber=[% biblio.biblionumber %]#item[% item.itemnumber %]' title='Go to item details'>[% item.barcode |html %]</a>",
+ "[% item.itemcallnumber |html %]",
+ "[% Branches.GetName(item.homebranch) |html %]",
+ "[% Branches.GetName(item.holdingbranch) |html %]",
+ "[% item.location |html %]",
+ "[% item.stocknumber |html %]",
+ "[% item.status |html %]",
+ "[% (item.issues || 0) |html %]",
+ "<a href='/cgi-bin/koha/cataloguing/additem.pl?op=edititem&biblionumber=[% item.biblionumber %]&itemnumber=[% item.itemnumber %]'>Modify</a>"
+]
--- /dev/null
+[% names = CGI.param() %]
+[% params = [] %]
+[% FOREACH name IN names %]
+ [% IF name != 'sortby' AND name != 'sortorder' %]
+ [% params.push(name _ "=" _ CGI.param(name)) %]
+ [% END %]
+[% END %]
+[% base_url = "/cgi-bin/koha/catalogue/itemsearch.pl?" _ params.join('&') %]
+
+[% BLOCK itemsearch_header %]
+ [% sortorder = 'asc' %]
+ [% classes = [] %]
+ [% IF CGI.param('sortby') == name %]
+ [% classes.push('active') %]
+ [% classes.push('sort-' _ CGI.param('sortorder')) %]
+ [% IF CGI.param('sortorder') == 'asc' %]
+ [% sortorder = 'desc' %]
+ [% END %]
+ [% END %]
+ [% url = base_url _ '&sortby=' _ name _ '&sortorder=' _ sortorder %]
+ <th class="[% classes.join(' ') %]">
+ <a href="[% url %]" title="Sort on [% label %] ([% sortorder %])">[% text %]</a>
+ </th>
+[% END %]
+
+<table>
+ <thead>
+ <tr>
+ [% INCLUDE itemsearch_header name='title' label='title' text='Bibliographic reference' %]
+ [% INCLUDE itemsearch_header name='publicationyear' label='publication date' text='Publication date' %]
+ [% INCLUDE itemsearch_header name='publishercode' label='publisher' text='Publisher' %]
+ [% INCLUDE itemsearch_header name='collectiontitle' label='collection' text='Collection' %]
+ [% INCLUDE itemsearch_header name='barcode' label='barcode' text='Barcode' %]
+ [% INCLUDE itemsearch_header name='itemcallnumber' label='callnumber' text='Callnumber' %]
+ [% INCLUDE itemsearch_header name='homebranch' label='home branch' text='Home branch' %]
+ [% INCLUDE itemsearch_header name='holdingbranch' label='holding branch' text='Holding branch' %]
+ [% INCLUDE itemsearch_header name='location' label='location' text='Location' %]
+ [% INCLUDE itemsearch_header name='stocknumber' label='stock number' text='Stock number' %]
+ [% INCLUDE itemsearch_header name='notforloan' label='status' text='Status' %]
+ [% INCLUDE itemsearch_header name='issues' label='issues' text='Issues' %]
+ <th></th>
+ </tr>
+ </thead>
+ <tbody>
+ [% FOREACH item IN items %]
+ [% INCLUDE 'catalogue/itemsearch_item.inc' item = item %]
+ [% END %]
+ </tbody>
+</table>
<dd>Manage rules for automatically matching MARC records during record imports.</dd>
<dt><a href="/cgi-bin/koha/admin/oai_sets.pl">OAI sets configuration</a></dt>
<dd>Manage OAI Sets</dd>
+ <dt><a href="/cgi-bin/koha/admin/items_search_fields.pl">Items search fields</a></dt>
+ <dd>Manage custom fields for items search</dd>
</dl>
<h3>Acquisition parameters</h3>
--- /dev/null
+[% INCLUDE 'doc-head-open.inc' %]
+ <title>Koha › Administration › Items search fields</title>
+ [% INCLUDE 'doc-head-close.inc' %]
+</head>
+<body id="admin_itemssearchfields" class="admin">
+ [% INCLUDE 'header.inc' %]
+ [% INCLUDE 'cat-search.inc' %]
+ <div id="breadcrumbs">
+ <a href="/cgi-bin/koha/mainpage.pl">Home</a> ›
+ <a href="/cgi-bin/koha/admin/admin-home.pl">Administration</a> ›
+ <a href="/cgi-bin/koha/admin/items_search_fields.pl">Items search fields</a> ›
+ [% field.name %]
+ </div>
+
+ <div id="doc3" class="yui-t2">
+ <div id="bd">
+ <div id="yui-main">
+ <div class="yui-b">
+ <h1>Items search field: [% field.label %]</h1>
+
+ <form action="" method="POST">
+ <fieldset class="rows">
+ <legend>Edit field</legend>
+ [% INCLUDE 'admin-items-search-field-form.inc' field=field %]
+ <div>
+ <input type="hidden" name="op" value="mod" />
+ </div>
+ <fieldset class="action">
+ <input type="submit" value="Update" />
+ </fieldset>
+ </fieldset>
+ </form>
+ <a href="/cgi-bin/koha/admin/items_search_fields.pl">Return to items search fields overview page</a>
+ </div>
+ </div>
+ <div class="yui-b">
+ [% INCLUDE 'admin-menu.inc' %]
+ </div>
+ </div>
+
+ [% INCLUDE 'intranet-bottom.inc' %]
--- /dev/null
+[% INCLUDE 'doc-head-open.inc' %]
+ <title>Koha › Administration › Items search fields</title>
+ [% INCLUDE 'doc-head-close.inc' %]
+</head>
+<body id="admin_itemssearchfields" class="admin">
+ [% INCLUDE 'header.inc' %]
+ [% INCLUDE 'cat-search.inc' %]
+ <div id="breadcrumbs">
+ <a href="/cgi-bin/koha/mainpage.pl">Home</a> ›
+ <a href="/cgi-bin/koha/admin/admin-home.pl">Administration</a> ›
+ Items search fields
+ </div>
+
+ <div id="doc3" class="yui-t2">
+ <div id="bd">
+ <div id="yui-main">
+ <div class="yui-b">
+ [% IF field_added %]
+ <div class="dialog">
+ Field successfully added: [% field_added.label %]
+ </div>
+ [% ELSIF field_not_added %]
+ <div class="alert">
+ <p>Failed to add field. Please check if the field name doesn't already exist.</p>
+ <p>Check logs for more details.</p>
+ </div>
+ [% ELSIF field_deleted %]
+ <div class="dialog">
+ Field successfully deleted.
+ </div>
+ [% ELSIF field_not_deleted %]
+ <div class="alert">
+ <p>Failed to delete field.</p>
+ <p>Check logs for more details.</p>
+ </div>
+ [% ELSIF field_updated %]
+ <div class="dialog">
+ Field successfully updated: [% field_updated.label %]
+ </div>
+ [% ELSIF field_not_updated %]
+ <div class="alert">
+ <p>Failed to update field.</p>
+ <p>Check logs for more details.</p>
+ </div>
+ [% END %]
+ <h1>Items search fields</h1>
+ [% IF fields.size %]
+ <table>
+ <thead>
+ <tr>
+ <th>Name</th>
+ <th>Label</th>
+ <th>MARC field</th>
+ <th>MARC subfield</th>
+ <th>Authorised values category</th>
+ <th>Operations</th>
+ </tr>
+ </thead>
+ <tbody>
+ [% FOREACH field IN fields %]
+ <tr>
+ <td>[% field.name %]</td>
+ <td>[% field.label %]</td>
+ <td>[% field.tagfield %]</td>
+ <td>[% field.tagsubfield %]</td>
+ <td>[% field.authorised_values_category %]</td>
+ <td>
+ <a href="/cgi-bin/koha/admin/items_search_field.pl?name=[% field.name %]" title="Edit [% field.name %] field">Edit</a>
+ <a href="/cgi-bin/koha/admin/items_search_fields.pl?op=del&name=[% field.name %]" title="Delete [% field.name %] field">Delete</a>
+ </td>
+ </tr>
+ [% END %]
+ </tbody>
+ </table>
+ [% END %]
+ <form action="" method="POST">
+ <fieldset class="rows">
+ <legend>Add a new field</legend>
+ [% INCLUDE 'admin-items-search-field-form.inc' field=undef %]
+ <div>
+ <input type="hidden" name="op" value="add" />
+ </div>
+ <fieldset class="action">
+ <input type="submit" value="Add this field" />
+ </fieldset>
+ </fieldset>
+ </form>
+ </div>
+ </div>
+ <div class="yui-b">
+ [% INCLUDE 'admin-menu.inc' %]
+ </div>
+ </div>
+
+ [% INCLUDE 'intranet-bottom.inc' %]
<form action="search.pl" method="get">
<div id="advanced-search">
<h1>Advanced search</h1>
+<a href="/cgi-bin/koha/catalogue/itemsearch.pl">Go to item search</a>
[% IF ( outer_servers_loop ) %]
<!-- DATABASES -->
--- /dev/null
+Bibliographic reference, Publication Date, Publisher, Collection, Barcode, Callnumber, Home branch, Holding branch, Location, Stock number, Status, Issues
+[% FOREACH item IN results -%]
+ [%- INCLUDE 'catalogue/itemsearch_item.csv.inc' item = item -%]
+[%- END -%]
--- /dev/null
+[%- USE CGI -%]
+{
+ "sEcho": [% CGI.param('sEcho') %],
+ "iTotalRecords": [% total_rows %],
+ "iTotalDisplayRecords": [% total_rows %],
+ "aaData": [
+ [%- FOREACH item IN results -%]
+ [%- INCLUDE 'catalogue/itemsearch_item.json.inc' item = item -%]
+ [%- UNLESS loop.last %],[% END -%]
+ [%- END -%]
+ ]
+}
--- /dev/null
+[% USE CGI %]
+[% USE JSON.Escape %]
+
+[% BLOCK form_field_select %]
+ <div class="form-field form-field-select">
+ <label class="form-field-label" for="[% name %]">[% label %]</label>
+ <select id="[% name %]_op" name="[% name %]_op">
+ <option value="=">is</option>
+ [% IF CGI.param(name _ '_op') == '!=' %]
+ <option value="!=" selected="selected">is not</option>
+ [% ELSE %]
+ <option value="!=" >is not</option>
+ [% END %]
+ </select>
+ [% values = CGI.param(name) %]
+ <select id="[% name %]" name="[% name %]" multiple="multiple" size="[% options.size < 4 ? options.size + 1 : 4 %]">
+ [% IF (values == '') %]
+ <option value="" selected="selected">
+ [% ELSE %]
+ <option value="">
+ [% END %]
+ [% empty_option || "All" %]
+ </option>
+ [% FOREACH option IN options %]
+ [% IF values.grep(option.value).size %]
+ <option value="[% option.value %]" selected="selected">[% option.label %]</option>
+ [% ELSE %]
+ <option value="[% option.value %]">[% option.label %]</option>
+ [% END %]
+ [% END %]
+ </select>
+ </div>
+[% END %]
+
+[% BLOCK form_field_select_option %]
+ [% IF params.f == value %]
+ <option value="[% value %]" selected="selected">[% label %]</option>
+ [% ELSE %]
+ <option value="[% value %]">[% label %]</option>
+ [% END %]
+[% END %]
+
+[% BLOCK form_field_select_text %]
+ <div class="form-field form-field-select-text">
+ [% IF params.exists('c') %]
+ <select name="c" class="form-field-conjunction">
+ <option value="and">AND</option>
+ [% IF params.c == 'or' %]
+ <option value="or" selected="selected">OR</option>
+ [% ELSE %]
+ <option value="or">OR</option>
+ [% END %]
+ </select>
+ [% ELSE %]
+ <select name="c" class="form-field-conjunction" disabled="disabled">
+ <option value="and">AND</option>
+ <option value="or">OR</option>
+ </select>
+ [% END %]
+ <select name="f" class="form-field-column">
+ [% INCLUDE form_field_select_option value='barcode' label='Barcode' %]
+ [% INCLUDE form_field_select_option value='itemcallnumber' label='Callnumber' %]
+ [% INCLUDE form_field_select_option value='stocknumber' label='Stock number' %]
+ [% INCLUDE form_field_select_option value='title' label='Title' %]
+ [% INCLUDE form_field_select_option value='author' label='Author' %]
+ [% INCLUDE form_field_select_option value='publishercode' label='Publisher' %]
+ [% INCLUDE form_field_select_option value='publicationdate' label='Publication date' %]
+ [% INCLUDE form_field_select_option value='collectiontitle' label='Collection' %]
+ [% INCLUDE form_field_select_option value='isbn' label='ISBN' %]
+ [% INCLUDE form_field_select_option value='issn' label='ISSN' %]
+ [% IF items_search_fields.size %]
+ <optgroup label="Custom search fields">
+ [% FOREACH field IN items_search_fields %]
+ [% marcfield = field.tagfield %]
+ [% IF field.tagsubfield %]
+ [% marcfield = marcfield _ '$' _ field.tagsubfield %]
+ [% END %]
+ [% IF params.f == "marc:$marcfield" %]
+ <option value="marc:[% marcfield %]" data-authorised-values-category="[% field.authorised_values_category %]" selected="selected">[% field.label %] ([% marcfield %])</option>
+ [% ELSE %]
+ <option value="marc:[% marcfield %]" data-authorised-values-category="[% field.authorised_values_category %]">[% field.label %] ([% marcfield %])</option>
+ [% END %]
+ [% END %]
+ </optgroup>
+ [% END %]
+ </select>
+ <input type="text" name="q" class="form-field-value" value="[% params.q %]" />
+ <input type="hidden" name="op" value="like" />
+ </div>
+[% END %]
+
+[% BLOCK form_field_select_text_block %]
+ [% c = CGI.param('c').list %]
+ [% f = CGI.param('f').list %]
+ [% q = CGI.param('q').list %]
+ [% op = CGI.param('op').list %]
+ [% IF q.size %]
+ [% size = q.size - 1 %]
+ [% FOREACH i IN [0 .. size] %]
+ [%
+ params = {
+ f => f.$i
+ q = q.$i
+ op = op.$i
+ }
+ %]
+ [% IF i > 0 %]
+ [% j = i - 1 %]
+ [% params.c = c.$j %]
+ [% END %]
+ [% INCLUDE form_field_select_text params=params %]
+ [% END %]
+ [% ELSE %]
+ [% INCLUDE form_field_select_text %]
+ [% END %]
+[% END %]
+
+[% BLOCK form_field_radio_yes_no %]
+ <div class="form-field">
+ <label class="form-field-label" for="[% name %]">[% label %]:</label>
+ <input type="radio" name="[% name %]" id="[% name %]_indifferent" value="" checked="checked"/>
+ <label for="[% name %]_indifferent">Indifferent</label>
+ <input type="radio" name="[% name %]" id="[% name %]_yes" value="yes" />
+ <label for="[% name %]_yes">Yes</label>
+ <input type="radio" name="[% name %]" id="[% name %]_no" value="no" />
+ <label for="[% name %]_no">No</label>
+ </div>
+[% END %]
+
+[%# Page starts here %]
+
+[% INCLUDE 'doc-head-open.inc' %]
+ <title>Koha › Catalog › Advanced search</title>
+ [% INCLUDE 'doc-head-close.inc' %]
+ [% INCLUDE 'datatables.inc' %]
+ <script type="text/javascript" src="[% themelang %]/lib/jquery/plugins/jquery.dataTables.columnFilter.js"></script>
+ <link rel="stylesheet" type="text/css" href="[% themelang %]/css/datatables.css" />
+ <link rel="stylesheet" type="text/css" href="[% themelang %]/css/itemsearchform.css" />
+ <script type="text/javascript">
+ //<![CDATA[
+ var authorised_values = [% authorised_values_json %];
+
+ function loadAuthorisedValuesSelect(select) {
+ var selected = select.find('option:selected');
+ var category = selected.data('authorised-values-category');
+ var form_field_value = select.siblings('.form-field-value');
+ if (category && category in authorised_values) {
+ var values = authorised_values[category];
+ var html = '<select name="q" class="form-field-value">\n';
+ for (i in values) {
+ var value = values[i];
+ html += '<option value="' + value.authorised_value + '">' + value.lib + '</option>\n';
+ }
+ html += '</select>\n';
+ var new_form_field_value = $(html);
+ new_form_field_value.val(form_field_value.val());
+ form_field_value.replaceWith(new_form_field_value);
+ } else {
+ if (form_field_value.prop('tagName').toLowerCase() == 'select') {
+ html = '<input name="q" type="text" class="form-field-value" />';
+ var new_form_field_value = $(html);
+ form_field_value.replaceWith(new_form_field_value);
+ }
+ }
+ }
+
+ function addNewField() {
+ var form_field = $('div.form-field-select-text').last();
+ var copy = form_field.clone(true);
+ copy.find('input,select').not('[type="hidden"]').each(function() {
+ $(this).val('');
+ });
+ copy.find('.form-field-conjunction').removeAttr('disabled');
+ form_field.after(copy);
+ copy.find('select.form-field-column').change();
+ }
+
+ function submitForm($form) {
+ var tr = ''
+ + ' <tr>'
+ + ' <th>' + _("Bibliographic reference") + '</th>'
+ + ' <th>' + _("Publication date") + '</th>'
+ + ' <th>' + _("Publisher") + '</th>'
+ + ' <th>' + _("Collection") + '</th>'
+ + ' <th>' + _("Barcode") + '</th>'
+ + ' <th>' + _("Callnumber") + '</th>'
+ + ' <th>' + _("Home branch") + '</th>'
+ + ' <th>' + _("Holding branch") + '</th>'
+ + ' <th>' + _("Location") + '</th>'
+ + ' <th>' + _("Stock number") + '</th>'
+ + ' <th>' + _("Status") + '</th>'
+ + ' <th>' + _("Issues") + '</th>'
+ + ' <th></th>'
+ + ' </tr>'
+ var table = ''
+ + '<table id="results">'
+ + ' <thead>' + tr + tr + '</thead>'
+ + ' <tbody></tbody>'
+ + '</table>';
+ $('#results-wrapper').empty().html(table);
+
+ var params = [];
+ $form.find('select,input[type="text"],input[type="hidden"]').not('[disabled]').each(function () {
+ params.push({ 'name': $(this).attr('name'), 'value': $(this).val() });
+ });
+ $form.find('input[type="radio"]:checked').each(function() {
+ params.push({ 'name': $(this).attr('name'), 'value': $(this).val() });
+ });
+
+ $('#results').dataTable($.extend(true, {}, dataTablesDefaults, {
+ 'bDestroy': true,
+ 'bServerSide': true,
+ 'sAjaxSource': '/cgi-bin/koha/catalogue/itemsearch.pl',
+ 'fnServerParams': function(aoData) {
+ aoData.push( { 'name': 'format', 'value': 'json' } );
+ for (i in params) {
+ aoData.push(params[i]);
+ }
+ },
+ 'sDom': '<"top pager"ilp>t<"bottom pager"ip>',
+ 'aoColumns': [
+ { 'sName': 'title' },
+ { 'sName': 'publicationyear' },
+ { 'sName': 'publishercode' },
+ { 'sName': 'collectiontitle' },
+ { 'sName': 'barcode' },
+ { 'sName': 'itemcallnumber' },
+ { 'sName': 'homebranch' },
+ { 'sName': 'holdingbranch' },
+ { 'sName': 'location' },
+ { 'sName': 'stocknumber' },
+ { 'sName': 'notforloan' },
+ { 'sName': 'issues' },
+ { 'sName': 'checkbox', 'bSortable': false }
+ ]
+ })).columnFilter({
+ 'sPlaceHolder': 'head:after',
+ 'aoColumns': [
+ { 'type': 'text' },
+ { 'type': 'text' },
+ { 'type': 'text' },
+ { 'type': 'text' },
+ { 'type': 'text' },
+ { 'type': 'text' },
+ { 'type': 'select', 'values': [% branches.json %] },
+ { 'type': 'select', 'values': [% branches.json %] },
+ { 'type': 'select', 'values': [% locations.json %] },
+ { 'type': 'text' },
+ { 'type': 'select', 'values': [% notforloans.json %] },
+ { 'type': 'text' },
+ null
+ ]
+ });
+ }
+
+ function hideForm($form) {
+ $form.hide();
+ $('#editsearchlink').show();
+ }
+
+ $(document).ready(function () {
+ // Add the "New field" link.
+ var form_field = $('div.form-field-select-text').last()
+ var button_field_new = $('<a href="#" class="button-field-new" title="Add a new field">New field</a>');
+ button_field_new.click(function() {
+ addNewField();
+ return false;
+ });
+ form_field.after(button_field_new);
+
+ // If a field is linked to an authorised values list, display the list.
+ $('div.form-field-select-text select').change(function() {
+ loadAuthorisedValuesSelect($(this));
+ }).change();
+
+ // Prevent user to select the 'All ...' option with other options.
+ $('div.form-field-select').each(function() {
+ $(this).find('select').filter(':last').change(function() {
+ values = $(this).val();
+ if (values.length > 1) {
+ var idx = $.inArray('', values);
+ if (idx != -1) {
+ values.splice(idx, 1);
+ $(this).val(values);
+ }
+ }
+ });
+ });
+
+ $('#itemsearchform').submit(function() {
+ var format = $(this).find('input[name="format"]:checked').val();
+ if (format == 'html') {
+ submitForm($(this));
+ hideForm($(this));
+ return false;
+ }
+ });
+
+ $('#editsearchlink').click(function() {
+ $('#itemsearchform').show();
+ $(this).hide();
+ return false;
+ });
+ });
+ //]]>
+ </script>
+</head>
+<body id="catalog_itemsearch" class="catalog">
+ [% INCLUDE 'header.inc' %]
+ <div id="breadcrumbs">
+ <a href="/cgi-bin/koha/mainpage.pl">Home</a> › Item search
+ </div>
+
+ <div id="doc" class="yui-t7">
+ <div id="bd">
+ <h1>Item search</h1>
+ <a href="/cgi-bin/koha/catalogue/search.pl">Go to advanced search</a>
+ <form action="" method="get" id="itemsearchform">
+ <fieldset>
+ <legend>Item search</legend>
+ <fieldset>
+ [% INCLUDE form_field_select
+ name="homebranch"
+ label="Home branch"
+ options = branches
+ empty_option = "All branches"
+ %]
+ [% INCLUDE form_field_select
+ name="location"
+ label="Location"
+ options = locations
+ empty_option = "All locations"
+ %]
+ </fieldset>
+ <fieldset>
+ [% INCLUDE form_field_select
+ name="itype"
+ label="Item type"
+ options = itemtypes
+ empty_option = "All item types"
+ %]
+ [% INCLUDE form_field_select
+ name="ccode"
+ label="Collection code"
+ options = ccodes
+ empty_option = "All collection codes"
+ %]
+ </fieldset>
+ <fieldset>
+ [% INCLUDE form_field_select_text_block %]
+ <p class="hint">You can use the following joker characters: % _</p>
+ </fieldset>
+ <fieldset>
+ <div class="form-field">
+ <label class="form-field-label" for="itemcallnumber_from">From call number:</label>
+ [% value = CGI.param('itemcallnumber_from') %]
+ <input type="text" id="itemcallnumber_from" name="itemcallnumber_from" value="[% value %]" />
+ <span class="hint">(inclusive)</span>
+ </div>
+ <div class="form-field">
+ [% value = CGI.param('itemcallnumber_to') %]
+ <label class="form-field-label" for="itemcallnumber_to">To call number:</label>
+ <input type="text" id="itemcallnumber_to" name="itemcallnumber_to" value="[% value %]" />
+ <span class="hint">(inclusive)</span>
+ </div>
+ [% INCLUDE form_field_radio_yes_no name="damaged" label="Damaged" %]
+ [% INCLUDE form_field_radio_yes_no name="itemlost" label="Lost" %]
+ <div class="form-field">
+ <label class="form-field-label" for="issues">Issues count:</label>
+ <select id="issues_op" name="issues_op">
+ <option value=">">></option>
+ <option value="<"><</option>
+ <option value="=">=</option>
+ <option value="!=">!=</option>
+ </select>
+ <input type="text" name="issues" />
+ </div>
+ <div class="form-field">
+ <label class="form-field-label" for="datelastborrowed">Last issue date:</label>
+ <select id="datelastborrowed_op" name="datelastborrowed_op">
+ <option value=">">After</option>
+ <option value="<">Before</option>
+ <option value="=">On</option>
+ </select>
+ <input type="text" name="datelastborrowed" />
+ <span class="hint">ISO Format (AAAA-MM-DD)</span>
+ </div>
+ </fieldset>
+ <fieldset>
+ <div class="form-field-radio">
+ <label>Output:</label>
+ <input type="radio" id="format-html" name="format" value="html" checked="checked" /> <label for="format-html">Screen</label>
+ <input type="radio" id="format-csv" name="format" value="csv" /> <label for="format-csv">CSV</label>
+ </div>
+ <div class="form-actions">
+ <input type="submit" value="Search" />
+ </div>
+ </fieldset>
+ </fieldset>
+ </form>
+
+ <p><a id="editsearchlink" href="#" style="display:none">Edit search</a></p>
+
+ <div id="results-wrapper">
+ [% IF search_done %]
+
+ [% IF total_rows > 0 %]
+ <p>Found [% total_rows %] results.</p>
+ [% ELSE %]
+ <p>No results found.</p>
+ [% END %]
+
+ [% IF results %]
+ [% INCLUDE 'catalogue/itemsearch_items.inc' items = results %]
+ [% END %]
+
+ <div id="pagination-bar">
+ [% pagination_bar %]
+ </div>
+
+ [% END %]
+ </div>
+ </div>
+
+ [% INCLUDE 'intranet-bottom.inc' %]