View | Details | Raw Unified | Return to bug 18823
Collapse All | Expand All

(-)a/Koha/MetaSearcher.pm (-37 / +131 lines)
Lines 56-64 sub new { Link Here
56
}
56
}
57
57
58
sub handle_hit {
58
sub handle_hit {
59
    my ( $self, $index, $server, $marcrecord ) = @_;
59
    my ( $self, $index, $server, $hit ) = @_;
60
60
61
    my $record = Koha::MetadataRecord->new( { schema => 'marc', record => $marcrecord } );
61
    my $record = Koha::MetadataRecord->new( { schema => 'marc', record => $hit->{record} } );
62
62
63
    my %fetch = (
63
    my %fetch = (
64
        title => 'biblio.title',
64
        title => 'biblio.title',
Lines 79-93 sub handle_hit { Link Here
79
    $metadata->{date} //= $metadata->{date2};
79
    $metadata->{date} //= $metadata->{date2};
80
80
81
    push @{ $self->{results} }, {
81
    push @{ $self->{results} }, {
82
        %$hit,
82
        server => $server,
83
        server => $server,
83
        index => $index,
84
        index => $index,
84
        record => $marcrecord,
85
        metadata => $metadata,
85
        metadata => $metadata,
86
    };
86
    };
87
}
87
}
88
88
89
sub search {
89
sub search {
90
    my ( $self, $server_ids, $query ) = @_;
90
    my ( $self, $server_ids, $terms ) = @_;
91
91
92
    my $resultset_expiry = 300;
92
    my $resultset_expiry = 300;
93
93
Lines 142-148 sub search { Link Here
142
            }
142
            }
143
        }
143
        }
144
144
145
        $select->add( $self->_start_worker( $server, $query ) );
145
        $select->add( $self->_start_worker( $server, $terms ) );
146
    }
146
    }
147
147
148
    # Handle these while the servers are searching
148
    # Handle these while the servers are searching
