fabrikantencore 2.39.13 → 2.39.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, Inject, Optional, Injectable, ViewEncapsulation, Component, Input, signal, Pipe, ViewChild, EventEmitter, Output, ViewContainerRef, HostListener, ApplicationRef, EnvironmentInjector, createComponent, NgModule } from '@angular/core';
2
+ import { InjectionToken, Inject, Optional, Injectable, signal, ViewEncapsulation, Component, Input, Pipe, ViewChild, EventEmitter, Output, ViewContainerRef, HostListener, NgModule } from '@angular/core';
3
3
  import * as i4 from '@angular/common';
4
4
  import { CommonModule } from '@angular/common';
5
5
  import * as i3 from '@angular/router';
@@ -10,10 +10,8 @@ import * as i6$1 from '@angular/forms';
10
10
  import { Validators, FormsModule, ReactiveFormsModule } from '@angular/forms';
11
11
  import * as i8 from 'ngx-cookie-service';
12
12
  import { CookieService } from 'ngx-cookie-service';
13
- import * as i7$2 from 'ngx-three-engine';
14
- import { ActorComponent, PlayerController, InjectorService, SettingsPanelComponent, SettingsService, VIEWER_GRAPHICS_PRESET_LOCALSTORAGE_KEY, Actor, GraphicsScalabilityConfigsManager, GameModeBase, GameStateBase, OrbitPawn, World, ThreejsEngineComponent } from 'ngx-three-engine';
15
13
  import { mergeMap, catchError } from 'rxjs/operators';
16
- import { throwError, of, Observable, BehaviorSubject, Subject } from 'rxjs';
14
+ import { throwError, of, Observable, BehaviorSubject } from 'rxjs';
17
15
  import * as i7 from '@angular/material/button';
18
16
  import { MatButtonModule } from '@angular/material/button';
19
17
  import * as i5 from '@angular/material/input';
@@ -45,7 +43,7 @@ import * as i16 from '@angular/material/slide-toggle';
45
43
  import { MatSlideToggle } from '@angular/material/slide-toggle';
46
44
  import * as i10$1 from '@angular/material/tabs';
47
45
  import { MatTabsModule } from '@angular/material/tabs';
48
- import * as i9$2 from '@angular/material/sidenav';
46
+ import * as i9$3 from '@angular/material/sidenav';
49
47
  import { MatSidenavModule } from '@angular/material/sidenav';
50
48
  import { MatTreeModule } from '@angular/material/tree';
51
49
  import * as i8$1 from '@angular/material/icon';
@@ -53,7 +51,7 @@ import { MatIconModule } from '@angular/material/icon';
53
51
  import { MatDividerModule } from '@angular/material/divider';
54
52
  import * as i15 from '@angular/material/button-toggle';
55
53
  import { MatButtonToggleModule } from '@angular/material/button-toggle';
56
- import * as i8$2 from '@angular/material/stepper';
54
+ import * as i9$2 from '@angular/material/stepper';
57
55
  import { MatStepperModule } from '@angular/material/stepper';
58
56
  import * as i9$1 from '@angular/cdk/drag-drop';
59
57
  import { moveItemInArray, DragDropModule } from '@angular/cdk/drag-drop';
@@ -62,12 +60,6 @@ import { MatRadioModule } from '@angular/material/radio';
62
60
  import * as i11 from '@angular/material/paginator';
63
61
  import { MatPaginatorModule } from '@angular/material/paginator';
64
62
  import { MatFormFieldModule } from '@angular/material/form-field';
65
- import { Matrix4, Group, Box3, TextureLoader, RepeatWrapping, LinearMipMapLinearFilter, LinearFilter, Mesh, BufferGeometry, BufferAttribute, MeshStandardMaterial, SRGBColorSpace, Vector3, PerspectiveCamera, MathUtils, MeshPhysicalMaterial, DirectionalLight, AmbientLight, Color } from 'three';
66
- import { Inspector } from 'three/addons/inspector/Inspector.js';
67
- import { InspectorBase, PMREMGenerator } from 'three/webgpu';
68
- import Stats from 'three/examples/jsm/libs/stats.module.js';
69
- import { RoomEnvironment } from 'three/examples/jsm/environments/RoomEnvironment.js';
70
- import { HDRLoader } from 'three/examples/jsm/loaders/HDRLoader.js';
71
63
  import * as i6$4 from '@kolkov/angular-editor';
72
64
  import { AngularEditorModule } from '@kolkov/angular-editor';
73
65
 
