Refactor input fields, converter selectors and error messages into their own components.
Some checks failed
continuous-integration/drone the build failed

This commit is contained in:
Manuel Friedli 2018-09-06 14:37:20 +02:00
parent 62ba5a3357
commit 81db470a5a
16 changed files with 337 additions and 157 deletions

View file

@ -1,18 +1,7 @@
<div *ngFor="let step of steps" class="inputwrapper"> <div *ngFor="let step of steps" class="inputwrapper">
<div class="textwrapper arrow_box"> <app-text-input-field [step]="step" #ti></app-text-input-field>
<textarea class="textinput" (keyup)="update(step)" placeholder="Please enter your input ..." <app-converter-selector [step]="step" [textInput]="ti"></app-converter-selector>
[(ngModel)]="step.content">{{step.content}}</textarea> <app-error-message [step]="step"></app-error-message>
</div>
<div [ngClass]="{selectwrapper: true, error: step.error}">
<div class="arrow_box">
<select class="select" (change)="convert(step, $event)">
<option id="undefined">Select conversion ...</option>
<option class="option" *ngFor="let c of converters" id="{{c.getId()}}">{{c.getDisplayname()}}
</option>
</select>
</div>
</div>
<div class="errormessage" *ngIf="step.error" [innerHTML]="step.message"></div>
</div> </div>
<app-version></app-version> <app-version></app-version>
<!--<router-outlet></router-outlet>--> <!--<router-outlet></router-outlet>-->

View file

@ -2,106 +2,3 @@
font-family: "ABeeZee", sans-serif; font-family: "ABeeZee", sans-serif;
margin: 0 1em 1em 1em; margin: 0 1em 1em 1em;
} }
.textwrapper {
margin: 0 0 1em 0;
padding: 0 1em 0 0;
}
.arrow_box {
position: relative;
background: #fff;
border: 1px solid #aaa;
&:focus {
border-color: #888;
}
&:hover {
border-color: #333;
}
&:after, &:before {
top: 100%;
left: 50%;
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
pointer-events: none;
}
&:after {
border-color: rgba(255, 255, 255, 0);
border-top-color: #fff;
border-width: 1em;
margin-left: -1em;
}
&:before {
border-color: rgba(170, 170, 170, 0);
border-top-color: #aaa;
border-width: calc(1em + 1px);
margin-left: calc(-1em - 1px);
}
&:focus:before {
border-color: rgba(136, 136, 136, 0);
border-top-color: #888;
}
&:hover:before {
border-color: rgba(51, 51, 51, 0);
border-top-color: #333;
}
.selectwrapper > & {
display: inline-block;
}
}
.textinput {
background-color: #fff;
border: none;
color: #000;
font-family: "Free Monospaced", monospace;
height: 10em;
margin: 0;
padding: 0.5em;
resize: vertical;
width: 100%;
&:focus {
border-color: #888;
}
&:hover {
border-color: #333;
}
}
.selectwrapper {
margin: 0 0 1em 0;
padding: 0;
text-align: center;
&.error {
> .arrow_box {
border-color: red;
&:before {
border-top-color: red;
}
}
select {
color: red;
}
}
}
.select {
background-color: #fff;
border: none;
color: #000;
font-family: "ABeeZee", sans-serif;
margin: 0;
padding: 0.5em;
}
.option {
/* font-family: "ABeeZee", sans-serif;*/
}
.errormessage {
color: red;
text-align: center;
}

View file

