mirror of
https://github.com/xuthus83/pigallery2.git
synced 2025-01-14 14:43:17 +08:00
improving job ui and job handling
This commit is contained in:
parent
c4ca9e5857
commit
4c507f286d
@ -50,11 +50,13 @@ export class AdminMWs {
|
||||
}
|
||||
}
|
||||
|
||||
public static async startJob(req: Request, res: Response, next: NextFunction) {
|
||||
|
||||
public static startJob(soloRun: boolean) {
|
||||
return async (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
const id = req.params.id;
|
||||
const JobConfig: any = req.body.config;
|
||||
await ObjectManagers.getInstance().JobManager.run(id, JobConfig);
|
||||
await ObjectManagers.getInstance().JobManager.run(id, JobConfig, soloRun);
|
||||
req.resultPipe = 'ok';
|
||||
return next();
|
||||
} catch (err) {
|
||||
@ -63,6 +65,7 @@ export class AdminMWs {
|
||||
}
|
||||
return next(new ErrorDTO(ErrorCodes.JOB_ERROR, 'Job error: ' + JSON.stringify(err, null, ' '), err));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static stopJob(req: Request, res: Response, next: NextFunction) {
|
||||
@ -102,15 +105,4 @@ export class AdminMWs {
|
||||
return next(new ErrorDTO(ErrorCodes.JOB_ERROR, 'Job error: ' + JSON.stringify(err, null, ' '), err));
|
||||
}
|
||||
}
|
||||
public static getJobLastRuns(req: Request, res: Response, next: NextFunction) {
|
||||
try {
|
||||
req.resultPipe = ObjectManagers.getInstance().JobManager.getJobLastRuns();
|
||||
return next();
|
||||
} catch (err) {
|
||||
if (err instanceof Error) {
|
||||
return next(new ErrorDTO(ErrorCodes.JOB_ERROR, 'Job error: ' + err.toString(), err));
|
||||
}
|
||||
return next(new ErrorDTO(ErrorCodes.JOB_ERROR, 'Job error: ' + JSON.stringify(err, null, ' '), err));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,18 +3,17 @@ import {JobDTO} from '../../../../common/entities/job/JobDTO';
|
||||
|
||||
export interface IJobManager {
|
||||
|
||||
run(jobId: string, config: any): Promise<void>;
|
||||
|
||||
run(jobId: string, config: any, soloRun: boolean): Promise<void>;
|
||||
|
||||
stop(jobId: string): void;
|
||||
|
||||
getProgresses(): { [key: string]: JobProgressDTO };
|
||||
|
||||
|
||||
getAvailableJobs(): JobDTO[];
|
||||
|
||||
stopSchedules(): void;
|
||||
|
||||
runSchedules(): void;
|
||||
|
||||
getJobLastRuns(): { [key: string]: JobProgressDTO };
|
||||
}
|
||||
|
@ -23,18 +23,14 @@ export class JobManager implements IJobManager, IJobListener {
|
||||
}
|
||||
|
||||
getProgresses(): { [id: string]: JobProgressDTO } {
|
||||
return this.progressManager.Running;
|
||||
return this.progressManager.Progresses;
|
||||
}
|
||||
|
||||
getJobLastRuns(): { [key: string]: JobProgressDTO } {
|
||||
return this.progressManager.Finished;
|
||||
}
|
||||
|
||||
async run<T>(jobName: string, config: T): Promise<void> {
|
||||
async run<T>(jobName: string, config: T, soloRun: boolean): Promise<void> {
|
||||
const t = this.findJob(jobName);
|
||||
if (t) {
|
||||
t.JobListener = this;
|
||||
await t.start(config);
|
||||
await t.start(config, soloRun);
|
||||
} else {
|
||||
Logger.warn(LOG_TAG, 'cannot find job to start:' + jobName);
|
||||
}
|
||||
@ -54,8 +50,9 @@ export class JobManager implements IJobManager, IJobListener {
|
||||
};
|
||||
|
||||
|
||||
onJobFinished = async (job: IJob<any>, state: JobProgressStates): Promise<void> => {
|
||||
if (state !== JobProgressStates.finished) { // if it was not finished peacefully, do not start the next one
|
||||
onJobFinished = async (job: IJob<any>, state: JobProgressStates, soloRun: boolean): Promise<void> => {
|
||||
// if it was not finished peacefully or was a soloRun, do not start the next one
|
||||
if (state !== JobProgressStates.finished || soloRun === true) {
|
||||
return;
|
||||
}
|
||||
const sch = Config.Server.Jobs.scheduled.find(s => s.jobName === job.Name);
|
||||
@ -64,7 +61,7 @@ export class JobManager implements IJobManager, IJobListener {
|
||||
(<AfterJobTrigger>s.trigger).afterScheduleName === sch.name);
|
||||
for (let i = 0; i < children.length; ++i) {
|
||||
try {
|
||||
await this.run(children[i].jobName, children[i].config);
|
||||
await this.run(children[i].jobName, children[i].config, false);
|
||||
} catch (e) {
|
||||
NotificationManager.warning('Job running error:' + children[i].name, e.toString());
|
||||
}
|
||||
@ -99,7 +96,7 @@ export class JobManager implements IJobManager, IJobListener {
|
||||
|
||||
const timer: NodeJS.Timeout = setTimeout(async () => {
|
||||
this.timers = this.timers.filter(t => t.timer !== timer);
|
||||
await this.run(schedule.jobName, schedule.config);
|
||||
await this.run(schedule.jobName, schedule.config, false);
|
||||
this.runSchedule(schedule);
|
||||
}, nextDate.getTime() - Date.now());
|
||||
this.timers.push({schedule: schedule, timer: timer});
|
||||
|
@ -5,13 +5,13 @@ import {Config} from '../../../common/config/private/Config';
|
||||
import {JobProgressDTO, JobProgressStates} from '../../../common/entities/job/JobProgressDTO';
|
||||
|
||||
export class JobProgressManager {
|
||||
private static readonly VERSION = 1;
|
||||
db: {
|
||||
private static readonly VERSION = 2;
|
||||
private db: {
|
||||
version: number,
|
||||
db: { [key: string]: { progress: JobProgressDTO, timestamp: number } }
|
||||
progresses: { [key: string]: { progress: JobProgressDTO, timestamp: number } }
|
||||
} = {
|
||||
version: JobProgressManager.VERSION,
|
||||
db: {}
|
||||
progresses: {}
|
||||
};
|
||||
private readonly dbPath: string;
|
||||
private timer: NodeJS.Timeout = null;
|
||||
@ -21,29 +21,20 @@ export class JobProgressManager {
|
||||
this.loadDB().catch(console.error);
|
||||
}
|
||||
|
||||
get Running(): { [key: string]: JobProgressDTO } {
|
||||
get Progresses(): { [key: string]: JobProgressDTO } {
|
||||
const m: { [key: string]: JobProgressDTO } = {};
|
||||
for (const key of Object.keys(this.db.db)) {
|
||||
if (this.db.db[key].progress.state === JobProgressStates.running) {
|
||||
m[key] = this.db.db[key].progress;
|
||||
for (const key of Object.keys(this.db.progresses)) {
|
||||
m[key] = this.db.progresses[key].progress;
|
||||
if (this.db.progresses[key].progress.state === JobProgressStates.running) {
|
||||
m[key].time.end = Date.now();
|
||||
}
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
get Finished(): { [key: string]: JobProgressDTO } {
|
||||
const m: { [key: string]: JobProgressDTO } = {};
|
||||
for (const key of Object.keys(this.db.db)) {
|
||||
if (this.db.db[key].progress.state !== JobProgressStates.running) {
|
||||
m[key] = this.db.db[key].progress;
|
||||
}
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
onJobProgressUpdate(progress: JobProgressDTO) {
|
||||
this.db.db[progress.HashName] = {progress: progress, timestamp: Date.now()};
|
||||
this.db.progresses[progress.HashName] = {progress: progress, timestamp: Date.now()};
|
||||
this.delayedSave();
|
||||
}
|
||||
|
||||
@ -60,19 +51,20 @@ export class JobProgressManager {
|
||||
}
|
||||
this.db = db;
|
||||
|
||||
while (Object.keys(this.db.db).length > Config.Server.Jobs.maxSavedProgress) {
|
||||
while (Object.keys(this.db.progresses).length > Config.Server.Jobs.maxSavedProgress) {
|
||||
let min: string = null;
|
||||
for (const key of Object.keys(this.db.db)) {
|
||||
if (min === null || this.db.db[min].timestamp > this.db.db[key].timestamp) {
|
||||
for (const key of Object.keys(this.db.progresses)) {
|
||||
if (min === null || this.db.progresses[min].timestamp > this.db.progresses[key].timestamp) {
|
||||
min = key;
|
||||
}
|
||||
}
|
||||
delete this.db.db[min];
|
||||
delete this.db.progresses[min];
|
||||
}
|
||||
|
||||
for (const key of Object.keys(this.db.db)) {
|
||||
if (this.db.db[key].progress.state === JobProgressStates.running) {
|
||||
this.db.db[key].progress.state = JobProgressStates.interrupted;
|
||||
for (const key of Object.keys(this.db.progresses)) {
|
||||
if (this.db.progresses[key].progress.state === JobProgressStates.running ||
|
||||
this.db.progresses[key].progress.state === JobProgressStates.cancelling) {
|
||||
this.db.progresses[key].progress.state = JobProgressStates.interrupted;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -88,7 +80,7 @@ export class JobProgressManager {
|
||||
this.timer = setTimeout(async () => {
|
||||
this.saveDB().catch(console.error);
|
||||
this.timer = null;
|
||||
}, 1000);
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ export interface IJob<T> extends JobDTO {
|
||||
Progress: JobProgress;
|
||||
JobListener: IJobListener;
|
||||
|
||||
start(config: T): Promise<void>;
|
||||
start(config: T, soloRun?: boolean): Promise<void>;
|
||||
|
||||
cancel(): void;
|
||||
|
||||
|
@ -3,7 +3,7 @@ import {IJob} from './IJob';
|
||||
import {JobProgressStates} from '../../../../common/entities/job/JobProgressDTO';
|
||||
|
||||
export interface IJobListener {
|
||||
onJobFinished(job: IJob<any>, state: JobProgressStates): void;
|
||||
onJobFinished(job: IJob<any>, state: JobProgressStates, soloRun: boolean): void;
|
||||
|
||||
onProgressUpdate(progress: JobProgress): void;
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ export abstract class Job<T = void> implements IJob<T> {
|
||||
protected prResolve: () => void;
|
||||
protected IsInstant = false;
|
||||
private jobListener: IJobListener;
|
||||
private soloRun: boolean;
|
||||
|
||||
public set JobListener(value: IJobListener) {
|
||||
this.jobListener = value;
|
||||
@ -32,13 +33,15 @@ export abstract class Job<T = void> implements IJob<T> {
|
||||
return this.progress;
|
||||
}
|
||||
|
||||
public get CanRun() {
|
||||
return this.Progress == null && this.Supported;
|
||||
protected get InProgress(): boolean {
|
||||
return this.Progress !== null && (this.Progress.State === JobProgressStates.running ||
|
||||
this.Progress.State === JobProgressStates.cancelling);
|
||||
}
|
||||
|
||||
public start(config: T): Promise<void> {
|
||||
if (this.CanRun) {
|
||||
Logger.info(LOG_TAG, 'Running job: ' + this.Name);
|
||||
public start(config: T, soloRun = false): Promise<void> {
|
||||
if (this.InProgress === false && this.Supported === true) {
|
||||
Logger.info(LOG_TAG, 'Running job ' + (soloRun === true ? 'solo' : '') + ': ' + this.Name);
|
||||
this.soloRun = soloRun;
|
||||
this.config = config;
|
||||
this.progress = new JobProgress(JobDTO.getHashName(this.Name, this.config));
|
||||
this.progress.OnChange = this.jobListener.onProgressUpdate;
|
||||
@ -52,12 +55,15 @@ export abstract class Job<T = void> implements IJob<T> {
|
||||
}
|
||||
return pr;
|
||||
} else {
|
||||
Logger.info(LOG_TAG, 'Job already running: ' + this.Name);
|
||||
return Promise.reject();
|
||||
Logger.info(LOG_TAG, 'Job already running or not supported: ' + this.Name);
|
||||
return Promise.reject('Job already running or not supported: ' + this.Name);
|
||||
}
|
||||
}
|
||||
|
||||
public cancel(): void {
|
||||
if (this.InProgress === false) {
|
||||
return;
|
||||
}
|
||||
Logger.info(LOG_TAG, 'Stopping job: ' + this.Name);
|
||||
this.Progress.State = JobProgressStates.cancelling;
|
||||
}
|
||||
@ -69,18 +75,20 @@ export abstract class Job<T = void> implements IJob<T> {
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
protected abstract async step(): Promise<boolean>;
|
||||
|
||||
protected abstract async init(): Promise<void>;
|
||||
|
||||
private onFinish(): void {
|
||||
if (this.InProgress === false) {
|
||||
return;
|
||||
}
|
||||
if (this.Progress.State === JobProgressStates.running) {
|
||||
this.Progress.State = JobProgressStates.finished;
|
||||
}
|
||||
if (this.Progress.State === JobProgressStates.cancelling) {
|
||||
} else if (this.Progress.State === JobProgressStates.cancelling) {
|
||||
this.Progress.State = JobProgressStates.canceled;
|
||||
}
|
||||
|
||||
const finishState = this.Progress.State;
|
||||
this.progress = null;
|
||||
if (global.gc) {
|
||||
@ -90,13 +98,14 @@ export abstract class Job<T = void> implements IJob<T> {
|
||||
if (this.IsInstant) {
|
||||
this.prResolve();
|
||||
}
|
||||
this.jobListener.onJobFinished(this, finishState);
|
||||
this.jobListener.onJobFinished(this, finishState, this.soloRun);
|
||||
}
|
||||
|
||||
private run() {
|
||||
process.nextTick(async () => {
|
||||
try {
|
||||
if (this.Progress == null || this.Progress.State !== JobProgressStates.running) {
|
||||
this.onFinish();
|
||||
return;
|
||||
}
|
||||
if (await this.step() === false) { // finished
|
||||
|
@ -31,14 +31,14 @@ export class ThumbnailGenerationJob extends FileJob<{ sizes: number[], indexedOn
|
||||
return true;
|
||||
}
|
||||
|
||||
start(config: { sizes: number[], indexedOnly: boolean }): Promise<void> {
|
||||
start(config: { sizes: number[], indexedOnly: boolean }, soloRun = false): Promise<void> {
|
||||
for (let i = 0; i < config.sizes.length; ++i) {
|
||||
if (Config.Client.Media.Thumbnail.thumbnailSizes.indexOf(config.sizes[i]) === -1) {
|
||||
throw new Error('unknown thumbnails size: ' + config.sizes[i] + '. Add it to the possible thumbnail sizes.');
|
||||
}
|
||||
}
|
||||
|
||||
return super.start(config);
|
||||
return super.start(config, soloRun);
|
||||
}
|
||||
|
||||
protected async filterMediaFiles(files: FileDTO[]): Promise<FileDTO[]> {
|
||||
|
@ -43,16 +43,16 @@ export class AdminRouter {
|
||||
AdminMWs.getJobProgresses,
|
||||
RenderingMWs.renderResult
|
||||
);
|
||||
app.get('/api/admin/jobs/scheduled/lastRun',
|
||||
AuthenticationMWs.authenticate,
|
||||
AuthenticationMWs.authorise(UserRoles.Admin),
|
||||
AdminMWs.getJobLastRuns,
|
||||
RenderingMWs.renderResult
|
||||
);
|
||||
app.post('/api/admin/jobs/scheduled/:id/start',
|
||||
AuthenticationMWs.authenticate,
|
||||
AuthenticationMWs.authorise(UserRoles.Admin),
|
||||
AdminMWs.startJob,
|
||||
AdminMWs.startJob(false),
|
||||
RenderingMWs.renderResult
|
||||
);
|
||||
app.post('/api/admin/jobs/scheduled/:id/soloStart',
|
||||
AuthenticationMWs.authenticate,
|
||||
AuthenticationMWs.authorise(UserRoles.Admin),
|
||||
AdminMWs.startJob(true),
|
||||
RenderingMWs.renderResult
|
||||
);
|
||||
app.post('/api/admin/jobs/scheduled/:id/stop',
|
||||
|
@ -89,6 +89,7 @@ import {JobProgressComponent} from './ui/settings/jobs/progress/job-progress.set
|
||||
import {JobsSettingsComponent} from './ui/settings/jobs/jobs.settings.component';
|
||||
import {ScheduledJobsService} from './ui/settings/scheduled-jobs.service';
|
||||
import {BackendtextService} from './model/backendtext.service';
|
||||
import {JobButtonComponent} from './ui/settings/jobs/button/job-button.settings.component';
|
||||
|
||||
|
||||
@Injectable()
|
||||
@ -200,6 +201,8 @@ export function translationsFactory(locale: string) {
|
||||
IndexingSettingsComponent,
|
||||
JobProgressComponent,
|
||||
JobsSettingsComponent,
|
||||
JobButtonComponent,
|
||||
|
||||
// Pipes
|
||||
StringifyRole,
|
||||
IconizeSortingMethod,
|
||||
|
@ -103,33 +103,26 @@
|
||||
<ng-container i18n>If you add a new folder to your gallery, the site indexes it automatically.</ng-container>
|
||||
<ng-container i18n>If you would like to trigger indexing manually, click index button.</ng-container>
|
||||
<br/>
|
||||
(<ng-container i18n>Note: search only works among the indexed directories</ng-container>)
|
||||
(
|
||||
<ng-container i18n>Note: search only works among the indexed directories</ng-container>
|
||||
)
|
||||
</div>
|
||||
|
||||
|
||||
<div *ngIf="Progress != null">
|
||||
<app-settings-job-progress [progress]="Progress"></app-settings-job-progress>
|
||||
</div>
|
||||
|
||||
<app-settings-job-button #indexingButton
|
||||
[soloRun]="true"
|
||||
(error)="error=$event"
|
||||
[jobName]="indexingJobName"></app-settings-job-button>
|
||||
|
||||
|
||||
<button class="btn btn-success ml-0"
|
||||
*ngIf="Progress == null"
|
||||
[disabled]="inProgress"
|
||||
title="Indexes the folders"
|
||||
i18n-title
|
||||
(click)="index()">
|
||||
<ng-container i18n>Index folders now</ng-container>
|
||||
<span class="oi oi-media-play ml-2"></span>
|
||||
</button>
|
||||
<button class="btn btn-secondary ml-0"
|
||||
*ngIf="Progress != null"
|
||||
[disabled]="inProgress || Progress.state !== JobProgressStates.running"
|
||||
(click)="cancelIndexing()" i18n>Cancel converting
|
||||
</button>
|
||||
<button class="btn btn-danger ml-2"
|
||||
[disabled]="inProgress"
|
||||
(click)="resetDatabase()" i18n>Reset Indexes
|
||||
</button>
|
||||
<app-settings-job-button class="ml-2"
|
||||
danger="true"
|
||||
[soloRun]="true"
|
||||
(error)="error=$event"
|
||||
[disabled]="indexingButton.Running"
|
||||
[jobName]="resetJobName"></app-settings-job-button>
|
||||
|
||||
|
||||
<hr/>
|
||||
|
@ -25,6 +25,8 @@ export class IndexingSettingsComponent extends SettingsComponent<ServerConfig.In
|
||||
|
||||
types: { key: number; value: string }[] = [];
|
||||
JobProgressStates = JobProgressStates;
|
||||
readonly indexingJobName = DefaultsJobs[DefaultsJobs.Indexing];
|
||||
readonly resetJobName = DefaultsJobs[DefaultsJobs['Database Reset']];
|
||||
|
||||
constructor(_authService: AuthenticationService,
|
||||
_navigation: NavigationService,
|
||||
|
@ -0,0 +1,3 @@
|
||||
:host{
|
||||
display: inline-block;
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
<button class="btn {{danger ? 'btn-danger': 'btn-success'}}"
|
||||
title="Trigger job run manually"
|
||||
i18n-title
|
||||
*ngIf="!Running"
|
||||
[disabled]="disabled || jobsService.jobStartingStopping[jobName]"
|
||||
(click)="start();">
|
||||
<span class="mr-2" *ngIf="!shortName">Run {{jobName}} now</span>
|
||||
<span class="oi oi-media-play"></span>
|
||||
</button>
|
||||
<button class="btn btn-secondary"
|
||||
*ngIf="Running"
|
||||
[disabled]="disabled || jobsService.jobStartingStopping[jobName] || Progress.state !== JobProgressStates.running"
|
||||
(click)="stop();">
|
||||
<span class="oi oi-media-stop"></span>
|
||||
<span class="ml-2" *ngIf="!shortName">Cancel {{jobName}}</span>
|
||||
</button>
|
@ -0,0 +1,73 @@
|
||||
import {Component, EventEmitter, Input, Output} from '@angular/core';
|
||||
import {JobProgressStates} from '../../../../../../common/entities/job/JobProgressDTO';
|
||||
import {ErrorDTO} from '../../../../../../common/entities/Error';
|
||||
import {ScheduledJobsService} from '../../scheduled-jobs.service';
|
||||
import {NotificationService} from '../../../../model/notification.service';
|
||||
import {I18n} from '@ngx-translate/i18n-polyfill';
|
||||
import {JobDTO} from '../../../../../../common/entities/job/JobDTO';
|
||||
|
||||
@Component({
|
||||
selector: 'app-settings-job-button',
|
||||
templateUrl: './job-button.settings.component.html',
|
||||
styleUrls: ['./job-button.settings.component.css']
|
||||
})
|
||||
export class JobButtonComponent {
|
||||
@Input() jobName: string;
|
||||
@Input() config: any = {};
|
||||
@Input() shortName = false;
|
||||
@Input() disabled = false;
|
||||
@Input() soloRun = false;
|
||||
@Input() danger = false;
|
||||
JobProgressStates = JobProgressStates;
|
||||
@Output() error = new EventEmitter<string>();
|
||||
|
||||
constructor(private notification: NotificationService,
|
||||
public jobsService: ScheduledJobsService,
|
||||
private i18n: I18n) {
|
||||
}
|
||||
|
||||
public get Running() {
|
||||
return this.Progress && (this.Progress.state === JobProgressStates.running || this.Progress.state === JobProgressStates.cancelling);
|
||||
}
|
||||
|
||||
get Progress() {
|
||||
return this.jobsService.progress.value[JobDTO.getHashName(this.jobName, this.config)];
|
||||
}
|
||||
|
||||
|
||||
public async start() {
|
||||
this.error.emit('');
|
||||
try {
|
||||
await this.jobsService.start(this.jobName, this.config, this.soloRun);
|
||||
this.notification.info(this.i18n('Job') + ' ' + this.jobName + ' ' + this.i18n('started'));
|
||||
return true;
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
if (err.message) {
|
||||
this.error.emit((<ErrorDTO>err).message);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public async stop() {
|
||||
this.error.emit('');
|
||||
try {
|
||||
await this.jobsService.stop(this.jobName);
|
||||
this.notification.info(this.i18n('Job') + ' ' + this.jobName + ' ' + this.i18n('stopped'));
|
||||
return true;
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
if (err.message) {
|
||||
this.error.emit((<ErrorDTO>err).message);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -8,9 +8,11 @@
|
||||
|
||||
<div *ngFor="let schedule of sortedSchedules() as schedules; let i= index">
|
||||
<div class="card bg-light {{shouldIdent(schedule,schedules[i-1])? 'ml-4' : ''}}">
|
||||
<div class="card-header clickable"
|
||||
(click)="showDetails[schedule.name]=!showDetails[schedule.name]">
|
||||
<div class="card-header">
|
||||
<div class="d-flex justify-content-between">
|
||||
<div class="clickable"
|
||||
(click)="showDetails[schedule.name]=!showDetails[schedule.name]">
|
||||
<span class="oi oi-chevron-{{showDetails[schedule.name] ? 'bottom' : 'right'}}"></span>
|
||||
{{schedule.name}} @<!--
|
||||
-->
|
||||
<ng-container [ngSwitch]="schedule.trigger.type">
|
||||
@ -26,19 +28,14 @@
|
||||
{{schedule.trigger.afterScheduleName}}
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
</div>
|
||||
<div>
|
||||
<button class="btn btn-danger job-control-button" (click)="remove(i)"><span class="oi oi-trash"></span>
|
||||
</button>
|
||||
<button class="btn btn-success job-control-button"
|
||||
*ngIf="!getProgress(schedule)"
|
||||
[disabled]="disableButtons"
|
||||
(click)="start(schedule); $event.stopPropagation();"><span class="oi oi-media-play"></span>
|
||||
</button>
|
||||
<button class="btn btn-secondary job-control-button"
|
||||
*ngIf="getProgress(schedule)"
|
||||
[disabled]="disableButtons || getProgress(schedule).state !== JobProgressStates.running"
|
||||
(click)="stop(schedule); $event.stopPropagation();"><span class="oi oi-media-stop"></span>
|
||||
<button class="btn btn-danger job-control-button" (click)="remove(schedule)"><span class="oi oi-trash"></span>
|
||||
</button>
|
||||
<app-settings-job-button class="job-control-button ml-2"
|
||||
(error)="error=$event"
|
||||
[jobName]="schedule.jobName" [config]="schedule.config"
|
||||
[shortName]="true"></app-settings-job-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -120,18 +117,10 @@
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<button class="btn btn-success float-right"
|
||||
*ngIf="!getProgress(schedule)"
|
||||
[disabled]="disableButtons"
|
||||
title="Trigger job run manually"
|
||||
i18n-title
|
||||
(click)="start(schedule)" i18n>Start now
|
||||
</button>
|
||||
<button class="btn btn-secondary float-right"
|
||||
*ngIf="getProgress(schedule)"
|
||||
[disabled]="disableButtons || getProgress(schedule).state !== JobProgressStates.running"
|
||||
(click)="stop(schedule)" i18n>Stop
|
||||
</button>
|
||||
<app-settings-job-button class="float-right"
|
||||
[jobName]="schedule.jobName"
|
||||
(error)="error=$event"
|
||||
[config]="schedule.config"></app-settings-job-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -194,8 +183,8 @@
|
||||
|
||||
<app-settings-job-progress
|
||||
class="card-footer bg-transparent"
|
||||
*ngIf="getProgress(schedule) || getLastRun(schedule)"
|
||||
[progress]="getProgress(schedule) || getLastRun(schedule)">
|
||||
*ngIf="getProgress(schedule)"
|
||||
[progress]="getProgress(schedule)">
|
||||
</app-settings-job-progress>
|
||||
|
||||
</div>
|
||||
|
@ -5,7 +5,6 @@ import {NavigationService} from '../../../model/navigation.service';
|
||||
import {NotificationService} from '../../../model/notification.service';
|
||||
import {SettingsComponent} from '../_abstract/abstract.settings.component';
|
||||
import {I18n} from '@ngx-translate/i18n-polyfill';
|
||||
import {ErrorDTO} from '../../../../../common/entities/Error';
|
||||
import {ScheduledJobsService} from '../scheduled-jobs.service';
|
||||
import {
|
||||
AfterJobTrigger,
|
||||
@ -18,7 +17,6 @@ import {
|
||||
import {Utils} from '../../../../../common/Utils';
|
||||
import {ServerConfig} from '../../../../../common/config/private/IPrivateConfig';
|
||||
import {ConfigTemplateEntry} from '../../../../../common/entities/job/JobDTO';
|
||||
import {Job} from '../../../../../backend/model/jobs/jobs/Job';
|
||||
import {ModalDirective} from 'ngx-bootstrap/modal';
|
||||
import {JobProgressDTO, JobProgressStates} from '../../../../../common/entities/job/JobProgressDTO';
|
||||
import {BackendtextService} from '../../../model/backendtext.service';
|
||||
@ -96,46 +94,8 @@ export class JobsSettingsComponent extends SettingsComponent<ServerConfig.JobCon
|
||||
this.jobsService.unsubscribeFromProgress();
|
||||
}
|
||||
|
||||
public async start(schedule: JobScheduleDTO) {
|
||||
this.error = '';
|
||||
try {
|
||||
this.disableButtons = true;
|
||||
await this.jobsService.start(schedule.jobName, schedule.config);
|
||||
this.notification.info(this.i18n('Job') + ' ' + schedule.jobName + ' ' + this.i18n('started'));
|
||||
return true;
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
if (err.message) {
|
||||
this.error = (<ErrorDTO>err).message;
|
||||
}
|
||||
} finally {
|
||||
this.disableButtons = false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public async stop(schedule: JobScheduleDTO) {
|
||||
this.error = '';
|
||||
try {
|
||||
this.disableButtons = true;
|
||||
await this.jobsService.stop(schedule.jobName);
|
||||
this.notification.info(this.i18n('Job') + ' ' + schedule.jobName + ' ' + this.i18n('stopped'));
|
||||
return true;
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
if (err.message) {
|
||||
this.error = (<ErrorDTO>err).message;
|
||||
}
|
||||
} finally {
|
||||
this.disableButtons = false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
remove(index: number) {
|
||||
this.settings.scheduled.splice(index, 1);
|
||||
remove(schedule: JobScheduleDTO) {
|
||||
this.settings.scheduled.splice(this.settings.scheduled.indexOf(schedule), 1);
|
||||
}
|
||||
|
||||
jobTypeChanged(schedule: JobScheduleDTO) {
|
||||
@ -211,18 +171,11 @@ export class JobsSettingsComponent extends SettingsComponent<ServerConfig.JobCon
|
||||
this.jobModal.hide();
|
||||
}
|
||||
|
||||
getConfigHash(schedule: JobScheduleDTO): string {
|
||||
return JSON.stringify(schedule.config);
|
||||
}
|
||||
|
||||
getProgress(schedule: JobScheduleDTO): JobProgressDTO {
|
||||
return this.jobsService.getProgress(schedule);
|
||||
}
|
||||
|
||||
getLastRun(schedule: JobScheduleDTO): JobProgressDTO {
|
||||
return this.jobsService.getLastRun(schedule);
|
||||
}
|
||||
|
||||
private getNextRunningDate(sch: JobScheduleDTO, list: JobScheduleDTO[], depth: number = 0): number {
|
||||
if (depth > list.length) {
|
||||
return 0;
|
||||
|
@ -1,5 +1,4 @@
|
||||
<div class="row clickable" *ngIf="!IsRunning"
|
||||
(click)="openModal(template)">
|
||||
<div class="row" *ngIf="Stopped">
|
||||
<div class="col-md-2 col-12" i18n>
|
||||
Last run:
|
||||
</div>
|
||||
@ -7,19 +6,24 @@
|
||||
<span class="oi oi-clock" aria-hidden="true"></span>
|
||||
{{progress.time.start | date:'medium'}} - {{progress.time.end | date:'mediumTime'}}
|
||||
</div>
|
||||
<div class="col-md-3 col-6" title="processed+skipped/all" i18n-title>
|
||||
<div class="col-md-2 col-4"
|
||||
title="processed:{{progress.steps.processed}}+ skipped:{{progress.steps.skipped}} / all:{{progress.steps.all}}">
|
||||
<span class="oi oi-check" aria-hidden="true"></span>
|
||||
{{progress.steps.processed}}+{{progress.steps.skipped}}/{{progress.steps.all}}
|
||||
{{progress.steps.processed + progress.steps.skipped}}/{{progress.steps.all}}
|
||||
</div>
|
||||
<div class="col-md-3 col-6" title="Status" i18n-title>
|
||||
<div class="col-md-2 col-4" title="Status" i18n-title>
|
||||
<span class="oi oi-pulse" aria-hidden="true"></span>
|
||||
{{JobProgressStates[progress.state]}}
|
||||
</div>
|
||||
<div class="col-md-2 col-4">
|
||||
<button class="btn btn-secondary float-right" (click)="openModal(template)">
|
||||
<span class="oi oi-resize-both"></span>
|
||||
</button>
|
||||
</div>
|
||||
<div *ngIf="IsRunning" class="clickable" (click)="openModal(template)">
|
||||
</div>
|
||||
<div *ngIf="Running">
|
||||
|
||||
<div class="form-group row">
|
||||
<div class="col-md-12">
|
||||
<div class="input-group form-group">
|
||||
<input
|
||||
*ngIf="progress.state === JobProgressStates.running" type="text" class="form-control" disabled
|
||||
[ngModel]="progress.logs[progress.logs.length-1].comment" name="details">
|
||||
@ -27,6 +31,10 @@
|
||||
*ngIf="progress.state === JobProgressStates.cancelling" type="text" class="form-control" disabled
|
||||
value="Cancelling: {{progress.logs[progress.logs.length-1].comment}}"
|
||||
i18n-value name="details">
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-secondary" (click)="openModal(template)">
|
||||
<span class="oi oi-resize-both"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -47,7 +55,7 @@
|
||||
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}}
|
||||
{{progress.steps.processed + progress.steps.skipped}}/{{progress.steps.all}}
|
||||
</div>
|
||||
<div
|
||||
*ngIf="progress.steps.all === 0"
|
||||
@ -69,10 +77,12 @@
|
||||
</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 class="container">
|
||||
<div class="row justify-content-between">
|
||||
<div>Processed: {{progress.steps.processed}}</div>
|
||||
<div>Skipped: {{progress.steps.skipped}}</div>
|
||||
<div>Left: {{progress.steps.all - progress.steps.skipped - progress.steps.processed}}</div>
|
||||
<div>All: {{progress.steps.all}}</div>
|
||||
</div>
|
||||
<div class="row mt-3 mb-3">
|
||||
<div class="progress col-12">
|
||||
@ -95,6 +105,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card bg-light">
|
||||
<div class="card-header" i18n>
|
||||
Logs
|
||||
|
@ -20,6 +20,9 @@ export class JobProgressComponent implements OnDestroy, OnChanges {
|
||||
}
|
||||
|
||||
get Name(): string {
|
||||
if (!this.progress) {
|
||||
return '';
|
||||
}
|
||||
return this.progress.HashName;
|
||||
}
|
||||
|
||||
@ -28,11 +31,15 @@ export class JobProgressComponent implements OnDestroy, OnChanges {
|
||||
return 0;
|
||||
}
|
||||
return (this.progress.time.end - this.progress.time.start) /
|
||||
(this.progress.steps.processed + this.progress.steps.skipped) * this.progress.steps.all;
|
||||
(this.progress.steps.processed) * (this.progress.steps.all - this.progress.steps.skipped);
|
||||
}
|
||||
|
||||
get IsRunning() {
|
||||
return this.progress.state === JobProgressStates.running || this.progress.state === JobProgressStates.canceled;
|
||||
get Running() {
|
||||
return this.progress && (this.progress.state === JobProgressStates.running || this.progress.state === JobProgressStates.cancelling);
|
||||
}
|
||||
|
||||
get Stopped() {
|
||||
return this.progress && (this.progress.state !== JobProgressStates.running && this.progress.state !== JobProgressStates.cancelling);
|
||||
}
|
||||
|
||||
get TimeLeft(): number {
|
||||
|
@ -100,21 +100,10 @@
|
||||
</button>
|
||||
|
||||
<div [hidden]="!settings.client.Converting.enabled">
|
||||
<button class="btn btn-success float-left ml-0"
|
||||
*ngIf="Progress == null"
|
||||
[disabled]="inProgress"
|
||||
title="Indexes the folders"
|
||||
i18n-title
|
||||
(click)="convertPhoto()">
|
||||
<ng-container i18n>Convert photos now</ng-container>
|
||||
<span class="oi oi-media-play ml-2"></span>
|
||||
</button>
|
||||
<button class="btn btn-secondary float-left ml-0"
|
||||
*ngIf="Progress != null"
|
||||
[disabled]="inProgress || Progress.state !== JobProgressStates.running"
|
||||
(click)="cancelPhotoConverting()" i18n>Cancel converting
|
||||
</button>
|
||||
|
||||
<app-settings-job-button class="float-left"
|
||||
[soloRun]="true"
|
||||
(error)="error=$event"
|
||||
[jobName]="jobName"></app-settings-job-button>
|
||||
|
||||
<ng-container *ngIf="Progress != null">
|
||||
<br/>
|
||||
|
@ -39,6 +39,7 @@ export class PhotoSettingsComponent extends SettingsComponent<{
|
||||
}
|
||||
return v;
|
||||
});
|
||||
readonly jobName = DefaultsJobs[DefaultsJobs['Photo Converting']];
|
||||
|
||||
constructor(_authService: AuthenticationService,
|
||||
_navigation: NavigationService,
|
||||
@ -61,44 +62,6 @@ export class PhotoSettingsComponent extends SettingsComponent<{
|
||||
get Progress() {
|
||||
return this.jobsService.progress.value[JobDTO.getHashName(DefaultsJobs[DefaultsJobs['Photo Converting']])];
|
||||
}
|
||||
|
||||
async convertPhoto() {
|
||||
this.inProgress = true;
|
||||
this.error = '';
|
||||
try {
|
||||
await this.jobsService.start(DefaultsJobs[DefaultsJobs['Photo Converting']]);
|
||||
this.notification.info(this.i18n('Photo converting started'));
|
||||
return true;
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
if (err.message) {
|
||||
this.error = (<ErrorDTO>err).message;
|
||||
}
|
||||
} finally {
|
||||
this.inProgress = false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
async cancelPhotoConverting() {
|
||||
this.inProgress = true;
|
||||
this.error = '';
|
||||
try {
|
||||
await this.jobsService.stop(DefaultsJobs[DefaultsJobs['Photo Converting']]);
|
||||
this.notification.info(this.i18n('Photo converting interrupted'));
|
||||
return true;
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
if (err.message) {
|
||||
this.error = (<ErrorDTO>err).message;
|
||||
}
|
||||
} finally {
|
||||
this.inProgress = false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -10,24 +10,19 @@ export class ScheduledJobsService {
|
||||
|
||||
|
||||
public progress: BehaviorSubject<{ [key: string]: JobProgressDTO }>;
|
||||
public lastRuns: BehaviorSubject<{ [key: string]: JobProgressDTO }>;
|
||||
public onJobFinish: EventEmitter<string> = new EventEmitter<string>();
|
||||
timer: number = null;
|
||||
public jobStartingStopping: { [key: string]: boolean } = {};
|
||||
private subscribers = 0;
|
||||
|
||||
constructor(private _networkService: NetworkService) {
|
||||
this.progress = 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 {
|
||||
this.incSubscribers();
|
||||
}
|
||||
@ -40,20 +35,24 @@ export class ScheduledJobsService {
|
||||
return await this.loadProgress();
|
||||
}
|
||||
|
||||
public async start(id: string, config?: any): Promise<void> {
|
||||
await this._networkService.postJson('/admin/jobs/scheduled/' + id + '/start', {config: config});
|
||||
public async start(jobName: string, config?: any, soloStart: boolean = false): Promise<void> {
|
||||
this.jobStartingStopping[jobName] = true;
|
||||
await this._networkService.postJson('/admin/jobs/scheduled/' + jobName + '/' + (soloStart === true ? 'soloStart' : 'start'),
|
||||
{config: config});
|
||||
delete this.jobStartingStopping[jobName];
|
||||
this.forceUpdate();
|
||||
}
|
||||
|
||||
public async stop(id: string): Promise<void> {
|
||||
await this._networkService.postJson('/admin/jobs/scheduled/' + id + '/stop');
|
||||
public async stop(jobName: string): Promise<void> {
|
||||
this.jobStartingStopping[jobName] = true;
|
||||
await this._networkService.postJson('/admin/jobs/scheduled/' + jobName + '/stop');
|
||||
delete this.jobStartingStopping[jobName];
|
||||
this.forceUpdate();
|
||||
}
|
||||
|
||||
protected async loadProgress(): Promise<void> {
|
||||
const prevPrg = this.progress.value;
|
||||
this.progress.next(await this._networkService.getJson<{ [key: string]: JobProgressDTO }>('/admin/jobs/scheduled/progress'));
|
||||
this.lastRuns.next(await this._networkService.getJson<{ [key: string]: JobProgressDTO }>('/admin/jobs/scheduled/lastRun'));
|
||||
for (const prg in prevPrg) {
|
||||
if (!this.progress.value.hasOwnProperty(prg)) {
|
||||
this.onJobFinish.emit(prg);
|
||||
|
@ -74,20 +74,11 @@
|
||||
</button>
|
||||
|
||||
|
||||
<button class="btn btn-success float-left ml-0"
|
||||
*ngIf="Progress == null"
|
||||
[disabled]="inProgress"
|
||||
title="Generates all thumbnails now"
|
||||
i18n-title
|
||||
(click)="startJob()">
|
||||
<ng-container i18n>Generate thumbnails now</ng-container>
|
||||
<span class="oi oi-media-play ml-2"></span>
|
||||
</button>
|
||||
<button class="btn btn-secondary float-left ml-0"
|
||||
*ngIf="Progress != null"
|
||||
[disabled]="inProgress || Progress.state !== JobProgressStates.running"
|
||||
(click)="cancelJob()" i18n>Cancel thumbnail generation
|
||||
</button>
|
||||
<app-settings-job-button class="float-left"
|
||||
[soloRun]="true"
|
||||
(error)="error=$event"
|
||||
[jobName]="jobName"
|
||||
[config]="Config"></app-settings-job-button>
|
||||
|
||||
|
||||
<ng-container *ngIf="Progress != null">
|
||||
|
@ -8,7 +8,6 @@ import {ThumbnailSettingsService} from './thumbnail.settings.service';
|
||||
import {I18n} from '@ngx-translate/i18n-polyfill';
|
||||
import {ServerConfig} from '../../../../../common/config/private/IPrivateConfig';
|
||||
import {DefaultsJobs, JobDTO} from '../../../../../common/entities/job/JobDTO';
|
||||
import {ErrorDTO} from '../../../../../common/entities/Error';
|
||||
import {ScheduledJobsService} from '../scheduled-jobs.service';
|
||||
import {JobProgressStates} from '../../../../../common/entities/job/JobProgressDTO';
|
||||
|
||||
@ -23,6 +22,7 @@ export class ThumbnailSettingsComponent
|
||||
extends SettingsComponent<{ server: ServerConfig.ThumbnailConfig, client: ClientConfig.ThumbnailConfig }>
|
||||
implements OnInit {
|
||||
JobProgressStates = JobProgressStates;
|
||||
readonly jobName = DefaultsJobs[DefaultsJobs['Thumbnail Generation']];
|
||||
|
||||
constructor(_authService: AuthenticationService,
|
||||
_navigation: NavigationService,
|
||||
@ -36,6 +36,10 @@ export class ThumbnailSettingsComponent
|
||||
}));
|
||||
}
|
||||
|
||||
get Config(): any {
|
||||
return {sizes: this.original.client.thumbnailSizes[0]};
|
||||
}
|
||||
|
||||
get ThumbnailSizes(): string {
|
||||
return this.settings.client.thumbnailSizes.join('; ');
|
||||
}
|
||||
@ -49,52 +53,12 @@ export class ThumbnailSettingsComponent
|
||||
}
|
||||
|
||||
get Progress() {
|
||||
return this.jobsService.progress.value[JobDTO.getHashName(DefaultsJobs[DefaultsJobs['Thumbnail Generation']],
|
||||
{sizes: this.original.client.thumbnailSizes[0]})];
|
||||
return this.jobsService.progress.value[JobDTO.getHashName(this.jobName, this.Config)];
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
super.ngOnInit();
|
||||
}
|
||||
|
||||
async startJob() {
|
||||
this.inProgress = true;
|
||||
this.error = '';
|
||||
try {
|
||||
await this.jobsService.start(DefaultsJobs[DefaultsJobs['Thumbnail Generation']], {sizes: this.original.client.thumbnailSizes[0]});
|
||||
this.notification.info(this.i18n('Thumbnail generation started'));
|
||||
this.inProgress = false;
|
||||
return true;
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
if (err.message) {
|
||||
this.error = (<ErrorDTO>err).message;
|
||||
}
|
||||
}
|
||||
|
||||
this.inProgress = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
async cancelJob() {
|
||||
this.inProgress = true;
|
||||
this.error = '';
|
||||
try {
|
||||
await this.jobsService.stop(DefaultsJobs[DefaultsJobs['Thumbnail Generation']]);
|
||||
this.notification.info(this.i18n('Thumbnail generation interrupted'));
|
||||
this.inProgress = false;
|
||||
return true;
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
if (err.message) {
|
||||
this.error = (<ErrorDTO>err).message;
|
||||
}
|
||||
}
|
||||
|
||||
this.inProgress = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -115,6 +115,9 @@
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<button class="btn btn-success float-right"
|
||||
[disabled]="!settingsForm.form.valid || !changed || inProgress"
|
||||
(click)="save()" i18n>Save
|
||||
@ -124,22 +127,10 @@
|
||||
(click)="reset()" i18n>Reset
|
||||
</button>
|
||||
|
||||
|
||||
<button class="btn btn-success float-left ml-0"
|
||||
*ngIf="Progress == null"
|
||||
[disabled]="inProgress"
|
||||
title="Indexes the folders"
|
||||
i18n-title
|
||||
(click)="transcode()">
|
||||
<ng-container i18n>Transcode videos now</ng-container>
|
||||
<span class="oi oi-media-play ml-2"></span>
|
||||
</button>
|
||||
<button class="btn btn-secondary float-left ml-0"
|
||||
*ngIf="Progress != null"
|
||||
[disabled]="inProgress || Progress.state !== JobProgressStates.running"
|
||||
(click)="cancelTranscoding()" i18n>Cancel transcoding
|
||||
</button>
|
||||
|
||||
<app-settings-job-button class="float-left"
|
||||
[soloRun]="true"
|
||||
(error)="error=$event"
|
||||
[jobName]="jobName"></app-settings-job-button>
|
||||
|
||||
<ng-container *ngIf="Progress != null">
|
||||
<br/>
|
||||
|
@ -8,7 +8,6 @@ import {ClientConfig} from '../../../../../common/config/public/ConfigClass';
|
||||
import {I18n} from '@ngx-translate/i18n-polyfill';
|
||||
import {ScheduledJobsService} from '../scheduled-jobs.service';
|
||||
import {DefaultsJobs, JobDTO} from '../../../../../common/entities/job/JobDTO';
|
||||
import {ErrorDTO} from '../../../../../common/entities/Error';
|
||||
import {ServerConfig} from '../../../../../common/config/private/IPrivateConfig';
|
||||
import {JobProgressStates} from '../../../../../common/entities/job/JobProgressDTO';
|
||||
|
||||
@ -28,6 +27,7 @@ export class VideoSettingsComponent extends SettingsComponent<{ server: ServerCo
|
||||
fps = [24, 25, 30, 48, 50, 60];
|
||||
|
||||
JobProgressStates = JobProgressStates;
|
||||
readonly jobName = DefaultsJobs[DefaultsJobs['Video Converting']];
|
||||
|
||||
constructor(_authService: AuthenticationService,
|
||||
_navigation: NavigationService,
|
||||
@ -92,43 +92,6 @@ export class VideoSettingsComponent extends SettingsComponent<{ server: ServerCo
|
||||
}
|
||||
|
||||
|
||||
async transcode() {
|
||||
this.inProgress = true;
|
||||
this.error = '';
|
||||
try {
|
||||
await this.jobsService.start(DefaultsJobs[DefaultsJobs['Video Converting']]);
|
||||
this.notification.info(this.i18n('Video transcoding started'));
|
||||
this.inProgress = false;
|
||||
return true;
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
if (err.message) {
|
||||
this.error = (<ErrorDTO>err).message;
|
||||
}
|
||||
}
|
||||
|
||||
this.inProgress = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
async cancelTranscoding() {
|
||||
this.inProgress = true;
|
||||
this.error = '';
|
||||
try {
|
||||
await this.jobsService.stop(DefaultsJobs[DefaultsJobs['Video Converting']]);
|
||||
this.notification.info(this.i18n('Video transcoding interrupted'));
|
||||
this.inProgress = false;
|
||||
return true;
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
if (err.message) {
|
||||
this.error = (<ErrorDTO>err).message;
|
||||
}
|
||||
}
|
||||
|
||||
this.inProgress = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user