@@ -10196,6 +10188,7 @@ class FabrikantenFilterViewModel {
10196
10188
  required;
10197
10189
  affectsOnlyBestek;
10198
10190
  selectedOption;
10191
+ defaultOption;
10199
10192
  selectedOptions;
10200
10193
  selectedColour;
10201
10194
  selectedColourValue;
@@ -10226,6 +10219,7 @@ class FabrikantenFilterViewModel {
10226
10219
  this.required = _data["required"];
10227
10220
  this.affectsOnlyBestek = _data["affectsOnlyBestek"];
10228
10221
  this.selectedOption = _data["selectedOption"];
10222
+ this.defaultOption = _data["defaultOption"];
10229
10223
  if (Array.isArray(_data["selectedOptions"])) {
10230
10224
  this.selectedOptions = [];
10231
10225
  for (let item of _data["selectedOptions"])
@@ -10268,6 +10262,7 @@ class FabrikantenFilterViewModel {
10268
10262
  data["required"] = this.required;
10269
10263
  data["affectsOnlyBestek"] = this.affectsOnlyBestek;
10270
10264
  data["selectedOption"] = this.selectedOption;
10265
+ data["defaultOption"] = this.defaultOption;
10271
10266
  if (Array.isArray(this.selectedOptions)) {
10272
10267
  data["selectedOptions"] = [];
10273
10268
  for (let item of this.selectedOptions)
@@ -10880,6 +10875,8 @@ class FabrikantenSettingsViewModel {
10880
10875
  osfNew;
10881
10876
  onlyShowBestekWhenFilled;
10882
10877
  rekenenParameters;
10878
+ filtersSelectDefault;
10879
+ stepperFoldable;
10883
10880
  downloadForm;
10884
10881
  selectProductForm;
10885
10882
  downloadCategories;
@@ -10945,6 +10942,8 @@ class FabrikantenSettingsViewModel {
10945
10942
  this.osfNew = _data["osfNew"];
10946
10943
  this.onlyShowBestekWhenFilled = _data["onlyShowBestekWhenFilled"];
10947
10944
  this.rekenenParameters = _data["rekenenParameters"];
10945
+ this.filtersSelectDefault = _data["filtersSelectDefault"];
10946
+ this.stepperFoldable = _data["stepperFoldable"];
10948
10947
  this.downloadForm = _data["downloadForm"] ? FabrikantenFormViewModel.fromJS(_data["downloadForm"]) : undefined;
10949
10948
  this.selectProductForm = _data["selectProductForm"] ? FabrikantenFormViewModel.fromJS(_data["selectProductForm"]) : undefined;
10950
10949
  if (Array.isArray(_data["downloadCategories"])) {
@@ -11018,6 +11017,8 @@ class FabrikantenSettingsViewModel {
11018
11017
  data["osfNew"] = this.osfNew;
11019
11018
  data["onlyShowBestekWhenFilled"] = this.onlyShowBestekWhenFilled;
11020
11019
  data["rekenenParameters"] = this.rekenenParameters;
11020
+ data["filtersSelectDefault"] = this.filtersSelectDefault;
11021
+ data["stepperFoldable"] = this.stepperFoldable;
11021
11022
  data["downloadForm"] = this.downloadForm ? this.downloadForm.toJSON() : undefined;
11022
11023
  data["selectProductForm"] = this.selectProductForm ? this.selectProductForm.toJSON() : undefined;
11023
11024
  if (Array.isArray(this.downloadCategories)) {
@@ -17843,7 +17844,7 @@ class BeheerNavComponent {
17843
17844
  authenticationService;
17844
17845
  router;
17845
17846
  FabrikantenApiClient;
17846
- ResetCacheTitle = "Reset Cache";
17847
+ ResettingCache = signal(false, ...(ngDevMode ? [{ debugName: "ResettingCache" }] : /* istanbul ignore next */ []));
17847
17848
  FabrikantenSettingsViewModel;
17848
17849
  UploadsResponseModel = null;
17849
17850
  constructor(authenticationService, router, FabrikantenApiClient) {
@@ -17855,6 +17856,14 @@ class BeheerNavComponent {
17855
17856
  this.LoadSettings();
17856
17857
  this.LoadUploads();
17857
17858
  }
17859
+ GetResetCacheTitle() {
17860
+ if (this.ResettingCache()) {
17861
+ return "...";
17862
+ }
17863
+ else {
17864
+ return "Reset Cache";
17865
+ }
17866
+ }
17858
17867
  HangfireEnabled() {
17859
17868
  return this.FabrikantenSettingsViewModel?.hangfireEnabled == true;
17860
17869
  }
@@ -17881,9 +17890,9 @@ class BeheerNavComponent {
17881
17890
  return window.location.href.toLowerCase().indexOf(name.toLowerCase()) != -1;
17882
17891
  }
17883
17892
  ResetCache() {
17884
- this.ResetCacheTitle = "...";
17893
+ this.ResettingCache.set(true);
17885
17894
  this.FabrikantenApiClient.resetCache().subscribe(() => {
17886
- this.ResetCacheTitle = "Reset Cache";
17895
+ this.ResettingCache.set(false);
17887
17896
  alert('cache reset success');
17888
17897
  }, (error) => {
17889
17898
  alert('An unexpected error occured');
@@ -17917,11 +17926,11 @@ class BeheerNavComponent {
17917
17926
  });
17918
17927
  }
17919
17928
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: BeheerNavComponent, deps: [{ token: AuthenticationService }, { token: i3.Router }, { token: FabrikantenApiClient }], target: i0.ɵɵFactoryTarget.Component });
17920
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.13", type: BeheerNavComponent, isStandalone: false, selector: "app-beheer-nav", ngImport: i0, template: "<div class=\"main-block\">\r\n <div class=\"row\">\r\n <div class=\"cell left-block\" *ngIf=\"authenticationService.DeTweeSnoekenRights()\">\r\n <button mat-raised-button (click)=\"NavigateTo('searchproducts')\" class=\"link\" [disabled]=\"IsActive('/searchproducts')\">\r\n Zoeken\r\n </button>\r\n <button mat-raised-button (click)=\"NavigateTo('importsets')\" class=\"link\" [disabled]=\"IsActive('/importsets')\">\r\n Import\r\n </button>\r\n <button mat-raised-button (click)=\"NavigateTo('products')\" class=\"link\" [disabled]=\"IsActive('/products')\">\r\n Products\r\n </button>\r\n <button mat-raised-button (click)=\"NavigateTo('filters')\" class=\"link\" [disabled]=\"IsActive('/filters')\">\r\n Filters\r\n </button>\r\n <button mat-raised-button (click)=\"NavigateTo('ebokoppel')\" class=\"link\" [disabled]=\"IsActive('/ebokoppel')\">\r\n EBO Koppel\r\n </button>\r\n <button mat-raised-button (click)=\"NavigateTo('categories')\" class=\"link\" [disabled]=\"IsActive('/categories')\">\r\n Categories\r\n </button>\r\n <button mat-raised-button (click)=\"NavigateTo('deeplink')\" class=\"link\" [disabled]=\"IsActive('/deeplink')\">\r\n Deeplink\r\n </button>\r\n </div>\r\n <div class=\"cell right-block\">\r\n <button mat-raised-button (click)=\"Home()\" class=\"link\">\r\n Home\r\n </button>\r\n <button *ngIf=\"!authenticationService.ConfiguratorRights()\" mat-raised-button (click)=\"ResetCache()\" class=\"link\">\r\n {{ ResetCacheTitle }}\r\n </button>\r\n <button *ngIf=\"authenticationService.DeTweeSnoekenRights()\" mat-raised-button (click)=\"NavigateTo('settings')\" class=\"link\" [disabled]=\"IsActive('/settings')\">\r\n Settings\r\n </button>\r\n <button *ngIf=\"!authenticationService.ConfiguratorRights() && DocumentsEnabled()\" mat-raised-button (click)=\"NavigateTo('documents')\" class=\"link\" [disabled]=\"IsActive('/documents')\">\r\n Documents\r\n </button>\r\n <button *ngIf=\"!authenticationService.ConfiguratorRights()\" mat-raised-button (click)=\"NavigateTo('translate')\" class=\"link\" [disabled]=\"IsActive('/translate')\">\r\n Translate\r\n </button>\r\n <button *ngIf=\"!authenticationService.ConfiguratorRights() && ShowUploads()\" mat-raised-button (click)=\"NavigateTo('uploads')\" class=\"link\" [disabled]=\"IsActive('/uploads')\">\r\n Files\r\n </button>\r\n <button *ngIf=\"authenticationService.ConfiguratorRights()\" mat-raised-button (click)=\"NavigateTo('configurator')\" class=\"link\" [disabled]=\"IsActive('/configurator')\">\r\n Configurator\r\n </button>\r\n <button *ngIf=\"authenticationService.AdministratorRights()\" mat-raised-button (click)=\"NavigateTo('users')\" class=\"link\" [disabled]=\"IsActive('/users')\">\r\n Users\r\n </button>\r\n <button *ngIf=\"authenticationService.DeTweeSnoekenRights() && HangfireEnabled()\" mat-raised-button (click)=\"NavigateTo('hangfire')\" class=\"link\" [disabled]=\"IsActive('/hangfire')\">\r\n Hangfire\r\n </button>\r\n <button mat-raised-button (click)=\"LogOff()\" class=\"link\">\r\n Uitloggen\r\n </button>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: ["app-beheer-nav .main-block{width:100%;display:table}app-beheer-nav .main-block .left-block{text-align:left}app-beheer-nav .main-block .right-block{text-align:right}app-beheer-nav .main-block .row{display:table-row}app-beheer-nav .main-block .cell{display:table-cell}app-beheer-nav .main-block .link{margin:5px}body{background:url(/assets/bouwconnect-achtergrond.png) fixed}.full-width{width:100%}\n"], dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i7.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }], encapsulation: i0.ViewEncapsulation.None });
17929
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.13", type: BeheerNavComponent, isStandalone: false, selector: "app-beheer-nav", ngImport: i0, template: "<div class=\"main-block\">\r\n <div class=\"row\">\r\n <div class=\"cell left-block\" *ngIf=\"authenticationService.DeTweeSnoekenRights()\">\r\n <button mat-raised-button (click)=\"NavigateTo('searchproducts')\" class=\"link\" [disabled]=\"IsActive('/searchproducts')\">\r\n Zoeken\r\n </button>\r\n <button mat-raised-button (click)=\"NavigateTo('importsets')\" class=\"link\" [disabled]=\"IsActive('/importsets')\">\r\n Import\r\n </button>\r\n <button mat-raised-button (click)=\"NavigateTo('products')\" class=\"link\" [disabled]=\"IsActive('/products')\">\r\n Products\r\n </button>\r\n <button mat-raised-button (click)=\"NavigateTo('filters')\" class=\"link\" [disabled]=\"IsActive('/filters')\">\r\n Filters\r\n </button>\r\n <button mat-raised-button (click)=\"NavigateTo('ebokoppel')\" class=\"link\" [disabled]=\"IsActive('/ebokoppel')\">\r\n EBO Koppel\r\n </button>\r\n <button mat-raised-button (click)=\"NavigateTo('categories')\" class=\"link\" [disabled]=\"IsActive('/categories')\">\r\n Categories\r\n </button>\r\n <button mat-raised-button (click)=\"NavigateTo('deeplink')\" class=\"link\" [disabled]=\"IsActive('/deeplink')\">\r\n Deeplink\r\n </button>\r\n </div>\r\n <div class=\"cell right-block\">\r\n <button mat-raised-button (click)=\"Home()\" class=\"link\">\r\n Home\r\n </button>\r\n <button *ngIf=\"!authenticationService.ConfiguratorRights()\" mat-raised-button (click)=\"ResetCache()\" class=\"link\">\r\n {{ GetResetCacheTitle() }}\r\n </button>\r\n <button *ngIf=\"authenticationService.DeTweeSnoekenRights()\" mat-raised-button (click)=\"NavigateTo('settings')\" class=\"link\" [disabled]=\"IsActive('/settings')\">\r\n Settings\r\n </button>\r\n <button *ngIf=\"!authenticationService.ConfiguratorRights() && DocumentsEnabled()\" mat-raised-button (click)=\"NavigateTo('documents')\" class=\"link\" [disabled]=\"IsActive('/documents')\">\r\n Documents\r\n </button>\r\n <button *ngIf=\"!authenticationService.ConfiguratorRights()\" mat-raised-button (click)=\"NavigateTo('translate')\" class=\"link\" [disabled]=\"IsActive('/translate')\">\r\n Translate\r\n </button>\r\n <button *ngIf=\"!authenticationService.ConfiguratorRights() && ShowUploads()\" mat-raised-button (click)=\"NavigateTo('uploads')\" class=\"link\" [disabled]=\"IsActive('/uploads')\">\r\n Files\r\n </button>\r\n <button *ngIf=\"authenticationService.ConfiguratorRights()\" mat-raised-button (click)=\"NavigateTo('configurator')\" class=\"link\" [disabled]=\"IsActive('/configurator')\">\r\n Configurator\r\n </button>\r\n <button *ngIf=\"authenticationService.AdministratorRights()\" mat-raised-button (click)=\"NavigateTo('users')\" class=\"link\" [disabled]=\"IsActive('/users')\">\r\n Users\r\n </button>\r\n <button *ngIf=\"authenticationService.DeTweeSnoekenRights() && HangfireEnabled()\" mat-raised-button (click)=\"NavigateTo('hangfire')\" class=\"link\" [disabled]=\"IsActive('/hangfire')\">\r\n Hangfire\r\n </button>\r\n <button mat-raised-button (click)=\"LogOff()\" class=\"link\">\r\n Uitloggen\r\n </button>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: ["app-beheer-nav .main-block{width:100%;display:table}app-beheer-nav .main-block .left-block{text-align:left}app-beheer-nav .main-block .right-block{text-align:right}app-beheer-nav .main-block .row{display:table-row}app-beheer-nav .main-block .cell{display:table-cell}app-beheer-nav .main-block .link{margin:5px}body{background:url(/assets/bouwconnect-achtergrond.png) fixed}.full-width{width:100%}\n"], dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i7.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }], encapsulation: i0.ViewEncapsulation.None });
17921
17930
  }
17922
17931
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: BeheerNavComponent, decorators: [{
17923
17932
  type: Component,
17924
- args: [{ selector: 'app-beheer-nav', standalone: false, encapsulation: ViewEncapsulation.None, template: "<div class=\"main-block\">\r\n <div class=\"row\">\r\n <div class=\"cell left-block\" *ngIf=\"authenticationService.DeTweeSnoekenRights()\">\r\n <button mat-raised-button (click)=\"NavigateTo('searchproducts')\" class=\"link\" [disabled]=\"IsActive('/searchproducts')\">\r\n Zoeken\r\n </button>\r\n <button mat-raised-button (click)=\"NavigateTo('importsets')\" class=\"link\" [disabled]=\"IsActive('/importsets')\">\r\n Import\r\n </button>\r\n <button mat-raised-button (click)=\"NavigateTo('products')\" class=\"link\" [disabled]=\"IsActive('/products')\">\r\n Products\r\n </button>\r\n <button mat-raised-button (click)=\"NavigateTo('filters')\" class=\"link\" [disabled]=\"IsActive('/filters')\">\r\n Filters\r\n </button>\r\n <button mat-raised-button (click)=\"NavigateTo('ebokoppel')\" class=\"link\" [disabled]=\"IsActive('/ebokoppel')\">\r\n EBO Koppel\r\n </button>\r\n <button mat-raised-button (click)=\"NavigateTo('categories')\" class=\"link\" [disabled]=\"IsActive('/categories')\">\r\n Categories\r\n </button>\r\n <button mat-raised-button (click)=\"NavigateTo('deeplink')\" class=\"link\" [disabled]=\"IsActive('/deeplink')\">\r\n Deeplink\r\n </button>\r\n </div>\r\n <div class=\"cell right-block\">\r\n <button mat-raised-button (click)=\"Home()\" class=\"link\">\r\n Home\r\n </button>\r\n <button *ngIf=\"!authenticationService.ConfiguratorRights()\" mat-raised-button (click)=\"ResetCache()\" class=\"link\">\r\n {{ ResetCacheTitle }}\r\n </button>\r\n <button *ngIf=\"authenticationService.DeTweeSnoekenRights()\" mat-raised-button (click)=\"NavigateTo('settings')\" class=\"link\" [disabled]=\"IsActive('/settings')\">\r\n Settings\r\n </button>\r\n <button *ngIf=\"!authenticationService.ConfiguratorRights() && DocumentsEnabled()\" mat-raised-button (click)=\"NavigateTo('documents')\" class=\"link\" [disabled]=\"IsActive('/documents')\">\r\n Documents\r\n </button>\r\n <button *ngIf=\"!authenticationService.ConfiguratorRights()\" mat-raised-button (click)=\"NavigateTo('translate')\" class=\"link\" [disabled]=\"IsActive('/translate')\">\r\n Translate\r\n </button>\r\n <button *ngIf=\"!authenticationService.ConfiguratorRights() && ShowUploads()\" mat-raised-button (click)=\"NavigateTo('uploads')\" class=\"link\" [disabled]=\"IsActive('/uploads')\">\r\n Files\r\n </button>\r\n <button *ngIf=\"authenticationService.ConfiguratorRights()\" mat-raised-button (click)=\"NavigateTo('configurator')\" class=\"link\" [disabled]=\"IsActive('/configurator')\">\r\n Configurator\r\n </button>\r\n <button *ngIf=\"authenticationService.AdministratorRights()\" mat-raised-button (click)=\"NavigateTo('users')\" class=\"link\" [disabled]=\"IsActive('/users')\">\r\n Users\r\n </button>\r\n <button *ngIf=\"authenticationService.DeTweeSnoekenRights() && HangfireEnabled()\" mat-raised-button (click)=\"NavigateTo('hangfire')\" class=\"link\" [disabled]=\"IsActive('/hangfire')\">\r\n Hangfire\r\n </button>\r\n <button mat-raised-button (click)=\"LogOff()\" class=\"link\">\r\n Uitloggen\r\n </button>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: ["app-beheer-nav .main-block{width:100%;display:table}app-beheer-nav .main-block .left-block{text-align:left}app-beheer-nav .main-block .right-block{text-align:right}app-beheer-nav .main-block .row{display:table-row}app-beheer-nav .main-block .cell{display:table-cell}app-beheer-nav .main-block .link{margin:5px}body{background:url(/assets/bouwconnect-achtergrond.png) fixed}.full-width{width:100%}\n"] }]
17933
+ args: [{ selector: 'app-beheer-nav', standalone: false, encapsulation: ViewEncapsulation.None, template: "<div class=\"main-block\">\r\n <div class=\"row\">\r\n <div class=\"cell left-block\" *ngIf=\"authenticationService.DeTweeSnoekenRights()\">\r\n <button mat-raised-button (click)=\"NavigateTo('searchproducts')\" class=\"link\" [disabled]=\"IsActive('/searchproducts')\">\r\n Zoeken\r\n </button>\r\n <button mat-raised-button (click)=\"NavigateTo('importsets')\" class=\"link\" [disabled]=\"IsActive('/importsets')\">\r\n Import\r\n </button>\r\n <button mat-raised-button (click)=\"NavigateTo('products')\" class=\"link\" [disabled]=\"IsActive('/products')\">\r\n Products\r\n </button>\r\n <button mat-raised-button (click)=\"NavigateTo('filters')\" class=\"link\" [disabled]=\"IsActive('/filters')\">\r\n Filters\r\n </button>\r\n <button mat-raised-button (click)=\"NavigateTo('ebokoppel')\" class=\"link\" [disabled]=\"IsActive('/ebokoppel')\">\r\n EBO Koppel\r\n </button>\r\n <button mat-raised-button (click)=\"NavigateTo('categories')\" class=\"link\" [disabled]=\"IsActive('/categories')\">\r\n Categories\r\n </button>\r\n <button mat-raised-button (click)=\"NavigateTo('deeplink')\" class=\"link\" [disabled]=\"IsActive('/deeplink')\">\r\n Deeplink\r\n </button>\r\n </div>\r\n <div class=\"cell right-block\">\r\n <button mat-raised-button (click)=\"Home()\" class=\"link\">\r\n Home\r\n </button>\r\n <button *ngIf=\"!authenticationService.ConfiguratorRights()\" mat-raised-button (click)=\"ResetCache()\" class=\"link\">\r\n {{ GetResetCacheTitle() }}\r\n </button>\r\n <button *ngIf=\"authenticationService.DeTweeSnoekenRights()\" mat-raised-button (click)=\"NavigateTo('settings')\" class=\"link\" [disabled]=\"IsActive('/settings')\">\r\n Settings\r\n </button>\r\n <button *ngIf=\"!authenticationService.ConfiguratorRights() && DocumentsEnabled()\" mat-raised-button (click)=\"NavigateTo('documents')\" class=\"link\" [disabled]=\"IsActive('/documents')\">\r\n Documents\r\n </button>\r\n <button *ngIf=\"!authenticationService.ConfiguratorRights()\" mat-raised-button (click)=\"NavigateTo('translate')\" class=\"link\" [disabled]=\"IsActive('/translate')\">\r\n Translate\r\n </button>\r\n <button *ngIf=\"!authenticationService.ConfiguratorRights() && ShowUploads()\" mat-raised-button (click)=\"NavigateTo('uploads')\" class=\"link\" [disabled]=\"IsActive('/uploads')\">\r\n Files\r\n </button>\r\n <button *ngIf=\"authenticationService.ConfiguratorRights()\" mat-raised-button (click)=\"NavigateTo('configurator')\" class=\"link\" [disabled]=\"IsActive('/configurator')\">\r\n Configurator\r\n </button>\r\n <button *ngIf=\"authenticationService.AdministratorRights()\" mat-raised-button (click)=\"NavigateTo('users')\" class=\"link\" [disabled]=\"IsActive('/users')\">\r\n Users\r\n </button>\r\n <button *ngIf=\"authenticationService.DeTweeSnoekenRights() && HangfireEnabled()\" mat-raised-button (click)=\"NavigateTo('hangfire')\" class=\"link\" [disabled]=\"IsActive('/hangfire')\">\r\n Hangfire\r\n </button>\r\n <button mat-raised-button (click)=\"LogOff()\" class=\"link\">\r\n Uitloggen\r\n </button>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: ["app-beheer-nav .main-block{width:100%;display:table}app-beheer-nav .main-block .left-block{text-align:left}app-beheer-nav .main-block .right-block{text-align:right}app-beheer-nav .main-block .row{display:table-row}app-beheer-nav .main-block .cell{display:table-cell}app-beheer-nav .main-block .link{margin:5px}body{background:url(/assets/bouwconnect-achtergrond.png) fixed}.full-width{width:100%}\n"] }]
17925
17934
  }], ctorParameters: () => [{ type: AuthenticationService }, { type: i3.Router }, { type: FabrikantenApiClient }] });
17926
17935
 
17927
17936
  class BeheerMainComponent {
@@ -23803,6 +23812,20 @@ class FabFilterComponent {
23803
23812
  this.SelectedOptionId = options[0].id;
23804
23813
  }
23805
23814
  }
23815
+ if (this.SelectedOptionId == 0 && this._filter.defaultOption != undefined) {
23816
+ var set = false;
23817
+ if (this._filter.options != null) {
23818
+ for (var i = 0; i < this._filter.options.length; i++) {
23819
+ if (this._filter.options[i].id == this._filter.defaultOption) {
23820
+ set = true;
23821
+ break;
23822
+ }
23823
+ }
23824
+ }
23825
+ if (set) {
23826
+ this.SelectedOptionId = this._filter.defaultOption;
23827
+ }
23828
+ }
23806
23829
  }
23807
23830
  filterchanged = new EventEmitter();
23808
23831
  selectoption = new EventEmitter();
@@ -23825,6 +23848,7 @@ class FabFilterComponent {
23825
23848
  filterid: this.filter.id,
23826
23849
  filteroptionid: this.SelectedOptionId
23827
23850
  });
23851
+ //alert(this.SelectedOptionId);
23828
23852
  //this.FabrikantenService.SelectOption(this.filter.id, this.SelectedOptionId, this.ChangeDetectorRef, this.ActivatedRoute);
23829
23853
  }
23830
23854
  ResetSelection() {
@@ -23916,11 +23940,11 @@ class FabFilterComponent {
23916
23940
  return result;
23917
23941
  }
23918
23942
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: FabFilterComponent, deps: [{ token: FabrikantenService }, { token: TranslateService }, { token: i3.ActivatedRoute }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
23919
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.13", type: FabFilterComponent, isStandalone: false, selector: "app-fab-filter", inputs: { filter: "filter" }, outputs: { filterchanged: "filterchanged", selectoption: "selectoption" }, ngImport: i0, template: "<div class=\"row\" *ngIf=\"!filter.hidden\">\r\n <div class=\"select\" (click)=\"Click()\" [ngClass]=\"{'selectoption': filter.selectedOption != 0 }\">\r\n <mat-form-field appearance=\"fill\" class=\"full-width\">\r\n <mat-label class=\"select-mat-label filter-name\">\r\n {{ TranslateService.GetActiveValue(TranslationCategory.Filter, TranslationSubCategory.Name, filter.id) }}\r\n <ng-container *ngIf=\"filter.blocksProductSelect || FabrikantenService.IsAProductSelected()\">\r\n <span *ngIf=\"filter.blocksProductSelect || filter.required\">*&nbsp;</span>\r\n <span *ngIf=\"filter.affectsOnlyBestek\"><sup>1</sup></span>\r\n </ng-container>\r\n </mat-label>\r\n <mat-select [(ngModel)]=\"SelectedOptionId\" (selectionChange)=\"SelectOption()\" [disabled]=\"IsDisabled()\">\r\n <ng-container *ngFor=\"let option of filter.options\">\r\n <mat-option [value]=\"option.id\" class=\"select-mat-option\" *ngIf=\"!option.hidden\">\r\n <ng-container *ngIf=\"option.colour != null && option.colour != ''\">\r\n <span [ngStyle]=\"{'background-color': option.colour}\" class=\"colour-preview\">\r\n &nbsp;\r\n &nbsp;\r\n </span>\r\n </ng-container>\r\n <ng-container *ngIf=\"option.imagePath != null && option.imagePath != ''\">\r\n <div class=\"filter-option-image-div\">\r\n <img src=\"{{ GetImagePath(option) }}\" class=\"filter-option-image\" />\r\n </div>\r\n </ng-container>\r\n <span class=\"name-span\">\r\n {{ TranslateService.GetActiveValue(TranslationCategory.FilterOption, TranslationSubCategory.Name, option.id) }}\r\n </span>\r\n <span *ngIf=\"filter.unit != null\" class=\"name-span unit-span\">\r\n &nbsp;{{ filter.unit }}\r\n </span>\r\n </mat-option>\r\n </ng-container>\r\n </mat-select>\r\n </mat-form-field>\r\n <p *ngIf=\"ShowDescription()\" class=\"description-block\">{{ GetDescription() }}</p>\r\n </div>\r\n <div *ngIf=\"GetSelectedOption() != null && GetSelectedOption().colour != null && GetSelectedOption().colour != ''\">\r\n <div [ngStyle]=\"{'background-color': GetSelectedOption().colour}\" class=\"colour-preview-selected\">\r\n &nbsp;\r\n &nbsp;\r\n </div>\r\n </div>\r\n <div class=\"reset\" *ngIf=\"filter.selectedOption != 0\" (click)=\"ResetSelection()\">\r\n <mat-icon class=\"icon-position clear\" [inline]=\"true\">clear</mat-icon>\r\n </div>\r\n</div>\r\n<div *ngFor=\"let description of filter.descriptions\" class=\"description-block\">\r\n {{ description.description }}\r\n</div>\r\n", styles: ["app-fab-filter .description-block{padding-bottom:15px;font-size:12px}app-fab-filter .selectoption{cursor:pointer!important}app-fab-filter .mat-select-value{cursor:pointer!important}app-fab-filter .row{display:flex}app-fab-filter .full-width{width:100%}app-fab-filter .icon-position{margin-top:14px}app-fab-filter .select{flex:auto}app-fab-filter .reset{cursor:pointer;font-size:26px}app-fab-filter .colour-preview-selected{padding:5px;margin-left:5px;margin-top:8px;border:1px solid #000}.mat-select-min-line:first-letter{text-transform:capitalize}.filter-name:first-letter{text-transform:capitalize}.colour-preview{padding:5px;border:1px solid #000;line-height:20px;margin:10px}.name-span{line-height:52px}.select-mat-option .mat-option-text:first-letter{text-transform:capitalize}.select-mat-option .mat-option-text{display:flex}.mat-select-disabled .mat-select-arrow{display:none}.mat-select-panel-wrap{top:15px;position:relative}.mat-select-panel{max-width:100%!important}.filter-option-image{max-width:40px;max-height:40px}.filter-option-image-div{max-height:40px;padding-right:4px}\n"], dependencies: [{ kind: "directive", type: i4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: i5.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i5.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i6$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i8$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i10.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i10.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }], encapsulation: i0.ViewEncapsulation.None });
23943
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.13", type: FabFilterComponent, isStandalone: false, selector: "app-fab-filter", inputs: { filter: "filter" }, outputs: { filterchanged: "filterchanged", selectoption: "selectoption" }, ngImport: i0, template: "<div class=\"row\" *ngIf=\"!filter.hidden\">\r\n <div class=\"select\" (click)=\"Click()\" [ngClass]=\"{'selectoption': filter.selectedOption != 0 }\">\r\n <mat-form-field appearance=\"fill\" class=\"full-width\">\r\n <mat-label class=\"select-mat-label filter-name\">\r\n {{ TranslateService.GetActiveValue(TranslationCategory.Filter, TranslationSubCategory.Name, filter.id) }}\r\n <ng-container *ngIf=\"filter.blocksProductSelect || FabrikantenService.IsAProductSelected()\">\r\n <span *ngIf=\"filter.blocksProductSelect || filter.required\">*&nbsp;</span>\r\n <span *ngIf=\"filter.affectsOnlyBestek\"><sup>1</sup></span>\r\n </ng-container>\r\n </mat-label>\r\n <mat-select [(ngModel)]=\"SelectedOptionId\" [disabled]=\"IsDisabled()\">\r\n <ng-container *ngFor=\"let option of filter.options\">\r\n <mat-option [value]=\"option.id\" class=\"select-mat-option\" *ngIf=\"!option.hidden\" (click)=\"SelectOption()\">\r\n <ng-container *ngIf=\"option.colour != null && option.colour != ''\">\r\n <span [ngStyle]=\"{'background-color': option.colour}\" class=\"colour-preview\">\r\n &nbsp;\r\n &nbsp;\r\n </span>\r\n </ng-container>\r\n <ng-container *ngIf=\"option.imagePath != null && option.imagePath != ''\">\r\n <div class=\"filter-option-image-div\">\r\n <img src=\"{{ GetImagePath(option) }}\" class=\"filter-option-image\" />\r\n </div>\r\n </ng-container>\r\n <span class=\"name-span\">\r\n {{ TranslateService.GetActiveValue(TranslationCategory.FilterOption, TranslationSubCategory.Name, option.id) }}\r\n </span>\r\n <span *ngIf=\"filter.unit != null\" class=\"name-span unit-span\">\r\n &nbsp;{{ filter.unit }}\r\n </span>\r\n </mat-option>\r\n </ng-container>\r\n </mat-select>\r\n </mat-form-field>\r\n <p *ngIf=\"ShowDescription()\" class=\"description-block\">{{ GetDescription() }}</p>\r\n </div>\r\n <div *ngIf=\"GetSelectedOption() != null && GetSelectedOption().colour != null && GetSelectedOption().colour != ''\">\r\n <div [ngStyle]=\"{'background-color': GetSelectedOption().colour}\" class=\"colour-preview-selected\">\r\n &nbsp;\r\n &nbsp;\r\n </div>\r\n </div>\r\n <div class=\"reset\" *ngIf=\"filter.selectedOption != 0\" (click)=\"ResetSelection()\">\r\n <mat-icon class=\"icon-position clear\" [inline]=\"true\">clear</mat-icon>\r\n </div>\r\n</div>\r\n<div *ngFor=\"let description of filter.descriptions\" class=\"description-block\">\r\n {{ description.description }}\r\n</div>\r\n", styles: ["app-fab-filter .description-block{padding-bottom:15px;font-size:12px}app-fab-filter .selectoption{cursor:pointer!important}app-fab-filter .mat-select-value{cursor:pointer!important}app-fab-filter .row{display:flex}app-fab-filter .full-width{width:100%}app-fab-filter .icon-position{margin-top:14px}app-fab-filter .select{flex:auto}app-fab-filter .reset{cursor:pointer;font-size:26px}app-fab-filter .colour-preview-selected{padding:5px;margin-left:5px;margin-top:8px;border:1px solid #000}.mat-select-min-line:first-letter{text-transform:capitalize}.filter-name:first-letter{text-transform:capitalize}.colour-preview{padding:5px;border:1px solid #000;line-height:20px;margin:10px}.name-span{line-height:52px}.select-mat-option .mat-option-text:first-letter{text-transform:capitalize}.select-mat-option .mat-option-text{display:flex}.mat-select-disabled .mat-select-arrow{display:none}.mat-select-panel-wrap{top:15px;position:relative}.mat-select-panel{max-width:100%!important}.filter-option-image{max-width:40px;max-height:40px}.filter-option-image-div{max-height:40px;padding-right:4px}\n"], dependencies: [{ kind: "directive", type: i4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: i5.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i5.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i6$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i8$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i10.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i10.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }], encapsulation: i0.ViewEncapsulation.None });
23920
23944
  }
23921
23945
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: FabFilterComponent, decorators: [{
23922
23946
  type: Component,
23923
- args: [{ selector: 'app-fab-filter', standalone: false, encapsulation: ViewEncapsulation.None, template: "<div class=\"row\" *ngIf=\"!filter.hidden\">\r\n <div class=\"select\" (click)=\"Click()\" [ngClass]=\"{'selectoption': filter.selectedOption != 0 }\">\r\n <mat-form-field appearance=\"fill\" class=\"full-width\">\r\n <mat-label class=\"select-mat-label filter-name\">\r\n {{ TranslateService.GetActiveValue(TranslationCategory.Filter, TranslationSubCategory.Name, filter.id) }}\r\n <ng-container *ngIf=\"filter.blocksProductSelect || FabrikantenService.IsAProductSelected()\">\r\n <span *ngIf=\"filter.blocksProductSelect || filter.required\">*&nbsp;</span>\r\n <span *ngIf=\"filter.affectsOnlyBestek\"><sup>1</sup></span>\r\n </ng-container>\r\n </mat-label>\r\n <mat-select [(ngModel)]=\"SelectedOptionId\" (selectionChange)=\"SelectOption()\" [disabled]=\"IsDisabled()\">\r\n <ng-container *ngFor=\"let option of filter.options\">\r\n <mat-option [value]=\"option.id\" class=\"select-mat-option\" *ngIf=\"!option.hidden\">\r\n <ng-container *ngIf=\"option.colour != null && option.colour != ''\">\r\n <span [ngStyle]=\"{'background-color': option.colour}\" class=\"colour-preview\">\r\n &nbsp;\r\n &nbsp;\r\n </span>\r\n </ng-container>\r\n <ng-container *ngIf=\"option.imagePath != null && option.imagePath != ''\">\r\n <div class=\"filter-option-image-div\">\r\n <img src=\"{{ GetImagePath(option) }}\" class=\"filter-option-image\" />\r\n </div>\r\n </ng-container>\r\n <span class=\"name-span\">\r\n {{ TranslateService.GetActiveValue(TranslationCategory.FilterOption, TranslationSubCategory.Name, option.id) }}\r\n </span>\r\n <span *ngIf=\"filter.unit != null\" class=\"name-span unit-span\">\r\n &nbsp;{{ filter.unit }}\r\n </span>\r\n </mat-option>\r\n </ng-container>\r\n </mat-select>\r\n </mat-form-field>\r\n <p *ngIf=\"ShowDescription()\" class=\"description-block\">{{ GetDescription() }}</p>\r\n </div>\r\n <div *ngIf=\"GetSelectedOption() != null && GetSelectedOption().colour != null && GetSelectedOption().colour != ''\">\r\n <div [ngStyle]=\"{'background-color': GetSelectedOption().colour}\" class=\"colour-preview-selected\">\r\n &nbsp;\r\n &nbsp;\r\n </div>\r\n </div>\r\n <div class=\"reset\" *ngIf=\"filter.selectedOption != 0\" (click)=\"ResetSelection()\">\r\n <mat-icon class=\"icon-position clear\" [inline]=\"true\">clear</mat-icon>\r\n </div>\r\n</div>\r\n<div *ngFor=\"let description of filter.descriptions\" class=\"description-block\">\r\n {{ description.description }}\r\n</div>\r\n", styles: ["app-fab-filter .description-block{padding-bottom:15px;font-size:12px}app-fab-filter .selectoption{cursor:pointer!important}app-fab-filter .mat-select-value{cursor:pointer!important}app-fab-filter .row{display:flex}app-fab-filter .full-width{width:100%}app-fab-filter .icon-position{margin-top:14px}app-fab-filter .select{flex:auto}app-fab-filter .reset{cursor:pointer;font-size:26px}app-fab-filter .colour-preview-selected{padding:5px;margin-left:5px;margin-top:8px;border:1px solid #000}.mat-select-min-line:first-letter{text-transform:capitalize}.filter-name:first-letter{text-transform:capitalize}.colour-preview{padding:5px;border:1px solid #000;line-height:20px;margin:10px}.name-span{line-height:52px}.select-mat-option .mat-option-text:first-letter{text-transform:capitalize}.select-mat-option .mat-option-text{display:flex}.mat-select-disabled .mat-select-arrow{display:none}.mat-select-panel-wrap{top:15px;position:relative}.mat-select-panel{max-width:100%!important}.filter-option-image{max-width:40px;max-height:40px}.filter-option-image-div{max-height:40px;padding-right:4px}\n"] }]
23947
+ args: [{ selector: 'app-fab-filter', standalone: false, encapsulation: ViewEncapsulation.None, template: "<div class=\"row\" *ngIf=\"!filter.hidden\">\r\n <div class=\"select\" (click)=\"Click()\" [ngClass]=\"{'selectoption': filter.selectedOption != 0 }\">\r\n <mat-form-field appearance=\"fill\" class=\"full-width\">\r\n <mat-label class=\"select-mat-label filter-name\">\r\n {{ TranslateService.GetActiveValue(TranslationCategory.Filter, TranslationSubCategory.Name, filter.id) }}\r\n <ng-container *ngIf=\"filter.blocksProductSelect || FabrikantenService.IsAProductSelected()\">\r\n <span *ngIf=\"filter.blocksProductSelect || filter.required\">*&nbsp;</span>\r\n <span *ngIf=\"filter.affectsOnlyBestek\"><sup>1</sup></span>\r\n </ng-container>\r\n </mat-label>\r\n <mat-select [(ngModel)]=\"SelectedOptionId\" [disabled]=\"IsDisabled()\">\r\n <ng-container *ngFor=\"let option of filter.options\">\r\n <mat-option [value]=\"option.id\" class=\"select-mat-option\" *ngIf=\"!option.hidden\" (click)=\"SelectOption()\">\r\n <ng-container *ngIf=\"option.colour != null && option.colour != ''\">\r\n <span [ngStyle]=\"{'background-color': option.colour}\" class=\"colour-preview\">\r\n &nbsp;\r\n &nbsp;\r\n </span>\r\n </ng-container>\r\n <ng-container *ngIf=\"option.imagePath != null && option.imagePath != ''\">\r\n <div class=\"filter-option-image-div\">\r\n <img src=\"{{ GetImagePath(option) }}\" class=\"filter-option-image\" />\r\n </div>\r\n </ng-container>\r\n <span class=\"name-span\">\r\n {{ TranslateService.GetActiveValue(TranslationCategory.FilterOption, TranslationSubCategory.Name, option.id) }}\r\n </span>\r\n <span *ngIf=\"filter.unit != null\" class=\"name-span unit-span\">\r\n &nbsp;{{ filter.unit }}\r\n </span>\r\n </mat-option>\r\n </ng-container>\r\n </mat-select>\r\n </mat-form-field>\r\n <p *ngIf=\"ShowDescription()\" class=\"description-block\">{{ GetDescription() }}</p>\r\n </div>\r\n <div *ngIf=\"GetSelectedOption() != null && GetSelectedOption().colour != null && GetSelectedOption().colour != ''\">\r\n <div [ngStyle]=\"{'background-color': GetSelectedOption().colour}\" class=\"colour-preview-selected\">\r\n &nbsp;\r\n &nbsp;\r\n </div>\r\n </div>\r\n <div class=\"reset\" *ngIf=\"filter.selectedOption != 0\" (click)=\"ResetSelection()\">\r\n <mat-icon class=\"icon-position clear\" [inline]=\"true\">clear</mat-icon>\r\n </div>\r\n</div>\r\n<div *ngFor=\"let description of filter.descriptions\" class=\"description-block\">\r\n {{ description.description }}\r\n</div>\r\n", styles: ["app-fab-filter .description-block{padding-bottom:15px;font-size:12px}app-fab-filter .selectoption{cursor:pointer!important}app-fab-filter .mat-select-value{cursor:pointer!important}app-fab-filter .row{display:flex}app-fab-filter .full-width{width:100%}app-fab-filter .icon-position{margin-top:14px}app-fab-filter .select{flex:auto}app-fab-filter .reset{cursor:pointer;font-size:26px}app-fab-filter .colour-preview-selected{padding:5px;margin-left:5px;margin-top:8px;border:1px solid #000}.mat-select-min-line:first-letter{text-transform:capitalize}.filter-name:first-letter{text-transform:capitalize}.colour-preview{padding:5px;border:1px solid #000;line-height:20px;margin:10px}.name-span{line-height:52px}.select-mat-option .mat-option-text:first-letter{text-transform:capitalize}.select-mat-option .mat-option-text{display:flex}.mat-select-disabled .mat-select-arrow{display:none}.mat-select-panel-wrap{top:15px;position:relative}.mat-select-panel{max-width:100%!important}.filter-option-image{max-width:40px;max-height:40px}.filter-option-image-div{max-height:40px;padding-right:4px}\n"] }]
23924
23948
  }], ctorParameters: () => [{ type: FabrikantenService }, { type: TranslateService }, { type: i3.ActivatedRoute }, { type: i0.ChangeDetectorRef }], propDecorators: { filter: [{
23925
23949
  type: Input
23926
23950
  }], filterchanged: [{
@@ -24109,11 +24133,11 @@ class FabFormComponent {
24109
24133
  return false;
24110
24134
  }
24111
24135
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: FabFormComponent, deps: [{ token: i6$1.FormBuilder }, { token: FabrikantenApiClient }, { token: FabrikantenService }, { token: TranslateService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
24112
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.13", type: FabFormComponent, isStandalone: false, selector: "app-fab-form", inputs: { form: "form", instanceid: "instanceid" }, outputs: { completed: "completed" }, ngImport: i0, template: "<form [formGroup]=\"FormGroup\">\n <ng-container *ngFor=\"let cat of form.formCategories\">\n <div class=\"form-cat-name\" [ngClass]=\"'cat-' + cat.id\">\n {{ TranslateService.GetActiveValue(TranslationCategory.Forms, TranslationSubCategory.Category, cat.id) }}\n </div>\n <ng-container *ngFor=\"let row of cat.rows\">\n <div class=\"form-cat-inputs displayflex\">\n <div class=\"form-cat-input\" *ngFor=\"let input of row.inputs\">\n <ng-container *ngIf=\"input.formInputType == 1 || input.formInputType == 6\">\n <mat-form-field appearance=\"fill\" class=\"full-width form-cat-input-input\">\n <mat-label>\n {{ TranslateService.GetActiveValue(TranslationCategory.Forms, TranslationSubCategory.Input, input.id) }}\n </mat-label>\n <input matInput type=\"text\" formControlName=\"{{ input.name }}\" [(ngModel)]=\"input.value\">\n <mat-error></mat-error>\n </mat-form-field>\n </ng-container>\n\n <ng-container *ngIf=\"input.formInputType == 2\">\n <mat-form-field appearance=\"fill\" class=\"full-width form-cat-input-select\">\n <mat-label class=\"select-mat-label filter-name\">\n {{ TranslateService.GetActiveValue(TranslationCategory.Forms, TranslationSubCategory.Input, input.id) }}\n </mat-label>\n <mat-select formControlName=\"{{ input.name }}\" [(ngModel)]=\"input.value\">\n <ng-container *ngFor=\"let option of input.options\">\n <mat-option [value]=\"TranslateService.GetActiveValue(TranslationCategory.Forms, TranslationSubCategory.Option, option.id)\" class=\"select-mat-option\">\n <span class=\"name-span\">\n {{ TranslateService.GetActiveValue(TranslationCategory.Forms, TranslationSubCategory.Option, option.id) }}\n </span>\n </mat-option>\n </ng-container>\n </mat-select>\n </mat-form-field>\n </ng-container>\n\n <ng-container *ngIf=\"input.formInputType == 3 || input.formInputType == 7\">\n <mat-checkbox class=\"form-cat-input-checkbox\" formControlName=\"{{ input.name }}\" [(ngModel)]=\"input.checked\">\n <span [innerHTML]=\"TranslateService.GetActiveValue(TranslationCategory.Forms, TranslationSubCategory.Input, input.id)\"></span>\n </mat-checkbox>\n </ng-container>\n\n <ng-container *ngIf=\"input.formInputType == 8\">\n <span class=\"form-input-text\" [innerHTML]=\"TranslateService.GetActiveValue(TranslationCategory.Forms, TranslationSubCategory.Input, input.id)\"></span>\n </ng-container>\n\n <ng-container *ngIf=\"input.formInputType == 5\">\n <mat-form-field class=\"full-width form-cat-input-textarea\">\n <mat-label>\n {{ TranslateService.GetActiveValue(TranslationCategory.Forms, TranslationSubCategory.Input, input.id) }}\n </mat-label>\n <textarea matInput formControlName=\"{{ input.name }}\" [(ngModel)]=\"input.value\" style=\"height: 100px;\"></textarea>\n </mat-form-field>\n </ng-container>\n </div>\n </div>\n </ng-container>\n </ng-container>\n\n <div class=\"form-button-row\">\n <div class=\"mandatory-text\" *ngIf=\"ShowMandatoryText()\">\n {{ TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.RequiredField) }}\n </div>\n <button mat-raised-button (click)=\"Close()\" class=\"form-cat-close form-button-row-button\">\n {{ TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.Close) }}\n </button>\n <ng-container *ngIf=\"AllowSkip()\">\n <button mat-raised-button (click)=\"Skip()\" class=\"form-cat-close form-button-row-button\">\n {{ TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.Skip) }}\n </button>\n </ng-container>\n <button mat-raised-button (click)=\"OnSubmit()\" class=\"form-cat-submit form-button-row-button\">\n {{ TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.Send) }}\n </button>\n </div>\n</form>\n", styles: ["app-fab-form .mat-form-field-wrapper{padding-bottom:0}app-fab-form .mat-form-field-underline{bottom:0}app-fab-form .displayflex{display:flex}app-fab-form .form-cat-name{border-bottom:1px solid #000;font-size:20px;padding:5px}app-fab-form .form-cat-input{padding:3px;width:100%}app-fab-form .form-button-row{text-align:right}app-fab-form .form-button-row-button{margin:5px}app-fab-form .full-width{width:100%}\n"], dependencies: [{ kind: "directive", type: i4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: i5.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i5.MatLabel, selector: "mat-label" }, { kind: "directive", type: i5.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i6$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i6$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i6$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i6$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "component", type: i7.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i9.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "component", type: i10.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i10.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "directive", type: i6$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i6$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }], encapsulation: i0.ViewEncapsulation.None });
24136
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.13", type: FabFormComponent, isStandalone: false, selector: "app-fab-form", inputs: { form: "form", instanceid: "instanceid" }, outputs: { completed: "completed" }, ngImport: i0, template: "<form [formGroup]=\"FormGroup\">\r\n <ng-container *ngFor=\"let cat of form.formCategories\">\r\n <div class=\"form-cat-name\" [ngClass]=\"'cat-' + cat.id\">\r\n {{ TranslateService.GetActiveValue(TranslationCategory.Forms, TranslationSubCategory.Category, cat.id) }}\r\n </div>\r\n <ng-container *ngFor=\"let row of cat.rows\">\r\n <div class=\"form-cat-inputs displayflex\">\r\n <div class=\"form-cat-input\" *ngFor=\"let input of row.inputs\">\r\n <ng-container *ngIf=\"input.formInputType == 1 || input.formInputType == 6\">\r\n <mat-form-field appearance=\"fill\" class=\"full-width form-cat-input-input\">\r\n <mat-label>\r\n {{ TranslateService.GetActiveValue(TranslationCategory.Forms, TranslationSubCategory.Input, input.id) }}\r\n </mat-label>\r\n <input matInput type=\"text\" formControlName=\"{{ input.name }}\" [(ngModel)]=\"input.value\">\r\n <mat-error></mat-error>\r\n </mat-form-field>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"input.formInputType == 2\">\r\n <mat-form-field appearance=\"fill\" class=\"full-width form-cat-input-select\">\r\n <mat-label class=\"select-mat-label filter-name\">\r\n {{ TranslateService.GetActiveValue(TranslationCategory.Forms, TranslationSubCategory.Input, input.id) }}\r\n </mat-label>\r\n <mat-select formControlName=\"{{ input.name }}\" [(ngModel)]=\"input.value\">\r\n <ng-container *ngFor=\"let option of input.options\">\r\n <mat-option [value]=\"TranslateService.GetActiveValue(TranslationCategory.Forms, TranslationSubCategory.Option, option.id)\" class=\"select-mat-option\">\r\n <span class=\"name-span\">\r\n {{ TranslateService.GetActiveValue(TranslationCategory.Forms, TranslationSubCategory.Option, option.id) }}\r\n </span>\r\n </mat-option>\r\n </ng-container>\r\n </mat-select>\r\n </mat-form-field>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"input.formInputType == 3 || input.formInputType == 7\">\r\n <mat-checkbox class=\"form-cat-input-checkbox\" formControlName=\"{{ input.name }}\" [(ngModel)]=\"input.checked\">\r\n <span [innerHTML]=\"TranslateService.GetActiveValue(TranslationCategory.Forms, TranslationSubCategory.Input, input.id)\"></span>\r\n </mat-checkbox>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"input.formInputType == 8\">\r\n <span class=\"form-input-text\" [innerHTML]=\"TranslateService.GetActiveValue(TranslationCategory.Forms, TranslationSubCategory.Input, input.id)\"></span>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"input.formInputType == 5\">\r\n <mat-form-field class=\"full-width form-cat-input-textarea\">\r\n <mat-label>\r\n {{ TranslateService.GetActiveValue(TranslationCategory.Forms, TranslationSubCategory.Input, input.id) }}\r\n </mat-label>\r\n <textarea matInput formControlName=\"{{ input.name }}\" [(ngModel)]=\"input.value\" style=\"height: 100px;\"></textarea>\r\n </mat-form-field>\r\n </ng-container>\r\n </div>\r\n </div>\r\n </ng-container>\r\n </ng-container>\r\n\r\n <div class=\"form-button-row\">\r\n <div class=\"mandatory-text\" *ngIf=\"ShowMandatoryText()\">\r\n {{ TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.RequiredField) }}\r\n </div>\r\n <button mat-raised-button (click)=\"Close()\" class=\"form-cat-close form-button-row-button\">\r\n {{ TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.Close) }}\r\n </button>\r\n <ng-container *ngIf=\"AllowSkip()\">\r\n <button mat-raised-button (click)=\"Skip()\" class=\"form-cat-close form-button-row-button\">\r\n {{ TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.Skip) }}\r\n </button>\r\n </ng-container>\r\n <button mat-raised-button (click)=\"OnSubmit()\" class=\"form-cat-submit form-button-row-button\">\r\n {{ TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.Send) }}\r\n </button>\r\n </div>\r\n</form>\r\n", styles: ["app-fab-form .mat-form-field-wrapper{padding-bottom:0}app-fab-form .mat-form-field-underline{bottom:0}app-fab-form .displayflex{display:flex}app-fab-form .form-cat-name{border-bottom:1px solid #000;font-size:20px;padding:5px}app-fab-form .form-cat-input{padding:3px;width:100%}app-fab-form .form-button-row{text-align:right}app-fab-form .form-button-row-button{margin:5px}app-fab-form .full-width{width:100%}\n"], dependencies: [{ kind: "directive", type: i4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: i5.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i5.MatLabel, selector: "mat-label" }, { kind: "directive", type: i5.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i6$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i6$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i6$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i6$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "component", type: i7.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i9.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "component", type: i10.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i10.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "directive", type: i6$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i6$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }], encapsulation: i0.ViewEncapsulation.None });
24113
24137
  }
24114
24138
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: FabFormComponent, decorators: [{
24115
24139
  type: Component,
24116
- args: [{ selector: 'app-fab-form', standalone: false, encapsulation: ViewEncapsulation.None, template: "<form [formGroup]=\"FormGroup\">\n <ng-container *ngFor=\"let cat of form.formCategories\">\n <div class=\"form-cat-name\" [ngClass]=\"'cat-' + cat.id\">\n {{ TranslateService.GetActiveValue(TranslationCategory.Forms, TranslationSubCategory.Category, cat.id) }}\n </div>\n <ng-container *ngFor=\"let row of cat.rows\">\n <div class=\"form-cat-inputs displayflex\">\n <div class=\"form-cat-input\" *ngFor=\"let input of row.inputs\">\n <ng-container *ngIf=\"input.formInputType == 1 || input.formInputType == 6\">\n <mat-form-field appearance=\"fill\" class=\"full-width form-cat-input-input\">\n <mat-label>\n {{ TranslateService.GetActiveValue(TranslationCategory.Forms, TranslationSubCategory.Input, input.id) }}\n </mat-label>\n <input matInput type=\"text\" formControlName=\"{{ input.name }}\" [(ngModel)]=\"input.value\">\n <mat-error></mat-error>\n </mat-form-field>\n </ng-container>\n\n <ng-container *ngIf=\"input.formInputType == 2\">\n <mat-form-field appearance=\"fill\" class=\"full-width form-cat-input-select\">\n <mat-label class=\"select-mat-label filter-name\">\n {{ TranslateService.GetActiveValue(TranslationCategory.Forms, TranslationSubCategory.Input, input.id) }}\n </mat-label>\n <mat-select formControlName=\"{{ input.name }}\" [(ngModel)]=\"input.value\">\n <ng-container *ngFor=\"let option of input.options\">\n <mat-option [value]=\"TranslateService.GetActiveValue(TranslationCategory.Forms, TranslationSubCategory.Option, option.id)\" class=\"select-mat-option\">\n <span class=\"name-span\">\n {{ TranslateService.GetActiveValue(TranslationCategory.Forms, TranslationSubCategory.Option, option.id) }}\n </span>\n </mat-option>\n </ng-container>\n </mat-select>\n </mat-form-field>\n </ng-container>\n\n <ng-container *ngIf=\"input.formInputType == 3 || input.formInputType == 7\">\n <mat-checkbox class=\"form-cat-input-checkbox\" formControlName=\"{{ input.name }}\" [(ngModel)]=\"input.checked\">\n <span [innerHTML]=\"TranslateService.GetActiveValue(TranslationCategory.Forms, TranslationSubCategory.Input, input.id)\"></span>\n </mat-checkbox>\n </ng-container>\n\n <ng-container *ngIf=\"input.formInputType == 8\">\n <span class=\"form-input-text\" [innerHTML]=\"TranslateService.GetActiveValue(TranslationCategory.Forms, TranslationSubCategory.Input, input.id)\"></span>\n </ng-container>\n\n <ng-container *ngIf=\"input.formInputType == 5\">\n <mat-form-field class=\"full-width form-cat-input-textarea\">\n <mat-label>\n {{ TranslateService.GetActiveValue(TranslationCategory.Forms, TranslationSubCategory.Input, input.id) }}\n </mat-label>\n <textarea matInput formControlName=\"{{ input.name }}\" [(ngModel)]=\"input.value\" style=\"height: 100px;\"></textarea>\n </mat-form-field>\n </ng-container>\n </div>\n </div>\n </ng-container>\n </ng-container>\n\n <div class=\"form-button-row\">\n <div class=\"mandatory-text\" *ngIf=\"ShowMandatoryText()\">\n {{ TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.RequiredField) }}\n </div>\n <button mat-raised-button (click)=\"Close()\" class=\"form-cat-close form-button-row-button\">\n {{ TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.Close) }}\n </button>\n <ng-container *ngIf=\"AllowSkip()\">\n <button mat-raised-button (click)=\"Skip()\" class=\"form-cat-close form-button-row-button\">\n {{ TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.Skip) }}\n </button>\n </ng-container>\n <button mat-raised-button (click)=\"OnSubmit()\" class=\"form-cat-submit form-button-row-button\">\n {{ TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.Send) }}\n </button>\n </div>\n</form>\n", styles: ["app-fab-form .mat-form-field-wrapper{padding-bottom:0}app-fab-form .mat-form-field-underline{bottom:0}app-fab-form .displayflex{display:flex}app-fab-form .form-cat-name{border-bottom:1px solid #000;font-size:20px;padding:5px}app-fab-form .form-cat-input{padding:3px;width:100%}app-fab-form .form-button-row{text-align:right}app-fab-form .form-button-row-button{margin:5px}app-fab-form .full-width{width:100%}\n"] }]
24140
+ args: [{ selector: 'app-fab-form', standalone: false, encapsulation: ViewEncapsulation.None, template: "<form [formGroup]=\"FormGroup\">\r\n <ng-container *ngFor=\"let cat of form.formCategories\">\r\n <div class=\"form-cat-name\" [ngClass]=\"'cat-' + cat.id\">\r\n {{ TranslateService.GetActiveValue(TranslationCategory.Forms, TranslationSubCategory.Category, cat.id) }}\r\n </div>\r\n <ng-container *ngFor=\"let row of cat.rows\">\r\n <div class=\"form-cat-inputs displayflex\">\r\n <div class=\"form-cat-input\" *ngFor=\"let input of row.inputs\">\r\n <ng-container *ngIf=\"input.formInputType == 1 || input.formInputType == 6\">\r\n <mat-form-field appearance=\"fill\" class=\"full-width form-cat-input-input\">\r\n <mat-label>\r\n {{ TranslateService.GetActiveValue(TranslationCategory.Forms, TranslationSubCategory.Input, input.id) }}\r\n </mat-label>\r\n <input matInput type=\"text\" formControlName=\"{{ input.name }}\" [(ngModel)]=\"input.value\">\r\n <mat-error></mat-error>\r\n </mat-form-field>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"input.formInputType == 2\">\r\n <mat-form-field appearance=\"fill\" class=\"full-width form-cat-input-select\">\r\n <mat-label class=\"select-mat-label filter-name\">\r\n {{ TranslateService.GetActiveValue(TranslationCategory.Forms, TranslationSubCategory.Input, input.id) }}\r\n </mat-label>\r\n <mat-select formControlName=\"{{ input.name }}\" [(ngModel)]=\"input.value\">\r\n <ng-container *ngFor=\"let option of input.options\">\r\n <mat-option [value]=\"TranslateService.GetActiveValue(TranslationCategory.Forms, TranslationSubCategory.Option, option.id)\" class=\"select-mat-option\">\r\n <span class=\"name-span\">\r\n {{ TranslateService.GetActiveValue(TranslationCategory.Forms, TranslationSubCategory.Option, option.id) }}\r\n </span>\r\n </mat-option>\r\n </ng-container>\r\n </mat-select>\r\n </mat-form-field>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"input.formInputType == 3 || input.formInputType == 7\">\r\n <mat-checkbox class=\"form-cat-input-checkbox\" formControlName=\"{{ input.name }}\" [(ngModel)]=\"input.checked\">\r\n <span [innerHTML]=\"TranslateService.GetActiveValue(TranslationCategory.Forms, TranslationSubCategory.Input, input.id)\"></span>\r\n </mat-checkbox>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"input.formInputType == 8\">\r\n <span class=\"form-input-text\" [innerHTML]=\"TranslateService.GetActiveValue(TranslationCategory.Forms, TranslationSubCategory.Input, input.id)\"></span>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"input.formInputType == 5\">\r\n <mat-form-field class=\"full-width form-cat-input-textarea\">\r\n <mat-label>\r\n {{ TranslateService.GetActiveValue(TranslationCategory.Forms, TranslationSubCategory.Input, input.id) }}\r\n </mat-label>\r\n <textarea matInput formControlName=\"{{ input.name }}\" [(ngModel)]=\"input.value\" style=\"height: 100px;\"></textarea>\r\n </mat-form-field>\r\n </ng-container>\r\n </div>\r\n </div>\r\n </ng-container>\r\n </ng-container>\r\n\r\n <div class=\"form-button-row\">\r\n <div class=\"mandatory-text\" *ngIf=\"ShowMandatoryText()\">\r\n {{ TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.RequiredField) }}\r\n </div>\r\n <button mat-raised-button (click)=\"Close()\" class=\"form-cat-close form-button-row-button\">\r\n {{ TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.Close) }}\r\n </button>\r\n <ng-container *ngIf=\"AllowSkip()\">\r\n <button mat-raised-button (click)=\"Skip()\" class=\"form-cat-close form-button-row-button\">\r\n {{ TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.Skip) }}\r\n </button>\r\n </ng-container>\r\n <button mat-raised-button (click)=\"OnSubmit()\" class=\"form-cat-submit form-button-row-button\">\r\n {{ TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.Send) }}\r\n </button>\r\n </div>\r\n</form>\r\n", styles: ["app-fab-form .mat-form-field-wrapper{padding-bottom:0}app-fab-form .mat-form-field-underline{bottom:0}app-fab-form .displayflex{display:flex}app-fab-form .form-cat-name{border-bottom:1px solid #000;font-size:20px;padding:5px}app-fab-form .form-cat-input{padding:3px;width:100%}app-fab-form .form-button-row{text-align:right}app-fab-form .form-button-row-button{margin:5px}app-fab-form .full-width{width:100%}\n"] }]
24117
24141
  }], ctorParameters: () => [{ type: i6$1.FormBuilder }, { type: FabrikantenApiClient }, { type: FabrikantenService }, { type: TranslateService }, { type: i0.ChangeDetectorRef }], propDecorators: { form: [{
24118
24142
  type: Input
24119
24143
  }], instanceid: [{
@@ -28783,6 +28807,9 @@ class FabFiltersInputComponent {
28783
28807
  }
28784
28808
  return false;
28785
28809
  }
28810
+ ShowAccordion() {
28811
+ return this.FabrikantenService.FabrikantenSettingsViewModel?.stepperFoldable == true;
28812
+ }
28786
28813
  ShowAffectsOnlyBestek() {
28787
28814
  if (this.FabrikantenService.FabrikantenViewModel?.selectedProduct != null) {
28788
28815
  if (this.FabrikantenService.FabrikantenViewModel?.inputs != null) {
@@ -28829,11 +28856,11 @@ class FabFiltersInputComponent {
28829
28856
  return "disabled_af";
28830
28857
  }
28831
28858
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: FabFiltersInputComponent, deps: [{ token: i3.Router }, { token: FabrikantenService }, { token: TranslateService }, { token: FabrikantenApiClient }, { token: ConfiguratorApiClient }, { token: AuthenticationService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
28832
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.13", type: FabFiltersInputComponent, isStandalone: false, selector: "fab-filters-input", inputs: { displayExtra: "displayExtra" }, ngImport: i0, template: "<div class=\"filter-view-margin\">\r\n <div class=\"filter-view-header\">\r\n <ng-container *ngIf=\"ShowInputCode()\">\r\n <div>\r\n <div class=\"filter-view-header-h1\">\r\n <h1 class=\"h1-auto\">{{ GetHeaderName() }}</h1>\r\n <div class=\"filter-view-header-reset\" (click)=\"ResetAllFilters()\">\r\n {{ TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.ResetFilters) }}\r\n </div>\r\n </div>\r\n <div>\r\n <app-fab-input-code></app-fab-input-code>\r\n </div>\r\n </div>\r\n </ng-container>\r\n <ng-container *ngIf=\"!ShowInputCode()\">\r\n <div class=\"filter-view-header-h1\">\r\n <h1>{{ GetHeaderName() }}</h1>\r\n </div>\r\n <div class=\"filter-view-header-reset\" (click)=\"ResetAllFilters()\">\r\n {{ TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.ResetFilters) }}\r\n </div>\r\n </ng-container>\r\n </div>\r\n\r\n <ng-container *ngIf=\"!ShowCategories()\">\r\n <div class=\"inputs-container\" [ngClass]=\"{'two-columns': ShowTwoColumns() }\">\r\n <ng-container *ngFor=\"let inputviewmodel of FabrikantenService.FabrikantenViewModel.inputs; index as i\">\r\n <ng-container *ngIf=\"!inputviewmodel.extra || displayExtra\">\r\n <app-fab-input [input]=\"inputviewmodel\" [ngClass]=\"{'col1': i % 2 == 0, 'col2': i % 2 == 1 }\"></app-fab-input>\r\n </ng-container>\r\n </ng-container>\r\n </div>\r\n\r\n <ng-container *ngIf=\"ShowAffectsOnlyBestek()\">\r\n <div class=\"affects-only-bestek\">\r\n <span><sup>1</sup></span>\r\n {{ TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.AffectsOnlyBestek) }}\r\n </div>\r\n </ng-container>\r\n </ng-container>\r\n\r\n <div *ngIf=\"ShowCategories()\">\r\n <mat-stepper orientation=\"vertical\" [linear]=\"true\" #stepper>\r\n <ng-template matStepperIcon=\"edit\" let-index=\"index\">\r\n {{ index + 1 }}\r\n </ng-template>\r\n\r\n <mat-step *ngFor=\"let cat of FabrikantenService.FabrikantenViewModel.filterCategories\" state=\"{{ cat.id }}\" [completed]=\"cat.completed\" [aria-labelledby]=\"GetHeaderAriaLabel(cat)\" [class.completed-step]=\"cat.completed\">\r\n <ng-template matStepLabel>\r\n <div class=\"step-name-div\">\r\n <div class=\"step-name-completed\" *ngIf=\"cat.completed\">\r\n <mat-icon class=\"step-name-completed-icon\">done</mat-icon>\r\n </div>\r\n <div class=\"step-name-name\">\r\n {{ TranslateService.GetActiveValue(TranslationCategory.FilterCategory, TranslationSubCategory.Name, cat.id) }}\r\n </div>\r\n <div class=\"step-name-icon\" *ngIf=\"cat.icon != null\">\r\n <span class=\"helper\"></span>\r\n <img [src]=\"cat.icon\" class=\"filter-category-icon\" />\r\n </div>\r\n </div>\r\n </ng-template>\r\n\r\n <ng-container *ngFor=\"let inputviewmodel of cat.inputs\">\r\n <app-fab-input [input]=\"inputviewmodel\"></app-fab-input>\r\n </ng-container>\r\n </mat-step>\r\n </mat-stepper>\r\n </div>\r\n</div>\r\n", styles: ["fab-filters-input .mat-step-header{cursor:pointer!important}fab-filters-input .filter-view-header-h1{display:flex}fab-filters-input .h1-auto{flex:auto}fab-filters-input .two-columns{display:flex;flex-wrap:wrap}fab-filters-input .mat-step-header[aria-labelledby=disabled_af]{cursor:not-allowed!important;opacity:.6}fab-filters-input .mat-step-header[aria-labelledby=enabled] .mat-step-icon{background-color:#000}fab-filters-input .mat-step-header[aria-labelledby=enabled] .mat-step-icon-selected{background-color:#3f51b5}fab-filters-input .filter-view-header{display:flex}fab-filters-input .filter-view-header-h1{flex:auto;text-transform:capitalize}fab-filters-input .step-name-icon{height:54px;white-space:nowrap;text-align:center;margin:auto 0}fab-filters-input .step-name-completed{height:54px;display:flex;align-items:center}fab-filters-input .step-name-div{width:100%}fab-filters-input .filter-category-icon{height:48px;vertical-align:middle}fab-filters-input .mat-step-text-label{width:100%}fab-filters-input .mat-step-label{width:100%}fab-filters-input .step-name-name{line-height:56px}fab-filters-input .helper{display:inline-block;height:100%;vertical-align:middle}fab-filters-input .filter-view-margin{padding:10px}fab-filters-input .filter-view-header-reset{cursor:pointer}fab-filters-input .mat-vertical-content-container{padding-top:10px}fab-filters-input .mat-vertical-content{padding:0}fab-filters-input .step-name-div{display:flex}fab-filters-input .step-name-name{flex:auto}fab-filters-input .save-conf-div{padding:15px}fab-filters-input .save-conf-div mat-spinner{margin:auto}\n"], dependencies: [{ kind: "directive", type: i4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i8$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i8$2.MatStep, selector: "mat-step", inputs: ["color"], exportAs: ["matStep"] }, { kind: "directive", type: i8$2.MatStepLabel, selector: "[matStepLabel]" }, { kind: "component", type: i8$2.MatStepper, selector: "mat-stepper, mat-vertical-stepper, mat-horizontal-stepper, [matStepper]", inputs: ["disableRipple", "color", "labelPosition", "headerPosition", "aria-label", "headerPrefix", "animationDuration"], outputs: ["animationDone"], exportAs: ["matStepper", "matVerticalStepper", "matHorizontalStepper"] }, { kind: "directive", type: i8$2.MatStepperIcon, selector: "ng-template[matStepperIcon]", inputs: ["matStepperIcon"] }, { kind: "component", type: FabInputCodeComponent, selector: "app-fab-input-code" }, { kind: "component", type: FabInputComponent, selector: "app-fab-input", inputs: ["input"] }], encapsulation: i0.ViewEncapsulation.None });
28859
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.13", type: FabFiltersInputComponent, isStandalone: false, selector: "fab-filters-input", inputs: { displayExtra: "displayExtra" }, ngImport: i0, template: "<div class=\"filter-view-margin\">\r\n <div class=\"filter-view-header\">\r\n <ng-container *ngIf=\"ShowInputCode()\">\r\n <div>\r\n <div class=\"filter-view-header-h1\">\r\n <h1 class=\"h1-auto\">{{ GetHeaderName() }}</h1>\r\n <div class=\"filter-view-header-reset\" (click)=\"ResetAllFilters()\">\r\n {{ TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.ResetFilters) }}\r\n </div>\r\n </div>\r\n <div>\r\n <app-fab-input-code></app-fab-input-code>\r\n </div>\r\n </div>\r\n </ng-container>\r\n <ng-container *ngIf=\"!ShowInputCode()\">\r\n <div class=\"filter-view-header-h1\">\r\n <h1>{{ GetHeaderName() }}</h1>\r\n </div>\r\n <div class=\"filter-view-header-reset\" (click)=\"ResetAllFilters()\">\r\n {{ TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.ResetFilters) }}\r\n </div>\r\n </ng-container>\r\n </div>\r\n\r\n <ng-container *ngIf=\"!ShowCategories()\">\r\n <div class=\"inputs-container\" [ngClass]=\"{'two-columns': ShowTwoColumns() }\">\r\n <ng-container *ngFor=\"let inputviewmodel of FabrikantenService.FabrikantenViewModel.inputs; index as i\">\r\n <ng-container *ngIf=\"!inputviewmodel.extra || displayExtra\">\r\n <app-fab-input [input]=\"inputviewmodel\" [ngClass]=\"{'col1': i % 2 == 0, 'col2': i % 2 == 1 }\"></app-fab-input>\r\n </ng-container>\r\n </ng-container>\r\n </div>\r\n\r\n <ng-container *ngIf=\"ShowAffectsOnlyBestek()\">\r\n <div class=\"affects-only-bestek\">\r\n <span><sup>1</sup></span>\r\n {{ TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.AffectsOnlyBestek) }}\r\n </div>\r\n </ng-container>\r\n </ng-container>\r\n\r\n <div *ngIf=\"ShowCategories()\">\r\n @if (ShowAccordion()) {\r\n <mat-accordion [multi]=\"false\">\r\n <mat-expansion-panel *ngFor=\"let cat of FabrikantenService.FabrikantenViewModel.filterCategories; let index = index\"\r\n [expanded]=\"index === 0\"\r\n [class.completed-step]=\"cat.completed\">\r\n <mat-expansion-panel-header [attr.aria-label]=\"GetHeaderAriaLabel(cat)\">\r\n <mat-panel-title>\r\n <div class=\"step-name-div\">\r\n <div class=\"accordion-step-number\">\r\n {{ index + 1 }}\r\n </div>\r\n\r\n <div class=\"step-name-name\">\r\n {{ TranslateService.GetActiveValue(TranslationCategory.FilterCategory, TranslationSubCategory.Name, cat.id) }}\r\n </div>\r\n\r\n <div class=\"step-name-icon\"\r\n *ngIf=\"cat.icon != null\">\r\n <span class=\"helper\"></span>\r\n\r\n <img [src]=\"cat.icon\"\r\n class=\"filter-category-icon\"\r\n alt=\"\" />\r\n </div>\r\n </div>\r\n </mat-panel-title>\r\n </mat-expansion-panel-header>\r\n\r\n <ng-container *ngFor=\"let inputviewmodel of cat.inputs\">\r\n <app-fab-input [input]=\"inputviewmodel\"></app-fab-input>\r\n </ng-container>\r\n </mat-expansion-panel>\r\n </mat-accordion>\r\n } @else {\r\n <mat-stepper orientation=\"vertical\" [linear]=\"true\" #stepper>\r\n <ng-template matStepperIcon=\"edit\" let-index=\"index\">\r\n {{ index + 1 }}\r\n </ng-template>\r\n\r\n <mat-step *ngFor=\"let cat of FabrikantenService.FabrikantenViewModel.filterCategories\" state=\"{{ cat.id }}\" [completed]=\"cat.completed\" [aria-labelledby]=\"GetHeaderAriaLabel(cat)\" [class.completed-step]=\"cat.completed\">\r\n <ng-template matStepLabel>\r\n <div class=\"step-name-div\">\r\n <div class=\"step-name-completed\" *ngIf=\"cat.completed\">\r\n <mat-icon class=\"step-name-completed-icon\">done</mat-icon>\r\n </div>\r\n <div class=\"step-name-name\">\r\n {{ TranslateService.GetActiveValue(TranslationCategory.FilterCategory, TranslationSubCategory.Name, cat.id) }}\r\n </div>\r\n <div class=\"step-name-icon\" *ngIf=\"cat.icon != null\">\r\n <span class=\"helper\"></span>\r\n <img [src]=\"cat.icon\" class=\"filter-category-icon\" />\r\n </div>\r\n </div>\r\n </ng-template>\r\n\r\n <ng-container *ngFor=\"let inputviewmodel of cat.inputs\">\r\n <app-fab-input [input]=\"inputviewmodel\"></app-fab-input>\r\n </ng-container>\r\n </mat-step>\r\n </mat-stepper>\r\n }\r\n </div>\r\n</div>\r\n", styles: ["fab-filters-input .mat-step-header{cursor:pointer!important}fab-filters-input .filter-view-header-h1{display:flex}fab-filters-input .h1-auto{flex:auto}fab-filters-input .two-columns{display:flex;flex-wrap:wrap}fab-filters-input .mat-step-header[aria-labelledby=disabled_af]{cursor:not-allowed!important;opacity:.6}fab-filters-input .mat-step-header[aria-labelledby=enabled] .mat-step-icon{background-color:#000}fab-filters-input .mat-step-header[aria-labelledby=enabled] .mat-step-icon-selected{background-color:#3f51b5}fab-filters-input .filter-view-header{display:flex}fab-filters-input .filter-view-header-h1{flex:auto;text-transform:capitalize}fab-filters-input .step-name-icon{height:54px;white-space:nowrap;text-align:center;margin:auto 0}fab-filters-input .step-name-completed{height:54px;display:flex;align-items:center}fab-filters-input .step-name-div{width:100%}fab-filters-input .filter-category-icon{height:48px;vertical-align:middle}fab-filters-input .mat-step-text-label{width:100%}fab-filters-input .mat-step-label{width:100%}fab-filters-input .step-name-name{line-height:56px}fab-filters-input .helper{display:inline-block;height:100%;vertical-align:middle}fab-filters-input .filter-view-margin{padding:10px}fab-filters-input .filter-view-header-reset{cursor:pointer}fab-filters-input .mat-vertical-content-container{padding-top:10px}fab-filters-input .mat-vertical-content{padding:0}fab-filters-input .step-name-div{display:flex}fab-filters-input .step-name-name{flex:auto}fab-filters-input .save-conf-div{padding:15px}fab-filters-input .save-conf-div mat-spinner{margin:auto}fab-filters-input .accordion-step-number{display:flex;align-items:center;justify-content:center;width:28px;height:28px;flex-shrink:0;border-radius:50%;background:var(--mat-sys-primary);color:var(--mat-sys-on-primary);font-weight:500;line-height:56px;height:56px}\n"], dependencies: [{ kind: "directive", type: i4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3$1.MatAccordion, selector: "mat-accordion", inputs: ["hideToggle", "displayMode", "togglePosition"], exportAs: ["matAccordion"] }, { kind: "component", type: i3$1.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i3$1.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i3$1.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "component", type: i8$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i9$2.MatStep, selector: "mat-step", inputs: ["color"], exportAs: ["matStep"] }, { kind: "directive", type: i9$2.MatStepLabel, selector: "[matStepLabel]" }, { kind: "component", type: i9$2.MatStepper, selector: "mat-stepper, mat-vertical-stepper, mat-horizontal-stepper, [matStepper]", inputs: ["disableRipple", "color", "labelPosition", "headerPosition", "aria-label", "headerPrefix", "animationDuration"], outputs: ["animationDone"], exportAs: ["matStepper", "matVerticalStepper", "matHorizontalStepper"] }, { kind: "directive", type: i9$2.MatStepperIcon, selector: "ng-template[matStepperIcon]", inputs: ["matStepperIcon"] }, { kind: "component", type: FabInputCodeComponent, selector: "app-fab-input-code" }, { kind: "component", type: FabInputComponent, selector: "app-fab-input", inputs: ["input"] }], encapsulation: i0.ViewEncapsulation.None });
28833
28860
  }
28834
28861
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: FabFiltersInputComponent, decorators: [{
28835
28862
  type: Component,
28836
- args: [{ selector: 'fab-filters-input', standalone: false, encapsulation: ViewEncapsulation.None, template: "<div class=\"filter-view-margin\">\r\n <div class=\"filter-view-header\">\r\n <ng-container *ngIf=\"ShowInputCode()\">\r\n <div>\r\n <div class=\"filter-view-header-h1\">\r\n <h1 class=\"h1-auto\">{{ GetHeaderName() }}</h1>\r\n <div class=\"filter-view-header-reset\" (click)=\"ResetAllFilters()\">\r\n {{ TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.ResetFilters) }}\r\n </div>\r\n </div>\r\n <div>\r\n <app-fab-input-code></app-fab-input-code>\r\n </div>\r\n </div>\r\n </ng-container>\r\n <ng-container *ngIf=\"!ShowInputCode()\">\r\n <div class=\"filter-view-header-h1\">\r\n <h1>{{ GetHeaderName() }}</h1>\r\n </div>\r\n <div class=\"filter-view-header-reset\" (click)=\"ResetAllFilters()\">\r\n {{ TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.ResetFilters) }}\r\n </div>\r\n </ng-container>\r\n </div>\r\n\r\n <ng-container *ngIf=\"!ShowCategories()\">\r\n <div class=\"inputs-container\" [ngClass]=\"{'two-columns': ShowTwoColumns() }\">\r\n <ng-container *ngFor=\"let inputviewmodel of FabrikantenService.FabrikantenViewModel.inputs; index as i\">\r\n <ng-container *ngIf=\"!inputviewmodel.extra || displayExtra\">\r\n <app-fab-input [input]=\"inputviewmodel\" [ngClass]=\"{'col1': i % 2 == 0, 'col2': i % 2 == 1 }\"></app-fab-input>\r\n </ng-container>\r\n </ng-container>\r\n </div>\r\n\r\n <ng-container *ngIf=\"ShowAffectsOnlyBestek()\">\r\n <div class=\"affects-only-bestek\">\r\n <span><sup>1</sup></span>\r\n {{ TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.AffectsOnlyBestek) }}\r\n </div>\r\n </ng-container>\r\n </ng-container>\r\n\r\n <div *ngIf=\"ShowCategories()\">\r\n <mat-stepper orientation=\"vertical\" [linear]=\"true\" #stepper>\r\n <ng-template matStepperIcon=\"edit\" let-index=\"index\">\r\n {{ index + 1 }}\r\n </ng-template>\r\n\r\n <mat-step *ngFor=\"let cat of FabrikantenService.FabrikantenViewModel.filterCategories\" state=\"{{ cat.id }}\" [completed]=\"cat.completed\" [aria-labelledby]=\"GetHeaderAriaLabel(cat)\" [class.completed-step]=\"cat.completed\">\r\n <ng-template matStepLabel>\r\n <div class=\"step-name-div\">\r\n <div class=\"step-name-completed\" *ngIf=\"cat.completed\">\r\n <mat-icon class=\"step-name-completed-icon\">done</mat-icon>\r\n </div>\r\n <div class=\"step-name-name\">\r\n {{ TranslateService.GetActiveValue(TranslationCategory.FilterCategory, TranslationSubCategory.Name, cat.id) }}\r\n </div>\r\n <div class=\"step-name-icon\" *ngIf=\"cat.icon != null\">\r\n <span class=\"helper\"></span>\r\n <img [src]=\"cat.icon\" class=\"filter-category-icon\" />\r\n </div>\r\n </div>\r\n </ng-template>\r\n\r\n <ng-container *ngFor=\"let inputviewmodel of cat.inputs\">\r\n <app-fab-input [input]=\"inputviewmodel\"></app-fab-input>\r\n </ng-container>\r\n </mat-step>\r\n </mat-stepper>\r\n </div>\r\n</div>\r\n", styles: ["fab-filters-input .mat-step-header{cursor:pointer!important}fab-filters-input .filter-view-header-h1{display:flex}fab-filters-input .h1-auto{flex:auto}fab-filters-input .two-columns{display:flex;flex-wrap:wrap}fab-filters-input .mat-step-header[aria-labelledby=disabled_af]{cursor:not-allowed!important;opacity:.6}fab-filters-input .mat-step-header[aria-labelledby=enabled] .mat-step-icon{background-color:#000}fab-filters-input .mat-step-header[aria-labelledby=enabled] .mat-step-icon-selected{background-color:#3f51b5}fab-filters-input .filter-view-header{display:flex}fab-filters-input .filter-view-header-h1{flex:auto;text-transform:capitalize}fab-filters-input .step-name-icon{height:54px;white-space:nowrap;text-align:center;margin:auto 0}fab-filters-input .step-name-completed{height:54px;display:flex;align-items:center}fab-filters-input .step-name-div{width:100%}fab-filters-input .filter-category-icon{height:48px;vertical-align:middle}fab-filters-input .mat-step-text-label{width:100%}fab-filters-input .mat-step-label{width:100%}fab-filters-input .step-name-name{line-height:56px}fab-filters-input .helper{display:inline-block;height:100%;vertical-align:middle}fab-filters-input .filter-view-margin{padding:10px}fab-filters-input .filter-view-header-reset{cursor:pointer}fab-filters-input .mat-vertical-content-container{padding-top:10px}fab-filters-input .mat-vertical-content{padding:0}fab-filters-input .step-name-div{display:flex}fab-filters-input .step-name-name{flex:auto}fab-filters-input .save-conf-div{padding:15px}fab-filters-input .save-conf-div mat-spinner{margin:auto}\n"] }]
28863
+ args: [{ selector: 'fab-filters-input', standalone: false, encapsulation: ViewEncapsulation.None, template: "<div class=\"filter-view-margin\">\r\n <div class=\"filter-view-header\">\r\n <ng-container *ngIf=\"ShowInputCode()\">\r\n <div>\r\n <div class=\"filter-view-header-h1\">\r\n <h1 class=\"h1-auto\">{{ GetHeaderName() }}</h1>\r\n <div class=\"filter-view-header-reset\" (click)=\"ResetAllFilters()\">\r\n {{ TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.ResetFilters) }}\r\n </div>\r\n </div>\r\n <div>\r\n <app-fab-input-code></app-fab-input-code>\r\n </div>\r\n </div>\r\n </ng-container>\r\n <ng-container *ngIf=\"!ShowInputCode()\">\r\n <div class=\"filter-view-header-h1\">\r\n <h1>{{ GetHeaderName() }}</h1>\r\n </div>\r\n <div class=\"filter-view-header-reset\" (click)=\"ResetAllFilters()\">\r\n {{ TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.ResetFilters) }}\r\n </div>\r\n </ng-container>\r\n </div>\r\n\r\n <ng-container *ngIf=\"!ShowCategories()\">\r\n <div class=\"inputs-container\" [ngClass]=\"{'two-columns': ShowTwoColumns() }\">\r\n <ng-container *ngFor=\"let inputviewmodel of FabrikantenService.FabrikantenViewModel.inputs; index as i\">\r\n <ng-container *ngIf=\"!inputviewmodel.extra || displayExtra\">\r\n <app-fab-input [input]=\"inputviewmodel\" [ngClass]=\"{'col1': i % 2 == 0, 'col2': i % 2 == 1 }\"></app-fab-input>\r\n </ng-container>\r\n </ng-container>\r\n </div>\r\n\r\n <ng-container *ngIf=\"ShowAffectsOnlyBestek()\">\r\n <div class=\"affects-only-bestek\">\r\n <span><sup>1</sup></span>\r\n {{ TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.AffectsOnlyBestek) }}\r\n </div>\r\n </ng-container>\r\n </ng-container>\r\n\r\n <div *ngIf=\"ShowCategories()\">\r\n @if (ShowAccordion()) {\r\n <mat-accordion [multi]=\"false\">\r\n <mat-expansion-panel *ngFor=\"let cat of FabrikantenService.FabrikantenViewModel.filterCategories; let index = index\"\r\n [expanded]=\"index === 0\"\r\n [class.completed-step]=\"cat.completed\">\r\n <mat-expansion-panel-header [attr.aria-label]=\"GetHeaderAriaLabel(cat)\">\r\n <mat-panel-title>\r\n <div class=\"step-name-div\">\r\n <div class=\"accordion-step-number\">\r\n {{ index + 1 }}\r\n </div>\r\n\r\n <div class=\"step-name-name\">\r\n {{ TranslateService.GetActiveValue(TranslationCategory.FilterCategory, TranslationSubCategory.Name, cat.id) }}\r\n </div>\r\n\r\n <div class=\"step-name-icon\"\r\n *ngIf=\"cat.icon != null\">\r\n <span class=\"helper\"></span>\r\n\r\n <img [src]=\"cat.icon\"\r\n class=\"filter-category-icon\"\r\n alt=\"\" />\r\n </div>\r\n </div>\r\n </mat-panel-title>\r\n </mat-expansion-panel-header>\r\n\r\n <ng-container *ngFor=\"let inputviewmodel of cat.inputs\">\r\n <app-fab-input [input]=\"inputviewmodel\"></app-fab-input>\r\n </ng-container>\r\n </mat-expansion-panel>\r\n </mat-accordion>\r\n } @else {\r\n <mat-stepper orientation=\"vertical\" [linear]=\"true\" #stepper>\r\n <ng-template matStepperIcon=\"edit\" let-index=\"index\">\r\n {{ index + 1 }}\r\n </ng-template>\r\n\r\n <mat-step *ngFor=\"let cat of FabrikantenService.FabrikantenViewModel.filterCategories\" state=\"{{ cat.id }}\" [completed]=\"cat.completed\" [aria-labelledby]=\"GetHeaderAriaLabel(cat)\" [class.completed-step]=\"cat.completed\">\r\n <ng-template matStepLabel>\r\n <div class=\"step-name-div\">\r\n <div class=\"step-name-completed\" *ngIf=\"cat.completed\">\r\n <mat-icon class=\"step-name-completed-icon\">done</mat-icon>\r\n </div>\r\n <div class=\"step-name-name\">\r\n {{ TranslateService.GetActiveValue(TranslationCategory.FilterCategory, TranslationSubCategory.Name, cat.id) }}\r\n </div>\r\n <div class=\"step-name-icon\" *ngIf=\"cat.icon != null\">\r\n <span class=\"helper\"></span>\r\n <img [src]=\"cat.icon\" class=\"filter-category-icon\" />\r\n </div>\r\n </div>\r\n </ng-template>\r\n\r\n <ng-container *ngFor=\"let inputviewmodel of cat.inputs\">\r\n <app-fab-input [input]=\"inputviewmodel\"></app-fab-input>\r\n </ng-container>\r\n </mat-step>\r\n </mat-stepper>\r\n }\r\n </div>\r\n</div>\r\n", styles: ["fab-filters-input .mat-step-header{cursor:pointer!important}fab-filters-input .filter-view-header-h1{display:flex}fab-filters-input .h1-auto{flex:auto}fab-filters-input .two-columns{display:flex;flex-wrap:wrap}fab-filters-input .mat-step-header[aria-labelledby=disabled_af]{cursor:not-allowed!important;opacity:.6}fab-filters-input .mat-step-header[aria-labelledby=enabled] .mat-step-icon{background-color:#000}fab-filters-input .mat-step-header[aria-labelledby=enabled] .mat-step-icon-selected{background-color:#3f51b5}fab-filters-input .filter-view-header{display:flex}fab-filters-input .filter-view-header-h1{flex:auto;text-transform:capitalize}fab-filters-input .step-name-icon{height:54px;white-space:nowrap;text-align:center;margin:auto 0}fab-filters-input .step-name-completed{height:54px;display:flex;align-items:center}fab-filters-input .step-name-div{width:100%}fab-filters-input .filter-category-icon{height:48px;vertical-align:middle}fab-filters-input .mat-step-text-label{width:100%}fab-filters-input .mat-step-label{width:100%}fab-filters-input .step-name-name{line-height:56px}fab-filters-input .helper{display:inline-block;height:100%;vertical-align:middle}fab-filters-input .filter-view-margin{padding:10px}fab-filters-input .filter-view-header-reset{cursor:pointer}fab-filters-input .mat-vertical-content-container{padding-top:10px}fab-filters-input .mat-vertical-content{padding:0}fab-filters-input .step-name-div{display:flex}fab-filters-input .step-name-name{flex:auto}fab-filters-input .save-conf-div{padding:15px}fab-filters-input .save-conf-div mat-spinner{margin:auto}fab-filters-input .accordion-step-number{display:flex;align-items:center;justify-content:center;width:28px;height:28px;flex-shrink:0;border-radius:50%;background:var(--mat-sys-primary);color:var(--mat-sys-on-primary);font-weight:500;line-height:56px;height:56px}\n"] }]
28837
28864
  }], ctorParameters: () => [{ type: i3.Router }, { type: FabrikantenService }, { type: TranslateService }, { type: FabrikantenApiClient }, { type: ConfiguratorApiClient }, { type: AuthenticationService }, { type: i0.ChangeDetectorRef }], propDecorators: { displayExtra: [{
28838
28865
  type: Input
28839
28866
  }] } });
@@ -29490,965 +29517,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImpo
29490
29517
  args: ['viewercontainertoebehoren']
29491
29518
  }] } });
29492
29519
 
29493
- /**
29494
- * three.js renderer inspector (scene graph / render debugging), toggled from the
29495
- * settings panel. Adapted from the digihuis threejs-viewer InspectorComponent.
29496
- */
29497
- class InspectorComponent extends ActorComponent {
29498
- enabled = false;
29499
- inspector;
29500
- constructor(owner, autoActivate = true) {
29501
- super(owner, autoActivate);
29502
- }
29503
- toggle() {
29504
- const renderer = this.getWorld().getRenderer();
29505
- if (this.enabled) {
29506
- this.inspector.domElement.remove();
29507
- renderer.inspector = new InspectorBase();
29508
- this.inspector = undefined;
29509
- this.enabled = false;
29510
- }
29511
- else {
29512
- this.inspector = new Inspector();
29513
- renderer.inspector = this.inspector;
29514
- this.inspector.init();
29515
- this.enabled = true;
29516
- }
29517
- }
29518
- destroyComponent() {
29519
- if (this.enabled) {
29520
- this.toggle();
29521
- }
29522
- super.destroyComponent();
29523
- }
29524
- }
29525
-
29526
- /**
29527
- * Performance stats overlay (FPS panel), toggled from the settings panel.
29528
- * Adapted from the digihuis threejs-viewer StatsComponent.
29529
- */
29530
- class StatsComponent extends ActorComponent {
29531
- stats;
29532
- visible = false;
29533
- onPreRenderSubscription;
29534
- onPostRenderSubscription;
29535
- f2Handler;
29536
- constructor(owner, autoActivate = true, useF2Toggle = false) {
29537
- super(owner, autoActivate);
29538
- this.createStatsComponent();
29539
- this.onPreRenderSubscription = this.getWorld().onPreRenderObservable.subscribe(() => {
29540
- this.stats.begin();
29541
- });
29542
- this.onPostRenderSubscription = this.getWorld().onPostRenderObservable.subscribe(() => {
29543
- this.stats.end();
29544
- });
29545
- if (useF2Toggle) {
29546
- this.f2Handler = (e) => {
29547
- if (e.code === 'F2') {
29548
- e.preventDefault();
29549
- this.toggleVisiblity();
29550
- }
29551
- };
29552
- window.addEventListener('keydown', this.f2Handler);
29553
- }
29554
- }
29555
- toggleVisiblity() {
29556
- this.visible = !this.visible;
29557
- this.stats.dom.style.display = this.visible ? 'block' : 'none';
29558
- }
29559
- createStatsComponent() {
29560
- this.stats = new Stats();
29561
- this.stats.showPanel(0); // 0 = fps, 1 = ms, 2 = memory
29562
- this.stats.dom.style.position = 'absolute';
29563
- this.stats.dom.style.top = '10px';
29564
- this.stats.dom.style.left = '10px';
29565
- this.stats.dom.style.zIndex = '1000';
29566
- this.stats.dom.style.display = 'none';
29567
- this.getWorld().getEngineWrapper().appendChild(this.stats.dom);
29568
- }
29569
- destroyComponent() {
29570
- this.stats.dom.parentElement?.removeChild(this.stats.dom);
29571
- this.onPreRenderSubscription?.unsubscribe();
29572
- this.onPostRenderSubscription?.unsubscribe();
29573
- if (this.f2Handler) {
29574
- window.removeEventListener('keydown', this.f2Handler);
29575
- this.f2Handler = undefined;
29576
- }
29577
- super.destroyComponent();
29578
- }
29579
- }
29580
-
29581
- /**
29582
- * Player controller for the Fabrikanten 3D product viewer.
29583
- *
29584
- * Adds the engine's settings panel (top-right) with: graphics quality presets,
29585
- * a performance stats toggle and a renderer inspector toggle. Adapted from the
29586
- * digihuis ViewerController, without storeys dropdown, XR toolbar and input actions.
29587
- */
29588
- class FabThreeViewerController extends PlayerController {
29589
- settingsPanelComponentRef;
29590
- constructor() {
29591
- super();
29592
- this.name = 'Fab Viewer Controller';
29593
- }
29594
- start() {
29595
- super.start();
29596
- this.addSettingsPanel();
29597
- this.addGraphicPresetsSetting();
29598
- this.addStatsSetting();
29599
- this.addInspectorSetting();
29600
- }
29601
- addSettingsPanel() {
29602
- const appRef = InjectorService.get(ApplicationRef);
29603
- const environmentInjector = InjectorService.get(EnvironmentInjector);
29604
- const compRef = createComponent(SettingsPanelComponent, {
29605
- environmentInjector: appRef.injector,
29606
- elementInjector: environmentInjector,
29607
- bindings: []
29608
- });
29609
- this.settingsPanelComponentRef = compRef;
29610
- const host = compRef.location.nativeElement;
29611
- host.style.position = 'absolute';
29612
- host.style.top = '10px';
29613
- host.style.right = '10px';
29614
- this.getWorld().getEngineWrapper().appendChild(host);
29615
- appRef.attachView(compRef.hostView);
29616
- compRef.changeDetectorRef.detectChanges();
29617
- }
29618
- addGraphicPresetsSetting() {
29619
- const settingsService = InjectorService.get(SettingsService);
29620
- const graphicPresetsSetting = {
29621
- displayName: 'Grafische kwaliteit',
29622
- category: undefined,
29623
- settingType: {
29624
- selectedOptionValue: localStorage.getItem(VIEWER_GRAPHICS_PRESET_LOCALSTORAGE_KEY),
29625
- optionChanged: (option) => {
29626
- localStorage.setItem(VIEWER_GRAPHICS_PRESET_LOCALSTORAGE_KEY, option.value);
29627
- void this.getWorld().restart();
29628
- },
29629
- options: [
29630
- {
29631
- displayName: 'Laag',
29632
- value: 'low'
29633
- },
29634
- {
29635
- displayName: 'Middel',
29636
- value: 'mid'
29637
- },
29638
- {
29639
- displayName: 'Hoog',
29640
- value: 'high'
29641
- }
29642
- ]
29643
- }
29644
- };
29645
- settingsService.addSetting(graphicPresetsSetting);
29646
- }
29647
- addStatsSetting() {
29648
- const statsComponent = new StatsComponent(this, true, false);
29649
- const settingsService = InjectorService.get(SettingsService);
29650
- const fpsSetting = {
29651
- displayName: 'Toon prestatiespaneel',
29652
- category: undefined,
29653
- settingType: {
29654
- checked: false,
29655
- checkedChanged: (checked) => {
29656
- fpsSetting.settingType.checked = checked;
29657
- statsComponent.toggleVisiblity();
29658
- }
29659
- }
29660
- };
29661
- settingsService.addSetting(fpsSetting);
29662
- }
29663
- addInspectorSetting() {
29664
- const inspectorComponent = new InspectorComponent(this);
29665
- const settingsService = InjectorService.get(SettingsService);
29666
- const inspectorSetting = {
29667
- displayName: 'Toon inspector',
29668
- category: undefined,
29669
- settingType: {
29670
- checked: false,
29671
- checkedChanged: (checked) => {
29672
- inspectorSetting.settingType.checked = checked;
29673
- inspectorComponent.toggle();
29674
- }
29675
- }
29676
- };
29677
- settingsService.addSetting(inspectorSetting);
29678
- }
29679
- destroy() {
29680
- if (this.settingsPanelComponentRef) {
29681
- const host = this.settingsPanelComponentRef.location.nativeElement;
29682
- host.parentElement?.removeChild(host);
29683
- this.settingsPanelComponentRef.destroy();
29684
- this.settingsPanelComponentRef = undefined;
29685
- }
29686
- super.destroy();
29687
- }
29688
- }
29689
-
29690
- /**
29691
- * Type definitions for the legacy HDH WebGL JSON format, as produced by the server
29692
- * in Fabrikanten3DViewModel.webGLJSON.
29693
- *
29694
- * Adapted from the digihuis/WoonConnect threejs-viewer module
29695
- * (src/app/modules/threejs/include/LegacyFragment.ts).
29696
- */
29697
- /** Number of floats per vertex for each vertex data layout. */
29698
- var LegacyVertexDataLayout;
29699
- (function (LegacyVertexDataLayout) {
29700
- LegacyVertexDataLayout[LegacyVertexDataLayout["Position"] = 3] = "Position";
29701
- LegacyVertexDataLayout[LegacyVertexDataLayout["PositionUv"] = 5] = "PositionUv";
29702
- LegacyVertexDataLayout[LegacyVertexDataLayout["PositionNormal"] = 6] = "PositionNormal";
29703
- LegacyVertexDataLayout[LegacyVertexDataLayout["PositionNormalUv"] = 8] = "PositionNormalUv";
29704
- LegacyVertexDataLayout[LegacyVertexDataLayout["PositionNormalUvTangent"] = 11] = "PositionNormalUvTangent";
29705
- })(LegacyVertexDataLayout || (LegacyVertexDataLayout = {}));
29706
-
29707
- /**
29708
- * Converts the legacy HDH WebGL JSON (Fabrikanten3DViewModel.webGLJSON) into a three.js
29709
- * scene graph. View-only: builds geometry, materials and textures; no selection logic.
29710
- *
29711
- * Conversion logic is adapted from the digihuis/WoonConnect HdhToThreejsConverter
29712
- * (threejs-viewer/hdhToThree), with the server fragment-fetch pipeline removed:
29713
- * FabrikantenCore already has the complete model as a single JSON string.
29714
- */
29715
- class FabWebglJsonConverter extends Actor {
29716
- /**
29717
- * HDH (Z-up) to three.js (Y-up) axis conversion (column-major):
29718
- * threeX = hdhX, threeY = hdhZ, threeZ = -hdhY.
29719
- */
29720
- hdhToThree = new Matrix4().fromArray([
29721
- 1, 0, 0, 0, // column 0
29722
- 0, 0, -1, 0, // column 1 (hdh Y -> -three Z)
29723
- 0, 1, 0, 0, // column 2 (hdh Z -> three Y)
29724
- 0, 0, 0, 1
29725
- ]);
29726
- /** Shared glass material, provided by the world (see FabThreeViewerWorld). */
29727
- glassMaterial = null;
29728
- modelRoot;
29729
- /** Texture cache, keyed by texture path. Kept across model rebuilds. */
29730
- textures = new Map();
29731
- /** Texture paths that failed to load; do not retry, fall back to flat colors. */
29732
- failedTextures = new Set();
29733
- /** Material cache for the currently loaded model. Disposed on rebuild. */
29734
- materialCache = new Map();
29735
- pendingJson;
29736
- inflightJson;
29737
- lastLoadedJson;
29738
- isActorStarted = false;
29739
- /** Incremented on every load; async loads abort when a newer one started. */
29740
- loadGeneration = 0;
29741
- onModelLoadedSubject = new Subject();
29742
- /** Emits the world-space bounding box of the model after each (re)build. */
29743
- onModelLoaded$ = this.onModelLoadedSubject.asObservable();
29744
- constructor() {
29745
- super();
29746
- this.name = 'Fab WebGL JSON converter';
29747
- this.matrixAutoUpdate = false;
29748
- }
29749
- start() {
29750
- super.start();
29751
- this.isActorStarted = true;
29752
- void this.processPending();
29753
- }
29754
- /** Sets the shared glass material used for transparent items. */
29755
- setGlassMaterial(material) {
29756
- this.glassMaterial = material;
29757
- }
29758
- /**
29759
- * Queues a webGLJSON model for loading. Safe to call repeatedly: identical JSON is
29760
- * ignored, and a newer call supersedes any load still in progress.
29761
- */
29762
- queueModel(webGLJSON) {
29763
- if (webGLJSON === this.lastLoadedJson && this.modelRoot !== undefined && this.pendingJson === undefined) {
29764
- return;
29765
- }
29766
- // The same model is already being built: don't restart the build.
29767
- if (webGLJSON === this.inflightJson) {
29768
- return;
29769
- }
29770
- this.pendingJson = webGLJSON;
29771
- void this.processPending();
29772
- }
29773
- async processPending() {
29774
- if (!this.isActorStarted || !this.hasWorld() || this.pendingJson === undefined) {
29775
- return;
29776
- }
29777
- const json = this.pendingJson;
29778
- this.pendingJson = undefined;
29779
- const generation = ++this.loadGeneration;
29780
- this.inflightJson = json;
29781
- try {
29782
- await this.buildModel(json, generation);
29783
- }
29784
- catch (error) {
29785
- console.error('FabWebglJsonConverter: failed to build model from webGLJSON.', error);
29786
- }
29787
- finally {
29788
- if (this.inflightJson === json) {
29789
- this.inflightJson = undefined;
29790
- }
29791
- }
29792
- }
29793
- async buildModel(json, generation) {
29794
- const parsed = JSON.parse(json);
29795
- // Defensive: accept both a single fragment object and an array of fragments.
29796
- const fragments = (Array.isArray(parsed) ? parsed : [parsed]);
29797
- // Load all referenced textures up front (cached across rebuilds).
29798
- const textureNames = new Set();
29799
- for (const fragment of fragments) {
29800
- fragment?.texNamen?.forEach((name) => textureNames.add(name));
29801
- }
29802
- await this.loadTextures([...textureNames]);
29803
- // A newer load superseded this one while textures were loading.
29804
- if (generation !== this.loadGeneration) {
29805
- return;
29806
- }
29807
- this.removeModel();
29808
- const root = new Group();
29809
- root.name = 'FabWebglModel';
29810
- root.matrixAutoUpdate = false;
29811
- for (const fragment of fragments) {
29812
- if (fragment == null || fragment.itemsOpaak == null) {
29813
- console.warn('FabWebglJsonConverter: skipping fragment without itemsOpaak.', fragment);
29814
- continue;
29815
- }
29816
- this.addLegacyFragment(root, fragment);
29817
- }
29818
- this.modelRoot = root;
29819
- this.add(root);
29820
- this.lastLoadedJson = json;
29821
- root.updateMatrixWorld(true);
29822
- const boundingBox = new Box3().setFromObject(root);
29823
- this.getWorld().onSceneChanged.next();
29824
- this.onModelLoadedSubject.next(boundingBox);
29825
- }
29826
- async loadTextures(textureNames) {
29827
- const loader = new TextureLoader();
29828
- const toLoad = textureNames.filter(name => !this.textures.has(name) && !this.failedTextures.has(name));
29829
- await Promise.all(toLoad.map(async (name) => {
29830
- try {
29831
- // The legacy viewer assigns the texture path directly to Image.src,
29832
- // so relative paths resolve against the document base. TextureLoader does the same.
29833
- const texture = await loader.loadAsync(name);
29834
- texture.wrapS = RepeatWrapping;
29835
- texture.wrapT = RepeatWrapping;
29836
- texture.minFilter = LinearMipMapLinearFilter;
29837
- texture.magFilter = LinearFilter;
29838
- texture.anisotropy = GraphicsScalabilityConfigsManager.activeGraphicsScalabilityConfig.textureAnisotropy;
29839
- this.textures.set(name, texture);
29840
- }
29841
- catch (error) {
29842
- this.failedTextures.add(name);
29843
- console.warn(`FabWebglJsonConverter: failed to load texture "${name}", falling back to flat color.`, error);
29844
- }
29845
- }));
29846
- }
29847
- addLegacyFragment(root, fragment) {
29848
- const instanceMatrices = this.fragmentTransformations(fragment);
29849
- const texturePaths = fragment.texNamen ?? [];
29850
- instanceMatrices.forEach((instanceMatrix) => {
29851
- const fragmentGroup = new Group();
29852
- fragmentGroup.name = `Fragment ${fragment.ID}`;
29853
- fragmentGroup.matrixAutoUpdate = false;
29854
- fragmentGroup.matrix.copy(instanceMatrix);
29855
- fragment.itemsOpaak?.forEach((item) => {
29856
- this.addLegacyFragmentItem(fragment, item, texturePaths, false, fragmentGroup);
29857
- });
29858
- fragment.itemsTransparant?.forEach((item) => {
29859
- this.addLegacyFragmentItem(fragment, item, texturePaths, true, fragmentGroup);
29860
- });
29861
- root.add(fragmentGroup);
29862
- });
29863
- }
29864
- /** Returns the instance matrices for a fragment, converted from HDH to three.js space. */
29865
- fragmentTransformations(fragment) {
29866
- const matrices = [];
29867
- if (fragment.transLijst && fragment.transLijst.aantal > 0 && fragment.transLijst.transMats?.length) {
29868
- for (const raw of fragment.transLijst.transMats) {
29869
- const parsed = this.parseHdhMatrix(raw);
29870
- matrices.push(new Matrix4().multiplyMatrices(this.hdhToThree, parsed));
29871
- }
29872
- }
29873
- else {
29874
- // No transformation list: apply only the axis conversion; geometry is scaled on the mesh.
29875
- matrices.push(new Matrix4().copy(this.hdhToThree));
29876
- }
29877
- return matrices;
29878
- }
29879
- /** Parses an HDH 4x4 matrix (detects row-major layout) and converts translation mm -> m. */
29880
- parseHdhMatrix(raw) {
29881
- const arr = raw.slice();
29882
- const looksRowMajor = (Math.abs(arr[3]) > 1e-6 || Math.abs(arr[7]) > 1e-6 || Math.abs(arr[11]) > 1e-6) &&
29883
- arr[12] === 0 && arr[13] === 0 && arr[14] === 0;
29884
- const matrix = new Matrix4().fromArray(arr);
29885
- if (looksRowMajor) {
29886
- matrix.transpose();
29887
- }
29888
- // mm -> m: only the translation; the geometry itself is scaled on the mesh.
29889
- matrix.elements[12] /= 1000;
29890
- matrix.elements[13] /= 1000;
29891
- matrix.elements[14] /= 1000;
29892
- return matrix;
29893
- }
29894
- itemLayout(item) {
29895
- if (item.type === 2) {
29896
- return (item.tableau != null || item.bumpmap != null)
29897
- ? LegacyVertexDataLayout.PositionUv
29898
- : LegacyVertexDataLayout.Position;
29899
- }
29900
- if (item.type === 3) {
29901
- if (item.bumpmap != null) {
29902
- return LegacyVertexDataLayout.PositionNormalUvTangent;
29903
- }
29904
- return (item.tableau != null)
29905
- ? LegacyVertexDataLayout.PositionNormalUv
29906
- : LegacyVertexDataLayout.PositionNormal;
29907
- }
29908
- return undefined;
29909
- }
29910
- addLegacyFragmentItem(fragment, item, texturePaths, isTransparent, parent) {
29911
- // Points (0) and lines (1) are not rendered in 3D.
29912
- if (item.type === 0 || item.type === 1) {
29913
- return;
29914
- }
29915
- const layout = this.itemLayout(item);
29916
- if (layout === undefined || item.vertexData == null || item.vertexData.length === 0) {
29917
- return;
29918
- }
29919
- const material = this.resolveMaterial(fragment, item, texturePaths, isTransparent);
29920
- if (material === null) {
29921
- // Opacity-0 "air" items (e.g. cavities) are present in the geometry but irrelevant for rendering.
29922
- return;
29923
- }
29924
- const geometry = this.buildGeometry(item, layout);
29925
- if (geometry === null) {
29926
- return;
29927
- }
29928
- const mesh = new Mesh(geometry, material);
29929
- if (material === this.glassMaterial) {
29930
- // Glass neither casts nor receives shadows.
29931
- mesh.castShadow = false;
29932
- mesh.receiveShadow = false;
29933
- }
29934
- else {
29935
- mesh.castShadow = GraphicsScalabilityConfigsManager.activeGraphicsScalabilityConfig.enableCastShadows;
29936
- mesh.receiveShadow = GraphicsScalabilityConfigsManager.activeGraphicsScalabilityConfig.enableReceiveShadows;
29937
- }
29938
- // Geometry coordinates are in mm; the instance matrix translation is already in m.
29939
- mesh.scale.multiplyScalar(0.001);
29940
- mesh.matrixAutoUpdate = false;
29941
- mesh.updateMatrix();
29942
- parent.add(mesh);
29943
- }
29944
- buildGeometry(item, layout) {
29945
- const vertexData = item.vertexData;
29946
- const stride = layout;
29947
- const sourceVertexCount = Math.floor(vertexData.length / stride);
29948
- if (sourceVertexCount === 0) {
29949
- return null;
29950
- }
29951
- // Layouts without per-vertex normals are single-sided planes: generate backfaces.
29952
- const createBackfaces = layout === LegacyVertexDataLayout.Position || layout === LegacyVertexDataLayout.PositionUv;
29953
- const vertexCount = createBackfaces ? sourceVertexCount * 2 : sourceVertexCount;
29954
- const positions = new Float32Array(vertexCount * 3);
29955
- const normals = new Float32Array(vertexCount * 3);
29956
- const uvs = new Float32Array(vertexCount * 2);
29957
- // Per-item plane normal for layouts without per-vertex normals.
29958
- const planeNormal = item.normaal ?? [0, 0, 1];
29959
- const hasIndices = item.vertexIndices != null && item.vertexIndices.length > 0;
29960
- let offset = 0;
29961
- let vertexIndex = 0;
29962
- while (offset + stride <= vertexData.length) {
29963
- positions[3 * vertexIndex + 0] = vertexData[offset + 0];
29964
- positions[3 * vertexIndex + 1] = vertexData[offset + 1];
29965
- positions[3 * vertexIndex + 2] = vertexData[offset + 2];
29966
- if (createBackfaces) {
29967
- // Backface vertex index: with indexed geometry vertices are duplicated 1:1 (winding is
29968
- // reversed in the index buffer); with triangle soup the order within each triangle is reversed.
29969
- const backfaceIndex = hasIndices
29970
- ? vertexIndex + sourceVertexCount
29971
- : vertexIndex + sourceVertexCount + 2 * (1 - (vertexIndex % 3));
29972
- positions[3 * backfaceIndex + 0] = vertexData[offset + 0];
29973
- positions[3 * backfaceIndex + 1] = vertexData[offset + 1];
29974
- positions[3 * backfaceIndex + 2] = vertexData[offset + 2];
29975
- normals[3 * vertexIndex + 0] = planeNormal[0];
29976
- normals[3 * vertexIndex + 1] = planeNormal[1];
29977
- normals[3 * vertexIndex + 2] = planeNormal[2];
29978
- normals[3 * backfaceIndex + 0] = -planeNormal[0];
29979
- normals[3 * backfaceIndex + 1] = -planeNormal[1];
29980
- normals[3 * backfaceIndex + 2] = -planeNormal[2];
29981
- if (layout === LegacyVertexDataLayout.PositionUv) {
29982
- uvs[2 * vertexIndex + 0] = vertexData[offset + 3];
29983
- uvs[2 * vertexIndex + 1] = vertexData[offset + 4];
29984
- uvs[2 * backfaceIndex + 0] = vertexData[offset + 3];
29985
- uvs[2 * backfaceIndex + 1] = vertexData[offset + 4];
29986
- }
29987
- }
29988
- else {
29989
- normals[3 * vertexIndex + 0] = vertexData[offset + 3];
29990
- normals[3 * vertexIndex + 1] = vertexData[offset + 4];
29991
- normals[3 * vertexIndex + 2] = vertexData[offset + 5];
29992
- if (layout !== LegacyVertexDataLayout.PositionNormal) {
29993
- uvs[2 * vertexIndex + 0] = vertexData[offset + 6];
29994
- uvs[2 * vertexIndex + 1] = vertexData[offset + 7];
29995
- }
29996
- }
29997
- vertexIndex++;
29998
- offset += stride;
29999
- }
30000
- const geometry = new BufferGeometry();
30001
- geometry.setAttribute('position', new BufferAttribute(positions, 3));
30002
- geometry.setAttribute('normal', new BufferAttribute(normals, 3));
30003
- geometry.setAttribute('uv', new BufferAttribute(uvs, 2));
30004
- if (hasIndices) {
30005
- const indices = item.vertexIndices;
30006
- if (createBackfaces) {
30007
- // Front faces keep the original indices; backfaces reference the duplicated
30008
- // vertices with reversed winding order.
30009
- const extended = new Array(indices.length * 2);
30010
- for (let i = 0; i < indices.length; i += 3) {
30011
- extended[i + 0] = indices[i + 0];
30012
- extended[i + 1] = indices[i + 1];
30013
- extended[i + 2] = indices[i + 2];
30014
- extended[indices.length + i + 0] = indices[i + 2] + sourceVertexCount;
30015
- extended[indices.length + i + 1] = indices[i + 1] + sourceVertexCount;
30016
- extended[indices.length + i + 2] = indices[i + 0] + sourceVertexCount;
30017
- }
30018
- geometry.setIndex(extended);
30019
- }
30020
- else {
30021
- geometry.setIndex(indices);
30022
- }
30023
- }
30024
- return geometry;
30025
- }
30026
- /**
30027
- * Resolves the material for an item. Returns null when the item should be skipped
30028
- * (fully transparent "air" geometry).
30029
- */
30030
- resolveMaterial(fragment, item, texturePaths, isTransparent) {
30031
- const color = fragment.kleurBronnen?.[item.kleur];
30032
- const opacity = color != null ? color[3] / 255 : 1;
30033
- if (isTransparent) {
30034
- if (opacity === 0) {
30035
- // Air / gas elements (e.g. the cavity in a cavity wall): skip entirely.
30036
- return null;
30037
- }
30038
- /* The only transparent elements with non-zero opacity in practice are glass.
30039
- A shared physical glass material (with env reflections) looks much better
30040
- than a plain transparent color material. */
30041
- if (this.glassMaterial !== null) {
30042
- return this.glassMaterial;
30043
- }
30044
- }
30045
- const albedoPath = item.tableau != null ? texturePaths[item.tableau] : undefined;
30046
- const bumpPath = item.bumpmap != null ? texturePaths[item.bumpmap] : undefined;
30047
- const cacheKey = `${fragment.ID}|k${item.kleur}|t${albedoPath ?? ''}|b${bumpPath ?? ''}` +
30048
- `|s${item.schitteringMat ?? ''}|m${item.metaalachtigheid ?? ''}|tr${isTransparent ? 1 : 0}`;
30049
- const cached = this.materialCache.get(cacheKey);
30050
- if (cached !== undefined) {
30051
- return cached;
30052
- }
30053
- const material = new MeshStandardMaterial();
30054
- const albedoTexture = albedoPath !== undefined ? this.textures.get(albedoPath) : undefined;
30055
- if (albedoTexture !== undefined) {
30056
- albedoTexture.colorSpace = SRGBColorSpace;
30057
- material.map = albedoTexture;
30058
- material.color.set(0xffffff);
30059
- // Legacy viewer convention: texture names containing "transparant" carry an alpha channel.
30060
- if (albedoPath.toLowerCase().includes('transparant')) {
30061
- material.transparent = true;
30062
- }
30063
- material.alphaTest = 0.5;
30064
- }
30065
- else if (color != null) {
30066
- material.color.setRGB(color[0] / 255, color[1] / 255, color[2] / 255, SRGBColorSpace);
30067
- material.opacity = opacity;
30068
- if (isTransparent && opacity < 1) {
30069
- // Fallback when no glass material is available (engine still booting).
30070
- material.transparent = true;
30071
- }
30072
- }
30073
- const bumpTexture = bumpPath !== undefined ? this.textures.get(bumpPath) : undefined;
30074
- if (bumpTexture !== undefined) {
30075
- // Files named "*bumpmap*" are grayscale height maps; everything else is a normal map.
30076
- if (bumpPath.toLowerCase().includes('bumpmap')) {
30077
- material.bumpMap = bumpTexture;
30078
- }
30079
- else {
30080
- material.normalMap = bumpTexture;
30081
- }
30082
- }
30083
- if (isTransparent) {
30084
- // As little blur as possible behind regular glass.
30085
- material.roughness = 0;
30086
- }
30087
- else if (item.schitteringMat !== undefined) {
30088
- /* Real-world materials are never perfectly smooth: a minimum roughness
30089
- avoids overly bright specular reflections. */
30090
- const minimumRoughness = 0.45;
30091
- material.roughness = Math.max(minimumRoughness, 1 - item.schitteringMat);
30092
- }
30093
- material.metalness = item.metaalachtigheid ?? 0;
30094
- this.materialCache.set(cacheKey, material);
30095
- return material;
30096
- }
30097
- /** Removes the current model and disposes its geometries and per-model materials. */
30098
- removeModel() {
30099
- if (this.modelRoot === undefined) {
30100
- return;
30101
- }
30102
- const root = this.modelRoot;
30103
- this.modelRoot = undefined;
30104
- this.lastLoadedJson = undefined;
30105
- root.traverse((object) => {
30106
- const mesh = object;
30107
- if (mesh.isMesh === true) {
30108
- mesh.geometry?.dispose();
30109
- }
30110
- });
30111
- // Cached materials are per-model; textures are kept (cached across rebuilds).
30112
- this.materialCache.forEach(material => material.dispose());
30113
- this.materialCache.clear();
30114
- this.remove(root);
30115
- root.clear();
30116
- if (this.hasWorld()) {
30117
- this.getWorld().onSceneChanged.next();
30118
- }
30119
- }
30120
- destroy() {
30121
- // Invalidate any in-flight load.
30122
- this.loadGeneration++;
30123
- this.pendingJson = undefined;
30124
- this.removeModel();
30125
- this.textures.forEach(texture => texture.dispose());
30126
- this.textures.clear();
30127
- this.failedTextures.clear();
30128
- this.onModelLoadedSubject.complete();
30129
- super.destroy();
30130
- }
30131
- }
30132
-
30133
- /**
30134
- * View-only game mode for the Fabrikanten 3D product viewer.
30135
- *
30136
- * OrbitPawn: orbit, pan and zoom only — no input actions, no selection. The
30137
- * FabThreeViewerController adds the settings panel (graphics presets, stats,
30138
- * inspector). Creates the JSON converter and frames the camera around the
30139
- * model whenever it (re)loads.
30140
- */
30141
- class FabThreeViewerMode extends GameModeBase {
30142
- /**
30143
- * Default view direction towards the model, matching the legacy viewer's
30144
- * "kijkrichting" [0.500, 0.744, -0.442] (HDH Z-up), converted to three.js Y-up.
30145
- */
30146
- static CAMERA_OFFSET_DIRECTION = new Vector3(-0.5002, 0.4424, 0.7444).normalize();
30147
- converter;
30148
- modelLoadedSubscription;
30149
- constructor() {
30150
- super(GameStateBase, FabThreeViewerController, OrbitPawn);
30151
- this.name = 'Fab Viewer Mode';
30152
- }
30153
- init() {
30154
- super.init();
30155
- const world = this.getWorld();
30156
- // Sensible default pose until the model bounding box is known.
30157
- this.pawn.setCameraPositionAndLookAt(new Vector3(-3, 2.5, 4.5), new Vector3(0, 0, 0));
30158
- const converter = new FabWebglJsonConverter();
30159
- this.converter = converter;
30160
- world.addActor(converter);
30161
- this.modelLoadedSubscription?.unsubscribe();
30162
- this.modelLoadedSubscription = converter.onModelLoaded$.subscribe((box) => {
30163
- this.frameModel(box);
30164
- });
30165
- // Registers the glass material on the converter and re-queues the last model.
30166
- world.registerConverter(converter);
30167
- }
30168
- /**
30169
- * Positions the orbit camera so the whole model is in view (the equivalent of the
30170
- * legacy viewer's "zetZoomGeheel"), and adapts near/far planes and zoom limits
30171
- * to the model size.
30172
- */
30173
- frameModel(box) {
30174
- if (box.isEmpty()) {
30175
- return;
30176
- }
30177
- const pawn = this.pawn;
30178
- const camera = pawn.getCamera();
30179
- if (!(camera instanceof PerspectiveCamera)) {
30180
- return;
30181
- }
30182
- const center = box.getCenter(new Vector3());
30183
- const radius = Math.max(box.getSize(new Vector3()).length() / 2, 0.05);
30184
- // Fit the bounding sphere in both the vertical and horizontal field of view.
30185
- const verticalFov = MathUtils.degToRad(camera.fov);
30186
- const horizontalFov = 2 * Math.atan(Math.tan(verticalFov / 2) * camera.aspect);
30187
- const fitFov = Math.min(verticalFov, horizontalFov);
30188
- const distance = (radius / Math.sin(fitFov / 2)) * 1.05;
30189
- const position = center.clone().addScaledVector(FabThreeViewerMode.CAMERA_OFFSET_DIRECTION, distance);
30190
- camera.near = Math.max(radius / 100, 0.001);
30191
- camera.far = Math.max(distance + radius * 20, 100);
30192
- camera.updateProjectionMatrix();
30193
- pawn.setCameraPositionAndLookAt(position, center);
30194
- const orbitControls = pawn.getOrbitControls();
30195
- if (orbitControls) {
30196
- orbitControls.minDistance = radius * 0.05;
30197
- orbitControls.maxDistance = radius * 20;
30198
- orbitControls.update();
30199
- }
30200
- this.getWorld().dispatchOnCameraMatrixChanged();
30201
- }
30202
- destroy() {
30203
- this.modelLoadedSubscription?.unsubscribe();
30204
- this.modelLoadedSubscription = undefined;
30205
- this.converter = undefined;
30206
- super.destroy();
30207
- }
30208
- }
30209
-
30210
- /**
30211
- * View-only world for the Fabrikanten 3D product viewer.
30212
- *
30213
- * Sets up sun + ambient lighting with shadows and a generated PBR room environment
30214
- * (reflections for glass/metal). Lighting adapted from the digihuis ViewerWorld,
30215
- * without skybox, day/night cycle, settings panel, selection and demo actors.
30216
- */
30217
- class FabThreeViewerWorld extends World {
30218
- /** Normalized sun direction (from the model towards the sun). */
30219
- static SUN_DIRECTION = new Vector3(-5, 20, 5).normalize();
30220
- /** Served from src/assets (see angular.json); relative so it respects the base href. */
30221
- static GLASS_HDRI_URL = 'assets/hdri/urban_courtyard_1k.hdr';
30222
- sun;
30223
- ambient;
30224
- environmentRenderTarget;
30225
- glassEnvironmentRenderTarget;
30226
- converter;
30227
- lastJson;
30228
- lastModelBox;
30229
- sceneChangedSubscription;
30230
- modelLoadedSubscription;
30231
- /** Shared glass material for transparent items (env map assigned once generated). */
30232
- glassMaterial = new MeshPhysicalMaterial({
30233
- color: 0xffffff,
30234
- metalness: 0.1,
30235
- roughness: 0,
30236
- transmission: 1.0,
30237
- transparent: true,
30238
- opacity: 1.0,
30239
- ior: 1,
30240
- thickness: 0,
30241
- specularIntensity: 0.02,
30242
- attenuationDistance: 0.0001,
30243
- attenuationColor: 0xffffff
30244
- });
30245
- init(engineWrapper, rendererCanvas, renderPipeline, renderer, onWindowResize, onPreRender, onPostRender, useWebGlFallback) {
30246
- super.init(engineWrapper, rendererCanvas, renderPipeline, renderer, onWindowResize, onPreRender, onPostRender, useWebGlFallback);
30247
- // View-only: no object selection.
30248
- this.objectSelector?.deactivate();
30249
- // Static scene: shadows are only re-rendered when the scene actually changes.
30250
- this.sceneChangedSubscription?.unsubscribe();
30251
- this.sceneChangedSubscription = this.onSceneChangedObservable.subscribe(() => {
30252
- if (this.sun) {
30253
- this.sun.shadow.needsUpdate = true;
30254
- }
30255
- });
30256
- this.setupLighting();
30257
- void this.setupEnvironment();
30258
- }
30259
- /** Shared glass material for transparent (glass) items. */
30260
- getGlassMaterial() {
30261
- return this.glassMaterial;
30262
- }
30263
- /**
30264
- * Registers the converter created by the game mode. Re-queues the last model so the
30265
- * scene survives engine restarts (the game mode is re-initialized on restart).
30266
- */
30267
- registerConverter(converter) {
30268
- this.converter = converter;
30269
- converter.setGlassMaterial(this.glassMaterial);
30270
- this.modelLoadedSubscription?.unsubscribe();
30271
- this.modelLoadedSubscription = converter.onModelLoaded$.subscribe((box) => {
30272
- this.lastModelBox = box;
30273
- this.fitLightingToBox(box);
30274
- });
30275
- if (this.lastJson !== undefined) {
30276
- converter.queueModel(this.lastJson);
30277
- }
30278
- }
30279
- /**
30280
- * Loads (or replaces) the product model from a webGLJSON string.
30281
- * Can be called before the engine has booted; the model is queued until ready.
30282
- */
30283
- loadModel(webGLJSON) {
30284
- this.lastJson = webGLJSON;
30285
- this.converter?.queueModel(webGLJSON);
30286
- }
30287
- setupLighting() {
30288
- this.teardownLighting();
30289
- const config = GraphicsScalabilityConfigsManager.activeGraphicsScalabilityConfig;
30290
- // Sunlight
30291
- const sun = new DirectionalLight(0xf7efe1, 2.0);
30292
- sun.position.copy(FabThreeViewerWorld.SUN_DIRECTION).multiplyScalar(20);
30293
- sun.castShadow = config.enableCastShadows;
30294
- sun.shadow.mapSize.width = config.sunShadowMapSize;
30295
- sun.shadow.mapSize.height = config.sunShadowMapSize;
30296
- sun.shadow.camera.left = -15;
30297
- sun.shadow.camera.right = 15;
30298
- sun.shadow.camera.top = 15;
30299
- sun.shadow.camera.bottom = -15;
30300
- sun.shadow.camera.near = 1;
30301
- sun.shadow.camera.far = config.shadowRenderDistance;
30302
- sun.shadow.bias = -0.0005;
30303
- sun.shadow.normalBias = 0.02;
30304
- sun.name = 'Sun';
30305
- sun.matrixAutoUpdate = false;
30306
- sun.updateMatrix();
30307
- // Static scene: prevent automatic shadow re-rendering every frame.
30308
- sun.shadow.autoUpdate = false;
30309
- this._scene.add(sun);
30310
- this._scene.add(sun.target);
30311
- this.sun = sun;
30312
- // Ambient light
30313
- const ambient = new AmbientLight(0xe9eff5, 1.25);
30314
- ambient.name = 'Ambient';
30315
- ambient.matrixAutoUpdate = false;
30316
- ambient.updateMatrix();
30317
- this._scene.add(ambient);
30318
- this.ambient = ambient;
30319
- // Neutral background, matching the legacy viewer's white canvas. The intensity
30320
- // compensates for ACES filmic tone mapping, which would otherwise render
30321
- // a 1.0 white as visibly gray.
30322
- this._scene.background = new Color(0xffffff);
30323
- this._scene.backgroundIntensity = 5;
30324
- // Re-fit when lighting is rebuilt after an engine restart.
30325
- if (this.lastModelBox) {
30326
- this.fitLightingToBox(this.lastModelBox);
30327
- }
30328
- this.onSceneChanged.next();
30329
- }
30330
- teardownLighting() {
30331
- if (this.sun) {
30332
- this.sun.shadow?.map?.dispose();
30333
- this.sun.target.removeFromParent();
30334
- this.sun.removeFromParent();
30335
- this.sun = undefined;
30336
- }
30337
- if (this.ambient) {
30338
- this.ambient.removeFromParent();
30339
- this.ambient = undefined;
30340
- }
30341
- }
30342
- /**
30343
- * Positions the sun relative to the model and fits the shadow camera around it,
30344
- * so shadows stay crisp regardless of model size and position.
30345
- */
30346
- fitLightingToBox(box) {
30347
- if (!this.sun || box.isEmpty()) {
30348
- return;
30349
- }
30350
- const center = box.getCenter(new Vector3());
30351
- const radius = Math.max(box.getSize(new Vector3()).length() / 2, 0.1);
30352
- const sun = this.sun;
30353
- sun.position.copy(center).addScaledVector(FabThreeViewerWorld.SUN_DIRECTION, radius * 3);
30354
- sun.target.position.copy(center);
30355
- sun.updateMatrix();
30356
- sun.target.updateMatrixWorld(true);
30357
- const extent = radius * 1.25;
30358
- sun.shadow.camera.left = -extent;
30359
- sun.shadow.camera.right = extent;
30360
- sun.shadow.camera.top = extent;
30361
- sun.shadow.camera.bottom = -extent;
30362
- sun.shadow.camera.near = radius * 0.5;
30363
- sun.shadow.camera.far = radius * 6;
30364
- sun.shadow.camera.updateProjectionMatrix();
30365
- sun.shadow.needsUpdate = true;
30366
- }
30367
- /**
30368
- * Sets up image-based lighting. Skipped on low graphics presets.
30369
- *
30370
- * - Scene-wide: a generated PBR room environment (subtle reflections on all materials).
30371
- * - Glass: the urban courtyard HDRI (same as the digihuis viewer), which gives glass
30372
- * far more convincing reflections than the synthetic room.
30373
- */
30374
- async setupEnvironment() {
30375
- if (!GraphicsScalabilityConfigsManager.activeGraphicsScalabilityConfig.enableEnvReflections) {
30376
- return;
30377
- }
30378
- const renderer = this.getRenderer();
30379
- // The WebGPU backend initializes asynchronously; PMREM requires it to be ready.
30380
- await renderer.init();
30381
- try {
30382
- const pmremGenerator = new PMREMGenerator(renderer);
30383
- const roomEnvironment = new RoomEnvironment();
30384
- const renderTarget = pmremGenerator.fromScene(roomEnvironment, 0.04);
30385
- pmremGenerator.dispose();
30386
- roomEnvironment.dispose();
30387
- this.environmentRenderTarget?.dispose();
30388
- this.environmentRenderTarget = renderTarget;
30389
- const scene = this.getScene();
30390
- scene.environment = renderTarget.texture;
30391
- // Subtle image-based lighting: the sun + ambient remain the dominant lights.
30392
- scene.environmentIntensity = 0.4;
30393
- // Until the HDRI is loaded (or when it fails), glass falls back to the room environment.
30394
- this.setGlassEnvMap(renderTarget.texture);
30395
- this.onSceneChanged.next();
30396
- }
30397
- catch (error) {
30398
- console.warn('FabThreeViewerWorld: environment map generation failed; continuing without reflections.', error);
30399
- }
30400
- try {
30401
- const hdrTexture = await new HDRLoader().loadAsync(FabThreeViewerWorld.GLASS_HDRI_URL);
30402
- const pmremGenerator = new PMREMGenerator(renderer);
30403
- const renderTarget = pmremGenerator.fromEquirectangular(hdrTexture);
30404
- pmremGenerator.dispose();
30405
- hdrTexture.dispose();
30406
- this.glassEnvironmentRenderTarget?.dispose();
30407
- this.glassEnvironmentRenderTarget = renderTarget;
30408
- this.setGlassEnvMap(renderTarget.texture);
30409
- this.onSceneChanged.next();
30410
- }
30411
- catch (error) {
30412
- console.warn('FabThreeViewerWorld: failed to load glass HDRI; glass keeps the room environment.', error);
30413
- }
30414
- }
30415
- setGlassEnvMap(texture) {
30416
- this.glassMaterial.envMap = texture;
30417
- this.glassMaterial.envMapIntensity = 4;
30418
- this.glassMaterial.needsUpdate = true;
30419
- }
30420
- stop() {
30421
- this.sceneChangedSubscription?.unsubscribe();
30422
- this.sceneChangedSubscription = undefined;
30423
- this.modelLoadedSubscription?.unsubscribe();
30424
- this.modelLoadedSubscription = undefined;
30425
- this.converter = undefined;
30426
- this.teardownLighting();
30427
- this.environmentRenderTarget?.dispose();
30428
- this.environmentRenderTarget = undefined;
30429
- this.glassEnvironmentRenderTarget?.dispose();
30430
- this.glassEnvironmentRenderTarget = undefined;
30431
- super.stop();
30432
- }
30433
- }
30434
-
30435
29520
  class FabWebglViewerComponent {
30436
29521
  FabrikantenService;
30437
29522
  WebGLService;
30438
29523
  TranslateService;
30439
29524
  MobileService;
30440
29525
  ChangeDetectorRef;
30441
- /**
30442
- * The three-engine world rendered by <threejs-engine>. Created lazily once the
30443
- * 3D model data is available; reused (model reloaded in place) afterwards.
30444
- */
30445
- ViewerWorld = null;
29526
+ Height = "calc(100% - 0px)";
30446
29527
  _viewercontainer;
30447
29528
  set viewercontainer(value) {
30448
29529
  this._viewercontainer = value;
30449
29530
  if (value) {
30450
- // The container just appeared (e.g. after variant selection): ensure the viewer is up to date.
30451
29531
  queueMicrotask(() => {
29532
+ this.RefreshViewerSize();
30452
29533
  this.RefreshViewer();
30453
29534
  });
30454
29535
  }
@@ -30470,10 +29551,17 @@ class FabWebglViewerComponent {
30470
29551
  this.ChangeDetectorRef = ChangeDetectorRef;
30471
29552
  this.WebGLService.FabWebglViewerComponent = this;
30472
29553
  }
29554
+ ngOnInit() {
29555
+ this.RefreshViewerSize();
29556
+ }
30473
29557
  ngAfterViewInit() {
29558
+ this.RefreshViewerSize();
30474
29559
  this.RefreshViewer();
30475
29560
  this.ChangeDetectorRef.detectChanges();
30476
29561
  }
29562
+ ngDoCheck() {
29563
+ this.RefreshViewerSize();
29564
+ }
30477
29565
  ShowWebGL() {
30478
29566
  if (!this.FabrikantenService.ShowVariants()) {
30479
29567
  if (this.WebGLService.Fabrikanten3DViewModel != undefined) {
@@ -30482,30 +29570,103 @@ class FabWebglViewerComponent {
30482
29570
  }
30483
29571
  return false;
30484
29572
  }
30485
- /**
30486
- * Creates the three-engine world on first call and (re)loads the current
30487
- * webGLJSON model. Safe to call repeatedly: identical models are ignored.
30488
- */
30489
29573
  RefreshViewer() {
30490
- if (this.WebGLService.Loading || this.WebGLService.Fabrikanten3DViewModel == null) {
29574
+ if (!this.WebGLService.Loading && this.WebGLService.Fabrikanten3DViewModel != null) {
29575
+ var viewer = ModuleViewer3DLight.get("viewerCanvas");
29576
+ if (viewer != null) {
29577
+ //var belichting = viewer.belichting;
29578
+ //belichting.toonSlagschaduw = true;
29579
+ //belichting.slagschaduwVerzadiging = 0.5;
29580
+ //belichting.lichtbronSterkte = 3;
29581
+ //belichting.lichtSchittering = 0.333;
29582
+ //belichting.omgevinglichtSterkte = 0.8;
29583
+ //belichting.isCameraLicht = true;
29584
+ //if (belichting.isCameraLicht == true) {
29585
+ // belichting.lichtval = [0, 1, 0];
29586
+ //} else {
29587
+ // belichting.lichtval = [-1.0, 0.5, -1.2];
29588
+ //}
29589
+ //viewer.orthografischeProjectie = false;
29590
+ //viewer.kijkrichting = [0.56777614549287847, 0.69328989820855813, -0.44382357491599833];
29591
+ //belichting.lichtbronSterkte = 0.8;
29592
+ //belichting.lichtSchittering = 0.333;
29593
+ //belichting.omgevinglichtSterkte = 0.4;
29594
+ //belichting.lichtval = [-1.0, 0.5, -1.2];
29595
+ var lichtbronSterkte = 1;
29596
+ var omgevinglichtSterkte = 0.6;
29597
+ var lichtvalX = 1;
29598
+ var lichtvalY = 2;
29599
+ var lichtvalZ = -2;
29600
+ var toonSlagshaduw = true;
29601
+ try {
29602
+ if (this.FabrikantenService.FabrikantenSettingsViewModel.lichtbronSterkte != undefined) {
29603
+ lichtbronSterkte = parseFloat(this.FabrikantenService.FabrikantenSettingsViewModel.lichtbronSterkte);
29604
+ }
29605
+ if (this.FabrikantenService.FabrikantenSettingsViewModel.omgevinglichtSterkte != undefined) {
29606
+ omgevinglichtSterkte = parseFloat(this.FabrikantenService.FabrikantenSettingsViewModel.omgevinglichtSterkte);
29607
+ }
29608
+ if (this.FabrikantenService.FabrikantenSettingsViewModel.lichtvalX != undefined) {
29609
+ lichtvalX = parseFloat(this.FabrikantenService.FabrikantenSettingsViewModel.lichtvalX);
29610
+ }
29611
+ if (this.FabrikantenService.FabrikantenSettingsViewModel.lichtvalY != undefined) {
29612
+ lichtvalY = parseFloat(this.FabrikantenService.FabrikantenSettingsViewModel.lichtvalY);
29613
+ }
29614
+ if (this.FabrikantenService.FabrikantenSettingsViewModel.lichtvalZ != undefined) {
29615
+ lichtvalZ = parseFloat(this.FabrikantenService.FabrikantenSettingsViewModel.lichtvalZ);
29616
+ }
29617
+ if (this.FabrikantenService.FabrikantenSettingsViewModel.lichtvalZ != undefined) {
29618
+ toonSlagshaduw = this.FabrikantenService.FabrikantenSettingsViewModel.toonSlagshaduw;
29619
+ }
29620
+ }
29621
+ catch (ex) {
29622
+ lichtbronSterkte = 1;
29623
+ omgevinglichtSterkte = 0.6;
29624
+ lichtvalX = 1;
29625
+ lichtvalY = 2;
29626
+ lichtvalZ = -2;
29627
+ toonSlagshaduw = true;
29628
+ }
29629
+ var belichting = viewer.belichting;
29630
+ belichting.toonSlagschaduw = toonSlagshaduw;
29631
+ belichting.slagschaduwVerzadiging = 0.5;
29632
+ belichting.lichtbronSterkte = lichtbronSterkte;
29633
+ belichting.lichtSchittering = 0.333;
29634
+ belichting.isCameraLicht = false;
29635
+ belichting.omgevinglichtSterkte = omgevinglichtSterkte;
29636
+ belichting.lichtval = [1, 2, -2];
29637
+ viewer.orthografischeProjectie = false;
29638
+ viewer.kijkrichting = [0.50023241910093, 0.7443600526604934, -0.4423749980318723];
29639
+ viewer.clear();
29640
+ viewer.add(this.WebGLService.Fabrikanten3DViewModel.webGLJSON, function () {
29641
+ viewer.zetZoomGeheel();
29642
+ viewer.toonModel();
29643
+ });
29644
+ }
29645
+ }
29646
+ }
29647
+ RefreshViewerSize() {
29648
+ if (!this.viewercontainer) {
30491
29649
  return;
30492
29650
  }
30493
- const webGLJSON = this.WebGLService.Fabrikanten3DViewModel.webGLJSON;
30494
- if (!webGLJSON) {
29651
+ const nativeElement = this.viewercontainer.nativeElement;
29652
+ const width = nativeElement.offsetWidth - 6;
29653
+ const height = nativeElement.offsetHeight - 6;
29654
+ if (width <= 0 || height <= 0) {
30495
29655
  return;
30496
29656
  }
30497
- if (this.ViewerWorld == null) {
30498
- this.ViewerWorld = new FabThreeViewerWorld(new FabThreeViewerMode());
29657
+ if (this.WebGLService.ViewerWidth !== width || this.WebGLService.ViewerHeight !== height) {
29658
+ this.WebGLService.ViewerWidth = width;
29659
+ this.WebGLService.ViewerHeight = height;
30499
29660
  this.ChangeDetectorRef.detectChanges();
29661
+ this.RefreshViewer();
30500
29662
  }
30501
- this.ViewerWorld.loadModel(webGLJSON);
30502
29663
  }
30503
29664
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: FabWebglViewerComponent, deps: [{ token: FabrikantenService }, { token: WebGLService }, { token: TranslateService }, { token: MobileService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
30504
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.13", type: FabWebglViewerComponent, isStandalone: false, selector: "app-fab-webgl-viewer", viewQueries: [{ propertyName: "viewercontainer", first: true, predicate: ["viewercontainer"], descendants: true }], ngImport: i0, template: "<div class=\"loader\" *ngIf=\"WebGLService.Loading\">\r\n <app-fab-loader [text]=\"TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.ProductLoading)\"></app-fab-loader>\r\n</div>\r\n\r\n<div class=\"webgl-viewer-main-window\">\r\n <div *ngIf=\"FabrikantenService.ShowVariants()\" class=\"multiplevariants\">\r\n <app-fab-select-bcbproduct></app-fab-select-bcbproduct>\r\n </div>\r\n <div *ngIf=\"ShowWebGL()\" class=\"main-window flex-col\">\r\n <div #viewercontainer class=\"viewer-container\">\r\n <threejs-engine *ngIf=\"ViewerWorld\" [world]=\"ViewerWorld\"></threejs-engine>\r\n </div>\r\n\r\n <div class=\"webgl-settings\" *ngIf=\"MobileService.ShowActionMenu()\">\r\n <mat-card>\r\n <mat-card-content>\r\n <app-fab-actionmenu [display]=\"'3D'\"></app-fab-actionmenu>\r\n </mat-card-content>\r\n </mat-card>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n\r\n", styles: [".webgl-viewer-main-window{height:calc(100vH - 124px)}.main-window{height:100%}.row{display:flex;line-height:37px}.flex-col{display:flex;flex-direction:column}.multiplevariants{padding:20px}.loader{position:absolute;width:100%;height:100%;justify-content:center}.column{display:flex;flex-direction:column}.webgl-settings{position:absolute;top:10px;right:10px;display:flex}.icon{margin-right:3px}.viewer-container{display:flex;overflow:hidden;height:100%;background-color:#fff;cursor:grab}.viewer-container:active{cursor:grabbing}.row-icon{align-items:center;display:flex}.row-title{flex:auto}.viewer-canvas{background-color:#fff;cursor:grab}button{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.toolbar-button{margin-top:3px}.button{margin:5px;width:100%}\n"], dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i6$2.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i6$2.MatCardContent, selector: "mat-card-content" }, { kind: "component", type: i7$2.ThreejsEngineComponent, selector: "threejs-engine", inputs: ["world"] }, { kind: "component", type: FabActionmenuComponent, selector: "app-fab-actionmenu", inputs: ["display"] }, { kind: "component", type: FabLoaderComponent, selector: "app-fab-loader", inputs: ["text"] }, { kind: "component", type: FabSelectBcbproductComponent, selector: "app-fab-select-bcbproduct" }] });
29665
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.13", type: FabWebglViewerComponent, isStandalone: false, selector: "app-fab-webgl-viewer", viewQueries: [{ propertyName: "viewercontainer", first: true, predicate: ["viewercontainer"], descendants: true }], ngImport: i0, template: "<div class=\"loader\" *ngIf=\"WebGLService.Loading\">\r\n <app-fab-loader [text]=\"TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.ProductLoading)\"></app-fab-loader>\r\n</div>\r\n\r\n<div class=\"webgl-viewer-main-window\">\r\n <div *ngIf=\"FabrikantenService.ShowVariants()\" class=\"multiplevariants\">\r\n <app-fab-select-bcbproduct></app-fab-select-bcbproduct>\r\n </div>\r\n <div *ngIf=\"ShowWebGL()\" class=\"main-window flex-col\">\r\n <div #viewercontainer class=\"viewer-container\">\r\n <canvas id=\"viewerCanvas\" class=\"viewer-canvas\" [attr.width]=\"WebGLService.ViewerWidth\" [attr.height]=\"WebGLService.ViewerHeight\"></canvas>\r\n </div>\r\n\r\n <div class=\"webgl-settings\" *ngIf=\"MobileService.ShowActionMenu()\">\r\n <mat-card>\r\n <mat-card-content>\r\n <app-fab-actionmenu [display]=\"'3D'\"></app-fab-actionmenu>\r\n </mat-card-content>\r\n </mat-card>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n\r\n", styles: [".webgl-viewer-main-window{height:calc(100vH - 124px)}.main-window{height:100%}.row{display:flex;line-height:37px}.flex-col{display:flex;flex-direction:column}.multiplevariants{padding:20px}.loader{position:absolute;width:100%;height:100%;justify-content:center}.column{display:flex;flex-direction:column}.webgl-settings{position:absolute;top:10px;right:10px;display:flex}.icon{margin-right:3px}.viewer-container{overflow:auto;height:100%}.row-icon{align-items:center;display:flex}.row-title{flex:auto}.viewer-canvas{background-color:#fff;cursor:grab}button{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.toolbar-button{margin-top:3px}.button{margin:5px;width:100%}\n"], dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i6$2.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i6$2.MatCardContent, selector: "mat-card-content" }, { kind: "component", type: FabActionmenuComponent, selector: "app-fab-actionmenu", inputs: ["display"] }, { kind: "component", type: FabLoaderComponent, selector: "app-fab-loader", inputs: ["text"] }, { kind: "component", type: FabSelectBcbproductComponent, selector: "app-fab-select-bcbproduct" }] });
30505
29666
  }
30506
29667
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: FabWebglViewerComponent, decorators: [{
30507
29668
  type: Component,
30508
- args: [{ selector: 'app-fab-webgl-viewer', standalone: false, template: "<div class=\"loader\" *ngIf=\"WebGLService.Loading\">\r\n <app-fab-loader [text]=\"TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.ProductLoading)\"></app-fab-loader>\r\n</div>\r\n\r\n<div class=\"webgl-viewer-main-window\">\r\n <div *ngIf=\"FabrikantenService.ShowVariants()\" class=\"multiplevariants\">\r\n <app-fab-select-bcbproduct></app-fab-select-bcbproduct>\r\n </div>\r\n <div *ngIf=\"ShowWebGL()\" class=\"main-window flex-col\">\r\n <div #viewercontainer class=\"viewer-container\">\r\n <threejs-engine *ngIf=\"ViewerWorld\" [world]=\"ViewerWorld\"></threejs-engine>\r\n </div>\r\n\r\n <div class=\"webgl-settings\" *ngIf=\"MobileService.ShowActionMenu()\">\r\n <mat-card>\r\n <mat-card-content>\r\n <app-fab-actionmenu [display]=\"'3D'\"></app-fab-actionmenu>\r\n </mat-card-content>\r\n </mat-card>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n\r\n", styles: [".webgl-viewer-main-window{height:calc(100vH - 124px)}.main-window{height:100%}.row{display:flex;line-height:37px}.flex-col{display:flex;flex-direction:column}.multiplevariants{padding:20px}.loader{position:absolute;width:100%;height:100%;justify-content:center}.column{display:flex;flex-direction:column}.webgl-settings{position:absolute;top:10px;right:10px;display:flex}.icon{margin-right:3px}.viewer-container{display:flex;overflow:hidden;height:100%;background-color:#fff;cursor:grab}.viewer-container:active{cursor:grabbing}.row-icon{align-items:center;display:flex}.row-title{flex:auto}.viewer-canvas{background-color:#fff;cursor:grab}button{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.toolbar-button{margin-top:3px}.button{margin:5px;width:100%}\n"] }]
29669
+ args: [{ selector: 'app-fab-webgl-viewer', standalone: false, template: "<div class=\"loader\" *ngIf=\"WebGLService.Loading\">\r\n <app-fab-loader [text]=\"TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.ProductLoading)\"></app-fab-loader>\r\n</div>\r\n\r\n<div class=\"webgl-viewer-main-window\">\r\n <div *ngIf=\"FabrikantenService.ShowVariants()\" class=\"multiplevariants\">\r\n <app-fab-select-bcbproduct></app-fab-select-bcbproduct>\r\n </div>\r\n <div *ngIf=\"ShowWebGL()\" class=\"main-window flex-col\">\r\n <div #viewercontainer class=\"viewer-container\">\r\n <canvas id=\"viewerCanvas\" class=\"viewer-canvas\" [attr.width]=\"WebGLService.ViewerWidth\" [attr.height]=\"WebGLService.ViewerHeight\"></canvas>\r\n </div>\r\n\r\n <div class=\"webgl-settings\" *ngIf=\"MobileService.ShowActionMenu()\">\r\n <mat-card>\r\n <mat-card-content>\r\n <app-fab-actionmenu [display]=\"'3D'\"></app-fab-actionmenu>\r\n </mat-card-content>\r\n </mat-card>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n\r\n", styles: [".webgl-viewer-main-window{height:calc(100vH - 124px)}.main-window{height:100%}.row{display:flex;line-height:37px}.flex-col{display:flex;flex-direction:column}.multiplevariants{padding:20px}.loader{position:absolute;width:100%;height:100%;justify-content:center}.column{display:flex;flex-direction:column}.webgl-settings{position:absolute;top:10px;right:10px;display:flex}.icon{margin-right:3px}.viewer-container{overflow:auto;height:100%}.row-icon{align-items:center;display:flex}.row-title{flex:auto}.viewer-canvas{background-color:#fff;cursor:grab}button{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.toolbar-button{margin-top:3px}.button{margin:5px;width:100%}\n"] }]
30509
29670
  }], ctorParameters: () => [{ type: FabrikantenService }, { type: WebGLService }, { type: TranslateService }, { type: MobileService }, { type: i0.ChangeDetectorRef }], propDecorators: { viewercontainer: [{
30510
29671
  type: ViewChild,
30511
29672
  args: ['viewercontainer']
@@ -30649,7 +29810,7 @@ class FabProductComponent {
30649
29810
  return this.MobileService.NavMode;
30650
29811
  }
30651
29812
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: FabProductComponent, deps: [{ token: MobileService }, { token: FabrikantenService }, { token: BestekService }, { token: TranslateService }, { token: WebGLService }, { token: i3.ActivatedRoute }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
30652
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.13", type: FabProductComponent, isStandalone: false, selector: "app-fab-product", viewQueries: [{ propertyName: "header", first: true, predicate: ["header"], descendants: true }], ngImport: i0, template: "<div *ngIf=\"FabrikantenService.IsLoadingSmall()\" [ngClass]=\"HasParameter() ? GetParameterClass() : ''\" class=\"loader\">\r\n <mat-card class=\"loader-card\">\r\n <mat-card-content>\r\n <mat-spinner class=\"loader-spinner\" [diameter]=\"80\"></mat-spinner>\r\n </mat-card-content>\r\n <mat-card-subtitle class=\"loader-subtitle\" *ngIf=\"!FabrikantenService.IsStartingDownload()\">\r\n {{ TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.ProductsLoading) }}\r\n </mat-card-subtitle>\r\n </mat-card>\r\n</div>\r\n\r\n<mat-drawer-container class=\"view-container\" [ngClass]=\"HasParameter() ? GetParameterClass() : ''\" *ngIf=\"FabrikantenService.Loaded\">\r\n <mat-drawer #drawer [mode]=\"GetNavMode()\" [(opened)]=\"MobileService.NavOpened\" *ngIf=\"FabrikantenService.FabrikantenViewModel != null\">\r\n <div class=\"filter-view\">\r\n <fab-filters-input></fab-filters-input>\r\n </div>\r\n </mat-drawer>\r\n <mat-drawer mode=\"over\" position=\"end\" [(opened)]=\"MobileService.ActionOpened\">\r\n <div class=\"actionwrapper\">\r\n <app-fab-actionmenu [display]=\"FabrikantenService.SelectedTab\"></app-fab-actionmenu>\r\n </div>\r\n </mat-drawer>\r\n <mat-drawer-content class=\"view-content\">\r\n <div #header *ngIf=\"ShowBreadcrumb()\">\r\n <app-fab-header [showfiltermenubutton]=\"true\"></app-fab-header>\r\n\r\n <ng-container *ngIf=\"ShowInformationBlock()\">\r\n <app-fab-product-info></app-fab-product-info>\r\n </ng-container>\r\n </div>\r\n\r\n <ng-container *ngIf=\"FabrikantenService.ShowRequired()\">\r\n <div class=\"required-div\">{{ TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.NotAllRequiredFilled) }}</div>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"FabrikantenService.ShowNoParameters() && !FabrikantenService.IsLoading()\">\r\n <div class=\"no-parameters-div\">\r\n No product request send to BCB due to invalid or missing parameters\r\n </div>\r\n <div class=\"required-div\">\r\n <ng-container *ngIf=\"FabrikantenService.FabrikantenViewModel?.customInfoParameters != undefined\">\r\n <ng-container *ngFor=\"let customparameter of FabrikantenService.FabrikantenViewModel.customInfoParameters\">\r\n <div class=\"display-value-item\">\r\n {{ customparameter.name }}: {{ customparameter.value }}\r\n </div>\r\n </ng-container>\r\n </ng-container>\r\n </div>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"!FabrikantenService.ShowRequired() && !FabrikantenService.ShowNoParameters()\">\r\n <div [style.height]=\"Height\" *ngIf=\"FabrikantenService.FabrikantenViewModel != null\">\r\n <mat-tab-group class=\"view-container\" [selectedIndex]=\"FabrikantenService.SelectedTabIndex\" (selectedTabChange)=\"SelectedTabChange($event)\">\r\n <mat-tab label=\"Informatie\" *ngIf=\"ShowInformation()\">\r\n <ng-template mat-tab-label>\r\n <span>{{ TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.TabInformation) }}</span>\r\n </ng-template>\r\n <app-fab-product-info></app-fab-product-info>\r\n </mat-tab>\r\n <mat-tab label=\"3D\" *ngIf=\"Show3D()\">\r\n <ng-template mat-tab-label>\r\n <span>{{ TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.Tab3D) }}</span>\r\n </ng-template>\r\n <app-fab-webgl-viewer></app-fab-webgl-viewer>\r\n </mat-tab>\r\n <mat-tab label=\"2D\" *ngIf=\"Show2D()\" style=\"height: 100%;\">\r\n <ng-template mat-tab-label>\r\n <span>{{ TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.Tab2D) }}</span>\r\n </ng-template>\r\n <app-fab-svg-viewer></app-fab-svg-viewer>\r\n </mat-tab>\r\n <mat-tab label=\"Bestek\" *ngIf=\"ShowSpecification()\">\r\n <ng-template mat-tab-label>\r\n <span>{{ TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.TabSpecification) }}</span>\r\n </ng-template>\r\n <app-fab-product-bestek *ngIf=\"TranslateService.ShowSpecification()\"></app-fab-product-bestek>\r\n <app-fab-product-auto-specification *ngIf=\"TranslateService.ShowAutoSpecification()\"></app-fab-product-auto-specification>\r\n <app-fab-product-lastenboek *ngIf=\"TranslateService.ShowLastenboek()\"></app-fab-product-lastenboek>\r\n </mat-tab>\r\n <mat-tab label=\"Texture\" *ngIf=\"FabrikantenService.ShowTexture()\">\r\n <ng-template mat-tab-label>\r\n <span>{{ TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.Texture) }}</span>\r\n </ng-template>\r\n <app-fab-texture></app-fab-texture>\r\n </mat-tab>\r\n <mat-tab label=\"Toebehoren\" *ngIf=\"FabrikantenService.ShowToebehoren()\">\r\n <ng-template mat-tab-label>\r\n <span>{{ TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.Toebehoren) }}</span>\r\n </ng-template>\r\n <app-fab-toebehoren></app-fab-toebehoren>\r\n </mat-tab>\r\n </mat-tab-group>\r\n </div>\r\n </ng-container>\r\n </mat-drawer-content>\r\n</mat-drawer-container>\r\n\r\n\r\n", styles: ["app-fab-product .tabs{height:100%}app-fab-product .no-parameters-div{padding:5px}app-fab-product .required-div{padding:40px}app-fab-product .row{display:flex}app-fab-product .loader-card{margin:auto;width:300px}app-fab-product .loader-subtitle{text-align:center;padding-top:20px;padding-bottom:10px}app-fab-product .actionwrapper{width:250px;padding:20px}app-fab-product .loader-spinner{margin:auto}app-fab-product .view-container{height:100%}app-fab-product .view-content{background-color:#fff}app-fab-product .loader{position:fixed;display:flex;width:100%;height:100%;align-items:center;z-index:20;background-color:#ffffffb3;top:0;left:0}app-fab-product .filter-view{height:100%;width:300px;min-width:300px;background-color:#fafafa}app-fab-product .product-view{flex:auto}app-fab-product .mat-drawer-inner-container{overflow-y:scroll}.mat-tab-body-wrapper{height:100%}\n"], dependencies: [{ kind: "directive", type: i4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i6$2.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i6$2.MatCardContent, selector: "mat-card-content" }, { kind: "directive", type: i6$2.MatCardSubtitle, selector: "mat-card-subtitle, [mat-card-subtitle], [matCardSubtitle]" }, { kind: "component", type: i9$2.MatDrawer, selector: "mat-drawer", inputs: ["position", "mode", "disableClose", "autoFocus", "opened"], outputs: ["openedChange", "opened", "openedStart", "closed", "closedStart", "positionChanged"], exportAs: ["matDrawer"] }, { kind: "component", type: i9$2.MatDrawerContainer, selector: "mat-drawer-container", inputs: ["autosize", "hasBackdrop"], outputs: ["backdropClick"], exportAs: ["matDrawerContainer"] }, { kind: "component", type: i9$2.MatDrawerContent, selector: "mat-drawer-content" }, { kind: "directive", type: i10$1.MatTabLabel, selector: "[mat-tab-label], [matTabLabel]" }, { kind: "component", type: i10$1.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i10$1.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "component", type: i6.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "component", type: FabActionmenuComponent, selector: "app-fab-actionmenu", inputs: ["display"] }, { kind: "component", type: FabFiltersInputComponent, selector: "fab-filters-input", inputs: ["displayExtra"] }, { kind: "component", type: FabHeaderComponent, selector: "app-fab-header", inputs: ["showfiltermenubutton"] }, { kind: "component", type: FabProductAutoSpecificationComponent, selector: "app-fab-product-auto-specification" }, { kind: "component", type: FabProductBestekComponent, selector: "app-fab-product-bestek" }, { kind: "component", type: FabProductInfoComponent, selector: "app-fab-product-info" }, { kind: "component", type: FabProductLastenboekComponent, selector: "app-fab-product-lastenboek" }, { kind: "component", type: FabSvgViewerComponent, selector: "app-fab-svg-viewer" }, { kind: "component", type: FabTextureComponent, selector: "app-fab-texture" }, { kind: "component", type: FabToebehorenComponent, selector: "app-fab-toebehoren" }, { kind: "component", type: FabWebglViewerComponent, selector: "app-fab-webgl-viewer" }], encapsulation: i0.ViewEncapsulation.None });
29813
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.13", type: FabProductComponent, isStandalone: false, selector: "app-fab-product", viewQueries: [{ propertyName: "header", first: true, predicate: ["header"], descendants: true }], ngImport: i0, template: "<div *ngIf=\"FabrikantenService.IsLoadingSmall()\" [ngClass]=\"HasParameter() ? GetParameterClass() : ''\" class=\"loader\">\r\n <mat-card class=\"loader-card\">\r\n <mat-card-content>\r\n <mat-spinner class=\"loader-spinner\" [diameter]=\"80\"></mat-spinner>\r\n </mat-card-content>\r\n <mat-card-subtitle class=\"loader-subtitle\" *ngIf=\"!FabrikantenService.IsStartingDownload()\">\r\n {{ TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.ProductsLoading) }}\r\n </mat-card-subtitle>\r\n </mat-card>\r\n</div>\r\n\r\n<mat-drawer-container class=\"view-container\" [ngClass]=\"HasParameter() ? GetParameterClass() : ''\" *ngIf=\"FabrikantenService.Loaded\">\r\n <mat-drawer #drawer [mode]=\"GetNavMode()\" [(opened)]=\"MobileService.NavOpened\" *ngIf=\"FabrikantenService.FabrikantenViewModel != null\">\r\n <div class=\"filter-view\">\r\n <fab-filters-input></fab-filters-input>\r\n </div>\r\n </mat-drawer>\r\n <mat-drawer mode=\"over\" position=\"end\" [(opened)]=\"MobileService.ActionOpened\">\r\n <div class=\"actionwrapper\">\r\n <app-fab-actionmenu [display]=\"FabrikantenService.SelectedTab\"></app-fab-actionmenu>\r\n </div>\r\n </mat-drawer>\r\n <mat-drawer-content class=\"view-content\">\r\n <div #header *ngIf=\"ShowBreadcrumb()\">\r\n <app-fab-header [showfiltermenubutton]=\"true\"></app-fab-header>\r\n\r\n <ng-container *ngIf=\"ShowInformationBlock()\">\r\n <app-fab-product-info></app-fab-product-info>\r\n </ng-container>\r\n </div>\r\n\r\n <ng-container *ngIf=\"FabrikantenService.ShowRequired()\">\r\n <div class=\"required-div\">{{ TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.NotAllRequiredFilled) }}</div>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"FabrikantenService.ShowNoParameters() && !FabrikantenService.IsLoading()\">\r\n <div class=\"no-parameters-div\">\r\n No product request send to BCB due to invalid or missing parameters\r\n </div>\r\n <div class=\"required-div\">\r\n <ng-container *ngIf=\"FabrikantenService.FabrikantenViewModel?.customInfoParameters != undefined\">\r\n <ng-container *ngFor=\"let customparameter of FabrikantenService.FabrikantenViewModel.customInfoParameters\">\r\n <div class=\"display-value-item\">\r\n {{ customparameter.name }}: {{ customparameter.value }}\r\n </div>\r\n </ng-container>\r\n </ng-container>\r\n </div>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"!FabrikantenService.ShowRequired() && !FabrikantenService.ShowNoParameters()\">\r\n <div [style.height]=\"Height\" *ngIf=\"FabrikantenService.FabrikantenViewModel != null\">\r\n <mat-tab-group class=\"view-container\" [selectedIndex]=\"FabrikantenService.SelectedTabIndex\" (selectedTabChange)=\"SelectedTabChange($event)\">\r\n <mat-tab label=\"Informatie\" *ngIf=\"ShowInformation()\">\r\n <ng-template mat-tab-label>\r\n <span>{{ TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.TabInformation) }}</span>\r\n </ng-template>\r\n <app-fab-product-info></app-fab-product-info>\r\n </mat-tab>\r\n <mat-tab label=\"3D\" *ngIf=\"Show3D()\">\r\n <ng-template mat-tab-label>\r\n <span>{{ TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.Tab3D) }}</span>\r\n </ng-template>\r\n <app-fab-webgl-viewer></app-fab-webgl-viewer>\r\n </mat-tab>\r\n <mat-tab label=\"2D\" *ngIf=\"Show2D()\" style=\"height: 100%;\">\r\n <ng-template mat-tab-label>\r\n <span>{{ TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.Tab2D) }}</span>\r\n </ng-template>\r\n <app-fab-svg-viewer></app-fab-svg-viewer>\r\n </mat-tab>\r\n <mat-tab label=\"Bestek\" *ngIf=\"ShowSpecification()\">\r\n <ng-template mat-tab-label>\r\n <span>{{ TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.TabSpecification) }}</span>\r\n </ng-template>\r\n <app-fab-product-bestek *ngIf=\"TranslateService.ShowSpecification()\"></app-fab-product-bestek>\r\n <app-fab-product-auto-specification *ngIf=\"TranslateService.ShowAutoSpecification()\"></app-fab-product-auto-specification>\r\n <app-fab-product-lastenboek *ngIf=\"TranslateService.ShowLastenboek()\"></app-fab-product-lastenboek>\r\n </mat-tab>\r\n <mat-tab label=\"Texture\" *ngIf=\"FabrikantenService.ShowTexture()\">\r\n <ng-template mat-tab-label>\r\n <span>{{ TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.Texture) }}</span>\r\n </ng-template>\r\n <app-fab-texture></app-fab-texture>\r\n </mat-tab>\r\n <mat-tab label=\"Toebehoren\" *ngIf=\"FabrikantenService.ShowToebehoren()\">\r\n <ng-template mat-tab-label>\r\n <span>{{ TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.Toebehoren) }}</span>\r\n </ng-template>\r\n <app-fab-toebehoren></app-fab-toebehoren>\r\n </mat-tab>\r\n </mat-tab-group>\r\n </div>\r\n </ng-container>\r\n </mat-drawer-content>\r\n</mat-drawer-container>\r\n\r\n\r\n", styles: ["app-fab-product .tabs{height:100%}app-fab-product .no-parameters-div{padding:5px}app-fab-product .required-div{padding:40px}app-fab-product .row{display:flex}app-fab-product .loader-card{margin:auto;width:300px}app-fab-product .loader-subtitle{text-align:center;padding-top:20px;padding-bottom:10px}app-fab-product .actionwrapper{width:250px;padding:20px}app-fab-product .loader-spinner{margin:auto}app-fab-product .view-container{height:100%}app-fab-product .view-content{background-color:#fff}app-fab-product .loader{position:fixed;display:flex;width:100%;height:100%;align-items:center;z-index:20;background-color:#ffffffb3;top:0;left:0}app-fab-product .filter-view{height:100%;width:300px;min-width:300px;background-color:#fafafa}app-fab-product .product-view{flex:auto}app-fab-product .mat-drawer-inner-container{overflow-y:scroll}.mat-tab-body-wrapper{height:100%}\n"], dependencies: [{ kind: "directive", type: i4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i6$2.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i6$2.MatCardContent, selector: "mat-card-content" }, { kind: "directive", type: i6$2.MatCardSubtitle, selector: "mat-card-subtitle, [mat-card-subtitle], [matCardSubtitle]" }, { kind: "component", type: i9$3.MatDrawer, selector: "mat-drawer", inputs: ["position", "mode", "disableClose", "autoFocus", "opened"], outputs: ["openedChange", "opened", "openedStart", "closed", "closedStart", "positionChanged"], exportAs: ["matDrawer"] }, { kind: "component", type: i9$3.MatDrawerContainer, selector: "mat-drawer-container", inputs: ["autosize", "hasBackdrop"], outputs: ["backdropClick"], exportAs: ["matDrawerContainer"] }, { kind: "component", type: i9$3.MatDrawerContent, selector: "mat-drawer-content" }, { kind: "directive", type: i10$1.MatTabLabel, selector: "[mat-tab-label], [matTabLabel]" }, { kind: "component", type: i10$1.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i10$1.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "component", type: i6.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "component", type: FabActionmenuComponent, selector: "app-fab-actionmenu", inputs: ["display"] }, { kind: "component", type: FabFiltersInputComponent, selector: "fab-filters-input", inputs: ["displayExtra"] }, { kind: "component", type: FabHeaderComponent, selector: "app-fab-header", inputs: ["showfiltermenubutton"] }, { kind: "component", type: FabProductAutoSpecificationComponent, selector: "app-fab-product-auto-specification" }, { kind: "component", type: FabProductBestekComponent, selector: "app-fab-product-bestek" }, { kind: "component", type: FabProductInfoComponent, selector: "app-fab-product-info" }, { kind: "component", type: FabProductLastenboekComponent, selector: "app-fab-product-lastenboek" }, { kind: "component", type: FabSvgViewerComponent, selector: "app-fab-svg-viewer" }, { kind: "component", type: FabTextureComponent, selector: "app-fab-texture" }, { kind: "component", type: FabToebehorenComponent, selector: "app-fab-toebehoren" }, { kind: "component", type: FabWebglViewerComponent, selector: "app-fab-webgl-viewer" }], encapsulation: i0.ViewEncapsulation.None });
30653
29814
  }
