Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
263701c499 |
@@ -1,8 +1,10 @@
|
|||||||
<div [attr.class]="layout | async">
|
<div [attr.class]="layout | async">
|
||||||
<div class="tfw-grid-main-components">
|
<div class="tfw-grid-main-components">
|
||||||
<div class="tfw-header"><app-header></app-header></div>
|
<div class="tfw-header"><app-header></app-header></div>
|
||||||
<div [ngClass]="{'hide-attribute': hideMessages | async}" class="tfw-messages">
|
<div [ngClass]="{'hide-attribute': hideMessages | async}"
|
||||||
<app-messages></app-messages>
|
class="tfw-messages"
|
||||||
|
#tfwmessages>
|
||||||
|
<app-messages (newMessageEvent)="scrollMessagesToBottom()"></app-messages>
|
||||||
</div>
|
</div>
|
||||||
<div class="tfw-web tao-grid-top-left"
|
<div class="tfw-web tao-grid-top-left"
|
||||||
[ngClass]="{'deploy-blur': deploying || (polling | async)}">
|
[ngClass]="{'deploy-blur': deploying || (polling | async)}">
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import { DashboardConfigService } from '../services/config.service';
|
|||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
import { delay, retryWhen, tap } from 'rxjs/operators';
|
import { delay, retryWhen, tap } from 'rxjs/operators';
|
||||||
import { FSMUpdateService } from '../services/fsmupdate.service';
|
import { FSMUpdateService } from '../services/fsmupdate.service';
|
||||||
import { MessagesComponent } from '../messages/messages.component';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-dashboard',
|
selector: 'app-dashboard',
|
||||||
@@ -19,7 +18,7 @@ export class DashboardComponent implements OnInit, OnDestroy {
|
|||||||
polling = new BehaviorSubject<boolean>(false);
|
polling = new BehaviorSubject<boolean>(false);
|
||||||
deploymentNotificationSubscription: Subscription;
|
deploymentNotificationSubscription: Subscription;
|
||||||
@ViewChild('webiframe', {static: false}) webiframe: ElementRef;
|
@ViewChild('webiframe', {static: false}) webiframe: ElementRef;
|
||||||
@ViewChild(MessagesComponent, {static: false}) messages: MessagesComponent;
|
@ViewChild('tfwmessages', {static: false}) messages: ElementRef;
|
||||||
@ViewChild('urlbar', {static: false}) urlbar: ElementRef;
|
@ViewChild('urlbar', {static: false}) urlbar: ElementRef;
|
||||||
|
|
||||||
layout = this.configService.layout;
|
layout = this.configService.layout;
|
||||||
@@ -70,7 +69,7 @@ export class DashboardComponent implements OnInit, OnDestroy {
|
|||||||
subscribeResizeOnLayoutChange() {
|
subscribeResizeOnLayoutChange() {
|
||||||
this.configService.layout.subscribe(() => {
|
this.configService.layout.subscribe(() => {
|
||||||
this.emitResizeEvent();
|
this.emitResizeEvent();
|
||||||
setTimeout(() => this.messages.scrollToBottom(), 0);
|
setTimeout(() => this.scrollMessagesToBottom(), 0);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,7 +99,7 @@ export class DashboardComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
reloadIframeHandler(message: WebSocketMessage) {
|
reloadIframeHandler(message: WebSocketMessage) {
|
||||||
setTimeout(() => this.reloadIframe(), 200);
|
setTimeout(() => this.reloadIframeNoSubmit(), 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
setLayout(layout: string) {
|
setLayout(layout: string) {
|
||||||
@@ -115,7 +114,14 @@ export class DashboardComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
reloadIframe() {
|
reloadIframe() {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.webiframe.nativeElement.contentWindow.frames.location.href = this.iframeUrl.value;
|
this.webiframe.nativeElement.contentWindow.location.reload(true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
reloadIframeNoSubmit() {
|
||||||
|
// Sometimes it is needed to reload the iframe without resending the previous form data
|
||||||
|
setTimeout(() => {
|
||||||
|
this.webiframe.nativeElement.contentWindow.location = this.webiframe.nativeElement.contentWindow.location.href;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,16 +132,22 @@ export class DashboardComponent implements OnInit, OnDestroy {
|
|||||||
this.terminalMenuItem.next(item);
|
this.terminalMenuItem.next(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scrollMessagesToBottom() {
|
||||||
|
const element = this.messages.nativeElement;
|
||||||
|
// This must be done in the Angular event loop to avoid messing up
|
||||||
|
// change detection (not in the template like ConsoleComponent does)
|
||||||
|
element.scrollTop = element.scrollHeight;
|
||||||
|
}
|
||||||
|
|
||||||
iframeLoad() {
|
iframeLoad() {
|
||||||
if (this.webiframe && this.iframeUrl.value) {
|
if (this.webiframe && this.iframeUrl.value) {
|
||||||
const href = this.webiframe.nativeElement.contentWindow.frames.location.href;
|
// This hack deals with Firefox iframes having a valid src,
|
||||||
const match = href.match(/.*?\/\/.*?(\/.*)/);
|
// but 'about:blank' contentWindow on (load) events
|
||||||
if (match !== null) {
|
setTimeout(() => {
|
||||||
// iframes on Firefox can have an about:blank
|
const href = this.webiframe.nativeElement.contentWindow.frames.location.href;
|
||||||
// contentWindow after firing a (load) event
|
const niceURL = href.match(/.*?\/\/.*?(\/.*)/)[1];
|
||||||
const niceURL = match[1];
|
|
||||||
this.actualIframeUrl = niceURL;
|
this.actualIframeUrl = niceURL;
|
||||||
}
|
}, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,7 +160,7 @@ export class DashboardComponent implements OnInit, OnDestroy {
|
|||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.iframeUrl.next(this.urlbar.nativeElement.value);
|
this.webiframe.nativeElement.contentWindow.frames.location.href = this.urlbar.nativeElement.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
reloadIframeWhenResponseOk() {
|
reloadIframeWhenResponseOk() {
|
||||||
@@ -161,10 +173,6 @@ export class DashboardComponent implements OnInit, OnDestroy {
|
|||||||
errors.pipe(
|
errors.pipe(
|
||||||
tap(
|
tap(
|
||||||
response => {
|
response => {
|
||||||
if (this.iframeUrl.value === '') {
|
|
||||||
this.iframeReloadSubscription.unsubscribe();
|
|
||||||
this.polling.next(false);
|
|
||||||
}
|
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
this.iframeReloadSubscription.unsubscribe();
|
this.iframeReloadSubscription.unsubscribe();
|
||||||
this.polling.next(false);
|
this.polling.next(false);
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
import { WebSocketMessage } from './websocket-message';
|
import { WebSocketMessage } from './websocket-message';
|
||||||
|
|
||||||
|
export interface MessageConfig extends WebSocketMessage {
|
||||||
|
originator?: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface MessageData {
|
export interface MessageData {
|
||||||
originator?: string;
|
originator?: string;
|
||||||
timestamp?: Date;
|
timestamp?: Date;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { ChangeDetectorRef, Component, OnInit, EventEmitter, Output, ElementRef } from '@angular/core';
|
import { ChangeDetectorRef, Component, OnInit, EventEmitter, Output } from '@angular/core';
|
||||||
import { MessageData, Message } from '../message-types/bot-messages';
|
import { MessageData, Message } from '../message-types/bot-messages';
|
||||||
import { MarkdownService } from '../services/markdown.service';
|
import { MarkdownService } from '../services/markdown.service';
|
||||||
import { WebSocketService } from '../services/websocket.service';
|
import { WebSocketService } from '../services/websocket.service';
|
||||||
@@ -19,8 +19,7 @@ export class MessagesComponent implements OnInit {
|
|||||||
constructor(
|
constructor(
|
||||||
private markdownService: MarkdownService,
|
private markdownService: MarkdownService,
|
||||||
private websocketService: WebSocketService,
|
private websocketService: WebSocketService,
|
||||||
private changeDetectorRef: ChangeDetectorRef,
|
private changeDetectorRef: ChangeDetectorRef
|
||||||
private ref: ElementRef
|
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
@@ -28,7 +27,6 @@ export class MessagesComponent implements OnInit {
|
|||||||
message => {
|
message => {
|
||||||
this.writeMessage(message);
|
this.writeMessage(message);
|
||||||
this.newMessageEvent.emit();
|
this.newMessageEvent.emit();
|
||||||
this.scrollToBottom();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this.websocketService.connect();
|
this.websocketService.connect();
|
||||||
@@ -43,11 +41,6 @@ export class MessagesComponent implements OnInit {
|
|||||||
this.changeDetectorRef.detectChanges();
|
this.changeDetectorRef.detectChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
scrollToBottom() {
|
|
||||||
const element = this.ref.nativeElement.parentElement;
|
|
||||||
element.scrollTop = element.scrollHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
transformMessage(message: MessageData) {
|
transformMessage(message: MessageData) {
|
||||||
message.message = this.convertMarkdownToHTML(message.message);
|
message.message = this.convertMarkdownToHTML(message.message);
|
||||||
if (!message.timestamp) {
|
if (!message.timestamp) {
|
||||||
|
|||||||
Reference in New Issue
Block a user