@ -1,8 +1,6 @@
import {Component, OnInit} from '@angular/core'; import {Component, OnInit} from '@angular/core';
import {ConverterRegistryService} from './converter-registry.service';
import {InputComponentManagerService} from './input-component-manager.service'; import {InputComponentManagerService} from './input-component-manager.service';
import {Step} from './step'; import {Step} from './step';
import {Converter} from './converter/converter';
@Component({ @Component({
selector: 'app-root', selector: 'app-root',
@ -11,47 +9,11 @@ import {Converter} from './converter/converter';
}) })
export class AppComponent implements OnInit { export class AppComponent implements OnInit {
public steps: Step[] = []; public steps: Step[] = [];
public converters: Converter[] = [];
constructor(private converterRegistryService: ConverterRegistryService, constructor(private inputComponentManagerService: InputComponentManagerService) {
private inputComponentManagerService: InputComponentManagerService) {
}
convert(step: Step, $event: any): void {
step.selectedConverter = this.converterRegistryService.getConverter($event.target.selectedOptions[0].id);
this.update(step);
}
update(step: Step): void {
const converter: Converter = step.selectedConverter;
if (converter !== undefined) {
const content: string = step.content;
let result: string;
try {
result = converter.convert(content);
} catch (error) {
if (typeof console === 'object' && typeof console.log === 'function') {
console.log(error);
}
step.message = error.message;
step.error = true;
result = null;
}
if (result !== null) {
step.message = '';
step.error = false;
if (result !== '') {
const nextComponent: Step = this.inputComponentManagerService.getNext(step);
nextComponent.content = result;
this.update(nextComponent);
}
}
}
} }
ngOnInit(): void { ngOnInit(): void {
this.converters = this.converterRegistryService.getAllConverters();
this.steps = this.inputComponentManagerService.getAllComponents(); this.steps = this.inputComponentManagerService.getAllComponents();
this.inputComponentManagerService.getFirst(); this.inputComponentManagerService.getFirst();
} }

View file

@ -6,11 +6,17 @@ import {InputComponentManagerService} from './input-component-manager.service';
import {NativeLibraryWrapperService} from './native-library-wrapper.service'; import {NativeLibraryWrapperService} from './native-library-wrapper.service';
import {FormsModule} from '@angular/forms'; import {FormsModule} from '@angular/forms';
import {VersionComponent} from './version/version.component'; import {VersionComponent} from './version/version.component';
import { TextInputFieldComponent } from './text-input-field/text-input-field.component';
import { ConverterSelectorComponent } from './converter-selector/converter-selector.component';
import { ErrorMessageComponent } from './error-message/error-message.component';
@NgModule({ @NgModule({
declarations: [ declarations: [
AppComponent, AppComponent,
VersionComponent VersionComponent,
TextInputFieldComponent,
ConverterSelectorComponent,
ErrorMessageComponent
], ],
imports: [ imports: [
BrowserModule, BrowserModule,

View file

@ -0,0 +1,9 @@
<div [ngClass]="{selectwrapper: true, error: step.error}">
<div class="arrow_box">
<select class="select" (change)="convert(step, $event)">
<option id="undefined">Select conversion ...</option>
<option class="option" *ngFor="let c of converters" id="{{c.getId()}}">{{c.getDisplayname()}}
</option>
</select>
</div>
</div>

View file

@ -0,0 +1,74 @@
.selectwrapper {
margin: 0 0 1em 0;
padding: 0;
text-align: center;
&.error {
> .arrow_box {
border-color: red;
&:before {
border-top-color: red;
}
}
select {
color: red;
}
}
}
.select {
background-color: #fff;
border: none;
color: #000;
font-family: "ABeeZee", sans-serif;
margin: 0;
padding: 0.5em;
}
.arrow_box {
position: relative;
background: #fff;
border: 1px solid #aaa;
&:focus {
border-color: #888;
}
&:hover {
border-color: #333;
}
&:after, &:before {
top: 100%;
left: 50%;
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
pointer-events: none;
}
&:after {
border-color: rgba(255, 255, 255, 0);
border-top-color: #fff;
border-width: 1em;
margin-left: -1em;
}
&:before {
border-color: rgba(170, 170, 170, 0);
border-top-color: #aaa;
border-width: calc(1em + 1px);
margin-left: calc(-1em - 1px);
}
&:focus:before {
border-color: rgba(136, 136, 136, 0);
border-top-color: #888;
}
&:hover:before {
border-color: rgba(51, 51, 51, 0);
border-top-color: #333;
}
.selectwrapper > & {
display: inline-block;
}
}
.option {
/* font-family: "ABeeZee", sans-serif;*/
}

View file

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ConverterSelectorComponent } from './converter-selector.component';
describe('ConverterSelectorComponent', () => {
let component: ConverterSelectorComponent;
let fixture: ComponentFixture<ConverterSelectorComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ConverterSelectorComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ConverterSelectorComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View file

@ -0,0 +1,30 @@
import {Component, Input, OnInit} from '@angular/core';
import {Step} from '../step';
import {Converter} from '../converter/converter';
import {ConverterRegistryService} from '../converter-registry.service';
import {TextInputFieldComponent} from '../text-input-field/text-input-field.component';
@Component({
selector: 'app-converter-selector',
templateUrl: './converter-selector.component.html',
styleUrls: ['./converter-selector.component.scss']
})
export class ConverterSelectorComponent implements OnInit {
@Input()
public step: Step;
@Input()
private textInput: TextInputFieldComponent;
public converters: Converter[] = [];
constructor(private converterRegistryService: ConverterRegistryService) {
}
convert(step: Step, $event: any): void {
step.selectedConverter = this.converterRegistryService.getConverter($event.target.selectedOptions[0].id);
this.textInput.update(step);
}
ngOnInit() {
this.converters = this.converterRegistryService.getAllConverters();
}
}

View file

@ -0,0 +1 @@
<div class="errormessage" *ngIf="step.error" [innerHTML]="step.message"></div>

View file

@ -0,0 +1,4 @@
.errormessage {
color: red;
text-align: center;
}

View file

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ErrorMessageComponent } from './error-message.component';
describe('ErrorMessageComponent', () => {
let component: ErrorMessageComponent;
let fixture: ComponentFixture<ErrorMessageComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ErrorMessageComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ErrorMessageComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View file

@ -0,0 +1,15 @@
import {Component, Input} from '@angular/core';
import {Step} from '../step';
@Component({
selector: 'app-error-message',
templateUrl: './error-message.component.html',
styleUrls: ['./error-message.component.scss']
})
export class ErrorMessageComponent {
@Input()
public step: Step;
constructor() {
}
}

View file

@ -0,0 +1,4 @@
<div class="textwrapper arrow_box">
<textarea class="textinput" (keyup)="update(step)" placeholder="Please enter your input ..."
[(ngModel)]="step.content">{{step.content}}</textarea>
</div>

View file

@ -0,0 +1,69 @@
.textwrapper {
margin: 0 0 1em 0;
padding: 0 1em 0 0;
}
.arrow_box {
position: relative;
background: #fff;
border: 1px solid #aaa;
&:focus {
border-color: #888;
}
&:hover {
border-color: #333;
}
&:after, &:before {
top: 100%;
left: 50%;
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
pointer-events: none;
}
&:after {
border-color: rgba(255, 255, 255, 0);
border-top-color: #fff;
border-width: 1em;
margin-left: -1em;
}
&:before {
border-color: rgba(170, 170, 170, 0);
border-top-color: #aaa;
border-width: calc(1em + 1px);
margin-left: calc(-1em - 1px);
}
&:focus:before {
border-color: rgba(136, 136, 136, 0);
border-top-color: #888;
}
&:hover:before {
border-color: rgba(51, 51, 51, 0);
border-top-color: #333;
}
}
.textinput {
background-color: #fff;
border: none;
color: #000;
font-family: "Free Monospaced", monospace;
height: 10em;
margin: 0;
padding: 0.5em;
resize: vertical;
width: 100%;
&:focus {
border-color: #888;
}
&:hover {
border-color: #333;
}
}
.errormessage {
color: red;
text-align: center;
}

View file

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { TextInputFieldComponent } from './text-input-field.component';
describe('TextInputFieldComponent', () => {
let component: TextInputFieldComponent;
let fixture: ComponentFixture<TextInputFieldComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ TextInputFieldComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(TextInputFieldComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View file

@ -0,0 +1,45 @@
import {Component, Input} from '@angular/core';
import {Step} from '../step';
import {Converter} from '../converter/converter';
import {InputComponentManagerService} from '../input-component-manager.service';
@Component({
selector: 'app-text-input-field',
templateUrl: './text-input-field.component.html',
styleUrls: ['./text-input-field.component.scss']
})
export class TextInputFieldComponent {
@Input()
public step: Step;
constructor(private inputComponentManagerService: InputComponentManagerService) {
}
update(step: Step): void {
const converter: Converter = step.selectedConverter;
if (converter !== undefined) {
const content: string = step.content;
let result: string;
try {
result = converter.convert(content);
} catch (error) {
if (typeof console === 'object' && typeof console.log === 'function') {
console.log(error);
}
step.message = error.message;
step.error = true;
result = null;
}
if (result !== null) {
step.message = '';
step.error = false;
if (result !== '') {
const nextComponent: Step = this.inputComponentManagerService.getNext(step);
nextComponent.content = result;
this.update(nextComponent);
}
}
}
}
}