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

(-)a/Koha/BackgroundJob.pm (+14 lines)
Lines 472-477 sub plugin_types_to_classes { Link Here
472
    return $self->{_plugin_mapping};
472
    return $self->{_plugin_mapping};
473
}
473
}
474
474
475
=head3 to_api_mapping
476
477
This method returns the mapping for representing a Koha::BackgroundJob object
478
on the API.
479
480
=cut
481
482
sub to_api_mapping {
483
    return {
484
        id             => 'background_job_id',
485
        borrowernumber => 'patron_id',
486
    };
487
}
488
475
=head3 _type
489
=head3 _type
476
490
477
=cut
491
=cut
(-)a/Koha/REST/V1/BackgroundJobs.pm (+58 lines)
Line 0 Link Here
1
package Koha::REST::V1::BackgroundJobs;
2
3
# This file is part of Koha.
4
#
5
# Koha is free software; you can redistribute it and/or modify it
6
# under the terms of the GNU General Public License as published by
7
# the Free Software Foundation; either version 3 of the License, or
8
# (at your option) any later version.
9
#
10
# Koha is distributed in the hope that it will be useful, but
11
# WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
# GNU General Public License for more details.
14
#
15
# You should have received a copy of the GNU General Public License
16
# along with Koha; if not, see <http://www.gnu.org/licenses>.
17
18
use Modern::Perl;
19
20
use Mojo::Base 'Mojolicious::Controller';
21
22
use Koha::BackgroundJobs;
23
24
use Try::Tiny;
25
26
=head1 API
27
28
=head2 Methods
29
30
=head3 list
31
32
=cut
33
34
sub list {
35
    my $c = shift->openapi->valid_input or return;
36
37
    return try {
38
        my $patron = $c->stash('koha.user');
39
40
        my $can_manage_background_jobs =
41
          $patron->has_permission( { parameters => 'manage_background_jobs' } );
42
43
        my $background_jobs_set =
44
          $can_manage_background_jobs
45
          ? Koha::BackgroundJobs->new
46
          : Koha::BackgroundJobs->search(
47
            { borrowernumber => $patron->borrowernumber } );
48
49
        my $background_jobs = $c->objects->search( $background_jobs_set );
50
        return $c->render( status => 200, openapi => $background_jobs );
51
    }
52
    catch {
53
        $c->unhandled_exception($_);
54
    };
55
56
}
57
58
1;
(-)a/admin/background_jobs.pl (-33 lines)
Lines 77-115 if ( $op eq 'cancel' ) { Link Here
77
    $op = 'list';
77
    $op = 'list';
78
}
78
}
79
79
80
81
if ( $op eq 'list' ) {
82
    my $queued_jobs =
83
      $can_manage_background_jobs
84
      ? Koha::BackgroundJobs->search( { ended_on => undef },
85
        { order_by => { -desc => 'enqueued_on' } } )
86
      : Koha::BackgroundJobs->search(
87
        { borrowernumber => $logged_in_user->borrowernumber, ended_on => undef },
88
        { order_by       => { -desc => 'enqueued_on' } }
89
      );
90
    $template->param( queued => $queued_jobs );
91
92
    my $ended_since = dt_from_string->subtract( minutes => '60' );
93
    my $dtf = Koha::Database->new->schema->storage->datetime_parser;
94
95
    my $complete_jobs =
96
      $can_manage_background_jobs
97
      ? Koha::BackgroundJobs->search(
98
        {
99
            ended_on => { '>=' => $dtf->format_datetime($ended_since) }
100
        },
101
        { order_by => { -desc => 'enqueued_on' } }
102
      )
103
      : Koha::BackgroundJobs->search(
104
        {
105
            borrowernumber => $logged_in_user->borrowernumber,
106
            ended_on       => { '>=' => $dtf->format_datetime($ended_since) }
107
        },
108
        { order_by => { -desc => 'enqueued_on' } }
109
      );
110
    $template->param( complete => $complete_jobs );
111
}
112
113
$template->param(
80
$template->param(
114
    messages => \@messages,
81
    messages => \@messages,
115
    op       => $op,
82
    op       => $op,
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/background_jobs.tt (-1 / +174 lines)
Lines 262-267 Link Here
262
        </div>
262
        </div>
263
    </div>
263
    </div>
264
264
265
    <label for="include_last_hour">Only include jobs started in the last hour</label>
266
    <input type="checkbox" id="include_last_hour" checked />
267
268
    <table id="table_jobs">
269
        <thead>
270
            <tr>
271
                <th>Job ID</th>
272
                <th data-filter="job_statuses">Status</th>
273
                <th>Progress</th>
274
                <th data-filter="job_types">Type</th>
275
                <th>Queued</th>
276
                <th>Started</th>
277
                <th>Ended</th>
278
                <th class="noExport">Actions</th>
279
            </tr>
280
        </thead>
281
    </table>
265
[% END %]
282
[% END %]
266
283
267
            </main>
284
            </main>
Lines 276-281 Link Here
276
293
277
[% MACRO jsinclude BLOCK %]
294
[% MACRO jsinclude BLOCK %]
278
    [% Asset.js("js/admin-menu.js") | $raw %]
295
    [% Asset.js("js/admin-menu.js") | $raw %]
296
    [% INCLUDE 'js-date-format.inc' %]
279
    [% INCLUDE 'datatables.inc' %]
297
    [% INCLUDE 'datatables.inc' %]
280
    <script>
298
    <script>
281
        $(document).ready(function() {
299
        $(document).ready(function() {
Lines 297-302 Link Here
297
                "sPaginationType": "full_numbers"
315
                "sPaginationType": "full_numbers"
298
            }));
316
            }));
299
        });
317
        });
