From 4197bca2996135a225fd351d1c8c72d84479a7af Mon Sep 17 00:00:00 2001
From: Manuel Friedli <manuel@fritteli.ch>
Date: Tue, 20 Sep 2016 20:30:39 +0200
Subject: [PATCH] First usable version based on AngularJS 2! Almost no
 converters yet, though.

---
 .gitignore                           |  1 +
 app/InputcomponentmanagerService.ts  | 41 +++++++++++++++++++
 app/app.component.html               | 10 ++++-
 app/app.component.ts                 | 53 +++++++++++++++++++-----
 app/app.module.ts                    |  9 ++--
 app/{ => converter}/base64decoder.ts |  2 +-
 app/{ => converter}/base64encoder.ts |  2 +-
 app/{ => converter}/converter.ts     |  0
 app/converterregistry.service.ts     | 11 +++--
 app/inputarea.component.html         | 23 +++++++----
 app/inputarea.component.ts           | 61 ++++++++++++++--------------
 app/main.ts                          |  1 -
 dencode.css                          |  7 ++++
 13 files changed, 155 insertions(+), 66 deletions(-)
 create mode 100644 app/InputcomponentmanagerService.ts
 rename app/{ => converter}/base64decoder.ts (86%)
 rename app/{ => converter}/base64encoder.ts (86%)
 rename app/{ => converter}/converter.ts (100%)

diff --git a/.gitignore b/.gitignore
index a74b159..7404c57 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,3 +6,4 @@ node_modules/
 typings/
 app/**/*.js
 app/**/*.js.map
+npm-debug.log
diff --git a/app/InputcomponentmanagerService.ts b/app/InputcomponentmanagerService.ts
new file mode 100644
index 0000000..a1717b8
--- /dev/null
+++ b/app/InputcomponentmanagerService.ts
@@ -0,0 +1,41 @@
+import {Injectable} from "@angular/core";
+@Injectable()
+export class InputcomponentmanagerService {
+    private components:any[] = [];
+
+    public constructor() {
+    }
+
+    public register(component:any):void {
+        this.components.push(component);
+    }
+
+    public getAllComponents():any[] {
+        return this.components;
+    }
+
+    public getNext(component:any):any {
+        let index:number = component.index;
+        if (index == this.components.length - 1) {
+            this.addComponent();
+        }
+        return this.components[index + 1];
+    }
+
+    public getFirst():any {
+        if (this.components.length == 0) {
+            this.addComponent();
+        }
+        return this.components[0];
+    }
+
+    private addComponent():void {
+        this.register({
+            content: "",
+            selectedConverter: undefined,
+            index: this.components.length,
+            error: false,
+            message: ""
+        });
+    }
+}
\ No newline at end of file
diff --git a/app/app.component.html b/app/app.component.html
index 47161cb..13f8984 100644
--- a/app/app.component.html
+++ b/app/app.component.html
@@ -1,3 +1,9 @@
-<div>
-    <den-inputarea></den-inputarea>
+<div *ngFor="let step of steps" class="wrapper">
+    <textarea class="input" (change)="update(step)" placeholder="Please enter your input ..."
+              [(ngModel)]="step.content">{{step.content}}</textarea>
+    <select class="conversion" (change)="convert(step, $event)">
+        <option id="-1">Select conversion ...</option>
+        <option *ngFor="let c of converters" id="{{c.getId()}}">{{c.getDisplayname()}}</option>
+    </select>
+    <div class="message" *ngIf="step.error">{{step.message}}</div>
 </div>
diff --git a/app/app.component.ts b/app/app.component.ts
index dc913bf..2c8f5a1 100644
--- a/app/app.component.ts
+++ b/app/app.component.ts
@@ -1,26 +1,57 @@
-import {Component} from "@angular/core";
-import {OnInit}from "@angular/core";
-
+import {Component, OnInit} from "@angular/core";
 import {ConverterregistryService} from "./converterregistry.service";
