Add maintenance menu to repository overview

Signed-off-by: trivernis <trivernis@protonmail.com>
pull/25/head
trivernis 2 years ago
parent 99c224586a
commit 6dfefe01c2
Signed by: Trivernis
GPG Key ID: DFFFCC2C7A02DB45

@ -8,6 +8,15 @@ version = "0.11.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3"
[[package]]
name = "addr2line"
version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b"
dependencies = [
"gimli",
]
[[package]]
name = "adler"
version = "1.0.2"
@ -40,6 +49,15 @@ dependencies = [
"version_check",
]
[[package]]
name = "aho-corasick"
version = "0.7.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
dependencies = [
"memchr",
]
[[package]]
name = "aliasable"
version = "0.1.3"
@ -185,6 +203,21 @@ dependencies = [
"mime",
]
[[package]]
name = "backtrace"
version = "0.3.65"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11a17d453482a265fd5f8479f2a3f405566e6ca627837aaddb85af8b1ab8ef61"
dependencies = [
"addr2line",
"cc",
"cfg-if 1.0.0",
"libc",
"miniz_oxide",
"object",
"rustc-demangle",
]
[[package]]
name = "bae"
version = "0.1.7"
@ -1015,6 +1048,12 @@ dependencies = [
"weezl",
]
[[package]]
name = "gimli"
version = "0.26.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4"
[[package]]
name = "glob"
version = "0.3.0"
@ -1150,6 +1189,21 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421"
[[package]]
name = "human-panic"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39f357a500abcbd7c5f967c1d45c8838585b36743823b9d43488f24850534e36"
dependencies = [
"backtrace",
"os_type",
"serde",
"serde_derive",
"termcolor",
"toml",
"uuid",
]
[[package]]
name = "humantime"
version = "2.1.0"
@ -1451,6 +1505,7 @@ version = "1.0.3"
dependencies = [
"console-subscriber",
"glob",
"human-panic",
"log",
"mediarepo-core",
"mediarepo-logic",
@ -1785,6 +1840,15 @@ dependencies = [
"libc",
]
[[package]]
name = "object"
version = "0.28.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "40bec70ba014595f99f7aa110b84331ffe1ee9aece7fe6f387cc7e3ecda4d456"
dependencies = [
"memchr",
]
[[package]]
name = "once_cell"
version = "1.10.0"
@ -1900,6 +1964,15 @@ dependencies = [
"hashbrown 0.12.0",
]
[[package]]
name = "os_type"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3df761f6470298359f84fcfb60d86db02acc22c251c37265c07a3d1057d2389"
dependencies = [
"regex",
]
[[package]]
name = "ouroboros"
version = "0.15.0"
@ -2293,6 +2366,8 @@ version = "1.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
@ -2361,6 +2436,12 @@ dependencies = [
"serde",
]
[[package]]
name = "rustc-demangle"
version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
[[package]]
name = "rustc_version"
version = "0.2.3"
@ -2958,6 +3039,15 @@ dependencies = [
"winapi",
]
[[package]]
name = "termcolor"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
dependencies = [
"winapi-util",
]
[[package]]
name = "textwrap"
version = "0.11.0"
@ -3689,6 +3779,15 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"

@ -30,6 +30,7 @@ log = "0.4.16"
opentelemetry = { version = "0.17.0", features = ["rt-tokio"] }
opentelemetry-jaeger = { version = "0.16.0", features = ["rt-tokio"] }
tracing-opentelemetry = "0.17.2"
human-panic = "1.0.3"
[dependencies.mediarepo-core]
path = "./mediarepo-core"

@ -55,6 +55,7 @@ enum SubCommand {
#[tokio::main]
async fn main() -> RepoResult<()> {
human_panic::setup_panic!();
let mut opt: Opt = Opt::from_args();
opt.repo = env::current_dir().unwrap().join(opt.repo);

@ -34,7 +34,7 @@ import {TagModule} from "../shared/tag/tag.module";
import {
DownloadDaemonDialogComponent
} from "./repositories-tab/download-daemon-dialog/download-daemon-dialog.component";
import {RepositoryModule} from "../shared/repository/repository/repository.module";
import {RepositoryModule} from "../shared/repository/repository.module";
import {MatToolbarModule} from "@angular/material/toolbar";
import {
RepositoryDetailsViewComponent

@ -6,7 +6,7 @@ import {ConfirmDialogComponent} from "../../../shared/app-common/confirm-dialog/
import {BusyIndicatorComponent} from "../../../shared/app-common/busy-indicator/busy-indicator.component";
import {
EditRepositoryDialogComponent
} from "../../../shared/repository/repository/edit-repository-dialog/edit-repository-dialog.component";
} from "../../../shared/repository/edit-repository-dialog/edit-repository-dialog.component";
@Component({
selector: "app-repository-card",

@ -47,13 +47,16 @@
{{this.databaseFileSize | async}}
</app-metadata-entry>
</div>
<div class="repository-charts">
<app-chart *ngIf="this.chartData"
[datasets]="this.chartData"
[labels]="this.chartLabels"
chartType="doughnut"
class="size-chart"
title="Sizes"></app-chart>
</div>
</div>
<div class="repository-charts" fxFlex="50%">
<app-chart *ngIf="this.chartData"
[datasets]="this.chartData"
[labels]="this.chartLabels"
chartType="doughnut"
class="size-chart"
title="Sizes"></app-chart>
<div fxFlex="50%">
<app-repository-maintenance class="repo-maintenance"></app-repository-maintenance>
</div>
</div>

@ -31,14 +31,17 @@
.stats-container {
margin-left: auto;
margin-right: auto;
display: block;
width: 50%;
}
}
.repository-charts {
margin-top: 4em;
margin-right: 2em;
height: 100%;
display: block;
.repository-charts {
margin-top: 4em;
margin-right: 2em;
height: calc(100% - 4em);;
width: 50%;
display: block;
}
}
.details-content {
@ -54,3 +57,7 @@
max-width: 500px;
margin: auto;
}
.repo-maintenance {
padding: 2em;
}

@ -7,7 +7,7 @@ import {StateService} from "../../../../services/state/state.service";
import {MatDialog, MatDialogRef} from "@angular/material/dialog";
import {
AddRepositoryDialogComponent
} from "../../../shared/repository/repository/add-repository-dialog/add-repository-dialog.component";
} from "../../../shared/repository/add-repository-dialog/add-repository-dialog.component";
import {BehaviorSubject} from "rxjs";
import {BusyDialogComponent} from "../../../shared/app-common/busy-dialog/busy-dialog.component";
import {DownloadDaemonDialogComponent} from "../download-daemon-dialog/download-daemon-dialog.component";

@ -1,8 +1,8 @@
import {Component, Inject, ViewChild} from "@angular/core";
import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog";
import {RepositoryFormComponent} from "../repository-form/repository-form.component";
import {RepositoryService} from "../../../../../services/repository/repository.service";
import {LoggingService} from "../../../../../services/logging/logging.service";
import {RepositoryService} from "../../../../services/repository/repository.service";
import {LoggingService} from "../../../../services/logging/logging.service";
@Component({
selector: "app-add-repository-dialog",

@ -1,9 +1,9 @@
import {Component, Inject, ViewChild} from "@angular/core";
import {RepositoryFormComponent} from "../repository-form/repository-form.component";
import {RepositoryService} from "../../../../../services/repository/repository.service";
import {LoggingService} from "../../../../../services/logging/logging.service";
import {RepositoryService} from "../../../../services/repository/repository.service";
import {LoggingService} from "../../../../services/logging/logging.service";
import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog";
import {Repository} from "../../../../../../api/models/Repository";
import {Repository} from "../../../../../api/models/Repository";
@Component({
selector: "app-edit-repository-dialog",

@ -1,7 +1,7 @@
import {Component, Input, OnInit, Output} from "@angular/core";
import {AbstractControl, FormControl, FormGroup, ValidationErrors, Validators} from "@angular/forms";
import {Repository} from "../../../../../../api/models/Repository";
import {RepositoryService} from "../../../../../services/repository/repository.service";
import {Repository} from "../../../../../api/models/Repository";
import {RepositoryService} from "../../../../services/repository/repository.service";
import {dialog} from "@tauri-apps/api";
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,68 @@
import {ChangeDetectionStrategy, ChangeDetectorRef, Component} 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 {
public jobState: { [Property in JobType]?: boolean } = {
CalculateSizes: false,
GenerateThumbnails: false,
};
constructor(
private changeDetector: ChangeDetectorRef,
private jobService: JobService,
private dialog: MatDialog,
private logger: LoggingService
) {
}
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.detectChanges();
});
this.changeDetector.detectChanges();
} 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.detectChanges();
await this.jobService.runJob(jobType);
} catch (err: any) {
this.logger.error(err);
} finally {
dialog.close();
this.changeDetector.detectChanges();
}
}
}
private async delay(ms: number) {
return new Promise((res, _) => setTimeout(
res,
ms
));
}
}

@ -11,17 +11,22 @@ import {MatInputModule} from "@angular/material/input";
import {ReactiveFormsModule} from "@angular/forms";
import {NgIconsModule} from "@ng-icons/core";
import {MatFolder} from "@ng-icons/material-icons/baseline";
import {RepositoryMaintenanceComponent} from "./repository-maintenance/repository-maintenance.component";
import {MatCardModule} from "@angular/material/card";
import {MatProgressBarModule} from "@angular/material/progress-bar";
@NgModule({
declarations: [
AddRepositoryDialogComponent,
EditRepositoryDialogComponent,
RepositoryFormComponent
RepositoryFormComponent,
RepositoryMaintenanceComponent
],
exports: [
AddRepositoryDialogComponent,
EditRepositoryDialogComponent,
RepositoryMaintenanceComponent,
],
imports: [
CommonModule,
@ -31,7 +36,9 @@ import {MatFolder} from "@ng-icons/material-icons/baseline";
MatSelectModule,
MatInputModule,
ReactiveFormsModule,
NgIconsModule.withIcons({ MatFolder })
NgIconsModule.withIcons({ MatFolder }),
MatCardModule,
MatProgressBarModule
]
})
export class RepositoryModule {
Loading…
Cancel
Save