Lines 182-189 sub search { Link Here
182
    return $stats;
182
    return $stats;
183
}
183
}
184
184
185
our $_pqf_mapping = {
186
    author => '1=1004',
187
    'cn-dewey' => '1=13',
188
    'cn-lc' => '1=16',
189
    date => '1=30',
190
    isbn => '1=7',
191
    issn => '1=8',
192
    keyword => '1=1016',
193
    lccn => '1=9',
194
    'local-number' => '1=12',
195
    'music-identifier' => '1=51',
196
    'standard-identifier' => '1=1007',
197
    subject => '1=21',
198
    title => '1=4',
199
};
200
201
our $_batch_db_mapping = {
202
    author => 'import_biblios.author',
203
    isbn => 'import_biblios.isbn',
204
    issn => 'import_biblios.issn',
205
    'local-number' => 'import_biblios.control_number',
206
    title => 'import_biblios.title',
207
};
208
209
our $_batch_db_text_columns = {
210
    author => 1,
211
    keyword => 1,
212
    title => 1,
213
};
214
215
sub _pqf_query_from_terms {
216
    my ( $terms ) = @_;
217
218
    my $query;
219
220
    while ( my ( $index, $value ) = each %$terms ) {
221
        $value =~ s/"/\\"/;
222
223
        my $term = '@attr ' . $_pqf_mapping->{$index} . ' "' . $value . '"';
224
225
        if ( $query ) {
226
            $query = '@and ' . $query . ' ' . $term;
227
        } else {
228
            $query = $term;
229
        }
230
    }
231
232
    return $query;
233
}
234
235
sub _db_query_get_match_conditions {
236
    my ( $index, $value ) = @_;
237
238
    if ( $value =~ /\*/ ) {
239
        $value =~ s/\*/%/;
240
        return { -like => $value };
241
    } elsif ( $_batch_db_text_columns->{$index} ) {
242
        return map +{ -regexp => '[[:<:]]' . $_ . '[[:>:]]' }, split( /\s+/, $value );
243
    } else {
244
        return $value;
245
    }
246
}
247
248
sub _batch_db_query_from_terms {
249
    my ( $import_batch_id, $terms ) = @_;
250
251
    my @db_terms;
252
253
    while ( my ( $index, $value ) = each %$terms ) {
254
        if ( $index eq 'keyword' ) {
255
            my @term;
256
257
            while ( my ( $index, $db_column ) = each %$_batch_db_mapping ) {
258
                push @term, { $db_column => [ _db_query_get_match_conditions( $index, $value ) ] };
259
            }
260
261
            # These are implicitly joined with OR because the arrayref doesn't start with -and
262
            push @db_terms, \@term;
263
        } elsif ( $_batch_db_mapping->{$index} ) {
264
            push @db_terms, $_batch_db_mapping->{$index} => [ -and => _db_query_get_match_conditions( $index, $value ) ];
265
        } else {
266
            # No such index, we should fail
267
            return undef;
268
        }
269
    }
270
271
    return {
272
        -and => [
273
            import_batch_id => $import_batch_id,
274
            @db_terms
275
        ],
276
    },
277
}
278
185
sub _start_worker {
279
sub _start_worker {
186
    my ( $self, $server, $query ) = @_;
280
    my ( $self, $server, $terms ) = @_;
187
    pipe my $readfh, my $writefh;
281
    pipe my $readfh, my $writefh;
188
282
189
    # Accessing the cache or Koha database after the fork is risky, so get any resources we need
283
    # Accessing the cache or Koha database after the fork is risky, so get any resources we need
Lines 207-212 sub _start_worker { Link Here
207
    my $connection;
301
    my $connection;
208
    my ( $num_hits, $num_fetched, $hits, $results );
302
    my ( $num_hits, $num_fetched, $hits, $results );
209
303
304
    my $pqf_query = _pqf_query_from_terms( $terms );
305
210
    eval {
306
    eval {
211
        if ( $server->{type} eq 'z3950' ) {
307
        if ( $server->{type} eq 'z3950' ) {
212
            my $zoptions = ZOOM::Options->new();
308
            my $zoptions = ZOOM::Options->new();
Lines 220-285 sub _start_worker { Link Here
220
            $connection = ZOOM::Connection->create($zoptions);
316
            $connection = ZOOM::Connection->create($zoptions);
221
317
222
            $connection->connect( $server->{host}, $server->{port} );
318
            $connection->connect( $server->{host}, $server->{port} );
223
            $results = $connection->search_pqf( $query ); # Starts the search
319
            $results = $connection->search_pqf( $pqf_query ); # Starts the search
224
        } elsif ( $server->{type} eq 'koha' ) {
320
        } elsif ( $server->{type} eq 'koha' ) {
225
            $connection = C4::Context->Zconn( $server->{extra} );
321
            $connection = C4::Context->Zconn( $server->{extra} );
226
            $results = $connection->search_pqf( $query ); # Starts the search
322
            $results = $connection->search_pqf( $pqf_query ); # Starts the search
227
        } elsif ( $server->{type} eq 'batch' )  {
323
        } elsif ( $server->{type} eq 'batch' )  {
228
            $server->{encoding} = 'utf-8';
324
            $server->{encoding} = 'utf-8';
229
        }
325
        }
230
    };
326
    };
231
    if ($@) {
327
    if ($@) {
232
        store_fd {
328
        store_fd {
233
            error => $connection ? $connection->exception() : $@,
329
            error => $connection ? $connection->exception()->message() : $@,
234
            server => $server,
330
            server => $server,
235
        }, $writefh;
331
        }, $writefh;
236
        exit;
332
        exit;
237
    }
333
    }
238
334
335
    my $error;
239
    if ( $server->{type} eq 'batch' ) {
336
    if ( $server->{type} eq 'batch' ) {
240
        # TODO: actually handle PQF
241
        $query =~ s/@\w+ (?:\d+=\d+ )?//g;
242
        $query =~ s/"//g;
243
244
        my $schema = Koha::Database->new->schema;
337
        my $schema = Koha::Database->new->schema;
245
        $schema->storage->debug(1);
338
        my $db_query = _batch_db_query_from_terms( $server->{extra}, $terms );
246
        my $match_condition = [ map +{ -like => '%' . $_ . '%' }, split( /\s+/, $query ) ];
339
247
        $hits = [ $schema->resultset('ImportRecord')->search(
340
        if ( $db_query ) {
248
            {
341
            $hits = [ $schema->resultset('ImportRecord')->search(
249
                import_batch_id => $server->{extra},
342
                $db_query,
250
                -or => [
343
                {
251
                    { 'import_biblios.title' => $match_condition },
344
                    columns => [ 'import_record_id', { record => 'marc' } ],
252
                    { 'import_biblios.author' => $match_condition },
345
                    join => [ 'import_biblios' ],
253
                    { 'import_biblios.isbn' => $match_condition },
346
                    offset => $self->{offset},
254
                    { 'import_biblios.issn' => $match_condition },
347
                    result_class => 'DBIx::Class::ResultClass::HashRefInflator',
255
                ],
348
                    rows => $self->{fetch},
256
            },
349
                }
257
            {
350
            )->all ];
258
                join => [ qw( import_biblios ) ],
351
259
                rows => $self->{fetch},
352
            $num_hits = $num_fetched = scalar @$hits;
260
            }
353
        } else {
261
        )->get_column( 'marc' )->all ];
354
            $error = "Invalid search";
262
355
        }
263
        $num_hits = $num_fetched = scalar @$hits;
264
    } else {
356
    } else {
265
        $num_hits = $results->size;
357
        $num_hits = $results->size;
266
        $num_fetched = ( $self->{offset} + $self->{fetch} ) < $num_hits ? $self->{fetch} : $num_hits;
358
        $num_fetched = ( $self->{offset} + $self->{fetch} ) < $num_hits ? $self->{fetch} : $num_hits;
267
359
268
        $hits = [ map { $_->raw() } @{ $results->records( $self->{offset}, $num_fetched, 1 ) } ];
360
        $hits = [ map +{ record => $_->raw() }, @{ $results->records( $self->{offset}, $num_fetched, 1 ) } ];
361
362
        $error = $connection->exception()->message() if ( !@$hits && $connection && $connection->exception() );
269
    }
363
    }
270
364
271
    if ( !@$hits && $connection && $connection->exception() ) {
365
    if ( $error ) {
272
        store_fd {
366
        store_fd {
273
            error => $connection->exception(),
367
            error => $error,
274
            server => $server,
368
            server => $server,
275
        }, $writefh;
369
        }, $writefh;
276
        exit;
370
        exit;
277
    }
371
    }
278
372
279
    if ( $server->{type} eq 'koha' ) {
373
    if ( $server->{type} eq 'koha' ) {
280
        $hits = [ map { C4::Search::new_record_from_zebra( $server->{extra}, $_ ) } @$hits ];
374
        $hits = [ map +{ %$_, record => C4::Search::new_record_from_zebra( $server->{extra}, $_->{record} ) }, @$hits ];
281
    } else {
375
    } else {
282
        $hits = [ map { $self->_import_record( $_, $marcflavour, $server->{encoding} ? $server->{encoding} : "iso-5426" ) } @$hits ];
376
        $hits = [ map +{ %$_, record => $self->_import_record( $_->{record}, $marcflavour, $server->{encoding} ? $server->{encoding} : "iso-5426" ) }, @$hits ];
283
    }
377
    }
284
378
285
    store_fd {
379
    store_fd {
(-)a/installer/data/mysql/mandatory/auth_val_cat.sql (-1 / +2 lines)
Lines 44-50 INSERT IGNORE INTO authorised_value_categories( category_name ) Link Here
44
    ('HINGS_C'),
44
    ('HINGS_C'),
45
    ('HINGS_AS'),
45
    ('HINGS_AS'),
46
    ('HINGS_RD'),
46
    ('HINGS_RD'),
47
    ('STACK');
47
    ('STACK'),
48
    ('CONTROL_NUM_SEQUENCE');
48
49
49
-- UNIMARC specific?
50
-- UNIMARC specific?
50
INSERT IGNORE INTO authorised_value_categories( category_name ) VALUES
51
INSERT IGNORE INTO authorised_value_categories( category_name ) VALUES
(-)a/koha-tmpl/intranet-tmpl/lib/koha/cateditor/preferences.js (+1 lines)
Lines 30-35 define( function() { Link Here
30
            Preferences.user = $.extend( {
30
            Preferences.user = $.extend( {
31
                // Preference defaults
31
                // Preference defaults
32
                enabledBatches: {},
32
                enabledBatches: {},
33
                enabledSearchBatches: {},
33
                fieldWidgets: true,
34
                fieldWidgets: true,
34
                font: 'monospace',
35
                font: 'monospace',
35
                fontSize: '1em',
36
                fontSize: '1em',
(-)a/koha-tmpl/intranet-tmpl/lib/koha/cateditor/search.js (-37 / +11 lines)
Lines 22-63 define( [ 'koha-backend', 'marc-record' ], function( KohaBackend, MARC ) { Link Here
22
    var _records = {};
22
    var _records = {};
23
    var _last;
23
    var _last;
24
24
25
    var _pqfMapping = {
26
        author: '1=1004', // s=al',
27
        cn_dewey: '1=13',
28
        cn_lc: '1=16',
29
        date: '1=30', // r=r',
30
        isbn: '1=7',
31
        issn: '1=8',
32
        lccn: '1=9',
33
        local_number: '1=12',
34
        music_identifier: '1=51',
35
        standard_identifier: '1=1007',
36
        subject: '1=21', // s=al',
37
        term: '1=1016', // t=l,r s=al',
38
        title: '1=4', // s=al',
39
    }
40
41
    var Search = {
25
    var Search = {
42
        Init: function( options ) {
26
        Init: function( options ) {
43
            _options = options;
27
            _options = options;
44
        },
28
        },
45
        JoinTerms: function( terms ) {
29
        Run: function( servers, terms, options ) {
46
            var q = '';
47
48
            $.each( terms, function( i, term ) {
49
                var term = '@attr ' + _pqfMapping[ term[0] ] + ' "' + term[1].replace( '"', '\\"' ) + '"'
50
51
                if ( q ) {
52
                    q = '@and ' + q + ' ' + term;
53
                } else {
54
                    q = term;
55
                }
56
            } );
57
58
            return q;
59
        },
60
        Run: function( servers, q, options ) {
61
            options = $.extend( {
30
            options = $.extend( {
62
                offset: 0,
31
                offset: 0,
63
                page_size: 20,
32
                page_size: 20,
Lines 67-76 define( [ 'koha-backend', 'marc-record' ], function( KohaBackend, MARC ) { Link Here
67
            _records = {};
36
            _records = {};
68
            _last = {
37
            _last = {
69
                servers: servers,
38
                servers: servers,
70
                q: q,
39
                terms: terms,
71
                options: options,
40
                options: options,
72
            };
41
            };
73
42
43
            var newTerms = {};
44
            $.each( terms, function( index, value ) {
45
                newTerms[ "term-" + index ] = value;
46
            } );
47
            terms = newTerms;
48
74
            var itemTag = KohaBackend.GetSubfieldForKohaField('items.itemnumber')[0];
49
            var itemTag = KohaBackend.GetSubfieldForKohaField('items.itemnumber')[0];
75
50
76
            $.each( servers, function ( id, info ) {
51
            $.each( servers, function ( id, info ) {
Lines 81-95 define( [ 'koha-backend', 'marc-record' ], function( KohaBackend, MARC ) { Link Here
81
56
82
            $.get(
57
            $.get(
83
                '/cgi-bin/koha/svc/cataloguing/metasearch',
58
                '/cgi-bin/koha/svc/cataloguing/metasearch',
84
                {
59
                $.extend( {
85
                    q: q,
86
                    servers: Search.includedServers.join( ',' ),
60
                    servers: Search.includedServers.join( ',' ),
87
                    offset: options.offset,
61
                    offset: options.offset,
88
                    page_size: options.page_size,
62
                    page_size: options.page_size,
89
                    sort_direction: options.sort_direction,
63
                    sort_direction: options.sort_direction,
90
                    sort_key: options.sort_key,
64
                    sort_key: options.sort_key,
91
                    resultset: options.resultset,
65
                    resultset: options.resultset,
92
                }
66
                }, terms )
93
            )
67
            )
94
                .done( function( data ) {
68
                .done( function( data ) {
95
                    _last.options.resultset = data.resultset;
69
                    _last.options.resultset = data.resultset;
Lines 115-121 define( [ 'koha-backend', 'marc-record' ], function( KohaBackend, MARC ) { Link Here
115
        Fetch: function( options ) {
89
        Fetch: function( options ) {
116
            if ( !_last ) return;
90
            if ( !_last ) return;
117
            $.extend( _last.options, options );
91
            $.extend( _last.options, options );
118
            return Search.Run( _last.servers, _last.q, _last.options );
92
            return Search.Run( _last.servers, _last.terms, _last.options );
119
        }
93
        }
120
    };
94
    };
121
95
(-)a/koha-tmpl/intranet-tmpl/prog/css/cateditor.css (+9 lines)
Lines 161-166 body { Link Here
161
    padding: 2px;
161
    padding: 2px;
162
}
162
}
163
163
164
#editor .subfield-widget button {
165
    font-family: inherit;
166
    font-size: inherit;
167
    height: 1.5em;
168
    line-height: 1em;
169
    margin-left: 5px;
170
    vertical-align: middle;
171
}
172
164
#editor .subfield-widget select, #editor .subfield-widget input {
173
#editor .subfield-widget select, #editor .subfield-widget input {
165
    height: 1.5em;
174
    height: 1.5em;
166
    vertical-align: middle;
175
    vertical-align: middle;
(-)a/koha-tmpl/intranet-tmpl/prog/en/includes/cateditor-ui.inc (-37 / +57 lines)
Lines 37-42 require( [ 'koha-backend', 'search', 'macros', 'marc-editor', 'marc-record', 'pr Link Here
37
        'koha:biblioserver': {
37
        'koha:biblioserver': {
38
            name: _("Local catalog"),
38
            name: _("Local catalog"),
39
            recordtype: 'biblio',
39
            recordtype: 'biblio',
40
            enabled: true,
40
            checked: false,
41
            checked: false,
41
        },
42
        },
42
        [%- FOREACH batch = editable_batches -%]
43
        [%- FOREACH batch = editable_batches -%]
Lines 51-56 require( [ 'koha-backend', 'search', 'macros', 'marc-editor', 'marc-record', 'pr Link Here
51
                name: '[% server.servername | html %]',
52
                name: '[% server.servername | html %]',
52
                recordtype: '[% server.recordtype | html %]',
53
                recordtype: '[% server.recordtype | html %]',
53
                checked: [% server.checked ? 'true' : 'false' | html %],
54
                checked: [% server.checked ? 'true' : 'false' | html %],
55
                enabled: true,
54
            },
56
            },
55
        [%- END -%]
57
        [%- END -%]
56
    };
58
    };
Lines 165-181 require( [ 'koha-backend', 'search', 'macros', 'marc-editor', 'marc-record', 'pr Link Here
165
167
166
        $('#quicksearch .search-box').each( function() {
168
        $('#quicksearch .search-box').each( function() {
167
            shortcut.add( 'enter', $.proxy( function() {
169
            shortcut.add( 'enter', $.proxy( function() {
168
                var terms = [];
170
                var terms = {};
169
171
170
                $('#quicksearch .search-box').each( function() {
172
                $('#quicksearch .search-box').each( function() {
171
                    if ( !this.value ) return;
173
                    if ( !this.value ) return;
172
174
173
                    terms.push( [ $(this).data('qualifier'), this.value ] );
175
                    terms[ $(this).data('qualifier') ] = this.value;
174
                } );
176
                } );
175
177
176
                if ( !terms.length ) return;
178
                if ( $.isEmptyObject(terms) ) return;
177
179
178
                if ( Search.Run( z3950Servers, Search.JoinTerms(terms) ) ) {
180
                if ( Search.Run( z3950Servers, terms ) ) {
179
                    $("#search-overlay").show();
181
                    $("#search-overlay").show();
180
                    showResultsBox();
182
                    showResultsBox();
181
                }
183
                }
Lines 366-371 require( [ 'koha-backend', 'search', 'macros', 'marc-editor', 'marc-record', 'pr Link Here
366
        $( '#save-targets input[data-target-id="' + target_id + '"]' ).closest('li').toggle(enabled);
368
        $( '#save-targets input[data-target-id="' + target_id + '"]' ).closest('li').toggle(enabled);
367
    }
369
    }
368
370
371
    function setSearchTargetChecked( server_id, checked ) {
372
        if ( z3950Servers[server_id] == null ) return;
373
374
        z3950Servers[server_id].checked = checked;
375
        $( '.search-target-list li[data-server-id="' + server_id + '"] input' ).prop('checked', checked);
376
    }
377
378
    function setSearchTargetEnabled( server_id, enabled ) {
379
        if ( !enabled ) {
380
            setSearchTargetChecked( server_id, false );
381
        }
382
383
        z3950Servers[server_id].enabled = enabled;
384
        $( '.search-target-list li[data-server-id="' + server_id + '"]' ).toggle(enabled);
385
    }
386
369
    function setSource(parts) {
387
    function setSource(parts) {
370
        state.backend = parts[0];
388
        state.backend = parts[0];
371
        state.recordID = parts[1];
389
        state.recordID = parts[1];
Lines 466-488 require( [ 'koha-backend', 'search', 'macros', 'marc-editor', 'marc-record', 'pr Link Here
466
    function showAdvancedSearch() {
484
    function showAdvancedSearch() {
467
        $('#advanced-search-servers').empty();
485
        $('#advanced-search-servers').empty();
468
        $.each( z3950Servers, function( server_id, server ) {
486
        $.each( z3950Servers, function( server_id, server ) {
487
            if ( !server.enabled ) return;
469
            $('#advanced-search-servers').append( '<li data-server-id="' + server_id + '"><label><input class="search-toggle-server" type="checkbox"' + ( server.checked ? ' checked="checked">' : '>' ) + server.name + '</label></li>' );
488
            $('#advanced-search-servers').append( '<li data-server-id="' + server_id + '"><label><input class="search-toggle-server" type="checkbox"' + ( server.checked ? ' checked="checked">' : '>' ) + server.name + '</label></li>' );
470
        } );
489
        } );
471
        $('#advanced-search-ui').modal('show');
490
        $('#advanced-search-ui').modal('show');
472
    }
491
    }
473
492
474
    function startAdvancedSearch() {
493
    function startAdvancedSearch() {
475
        var terms = [];
494
        var terms = {};
476
495
477
        $('#advanced-search-ui .search-box').each( function() {
496
        $('#advanced-search-ui .search-box').each( function() {
478
            if ( !this.value ) return;
497
            if ( !this.value ) return;
479
498
480
            terms.push( [ $(this).data('qualifier'), this.value ] );
499
            terms[ $(this).data('qualifier') ] = this.value;
481
        } );
500
        } );
482
501
483
        if ( !terms.length ) return;
502
        if ( $.isEmptyObject(terms) ) return;
484
503
485
        if ( Search.Run( z3950Servers, Search.JoinTerms(terms) ) ) {
504
        if ( Search.Run( z3950Servers, terms ) ) {
486
            $('#advanced-search-ui').modal('hide');
505
            $('#advanced-search-ui').modal('hide');
487
            $("#search-overlay").show();
506
            $("#search-overlay").show();
488
            showResultsBox();
507
            showResultsBox();
Lines 555-573 require( [ 'koha-backend', 'search', 'macros', 'marc-editor', 'marc-record', 'pr Link Here
555
        $.each( data.hits, function( undef, hit ) {
574
        $.each( data.hits, function( undef, hit ) {
556
            backends.search.records[ hit.server + ':' + hit.index ] = hit.record;
575
            backends.search.records[ hit.server + ':' + hit.index ] = hit.record;
557
576
558
            switch ( hit.server ) {
577
            hit.id = 'search/' + hit.server + ':' + hit.index;
559
                case 'koha:biblioserver':
578
            if ( hit.server == 'koha:biblioserver' ) {
560
                    var bibnumField = hit.record.field( bibnumMap[0] );
579
                var bibnumField = hit.record.field( bibnumMap[0] );
561
562
                    if ( bibnumField && bibnumField.hasSubfield( bibnumMap[1] ) ) {
563
                        hit.id = 'catalog/' + bibnumField.subfield( bibnumMap[1] );
564
                        break;
565
                    }
566
567
                    // Otherwise, fallthrough
568
580
569
                default:
581
                if ( bibnumField && bibnumField.hasSubfield( bibnumMap[1] ) ) {
570
                    hit.id = 'search/' + hit.server + ':' + hit.index;
582
                    hit.id = 'catalog/' + bibnumField.subfield( bibnumMap[1] );
583
                }
584
            } else if ( /^batch:/.test(hit.server) && hit.import_record_id ) {
585
                hit.id = hit.server + '/' + hit.import_record_id;
571
            }
586
            }
572
587
573
            var result = '<tr>';
588
            var result = '<tr>';
Lines 688-696 require( [ 'koha-backend', 'search', 'macros', 'marc-editor', 'marc-record', 'pr Link Here
688
        switch (pref) {
703
        switch (pref) {
689
            case 'enabledBatches':
704
            case 'enabledBatches':
690
                $.each( editable_batches, function( batch_id, batch ) {
705
                $.each( editable_batches, function( batch_id, batch ) {
691
                    $( '#batches-list li[data-batch-id=' + batch_id + '] input' )[0].checked = Preferences.user.enabledBatches[batch_id];
706
                    $( '#batches-table tr[data-batch-id=' + batch_id + '] input.is-save-target' )[0].checked = Preferences.user.enabledBatches[batch_id];
692
                    setSaveTargetEnabled( 'batch:' + batch_id + '/', Preferences.user.enabledBatches[batch_id] || false );
707
                    setSaveTargetEnabled( 'batch:' + batch_id + '/', Preferences.user.enabledBatches[batch_id] || false );
693
                } );
708
                } );
709
            case 'enabledSearchBatches':
710
                $.each( editable_batches, function( batch_id, batch ) {
711
                    $( '#batches-table tr[data-batch-id=' + batch_id + '] input.is-searchable' )[0].checked = Preferences.user.enabledSearchBatches[batch_id];
712
                    setSearchTargetEnabled( 'batch:' + batch_id, Preferences.user.enabledSearchBatches[batch_id] || false );
713
                } );
694
            case 'fieldWidgets':
714
            case 'fieldWidgets':
695
                $( '#set-field-widgets' ).text( value ? _("Show fields verbatim") : _("Show helpers for fixed and coded fields") );
715
                $( '#set-field-widgets' ).text( value ? _("Show fields verbatim") : _("Show helpers for fixed and coded fields") );
696
                break;
716
                break;
Lines 719-731 require( [ 'koha-backend', 'search', 'macros', 'marc-editor', 'marc-record', 'pr Link Here
719
                    if ( saved_val != null ) setSaveTargetChecked( target_id, saved_val );
739
                    if ( saved_val != null ) setSaveTargetChecked( target_id, saved_val );
720
                } );
740
                } );
721
                break;
741
                break;
722
            case 'selected_search_targets':
723
                $.each( z3950Servers, function( server_id, server ) {
724
                    var saved_val = Preferences.user.selected_search_targets[server_id];
725
726
                    if ( saved_val != null ) server.checked = saved_val;
727
                } );
728
                break;
729
        }
742
        }
730
    }
743
    }
731
744
Lines 750-757 require( [ 'koha-backend', 'search', 'macros', 'marc-editor', 'marc-record', 'pr Link Here
750
763
751
        switch (pref) {
764
        switch (pref) {
752
            case 'enabledBatches':
765
            case 'enabledBatches':
753
                _addLiveHandler( '#batches-list input', 'change', function() {
766
                _addLiveHandler( '#batches-table input.is-save-target', 'change', function() {
754
                    Preferences.user.enabledBatches[ $( this ).closest('li').data('batch-id') ] = this.checked;
767
                    Preferences.user.enabledBatches[ $( this ).closest('tr').data('batch-id') ] = this.checked;
768
                } );
769
                break;
770
            case 'enabledSearchBatches':
771
                _addLiveHandler( '#batches-table input.is-searchable', 'change', function() {
772
                    Preferences.user.enabledSearchBatches[ $( this ).closest('tr').data('batch-id') ] = this.checked;
755
                } );
773
                } );
756
                break;
774
                break;
757
            case 'fieldWidgets':
775
            case 'fieldWidgets':
Lines 908-921 require( [ 'koha-backend', 'search', 'macros', 'marc-editor', 'marc-record', 'pr Link Here
908
        };
926
        };
909
927
910
        // Build batch UI
928
        // Build batch UI
911
        var $batch_entry = $( '<li data-batch-id="' + batch.batch_id + '"><input type="checkbox" />' + batch.name + '</li>' );
929
        var $batch_entry = $( '<tr data-batch-id="' + batch.batch_id + '"><td>' + batch.name + '</td><td><input type="checkbox" class="is-searchable" /></td><td><input type="checkbox" class="is-save-target" /></td></tr>' );
912
930
913
        var $batch_buttons = $('<span class="batch-buttons"></span>').appendTo($batch_entry);
931
        var $batch_buttons = $('<td class="batch-buttons"></td>').appendTo($batch_entry);
914
        var $export_button = $( '<button>' + _("Export...") + '</button>' ).appendTo($batch_buttons).click( function() {
932
        var $export_button = $( '<button>' + _("Export...") + '</button>' ).appendTo($batch_buttons).click( function() {
915
            $('#batches-list .batch-export').hide();
933
            $('#batches-table .batch-export').hide();
916
            $export_screen.show();
934
            $export_screen.show();
917
        } );
935
        } );
918
936
937
        timestamp_pattern = '\\d{4}(0\\d|1[012])([012]\\d|3[01])(([01]\\d|2[0-3])[0-5]\\d[0-5]\\d)?'
938
919
        var $export_screen = $(
939
        var $export_screen = $(
920
            '<form class="batch-export form-horizontal" style="display: none">'
940
            '<form class="batch-export form-horizontal" style="display: none">'
921
            + '<div class="control-group">'
941
            + '<div class="control-group">'
Lines 923-936 require( [ 'koha-backend', 'search', 'macros', 'marc-editor', 'marc-record', 'pr Link Here
923
            + '<div class="controls"><input class="batch-control-number-start" type="text"> - <input class="batch-control-number-end" type="text"></div>'
943
            + '<div class="controls"><input class="batch-control-number-start" type="text"> - <input class="batch-control-number-end" type="text"></div>'
924
            + '</div>'
944
            + '</div>'
925
            + '<label class="control-label">' + _("Timestamp range (YYYYMMDD or YYYMMDDHHMMSS):") + '</label>'
945
            + '<label class="control-label">' + _("Timestamp range (YYYYMMDD or YYYMMDDHHMMSS):") + '</label>'
926
            + '<div class="controls"><input class="batch-timestamp-start" type="text"> - <input class="batch-timestamp-end" type="text"></div>'
946
            + '<div class="controls"><input class="batch-timestamp-start" type="text" pattern="' + timestamp_pattern + '"> - <input class="batch-timestamp-end" type="text" pattern="' + timestamp_pattern + '"></div>'
927
            + '</div>'
947
            + '</div>'
928
            + '<div class="control-group">'
948
            + '<div class="control-group">'
929
            + '<div class="controls"><button class="batch-export-start">' + _("Start export") + '</div>'
949
            + '<div class="controls"><button class="batch-export-start">' + _("Start export") + '</div>'
930
            + '</form>'
950
            + '</form>'
931
        ).appendTo($batch_entry);
951
        ).appendTo($batch_buttons);
932
952
933
        $export_screen.find('.batch-export-start').click( function() {
953
        $export_screen.submit( function() {
934
            function getFormVal(name) {
954
            function getFormVal(name) {
935
                return $export_screen.find( '.batch-' + name ).val();
955
                return $export_screen.find( '.batch-' + name ).val();
936
            }
956
            }
Lines 945-951 require( [ 'koha-backend', 'search', 'macros', 'marc-editor', 'marc-record', 'pr Link Here
945
            KohaBackend.StartBatchExport( batch.batch_id, options );
965
            KohaBackend.StartBatchExport( batch.batch_id, options );
946
        } );
966
        } );
947
967
948
        $('#batches-list').append( $batch_entry );
968
        $('#batches-table tbody').append( $batch_entry );
949
    }
969
    }
950
970
951
    $(document).ready( function() {
971
    $(document).ready( function() {
(-)a/koha-tmpl/intranet-tmpl/prog/en/includes/cateditor-widgets-marc21.inc (-1 / +60 lines)
Lines 85-91 Link Here
85
 * single subfield, '@'.
85
 * single subfield, '@'.
86
 */
86
 */
87
87
88
require( [ 'widget' ], function( Widget ) {
88
require( [ 'koha-backend', 'widget' ], function( KohaBackend, Widget ) {
89
    Widget.Register( '000@', {
89
    Widget.Register( '000@', {
90
        makeTemplate: function() {
90
        makeTemplate: function() {
91
            return '     nam a22     7a 4500';
91
            return '     nam a22     7a 4500';
Lines 113-118 require( [ 'widget' ], function( Widget ) { Link Here
113
        },
113
        },
114
    } );
114
    } );
115
115
116
    /* Check to see if there are any Control Number entries
117
     *  in the authorised values table.
118
     * If not, let's not show the widget
119
     */
120
    var reg001 = KohaBackend.GetAuthorisedValues( 'CONTROL_NUM_SEQUENCE');
121
    if(reg001) {
122
123
        Widget.Register( '001@', {
124
            init: function() {
125
                var $result = $(
126
                    '<span class="subfield-widget">'
127
                    + _("Control number: ")
128
                    + '<span class="control-number-widget-contents"></span>'
129
                    + '<button class="control-number-widget-assign">' + _("Assign next") + '</button>'
130
                    + '<select class="control-number-widget-sequence"></select>'
131
                    + '<button class="control-number-widget-override">' + _("Override") + '</button>'
132
                    + '</span>'
133
                );
134
135
                return $result[0];
136
            },
137
            setControlNumber: function( text ) {
138
                if ( text ) this.setText( text );
139
                $( this.node ).find('.control-number-widget-contents')
140
                    .html( text == '<empty>' ? ( '<span class="hint">' + _("unset") + '</span>' ) : text );
141
                this.mark.changed();
142
            },
143
            postCreate: function( node, mark ) {
144
                var widget = this;
145
                this.setControlNumber( this.text );
146
                $( this.node )
147
                    .find('.control-number-widget-assign').click( function() {
148
                        var sequence = $( widget.node ).find('.control-number-widget-sequence').val();
149
                        $.post(
150
                            '/cgi-bin/koha/svc/cataloguing/control_num_sequences/' + sequence
151
                        ).done( function( result ) {
152
                            if ( result.next_value ) widget.setControlNumber( result.next_value );
153
                        } );
154
                    } ).end()
155
                    .find('.control-number-widget-override').click( function() {
156
                        var result = prompt( _("Enter new control number") );
157
158
                        if ( result ) widget.setControlNumber( result );
159
                    } ).end();
160
161
                var sequence_list = $.map( reg001 , function( authval ) {
162
                    return authval.lib;
163
                } );
164
                sequence_list.sort();
165
166
                $.each( sequence_list, function( undef, sequence ) {
167
                    $( widget.node ).find('.control-number-widget-sequence').append( '<option>' + sequence + '</option>' );
168
                } );
169
170
                // TODO: Make Enter on select click "Assign"
171
            }
172
        } );
173
        };
174
116
    Widget.Register( '005@', {
175
    Widget.Register( '005@', {
117
        init: function() {
176
        init: function() {
118
            var $result = $( '<span class="subfield-widget fixed-widget">' + _("Updated: ") + '</span>' );
177
            var $result = $( '<span class="subfield-widget fixed-widget">' + _("Updated: ") + '</span>' );
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/editor.tt (-9 / +20 lines)
Lines 101-107 Link Here
101
    <fieldset class="brief">
101
    <fieldset class="brief">
102
    <ol>
102
    <ol>
103
        <li><label for="search-by-keywords">Keywords:</label></li>
103
        <li><label for="search-by-keywords">Keywords:</label></li>
104
        <li><input class="search-box" data-qualifier="term" id="search-by-keywords" placeholder="(Ctrl-Alt-K)" /></li>
104
        <li><input class="search-box" data-qualifier="keyword" id="search-by-keywords" placeholder="(Ctrl-Alt-K)" /></li>
105
        <li><label for="search-by-author">Author:</label></li>
105
        <li><label for="search-by-author">Author:</label></li>
106
        <li><input class="search-box" data-qualifier="author" id="search-by-author" placeholder="(Ctrl-Alt-A)" /></li>
106
        <li><input class="search-box" data-qualifier="author" id="search-by-author" placeholder="(Ctrl-Alt-A)" /></li>
107
        <li><label for="search-by-isbn">ISBN:</label></li>
107
        <li><label for="search-by-isbn">ISBN:</label></li>
Lines 138-144 Link Here
138
    <div class="col-md-3">
138
    <div class="col-md-3">
139
        <div id="search-facets">
139
        <div id="search-facets">
140
            <ul>
140
            <ul>
141
                <li>Servers:<ul id="advanced-search-servers"></ul></li>
141
                <li>Servers:<ul id="advanced-search-servers" class="search-target-list"></ul></li>
142
            </ul>
142
            </ul>
143
        </div>
143
        </div>
144
    </div>
144
    </div>
Lines 170-176 Link Here
170
            </li>
170
            </li>
171
            <li>
171
            <li>
172
                <label for="advanced-search-by-lc-number">LC call number:</label>
172
                <label for="advanced-search-by-lc-number">LC call number:</label>
173
                <input class="search-box" data-qualifier="cn_lc" id="advanced-search-by-lc-number" />
173
                <input class="search-box" data-qualifier="cn-lc" id="advanced-search-by-lc-number" />
174
            </li>
174
            </li>
175
            <li>
175
            <li>
176
                <label for="advanced-search-by-lccn">LCCN:</label>
176
                <label for="advanced-search-by-lccn">LCCN:</label>
Lines 178-196 Link Here
178
            </li>
178
            </li>
179
            <li>
179
            <li>
180
                <label for="advanced-search-by-control-number">Control number:</label>
180
                <label for="advanced-search-by-control-number">Control number:</label>
181
                <input class="search-box" data-qualifier="local_number" id="advanced-search-by-control-number" />
181
                <input class="search-box" data-qualifier="local-number" id="advanced-search-by-control-number" />
182
            </li>
182
            </li>
183
            <li>
183
            <li>
184
                <label for="advanced-search-by-dewey">Dewey number:</label>
184
                <label for="advanced-search-by-dewey">Dewey number:</label>
185
                <input class="search-box" data-qualifier="cn_dewey" id="advanced-search-by-dewey" />
185
                <input class="search-box" data-qualifier="cn-dewey" id="advanced-search-by-dewey" />
186
            </li>
186
            </li>
187
            <li>
187
            <li>
188
                <label for="advanced-search-by-standard-number">Standard number:</label>
188
                <label for="advanced-search-by-standard-number">Standard number:</label>
189
                <input class="search-box" data-qualifier="standard_identifier" id="advanced-search-by-standard-number" />
189
                <input class="search-box" data-qualifier="standard-identifier" id="advanced-search-by-standard-number" />
190
            </li>
190
            </li>
191
            <li>
191
            <li>
192
                <label for="advanced-search-by-publisher-number">Publisher number:</label>
192
                <label for="advanced-search-by-publisher-number">Publisher number:</label>
193
                <input class="search-box" data-qualifier="music_identifier" id="advanced-search-by-publisher-number" />
193
                <input class="search-box" data-qualifier="music-identifier" id="advanced-search-by-publisher-number" />
194
            </li>
194
            </li>
195
            <li>
195
            <li>
196
                <label for="advanced-search-by-publication-date">Publication date:</label>
196
                <label for="advanced-search-by-publication-date">Publication date:</label>
Lines 219-225 Link Here
219
    <div class="col-md-3">
219
    <div class="col-md-3">
220
        <div id="search-facets">
220
        <div id="search-facets">
221
            <ul>
221
            <ul>
222
                <li>Servers:<ul id="search-serversinfo"></ul></li>
222
                <li>Servers:<ul id="search-serversinfo" class="search-target-list"></ul></li>
223
            </ul>
223
            </ul>
224
        </div>
224
        </div>
225
    </div>
225
    </div>
Lines 291-297 Link Here
291
            <button class="btn btn-small" type="submit" id="create-batch"><i class="icon-plus"></i> <span>Create new batch...</span></button>
291
            <button class="btn btn-small" type="submit" id="create-batch"><i class="icon-plus"></i> <span>Create new batch...</span></button>
292
            <button class="btn btn-small" type="submit" id="manage-batches"><i class="icon-list"></i> <span>Manage import batches...</span></button>
292
            <button class="btn btn-small" type="submit" id="manage-batches"><i class="icon-list"></i> <span>Manage import batches...</span></button>
293
        </div>
293
        </div>
294
        <ul id="batches-list"></ul>
294
        <table id="batches-table">
295
            <thead>
296
                <tr>
297
                    <th>Batch</th>
298
                    <th>Searchable?</th>
299
                    <th>Save target?</th>
300
                    <th>&nbsp;</th>
301
                </tr>
302
            </thead>
303
            <tbody>
304
            </tbody>
305
        </table>
295
    </div>
306
    </div>
296
    <div class="span3">
307
    <div class="span3">
297
    </div>
308
    </div>
(-)a/svc/cataloguing/metasearch (-5 / +13 lines)
Lines 25-31 use Koha::MetaSearcher; Link Here
25
25
26
my ( $query, $response ) = C4::Service->init( catalogue => 1 );
26
my ( $query, $response ) = C4::Service->init( catalogue => 1 );
27
27
28
my ( $query_string, $servers ) = C4::Service->require_params( 'q', 'servers' );
28
my ( $servers ) = C4::Service->require_params( 'servers' );
29
29
30
my $server_errors = {};
30
my $server_errors = {};
31
31
Lines 35-53 my $offset = $query->param( 'offset' ) || 0; Link Here
35
my $page_size = $query->param( 'page_size' ) || 20;
35
my $page_size = $query->param( 'page_size' ) || 20;
36
my $fetched = $query->param( 'fetched' ) || 100;
36
my $fetched = $query->param( 'fetched' ) || 100;
37
37
38
my $terms = {};
39
40
foreach my $term ( $query->param ) {
41
    next unless ( $term =~ /^term-([A-Za-z0-9-]+)/ );
42
43
    $terms->{$1} = $query->param($term);
44
}
45
38
my $searcher = Koha::MetaSearcher->new( {
46
my $searcher = Koha::MetaSearcher->new( {
39
    fetched => $fetched,
47
    fetched => $fetched,
40
    on_error => sub {
48
    on_error => sub {
41
        my ( $server, $exception ) = @_;
49
        my ( $server, $exception ) = @_;
42
50
43
        $server_errors->{ $server->{id} } = $exception->message;
51
        $server_errors->{ $server->{id} } = $exception;
44
    },
52
    },
45
} );
53
} );
46
54
47
$searcher->resultset( $query->param('resultset') ) if ( $query->param('resultset') );
55
$searcher->resultset( $query->param('resultset') ) if ( $query->param('resultset') );
48
56
49
my @server_ids = split( /,/, $servers );
57
my @server_ids = split( /,/, $servers );
50
my $stats = $searcher->search( \@server_ids, $query_string );
58
my $stats = $searcher->search( \@server_ids, $terms );
51
59
52
$searcher->sort( $sort_key, $sort_direction eq 'desc' ? -1 : 1 );
60
$searcher->sort( $sort_key, $sort_direction eq 'desc' ? -1 : 1 );
53
61
Lines 55-64 my @hits; Link Here
55
63
56
foreach my $hit ( $searcher->results( $offset, $page_size ) ) {
64
foreach my $hit ( $searcher->results( $offset, $page_size ) ) {
57
    push @hits, {
65
    push @hits, {
66
        %$hit,
58
        server => $hit->{server}->{id},
67
        server => $hit->{server}->{id},
59
        index => $hit->{index},
68
        index => $hit->{index},
60
        record => $hit->{record}->as_xml_record(),
69
        record => $hit->{record}->as_xml_record(),
61
        metadata => $hit->{metadata}
70
        metadata => $hit->{metadata},
62
    };
71
    };
63
}
72
}
64
73
65
- 

Return to bug 18823