318
319
        const job_statuses = [
320
            {'_id': 'new',       '_str': _('New')},
321
            {'_id': 'cancelled', '_str': _('Cancelled')},
322
            {'_id': 'finished',  '_str': _('Finished')},
323
            {'_id': 'started',   '_str': _('Started')},
324
            {'_id': 'running',   '_str': _('Running')},
325
            {'_id': 'failed',    '_str': _('Failed')},
326
        ];
327
        function get_job_status (status) {
328
            let status_lib = job_statuses.find( s => s._id == status );
329
            if (status_lib) {
330
                return status_lib._str;
331
            }
332
            return status;
333
        }
334
335
        const job_types = [
336
            {
337
                '_id': 'batch_biblio_record_modification',
338
                '_str': _('Batch bibliographic record modification')
339
            },
340
            {
341
                '_id': 'batch_biblio_record_deletion',
342
                '_str': _('Batch bibliographic record record deletion')
343
            },
344
            {
345
                '_id': 'batch_authority_record_modification',
346
                '_str': _('Batch authority record modification')
347
            },
348
            {
349
                '_id': 'batch_authority_record_deletion',
350
                '_str': _('Batch authority record deletion')
351
            },
352
            {
353
                '_id': 'batch_item_record_modification',
354
                '_str': _('Batch item record modification')
355
            },
356
            {
357
                '_id': 'batch_item_record_deletion',
358
                '_str': _('Batch item record deletion')
359
            },
360
            {
361
                '_id': 'batch_hold_cancel',
362
                '_str': _('Batch hold cancellation')
363
            },
364
            {
365
                '_id': 'update_elastic_index'
366
                , '_str': _('Update Elasticsearch index')
367
            },
368
            {
369
                '_id': 'update_holds_queue_for_biblios',
370
                '_str': _('Holds queue update')
371
            }
372
        ];
373
374
        function get_job_type (job_type) {
375
            let job_type_lib = job_types.find( t => t._id == job_type );
376
            if ( job_type_lib ) {
377
                return job_type_lib._str;
378
            }
379
            return _("Unknown job type '%s'").format(job_type);
380
        }
381
382
        $(document).ready(function() {
383
            let additional_filters = {
384
                started_on: function(){
385
                    let now = new Date();
386
                    if ( $("#include_last_hour").is(":checked") ) {
387
                        now.setHours(now.getHours() - 1);
388
                        return { ">": now.toISOString() };
389
                    } else {
390
                    console.log("not checked");
391
                        return { "<": now.toISOString() };
392
                    }
393
                },
394
            };
395
            let jobs_table = $("#table_jobs").kohaTable({
396
                "ajax": {
397
                    "url": "/api/v1/background_jobs"
398
                },
399
                "order": [[ 1, "desc" ]],
400
                "columns": [
401
                    {
402
                        "data": "background_job_id",
403
                        "searchable": true,
404
                        "orderable": true
405
                    },
406
                    {
407
                        "data": "status",
408
                        "searchable": true,
409
                        "orderable": true,
410
                        "render": function(data, type, row, meta) {
411
                            return get_job_status(row.status).escapeHtml();
412
                        },
413
                    },
414
                    {
415
                        "data": "progress,size",
416
                        "searchable": false,
417
                        "orderable": true,
418
                        "render": function(data, type, row, meta) {
419
                            return "%s/%s".format(row.progress, row.size).escapeHtml();
420
                        },
421
                    },
422
                    {
423
                        "data": "type",
424
                        "searchable": true,
425
                        "orderable": true,
426
                        "render": function(data, type, row, meta) {
427
                            return get_job_type(row.type).escapeHtml();
428
                        },
429
                    },
430
                    {
431
                        "data": "enqueued_on",
432
                        "searchable": true,
433
                        "orderable": true,
434
                        "render": function(data, type, row, meta) {
435
                            return $datetime(row.enqueued_on);
436
                        },
437
                    },
438
                    {
439
                        "data": "started_on",
440
                        "searchable": true,
441
                        "orderable": true,
442
                        "render": function(data, type, row, meta) {
443
                            return $datetime(row.started_on);
444
                        },
445
                    },
446
447
                    {
448
                        "data": "ended_on",
449
                        "searchable": true,
450
                        "orderable": true,
451
                        "render": function(data, type, row, meta) {
452
                            return $datetime(row.ended_on);
453
                        },
454
                    },
455
                    {
456
                        "data": function( row, type, val, meta ) {
457
                            var result = '<a class="btn btn-default btn-xs" role="button" href="/cgi-bin/koha/admin/background_jobs.pl?op=view&amp;id='+ encodeURIComponent(row.background_job_id) +'"><i class="fa fa-eye" aria-hidden="true"></i> '+_("View")+'</a>'+"\n";
458
                            if ( row.status == 'new' || row.status == 'started' ) {
459
                                result += '<a class="btn btn-default btn-xs" role="button" href="/cgi-bin/koha/admin/bakcground_jobs.pl?op=cancel&amp;id='+ encodeURIComponent(row.background_job_id) +'"><i class="fa fa-trash" aria-hidden="true"></i> '+_("Cancel")+'</a>';
460
                            }
461
                            return result;
462
463
                        },
464
                        "searchable": false,
465
                        "orderable": false
466
                    }
467
                ]
468
            }, null, 1, additional_filters);
469
470
            $("#include_last_hour").on("change", function(){
471
                jobs_table.DataTable().draw();
472
                return false;
473
            });
300
    </script>
474
    </script>
301
    [% IF op == 'view' %]
475
    [% IF op == 'view' %]
302
        [% PROCESS 'js' %]
476
        [% PROCESS 'js' %]
303
- 

Return to bug 30982