mirror of
https://github.com/avatao-content/frontend-tutorial-framework
synced 2024-12-05 02:31:33 +00:00
Merge branch 'monaco'
This commit is contained in:
commit
0305d73c49
@ -24,8 +24,8 @@
|
||||
"output": "./"
|
||||
},{
|
||||
"glob": "**/*",
|
||||
"input": "node_modules/brace/",
|
||||
"output": "./"
|
||||
"input": "./node_modules/ngx-monaco-editor/assets/monaco",
|
||||
"output": "./assets/monaco/"
|
||||
}
|
||||
],
|
||||
"styles": [
|
||||
|
24
package.json
24
package.json
@ -5,10 +5,7 @@
|
||||
"scripts": {
|
||||
"ng": "ng",
|
||||
"start": "ng serve --proxy-config proxy.conf.json",
|
||||
"build": "ng build --prod --aot --build-optimizer",
|
||||
"test": "ng test",
|
||||
"lint": "ng lint",
|
||||
"e2e": "ng e2e"
|
||||
"build": "ng build --prod --aot --build-optimizer"
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
@ -23,14 +20,13 @@
|
||||
"@angular/router": "^6.0.2",
|
||||
"@ng-bootstrap/ng-bootstrap": "^2.0.0",
|
||||
"bootstrap": "^4.0.0",
|
||||
"brace": "^0.11.0",
|
||||
"classlist.js": "^1.1.20150312",
|
||||
"core-js": "^2.5.4",
|
||||
"ng2-ace-editor": "^0.3.7",
|
||||
"ngx-monaco-editor": "^6.0.0",
|
||||
"node-sass": "^4.7.2",
|
||||
"rxjs": "^6.0.0",
|
||||
"rxjs-compat": "^6.1.0",
|
||||
"rxjs-websockets": "^4.0.0",
|
||||
"rxjs-websockets": "^5.0.0",
|
||||
"showdown": "^1.8.5",
|
||||
"xterm": "^3.1.0",
|
||||
"zone.js": "^0.8.26"
|
||||
@ -40,21 +36,11 @@
|
||||
"@angular/cli": "^6.0.3",
|
||||
"@angular/compiler-cli": "^6.0.2",
|
||||
"@angular/language-service": "^6.0.2",
|
||||
"@types/jasmine": "~2.8.6",
|
||||
"@types/jasminewd2": "~2.0.3",
|
||||
"@types/node": "~8.9.4",
|
||||
"@types/showdown": "^1.7.2",
|
||||
"codelyzer": "~4.2.1",
|
||||
"jasmine-core": "~2.99.1",
|
||||
"jasmine-spec-reporter": "~4.2.1",
|
||||
"karma": "~1.7.1",
|
||||
"karma-chrome-launcher": "~2.2.0",
|
||||
"karma-coverage-istanbul-reporter": "~1.4.2",
|
||||
"karma-jasmine": "~1.1.1",
|
||||
"karma-jasmine-html-reporter": "^0.2.2",
|
||||
"protractor": "~5.3.0",
|
||||
"ts-node": "~5.0.1",
|
||||
"tslint": "~5.9.1",
|
||||
"tslint": "^5.10.0",
|
||||
"typescript": "~2.7.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,6 @@ import { FormsModule } from '@angular/forms';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { AceEditorModule } from 'ng2-ace-editor';
|
||||
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
@ -28,6 +27,7 @@ import { DeploymentNotificationService } from './services/deployment-notificatio
|
||||
import { SafePipe } from './pipes/safe.pipe';
|
||||
import { ConsoleComponent } from './console/console.component';
|
||||
import { ProcessLogService } from './services/processlog.service';
|
||||
import { MonacoEditorModule } from 'ngx-monaco-editor';
|
||||
|
||||
|
||||
@NgModule({
|
||||
@ -49,8 +49,8 @@ import { ProcessLogService } from './services/processlog.service';
|
||||
FormsModule,
|
||||
HttpClientModule,
|
||||
NgbModule.forRoot(),
|
||||
AceEditorModule,
|
||||
AppRoutingModule,
|
||||
MonacoEditorModule.forRoot()
|
||||
],
|
||||
providers: [
|
||||
MarkdownService,
|
||||
|
@ -30,6 +30,8 @@ export const config = {
|
||||
showDeployButton: true,
|
||||
reloadIframeOnDeploy: true,
|
||||
showConsoleOnDeploy: true,
|
||||
autoDetectFileLanguage: true,
|
||||
showMiniMap: false
|
||||
},
|
||||
terminal: {
|
||||
route: 'shell'
|
||||
|
@ -59,7 +59,7 @@
|
||||
}
|
||||
|
||||
.tfw-ide {
|
||||
background-color: $tao-plum-900;
|
||||
background-color: #1e1e1e; // vscode dark theme
|
||||
}
|
||||
|
||||
.tfw-sidebar {
|
||||
|
@ -93,8 +93,8 @@ export class DashboardComponent implements OnInit, OnDestroy {
|
||||
|
||||
setLayout(layout: string) {
|
||||
this.layout = layout;
|
||||
// We need to trigger a 'resize' event manually, otherwise ace editor stays collapsed
|
||||
// Ace editors 'resize' event listener requires a parameter of force=true
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
@ -37,11 +37,8 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div (keyup)="setCodeState(CodeState.DIRTY); setDeployButtonState(DeployButtonState.TODEPLOY); resetAutoSaveCountdown()"
|
||||
ace-editor
|
||||
[(text)]="code"
|
||||
[mode]="language"
|
||||
[theme]="theme"
|
||||
[options]="options"
|
||||
class="tfw-ace-editor">
|
||||
</div>
|
||||
<ngx-monaco-editor [(ngModel)]="code"
|
||||
class="tfw-ide-editor"
|
||||
(keyup)="editorWriteHanlder()"
|
||||
[options]="editorOptions"
|
||||
></ngx-monaco-editor>
|
||||
|
@ -9,9 +9,10 @@
|
||||
grid-template-columns: 8fr 1fr;
|
||||
}
|
||||
|
||||
.tfw-ace-editor {
|
||||
.tfw-ide-editor {
|
||||
height: calc(100% - 67px);
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.btn-group {
|
||||
@ -23,8 +24,8 @@
|
||||
}
|
||||
|
||||
.tfw-tab-btn {
|
||||
background-color: white;
|
||||
border: 1px solid $tao-plum-900;
|
||||
background-color: gray;
|
||||
color: $tao-gray-600;
|
||||
border-left: 0;
|
||||
border-right: 0;
|
||||
border-radius: 100px;
|
||||
@ -35,7 +36,7 @@
|
||||
.active,
|
||||
.disabled,
|
||||
&:disabled {
|
||||
background-color: $tao-plum-100;
|
||||
background-color: white;
|
||||
font-weight: bolder;
|
||||
color: black;
|
||||
border: 0;
|
||||
|
@ -3,29 +3,14 @@
|
||||
|
||||
import { ChangeDetectorRef, Component, EventEmitter, OnInit, Output } from '@angular/core';
|
||||
|
||||
import * as brace from 'brace';
|
||||
import 'brace/ext/modelist';
|
||||
import 'brace/ext/language_tools';
|
||||
|
||||
import 'brace/mode/c_cpp';
|
||||
import 'brace/mode/csharp';
|
||||
import 'brace/mode/java';
|
||||
import 'brace/mode/typescript';
|
||||
import 'brace/mode/javascript';
|
||||
import 'brace/mode/json';
|
||||
import 'brace/mode/python';
|
||||
import 'brace/mode/sql';
|
||||
|
||||
import 'brace/theme/cobalt';
|
||||
import { IDECommand } from '../message-types/ide-command';
|
||||
import { WebSocketService } from '../services/websocket.service';
|
||||
import { ProcessManagerService } from '../services/processmanager.service';
|
||||
import { DeploymentNotificationService } from '../services/deployment-notification.service';
|
||||
import { config } from '../config';
|
||||
import { CommandMessage } from '../message-types/command-message';
|
||||
|
||||
const modelist = brace.acequire('ace/ext/modelist');
|
||||
const langTools = brace.acequire('ace/ext/language_tools');
|
||||
import { LanguageMap } from './language-map';
|
||||
import { filter, first } from 'rxjs/operators';
|
||||
|
||||
|
||||
enum DeployButtonState {
|
||||
@ -62,20 +47,22 @@ export class IdeComponent implements OnInit {
|
||||
showDeployButton: boolean = config.ide.showDeployButton;
|
||||
autosave = null;
|
||||
|
||||
language: string = config.ide.defaultLanguage;
|
||||
theme = 'cobalt';
|
||||
editorOptions = {
|
||||
theme: 'vs-dark',
|
||||
language: config.ide.defaultLanguage,
|
||||
glyphMargin: false,
|
||||
minimap: {enabled: config.ide.showMiniMap}
|
||||
};
|
||||
|
||||
@Output() newLogs = new EventEmitter<any>();
|
||||
|
||||
options: any = {enableBasicAutocompletion: true,
|
||||
enableSnippets: true,
|
||||
enableLiveAutocompletion: true};
|
||||
|
||||
command_handlers = {'reload': this.reloadHandler.bind(this),
|
||||
'read': this.readHandler.bind(this),
|
||||
'select': this.selectHandler.bind(this),
|
||||
'write': this.writeHandler.bind(this),
|
||||
'selectdir': this.selectdirHandler.bind(this)};
|
||||
command_handlers = {
|
||||
'reload': this.reloadHandler.bind(this),
|
||||
'read': this.readHandler.bind(this),
|
||||
'select': this.selectHandler.bind(this),
|
||||
'write': this.writeHandler.bind(this),
|
||||
'selectdir': this.selectdirHandler.bind(this)
|
||||
};
|
||||
|
||||
constructor(private webSocketService: WebSocketService,
|
||||
private changeDetectorRef: ChangeDetectorRef,
|
||||
@ -85,6 +72,7 @@ export class IdeComponent implements OnInit {
|
||||
ngOnInit() {
|
||||
this.webSocketService.connect();
|
||||
this.subscribeWS();
|
||||
this.subscribeFirstLanguageDetection();
|
||||
this.requestCode();
|
||||
this.initProcessManagerService();
|
||||
this.resetAutoSaveCountdown();
|
||||
@ -97,6 +85,15 @@ export class IdeComponent implements OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
subscribeFirstLanguageDetection() {
|
||||
this.webSocketService.observeKey<CommandMessage>(this.key_id).pipe(
|
||||
filter(message => message.data.command === 'read'),
|
||||
first()
|
||||
).subscribe(
|
||||
() => this.autoDetectEditorLanguageIfEnabled(this.filename)
|
||||
);
|
||||
}
|
||||
|
||||
initProcessManagerService() {
|
||||
this.processManagerService.init();
|
||||
this.processManagerService.subscribeCallback(
|
||||
@ -117,7 +114,7 @@ export class IdeComponent implements OnInit {
|
||||
|
||||
this.processManagerService.subscribeErrorCallback(
|
||||
config.ide.deployProcessName,
|
||||
(event) => this.setDeployButtonState(DeployButtonState.FAILED)
|
||||
() => this.setDeployButtonState(DeployButtonState.FAILED)
|
||||
);
|
||||
}
|
||||
|
||||
@ -125,12 +122,12 @@ export class IdeComponent implements OnInit {
|
||||
this.filename = data.filename;
|
||||
this.directory = data.directory;
|
||||
this.code = (data.content != null) ? data.content : this.code;
|
||||
this.language = modelist.getModeForPath(this.filename).name;
|
||||
this.files = data.files;
|
||||
}
|
||||
|
||||
selectHandler(data: IDECommand) {
|
||||
this.updateFileData(data);
|
||||
this.autoDetectEditorLanguageIfEnabled(this.filename);
|
||||
}
|
||||
|
||||
reloadHandler(data: CommandMessage) {
|
||||
@ -151,6 +148,24 @@ export class IdeComponent implements OnInit {
|
||||
this.updateFileData(data);
|
||||
}
|
||||
|
||||
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);
|
||||
@ -169,6 +184,12 @@ export class IdeComponent implements OnInit {
|
||||
this.requestCode();
|
||||
}
|
||||
|
||||
editorWriteHanlder() {
|
||||
this.setCodeState(CodeState.DIRTY);
|
||||
this.setDeployButtonState(DeployButtonState.TODEPLOY);
|
||||
this.resetAutoSaveCountdown();
|
||||
}
|
||||
|
||||
setCodeState(state: CodeState) {
|
||||
this.codeState = state;
|
||||
}
|
||||
|
36
src/app/ide/language-map.ts
Normal file
36
src/app/ide/language-map.ts
Normal file
@ -0,0 +1,36 @@
|
||||
// Copyright (C) 2018 Avatao.com Innovative Learning Kft.
|
||||
// All Rights Reserved. See LICENSE file for details.
|
||||
|
||||
export const LanguageMap: { [extension: string]: string; } = {
|
||||
bat: 'bat',
|
||||
clje: 'clojure',
|
||||
coffee: 'coffee',
|
||||
c: 'cpp',
|
||||
h: 'cpp',
|
||||
cpp: 'cpp',
|
||||
hpp: 'cpp',
|
||||
cs: 'csharp',
|
||||
fs: 'fsharp',
|
||||
go: 'go',
|
||||
html: 'html',
|
||||
java: 'java',
|
||||
js: 'javascript',
|
||||
ts: 'typescript',
|
||||
lua: 'lua',
|
||||
md: 'markdown',
|
||||
m: 'objective-c',
|
||||
mm: 'objective-c',
|
||||
php: 'php',
|
||||
py: 'python',
|
||||
r: 'r',
|
||||
rb: 'ruby',
|
||||
rs: 'rust',
|
||||
rlib: 'rust',
|
||||
sql: 'sql',
|
||||
swift: 'swift',
|
||||
xml: 'xml',
|
||||
yml: 'yaml',
|
||||
css: 'css',
|
||||
less: 'less',
|
||||
scss: 'scss'
|
||||
};
|
@ -5,7 +5,7 @@ import { Injectable } from '@angular/core';
|
||||
import { WebSocketService } from './websocket.service';
|
||||
import { ProcessLogCommand } from '../message-types/process-log-command';
|
||||
import { config } from '../config';
|
||||
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import { LogMessage } from '../message-types/log-message';
|
||||
import { CommandMessage } from '../message-types/command-message';
|
||||
|
||||
|
@ -3,3 +3,9 @@
|
||||
@import '../node_modules/xterm/dist/xterm.css';
|
||||
|
||||
@import "assets/scss/main";
|
||||
|
||||
body, html {
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user