File

src/app/ide/ide.component.ts

Implements

OnInit

Metadata

selector app-ide
styleUrls ./ide.component.scss
templateUrl ./ide.component.html

Index

Properties
Methods

Constructor

constructor(route: ActivatedRoute, runCodeService: RunCodeService, fileService: FileService, apiService: ApiService, router: Router)
Parameters :
Name Type Optional
route ActivatedRoute No
runCodeService RunCodeService No
fileService FileService No
apiService ApiService No
router Router No

Methods

ngOnInit
ngOnInit()
Returns : void
optimizeURI
optimizeURI(uri: string)
Parameters :
Name Type Optional
uri string No
Returns : string
runFile
runFile()
Returns : void
updateFile
updateFile()
Returns : void
updateInput
updateInput(val: string)
Parameters :
Name Type Optional
val string No
Returns : void

Properties

extensions
Type : []
Default value : ['.cpp', '.py', '.java']
file
Type : File
Default value : { filename: 'Untitled', language: '.cpp', text: '', username: JSON.parse(this.apiService.getToken()).username, path: '/' }
inp
Type : string
Default value : ''
inputField
Decorators :
@ViewChild(InputComponent)
isCompiling
Default value : false
isError
Default value : false
isSaved
Default value : false
isUploading
Default value : false
isUpToDate
Default value : false
loadingFile
Default value : false
Public route
Type : ActivatedRoute
Public runCodeService
Type : RunCodeService
runField
Decorators :
@ViewChild(IdeCompileComponent)
saveField
Decorators :
@ViewChild(SaveFileComponent)
import {Component, OnInit, ViewChild} from '@angular/core';
import {ActivatedRoute, Router} from '@angular/router';
import {InputComponent} from '../input/input.component';
import {IdeCompileComponent} from '../ide-compile/ide-compile.component';
import {RunCodeService} from '../run-code.service';
import {SaveFileComponent} from '../save-file/save-file.component';
import {File} from '../file';
import {FileService} from '../file.service';
import {ApiService} from '../api.service';

declare const CodeMirror: any;

@Component({
  selector: 'app-ide',
  templateUrl: './ide.component.html',
  styleUrls: ['./ide.component.scss']
})
export class IdeComponent implements OnInit {

  inp = '';
  extensions = ['.cpp', '.py', '.java'];
  loadingFile = false;
  isSaved = false;
  isUploading = false;
  isCompiling = false;
  isError = false;
  isUpToDate = false;
  file: File = {
    filename: 'Untitled',
    language: '.cpp',
    text: '',
    username: JSON.parse(this.apiService.getToken()).username,
    path: '/'
  };
  @ViewChild(InputComponent) inputField;
  @ViewChild(IdeCompileComponent) runField;
  @ViewChild(SaveFileComponent) saveField;

  constructor(public route: ActivatedRoute, public runCodeService: RunCodeService, private fileService: FileService,
              private apiService: ApiService, private router: Router) {
  }

  ngOnInit(): void {
    const filepath = decodeURIComponent(this.route.snapshot.params.filepath);
    const editorArea = document.getElementById('editor');
    const editor = CodeMirror.fromTextArea(editorArea as HTMLTextAreaElement, {
      lineNumbers: true,
      theme: 'material-ocean',
      mode: 'text/x-c++src',
      autoCloseBrackets: true,
      matchBrackets: true
    });
    editor.setSize('auto', '70vh');
    Object.assign((document.getElementsByClassName('CodeMirror')[0] as HTMLTextAreaElement).style, {
      borderBottom: '1px solid #ddf',
      padding: '20px',
      fontFamily: '"Anonymous Pro", monospace',
    });

    let activeLang = 0;
    const langs = ['C++', 'Python', 'Java'];
    const langsMime = ['text/x-c++src', 'text/x-python', 'text/x-java'];
    const code = [`#include <iostream>
using namespace std;

int main() {
  cout << "Hello World!\\n";
  return 0;
}`, `print("Hello World!")`, `class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}`];

    editor.setValue(code[activeLang]);
    this.file.text = code[activeLang];
    const tl = document.getElementById('toggle-lang') as HTMLDivElement;
    tl.onclick = () => {
      if (this.isSaved) {
        return;
      }
      activeLang = (activeLang + 1) % 3;
      this.file.language = this.extensions[activeLang];
      tl.innerHTML = langs[activeLang];
      editor.setValue(code[activeLang]);
      editor.setOption('mode', langsMime[activeLang]);
    };

    editor.on('update', () => {
      if (!this.isUploading) {
        this.isUpToDate = false;
        document.getElementById('saveBtn').innerHTML = 'Save File';
      }
      code[activeLang] = editor.getValue();
      this.file.text = editor.getValue();
    });

    if (filepath !== 'new') {
      const arr = filepath.split('.');
      if (!(['cpp', 'py', 'java']).includes(arr[arr.length - 1])) {
        this.router.navigate(['arena/file/new']).then(() => window.location.reload());
      }
      const arrf = filepath.split('/');
      const arrg = arrf.pop().split('.');
      arrg.pop();
      this.file.filename = arrg.join('.');
      this.file.path = arrf.join('/');
      this.file.language = '.' + arr[arr.length - 1];
      tl.innerHTML = langs[this.extensions.indexOf(this.file.language)];
      this.fileService.getFileContent(this.file.username, filepath)
        .subscribe(data => {
          editor.setValue(data);
          this.isSaved = true;
          this.isUpToDate = true;
          this.loadingFile = false;
          console.log(this.file);
        }, error => {
          this.router.navigate(['arena/file/new']).then(() => window.location.reload());
        });
    } else {
      this.loadingFile = false;
    }

  }

