improving job settings ui
This commit is contained in:
parent
c2d7931d8d
commit
3e060e2b8d
@ -5,7 +5,14 @@ import {Config} from '../../../common/config/private/Config';
|
|||||||
import {JobProgressDTO, JobProgressStates} from '../../../common/entities/job/JobProgressDTO';
|
import {JobProgressDTO, JobProgressStates} from '../../../common/entities/job/JobProgressDTO';
|
||||||
|
|
||||||
export class JobProgressManager {
|
export class JobProgressManager {
|
||||||
db: { [key: string]: { progress: JobProgressDTO, timestamp: number } } = {};
|
private static readonly VERSION = 1;
|
||||||
|
db: {
|
||||||
|
version: number,
|
||||||
|
db: { [key: string]: { progress: JobProgressDTO, timestamp: number } }
|
||||||
|
} = {
|
||||||
|
version: JobProgressManager.VERSION,
|
||||||
|
db: {}
|
||||||
|
};
|
||||||
private readonly dbPath: string;
|
private readonly dbPath: string;
|
||||||
private timer: NodeJS.Timeout = null;
|
private timer: NodeJS.Timeout = null;
|
||||||
|
|
||||||
@ -16,9 +23,9 @@ export class JobProgressManager {
|
|||||||
|
|
||||||
get Running(): { [key: string]: JobProgressDTO } {
|
get Running(): { [key: string]: JobProgressDTO } {
|
||||||
const m: { [key: string]: JobProgressDTO } = {};
|
const m: { [key: string]: JobProgressDTO } = {};
|
||||||
for (const key of Object.keys(this.db)) {
|
for (const key of Object.keys(this.db.db)) {
|
||||||
if (this.db[key].progress.state === JobProgressStates.running) {
|
if (this.db.db[key].progress.state === JobProgressStates.running) {
|
||||||
m[key] = this.db[key].progress;
|
m[key] = this.db.db[key].progress;
|
||||||
m[key].time.end = Date.now();
|
m[key].time.end = Date.now();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -27,16 +34,16 @@ export class JobProgressManager {
|
|||||||
|
|
||||||
get Finished(): { [key: string]: JobProgressDTO } {
|
get Finished(): { [key: string]: JobProgressDTO } {
|
||||||
const m: { [key: string]: JobProgressDTO } = {};
|
const m: { [key: string]: JobProgressDTO } = {};
|
||||||
for (const key of Object.keys(this.db)) {
|
for (const key of Object.keys(this.db.db)) {
|
||||||
if (this.db[key].progress.state !== JobProgressStates.running) {
|
if (this.db.db[key].progress.state !== JobProgressStates.running) {
|
||||||
m[key] = this.db[key].progress;
|
m[key] = this.db.db[key].progress;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
onJobProgressUpdate(progress: JobProgressDTO) {
|
onJobProgressUpdate(progress: JobProgressDTO) {
|
||||||
this.db[progress.HashName] = {progress: progress, timestamp: Date.now()};
|
this.db.db[progress.HashName] = {progress: progress, timestamp: Date.now()};
|
||||||
this.delayedSave();
|
this.delayedSave();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,21 +54,25 @@ export class JobProgressManager {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const data = await fsp.readFile(this.dbPath, 'utf8');
|
const data = await fsp.readFile(this.dbPath, 'utf8');
|
||||||
this.db = JSON.parse(data);
|
const db = JSON.parse(data);
|
||||||
|
if (db.version !== JobProgressManager.VERSION) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.db = db;
|
||||||
|
|
||||||
while (Object.keys(this.db).length > Config.Server.Jobs.maxSavedProgress) {
|
while (Object.keys(this.db.db).length > Config.Server.Jobs.maxSavedProgress) {
|
||||||
let min: string = null;
|
let min: string = null;
|
||||||
for (const key of Object.keys(this.db)) {
|
for (const key of Object.keys(this.db.db)) {
|
||||||
if (min === null || this.db[min].timestamp > this.db[key].timestamp) {
|
if (min === null || this.db.db[min].timestamp > this.db.db[key].timestamp) {
|
||||||
min = key;
|
min = key;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delete this.db[min];
|
delete this.db.db[min];
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const key of Object.keys(this.db)) {
|
for (const key of Object.keys(this.db.db)) {
|
||||||
if (this.db[key].progress.state === JobProgressStates.running) {
|
if (this.db.db[key].progress.state === JobProgressStates.running) {
|
||||||
this.db[key].progress.state = JobProgressStates.interrupted;
|
this.db.db[key].progress.state = JobProgressStates.interrupted;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import {JobProgressDTO, JobProgressStates} from '../../../../common/entities/job/JobProgressDTO';
|
import {JobProgressDTO, JobProgressLogDTO, JobProgressStates} from '../../../../common/entities/job/JobProgressDTO';
|
||||||
|
|
||||||
|
|
||||||
export class JobProgress {
|
export class JobProgress {
|
||||||
@ -12,7 +12,8 @@ export class JobProgress {
|
|||||||
start: <number>Date.now(),
|
start: <number>Date.now(),
|
||||||
end: <number>null,
|
end: <number>null,
|
||||||
};
|
};
|
||||||
private logs: string[] = [];
|
private logCounter = 0;
|
||||||
|
private logs: { id: number, timestamp: string, comment: string }[] = [];
|
||||||
|
|
||||||
|
|
||||||
constructor(public readonly HashName: string) {
|
constructor(public readonly HashName: string) {
|
||||||
@ -72,7 +73,7 @@ export class JobProgress {
|
|||||||
this.onChange(this);
|
this.onChange(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
get Logs(): string[] {
|
get Logs(): JobProgressLogDTO[] {
|
||||||
return this.logs;
|
return this.logs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,7 +84,7 @@ export class JobProgress {
|
|||||||
while (this.logs.length > 10) {
|
while (this.logs.length > 10) {
|
||||||
this.logs.shift();
|
this.logs.shift();
|
||||||
}
|
}
|
||||||
this.logs.push(log);
|
this.logs.push({id: this.logCounter++, timestamp: (new Date()).toISOString(), comment: log});
|
||||||
this.onChange(this);
|
this.onChange(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3,6 +3,12 @@ export enum JobProgressStates {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export interface JobProgressLogDTO {
|
||||||
|
id: number;
|
||||||
|
timestamp: string;
|
||||||
|
comment: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface JobProgressDTO {
|
export interface JobProgressDTO {
|
||||||
HashName: string;
|
HashName: string;
|
||||||
steps: {
|
steps: {
|
||||||
@ -11,7 +17,7 @@ export interface JobProgressDTO {
|
|||||||
skipped: number,
|
skipped: number,
|
||||||
};
|
};
|
||||||
state: JobProgressStates;
|
state: JobProgressStates;
|
||||||
logs: string[];
|
logs: JobProgressLogDTO[];
|
||||||
time: {
|
time: {
|
||||||
start: number,
|
start: number,
|
||||||
end: number
|
end: number
|
||||||
|
|||||||
@ -36,7 +36,7 @@
|
|||||||
</button>
|
</button>
|
||||||
<button class="btn btn-secondary job-control-button"
|
<button class="btn btn-secondary job-control-button"
|
||||||
*ngIf="getProgress(schedule)"
|
*ngIf="getProgress(schedule)"
|
||||||
[disabled]="disableButtons || jobsService.progress.value[schedule.jobName].state !== JobProgressStates.running"
|
[disabled]="disableButtons || getProgress(schedule).state !== JobProgressStates.running"
|
||||||
(click)="stop(schedule); $event.stopPropagation();"><span class="oi oi-media-stop"></span>
|
(click)="stop(schedule); $event.stopPropagation();"><span class="oi oi-media-stop"></span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@ -129,7 +129,7 @@
|
|||||||
</button>
|
</button>
|
||||||
<button class="btn btn-secondary float-right"
|
<button class="btn btn-secondary float-right"
|
||||||
*ngIf="getProgress(schedule)"
|
*ngIf="getProgress(schedule)"
|
||||||
[disabled]="disableButtons || jobsService.progress.value[schedule.jobName].state !== JobProgressStates.running"
|
[disabled]="disableButtons || getProgress(schedule).state !== JobProgressStates.running"
|
||||||
(click)="stop(schedule)" i18n>Stop
|
(click)="stop(schedule)" i18n>Stop
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@ -181,7 +181,8 @@
|
|||||||
</ng-container>
|
</ng-container>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<small class="form-text text-muted">
|
<small class="form-text text-muted">
|
||||||
<ng-container *ngIf="configEntry.type == 'number-array'" i18n>';' separated integers.</ng-container>
|
<ng-container *ngIf="configEntry.type == 'number-array'" i18n>';' separated integers.
|
||||||
|
</ng-container>
|
||||||
{{backendtextService.get(configEntry.description)}}
|
{{backendtextService.get(configEntry.description)}}
|
||||||
</small>
|
</small>
|
||||||
</div>
|
</div>
|
||||||
@ -194,8 +195,7 @@
|
|||||||
<app-settings-job-progress
|
<app-settings-job-progress
|
||||||
class="card-footer bg-transparent"
|
class="card-footer bg-transparent"
|
||||||
*ngIf="getProgress(schedule) || getLastRun(schedule)"
|
*ngIf="getProgress(schedule) || getLastRun(schedule)"
|
||||||
[progress]="getProgress(schedule)"
|
[progress]="getProgress(schedule) || getLastRun(schedule)">
|
||||||
[lastRun]="getLastRun(schedule)">
|
|
||||||
</app-settings-job-progress>
|
</app-settings-job-progress>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -17,10 +17,10 @@ import {
|
|||||||
} from '../../../../../common/entities/job/JobScheduleDTO';
|
} from '../../../../../common/entities/job/JobScheduleDTO';
|
||||||
import {Utils} from '../../../../../common/Utils';
|
import {Utils} from '../../../../../common/Utils';
|
||||||
import {ServerConfig} from '../../../../../common/config/private/IPrivateConfig';
|
import {ServerConfig} from '../../../../../common/config/private/IPrivateConfig';
|
||||||
import {ConfigTemplateEntry, JobDTO} from '../../../../../common/entities/job/JobDTO';
|
import {ConfigTemplateEntry} from '../../../../../common/entities/job/JobDTO';
|
||||||
import {Job} from '../../../../../backend/model/jobs/jobs/Job';
|
import {Job} from '../../../../../backend/model/jobs/jobs/Job';
|
||||||
import {ModalDirective} from 'ngx-bootstrap/modal';
|
import {ModalDirective} from 'ngx-bootstrap/modal';
|
||||||
import {JobProgressStates} from '../../../../../common/entities/job/JobProgressDTO';
|
import {JobProgressDTO, JobProgressStates} from '../../../../../common/entities/job/JobProgressDTO';
|
||||||
import {BackendtextService} from '../../../model/backendtext.service';
|
import {BackendtextService} from '../../../model/backendtext.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -181,8 +181,6 @@ export class JobsSettingsComponent extends SettingsComponent<ServerConfig.JobCon
|
|||||||
}
|
}
|
||||||
|
|
||||||
setNumberArray(configElement: any, id: string, value: string) {
|
setNumberArray(configElement: any, id: string, value: string) {
|
||||||
console.log(value);
|
|
||||||
console.log(configElement[id]);
|
|
||||||
value = value.replace(new RegExp(',', 'g'), ';');
|
value = value.replace(new RegExp(',', 'g'), ';');
|
||||||
value = value.replace(new RegExp(' ', 'g'), ';');
|
value = value.replace(new RegExp(' ', 'g'), ';');
|
||||||
configElement[id] = value.split(';')
|
configElement[id] = value.split(';')
|
||||||
@ -217,12 +215,12 @@ export class JobsSettingsComponent extends SettingsComponent<ServerConfig.JobCon
|
|||||||
return JSON.stringify(schedule.config);
|
return JSON.stringify(schedule.config);
|
||||||
}
|
}
|
||||||
|
|
||||||
getProgress(schedule: JobScheduleDTO) {
|
getProgress(schedule: JobScheduleDTO): JobProgressDTO {
|
||||||
return this.jobsService.progress.value[JobDTO.getHashName(schedule.jobName, schedule.config)];
|
return this.jobsService.getProgress(schedule);
|
||||||
}
|
}
|
||||||
|
|
||||||
getLastRun(schedule: JobScheduleDTO) {
|
getLastRun(schedule: JobScheduleDTO): JobProgressDTO {
|
||||||
return this.jobsService.lastRuns.value[JobDTO.getHashName(schedule.jobName, schedule.config)];
|
return this.jobsService.getLastRun(schedule);
|
||||||
}
|
}
|
||||||
|
|
||||||
private getNextRunningDate(sch: JobScheduleDTO, list: JobScheduleDTO[], depth: number = 0): number {
|
private getNextRunningDate(sch: JobScheduleDTO, list: JobScheduleDTO[], depth: number = 0): number {
|
||||||
|
|||||||
@ -6,3 +6,8 @@
|
|||||||
.progress-row {
|
.progress-row {
|
||||||
font-size: .75rem;
|
font-size: .75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.clickable {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|||||||
@ -1,40 +1,46 @@
|
|||||||
<div class="row" *ngIf="!progress && lastRun">
|
<div class="row clickable" *ngIf="!IsRunning"
|
||||||
|
(click)="openModal(template)">
|
||||||
<div class="col-md-2 col-12" i18n>
|
<div class="col-md-2 col-12" i18n>
|
||||||
Last run:
|
Last run:
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4 col-12" title="Run between" i18n-title >
|
<div class="col-md-4 col-12" title="Run between" i18n-title>
|
||||||
<span class="oi oi-clock" aria-hidden="true"></span>
|
<span class="oi oi-clock" aria-hidden="true"></span>
|
||||||
{{lastRun.time.start | date:'medium'}} - {{lastRun.time.end | date:'mediumTime'}}
|
{{progress.time.start | date:'medium'}} - {{progress.time.end | date:'mediumTime'}}
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-3 col-6" title="processed+skipped/all" i18n-title>
|
<div class="col-md-3 col-6" title="processed+skipped/all" i18n-title>
|
||||||
<span class="oi oi-check" aria-hidden="true"></span>
|
<span class="oi oi-check" aria-hidden="true"></span>
|
||||||
{{lastRun.steps.processed}}+{{lastRun.steps.skipped}}/{{lastRun.steps.all}}
|
{{progress.steps.processed}}+{{progress.steps.skipped}}/{{progress.steps.all}}
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-3 col-6" title="Status" i18n-title >
|
<div class="col-md-3 col-6" title="Status" i18n-title>
|
||||||
<span class="oi oi-pulse" aria-hidden="true"></span>
|
<span class="oi oi-pulse" aria-hidden="true"></span>
|
||||||
{{JobProgressStates[lastRun.state]}}
|
{{JobProgressStates[progress.state]}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="progress">
|
<div *ngIf="IsRunning" class="clickable" (click)="openModal(template)">
|
||||||
|
|
||||||
<div class="form-group row">
|
<div class="form-group row">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<input *ngIf="progress.state === JobProgressStates.running" type="text" class="form-control" disabled
|
<input
|
||||||
[ngModel]="progress.logs[progress.logs.length-1]" name="details">
|
*ngIf="progress.state === JobProgressStates.running" type="text" class="form-control" disabled
|
||||||
<input *ngIf="progress.state === JobProgressStates.cancelling" type="text" class="form-control" disabled value="Cancelling: {{progress.logs[progress.logs.length-1]}}"
|
[ngModel]="progress.logs[progress.logs.length-1].comment" name="details">
|
||||||
|
<input
|
||||||
|
*ngIf="progress.state === JobProgressStates.cancelling" type="text" class="form-control" disabled
|
||||||
|
value="Cancelling: {{progress.logs[progress.logs.length-1].comment}}"
|
||||||
i18n-value name="details">
|
i18n-value name="details">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="form-group row progress-row ">
|
<div class="form-group row progress-row ">
|
||||||
<div class="col-6 col-md-2 col-lg-1 text-md-right order-md-0" title="time elapsed" i18n-title>{{TimeElapsed| duration:':'}}</div>
|
<div class="col-6 col-md-2 col-lg-1 text-md-right order-md-0" title="time elapsed"
|
||||||
<div class="col-6 col-md-2 col-lg-1 order-md-2 text-right text-md-left" title="time left" i18n-title>{{TimeAll| duration:':'}}</div>
|
i18n-title>{{TimeElapsed| duration:':'}}</div>
|
||||||
|
<div class="col-6 col-md-2 col-lg-1 order-md-2 text-right text-md-left" title="time left"
|
||||||
|
i18n-title>{{TimeAll| duration:':'}}</div>
|
||||||
<div class="progress col-md-8 col-lg-10 order-md-1"
|
<div class="progress col-md-8 col-lg-10 order-md-1"
|
||||||
title="processed:{{progress.steps.processed}}+ skipped:{{progress.steps.skipped}} / all:{{progress.steps.all}}">
|
title="processed:{{progress.steps.processed}}+ skipped:{{progress.steps.skipped}} / all:{{progress.steps.all}}">
|
||||||
<div
|
<div
|
||||||
*ngIf="progress.steps.all >0"
|
*ngIf="progress.steps.all >0"
|
||||||
class="progress-bar d-inline-block progress-bar-success {{progress.state === JobProgressStates.cancelling ? 'bg-secondary' : ''}}"
|
class="progress-bar clickable d-inline-block progress-bar-success {{progress.state === JobProgressStates.cancelling ? 'bg-secondary' : ''}}"
|
||||||
role="progressbar"
|
role="progressbar"
|
||||||
aria-valuenow="2"
|
aria-valuenow="2"
|
||||||
aria-valuemin="0"
|
aria-valuemin="0"
|
||||||
@ -52,3 +58,57 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Modal -->
|
||||||
|
<ng-template #template>
|
||||||
|
<div class="modal-header">
|
||||||
|
<h4 class="modal-title pull-left">{{Name}}</h4>
|
||||||
|
<button type="button" class="close pull-right" aria-label="Close" (click)="modalRef.hide()">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-4">Processed: {{progress.steps.processed}}</div>
|
||||||
|
<div class="col-sm-4">Skipped: {{progress.steps.skipped}}</div>
|
||||||
|
<div class="col-sm-4">All: {{progress.steps.all}}</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mt-3 mb-3">
|
||||||
|
<div class="progress col-12">
|
||||||
|
<div
|
||||||
|
*ngIf="progress.steps.all >0"
|
||||||
|
class="progress-bar clickable d-inline-block progress-bar-success {{progress.state !== JobProgressStates.running ? 'bg-secondary' : ''}}"
|
||||||
|
role="progressbar"
|
||||||
|
aria-valuenow="2"
|
||||||
|
aria-valuemin="0"
|
||||||
|
aria-valuemax="100"
|
||||||
|
style="min-width: 2em;"
|
||||||
|
[style.width.%]="((progress.steps.processed+progress.steps.skipped)/progress.steps.all)*100">
|
||||||
|
{{((progress.steps.processed + progress.steps.skipped) / progress.steps.all) * 100 | number:'1.1-2'}}%
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
*ngIf="progress.steps.all === 0"
|
||||||
|
class="progress-bar d-inline-block progress-bar-success progress-bar-striped progress-bar-animated {{progress.state !== JobProgressStates.running ? 'bg-secondary' : ''}}"
|
||||||
|
role="progressbar" aria-valuenow="100"
|
||||||
|
aria-valuemin="0" aria-valuemax="100" style="width: 100%">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card bg-light">
|
||||||
|
<div class="card-header" i18n>
|
||||||
|
Logs
|
||||||
|
</div>
|
||||||
|
<div class="card-body text-secondary">
|
||||||
|
<ng-container *ngFor="let log of progress.logs; let i = index;">
|
||||||
|
<p class="card-text" *ngIf="(i==0 && log.id > 0) || ( i> 0 && progress.logs[i-1].id+1!=log.id)">
|
||||||
|
...
|
||||||
|
</p>
|
||||||
|
<p class="card-text">
|
||||||
|
#{{log.id}} [{{log.timestamp | date:'medium'}}] {{log.comment}}
|
||||||
|
</p>
|
||||||
|
</ng-container>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ng-template>
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import {Component, Input, OnChanges, OnDestroy} from '@angular/core';
|
import {Component, Input, OnChanges, OnDestroy, TemplateRef} from '@angular/core';
|
||||||
import {JobProgressDTO, JobProgressStates} from '../../../../../../common/entities/job/JobProgressDTO';
|
import {JobProgressDTO, JobProgressStates} from '../../../../../../common/entities/job/JobProgressDTO';
|
||||||
import {Subscription, timer} from 'rxjs';
|
import {Subscription, timer} from 'rxjs';
|
||||||
|
import {BsModalRef, BsModalService} from 'ngx-bootstrap';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-settings-job-progress',
|
selector: 'app-settings-job-progress',
|
||||||
@ -10,12 +11,16 @@ import {Subscription, timer} from 'rxjs';
|
|||||||
export class JobProgressComponent implements OnDestroy, OnChanges {
|
export class JobProgressComponent implements OnDestroy, OnChanges {
|
||||||
|
|
||||||
@Input() progress: JobProgressDTO;
|
@Input() progress: JobProgressDTO;
|
||||||
@Input() lastRun: JobProgressDTO;
|
|
||||||
JobProgressStates = JobProgressStates;
|
JobProgressStates = JobProgressStates;
|
||||||
timeCurrentCopy: number;
|
timeCurrentCopy: number;
|
||||||
|
modalRef: BsModalRef;
|
||||||
private timerSub: Subscription;
|
private timerSub: Subscription;
|
||||||
|
|
||||||
constructor() {
|
constructor(private modalService: BsModalService) {
|
||||||
|
}
|
||||||
|
|
||||||
|
get Name(): string {
|
||||||
|
return this.progress.HashName;
|
||||||
}
|
}
|
||||||
|
|
||||||
get TimeAll(): number {
|
get TimeAll(): number {
|
||||||
@ -26,6 +31,10 @@ export class JobProgressComponent implements OnDestroy, OnChanges {
|
|||||||
(this.progress.steps.processed + this.progress.steps.skipped) * this.progress.steps.all;
|
(this.progress.steps.processed + this.progress.steps.skipped) * this.progress.steps.all;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get IsRunning() {
|
||||||
|
return this.progress.state === JobProgressStates.running || this.progress.state === JobProgressStates.canceled;
|
||||||
|
}
|
||||||
|
|
||||||
get TimeLeft(): number {
|
get TimeLeft(): number {
|
||||||
if (!this.progress) {
|
if (!this.progress) {
|
||||||
return 0;
|
return 0;
|
||||||
@ -40,6 +49,11 @@ export class JobProgressComponent implements OnDestroy, OnChanges {
|
|||||||
return (this.timeCurrentCopy - this.progress.time.start);
|
return (this.timeCurrentCopy - this.progress.time.start);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
openModal(template: TemplateRef<any>) {
|
||||||
|
this.modalRef = this.modalService.show(template, {class: 'modal-lg'});
|
||||||
|
}
|
||||||
|
|
||||||
ngOnChanges(): void {
|
ngOnChanges(): void {
|
||||||
if (!this.progress) {
|
if (!this.progress) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -1,14 +1,16 @@
|
|||||||
import {EventEmitter, Injectable} from '@angular/core';
|
import {EventEmitter, Injectable} from '@angular/core';
|
||||||
import {BehaviorSubject} from 'rxjs';
|
import {BehaviorSubject} from 'rxjs';
|
||||||
import {JobProgressDTO, JobProgressStates} from '../../../../common/entities/job/JobProgressDTO';
|
import {JobProgressDTO} from '../../../../common/entities/job/JobProgressDTO';
|
||||||
import {NetworkService} from '../../model/network/network.service';
|
import {NetworkService} from '../../model/network/network.service';
|
||||||
|
import {JobScheduleDTO} from '../../../../common/entities/job/JobScheduleDTO';
|
||||||
|
import {JobDTO} from '../../../../common/entities/job/JobDTO';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ScheduledJobsService {
|
export class ScheduledJobsService {
|
||||||
|
|
||||||
|
|
||||||
public progress: BehaviorSubject<{ [key: string]: JobProgressDTO }>;
|
public progress: BehaviorSubject<{ [key: string]: JobProgressDTO }>;
|
||||||
public lastRuns: BehaviorSubject<{ [key: string]: { [key: string]: JobProgressStates } }>;
|
public lastRuns: BehaviorSubject<{ [key: string]: JobProgressDTO }>;
|
||||||
public onJobFinish: EventEmitter<string> = new EventEmitter<string>();
|
public onJobFinish: EventEmitter<string> = new EventEmitter<string>();
|
||||||
timer: number = null;
|
timer: number = null;
|
||||||
private subscribers = 0;
|
private subscribers = 0;
|
||||||
@ -18,6 +20,13 @@ export class ScheduledJobsService {
|
|||||||
this.lastRuns = new BehaviorSubject({});
|
this.lastRuns = new BehaviorSubject({});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getProgress(schedule: JobScheduleDTO): JobProgressDTO {
|
||||||
|
return this.progress.value[JobDTO.getHashName(schedule.jobName, schedule.config)];
|
||||||
|
}
|
||||||
|
|
||||||
|
getLastRun(schedule: JobScheduleDTO): JobProgressDTO {
|
||||||
|
return this.lastRuns.value[JobDTO.getHashName(schedule.jobName, schedule.config)];
|
||||||
|
}
|
||||||
|
|
||||||
subscribeToProgress(): void {
|
subscribeToProgress(): void {
|
||||||
this.incSubscribers();
|
this.incSubscribers();
|
||||||
@ -28,7 +37,7 @@ export class ScheduledJobsService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async forceUpdate(): Promise<void> {
|
public async forceUpdate(): Promise<void> {
|
||||||
return await this.getProgress();
|
return await this.loadProgress();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async start(id: string, config?: any): Promise<void> {
|
public async start(id: string, config?: any): Promise<void> {
|
||||||
@ -41,10 +50,10 @@ export class ScheduledJobsService {
|
|||||||
this.forceUpdate();
|
this.forceUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async getProgress(): Promise<void> {
|
protected async loadProgress(): Promise<void> {
|
||||||
const prevPrg = this.progress.value;
|
const prevPrg = this.progress.value;
|
||||||
this.progress.next(await this._networkService.getJson<{ [key: string]: JobProgressDTO }>('/admin/jobs/scheduled/progress'));
|
this.progress.next(await this._networkService.getJson<{ [key: string]: JobProgressDTO }>('/admin/jobs/scheduled/progress'));
|
||||||
this.lastRuns.next(await this._networkService.getJson<{ [key: string]: { [key: string]: JobProgressStates } }>('/admin/jobs/scheduled/lastRun'));
|
this.lastRuns.next(await this._networkService.getJson<{ [key: string]: JobProgressDTO }>('/admin/jobs/scheduled/lastRun'));
|
||||||
for (const prg in prevPrg) {
|
for (const prg in prevPrg) {
|
||||||
if (!this.progress.value.hasOwnProperty(prg)) {
|
if (!this.progress.value.hasOwnProperty(prg)) {
|
||||||
this.onJobFinish.emit(prg);
|
this.onJobFinish.emit(prg);
|
||||||
@ -65,7 +74,7 @@ export class ScheduledJobsService {
|
|||||||
this.timer = null;
|
this.timer = null;
|
||||||
this.getProgressPeriodically();
|
this.getProgressPeriodically();
|
||||||
}, repeatTime);
|
}, repeatTime);
|
||||||
this.getProgress().catch(console.error);
|
this.loadProgress().catch(console.error);
|
||||||
}
|
}
|
||||||
|
|
||||||
private incSubscribers() {
|
private incSubscribers() {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user