30654
29815
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: FabProductComponent, decorators: [{
30655
29816
  type: Component,
@@ -30842,7 +30003,7 @@ class FabProductSelectComponent {
30842
30003
  return products;
30843
30004
  }
30844
30005
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: FabProductSelectComponent, deps: [{ token: MobileService }, { token: FabrikantenService }, { token: BestekService }, { token: TranslateService }, { token: i3.ActivatedRoute }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
30845
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.13", type: FabProductSelectComponent, isStandalone: false, selector: "app-fab-product-select", viewQueries: [{ propertyName: "header", first: true, predicate: ["header"], descendants: true }, { propertyName: "info", first: true, predicate: ["info"], descendants: true }], ngImport: i0, template: "<div *ngIf=\"FabrikantenService.IsLoadingSmall()\" class=\"loader\">\r\n <mat-card class=\"loader-card\">\r\n <mat-card-content>\r\n <mat-spinner class=\"loader-spinner\" [diameter]=\"80\"></mat-spinner>\r\n </mat-card-content>\r\n <mat-card-subtitle class=\"loader-subtitle\">\r\n {{ TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.ProductsLoading) }}\r\n </mat-card-subtitle>\r\n </mat-card>\r\n</div>\r\n\r\n<mat-drawer-container class=\"view-container\" *ngIf=\"FabrikantenService.FabrikantenViewModel != null\">\r\n <mat-drawer #drawer [mode]=\"MobileService.NavMode\" [(opened)]=\"MobileService.NavOpened\">\r\n <div class=\"filter-view\">\r\n <fab-filters-input></fab-filters-input>\r\n </div>\r\n </mat-drawer>\r\n <mat-drawer-content class=\"view-content\">\r\n <div #header>\r\n <app-fab-header [showfiltermenubutton]=\"true\"></app-fab-header>\r\n </div>\r\n\r\n <div #info class=\"header\">\r\n <div class=\"title\">\r\n <h1>{{ TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.ProductSelection) }}</h1>\r\n </div>\r\n <div class=\"subtitle\" *ngIf=\"!FabrikantenService.FabrikantenViewModel.productSelectBlockedByFilters\">\r\n {{ TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.ProductSelectionInfo) }}\r\n </div>\r\n <div class=\"subtitle\" *ngIf=\"FabrikantenService.FabrikantenViewModel.productSelectBlockedByFilters\">\r\n {{ TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.ProductSelectionBlocked) }}\r\n </div>\r\n </div>\r\n\r\n <div [style.height]=\"Height\" *ngIf=\"!FabrikantenService.FabrikantenViewModel.productSelectBlockedByFilters\">\r\n <ng-container *ngIf=\"IsGrouped()\">\r\n <ng-container *ngFor=\"let group of GetGroups()\">\r\n <div class=\"group-header\">\r\n {{ group }}\r\n </div>\r\n <div class=\"main-window group-collection\">\r\n <app-fab-product-tile *ngFor=\"let product of GetProducts(group)\" [product]=\"product\"></app-fab-product-tile>\r\n </div>\r\n </ng-container>\r\n </ng-container>\r\n <ng-container *ngIf=\"!IsGrouped()\">\r\n <div class=\"main-window\">\r\n <app-fab-product-tile *ngFor=\"let product of FabrikantenService.FabrikantenViewModel.products\" [product]=\"product\"></app-fab-product-tile>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </mat-drawer-content>\r\n</mat-drawer-container>\r\n\r\n\r\n", styles: ["app-fab-product-select .main-window{display:flex;flex-flow:row wrap;overflow:auto}app-fab-product-select .group-header{border-bottom:1px solid #000;margin:10px;font-size:16px}app-fab-product-select .group-collection{margin:10px}app-fab-product-select .subtitle{margin-bottom:10px}app-fab-product-select .subtitle:first-letter{text-transform:uppercase}app-fab-product-select .title:first-letter{text-transform:uppercase}app-fab-product-select .header{padding:4px}app-fab-product-select .row{display:flex}app-fab-product-select .loader-card{margin:auto;width:300px}app-fab-product-select .loader-subtitle{text-align:center;padding-top:20px;padding-bottom:10px}app-fab-product-select .loader-spinner{margin:auto}app-fab-product-select .view-container{height:100%}app-fab-product-select .view-content{background-color:#fff}app-fab-product-select .loader{position:fixed;width:100%;height:100%;display:flex;align-items:center;z-index:20;background-color:#ffffffb3;top:0;left:0}app-fab-product-select .filter-view{width:300px;min-width:300px;background-color:#fafafa;height:100%}app-fab-product-select .product-view{flex:auto}\n"], dependencies: [{ kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i6$2.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i6$2.MatCardContent, selector: "mat-card-content" }, { kind: "directive", type: i6$2.MatCardSubtitle, selector: "mat-card-subtitle, [mat-card-subtitle], [matCardSubtitle]" }, { kind: "component", type: i9$2.MatDrawer, selector: "mat-drawer", inputs: ["position", "mode", "disableClose", "autoFocus", "opened"], outputs: ["openedChange", "opened", "openedStart", "closed", "closedStart", "positionChanged"], exportAs: ["matDrawer"] }, { kind: "component", type: i9$2.MatDrawerContainer, selector: "mat-drawer-container", inputs: ["autosize", "hasBackdrop"], outputs: ["backdropClick"], exportAs: ["matDrawerContainer"] }, { kind: "component", type: i9$2.MatDrawerContent, selector: "mat-drawer-content" }, { kind: "component", type: i6.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "component", type: FabFiltersInputComponent, selector: "fab-filters-input", inputs: ["displayExtra"] }, { kind: "component", type: FabHeaderComponent, selector: "app-fab-header", inputs: ["showfiltermenubutton"] }, { kind: "component", type: FabProductTileComponent, selector: "app-fab-product-tile", inputs: ["product"] }], encapsulation: i0.ViewEncapsulation.None });
30006
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.13", type: FabProductSelectComponent, isStandalone: false, selector: "app-fab-product-select", viewQueries: [{ propertyName: "header", first: true, predicate: ["header"], descendants: true }, { propertyName: "info", first: true, predicate: ["info"], descendants: true }], ngImport: i0, template: "<div *ngIf=\"FabrikantenService.IsLoadingSmall()\" class=\"loader\">\r\n <mat-card class=\"loader-card\">\r\n <mat-card-content>\r\n <mat-spinner class=\"loader-spinner\" [diameter]=\"80\"></mat-spinner>\r\n </mat-card-content>\r\n <mat-card-subtitle class=\"loader-subtitle\">\r\n {{ TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.ProductsLoading) }}\r\n </mat-card-subtitle>\r\n </mat-card>\r\n</div>\r\n\r\n<mat-drawer-container class=\"view-container\" *ngIf=\"FabrikantenService.FabrikantenViewModel != null\">\r\n <mat-drawer #drawer [mode]=\"MobileService.NavMode\" [(opened)]=\"MobileService.NavOpened\">\r\n <div class=\"filter-view\">\r\n <fab-filters-input></fab-filters-input>\r\n </div>\r\n </mat-drawer>\r\n <mat-drawer-content class=\"view-content\">\r\n <div #header>\r\n <app-fab-header [showfiltermenubutton]=\"true\"></app-fab-header>\r\n </div>\r\n\r\n <div #info class=\"header\">\r\n <div class=\"title\">\r\n <h1>{{ TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.ProductSelection) }}</h1>\r\n </div>\r\n <div class=\"subtitle\" *ngIf=\"!FabrikantenService.FabrikantenViewModel.productSelectBlockedByFilters\">\r\n {{ TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.ProductSelectionInfo) }}\r\n </div>\r\n <div class=\"subtitle\" *ngIf=\"FabrikantenService.FabrikantenViewModel.productSelectBlockedByFilters\">\r\n {{ TranslateService.GetActiveValue(TranslationCategory.Common, TranslationSubCategory.ProductSelectionBlocked) }}\r\n </div>\r\n </div>\r\n\r\n <div [style.height]=\"Height\" *ngIf=\"!FabrikantenService.FabrikantenViewModel.productSelectBlockedByFilters\">\r\n <ng-container *ngIf=\"IsGrouped()\">\r\n <ng-container *ngFor=\"let group of GetGroups()\">\r\n <div class=\"group-header\">\r\n {{ group }}\r\n </div>\r\n <div class=\"main-window group-collection\">\r\n <app-fab-product-tile *ngFor=\"let product of GetProducts(group)\" [product]=\"product\"></app-fab-product-tile>\r\n </div>\r\n </ng-container>\r\n </ng-container>\r\n <ng-container *ngIf=\"!IsGrouped()\">\r\n <div class=\"main-window\">\r\n <app-fab-product-tile *ngFor=\"let product of FabrikantenService.FabrikantenViewModel.products\" [product]=\"product\"></app-fab-product-tile>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </mat-drawer-content>\r\n</mat-drawer-container>\r\n\r\n\r\n", styles: ["app-fab-product-select .main-window{display:flex;flex-flow:row wrap;overflow:auto}app-fab-product-select .group-header{border-bottom:1px solid #000;margin:10px;font-size:16px}app-fab-product-select .group-collection{margin:10px}app-fab-product-select .subtitle{margin-bottom:10px}app-fab-product-select .subtitle:first-letter{text-transform:uppercase}app-fab-product-select .title:first-letter{text-transform:uppercase}app-fab-product-select .header{padding:4px}app-fab-product-select .row{display:flex}app-fab-product-select .loader-card{margin:auto;width:300px}app-fab-product-select .loader-subtitle{text-align:center;padding-top:20px;padding-bottom:10px}app-fab-product-select .loader-spinner{margin:auto}app-fab-product-select .view-container{height:100%}app-fab-product-select .view-content{background-color:#fff}app-fab-product-select .loader{position:fixed;width:100%;height:100%;display:flex;align-items:center;z-index:20;background-color:#ffffffb3;top:0;left:0}app-fab-product-select .filter-view{width:300px;min-width:300px;background-color:#fafafa;height:100%}app-fab-product-select .product-view{flex:auto}\n"], dependencies: [{ kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i6$2.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i6$2.MatCardContent, selector: "mat-card-content" }, { kind: "directive", type: i6$2.MatCardSubtitle, selector: "mat-card-subtitle, [mat-card-subtitle], [matCardSubtitle]" }, { kind: "component", type: i9$3.MatDrawer, selector: "mat-drawer", inputs: ["position", "mode", "disableClose", "autoFocus", "opened"], outputs: ["openedChange", "opened", "openedStart", "closed", "closedStart", "positionChanged"], exportAs: ["matDrawer"] }, { kind: "component", type: i9$3.MatDrawerContainer, selector: "mat-drawer-container", inputs: ["autosize", "hasBackdrop"], outputs: ["backdropClick"], exportAs: ["matDrawerContainer"] }, { kind: "component", type: i9$3.MatDrawerContent, selector: "mat-drawer-content" }, { kind: "component", type: i6.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "component", type: FabFiltersInputComponent, selector: "fab-filters-input", inputs: ["displayExtra"] }, { kind: "component", type: FabHeaderComponent, selector: "app-fab-header", inputs: ["showfiltermenubutton"] }, { kind: "component", type: FabProductTileComponent, selector: "app-fab-product-tile", inputs: ["product"] }], encapsulation: i0.ViewEncapsulation.None });
30846
30007
  }
