Add jobs and open dialog

Signed-off-by: trivernis <trivernis@protonmail.com>
pull/4/head
trivernis 2 years ago
parent d48cff688f
commit 3d5fcc8169

@ -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",

@ -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]

@ -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<boolean> {
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<void> {
return this.invokePlugin(ApiFunction.RunJob, request);
}
private static async invokePlugin<T>(fn: ApiFunction, args?: any): Promise<T> {
return invoke<T>(`plugin:mediarepo|${fn}`, args);
}

@ -35,4 +35,6 @@ export enum ApiFunction {
// state
GetFrontendState = "get_frontend_state",
SetFrontendState = "set_frontend_state",
// jobs
RunJob = "run_job",
}

@ -0,0 +1,3 @@
export type JobType = "MigrateContentDescriptors"
| "CalculateSizes"
| "CheckIntegrity";

@ -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,
}

@ -4,7 +4,7 @@
</div>
<div class="repository-list">
<div *ngFor="let repository of repositories" class="repository-container">
<app-repository-card [repository]="repository"></app-repository-card>
<app-repository-card [repository]="repository" (openEvent)="this.onOpenRepository($event)"></app-repository-card>
</div>
</div>
</div>

@ -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<string>, dialog: MatDialogRef<BusyDialogComponent> };
@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<void> {
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<string>(
"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);
}
}
}

@ -9,11 +9,11 @@
<p *ngIf="!repository.local" class="repository-address">{{repository.address}}</p>
</mat-card-content>
<mat-action-list>
<button (click)="startDaemonAndSelectRepository()" *ngIf="!this.isSelectedRepository() && repository.local"
<button (click)="this.openEvent.next(repository)" *ngIf="!this.isSelectedRepository() && repository.local"
color="primary"
mat-flat-button>Open
</button>
<button (click)="selectRepository()" *ngIf="!this.isSelectedRepository() && !repository.local"
<button (click)="this.openEvent.next(repository)" *ngIf="!this.isSelectedRepository() && !repository.local"
[disabled]="!this.daemonRunning"
color="primary" mat-flat-button>Connect
</button>

@ -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<Repository>();
@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!);

@ -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,

@ -0,0 +1,12 @@
<h1 mat-dialog-title class="title">
{{title}}
</h1>
<div class="content" mat-dialog-content>
<mat-progress-spinner mode="indeterminate" color="primary"></mat-progress-spinner>
{{message}}
</div>
<div mat-dialog-actions *ngIf="this.allowCancel" class="busy-dialog-actions">
<button mat-flat-button (click)="this.dialogRef.close(false)">
Cancel
</button>
</div>

@ -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;
}
}

@ -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<BusyDialogComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ BusyDialogComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(BusyDialogComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

@ -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<string>,
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<BusyDialogComponent>, @Inject(MAT_DIALOG_DATA) data: BusyDialogData) {
this.title = data.title;
data.message.subscribe(m => this.message = m);
this.allowCancel = data.allowCancel ?? false;
}
}

@ -32,14 +32,16 @@
</div>
<div class="file-tag-list" fxFlex fxFlexAlign="start" fxFlexFill>
<cdk-virtual-scroll-viewport itemSize="50" maxBufferPx="4000" minBufferPx="500">
<div (click)="addSearchTag(tag.getNormalizedOutput())"
(contextmenu)="contextMenuTag = tag; contextMenu.onContextMenu($event)"
*cdkVirtualFor="let tag of contextTags" class="selectable-tag">
<app-tag-item [tag]="tag"></app-tag-item>
</div>
</cdk-virtual-scroll-viewport>
<app-busy-indicator [busy]="this.tagsLoading" [blurBackground]="true" [darkenBackground]="false"></app-busy-indicator>
<app-busy-indicator [busy]="this.tagsLoading" [blurBackground]="true" [darkenBackground]="false">
<cdk-virtual-scroll-viewport itemSize="50" maxBufferPx="4000" minBufferPx="500">
<div (click)="addSearchTag(tag.getNormalizedOutput())"
(contextmenu)="contextMenuTag = tag; contextMenu.onContextMenu($event)"
*cdkVirtualFor="let tag of contextTags" class="selectable-tag">
<app-tag-item [tag]="tag"></app-tag-item>
</div>
</cdk-virtual-scroll-viewport>
</app-busy-indicator>
</div>
</div>

@ -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;
}

