diff --git a/mediarepo-ui/src/app/components/core/core.module.ts b/mediarepo-ui/src/app/components/core/core.module.ts
index a514aba..067bb3a 100644
--- a/mediarepo-ui/src/app/components/core/core.module.ts
+++ b/mediarepo-ui/src/app/components/core/core.module.ts
@@ -40,6 +40,7 @@ import {
RepositoryDetailsViewComponent
} from "./repositories-tab/repository-details-view/repository-details-view.component";
import { EmptyTabComponent } from './empty-tab/empty-tab.component';
+import { RepositoryOverviewComponent } from './repositories-tab/repository-overview/repository-overview.component';
@NgModule({
@@ -54,6 +55,7 @@ import { EmptyTabComponent } from './empty-tab/empty-tab.component';
DownloadDaemonDialogComponent,
RepositoryDetailsViewComponent,
EmptyTabComponent,
+ RepositoryOverviewComponent,
],
exports: [
CoreComponent,
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 48622cd..4093b2a 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
@@ -1,18 +1,6 @@
-
-
-
-
-
-
-
- There are no repositories yet. You can create a repository or add an existing one.
-
-
-
+
-
-
+
diff --git a/mediarepo-ui/src/app/components/core/repositories-tab/repositories-tab.component.scss b/mediarepo-ui/src/app/components/core/repositories-tab/repositories-tab.component.scss
index 4e2ab92..2e3c1d6 100644
--- a/mediarepo-ui/src/app/components/core/repositories-tab/repositories-tab.component.scss
+++ b/mediarepo-ui/src/app/components/core/repositories-tab/repositories-tab.component.scss
@@ -1,41 +1,3 @@
-.repository-container {
- margin: 1em;
-}
-
-.repo-page-content {
- margin: 0 10%;
- height: calc(100% - 2em);
-}
-
-.add-repo-tools {
- height: 5em;
- display: flex;
- flex-direction: row-reverse;
-
- button {
- margin: 1em;
- }
-}
-
-.repository-list {
- display: flex;
- flex-direction: column;
- overflow-y: auto;
- height: calc(100% - 5em);
-}
-
-app-repository-card {
- position: relative;
-}
-
-app-repository-details-view, .repo-details {
+app-repository-details-view {
height: 100%;
}
-
-.add-repository-prompt {
- button {
- font-size: 1.5em;
- padding: 0.5em 1em;
- border-radius: 0.5em;
- }
-}
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 3c4f421..4b17e68 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
@@ -1,164 +1,18 @@
-import {AfterViewInit, Component, OnInit} from "@angular/core";
-import {Repository} from "../../../../api/models/Repository";
+import {Component} from "@angular/core";
import {RepositoryService} from "../../../services/repository/repository.service";
-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 {LoggingService} from "../../../services/logging/logging.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";
+import {Repository} from "../../../../api/models/Repository";
-type BusyDialogContext = { message: BehaviorSubject
, dialog: MatDialogRef };
@Component({
selector: "app-repositories-tab",
templateUrl: "./repositories-tab.component.html",
styleUrls: ["./repositories-tab.component.scss"]
})
-export class RepositoriesTabComponent implements OnInit, AfterViewInit {
- public repositories: Repository[] = [];
- public selectedRepository?: Repository;
-
- constructor(
- private logger: LoggingService,
- private repoService: RepositoryService,
- private jobService: JobService,
- private stateService: StateService,
- public dialog: MatDialog
- ) {
- }
-
- ngOnInit(): void {
- this.repoService.repositories.subscribe({
- next: (repos) => {
- this.repositories = repos;
- }
- });
- this.repoService.selectedRepository.subscribe(
- repo => this.selectedRepository = repo);
- }
+export class RepositoriesTabComponent {
- 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: any) {
- this.logger.error(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();
- dialogContext.dialog.close(true);
- } catch (err: any) {
- this.logger.error(err);
- dialogContext.message.next(
- "Failed to open repository: " + err.toString());
- await this.forceCloseRepository();
- setTimeout(() => dialogContext!.dialog.close(true), 1000);
- }
- }
-
- public openAddRepositoryDialog() {
- this.dialog.open(AddRepositoryDialogComponent, {
- disableClose: true,
- minWidth: "30%",
- minHeight: "30%",
- });
- }
-
- public async onOpenRepository(repository: Repository) {
- if (!repository.local) {
- await this.selectRepository(repository);
- } else {
- await this.startDaemonAndSelectRepository(repository);
- }
- }
-
- private async forceCloseRepository() {
- try {
- await this.repoService.closeSelectedRepository();
- } catch {
- }
- try {
- await this.repoService.disconnectSelectedRepository();
- } catch {
- }
- }
-
- private async runRepositoryStartupTasks(dialogContext: BusyDialogContext): Promise {
- dialogContext.message.next("Checking integrity...");
- await this.jobService.runJob("CheckIntegrity");
- dialogContext.message.next("Running a vacuum on the database...");
- await this.jobService.runJob("Vacuum");
- 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", false);
- dialogContext.message.next("Generating missing thumbnails...");
- await this.jobService.runJob("GenerateThumbnails");
- dialogContext.message.next("Finished repository startup");
- }
-
- private openStartupDialog(repository: Repository): BusyDialogContext {
- const 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 selectedRepository?: Repository;
- private async checkAndPromptDaemonExecutable() {
- if (!await this.repoService.checkDameonConfigured()) {
- const result = await this.dialog.open(
- DownloadDaemonDialogComponent,
- {
- disableClose: true,
- }
- ).afterClosed().toPromise();
- if (result) {
- // recursion avoidance
- setTimeout(
- async () => await this.checkAndPromptDaemonExecutable(), 0);
- }
- }
+ constructor(private repositoryService: RepositoryService) {
+ const sub = this.repositoryService.selectedRepository.subscribe(repo => this.selectedRepository = repo);
}
}
diff --git a/mediarepo-ui/src/app/components/core/repositories-tab/repository-overview/repository-overview.component.html b/mediarepo-ui/src/app/components/core/repositories-tab/repository-overview/repository-overview.component.html
new file mode 100644
index 0000000..6b9d51f
--- /dev/null
+++ b/mediarepo-ui/src/app/components/core/repositories-tab/repository-overview/repository-overview.component.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+ There are no repositories yet. You can create a repository or add an existing one.
+
+
+
+
diff --git a/mediarepo-ui/src/app/components/core/repositories-tab/repository-overview/repository-overview.component.scss b/mediarepo-ui/src/app/components/core/repositories-tab/repository-overview/repository-overview.component.scss
new file mode 100644
index 0000000..4f97bb8
--- /dev/null
+++ b/mediarepo-ui/src/app/components/core/repositories-tab/repository-overview/repository-overview.component.scss
@@ -0,0 +1,42 @@
+.repository-container {
+ margin: 1em;
+ display: block;
+ width: 600px;
+ float: left;
+}
+
+.repo-page-content {
+ margin: 0 10%;
+ height: calc(100% - 2em);
+}
+
+.add-repo-tools {
+ height: 5em;
+ display: flex;
+ flex-direction: row-reverse;
+
+ button {
+ margin: 1em;
+ }
+}
+
+.repository-list {
+ display: block;
+ overflow-y: auto;
+ overflow-x: hidden;
+ height: calc(100% - 5em);
+}
+
+app-repository-card {
+ display: block;
+ position: relative;
+}
+
+
+.add-repository-prompt {
+ button {
+ font-size: 1.5em;
+ padding: 0.5em 1em;
+ border-radius: 0.5em;
+ }
+}
diff --git a/mediarepo-ui/src/app/components/core/repositories-tab/repository-overview/repository-overview.component.spec.ts b/mediarepo-ui/src/app/components/core/repositories-tab/repository-overview/repository-overview.component.spec.ts
new file mode 100644
index 0000000..89b6b32
--- /dev/null
+++ b/mediarepo-ui/src/app/components/core/repositories-tab/repository-overview/repository-overview.component.spec.ts
@@ -0,0 +1,25 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { RepositoryOverviewComponent } from './repository-overview.component';
+
+describe('RepositoryOverviewComponent', () => {
+ let component: RepositoryOverviewComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ RepositoryOverviewComponent ]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(RepositoryOverviewComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/mediarepo-ui/src/app/components/core/repositories-tab/repository-overview/repository-overview.component.ts b/mediarepo-ui/src/app/components/core/repositories-tab/repository-overview/repository-overview.component.ts
new file mode 100644
index 0000000..3b109f0
--- /dev/null
+++ b/mediarepo-ui/src/app/components/core/repositories-tab/repository-overview/repository-overview.component.ts
@@ -0,0 +1,159 @@
+import {AfterViewInit, ChangeDetectionStrategy, Component, OnInit} from "@angular/core";
+import {Repository} from "../../../../../api/models/Repository";
+import {LoggingService} from "../../../../services/logging/logging.service";
+import {RepositoryService} from "../../../../services/repository/repository.service";
+import {JobService} from "../../../../services/job/job.service";
+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";
+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";
+
+type BusyDialogContext = { message: BehaviorSubject, dialog: MatDialogRef };
+
+@Component({
+ selector: "app-repository-overview",
+ templateUrl: "./repository-overview.component.html",
+ styleUrls: ["./repository-overview.component.scss"],
+ changeDetection: ChangeDetectionStrategy.Default
+})
+export class RepositoryOverviewComponent implements OnInit, AfterViewInit {
+
+ public repositories: Repository[] = [];
+
+ constructor(
+ private logger: LoggingService,
+ private repoService: RepositoryService,
+ private jobService: JobService,
+ private stateService: StateService,
+ public dialog: MatDialog
+ ) {
+ }
+
+ ngOnInit(): void {
+ this.repoService.repositories.subscribe(repos => this.repositories = repos);
+ }
+
+ 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: any) {
+ this.logger.error(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();
+ dialogContext.dialog.close(true);
+ } catch (err: any) {
+ this.logger.error(err);
+ dialogContext.message.next(
+ "Failed to open repository: " + err.toString());
+ await this.forceCloseRepository();
+ setTimeout(() => dialogContext!.dialog.close(true), 1000);
+ }
+ }
+
+ public openAddRepositoryDialog() {
+ this.dialog.open(AddRepositoryDialogComponent, {
+ disableClose: true,
+ minWidth: "30%",
+ minHeight: "30%",
+ });
+ }
+
+ public async onOpenRepository(repository: Repository) {
+ if (!repository.local) {
+ await this.selectRepository(repository);
+ } else {
+ await this.startDaemonAndSelectRepository(repository);
+ }
+ }
+
+ private async forceCloseRepository() {
+ try {
+ await this.repoService.closeSelectedRepository();
+ } catch {
+ }
+ try {
+ await this.repoService.disconnectSelectedRepository();
+ } catch {
+ }
+ }
+
+ private async runRepositoryStartupTasks(dialogContext: BusyDialogContext): Promise {
+ dialogContext.message.next("Checking integrity...");
+ await this.jobService.runJob("CheckIntegrity");
+ dialogContext.message.next("Running a vacuum on the database...");
+ await this.jobService.runJob("Vacuum");
+ 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", false);
+ dialogContext.message.next("Generating missing thumbnails...");
+ await this.jobService.runJob("GenerateThumbnails");
+ dialogContext.message.next("Finished repository startup");
+ }
+
+ private openStartupDialog(repository: Repository): BusyDialogContext {
+ const 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 };
+ }
+
+ private async checkAndPromptDaemonExecutable() {
+ if (!await this.repoService.checkDameonConfigured()) {
+ const result = await this.dialog.open(
+ DownloadDaemonDialogComponent,
+ {
+ disableClose: true,
+ }
+ ).afterClosed().toPromise();
+ if (result) {
+ // recursion avoidance
+ setTimeout(
+ async () => await this.checkAndPromptDaemonExecutable(), 0);
+ }
+ }
+ }
+}