30847
30008
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: FabProductSelectComponent, decorators: [{
30848
30009
  type: Component,
@@ -33430,8 +32591,7 @@ class FabrikantenCoreModule {
33430
32591
  MatFormFieldModule,
33431
32592
  MatSnackBarModule,
33432
32593
  ReactiveFormsModule,
33433
- SafehtmlPipe,
33434
- ThreejsEngineComponent, i3.RouterModule], exports: [FabActionmenuComponent,
32594
+ SafehtmlPipe, i3.RouterModule], exports: [FabActionmenuComponent,
33435
32595
  FabCategoryNavigatorComponent,
33436
32596
  FabFilterColourDialogComponent,
33437
32597
  FabFilterComponent,
@@ -33512,7 +32672,6 @@ class FabrikantenCoreModule {
33512
32672
  MatFormFieldModule,
33513
32673
  MatSnackBarModule,
33514
32674
  ReactiveFormsModule,
33515
- ThreejsEngineComponent,
33516
32675
  RouterModule.forRoot(routes, {
33517
32676
  scrollPositionRestoration: 'enabled',
33518
32677
  anchorScrolling: 'enabled',
@@ -33554,7 +32713,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImpo
33554
32713
  MatSnackBarModule,
33555
32714
  ReactiveFormsModule,
33556
32715
  SafehtmlPipe,
33557
- ThreejsEngineComponent,
33558
32716
  RouterModule.forRoot(routes, {
33559
32717
  scrollPositionRestoration: 'enabled',
33560
32718
  anchorScrolling: 'enabled',