-import {Converter} from "./converter";
+import {InputcomponentmanagerService} from "./InputcomponentmanagerService";
+import {Converter} from "./converter/converter";
 
 @Component({
     moduleId: module.id,
     selector: "den-app",
     templateUrl: "app.component.html",
     styleUrls: ["app.component.css"],
-    providers: [ConverterregistryService]
+    providers: [ConverterregistryService, InputcomponentmanagerService]
 })
 export class AppComponent extends OnInit {
-    constructor(private converterregistryService:ConverterregistryService) {
+    public steps:any[] = [];
+    public converters:Converter[] = [];
+
+    constructor(private converterregistryService:ConverterregistryService, private inputcomponentmanagerService:InputcomponentmanagerService) {
         super();
     }
 
-    ngOnInit():void {
-        let converters:Converter[] = this.converterregistryService.getConverters();
-        console.log("Number of registered converters: " + converters.length);
-        for (let i = 0; i < converters.length; i++) {
-            console.log("Converter " + converters[i].getId() + ": " + converters[i].getDisplayname());
+    convert(step:any, $event:any):void {
+        step.selectedConverter = this.converterregistryService.getConverter($event.target.selectedOptions[0].id);
+        this.update(step);
+    }
+
+    update(step:any):void {
+        let converter:Converter = step.selectedConverter;
+
+        if (converter !== undefined) {
+            let content:string = step.content;
+            let result:string;
+            try {
+                result = converter.convert(content);
+            } catch (error) {
+                result = null;
+            }
+            if (result === null) {
+                step.message = "Error converting. Not applicable?";
+                step.error = true;
+            } else {
+                step.message = "";
+                step.error = false;
+                if (result !== "") {
+                    let nextComponent:any = this.inputcomponentmanagerService.getNext(step);
+                    nextComponent.content = result;
+                    this.update(nextComponent);
+                }
+            }
         }
     }
+
+    ngOnInit():void {
+        this.converters = this.converterregistryService.getAllConverters();
+        this.steps = this.inputcomponentmanagerService.getAllComponents();
+        this.inputcomponentmanagerService.getFirst();
+    }
 }
diff --git a/app/app.module.ts b/app/app.module.ts
index 4cf0a38..8988169 100644
--- a/app/app.module.ts
+++ b/app/app.module.ts
@@ -1,8 +1,7 @@
-import {NgModule} from '@angular/core'
-import {BrowserModule} from '@angular/platform-browser'
-import {FormsModule} from '@angular/forms'
-
-import {AppComponent} from './app.component'
+import {NgModule} from "@angular/core";
+import {BrowserModule} from "@angular/platform-browser";
+import {FormsModule} from "@angular/forms";
+import {AppComponent} from "./app.component";
 import {InputareaComponent} from "./inputarea.component";
 
 @NgModule({
diff --git a/app/base64decoder.ts b/app/converter/base64decoder.ts
similarity index 86%
rename from app/base64decoder.ts
rename to app/converter/base64decoder.ts
index eba3379..1b4e5b1 100644
--- a/app/base64decoder.ts
+++ b/app/converter/base64decoder.ts
@@ -1,4 +1,4 @@
-import {Converter} from './converter';
+import {Converter} from "./converter";
 
 export class Base64Decoder implements Converter {
     getDisplayname():string {
diff --git a/app/base64encoder.ts b/app/converter/base64encoder.ts
similarity index 86%
rename from app/base64encoder.ts
rename to app/converter/base64encoder.ts
index bb9de8f..409636d 100644
--- a/app/base64encoder.ts
+++ b/app/converter/base64encoder.ts
@@ -1,4 +1,4 @@
-import {Converter} from './converter';
+import {Converter} from "./converter";
 
 export class Base64Encoder implements Converter {
     getDisplayname():string {
diff --git a/app/converter.ts b/app/converter/converter.ts
similarity index 100%
rename from app/converter.ts
rename to app/converter/converter.ts
diff --git a/app/converterregistry.service.ts b/app/converterregistry.service.ts
index 44ad46d..8bd7f7f 100644
--- a/app/converterregistry.service.ts
+++ b/app/converterregistry.service.ts
@@ -1,8 +1,7 @@
-import {Injectable} from '@angular/core';
-
-import {Converter} from './converter';
-import {Base64Encoder} from "./base64encoder";
-import {Base64Decoder} from "./base64decoder";
+import {Injectable} from "@angular/core";
+import {Converter} from "./converter/converter";
+import {Base64Encoder} from "./converter/base64encoder";
+import {Base64Decoder} from "./converter/base64decoder";
 
 @Injectable()
 export class ConverterregistryService {
@@ -12,7 +11,7 @@ export class ConverterregistryService {
         this.init();
     }
 
-    public getConverters():Converter[] {
+    public getAllConverters():Converter[] {
         return this.converters;
     }
 
diff --git a/app/inputarea.component.html b/app/inputarea.component.html
index da0a65a..d8e65ee 100644
--- a/app/inputarea.component.html
+++ b/app/inputarea.component.html
@@ -1,8 +1,15 @@
-<div id="wrapper-{{index}}" class="wrapper">
-    <textarea id="input-{{index}}" class="input" (change)="update()" placeholder="Please enter your input ..."
-              [(ngModel)]="conversion.content">{{conversion.content}}</textarea>
-    <select id="type-{{index}}" class="conversion" (change)="convert($event)">
-        <option id="-1">Select conversion ...</option>
-        <option *ngFor="let c of conversions" id="{{c}}">Type {{ConversionType[c]}}</option>
-    </select>
-</div>
+<!--<div id="wrapper-{{index}}" class="wrapper">-->
+<!--<textarea id="input-{{index}}" class="input" (change)="update()" placeholder="Please enter your input ..."-->
+<!--[(ngModel)]="conversion.content">{{conversion.content}}</textarea>-->
+<!--<select id="type-{{index}}" class="conversion" (change)="convert($event)">-->
+<!--<option id="-1">Select conversion ...</option>-->
+<!--<option *ngFor="let c of conversions" id="{{c}}">Type {{ConversionType[c]}}</option>-->
+<!--</select>-->
+<!--</div>-->
+
+<textarea class="input" (change)="update()" placeholder="Please enter your input ..."
+          [(ngModel)]="content">{{content}}</textarea>
+<select class="conversion" (change)="convert($event)">
+    <option id="-1">Select conversion ...</option>
+    <option *ngFor="let c of converters" id="{{c.getId()}}">{{c.getDisplayname()}}</option>
+</select>
diff --git a/app/inputarea.component.ts b/app/inputarea.component.ts
index c07a4da..d3a3e1e 100644
--- a/app/inputarea.component.ts
+++ b/app/inputarea.component.ts
@@ -1,6 +1,7 @@
-import {Component} from "@angular/core";
-import {ConversionInput} from "./conversioninput";
-import {ConversionType} from "./conversiontype";
+import {Component, OnInit} from "@angular/core";
+import {ConverterregistryService} from "./converterregistry.service";
+import {Converter} from "./converter/converter";
+import {InputcomponentmanagerService} from "./InputcomponentmanagerService";
 
 
 @Component({
@@ -9,40 +10,38 @@ import {ConversionType} from "./conversiontype";
     templateUrl: "inputarea.component.html",
     styleUrls: ["inputarea.component.css"]
 })
-export class InputareaComponent {
-    public index:number = 0;
-    public conversions:ConversionType[] = [ConversionType.ENCODE_BASE64, ConversionType.DECODE_BASE64];
-    private conversion:ConversionInput;
-    // private ConversionType:ConversionType = ConversionType;
+export class InputareaComponent extends OnInit {
+    public converters:Converter[] = [];
+    public content:string = '';
+    private selectedConverter:Converter;
 
-    constructor() {
-        console.log("Aloha, " + this.index);
-        this.conversion = new ConversionInput();
-        this.conversion.content = "";
-        this.conversion.type = ConversionType.DECODE_BASE64;
-    }
-
-    public update():void {
-        console.log(this.conversion.content);
+    constructor(private converterregistryService:ConverterregistryService, private inputcomponentmanagerService:InputcomponentmanagerService) {
+        super();
     }
 
     public convert(e):void {
-        this.conversion.type = ConversionType.of(+e.target.selectedOptions[0].id);
-        console.log(this.conversion.type);
-        switch (this.conversion.type) {
-            case ConversionType.DECODE_BASE64:
-                this.conversion.content = "Base64 decode";
-                break;
-            case ConversionType.ENCODE_BASE64:
-                this.conversion.content = "Base64 encode";
-                break;
-            default:
-                this.conversion.content = "Unknown: " + this.conversion.type;
-                break;
+        this.selectedConverter = this.converterregistryService.getConverter(e.target.selectedOptions[0].id);
+        this.update();
+    }
+
+    public update():void {
+        if (this.selectedConverter !== undefined) {
+            let result:string = this.selectedConverter.convert(this.content);
+            let nextComponent:InputareaComponent = this.inputcomponentmanagerService.getNext(this);
+            if (nextComponent !== undefined) {
+                nextComponent.setContent(result);
+            }
         }
     }
 
-    public setIndex(index:number):void {
-        this.index = index;
+    public setContent(content:string):void {
+        this.content = content;
+        this.update();
+    }
+
+    ngOnInit():void {
+        this.converters = this.converterregistryService.getAllConverters();
+        this.selectedConverter = undefined;
+        this.inputcomponentmanagerService.register(this);
     }
 }
diff --git a/app/main.ts b/app/main.ts
index 244ca48..c31c26f 100644
--- a/app/main.ts
+++ b/app/main.ts
@@ -1,5 +1,4 @@
 import {platformBrowserDynamic} from "@angular/platform-browser-dynamic";
-
 import {AppModule} from "./app.module";
 
 platformBrowserDynamic().bootstrapModule(AppModule);
diff --git a/dencode.css b/dencode.css
index 8fadfda..261f217 100644
--- a/dencode.css
+++ b/dencode.css
@@ -59,6 +59,13 @@ div.wrapper {
 	padding: 0.5em;
 }
 
+div.wrapper div.message {
+	display: inline-block;
+	color: #f00;
+	background-color: #fff;
+	border: 1px solid #f00;
+}
+
 textarea.input {
 	border-style: solid;
 	border-width: 1px;