diff --git a/mediarepo-ui/src-tauri/Cargo.lock b/mediarepo-ui/src-tauri/Cargo.lock index af2b101..edd4860 100644 --- a/mediarepo-ui/src-tauri/Cargo.lock +++ b/mediarepo-ui/src-tauri/Cargo.lock @@ -1489,8 +1489,8 @@ checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" [[package]] name = "mediarepo-api" -version = "0.24.1" -source = "git+https://github.com/Trivernis/mediarepo-api.git?rev=91d8182548bfdb19f2de9afd8c29d5c8ebd48993#91d8182548bfdb19f2de9afd8c29d5c8ebd48993" +version = "0.24.2" +source = "git+https://github.com/Trivernis/mediarepo-api.git?rev=076e9f344da034fc70c99cb1b9c4359374acc2ca#076e9f344da034fc70c99cb1b9c4359374acc2ca" dependencies = [ "async-trait", "bromine", diff --git a/mediarepo-ui/src-tauri/Cargo.toml b/mediarepo-ui/src-tauri/Cargo.toml index 7ebae95..10fe426 100644 --- a/mediarepo-ui/src-tauri/Cargo.toml +++ b/mediarepo-ui/src-tauri/Cargo.toml @@ -25,7 +25,7 @@ features = [ "env-filter" ] [dependencies.mediarepo-api] git = "https://github.com/Trivernis/mediarepo-api.git" -rev = "91d8182548bfdb19f2de9afd8c29d5c8ebd48993" +rev = "076e9f344da034fc70c99cb1b9c4359374acc2ca" features = [ "tauri-plugin" ] [features] diff --git a/mediarepo-ui/src/api/Api.ts b/mediarepo-ui/src/api/Api.ts index d0e6456..fde6655 100644 --- a/mediarepo-ui/src/api/Api.ts +++ b/mediarepo-ui/src/api/Api.ts @@ -18,6 +18,7 @@ import { ReadFileRequest, RemoveRepositoryRequest, ResolvePathsToFilesRequest, + RunJobRequest, SaveFileRequest, SelectRepositoryRequest, SetFrontendStateRequest, @@ -31,7 +32,7 @@ import { } from "./api-types/repo"; import {NamespaceData, TagData} from "./api-types/tags"; -export class MediarepApi { +export class MediarepoApi { public static async hasExecutable(): Promise { return this.invokePlugin(ApiFunction.HasExecutable); @@ -157,6 +158,10 @@ export class MediarepApi { return this.invokePlugin(ApiFunction.SetFrontendState, request); } + public static async runJob(request: RunJobRequest): Promise { + return this.invokePlugin(ApiFunction.RunJob, request); + } + private static async invokePlugin(fn: ApiFunction, args?: any): Promise { return invoke(`plugin:mediarepo|${fn}`, args); } diff --git a/mediarepo-ui/src/api/api-types/functions.ts b/mediarepo-ui/src/api/api-types/functions.ts index f26d9bf..3884d6c 100644 --- a/mediarepo-ui/src/api/api-types/functions.ts +++ b/mediarepo-ui/src/api/api-types/functions.ts @@ -35,4 +35,6 @@ export enum ApiFunction { // state GetFrontendState = "get_frontend_state", SetFrontendState = "set_frontend_state", + // jobs + RunJob = "run_job", } diff --git a/mediarepo-ui/src/api/api-types/job.ts b/mediarepo-ui/src/api/api-types/job.ts new file mode 100644 index 0000000..c61458a --- /dev/null +++ b/mediarepo-ui/src/api/api-types/job.ts @@ -0,0 +1,3 @@ +export type JobType = "MigrateContentDescriptors" + | "CalculateSizes" + | "CheckIntegrity"; diff --git a/mediarepo-ui/src/api/api-types/requests.ts b/mediarepo-ui/src/api/api-types/requests.ts index 3015171..8c64a91 100644 --- a/mediarepo-ui/src/api/api-types/requests.ts +++ b/mediarepo-ui/src/api/api-types/requests.ts @@ -1,5 +1,6 @@ import {FileOsMetadata, FilterExpression, SortKey} from "./files"; import {RepositoryData, SizeType} from "./repo"; +import {JobType} from "./job"; type NameIdentifierRequest = { name: string @@ -92,3 +93,7 @@ type AddFileOptions = { export type SetFrontendStateRequest = { state: string }; + +export type RunJobRequest = { + jobType: JobType, +} diff --git a/mediarepo-ui/src/app/components/core/repositories-tab/repositories-tab.component.html b/mediarepo-ui/src/app/components/core/repositories-tab/repositories-tab.component.html index 67204d1..46d3d76 100644 --- a/mediarepo-ui/src/app/components/core/repositories-tab/repositories-tab.component.html +++ b/mediarepo-ui/src/app/components/core/repositories-tab/repositories-tab.component.html @@ -4,7 +4,7 @@
- +
diff --git a/mediarepo-ui/src/app/components/core/repositories-tab/repositories-tab.component.ts b/mediarepo-ui/src/app/components/core/repositories-tab/repositories-tab.component.ts index 7fc543c..bf80d01 100644 --- a/mediarepo-ui/src/app/components/core/repositories-tab/repositories-tab.component.ts +++ b/mediarepo-ui/src/app/components/core/repositories-tab/repositories-tab.component.ts @@ -3,13 +3,24 @@ import {Repository} from "../../../../api/models/Repository"; import { RepositoryService } from "../../../services/repository/repository.service"; -import {MatDialog} from "@angular/material/dialog"; +import {MatDialog, MatDialogRef} from "@angular/material/dialog"; import { DownloadDaemonDialogComponent } from "./download-daemon-dialog/download-daemon-dialog.component"; import { AddRepositoryDialogComponent } from "../../shared/repository/repository/add-repository-dialog/add-repository-dialog.component"; +import { + ErrorBrokerService +} from "../../../services/error-broker/error-broker.service"; +import {BehaviorSubject} from "rxjs"; +import { + BusyDialogComponent +} from "../../shared/app-common/busy-dialog/busy-dialog.component"; +import {JobService} from "../../../services/job/job.service"; +import {StateService} from "../../../services/state/state.service"; + +type BusyDialogContext = { message: BehaviorSubject, dialog: MatDialogRef }; @Component({ selector: "app-repositories-tab", @@ -21,7 +32,10 @@ export class RepositoriesTabComponent implements OnInit, AfterViewInit { public selectedRepository?: Repository; constructor( + private errorBroker: ErrorBrokerService, private repoService: RepositoryService, + private jobService: JobService, + private stateService: StateService, public dialog: MatDialog ) { } @@ -32,13 +46,95 @@ export class RepositoriesTabComponent implements OnInit, AfterViewInit { this.repositories = repos; } }); - this.repoService.selectedRepository.subscribe(repo => this.selectedRepository = repo); + this.repoService.selectedRepository.subscribe( + repo => this.selectedRepository = repo); } public async ngAfterViewInit() { await this.checkAndPromptDaemonExecutable(); } + public async startDaemonAndSelectRepository(repository: Repository) { + try { + let dialogContext = this.openStartupDialog(repository); + let daemonRunning = await this.repoService.checkDaemonRunning( + repository.path!); + if (!daemonRunning) { + dialogContext.message.next("Starting repository daemon..."); + await this.repoService.startDaemon(repository.path!); + + await new Promise((res, _) => { + setTimeout(res, 2000); // wait for the daemon to start + }); + } + await this.selectRepository(repository, dialogContext); + } catch (err) { + this.errorBroker.showError(err); + } + } + + public async selectRepository(repository: Repository, dialogContext?: BusyDialogContext) { + dialogContext = dialogContext ?? this.openStartupDialog(repository); + try { + dialogContext.message.next("Opening repository..."); + await this.repoService.setRepository(repository); + await this.runRepositoryStartupTasks(dialogContext); + dialogContext.message.next("Restoring previous tabs..."); + await this.repoService.loadRepositories(); + await this.stateService.loadState(); + dialogContext.dialog.close(true); + } catch (err) { + this.errorBroker.showError(err); + dialogContext.message.next( + "Failed to open repository: " + err.toString()); + await this.forceCloseRepository(); + setTimeout(() => dialogContext!.dialog.close(true), 1000); + } + } + + private async forceCloseRepository() { + try { + await this.repoService.closeSelectedRepository(); + } catch { + } + try { + await this.repoService.disconnectSelectedRepository(); + } catch { + } + } + + private async runRepositoryStartupTasks(dialogContext: BusyDialogContext): Promise { + dialogContext.message.next( + "Migrating content descriptors to new format..."); + await this.jobService.runJob("MigrateContentDescriptors"); + dialogContext.message.next("Calculating repository sizes..."); + await this.jobService.runJob("CalculateSizes"); + dialogContext.message.next("Checking integrity..."); + await this.jobService.runJob("CheckIntegrity"); + dialogContext.message.next("Finished repository startup"); + } + + private openStartupDialog(repository: Repository): BusyDialogContext { + let dialogMessage = new BehaviorSubject( + "Opening repository..."); + let dialog = this.dialog.open(BusyDialogComponent, { + data: { + title: `Opening repository ${repository.name}`, + message: dialogMessage, + allowCancel: true, + }, disableClose: true, + minWidth: "30%", + minHeight: "30%", + }); + dialog.afterClosed().subscribe(async (result) => { + if (!result) { + await this.forceCloseRepository(); + } + }); + + return {message: dialogMessage, dialog}; + } + public openAddRepositoryDialog() { this.dialog.open(AddRepositoryDialogComponent, { disableClose: true, @@ -49,13 +145,23 @@ export class RepositoriesTabComponent implements OnInit, AfterViewInit { private async checkAndPromptDaemonExecutable() { if (!await this.repoService.checkDameonConfigured()) { - const result = await this.dialog.open(DownloadDaemonDialogComponent, { - disableClose: true, - }).afterClosed().toPromise(); + const result = await this.dialog.open(DownloadDaemonDialogComponent, + { + disableClose: true, + }).afterClosed().toPromise(); if (result) { // recursion avoidance - setTimeout(async () => await this.checkAndPromptDaemonExecutable(), 0); + setTimeout( + async () => await this.checkAndPromptDaemonExecutable(), 0); } } } + + public async onOpenRepository(repository: Repository) { + if (!repository.local) { + await this.selectRepository(repository); + } else { + await this.startDaemonAndSelectRepository(repository); + } + } } diff --git a/mediarepo-ui/src/app/components/core/repositories-tab/repository-card/repository-card.component.html b/mediarepo-ui/src/app/components/core/repositories-tab/repository-card/repository-card.component.html index 04fff0f..eeaf005 100644 --- a/mediarepo-ui/src/app/components/core/repositories-tab/repository-card/repository-card.component.html +++ b/mediarepo-ui/src/app/components/core/repositories-tab/repository-card/repository-card.component.html @@ -9,11 +9,11 @@

{{repository.address}}

- - diff --git a/mediarepo-ui/src/app/components/core/repositories-tab/repository-card/repository-card.component.ts b/mediarepo-ui/src/app/components/core/repositories-tab/repository-card/repository-card.component.ts index d364753..bf5acd8 100644 --- a/mediarepo-ui/src/app/components/core/repositories-tab/repository-card/repository-card.component.ts +++ b/mediarepo-ui/src/app/components/core/repositories-tab/repository-card/repository-card.component.ts @@ -1,11 +1,15 @@ -import {Component, Input, OnDestroy, OnInit, ViewChild} from "@angular/core"; +import { + Component, EventEmitter, + Input, + OnDestroy, + OnInit, + Output, + ViewChild +} from "@angular/core"; import {Repository} from "../../../../../api/models/Repository"; import { RepositoryService } from "../../../../services/repository/repository.service"; -import { - ErrorBrokerService -} from "../../../../services/error-broker/error-broker.service"; import {MatDialog} from "@angular/material/dialog"; import { ConfirmDialogComponent @@ -25,6 +29,8 @@ import { export class RepositoryCardComponent implements OnInit, OnDestroy { @Input() repository!: Repository; + @Output() openEvent = new EventEmitter(); + @ViewChild(BusyIndicatorComponent) busyIndicator!: BusyIndicatorComponent; public daemonRunning: boolean = false; @@ -33,7 +39,6 @@ export class RepositoryCardComponent implements OnInit, OnDestroy { constructor( public repoService: RepositoryService, - private errorBroker: ErrorBrokerService, public dialog: MatDialog) { } @@ -118,31 +123,6 @@ export class RepositoryCardComponent implements OnInit, OnDestroy { } } - public async startDaemonAndSelectRepository() { - try { - if (!this.daemonRunning) { - await this.repoService.startDaemon(this.repository.path!); - this.daemonRunning = true; - await new Promise((res, _) => { - setTimeout(res, 2000); // wait for the daemon to start - }); - } - await this.selectRepository(); - } catch (err) { - this.errorBroker.showError(err); - } - } - - public async selectRepository() { - this.busyIndicator.setBusy(true); - try { - await this.repoService.setRepository(this.repository); - } catch (err) { - this.errorBroker.showError(err); - } - this.busyIndicator.setBusy(false); - } - async checkRemoteRepositoryStatus() { this.daemonRunning = await this.repoService.checkDaemonRunning( this.repository.address!); diff --git a/mediarepo-ui/src/app/components/shared/app-common/app-common.module.ts b/mediarepo-ui/src/app/components/shared/app-common/app-common.module.ts index e05c03d..b133e42 100644 --- a/mediarepo-ui/src/app/components/shared/app-common/app-common.module.ts +++ b/mediarepo-ui/src/app/components/shared/app-common/app-common.module.ts @@ -21,6 +21,7 @@ import { import { MetadataEntryComponent } from "./metadata-entry/metadata-entry.component"; +import { BusyDialogComponent } from './busy-dialog/busy-dialog.component'; @NgModule({ @@ -31,6 +32,7 @@ import { ContentAwareImageComponent, InputReceiverDirective, MetadataEntryComponent, + BusyDialogComponent, ], exports: [ ConfirmDialogComponent, diff --git a/mediarepo-ui/src/app/components/shared/app-common/busy-dialog/busy-dialog.component.html b/mediarepo-ui/src/app/components/shared/app-common/busy-dialog/busy-dialog.component.html new file mode 100644 index 0000000..af11caf --- /dev/null +++ b/mediarepo-ui/src/app/components/shared/app-common/busy-dialog/busy-dialog.component.html @@ -0,0 +1,12 @@ +

+ {{title}} +

+
+ + {{message}} +
+
+ +
diff --git a/mediarepo-ui/src/app/components/shared/app-common/busy-dialog/busy-dialog.component.scss b/mediarepo-ui/src/app/components/shared/app-common/busy-dialog/busy-dialog.component.scss new file mode 100644 index 0000000..6c4611e --- /dev/null +++ b/mediarepo-ui/src/app/components/shared/app-common/busy-dialog/busy-dialog.component.scss @@ -0,0 +1,17 @@ +mat-progress-spinner { + margin: auto; + padding-bottom: 1em; +} + +.title, .content { + text-align: center; +} + +.busy-dialog-actions { + display: block; + + button { + float: right; + margin-left: 1em; + } +} diff --git a/mediarepo-ui/src/app/components/shared/app-common/busy-dialog/busy-dialog.component.spec.ts b/mediarepo-ui/src/app/components/shared/app-common/busy-dialog/busy-dialog.component.spec.ts new file mode 100644 index 0000000..c753f30 --- /dev/null +++ b/mediarepo-ui/src/app/components/shared/app-common/busy-dialog/busy-dialog.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { BusyDialogComponent } from './busy-dialog.component'; + +describe('BusyDialogComponent', () => { + let component: BusyDialogComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ BusyDialogComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(BusyDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/mediarepo-ui/src/app/components/shared/app-common/busy-dialog/busy-dialog.component.ts b/mediarepo-ui/src/app/components/shared/app-common/busy-dialog/busy-dialog.component.ts new file mode 100644 index 0000000..03fffc4 --- /dev/null +++ b/mediarepo-ui/src/app/components/shared/app-common/busy-dialog/busy-dialog.component.ts @@ -0,0 +1,27 @@ +import {Component, Inject} from "@angular/core"; +import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog"; +import {BehaviorSubject} from "rxjs"; + +export type BusyDialogData = { + title: string, + message: BehaviorSubject, + allowCancel?: boolean, +} + +@Component({ + selector: "app-busy-dialog", + templateUrl: "./busy-dialog.component.html", + styleUrls: ["./busy-dialog.component.scss"] +}) +export class BusyDialogComponent { + + public title: string; + public message?: string; + public allowCancel: boolean; + + constructor(public dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) data: BusyDialogData) { + this.title = data.title; + data.message.subscribe(m => this.message = m); + this.allowCancel = data.allowCancel ?? false; + } +} diff --git a/mediarepo-ui/src/app/components/shared/sidebar/file-search/file-search.component.html b/mediarepo-ui/src/app/components/shared/sidebar/file-search/file-search.component.html index 8183620..f7b6335 100644 --- a/mediarepo-ui/src/app/components/shared/sidebar/file-search/file-search.component.html +++ b/mediarepo-ui/src/app/components/shared/sidebar/file-search/file-search.component.html @@ -32,14 +32,16 @@
- -
- -
-
- + + + +
+ +
+
+
diff --git a/mediarepo-ui/src/app/components/shared/sidebar/file-search/file-search.component.scss b/mediarepo-ui/src/app/components/shared/sidebar/file-search/file-search.component.scss index 3d055e9..1a0ebcb 100644 --- a/mediarepo-ui/src/app/components/shared/sidebar/file-search/file-search.component.scss +++ b/mediarepo-ui/src/app/components/shared/sidebar/file-search/file-search.component.scss @@ -123,12 +123,3 @@ mat-divider { .file-tag-list { position: relative; } - -app-busy-indicator { - position: absolute; - top: 0; - left: 0; - height: 100%; - width: 100%; - z-index: 99; -} diff --git a/mediarepo-ui/src/app/models/AppState.ts b/mediarepo-ui/src/app/models/AppState.ts index 1a30ef9..5d47a0d 100644 --- a/mediarepo-ui/src/app/models/AppState.ts +++ b/mediarepo-ui/src/app/models/AppState.ts @@ -8,6 +8,7 @@ export class AppState { private tabIdCounter = 0; public tabs = new BehaviorSubject([]); public selectedTab = new BehaviorSubject(undefined); + public repoName: string | undefined; private readonly fileService: FileService @@ -36,6 +37,7 @@ export class AppState { appState.tabIdCounter = state.tabIdCounter; appState.selectedTab.next(state.selectedTab); + appState.repoName = state.repoName; return appState; } @@ -43,6 +45,7 @@ export class AppState { public serializeJson(): string { const tabDTOs = this.tabs.value.map(tab => tab.getDTO()); return JSON.stringify({ + repoName: this.repoName, tabs: tabDTOs, tabIdCounter: this.tabIdCounter, selectedTab: this.selectedTab.value, diff --git a/mediarepo-ui/src/app/services/file/file.service.ts b/mediarepo-ui/src/app/services/file/file.service.ts index e371646..06dceac 100644 --- a/mediarepo-ui/src/app/services/file/file.service.ts +++ b/mediarepo-ui/src/app/services/file/file.service.ts @@ -3,7 +3,7 @@ import {File} from "../../../api/models/File"; import {DomSanitizer, SafeResourceUrl} from "@angular/platform-browser"; import {SortKey} from "../../models/SortKey"; import {GenericFilter} from "../../models/GenericFilter"; -import {MediarepApi} from "../../../api/Api"; +import {MediarepoApi} from "../../../api/Api"; import {mapMany, mapNew} from "../../../api/models/adaptors"; import {FileMetadata} from "../../../api/api-types/files"; @@ -19,20 +19,20 @@ export class FileService { } public async getAllFiles(): Promise { - return MediarepApi.getAllFiles().then(mapMany(mapNew(File))); + return MediarepoApi.getAllFiles().then(mapMany(mapNew(File))); } public async findFiles(filters: GenericFilter[], sortBy: SortKey[]): Promise { let backendFilters = filters.map(f => f.toBackendType()); - return MediarepApi.findFiles({filters: backendFilters, sortBy: sortBy.map(k => k.toBackendType())}).then(mapMany(mapNew(File))); + return MediarepoApi.findFiles({filters: backendFilters, sortBy: sortBy.map(k => k.toBackendType())}).then(mapMany(mapNew(File))); } public async getFileMetadata(id: number): Promise { - return MediarepApi.getFileMetadata({id}); + return MediarepoApi.getFileMetadata({id}); } public async updateFileName(id: number, name: string): Promise { - return MediarepApi.updateFileName({id, name}); + return MediarepoApi.updateFileName({id, name}); } /** @@ -64,7 +64,7 @@ export class FileService { * @returns {Promise} */ public async saveFile(file: File, targetPath: string) { - await MediarepApi.saveFileLocally({id: file.id, path: targetPath}); + await MediarepoApi.saveFileLocally({id: file.id, path: targetPath}); } /** @@ -73,7 +73,7 @@ export class FileService { * @returns {Promise} */ public async deleteThumbnails(file: File) { - await MediarepApi.deleteThumbnails({id: file.id}); + await MediarepoApi.deleteThumbnails({id: file.id}); } /** @@ -82,7 +82,7 @@ export class FileService { * @returns {Promise} */ public async readFile(file: File): Promise { - const data = await MediarepApi.readFile({mimeType: file.mimeType, hash: file.cd}); + const data = await MediarepoApi.readFile({mimeType: file.mimeType, hash: file.cd}); const blob = new Blob([new Uint8Array(data)], {type: file.mimeType}); const url = URL?.createObjectURL(blob); return this.sanitizer.bypassSecurityTrustResourceUrl(url); diff --git a/mediarepo-ui/src/app/services/import/import.service.ts b/mediarepo-ui/src/app/services/import/import.service.ts index 1fe0c84..c106ebe 100644 --- a/mediarepo-ui/src/app/services/import/import.service.ts +++ b/mediarepo-ui/src/app/services/import/import.service.ts @@ -1,7 +1,7 @@ import {Injectable} from "@angular/core"; import {AddFileOptions} from "../../models/AddFileOptions"; import {File} from "../../../api/models/File"; -import {MediarepApi} from "../../../api/Api"; +import {MediarepoApi} from "../../../api/Api"; import {mapNew,} from "../../../api/models/adaptors"; import {FileOsMetadata} from "../../../api/api-types/files"; @@ -19,7 +19,7 @@ export class ImportService { * @returns {Promise} */ public async resolvePathsToFiles(paths: string[]): Promise { - return MediarepApi.resolvePathsToFiles({paths}); + return MediarepoApi.resolvePathsToFiles({paths}); } /** @@ -29,6 +29,6 @@ export class ImportService { * @returns {Promise} */ public async addLocalFile(metadata: FileOsMetadata, options: AddFileOptions): Promise { - return MediarepApi.addLocalFile({metadata, options}).then(mapNew(File)); + return MediarepoApi.addLocalFile({metadata, options}).then(mapNew(File)); } } diff --git a/mediarepo-ui/src/app/services/job/job.service.spec.ts b/mediarepo-ui/src/app/services/job/job.service.spec.ts new file mode 100644 index 0000000..2e71d9e --- /dev/null +++ b/mediarepo-ui/src/app/services/job/job.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { JobService } from './job.service'; + +describe('JobService', () => { + let service: JobService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(JobService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/mediarepo-ui/src/app/services/job/job.service.ts b/mediarepo-ui/src/app/services/job/job.service.ts new file mode 100644 index 0000000..9642eb3 --- /dev/null +++ b/mediarepo-ui/src/app/services/job/job.service.ts @@ -0,0 +1,16 @@ +import {Injectable} from "@angular/core"; +import {MediarepoApi} from "../../../api/Api"; +import {JobType} from "../../../api/api-types/job"; + +@Injectable({ + providedIn: "root" +}) +export class JobService { + + constructor() { + } + + public async runJob(jobType: JobType): Promise { + return MediarepoApi.runJob({jobType}); + } +} diff --git a/mediarepo-ui/src/app/services/repository/repository.service.ts b/mediarepo-ui/src/app/services/repository/repository.service.ts index 81ca2f2..f47fc77 100644 --- a/mediarepo-ui/src/app/services/repository/repository.service.ts +++ b/mediarepo-ui/src/app/services/repository/repository.service.ts @@ -5,7 +5,7 @@ import {listen} from "@tauri-apps/api/event"; import {Info} from "../../models/Info"; import {ErrorBrokerService} from "../error-broker/error-broker.service"; import {RepositoryMetadata} from "../../models/RepositoryMetadata"; -import {MediarepApi} from "../../../api/Api"; +import {MediarepoApi} from "../../../api/Api"; import {mapMany, mapNew, mapOptional,} from "../../../api/models/adaptors"; import {SizeMetadata, SizeType} from "../../../api/api-types/repo"; @@ -34,7 +34,7 @@ export class RepositoryService { * @returns {Promise} */ public async checkDameonConfigured(): Promise { - return MediarepApi.hasExecutable(); + return MediarepoApi.hasExecutable(); } /** @@ -43,7 +43,7 @@ export class RepositoryService { */ public async loadRepositories() { await this.loadSelectedRepository(); - let repos = await MediarepApi.getRepositories().then(mapMany(mapNew(Repository))); + let repos = await MediarepoApi.getRepositories().then(mapMany(mapNew(Repository))); this.repositories.next(repos); } @@ -67,10 +67,8 @@ export class RepositoryService { } catch (err) { console.warn(err); } - } - await MediarepApi.selectRepository({name: repo.name}); - await this.loadRepositories(); + await MediarepoApi.selectRepository({name: repo.name}); } /** @@ -78,7 +76,7 @@ export class RepositoryService { * @returns {Promise} */ public async disconnectSelectedRepository() { - await MediarepApi.disconnectRepository(); + await MediarepoApi.disconnectRepository(); await this.loadRepositories(); } @@ -87,7 +85,7 @@ export class RepositoryService { * @returns {Promise} */ public async closeSelectedRepository() { - await MediarepApi.closeLocalRepository(); + await MediarepoApi.closeLocalRepository(); await this.loadRepositories(); } @@ -100,7 +98,7 @@ export class RepositoryService { * @returns {Promise} */ public async addRepository(name: string, path: string | undefined, address: string | undefined, local: boolean) { - let repos = await MediarepApi.addRepository({name, path, address, local}).then(mapMany(mapNew(Repository))); + let repos = await MediarepoApi.addRepository({name, path, address, local}).then(mapMany(mapNew(Repository))); this.repositories.next(repos); } @@ -110,7 +108,7 @@ export class RepositoryService { * @returns {Promise} */ public async checkDaemonRunning(address: string): Promise { - return MediarepApi.checkDaemonRunning({address}); + return MediarepoApi.checkDaemonRunning({address}); } /** @@ -119,7 +117,7 @@ export class RepositoryService { * @returns {Promise} */ public async checkLocalRepositoryExists(path: string): Promise { - return await MediarepApi.checkLocalRepositoryExists({path}); + return await MediarepoApi.checkLocalRepositoryExists({path}); } /** @@ -128,7 +126,7 @@ export class RepositoryService { * @returns {Promise} */ public async removeRepository(name: string): Promise { - await MediarepApi.removeRepository({name}); + await MediarepoApi.removeRepository({name}); await this.loadRepositories(); } @@ -138,7 +136,7 @@ export class RepositoryService { * @returns {Promise} */ public async deleteRepository(name: string): Promise { - await MediarepApi.deleteRepository({name}); + await MediarepoApi.deleteRepository({name}); await this.removeRepository(name); } @@ -148,7 +146,7 @@ export class RepositoryService { * @returns {Promise} */ public async startDaemon(repoPath: string): Promise { - return MediarepApi.startDaemon({repoPath}); + return MediarepoApi.startDaemon({repoPath}); } /** @@ -157,7 +155,7 @@ export class RepositoryService { * @returns {Promise} */ public async initRepository(repoPath: string): Promise { - return MediarepApi.initRepository({repoPath}); + return MediarepoApi.initRepository({repoPath}); } /** @@ -165,7 +163,7 @@ export class RepositoryService { * @returns {Promise} */ public async getRepositoryMetadata(): Promise { - return MediarepApi.getRepositoryMetadata(); + return MediarepoApi.getRepositoryMetadata(); } /** @@ -174,11 +172,11 @@ export class RepositoryService { * @param sizeType */ public async getSize(sizeType: SizeType): Promise { - return MediarepApi.getSize({sizeType}); + return MediarepoApi.getSize({sizeType}); } async loadSelectedRepository() { - let active_repo = await MediarepApi.getActiveRepository().then(mapOptional(mapNew(Repository))); + let active_repo = await MediarepoApi.getActiveRepository().then(mapOptional(mapNew(Repository))); this.selectedRepository.next(active_repo); } } diff --git a/mediarepo-ui/src/app/services/state/state.service.ts b/mediarepo-ui/src/app/services/state/state.service.ts index b4475a6..e1ee72a 100644 --- a/mediarepo-ui/src/app/services/state/state.service.ts +++ b/mediarepo-ui/src/app/services/state/state.service.ts @@ -5,7 +5,7 @@ import {FileService} from "../file/file.service"; import {RepositoryService} from "../repository/repository.service"; import {TabState} from "../../models/TabState"; import {debounceTime} from "rxjs/operators"; -import {MediarepApi} from "../../../api/Api"; +import {MediarepoApi} from "../../../api/Api"; @Injectable({ providedIn: "root" @@ -21,7 +21,7 @@ export class StateService { constructor(private fileService: FileService, private repoService: RepositoryService) { this.state = new BehaviorSubject(new AppState(fileService)); this.repoService.selectedRepository.subscribe(async (repo) => { - if (repo) { + if (repo && (!this.state.value.repoName || this.state.value.repoName !== repo.name)) { await this.loadState(); } else { const state = new AppState(this.fileService); @@ -38,7 +38,7 @@ export class StateService { * @returns {Promise} */ public async loadState() { - let stateString = await MediarepApi.getFrontendState(); + let stateString = await MediarepoApi.getFrontendState(); let state; if (stateString) { @@ -46,6 +46,10 @@ export class StateService { } else { state = new AppState(this.fileService); } + let selectedRepo = this.repoService.selectedRepository.value; + if (selectedRepo) { + state.repoName = selectedRepo.name; + } this.subscribeToState(state); this.state.next(state); } @@ -75,6 +79,8 @@ export class StateService { * @returns {Promise} */ public async saveState(): Promise { - await MediarepApi.setFrontendState({state: this.state.value.serializeJson()}); + if (this.repoService.selectedRepository.value) { + await MediarepoApi.setFrontendState({state: this.state.value.serializeJson()}); + } } } diff --git a/mediarepo-ui/src/app/services/tag/tag.service.ts b/mediarepo-ui/src/app/services/tag/tag.service.ts index 1122904..6722383 100644 --- a/mediarepo-ui/src/app/services/tag/tag.service.ts +++ b/mediarepo-ui/src/app/services/tag/tag.service.ts @@ -3,7 +3,7 @@ import {Tag} from "../../../api/models/Tag"; import {BehaviorSubject} from "rxjs"; import {Namespace} from "../../../api/models/Namespace"; import {mapMany, mapNew} from "../../../api/models/adaptors"; -import {MediarepApi} from "../../../api/Api"; +import {MediarepoApi} from "../../../api/Api"; @Injectable({ providedIn: "root" @@ -17,28 +17,28 @@ export class TagService { } public async loadTags() { - const tags = await MediarepApi.getAllTags().then(mapMany(mapNew(Tag))); + const tags = await MediarepoApi.getAllTags().then(mapMany(mapNew(Tag))); this.tags.next(tags); } public async loadNamespaces() { - const namespaces = await MediarepApi.getAllNamespaces().then(mapMany(mapNew(Namespace))); + const namespaces = await MediarepoApi.getAllNamespaces().then(mapMany(mapNew(Namespace))); this.namespaces.next(namespaces); } public async getTagsForFiles(cds: string[]): Promise { let tags: Tag[] = []; if (cds.length > 0) { - tags = await MediarepApi.getTagsForFiles({cds}).then(mapMany(mapNew(Tag))); + tags = await MediarepoApi.getTagsForFiles({cds}).then(mapMany(mapNew(Tag))); } return tags; } public async createTags(tags: string[]): Promise { - return MediarepApi.createTags({tags}).then(mapMany(mapNew(Tag))); + return MediarepoApi.createTags({tags}).then(mapMany(mapNew(Tag))); } public async changeFileTags(fileId: number, addedTags: number[], removedTags: number[]): Promise { - return MediarepApi.changeFileTags({id: fileId, addedTags, removedTags}).then(mapMany(mapNew(Tag))); + return MediarepoApi.changeFileTags({id: fileId, addedTags, removedTags}).then(mapMany(mapNew(Tag))); } }