parent
2691653274
commit
e6026cfd27
@ -1,10 +1,10 @@
|
|||||||
<h1 mat-dialog-title>
|
<h1 mat-dialog-title>
|
||||||
{{title}}
|
{{title}}
|
||||||
</h1>
|
</h1>
|
||||||
<div mat-dialog-content>
|
<div mat-dialog-content>
|
||||||
{{message}}
|
{{message}}
|
||||||
</div>
|
</div>
|
||||||
<div mat-dialog-actions class="confirm-dialog-actions">
|
<div class="confirm-dialog-actions" mat-dialog-actions>
|
||||||
<button mat-stroked-button [color]="this.denyColor" (click)="closeDialog(false)">{{denyAction}}</button>
|
<button (click)="closeDialog(false)" [color]="this.denyColor" mat-stroked-button>{{denyAction}}</button>
|
||||||
<button mat-flat-button [color]="this.confirmColor" (click)="closeDialog(true)">{{confirmAction}}</button>
|
<button (click)="closeDialog(true)" [color]="this.confirmColor" mat-flat-button>{{confirmAction}}</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<div #imageContainer class="image-container" (window:resize)="this.adjustSize(image, imageContainer)">
|
<div #imageContainer (window:resize)="this.adjustSize(image, imageContainer)" class="image-container">
|
||||||
<img #image [src]="this.imageSrc" alt="" (load)="this.adjustSize(image, imageContainer)"
|
<img #image (load)="this.adjustSize(image, imageContainer)" [class.scale-height]="(!scaleWidth) && maximizeHeight" [class.scale-width]="scaleWidth && maximizeWidth"
|
||||||
[class.scale-width]="scaleWidth && maximizeWidth" [class.scale-height]="(!scaleWidth) && maximizeHeight"
|
[src]="this.imageSrc" alt=""
|
||||||
decoding="async">
|
decoding="async">
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<div class="image-wrapper" (click)="fileSelectEvent.emit(this.file)" [class.selected]="this.file.selected">
|
<div (click)="fileSelectEvent.emit(this.file)" [class.selected]="this.file.selected" class="image-wrapper">
|
||||||
<mat-progress-spinner *ngIf="!contentUrl"></mat-progress-spinner>
|
<mat-progress-spinner *ngIf="!contentUrl"></mat-progress-spinner>
|
||||||
<app-content-aware-image *ngIf="contentUrl" [imageSrc]="contentUrl"></app-content-aware-image>
|
<app-content-aware-image *ngIf="contentUrl" [imageSrc]="contentUrl"></app-content-aware-image>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,60 +1,65 @@
|
|||||||
import {
|
import {
|
||||||
Component,
|
Component,
|
||||||
Input,
|
ElementRef,
|
||||||
OnInit,
|
EventEmitter,
|
||||||
ViewChild,
|
Input,
|
||||||
ElementRef, Output, EventEmitter, OnDestroy, OnChanges
|
OnChanges,
|
||||||
|
OnInit,
|
||||||
|
Output,
|
||||||
|
ViewChild
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import {File} from "../../../models/File";
|
import {File} from "../../../models/File";
|
||||||
import {FileService} from "../../../services/file/file.service";
|
import {FileService} from "../../../services/file/file.service";
|
||||||
import {ErrorBrokerService} from "../../../services/error-broker/error-broker.service";
|
import {ErrorBrokerService} from "../../../services/error-broker/error-broker.service";
|
||||||
import {SafeResourceUrl} from "@angular/platform-browser";
|
import {SafeResourceUrl} from "@angular/platform-browser";
|
||||||
import {MatCard} from "@angular/material/card";
|
|
||||||
import {Thumbnail} from "../../../models/Thumbnail";
|
|
||||||
import {GridEntry} from "./GridEntry";
|
import {GridEntry} from "./GridEntry";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-file-grid-entry',
|
selector: 'app-file-grid-entry',
|
||||||
templateUrl: './file-grid-entry.component.html',
|
templateUrl: './file-grid-entry.component.html',
|
||||||
styleUrls: ['./file-grid-entry.component.scss']
|
styleUrls: ['./file-grid-entry.component.scss']
|
||||||
})
|
})
|
||||||
export class FileGridEntryComponent implements OnInit, OnChanges {
|
export class FileGridEntryComponent implements OnInit, OnChanges {
|
||||||
|
|
||||||
@ViewChild("card") card!: ElementRef;
|
@ViewChild("card") card!: ElementRef;
|
||||||
@Input() public gridEntry!: GridEntry;
|
@Input() public gridEntry!: GridEntry;
|
||||||
@Output() clickEvent = new EventEmitter<FileGridEntryComponent>();
|
@Output() clickEvent = new EventEmitter<FileGridEntryComponent>();
|
||||||
@Output() dblClickEvent = new EventEmitter<FileGridEntryComponent>();
|
@Output() dblClickEvent = new EventEmitter<FileGridEntryComponent>();
|
||||||
|
|
||||||
contentUrl: SafeResourceUrl | undefined;
|
contentUrl: SafeResourceUrl | undefined;
|
||||||
private cachedFile: File | undefined;
|
private cachedFile: File | undefined;
|
||||||
|
|
||||||
constructor(private fileService: FileService, private errorBroker: ErrorBrokerService) { }
|
constructor(private fileService: FileService, private errorBroker: ErrorBrokerService) {
|
||||||
|
}
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
this.cachedFile = this.gridEntry.file;
|
this.cachedFile = this.gridEntry.file;
|
||||||
await this.loadImage();
|
await this.loadImage();
|
||||||
}
|
}
|
||||||
|
|
||||||
async ngOnChanges() {
|
async ngOnChanges() {
|
||||||
if (!this.cachedFile || this.gridEntry.file.hash !== this.cachedFile.hash) {
|
if (!this.cachedFile || this.gridEntry.file.hash !== this.cachedFile.hash) {
|
||||||
this.cachedFile = this.gridEntry.file;
|
this.cachedFile = this.gridEntry.file;
|
||||||
await this.loadImage();
|
await this.loadImage();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
async loadImage() {
|
||||||
async loadImage() {
|
try {
|
||||||
try {
|
const thumbnails = await this.fileService.getThumbnails(
|
||||||
const thumbnails = await this.fileService.getThumbnails(this.gridEntry.file.hash);
|
this.gridEntry.file.hash);
|
||||||
let thumbnail = thumbnails.find(t => (t.height > 250 || t.width > 250) && (t.height < 500 && t.width < 500));
|
let thumbnail = thumbnails.find(
|
||||||
thumbnail = thumbnail ?? thumbnails[0];
|
t => (t.height > 250 || t.width > 250) && (t.height < 500 && t.width < 500));
|
||||||
|
thumbnail = thumbnail ?? thumbnails[0];
|
||||||
if (!thumbnail) {
|
|
||||||
console.log("Thumbnail is empty?!", thumbnails);
|
if (!thumbnail) {
|
||||||
} else {
|
console.log("Thumbnail is empty?!", thumbnails);
|
||||||
this.contentUrl = await this.fileService.readThumbnail(thumbnail!!);
|
} else {
|
||||||
|
this.contentUrl = await this.fileService.readThumbnail(
|
||||||
|
thumbnail!!);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
this.errorBroker.showError(err);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
|
||||||
this.errorBroker.showError(err);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,25 +1,25 @@
|
|||||||
<div class="tag-input-list-and-actions">
|
<div class="tag-input-list-and-actions">
|
||||||
<div class="tag-input-list" #tagInputList>
|
<div #tagInputList class="tag-input-list">
|
||||||
<div class="tag-input-list-inner">
|
<div class="tag-input-list-inner">
|
||||||
<div class="tag-input-item" *ngFor="let tag of searchTags" mat-ripple
|
<div (click)="removeSearchTag(tag)" *ngFor="let tag of searchTags" class="tag-input-item"
|
||||||
(click)="removeSearchTag(tag)">{{tag.getNormalizedTag()}}</div>
|
mat-ripple>{{tag.getNormalizedTag()}}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button id="delete-all-tags-button" mat-icon-button (click)="removeAllSearchTags()">
|
<button (click)="removeAllSearchTags()" id="delete-all-tags-button" mat-icon-button>
|
||||||
<mat-icon>delete-sweep</mat-icon>
|
<mat-icon>delete-sweep</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<mat-form-field class="full-width" appearance="fill">
|
<mat-form-field appearance="fill" class="full-width">
|
||||||
<mat-label>Enter tags to filter for</mat-label>
|
<mat-label>Enter tags to filter for</mat-label>
|
||||||
<input matInput
|
<input #tagInput
|
||||||
#tagInput
|
|
||||||
(keydown)="addSearchTagByInput($event)"
|
(keydown)="addSearchTagByInput($event)"
|
||||||
|
[formControl]="formControl"
|
||||||
[matAutocomplete]="auto"
|
[matAutocomplete]="auto"
|
||||||
[formControl]="formControl"/>
|
matInput/>
|
||||||
<mat-autocomplete #auto (optionSelected)="addSearchTagByAutocomplete($event)">
|
<mat-autocomplete #auto (optionSelected)="addSearchTagByAutocomplete($event)">
|
||||||
<mat-option *ngFor="let tag of suggestionTags | async" [value]="tag">
|
<mat-option *ngFor="let tag of suggestionTags | async" [value]="tag">
|
||||||
{{tag}}
|
{{tag}}
|
||||||
</mat-option>
|
</mat-option>
|
||||||
</mat-autocomplete>
|
</mat-autocomplete>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<button mat-flat-button id="sort-button" (click)="openSortDialog()">Sort: {{sortExpression.join(", ")}}</button>
|
<button (click)="openSortDialog()" id="sort-button" mat-flat-button>Sort: {{sortExpression.join(", ")}}</button>
|
||||||
|
@ -1,40 +1,48 @@
|
|||||||
<h1 mat-dialog-title>Sort Entries</h1>
|
<h1 mat-dialog-title>Sort Entries</h1>
|
||||||
<div mat-dialog-content>
|
<div mat-dialog-content>
|
||||||
<div cdkDropList class="sort-input-list" (cdkDropListDropped)="this.onSortEntryDrop($event)">
|
<div (cdkDropListDropped)="this.onSortEntryDrop($event)" cdkDropList class="sort-input-list">
|
||||||
<div cdkDrag class="sort-input-row" *ngFor="let sortKey of sortEntries">
|
<div *ngFor="let sortKey of sortEntries" cdkDrag class="sort-input-row">
|
||||||
<div class="drag-placeholder" *cdkDragPlaceholder></div>
|
<div *cdkDragPlaceholder class="drag-placeholder"></div>
|
||||||
<div class="drag-handle" cdkDragHandle><mat-icon>drag_handle</mat-icon></div>
|
<div cdkDragHandle class="drag-handle">
|
||||||
<mat-form-field>
|
<mat-icon>drag_handle</mat-icon>
|
||||||
<mat-label>Key</mat-label>
|
|
||||||
<mat-select required [(value)]="sortKey.sortType">
|
|
||||||
<mat-option value="Namespace">Namespace</mat-option>
|
|
||||||
<mat-option value="FileName">File Name</mat-option>
|
|
||||||
<mat-option value="FileSize">File Size</mat-option>
|
|
||||||
<mat-option value="FileImportedTime">Time Imported</mat-option>
|
|
||||||
<mat-option value="FileCreatedTime">Time Created</mat-option>
|
|
||||||
<mat-option value="FileChangeTime">Time Changed</mat-option>
|
|
||||||
<mat-option value="FileType">File Type</mat-option>
|
|
||||||
<mat-option value="NumTags">Number of Tags</mat-option>
|
|
||||||
</mat-select>
|
|
||||||
</mat-form-field>
|
|
||||||
<mat-form-field *ngIf="sortKey.sortType === 'Namespace'">
|
|
||||||
<mat-label>Namespace Name</mat-label>
|
|
||||||
<input #namespaceInput matInput required [value]="sortKey.namespaceName ?? ''" (change)="sortKey.namespaceName = namespaceInput.value">
|
|
||||||
</mat-form-field>
|
|
||||||
<div class="filler" *ngIf="sortKey.sortType !== 'Namespace'"></div>
|
|
||||||
<mat-form-field>
|
|
||||||
<mat-label>Direction</mat-label>
|
|
||||||
<mat-select [(value)]="sortKey.sortDirection" required>
|
|
||||||
<mat-option value="Ascending">Ascending</mat-option>
|
|
||||||
<mat-option value="Descending">Descending</mat-option>
|
|
||||||
</mat-select>
|
|
||||||
</mat-form-field>
|
|
||||||
<button *ngIf="sortEntries.indexOf(sortKey) === sortEntries.length -1" mat-flat-button (click)="addNewSortKey()"><mat-icon>add</mat-icon></button>
|
|
||||||
<button *ngIf="sortEntries.indexOf(sortKey) !== sortEntries.length -1" mat-flat-button (click)="removeSortKey(sortKey)"><mat-icon>remove</mat-icon></button>
|
|
||||||
</div>
|
</div>
|
||||||
|
<mat-form-field>
|
||||||
|
<mat-label>Key</mat-label>
|
||||||
|
<mat-select [(value)]="sortKey.sortType" required>
|
||||||
|
<mat-option value="Namespace">Namespace</mat-option>
|
||||||
|
<mat-option value="FileName">File Name</mat-option>
|
||||||
|
<mat-option value="FileSize">File Size</mat-option>
|
||||||
|
<mat-option value="FileImportedTime">Time Imported</mat-option>
|
||||||
|
<mat-option value="FileCreatedTime">Time Created</mat-option>
|
||||||
|
<mat-option value="FileChangeTime">Time Changed</mat-option>
|
||||||
|
<mat-option value="FileType">File Type</mat-option>
|
||||||
|
<mat-option value="NumTags">Number of Tags</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
<mat-form-field *ngIf="sortKey.sortType === 'Namespace'">
|
||||||
|
<mat-label>Namespace Name</mat-label>
|
||||||
|
<input #namespaceInput (change)="sortKey.namespaceName = namespaceInput.value" [value]="sortKey.namespaceName ?? ''" matInput
|
||||||
|
required>
|
||||||
|
</mat-form-field>
|
||||||
|
<div *ngIf="sortKey.sortType !== 'Namespace'" class="filler"></div>
|
||||||
|
<mat-form-field>
|
||||||
|
<mat-label>Direction</mat-label>
|
||||||
|
<mat-select [(value)]="sortKey.sortDirection" required>
|
||||||
|
<mat-option value="Ascending">Ascending</mat-option>
|
||||||
|
<mat-option value="Descending">Descending</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
<button (click)="addNewSortKey()" *ngIf="sortEntries.indexOf(sortKey) === sortEntries.length -1" mat-flat-button>
|
||||||
|
<mat-icon>add</mat-icon>
|
||||||
|
</button>
|
||||||
|
<button (click)="removeSortKey(sortKey)" *ngIf="sortEntries.indexOf(sortKey) !== sortEntries.length -1"
|
||||||
|
mat-flat-button>
|
||||||
|
<mat-icon>remove</mat-icon>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="dialog-actions" mat-dialog-actions>
|
<div class="dialog-actions" mat-dialog-actions>
|
||||||
<button mat-flat-button color="primary" (click)="confirmSort()">Sort</button>
|
<button (click)="confirmSort()" color="primary" mat-flat-button>Sort</button>
|
||||||
<button mat-stroked-button color="accent" (click)="cancelSort()">Cancel</button>
|
<button (click)="cancelSort()" color="accent" mat-stroked-button>Cancel</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<div class="tag-item-wrapper">
|
<div class="tag-item-wrapper">
|
||||||
<span *ngIf="tag.namespace" class="tag-item-namespace" [style]="{color: namespaceColor}">{{tag.namespace}}:</span>
|
<span *ngIf="tag.namespace" [style]="{color: namespaceColor}" class="tag-item-namespace">{{tag.namespace}}:</span>
|
||||||
<span class="tag-item-name" [style]="{color: tagColor}">{{tag.name}}</span>
|
<span [style]="{color: tagColor}" class="tag-item-name">{{tag.name}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,19 +1,20 @@
|
|||||||
<mat-drawer-container class="page">
|
<mat-drawer-container class="page">
|
||||||
<mat-drawer mode="side" opened disableClose>
|
<mat-drawer disableClose mode="side" opened>
|
||||||
<app-files-tab-sidebar (searchEndEvent)="this.contentLoading = false"
|
<app-files-tab-sidebar (searchEndEvent)="this.contentLoading = false"
|
||||||
(searchStartEvent)="this.contentLoading = true" [selectedFiles]="this.selectedFiles"></app-files-tab-sidebar>
|
(searchStartEvent)="this.contentLoading = true"
|
||||||
|
[selectedFiles]="this.selectedFiles"></app-files-tab-sidebar>
|
||||||
</mat-drawer>
|
</mat-drawer>
|
||||||
<mat-drawer-content>
|
<mat-drawer-content>
|
||||||
<div *ngIf="contentLoading" class="spinner-overlay">
|
<div *ngIf="contentLoading" class="spinner-overlay">
|
||||||
<mat-progress-spinner color="primary" mode="indeterminate"></mat-progress-spinner>
|
<mat-progress-spinner color="primary" mode="indeterminate"></mat-progress-spinner>
|
||||||
</div>
|
</div>
|
||||||
<app-file-grid *ngIf="!this.showGallery" (fileDblClickEvent)="openGallery($event)" [files]="files"
|
<app-file-grid (fileDblClickEvent)="openGallery($event)" (fileMultiselectEvent)="onFileMultiSelect($event)" (fileSelectEvent)="onFileSelect($event)"
|
||||||
(fileSelectEvent)="onFileSelect($event)"
|
*ngIf="!this.showGallery"
|
||||||
|
[files]="files"
|
||||||
[preselectedFile]="this.preselectedFile"
|
[preselectedFile]="this.preselectedFile"
|
||||||
(fileMultiselectEvent)="onFileMultiSelect($event)"
|
|
||||||
></app-file-grid>
|
></app-file-grid>
|
||||||
<app-file-gallery *ngIf="this.showGallery" [files]="files" (fileSelectEvent)="onFileSelect($event)"
|
<app-file-gallery (closeEvent)="this.closeGallery($event.selectedFile?.data)" (fileSelectEvent)="onFileSelect($event)" *ngIf="this.showGallery"
|
||||||
[preselectedFile]="this.preselectedFile"
|
[files]="files"
|
||||||
(closeEvent)="this.closeGallery($event.selectedFile?.data)"></app-file-gallery>
|
[preselectedFile]="this.preselectedFile"></app-file-gallery>
|
||||||
</mat-drawer-content>
|
</mat-drawer-content>
|
||||||
</mat-drawer-container>
|
</mat-drawer-container>
|
||||||
|
Loading…
Reference in New Issue