fixed changelog paging

This commit is contained in:
VLE2FE
2020-08-28 16:58:35 +02:00
parent 52e0d94e61
commit 08d5ac8366
26 changed files with 251 additions and 87 deletions

View File

@ -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

View File

@ -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>

View File

@ -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(['/']);
}
});

View File

@ -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,

View File

@ -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) {

View File

@ -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>

View File

@ -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();
});
});

View File

@ -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 {
}
}

View File

@ -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 &lt;app-name, probably definma-api&gt;</li>
<li>cf create-service-key &lt;service-name, probably definmadb&gt; &lt;key-name, can be whatever&gt;</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:&quot;6ebe4c5d-0da3-4347-b484-66894dcf3f27&quot; /username:&quot;&lt:username&gt;&quot;
/password:&quot;&lt:username&gt;&quot; /out:&quot;C:\Path\to\backup\folder&quot;<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>

View File

@ -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

View File

@ -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>

View File

@ -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;

View File

@ -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;

View File

@ -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>

View File

@ -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)]

View File

@ -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);
}

Binary file not shown.

Binary file not shown.

View File

@ -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>

View File

@ -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;
}
}
}