diff options
Diffstat (limited to 'frontend/src/app/_elements/folder')
3 files changed, 197 insertions, 84 deletions
diff --git a/frontend/src/app/_elements/folder/folder.component.css b/frontend/src/app/_elements/folder/folder.component.css index 137a9643..2340ee8a 100644 --- a/frontend/src/app/_elements/folder/folder.component.css +++ b/frontend/src/app/_elements/folder/folder.component.css @@ -129,6 +129,8 @@ .list-view { height: 100%; overflow-y: auto; + display: flex; + flex-direction: column; } .list-item { @@ -138,6 +140,7 @@ align-items: center; justify-content: space-between; border-bottom: 1px solid var(--ns-primary); + flex-shrink: 0; } .list-item:hover { @@ -149,6 +152,15 @@ display: none; } +.list-add { + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + flex-grow: 1; + height: 100%; +} + .folder-inside { width: 100%; height: 40rem; @@ -157,7 +169,7 @@ .file-content { width: 100%; - height: 92%; + height: 100%; position: relative; } @@ -186,4 +198,8 @@ .file-button:hover { background-color: var(--ns-primary); +} + +.form-hidden { + display: none; }
\ No newline at end of file diff --git a/frontend/src/app/_elements/folder/folder.component.html b/frontend/src/app/_elements/folder/folder.component.html index 36f70c97..48b59dc8 100644 --- a/frontend/src/app/_elements/folder/folder.component.html +++ b/frontend/src/app/_elements/folder/folder.component.html @@ -1,9 +1,9 @@ <div id="folder"> <div id="tabs"> - <div id="new-file-tab" class="folder-tab p-1 rounded-top" [style]="'z-index:' + (selectedTab == TabType.NewFile ? 11 : 10) + ' ;'" [ngClass]="{'selected-tab' : selectedTab == TabType.NewFile, 'hover-tab' : hoverTab == TabType.NewFile}"> + <div id="new-file-tab" *ngIf="newFile" class="folder-tab p-1 rounded-top" [style]="'z-index:' + (selectedTab == TabType.NewFile ? 11 : 10) + ' ;'" [ngClass]="{'selected-tab' : selectedTab == TabType.NewFile, 'hover-tab' : hoverTab == TabType.NewFile}"> <mat-icon class="text-offwhite">add</mat-icon> <a class="stretched-link tab-link" (click)="selectTab(TabType.NewFile)" (mouseenter)="hoverOverTab(TabType.NewFile)" (mouseleave)="hoverOverTab(TabType.None)"> - {{tabTitles[TabType.NewFile]}} + {{newFile.name}} </a> </div> <!--<div class="folder-tab p-1 rounded-top" *ngFor="let file of filteredFiles; let i = index" [style]="'z-index:' + calcZIndex(i) + ' ;'" [ngClass]="{'selected-tab' : selectedFileIndex == i, 'hover-tab' : hoveringOverFileIndex == i}"> @@ -12,6 +12,10 @@ <div class="folder-tab p-1 rounded-top" *ngFor="let tab of tabsToShow; let i = index" [style]="'z-index:' + (selectedTab == tab ? 11 : (tabsToShow.length - i)) + ' ;'" [ngClass]="{'selected-tab' : selectedTab == tab, 'hover-tab' : hoverTab == tab}"> <a class="m-1 stretched-link tab-link" (click)="selectTab(tab)" (mouseenter)="hoverOverTab(tab)" (mouseleave)="hoverOverTab(TabType.None)">{{tabTitles[tab]}}</a> </div> + + <div class="folder-tab p-1 rounded-top" *ngIf="selectedFile" [style]="'z-index:' + (selectedTab == TabType.File ? 11 : (tabsToShow.length)) + ' ;'" [ngClass]="{'selected-tab' : selectedTab == TabType.File, 'hover-tab' : hoverTab == TabType.File}"> + <a class="m-1 stretched-link tab-link" (click)="selectTab(TabType.File)" (mouseenter)="hoverOverTab(TabType.File)" (mouseleave)="hoverOverTab(TabType.None)">{{selectedFile.name}}</a> + </div> </div> <div id="selected-content" class="rounded-bottom text-offwhite"> <div id="searchbar" *ngIf="listView"> @@ -26,20 +30,20 @@ </mat-form-field> </div> <div id="search-options"> - <div id="collapseFilters" class="collapse collapse-horizontal"> + <!-- <div id="collapseFilters" class="collapse collapse-horizontal"> <mat-icon class="text-offwhite ">timeline</mat-icon> Regresioni <mat-icon class="text-offwhite ">looks_two</mat-icon> Binarni klasifikacioni <mat-icon class="text-offwhite ">auto_awesome_motion</mat-icon> Multiklasifikacioni - </div> + </div> --> <button class="btn-clear icon-toggle" data-bs-toggle="collapse" data-bs-target="#collapseFilters" aria-expanded="false" aria-controls="collapseFilters"> <mat-icon>filter_alt</mat-icon> </button> - <div id="collapseSort" class="collapse collapse-horizontal"> + <!-- <div id="collapseSort" class="collapse collapse-horizontal"> [sort options here TODO] - </div> + </div> --> <button class="btn-clear icon-toggle" data-bs-toggle="collapse" data-bs-target="#collapseSort" aria-expanded="false" aria-controls="collapseSort"> <mat-icon>sort</mat-icon> </button> @@ -49,35 +53,37 @@ </div> </div> <!--{{fileToDisplay ? fileToDisplay.name : 'No file selected.'}} {{selectedFileIndex}} {{hoveringOverFileIndex}}--> - <div [ngSwitch]="listView" class="folder-inside bg-blur"> - <div class="file-content" [ngSwitch]="type" *ngSwitchCase="false"> - <div class="file-bottom-buttons"> - <button class="btn-clear file-button" (click)="deleteFile()"> + <div class="folder-inside bg-blur"> + <div class="file-content" [ngClass]="{'form-hidden' : listView}"> + <div class="file-bottom-buttons" *ngIf="selectedTab != TabType.NewFile"> + <button *ngIf="this.selectedFile && selectedTab == TabType.File" class="btn-clear file-button" (click)="deleteFile(this.selectedFile)"> <mat-icon>delete</mat-icon> </button> - <button class="btn-clear file-button"> - <mat-icon>link</mat-icon> - </button> - <button class="btn-clear file-button"> + <!-- <button class="btn-clear file-button"> <mat-icon>zoom_out_map</mat-icon> - </button> + </button> --> </div> - <app-form-model [forExperiment]="forExperiment" [model]="fileToDisplay" *ngSwitchCase="FolderType.Model"></app-form-model> - <app-form-dataset *ngSwitchCase="FolderType.Dataset" ></app-form-dataset> + <app-form-model [ngClass]="{'form-hidden': type != FolderType.Model}"></app-form-model> + <app-form-dataset [ngClass]="{'form-hidden': type != FolderType.Dataset}"></app-form-dataset> </div> - <div *ngSwitchCase="true" class="list-view"> - <div *ngFor="let file of filteredFiles; let i = index" class="list-item"> + <div [ngClass]="{'form-hidden' : !listView}" class="list-view"> + <div *ngFor="let file of filteredFiles; let i = index" class="list-item force-link" (click)="selectFile(file)"> <div class="mx-2"> - <a class="force-link" (click)="selectFile(i)">{{file.name}}</a> + {{file.name}} </div> <div class="mx-2 hover-hide"> {{file.lastUpdated | date}} </div> </div> + <div class="list-add" [ngSwitch]="type"> + <button mat-raised-button *ngSwitchCase="FolderType.Dataset" (click)="selectNewFile()">Dodaj {{privacy == Privacy.Public ? 'javni ' : ' '}}izvor podataka</button> + <button mat-raised-button *ngSwitchCase="FolderType.Model" (click)="selectNewFile()">Dodaj {{privacy == Privacy.Public ? 'javnu ' : ' '}}konfiguraciju neuronske mreže</button> + <button mat-raised-button *ngSwitchCase="FolderType.Experiment" routerLink="/experiment">Dodaj eksperiment</button> + </div> </div> </div> </div> - <div id="footer" [ngSwitch]="newFileSelected"> + <div id="footer" [ngSwitch]="newFileSelected" *ngIf="!listView"> <button mat-button (click)="saveNewFile()" class="bottom-button text-offwhite rounded-bottom" *ngSwitchCase="true"> <div class="f-row"> <div>Sačuvaj</div> diff --git a/frontend/src/app/_elements/folder/folder.component.ts b/frontend/src/app/_elements/folder/folder.component.ts index 06b4d893..20ca1121 100644 --- a/frontend/src/app/_elements/folder/folder.component.ts +++ b/frontend/src/app/_elements/folder/folder.component.ts @@ -1,33 +1,35 @@ -import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core'; +import { AfterViewInit, Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core'; import Dataset from 'src/app/_data/Dataset'; import { FolderFile, FolderType } from 'src/app/_data/FolderFile'; import Model from 'src/app/_data/Model'; import { DatasetsService } from 'src/app/_services/datasets.service'; -import shared from 'src/app/Shared'; +import Shared from 'src/app/Shared'; import { ModelsService } from 'src/app/_services/models.service'; import { FormDatasetComponent } from '../form-dataset/form-dataset.component'; import Experiment from 'src/app/_data/Experiment'; import { ExperimentsService } from 'src/app/_services/experiments.service'; import { PredictorsService } from 'src/app/_services/predictors.service'; +import { SignalRService } from 'src/app/_services/signal-r.service'; +import { FormModelComponent } from '../form-model/form-model.component'; @Component({ selector: 'app-folder', templateUrl: './folder.component.html', styleUrls: ['./folder.component.css'] }) -export class FolderComponent implements OnInit { +export class FolderComponent implements AfterViewInit { - @ViewChild(FormDatasetComponent) formDataset?: FormDatasetComponent; + @ViewChild(FormDatasetComponent) formDataset!: FormDatasetComponent; + @ViewChild(FormModelComponent) formModel!: FormModelComponent; @Input() folderName: string = 'Moji podaci'; - @Input() files!: FolderFile[] - newFile!: Dataset | Model; + newFile?: Dataset | Model; @Input() type: FolderType = FolderType.Dataset; - - @Input() forExperiment?: Experiment; + @Input() forExperiment!: Experiment; + @Input() startingTab!: TabType; newFileSelected: boolean = true; @@ -42,34 +44,32 @@ export class FolderComponent implements OnInit { searchTerm: string = ''; - constructor(private datasetsService: DatasetsService, private experimentsService: ExperimentsService, private modelsService: ModelsService, private predictorsService: PredictorsService) { - //PLACEHOLDER - this.forExperiment = new Experiment(); - this.forExperiment.inputColumns = ['kolona1', 'kol2', '???', 'test']; + constructor(private datasetsService: DatasetsService, private experimentsService: ExperimentsService, private modelsService: ModelsService, private predictorsService: PredictorsService, private signalRService: SignalRService) { + this.tabsToShow.forEach(tab => this.folders[tab] = []); + } - this.folders[TabType.File] = []; - this.folders[TabType.NewFile] = []; + ngAfterViewInit(): void { + this.refreshFiles(null); - this.refreshFiles(); + if (this.signalRService.hubConnection) { + this.signalRService.hubConnection.on("NotifyDataset", (dName: string, dId: string) => { + this.refreshFiles(dId); - - } - - ngOnInit(): void { - if (this.files.length > 0) - this.selectFile(0); - else { - this.selectNewFile(); + }); + } else { + console.warn("Dataset-Load: No connection!"); } } - displayFile(){ - if(this.type == FolderType.Dataset) - this.formDataset!.dataset = <Dataset>this.fileToDisplay; + displayFile() { + if (this.type == FolderType.Dataset) + this.formDataset.dataset = <Dataset>this.fileToDisplay; + else if (this.type == FolderType.Model) + this.formModel.newModel = <Model>this.fileToDisplay; } hoverOverFile(i: number) { - this.hoveringOverFileIndex = i; + /*this.hoveringOverFileIndex = i; if (i != -1) { this.fileToDisplay = this.files[i]; } else { @@ -79,7 +79,7 @@ export class FolderComponent implements OnInit { this.fileToDisplay = this.files[this.selectedFileIndex]; } } - this.displayFile(); + this.displayFile();*/ } selectNewFile() { @@ -87,20 +87,19 @@ export class FolderComponent implements OnInit { this.createNewFile(); } this.fileToDisplay = this.newFile; - this.selectedFile = this.newFile; this.newFileSelected = true; this.listView = false; - this.selectedFileChanged.emit(this.newFile); this.displayFile(); } - selectFile(index: number) { - this.selectedFile = this.filteredFiles[index]; - this.fileToDisplay = this.filteredFiles[index]; + selectFile(file?: FolderFile) { + this.selectedFile = file; + this.fileToDisplay = file; this.newFileSelected = false; this.listView = false; this.selectedFileChanged.emit(this.selectedFile); this.displayFile(); + this.selectTab(TabType.File); } createNewFile() { @@ -115,9 +114,22 @@ export class FolderComponent implements OnInit { this.okPressed.emit(); } - refreshFiles(){ + _initialized: boolean = false; + + refreshFiles(selectedDatasetId: string | null) { + this.tabsToShow.forEach(tab => { + this.folders[tab] = []; + }) + this.datasetsService.getMyDatasets().subscribe((datasets) => { this.folders[TabType.MyDatasets] = datasets; + if (selectedDatasetId) { + this.selectFile(datasets.filter(x => x._id == selectedDatasetId)[0]); + } + }); + + this.experimentsService.getMyExperiments().subscribe((experiments) => { + this.folders[TabType.MyExperiments] = experiments; }); this.datasetsService.getPublicDatasets().subscribe((datasets) => { @@ -125,6 +137,7 @@ export class FolderComponent implements OnInit { }); this.modelsService.getMyModels().subscribe((models) => { + console.log(models); this.folders[TabType.MyModels] = models; }); @@ -137,20 +150,40 @@ export class FolderComponent implements OnInit { this.folders[TabType.MyExperiments] = experiments; }); - this.files = []; - - this.filteredFiles.length = 0; - this.filteredFiles.push(...this.files); + if (!this._initialized) { + this.files = this.folders[this.startingTab]; + this.filteredFiles = []; + this.selectTab(this.startingTab); + this._initialized = true; + } this.searchTermsChanged(); - } saveNewFile() { - if(this.type == FolderType.Dataset) - this.formDataset!.uploadDataset(); + switch (this.type) { + case FolderType.Dataset: + this.formDataset!.uploadDataset((dataset: Dataset) => { + Shared.openDialog("Obaveštenje", "Uspešno ste dodali novi izvor podataka u kolekciju. Molimo sačekajte par trenutaka da se procesira."); + this.refreshFiles(dataset._id); + }, + () => { + Shared.openDialog("Neuspeo pokušaj!", "Izvor podataka sa unetim nazivom već postoji u Vašoj kolekciji. Izmenite naziv ili iskoristite postojeći dataset."); + }); + break; + case FolderType.Model: + this.modelsService.addModel(this.formModel.newModel).subscribe(model => { + this.formModel.newModel = model; + Shared.openDialog("Obaveštenje", "Uspešno ste dodali novu konfiguraciju neuronske mreže u kolekciju."); + this.refreshFiles(null); // todo select model + }, (err) => { + Shared.openDialog("Neuspeo pokušaj!", "Konfiguracija neuronske mreže sa unetim nazivom već postoji u Vašoj kolekciji. Izmenite naziv ili iskoristite postojeću konfiguraciju."); + }); + break; + } } + /*calcZIndex(i: number) { let zIndex = (this.files.length - i - 1) if (this.selectedFileIndex == i) @@ -159,7 +192,7 @@ export class FolderComponent implements OnInit { zIndex = this.files.length + 3; return zIndex; } - + newFileZIndex() { return (this.files.length + 1); }*/ @@ -172,25 +205,47 @@ export class FolderComponent implements OnInit { filteredFiles: FolderFile[] = []; searchTermsChanged() { + if (!this.files) return; this.filteredFiles.length = 0; this.filteredFiles.push(...this.files.filter((file) => file.name.toLowerCase().includes(this.searchTerm.toLowerCase()))); - if (this.selectedFile) { + /*if (this.selectedFile) { if (!this.filteredFiles.includes(this.selectedFile)) { - this.selectFile(-1); + if (this.hoverTab === TabType.None && this.getFolderType(this.selectedTab) === this.type) { + this.selectFile(undefined); + console.log(this.getFolderType(this.selectedTab), this.type); + } } else { - this.selectedFileIndex = this.filteredFiles.indexOf(this.selectedFile); + //this.selectedFileIndex = this.filteredFiles.indexOf(this.selectedFile); } - } + }*/ } - listView: boolean = false; + listView: boolean = true; toggleListView() { this.listView = !this.listView; } - deleteFile() { + deleteFile(file: FolderFile) { console.log('delete'); + switch (this.type) { + case FolderType.Dataset: + this.datasetsService.deleteDataset(<Dataset>file).subscribe((response) => { + console.log(response); + }); + break; + case FolderType.Model: + this.modelsService.deleteModel(<Model>file).subscribe((response) => { + console.log(response); + }); + break; + case FolderType.Experiment: + // this.experimentsService.deleteExperiment(<Model>file).subscribe((response) => { + // console.log(response); + // }); + //todo delete za predictor + break; + } } folders: { [tab: number]: FolderFile[] } = {}; @@ -206,51 +261,87 @@ export class FolderComponent implements OnInit { }; FolderType = FolderType; - + Privacy = Privacy; TabType = TabType; + privacy: Privacy = Privacy.Private; + @Input() tabsToShow: TabType[] = [ TabType.MyDatasets, TabType.PublicDatasets, TabType.MyModels, TabType.PublicModels, - TabType.MyExperiments, - TabType.File + TabType.MyExperiments ] @Input() selectedTab: TabType = TabType.NewFile; hoverTab: TabType = TabType.None; selectTab(tab: TabType) { - this.checkListView(tab); - this.selectedTab = tab; - this.files = this.folders[tab]; + setTimeout(() => { + if (tab == TabType.NewFile) { + this.selectNewFile(); + } - this.searchTermsChanged(); + this.listView = this.getListView(tab); + this.type = this.getFolderType(tab); + this.privacy = this.getPrivacy(tab); + this.selectedTab = tab; + this.files = this.folders[tab]; + + if (tab !== TabType.File && tab !== TabType.NewFile) + this.searchTermsChanged(); + }); } - checkListView(tab: TabType) { + getListView(tab: TabType) { switch (tab) { case TabType.File: case TabType.NewFile: case TabType.None: - this.listView = false; - break; + return false; case TabType.MyExperiments: case TabType.MyDatasets: case TabType.MyModels: case TabType.PublicDatasets: case TabType.PublicModels: - this.listView = true; - break; + return true; + default: + return false; + } + } + + getFolderType(tab: TabType) { + switch (tab) { + case TabType.MyExperiments: + return FolderType.Experiment; + case TabType.MyDatasets: + case TabType.PublicDatasets: + return FolderType.Dataset; + case TabType.MyModels: + case TabType.PublicModels: + return FolderType.Model; + default: + return this.type; + } + } + + getPrivacy(tab: TabType) { + switch (tab) { + case TabType.PublicDatasets: + case TabType.PublicModels: + return Privacy.Public; + default: + return Privacy.Private; } } hoverOverTab(tab: TabType) { - this.checkListView(tab); + this.listView = this.getListView(tab); + this.privacy = this.getPrivacy(tab); this.hoverTab = tab; if (tab == TabType.None) { - this.checkListView(this.selectedTab); + this.listView = this.getListView(this.selectedTab); this.files = this.folders[this.selectedTab]; } else { this.files = this.folders[tab]; |