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

(-)a/Koha/BackgroundJob.pm (+14 lines)
Lines 469-474 sub plugin_types_to_classes { Link Here
469
    return $self->{_plugin_mapping};
469
    return $self->{_plugin_mapping};
470
}
470
}
471
471
472
=head3 to_api_mapping
473
474
This method returns the mapping for representing a Koha::BackgroundJob object
475
on the API.
476
477
=cut
478
479
sub to_api_mapping {
480
    return {
481
        id             => 'background_job_id',
482
        borrowernumber => 'patron_id',
483
    };
484
}
485
472
=head3 _type
486
=head3 _type
473
487
474
=cut
488
=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 256-261 Link Here
256
        </div>
256
        </div>
257
    </div>
257
    </div>
258
258
259
    <label for="include_last_hour">Only include jobs started in the last hour</label>
260
    <input type="checkbox" id="include_last_hour" checked />
261
262
    <table id="table_jobs">
263
        <thead>
264
            <tr>
265
                <th>Job ID</th>
266
                <th data-filter="job_statuses">Status</th>
267
                <th>Progress</th>
268
                <th data-filter="job_types">Type</th>
269
                <th>Queued</th>
270
                <th>Started</th>
271
                <th>Ended</th>
272
                <th class="noExport">Actions</th>
273
            </tr>
274
        </thead>
275
    </table>
259
[% END %]
276
[% END %]
260
277
261
            </main>
278
            </main>
Lines 270-275 Link Here
270
287
271
[% MACRO jsinclude BLOCK %]
288
[% MACRO jsinclude BLOCK %]
272
    [% Asset.js("js/admin-menu.js") | $raw %]
289
    [% Asset.js("js/admin-menu.js") | $raw %]
290
    [% INCLUDE 'js-date-format.inc' %]
273
    [% INCLUDE 'datatables.inc' %]
291
    [% INCLUDE 'datatables.inc' %]
274
    <script>
292
    <script>
275
        $(document).ready(function() {
293
        $(document).ready(function() {
Lines 291-296 Link Here
291
                "sPaginationType": "full_numbers"
309
                "sPaginationType": "full_numbers"
292
            }));
310
            }));
293
        });
311
        });
312
313
        const job_statuses = [
314
            {'_id': 'new',       '_str': _('New')},
315
            {'_id': 'cancelled', '_str': _('Cancelled')},
316
            {'_id': 'finished',  '_str': _('Finished')},
317
            {'_id': 'started',   '_str': _('Started')},
318
            {'_id': 'running',   '_str': _('Running')},
319
            {'_id': 'failed',    '_str': _('Failed')},
320
        ];
321
        function get_job_status (status) {
322
            let status_lib = job_statuses.find( s => s._id == status );
323
            if (status_lib) {
324
                return status_lib._str;
325
            }
326
            return status;
327
        }
328
329
        const job_types = [
330
            {
331
                '_id': 'batch_biblio_record_modification',
332
                '_str': _('Batch bibliographic record modification')
333
            },
334
            {
335
                '_id': 'batch_biblio_record_deletion',
336
                '_str': _('Batch bibliographic record record deletion')
337
            },
338
            {
339
                '_id': 'batch_authority_record_modification',
340
                '_str': _('Batch authority record modification')
341
            },
342
            {
343
                '_id': 'batch_authority_record_deletion',
344
                '_str': _('Batch authority record deletion')
345
            },
346
            {
347
                '_id': 'batch_item_record_modification',
348
                '_str': _('Batch item record modification')
349
            },
350
            {
351
                '_id': 'batch_item_record_deletion',
352
                '_str': _('Batch item record deletion')
353
            },
354
            {
355
                '_id': 'batch_hold_cancel',
356
                '_str': _('Batch hold cancellation')
357
            },
358
            {
359
                '_id': 'update_elastic_index'
360
                , '_str': _('Update Elasticsearch index')
361
            },
362
            {
363
                '_id': 'update_holds_queue_for_biblios',
364
                '_str': _('Holds queue update')
365
            }
366
        ];
367
368
        function get_job_type (job_type) {
369
            let job_type_lib = job_types.find( t => t._id == job_type );
370
            if ( job_type_lib ) {
371
                return job_type_lib._str;
372
            }
373
            return _("Unknown job type '%s'").format(job_type);
374
        }
375
376
        $(document).ready(function() {
377
            let additional_filters = {
378
                started_on: function(){
379
                    let now = new Date();
380
                    if ( $("#include_last_hour").is(":checked") ) {
381
                        now.setHours(now.getHours() - 1);
382
                        return { ">": now.toISOString() };
383
                    } else {
384
                    console.log("not checked");
385
                        return { "<": now.toISOString() };
386
                    }
387
                },
388
            };
389
            let jobs_table = $("#table_jobs").kohaTable({
390
                "ajax": {
391
                    "url": "/api/v1/background_jobs"
392
                },
393
                "order": [[ 1, "desc" ]],
394
                "columns": [
395
                    {
396
                        "data": "background_job_id",
397
                        "searchable": true,
398
                        "orderable": true
399
                    },
400
                    {
401
                        "data": "status",
402
                        "searchable": true,
403
                        "orderable": true,
404
                        "render": function(data, type, row, meta) {
405
                            return get_job_status(row.status).escapeHtml();
406
                        },
407
                    },
408
                    {
409
                        "data": "progress,size",
410
                        "searchable": false,
411
                        "orderable": true,
412
                        "render": function(data, type, row, meta) {
413
                            return "%s/%s".format(row.progress, row.size).escapeHtml();
414
                        },
415
                    },
416
                    {
417
                        "data": "type",
418
                        "searchable": true,
419
                        "orderable": true,
420
                        "render": function(data, type, row, meta) {
421
                            return get_job_type(row.type).escapeHtml();
422
                        },
423
                    },
424
                    {
425
                        "data": "enqueued_on",
426
                        "searchable": true,
427
                        "orderable": true,
428
                        "render": function(data, type, row, meta) {
429
                            return $datetime(row.enqueued_on);
430
                        },
431
                    },
432
                    {
433
                        "data": "started_on",
434
                        "searchable": true,
435
                        "orderable": true,
436
                        "render": function(data, type, row, meta) {
437
                            return $datetime(row.started_on);
438
                        },
439
                    },
440
441
                    {
442
                        "data": "ended_on",
443
                        "searchable": true,
444
                        "orderable": true,
445
                        "render": function(data, type, row, meta) {
446
                            return $datetime(row.ended_on);
447
                        },
448
                    },
449
                    {
450
                        "data": function( row, type, val, meta ) {
451
                            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";
452
                            if ( row.status == 'new' || row.status == 'started' ) {
453
                                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>';
454
                            }
455
                            return result;
456
457
                        },
458
                        "searchable": false,
459
                        "orderable": false
460
                    }
461
                ]
462
            }, null, 1, additional_filters);
463
464
            $("#include_last_hour").on("change", function(){
465
                jobs_table.DataTable().draw();
466
                return false;
467
            });
294
    </script>
468
    </script>
295
    [% IF op == 'view' %]
469
    [% IF op == 'view' %]
296
        [% PROCESS 'js' %]
470
        [% PROCESS 'js' %]
297
- 

Return to bug 30982