Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4f3a6057a4 | ||
|
|
ea5bf30a95 | ||
|
|
d8545c48be | ||
|
|
031a9916a0 |
+2
-1
@@ -5,7 +5,8 @@
|
||||
"scripts": {
|
||||
"ng": "ng",
|
||||
"start": "ng serve --proxy-config proxy.conf.json",
|
||||
"build": "ng build --prod --aot --build-optimizer"
|
||||
"build": "ng build --prod --aot --build-optimizer",
|
||||
"lint": "ng lint --fix"
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
|
||||
@@ -17,7 +17,7 @@ import { TerminalComponent } from './terminal/terminal.component';
|
||||
import { AppRoutingModule } from './app-routing.module';
|
||||
import { TestmessengerComponent } from './testmessenger/testmessenger.component';
|
||||
import { DeploymentNotificationService } from './services/deployment-notification.service';
|
||||
import { SafePipe } from './pipes/safe.pipe';
|
||||
import { SafePipe, SafeHtmlPipe } from './pipes/safe.pipe';
|
||||
import { ConsoleComponent } from './console/console.component';
|
||||
import { MonacoEditorModule } from 'ngx-monaco-editor';
|
||||
import {
|
||||
@@ -41,6 +41,7 @@ import { LoaderComponent } from './loader/loader.component';
|
||||
DashboardComponent,
|
||||
TestmessengerComponent,
|
||||
SafePipe,
|
||||
SafeHtmlPipe,
|
||||
ConsoleComponent,
|
||||
LoaderComponent
|
||||
],
|
||||
|
||||
@@ -32,6 +32,7 @@ export class IdeComponent implements OnInit {
|
||||
files: string[];
|
||||
filename = '';
|
||||
lastFilename = '';
|
||||
reloadFile = false;
|
||||
code = 'Loading your file...';
|
||||
|
||||
codeState = CodeState.SAVED;
|
||||
@@ -85,10 +86,18 @@ export class IdeComponent implements OnInit {
|
||||
}
|
||||
|
||||
reloadHandler(message: WebSocketMessage) {
|
||||
this.requestCode();
|
||||
if (!this.reloadFile) {
|
||||
this.reloadFile = true;
|
||||
this.requestCode();
|
||||
}
|
||||
}
|
||||
|
||||
readHandler(message: IDEMessage) {
|
||||
if (!this.reloadFile && message.reload) {
|
||||
return;
|
||||
}
|
||||
this.reloadFile = false;
|
||||
|
||||
if (this.codeState === CodeState.SAVED) {
|
||||
if (this.filename !== message.filename) {
|
||||
this.filename = message.filename;
|
||||
@@ -189,7 +198,8 @@ export class IdeComponent implements OnInit {
|
||||
requestCode() {
|
||||
this.webSocketService.send({
|
||||
'key': 'ide.read',
|
||||
'filename': this.filename
|
||||
'filename': this.filename,
|
||||
'reload': this.reloadFile
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,4 +4,5 @@ export interface IDEMessage extends WebSocketMessage {
|
||||
filename: string;
|
||||
content?: string;
|
||||
files?: string[];
|
||||
reload?: boolean;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<div class="tao-grid-center-left originator">{{message.originator}}</div>
|
||||
<div class="timestamp tao-grid-center-right">{{message.timestamp | date:'HH:mm:ss'}}</div>
|
||||
</div>
|
||||
<div class="tfw-grid-message-body" [innerHtml]="message.message"></div>
|
||||
<div class="tfw-grid-message-body" [innerHtml]="message.message | safeHtml"></div>
|
||||
</div>
|
||||
<div *ngIf="showTypingIndicator"
|
||||
class="tfw-grid-message jumping-circle-container"
|
||||
|
||||
@@ -11,3 +11,14 @@ export class SafePipe implements PipeTransform {
|
||||
return this.sanitizer.bypassSecurityTrustResourceUrl(value);
|
||||
}
|
||||
}
|
||||
|
||||
@Pipe({
|
||||
name: 'safeHtml'
|
||||
})
|
||||
export class SafeHtmlPipe implements PipeTransform {
|
||||
constructor(private sanitized: DomSanitizer) {}
|
||||
|
||||
transform(value) {
|
||||
return this.sanitized.bypassSecurityTrustHtml(value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ export class DashboardConfigService extends ConfigServiceBase {
|
||||
|
||||
layout = new BehaviorSubject<string>('terminal-ide-web');
|
||||
hideMessages = new BehaviorSubject<boolean>(false);
|
||||
iframeUrl = new BehaviorSubject<string>('/webservice');
|
||||
iframeUrl = new BehaviorSubject<string>('');
|
||||
showUrlBar = new BehaviorSubject<boolean>(false);
|
||||
terminalMenuItem = new BehaviorSubject<string>('terminal');
|
||||
reloadIframeOnDeploy = new BehaviorSubject<boolean>(false);
|
||||
|
||||
@@ -8,11 +8,16 @@ export class TerminadoService {
|
||||
xterm: Terminal;
|
||||
ws: WebSocket;
|
||||
attached = false;
|
||||
private dataListener: any;
|
||||
private resizeListener: any;
|
||||
|
||||
constructor() {
|
||||
Terminal.applyAddon(fit);
|
||||
Terminal.applyAddon(terminado);
|
||||
this.xterm = new Terminal({
|
||||
this.xterm = this.createTerminal();
|
||||
}
|
||||
|
||||
createTerminal() {
|
||||
return new Terminal({
|
||||
theme: {
|
||||
foreground: '#ffffff',
|
||||
background: '#0C0C0C', // $tao-gray-800
|
||||
@@ -37,26 +42,52 @@ export class TerminadoService {
|
||||
},
|
||||
fontSize: 14
|
||||
});
|
||||
|
||||
const wsproto = (location.protocol === 'https:') ? 'wss://' : 'ws://';
|
||||
this.ws = new WebSocket(wsproto + window.location.host + '/terminal');
|
||||
}
|
||||
|
||||
attach(element: HTMLElement) {
|
||||
if (this.attached) {
|
||||
return;
|
||||
}
|
||||
|
||||
const wsproto = (location.protocol === 'https:') ? 'wss://' : 'ws://';
|
||||
this.ws = new WebSocket(wsproto + window.location.host + '/terminal');
|
||||
|
||||
this.ws.onopen = () => {
|
||||
(<any>this.xterm).terminadoAttach(this.ws);
|
||||
this.attached = true;
|
||||
this.xterm = this.createTerminal();
|
||||
this.xterm.open(element);
|
||||
this.fit();
|
||||
this.xterm.blur();
|
||||
this.attached = true;
|
||||
// In order to reset the terminal state after a broken socket, we need to register the listeners manually.
|
||||
(<any>this.xterm)._core.register(this.dataListener = this.xterm.onData(data => {
|
||||
this.ws.send(JSON.stringify(['stdin', data]));
|
||||
}));
|
||||
(<any>this.xterm)._core.register(this.resizeListener = this.xterm.onResize((size: { rows: number, cols: number }) => {
|
||||
this.ws.send(JSON.stringify(['set_size', size.rows, size.cols]));
|
||||
}));
|
||||
};
|
||||
|
||||
this.ws.onclose = () => {
|
||||
this.detach();
|
||||
this.xterm.destroy();
|
||||
this.attach(element);
|
||||
};
|
||||
|
||||
this.ws.onmessage = msg => {
|
||||
const data = JSON.parse(msg.data);
|
||||
if (data[0] === 'stdout') {
|
||||
this.xterm.write(data[1]);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
detach() {
|
||||
(<any>this.xterm).terminadoDetach(this.ws);
|
||||
this.xterm.destroy();
|
||||
this.ws.close();
|
||||
if (!this.attached) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.attached = false;
|
||||
this.dataListener.dispose();
|
||||
this.resizeListener.dispose();
|
||||
}
|
||||
|
||||
fit() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { Observable, Subject, Subscription } from 'rxjs';
|
||||
import { webSocket, WebSocketSubject } from 'rxjs/webSocket';
|
||||
import { filter, map } from 'rxjs/operators';
|
||||
import { WebSocketMessage } from '../message-types/websocket-message';
|
||||
@@ -17,14 +17,28 @@ export enum Intent {
|
||||
@Injectable()
|
||||
export class WebSocketService {
|
||||
private ws: WebSocketSubject<WebSocketMessage>;
|
||||
private subject: Subject<WebSocketMessage> = new Subject<WebSocketMessage>();
|
||||
private subscription: Subscription;
|
||||
|
||||
constructor() {}
|
||||
|
||||
public connect() {
|
||||
if (!this.ws) {
|
||||
if (this.subscription) {
|
||||
this.subscription.unsubscribe();
|
||||
}
|
||||
const wsproto = (location.protocol === 'https:') ? 'wss://' : 'ws://';
|
||||
const connAddr = wsproto + window.location.host + '/ws';
|
||||
this.ws = webSocket<WebSocketMessage>(connAddr);
|
||||
this.ws = webSocket<WebSocketMessage>({
|
||||
url: connAddr,
|
||||
closeObserver: {
|
||||
next: closeEvent => {
|
||||
this.ws = null;
|
||||
this.connect();
|
||||
}
|
||||
}
|
||||
});
|
||||
this.subscription = this.ws.subscribe(msg => this.subject.next(msg));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +49,7 @@ export class WebSocketService {
|
||||
}
|
||||
|
||||
public observeAll<T extends WebSocketMessage>(key: string): Observable<T> {
|
||||
return this.ws.pipe(
|
||||
return this.subject.pipe(
|
||||
filter(message => message.key.startsWith(key)),
|
||||
map(message => <T> message)
|
||||
);
|
||||
|
||||
+6796
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user