Merge pull request #32 in ~VLE2FE/definma-ui from development to master
* commit '08d5ac8366279aae4da809a545c4949b2d583c6e': fixed changelog paging
This commit is contained in:
		
							
								
								
									
										47
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										47
									
								
								README.md
									
									
									
									
									
								
							@@ -1,6 +1,9 @@
 | 
			
		||||
# DeFinMa - UI
 | 
			
		||||
 | 
			
		||||
This is the Angular front end for the digital fingerprint of plastics web page hosted in the bic
 | 
			
		||||
This is the Angular front end for the DeFinMa web page hosted on the BIC at
 | 
			
		||||
[https://definma.apps.de1.bosch-iot-cloud.com](https://definma.apps.de1.bosch-iot-cloud.com).
 | 
			
		||||
A deep insight into the project structure can be gained in the 
 | 
			
		||||
[Bachelor Thesis](https://definma.apps.de1.bosch-iot-cloud.com/assets/docs/Veit-Lukas_Bachelor-Thesis.pdf).
 | 
			
		||||
 | 
			
		||||
## Bosch styled components
 | 
			
		||||
 | 
			
		||||
@@ -8,7 +11,43 @@ Bosch styled Angular components were added following
 | 
			
		||||
[this](https://connect.bosch.com/blogs/f6aacf06-98dd-440c-b3a7-0c5a4ad4c1bd/entry/Getting_started_a_Bosch_styled_Angular_Project?lang=de_de) 
 | 
			
		||||
guide, included using the `@inst-iot/bosch-angular-ui-components` package.
 | 
			
		||||
 | 
			
		||||
## Testing
 | 
			
		||||
## General structure
 | 
			
		||||
 | 
			
		||||
Unit and e2e tests are implemented and can be executed using `ng test` and `protractor ./e2e/protractor.conf.js` 
 | 
			
		||||
respectively.
 | 
			
		||||
All components are displayed inside of the `app.component`, most of them directly as routes, see 
 | 
			
		||||
[app-routing.module.ts](./src/app/app-routing.module.ts). For all routes except the `/documentation` the user has to be 
 | 
			
		||||
logged in and has to have the right user level. Login is handled by the 
 | 
			
		||||
[login.service](./src/app/services/login.service.ts), which also provides the `canActivate` function.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### Additional components
 | 
			
		||||
 | 
			
		||||
The [error.component](./src/app/error) provides an error pop over.
 | 
			
		||||
 | 
			
		||||
The [help.component](./src/app/help) provides the help information for all pages which can be accessed by the question 
 | 
			
		||||
mark in the top right corner.
 | 
			
		||||
 | 
			
		||||
The [img-magnifier](./src/app/img-magnifier) is used for displaying an image with a magnifying glass when hovering over 
 | 
			
		||||
the image.
 | 
			
		||||
 | 
			
		||||
[rb-custom-inputs](./src/app/rb-custom-inputs) provides Bosch styled components which were not included in the library.
 | 
			
		||||
These are an array input for displaying nested input elements for every array item, a button with icon and a table. 
 | 
			
		||||
 | 
			
		||||
The [models](./src/app/models) folder provides TS classes for database objects.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### Services
 | 
			
		||||
 | 
			
		||||
The [api.service](./src/app/services/api.service.ts) provides API access with integrated authorization and error 
 | 
			
		||||
handling.
 | 
			
		||||
 | 
			
		||||
The [autocomplete.service](./src/app/services/autocomplete.service.ts) uses the _QuickScore_ module for sorting 
 | 
			
		||||
autocomplete results.
 | 
			
		||||
 | 
			
		||||
The [data.service](./src/app/services/data.service.ts) loads some resources needed in multiple Components. Take a look 
 | 
			
		||||
at the `collectionMap` in line 19 for available resources.
 | 
			
		||||
 | 
			
		||||
The [login.service](./src/app/services/login.service.ts) provides login and logout as well as information about the 
 | 
			
		||||
current user.
 | 
			
		||||
 | 
			
		||||
The [validation.service](./src/app/services/validation.service.ts) provides validation together with the
 | 
			
		||||
[validate.directive](./src/app/validate.directive.ts) for Angular Forms.
 | 
			
		||||
 
 | 
			
		||||
@@ -65,9 +65,7 @@
 | 
			
		||||
                  "maximumWarning": "6kb",
 | 
			
		||||
                  "maximumError": "10kb"
 | 
			
		||||
                }
 | 
			
		||||
              ],
 | 
			
		||||
              "serviceWorker": true,
 | 
			
		||||
              "ngswConfigPath": "ngsw-config.json"
 | 
			
		||||
              ]
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
 
 | 
			
		||||
