File
Implements
Metadata
selector |
app-file-dir-card |
styleUrls |
./file-dir-card.component.scss |
templateUrl |
./file-dir-card.component.html |
Index
Properties
|
|
Methods
|
|
Inputs
|
|
Outputs
|
|
noEdits
|
Default value : false
|
|
Outputs
cancelled
|
Type : EventEmitter<boolean>
|
|
createDir
|
Type : EventEmitter<any>
|
|
deleteDir
|
Type : EventEmitter<any>
|
|
deleteFile
|
Type : EventEmitter<any>
|
|
Methods
addToTraceDir
|
addToTraceDir(dir: Directory)
|
|
Returns : number[]
|
addToTraceFile
|
addToTraceFile(file: File)
|
|
Parameters :
Name |
Type |
Optional |
file |
File
|
No
|
Returns : number[]
|
Private
countFiles
|
countFiles(directory: Directory)
|
|
|
createDirExec
|
createDirExec(name: string)
|
|
Parameters :
Name |
Type |
Optional |
name |
string
|
No
|
|
createFileExec
|
createFileExec(file: File)
|
|
Parameters :
Name |
Type |
Optional |
file |
File
|
No
|
|
deleteDirExec
|
deleteDirExec($event: any)
|
|
Parameters :
Name |
Type |
Optional |
$event |
any
|
No
|
|
deleteFileExec
|
deleteFileExec($event: any)
|
|
Parameters :
Name |
Type |
Optional |
$event |
any
|
No
|
|
getRouterLink
|
getRouterLink()
|
|
|
onCreateDir
|
onCreateDir()
|
|
|
onCreateFile
|
onCreateFile()
|
|
|
present
|
present(newName: string)
|
|
Parameters :
Name |
Type |
Optional |
newName |
string
|
No
|
|
creating
|
Default value : false
|
|
creatingNewSub
|
Type : number
|
Default value : 0
|
|
dirnames
|
Type : []
|
Default value : []
|
|
extensions
|
Type : []
|
Default value : ['.cpp', '.py', '.java']
|
|
filenames
|
Type : []
|
Default value : []
|
|
isErrorCreating
|
Default value : false
|
|
isErrorDeleting
|
Default value : false
|
|
isExpanded
|
Default value : false
|
|
lang
|
Type : number
|
Default value : 0
|
|
newName
|
Type : string
|
Default value : ''
|
|
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
import {File} from '../file';
import {Directory} from '../directory';
import {FileService} from '../file.service';
import {ApiService} from '../api.service';
@Component({
selector: 'app-file-dir-card',
templateUrl: './file-dir-card.component.html',
styleUrls: ['./file-dir-card.component.scss']
})
export class FileDirCardComponent implements OnInit {
@Input() isFile: boolean;
@Input() level: number;
@Input() file: File;
@Input() directory: Directory;
@Input() trace: number[];
@Input() isNew: boolean;
@Input() parentPath: string;
@Input() noEdits = false;
@Input() parentDirs: Directory[];
@Input() parentFiles: File[];
deleting: boolean;
isExpanded = false;
newName = '';
isErrorDeleting = false;
isErrorCreating = false;
creating = false;
creatingNewSub = 0;
extensions = ['.cpp', '.py', '.java'];
lang = 0;
filenames = [];
dirnames = [];
@Output() deleteFile: EventEmitter<any> = new EventEmitter();
@Output() deleteDir: EventEmitter<any> = new EventEmitter();
@Output() createDir: EventEmitter<any> = new EventEmitter();
@Output() createFile: EventEmitter<File> = new EventEmitter();
@Output() cancelled: EventEmitter<boolean> = new EventEmitter();
constructor(private fileService: FileService, private apiService: ApiService) {
}
ngOnInit(): void {
if (!this.isFile && !this.isNew) {
this.filenames = this.directory.files.map(item => item.filename);
this.dirnames = this.directory.dirs.map(item => item.name);
}
}
onDelete(): void {
this.deleting = true;
this.fileService.delete(this.isFile ? this.file : this.directory, this.isFile,
JSON.parse(this.apiService.getToken()).username, this.isFile ? 0 : this.countFiles(this.directory)).subscribe(
data => {
console.log(data);
if (this.isFile) {
this.deleteFile.emit(this.file);
} else {
this.deleteDir.emit(this.directory);
}
this.deleting = false;
}, error => {
console.log(error);
}
);
}
addToTraceDir(dir: Directory): number[] {
const arr = JSON.parse(JSON.stringify(this.trace));
arr.push(this.directory.dirs.indexOf(dir));
return arr;
}
addToTraceFile(file: File): number[] {
const arr = JSON.parse(JSON.stringify(this.trace));
arr.push(this.directory.files.indexOf(file));
return arr;
}
deleteFileExec($event: any): void {
const index = this.directory.files.indexOf($event, 0);
if (index > -1) {
this.directory.files.splice(index, 1);
}
}
deleteDirExec($event: any): void {
const index = this.directory.dirs.indexOf($event, 0);
if (index > -1) {
this.directory.dirs.splice(index, 1);
}
}
onCreateDir(): void {
this.creating = true;
this.fileService.createDirectory(JSON.parse(this.apiService.getToken()).username, this.newName, this.parentPath)
.subscribe(data => {
if (data === '0') {
this.creating = false;
this.isErrorCreating = true;
} else {
this.createDir.emit(this.newName);
}
});
}
getRouterLink(): string {
return '/arena/file/' + encodeURIComponent(this.file.path + '/' + this.file.filename + this.file.language);
}
onCreateFile(): void {
this.creating = true;
const file: File = {
username: JSON.parse(this.apiService.getToken()).username,
filename: this.newName,
language: this.extensions[this.lang],
text: '',
path: this.parentPath
};
this.fileService.upload(file, false).subscribe(data => {
if (data === '1') {
console.log(data);
this.createFile.emit(file);
} else {
console.log(data);
this.creating = false;
this.isErrorCreating = true;
}
});
}
createFileExec(file: File): void {
this.directory.files.push(file);
this.creatingNewSub = 0;
}
createDirExec(name: string): void {
this.directory.dirs.push({
name,
dirs: [],
files: [],
path: this.directory.path + this.directory.name + '/',
});
this.creatingNewSub = 0;
}
private countFiles(directory: Directory): number {
let count = directory.files.length;
for (const dir of directory.dirs) {
count += this.countFiles(dir);
}
return count;
}
present(newName: string): boolean {
if (this.isFile) {
return this.parentFiles.map(item => item.filename + item.language).includes(newName + this.extensions[this.lang]);
} else {
return this.parentDirs.map(item => item.name).includes(newName);
}
}
}
<div [style.background]="isFile ? '#002' : '#022'" [style.marginLeft]="level * 20 + 'px'" class="card">
<div *ngIf="!isNew && isFile" class="title">{{file.filename}}{{file.language}}</div>
<div *ngIf="!isNew && !isFile" class="title">{{directory.name}}</div>
<div *ngIf="!isNew && !isFile" class="dir-desc">{{directory.dirs.length}} directories, {{directory.files.length}}
files
</div>
<div *ngIf="isNew" class="title">
<input (input)="isErrorCreating = false" [(ngModel)]="newName" [disabled]="creating" [placeholder]="'Name of new ' + (isFile ? 'file' : 'directory')"
id="newFilenameInput" type="text">
<label (click)="lang = (lang + 1) % 3" *ngIf="isFile" for="newFilenameInput">{{extensions[lang]}}</label>
</div>
<div *ngIf="isNew || isFile"></div>
<div *ngIf="!isNew" class="file-buttons">
<button *ngIf="!noEdits" (click)="onDelete()" [class.disabled]="deleting || isErrorDeleting"
[disabled]="deleting || isErrorDeleting">{{isErrorDeleting ? 'Error' : (deleting ? 'Deleting...' : 'Delete')}}</button>
<button (click)="isExpanded = !isExpanded" *ngIf="!isFile">{{isExpanded ? 'Collapse' : 'Expand'}}</button>
<button (click)="isExpanded = true; creatingNewSub = 1" *ngIf="!noEdits && !isFile && level < 3" [class.disabled]="deleting" [disabled]="deleting">New Directory</button>
<button (click)="isExpanded = true; creatingNewSub = 2" *ngIf="!noEdits && !isFile" [class.disabled]="deleting" [disabled]="deleting">New File</button>
<button *ngIf="!noEdits && isFile" [class.disabled]="deleting" [disabled]="deleting"
[routerLink]="getRouterLink()">Edit
</button>
</div>
<div *ngIf="isNew" class="file-buttons">
<button (click)="cancelled.emit(true)" [class.disabled]="creating" [disabled]="creating">Cancel</button>
<button (click)="isFile ? onCreateFile() : onCreateDir()"
[class.disabled]="newName==='' || present(newName) || creating || isErrorCreating"
[disabled]="newName==='' || present(newName) || creating || isErrorCreating">{{isErrorCreating ? 'Error' : (creating ? 'Creating...' : 'Create')}}</button>
</div>
</div>
<div *ngIf="!isNew && !isFile" [style.display]="isExpanded ? 'block' : 'none'" class="subs">
<app-file-dir-card (cancelled)="creatingNewSub = 0" (createDir)="createDirExec($event)"
(createFile)="createFileExec($event)"
*ngIf="creatingNewSub !== 0" [isFile]="creatingNewSub === 2" [isNew]="true"
[parentDirs]="this.directory.dirs" [parentFiles]="this.directory.files"
[level]="level + 1" [parentPath]="directory.path + directory.name + '/'"></app-file-dir-card>
<app-file-dir-card (deleteDir)="deleteDirExec($event)" (deleteFile)="deleteFileExec($event)"
*ngFor="let dir of directory.dirs" [directory]="dir"
[isFile]="false" [isNew]="false" [level]="level + 1"
[trace]="addToTraceDir(dir)" [noEdits]="noEdits"></app-file-dir-card>
<app-file-dir-card (deleteDir)="deleteDirExec($event)" (deleteFile)="deleteFileExec($event)"
*ngFor="let file of directory.files" [file]="file"
[isFile]="true" [isNew]="false" [level]="level + 1"
[trace]="addToTraceFile(file)" [noEdits]="noEdits"></app-file-dir-card>
</div>
.card {
display: grid;
grid-template-columns: 30% 20% 50%;
height: 3em;
border-bottom: 1px solid #fff;
button {
float: right;
border: none;
user-select: none;
}
.title {
padding: 1em 20px;
input {
background: none;
border: none;
border-bottom: 1px solid #ddf;
font: inherit;
color: inherit;
width: 60%;
&::placeholder {
font-size: 0.8em;
}
}
label {
font-size: 0.9em;
padding: 5px;
background: #202;
border-radius: 5px;
cursor: pointer;
user-select: none;
}
}
.dir-desc {
padding: 1.1em 20px;
font-size: 0.8em;
}
.file-buttons {
padding: 0.7em 20px;
}
}
Legend
Html element with directive