mirror of
https://github.com/avatao-content/frontend-tutorial-framework
synced 2025-07-12 14:36:23 +00:00
Make whole frontend dynamically configurable to avoid rebuilds
This commit is contained in:
@ -1,31 +1,30 @@
|
||||
<div [attr.class]="layout">
|
||||
<div [attr.class]="layout | async">
|
||||
<div class="tfw-grid-main-components">
|
||||
<div class="tfw-header"><app-header></app-header></div>
|
||||
<div [ngClass]="{'hide-attribute': hideMessages}"
|
||||
<div [ngClass]="{'hide-attribute': hideMessages | async}"
|
||||
class="tfw-messages"
|
||||
#tfwmessages>
|
||||
<app-messages (newMessageEvent)="scrollMessagesToBottom()"></app-messages>
|
||||
</div>
|
||||
<div class="tfw-web tao-grid-top-left"
|
||||
[ngClass]="{'deploy-blur': deploying || polling}">
|
||||
<app-web *ngIf="!iframeUrl"></app-web>
|
||||
<div *ngIf="showUrlBar" class="urlbar-container">
|
||||
<button class="refresh btn btn-sm rounded-circle" (click)="reloadIframe()">↻</button>
|
||||
<input type="text"
|
||||
#urlbar
|
||||
class="urlbar form-control"
|
||||
value="{{actualIframeUrl}}"
|
||||
(keyup.enter)="changeIframeURL()">
|
||||
<button class="go btn btn-sm rounded-circle" (click)="changeIframeURL()">⇨</button>
|
||||
</div>
|
||||
<div *ngIf="iframeUrl" class="iframe-container">
|
||||
<iframe class="iframe"
|
||||
#webiframe
|
||||
scrolling="yes"
|
||||
frameborder="0"
|
||||
(load)="iframeLoad()"
|
||||
[src]="iframeUrl | safe">
|
||||
</iframe>
|
||||
<div class="iframe-container">
|
||||
<div *ngIf="showUrlBar | async" class="urlbar-container">
|
||||
<button class="refresh btn btn-sm rounded-circle" (click)="reloadIframe()">↻</button>
|
||||
<input type="text"
|
||||
#urlbar
|
||||
class="urlbar form-control"
|
||||
value="{{actualIframeUrl}}"
|
||||
(keyup.enter)="changeIframeURL()">
|
||||
<button class="go btn btn-sm rounded-circle" (click)="changeIframeURL()">⇨</button>
|
||||
</div>
|
||||
<iframe class="iframe"
|
||||
#webiframe
|
||||
scrolling="yes"
|
||||
frameborder="0"
|
||||
(load)="iframeLoad()"
|
||||
[src]="iframeUrl | async | safe">
|
||||
</iframe>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tfw-ide">
|
||||
@ -35,17 +34,17 @@
|
||||
<div class="btn-group btn-group-sm flex-wrap tao-grid-center-left tfw-console-terminal-menu">
|
||||
<button class="tfw-console-terminal-menu-button"
|
||||
(click)="selectTerminalMenuItem('terminal')"
|
||||
[class.selected]="selectedTerminalMenuItem === 'terminal'">TERMINAL</button>
|
||||
[class.selected]="(terminalMenuItem | async) === 'terminal'">TERMINAL</button>
|
||||
<button class="tfw-console-terminal-menu-button"
|
||||
(click)="selectTerminalMenuItem('console')"
|
||||
[class.selected]="selectedTerminalMenuItem === 'console'">CONSOLE</button>
|
||||
[class.selected]="(terminalMenuItem | async) === 'console'">CONSOLE</button>
|
||||
</div>
|
||||
<hr>
|
||||
<app-terminal [class.hidden]="selectedTerminalMenuItem !== 'terminal'"></app-terminal>
|
||||
<app-console [class.hidden]="selectedTerminalMenuItem !== 'console'"></app-console>
|
||||
<app-terminal [class.hidden]="(terminalMenuItem | async) !== 'terminal'"></app-terminal>
|
||||
<app-console [class.hidden]="(terminalMenuItem | async) !== 'console'"></app-console>
|
||||
</div>
|
||||
<div class="tfw-sidebar">
|
||||
<app-sidebar (layoutChanged)="setLayout($event)" [layout]="layout"></app-sidebar>
|
||||
<app-sidebar (layoutChanged)="setLayout($event)" [layout]="layout | async"></app-sidebar>
|
||||
</div>
|
||||
|
||||
<div class="tfw-terminal-footer"></div>
|
||||
|
@ -3,9 +3,7 @@ import { DeploymentNotificationService } from '../services/deployment-notificati
|
||||
import { Subscription } from 'rxjs';
|
||||
import { WebSocketService } from '../services/websocket.service';
|
||||
import { WebSocketMessage } from '../message-types/websocket-message';
|
||||
import { HideMessagesMessage, LayoutMessage, TerminalMenuItemMessage } from '../message-types/dashboard-messages';
|
||||
import { config } from '../config';
|
||||
import { LogMessage } from '../message-types/log-message';
|
||||
import { DashboardConfigService } from '../services/config.service';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { delay, retryWhen, tap } from 'rxjs/operators';
|
||||
|
||||
@ -18,22 +16,19 @@ export class DashboardComponent implements OnInit, OnDestroy {
|
||||
deploying = false;
|
||||
polling = false;
|
||||
deploymentNotificationSubscription: Subscription;
|
||||
@ViewChild('webiframe', {static: true}) webiframe: ElementRef;
|
||||
@ViewChild('tfwmessages', {static: true}) messages: ElementRef;
|
||||
@ViewChild('urlbar', {static: true}) urlbar: ElementRef;
|
||||
@ViewChild('webiframe', {static: false}) webiframe: ElementRef;
|
||||
@ViewChild('tfwmessages', {static: false}) messages: ElementRef;
|
||||
@ViewChild('urlbar', {static: false}) urlbar: ElementRef;
|
||||
|
||||
layout: string = config.dashboard.currentLayout;
|
||||
hideMessages: boolean = config.dashboard.hideMessages;
|
||||
iframeUrl: string = config.dashboard.iframeUrl;
|
||||
showUrlBar = config.dashboard.showUrlBar;
|
||||
actualIframeUrl: string = this.iframeUrl;
|
||||
selectedTerminalMenuItem: string = config.dashboard.terminalOrConsole;
|
||||
layout = this.configService.layout;
|
||||
hideMessages = this.configService.hideMessages;
|
||||
showUrlBar = this.configService.showUrlBar;
|
||||
iframeUrl = this.configService.iframeUrl;
|
||||
actualIframeUrl = this.iframeUrl.value;
|
||||
terminalMenuItem = this.configService.terminalMenuItem;
|
||||
iframeReloadSubscription: Subscription;
|
||||
|
||||
command_handlers = {
|
||||
'dashboard.layout': this.layoutHandler.bind(this),
|
||||
'dashboard.hideMessages': this.hideMessagesHandler.bind(this),
|
||||
'dashboard.terminalMenuItem': this.terminalMenuItemHandler.bind(this),
|
||||
'dashboard.reloadFrontend': this.reloadFrontendHandlder.bind(this),
|
||||
'dashboard.reloadIframe': this.reloadIframeHandler.bind(this)
|
||||
};
|
||||
@ -41,13 +36,20 @@ export class DashboardComponent implements OnInit, OnDestroy {
|
||||
constructor(private deploymentNotificationService: DeploymentNotificationService,
|
||||
private webSocketService: WebSocketService,
|
||||
private changeDetectorRef: ChangeDetectorRef,
|
||||
private http: HttpClient) {}
|
||||
private http: HttpClient,
|
||||
private configService: DashboardConfigService) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.webSocketService.connect();
|
||||
this.configService.init();
|
||||
this.subscribeResizeOnLayoutChange();
|
||||
this.initCommandHandling();
|
||||
this.initDeploymentNotifications();
|
||||
this.sendReadyIfNeeded();
|
||||
this.sendReady();
|
||||
}
|
||||
|
||||
subscribeResizeOnLayoutChange() {
|
||||
this.configService.layout.subscribe(() => this.emitResizeEvent());
|
||||
}
|
||||
|
||||
initCommandHandling() {
|
||||
@ -61,7 +63,7 @@ export class DashboardComponent implements OnInit, OnDestroy {
|
||||
this.deploymentNotificationSubscription = this.deploymentNotificationService.deploying.subscribe(
|
||||
(deploying) => {
|
||||
this.deploying = deploying;
|
||||
if (!deploying && config.ide.reloadIframeOnDeploy) {
|
||||
if (!deploying && this.configService.reloadIframeOnDeploy.value) {
|
||||
if (this.polling) {
|
||||
this.iframeReloadSubscription.unsubscribe();
|
||||
}
|
||||
@ -70,26 +72,8 @@ export class DashboardComponent implements OnInit, OnDestroy {
|
||||
});
|
||||
}
|
||||
|
||||
sendReadyIfNeeded() {
|
||||
if (config.dashboard.sendReadyAfterPageReload) {
|
||||
setTimeout(() => this.webSocketService.send({'key': 'frontend.ready'}));
|
||||
}
|
||||
}
|
||||
|
||||
layoutHandler(message: LayoutMessage) {
|
||||
if (config.dashboard.enabledLayouts.includes(message.value)) {
|
||||
this.setLayout(message.value);
|
||||
} else {
|
||||
console.log('Invalid ide layout "' + message.value + '" received!');
|
||||
}
|
||||
}
|
||||
|
||||
hideMessagesHandler(message: HideMessagesMessage) {
|
||||
this.hideMessages = message.value;
|
||||
}
|
||||
|
||||
terminalMenuItemHandler(message: TerminalMenuItemMessage) {
|
||||
this.selectTerminalMenuItem(message.value);
|
||||
sendReady() {
|
||||
setTimeout(() => this.webSocketService.send({'key': 'frontend.ready'}));
|
||||
}
|
||||
|
||||
reloadFrontendHandlder(message: WebSocketMessage) {
|
||||
@ -101,7 +85,11 @@ export class DashboardComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
setLayout(layout: string) {
|
||||
this.layout = layout;
|
||||
this.layout.next(layout);
|
||||
this.emitResizeEvent();
|
||||
}
|
||||
|
||||
emitResizeEvent() {
|
||||
// We need to trigger a 'resize' event manually, otherwise editor stays collapsed
|
||||
// editor 'resize' event listener requires a parameter of force=true
|
||||
setTimeout(() => window.dispatchEvent(new Event('resize', {force: true} as any)), 0);
|
||||
@ -124,7 +112,7 @@ export class DashboardComponent implements OnInit, OnDestroy {
|
||||
if (!item.match('(terminal|console)')) {
|
||||
return;
|
||||
}
|
||||
this.selectedTerminalMenuItem = item;
|
||||
this.terminalMenuItem.next(item);
|
||||
}
|
||||
|
||||
scrollMessagesToBottom(): void {
|
||||
|
Reference in New Issue
Block a user