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

206 lines
5.3 KiB
TypeScript

import { ChangeDetectorRef, Component, OnInit } from '@angular/core';
import { WebSocketService } from '../services/websocket.service';
import { WebSocketMessage } from '../message-types/websocket-message';
import { IDEMessage } from '../message-types/ide-message';
import { DeployMessage } from '../message-types/deploy-message';
import { DeploymentNotificationService } from '../services/deployment-notification.service';
import { IdeConfigService } from '../services/config.service';
import { LanguageMap } from './language-map';
import { 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 = '';
lastFilename = '';
reloadFile = false;
code = 'Loading your file...';
codeState = CodeState.SAVED;
deployButtonState = DeployButtonState.DEPLOYED;
deployButtonText = this.configService.deployButtonText;
showDeployButton = this.configService.showDeployButton;
autosave = null;
editorOptions = {
theme: 'vs-dark',
language: 'text',
glyphMargin: false,
minimap: {enabled: false}
};
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 deploymentNotificationService: DeploymentNotificationService,
private configService: IdeConfigService) {}
ngOnInit() {
this.webSocketService.connect();
this.configService.init();
this.subscribeWS();
this.subscribeFirstLanguageDetection();
this.requestCode();
this.resetAutoSaveCountdown();
}
subscribeWS() {
this.webSocketService.observeControl<WebSocketMessage>('ide').subscribe(message => {
this.command_handlers[message.key](message);
this.changeDetectorRef.detectChanges();
});
this.webSocketService.observeControl<DeployMessage>('deploy.finish').subscribe(
message => this.deployHandler(message)
);
}
subscribeFirstLanguageDetection() {
this.webSocketService.observeControl<IDEMessage>('ide.read').pipe(first()).subscribe(
() => this.autoDetectEditorLanguage(this.filename)
);
}
reloadHandler(message: WebSocketMessage) {
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;
}
this.code = (message.content != null) ? message.content : this.code;
this.files = message.files;
if (this.lastFilename !== this.filename) {
this.autoDetectEditorLanguage(this.filename);
}
this.lastFilename = this.filename;
}
}
writeHandler(message: IDEMessage) {
this.setCodeState(CodeState.SAVED);
}
deployHandler(message: DeployMessage) {
if ('error' in message) {
this.setDeployButtonState(DeployButtonState.FAILED);
} else {
this.setDeployButtonState(DeployButtonState.DEPLOYED);
}
this.deploymentNotificationService.deploying.next(false);
}
autoDetectEditorLanguage(filename: string) {
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(); },
this.configService.autoSaveInterval.value
);
}
tabSwitchButtonHandler(file: string) {
if (this.codeState === CodeState.DIRTY) {
this.sendCodeContents();
}
this.filename = file;
this.requestCode();
}
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.webSocketService.send({'key': 'deploy.start'});
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.send({
'key': 'ide.write',
'filename': this.filename,
'content': this.code
});
}
requestCode() {
this.webSocketService.send({
'key': 'ide.read',
'filename': this.filename,
'reload': this.reloadFile
});
}
}