|
|
@ -2,71 +2,91 @@ import {
|
|
|
|
Component,
|
|
|
|
Component,
|
|
|
|
EventEmitter,
|
|
|
|
EventEmitter,
|
|
|
|
HostListener,
|
|
|
|
HostListener,
|
|
|
|
Input,
|
|
|
|
Input, OnChanges,
|
|
|
|
OnInit,
|
|
|
|
OnInit,
|
|
|
|
Output, QueryList, ViewChildren
|
|
|
|
Output, QueryList, SimpleChanges, ViewChildren
|
|
|
|
} 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 {FileGridEntryComponent} from "./file-grid-entry/file-grid-entry.component";
|
|
|
|
import {FileGridEntryComponent} from "./file-grid-entry/file-grid-entry.component";
|
|
|
|
|
|
|
|
import {GridEntry} from "./file-grid-entry/GridEntry";
|
|
|
|
|
|
|
|
|
|
|
|
@Component({
|
|
|
|
@Component({
|
|
|
|
selector: 'app-file-grid',
|
|
|
|
selector: 'app-file-grid',
|
|
|
|
templateUrl: './file-grid.component.html',
|
|
|
|
templateUrl: './file-grid.component.html',
|
|
|
|
styleUrls: ['./file-grid.component.scss']
|
|
|
|
styleUrls: ['./file-grid.component.scss']
|
|
|
|
})
|
|
|
|
})
|
|
|
|
export class FileGridComponent {
|
|
|
|
export class FileGridComponent implements OnChanges {
|
|
|
|
|
|
|
|
|
|
|
|
@Input() fileRows: File[][] = [];
|
|
|
|
@Input() files: File[] = [];
|
|
|
|
|
|
|
|
@Input() columns: number = 6;
|
|
|
|
@Output() fileDblClickEvent = new EventEmitter<File>();
|
|
|
|
@Output() fileDblClickEvent = new EventEmitter<File>();
|
|
|
|
@Output() filesSelectEvent = new EventEmitter<File[]>();
|
|
|
|
@Output() filesSelectEvent = new EventEmitter<File[]>();
|
|
|
|
|
|
|
|
|
|
|
|
@ViewChildren(FileGridEntryComponent) childQuery!: QueryList<FileGridEntryComponent>;
|
|
|
|
selectedEntries: GridEntry[] = [];
|
|
|
|
|
|
|
|
|
|
|
|
selectedEntries: FileGridEntryComponent[] = [];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private shiftClicked = false;
|
|
|
|
private shiftClicked = false;
|
|
|
|
private ctrlClicked = false;
|
|
|
|
private ctrlClicked = false;
|
|
|
|
|
|
|
|
private gridEntries: GridEntry[] = []
|
|
|
|
|
|
|
|
partitionedGridEntries: GridEntry[][] = [];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
constructor() {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ngOnChanges(changes: SimpleChanges): void {
|
|
|
|
|
|
|
|
this.gridEntries = this.files.map(file => {return {file, selected: false}});
|
|
|
|
|
|
|
|
this.setPartitionedGridEntries();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
constructor() { }
|
|
|
|
private setPartitionedGridEntries() {
|
|
|
|
|
|
|
|
this.partitionedGridEntries = [];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (let i = 0; i < (Math.ceil(this.gridEntries.length / this.columns)); i++) {
|
|
|
|
|
|
|
|
this.partitionedGridEntries.push(this.gridEntries.slice(i * this.columns, Math.min(this.gridEntries.length, (i + 1) * this.columns)))
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* File selector logic
|
|
|
|
* File selector logic
|
|
|
|
* @param {FileGridEntryComponent} entry
|
|
|
|
* @param {FileGridEntryComponent} clickedEntry
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
setSelectedFile(entry: FileGridEntryComponent) {
|
|
|
|
setSelectedFile(clickedEntry: GridEntry) {
|
|
|
|
if (!(this.shiftClicked || this.ctrlClicked) && this.selectedEntries.length > 0) {
|
|
|
|
if (!(this.shiftClicked || this.ctrlClicked) && this.selectedEntries.length > 0) {
|
|
|
|
this.selectedEntries.forEach(entry => entry.selected = false);
|
|
|
|
this.selectedEntries.forEach(entry => {if (entry !== clickedEntry) entry.selected = false});
|
|
|
|
this.selectedEntries = [];
|
|
|
|
this.selectedEntries = [];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// shift selector (forwards and backwards)
|
|
|
|
|
|
|
|
if (this.shiftClicked && this.selectedEntries.length > 0) {
|
|
|
|
if (this.shiftClicked && this.selectedEntries.length > 0) {
|
|
|
|
|
|
|
|
this.handleShiftSelect(clickedEntry);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
clickedEntry.selected = !clickedEntry.selected;
|
|
|
|
|
|
|
|
this.selectedEntries.push(clickedEntry);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
this.filesSelectEvent.emit(this.selectedEntries.map(entry => entry.file));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private handleShiftSelect(clickedEntry: GridEntry): void {
|
|
|
|
const lastEntry = this.selectedEntries[this.selectedEntries.length - 1];
|
|
|
|
const lastEntry = this.selectedEntries[this.selectedEntries.length - 1];
|
|
|
|
let found = false;
|
|
|
|
let found = false;
|
|
|
|
|
|
|
|
if (clickedEntry == lastEntry) {
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: change to use wrapped entry files instead because of reused components
|
|
|
|
for (const gridEntry of this.gridEntries) {
|
|
|
|
for (const child of this.childQuery) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (found) {
|
|
|
|
if (found) {
|
|
|
|
child.selected = true;
|
|
|
|
gridEntry.selected = true;
|
|
|
|
this.selectedEntries.push(child);
|
|
|
|
this.selectedEntries.push(gridEntry);
|
|
|
|
if (child === entry || child == lastEntry) {
|
|
|
|
if (gridEntry === clickedEntry || gridEntry == lastEntry) {
|
|
|
|
break;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (child === lastEntry || child === entry) {
|
|
|
|
} else if (gridEntry === lastEntry || gridEntry === clickedEntry) {
|
|
|
|
found = true;
|
|
|
|
found = true;
|
|
|
|
if (child === entry) {
|
|
|
|
if (gridEntry === clickedEntry) {
|
|
|
|
child.selected = true;
|
|
|
|
gridEntry.selected = true;
|
|
|
|
this.selectedEntries.push(child);
|
|
|
|
this.selectedEntries.push(gridEntry);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
|
|
|
|
entry.selected = true;
|
|
|
|
|
|
|
|
this.selectedEntries.push(entry);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
this.filesSelectEvent.emit(this.selectedEntries.map(entry => entry.file));
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@HostListener("window:keydown", ["$event"])
|
|
|
|
@HostListener("window:keydown", ["$event"])
|
|
|
|