  updateInput(val: string): void {
    this.inp = val;
  }

  updateFile(): void {
    const btn = document.getElementById('saveBtn') as HTMLButtonElement;
    if (btn.classList.contains('disabled')) {
      return;
    }
    this.isUploading = true;
    btn.innerHTML = 'Saving...';
    this.fileService.upload(this.file, false)
      .subscribe(data => {
        btn.innerHTML = 'Saved';
        this.isUploading = false;
        this.isUpToDate = true;
        console.log(data);
      }, error => {
        console.log(error);
        this.isUploading = false;
        btn.innerHTML = 'Save File';
      });
  }

  runFile(): void {
    const btn = document.getElementById('runBtn');
    if (btn.classList.contains('disabled')) {
      return;
    }
    this.isCompiling = true;
    this.runCodeService.compileFile(this.file)
      .subscribe(data => {
        this.runCodeService.executeFile(this.file, this.inp)
          .subscribe(d => {
            console.log(d);
            this.runField.status = '<div class="code">' + d + '</div>';
            this.runField.setState(true);
            this.isCompiling = false;
          }, err => {
            console.log(err);
            this.isCompiling = false;
            this.isError = true;
            this.runField.status = '<div class="error">Runtime Error!</div>';
            this.runField.setState(true);
            setTimeout(() => {
              this.isError = false;
            }, 3000);
          });
      }, error => {
        console.log(error);
        this.isCompiling = false;
        this.isError = true;
        this.runField.status = '<div class="error">Compilation Error!</div>';
        this.runField.setState(true);
        setTimeout(() => {
          this.isError = false;
        }, 3000);
      });
  }

  optimizeURI(uri: string): string {
    const ret: string[] = [];
    for (const c of uri.split('/')) {
      if (c === '' || c === '.') {
      } else if (c === '..') {
        ret.pop();
      } else {
        ret.push(c);
      }
    }
    return ret.join('') === '' ? '/' : '/' + ret.join('/') + '/';
  }
}
<div id="ide-cover" *ngIf="loadingFile">
  <div id="ide-cover-text">
    Loading file...
  </div>
</div>

<div class="container">
  <div id="toggle-lang" [class.disabled]="isSaved">C++</div>
  <div id="attempt">
    <span *ngIf="!isUpToDate">• </span>
    <span id="ideFileName">{{optimizeURI(file.path)}}{{file.filename + file.language}}</span>
    <button (click)="inputField.setState(true);" id="inputBtn">Input</button>
    <button (click)="runFile()" id="runBtn" [class.disabled]="isCompiling || isError">{{isError ? 'Error' : (isCompiling ? 'Compiling...' : 'Run File')}}</button>
    <button (click)="!isSaved ? this.saveField.setState(true) : updateFile();"
            [class.disabled]="isUploading || isUpToDate"
            id="saveBtn">{{isUploading ? "Saving File..." : "Save File"}}</button>
  </div>
  <label for="editor"></label>
  <textarea id="editor" name="editor" value="{{inp}}"></textarea>
</div>
<app-input (valueEmit)="updateInput($event)"></app-input>
<app-ide-compile [statusVal]="runCodeService.runStatus"></app-ide-compile>
<app-save-file (savedFile)="isSaved = isUpToDate = true;" [file]="file"></app-save-file>

./ide.component.scss

.container {
  position: relative;
  padding: 20px;

  #toggle-lang {
    position: absolute;
    background: var(--bgcolor);
    color: var(--color);
    padding: 5px 10px;
    right: 22px;
    top: 22px;
    z-index: 100;
    cursor: pointer;
    user-select: none;

    &.disabled {
      cursor: not-allowed;
    }
  }

  label {
    display: none;
  }

  #attempt {
    position: absolute;
    right: 24px;
    bottom: 24px;
    z-index: 100;

    #runBtn,
    #inputBtn,
    #saveBtn {
      display: inline-block;
      background: transparent;
      color: #ddf;
      margin: 2px;
      cursor: pointer;
      transition: 0.25s all;
      user-select: none;

      &:hover {
        background: var(--color);
        color: var(--bgcolor);
      }

      &.disabled:hover {
        cursor: default;
        background: transparent;
        color: #ddf;
      }
    }
  }
}

#ideFileName {
  margin-right: 10px;
}

#ide-cover {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: #002e;
  color: #ddf;
  font-size: 1.5em;
  z-index: 10000;

  #ide-cover-text {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%);
  }
}

@media screen and (max-width: 800px) {
  .container {
    padding: 20px 0;
  }

  #attempt {
    right: 4px !important;
    bottom: 24px !important;
  }

  #toggle-lang {
    right: 0 !important;
  }
}
Legend
Html element
Component
Html element with directive

result-matching ""

    No results matching ""