@ -8,6 +8,7 @@ export class AppState {
private tabIdCounter = 0;
public tabs = new BehaviorSubject<TabState[]>([]);
public selectedTab = new BehaviorSubject<number | undefined>(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,

@ -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<File[]> {
return MediarepApi.getAllFiles().then(mapMany(mapNew(File)));
return MediarepoApi.getAllFiles().then(mapMany(mapNew(File)));
}
public async findFiles(filters: GenericFilter[], sortBy: SortKey[]): Promise<File[]> {
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<FileMetadata> {
return MediarepApi.getFileMetadata({id});
return MediarepoApi.getFileMetadata({id});
}
public async updateFileName(id: number, name: string): Promise<FileMetadata> {
return MediarepApi.updateFileName({id, name});
return MediarepoApi.updateFileName({id, name});
}
/**
@ -64,7 +64,7 @@ export class FileService {
* @returns {Promise<void>}
*/
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<void>}
*/
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<SafeResourceUrl>}
*/
public async readFile(file: File): Promise<SafeResourceUrl> {
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);

@ -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<FileOsMetadata[]>}
*/
public async resolvePathsToFiles(paths: string[]): Promise<FileOsMetadata[]> {
return MediarepApi.resolvePathsToFiles({paths});
return MediarepoApi.resolvePathsToFiles({paths});
}
/**
@ -29,6 +29,6 @@ export class ImportService {
* @returns {Promise<File>}
*/
public async addLocalFile(metadata: FileOsMetadata, options: AddFileOptions): Promise<File> {
return MediarepApi.addLocalFile({metadata, options}).then(mapNew(File));
return MediarepoApi.addLocalFile({metadata, options}).then(mapNew(File));
}
}

@ -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();
});
});

@ -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<void> {
return MediarepoApi.runJob({jobType});
}
}

@ -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<boolean>}
*/
public async checkDameonConfigured(): Promise<boolean> {
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<void>}
*/
public async disconnectSelectedRepository() {
await MediarepApi.disconnectRepository();
await MediarepoApi.disconnectRepository();
await this.loadRepositories();
}
@ -87,7 +85,7 @@ export class RepositoryService {
* @returns {Promise<void>}
*/
public async closeSelectedRepository() {
await MediarepApi.closeLocalRepository();
await MediarepoApi.closeLocalRepository();
await this.loadRepositories();
}
@ -100,7 +98,7 @@ export class RepositoryService {
* @returns {Promise<void>}
*/
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<boolean>}
*/
public async checkDaemonRunning(address: string): Promise<boolean> {
return MediarepApi.checkDaemonRunning({address});
return MediarepoApi.checkDaemonRunning({address});
}
/**
@ -119,7 +117,7 @@ export class RepositoryService {
* @returns {Promise<boolean>}
*/
public async checkLocalRepositoryExists(path: string): Promise<boolean> {
return await MediarepApi.checkLocalRepositoryExists({path});
return await MediarepoApi.checkLocalRepositoryExists({path});
}
/**
@ -128,7 +126,7 @@ export class RepositoryService {
* @returns {Promise<void>}
*/
public async removeRepository(name: string): Promise<void> {
await MediarepApi.removeRepository({name});
await MediarepoApi.removeRepository({name});
await this.loadRepositories();
}
@ -138,7 +136,7 @@ export class RepositoryService {
* @returns {Promise<void>}
*/
public async deleteRepository(name: string): Promise<void> {
await MediarepApi.deleteRepository({name});
await MediarepoApi.deleteRepository({name});
await this.removeRepository(name);
}
@ -148,7 +146,7 @@ export class RepositoryService {
* @returns {Promise<void>}
*/
public async startDaemon(repoPath: string): Promise<void> {
return MediarepApi.startDaemon({repoPath});
return MediarepoApi.startDaemon({repoPath});
}
/**
@ -157,7 +155,7 @@ export class RepositoryService {
* @returns {Promise<void>}
*/
public async initRepository(repoPath: string): Promise<void> {
return MediarepApi.initRepository({repoPath});
return MediarepoApi.initRepository({repoPath});
}
/**
@ -165,7 +163,7 @@ export class RepositoryService {
* @returns {Promise<RepositoryMetadata>}
*/
public async getRepositoryMetadata(): Promise<RepositoryMetadata> {
return MediarepApi.getRepositoryMetadata();
return MediarepoApi.getRepositoryMetadata();
}
/**
@ -174,11 +172,11 @@ export class RepositoryService {
* @param sizeType
*/
public async getSize(sizeType: SizeType): Promise<SizeMetadata> {
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);
}
}

@ -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<void>}
*/
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<void>}
*/
public async saveState(): Promise<void> {
await MediarepApi.setFrontendState({state: this.state.value.serializeJson()});
if (this.repoService.selectedRepository.value) {
await MediarepoApi.setFrontendState({state: this.state.value.serializeJson()});
}
}
}

@ -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<Tag[]> {
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<Tag[]> {
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<Tag[]> {
return MediarepApi.changeFileTags({id: fileId, addedTags, removedTags}).then(mapMany(mapNew(Tag)));
return MediarepoApi.changeFileTags({id: fileId, addedTags, removedTags}).then(mapMany(mapNew(Tag)));
}
}

Loading…
Cancel
Save