diff --git a/mediarepo-ui/src/app/app.module.ts b/mediarepo-ui/src/app/app.module.ts index 135e3a9..7ea78bb 100644 --- a/mediarepo-ui/src/app/app.module.ts +++ b/mediarepo-ui/src/app/app.module.ts @@ -46,6 +46,7 @@ import { AddRepositoryDialogComponent } from './pages/home/repositories-tab/add- import {MatTooltipModule} from "@angular/material/tooltip"; import {MatMenuModule} from "@angular/material/menu"; import { ConfirmDialogComponent } from './components/confirm-dialog/confirm-dialog.component'; +import { FilesTabSidebarComponent } from './pages/home/files-tab/files-tab-sidebar/files-tab-sidebar.component'; @NgModule({ declarations: [ @@ -63,6 +64,7 @@ import { ConfirmDialogComponent } from './components/confirm-dialog/confirm-dial ContentAwareImageComponent, AddRepositoryDialogComponent, ConfirmDialogComponent, + FilesTabSidebarComponent, ], imports: [ BrowserModule, diff --git a/mediarepo-ui/src/app/components/file-search/file-search.component.ts b/mediarepo-ui/src/app/components/file-search/file-search.component.ts index 7262ca1..485e979 100644 --- a/mediarepo-ui/src/app/components/file-search/file-search.component.ts +++ b/mediarepo-ui/src/app/components/file-search/file-search.component.ts @@ -22,11 +22,7 @@ import {ErrorBrokerService} from "../../services/error-broker/error-broker.servi templateUrl: './file-search.component.html', styleUrls: ['./file-search.component.scss'] }) -export class FileSearchComponent implements AfterViewChecked { - public ngAfterViewChecked(): void { - this.inputList.nativeElement.scrollLeft = this.inputList.nativeElement.scrollWidth; - } - +export class FileSearchComponent implements AfterViewChecked, OnInit { public sortExpression: SortKey[] = [new SortKey("FileImportedTime", "Ascending", undefined)]; public formControl = new FormControl(); @@ -47,6 +43,14 @@ export class FileSearchComponent implements AfterViewChecked { tag) : this.validTags.slice(0, 20))); } + public async ngOnInit() { + await this.searchForFiles(); + } + + public ngAfterViewChecked(): void { + this.inputList.nativeElement.scrollLeft = this.inputList.nativeElement.scrollWidth; + } + private filterSuggestionTag(tag: string) { const negated = tag.startsWith("-"); const normalizedTag = tag.replace(/^-/, ""); diff --git a/mediarepo-ui/src/app/pages/home/files-tab/files-tab-sidebar/files-tab-sidebar.component.html b/mediarepo-ui/src/app/pages/home/files-tab/files-tab-sidebar/files-tab-sidebar.component.html new file mode 100644 index 0000000..a42e464 --- /dev/null +++ b/mediarepo-ui/src/app/pages/home/files-tab/files-tab-sidebar/files-tab-sidebar.component.html @@ -0,0 +1,15 @@ + diff --git a/mediarepo-ui/src/app/pages/home/files-tab/files-tab-sidebar/files-tab-sidebar.component.scss b/mediarepo-ui/src/app/pages/home/files-tab/files-tab-sidebar/files-tab-sidebar.component.scss new file mode 100644 index 0000000..37777e2 --- /dev/null +++ b/mediarepo-ui/src/app/pages/home/files-tab/files-tab-sidebar/files-tab-sidebar.component.scss @@ -0,0 +1,20 @@ +#file-search-input { + width: 100%; + overflow: hidden; +} + +app-file-search { + display: block; + width: 100%; +} + +#file-tag-list { + height: 100%; + overflow-y: auto; +} + +.sidebar-inner { + height: 100%; + width: 100%; + display: block; +} diff --git a/mediarepo-ui/src/app/pages/home/files-tab/files-tab-sidebar/files-tab-sidebar.component.spec.ts b/mediarepo-ui/src/app/pages/home/files-tab/files-tab-sidebar/files-tab-sidebar.component.spec.ts new file mode 100644 index 0000000..7f2865f --- /dev/null +++ b/mediarepo-ui/src/app/pages/home/files-tab/files-tab-sidebar/files-tab-sidebar.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { FilesTabSidebarComponent } from './files-tab-sidebar.component'; + +describe('FilesTabSidebarComponent', () => { + let component: FilesTabSidebarComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ FilesTabSidebarComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(FilesTabSidebarComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/mediarepo-ui/src/app/pages/home/files-tab/files-tab-sidebar/files-tab-sidebar.component.ts b/mediarepo-ui/src/app/pages/home/files-tab/files-tab-sidebar/files-tab-sidebar.component.ts new file mode 100644 index 0000000..2c53808 --- /dev/null +++ b/mediarepo-ui/src/app/pages/home/files-tab/files-tab-sidebar/files-tab-sidebar.component.ts @@ -0,0 +1,74 @@ +import { + Component, + EventEmitter, + Input, OnChanges, + OnInit, + Output, SimpleChanges, + ViewChild +} from '@angular/core'; +import {Tag} from "../../../../models/Tag"; +import {TagService} from "../../../../services/tag/tag.service"; +import {FileService} from "../../../../services/file/file.service"; +import {File} from "../../../../models/File"; +import {MatSelectionListChange} from "@angular/material/list"; +import {FileSearchComponent} from "../../../../components/file-search/file-search.component"; +import {RepositoryService} from "../../../../services/repository/repository.service"; + +@Component({ + selector: 'app-files-tab-sidebar', + templateUrl: './files-tab-sidebar.component.html', + styleUrls: ['./files-tab-sidebar.component.scss'] +}) +export class FilesTabSidebarComponent implements OnInit, OnChanges { + + @Input() selectedFiles: File[] = []; + @Output() searchStartEvent = new EventEmitter(); + @Output() searchEndEvent = new EventEmitter(); + + @ViewChild('filesearch') fileSearch!: FileSearchComponent; + + public tagsOfFiles: Tag[] = []; + public tags: Tag[] = []; + public files: File[] = []; + + constructor(private repoService: RepositoryService, private tagService: TagService, private fileService: FileService) { + this.fileService.displayedFiles.subscribe(async files => { + this.files = files; + await this.loadTagsForDisplayedFiles(); + }); + this.repoService.selectedRepository.subscribe(async (repo) => repo && this.fileSearch && await this.fileSearch.searchForFiles()); + } + + async ngOnInit() { + this.fileSearch && await this.fileSearch.searchForFiles(); + } + + public async ngOnChanges(changes: SimpleChanges): Promise{ + if (changes["selectedFiles"]) { + const tags = await this.tagService.getTagsForFiles(this.selectedFiles.map(f => f.hash)); + this.tags = tags.sort((a, b) => a.getNormalizedOutput().localeCompare(b.getNormalizedOutput())); + } + } + + async loadTagsForDisplayedFiles() { + this.tagsOfFiles = await this.tagService.getTagsForFiles(this.files.map(f => f.hash)); + } + + async addSearchTagFromList(event: MatSelectionListChange) { + if (event.options.length > 0) { + const tag = event.options[0].value; + this.fileSearch.addSearchTag(tag); + await this.fileSearch.searchForFiles(); + } + event.source.deselectAll(); + } + + getValidTagsForSearch(): string[] { + return this.tagsOfFiles.map(t => t.getNormalizedOutput()) + } + + async showFileDetails(files: File[]) { + this.tags = await this.tagService.getTagsForFiles(files.map(f => f.hash)) + this.tags = this.tags.sort((a, b) => a.getNormalizedOutput().localeCompare(b.getNormalizedOutput())); + } +} diff --git a/mediarepo-ui/src/app/pages/home/files-tab/files-tab.component.html b/mediarepo-ui/src/app/pages/home/files-tab/files-tab.component.html index 2770010..0c01846 100644 --- a/mediarepo-ui/src/app/pages/home/files-tab/files-tab.component.html +++ b/mediarepo-ui/src/app/pages/home/files-tab/files-tab.component.html @@ -1,32 +1,19 @@ -
-
- -
-
-

Selection Tags

- - {{tag.getNormalizedOutput()}} - -
-
+
-
- -
- - +
+ +
+ +
diff --git a/mediarepo-ui/src/app/pages/home/files-tab/files-tab.component.scss b/mediarepo-ui/src/app/pages/home/files-tab/files-tab.component.scss index fc6b9c1..7ae1feb 100644 --- a/mediarepo-ui/src/app/pages/home/files-tab/files-tab.component.scss +++ b/mediarepo-ui/src/app/pages/home/files-tab/files-tab.component.scss @@ -1,24 +1,3 @@ -.drawer-sidebar-inner { - height: 100%; - width: 100%; - display: block; -} - -#file-search-input { - width: 100%; - overflow: hidden; -} - -app-file-search { - display: block; - width: 100%; -} - -#file-tag-list { - height: 100%; - overflow-y: auto; -} - mat-selection-list { height: 100%; } diff --git a/mediarepo-ui/src/app/pages/home/files-tab/files-tab.component.ts b/mediarepo-ui/src/app/pages/home/files-tab/files-tab.component.ts index d542677..9e756de 100644 --- a/mediarepo-ui/src/app/pages/home/files-tab/files-tab.component.ts +++ b/mediarepo-ui/src/app/pages/home/files-tab/files-tab.component.ts @@ -17,66 +17,36 @@ import {RepositoryService} from "../../../services/repository/repository.service }) export class FilesTabComponent implements OnInit { - tagsOfFiles: Tag[] = []; - tags: Tag[] = []; + files: File[] = []; - private openingLightbox = false; showGallery = false; preselectedFile: File | undefined; contentLoading = false; - - @ViewChild('filesearch') fileSearch!: FileSearchComponent; + selectedFiles: File[] = []; constructor( private errorBroker: ErrorBrokerService, private repoService: RepositoryService, - private fileService: FileService, - private tagService: TagService,) { + private fileService: FileService,) { } async ngOnInit() { this.fileService.displayedFiles.subscribe(async (files) => { this.files = files; - await this.loadTagsForDisplayedFiles(); }); - this.repoService.selectedRepository.subscribe(async (repo) => repo && await this.loadFilesInitially()); - await this.loadFilesInitially(); - } - - async loadFilesInitially() { - this.files = []; - this.contentLoading = true; - - if (this.fileSearch) { - await this.fileSearch.searchForFiles(); - } else { - await this.fileService.findFiles([], [new SortKey("FileImportedTime", "Ascending", undefined)]) - } - this.contentLoading = false; } async onFileMultiSelect(files: File[]) { - await this.showFileDetails(files); + this.selectedFiles = files; } + async onFileSelect(file: File | undefined) { if (file) { - await this.showFileDetails([file]); - } - } - - async showFileDetails(files: File[]) { - this.tags = await this.tagService.getTagsForFiles(files.map(f => f.hash)) - this.tags = this.tags.sort((a, b) => a.getNormalizedOutput().localeCompare(b.getNormalizedOutput())); - } - - async addSearchTagFromList(event: MatSelectionListChange) { - if (event.options.length > 0) { - const tag = event.options[0].value; - this.fileSearch.addSearchTag(tag); - await this.fileSearch.searchForFiles(); + this.selectedFiles = [file]; + } else { + this.selectedFiles = []; } - event.source.deselectAll(); } async openGallery(preselectedFile: File) { @@ -88,12 +58,4 @@ export class FilesTabComponent implements OnInit { this.preselectedFile = preselectedFile; this.showGallery = false; } - - async loadTagsForDisplayedFiles() { - this.tagsOfFiles = await this.tagService.getTagsForFiles(this.files.map(f => f.hash)); - } - - getValidTagsForSearch(): string[] { - return this.tagsOfFiles.map(t => t.getNormalizedOutput()) - } }