Move home view to separate view and add tabs
Signed-off-by: trivernis <trivernis@protonmail.com>pull/4/head
parent
e721344d07
commit
5b0769dcd2
@ -0,0 +1,22 @@
|
|||||||
|
<mat-drawer-container class="page">
|
||||||
|
<mat-drawer mode="side" opened>
|
||||||
|
<div class="drawer-sidebar-inner">
|
||||||
|
<app-file-search #filesearch></app-file-search>
|
||||||
|
<div id="file-tag-list">
|
||||||
|
<h1>Selection Tags</h1>
|
||||||
|
<mat-selection-list [multiple]="false" *ngIf="tags.length > 0"
|
||||||
|
(selectionChange)="addSearchTagFromList($event)">
|
||||||
|
<mat-list-option
|
||||||
|
*ngFor="let tag of tags"
|
||||||
|
[value]="tag.getNormalizedOutput()">{{tag.getNormalizedOutput()}}</mat-list-option>
|
||||||
|
</mat-selection-list>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</mat-drawer>
|
||||||
|
<mat-drawer-content>
|
||||||
|
<app-file-grid (fileDblClickEvent)="openFile($event)" [files]="files"
|
||||||
|
(fileSelectEvent)="onFileSelect($event)"
|
||||||
|
(fileMultiselectEvent)="onFileMultiSelect($event)"
|
||||||
|
></app-file-grid>
|
||||||
|
</mat-drawer-content>
|
||||||
|
</mat-drawer-container>
|
@ -0,0 +1,35 @@
|
|||||||
|
#file-tag-list {
|
||||||
|
height: calc(100% - 8em);
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.drawer-sidebar-inner {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
mat-drawer {
|
||||||
|
height: 100%;
|
||||||
|
width: 25%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
mat-drawer-content {
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-y: auto;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
mat-drawer-container {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
app-file-grid {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { SearchPageComponent } from './search-page.component';
|
||||||
|
|
||||||
|
describe('SearchPageComponent', () => {
|
||||||
|
let component: SearchPageComponent;
|
||||||
|
let fixture: ComponentFixture<SearchPageComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [ SearchPageComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(SearchPageComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,119 @@
|
|||||||
|
import {Component, OnInit, ViewChild} from '@angular/core';
|
||||||
|
import {Tag} from "../../../models/Tag";
|
||||||
|
import {File} from "../../../models/File";
|
||||||
|
import {FileSearchComponent} from "../../../components/file-search/file-search.component";
|
||||||
|
import {ErrorBrokerService} from "../../../services/error-broker/error-broker.service";
|
||||||
|
import {FileService} from "../../../services/file/file.service";
|
||||||
|
import {TagService} from "../../../services/tag/tag.service";
|
||||||
|
import {Lightbox, LIGHTBOX_EVENT, LightboxEvent} from "ngx-lightbox";
|
||||||
|
import {MatSelectionListChange} from "@angular/material/list";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-search-page',
|
||||||
|
templateUrl: './search-page.component.html',
|
||||||
|
styleUrls: ['./search-page.component.scss']
|
||||||
|
})
|
||||||
|
export class SearchPageComponent implements OnInit {
|
||||||
|
|
||||||
|
tags: Tag[] = [];
|
||||||
|
files: File[] = [];
|
||||||
|
private openingLightbox = false;
|
||||||
|
|
||||||
|
@ViewChild('filesearch') fileSearch!: FileSearchComponent;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private errorBroker: ErrorBrokerService,
|
||||||
|
private fileService: FileService,
|
||||||
|
private tagService: TagService,
|
||||||
|
private lightbox: Lightbox,
|
||||||
|
private lightboxEvent: LightboxEvent) {
|
||||||
|
}
|
||||||
|
|
||||||
|
async ngOnInit() {
|
||||||
|
this.fileService.displayedFiles.subscribe((files) => this.files = files);
|
||||||
|
}
|
||||||
|
|
||||||
|
async onFileMultiSelect(files: File[]) {
|
||||||
|
await this.showFileDetails(files);
|
||||||
|
}
|
||||||
|
|
||||||
|
async onFileSelect(file: File | undefined) {
|
||||||
|
if (file) {
|
||||||
|
await this.showFileDetails([file]);
|
||||||
|
} else {
|
||||||
|
this.tags = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async showFileDetails(files: File[]) {
|
||||||
|
this.tags = [];
|
||||||
|
|
||||||
|
for (const file of files) {
|
||||||
|
const fileTags = await this.tagService.getTagsForFile(file.hash)
|
||||||
|
for (const tag of fileTags) {
|
||||||
|
if (this.tags.findIndex((t) => t.getNormalizedOutput() === tag.getNormalizedOutput()) < 0) {
|
||||||
|
this.tags.push(tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.tags = this.tags.sort((a, b) => {
|
||||||
|
const aNorm = a.getNormalizedOutput();
|
||||||
|
const bNorm = b.getNormalizedOutput();
|
||||||
|
if (aNorm > bNorm) {
|
||||||
|
return 1
|
||||||
|
} else if (bNorm > aNorm) {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
async openFile(file: File) {
|
||||||
|
if (this.openingLightbox) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.openingLightbox = true;
|
||||||
|
try {
|
||||||
|
await this.openLightbox(file);
|
||||||
|
} catch (err) {
|
||||||
|
this.errorBroker.showError(err);
|
||||||
|
}
|
||||||
|
this.openingLightbox = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async openLightbox(file: File): Promise<void> {
|
||||||
|
let url = await this.fileService.readFile(file);
|
||||||
|
|
||||||
|
let albums = [
|
||||||
|
{
|
||||||
|
src: url as string,
|
||||||
|
caption: file.name ?? file.comment,
|
||||||
|
thumb: url as string,
|
||||||
|
}
|
||||||
|
];
|
||||||
|
this.lightbox.open(albums, 0, {
|
||||||
|
disableScrolling: true,
|
||||||
|
showImageNumberLabel: false,
|
||||||
|
showDownloadButton: true,
|
||||||
|
centerVertically: true,
|
||||||
|
});
|
||||||
|
const lighboxSubscription = this.lightboxEvent.lightboxEvent$.subscribe(
|
||||||
|
(event: any) => {
|
||||||
|
if (event?.id == LIGHTBOX_EVENT.CLOSE) {
|
||||||
|
lighboxSubscription.unsubscribe();
|
||||||
|
URL?.revokeObjectURL(url as string);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue