commit
3a25a8b812
@ -1,7 +0,0 @@
|
|||||||
use async_trait::async_trait;
|
|
||||||
|
|
||||||
#[async_trait]
|
|
||||||
pub trait AsyncTryFrom<T> {
|
|
||||||
type Error;
|
|
||||||
fn async_try_from(other: T) -> Result<Self, Self::Error>;
|
|
||||||
}
|
|
@ -1,8 +1,8 @@
|
|||||||
import {Component, Inject, ViewChild} from "@angular/core";
|
import {Component, Inject, ViewChild} from "@angular/core";
|
||||||
import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog";
|
import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog";
|
||||||
import {RepositoryFormComponent} from "../repository-form/repository-form.component";
|
import {RepositoryFormComponent} from "../repository-form/repository-form.component";
|
||||||
import {RepositoryService} from "../../../../../services/repository/repository.service";
|
import {RepositoryService} from "../../../../services/repository/repository.service";
|
||||||
import {LoggingService} from "../../../../../services/logging/logging.service";
|
import {LoggingService} from "../../../../services/logging/logging.service";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "app-add-repository-dialog",
|
selector: "app-add-repository-dialog",
|
@ -1,9 +1,9 @@
|
|||||||
import {Component, Inject, ViewChild} from "@angular/core";
|
import {Component, Inject, ViewChild} from "@angular/core";
|
||||||
import {RepositoryFormComponent} from "../repository-form/repository-form.component";
|
import {RepositoryFormComponent} from "../repository-form/repository-form.component";
|
||||||
import {RepositoryService} from "../../../../../services/repository/repository.service";
|
import {RepositoryService} from "../../../../services/repository/repository.service";
|
||||||
import {LoggingService} from "../../../../../services/logging/logging.service";
|
import {LoggingService} from "../../../../services/logging/logging.service";
|
||||||
import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog";
|
import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog";
|
||||||
import {Repository} from "../../../../../../api/models/Repository";
|
import {Repository} from "../../../../../api/models/Repository";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "app-edit-repository-dialog",
|
selector: "app-edit-repository-dialog",
|
@ -1,7 +1,7 @@
|
|||||||
import {Component, Input, OnInit, Output} from "@angular/core";
|
import {Component, Input, OnInit, Output} from "@angular/core";
|
||||||
import {AbstractControl, FormControl, FormGroup, ValidationErrors, Validators} from "@angular/forms";
|
import {AbstractControl, FormControl, FormGroup, ValidationErrors, Validators} from "@angular/forms";
|
||||||
import {Repository} from "../../../../../../api/models/Repository";
|
import {Repository} from "../../../../../api/models/Repository";
|
||||||
import {RepositoryService} from "../../../../../services/repository/repository.service";
|
import {RepositoryService} from "../../../../services/repository/repository.service";
|
||||||
import {dialog} from "@tauri-apps/api";
|
import {dialog} from "@tauri-apps/api";
|
||||||
import {MatDialog} from "@angular/material/dialog";
|
import {MatDialog} from "@angular/material/dialog";
|
||||||
|
|
@ -0,0 +1,29 @@
|
|||||||
|
<mat-card>
|
||||||
|
<mat-card-header>
|
||||||
|
<mat-card-title>
|
||||||
|
<h1>Maintenance</h1></mat-card-title>
|
||||||
|
</mat-card-header>
|
||||||
|
<mat-card-content>
|
||||||
|
<div class="button-list">
|
||||||
|
<button (click)="this.runJob('CheckIntegrity', false)" color="primary" mat-flat-button>Check Integrity
|
||||||
|
</button>
|
||||||
|
<button (click)="this.runJob('Vacuum', false)" color="primary" mat-flat-button>Optimize Database</button>
|
||||||
|
<button (click)="this.runJob('GenerateThumbnails', true)"
|
||||||
|
[disabled]="this.jobState.GenerateThumbnails"
|
||||||
|
color="primary"
|
||||||
|
mat-flat-button>Generate missing
|
||||||
|
Thumbnails
|
||||||
|
<mat-progress-bar *ngIf="this.jobState.GenerateThumbnails" color="primary"
|
||||||
|
mode="indeterminate"></mat-progress-bar>
|
||||||
|
</button>
|
||||||
|
<button (click)="this.runJob('CalculateSizes', true)"
|
||||||
|
[disabled]="this.jobState.CalculateSizes"
|
||||||
|
color="primary"
|
||||||
|
mat-flat-button>Recalculate Repository
|
||||||
|
Size
|
||||||
|
<mat-progress-bar *ngIf="this.jobState.CalculateSizes" color="primary"
|
||||||
|
mode="indeterminate"></mat-progress-bar>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
@ -0,0 +1,18 @@
|
|||||||
|
mat-card-header {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
mat-card-title h1 {
|
||||||
|
margin: auto;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-list {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
button {
|
||||||
|
display: block;
|
||||||
|
margin: 2em auto;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
import {ComponentFixture, TestBed} from "@angular/core/testing";
|
||||||
|
|
||||||
|
import {RepositoryMaintenanceComponent} from "./repository-maintenance.component";
|
||||||
|
|
||||||
|
describe("RepositoryMaintenanceComponent", () => {
|
||||||
|
let component: RepositoryMaintenanceComponent;
|
||||||
|
let fixture: ComponentFixture<RepositoryMaintenanceComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [RepositoryMaintenanceComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(RepositoryMaintenanceComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should create", () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,85 @@
|
|||||||
|
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit} from "@angular/core";
|
||||||
|
import {JobService} from "../../../../services/job/job.service";
|
||||||
|
import {JobType} from "../../../../../api/api-types/job";
|
||||||
|
import {MatDialog} from "@angular/material/dialog";
|
||||||
|
import {BusyDialogComponent, BusyDialogData} from "../../app-common/busy-dialog/busy-dialog.component";
|
||||||
|
import {LoggingService} from "../../../../services/logging/logging.service";
|
||||||
|
import {BehaviorSubject} from "rxjs";
|
||||||
|
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: "app-repository-maintenance",
|
||||||
|
templateUrl: "./repository-maintenance.component.html",
|
||||||
|
styleUrls: ["./repository-maintenance.component.scss"],
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush
|
||||||
|
})
|
||||||
|
export class RepositoryMaintenanceComponent implements OnInit, OnDestroy {
|
||||||
|
public jobState: { [Property in JobType]?: boolean } = {
|
||||||
|
CalculateSizes: false,
|
||||||
|
GenerateThumbnails: false,
|
||||||
|
};
|
||||||
|
private jobStatusInterval: any;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private changeDetector: ChangeDetectorRef,
|
||||||
|
private jobService: JobService,
|
||||||
|
private dialog: MatDialog,
|
||||||
|
private logger: LoggingService
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public ngOnDestroy(): void {
|
||||||
|
clearInterval(this.jobStatusInterval);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ngOnInit() {
|
||||||
|
await this.updateJobStatus();
|
||||||
|
this.jobStatusInterval = setInterval(() => this.updateJobStatus(), 10000);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async runJob(jobType: JobType, runAsync: boolean) {
|
||||||
|
if (runAsync) {
|
||||||
|
this.jobState[jobType] = true;
|
||||||
|
this.jobService.runJob(jobType).then(() => this.delay(1000)).catch(this.logger.error).finally(() => {
|
||||||
|
this.jobState[jobType] = false;
|
||||||
|
this.changeDetector.markForCheck();
|
||||||
|
});
|
||||||
|
this.changeDetector.markForCheck();
|
||||||
|
} else {
|
||||||
|
const dialog = this.dialog.open<BusyDialogComponent, BusyDialogData>(BusyDialogComponent, {
|
||||||
|
disableClose: true,
|
||||||
|
minWidth: "30%",
|
||||||
|
minHeight: "30%",
|
||||||
|
data: {
|
||||||
|
title: "Synchronous Job",
|
||||||
|
message: new BehaviorSubject(`Running Job ${jobType}`),
|
||||||
|
allowCancel: false,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
this.changeDetector.markForCheck();
|
||||||
|
await this.jobService.runJob(jobType);
|
||||||
|
} catch (err: any) {
|
||||||
|
this.logger.error(err);
|
||||||
|
} finally {
|
||||||
|
dialog.close();
|
||||||
|
this.changeDetector.markForCheck();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async delay(ms: number) {
|
||||||
|
return new Promise((res, _) => setTimeout(
|
||||||
|
res,
|
||||||
|
ms
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
private async updateJobStatus() {
|
||||||
|
const indexedTypes: JobType[] = ["CalculateSizes", "GenerateThumbnails"];
|
||||||
|
for (const jobType of indexedTypes) {
|
||||||
|
this.jobState[jobType] = await this.jobService.isJobRunning(jobType);
|
||||||
|
}
|
||||||
|
this.changeDetector.markForCheck();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue