Merge branch 'master' of https://sourcecode.socialcoding.bosch.com/scm/definma/definma-ui into f/dashboard
This commit is contained in:
		@@ -7,10 +7,14 @@
 | 
				
			|||||||
<div *ngIf="login.isLoggedIn">
 | 
					<div *ngIf="login.isLoggedIn">
 | 
				
			||||||
    <rb-form-multi-select name="groupSelect" idField="id" [items]="keys" [(ngModel)]="isActiveKey" label="Groups" class="selection">
 | 
					    <rb-form-multi-select name="groupSelect" idField="id" [items]="keys" [(ngModel)]="isActiveKey" label="Groups" class="selection">
 | 
				
			||||||
        <span *rbFormMultiSelectOption="let key">{{key.id}}</span>
 | 
					        <span *rbFormMultiSelectOption="let key">{{key.id}}</span>
 | 
				
			||||||
 | 
					<<<<<<< HEAD
 | 
				
			||||||
    </rb-form-multi-select> 
 | 
					    </rb-form-multi-select> 
 | 
				
			||||||
    <rb-icon-button icon="forward-right" mode="primary" (click)="updateGroups(isActiveKey)">
 | 
					    <rb-icon-button icon="forward-right" mode="primary" (click)="updateGroups(isActiveKey)">
 | 
				
			||||||
        Apply groups 
 | 
					        Apply groups 
 | 
				
			||||||
    </rb-icon-button>
 | 
					    </rb-icon-button>
 | 
				
			||||||
 | 
					=======
 | 
				
			||||||
 | 
					    </rb-form-multi-select>
 | 
				
			||||||
 | 
					>>>>>>> bdce6912108211cbde87033003ce8143ba7c173e
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <div id="divChart">
 | 
					    <div id="divChart">
 | 
				
			||||||
        <canvas id="myChart">
 | 
					        <canvas id="myChart">
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,7 +7,13 @@ app-login {
 | 
				
			|||||||
  float: right;
 | 
					  float: right;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<<<<<<< HEAD
 | 
				
			||||||
.selection{
 | 
					.selection{
 | 
				
			||||||
  float: left;
 | 
					  float: left;
 | 
				
			||||||
  width: 20%;
 | 
					  width: 20%;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					=======
 | 
				
			||||||
 | 
					rb-form-multi-select {
 | 
				
			||||||
 | 
					  width: 20%;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					>>>>>>> bdce6912108211cbde87033003ce8143ba7c173e
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,8 +4,8 @@
 | 
				
			|||||||
  </a>
 | 
					  </a>
 | 
				
			||||||
  <rb-icon-button *ngIf="sampleSelect === 2" mode="secondary" icon="close" (click)="sampleSelect = 0"
 | 
					  <rb-icon-button *ngIf="sampleSelect === 2" mode="secondary" icon="close" (click)="sampleSelect = 0"
 | 
				
			||||||
    class="validation-close" iconOnly></rb-icon-button>
 | 
					    class="validation-close" iconOnly></rb-icon-button>
 | 
				
			||||||
  <rb-icon-button *ngIf="login.isLevel.dev" [icon]="sampleSelect === 2 ? 'checkmark' : 'clear-all'"
 | 
					  <rb-icon-button *ngIf="login.isLevel.dev" [icon]="sampleSelect === 2 ? 'checkmark' : 'clear-all'" mode="secondary"
 | 
				
			||||||
                  mode="secondary" (click)="validate()">
 | 
					    (click)="validate()">
 | 
				
			||||||
    {{sampleSelect === 2 ? 'Validate' : 'Validation'}}
 | 
					    {{sampleSelect === 2 ? 'Validate' : 'Validation'}}
 | 
				
			||||||
  </rb-icon-button>
 | 
					  </rb-icon-button>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
@@ -19,8 +19,7 @@
 | 
				
			|||||||
      <div class="status-selection">
 | 
					      <div class="status-selection">
 | 
				
			||||||
        <label class="label">Status</label>
 | 
					        <label class="label">Status</label>
 | 
				
			||||||
        <rb-form-checkbox name="status-validated" [(ngModel)]="filters.status.validated"
 | 
					        <rb-form-checkbox name="status-validated" [(ngModel)]="filters.status.validated"
 | 
				
			||||||
                          [disabled]="!filters.status.new && !filters.status.deleted"
 | 
					          [disabled]="!filters.status.new && !filters.status.deleted" (ngModelChange)="loadSamples({firstPage: true})">
 | 
				
			||||||
                          (ngModelChange)="loadSamples({firstPage: true})">
 | 
					 | 
				
			||||||
          validated
 | 
					          validated
 | 
				
			||||||
        </rb-form-checkbox>
 | 
					        </rb-form-checkbox>
 | 
				
			||||||
        <rb-form-checkbox name="status-new" [(ngModel)]="filters.status.new"
 | 
					        <rb-form-checkbox name="status-new" [(ngModel)]="filters.status.new"
 | 
				
			||||||
@@ -29,8 +28,8 @@
 | 
				
			|||||||
          new
 | 
					          new
 | 
				
			||||||
        </rb-form-checkbox>
 | 
					        </rb-form-checkbox>
 | 
				
			||||||
        <rb-form-checkbox name="status-deleted" [(ngModel)]="filters.status.deleted"
 | 
					        <rb-form-checkbox name="status-deleted" [(ngModel)]="filters.status.deleted"
 | 
				
			||||||
                          [disabled]="!filters.status.validated && !filters.status.new"
 | 
					          [disabled]="!filters.status.validated && !filters.status.new" (ngModelChange)="loadSamples({firstPage: true})"
 | 
				
			||||||
                          (ngModelChange)="loadSamples({firstPage: true})" *ngIf="login.isLevel.dev">
 | 
					          *ngIf="login.isLevel.dev">
 | 
				
			||||||
          deleted
 | 
					          deleted
 | 
				
			||||||
        </rb-form-checkbox>
 | 
					        </rb-form-checkbox>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
@@ -45,10 +44,13 @@
 | 
				
			|||||||
        <option value="500">500</option>
 | 
					        <option value="500">500</option>
 | 
				
			||||||
      </rb-form-select>
 | 
					      </rb-form-select>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      <rb-form-multi-select name="fieldSelect" idField="id" [items]="keys" [(ngModel)]="isActiveKey" label="Fields"
 | 
					      <div id="multi">
 | 
				
			||||||
                            class="selection" (ngModelChange)="loadSamples({}, $event)">
 | 
					        <rb-form-multi-select *ngFor="let item of categories | keyvalue: originalOrder" name="fieldSelect" idField="id"
 | 
				
			||||||
 | 
					          [items]="item.value" [(ngModel)]="isActiveKey" [label]="item.key" class="selection"
 | 
				
			||||||
 | 
					          (ngModelChange)="loadSamples({}, $event, item.key)">
 | 
				
			||||||
          <span *rbFormMultiSelectOption="let item" class="load-first-page">{{item.label}}</span>
 | 
					          <span *rbFormMultiSelectOption="let item" class="load-first-page">{{item.label}}</span>
 | 
				
			||||||
        </rb-form-multi-select>
 | 
					        </rb-form-multi-select>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      <rb-icon-button icon="reset" mode="secondary" (click)="resetPreferences()" class="reset-preferences">
 | 
					      <rb-icon-button icon="reset" mode="secondary" (click)="resetPreferences()" class="reset-preferences">
 | 
				
			||||||
        Reset to default
 | 
					        Reset to default
 | 
				
			||||||
@@ -75,27 +77,23 @@
 | 
				
			|||||||
              <rb-array-input [(ngModel)]="filter.values" [name]="'filter-' + filter.field"
 | 
					              <rb-array-input [(ngModel)]="filter.values" [name]="'filter-' + filter.field"
 | 
				
			||||||
                [pushTemplate]="!(filter.mode === 'in' || filter.mode === 'nin') ? null :''"
 | 
					                [pushTemplate]="!(filter.mode === 'in' || filter.mode === 'nin') ? null :''"
 | 
				
			||||||
                (ngModelChange)="updateFilterFields(filter.field)">
 | 
					                (ngModelChange)="updateFilterFields(filter.field)">
 | 
				
			||||||
                <ng-container *rbArrayInputItem="let item"
 | 
					                <ng-container *rbArrayInputItem="let item" [ngSwitch]="(filter.autocomplete.length ? 'autocomplete' : '') +
 | 
				
			||||||
                              [ngSwitch]="(filter.autocomplete.length ? 'autocomplete' : '') +
 | 
					 | 
				
			||||||
                              (filter.field == 'added' ? 'date' : (filter.field == 'type' ? 'type' : ''))">
 | 
					                              (filter.field == 'added' ? 'date' : (filter.field == 'type' ? 'type' : ''))">
 | 
				
			||||||
                  <rb-form-date-input *ngSwitchCase="'date'" [rbArrayInputListener]="'filter-' + filter.field"
 | 
					                  <rb-form-date-input *ngSwitchCase="'date'" [rbArrayInputListener]="'filter-' + filter.field"
 | 
				
			||||||
                                      [name]="'filter-' + filter.field + item.i" [index]="item.i"
 | 
					                    [name]="'filter-' + filter.field + item.i" [index]="item.i" [label]="filter.label"
 | 
				
			||||||
                                      [label]="filter.label" [(ngModel)]="item.value"
 | 
					                    [(ngModel)]="item.value" [disabled]="filter.mode === 'null'"></rb-form-date-input>
 | 
				
			||||||
                                      [disabled]="filter.mode === 'null'"></rb-form-date-input>
 | 
					 | 
				
			||||||
                  <rb-form-input *ngSwitchCase="''" [rbArrayInputListener]="'filter-' + filter.field"
 | 
					                  <rb-form-input *ngSwitchCase="''" [rbArrayInputListener]="'filter-' + filter.field"
 | 
				
			||||||
                                 [name]="'filter-' + filter.field + item.i" [index]="item.i"
 | 
					                    [name]="'filter-' + filter.field + item.i" [index]="item.i" [label]="filter.label"
 | 
				
			||||||
                                 [label]="filter.label" [(ngModel)]="item.value" [disabled]="filter.mode === 'null'">
 | 
					                    [(ngModel)]="item.value" [disabled]="filter.mode === 'null'">
 | 
				
			||||||
                  </rb-form-input>
 | 
					                  </rb-form-input>
 | 
				
			||||||
                  <rb-form-input *ngSwitchCase="'autocomplete'" [rbArrayInputListener]="'filter-' + filter.field"
 | 
					                  <rb-form-input *ngSwitchCase="'autocomplete'" [rbArrayInputListener]="'filter-' + filter.field"
 | 
				
			||||||
                                 [name]="'filter-' + filter.field + item.i" [index]="item.i"
 | 
					                    [name]="'filter-' + filter.field + item.i" [index]="item.i" [label]="filter.label"
 | 
				
			||||||
                                 [label]="filter.label" [(ngModel)]="item.value"
 | 
					                    [(ngModel)]="item.value" [rbDebounceTime]="0" (keydown)="preventDefault($event, 'Enter')"
 | 
				
			||||||
                                 [rbDebounceTime]="0" (keydown)="preventDefault($event, 'Enter')"
 | 
					 | 
				
			||||||
                    [rbFormInputAutocomplete]="autocomplete.bind(this, filter.autocomplete)"
 | 
					                    [rbFormInputAutocomplete]="autocomplete.bind(this, filter.autocomplete)"
 | 
				
			||||||
                                 [disabled]="filter.mode === 'null'"
 | 
					                    [disabled]="filter.mode === 'null'" ngModel></rb-form-input>
 | 
				
			||||||
                                 ngModel></rb-form-input>
 | 
					 | 
				
			||||||
                  <rb-form-select *ngSwitchCase="'type'" [rbArrayInputListener]="'filter-' + filter.field"
 | 
					                  <rb-form-select *ngSwitchCase="'type'" [rbArrayInputListener]="'filter-' + filter.field"
 | 
				
			||||||
                                  [name]="'filter-' + filter.field + item.i" [index]="item.i"
 | 
					                    [name]="'filter-' + filter.field + item.i" [index]="item.i" [label]="filter.label"
 | 
				
			||||||
                                  [label]="filter.label" [(ngModel)]="item.value">
 | 
					                    [(ngModel)]="item.value">
 | 
				
			||||||
                    <option value="as-delivered/raw">as-delivered/raw</option>
 | 
					                    <option value="as-delivered/raw">as-delivered/raw</option>
 | 
				
			||||||
                    <option value="processed">processed</option>
 | 
					                    <option value="processed">processed</option>
 | 
				
			||||||
                  </rb-form-select>
 | 
					                  </rb-form-select>
 | 
				
			||||||
@@ -119,7 +117,6 @@
 | 
				
			|||||||
  </rb-accordion-body>
 | 
					  </rb-accordion-body>
 | 
				
			||||||
</rb-accordion>
 | 
					</rb-accordion>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
<ng-container *ngTemplateOutlet="paging"></ng-container>
 | 
					<ng-container *ngTemplateOutlet="paging"></ng-container>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div class="samples-loading" *ngIf="loading">
 | 
					<div class="samples-loading" *ngIf="loading">
 | 
				
			||||||
@@ -185,8 +182,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  <tr *ngFor="let sample of samples; index as i" class="clickable" (click)="sampleDetails(sample._id, sampleModal)">
 | 
					  <tr *ngFor="let sample of samples; index as i" class="clickable" (click)="sampleDetails(sample._id, sampleModal)">
 | 
				
			||||||
    <td *ngIf="login.isLevel.write">
 | 
					    <td *ngIf="login.isLevel.write">
 | 
				
			||||||
      <a [routerLink]="'/samples/edit/' + sample._id"
 | 
					      <a [routerLink]="'/samples/edit/' + sample._id" *ngIf="sample.status !== 'deleted' &&
 | 
				
			||||||
         *ngIf="sample.status !== 'deleted' &&
 | 
					 | 
				
			||||||
         (login.isLevel.dev || (login.isLevel.write && sample.user_id === login.userId))">
 | 
					         (login.isLevel.dev || (login.isLevel.write && sample.user_id === login.userId))">
 | 
				
			||||||
        <span class="rb-ic rb-ic-edit clickable"></span>
 | 
					        <span class="rb-ic rb-ic-edit clickable"></span>
 | 
				
			||||||
      </a>
 | 
					      </a>
 | 
				
			||||||
@@ -198,25 +194,9 @@
 | 
				
			|||||||
        [(ngModel)]="sample.selected">
 | 
					        [(ngModel)]="sample.selected">
 | 
				
			||||||
      </rb-form-checkbox>
 | 
					      </rb-form-checkbox>
 | 
				
			||||||
    </td>
 | 
					    </td>
 | 
				
			||||||
    <td *ngIf="isActiveKey['number']">{{sample.number}}</td>
 | 
					    <td *ngFor="let item of activeKeys; index as j">
 | 
				
			||||||
    <td *ngIf="isActiveKey['material.numbers']">{{d.id.materials[sample.material_id].numbers}}</td>
 | 
					      {{data[i].data[j]}}
 | 
				
			||||||
    <td *ngIf="isActiveKey['material.name']">{{d.id.materials[sample.material_id].name}}</td>
 | 
					 | 
				
			||||||
    <td *ngIf="isActiveKey['material.supplier']">{{d.id.materials[sample.material_id].supplier}}</td>
 | 
					 | 
				
			||||||
    <td *ngIf="isActiveKey['material.group']">{{d.id.materials[sample.material_id].group}}</td>
 | 
					 | 
				
			||||||
    <td *ngFor="let key of activeTemplateKeys.material">
 | 
					 | 
				
			||||||
      {{d.id.materials[sample.material_id].properties[key[2]] | exists}}
 | 
					 | 
				
			||||||
    </td>
 | 
					    </td>
 | 
				
			||||||
    <td *ngIf="isActiveKey['type']">{{sample.type}}</td>
 | 
					 | 
				
			||||||
    <td *ngIf="isActiveKey['color']">{{sample.color}}</td>
 | 
					 | 
				
			||||||
    <td *ngIf="isActiveKey['batch']">{{sample.batch}}</td>
 | 
					 | 
				
			||||||
    <td *ngFor="let key of activeTemplateKeys.condition">
 | 
					 | 
				
			||||||
      {{sample.condition ? sample.condition[key[1]] : '' | exists}}
 | 
					 | 
				
			||||||
    </td>
 | 
					 | 
				
			||||||
    <td *ngIf="isActiveKey['notes.comment']">{{sample.notes | exists: 'comment'}}</td>
 | 
					 | 
				
			||||||
    <td *ngIf="isActiveKey['notes']">{{sample.notes | object: ['_id', 'sample_references']}}</td>
 | 
					 | 
				
			||||||
    <td *ngFor="let key of activeTemplateKeys.measurements">{{sample[key[1]] | exists: key[2]}}</td>
 | 
					 | 
				
			||||||
    <td *ngIf="isActiveKey['status']">{{sample.status}}</td>
 | 
					 | 
				
			||||||
    <td *ngIf="isActiveKey['added']">{{sample.added | date:'dd/MM/yy'}}</td>
 | 
					 | 
				
			||||||
  </tr>
 | 
					  </tr>
 | 
				
			||||||
</rb-table>
 | 
					</rb-table>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -245,13 +225,34 @@
 | 
				
			|||||||
  <ng-template #sampleDetailsTemplate>
 | 
					  <ng-template #sampleDetailsTemplate>
 | 
				
			||||||
    <h3>{{sampleDetailsSample.number}}</h3>
 | 
					    <h3>{{sampleDetailsSample.number}}</h3>
 | 
				
			||||||
    <rb-table class="sample-details-table">
 | 
					    <rb-table class="sample-details-table">
 | 
				
			||||||
      <tr><th>Material</th><td>{{sampleDetailsSample.material.name}}</td></tr>
 | 
					      <tr>
 | 
				
			||||||
      <tr><th>Supplier</th><td>{{sampleDetailsSample.material.supplier}}</td></tr>
 | 
					        <th>Material</th>
 | 
				
			||||||
      <tr><th>Group</th><td>{{sampleDetailsSample.material.group}}</td></tr>
 | 
					        <td>{{sampleDetailsSample.material.name}}</td>
 | 
				
			||||||
      <tr><th>Type</th><td>{{sampleDetailsSample.type}}</td></tr>
 | 
					      </tr>
 | 
				
			||||||
      <tr><th>color</th><td>{{sampleDetailsSample.color}}</td></tr>
 | 
					      <tr>
 | 
				
			||||||
      <tr><th>Batch</th><td>{{sampleDetailsSample.batch}}</td></tr>
 | 
					        <th>Supplier</th>
 | 
				
			||||||
      <tr><th>Comment</th><td>{{sampleDetailsSample.notes.comment | exists}}</td></tr>
 | 
					        <td>{{sampleDetailsSample.material.supplier}}</td>
 | 
				
			||||||
 | 
					      </tr>
 | 
				
			||||||
 | 
					      <tr>
 | 
				
			||||||
 | 
					        <th>Group</th>
 | 
				
			||||||
 | 
					        <td>{{sampleDetailsSample.material.group}}</td>
 | 
				
			||||||
 | 
					      </tr>
 | 
				
			||||||
 | 
					      <tr>
 | 
				
			||||||
 | 
					        <th>Type</th>
 | 
				
			||||||
 | 
					        <td>{{sampleDetailsSample.type}}</td>
 | 
				
			||||||
 | 
					      </tr>
 | 
				
			||||||
 | 
					      <tr>
 | 
				
			||||||
 | 
					        <th>color</th>
 | 
				
			||||||
 | 
					        <td>{{sampleDetailsSample.color}}</td>
 | 
				
			||||||
 | 
					      </tr>
 | 
				
			||||||
 | 
					      <tr>
 | 
				
			||||||
 | 
					        <th>Batch</th>
 | 
				
			||||||
 | 
					        <td>{{sampleDetailsSample.batch}}</td>
 | 
				
			||||||
 | 
					      </tr>
 | 
				
			||||||
 | 
					      <tr>
 | 
				
			||||||
 | 
					        <th>Comment</th>
 | 
				
			||||||
 | 
					        <td>{{sampleDetailsSample.notes.comment | exists}}</td>
 | 
				
			||||||
 | 
					      </tr>
 | 
				
			||||||
      <tr *ngFor="let customField of sampleDetailsSample.notes.custom_fields_entries">
 | 
					      <tr *ngFor="let customField of sampleDetailsSample.notes.custom_fields_entries">
 | 
				
			||||||
        <th>{{customField[0]}}</th>
 | 
					        <th>{{customField[0]}}</th>
 | 
				
			||||||
        <td>{{customField[1]}}</td>
 | 
					        <td>{{customField[1]}}</td>
 | 
				
			||||||
@@ -272,8 +273,14 @@
 | 
				
			|||||||
        <th>{{measurement.name}}</th>
 | 
					        <th>{{measurement.name}}</th>
 | 
				
			||||||
        <td>{{measurement.value}}</td>
 | 
					        <td>{{measurement.value}}</td>
 | 
				
			||||||
      </tr>
 | 
					      </tr>
 | 
				
			||||||
      <tr><th>User</th><td>{{sampleDetailsSample.user}}</td></tr>
 | 
					      <tr>
 | 
				
			||||||
      <tr><th>Status</th><td>{{sampleDetailsSample.status}}</td></tr>
 | 
					        <th>User</th>
 | 
				
			||||||
 | 
					        <td>{{sampleDetailsSample.user}}</td>
 | 
				
			||||||
 | 
					      </tr>
 | 
				
			||||||
 | 
					      <tr>
 | 
				
			||||||
 | 
					        <th>Status</th>
 | 
				
			||||||
 | 
					        <td>{{sampleDetailsSample.status}}</td>
 | 
				
			||||||
 | 
					      </tr>
 | 
				
			||||||
    </rb-table>
 | 
					    </rb-table>
 | 
				
			||||||
  </ng-template>
 | 
					  </ng-template>
 | 
				
			||||||
</ng-template>
 | 
					</ng-template>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,6 +28,10 @@ rb-table {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					rb-form-multi-select{
 | 
				
			||||||
 | 
					  min-width: 9rem;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.status-selection {
 | 
					.status-selection {
 | 
				
			||||||
  overflow: hidden;
 | 
					  overflow: hidden;
 | 
				
			||||||
  margin-bottom: 10px;
 | 
					  margin-bottom: 10px;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,6 +10,7 @@ import { ModalService } from '@inst-iot/bosch-angular-ui-components';
 | 
				
			|||||||
import { DataService } from '../services/data.service';
 | 
					import { DataService } from '../services/data.service';
 | 
				
			||||||
import { LocalStorageService } from 'angular-2-local-storage';
 | 
					import { LocalStorageService } from 'angular-2-local-storage';
 | 
				
			||||||
import { Router } from '@angular/router';
 | 
					import { Router } from '@angular/router';
 | 
				
			||||||
 | 
					import { KeyValue } from '@angular/common';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface LoadSamplesOptions {
 | 
					interface LoadSamplesOptions {
 | 
				
			||||||
  toPage?: number;
 | 
					  toPage?: number;
 | 
				
			||||||
@@ -24,6 +25,11 @@ interface KeyInterface {
 | 
				
			|||||||
  sortable: boolean;
 | 
					  sortable: boolean;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface Data {
 | 
				
			||||||
 | 
					  id: string;
 | 
				
			||||||
 | 
					  data: any[];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Component({
 | 
					@Component({
 | 
				
			||||||
  selector: 'app-samples',
 | 
					  selector: 'app-samples',
 | 
				
			||||||
  templateUrl: './samples.component.html',
 | 
					  templateUrl: './samples.component.html',
 | 
				
			||||||
@@ -39,6 +45,7 @@ export class SamplesComponent implements OnInit {
 | 
				
			|||||||
  downloadCondition = false;
 | 
					  downloadCondition = false;
 | 
				
			||||||
  downloadFlatten = true;
 | 
					  downloadFlatten = true;
 | 
				
			||||||
  samples: SampleModel[] = [];  // all samples to display
 | 
					  samples: SampleModel[] = [];  // all samples to display
 | 
				
			||||||
 | 
					  data: Data[] = [];
 | 
				
			||||||
  totalSamples = 0;  // total number of samples
 | 
					  totalSamples = 0;  // total number of samples
 | 
				
			||||||
  csvUrl = '';  // store url separate so it only has to be generated when clicking the download button
 | 
					  csvUrl = '';  // store url separate so it only has to be generated when clicking the download button
 | 
				
			||||||
  filters = {
 | 
					  filters = {
 | 
				
			||||||
@@ -65,27 +72,44 @@ export class SamplesComponent implements OnInit {
 | 
				
			|||||||
  page = 1;   // current page
 | 
					  page = 1;   // current page
 | 
				
			||||||
  pages = 1;  // total number of pages
 | 
					  pages = 1;  // total number of pages
 | 
				
			||||||
  loadSamplesQueue = [];  // arguments of queued up loadSamples() calls
 | 
					  loadSamplesQueue = [];  // arguments of queued up loadSamples() calls
 | 
				
			||||||
  keys: KeyInterface[] = [
 | 
					  materialKeys: KeyInterface[] = [
 | 
				
			||||||
    { id: 'number', label: 'Number', active: true, sortable: true },
 | 
					    { id: 'number', label: 'Number', active: true, sortable: true },
 | 
				
			||||||
    { id: 'material.numbers', label: 'Material numbers', active: false, sortable: false },
 | 
					    { id: 'material.numbers', label: 'Material numbers', active: false, sortable: false },
 | 
				
			||||||
    { id: 'material.name', label: 'Product name', active: true, sortable: true },
 | 
					 | 
				
			||||||
    { id: 'material.supplier', label: 'Supplier', active: false, sortable: true },
 | 
					    { id: 'material.supplier', label: 'Supplier', active: false, sortable: true },
 | 
				
			||||||
    { id: 'material.group', label: 'Material', active: true, sortable: true },
 | 
					    { id: 'material.group', label: 'Material', active: true, sortable: true },
 | 
				
			||||||
    { id: 'type', label: 'Type', active: true, sortable: true },
 | 
					    { id: 'type', label: 'Type', active: true, sortable: true },
 | 
				
			||||||
    { id: 'color', label: 'Color', active: false, sortable: true },
 | 
					    { id: 'color', label: 'Color', active: false, sortable: true },
 | 
				
			||||||
    { id: 'batch', label: 'Batch', active: true, sortable: true },
 | 
					    { id: 'batch', label: 'Batch', active: true, sortable: true },
 | 
				
			||||||
    { id: 'notes.comment', label: 'Comment', active: false, sortable: false },
 | 
					    { id: 'notes.comment', label: 'Comment', active: false, sortable: false }
 | 
				
			||||||
 | 
					  ];
 | 
				
			||||||
 | 
					  conditionKeys: KeyInterface[] = [
 | 
				
			||||||
    { id: 'notes', label: 'Notes', active: false, sortable: false },
 | 
					    { id: 'notes', label: 'Notes', active: false, sortable: false },
 | 
				
			||||||
 | 
					  ];
 | 
				
			||||||
 | 
					  measurementKeys: KeyInterface[] = [
 | 
				
			||||||
 | 
					    { id: 'material.name', label: 'Product name', active: true, sortable: true },
 | 
				
			||||||
    { id: 'status', label: 'Status', active: false, sortable: true },
 | 
					    { id: 'status', label: 'Status', active: false, sortable: true },
 | 
				
			||||||
    { id: 'added', label: 'Added', active: true, sortable: true }
 | 
					    { id: 'added', label: 'Added', active: true, sortable: true }
 | 
				
			||||||
  ];
 | 
					  ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // combines the 3 different categories
 | 
				
			||||||
 | 
					  categories = {
 | 
				
			||||||
 | 
					    material: this.materialKeys,
 | 
				
			||||||
 | 
					    condition: this.conditionKeys,
 | 
				
			||||||
 | 
					    measurement: this.measurementKeys
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  isActiveKey: { [key: string]: boolean } = {};  // object to check if key is currently active
 | 
					  isActiveKey: { [key: string]: boolean } = {};  // object to check if key is currently active
 | 
				
			||||||
  activeKeys: KeyInterface[] = [];  // list of active keys
 | 
					  activeKeys: KeyInterface[] = [];  // list of active keys
 | 
				
			||||||
  activeTemplateKeys = { material: [], condition: [], measurements: [] };
 | 
					 | 
				
			||||||
  sampleDetailsSample: any = null;  // sample for the sample details dialog
 | 
					  sampleDetailsSample: any = null;  // sample for the sample details dialog
 | 
				
			||||||
  sampleSelect = 0;  // modes: 0 - no selection, 1 - sample edit selection, 2 - validation selection
 | 
					  sampleSelect = 0;  // modes: 0 - no selection, 1 - sample edit selection, 2 - validation selection
 | 
				
			||||||
  loading = 0;  // number of loading instances
 | 
					  loading = 0;  // number of loading instances
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // change the way values are displayed
 | 
				
			||||||
 | 
					  valueConverters = {
 | 
				
			||||||
 | 
					    'added': (v: string, _sample) => new Date(v).toLocaleDateString(),
 | 
				
			||||||
 | 
					    'notes': (v: any, _sample: any) => v.sample_references.length > 0 ? Object.keys(v.sample_references).map(r => v.sample_references[r].relation).join(", ") : "",
 | 
				
			||||||
 | 
					    'notes.comment': (v: any, sample: any) => sample['notes']['comment']
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  constructor(
 | 
					  constructor(
 | 
				
			||||||
    private api: ApiService,
 | 
					    private api: ApiService,
 | 
				
			||||||
@@ -96,8 +120,7 @@ export class SamplesComponent implements OnInit {
 | 
				
			|||||||
    private storage: LocalStorageService,
 | 
					    private storage: LocalStorageService,
 | 
				
			||||||
    private window: Window,
 | 
					    private window: Window,
 | 
				
			||||||
    private router: Router
 | 
					    private router: Router
 | 
				
			||||||
  ) {
 | 
					  ) {}
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ngOnInit(): void {
 | 
					  ngOnInit(): void {
 | 
				
			||||||
    this.loading = 8;
 | 
					    this.loading = 8;
 | 
				
			||||||
@@ -123,7 +146,7 @@ export class SamplesComponent implements OnInit {
 | 
				
			|||||||
    this.d.load('userKey', onLoad);
 | 
					    this.d.load('userKey', onLoad);
 | 
				
			||||||
    this.d.load('conditionTemplates', onLoad);
 | 
					    this.d.load('conditionTemplates', onLoad);
 | 
				
			||||||
    this.loadTemplateKeys('material', 'type', onLoad);
 | 
					    this.loadTemplateKeys('material', 'type', onLoad);
 | 
				
			||||||
    this.loadTemplateKeys('condition', 'notes.comment', onLoad);
 | 
					    this.loadTemplateKeys('condition', 'notes', onLoad);
 | 
				
			||||||
    this.loadTemplateKeys('measurement', 'status', onLoad);
 | 
					    this.loadTemplateKeys('measurement', 'status', onLoad);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -157,18 +180,17 @@ export class SamplesComponent implements OnInit {
 | 
				
			|||||||
          }
 | 
					          }
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
      this.keys.splice(this.keys.findIndex(e => e.id === insertBefore), 0, ...templateKeys);
 | 
					      this.categories[collection].splice(this.categories[collection].findIndex(e => e.id === insertBefore), 0, ...templateKeys);
 | 
				
			||||||
      this.keys = [...this.keys];  // complete overwrite array to invoke update in rb-multiselect
 | 
					      this.categories[collection] = [...this.categories[collection]];  // complete overwrite array to invoke update in rb-multiselect
 | 
				
			||||||
      this.loadPreferences();
 | 
					      this.loadPreferences();
 | 
				
			||||||
      f();
 | 
					      f();
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // set toPage to null to reload first page, queues calls
 | 
					  // set toPage to null to reload first page, queues calls
 | 
				
			||||||
  loadSamples(options: LoadSamplesOptions = {}, event = null) {
 | 
					  loadSamples(options: LoadSamplesOptions = {}, event = null, category?) {
 | 
				
			||||||
    if (event) {  // adjust active keys
 | 
					    if (event) {  // adjust active keys
 | 
				
			||||||
      console.log(event);
 | 
					      this.categories[category].forEach(key => {
 | 
				
			||||||
      this.keys.forEach(key => {
 | 
					 | 
				
			||||||
        if (event.hasOwnProperty(key.id)) {
 | 
					        if (event.hasOwnProperty(key.id)) {
 | 
				
			||||||
          key.active = event[key.id];
 | 
					          key.active = event[key.id];
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -203,6 +225,7 @@ export class SamplesComponent implements OnInit {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        this.pages = Math.ceil(this.totalSamples / this.filters.pageSize);
 | 
					        this.pages = Math.ceil(this.totalSamples / this.filters.pageSize);
 | 
				
			||||||
        this.samples = sData as any;
 | 
					        this.samples = sData as any;
 | 
				
			||||||
 | 
					        this.storeData();
 | 
				
			||||||
        this.loadSamplesQueue.shift();
 | 
					        this.loadSamplesQueue.shift();
 | 
				
			||||||
        if (this.loadSamplesQueue.length > 0) {  // execute next queue item
 | 
					        if (this.loadSamplesQueue.length > 0) {  // execute next queue item
 | 
				
			||||||
          this.sampleLoader(this.loadSamplesQueue[0]);
 | 
					          this.sampleLoader(this.loadSamplesQueue[0]);
 | 
				
			||||||
@@ -247,13 +270,14 @@ export class SamplesComponent implements OnInit {
 | 
				
			|||||||
    if (options.export) {  // append API key on export
 | 
					    if (options.export) {  // append API key on export
 | 
				
			||||||
      query.push('key=' + this.d.d.userKey.key);
 | 
					      query.push('key=' + this.d.d.userKey.key);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    this.keys.forEach(key => {
 | 
					
 | 
				
			||||||
      // do not load material properties for table
 | 
					    for (let category in this.categories) {
 | 
				
			||||||
 | 
					      this.categories[category].forEach(key => {
 | 
				
			||||||
        if (key.active && (options.export || (!options.export && key.id.indexOf('material.') < 0))) {
 | 
					        if (key.active && (options.export || (!options.export && key.id.indexOf('material.') < 0))) {
 | 
				
			||||||
          query.push('fields[]=' + key.id);
 | 
					          query.push('fields[]=' + key.id);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    query.push(...cloneDeep(this.filters.filters)
 | 
					    query.push(...cloneDeep(this.filters.filters)
 | 
				
			||||||
      .map(e => {
 | 
					      .map(e => {
 | 
				
			||||||
        e.values = e.values.filter(el => el !== '');  // do not include empty values
 | 
					        e.values = e.values.filter(el => el !== '');  // do not include empty values
 | 
				
			||||||
@@ -314,14 +338,20 @@ export class SamplesComponent implements OnInit {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  storePreferences() {
 | 
					  storePreferences() {
 | 
				
			||||||
 | 
					    let keys = [];
 | 
				
			||||||
 | 
					    for (let category in this.categories) {
 | 
				
			||||||
 | 
					      keys.push(...this.categories[category].map(e => pick(e, ['id', 'active'])));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const store = {
 | 
					    const store = {
 | 
				
			||||||
      filters: {
 | 
					      filters: {
 | 
				
			||||||
        ...pick(this.filters, ['status', 'pageSize', 'toPage', 'sort']),
 | 
					        ...pick(this.filters, ['status', 'pageSize', 'toPage', 'sort']),
 | 
				
			||||||
        filters: this.filters.filters.map(e => pick(e, ['field', 'active', 'mode', 'values']))
 | 
					        filters: this.filters.filters.map(e => pick(e, ['field', 'active', 'mode', 'values']))
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      keys: this.keys.map(e => pick(e, ['id', 'active']))
 | 
					      keys: keys
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    this.storage.set('samplesPreferences', store);
 | 
					    this.storage.set('samplesPreferences', store);
 | 
				
			||||||
 | 
					    this.calcFieldSelectKeys();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  loadPreferences() {
 | 
					  loadPreferences() {
 | 
				
			||||||
@@ -334,10 +364,13 @@ export class SamplesComponent implements OnInit {
 | 
				
			|||||||
          this.filters.filters[filterIndex] = { ...this.filters.filters[filterIndex], ...filter };
 | 
					          this.filters.filters[filterIndex] = { ...this.filters.filters[filterIndex], ...filter };
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      store.keys.forEach(key => {
 | 
					      store.keys.forEach(key => {
 | 
				
			||||||
        const keyIndex = this.keys.findIndex(e => e.id === key.id);
 | 
					        for (let category in this.categories) {
 | 
				
			||||||
 | 
					          const keyIndex = this.categories[category].findIndex(e => e.id === key.id);
 | 
				
			||||||
          if (keyIndex >= 0) {
 | 
					          if (keyIndex >= 0) {
 | 
				
			||||||
          this.keys[keyIndex].active = key.active;
 | 
					            this.categories[category][keyIndex].active = key.active;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -361,29 +394,24 @@ export class SamplesComponent implements OnInit {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  updateActiveKeys() {  // array with all activeKeys
 | 
					  updateActiveKeys() {  // array with all activeKeys
 | 
				
			||||||
    this.activeKeys = this.keys.filter(e => e.active);
 | 
					    this.activeKeys = [];
 | 
				
			||||||
 | 
					    for (let category in this.categories) {
 | 
				
			||||||
 | 
					      this.activeKeys.push(...this.categories[category].filter(e => e.active));
 | 
				
			||||||
      this.filters.filters.forEach(filter => {  // disable filters of fields not displayed
 | 
					      this.filters.filters.forEach(filter => {  // disable filters of fields not displayed
 | 
				
			||||||
        if (!this.isActiveKey[filter.field]) {
 | 
					        if (!this.isActiveKey[filter.field]) {
 | 
				
			||||||
          filter.active = false;
 | 
					          filter.active = false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
    this.activeTemplateKeys.material = this.keys
 | 
					    }
 | 
				
			||||||
      .filter(e => e.id.indexOf('material.properties.') >= 0 && e.active)
 | 
					 | 
				
			||||||
      .map(e => e.id.split('.')
 | 
					 | 
				
			||||||
        .map(el => decodeURIComponent(el)));
 | 
					 | 
				
			||||||
    this.activeTemplateKeys.condition = this.keys.filter(e => e.id.indexOf('condition.') >= 0 && e.active)
 | 
					 | 
				
			||||||
      .map(e => e.id.split('.')
 | 
					 | 
				
			||||||
        .map(el => decodeURIComponent(el)));
 | 
					 | 
				
			||||||
    this.activeTemplateKeys.measurements = this.keys.filter(e => e.id.indexOf('measurements.') >= 0 && e.active)
 | 
					 | 
				
			||||||
      .map(e => e.id.split('.')
 | 
					 | 
				
			||||||
        .map(el => decodeURIComponent(el)));
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  calcFieldSelectKeys() {
 | 
					  calcFieldSelectKeys() {
 | 
				
			||||||
    this.keys.forEach(key => {
 | 
					    for (let category in this.categories) {
 | 
				
			||||||
 | 
					      this.categories[category].forEach(key => {
 | 
				
			||||||
        this.isActiveKey[key.id] = key.active;
 | 
					        this.isActiveKey[key.id] = key.active;
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  sampleDetails(id: string, modal: TemplateRef<any>) {  // show sample details
 | 
					  sampleDetails(id: string, modal: TemplateRef<any>) {  // show sample details
 | 
				
			||||||
    this.sampleDetailsSample = null;
 | 
					    this.sampleDetailsSample = null;
 | 
				
			||||||
@@ -417,7 +445,7 @@ export class SamplesComponent implements OnInit {
 | 
				
			|||||||
          .push(...Object.entries(measurement.values).filter(e => e[0] !== 'dpt')
 | 
					          .push(...Object.entries(measurement.values).filter(e => e[0] !== 'dpt')
 | 
				
			||||||
            .map(e => ({ name: this.ucFirst(name) + ' ' + e[0], value: e[1] })));
 | 
					            .map(e => ({ name: this.ucFirst(name) + ' ' + e[0], value: e[1] })));
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
      new Promise(resolve => {
 | 
					      new Promise<void>(resolve => {
 | 
				
			||||||
        if (data.notes.sample_references.length) {  // load referenced samples if available
 | 
					        if (data.notes.sample_references.length) {  // load referenced samples if available
 | 
				
			||||||
          let loadingCounter = data.notes.sample_references.length;
 | 
					          let loadingCounter = data.notes.sample_references.length;
 | 
				
			||||||
          this.sampleDetailsSample.notes.sample_references.forEach(reference => {
 | 
					          this.sampleDetailsSample.notes.sample_references.forEach(reference => {
 | 
				
			||||||
@@ -505,4 +533,28 @@ export class SamplesComponent implements OnInit {
 | 
				
			|||||||
  ucFirst(string) {  // convert first character of string to uppercase
 | 
					  ucFirst(string) {  // convert first character of string to uppercase
 | 
				
			||||||
    return string[0].toUpperCase() + string.slice(1);
 | 
					    return string[0].toUpperCase() + string.slice(1);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  refreshMultiSelect() {
 | 
				
			||||||
 | 
					    for (let collection in this.categories) {
 | 
				
			||||||
 | 
					      this.categories[collection] = [...this.categories[collection]];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // stores data in a unified way
 | 
				
			||||||
 | 
					  storeData() {
 | 
				
			||||||
 | 
					    this.data = [];
 | 
				
			||||||
 | 
					    this.samples.forEach(sample => {
 | 
				
			||||||
 | 
					      let value = [];
 | 
				
			||||||
 | 
					      this.activeKeys.forEach(key => {
 | 
				
			||||||
 | 
					        let id = key.id.split('material.')[1];
 | 
				
			||||||
 | 
					        let tmpValue = id ? this.d.id.materials[sample.material_id][id] : sample[key.id];
 | 
				
			||||||
 | 
					        value.push(this.valueConverters[key.id] ? this.valueConverters[key.id](tmpValue, sample) : tmpValue);
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					      this.data.push({ id: sample._id, data: value });
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  originalOrder = (a: KeyValue<number, string>, b: KeyValue<number, string>): number => {
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user