@@ -1,29 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
  "$schema": "./node_modules/@angular/service-worker/config/schema.json",
 | 
			
		||||
  "index": "/index.html",
 | 
			
		||||
  "assetGroups": [
 | 
			
		||||
    {
 | 
			
		||||
      "name": "app",
 | 
			
		||||
      "installMode": "prefetch",
 | 
			
		||||
      "resources": {
 | 
			
		||||
        "files": [
 | 
			
		||||
          "/favicon.ico",
 | 
			
		||||
          "/index.html",
 | 
			
		||||
          "/manifest.webmanifest",
 | 
			
		||||
          "/*.css",
 | 
			
		||||
          "/*.js"
 | 
			
		||||
        ]
 | 
			
		||||
      }
 | 
			
		||||
    }, {
 | 
			
		||||
      "name": "assets",
 | 
			
		||||
      "installMode": "lazy",
 | 
			
		||||
      "updateMode": "prefetch",
 | 
			
		||||
      "resources": {
 | 
			
		||||
        "files": [
 | 
			
		||||
          "/assets/**",
 | 
			
		||||
          "/*.(eot|svg|cur|jpg|png|webp|gif|otf|ttf|woff|woff2|ani)"
 | 
			
		||||
        ]
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
@@ -9,9 +9,10 @@ import {TemplatesComponent} from './templates/templates.component';
 | 
			
		||||
import {SettingsComponent} from './settings/settings.component';
 | 
			
		||||
import {UsersComponent} from './users/users.component';
 | 
			
		||||
import {ChangelogComponent} from './changelog/changelog.component';
 | 
			
		||||
import {DocumentationDatabaseComponent} from './documentation-database/documentation-database.component';
 | 
			
		||||
import {DocumentationDatabaseComponent} from './documentation/documentation-database/documentation-database.component';
 | 
			
		||||
import {PredictionComponent} from './prediction/prediction.component';
 | 
			
		||||
import {ModelTemplatesComponent} from './model-templates/model-templates.component';
 | 
			
		||||
import {DocumentationArchitectureComponent} from './documentation/documentation-architecture/documentation-architecture.component';
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const routes: Routes = [
 | 
			
		||||
@@ -27,6 +28,7 @@ const routes: Routes = [
 | 
			
		||||
  {path: 'users', component: UsersComponent, canActivate: [LoginService]},
 | 
			
		||||
  {path: 'settings', component: SettingsComponent, canActivate: [LoginService]},
 | 
			
		||||
  {path: 'documentation', component: DocumentationComponent},
 | 
			
		||||
  {path: 'documentation/architecture', component: DocumentationArchitectureComponent},
 | 
			
		||||
  {path: 'documentation/database', component: DocumentationDatabaseComponent},
 | 
			
		||||
 | 
			
		||||
  // if not authenticated
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,7 @@
 | 
			
		||||
  <ng-container *ngIf="isDocumentation">
 | 
			
		||||
    <nav *rbSubNavItems>
 | 
			
		||||
      <a routerLink="/documentation" routerLinkActive="active" [routerLinkActiveOptions]="{exact: true}">General</a>
 | 
			
		||||
      <a routerLink="/documentation/architecture" routerLinkActive="active">Architecture</a>
 | 
			
		||||
      <a routerLink="/documentation/database" routerLinkActive="active">Database</a>
 | 
			
		||||
    </nav>
 | 
			
		||||
  </ng-container>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
import {Component, isDevMode, OnInit} from '@angular/core';
 | 
			
		||||
import {LoginService} from './services/login.service';
 | 
			
		||||
import {NavigationStart, Router} from '@angular/router';
 | 
			
		||||
import {ActivatedRoute, NavigationStart, Router} from '@angular/router';
 | 
			
		||||
import {ModalService} from '@inst-iot/bosch-angular-ui-components';
 | 
			
		||||
import {HelpComponent} from './help/help.component';
 | 
			
		||||
import {DataService} from './services/data.service';
 | 
			
		||||
@@ -22,6 +22,7 @@ export class AppComponent implements OnInit{
 | 
			
		||||
  constructor(
 | 
			
		||||
    public login: LoginService,
 | 
			
		||||
    public router: Router,
 | 
			
		||||
    private route: ActivatedRoute,
 | 
			
		||||
    public window: Window,
 | 
			
		||||
    private modal: ModalService,
 | 
			
		||||
    public d: DataService
 | 
			
		||||
@@ -36,7 +37,7 @@ export class AppComponent implements OnInit{
 | 
			
		||||
 | 
			
		||||
  ngOnInit() {
 | 
			
		||||
    this.login.login().then(res => {
 | 
			
		||||
      if (!res) {
 | 
			
		||||
      if (!res && !(this.route.snapshot.url.length && this.route.snapshot.url[0].path === '/documentation')) {
 | 
			
		||||
        this.router.navigate(['/']);
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
 
 | 
			
		||||
@@ -26,13 +26,12 @@ import { ParametersPipe } from './parameters.pipe';
 | 
			
		||||
import { SettingsComponent } from './settings/settings.component';
 | 
			
		||||
import { UsersComponent } from './users/users.component';
 | 
			
		||||
import { ChangelogComponent } from './changelog/changelog.component';
 | 
			
		||||
import { DocumentationDatabaseComponent } from './documentation-database/documentation-database.component';
 | 
			
		||||
import { DocumentationDatabaseComponent } from './documentation/documentation-database/documentation-database.component';
 | 
			
		||||
import { PredictionComponent } from './prediction/prediction.component';
 | 
			
		||||
import { ServiceWorkerModule } from '@angular/service-worker';
 | 
			
		||||
import { environment } from '../environments/environment';
 | 
			
		||||
import { HelpComponent } from './help/help.component';
 | 
			
		||||
import { ModelTemplatesComponent } from './model-templates/model-templates.component';
 | 
			
		||||
import { SizePipe } from './size.pipe';
 | 
			
		||||
import { DocumentationArchitectureComponent } from './documentation/documentation-architecture/documentation-architecture.component';
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
  declarations: [
 | 
			
		||||
@@ -56,7 +55,8 @@ import { SizePipe } from './size.pipe';
 | 
			
		||||
    PredictionComponent,
 | 
			
		||||
    HelpComponent,
 | 
			
		||||
    ModelTemplatesComponent,
 | 
			
		||||
    SizePipe
 | 
			
		||||
    SizePipe,
 | 
			
		||||
    DocumentationArchitectureComponent
 | 
			
		||||
  ],
 | 
			
		||||
  imports: [
 | 
			
		||||
    LocalStorageModule.forRoot({
 | 
			
		||||
@@ -73,8 +73,7 @@ import { SizePipe } from './size.pipe';
 | 
			
		||||
    ReactiveFormsModule,
 | 
			
		||||
    FormFieldsModule,
 | 
			
		||||
    CommonModule,
 | 
			
		||||
    ChartsModule,
 | 
			
		||||
    ServiceWorkerModule.register('ngsw-worker.js', { enabled: environment.production })
 | 
			
		||||
    ChartsModule
 | 
			
		||||
  ],
 | 
			
		||||
  providers: [
 | 
			
		||||
    ModalService,
 | 
			
		||||
 
 | 
			
		||||
@@ -26,7 +26,10 @@ export class ChangelogComponent implements OnInit {
 | 
			
		||||
 | 
			
		||||
  loadChangelog(page = 0) {
 | 
			
		||||
    this.api.get<ChangelogModel[]>(`/changelog/${
 | 
			
		||||
      new Date(new Date(this.timestamp).getTime() - new Date(this.timestamp).getTimezoneOffset() * 60000).toISOString()
 | 
			
		||||
      page > 0 ? this.changelog[0]._id :  // use id if no new date was given
 | 
			
		||||
      Math.floor(new Date(
 | 
			
		||||
        new Date(this.timestamp).getTime() - new Date(this.timestamp).getTimezoneOffset() * 60000  // adjust timezone
 | 
			
		||||
      ).getTime() / 1000).toString(16) + '0000000000000000'  // id from time
 | 
			
		||||
    }/${page}/${this.pageSize}`, data => {
 | 
			
		||||
      this.changelog = data.map(e => new ChangelogModel().deserialize(e));
 | 
			
		||||
      if (page) {
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,50 @@
 | 
			
		||||
<h4>Architecture</h4>
 | 
			
		||||
 | 
			
		||||
<img src="/assets/imgs/architecture.svg" alt="architecture" class="space-below">
 | 
			
		||||
 | 
			
		||||
<p>
 | 
			
		||||
  Bosch IoT Cloud space where all applications are hosted:
 | 
			
		||||
  <a href="https://apps.sys.de1.bosch-iot-cloud.com/organizations/b28baba5-f95f-4ce5-bc9c-3f45acd1dfb2">
 | 
			
		||||
    https://apps.sys.de1.bosch-iot-cloud.com/organizations/b28baba5-f95f-4ce5-bc9c-3f45acd1dfb2
 | 
			
		||||
  </a><br>
 | 
			
		||||
  Find the API documentation here:
 | 
			
		||||
  <a href="https://definma-api.apps.de1.bosch-iot-cloud.com/api-doc/">
 | 
			
		||||
    https://definma-api.apps.de1.bosch-iot-cloud.com/api-doc/
 | 
			
		||||
  </a><br>
 | 
			
		||||
  Admin database management page:
 | 
			
		||||
  <a href="https://definma-db.apps.de1.bosch-iot-cloud.com/api-doc/">
 | 
			
		||||
    https://definma-db.apps.de1.bosch-iot-cloud.com/api-doc/
 | 
			
		||||
  </a><br>
 | 
			
		||||
  Code repository UI
 | 
			
		||||
  <a href="https://sourcecode.socialcoding.bosch.com/users/vle2fe/repos/definma-ui">
 | 
			
		||||
    https://sourcecode.socialcoding.bosch.com/users/vle2fe/repos/definma-ui
 | 
			
		||||
  </a><br>
 | 
			
		||||
  Code repository API
 | 
			
		||||
  <a href="https://sourcecode.socialcoding.bosch.com/users/vle2fe/repos/definma-api">
 | 
			
		||||
    https://sourcecode.socialcoding.bosch.com/users/vle2fe/repos/definma-api
 | 
			
		||||
  </a><br>
 | 
			
		||||
</p>
 | 
			
		||||
 | 
			
		||||
<p>
 | 
			
		||||
  All applications are hosted in the bosch IoT Cloud. The API is hosted in a Node.js container, with a bound MongoDB
 | 
			
		||||
  instance. <br>
 | 
			
		||||
  The Angular UI is hosted in a staticfile container, serving the built Angular bundle. <br>
 | 
			
		||||
  Finally any machine learning models are hosted in Python containers.
 | 
			
		||||
</p>
 | 
			
		||||
 | 
			
		||||
<h4>Development setup</h4>
 | 
			
		||||
 | 
			
		||||
<p>
 | 
			
		||||
  In any case, it is good to have PxProxy working, following the
 | 
			
		||||
  <a href="https://inside-docupedia.bosch.com/confluence/pages/viewpage.action?pageId=608652557">
 | 
			
		||||
    Bosch installation guide
 | 
			
		||||
  </a>. <br>
 | 
			
		||||
  For pushing to the BIC, you need the CloudFoundry CLI as described in the
 | 
			
		||||
  <a href="https://inside-docupedia.bosch.com/confluence/display/BICI/Cloud+Foundry+CLI">BIC documentation</a>.
 | 
			
		||||
  If the the downloaded version of the CLI should not work, there is an old installer with a definitely working version
 | 
			
		||||
  on the file share in the bin folder.
 | 
			
		||||
  Please consider that you need to have a login to the BIC and be marked as space developer for the DeFinMa Org. <br>
 | 
			
		||||
  For front and back end development, you need a
 | 
			
		||||
  <a href="https://www.mongodb.com/try/download/community">local MongoDB server</a> as well as
 | 
			
		||||
  <a href="https://nodejs.org/en/">Node.js</a>.
 | 
			
		||||
</p>
 | 
			
		||||
@@ -0,0 +1,25 @@
 | 
			
		||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
 | 
			
		||||
 | 
			
		||||
import { DocumentationArchitectureComponent } from './documentation-architecture.component';
 | 
			
		||||
 | 
			
		||||
describe('DocumentationArchitectureComponent', () => {
 | 
			
		||||
  let component: DocumentationArchitectureComponent;
 | 
			
		||||
  let fixture: ComponentFixture<DocumentationArchitectureComponent>;
 | 
			
		||||
 | 
			
		||||
  beforeEach(async(() => {
 | 
			
		||||
    TestBed.configureTestingModule({
 | 
			
		||||
      declarations: [ DocumentationArchitectureComponent ]
 | 
			
		||||
    })
 | 
			
		||||
    .compileComponents();
 | 
			
		||||
  }));
 | 
			
		||||
 | 
			
		||||
  beforeEach(() => {
 | 
			
		||||
    fixture = TestBed.createComponent(DocumentationArchitectureComponent);
 | 
			
		||||
    component = fixture.componentInstance;
 | 
			
		||||
    fixture.detectChanges();
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  it('should create', () => {
 | 
			
		||||
    expect(component).toBeTruthy();
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
@@ -0,0 +1,15 @@
 | 
			
		||||
import { Component, OnInit } from '@angular/core';
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'app-documentation-architecture',
 | 
			
		||||
  templateUrl: './documentation-architecture.component.html',
 | 
			
		||||
  styleUrls: ['./documentation-architecture.component.scss']
 | 
			
		||||
})
 | 
			
		||||
export class DocumentationArchitectureComponent implements OnInit {
 | 
			
		||||
 | 
			
		||||
  constructor() { }
 | 
			
		||||
 | 
			
		||||
  ngOnInit(): void {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -1,7 +1,45 @@
 | 
			
		||||
<h2>Database</h2>
 | 
			
		||||
 | 
			
		||||
<p class="space-below">
 | 
			
		||||
  Structure of the MongoDB instance running on the BIC, storing all application data.
 | 
			
		||||
<p>
 | 
			
		||||
  The used database instance is a MongoDB instance running on the BIC, storing all application data. The admin database
 | 
			
		||||
  management page can be accessed
 | 
			
		||||
  <a href="https://definma-db.apps.de1.bosch-iot-cloud.com/api-doc/">
 | 
			
		||||
    https://definma-db.apps.de1.bosch-iot-cloud.com/api-doc/
 | 
			
		||||
  </a>.
 | 
			
		||||
  However, it is recommended to use a dedicated MongoDB application for anything apart from a quick look. The two tested
 | 
			
		||||
  applications are <a href="https://www.mongodb.com/products/compass">MongoDB Compass</a> and
 | 
			
		||||
  <a href="https://robomongo.org/s">Robo 3T</a> (recommended for trying queries).<br>
 | 
			
		||||
  To connect to the BIC instance from your local application follow the
 | 
			
		||||
  <a href="https://inside-docupedia.bosch.com/confluence/display/BICI/MongoDB+Client+Tool+via+SSH+Tunnel">BIC guide</a>.
 | 
			
		||||
  <br>TLDR:
 | 
			
		||||
</p>
 | 
			
		||||
For the first time:
 | 
			
		||||
<ul>
 | 
			
		||||
  <li>cf login</li>
 | 
			
		||||
  <li>cf enable-ssh <app-name, probably definma-api></li>
 | 
			
		||||
  <li>cf create-service-key <service-name, probably definmadb> <key-name, can be whatever></li>
 | 
			
		||||
</ul>
 | 
			
		||||
Every time:
 | 
			
		||||
<ul>
 | 
			
		||||
  <li>cf ssh -L 1120:st0cvm200118.internal-mongodb.de1.bosch-iot-cloud.com:30000 definma-api</li>
 | 
			
		||||
  <li>
 | 
			
		||||
    Login into your application with localhost:1120 and use credentials and Authentication Database from the BIC
 | 
			
		||||
    (Data can be found at Home>DeFinMa>production>definma-api>Services>dots on the right of definmadb>View Credentials)
 | 
			
		||||
  </li>
 | 
			
		||||
</ul>
 | 
			
		||||
 | 
			
		||||
<h6>Backup</h6>
 | 
			
		||||
<p>
 | 
			
		||||
  For creating a database backup, you must follow the same steps from above (except the last one). Additionally you need
 | 
			
		||||
  the <a href="https://www.mongodb.com/try/download/community">MongoDB server</a> installed. Open the MongoDB bin folder
 | 
			
		||||
  (normally at C:\Program Files\MongoDB\Server\4.2\bin) in a PowerShell and execute following command for backup,
 | 
			
		||||
  adjust parameters and credentials as needed: <br><br>
 | 
			
		||||
  mongodump.exe /port:1120 /db:"6ebe4c5d-0da3-4347-b484-66894dcf3f27" /username:"<:username>"
 | 
			
		||||
  /password:"<:username>" /out:"C:\Path\to\backup\folder"<br><br>
 | 
			
		||||
  Restoring the database from a backup is done with mongorestore.exe, more information can be found at the
 | 
			
		||||
  <a href="https://docs.mongodb.com/database-tools/">documentation</a>. <br>
 | 
			
		||||
  The BIC service also creates internal backup, which can be requested to restore, see
 | 
			
		||||
  <a href="https://inside-docupedia.bosch.com/confluence/pages/viewpage.action?pageId=565402281">MongoDB FAQ</a>
 | 
			
		||||
</p>
 | 
			
		||||
 | 
			
		||||
<h4>Database model</h4>
 | 
			
		||||
@@ -274,8 +312,34 @@
 | 
			
		||||
    <td>The API key, generated when the user is created</td>
 | 
			
		||||
    <td>'5f294dd4aa9ea5085c7d7314'</td>
 | 
			
		||||
  </tr>
 | 
			
		||||
  <tr>
 | 
			
		||||
    <td>models</td>
 | 
			
		||||
    <td>
 | 
			
		||||
      Reference to the prediction models the user should have access to. Ignored for <span class="name">dev</span> and
 | 
			
		||||
      <span class="name">admin</span> as they automatically have access to all models.
 | 
			
		||||
    </td>
 | 
			
		||||
    <td>['5f466fb1e566810dd8b3e919', '5f294d8aaa9ea5085c7d730b']</td>
 | 
			
		||||
  </tr>
 | 
			
		||||
  <tr>
 | 
			
		||||
    <td>status</td>
 | 
			
		||||
    <td>Status of the document, can be either <span class="name">new</span>, <span class="name">validated</span> or
 | 
			
		||||
      <span class="name">deleted</span>.</td>
 | 
			
		||||
    <td>'new'</td>
 | 
			
		||||
  </tr>
 | 
			
		||||
 | 
			
		||||
  <tr><th>models</th><th></th><th></th></tr>
 | 
			
		||||
  <tr>
 | 
			
		||||
    <td>group</td>
 | 
			
		||||
    <td>group the model belongs to</td>
 | 
			
		||||
    <td>'VN'</td>
 | 
			
		||||
  </tr>
 | 
			
		||||
  <tr>
 | 
			
		||||
    <td>models</td>
 | 
			
		||||
    <td>models of the group with _id, name and url to the Python endpoint</td>
 | 
			
		||||
    <td>{{'{'}}_id: '5f466fb1e566810dd8b3e919', name: POM, url: 'http://localhost:9099/test'{{'}'}}</td>
 | 
			
		||||
  </tr>
 | 
			
		||||
 | 
			
		||||
  <tr><th>model_files</th><th></th><th></th></tr>
 | 
			
		||||
  <tr>
 | 
			
		||||
    <td>_id</td>
 | 
			
		||||
    <td>Automatically generated unique id</td>
 | 
			
		||||
@@ -2,7 +2,7 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing';
 | 
			
		||||
 | 
			
		||||
import { DocumentationDatabaseComponent } from './documentation-database.component';
 | 
			
		||||
import {Component, Input} from '@angular/core';
 | 
			
		||||
import {RbCustomInputsModule} from '../rb-custom-inputs/rb-custom-inputs.module';
 | 
			
		||||
import {RbCustomInputsModule} from '../../rb-custom-inputs/rb-custom-inputs.module';
 | 
			
		||||
 | 
			
		||||
// TODO
 | 
			
		||||
 | 
			
		||||
@@ -1,30 +1,11 @@
 | 
			
		||||
<h2>Documentation</h2>
 | 
			
		||||
 | 
			
		||||
<p>
 | 
			
		||||
  Bosch IoT Cloud space where all applications are hosted:
 | 
			
		||||
  <a href="https://apps.sys.de1.bosch-iot-cloud.com/organizations/b28baba5-f95f-4ce5-bc9c-3f45acd1dfb2">
 | 
			
		||||
    https://apps.sys.de1.bosch-iot-cloud.com/organizations/b28baba5-f95f-4ce5-bc9c-3f45acd1dfb2
 | 
			
		||||
  </a><br>
 | 
			
		||||
  Find the API documentation here:
 | 
			
		||||
  <a href="https://definma-api.apps.de1.bosch-iot-cloud.com/api-doc/">
 | 
			
		||||
    https://definma-api.apps.de1.bosch-iot-cloud.com/api-doc/
 | 
			
		||||
  </a><br>
 | 
			
		||||
  Code repository UI
 | 
			
		||||
  <a href="https://sourcecode.socialcoding.bosch.com/users/vle2fe/repos/definma-ui">
 | 
			
		||||
    https://sourcecode.socialcoding.bosch.com/users/vle2fe/repos/definma-ui
 | 
			
		||||
  </a><br>
 | 
			
		||||
  Code repository API
 | 
			
		||||
  <a href="https://sourcecode.socialcoding.bosch.com/users/vle2fe/repos/definma-api">
 | 
			
		||||
    https://sourcecode.socialcoding.bosch.com/users/vle2fe/repos/definma-api
 | 
			
		||||
  </a><br>
 | 
			
		||||
</p>
 | 
			
		||||
 | 
			
		||||
<h4>Introduction</h4>
 | 
			
		||||
 | 
			
		||||
<p>
 | 
			
		||||
  <a [href]="api.hostName + '/static/intro-presentation/index.html'">
 | 
			
		||||
    View the presentation explaining the main functions
 | 
			
		||||
  </a>
 | 
			
		||||
  </a><br>
 | 
			
		||||
  View the <a href="/assets/docs/Veit-Lukas_T3000.pdf">T3000 report</a> and
 | 
			
		||||
  <a href="/assets/docs/Veit-Lukas_Bachelor-Thesis.pdf">Bachelor Thesis</a> for an in-depth application description.
 | 
			
		||||
</p>
 | 
			
		||||
 | 
			
		||||
<h4>User levels</h4>
 | 
			
		||||
@@ -96,13 +77,6 @@
 | 
			
		||||
  </tr>
 | 
			
		||||
</rb-table>
 | 
			
		||||
 | 
			
		||||
<h4>Architecture</h4>
 | 
			
		||||
 | 
			
		||||
<img src="/assets/imgs/architecture.svg" alt="architecture" class="space-below">
 | 
			
		||||
 | 
			
		||||
<p>
 | 
			
		||||
  All applications are hosted in the bosch IoT Cloud. The API is hosted in a Node.js container, with a bound MongoDB
 | 
			
		||||
  instance. <br>
 | 
			
		||||
  The Angular UI is hosted in a staticfile container, serving the built Angular bundle. <br>
 | 
			
		||||
  Finally any machine learning models are hosted in Python containers.
 | 
			
		||||
</p>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -42,7 +42,7 @@ export class ModelTemplatesComponent implements OnInit {
 | 
			
		||||
    console.log(this.modelGroup);
 | 
			
		||||
    console.log(this.oldModelGroup);
 | 
			
		||||
    if (this.oldModelGroup !== '' && this.modelGroup !== this.oldModelGroup) {  // group was changed, delete model in old group
 | 
			
		||||
      this.deleteModel(null, this.oldModelGroup, this.oldModelName);
 | 
			
		||||
      this.delete(null, this.oldModelGroup, this.oldModelName);
 | 
			
		||||
    }
 | 
			
		||||
    this.api.post('/model/' + this.modelGroup, this.model, () => {
 | 
			
		||||
      this.newModel = false;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,8 @@
 | 
			
		||||
import {BaseModel} from './base.model';
 | 
			
		||||
import {IdModel} from './id.model';
 | 
			
		||||
 | 
			
		||||
export class ChangelogModel extends BaseModel {
 | 
			
		||||
  _id: IdModel = null;
 | 
			
		||||
  date: Date;
 | 
			
		||||
  action: string;
 | 
			
		||||
  collection: string;
 | 
			
		||||
 
 | 
			
		||||
@@ -13,13 +13,14 @@
 | 
			
		||||
                       [rbFormInputAutocomplete]="autocomplete.bind(this, materialNames)" appValidate="stringOf"
 | 
			
		||||
                       (keydown)="preventDefault($event)" (ngModelChange)="findMaterial($event)" ngModel
 | 
			
		||||
                       [appValidateArgs]="[materialNames]" required [(ngModel)]="material.name" [autofocus]="true"
 | 
			
		||||
                       *ngIf="baseSample.material.name !== undefined || mode === 'new'"
 | 
			
		||||
                       *ngIf="mode === 'new' || (baseSample.material && baseSample.material.name !== undefined)"
 | 
			
		||||
                       title="trade name of the material, eg. Ultradur B4300 G6">
 | 
			
		||||
          <ng-template rbFormValidationMessage="required">Cannot be empty</ng-template>
 | 
			
		||||
          <ng-template rbFormValidationMessage="failure">Unknown material, add properties for new material</ng-template>
 | 
			
		||||
        </rb-form-input>
 | 
			
		||||
        <rb-icon-button class="set-new-material space-below" icon="add" mode="secondary"
 | 
			
		||||
                        (click)="setNewMaterial(!newMaterial)" *ngIf="baseSample.material.name !== undefined">
 | 
			
		||||
                        (click)="setNewMaterial(!newMaterial)"
 | 
			
		||||
                        *ngIf="mode === 'new' || (baseSample.material && baseSample.material.name !== undefined)">
 | 
			
		||||
          New material
 | 
			
		||||
        </rb-icon-button>
 | 
			
		||||
      </div>
 | 
			
		||||
 
 | 
			
		||||
@@ -118,6 +118,7 @@ export class SampleComponent implements OnInit, AfterContentChecked {
 | 
			
		||||
  ) { }
 | 
			
		||||
 | 
			
		||||
  ngOnInit(): void {
 | 
			
		||||
    console.log(this.baseSample);
 | 
			
		||||
    this.mode = this.router.url === '/samples/new' ? 'new' : '';
 | 
			
		||||
    this.loading = 7;
 | 
			
		||||
    this.d.load('materials', () => {
 | 
			
		||||
@@ -378,8 +379,6 @@ export class SampleComponent implements OnInit, AfterContentChecked {
 | 
			
		||||
  cmSave() {  // save measurements and conditions
 | 
			
		||||
    this.samples.forEach(sample => {
 | 
			
		||||
      if (sample.condition.condition_template) {  // condition was set
 | 
			
		||||
        console.log(sample.condition);
 | 
			
		||||
        console.log(this.d.id.conditionTemplates[sample.condition.condition_template]);
 | 
			
		||||
        this.api.put('/sample/' + sample._id,
 | 
			
		||||
          {condition: pick(sample.condition,
 | 
			
		||||
              ['condition_template', ...this.d.id.conditionTemplates[sample.condition.condition_template].parameters.map(e => e.name)]
 | 
			
		||||
 
 | 
			
		||||
@@ -45,7 +45,6 @@ export class ApiService {
 | 
			
		||||
    observable.subscribe(data => {
 | 
			
		||||
      f(data.body, undefined, data.headers.keys().reduce((s, e) => {s[e.toLowerCase()] = data.headers.get(e); return s; }, {}));
 | 
			
		||||
    }, err => {
 | 
			
		||||
      console.log(f.length);
 | 
			
		||||
      if (f.length > 1) {
 | 
			
		||||
        f(undefined, err, undefined);
 | 
			
		||||
      }
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								src/assets/docs/Veit-Lukas_Bachelor-Thesis.pdf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/assets/docs/Veit-Lukas_Bachelor-Thesis.pdf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								src/assets/docs/Veit-Lukas_T3000.pdf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/assets/docs/Veit-Lukas_T3000.pdf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							@@ -6,8 +6,6 @@
 | 
			
		||||
  <base href="/">
 | 
			
		||||
  <meta name="viewport" content="width=device-width, initial-scale=1">
 | 
			
		||||
  <link rel="icon" type="image/x-icon" href="favicon.ico">
 | 
			
		||||
  <link rel="manifest" href="manifest.webmanifest">
 | 
			
		||||
  <meta name="theme-color" content="#1976d2">
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
  <app-root></app-root>
 | 
			
		||||
 
 | 
			
		||||
@@ -46,3 +46,26 @@ button::-moz-focus-inner {
 | 
			
		||||
.supergraphic {
 | 
			
		||||
  background-image: url("/assets/imgs/supergraphic.svg");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//list styles
 | 
			
		||||
ul {
 | 
			
		||||
  margin: 10px 0 10px 25px;
 | 
			
		||||
  padding-left: 10px;
 | 
			
		||||
  list-style: none;
 | 
			
		||||
 | 
			
		||||
  li {
 | 
			
		||||
 | 
			
		||||
    &:before {
 | 
			
		||||
      float: left;
 | 
			
		||||
      content: '';
 | 
			
		||||
      height: 8px;
 | 
			
		||||
      width: 8px;
 | 
			
		||||
      background: rgb(0,0,0);
 | 
			
		||||
      position: relative;
 | 
			
		||||
      top: 0.5em;
 | 
			
		||||
      margin-left: -1.5em;
 | 
			
		||||
      margin-right: .3em;
 | 
			
		||||
      text-align: right;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user