diff --git a/src/app/app.component.ts b/src/app/app.component.ts index d67790b..22a2f0d 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -337,11 +337,10 @@ export class AppComponent implements OnDestroy { onOperationClick(operation: Operation) { if (operation instanceof ToolOperation) { - const tool = operation; + const tool = operation; if ((tool.task.operations[0].results.length > 0 && !tool.task.operations[0].lastResult.available) || (!(tool.previousOperation === null || tool.previousOperation === undefined) && tool.previousOperation.results.length > 0 && !tool.previousOperation.lastResult.available)) { if (!tool.task.operations[0].results[0].available) { - if ((tool.task.files[0].file === null || tool.task.files[0].file === undefined)) { this.alertService.showAlert('warning', `Please add the audio file "${tool.task.operations[0].results[0].fullname}" and run "${tool.title}" again.`, 10); @@ -380,7 +379,7 @@ export class AppComponent implements OnDestroy { const subj = UploadOperation.upload([tool.lastResult], url, this.httpclient); subj.subscribe((obj) => { if (obj.type === 'loadend') { - const result = obj.result; + const result = obj.result; const x2js = new X2JS(); let json: any = x2js.xml2js(result); json = json.UploadFileMultiResponse; @@ -419,7 +418,7 @@ export class AppComponent implements OnDestroy { const subj = UploadOperation.upload([tool.previousOperation.lastResult], url, this.httpclient); subj.subscribe((obj) => { if (obj.type === 'loadend') { - const result = obj.result; + const result = obj.result; const x2js = new X2JS(); let json: any = x2js.xml2js(result); json = json.UploadFileMultiResponse; @@ -465,6 +464,8 @@ export class AppComponent implements OnDestroy { this.tool_url = tool.getToolURL(); if (this.tool_url !== '') { + this.proceedings.cd.markForCheck(); + this.proceedings.cd.detectChanges(); this.toolLoader.url = tool.getToolURL(); if (!(this.toolSelectedOperation === null || this.toolSelectedOperation === undefined) && operation.id !== this.toolSelectedOperation.id) { // some operation already initialized @@ -478,6 +479,7 @@ export class AppComponent implements OnDestroy { if (operation instanceof OCTRAOperation) { operation.time.start = Date.now(); } + this.proceedings.togglePopover(false); } else { console.warn(`tool url is empty`); } @@ -491,7 +493,7 @@ export class AppComponent implements OnDestroy { onOperationHover(operation: Operation) { } - onASRLangCHanged(lang) { + onASRLangChanged(lang) { if (lang.code !== this.taskService.selectedlanguage.code) { this.taskService.selectedlanguage = lang; this.changeLanguageforAllQueuedTasks(); @@ -584,7 +586,7 @@ export class AppComponent implements OnDestroy { } public getTime(): number { - let elem: AudioInfo = this.toolSelectedOperation.task.files[0]; + let elem: AudioInfo = this.toolSelectedOperation.task.files[0]; if (!(elem.duration === null || elem.duration === undefined)) { return elem.duration.unix; diff --git a/src/app/components/proceedings/directives/proc-col-operation.directive.ts b/src/app/components/proceedings/directives/proc-col-operation.directive.ts index 45f9bbc..dc67bc1 100644 --- a/src/app/components/proceedings/directives/proc-col-operation.directive.ts +++ b/src/app/components/proceedings/directives/proc-col-operation.directive.ts @@ -69,11 +69,18 @@ export class ProcColOperationDirective implements AfterViewInit, OnChanges, OnDe // result is available if (this.operation.enabled) { + let icon = null; if (!(this.operation.mouseover && this.operation.state === 'ERROR')) { - const icon = this.operation.getStateIcon2(this.operation.state); - this.elementRef.nativeElement.innerHTML = icon; + const wrapper = this.renderer.createElement('div'); + this.renderer.setStyle(wrapper, 'display', 'inline'); + wrapper.innerHTML = this.operation.getStateIcon2(this.operation.state); + + this.renderer.listen(wrapper, 'mouseover', this.onMouseOver); + this.renderer.listen(wrapper, 'mouseenter', this.onMouseEnter); + this.renderer.listen(wrapper, 'mouseleave', this.onMouseLeave); + this.renderer.appendChild(this.elementRef.nativeElement, wrapper); } else { - const icon = this.renderer.createElement('i'); + icon = this.renderer.createElement('i'); this.renderer.addClass(icon, 'fa'); this.renderer.addClass(icon, 'fa-repeat'); this.renderer.setAttribute(icon, 'aria-hidden', 'true'); @@ -81,6 +88,7 @@ export class ProcColOperationDirective implements AfterViewInit, OnChanges, OnDe this.renderer.listen(icon, 'click', this.onRepeatIconClick); } + this.renderer.removeClass(this.elementRef.nativeElement, 'op-deactivated'); } else { // operation disabled @@ -104,7 +112,7 @@ export class ProcColOperationDirective implements AfterViewInit, OnChanges, OnDe } private clearContents() { - for (let i = 0; i < ( this.elementRef.nativeElement).children.length; i++) { + for (let i = 0; i < (this.elementRef.nativeElement).children.length; i++) { const child = this.elementRef.nativeElement.children[i]; if (!(child === null || child === undefined)) { @@ -117,6 +125,19 @@ export class ProcColOperationDirective implements AfterViewInit, OnChanges, OnDe } } + private onMouseOver = (event) => { + console.log(`MOUSEOVER PROCCOL`); + this.onOperationMouseOver.next(event); + } + + private onMouseEnter = (event) => { + this.onOperationMouseEnter.next(event); + } + + private onMouseLeave = (event) => { + this.onOperationMouseLeave.next(event); + } + private onRepeatIconClick = () => { const langObj = AppSettings.getLanguageByCode(this.entry.language); this.entry.restartFailedOperation(langObj, this.taskService.httpclient); diff --git a/src/app/components/proceedings/proceedings.component.html b/src/app/components/proceedings/proceedings.component.html index c4e6d98..bfac721 100644 --- a/src/app/components/proceedings/proceedings.component.html +++ b/src/app/components/proceedings/proceedings.component.html @@ -62,7 +62,8 @@

Start Processing

'height': popover.height + 'px', 'margin-top': popover.y + 'px', 'margin-left': (popover.x + 4) + 'px' - }" (mouseover)="popover.state = 'opened';" (mouseout)="popover.state = 'closed';" + }" (mouseenter)="popover.mouseIn = true" + (mouseleave)="popover.state = 'closed'" [borderColor]="getPopoverColor(popover.operation)" [pointer]="popover.pointer" #popoverRef> @@ -77,7 +78,7 @@

Start Processing

{{popover.operation.time.start - | date :"dd.MM.yyyy H:mm"}} + | date :"dd.MM.yyyy H:mm"}} {{calculateDuration(popover.operation.time) | time:'true'}} @@ -138,8 +139,8 @@

Start Processing

(click)="openArchiveDownload('column', operation)" [ngbTooltip]="tipContent" tooltipClass="operation-tooltip" triggers="manual" #t2="ngbTooltip" placement="bottom" - (mouseover)="toggleOperationDescription(t2)" - (mouseleave)="toggleOperationDescription(t2)" + (mouseenter)="toolTipAction('open', t2)" + (mouseleave)="toolTipAction('close', t2)" > {{operation.shortTitle}} @@ -212,9 +213,9 @@

Start Processing

[entry]="entry" [operation]="operation" - (mouseenter)="onOperationMouseEnter($event, operation)" - (mouseleave)="onOperationMouseLeave($event, operation)" - (mouseover)="onOperationMouseOver($event, operation)" + (onOperationMouseEnter)="onOperationMouseEnter($event, operation)" + (onOperationMouseLeave)="onOperationMouseLeave($event, operation)" + (onOperationMouseOver)="onOperationMouseOver($event, operation)" (mousedown)="onOperationClick($event, operation)" (click)="onRowSelected(entry, operation)" > @@ -259,9 +260,9 @@

Start Processing

[entry]="entry" [operation]="operation" - (mouseenter)="onOperationMouseEnter($event, operation)" - (mouseleave)="onOperationMouseLeave($event, operation)" - (mouseover)="onOperationMouseOver($event, operation)" + (onOperationMouseEnter)="onOperationMouseEnter($event, operation)" + (onOperationMouseLeave)="onOperationMouseLeave($event, operation)" + (onOperationMouseOver)="onOperationMouseOver($event, operation)" (mousedown)="onOperationClick($event, operation)" (click)="onRowSelected(entry, operation)" > @@ -272,9 +273,9 @@

Start Processing

[entry]="dirEntry" [operation]="operation" - (mouseenter)="onOperationMouseEnter($event, operation)" - (mouseleave)="onOperationMouseLeave($event, operation)" - (mouseover)="onOperationMouseOver($event, operation)" + (onOperationMouseEnter)="onOperationMouseEnter($event, operation)" + (onOperationMouseLeave)="onOperationMouseLeave($event, operation)" + (onOperationMouseOver)="onOperationMouseOver($event, operation)" (mousedown)="onOperationClick($event, operation)" (click)="onRowSelected(dirEntry, operation)"> diff --git a/src/app/components/proceedings/proceedings.component.ts b/src/app/components/proceedings/proceedings.component.ts index 0d347c8..774bd43 100644 --- a/src/app/components/proceedings/proceedings.component.ts +++ b/src/app/components/proceedings/proceedings.component.ts @@ -33,6 +33,7 @@ import {FilePreviewModalComponent} from '../../modals/file-preview-modal/file-pr import {DownloadModalComponent} from '../../modals/download-modal/download-modal.component'; import {G2pMausOperation} from '../../obj/operations/g2p-maus-operation'; import {ShortcutManager} from '../../obj/shortcut-manager'; +import {NgbTooltip} from '@ng-bootstrap/ng-bootstrap'; declare var window: any; @@ -59,7 +60,8 @@ export class ProceedingsComponent implements OnInit, OnDestroy, OnChanges { height: number, operation: Operation, task: Task | TaskDirectory, - pointer: string + pointer: string, + mouseIn: boolean } = { x: 0, y: 0, @@ -68,7 +70,8 @@ export class ProceedingsComponent implements OnInit, OnDestroy, OnChanges { height: 320, operation: null, task: null, - pointer: 'left' + pointer: 'left', + mouseIn: false }; @Input() taskList: TaskList = new TaskList(); @@ -97,11 +100,12 @@ export class ProceedingsComponent implements OnInit, OnDestroy, OnChanges { @ViewChild('popoverRef') public popoverRef: PopoverComponent; @ViewChild('filePreview') public filePreview: FilePreviewModalComponent; + @ViewChild('t2') public tooltip: NgbTooltip; public selectedOperation: Operation; public toolSelectedOperation: Operation; - constructor(public sanitizer: DomSanitizer, private cd: ChangeDetectorRef, public taskService: TaskService, private http: HttpClient, + constructor(public sanitizer: DomSanitizer, public cd: ChangeDetectorRef, public taskService: TaskService, private http: HttpClient, public storage: StorageService) { // Check for the various FileInfo API support. if (window.File && window.FileReader && window.FileList && window.Blob) { @@ -329,7 +333,7 @@ export class ProceedingsComponent implements OnInit, OnDestroy, OnChanges { } } else { for (let j = 0; j < entry.entries.length; j++) { - const task = entry.entries[j]; + const task = entry.entries[j]; if (task.files.length > 1) { task.files.splice(1); task.operations[1].enabled = this.taskService.operations[1].enabled; @@ -368,12 +372,21 @@ export class ProceedingsComponent implements OnInit, OnDestroy, OnChanges { } else { this.popover.state = 'closed'; } + + this.cd.markForCheck(); + this.cd.detectChanges(); } onOperationMouseEnter($event, operation: Operation) { + console.log(`MOUSE ENTERED!`); + console.log($event); // show Popover for normal operations only if (!(operation instanceof EmuOperation) && !(operation.state === TaskState.PENDING || operation.state === TaskState.SKIPPED || operation.state === TaskState.READY)) { + console.log(`show popup!`); + const icon = $event.target; + const parentNode = icon.parentNode; + this.popover.operation = operation; if (operation.protocol !== '') { this.popover.width = 500; @@ -381,16 +394,17 @@ export class ProceedingsComponent implements OnInit, OnDestroy, OnChanges { this.popover.width = 400; } this.popover.height = 230; - if (($event.target.offsetLeft + this.popover.width) < window.innerWidth) { - this.popover.x = $event.target.offsetLeft + ($event.target.offsetWidth / 2); + if ((parentNode.offsetLeft + this.popover.width) < window.innerWidth) { + this.popover.x = parentNode.offsetLeft + (parentNode.offsetWidth / 2); this.popover.pointer = ($event.layerY + this.popoverRef.height > window.innerHeight) ? 'bottom-left' : 'left'; } else { - this.popover.x = $event.target.offsetLeft - this.popover.width + ($event.target.offsetWidth / 2); + this.popover.x = parentNode.offsetLeft - this.popover.width + (parentNode.offsetWidth / 2); this.popover.pointer = ($event.layerY + this.popoverRef.height < window.innerHeight) ? 'right' : 'bottom-right'; } - this.popover.y = ($event.layerY + this.popoverRef.height > window.innerHeight) - ? $event.layerY - this.popoverRef.height : $event.layerY; + const top = icon.offsetTop + parentNode.offsetTop + icon.offsetHeight; + this.popover.y = (top + this.popoverRef.height > window.innerHeight) + ? top - this.popoverRef.height : top; this.togglePopover(true); } @@ -399,15 +413,19 @@ export class ProceedingsComponent implements OnInit, OnDestroy, OnChanges { } onOperationMouseLeave($event, operation: Operation) { - if (!(operation instanceof EmuOperation) && !(operation.state === TaskState.PENDING)) { - this.togglePopover(false); - } operation.mouseover = false; + this.popover.mouseIn = false; + setTimeout(() => { + if (!this.popover.mouseIn) { + this.togglePopover(false); + } + }, 250); operation.onMouseLeave(); } onOperationMouseOver($event, operation: Operation) { operation.mouseover = true; + this.popover.mouseIn = true; this.selectedOperation = operation; operation.onMouseOver(); this.operationhover.emit(); @@ -463,7 +481,7 @@ export class ProceedingsComponent implements OnInit, OnDestroy, OnChanges { getMailToLink(task: Task) { if (task.state === TaskState.FINISHED) { - const tool_url = ( task.operations[4]).getToolURL(); + const tool_url = (task.operations[4]).getToolURL(); let subject = 'OH-Portal Links'; let body = '' + 'Pipeline ASR->G2P->CHUNKER:\n' + task.operations[1].results[0].url + '\n\n' + @@ -587,9 +605,9 @@ export class ProceedingsComponent implements OnInit, OnDestroy, OnChanges { public onOperationClick($event, operation: Operation) { if (operation instanceof UploadOperation || operation instanceof EmuOperation) { - setTimeout(() => { - this.popover.state = 'closed'; - }, 1000); + this.popover.state = 'closed'; + this.cd.markForCheck(); + this.cd.detectChanges(); this.selectedOperation = undefined; } else { this.selectedOperation = operation; @@ -598,7 +616,6 @@ export class ProceedingsComponent implements OnInit, OnDestroy, OnChanges { } openArchiveDownload(type: 'column' | 'line', operation: Operation) { - this.selectedOperation = operation; this.content.open(type); } @@ -713,15 +730,15 @@ export class ProceedingsComponent implements OnInit, OnDestroy, OnChanges { } } - toggleOperationDescription(tooltip) { - if (tooltip.isOpen()) { - tooltip.close(); - this.cd.markForCheck(); - this.cd.detectChanges(); - } else { + toolTipAction(action: string, tooltip) { + if (action === 'open') { tooltip.open(); - this.cd.markForCheck(); - this.cd.detectChanges(); + } else { + tooltip.close(); } + + + this.cd.markForCheck(); + this.cd.detectChanges(); } } diff --git a/src/app/obj/operations/operation.ts b/src/app/obj/operations/operation.ts index b0a668d..a91c849 100644 --- a/src/app/obj/operations/operation.ts +++ b/src/app/obj/operations/operation.ts @@ -208,7 +208,7 @@ export abstract class Operation { return sanitizer.bypassSecurityTrustHtml(result); } - public getStateIcon2 = (state: TaskState): String => { + public getStateIcon2 = (state: TaskState): string => { let result = ''; switch (state) { diff --git a/src/app/obj/operations/upload-operation.ts b/src/app/obj/operations/upload-operation.ts index 712165c..f363e99 100644 --- a/src/app/obj/operations/upload-operation.ts +++ b/src/app/obj/operations/upload-operation.ts @@ -176,7 +176,7 @@ export class UploadOperation extends Operation { return sanitizer.bypassSecurityTrustHtml(result); } - public getStateIcon2 = (state: TaskState): String => { + public getStateIcon2 = (state: TaskState): string => { let result = ''; switch (state) {