Bugzilla – Attachment 36247 Details for
Bug 11559
Professional cataloger's interface
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 11559 followup - Remove Pazpar2 dependency, bugfixes
Bug-11559-followup---Remove-Pazpar2-dependency-bug.patch (text/plain), 37.28 KB, created by
Jesse Weaver
on 2015-03-01 07:46:35 UTC
(
hide
)
Description:
Bug 11559 followup - Remove Pazpar2 dependency, bugfixes
Filename:
MIME Type:
Creator:
Jesse Weaver
Created:
2015-03-01 07:46:35 UTC
Size:
37.28 KB
patch
obsolete
>From cf914e1e5952425472ae981b1c38a0029a5da476 Mon Sep 17 00:00:00 2001 >From: Jesse Weaver <pianohacker@gmail.com> >Date: Tue, 20 May 2014 20:35:58 -0600 >Subject: [PATCH] Bug 11559 followup - Remove Pazpar2 dependency, bugfixes > >Adds a new metasearch service, removing dependency on Pazpar2. Current >limitations: > > * Can only sort by title. Should be easy to fix. > * Requires refetching results when changing pages. > >Also adds an "edit items" link, and fixes a loading error when logged in >as the database user. >--- > C4/Breeding.pm | 105 +++++++++++- > cataloguing/editor.pl | 3 +- > .../lib/koha/cateditor/preferences.js | 3 +- > .../intranet-tmpl/lib/koha/cateditor/search.js | 148 ++++++++--------- > koha-tmpl/intranet-tmpl/prog/en/css/cateditor.css | 2 +- > .../prog/en/includes/cateditor-ui.inc | 179 +++++++++++++-------- > .../prog/en/modules/cataloguing/editor.tt | 47 +++--- > svc/z3950 | 102 ++++++++++++ > 8 files changed, 422 insertions(+), 167 deletions(-) > create mode 100755 svc/z3950 > >diff --git a/C4/Breeding.pm b/C4/Breeding.pm >index b5a4717..9848cb0 100644 >--- a/C4/Breeding.pm >+++ b/C4/Breeding.pm >@@ -30,6 +30,7 @@ use C4::AuthoritiesMarc; #GuessAuthTypeCode, FindDuplicateAuthority > use C4::Languages; > use Koha::Database; > use Koha::XSLT_Handler; >+use Time::HiRes qw( clock_gettime CLOCK_MONOTONIC ); > > use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); > >@@ -38,7 +39,7 @@ BEGIN { > $VERSION = 3.07.00.049; > require Exporter; > @ISA = qw(Exporter); >- @EXPORT = qw(&BreedingSearch &Z3950Search &Z3950SearchAuth); >+ @EXPORT = qw(&BreedingSearch &Z3950Search &Z3950SearchAuth &RunZ3950); > } > > =head1 NAME >@@ -326,8 +327,10 @@ sub _add_rowdata { > my ($row, $record)=@_; > my %fetch= ( > title => 'biblio.title', >+ seriestitle => 'biblio.seriestitle', > author => 'biblio.author', > isbn =>'biblioitems.isbn', >+ issn =>'biblioitems.issn', > lccn =>'biblioitems.lccn', #LC control number (not call number) > edition =>'biblioitems.editionstatement', > date => 'biblio.copyrightdate', #MARC21 >@@ -711,6 +714,106 @@ sub Z3950SearchAuth { > ); > } > >+sub RunZ3950 { >+ my ( $server_ids, $query, $options ) = @_; >+ >+ $options = { >+ offset => 0, >+ fetch => 20, >+ on_error => sub {}, >+ on_hit => sub {}, >+ %{ $options || {} } >+ }; >+ >+ my $schema = Koha::Database->new->schema; >+ my $stats = { >+ num_fetched => { >+ map { $_ => 0 } @$server_ids >+ }, >+ num_hits => { >+ map { $_ => 0 } @$server_ids >+ }, >+ total_fetched => 0, >+ total_hits => 0, >+ }; >+ my $start = clock_gettime( CLOCK_MONOTONIC ); >+ my @servers; >+ >+ foreach my $server ( $schema->resultset('Z3950server')->search( { id => $server_ids } )->all ) { >+ my $zoptions = ZOOM::Options->new(); >+ $zoptions->option( 'async', 1 ); >+ $zoptions->option( 'elementSetName', 'F' ); >+ $zoptions->option( 'databaseName', $server->db ); >+ $zoptions->option( 'user', $server->userid ) if $server->userid; >+ $zoptions->option( 'password', $server->password ) if $server->password; >+ $zoptions->option( 'preferredRecordSyntax', $server->syntax ); >+ $zoptions->option( 'timeout', $server->timeout ) if $server->timeout; >+ >+ my $connection = ZOOM::Connection->create($zoptions); >+ $connection->connect( $server->host, $server->port ); >+ >+ push @servers, { >+ connection => $connection, >+ id => $server->id, >+ host => $server->host, >+ name => $server->name, >+ encoding => ( $server->encoding ? $server->encoding : "iso-5426" ), >+ results => $connection->search_pqf( $query ), # Starts the search >+ }; >+ } >+ >+ my $servers_left = scalar @servers; >+ my $total_raw_size = 0; >+ >+ while ( $servers_left ) { >+ my $i; >+ >+ # Read pending events from servers until one finishes >+ while ( ( $i = ZOOM::event( [ map { $_->{connection} } @servers ] ) ) != 0 ) { >+ last if $servers[ $i - 1 ]->{connection}->last_event() == ZOOM::Event::ZEND; >+ } >+ >+ $servers_left--; >+ my $server = $servers[ --$i ]; >+ my $exception = $server->{connection}->exception(); #ignores errmsg, addinfo, diagset >+ >+ if ($exception) { >+ $options->{on_error}->( $server, $exception ); >+ } else { >+ my $num_results = $stats->{num_hits}->{ $server->{id} } = $server->{results}->size; >+ my $num_fetched = $stats->{num_fetched}->{ $server->{id} } = ( $options->{offset} + $options->{fetch} ) < $num_results ? $options->{fetch} : $num_results; >+ >+ $stats->{total_hits} += $num_results; >+ $stats->{total_fetched} += $num_fetched; >+ >+ next if ( !$num_results ); >+ >+ my $hits = $server->{results}->records( $options->{offset}, $num_fetched, 1 ); >+ >+ if ( !@$hits ) { >+ $options->{on_error}->( $server, $server->{connection}->exception() ) if ( $server->{connection}->exception() ); >+ next; >+ } >+ >+ foreach my $j ( 0..$#$hits ) { >+ $total_raw_size += length $hits->[$j]->raw(); >+ my ($marcrecord) = MarcToUTF8Record( $hits->[$j]->raw(), C4::Context->preference('marcflavour'), $server->{encoding} ); #ignores charset return values >+ my $metadata = {}; >+ _add_rowdata( $metadata, $marcrecord ); >+ $options->{on_hit}->( $server, { >+ index => $options->{offset} + $j, >+ record => $marcrecord, >+ metadata => $metadata, >+ } ); >+ } >+ } >+ } >+ >+ $stats->{time} = clock_gettime( CLOCK_MONOTONIC ) - $start; >+ >+ return $stats; >+} >+ > 1; > __END__ > >diff --git a/cataloguing/editor.pl b/cataloguing/editor.pl >index fe9d897..85a1191 100755 >--- a/cataloguing/editor.pl >+++ b/cataloguing/editor.pl >@@ -45,8 +45,9 @@ $template->{VARS}->{DefaultLanguageField008} = pack( 'A3', C4::Context->preferen > > # Z39.50 servers > my $dbh = C4::Context->dbh; >-$template->{VARS}->{z3950_targets} = $dbh->selectall_arrayref( q{ >+$template->{VARS}->{z3950_servers} = $dbh->selectall_arrayref( q{ > SELECT * FROM z3950servers >+ WHERE recordtype != 'authority' > ORDER BY name > }, { Slice => {} } ); > >diff --git a/koha-tmpl/intranet-tmpl/lib/koha/cateditor/preferences.js b/koha-tmpl/intranet-tmpl/lib/koha/cateditor/preferences.js >index 1372dbf..6e324e6 100644 >--- a/koha-tmpl/intranet-tmpl/lib/koha/cateditor/preferences.js >+++ b/koha-tmpl/intranet-tmpl/lib/koha/cateditor/preferences.js >@@ -1,7 +1,8 @@ > define( function() { > var Preferences = { > Load: function( borrowernumber ) { >- if ( !borrowernumber ) return; >+ if ( borrowernumber == null ) return; >+ > var saved_prefs; > try { > saved_prefs = JSON.parse( localStorage[ 'cateditor_preferences_' + borrowernumber ] ); >diff --git a/koha-tmpl/intranet-tmpl/lib/koha/cateditor/search.js b/koha-tmpl/intranet-tmpl/lib/koha/cateditor/search.js >index 916076c..e2e248c 100644 >--- a/koha-tmpl/intranet-tmpl/lib/koha/cateditor/search.js >+++ b/koha-tmpl/intranet-tmpl/lib/koha/cateditor/search.js >@@ -1,94 +1,88 @@ >-define( [ 'marc-record', 'pz2' ], function( MARC, Pazpar2 ) { >- //var _pz; >- var _onresults; >- var _recordCache = {}; >+define( [ 'marc-record' ], function( MARC ) { > var _options; >+ var _records = {}; >+ var _last; > >- var Search = { >- Init: function( targets, options ) { >- var initOpts = {}; >+ var _pqfMapping = { >+ author: '1=1004', // s=al', >+ cn_dewey: '1=13', >+ cn_lc: '1=16', >+ date: '1=30', // r=r', >+ isbn: '1=7', >+ issn: '1=8', >+ lccn: '1=9', >+ local_number: '1=12', >+ music_identifier: '1=51', >+ standard_identifier: '1=1007', >+ subject: '1=21', // s=al', >+ term: '1=1016', // t=l,r s=al', >+ title: '1=4', // s=al', >+ } > >- $.each( targets, function ( url, info ) { >- initOpts[ 'pz:name[' + url + ']' ] = info.name; >- initOpts[ 'pz:queryencoding[' + url + ']' ] = info.encoding; >- initOpts[ 'pz:xslt[' + url + ']' ] = info.kohasyntax.toLowerCase() + '-work-groups.xsl'; >- initOpts[ 'pz:requestsyntax[' + url + ']' ] = info.syntax; >+ var Search = { >+ Init: function( options ) { >+ _options = options; >+ }, >+ JoinTerms: function( terms ) { >+ var q = ''; > >- // Load in default CCL mappings >- // Pazpar2 seems to have a bug where wildcard cclmaps are ignored. >- // What an incredible surprise. >- initOpts[ 'pz:cclmap:term[' + url + ']' ] = 'u=1016 t=l,r s=al'; >- initOpts[ 'pz:cclmap:Author-name[' + url + ']' ] = 'u=1004 s=al'; >- initOpts[ 'pz:cclmap:Classification-Dewey[' + url + ']' ] = 'u=13'; >- initOpts[ 'pz:cclmap:Classification-LC[' + url + ']' ] = 'u=16'; >- initOpts[ 'pz:cclmap:Date[' + url + ']' ] = 'u=30 r=r'; >- initOpts[ 'pz:cclmap:Identifier-ISBN[' + url + ']' ] = 'u=7'; >- initOpts[ 'pz:cclmap:Identifier-ISSN[' + url + ']' ] = 'u=8'; >- initOpts[ 'pz:cclmap:Identifier-publisher-for-music[' + url + ']' ] = 'u=51'; >- initOpts[ 'pz:cclmap:Identifier-standard[' + url + ']' ] = 'u=1007'; >- initOpts[ 'pz:cclmap:LC-card-number[' + url + ']' ] = 'u=9'; >- initOpts[ 'pz:cclmap:Local-number[' + url + ']' ] = 'u=12'; >- initOpts[ 'pz:cclmap:Subject[' + url + ']' ] = 'u=21 s=al'; >- initOpts[ 'pz:cclmap:Title[' + url + ']' ] = 'u=4 s=al'; >+ $.each( terms, function( i, term ) { >+ var term = '@attr ' + _pqfMapping[ term[0] ] + ' "' + term[1].replace( '"', '\\"' ) + '"' > >- if ( info.authentication ) initOpts[ 'pz:authentication[' + url + ']' ] = info.authentication; >+ if ( q ) { >+ q = '@and ' + q + ' ' + term; >+ } else { >+ q = term; >+ } > } ); > >- _options = $.extend( { >- initopts: initOpts, >- onshow: Search._onshow, >- errorhandler: Search._onerror, >- }, options ); >- >- _pz = new Pazpar2( _options ); >+ return q; > }, >- Reconnect: function() { >- _pz.reset(); >- _pz = new Pazpar2( _options ); >- }, >- Start: function( targets, q, limit ) { >- Search.includedTargets = []; >- recordcache = {}; >+ Run: function( servers, q, options ) { >+ Search.includedServers = []; >+ _records = {}; >+ _last = { >+ servers: servers, >+ q: q, >+ options: options, >+ }; > >- $.each( targets, function ( url, info ) { >- if ( !info.disabled ) Search.includedTargets.push( url ); >- } ); >+ options = $.extend( { >+ offset: 0, >+ page_size: 20, >+ }, _options, options ); > >- _pz.search( q, limit, 'relevance:0', 'pz:id=' + Search.includedTargets.join( '|' ) ); >- return true; >- }, >- Fetch: function( offset ) { >- _pz.show( offset ); >- }, >- GetDetailedRecord: function( recid, callback ) { >- if ( _recordCache[recid] ) { >- callback( _recordCache[recid] ); >- return; >- } >+ $.each( servers, function ( id, info ) { >+ if ( info.checked ) Search.includedServers.push( id ); >+ } ); > >- _pz.record( recid, 0, undefined, { callback: function(data) { >- var record = _recordCache[recid] = new MARC.Record(); >- record.loadMARCXML(data.xmlDoc); >+ $.get( >+ '/cgi-bin/koha/svc/z3950', >+ { >+ q: q, >+ servers: Search.includedServers.join( ',' ), >+ offset: options.offset, >+ page_size: options.page_size >+ } >+ ) >+ .done( function( data ) { >+ $.each( data.hits, function( undef, hit ) { >+ var record = new MARC.Record(); >+ record.loadMARCXML( hit.record ); >+ hit.record = record; >+ } ); > >- callback(record); >- } } ); >- }, >- IsAvailable: function() { >- return _pz.initStatusOK; >- }, >- _onshow: function( data ) { >- $.each( data.hits, function( undef, hit ) { >- hit.id = 'search:' + encodeURIComponent( hit.recid[0] ); >- } ); >+ _options.onresults( data ); >+ } ) >+ .fail( function( error ) { >+ _options.onerror( error ); >+ } ); > >- _options.onresults( data ); >+ return true; > }, >- _onerror: function( error ) { >- if ( _options.oniniterror && !_pz.initStatusOK ) { >- _options.oniniterror( error ); >- } else { >- _options.onerror( error ); >- } >+ Fetch: function( offset ) { >+ if ( !_last ) return; >+ Search.Run( _last.servers, _last.q, $.extend( {}, _last.options, { offset: offset } ) ); > } > }; > >diff --git a/koha-tmpl/intranet-tmpl/prog/en/css/cateditor.css b/koha-tmpl/intranet-tmpl/prog/en/css/cateditor.css >index 8dd7c06..ad9f9cb 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/css/cateditor.css >+++ b/koha-tmpl/intranet-tmpl/prog/en/css/cateditor.css >@@ -315,7 +315,7 @@ body { > line-height: 24px; > } > >-.results-marc { >+.marccol { > font-family: monospace; > height: auto; > white-space: pre-wrap; >diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/cateditor-ui.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/cateditor-ui.inc >index c0637be..673aa2f 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/includes/cateditor-ui.inc >+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/cateditor-ui.inc >@@ -10,12 +10,6 @@ require.config( { > themelang: '[% themelang %]', > }, > }, >- paths: { >- pz2: '../../pz2', >- }, >- shim: { >- pz2: { exports: 'pz2' }, >- }, > } ); > </script> > >@@ -27,30 +21,27 @@ require.config( { > > <script> > require( [ 'koha-backend', 'search', 'macros', 'marc-editor', 'marc-record', 'preferences', 'resources', 'text-marc', 'widget' ], function( KohaBackend, Search, Macros, MARCEditor, MARC, Preferences, Resources, TextMARC, Widget ) { >- var z3950Targets = { >- [% FOREACH target = z3950_targets %] >- '[% target.host %]:[% target.port %]/[% target.db %]': { >- 'name': '[% target.name %]', >- 'authentication': '[% target.userid %]:[% target.password %]', >- 'syntax': '[% target.syntax %]', >- 'kohasyntax': '[% target.syntax == 'USMARC' ? 'MARC21' : target.syntax %]', >- 'encoding': '[% target.encoding %]', >- 'checked': [% target.checked ? 'true' : 'false' %], >+ var z3950Servers = { >+ [% FOREACH server = z3950_servers %] >+ [% server.id %]: { >+ 'name': '[% server.name %]', >+ 'kohasyntax': '[% server.syntax == 'USMARC' ? 'MARC21' : server.syntax %]', >+ 'checked': [% server.checked ? 'true' : 'false' %], > }, > [% END %] > }; > > // The columns that should show up in a search, in order, and keyed by the corresponding <metadata> tag in the XSL and Pazpar2 config > var z3950Labels = [ >- [ "md-work-title", _("Title") ], >- [ "md-series-title", _("Series Title") ], >- [ "md-work-author", _("Author") ], >- [ "md-lccn", _("LCCN") ], >- [ "md-isbn", _("ISBN") ], >- [ "md-issn", _("ISSN") ], >- [ "md-medium", _("Medium") ], >- [ "md-edition", _("Edition") ], >- [ "md-description", _("Description") ], >+ [ "title", _("Title") ], >+ [ "series", _("Series Title") ], >+ [ "author", _("Author") ], >+ [ "lccn", _("LCCN") ], >+ [ "isbn", _("ISBN") ], >+ [ "issn", _("ISSN") ], >+ [ "medium", _("Medium") ], >+ [ "edition", _("Edition") ], >+ [ "notes", _("Notes") ], > ]; > > var state = { >@@ -132,10 +123,18 @@ require( [ 'koha-backend', 'search', 'macros', 'marc-editor', 'marc-record', 'pr > > $('#quicksearch .search-box').each( function() { > shortcut.add( 'enter', $.proxy( function() { >- var q = this.value; >- if (!q) return false; >+ var terms = []; >+ >+ $('#quicksearch .search-box').each( function() { >+ if ( !this.value ) return; >+ >+ terms.push( [ $(this).data('qualifier'), this.value ] ); >+ } ); >+ >+ if ( !terms.length ) return; > >- if ( Search.Start( z3950Targets, $(this).data('qualifier') + q, 20 ) ) { >+ if ( Search.Run( z3950Servers, Search.JoinTerms(terms) ) ) { >+ $("#search-overlay").show(); > showResultsBox(); > } > >@@ -166,7 +165,10 @@ require( [ 'koha-backend', 'search', 'macros', 'marc-editor', 'marc-record', 'pr > }, > 'catalog': { > titleForRecord: _("Editing catalog record #{ID}"), >- href: "/cgi-bin/koha/catalogue/detail.pl?biblionumber={ID}", >+ links: [ >+ { title: _("view"), href: "/cgi-bin/koha/catalogue/detail.pl?biblionumber={ID}" }, >+ { title: _("edit items"), href: "/cgi-bin/koha/cataloguing/additem.pl?biblionumber={ID}" }, >+ ], > saveLabel: _("Save to catalog"), > get: function( id, callback ) { > if ( !id ) return false; >@@ -206,8 +208,9 @@ require( [ 'koha-backend', 'search', 'macros', 'marc-editor', 'marc-record', 'pr > get: function( id, callback ) { > if ( !id ) return false; > >- Search.GetDetailedRecord( decodeURIComponent(id), callback ); >+ callback( backends.search.records[ id ] ); > }, >+ records: {}, > }, > }; > >@@ -221,13 +224,13 @@ require( [ 'koha-backend', 'search', 'macros', 'marc-editor', 'marc-record', 'pr > > document.location.hash = '#' + parts[0] + ':' + parts[1]; > >- if ( backend.href ) { >- $( '#title' ).html( backend.titleForRecord.replace( '{ID}', parts[1] ) + ' <a target="_blank" href="' + backend.href.replace( '{ID}', parts[1] ) + '">' + _("(view)") + '</a>' ); >- } else { >- $( '#title' ).text( backend.titleForRecord.replace( '{ID}', parts[1] ) ); >- } >+ $('#title').text( backend.titleForRecord.replace( '{ID}', parts[1] ) ); >+ >+ $.each( backend.links || [], function( i, link ) { >+ $('#title').append(' <a target="_blank" href="' + link.href.replace( '{ID}', parts[1] ) + '">(' + link.title + ')</a>' ); >+ } ); > $( 'title', document.head ).html( _("Koha › Cataloging › ") + backend.titleForRecord.replace( '{ID}', parts[1] ) ); >- $( '#save-record span' ).text( backends[ state.saveBackend ].saveLabel ); >+ $('#save-record span').text( backends[ state.saveBackend ].saveLabel ); > } > > function saveRecord( recid, editor, callback ) { >@@ -313,33 +316,40 @@ require( [ 'koha-backend', 'search', 'macros', 'marc-editor', 'marc-record', 'pr > > $('#advanced-search-ui').modal('hide'); > >- if ( Search.Start( z3950Targets, search, 20 ) ) { >+ if ( Search.Run( z3950Servers, search, 20 ) ) { >+ $("#search-overlay").show(); > showResultsBox(); > } > } > > function showResultsBox(data) { >+ $('#search-top-pages, #search-bottom-pages').find('.pagination').empty(); > $('#searchresults thead tr').empty(); > $('#searchresults tbody').empty(); >- $('#search-targetsinfo').empty().append('<li>' + _("Loading...") + '</li>'); >+ $('#search-serversinfo').empty().append('<li>' + _("Loading...") + '</li>'); > $('#search-results-ui').modal('show'); > } > > function showSearchResults( editor, data ) { >+ backends.search.records = {}; >+ > $('#searchresults thead tr').empty(); > $('#searchresults tbody').empty(); >+ $('#search-serversinfo').empty(); >+ >+ $.each( data.num_fetched, function( server_id, num_fetched ) { >+ if ( num_fetched < data.num_hits[server_id] ) { >+ num_fetched += '+'; >+ } >+ >+ $('#search-serversinfo').append( '<li>' + z3950Servers[server_id].name + ' (' + num_fetched + ')' + '</li>' ); >+ } ); > > var seenColumns = {}; > > $.each( data.hits, function( undef, hit ) { >- for ( key in hit ) { >- if ( /^md-/.test(key) ) seenColumns[key] = true; >- } >- >- $.each( hit.location, function( undef, location ) { >- for ( key in location ) { >- if ( /^md-/.test(key) ) seenColumns[key] = true; >- } >+ $.each( hit.metadata, function(key) { >+ seenColumns[key] = true; > } ); > } ); > >@@ -354,16 +364,17 @@ require( [ 'koha-backend', 'search', 'macros', 'marc-editor', 'marc-record', 'pr > $('#searchresults thead tr').append('<th>' + _("Tools") + '</th>'); > > $.each( data.hits, function( undef, hit ) { >+ backends.search.records[ hit.server + '-' + hit.index ] = hit.record; >+ hit.id = 'search:' + hit.server + '-' + hit.index; >+ > var result = '<tr>'; >- result += '<td class="sourcecol">' + hit.location[0]['@name'] + '</td>'; >+ result += '<td class="sourcecol">' + z3950Servers[ hit.server ].name + '</td>'; > > $.each( z3950Labels, function( undef, label ) { > if ( !seenColumns[ label[0] ] ) return; > >- if ( hit[ label[0] ] ) { >- result += '<td class="infocol">' + hit[ label[0] ].join('<br/>') + '</td>'; >- } else if ( hit.location[0][ label[0] ] ) { >- result += '<td class="infocol">' + hit.location[0][ label[0] ].join('<br/>') + '</td>'; >+ if ( hit.metadata[ label[0] ] ) { >+ result += '<td class="infocol">' + hit.metadata[ label[0] ] + '</td>'; > } else { > result += '<td class="infocol"> </td>'; > } >@@ -376,10 +387,23 @@ require( [ 'koha-backend', 'search', 'macros', 'marc-editor', 'marc-record', 'pr > > var $tr = $( result ); > $tr.find( '.marc-link' ).click( function() { >- Search.GetDetailedRecord( hit.recid, function( record ) { >- var $columns = $tr.find( '.infocol' ); >- CodeMirror.runMode( TextMARC.RecordToText( record ), 'marc', $( '<td class="infocol results-marc" colspan="' + $columns.length + '"></td>' ).replaceAll( $columns.slice(1).remove().end()[0] )[0] ); >- } ); >+ var $info_columns = $tr.find( '.infocol' ); >+ var $marc_column = $tr.find( '.marccol' ); >+ >+ if ( !$marc_column.length ) { >+ $marc_column = $( '<td class="marccol" colspan="' + $info_columns.length + '"></td>' ).insertAfter( $info_columns.eq(-1) ).hide(); >+ CodeMirror.runMode( TextMARC.RecordToText( hit.record ), 'marc', $marc_column[0] ); >+ } >+ >+ if ( $marc_column.is(':visible') ) { >+ $tr.find('.marc-link').text( _("View MARC") ); >+ $info_columns.show(); >+ $marc_column.hide(); >+ } else { >+ $tr.find('.marc-link').text( _("Hide MARC") ); >+ $marc_column.show(); >+ $info_columns.hide(); >+ } > > return false; > } ); >@@ -398,12 +422,34 @@ require( [ 'koha-backend', 'search', 'macros', 'marc-editor', 'marc-record', 'pr > $('#searchresults tbody').append( $tr ); > } ); > >+ var pages = []; >+ var cur_page = data.offset / data.page_size; >+ var max_page = Math.ceil( data.total_fetched / data.page_size ) - 1; >+ >+ if ( cur_page != 0 ) { >+ pages.push( '<li><a class="search-nav" href="#" data-offset="' + (data.offset - data.page_size) + '">« ' + _("Previous") + '</a></li>' ); >+ } >+ >+ for ( var page = Math.max( 0, cur_page - 9 ); page <= Math.min( max_page, cur_page + 9 ); page++ ) { >+ if ( page == cur_page ) { >+ pages.push( ' <li class="active"><a href="#">' + ( page + 1 ) + '</a></li>' ); >+ } else { >+ pages.push( ' <li><a class="search-nav" href="#" data-offset="' + ( page * data.page_size ) + '">' + ( page + 1 ) + '</a></li>' ); >+ } >+ } >+ >+ if ( cur_page < max_page ) { >+ pages.push( ' <li><a class="search-nav" href="#" data-offset="' + (data.offset + data.page_size) + '">' + _("Next") + ' »</a></li>' ); >+ } >+ >+ if ( pages.length > 1 ) $( '#search-top-pages, #search-bottom-pages' ).find( '.pagination' ).html( '<ul>' + pages.join( '' ) + '</ul>'); >+ > var $overlay = $('#search-overlay'); > $overlay.find('span').text(_("Loading")); >- $overlay.find('.bar').css( { display: 'block', width: 100 * ( 1 - data.activeclients / Search.includedTargets.length ) + '%' } ); >+ $overlay.find('.bar').css( { display: 'block', width: 100 * ( 1 - data.activeclients / Search.includedServers.length ) + '%' } ); > > if ( data.activeclients ) { >- $overlay.find('.bar').css( { display: 'block', width: 100 * ( 1 - data.activeclients / Search.includedTargets.length ) + '%' } ); >+ $overlay.find('.bar').css( { display: 'block', width: 100 * ( 1 - data.activeclients / Search.includedServers.length ) + '%' } ); > $overlay.show(); > } else { > $overlay.find('.bar').css( { display: 'block', width: '100%' } ); >@@ -418,14 +464,6 @@ require( [ 'koha-backend', 'search', 'macros', 'marc-editor', 'marc-record', 'pr > $overlay.show(); > } > >- function showSearchTargets(data) { >- $('#search-targetsinfo').empty(); >- >- $.each( data, function( undef, target ) { >- $('#search-targetsinfo').append( '<li>' + target.name + ' (' + target.hits + ')' + '</li>' ); >- } ); >- } >- > function handleSearchError(error) { > if (error.code == 1) { > invalidateSearchResults(); >@@ -768,6 +806,12 @@ require( [ 'koha-backend', 'search', 'macros', 'marc-editor', 'marc-record', 'pr > return false; > } ); > >+ $( document ).on( 'click', 'a.search-nav', function() { >+ $("#search-overlay").show(); >+ Search.Fetch( $( this ).data( 'offset' ) ); >+ return false; >+ }); >+ > // Key bindings > bindGlobalKeys(); > >@@ -805,14 +849,13 @@ require( [ 'koha-backend', 'search', 'macros', 'marc-editor', 'marc-record', 'pr > }); > > // Start editor >- Preferences.Load( [% USER_INFO.0.borrowernumber %] ); >+ Preferences.Load( [% USER_INFO.0.borrowernumber || 0 %] ); > displayPreferences(editor); > makeAuthorisedValueWidgets( '' ); >- Search.Init( z3950Targets, { >+ Search.Init( { >+ page_size: 20, > onresults: function(data) { showSearchResults( editor, data ) }, >- onbytarget: showSearchTargets, > onerror: handleSearchError, >- oniniterror: handleSearchInitError, > } ); > > function finishCb() { >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/editor.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/editor.tt >index 17ef1b7..70d0c38 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/editor.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/editor.tt >@@ -75,13 +75,13 @@ > <fieldset class="brief"> > <ol> > <li><label for="search-by-keywords">Keywords:</label></li> >- <li><input class="search-box" data-qualifier="term=" id="search-by-keywords" placeholder="(Ctrl-Alt-K)" /></li> >+ <li><input class="search-box" data-qualifier="term" id="search-by-keywords" placeholder="(Ctrl-Alt-K)" /></li> > <li><label for="search-by-author">Author:</label></li> >- <li><input class="search-box" data-qualifier="Author-name=" id="search-by-author" placeholder="(Ctrl-Alt-A)" /></li> >+ <li><input class="search-box" data-qualifier="author" id="search-by-author" placeholder="(Ctrl-Alt-A)" /></li> > <li><label for="search-by-isbn">ISBN:</label></li> >- <li><input class="search-box" data-qualifier="Identifier-ISBN=" id="search-by-isbn" placeholder="(Ctrl-Alt-I)" /></li> >+ <li><input class="search-box" data-qualifier="isbn" id="search-by-isbn" placeholder="(Ctrl-Alt-I)" /></li> > <li><label for="search-by-title">Title:</label></li> >- <li><input class="search-box" data-qualifier="Title=" id="search-by-title" placeholder="(Ctrl-Alt-T)" /></li> >+ <li><input class="search-box" data-qualifier="title" id="search-by-title" placeholder="(Ctrl-Alt-T)" /></li> > <li><a href="#" id="show-advanced-search" title="Show advanced search (Ctrl-Alt-S)">Advanced »</a></li> > </fieldset> > </form> >@@ -106,51 +106,51 @@ > <ul id="advanced-search-fields"> > <li> > <label for="advanced-search-by-author">Author:</label> >- <input class="search-box" data-qualifier="Author-name=" id="advanced-search-by-author" /> >+ <input class="search-box" data-qualifier="author" id="advanced-search-by-author" /> > </li> > <li> > <label for="advanced-search-by-control-number">Control number:</label> >- <input class="search-box" data-qualifier="Local-number=" id="advanced-search-by-control-number" /> >+ <input class="search-box" data-qualifier="local_number" id="advanced-search-by-control-number" /> > </li> > <li> > <label for="advanced-search-by-dewey">Dewey number:</label> >- <input class="search-box" data-qualifier="Classification-Dewey=" id="advanced-search-by-dewey" /> >+ <input class="search-box" data-qualifier="cn_dewey" id="advanced-search-by-dewey" /> > </li> > <li> > <label for="advanced-search-by-isbn">ISBN:</label> >- <input class="search-box" data-qualifier="Identifier-ISBN=" id="advanced-search-by-isbn" /> >+ <input class="search-box" data-qualifier="isbn" id="advanced-search-by-isbn" /> > </li> > <li> > <label for="advanced-search-by-issn">ISSN:</label> >- <input class="search-box" data-qualifier="Identifier-ISSN=" id="advanced-search-by-issn" /> >+ <input class="search-box" data-qualifier="issn" id="advanced-search-by-issn" /> > </li> > <li> > <label for="advanced-search-by-lccn">LCCN:</label> >- <input class="search-box" data-qualifier="LC-card-number=" id="advanced-search-by-lccn" /> >+ <input class="search-box" data-qualifier="lccn" id="advanced-search-by-lccn" /> > </li> > <li> > <label for="advanced-search-by-lc-number">LC call number:</label> >- <input class="search-box" data-qualifier="Classification-LC=" id="advanced-search-by-lc-number" /> >+ <input class="search-box" data-qualifier="cn_lc" id="advanced-search-by-lc-number" /> > </li> > <li> > <label for="advanced-search-by-publisher-number">Publisher number:</label> >- <input class="search-box" data-qualifier="Identifier-publisher-for-music=" id="advanced-search-by-publisher-number" /> >+ <input class="search-box" data-qualifier="music_identifier" id="advanced-search-by-publisher-number" /> > </li> > <li> > <label for="advanced-search-by-standard-number">Standard number:</label> >- <input class="search-box" data-qualifier="Identifier-standard=" id="advanced-search-by-standard-number" /> >+ <input class="search-box" data-qualifier="standard_identifier" id="advanced-search-by-standard-number" /> > </li> > <li> > <label for="advanced-search-by-subject">Subject:</label> >- <input class="search-box" data-qualifier="Subject=" id="advanced-search-by-subject" /> >+ <input class="search-box" data-qualifier="subject" id="advanced-search-by-subject" /> > </li> > <li> > <label for="advanced-search-by-publication-date">Publication date:</label> >- <input class="search-box" data-qualifier="Date=" id="advanced-search-by-publication-date" /> >+ <input class="search-box" data-qualifier="date" id="advanced-search-by-publication-date" /> > </li> > <li> > <label for="advanced-search-by-title">Title:</label> >- <input class="search-box" data-qualifier="Title=" id="advanced-search-by-title" /> >+ <input class="search-box" data-qualifier="title" id="advanced-search-by-title" /> > </li> > </ul> > </form> >@@ -168,19 +168,30 @@ > <div class="span3"> > <div id="search-facets"> > <ul> >- <li>Targets:<ul id="search-targetsinfo"></ul></li> >+ <li>Servers:<ul id="search-serversinfo"></ul></li> > </ul> > </div> > </div> > <div class="span9"> > <div id="searchresults"> >+ <div id="search-top-pages"> >+ <div class="pagination pagination-small"> >+ </div> >+ </div> >+ > <table> > <thead> > <tr></tr> > </thead> > <tbody></tbody> > </table> >- <div id="search-overlay"><span>Loading...</span><div class="progress progress-striped active"><div class="bar" style="width: 0"></div></div></div> >+ >+ <div id="search-bottom-pages"> >+ <div class="pagination pagination-small"> >+ </div> >+ </div> >+ >+ <div id="search-overlay"><span>Loading...</span><div class="progress progress-striped active"><div class="bar" style="width: 100%"></div></div></div> > </div> > </div> > </div> >diff --git a/svc/z3950 b/svc/z3950 >new file mode 100755 >index 0000000..e0c07e3 >--- /dev/null >+++ b/svc/z3950 >@@ -0,0 +1,102 @@ >+#!/usr/bin/perl >+# >+# Copyright 2014 ByWater Solutions >+ >+# >+# 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 C4::Breeding qw( RunZ3950 ); >+use C4::Service; >+use Encode qw( encode_utf8 ); >+ >+use sort 'stable'; >+ >+my ( $query, $response ) = C4::Service->init( catalogue => 1 ); >+ >+my ( $query_string, $servers ) = C4::Service->require_params( 'q', 'servers' ); >+ >+my $server_hits = {}; >+my $server_errors = {}; >+ >+my $offset = $query->param( 'offset' ) || 0; >+my $page_size = $query->param( 'page_size' ) || 20; >+my $fetched = $query->param( 'fetched' ) || 100; >+my $empty_flip = -1; # Determines the flip of ordering for records with empty sort keys. >+ >+my @server_ids = split( /,/, $servers ); >+ >+my $stats = RunZ3950( \@server_ids, $query_string, { >+ on_error => sub { >+ my ( $server, $exception ) = @_; >+ >+ $server_errors->{ $server->{id} } = $exception->message; >+ }, >+ on_hit => sub { >+ my ( $server, $hit ) = @_; >+ >+ push @{ $server_hits->{ $server->{id} } }, { server => $server->{id}, >+ index => $hit->{index}, >+ record => encode_utf8( $hit->{record}->as_xml_record() ), >+ metadata => $hit->{metadata} >+ }; >+ }, >+ >+ offset => 0, >+ fetch => $fetched, >+} ); >+ >+my @hits; >+ >+foreach my $id ( @server_ids ) { >+ warn scalar @{ $server_hits->{$id} ||= [] } . ' hits from ' . $id; >+} >+ >+# Interleave hits; should be replaced by actual relevance ranking at some point >+foreach my $i ( 0..$fetched ) { >+ foreach my $id ( @server_ids ) { >+ my $hit = shift @{ $server_hits->{ $id } }; >+ next unless ( $hit ); >+ >+ ( $hit->{sort_key} = $hit->{metadata}->{title} || '' ) =~ s/\W//g; >+ push @hits, $hit; >+ } >+} >+ >+@hits = sort { >+ # Sort empty records at the end >+ return -$empty_flip unless $a->{sort_key}; >+ return $empty_flip unless $b->{sort_key}; >+ >+ $a->{sort_key} cmp $b->{sort_key}; >+} @hits; >+ >+my @hits_subset; >+ >+foreach my $i ( $offset..( $offset + $page_size - 1 ) ) { >+ push @hits_subset, $hits[$i] if $hits[$i]; >+} >+ >+$response->param( >+ offset => $offset, >+ page_size => $page_size, >+ errors => $server_errors, >+ hits => \@hits_subset, >+ %$stats >+); >+ >+C4::Service->return_success( $response ); >-- >2.1.4
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 11559
:
26069
|
26070
|
26071
|
26104
|
26653
|
26654
|
27140
|
27141
|
27142
|
27757
|
27758
|
27759
|
27760
|
27761
|
27900
|
27901
|
27902
|
27993
|
27995
|
34458
|
34459
|
34460
|
34461
|
34462
|
34463
|
36243
|
36244
|
36245
|
36246
|
36247
|
36248
|
36455
|
38533
|
38534
|
38535
|
38536
|
38537
|
38538
|
38539
|
40153
|
40154
|
40155
|
40543
|
40555
|
40556
|
40557
|
40558
|
40811
|
40812
|
40813
|
40814
|
40815
|
41425
|
41453
|
41476
|
42373
|
43261
|
43547
|
43614
|
43615
|
43616
|
43617
|
43618
|
43619
|
43620
|
43621
|
43622
|
43623
|
43703
|
43704
|
43705
|
43706
|
43707
|
43708
|
43709
|
43710
|
43711
|
43712
|
43713
|
43772
|
43790
|
43883
|
43969
|
44016
|
44018
|
44022
|
44023
|
44024
|
44025
|
44026
|
44027
|
44028
|
44029
|
44030
|
44031
|
44032
|
44033
|
44034
|
44035
|
44036