frontend-tutorial-framework/src/app/ide/ide.component.ts

209 lines
5.5 KiB
TypeScript

import { ChangeDetectorRef, Component, EventEmitter, OnInit, Output } from '@angular/core';
import { WebSocketService } from '../services/websocket.service';
import { WebSocketMessage } from '../message-types/websocket-message';
import { IDEMessage } from '../message-types/ide-message';
import { ProcessManagerService } from '../services/processmanager.service';
import { DeploymentNotificationService } from '../services/deployment-notification.service';
import { config } from '../config';
import { LanguageMap } from './language-map';
import { filter, first } from 'rxjs/operators';
enum DeployButtonState {
DEPLOYED,
DEPLOYING,
FAILED,
TODEPLOY
}
enum CodeState {
SAVED,
DIRTY
}
@Component({
selector: 'app-ide',
templateUrl: './ide.component.html',
styleUrls: ['./ide.component.scss']
})
export class IdeComponent implements OnInit {
CodeState = CodeState;
DeployButtonState = DeployButtonState;
files: string[];
filename = '';
code: string = config.ide.defaultCode;
codeState = CodeState.SAVED;
deployButtonState = DeployButtonState.DEPLOYED;
deployButtonText = config.ide.deployButtonText;
showDeployButton: boolean = config.ide.showDeployButton;
autosave = null;
editorOptions = {
theme: 'vs-dark',
language: config.ide.defaultLanguage,
glyphMargin: false,
minimap: {enabled: config.ide.showMiniMap}
};
@Output() newLogs = new EventEmitter<any>();
command_handlers = {
'ide.reload': this.reloadHandler.bind(this),
'ide.read': this.readHandler.bind(this),
'ide.write': this.writeHandler.bind(this),
};
constructor(private webSocketService: WebSocketService,
private changeDetectorRef: ChangeDetectorRef,
private processManagerService: ProcessManagerService,
private deploymentNotificationService: DeploymentNotificationService) { }
ngOnInit() {
this.webSocketService.connect();
this.subscribeWS();
this.subscribeFirstLanguageDetection();
this.requestCode();
this.initProcessManagerService();
this.resetAutoSaveCountdown();
}
subscribeWS() {
this.webSocketService.observeKey<WebSocketMessage>('ide').subscribe(message => {
this.command_handlers[message.key](message);
this.changeDetectorRef.detectChanges();
});
}
subscribeFirstLanguageDetection() {
this.webSocketService.observeKey<IDEMessage>('ide.read').pipe(first()).subscribe(
() => this.autoDetectEditorLanguageIfEnabled(this.filename)
);
}
initProcessManagerService() {
this.processManagerService.init();
this.processManagerService.subscribeCallback(
config.ide.deployProcessName,
message => {
this.deploymentNotificationService.deploying.next(false);
this.newLogs.emit({
stdout: message.stdout,
stderr: message.stderr
});
}
);
this.processManagerService.subscribeSuccessCallback(
config.ide.deployProcessName,
message => this.setDeployButtonState(DeployButtonState.DEPLOYED)
);
this.processManagerService.subscribeErrorCallback(
config.ide.deployProcessName,
() => this.setDeployButtonState(DeployButtonState.FAILED)
);
}
reloadHandler(message: WebSocketMessage) {
this.requestCode();
}
readHandler(message: IDEMessage) {
if (this.codeState === CodeState.SAVED) {
if (this.filename !== message.filename) {
this.filename = message.filename;
}
this.code = (message.content != null) ? message.content : this.code;
this.files = message.files;
}
}
writeHandler(message: IDEMessage) {
this.setCodeState(CodeState.SAVED);
}
autoDetectEditorLanguageIfEnabled(filename: string) {
if (!config.ide.autoDetectFileLanguage) {
return;
}
const extension = filename.substr(filename.lastIndexOf('.') + 1);
let language = LanguageMap[extension];
language = (language === undefined) ? 'text' : language;
this.setEditorLanguage(language);
}
setEditorLanguage(lang: string) {
this.editorOptions = Object.assign(
{},
this.editorOptions,
{ language: lang }
);
}
resetAutoSaveCountdown() {
if (this.autosave) {
clearInterval(this.autosave);
}
this.autosave = setInterval(
() => { this.sendCodeIfDirty(); },
config.ide.autoSaveInterval
);
}
tabSwitchButtonHandler(file: string) {
if (this.codeState === CodeState.DIRTY) {
this.sendCodeContents();
}
this.filename = file;
this.requestCode();
this.autoDetectEditorLanguageIfEnabled(this.filename);
}
editorWriteHandler() {
this.setCodeState(CodeState.DIRTY);
this.setDeployButtonState(DeployButtonState.TODEPLOY);
this.resetAutoSaveCountdown();
}
setCodeState(state: CodeState) {
this.codeState = state;
}
setDeployButtonState(state: DeployButtonState) {
this.deployButtonState = state;
}
deployCode() {
this.processManagerService.restartProcess(config.ide.deployProcessName);
this.setDeployButtonState(DeployButtonState.DEPLOYING);
this.deploymentNotificationService.deploying.next(true);
}
sendCodeIfDirty() {
if (this.codeState === CodeState.DIRTY) {
this.sendCodeContents();
}
}
pathBasename(path: string) {
return path.split('/').reverse()[0];
}
sendCodeContents() {
this.webSocketService.sendJSON({
'key': 'ide.write',
'filename': this.filename,
'content': this.code
});
}
requestCode() {
this.webSocketService.sendJSON({
'key': 'ide.read',
'filename': this.filename
});
}
}