Merge pull request #15 in ~VLE2FE/definma-ui from development to master
* commit 'c0b410c4830179c6f5dcc41901da4b234134ee8e': fixed material numbers in new dialog fixed new sample material group/supplier autocomplete, template refresh after changes, template array input
This commit is contained in:
		@@ -8,6 +8,7 @@ import {DocumentationComponent} from './documentation/documentation.component';
 | 
			
		||||
import {TemplatesComponent} from './templates/templates.component';
 | 
			
		||||
import {SettingsComponent} from './settings/settings.component';
 | 
			
		||||
import {UsersComponent} from './users/users.component';
 | 
			
		||||
import {ChangelogComponent} from './changelog/changelog.component';
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const routes: Routes = [
 | 
			
		||||
@@ -17,6 +18,7 @@ const routes: Routes = [
 | 
			
		||||
  {path: 'samples/new', component: SampleComponent, canActivate: [LoginService]},
 | 
			
		||||
  {path: 'samples/edit/:id', component: SampleComponent, canActivate: [LoginService]},
 | 
			
		||||
  {path: 'templates', component: TemplatesComponent, canActivate: [LoginService]},
 | 
			
		||||
  {path: 'changelog', component: ChangelogComponent, canActivate: [LoginService]},
 | 
			
		||||
  {path: 'users', component: UsersComponent, canActivate: [LoginService]},
 | 
			
		||||
  {path: 'settings', component: SettingsComponent, canActivate: [LoginService]},
 | 
			
		||||
  {path: 'documentation', component: DocumentationComponent},
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,7 @@
 | 
			
		||||
    <a routerLink="/templates" routerLinkActive="active" rbLoadingLink *ngIf="login.isLevel.dev">
 | 
			
		||||
      Templates
 | 
			
		||||
    </a>
 | 
			
		||||
    <a routerLink="/changelog" routerLinkActive="active" rbLoadingLink *ngIf="login.isLevel.dev">Changelog</a>
 | 
			
		||||
    <a routerLink="/users" routerLinkActive="active" rbLoadingLink *ngIf="login.isLevel.admin">Users</a>
 | 
			
		||||
    <a routerLink="/documentation" routerLinkActive="active" rbLoadingLink>Documentation</a>
 | 
			
		||||
  </nav>
 | 
			
		||||
@@ -32,7 +33,7 @@
 | 
			
		||||
        <rb-icon-button icon="mail" mode="primary" (mouseup)="closeBugReport(close)">Send report</rb-icon-button>
 | 
			
		||||
      </a>
 | 
			
		||||
    </ng-template>
 | 
			
		||||
<!--    <span class="dev-label" *ngIf="devMode">DEVELOPMENT</span>-->
 | 
			
		||||
    <span class="dev-label" *ngIf="devMode">DEVELOPMENT</span>
 | 
			
		||||
    DeFinMa
 | 
			
		||||
  </div>
 | 
			
		||||
</rb-full-header>
 | 
			
		||||
 
 | 
			
		||||
@@ -25,6 +25,7 @@ import { TemplatesComponent } from './templates/templates.component';
 | 
			
		||||
import { ParametersPipe } from './parameters.pipe';
 | 
			
		||||
import { SettingsComponent } from './settings/settings.component';
 | 
			
		||||
import { UsersComponent } from './users/users.component';
 | 
			
		||||
import { ChangelogComponent } from './changelog/changelog.component';
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
  declarations: [
 | 
			
		||||
@@ -42,7 +43,8 @@ import { UsersComponent } from './users/users.component';
 | 
			
		||||
    TemplatesComponent,
 | 
			
		||||
    ParametersPipe,
 | 
			
		||||
    SettingsComponent,
 | 
			
		||||
    UsersComponent
 | 
			
		||||
    UsersComponent,
 | 
			
		||||
    ChangelogComponent
 | 
			
		||||
  ],
 | 
			
		||||
  imports: [
 | 
			
		||||
    LocalStorageModule.forRoot({
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										35
									
								
								src/app/changelog/changelog.component.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								src/app/changelog/changelog.component.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,35 @@
 | 
			
		||||
<h2>Changelog</h2>
 | 
			
		||||
 | 
			
		||||
<div class="header">
 | 
			
		||||
  <rb-form-date-input name="dateInput" label="older than" [options]="{enableTime: true}"
 | 
			
		||||
                      [(ngModel)]="timestamp" (ngModelChange)="loadChangelog()">
 | 
			
		||||
  </rb-form-date-input>
 | 
			
		||||
 | 
			
		||||
  <rb-form-select name="pageSizeSelection" label="page size" [(ngModel)]="pageSize" (ngModelChange)="loadChangelog()">
 | 
			
		||||
    <option value="3">3</option>
 | 
			
		||||
    <option value="10">10</option>
 | 
			
		||||
    <option value="25">25</option>
 | 
			
		||||
    <option value="50">50</option>
 | 
			
		||||
    <option value="100">100</option>
 | 
			
		||||
    <option value="250">250</option>
 | 
			
		||||
    <option value="500">500</option>
 | 
			
		||||
  </rb-form-select>
 | 
			
		||||
 | 
			
		||||
  <button class="rb-btn rb-link" type="button" (click)="loadChangelog(1)">
 | 
			
		||||
    next page
 | 
			
		||||
    <span class="rb-ic  rb-ic-forward-right"></span>
 | 
			
		||||
  </button>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<rb-table>
 | 
			
		||||
  <tr>
 | 
			
		||||
    <th>Date</th>
 | 
			
		||||
    <th>Action</th>
 | 
			
		||||
    <th>Data</th>
 | 
			
		||||
  </tr>
 | 
			
		||||
  <tr *ngFor="let entry of changelog">
 | 
			
		||||
    <td>{{entry.date}}</td>
 | 
			
		||||
    <td>{{entry.action}}</td>
 | 
			
		||||
    <td>{{entry.data | json}}</td>
 | 
			
		||||
  </tr>
 | 
			
		||||
</rb-table>
 | 
			
		||||
							
								
								
									
										10
									
								
								src/app/changelog/changelog.component.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/app/changelog/changelog.component.scss
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
			
		||||
.header {
 | 
			
		||||
 | 
			
		||||
  & > * {
 | 
			
		||||
    float: left;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  button {
 | 
			
		||||
    float: right;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										25
									
								
								src/app/changelog/changelog.component.spec.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/app/changelog/changelog.component.spec.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
			
		||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
 | 
			
		||||
 | 
			
		||||
import { ChangelogComponent } from './changelog.component';
 | 
			
		||||
 | 
			
		||||
describe('ChangelogComponent', () => {
 | 
			
		||||
  let component: ChangelogComponent;
 | 
			
		||||
  let fixture: ComponentFixture<ChangelogComponent>;
 | 
			
		||||
 | 
			
		||||
  beforeEach(async(() => {
 | 
			
		||||
    TestBed.configureTestingModule({
 | 
			
		||||
      declarations: [ ChangelogComponent ]
 | 
			
		||||
    })
 | 
			
		||||
    .compileComponents();
 | 
			
		||||
  }));
 | 
			
		||||
 | 
			
		||||
  beforeEach(() => {
 | 
			
		||||
    fixture = TestBed.createComponent(ChangelogComponent);
 | 
			
		||||
    component = fixture.componentInstance;
 | 
			
		||||
    fixture.detectChanges();
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  it('should create', () => {
 | 
			
		||||
    expect(component).toBeTruthy();
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										32
									
								
								src/app/changelog/changelog.component.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/app/changelog/changelog.component.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,32 @@
 | 
			
		||||
import { Component, OnInit } from '@angular/core';
 | 
			
		||||
import {ChangelogModel} from '../models/changelog.model';
 | 
			
		||||
import {ApiService} from '../services/api.service';
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'app-changelog',
 | 
			
		||||
  templateUrl: './changelog.component.html',
 | 
			
		||||
  styleUrls: ['./changelog.component.scss']
 | 
			
		||||
})
 | 
			
		||||
export class ChangelogComponent implements OnInit {
 | 
			
		||||
 | 
			
		||||
  timestamp = new Date();
 | 
			
		||||
  pageSize = 25;
 | 
			
		||||
  changelog: ChangelogModel[] = [];
 | 
			
		||||
 | 
			
		||||
  constructor(
 | 
			
		||||
    private api: ApiService
 | 
			
		||||
  ) { }
 | 
			
		||||
 | 
			
		||||
  ngOnInit(): void {
 | 
			
		||||
    this.loadChangelog();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  loadChangelog(page = 0) {
 | 
			
		||||
    this.api.get<ChangelogModel[]>(`/changelog/${this.timestamp.toISOString()}/${page}/${this.pageSize}`, data => {
 | 
			
		||||
      this.changelog = data.map(e => new ChangelogModel().deserialize(e));
 | 
			
		||||
      this.timestamp = new Date(this.changelog[0].date);
 | 
			
		||||
      console.log(this.changelog);
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										7
									
								
								src/app/models/changelog.model.spec.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								src/app/models/changelog.model.spec.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
			
		||||
import { ChangelogModel } from './changelog.model';
 | 
			
		||||
 | 
			
		||||
describe('ChangelogModel', () => {
 | 
			
		||||
  it('should create an instance', () => {
 | 
			
		||||
    expect(new ChangelogModel()).toBeTruthy();
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										9
									
								
								src/app/models/changelog.model.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/app/models/changelog.model.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
			
		||||
import {BaseModel} from './base.model';
 | 
			
		||||
 | 
			
		||||
export class ChangelogModel extends BaseModel {
 | 
			
		||||
  date: Date;
 | 
			
		||||
  action: string;
 | 
			
		||||
  collection: string;
 | 
			
		||||
  conditions: {[key: string]: any};
 | 
			
		||||
  data: {[key: string]: any};
 | 
			
		||||
}
 | 
			
		||||
@@ -19,16 +19,17 @@
 | 
			
		||||
    <div class="material shaded-container" *ngIf="newMaterial" [@inOut]>
 | 
			
		||||
      <h4>Material properties</h4>
 | 
			
		||||
      <rb-form-input name="supplier" label="supplier"
 | 
			
		||||
                     [rbFormInputAutocomplete]="autocomplete.bind(this, d.arr.materialSupplier)"
 | 
			
		||||
                     [rbFormInputAutocomplete]="autocomplete.bind(this, d.arr.materialSuppliers)"
 | 
			
		||||
                     [rbDebounceTime]="0" [rbInitialOpen]="true" appValidate="string" required
 | 
			
		||||
                     [(ngModel)]="material.supplier" #supplierInput="ngModel"
 | 
			
		||||
                     (focusout)="checkTypo('materialSuppliers', 'supplier', modalWarning)">
 | 
			
		||||
                     (focusout)="checkTypo($event, 'materialSuppliers', 'supplier', modalWarning)">
 | 
			
		||||
        <ng-template rbFormValidationMessage="failure">{{supplierInput.errors.failure}}</ng-template>
 | 
			
		||||
      </rb-form-input>
 | 
			
		||||
      <rb-form-input name="group" label="group" [rbFormInputAutocomplete]="autocomplete.bind(this, d.arr.materialGroup)"
 | 
			
		||||
      <rb-form-input name="group" label="group"
 | 
			
		||||
                     [rbFormInputAutocomplete]="autocomplete.bind(this, d.arr.materialGroups)"
 | 
			
		||||
                     [rbDebounceTime]="0" [rbInitialOpen]="true" appValidate="string" required
 | 
			
		||||
                     [(ngModel)]="material.group" #groupInput="ngModel"
 | 
			
		||||
                     (focusout)="checkTypo('materialGroups', 'group', modalWarning)">
 | 
			
		||||
                     (focusout)="checkTypo($event, 'materialGroups', 'group', modalWarning)">
 | 
			
		||||
        <ng-template rbFormValidationMessage="failure">{{groupInput.errors.failure}}</ng-template>
 | 
			
		||||
      </rb-form-input>
 | 
			
		||||
      <ng-template #modalWarning>
 | 
			
		||||
@@ -44,7 +45,7 @@
 | 
			
		||||
      </rb-array-input>
 | 
			
		||||
      <rb-form-select name="conditionSelect" label="Type"
 | 
			
		||||
                      [(ngModel)]="material.properties.material_template">
 | 
			
		||||
        <option *ngFor="let m of d.arr.materialTemplates" [value]="m._id">{{m.name}}</option>
 | 
			
		||||
        <option *ngFor="let m of d.latest.materialTemplates" [value]="m._id">{{m.name}}</option>
 | 
			
		||||
      </rb-form-select>
 | 
			
		||||
      <rb-form-input *ngFor="let parameter of d.id.materialTemplates[material.properties.material_template].parameters;
 | 
			
		||||
                     index as i" [name]="'materialParameter' + i"
 | 
			
		||||
@@ -157,7 +158,7 @@
 | 
			
		||||
        <div *ngIf="gSample.condition.condition_template" [@inOut]>
 | 
			
		||||
          <rb-form-select name="conditionSelect" label="Condition"
 | 
			
		||||
                          [(ngModel)]="gSample.condition.condition_template">
 | 
			
		||||
            <option *ngFor="let c of d.arr.conditionTemplates" [value]="c._id">{{c.name}}</option>
 | 
			
		||||
            <option *ngFor="let c of d.latest.conditionTemplates" [value]="c._id">{{c.name}}</option>
 | 
			
		||||
          </rb-form-select>
 | 
			
		||||
 | 
			
		||||
          <ng-container *ngFor="let parameter of
 | 
			
		||||
@@ -186,7 +187,7 @@
 | 
			
		||||
          <rb-form-select [name]="'measurementTemplateSelect-' + gIndex + '-' + mIndex" label="Template"
 | 
			
		||||
                          [(ngModel)]="measurement.measurement_template"
 | 
			
		||||
                          (ngModelChange)="clearMeasurement(gIndex, mIndex)">
 | 
			
		||||
            <option *ngFor="let m of d.arr.measurementTemplates" [value]="m._id">{{m.name}}</option>
 | 
			
		||||
            <option *ngFor="let m of d.latest.measurementTemplates" [value]="m._id">{{m.name}}</option>
 | 
			
		||||
          </rb-form-select>
 | 
			
		||||
 | 
			
		||||
          <div *ngFor="let parameter of d.id.measurementTemplates[measurement.measurement_template].parameters;
 | 
			
		||||
 
 | 
			
		||||
@@ -139,7 +139,7 @@ export class SampleComponent implements OnInit, AfterContentChecked {
 | 
			
		||||
    });
 | 
			
		||||
    this.d.load('materialTemplates', () => {
 | 
			
		||||
      if (!this.material.properties.material_template) {
 | 
			
		||||
        this.material.properties.material_template = this.d.arr.materialTemplates.filter(e => e.name === 'plastic').reverse()[0]._id;
 | 
			
		||||
        this.material.properties.material_template = this.d.latest.materialTemplates.find(e => e.name === 'plastic')._id;
 | 
			
		||||
      }
 | 
			
		||||
      this.loading--;
 | 
			
		||||
    });
 | 
			
		||||
@@ -270,6 +270,8 @@ export class SampleComponent implements OnInit, AfterContentChecked {
 | 
			
		||||
    }
 | 
			
		||||
    new Promise<void>(resolve => {
 | 
			
		||||
      if (this.newMaterial) {  // save material first if new one exists
 | 
			
		||||
        console.log(this.material);
 | 
			
		||||
        this.material.numbers = this.material.numbers.filter(e => e !== '');
 | 
			
		||||
        this.api.post<MaterialModel>('/material/new', this.material.sendFormat(), data => {
 | 
			
		||||
          this.d.arr.materials.push(data);  // add material to data
 | 
			
		||||
          this.material = data;
 | 
			
		||||
@@ -348,7 +350,7 @@ export class SampleComponent implements OnInit, AfterContentChecked {
 | 
			
		||||
    else {  // no matching material found
 | 
			
		||||
      if (this.sample.material_id !== null) {  // reset previous match
 | 
			
		||||
        this.material = new MaterialModel();
 | 
			
		||||
        this.material.properties.material_template = this.d.arr.materialTemplates.filter(e => e.name === 'plastic').reverse()[0]._id;
 | 
			
		||||
        this.material.properties.material_template = this.d.latest.materialTemplates.find(e => e.name === 'plastic')._id;
 | 
			
		||||
      }
 | 
			
		||||
      this.sample.material_id = null;
 | 
			
		||||
    }
 | 
			
		||||
@@ -376,9 +378,9 @@ export class SampleComponent implements OnInit, AfterContentChecked {
 | 
			
		||||
  // add a new measurement for generated sample at index
 | 
			
		||||
  addMeasurement(gIndex) {
 | 
			
		||||
    this.generatedSamples[gIndex].measurements.push(
 | 
			
		||||
      new MeasurementModel(this.d.arr.measurementTemplates.filter(e => e.name === 'spectrum').reverse()[0]._id)
 | 
			
		||||
      new MeasurementModel(this.d.latest.measurementTemplates.find(e => e.name === 'spectrum')._id)
 | 
			
		||||
    );
 | 
			
		||||
    this.generatedSamples[gIndex].measurements[this.generatedSamples[gIndex].measurements.length - 1].values.device = this.defaultDevice;
 | 
			
		||||
    console.log(this.d.latest.measurementTemplates.find(e => e.name === 'spectrum'));
 | 
			
		||||
    if (!this.charts[gIndex]) {  // add array if there are no charts yet
 | 
			
		||||
      this.charts[gIndex] = [];
 | 
			
		||||
    }
 | 
			
		||||
@@ -411,6 +413,8 @@ export class SampleComponent implements OnInit, AfterContentChecked {
 | 
			
		||||
            this.addMeasurement(gIndex);
 | 
			
		||||
            index = this.generatedSamples[gIndex].measurements.length - 1;
 | 
			
		||||
          }
 | 
			
		||||
          this.generatedSamples[gIndex].measurements[index].values.device =
 | 
			
		||||
            this.generatedSamples[gIndex].measurements[mIndex].values.device;
 | 
			
		||||
          this.generatedSamples[gIndex].measurements[index].values.filename = files[i].name;
 | 
			
		||||
          this.generatedSamples[gIndex].measurements[index].values[parameter] =
 | 
			
		||||
            fileReader.result.toString().split('\r\n').map(e => e.split(','));
 | 
			
		||||
@@ -430,12 +434,15 @@ export class SampleComponent implements OnInit, AfterContentChecked {
 | 
			
		||||
      sample.condition.condition_template = null;
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
      sample.condition.condition_template = this.d.arr.conditionTemplates[0]._id;
 | 
			
		||||
      sample.condition.condition_template = this.d.latest.conditionTemplates[0]._id;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  checkTypo(list, mKey, modal: TemplateRef<any>) {
 | 
			
		||||
    if (this.d.arr[list].indexOf(this.material[list]) < 0) {  // entry is not in list
 | 
			
		||||
  checkTypo(event, list, mKey, modal: TemplateRef<any>) {
 | 
			
		||||
    // user did not click on suggestion and entry is not in list
 | 
			
		||||
    if (!(event.relatedTarget && (event.relatedTarget.className.indexOf('rb-dropdown-item') >= 0 ||
 | 
			
		||||
        event.relatedTarget.className.indexOf('close-btn rb-btn rb-passive-link') >= 0)) &&
 | 
			
		||||
      this.d.arr[list].indexOf(this.material[mKey]) < 0) {
 | 
			
		||||
      this.modalText.list = mKey;
 | 
			
		||||
      this.modalText.suggestion = this.d.arr[list]  // find possible entry from list
 | 
			
		||||
        .map(e => ({v: e, s: strCompare.sorensenDice(e, this.material[mKey])}))
 | 
			
		||||
 
 | 
			
		||||
@@ -15,19 +15,20 @@ export class DataService {
 | 
			
		||||
  ) { }
 | 
			
		||||
 | 
			
		||||
  private collectionMap = {
 | 
			
		||||
    materials: {path: '/materials?status=all', model: MaterialModel, array: true},
 | 
			
		||||
    materialSuppliers: {path: '/material/suppliers', model: null, array: true},
 | 
			
		||||
    materialGroups: {path: '/material/groups', model: null, array: true},
 | 
			
		||||
    materialTemplates: {path: '/template/materials', model: TemplateModel, array: true},
 | 
			
		||||
    measurementTemplates: {path: '/template/measurements', model: TemplateModel, array: true},
 | 
			
		||||
    conditionTemplates: {path: '/template/conditions', model: TemplateModel, array: true},
 | 
			
		||||
    sampleNotesFields: {path: '/sample/notes/fields', model: TemplateModel, array: true},
 | 
			
		||||
    users: {path: '/users', model: UserModel, array: true},
 | 
			
		||||
    user: {path: '/user', model: UserModel, array: false},
 | 
			
		||||
    userKey: {path: '/user/key', model: BaseModel, array: false}
 | 
			
		||||
    materials: {path: '/materials?status=all', model: MaterialModel, type: 'array'},
 | 
			
		||||
    materialSuppliers: {path: '/material/suppliers', model: null, type: 'array'},
 | 
			
		||||
    materialGroups: {path: '/material/groups', model: null, type: 'array'},
 | 
			
		||||
    materialTemplates: {path: '/template/materials', model: TemplateModel, type: 'template'},
 | 
			
		||||
    measurementTemplates: {path: '/template/measurements', model: TemplateModel, type: 'template'},
 | 
			
		||||
    conditionTemplates: {path: '/template/conditions', model: TemplateModel, type: 'template'},
 | 
			
		||||
    sampleNotesFields: {path: '/sample/notes/fields', model: TemplateModel, type: 'array'},
 | 
			
		||||
    users: {path: '/users', model: UserModel, type: 'array'},
 | 
			
		||||
    user: {path: '/user', model: UserModel, type: 'string'},
 | 
			
		||||
    userKey: {path: '/user/key', model: BaseModel, type: 'string'}
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  arr: {[key: string]: any[]} = {};  // array of data
 | 
			
		||||
  latest: {[key: string]: any[]} = {};  // array of latest template versions
 | 
			
		||||
  id: {[key: string]: {[id: string]: any}} = {};  // data in format _id: data
 | 
			
		||||
  d: {[key: string]: any} = {};      // data not in array format
 | 
			
		||||
 | 
			
		||||
@@ -37,10 +38,24 @@ export class DataService {
 | 
			
		||||
    }
 | 
			
		||||
    else {  // load data
 | 
			
		||||
      this.api.get<any>(this.collectionMap[collection].path, data => {
 | 
			
		||||
        if (this.collectionMap[collection].array) {  // array data
 | 
			
		||||
        if (this.collectionMap[collection].type !== 'string') {  // array data
 | 
			
		||||
          this.arr[collection] = data
 | 
			
		||||
            .map(e => this.collectionMap[collection].model ? new this.collectionMap[collection].model().deserialize(e) : e);
 | 
			
		||||
          this.idReload(collection);
 | 
			
		||||
          if (this.collectionMap[collection].type === 'template') {
 | 
			
		||||
            const tmpTemplates = {};
 | 
			
		||||
            this.arr[collection].forEach(template => {
 | 
			
		||||
              if (tmpTemplates[template.first_id]) {  // already found another version
 | 
			
		||||
                if (template.version > tmpTemplates[template.first_id].version) {
 | 
			
		||||
                  tmpTemplates[template.first_id] = template;
 | 
			
		||||
                }
 | 
			
		||||
              }
 | 
			
		||||
              else {
 | 
			
		||||
                tmpTemplates[template.first_id] = template;
 | 
			
		||||
              }
 | 
			
		||||
            });
 | 
			
		||||
            this.latest[collection] = Object.values(tmpTemplates);
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        else {  // not array data
 | 
			
		||||
          this.d[collection] = new this.collectionMap[collection].model().deserialize(data);
 | 
			
		||||
 
 | 
			
		||||
@@ -11,6 +11,7 @@ export class LoginService implements CanActivate {
 | 
			
		||||
 | 
			
		||||
  private pathPermissions = [
 | 
			
		||||
    {path: 'templates', permission: 'dev'},
 | 
			
		||||
    {path: 'changelog', permission: 'dev'},
 | 
			
		||||
    {path: 'users', permission: 'admin'}
 | 
			
		||||
  ];
 | 
			
		||||
  readonly levels = [
 | 
			
		||||
 
 | 
			
		||||
@@ -122,6 +122,7 @@ export class ValidationService {
 | 
			
		||||
    const {ignore, error} = Joi.string()
 | 
			
		||||
      .max(128)
 | 
			
		||||
      .invalid('condition_template', 'material_template')
 | 
			
		||||
      .allow('')
 | 
			
		||||
      .pattern(/^[^.]+$/)
 | 
			
		||||
      .required()
 | 
			
		||||
      .messages({'string.pattern.base': 'name must not contain a dot'})
 | 
			
		||||
 
 | 
			
		||||
@@ -55,7 +55,8 @@
 | 
			
		||||
            <rb-icon-button icon="edit" mode="secondary" (click)="group.edit = !group.edit">
 | 
			
		||||
              Edit template
 | 
			
		||||
            </rb-icon-button>
 | 
			
		||||
            <rb-icon-button icon="save" mode="primary" (click)="saveTemplate(group.first_id)" *ngIf="group.edit">
 | 
			
		||||
            <rb-icon-button icon="save" mode="primary" (click)="saveTemplate(group.first_id)" *ngIf="group.edit"
 | 
			
		||||
                            [disabled]="templateForm.invalid">
 | 
			
		||||
              Save template
 | 
			
		||||
            </rb-icon-button>
 | 
			
		||||
          </form>
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,7 @@ import {animate, style, transition, trigger} from '@angular/animations';
 | 
			
		||||
import {ValidationService} from '../services/validation.service';
 | 
			
		||||
import cloneDeep from 'lodash/cloneDeep';
 | 
			
		||||
import omit from 'lodash/omit';
 | 
			
		||||
import {DataService} from '../services/data.service';
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'app-templates',
 | 
			
		||||
@@ -36,7 +37,8 @@ export class TemplatesComponent implements OnInit {
 | 
			
		||||
 | 
			
		||||
  constructor(
 | 
			
		||||
    private api: ApiService,
 | 
			
		||||
    private validate: ValidationService
 | 
			
		||||
    private validate: ValidationService,
 | 
			
		||||
    public d: DataService
 | 
			
		||||
  ) { }
 | 
			
		||||
 | 
			
		||||
  ngOnInit(): void {
 | 
			
		||||
@@ -44,8 +46,8 @@ export class TemplatesComponent implements OnInit {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  loadTemplates() {
 | 
			
		||||
    this.api.get<TemplateModel[]>(`/template/${this.collection}s`, data => {
 | 
			
		||||
      this.templates = data;
 | 
			
		||||
    this.d.load(this.collection + 'Templates', () => {
 | 
			
		||||
      this.templates = this.d.arr[this.collection + 'Templates'];
 | 
			
		||||
      this.templateFormat();
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
@@ -99,6 +101,7 @@ export class TemplatesComponent implements OnInit {
 | 
			
		||||
            this.templates.push(data);
 | 
			
		||||
          }
 | 
			
		||||
          this.templateFormat();
 | 
			
		||||
          this.d.idReload(this.collection + 'Templates');
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
      else {
 | 
			
		||||
@@ -107,6 +110,7 @@ export class TemplatesComponent implements OnInit {
 | 
			
		||||
            this.templates.push(data);
 | 
			
		||||
          }
 | 
			
		||||
          this.templateFormat();
 | 
			
		||||
          this.d.idReload(this.collection + 'Templates');
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user