diff --git a/angular.json b/angular.json
index 066b70a..126fb2c 100644
--- a/angular.json
+++ b/angular.json
@@ -26,8 +26,7 @@
"assets": [
"src/favicon.ico",
"src/assets",
- { "glob": "**/*", "input": "./node_modules/@inst-iot/bosch-angular-ui-components/assets", "output": "./assets" },
- "src/Staticfile"
+ { "glob": "**/*", "input": "./node_modules/@inst-iot/bosch-angular-ui-components/assets", "output": "./assets" }
],
"styles": [
"src/styles.scss"
diff --git a/src/Staticfile b/cf_config/Staticfile
similarity index 55%
rename from src/Staticfile
rename to cf_config/Staticfile
index 1b9f882..b6f086b 100644
--- a/src/Staticfile
+++ b/cf_config/Staticfile
@@ -1,4 +1,4 @@
pushstate: enabled
force_https: true
root: UI
-location_include: custom-header.conf
+location_include: ../../headers.conf
diff --git a/cf_config/headers.conf b/cf_config/headers.conf
new file mode 100644
index 0000000..a9ddb9f
--- /dev/null
+++ b/cf_config/headers.conf
@@ -0,0 +1 @@
+add_header Content-Security-Policy "default-src 'none'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self'; font-src 'self'; connect-src https://definma-api.apps.de1.bosch-iot-cloud.com; form-action 'none'; frame-ancestors 'none'; base-uri 'self'";
diff --git a/manifest.yml b/manifest.yml
index 19a5de6..5aa697c 100644
--- a/manifest.yml
+++ b/manifest.yml
@@ -1,9 +1,9 @@
---
applications:
- name: definma
- path: dist/UI
+ path: dist
buildpacks:
- staticfile_buildpack
- memory: 128M
+ memory: 64M
instances: 1
stack: cflinuxfs3
diff --git a/package-lock.json b/package-lock.json
index 7d7b150..cde5a07 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -2316,6 +2316,12 @@
"integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==",
"dev": true
},
+ "acorn-walk": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz",
+ "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==",
+ "dev": true
+ },
"adm-zip": {
"version": "0.4.13",
"resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.13.tgz",
@@ -2892,6 +2898,18 @@
"callsite": "1.0.0"
}
},
+ "bfj": {
+ "version": "6.1.2",
+ "resolved": "https://registry.npmjs.org/bfj/-/bfj-6.1.2.tgz",
+ "integrity": "sha512-BmBJa4Lip6BPRINSZ0BPEIfB1wUY/9rwbwvIHQA1KjX9om29B6id0wnWXq7m3bn5JrUVjeOTnVuhPT1FiHwPGw==",
+ "dev": true,
+ "requires": {
+ "bluebird": "^3.5.5",
+ "check-types": "^8.0.3",
+ "hoopy": "^0.1.4",
+ "tryer": "^1.0.1"
+ }
+ },
"big.js": {
"version": "5.2.2",
"resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz",
@@ -3393,6 +3411,12 @@
"resolved": "https://registry.npmjs.org/chartjs-plugin-datalabels/-/chartjs-plugin-datalabels-0.7.0.tgz",
"integrity": "sha512-PKVUX14nYhH0wcdCpgOoC39Gbzvn6cZ7O9n+bwc02yKD9FTnJ7/TSrBcfebmolFZp1Rcicr9xbT0a5HUbigS7g=="
},
+ "check-types": {
+ "version": "8.0.3",
+ "resolved": "https://registry.npmjs.org/check-types/-/check-types-8.0.3.tgz",
+ "integrity": "sha512-YpeKZngUmG65rLudJ4taU7VLkOCTMhNl/u4ctNC56LQS/zJTyNH0Lrtwm1tfTsbLlwvlfsA2d1c8vCf/Kh2KwQ==",
+ "dev": true
+ },
"chokidar": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.0.tgz",
@@ -4782,6 +4806,12 @@
"is-obj": "^2.0.0"
}
},
+ "duplexer": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
+ "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=",
+ "dev": true
+ },
"duplexify": {
"version": "3.7.1",
"resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz",
@@ -4810,6 +4840,12 @@
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=",
"dev": true
},
+ "ejs": {
+ "version": "2.7.4",
+ "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.7.4.tgz",
+ "integrity": "sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA==",
+ "dev": true
+ },
"electron-to-chromium": {
"version": "1.3.446",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.446.tgz",
@@ -5483,6 +5519,12 @@
"minimatch": "^3.0.3"
}
},
+ "filesize": {
+ "version": "3.6.1",
+ "resolved": "https://registry.npmjs.org/filesize/-/filesize-3.6.1.tgz",
+ "integrity": "sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg==",
+ "dev": true
+ },
"fill-range": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
@@ -5879,6 +5921,16 @@
"integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==",
"dev": true
},
+ "gzip-size": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-5.1.1.tgz",
+ "integrity": "sha512-FNHi6mmoHvs1mxZAds4PpdCS6QG8B4C1krxJsMutgxl5t3+GlRTzzI3NEkifXx2pVsOvJdOGSmIgDhQ55FwdPA==",
+ "dev": true,
+ "requires": {
+ "duplexer": "^0.1.1",
+ "pify": "^4.0.1"
+ }
+ },
"handle-thing": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz",
@@ -6063,6 +6115,12 @@
"minimalistic-crypto-utils": "^1.0.1"
}
},
+ "hoopy": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz",
+ "integrity": "sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ==",
+ "dev": true
+ },
"hosted-git-info": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.4.tgz",
@@ -9242,6 +9300,12 @@
"is-wsl": "^2.1.1"
}
},
+ "opener": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.1.tgz",
+ "integrity": "sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA==",
+ "dev": true
+ },
"opn": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz",
@@ -12914,6 +12978,12 @@
"integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==",
"dev": true
},
+ "tryer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz",
+ "integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==",
+ "dev": true
+ },
"ts-node": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-7.0.1.tgz",
@@ -13726,6 +13796,35 @@
}
}
},
+ "webpack-bundle-analyzer": {
+ "version": "3.8.0",
+ "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.8.0.tgz",
+ "integrity": "sha512-PODQhAYVEourCcOuU+NiYI7WdR8QyELZGgPvB1y2tjbUpbmcQOt5Q7jEK+ttd5se0KSBKD9SXHCEozS++Wllmw==",
+ "dev": true,
+ "requires": {
+ "acorn": "^7.1.1",
+ "acorn-walk": "^7.1.1",
+ "bfj": "^6.1.1",
+ "chalk": "^2.4.1",
+ "commander": "^2.18.0",
+ "ejs": "^2.6.1",
+ "express": "^4.16.3",
+ "filesize": "^3.6.1",
+ "gzip-size": "^5.0.0",
+ "lodash": "^4.17.15",
+ "mkdirp": "^0.5.1",
+ "opener": "^1.5.1",
+ "ws": "^6.0.0"
+ },
+ "dependencies": {
+ "acorn": {
+ "version": "7.3.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.3.1.tgz",
+ "integrity": "sha512-tLc0wSnatxAQHVHUapaHdz72pi9KUyHjq5KyHjGg9Y8Ifdc79pTh2XvI6I1/chZbnM7QtNKzh66ooDogPZSleA==",
+ "dev": true
+ }
+ }
+ },
"webpack-dev-middleware": {
"version": "3.7.2",
"resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.2.tgz",
diff --git a/package.json b/package.json
index 9941ad5..96c6204 100644
--- a/package.json
+++ b/package.json
@@ -5,12 +5,13 @@
"ng": "ng",
"start": "ng serve",
"build": "ng build --prod --aot",
- "build-push": "ng build --prod --aot && cf push",
+ "build-push": "ng build --prod --aot && copy /Y cf_config\\ dist && cf push",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e",
"coverage": "ng test --no-watch --code-coverage",
- "api": "cd C:\\Users\\vle2fe\\Documents\\Code\\API && node dist\\index.js"
+ "api": "cd C:\\Users\\vle2fe\\Documents\\Code\\API && node dist\\index.js",
+ "bundle-report": "ng build --prod --aot --stats-json && webpack-bundle-analyzer dist/UI/stats-es2015.json"
},
"private": true,
"dependencies": {
@@ -54,6 +55,7 @@
"protractor": "~5.4.0",
"ts-node": "~7.0.0",
"tslint": "~5.15.0",
- "typescript": "~3.8.3"
+ "typescript": "~3.8.3",
+ "webpack-bundle-analyzer": "^3.8.0"
}
}
diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts
index d3071c5..25fcf56 100644
--- a/src/app/app-routing.module.ts
+++ b/src/app/app-routing.module.ts
@@ -5,6 +5,7 @@ import {LoginService} from './services/login.service';
import {SampleComponent} from './sample/sample.component';
import {SamplesComponent} from './samples/samples.component';
import {DocumentationComponent} from './documentation/documentation.component';
+import {TemplatesComponent} from './templates/templates.component';
const routes: Routes = [
@@ -13,6 +14,8 @@ const routes: Routes = [
{path: 'samples', component: SamplesComponent, canActivate: [LoginService]},
{path: 'samples/new', component: SampleComponent, canActivate: [LoginService]},
{path: 'samples/edit/:id', component: SampleComponent, canActivate: [LoginService]},
+ {path: 'templates', component: TemplatesComponent}, // TODO: change after development
+ // {path: 'templates', component: TemplatesComponent, canActivate: [LoginService]},
{path: 'documentation', component: DocumentationComponent},
// if not authenticated
diff --git a/src/app/app.component.html b/src/app/app.component.html
index eadcb78..919b47f 100644
--- a/src/app/app.component.html
+++ b/src/app/app.component.html
@@ -2,6 +2,7 @@
diff --git a/src/app/app.component.ts b/src/app/app.component.ts
index fc074c0..77cccbb 100644
--- a/src/app/app.component.ts
+++ b/src/app/app.component.ts
@@ -8,6 +8,13 @@ import {Router} from '@angular/router';
// TODO: filter by not completely filled/no measurements
// TODO: account
// TODO: admin user handling, template pages, validation of samples
+// TODO: activate filter on start typing
+
+// TODO: Build IconComponent free lib version because of CSP
+// TODO: more helmet headers, UI presentatin plan
+// TODO: sort material numbers, filter field measurements
+// TODO: get rid of chart.js (+moment.js) and lodash
+// TODO: look into CSS/XHR/Anfragen tab of console
@Component({
selector: 'app-root',
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index 4fd6a1c..c78cc33 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -11,7 +11,7 @@ import {FormsModule, ReactiveFormsModule} from '@angular/forms';
import {LocalStorageModule} from 'angular-2-local-storage';
import {HttpClientModule} from '@angular/common/http';
import { SamplesComponent } from './samples/samples.component';
-import {RbTableModule} from './rb-table/rb-table.module';
+import {RbCustomInputsModule} from './rb-custom-inputs/rb-custom-inputs.module';
import { SampleComponent } from './sample/sample.component';
import { ValidateDirective } from './validate.directive';
import {CommonModule} from '@angular/common';
@@ -21,6 +21,8 @@ import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
import { DocumentationComponent } from './documentation/documentation.component';
import { ImgMagnifierComponent } from './img-magnifier/img-magnifier.component';
import { ExistsPipe } from './exists.pipe';
+import { TemplatesComponent } from './templates/templates.component';
+import { ParametersPipe } from './parameters.pipe';
@NgModule({
declarations: [
@@ -34,7 +36,9 @@ import { ExistsPipe } from './exists.pipe';
ObjectPipe,
DocumentationComponent,
ImgMagnifierComponent,
- ExistsPipe
+ ExistsPipe,
+ TemplatesComponent,
+ ParametersPipe
],
imports: [
LocalStorageModule.forRoot({
@@ -47,7 +51,7 @@ import { ExistsPipe } from './exists.pipe';
RbUiComponentsModule,
FormsModule,
HttpClientModule,
- RbTableModule,
+ RbCustomInputsModule,
ReactiveFormsModule,
FormFieldsModule,
CommonModule,
diff --git a/src/app/models/sample.model.ts b/src/app/models/sample.model.ts
index 319af04..18cbfc1 100644
--- a/src/app/models/sample.model.ts
+++ b/src/app/models/sample.model.ts
@@ -17,6 +17,7 @@ export class SampleModel extends BaseModel {
note_id: IdModel = null;
user_id: IdModel = null;
notes: {comment: string, sample_references: {sample_id: IdModel, relation: string}[], custom_fields: {[prop: string]: string}} = {comment: '', sample_references: [], custom_fields: {}};
+ added: Date = null;
deserialize(input: any): this {
Object.assign(this, input);
@@ -27,6 +28,9 @@ export class SampleModel extends BaseModel {
if (input.hasOwnProperty('measurements')) {
this.measurements = input.measurements.map(e => new MeasurementModel().deserialize(e));
}
+ if (input.hasOwnProperty('added')) {
+ this.added = new Date(input.added);
+ }
return this;
}
diff --git a/src/app/models/template.model.ts b/src/app/models/template.model.ts
index c6d7099..23cbbe6 100644
--- a/src/app/models/template.model.ts
+++ b/src/app/models/template.model.ts
@@ -4,6 +4,7 @@ import {BaseModel} from './base.model';
export class TemplateModel extends BaseModel {
_id: IdModel = null;
name = '';
- version = 1;
- parameters: {name: string, range: {[prop: string]: any}}[] = [];
+ version = 0;
+ first_id: IdModel = null;
+ parameters: {name: string, range: {[prop: string]: any}, rangeString?: string}[] = [];
}
diff --git a/src/app/object.pipe.ts b/src/app/object.pipe.ts
index 7dc3e50..27c101b 100644
--- a/src/app/object.pipe.ts
+++ b/src/app/object.pipe.ts
@@ -1,4 +1,5 @@
import { Pipe, PipeTransform } from '@angular/core';
+import _ from 'lodash';
@Pipe({
name: 'object',
@@ -6,8 +7,9 @@ import { Pipe, PipeTransform } from '@angular/core';
})
export class ObjectPipe implements PipeTransform {
- transform(value: object): string {
- return value ? JSON.stringify(value) : '';
+ transform(value: object, omit: string[] = []): string {
+ const res = _.omit(value, omit);
+ return res && Object.keys(res).length ? JSON.stringify(res) : '';
}
}
diff --git a/src/app/parameters.pipe.spec.ts b/src/app/parameters.pipe.spec.ts
new file mode 100644
index 0000000..2dc7f21
--- /dev/null
+++ b/src/app/parameters.pipe.spec.ts
@@ -0,0 +1,8 @@
+import { ParametersPipe } from './parameters.pipe';
+
+describe('ParametersPipe', () => {
+ it('create an instance', () => {
+ const pipe = new ParametersPipe();
+ expect(pipe).toBeTruthy();
+ });
+});
diff --git a/src/app/parameters.pipe.ts b/src/app/parameters.pipe.ts
new file mode 100644
index 0000000..c3372e1
--- /dev/null
+++ b/src/app/parameters.pipe.ts
@@ -0,0 +1,12 @@
+import { Pipe, PipeTransform } from '@angular/core';
+
+@Pipe({
+ name: 'parameters'
+})
+export class ParametersPipe implements PipeTransform {
+
+ transform(value: {name: string, range: object}[]): string {
+ return `{${value.map(e => `${e.name}: <${JSON.stringify(e.range).replace('{}', 'any').replace(/["{}]/g, '')}>`).join(', ')}}`;
+ }
+
+}
diff --git a/src/app/rb-custom-inputs/rb-array-input/array-input-helper.service.spec.ts b/src/app/rb-custom-inputs/rb-array-input/array-input-helper.service.spec.ts
new file mode 100644
index 0000000..9c60a48
--- /dev/null
+++ b/src/app/rb-custom-inputs/rb-array-input/array-input-helper.service.spec.ts
@@ -0,0 +1,16 @@
+import { TestBed } from '@angular/core/testing';
+
+import { ArrayInputHelperService } from './array-input-helper.service';
+
+describe('ArrayInputHelperService', () => {
+ let service: ArrayInputHelperService;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({});
+ service = TestBed.inject(ArrayInputHelperService);
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+});
diff --git a/src/app/rb-custom-inputs/rb-array-input/array-input-helper.service.ts b/src/app/rb-custom-inputs/rb-array-input/array-input-helper.service.ts
new file mode 100644
index 0000000..5f71f55
--- /dev/null
+++ b/src/app/rb-custom-inputs/rb-array-input/array-input-helper.service.ts
@@ -0,0 +1,26 @@
+import { Injectable } from '@angular/core';
+import {Observable, Subject} from 'rxjs';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class ArrayInputHelperService {
+
+ com: Subject<{ id: string, index: number, value: any }> = new Subject();
+
+ constructor() { }
+
+ values(id: string) {
+ return new Observable<{index: number, value: any}>(observer => {
+ this.com.subscribe(data => {
+ if (data.id === id) {
+ observer.next({index: data.index, value: data.value});
+ }
+ });
+ });
+ }
+
+ newValue(id: string, index: number, value: any) {
+ this.com.next({id, index, value});
+ }
+}
diff --git a/src/app/rb-custom-inputs/rb-array-input/rb-array-input.component.html b/src/app/rb-custom-inputs/rb-array-input/rb-array-input.component.html
new file mode 100644
index 0000000..d68f8c8
--- /dev/null
+++ b/src/app/rb-custom-inputs/rb-array-input/rb-array-input.component.html
@@ -0,0 +1,3 @@
+
+
+
diff --git a/src/app/rb-custom-inputs/rb-array-input/rb-array-input.component.scss b/src/app/rb-custom-inputs/rb-array-input/rb-array-input.component.scss
new file mode 100644
index 0000000..e69de29
diff --git a/src/app/rb-custom-inputs/rb-array-input/rb-array-input.component.spec.ts b/src/app/rb-custom-inputs/rb-array-input/rb-array-input.component.spec.ts
new file mode 100644
index 0000000..1e0acad
--- /dev/null
+++ b/src/app/rb-custom-inputs/rb-array-input/rb-array-input.component.spec.ts
@@ -0,0 +1,25 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { RbArrayInputComponent } from './rb-array-input.component';
+
+describe('RbArrayInputComponent', () => {
+ let component: RbArrayInputComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ RbArrayInputComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(RbArrayInputComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/rb-custom-inputs/rb-array-input/rb-array-input.component.ts b/src/app/rb-custom-inputs/rb-array-input/rb-array-input.component.ts
new file mode 100644
index 0000000..e258217
--- /dev/null
+++ b/src/app/rb-custom-inputs/rb-array-input/rb-array-input.component.ts
@@ -0,0 +1,107 @@
+import {
+ AfterViewInit,
+ Component,
+ ContentChild,
+ Directive,
+ forwardRef,
+ HostListener,
+ Input,
+ OnInit,
+ TemplateRef
+} from '@angular/core';
+import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms';
+import _ from 'lodash';
+import {ArrayInputHelperService} from './array-input-helper.service';
+
+// TODO: implement everywhere
+
+@Directive({ // directive for template and input values
+ // tslint:disable-next-line:directive-selector
+ selector: '[rbArrayInputItem]'
+})
+export class RbArrayInputItemDirective {
+ constructor(public templateRef: TemplateRef) {
+ }
+}
+
+@Directive({ // directive for change detection
+ // tslint:disable-next-line:directive-selector
+ selector: '[rbArrayInputListener]'
+})
+export class RbArrayInputListenerDirective {
+
+ @Input() rbArrayInputListener: string;
+ @Input() index: number;
+
+ constructor(
+ private helperService: ArrayInputHelperService
+ ) { }
+
+ @HostListener('ngModelChange', ['$event'])
+ onChange(event) {
+ console.log(event);
+ this.helperService.newValue(this.rbArrayInputListener, this.index, event);
+ }
+}
+
+
+@Component({
+ // tslint:disable-next-line:component-selector
+ selector: 'rb-array-input',
+ templateUrl: './rb-array-input.component.html',
+ styleUrls: ['./rb-array-input.component.scss'],
+ providers: [{provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => RbArrayInputComponent), multi: true}]
+})
+export class RbArrayInputComponent implements ControlValueAccessor, OnInit, AfterViewInit {
+
+ @Input() pushTemplate: any;
+ @Input() pushPath: string;
+
+ @ContentChild(RbArrayInputItemDirective) item: RbArrayInputItemDirective;
+ @ContentChild(RbArrayInputListenerDirective) item2: RbArrayInputListenerDirective;
+
+ values = []; // main array to display
+
+ onChange = (ignore?: any): void => {};
+ onTouched = (ignore?: any): void => {};
+
+
+ constructor(
+ private helperService: ArrayInputHelperService
+ ) { }
+
+ ngOnInit(): void {
+ }
+
+ ngAfterViewInit() {
+ setTimeout(() => { // needed to find reference
+ this.helperService.values(this.item2.rbArrayInputListener).subscribe(data => { // action on value change
+ this.values[data.index][this.pushPath] = data.value;
+ console.log(this.values);
+ if (this.values[this.values.length - 1][this.pushPath] === '' && this.values[this.values.length - 2][this.pushPath] === '') { // remove last element if last two are empty
+ this.values.pop();
+ }
+ else if (this.values[this.values.length - 1][this.pushPath] !== '') { // add element if last one is filled
+ this.values.push(_.cloneDeep(this.pushTemplate));
+ }
+ this.onChange(this.values.filter(e => e !== '')); // trigger ngModel with filled elements
+ });
+ }, 0);
+ }
+
+ writeValue(obj: any) { // add empty value on init
+ this.values = obj ? obj : [];
+ if (this.values.length === 0 || this.values[0] !== '') {
+ console.log(this.values);
+ this.values.push(_.cloneDeep(this.pushTemplate));
+ }
+ }
+
+ registerOnChange(fn: any) {
+ this.onChange = fn;
+ }
+
+ registerOnTouched(fn: any) {
+ this.onTouched = fn;
+ }
+}
diff --git a/src/app/rb-custom-inputs/rb-custom-inputs.module.ts b/src/app/rb-custom-inputs/rb-custom-inputs.module.ts
new file mode 100644
index 0000000..890205f
--- /dev/null
+++ b/src/app/rb-custom-inputs/rb-custom-inputs.module.ts
@@ -0,0 +1,32 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { RbTableComponent } from './rb-table/rb-table.component';
+import {RbArrayInputComponent, RbArrayInputListenerDirective, RbArrayInputItemDirective} from './rb-array-input/rb-array-input.component';
+import {RbUiComponentsModule} from '@inst-iot/bosch-angular-ui-components';
+import {FormsModule} from '@angular/forms';
+import { RbIconButtonComponent } from './rb-icon-button/rb-icon-button.component';
+
+
+
+@NgModule({
+ declarations: [
+ RbTableComponent,
+ RbArrayInputComponent,
+ RbArrayInputListenerDirective,
+ RbArrayInputItemDirective,
+ RbIconButtonComponent
+ ],
+ imports: [
+ CommonModule,
+ FormsModule,
+ RbUiComponentsModule
+ ],
+ exports: [
+ RbTableComponent,
+ RbArrayInputComponent,
+ RbArrayInputListenerDirective,
+ RbArrayInputItemDirective,
+ RbIconButtonComponent
+ ]
+})
+export class RbCustomInputsModule { }
diff --git a/src/app/rb-custom-inputs/rb-icon-button/rb-icon-button.component.html b/src/app/rb-custom-inputs/rb-icon-button/rb-icon-button.component.html
new file mode 100644
index 0000000..33826bc
--- /dev/null
+++ b/src/app/rb-custom-inputs/rb-icon-button/rb-icon-button.component.html
@@ -0,0 +1,4 @@
+
diff --git a/src/app/rb-custom-inputs/rb-icon-button/rb-icon-button.component.scss b/src/app/rb-custom-inputs/rb-icon-button/rb-icon-button.component.scss
new file mode 100644
index 0000000..e69de29
diff --git a/src/app/rb-custom-inputs/rb-icon-button/rb-icon-button.component.spec.ts b/src/app/rb-custom-inputs/rb-icon-button/rb-icon-button.component.spec.ts
new file mode 100644
index 0000000..dad6730
--- /dev/null
+++ b/src/app/rb-custom-inputs/rb-icon-button/rb-icon-button.component.spec.ts
@@ -0,0 +1,25 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { RbIconButtonComponent } from './rb-icon-button.component';
+
+describe('RbIconButtonComponent', () => {
+ let component: RbIconButtonComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ RbIconButtonComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(RbIconButtonComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/rb-custom-inputs/rb-icon-button/rb-icon-button.component.ts b/src/app/rb-custom-inputs/rb-icon-button/rb-icon-button.component.ts
new file mode 100644
index 0000000..f48ebf7
--- /dev/null
+++ b/src/app/rb-custom-inputs/rb-icon-button/rb-icon-button.component.ts
@@ -0,0 +1,22 @@
+import {Component, Input, OnInit} from '@angular/core';
+
+// TODO: apply everywhere
+
+@Component({
+ // tslint:disable-next-line:component-selector
+ selector: 'rb-icon-button',
+ templateUrl: './rb-icon-button.component.html',
+ styleUrls: ['./rb-icon-button.component.scss']
+})
+export class RbIconButtonComponent implements OnInit {
+
+ @Input() icon: string;
+ @Input() mode: string;
+ @Input() disabled;
+
+ constructor() { }
+
+ ngOnInit(): void {
+ }
+
+}
diff --git a/src/app/rb-table/rb-table/rb-table.component.html b/src/app/rb-custom-inputs/rb-table/rb-table.component.html
similarity index 100%
rename from src/app/rb-table/rb-table/rb-table.component.html
rename to src/app/rb-custom-inputs/rb-table/rb-table.component.html
diff --git a/src/app/rb-table/rb-table/rb-table.component.scss b/src/app/rb-custom-inputs/rb-table/rb-table.component.scss
similarity index 100%
rename from src/app/rb-table/rb-table/rb-table.component.scss
rename to src/app/rb-custom-inputs/rb-table/rb-table.component.scss
diff --git a/src/app/rb-table/rb-table/rb-table.component.spec.ts b/src/app/rb-custom-inputs/rb-table/rb-table.component.spec.ts
similarity index 100%
rename from src/app/rb-table/rb-table/rb-table.component.spec.ts
rename to src/app/rb-custom-inputs/rb-table/rb-table.component.spec.ts
diff --git a/src/app/rb-table/rb-table/rb-table.component.ts b/src/app/rb-custom-inputs/rb-table/rb-table.component.ts
similarity index 85%
rename from src/app/rb-table/rb-table/rb-table.component.ts
rename to src/app/rb-custom-inputs/rb-table/rb-table.component.ts
index 6394052..67e4f68 100644
--- a/src/app/rb-table/rb-table/rb-table.component.ts
+++ b/src/app/rb-custom-inputs/rb-table/rb-table.component.ts
@@ -1,6 +1,7 @@
import { Component, OnInit } from '@angular/core';
@Component({
+ // tslint:disable-next-line:component-selector
selector: 'rb-table',
templateUrl: './rb-table.component.html',
styleUrls: ['./rb-table.component.scss']
diff --git a/src/app/rb-table/rb-table.module.ts b/src/app/rb-table/rb-table.module.ts
deleted file mode 100644
index 37ff2ed..0000000
--- a/src/app/rb-table/rb-table.module.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import { NgModule } from '@angular/core';
-import { CommonModule } from '@angular/common';
-import { RbTableComponent } from './rb-table/rb-table.component';
-
-
-
-@NgModule({
- declarations: [
- RbTableComponent
- ],
- imports: [
- CommonModule
- ],
- exports: [
- RbTableComponent
- ]
-})
-export class RbTableModule { }
diff --git a/src/app/samples/samples.component.html b/src/app/samples/samples.component.html
index 1e453bb..4056ef8 100644
--- a/src/app/samples/samples.component.html
+++ b/src/app/samples/samples.component.html
@@ -1,3 +1,4 @@
+